From 9f7dc1deb4fe7518c94d8861e02831e4e4a6ca67 Mon Sep 17 00:00:00 2001 From: Christian Farris Date: Thu, 16 Sep 2021 19:15:42 -0500 Subject: [PATCH 01/12] feat: take in parse option --- src/fetch.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fetch.ts b/src/fetch.ts index 93f6736..a116710 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -15,6 +15,7 @@ export interface FetchOptions extends Omit { baseURL?: string body?: RequestInit['body'] | Record params?: SearchParams + parse?: 'destr' | 'JSON.parse' | boolean response?: boolean } @@ -67,7 +68,7 @@ export function createFetch ({ fetch }: CreateFetchOptions): $Fetch { } const $fetch = function (request, opts) { - return raw(request, opts).then(r => r.data) + return raw(request, { parse: true, ...opts }).then(r => r.data) } as $Fetch $fetch.raw = raw From afb61a25a13ff04daffa6bc37e737e0d5433b429 Mon Sep 17 00:00:00 2001 From: Christian Farris Date: Thu, 16 Sep 2021 19:24:39 -0500 Subject: [PATCH 02/12] feat: allow for function to be passed for use to parse response --- src/fetch.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fetch.ts b/src/fetch.ts index a116710..8fead1d 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -15,7 +15,7 @@ export interface FetchOptions extends Omit { baseURL?: string body?: RequestInit['body'] | Record params?: SearchParams - parse?: 'destr' | 'JSON.parse' | boolean + parse?: (text: string) => any response?: boolean } @@ -60,7 +60,7 @@ export function createFetch ({ fetch }: CreateFetchOptions): $Fetch { } const response: FetchResponse = await fetch(request, opts as RequestInit) const text = await response.text() - response.data = destr(text) + response.data = opts?.parse ? opts.parse(text) : text if (!response.ok) { throw createFetchError(request, response) } @@ -68,7 +68,7 @@ export function createFetch ({ fetch }: CreateFetchOptions): $Fetch { } const $fetch = function (request, opts) { - return raw(request, { parse: true, ...opts }).then(r => r.data) + return raw(request, { parse: destr, ...opts }).then(r => r.data) } as $Fetch $fetch.raw = raw From 34f28930f7b329c52feba78c7f75559416cf022c Mon Sep 17 00:00:00 2001 From: Christian Farris Date: Thu, 16 Sep 2021 19:32:19 -0500 Subject: [PATCH 03/12] feat: allow for false parse flag --- src/fetch.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/fetch.ts b/src/fetch.ts index 8fead1d..50f3468 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -3,6 +3,9 @@ import { joinURL, withQuery } from 'ufo' import type { Fetch, RequestInfo, RequestInit, Response } from './types' import { createFetchError } from './error' +type Parser = (text: string) => any +type GetParser = (parse: Parser | boolean | undefined) => Parser | undefined + export interface CreateFetchOptions { fetch: Fetch } export type FetchRequest = RequestInfo @@ -15,7 +18,7 @@ export interface FetchOptions extends Omit { baseURL?: string body?: RequestInit['body'] | Record params?: SearchParams - parse?: (text: string) => any + parse?: Parser | boolean response?: boolean } @@ -26,6 +29,16 @@ export interface $Fetch { raw(request: FetchRequest, opts?: FetchOptions): Promise> } +const getParser: GetParser = (parse) => { + if (!parse) { + return undefined + } + + return typeof parse === 'boolean' + ? destr + : parse +} + export function setHeader (options: FetchOptions, _key: string, value: string) { const key = _key.toLowerCase() options.headers = options.headers || {} @@ -60,7 +73,8 @@ export function createFetch ({ fetch }: CreateFetchOptions): $Fetch { } const response: FetchResponse = await fetch(request, opts as RequestInit) const text = await response.text() - response.data = opts?.parse ? opts.parse(text) : text + const parse = getParser(opts?.parse) + response.data = parse ? parse(text) : text if (!response.ok) { throw createFetchError(request, response) } From 5c623d51d04ec5de64f3df95f29e9ef4ba814edf Mon Sep 17 00:00:00 2001 From: Christian Farris Date: Thu, 16 Sep 2021 19:33:27 -0500 Subject: [PATCH 04/12] refactor: be more specific in conditional --- src/fetch.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/fetch.ts b/src/fetch.ts index 50f3468..28c819e 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -34,9 +34,7 @@ const getParser: GetParser = (parse) => { return undefined } - return typeof parse === 'boolean' - ? destr - : parse + return parse === true ? destr : parse } export function setHeader (options: FetchOptions, _key: string, value: string) { From a31a0a993be99bdf28d54be145e418f91c8f57cc Mon Sep 17 00:00:00 2001 From: Christian Farris Date: Thu, 16 Sep 2021 19:39:15 -0500 Subject: [PATCH 05/12] refactor: update README to include custom parsing instructions --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 11a7747..b04214c 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,18 @@ const response = await $fetch.raw('/sushi') // ... ``` +## ✔️ Custom JSON parsing + +By using `parse` option, `$fetch` determines how to parse data. + +```js +// Disable JSON parsing +await $fetch('/movie?lang=en', { parse: false }) + +// Use JSON.parse to parse +await $fetch('/movie?lang=en', { parse: JSON.parse }) +``` + ## 📦 Bundler Notes - All targets are exported with Module and CommonJS format and named exports From 818863b7849cea6bd9b3122a05a66887bff9b5c7 Mon Sep 17 00:00:00 2001 From: Christian Farris Date: Fri, 24 Sep 2021 18:16:45 -0500 Subject: [PATCH 06/12] test: custom parsing with custom parser and with false --- test/index.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/index.test.ts b/test/index.test.ts index baccee0..e945ec8 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,3 +1,4 @@ +import destr from 'destr' import { listen, Listener } from 'listhen' import { getQuery, joinURL } from 'ufo' import { createApp, useBody } from 'h3' @@ -25,6 +26,17 @@ describe('ohmyfetch', () => { expect(await $fetch(getURL('ok'))).toBe('ok') }) + it('custom parse', async () => { + const parser = jest.fn().mockReturnValue('asdf') + await $fetch(getURL('ok'), { parse: parser }) + expect(parser).toHaveBeenCalledTimes(1) + }) + + it('custom parse false', async () => { + await $fetch(getURL('ok'), { parse: false }) + expect(destr).toHaveBeenCalledTimes(0) + }) + it('baseURL', async () => { expect(await $fetch('/x?foo=123', { baseURL: getURL('url') })).toBe('/x?foo=123') }) From e445ba8af00526a6aa7c54880f219e84402f43c8 Mon Sep 17 00:00:00 2001 From: Christian Farris Date: Fri, 24 Sep 2021 18:44:54 -0500 Subject: [PATCH 07/12] fix: failing test --- test/index.test.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/index.test.ts b/test/index.test.ts index e945ec8..7cb173e 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,4 +1,3 @@ -import destr from 'destr' import { listen, Listener } from 'listhen' import { getQuery, joinURL } from 'ufo' import { createApp, useBody } from 'h3' @@ -9,7 +8,7 @@ describe('ohmyfetch', () => { let listener: Listener const getURL = (url: string) => joinURL(listener.url, url) - it('setup', async () => { + beforeEach(async () => { const app = createApp() .use('/ok', () => 'ok') .use('/params', req => (getQuery(req.url || ''))) @@ -18,8 +17,9 @@ describe('ohmyfetch', () => { listener = await listen(app) }) - afterAll(async () => { + afterEach(async () => { await listener.close() + jest.resetAllMocks() }) it('ok', async () => { @@ -33,8 +33,7 @@ describe('ohmyfetch', () => { }) it('custom parse false', async () => { - await $fetch(getURL('ok'), { parse: false }) - expect(destr).toHaveBeenCalledTimes(0) + expect(await $fetch(getURL('ok'), { parse: false })).toBe('ok') }) it('baseURL', async () => { From 3982d0d702c93e5964001bd928ebe9adb84ea2c6 Mon Sep 17 00:00:00 2001 From: Christian Farris Date: Fri, 24 Sep 2021 18:48:19 -0500 Subject: [PATCH 08/12] refactor: remove extra resetAllMocks --- test/index.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/index.test.ts b/test/index.test.ts index 7cb173e..00419f5 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -19,7 +19,6 @@ describe('ohmyfetch', () => { afterEach(async () => { await listener.close() - jest.resetAllMocks() }) it('ok', async () => { From 0fa806d4d192a941f8b5132c31aef9b134af1333 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 22 Oct 2021 17:08:02 +0200 Subject: [PATCH 09/12] simplify with `parseResponse` option --- src/fetch.ts | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/fetch.ts b/src/fetch.ts index 28c819e..e7b61d2 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -3,9 +3,6 @@ import { joinURL, withQuery } from 'ufo' import type { Fetch, RequestInfo, RequestInit, Response } from './types' import { createFetchError } from './error' -type Parser = (text: string) => any -type GetParser = (parse: Parser | boolean | undefined) => Parser | undefined - export interface CreateFetchOptions { fetch: Fetch } export type FetchRequest = RequestInfo @@ -18,7 +15,7 @@ export interface FetchOptions extends Omit { baseURL?: string body?: RequestInit['body'] | Record params?: SearchParams - parse?: Parser | boolean + parseResponse?: (responseText: string) => any response?: boolean } @@ -29,14 +26,6 @@ export interface $Fetch { raw(request: FetchRequest, opts?: FetchOptions): Promise> } -const getParser: GetParser = (parse) => { - if (!parse) { - return undefined - } - - return parse === true ? destr : parse -} - export function setHeader (options: FetchOptions, _key: string, value: string) { const key = _key.toLowerCase() options.headers = options.headers || {} @@ -56,8 +45,8 @@ export function setHeader (options: FetchOptions, _key: string, value: string) { } export function createFetch ({ fetch }: CreateFetchOptions): $Fetch { - const raw: $Fetch['raw'] = async function (request, opts) { - if (opts && typeof request === 'string') { + const raw: $Fetch['raw'] = async function (request, opts = {}) { + if (typeof request === 'string') { if (opts.baseURL) { request = joinURL(opts.baseURL, request) } @@ -71,8 +60,8 @@ export function createFetch ({ fetch }: CreateFetchOptions): $Fetch { } const response: FetchResponse = await fetch(request, opts as RequestInit) const text = await response.text() - const parse = getParser(opts?.parse) - response.data = parse ? parse(text) : text + const parseFn = opts.parseResponse || destr + response.data = parseFn(text) if (!response.ok) { throw createFetchError(request, response) } @@ -80,7 +69,7 @@ export function createFetch ({ fetch }: CreateFetchOptions): $Fetch { } const $fetch = function (request, opts) { - return raw(request, { parse: destr, ...opts }).then(r => r.data) + return raw(request, opts).then(r => r.data) } as $Fetch $fetch.raw = raw From 0138978f4fc0c23f61266cf27a6df7729432dd55 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 22 Oct 2021 17:08:07 +0200 Subject: [PATCH 10/12] update tests --- test/index.test.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/index.test.ts b/test/index.test.ts index 00419f5..1e9cc8e 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -8,7 +8,7 @@ describe('ohmyfetch', () => { let listener: Listener const getURL = (url: string) => joinURL(listener.url, url) - beforeEach(async () => { + beforeAll(async () => { const app = createApp() .use('/ok', () => 'ok') .use('/params', req => (getQuery(req.url || ''))) @@ -17,7 +17,7 @@ describe('ohmyfetch', () => { listener = await listen(app) }) - afterEach(async () => { + afterAll(async () => { await listener.close() }) @@ -25,16 +25,12 @@ describe('ohmyfetch', () => { expect(await $fetch(getURL('ok'))).toBe('ok') }) - it('custom parse', async () => { + it('custom parseResponse', async () => { const parser = jest.fn().mockReturnValue('asdf') - await $fetch(getURL('ok'), { parse: parser }) + await $fetch(getURL('ok'), { parseResponse: parser }) expect(parser).toHaveBeenCalledTimes(1) }) - it('custom parse false', async () => { - expect(await $fetch(getURL('ok'), { parse: false })).toBe('ok') - }) - it('baseURL', async () => { expect(await $fetch('/x?foo=123', { baseURL: getURL('url') })).toBe('/x?foo=123') }) From 8b81062a80734ac5e278dec4a49704642378e57b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 22 Oct 2021 17:08:10 +0200 Subject: [PATCH 11/12] update readme --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index b04214c..d5ca17c 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,13 @@ We use [conditional exports](https://nodejs.org/api/packages.html#packages_condi const { users } = await $fetch('/api/users') ``` +You can optionally provde a different parser than destr. + +```js +// Use JSON.parse +await $fetch('/movie?lang=en', { parseResponse: JSON.parse }) +``` + ## ✔️ JSON Body `$fetch` automatically stringifies request body (if an object is passed) and adds JSON `Content-Type` headers (for `put`, `patch` and `post` requests). From f484a445087c8ec438a419e27287aae0dba1c029 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 22 Oct 2021 17:09:46 +0200 Subject: [PATCH 12/12] remove duplicate docs --- README.md | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d5ca17c..662ff5b 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,9 @@ You can optionally provde a different parser than destr. ```js // Use JSON.parse await $fetch('/movie?lang=en', { parseResponse: JSON.parse }) + +// Return text as is +await $fetch('/movie?lang=en', { parseResponse: txt => txt }) ``` ## ✔️ JSON Body @@ -117,18 +120,6 @@ const response = await $fetch.raw('/sushi') // ... ``` -## ✔️ Custom JSON parsing - -By using `parse` option, `$fetch` determines how to parse data. - -```js -// Disable JSON parsing -await $fetch('/movie?lang=en', { parse: false }) - -// Use JSON.parse to parse -await $fetch('/movie?lang=en', { parse: JSON.parse }) -``` - ## 📦 Bundler Notes - All targets are exported with Module and CommonJS format and named exports