mirror of
https://github.com/Kong/insomnia.git
synced 2026-11-02 11:05:33 -05:00
chore(deps): bump major dependencies (#10587)
* chore: bumped zod@3.25.76 to zod@4.6.5 Zod 4 treats a required z.undefined() object key as non-optional, so absent keys in the RequestCollectionSchema union discriminators failed. Wrap those keys in .optional() to keep v3 semantics. Update the deep-strict auth test to expect the unrecognized_keys issue that zod 4 reports for the strict empty-object fallback branch. * chore: bumped jsdom@25.0.1 to jsdom@30.1.2 - Clears @asamuzakjp/css-color@3.2.0 advisory (AIKIDO-2026-199800); css-color now 7.1.4. - No source changes needed: none of the jsdom 26-30 breaking changes hit the repo's jsdom tests. * chore: bumped @bufbuild/protobuf@1.10.1 to @bufbuild/protobuf@2.16.0 Moves the gRPC stack to connect v2 alongside protobuf v2 (connect-node and connect 1.7.0 -> 2.2.0). This clears the transitive undici 5.29.0 and @fastify/busboy 2.1.1 under connect-node 1.x. Source changes: - grpc.ts: createPromiseClient is removed in v2, so the reflection service is now built from a FileDescriptorProto via fromJson and createFileRegistry (proto3.makeMessageType is removed). The unary call goes through transport.unary directly because createClient cannot type a runtime-built descriptor. - grpc.ts: toBinary takes the schema (FileDescriptorSetSchema from wkt). - grpc.test.ts: mock transport uses the v2 unary signature (no service argument, method.output, fromJsonString). * chore: regenerate insomnia JSON schema for dependency bumps * test: add grpc reflection regression tests for connect v2 * test: add smoke tests for buf reflection API * fix: don't auto-send gRPC reflection API key on request open * fix: drop non-standard starts_with format from published schema
This commit is contained in:
1 parent
d370ff0a60
commit
ec7b4e1d2a
10 files changed
+832
-263
No files matched your search
Generated
+333
-201
@@ -123,23 +123,72 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/css-color": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz",
|
||||
"integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==",
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-7.1.6.tgz",
|
||||
"integrity": "sha512-jZJUZX0mR6JqnjQGb79yTYbR5WXmACmcLoFSgZk+7W+0qMJ8jWGRp9ncYvE1ihwL3dwbmfeCe6/O0rRwWTko4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@csstools/css-calc": "^2.1.3",
|
||||
"@csstools/css-color-parser": "^3.0.9",
|
||||
"@csstools/css-parser-algorithms": "^3.0.4",
|
||||
"@csstools/css-tokenizer": "^3.0.3",
|
||||
"lru-cache": "^10.4.3"
|
||||
"@csstools/css-calc": "^3.4.3",
|
||||
"@csstools/css-color-parser": "^4.2.6",
|
||||
"@csstools/css-parser-algorithms": "^4.0.2",
|
||||
"@csstools/css-tokenizer": "^4.0.2",
|
||||
"lru-cache": "^11.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/css-color/node_modules/lru-cache": {
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
||||
"license": "ISC"
|
||||
"version": "11.5.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz",
|
||||
"integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/dom-selector": {
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-10.0.3.tgz",
|
||||
"integrity": "sha512-3+777rEPsOOjoy5/sRmIzHnoRDaLpm3XWY2dmWn/N7f/XwDG0bcpnFaKL3X9FYJUbNwLmpcJC1bUYexJRxsFlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bidi-js": "^1.1.0",
|
||||
"css-tree": "^3.2.1",
|
||||
"is-potential-custom-element-name": "^1.0.1",
|
||||
"lru-cache": "^11.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/dom-selector/node_modules/css-tree": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
|
||||
"integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mdn-data": "2.27.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": {
|
||||
"version": "11.5.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz",
|
||||
"integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/dom-selector/node_modules/mdn-data": {
|
||||
"version": "2.27.1",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
|
||||
"integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/@asyncapi/specs": {
|
||||
"version": "6.11.1",
|
||||
@@ -1127,53 +1176,41 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@bufbuild/protobuf": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.10.1.tgz",
|
||||
"integrity": "sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ==",
|
||||
"license": "(Apache-2.0 AND BSD-3-Clause)"
|
||||
},
|
||||
"node_modules/@connectrpc/connect": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@connectrpc/connect/-/connect-1.7.0.tgz",
|
||||
"integrity": "sha512-iNKdJRi69YP3mq6AePRT8F/HrxWCewrhxnLMNm0vpqXAR8biwzRtO6Hjx80C6UvtKJ5sFmffQT7I4Baecz389w==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"@bufbuild/protobuf": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@connectrpc/connect-node": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@connectrpc/connect-node/-/connect-node-1.7.0.tgz",
|
||||
"integrity": "sha512-6vaPIkG/NyhxlYgytLoR9KYbPhczEboFB2OYWkA9qvUz1K7efXfeGrlRxoLtpa+r8VxyIOw73w5ktNe743nD+A==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"undici": "^5.28.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@bufbuild/protobuf": "^1.10.0",
|
||||
"@connectrpc/connect": "1.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@connectrpc/connect-node/node_modules/undici": {
|
||||
"version": "5.29.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
|
||||
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
|
||||
"node_modules/@bramus/specificity": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.3.tgz",
|
||||
"integrity": "sha512-0GEz8qJWokkUVYQYRukmkSHIFNoBH8QTreeHrAFbvz1XFYc3Y+puhMs8PQ5x8GNugiC2l5jvDBXKLbBIByeSBw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
"css-tree": "^3.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0"
|
||||
"bin": {
|
||||
"specificity": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@bramus/specificity/node_modules/css-tree": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
|
||||
"integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mdn-data": "2.27.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@bramus/specificity/node_modules/mdn-data": {
|
||||
"version": "2.27.1",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
|
||||
"integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/@csstools/color-helpers": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
|
||||
"integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==",
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.1.2.tgz",
|
||||
"integrity": "sha512-grhRy3OKmniaAEKXMjua5z/EODX0MSqBGjunw8+j/3HQjOnahs2AGhvEOIYVUWcU6ScApbhLhVrQTX8XqrMrow==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -1186,13 +1223,13 @@
|
||||
],
|
||||
"license": "MIT-0",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": ">=20.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-calc": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz",
|
||||
"integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==",
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.4.3.tgz",
|
||||
"integrity": "sha512-iex20d8CHVkyvg6B7UKV7uHnI2Bqo9g+EFfT9E0y+GvTvhZ/DwONJ+9aKb1dlqm0ZiGsL5RXjp0fCoJYnkeDjA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -1205,17 +1242,17 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-parser-algorithms": "^3.0.5",
|
||||
"@csstools/css-tokenizer": "^3.0.4"
|
||||
"@csstools/css-parser-algorithms": "^4.0.2",
|
||||
"@csstools/css-tokenizer": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-color-parser": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz",
|
||||
"integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==",
|
||||
"version": "4.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.2.6.tgz",
|
||||
"integrity": "sha512-iiPQ3iRWwnJkeEn6RIu6SJPr7hYrLz6XZ9s/QZl+2/LI5KQVjpl2fdmDSZKuD4xP6GMmMPgHFFXg6k1Wkz0Trg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -1228,21 +1265,21 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@csstools/color-helpers": "^5.1.0",
|
||||
"@csstools/css-calc": "^2.1.4"
|
||||
"@csstools/color-helpers": "^6.1.2",
|
||||
"@csstools/css-calc": "^3.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-parser-algorithms": "^3.0.5",
|
||||
"@csstools/css-tokenizer": "^3.0.4"
|
||||
"@csstools/css-parser-algorithms": "^4.0.2",
|
||||
"@csstools/css-tokenizer": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-parser-algorithms": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz",
|
||||
"integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.2.tgz",
|
||||
"integrity": "sha512-40cSKyMvK+tq4qz6Awrlye2WGuOKt3FwPgtGg6KTfbHOWNw+Rk1rzbAtZnZ6IBhsY491HLRnDXwoyBAijmmILA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -1255,16 +1292,16 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-tokenizer": "^3.0.4"
|
||||
"@csstools/css-tokenizer": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-tokenizer": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz",
|
||||
"integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.2.tgz",
|
||||
"integrity": "sha512-OoKoR0f76dCY666JlcbhmVTs2drYj1GUXZTYTcbUgJjh9Nv41aFfZ21bPQTERm5+L5cBDo466NltB2lplS5GBw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -1277,7 +1314,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": ">=20.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@customerio/cdp-analytics-browser": {
|
||||
@@ -2349,6 +2386,23 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@exodus/bytes": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.16.0.tgz",
|
||||
"integrity": "sha512-IcpW84uEn3N7ETtNZMlxKhfl6Pec8rUNGOTBtWbK1FKhJxIFAptZyVrvVRVBimAJxJCgc3PxepxkdWWG4DVzfA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@noble/hashes": "^1.8.0 || ^2.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@noble/hashes": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@exodus/schemasafe": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz",
|
||||
@@ -2371,15 +2425,6 @@
|
||||
"npm": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/busboy": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
|
||||
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/ecma402-abstract": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.6.tgz",
|
||||
@@ -3288,7 +3333,7 @@
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.2.0.tgz",
|
||||
"integrity": "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 20.19.0"
|
||||
@@ -10250,6 +10295,15 @@
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bidi-js": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.1.0.tgz",
|
||||
"integrity": "sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"require-from-string": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/bignumber.js": {
|
||||
"version": "9.3.1",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
|
||||
@@ -11628,25 +11682,6 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/cssstyle": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz",
|
||||
"integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@asamuzakjp/css-color": "^3.2.0",
|
||||
"rrweb-cssom": "^0.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/cssstyle/node_modules/rrweb-cssom": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz",
|
||||
"integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||
@@ -11693,16 +11728,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
|
||||
"integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-8.0.0.tgz",
|
||||
"integrity": "sha512-JQUCCK+/CAGbGGx618PlFZMXH81Jtj7t73CHv9dd/zVWvxgGT2zLFRjnKb+Ng46GIwcy+f7f88qd4duqllK+WQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"whatwg-mimetype": "^4.0.0",
|
||||
"whatwg-url": "^14.0.0"
|
||||
"whatwg-mimetype": "^5.0.0",
|
||||
"whatwg-url": "^17.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": "^22.14.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls/node_modules/whatwg-mimetype": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz",
|
||||
"integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/data-view-buffer": {
|
||||
@@ -15431,15 +15475,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/html-encoding-sniffer": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
|
||||
"integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-7.0.0.tgz",
|
||||
"integrity": "sha512-UikN5yr7xsCDAq87Or5or0PAlD3HJJOKVzM05az588WnpDJ4Ux7a2A53Qi6gofGg2/EtvF/H4hCi/TXfCW4Y6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"whatwg-encoding": "^3.1.1"
|
||||
"@exodus/bytes": "^1.15.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": "^22.13.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-entities": {
|
||||
@@ -16896,38 +16940,37 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jsdom": {
|
||||
"version": "25.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz",
|
||||
"integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==",
|
||||
"version": "30.1.3",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-30.1.3.tgz",
|
||||
"integrity": "sha512-hQMUPvRgN7KxsfIytDQji7bimuJeRQa6Qo5+iuiZQk5CafeRxLIA10/cG5YCBFNpD9RO3oqIiN4CO1Y44kxqXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cssstyle": "^4.1.0",
|
||||
"data-urls": "^5.0.0",
|
||||
"decimal.js": "^10.4.3",
|
||||
"form-data": "^4.0.0",
|
||||
"html-encoding-sniffer": "^4.0.0",
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
"https-proxy-agent": "^7.0.5",
|
||||
"@asamuzakjp/css-color": "^7.1.3",
|
||||
"@asamuzakjp/dom-selector": "^10.0.3",
|
||||
"@bramus/specificity": "^2.4.2",
|
||||
"@csstools/css-syntax-patches-for-csstree": "^1.1.15",
|
||||
"@exodus/bytes": "^1.16.0",
|
||||
"css-tree": "^3.2.1",
|
||||
"data-urls": "^8.0.0",
|
||||
"decimal.js": "^10.6.0",
|
||||
"html-encoding-sniffer": "^7.0.0",
|
||||
"is-potential-custom-element-name": "^1.0.1",
|
||||
"nwsapi": "^2.2.12",
|
||||
"parse5": "^7.1.2",
|
||||
"rrweb-cssom": "^0.7.1",
|
||||
"lru-cache": "^11.5.3",
|
||||
"parse5": "^8.0.1",
|
||||
"saxes": "^6.0.0",
|
||||
"symbol-tree": "^3.2.4",
|
||||
"tough-cookie": "^5.0.0",
|
||||
"w3c-xmlserializer": "^5.0.0",
|
||||
"webidl-conversions": "^7.0.0",
|
||||
"whatwg-encoding": "^3.1.1",
|
||||
"whatwg-mimetype": "^4.0.0",
|
||||
"whatwg-url": "^14.0.0",
|
||||
"ws": "^8.18.0",
|
||||
"tough-cookie": "^6.0.2",
|
||||
"undici": "^8.12.1",
|
||||
"w3c-xmlserializer": "^6.0.0",
|
||||
"webidl-conversions": "^8.0.1",
|
||||
"whatwg-mimetype": "^5.0.0",
|
||||
"whatwg-url": "^17.2.0",
|
||||
"xml-name-validator": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"canvas": "^2.11.2"
|
||||
"canvas": "^3.2.3"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"canvas": {
|
||||
@@ -16935,34 +16978,112 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/form-data": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
|
||||
"integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
|
||||
"node_modules/jsdom/node_modules/@csstools/css-syntax-patches-for-csstree": {
|
||||
"version": "1.1.15",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.15.tgz",
|
||||
"integrity": "sha512-J0u7HkVl2nzSlhsiTOp4AmwcUQ3D+mGEEKfBy/7To5/y7F2OHwyLrXfrhR0SMgr4p5Lo+eaMVSeai24zUcBIxA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT-0",
|
||||
"peerDependencies": {
|
||||
"css-tree": "^3.2.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"css-tree": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/css-tree": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
|
||||
"integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.4",
|
||||
"mime-types": "^2.1.35"
|
||||
"mdn-data": "2.27.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/entities": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz",
|
||||
"integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/lru-cache": {
|
||||
"version": "11.5.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz",
|
||||
"integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/mdn-data": {
|
||||
"version": "2.27.1",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
|
||||
"integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/jsdom/node_modules/parse5": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz",
|
||||
"integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"entities": "^8.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/tough-cookie": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
|
||||
"integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.2.tgz",
|
||||
"integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"tldts": "^6.1.32"
|
||||
"tldts": "^7.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/undici": {
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-8.12.2.tgz",
|
||||
"integrity": "sha512-XtuDWVdqTLr3NAxm2ly9/hU6kUsJOgGh1RASzMBbsw6aWCOaQzHdW+QQDfdERjfJ2V5vL5pRPa4RetO9UfivDg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/whatwg-mimetype": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz",
|
||||
"integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/jsep": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz",
|
||||
@@ -19696,12 +19817,6 @@
|
||||
"integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nwsapi": {
|
||||
"version": "2.2.23",
|
||||
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz",
|
||||
"integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/oas-kit-common": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz",
|
||||
@@ -22124,12 +22239,6 @@
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/rrweb-cssom": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz",
|
||||
"integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/rtl-css-js": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz",
|
||||
@@ -23719,12 +23828,6 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tailwind-merge": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz",
|
||||
@@ -24047,21 +24150,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tldts": {
|
||||
"version": "6.1.86",
|
||||
"resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz",
|
||||
"integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==",
|
||||
"version": "7.4.18",
|
||||
"resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.18.tgz",
|
||||
"integrity": "sha512-somxA8xKAUzlAxl0TX/jMSYIbRNFIVGnI96pVGJPeMc5BsHmfVXn6mOJT6U++ELnl04eGfzpfcEuZe8WiASkXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tldts-core": "^6.1.86"
|
||||
"tldts-core": "^7.4.18"
|
||||
},
|
||||
"bin": {
|
||||
"tldts": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tldts-core": {
|
||||
"version": "6.1.86",
|
||||
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz",
|
||||
"integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==",
|
||||
"version": "7.4.18",
|
||||
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.18.tgz",
|
||||
"integrity": "sha512-KI2PKvCmvQI/xD6ypPqkU0i7oxNXR/O58RLRaHR4svsgVUQ2JE/XC8BtMbG6PSehD27I8sZJRcC1ASnCy6lp3g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
@@ -24151,15 +24254,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
|
||||
"integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-7.0.0.tgz",
|
||||
"integrity": "sha512-BcDSDW+SIGWVOns1Zm6Yg91q9AEj7eaID0QDY9oIqJD1A8dscNwMcl9Sms2DeuWCNov1X0/oXanHGYQBSLwZsg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": "^22.14.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/truncate-utf8-bytes": {
|
||||
@@ -25571,15 +25674,15 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/w3c-xmlserializer": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
|
||||
"integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-6.0.0.tgz",
|
||||
"integrity": "sha512-4Nsy8K5Tr6SPDH9jhKJOHf7ChDrc1zufZTVSF7x72hwuEXBqxqk9G6cK+K2NRUtB3iELRJqjXb4JPDMBjMTl2Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"xml-name-validator": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/watskeburt": {
|
||||
@@ -25627,12 +25730,12 @@
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",
|
||||
"integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-encoding": {
|
||||
@@ -25658,16 +25761,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "14.2.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
|
||||
"integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
|
||||
"version": "17.3.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-17.3.0.tgz",
|
||||
"integrity": "sha512-KwOAJrpf+GTgBvcBQJcP38sMF0DsQKdwtG+TxM2pW44P6E5k0hDbWrDmyuJDIF0Uef0aQq0ZoJs+5oI+k8ddhg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tr46": "^5.1.0",
|
||||
"webidl-conversions": "^7.0.0"
|
||||
"@exodus/bytes": "^1.16.0",
|
||||
"tr46": "^7.0.0",
|
||||
"webidl-conversions": "^8.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": "^22.14.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
@@ -26184,9 +26288,9 @@
|
||||
"dependencies": {
|
||||
"@apideck/better-ajv-errors": "^0.3.6",
|
||||
"@apidevtools/swagger-parser": "12.1.0",
|
||||
"@bufbuild/protobuf": "^1.10.0",
|
||||
"@connectrpc/connect": "^1.6.1",
|
||||
"@connectrpc/connect-node": "^1.6.1",
|
||||
"@bufbuild/protobuf": "^2.16.0",
|
||||
"@connectrpc/connect": "^2.2.0",
|
||||
"@connectrpc/connect-node": "^2.2.0",
|
||||
"@customerio/cdp-analytics-browser": "^0.5.9",
|
||||
"@faker-js/faker": "^10.6.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||
@@ -26258,7 +26362,7 @@
|
||||
"isbot": "^5",
|
||||
"isomorphic-git": "1.25.7",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsdom": "^25.0.1",
|
||||
"jsdom": "^30.1.2",
|
||||
"jshint": "^2.13.6",
|
||||
"json-bigint": "^1.0.0",
|
||||
"json-order": "^1.1.3",
|
||||
@@ -26817,6 +26921,34 @@
|
||||
"@types/node-forge": "^1.3.14"
|
||||
}
|
||||
},
|
||||
"packages/insomnia/node_modules/@bufbuild/protobuf": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.16.0.tgz",
|
||||
"integrity": "sha512-FWa0sPlqYGJgpTs6OxBRcL/AW4JT0OIO+W1ajerluoTVh8CV0B7XM1qsNCRgnkSCkRCgOICKHRQlY17jrsm0+Q==",
|
||||
"license": "(Apache-2.0 AND BSD-3-Clause)"
|
||||
},
|
||||
"packages/insomnia/node_modules/@connectrpc/connect": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@connectrpc/connect/-/connect-2.2.0.tgz",
|
||||
"integrity": "sha512-M63OQ1ZFcPUm85CuewJ9G9CMV8LjzGR9935xOnXNQGSazAbwMb3x2W7vXBYM1zqrP7XFD8uxp/dUAhirclgwnQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"@bufbuild/protobuf": "^2.7.0"
|
||||
}
|
||||
},
|
||||
"packages/insomnia/node_modules/@connectrpc/connect-node": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@connectrpc/connect-node/-/connect-node-2.2.0.tgz",
|
||||
"integrity": "sha512-E6uUO6e11WdynAuBjuN+0WpHjqxEM9BNDdfDIJHcn49Esg/WxSIbn2y1KFt9XL96IJi01qdBbvubcdpBz1X3Zw==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@bufbuild/protobuf": "^2.7.0",
|
||||
"@connectrpc/connect": "2.2.0"
|
||||
}
|
||||
},
|
||||
"packages/insomnia/node_modules/@testing-library/dom": {
|
||||
"version": "10.4.1",
|
||||
"dev": true,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
type: collection.insomnia.rest/5.0
|
||||
schema_version: "5.1"
|
||||
name: gRPC Reflection API
|
||||
meta:
|
||||
id: wrk_grpc_reflection_api_smoke
|
||||
created: 1736278634829
|
||||
modified: 1736278634829
|
||||
collection:
|
||||
- url: localhost:50051
|
||||
name: ReflectionApiUnary
|
||||
meta:
|
||||
id: greq_grpc_reflection_api_smoke
|
||||
created: 1638200268776
|
||||
modified: 1669986544274
|
||||
isPrivate: false
|
||||
sortKey: -1638200268776
|
||||
body:
|
||||
text: |-
|
||||
{
|
||||
"latitude":"409146138",
|
||||
"longitude":"-746188906"
|
||||
}
|
||||
reflectionApi:
|
||||
enabled: true
|
||||
url: http://localhost:4010
|
||||
apiKey: smoke-reflection-key
|
||||
module: smoke-module
|
||||
- url: localhost:50051
|
||||
name: ReflectionApiInvalidKey
|
||||
meta:
|
||||
id: greq_grpc_reflection_api_invalid_key_smoke
|
||||
created: 1638200268776
|
||||
modified: 1669986544274
|
||||
isPrivate: false
|
||||
sortKey: -1638200268775
|
||||
body:
|
||||
text: |-
|
||||
{
|
||||
"latitude":"409146138",
|
||||
"longitude":"-746188906"
|
||||
}
|
||||
reflectionApi:
|
||||
enabled: true
|
||||
url: http://localhost:4010
|
||||
apiKey: wrong-key
|
||||
module: smoke-module
|
||||
@@ -0,0 +1,155 @@
|
||||
import express from 'express';
|
||||
|
||||
// Mock of the buf.build reflection API (Connect unary) used by getMethodsFromReflectionServer.
|
||||
// The Insomnia Connect client sends application/proto by default, so responses are encoded to match the
|
||||
// request content type (binary protobuf or JSON).
|
||||
const ROUTE_GUIDE_FILE = {
|
||||
name: 'route_guide.proto',
|
||||
package: 'routeguide',
|
||||
syntax: 'proto3',
|
||||
messageType: [
|
||||
{
|
||||
name: 'Point',
|
||||
field: [
|
||||
{ name: 'latitude', number: 1, label: 'LABEL_OPTIONAL', type: 'TYPE_INT32', jsonName: 'latitude' },
|
||||
{ name: 'longitude', number: 2, label: 'LABEL_OPTIONAL', type: 'TYPE_INT32', jsonName: 'longitude' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Feature',
|
||||
field: [
|
||||
{ name: 'name', number: 1, label: 'LABEL_OPTIONAL', type: 'TYPE_STRING', jsonName: 'name' },
|
||||
{
|
||||
name: 'location',
|
||||
number: 2,
|
||||
label: 'LABEL_OPTIONAL',
|
||||
type: 'TYPE_MESSAGE',
|
||||
typeName: '.routeguide.Point',
|
||||
jsonName: 'location',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
service: [
|
||||
{
|
||||
name: 'RouteGuide',
|
||||
method: [{ name: 'GetFeature', inputType: '.routeguide.Point', outputType: '.routeguide.Feature' }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Protobuf wire encoding for the descriptor subset above (field numbers from descriptor.proto).
|
||||
const LABEL_VALUES: Record<string, number> = { LABEL_OPTIONAL: 1, LABEL_REPEATED: 3 };
|
||||
const TYPE_VALUES: Record<string, number> = { TYPE_INT32: 5, TYPE_STRING: 9, TYPE_MESSAGE: 11 };
|
||||
|
||||
const encodeVarint = (value: number): Buffer => {
|
||||
const bytes: number[] = [];
|
||||
let rest = value;
|
||||
while (rest > 0x7f) {
|
||||
bytes.push((rest & 0x7f) | 0x80);
|
||||
rest >>>= 7;
|
||||
}
|
||||
bytes.push(rest);
|
||||
return Buffer.from(bytes);
|
||||
};
|
||||
const encodeTag = (fieldNumber: number, wireType: number) => encodeVarint((fieldNumber << 3) | wireType);
|
||||
const encodeString = (fieldNumber: number, value: string) => {
|
||||
const bytes = Buffer.from(value, 'utf8');
|
||||
return Buffer.concat([encodeTag(fieldNumber, 2), encodeVarint(bytes.length), bytes]);
|
||||
};
|
||||
const encodeInt = (fieldNumber: number, value: number) =>
|
||||
Buffer.concat([encodeTag(fieldNumber, 0), encodeVarint(value)]);
|
||||
const encodeMessage = (fieldNumber: number, body: Buffer) =>
|
||||
Buffer.concat([encodeTag(fieldNumber, 2), encodeVarint(body.length), body]);
|
||||
|
||||
type FileDescriptor = typeof ROUTE_GUIDE_FILE;
|
||||
|
||||
const encodeFileDescriptor = (file: FileDescriptor) =>
|
||||
Buffer.concat([
|
||||
encodeString(1, file.name),
|
||||
encodeString(2, file.package),
|
||||
...file.messageType.map(message =>
|
||||
encodeMessage(
|
||||
4,
|
||||
Buffer.concat([
|
||||
encodeString(1, message.name),
|
||||
...message.field.map(field =>
|
||||
encodeMessage(
|
||||
2,
|
||||
Buffer.concat([
|
||||
encodeString(1, field.name),
|
||||
encodeInt(3, field.number),
|
||||
encodeInt(4, LABEL_VALUES[field.label]),
|
||||
encodeInt(5, TYPE_VALUES[field.type]),
|
||||
...('typeName' in field ? [encodeString(6, field.typeName)] : []),
|
||||
encodeString(10, field.jsonName),
|
||||
]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
...file.service.map(service =>
|
||||
encodeMessage(
|
||||
6,
|
||||
Buffer.concat([
|
||||
encodeString(1, service.name),
|
||||
...service.method.map(method =>
|
||||
encodeMessage(
|
||||
2,
|
||||
Buffer.concat([
|
||||
encodeString(1, method.name),
|
||||
encodeString(2, method.inputType),
|
||||
encodeString(3, method.outputType),
|
||||
]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
encodeString(12, file.syntax),
|
||||
]);
|
||||
|
||||
// GetFileDescriptorSetResponse { FileDescriptorSet file_descriptor_set = 1 } where FileDescriptorSet { repeated FileDescriptorProto file = 1 }
|
||||
const encodeResponse = () => encodeMessage(1, encodeMessage(1, encodeFileDescriptor(ROUTE_GUIDE_FILE)));
|
||||
|
||||
// The Connect client only sets `module` (field 1, string) on the wire.
|
||||
const decodeModuleFromProto = (body: Buffer): string | undefined => {
|
||||
if (body[0] !== 0x0a) {
|
||||
return undefined;
|
||||
}
|
||||
const length = body[1];
|
||||
return body.subarray(2, 2 + length).toString('utf8');
|
||||
};
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.post(
|
||||
'/buf.reflect.v1beta1.FileDescriptorSetService/GetFileDescriptorSet',
|
||||
express.raw({ type: '*/*' }),
|
||||
(req, res) => {
|
||||
if (req.headers.authorization !== 'Bearer smoke-reflection-key') {
|
||||
res.status(401).json({ code: 'unauthenticated', message: 'invalid api key' });
|
||||
return;
|
||||
}
|
||||
|
||||
const body = Buffer.isBuffer(req.body) ? req.body : Buffer.alloc(0);
|
||||
const isJson = (req.headers['content-type'] ?? '').includes('json');
|
||||
const moduleName = isJson
|
||||
? (JSON.parse(body.toString('utf8') || '{}') as { module?: string }).module
|
||||
: decodeModuleFromProto(body);
|
||||
|
||||
if (moduleName !== 'smoke-module') {
|
||||
res.status(404).json({ code: 'not_found', message: 'module not found' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (isJson) {
|
||||
res.status(200).json({ fileDescriptorSet: { file: [ROUTE_GUIDE_FILE] } });
|
||||
return;
|
||||
}
|
||||
res.status(200).type('application/proto').send(encodeResponse());
|
||||
},
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -29,6 +29,7 @@ import githubApi from './github-api';
|
||||
import gitlabApi from './gitlab-api';
|
||||
import { schema } from './graphql';
|
||||
import { startGRPCServer } from './grpc';
|
||||
import grpcReflectionApi from './grpc-reflection-api';
|
||||
import insomniaApi from './insomnia-api';
|
||||
import { mtlsRouter } from './mtls';
|
||||
import { oauthRoutes } from './oauth';
|
||||
@@ -109,6 +110,7 @@ app.get('/cookies', (_req, res) => {
|
||||
app.use('/file', express.static('fixtures/files'));
|
||||
app.use('/auth/basic', basicAuthRouter);
|
||||
app.use('/protected', mtlsRouter);
|
||||
app.use(grpcReflectionApi);
|
||||
|
||||
githubApi(app);
|
||||
gitlabApi(app);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
import { loadFixture } from '../../playwright/paths';
|
||||
import { test } from '../../playwright/test';
|
||||
|
||||
test('can load methods through the buf reflection API', async ({ app, page, insomnia }) => {
|
||||
test.slow(process.platform === 'darwin' || process.platform === 'win32', 'Slow app start on these platforms');
|
||||
|
||||
const text = await loadFixture('grpc-reflection-api.yaml');
|
||||
await app.evaluate(async ({ clipboard }, text) => clipboard.writeText(text), text);
|
||||
|
||||
await page.getByLabel('Import').click();
|
||||
await page.locator('[data-test-id="import-from-clipboard"]').click();
|
||||
await page.getByRole('button', { name: 'Scan' }).click();
|
||||
await page.getByRole('dialog').getByRole('button', { name: 'Import' }).click();
|
||||
|
||||
await insomnia.navigationSidebar.clickRequestOrFolder('ReflectionApiUnary');
|
||||
await page.getByTestId('button-server-reflection').click();
|
||||
|
||||
await page.getByRole('button', { name: 'Select Method' }).click();
|
||||
await expect.soft(page.getByRole('option', { name: 'RouteGuide/GetFeature' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('shows an error for an invalid reflection api key', async ({ app, page, insomnia }) => {
|
||||
test.slow(process.platform === 'darwin' || process.platform === 'win32', 'Slow app start on these platforms');
|
||||
|
||||
const text = await loadFixture('grpc-reflection-api.yaml');
|
||||
await app.evaluate(async ({ clipboard }, text) => clipboard.writeText(text), text);
|
||||
|
||||
await page.getByLabel('Import').click();
|
||||
await page.locator('[data-test-id="import-from-clipboard"]').click();
|
||||
await page.getByRole('button', { name: 'Scan' }).click();
|
||||
await page.getByRole('dialog').getByRole('button', { name: 'Import' }).click();
|
||||
|
||||
await insomnia.navigationSidebar.clickRequestOrFolder('ReflectionApiInvalidKey');
|
||||
await page.getByTestId('button-server-reflection').click();
|
||||
|
||||
await expect.soft(page.getByRole('dialog')).toContainText('Invalid reflection server api key');
|
||||
});
|
||||
@@ -51,9 +51,9 @@
|
||||
"dependencies": {
|
||||
"@apideck/better-ajv-errors": "^0.3.6",
|
||||
"@apidevtools/swagger-parser": "12.1.0",
|
||||
"@bufbuild/protobuf": "^1.10.0",
|
||||
"@connectrpc/connect": "^1.6.1",
|
||||
"@connectrpc/connect-node": "^1.6.1",
|
||||
"@bufbuild/protobuf": "^2.16.0",
|
||||
"@connectrpc/connect": "^2.2.0",
|
||||
"@connectrpc/connect-node": "^2.2.0",
|
||||
"@customerio/cdp-analytics-browser": "^0.5.9",
|
||||
"@faker-js/faker": "^10.6.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||
@@ -125,7 +125,7 @@
|
||||
"isbot": "^5",
|
||||
"isomorphic-git": "1.25.7",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsdom": "^25.0.1",
|
||||
"jsdom": "^30.1.2",
|
||||
"jshint": "^2.13.6",
|
||||
"json-bigint": "^1.0.0",
|
||||
"json-order": "^1.1.3",
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
import { type DescMessage, type DescMethodUnary, fromJson, type JsonObject, type MessageInitShape } from '@bufbuild/protobuf';
|
||||
import { Code, ConnectError, type UnaryResponse } from '@connectrpc/connect';
|
||||
import { createConnectTransport } from '@connectrpc/connect-node';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { version } from '../../../../package.json';
|
||||
import { loadMethodsFromReflection } from '../grpc';
|
||||
|
||||
vi.mock('@connectrpc/connect-node');
|
||||
vi.mock('../../../network/grpc/write-proto-file.node');
|
||||
|
||||
const reflectionApi = {
|
||||
enabled: true,
|
||||
apiKey: 'TEST_KEY',
|
||||
url: 'https://buf.build',
|
||||
module: 'buf.build/acme/greeter',
|
||||
};
|
||||
|
||||
const fileDescriptorSetJson: JsonObject = {
|
||||
file: [
|
||||
{
|
||||
name: 'acme/greeter/v1/greeter.proto',
|
||||
package: 'acme.greeter.v1',
|
||||
syntax: 'proto3',
|
||||
messageType: [
|
||||
{
|
||||
name: 'Msg',
|
||||
field: [{ name: 'text', number: 1, label: 'LABEL_OPTIONAL', type: 'TYPE_STRING', jsonName: 'text' }],
|
||||
},
|
||||
],
|
||||
service: [
|
||||
{
|
||||
name: 'GreeterService',
|
||||
method: [
|
||||
{ name: 'Unary', inputType: '.acme.greeter.v1.Msg', outputType: '.acme.greeter.v1.Msg' },
|
||||
{
|
||||
name: 'ClientStream',
|
||||
inputType: '.acme.greeter.v1.Msg',
|
||||
outputType: '.acme.greeter.v1.Msg',
|
||||
clientStreaming: true,
|
||||
},
|
||||
{
|
||||
name: 'ServerStream',
|
||||
inputType: '.acme.greeter.v1.Msg',
|
||||
outputType: '.acme.greeter.v1.Msg',
|
||||
serverStreaming: true,
|
||||
},
|
||||
{
|
||||
name: 'BidiStream',
|
||||
inputType: '.acme.greeter.v1.Msg',
|
||||
outputType: '.acme.greeter.v1.Msg',
|
||||
clientStreaming: true,
|
||||
serverStreaming: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Installs a fake Connect transport whose unary() is the given mock.
|
||||
const useTransport = (unary: ReturnType<typeof vi.fn>) => {
|
||||
vi.mocked(createConnectTransport).mockReturnValue({ unary } as unknown as ReturnType<typeof createConnectTransport>);
|
||||
};
|
||||
|
||||
const loadBuf = (options: { apiKey?: string; disableUserAgentHeader?: boolean } = {}) =>
|
||||
loadMethodsFromReflection({
|
||||
url: 'foo.com',
|
||||
metadata: [],
|
||||
rejectUnauthorized: true,
|
||||
disableUserAgentHeader: options.disableUserAgentHeader,
|
||||
reflectionApi: { ...reflectionApi, apiKey: options.apiKey ?? reflectionApi.apiKey },
|
||||
});
|
||||
|
||||
const headersOf = (unary: ReturnType<typeof vi.fn>) => new Headers(unary.mock.calls[0][3] as HeadersInit);
|
||||
|
||||
describe('loadMethodsFromReflection (buf reflection api)', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('error mapping', () => {
|
||||
it('maps Unauthenticated to an invalid api key error', async () => {
|
||||
useTransport(vi.fn().mockRejectedValue(new ConnectError('denied', Code.Unauthenticated)));
|
||||
|
||||
await expect(loadBuf()).rejects.toThrow('Invalid reflection server api key');
|
||||
});
|
||||
|
||||
it('maps NotFound to a module access error', async () => {
|
||||
useTransport(vi.fn().mockRejectedValue(new ConnectError('missing', Code.NotFound)));
|
||||
|
||||
await expect(loadBuf()).rejects.toThrow(
|
||||
"The reflection server api key doesn't have access to the module or the module does not exists",
|
||||
);
|
||||
});
|
||||
|
||||
it('rethrows other Connect errors unchanged', async () => {
|
||||
const error = new ConnectError('boom', Code.Internal);
|
||||
useTransport(vi.fn().mockRejectedValue(error));
|
||||
|
||||
await expect(loadBuf()).rejects.toBe(error);
|
||||
});
|
||||
|
||||
it('rethrows non-Connect errors unchanged', async () => {
|
||||
const error = new Error('network down');
|
||||
useTransport(vi.fn().mockRejectedValue(error));
|
||||
|
||||
await expect(loadBuf()).rejects.toBe(error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('request headers', () => {
|
||||
it('sends the Insomnia User-Agent and Bearer auth when enabled', async () => {
|
||||
const unary = vi.fn().mockRejectedValue(new ConnectError('stop', Code.Internal));
|
||||
useTransport(unary);
|
||||
|
||||
await expect(loadBuf()).rejects.toBeDefined();
|
||||
|
||||
expect(headersOf(unary).get('User-Agent')).toBe(`insomnia/${version}`);
|
||||
expect(headersOf(unary).get('Authorization')).toBe('Bearer TEST_KEY');
|
||||
});
|
||||
|
||||
it('omits the User-Agent header when disabled', async () => {
|
||||
const unary = vi.fn().mockRejectedValue(new ConnectError('stop', Code.Internal));
|
||||
useTransport(unary);
|
||||
|
||||
await expect(loadBuf({ disableUserAgentHeader: true })).rejects.toBeDefined();
|
||||
|
||||
expect(headersOf(unary).has('User-Agent')).toBe(false);
|
||||
expect(headersOf(unary).get('Authorization')).toBe('Bearer TEST_KEY');
|
||||
});
|
||||
|
||||
it('omits the Authorization header when no api key is set', async () => {
|
||||
const unary = vi.fn().mockRejectedValue(new ConnectError('stop', Code.Internal));
|
||||
useTransport(unary);
|
||||
|
||||
await expect(loadBuf({ apiKey: '' })).rejects.toBeDefined();
|
||||
|
||||
expect(headersOf(unary).has('Authorization')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('response handling', () => {
|
||||
it('returns no methods when the response has no file descriptor set', async () => {
|
||||
useTransport(
|
||||
vi.fn(
|
||||
async (method: DescMethodUnary): Promise<UnaryResponse> =>
|
||||
({ message: fromJson(method.output, {}) }) as unknown as UnaryResponse,
|
||||
),
|
||||
);
|
||||
|
||||
await expect(loadBuf()).resolves.toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('maps unary, client, server and bidi methods from the file descriptor set', async () => {
|
||||
useTransport(
|
||||
vi.fn(
|
||||
async (
|
||||
method: DescMethodUnary,
|
||||
_signal: AbortSignal | undefined,
|
||||
_timeoutMs: number | undefined,
|
||||
_header: HeadersInit | undefined,
|
||||
_input: MessageInitShape<DescMessage>,
|
||||
): Promise<UnaryResponse> =>
|
||||
({
|
||||
message: fromJson(method.output, { fileDescriptorSet: fileDescriptorSetJson }),
|
||||
}) as unknown as UnaryResponse,
|
||||
),
|
||||
);
|
||||
|
||||
const methods = await loadBuf();
|
||||
|
||||
expect(methods.map(({ fullPath, type }) => ({ fullPath, type }))).toStrictEqual([
|
||||
{ fullPath: '/acme.greeter.v1.GreeterService/Unary', type: 'unary' },
|
||||
{ fullPath: '/acme.greeter.v1.GreeterService/ClientStream', type: 'client' },
|
||||
{ fullPath: '/acme.greeter.v1.GreeterService/ServerStream', type: 'server' },
|
||||
{ fullPath: '/acme.greeter.v1.GreeterService/BidiStream', type: 'bidi' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import type { AnyMessage, MethodInfo, PartialMessage, ServiceType } from '@bufbuild/protobuf';
|
||||
import { type DescMessage, type DescMethodUnary, fromJsonString, type MessageInitShape } from '@bufbuild/protobuf';
|
||||
import type { UnaryResponse } from '@connectrpc/connect';
|
||||
import { createConnectTransport } from '@connectrpc/connect-node';
|
||||
import * as grpcReflection from 'grpc-reflection-js';
|
||||
@@ -193,23 +193,22 @@ describe('loadMethodsFromReflection', () => {
|
||||
expect(options.baseUrl).toStrictEqual('https://buf.build');
|
||||
return {
|
||||
async unary(
|
||||
service: ServiceType,
|
||||
method: MethodInfo,
|
||||
method: DescMethodUnary,
|
||||
_: AbortSignal | undefined,
|
||||
__: number | undefined,
|
||||
header: HeadersInit | undefined,
|
||||
input: PartialMessage<AnyMessage>,
|
||||
input: MessageInitShape<DescMessage>,
|
||||
): Promise<UnaryResponse> {
|
||||
expect(new Headers(header).get('Authorization')).toStrictEqual('Bearer TEST_KEY');
|
||||
expect(input).toStrictEqual({ module: 'buf.build/connectrpc/eliza' });
|
||||
return {
|
||||
service: service,
|
||||
method: method,
|
||||
header: new Headers(),
|
||||
trailer: new Headers(),
|
||||
stream: false,
|
||||
// Output of running `buf curl https://buf.build/buf.reflect.v1beta1.FileDescriptorSetService/GetFileDescriptorSet --data '{"module": "buf.build/connectrpc/eliza"}' --schema buf.build/bufbuild/reflect -H 'Authorization: Bearer buf-token'`
|
||||
message: method.O.fromJsonString(
|
||||
message: fromJsonString(
|
||||
method.output,
|
||||
'{"fileDescriptorSet":{"file":[{"name":"connectrpc/eliza/v1/eliza.proto","package":"connectrpc.eliza.v1","messageType":[{"name":"SayRequest","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"SayResponse","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"ConverseRequest","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"ConverseResponse","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"IntroduceRequest","field":[{"name":"name","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"name"}]},{"name":"IntroduceResponse","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]}],"service":[{"name":"ElizaService","method":[{"name":"Say","inputType":".connectrpc.eliza.v1.SayRequest","outputType":".connectrpc.eliza.v1.SayResponse","options":{"idempotencyLevel":"NO_SIDE_EFFECTS"}},{"name":"Converse","inputType":".connectrpc.eliza.v1.ConverseRequest","outputType":".connectrpc.eliza.v1.ConverseResponse","options":{},"clientStreaming":true,"serverStreaming":true},{"name":"Introduce","inputType":".connectrpc.eliza.v1.IntroduceRequest","outputType":".connectrpc.eliza.v1.IntroduceResponse","options":{},"serverStreaming":true}]}],"syntax":"proto3"}]},"version":"233fca715f49425581ec0a1b660be886"}',
|
||||
),
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { createFileRegistry, type DescMethodUnary, fromJson, toBinary } from '@bufbuild/protobuf';
|
||||
import {
|
||||
FileDescriptorSet as ProtobufEsFileDescriptorSet,
|
||||
MethodIdempotency,
|
||||
MethodKind,
|
||||
proto3,
|
||||
} from '@bufbuild/protobuf';
|
||||
import { Code, ConnectError, createPromiseClient } from '@connectrpc/connect';
|
||||
file_google_protobuf_descriptor,
|
||||
FileDescriptorProtoSchema,
|
||||
type FileDescriptorSet,
|
||||
FileDescriptorSetSchema,
|
||||
} from '@bufbuild/protobuf/wkt';
|
||||
import { Code, ConnectError } from '@connectrpc/connect';
|
||||
import { createConnectTransport } from '@connectrpc/connect-node';
|
||||
import {
|
||||
type Call,
|
||||
@@ -132,65 +133,76 @@ const getMethodsFromReflectionServer = async (
|
||||
disableUserAgentHeader: boolean,
|
||||
): Promise<MethodDefs[]> => {
|
||||
const { url, module, apiKey } = reflectionApi;
|
||||
const GetFileDescriptorSetRequest = proto3.makeMessageType('buf.reflect.v1beta1.GetFileDescriptorSetRequest', () => [
|
||||
{ no: 1, name: 'module', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
||||
{ no: 2, name: 'version', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
||||
{
|
||||
no: 3,
|
||||
name: 'symbols',
|
||||
kind: 'scalar',
|
||||
T: 9 /* ScalarType.STRING */,
|
||||
repeated: true,
|
||||
},
|
||||
]);
|
||||
const GetFileDescriptorSetResponse = proto3.makeMessageType(
|
||||
'buf.reflect.v1beta1.GetFileDescriptorSetResponse',
|
||||
() => [
|
||||
{
|
||||
no: 1,
|
||||
name: 'file_descriptor_set',
|
||||
kind: 'message',
|
||||
T: ProtobufEsFileDescriptorSet,
|
||||
},
|
||||
{ no: 2, name: 'version', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
||||
],
|
||||
const reflectionRegistry = createFileRegistry(
|
||||
fromJson(FileDescriptorProtoSchema, {
|
||||
name: 'buf/reflect/v1beta1/file_descriptor_set_service.proto',
|
||||
package: 'buf.reflect.v1beta1',
|
||||
syntax: 'proto3',
|
||||
dependency: ['google/protobuf/descriptor.proto'],
|
||||
messageType: [
|
||||
{
|
||||
name: 'GetFileDescriptorSetRequest',
|
||||
field: [
|
||||
{ name: 'module', number: 1, label: 'LABEL_OPTIONAL', type: 'TYPE_STRING', jsonName: 'module' },
|
||||
{ name: 'version', number: 2, label: 'LABEL_OPTIONAL', type: 'TYPE_STRING', jsonName: 'version' },
|
||||
{ name: 'symbols', number: 3, label: 'LABEL_REPEATED', type: 'TYPE_STRING', jsonName: 'symbols' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'GetFileDescriptorSetResponse',
|
||||
field: [
|
||||
{
|
||||
name: 'file_descriptor_set',
|
||||
number: 1,
|
||||
label: 'LABEL_OPTIONAL',
|
||||
type: 'TYPE_MESSAGE',
|
||||
typeName: '.google.protobuf.FileDescriptorSet',
|
||||
jsonName: 'fileDescriptorSet',
|
||||
},
|
||||
{ name: 'version', number: 2, label: 'LABEL_OPTIONAL', type: 'TYPE_STRING', jsonName: 'version' },
|
||||
],
|
||||
},
|
||||
],
|
||||
service: [
|
||||
{
|
||||
name: 'FileDescriptorSetService',
|
||||
method: [
|
||||
{
|
||||
name: 'GetFileDescriptorSet',
|
||||
inputType: '.buf.reflect.v1beta1.GetFileDescriptorSetRequest',
|
||||
outputType: '.buf.reflect.v1beta1.GetFileDescriptorSetResponse',
|
||||
options: { idempotencyLevel: 'NO_SIDE_EFFECTS' },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
importName => (importName === 'google/protobuf/descriptor.proto' ? file_google_protobuf_descriptor : undefined),
|
||||
);
|
||||
const FileDescriptorSetService = {
|
||||
typeName: 'buf.reflect.v1beta1.FileDescriptorSetService',
|
||||
methods: {
|
||||
getFileDescriptorSet: {
|
||||
name: 'GetFileDescriptorSet',
|
||||
I: GetFileDescriptorSetRequest,
|
||||
O: GetFileDescriptorSetResponse,
|
||||
kind: MethodKind.Unary,
|
||||
idempotency: MethodIdempotency.NoSideEffects,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
const FileDescriptorSetService = reflectionRegistry.getService('buf.reflect.v1beta1.FileDescriptorSetService');
|
||||
invariant(FileDescriptorSetService, 'FileDescriptorSetService is missing from the reflection descriptor');
|
||||
const transport = createConnectTransport({
|
||||
baseUrl: url,
|
||||
httpVersion: '1.1',
|
||||
});
|
||||
const client = createPromiseClient(FileDescriptorSetService, transport);
|
||||
const getFileDescriptorSetMethod = FileDescriptorSetService.method.getFileDescriptorSet;
|
||||
invariant(getFileDescriptorSetMethod.methodKind === 'unary', 'GetFileDescriptorSet must be a unary method');
|
||||
const headers: HeadersInit = {
|
||||
...(disableUserAgentHeader ? {} : { 'User-Agent': `insomnia/${version}` }),
|
||||
...(apiKey === '' ? {} : { Authorization: `Bearer ${apiKey}` }),
|
||||
};
|
||||
try {
|
||||
const res = await client.getFileDescriptorSet(
|
||||
{
|
||||
module,
|
||||
},
|
||||
{
|
||||
headers,
|
||||
},
|
||||
);
|
||||
// Calls the transport directly: createClient() cannot type a descriptor built at runtime.
|
||||
const res = await transport.unary(getFileDescriptorSetMethod as DescMethodUnary, undefined, undefined, headers, {
|
||||
module,
|
||||
});
|
||||
const response = res.message as { fileDescriptorSet?: FileDescriptorSet };
|
||||
const methodDefs: MethodDefs[] = [];
|
||||
if (res.fileDescriptorSet === undefined) {
|
||||
if (response.fileDescriptorSet === undefined) {
|
||||
return [];
|
||||
}
|
||||
const packageDefinition = protoLoader.loadFileDescriptorSetFromBuffer(
|
||||
Buffer.from(res.fileDescriptorSet.toBinary()),
|
||||
Buffer.from(toBinary(FileDescriptorSetSchema, response.fileDescriptorSet)),
|
||||
);
|
||||
for (const definition of Object.values(packageDefinition)) {
|
||||
const serviceDefinition = asServiceDefinition(definition);
|
||||
|
||||
@@ -86,7 +86,9 @@ export const GrpcRequestPane: FunctionComponent<Props> = ({ grpcState, setGrpcSt
|
||||
console.log(`[gRPC] loading proto file methods pf=${activeRequest.protoFileId}`);
|
||||
const methods = await window.main.grpc.loadMethods(activeRequest.protoFileId);
|
||||
setGrpcState({ ...grpcState, methods });
|
||||
} else if (activeRequest.url && activeRequest.reflectionApi) {
|
||||
} else if (activeRequest.url && activeRequest.reflectionApi && !activeRequest.reflectionApi.enabled) {
|
||||
// Intentionally skipped when the buf reflection API is enabled: loading would send the API key on pane open.
|
||||
// In that case methods are only loaded when the user clicks the reflection refresh button.
|
||||
const requestGroups = (
|
||||
await db.withAncestors<GrpcRequest | RequestGroup>(activeRequest, [models.requestGroup.type])
|
||||
).filter(isRequestGroup);
|
||||
|
||||
Reference in new issue
Block a user