diff --git a/src/PostgrestBuilder.ts b/src/PostgrestBuilder.ts index 96a8bc55..efb221d8 100644 --- a/src/PostgrestBuilder.ts +++ b/src/PostgrestBuilder.ts @@ -1,8 +1,7 @@ // @ts-ignore import nodeFetch from '@supabase/node-fetch' -import type { Fetch, PostgrestSingleResponse } from './types' -import PostgrestError from './PostgrestError' +import type { Fetch, PostgrestResponseSuccess, PostgrestSingleResponse } from './types' export default abstract class PostgrestBuilder implements PromiseLike> @@ -12,7 +11,6 @@ export default abstract class PostgrestBuilder protected headers: Record protected schema?: string protected body?: unknown - protected shouldThrowOnError = false protected signal?: AbortSignal protected fetch: Fetch protected isMaybeSingle: boolean @@ -23,7 +21,6 @@ export default abstract class PostgrestBuilder this.headers = builder.headers this.schema = builder.schema this.body = builder.body - this.shouldThrowOnError = builder.shouldThrowOnError this.signal = builder.signal this.isMaybeSingle = builder.isMaybeSingle @@ -39,12 +36,20 @@ export default abstract class PostgrestBuilder /** * If there's an error with the query, throwOnError will reject the promise by * throwing the error instead of returning it as part of a successful response. + * also return `PostgrestResponseSuccess` type for correct type inference * - * {@link https://github.com/supabase/supabase-js/issues/92} + * {@link https://github.com/supabase/supabase-js/issues/801} */ - throwOnError(): this { - this.shouldThrowOnError = true - return this + throwOnError(): PromiseLike> { + return this.then>( + (response) => { + if (response.error) throw response.error + return response as PostgrestResponseSuccess + }, + (error) => { + throw error + } + ) } then, TResult2 = never>( @@ -155,10 +160,6 @@ export default abstract class PostgrestBuilder status = 200 statusText = 'OK' } - - if (error && this.shouldThrowOnError) { - throw new PostgrestError(error) - } } const postgrestResponse = { @@ -171,20 +172,18 @@ export default abstract class PostgrestBuilder return postgrestResponse }) - if (!this.shouldThrowOnError) { - res = res.catch((fetchError) => ({ - error: { - message: `${fetchError?.name ?? 'FetchError'}: ${fetchError?.message}`, - details: `${fetchError?.stack ?? ''}`, - hint: '', - code: `${fetchError?.code ?? ''}`, - }, - data: null, - count: null, - status: 0, - statusText: '', - })) - } + res = res.catch((fetchError) => ({ + error: { + message: `${fetchError?.name ?? 'FetchError'}: ${fetchError?.message}`, + details: `${fetchError?.stack ?? ''}`, + hint: '', + code: `${fetchError?.code ?? ''}`, + }, + data: null, + count: null, + status: 0, + statusText: '', + })) return res.then(onfulfilled, onrejected) } diff --git a/test/basic.ts b/test/basic.ts index 9a170019..9f960c1d 100644 --- a/test/basic.ts +++ b/test/basic.ts @@ -640,6 +640,13 @@ test('throwOnError throws errors instead of returning them', async () => { expect(isErrorCaught).toBe(true) }) +test('throwOnError should return response success type', async () => { + const { data, error } = await postgrest.from('users').select().throwOnError() + + expect(data).not.toBeNull() + expect(error).toBeNull() +}) + test('throwOnError throws errors which include stack', async () => { try { await postgrest.from('does_not_exist').select().throwOnError() @@ -692,25 +699,22 @@ test('throwOnError throws errors which include stack', async () => { test('connection error w/o throwing', async () => { const postgrest = new PostgrestClient('http://foo.invalid') let isErrorCaught = false - await postgrest - .from('users') - .select() - .then(undefined, () => { - isErrorCaught = true - }) + try { + await postgrest.from('users').select() + } catch (_) { + isErrorCaught = true + } expect(isErrorCaught).toBe(false) }) test('connection error w/ throwOnError', async () => { const postgrest = new PostgrestClient('http://foo.invalid') let isErrorCaught = false - await postgrest - .from('users') - .select() - .throwOnError() - .then(undefined, () => { - isErrorCaught = true - }) + try { + await postgrest.from('users').select().throwOnError() + } catch (_) { + isErrorCaught = true + } expect(isErrorCaught).toBe(true) }) @@ -720,8 +724,8 @@ test('maybeSingle w/ throwOnError', async () => { .from('messages') .select() .eq('message', 'i do not exist') - .throwOnError() .maybeSingle() + .throwOnError() .then(undefined, () => { passes = false }) @@ -1418,4 +1422,4 @@ test('update with no match - return=representation', async () => { "statusText": "OK", } `) -}) +}) \ No newline at end of file diff --git a/test/transforms.ts b/test/transforms.ts index a7ca4e76..509bf67e 100644 --- a/test/transforms.ts +++ b/test/transforms.ts @@ -276,10 +276,10 @@ test('abort signal', async () => { "count": null, "data": null, "error": Object { - "code": "", + "code": "20", "details": Any, "hint": "", - "message": "AbortError: The user aborted a request.", + "message": "AbortError: This operation was aborted", }, "status": 0, "statusText": "",