From 210a9b70ab6ed9e0e016a53e82174f3ca07b58b3 Mon Sep 17 00:00:00 2001 From: Reverier-Xu Date: Sun, 21 Apr 2024 23:07:19 +0800 Subject: [PATCH 01/10] feat: add support for `stringifyJson` --- source/core/Ky.ts | 2 +- source/core/constants.ts | 1 + source/types/options.ts | 26 ++++++++++++++++++++++++++ test/main.ts | 21 +++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/source/core/Ky.ts b/source/core/Ky.ts index 638cb324..5098a837 100644 --- a/source/core/Ky.ts +++ b/source/core/Ky.ts @@ -203,7 +203,7 @@ export class Ky { } if (this._options.json !== undefined) { - this._options.body = JSON.stringify(this._options.json); + this._options.body = this._options.stringifyJson ? this._options.stringifyJson(this._options.json) : JSON.stringify(this._options.json); this.request.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json'); this.request = new globalThis.Request(this.request, {body: this._options.body}); } diff --git a/source/core/constants.ts b/source/core/constants.ts index 27309629..50f948d4 100644 --- a/source/core/constants.ts +++ b/source/core/constants.ts @@ -50,6 +50,7 @@ export const stop = Symbol('stop'); export const kyOptionKeys: KyOptionsRegistry = { json: true, parseJson: true, + stringifyJson: true, searchParams: true, prefixUrl: true, retry: true, diff --git a/source/types/options.ts b/source/types/options.ts index c391dbaa..bb4ee834 100644 --- a/source/types/options.ts +++ b/source/types/options.ts @@ -58,6 +58,32 @@ export type KyOptions = { */ parseJson?: (text: string) => unknown; + /** + User-defined JSON-stringifying function. + + Use-cases: + 1. Stringify JSON with the custom `replacer` function. + + @default JSON.stringify() + + @example + ``` + import ky from 'ky'; + import { DateTime } from 'luxon'; + + const json = await ky('https://example.com', { + stringifyJson: data => JSON.stringify(data, (_, value) => { + if (value instanceof DateTime) { + return value.toSeconds(); + } + + return value; + }) + }).json(); + ``` + */ + stringifyJson?: (data: unknown) => string; + /** Search parameters to include in the request URL. Setting this will override all existing search parameters in the input URL. diff --git a/test/main.ts b/test/main.ts index 7c9933eb..a55ce270 100644 --- a/test/main.ts +++ b/test/main.ts @@ -733,3 +733,24 @@ test('parseJson option with promise.json() shortcut', async t => { await server.close(); }); + +test('stringifyJson option with request.json()', async t => { + const server = await createHttpTestServer({bodyParser: false}); + server.post('/', async (request, response) => { + const body = await parseRawBody(request); + t.is(body, '{"data":{"hello":"world"},"extra":"extraValue"}'); + response.end(); + }); + + const json = {hello: 'world'}; + + await ky.post(server.url, { + stringifyJson: data => JSON.stringify({ + data, + extra: 'extraValue', + }), + json, + }); + + await server.close(); +}); From 512754475b5d8508b6074f6e2abef94664913138 Mon Sep 17 00:00:00 2001 From: Reverier-Xu Date: Sun, 21 Apr 2024 23:15:03 +0800 Subject: [PATCH 02/10] feat: add support for `stringifyJson` --- readme.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/readme.md b/readme.md index b31fbcc3..33ed754a 100644 --- a/readme.md +++ b/readme.md @@ -426,6 +426,29 @@ const json = await ky('https://example.com', { }).json(); ``` +##### stringifyJson + +Type: `Function`\ +Default: `JSON.stringify()` + +User-defined JSON-stringifying function. + +Use-cases: +1. Stringify JSON with the custom `replacer` function. + +```js +import ky from 'ky'; +import { DateTime } from 'luxon'; +const json = await ky('https://example.com', { + stringifyJson: data => JSON.stringify(data, (_, value) => { + if (value instanceof DateTime) { + return value.toSeconds(); + } + return value; + }) +}).json(); +``` + ##### fetch Type: `Function`\ From 1e1e476311873c049bb051eac5fd19c7e350982c Mon Sep 17 00:00:00 2001 From: Reverier-Xu Date: Sun, 21 Apr 2024 23:56:46 +0800 Subject: [PATCH 03/10] fix the example of `stringifyJson` in doc --- readme.md | 6 +++--- source/types/options.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index 33ed754a..44ca2d29 100644 --- a/readme.md +++ b/readme.md @@ -440,9 +440,9 @@ Use-cases: import ky from 'ky'; import { DateTime } from 'luxon'; const json = await ky('https://example.com', { - stringifyJson: data => JSON.stringify(data, (_, value) => { - if (value instanceof DateTime) { - return value.toSeconds(); + stringifyJson: data => JSON.stringify(data, (key, value) => { + if (key.endsWith('_at')) { + return DateTime.fromISO(value).toSeconds(); } return value; }) diff --git a/source/types/options.ts b/source/types/options.ts index bb4ee834..ab41ebb9 100644 --- a/source/types/options.ts +++ b/source/types/options.ts @@ -72,9 +72,9 @@ export type KyOptions = { import { DateTime } from 'luxon'; const json = await ky('https://example.com', { - stringifyJson: data => JSON.stringify(data, (_, value) => { - if (value instanceof DateTime) { - return value.toSeconds(); + stringifyJson: data => JSON.stringify(data, (key, value) => { + if (key.endsWith('_at')) { + return DateTime.fromISO(value).toSeconds(); } return value; From 15ac95bc2615656db35f009332abc5e8b7fdb91d Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Tue, 23 Apr 2024 13:08:48 +0700 Subject: [PATCH 04/10] Update readme.md --- readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 44ca2d29..2df50b20 100644 --- a/readme.md +++ b/readme.md @@ -438,12 +438,14 @@ Use-cases: ```js import ky from 'ky'; -import { DateTime } from 'luxon'; +import {DateTime} from 'luxon'; + const json = await ky('https://example.com', { stringifyJson: data => JSON.stringify(data, (key, value) => { if (key.endsWith('_at')) { return DateTime.fromISO(value).toSeconds(); } + return value; }) }).json(); From c09ed081795dc9e3ce5a6e4016a1ae170bed486e Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Tue, 23 Apr 2024 13:11:34 +0700 Subject: [PATCH 05/10] Update options.ts --- source/types/options.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/types/options.ts b/source/types/options.ts index ab41ebb9..4e2766cf 100644 --- a/source/types/options.ts +++ b/source/types/options.ts @@ -69,7 +69,7 @@ export type KyOptions = { @example ``` import ky from 'ky'; - import { DateTime } from 'luxon'; + import {DateTime} from 'luxon'; const json = await ky('https://example.com', { stringifyJson: data => JSON.stringify(data, (key, value) => { @@ -81,7 +81,7 @@ export type KyOptions = { }) }).json(); ``` - */ + */ stringifyJson?: (data: unknown) => string; /** From a022cf60a54725d85f6e91c2d2f8b11b13c3c8eb Mon Sep 17 00:00:00 2001 From: Reverier-Xu Date: Tue, 23 Apr 2024 14:27:24 +0800 Subject: [PATCH 06/10] fix code styles --- source/core/Ky.ts | 2 +- test/main.ts | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/source/core/Ky.ts b/source/core/Ky.ts index 5098a837..8477a2cf 100644 --- a/source/core/Ky.ts +++ b/source/core/Ky.ts @@ -203,7 +203,7 @@ export class Ky { } if (this._options.json !== undefined) { - this._options.body = this._options.stringifyJson ? this._options.stringifyJson(this._options.json) : JSON.stringify(this._options.json); + this._options.body = this._options.stringifyJson?.(this._options.json) ?? JSON.stringify(this._options.json); this.request.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json'); this.request = new globalThis.Request(this.request, {body: this._options.body}); } diff --git a/test/main.ts b/test/main.ts index a55ce270..e8aaff74 100644 --- a/test/main.ts +++ b/test/main.ts @@ -736,14 +736,16 @@ test('parseJson option with promise.json() shortcut', async t => { test('stringifyJson option with request.json()', async t => { const server = await createHttpTestServer({bodyParser: false}); + + const json = {hello: 'world'}; + const result = {data: json, extra: 'extraValue'}; + server.post('/', async (request, response) => { const body = await parseRawBody(request); - t.is(body, '{"data":{"hello":"world"},"extra":"extraValue"}'); + t.is(body, JSON.stringify(result)); response.end(); }); - const json = {hello: 'world'}; - await ky.post(server.url, { stringifyJson: data => JSON.stringify({ data, From bb063e5a6f851e720944554eebbe187506fb782a Mon Sep 17 00:00:00 2001 From: Reverier-Xu Date: Tue, 23 Apr 2024 14:29:17 +0800 Subject: [PATCH 07/10] fix styles --- test/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/main.ts b/test/main.ts index e8aaff74..28105286 100644 --- a/test/main.ts +++ b/test/main.ts @@ -736,7 +736,7 @@ test('parseJson option with promise.json() shortcut', async t => { test('stringifyJson option with request.json()', async t => { const server = await createHttpTestServer({bodyParser: false}); - + const json = {hello: 'world'}; const result = {data: json, extra: 'extraValue'}; From 5aa769349230d7e8ff611c22f3639c0c6c8a70fc Mon Sep 17 00:00:00 2001 From: Reverier Xu Date: Tue, 23 Apr 2024 16:21:33 +0800 Subject: [PATCH 08/10] Simplify stringifyJson test case Co-authored-by: Sindre Sorhus --- test/main.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/main.ts b/test/main.ts index 28105286..7d02c58d 100644 --- a/test/main.ts +++ b/test/main.ts @@ -738,19 +738,16 @@ test('stringifyJson option with request.json()', async t => { const server = await createHttpTestServer({bodyParser: false}); const json = {hello: 'world'}; - const result = {data: json, extra: 'extraValue'}; + const extra = 'extraValue'; server.post('/', async (request, response) => { const body = await parseRawBody(request); - t.is(body, JSON.stringify(result)); + t.is(body, JSON.stringify({data: json, extra})); response.end(); }); await ky.post(server.url, { - stringifyJson: data => JSON.stringify({ - data, - extra: 'extraValue', - }), + stringifyJson: data => JSON.stringify({data, extra}), json, }); From 959fa6ce04b6f5bd024630dabee0cc58def2b056 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Fri, 31 May 2024 18:27:29 +0200 Subject: [PATCH 09/10] Update options.ts --- source/types/options.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/types/options.ts b/source/types/options.ts index 4e2766cf..22fd0651 100644 --- a/source/types/options.ts +++ b/source/types/options.ts @@ -62,7 +62,7 @@ export type KyOptions = { User-defined JSON-stringifying function. Use-cases: - 1. Stringify JSON with the custom `replacer` function. + 1. Stringify JSON with a custom `replacer` function. @default JSON.stringify() From 6ed3a6fcb07d39a2eedf803e3670e9e54b2478b2 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Fri, 31 May 2024 18:27:34 +0200 Subject: [PATCH 10/10] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index fe375356..d410de48 100644 --- a/readme.md +++ b/readme.md @@ -436,7 +436,7 @@ Default: `JSON.stringify()` User-defined JSON-stringifying function. Use-cases: -1. Stringify JSON with the custom `replacer` function. +1. Stringify JSON with a custom `replacer` function. ```js import ky from 'ky';