From bbf05b99b23545f15f6bc5a0da745de74f9e1939 Mon Sep 17 00:00:00 2001 From: Misha Kaletsky Date: Thu, 12 Sep 2024 14:41:26 -0400 Subject: [PATCH] fix sql.type(...)` ` bug with identifiers --- packages/client/src/sql.ts | 17 +++++++---------- packages/client/src/types.ts | 10 ++++------ packages/client/test/pgp.test.ts | 3 --- packages/client/test/zod.test.ts | 20 +++++++++++++------- packages/typegen/src/query/column-info.ts | 6 ++---- 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/packages/client/src/sql.ts b/packages/client/src/sql.ts index 8dbf33d6..6b3727f1 100644 --- a/packages/client/src/sql.ts +++ b/packages/client/src/sql.ts @@ -41,19 +41,16 @@ const sqlMethodHelpers: SQLMethodHelpers = { cause: type, }) } - return (strings, ...parameters) => { - return { - parse: parseAsync, - name: nameQuery(strings), - sql: strings.join(''), - token: 'sql', - values: parameters, - templateArgs: () => [strings, ...parameters], - } - } + return (strings, ...parameters) => ({ + ...sqlFn(strings, ...parameters), + parse: parseAsync, + }) }, } +/** + * Template tag function. Walks through each string segment and parameter, and concatenates them into a valid SQL query. + */ const sqlFn: SQLTagFunction = (strings, ...inputParameters) => { let sql = '' const values: unknown[] = [] diff --git a/packages/client/src/types.ts b/packages/client/src/types.ts index 79f4587b..e5491dad 100644 --- a/packages/client/src/types.ts +++ b/packages/client/src/types.ts @@ -104,17 +104,15 @@ export type TypeNameIdentifier = /* eslint-enable @typescript-eslint/no-redundant-type-constituents */ export type ZodesqueType = - | ZodesqueTypeUnsafe | ZodesqueTypeSafe - | ZodesqueTypeAsyncUnsafe | ZodesqueTypeAsyncSafe + | ZodesqueTypeAsyncUnsafe + | ZodesqueTypeUnsafe export type ZodesqueTypeUnsafe = {parse: (input: unknown) => T} export type ZodesqueTypeSafe = {safeParse: (input: unknown) => ZodesqueResult} export type ZodesqueTypeAsyncUnsafe = {parseAsync: (input: unknown) => Promise} export type ZodesqueTypeAsyncSafe = {safeParseAsync: (input: unknown) => Promise>} -export type ZodesqueResult = - | {success: true; data: T; error: undefined} - | {success: false; error: Error; data: undefined} +export type ZodesqueResult = {success: true; data: T} | {success: false; error: Error} export type SQLTagHelperParameters = { array: [values: readonly PrimitiveValueExpression[], memberType: MemberType] @@ -152,7 +150,7 @@ export type SQLTagFunction = , Parameters extends export type SQLMethodHelpers = { raw: (query: string) => SQLQuery - type: >( + type: ( parser: ZodesqueType, ) => ( strings: TemplateStringsArray, diff --git a/packages/client/test/pgp.test.ts b/packages/client/test/pgp.test.ts index 54de071c..f0c69357 100644 --- a/packages/client/test/pgp.test.ts +++ b/packages/client/test/pgp.test.ts @@ -157,7 +157,6 @@ test('type parsers', async () => { {"oid":194,"typname":"pg_node_tree","regtype":"pg_node_tree"}, {"oid":20,"typname":"int8","regtype":"bigint"}, {"oid":21,"typname":"int2","regtype":"smallint"}, - {"oid":210,"typname":"_pg_type","regtype":"pg_type[]"}, {"oid":2202,"typname":"regprocedure","regtype":"regprocedure"}, {"oid":2203,"typname":"regoper","regtype":"regoper"}, {"oid":2204,"typname":"regoperator","regtype":"regoperator"}, @@ -298,8 +297,6 @@ test('type parsers', async () => { { "name": "SMGR", "oid": 210, - "regtype": "pg_type[]", - "typname": "_pg_type", }, { "name": "PATH", diff --git a/packages/client/test/zod.test.ts b/packages/client/test/zod.test.ts index a9ad01f4..f5ac9cd2 100644 --- a/packages/client/test/zod.test.ts +++ b/packages/client/test/zod.test.ts @@ -1,4 +1,4 @@ -import {beforeAll, beforeEach, expect, test} from 'vitest' +import {beforeAll, beforeEach, expect, expectTypeOf, test} from 'vitest' import {z} from 'zod' import {createClient, sql} from '../src' @@ -16,14 +16,15 @@ beforeAll(async () => { beforeEach(async () => { await client.query(sql` drop table if exists zod_test; - create table zod_test(id int, location text); - insert into zod_test values (1, '70,-108'), (2, '71,-102'), (3, '66,-90'); + create table zod_test(id int, location text, label text); + insert into zod_test values (1, '70,-108', 'a'), (2, '71,-102', 'b'), (3, '66,-90', null); `) }) test('Transform rows', async () => { const Row = z.object({ id: z.number(), + label: z.string().nullable(), location: z .string() .regex(/^-?\d+,-?\d+$/) @@ -37,16 +38,19 @@ test('Transform rows', async () => { select * from zod_test `) - // const result2 = await client.any(sql.type(Row)` - // select * from ${sql.identifier(['zod_test'])} - // `) + expectTypeOf(result).toEqualTypeOf<{id: number; label: string | null; location: {lat: number; lon: number}}[]>() - // expect(result2).toEqual(result) + const result2 = await client.any(sql.type(Row)` + select * from ${sql.identifier(['zod_test'])} + `) + + expect(result2).toEqual(result) expect(result).toMatchInlineSnapshot(` [ { "id": 1, + "label": "a", "location": { "lat": 70, "lon": -108 @@ -54,6 +58,7 @@ test('Transform rows', async () => { }, { "id": 2, + "label": "b", "location": { "lat": 71, "lon": -102 @@ -61,6 +66,7 @@ test('Transform rows', async () => { }, { "id": 3, + "label": null, "location": { "lat": 66, "lon": -90 diff --git a/packages/typegen/src/query/column-info.ts b/packages/typegen/src/query/column-info.ts index 0f1873bf..0ee233e5 100644 --- a/packages/typegen/src/query/column-info.ts +++ b/packages/typegen/src/query/column-info.ts @@ -237,14 +237,12 @@ export const analyzeAST = async ( } } - const AnalyzeSelectStatementColumnsQuery = (statmentSql: string) => sql` + const AnalyzeSelectStatementColumnsQuery = (statmentSql: string) => sql.type(SelectStatementAnalyzedColumnSchema)` --typegen-ignore select * from ${sql.identifier([schemaName, 'analyze_select_statement_columns'])}(${statmentSql}) ` // todo: figure out why sql.type(MyZodType) isn't working here - let results = SelectStatementAnalyzedColumnSchema.array().parse( - await tx.any(AnalyzeSelectStatementColumnsQuery(astSql)), - ) + let results = await tx.any(AnalyzeSelectStatementColumnsQuery(astSql)) results = lodash.uniqBy(results, JSON.stringify)