@suveren/gateway 0.7.4 → 0.8.0

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 (264) hide show
  1. package/content/integrations/mollie.json +103 -28
  2. package/dist/control-plane/index.mjs +248 -58
  3. package/dist/mcp-server/http.mjs +577 -124
  4. package/dist/ui/assets/index-BFnSVa9N.js +110 -0
  5. package/dist/ui/assets/{index-CkWaRck1.css → index-BYVb_0oG.css} +1 -1
  6. package/dist/ui/index.html +2 -2
  7. package/node_modules/@hap/core/dist/index.d.mts +285 -13
  8. package/node_modules/@hap/core/dist/index.d.ts +285 -13
  9. package/node_modules/@hap/core/dist/index.js +281 -13
  10. package/node_modules/@hap/core/dist/index.mjs +266 -12
  11. package/node_modules/@hap/core/package.json +4 -2
  12. package/node_modules/@hap/core/src/did-key.ts +126 -0
  13. package/node_modules/@hap/core/src/frame.ts +115 -14
  14. package/node_modules/@hap/core/src/gatekeeper.ts +26 -0
  15. package/node_modules/@hap/core/src/identity.ts +21 -5
  16. package/node_modules/@hap/core/src/index.ts +3 -0
  17. package/node_modules/@hap/core/src/mandate.ts +207 -0
  18. package/node_modules/@hap/core/src/receipt.ts +74 -0
  19. package/node_modules/@hap/core/src/types.ts +87 -5
  20. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/lib/accept.js +54 -0
  21. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/lib/charset.js +10 -34
  22. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/lib/encoding.js +9 -30
  23. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/lib/language.js +15 -36
  24. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/lib/mediaType.js +16 -134
  25. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
  26. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/README.md +71 -0
  27. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
  28. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
  29. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
  30. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type/package.json +52 -0
  31. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/package.json +16 -10
  32. package/node_modules/@types/node/README.md +1 -1
  33. package/node_modules/@types/node/buffer.buffer.d.ts +10 -5
  34. package/node_modules/@types/node/crypto.d.ts +2 -4
  35. package/node_modules/@types/node/dgram.d.ts +119 -4
  36. package/node_modules/@types/node/ffi.d.ts +1 -1
  37. package/node_modules/@types/node/fs/promises.d.ts +61 -65
  38. package/node_modules/@types/node/fs.d.ts +86 -76
  39. package/node_modules/@types/node/http.d.ts +17 -1
  40. package/node_modules/@types/node/http2.d.ts +12 -4
  41. package/node_modules/@types/node/index.d.ts +1 -0
  42. package/node_modules/@types/node/inspector.d.ts +2 -1
  43. package/node_modules/@types/node/net.d.ts +108 -16
  44. package/node_modules/@types/node/package.json +2 -2
  45. package/node_modules/@types/node/process.d.ts +52 -0
  46. package/node_modules/@types/node/quic.d.ts +246 -38
  47. package/node_modules/@types/node/sqlite.d.ts +6 -2
  48. package/node_modules/@types/node/stream/iter.d.ts +4 -4
  49. package/node_modules/@types/node/test.d.ts +36 -0
  50. package/node_modules/@types/node/tls.d.ts +24 -0
  51. package/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +5 -0
  52. package/node_modules/@types/node/ts5.6/index.d.ts +1 -0
  53. package/node_modules/@types/node/ts5.7/index.d.ts +1 -0
  54. package/node_modules/@types/node/tty.d.ts +4 -3
  55. package/node_modules/@types/node/vfs.d.ts +210 -0
  56. package/node_modules/@types/node/vm.d.ts +1 -1
  57. package/node_modules/express-rate-limit/dist/index.cjs +6 -3
  58. package/node_modules/express-rate-limit/dist/index.d.cts +11 -0
  59. package/node_modules/express-rate-limit/dist/index.d.mts +11 -0
  60. package/node_modules/express-rate-limit/dist/index.d.ts +11 -0
  61. package/node_modules/express-rate-limit/dist/index.mjs +6 -3
  62. package/node_modules/express-rate-limit/{license.md → license} +7 -6
  63. package/node_modules/express-rate-limit/package.json +5 -5
  64. package/node_modules/express-rate-limit/readme.md +1 -0
  65. package/node_modules/fast-uri/index.js +215 -47
  66. package/node_modules/fast-uri/lib/schemes.js +9 -4
  67. package/node_modules/fast-uri/lib/utils.js +396 -92
  68. package/node_modules/fast-uri/package.json +1 -1
  69. package/node_modules/fast-uri/test/component-safe-serialization.test.js +163 -0
  70. package/node_modules/fast-uri/test/equal.test.js +31 -3
  71. package/node_modules/fast-uri/test/fixtures/uri-js-parse.json +2 -0
  72. package/node_modules/fast-uri/test/ipv6-canonical.test.js +34 -0
  73. package/node_modules/fast-uri/test/ipv6-validation.test.js +124 -0
  74. package/node_modules/fast-uri/test/malformed-percent.test.js +77 -0
  75. package/node_modules/fast-uri/test/malformed-urn.test.js +61 -0
  76. package/node_modules/fast-uri/test/parse.test.js +7 -3
  77. package/node_modules/fast-uri/test/query-fragment-normalization.test.js +33 -0
  78. package/node_modules/fast-uri/test/reserved-path-normalization.test.js +109 -0
  79. package/node_modules/fast-uri/test/scheme-validation.test.js +124 -0
  80. package/node_modules/fast-uri/test/security-normalization.test.js +101 -0
  81. package/node_modules/fast-uri/test/security.test.js +75 -3
  82. package/node_modules/fast-uri/test/urn-full-input.test.js +29 -0
  83. package/node_modules/fast-uri/test/websocket-query-preservation.test.js +24 -0
  84. package/node_modules/hono/dist/cjs/client/client.js +25 -11
  85. package/node_modules/hono/dist/cjs/client/utils.js +4 -1
  86. package/node_modules/hono/dist/cjs/context.js +4 -0
  87. package/node_modules/hono/dist/cjs/helper/accepts/accepts.js +36 -2
  88. package/node_modules/hono/dist/cjs/helper/ssg/ssg.js +1 -1
  89. package/node_modules/hono/dist/cjs/helper/ssg/utils.js +30 -10
  90. package/node_modules/hono/dist/cjs/jsx/dom/render.js +2 -0
  91. package/node_modules/hono/dist/cjs/middleware/cache/index.js +1 -1
  92. package/node_modules/hono/dist/cjs/middleware/cors/index.js +1 -1
  93. package/node_modules/hono/dist/cjs/middleware/csrf/index.js +1 -1
  94. package/node_modules/hono/dist/cjs/middleware/etag/digest.js +1 -1
  95. package/node_modules/hono/dist/cjs/middleware/etag/index.js +3 -3
  96. package/node_modules/hono/dist/cjs/middleware/pretty-json/index.js +3 -1
  97. package/node_modules/hono/dist/cjs/request.js +8 -4
  98. package/node_modules/hono/dist/cjs/router/linear-router/router.js +7 -2
  99. package/node_modules/hono/dist/cjs/router/pattern-router/router.js +3 -9
  100. package/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +10 -3
  101. package/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +47 -83
  102. package/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +2 -1
  103. package/node_modules/hono/dist/cjs/router/trie-router/node.js +46 -69
  104. package/node_modules/hono/dist/cjs/router/trie-router/router.js +3 -11
  105. package/node_modules/hono/dist/cjs/router/utils.js +27 -0
  106. package/node_modules/hono/dist/cjs/utils/body.js +15 -3
  107. package/node_modules/hono/dist/cjs/utils/cookie.js +1 -1
  108. package/node_modules/hono/dist/cjs/utils/ipaddr.js +5 -3
  109. package/node_modules/hono/dist/cjs/utils/stream.js +7 -1
  110. package/node_modules/hono/dist/cjs/utils/url.js +9 -1
  111. package/node_modules/hono/dist/client/client.js +25 -11
  112. package/node_modules/hono/dist/client/utils.js +4 -1
  113. package/node_modules/hono/dist/context.js +4 -0
  114. package/node_modules/hono/dist/helper/accepts/accepts.js +36 -2
  115. package/node_modules/hono/dist/helper/ssg/ssg.js +1 -1
  116. package/node_modules/hono/dist/helper/ssg/utils.js +30 -10
  117. package/node_modules/hono/dist/jsx/dom/render.js +2 -0
  118. package/node_modules/hono/dist/middleware/cache/index.js +1 -1
  119. package/node_modules/hono/dist/middleware/cors/index.js +1 -1
  120. package/node_modules/hono/dist/middleware/csrf/index.js +1 -1
  121. package/node_modules/hono/dist/middleware/etag/digest.js +1 -1
  122. package/node_modules/hono/dist/middleware/etag/index.js +3 -3
  123. package/node_modules/hono/dist/middleware/pretty-json/index.js +3 -1
  124. package/node_modules/hono/dist/request.js +8 -4
  125. package/node_modules/hono/dist/router/linear-router/router.js +7 -2
  126. package/node_modules/hono/dist/router/pattern-router/router.js +3 -9
  127. package/node_modules/hono/dist/router/reg-exp-router/node.js +6 -2
  128. package/node_modules/hono/dist/router/reg-exp-router/router.js +53 -84
  129. package/node_modules/hono/dist/router/reg-exp-router/trie.js +2 -1
  130. package/node_modules/hono/dist/router/trie-router/node.js +46 -69
  131. package/node_modules/hono/dist/router/trie-router/router.js +3 -11
  132. package/node_modules/hono/dist/router/utils.js +5 -0
  133. package/node_modules/hono/dist/types/context.d.ts +4 -0
  134. package/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +3 -0
  135. package/node_modules/hono/dist/types/router/trie-router/node.d.ts +1 -2
  136. package/node_modules/hono/dist/types/router/trie-router/router.d.ts +0 -1
  137. package/node_modules/hono/dist/types/router/utils.d.ts +1 -0
  138. package/node_modules/hono/dist/types/utils/url.d.ts +4 -0
  139. package/node_modules/hono/dist/utils/body.js +15 -3
  140. package/node_modules/hono/dist/utils/cookie.js +1 -1
  141. package/node_modules/hono/dist/utils/ipaddr.js +5 -3
  142. package/node_modules/hono/dist/utils/stream.js +7 -1
  143. package/node_modules/hono/dist/utils/url.js +9 -1
  144. package/node_modules/hono/package.json +1 -1
  145. package/node_modules/ip-address/README.md +92 -82
  146. package/node_modules/ip-address/dist/common.d.ts +20 -0
  147. package/node_modules/ip-address/dist/common.js +36 -0
  148. package/node_modules/ip-address/dist/common.js.map +1 -1
  149. package/node_modules/ip-address/dist/ipv4.d.ts +50 -0
  150. package/node_modules/ip-address/dist/ipv4.js +75 -0
  151. package/node_modules/ip-address/dist/ipv4.js.map +1 -1
  152. package/node_modules/ip-address/dist/ipv6.d.ts +79 -10
  153. package/node_modules/ip-address/dist/ipv6.js +120 -30
  154. package/node_modules/ip-address/dist/ipv6.js.map +1 -1
  155. package/node_modules/ip-address/dist/v4/constants.d.ts +12 -0
  156. package/node_modules/ip-address/dist/v4/constants.js +40 -1
  157. package/node_modules/ip-address/dist/v4/constants.js.map +1 -1
  158. package/node_modules/ip-address/dist/v6/constants.d.ts +14 -0
  159. package/node_modules/ip-address/dist/v6/constants.js +47 -1
  160. package/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  161. package/node_modules/ip-address/package.json +1 -1
  162. package/node_modules/is-plain-object/README.md +39 -95
  163. package/node_modules/is-plain-object/dist/is-plain-object.js +0 -2
  164. package/node_modules/is-plain-object/is-plain-object.d.ts +6 -1
  165. package/node_modules/is-plain-object/package.json +8 -34
  166. package/node_modules/jose/dist/types/jwe/compact/decrypt.d.ts +7 -16
  167. package/node_modules/jose/dist/types/jwe/compact/encrypt.d.ts +10 -20
  168. package/node_modules/jose/dist/types/jwe/flattened/decrypt.d.ts +7 -16
  169. package/node_modules/jose/dist/types/jwe/flattened/encrypt.d.ts +16 -38
  170. package/node_modules/jose/dist/types/jwe/general/decrypt.d.ts +7 -16
  171. package/node_modules/jose/dist/types/jwe/general/encrypt.d.ts +19 -38
  172. package/node_modules/jose/dist/types/jwk/embedded.d.ts +3 -8
  173. package/node_modules/jose/dist/types/jwk/thumbprint.d.ts +5 -5
  174. package/node_modules/jose/dist/types/jwks/local.d.ts +6 -10
  175. package/node_modules/jose/dist/types/jwks/remote.d.ts +17 -28
  176. package/node_modules/jose/dist/types/jws/compact/sign.d.ts +5 -10
  177. package/node_modules/jose/dist/types/jws/compact/verify.d.ts +9 -18
  178. package/node_modules/jose/dist/types/jws/flattened/sign.d.ts +7 -16
  179. package/node_modules/jose/dist/types/jws/flattened/verify.d.ts +9 -18
  180. package/node_modules/jose/dist/types/jws/general/sign.d.ts +11 -21
  181. package/node_modules/jose/dist/types/jws/general/verify.d.ts +12 -21
  182. package/node_modules/jose/dist/types/jwt/decrypt.d.ts +10 -20
  183. package/node_modules/jose/dist/types/jwt/encrypt.d.ts +17 -29
  184. package/node_modules/jose/dist/types/jwt/sign.d.ts +12 -19
  185. package/node_modules/jose/dist/types/jwt/unsecured.d.ts +17 -28
  186. package/node_modules/jose/dist/types/jwt/verify.d.ts +9 -19
  187. package/node_modules/jose/dist/types/key/export.d.ts +4 -4
  188. package/node_modules/jose/dist/types/key/generate_key_pair.d.ts +6 -8
  189. package/node_modules/jose/dist/types/key/generate_secret.d.ts +4 -11
  190. package/node_modules/jose/dist/types/key/import.d.ts +10 -17
  191. package/node_modules/jose/dist/types/types.d.ts +48 -86
  192. package/node_modules/jose/dist/types/util/base64url.d.ts +2 -2
  193. package/node_modules/jose/dist/types/util/decode_jwt.d.ts +3 -10
  194. package/node_modules/jose/dist/types/util/decode_protected_header.d.ts +4 -4
  195. package/node_modules/jose/dist/types/util/errors.d.ts +26 -53
  196. package/node_modules/jose/dist/webapi/index.js +70 -32
  197. package/node_modules/jose/dist/webapi/jwe/compact/decrypt.js +7 -8
  198. package/node_modules/jose/dist/webapi/jwe/compact/encrypt.js +42 -26
  199. package/node_modules/jose/dist/webapi/jwe/flattened/decrypt.js +14 -10
  200. package/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +53 -71
  201. package/node_modules/jose/dist/webapi/jwe/general/decrypt.js +38 -49
  202. package/node_modules/jose/dist/webapi/jwe/general/encrypt.js +121 -158
  203. package/node_modules/jose/dist/webapi/jwk/embedded.js +30 -18
  204. package/node_modules/jose/dist/webapi/jwk/thumbprint.js +54 -64
  205. package/node_modules/jose/dist/webapi/jwks/local.js +49 -74
  206. package/node_modules/jose/dist/webapi/jwks/remote.js +91 -160
  207. package/node_modules/jose/dist/webapi/jws/compact/sign.js +21 -20
  208. package/node_modules/jose/dist/webapi/jws/compact/verify.js +7 -8
  209. package/node_modules/jose/dist/webapi/jws/flattened/sign.js +29 -30
  210. package/node_modules/jose/dist/webapi/jws/flattened/verify.js +21 -23
  211. package/node_modules/jose/dist/webapi/jws/general/sign.js +61 -70
  212. package/node_modules/jose/dist/webapi/jws/general/verify.js +47 -41
  213. package/node_modules/jose/dist/webapi/jwt/decrypt.js +13 -22
  214. package/node_modules/jose/dist/webapi/jwt/encrypt.js +58 -100
  215. package/node_modules/jose/dist/webapi/jwt/sign.js +18 -50
  216. package/node_modules/jose/dist/webapi/jwt/unsecured.js +34 -63
  217. package/node_modules/jose/dist/webapi/jwt/verify.js +12 -14
  218. package/node_modules/jose/dist/webapi/key/export.js +32 -37
  219. package/node_modules/jose/dist/webapi/key/generate_key_pair.js +40 -44
  220. package/node_modules/jose/dist/webapi/key/generate_secret.js +35 -39
  221. package/node_modules/jose/dist/webapi/key/import.js +52 -52
  222. package/node_modules/jose/dist/webapi/lib/asn1.js +130 -164
  223. package/node_modules/jose/dist/webapi/lib/base64.js +18 -20
  224. package/node_modules/jose/dist/webapi/lib/buffer_utils.js +34 -38
  225. package/node_modules/jose/dist/webapi/lib/content_encryption.js +79 -123
  226. package/node_modules/jose/dist/webapi/lib/crypto_key.js +24 -25
  227. package/node_modules/jose/dist/webapi/lib/deflate.js +46 -40
  228. package/node_modules/jose/dist/webapi/lib/helpers.js +40 -37
  229. package/node_modules/jose/dist/webapi/lib/invalid_key_input.js +10 -24
  230. package/node_modules/jose/dist/webapi/lib/is_key_like.js +17 -15
  231. package/node_modules/jose/dist/webapi/lib/jwe_algorithms.js +106 -93
  232. package/node_modules/jose/dist/webapi/lib/jwe_decrypt.js +210 -176
  233. package/node_modules/jose/dist/webapi/lib/jwe_encrypt.js +105 -107
  234. package/node_modules/jose/dist/webapi/lib/jwk_metadata.js +19 -0
  235. package/node_modules/jose/dist/webapi/lib/jwk_to_key.js +9 -16
  236. package/node_modules/jose/dist/webapi/lib/jws_algorithms.js +62 -61
  237. package/node_modules/jose/dist/webapi/lib/jws_sign.js +58 -72
  238. package/node_modules/jose/dist/webapi/lib/jws_verify.js +90 -103
  239. package/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +134 -185
  240. package/node_modules/jose/dist/webapi/lib/key.js +84 -121
  241. package/node_modules/jose/dist/webapi/lib/key_algorithm.js +13 -8
  242. package/node_modules/jose/dist/webapi/lib/key_descriptor.js +8 -6
  243. package/node_modules/jose/dist/webapi/lib/key_management.js +200 -225
  244. package/node_modules/jose/dist/webapi/lib/key_options.js +8 -0
  245. package/node_modules/jose/dist/webapi/lib/options.js +57 -44
  246. package/node_modules/jose/dist/webapi/lib/signing.js +18 -22
  247. package/node_modules/jose/dist/webapi/lib/type_checks.js +28 -33
  248. package/node_modules/jose/dist/webapi/util/base64url.js +26 -35
  249. package/node_modules/jose/dist/webapi/util/decode_jwt.js +32 -31
  250. package/node_modules/jose/dist/webapi/util/decode_protected_header.js +18 -23
  251. package/node_modules/jose/dist/webapi/util/errors.js +94 -84
  252. package/node_modules/jose/package.json +17 -81
  253. package/package.json +2 -2
  254. package/profiles/calendar/0.5.profile.json +190 -0
  255. package/profiles/charge/0.5.profile.json +210 -0
  256. package/profiles/customers/0.7.profile.json +157 -0
  257. package/profiles/deploy/0.9.profile.json +176 -0
  258. package/profiles/email/0.6.profile.json +208 -0
  259. package/profiles/index.json +9 -1
  260. package/profiles/publish/0.5.profile.json +186 -0
  261. package/profiles/purchase/0.5.profile.json +231 -0
  262. package/profiles/records/0.5.profile.json +117 -0
  263. package/dist/ui/assets/index-0Q2eNytX.js +0 -110
  264. package/node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/HISTORY.md +0 -114
