diff --git a/drizzle-typebox/src/column.ts b/drizzle-typebox/src/column.ts index 80e6ff39d..510ba7bbe 100644 --- a/drizzle-typebox/src/column.ts +++ b/drizzle-typebox/src/column.ts @@ -55,7 +55,6 @@ export function mapEnumValues(values: string[]) { return Object.fromEntries(values.map((value) => [value, value])); } -/** @internal */ export function columnToSchema(column: Column, t: typeof typebox): TSchema { let schema!: TSchema; diff --git a/drizzle-typebox/src/schema.types.internal.ts b/drizzle-typebox/src/schema.types.internal.ts index beccef94b..e48b764f4 100644 --- a/drizzle-typebox/src/schema.types.internal.ts +++ b/drizzle-typebox/src/schema.types.internal.ts @@ -40,13 +40,20 @@ export type BuildRefine< : never; type HandleRefinement< + TType extends 'select' | 'insert' | 'update', TRefinement extends t.TSchema | ((schema: t.TSchema) => t.TSchema), TColumn extends Column, -> = TRefinement extends (schema: t.TSchema) => t.TSchema - ? TColumn['_']['notNull'] extends true ? ReturnType - : t.TTuple<[ReturnType, t.TNull]> +> = TRefinement extends (schema: any) => t.TSchema ? (TColumn['_']['notNull'] extends true ? ReturnType + : t.TUnion<[ReturnType, t.TNull]>) extends infer TSchema + ? TType extends 'update' ? t.TOptional> : TSchema + : t.TSchema : TRefinement; +type IsRefinementDefined = TKey extends keyof TRefinements + ? TRefinements[TKey] extends t.TSchema | ((schema: any) => any) ? true + : false + : false; + export type BuildSchema< TType extends 'select' | 'insert' | 'update', TColumns extends Record, @@ -57,9 +64,8 @@ export type BuildSchema< { [K in keyof TColumns]: TColumns[K] extends infer TColumn extends Column ? TRefinements extends object - ? TRefinements[Assume] extends - infer TRefinement extends t.TSchema | ((schema: t.TSchema) => t.TSchema) - ? HandleRefinement + ? IsRefinementDefined> extends true + ? HandleRefinement], TColumn> : HandleColumn : HandleColumn : TColumns[K] extends infer TObject extends SelectedFieldsFlat | Table | View ? BuildSchema< diff --git a/drizzle-typebox/tests/mysql.test.ts b/drizzle-typebox/tests/mysql.test.ts index 213240368..8863f0fb9 100644 --- a/drizzle-typebox/tests/mysql.test.ts +++ b/drizzle-typebox/tests/mysql.test.ts @@ -1,6 +1,6 @@ import { Type as t } from '@sinclair/typebox'; import { type Equal, sql } from 'drizzle-orm'; -import { int, mysqlSchema, mysqlTable, mysqlView, serial, text } from 'drizzle-orm/mysql-core'; +import { customType, int, mysqlSchema, mysqlTable, mysqlView, serial, text } from 'drizzle-orm/mysql-core'; import { test } from 'vitest'; import { jsonSchema } from '~/column.ts'; import { CONSTANTS } from '~/constants.ts'; @@ -207,6 +207,32 @@ test('refine table - select', (tc) => { Expect>(); }); +test('refine table - select with custom data type', (tc) => { + const customText = customType({ dataType: () => 'text' }); + const table = mysqlTable('test', { + c1: int(), + c2: int().notNull(), + c3: int().notNull(), + c4: customText(), + }); + + const customTextSchema = t.String({ minLength: 1, maxLength: 100 }); + const result = createSelectSchema(table, { + c2: (schema) => t.Integer({ minimum: schema.minimum, maximum: 1000 }), + c3: t.Integer({ minimum: 1, maximum: 10 }), + c4: customTextSchema, + }); + const expected = t.Object({ + c1: t.Union([intSchema, t.Null()]), + c2: t.Integer({ minimum: CONSTANTS.INT32_MIN, maximum: 1000 }), + c3: t.Integer({ minimum: 1, maximum: 10 }), + c4: customTextSchema, + }); + + expectSchemaShape(tc, expected).from(result); + Expect>(); +}); + test('refine table - insert', (tc) => { const table = mysqlTable('test', { c1: int(), diff --git a/drizzle-typebox/tests/pg.test.ts b/drizzle-typebox/tests/pg.test.ts index 3e9769aef..8fd8148d8 100644 --- a/drizzle-typebox/tests/pg.test.ts +++ b/drizzle-typebox/tests/pg.test.ts @@ -1,6 +1,16 @@ import { Type as t } from '@sinclair/typebox'; import { type Equal, sql } from 'drizzle-orm'; -import { integer, pgEnum, pgMaterializedView, pgSchema, pgTable, pgView, serial, text } from 'drizzle-orm/pg-core'; +import { + customType, + integer, + pgEnum, + pgMaterializedView, + pgSchema, + pgTable, + pgView, + serial, + text, +} from 'drizzle-orm/pg-core'; import { test } from 'vitest'; import { jsonSchema } from '~/column.ts'; import { CONSTANTS } from '~/constants.ts'; @@ -233,6 +243,32 @@ test('refine table - select', (tc) => { Expect>(); }); +test('refine table - select with custom data type', (tc) => { + const customText = customType({ dataType: () => 'text' }); + const table = pgTable('test', { + c1: integer(), + c2: integer().notNull(), + c3: integer().notNull(), + c4: customText(), + }); + + const customTextSchema = t.String({ minLength: 1, maxLength: 100 }); + const result = createSelectSchema(table, { + c2: (schema) => t.Integer({ minimum: schema.minimum, maximum: 1000 }), + c3: t.Integer({ minimum: 1, maximum: 10 }), + c4: customTextSchema, + }); + const expected = t.Object({ + c1: t.Union([integerSchema, t.Null()]), + c2: t.Integer({ minimum: CONSTANTS.INT32_MIN, maximum: 1000 }), + c3: t.Integer({ minimum: 1, maximum: 10 }), + c4: customTextSchema, + }); + + expectSchemaShape(tc, expected).from(result); + Expect>(); +}); + test('refine table - insert', (tc) => { const table = pgTable('test', { c1: integer(), diff --git a/drizzle-typebox/tests/sqlite.test.ts b/drizzle-typebox/tests/sqlite.test.ts index ba2b55002..2b5083b92 100644 --- a/drizzle-typebox/tests/sqlite.test.ts +++ b/drizzle-typebox/tests/sqlite.test.ts @@ -1,6 +1,6 @@ import { Type as t } from '@sinclair/typebox'; import { type Equal, sql } from 'drizzle-orm'; -import { int, sqliteTable, sqliteView, text } from 'drizzle-orm/sqlite-core'; +import { customType, int, sqliteTable, sqliteView, text } from 'drizzle-orm/sqlite-core'; import { test } from 'vitest'; import { bufferSchema, jsonSchema } from '~/column.ts'; import { CONSTANTS } from '~/constants.ts'; @@ -186,6 +186,32 @@ test('refine table - select', (tc) => { Expect>(); }); +test('refine table - select with custom data type', (tc) => { + const customText = customType({ dataType: () => 'text' }); + const table = sqliteTable('test', { + c1: int(), + c2: int().notNull(), + c3: int().notNull(), + c4: customText(), + }); + + const customTextSchema = t.String({ minLength: 1, maxLength: 100 }); + const result = createSelectSchema(table, { + c2: (schema) => t.Integer({ minimum: schema.minimum, maximum: 1000 }), + c3: t.Integer({ minimum: 1, maximum: 10 }), + c4: customTextSchema, + }); + const expected = t.Object({ + c1: t.Union([intSchema, t.Null()]), + c2: t.Integer({ minimum: Number.MIN_SAFE_INTEGER, maximum: 1000 }), + c3: t.Integer({ minimum: 1, maximum: 10 }), + c4: customTextSchema, + }); + + expectSchemaShape(tc, expected).from(result); + Expect>(); +}); + test('refine table - insert', (tc) => { const table = sqliteTable('test', { c1: int(), diff --git a/drizzle-valibot/src/column.ts b/drizzle-valibot/src/column.ts index e5716fe1e..5d7a1784e 100644 --- a/drizzle-valibot/src/column.ts +++ b/drizzle-valibot/src/column.ts @@ -55,7 +55,6 @@ export function mapEnumValues(values: string[]) { return Object.fromEntries(values.map((value) => [value, value])); } -/** @internal */ export function columnToSchema(column: Column): v.GenericSchema { let schema!: v.GenericSchema; diff --git a/drizzle-valibot/src/column.types.ts b/drizzle-valibot/src/column.types.ts index e6cd797ed..b9567b12d 100644 --- a/drizzle-valibot/src/column.types.ts +++ b/drizzle-valibot/src/column.types.ts @@ -30,21 +30,23 @@ export type ExtractAdditionalProperties = { fixedLength: TColumn['_']['columnType'] extends 'PgChar' | 'MySqlChar' | 'PgHalfVector' | 'PgVector' | 'PgArray' ? true : false; - arrayPipelines: []; }; -type RemovePipeIfNoElements> = T extends - infer TPiped extends { pipe: [any, ...any[]] } ? TPiped['pipe'][1] extends undefined ? T['pipe'][0] : TPiped - : never; +type GetLengthAction, TType extends string | ArrayLike> = + T['fixedLength'] extends true ? v.LengthAction + : v.MaxLengthAction; -type BuildArraySchema< - TWrapped extends v.GenericSchema, - TPipelines extends any[][], -> = TPipelines extends [infer TFirst extends any[], ...infer TRest extends any[][]] - ? BuildArraySchema, ...TFirst]>>, TRest> - : TPipelines extends [infer TFirst extends any[]] - ? BuildArraySchema, ...TFirst]>>, []> - : TWrapped; +type GetArraySchema = v.ArraySchema< + GetValibotType< + T['_']['data'], + T['_']['dataType'], + T['_']['columnType'], + GetEnumValuesFromColumn, + GetBaseColumn, + ExtractAdditionalProperties + >, + undefined +>; export type GetValibotType< TData, @@ -53,51 +55,22 @@ export type GetValibotType< TEnumValues extends [string, ...string[]] | undefined, TBaseColumn extends Column | undefined, TAdditionalProperties extends Record, -> = TColumnType extends 'PgHalfVector' | 'PgVector' ? RemovePipeIfNoElements< - v.SchemaWithPipe< - RemoveNeverElements<[ - v.ArraySchema, undefined>, - TAdditionalProperties['max'] extends number - ? TAdditionalProperties['fixedLength'] extends true ? v.LengthAction - : v.MaxLengthAction - : never, - ]> +> = TColumnType extends 'PgHalfVector' | 'PgVector' ? TAdditionalProperties['max'] extends number ? v.SchemaWithPipe< + [v.ArraySchema, undefined>, GetLengthAction] > - > + : v.ArraySchema, undefined> : TColumnType extends 'PgUUID' ? v.SchemaWithPipe<[v.StringSchema, v.UuidAction]> - // PG array handling start - // Nesting `GetValibotType` within `v.ArraySchema` will cause infinite recursion - // The workaround is to accumulate all the array validations (done via `arrayPipelines` in `TAdditionalProperties`) and then build the schema afterwards - : TAdditionalProperties['arrayFinished'] extends true ? GetValibotType< - TData, - TDataType, - TColumnType, - TEnumValues, - TBaseColumn, - Omit - > extends infer TSchema extends v.GenericSchema ? BuildArraySchema - : never - : TBaseColumn extends Column ? GetValibotType< - TBaseColumn['_']['data'], - TBaseColumn['_']['dataType'], - TBaseColumn['_']['columnType'], - GetEnumValuesFromColumn, - GetBaseColumn, - Omit, 'arrayPipelines'> & { - arrayPipelines: [ - RemoveNeverElements<[ - TAdditionalProperties['max'] extends number - ? TAdditionalProperties['fixedLength'] extends true - ? v.LengthAction[], number, undefined> - : v.MaxLengthAction[], number, undefined> - : never, - ]>, - ...TAdditionalProperties['arrayPipelines'], - ]; - arrayFinished: GetBaseColumn extends undefined ? true : false; - } + : TColumnType extends 'PgBinaryVector' ? v.SchemaWithPipe< + RemoveNeverElements<[ + v.StringSchema, + v.RegexAction, + TAdditionalProperties['max'] extends number ? GetLengthAction : never, + ]> > - // PG array handling end + : TBaseColumn extends Column ? TAdditionalProperties['max'] extends number ? v.SchemaWithPipe< + [GetArraySchema, GetLengthAction] + > + : GetArraySchema : ArrayHasAtLeastOneValue extends true ? v.EnumSchema>, undefined> : TData extends infer TTuple extends [any, ...any[]] ? v.TupleSchema< @@ -147,19 +120,10 @@ export type GetValibotType< v.MaxValueAction, ]> : TData extends boolean ? v.BooleanSchema - : TData extends string ? RemovePipeIfNoElements< - v.SchemaWithPipe< - RemoveNeverElements<[ - v.StringSchema, - TColumnType extends 'PgBinaryVector' ? v.RegexAction - : never, - TAdditionalProperties['max'] extends number - ? TAdditionalProperties['fixedLength'] extends true ? v.LengthAction - : v.MaxLengthAction - : never, - ]> - > - > + : TData extends string + ? TAdditionalProperties['max'] extends number + ? v.SchemaWithPipe<[v.StringSchema, GetLengthAction]> + : v.StringSchema : v.AnySchema; type HandleSelectColumn< diff --git a/drizzle-valibot/src/schema.types.internal.ts b/drizzle-valibot/src/schema.types.internal.ts index 57dcedc7c..e39c34d8a 100644 --- a/drizzle-valibot/src/schema.types.internal.ts +++ b/drizzle-valibot/src/schema.types.internal.ts @@ -67,8 +67,7 @@ export type BuildSchema< TType extends 'select' | 'insert' | 'update', TColumns extends Record, TRefinements extends Record | undefined, -> // @ts-ignore false-positive - = v.ObjectSchema< +> = v.ObjectSchema< Simplify< RemoveNever< { diff --git a/drizzle-valibot/tests/mysql.test.ts b/drizzle-valibot/tests/mysql.test.ts index 5bf9520cb..6578729a4 100644 --- a/drizzle-valibot/tests/mysql.test.ts +++ b/drizzle-valibot/tests/mysql.test.ts @@ -1,5 +1,5 @@ import { type Equal, sql } from 'drizzle-orm'; -import { int, mysqlSchema, mysqlTable, mysqlView, serial, text } from 'drizzle-orm/mysql-core'; +import { customType, int, mysqlSchema, mysqlTable, mysqlView, serial, text } from 'drizzle-orm/mysql-core'; import * as v from 'valibot'; import { test } from 'vitest'; import { jsonSchema } from '~/column.ts'; @@ -210,6 +210,32 @@ test('refine table - select', (t) => { Expect>(); }); +test('refine table - select with custom data type', (t) => { + const customText = customType({ dataType: () => 'text' }); + const table = mysqlTable('test', { + c1: int(), + c2: int().notNull(), + c3: int().notNull(), + c4: customText(), + }); + + const customTextSchema = v.pipe(v.string(), v.minLength(1), v.maxLength(100)); + const result = createSelectSchema(table, { + c2: (schema) => v.pipe(schema, v.maxValue(1000)), + c3: v.pipe(v.string(), v.transform(Number)), + c4: customTextSchema, + }); + const expected = v.object({ + c1: v.nullable(intSchema), + c2: v.pipe(intSchema, v.maxValue(1000)), + c3: v.pipe(v.string(), v.transform(Number)), + c4: customTextSchema, + }); + + expectSchemaShape(t, expected).from(result); + Expect>(); +}); + test('refine table - insert', (t) => { const table = mysqlTable('test', { c1: int(), diff --git a/drizzle-valibot/tests/pg.test.ts b/drizzle-valibot/tests/pg.test.ts index 4d1651a7c..ea2bf2dd0 100644 --- a/drizzle-valibot/tests/pg.test.ts +++ b/drizzle-valibot/tests/pg.test.ts @@ -1,5 +1,15 @@ import { type Equal, sql } from 'drizzle-orm'; -import { integer, pgEnum, pgMaterializedView, pgSchema, pgTable, pgView, serial, text } from 'drizzle-orm/pg-core'; +import { + customType, + integer, + pgEnum, + pgMaterializedView, + pgSchema, + pgTable, + pgView, + serial, + text, +} from 'drizzle-orm/pg-core'; import * as v from 'valibot'; import { test } from 'vitest'; import { jsonSchema } from '~/column.ts'; @@ -234,6 +244,32 @@ test('refine table - select', (t) => { Expect>(); }); +test('refine table - select with custom data type', (t) => { + const customText = customType({ dataType: () => 'text' }); + const table = pgTable('test', { + c1: integer(), + c2: integer().notNull(), + c3: integer().notNull(), + c4: customText(), + }); + + const customTextSchema = v.pipe(v.string(), v.minLength(1), v.maxLength(100)); + const result = createSelectSchema(table, { + c2: (schema) => v.pipe(schema, v.maxValue(1000)), + c3: v.pipe(v.string(), v.transform(Number)), + c4: customTextSchema, + }); + const expected = v.object({ + c1: v.nullable(integerSchema), + c2: v.pipe(integerSchema, v.maxValue(1000)), + c3: v.pipe(v.string(), v.transform(Number)), + c4: customTextSchema, + }); + + expectSchemaShape(t, expected).from(result); + Expect>(); +}); + test('refine table - insert', (t) => { const table = pgTable('test', { c1: integer(), diff --git a/drizzle-valibot/tests/sqlite.test.ts b/drizzle-valibot/tests/sqlite.test.ts index 7eb5fc7bf..14e6b4bd6 100644 --- a/drizzle-valibot/tests/sqlite.test.ts +++ b/drizzle-valibot/tests/sqlite.test.ts @@ -1,5 +1,5 @@ import { type Equal, sql } from 'drizzle-orm'; -import { int, sqliteTable, sqliteView, text } from 'drizzle-orm/sqlite-core'; +import { customType, int, sqliteTable, sqliteView, text } from 'drizzle-orm/sqlite-core'; import * as v from 'valibot'; import { test } from 'vitest'; import { bufferSchema, jsonSchema } from '~/column.ts'; @@ -187,6 +187,32 @@ test('refine table - select', (t) => { Expect>(); }); +test('refine table - select with custom data type', (t) => { + const customText = customType({ dataType: () => 'text' }); + const table = sqliteTable('test', { + c1: int(), + c2: int().notNull(), + c3: int().notNull(), + c4: customText(), + }); + + const customTextSchema = v.pipe(v.string(), v.minLength(1), v.maxLength(100)); + const result = createSelectSchema(table, { + c2: (schema) => v.pipe(schema, v.maxValue(1000)), + c3: v.pipe(v.string(), v.transform(Number)), + c4: customTextSchema, + }); + const expected = v.object({ + c1: v.nullable(intSchema), + c2: v.pipe(intSchema, v.maxValue(1000)), + c3: v.pipe(v.string(), v.transform(Number)), + c4: customTextSchema, + }); + + expectSchemaShape(t, expected).from(result); + Expect>(); +}); + test('refine table - insert', (t) => { const table = sqliteTable('test', { c1: int(), diff --git a/drizzle-zod/src/column.ts b/drizzle-zod/src/column.ts index 4aae40e7e..d6fff3445 100644 --- a/drizzle-zod/src/column.ts +++ b/drizzle-zod/src/column.ts @@ -50,7 +50,6 @@ export const jsonSchema: z.ZodType = z.lazy(() => ); export const bufferSchema: z.ZodType = z.custom((v) => v instanceof Buffer); // eslint-disable-line no-instanceof/no-instanceof -/** @internal */ export function columnToSchema(column: Column, z: typeof zod): z.ZodTypeAny { let schema!: z.ZodTypeAny; diff --git a/drizzle-zod/src/schema.types.internal.ts b/drizzle-zod/src/schema.types.internal.ts index 5732e2e0f..8b89187f2 100644 --- a/drizzle-zod/src/schema.types.internal.ts +++ b/drizzle-zod/src/schema.types.internal.ts @@ -39,13 +39,20 @@ export type BuildRefine< : never; type HandleRefinement< + TType extends 'select' | 'insert' | 'update', TRefinement extends z.ZodTypeAny | ((schema: z.ZodTypeAny) => z.ZodTypeAny), TColumn extends Column, -> = TRefinement extends (schema: z.ZodTypeAny) => z.ZodTypeAny - ? TColumn['_']['notNull'] extends true ? ReturnType - : z.ZodNullable> +> = TRefinement extends (schema: any) => z.ZodTypeAny ? (TColumn['_']['notNull'] extends true ? ReturnType + : z.ZodNullable>) extends infer TSchema + ? TType extends 'update' ? z.ZodOptional> : TSchema + : z.ZodTypeAny : TRefinement; +type IsRefinementDefined = TKey extends keyof TRefinements + ? TRefinements[TKey] extends z.ZodTypeAny | ((schema: any) => any) ? true + : false + : false; + export type BuildSchema< TType extends 'select' | 'insert' | 'update', TColumns extends Record, @@ -56,9 +63,8 @@ export type BuildSchema< { [K in keyof TColumns]: TColumns[K] extends infer TColumn extends Column ? TRefinements extends object - ? TRefinements[Assume] extends - infer TRefinement extends z.ZodTypeAny | ((schema: z.ZodTypeAny) => z.ZodTypeAny) - ? HandleRefinement + ? IsRefinementDefined> extends true + ? HandleRefinement], TColumn> : HandleColumn : HandleColumn : TColumns[K] extends infer TObject extends SelectedFieldsFlat | Table | View ? BuildSchema< diff --git a/drizzle-zod/tests/mysql.test.ts b/drizzle-zod/tests/mysql.test.ts index 37c9b7e64..73ba48dae 100644 --- a/drizzle-zod/tests/mysql.test.ts +++ b/drizzle-zod/tests/mysql.test.ts @@ -1,5 +1,5 @@ import { type Equal, sql } from 'drizzle-orm'; -import { int, mysqlSchema, mysqlTable, mysqlView, serial, text } from 'drizzle-orm/mysql-core'; +import { customType, int, mysqlSchema, mysqlTable, mysqlView, serial, text } from 'drizzle-orm/mysql-core'; import { test } from 'vitest'; import { z } from 'zod'; import { jsonSchema } from '~/column.ts'; @@ -201,6 +201,32 @@ test('refine table - select', (t) => { Expect>(); }); +test('refine table - select with custom data type', (t) => { + const customText = customType({ dataType: () => 'text' }); + const table = mysqlTable('test', { + c1: int(), + c2: int().notNull(), + c3: int().notNull(), + c4: customText(), + }); + + const customTextSchema = z.string().min(1).max(100); + const result = createSelectSchema(table, { + c2: (schema) => schema.max(1000), + c3: z.string().transform(Number), + c4: customTextSchema, + }); + const expected = z.object({ + c1: intSchema.nullable(), + c2: intSchema.max(1000), + c3: z.string().transform(Number), + c4: customTextSchema, + }); + + expectSchemaShape(t, expected).from(result); + Expect>(); +}); + test('refine table - insert', (t) => { const table = mysqlTable('test', { c1: int(), diff --git a/drizzle-zod/tests/pg.test.ts b/drizzle-zod/tests/pg.test.ts index dc703b4fc..7964f65d6 100644 --- a/drizzle-zod/tests/pg.test.ts +++ b/drizzle-zod/tests/pg.test.ts @@ -1,5 +1,15 @@ import { type Equal, sql } from 'drizzle-orm'; -import { integer, pgEnum, pgMaterializedView, pgSchema, pgTable, pgView, serial, text } from 'drizzle-orm/pg-core'; +import { + customType, + integer, + pgEnum, + pgMaterializedView, + pgSchema, + pgTable, + pgView, + serial, + text, +} from 'drizzle-orm/pg-core'; import { test } from 'vitest'; import { z } from 'zod'; import { jsonSchema } from '~/column.ts'; @@ -234,6 +244,32 @@ test('refine table - select', (t) => { Expect>(); }); +test('refine table - select with custom data type', (t) => { + const customText = customType({ dataType: () => 'text' }); + const table = pgTable('test', { + c1: integer(), + c2: integer().notNull(), + c3: integer().notNull(), + c4: customText(), + }); + + const customTextSchema = z.string().min(1).max(100); + const result = createSelectSchema(table, { + c2: (schema) => schema.max(1000), + c3: z.string().transform(Number), + c4: customTextSchema, + }); + const expected = z.object({ + c1: integerSchema.nullable(), + c2: integerSchema.max(1000), + c3: z.string().transform(Number), + c4: customTextSchema, + }); + + expectSchemaShape(t, expected).from(result); + Expect>(); +}); + test('refine table - insert', (t) => { const table = pgTable('test', { c1: integer(), diff --git a/drizzle-zod/tests/sqlite.test.ts b/drizzle-zod/tests/sqlite.test.ts index 45e64bbde..bb0f254b5 100644 --- a/drizzle-zod/tests/sqlite.test.ts +++ b/drizzle-zod/tests/sqlite.test.ts @@ -1,5 +1,5 @@ import { type Equal, sql } from 'drizzle-orm'; -import { int, sqliteTable, sqliteView, text } from 'drizzle-orm/sqlite-core'; +import { customType, int, sqliteTable, sqliteView, text } from 'drizzle-orm/sqlite-core'; import { test } from 'vitest'; import { z } from 'zod'; import { bufferSchema, jsonSchema } from '~/column.ts'; @@ -182,6 +182,32 @@ test('refine table - select', (t) => { Expect>(); }); +test('refine table - select with custom data type', (t) => { + const customText = customType({ dataType: () => 'text' }); + const table = sqliteTable('test', { + c1: int(), + c2: int().notNull(), + c3: int().notNull(), + c4: customText(), + }); + + const customTextSchema = z.string().min(1).max(100); + const result = createSelectSchema(table, { + c2: (schema) => schema.max(1000), + c3: z.string().transform(Number), + c4: customTextSchema, + }); + const expected = z.object({ + c1: intSchema.nullable(), + c2: intSchema.max(1000), + c3: z.string().transform(Number), + c4: customTextSchema, + }); + + expectSchemaShape(t, expected).from(result); + Expect>(); +}); + test('refine table - insert', (t) => { const table = sqliteTable('test', { c1: int(),