From 70c3402b84e573190ceea66ea2243f82cbdab5d3 Mon Sep 17 00:00:00 2001 From: Lubos Date: Wed, 20 Mar 2024 13:34:52 +0000 Subject: [PATCH] fix(request): discard only null or undefined in query string --- package-lock.json | 21 +-- package.json | 9 +- .../core/functions/getQueryString.hbs | 34 ++--- src/templates/core/functions/getUrl.hbs | 7 +- test/__snapshots__/index.spec.ts.snap | 123 +++++++----------- 5 files changed, 65 insertions(+), 129 deletions(-) diff --git a/package-lock.json b/package-lock.json index 881bc1fa0..0a234ad1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,6 @@ "@types/cross-spawn": "6.0.6", "@types/express": "4.17.21", "@types/node": "20.11.30", - "@types/qs": "6.9.13", "@typescript-eslint/eslint-plugin": "7.3.1", "@typescript-eslint/parser": "7.3.1", "@vitest/coverage-v8": "1.4.0", @@ -53,7 +52,6 @@ "npm-run-all2": "6.1.2", "prettier": "3.2.5", "puppeteer": "22.5.0", - "qs": "6.12.0", "rimraf": "5.0.5", "rollup": "4.13.0", "rollup-plugin-dts": "6.1.0", @@ -61,8 +59,7 @@ "ts-node": "10.9.2", "tslib": "2.6.2", "typescript": "5.4.2", - "vitest": "1.4.0", - "zone.js": "0.14.4" + "vitest": "1.4.0" }, "engines": { "node": "^18.0.0 || >=20.0.0" @@ -11420,21 +11417,6 @@ "node": ">=18" } }, - "node_modules/qs": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", - "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -14685,6 +14667,7 @@ "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.4.tgz", "integrity": "sha512-NtTUvIlNELez7Q1DzKVIFZBzNb646boQMgpATo9z3Ftuu/gWvzxCW7jdjcUDoRGxRikrhVHB/zLXh1hxeJawvw==", "dev": true, + "peer": true, "dependencies": { "tslib": "^2.3.0" } diff --git a/package.json b/package.json index 891b8e814..dae61eb82 100644 --- a/package.json +++ b/package.json @@ -54,11 +54,11 @@ "lint": "eslint .", "prepublishOnly": "npm run build", "test": "vitest run --config vitest.config.unit.ts", - "test:update": "vitest run --config vitest.config.unit.ts --update", "test:coverage": "vitest run --config vitest.config.unit.ts --coverage", - "test:watch": "vitest --config vitest.config.unit.ts --watch", "test:e2e": "vitest run --config vitest.config.e2e.ts", "test:sample": "node test/sample.cjs", + "test:update": "vitest run --config vitest.config.unit.ts --update", + "test:watch": "vitest --config vitest.config.unit.ts --watch", "typecheck": "tsc --noEmit" }, "engines": { @@ -90,7 +90,6 @@ "@types/cross-spawn": "6.0.6", "@types/express": "4.17.21", "@types/node": "20.11.30", - "@types/qs": "6.9.13", "@typescript-eslint/eslint-plugin": "7.3.1", "@typescript-eslint/parser": "7.3.1", "@vitest/coverage-v8": "1.4.0", @@ -106,7 +105,6 @@ "npm-run-all2": "6.1.2", "prettier": "3.2.5", "puppeteer": "22.5.0", - "qs": "6.12.0", "rimraf": "5.0.5", "rollup": "4.13.0", "rollup-plugin-dts": "6.1.0", @@ -114,8 +112,7 @@ "ts-node": "10.9.2", "tslib": "2.6.2", "typescript": "5.4.2", - "vitest": "1.4.0", - "zone.js": "0.14.4" + "vitest": "1.4.0" }, "packageManager": "npm@10.5.0+sha256.17ca6e08e7633b624e8f870db81a78f46afe119de62bcaf0a7407574139198fc" } diff --git a/src/templates/core/functions/getQueryString.hbs b/src/templates/core/functions/getQueryString.hbs index 0f17d43ac..0fc550c06 100644 --- a/src/templates/core/functions/getQueryString.hbs +++ b/src/templates/core/functions/getQueryString.hbs @@ -5,29 +5,21 @@ export const getQueryString = (params: Record): string => { qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`); }; - const process = (key: string, value: unknown) => { - if (value) { - if (Array.isArray(value)) { - value.forEach(v => { - process(key, v); - }); - } else if (typeof value === 'object') { - Object.entries(value).forEach(([k, v]) => { - process(`${key}[${k}]`, v); - }); - } else { - append(key, value); - } + const encodePair = (key: string, value: unknown) => { + if (value === undefined || value === null) { + return; } - }; - Object.entries(params).forEach(([key, value]) => { - process(key, value); - }); + if (Array.isArray(value)) { + value.forEach(v => encodePair(key, v)); + } else if (typeof value === 'object') { + Object.entries(value).forEach(([k, v]) => encodePair(`${key}[${k}]`, v)); + } else { + append(key, value); + } + }; - if (qs.length > 0) { - return `?${qs.join('&')}`; - } + Object.entries(params).forEach(([key, value]) => encodePair(key, value)); - return ''; + return qs.length ? `?${qs.join('&')}` : ''; }; diff --git a/src/templates/core/functions/getUrl.hbs b/src/templates/core/functions/getUrl.hbs index fe181ab2e..ec617ac18 100644 --- a/src/templates/core/functions/getUrl.hbs +++ b/src/templates/core/functions/getUrl.hbs @@ -10,9 +10,6 @@ const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { return substring; }); - const url = `${config.BASE}${path}`; - if (options.query) { - return `${url}${getQueryString(options.query)}`; - } - return url; + const url = config.BASE + path; + return options.query ? url + getQueryString(options.query) : url; }; diff --git a/test/__snapshots__/index.spec.ts.snap b/test/__snapshots__/index.spec.ts.snap index 5705279aa..ae8afb5f6 100644 --- a/test/__snapshots__/index.spec.ts.snap +++ b/test/__snapshots__/index.spec.ts.snap @@ -283,31 +283,23 @@ export const getQueryString = (params: Record): string => { qs.push(\`\${encodeURIComponent(key)}=\${encodeURIComponent(String(value))}\`); }; - const process = (key: string, value: unknown) => { - if (value) { - if (Array.isArray(value)) { - value.forEach(v => { - process(key, v); - }); - } else if (typeof value === 'object') { - Object.entries(value).forEach(([k, v]) => { - process(\`\${key}[\${k}]\`, v); - }); - } else { - append(key, value); - } + const encodePair = (key: string, value: unknown) => { + if (value === undefined || value === null) { + return; + } + + if (Array.isArray(value)) { + value.forEach(v => encodePair(key, v)); + } else if (typeof value === 'object') { + Object.entries(value).forEach(([k, v]) => encodePair(\`\${key}[\${k}]\`, v)); + } else { + append(key, value); } }; - Object.entries(params).forEach(([key, value]) => { - process(key, value); - }); + Object.entries(params).forEach(([key, value]) => encodePair(key, value)); - if (qs.length > 0) { - return \`?\${qs.join('&')}\`; - } - - return ''; + return qs.length ? \`?\${qs.join('&')}\` : ''; }; const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { @@ -322,11 +314,8 @@ const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { return substring; }); - const url = \`\${config.BASE}\${path}\`; - if (options.query) { - return \`\${url}\${getQueryString(options.query)}\`; - } - return url; + const url = config.BASE + path; + return options.query ? url + getQueryString(options.query) : url; }; export const getFormData = (options: ApiRequestOptions): FormData | undefined => { @@ -3261,31 +3250,23 @@ export const getQueryString = (params: Record): string => { qs.push(\`\${encodeURIComponent(key)}=\${encodeURIComponent(String(value))}\`); }; - const process = (key: string, value: unknown) => { - if (value) { - if (Array.isArray(value)) { - value.forEach(v => { - process(key, v); - }); - } else if (typeof value === 'object') { - Object.entries(value).forEach(([k, v]) => { - process(\`\${key}[\${k}]\`, v); - }); - } else { - append(key, value); - } + const encodePair = (key: string, value: unknown) => { + if (value === undefined || value === null) { + return; } - }; - Object.entries(params).forEach(([key, value]) => { - process(key, value); - }); + if (Array.isArray(value)) { + value.forEach(v => encodePair(key, v)); + } else if (typeof value === 'object') { + Object.entries(value).forEach(([k, v]) => encodePair(\`\${key}[\${k}]\`, v)); + } else { + append(key, value); + } + }; - if (qs.length > 0) { - return \`?\${qs.join('&')}\`; - } + Object.entries(params).forEach(([key, value]) => encodePair(key, value)); - return ''; + return qs.length ? \`?\${qs.join('&')}\` : ''; }; const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { @@ -3300,11 +3281,8 @@ const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { return substring; }); - const url = \`\${config.BASE}\${path}\`; - if (options.query) { - return \`\${url}\${getQueryString(options.query)}\`; - } - return url; + const url = config.BASE + path; + return options.query ? url + getQueryString(options.query) : url; }; export const getFormData = (options: ApiRequestOptions): FormData | undefined => { @@ -8352,31 +8330,23 @@ export const getQueryString = (params: Record): string => { qs.push(\`\${encodeURIComponent(key)}=\${encodeURIComponent(String(value))}\`); }; - const process = (key: string, value: unknown) => { - if (value) { - if (Array.isArray(value)) { - value.forEach(v => { - process(key, v); - }); - } else if (typeof value === 'object') { - Object.entries(value).forEach(([k, v]) => { - process(\`\${key}[\${k}]\`, v); - }); - } else { - append(key, value); - } + const encodePair = (key: string, value: unknown) => { + if (value === undefined || value === null) { + return; } - }; - Object.entries(params).forEach(([key, value]) => { - process(key, value); - }); + if (Array.isArray(value)) { + value.forEach(v => encodePair(key, v)); + } else if (typeof value === 'object') { + Object.entries(value).forEach(([k, v]) => encodePair(\`\${key}[\${k}]\`, v)); + } else { + append(key, value); + } + }; - if (qs.length > 0) { - return \`?\${qs.join('&')}\`; - } + Object.entries(params).forEach(([key, value]) => encodePair(key, value)); - return ''; + return qs.length ? \`?\${qs.join('&')}\` : ''; }; const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { @@ -8391,11 +8361,8 @@ const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { return substring; }); - const url = \`\${config.BASE}\${path}\`; - if (options.query) { - return \`\${url}\${getQueryString(options.query)}\`; - } - return url; + const url = config.BASE + path; + return options.query ? url + getQueryString(options.query) : url; }; export const getFormData = (options: ApiRequestOptions): FormData | undefined => {