UNPKG

better-auth

Version:

The most comprehensive authentication framework for TypeScript.

1 lines • 9.02 kB
{"version":3,"file":"wildcard.mjs","names":[],"sources":["../../src/utils/wildcard.ts"],"sourcesContent":["//https://github.com/axtgr/wildcard-match\n\n/**\n * Escapes a character if it has a special meaning in regular expressions\n * and returns the character as is if it doesn't\n */\nfunction escapeRegExpChar(char: string) {\n\tif (\n\t\tchar === \"-\" ||\n\t\tchar === \"^\" ||\n\t\tchar === \"$\" ||\n\t\tchar === \"+\" ||\n\t\tchar === \".\" ||\n\t\tchar === \"(\" ||\n\t\tchar === \")\" ||\n\t\tchar === \"|\" ||\n\t\tchar === \"[\" ||\n\t\tchar === \"]\" ||\n\t\tchar === \"{\" ||\n\t\tchar === \"}\" ||\n\t\tchar === \"*\" ||\n\t\tchar === \"?\" ||\n\t\tchar === \"\\\\\"\n\t) {\n\t\treturn `\\\\${char}`;\n\t} else {\n\t\treturn char;\n\t}\n}\n\n/**\n * Escapes all characters in a given string that have a special meaning in regular expressions\n */\nfunction escapeRegExpString(str: string) {\n\tlet result = \"\";\n\tfor (let i = 0; i < str.length; i++) {\n\t\tresult += escapeRegExpChar(str[i]!);\n\t}\n\treturn result;\n}\n\n/**\n * Transforms one or more glob patterns into a RegExp pattern\n */\nfunction transform(\n\tpattern: string | string[],\n\tseparator: string | boolean = true,\n): string {\n\tif (Array.isArray(pattern)) {\n\t\tlet regExpPatterns = pattern.map((p) => `^${transform(p, separator)}$`);\n\t\treturn `(?:${regExpPatterns.join(\"|\")})`;\n\t}\n\n\tlet separatorSplitter = \"\";\n\tlet separatorMatcher = \"\";\n\tlet wildcard = \".\";\n\n\tif (separator === true) {\n\t\t// In this case forward slashes in patterns match both forward and backslashes in samples:\n\t\t//\n\t\t// `foo/bar` will match `foo/bar`\n\t\t// will match `foo\\bar`\n\t\t//\n\t\tseparatorSplitter = \"/\";\n\t\tseparatorMatcher = \"[/\\\\\\\\]\";\n\t\twildcard = \"[^/\\\\\\\\]\";\n\t} else if (separator) {\n\t\tseparatorSplitter = separator;\n\t\tseparatorMatcher = escapeRegExpString(separatorSplitter);\n\n\t\tif (separatorMatcher.length > 1) {\n\t\t\tseparatorMatcher = `(?:${separatorMatcher})`;\n\t\t\twildcard = `((?!${separatorMatcher}).)`;\n\t\t} else {\n\t\t\twildcard = `[^${separatorMatcher}]`;\n\t\t}\n\t}\n\n\t// When a separator is explicitly specified in a pattern,\n\t// it MUST match ONE OR MORE separators in a sample:\n\t//\n\t// `foo/bar/` will match `foo//bar///`\n\t// won't match `foo/bar`\n\t//\n\t// When a pattern doesn't have a trailing separator,\n\t// a sample can still optionally have them:\n\t//\n\t// `foo/bar` will match `foo/bar//`\n\t//\n\t// So we use different quantifiers depending on the index of a segment.\n\tlet requiredSeparator = separator ? `${separatorMatcher}+?` : \"\";\n\tlet optionalSeparator = separator ? `${separatorMatcher}*?` : \"\";\n\n\tlet segments = separator ? pattern.split(separatorSplitter) : [pattern];\n\tlet result = \"\";\n\n\tfor (let s = 0; s < segments.length; s++) {\n\t\tlet segment = segments[s]!;\n\t\tlet nextSegment = segments[s + 1]!;\n\t\tlet currentSeparator = \"\";\n\n\t\tif (!segment && s > 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (separator) {\n\t\t\tif (s === segments.length - 1) {\n\t\t\t\tcurrentSeparator = optionalSeparator;\n\t\t\t} else if (nextSegment !== \"**\") {\n\t\t\t\tcurrentSeparator = requiredSeparator;\n\t\t\t} else {\n\t\t\t\tcurrentSeparator = \"\";\n\t\t\t}\n\t\t}\n\n\t\tif (separator && segment === \"**\") {\n\t\t\tif (currentSeparator) {\n\t\t\t\tresult += s === 0 ? \"\" : currentSeparator;\n\t\t\t\tresult += `(?:${wildcard}*?${currentSeparator})*?`;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (let c = 0; c < segment.length; c++) {\n\t\t\tlet char = segment[c]!;\n\n\t\t\tif (char === \"\\\\\") {\n\t\t\t\tif (c < segment.length - 1) {\n\t\t\t\t\tresult += escapeRegExpChar(segment[c + 1]!);\n\t\t\t\t\tc++;\n\t\t\t\t}\n\t\t\t} else if (char === \"?\") {\n\t\t\t\tresult += wildcard;\n\t\t\t} else if (char === \"*\") {\n\t\t\t\tresult += `${wildcard}*?`;\n\t\t\t} else {\n\t\t\t\tresult += escapeRegExpChar(char);\n\t\t\t}\n\t\t}\n\n\t\tresult += currentSeparator;\n\t}\n\n\treturn result;\n}\n\ninterface WildcardMatchOptions {\n\t/** Separator to be used to split patterns and samples into segments */\n\tseparator?: string | boolean;\n\n\t/** Flags to pass to the RegExp */\n\tflags?: string;\n}\n\n// This overrides the function's signature because for the end user\n// the function is always bound to a RegExp\ninterface isMatch {\n\t/**\n\t * Tests if a sample string matches the pattern(s)\n\t *\n\t * ```js\n\t * isMatch('foo') //=> true\n\t * ```\n\t */\n\t(sample: string): boolean;\n\n\t/** Compiled regular expression */\n\tregexp: RegExp;\n\n\t/** Original pattern or array of patterns that was used to compile the RegExp */\n\tpattern: string | string[];\n\n\t/** Options that were used to compile the RegExp */\n\toptions: WildcardMatchOptions;\n}\n\nfunction isMatch(regexp: RegExp, sample: string) {\n\tif (typeof sample !== \"string\") {\n\t\tthrow new TypeError(`Sample must be a string, but ${typeof sample} given`);\n\t}\n\n\treturn regexp.test(sample);\n}\n\n/**\n * Compiles one or more glob patterns into a RegExp and returns an isMatch function.\n * The isMatch function takes a sample string as its only argument and returns `true`\n * if the string matches the pattern(s).\n *\n * ```js\n * wildcardMatch('src/*.js')('src/index.js') //=> true\n * ```\n *\n * ```js\n * const isMatch = wildcardMatch('*.example.com', '.')\n * isMatch('foo.example.com') //=> true\n * isMatch('foo.bar.com') //=> false\n * ```\n */\nfunction wildcardMatch(\n\tpattern: string | string[],\n\toptions?: string | boolean | WildcardMatchOptions,\n) {\n\tif (typeof pattern !== \"string\" && !Array.isArray(pattern)) {\n\t\tthrow new TypeError(\n\t\t\t`The first argument must be a single pattern string or an array of patterns, but ${typeof pattern} given`,\n\t\t);\n\t}\n\n\tif (typeof options === \"string\" || typeof options === \"boolean\") {\n\t\toptions = { separator: options };\n\t}\n\n\tif (\n\t\targuments.length === 2 &&\n\t\t!(\n\t\t\ttypeof options === \"undefined\" ||\n\t\t\t(typeof options === \"object\" &&\n\t\t\t\toptions !== null &&\n\t\t\t\t!Array.isArray(options))\n\t\t)\n\t) {\n\t\tthrow new TypeError(\n\t\t\t`The second argument must be an options object or a string/boolean separator, but ${typeof options} given`,\n\t\t);\n\t}\n\n\toptions = options || {};\n\n\tif (options.separator === \"\\\\\") {\n\t\tthrow new Error(\n\t\t\t\"\\\\ is not a valid separator because it is used for escaping. Try setting the separator to `true` instead\",\n\t\t);\n\t}\n\n\tlet regexpPattern = transform(pattern, options.separator);\n\tlet regexp = new RegExp(`^${regexpPattern}$`, options.flags);\n\n\tlet fn = isMatch.bind(null, regexp) as isMatch;\n\tfn.options = options;\n\tfn.pattern = pattern;\n\tfn.regexp = regexp;\n\treturn fn;\n}\n\nexport { wildcardMatch };\n"],"mappings":";;;;;AAMA,SAAS,iBAAiB,MAAc;AACvC,KACC,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,OACT,SAAS,KAET,QAAO,KAAK;KAEZ,QAAO;;;;;AAOT,SAAS,mBAAmB,KAAa;CACxC,IAAI,SAAS;AACb,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,IAC/B,WAAU,iBAAiB,IAAI,GAAI;AAEpC,QAAO;;;;;AAMR,SAAS,UACR,SACA,YAA8B,MACrB;AACT,KAAI,MAAM,QAAQ,QAAQ,CAEzB,QAAO,MADc,QAAQ,KAAK,MAAM,IAAI,UAAU,GAAG,UAAU,CAAC,GAAG,CAC3C,KAAK,IAAI,CAAC;CAGvC,IAAI,oBAAoB;CACxB,IAAI,mBAAmB;CACvB,IAAI,WAAW;AAEf,KAAI,cAAc,MAAM;AAMvB,sBAAoB;AACpB,qBAAmB;AACnB,aAAW;YACD,WAAW;AACrB,sBAAoB;AACpB,qBAAmB,mBAAmB,kBAAkB;AAExD,MAAI,iBAAiB,SAAS,GAAG;AAChC,sBAAmB,MAAM,iBAAiB;AAC1C,cAAW,OAAO,iBAAiB;QAEnC,YAAW,KAAK,iBAAiB;;CAgBnC,IAAI,oBAAoB,YAAY,GAAG,iBAAiB,MAAM;CAC9D,IAAI,oBAAoB,YAAY,GAAG,iBAAiB,MAAM;CAE9D,IAAI,WAAW,YAAY,QAAQ,MAAM,kBAAkB,GAAG,CAAC,QAAQ;CACvE,IAAI,SAAS;AAEb,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACzC,IAAI,UAAU,SAAS;EACvB,IAAI,cAAc,SAAS,IAAI;EAC/B,IAAI,mBAAmB;AAEvB,MAAI,CAAC,WAAW,IAAI,EACnB;AAGD,MAAI,UACH,KAAI,MAAM,SAAS,SAAS,EAC3B,oBAAmB;WACT,gBAAgB,KAC1B,oBAAmB;MAEnB,oBAAmB;AAIrB,MAAI,aAAa,YAAY,MAAM;AAClC,OAAI,kBAAkB;AACrB,cAAU,MAAM,IAAI,KAAK;AACzB,cAAU,MAAM,SAAS,IAAI,iBAAiB;;AAE/C;;AAGD,OAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;GACxC,IAAI,OAAO,QAAQ;AAEnB,OAAI,SAAS,MACZ;QAAI,IAAI,QAAQ,SAAS,GAAG;AAC3B,eAAU,iBAAiB,QAAQ,IAAI,GAAI;AAC3C;;cAES,SAAS,IACnB,WAAU;YACA,SAAS,IACnB,WAAU,GAAG,SAAS;OAEtB,WAAU,iBAAiB,KAAK;;AAIlC,YAAU;;AAGX,QAAO;;AAiCR,SAAS,QAAQ,QAAgB,QAAgB;AAChD,KAAI,OAAO,WAAW,SACrB,OAAM,IAAI,UAAU,gCAAgC,OAAO,OAAO,QAAQ;AAG3E,QAAO,OAAO,KAAK,OAAO;;;;;;;;;;;;;;;;;AAkB3B,SAAS,cACR,SACA,SACC;AACD,KAAI,OAAO,YAAY,YAAY,CAAC,MAAM,QAAQ,QAAQ,CACzD,OAAM,IAAI,UACT,mFAAmF,OAAO,QAAQ,QAClG;AAGF,KAAI,OAAO,YAAY,YAAY,OAAO,YAAY,UACrD,WAAU,EAAE,WAAW,SAAS;AAGjC,KACC,UAAU,WAAW,KACrB,EACC,OAAO,YAAY,eAClB,OAAO,YAAY,YACnB,YAAY,QACZ,CAAC,MAAM,QAAQ,QAAQ,EAGzB,OAAM,IAAI,UACT,oFAAoF,OAAO,QAAQ,QACnG;AAGF,WAAU,WAAW,EAAE;AAEvB,KAAI,QAAQ,cAAc,KACzB,OAAM,IAAI,MACT,2GACA;CAGF,IAAI,gBAAgB,UAAU,SAAS,QAAQ,UAAU;CACzD,IAAI,SAAS,IAAI,OAAO,IAAI,cAAc,IAAI,QAAQ,MAAM;CAE5D,IAAI,KAAK,QAAQ,KAAK,MAAM,OAAO;AACnC,IAAG,UAAU;AACb,IAAG,UAAU;AACb,IAAG,SAAS;AACZ,QAAO"}