@quantiya/codevibe-claude-plugin 1.0.36 → 1.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/bin/codevibe-claude +17 -3
  3. package/dist/server.js +13 -13
  4. package/hooks/stop.sh +30 -10
  5. package/node_modules/@quantiya/codevibe-core/dist/auth/auth-telemetry.d.ts +56 -0
  6. package/node_modules/@quantiya/codevibe-core/dist/index.js +30 -30
  7. package/node_modules/@quantiya/codevibe-core/dist/keychain/keychain-manager.d.ts +16 -2
  8. package/node_modules/@quantiya/codevibe-core/dist/session/session-rekey.d.ts +40 -0
  9. package/node_modules/@quantiya/codevibe-core/dist/session/session-resume.d.ts +1 -0
  10. package/node_modules/@quantiya/codevibe-core/package.json +1 -1
  11. package/node_modules/body-parser/README.md +18 -18
  12. package/node_modules/body-parser/index.js +6 -15
  13. package/node_modules/body-parser/lib/read.js +17 -20
  14. package/node_modules/body-parser/lib/types/json.js +8 -16
  15. package/node_modules/body-parser/lib/types/raw.js +3 -4
  16. package/node_modules/body-parser/lib/types/text.js +3 -4
  17. package/node_modules/body-parser/lib/types/urlencoded.js +8 -8
  18. package/node_modules/body-parser/lib/utils.js +11 -9
  19. package/node_modules/body-parser/package.json +2 -2
  20. package/node_modules/content-disposition/README.md +7 -8
  21. package/node_modules/content-disposition/index.js +118 -40
  22. package/node_modules/content-disposition/package.json +8 -11
  23. package/node_modules/express/Readme.md +39 -29
  24. package/node_modules/express/lib/application.js +1 -1
  25. package/node_modules/express/lib/request.js +5 -6
  26. package/node_modules/express/lib/response.js +14 -0
  27. package/node_modules/express/lib/utils.js +3 -1
  28. package/node_modules/express/package.json +6 -5
  29. package/node_modules/finalhandler/HISTORY.md +6 -0
  30. package/node_modules/finalhandler/README.md +26 -23
  31. package/node_modules/finalhandler/package.json +13 -9
  32. package/node_modules/graphql/execution/execute.d.ts +14 -1
  33. package/node_modules/graphql/execution/execute.js +63 -13
  34. package/node_modules/graphql/execution/execute.mjs +63 -13
  35. package/node_modules/graphql/execution/subscribe.js +1 -0
  36. package/node_modules/graphql/execution/subscribe.mjs +2 -0
  37. package/node_modules/graphql/execution/values.js +4 -4
  38. package/node_modules/graphql/execution/values.mjs +4 -4
  39. package/node_modules/graphql/index.d.ts +1 -0
  40. package/node_modules/graphql/language/ast.d.ts +10 -1
  41. package/node_modules/graphql/language/ast.js +8 -1
  42. package/node_modules/graphql/language/ast.mjs +8 -1
  43. package/node_modules/graphql/language/directiveLocation.d.ts +1 -0
  44. package/node_modules/graphql/language/directiveLocation.js +1 -0
  45. package/node_modules/graphql/language/directiveLocation.mjs +1 -0
  46. package/node_modules/graphql/language/index.d.ts +1 -0
  47. package/node_modules/graphql/language/kinds.d.ts +1 -0
  48. package/node_modules/graphql/language/kinds.js +1 -0
  49. package/node_modules/graphql/language/kinds.mjs +1 -0
  50. package/node_modules/graphql/language/parser.d.ts +14 -0
  51. package/node_modules/graphql/language/parser.js +33 -0
  52. package/node_modules/graphql/language/parser.mjs +33 -0
  53. package/node_modules/graphql/language/predicates.js +3 -1
  54. package/node_modules/graphql/language/predicates.mjs +5 -1
  55. package/node_modules/graphql/language/printer.js +13 -1
  56. package/node_modules/graphql/language/printer.mjs +13 -1
  57. package/node_modules/graphql/package.json +1 -1
  58. package/node_modules/graphql/type/directives.d.ts +9 -1
  59. package/node_modules/graphql/type/directives.js +10 -1
  60. package/node_modules/graphql/type/directives.mjs +10 -1
  61. package/node_modules/graphql/type/introspection.js +24 -1
  62. package/node_modules/graphql/type/introspection.mjs +24 -1
  63. package/node_modules/graphql/utilities/buildASTSchema.js +4 -0
  64. package/node_modules/graphql/utilities/buildASTSchema.mjs +4 -0
  65. package/node_modules/graphql/utilities/buildClientSchema.js +1 -0
  66. package/node_modules/graphql/utilities/buildClientSchema.mjs +1 -0
  67. package/node_modules/graphql/utilities/coerceInputValue.js +2 -2
  68. package/node_modules/graphql/utilities/coerceInputValue.mjs +2 -2
  69. package/node_modules/graphql/utilities/extendSchema.js +58 -3
  70. package/node_modules/graphql/utilities/extendSchema.mjs +58 -3
  71. package/node_modules/graphql/utilities/getIntrospectionQuery.d.ts +16 -0
  72. package/node_modules/graphql/utilities/getIntrospectionQuery.js +31 -38
  73. package/node_modules/graphql/utilities/getIntrospectionQuery.mjs +31 -38
  74. package/node_modules/graphql/utilities/introspectionFromSchema.js +1 -0
  75. package/node_modules/graphql/utilities/introspectionFromSchema.mjs +1 -0
  76. package/node_modules/graphql/utilities/printSchema.js +1 -0
  77. package/node_modules/graphql/utilities/printSchema.mjs +1 -0
  78. package/node_modules/graphql/utilities/valueFromAST.js +12 -2
  79. package/node_modules/graphql/utilities/valueFromAST.mjs +12 -2
  80. package/node_modules/graphql/validation/rules/KnownDirectivesRule.js +4 -0
  81. package/node_modules/graphql/validation/rules/KnownDirectivesRule.mjs +4 -0
  82. package/node_modules/graphql/validation/rules/UniqueDirectivesPerLocationRule.js +12 -0
  83. package/node_modules/graphql/validation/rules/UniqueDirectivesPerLocationRule.mjs +12 -0
  84. package/node_modules/graphql/validation/rules/ValuesOfCorrectTypeRule.js +5 -11
  85. package/node_modules/graphql/validation/rules/ValuesOfCorrectTypeRule.mjs +5 -11
  86. package/node_modules/graphql/validation/validate.js +12 -0
  87. package/node_modules/graphql/validation/validate.mjs +13 -2
  88. package/node_modules/graphql/version.js +2 -2
  89. package/node_modules/graphql/version.mjs +2 -2
  90. package/node_modules/hasown/CHANGELOG.md +11 -0
  91. package/node_modules/hasown/eslint.config.mjs +6 -0
  92. package/node_modules/hasown/index.d.ts +1 -0
  93. package/node_modules/hasown/package.json +14 -14
  94. package/node_modules/iconv-lite/lib/index.d.ts +114 -26
  95. package/node_modules/iconv-lite/lib/index.js +39 -40
  96. package/node_modules/iconv-lite/package.json +13 -2
  97. package/node_modules/iconv-lite/types/encodings.d.ts +423 -0
  98. package/node_modules/node-abi/abi_registry.json +10 -3
  99. package/node_modules/{semver → node-abi/node_modules/semver}/README.md +19 -4
  100. package/node_modules/{semver → node-abi/node_modules/semver}/bin/semver.js +14 -10
  101. package/node_modules/node-abi/node_modules/semver/functions/truncate.js +48 -0
  102. package/node_modules/{semver → node-abi/node_modules/semver}/index.js +2 -0
  103. package/node_modules/{semver → node-abi/node_modules/semver}/internal/re.js +1 -1
  104. package/node_modules/{semver → node-abi/node_modules/semver}/package.json +3 -3
  105. package/node_modules/{semver → node-abi/node_modules/semver}/range.bnf +5 -4
  106. package/node_modules/node-abi/package.json +1 -1
  107. package/node_modules/path-to-regexp/Readme.md +3 -3
  108. package/node_modules/path-to-regexp/dist/index.d.ts +3 -0
  109. package/node_modules/path-to-regexp/dist/index.js +215 -193
  110. package/node_modules/path-to-regexp/dist/index.js.map +1 -1
  111. package/node_modules/path-to-regexp/package.json +2 -2
  112. package/node_modules/qs/.editorconfig +1 -1
  113. package/node_modules/qs/.github/SECURITY.md +11 -0
  114. package/node_modules/qs/.github/THREAT_MODEL.md +78 -0
  115. package/node_modules/qs/CHANGELOG.md +190 -0
  116. package/node_modules/qs/README.md +29 -4
  117. package/node_modules/qs/dist/qs.js +21 -21
  118. package/node_modules/qs/eslint.config.mjs +56 -0
  119. package/node_modules/qs/lib/parse.js +94 -49
  120. package/node_modules/qs/lib/utils.js +85 -11
  121. package/node_modules/qs/package.json +10 -9
  122. package/node_modules/qs/test/parse.js +391 -13
  123. package/node_modules/qs/test/stringify.js +16 -3
  124. package/node_modules/qs/test/utils.js +173 -3
  125. package/node_modules/send/package.json +11 -8
  126. package/node_modules/serve-static/README.md +23 -23
  127. package/node_modules/serve-static/package.json +6 -3
  128. package/node_modules/side-channel-list/CHANGELOG.md +25 -4
  129. package/node_modules/side-channel-list/index.js +1 -3
  130. package/node_modules/side-channel-list/package.json +8 -8
  131. package/node_modules/side-channel-list/test/index.js +50 -0
  132. package/node_modules/uuid/dist/v35.js +3 -0
  133. package/node_modules/uuid/dist/v6.js +3 -0
  134. package/node_modules/uuid/dist-node/v35.js +3 -0
  135. package/node_modules/uuid/dist-node/v6.js +3 -0
  136. package/node_modules/uuid/package.json +1 -1
  137. package/node_modules/ws/index.js +15 -6
  138. package/node_modules/ws/lib/constants.js +1 -0
  139. package/node_modules/ws/lib/permessage-deflate.js +6 -6
  140. package/node_modules/ws/lib/websocket-server.js +10 -6
  141. package/node_modules/ws/lib/websocket.js +19 -14
  142. package/node_modules/ws/package.json +4 -3
  143. package/node_modules/ws/wrapper.mjs +14 -1
  144. package/package.json +2 -2
  145. package/node_modules/content-disposition/HISTORY.md +0 -72
  146. package/node_modules/express/History.md +0 -3858
  147. package/node_modules/hasown/.eslintrc +0 -5
  148. package/node_modules/iconv-lite/Changelog.md +0 -236
  149. package/node_modules/qs/.eslintrc +0 -39
  150. package/node_modules/send/HISTORY.md +0 -580
  151. package/node_modules/serve-static/HISTORY.md +0 -516
  152. /package/node_modules/{semver → node-abi/node_modules/semver}/LICENSE +0 -0
  153. /package/node_modules/{semver → node-abi/node_modules/semver}/classes/comparator.js +0 -0
  154. /package/node_modules/{semver → node-abi/node_modules/semver}/classes/index.js +0 -0
  155. /package/node_modules/{semver → node-abi/node_modules/semver}/classes/range.js +0 -0
  156. /package/node_modules/{semver → node-abi/node_modules/semver}/classes/semver.js +0 -0
  157. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/clean.js +0 -0
  158. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/cmp.js +0 -0
  159. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/coerce.js +0 -0
  160. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/compare-build.js +0 -0
  161. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/compare-loose.js +0 -0
  162. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/compare.js +0 -0
  163. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/diff.js +0 -0
  164. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/eq.js +0 -0
  165. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/gt.js +0 -0
  166. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/gte.js +0 -0
  167. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/inc.js +0 -0
  168. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/lt.js +0 -0
  169. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/lte.js +0 -0
  170. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/major.js +0 -0
  171. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/minor.js +0 -0
  172. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/neq.js +0 -0
  173. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/parse.js +0 -0
  174. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/patch.js +0 -0
  175. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/prerelease.js +0 -0
  176. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/rcompare.js +0 -0
  177. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/rsort.js +0 -0
  178. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/satisfies.js +0 -0
  179. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/sort.js +0 -0
  180. /package/node_modules/{semver → node-abi/node_modules/semver}/functions/valid.js +0 -0
  181. /package/node_modules/{semver → node-abi/node_modules/semver}/internal/constants.js +0 -0
  182. /package/node_modules/{semver → node-abi/node_modules/semver}/internal/debug.js +0 -0
  183. /package/node_modules/{semver → node-abi/node_modules/semver}/internal/identifiers.js +0 -0
  184. /package/node_modules/{semver → node-abi/node_modules/semver}/internal/lrucache.js +0 -0
  185. /package/node_modules/{semver → node-abi/node_modules/semver}/internal/parse-options.js +0 -0
  186. /package/node_modules/{semver → node-abi/node_modules/semver}/preload.js +0 -0
  187. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/gtr.js +0 -0
  188. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/intersects.js +0 -0
  189. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/ltr.js +0 -0
  190. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/max-satisfying.js +0 -0
  191. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/min-satisfying.js +0 -0
  192. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/min-version.js +0 -0
  193. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/outside.js +0 -0
  194. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/simplify.js +0 -0
  195. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/subset.js +0 -0
  196. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/to-comparators.js +0 -0
  197. /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/valid.js +0 -0
  198. /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/index.js +0 -0
  199. /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/license +0 -0
  200. /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/package.json +0 -0
  201. /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/readme.md +0 -0
