From 4d2d1e727aa7ef237dbd5ef46357a5f8004cc31a Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 13 Feb 2024 15:55:54 +0100 Subject: [PATCH] Strip primary keys from the update payload --- .changeset/tricky-pans-draw.md | 7 +++ packages/postgrest-core/src/update-fetcher.ts | 21 ++++++-- .../tests/update-fetcher.spec.ts | 51 ++++++++++++++++--- 3 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 .changeset/tricky-pans-draw.md diff --git a/.changeset/tricky-pans-draw.md b/.changeset/tricky-pans-draw.md new file mode 100644 index 00000000..2d8c9f7b --- /dev/null +++ b/.changeset/tricky-pans-draw.md @@ -0,0 +1,7 @@ +--- +"@supabase-cache-helpers/postgrest-core": minor +"@supabase-cache-helpers/postgrest-react-query": minor +"@supabase-cache-helpers/postgrest-swr": minor +--- + +Strip primary keys from the update payload diff --git a/packages/postgrest-core/src/update-fetcher.ts b/packages/postgrest-core/src/update-fetcher.ts index 6fba2ba0..caaf39a4 100644 --- a/packages/postgrest-core/src/update-fetcher.ts +++ b/packages/postgrest-core/src/update-fetcher.ts @@ -22,7 +22,9 @@ export type UpdateFetcherOptions< S extends GenericSchema, T extends GenericTable, Re = T extends { Relationships: infer R } ? R : unknown, -> = Parameters['update']>[1]; +> = Parameters['update']>[1] & { + stripPrimaryKeys?: boolean; +}; export const buildUpdateFetcher = < @@ -35,13 +37,24 @@ export const buildUpdateFetcher = >( qb: PostgrestQueryBuilder, primaryKeys: (keyof T['Row'])[], - opts: BuildNormalizedQueryOps & UpdateFetcherOptions, + { + stripPrimaryKeys = true, + ...opts + }: BuildNormalizedQueryOps & UpdateFetcherOptions, ): UpdateFetcher => async ( input: Partial, ): Promise | null> => { - let filterBuilder = qb.update(input as any, opts); // todo fix type; - + const payload = stripPrimaryKeys + ? primaryKeys.reduce( + (acc, key) => { + delete acc[key]; + return acc; + }, + { ...input }, + ) + : input; + let filterBuilder = qb.update(payload as any, opts); // todo fix type; for (const key of primaryKeys) { const value = input[key]; if (!value) diff --git a/packages/postgrest-core/tests/update-fetcher.spec.ts b/packages/postgrest-core/tests/update-fetcher.spec.ts index 3fef225e..9eb6fb3f 100644 --- a/packages/postgrest-core/tests/update-fetcher.spec.ts +++ b/packages/postgrest-core/tests/update-fetcher.spec.ts @@ -1,5 +1,5 @@ import { type SupabaseClient, createClient } from '@supabase/supabase-js'; -import { beforeAll, describe, expect, it } from 'vitest'; +import { beforeAll, describe, expect, it, vi } from 'vitest'; import type { Database } from './database.types'; import './utils'; @@ -41,20 +41,55 @@ describe('update', () => { }); it('should update entity by primary keys', async () => { - const updatedContact = await buildUpdateFetcher( - client.from('contact'), - ['id'], - { queriesForTable: () => [] }, - )({ + const qb = client.from('contact'); + const updateSpy = vi.spyOn(qb, 'update'); + const username = `${testRunPrefix}-username-2`; + const updatedContact = await buildUpdateFetcher(qb, ['id'], { + stripPrimaryKeys: false, + queriesForTable: () => [], + })({ + id: contact?.id, + username, + }); + expect(updatedContact).toEqual({ + normalizedData: { + id: expect.anything(), + username, + }, + }); + expect(updateSpy).toHaveBeenCalledWith( + { + id: expect.anything(), + username, + }, + expect.anything(), + ); + const { data } = await client + .from('contact') + .select('*') + .eq('id', contact?.id ?? '') + .throwOnError() + .maybeSingle(); + expect(data?.username).toEqual(`${testRunPrefix}-username-2`); + }); + + it('should update entity by primary keys excluding primary keys in payload', async () => { + const qb = client.from('contact'); + const updateSpy = vi.spyOn(qb, 'update'); + const username = `${testRunPrefix}-username-2`; + const updatedContact = await buildUpdateFetcher(qb, ['id'], { + queriesForTable: () => [], + })({ id: contact?.id, - username: `${testRunPrefix}-username-2`, + username, }); expect(updatedContact).toEqual({ normalizedData: { id: expect.anything(), - username: `${testRunPrefix}-username-2`, + username, }, }); + expect(updateSpy).toHaveBeenCalledWith({ username }, expect.anything()); const { data } = await client .from('contact') .select('*')