diff --git a/src/PostgrestBuilder.ts b/src/PostgrestBuilder.ts index 2c3863e2..dfd8a3c0 100644 --- a/src/PostgrestBuilder.ts +++ b/src/PostgrestBuilder.ts @@ -1,7 +1,7 @@ // @ts-ignore import nodeFetch from '@supabase/node-fetch' -import type { Fetch, PostgrestSingleResponse, PostgrestResponseSuccess } from './types' +import type { Fetch, FetchOptions, PostgrestSingleResponse, PostgrestResponseSuccess } from './types' import PostgrestError from './PostgrestError' export default abstract class PostgrestBuilder @@ -16,7 +16,7 @@ export default abstract class PostgrestBuilder = {} protected fetch: Fetch protected isMaybeSingle: boolean @@ -27,7 +27,7 @@ export default abstract class PostgrestBuilder { let error = null let data = null diff --git a/src/PostgrestTransformBuilder.ts b/src/PostgrestTransformBuilder.ts index 2be085c8..74772990 100644 --- a/src/PostgrestTransformBuilder.ts +++ b/src/PostgrestTransformBuilder.ts @@ -1,6 +1,6 @@ import PostgrestBuilder from './PostgrestBuilder' -import { GetResult } from './select-query-parser/result' -import { GenericSchema } from './types' +import { GetResult } from './select-query-parser/reesult' +import type { FetchOptions, GenericSchema } from './types' export default class PostgrestTransformBuilder< Schema extends GenericSchema, @@ -176,9 +176,43 @@ export default class PostgrestTransformBuilder< * Set the AbortSignal for the fetch request. * * @param signal - The AbortSignal to use for the fetch request + * @deprecated Use fetchOptions instead. E.g. `fetchOptions({ signal: new AbortController().signal })` */ abortSignal(signal: AbortSignal): this { - this.signal = signal + this.fetchOptions({ signal }) + + return this + } + + /** + * Set fetch options for the request. + * + * @param init - Fetch options. + */ + fetchOptions(init: FetchOptions): this { + const { headers, ...rest } = init + + this.fetchOpts = { + ...this.fetchOpts, + ...rest, + } + + if (headers) { + let entries: Iterable + + if (Array.isArray(headers)) { + entries = headers.values() + } else if (headers instanceof Headers) { + entries = headers.entries() + } else { + entries = Object.entries(headers) + } + + for (const [name, val] of entries) { + this.headers[name] = val + } + } + return this } diff --git a/src/types.ts b/src/types.ts index fd1378ce..effd6628 100644 --- a/src/types.ts +++ b/src/types.ts @@ -71,6 +71,7 @@ export type GenericSchema = { // https://twitter.com/mattpocockuk/status/1622730173446557697 export type Prettify = { [K in keyof T]: T[K] } & {} + // https://github.com/sindresorhus/type-fest export type SimplifyDeep = ConditionalSimplifyDeep< Type, @@ -89,3 +90,5 @@ type ConditionalSimplifyDeep< type NonRecursiveType = BuiltIns | Function | (new (...arguments_: any[]) => unknown) type BuiltIns = Primitive | void | Date | RegExp type Primitive = null | undefined | string | number | boolean | symbol | bigint + +export type FetchOptions = Omit diff --git a/test/transforms.ts b/test/transforms.ts index 10892d8f..46904309 100644 --- a/test/transforms.ts +++ b/test/transforms.ts @@ -2,6 +2,8 @@ import { PostgrestClient } from '../src/index' import { Database } from './types' import { AbortController } from 'node-abort-controller' +// @ts-ignore +import nodeFetch from '@supabase/node-fetch' const postgrest = new PostgrestClient('http://localhost:3000') @@ -539,3 +541,57 @@ test('rollback delete', async () => { } `) }) + +test('Next.js options', async () => { + let fetchImpl = fetch + if (typeof fetchImpl === 'undefined') { + fetchImpl = nodeFetch + } + const fetchSpy = jest.fn(fetchImpl) + + const postgrest = new PostgrestClient('http://localhost:3000', { + fetch: fetchSpy, + }) + + const builder = postgrest + .from('users') + .select() + .eq('username', 'supabot') + .fetchOptions({ + next: { + tags: ['users', 'supabot'], + }, + } as any) + const res = await builder + expect(res).toMatchInlineSnapshot(` + Object { + "count": null, + "data": Array [ + Object { + "age_range": "[1,2)", + "catchphrase": "'cat' 'fat'", + "data": null, + "status": "ONLINE", + "username": "supabot", + }, + ], + "error": null, + "status": 200, + "statusText": "OK", + } + `) + expect(fetchSpy).toHaveBeenCalledWith( + 'http://localhost:3000/users?select=*&username=eq.supabot', + { + body: undefined, + headers: { + 'X-Client-Info': 'postgrest-js/0.0.0-automated', + }, + method: 'GET', + next: { + tags: ['users', 'supabot'], + }, + signal: undefined, + } + ) +})