Skip to content

Commit

Permalink
chore(internal): restructure code to stringify query (#159)
Browse files Browse the repository at this point in the history
  • Loading branch information
stainless-bot authored and chen-annie committed Jul 24, 2023
1 parent 1dba8bc commit 82dae5b
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 33 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@
"@types/jest": "^29.4.0",
"@typescript-eslint/eslint-plugin": "^5.33.0",
"@typescript-eslint/parser": "^5.33.0",
"modern-treasury": "link:.",
"eslint": "^8.22.0",
"eslint-plugin-unused-imports": "^2.0.0",
"jest": "^29.4.0",
"modern-treasury": "link:.",
"prettier": "rattrayalex/prettier#postfix-ternaries",
"ts-jest": "^29.1.0",
"ts-node": "^10.5.0",
Expand Down
32 changes: 18 additions & 14 deletions src/core.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as qs from 'qs';
import { VERSION } from './version';
import { APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError } from './error';
import type { Readable } from 'modern-treasury/_shims/node-readable';
Expand Down Expand Up @@ -81,18 +80,6 @@ export abstract class APIClient {
*/
protected validateHeaders(headers: Headers, customHeaders: Headers) {}

/**
* Override this to add your own qs.stringify options, for example:
*
* {
* ...super.qsOptions(),
* strictNullHandling: true,
* }
*/
protected qsOptions(): qs.IStringifyOptions | undefined {
return {};
}

protected defaultIdempotencyKey(): string {
return `stainless-node-retry-${uuid4()}`;
}
Expand Down Expand Up @@ -297,12 +284,29 @@ export abstract class APIClient {
}

if (query) {
url.search = qs.stringify(query, this.qsOptions());
url.search = this.stringifyQuery(query);
}

return url.toString();
}

protected stringifyQuery(query: Record<string, unknown>): string {
return Object.entries(query)
.filter(([_, value]) => typeof value !== 'undefined')
.map(([key, value]) => {
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
}
if (value === null) {
return `${encodeURIComponent(key)}=`;
}
throw new Error(
`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,
);
})
.join('&');
}

async fetchWithTimeout(
url: RequestInfo,
init: RequestInit | undefined,
Expand Down
6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// File generated from our OpenAPI spec by Stainless.

import * as qs from 'qs';
import * as Core from './core';
import * as Pagination from './pagination';
import * as API from './resources/index';
import * as Errors from './error';
import type { Agent } from 'modern-treasury/_shims/agent';
import * as Uploads from './uploads';
import * as qs from 'qs';

type Config = {
/**
Expand Down Expand Up @@ -172,8 +172,8 @@ export class ModernTreasury extends Core.APIClient {
return { Authorization };
}

protected override qsOptions(): qs.IStringifyOptions {
return { arrayFormat: 'repeat' };
protected override stringifyQuery(query: Record<string, unknown>): string {
return qs.stringify(query, { arrayFormat: 'repeat' });
}

static ModernTreasury = this;
Expand Down
26 changes: 26 additions & 0 deletions tests/stringifyQuery.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { APIClient } from 'modern-treasury/core';

const { stringifyQuery } = APIClient.prototype as any;

describe('APIClient.stringifyQuery', () => {
for (const [input, expected] of [
[{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'],
[{ a: null, b: false, c: undefined }, 'a=&b=false'],
[{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`],
[
{ 'a/b': 'c/d', 'e=f': 'g&h' },
`${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent(
'e=f',
)}=${encodeURIComponent('g&h')}`,
],
]) {
it(`${JSON.stringify(input)} -> ${expected}`, () => {
expect(stringifyQuery(input)).toEqual(expected);
});
}
for (const value of [[], {}, new Date()]) {
it(`${JSON.stringify(value)} -> <error>`, () => {
expect(() => stringifyQuery({ value })).toThrow(`Cannot stringify type ${typeof value}`);
});
}
});
36 changes: 21 additions & 15 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -978,10 +978,6 @@
"@typescript-eslint/types" "5.45.0"
eslint-visitor-keys "^3.3.0"

"modern-treasury@link:.":
version "0.0.0"
uid ""

abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
Expand Down Expand Up @@ -2028,13 +2024,14 @@ get-caller-file@^2.0.5:
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==

get-intrinsic@^1.0.2:
version "1.1.1"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
version "1.2.1"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82"
integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==
dependencies:
function-bind "^1.1.1"
has "^1.0.3"
has-symbols "^1.0.1"
has-proto "^1.0.1"
has-symbols "^1.0.3"

get-package-type@^0.1.0:
version "0.1.0"
Expand Down Expand Up @@ -2126,7 +2123,12 @@ has-flag@^4.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==

has-symbols@^1.0.1:
has-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==

has-symbols@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
Expand Down Expand Up @@ -2994,6 +2996,10 @@ minimist@1.2.6, minimist@^1.2.0, minimist@^1.2.6:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==

"modern-treasury@link:.":
version "0.0.0"
uid ""

ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
Expand Down Expand Up @@ -3054,9 +3060,9 @@ npm-run-path@^4.0.1:
path-key "^3.0.0"

object-inspect@^1.9.0:
version "1.12.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0"
integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==
version "1.12.3"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==

once@^1.3.0:
version "1.4.0"
Expand Down Expand Up @@ -3398,9 +3404,9 @@ pure-rand@^6.0.0:
integrity sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==

qs@^6.10.3:
version "6.10.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
version "6.11.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9"
integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==
dependencies:
side-channel "^1.0.4"

Expand Down

0 comments on commit 82dae5b

Please sign in to comment.