diff --git a/.github/workflows/release-feature-branch.yaml b/.github/workflows/release-feature-branch.yaml index d0e0240c0..5c2d76fb7 100644 --- a/.github/workflows/release-feature-branch.yaml +++ b/.github/workflows/release-feature-branch.yaml @@ -136,12 +136,6 @@ jobs: cd drizzle-orm pnpm prisma generate --schema src/prisma/schema.prisma ) - ( - cd integration-tests - pnpm prisma generate --schema tests/prisma/pg/schema.prisma - pnpm prisma generate --schema tests/prisma/mysql/schema.prisma - pnpm prisma generate --schema tests/prisma/sqlite/schema.prisma - ) pnpm build - name: Run tests diff --git a/.github/workflows/release-latest.yaml b/.github/workflows/release-latest.yaml index ce194530f..d81a0bcab 100644 --- a/.github/workflows/release-latest.yaml +++ b/.github/workflows/release-latest.yaml @@ -139,12 +139,6 @@ jobs: cd drizzle-orm pnpm prisma generate --schema src/prisma/schema.prisma ) - ( - cd integration-tests - pnpm prisma generate --schema tests/prisma/pg/schema.prisma - pnpm prisma generate --schema tests/prisma/mysql/schema.prisma - pnpm prisma generate --schema tests/prisma/sqlite/schema.prisma - ) pnpm build - name: Run tests diff --git a/changelogs/drizzle-kit/0.24.1.md b/changelogs/drizzle-kit/0.24.1.md new file mode 100644 index 000000000..d70f6ebbe --- /dev/null +++ b/changelogs/drizzle-kit/0.24.1.md @@ -0,0 +1,32 @@ +## Bug fixes + +> Big thanks to @L-Mario564 for his [PR](https://github.com/drizzle-team/drizzle-orm/pull/2804). It conflicted in most cases with a PR that was merged, but we incorporated some of his logic. Merging it would have caused more problems and taken more time to resolve, so we just took a few things from his PR, like removing "::" mappings in introspect and some array type default handlers + +### What was fixed + +1. The Drizzle Kit CLI was not working properly for the `introspect` command. +2. Added the ability to use column names with special characters for all dialects. +3. Included PostgreSQL sequences in the introspection process. +4. Reworked array type introspection and added all test cases. +5. Fixed all (we hope) default issues in PostgreSQL, where `::` was included in the introspected output. +6. `preserve` casing option was broken + +### Tickets that were closed + +- [[BUG]: invalid schema generation with drizzle-kit introspect:pg](https://github.com/drizzle-team/drizzle-orm/issues/1210) +- [[BUG][mysql introspection]: TS error when introspect column including colon](https://github.com/drizzle-team/drizzle-orm/issues/1928) +- [[BUG]: Unhandled defaults when introspecting postgres db](https://github.com/drizzle-team/drizzle-orm/issues/1625) +- [[BUG]: PostgreSQL Enum Naming and Schema Typing Issue](https://github.com/drizzle-team/drizzle-orm/issues/2315) +- [[BUG]: drizzle-kit instrospect command generates syntax error on varchar column types](https://github.com/drizzle-team/drizzle-orm/issues/2714) +- [[BUG]: Introspecting varchar[] type produces syntactically invalid schema.ts](https://github.com/drizzle-team/drizzle-orm/issues/1633) +- [[BUG]: introspect:pg column not using generated enum name](https://github.com/drizzle-team/drizzle-orm/issues/1648) +- [[BUG]: drizzle-kit introspect casing "preserve" config not working](https://github.com/drizzle-team/drizzle-orm/issues/2773) +- [[BUG]: drizzle-kit introspect fails on required param that is defined](https://github.com/drizzle-team/drizzle-orm/issues/2719) +- [[BUG]: Error when running npx drizzle-kit introspect: "Expected object, received string"](https://github.com/drizzle-team/drizzle-orm/issues/2657) +- [[BUG]: Missing index names when running introspect command [MYSQL]](https://github.com/drizzle-team/drizzle-orm/issues/2525) +- [[BUG]: drizzle-kit introspect TypeError: Cannot read properties of undefined (reading 'toLowerCase')](https://github.com/drizzle-team/drizzle-orm/issues/2338) +- [[BUG]: Wrong column name when using PgEnum.array()](https://github.com/drizzle-team/drizzle-orm/issues/2100) +- [[BUG]: Incorrect Schema Generated when introspecting extisting pg database](https://github.com/drizzle-team/drizzle-orm/issues/1985) +- [[⚠️🐞BUG]: index() missing argument after introspection, causes tsc error that fails the build](https://github.com/drizzle-team/drizzle-orm/issues/1870) +- [[BUG]: drizzle-kit introspect small errors](https://github.com/drizzle-team/drizzle-orm/issues/1738) +- [[BUG]: Missing bigint import in drizzle-kit introspect](https://github.com/drizzle-team/drizzle-orm/issues/1020) \ No newline at end of file diff --git a/changelogs/drizzle-kit/0.24.2.md b/changelogs/drizzle-kit/0.24.2.md new file mode 100644 index 000000000..962a29acc --- /dev/null +++ b/changelogs/drizzle-kit/0.24.2.md @@ -0,0 +1,24 @@ +## New Features + +### 🎉 Support for `pglite` driver + +You can now use pglite with all drizzle-kit commands, including Drizzle Studio! + +```ts +import { defineConfig } from "drizzle-kit"; + +export default defineConfig({ + dialect: "postgresql", + driver: "pglite", + schema: "./schema.ts", + dbCredentials: { + url: "local-pg.db", + }, + verbose: true, + strict: true, +}); +``` + +## Bug fixes + +- mysql-kit: fix GENERATED ALWAYS AS ... NOT NULL - [#2824](https://github.com/drizzle-team/drizzle-orm/pull/2824) \ No newline at end of file diff --git a/drizzle-kit/build.ts b/drizzle-kit/build.ts index 8616112fd..701e9c84c 100644 --- a/drizzle-kit/build.ts +++ b/drizzle-kit/build.ts @@ -9,6 +9,7 @@ const driversPackages = [ 'postgres', '@vercel/postgres', '@neondatabase/serverless', + '@electric-sql/pglite', // mysql drivers 'mysql2', '@planetscale/database', diff --git a/drizzle-kit/package.json b/drizzle-kit/package.json index dda0ca2a4..9d9e1d227 100644 --- a/drizzle-kit/package.json +++ b/drizzle-kit/package.json @@ -1,6 +1,6 @@ { "name": "drizzle-kit", - "version": "0.24.0", + "version": "0.24.2", "homepage": "https://orm.drizzle.team", "keywords": [ "drizzle", @@ -42,7 +42,7 @@ "publish": "npm publish package.tgz" }, "dependencies": { - "@drizzle-team/brocli": "^0.8.2", + "@drizzle-team/brocli": "^0.10.1", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.19.7", "esbuild-register": "^3.5.0" @@ -92,7 +92,7 @@ "hono": "^4.1.5", "json-diff": "1.0.6", "minimatch": "^7.4.3", - "mysql2": "^3.3.3", + "mysql2": "3.3.3", "node-fetch": "^3.3.2", "pg": "^8.11.5", "pluralize": "^8.0.0", diff --git a/drizzle-kit/src/cli/commands/utils.ts b/drizzle-kit/src/cli/commands/utils.ts index 62be14b35..8f51d0c18 100644 --- a/drizzle-kit/src/cli/commands/utils.ts +++ b/drizzle-kit/src/cli/commands/utils.ts @@ -84,7 +84,7 @@ export const safeRegister = async () => { export const prepareCheckParams = async ( options: { config?: string; - dialect: Dialect; + dialect?: Dialect; out?: string; }, from: 'cli' | 'config', @@ -440,11 +440,11 @@ export const preparePullConfig = async ( dialect: 'postgresql', out: config.out, breakpoints: config.breakpoints, - casing: config.introspectCasing, + casing: config.casing, credentials: parsed.data, tablesFilter, schemasFilter, - prefix: config.database?.prefix || 'index', + prefix: config.migrations?.prefix || 'index', }; } @@ -458,11 +458,11 @@ export const preparePullConfig = async ( dialect: 'mysql', out: config.out, breakpoints: config.breakpoints, - casing: config.introspectCasing, + casing: config.casing, credentials: parsed.data, tablesFilter, schemasFilter, - prefix: config.database?.prefix || 'index', + prefix: config.migrations?.prefix || 'index', }; } @@ -495,11 +495,11 @@ export const preparePullConfig = async ( dialect: 'sqlite', out: config.out, breakpoints: config.breakpoints, - casing: config.introspectCasing, + casing: config.casing, credentials: parsed.data, tablesFilter, schemasFilter, - prefix: config.database?.prefix || 'index', + prefix: config.migrations?.prefix || 'index', }; } diff --git a/drizzle-kit/src/cli/connections.ts b/drizzle-kit/src/cli/connections.ts index 18c9b04a1..3357bf146 100644 --- a/drizzle-kit/src/cli/connections.ts +++ b/drizzle-kit/src/cli/connections.ts @@ -5,7 +5,7 @@ import fetch from 'node-fetch'; import ws from 'ws'; import { assertUnreachable } from '../global'; import type { ProxyParams } from '../serializer/studio'; -import { type DB, normaliseSQLiteUrl, type Proxy, type SQLiteDB, type SqliteProxy } from '../utils'; +import { type DB, normalisePGliteUrl, normaliseSQLiteUrl, type Proxy, type SQLiteDB, type SqliteProxy } from '../utils'; import { assertPackages, checkPackage } from './utils'; import type { MysqlCredentials } from './validations/mysql'; import { withStyle } from './validations/outputs'; @@ -22,7 +22,8 @@ export const preparePostgresDB = async ( } > => { if ('driver' in credentials) { - if (credentials.driver === 'aws-data-api') { + const { driver } = credentials; + if (driver === 'aws-data-api') { assertPackages('@aws-sdk/client-rds-data'); const { RDSDataClient, ExecuteStatementCommand, TypeHint } = await import( '@aws-sdk/client-rds-data' @@ -93,7 +94,45 @@ export const preparePostgresDB = async ( }; } - assertUnreachable(credentials.driver); + if (driver === 'pglite') { + assertPackages('@electric-sql/pglite'); + const { PGlite } = await import('@electric-sql/pglite'); + const { drizzle } = await import('drizzle-orm/pglite'); + const { migrate } = await import('drizzle-orm/pglite/migrator'); + + const pglite = new PGlite(normalisePGliteUrl(credentials.url)); + await pglite.waitReady; + const drzl = drizzle(pglite); + const migrateFn = async (config: MigrationConfig) => { + return migrate(drzl, config); + }; + + const query = async (sql: string, params: any[] = []) => { + const result = await pglite.query(sql, params); + return result.rows as T[]; + }; + + const proxy = async (params: ProxyParams) => { + const preparedParams = preparePGliteParams(params.params); + if ( + params.method === 'values' + || params.method === 'get' + || params.method === 'all' + ) { + const result = await pglite.query(params.sql, preparedParams, { + rowMode: params.mode, + }); + return result.rows; + } + + const result = await pglite.query(params.sql, preparedParams); + return result.rows; + }; + + return { query, proxy, migrate: migrateFn }; + } + + assertUnreachable(driver); } if (await checkPackage('pg')) { @@ -416,6 +455,25 @@ const prepareSqliteParams = (params: any[], driver?: string) => { }); }; +const preparePGliteParams = (params: any[]) => { + return params.map((param) => { + if ( + param + && typeof param === 'object' + && 'type' in param + && 'value' in param + && param.type === 'binary' + ) { + const value = typeof param.value === 'object' + ? JSON.stringify(param.value) + : (param.value as string); + + return value; + } + return param; + }); +}; + export const connectToSQLite = async ( credentials: SqliteCredentials, ): Promise< diff --git a/drizzle-kit/src/cli/index.ts b/drizzle-kit/src/cli/index.ts index a7272ffef..86bffdf3d 100644 --- a/drizzle-kit/src/cli/index.ts +++ b/drizzle-kit/src/cli/index.ts @@ -43,5 +43,6 @@ const legacy = [ ]; run([generate, migrate, pull, push, studio, up, check, drop, ...legacy], { + name: 'drizzle-kit', version: version, }); diff --git a/drizzle-kit/src/cli/schema.ts b/drizzle-kit/src/cli/schema.ts index 642344bda..4da8af0ac 100644 --- a/drizzle-kit/src/cli/schema.ts +++ b/drizzle-kit/src/cli/schema.ts @@ -108,15 +108,23 @@ export const migrate = command({ try { if (dialect === 'postgresql') { if ('driver' in credentials) { - if (credentials.driver === 'aws-data-api') { + const { driver } = credentials; + if (driver === 'aws-data-api') { if (!(await ormVersionGt('0.30.10'))) { console.log( "To use 'aws-data-api' driver - please update drizzle-orm to the latest version", ); process.exit(1); } + } else if (driver === 'pglite') { + if (!(await ormVersionGt('0.30.6'))) { + console.log( + "To use 'pglite' driver - please update drizzle-orm to the latest version", + ); + process.exit(1); + } } else { - assertUnreachable(credentials.driver); + assertUnreachable(driver); } } const { preparePostgresDB } = await import('./connections'); @@ -256,15 +264,23 @@ export const push = command({ ); } else if (dialect === 'postgresql') { if ('driver' in credentials) { - if (credentials.driver === 'aws-data-api') { + const { driver } = credentials; + if (driver === 'aws-data-api') { if (!(await ormVersionGt('0.30.10'))) { console.log( "To use 'aws-data-api' driver - please update drizzle-orm to the latest version", ); process.exit(1); } + } else if (driver === 'pglite') { + if (!(await ormVersionGt('0.30.6'))) { + console.log( + "To use 'pglite' driver - please update drizzle-orm to the latest version", + ); + process.exit(1); + } } else { - assertUnreachable(credentials.driver); + assertUnreachable(driver); } } @@ -417,15 +433,23 @@ export const pull = command({ try { if (dialect === 'postgresql') { if ('driver' in credentials) { - if (credentials.driver === 'aws-data-api') { + const { driver } = credentials; + if (driver === 'aws-data-api') { if (!(await ormVersionGt('0.30.10'))) { console.log( "To use 'aws-data-api' driver - please update drizzle-orm to the latest version", ); process.exit(1); } + } else if (driver === 'pglite') { + if (!(await ormVersionGt('0.30.6'))) { + console.log( + "To use 'pglite' driver - please update drizzle-orm to the latest version", + ); + process.exit(1); + } } else { - assertUnreachable(credentials.driver); + assertUnreachable(driver); } } @@ -525,15 +549,23 @@ export const studio = command({ try { if (dialect === 'postgresql') { if ('driver' in credentials) { - if (credentials.driver === 'aws-data-api') { + const { driver } = credentials; + if (driver === 'aws-data-api') { if (!(await ormVersionGt('0.30.10'))) { console.log( "To use 'aws-data-api' driver - please update drizzle-orm to the latest version", ); process.exit(1); } + } else if (driver === 'pglite') { + if (!(await ormVersionGt('0.30.6'))) { + console.log( + "To use 'pglite' driver - please update drizzle-orm to the latest version", + ); + process.exit(1); + } } else { - assertUnreachable(credentials.driver); + assertUnreachable(driver); } } diff --git a/drizzle-kit/src/cli/validations/cli.ts b/drizzle-kit/src/cli/validations/cli.ts index 67e118a98..c4bbbe530 100644 --- a/drizzle-kit/src/cli/validations/cli.ts +++ b/drizzle-kit/src/cli/validations/cli.ts @@ -38,9 +38,9 @@ export const pullParams = object({ .optional() .default(['public']), extensionsFilters: literal('postgis').array().optional(), - introspectCasing: casing, + casing, breakpoints: boolean().optional().default(true), - database: object({ + migrations: object({ prefix: prefix.optional().default('index'), }).optional(), }).passthrough(); diff --git a/drizzle-kit/src/cli/validations/common.ts b/drizzle-kit/src/cli/validations/common.ts index e800afbc5..a7307f4d6 100644 --- a/drizzle-kit/src/cli/validations/common.ts +++ b/drizzle-kit/src/cli/validations/common.ts @@ -66,6 +66,11 @@ export const sqliteDriversLiterals = [ literal('expo'), ] as const; +export const postgresqlDriversLiterals = [ + literal('aws-data-api'), + literal('pglite'), +] as const; + export const prefixes = [ 'index', 'timestamp', @@ -81,7 +86,7 @@ export type Prefix = (typeof prefixes)[number]; } export const sqliteDriver = union(sqliteDriversLiterals); -export const postgresDriver = literal('aws-data-api'); +export const postgresDriver = union(postgresqlDriversLiterals); export const driver = union([sqliteDriver, postgresDriver]); export const configMigrations = object({ @@ -151,7 +156,7 @@ export const configPushSchema = object({ }); export type CliConfig = TypeOf; -export const drivers = ['turso', 'd1-http', 'expo', 'aws-data-api'] as const; +export const drivers = ['turso', 'd1-http', 'expo', 'aws-data-api', 'pglite'] as const; export type Driver = (typeof drivers)[number]; const _: Driver = '' as TypeOf; diff --git a/drizzle-kit/src/cli/validations/postgres.ts b/drizzle-kit/src/cli/validations/postgres.ts index 3dd02b4f3..658760c61 100644 --- a/drizzle-kit/src/cli/validations/postgres.ts +++ b/drizzle-kit/src/cli/validations/postgres.ts @@ -35,6 +35,10 @@ export const postgresCredentials = union([ secretArn: string().min(1), resourceArn: string().min(1), }), + object({ + driver: literal('pglite'), + url: string().min(1), + }), ]); export type PostgresCredentials = TypeOf; diff --git a/drizzle-kit/src/index.ts b/drizzle-kit/src/index.ts index b99ac204a..5da4cb7b4 100644 --- a/drizzle-kit/src/index.ts +++ b/drizzle-kit/src/index.ts @@ -40,7 +40,7 @@ type Verify = U; * * --- * `driver` - optional param that is responsible for explicitly providing a driver to use when accessing a database - * *Possible values*: `aws-data-api`, `d1-http`, `expo`, `turso` + * *Possible values*: `aws-data-api`, `d1-http`, `expo`, `turso`, `pglite` * If you don't use AWS Data API, D1, Turso or Expo - ypu don't need this driver. You can check a driver strategy choice here: https://orm.drizzle.team/kit-docs/upgrade-21 * * See https://orm.drizzle.team/kit-docs/config-reference#driver @@ -136,7 +136,7 @@ export type Config = }; } | { - dialect: 'sqlite'; + dialect: Verify; dbCredentials: { url: string; }; @@ -171,6 +171,13 @@ export type Config = resourceArn: string; }; } + | { + dialect: Verify; + driver: Verify; + dbCredentials: { + url: string; + }; + } | { dialect: Verify; dbCredentials: @@ -241,7 +248,7 @@ export type Config = * * --- * `driver` - optional param that is responsible for explicitly providing a driver to use when accessing a database - * *Possible values*: `aws-data-api`, `d1-http`, `expo`, `turso` + * *Possible values*: `aws-data-api`, `d1-http`, `expo`, `turso`, `pglite` * If you don't use AWS Data API, D1, Turso or Expo - ypu don't need this driver. You can check a driver strategy choice here: https://orm.drizzle.team/kit-docs/upgrade-21 * * See https://orm.drizzle.team/kit-docs/config-reference#driver diff --git a/drizzle-kit/src/introspect-mysql.ts b/drizzle-kit/src/introspect-mysql.ts index 21be79654..f206935a3 100644 --- a/drizzle-kit/src/introspect-mysql.ts +++ b/drizzle-kit/src/introspect-mysql.ts @@ -101,15 +101,22 @@ const importsPatch = { const relations = new Set(); +const escapeColumnKey = (value: string) => { + if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) { + return `"${value}"`; + } + return value; +}; + const prepareCasing = (casing?: Casing) => (value: string) => { - if (typeof casing === 'undefined') { - return value; + if (casing === 'preserve') { + return escapeColumnKey(value); } if (casing === 'camel') { - return value.camelCase(); + return escapeColumnKey(value.camelCase()); } - return value; + return escapeColumnKey(value); }; export const schemaToTypeScript = ( diff --git a/drizzle-kit/src/introspect-pg.ts b/drizzle-kit/src/introspect-pg.ts index d20a96562..b7a52b735 100644 --- a/drizzle-kit/src/introspect-pg.ts +++ b/drizzle-kit/src/introspect-pg.ts @@ -140,6 +140,14 @@ const intervalConfig = (str: string) => { return statement; }; +const mapColumnDefault = (defaultValue: any, isExpression?: boolean) => { + if (isExpression) { + return `sql\`${defaultValue}\``; + } + + return defaultValue; +}; + const importsPatch = { 'double precision': 'doublePrecision', 'timestamp without time zone': 'timestamp', @@ -150,12 +158,19 @@ const importsPatch = { const relations = new Set(); +const escapeColumnKey = (value: string) => { + if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) { + return `"${value}"`; + } + return value; +}; + const withCasing = (value: string, casing: Casing) => { if (casing === 'preserve') { - return value; + return escapeColumnKey(value); } if (casing === 'camel') { - return value.camelCase(); + return escapeColumnKey(value.camelCase()); } assertUnreachable(casing); @@ -267,6 +282,33 @@ export const relationsToTypeScriptForStudio = ( return result; }; +function generateIdentityParams(identity: Column['identity']) { + let paramsObj = `{ name: "${identity!.name}"`; + if (identity?.startWith) { + paramsObj += `, startWith: ${identity.startWith}`; + } + if (identity?.increment) { + paramsObj += `, increment: ${identity.increment}`; + } + if (identity?.minValue) { + paramsObj += `, minValue: ${identity.minValue}`; + } + if (identity?.maxValue) { + paramsObj += `, maxValue: ${identity.maxValue}`; + } + if (identity?.cache) { + paramsObj += `, cache: ${identity.cache}`; + } + if (identity?.cycle) { + paramsObj += `, cycle: true`; + } + paramsObj += ' }'; + if (identity?.type === 'always') { + return `.generatedAlwaysAsIdentity(${paramsObj})`; + } + return `.generatedByDefaultAsIdentity(${paramsObj})`; +} + export const paramNameFor = (name: string, schema?: string) => { const schemaSuffix = schema && schema !== 'public' ? `In${schema.capitalise()}` : ''; return `${name}${schemaSuffix}`; @@ -290,7 +332,13 @@ export const schemaToTypeScript = ( }), ); - const enumTypes = new Set(Object.values(schema.enums).map((it) => it.name)); + const enumTypes = Object.values(schema.enums).reduce( + (acc, cur) => { + acc.add(`${cur.schema}.${cur.name}`); + return acc; + }, + new Set(), + ); const imports = Object.values(schema.tables).reduce( (res, it) => { @@ -317,13 +365,10 @@ export const schemaToTypeScript = ( res.pg.push(...pkImports); res.pg.push(...uniqueImports); - if (enumTypes.size > 0) { - res.pg.push('pgEnum'); - } - const columnImports = Object.values(it.columns) .map((col) => { - let patched: string = importsPatch[col.type] || col.type; + let patched: string = (importsPatch[col.type] || col.type).replace('[]', ''); + patched = patched === 'double precision' ? 'doublePrecision' : patched; patched = patched.startsWith('varchar(') ? 'varchar' : patched; patched = patched.startsWith('char(') ? 'char' : patched; patched = patched.startsWith('numeric(') ? 'numeric' : patched; @@ -343,6 +388,22 @@ export const schemaToTypeScript = ( { pg: [] as string[] }, ); + Object.values(schema.sequences).forEach((it) => { + if (it.schema && it.schema !== 'public' && it.schema !== '') { + imports.pg.push('pgSchema'); + } else if (it.schema === 'public') { + imports.pg.push('pgSequence'); + } + }); + + Object.values(schema.enums).forEach((it) => { + if (it.schema && it.schema !== 'public' && it.schema !== '') { + imports.pg.push('pgSchema'); + } else if (it.schema === 'public') { + imports.pg.push('pgEnum'); + } + }); + const enumStatements = Object.values(schema.enums) .map((it) => { const enumSchema = schemas[it.schema]; @@ -359,6 +420,43 @@ export const schemaToTypeScript = ( .join('') .concat('\n'); + const sequencesStatements = Object.values(schema.sequences) + .map((it) => { + const seqSchema = schemas[it.schema]; + const paramName = paramNameFor(it.name, seqSchema); + + const func = seqSchema ? `${seqSchema}.sequence` : 'pgSequence'; + + let params = ''; + + if (it.startWith) { + params += `, startWith: "${it.startWith}"`; + } + if (it.increment) { + params += `, increment: "${it.increment}"`; + } + if (it.minValue) { + params += `, minValue: "${it.minValue}"`; + } + if (it.maxValue) { + params += `, maxValue: "${it.maxValue}"`; + } + if (it.cache) { + params += `, cache: "${it.cache}"`; + } + if (it.cycle) { + params += `, cycle: true`; + } else { + params += `, cycle: false`; + } + + return `export const ${withCasing(paramName, casing)} = ${func}("${it.name}"${ + params ? `, { ${params.trimChar(',')} }` : '' + })\n`; + }) + .join('') + .concat('\n'); + const schemaStatements = Object.entries(schemas) // .filter((it) => it[0] !== "public") .map((it) => { @@ -384,13 +482,14 @@ export const schemaToTypeScript = ( statement += '}'; // more than 2 fields or self reference or cyclic - const filteredFKs = Object.values(table.foreignKeys).filter((it) => { - return it.columnsFrom.length > 1 || isSelf(it); - }); + // Andrii: I switched this one off until we will get custom names in .references() + // const filteredFKs = Object.values(table.foreignKeys).filter((it) => { + // return it.columnsFrom.length > 1 || isSelf(it); + // }); if ( Object.keys(table.indexes).length > 0 - || filteredFKs.length > 0 + || Object.values(table.foreignKeys).length > 0 || Object.keys(table.compositePrimaryKeys).length > 0 || Object.keys(table.uniqueConstraints).length > 0 ) { @@ -402,7 +501,7 @@ export const schemaToTypeScript = ( Object.values(table.indexes), casing, ); - statement += createTableFKs(Object.values(filteredFKs), schemas, casing); + statement += createTableFKs(Object.values(table.foreignKeys), schemas, casing); statement += createTablePKs( Object.values(table.compositePrimaryKeys), casing, @@ -430,6 +529,7 @@ export const schemaToTypeScript = ( let decalrations = schemaStatements; decalrations += enumStatements; + decalrations += sequencesStatements; decalrations += '\n'; decalrations += tableStatements.join('\n\n'); @@ -459,16 +559,211 @@ const isSelf = (fk: ForeignKey) => { return fk.tableFrom === fk.tableTo; }; +const buildArrayDefault = (defaultValue: string, typeName: string): string => { + if (typeof defaultValue === 'string' && !(defaultValue.startsWith('{') || defaultValue.startsWith("'{"))) { + return `sql\`${defaultValue}\``; + } + defaultValue = defaultValue.substring(2, defaultValue.length - 2); + return `[${ + defaultValue + .split(/\s*,\s*/g) + .map((value) => { + // if (['integer', 'smallint', 'bigint', 'double precision', 'real'].includes(typeName)) { + // return value; + // } else if (typeName === 'interval') { + // return value.replaceAll('"', "'"); + // } else if (typeName === 'boolean') { + // return value === 't' ? 'true' : 'false'; + if (typeName === 'json' || typeName === 'jsonb') { + return value + .substring(1, value.length - 1) + .replaceAll('\\', ''); + } + return value; + // } + }) + .join(', ') + }]`; +}; + +const mapDefault = ( + tableName: string, + type: string, + name: string, + enumTypes: Set, + typeSchema: string, + defaultValue?: any, + internals?: PgKitInternals, +) => { + const isExpression = internals?.tables[tableName]?.columns[name]?.isDefaultAnExpression ?? false; + const isArray = internals?.tables[tableName]?.columns[name]?.isArray ?? false; + const lowered = type.toLowerCase().replace('[]', ''); + + if (isArray) { + return typeof defaultValue !== 'undefined' ? `.default(${buildArrayDefault(defaultValue, lowered)})` : ''; + } + + if (enumTypes.has(`${typeSchema}.${type.replace('[]', '')}`)) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('integer')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('smallint')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('bigint')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('boolean')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('double precision')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('real')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('uuid')) { + return defaultValue === 'gen_random_uuid()' + ? '.defaultRandom()' + : defaultValue + ? `.default(sql\`${defaultValue}\`)` + : ''; + } + + if (lowered.startsWith('numeric')) { + defaultValue = defaultValue + ? defaultValue.startsWith(`'`) && defaultValue.endsWith(`'`) + ? defaultValue.substring(1, defaultValue.length - 1) + : defaultValue + : undefined; + return defaultValue ? `.default('${mapColumnDefault(defaultValue, isExpression)}')` : ''; + } + + if (lowered.startsWith('timestamp')) { + return defaultValue === 'now()' + ? '.defaultNow()' + : defaultValue === 'CURRENT_TIMESTAMP' + ? '.default(sql\`CURRENT_TIMESTAMP\`)' + : defaultValue + ? `.default(${mapColumnDefault(defaultValue, isExpression)})` + : ''; + } + + if (lowered.startsWith('time')) { + return defaultValue === 'now()' + ? '.defaultNow()' + : defaultValue + ? `.default(${mapColumnDefault(defaultValue, isExpression)})` + : ''; + } + + if (lowered.startsWith('interval')) { + return defaultValue ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered === 'date') { + return defaultValue === 'now()' + ? '.defaultNow()' + : defaultValue === 'CURRENT_DATE' + ? `.default(sql\`${defaultValue}\`)` + : defaultValue + ? `.default(${defaultValue})` + : ''; + } + + if (lowered.startsWith('text')) { + return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : ''; + } + + if (lowered.startsWith('jsonb')) { + const def = typeof defaultValue !== 'undefined' + ? defaultValue.replace(/::(.*?)(?, + typeSchema: string, casing: Casing, defaultValue?: any, internals?: PgKitInternals, ) => { - const lowered = type.toLowerCase(); + const isExpression = internals?.tables[tableName]?.columns[name]?.isDefaultAnExpression ?? false; + const lowered = type.toLowerCase().replace('[]', ''); + + if (enumTypes.has(`${typeSchema}.${type.replace('[]', '')}`)) { + let out = `${withCasing(name, casing)}: ${ + withCasing( + paramNameFor(type.replace('[]', ''), typeSchema), + casing, + ) + }("${name}")`; + return out; + } + if (lowered.startsWith('serial')) { return `${withCasing(name, casing)}: serial("${name}")`; } @@ -488,49 +783,38 @@ const column = ( if (lowered.startsWith('integer')) { let out = `${withCasing(name, casing)}: integer("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('smallint')) { let out = `${withCasing(name, casing)}: smallint("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('bigint')) { let out = `// You can use { mode: "bigint" } if numbers are exceeding js number limitations\n\t`; out += `${withCasing(name, casing)}: bigint("${name}", { mode: "number" })`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('boolean')) { let out = `${withCasing(name, casing)}: boolean("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('double precision')) { let out = `${withCasing(name, casing)}: doublePrecision("${name}")`; - out += defaultValue ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('real')) { let out = `${withCasing(name, casing)}: real("${name}")`; - out += defaultValue ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('uuid')) { let out = `${withCasing(name, casing)}: uuid("${name}")`; - out += defaultValue === 'gen_random_uuid()' - ? '.defaultRandom()' - : defaultValue - ? `.default(sql\`${defaultValue}\`)` - : ''; return out; } @@ -550,13 +834,6 @@ const column = ( ? `${withCasing(name, casing)}: numeric("${name}", ${timeConfig(params)})` : `${withCasing(name, casing)}: numeric("${name}")`; - defaultValue = defaultValue - ? defaultValue.startsWith(`'`) && defaultValue.endsWith(`'`) - ? defaultValue.substring(1, defaultValue.length - 1) - : defaultValue - : undefined; - out += defaultValue ? `.default('${defaultValue}')` : ''; - return out; } @@ -582,21 +859,6 @@ const column = ( ? `${withCasing(name, casing)}: timestamp("${name}", ${params})` : `${withCasing(name, casing)}: timestamp("${name}")`; - // defaultValue = defaultValue?.endsWith("::timestamp without time zone") - // ? defaultValue.substring(0, defaultValue.length - 29) - // : defaultValue; - - // defaultValue = defaultValue?.endsWith("::timestamp with time zone") - // ? defaultValue.substring(0, defaultValue.length - 26) - // : defaultValue; - - defaultValue = defaultValue === 'now()' || defaultValue === 'CURRENT_TIMESTAMP' - ? '.defaultNow()' - : defaultValue - ? `.default(${defaultValue})` - : ''; - - out += defaultValue; return out; } @@ -618,13 +880,6 @@ const column = ( ? `${withCasing(name, casing)}: time("${name}", ${params})` : `${withCasing(name, casing)}: time("${name}")`; - defaultValue = defaultValue === 'now()' - ? '.defaultNow()' - : defaultValue - ? `.default(${defaultValue})` - : ''; - - out += defaultValue; return out; } @@ -640,105 +895,51 @@ const column = ( ? `${withCasing(name, casing)}: interval("${name}", ${params})` : `${withCasing(name, casing)}: interval("${name}")`; - out += defaultValue ? `.default(${defaultValue})` : ''; return out; } if (lowered === 'date') { let out = `${withCasing(name, casing)}: date("${name}")`; - defaultValue = defaultValue === 'now()' - ? '.defaultNow()' - : defaultValue === 'CURRENT_DATE' - ? `.default(sql\`${defaultValue}\`)` - : defaultValue - ? `.default(${defaultValue})` - : ''; - - out += defaultValue; return out; } if (lowered.startsWith('text')) { let out = `${withCasing(name, casing)}: text("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } - if (lowered === 'json') { - let out = `${withCasing(name, casing)}: json("${name}")`; - // defaultValue = defaultValue?.replace("::json", ""); - - defaultValue = defaultValue?.endsWith('::json') - ? defaultValue.substring(1, defaultValue.length - 7) - : defaultValue; - // const def = defaultValue ? objToStatement(JSON.parse(defaultValue)) : null; - const def = defaultValue ? defaultValue : null; - - out += typeof defaultValue !== 'undefined' ? `.default(${def})` : ''; + if (lowered.startsWith('jsonb')) { + let out = `${withCasing(name, casing)}: jsonb("${name}")`; return out; } - if (lowered === 'jsonb') { - let out = `${withCasing(name, casing)}: jsonb("${name}")`; - - defaultValue = defaultValue?.endsWith('::jsonb') - ? defaultValue.substring(1, defaultValue.length - 8) - : defaultValue; - // const def = defaultValue ? objToStatement(JSON.parse(defaultValue)) : null; - const def = typeof defaultValue !== 'undefined' ? defaultValue : null; - - out += defaultValue ? `.default(${def})` : ''; + if (lowered.startsWith('json')) { + let out = `${withCasing(name, casing)}: json("${name}")`; return out; } if (lowered.startsWith('inet')) { let out = `${withCasing(name, casing)}: inet("${name}")`; - - // defaultValue = defaultValue?.endsWith("::inet") - // ? defaultValue.substring(0, defaultValue.length - 6) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('cidr')) { let out = `${withCasing(name, casing)}: cidr("${name}")`; - - // defaultValue = defaultValue?.endsWith("::cidr") - // ? defaultValue.substring(0, defaultValue.length - 6) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; - return out; - } - - if (lowered.startsWith('macaddr')) { - let out = `${withCasing(name, casing)}: macaddr("${name}")`; - - // defaultValue = defaultValue?.endsWith("::macaddr") - // ? defaultValue.substring(0, defaultValue.length - 9) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('macaddr8')) { let out = `${withCasing(name, casing)}: macaddr8("${name}")`; + return out; + } - // defaultValue = defaultValue?.endsWith("::macaddr8") - // ? defaultValue.substring(0, defaultValue.length - 10) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; + if (lowered.startsWith('macaddr')) { + let out = `${withCasing(name, casing)}: macaddr("${name}")`; return out; } if (lowered.startsWith('varchar')) { - const split = lowered.split(' '); - let out: string; if (lowered.length !== 7) { out = `${ @@ -756,25 +957,16 @@ const column = ( out = `${withCasing(name, casing)}: varchar("${name}")`; } - // defaultValue = defaultValue?.endsWith("::character varying") - // ? defaultValue.substring(0, defaultValue.length - 19) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('point')) { let out: string = `${withCasing(name, casing)}: point("${name}")`; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('line')) { let out: string = `${withCasing(name, casing)}: point("${name}")`; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } @@ -798,8 +990,6 @@ const column = ( out = `${withCasing(name, casing)}: geometry("${name}")`; } - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; - if (isGeoUnknown) { let unknown = `// TODO: failed to parse geometry type because found more than 2 options inside geometry function '${type}'\n// Introspect is currently supporting only type and srid options\n`; @@ -810,8 +1000,6 @@ const column = ( } if (lowered.startsWith('vector')) { - const split = lowered.split(' '); - let out: string; if (lowered.length !== 6) { out = `${ @@ -829,13 +1017,10 @@ const column = ( out = `${withCasing(name, casing)}: vector("${name}")`; } - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } if (lowered.startsWith('char')) { - // const split = lowered.split(" "); - let out: string; if (lowered.length !== 4) { out = `${ @@ -853,42 +1038,6 @@ const column = ( out = `${withCasing(name, casing)}: char("${name}")`; } - // defaultValue = defaultValue?.endsWith("::bpchar") - // ? defaultValue.substring(0, defaultValue.length - 8) - // : defaultValue; - - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; - return out; - } - - // if internal has this column - use it - const columnInternals = internals?.tables[tableName]?.columns[name]; - if (typeof columnInternals !== 'undefined') { - // it means there is enum as array case - if ( - columnInternals.isArray - && columnInternals.rawType - && enumTypes.has(columnInternals.rawType) - ) { - let out = `${withCasing(columnInternals.rawType, casing)}: ${ - withCasing( - columnInternals.rawType, - casing, - ) - }("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; - return out; - } - } - - if (enumTypes.has(type)) { - let out = `${withCasing(name, casing)}: ${ - withCasing( - type, - casing, - ) - }("${name}")`; - out += typeof defaultValue !== 'undefined' ? `.default(${defaultValue})` : ''; return out; } @@ -937,6 +1086,7 @@ const createTableColumns = ( it.type, it.name, enumTypes, + it.typeSchema ?? 'public', casing, it.default, internals, @@ -949,73 +1099,56 @@ const createTableColumns = ( internals?.tables[tableName]?.columns[it.name]?.dimensions, ); } + statement += mapDefault( + tableName, + it.type, + it.name, + enumTypes, + it.typeSchema ?? 'public', + it.default, + internals, + ); statement += it.primaryKey ? '.primaryKey()' : ''; statement += it.notNull && !it.identity ? '.notNull()' : ''; - function generateIdentityParams(identity: Column['identity']) { - let paramsObj = `{ name: "${identity!.name}"`; - if (identity?.startWith) { - paramsObj += `, startWith: ${identity.startWith}`; - } - if (identity?.increment) { - paramsObj += `, increment: ${identity.increment}`; - } - if (identity?.minValue) { - paramsObj += `, minValue: ${identity.minValue}`; - } - if (identity?.maxValue) { - paramsObj += `, maxValue: ${identity.maxValue}`; - } - if (identity?.cache) { - paramsObj += `, cache: ${identity.cache}`; - } - if (identity?.cycle) { - paramsObj += `, cycle: true`; - } - paramsObj += ' }'; - if (identity?.type === 'always') { - return `.generatedAlwaysAsIdentity(${paramsObj})`; - } - return `.generatedByDefaultAsIdentity(${paramsObj})`; - } - statement += it.identity ? generateIdentityParams(it.identity) : ''; statement += it.generated ? `.generatedAlwaysAs(sql\`${it.generated.as}\`)` : ''; - const fks = fkByColumnName[it.name]; - if (fks) { - const fksStatement = fks - .map((it) => { - const onDelete = it.onDelete && it.onDelete !== 'no action' ? it.onDelete : null; - const onUpdate = it.onUpdate && it.onUpdate !== 'no action' ? it.onUpdate : null; - const params = { onDelete, onUpdate }; - - const typeSuffix = isCyclic(it) ? ': AnyPgColumn' : ''; - - const paramsStr = objToStatement2(params); - const tableSchema = schemas[it.schemaTo || '']; - const paramName = paramNameFor(it.tableTo, tableSchema); - if (paramsStr) { - return `.references(()${typeSuffix} => ${ - withCasing( - paramName, - casing, - ) - }.${withCasing(it.columnsTo[0], casing)}, ${paramsStr} )`; - } - return `.references(()${typeSuffix} => ${ - withCasing( - paramName, - casing, - ) - }.${withCasing(it.columnsTo[0], casing)})`; - }) - .join(''); - statement += fksStatement; - } + // const fks = fkByColumnName[it.name]; + // Andrii: I switched it off until we will get a custom naem setting in references + // if (fks) { + // const fksStatement = fks + // .map((it) => { + // const onDelete = it.onDelete && it.onDelete !== 'no action' ? it.onDelete : null; + // const onUpdate = it.onUpdate && it.onUpdate !== 'no action' ? it.onUpdate : null; + // const params = { onDelete, onUpdate }; + + // const typeSuffix = isCyclic(it) ? ': AnyPgColumn' : ''; + + // const paramsStr = objToStatement2(params); + // const tableSchema = schemas[it.schemaTo || '']; + // const paramName = paramNameFor(it.tableTo, tableSchema); + // if (paramsStr) { + // return `.references(()${typeSuffix} => ${ + // withCasing( + // paramName, + // casing, + // ) + // }.${withCasing(it.columnsTo[0], casing)}, ${paramsStr} )`; + // } + // return `.references(()${typeSuffix} => ${ + // withCasing( + // paramName, + // casing, + // ) + // }.${withCasing(it.columnsTo[0], casing)})`; + // }) + // .join(''); + // statement += fksStatement; + // } statement += ',\n'; }); @@ -1058,7 +1191,9 @@ const createTableIndexes = ( if (it.isExpression) { return `sql\`${it.expression}\``; } else { - return `table.${withCasing(it.expression, casing)}${ + return `table.${withCasing(it.expression, casing)}${it.asc ? '.asc()' : '.desc()'}${ + it.nulls === 'first' ? '.nullsFirst()' : '.nullsLast()' + }${ it.opclass && vectorOps.includes(it.opclass) ? `.op("${it.opclass}")` : '' diff --git a/drizzle-kit/src/introspect-sqlite.ts b/drizzle-kit/src/introspect-sqlite.ts index 9ff119ce6..b4a729f4c 100644 --- a/drizzle-kit/src/introspect-sqlite.ts +++ b/drizzle-kit/src/introspect-sqlite.ts @@ -38,12 +38,19 @@ const objToStatement2 = (json: any) => { const relations = new Set(); +const escapeColumnKey = (value: string) => { + if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) { + return `"${value}"`; + } + return value; +}; + const withCasing = (value: string, casing?: Casing) => { - if (typeof casing === 'undefined') { - return value; + if (casing === 'preserve') { + return escapeColumnKey(value); } if (casing === 'camel') { - return value.camelCase(); + return escapeColumnKey(value.camelCase()); } return value; diff --git a/drizzle-kit/src/serializer/pgSchema.ts b/drizzle-kit/src/serializer/pgSchema.ts index 7e4a55afd..5860a6fef 100644 --- a/drizzle-kit/src/serializer/pgSchema.ts +++ b/drizzle-kit/src/serializer/pgSchema.ts @@ -1,3 +1,4 @@ +import { vectorOps } from 'src/extensions/vector'; import { mapValues, originUUID, snapshotVersion } from '../global'; import { any, array, boolean, enum as enumType, literal, number, object, record, string, TypeOf, union } from 'zod'; @@ -282,6 +283,7 @@ export const kitInternals = object({ isArray: boolean().optional(), dimensions: number().optional(), rawType: string().optional(), + isDefaultAnExpression: boolean().optional(), }).optional(), ), }).optional(), @@ -464,7 +466,10 @@ export const PgSquasher = { return `${idx.name};${ idx.columns .map( - (c) => `${c.expression}--${c.isExpression}--${c.asc}--${c.nulls}--${c.opclass}`, + (c) => + `${c.expression}--${c.isExpression}--${c.asc}--${c.nulls}--${ + c.opclass && vectorOps.includes(c.opclass) ? c.opclass : '' + }`, ) .join(',,') };${idx.isUnique};${idx.concurrently};${idx.method};${idx.where};${JSON.stringify(idx.with)}`; diff --git a/drizzle-kit/src/serializer/pgSerializer.ts b/drizzle-kit/src/serializer/pgSerializer.ts index 6470cf1ff..b479e59e2 100644 --- a/drizzle-kit/src/serializer/pgSerializer.ts +++ b/drizzle-kit/src/serializer/pgSerializer.ts @@ -269,7 +269,7 @@ export const generatePgSnapshot = ( column.default, sqlTypeLowered, ) - }'::${sqlTypeLowered}`; + }'`; } else { // Should do for all types // columnToSet.default = `'${column.default}'::${sqlTypeLowered}`; @@ -739,7 +739,7 @@ export const fromDatabase = async ( WHEN 'int2'::regtype THEN 'smallserial' END ELSE format_type(a.atttypid, a.atttypmod) - END AS data_type, INFORMATION_SCHEMA.COLUMNS.table_name, + END AS data_type, INFORMATION_SCHEMA.COLUMNS.table_name, ns.nspname as type_schema, pg_get_serial_sequence('"${tableSchema}"."${tableName}"', a.attname)::regclass as seq_name, INFORMATION_SCHEMA.COLUMNS.column_name, INFORMATION_SCHEMA.COLUMNS.column_default, INFORMATION_SCHEMA.COLUMNS.data_type as additional_dt, INFORMATION_SCHEMA.COLUMNS.udt_name as enum_name, @@ -750,6 +750,7 @@ export const fromDatabase = async ( INFORMATION_SCHEMA.COLUMNS.identity_cycle FROM pg_attribute a JOIN INFORMATION_SCHEMA.COLUMNS ON INFORMATION_SCHEMA.COLUMNS.column_name = a.attname + JOIN pg_type t ON t.oid = a.atttypid LEFT JOIN pg_namespace ns ON ns.oid = t.typnamespace WHERE a.attrelid = '"${tableSchema}"."${tableName}"'::regclass and INFORMATION_SCHEMA.COLUMNS.table_name = '${tableName}' and INFORMATION_SCHEMA.COLUMNS.table_schema = '${tableSchema}' AND a.attnum > 0 AND NOT a.attisdropped @@ -772,30 +773,42 @@ export const fromDatabase = async ( const tableForeignKeys = await db.query( `SELECT - tc.table_schema, - tc.constraint_name, - tc.table_name, - kcu.column_name, - ( - SELECT ccu.table_schema - FROM information_schema.constraint_column_usage ccu - WHERE ccu.constraint_name = tc.constraint_name - LIMIT 1 - ) AS foreign_table_schema, - ccu.table_name AS foreign_table_name, - ccu.column_name AS foreign_column_name, - rc.delete_rule, - rc.update_rule - FROM - information_schema.table_constraints AS tc - JOIN information_schema.key_column_usage AS kcu - ON tc.constraint_name = kcu.constraint_name - AND tc.table_schema = kcu.table_schema - JOIN information_schema.constraint_column_usage AS ccu - ON ccu.constraint_name = tc.constraint_name - JOIN information_schema.referential_constraints AS rc - ON ccu.constraint_name = rc.constraint_name - WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name='${tableName}' and tc.table_schema='${tableSchema}';`, + con.contype AS constraint_type, + nsp.nspname AS constraint_schema, + con.conname AS constraint_name, + rel.relname AS table_name, + att.attname AS column_name, + fnsp.nspname AS foreign_table_schema, + frel.relname AS foreign_table_name, + fatt.attname AS foreign_column_name, + CASE con.confupdtype + WHEN 'a' THEN 'NO ACTION' + WHEN 'r' THEN 'RESTRICT' + WHEN 'n' THEN 'SET NULL' + WHEN 'c' THEN 'CASCADE' + WHEN 'd' THEN 'SET DEFAULT' + END AS update_rule, + CASE con.confdeltype + WHEN 'a' THEN 'NO ACTION' + WHEN 'r' THEN 'RESTRICT' + WHEN 'n' THEN 'SET NULL' + WHEN 'c' THEN 'CASCADE' + WHEN 'd' THEN 'SET DEFAULT' + END AS delete_rule + FROM + pg_catalog.pg_constraint con + JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid + JOIN pg_catalog.pg_namespace nsp ON nsp.oid = con.connamespace + LEFT JOIN pg_catalog.pg_attribute att ON att.attnum = ANY (con.conkey) + AND att.attrelid = con.conrelid + LEFT JOIN pg_catalog.pg_class frel ON frel.oid = con.confrelid + LEFT JOIN pg_catalog.pg_namespace fnsp ON fnsp.oid = frel.relnamespace + LEFT JOIN pg_catalog.pg_attribute fatt ON fatt.attnum = ANY (con.confkey) + AND fatt.attrelid = con.confrelid + WHERE + nsp.nspname = '${tableSchema}' + AND rel.relname = '${tableName}' + AND con.contype IN ('f');`, ); foreignKeysCount += tableForeignKeys.length; @@ -809,8 +822,8 @@ export const fromDatabase = async ( const columnTo: string = fk.foreign_column_name; const schemaTo: string = fk.foreign_table_schema; const foreignKeyName = fk.constraint_name; - const onUpdate = fk.update_rule.toLowerCase(); - const onDelete = fk.delete_rule.toLowerCase(); + const onUpdate = fk.update_rule?.toLowerCase(); + const onDelete = fk.delete_rule?.toLowerCase(); if (typeof foreignKeysToReturn[foreignKeyName] !== 'undefined') { foreignKeysToReturn[foreignKeyName].columnsFrom.push(columnFrom); @@ -863,6 +876,8 @@ export const fromDatabase = async ( const columnDimensions = columnResponse.array_dimensions; const enumType: string = columnResponse.enum_name; let columnType: string = columnResponse.data_type; + const typeSchema = columnResponse.type_schema; + const defaultValueRes: string = columnResponse.column_default; const isGenerated = columnResponse.is_generated === 'ALWAYS'; const generationExpression = columnResponse.generation_expression; @@ -902,16 +917,8 @@ export const fromDatabase = async ( }; } - const defaultValue = defaultForColumn(columnResponse); - - const isSerial = columnType === 'serial'; - let columnTypeMapped = columnType; - if (columnTypeMapped.startsWith('numeric(')) { - columnTypeMapped = columnTypeMapped.replace(',', ', '); - } - // Set default to internal object if (columnAdditionalDT === 'ARRAY') { if (typeof internals.tables[tableName] === 'undefined') { @@ -944,6 +951,45 @@ export const fromDatabase = async ( } } + const defaultValue = defaultForColumn( + columnResponse, + internals, + tableName, + ); + if ( + defaultValue === 'NULL' + || (defaultValueRes && defaultValueRes.startsWith('(') && defaultValueRes.endsWith(')')) + ) { + if (typeof internals!.tables![tableName] === 'undefined') { + internals!.tables![tableName] = { + columns: { + [columnName]: { + isDefaultAnExpression: true, + }, + }, + }; + } else { + if ( + typeof internals!.tables![tableName]!.columns[columnName] + === 'undefined' + ) { + internals!.tables![tableName]!.columns[columnName] = { + isDefaultAnExpression: true, + }; + } else { + internals!.tables![tableName]!.columns[ + columnName + ]!.isDefaultAnExpression = true; + } + } + } + + const isSerial = columnType === 'serial'; + + if (columnTypeMapped.startsWith('numeric(')) { + columnTypeMapped = columnTypeMapped.replace(',', ', '); + } + if (columnAdditionalDT === 'ARRAY') { for (let i = 1; i < Number(columnDimensions); i++) { columnTypeMapped += '[]'; @@ -966,8 +1012,8 @@ export const fromDatabase = async ( && !['vector', 'geometry'].includes(enumType) ? enumType : columnTypeMapped, - typeSchema: enumsToReturn[`${tableSchema}.${enumType}`] !== undefined - ? enumsToReturn[`${tableSchema}.${enumType}`].schema + typeSchema: enumsToReturn[`${typeSchema}.${enumType}`] !== undefined + ? enumsToReturn[`${typeSchema}.${enumType}`].schema : undefined, primaryKey: primaryKey.length === 1 && cprimaryKey.length < 2, // default: isSerial ? undefined : defaultValue, @@ -995,7 +1041,12 @@ export const fromDatabase = async ( }; if (identityName) { - delete sequencesToReturn[`${tableSchema}.${identityName}`]; + // remove "" from sequence name + delete sequencesToReturn[ + `${tableSchema}.${ + identityName.startsWith('"') && identityName.endsWith('"') ? identityName.slice(1, -1) : identityName + }` + ]; delete sequencesToReturn[identityName]; } @@ -1170,29 +1221,10 @@ export const fromDatabase = async ( }; }; -const columnToDefault: Record = { - 'numeric(': '::numeric', - // text: "::text", - // "character varying": "::character varying", - // "double precision": "::double precision", - // "time with time zone": "::time with time zone", - 'time without time zone': '::time without time zone', - // "timestamp with time zone": "::timestamp with time zone", - 'timestamp without time zone': '::timestamp without time zone', - 'timestamp(': '::timestamp without time zone', - // date: "::date", - // interval: "::interval", - // character: "::bpchar", - // macaddr8: "::macaddr8", - // macaddr: "::macaddr", - // inet: "::inet", - // cidr: "::cidr", - // jsonb: "::jsonb", - // json: "::json", - 'character(': '::bpchar', -}; +const defaultForColumn = (column: any, internals: PgKitInternals, tableName: string) => { + const columnName = column.attname; + const isArray = internals?.tables[tableName]?.columns[columnName]?.isArray ?? false; -const defaultForColumn = (column: any) => { if (column.column_default === null) { return undefined; } @@ -1205,54 +1237,81 @@ const defaultForColumn = (column: any) => { return undefined; } - const hasDifferentDefaultCast = Object.keys(columnToDefault).find((it) => column.data_type.startsWith(it)); + if (column.column_default.endsWith('[]')) { + column.column_default = column.column_default.slice(0, -2); + } + + // if ( + // !['integer', 'smallint', 'bigint', 'double precision', 'real'].includes(column.data_type) + // ) { + column.column_default = column.column_default.replace(/::(.*?)(? { + if (['integer', 'smallint', 'bigint', 'double precision', 'real'].includes(column.data_type.slice(0, -2))) { + return value; + } else if (column.data_type.startsWith('timestamp')) { + return `${value}`; + } else if (column.data_type.slice(0, -2) === 'interval') { + return value.replaceAll('"', `\"`); + } else if (column.data_type.slice(0, -2) === 'boolean') { + return value === 't' ? 'true' : 'false'; + } else if (['json', 'jsonb'].includes(column.data_type.slice(0, -2))) { + return JSON.stringify(JSON.stringify(JSON.parse(JSON.parse(value)), null, 0)); + } else { + return `\"${value}\"`; + } + }) + .join(',') + }}'`; + } + if ( - columnDefaultAsString.endsWith( - hasDifferentDefaultCast - ? columnToDefault[hasDifferentDefaultCast] - : (column.data_type as string), - ) + ['integer', 'smallint', 'bigint', 'double precision', 'real'].includes(column.data_type) ) { - const nonPrefixPart = column.column_default.length - - (hasDifferentDefaultCast - ? columnToDefault[hasDifferentDefaultCast] - : `::${column.data_type as string}`).length - - 1; - - const rt = column.column_default - .toString() - .substring(1, nonPrefixPart) as string; - - if ( - /^-?[\d.]+(?:e-?\d+)?$/.test(rt) - && !column.data_type.startsWith('numeric') - ) { - return Number(rt); - } else if (column.data_type === 'json' || column.data_type === 'jsonb') { - const jsonWithoutSpaces = JSON.stringify(JSON.parse(rt)); - return `'${jsonWithoutSpaces}'${ - hasDifferentDefaultCast - ? columnToDefault[hasDifferentDefaultCast] - : `::${column.data_type as string}` - }`; - } else if (column.data_type === 'boolean') { - return column.column_default === 'true'; - } else { - return `'${rt}'`; - } - } else { - if ( - /^-?[\d.]+(?:e-?\d+)?$/.test(columnDefaultAsString) - && !column.data_type.startsWith('numeric') - ) { + if (/^-?[\d.]+(?:e-?\d+)?$/.test(columnDefaultAsString)) { return Number(columnDefaultAsString); - } else if (column.data_type === 'boolean') { - return column.column_default === 'true'; } else { - return `${columnDefaultAsString}`; + if (typeof internals!.tables![tableName] === 'undefined') { + internals!.tables![tableName] = { + columns: { + [columnName]: { + isDefaultAnExpression: true, + }, + }, + }; + } else { + if ( + typeof internals!.tables![tableName]!.columns[columnName] + === 'undefined' + ) { + internals!.tables![tableName]!.columns[columnName] = { + isDefaultAnExpression: true, + }; + } else { + internals!.tables![tableName]!.columns[ + columnName + ]!.isDefaultAnExpression = true; + } + } + return columnDefaultAsString; } + } else if (column.data_type === 'json' || column.data_type === 'jsonb') { + const jsonWithoutSpaces = JSON.stringify(JSON.parse(columnDefaultAsString.slice(1, -1))); + return `'${jsonWithoutSpaces}'::${column.data_type}`; + } else if (column.data_type === 'boolean') { + return column.column_default === 'true'; + } else if (columnDefaultAsString === 'NULL') { + return `NULL`; + } else if (columnDefaultAsString.startsWith("'") && columnDefaultAsString.endsWith("'")) { + return columnDefaultAsString; + } else { + return `${columnDefaultAsString.replace(/\\/g, '\`\\')}`; } }; diff --git a/drizzle-kit/src/serializer/studio.ts b/drizzle-kit/src/serializer/studio.ts index c85950ad7..5515e6f59 100644 --- a/drizzle-kit/src/serializer/studio.ts +++ b/drizzle-kit/src/serializer/studio.ts @@ -50,7 +50,7 @@ type SchemaFile = { export type Setup = { dbHash: string; dialect: 'postgresql' | 'mysql' | 'sqlite' | 'singlestore'; - driver?: 'aws-data-api' | 'd1-http' | 'turso'; + driver?: 'aws-data-api' | 'd1-http' | 'turso' | 'pglite'; proxy: (params: ProxyParams) => Promise; customDefaults: CustomDefault[]; schema: Record>>; @@ -263,11 +263,13 @@ export const drizzleForPostgres = async ( let dbUrl: string; if ('driver' in credentials) { - // aws-data-api - if (credentials.driver === 'aws-data-api') { + const { driver } = credentials; + if (driver === 'aws-data-api') { dbUrl = `aws-data-api://${credentials.database}/${credentials.secretArn}/${credentials.resourceArn}`; + } else if (driver === 'pglite') { + dbUrl = credentials.url; } else { - assertUnreachable(credentials.driver); + assertUnreachable(driver); } } else if ('url' in credentials) { dbUrl = credentials.url; diff --git a/drizzle-kit/src/sqlgenerator.ts b/drizzle-kit/src/sqlgenerator.ts index be1f53bf7..07b24b6c9 100644 --- a/drizzle-kit/src/sqlgenerator.ts +++ b/drizzle-kit/src/sqlgenerator.ts @@ -106,6 +106,7 @@ const isPgNativeType = (it: string) => { || toCheck.startsWith('char(') || toCheck.startsWith('numeric(') || toCheck.startsWith('timestamp(') + || toCheck.startsWith('doubleprecision[') || toCheck.startsWith('intervalyear(') || toCheck.startsWith('intervalmonth(') || toCheck.startsWith('intervalday(') @@ -162,7 +163,7 @@ class PgCreateTableConvertor extends Convertor { : `${schemaPrefix}"${column.type}"`; const generated = column.generated; - const generatedStatement = ` GENERATED ALWAYS AS (${generated?.as}) STORED`; + const generatedStatement = generated ? ` GENERATED ALWAYS AS (${generated?.as}) STORED` : ''; const unsquashedIdentity = column.identity ? PgSquasher.unsquashIdentity(column.identity) @@ -197,9 +198,7 @@ class PgCreateTableConvertor extends Convertor { : ''; statement += '\t' - + `"${column.name}" ${type}${primaryKeyStatement}${defaultStatement}${notNullStatement}${uniqueConstraint}${ - generated ? generatedStatement : '' - }${identity}`; + + `"${column.name}" ${type}${primaryKeyStatement}${defaultStatement}${generatedStatement}${notNullStatement}${uniqueConstraint}${identity}`; statement += i === columns.length - 1 ? '' : ',\n'; } @@ -267,7 +266,7 @@ class MySqlCreateTableConvertor extends Convertor { : ''; statement += '\t' - + `\`${column.name}\` ${column.type}${autoincrementStatement}${primaryKeyStatement}${notNullStatement}${defaultStatement}${onUpdateStatement}${generatedStatement}`; + + `\`${column.name}\` ${column.type}${autoincrementStatement}${primaryKeyStatement}${generatedStatement}${notNullStatement}${defaultStatement}${onUpdateStatement}`; statement += i === columns.length - 1 ? '' : ',\n'; } @@ -414,7 +413,7 @@ export class SQLiteCreateTableConvertor extends Convertor { statement += '\t'; statement += - `\`${column.name}\` ${column.type}${primaryKeyStatement}${autoincrementStatement}${defaultStatement}${notNullStatement}${generatedStatement}`; + `\`${column.name}\` ${column.type}${primaryKeyStatement}${autoincrementStatement}${defaultStatement}${generatedStatement}${notNullStatement}`; statement += i === columns.length - 1 ? '' : ',\n'; } @@ -1115,11 +1114,9 @@ class PgAlterTableAddColumnConvertor extends Convertor { })` : ''; - const generatedStatement = ` GENERATED ALWAYS AS (${generated?.as}) STORED`; + const generatedStatement = generated ? ` GENERATED ALWAYS AS (${generated?.as}) STORED` : ''; - return `ALTER TABLE ${tableNameWithSchema} ADD COLUMN "${name}" ${fixedType}${primaryKeyStatement}${defaultStatement}${notNullStatement}${ - generated ? generatedStatement : '' - }${identityStatement};`; + return `ALTER TABLE ${tableNameWithSchema} ADD COLUMN "${name}" ${fixedType}${primaryKeyStatement}${defaultStatement}${generatedStatement}${notNullStatement}${identityStatement};`; } } @@ -1150,7 +1147,7 @@ class MySqlAlterTableAddColumnConvertor extends Convertor { ? ` GENERATED ALWAYS AS (${generated?.as}) ${generated?.type.toUpperCase()}` : ''; - return `ALTER TABLE \`${tableName}\` ADD \`${name}\` ${type}${primaryKeyStatement}${autoincrementStatement}${defaultStatement}${notNullStatement}${onUpdateStatement}${generatedStatement};`; + return `ALTER TABLE \`${tableName}\` ADD \`${name}\` ${type}${primaryKeyStatement}${autoincrementStatement}${defaultStatement}${generatedStatement}${notNullStatement}${onUpdateStatement};`; } } @@ -1212,7 +1209,7 @@ export class SQLiteAlterTableAddColumnConvertor extends Convertor { ? ` GENERATED ALWAYS AS ${generated.as} ${generated.type.toUpperCase()}` : ''; - return `ALTER TABLE \`${tableName}\` ADD \`${name}\` ${type}${primaryKeyStatement}${defaultStatement}${notNullStatement}${generatedStatement}${referenceStatement};`; + return `ALTER TABLE \`${tableName}\` ADD \`${name}\` ${type}${primaryKeyStatement}${defaultStatement}${generatedStatement}${notNullStatement}${referenceStatement};`; } } @@ -1909,7 +1906,7 @@ class MySqlModifyColumn extends Convertor { ? columnDefault.toISOString() : columnDefault; - return `ALTER TABLE \`${tableName}\` MODIFY COLUMN \`${columnName}\`${columnType}${columnAutoincrement}${columnNotNull}${columnDefault}${columnOnUpdate}${columnGenerated};`; + return `ALTER TABLE \`${tableName}\` MODIFY COLUMN \`${columnName}\`${columnType}${columnAutoincrement}${columnGenerated}${columnNotNull}${columnDefault}${columnOnUpdate};`; } } diff --git a/drizzle-kit/src/utils.ts b/drizzle-kit/src/utils.ts index 6a7faff45..7b363a9d3 100644 --- a/drizzle-kit/src/utils.ts +++ b/drizzle-kit/src/utils.ts @@ -328,6 +328,16 @@ export const normaliseSQLiteUrl = ( assertUnreachable(type); }; +export const normalisePGliteUrl = ( + it: string, +) => { + if (it.startsWith('file:')) { + return it.substring(5); + } + + return it; +}; + export function isPgArrayType(sqlType: string) { return sqlType.match(/.*\[\d*\].*|.*\[\].*/g) !== null; } diff --git a/drizzle-kit/tests/indexes/pg.test.ts b/drizzle-kit/tests/indexes/pg.test.ts index 8419fd765..9958a2356 100644 --- a/drizzle-kit/tests/indexes/pg.test.ts +++ b/drizzle-kit/tests/indexes/pg.test.ts @@ -125,12 +125,12 @@ const pgSuite: DialectSuite = { expect(sqlStatements).toStrictEqual([ 'DROP INDEX IF EXISTS "indx";', 'DROP INDEX IF EXISTS "indx1";', - 'DROP INDEX IF EXISTS "indx2";', + // 'DROP INDEX IF EXISTS "indx2";', 'DROP INDEX IF EXISTS "indx3";', 'CREATE INDEX IF NOT EXISTS "indx4" ON "users" USING btree (lower(id)) WHERE true;', 'CREATE INDEX IF NOT EXISTS "indx" ON "users" USING btree ("name" DESC NULLS LAST);', 'CREATE INDEX IF NOT EXISTS "indx1" ON "users" USING btree ("name" DESC NULLS LAST) WHERE false;', - 'CREATE INDEX IF NOT EXISTS "indx2" ON "users" USING btree ("name" test) WHERE true;', + // 'CREATE INDEX IF NOT EXISTS "indx2" ON "users" USING btree ("name" test) WHERE true;', 'CREATE INDEX IF NOT EXISTS "indx3" ON "users" USING btree (lower("id")) WHERE true;', ]); }, @@ -180,14 +180,14 @@ const pgSuite: DialectSuite = { expression: 'name', isExpression: false, nulls: 'last', - opclass: undefined, + opclass: '', }, { asc: true, expression: 'id', isExpression: false, nulls: 'last', - opclass: undefined, + opclass: '', }, ], concurrently: false, @@ -212,14 +212,14 @@ const pgSuite: DialectSuite = { expression: 'name', isExpression: false, nulls: 'last', - opclass: undefined, + opclass: '', }, { asc: true, expression: '"name"', isExpression: true, nulls: 'last', - opclass: undefined, + opclass: '', }, ], concurrently: false, diff --git a/drizzle-kit/tests/introspect/pg.test.ts b/drizzle-kit/tests/introspect/pg.test.ts index 40b06187f..e65c0f904 100644 --- a/drizzle-kit/tests/introspect/pg.test.ts +++ b/drizzle-kit/tests/introspect/pg.test.ts @@ -1,6 +1,34 @@ import { PGlite } from '@electric-sql/pglite'; import { SQL, sql } from 'drizzle-orm'; -import { integer, pgTable, text } from 'drizzle-orm/pg-core'; +import { + bigint, + bigserial, + boolean, + char, + cidr, + date, + doublePrecision, + inet, + integer, + interval, + json, + jsonb, + macaddr, + macaddr8, + numeric, + pgEnum, + pgSchema, + pgTable, + real, + serial, + smallint, + smallserial, + text, + time, + timestamp, + uuid, + varchar, +} from 'drizzle-orm/pg-core'; import { introspectPgToFile } from 'tests/schemaDiffer'; import { expect, test } from 'vitest'; @@ -186,3 +214,194 @@ test('generated column: link to another column', async () => { expect(statements.length).toBe(0); expect(sqlStatements.length).toBe(0); }); + +test('instrospect all column types', async () => { + const client = new PGlite(); + + const myEnum = pgEnum('my_enum', ['a', 'b', 'c']); + const schema = { + enum_: myEnum, + // NOTE: Types from extensions aren't tested due to PGlite not supporting at the moment + columns: pgTable('columns', { + enum: myEnum('my_enum').default('a'), + smallint: smallint('smallint').default(10), + integer: integer('integer').default(10), + numeric: numeric('numeric', { precision: 3, scale: 1 }).default('99.9'), + bigint: bigint('bigint', { mode: 'number' }).default(100), + boolean: boolean('boolean').default(true), + text: text('test').default('abc'), + varchar: varchar('varchar', { length: 25 }).default('abc'), + char: char('char', { length: 3 }).default('abc'), + serial: serial('serial'), + bigserial: bigserial('bigserial', { mode: 'number' }), + smallserial: smallserial('smallserial'), + doublePrecision: doublePrecision('doublePrecision').default(100), + real: real('real').default(100), + json: json('json').$type<{ attr: string }>().default({ attr: 'value' }), + jsonb: jsonb('jsonb').$type<{ attr: string }>().default({ attr: 'value' }), + time1: time('time1').default('00:00:00'), + time2: time('time2').defaultNow(), + timestamp1: timestamp('timestamp1', { withTimezone: true, precision: 6 }).default(new Date()), + timestamp2: timestamp('timestamp2', { withTimezone: true, precision: 6 }).defaultNow(), + date1: date('date1').default('2024-01-01'), + date2: date('date2').defaultNow(), + uuid1: uuid('uuid1').default('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'), + uuid2: uuid('uuid2').defaultRandom(), + inet: inet('inet').default('127.0.0.1'), + cidr: cidr('cidr').default('127.0.0.1/32'), + macaddr: macaddr('macaddr').default('00:00:00:00:00:00'), + macaddr8: macaddr8('macaddr8').default('00:00:00:ff:fe:00:00:00'), + interval: interval('interval').default('1 day 01:00:00'), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-all-columns-types', + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); + +test('instrospect all column array types', async () => { + const client = new PGlite(); + + const myEnum = pgEnum('my_enum', ['a', 'b', 'c']); + const schema = { + enum_: myEnum, + // NOTE: Types from extensions aren't tested due to PGlite not supporting at the moment + columns: pgTable('columns', { + enum: myEnum('my_enum').array().default(['a', 'b']), + smallint: smallint('smallint').array().default([10, 20]), + integer: integer('integer').array().default([10, 20]), + numeric: numeric('numeric', { precision: 3, scale: 1 }).array().default(['99.9', '88.8']), + bigint: bigint('bigint', { mode: 'number' }).array().default([100, 200]), + boolean: boolean('boolean').array().default([true, false]), + text: text('test').array().default(['abc', 'def']), + varchar: varchar('varchar', { length: 25 }).array().default(['abc', 'def']), + char: char('char', { length: 3 }).array().default(['abc', 'def']), + doublePrecision: doublePrecision('doublePrecision').array().default([100, 200]), + real: real('real').array().default([100, 200]), + json: json('json').$type<{ attr: string }>().array().default([{ attr: 'value1' }, { attr: 'value2' }]), + jsonb: jsonb('jsonb').$type<{ attr: string }>().array().default([{ attr: 'value1' }, { attr: 'value2' }]), + time: time('time').array().default(['00:00:00', '01:00:00']), + timestamp: timestamp('timestamp', { withTimezone: true, precision: 6 }) + .array() + .default([new Date(), new Date()]), + date: date('date').array().default(['2024-01-01', '2024-01-02']), + uuid: uuid('uuid').array().default([ + 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', + 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12', + ]), + inet: inet('inet').array().default(['127.0.0.1', '127.0.0.2']), + cidr: cidr('cidr').array().default(['127.0.0.1/32', '127.0.0.2/32']), + macaddr: macaddr('macaddr').array().default(['00:00:00:00:00:00', '00:00:00:00:00:01']), + macaddr8: macaddr8('macaddr8').array().default(['00:00:00:ff:fe:00:00:00', '00:00:00:ff:fe:00:00:01']), + interval: interval('interval').array().default(['1 day 01:00:00', '1 day 02:00:00']), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-all-columns-array-types', + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); + +test('introspect columns with name with non-alphanumeric characters', async () => { + const client = new PGlite(); + const schema = { + users: pgTable('users', { + 'not:allowed': integer('not:allowed'), + 'nuh--uh': integer('nuh-uh'), + '1_nope': integer('1_nope'), + valid: integer('valid'), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-column-with-name-with-non-alphanumeric-characters', + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); + +test('introspect enum from different schema', async () => { + const client = new PGlite(); + + const schema2 = pgSchema('schema2'); + const myEnumInSchema2 = schema2.enum('my_enum', ['a', 'b', 'c']); + const schema = { + schema2, + myEnumInSchema2, + users: pgTable('users', { + col: myEnumInSchema2('col'), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-enum-from-different-schema', + ['public', 'schema2'], + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); + +test('introspect enum with same names across different schema', async () => { + const client = new PGlite(); + + const schema2 = pgSchema('schema2'); + const myEnumInSchema2 = schema2.enum('my_enum', ['a', 'b', 'c']); + const myEnum = pgEnum('my_enum', ['a', 'b', 'c']); + const schema = { + schema2, + myEnumInSchema2, + myEnum, + users: pgTable('users', { + col1: myEnumInSchema2('col1'), + col2: myEnum('col2'), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-enum-with-same-names-across-different-schema', + ['public', 'schema2'], + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); + +test('introspect enum with similar name to native type', async () => { + const client = new PGlite(); + + const timeLeft = pgEnum('time_left', ['short', 'medium', 'long']); + const schema = { + timeLeft, + auction: pgTable('auction', { + col: timeLeft('col1'), + }), + }; + + const { statements, sqlStatements } = await introspectPgToFile( + client, + schema, + 'introspect-enum-with-similar-name-to-native-type', + ); + + expect(statements.length).toBe(0); + expect(sqlStatements.length).toBe(0); +}); diff --git a/drizzle-kit/tests/mysql-generated.test.ts b/drizzle-kit/tests/mysql-generated.test.ts index c7365f7e3..3531582d0 100644 --- a/drizzle-kit/tests/mysql-generated.test.ts +++ b/drizzle-kit/tests/mysql-generated.test.ts @@ -99,7 +99,7 @@ test('generated as callback: add generated constraint to an exisiting column as }, ]); expect(sqlStatements).toStrictEqual([ - "ALTER TABLE `users` MODIFY COLUMN `gen_name` text NOT NULL GENERATED ALWAYS AS (`users`.`name` || 'to add') STORED;", + "ALTER TABLE `users` MODIFY COLUMN `gen_name` text GENERATED ALWAYS AS (`users`.`name` || 'to add') STORED NOT NULL;", ]); }); @@ -151,7 +151,7 @@ test('generated as callback: add generated constraint to an exisiting column as ]); expect(sqlStatements).toStrictEqual([ 'ALTER TABLE `users` DROP COLUMN `gen_name`;', - "ALTER TABLE `users` ADD `gen_name` text NOT NULL GENERATED ALWAYS AS (`users`.`name` || 'to add') VIRTUAL;", + "ALTER TABLE `users` ADD `gen_name` text GENERATED ALWAYS AS (`users`.`name` || 'to add') VIRTUAL NOT NULL;", ]); }); @@ -530,7 +530,7 @@ test('generated as sql: add generated constraint to an exisiting column as store }, ]); expect(sqlStatements).toStrictEqual([ - "ALTER TABLE `users` MODIFY COLUMN `gen_name` text NOT NULL GENERATED ALWAYS AS (`users`.`name` || 'to add') STORED;", + "ALTER TABLE `users` MODIFY COLUMN `gen_name` text GENERATED ALWAYS AS (`users`.`name` || 'to add') STORED NOT NULL;", ]); }); @@ -582,7 +582,7 @@ test('generated as sql: add generated constraint to an exisiting column as virtu ]); expect(sqlStatements).toStrictEqual([ 'ALTER TABLE `users` DROP COLUMN `gen_name`;', - "ALTER TABLE `users` ADD `gen_name` text NOT NULL GENERATED ALWAYS AS (`users`.`name` || 'to add') VIRTUAL;", + "ALTER TABLE `users` ADD `gen_name` text GENERATED ALWAYS AS (`users`.`name` || 'to add') VIRTUAL NOT NULL;", ]); }); @@ -961,7 +961,7 @@ test('generated as string: add generated constraint to an exisiting column as st }, ]); expect(sqlStatements).toStrictEqual([ - "ALTER TABLE `users` MODIFY COLUMN `gen_name` text NOT NULL GENERATED ALWAYS AS (`users`.`name` || 'to add') STORED;", + "ALTER TABLE `users` MODIFY COLUMN `gen_name` text GENERATED ALWAYS AS (`users`.`name` || 'to add') STORED NOT NULL;", ]); }); @@ -1013,7 +1013,7 @@ test('generated as string: add generated constraint to an exisiting column as vi ]); expect(sqlStatements).toStrictEqual([ 'ALTER TABLE `users` DROP COLUMN `gen_name`;', - "ALTER TABLE `users` ADD `gen_name` text NOT NULL GENERATED ALWAYS AS (`users`.`name` || 'to add') VIRTUAL;", + "ALTER TABLE `users` ADD `gen_name` text GENERATED ALWAYS AS (`users`.`name` || 'to add') VIRTUAL NOT NULL;", ]); }); diff --git a/drizzle-kit/tests/pg-array.test.ts b/drizzle-kit/tests/pg-array.test.ts index a35411adb..e6c06d535 100644 --- a/drizzle-kit/tests/pg-array.test.ts +++ b/drizzle-kit/tests/pg-array.test.ts @@ -34,7 +34,7 @@ test('array #1: empty array default', async (t) => { type: 'alter_table_add_column', tableName: 'test', schema: '', - column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{}'::integer[]" }, + column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{}'" }, }); }); @@ -58,7 +58,7 @@ test('array #2: integer array default', async (t) => { type: 'alter_table_add_column', tableName: 'test', schema: '', - column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{1,2,3}'::integer[]" }, + column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{1,2,3}'" }, }); }); @@ -82,7 +82,7 @@ test('array #3: bigint array default', async (t) => { type: 'alter_table_add_column', tableName: 'test', schema: '', - column: { name: 'values', type: 'bigint[]', primaryKey: false, notNull: false, default: "'{1,2,3}'::bigint[]" }, + column: { name: 'values', type: 'bigint[]', primaryKey: false, notNull: false, default: "'{1,2,3}'" }, }); }); @@ -111,7 +111,7 @@ test('array #4: boolean array default', async (t) => { type: 'boolean[]', primaryKey: false, notNull: false, - default: "'{true,false,true}'::boolean[]", + default: "'{true,false,true}'", }, }); }); @@ -141,7 +141,7 @@ test('array #5: multi-dimensional array default', async (t) => { type: 'integer[][]', primaryKey: false, notNull: false, - default: "'{{1,2},{3,4}}'::integer[][]", + default: "'{{1,2},{3,4}}'", }, }); }); @@ -171,7 +171,7 @@ test('array #6: date array default', async (t) => { type: 'date[]', primaryKey: false, notNull: false, - default: '\'{"2024-08-06","2024-08-07"}\'::date[]', + default: '\'{"2024-08-06","2024-08-07"}\'', }, }); }); @@ -201,7 +201,7 @@ test('array #7: timestamp array default', async (t) => { type: 'timestamp[]', primaryKey: false, notNull: false, - default: '\'{"2024-08-06 00:00:00.000","2024-08-07 00:00:00.000"}\'::timestamp[]', + default: '\'{"2024-08-06 00:00:00.000","2024-08-07 00:00:00.000"}\'', }, }); }); @@ -231,7 +231,7 @@ test('array #8: json array default', async (t) => { type: 'json[]', primaryKey: false, notNull: false, - default: '\'{"{\\"a\\":1}","{\\"b\\":2}"}\'::json[]', + default: '\'{"{\\"a\\":1}","{\\"b\\":2}"}\'', }, }); }); @@ -261,7 +261,7 @@ test('array #9: text array default', async (t) => { type: 'text[]', primaryKey: false, notNull: false, - default: '\'{"abc","def"}\'::text[]', + default: '\'{"abc","def"}\'', }, }); }); @@ -294,7 +294,7 @@ test('array #10: uuid array default', async (t) => { type: 'uuid[]', primaryKey: false, notNull: false, - default: '\'{"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11","b0eebc99-9c0b-4ef8-bb6d-cbb9bd380a11"}\'::uuid[]', + default: '\'{"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11","b0eebc99-9c0b-4ef8-bb6d-cbb9bd380a11"}\'', }, }); }); @@ -328,7 +328,7 @@ test('array #11: enum array default', async (t) => { type: 'test_enum[]', primaryKey: false, notNull: false, - default: '\'{"a","b","c"}\'::test_enum[]', + default: '\'{"a","b","c"}\'', }, }); }); @@ -362,7 +362,7 @@ test('array #12: enum empty array default', async (t) => { type: 'test_enum[]', primaryKey: false, notNull: false, - default: "'{}'::test_enum[]", + default: "'{}'", }, }); }); diff --git a/drizzle-kit/tests/pg-generated.test.ts b/drizzle-kit/tests/pg-generated.test.ts index 2f7f58491..e9f294891 100644 --- a/drizzle-kit/tests/pg-generated.test.ts +++ b/drizzle-kit/tests/pg-generated.test.ts @@ -87,7 +87,7 @@ test('generated as callback: add generated constraint to an exisiting column', a ]); expect(sqlStatements).toStrictEqual([ 'ALTER TABLE "users" drop column "gen_name";', - 'ALTER TABLE "users" ADD COLUMN "gen_name" text NOT NULL GENERATED ALWAYS AS ("users"."name" || \'to add\') STORED;', + 'ALTER TABLE "users" ADD COLUMN "gen_name" text GENERATED ALWAYS AS ("users"."name" || \'to add\') STORED NOT NULL;', ]); }); @@ -262,7 +262,7 @@ test('generated as sql: add generated constraint to an exisiting column', async ]); expect(sqlStatements).toStrictEqual([ 'ALTER TABLE "users" drop column "gen_name";', - 'ALTER TABLE "users" ADD COLUMN "gen_name" text NOT NULL GENERATED ALWAYS AS ("users"."name" || \'to add\') STORED;', + 'ALTER TABLE "users" ADD COLUMN "gen_name" text GENERATED ALWAYS AS ("users"."name" || \'to add\') STORED NOT NULL;', ]); }); @@ -437,7 +437,7 @@ test('generated as string: add generated constraint to an exisiting column', asy ]); expect(sqlStatements).toStrictEqual([ 'ALTER TABLE "users" drop column "gen_name";', - 'ALTER TABLE "users" ADD COLUMN "gen_name" text NOT NULL GENERATED ALWAYS AS ("users"."name" || \'to add\') STORED;', + 'ALTER TABLE "users" ADD COLUMN "gen_name" text GENERATED ALWAYS AS ("users"."name" || \'to add\') STORED NOT NULL;', ]); }); diff --git a/drizzle-kit/tests/push/pg.test.ts b/drizzle-kit/tests/push/pg.test.ts index cd5908bad..cb1a97122 100644 --- a/drizzle-kit/tests/push/pg.test.ts +++ b/drizzle-kit/tests/push/pg.test.ts @@ -2192,11 +2192,11 @@ test('add array column - empty array default', async () => { type: 'alter_table_add_column', tableName: 'test', schema: '', - column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{}'::integer[]" }, + column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{}'" }, }, ]); expect(sqlStatements).toStrictEqual([ - 'ALTER TABLE "test" ADD COLUMN "values" integer[] DEFAULT \'{}\'::integer[];', + 'ALTER TABLE "test" ADD COLUMN "values" integer[] DEFAULT \'{}\';', ]); }); @@ -2229,10 +2229,10 @@ test('add array column - default', async () => { type: 'alter_table_add_column', tableName: 'test', schema: '', - column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{1,2,3}'::integer[]" }, + column: { name: 'values', type: 'integer[]', primaryKey: false, notNull: false, default: "'{1,2,3}'" }, }, ]); expect(sqlStatements).toStrictEqual([ - 'ALTER TABLE "test" ADD COLUMN "values" integer[] DEFAULT \'{1,2,3}\'::integer[];', + 'ALTER TABLE "test" ADD COLUMN "values" integer[] DEFAULT \'{1,2,3}\';', ]); }); diff --git a/drizzle-kit/tests/sqlite-generated.test.ts b/drizzle-kit/tests/sqlite-generated.test.ts index 3e1129be4..749dde825 100644 --- a/drizzle-kit/tests/sqlite-generated.test.ts +++ b/drizzle-kit/tests/sqlite-generated.test.ts @@ -171,7 +171,7 @@ test('generated as callback: add generated constraint to an exisiting column as ]); expect(sqlStatements).toStrictEqual([ 'ALTER TABLE `users` DROP COLUMN `gen_name`;', - 'ALTER TABLE `users` ADD `gen_name` text NOT NULL GENERATED ALWAYS AS ("name" || \'to add\') VIRTUAL;', + 'ALTER TABLE `users` ADD `gen_name` text GENERATED ALWAYS AS ("name" || \'to add\') VIRTUAL NOT NULL;', ]); }); @@ -744,7 +744,7 @@ test('generated as sql: add generated constraint to an exisiting column as virtu ]); expect(sqlStatements).toStrictEqual([ 'ALTER TABLE `users` DROP COLUMN `gen_name`;', - 'ALTER TABLE `users` ADD `gen_name` text NOT NULL GENERATED ALWAYS AS ("users"."name" || \'to add\') VIRTUAL;', + 'ALTER TABLE `users` ADD `gen_name` text GENERATED ALWAYS AS ("users"."name" || \'to add\') VIRTUAL NOT NULL;', ]); }); @@ -1312,7 +1312,7 @@ test('generated as string: add generated constraint to an exisiting column as vi ]); expect(sqlStatements).toStrictEqual([ 'ALTER TABLE `users` DROP COLUMN `gen_name`;', - 'ALTER TABLE `users` ADD `gen_name` text NOT NULL GENERATED ALWAYS AS ("users"."name" || \'to add\') VIRTUAL;', + 'ALTER TABLE `users` ADD `gen_name` text GENERATED ALWAYS AS ("users"."name" || \'to add\') VIRTUAL NOT NULL;', ]); }); diff --git a/drizzle-kit/tests/validations.test.ts b/drizzle-kit/tests/validations.test.ts index b56603fb4..8a64603bb 100644 --- a/drizzle-kit/tests/validations.test.ts +++ b/drizzle-kit/tests/validations.test.ts @@ -271,6 +271,38 @@ test('AWS Data API #8', () => { }).toThrowError(); }); +test('PGlite #1', () => { + expect( + postgresCredentials.parse({ + dialect: 'postgres', + driver: 'pglite', + url: './my.db', + }), + ).toStrictEqual({ + driver: 'pglite', + url: './my.db', + }); +}); + +test('PGlite #2', () => { + expect(() => { + postgresCredentials.parse({ + dialect: 'postgres', + driver: 'pglite', + url: '', + }); + }).toThrowError(); +}); + +test('PGlite #3', () => { + expect(() => { + postgresCredentials.parse({ + dialect: 'postgres', + driver: 'pglite', + }); + }).toThrowError(); +}); + test('postgres #1', () => { expect( postgresCredentials.parse({ diff --git a/integration-tests/tests/prisma/.gitignore b/integration-tests/tests/prisma/.gitignore deleted file mode 100644 index 794cddf53..000000000 --- a/integration-tests/tests/prisma/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*/client -*/drizzle diff --git a/integration-tests/tests/prisma/mysql/prisma.test.ts b/integration-tests/tests/prisma/mysql/prisma.test.ts deleted file mode 100644 index ee5511a25..000000000 --- a/integration-tests/tests/prisma/mysql/prisma.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import 'dotenv/config'; -import 'zx/globals'; - -import type { PrismaMySqlDatabase } from 'drizzle-orm/prisma/mysql'; -import { drizzle } from 'drizzle-orm/prisma/mysql'; -import { beforeAll, expect, expectTypeOf, test } from 'vitest'; - -import { PrismaClient } from './client'; -import { User } from './drizzle/schema.ts'; - -const ENABLE_LOGGING = false; - -let db: PrismaMySqlDatabase; - -beforeAll(async () => { - await $`prisma generate --schema tests/prisma/mysql/schema.prisma`.quiet(); - await $`prisma db push --force-reset --schema tests/prisma/mysql/schema.prisma`.quiet(); - const prisma = new PrismaClient().$extends(drizzle({ logger: ENABLE_LOGGING })); - db = prisma.$drizzle; -}); - -test('extension works', async () => { - const insert = await db.insert(User).values({ email: 'test@test.com' }); - expectTypeOf(insert).toEqualTypeOf<[]>(); - expect(insert).toEqual([]); - - const result = await db.select().from(User); - expectTypeOf(result).toEqualTypeOf(); - expect(result).toEqual([{ id: 1, email: 'test@test.com', name: null }]); -}); diff --git a/integration-tests/tests/prisma/mysql/schema.prisma b/integration-tests/tests/prisma/mysql/schema.prisma deleted file mode 100644 index 5bb496dcb..000000000 --- a/integration-tests/tests/prisma/mysql/schema.prisma +++ /dev/null @@ -1,20 +0,0 @@ -generator client { - provider = "prisma-client-js" - output = "./client" -} - -generator drizzle { - provider = "drizzle-prisma-generator" - output = "./drizzle" -} - -datasource db { - provider = "mysql" - url = env("MYSQL_CONNECTION_STRING") -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? -} diff --git a/integration-tests/tests/prisma/pg/prisma.test.ts b/integration-tests/tests/prisma/pg/prisma.test.ts deleted file mode 100644 index 16c5ce106..000000000 --- a/integration-tests/tests/prisma/pg/prisma.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import 'dotenv/config'; -import 'zx/globals'; - -import { drizzle } from 'drizzle-orm/prisma/pg'; -import type { PrismaPgDatabase } from 'drizzle-orm/prisma/pg'; -import { beforeAll, expect, expectTypeOf, test } from 'vitest'; - -import { PrismaClient } from './client'; -import { User } from './drizzle/schema.ts'; - -const ENABLE_LOGGING = false; - -let db: PrismaPgDatabase; - -beforeAll(async () => { - await $`prisma db push --force-reset --schema tests/prisma/pg/schema.prisma`.quiet(); - const prisma = new PrismaClient().$extends(drizzle({ logger: ENABLE_LOGGING })); - db = prisma.$drizzle; -}); - -test('extension works', async () => { - const insert = await db.insert(User).values({ email: 'test@test.com' }); - expectTypeOf(insert).toEqualTypeOf<[]>(); - expect(insert).toEqual([]); - - const result = await db.select().from(User); - expectTypeOf(result).toEqualTypeOf(); - expect(result).toEqual([{ id: 1, email: 'test@test.com', name: null }]); -}); diff --git a/integration-tests/tests/prisma/pg/schema.prisma b/integration-tests/tests/prisma/pg/schema.prisma deleted file mode 100644 index a5345d047..000000000 --- a/integration-tests/tests/prisma/pg/schema.prisma +++ /dev/null @@ -1,20 +0,0 @@ -generator client { - provider = "prisma-client-js" - output = "./client" -} - -generator drizzle { - provider = "drizzle-prisma-generator" - output = "./drizzle" -} - -datasource db { - provider = "postgresql" - url = env("PG_CONNECTION_STRING") -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? -} diff --git a/integration-tests/tests/prisma/sqlite/.gitignore b/integration-tests/tests/prisma/sqlite/.gitignore deleted file mode 100644 index 2fa69c243..000000000 --- a/integration-tests/tests/prisma/sqlite/.gitignore +++ /dev/null @@ -1 +0,0 @@ -db.sqlite diff --git a/integration-tests/tests/prisma/sqlite/prisma.test.ts b/integration-tests/tests/prisma/sqlite/prisma.test.ts deleted file mode 100644 index 4e8979cb8..000000000 --- a/integration-tests/tests/prisma/sqlite/prisma.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -import 'dotenv/config'; -import 'zx/globals'; - -import { drizzle } from 'drizzle-orm/prisma/sqlite'; -import type { PrismaSQLiteDatabase } from 'drizzle-orm/prisma/sqlite'; -import { beforeAll, expect, expectTypeOf, test } from 'vitest'; - -import { PrismaClient } from './client'; -import { User } from './drizzle/schema.ts'; - -const ENABLE_LOGGING = false; - -let db: PrismaSQLiteDatabase; - -beforeAll(async () => { - await $`prisma db push --force-reset --schema tests/prisma/sqlite/schema.prisma`.quiet(); - const prisma = new PrismaClient().$extends(drizzle({ logger: ENABLE_LOGGING })); - db = prisma.$drizzle; -}); - -test('extension works', async () => { - const insert = await db.insert(User).values({ email: 'test@test.com' }); - expectTypeOf(insert).toEqualTypeOf<[]>(); - expect(insert).toEqual([]); - - const result = await db.select().from(User); - expectTypeOf(result).toEqualTypeOf(); - expect(result).toEqual([{ id: 1, email: 'test@test.com', name: null }]); - - const all = await db.select().from(User).all(); - expectTypeOf(all).toEqualTypeOf(); - expect(all).toEqual([{ id: 1, email: 'test@test.com', name: null }]); - - const get = await db.select().from(User).get(); - expectTypeOf(get).toEqualTypeOf(); - expect(get).toEqual({ id: 1, email: 'test@test.com', name: null }); - - const run = await db.insert(User).values({ email: 'test2@test.com' }).run(); - expectTypeOf(run).toEqualTypeOf<[]>(); - expect(run).toEqual([]); -}); diff --git a/integration-tests/tests/prisma/sqlite/schema.prisma b/integration-tests/tests/prisma/sqlite/schema.prisma deleted file mode 100644 index 6dbf2643e..000000000 --- a/integration-tests/tests/prisma/sqlite/schema.prisma +++ /dev/null @@ -1,20 +0,0 @@ -generator client { - provider = "prisma-client-js" - output = "./client" -} - -generator drizzle { - provider = "drizzle-prisma-generator" - output = "./drizzle" -} - -datasource db { - provider = "sqlite" - url = "file:./db.sqlite" -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? -} diff --git a/package.json b/package.json index 642121e54..9b5c6739f 100755 --- a/package.json +++ b/package.json @@ -42,5 +42,6 @@ "patchedDependencies": { "typescript@5.4.5": "patches/typescript@5.4.5.patch" } - } + }, + "packageManager": "pnpm@9.7.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 388f8017c..3d532848e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,7 +45,7 @@ importers: version: link:drizzle-orm/dist drizzle-orm-old: specifier: npm:drizzle-orm@^0.27.2 - version: drizzle-orm@0.27.2(@aws-sdk/client-rds-data@3.583.0)(@cloudflare/workers-types@4.20240524.0)(@libsql/client@0.6.0)(@neondatabase/serverless@0.9.3)(@opentelemetry/api@1.8.0)(@planetscale/database@1.18.0)(@types/better-sqlite3@7.6.10)(@types/pg@8.11.6)(@types/sql.js@1.4.9)(@vercel/postgres@0.8.0)(better-sqlite3@10.0.0)(bun-types@1.0.3)(knex@3.1.0(better-sqlite3@10.0.0)(mysql2@3.9.8)(pg@8.11.5)(sqlite3@5.1.7))(kysely@0.27.3)(mysql2@3.9.8)(pg@8.11.5)(postgres@3.4.4)(sql.js@1.10.3)(sqlite3@5.1.7) + version: drizzle-orm@0.27.2(@aws-sdk/client-rds-data@3.583.0)(@cloudflare/workers-types@4.20240524.0)(@libsql/client@0.5.6)(@neondatabase/serverless@0.9.3)(@opentelemetry/api@1.8.0)(@planetscale/database@1.18.0)(@types/better-sqlite3@7.6.10)(@types/pg@8.11.6)(@types/sql.js@1.4.9)(@vercel/postgres@0.8.0)(better-sqlite3@9.6.0)(bun-types@1.0.3)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.11.0)(pg@8.11.5)(sqlite3@5.1.7))(kysely@0.25.0)(mysql2@3.11.0)(pg@8.11.5)(postgres@3.4.4)(sql.js@1.10.3)(sqlite3@5.1.7) eslint: specifier: ^8.50.0 version: 8.50.0 @@ -92,8 +92,8 @@ importers: drizzle-kit: dependencies: '@drizzle-team/brocli': - specifier: ^0.8.2 - version: 0.8.2 + specifier: ^0.10.1 + version: 0.10.1 '@esbuild-kit/esm-loader': specifier: ^2.5.5 version: 2.5.5 @@ -237,7 +237,7 @@ importers: specifier: ^7.4.3 version: 7.4.6 mysql2: - specifier: ^3.3.3 + specifier: 3.3.3 version: 3.3.3 node-fetch: specifier: ^3.3.2 @@ -1974,8 +1974,8 @@ packages: cpu: [x64] os: [win32] - '@drizzle-team/brocli@0.8.2': - resolution: {integrity: sha512-zTrFENsqGvOkBOuHDC1pXCkDXNd2UhP4lI3gYGhQ1R1SPeAAfqzPsV1dcpMy4uNU6kB5VpU5NGhvwxVNETR02A==} + '@drizzle-team/brocli@0.10.1': + resolution: {integrity: sha512-AHy0vjc+n/4w/8Mif+w86qpppHuF3AyXbcWW+R/W7GNA3F5/p2nuhlkCJaTXSLZheB4l1rtHzOfr9A7NwoR/Zg==} '@drizzle-team/studio@0.0.5': resolution: {integrity: sha512-ps5qF0tMxWRVu+V5gvCRrQNqlY92aTnIKdq27gm9LZMSdaKYZt6AVvSK1dlUMzs6Rt0Jm80b+eWct6xShBKhIw==} @@ -3088,18 +3088,12 @@ packages: '@libsql/client@0.5.6': resolution: {integrity: sha512-UBjmDoxz75Z2sHdP+ETCROpeLA/77VMesiff8R4UWK1rnaWbh6/YoCLDILMJL3Rh0udQeKxjL8MjXthqohax+g==} - '@libsql/client@0.6.0': - resolution: {integrity: sha512-qhQzTG/y2IEVbL3+9PULDvlQFWJ/RnjFXECr/Nc3nRngGiiMysDaOV5VUzYk7DulUX98EA4wi+z3FspKrUplUA==} - '@libsql/core@0.4.3': resolution: {integrity: sha512-r28iYBtaLBW9RRgXPFh6cGCsVI/rwRlOzSOpAu/1PVTm6EJ3t233pUf97jETVHU0vjdr1d8VvV6fKAvJkokqCw==} '@libsql/core@0.5.6': resolution: {integrity: sha512-3vicUAydq6jPth410n4AsHHm1n2psTwvkSf94nfJlSXutGSZsl0updn2N/mJBgqUHkbuFoWZtlMifF0SwBj1xQ==} - '@libsql/core@0.6.0': - resolution: {integrity: sha512-affAB8vSqQwqI9NBDJ5uJCVaHoOAS2pOpbv1kWConh1SBbmJBnHHd4KG73RAJ2sgd2+NbT9WA+XJBqxgp28YSw==} - '@libsql/darwin-arm64@0.2.0': resolution: {integrity: sha512-+qyT2W/n5CFH1YZWv2mxW4Fsoo4dX9Z9M/nvbQqZ7H84J8hVegvVAsIGYzcK8xAeMEcpU5yGKB1Y9NoDY4hOSQ==} cpu: [arm64] @@ -3123,15 +3117,9 @@ packages: '@libsql/hrana-client@0.5.6': resolution: {integrity: sha512-mjQoAmejZ1atG+M3YR2ZW+rg6ceBByH/S/h17ZoYZkqbWrvohFhXyz2LFxj++ARMoY9m6w3RJJIRdJdmnEUlFg==} - '@libsql/hrana-client@0.6.0': - resolution: {integrity: sha512-k+fqzdjqg3IvWfKmVJK5StsbjeTcyNAXFelUbXbGNz3yH1gEVT9mZ6kmhsIXP30ZSyVV0AE1Gi25p82mxC9hwg==} - '@libsql/isomorphic-fetch@0.1.12': resolution: {integrity: sha512-MRo4UcmjAGAa3ac56LoD5OE13m2p0lu0VEtZC2NZMcogM/jc5fU9YtMQ3qbPjFJ+u2BBjFZgMPkQaLS1dlMhpg==} - '@libsql/isomorphic-fetch@0.2.1': - resolution: {integrity: sha512-Sv07QP1Aw8A5OOrmKgRUBKe2fFhF2hpGJhtHe3d1aRnTESZCGkn//0zDycMKTGamVWb3oLYRroOsCV8Ukes9GA==} - '@libsql/isomorphic-ws@0.1.5': resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==} @@ -4647,6 +4635,10 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + aws-ssl-profiles@1.1.1: + resolution: {integrity: sha512-+H+kuK34PfMaI9PNU/NSjBKL5hh/KDM9J72kwYeYEm0A8B1AC4fuCy3qsjnA7lxklgyXsB68yn8Z2xoZEjgwCQ==} + engines: {node: '>= 6.0.0'} + axios@1.6.8: resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} @@ -4692,9 +4684,6 @@ packages: resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} engines: {node: '>=12.0.0'} - better-sqlite3@10.0.0: - resolution: {integrity: sha512-rOz0JY8bt9oMgrFssP7GnvA5R3yln73y/NizzWqy3WlFth8Ux8+g4r/N9fjX97nn4X1YX6MTER2doNpTu5pqiA==} - better-sqlite3@8.7.0: resolution: {integrity: sha512-99jZU4le+f3G6aIl6PmmV0cxUIWqKieHxsiF7G34CVFiE+/UabpYqkU0NJIkY/96mQKikHeBjtR27vFfs5JpEw==} @@ -7097,42 +7086,10 @@ packages: tedious: optional: true - knex@3.1.0: - resolution: {integrity: sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==} - engines: {node: '>=16'} - hasBin: true - peerDependencies: - better-sqlite3: '*' - mysql: '*' - mysql2: '*' - pg: '*' - pg-native: '*' - sqlite3: '*' - tedious: '*' - peerDependenciesMeta: - better-sqlite3: - optional: true - mysql: - optional: true - mysql2: - optional: true - pg: - optional: true - pg-native: - optional: true - sqlite3: - optional: true - tedious: - optional: true - kysely@0.25.0: resolution: {integrity: sha512-srn0efIMu5IoEBk0tBmtGnoUss4uwvxtbFQWG/U2MosfqIace1l43IFP1PmEpHRDp+Z79xIcKEqmHH3dAvQdQA==} engines: {node: '>=14.0.0'} - kysely@0.27.3: - resolution: {integrity: sha512-lG03Ru+XyOJFsjH3OMY6R/9U38IjDPfnOfDgO3ynhbDr+Dz8fak+X6L62vqu3iybQnj+lG84OttBuU9KY3L9kA==} - engines: {node: '>=14.0.0'} - leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -7676,10 +7633,6 @@ packages: resolution: {integrity: sha512-MxDQJztArk4JFX1PKVjDhIXRzAmVJfuqZrVU+my6NeYBAA/XZRaDw5q7vga8TNvgyy3Lv3rivBFBBuJFbsdjaw==} engines: {node: '>= 8.0'} - mysql2@3.9.8: - resolution: {integrity: sha512-+5JKNjPuks1FNMoy9TYpl77f+5frbTklz7eb3XDwbpsERRLEeXiW2PDEkakYF50UuKU2qwfGnyXpKYvukv8mGA==} - engines: {node: '>= 8.0'} - mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -8115,9 +8068,6 @@ packages: pg-connection-string@2.6.1: resolution: {integrity: sha512-w6ZzNu6oMmIzEAYVw+RLK0+nqHPt8K3ZnknKi+g48Ak2pr3dtljJW3o+D/n2zzCG07Zoe9VOX3aiKpj+BN0pjg==} - pg-connection-string@2.6.2: - resolution: {integrity: sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==} - pg-connection-string@2.6.4: resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==} @@ -10261,7 +10211,7 @@ snapshots: '@aws-sdk/client-sso-oidc': 3.583.0(@aws-sdk/client-sts@3.583.0) '@aws-sdk/client-sts': 3.583.0 '@aws-sdk/core': 3.582.0 - '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0) + '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0) '@aws-sdk/middleware-host-header': 3.577.0 '@aws-sdk/middleware-logger': 3.577.0 '@aws-sdk/middleware-recursion-detection': 3.577.0 @@ -10351,7 +10301,7 @@ snapshots: '@aws-crypto/sha256-js': 3.0.0 '@aws-sdk/client-sts': 3.583.0 '@aws-sdk/core': 3.582.0 - '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0) + '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0) '@aws-sdk/middleware-host-header': 3.577.0 '@aws-sdk/middleware-logger': 3.577.0 '@aws-sdk/middleware-recursion-detection': 3.577.0 @@ -10661,7 +10611,7 @@ snapshots: '@aws-crypto/sha256-js': 3.0.0 '@aws-sdk/client-sso-oidc': 3.583.0(@aws-sdk/client-sts@3.583.0) '@aws-sdk/core': 3.582.0 - '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0) + '@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0) '@aws-sdk/middleware-host-header': 3.577.0 '@aws-sdk/middleware-logger': 3.577.0 '@aws-sdk/middleware-recursion-detection': 3.577.0 @@ -10850,12 +10800,12 @@ snapshots: - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-ini@3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0)': + '@aws-sdk/credential-provider-ini@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)': dependencies: '@aws-sdk/client-sts': 3.583.0 '@aws-sdk/credential-provider-env': 3.577.0 '@aws-sdk/credential-provider-process': 3.577.0 - '@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0) + '@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0)) '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.583.0) '@aws-sdk/types': 3.577.0 '@smithy/credential-provider-imds': 3.0.0 @@ -10940,13 +10890,13 @@ snapshots: - '@aws-sdk/client-sts' - aws-crt - '@aws-sdk/credential-provider-node@3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0)': + '@aws-sdk/credential-provider-node@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)': dependencies: '@aws-sdk/credential-provider-env': 3.577.0 '@aws-sdk/credential-provider-http': 3.582.0 - '@aws-sdk/credential-provider-ini': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0) + '@aws-sdk/credential-provider-ini': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0) '@aws-sdk/credential-provider-process': 3.577.0 - '@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0) + '@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0)) '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.583.0) '@aws-sdk/types': 3.577.0 '@smithy/credential-provider-imds': 3.0.0 @@ -11021,10 +10971,10 @@ snapshots: - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-sso@3.583.0(@aws-sdk/client-sso-oidc@3.583.0)': + '@aws-sdk/credential-provider-sso@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))': dependencies: '@aws-sdk/client-sso': 3.583.0 - '@aws-sdk/token-providers': 3.577.0(@aws-sdk/client-sso-oidc@3.583.0) + '@aws-sdk/token-providers': 3.577.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0)) '@aws-sdk/types': 3.577.0 '@smithy/property-provider': 3.0.0 '@smithy/shared-ini-file-loader': 3.0.0 @@ -11267,7 +11217,7 @@ snapshots: '@smithy/types': 2.12.0 tslib: 2.6.2 - '@aws-sdk/token-providers@3.577.0(@aws-sdk/client-sso-oidc@3.583.0)': + '@aws-sdk/token-providers@3.577.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))': dependencies: '@aws-sdk/client-sso-oidc': 3.583.0(@aws-sdk/client-sts@3.583.0) '@aws-sdk/types': 3.577.0 @@ -12409,7 +12359,7 @@ snapshots: '@dprint/win32-x64@0.46.3': optional: true - '@drizzle-team/brocli@0.8.2': {} + '@drizzle-team/brocli@0.10.1': {} '@drizzle-team/studio@0.0.5': {} @@ -13402,17 +13352,6 @@ snapshots: - encoding - utf-8-validate - '@libsql/client@0.6.0': - dependencies: - '@libsql/core': 0.6.0 - '@libsql/hrana-client': 0.6.0 - js-base64: 3.7.7 - libsql: 0.3.18 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - optional: true - '@libsql/core@0.4.3': dependencies: js-base64: 3.7.7 @@ -13421,11 +13360,6 @@ snapshots: dependencies: js-base64: 3.7.7 - '@libsql/core@0.6.0': - dependencies: - js-base64: 3.7.7 - optional: true - '@libsql/darwin-arm64@0.2.0': optional: true @@ -13449,17 +13383,6 @@ snapshots: - encoding - utf-8-validate - '@libsql/hrana-client@0.6.0': - dependencies: - '@libsql/isomorphic-fetch': 0.2.1 - '@libsql/isomorphic-ws': 0.1.5(bufferutil@4.0.8)(utf-8-validate@6.0.3) - js-base64: 3.7.7 - node-fetch: 3.3.2 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - optional: true - '@libsql/isomorphic-fetch@0.1.12(encoding@0.1.13)': dependencies: '@types/node-fetch': 2.6.11 @@ -13467,9 +13390,6 @@ snapshots: transitivePeerDependencies: - encoding - '@libsql/isomorphic-fetch@0.2.1': - optional: true - '@libsql/isomorphic-ws@0.1.5(bufferutil@4.0.8)(utf-8-validate@6.0.3)': dependencies: '@types/ws': 8.5.11 @@ -15506,6 +15426,9 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 + aws-ssl-profiles@1.1.1: + optional: true + axios@1.6.8: dependencies: follow-redirects: 1.15.6 @@ -15578,12 +15501,6 @@ snapshots: dependencies: open: 8.4.2 - better-sqlite3@10.0.0: - dependencies: - bindings: 1.5.0 - prebuild-install: 7.1.2 - optional: true - better-sqlite3@8.7.0: dependencies: bindings: 1.5.0 @@ -16397,11 +16314,11 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.27.2(@aws-sdk/client-rds-data@3.583.0)(@cloudflare/workers-types@4.20240524.0)(@libsql/client@0.6.0)(@neondatabase/serverless@0.9.3)(@opentelemetry/api@1.8.0)(@planetscale/database@1.18.0)(@types/better-sqlite3@7.6.10)(@types/pg@8.11.6)(@types/sql.js@1.4.9)(@vercel/postgres@0.8.0)(better-sqlite3@10.0.0)(bun-types@1.0.3)(knex@3.1.0(better-sqlite3@10.0.0)(mysql2@3.9.8)(pg@8.11.5)(sqlite3@5.1.7))(kysely@0.27.3)(mysql2@3.9.8)(pg@8.11.5)(postgres@3.4.4)(sql.js@1.10.3)(sqlite3@5.1.7): + drizzle-orm@0.27.2(@aws-sdk/client-rds-data@3.583.0)(@cloudflare/workers-types@4.20240524.0)(@libsql/client@0.5.6)(@neondatabase/serverless@0.9.3)(@opentelemetry/api@1.8.0)(@planetscale/database@1.18.0)(@types/better-sqlite3@7.6.10)(@types/pg@8.11.6)(@types/sql.js@1.4.9)(@vercel/postgres@0.8.0)(better-sqlite3@9.6.0)(bun-types@1.0.3)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.11.0)(pg@8.11.5)(sqlite3@5.1.7))(kysely@0.25.0)(mysql2@3.11.0)(pg@8.11.5)(postgres@3.4.4)(sql.js@1.10.3)(sqlite3@5.1.7): optionalDependencies: '@aws-sdk/client-rds-data': 3.583.0 '@cloudflare/workers-types': 4.20240524.0 - '@libsql/client': 0.6.0 + '@libsql/client': 0.5.6(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@6.0.3) '@neondatabase/serverless': 0.9.3 '@opentelemetry/api': 1.8.0 '@planetscale/database': 1.18.0 @@ -16409,11 +16326,11 @@ snapshots: '@types/pg': 8.11.6 '@types/sql.js': 1.4.9 '@vercel/postgres': 0.8.0 - better-sqlite3: 10.0.0 + better-sqlite3: 9.6.0 bun-types: 1.0.3 - knex: 3.1.0(better-sqlite3@10.0.0)(mysql2@3.9.8)(pg@8.11.5)(sqlite3@5.1.7) - kysely: 0.27.3 - mysql2: 3.9.8 + knex: 2.5.1(better-sqlite3@9.6.0)(mysql2@3.11.0)(pg@8.11.5)(sqlite3@5.1.7) + kysely: 0.25.0 + mysql2: 3.11.0 pg: 8.11.5 postgres: 3.4.4 sql.js: 1.10.3 @@ -18404,7 +18321,7 @@ snapshots: transitivePeerDependencies: - supports-color - knex@3.1.0(better-sqlite3@10.0.0)(mysql2@3.9.8)(pg@8.11.5)(sqlite3@5.1.7): + knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.11.0)(pg@8.11.5)(sqlite3@5.1.7): dependencies: colorette: 2.0.19 commander: 10.0.1 @@ -18415,14 +18332,14 @@ snapshots: getopts: 2.3.0 interpret: 2.2.0 lodash: 4.17.21 - pg-connection-string: 2.6.2 + pg-connection-string: 2.6.1 rechoir: 0.8.0 resolve-from: 5.0.0 tarn: 3.0.2 tildify: 2.0.0 optionalDependencies: - better-sqlite3: 10.0.0 - mysql2: 3.9.8 + better-sqlite3: 9.6.0 + mysql2: 3.11.0 pg: 8.11.5 sqlite3: 5.1.7 transitivePeerDependencies: @@ -18431,9 +18348,6 @@ snapshots: kysely@0.25.0: {} - kysely@0.27.3: - optional: true - leven@3.1.0: {} levn@0.4.1: @@ -19075,6 +18989,7 @@ snapshots: mysql2@3.3.3: dependencies: + aws-ssl-profiles: 1.1.1 denque: 2.1.0 generate-function: 2.3.1 iconv-lite: 0.6.3 @@ -19083,8 +18998,9 @@ snapshots: named-placeholders: 1.1.3 seq-queue: 0.0.5 sqlstring: 2.3.3 + optional: true - mysql2@3.9.8: + mysql2@3.3.3: dependencies: denque: 2.1.0 generate-function: 2.3.1 @@ -19094,7 +19010,6 @@ snapshots: named-placeholders: 1.1.3 seq-queue: 0.0.5 sqlstring: 2.3.3 - optional: true mz@2.7.0: dependencies: @@ -19524,9 +19439,6 @@ snapshots: pg-connection-string@2.6.1: {} - pg-connection-string@2.6.2: - optional: true - pg-connection-string@2.6.4: {} pg-int8@1.0.1: {}