@@ -134,6 +134,9 @@ export type Path = string | TokenData;
134
134
  * Transform a path into a match function.
135
135
  */
136
136
  export declare function match<P extends ParamData>(path: Path | Path[], options?: MatchOptions & ParseOptions): MatchFunction<P>;
137
+ /**
138
+ * Transform a path into a regular expression and capture keys.
139
+ */
137
140
  export declare function pathToRegexp(path: Path | Path[], options?: PathToRegexpOptions & ParseOptions): {
138
141
  regexp: RegExp;
139
142
  keys: Keys;
@@ -10,19 +10,7 @@ const DEFAULT_DELIMITER = "/";
10
10
  const NOOP_VALUE = (value) => value;
11
11
  const ID_START = /^[$_\p{ID_Start}]$/u;
12
12
  const ID_CONTINUE = /^[$\u200c\u200d\p{ID_Continue}]$/u;
13
- const SIMPLE_TOKENS = {
14
- // Groups.
15
- "{": "{",
16
- "}": "}",
17
- // Reserved.
18
- "(": "(",
19
- ")": ")",
20
- "[": "[",
21
- "]": "]",
22
- "+": "+",
23
- "?": "?",
24
- "!": "!",
25
- };
13
+ const ID = /^[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*$/u;
26
14
  /**
27
15
  * Escape text for stringify to path.
28
16
  */
@@ -65,96 +53,91 @@ exports.PathError = PathError;
65
53
  function parse(str, options = {}) {
66
54
  const { encodePath = NOOP_VALUE } = options;
67
55
  const chars = [...str];
68
- const tokens = [];
69
56
  let index = 0;
70
- let pos = 0;
71
- function name() {
72
- let value = "";
73
- if (ID_START.test(chars[index])) {
74
- do {
75
- value += chars[index++];
76
- } while (ID_CONTINUE.test(chars[index]));
57
+ function consumeUntil(end) {
58
+ const output = [];
59
+ let path = "";
60
+ function writePath() {
61
+ if (!path)
62
+ return;
63
+ output.push({
64
+ type: "text",
65
+ value: encodePath(path),
66
+ });
67
+ path = "";
77
68
  }
78
- else if (chars[index] === '"') {
79
- let quoteStart = index;
80
- while (index++ < chars.length) {
81
- if (chars[index] === '"') {
82
- index++;
83
- quoteStart = 0;
84
- break;
85
- }
86
- // Increment over escape characters.
87
- if (chars[index] === "\\")
88
- index++;
89
- value += chars[index];
90
- }
91
- if (quoteStart) {
92
- throw new PathError(`Unterminated quote at index ${quoteStart}`, str);
69
+ while (index < chars.length) {
70
+ const value = chars[index++];
71
+ if (value === end) {
72
+ writePath();
73
+ return output;
93
74
  }
94
- }
95
- if (!value) {
96
- throw new PathError(`Missing parameter name at index ${index}`, str);
97
- }
98
- return value;
99
- }
100
- while (index < chars.length) {
101
- const value = chars[index];
102
- const type = SIMPLE_TOKENS[value];
103
- if (type) {
104
- tokens.push({ type, index: index++, value });
105
- }
106
- else if (value === "\\") {
107
- tokens.push({ type: "escape", index: index++, value: chars[index++] });
108
- }
109
- else if (value === ":") {
110
- tokens.push({ type: "param", index: index++, value: name() });
111
- }
112
- else if (value === "*") {
113
- tokens.push({ type: "wildcard", index: index++, value: name() });
114
- }
115
- else {
116
- tokens.push({ type: "char", index: index++, value });
117
- }
118
- }
119
- tokens.push({ type: "end", index, value: "" });
120
- function consumeUntil(endType) {
121
- const output = [];
122
- while (true) {
123
- const token = tokens[pos++];
124
- if (token.type === endType)
125
- break;
126
- if (token.type === "char" || token.type === "escape") {
127
- let path = token.value;
128
- let cur = tokens[pos];
129
- while (cur.type === "char" || cur.type === "escape") {
130
- path += cur.value;
131
- cur = tokens[++pos];
75
+ if (value === "\\") {
76
+ if (index === chars.length) {
77
+ throw new PathError(`Unexpected end after \\ at index ${index}`, str);
132
78
  }
133
- output.push({
134
- type: "text",
135
- value: encodePath(path),
136
- });
79
+ path += chars[index++];
137
80
  continue;
138
81
  }
139
- if (token.type === "param" || token.type === "wildcard") {
140
- output.push({
141
- type: token.type,
142
- name: token.value,
143
- });
82
+ if (value === ":" || value === "*") {
83
+ const type = value === ":" ? "param" : "wildcard";
84
+ let name = "";
85
+ if (ID_START.test(chars[index])) {
86
+ do {
87
+ name += chars[index++];
88
+ } while (ID_CONTINUE.test(chars[index]));
89
+ }
90
+ else if (chars[index] === '"') {
91
+ let quoteStart = index;
92
+ while (index < chars.length) {
93
+ if (chars[++index] === '"') {
94
+ index++;
95
+ quoteStart = 0;
96
+ break;
97
+ }
98
+ // Increment over escape characters.
99
+ if (chars[index] === "\\")
100
+ index++;
101
+ name += chars[index];
102
+ }
103
+ if (quoteStart) {
104
+ throw new PathError(`Unterminated quote at index ${quoteStart}`, str);
105
+ }
106
+ }
107
+ if (!name) {
108
+ throw new PathError(`Missing parameter name at index ${index}`, str);
109
+ }
110
+ writePath();
111
+ output.push({ type, name });
144
112
  continue;
145
113
  }
146
- if (token.type === "{") {
114
+ if (value === "{") {
115
+ writePath();
147
116
  output.push({
148
117
  type: "group",
149
118
  tokens: consumeUntil("}"),
150
119
  });
151
120
  continue;
152
121
  }
153
- throw new PathError(`Unexpected ${token.type} at index ${token.index}, expected ${endType}`, str);
122
+ if (value === "}" ||
123
+ value === "(" ||
124
+ value === ")" ||
125
+ value === "[" ||
126
+ value === "]" ||
127
+ value === "+" ||
128
+ value === "?" ||
129
+ value === "!") {
130
+ throw new PathError(`Unexpected ${value} at index ${index - 1}`, str);
131
+ }
132
+ path += value;
133
+ }
134
+ if (end) {
135
+ throw new PathError(`Unexpected end at index ${index}, expected ${end}`, str);
154
136
  }
137
+ writePath();
155
138
  return output;
156
139
  }
157
- return new TokenData(consumeUntil("end"), str);
140
+ return new TokenData(consumeUntil(""), str);
158
141
  }
159
142
  /**
160
143
  * Compile a string to a template function for the path.
@@ -164,7 +147,8 @@ function compile(path, options = {}) {
164
147
  const data = typeof path === "object" ? path : parse(path, options);
165
148
  const fn = tokensToFunction(data.tokens, delimiter, encode);
166
149
  return function path(params = {}) {
167
- const [path, ...missing] = fn(params);
150
+ const missing = [];
151
+ const path = fn(params, missing);
168
152
  if (missing.length) {
169
153
  throw new TypeError(`Missing parameters: ${missing.join(", ")}`);
170
154
  }
@@ -173,12 +157,10 @@ function compile(path, options = {}) {
173
157
  }
174
158
  function tokensToFunction(tokens, delimiter, encode) {
175
159
  const encoders = tokens.map((token) => tokenToFunction(token, delimiter, encode));
176
- return (data) => {
177
- const result = [""];
160
+ return (data, missing) => {
161
+ let result = "";
178
162
  for (const encoder of encoders) {
179
- const [value, ...extras] = encoder(data);
180
- result[0] += value;
181
- result.push(...extras);
163
+ result += encoder(data, missing);
182
164
  }
183
165
  return result;
184
166
  };
@@ -188,45 +170,51 @@ function tokensToFunction(tokens, delimiter, encode) {
188
170
  */
189
171
  function tokenToFunction(token, delimiter, encode) {
190
172
  if (token.type === "text")
191
- return () => [token.value];
173
+ return () => token.value;
192
174
  if (token.type === "group") {
193
175
  const fn = tokensToFunction(token.tokens, delimiter, encode);
194
- return (data) => {
195
- const [value, ...missing] = fn(data);
196
- if (!missing.length)
197
- return [value];
198
- return [""];
176
+ return (data, missing) => {
177
+ const len = missing.length;
178
+ const value = fn(data, missing);
179
+ if (missing.length === len)
180
+ return value;
181
+ missing.length = len; // Reset optional group.
182
+ return "";
199
183
  };
200
184
  }
201
185
  const encodeValue = encode || NOOP_VALUE;
202
186
  if (token.type === "wildcard" && encode !== false) {
203
- return (data) => {
187
+ return (data, missing) => {
204
188
  const value = data[token.name];
205
- if (value == null)
206
- return ["", token.name];
189
+ if (value == null) {
190
+ missing.push(token.name);
191
+ return "";
192
+ }
207
193
  if (!Array.isArray(value) || value.length === 0) {
208
194
  throw new TypeError(`Expected "${token.name}" to be a non-empty array`);
209
195
  }
210
- return [
211
- value
212
- .map((value, index) => {
213
- if (typeof value !== "string") {
214
- throw new TypeError(`Expected "${token.name}/${index}" to be a string`);
215
- }
216
- return encodeValue(value);
217
- })
218
- .join(delimiter),
219
- ];
196
+ let result = "";
197
+ for (let i = 0; i < value.length; i++) {
198
+ if (typeof value[i] !== "string") {
199
+ throw new TypeError(`Expected "${token.name}/${i}" to be a string`);
200
+ }
201
+ if (i > 0)
202
+ result += delimiter;
203
+ result += encodeValue(value[i]);
204
+ }
205
+ return result;
220
206
  };
221
207
  }
222
- return (data) => {
208
+ return (data, missing) => {
223
209
  const value = data[token.name];
224
- if (value == null)
225
- return ["", token.name];
210
+ if (value == null) {
211
+ missing.push(token.name);
212
+ return "";
213
+ }
226
214
  if (typeof value !== "string") {
227
215
  throw new TypeError(`Expected "${token.name}" to be a string`);
228
216
  }
229
- return [encodeValue(value)];
217
+ return encodeValue(value);
230
218
  };
231
219
  }
232
220
  /**
@@ -258,54 +246,53 @@ function match(path, options = {}) {
258
246
  return { path, params };
259
247
  };
260
248
  }
249
+ /**
250
+ * Transform a path into a regular expression and capture keys.
251
+ */
261
252
  function pathToRegexp(path, options = {}) {
262
253
  const { delimiter = DEFAULT_DELIMITER, end = true, sensitive = false, trailing = true, } = options;
263
254
  const keys = [];
264
- const flags = sensitive ? "" : "i";
265
- const sources = [];
266
- for (const input of pathsToArray(path, [])) {
267
- const data = typeof input === "object" ? input : parse(input, options);
268
- for (const tokens of flatten(data.tokens, 0, [])) {
269
- sources.push(toRegExpSource(tokens, delimiter, keys, data.originalPath));
255
+ let source = "";
256
+ let combinations = 0;
257
+ function process(path) {
258
+ if (Array.isArray(path)) {
259
+ for (const p of path)
260
+ process(p);
261
+ return;
270
262
  }
263
+ const data = typeof path === "object" ? path : parse(path, options);
264
+ flatten(data.tokens, 0, [], (tokens) => {
265
+ if (combinations >= 256) {
266
+ throw new PathError("Too many path combinations", data.originalPath);
267
+ }
268
+ if (combinations > 0)
269
+ source += "|";
270
+ source += toRegExpSource(tokens, delimiter, keys, data.originalPath);
271
+ combinations++;
272
+ });
271
273
  }
272
- let pattern = `^(?:${sources.join("|")})`;
274
+ process(path);
275
+ let pattern = `^(?:${source})`;
273
276
  if (trailing)
274
- pattern += `(?:${escape(delimiter)}$)?`;
275
- pattern += end ? "$" : `(?=${escape(delimiter)}|$)`;
276
- const regexp = new RegExp(pattern, flags);
277
- return { regexp, keys };
278
- }
279
- /**
280
- * Convert a path or array of paths into a flat array.
281
- */
282
- function pathsToArray(paths, init) {
283
- if (Array.isArray(paths)) {
284
- for (const p of paths)
285
- pathsToArray(p, init);
286
- }
287
- else {
288
- init.push(paths);
289
- }
290
- return init;
277
+ pattern += "(?:" + escape(delimiter) + "$)?";
278
+ pattern += end ? "$" : "(?=" + escape(delimiter) + "|$)";
279
+ return { regexp: new RegExp(pattern, sensitive ? "" : "i"), keys };
291
280
  }
292
281
  /**
293
282
  * Generate a flat list of sequence tokens from the given tokens.
294
283
  */
295
- function* flatten(tokens, index, init) {
296
- if (index === tokens.length) {
297
- return yield init;
298
- }
299
- const token = tokens[index];
300
- if (token.type === "group") {
301
- for (const seq of flatten(token.tokens, 0, init.slice())) {
302
- yield* flatten(tokens, index + 1, seq);
284
+ function flatten(tokens, index, result, callback) {
285
+ while (index < tokens.length) {
286
+ const token = tokens[index++];
287
+ if (token.type === "group") {
288
+ const len = result.length;
289
+ flatten(token.tokens, 0, result, (seq) => flatten(tokens, index, seq, callback));
290
+ result.length = len;
291
+ continue;
303
292
  }
293
+ result.push(token);
304
294
  }
305
- else {
306
- init.push(token);
307
- }
308
- yield* flatten(tokens, index + 1, init);
295
+ callback(result);
309
296
  }
310
297
  /**
311
298
  * Transform a flat sequence of tokens into a regular expression.
@@ -313,72 +300,111 @@ function* flatten(tokens, index, init) {
313
300
  function toRegExpSource(tokens, delimiter, keys, originalPath) {
314
301
  let result = "";
315
302
  let backtrack = "";
316
- let isSafeSegmentParam = true;
317
- for (const token of tokens) {
303
+ let wildcardBacktrack = "";
304
+ let prevCaptureType = 0;
305
+ let hasSegmentCapture = 0;
306
+ let index = 0;
307
+ function hasInSegment(index, type) {
308
+ while (index < tokens.length) {
309
+ const token = tokens[index++];
310
+ if (token.type === type)
311
+ return true;
312
+ if (token.type === "text") {
313
+ if (token.value.includes(delimiter))
314
+ break;
315
+ }
316
+ }
317
+ return false;
318
+ }
319
+ function peekText(index) {
320
+ let result = "";
321
+ while (index < tokens.length) {
322
+ const token = tokens[index++];
323
+ if (token.type !== "text")
324
+ break;
325
+ result += token.value;
326
+ }
327
+ return result;
328
+ }
329
+ while (index < tokens.length) {
330
+ const token = tokens[index++];
318
331
  if (token.type === "text") {
319
332
  result += escape(token.value);
320
333
  backtrack += token.value;
321
- isSafeSegmentParam || (isSafeSegmentParam = token.value.includes(delimiter));
334
+ if (prevCaptureType === 2)
335
+ wildcardBacktrack += token.value;
336
+ if (token.value.includes(delimiter))
337
+ hasSegmentCapture = 0;
322
338
  continue;
323
339
  }
324
340
  if (token.type === "param" || token.type === "wildcard") {
325
- if (!isSafeSegmentParam && !backtrack) {
341
+ if (prevCaptureType && !backtrack) {
326
342
  throw new PathError(`Missing text before "${token.name}" ${token.type}`, originalPath);
327
343
  }
328
344
  if (token.type === "param") {
329
- result += `(${negate(delimiter, isSafeSegmentParam ? "" : backtrack)}+)`;
345
+ result +=
346
+ hasSegmentCapture & 2 // Seen wildcard in segment.
347
+ ? `(${negate(delimiter, backtrack)}+)`
348
+ : hasInSegment(index, "wildcard") // See wildcard later in segment.
349
+ ? `(${negate(delimiter, peekText(index))}+)`
350
+ : hasSegmentCapture & 1 // Seen parameter in segment.
351
+ ? `(${negate(delimiter, backtrack)}+|${escape(backtrack)})`
352
+ : `(${negate(delimiter, "")}+)`;
353
+ hasSegmentCapture |= prevCaptureType = 1;
330
354
  }
331
355
  else {
332
- result += `([\\s\\S]+)`;
356
+ result +=
357
+ hasSegmentCapture & 2 // Seen wildcard in segment.
358
+ ? `(${negate(backtrack, "")}+)`
359
+ : wildcardBacktrack // No capture in segment, seen wildcard in path.
360
+ ? `(${negate(wildcardBacktrack, "")}+|${negate(delimiter, "")}+)`
361
+ : `([^]+)`;
362
+ wildcardBacktrack = "";
363
+ hasSegmentCapture |= prevCaptureType = 2;
333
364
  }
334
365
  keys.push(token);
335
366
  backtrack = "";
336
- isSafeSegmentParam = false;
337
367
  continue;
338
368
  }
369
+ throw new TypeError(`Unknown token type: ${token.type}`);
339
370
  }
340
371
  return result;
341
372
  }
342
373
  /**
343
- * Block backtracking on previous text and ignore delimiter string.
374
+ * Block backtracking on previous text/delimiter.
344
375
  */
345
- function negate(delimiter, backtrack) {
346
- if (backtrack.length < 2) {
347
- if (delimiter.length < 2)
348
- return `[^${escape(delimiter + backtrack)}]`;
349
- return `(?:(?!${escape(delimiter)})[^${escape(backtrack)}])`;
350
- }
351
- if (delimiter.length < 2) {
352
- return `(?:(?!${escape(backtrack)})[^${escape(delimiter)}])`;
353
- }
354
- return `(?:(?!${escape(backtrack)}|${escape(delimiter)})[\\s\\S])`;
376
+ function negate(a, b) {
377
+ if (b.length > a.length)
378
+ return negate(b, a); // Longest string first.
379
+ if (a === b)
380
+ b = ""; // Cleaner regex strings, no duplication.
381
+ if (b.length > 1)
382
+ return `(?:(?!${escape(a)}|${escape(b)})[^])`;
383
+ if (a.length > 1)
384
+ return `(?:(?!${escape(a)})[^${escape(b)}])`;
385
+ return `[^${escape(a + b)}]`;
355
386
  }
356
387
  /**
357
388
  * Stringify an array of tokens into a path string.
358
389
  */
359
- function stringifyTokens(tokens) {
390
+ function stringifyTokens(tokens, index) {
360
391
  let value = "";
361
- let i = 0;
362
- function name(value) {
363
- const isSafe = isNameSafe(value) && isNextNameSafe(tokens[i]);
364
- return isSafe ? value : JSON.stringify(value);
365
- }
366
- while (i < tokens.length) {
367
- const token = tokens[i++];
392
+ while (index < tokens.length) {
393
+ const token = tokens[index++];
368
394
  if (token.type === "text") {
369
395
  value += escapeText(token.value);
370
396
  continue;
371
397
  }
372
398
  if (token.type === "group") {
373
- value += `{${stringifyTokens(token.tokens)}}`;
399
+ value += "{" + stringifyTokens(token.tokens, 0) + "}";
374
400
  continue;
375
401
  }
376
402
  if (token.type === "param") {
377
- value += `:${name(token.name)}`;
403
+ value += ":" + stringifyName(token.name, tokens[index]);
378
404
  continue;
379
405
  }
380
406
  if (token.type === "wildcard") {
381
- value += `*${name(token.name)}`;
407
+ value += "*" + stringifyName(token.name, tokens[index]);
382
408
  continue;
383
409
  }
384
410
  throw new TypeError(`Unknown token type: ${token.type}`);
@@ -389,21 +415,17 @@ function stringifyTokens(tokens) {
389
415
  * Stringify token data into a path string.
390
416
  */
391
417
  function stringify(data) {
392
- return stringifyTokens(data.tokens);
418
+ return stringifyTokens(data.tokens, 0);
393
419
  }
394
420
  /**
395
- * Validate the parameter name contains valid ID characters.
421
+ * Stringify a parameter name, escaping when it cannot be emitted directly.
396
422
  */
397
- function isNameSafe(name) {
398
- const [first, ...rest] = name;
399
- return ID_START.test(first) && rest.every((char) => ID_CONTINUE.test(char));
400
- }
401
- /**
402
- * Validate the next token does not interfere with the current param name.
403
- */
404
- function isNextNameSafe(token) {
405
- if (token && token.type === "text")
406
- return !ID_CONTINUE.test(token.value[0]);
407
- return true;
423
+ function stringifyName(name, next) {
424
+ if (!ID.test(name))
425
+ return JSON.stringify(name);
426
+ if ((next === null || next === void 0 ? void 0 : next.type) === "text" && ID_CONTINUE.test(next.value[0])) {
427
+ return JSON.stringify(name);
428
+ }
429
+ return name;
408
430
  }
409
431
  //# sourceMappingURL=index.js.map