@@ -6,6 +6,9 @@ const isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\d
6
6
  /** @type {(value: string) => boolean} */
7
7
  const isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u)
8
8
 
9
+ /** @type {(value: string) => boolean} */
10
+ const isPort = RegExp.prototype.test.bind(/^\d*$/u)
11
+
9
12
  /** @type {(value: string) => boolean} */
10
13
  const isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu)
11
14
 
@@ -13,7 +16,36 @@ const isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu)
13
16
  const isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu)
14
17
 
15
18
  /** @type {(value: string) => boolean} */
16
- const isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu)
19
+ const isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u)
20
+
21
+ /** @type {(value: string) => boolean} */
22
+ const isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u)
23
+
24
+ /** @type {(value: string) => boolean} */
25
+ const isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u)
26
+
27
+ const BYTE_HEX = new Array(256)
28
+ {
29
+ const HEX_DIGITS = '0123456789ABCDEF'
30
+ for (let i = 0; i < 256; i++) {
31
+ BYTE_HEX[i] = '%' + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 0xF]
32
+ }
33
+ }
34
+ function percentEncodeNonAscii (cp) {
35
+ if (cp < 0x800) {
36
+ return BYTE_HEX[0xC0 | (cp >> 6)] +
37
+ BYTE_HEX[0x80 | (cp & 0x3F)]
38
+ }
39
+ if (cp < 0x10000) {
40
+ return BYTE_HEX[0xE0 | (cp >> 12)] +
41
+ BYTE_HEX[0x80 | ((cp >> 6) & 0x3F)] +
42
+ BYTE_HEX[0x80 | (cp & 0x3F)]
43
+ }
44
+ return BYTE_HEX[0xF0 | (cp >> 18)] +
45
+ BYTE_HEX[0x80 | ((cp >> 12) & 0x3F)] +
46
+ BYTE_HEX[0x80 | ((cp >> 6) & 0x3F)] +
47
+ BYTE_HEX[0x80 | (cp & 0x3F)]
48
+ }
17
49
 
