From e556d3f83d1a3f1b79ec65be05c475cad3c2304f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Tue, 24 Dec 2024 14:36:57 +0100 Subject: [PATCH] fix: Correctly validate enum values in eq, neq and in methods --- src/PostgrestFilterBuilder.ts | 27 ++++++++++++--------------- test/index.test-d.ts | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/PostgrestFilterBuilder.ts b/src/PostgrestFilterBuilder.ts index 21cc4090..59da806e 100644 --- a/src/PostgrestFilterBuilder.ts +++ b/src/PostgrestFilterBuilder.ts @@ -32,11 +32,6 @@ export default class PostgrestFilterBuilder< RelationName = unknown, Relationships = unknown > extends PostgrestTransformBuilder { - eq( - column: ColumnName, - value: NonNullable - ): this - eq(column: string, value: NonNullable): this /** * Match only rows where `column` is equal to `value`. * @@ -45,20 +40,24 @@ export default class PostgrestFilterBuilder< * @param column - The column to filter on * @param value - The value to filter with */ - eq(column: string, value: unknown): this { + eq( + column: ColumnName, + value: ColumnName extends keyof Row ? NonNullable : NonNullable + ): this { this.url.searchParams.append(column, `eq.${value}`) return this } - neq(column: ColumnName, value: Row[ColumnName]): this - neq(column: string, value: unknown): this /** * Match only rows where `column` is not equal to `value`. * * @param column - The column to filter on * @param value - The value to filter with */ - neq(column: string, value: unknown): this { + neq( + column: ColumnName, + value: ColumnName extends keyof Row ? Row[ColumnName] : unknown + ): this { this.url.searchParams.append(column, `neq.${value}`) return this } @@ -227,18 +226,16 @@ export default class PostgrestFilterBuilder< return this } - in( - column: ColumnName, - values: ReadonlyArray - ): this - in(column: string, values: readonly unknown[]): this /** * Match only rows where `column` is included in the `values` array. * * @param column - The column to filter on * @param values - The values array to filter with */ - in(column: string, values: readonly unknown[]): this { + in( + column: ColumnName, + values: ColumnName extends keyof Row ? ReadonlyArray : unknown[] + ): this { const cleanedValues = Array.from(new Set(values)) .map((s) => { // handle postgrest reserved characters diff --git a/test/index.test-d.ts b/test/index.test-d.ts index e64dabcc..34bb3f65 100644 --- a/test/index.test-d.ts +++ b/test/index.test-d.ts @@ -21,6 +21,40 @@ const postgrest = new PostgrestClient(REST_URL) expectError(postgrest.from('users').select().eq('username', nullableVar)) } +// `.eq()`, '.neq()' and `.in()` validate value when column is an enum +{ + expectError(postgrest.from('users').select().eq('status', 'invalid')) + expectError(postgrest.from('users').select().neq('status', 'invalid')) + expectError(postgrest.from('users').select().in('status', ['invalid'])) + + { + const { data, error } = await postgrest.from('users').select('status').eq('status', 'ONLINE') + if (error) { + throw new Error(error.message) + } + expectType<{ status: Database['public']['Enums']['user_status'] | null }[]>(data) + } + + { + const { data, error } = await postgrest.from('users').select('status').neq('status', 'ONLINE') + if (error) { + throw new Error(error.message) + } + expectType<{ status: Database['public']['Enums']['user_status'] | null }[]>(data) + } + + { + const { data, error } = await postgrest + .from('users') + .select('status') + .in('status', ['ONLINE', 'OFFLINE']) + if (error) { + throw new Error(error.message) + } + expectType<{ status: Database['public']['Enums']['user_status'] | null }[]>(data) + } +} + // can override result type { const { data, error } = await postgrest