diff --git a/drizzle-orm/src/sqlite-core/columns/text.ts b/drizzle-orm/src/sqlite-core/columns/text.ts index 4b1285259..2af29dab6 100644 --- a/drizzle-orm/src/sqlite-core/columns/text.ts +++ b/drizzle-orm/src/sqlite-core/columns/text.ts @@ -55,6 +55,53 @@ export class SQLiteText> } } +export type SQLiteTextDateBuilderInitial = SQLiteTextDateBuilder<{ + name: TName; + dataType: 'date'; + columnType: 'SQLiteTextDate'; + data: Date; + driverParam: string; + enumValues: undefined; +}>; + +export class SQLiteTextDateBuilder> + extends SQLiteColumnBuilder +{ + static readonly [entityKind]: string = 'SQLiteTextDateBuilder'; + + constructor(name: T['name']) { + super(name, 'date', 'SQLiteTextDate'); + } + + /** @internal */ + override build( + table: AnySQLiteTable<{ name: TTableName }>, + ): SQLiteTextDate> { + return new SQLiteTextDate>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class SQLiteTextDate> + extends SQLiteColumn +{ + static readonly [entityKind]: string = 'SQLiteTextDate'; + + getSQLType(): string { + return 'text'; + } + + override mapFromDriverValue(value: string): Date { + return new Date(value); + } + + override mapToDriverValue(value: Date): string { + return value.toISOString(); + } +} + export type SQLiteTextJsonBuilderInitial = SQLiteTextJsonBuilder<{ name: TName; dataType: 'json'; @@ -103,7 +150,7 @@ export class SQLiteTextJson } export type SQLiteTextConfig< - TMode extends 'text' | 'json', + TMode extends 'text' | 'json' | 'date', TEnum extends readonly string[] | string[] | undefined, > = TMode extends 'text' ? { mode?: TMode; @@ -118,16 +165,20 @@ export function text< TName extends string, U extends string, T extends Readonly<[U, ...U[]]>, - TMode extends 'text' | 'json' = 'text' | 'json', + TMode extends 'text' | 'json' | 'date' = 'text' | 'json' | 'date', >( name: TName, config: SQLiteTextConfig> = {} as SQLiteTextConfig>, ): Equal extends true ? SQLiteTextJsonBuilderInitial + : Equal extends true ? SQLiteTextDateBuilderInitial : SQLiteTextBuilderInitial> { return (config.mode === 'json' ? new SQLiteTextJsonBuilder(name) + : config.mode === 'date' + ? new SQLiteTextDateBuilder(name) : new SQLiteTextBuilder(name, config as SQLiteTextConfig<'text', Writable>)) as Equal extends true ? SQLiteTextJsonBuilderInitial + : Equal extends true ? SQLiteTextDateBuilderInitial : SQLiteTextBuilderInitial>; } diff --git a/integration-tests/tests/libsql.test.ts b/integration-tests/tests/libsql.test.ts index d57904626..a0b6e3f11 100644 --- a/integration-tests/tests/libsql.test.ts +++ b/integration-tests/tests/libsql.test.ts @@ -2798,3 +2798,33 @@ test.serial('test $onUpdateFn and $onUpdate works updating', async (t) => { t.assert(eachUser.updatedAt!.valueOf() > Date.now() - msDelay); } }); + +test.serial('test date mode for text data type', async (t) => { + const { db } = t.context; + + const test = sqliteTable('test', { + t1: text('t1', { mode: 'date' }), + t2: text('t2', { mode: 'date' }), + }); + + await db.run(sql`create table ${test} (t1 text, t2 text)`); + + const now = new Date(); + const now2 = new Date('2024-04-19 23:01:30'); + + await db.insert(test).values({ t1: now, t2: now2 }).run(); + const res = await db.select().from(test).all(); + + t.deepEqual(res, [{ t1: now, t2: now2 }]); + + const res2 = await db.all< + Array<{ + t1: string; + t2: string; + }> + >(sql`select * from ${test}`); + + t.deepEqual(res2, [{ t1: now.toISOString(), t2: now2.toISOString() }]); + + await db.run(sql`drop table ${test}`); +});