From 03211bea19d3e30314be78aa9949f42a737905d7 Mon Sep 17 00:00:00 2001 From: dogukanakkaya Date: Sun, 30 Jul 2023 14:26:18 +0300 Subject: [PATCH 1/3] fix: throwOnError function call should return response success type always --- src/PostgrestBuilder.ts | 50 +++++++------- test/basic.ts | 141 ++++++++++++++++++++++++++-------------- test/transforms.ts | 4 +- 3 files changed, 119 insertions(+), 76 deletions(-) diff --git a/src/PostgrestBuilder.ts b/src/PostgrestBuilder.ts index e48d69f0..a196c246 100644 --- a/src/PostgrestBuilder.ts +++ b/src/PostgrestBuilder.ts @@ -1,6 +1,6 @@ import crossFetch from 'cross-fetch' -import type { Fetch, PostgrestSingleResponse } from './types' +import type { Fetch, PostgrestResponseSuccess, PostgrestSingleResponse } from './types' export default abstract class PostgrestBuilder implements PromiseLike> @@ -10,7 +10,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 @@ -21,7 +20,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 @@ -37,12 +35,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 data nonnullable 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>( @@ -153,10 +159,6 @@ export default abstract class PostgrestBuilder status = 200 statusText = 'OK' } - - if (error && this.shouldThrowOnError) { - throw error - } } const postgrestResponse = { @@ -169,20 +171,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 9e7951fd..62d58fb9 100644 --- a/test/basic.ts +++ b/test/basic.ts @@ -249,7 +249,7 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 1, "data": null, - "id": 3, + "id": 87, "message": "foo", "username": "supabot", }, @@ -282,7 +282,7 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 1, "data": null, - "id": 3, + "id": 87, "message": "foo", "username": "supabot", }, @@ -336,6 +336,13 @@ describe('basic insert, update, delete', () => { "message": "Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.", "username": "supabot", }, + Object { + "channel_id": 1, + "data": null, + "id": 87, + "message": "foo", + "username": "supabot", + }, Object { "channel_id": 2, "data": null, @@ -366,14 +373,14 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 1, "data": null, - "id": 4, + "id": 88, "message": "foo", "username": "supabot", }, Object { "channel_id": 1, "data": null, - "id": 5, + "id": 89, "message": "foo", "username": "supabot", }, @@ -403,6 +410,13 @@ describe('basic insert, update, delete', () => { "message": "Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.", "username": "supabot", }, + Object { + "channel_id": 1, + "data": null, + "id": 87, + "message": "foo", + "username": "supabot", + }, Object { "channel_id": 2, "data": null, @@ -413,14 +427,14 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 1, "data": null, - "id": 4, + "id": 88, "message": "foo", "username": "supabot", }, Object { "channel_id": 1, "data": null, - "id": 5, + "id": 89, "message": "foo", "username": "supabot", }, @@ -442,6 +456,13 @@ describe('basic insert, update, delete', () => { Object { "count": null, "data": Array [ + Object { + "channel_id": 2, + "data": null, + "id": 87, + "message": "foo", + "username": "supabot", + }, Object { "channel_id": 2, "data": null, @@ -452,14 +473,14 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 2, "data": null, - "id": 4, + "id": 88, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 5, + "id": 89, "message": "foo", "username": "supabot", }, @@ -489,6 +510,13 @@ describe('basic insert, update, delete', () => { "message": "Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.", "username": "supabot", }, + Object { + "channel_id": 2, + "data": null, + "id": 87, + "message": "foo", + "username": "supabot", + }, Object { "channel_id": 2, "data": null, @@ -499,14 +527,14 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 2, "data": null, - "id": 4, + "id": 88, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 5, + "id": 89, "message": "foo", "username": "supabot", }, @@ -524,6 +552,13 @@ describe('basic insert, update, delete', () => { Object { "count": null, "data": Array [ + Object { + "channel_id": 2, + "data": null, + "id": 87, + "message": "foo", + "username": "supabot", + }, Object { "channel_id": 2, "data": null, @@ -534,14 +569,14 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 2, "data": null, - "id": 4, + "id": 88, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 5, + "id": 89, "message": "foo", "username": "supabot", }, @@ -600,6 +635,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 setting at the client level - query', async () => { // let isErrorCaught = false // const postgrest_ = new PostgrestClient(REST_URL, { throwOnError: true }) @@ -643,25 +685,26 @@ test('throwOnError throws errors instead of returning them', 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) }) @@ -671,8 +714,8 @@ test('maybeSingle w/ throwOnError', async () => { .from('messages') .select() .eq('message', 'i do not exist') - .throwOnError() .maybeSingle() + .throwOnError() .then(undefined, () => { passes = false }) @@ -768,8 +811,8 @@ test('select with head:true, count:planned', async () => { "count": Any, "data": null, "error": null, - "status": 206, - "statusText": "Partial Content", + "status": 200, + "statusText": "OK", } ` ) @@ -786,8 +829,8 @@ test('select with head:true, count:estimated', async () => { "count": Any, "data": null, "error": null, - "status": 206, - "statusText": "Partial Content", + "status": 200, + "statusText": "OK", } ` ) @@ -878,7 +921,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 6, + "id": 90, "message": "foo", "username": "supabot", }, @@ -911,7 +954,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 6, + "id": 90, "message": "foo", "username": "supabot", }, @@ -968,7 +1011,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 6, + "id": 90, "message": "foo", "username": "supabot", }, @@ -1005,14 +1048,14 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 7, + "id": 91, "message": "foo", "username": "supabot", }, Object { "channel_id": 1, "data": null, - "id": 8, + "id": 92, "message": "foo", "username": "supabot", }, @@ -1045,7 +1088,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 6, + "id": 90, "message": "foo", "username": "supabot", }, @@ -1059,14 +1102,14 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 7, + "id": 91, "message": "foo", "username": "supabot", }, Object { "channel_id": 1, "data": null, - "id": 8, + "id": 92, "message": "foo", "username": "supabot", }, @@ -1095,7 +1138,7 @@ describe("insert, update, delete with count: 'exact'", () => { }, Object { "data": null, - "id": 4, + "id": 60, "slug": "test-slug", }, ], @@ -1123,7 +1166,7 @@ describe("insert, update, delete with count: 'exact'", () => { }, Object { "data": null, - "id": 6, + "id": 62, "slug": "test-slug", }, ], @@ -1147,7 +1190,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 6, + "id": 90, "message": "foo", "username": "supabot", }, @@ -1161,14 +1204,14 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 7, + "id": 91, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 8, + "id": 92, "message": "foo", "username": "supabot", }, @@ -1201,7 +1244,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 6, + "id": 90, "message": "foo", "username": "supabot", }, @@ -1215,14 +1258,14 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 7, + "id": 91, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 8, + "id": 92, "message": "foo", "username": "supabot", }, @@ -1247,7 +1290,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 6, + "id": 90, "message": "foo", "username": "supabot", }, @@ -1261,14 +1304,14 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 7, + "id": 91, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 8, + "id": 92, "message": "foo", "username": "supabot", }, diff --git a/test/transforms.ts b/test/transforms.ts index cce8e227..edb0abd6 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": "", From be6b57353d4e107e370bdbc5690b13b73ded64f3 Mon Sep 17 00:00:00 2001 From: dogukanakkaya Date: Sun, 30 Jul 2023 14:33:02 +0300 Subject: [PATCH 2/3] chore: revert changes done by test --- src/PostgrestBuilder.ts | 2 +- test/basic.ts | 111 +++++++++++++--------------------------- 2 files changed, 37 insertions(+), 76 deletions(-) diff --git a/src/PostgrestBuilder.ts b/src/PostgrestBuilder.ts index a196c246..0c6ecbb6 100644 --- a/src/PostgrestBuilder.ts +++ b/src/PostgrestBuilder.ts @@ -35,7 +35,7 @@ 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 data nonnullable type for correct type inference + * also return `PostgrestResponseSuccess` type for correct type inference * * {@link https://github.com/supabase/supabase-js/issues/801} */ diff --git a/test/basic.ts b/test/basic.ts index 62d58fb9..a546e751 100644 --- a/test/basic.ts +++ b/test/basic.ts @@ -249,7 +249,7 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 1, "data": null, - "id": 87, + "id": 3, "message": "foo", "username": "supabot", }, @@ -282,7 +282,7 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 1, "data": null, - "id": 87, + "id": 3, "message": "foo", "username": "supabot", }, @@ -336,13 +336,6 @@ describe('basic insert, update, delete', () => { "message": "Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.", "username": "supabot", }, - Object { - "channel_id": 1, - "data": null, - "id": 87, - "message": "foo", - "username": "supabot", - }, Object { "channel_id": 2, "data": null, @@ -373,14 +366,14 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 1, "data": null, - "id": 88, + "id": 4, "message": "foo", "username": "supabot", }, Object { "channel_id": 1, "data": null, - "id": 89, + "id": 5, "message": "foo", "username": "supabot", }, @@ -410,13 +403,6 @@ describe('basic insert, update, delete', () => { "message": "Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.", "username": "supabot", }, - Object { - "channel_id": 1, - "data": null, - "id": 87, - "message": "foo", - "username": "supabot", - }, Object { "channel_id": 2, "data": null, @@ -427,14 +413,14 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 1, "data": null, - "id": 88, + "id": 4, "message": "foo", "username": "supabot", }, Object { "channel_id": 1, "data": null, - "id": 89, + "id": 5, "message": "foo", "username": "supabot", }, @@ -456,13 +442,6 @@ describe('basic insert, update, delete', () => { Object { "count": null, "data": Array [ - Object { - "channel_id": 2, - "data": null, - "id": 87, - "message": "foo", - "username": "supabot", - }, Object { "channel_id": 2, "data": null, @@ -473,14 +452,14 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 2, "data": null, - "id": 88, + "id": 4, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 89, + "id": 5, "message": "foo", "username": "supabot", }, @@ -510,13 +489,6 @@ describe('basic insert, update, delete', () => { "message": "Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.", "username": "supabot", }, - Object { - "channel_id": 2, - "data": null, - "id": 87, - "message": "foo", - "username": "supabot", - }, Object { "channel_id": 2, "data": null, @@ -527,14 +499,14 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 2, "data": null, - "id": 88, + "id": 4, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 89, + "id": 5, "message": "foo", "username": "supabot", }, @@ -552,13 +524,6 @@ describe('basic insert, update, delete', () => { Object { "count": null, "data": Array [ - Object { - "channel_id": 2, - "data": null, - "id": 87, - "message": "foo", - "username": "supabot", - }, Object { "channel_id": 2, "data": null, @@ -569,14 +534,14 @@ describe('basic insert, update, delete', () => { Object { "channel_id": 2, "data": null, - "id": 88, + "id": 4, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 89, + "id": 5, "message": "foo", "username": "supabot", }, @@ -685,26 +650,22 @@ test('throwOnError should return response success type', async () => { test('connection error w/o throwing', async () => { const postgrest = new PostgrestClient('http://foo.invalid') let isErrorCaught = false - 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 - try { await postgrest.from('users').select().throwOnError() } catch (_) { isErrorCaught = true } - expect(isErrorCaught).toBe(true) }) @@ -811,8 +772,8 @@ test('select with head:true, count:planned', async () => { "count": Any, "data": null, "error": null, - "status": 200, - "statusText": "OK", + "status": 206, + "statusText": "Partial Content", } ` ) @@ -829,8 +790,8 @@ test('select with head:true, count:estimated', async () => { "count": Any, "data": null, "error": null, - "status": 200, - "statusText": "OK", + "status": 206, + "statusText": "Partial Content", } ` ) @@ -921,7 +882,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 90, + "id": 6, "message": "foo", "username": "supabot", }, @@ -954,7 +915,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 90, + "id": 6, "message": "foo", "username": "supabot", }, @@ -1011,7 +972,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 90, + "id": 6, "message": "foo", "username": "supabot", }, @@ -1048,14 +1009,14 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 91, + "id": 7, "message": "foo", "username": "supabot", }, Object { "channel_id": 1, "data": null, - "id": 92, + "id": 8, "message": "foo", "username": "supabot", }, @@ -1088,7 +1049,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 90, + "id": 6, "message": "foo", "username": "supabot", }, @@ -1102,14 +1063,14 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 1, "data": null, - "id": 91, + "id": 7, "message": "foo", "username": "supabot", }, Object { "channel_id": 1, "data": null, - "id": 92, + "id": 8, "message": "foo", "username": "supabot", }, @@ -1138,7 +1099,7 @@ describe("insert, update, delete with count: 'exact'", () => { }, Object { "data": null, - "id": 60, + "id": 4, "slug": "test-slug", }, ], @@ -1166,7 +1127,7 @@ describe("insert, update, delete with count: 'exact'", () => { }, Object { "data": null, - "id": 62, + "id": 6, "slug": "test-slug", }, ], @@ -1190,7 +1151,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 90, + "id": 6, "message": "foo", "username": "supabot", }, @@ -1204,14 +1165,14 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 91, + "id": 7, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 92, + "id": 8, "message": "foo", "username": "supabot", }, @@ -1244,7 +1205,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 90, + "id": 6, "message": "foo", "username": "supabot", }, @@ -1258,14 +1219,14 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 91, + "id": 7, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 92, + "id": 8, "message": "foo", "username": "supabot", }, @@ -1290,7 +1251,7 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 90, + "id": 6, "message": "foo", "username": "supabot", }, @@ -1304,14 +1265,14 @@ describe("insert, update, delete with count: 'exact'", () => { Object { "channel_id": 2, "data": null, - "id": 91, + "id": 7, "message": "foo", "username": "supabot", }, Object { "channel_id": 2, "data": null, - "id": 92, + "id": 8, "message": "foo", "username": "supabot", }, @@ -1399,4 +1360,4 @@ test('update with no match - return=representation', async () => { "statusText": "OK", } `) -}) +}) \ No newline at end of file From 9e02081abc2b97d53090e877af97022928212e40 Mon Sep 17 00:00:00 2001 From: dogukanakkaya Date: Thu, 1 Feb 2024 22:45:13 +0300 Subject: [PATCH 3/3] chore: resolved conflict minor changes --- src/PostgrestBuilder.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/PostgrestBuilder.ts b/src/PostgrestBuilder.ts index 534fa108..efb221d8 100644 --- a/src/PostgrestBuilder.ts +++ b/src/PostgrestBuilder.ts @@ -2,8 +2,6 @@ import nodeFetch from '@supabase/node-fetch' import type { Fetch, PostgrestResponseSuccess, PostgrestSingleResponse } from './types' -import type { Fetch, PostgrestResponseSuccess, PostgrestSingleResponse } from './types' -import PostgrestError from './PostgrestError' export default abstract class PostgrestBuilder implements PromiseLike>