diff --git a/.changeset/ten-tires-yawn.md b/.changeset/ten-tires-yawn.md new file mode 100644 index 000000000000..6217f1da36c9 --- /dev/null +++ b/.changeset/ten-tires-yawn.md @@ -0,0 +1,6 @@ +--- +'@modern-js/create-request': patch +--- + +feat: bff query supports obj +feat: bff query 支持对象类型 diff --git a/packages/cli/plugin-bff/src/utils/createHonoRoutes.ts b/packages/cli/plugin-bff/src/utils/createHonoRoutes.ts index d14e59ed05d0..356309d564eb 100644 --- a/packages/cli/plugin-bff/src/utils/createHonoRoutes.ts +++ b/packages/cli/plugin-bff/src/utils/createHonoRoutes.ts @@ -6,6 +6,7 @@ import { ValidationError, isWithMetaHandler, } from '@modern-js/bff-core'; +import { parse } from '@modern-js/create-request/qs'; import type { Context, Next } from '@modern-js/server-core'; import typeIs from 'type-is'; @@ -108,7 +109,7 @@ export const createHonoHandler = (handler: Handler) => { const getHonoInput = async (c: Context) => { const draft: Record = { params: c.req.param(), - query: c.req.query(), + query: parse(c.req.query()), headers: c.req.header(), cookies: c.req.header('cookie'), }; diff --git a/packages/server/create-request/package.json b/packages/server/create-request/package.json index e175e5733848..76c90be325b2 100644 --- a/packages/server/create-request/package.json +++ b/packages/server/create-request/package.json @@ -54,6 +54,11 @@ "types": "./dist/types/node.d.ts", "jsnext:source": "./src/node.ts", "default": "./dist/cjs/node.js" + }, + "./qs": { + "types": "./dist/types/qs.d.ts", + "jsnext:source": "./src/qs.ts", + "default": "./dist/cjs/qs.js" } }, "typesVersions": { @@ -66,6 +71,9 @@ ], "server": [ "./dist/types/node.d.ts" + ], + "qs": [ + "./dist/types/qs.d.ts" ] } }, @@ -83,7 +91,7 @@ "encoding": "^0.1.13", "node-fetch": "^2.7.0", "path-to-regexp": "^6.3.0", - "query-string": "^7.1.3" + "qs": "^6.14.0" }, "devDependencies": { "@modern-js/types": "workspace:*", @@ -95,6 +103,7 @@ "isomorphic-fetch": "^3.0.0", "jest": "^29.7.0", "nock": "^13.5.6", + "@types/qs": "^6.14.0", "typescript": "^5" }, "sideEffects": false, diff --git a/packages/server/create-request/src/browser.ts b/packages/server/create-request/src/browser.ts index b7ac5b9b8a77..3f111963c463 100644 --- a/packages/server/create-request/src/browser.ts +++ b/packages/server/create-request/src/browser.ts @@ -1,5 +1,5 @@ import { type Key, compile, pathToRegexp } from 'path-to-regexp'; -import { stringify } from 'query-string'; +import { stringify } from 'qs'; import { handleRes } from './handleRes'; import type { BFFRequestPayload, diff --git a/packages/server/create-request/src/node.ts b/packages/server/create-request/src/node.ts index 095016e65f56..166138f9ba4e 100644 --- a/packages/server/create-request/src/node.ts +++ b/packages/server/create-request/src/node.ts @@ -2,7 +2,7 @@ import type { IncomingHttpHeaders } from 'http'; import { storage } from '@modern-js/runtime-utils/node'; import nodeFetch from 'node-fetch'; import { type Key, compile, pathToRegexp } from 'path-to-regexp'; -import { stringify } from 'query-string'; +import { stringify } from 'qs'; import { handleRes } from './handleRes'; import type { BFFRequestPayload, diff --git a/packages/server/create-request/src/qs.ts b/packages/server/create-request/src/qs.ts new file mode 100644 index 000000000000..25cfc880c7f0 --- /dev/null +++ b/packages/server/create-request/src/qs.ts @@ -0,0 +1 @@ +export { stringify, parse } from 'qs'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 754c1731cd48..bd55324c5681 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1609,9 +1609,9 @@ importers: path-to-regexp: specifier: ^6.3.0 version: 6.3.0 - query-string: - specifier: ^7.1.3 - version: 7.1.3 + qs: + specifier: ^6.14.0 + version: 6.14.0 devDependencies: '@modern-js/types': specifier: workspace:* @@ -1631,6 +1631,9 @@ importers: '@types/node-fetch': specifier: ^2.6.13 version: 2.6.13 + '@types/qs': + specifier: ^6.14.0 + version: 6.14.0 isomorphic-fetch: specifier: ^3.0.0 version: 3.0.0(encoding@0.1.13) @@ -9143,8 +9146,8 @@ packages: '@types/parse-json@4.0.0': resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} - '@types/qs@6.9.16': - resolution: {integrity: sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==} + '@types/qs@6.14.0': + resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} @@ -9903,6 +9906,10 @@ packages: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -10777,10 +10784,6 @@ packages: decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} - decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -11549,10 +11552,6 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - filter-obj@1.1.0: - resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} - engines: {node: '>=0.10.0'} - finalhandler@1.1.2: resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} engines: {node: '>= 0.8'} @@ -13532,6 +13531,10 @@ packages: resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} engines: {node: '>= 0.4'} + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -14261,13 +14264,13 @@ packages: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} - query-string@7.1.3: - resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} - engines: {node: '>=6'} - querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} @@ -15181,10 +15184,26 @@ packages: shiki@3.5.0: resolution: {integrity: sha512-1lyPuqIPPAlmR1BKtDkxiuoZTB2IKSyr+GeHXu4ReOyHoEMhCnUoGZDUv4SJRH0Bi4QmsEPsrkQCRSOgnVRC+g==} + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -15309,10 +15328,6 @@ packages: spdx-licenses@1.0.0: resolution: {integrity: sha512-BmeFZRYH9XXf56omx0LuiG+gBXRqwmrKsOtcsGTJh8tw9U0cgRKTrOnyDpP1uvI1AVEkoRKYaAvR902ByotFOw==} - split-on-first@1.1.0: - resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} - engines: {node: '>=6'} - split2@3.2.2: resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} @@ -15365,10 +15380,6 @@ packages: strict-event-emitter@0.4.6: resolution: {integrity: sha512-12KWeb+wixJohmnwNFerbyiBrAlq5qJLwIt38etRtKtmmHyDSoGlIqFE9wx+4IwG0aDjI7GV8tc8ZccjWZZtTg==} - strict-uri-encode@2.0.0: - resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} - engines: {node: '>=4'} - string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -20807,14 +20818,14 @@ snapshots: '@types/express-serve-static-core@4.19.6': dependencies: '@types/node': 20.8.8 - '@types/qs': 6.9.16 + '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 '@types/express-serve-static-core@5.0.0': dependencies: '@types/node': 20.8.8 - '@types/qs': 6.9.16 + '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -20822,7 +20833,7 @@ snapshots: dependencies: '@types/body-parser': 1.19.5 '@types/express-serve-static-core': 4.19.6 - '@types/qs': 6.9.16 + '@types/qs': 6.14.0 '@types/serve-static': 1.15.9 '@types/fs-extra@11.0.4': @@ -21004,7 +21015,7 @@ snapshots: '@types/parse-json@4.0.0': {} - '@types/qs@6.9.16': {} + '@types/qs@6.14.0': {} '@types/range-parser@1.2.7': {} @@ -21948,6 +21959,11 @@ snapshots: get-intrinsic: 1.3.0 set-function-length: 1.2.2 + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + callsites@3.1.0: {} camel-case@4.1.2: @@ -22852,8 +22868,6 @@ snapshots: dependencies: character-entities: 2.0.2 - decode-uri-component@0.2.2: {} - decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 @@ -23721,8 +23735,6 @@ snapshots: dependencies: to-regex-range: 5.0.1 - filter-obj@1.1.0: {} - finalhandler@1.1.2: dependencies: debug: 2.6.9 @@ -23831,7 +23843,7 @@ snapshots: '@paralleldrive/cuid2': 2.2.2 dezalgo: 1.0.4 once: 1.4.0 - qs: 6.13.0 + qs: 6.14.0 forwarded@0.2.0: {} @@ -26612,6 +26624,8 @@ snapshots: object-inspect@1.13.2: {} + object-inspect@1.13.4: {} + object-keys@1.1.1: {} object.assign@4.1.4: @@ -27340,14 +27354,11 @@ snapshots: dependencies: side-channel: 1.0.6 - quansync@0.2.11: {} - - query-string@7.1.3: + qs@6.14.0: dependencies: - decode-uri-component: 0.2.2 - filter-obj: 1.1.0 - split-on-first: 1.1.0 - strict-uri-encode: 2.0.0 + side-channel: 1.1.0 + + quansync@0.2.11: {} querystringify@2.2.0: {} @@ -28443,6 +28454,26 @@ snapshots: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + side-channel@1.0.6: dependencies: call-bind: 1.0.7 @@ -28450,6 +28481,14 @@ snapshots: get-intrinsic: 1.3.0 object-inspect: 1.13.2 + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} signal-exit@3.0.7: {} @@ -28603,8 +28642,6 @@ snapshots: transitivePeerDependencies: - supports-color - split-on-first@1.1.0: {} - split2@3.2.2: dependencies: readable-stream: 3.6.2 @@ -28653,8 +28690,6 @@ snapshots: strict-event-emitter@0.4.6: {} - strict-uri-encode@2.0.0: {} - string-argv@0.3.2: {} string-convert@0.2.1: {} @@ -28790,7 +28825,7 @@ snapshots: formidable: 2.1.5 methods: 1.1.2 mime: 2.6.0 - qs: 6.13.0 + qs: 6.14.0 semver: 7.7.3 transitivePeerDependencies: - supports-color diff --git a/tests/integration/bff-hono/api/lambda/index.ts b/tests/integration/bff-hono/api/lambda/index.ts index 07ce93be44a5..23477ba90aff 100644 --- a/tests/integration/bff-hono/api/lambda/index.ts +++ b/tests/integration/bff-hono/api/lambda/index.ts @@ -27,6 +27,11 @@ export const post = async ({ formUrlencoded }: { formUrlencoded: any }) => { const QuerySchema = z.object({ user: z.string().email(), + ext: z.array(z.object({ from: z.string() })), + arr: z.array(z.string()), + obj: z.object({ + a: z.string(), + }), }); const DataSchema = z.object({ @@ -76,9 +81,13 @@ export const postHello = Api( }, ); +const GetQuerySchema = z.object({ + user: z.string().email(), +}); + export const getHello = Api( Get('/hello/get'), - Query(QuerySchema), + Query(GetQuerySchema), async ({ query }) => { try { const c = useHonoContext(); diff --git a/tests/integration/bff-hono/src/routes/base/page.tsx b/tests/integration/bff-hono/src/routes/base/page.tsx index 67e95ccf84c1..15ee7c4a1a66 100644 --- a/tests/integration/bff-hono/src/routes/base/page.tsx +++ b/tests/integration/bff-hono/src/routes/base/page.tsx @@ -27,6 +27,11 @@ const Page = () => { }, query: { user: 'modern@email.com', + ext: [{ from: '123' }], + arr: ['1', '2'], + obj: { + a: '1', + }, }, data: { message: '3333',