(http://gianlucaguarini.com)",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/gianlucaguarini/erre/issues"
+ },
+ "homepage": "https://github.com/gianlucaguarini/erre#readme",
+ "devDependencies": {
+ "@gianlucaguarini/eslint-config": "^2.0.0",
+ "benchmark": "^2.1.4",
+ "eslint": "^8.49.0",
+ "mocha": "^10.2.0",
+ "rollup": "^3.29.2",
+ "rollup-plugin-node-resolve": "^5.2.0"
+ },
+ "dependencies": {
+ "ruit": "^1.0.4"
+ }
+}
diff --git a/node_modules/path-to-regexp/LICENSE b/node_modules/path-to-regexp/LICENSE
new file mode 100644
index 0000000..983fbe8
--- /dev/null
+++ b/node_modules/path-to-regexp/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/path-to-regexp/Readme.md b/node_modules/path-to-regexp/Readme.md
new file mode 100644
index 0000000..f20eb28
--- /dev/null
+++ b/node_modules/path-to-regexp/Readme.md
@@ -0,0 +1,350 @@
+# Path-to-RegExp
+
+> Turn a path string such as `/user/:name` into a regular expression.
+
+[![NPM version][npm-image]][npm-url]
+[![NPM downloads][downloads-image]][downloads-url]
+[![Build status][build-image]][build-url]
+[![Build coverage][coverage-image]][coverage-url]
+[![License][license-image]][license-url]
+
+## Installation
+
+```
+npm install path-to-regexp --save
+```
+
+## Usage
+
+```javascript
+const { pathToRegexp, match, parse, compile } = require("path-to-regexp");
+
+// pathToRegexp(path, keys?, options?)
+// match(path)
+// parse(path)
+// compile(path)
+```
+
+### Path to regexp
+
+The `pathToRegexp` function will return a regular expression object based on the provided `path` argument. It accepts the following arguments:
+
+- **path** A string, array of strings, or a regular expression.
+- **keys** _(optional)_ An array to populate with keys found in the path.
+- **options** _(optional)_
+ - **sensitive** When `true` the regexp will be case sensitive. (default: `false`)
+ - **strict** When `true` the regexp won't allow an optional trailing delimiter to match. (default: `false`)
+ - **end** When `true` the regexp will match to the end of the string. (default: `true`)
+ - **start** When `true` the regexp will match from the beginning of the string. (default: `true`)
+ - **delimiter** The default delimiter for segments, e.g. `[^/#?]` for `:named` patterns. (default: `'/#?'`)
+ - **endsWith** Optional character, or list of characters, to treat as "end" characters.
+ - **encode** A function to encode strings before inserting into `RegExp`. (default: `x => x`)
+ - **prefixes** List of characters to automatically consider prefixes when parsing. (default: `./`)
+
+```javascript
+const keys = [];
+const regexp = pathToRegexp("/foo/:bar", keys);
+// regexp = /^\/foo(?:\/([^\/#\?]+?))[\/#\?]?$/i
+// keys = [{ name: 'bar', prefix: '/', suffix: '', pattern: '[^\\/#\\?]+?', modifier: '' }]
+```
+
+**Please note:** The `RegExp` returned by `path-to-regexp` is intended for ordered data (e.g. pathnames, hostnames). It can not handle arbitrarily ordered data (e.g. query strings, URL fragments, JSON, etc). When using paths that contain query strings, you need to escape the question mark (`?`) to ensure it does not flag the parameter as [optional](#optional).
+
+### Parameters
+
+The path argument is used to define parameters and populate keys.
+
+#### Named Parameters
+
+Named parameters are defined by prefixing a colon to the parameter name (`:foo`).
+
+```js
+const regexp = pathToRegexp("/:foo/:bar");
+// keys = [{ name: 'foo', prefix: '/', ... }, { name: 'bar', prefix: '/', ... }]
+
+regexp.exec("/test/route");
+//=> [ '/test/route', 'test', 'route', index: 0, input: '/test/route', groups: undefined ]
+```
+
+**Please note:** Parameter names must use "word characters" (`[A-Za-z0-9_]`).
+
+##### Custom Matching Parameters
+
+Parameters can have a custom regexp, which overrides the default match (`[^/]+`). For example, you can match digits or names in a path:
+
+```js
+const regexpNumbers = pathToRegexp("/icon-:foo(\\d+).png");
+// keys = [{ name: 'foo', ... }]
+
+regexpNumbers.exec("/icon-123.png");
+//=> ['/icon-123.png', '123']
+
+regexpNumbers.exec("/icon-abc.png");
+//=> null
+
+const regexpWord = pathToRegexp("/(user|u)");
+// keys = [{ name: 0, ... }]
+
+regexpWord.exec("/u");
+//=> ['/u', 'u']
+
+regexpWord.exec("/users");
+//=> null
+```
+
+**Tip:** Backslashes need to be escaped with another backslash in JavaScript strings.
+
+##### Custom Prefix and Suffix
+
+Parameters can be wrapped in `{}` to create custom prefixes or suffixes for your segment:
+
+```js
+const regexp = pathToRegexp("/:attr1?{-:attr2}?{-:attr3}?");
+
+regexp.exec("/test");
+// => ['/test', 'test', undefined, undefined]
+
+regexp.exec("/test-test");
+// => ['/test', 'test', 'test', undefined]
+```
+
+#### Unnamed Parameters
+
+It is possible to write an unnamed parameter that only consists of a regexp. It works the same the named parameter, except it will be numerically indexed:
+
+```js
+const regexp = pathToRegexp("/:foo/(.*)");
+// keys = [{ name: 'foo', ... }, { name: 0, ... }]
+
+regexp.exec("/test/route");
+//=> [ '/test/route', 'test', 'route', index: 0, input: '/test/route', groups: undefined ]
+```
+
+#### Modifiers
+
+Modifiers must be placed after the parameter (e.g. `/:foo?`, `/(test)?`, `/:foo(test)?`, or `{-:foo(test)}?`).
+
+##### Optional
+
+Parameters can be suffixed with a question mark (`?`) to make the parameter optional.
+
+```js
+const regexp = pathToRegexp("/:foo/:bar?");
+// keys = [{ name: 'foo', ... }, { name: 'bar', prefix: '/', modifier: '?' }]
+
+regexp.exec("/test");
+//=> [ '/test', 'test', undefined, index: 0, input: '/test', groups: undefined ]
+
+regexp.exec("/test/route");
+//=> [ '/test/route', 'test', 'route', index: 0, input: '/test/route', groups: undefined ]
+```
+
+**Tip:** The prefix is also optional, escape the prefix `\/` to make it required.
+
+When dealing with query strings, escape the question mark (`?`) so it doesn't mark the parameter as optional. Handling unordered data is outside the scope of this library.
+
+```js
+const regexp = pathToRegexp("/search/:tableName\\?useIndex=true&term=amazing");
+
+regexp.exec("/search/people?useIndex=true&term=amazing");
+//=> [ '/search/people?useIndex=true&term=amazing', 'people', index: 0, input: '/search/people?useIndex=true&term=amazing', groups: undefined ]
+
+// This library does not handle query strings in different orders
+regexp.exec("/search/people?term=amazing&useIndex=true");
+//=> null
+```
+
+##### Zero or more
+
+Parameters can be suffixed with an asterisk (`*`) to denote a zero or more parameter matches.
+
+```js
+const regexp = pathToRegexp("/:foo*");
+// keys = [{ name: 'foo', prefix: '/', modifier: '*' }]
+
+regexp.exec("/");
+//=> [ '/', undefined, index: 0, input: '/', groups: undefined ]
+
+regexp.exec("/bar/baz");
+//=> [ '/bar/baz', 'bar/baz', index: 0, input: '/bar/baz', groups: undefined ]
+```
+
+##### One or more
+
+Parameters can be suffixed with a plus sign (`+`) to denote a one or more parameter matches.
+
+```js
+const regexp = pathToRegexp("/:foo+");
+// keys = [{ name: 'foo', prefix: '/', modifier: '+' }]
+
+regexp.exec("/");
+//=> null
+
+regexp.exec("/bar/baz");
+//=> [ '/bar/baz','bar/baz', index: 0, input: '/bar/baz', groups: undefined ]
+```
+
+### Match
+
+The `match` function will return a function for transforming paths into parameters:
+
+```js
+// Make sure you consistently `decode` segments.
+const fn = match("/user/:id", { decode: decodeURIComponent });
+
+fn("/user/123"); //=> { path: '/user/123', index: 0, params: { id: '123' } }
+fn("/invalid"); //=> false
+fn("/user/caf%C3%A9"); //=> { path: '/user/caf%C3%A9', index: 0, params: { id: 'café' } }
+```
+
+The `match` function can be used to custom match named parameters. For example, this can be used to whitelist a small number of valid paths:
+
+```js
+const urlMatch = match("/users/:id/:tab(home|photos|bio)", {
+ decode: decodeURIComponent,
+});
+
+urlMatch("/users/1234/photos");
+//=> { path: '/users/1234/photos', index: 0, params: { id: '1234', tab: 'photos' } }
+
+urlMatch("/users/1234/bio");
+//=> { path: '/users/1234/bio', index: 0, params: { id: '1234', tab: 'bio' } }
+
+urlMatch("/users/1234/otherstuff");
+//=> false
+```
+
+#### Process Pathname
+
+You should make sure variations of the same path match the expected `path`. Here's one possible solution using `encode`:
+
+```js
+const fn = match("/café", { encode: encodeURI });
+
+fn("/caf%C3%A9"); //=> { path: '/caf%C3%A9', index: 0, params: {} }
+```
+
+**Note:** [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) encodes paths, so `/café` would be normalized to `/caf%C3%A9` and match in the above example.
+
+##### Alternative Using Normalize
+
+Sometimes you won't have already normalized paths to use, so you could normalize it yourself before matching:
+
+```js
+/**
+ * Normalize a pathname for matching, replaces multiple slashes with a single
+ * slash and normalizes unicode characters to "NFC". When using this method,
+ * `decode` should be an identity function so you don't decode strings twice.
+ */
+function normalizePathname(pathname: string) {
+ return (
+ decodeURI(pathname)
+ // Replaces repeated slashes in the URL.
+ .replace(/\/+/g, "/")
+ // Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
+ // Note: Missing native IE support, may want to skip this step.
+ .normalize()
+ );
+}
+
+// Two possible ways of writing `/café`:
+const re = pathToRegexp("/caf\u00E9");
+const input = encodeURI("/cafe\u0301");
+
+re.test(input); //=> false
+re.test(normalizePathname(input)); //=> true
+```
+
+### Parse
+
+The `parse` function will return a list of strings and keys from a path string:
+
+```js
+const tokens = parse("/route/:foo/(.*)");
+
+console.log(tokens[0]);
+//=> "/route"
+
+console.log(tokens[1]);
+//=> { name: 'foo', prefix: '/', suffix: '', pattern: '[^\\/#\\?]+?', modifier: '' }
+
+console.log(tokens[2]);
+//=> { name: 0, prefix: '/', suffix: '', pattern: '.*', modifier: '' }
+```
+
+**Note:** This method only works with strings.
+
+### Compile ("Reverse" Path-To-RegExp)
+
+The `compile` function will return a function for transforming parameters into a valid path:
+
+```js
+// Make sure you encode your path segments consistently.
+const toPath = compile("/user/:id", { encode: encodeURIComponent });
+
+toPath({ id: 123 }); //=> "/user/123"
+toPath({ id: "café" }); //=> "/user/caf%C3%A9"
+toPath({ id: ":/" }); //=> "/user/%3A%2F"
+
+// Without `encode`, you need to make sure inputs are encoded correctly.
+// (Note: You can use `validate: false` to create an invalid paths.)
+const toPathRaw = compile("/user/:id", { validate: false });
+
+toPathRaw({ id: "%3A%2F" }); //=> "/user/%3A%2F"
+toPathRaw({ id: ":/" }); //=> "/user/:/"
+
+const toPathRepeated = compile("/:segment+");
+
+toPathRepeated({ segment: "foo" }); //=> "/foo"
+toPathRepeated({ segment: ["a", "b", "c"] }); //=> "/a/b/c"
+
+const toPathRegexp = compile("/user/:id(\\d+)");
+
+toPathRegexp({ id: 123 }); //=> "/user/123"
+toPathRegexp({ id: "123" }); //=> "/user/123"
+```
+
+**Note:** The generated function will throw on invalid input.
+
+### Working with Tokens
+
+Path-To-RegExp exposes the two functions used internally that accept an array of tokens:
+
+- `tokensToRegexp(tokens, keys?, options?)` Transform an array of tokens into a matching regular expression.
+- `tokensToFunction(tokens)` Transform an array of tokens into a path generator function.
+
+#### Token Information
+
+- `name` The name of the token (`string` for named or `number` for unnamed index)
+- `prefix` The prefix string for the segment (e.g. `"/"`)
+- `suffix` The suffix string for the segment (e.g. `""`)
+- `pattern` The RegExp used to match this token (`string`)
+- `modifier` The modifier character used for the segment (e.g. `?`)
+
+## Compatibility with Express <= 4.x
+
+Path-To-RegExp breaks compatibility with Express <= `4.x`:
+
+- RegExp special characters can only be used in a parameter
+ - Express.js 4.x supported `RegExp` special characters regardless of position - this is considered a bug
+- Parameters have suffixes that augment meaning - `*`, `+` and `?`. E.g. `/:user*`
+- No wildcard asterisk (`*`) - use parameters instead (`(.*)` or `:splat*`)
+
+## Live Demo
+
+You can see a live demo of this library in use at [express-route-tester](http://forbeslindesay.github.io/express-route-tester/).
+
+## License
+
+MIT
+
+[npm-image]: https://img.shields.io/npm/v/path-to-regexp
+[npm-url]: https://npmjs.org/package/path-to-regexp
+[downloads-image]: https://img.shields.io/npm/dm/path-to-regexp
+[downloads-url]: https://npmjs.org/package/path-to-regexp
+[build-image]: https://img.shields.io/github/actions/workflow/status/pillarjs/path-to-regexp/ci.yml?branch=master
+[build-url]: https://github.com/pillarjs/path-to-regexp/actions/workflows/ci.yml?query=branch%3Amaster
+[coverage-image]: https://img.shields.io/codecov/c/gh/pillarjs/path-to-regexp
+[coverage-url]: https://codecov.io/gh/pillarjs/path-to-regexp
+[license-image]: http://img.shields.io/npm/l/path-to-regexp.svg?style=flat
+[license-url]: LICENSE.md
diff --git a/node_modules/path-to-regexp/dist.es2015/index.js b/node_modules/path-to-regexp/dist.es2015/index.js
new file mode 100644
index 0000000..62e30de
--- /dev/null
+++ b/node_modules/path-to-regexp/dist.es2015/index.js
@@ -0,0 +1,415 @@
+/**
+ * Tokenize input string.
+ */
+function lexer(str) {
+ var tokens = [];
+ var i = 0;
+ while (i < str.length) {
+ var char = str[i];
+ if (char === "*" || char === "+" || char === "?") {
+ tokens.push({ type: "MODIFIER", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === "\\") {
+ tokens.push({ type: "ESCAPED_CHAR", index: i++, value: str[i++] });
+ continue;
+ }
+ if (char === "{") {
+ tokens.push({ type: "OPEN", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === "}") {
+ tokens.push({ type: "CLOSE", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === ":") {
+ var name = "";
+ var j = i + 1;
+ while (j < str.length) {
+ var code = str.charCodeAt(j);
+ if (
+ // `0-9`
+ (code >= 48 && code <= 57) ||
+ // `A-Z`
+ (code >= 65 && code <= 90) ||
+ // `a-z`
+ (code >= 97 && code <= 122) ||
+ // `_`
+ code === 95) {
+ name += str[j++];
+ continue;
+ }
+ break;
+ }
+ if (!name)
+ throw new TypeError("Missing parameter name at ".concat(i));
+ tokens.push({ type: "NAME", index: i, value: name });
+ i = j;
+ continue;
+ }
+ if (char === "(") {
+ var count = 1;
+ var pattern = "";
+ var j = i + 1;
+ if (str[j] === "?") {
+ throw new TypeError("Pattern cannot start with \"?\" at ".concat(j));
+ }
+ while (j < str.length) {
+ if (str[j] === "\\") {
+ pattern += str[j++] + str[j++];
+ continue;
+ }
+ if (str[j] === ")") {
+ count--;
+ if (count === 0) {
+ j++;
+ break;
+ }
+ }
+ else if (str[j] === "(") {
+ count++;
+ if (str[j + 1] !== "?") {
+ throw new TypeError("Capturing groups are not allowed at ".concat(j));
+ }
+ }
+ pattern += str[j++];
+ }
+ if (count)
+ throw new TypeError("Unbalanced pattern at ".concat(i));
+ if (!pattern)
+ throw new TypeError("Missing pattern at ".concat(i));
+ tokens.push({ type: "PATTERN", index: i, value: pattern });
+ i = j;
+ continue;
+ }
+ tokens.push({ type: "CHAR", index: i, value: str[i++] });
+ }
+ tokens.push({ type: "END", index: i, value: "" });
+ return tokens;
+}
+/**
+ * Parse a string for the raw tokens.
+ */
+export function parse(str, options) {
+ if (options === void 0) { options = {}; }
+ var tokens = lexer(str);
+ var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a, _b = options.delimiter, delimiter = _b === void 0 ? "/#?" : _b;
+ var result = [];
+ var key = 0;
+ var i = 0;
+ var path = "";
+ var tryConsume = function (type) {
+ if (i < tokens.length && tokens[i].type === type)
+ return tokens[i++].value;
+ };
+ var mustConsume = function (type) {
+ var value = tryConsume(type);
+ if (value !== undefined)
+ return value;
+ var _a = tokens[i], nextType = _a.type, index = _a.index;
+ throw new TypeError("Unexpected ".concat(nextType, " at ").concat(index, ", expected ").concat(type));
+ };
+ var consumeText = function () {
+ var result = "";
+ var value;
+ while ((value = tryConsume("CHAR") || tryConsume("ESCAPED_CHAR"))) {
+ result += value;
+ }
+ return result;
+ };
+ var isSafe = function (value) {
+ for (var _i = 0, delimiter_1 = delimiter; _i < delimiter_1.length; _i++) {
+ var char = delimiter_1[_i];
+ if (value.indexOf(char) > -1)
+ return true;
+ }
+ return false;
+ };
+ var safePattern = function (prefix) {
+ var prev = result[result.length - 1];
+ var prevText = prefix || (prev && typeof prev === "string" ? prev : "");
+ if (prev && !prevText) {
+ throw new TypeError("Must have text between two parameters, missing text after \"".concat(prev.name, "\""));
+ }
+ if (!prevText || isSafe(prevText))
+ return "[^".concat(escapeString(delimiter), "]+?");
+ return "(?:(?!".concat(escapeString(prevText), ")[^").concat(escapeString(delimiter), "])+?");
+ };
+ while (i < tokens.length) {
+ var char = tryConsume("CHAR");
+ var name = tryConsume("NAME");
+ var pattern = tryConsume("PATTERN");
+ if (name || pattern) {
+ var prefix = char || "";
+ if (prefixes.indexOf(prefix) === -1) {
+ path += prefix;
+ prefix = "";
+ }
+ if (path) {
+ result.push(path);
+ path = "";
+ }
+ result.push({
+ name: name || key++,
+ prefix: prefix,
+ suffix: "",
+ pattern: pattern || safePattern(prefix),
+ modifier: tryConsume("MODIFIER") || "",
+ });
+ continue;
+ }
+ var value = char || tryConsume("ESCAPED_CHAR");
+ if (value) {
+ path += value;
+ continue;
+ }
+ if (path) {
+ result.push(path);
+ path = "";
+ }
+ var open = tryConsume("OPEN");
+ if (open) {
+ var prefix = consumeText();
+ var name_1 = tryConsume("NAME") || "";
+ var pattern_1 = tryConsume("PATTERN") || "";
+ var suffix = consumeText();
+ mustConsume("CLOSE");
+ result.push({
+ name: name_1 || (pattern_1 ? key++ : ""),
+ pattern: name_1 && !pattern_1 ? safePattern(prefix) : pattern_1,
+ prefix: prefix,
+ suffix: suffix,
+ modifier: tryConsume("MODIFIER") || "",
+ });
+ continue;
+ }
+ mustConsume("END");
+ }
+ return result;
+}
+/**
+ * Compile a string to a template function for the path.
+ */
+export function compile(str, options) {
+ return tokensToFunction(parse(str, options), options);
+}
+/**
+ * Expose a method for transforming tokens into the path function.
+ */
+export function tokensToFunction(tokens, options) {
+ if (options === void 0) { options = {}; }
+ var reFlags = flags(options);
+ var _a = options.encode, encode = _a === void 0 ? function (x) { return x; } : _a, _b = options.validate, validate = _b === void 0 ? true : _b;
+ // Compile all the tokens into regexps.
+ var matches = tokens.map(function (token) {
+ if (typeof token === "object") {
+ return new RegExp("^(?:".concat(token.pattern, ")$"), reFlags);
+ }
+ });
+ return function (data) {
+ var path = "";
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+ if (typeof token === "string") {
+ path += token;
+ continue;
+ }
+ var value = data ? data[token.name] : undefined;
+ var optional = token.modifier === "?" || token.modifier === "*";
+ var repeat = token.modifier === "*" || token.modifier === "+";
+ if (Array.isArray(value)) {
+ if (!repeat) {
+ throw new TypeError("Expected \"".concat(token.name, "\" to not repeat, but got an array"));
+ }
+ if (value.length === 0) {
+ if (optional)
+ continue;
+ throw new TypeError("Expected \"".concat(token.name, "\" to not be empty"));
+ }
+ for (var j = 0; j < value.length; j++) {
+ var segment = encode(value[j], token);
+ if (validate && !matches[i].test(segment)) {
+ throw new TypeError("Expected all \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
+ }
+ path += token.prefix + segment + token.suffix;
+ }
+ continue;
+ }
+ if (typeof value === "string" || typeof value === "number") {
+ var segment = encode(String(value), token);
+ if (validate && !matches[i].test(segment)) {
+ throw new TypeError("Expected \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
+ }
+ path += token.prefix + segment + token.suffix;
+ continue;
+ }
+ if (optional)
+ continue;
+ var typeOfMessage = repeat ? "an array" : "a string";
+ throw new TypeError("Expected \"".concat(token.name, "\" to be ").concat(typeOfMessage));
+ }
+ return path;
+ };
+}
+/**
+ * Create path match function from `path-to-regexp` spec.
+ */
+export function match(str, options) {
+ var keys = [];
+ var re = pathToRegexp(str, keys, options);
+ return regexpToFunction(re, keys, options);
+}
+/**
+ * Create a path match function from `path-to-regexp` output.
+ */
+export function regexpToFunction(re, keys, options) {
+ if (options === void 0) { options = {}; }
+ var _a = options.decode, decode = _a === void 0 ? function (x) { return x; } : _a;
+ return function (pathname) {
+ var m = re.exec(pathname);
+ if (!m)
+ return false;
+ var path = m[0], index = m.index;
+ var params = Object.create(null);
+ var _loop_1 = function (i) {
+ if (m[i] === undefined)
+ return "continue";
+ var key = keys[i - 1];
+ if (key.modifier === "*" || key.modifier === "+") {
+ params[key.name] = m[i].split(key.prefix + key.suffix).map(function (value) {
+ return decode(value, key);
+ });
+ }
+ else {
+ params[key.name] = decode(m[i], key);
+ }
+ };
+ for (var i = 1; i < m.length; i++) {
+ _loop_1(i);
+ }
+ return { path: path, index: index, params: params };
+ };
+}
+/**
+ * Escape a regular expression string.
+ */
+function escapeString(str) {
+ return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
+}
+/**
+ * Get the flags for a regexp from the options.
+ */
+function flags(options) {
+ return options && options.sensitive ? "" : "i";
+}
+/**
+ * Pull out keys from a regexp.
+ */
+function regexpToRegexp(path, keys) {
+ if (!keys)
+ return path;
+ var groupsRegex = /\((?:\?<(.*?)>)?(?!\?)/g;
+ var index = 0;
+ var execResult = groupsRegex.exec(path.source);
+ while (execResult) {
+ keys.push({
+ // Use parenthesized substring match if available, index otherwise
+ name: execResult[1] || index++,
+ prefix: "",
+ suffix: "",
+ modifier: "",
+ pattern: "",
+ });
+ execResult = groupsRegex.exec(path.source);
+ }
+ return path;
+}
+/**
+ * Transform an array into a regexp.
+ */
+function arrayToRegexp(paths, keys, options) {
+ var parts = paths.map(function (path) { return pathToRegexp(path, keys, options).source; });
+ return new RegExp("(?:".concat(parts.join("|"), ")"), flags(options));
+}
+/**
+ * Create a path regexp from string input.
+ */
+function stringToRegexp(path, keys, options) {
+ return tokensToRegexp(parse(path, options), keys, options);
+}
+/**
+ * Expose a function for taking tokens and returning a RegExp.
+ */
+export function tokensToRegexp(tokens, keys, options) {
+ if (options === void 0) { options = {}; }
+ var _a = options.strict, strict = _a === void 0 ? false : _a, _b = options.start, start = _b === void 0 ? true : _b, _c = options.end, end = _c === void 0 ? true : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d, _e = options.delimiter, delimiter = _e === void 0 ? "/#?" : _e, _f = options.endsWith, endsWith = _f === void 0 ? "" : _f;
+ var endsWithRe = "[".concat(escapeString(endsWith), "]|$");
+ var delimiterRe = "[".concat(escapeString(delimiter), "]");
+ var route = start ? "^" : "";
+ // Iterate over the tokens and create our regexp string.
+ for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {
+ var token = tokens_1[_i];
+ if (typeof token === "string") {
+ route += escapeString(encode(token));
+ }
+ else {
+ var prefix = escapeString(encode(token.prefix));
+ var suffix = escapeString(encode(token.suffix));
+ if (token.pattern) {
+ if (keys)
+ keys.push(token);
+ if (prefix || suffix) {
+ if (token.modifier === "+" || token.modifier === "*") {
+ var mod = token.modifier === "*" ? "?" : "";
+ route += "(?:".concat(prefix, "((?:").concat(token.pattern, ")(?:").concat(suffix).concat(prefix, "(?:").concat(token.pattern, "))*)").concat(suffix, ")").concat(mod);
+ }
+ else {
+ route += "(?:".concat(prefix, "(").concat(token.pattern, ")").concat(suffix, ")").concat(token.modifier);
+ }
+ }
+ else {
+ if (token.modifier === "+" || token.modifier === "*") {
+ throw new TypeError("Can not repeat \"".concat(token.name, "\" without a prefix and suffix"));
+ }
+ route += "(".concat(token.pattern, ")").concat(token.modifier);
+ }
+ }
+ else {
+ route += "(?:".concat(prefix).concat(suffix, ")").concat(token.modifier);
+ }
+ }
+ }
+ if (end) {
+ if (!strict)
+ route += "".concat(delimiterRe, "?");
+ route += !options.endsWith ? "$" : "(?=".concat(endsWithRe, ")");
+ }
+ else {
+ var endToken = tokens[tokens.length - 1];
+ var isEndDelimited = typeof endToken === "string"
+ ? delimiterRe.indexOf(endToken[endToken.length - 1]) > -1
+ : endToken === undefined;
+ if (!strict) {
+ route += "(?:".concat(delimiterRe, "(?=").concat(endsWithRe, "))?");
+ }
+ if (!isEndDelimited) {
+ route += "(?=".concat(delimiterRe, "|").concat(endsWithRe, ")");
+ }
+ }
+ return new RegExp(route, flags(options));
+}
+/**
+ * Normalize the given path string, returning a regular expression.
+ *
+ * An empty array can be passed in for the keys, which will hold the
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
+ */
+export function pathToRegexp(path, keys, options) {
+ if (path instanceof RegExp)
+ return regexpToRegexp(path, keys);
+ if (Array.isArray(path))
+ return arrayToRegexp(path, keys, options);
+ return stringToRegexp(path, keys, options);
+}
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/node_modules/path-to-regexp/dist.es2015/index.js.map b/node_modules/path-to-regexp/dist.es2015/index.js.map
new file mode 100644
index 0000000..e2d7356
--- /dev/null
+++ b/node_modules/path-to-regexp/dist.es2015/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA;;GAEG;AACH,SAAS,KAAK,CAAC,GAAW;IACxB,IAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE;QACrB,IAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE;YAChD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7D,SAAS;SACV;QAED,IAAI,IAAI,KAAK,IAAI,EAAE;YACjB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACnE,SAAS;SACV;QAED,IAAI,IAAI,KAAK,GAAG,EAAE;YAChB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACzD,SAAS;SACV;QAED,IAAI,IAAI,KAAK,GAAG,EAAE;YAChB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC1D,SAAS;SACV;QAED,IAAI,IAAI,KAAK,GAAG,EAAE;YAChB,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEd,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE;gBACrB,IAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAE/B;gBACE,QAAQ;gBACR,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC;oBAC1B,QAAQ;oBACR,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC;oBAC1B,QAAQ;oBACR,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,GAAG,CAAC;oBAC3B,MAAM;oBACN,IAAI,KAAK,EAAE,EACX;oBACA,IAAI,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;oBACjB,SAAS;iBACV;gBAED,MAAM;aACP;YAED,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,SAAS,CAAC,oCAA6B,CAAC,CAAE,CAAC,CAAC;YAEjE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,CAAC,GAAG,CAAC,CAAC;YACN,SAAS;SACV;QAED,IAAI,IAAI,KAAK,GAAG,EAAE;YAChB,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,IAAI,OAAO,GAAG,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEd,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;gBAClB,MAAM,IAAI,SAAS,CAAC,6CAAoC,CAAC,CAAE,CAAC,CAAC;aAC9D;YAED,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE;gBACrB,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;oBACnB,OAAO,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC/B,SAAS;iBACV;gBAED,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;oBAClB,KAAK,EAAE,CAAC;oBACR,IAAI,KAAK,KAAK,CAAC,EAAE;wBACf,CAAC,EAAE,CAAC;wBACJ,MAAM;qBACP;iBACF;qBAAM,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;oBACzB,KAAK,EAAE,CAAC;oBACR,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE;wBACtB,MAAM,IAAI,SAAS,CAAC,8CAAuC,CAAC,CAAE,CAAC,CAAC;qBACjE;iBACF;gBAED,OAAO,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;aACrB;YAED,IAAI,KAAK;gBAAE,MAAM,IAAI,SAAS,CAAC,gCAAyB,CAAC,CAAE,CAAC,CAAC;YAC7D,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,SAAS,CAAC,6BAAsB,CAAC,CAAE,CAAC,CAAC;YAE7D,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YAC3D,CAAC,GAAG,CAAC,CAAC;YACN,SAAS;SACV;QAED,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;KAC1D;IAED,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAElD,OAAO,MAAM,CAAC;AAChB,CAAC;AAaD;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,GAAW,EAAE,OAA0B;IAA1B,wBAAA,EAAA,YAA0B;IAC3D,IAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,IAAA,KAAuC,OAAO,SAA/B,EAAf,QAAQ,mBAAG,IAAI,KAAA,EAAE,KAAsB,OAAO,UAAZ,EAAjB,SAAS,mBAAG,KAAK,KAAA,CAAa;IACvD,IAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,IAAI,IAAI,GAAG,EAAE,CAAC;IAEd,IAAM,UAAU,GAAG,UAAC,IAAsB;QACxC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;IAC7E,CAAC,CAAC;IAEF,IAAM,WAAW,GAAG,UAAC,IAAsB;QACzC,IAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAChC,IAAA,KAA4B,MAAM,CAAC,CAAC,CAAC,EAA7B,QAAQ,UAAA,EAAE,KAAK,WAAc,CAAC;QAC5C,MAAM,IAAI,SAAS,CAAC,qBAAc,QAAQ,iBAAO,KAAK,wBAAc,IAAI,CAAE,CAAC,CAAC;IAC9E,CAAC,CAAC;IAEF,IAAM,WAAW,GAAG;QAClB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,KAAyB,CAAC;QAC9B,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,cAAc,CAAC,CAAC,EAAE;YACjE,MAAM,IAAI,KAAK,CAAC;SACjB;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,IAAM,MAAM,GAAG,UAAC,KAAa;QAC3B,KAAmB,UAAS,EAAT,uBAAS,EAAT,uBAAS,EAAT,IAAS;YAAvB,IAAM,IAAI,kBAAA;YAAe,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;SAAA;QACxE,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,IAAM,WAAW,GAAG,UAAC,MAAc;QACjC,IAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACvC,IAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAE1E,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE;YACrB,MAAM,IAAI,SAAS,CACjB,sEAA+D,IAAY,CAAC,IAAI,OAAG,CACpF,CAAC;SACH;QAED,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC;YAAE,OAAO,YAAK,YAAY,CAAC,SAAS,CAAC,QAAK,CAAC;QAC5E,OAAO,gBAAS,YAAY,CAAC,QAAQ,CAAC,gBAAM,YAAY,CAAC,SAAS,CAAC,SAAM,CAAC;IAC5E,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE;QACxB,IAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAChC,IAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAChC,IAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QAEtC,IAAI,IAAI,IAAI,OAAO,EAAE;YACnB,IAAI,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YAExB,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;gBACnC,IAAI,IAAI,MAAM,CAAC;gBACf,MAAM,GAAG,EAAE,CAAC;aACb;YAED,IAAI,IAAI,EAAE;gBACR,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClB,IAAI,GAAG,EAAE,CAAC;aACX;YAED,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,IAAI,IAAI,GAAG,EAAE;gBACnB,MAAM,QAAA;gBACN,MAAM,EAAE,EAAE;gBACV,OAAO,EAAE,OAAO,IAAI,WAAW,CAAC,MAAM,CAAC;gBACvC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE;aACvC,CAAC,CAAC;YACH,SAAS;SACV;QAED,IAAM,KAAK,GAAG,IAAI,IAAI,UAAU,CAAC,cAAc,CAAC,CAAC;QACjD,IAAI,KAAK,EAAE;YACT,IAAI,IAAI,KAAK,CAAC;YACd,SAAS;SACV;QAED,IAAI,IAAI,EAAE;YACR,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,IAAI,GAAG,EAAE,CAAC;SACX;QAED,IAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,IAAI,EAAE;YACR,IAAM,MAAM,GAAG,WAAW,EAAE,CAAC;YAC7B,IAAM,MAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACtC,IAAM,SAAO,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAM,MAAM,GAAG,WAAW,EAAE,CAAC;YAE7B,WAAW,CAAC,OAAO,CAAC,CAAC;YAErB,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,MAAI,IAAI,CAAC,SAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpC,OAAO,EAAE,MAAI,IAAI,CAAC,SAAO,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAO;gBACzD,MAAM,QAAA;gBACN,MAAM,QAAA;gBACN,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE;aACvC,CAAC,CAAC;YACH,SAAS;SACV;QAED,WAAW,CAAC,KAAK,CAAC,CAAC;KACpB;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAiBD;;GAEG;AACH,MAAM,UAAU,OAAO,CACrB,GAAW,EACX,OAAgD;IAEhD,OAAO,gBAAgB,CAAI,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;AAC3D,CAAC;AAID;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAe,EACf,OAAqC;IAArC,wBAAA,EAAA,YAAqC;IAErC,IAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IACvB,IAAA,KAA+C,OAAO,OAA7B,EAAzB,MAAM,mBAAG,UAAC,CAAS,IAAK,OAAA,CAAC,EAAD,CAAC,KAAA,EAAE,KAAoB,OAAO,SAAZ,EAAf,QAAQ,mBAAG,IAAI,KAAA,CAAa;IAE/D,uCAAuC;IACvC,IAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,UAAC,KAAK;QAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC7B,OAAO,IAAI,MAAM,CAAC,cAAO,KAAK,CAAC,OAAO,OAAI,EAAE,OAAO,CAAC,CAAC;SACtD;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,UAAC,IAA4C;QAClD,IAAI,IAAI,GAAG,EAAE,CAAC;QAEd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACtC,IAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAExB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBAC7B,IAAI,IAAI,KAAK,CAAC;gBACd,SAAS;aACV;YAED,IAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAClD,IAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC;YAClE,IAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC;YAEhE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBACxB,IAAI,CAAC,MAAM,EAAE;oBACX,MAAM,IAAI,SAAS,CACjB,qBAAa,KAAK,CAAC,IAAI,uCAAmC,CAC3D,CAAC;iBACH;gBAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;oBACtB,IAAI,QAAQ;wBAAE,SAAS;oBAEvB,MAAM,IAAI,SAAS,CAAC,qBAAa,KAAK,CAAC,IAAI,uBAAmB,CAAC,CAAC;iBACjE;gBAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBACrC,IAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;oBAExC,IAAI,QAAQ,IAAI,CAAE,OAAO,CAAC,CAAC,CAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;wBACrD,MAAM,IAAI,SAAS,CACjB,yBAAiB,KAAK,CAAC,IAAI,2BAAe,KAAK,CAAC,OAAO,2BAAe,OAAO,OAAG,CACjF,CAAC;qBACH;oBAED,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC;iBAC/C;gBAED,SAAS;aACV;YAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBAC1D,IAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;gBAE7C,IAAI,QAAQ,IAAI,CAAE,OAAO,CAAC,CAAC,CAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;oBACrD,MAAM,IAAI,SAAS,CACjB,qBAAa,KAAK,CAAC,IAAI,2BAAe,KAAK,CAAC,OAAO,2BAAe,OAAO,OAAG,CAC7E,CAAC;iBACH;gBAED,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC;gBAC9C,SAAS;aACV;YAED,IAAI,QAAQ;gBAAE,SAAS;YAEvB,IAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;YACvD,MAAM,IAAI,SAAS,CAAC,qBAAa,KAAK,CAAC,IAAI,sBAAW,aAAa,CAAE,CAAC,CAAC;SACxE;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC;AA8BD;;GAEG;AACH,MAAM,UAAU,KAAK,CACnB,GAAS,EACT,OAAwE;IAExE,IAAM,IAAI,GAAU,EAAE,CAAC;IACvB,IAAM,EAAE,GAAG,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,gBAAgB,CAAI,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,EAAU,EACV,IAAW,EACX,OAAqC;IAArC,wBAAA,EAAA,YAAqC;IAE7B,IAAA,KAA8B,OAAO,OAAZ,EAAzB,MAAM,mBAAG,UAAC,CAAS,IAAK,OAAA,CAAC,EAAD,CAAC,KAAA,CAAa;IAE9C,OAAO,UAAU,QAAgB;QAC/B,IAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAEb,IAAG,IAAI,GAAY,CAAC,GAAb,EAAE,KAAK,GAAK,CAAC,MAAN,CAAO;QAC7B,IAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gCAE1B,CAAC;YACR,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS;kCAAW;YAEjC,IAAM,GAAG,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAExB,IAAI,GAAG,CAAC,QAAQ,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,KAAK,GAAG,EAAE;gBAChD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,UAAC,KAAK;oBAC/D,OAAO,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC5B,CAAC,CAAC,CAAC;aACJ;iBAAM;gBACL,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;aACtC;;QAXH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;oBAAxB,CAAC;SAYT;QAED,OAAO,EAAE,IAAI,MAAA,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,EAAE,CAAC;IACjC,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG,CAAC,OAAO,CAAC,2BAA2B,EAAE,MAAM,CAAC,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,SAAS,KAAK,CAAC,OAAiC;IAC9C,OAAO,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AACjD,CAAC;AAkBD;;GAEG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,IAAY;IAChD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,IAAM,WAAW,GAAG,yBAAyB,CAAC;IAE9C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C,OAAO,UAAU,EAAE;QACjB,IAAI,CAAC,IAAI,CAAC;YACR,kEAAkE;YAClE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE;YAC9B,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,EAAE;YACZ,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QACH,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;KAC5C;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CACpB,KAA6B,EAC7B,IAAY,EACZ,OAA8C;IAE9C,IAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,UAAC,IAAI,IAAK,OAAA,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,MAAM,EAAxC,CAAwC,CAAC,CAAC;IAC5E,OAAO,IAAI,MAAM,CAAC,aAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACrB,IAAY,EACZ,IAAY,EACZ,OAA8C;IAE9C,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC7D,CAAC;AAiCD;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAe,EACf,IAAY,EACZ,OAAmC;IAAnC,wBAAA,EAAA,YAAmC;IAGjC,IAAA,KAME,OAAO,OANK,EAAd,MAAM,mBAAG,KAAK,KAAA,EACd,KAKE,OAAO,MALG,EAAZ,KAAK,mBAAG,IAAI,KAAA,EACZ,KAIE,OAAO,IAJC,EAAV,GAAG,mBAAG,IAAI,KAAA,EACV,KAGE,OAAO,OAHgB,EAAzB,MAAM,mBAAG,UAAC,CAAS,IAAK,OAAA,CAAC,EAAD,CAAC,KAAA,EACzB,KAEE,OAAO,UAFQ,EAAjB,SAAS,mBAAG,KAAK,KAAA,EACjB,KACE,OAAO,SADI,EAAb,QAAQ,mBAAG,EAAE,KAAA,CACH;IACZ,IAAM,UAAU,GAAG,WAAI,YAAY,CAAC,QAAQ,CAAC,QAAK,CAAC;IACnD,IAAM,WAAW,GAAG,WAAI,YAAY,CAAC,SAAS,CAAC,MAAG,CAAC;IACnD,IAAI,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7B,wDAAwD;IACxD,KAAoB,UAAM,EAAN,iBAAM,EAAN,oBAAM,EAAN,IAAM,EAAE;QAAvB,IAAM,KAAK,eAAA;QACd,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC7B,KAAK,IAAI,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;SACtC;aAAM;YACL,IAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;YAClD,IAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;YAElD,IAAI,KAAK,CAAC,OAAO,EAAE;gBACjB,IAAI,IAAI;oBAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAE3B,IAAI,MAAM,IAAI,MAAM,EAAE;oBACpB,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,EAAE;wBACpD,IAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC9C,KAAK,IAAI,aAAM,MAAM,iBAAO,KAAK,CAAC,OAAO,iBAAO,MAAM,SAAG,MAAM,gBAAM,KAAK,CAAC,OAAO,iBAAO,MAAM,cAAI,GAAG,CAAE,CAAC;qBAC1G;yBAAM;wBACL,KAAK,IAAI,aAAM,MAAM,cAAI,KAAK,CAAC,OAAO,cAAI,MAAM,cAAI,KAAK,CAAC,QAAQ,CAAE,CAAC;qBACtE;iBACF;qBAAM;oBACL,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,EAAE;wBACpD,MAAM,IAAI,SAAS,CACjB,2BAAmB,KAAK,CAAC,IAAI,mCAA+B,CAC7D,CAAC;qBACH;oBAED,KAAK,IAAI,WAAI,KAAK,CAAC,OAAO,cAAI,KAAK,CAAC,QAAQ,CAAE,CAAC;iBAChD;aACF;iBAAM;gBACL,KAAK,IAAI,aAAM,MAAM,SAAG,MAAM,cAAI,KAAK,CAAC,QAAQ,CAAE,CAAC;aACpD;SACF;KACF;IAED,IAAI,GAAG,EAAE;QACP,IAAI,CAAC,MAAM;YAAE,KAAK,IAAI,UAAG,WAAW,MAAG,CAAC;QAExC,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,aAAM,UAAU,MAAG,CAAC;KACxD;SAAM;QACL,IAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC3C,IAAM,cAAc,GAClB,OAAO,QAAQ,KAAK,QAAQ;YAC1B,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACzD,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC;QAE7B,IAAI,CAAC,MAAM,EAAE;YACX,KAAK,IAAI,aAAM,WAAW,gBAAM,UAAU,QAAK,CAAC;SACjD;QAED,IAAI,CAAC,cAAc,EAAE;YACnB,KAAK,IAAI,aAAM,WAAW,cAAI,UAAU,MAAG,CAAC;SAC7C;KACF;IAED,OAAO,IAAI,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3C,CAAC;AAOD;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAU,EACV,IAAY,EACZ,OAA8C;IAE9C,IAAI,IAAI,YAAY,MAAM;QAAE,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9D,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACnE,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["/**\n * Tokenizer results.\n */\ninterface LexToken {\n type:\n | \"OPEN\"\n | \"CLOSE\"\n | \"PATTERN\"\n | \"NAME\"\n | \"CHAR\"\n | \"ESCAPED_CHAR\"\n | \"MODIFIER\"\n | \"END\";\n index: number;\n value: string;\n}\n\n/**\n * Tokenize input string.\n */\nfunction lexer(str: string): LexToken[] {\n const tokens: LexToken[] = [];\n let i = 0;\n\n while (i < str.length) {\n const char = str[i];\n\n if (char === \"*\" || char === \"+\" || char === \"?\") {\n tokens.push({ type: \"MODIFIER\", index: i, value: str[i++] });\n continue;\n }\n\n if (char === \"\\\\\") {\n tokens.push({ type: \"ESCAPED_CHAR\", index: i++, value: str[i++] });\n continue;\n }\n\n if (char === \"{\") {\n tokens.push({ type: \"OPEN\", index: i, value: str[i++] });\n continue;\n }\n\n if (char === \"}\") {\n tokens.push({ type: \"CLOSE\", index: i, value: str[i++] });\n continue;\n }\n\n if (char === \":\") {\n let name = \"\";\n let j = i + 1;\n\n while (j < str.length) {\n const code = str.charCodeAt(j);\n\n if (\n // `0-9`\n (code >= 48 && code <= 57) ||\n // `A-Z`\n (code >= 65 && code <= 90) ||\n // `a-z`\n (code >= 97 && code <= 122) ||\n // `_`\n code === 95\n ) {\n name += str[j++];\n continue;\n }\n\n break;\n }\n\n if (!name) throw new TypeError(`Missing parameter name at ${i}`);\n\n tokens.push({ type: \"NAME\", index: i, value: name });\n i = j;\n continue;\n }\n\n if (char === \"(\") {\n let count = 1;\n let pattern = \"\";\n let j = i + 1;\n\n if (str[j] === \"?\") {\n throw new TypeError(`Pattern cannot start with \"?\" at ${j}`);\n }\n\n while (j < str.length) {\n if (str[j] === \"\\\\\") {\n pattern += str[j++] + str[j++];\n continue;\n }\n\n if (str[j] === \")\") {\n count--;\n if (count === 0) {\n j++;\n break;\n }\n } else if (str[j] === \"(\") {\n count++;\n if (str[j + 1] !== \"?\") {\n throw new TypeError(`Capturing groups are not allowed at ${j}`);\n }\n }\n\n pattern += str[j++];\n }\n\n if (count) throw new TypeError(`Unbalanced pattern at ${i}`);\n if (!pattern) throw new TypeError(`Missing pattern at ${i}`);\n\n tokens.push({ type: \"PATTERN\", index: i, value: pattern });\n i = j;\n continue;\n }\n\n tokens.push({ type: \"CHAR\", index: i, value: str[i++] });\n }\n\n tokens.push({ type: \"END\", index: i, value: \"\" });\n\n return tokens;\n}\n\nexport interface ParseOptions {\n /**\n * Set the default delimiter for repeat parameters. (default: `'/'`)\n */\n delimiter?: string;\n /**\n * List of characters to automatically consider prefixes when parsing.\n */\n prefixes?: string;\n}\n\n/**\n * Parse a string for the raw tokens.\n */\nexport function parse(str: string, options: ParseOptions = {}): Token[] {\n const tokens = lexer(str);\n const { prefixes = \"./\", delimiter = \"/#?\" } = options;\n const result: Token[] = [];\n let key = 0;\n let i = 0;\n let path = \"\";\n\n const tryConsume = (type: LexToken[\"type\"]): string | undefined => {\n if (i < tokens.length && tokens[i].type === type) return tokens[i++].value;\n };\n\n const mustConsume = (type: LexToken[\"type\"]): string => {\n const value = tryConsume(type);\n if (value !== undefined) return value;\n const { type: nextType, index } = tokens[i];\n throw new TypeError(`Unexpected ${nextType} at ${index}, expected ${type}`);\n };\n\n const consumeText = (): string => {\n let result = \"\";\n let value: string | undefined;\n while ((value = tryConsume(\"CHAR\") || tryConsume(\"ESCAPED_CHAR\"))) {\n result += value;\n }\n return result;\n };\n\n const isSafe = (value: string): boolean => {\n for (const char of delimiter) if (value.indexOf(char) > -1) return true;\n return false;\n };\n\n const safePattern = (prefix: string) => {\n const prev = result[result.length - 1];\n const prevText = prefix || (prev && typeof prev === \"string\" ? prev : \"\");\n\n if (prev && !prevText) {\n throw new TypeError(\n `Must have text between two parameters, missing text after \"${(prev as Key).name}\"`,\n );\n }\n\n if (!prevText || isSafe(prevText)) return `[^${escapeString(delimiter)}]+?`;\n return `(?:(?!${escapeString(prevText)})[^${escapeString(delimiter)}])+?`;\n };\n\n while (i < tokens.length) {\n const char = tryConsume(\"CHAR\");\n const name = tryConsume(\"NAME\");\n const pattern = tryConsume(\"PATTERN\");\n\n if (name || pattern) {\n let prefix = char || \"\";\n\n if (prefixes.indexOf(prefix) === -1) {\n path += prefix;\n prefix = \"\";\n }\n\n if (path) {\n result.push(path);\n path = \"\";\n }\n\n result.push({\n name: name || key++,\n prefix,\n suffix: \"\",\n pattern: pattern || safePattern(prefix),\n modifier: tryConsume(\"MODIFIER\") || \"\",\n });\n continue;\n }\n\n const value = char || tryConsume(\"ESCAPED_CHAR\");\n if (value) {\n path += value;\n continue;\n }\n\n if (path) {\n result.push(path);\n path = \"\";\n }\n\n const open = tryConsume(\"OPEN\");\n if (open) {\n const prefix = consumeText();\n const name = tryConsume(\"NAME\") || \"\";\n const pattern = tryConsume(\"PATTERN\") || \"\";\n const suffix = consumeText();\n\n mustConsume(\"CLOSE\");\n\n result.push({\n name: name || (pattern ? key++ : \"\"),\n pattern: name && !pattern ? safePattern(prefix) : pattern,\n prefix,\n suffix,\n modifier: tryConsume(\"MODIFIER\") || \"\",\n });\n continue;\n }\n\n mustConsume(\"END\");\n }\n\n return result;\n}\n\nexport interface TokensToFunctionOptions {\n /**\n * When `true` the regexp will be case sensitive. (default: `false`)\n */\n sensitive?: boolean;\n /**\n * Function for encoding input strings for output.\n */\n encode?: (value: string, token: Key) => string;\n /**\n * When `false` the function can produce an invalid (unmatched) path. (default: `true`)\n */\n validate?: boolean;\n}\n\n/**\n * Compile a string to a template function for the path.\n */\nexport function compile(\n str: string,\n options?: ParseOptions & TokensToFunctionOptions,\n) {\n return tokensToFunction
(parse(str, options), options);\n}\n\nexport type PathFunction
= (data?: P) => string;\n\n/**\n * Expose a method for transforming tokens into the path function.\n */\nexport function tokensToFunction
(\n tokens: Token[],\n options: TokensToFunctionOptions = {},\n): PathFunction
{\n const reFlags = flags(options);\n const { encode = (x: string) => x, validate = true } = options;\n\n // Compile all the tokens into regexps.\n const matches = tokens.map((token) => {\n if (typeof token === \"object\") {\n return new RegExp(`^(?:${token.pattern})$`, reFlags);\n }\n });\n\n return (data: Record | null | undefined) => {\n let path = \"\";\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n\n if (typeof token === \"string\") {\n path += token;\n continue;\n }\n\n const value = data ? data[token.name] : undefined;\n const optional = token.modifier === \"?\" || token.modifier === \"*\";\n const repeat = token.modifier === \"*\" || token.modifier === \"+\";\n\n if (Array.isArray(value)) {\n if (!repeat) {\n throw new TypeError(\n `Expected \"${token.name}\" to not repeat, but got an array`,\n );\n }\n\n if (value.length === 0) {\n if (optional) continue;\n\n throw new TypeError(`Expected \"${token.name}\" to not be empty`);\n }\n\n for (let j = 0; j < value.length; j++) {\n const segment = encode(value[j], token);\n\n if (validate && !(matches[i] as RegExp).test(segment)) {\n throw new TypeError(\n `Expected all \"${token.name}\" to match \"${token.pattern}\", but got \"${segment}\"`,\n );\n }\n\n path += token.prefix + segment + token.suffix;\n }\n\n continue;\n }\n\n if (typeof value === \"string\" || typeof value === \"number\") {\n const segment = encode(String(value), token);\n\n if (validate && !(matches[i] as RegExp).test(segment)) {\n throw new TypeError(\n `Expected \"${token.name}\" to match \"${token.pattern}\", but got \"${segment}\"`,\n );\n }\n\n path += token.prefix + segment + token.suffix;\n continue;\n }\n\n if (optional) continue;\n\n const typeOfMessage = repeat ? \"an array\" : \"a string\";\n throw new TypeError(`Expected \"${token.name}\" to be ${typeOfMessage}`);\n }\n\n return path;\n };\n}\n\nexport interface RegexpToFunctionOptions {\n /**\n * Function for decoding strings for params.\n */\n decode?: (value: string, token: Key) => string;\n}\n\n/**\n * A match result contains data about the path match.\n */\nexport interface MatchResult {\n path: string;\n index: number;\n params: P;\n}\n\n/**\n * A match is either `false` (no match) or a match result.\n */\nexport type Match
= false | MatchResult
;\n\n/**\n * The match function takes a string and returns whether it matched the path.\n */\nexport type MatchFunction
= (\n path: string,\n) => Match
;\n\n/**\n * Create path match function from `path-to-regexp` spec.\n */\nexport function match
(\n str: Path,\n options?: ParseOptions & TokensToRegexpOptions & RegexpToFunctionOptions,\n) {\n const keys: Key[] = [];\n const re = pathToRegexp(str, keys, options);\n return regexpToFunction
(re, keys, options);\n}\n\n/**\n * Create a path match function from `path-to-regexp` output.\n */\nexport function regexpToFunction
(\n re: RegExp,\n keys: Key[],\n options: RegexpToFunctionOptions = {},\n): MatchFunction
{\n const { decode = (x: string) => x } = options;\n\n return function (pathname: string) {\n const m = re.exec(pathname);\n if (!m) return false;\n\n const { 0: path, index } = m;\n const params = Object.create(null);\n\n for (let i = 1; i < m.length; i++) {\n if (m[i] === undefined) continue;\n\n const key = keys[i - 1];\n\n if (key.modifier === \"*\" || key.modifier === \"+\") {\n params[key.name] = m[i].split(key.prefix + key.suffix).map((value) => {\n return decode(value, key);\n });\n } else {\n params[key.name] = decode(m[i], key);\n }\n }\n\n return { path, index, params };\n };\n}\n\n/**\n * Escape a regular expression string.\n */\nfunction escapeString(str: string) {\n return str.replace(/([.+*?=^!:${}()[\\]|/\\\\])/g, \"\\\\$1\");\n}\n\n/**\n * Get the flags for a regexp from the options.\n */\nfunction flags(options?: { sensitive?: boolean }) {\n return options && options.sensitive ? \"\" : \"i\";\n}\n\n/**\n * Metadata about a key.\n */\nexport interface Key {\n name: string | number;\n prefix: string;\n suffix: string;\n pattern: string;\n modifier: string;\n}\n\n/**\n * A token is a string (nothing special) or key metadata (capture group).\n */\nexport type Token = string | Key;\n\n/**\n * Pull out keys from a regexp.\n */\nfunction regexpToRegexp(path: RegExp, keys?: Key[]): RegExp {\n if (!keys) return path;\n\n const groupsRegex = /\\((?:\\?<(.*?)>)?(?!\\?)/g;\n\n let index = 0;\n let execResult = groupsRegex.exec(path.source);\n while (execResult) {\n keys.push({\n // Use parenthesized substring match if available, index otherwise\n name: execResult[1] || index++,\n prefix: \"\",\n suffix: \"\",\n modifier: \"\",\n pattern: \"\",\n });\n execResult = groupsRegex.exec(path.source);\n }\n\n return path;\n}\n\n/**\n * Transform an array into a regexp.\n */\nfunction arrayToRegexp(\n paths: Array,\n keys?: Key[],\n options?: TokensToRegexpOptions & ParseOptions,\n): RegExp {\n const parts = paths.map((path) => pathToRegexp(path, keys, options).source);\n return new RegExp(`(?:${parts.join(\"|\")})`, flags(options));\n}\n\n/**\n * Create a path regexp from string input.\n */\nfunction stringToRegexp(\n path: string,\n keys?: Key[],\n options?: TokensToRegexpOptions & ParseOptions,\n) {\n return tokensToRegexp(parse(path, options), keys, options);\n}\n\nexport interface TokensToRegexpOptions {\n /**\n * When `true` the regexp will be case sensitive. (default: `false`)\n */\n sensitive?: boolean;\n /**\n * When `true` the regexp won't allow an optional trailing delimiter to match. (default: `false`)\n */\n strict?: boolean;\n /**\n * When `true` the regexp will match to the end of the string. (default: `true`)\n */\n end?: boolean;\n /**\n * When `true` the regexp will match from the beginning of the string. (default: `true`)\n */\n start?: boolean;\n /**\n * Sets the final character for non-ending optimistic matches. (default: `/`)\n */\n delimiter?: string;\n /**\n * List of characters that can also be \"end\" characters.\n */\n endsWith?: string;\n /**\n * Encode path tokens for use in the `RegExp`.\n */\n encode?: (value: string) => string;\n}\n\n/**\n * Expose a function for taking tokens and returning a RegExp.\n */\nexport function tokensToRegexp(\n tokens: Token[],\n keys?: Key[],\n options: TokensToRegexpOptions = {},\n) {\n const {\n strict = false,\n start = true,\n end = true,\n encode = (x: string) => x,\n delimiter = \"/#?\",\n endsWith = \"\",\n } = options;\n const endsWithRe = `[${escapeString(endsWith)}]|$`;\n const delimiterRe = `[${escapeString(delimiter)}]`;\n let route = start ? \"^\" : \"\";\n\n // Iterate over the tokens and create our regexp string.\n for (const token of tokens) {\n if (typeof token === \"string\") {\n route += escapeString(encode(token));\n } else {\n const prefix = escapeString(encode(token.prefix));\n const suffix = escapeString(encode(token.suffix));\n\n if (token.pattern) {\n if (keys) keys.push(token);\n\n if (prefix || suffix) {\n if (token.modifier === \"+\" || token.modifier === \"*\") {\n const mod = token.modifier === \"*\" ? \"?\" : \"\";\n route += `(?:${prefix}((?:${token.pattern})(?:${suffix}${prefix}(?:${token.pattern}))*)${suffix})${mod}`;\n } else {\n route += `(?:${prefix}(${token.pattern})${suffix})${token.modifier}`;\n }\n } else {\n if (token.modifier === \"+\" || token.modifier === \"*\") {\n throw new TypeError(\n `Can not repeat \"${token.name}\" without a prefix and suffix`,\n );\n }\n\n route += `(${token.pattern})${token.modifier}`;\n }\n } else {\n route += `(?:${prefix}${suffix})${token.modifier}`;\n }\n }\n }\n\n if (end) {\n if (!strict) route += `${delimiterRe}?`;\n\n route += !options.endsWith ? \"$\" : `(?=${endsWithRe})`;\n } else {\n const endToken = tokens[tokens.length - 1];\n const isEndDelimited =\n typeof endToken === \"string\"\n ? delimiterRe.indexOf(endToken[endToken.length - 1]) > -1\n : endToken === undefined;\n\n if (!strict) {\n route += `(?:${delimiterRe}(?=${endsWithRe}))?`;\n }\n\n if (!isEndDelimited) {\n route += `(?=${delimiterRe}|${endsWithRe})`;\n }\n }\n\n return new RegExp(route, flags(options));\n}\n\n/**\n * Supported `path-to-regexp` input types.\n */\nexport type Path = string | RegExp | Array;\n\n/**\n * Normalize the given path string, returning a regular expression.\n *\n * An empty array can be passed in for the keys, which will hold the\n * placeholder key descriptions. For example, using `/user/:id`, `keys` will\n * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.\n */\nexport function pathToRegexp(\n path: Path,\n keys?: Key[],\n options?: TokensToRegexpOptions & ParseOptions,\n) {\n if (path instanceof RegExp) return regexpToRegexp(path, keys);\n if (Array.isArray(path)) return arrayToRegexp(path, keys, options);\n return stringToRegexp(path, keys, options);\n}\n"]}
\ No newline at end of file
diff --git a/node_modules/path-to-regexp/dist/index.d.ts b/node_modules/path-to-regexp/dist/index.d.ts
new file mode 100644
index 0000000..6e5d250
--- /dev/null
+++ b/node_modules/path-to-regexp/dist/index.d.ts
@@ -0,0 +1,127 @@
+export interface ParseOptions {
+ /**
+ * Set the default delimiter for repeat parameters. (default: `'/'`)
+ */
+ delimiter?: string;
+ /**
+ * List of characters to automatically consider prefixes when parsing.
+ */
+ prefixes?: string;
+}
+/**
+ * Parse a string for the raw tokens.
+ */
+export declare function parse(str: string, options?: ParseOptions): Token[];
+export interface TokensToFunctionOptions {
+ /**
+ * When `true` the regexp will be case sensitive. (default: `false`)
+ */
+ sensitive?: boolean;
+ /**
+ * Function for encoding input strings for output.
+ */
+ encode?: (value: string, token: Key) => string;
+ /**
+ * When `false` the function can produce an invalid (unmatched) path. (default: `true`)
+ */
+ validate?: boolean;
+}
+/**
+ * Compile a string to a template function for the path.
+ */
+export declare function compile(str: string, options?: ParseOptions & TokensToFunctionOptions): PathFunction
;
+export type PathFunction
= (data?: P) => string;
+/**
+ * Expose a method for transforming tokens into the path function.
+ */
+export declare function tokensToFunction
(tokens: Token[], options?: TokensToFunctionOptions): PathFunction
;
+export interface RegexpToFunctionOptions {
+ /**
+ * Function for decoding strings for params.
+ */
+ decode?: (value: string, token: Key) => string;
+}
+/**
+ * A match result contains data about the path match.
+ */
+export interface MatchResult
{
+ path: string;
+ index: number;
+ params: P;
+}
+/**
+ * A match is either `false` (no match) or a match result.
+ */
+export type Match
= false | MatchResult
;
+/**
+ * The match function takes a string and returns whether it matched the path.
+ */
+export type MatchFunction
= (path: string) => Match
;
+/**
+ * Create path match function from `path-to-regexp` spec.
+ */
+export declare function match
(str: Path, options?: ParseOptions & TokensToRegexpOptions & RegexpToFunctionOptions): MatchFunction
;
+/**
+ * Create a path match function from `path-to-regexp` output.
+ */
+export declare function regexpToFunction
(re: RegExp, keys: Key[], options?: RegexpToFunctionOptions): MatchFunction
;
+/**
+ * Metadata about a key.
+ */
+export interface Key {
+ name: string | number;
+ prefix: string;
+ suffix: string;
+ pattern: string;
+ modifier: string;
+}
+/**
+ * A token is a string (nothing special) or key metadata (capture group).
+ */
+export type Token = string | Key;
+export interface TokensToRegexpOptions {
+ /**
+ * When `true` the regexp will be case sensitive. (default: `false`)
+ */
+ sensitive?: boolean;
+ /**
+ * When `true` the regexp won't allow an optional trailing delimiter to match. (default: `false`)
+ */
+ strict?: boolean;
+ /**
+ * When `true` the regexp will match to the end of the string. (default: `true`)
+ */
+ end?: boolean;
+ /**
+ * When `true` the regexp will match from the beginning of the string. (default: `true`)
+ */
+ start?: boolean;
+ /**
+ * Sets the final character for non-ending optimistic matches. (default: `/`)
+ */
+ delimiter?: string;
+ /**
+ * List of characters that can also be "end" characters.
+ */
+ endsWith?: string;
+ /**
+ * Encode path tokens for use in the `RegExp`.
+ */
+ encode?: (value: string) => string;
+}
+/**
+ * Expose a function for taking tokens and returning a RegExp.
+ */
+export declare function tokensToRegexp(tokens: Token[], keys?: Key[], options?: TokensToRegexpOptions): RegExp;
+/**
+ * Supported `path-to-regexp` input types.
+ */
+export type Path = string | RegExp | Array;
+/**
+ * Normalize the given path string, returning a regular expression.
+ *
+ * An empty array can be passed in for the keys, which will hold the
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
+ */
+export declare function pathToRegexp(path: Path, keys?: Key[], options?: TokensToRegexpOptions & ParseOptions): RegExp;
diff --git a/node_modules/path-to-regexp/dist/index.js b/node_modules/path-to-regexp/dist/index.js
new file mode 100644
index 0000000..7ee8a6a
--- /dev/null
+++ b/node_modules/path-to-regexp/dist/index.js
@@ -0,0 +1,425 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.pathToRegexp = exports.tokensToRegexp = exports.regexpToFunction = exports.match = exports.tokensToFunction = exports.compile = exports.parse = void 0;
+/**
+ * Tokenize input string.
+ */
+function lexer(str) {
+ var tokens = [];
+ var i = 0;
+ while (i < str.length) {
+ var char = str[i];
+ if (char === "*" || char === "+" || char === "?") {
+ tokens.push({ type: "MODIFIER", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === "\\") {
+ tokens.push({ type: "ESCAPED_CHAR", index: i++, value: str[i++] });
+ continue;
+ }
+ if (char === "{") {
+ tokens.push({ type: "OPEN", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === "}") {
+ tokens.push({ type: "CLOSE", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === ":") {
+ var name = "";
+ var j = i + 1;
+ while (j < str.length) {
+ var code = str.charCodeAt(j);
+ if (
+ // `0-9`
+ (code >= 48 && code <= 57) ||
+ // `A-Z`
+ (code >= 65 && code <= 90) ||
+ // `a-z`
+ (code >= 97 && code <= 122) ||
+ // `_`
+ code === 95) {
+ name += str[j++];
+ continue;
+ }
+ break;
+ }
+ if (!name)
+ throw new TypeError("Missing parameter name at ".concat(i));
+ tokens.push({ type: "NAME", index: i, value: name });
+ i = j;
+ continue;
+ }
+ if (char === "(") {
+ var count = 1;
+ var pattern = "";
+ var j = i + 1;
+ if (str[j] === "?") {
+ throw new TypeError("Pattern cannot start with \"?\" at ".concat(j));
+ }
+ while (j < str.length) {
+ if (str[j] === "\\") {
+ pattern += str[j++] + str[j++];
+ continue;
+ }
+ if (str[j] === ")") {
+ count--;
+ if (count === 0) {
+ j++;
+ break;
+ }
+ }
+ else if (str[j] === "(") {
+ count++;
+ if (str[j + 1] !== "?") {
+ throw new TypeError("Capturing groups are not allowed at ".concat(j));
+ }
+ }
+ pattern += str[j++];
+ }
+ if (count)
+ throw new TypeError("Unbalanced pattern at ".concat(i));
+ if (!pattern)
+ throw new TypeError("Missing pattern at ".concat(i));
+ tokens.push({ type: "PATTERN", index: i, value: pattern });
+ i = j;
+ continue;
+ }
+ tokens.push({ type: "CHAR", index: i, value: str[i++] });
+ }
+ tokens.push({ type: "END", index: i, value: "" });
+ return tokens;
+}
+/**
+ * Parse a string for the raw tokens.
+ */
+function parse(str, options) {
+ if (options === void 0) { options = {}; }
+ var tokens = lexer(str);
+ var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a, _b = options.delimiter, delimiter = _b === void 0 ? "/#?" : _b;
+ var result = [];
+ var key = 0;
+ var i = 0;
+ var path = "";
+ var tryConsume = function (type) {
+ if (i < tokens.length && tokens[i].type === type)
+ return tokens[i++].value;
+ };
+ var mustConsume = function (type) {
+ var value = tryConsume(type);
+ if (value !== undefined)
+ return value;
+ var _a = tokens[i], nextType = _a.type, index = _a.index;
+ throw new TypeError("Unexpected ".concat(nextType, " at ").concat(index, ", expected ").concat(type));
+ };
+ var consumeText = function () {
+ var result = "";
+ var value;
+ while ((value = tryConsume("CHAR") || tryConsume("ESCAPED_CHAR"))) {
+ result += value;
+ }
+ return result;
+ };
+ var isSafe = function (value) {
+ for (var _i = 0, delimiter_1 = delimiter; _i < delimiter_1.length; _i++) {
+ var char = delimiter_1[_i];
+ if (value.indexOf(char) > -1)
+ return true;
+ }
+ return false;
+ };
+ var safePattern = function (prefix) {
+ var prev = result[result.length - 1];
+ var prevText = prefix || (prev && typeof prev === "string" ? prev : "");
+ if (prev && !prevText) {
+ throw new TypeError("Must have text between two parameters, missing text after \"".concat(prev.name, "\""));
+ }
+ if (!prevText || isSafe(prevText))
+ return "[^".concat(escapeString(delimiter), "]+?");
+ return "(?:(?!".concat(escapeString(prevText), ")[^").concat(escapeString(delimiter), "])+?");
+ };
+ while (i < tokens.length) {
+ var char = tryConsume("CHAR");
+ var name = tryConsume("NAME");
+ var pattern = tryConsume("PATTERN");
+ if (name || pattern) {
+ var prefix = char || "";
+ if (prefixes.indexOf(prefix) === -1) {
+ path += prefix;
+ prefix = "";
+ }
+ if (path) {
+ result.push(path);
+ path = "";
+ }
+ result.push({
+ name: name || key++,
+ prefix: prefix,
+ suffix: "",
+ pattern: pattern || safePattern(prefix),
+ modifier: tryConsume("MODIFIER") || "",
+ });
+ continue;
+ }
+ var value = char || tryConsume("ESCAPED_CHAR");
+ if (value) {
+ path += value;
+ continue;
+ }
+ if (path) {
+ result.push(path);
+ path = "";
+ }
+ var open = tryConsume("OPEN");
+ if (open) {
+ var prefix = consumeText();
+ var name_1 = tryConsume("NAME") || "";
+ var pattern_1 = tryConsume("PATTERN") || "";
+ var suffix = consumeText();
+ mustConsume("CLOSE");
+ result.push({
+ name: name_1 || (pattern_1 ? key++ : ""),
+ pattern: name_1 && !pattern_1 ? safePattern(prefix) : pattern_1,
+ prefix: prefix,
+ suffix: suffix,
+ modifier: tryConsume("MODIFIER") || "",
+ });
+ continue;
+ }
+ mustConsume("END");
+ }
+ return result;
+}
+exports.parse = parse;
+/**
+ * Compile a string to a template function for the path.
+ */
+function compile(str, options) {
+ return tokensToFunction(parse(str, options), options);
+}
+exports.compile = compile;
+/**
+ * Expose a method for transforming tokens into the path function.
+ */
+function tokensToFunction(tokens, options) {
+ if (options === void 0) { options = {}; }
+ var reFlags = flags(options);
+ var _a = options.encode, encode = _a === void 0 ? function (x) { return x; } : _a, _b = options.validate, validate = _b === void 0 ? true : _b;
+ // Compile all the tokens into regexps.
+ var matches = tokens.map(function (token) {
+ if (typeof token === "object") {
+ return new RegExp("^(?:".concat(token.pattern, ")$"), reFlags);
+ }
+ });
+ return function (data) {
+ var path = "";
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+ if (typeof token === "string") {
+ path += token;
+ continue;
+ }
+ var value = data ? data[token.name] : undefined;
+ var optional = token.modifier === "?" || token.modifier === "*";
+ var repeat = token.modifier === "*" || token.modifier === "+";
+ if (Array.isArray(value)) {
+ if (!repeat) {
+ throw new TypeError("Expected \"".concat(token.name, "\" to not repeat, but got an array"));
+ }
+ if (value.length === 0) {
+ if (optional)
+ continue;
+ throw new TypeError("Expected \"".concat(token.name, "\" to not be empty"));
+ }
+ for (var j = 0; j < value.length; j++) {
+ var segment = encode(value[j], token);
+ if (validate && !matches[i].test(segment)) {
+ throw new TypeError("Expected all \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
+ }
+ path += token.prefix + segment + token.suffix;
+ }
+ continue;
+ }
+ if (typeof value === "string" || typeof value === "number") {
+ var segment = encode(String(value), token);
+ if (validate && !matches[i].test(segment)) {
+ throw new TypeError("Expected \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
+ }
+ path += token.prefix + segment + token.suffix;
+ continue;
+ }
+ if (optional)
+ continue;
+ var typeOfMessage = repeat ? "an array" : "a string";
+ throw new TypeError("Expected \"".concat(token.name, "\" to be ").concat(typeOfMessage));
+ }
+ return path;
+ };
+}
+exports.tokensToFunction = tokensToFunction;
+/**
+ * Create path match function from `path-to-regexp` spec.
+ */
+function match(str, options) {
+ var keys = [];
+ var re = pathToRegexp(str, keys, options);
+ return regexpToFunction(re, keys, options);
+}
+exports.match = match;
+/**
+ * Create a path match function from `path-to-regexp` output.
+ */
+function regexpToFunction(re, keys, options) {
+ if (options === void 0) { options = {}; }
+ var _a = options.decode, decode = _a === void 0 ? function (x) { return x; } : _a;
+ return function (pathname) {
+ var m = re.exec(pathname);
+ if (!m)
+ return false;
+ var path = m[0], index = m.index;
+ var params = Object.create(null);
+ var _loop_1 = function (i) {
+ if (m[i] === undefined)
+ return "continue";
+ var key = keys[i - 1];
+ if (key.modifier === "*" || key.modifier === "+") {
+ params[key.name] = m[i].split(key.prefix + key.suffix).map(function (value) {
+ return decode(value, key);
+ });
+ }
+ else {
+ params[key.name] = decode(m[i], key);
+ }
+ };
+ for (var i = 1; i < m.length; i++) {
+ _loop_1(i);
+ }
+ return { path: path, index: index, params: params };
+ };
+}
+exports.regexpToFunction = regexpToFunction;
+/**
+ * Escape a regular expression string.
+ */
+function escapeString(str) {
+ return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
+}
+/**
+ * Get the flags for a regexp from the options.
+ */
+function flags(options) {
+ return options && options.sensitive ? "" : "i";
+}
+/**
+ * Pull out keys from a regexp.
+ */
+function regexpToRegexp(path, keys) {
+ if (!keys)
+ return path;
+ var groupsRegex = /\((?:\?<(.*?)>)?(?!\?)/g;
+ var index = 0;
+ var execResult = groupsRegex.exec(path.source);
+ while (execResult) {
+ keys.push({
+ // Use parenthesized substring match if available, index otherwise
+ name: execResult[1] || index++,
+ prefix: "",
+ suffix: "",
+ modifier: "",
+ pattern: "",
+ });
+ execResult = groupsRegex.exec(path.source);
+ }
+ return path;
+}
+/**
+ * Transform an array into a regexp.
+ */
+function arrayToRegexp(paths, keys, options) {
+ var parts = paths.map(function (path) { return pathToRegexp(path, keys, options).source; });
+ return new RegExp("(?:".concat(parts.join("|"), ")"), flags(options));
+}
+/**
+ * Create a path regexp from string input.
+ */
+function stringToRegexp(path, keys, options) {
+ return tokensToRegexp(parse(path, options), keys, options);
+}
+/**
+ * Expose a function for taking tokens and returning a RegExp.
+ */
+function tokensToRegexp(tokens, keys, options) {
+ if (options === void 0) { options = {}; }
+ var _a = options.strict, strict = _a === void 0 ? false : _a, _b = options.start, start = _b === void 0 ? true : _b, _c = options.end, end = _c === void 0 ? true : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d, _e = options.delimiter, delimiter = _e === void 0 ? "/#?" : _e, _f = options.endsWith, endsWith = _f === void 0 ? "" : _f;
+ var endsWithRe = "[".concat(escapeString(endsWith), "]|$");
+ var delimiterRe = "[".concat(escapeString(delimiter), "]");
+ var route = start ? "^" : "";
+ // Iterate over the tokens and create our regexp string.
+ for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {
+ var token = tokens_1[_i];
+ if (typeof token === "string") {
+ route += escapeString(encode(token));
+ }
+ else {
+ var prefix = escapeString(encode(token.prefix));
+ var suffix = escapeString(encode(token.suffix));
+ if (token.pattern) {
+ if (keys)
+ keys.push(token);
+ if (prefix || suffix) {
+ if (token.modifier === "+" || token.modifier === "*") {
+ var mod = token.modifier === "*" ? "?" : "";
+ route += "(?:".concat(prefix, "((?:").concat(token.pattern, ")(?:").concat(suffix).concat(prefix, "(?:").concat(token.pattern, "))*)").concat(suffix, ")").concat(mod);
+ }
+ else {
+ route += "(?:".concat(prefix, "(").concat(token.pattern, ")").concat(suffix, ")").concat(token.modifier);
+ }
+ }
+ else {
+ if (token.modifier === "+" || token.modifier === "*") {
+ throw new TypeError("Can not repeat \"".concat(token.name, "\" without a prefix and suffix"));
+ }
+ route += "(".concat(token.pattern, ")").concat(token.modifier);
+ }
+ }
+ else {
+ route += "(?:".concat(prefix).concat(suffix, ")").concat(token.modifier);
+ }
+ }
+ }
+ if (end) {
+ if (!strict)
+ route += "".concat(delimiterRe, "?");
+ route += !options.endsWith ? "$" : "(?=".concat(endsWithRe, ")");
+ }
+ else {
+ var endToken = tokens[tokens.length - 1];
+ var isEndDelimited = typeof endToken === "string"
+ ? delimiterRe.indexOf(endToken[endToken.length - 1]) > -1
+ : endToken === undefined;
+ if (!strict) {
+ route += "(?:".concat(delimiterRe, "(?=").concat(endsWithRe, "))?");
+ }
+ if (!isEndDelimited) {
+ route += "(?=".concat(delimiterRe, "|").concat(endsWithRe, ")");
+ }
+ }
+ return new RegExp(route, flags(options));
+}
+exports.tokensToRegexp = tokensToRegexp;
+/**
+ * Normalize the given path string, returning a regular expression.
+ *
+ * An empty array can be passed in for the keys, which will hold the
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
+ */
+function pathToRegexp(path, keys, options) {
+ if (path instanceof RegExp)
+ return regexpToRegexp(path, keys);
+ if (Array.isArray(path))
+ return arrayToRegexp(path, keys, options);
+ return stringToRegexp(path, keys, options);
+}
+exports.pathToRegexp = pathToRegexp;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/node_modules/path-to-regexp/dist/index.js.map b/node_modules/path-to-regexp/dist/index.js.map
new file mode 100644
index 0000000..5e3dc66
--- /dev/null
+++ b/node_modules/path-to-regexp/dist/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAiBA;;GAEG;AACH,SAAS,KAAK,CAAC,GAAW;IACxB,IAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE;QACrB,IAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE;YAChD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7D,SAAS;SACV;QAED,IAAI,IAAI,KAAK,IAAI,EAAE;YACjB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACnE,SAAS;SACV;QAED,IAAI,IAAI,KAAK,GAAG,EAAE;YAChB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACzD,SAAS;SACV;QAED,IAAI,IAAI,KAAK,GAAG,EAAE;YAChB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC1D,SAAS;SACV;QAED,IAAI,IAAI,KAAK,GAAG,EAAE;YAChB,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEd,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE;gBACrB,IAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAE/B;gBACE,QAAQ;gBACR,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC;oBAC1B,QAAQ;oBACR,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC;oBAC1B,QAAQ;oBACR,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,GAAG,CAAC;oBAC3B,MAAM;oBACN,IAAI,KAAK,EAAE,EACX;oBACA,IAAI,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;oBACjB,SAAS;iBACV;gBAED,MAAM;aACP;YAED,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,SAAS,CAAC,oCAA6B,CAAC,CAAE,CAAC,CAAC;YAEjE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,CAAC,GAAG,CAAC,CAAC;YACN,SAAS;SACV;QAED,IAAI,IAAI,KAAK,GAAG,EAAE;YAChB,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,IAAI,OAAO,GAAG,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEd,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;gBAClB,MAAM,IAAI,SAAS,CAAC,6CAAoC,CAAC,CAAE,CAAC,CAAC;aAC9D;YAED,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE;gBACrB,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;oBACnB,OAAO,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC/B,SAAS;iBACV;gBAED,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;oBAClB,KAAK,EAAE,CAAC;oBACR,IAAI,KAAK,KAAK,CAAC,EAAE;wBACf,CAAC,EAAE,CAAC;wBACJ,MAAM;qBACP;iBACF;qBAAM,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;oBACzB,KAAK,EAAE,CAAC;oBACR,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE;wBACtB,MAAM,IAAI,SAAS,CAAC,8CAAuC,CAAC,CAAE,CAAC,CAAC;qBACjE;iBACF;gBAED,OAAO,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;aACrB;YAED,IAAI,KAAK;gBAAE,MAAM,IAAI,SAAS,CAAC,gCAAyB,CAAC,CAAE,CAAC,CAAC;YAC7D,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,SAAS,CAAC,6BAAsB,CAAC,CAAE,CAAC,CAAC;YAE7D,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YAC3D,CAAC,GAAG,CAAC,CAAC;YACN,SAAS;SACV;QAED,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;KAC1D;IAED,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAElD,OAAO,MAAM,CAAC;AAChB,CAAC;AAaD;;GAEG;AACH,SAAgB,KAAK,CAAC,GAAW,EAAE,OAA0B;IAA1B,wBAAA,EAAA,YAA0B;IAC3D,IAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,IAAA,KAAuC,OAAO,SAA/B,EAAf,QAAQ,mBAAG,IAAI,KAAA,EAAE,KAAsB,OAAO,UAAZ,EAAjB,SAAS,mBAAG,KAAK,KAAA,CAAa;IACvD,IAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,IAAI,IAAI,GAAG,EAAE,CAAC;IAEd,IAAM,UAAU,GAAG,UAAC,IAAsB;QACxC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;IAC7E,CAAC,CAAC;IAEF,IAAM,WAAW,GAAG,UAAC,IAAsB;QACzC,IAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAChC,IAAA,KAA4B,MAAM,CAAC,CAAC,CAAC,EAA7B,QAAQ,UAAA,EAAE,KAAK,WAAc,CAAC;QAC5C,MAAM,IAAI,SAAS,CAAC,qBAAc,QAAQ,iBAAO,KAAK,wBAAc,IAAI,CAAE,CAAC,CAAC;IAC9E,CAAC,CAAC;IAEF,IAAM,WAAW,GAAG;QAClB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,KAAyB,CAAC;QAC9B,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,cAAc,CAAC,CAAC,EAAE;YACjE,MAAM,IAAI,KAAK,CAAC;SACjB;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,IAAM,MAAM,GAAG,UAAC,KAAa;QAC3B,KAAmB,UAAS,EAAT,uBAAS,EAAT,uBAAS,EAAT,IAAS;YAAvB,IAAM,IAAI,kBAAA;YAAe,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;SAAA;QACxE,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,IAAM,WAAW,GAAG,UAAC,MAAc;QACjC,IAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACvC,IAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAE1E,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE;YACrB,MAAM,IAAI,SAAS,CACjB,sEAA+D,IAAY,CAAC,IAAI,OAAG,CACpF,CAAC;SACH;QAED,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC;YAAE,OAAO,YAAK,YAAY,CAAC,SAAS,CAAC,QAAK,CAAC;QAC5E,OAAO,gBAAS,YAAY,CAAC,QAAQ,CAAC,gBAAM,YAAY,CAAC,SAAS,CAAC,SAAM,CAAC;IAC5E,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE;QACxB,IAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAChC,IAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAChC,IAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QAEtC,IAAI,IAAI,IAAI,OAAO,EAAE;YACnB,IAAI,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YAExB,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;gBACnC,IAAI,IAAI,MAAM,CAAC;gBACf,MAAM,GAAG,EAAE,CAAC;aACb;YAED,IAAI,IAAI,EAAE;gBACR,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClB,IAAI,GAAG,EAAE,CAAC;aACX;YAED,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,IAAI,IAAI,GAAG,EAAE;gBACnB,MAAM,QAAA;gBACN,MAAM,EAAE,EAAE;gBACV,OAAO,EAAE,OAAO,IAAI,WAAW,CAAC,MAAM,CAAC;gBACvC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE;aACvC,CAAC,CAAC;YACH,SAAS;SACV;QAED,IAAM,KAAK,GAAG,IAAI,IAAI,UAAU,CAAC,cAAc,CAAC,CAAC;QACjD,IAAI,KAAK,EAAE;YACT,IAAI,IAAI,KAAK,CAAC;YACd,SAAS;SACV;QAED,IAAI,IAAI,EAAE;YACR,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,IAAI,GAAG,EAAE,CAAC;SACX;QAED,IAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,IAAI,EAAE;YACR,IAAM,MAAM,GAAG,WAAW,EAAE,CAAC;YAC7B,IAAM,MAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACtC,IAAM,SAAO,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAM,MAAM,GAAG,WAAW,EAAE,CAAC;YAE7B,WAAW,CAAC,OAAO,CAAC,CAAC;YAErB,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,MAAI,IAAI,CAAC,SAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpC,OAAO,EAAE,MAAI,IAAI,CAAC,SAAO,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAO;gBACzD,MAAM,QAAA;gBACN,MAAM,QAAA;gBACN,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE;aACvC,CAAC,CAAC;YACH,SAAS;SACV;QAED,WAAW,CAAC,KAAK,CAAC,CAAC;KACpB;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AA7GD,sBA6GC;AAiBD;;GAEG;AACH,SAAgB,OAAO,CACrB,GAAW,EACX,OAAgD;IAEhD,OAAO,gBAAgB,CAAI,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;AAC3D,CAAC;AALD,0BAKC;AAID;;GAEG;AACH,SAAgB,gBAAgB,CAC9B,MAAe,EACf,OAAqC;IAArC,wBAAA,EAAA,YAAqC;IAErC,IAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IACvB,IAAA,KAA+C,OAAO,OAA7B,EAAzB,MAAM,mBAAG,UAAC,CAAS,IAAK,OAAA,CAAC,EAAD,CAAC,KAAA,EAAE,KAAoB,OAAO,SAAZ,EAAf,QAAQ,mBAAG,IAAI,KAAA,CAAa;IAE/D,uCAAuC;IACvC,IAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,UAAC,KAAK;QAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC7B,OAAO,IAAI,MAAM,CAAC,cAAO,KAAK,CAAC,OAAO,OAAI,EAAE,OAAO,CAAC,CAAC;SACtD;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,UAAC,IAA4C;QAClD,IAAI,IAAI,GAAG,EAAE,CAAC;QAEd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACtC,IAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAExB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBAC7B,IAAI,IAAI,KAAK,CAAC;gBACd,SAAS;aACV;YAED,IAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAClD,IAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC;YAClE,IAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC;YAEhE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBACxB,IAAI,CAAC,MAAM,EAAE;oBACX,MAAM,IAAI,SAAS,CACjB,qBAAa,KAAK,CAAC,IAAI,uCAAmC,CAC3D,CAAC;iBACH;gBAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;oBACtB,IAAI,QAAQ;wBAAE,SAAS;oBAEvB,MAAM,IAAI,SAAS,CAAC,qBAAa,KAAK,CAAC,IAAI,uBAAmB,CAAC,CAAC;iBACjE;gBAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBACrC,IAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;oBAExC,IAAI,QAAQ,IAAI,CAAE,OAAO,CAAC,CAAC,CAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;wBACrD,MAAM,IAAI,SAAS,CACjB,yBAAiB,KAAK,CAAC,IAAI,2BAAe,KAAK,CAAC,OAAO,2BAAe,OAAO,OAAG,CACjF,CAAC;qBACH;oBAED,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC;iBAC/C;gBAED,SAAS;aACV;YAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBAC1D,IAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;gBAE7C,IAAI,QAAQ,IAAI,CAAE,OAAO,CAAC,CAAC,CAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;oBACrD,MAAM,IAAI,SAAS,CACjB,qBAAa,KAAK,CAAC,IAAI,2BAAe,KAAK,CAAC,OAAO,2BAAe,OAAO,OAAG,CAC7E,CAAC;iBACH;gBAED,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC;gBAC9C,SAAS;aACV;YAED,IAAI,QAAQ;gBAAE,SAAS;YAEvB,IAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;YACvD,MAAM,IAAI,SAAS,CAAC,qBAAa,KAAK,CAAC,IAAI,sBAAW,aAAa,CAAE,CAAC,CAAC;SACxE;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC;AA9ED,4CA8EC;AA8BD;;GAEG;AACH,SAAgB,KAAK,CACnB,GAAS,EACT,OAAwE;IAExE,IAAM,IAAI,GAAU,EAAE,CAAC;IACvB,IAAM,EAAE,GAAG,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,gBAAgB,CAAI,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC;AAPD,sBAOC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAC9B,EAAU,EACV,IAAW,EACX,OAAqC;IAArC,wBAAA,EAAA,YAAqC;IAE7B,IAAA,KAA8B,OAAO,OAAZ,EAAzB,MAAM,mBAAG,UAAC,CAAS,IAAK,OAAA,CAAC,EAAD,CAAC,KAAA,CAAa;IAE9C,OAAO,UAAU,QAAgB;QAC/B,IAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAEb,IAAG,IAAI,GAAY,CAAC,GAAb,EAAE,KAAK,GAAK,CAAC,MAAN,CAAO;QAC7B,IAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gCAE1B,CAAC;YACR,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS;kCAAW;YAEjC,IAAM,GAAG,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAExB,IAAI,GAAG,CAAC,QAAQ,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,KAAK,GAAG,EAAE;gBAChD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,UAAC,KAAK;oBAC/D,OAAO,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC5B,CAAC,CAAC,CAAC;aACJ;iBAAM;gBACL,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;aACtC;;QAXH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;oBAAxB,CAAC;SAYT;QAED,OAAO,EAAE,IAAI,MAAA,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,EAAE,CAAC;IACjC,CAAC,CAAC;AACJ,CAAC;AA9BD,4CA8BC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG,CAAC,OAAO,CAAC,2BAA2B,EAAE,MAAM,CAAC,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,SAAS,KAAK,CAAC,OAAiC;IAC9C,OAAO,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AACjD,CAAC;AAkBD;;GAEG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,IAAY;IAChD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,IAAM,WAAW,GAAG,yBAAyB,CAAC;IAE9C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C,OAAO,UAAU,EAAE;QACjB,IAAI,CAAC,IAAI,CAAC;YACR,kEAAkE;YAClE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE;YAC9B,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,EAAE;YACZ,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QACH,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;KAC5C;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CACpB,KAA6B,EAC7B,IAAY,EACZ,OAA8C;IAE9C,IAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,UAAC,IAAI,IAAK,OAAA,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,MAAM,EAAxC,CAAwC,CAAC,CAAC;IAC5E,OAAO,IAAI,MAAM,CAAC,aAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACrB,IAAY,EACZ,IAAY,EACZ,OAA8C;IAE9C,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC7D,CAAC;AAiCD;;GAEG;AACH,SAAgB,cAAc,CAC5B,MAAe,EACf,IAAY,EACZ,OAAmC;IAAnC,wBAAA,EAAA,YAAmC;IAGjC,IAAA,KAME,OAAO,OANK,EAAd,MAAM,mBAAG,KAAK,KAAA,EACd,KAKE,OAAO,MALG,EAAZ,KAAK,mBAAG,IAAI,KAAA,EACZ,KAIE,OAAO,IAJC,EAAV,GAAG,mBAAG,IAAI,KAAA,EACV,KAGE,OAAO,OAHgB,EAAzB,MAAM,mBAAG,UAAC,CAAS,IAAK,OAAA,CAAC,EAAD,CAAC,KAAA,EACzB,KAEE,OAAO,UAFQ,EAAjB,SAAS,mBAAG,KAAK,KAAA,EACjB,KACE,OAAO,SADI,EAAb,QAAQ,mBAAG,EAAE,KAAA,CACH;IACZ,IAAM,UAAU,GAAG,WAAI,YAAY,CAAC,QAAQ,CAAC,QAAK,CAAC;IACnD,IAAM,WAAW,GAAG,WAAI,YAAY,CAAC,SAAS,CAAC,MAAG,CAAC;IACnD,IAAI,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7B,wDAAwD;IACxD,KAAoB,UAAM,EAAN,iBAAM,EAAN,oBAAM,EAAN,IAAM,EAAE;QAAvB,IAAM,KAAK,eAAA;QACd,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC7B,KAAK,IAAI,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;SACtC;aAAM;YACL,IAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;YAClD,IAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;YAElD,IAAI,KAAK,CAAC,OAAO,EAAE;gBACjB,IAAI,IAAI;oBAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAE3B,IAAI,MAAM,IAAI,MAAM,EAAE;oBACpB,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,EAAE;wBACpD,IAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC9C,KAAK,IAAI,aAAM,MAAM,iBAAO,KAAK,CAAC,OAAO,iBAAO,MAAM,SAAG,MAAM,gBAAM,KAAK,CAAC,OAAO,iBAAO,MAAM,cAAI,GAAG,CAAE,CAAC;qBAC1G;yBAAM;wBACL,KAAK,IAAI,aAAM,MAAM,cAAI,KAAK,CAAC,OAAO,cAAI,MAAM,cAAI,KAAK,CAAC,QAAQ,CAAE,CAAC;qBACtE;iBACF;qBAAM;oBACL,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,EAAE;wBACpD,MAAM,IAAI,SAAS,CACjB,2BAAmB,KAAK,CAAC,IAAI,mCAA+B,CAC7D,CAAC;qBACH;oBAED,KAAK,IAAI,WAAI,KAAK,CAAC,OAAO,cAAI,KAAK,CAAC,QAAQ,CAAE,CAAC;iBAChD;aACF;iBAAM;gBACL,KAAK,IAAI,aAAM,MAAM,SAAG,MAAM,cAAI,KAAK,CAAC,QAAQ,CAAE,CAAC;aACpD;SACF;KACF;IAED,IAAI,GAAG,EAAE;QACP,IAAI,CAAC,MAAM;YAAE,KAAK,IAAI,UAAG,WAAW,MAAG,CAAC;QAExC,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,aAAM,UAAU,MAAG,CAAC;KACxD;SAAM;QACL,IAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC3C,IAAM,cAAc,GAClB,OAAO,QAAQ,KAAK,QAAQ;YAC1B,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACzD,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC;QAE7B,IAAI,CAAC,MAAM,EAAE;YACX,KAAK,IAAI,aAAM,WAAW,gBAAM,UAAU,QAAK,CAAC;SACjD;QAED,IAAI,CAAC,cAAc,EAAE;YACnB,KAAK,IAAI,aAAM,WAAW,cAAI,UAAU,MAAG,CAAC;SAC7C;KACF;IAED,OAAO,IAAI,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3C,CAAC;AAvED,wCAuEC;AAOD;;;;;;GAMG;AACH,SAAgB,YAAY,CAC1B,IAAU,EACV,IAAY,EACZ,OAA8C;IAE9C,IAAI,IAAI,YAAY,MAAM;QAAE,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9D,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACnE,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC;AARD,oCAQC","sourcesContent":["/**\n * Tokenizer results.\n */\ninterface LexToken {\n type:\n | \"OPEN\"\n | \"CLOSE\"\n | \"PATTERN\"\n | \"NAME\"\n | \"CHAR\"\n | \"ESCAPED_CHAR\"\n | \"MODIFIER\"\n | \"END\";\n index: number;\n value: string;\n}\n\n/**\n * Tokenize input string.\n */\nfunction lexer(str: string): LexToken[] {\n const tokens: LexToken[] = [];\n let i = 0;\n\n while (i < str.length) {\n const char = str[i];\n\n if (char === \"*\" || char === \"+\" || char === \"?\") {\n tokens.push({ type: \"MODIFIER\", index: i, value: str[i++] });\n continue;\n }\n\n if (char === \"\\\\\") {\n tokens.push({ type: \"ESCAPED_CHAR\", index: i++, value: str[i++] });\n continue;\n }\n\n if (char === \"{\") {\n tokens.push({ type: \"OPEN\", index: i, value: str[i++] });\n continue;\n }\n\n if (char === \"}\") {\n tokens.push({ type: \"CLOSE\", index: i, value: str[i++] });\n continue;\n }\n\n if (char === \":\") {\n let name = \"\";\n let j = i + 1;\n\n while (j < str.length) {\n const code = str.charCodeAt(j);\n\n if (\n // `0-9`\n (code >= 48 && code <= 57) ||\n // `A-Z`\n (code >= 65 && code <= 90) ||\n // `a-z`\n (code >= 97 && code <= 122) ||\n // `_`\n code === 95\n ) {\n name += str[j++];\n continue;\n }\n\n break;\n }\n\n if (!name) throw new TypeError(`Missing parameter name at ${i}`);\n\n tokens.push({ type: \"NAME\", index: i, value: name });\n i = j;\n continue;\n }\n\n if (char === \"(\") {\n let count = 1;\n let pattern = \"\";\n let j = i + 1;\n\n if (str[j] === \"?\") {\n throw new TypeError(`Pattern cannot start with \"?\" at ${j}`);\n }\n\n while (j < str.length) {\n if (str[j] === \"\\\\\") {\n pattern += str[j++] + str[j++];\n continue;\n }\n\n if (str[j] === \")\") {\n count--;\n if (count === 0) {\n j++;\n break;\n }\n } else if (str[j] === \"(\") {\n count++;\n if (str[j + 1] !== \"?\") {\n throw new TypeError(`Capturing groups are not allowed at ${j}`);\n }\n }\n\n pattern += str[j++];\n }\n\n if (count) throw new TypeError(`Unbalanced pattern at ${i}`);\n if (!pattern) throw new TypeError(`Missing pattern at ${i}`);\n\n tokens.push({ type: \"PATTERN\", index: i, value: pattern });\n i = j;\n continue;\n }\n\n tokens.push({ type: \"CHAR\", index: i, value: str[i++] });\n }\n\n tokens.push({ type: \"END\", index: i, value: \"\" });\n\n return tokens;\n}\n\nexport interface ParseOptions {\n /**\n * Set the default delimiter for repeat parameters. (default: `'/'`)\n */\n delimiter?: string;\n /**\n * List of characters to automatically consider prefixes when parsing.\n */\n prefixes?: string;\n}\n\n/**\n * Parse a string for the raw tokens.\n */\nexport function parse(str: string, options: ParseOptions = {}): Token[] {\n const tokens = lexer(str);\n const { prefixes = \"./\", delimiter = \"/#?\" } = options;\n const result: Token[] = [];\n let key = 0;\n let i = 0;\n let path = \"\";\n\n const tryConsume = (type: LexToken[\"type\"]): string | undefined => {\n if (i < tokens.length && tokens[i].type === type) return tokens[i++].value;\n };\n\n const mustConsume = (type: LexToken[\"type\"]): string => {\n const value = tryConsume(type);\n if (value !== undefined) return value;\n const { type: nextType, index } = tokens[i];\n throw new TypeError(`Unexpected ${nextType} at ${index}, expected ${type}`);\n };\n\n const consumeText = (): string => {\n let result = \"\";\n let value: string | undefined;\n while ((value = tryConsume(\"CHAR\") || tryConsume(\"ESCAPED_CHAR\"))) {\n result += value;\n }\n return result;\n };\n\n const isSafe = (value: string): boolean => {\n for (const char of delimiter) if (value.indexOf(char) > -1) return true;\n return false;\n };\n\n const safePattern = (prefix: string) => {\n const prev = result[result.length - 1];\n const prevText = prefix || (prev && typeof prev === \"string\" ? prev : \"\");\n\n if (prev && !prevText) {\n throw new TypeError(\n `Must have text between two parameters, missing text after \"${(prev as Key).name}\"`,\n );\n }\n\n if (!prevText || isSafe(prevText)) return `[^${escapeString(delimiter)}]+?`;\n return `(?:(?!${escapeString(prevText)})[^${escapeString(delimiter)}])+?`;\n };\n\n while (i < tokens.length) {\n const char = tryConsume(\"CHAR\");\n const name = tryConsume(\"NAME\");\n const pattern = tryConsume(\"PATTERN\");\n\n if (name || pattern) {\n let prefix = char || \"\";\n\n if (prefixes.indexOf(prefix) === -1) {\n path += prefix;\n prefix = \"\";\n }\n\n if (path) {\n result.push(path);\n path = \"\";\n }\n\n result.push({\n name: name || key++,\n prefix,\n suffix: \"\",\n pattern: pattern || safePattern(prefix),\n modifier: tryConsume(\"MODIFIER\") || \"\",\n });\n continue;\n }\n\n const value = char || tryConsume(\"ESCAPED_CHAR\");\n if (value) {\n path += value;\n continue;\n }\n\n if (path) {\n result.push(path);\n path = \"\";\n }\n\n const open = tryConsume(\"OPEN\");\n if (open) {\n const prefix = consumeText();\n const name = tryConsume(\"NAME\") || \"\";\n const pattern = tryConsume(\"PATTERN\") || \"\";\n const suffix = consumeText();\n\n mustConsume(\"CLOSE\");\n\n result.push({\n name: name || (pattern ? key++ : \"\"),\n pattern: name && !pattern ? safePattern(prefix) : pattern,\n prefix,\n suffix,\n modifier: tryConsume(\"MODIFIER\") || \"\",\n });\n continue;\n }\n\n mustConsume(\"END\");\n }\n\n return result;\n}\n\nexport interface TokensToFunctionOptions {\n /**\n * When `true` the regexp will be case sensitive. (default: `false`)\n */\n sensitive?: boolean;\n /**\n * Function for encoding input strings for output.\n */\n encode?: (value: string, token: Key) => string;\n /**\n * When `false` the function can produce an invalid (unmatched) path. (default: `true`)\n */\n validate?: boolean;\n}\n\n/**\n * Compile a string to a template function for the path.\n */\nexport function compile(\n str: string,\n options?: ParseOptions & TokensToFunctionOptions,\n) {\n return tokensToFunction
(parse(str, options), options);\n}\n\nexport type PathFunction
= (data?: P) => string;\n\n/**\n * Expose a method for transforming tokens into the path function.\n */\nexport function tokensToFunction
(\n tokens: Token[],\n options: TokensToFunctionOptions = {},\n): PathFunction
{\n const reFlags = flags(options);\n const { encode = (x: string) => x, validate = true } = options;\n\n // Compile all the tokens into regexps.\n const matches = tokens.map((token) => {\n if (typeof token === \"object\") {\n return new RegExp(`^(?:${token.pattern})$`, reFlags);\n }\n });\n\n return (data: Record | null | undefined) => {\n let path = \"\";\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n\n if (typeof token === \"string\") {\n path += token;\n continue;\n }\n\n const value = data ? data[token.name] : undefined;\n const optional = token.modifier === \"?\" || token.modifier === \"*\";\n const repeat = token.modifier === \"*\" || token.modifier === \"+\";\n\n if (Array.isArray(value)) {\n if (!repeat) {\n throw new TypeError(\n `Expected \"${token.name}\" to not repeat, but got an array`,\n );\n }\n\n if (value.length === 0) {\n if (optional) continue;\n\n throw new TypeError(`Expected \"${token.name}\" to not be empty`);\n }\n\n for (let j = 0; j < value.length; j++) {\n const segment = encode(value[j], token);\n\n if (validate && !(matches[i] as RegExp).test(segment)) {\n throw new TypeError(\n `Expected all \"${token.name}\" to match \"${token.pattern}\", but got \"${segment}\"`,\n );\n }\n\n path += token.prefix + segment + token.suffix;\n }\n\n continue;\n }\n\n if (typeof value === \"string\" || typeof value === \"number\") {\n const segment = encode(String(value), token);\n\n if (validate && !(matches[i] as RegExp).test(segment)) {\n throw new TypeError(\n `Expected \"${token.name}\" to match \"${token.pattern}\", but got \"${segment}\"`,\n );\n }\n\n path += token.prefix + segment + token.suffix;\n continue;\n }\n\n if (optional) continue;\n\n const typeOfMessage = repeat ? \"an array\" : \"a string\";\n throw new TypeError(`Expected \"${token.name}\" to be ${typeOfMessage}`);\n }\n\n return path;\n };\n}\n\nexport interface RegexpToFunctionOptions {\n /**\n * Function for decoding strings for params.\n */\n decode?: (value: string, token: Key) => string;\n}\n\n/**\n * A match result contains data about the path match.\n */\nexport interface MatchResult {\n path: string;\n index: number;\n params: P;\n}\n\n/**\n * A match is either `false` (no match) or a match result.\n */\nexport type Match
= false | MatchResult
;\n\n/**\n * The match function takes a string and returns whether it matched the path.\n */\nexport type MatchFunction
= (\n path: string,\n) => Match
;\n\n/**\n * Create path match function from `path-to-regexp` spec.\n */\nexport function match
(\n str: Path,\n options?: ParseOptions & TokensToRegexpOptions & RegexpToFunctionOptions,\n) {\n const keys: Key[] = [];\n const re = pathToRegexp(str, keys, options);\n return regexpToFunction
(re, keys, options);\n}\n\n/**\n * Create a path match function from `path-to-regexp` output.\n */\nexport function regexpToFunction
(\n re: RegExp,\n keys: Key[],\n options: RegexpToFunctionOptions = {},\n): MatchFunction
{\n const { decode = (x: string) => x } = options;\n\n return function (pathname: string) {\n const m = re.exec(pathname);\n if (!m) return false;\n\n const { 0: path, index } = m;\n const params = Object.create(null);\n\n for (let i = 1; i < m.length; i++) {\n if (m[i] === undefined) continue;\n\n const key = keys[i - 1];\n\n if (key.modifier === \"*\" || key.modifier === \"+\") {\n params[key.name] = m[i].split(key.prefix + key.suffix).map((value) => {\n return decode(value, key);\n });\n } else {\n params[key.name] = decode(m[i], key);\n }\n }\n\n return { path, index, params };\n };\n}\n\n/**\n * Escape a regular expression string.\n */\nfunction escapeString(str: string) {\n return str.replace(/([.+*?=^!:${}()[\\]|/\\\\])/g, \"\\\\$1\");\n}\n\n/**\n * Get the flags for a regexp from the options.\n */\nfunction flags(options?: { sensitive?: boolean }) {\n return options && options.sensitive ? \"\" : \"i\";\n}\n\n/**\n * Metadata about a key.\n */\nexport interface Key {\n name: string | number;\n prefix: string;\n suffix: string;\n pattern: string;\n modifier: string;\n}\n\n/**\n * A token is a string (nothing special) or key metadata (capture group).\n */\nexport type Token = string | Key;\n\n/**\n * Pull out keys from a regexp.\n */\nfunction regexpToRegexp(path: RegExp, keys?: Key[]): RegExp {\n if (!keys) return path;\n\n const groupsRegex = /\\((?:\\?<(.*?)>)?(?!\\?)/g;\n\n let index = 0;\n let execResult = groupsRegex.exec(path.source);\n while (execResult) {\n keys.push({\n // Use parenthesized substring match if available, index otherwise\n name: execResult[1] || index++,\n prefix: \"\",\n suffix: \"\",\n modifier: \"\",\n pattern: \"\",\n });\n execResult = groupsRegex.exec(path.source);\n }\n\n return path;\n}\n\n/**\n * Transform an array into a regexp.\n */\nfunction arrayToRegexp(\n paths: Array,\n keys?: Key[],\n options?: TokensToRegexpOptions & ParseOptions,\n): RegExp {\n const parts = paths.map((path) => pathToRegexp(path, keys, options).source);\n return new RegExp(`(?:${parts.join(\"|\")})`, flags(options));\n}\n\n/**\n * Create a path regexp from string input.\n */\nfunction stringToRegexp(\n path: string,\n keys?: Key[],\n options?: TokensToRegexpOptions & ParseOptions,\n) {\n return tokensToRegexp(parse(path, options), keys, options);\n}\n\nexport interface TokensToRegexpOptions {\n /**\n * When `true` the regexp will be case sensitive. (default: `false`)\n */\n sensitive?: boolean;\n /**\n * When `true` the regexp won't allow an optional trailing delimiter to match. (default: `false`)\n */\n strict?: boolean;\n /**\n * When `true` the regexp will match to the end of the string. (default: `true`)\n */\n end?: boolean;\n /**\n * When `true` the regexp will match from the beginning of the string. (default: `true`)\n */\n start?: boolean;\n /**\n * Sets the final character for non-ending optimistic matches. (default: `/`)\n */\n delimiter?: string;\n /**\n * List of characters that can also be \"end\" characters.\n */\n endsWith?: string;\n /**\n * Encode path tokens for use in the `RegExp`.\n */\n encode?: (value: string) => string;\n}\n\n/**\n * Expose a function for taking tokens and returning a RegExp.\n */\nexport function tokensToRegexp(\n tokens: Token[],\n keys?: Key[],\n options: TokensToRegexpOptions = {},\n) {\n const {\n strict = false,\n start = true,\n end = true,\n encode = (x: string) => x,\n delimiter = \"/#?\",\n endsWith = \"\",\n } = options;\n const endsWithRe = `[${escapeString(endsWith)}]|$`;\n const delimiterRe = `[${escapeString(delimiter)}]`;\n let route = start ? \"^\" : \"\";\n\n // Iterate over the tokens and create our regexp string.\n for (const token of tokens) {\n if (typeof token === \"string\") {\n route += escapeString(encode(token));\n } else {\n const prefix = escapeString(encode(token.prefix));\n const suffix = escapeString(encode(token.suffix));\n\n if (token.pattern) {\n if (keys) keys.push(token);\n\n if (prefix || suffix) {\n if (token.modifier === \"+\" || token.modifier === \"*\") {\n const mod = token.modifier === \"*\" ? \"?\" : \"\";\n route += `(?:${prefix}((?:${token.pattern})(?:${suffix}${prefix}(?:${token.pattern}))*)${suffix})${mod}`;\n } else {\n route += `(?:${prefix}(${token.pattern})${suffix})${token.modifier}`;\n }\n } else {\n if (token.modifier === \"+\" || token.modifier === \"*\") {\n throw new TypeError(\n `Can not repeat \"${token.name}\" without a prefix and suffix`,\n );\n }\n\n route += `(${token.pattern})${token.modifier}`;\n }\n } else {\n route += `(?:${prefix}${suffix})${token.modifier}`;\n }\n }\n }\n\n if (end) {\n if (!strict) route += `${delimiterRe}?`;\n\n route += !options.endsWith ? \"$\" : `(?=${endsWithRe})`;\n } else {\n const endToken = tokens[tokens.length - 1];\n const isEndDelimited =\n typeof endToken === \"string\"\n ? delimiterRe.indexOf(endToken[endToken.length - 1]) > -1\n : endToken === undefined;\n\n if (!strict) {\n route += `(?:${delimiterRe}(?=${endsWithRe}))?`;\n }\n\n if (!isEndDelimited) {\n route += `(?=${delimiterRe}|${endsWithRe})`;\n }\n }\n\n return new RegExp(route, flags(options));\n}\n\n/**\n * Supported `path-to-regexp` input types.\n */\nexport type Path = string | RegExp | Array;\n\n/**\n * Normalize the given path string, returning a regular expression.\n *\n * An empty array can be passed in for the keys, which will hold the\n * placeholder key descriptions. For example, using `/user/:id`, `keys` will\n * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.\n */\nexport function pathToRegexp(\n path: Path,\n keys?: Key[],\n options?: TokensToRegexpOptions & ParseOptions,\n) {\n if (path instanceof RegExp) return regexpToRegexp(path, keys);\n if (Array.isArray(path)) return arrayToRegexp(path, keys, options);\n return stringToRegexp(path, keys, options);\n}\n"]}
\ No newline at end of file
diff --git a/node_modules/path-to-regexp/package.json b/node_modules/path-to-regexp/package.json
new file mode 100644
index 0000000..aa7a4f6
--- /dev/null
+++ b/node_modules/path-to-regexp/package.json
@@ -0,0 +1,63 @@
+{
+ "name": "path-to-regexp",
+ "version": "6.3.0",
+ "description": "Express style path to RegExp utility",
+ "keywords": [
+ "express",
+ "regexp",
+ "route",
+ "routing"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/pillarjs/path-to-regexp.git"
+ },
+ "license": "MIT",
+ "sideEffects": false,
+ "main": "dist/index.js",
+ "module": "dist.es2015/index.js",
+ "typings": "dist/index.d.ts",
+ "files": [
+ "dist.es2015/",
+ "dist/"
+ ],
+ "scripts": {
+ "build": "ts-scripts build",
+ "format": "ts-scripts format",
+ "lint": "ts-scripts lint",
+ "prepare": "ts-scripts install && npm run build",
+ "size": "size-limit",
+ "specs": "ts-scripts specs",
+ "test": "ts-scripts test && npm run size"
+ },
+ "devDependencies": {
+ "@borderless/ts-scripts": "^0.15.0",
+ "@size-limit/preset-small-lib": "^11.1.2",
+ "@types/node": "^20.4.9",
+ "@types/semver": "^7.3.1",
+ "@vitest/coverage-v8": "^1.4.0",
+ "recheck": "^4.4.5",
+ "semver": "^7.3.5",
+ "size-limit": "^11.1.2",
+ "typescript": "^5.1.6"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "size-limit": [
+ {
+ "path": "dist.es2015/index.js",
+ "limit": "2.1 kB"
+ }
+ ],
+ "ts-scripts": {
+ "dist": [
+ "dist",
+ "dist.es2015"
+ ],
+ "project": [
+ "tsconfig.build.json",
+ "tsconfig.es2015.json"
+ ]
+ }
+}
diff --git a/node_modules/rawth/LICENSE b/node_modules/rawth/LICENSE
new file mode 100644
index 0000000..74e6791
--- /dev/null
+++ b/node_modules/rawth/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Gianluca Guarini
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/rawth/README.md b/node_modules/rawth/README.md
new file mode 100644
index 0000000..14cc311
--- /dev/null
+++ b/node_modules/rawth/README.md
@@ -0,0 +1,100 @@
+
+
+
+
+
+##### Pure functional isomorphic router based on streams. It works consistently on modern browsers and on node.
+
+---
+
+
+[![Build Status][ci-image]][ci-url]
+
+[![NPM version][npm-version-image]][npm-url]
+[![NPM downloads][npm-downloads-image]][npm-url]
+[![Code Quality][codeclimate-image]][codeclimate-url]
+[![Coverage Status][coverage-image]][coverage-url]
+![rawth size][lib-size]
+[![MIT License][license-image]][license-url]
+
+## Usage
+
+Any `rawth.route` function creates an [erre stream](https://github.com/GianlucaGuarini/erre) connected to the main router stream. These sub-streams will be activated only when their paths will match the current router path. For example:
+
+```js
+import route, { router } from 'rawth'
+
+route('/users/:user').on.value(({params}) => {
+ const {user} = params
+
+ console.log(`Hello dear ${user}`)
+})
+
+// you can dispatch router events at any time
+router.push('/users/gianluca')
+```
+
+The argument passed to the subscribed functions is an [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) object having `params` as additional property. The `params` array will contain all the matched [route parameters](https://github.com/pillarjs/path-to-regexp#parameters)
+
+```js
+import route, { router } from 'rawth'
+
+route('/:group/:user').on.value(({params}) => {
+ const {group, user} = params
+
+ console.log(`Hello dear ${user}, you are part of the ${group} group`)
+})
+
+// you can dispatch router events at any time
+router.push('/friends/gianluca')
+```
+
+### Unsubscribe streams
+
+If you want to unsubscribe to a specific route you need just to end the stream
+
+```js
+import route from 'rawth'
+
+const usersRouteStream = route('/users/:user')
+
+// subscribe to the stream as many times as you want
+usersRouteStream.on.value(({params}) => { /* */ })
+usersRouteStream.on.value(({params}) => { /* */ })
+usersRouteStream.on.value(({params}) => { /* */ })
+
+// end the stream
+usersRouteStream.end()
+```
+
+### Set the base path
+
+You can set the base path and override the router default options using the `configure` method
+
+```js
+import { configure } from 'rawth'
+
+configure({
+ base: 'https://example.com',
+ strict: true
+})
+
+```
+
+[ci-image]:https://github.com/GianlucaGuarini/rawth/actions/workflows/test.yml/badge.svg
+[ci-url]:https://github.com/GianlucaGuarini/rawth/actions/workflows/test.yml
+
+[license-image]:http://img.shields.io/badge/license-MIT-000000.svg?style=flat-square
+[license-url]:LICENSE
+
+[lib-size]:https://img.badgesize.io/https://unpkg.com/rawth/rawth.min.js?compression=gzip
+
+[npm-version-image]:http://img.shields.io/npm/v/rawth.svg?style=flat-square
+[npm-downloads-image]:http://img.shields.io/npm/dm/rawth.svg?style=flat-square
+[npm-url]:https://npmjs.org/package/rawth
+
+[coverage-image]:https://img.shields.io/coveralls/GianlucaGuarini/rawth/main.svg?style=flat-square
+[coverage-url]:https://coveralls.io/r/GianlucaGuarini/rawth?branch=main
+
+[codeclimate-image]:https://api.codeclimate.com/v1/badges/5a4b8cf4736254115cb3/maintainability
+[codeclimate-url]:https://codeclimate.com/github/GianlucaGuarini/rawth/maintainability
diff --git a/node_modules/rawth/index.cjs b/node_modules/rawth/index.cjs
new file mode 100644
index 0000000..ad394b1
--- /dev/null
+++ b/node_modules/rawth/index.cjs
@@ -0,0 +1,776 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.rawth = {}));
+})(this, (function (exports) { 'use strict';
+
+ /**
+ * Tokenize input string.
+ */
+ function lexer(str) {
+ var tokens = [];
+ var i = 0;
+ while (i < str.length) {
+ var char = str[i];
+ if (char === "*" || char === "+" || char === "?") {
+ tokens.push({ type: "MODIFIER", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === "\\") {
+ tokens.push({ type: "ESCAPED_CHAR", index: i++, value: str[i++] });
+ continue;
+ }
+ if (char === "{") {
+ tokens.push({ type: "OPEN", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === "}") {
+ tokens.push({ type: "CLOSE", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === ":") {
+ var name = "";
+ var j = i + 1;
+ while (j < str.length) {
+ var code = str.charCodeAt(j);
+ if (
+ // `0-9`
+ (code >= 48 && code <= 57) ||
+ // `A-Z`
+ (code >= 65 && code <= 90) ||
+ // `a-z`
+ (code >= 97 && code <= 122) ||
+ // `_`
+ code === 95) {
+ name += str[j++];
+ continue;
+ }
+ break;
+ }
+ if (!name)
+ throw new TypeError("Missing parameter name at ".concat(i));
+ tokens.push({ type: "NAME", index: i, value: name });
+ i = j;
+ continue;
+ }
+ if (char === "(") {
+ var count = 1;
+ var pattern = "";
+ var j = i + 1;
+ if (str[j] === "?") {
+ throw new TypeError("Pattern cannot start with \"?\" at ".concat(j));
+ }
+ while (j < str.length) {
+ if (str[j] === "\\") {
+ pattern += str[j++] + str[j++];
+ continue;
+ }
+ if (str[j] === ")") {
+ count--;
+ if (count === 0) {
+ j++;
+ break;
+ }
+ }
+ else if (str[j] === "(") {
+ count++;
+ if (str[j + 1] !== "?") {
+ throw new TypeError("Capturing groups are not allowed at ".concat(j));
+ }
+ }
+ pattern += str[j++];
+ }
+ if (count)
+ throw new TypeError("Unbalanced pattern at ".concat(i));
+ if (!pattern)
+ throw new TypeError("Missing pattern at ".concat(i));
+ tokens.push({ type: "PATTERN", index: i, value: pattern });
+ i = j;
+ continue;
+ }
+ tokens.push({ type: "CHAR", index: i, value: str[i++] });
+ }
+ tokens.push({ type: "END", index: i, value: "" });
+ return tokens;
+ }
+ /**
+ * Parse a string for the raw tokens.
+ */
+ function parse(str, options) {
+ if (options === void 0) { options = {}; }
+ var tokens = lexer(str);
+ var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a;
+ var defaultPattern = "[^".concat(escapeString(options.delimiter || "/#?"), "]+?");
+ var result = [];
+ var key = 0;
+ var i = 0;
+ var path = "";
+ var tryConsume = function (type) {
+ if (i < tokens.length && tokens[i].type === type)
+ return tokens[i++].value;
+ };
+ var mustConsume = function (type) {
+ var value = tryConsume(type);
+ if (value !== undefined)
+ return value;
+ var _a = tokens[i], nextType = _a.type, index = _a.index;
+ throw new TypeError("Unexpected ".concat(nextType, " at ").concat(index, ", expected ").concat(type));
+ };
+ var consumeText = function () {
+ var result = "";
+ var value;
+ while ((value = tryConsume("CHAR") || tryConsume("ESCAPED_CHAR"))) {
+ result += value;
+ }
+ return result;
+ };
+ while (i < tokens.length) {
+ var char = tryConsume("CHAR");
+ var name = tryConsume("NAME");
+ var pattern = tryConsume("PATTERN");
+ if (name || pattern) {
+ var prefix = char || "";
+ if (prefixes.indexOf(prefix) === -1) {
+ path += prefix;
+ prefix = "";
+ }
+ if (path) {
+ result.push(path);
+ path = "";
+ }
+ result.push({
+ name: name || key++,
+ prefix: prefix,
+ suffix: "",
+ pattern: pattern || defaultPattern,
+ modifier: tryConsume("MODIFIER") || "",
+ });
+ continue;
+ }
+ var value = char || tryConsume("ESCAPED_CHAR");
+ if (value) {
+ path += value;
+ continue;
+ }
+ if (path) {
+ result.push(path);
+ path = "";
+ }
+ var open = tryConsume("OPEN");
+ if (open) {
+ var prefix = consumeText();
+ var name_1 = tryConsume("NAME") || "";
+ var pattern_1 = tryConsume("PATTERN") || "";
+ var suffix = consumeText();
+ mustConsume("CLOSE");
+ result.push({
+ name: name_1 || (pattern_1 ? key++ : ""),
+ pattern: name_1 && !pattern_1 ? defaultPattern : pattern_1,
+ prefix: prefix,
+ suffix: suffix,
+ modifier: tryConsume("MODIFIER") || "",
+ });
+ continue;
+ }
+ mustConsume("END");
+ }
+ return result;
+ }
+ /**
+ * Compile a string to a template function for the path.
+ */
+ function compile(str, options) {
+ return tokensToFunction(parse(str, options), options);
+ }
+ /**
+ * Expose a method for transforming tokens into the path function.
+ */
+ function tokensToFunction(tokens, options) {
+ if (options === void 0) { options = {}; }
+ var reFlags = flags(options);
+ var _a = options.encode, encode = _a === void 0 ? function (x) { return x; } : _a, _b = options.validate, validate = _b === void 0 ? true : _b;
+ // Compile all the tokens into regexps.
+ var matches = tokens.map(function (token) {
+ if (typeof token === "object") {
+ return new RegExp("^(?:".concat(token.pattern, ")$"), reFlags);
+ }
+ });
+ return function (data) {
+ var path = "";
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+ if (typeof token === "string") {
+ path += token;
+ continue;
+ }
+ var value = data ? data[token.name] : undefined;
+ var optional = token.modifier === "?" || token.modifier === "*";
+ var repeat = token.modifier === "*" || token.modifier === "+";
+ if (Array.isArray(value)) {
+ if (!repeat) {
+ throw new TypeError("Expected \"".concat(token.name, "\" to not repeat, but got an array"));
+ }
+ if (value.length === 0) {
+ if (optional)
+ continue;
+ throw new TypeError("Expected \"".concat(token.name, "\" to not be empty"));
+ }
+ for (var j = 0; j < value.length; j++) {
+ var segment = encode(value[j], token);
+ if (validate && !matches[i].test(segment)) {
+ throw new TypeError("Expected all \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
+ }
+ path += token.prefix + segment + token.suffix;
+ }
+ continue;
+ }
+ if (typeof value === "string" || typeof value === "number") {
+ var segment = encode(String(value), token);
+ if (validate && !matches[i].test(segment)) {
+ throw new TypeError("Expected \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
+ }
+ path += token.prefix + segment + token.suffix;
+ continue;
+ }
+ if (optional)
+ continue;
+ var typeOfMessage = repeat ? "an array" : "a string";
+ throw new TypeError("Expected \"".concat(token.name, "\" to be ").concat(typeOfMessage));
+ }
+ return path;
+ };
+ }
+ /**
+ * Escape a regular expression string.
+ */
+ function escapeString(str) {
+ return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
+ }
+ /**
+ * Get the flags for a regexp from the options.
+ */
+ function flags(options) {
+ return options && options.sensitive ? "" : "i";
+ }
+ /**
+ * Pull out keys from a regexp.
+ */
+ function regexpToRegexp(path, keys) {
+ if (!keys)
+ return path;
+ var groupsRegex = /\((?:\?<(.*?)>)?(?!\?)/g;
+ var index = 0;
+ var execResult = groupsRegex.exec(path.source);
+ while (execResult) {
+ keys.push({
+ // Use parenthesized substring match if available, index otherwise
+ name: execResult[1] || index++,
+ prefix: "",
+ suffix: "",
+ modifier: "",
+ pattern: "",
+ });
+ execResult = groupsRegex.exec(path.source);
+ }
+ return path;
+ }
+ /**
+ * Transform an array into a regexp.
+ */
+ function arrayToRegexp(paths, keys, options) {
+ var parts = paths.map(function (path) { return pathToRegexp(path, keys, options).source; });
+ return new RegExp("(?:".concat(parts.join("|"), ")"), flags(options));
+ }
+ /**
+ * Create a path regexp from string input.
+ */
+ function stringToRegexp(path, keys, options) {
+ return tokensToRegexp(parse(path, options), keys, options);
+ }
+ /**
+ * Expose a function for taking tokens and returning a RegExp.
+ */
+ function tokensToRegexp(tokens, keys, options) {
+ if (options === void 0) { options = {}; }
+ var _a = options.strict, strict = _a === void 0 ? false : _a, _b = options.start, start = _b === void 0 ? true : _b, _c = options.end, end = _c === void 0 ? true : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d, _e = options.delimiter, delimiter = _e === void 0 ? "/#?" : _e, _f = options.endsWith, endsWith = _f === void 0 ? "" : _f;
+ var endsWithRe = "[".concat(escapeString(endsWith), "]|$");
+ var delimiterRe = "[".concat(escapeString(delimiter), "]");
+ var route = start ? "^" : "";
+ // Iterate over the tokens and create our regexp string.
+ for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {
+ var token = tokens_1[_i];
+ if (typeof token === "string") {
+ route += escapeString(encode(token));
+ }
+ else {
+ var prefix = escapeString(encode(token.prefix));
+ var suffix = escapeString(encode(token.suffix));
+ if (token.pattern) {
+ if (keys)
+ keys.push(token);
+ if (prefix || suffix) {
+ if (token.modifier === "+" || token.modifier === "*") {
+ var mod = token.modifier === "*" ? "?" : "";
+ route += "(?:".concat(prefix, "((?:").concat(token.pattern, ")(?:").concat(suffix).concat(prefix, "(?:").concat(token.pattern, "))*)").concat(suffix, ")").concat(mod);
+ }
+ else {
+ route += "(?:".concat(prefix, "(").concat(token.pattern, ")").concat(suffix, ")").concat(token.modifier);
+ }
+ }
+ else {
+ if (token.modifier === "+" || token.modifier === "*") {
+ route += "((?:".concat(token.pattern, ")").concat(token.modifier, ")");
+ }
+ else {
+ route += "(".concat(token.pattern, ")").concat(token.modifier);
+ }
+ }
+ }
+ else {
+ route += "(?:".concat(prefix).concat(suffix, ")").concat(token.modifier);
+ }
+ }
+ }
+ if (end) {
+ if (!strict)
+ route += "".concat(delimiterRe, "?");
+ route += !options.endsWith ? "$" : "(?=".concat(endsWithRe, ")");
+ }
+ else {
+ var endToken = tokens[tokens.length - 1];
+ var isEndDelimited = typeof endToken === "string"
+ ? delimiterRe.indexOf(endToken[endToken.length - 1]) > -1
+ : endToken === undefined;
+ if (!strict) {
+ route += "(?:".concat(delimiterRe, "(?=").concat(endsWithRe, "))?");
+ }
+ if (!isEndDelimited) {
+ route += "(?=".concat(delimiterRe, "|").concat(endsWithRe, ")");
+ }
+ }
+ return new RegExp(route, flags(options));
+ }
+ /**
+ * Normalize the given path string, returning a regular expression.
+ *
+ * An empty array can be passed in for the keys, which will hold the
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
+ */
+ function pathToRegexp(path, keys, options) {
+ if (path instanceof RegExp)
+ return regexpToRegexp(path, keys);
+ if (Array.isArray(path))
+ return arrayToRegexp(path, keys, options);
+ return stringToRegexp(path, keys, options);
+ }
+
+ /**
+ * Cancel token
+ * @private
+ * @type { Symbol }
+ */
+ const CANCEL = Symbol();
+
+ /**
+ * Helper that can be returned by ruit function to cancel the tasks chain
+ * @returns { Symbol } internal private constant
+ * @example
+ *
+ * ruit(
+ * 100,
+ * num => Math.random() * num
+ * num => num > 50 ? ruit.cancel() : num
+ * num => num - 2
+ * ).then(result => {
+ * console.log(result) // here we will get only number lower than 50
+ * })
+ *
+ */
+ ruit.cancel = () => CANCEL;
+
+ /**
+ * The same as ruit() but with the arguments inverted from right to left
+ * @param { * } tasks - list of tasks to process sequentially
+ * @returns { Promise } a promise containing the result of the whole chain
+ * @example
+ *
+ * const curry = f => a => b => f(a, b)
+ * const add = (a, b) => a + b
+ *
+ * const addOne = curry(add)(1)
+ *
+ * const squareAsync = (num) => {
+ * return new Promise(r => {
+ * setTimeout(r, 500, num * 2)
+ * })
+ * }
+ *
+ * // a -> a + a -> a * 2
+ * // basically from right to left: 1 => 1 + 1 => 2 * 2
+ * ruit.compose(squareAsync, addOne, 1).then(result => console.log(result)) // 4
+ */
+ ruit.compose = (...tasks) => ruit(...tasks.reverse());
+
+ /**
+ * Serialize a list of sync and async tasks from left to right
+ * @param { * } tasks - list of tasks to process sequentially
+ * @returns { Promise } a promise containing the result of the whole chain
+ * @example
+ *
+ * const curry = f => a => b => f(a, b)
+ * const add = (a, b) => a + b
+ *
+ * const addOne = curry(add)(1)
+ *
+ * const squareAsync = (num) => {
+ * return new Promise(r => {
+ * setTimeout(r, 500, num * 2)
+ * })
+ * }
+ *
+ * // a -> a + a -> a * 2
+ * // basically from left to right: 1 => 1 + 1 => 2 * 2
+ * ruit(1, addOne, squareAsync).then(result => console.log(result)) // 4
+ */
+ function ruit(...tasks) {
+ return new Promise((resolve, reject) => {
+ return (function run(queue, result) {
+ if (!queue.length) return resolve(result)
+
+ const [task, ...rest] = queue;
+ const value = typeof task === 'function' ? task(result) : task;
+ const done = v => run(rest, v);
+
+ // check against nil values
+ if (value != null) {
+ if (value === CANCEL) return
+ if (value.then) return value.then(done, reject)
+ }
+
+ return Promise.resolve(done(value))
+ })(tasks)
+ })
+ }
+
+ // Store the erre the API methods to handle the plugins installation
+ const API_METHODS = new Set();
+ const UNSUBSCRIBE_SYMBOL = Symbol();
+ const UNSUBSCRIBE_METHOD = 'off';
+ const CANCEL_METHOD = 'cancel';
+
+ /**
+ * Factory function to create the stream generator
+ * @private
+ * @param {Set} modifiers - stream input modifiers
+ * @returns {Generator} the stream generator
+ */
+ function createStream(modifiers) {
+ const stream = (function *stream() {
+ while (true) {
+ // get the initial stream value
+ const input = yield;
+
+ // run the input sequence
+ yield ruit(input, ...modifiers);
+ }
+ })();
+
+ // start the stream
+ stream.next();
+
+ return stream
+ }
+
+ /**
+ * Dispatch a value to several listeners
+ * @private
+ * @param {Set} callbacks - callbacks collection
+ * @param {*} value - anything
+ * @returns {Set} the callbacks received
+ */
+ function dispatch(callbacks, value) {
+ callbacks.forEach(f => {
+ // unsubscribe the callback if erre.unsubscribe() will be returned
+ if (f(value) === UNSUBSCRIBE_SYMBOL) callbacks.delete(f);
+ });
+
+ return callbacks
+ }
+
+ /**
+ * Throw a panic error
+ * @param {string} message - error message
+ * @returns {Error} an error object
+ */
+ function panic$1(message) {
+ throw new Error(message)
+ }
+
+ /**
+ * Install an erre plugin adding it to the API
+ * @param {string} name - plugin name
+ * @param {Function} fn - new erre API method
+ * @returns {Function} return the erre function
+ */
+ erre.install = function(name, fn) {
+ if (!name || typeof name !== 'string')
+ panic$1('Please provide a name (as string) for your erre plugin');
+ if (!fn || typeof fn !== 'function')
+ panic$1('Please provide a function for your erre plugin');
+
+ if (API_METHODS.has(name)) {
+ panic$1(`The ${name} is already part of the erre API, please provide a different name`);
+ } else {
+ erre[name] = fn;
+ API_METHODS.add(name);
+ }
+
+ return erre
+ };
+
+ // alias for ruit canel to stop a stream chain
+ erre.install(CANCEL_METHOD, ruit.cancel);
+
+ // unsubscribe helper
+ erre.install(UNSUBSCRIBE_METHOD, () => UNSUBSCRIBE_SYMBOL);
+
+ /**
+ * Stream constuction function
+ * @param {...Function} fns - stream modifiers
+ * @returns {Object} erre instance
+ */
+ function erre(...fns) {
+ const
+ [success, error, end, modifiers] = [new Set(), new Set(), new Set(), new Set(fns)],
+ generator = createStream(modifiers),
+ stream = Object.create(generator),
+ addToCollection = (collection) => (fn) => collection.add(fn) && stream,
+ deleteFromCollection = (collection) => (fn) => collection.delete(fn) ? stream
+ : panic$1('Couldn\'t remove handler passed by reference');
+
+ return Object.assign(stream, {
+ on: Object.freeze({
+ value: addToCollection(success),
+ error: addToCollection(error),
+ end: addToCollection(end)
+ }),
+ off: Object.freeze({
+ value: deleteFromCollection(success),
+ error: deleteFromCollection(error),
+ end: deleteFromCollection(end)
+ }),
+ connect: addToCollection(modifiers),
+ push(input) {
+ const { value, done } = stream.next(input);
+
+ // dispatch the stream events
+ if (!done) {
+ value.then(
+ res => dispatch(success, res),
+ err => dispatch(error, err)
+ );
+ }
+
+ return stream
+ },
+ end() {
+ // kill the stream
+ generator.return();
+ // dispatch the end event
+ dispatch(end)
+ // clean up all the collections
+ ;[success, error, end, modifiers].forEach(el => el.clear());
+
+ return stream
+ },
+ fork() {
+ return erre(...modifiers)
+ },
+ next(input) {
+ // get the input and run eventually the promise
+ const result = generator.next(input);
+
+ // pause to the next iteration
+ generator.next();
+
+ return result
+ }
+ })
+ }
+
+ const isString = str => typeof str === 'string';
+ const parseURL = (...args) => new URL(...args);
+
+ /**
+ * Replace the base path from a path
+ * @param {string} path - router path string
+ * @returns {string} path cleaned up without the base
+ */
+ const replaceBase = path => path.replace(defaults.base, '');
+
+ /**
+ * Try to match the current path or skip it
+ * @param {RegExp} pathRegExp - target path transformed by pathToRegexp
+ * @returns {string|Symbol} if the path match we return it otherwise we cancel the stream
+ */
+ const matchOrSkip = pathRegExp => path => match(path, pathRegExp) ? path : erre.cancel();
+
+ /**
+ * Combine 2 streams connecting the events of dispatcherStream to the receiverStream
+ * @param {Stream} dispatcherStream - main stream dispatching events
+ * @param {Stream} receiverStream - sub stream receiving events from the dispatcher
+ * @returns {Stream} receiverStream
+ */
+ const joinStreams = (dispatcherStream, receiverStream) => {
+ dispatcherStream.on.value(receiverStream.push);
+
+ receiverStream.on.end(() => {
+ dispatcherStream.off.value(receiverStream.push);
+ });
+
+ return receiverStream
+ };
+
+ /**
+ * Error handling function
+ * @param {Error} error - error to catch
+ * @returns {void}
+ */
+ /* c8 ignore start */
+ const panic = error => {
+ if (defaults.silentErrors) return
+
+ throw new Error(error)
+ };
+ /* c8 ignore stop */
+
+ // make sure that the router will always receive strings params
+ const filterStrings = str => isString(str) ? str : erre.cancel();
+
+ // create the streaming router
+ const router = erre(filterStrings).on.error(panic); // cast the values of this stream always to string
+
+ /**
+ * Merge the user options with the defaults
+ * @param {Object} options - custom user options
+ * @returns {Object} options object merged with defaults
+ */
+ const mergeOptions = options => ({...defaults, ...options});
+
+ /* @type {object} general configuration object */
+ const defaults = {
+ base: 'https://localhost',
+ silentErrors: false,
+ // pathToRegexp options
+ sensitive: false,
+ strict: false,
+ end: true,
+ start: true,
+ delimiter: '/#?',
+ encode: undefined,
+ endsWith: undefined,
+ prefixes: './'
+ };
+
+ /**
+ * Configure the router options overriding the defaults
+ * @param {Object} options - custom user options to override
+ * @returns {Object} new defaults
+ */
+ const configure = (options) => {
+ Object.entries(options).forEach(([key, value]) => {
+ if (Object.hasOwn(defaults, key)) defaults[key] = value;
+ });
+
+ return defaults
+ };
+
+
+
+ /* {@link https://github.com/pillarjs/path-to-regexp#usage} */
+ const toRegexp = (path, keys, options) => pathToRegexp(path, keys, mergeOptions(options));
+
+ /**
+ * Convert a router entry to a real path computing the url parameters
+ * @param {string} path - router path string
+ * @param {Object} params - named matched parameters
+ * @param {Object} options - pathToRegexp options object
+ * @returns {string} computed url string
+ */
+ const toPath = (path, params, options) => compile(path, mergeOptions(options))(params);
+
+ /**
+ * Parse a string path generating an object containing
+ * @param {string} path - target path
+ * @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
+ * @param {Object} options - object containing the base path
+ * @returns {URL} url object enhanced with the `match` attribute
+ */
+ const toURL = (path, pathRegExp, options = {}) => {
+ const {base} = mergeOptions(options);
+ const [, ...params] = pathRegExp.exec(path);
+ const url = parseURL(path, base);
+
+ // extend the url object adding the matched params
+ url.params = params.reduce((acc, param, index) => {
+ const key = options.keys && options.keys[index];
+ if (key) acc[key.name] = param ? decodeURIComponent(param) : param;
+ return acc
+ }, {});
+
+ return url
+ };
+
+ /**
+ * Return true if a path will be matched
+ * @param {string} path - target path
+ * @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
+ * @returns {boolean} true if the path matches the regexp
+ */
+ const match = (path, pathRegExp) => pathRegExp.test(path);
+
+ /**
+ * Factory function to create an sequence of functions to pass to erre.js
+ * This function will be used in the erre stream
+ * @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
+ * @param {Object} options - pathToRegexp options object
+ * @returns {Array} a functions array that will be used as stream pipe for erre.js
+ */
+ const createURLStreamPipe = (pathRegExp, options) => [
+ decodeURI,
+ replaceBase,
+ matchOrSkip(pathRegExp),
+ path => toURL(path, pathRegExp, options)
+ ];
+
+ /**
+ * Create a fork of the main router stream
+ * @param {string} path - route to match
+ * @param {Object} options - pathToRegexp options object
+ * @returns {Stream} new route stream
+ */
+ function createRoute(path, options) {
+ const keys = [];
+ const pathRegExp = pathToRegexp(path, keys, options);
+ const URLStream = erre(...createURLStreamPipe(pathRegExp, {
+ ...options,
+ keys
+ }));
+
+ return joinStreams(router, URLStream).on.error(panic)
+ }
+
+ exports.configure = configure;
+ exports.createURLStreamPipe = createURLStreamPipe;
+ exports.default = createRoute;
+ exports.defaults = defaults;
+ exports.match = match;
+ exports.router = router;
+ exports.toPath = toPath;
+ exports.toRegexp = toRegexp;
+ exports.toURL = toURL;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+}));
diff --git a/node_modules/rawth/index.d.ts b/node_modules/rawth/index.d.ts
new file mode 100644
index 0000000..04fdea8
--- /dev/null
+++ b/node_modules/rawth/index.d.ts
@@ -0,0 +1,24 @@
+import { ErreStream } from 'erre'
+import { TokensToRegexpOptions, ParseOptions, pathToRegexp } from 'path-to-regexp'
+
+type Callback = (...args: any[]) => any
+
+export type URLWithParams = URL & { params: Record }
+export type RawthOptions = TokensToRegexpOptions & ParseOptions & {
+ base: string
+ silentErrors: boolean
+}
+
+// internal methods that probably you will never use by yourselves
+export declare const toRegexp: typeof pathToRegexp
+export declare const toPath: (path: string, params: Record, options: RawthOptions) => string
+export declare const toURL: (path: string, pathRegExp: RegExp, options: RawthOptions) => URLWithParams
+export declare const match: (path: string, pathRegExp: RegExp) => boolean
+export declare const createURLStreamPipe: (pathRegExp: RegExp, options: RawthOptions) => Callback[]
+
+// public API
+export declare const router: ErreStream
+export declare const defaults: RawthOptions
+export declare const configure: (options: Partial) => RawthOptions
+export declare function route(path: string): ErreStream
+export default route
diff --git a/node_modules/rawth/index.js b/node_modules/rawth/index.js
new file mode 100644
index 0000000..36f3b87
--- /dev/null
+++ b/node_modules/rawth/index.js
@@ -0,0 +1,758 @@
+/**
+ * Tokenize input string.
+ */
+function lexer(str) {
+ var tokens = [];
+ var i = 0;
+ while (i < str.length) {
+ var char = str[i];
+ if (char === "*" || char === "+" || char === "?") {
+ tokens.push({ type: "MODIFIER", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === "\\") {
+ tokens.push({ type: "ESCAPED_CHAR", index: i++, value: str[i++] });
+ continue;
+ }
+ if (char === "{") {
+ tokens.push({ type: "OPEN", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === "}") {
+ tokens.push({ type: "CLOSE", index: i, value: str[i++] });
+ continue;
+ }
+ if (char === ":") {
+ var name = "";
+ var j = i + 1;
+ while (j < str.length) {
+ var code = str.charCodeAt(j);
+ if (
+ // `0-9`
+ (code >= 48 && code <= 57) ||
+ // `A-Z`
+ (code >= 65 && code <= 90) ||
+ // `a-z`
+ (code >= 97 && code <= 122) ||
+ // `_`
+ code === 95) {
+ name += str[j++];
+ continue;
+ }
+ break;
+ }
+ if (!name)
+ throw new TypeError("Missing parameter name at ".concat(i));
+ tokens.push({ type: "NAME", index: i, value: name });
+ i = j;
+ continue;
+ }
+ if (char === "(") {
+ var count = 1;
+ var pattern = "";
+ var j = i + 1;
+ if (str[j] === "?") {
+ throw new TypeError("Pattern cannot start with \"?\" at ".concat(j));
+ }
+ while (j < str.length) {
+ if (str[j] === "\\") {
+ pattern += str[j++] + str[j++];
+ continue;
+ }
+ if (str[j] === ")") {
+ count--;
+ if (count === 0) {
+ j++;
+ break;
+ }
+ }
+ else if (str[j] === "(") {
+ count++;
+ if (str[j + 1] !== "?") {
+ throw new TypeError("Capturing groups are not allowed at ".concat(j));
+ }
+ }
+ pattern += str[j++];
+ }
+ if (count)
+ throw new TypeError("Unbalanced pattern at ".concat(i));
+ if (!pattern)
+ throw new TypeError("Missing pattern at ".concat(i));
+ tokens.push({ type: "PATTERN", index: i, value: pattern });
+ i = j;
+ continue;
+ }
+ tokens.push({ type: "CHAR", index: i, value: str[i++] });
+ }
+ tokens.push({ type: "END", index: i, value: "" });
+ return tokens;
+}
+/**
+ * Parse a string for the raw tokens.
+ */
+function parse(str, options) {
+ if (options === void 0) { options = {}; }
+ var tokens = lexer(str);
+ var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a;
+ var defaultPattern = "[^".concat(escapeString(options.delimiter || "/#?"), "]+?");
+ var result = [];
+ var key = 0;
+ var i = 0;
+ var path = "";
+ var tryConsume = function (type) {
+ if (i < tokens.length && tokens[i].type === type)
+ return tokens[i++].value;
+ };
+ var mustConsume = function (type) {
+ var value = tryConsume(type);
+ if (value !== undefined)
+ return value;
+ var _a = tokens[i], nextType = _a.type, index = _a.index;
+ throw new TypeError("Unexpected ".concat(nextType, " at ").concat(index, ", expected ").concat(type));
+ };
+ var consumeText = function () {
+ var result = "";
+ var value;
+ while ((value = tryConsume("CHAR") || tryConsume("ESCAPED_CHAR"))) {
+ result += value;
+ }
+ return result;
+ };
+ while (i < tokens.length) {
+ var char = tryConsume("CHAR");
+ var name = tryConsume("NAME");
+ var pattern = tryConsume("PATTERN");
+ if (name || pattern) {
+ var prefix = char || "";
+ if (prefixes.indexOf(prefix) === -1) {
+ path += prefix;
+ prefix = "";
+ }
+ if (path) {
+ result.push(path);
+ path = "";
+ }
+ result.push({
+ name: name || key++,
+ prefix: prefix,
+ suffix: "",
+ pattern: pattern || defaultPattern,
+ modifier: tryConsume("MODIFIER") || "",
+ });
+ continue;
+ }
+ var value = char || tryConsume("ESCAPED_CHAR");
+ if (value) {
+ path += value;
+ continue;
+ }
+ if (path) {
+ result.push(path);
+ path = "";
+ }
+ var open = tryConsume("OPEN");
+ if (open) {
+ var prefix = consumeText();
+ var name_1 = tryConsume("NAME") || "";
+ var pattern_1 = tryConsume("PATTERN") || "";
+ var suffix = consumeText();
+ mustConsume("CLOSE");
+ result.push({
+ name: name_1 || (pattern_1 ? key++ : ""),
+ pattern: name_1 && !pattern_1 ? defaultPattern : pattern_1,
+ prefix: prefix,
+ suffix: suffix,
+ modifier: tryConsume("MODIFIER") || "",
+ });
+ continue;
+ }
+ mustConsume("END");
+ }
+ return result;
+}
+/**
+ * Compile a string to a template function for the path.
+ */
+function compile(str, options) {
+ return tokensToFunction(parse(str, options), options);
+}
+/**
+ * Expose a method for transforming tokens into the path function.
+ */
+function tokensToFunction(tokens, options) {
+ if (options === void 0) { options = {}; }
+ var reFlags = flags(options);
+ var _a = options.encode, encode = _a === void 0 ? function (x) { return x; } : _a, _b = options.validate, validate = _b === void 0 ? true : _b;
+ // Compile all the tokens into regexps.
+ var matches = tokens.map(function (token) {
+ if (typeof token === "object") {
+ return new RegExp("^(?:".concat(token.pattern, ")$"), reFlags);
+ }
+ });
+ return function (data) {
+ var path = "";
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+ if (typeof token === "string") {
+ path += token;
+ continue;
+ }
+ var value = data ? data[token.name] : undefined;
+ var optional = token.modifier === "?" || token.modifier === "*";
+ var repeat = token.modifier === "*" || token.modifier === "+";
+ if (Array.isArray(value)) {
+ if (!repeat) {
+ throw new TypeError("Expected \"".concat(token.name, "\" to not repeat, but got an array"));
+ }
+ if (value.length === 0) {
+ if (optional)
+ continue;
+ throw new TypeError("Expected \"".concat(token.name, "\" to not be empty"));
+ }
+ for (var j = 0; j < value.length; j++) {
+ var segment = encode(value[j], token);
+ if (validate && !matches[i].test(segment)) {
+ throw new TypeError("Expected all \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
+ }
+ path += token.prefix + segment + token.suffix;
+ }
+ continue;
+ }
+ if (typeof value === "string" || typeof value === "number") {
+ var segment = encode(String(value), token);
+ if (validate && !matches[i].test(segment)) {
+ throw new TypeError("Expected \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
+ }
+ path += token.prefix + segment + token.suffix;
+ continue;
+ }
+ if (optional)
+ continue;
+ var typeOfMessage = repeat ? "an array" : "a string";
+ throw new TypeError("Expected \"".concat(token.name, "\" to be ").concat(typeOfMessage));
+ }
+ return path;
+ };
+}
+/**
+ * Escape a regular expression string.
+ */
+function escapeString(str) {
+ return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
+}
+/**
+ * Get the flags for a regexp from the options.
+ */
+function flags(options) {
+ return options && options.sensitive ? "" : "i";
+}
+/**
+ * Pull out keys from a regexp.
+ */
+function regexpToRegexp(path, keys) {
+ if (!keys)
+ return path;
+ var groupsRegex = /\((?:\?<(.*?)>)?(?!\?)/g;
+ var index = 0;
+ var execResult = groupsRegex.exec(path.source);
+ while (execResult) {
+ keys.push({
+ // Use parenthesized substring match if available, index otherwise
+ name: execResult[1] || index++,
+ prefix: "",
+ suffix: "",
+ modifier: "",
+ pattern: "",
+ });
+ execResult = groupsRegex.exec(path.source);
+ }
+ return path;
+}
+/**
+ * Transform an array into a regexp.
+ */
+function arrayToRegexp(paths, keys, options) {
+ var parts = paths.map(function (path) { return pathToRegexp(path, keys, options).source; });
+ return new RegExp("(?:".concat(parts.join("|"), ")"), flags(options));
+}
+/**
+ * Create a path regexp from string input.
+ */
+function stringToRegexp(path, keys, options) {
+ return tokensToRegexp(parse(path, options), keys, options);
+}
+/**
+ * Expose a function for taking tokens and returning a RegExp.
+ */
+function tokensToRegexp(tokens, keys, options) {
+ if (options === void 0) { options = {}; }
+ var _a = options.strict, strict = _a === void 0 ? false : _a, _b = options.start, start = _b === void 0 ? true : _b, _c = options.end, end = _c === void 0 ? true : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d, _e = options.delimiter, delimiter = _e === void 0 ? "/#?" : _e, _f = options.endsWith, endsWith = _f === void 0 ? "" : _f;
+ var endsWithRe = "[".concat(escapeString(endsWith), "]|$");
+ var delimiterRe = "[".concat(escapeString(delimiter), "]");
+ var route = start ? "^" : "";
+ // Iterate over the tokens and create our regexp string.
+ for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {
+ var token = tokens_1[_i];
+ if (typeof token === "string") {
+ route += escapeString(encode(token));
+ }
+ else {
+ var prefix = escapeString(encode(token.prefix));
+ var suffix = escapeString(encode(token.suffix));
+ if (token.pattern) {
+ if (keys)
+ keys.push(token);
+ if (prefix || suffix) {
+ if (token.modifier === "+" || token.modifier === "*") {
+ var mod = token.modifier === "*" ? "?" : "";
+ route += "(?:".concat(prefix, "((?:").concat(token.pattern, ")(?:").concat(suffix).concat(prefix, "(?:").concat(token.pattern, "))*)").concat(suffix, ")").concat(mod);
+ }
+ else {
+ route += "(?:".concat(prefix, "(").concat(token.pattern, ")").concat(suffix, ")").concat(token.modifier);
+ }
+ }
+ else {
+ if (token.modifier === "+" || token.modifier === "*") {
+ route += "((?:".concat(token.pattern, ")").concat(token.modifier, ")");
+ }
+ else {
+ route += "(".concat(token.pattern, ")").concat(token.modifier);
+ }
+ }
+ }
+ else {
+ route += "(?:".concat(prefix).concat(suffix, ")").concat(token.modifier);
+ }
+ }
+ }
+ if (end) {
+ if (!strict)
+ route += "".concat(delimiterRe, "?");
+ route += !options.endsWith ? "$" : "(?=".concat(endsWithRe, ")");
+ }
+ else {
+ var endToken = tokens[tokens.length - 1];
+ var isEndDelimited = typeof endToken === "string"
+ ? delimiterRe.indexOf(endToken[endToken.length - 1]) > -1
+ : endToken === undefined;
+ if (!strict) {
+ route += "(?:".concat(delimiterRe, "(?=").concat(endsWithRe, "))?");
+ }
+ if (!isEndDelimited) {
+ route += "(?=".concat(delimiterRe, "|").concat(endsWithRe, ")");
+ }
+ }
+ return new RegExp(route, flags(options));
+}
+/**
+ * Normalize the given path string, returning a regular expression.
+ *
+ * An empty array can be passed in for the keys, which will hold the
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
+ */
+function pathToRegexp(path, keys, options) {
+ if (path instanceof RegExp)
+ return regexpToRegexp(path, keys);
+ if (Array.isArray(path))
+ return arrayToRegexp(path, keys, options);
+ return stringToRegexp(path, keys, options);
+}
+
+/**
+ * Cancel token
+ * @private
+ * @type { Symbol }
+ */
+const CANCEL = Symbol();
+
+/**
+ * Helper that can be returned by ruit function to cancel the tasks chain
+ * @returns { Symbol } internal private constant
+ * @example
+ *
+ * ruit(
+ * 100,
+ * num => Math.random() * num
+ * num => num > 50 ? ruit.cancel() : num
+ * num => num - 2
+ * ).then(result => {
+ * console.log(result) // here we will get only number lower than 50
+ * })
+ *
+ */
+ruit.cancel = () => CANCEL;
+
+/**
+ * The same as ruit() but with the arguments inverted from right to left
+ * @param { * } tasks - list of tasks to process sequentially
+ * @returns { Promise } a promise containing the result of the whole chain
+ * @example
+ *
+ * const curry = f => a => b => f(a, b)
+ * const add = (a, b) => a + b
+ *
+ * const addOne = curry(add)(1)
+ *
+ * const squareAsync = (num) => {
+ * return new Promise(r => {
+ * setTimeout(r, 500, num * 2)
+ * })
+ * }
+ *
+ * // a -> a + a -> a * 2
+ * // basically from right to left: 1 => 1 + 1 => 2 * 2
+ * ruit.compose(squareAsync, addOne, 1).then(result => console.log(result)) // 4
+ */
+ruit.compose = (...tasks) => ruit(...tasks.reverse());
+
+/**
+ * Serialize a list of sync and async tasks from left to right
+ * @param { * } tasks - list of tasks to process sequentially
+ * @returns { Promise } a promise containing the result of the whole chain
+ * @example
+ *
+ * const curry = f => a => b => f(a, b)
+ * const add = (a, b) => a + b
+ *
+ * const addOne = curry(add)(1)
+ *
+ * const squareAsync = (num) => {
+ * return new Promise(r => {
+ * setTimeout(r, 500, num * 2)
+ * })
+ * }
+ *
+ * // a -> a + a -> a * 2
+ * // basically from left to right: 1 => 1 + 1 => 2 * 2
+ * ruit(1, addOne, squareAsync).then(result => console.log(result)) // 4
+ */
+function ruit(...tasks) {
+ return new Promise((resolve, reject) => {
+ return (function run(queue, result) {
+ if (!queue.length) return resolve(result)
+
+ const [task, ...rest] = queue;
+ const value = typeof task === 'function' ? task(result) : task;
+ const done = v => run(rest, v);
+
+ // check against nil values
+ if (value != null) {
+ if (value === CANCEL) return
+ if (value.then) return value.then(done, reject)
+ }
+
+ return Promise.resolve(done(value))
+ })(tasks)
+ })
+}
+
+// Store the erre the API methods to handle the plugins installation
+const API_METHODS = new Set();
+const UNSUBSCRIBE_SYMBOL = Symbol();
+const UNSUBSCRIBE_METHOD = 'off';
+const CANCEL_METHOD = 'cancel';
+
+/**
+ * Factory function to create the stream generator
+ * @private
+ * @param {Set} modifiers - stream input modifiers
+ * @returns {Generator} the stream generator
+ */
+function createStream(modifiers) {
+ const stream = (function *stream() {
+ while (true) {
+ // get the initial stream value
+ const input = yield;
+
+ // run the input sequence
+ yield ruit(input, ...modifiers);
+ }
+ })();
+
+ // start the stream
+ stream.next();
+
+ return stream
+}
+
+/**
+ * Dispatch a value to several listeners
+ * @private
+ * @param {Set} callbacks - callbacks collection
+ * @param {*} value - anything
+ * @returns {Set} the callbacks received
+ */
+function dispatch(callbacks, value) {
+ callbacks.forEach(f => {
+ // unsubscribe the callback if erre.unsubscribe() will be returned
+ if (f(value) === UNSUBSCRIBE_SYMBOL) callbacks.delete(f);
+ });
+
+ return callbacks
+}
+
+/**
+ * Throw a panic error
+ * @param {string} message - error message
+ * @returns {Error} an error object
+ */
+function panic$1(message) {
+ throw new Error(message)
+}
+
+/**
+ * Install an erre plugin adding it to the API
+ * @param {string} name - plugin name
+ * @param {Function} fn - new erre API method
+ * @returns {Function} return the erre function
+ */
+erre.install = function(name, fn) {
+ if (!name || typeof name !== 'string')
+ panic$1('Please provide a name (as string) for your erre plugin');
+ if (!fn || typeof fn !== 'function')
+ panic$1('Please provide a function for your erre plugin');
+
+ if (API_METHODS.has(name)) {
+ panic$1(`The ${name} is already part of the erre API, please provide a different name`);
+ } else {
+ erre[name] = fn;
+ API_METHODS.add(name);
+ }
+
+ return erre
+};
+
+// alias for ruit canel to stop a stream chain
+erre.install(CANCEL_METHOD, ruit.cancel);
+
+// unsubscribe helper
+erre.install(UNSUBSCRIBE_METHOD, () => UNSUBSCRIBE_SYMBOL);
+
+/**
+ * Stream constuction function
+ * @param {...Function} fns - stream modifiers
+ * @returns {Object} erre instance
+ */
+function erre(...fns) {
+ const
+ [success, error, end, modifiers] = [new Set(), new Set(), new Set(), new Set(fns)],
+ generator = createStream(modifiers),
+ stream = Object.create(generator),
+ addToCollection = (collection) => (fn) => collection.add(fn) && stream,
+ deleteFromCollection = (collection) => (fn) => collection.delete(fn) ? stream
+ : panic$1('Couldn\'t remove handler passed by reference');
+
+ return Object.assign(stream, {
+ on: Object.freeze({
+ value: addToCollection(success),
+ error: addToCollection(error),
+ end: addToCollection(end)
+ }),
+ off: Object.freeze({
+ value: deleteFromCollection(success),
+ error: deleteFromCollection(error),
+ end: deleteFromCollection(end)
+ }),
+ connect: addToCollection(modifiers),
+ push(input) {
+ const { value, done } = stream.next(input);
+
+ // dispatch the stream events
+ if (!done) {
+ value.then(
+ res => dispatch(success, res),
+ err => dispatch(error, err)
+ );
+ }
+
+ return stream
+ },
+ end() {
+ // kill the stream
+ generator.return();
+ // dispatch the end event
+ dispatch(end)
+ // clean up all the collections
+ ;[success, error, end, modifiers].forEach(el => el.clear());
+
+ return stream
+ },
+ fork() {
+ return erre(...modifiers)
+ },
+ next(input) {
+ // get the input and run eventually the promise
+ const result = generator.next(input);
+
+ // pause to the next iteration
+ generator.next();
+
+ return result
+ }
+ })
+}
+
+const isString = str => typeof str === 'string';
+const parseURL = (...args) => new URL(...args);
+
+/**
+ * Replace the base path from a path
+ * @param {string} path - router path string
+ * @returns {string} path cleaned up without the base
+ */
+const replaceBase = path => path.replace(defaults.base, '');
+
+/**
+ * Try to match the current path or skip it
+ * @param {RegExp} pathRegExp - target path transformed by pathToRegexp
+ * @returns {string|Symbol} if the path match we return it otherwise we cancel the stream
+ */
+const matchOrSkip = pathRegExp => path => match(path, pathRegExp) ? path : erre.cancel();
+
+/**
+ * Combine 2 streams connecting the events of dispatcherStream to the receiverStream
+ * @param {Stream} dispatcherStream - main stream dispatching events
+ * @param {Stream} receiverStream - sub stream receiving events from the dispatcher
+ * @returns {Stream} receiverStream
+ */
+const joinStreams = (dispatcherStream, receiverStream) => {
+ dispatcherStream.on.value(receiverStream.push);
+
+ receiverStream.on.end(() => {
+ dispatcherStream.off.value(receiverStream.push);
+ });
+
+ return receiverStream
+};
+
+/**
+ * Error handling function
+ * @param {Error} error - error to catch
+ * @returns {void}
+ */
+/* c8 ignore start */
+const panic = error => {
+ if (defaults.silentErrors) return
+
+ throw new Error(error)
+};
+/* c8 ignore stop */
+
+// make sure that the router will always receive strings params
+const filterStrings = str => isString(str) ? str : erre.cancel();
+
+// create the streaming router
+const router = erre(filterStrings).on.error(panic); // cast the values of this stream always to string
+
+/**
+ * Merge the user options with the defaults
+ * @param {Object} options - custom user options
+ * @returns {Object} options object merged with defaults
+ */
+const mergeOptions = options => ({...defaults, ...options});
+
+/* @type {object} general configuration object */
+const defaults = {
+ base: 'https://localhost',
+ silentErrors: false,
+ // pathToRegexp options
+ sensitive: false,
+ strict: false,
+ end: true,
+ start: true,
+ delimiter: '/#?',
+ encode: undefined,
+ endsWith: undefined,
+ prefixes: './'
+};
+
+/**
+ * Configure the router options overriding the defaults
+ * @param {Object} options - custom user options to override
+ * @returns {Object} new defaults
+ */
+const configure = (options) => {
+ Object.entries(options).forEach(([key, value]) => {
+ if (Object.hasOwn(defaults, key)) defaults[key] = value;
+ });
+
+ return defaults
+};
+
+
+
+/* {@link https://github.com/pillarjs/path-to-regexp#usage} */
+const toRegexp = (path, keys, options) => pathToRegexp(path, keys, mergeOptions(options));
+
+/**
+ * Convert a router entry to a real path computing the url parameters
+ * @param {string} path - router path string
+ * @param {Object} params - named matched parameters
+ * @param {Object} options - pathToRegexp options object
+ * @returns {string} computed url string
+ */
+const toPath = (path, params, options) => compile(path, mergeOptions(options))(params);
+
+/**
+ * Parse a string path generating an object containing
+ * @param {string} path - target path
+ * @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
+ * @param {Object} options - object containing the base path
+ * @returns {URL} url object enhanced with the `match` attribute
+ */
+const toURL = (path, pathRegExp, options = {}) => {
+ const {base} = mergeOptions(options);
+ const [, ...params] = pathRegExp.exec(path);
+ const url = parseURL(path, base);
+
+ // extend the url object adding the matched params
+ url.params = params.reduce((acc, param, index) => {
+ const key = options.keys && options.keys[index];
+ if (key) acc[key.name] = param ? decodeURIComponent(param) : param;
+ return acc
+ }, {});
+
+ return url
+};
+
+/**
+ * Return true if a path will be matched
+ * @param {string} path - target path
+ * @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
+ * @returns {boolean} true if the path matches the regexp
+ */
+const match = (path, pathRegExp) => pathRegExp.test(path);
+
+/**
+ * Factory function to create an sequence of functions to pass to erre.js
+ * This function will be used in the erre stream
+ * @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
+ * @param {Object} options - pathToRegexp options object
+ * @returns {Array} a functions array that will be used as stream pipe for erre.js
+ */
+const createURLStreamPipe = (pathRegExp, options) => [
+ decodeURI,
+ replaceBase,
+ matchOrSkip(pathRegExp),
+ path => toURL(path, pathRegExp, options)
+];
+
+/**
+ * Create a fork of the main router stream
+ * @param {string} path - route to match
+ * @param {Object} options - pathToRegexp options object
+ * @returns {Stream} new route stream
+ */
+function createRoute(path, options) {
+ const keys = [];
+ const pathRegExp = pathToRegexp(path, keys, options);
+ const URLStream = erre(...createURLStreamPipe(pathRegExp, {
+ ...options,
+ keys
+ }));
+
+ return joinStreams(router, URLStream).on.error(panic)
+}
+
+export { configure, createURLStreamPipe, createRoute as default, defaults, match, router, toPath, toRegexp, toURL };
diff --git a/node_modules/rawth/index.next.js b/node_modules/rawth/index.next.js
new file mode 100644
index 0000000..2831f33
--- /dev/null
+++ b/node_modules/rawth/index.next.js
@@ -0,0 +1,164 @@
+import {compile, pathToRegexp} from 'path-to-regexp'
+import erre from 'erre'
+
+const isString = str => typeof str === 'string'
+const parseURL = (...args) => new URL(...args)
+
+/**
+ * Replace the base path from a path
+ * @param {string} path - router path string
+ * @returns {string} path cleaned up without the base
+ */
+const replaceBase = path => path.replace(defaults.base, '')
+
+/**
+ * Try to match the current path or skip it
+ * @param {RegExp} pathRegExp - target path transformed by pathToRegexp
+ * @returns {string|Symbol} if the path match we return it otherwise we cancel the stream
+ */
+const matchOrSkip = pathRegExp => path => match(path, pathRegExp) ? path : erre.cancel()
+
+/**
+ * Combine 2 streams connecting the events of dispatcherStream to the receiverStream
+ * @param {Stream} dispatcherStream - main stream dispatching events
+ * @param {Stream} receiverStream - sub stream receiving events from the dispatcher
+ * @returns {Stream} receiverStream
+ */
+const joinStreams = (dispatcherStream, receiverStream) => {
+ dispatcherStream.on.value(receiverStream.push)
+
+ receiverStream.on.end(() => {
+ dispatcherStream.off.value(receiverStream.push)
+ })
+
+ return receiverStream
+}
+
+/**
+ * Error handling function
+ * @param {Error} error - error to catch
+ * @returns {void}
+ */
+/* c8 ignore start */
+const panic = error => {
+ if (defaults.silentErrors) return
+
+ throw new Error(error)
+}
+/* c8 ignore stop */
+
+// make sure that the router will always receive strings params
+const filterStrings = str => isString(str) ? str : erre.cancel()
+
+// create the streaming router
+export const router = erre(filterStrings).on.error(panic) // cast the values of this stream always to string
+
+/**
+ * Merge the user options with the defaults
+ * @param {Object} options - custom user options
+ * @returns {Object} options object merged with defaults
+ */
+const mergeOptions = options => ({...defaults, ...options})
+
+/* @type {object} general configuration object */
+export const defaults = {
+ base: 'https://localhost',
+ silentErrors: false,
+ // pathToRegexp options
+ sensitive: false,
+ strict: false,
+ end: true,
+ start: true,
+ delimiter: '/#?',
+ encode: undefined,
+ endsWith: undefined,
+ prefixes: './'
+}
+
+/**
+ * Configure the router options overriding the defaults
+ * @param {Object} options - custom user options to override
+ * @returns {Object} new defaults
+ */
+export const configure = (options) => {
+ Object.entries(options).forEach(([key, value]) => {
+ if (Object.hasOwn(defaults, key)) defaults[key] = value
+ })
+
+ return defaults
+}
+
+
+
+/* {@link https://github.com/pillarjs/path-to-regexp#usage} */
+export const toRegexp = (path, keys, options) => pathToRegexp(path, keys, mergeOptions(options))
+
+/**
+ * Convert a router entry to a real path computing the url parameters
+ * @param {string} path - router path string
+ * @param {Object} params - named matched parameters
+ * @param {Object} options - pathToRegexp options object
+ * @returns {string} computed url string
+ */
+export const toPath = (path, params, options) => compile(path, mergeOptions(options))(params)
+
+/**
+ * Parse a string path generating an object containing
+ * @param {string} path - target path
+ * @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
+ * @param {Object} options - object containing the base path
+ * @returns {URL} url object enhanced with the `match` attribute
+ */
+export const toURL = (path, pathRegExp, options = {}) => {
+ const {base} = mergeOptions(options)
+ const [, ...params] = pathRegExp.exec(path)
+ const url = parseURL(path, base)
+
+ // extend the url object adding the matched params
+ url.params = params.reduce((acc, param, index) => {
+ const key = options.keys && options.keys[index]
+ if (key) acc[key.name] = param ? decodeURIComponent(param) : param
+ return acc
+ }, {})
+
+ return url
+}
+
+/**
+ * Return true if a path will be matched
+ * @param {string} path - target path
+ * @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
+ * @returns {boolean} true if the path matches the regexp
+ */
+export const match = (path, pathRegExp) => pathRegExp.test(path)
+
+/**
+ * Factory function to create an sequence of functions to pass to erre.js
+ * This function will be used in the erre stream
+ * @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
+ * @param {Object} options - pathToRegexp options object
+ * @returns {Array} a functions array that will be used as stream pipe for erre.js
+ */
+export const createURLStreamPipe = (pathRegExp, options) => [
+ decodeURI,
+ replaceBase,
+ matchOrSkip(pathRegExp, options),
+ path => toURL(path, pathRegExp, options)
+]
+
+/**
+ * Create a fork of the main router stream
+ * @param {string} path - route to match
+ * @param {Object} options - pathToRegexp options object
+ * @returns {Stream} new route stream
+ */
+export default function createRoute(path, options) {
+ const keys = []
+ const pathRegExp = pathToRegexp(path, keys, options)
+ const URLStream = erre(...createURLStreamPipe(pathRegExp, {
+ ...options,
+ keys
+ }))
+
+ return joinStreams(router, URLStream).on.error(panic)
+}
diff --git a/node_modules/rawth/package.json b/node_modules/rawth/package.json
new file mode 100644
index 0000000..44bbb87
--- /dev/null
+++ b/node_modules/rawth/package.json
@@ -0,0 +1,59 @@
+{
+ "name": "rawth",
+ "version": "3.0.0",
+ "description": "Pure functional isomorphic router based on streams",
+ "main": "index.js",
+ "types": "index.d.ts",
+ "type": "module",
+ "exports": {
+ "types": "./index.d.ts",
+ "import": "./index.js",
+ "require": "./index.cjs"
+ },
+ "scripts": {
+ "prepublishOnly": "npm run build && npm test",
+ "lint": "eslint index.next.js test.js rollup.config.js",
+ "build": "rollup -c",
+ "cov-report": "c8 report --reporter=lcov --reporter=text",
+ "test": "npm run lint && c8 mocha test.js"
+ },
+ "files": [
+ "index.next.js",
+ "index.js",
+ "index.cjs",
+ "index.d.ts"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/GianlucaGuarini/rawth.git"
+ },
+ "keywords": [
+ "stream",
+ "streams",
+ "functional",
+ "route",
+ "URL",
+ "router"
+ ],
+ "author": "Gianluca Guarini (https://gianlucaguarini.com)",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/GianlucaGuarini/rawth/issues"
+ },
+ "homepage": "https://github.com/GianlucaGuarini/rawth#readme",
+ "devDependencies": {
+ "@gianlucaguarini/eslint-config": "^2.0.0",
+ "@rollup/plugin-commonjs": "^25.0.4",
+ "@rollup/plugin-node-resolve": "^15.2.1",
+ "c8": "^8.0.1",
+ "chai": "^4.3.10",
+ "coveralls": "^3.1.1",
+ "eslint": "^8.50.0",
+ "mocha": "^10.2.0",
+ "rollup": "^3.29.4"
+ },
+ "dependencies": {
+ "erre": "^3.0.1",
+ "path-to-regexp": "^6.2.1"
+ }
+}
diff --git a/node_modules/ruit/LICENSE b/node_modules/ruit/LICENSE
new file mode 100644
index 0000000..74e6791
--- /dev/null
+++ b/node_modules/ruit/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Gianluca Guarini
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/ruit/README.md b/node_modules/ruit/README.md
new file mode 100644
index 0000000..9a8ef60
--- /dev/null
+++ b/node_modules/ruit/README.md
@@ -0,0 +1,114 @@
+
+
+Functional tasks serialization mini script (0.3kb)
+
+[![Build Status][travis-image]][travis-url]
+
+[![NPM version][npm-version-image]][npm-url]
+[![NPM downloads][npm-downloads-image]][npm-url]
+[![MIT License][license-image]][license-url]
+
+## Installation
+
+```js
+import ruit from 'ruit'
+```
+
+[travis-image]: https://img.shields.io/travis/GianlucaGuarini/ruit.svg?style=flat-square
+
+[travis-url]: https://travis-ci.org/GianlucaGuarini/ruit
+
+[license-image]: http://img.shields.io/badge/license-MIT-000000.svg?style=flat-square
+
+[license-url]: LICENSE.txt
+
+[npm-version-image]: http://img.shields.io/npm/v/ruit.svg?style=flat-square
+
+[npm-downloads-image]: http://img.shields.io/npm/dm/ruit.svg?style=flat-square
+
+[npm-url]: https://npmjs.org/package/ruit
+
+## API
+
+
+
+### ruit
+
+Serialize a list of sync and async tasks from left to right
+
+**Parameters**
+
+- `tasks` **any** list of tasks to process sequentially
+
+**Examples**
+
+```javascript
+const curry = f => a => b => f(a, b)
+const add = (a, b) => a + b
+
+const addOne = curry(add)(1)
+
+const squareAsync = (num) => {
+ return new Promise(r => {
+ setTimeout(r, 500, num * 2)
+ })
+}
+
+// a -> a + a -> a * 2
+// basically from left to right: 1 => 1 + 1 => 2 * 2
+ruit(1, addOne, squareAsync).then(result => console.log(result)) // 4
+```
+
+Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** a promise containing the result of the whole chain
+
+#### cancel
+
+Helper that can be returned by ruit function to cancel the tasks chain
+
+**Examples**
+
+```javascript
+ruit(
+ 100,
+ num => Math.random() * num
+ num => num > 50 ? ruit.cancel() : num
+ num => num - 2
+).then(result => {
+ console.log(result) // here we will get only number lower than 50
+})
+```
+
+Returns **[Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)** internal private constant
+
+#### compose
+
+The same as ruit() but with the arguments inverted from right to left
+
+**Parameters**
+
+- `tasks` **any** list of tasks to process sequentially
+
+**Examples**
+
+```javascript
+const curry = f => a => b => f(a, b)
+const add = (a, b) => a + b
+
+const addOne = curry(add)(1)
+
+const squareAsync = (num) => {
+ return new Promise(r => {
+ setTimeout(r, 500, num * 2)
+ })
+}
+
+// a -> a + a -> a * 2
+// basically from right to left: 1 => 1 + 1 => 2 * 2
+ruit.compose(squareAsync, addOne, 1).then(result => console.log(result)) // 4
+```
+
+Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** a promise containing the result of the whole chain
+
+# Ruit meaning
+
+`ruit` comes from the `ruere` latin verb that means `It falls`, It expresses properly the essence of this script and sounds also similar to `run it`
diff --git a/node_modules/ruit/index.js b/node_modules/ruit/index.js
new file mode 100644
index 0000000..73a3845
--- /dev/null
+++ b/node_modules/ruit/index.js
@@ -0,0 +1,106 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global.ruit = factory());
+}(this, (function () { 'use strict';
+
+ /**
+ * Cancel token
+ * @private
+ * @type { Symbol }
+ */
+ var CANCEL = Symbol();
+
+ /**
+ * Helper that can be returned by ruit function to cancel the tasks chain
+ * @returns { Symbol } internal private constant
+ * @example
+ *
+ * ruit(
+ * 100,
+ * num => Math.random() * num
+ * num => num > 50 ? ruit.cancel() : num
+ * num => num - 2
+ * ).then(result => {
+ * console.log(result) // here we will get only number lower than 50
+ * })
+ *
+ */
+ ruit.cancel = function () { return CANCEL; };
+
+ /**
+ * The same as ruit() but with the arguments inverted from right to left
+ * @param { * } tasks - list of tasks to process sequentially
+ * @returns { Promise } a promise containing the result of the whole chain
+ * @example
+ *
+ * const curry = f => a => b => f(a, b)
+ * const add = (a, b) => a + b
+ *
+ * const addOne = curry(add)(1)
+ *
+ * const squareAsync = (num) => {
+ * return new Promise(r => {
+ * setTimeout(r, 500, num * 2)
+ * })
+ * }
+ *
+ * // a -> a + a -> a * 2
+ * // basically from right to left: 1 => 1 + 1 => 2 * 2
+ * ruit.compose(squareAsync, addOne, 1).then(result => console.log(result)) // 4
+ */
+ ruit.compose = function () {
+ var tasks = [], len = arguments.length;
+ while ( len-- ) tasks[ len ] = arguments[ len ];
+
+ return ruit.apply(void 0, tasks.reverse());
+ };
+
+ /**
+ * Serialize a list of sync and async tasks from left to right
+ * @param { * } tasks - list of tasks to process sequentially
+ * @returns { Promise } a promise containing the result of the whole chain
+ * @example
+ *
+ * const curry = f => a => b => f(a, b)
+ * const add = (a, b) => a + b
+ *
+ * const addOne = curry(add)(1)
+ *
+ * const squareAsync = (num) => {
+ * return new Promise(r => {
+ * setTimeout(r, 500, num * 2)
+ * })
+ * }
+ *
+ * // a -> a + a -> a * 2
+ * // basically from left to right: 1 => 1 + 1 => 2 * 2
+ * ruit(1, addOne, squareAsync).then(result => console.log(result)) // 4
+ */
+ function ruit() {
+ var tasks = [], len = arguments.length;
+ while ( len-- ) tasks[ len ] = arguments[ len ];
+
+ return new Promise(function (resolve, reject) {
+ return (function run(queue, result) {
+ if (!queue.length) { return resolve(result) }
+
+ var task = queue[0];
+ var rest = queue.slice(1);
+ var value = typeof task === 'function' ? task(result) : task;
+ var done = function (v) { return run(rest, v); };
+
+ // check against nil values
+ if (value != null) {
+ if (value === CANCEL) { return }
+ if (value.then) { return value.then(done, reject) }
+ }
+
+ return Promise.resolve(done(value))
+ })(tasks)
+ })
+ }
+
+ return ruit;
+
+})));
diff --git a/node_modules/ruit/index.next.js b/node_modules/ruit/index.next.js
new file mode 100644
index 0000000..e8a3b6f
--- /dev/null
+++ b/node_modules/ruit/index.next.js
@@ -0,0 +1,87 @@
+/**
+ * Cancel token
+ * @private
+ * @type { Symbol }
+ */
+const CANCEL = Symbol()
+
+/**
+ * Helper that can be returned by ruit function to cancel the tasks chain
+ * @returns { Symbol } internal private constant
+ * @example
+ *
+ * ruit(
+ * 100,
+ * num => Math.random() * num
+ * num => num > 50 ? ruit.cancel() : num
+ * num => num - 2
+ * ).then(result => {
+ * console.log(result) // here we will get only number lower than 50
+ * })
+ *
+ */
+ruit.cancel = () => CANCEL
+
+/**
+ * The same as ruit() but with the arguments inverted from right to left
+ * @param { * } tasks - list of tasks to process sequentially
+ * @returns { Promise } a promise containing the result of the whole chain
+ * @example
+ *
+ * const curry = f => a => b => f(a, b)
+ * const add = (a, b) => a + b
+ *
+ * const addOne = curry(add)(1)
+ *
+ * const squareAsync = (num) => {
+ * return new Promise(r => {
+ * setTimeout(r, 500, num * 2)
+ * })
+ * }
+ *
+ * // a -> a + a -> a * 2
+ * // basically from right to left: 1 => 1 + 1 => 2 * 2
+ * ruit.compose(squareAsync, addOne, 1).then(result => console.log(result)) // 4
+ */
+ruit.compose = (...tasks) => ruit(...tasks.reverse())
+
+/**
+ * Serialize a list of sync and async tasks from left to right
+ * @param { * } tasks - list of tasks to process sequentially
+ * @returns { Promise } a promise containing the result of the whole chain
+ * @example
+ *
+ * const curry = f => a => b => f(a, b)
+ * const add = (a, b) => a + b
+ *
+ * const addOne = curry(add)(1)
+ *
+ * const squareAsync = (num) => {
+ * return new Promise(r => {
+ * setTimeout(r, 500, num * 2)
+ * })
+ * }
+ *
+ * // a -> a + a -> a * 2
+ * // basically from left to right: 1 => 1 + 1 => 2 * 2
+ * ruit(1, addOne, squareAsync).then(result => console.log(result)) // 4
+ */
+export default function ruit(...tasks) {
+ return new Promise((resolve, reject) => {
+ return (function run(queue, result) {
+ if (!queue.length) return resolve(result)
+
+ const [task, ...rest] = queue
+ const value = typeof task === 'function' ? task(result) : task
+ const done = v => run(rest, v)
+
+ // check against nil values
+ if (value != null) {
+ if (value === CANCEL) return
+ if (value.then) return value.then(done, reject)
+ }
+
+ return Promise.resolve(done(value))
+ })(tasks)
+ })
+}
\ No newline at end of file
diff --git a/node_modules/ruit/package.json b/node_modules/ruit/package.json
new file mode 100644
index 0000000..16928c6
--- /dev/null
+++ b/node_modules/ruit/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "ruit",
+ "version": "1.0.4",
+ "description": "Tasks serialization minilibrary",
+ "main": "index.js",
+ "jsnext:main": "index.next.js",
+ "module": "index.next.js",
+ "scripts": {
+ "prepublish": "npm run build && npm test",
+ "lint": "eslint index.next.js test.js rollup.config.js",
+ "build": "rollup -c",
+ "doc": "documentation readme index.next.js -s API",
+ "test": "npm run lint && mocha test.js"
+ },
+ "files": [
+ "index.js",
+ "index.next.js"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/gianlucaguarini/ruit.git"
+ },
+ "keywords": [
+ "series",
+ "promises",
+ "flow",
+ "functional",
+ "composition",
+ "tasks"
+ ],
+ "author": "Gianluca Guarini (http://gianlucaguarini.com)",
+ "license": "MIT",
+ "devDependencies": {
+ "@gianlucaguarini/eslint-config": "^2.0.0",
+ "documentation": "^7.1.0",
+ "eslint": "^4.19.1",
+ "mocha": "^5.2.0",
+ "rollup": "^0.59.4",
+ "rollup-plugin-buble": "^0.19.2"
+ },
+ "bugs": {
+ "url": "https://github.com/gianlucaguarini/ruit/issues"
+ },
+ "homepage": "https://github.com/gianlucaguarini/ruit#readme",
+ "dependencies": {}
+}
diff --git a/package-lock.json b/package-lock.json
index d7f0328..74edacc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,14 +5,105 @@
"packages": {
"": {
"dependencies": {
+ "@riotjs/route": "^10.0.0",
"leaflet": "^1.9.4"
}
},
+ "node_modules/@riotjs/route": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@riotjs/route/-/route-10.0.0.tgz",
+ "integrity": "sha512-NQ9JfIzq/itFthEbCS7GqaVEJ+yjgMqIEZcP2QbiHALcMjyeaR1CacGMMd44e9Gi+Y+N+kOebpTVw2QczTAiqg==",
+ "license": "MIT",
+ "dependencies": {
+ "@riotjs/util": "^10.0.0",
+ "bianco.attr": "^1.1.1",
+ "bianco.events": "^1.1.1",
+ "bianco.query": "^1.1.4",
+ "cumpa": "^2.0.1",
+ "rawth": "^3.0.0"
+ }
+ },
+ "node_modules/@riotjs/util": {
+ "version": "10.1.2",
+ "resolved": "https://registry.npmjs.org/@riotjs/util/-/util-10.1.2.tgz",
+ "integrity": "sha512-K85suj+5YItWHB5N6LO1uMJNH6ZMBl8FxGH2xDb6dl8V3EBlLuQaPQGVzp3SOKKqeqcxJH3o5UHHIgjc2I8YrA==",
+ "license": "MIT"
+ },
+ "node_modules/bianco.attr": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/bianco.attr/-/bianco.attr-1.1.1.tgz",
+ "integrity": "sha512-fTjfPnnGYiCVbe5UltC/LsDRtJE+MjmadtL749CMIfCwjl18sdbCkaQ7cgtSao6iC9ZJC8Pzw0rjMdIuA6mK1g==",
+ "license": "MIT",
+ "dependencies": {
+ "bianco.dom-to-array": "^1.1.0"
+ }
+ },
+ "node_modules/bianco.dom-to-array": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/bianco.dom-to-array/-/bianco.dom-to-array-1.1.0.tgz",
+ "integrity": "sha512-IWUgplQRhJSZh+7PgD/my5+X27PXNUFdcHPosOYz39a/iFF8Wl9d0N/mOArdR7Zgr3J0Q9pKVk7nO6W+7XZwBg==",
+ "license": "MIT"
+ },
+ "node_modules/bianco.events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/bianco.events/-/bianco.events-1.1.1.tgz",
+ "integrity": "sha512-Ja7oY4xThYgsmfS+JltOnzdAvqP90DVXjbXab0lwrygJdCVRoL0Q4SkEKVMnN1VqNfDtxIUKNlubEUVNp00H7A==",
+ "license": "MIT",
+ "dependencies": {
+ "bianco.dom-to-array": "^1.1.0"
+ }
+ },
+ "node_modules/bianco.query": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/bianco.query/-/bianco.query-1.1.4.tgz",
+ "integrity": "sha512-jUu8l484ckacCBmxN0gYLZ4Ge5aMfReL+aYNiC81s37s8+l0+rn9pnQayEgQtMHGlnL8ejd+x5U2PKpo0rvQzw==",
+ "license": "MIT",
+ "dependencies": {
+ "bianco.dom-to-array": "^1.1.0"
+ }
+ },
+ "node_modules/cumpa": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/cumpa/-/cumpa-2.0.1.tgz",
+ "integrity": "sha512-8oBF1cSWkgYq0ZsLP9iiLLZDicIh1eYM8WLicRhaSLMrdtjEf9A3DgMYMxB/i/xgVUZGxPVD/hrwVzx/pjdmmw==",
+ "license": "MIT"
+ },
+ "node_modules/erre": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/erre/-/erre-3.0.1.tgz",
+ "integrity": "sha512-NoexRasUiWU1CcBMh997iybzdKRw4RPhjjiVjPwh1h+aK0PglsR6+7A3osXP5829hXNnarn9Yr1Zi9ThwwV4aA==",
+ "license": "MIT",
+ "dependencies": {
+ "ruit": "^1.0.4"
+ }
+ },
"node_modules/leaflet": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
"license": "BSD-2-Clause"
+ },
+ "node_modules/path-to-regexp": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
+ "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
+ "license": "MIT"
+ },
+ "node_modules/rawth": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/rawth/-/rawth-3.0.0.tgz",
+ "integrity": "sha512-712WxtKAVEhtFm/4keDUefyjxAZR/jKrFR8ownCdjnFUxJstyigv3LBo3Shtd5VPC/p6r5gd6jY0bnAfPSol9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "erre": "^3.0.1",
+ "path-to-regexp": "^6.2.1"
+ }
+ },
+ "node_modules/ruit": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/ruit/-/ruit-1.0.4.tgz",
+ "integrity": "sha512-eiHVb18DQ24Of/fdJmZCysw6X21IIyed5c87eAW95KQY5TvTfh6SR9pCkAowciyvhW1Bhm3RXuRX6eILKl+49w==",
+ "license": "MIT"
}
}
}
diff --git a/package.json b/package.json
index 0993804..f6b6797 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,6 @@
{
"dependencies": {
+ "@riotjs/route": "^10.0.0",
"leaflet": "^1.9.4"
}
}
diff --git a/parcoursup-app/src/components/page-details.riot b/parcoursup-app/src/components/page-details.riot
new file mode 100644
index 0000000..237d186
--- /dev/null
+++ b/parcoursup-app/src/components/page-details.riot
@@ -0,0 +1,52 @@
+
+
+
+
+
+
{ state.formation.fil_lib_voe_acc }
+
+
{ state.formation.g_ea_lib_vx }
+
+
{ state.formation.ville_etab } ({ state.formation.dep_lib })
+
+
Taux d'accès : { state.formation.taux_acces_ens }%
+
+
Capacité : { state.formation.capa_fin } places
+
+
Candidatures : { state.formation.voe_tot }
+
+
Admis : { state.formation.acc_tot }
+
+
+
+
+
+
+ Chargement...
+
+
+
+
+
+
+
\ No newline at end of file