diff --git a/.gitignore b/.gitignore index a377925fc..8982b9105 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ dist.new .turbo .rollup.cache dist-dts +rollup.config-*.mjs diff --git a/changelogs/drizzle-orm/0.28.3.md b/changelogs/drizzle-orm/0.28.3.md new file mode 100644 index 000000000..b6ad3336b --- /dev/null +++ b/changelogs/drizzle-orm/0.28.3.md @@ -0,0 +1,41 @@ +- 🎉 Added SQLite simplified query API + +- 🎉 Added `.$defaultFn()` / `.$default()` methods to column builders + +You can specify any logic and any implementation for a function like `cuid()` for runtime defaults. Drizzle won't limit you in the number of implementations you can add. + +> Note: This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm` + +```ts +import { varchar, mysqlTable } from "drizzle-orm/mysql-core"; +import { createId } from '@paralleldrive/cuid2'; + +const table = mysqlTable('table', { + id: varchar('id', { length: 128 }).$defaultFn(() => createId()), +}); +``` + +- 🎉 Added `table.$inferSelect` / `table._.inferSelect` and `table.$inferInsert` / `table._.inferInsert` for more convenient table model type inference + +- 🛠 Deprecated `InferModel` type in favor of more explicit `InferSelectModel` and `InferInsertModel` + +```ts +import { InferSelectModel, InferInsertModel } from 'drizzle-orm' + +const usersTable = pgTable('users', { + id: serial('id').primaryKey(), + name: text('name').notNull(), + verified: boolean('verified').notNull().default(false), + jsonb: jsonb('jsonb').$type(), + createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), +}); + +type SelectUser = typeof usersTable.$inferSelect; +type InsertUser = typeof usersTable.$inferInsert; + +type SelectUser2 = InferSelectModel; +type InsertUser2 = InferInsertModel; +``` + +- 🛠 Disabled `.d.ts` files bundling +- 🐛 Fixed sqlite-proxy and SQL.js response from `.get()` when the result is empty diff --git a/drizzle-orm/package.json b/drizzle-orm/package.json index b5cf7a901..ff97ef28e 100644 --- a/drizzle-orm/package.json +++ b/drizzle-orm/package.json @@ -1,6 +1,6 @@ { "name": "drizzle-orm", - "version": "0.28.2", + "version": "0.28.3", "description": "Drizzle ORM package for SQL databases", "type": "module", "scripts": { @@ -141,11 +141,13 @@ "better-sqlite3": "^8.4.0", "bun-types": "^0.6.6", "concurrently": "^8.1.0", + "cpy-cli": "^5.0.0", "knex": "^2.4.2", "kysely": "^0.25.0", "mysql2": "^3.3.3", "pg": "^8.11.0", "postgres": "^3.3.5", + "rimraf": "^5.0.0", "rollup": "^3.27.2", "rollup-plugin-dts": "^5.3.1", "sql.js": "^1.8.0", diff --git a/drizzle-orm/rollup.cjs.config.ts b/drizzle-orm/rollup.cjs.config.ts index 1e5c4c8a8..ba7164d67 100644 --- a/drizzle-orm/rollup.cjs.config.ts +++ b/drizzle-orm/rollup.cjs.config.ts @@ -31,6 +31,7 @@ export default defineConfig([ typescript({ tsconfig: 'tsconfig.cjs.json', outputToFilesystem: true, + incremental: false, }), ], }, diff --git a/drizzle-orm/rollup.dts.config.ts b/drizzle-orm/rollup.dts.config.ts deleted file mode 100644 index bba452d73..000000000 --- a/drizzle-orm/rollup.dts.config.ts +++ /dev/null @@ -1,26 +0,0 @@ -import json from '@rollup/plugin-json'; -import { defineConfig } from 'rollup'; -import dts from 'rollup-plugin-dts'; -import { entries, external } from './rollup.common'; - -export default defineConfig([ - { - input: entries.reduce>((acc, entry) => { - const from = 'dist-dts/' + entry + '.d.ts'; - const to = entry; - acc[to] = from; - return acc; - }, {}), - output: { - dir: 'dist.new', - minifyInternalExports: false, - }, - external, - plugins: [ - json({ - preferConst: true, - }), - dts(), - ], - }, -]); diff --git a/drizzle-orm/rollup.esm.config.ts b/drizzle-orm/rollup.esm.config.ts index a14dc78ed..c9ae38684 100644 --- a/drizzle-orm/rollup.esm.config.ts +++ b/drizzle-orm/rollup.esm.config.ts @@ -26,6 +26,7 @@ export default defineConfig([ typescript({ tsconfig: 'tsconfig.esm.json', outputToFilesystem: true, + incremental: false, }), ], }, diff --git a/drizzle-orm/scripts/build.ts b/drizzle-orm/scripts/build.ts index 7a868577a..7170886dc 100755 --- a/drizzle-orm/scripts/build.ts +++ b/drizzle-orm/scripts/build.ts @@ -1,6 +1,7 @@ #!/usr/bin/env -S pnpm tsx import 'zx/globals'; import concurrently from 'concurrently'; + import { entries } from '../rollup.common'; function updateAndCopyPackageJson() { @@ -36,9 +37,8 @@ await concurrently([ name: 'esm', }, { - command: `tsc -p tsconfig.esm.json --declaration --outDir dist-dts --emitDeclarationOnly && -resolve-tspaths --out dist-dts && -rollup --config rollup.dts.config.ts --configPlugin typescript`, + command: + `rimraf dist-dts && tsc -p tsconfig.dts.json --declaration --outDir dist-dts --emitDeclarationOnly && resolve-tspaths --out dist-dts && cpy 'dist-dts/**/*' dist.new && rimraf dist-dts`, name: 'dts', }, ], { diff --git a/drizzle-orm/src/column-builder.ts b/drizzle-orm/src/column-builder.ts index 97e021004..d1ec25ecd 100644 --- a/drizzle-orm/src/column-builder.ts +++ b/drizzle-orm/src/column-builder.ts @@ -65,6 +65,7 @@ export type ColumnBuilderRuntimeConfig TData | SQL) | undefined; hasDefault: boolean; primaryKey: boolean; isUnique: boolean; @@ -98,7 +99,9 @@ export type $Type = T & { // To understand how to use `ColumnBuilder` and `AnyColumnBuilder`, see `Column` and `AnyColumn` documentation. export abstract class ColumnBuilder< - T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig, + T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig & { + data: any; + }, TRuntimeConfig extends object = object, TTypeConfig extends object = object, TExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig, @@ -124,21 +127,66 @@ export abstract class ColumnBuilder< } as ColumnBuilderRuntimeConfig; } + /** + * Changes the data type of the column. Commonly used with `json` columns. Also, useful for branded types. + * + * @example + * ```ts + * const users = pgTable('users', { + * id: integer('id').$type().primaryKey(), + * details: json('details').$type().notNull(), + * }); + * ``` + */ $type(): $Type { return this as $Type; } + /** + * Adds a `not null` clause to the column definition. + * + * Affects the `select` model of the table - columns *without* `not null` will be nullable on select. + */ notNull(): NotNull { this.config.notNull = true; return this as NotNull; } + /** + * Adds a `default ` clause to the column definition. + * + * Affects the `insert` model of the table - columns *with* `default` are optional on insert. + * + * If you need to set a dynamic default value, use {@link $defaultFn} instead. + */ default(value: (this['_'] extends { $type: infer U } ? U : T['data']) | SQL): HasDefault { this.config.default = value; this.config.hasDefault = true; return this as HasDefault; } + /** + * Adds a dynamic default value to the column. + * The function will be called when the row is inserted, and the returned value will be used as the column value. + * + * **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`. + */ + $defaultFn(fn: () => (this['_'] extends { $type: infer U } ? U : T['data']) | SQL): HasDefault { + this.config.defaultFn = fn; + this.config.hasDefault = true; + return this as HasDefault; + } + + /** + * Alias for {@link $defaultFn}. + */ + $default = this.$defaultFn; + + /** + * Adds a `primary key` clause to the column definition. This implicitly makes the column `not null`. + * + * In SQLite, `integer primary key` implicitly makes the column auto-incrementing. + */ primaryKey(): TExtraConfig['primaryKeyHasDefault'] extends true ? HasDefault> : NotNull { this.config.primaryKey = true; this.config.notNull = true; diff --git a/drizzle-orm/src/column.ts b/drizzle-orm/src/column.ts index 2cbf1d021..d636efaa4 100644 --- a/drizzle-orm/src/column.ts +++ b/drizzle-orm/src/column.ts @@ -57,6 +57,7 @@ export abstract class Column< readonly primary: boolean; readonly notNull: boolean; readonly default: T['data'] | SQL | undefined; + readonly defaultFn: (() => T['data'] | SQL) | undefined; readonly hasDefault: boolean; readonly isUnique: boolean; readonly uniqueName: string | undefined; @@ -75,6 +76,7 @@ export abstract class Column< this.name = config.name; this.notNull = config.notNull; this.default = config.default; + this.defaultFn = config.defaultFn; this.hasDefault = config.hasDefault; this.primary = config.primaryKey; this.isUnique = config.isUnique; diff --git a/drizzle-orm/src/mysql-core/checks.ts b/drizzle-orm/src/mysql-core/checks.ts index 0d55998a4..a57b185c7 100644 --- a/drizzle-orm/src/mysql-core/checks.ts +++ b/drizzle-orm/src/mysql-core/checks.ts @@ -1,6 +1,6 @@ import { entityKind } from '~/entity'; import type { SQL } from '~/sql'; -import type { AnyMySqlTable } from './table'; +import type { MySqlTable } from './table'; export class CheckBuilder { static readonly [entityKind]: string = 'MySqlCheckBuilder'; @@ -10,7 +10,7 @@ export class CheckBuilder { constructor(public name: string, public value: SQL) {} /** @internal */ - build(table: AnyMySqlTable): Check { + build(table: MySqlTable): Check { return new Check(table, this); } } @@ -21,7 +21,7 @@ export class Check { readonly name: string; readonly value: SQL; - constructor(public table: AnyMySqlTable, builder: CheckBuilder) { + constructor(public table: MySqlTable, builder: CheckBuilder) { this.name = builder.name; this.value = builder.value; } diff --git a/drizzle-orm/src/mysql-core/columns/common.ts b/drizzle-orm/src/mysql-core/columns/common.ts index 53576a7da..6541a5b57 100644 --- a/drizzle-orm/src/mysql-core/columns/common.ts +++ b/drizzle-orm/src/mysql-core/columns/common.ts @@ -17,7 +17,7 @@ import { type Update } from '~/utils'; import { uniqueKeyName } from '../unique-constraint'; export interface ReferenceConfig { - ref: () => AnyMySqlColumn; + ref: () => MySqlColumn; actions: { onUpdate?: UpdateDeleteAction; onDelete?: UpdateDeleteAction; @@ -25,7 +25,9 @@ export interface ReferenceConfig { } export abstract class MySqlColumnBuilder< - T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig, + T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig & { + data: any; + }, TRuntimeConfig extends object = object, TTypeConfig extends object = object, TExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig, @@ -46,7 +48,7 @@ export abstract class MySqlColumnBuilder< } /** @internal */ - buildForeignKeys(column: AnyMySqlColumn, table: AnyMySqlTable): ForeignKey[] { + buildForeignKeys(column: MySqlColumn, table: MySqlTable): ForeignKey[] { return this.foreignKeyConfigs.map(({ ref, actions }) => { return ((ref, actions) => { const builder = new ForeignKeyBuilder(() => { diff --git a/drizzle-orm/src/mysql-core/db.ts b/drizzle-orm/src/mysql-core/db.ts index 05aad5bca..607b1a0c8 100644 --- a/drizzle-orm/src/mysql-core/db.ts +++ b/drizzle-orm/src/mysql-core/db.ts @@ -26,7 +26,7 @@ import type { QueryResultKind, } from './session'; import type { WithSubqueryWithSelection } from './subquery'; -import type { AnyMySqlTable } from './table'; +import type { MySqlTable } from './table'; export class MySqlDatabase< TQueryResult extends QueryResultHKT, @@ -66,7 +66,7 @@ export class MySqlDatabase< schema!.fullSchema, this._.schema, this._.tableNamesMap, - schema!.fullSchema[tableName] as AnyMySqlTable, + schema!.fullSchema[tableName] as MySqlTable, columns, dialect, session, @@ -147,15 +147,15 @@ export class MySqlDatabase< }); } - update(table: TTable): MySqlUpdateBuilder { + update(table: TTable): MySqlUpdateBuilder { return new MySqlUpdateBuilder(table, this.session, this.dialect); } - insert(table: TTable): MySqlInsertBuilder { + insert(table: TTable): MySqlInsertBuilder { return new MySqlInsertBuilder(table, this.session, this.dialect); } - delete(table: TTable): MySqlDelete { + delete(table: TTable): MySqlDelete { return new MySqlDelete(table, this.session, this.dialect); } diff --git a/drizzle-orm/src/mysql-core/dialect.ts b/drizzle-orm/src/mysql-core/dialect.ts index 8aba01146..dcb6cfaa6 100644 --- a/drizzle-orm/src/mysql-core/dialect.ts +++ b/drizzle-orm/src/mysql-core/dialect.ts @@ -20,14 +20,12 @@ import { getTableName, Table } from '~/table'; import { orderSelectedFields, type UpdateSet } from '~/utils'; import { View, ViewBaseConfig } from '~/view'; import { DrizzleError } from '..'; -import type { AnyMySqlColumn } from './columns/common'; import { MySqlColumn } from './columns/common'; import type { MySqlDeleteConfig } from './query-builders/delete'; import type { MySqlInsertConfig } from './query-builders/insert'; import type { Join, MySqlSelectConfig, SelectedFieldsOrdered } from './query-builders/select.types'; import type { MySqlUpdateConfig } from './query-builders/update'; import type { MySqlSession } from './session'; -import type { AnyMySqlTable } from './table'; import { MySqlTable } from './table'; import { MySqlViewBase } from './view'; @@ -100,14 +98,14 @@ export class MySqlDialect { return sql`delete from ${table}${whereSql}${returningSql}`; } - buildUpdateSet(table: AnyMySqlTable, set: UpdateSet): SQL { + buildUpdateSet(table: MySqlTable, set: UpdateSet): SQL { const setEntries = Object.entries(set); const setSize = setEntries.length; return sql.join( setEntries .flatMap(([colName, value], i): SQL[] => { - const col: AnyMySqlColumn = table[Table.Symbol.Columns][colName]!; + const col: MySqlColumn = table[Table.Symbol.Columns][colName]!; const res = sql`${sql.identifier(col.name)} = ${value}`; if (i < setSize - 1) { return [res, sql.raw(', ')]; @@ -208,7 +206,7 @@ export class MySqlDialect { distinct, }: MySqlSelectConfig, ): SQL { - const fieldsList = fieldsFlat ?? orderSelectedFields(fields); + const fieldsList = fieldsFlat ?? orderSelectedFields(fields); for (const f of fieldsList) { if ( is(f.field, Column) @@ -337,20 +335,26 @@ export class MySqlDialect { } buildInsertQuery({ table, values, ignore, onConflict }: MySqlInsertConfig): SQL { - const isSingleValue = values.length === 1; + // const isSingleValue = values.length === 1; const valuesSqlList: ((SQLChunk | SQL)[] | SQL)[] = []; - const columns: Record = table[Table.Symbol.Columns]; - const colEntries: [string, AnyMySqlColumn][] = isSingleValue - ? Object.keys(values[0]!).map((fieldName) => [fieldName, columns[fieldName]!]) - : Object.entries(columns); + const columns: Record = table[Table.Symbol.Columns]; + const colEntries: [string, MySqlColumn][] = Object.entries(columns) + const insertOrder = colEntries.map(([, column]) => sql.identifier(column.name)); for (const [valueIndex, value] of values.entries()) { const valueList: (SQLChunk | SQL)[] = []; - for (const [fieldName] of colEntries) { + for (const [fieldName, col] of colEntries) { const colValue = value[fieldName]; if (colValue === undefined || (is(colValue, Param) && colValue.value === undefined)) { - valueList.push(sql`default`); + // eslint-disable-next-line unicorn/no-negated-condition + if (col.defaultFn !== undefined) { + const defaultFnResult = col.defaultFn(); + const defaultValue = is(defaultFnResult, SQL) ? defaultFnResult : sql.param(defaultFnResult, col); + valueList.push(defaultValue); + } else { + valueList.push(sql`default`); + } } else { valueList.push(colValue); } @@ -392,14 +396,14 @@ export class MySqlDialect { fullSchema: Record; schema: TablesRelationalConfig; tableNamesMap: Record; - table: AnyMySqlTable; + table: MySqlTable; tableConfig: TableRelationalConfig; queryConfig: true | DBQueryConfig<'many', true>; tableAlias: string; nestedQueryRelation?: Relation; joinOn?: SQL; - }): BuildRelationalQueryResult { - let selection: BuildRelationalQueryResult['selection'] = []; + }): BuildRelationalQueryResult { + let selection: BuildRelationalQueryResult['selection'] = []; let limit, offset, orderBy: MySqlSelectConfig['orderBy'], where; const joins: Join[] = []; @@ -410,7 +414,7 @@ export class MySqlDialect { ) => ({ dbKey: value.name, tsKey: key, - field: aliasedTableColumn(value as AnyMySqlColumn, tableAlias), + field: aliasedTableColumn(value as MySqlColumn, tableAlias), relationTableTsKey: undefined, isJson: false, selection: [], @@ -427,7 +431,7 @@ export class MySqlDialect { where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); } - const fieldsSelection: { tsKey: string; value: AnyMySqlColumn | SQL.Aliased }[] = []; + const fieldsSelection: { tsKey: string; value: MySqlColumn | SQL.Aliased }[] = []; let selectedColumns: string[] = []; // Figure out which columns to select @@ -458,7 +462,7 @@ export class MySqlDialect { } for (const field of selectedColumns) { - const column = tableConfig.columns[field]! as AnyMySqlColumn; + const column = tableConfig.columns[field]! as MySqlColumn; fieldsSelection.push({ tsKey: field, value: column }); } @@ -511,7 +515,7 @@ export class MySqlDialect { } orderBy = orderByOrig.map((orderByValue) => { if (is(orderByValue, Column)) { - return aliasedTableColumn(orderByValue, tableAlias) as AnyMySqlColumn; + return aliasedTableColumn(orderByValue, tableAlias) as MySqlColumn; } return mapColumnsInSQLToAlias(orderByValue, tableAlias); }); @@ -543,7 +547,7 @@ export class MySqlDialect { fullSchema, schema, tableNamesMap, - table: fullSchema[relationTableTsName] as AnyMySqlTable, + table: fullSchema[relationTableTsName] as MySqlTable, tableConfig: schema[relationTableTsName]!, queryConfig: is(relation, One) ? (selectedRelationConfigValue === true @@ -687,14 +691,14 @@ export class MySqlDialect { fullSchema: Record; schema: TablesRelationalConfig; tableNamesMap: Record; - table: AnyMySqlTable; + table: MySqlTable; tableConfig: TableRelationalConfig; queryConfig: true | DBQueryConfig<'many', true>; tableAlias: string; nestedQueryRelation?: Relation; joinOn?: SQL; - }): BuildRelationalQueryResult { - let selection: BuildRelationalQueryResult['selection'] = []; + }): BuildRelationalQueryResult { + let selection: BuildRelationalQueryResult['selection'] = []; let limit, offset, orderBy: MySqlSelectConfig['orderBy'] = [], where; if (config === true) { @@ -704,7 +708,7 @@ export class MySqlDialect { ) => ({ dbKey: value.name, tsKey: key, - field: aliasedTableColumn(value as AnyMySqlColumn, tableAlias), + field: aliasedTableColumn(value as MySqlColumn, tableAlias), relationTableTsKey: undefined, isJson: false, selection: [], @@ -721,7 +725,7 @@ export class MySqlDialect { where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); } - const fieldsSelection: { tsKey: string; value: AnyMySqlColumn | SQL.Aliased }[] = []; + const fieldsSelection: { tsKey: string; value: MySqlColumn | SQL.Aliased }[] = []; let selectedColumns: string[] = []; // Figure out which columns to select @@ -752,7 +756,7 @@ export class MySqlDialect { } for (const field of selectedColumns) { - const column = tableConfig.columns[field]! as AnyMySqlColumn; + const column = tableConfig.columns[field]! as MySqlColumn; fieldsSelection.push({ tsKey: field, value: column }); } @@ -805,7 +809,7 @@ export class MySqlDialect { } orderBy = orderByOrig.map((orderByValue) => { if (is(orderByValue, Column)) { - return aliasedTableColumn(orderByValue, tableAlias) as AnyMySqlColumn; + return aliasedTableColumn(orderByValue, tableAlias) as MySqlColumn; } return mapColumnsInSQLToAlias(orderByValue, tableAlias); }); @@ -837,7 +841,7 @@ export class MySqlDialect { fullSchema, schema, tableNamesMap, - table: fullSchema[relationTableTsName] as AnyMySqlTable, + table: fullSchema[relationTableTsName] as MySqlTable, tableConfig: schema[relationTableTsName]!, queryConfig: is(relation, One) ? (selectedRelationConfigValue === true diff --git a/drizzle-orm/src/mysql-core/expressions.ts b/drizzle-orm/src/mysql-core/expressions.ts index 8bce4d893..6625f72d1 100644 --- a/drizzle-orm/src/mysql-core/expressions.ts +++ b/drizzle-orm/src/mysql-core/expressions.ts @@ -1,16 +1,16 @@ import { bindIfParam } from '~/expressions'; import type { Placeholder, SQL, SQLChunk, SQLWrapper } from '~/sql'; import { sql } from '~/sql'; -import type { AnyMySqlColumn } from './columns/common'; +import type { MySqlColumn } from './columns'; export * from '~/expressions'; -export function concat(column: AnyMySqlColumn | SQL.Aliased, value: string | Placeholder | SQLWrapper): SQL { +export function concat(column: MySqlColumn | SQL.Aliased, value: string | Placeholder | SQLWrapper): SQL { return sql`${column} || ${bindIfParam(value, column)}`; } export function substring( - column: AnyMySqlColumn | SQL.Aliased, + column: MySqlColumn | SQL.Aliased, { from, for: _for }: { from?: number | Placeholder | SQLWrapper; for?: number | Placeholder | SQLWrapper }, ): SQL { const chunks: SQLChunk[] = [sql`substring(`, column]; diff --git a/drizzle-orm/src/mysql-core/foreign-keys.ts b/drizzle-orm/src/mysql-core/foreign-keys.ts index c69751794..9d4123542 100644 --- a/drizzle-orm/src/mysql-core/foreign-keys.ts +++ b/drizzle-orm/src/mysql-core/foreign-keys.ts @@ -1,14 +1,13 @@ import { entityKind } from '~/entity'; -import type { AnyMySqlColumn } from './columns'; -import type { AnyMySqlTable } from './table'; +import type { AnyMySqlColumn, MySqlColumn } from './columns'; import { MySqlTable } from './table'; export type UpdateDeleteAction = 'cascade' | 'restrict' | 'no action' | 'set null' | 'set default'; export type Reference = () => { - readonly columns: AnyMySqlColumn[]; - readonly foreignTable: AnyMySqlTable; - readonly foreignColumns: AnyMySqlColumn[]; + readonly columns: MySqlColumn[]; + readonly foreignTable: MySqlTable; + readonly foreignColumns: MySqlColumn[]; }; export class ForeignKeyBuilder { @@ -25,8 +24,8 @@ export class ForeignKeyBuilder { constructor( config: () => { - columns: AnyMySqlColumn[]; - foreignColumns: AnyMySqlColumn[]; + columns: MySqlColumn[]; + foreignColumns: MySqlColumn[]; }, actions?: { onUpdate?: UpdateDeleteAction; @@ -35,7 +34,7 @@ export class ForeignKeyBuilder { ) { this.reference = () => { const { columns, foreignColumns } = config(); - return { columns, foreignTable: foreignColumns[0]!.table as AnyMySqlTable, foreignColumns }; + return { columns, foreignTable: foreignColumns[0]!.table as MySqlTable, foreignColumns }; }; if (actions) { this._onUpdate = actions.onUpdate; @@ -54,7 +53,7 @@ export class ForeignKeyBuilder { } /** @internal */ - build(table: AnyMySqlTable): ForeignKey { + build(table: MySqlTable): ForeignKey { return new ForeignKey(table, this); } } @@ -68,7 +67,7 @@ export class ForeignKey { readonly onUpdate: UpdateDeleteAction | undefined; readonly onDelete: UpdateDeleteAction | undefined; - constructor(readonly table: AnyMySqlTable, builder: ForeignKeyBuilder) { + constructor(readonly table: MySqlTable, builder: ForeignKeyBuilder) { this.reference = builder.reference; this.onUpdate = builder._onUpdate; this.onDelete = builder._onDelete; @@ -90,12 +89,12 @@ export class ForeignKey { type ColumnsWithTable< TTableName extends string, - TColumns extends AnyMySqlColumn[], + TColumns extends MySqlColumn[], > = { [Key in keyof TColumns]: AnyMySqlColumn<{ tableName: TTableName }> }; -export type GetColumnsTable = ( - TColumns extends AnyMySqlColumn ? TColumns - : TColumns extends AnyMySqlColumn[] ? TColumns[number] +export type GetColumnsTable = ( + TColumns extends MySqlColumn ? TColumns + : TColumns extends MySqlColumn[] ? TColumns[number] : never ) extends AnyMySqlColumn<{ tableName: infer TTableName extends string }> ? TTableName : never; diff --git a/drizzle-orm/src/mysql-core/indexes.ts b/drizzle-orm/src/mysql-core/indexes.ts index 937654570..c9bb5c553 100644 --- a/drizzle-orm/src/mysql-core/indexes.ts +++ b/drizzle-orm/src/mysql-core/indexes.ts @@ -1,7 +1,7 @@ import { entityKind } from '~/entity'; import type { SQL } from '~/sql'; -import type { AnyMySqlColumn } from './columns'; -import type { AnyMySqlTable } from './table'; +import type { AnyMySqlColumn, MySqlColumn } from './columns'; +import type { MySqlTable } from './table'; interface IndexConfig { name: string; @@ -29,7 +29,7 @@ interface IndexConfig { lock?: 'default' | 'none' | 'shared' | 'exclusive'; } -export type IndexColumn = AnyMySqlColumn | SQL; +export type IndexColumn = MySqlColumn | SQL; export class IndexBuilderOn { static readonly [entityKind]: string = 'MySqlIndexBuilderOn'; @@ -42,7 +42,7 @@ export class IndexBuilderOn { } export interface AnyIndexBuilder { - build(table: AnyMySqlTable): Index; + build(table: MySqlTable): Index; } // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -78,7 +78,7 @@ export class IndexBuilder implements AnyIndexBuilder { } /** @internal */ - build(table: AnyMySqlTable): Index { + build(table: MySqlTable): Index { return new Index(this.config, table); } } @@ -86,9 +86,9 @@ export class IndexBuilder implements AnyIndexBuilder { export class Index { static readonly [entityKind]: string = 'MySqlIndex'; - readonly config: IndexConfig & { table: AnyMySqlTable }; + readonly config: IndexConfig & { table: MySqlTable }; - constructor(config: IndexConfig, table: AnyMySqlTable) { + constructor(config: IndexConfig, table: MySqlTable) { this.config = { ...config, table }; } } diff --git a/drizzle-orm/src/mysql-core/primary-keys.ts b/drizzle-orm/src/mysql-core/primary-keys.ts index aa559c487..34837cb8d 100644 --- a/drizzle-orm/src/mysql-core/primary-keys.ts +++ b/drizzle-orm/src/mysql-core/primary-keys.ts @@ -1,6 +1,5 @@ import { entityKind } from '~/entity'; -import type { AnyMySqlColumn } from './columns'; -import type { AnyMySqlTable } from './table'; +import type { AnyMySqlColumn, MySqlColumn } from './columns'; import { MySqlTable } from './table'; export function primaryKey< @@ -14,16 +13,16 @@ export class PrimaryKeyBuilder { static readonly [entityKind]: string = 'MySqlPrimaryKeyBuilder'; /** @internal */ - columns: AnyMySqlColumn<{}>[]; + columns: MySqlColumn[]; constructor( - columns: AnyMySqlColumn[], + columns: MySqlColumn[], ) { this.columns = columns; } /** @internal */ - build(table: AnyMySqlTable): PrimaryKey { + build(table: MySqlTable): PrimaryKey { return new PrimaryKey(table, this.columns); } } @@ -31,9 +30,9 @@ export class PrimaryKeyBuilder { export class PrimaryKey { static readonly [entityKind]: string = 'MySqlPrimaryKey'; - readonly columns: AnyMySqlColumn<{}>[]; + readonly columns: MySqlColumn[]; - constructor(readonly table: AnyMySqlTable, columns: AnyMySqlColumn<{}>[]) { + constructor(readonly table: MySqlTable, columns: MySqlColumn[]) { this.columns = columns; } diff --git a/drizzle-orm/src/mysql-core/query-builders/delete.ts b/drizzle-orm/src/mysql-core/query-builders/delete.ts index feb24086d..05c86de72 100644 --- a/drizzle-orm/src/mysql-core/query-builders/delete.ts +++ b/drizzle-orm/src/mysql-core/query-builders/delete.ts @@ -8,28 +8,28 @@ import type { QueryResultHKT, QueryResultKind, } from '~/mysql-core/session'; -import type { AnyMySqlTable } from '~/mysql-core/table'; +import type { MySqlTable } from '~/mysql-core/table'; import { QueryPromise } from '~/query-promise'; import type { Query, SQL, SQLWrapper } from '~/sql'; import type { SelectedFieldsOrdered } from './select.types'; export interface MySqlDeleteConfig { where?: SQL | undefined; - table: AnyMySqlTable; + table: MySqlTable; returning?: SelectedFieldsOrdered; } // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface MySqlDelete< // eslint-disable-next-line @typescript-eslint/no-unused-vars - TTable extends AnyMySqlTable, + TTable extends MySqlTable, TQueryResult extends QueryResultHKT, // eslint-disable-next-line @typescript-eslint/no-unused-vars TPreparedQueryHKT extends PreparedQueryHKTBase, > extends QueryPromise> {} export class MySqlDelete< - TTable extends AnyMySqlTable, + TTable extends MySqlTable, TQueryResult extends QueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, > extends QueryPromise> implements SQLWrapper { diff --git a/drizzle-orm/src/mysql-core/query-builders/insert.ts b/drizzle-orm/src/mysql-core/query-builders/insert.ts index 615a52ab5..0886d820b 100644 --- a/drizzle-orm/src/mysql-core/query-builders/insert.ts +++ b/drizzle-orm/src/mysql-core/query-builders/insert.ts @@ -8,7 +8,7 @@ import type { QueryResultHKT, QueryResultKind, } from '~/mysql-core/session'; -import type { AnyMySqlTable } from '~/mysql-core/table'; +import type { MySqlTable } from '~/mysql-core/table'; import { QueryPromise } from '~/query-promise'; import type { Placeholder, Query, SQLWrapper } from '~/sql'; import { Param, SQL, sql } from '~/sql'; @@ -16,23 +16,23 @@ import { type InferModel, Table } from '~/table'; import { mapUpdateSet } from '~/utils'; import type { MySqlUpdateSetSource } from './update'; -export interface MySqlInsertConfig { +export interface MySqlInsertConfig { table: TTable; values: Record[]; ignore: boolean; onConflict?: SQL; } -export type AnyMySqlInsertConfig = MySqlInsertConfig; +export type AnyMySqlInsertConfig = MySqlInsertConfig; -export type MySqlInsertValue = +export type MySqlInsertValue = & { [Key in keyof InferModel]: InferModel[Key] | SQL | Placeholder; } & {}; export class MySqlInsertBuilder< - TTable extends AnyMySqlTable, + TTable extends MySqlTable, TQueryResult extends QueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, > { @@ -76,13 +76,13 @@ export class MySqlInsertBuilder< export interface MySqlInsert< // eslint-disable-next-line @typescript-eslint/no-unused-vars - TTable extends AnyMySqlTable, + TTable extends MySqlTable, TQueryResult extends QueryResultHKT, // eslint-disable-next-line @typescript-eslint/no-unused-vars TPreparedQueryHKT extends PreparedQueryHKTBase, > extends QueryPromise>, SQLWrapper {} export class MySqlInsert< - TTable extends AnyMySqlTable, + TTable extends MySqlTable, TQueryResult extends QueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, > extends QueryPromise> implements SQLWrapper { diff --git a/drizzle-orm/src/mysql-core/query-builders/query.ts b/drizzle-orm/src/mysql-core/query-builders/query.ts index 196dc893e..c7be3356a 100644 --- a/drizzle-orm/src/mysql-core/query-builders/query.ts +++ b/drizzle-orm/src/mysql-core/query-builders/query.ts @@ -17,7 +17,7 @@ import { type PreparedQueryHKTBase, type PreparedQueryKind, } from '../session'; -import { type AnyMySqlTable } from '../table'; +import { type MySqlTable } from '../table'; export class RelationalQueryBuilder< TPreparedQueryHKT extends PreparedQueryHKTBase, @@ -30,7 +30,7 @@ export class RelationalQueryBuilder< private fullSchema: Record, private schema: TSchema, private tableNamesMap: Record, - private table: AnyMySqlTable, + private table: MySqlTable, private tableConfig: TableRelationalConfig, private dialect: MySqlDialect, private session: MySqlSession, @@ -84,7 +84,7 @@ export class MySqlRelationalQuery< private fullSchema: Record, private schema: TablesRelationalConfig, private tableNamesMap: Record, - private table: AnyMySqlTable, + private table: MySqlTable, private tableConfig: TableRelationalConfig, private dialect: MySqlDialect, private session: MySqlSession, diff --git a/drizzle-orm/src/mysql-core/query-builders/select.ts b/drizzle-orm/src/mysql-core/query-builders/select.ts index 0396544ab..88bb24553 100644 --- a/drizzle-orm/src/mysql-core/query-builders/select.ts +++ b/drizzle-orm/src/mysql-core/query-builders/select.ts @@ -1,9 +1,9 @@ import { entityKind, is } from '~/entity'; -import type { AnyMySqlColumn } from '~/mysql-core/columns'; +import type { MySqlColumn } from '~/mysql-core/columns'; import type { MySqlDialect } from '~/mysql-core/dialect'; import type { MySqlSession, PreparedQueryConfig, PreparedQueryHKTBase, PreparedQueryKind } from '~/mysql-core/session'; import type { SubqueryWithSelection } from '~/mysql-core/subquery'; -import type { AnyMySqlTable } from '~/mysql-core/table'; +import type { MySqlTable } from '~/mysql-core/table'; import { MySqlViewBase } from '~/mysql-core/view'; import { TypedQueryBuilder } from '~/query-builders/query-builder'; import type { @@ -73,7 +73,7 @@ export class MySqlSelectBuilder< this.distinct = config.distinct; } - from( + from( source: TFrom, ): CreateMySqlSelectFromBuilderMode< TBuilderMode, @@ -99,7 +99,7 @@ export class MySqlSelectBuilder< } else if (is(source, SQL)) { fields = {}; } else { - fields = getTableColumns(source); + fields = getTableColumns(source); } return new MySqlSelect( @@ -176,7 +176,7 @@ export abstract class MySqlSelectQueryBuilder< joinType: TJoinType, ): JoinFn { return ( - table: AnyMySqlTable | Subquery | MySqlViewBase | SQL, + table: MySqlTable | Subquery | MySqlViewBase | SQL, on: ((aliases: TSelection) => SQL | undefined) | SQL | undefined, ) => { const baseTableName = this.tableName; @@ -283,12 +283,12 @@ export abstract class MySqlSelectQueryBuilder< return this; } - groupBy(builder: (aliases: TSelection) => ValueOrArray): this; - groupBy(...columns: (AnyMySqlColumn | SQL | SQL.Aliased)[]): this; + groupBy(builder: (aliases: TSelection) => ValueOrArray): this; + groupBy(...columns: (MySqlColumn | SQL | SQL.Aliased)[]): this; groupBy( ...columns: - | [(aliases: TSelection) => ValueOrArray] - | (AnyMySqlColumn | SQL | SQL.Aliased)[] + | [(aliases: TSelection) => ValueOrArray] + | (MySqlColumn | SQL | SQL.Aliased)[] ) { if (typeof columns[0] === 'function') { const groupBy = columns[0]( @@ -299,17 +299,17 @@ export abstract class MySqlSelectQueryBuilder< ); this.config.groupBy = Array.isArray(groupBy) ? groupBy : [groupBy]; } else { - this.config.groupBy = columns as (AnyMySqlColumn | SQL | SQL.Aliased)[]; + this.config.groupBy = columns as (MySqlColumn | SQL | SQL.Aliased)[]; } return this; } - orderBy(builder: (aliases: TSelection) => ValueOrArray): this; - orderBy(...columns: (AnyMySqlColumn | SQL | SQL.Aliased)[]): this; + orderBy(builder: (aliases: TSelection) => ValueOrArray): this; + orderBy(...columns: (MySqlColumn | SQL | SQL.Aliased)[]): this; orderBy( ...columns: - | [(aliases: TSelection) => ValueOrArray] - | (AnyMySqlColumn | SQL | SQL.Aliased)[] + | [(aliases: TSelection) => ValueOrArray] + | (MySqlColumn | SQL | SQL.Aliased)[] ) { if (typeof columns[0] === 'function') { const orderBy = columns[0]( @@ -320,7 +320,7 @@ export abstract class MySqlSelectQueryBuilder< ); this.config.orderBy = Array.isArray(orderBy) ? orderBy : [orderBy]; } else { - this.config.orderBy = columns as (AnyMySqlColumn | SQL | SQL.Aliased)[]; + this.config.orderBy = columns as (MySqlColumn | SQL | SQL.Aliased)[]; } return this; } @@ -399,7 +399,7 @@ export class MySqlSelect< if (!this.session) { throw new Error('Cannot execute a query on a query builder. Please use a database instance instead.'); } - const fieldsList = orderSelectedFields(this.config.fields); + const fieldsList = orderSelectedFields(this.config.fields); const query = this.session.prepareQuery< PreparedQueryConfig & { execute: SelectResult[] }, TPreparedQueryHKT diff --git a/drizzle-orm/src/mysql-core/query-builders/select.types.ts b/drizzle-orm/src/mysql-core/query-builders/select.types.ts index 87f0a4371..7d4c7f1c6 100644 --- a/drizzle-orm/src/mysql-core/query-builders/select.types.ts +++ b/drizzle-orm/src/mysql-core/query-builders/select.types.ts @@ -1,5 +1,5 @@ -import type { AnyMySqlColumn } from '~/mysql-core/columns'; -import type { AnyMySqlTable, MySqlTable, MySqlTableWithColumns } from '~/mysql-core/table'; +import type { MySqlColumn } from '~/mysql-core/columns'; +import type { MySqlTable, MySqlTableWithColumns } from '~/mysql-core/table'; import type { MySqlViewBase, MySqlViewWithSelection } from '~/mysql-core/view'; import type { SelectedFields as SelectedFieldsBase, @@ -25,7 +25,7 @@ import type { MySqlSelect, MySqlSelectQueryBuilder } from './select'; export interface Join { on: SQL | undefined; - table: AnyMySqlTable | Subquery | MySqlViewBase | SQL; + table: MySqlTable | Subquery | MySqlViewBase | SQL; alias: string | undefined; joinType: JoinType; lateral?: boolean; @@ -53,12 +53,12 @@ export interface MySqlSelectConfig { fieldsFlat?: SelectedFieldsOrdered; where?: SQL; having?: SQL; - table: AnyMySqlTable | Subquery | MySqlViewBase | SQL; + table: MySqlTable | Subquery | MySqlViewBase | SQL; limit?: number | Placeholder; offset?: number | Placeholder; joins?: Join[]; - orderBy?: (AnyMySqlColumn | SQL | SQL.Aliased)[]; - groupBy?: (AnyMySqlColumn | SQL | SQL.Aliased)[]; + orderBy?: (MySqlColumn | SQL | SQL.Aliased)[]; + groupBy?: (MySqlColumn | SQL | SQL.Aliased)[]; lockingClause?: { strength: LockStrength; config: LockConfig; @@ -74,7 +74,7 @@ export type JoinFn< TSelection, TNullabilityMap extends Record, > = < - TJoinedTable extends AnyMySqlTable | Subquery | MySqlViewBase | SQL, + TJoinedTable extends MySqlTable | Subquery | MySqlViewBase | SQL, TJoinedName extends GetSelectTableName = GetSelectTableName, >(table: TJoinedTable, on: ((aliases: TSelection) => SQL | undefined) | SQL | undefined) => MySqlSelectKind< THKT, @@ -83,7 +83,7 @@ export type JoinFn< TTableName, TSelection, TJoinedName, - TJoinedTable extends AnyMySqlTable ? TJoinedTable['_']['columns'] + TJoinedTable extends MySqlTable ? TJoinedTable['_']['columns'] : TJoinedTable extends Subquery ? Assume : never, TSelectMode @@ -92,11 +92,11 @@ export type JoinFn< AppendToNullabilityMap >; -export type SelectedFieldsFlat = SelectedFieldsFlatBase; +export type SelectedFieldsFlat = SelectedFieldsFlatBase; -export type SelectedFields = SelectedFieldsBase; +export type SelectedFields = SelectedFieldsBase; -export type SelectedFieldsOrdered = SelectedFieldsOrderedBase; +export type SelectedFieldsOrdered = SelectedFieldsOrderedBase; export type LockStrength = 'update' | 'share'; diff --git a/drizzle-orm/src/mysql-core/query-builders/update.ts b/drizzle-orm/src/mysql-core/query-builders/update.ts index dc38fdc81..b3d51037a 100644 --- a/drizzle-orm/src/mysql-core/query-builders/update.ts +++ b/drizzle-orm/src/mysql-core/query-builders/update.ts @@ -9,7 +9,7 @@ import type { QueryResultHKT, QueryResultKind, } from '~/mysql-core/session'; -import type { AnyMySqlTable } from '~/mysql-core/table'; +import type { MySqlTable } from '~/mysql-core/table'; import { QueryPromise } from '~/query-promise'; import type { Query, SQL, SQLWrapper } from '~/sql'; import { mapUpdateSet, type UpdateSet } from '~/utils'; @@ -18,11 +18,11 @@ import type { SelectedFieldsOrdered } from './select.types'; export interface MySqlUpdateConfig { where?: SQL | undefined; set: UpdateSet; - table: AnyMySqlTable; + table: MySqlTable; returning?: SelectedFieldsOrdered; } -export type MySqlUpdateSetSource = +export type MySqlUpdateSetSource = & { [Key in keyof TTable['_']['columns']]?: | GetColumnData @@ -31,7 +31,7 @@ export type MySqlUpdateSetSource = & {}; export class MySqlUpdateBuilder< - TTable extends AnyMySqlTable, + TTable extends MySqlTable, TQueryResult extends QueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, > { @@ -52,13 +52,13 @@ export class MySqlUpdateBuilder< export interface MySqlUpdate< // eslint-disable-next-line @typescript-eslint/no-unused-vars - TTable extends AnyMySqlTable, + TTable extends MySqlTable, TQueryResult extends QueryResultHKT, // eslint-disable-next-line @typescript-eslint/no-unused-vars TPreparedQueryHKT extends PreparedQueryHKTBase, > extends QueryPromise>, SQLWrapper {} export class MySqlUpdate< - TTable extends AnyMySqlTable, + TTable extends MySqlTable, TQueryResult extends QueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, > extends QueryPromise> implements SQLWrapper { diff --git a/drizzle-orm/src/mysql-core/unique-constraint.ts b/drizzle-orm/src/mysql-core/unique-constraint.ts index 39b235659..348c3ad12 100644 --- a/drizzle-orm/src/mysql-core/unique-constraint.ts +++ b/drizzle-orm/src/mysql-core/unique-constraint.ts @@ -1,30 +1,30 @@ import { entityKind } from '~/entity'; -import type { AnyMySqlColumn } from './columns'; -import { type AnyMySqlTable, MySqlTable } from './table'; +import type { MySqlColumn } from './columns'; +import { MySqlTable } from './table'; export function unique(name?: string): UniqueOnConstraintBuilder { return new UniqueOnConstraintBuilder(name); } -export function uniqueKeyName(table: AnyMySqlTable, columns: string[]) { - return `${table[MySqlTable.Symbol.Name]}_${columns.join('_')}_unique` +export function uniqueKeyName(table: MySqlTable, columns: string[]) { + return `${table[MySqlTable.Symbol.Name]}_${columns.join('_')}_unique`; } export class UniqueConstraintBuilder { static readonly [entityKind]: string = 'MySqlUniqueConstraintBuilder'; /** @internal */ - columns: AnyMySqlColumn<{}>[]; + columns: MySqlColumn[]; constructor( - columns: AnyMySqlColumn[], + columns: MySqlColumn[], private name?: string, ) { this.columns = columns; } /** @internal */ - build(table: AnyMySqlTable): UniqueConstraint { + build(table: MySqlTable): UniqueConstraint { return new UniqueConstraint(table, this.columns, this.name); } } @@ -41,7 +41,7 @@ export class UniqueOnConstraintBuilder { this.name = name; } - on(...columns: [AnyMySqlColumn, ...AnyMySqlColumn[]]) { + on(...columns: [MySqlColumn, ...MySqlColumn[]]) { return new UniqueConstraintBuilder(columns, this.name); } } @@ -49,11 +49,11 @@ export class UniqueOnConstraintBuilder { export class UniqueConstraint { static readonly [entityKind]: string = 'MySqlUniqueConstraint'; - readonly columns: AnyMySqlColumn<{}>[]; + readonly columns: MySqlColumn[]; readonly name?: string; readonly nullsNotDistinct: boolean = false; - constructor(readonly table: AnyMySqlTable, columns: AnyMySqlColumn<{}>[], name?: string) { + constructor(readonly table: MySqlTable, columns: MySqlColumn[], name?: string) { this.columns = columns; this.name = name ?? uniqueKeyName(this.table, this.columns.map((column) => column.name)); } diff --git a/drizzle-orm/src/mysql-core/utils.ts b/drizzle-orm/src/mysql-core/utils.ts index 1cf7488ed..d8cccf817 100644 --- a/drizzle-orm/src/mysql-core/utils.ts +++ b/drizzle-orm/src/mysql-core/utils.ts @@ -9,13 +9,12 @@ import type { Index } from './indexes'; import { IndexBuilder } from './indexes'; import type { PrimaryKey } from './primary-keys'; import { PrimaryKeyBuilder } from './primary-keys'; -import type { AnyMySqlTable } from './table'; import { MySqlTable } from './table'; +import { type UniqueConstraint, UniqueConstraintBuilder } from './unique-constraint'; import type { MySqlView } from './view'; import { MySqlViewConfig } from './view'; -import { type UniqueConstraint, UniqueConstraintBuilder } from './unique-constraint'; -export function getTableConfig(table: AnyMySqlTable) { +export function getTableConfig(table: MySqlTable) { const columns = Object.values(table[MySqlTable.Symbol.Columns]); const indexes: Index[] = []; const checks: Check[] = []; diff --git a/drizzle-orm/src/pg-core/alias.ts b/drizzle-orm/src/pg-core/alias.ts index 5d0937d68..4564c2123 100644 --- a/drizzle-orm/src/pg-core/alias.ts +++ b/drizzle-orm/src/pg-core/alias.ts @@ -1,10 +1,10 @@ import { TableAliasProxyHandler } from '~/alias'; import type { BuildAliasTable } from './query-builders/select.types'; -import type { AnyPgTable } from './table'; +import type { PgTable } from './table'; import { type PgViewBase } from './view'; -export function alias( +export function alias( table: TTable, alias: TAlias, ): BuildAliasTable { diff --git a/drizzle-orm/src/pg-core/checks.ts b/drizzle-orm/src/pg-core/checks.ts index 3f40a5776..5801f69ac 100644 --- a/drizzle-orm/src/pg-core/checks.ts +++ b/drizzle-orm/src/pg-core/checks.ts @@ -1,6 +1,6 @@ import { entityKind } from '~/entity'; import type { SQL } from '~/sql'; -import type { AnyPgTable } from './table'; +import type { PgTable } from './table'; export class CheckBuilder { static readonly [entityKind]: string = 'PgCheckBuilder'; @@ -10,7 +10,7 @@ export class CheckBuilder { constructor(public name: string, public value: SQL) {} /** @internal */ - build(table: AnyPgTable): Check { + build(table: PgTable): Check { return new Check(table, this); } } @@ -21,7 +21,7 @@ export class Check { readonly name: string; readonly value: SQL; - constructor(public table: AnyPgTable, builder: CheckBuilder) { + constructor(public table: PgTable, builder: CheckBuilder) { this.name = builder.name; this.value = builder.value; } diff --git a/drizzle-orm/src/pg-core/columns/common.ts b/drizzle-orm/src/pg-core/columns/common.ts index 7dc5f8b71..3dd1e6923 100644 --- a/drizzle-orm/src/pg-core/columns/common.ts +++ b/drizzle-orm/src/pg-core/columns/common.ts @@ -18,7 +18,7 @@ import { uniqueKeyName } from '../unique-constraint'; import { PgArrayBuilder } from './array'; export interface ReferenceConfig { - ref: () => AnyPgColumn; + ref: () => PgColumn; actions: { onUpdate?: UpdateDeleteAction; onDelete?: UpdateDeleteAction; @@ -26,7 +26,9 @@ export interface ReferenceConfig { } export abstract class PgColumnBuilder< - T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig, + T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig & { + data: any; + }, TRuntimeConfig extends object = object, TTypeConfig extends object = object, TExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig, @@ -98,9 +100,7 @@ export abstract class PgColumnBuilder< ): PgColumn>; } -export type AnyPgColumnBuilder = PgColumnBuilder>; - -// To understand how to use `PgColumn` and `AnyPgColumn`, see `Column` and `AnyColumn` documentation. +// To understand how to use `PgColumn` and `PgColumn`, see `Column` and `AnyColumn` documentation. export abstract class PgColumn< T extends ColumnBaseConfig = ColumnBaseConfig, TRuntimeConfig extends object = {}, diff --git a/drizzle-orm/src/pg-core/db.ts b/drizzle-orm/src/pg-core/db.ts index 172cde90e..d315331dd 100644 --- a/drizzle-orm/src/pg-core/db.ts +++ b/drizzle-orm/src/pg-core/db.ts @@ -2,14 +2,14 @@ import { entityKind } from '~/entity'; import type { PgDialect } from '~/pg-core/dialect'; import { PgDelete, PgInsertBuilder, PgSelectBuilder, PgUpdateBuilder, QueryBuilder } from '~/pg-core/query-builders'; import type { PgSession, PgTransaction, PgTransactionConfig, QueryResultHKT, QueryResultKind } from '~/pg-core/session'; -import { type AnyPgTable } from '~/pg-core/table'; +import { type PgTable } from '~/pg-core/table'; import type { TypedQueryBuilder } from '~/query-builders/query-builder'; import { type ExtractTablesWithRelations, type RelationalSchemaConfig, type TablesRelationalConfig } from '~/relations'; import { type SQLWrapper } from '~/sql'; import { SelectionProxyHandler, WithSubquery } from '~/subquery'; import { type DrizzleTypeError } from '~/utils'; import { type ColumnsSelection } from '~/view'; -import { type AnyPgColumn } from './columns'; +import { type PgColumn } from './columns'; import { RelationalQueryBuilder } from './query-builders/query'; import { PgRefreshMaterializedView } from './query-builders/refresh-materialized-view'; import type { SelectedFields } from './query-builders/select.types'; @@ -51,7 +51,7 @@ export class PgDatabase< schema!.fullSchema, this._.schema, this._.tableNamesMap, - schema!.fullSchema[tableName] as AnyPgTable, + schema!.fullSchema[tableName] as PgTable, columns, dialect, session, @@ -115,13 +115,13 @@ export class PgDatabase< }); } - selectDistinctOn(on: (AnyPgColumn | SQLWrapper)[]): PgSelectBuilder; + selectDistinctOn(on: (PgColumn | SQLWrapper)[]): PgSelectBuilder; selectDistinctOn( - on: (AnyPgColumn | SQLWrapper)[], + on: (PgColumn | SQLWrapper)[], fields: TSelection, ): PgSelectBuilder; selectDistinctOn( - on: (AnyPgColumn | SQLWrapper)[], + on: (PgColumn | SQLWrapper)[], fields?: SelectedFields, ): PgSelectBuilder { return new PgSelectBuilder({ @@ -132,15 +132,15 @@ export class PgDatabase< }); } - update(table: TTable): PgUpdateBuilder { + update(table: TTable): PgUpdateBuilder { return new PgUpdateBuilder(table, this.session, this.dialect); } - insert(table: TTable): PgInsertBuilder { + insert(table: TTable): PgInsertBuilder { return new PgInsertBuilder(table, this.session, this.dialect); } - delete(table: TTable): PgDelete { + delete(table: TTable): PgDelete { return new PgDelete(table, this.session, this.dialect); } diff --git a/drizzle-orm/src/pg-core/dialect.ts b/drizzle-orm/src/pg-core/dialect.ts index 2f453eb81..d9081dd1c 100644 --- a/drizzle-orm/src/pg-core/dialect.ts +++ b/drizzle-orm/src/pg-core/dialect.ts @@ -3,11 +3,9 @@ import { Column } from '~/column'; import { entityKind, is } from '~/entity'; import { DrizzleError } from '~/errors'; import type { MigrationMeta } from '~/migrator'; -import type { AnyPgColumn } from '~/pg-core/columns'; import { PgColumn, PgDate, PgJson, PgJsonb, PgNumeric, PgTime, PgTimestamp, PgUUID } from '~/pg-core/columns'; import type { PgDeleteConfig, PgInsertConfig, PgUpdateConfig } from '~/pg-core/query-builders'; import type { Join, PgSelectConfig, SelectedFieldsOrdered } from '~/pg-core/query-builders/select.types'; -import type { AnyPgTable } from '~/pg-core/table'; import { PgTable } from '~/pg-core/table'; import { type BuildRelationalQueryResult, @@ -97,7 +95,7 @@ export class PgDialect { return sql`delete from ${table}${whereSql}${returningSql}`; } - buildUpdateSet(table: AnyPgTable, set: UpdateSet): SQL { + buildUpdateSet(table: PgTable, set: UpdateSet): SQL { const setEntries = Object.entries(set); const setSize = setEntries.length; @@ -205,7 +203,7 @@ export class PgDialect { distinct, }: PgSelectConfig, ): SQL { - const fieldsList = fieldsFlat ?? orderSelectedFields(fields); + const fieldsList = fieldsFlat ?? orderSelectedFields(fields); for (const f of fieldsList) { if ( is(f.field, Column) @@ -355,10 +353,17 @@ export class PgDialect { for (const [valueIndex, value] of values.entries()) { const valueList: (SQLChunk | SQL)[] = []; - for (const [fieldName] of colEntries) { + for (const [fieldName, col] of colEntries) { const colValue = value[fieldName]; if (colValue === undefined || (is(colValue, Param) && colValue.value === undefined)) { - valueList.push(sql`default`); + // eslint-disable-next-line unicorn/no-negated-condition + if (col.defaultFn !== undefined) { + const defaultFnResult = col.defaultFn(); + const defaultValue = is(defaultFnResult, SQL) ? defaultFnResult : sql.param(defaultFnResult, col); + valueList.push(defaultValue); + } else { + valueList.push(sql`default`); + } } else { valueList.push(colValue); } @@ -433,22 +438,22 @@ export class PgDialect { // fullSchema: Record; // schema: TablesRelationalConfig; // tableNamesMap: Record; - // table: AnyPgTable; + // table: PgTable; // tableConfig: TableRelationalConfig; // queryConfig: true | DBQueryConfig<'many', true>; // tableAlias: string; // isRoot?: boolean; // joinOn?: SQL; - // }): BuildRelationalQueryResult { + // }): BuildRelationalQueryResult { // // For { "": true }, return a table with selection of all columns // if (config === true) { // const selectionEntries = Object.entries(tableConfig.columns); - // const selection: BuildRelationalQueryResult['selection'] = selectionEntries.map(( + // const selection: BuildRelationalQueryResult['selection'] = selectionEntries.map(( // [key, value], // ) => ({ // dbKey: value.name, // tsKey: key, - // field: value as AnyPgColumn, + // field: value as PgColumn, // relationTableTsKey: undefined, // isJson: false, // selection: [], @@ -461,7 +466,7 @@ export class PgDialect { // }; // } - // // let selection: BuildRelationalQueryResult['selection'] = []; + // // let selection: BuildRelationalQueryResult['selection'] = []; // // let selectionForBuild = selection; // const aliasedColumns = Object.fromEntries( @@ -482,7 +487,7 @@ export class PgDialect { // } // where = and(joinOn, where); - // // const fieldsSelection: { tsKey: string; value: AnyPgColumn | SQL.Aliased; isExtra?: boolean }[] = []; + // // const fieldsSelection: { tsKey: string; value: PgColumn | SQL.Aliased; isExtra?: boolean }[] = []; // let joins: Join[] = []; // let selectedColumns: string[] = []; @@ -514,7 +519,7 @@ export class PgDialect { // } // // for (const field of selectedColumns) { - // // const column = tableConfig.columns[field]! as AnyPgColumn; + // // const column = tableConfig.columns[field]! as PgColumn; // // fieldsSelection.push({ tsKey: field, value: column }); // // } @@ -524,7 +529,7 @@ export class PgDialect { // relation: Relation; // }[] = []; - // // let selectedRelations: BuildRelationalQueryResult['selection'] = []; + // // let selectedRelations: BuildRelationalQueryResult['selection'] = []; // // Figure out which relations to select // if (config.with) { @@ -580,7 +585,7 @@ export class PgDialect { // } // const orderBy = orderByOrig.map((orderByValue) => { // if (is(orderByValue, Column)) { - // return aliasedTableColumn(orderByValue, tableAlias) as AnyPgColumn; + // return aliasedTableColumn(orderByValue, tableAlias) as PgColumn; // } // return mapColumnsInSQLToAlias(orderByValue, tableAlias); // }); @@ -604,7 +609,7 @@ export class PgDialect { // selection: selectedColumns.map((key) => ({ // dbKey: tableConfig.columns[key]!.name, // tsKey: key, - // field: tableConfig.columns[key] as AnyPgColumn, + // field: tableConfig.columns[key] as PgColumn, // relationTableTsKey: undefined, // isJson: false, // selection: [], @@ -644,7 +649,7 @@ export class PgDialect { // fullSchema, // schema, // tableNamesMap, - // table: fullSchema[relationTableTsName] as AnyPgTable, + // table: fullSchema[relationTableTsName] as PgTable, // tableConfig: schema[relationTableTsName]!, // queryConfig: selectedRelationConfigValue, // tableAlias: relationTableAlias, @@ -703,7 +708,7 @@ export class PgDialect { // fullSchema, // schema, // tableNamesMap, - // table: fullSchema[relationTableTsName] as AnyPgTable, + // table: fullSchema[relationTableTsName] as PgTable, // tableConfig: schema[relationTableTsName]!, // queryConfig: selectedRelationConfigValue, // tableAlias: relationTableAlias, @@ -742,7 +747,7 @@ export class PgDialect { // } // let distinct: PgSelectConfig['distinct']; - // let tableFrom: AnyPgTable | Subquery = table; + // let tableFrom: PgTable | Subquery = table; // // Process first Many relation - each one requires a nested subquery // const manyRelation = manyRelations[0]; @@ -754,7 +759,7 @@ export class PgDialect { // } = manyRelation; // distinct = { - // on: tableConfig.primaryKey.map((c) => aliasedTableColumn(c as AnyPgColumn, tableAlias)), + // on: tableConfig.primaryKey.map((c) => aliasedTableColumn(c as PgColumn, tableAlias)), // }; // const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation); @@ -774,7 +779,7 @@ export class PgDialect { // fullSchema, // schema, // tableNamesMap, - // table: fullSchema[relationTableTsName] as AnyPgTable, + // table: fullSchema[relationTableTsName] as PgTable, // tableConfig: schema[relationTableTsName]!, // queryConfig: selectedRelationQueryConfig, // tableAlias: relationTableAlias, @@ -800,7 +805,7 @@ export class PgDialect { // on: isLateralJoin ? sql`true` : joinOn, // table: isLateralJoin // ? new Subquery(builtRelationJoin.sql as SQL, {}, relationTableAlias) - // : aliasedTable(builtRelationJoin.sql as AnyPgTable, relationTableAlias), + // : aliasedTable(builtRelationJoin.sql as PgTable, relationTableAlias), // alias: relationTableAlias, // joinType: 'left', // lateral: isLateralJoin, @@ -872,13 +877,13 @@ export class PgDialect { // throw new DrizzleError(`No fields selected for table "${tableConfig.tsName}" ("${tableAlias}")`); // } - // let selection: BuildRelationalQueryResult['selection']; + // let selection: BuildRelationalQueryResult['selection']; // function prepareSelectedColumns() { // return selectedColumns.map((key) => ({ // dbKey: tableConfig.columns[key]!.name, // tsKey: key, - // field: tableConfig.columns[key] as AnyPgColumn, + // field: tableConfig.columns[key] as PgColumn, // relationTableTsKey: undefined, // isJson: false, // selection: [], @@ -963,14 +968,14 @@ export class PgDialect { fullSchema: Record; schema: TablesRelationalConfig; tableNamesMap: Record; - table: AnyPgTable; + table: PgTable; tableConfig: TableRelationalConfig; queryConfig: true | DBQueryConfig<'many', true>; tableAlias: string; nestedQueryRelation?: Relation; joinOn?: SQL; - }): BuildRelationalQueryResult { - let selection: BuildRelationalQueryResult['selection'] = []; + }): BuildRelationalQueryResult { + let selection: BuildRelationalQueryResult['selection'] = []; let limit, offset, orderBy: NonNullable = [], where; const joins: Join[] = []; @@ -998,7 +1003,7 @@ export class PgDialect { where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); } - const fieldsSelection: { tsKey: string; value: AnyPgColumn | SQL.Aliased }[] = []; + const fieldsSelection: { tsKey: string; value: PgColumn | SQL.Aliased }[] = []; let selectedColumns: string[] = []; // Figure out which columns to select @@ -1029,7 +1034,7 @@ export class PgDialect { } for (const field of selectedColumns) { - const column = tableConfig.columns[field]! as AnyPgColumn; + const column = tableConfig.columns[field]! as PgColumn; fieldsSelection.push({ tsKey: field, value: column }); } @@ -1082,7 +1087,7 @@ export class PgDialect { } orderBy = orderByOrig.map((orderByValue) => { if (is(orderByValue, Column)) { - return aliasedTableColumn(orderByValue, tableAlias) as AnyPgColumn; + return aliasedTableColumn(orderByValue, tableAlias) as PgColumn; } return mapColumnsInSQLToAlias(orderByValue, tableAlias); }); @@ -1114,7 +1119,7 @@ export class PgDialect { fullSchema, schema, tableNamesMap, - table: fullSchema[relationTableTsName] as AnyPgTable, + table: fullSchema[relationTableTsName] as PgTable, tableConfig: schema[relationTableTsName]!, queryConfig: is(relation, One) ? (selectedRelationConfigValue === true diff --git a/drizzle-orm/src/pg-core/expressions.ts b/drizzle-orm/src/pg-core/expressions.ts index 79b5351e1..4d64b1bd7 100644 --- a/drizzle-orm/src/pg-core/expressions.ts +++ b/drizzle-orm/src/pg-core/expressions.ts @@ -1,16 +1,16 @@ import { bindIfParam } from '~/expressions'; -import type { AnyPgColumn } from '~/pg-core/columns'; +import type { PgColumn } from '~/pg-core/columns'; import type { Placeholder, SQL, SQLChunk, SQLWrapper } from '~/sql'; import { sql } from '~/sql'; export * from '~/expressions'; -export function concat(column: AnyPgColumn | SQL.Aliased, value: string | Placeholder | SQLWrapper): SQL { +export function concat(column: PgColumn | SQL.Aliased, value: string | Placeholder | SQLWrapper): SQL { return sql`${column} || ${bindIfParam(value, column)}`; } export function substring( - column: AnyPgColumn | SQL.Aliased, + column: PgColumn | SQL.Aliased, { from, for: _for }: { from?: number | Placeholder | SQLWrapper; for?: number | Placeholder | SQLWrapper }, ): SQL { const chunks: SQLChunk[] = [sql`substring(`, column]; diff --git a/drizzle-orm/src/pg-core/foreign-keys.ts b/drizzle-orm/src/pg-core/foreign-keys.ts index aabfdea39..2473d5fec 100644 --- a/drizzle-orm/src/pg-core/foreign-keys.ts +++ b/drizzle-orm/src/pg-core/foreign-keys.ts @@ -1,12 +1,12 @@ import { entityKind } from '~/entity'; -import { type AnyPgColumn, type PgColumn } from './columns'; -import { type AnyPgTable, PgTable } from './table'; +import type { AnyPgColumn, PgColumn } from './columns'; +import { PgTable } from './table'; export type UpdateDeleteAction = 'cascade' | 'restrict' | 'no action' | 'set null' | 'set default'; export type Reference = () => { readonly columns: PgColumn[]; - readonly foreignTable: AnyPgTable; + readonly foreignTable: PgTable; readonly foreignColumns: PgColumn[]; }; @@ -34,7 +34,7 @@ export class ForeignKeyBuilder { ) { this.reference = () => { const { columns, foreignColumns } = config(); - return { columns, foreignTable: foreignColumns[0]!.table as AnyPgTable, foreignColumns }; + return { columns, foreignTable: foreignColumns[0]!.table as PgTable, foreignColumns }; }; if (actions) { this._onUpdate = actions.onUpdate; @@ -53,7 +53,7 @@ export class ForeignKeyBuilder { } /** @internal */ - build(table: AnyPgTable): ForeignKey { + build(table: PgTable): ForeignKey { return new ForeignKey(table, this); } } @@ -67,7 +67,7 @@ export class ForeignKey { readonly onUpdate: UpdateDeleteAction | undefined; readonly onDelete: UpdateDeleteAction | undefined; - constructor(readonly table: AnyPgTable, builder: ForeignKeyBuilder) { + constructor(readonly table: PgTable, builder: ForeignKeyBuilder) { this.reference = builder.reference; this.onUpdate = builder._onUpdate; this.onDelete = builder._onDelete; diff --git a/drizzle-orm/src/pg-core/indexes.ts b/drizzle-orm/src/pg-core/indexes.ts index e44951369..e2a980959 100644 --- a/drizzle-orm/src/pg-core/indexes.ts +++ b/drizzle-orm/src/pg-core/indexes.ts @@ -1,8 +1,8 @@ import type { SQL } from '~/sql'; import { entityKind } from '~/entity'; -import type { AnyPgColumn } from './columns'; -import type { AnyPgTable } from './table'; +import type { PgColumn } from './columns'; +import type { PgTable } from './table'; interface IndexConfig { name?: string; @@ -45,7 +45,7 @@ interface IndexConfig { where?: SQL; } -export type IndexColumn = AnyPgColumn; +export type IndexColumn = PgColumn; export class IndexBuilderOn { static readonly [entityKind]: string = 'PgIndexBuilderOn'; @@ -62,7 +62,7 @@ export class IndexBuilderOn { } export interface AnyIndexBuilder { - build(table: AnyPgTable): Index; + build(table: PgTable): Index; } // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -119,7 +119,7 @@ export class IndexBuilder implements AnyIndexBuilder { } /** @internal */ - build(table: AnyPgTable): Index { + build(table: PgTable): Index { return new Index(this.config, table); } } @@ -127,15 +127,15 @@ export class IndexBuilder implements AnyIndexBuilder { export class Index { static readonly [entityKind]: string = 'PgIndex'; - readonly config: IndexConfig & { table: AnyPgTable }; + readonly config: IndexConfig & { table: PgTable }; - constructor(config: IndexConfig, table: AnyPgTable) { + constructor(config: IndexConfig, table: PgTable) { this.config = { ...config, table }; } } -export type GetColumnsTableName = TColumns extends AnyPgColumn ? TColumns['_']['name'] - : TColumns extends AnyPgColumn[] ? TColumns[number]['_']['name'] +export type GetColumnsTableName = TColumns extends PgColumn ? TColumns['_']['name'] + : TColumns extends PgColumn[] ? TColumns[number]['_']['name'] : never; export function index(name?: string): IndexBuilderOn { diff --git a/drizzle-orm/src/pg-core/primary-keys.ts b/drizzle-orm/src/pg-core/primary-keys.ts index b2783537a..3b56a8a07 100644 --- a/drizzle-orm/src/pg-core/primary-keys.ts +++ b/drizzle-orm/src/pg-core/primary-keys.ts @@ -1,6 +1,6 @@ import { entityKind } from '~/entity'; -import type { AnyPgColumn } from './columns'; -import { type AnyPgTable, PgTable } from './table'; +import type { AnyPgColumn, PgColumn } from './columns'; +import { PgTable } from './table'; export function primaryKey< TTableName extends string, @@ -13,16 +13,16 @@ export class PrimaryKeyBuilder { static readonly [entityKind]: string = 'PgPrimaryKeyBuilder'; /** @internal */ - columns: AnyPgColumn[]; + columns: PgColumn[]; constructor( - columns: AnyPgColumn[], + columns: PgColumn[], ) { this.columns = columns; } /** @internal */ - build(table: AnyPgTable): PrimaryKey { + build(table: PgTable): PrimaryKey { return new PrimaryKey(table, this.columns); } } @@ -32,7 +32,7 @@ export class PrimaryKey { readonly columns: AnyPgColumn<{}>[]; - constructor(readonly table: AnyPgTable, columns: AnyPgColumn<{}>[]) { + constructor(readonly table: PgTable, columns: AnyPgColumn<{}>[]) { this.columns = columns; } diff --git a/drizzle-orm/src/pg-core/query-builders/delete.ts b/drizzle-orm/src/pg-core/query-builders/delete.ts index f52790a7d..e10636c1d 100644 --- a/drizzle-orm/src/pg-core/query-builders/delete.ts +++ b/drizzle-orm/src/pg-core/query-builders/delete.ts @@ -1,7 +1,7 @@ import { entityKind } from '~/entity'; import type { PgDialect } from '~/pg-core/dialect'; import type { PgSession, PreparedQuery, PreparedQueryConfig, QueryResultHKT, QueryResultKind } from '~/pg-core/session'; -import type { AnyPgTable } from '~/pg-core/table'; +import type { PgTable } from '~/pg-core/table'; import type { SelectResultFields } from '~/query-builders/select.types'; import { QueryPromise } from '~/query-promise'; import type { Query, SQL, SQLWrapper } from '~/sql'; @@ -12,20 +12,20 @@ import type { SelectedFieldsFlat, SelectedFieldsOrdered } from './select.types'; export interface PgDeleteConfig { where?: SQL | undefined; - table: AnyPgTable; + table: PgTable; returning?: SelectedFieldsOrdered; } // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface PgDelete< // eslint-disable-next-line @typescript-eslint/no-unused-vars - TTable extends AnyPgTable, + TTable extends PgTable, TQueryResult extends QueryResultHKT, TReturning extends Record | undefined = undefined, > extends QueryPromise : TReturning[]> {} export class PgDelete< - TTable extends AnyPgTable, + TTable extends PgTable, TQueryResult extends QueryResultHKT, TReturning extends Record | undefined = undefined, > extends QueryPromise : TReturning[]> diff --git a/drizzle-orm/src/pg-core/query-builders/insert.ts b/drizzle-orm/src/pg-core/query-builders/insert.ts index bf701e3eb..90dd6e984 100644 --- a/drizzle-orm/src/pg-core/query-builders/insert.ts +++ b/drizzle-orm/src/pg-core/query-builders/insert.ts @@ -2,7 +2,7 @@ import { entityKind, is } from '~/entity'; import type { PgDialect } from '~/pg-core/dialect'; import type { IndexColumn } from '~/pg-core/indexes'; import type { PgSession, PreparedQuery, PreparedQueryConfig, QueryResultHKT, QueryResultKind } from '~/pg-core/session'; -import type { AnyPgTable } from '~/pg-core/table'; +import type { PgTable } from '~/pg-core/table'; import type { SelectResultFields } from '~/query-builders/select.types'; import { QueryPromise } from '~/query-promise'; import type { Placeholder, Query, SQLWrapper } from '~/sql'; @@ -13,20 +13,20 @@ import { mapUpdateSet, orderSelectedFields } from '~/utils'; import type { SelectedFieldsFlat, SelectedFieldsOrdered } from './select.types'; import type { PgUpdateSetSource } from './update'; -export interface PgInsertConfig { +export interface PgInsertConfig { table: TTable; values: Record[]; onConflict?: SQL; returning?: SelectedFieldsOrdered; } -export type PgInsertValue = +export type PgInsertValue = & { [Key in keyof InferModel]: InferModel[Key] | SQL | Placeholder; } & {}; -export class PgInsertBuilder { +export class PgInsertBuilder { static readonly [entityKind]: string = 'PgInsertBuilder'; constructor( @@ -58,7 +58,7 @@ export class PgInsertBuilder | undefined = undefined, > extends @@ -67,7 +67,7 @@ export interface PgInsert< {} export class PgInsert< - TTable extends AnyPgTable, + TTable extends PgTable, TQueryResult extends QueryResultHKT, TReturning extends Record | undefined = undefined, > extends QueryPromise : TReturning[]> diff --git a/drizzle-orm/src/pg-core/query-builders/query-builder.ts b/drizzle-orm/src/pg-core/query-builders/query-builder.ts index f5cc1ddee..a63410d8c 100644 --- a/drizzle-orm/src/pg-core/query-builders/query-builder.ts +++ b/drizzle-orm/src/pg-core/query-builders/query-builder.ts @@ -4,7 +4,7 @@ import type { TypedQueryBuilder } from '~/query-builders/query-builder'; import { type SQLWrapper } from '~/sql'; import { SelectionProxyHandler, WithSubquery } from '~/subquery'; import { type ColumnsSelection } from '~/view'; -import { type AnyPgColumn } from '../columns'; +import { type PgColumn } from '../columns'; import type { WithSubqueryWithSelection } from '../subquery'; import { PgSelectBuilder } from './select'; import type { SelectedFields } from './select.types'; @@ -60,13 +60,13 @@ export class QueryBuilder { }); } - function selectDistinctOn(on: (AnyPgColumn | SQLWrapper)[]): PgSelectBuilder; + function selectDistinctOn(on: (PgColumn | SQLWrapper)[]): PgSelectBuilder; function selectDistinctOn( - on: (AnyPgColumn | SQLWrapper)[], + on: (PgColumn | SQLWrapper)[], fields: TSelection, ): PgSelectBuilder; function selectDistinctOn( - on: (AnyPgColumn | SQLWrapper)[], + on: (PgColumn | SQLWrapper)[], fields?: SelectedFields, ): PgSelectBuilder { return new PgSelectBuilder({ @@ -101,13 +101,13 @@ export class QueryBuilder { }); } - selectDistinctOn(on: (AnyPgColumn | SQLWrapper)[]): PgSelectBuilder; + selectDistinctOn(on: (PgColumn | SQLWrapper)[]): PgSelectBuilder; selectDistinctOn( - on: (AnyPgColumn | SQLWrapper)[], + on: (PgColumn | SQLWrapper)[], fields: TSelection, ): PgSelectBuilder; selectDistinctOn( - on: (AnyPgColumn | SQLWrapper)[], + on: (PgColumn | SQLWrapper)[], fields?: SelectedFields, ): PgSelectBuilder { return new PgSelectBuilder({ diff --git a/drizzle-orm/src/pg-core/query-builders/query.ts b/drizzle-orm/src/pg-core/query-builders/query.ts index 1615ef117..5a0f389d9 100644 --- a/drizzle-orm/src/pg-core/query-builders/query.ts +++ b/drizzle-orm/src/pg-core/query-builders/query.ts @@ -12,7 +12,7 @@ import { tracer } from '~/tracing'; import { type KnownKeysOnly } from '~/utils'; import type { PgDialect } from '../dialect'; import type { PgSession, PreparedQuery, PreparedQueryConfig } from '../session'; -import { type AnyPgTable } from '../table'; +import { type PgTable } from '../table'; export class RelationalQueryBuilder { static readonly [entityKind]: string = 'PgRelationalQueryBuilder'; @@ -21,7 +21,7 @@ export class RelationalQueryBuilder, private schema: TSchema, private tableNamesMap: Record, - private table: AnyPgTable, + private table: PgTable, private tableConfig: TableRelationalConfig, private dialect: PgDialect, private session: PgSession, @@ -69,7 +69,7 @@ export class PgRelationalQuery extends QueryPromise { private fullSchema: Record, private schema: TablesRelationalConfig, private tableNamesMap: Record, - private table: AnyPgTable, + private table: PgTable, private tableConfig: TableRelationalConfig, private dialect: PgDialect, private session: PgSession, diff --git a/drizzle-orm/src/pg-core/query-builders/select.ts b/drizzle-orm/src/pg-core/query-builders/select.ts index 07f0b37ee..f7acc19f1 100644 --- a/drizzle-orm/src/pg-core/query-builders/select.ts +++ b/drizzle-orm/src/pg-core/query-builders/select.ts @@ -1,9 +1,9 @@ import { entityKind, is } from '~/entity'; -import type { AnyPgColumn } from '~/pg-core/columns'; +import type { PgColumn } from '~/pg-core/columns'; import type { PgDialect } from '~/pg-core/dialect'; import type { PgSession, PreparedQuery, PreparedQueryConfig } from '~/pg-core/session'; import type { SubqueryWithSelection } from '~/pg-core/subquery'; -import type { AnyPgTable } from '~/pg-core/table'; +import type { PgTable } from '~/pg-core/table'; import { PgViewBase } from '~/pg-core/view'; import { TypedQueryBuilder } from '~/query-builders/query-builder'; import type { @@ -53,7 +53,7 @@ export class PgSelectBuilder< private dialect: PgDialect; private withList: Subquery[] = []; private distinct: boolean | { - on: (AnyPgColumn | SQLWrapper)[]; + on: (PgColumn | SQLWrapper)[]; } | undefined; constructor( @@ -63,7 +63,7 @@ export class PgSelectBuilder< dialect: PgDialect; withList?: Subquery[]; distinct?: boolean | { - on: (AnyPgColumn | SQLWrapper)[]; + on: (PgColumn | SQLWrapper)[]; }; }, ) { @@ -82,7 +82,7 @@ export class PgSelectBuilder< * * {@link https://www.postgresql.org/docs/current/sql-select.html#SQL-FROM|Postgres from documentation} */ - from( + from( source: TFrom, ): CreatePgSelectFromBuilderMode< TBuilderMode, @@ -107,7 +107,7 @@ export class PgSelectBuilder< } else if (is(source, SQL)) { fields = {}; } else { - fields = getTableColumns(source); + fields = getTableColumns(source); } return new PgSelect({ @@ -158,7 +158,7 @@ export abstract class PgSelectQueryBuilder< dialect: PgDialect; withList: Subquery[]; distinct: boolean | { - on: (AnyPgColumn | SQLWrapper)[]; + on: (PgColumn | SQLWrapper)[]; } | undefined; }, ) { @@ -183,7 +183,7 @@ export abstract class PgSelectQueryBuilder< joinType: TJoinType, ): JoinFn { return ( - table: AnyPgTable | Subquery | PgViewBase | SQL, + table: PgTable | Subquery | PgViewBase | SQL, on: ((aliases: TSelection) => SQL | undefined) | SQL | undefined, ) => { const baseTableName = this.tableName; @@ -352,12 +352,12 @@ export abstract class PgSelectQueryBuilder< * * {@link https://www.postgresql.org/docs/current/sql-select.html#SQL-GROUPBY|Postgres GROUP BY documentation} */ - groupBy(builder: (aliases: TSelection) => ValueOrArray): this; - groupBy(...columns: (AnyPgColumn | SQL | SQL.Aliased)[]): this; + groupBy(builder: (aliases: TSelection) => ValueOrArray): this; + groupBy(...columns: (PgColumn | SQL | SQL.Aliased)[]): this; groupBy( ...columns: - | [(aliases: TSelection) => ValueOrArray] - | (AnyPgColumn | SQL | SQL.Aliased)[] + | [(aliases: TSelection) => ValueOrArray] + | (PgColumn | SQL | SQL.Aliased)[] ) { if (typeof columns[0] === 'function') { const groupBy = columns[0]( @@ -368,7 +368,7 @@ export abstract class PgSelectQueryBuilder< ); this.config.groupBy = Array.isArray(groupBy) ? groupBy : [groupBy]; } else { - this.config.groupBy = columns as (AnyPgColumn | SQL | SQL.Aliased)[]; + this.config.groupBy = columns as (PgColumn | SQL | SQL.Aliased)[]; } return this; } @@ -388,12 +388,12 @@ export abstract class PgSelectQueryBuilder< * * {@link https://www.postgresql.org/docs/current/sql-select.html#SQL-ORDERBY|Postgres ORDER BY documentation} */ - orderBy(builder: (aliases: TSelection) => ValueOrArray): this; - orderBy(...columns: (AnyPgColumn | SQL | SQL.Aliased)[]): this; + orderBy(builder: (aliases: TSelection) => ValueOrArray): this; + orderBy(...columns: (PgColumn | SQL | SQL.Aliased)[]): this; orderBy( ...columns: - | [(aliases: TSelection) => ValueOrArray] - | (AnyPgColumn | SQL | SQL.Aliased)[] + | [(aliases: TSelection) => ValueOrArray] + | (PgColumn | SQL | SQL.Aliased)[] ) { if (typeof columns[0] === 'function') { const orderBy = columns[0]( @@ -404,7 +404,7 @@ export abstract class PgSelectQueryBuilder< ); this.config.orderBy = Array.isArray(orderBy) ? orderBy : [orderBy]; } else { - this.config.orderBy = columns as (AnyPgColumn | SQL | SQL.Aliased)[]; + this.config.orderBy = columns as (PgColumn | SQL | SQL.Aliased)[]; } return this; } @@ -508,7 +508,7 @@ export class PgSelect< throw new Error('Cannot execute a query on a query builder. Please use a database instance instead.'); } return tracer.startActiveSpan('drizzle.prepareQuery', () => { - const fieldsList = orderSelectedFields(config.fields); + const fieldsList = orderSelectedFields(config.fields); const query = session.prepareQuery< PreparedQueryConfig & { execute: SelectResult[] } >(dialect.sqlToQuery(this.getSQL()), fieldsList, name); diff --git a/drizzle-orm/src/pg-core/query-builders/update.ts b/drizzle-orm/src/pg-core/query-builders/update.ts index addd8db38..fc370e4ca 100644 --- a/drizzle-orm/src/pg-core/query-builders/update.ts +++ b/drizzle-orm/src/pg-core/query-builders/update.ts @@ -2,7 +2,7 @@ import type { GetColumnData } from '~/column'; import { entityKind } from '~/entity'; import type { PgDialect } from '~/pg-core/dialect'; import type { PgSession, PreparedQuery, PreparedQueryConfig, QueryResultHKT, QueryResultKind } from '~/pg-core/session'; -import type { AnyPgTable } from '~/pg-core/table'; +import type { PgTable } from '~/pg-core/table'; import type { SelectResultFields } from '~/query-builders/select.types'; import { QueryPromise } from '~/query-promise'; import type { Query, SQL, SQLWrapper } from '~/sql'; @@ -13,11 +13,11 @@ import type { SelectedFields, SelectedFieldsOrdered } from './select.types'; export interface PgUpdateConfig { where?: SQL | undefined; set: UpdateSet; - table: AnyPgTable; + table: PgTable; returning?: SelectedFieldsOrdered; } -export type PgUpdateSetSource = +export type PgUpdateSetSource = & { [Key in keyof TTable['_']['columns']]?: | GetColumnData @@ -25,7 +25,7 @@ export type PgUpdateSetSource = } & {}; -export class PgUpdateBuilder { +export class PgUpdateBuilder { static readonly [entityKind]: string = 'PgUpdateBuilder'; declare readonly _: { @@ -45,7 +45,7 @@ export class PgUpdateBuilder | undefined = undefined, > extends @@ -54,7 +54,7 @@ export interface PgUpdate< {} export class PgUpdate< - TTable extends AnyPgTable, + TTable extends PgTable, TQueryResult extends QueryResultHKT, TReturning extends Record | undefined = undefined, > extends QueryPromise : TReturning[]> diff --git a/drizzle-orm/src/pg-core/table.ts b/drizzle-orm/src/pg-core/table.ts index 4cf37f55b..c2ac4c8ed 100644 --- a/drizzle-orm/src/pg-core/table.ts +++ b/drizzle-orm/src/pg-core/table.ts @@ -2,7 +2,7 @@ import type { BuildColumns } from '~/column-builder'; import { entityKind } from '~/entity'; import { Table, type TableConfig as TableConfigBase, type UpdateTableConfig } from '~/table'; import type { CheckBuilder } from './checks'; -import type { AnyPgColumnBuilder, PgColumn, PgColumnBuilder } from './columns/common'; +import type { PgColumn, PgColumnBuilder } from './columns/common'; import type { ForeignKey, ForeignKeyBuilder } from './foreign-keys'; import type { AnyIndexBuilder } from './indexes'; import type { PrimaryKeyBuilder } from './primary-keys'; @@ -50,7 +50,7 @@ export type PgTableWithColumns = export function pgTableWithSchema< TTableName extends string, TSchemaName extends string | undefined, - TColumnsMap extends Record, + TColumnsMap extends Record, >( name: TTableName, columns: TColumnsMap, diff --git a/drizzle-orm/src/pg-core/unique-constraint.ts b/drizzle-orm/src/pg-core/unique-constraint.ts index 52fb649c5..640390da1 100644 --- a/drizzle-orm/src/pg-core/unique-constraint.ts +++ b/drizzle-orm/src/pg-core/unique-constraint.ts @@ -1,12 +1,12 @@ import { entityKind } from '~/entity'; import type { PgColumn } from './columns'; -import { type AnyPgTable, PgTable } from './table'; +import { PgTable } from './table'; export function unique(name?: string): UniqueOnConstraintBuilder { return new UniqueOnConstraintBuilder(name); } -export function uniqueKeyName(table: AnyPgTable, columns: string[]) { +export function uniqueKeyName(table: PgTable, columns: string[]) { return `${table[PgTable.Symbol.Name]}_${columns.join('_')}_unique`; } @@ -31,7 +31,7 @@ export class UniqueConstraintBuilder { } /** @internal */ - build(table: AnyPgTable): UniqueConstraint { + build(table: PgTable): UniqueConstraint { return new UniqueConstraint(table, this.columns, this.nullsNotDistinctConfig, this.name); } } @@ -60,7 +60,7 @@ export class UniqueConstraint { readonly name?: string; readonly nullsNotDistinct: boolean = false; - constructor(readonly table: AnyPgTable, columns: PgColumn[], nullsNotDistinct: boolean, name?: string) { + constructor(readonly table: PgTable, columns: PgColumn[], nullsNotDistinct: boolean, name?: string) { this.columns = columns; this.name = name ?? uniqueKeyName(this.table, this.columns.map((column) => column.name)); this.nullsNotDistinct = nullsNotDistinct; diff --git a/drizzle-orm/src/pg-core/utils.ts b/drizzle-orm/src/pg-core/utils.ts index ae0ef5a46..0997d3c90 100644 --- a/drizzle-orm/src/pg-core/utils.ts +++ b/drizzle-orm/src/pg-core/utils.ts @@ -1,17 +1,16 @@ import { is } from '~/entity'; -import type { AnyPgTable } from '~/pg-core/table'; import { PgTable } from '~/pg-core/table'; import { Table } from '~/table'; import { ViewBaseConfig } from '~/view'; import { type Check, CheckBuilder } from './checks'; -import { type AnyPgColumn } from './columns'; +import type { AnyPgColumn } from './columns'; import { type ForeignKey, ForeignKeyBuilder } from './foreign-keys'; import { type Index, IndexBuilder } from './indexes'; import { type PrimaryKey, PrimaryKeyBuilder } from './primary-keys'; import { type UniqueConstraint, UniqueConstraintBuilder } from './unique-constraint'; import { type PgMaterializedView, PgMaterializedViewConfig, type PgView, PgViewConfig } from './view'; -export function getTableConfig(table: TTable) { +export function getTableConfig(table: TTable) { const columns = Object.values(table[Table.Symbol.Columns]); const indexes: Index[] = []; const checks: Check[] = []; diff --git a/drizzle-orm/src/pg-core/view.ts b/drizzle-orm/src/pg-core/view.ts index 6c37ac204..a75f5756c 100644 --- a/drizzle-orm/src/pg-core/view.ts +++ b/drizzle-orm/src/pg-core/view.ts @@ -6,7 +6,7 @@ import type { SQL } from '~/sql'; import { SelectionProxyHandler } from '~/subquery'; import { getTableColumns } from '~/utils'; import { type ColumnsSelection, View } from '~/view'; -import type { AnyPgColumnBuilder, PgColumn, PgColumnBuilder } from './columns/common'; +import type { PgColumn, PgColumnBuilder } from './columns/common'; import { QueryBuilder } from './query-builders'; import type { SelectedFields } from './query-builders/select.types'; import { pgTable } from './table'; @@ -214,7 +214,7 @@ export class MaterializedViewBuilder export class ManualMaterializedViewBuilder< TName extends string = string, - TColumns extends Record = Record, + TColumns extends Record = Record, > extends MaterializedViewBuilderCore<{ name: TName; columns: TColumns }> { static readonly [entityKind]: string = 'PgManualMaterializedViewBuilder'; @@ -370,7 +370,7 @@ export type PgMaterializedViewWithSelection< /** @internal */ export function pgViewWithSchema( name: string, - selection: Record | undefined, + selection: Record | undefined, schema: string | undefined, ): ViewBuilder | ManualViewBuilder { if (selection) { @@ -382,7 +382,7 @@ export function pgViewWithSchema( /** @internal */ export function pgMaterializedViewWithSchema( name: string, - selection: Record | undefined, + selection: Record | undefined, schema: string | undefined, ): MaterializedViewBuilder | ManualMaterializedViewBuilder { if (selection) { @@ -392,22 +392,22 @@ export function pgMaterializedViewWithSchema( } export function pgView(name: TName): ViewBuilder; -export function pgView>( +export function pgView>( name: TName, columns: TColumns, ): ManualViewBuilder; -export function pgView(name: string, columns?: Record): ViewBuilder | ManualViewBuilder { +export function pgView(name: string, columns?: Record): ViewBuilder | ManualViewBuilder { return pgViewWithSchema(name, columns, undefined); } export function pgMaterializedView(name: TName): MaterializedViewBuilder; -export function pgMaterializedView>( +export function pgMaterializedView>( name: TName, columns: TColumns, ): ManualMaterializedViewBuilder; export function pgMaterializedView( name: string, - columns?: Record, + columns?: Record, ): MaterializedViewBuilder | ManualMaterializedViewBuilder { return pgMaterializedViewWithSchema(name, columns, undefined); } diff --git a/drizzle-orm/src/sql-js/session.ts b/drizzle-orm/src/sql-js/session.ts index 941a7c542..ad8c0f03e 100644 --- a/drizzle-orm/src/sql-js/session.ts +++ b/drizzle-orm/src/sql-js/session.ts @@ -183,7 +183,7 @@ export class PreparedQuery this.free(); } - if (!row) { + if (!row || (row.length === 0 && fields!.length > 0)) { return undefined; } diff --git a/drizzle-orm/src/sql/index.ts b/drizzle-orm/src/sql/index.ts index 4d32c5be9..2a2fb6a2a 100644 --- a/drizzle-orm/src/sql/index.ts +++ b/drizzle-orm/src/sql/index.ts @@ -400,6 +400,7 @@ export class Param implements } } +/** @deprecated Use `sql.param` instead. */ export function param( value: TData, encoder?: DriverValueEncoder, @@ -502,6 +503,17 @@ export namespace sql { export function identifier(value: string): Name { return new Name(value); } + + export function placeholder(name: TName): Placeholder { + return new Placeholder(name); + } + + export function param( + value: TData, + encoder?: DriverValueEncoder, + ): Param { + return new Param(value, encoder); + } } export namespace SQL { @@ -544,6 +556,7 @@ export class Placeholder implements } } +/** @deprecated Use `sql.placeholder` instead. */ export function placeholder(name: TName): Placeholder { return new Placeholder(name); } diff --git a/drizzle-orm/src/sqlite-core/checks.ts b/drizzle-orm/src/sqlite-core/checks.ts index f5674241a..21021ac7a 100644 --- a/drizzle-orm/src/sqlite-core/checks.ts +++ b/drizzle-orm/src/sqlite-core/checks.ts @@ -1,6 +1,6 @@ import { entityKind } from '~/entity'; import type { SQL } from '~/sql'; -import type { AnySQLiteTable } from './table'; +import type { SQLiteTable } from './table'; export class CheckBuilder { static readonly [entityKind]: string = 'SQLiteCheckBuilder'; @@ -9,7 +9,7 @@ export class CheckBuilder { constructor(public name: string, public value: SQL) {} - build(table: AnySQLiteTable): Check { + build(table: SQLiteTable): Check { return new Check(table, this); } } @@ -24,7 +24,7 @@ export class Check { readonly name: string; readonly value: SQL; - constructor(public table: AnySQLiteTable, builder: CheckBuilder) { + constructor(public table: SQLiteTable, builder: CheckBuilder) { this.name = builder.name; this.value = builder.value; } diff --git a/drizzle-orm/src/sqlite-core/columns/common.ts b/drizzle-orm/src/sqlite-core/columns/common.ts index 05df5474a..cdcd7f3a9 100644 --- a/drizzle-orm/src/sqlite-core/columns/common.ts +++ b/drizzle-orm/src/sqlite-core/columns/common.ts @@ -24,7 +24,9 @@ export interface ReferenceConfig { } export abstract class SQLiteColumnBuilder< - T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig, + T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig & { + data: any; + }, TRuntimeConfig extends object = object, TTypeConfig extends object = object, TExtraConfig extends ColumnBuilderExtraConfig = object, @@ -50,7 +52,7 @@ export abstract class SQLiteColumnBuilder< } /** @internal */ - buildForeignKeys(column: SQLiteColumn, table: AnySQLiteTable): ForeignKey[] { + buildForeignKeys(column: SQLiteColumn, table: SQLiteTable): ForeignKey[] { return this.foreignKeyConfigs.map(({ ref, actions }) => { return ((ref, actions) => { const builder = new ForeignKeyBuilder(() => { diff --git a/drizzle-orm/src/sqlite-core/db.ts b/drizzle-orm/src/sqlite-core/db.ts index d3e7154d2..3a3a431be 100644 --- a/drizzle-orm/src/sqlite-core/db.ts +++ b/drizzle-orm/src/sqlite-core/db.ts @@ -11,7 +11,7 @@ import { SQLiteUpdateBuilder, } from '~/sqlite-core/query-builders'; import type { Result, SQLiteSession, SQLiteTransaction, SQLiteTransactionConfig } from '~/sqlite-core/session'; -import type { AnySQLiteTable } from '~/sqlite-core/table'; +import type { SQLiteTable } from '~/sqlite-core/table'; import { SelectionProxyHandler, WithSubquery } from '~/subquery'; import { type DrizzleTypeError } from '~/utils'; import { type ColumnsSelection } from '~/view'; @@ -57,7 +57,7 @@ export class BaseSQLiteDatabase< schema!.fullSchema, this._.schema, this._.tableNamesMap, - schema!.fullSchema[tableName] as AnySQLiteTable, + schema!.fullSchema[tableName] as SQLiteTable, columns, dialect, session as SQLiteSession as any, @@ -139,15 +139,15 @@ export class BaseSQLiteDatabase< }); } - update(table: TTable): SQLiteUpdateBuilder { + update(table: TTable): SQLiteUpdateBuilder { return new SQLiteUpdateBuilder(table, this.session, this.dialect); } - insert(into: TTable): SQLiteInsertBuilder { + insert(into: TTable): SQLiteInsertBuilder { return new SQLiteInsertBuilder(into, this.session, this.dialect); } - delete(from: TTable): SQLiteDelete { + delete(from: TTable): SQLiteDelete { return new SQLiteDelete(from, this.session, this.dialect); } diff --git a/drizzle-orm/src/sqlite-core/dialect.ts b/drizzle-orm/src/sqlite-core/dialect.ts index 9c1c53bf4..e4c83ddc5 100644 --- a/drizzle-orm/src/sqlite-core/dialect.ts +++ b/drizzle-orm/src/sqlite-core/dialect.ts @@ -16,10 +16,9 @@ import { type TableRelationalConfig, type TablesRelationalConfig, } from '~/relations'; -import { and, eq, Param, param, type Query, SQL, sql, type SQLChunk } from '~/sql'; +import { and, eq, Param, type Query, SQL, sql, type SQLChunk } from '~/sql'; import { SQLiteColumn } from '~/sqlite-core/columns'; import type { SQLiteDeleteConfig, SQLiteInsertConfig, SQLiteUpdateConfig } from '~/sqlite-core/query-builders'; -import type { AnySQLiteTable } from '~/sqlite-core/table'; import { SQLiteTable } from '~/sqlite-core/table'; import { Subquery, SubqueryConfig } from '~/subquery'; import { getTableName, Table } from '~/table'; @@ -54,7 +53,7 @@ export abstract class SQLiteDialect { return sql`delete from ${table}${whereSql}${returningSql}`; } - buildUpdateSet(table: AnySQLiteTable, set: UpdateSet): SQL { + buildUpdateSet(table: SQLiteTable, set: UpdateSet): SQL { const setEntries = Object.entries(set); const setSize = setEntries.length; @@ -288,7 +287,11 @@ export abstract class SQLiteDialect { if (colValue === undefined || (is(colValue, Param) && colValue.value === undefined)) { let defaultValue; if (col.default !== null && col.default !== undefined) { - defaultValue = is(col.default, SQL) ? col.default : param(col.default, col); + defaultValue = is(col.default, SQL) ? col.default : sql.param(col.default, col); + // eslint-disable-next-line unicorn/no-negated-condition + } else if (col.defaultFn !== undefined) { + const defaultFnResult = col.defaultFn(); + defaultValue = is(defaultFnResult, SQL) ? defaultFnResult : sql.param(defaultFnResult, col); } else { defaultValue = sql`null`; } @@ -340,7 +343,7 @@ export abstract class SQLiteDialect { fullSchema: Record; schema: TablesRelationalConfig; tableNamesMap: Record; - table: AnySQLiteTable; + table: SQLiteTable; tableConfig: TableRelationalConfig; queryConfig: true | DBQueryConfig<'many', true>; tableAlias: string; @@ -492,7 +495,7 @@ export abstract class SQLiteDialect { fullSchema, schema, tableNamesMap, - table: fullSchema[relationTableTsName] as AnySQLiteTable, + table: fullSchema[relationTableTsName] as SQLiteTable, tableConfig: schema[relationTableTsName]!, queryConfig: is(relation, One) ? (selectedRelationConfigValue === true diff --git a/drizzle-orm/src/sqlite-core/foreign-keys.ts b/drizzle-orm/src/sqlite-core/foreign-keys.ts index 16b7db64e..9d13aab8a 100644 --- a/drizzle-orm/src/sqlite-core/foreign-keys.ts +++ b/drizzle-orm/src/sqlite-core/foreign-keys.ts @@ -1,13 +1,12 @@ import { entityKind } from '~/entity'; import type { AnySQLiteColumn, SQLiteColumn } from './columns'; -import type { AnySQLiteTable } from './table'; import { SQLiteTable } from './table'; export type UpdateDeleteAction = 'cascade' | 'restrict' | 'no action' | 'set null' | 'set default'; export type Reference = () => { readonly columns: SQLiteColumn[]; - readonly foreignTable: AnySQLiteTable; + readonly foreignTable: SQLiteTable; readonly foreignColumns: SQLiteColumn[]; }; @@ -40,7 +39,7 @@ export class ForeignKeyBuilder { ) { this.reference = () => { const { columns, foreignColumns } = config(); - return { columns, foreignTable: foreignColumns[0]!.table as AnySQLiteTable, foreignColumns }; + return { columns, foreignTable: foreignColumns[0]!.table as SQLiteTable, foreignColumns }; }; if (actions) { this._onUpdate = actions.onUpdate; @@ -59,7 +58,7 @@ export class ForeignKeyBuilder { } /** @internal */ - build(table: AnySQLiteTable): ForeignKey { + build(table: SQLiteTable): ForeignKey { return new ForeignKey(table, this); } } @@ -71,7 +70,7 @@ export class ForeignKey { readonly onUpdate: UpdateDeleteAction | undefined; readonly onDelete: UpdateDeleteAction | undefined; - constructor(readonly table: AnySQLiteTable, builder: ForeignKeyBuilder) { + constructor(readonly table: SQLiteTable, builder: ForeignKeyBuilder) { this.reference = builder.reference; this.onUpdate = builder._onUpdate; this.onDelete = builder._onDelete; diff --git a/drizzle-orm/src/sqlite-core/indexes.ts b/drizzle-orm/src/sqlite-core/indexes.ts index c0a40c130..9f30ec106 100644 --- a/drizzle-orm/src/sqlite-core/indexes.ts +++ b/drizzle-orm/src/sqlite-core/indexes.ts @@ -1,7 +1,7 @@ import { entityKind } from '~/entity'; import type { SQL } from '~/sql'; import { type SQLiteColumn } from './columns'; -import type { AnySQLiteTable } from './table'; +import type { SQLiteTable } from './table'; export interface IndexConfig { name: string; @@ -50,7 +50,7 @@ export class IndexBuilder { } /** @internal */ - build(table: AnySQLiteTable): Index { + build(table: SQLiteTable): Index { return new Index(this.config, table); } } @@ -62,9 +62,9 @@ export class Index { brand: 'SQLiteIndex'; }; - readonly config: IndexConfig & { table: AnySQLiteTable }; + readonly config: IndexConfig & { table: SQLiteTable }; - constructor(config: IndexConfig, table: AnySQLiteTable) { + constructor(config: IndexConfig, table: SQLiteTable) { this.config = { ...config, table }; } } diff --git a/drizzle-orm/src/sqlite-core/primary-keys.ts b/drizzle-orm/src/sqlite-core/primary-keys.ts index e217c7ed5..0f9c0e1b9 100644 --- a/drizzle-orm/src/sqlite-core/primary-keys.ts +++ b/drizzle-orm/src/sqlite-core/primary-keys.ts @@ -1,6 +1,5 @@ import { entityKind } from '~/entity'; import type { AnySQLiteColumn, SQLiteColumn } from './columns'; -import type { AnySQLiteTable } from './table'; import { SQLiteTable } from './table'; export function primaryKey< @@ -29,7 +28,7 @@ export class PrimaryKeyBuilder { } /** @internal */ - build(table: AnySQLiteTable): PrimaryKey { + build(table: SQLiteTable): PrimaryKey { return new PrimaryKey(table, this.columns); } } @@ -39,7 +38,7 @@ export class PrimaryKey { readonly columns: SQLiteColumn[]; - constructor(readonly table: AnySQLiteTable, columns: SQLiteColumn[]) { + constructor(readonly table: SQLiteTable, columns: SQLiteColumn[]) { this.columns = columns; } diff --git a/drizzle-orm/src/sqlite-core/query-builders/insert.ts b/drizzle-orm/src/sqlite-core/query-builders/insert.ts index d768f4f69..703bca65d 100644 --- a/drizzle-orm/src/sqlite-core/query-builders/insert.ts +++ b/drizzle-orm/src/sqlite-core/query-builders/insert.ts @@ -6,28 +6,27 @@ import { Param, SQL, sql } from '~/sql'; import type { SQLiteDialect } from '~/sqlite-core/dialect'; import type { IndexColumn } from '~/sqlite-core/indexes'; import type { PreparedQuery, SQLiteSession } from '~/sqlite-core/session'; -import type { AnySQLiteTable } from '~/sqlite-core/table'; import { SQLiteTable } from '~/sqlite-core/table'; import { type InferModel, Table } from '~/table'; import { type DrizzleTypeError, mapUpdateSet, orderSelectedFields, type Simplify } from '~/utils'; import type { SelectedFieldsFlat, SelectedFieldsOrdered } from './select.types'; import type { SQLiteUpdateSetSource } from './update'; -export interface SQLiteInsertConfig { +export interface SQLiteInsertConfig { table: TTable; values: Record[]; onConflict?: SQL; returning?: SelectedFieldsOrdered; } -export type SQLiteInsertValue = Simplify< +export type SQLiteInsertValue = Simplify< { [Key in keyof InferModel]: InferModel[Key] | SQL | Placeholder; } >; export class SQLiteInsertBuilder< - TTable extends AnySQLiteTable, + TTable extends SQLiteTable, TResultType extends 'sync' | 'async', TRunResult, > { @@ -71,7 +70,7 @@ export class SQLiteInsertBuilder< // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SQLiteInsert< // eslint-disable-next-line @typescript-eslint/no-unused-vars - TTable extends AnySQLiteTable, + TTable extends SQLiteTable, // eslint-disable-next-line @typescript-eslint/no-unused-vars TResultType extends 'sync' | 'async', // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -81,7 +80,7 @@ export interface SQLiteInsert< > extends SQLWrapper, QueryPromise {} export class SQLiteInsert< - TTable extends AnySQLiteTable, + TTable extends SQLiteTable, TResultType extends 'sync' | 'async', TRunResult, TReturning = undefined, diff --git a/drizzle-orm/src/sqlite-core/query-builders/select.ts b/drizzle-orm/src/sqlite-core/query-builders/select.ts index d7e6e9f8c..3f42b57ad 100644 --- a/drizzle-orm/src/sqlite-core/query-builders/select.ts +++ b/drizzle-orm/src/sqlite-core/query-builders/select.ts @@ -3,7 +3,7 @@ import { type Placeholder, type Query, SQL } from '~/sql'; import type { SQLiteColumn } from '~/sqlite-core/columns'; import type { SQLiteDialect } from '~/sqlite-core/dialect'; import type { PreparedQuery, SQLiteSession } from '~/sqlite-core/session'; -import type { AnySQLiteTable } from '~/sqlite-core/table'; +import type { SQLiteTable } from '~/sqlite-core/table'; import { Table } from '~/table'; import { TypedQueryBuilder } from '~/query-builders/query-builder'; @@ -78,7 +78,7 @@ export class SQLiteSelectBuilder< this.distinct = config.distinct; } - from( + from( source: TFrom, ): CreateSQLiteSelectFromBuilderMode< TBuilderMode, @@ -105,7 +105,7 @@ export class SQLiteSelectBuilder< } else if (is(source, SQL)) { fields = {}; } else { - fields = getTableColumns(source); + fields = getTableColumns(source); } return new SQLiteSelect({ @@ -181,7 +181,7 @@ export abstract class SQLiteSelectQueryBuilder< joinType: TJoinType, ): JoinFn { return ( - table: AnySQLiteTable | Subquery | SQLiteViewBase | SQL, + table: SQLiteTable | Subquery | SQLiteViewBase | SQL, on: ((aliases: TSelection) => SQL | undefined) | SQL | undefined, ) => { const baseTableName = this.tableName; diff --git a/drizzle-orm/src/sqlite-core/query-builders/update.ts b/drizzle-orm/src/sqlite-core/query-builders/update.ts index 32a083a9a..88ad31a2f 100644 --- a/drizzle-orm/src/sqlite-core/query-builders/update.ts +++ b/drizzle-orm/src/sqlite-core/query-builders/update.ts @@ -5,7 +5,6 @@ import { QueryPromise } from '~/query-promise'; import type { Query, SQL, SQLWrapper } from '~/sql'; import type { SQLiteDialect } from '~/sqlite-core/dialect'; import type { PreparedQuery, SQLiteSession } from '~/sqlite-core/session'; -import type { AnySQLiteTable } from '~/sqlite-core/table'; import { SQLiteTable } from '~/sqlite-core/table'; import type { InferModel } from '~/table'; import { type DrizzleTypeError, mapUpdateSet, orderSelectedFields, type UpdateSet } from '~/utils'; @@ -14,11 +13,11 @@ import type { SelectedFields, SelectedFieldsOrdered } from './select.types'; export interface SQLiteUpdateConfig { where?: SQL | undefined; set: UpdateSet; - table: AnySQLiteTable; + table: SQLiteTable; returning?: SelectedFieldsOrdered; } -export type SQLiteUpdateSetSource = +export type SQLiteUpdateSetSource = & { [Key in keyof TTable['_']['columns']]?: | GetColumnData @@ -27,7 +26,7 @@ export type SQLiteUpdateSetSource = & {}; export class SQLiteUpdateBuilder< - TTable extends AnySQLiteTable, + TTable extends SQLiteTable, TResultType extends 'sync' | 'async', TRunResult, > { @@ -51,7 +50,7 @@ export class SQLiteUpdateBuilder< // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SQLiteUpdate< // eslint-disable-next-line @typescript-eslint/no-unused-vars - TTable extends AnySQLiteTable, + TTable extends SQLiteTable, // eslint-disable-next-line @typescript-eslint/no-unused-vars TResultType extends 'sync' | 'async', // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -61,7 +60,7 @@ export interface SQLiteUpdate< > extends SQLWrapper, QueryPromise {} export class SQLiteUpdate< - TTable extends AnySQLiteTable, + TTable extends SQLiteTable, TResultType extends 'sync' | 'async', TRunResult, TReturning = undefined, diff --git a/drizzle-orm/src/sqlite-core/utils.ts b/drizzle-orm/src/sqlite-core/utils.ts index d47af2a44..8756a4443 100644 --- a/drizzle-orm/src/sqlite-core/utils.ts +++ b/drizzle-orm/src/sqlite-core/utils.ts @@ -9,12 +9,11 @@ import type { Index } from './indexes'; import { IndexBuilder } from './indexes'; import type { PrimaryKey } from './primary-keys'; import { PrimaryKeyBuilder } from './primary-keys'; -import type { AnySQLiteTable } from './table'; import { SQLiteTable } from './table'; -import { type SQLiteView, SQLiteViewConfig } from './view'; import { type UniqueConstraint, UniqueConstraintBuilder } from './unique-constraint'; +import { type SQLiteView, SQLiteViewConfig } from './view'; -export function getTableConfig(table: TTable) { +export function getTableConfig(table: TTable) { const columns = Object.values(table[SQLiteTable.Symbol.Columns]); const indexes: Index[] = []; const checks: Check[] = []; diff --git a/drizzle-orm/src/sqlite-proxy/session.ts b/drizzle-orm/src/sqlite-proxy/session.ts index b040f9cc2..bb488ca83 100644 --- a/drizzle-orm/src/sqlite-proxy/session.ts +++ b/drizzle-orm/src/sqlite-proxy/session.ts @@ -134,7 +134,7 @@ export class PreparedQuery if (fields) { if (clientResult.rows === undefined) { - return mapResultRow(fields, [], joinsNotNullableMap); + return undefined; } return mapResultRow(fields, clientResult.rows, joinsNotNullableMap); } diff --git a/drizzle-orm/src/table.ts b/drizzle-orm/src/table.ts index 1fbc6f7f8..6919ee82a 100644 --- a/drizzle-orm/src/table.ts +++ b/drizzle-orm/src/table.ts @@ -47,12 +47,13 @@ export class Table implements SQLWrapper { readonly name: T['name']; readonly schema: T['schema']; readonly columns: T['columns']; - readonly model: { - select: InferModel>; - insert: InferModel, 'insert'>; - }; + readonly inferSelect: InferSelectModel>; + readonly inferInsert: InferInsertModel>; }; + declare readonly $inferSelect: InferSelectModel>; + declare readonly $inferInsert: InferInsertModel>; + /** @internal */ static readonly Symbol = { Name: TableName as typeof TableName, @@ -153,8 +154,20 @@ export type InferModelFromColumns< ]: GetColumnData; }; +/** @deprecated Use one of the alternatives: {@link InferSelectModel} / {@link InferInsertModel}, or `table._.inferSelect` / `table._.inferInsert` + */ export type InferModel< TTable extends Table, TInferMode extends 'select' | 'insert' = 'select', TConfig extends { dbColumnNames: boolean } = { dbColumnNames: false }, > = InferModelFromColumns; + +export type InferSelectModel< + TTable extends Table, + TConfig extends { dbColumnNames: boolean } = { dbColumnNames: false }, +> = InferModelFromColumns; + +export type InferInsertModel< + TTable extends Table, + TConfig extends { dbColumnNames: boolean } = { dbColumnNames: false }, +> = InferModelFromColumns; diff --git a/drizzle-orm/tsconfig.cjs.json b/drizzle-orm/tsconfig.cjs.json index 3986a7737..72bb4f1c4 100644 --- a/drizzle-orm/tsconfig.cjs.json +++ b/drizzle-orm/tsconfig.cjs.json @@ -3,8 +3,7 @@ "compilerOptions": { "target": "es2020", "module": "es2020", - "rootDir": "src", - "incremental": true + "rootDir": "src" }, "include": ["src"] } diff --git a/drizzle-orm/tsconfig.dts.json b/drizzle-orm/tsconfig.dts.json new file mode 100644 index 000000000..3377281ba --- /dev/null +++ b/drizzle-orm/tsconfig.dts.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "src" + }, + "include": ["src"] +} diff --git a/drizzle-orm/tsconfig.esm.json b/drizzle-orm/tsconfig.esm.json index 153a57f69..3377281ba 100644 --- a/drizzle-orm/tsconfig.esm.json +++ b/drizzle-orm/tsconfig.esm.json @@ -1,8 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "rootDir": "src", - "incremental": true + "rootDir": "src" }, "include": ["src"] } diff --git a/drizzle-orm/type-tests/knex/index.ts b/drizzle-orm/type-tests/knex/index.ts index 01406e054..8deacac0c 100644 --- a/drizzle-orm/type-tests/knex/index.ts +++ b/drizzle-orm/type-tests/knex/index.ts @@ -19,5 +19,5 @@ const db = Knex({}); { const res = db('test').select(); - Expect, typeof test['_']['model']['select'][]>>; + Expect, typeof test.$inferSelect[]>>; } diff --git a/drizzle-orm/type-tests/mysql/tables.ts b/drizzle-orm/type-tests/mysql/tables.ts index c1c2b0e39..22d00cb12 100644 --- a/drizzle-orm/type-tests/mysql/tables.ts +++ b/drizzle-orm/type-tests/mysql/tables.ts @@ -539,3 +539,26 @@ Expect< await db.select().from(newYorkers).leftJoin(newYorkers, eq(newYorkers.userId, newYorkers.userId)); } + +{ + const test = mysqlTable('test', { + id: text('id').$defaultFn(() => crypto.randomUUID()).primaryKey(), + }); + + Expect< + Equal<{ + id?: string; + }, typeof test.$inferInsert> + >; +} + +{ + mysqlTable('test', { + id: int('id').$default(() => 1), + id2: int('id').$defaultFn(() => 1), + // @ts-expect-error - should be number + id3: int('id').$default(() => '1'), + // @ts-expect-error - should be number + id4: int('id').$defaultFn(() => '1'), + }); +} diff --git a/drizzle-orm/type-tests/pg/tables.ts b/drizzle-orm/type-tests/pg/tables.ts index 37e7050c2..dcaa60e4a 100644 --- a/drizzle-orm/type-tests/pg/tables.ts +++ b/drizzle-orm/type-tests/pg/tables.ts @@ -1,3 +1,4 @@ +import crypto from 'node:crypto'; import type { Equal } from 'type-tests/utils'; import { Expect } from 'type-tests/utils'; import { z } from 'zod'; @@ -5,24 +6,33 @@ import { eq, gt } from '~/expressions'; import { bigint, bigserial, + boolean, char, check, cidr, customType, + date, decimal, + doublePrecision, foreignKey, index, inet, integer, + json, + jsonb, macaddr, macaddr8, + numeric, type PgColumn, pgEnum, pgTable, type PgTableWithColumns, primaryKey, + real, serial, + smallint, text, + time, timestamp, uniqueIndex, uuid, @@ -36,7 +46,7 @@ import { type PgViewWithSelection, } from '~/pg-core/view'; import { sql } from '~/sql'; -import type { InferModel } from '~/table'; +import type { InferInsertModel, InferModel, InferSelectModel } from '~/table'; import { db } from './db'; export const myEnum = pgEnum('my_enum', ['a', 'b', 'c']); @@ -81,6 +91,11 @@ export const users = pgTable( }), ); +Expect, typeof users['$inferSelect']>>; +Expect, typeof users['_']['inferSelect']>>; +Expect, typeof users['$inferInsert']>>; +Expect, typeof users['_']['inferInsert']>>; + export const cities = pgTable('cities_table', { id: serial('id').primaryKey(), name: text('name').notNull(), @@ -974,3 +989,70 @@ await db.refreshMaterializedView(newYorkers2).withNoData().concurrently(); Expect>; Expect>; } + +{ + const test = pgTable('test', { + id: text('id').$defaultFn(() => crypto.randomUUID()).primaryKey(), + }); + + Expect< + Equal<{ + id?: string; + }, typeof test.$inferInsert> + >; +} + +{ + pgTable('test', { + id: integer('id').$default(() => 1), + id2: integer('id').$defaultFn(() => 1), + // @ts-expect-error - should be number + id3: integer('id').$default(() => '1'), + // @ts-expect-error - should be number + id4: integer('id').$defaultFn(() => '1'), + }); +} + +{ + pgTable('all_columns', { + sm: smallint('smallint'), + smdef: smallint('smallint_def').default(10), + int: integer('integer'), + intdef: integer('integer_def').default(10), + numeric: numeric('numeric'), + numeric2: numeric('numeric2', { precision: 5 }), + numeric3: numeric('numeric3', { scale: 2 }), + numeric4: numeric('numeric4', { precision: 5, scale: 2 }), + numericdef: numeric('numeridef').default('100'), + bigint: bigint('bigint', { mode: 'number' }), + bigintdef: bigint('bigintdef', { mode: 'number' }).default(100), + bool: boolean('boolean'), + booldef: boolean('boolean_def').default(true), + text: text('text'), + textdef: text('textdef').default('text'), + varchar: varchar('varchar'), + varchardef: varchar('varchardef').default('text'), + serial: serial('serial'), + bigserial: bigserial('bigserial', { mode: 'number' }), + decimal: decimal('decimal', { precision: 100, scale: 2 }), + decimaldef: decimal('decimaldef', { precision: 100, scale: 2 }).default('100.0'), + doublePrecision: doublePrecision('doublePrecision'), + doublePrecisiondef: doublePrecision('doublePrecisiondef').default(100), + real: real('real'), + realdef: real('realdef').default(100), + json: json('json').$type<{ attr: string }>(), + jsondef: json('jsondef').$type<{ attr: string }>().default({ attr: 'value' }), + jsonb: jsonb('jsonb').$type<{ attr: string }>(), + jsonbdef: jsonb('jsonbdef').$type<{ attr: string }>().default({ attr: 'value' }), + time: time('time'), + time2: time('time2', { precision: 6, withTimezone: true }), + timedefnow: time('timedefnow').defaultNow(), + timestamp: timestamp('timestamp'), + timestamp2: timestamp('timestamp2', { precision: 6, withTimezone: true }), + timestamp3: timestamp('timestamp3', { withTimezone: true }), + timestamp4: timestamp('timestamp4', { precision: 4 }), + timestampdef: timestamp('timestampdef').defaultNow(), + date: date('date', { mode: 'date' }), + datedef: date('datedef').defaultNow(), + }); +} diff --git a/drizzle-orm/type-tests/sqlite/tables.ts b/drizzle-orm/type-tests/sqlite/tables.ts index 9a670dade..3db702b7c 100644 --- a/drizzle-orm/type-tests/sqlite/tables.ts +++ b/drizzle-orm/type-tests/sqlite/tables.ts @@ -371,6 +371,29 @@ Expect< Expect< Equal<{ col1: Id; - }, InferModel> + }, typeof table.$inferSelect> >; } + +{ + const test = sqliteTable('test', { + id: text('id').$defaultFn(() => crypto.randomUUID()).primaryKey(), + }); + + Expect< + Equal<{ + id?: string; + }, typeof test.$inferInsert> + >; +} + +{ + sqliteTable('test', { + id: integer('id').$default(() => 1), + id2: integer('id').$defaultFn(() => 1), + // @ts-expect-error - should be number + id3: integer('id').$default(() => '1'), + // @ts-expect-error - should be number + id4: integer('id').$defaultFn(() => '1'), + }); +} diff --git a/drizzle-typebox/tsconfig.build.json b/drizzle-typebox/tsconfig.build.json index 153a57f69..3377281ba 100644 --- a/drizzle-typebox/tsconfig.build.json +++ b/drizzle-typebox/tsconfig.build.json @@ -1,8 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "rootDir": "src", - "incremental": true + "rootDir": "src" }, "include": ["src"] } diff --git a/drizzle-valibot/tsconfig.build.json b/drizzle-valibot/tsconfig.build.json index 153a57f69..3377281ba 100644 --- a/drizzle-valibot/tsconfig.build.json +++ b/drizzle-valibot/tsconfig.build.json @@ -1,8 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "rootDir": "src", - "incremental": true + "rootDir": "src" }, "include": ["src"] } diff --git a/drizzle-zod/tsconfig.build.json b/drizzle-zod/tsconfig.build.json index 153a57f69..3377281ba 100644 --- a/drizzle-zod/tsconfig.build.json +++ b/drizzle-zod/tsconfig.build.json @@ -1,8 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "rootDir": "src", - "incremental": true + "rootDir": "src" }, "include": ["src"] } diff --git a/integration-tests/tests/awsdatapi.alltypes.test.ts b/integration-tests/tests/awsdatapi.alltypes.test.ts index 4179cefc5..585692cdd 100644 --- a/integration-tests/tests/awsdatapi.alltypes.test.ts +++ b/integration-tests/tests/awsdatapi.alltypes.test.ts @@ -76,7 +76,7 @@ export const allColumns = pgTable('all_columns', { interface Context { db: AwsDataApiPgDatabase; - row: typeof allColumns['_']['model']['select']; + row: typeof allColumns.$inferSelect; } const test = anyTest as TestFn; diff --git a/integration-tests/tests/better-sqlite.test.ts b/integration-tests/tests/better-sqlite.test.ts index be06341a8..9c431958c 100644 --- a/integration-tests/tests/better-sqlite.test.ts +++ b/integration-tests/tests/better-sqlite.test.ts @@ -1911,6 +1911,8 @@ test.serial('async api - CRUD', async (t) => { const res2 = await db.select().from(users); t.deepEqual(res2, []); + + db.run(sql`drop table ${users}`); }); test.serial('async api - insert + select w/ prepare + async execute', async (t) => { @@ -1948,6 +1950,8 @@ test.serial('async api - insert + select w/ prepare + async execute', async (t) const res2 = await selectStmt.execute(); t.deepEqual(res2, []); + + db.run(sql`drop table ${users}`); }); test.serial('async api - insert + select w/ prepare + sync execute', (t) => { @@ -1985,4 +1989,27 @@ test.serial('async api - insert + select w/ prepare + sync execute', (t) => { const res2 = selectStmt.execute().sync(); t.deepEqual(res2, []); + + db.run(sql`drop table ${users}`); +}); + +test.serial('select + .get() for empty result', (t) => { + const { db } = t.context; + + const users = sqliteTable('users', { + id: integer('id').primaryKey(), + name: text('name'), + }); + + db.run(sql`drop table if exists ${users}`); + + db.run( + sql`create table ${users} (id integer primary key, name text)`, + ); + + const res = db.select().from(users).where(eq(users.id, 1)).get(); + + t.is(res, undefined); + + db.run(sql`drop table ${users}`); }); diff --git a/integration-tests/tests/libsql.test.ts b/integration-tests/tests/libsql.test.ts index c76fa4e6e..6da1473f7 100644 --- a/integration-tests/tests/libsql.test.ts +++ b/integration-tests/tests/libsql.test.ts @@ -72,9 +72,9 @@ const courseCategoriesTable = sqliteTable('course_categories', { const orders = sqliteTable('orders', { id: integer('id').primaryKey(), region: text('region').notNull(), - product: text('product').notNull(), + product: text('product').notNull().$default(()=>'random_string'), amount: integer('amount').notNull(), - quantity: integer('quantity').notNull(), + quantity: integer('quantity').notNull() }); const usersMigratorTable = sqliteTable('users12', { @@ -310,6 +310,21 @@ test.serial('insert returning sql', async (t) => { t.deepEqual(users, [{ name: 'JOHN' }]); }); +test.serial('$default function', async (t) => { + const { db } = t.context; + + await db.insert(orders).values({ id: 1, region: 'Ukraine', amount: 1, quantity: 1 }); + const selectedOrder = await db.select().from(orders); + + t.deepEqual(selectedOrder, [{ + id: 1, + amount: 1, + quantity: 1, + region: 'Ukraine', + product: 'random_string', + }]); +}); + test.serial('delete returning sql', async (t) => { const { db } = t.context; @@ -1826,6 +1841,8 @@ test.serial('async api - CRUD', async (t) => { const res2 = await db.select().from(users); t.deepEqual(res2, []); + + await db.run(sql`drop table ${users}`); }); test.serial('async api - insert + select w/ prepare + async execute', async (t) => { @@ -1863,6 +1880,8 @@ test.serial('async api - insert + select w/ prepare + async execute', async (t) const res2 = await selectStmt.execute(); t.deepEqual(res2, []); + + await db.run(sql`drop table ${users}`); }); test.serial('async api - insert + select w/ prepare + sync execute', async (t) => { @@ -1900,4 +1919,27 @@ test.serial('async api - insert + select w/ prepare + sync execute', async (t) = const res2 = await selectStmt.execute(); t.deepEqual(res2, []); + + await db.run(sql`drop table ${users}`); +}); + +test.serial('select + .get() for empty result', async (t) => { + const { db } = t.context; + + const users = sqliteTable('users', { + id: integer('id').primaryKey(), + name: text('name'), + }); + + db.run(sql`drop table if exists ${users}`); + + db.run( + sql`create table ${users} (id integer primary key, name text)`, + ); + + const res = await db.select().from(users).where(eq(users.id, 1)).get(); + + t.is(res, undefined); + + await db.run(sql`drop table ${users}`); }); diff --git a/integration-tests/tests/mysql-schema.test.ts b/integration-tests/tests/mysql-schema.test.ts index 551b42be6..08a62bd16 100644 --- a/integration-tests/tests/mysql-schema.test.ts +++ b/integration-tests/tests/mysql-schema.test.ts @@ -471,7 +471,7 @@ test.serial('build query insert with onDuplicate', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into `mySchema`.`userstest` (`name`, `jsonb`) values (?, ?) on duplicate key update `name` = ?', + sql: 'insert into `mySchema`.`userstest` (`id`, `name`, `verified`, `jsonb`, `created_at`) values (default, ?, default, ?, default) on duplicate key update `name` = ?', params: ['John', '["foo","bar"]', 'John1'], }); }); diff --git a/integration-tests/tests/mysql.custom.test.ts b/integration-tests/tests/mysql.custom.test.ts index 0ce23dd81..e0ad8df25 100644 --- a/integration-tests/tests/mysql.custom.test.ts +++ b/integration-tests/tests/mysql.custom.test.ts @@ -486,7 +486,7 @@ test.serial('build query insert with onDuplicate', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into `userstest` (`name`, `jsonb`) values (?, ?) on duplicate key update `name` = ?', + sql: 'insert into `userstest` (`id`, `name`, `verified`, `jsonb`, `created_at`) values (default, ?, default, ?, default) on duplicate key update `name` = ?', params: ['John', '["foo","bar"]', 'John1'], }); }); diff --git a/integration-tests/tests/mysql.prefixed.test.ts b/integration-tests/tests/mysql.prefixed.test.ts index cc8fe6c67..1987c2d30 100644 --- a/integration-tests/tests/mysql.prefixed.test.ts +++ b/integration-tests/tests/mysql.prefixed.test.ts @@ -470,7 +470,7 @@ test.serial('build query insert with onDuplicate', async (t) => { t.deepEqual(query, { sql: `insert into \`${ getTableName(usersTable) - }\` (\`name\`, \`jsonb\`) values (?, ?) on duplicate key update \`name\` = ?`, + }\` (\`id\`, \`name\`, \`verified\`, \`jsonb\`, \`created_at\`) values (default, ?, default, ?, default) on duplicate key update \`name\` = ?`, params: ['John', '["foo","bar"]', 'John1'], }); }); @@ -698,7 +698,7 @@ test.serial('prepared statement with placeholder in .where', async (t) => { t.deepEqual(result, [{ id: 1, name: 'John' }]); }); -test.serial.only('migrator', async (t) => { +test.serial('migrator', async (t) => { const { db } = t.context; const usersMigratorTable = mysqlTableRaw('users12', { diff --git a/integration-tests/tests/mysql.test.ts b/integration-tests/tests/mysql.test.ts index 79bf73984..245bc425d 100644 --- a/integration-tests/tests/mysql.test.ts +++ b/integration-tests/tests/mysql.test.ts @@ -91,7 +91,7 @@ const courseCategoriesTable = mysqlTable('course_categories', { const orders = mysqlTable('orders', { id: serial('id').primaryKey(), region: text('region').notNull(), - product: text('product').notNull(), + product: text('product').notNull().$default(() => 'random_string'), amount: int('amount').notNull(), quantity: int('quantity').notNull(), }); @@ -251,11 +251,11 @@ test.serial('table configs: unique in column', async (t) => { t.assert(columnName?.isUnique); const columnState = tableConfig.columns.find((it) => it.name === 'state'); - t.assert(columnState?.uniqueName === "custom"); + t.assert(columnState?.uniqueName === 'custom'); t.assert(columnState?.isUnique); const columnField = tableConfig.columns.find((it) => it.name === 'field'); - t.assert(columnField?.uniqueName === "custom_field"); + t.assert(columnField?.uniqueName === 'custom_field'); t.assert(columnField?.isUnique); }); @@ -491,6 +491,64 @@ test.serial('select with group by as sql', async (t) => { t.deepEqual(result, [{ name: 'John' }, { name: 'Jane' }]); }); +test.serial('$default function', async (t) => { + const { db } = t.context; + + await db.execute(sql`drop table if exists \`orders\``); + await db.execute( + sql` + create table \`orders\` ( + \`id\` serial primary key, + \`region\` text not null, + \`product\` text not null, + \`amount\` int not null, + \`quantity\` int not null + ) + `, + ); + + await db.insert(orders).values({ id: 1, region: 'Ukraine', amount: 1, quantity: 1 }); + const selectedOrder = await db.select().from(orders); + + t.deepEqual(selectedOrder, [{ + id: 1, + amount: 1, + quantity: 1, + region: 'Ukraine', + product: 'random_string', + }]); +}); + +test.serial('$default with empty array', async (t) => { + const { db } = t.context; + + await db.execute(sql`drop table if exists \`s_orders\``); + await db.execute( + sql` + create table \`s_orders\` ( + \`id\` serial primary key, + \`region\` text default ('Ukraine'), + \`product\` text not null + ) + `, + ); + + const users = mysqlTable('s_orders', { + id: serial('id').primaryKey(), + region: text('region').default('Ukraine'), + product: text('product').$defaultFn(() => 'random_string'), + }); + + await db.insert(users).values({}); + const selectedOrder = await db.select().from(users); + + t.deepEqual(selectedOrder, [{ + id: 1, + region: 'Ukraine', + product: 'random_string', + }]); +}); + test.serial('select with group by as sql + column', async (t) => { const { db } = t.context; @@ -554,7 +612,7 @@ test.serial('Query check: Insert all defaults in 1 row', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into `users` () values ()', + sql: 'insert into `users` (`id`, `name`, `state`) values (default, default, default)', params: [], }); }); @@ -616,7 +674,7 @@ test.serial('Insert all defaults in multiple rows', async (t) => { sql`create table ${users} (id serial primary key, name text default ('Dan'), state text)`, ); - await db.insert(users).values([{}, {}]) + await db.insert(users).values([{}, {}]); const res = await db.select().from(users); @@ -632,7 +690,8 @@ test.serial('build query insert with onDuplicate', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into `userstest` (`name`, `jsonb`) values (?, ?) on duplicate key update `name` = ?', + sql: + 'insert into `userstest` (`id`, `name`, `verified`, `jsonb`, `created_at`) values (default, ?, default, ?, default) on duplicate key update `name` = ?', params: ['John', '["foo","bar"]', 'John1'], }); }); diff --git a/integration-tests/tests/neon-http.test.ts b/integration-tests/tests/neon-http.test.ts index 7ee9d68ce..b165fe696 100644 --- a/integration-tests/tests/neon-http.test.ts +++ b/integration-tests/tests/neon-http.test.ts @@ -960,7 +960,7 @@ test.serial('insert via db.execute + returning', async (t) => { test.serial('insert via db.execute w/ query builder', async (t) => { const { db } = t.context; - const inserted = await db.execute>( + const inserted = await db.execute>( db .insert(usersTable) .values({ name: 'John' }) @@ -1381,7 +1381,7 @@ test.serial('select count w/ custom mapper', async (t) => { test.serial('network types', async (t) => { const { db } = t.context; - const value: typeof network['_']['model']['select'] = { + const value: typeof network.$inferSelect = { inet: '127.0.0.1', cidr: '192.168.100.128/25', macaddr: '08:00:2b:01:02:03', @@ -1398,7 +1398,7 @@ test.serial('network types', async (t) => { test.serial('array types', async (t) => { const { db } = t.context; - const values: typeof salEmp['_']['model']['select'][] = [ + const values: typeof salEmp.$inferSelect[] = [ { name: 'John', payByQuarter: [10000, 10000, 10000, 10000], diff --git a/integration-tests/tests/pg-schema.test.ts b/integration-tests/tests/pg-schema.test.ts index 55cd52059..3e8dd27e3 100644 --- a/integration-tests/tests/pg-schema.test.ts +++ b/integration-tests/tests/pg-schema.test.ts @@ -677,7 +677,7 @@ test.serial('insert via db.execute + returning', async (t) => { test.serial('insert via db.execute w/ query builder', async (t) => { const { db } = t.context; - const inserted = await db.execute>( + const inserted = await db.execute>( db.insert(usersTable).values({ name: 'John' }).returning({ id: usersTable.id, name: usersTable.name }), ); t.deepEqual(inserted.rows, [{ id: 1, name: 'John' }]); @@ -722,7 +722,8 @@ test.serial('build query insert with onConflict do nothing', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into "mySchema"."users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict do nothing', + sql: + 'insert into "mySchema"."users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict do nothing', params: ['John', '["foo","bar"]'], }); }); @@ -736,7 +737,8 @@ test.serial('build query insert with onConflict do nothing + target', async (t) .toSQL(); t.deepEqual(query, { - sql: 'insert into "mySchema"."users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do nothing', + sql: + 'insert into "mySchema"."users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do nothing', params: ['John', '["foo","bar"]'], }); }); diff --git a/integration-tests/tests/pg.custom.test.ts b/integration-tests/tests/pg.custom.test.ts index 2190d94cd..8e1751816 100644 --- a/integration-tests/tests/pg.custom.test.ts +++ b/integration-tests/tests/pg.custom.test.ts @@ -645,7 +645,7 @@ test.serial('insert via db.execute + returning', async (t) => { test.serial('insert via db.execute w/ query builder', async (t) => { const { db } = t.context; - const inserted = await db.execute>( + const inserted = await db.execute>( db.insert(usersTable).values({ name: 'John' }).returning({ id: usersTable.id, name: usersTable.name }), ); t.deepEqual(inserted.rows, [{ id: 1, name: 'John' }]); @@ -660,7 +660,8 @@ test.serial('build query insert with onConflict do update', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do update set "name" = $3', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do update set "name" = $3', params: ['John', '["foo","bar"]', 'John1'], }); }); @@ -674,7 +675,8 @@ test.serial('build query insert with onConflict do update / multiple columns', a .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id","name") do update set "name" = $3', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id","name") do update set "name" = $3', params: ['John', '["foo","bar"]', 'John1'], }); }); @@ -688,7 +690,8 @@ test.serial('build query insert with onConflict do nothing', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict do nothing', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict do nothing', params: ['John', '["foo","bar"]'], }); }); @@ -702,7 +705,8 @@ test.serial('build query insert with onConflict do nothing + target', async (t) .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do nothing', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do nothing', params: ['John', '["foo","bar"]'], }); }); diff --git a/integration-tests/tests/pg.test.ts b/integration-tests/tests/pg.test.ts index fbae33e05..37687a96e 100644 --- a/integration-tests/tests/pg.test.ts +++ b/integration-tests/tests/pg.test.ts @@ -22,7 +22,6 @@ import { drizzle, type NodePgDatabase } from 'drizzle-orm/node-postgres'; import { migrate } from 'drizzle-orm/node-postgres/migrator'; import { alias, - type AnyPgColumn, boolean, char, cidr, @@ -34,6 +33,7 @@ import { jsonb, macaddr, macaddr8, + type PgColumn, pgEnum, pgMaterializedView, pgTable, @@ -88,7 +88,7 @@ const courseCategoriesTable = pgTable('course_categories', { const orders = pgTable('orders', { id: serial('id').primaryKey(), region: text('region').notNull(), - product: text('product').notNull(), + product: text('product').notNull().$default(() => 'random_string'), amount: integer('amount').notNull(), quantity: integer('quantity').notNull(), }); @@ -363,6 +363,30 @@ test.serial('select typed sql', async (t) => { t.deepEqual(users, [{ name: 'JOHN' }]); }); +test.serial('$default function', async (t) => { + const { db } = t.context; + + const insertedOrder = await db.insert(orders).values({ id: 1, region: 'Ukraine', amount: 1, quantity: 1 }) + .returning(); + const selectedOrder = await db.select().from(orders); + + t.deepEqual(insertedOrder, [{ + id: 1, + amount: 1, + quantity: 1, + region: 'Ukraine', + product: 'random_string', + }]); + + t.deepEqual(selectedOrder, [{ + id: 1, + amount: 1, + quantity: 1, + region: 'Ukraine', + product: 'random_string', + }]); +}); + test.serial('select distinct', async (t) => { const { db } = t.context; @@ -998,7 +1022,7 @@ test.serial('insert via db.execute + returning', async (t) => { test.serial('insert via db.execute w/ query builder', async (t) => { const { db } = t.context; - const inserted = await db.execute>( + const inserted = await db.execute>( db .insert(usersTable) .values({ name: 'John' }) @@ -1084,7 +1108,7 @@ test.serial('Insert all defaults in multiple rows', async (t) => { sql`create table ${users} (id serial primary key, name text default 'Dan', state text)`, ); - await db.insert(users).values([{}, {}]) + await db.insert(users).values([{}, {}]); const res = await db.select().from(users); @@ -1101,7 +1125,8 @@ test.serial('build query insert with onConflict do update', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do update set "name" = $3', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do update set "name" = $3', params: ['John', '["foo","bar"]', 'John1'], }); }); @@ -1116,7 +1141,8 @@ test.serial('build query insert with onConflict do update / multiple columns', a .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id","name") do update set "name" = $3', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id","name") do update set "name" = $3', params: ['John', '["foo","bar"]', 'John1'], }); }); @@ -1131,7 +1157,8 @@ test.serial('build query insert with onConflict do nothing', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict do nothing', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict do nothing', params: ['John', '["foo","bar"]'], }); }); @@ -1146,7 +1173,8 @@ test.serial('build query insert with onConflict do nothing + target', async (t) .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do nothing', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do nothing', params: ['John', '["foo","bar"]'], }); }); @@ -1483,9 +1511,9 @@ test.serial('select count()', async (t) => { test.serial('select count w/ custom mapper', async (t) => { const { db } = t.context; - function count(value: AnyPgColumn | SQLWrapper): SQL; - function count(value: AnyPgColumn | SQLWrapper, alias: string): SQL.Aliased; - function count(value: AnyPgColumn | SQLWrapper, alias?: string): SQL | SQL.Aliased { + function count(value: PgColumn | SQLWrapper): SQL; + function count(value: PgColumn | SQLWrapper, alias: string): SQL.Aliased; + function count(value: PgColumn | SQLWrapper, alias?: string): SQL | SQL.Aliased { const result = sql`count(${value})`.mapWith(Number); if (!alias) { return result; @@ -1503,7 +1531,7 @@ test.serial('select count w/ custom mapper', async (t) => { test.serial('network types', async (t) => { const { db } = t.context; - const value: typeof network['_']['model']['select'] = { + const value: typeof network.$inferSelect = { inet: '127.0.0.1', cidr: '192.168.100.128/25', macaddr: '08:00:2b:01:02:03', @@ -1520,7 +1548,7 @@ test.serial('network types', async (t) => { test.serial('array types', async (t) => { const { db } = t.context; - const values: typeof salEmp['_']['model']['select'][] = [ + const values: typeof salEmp.$inferSelect[] = [ { name: 'John', payByQuarter: [10000, 10000, 10000, 10000], diff --git a/integration-tests/tests/postgres.js.test.ts b/integration-tests/tests/postgres.js.test.ts index f3d15ce25..198c7a8a3 100644 --- a/integration-tests/tests/postgres.js.test.ts +++ b/integration-tests/tests/postgres.js.test.ts @@ -21,12 +21,12 @@ import { } from 'drizzle-orm'; import { alias, - type AnyPgColumn, boolean, getMaterializedViewConfig, getViewConfig, integer, jsonb, + type PgColumn, pgEnum, pgMaterializedView, pgTable, @@ -81,7 +81,7 @@ const courseCategoriesTable = pgTable('course_categories', { const orders = pgTable('orders', { id: serial('id').primaryKey(), region: text('region').notNull(), - product: text('product').notNull(), + product: text('product').notNull().$default(() => 'random_string'), amount: integer('amount').notNull(), quantity: integer('quantity').notNull(), }); @@ -796,7 +796,7 @@ test.serial('insert via db.execute + returning', async (t) => { test.serial('insert via db.execute w/ query builder', async (t) => { const { db } = t.context; - const result = await db.execute>( + const result = await db.execute>( db.insert(usersTable).values({ name: 'John' }).returning({ id: usersTable.id, name: usersTable.name }), ); t.deepEqual(Array.prototype.slice.call(result), [{ id: 1, name: 'John' }]); @@ -842,6 +842,30 @@ test.serial('Query check: Insert all defaults in multiple rows', async (t) => { }); }); +test.serial('$default function', async (t) => { + const { db } = t.context; + + const insertedOrder = await db.insert(orders).values({ id: 1, region: 'Ukraine', amount: 1, quantity: 1 }) + .returning(); + const selectedOrder = await db.select().from(orders); + + t.deepEqual(insertedOrder, [{ + id: 1, + amount: 1, + quantity: 1, + region: 'Ukraine', + product: 'random_string', + }]); + + t.deepEqual(selectedOrder, [{ + id: 1, + amount: 1, + quantity: 1, + region: 'Ukraine', + product: 'random_string', + }]); +}); + test.serial('Insert all defaults in 1 row', async (t) => { const { db } = t.context; @@ -879,7 +903,7 @@ test.serial('Insert all defaults in multiple rows', async (t) => { sql`create table ${users} (id serial primary key, name text default 'Dan', state text)`, ); - await db.insert(users).values([{}, {}]) + await db.insert(users).values([{}, {}]); const res = await db.select().from(users); @@ -895,7 +919,8 @@ test.serial('build query insert with onConflict do update', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do update set "name" = $3', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do update set "name" = $3', params: ['John', '["foo","bar"]', 'John1'], }); }); @@ -909,7 +934,8 @@ test.serial('build query insert with onConflict do update / multiple columns', a .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id","name") do update set "name" = $3', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id","name") do update set "name" = $3', params: ['John', '["foo","bar"]', 'John1'], }); }); @@ -923,7 +949,8 @@ test.serial('build query insert with onConflict do nothing', async (t) => { .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict do nothing', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict do nothing', params: ['John', '["foo","bar"]'], }); }); @@ -937,7 +964,8 @@ test.serial('build query insert with onConflict do nothing + target', async (t) .toSQL(); t.deepEqual(query, { - sql: 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do nothing', + sql: + 'insert into "users" ("id", "name", "verified", "jsonb", "created_at") values (default, $1, default, $2, default) on conflict ("id") do nothing', params: ['John', '["foo","bar"]'], }); }); @@ -1256,9 +1284,9 @@ test.serial('select count()', async (t) => { test.serial('select count w/ custom mapper', async (t) => { const { db } = t.context; - function count(value: AnyPgColumn | SQLWrapper): SQL; - function count(value: AnyPgColumn | SQLWrapper, alias: string): SQL.Aliased; - function count(value: AnyPgColumn | SQLWrapper, alias?: string): SQL | SQL.Aliased { + function count(value: PgColumn | SQLWrapper): SQL; + function count(value: PgColumn | SQLWrapper, alias: string): SQL.Aliased; + function count(value: PgColumn | SQLWrapper, alias?: string): SQL | SQL.Aliased { const result = sql`count(${value})`.mapWith(Number); if (!alias) { return result; diff --git a/integration-tests/tests/relational/pg.schema.ts b/integration-tests/tests/relational/pg.schema.ts index b64a31348..b17bafa60 100644 --- a/integration-tests/tests/relational/pg.schema.ts +++ b/integration-tests/tests/relational/pg.schema.ts @@ -1,4 +1,4 @@ -import { type AnyPgColumn, boolean, integer, pgTable, primaryKey, serial, text, timestamp } from 'drizzle-orm/pg-core'; +import { boolean, integer, type PgColumn, pgTable, primaryKey, serial, text, timestamp } from 'drizzle-orm/pg-core'; import { relations } from 'drizzle-orm'; @@ -6,7 +6,7 @@ export const usersTable = pgTable('users', { id: serial('id').primaryKey(), name: text('name').notNull(), verified: boolean('verified').notNull().default(false), - invitedBy: integer('invited_by').references((): AnyPgColumn => usersTable.id), + invitedBy: integer('invited_by').references((): PgColumn => usersTable.id), }); export const usersConfig = relations(usersTable, ({ one, many }) => ({ diff --git a/integration-tests/tests/sql.js.test.ts b/integration-tests/tests/sql.js.test.ts index a5f5922bd..6da546699 100644 --- a/integration-tests/tests/sql.js.test.ts +++ b/integration-tests/tests/sql.js.test.ts @@ -763,7 +763,7 @@ test.serial('insert via db.run + select via db.get', (t) => { test.serial('insert via db.get w/ query builder', (t) => { const { db } = t.context; - const inserted = db.get>( + const inserted = db.get>( db.insert(usersTable).values({ name: 'John' }).returning({ id: usersTable.id, name: usersTable.name }), ); t.deepEqual(inserted, { id: 1, name: 'John' }); @@ -1711,6 +1711,8 @@ test.serial('async api - CRUD', async (t) => { const res2 = await db.select().from(users); t.deepEqual(res2, []); + + db.run(sql`drop table ${users}`); }); test.serial('async api - insert + select w/ prepare + async execute', async (t) => { @@ -1748,6 +1750,8 @@ test.serial('async api - insert + select w/ prepare + async execute', async (t) const res2 = await selectStmt.execute(); t.deepEqual(res2, []); + + db.run(sql`drop table ${users}`); }); test.serial('async api - insert + select w/ prepare + sync execute', (t) => { @@ -1785,4 +1789,27 @@ test.serial('async api - insert + select w/ prepare + sync execute', (t) => { const res2 = selectStmt.execute().sync(); t.deepEqual(res2, []); + + db.run(sql`drop table ${users}`); +}); + +test.serial('select + .get() for empty result', (t) => { + const { db } = t.context; + + const users = sqliteTable('users', { + id: integer('id').primaryKey(), + name: text('name'), + }); + + db.run(sql`drop table if exists ${users}`); + + db.run( + sql`create table ${users} (id integer primary key, name text)`, + ); + + const res = db.select().from(users).where(eq(users.id, 1)).get(); + + t.is(res, undefined); + + db.run(sql`drop table ${users}`); }); diff --git a/integration-tests/tests/sqlite-proxy.test.ts b/integration-tests/tests/sqlite-proxy.test.ts index f562f963e..55a5a3e36 100644 --- a/integration-tests/tests/sqlite-proxy.test.ts +++ b/integration-tests/tests/sqlite-proxy.test.ts @@ -1010,6 +1010,8 @@ test.serial('async api - CRUD', async (t) => { const res2 = await db.select().from(users); t.deepEqual(res2, []); + + await db.run(sql`drop table ${users}`); }); test.serial('async api - insert + select w/ prepare + async execute', async (t) => { @@ -1047,6 +1049,8 @@ test.serial('async api - insert + select w/ prepare + async execute', async (t) const res2 = await selectStmt.execute(); t.deepEqual(res2, []); + + await db.run(sql`drop table ${users}`); }); test.serial('async api - insert + select w/ prepare + sync execute', async (t) => { @@ -1084,4 +1088,27 @@ test.serial('async api - insert + select w/ prepare + sync execute', async (t) = const res2 = await selectStmt.execute(); t.deepEqual(res2, []); + + await db.run(sql`drop table ${users}`); +}); + +test.serial('select + .get() for empty result', async (t) => { + const { db } = t.context; + + const users = sqliteTable('users', { + id: integer('id').primaryKey(), + name: text('name'), + }); + + db.run(sql`drop table if exists ${users}`); + + db.run( + sql`create table ${users} (id integer primary key, name text)`, + ); + + const res = await db.select().from(users).where(eq(users.id, 1)).get(); + + t.is(res, undefined); + + await db.run(sql`drop table ${users}`); }); diff --git a/integration-tests/tests/vercel-pg.test.ts b/integration-tests/tests/vercel-pg.test.ts index 1d01045a9..d9d47ef0d 100644 --- a/integration-tests/tests/vercel-pg.test.ts +++ b/integration-tests/tests/vercel-pg.test.ts @@ -21,7 +21,6 @@ import { } from 'drizzle-orm'; import { alias, - type AnyPgColumn, boolean, char, cidr, @@ -32,6 +31,7 @@ import { jsonb, macaddr, macaddr8, + type PgColumn, pgEnum, pgMaterializedView, pgTable, @@ -948,7 +948,7 @@ test.serial('insert via db.execute + returning', async (t) => { test.serial('insert via db.execute w/ query builder', async (t) => { const { db } = t.context; - const inserted = await db.execute>( + const inserted = await db.execute>( db .insert(usersTable) .values({ name: 'John' }) @@ -1349,9 +1349,9 @@ test.serial('select count()', async (t) => { test.serial('select count w/ custom mapper', async (t) => { const { db } = t.context; - function count(value: AnyPgColumn | SQLWrapper): SQL; - function count(value: AnyPgColumn | SQLWrapper, alias: string): SQL.Aliased; - function count(value: AnyPgColumn | SQLWrapper, alias?: string): SQL | SQL.Aliased { + function count(value: PgColumn | SQLWrapper): SQL; + function count(value: PgColumn | SQLWrapper, alias: string): SQL.Aliased; + function count(value: PgColumn | SQLWrapper, alias?: string): SQL | SQL.Aliased { const result = sql`count(${value})`.mapWith(Number); if (!alias) { return result; @@ -1369,7 +1369,7 @@ test.serial('select count w/ custom mapper', async (t) => { test.serial('network types', async (t) => { const { db } = t.context; - const value: typeof network['_']['model']['select'] = { + const value: typeof network.$inferSelect = { inet: '127.0.0.1', cidr: '192.168.100.128/25', macaddr: '08:00:2b:01:02:03', @@ -1386,7 +1386,7 @@ test.serial('network types', async (t) => { test.serial('array types', async (t) => { const { db } = t.context; - const values: typeof salEmp['_']['model']['select'][] = [ + const values: typeof salEmp.$inferSelect[] = [ { name: 'John', payByQuarter: [10000, 10000, 10000, 10000], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b1962c990..6fd5cf285 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -130,6 +130,9 @@ importers: concurrently: specifier: ^8.1.0 version: 8.1.0 + cpy-cli: + specifier: ^5.0.0 + version: 5.0.0 knex: specifier: ^2.4.2 version: 2.4.2(better-sqlite3@8.4.0)(mysql2@3.3.3)(pg@8.11.0)(sqlite3@5.1.6) @@ -145,6 +148,9 @@ importers: postgres: specifier: ^3.3.5 version: 3.3.5 + rimraf: + specifier: ^5.0.0 + version: 5.0.0 rollup: specifier: ^3.27.2 version: 3.27.2 @@ -1417,6 +1423,7 @@ packages: /@babel/code-frame@7.22.5: resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} engines: {node: '>=6.9.0'} + requiresBuild: true dependencies: '@babel/highlight': 7.22.5 dev: true @@ -1480,6 +1487,7 @@ packages: /@babel/helper-validator-identifier@7.22.5: resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} engines: {node: '>=6.9.0'} + requiresBuild: true dev: true /@babel/highlight@7.22.5: @@ -2829,6 +2837,7 @@ packages: /abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + requiresBuild: true /accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} @@ -3175,6 +3184,7 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + requiresBuild: true /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -3237,6 +3247,7 @@ packages: /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + requiresBuild: true dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 @@ -3568,6 +3579,7 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + requiresBuild: true /concordance@5.0.4: resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==} @@ -3627,6 +3639,15 @@ packages: engines: {node: '>= 0.6'} dev: false + /cp-file@10.0.0: + resolution: {integrity: sha512-vy2Vi1r2epK5WqxOLnskeKeZkdZvTKfFZQCplE3XWsP+SUJyd5XAUFC9lFgTjjXJF2GMne/UML14iEmkAaDfFg==} + engines: {node: '>=14.16'} + dependencies: + graceful-fs: 4.2.11 + nested-error-stacks: 2.1.1 + p-event: 5.0.1 + dev: true + /cpu-features@0.0.8: resolution: {integrity: sha512-BbHBvtYhUhksqTjr6bhNOjGgMnhwhGTQmOoZGD+K7BCaQDCuZl/Ve1ZxUSMRwVC4D/rkCPQ2MAIeYzrWyK7eEg==} engines: {node: '>=10.0.0'} @@ -3637,6 +3658,29 @@ packages: dev: false optional: true + /cpy-cli@5.0.0: + resolution: {integrity: sha512-fb+DZYbL9KHc0BC4NYqGRrDIJZPXUmjjtqdw4XRRg8iV8dIfghUX/WiL+q4/B/KFTy3sK6jsbUhBaz0/Hxg7IQ==} + engines: {node: '>=16'} + hasBin: true + dependencies: + cpy: 10.1.0 + meow: 12.1.0 + dev: true + + /cpy@10.1.0: + resolution: {integrity: sha512-VC2Gs20JcTyeQob6UViBLnyP0bYHkBh6EiKzot9vi2DmeGlFT9Wd7VG3NBrkNx/jYvFBeyDOMMHdHQhbtKLgHQ==} + engines: {node: '>=16'} + dependencies: + arrify: 3.0.0 + cp-file: 10.0.0 + globby: 13.1.4 + junk: 4.0.1 + micromatch: 4.0.5 + nested-error-stacks: 2.1.1 + p-filter: 3.0.0 + p-map: 6.0.0 + dev: true + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -3766,6 +3810,7 @@ packages: /depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + requiresBuild: true /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} @@ -4394,6 +4439,7 @@ packages: /escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} + requiresBuild: true dev: true /escape-string-regexp@2.0.0: @@ -4955,6 +5001,7 @@ packages: /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + requiresBuild: true /fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} @@ -5094,6 +5141,7 @@ packages: /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + requiresBuild: true dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -5333,10 +5381,12 @@ packages: /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + requiresBuild: true /indent-string@4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} + requiresBuild: true /indent-string@5.0.0: resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} @@ -5350,6 +5400,7 @@ packages: /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + requiresBuild: true dependencies: once: 1.4.0 wrappy: 1.0.2 @@ -5696,6 +5747,11 @@ packages: through2: 4.0.2 dev: false + /junk@4.0.1: + resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==} + engines: {node: '>=12.20'} + dev: true + /kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} @@ -5820,6 +5876,7 @@ packages: /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + requiresBuild: true dependencies: yallist: 4.0.0 @@ -5944,6 +6001,11 @@ packages: timers-ext: 0.1.7 dev: true + /meow@12.1.0: + resolution: {integrity: sha512-SvSqzS5ktjGoySdCwxQI16iO/ID1LtxM03QvJ4FF2H5cCtXLN7YbfKBCL9btqXSSuJ5TNG4UH6wvWtXZuvgvrw==} + engines: {node: '>=16.10'} + dev: true + /merge-descriptors@1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} dev: false @@ -5999,6 +6061,7 @@ packages: /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + requiresBuild: true dependencies: brace-expansion: 1.1.11 @@ -6130,6 +6193,7 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + requiresBuild: true /mysql2@3.3.3: resolution: {integrity: sha512-MxDQJztArk4JFX1PKVjDhIXRzAmVJfuqZrVU+my6NeYBAA/XZRaDw5q7vga8TNvgyy3Lv3rivBFBBuJFbsdjaw==} @@ -6175,6 +6239,11 @@ packages: /negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} + requiresBuild: true + + /nested-error-stacks@2.1.1: + resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==} + dev: true /next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} @@ -6388,6 +6457,13 @@ packages: p-timeout: 5.1.0 dev: true + /p-filter@3.0.0: + resolution: {integrity: sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-map: 5.5.0 + dev: true + /p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -6443,6 +6519,11 @@ packages: aggregate-error: 4.0.1 dev: true + /p-map@6.0.0: + resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==} + engines: {node: '>=16'} + dev: true + /p-timeout@5.1.0: resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} engines: {node: '>=12'} @@ -8124,6 +8205,7 @@ packages: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true + requiresBuild: true dependencies: isexe: 2.0.0