18
50
  /**
19
51
  * @param {Array<string>} input
@@ -46,12 +78,14 @@ function stringArrayToHexStripped (input) {
46
78
  return acc
47
79
  }
48
80
 
49
- /**
50
- * @typedef {Object} GetIPV6Result
51
- * @property {boolean} error - Indicates if there was an error parsing the IPv6 address.
52
- * @property {string} address - The parsed IPv6 address.
53
- * @property {string} [zone] - The zone identifier, if present.
54
- */
81
+ /** @type {(value: string) => boolean} */
82
+ const isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/)
83
+
84
+ /** @type {(value: string) => boolean} */
85
+ const isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/)
86
+
87
+ /** @type {(value: string) => boolean} */
88
+ const isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/)
55
89
 
56
90
  /**
57
91
  * @param {string} value
@@ -60,88 +94,104 @@ function stringArrayToHexStripped (input) {
60
94
  const nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u)
61
95
 
62
96
  /**
63
- * @param {Array<string>} buffer
97
+ * @param {string} zone
64
98
  * @returns {boolean}
65
99
  */
66
- function consumeIsZone (buffer) {
67
- buffer.length = 0
100
+ function isZoneIdentifier (zone) {
101
+ if (zone.length === 0) return false
102
+
103
+ for (let i = 0; i < zone.length; i++) {
104
+ if (isZoneCharacter(zone[i])) continue
105
+ if (zone[i] === '%' && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
106
+ i += 2
107
+ continue
108
+ }
109
+ return false
110
+ }
111
+
68
112
  return true
69
113
  }
70
114
 
71
115
  /**
72
- * @param {Array<string>} buffer
73
- * @param {Array<string>} address
74
- * @param {GetIPV6Result} output
75
- * @returns {boolean}
116
+ * Compresses the longest run of zero hextets to "::" per RFC 5952. A run of a
117
+ * single zero hextet is left uncompressed. On ties the leftmost run wins.
118
+ *
119
+ * @param {string[]} hextets
120
+ * @returns {string}
76
121
  */
77
- function consumeHextets (buffer, address, output) {
78
- if (buffer.length) {
79
- const hex = stringArrayToHexStripped(buffer)
80
- if (hex !== '') {
81
- address.push(hex)
122
+ function compressIPv6ZeroRun (hextets) {
123
+ let bestStart = -1
124
+ let bestLength = 0
125
+ let runStart = -1
126
+ let runLength = 0
127
+ for (let i = 0; i < hextets.length; i++) {
128
+ if (hextets[i] === '0') {
129
+ if (runStart === -1) runStart = i
130
+ runLength++
131
+ if (runLength > bestLength) {
132
+ bestLength = runLength
133
+ bestStart = runStart
134
+ }
82
135
  } else {
83
- output.error = true
84
- return false
136
+ runStart = -1
137
+ runLength = 0
85
138
  }
86
- buffer.length = 0
87
139
  }
88
- return true
140
+
141
+ if (bestLength < 2) return hextets.join(':')
142
+
143
+ const head = hextets.slice(0, bestStart).join(':')
144
+ const tail = hextets.slice(bestStart + bestLength).join(':')
145
+ return head + '::' + tail
89
146
  }
90
147
 
91
148
  /**
149
+ * Validates an IPv6 address against the alternatives in RFC 3986 section
150
+ * 3.2.2 and returns the same address with leading hextet zeroes removed.
151
+ * An embedded IPv4 address counts as two hextets and is only valid at the end.
152
+ *
92
153
  * @param {string} input
93
- * @returns {GetIPV6Result}
154
+ * @returns {string|undefined}
94
155
  */
95
- function getIPV6 (input) {
96
- let tokenCount = 0
97
- const output = { error: false, address: '', zone: '' }
98
- /** @type {Array<string>} */
99
- const address = []
100
- /** @type {Array<string>} */
101
- const buffer = []
102
- let endipv6Encountered = false
103
- let endIpv6 = false
104
-
105
- let consume = consumeHextets
156
+ function normalizeIPv6Address (input) {
157
+ const compression = input.indexOf('::')
158
+ if (compression !== -1 && input.indexOf('::', compression + 1) !== -1) return undefined
159
+
160
+ const left = compression === -1 ? input.split(':') : input.slice(0, compression).split(':')
161
+ const right = compression === -1 ? [] : input.slice(compression + 2).split(':')
162
+ if (compression !== -1) {
163
+ if (left.length === 1 && left[0] === '') left.length = 0
164
+ if (right.length === 1 && right[0] === '') right.length = 0
165
+ }
106
166
 
107
- for (let i = 0; i < input.length; i++) {
108
- const cursor = input[i]
109
- if (cursor === '[' || cursor === ']') { continue }
110
- if (cursor === ':') {
111
- if (endipv6Encountered === true) {
112
- endIpv6 = true
113
- }
114
- if (!consume(buffer, address, output)) { break }
115
- if (++tokenCount > 7) {
116
- // not valid
117
- output.error = true
118
- break
119
- }
120
- if (i > 0 && input[i - 1] === ':') {
121
- endipv6Encountered = true
122
- }
123
- address.push(':')
124
- continue
125
- } else if (cursor === '%') {
126
- if (!consume(buffer, address, output)) { break }
127
- // switch to zone detection
128
- consume = consumeIsZone
129
- } else {
130
- buffer.push(cursor)
167
+ const parts = left.concat(right)
168
+ let hextetCount = 0
169
+ for (let i = 0; i < parts.length; i++) {
170
+ const part = parts[i]
171
+ if (part === '') return undefined
172
+
173
+ if (part.indexOf('.') !== -1) {
174
+ if (i !== parts.length - 1 || (compression !== -1 && right.length === 0) || !isIPv4(part)) return undefined
175
+ hextetCount += 2
131
176
  continue
132
177
  }
178
+
179
+ if (!isHextet(part)) return undefined
180
+ parts[i] = parseInt(part, 16).toString(16)
181
+ hextetCount++
133
182
  }
134
- if (buffer.length) {
135
- if (consume === consumeIsZone) {
136
- output.zone = buffer.join('')
137
- } else if (endIpv6) {
138
- address.push(buffer.join(''))
139
- } else {
140
- address.push(stringArrayToHexStripped(buffer))
141
- }
183
+
184
+ if (compression === -1) {
185
+ if (hextetCount !== 8) return undefined
186
+ return compressIPv6ZeroRun(parts)
142
187
  }
143
- output.address = address.join('')
144
- return output
188
+ if (hextetCount >= 8) return undefined
189
+
190
+ // expand "::" then re-compress the longest run for a canonical result
191
+ const expanded = parts.slice(0, left.length)
192
+ for (let i = hextetCount; i < 8; i++) expanded.push('0')
193
+ for (let i = left.length; i < parts.length; i++) expanded.push(parts[i])
194
+ return compressIPv6ZeroRun(expanded)
145
195
  }
146
196
 
147
197
  /**
@@ -149,26 +199,49 @@ function getIPV6 (input) {
149
199
  * @property {string} host - The normalized host.
150
200
  * @property {string} [escapedHost] - The escaped host.
151
201
  * @property {boolean} isIPV6 - Indicates if the host is an IPv6 address.
202
+ * @property {boolean} [isIPVFuture] - Indicates if the host is an IPvFuture literal.
203
+ * @property {boolean} [error] - Indicates if a bracketed IP literal is malformed.
152
204
  */
153
205
 
154
206
  /**
207
+ * Validates and normalizes a bracketed IP literal. Raw zone separators remain
208
+ * accepted for backwards compatibility, while encoded separators and zone
209
+ * contents follow RFC 6874.
210
+ *
155
211
  * @param {string} host
156
212
  * @returns {NormalizeIPv6Result}
157
213
  */
158
214
  function normalizeIPv6 (host) {
159
- if (findToken(host, ':') < 2) { return { host, isIPV6: false } }
160
- const ipv6 = getIPV6(host)
161
-
162
- if (!ipv6.error) {
163
- let newHost = ipv6.address
164
- let escapedHost = ipv6.address
165
- if (ipv6.zone) {
166
- newHost += '%' + ipv6.zone
167
- escapedHost += '%25' + ipv6.zone
168
- }
169
- return { host: newHost, isIPV6: true, escapedHost }
170
- } else {
171
- return { host, isIPV6: false }
215
+ const bracketed = host[0] === '[' && host[host.length - 1] === ']'
216
+ const hasBracket = host[0] === '[' || host[host.length - 1] === ']'
217
+ if (hasBracket && !bracketed) return { host, isIPV6: false, error: true }
218
+
219
+ let input = bracketed ? host.slice(1, -1) : host
220
+ if (bracketed && isIPvFuture(input)) {
221
+ input = input.toLowerCase()
222
+ return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true }
223
+ }
224
+
225
+ if (findToken(input, ':') < 2) {
226
+ return { host, isIPV6: false, error: bracketed }
227
+ }
228
+
229
+ let zoneIdentifier = ''
230
+ const zoneSeparator = input.indexOf('%')
231
+ if (zoneSeparator !== -1) {
232
+ const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === '%25' ? 3 : 1
233
+ zoneIdentifier = input.slice(zoneSeparator + separatorLength)
234
+ if (!isZoneIdentifier(zoneIdentifier)) return { host, isIPV6: false, error: true }
235
+ input = input.slice(0, zoneSeparator)
236
+ }
237
+
238
+ const address = normalizeIPv6Address(input)
239
+ if (address === undefined) return { host, isIPV6: false, error: true }
240
+
241
+ return {
242
+ host: address + (zoneIdentifier ? '%' + zoneIdentifier : ''),
243
+ escapedHost: address + (zoneIdentifier ? '%25' + zoneIdentifier : ''),
244
+ isIPV6: true
172
245
  }
173
246
  }
174
247
 
@@ -294,7 +367,7 @@ function reescapeHostDelimiters (host, isIP) {
294
367
 
295
368
  /**
296
369
  * Normalizes percent escapes and optionally decodes only unreserved ASCII bytes.
297
- * Reserved delimiters such as `%2F` and `%2E` stay escaped.
370
+ * Reserved delimiters such as `%2F` stay escaped; `%2E` is unreserved.
298
371
  *
299
372
  * @param {string} input
300
373
  * @param {boolean} [decodeUnreserved=false]
@@ -343,7 +416,8 @@ function normalizePathEncoding (input) {
343
416
  let output = ''
344
417
 
345
418
  for (let i = 0; i < input.length; i++) {
346
- if (input[i] === '%' && i + 2 < input.length) {
419
+ const ch = input[i]
420
+ if (ch === '%' && i + 2 < input.length) {
347
421
  const hex = input.slice(i + 1, i + 3)
348
422
  if (isHexPair(hex)) {
349
423
  const normalizedHex = hex.toUpperCase()
@@ -360,10 +434,225 @@ function normalizePathEncoding (input) {
360
434
  }
361
435
  }
362
436
 
363
- if (isPathCharacter(input[i])) {
364
- output += input[i]
437
+ if (isPathCharacter(ch)) {
438
+ output += ch
439
+ } else {
440
+ const code = input.charCodeAt(i)
441
+ if (code < 0x80) {
442
+ output += isEscapeSafe(code) ? ch : BYTE_HEX[code]
443
+ } else if (code < 0xD800 || code > 0xDFFF) {
444
+ output += percentEncodeNonAscii(code)
445
+ } else if (code <= 0xDBFF && i + 1 < input.length) {
446
+ const low = input.charCodeAt(i + 1)
447
+ if (low >= 0xDC00 && low <= 0xDFFF) {
448
+ output += percentEncodeNonAscii(0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00))
449
+ i++
450
+ } else {
451
+ output += percentEncodeNonAscii(0xFFFD)
452
+ }
453
+ } else {
454
+ output += percentEncodeNonAscii(0xFFFD)
455
+ }
456
+ }
457
+ }
458
+
459
+ return output
460
+ }
461
+
462
+ /**
463
+ * Serializes a path without rewriting reserved data. Raw RFC 3986 path
464
+ * characters remain literal, valid escapes are preserved and uppercased, and
465
+ * everything else is UTF-8 percent-encoded. In a path-noscheme, a colon in the
466
+ * first segment must be escaped so the result cannot be parsed as a scheme.
467
+ *
468
+ * @param {string} input
469
+ * @param {boolean} [pathNoScheme=false]
470
+ * @returns {string}
471
+ */
472
+ function serializePathEncoding (input, pathNoScheme = false) {
473
+ let output = ''
474
+ let firstSegment = pathNoScheme && input[0] !== '/'
475
+
476
+ for (let i = 0; i < input.length; i++) {
477
+ const ch = input[i]
478
+ if (ch === '%' && i + 2 < input.length) {
479
+ const hex = input.slice(i + 1, i + 3)
480
+ if (isHexPair(hex)) {
481
+ output += '%' + hex.toUpperCase()
482
+ i += 2
483
+ continue
484
+ }
485
+ }
486
+
487
+ if (ch === '/') {
488
+ firstSegment = false
489
+ }
490
+
491
+ if (isPathCharacter(ch) && (ch !== ':' || !firstSegment)) {
492
+ output += ch
493
+ } else {
494
+ const code = input.charCodeAt(i)
495
+ if (code < 0x80) {
496
+ output += BYTE_HEX[code]
497
+ } else if (code < 0xD800 || code > 0xDFFF) {
498
+ output += percentEncodeNonAscii(code)
499
+ } else if (code <= 0xDBFF && i + 1 < input.length) {
500
+ const low = input.charCodeAt(i + 1)
501
+ if (low >= 0xDC00 && low <= 0xDFFF) {
502
+ output += percentEncodeNonAscii(0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00))
503
+ i++
504
+ } else {
505
+ output += percentEncodeNonAscii(0xFFFD)
506
+ }
507
+ } else {
508
+ output += percentEncodeNonAscii(0xFFFD)
509
+ }
510
+ }
511
+ }
512
+
513
+ return output
514
+ }
515
+
516
+ /**
517
+ * Percent-encodes a URI component using its RFC 3986 literal character set.
518
+ * Existing valid escapes are preserved and normalized to uppercase hex.
519
+ *
520
+ * @param {string} input
521
+ * @param {(value: string) => boolean} isAllowed
522
+ * @returns {string}
523
+ */
524
+ function encodeComponent (input, isAllowed) {
525
+ let output = ''
526
+
527
+ for (let i = 0; i < input.length; i++) {
528
+ const ch = input[i]
529
+ if (ch === '%' && i + 2 < input.length) {
530
+ const hex = input.slice(i + 1, i + 3)
531
+ if (isHexPair(hex)) {
532
+ output += '%' + hex.toUpperCase()
533
+ i += 2
534
+ continue
535
+ }
536
+ }
537
+
538
+ if (isAllowed(ch)) {
539
+ output += ch
540
+ } else {
541
+ const code = input.charCodeAt(i)
542
+ if (code < 0x80) {
543
+ output += BYTE_HEX[code]
544
+ } else if (code < 0xD800 || code > 0xDFFF) {
545
+ output += percentEncodeNonAscii(code)
546
+ } else if (code <= 0xDBFF && i + 1 < input.length) {
547
+ const low = input.charCodeAt(i + 1)
548
+ if (low >= 0xDC00 && low <= 0xDFFF) {
549
+ output += percentEncodeNonAscii(0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00))
550
+ i++
551
+ } else {
552
+ output += percentEncodeNonAscii(0xFFFD)
553
+ }
554
+ } else {
555
+ output += percentEncodeNonAscii(0xFFFD)
556
+ }
557
+ }
558
+ }
559
+
560
+ return output
561
+ }
562
+
563
+ /**
564
+ * Encodes userinfo while preserving its RFC 3986 §3.2.1 literal characters.
565
+ * In particular, authority delimiters such as `@`, `/`, `?`, and `#` are data.
566
+ *
567
+ * @param {string} input
568
+ * @returns {string}
569
+ */
570
+ function encodeUserinfo (input) {
571
+ return encodeComponent(input, isUserinfoCharacter)
572
+ }
573
+
574
+ /**
575
+ * Encodes query data using the RFC 3986 §3.4 grammar. A literal `#` must be
576
+ * escaped because it would otherwise begin the fragment component.
577
+ *
578
+ * @param {string} input
579
+ * @returns {string}
580
+ */
581
+ function encodeQuery (input) {
582
+ return encodeComponent(input, isQueryFragmentCharacter)
583
+ }
584
+
585
+ /**
586
+ * Encodes fragment data using the RFC 3986 §3.5 grammar.
587
+ *
588
+ * @param {string} input
589
+ * @returns {string}
590
+ */
591
+ function encodeFragment (input) {
592
+ return encodeComponent(input, isQueryFragmentCharacter)
593
+ }
594
+
595
+ function isEscapeSafe (cp) {
596
+ return (
597
+ (cp >= 0x30 && cp <= 0x39) ||
598
+ (cp >= 0x41 && cp <= 0x5A) ||
599
+ (cp >= 0x61 && cp <= 0x7A) ||
600
+ cp === 0x2A || cp === 0x2B || cp === 0x2D || cp === 0x2E ||
601
+ cp === 0x2F || cp === 0x40 || cp === 0x5F
602
+ )
603
+ }
604
+
605
+ /**
606
+ * Normalizes the percent-encoding of a query or fragment component.
607
+ *
608
+ * Like `normalizePathEncoding`, but uses the query/fragment character set
609
+ * (which additionally allows `?`) and decodes `.` since it has no dot-segment
610
+ * meaning outside of a path.
611
+ *
612
+ * @param {string} input
613
+ * @returns {string}
614
+ */
615
+ function normalizeQueryFragmentEncoding (input) {
616
+ let output = ''
617
+
618
+ for (let i = 0; i < input.length; i++) {
619
+ const ch = input[i]
620
+ if (ch === '%' && i + 2 < input.length) {
621
+ const hex = input.slice(i + 1, i + 3)
622
+ if (isHexPair(hex)) {
623
+ const normalizedHex = hex.toUpperCase()
624
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16))
625
+
626
+ if (isUnreserved(decoded)) {
627
+ output += decoded
628
+ } else {
629
+ output += '%' + normalizedHex
630
+ }
631
+
632
+ i += 2
633
+ continue
634
+ }
635
+ }
636
+
637
+ if (isQueryFragmentCharacter(ch)) {
638
+ output += ch
365
639
  } else {
366
- output += escape(input[i])
640
+ const code = input.charCodeAt(i)
641
+ if (code < 0x80) {
642
+ output += isEscapeSafe(code) ? ch : BYTE_HEX[code]
643
+ } else if (code < 0xD800 || code > 0xDFFF) {
644
+ output += percentEncodeNonAscii(code)
645
+ } else if (code <= 0xDBFF && i + 1 < input.length) {
646
+ const low = input.charCodeAt(i + 1)
647
+ if (low >= 0xDC00 && low <= 0xDFFF) {
648
+ output += percentEncodeNonAscii(0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00))
649
+ i++
650
+ } else {
651
+ output += percentEncodeNonAscii(0xFFFD)
652
+ }
653
+ } else {
654
+ output += percentEncodeNonAscii(0xFFFD)
655
+ }
367
656
  }
368
657
  }
369
658
 
@@ -403,15 +692,21 @@ function recomposeAuthority (component) {
403
692
  const uriTokens = []
404
693
 
405
694
  if (component.userinfo !== undefined) {
406
- uriTokens.push(component.userinfo)
695
+ uriTokens.push(encodeUserinfo(component.userinfo))
407
696
  uriTokens.push('@')
408
697
  }
409
698
 
410
699
  if (component.host !== undefined) {
411
- let host = unescape(component.host)
700
+ let host = component.host
412
701
  if (!isIPv4(host)) {
413
- const ipV6res = normalizeIPv6(host)
414
- if (ipV6res.isIPV6 === true) {
702
+ let ipV6res = normalizeIPv6(host)
703
+ if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
704
+ // Decode only unreserved bytes, once. In particular, keep %25 encoded
705
+ // so it cannot introduce a second escape during recomposition.
706
+ host = normalizePercentEncoding(host, true)
707
+ ipV6res = normalizeIPv6(host)
708
+ }
709
+ if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
415
710
  host = `[${ipV6res.escapedHost}]`
416
711
  } else {
417
712
  host = reescapeHostDelimiters(host, false)
@@ -421,8 +716,12 @@ function recomposeAuthority (component) {
421
716
  }
422
717
 
423
718
  if (typeof component.port === 'number' || typeof component.port === 'string') {
719
+ const port = String(component.port)
720
+ if (!isPort(port)) {
721
+ throw new TypeError('URI port is malformed.')
722
+ }
424
723
  uriTokens.push(':')
425
- uriTokens.push(String(component.port))
724
+ uriTokens.push(port)
426
725
  }
427
726
 
428
727
  return uriTokens.length ? uriTokens.join('') : undefined
@@ -434,6 +733,11 @@ module.exports = {
434
733
  reescapeHostDelimiters,
435
734
  normalizePercentEncoding,
436
735
  normalizePathEncoding,
736
+ serializePathEncoding,
737
+ normalizeQueryFragmentEncoding,
738
+ encodeUserinfo,
739
+ encodeQuery,
740
+ encodeFragment,
437
741
  escapePreservingEscapes,
438
742
  removeDotSegments,
439
743
  isIPv4,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fast-uri",
3
3
  "description": "Dependency-free RFC 3986 URI toolbox",
4
- "version": "3.1.5",
4
+ "version": "3.1.7",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
7
7
  "types": "types/index.d.ts",