@anthonyalayo/drizzle-kit 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/.gitignore +25 -0
  2. package/README.md +79 -0
  3. package/build.dev.ts +51 -0
  4. package/build.ts +112 -0
  5. package/imports-checker/analyze.ts +78 -0
  6. package/imports-checker/checker.ts +296 -0
  7. package/imports-checker/grammar/grammar.ohm +121 -0
  8. package/imports-checker/grammar/grammar.ohm-bundle.d.ts +164 -0
  9. package/imports-checker/grammar/grammar.ohm-bundle.js +753 -0
  10. package/imports-checker/index.ts +48 -0
  11. package/package.json +142 -0
  12. package/patches/difflib@0.2.4.patch +31 -0
  13. package/src/@types/utils.ts +58 -0
  14. package/src/api.ts +504 -0
  15. package/src/cli/commands/_es5.ts +2 -0
  16. package/src/cli/commands/check.ts +52 -0
  17. package/src/cli/commands/drop.ts +60 -0
  18. package/src/cli/commands/introspect.ts +772 -0
  19. package/src/cli/commands/libSqlPushUtils.ts +355 -0
  20. package/src/cli/commands/migrate.ts +1526 -0
  21. package/src/cli/commands/mysqlIntrospect.ts +53 -0
  22. package/src/cli/commands/mysqlPushUtils.ts +352 -0
  23. package/src/cli/commands/mysqlUp.ts +102 -0
  24. package/src/cli/commands/pgIntrospect.ts +55 -0
  25. package/src/cli/commands/pgPushUtils.ts +269 -0
  26. package/src/cli/commands/pgUp.ts +217 -0
  27. package/src/cli/commands/push.ts +637 -0
  28. package/src/cli/commands/singlestoreIntrospect.ts +53 -0
  29. package/src/cli/commands/singlestorePushUtils.ts +456 -0
  30. package/src/cli/commands/singlestoreUp.ts +1 -0
  31. package/src/cli/commands/sqliteIntrospect.ts +96 -0
  32. package/src/cli/commands/sqlitePushUtils.ts +322 -0
  33. package/src/cli/commands/sqliteUp.ts +52 -0
  34. package/src/cli/commands/utils.ts +858 -0
  35. package/src/cli/connections.ts +914 -0
  36. package/src/cli/index.ts +48 -0
  37. package/src/cli/schema.ts +794 -0
  38. package/src/cli/selector-ui.ts +38 -0
  39. package/src/cli/utils.ts +112 -0
  40. package/src/cli/validations/cli.ts +79 -0
  41. package/src/cli/validations/common.ts +193 -0
  42. package/src/cli/validations/libsql.ts +27 -0
  43. package/src/cli/validations/mysql.ts +61 -0
  44. package/src/cli/validations/outputs.ts +91 -0
  45. package/src/cli/validations/postgres.ts +83 -0
  46. package/src/cli/validations/singlestore.ts +61 -0
  47. package/src/cli/validations/sqlite.ts +104 -0
  48. package/src/cli/validations/studio.ts +24 -0
  49. package/src/cli/views.ts +658 -0
  50. package/src/extensions/getTablesFilterByExtensions.ts +16 -0
  51. package/src/extensions/vector.ts +10 -0
  52. package/src/global.ts +61 -0
  53. package/src/index.ts +326 -0
  54. package/src/introspect-mysql.ts +1030 -0
  55. package/src/introspect-pg.ts +1435 -0
  56. package/src/introspect-singlestore.ts +913 -0
  57. package/src/introspect-sqlite.ts +533 -0
  58. package/src/jsonDiffer.js +882 -0
  59. package/src/jsonStatements.ts +3590 -0
  60. package/src/loader.mjs +57 -0
  61. package/src/migrationPreparator.ts +217 -0
  62. package/src/schemaValidator.ts +23 -0
  63. package/src/serializer/index.ts +142 -0
  64. package/src/serializer/mysqlImports.ts +38 -0
  65. package/src/serializer/mysqlSchema.ts +423 -0
  66. package/src/serializer/mysqlSerializer.ts +999 -0
  67. package/src/serializer/pgImports.ts +106 -0
  68. package/src/serializer/pgSchema.ts +937 -0
  69. package/src/serializer/pgSerializer.ts +2223 -0
  70. package/src/serializer/singlestoreImports.ts +38 -0
  71. package/src/serializer/singlestoreSchema.ts +257 -0
  72. package/src/serializer/singlestoreSerializer.ts +767 -0
  73. package/src/serializer/sqliteImports.ts +41 -0
  74. package/src/serializer/sqliteSchema.ts +352 -0
  75. package/src/serializer/sqliteSerializer.ts +931 -0
  76. package/src/serializer/studio.ts +694 -0
  77. package/src/serializer/utils.ts +45 -0
  78. package/src/simulator.ts +157 -0
  79. package/src/snapshotsDiffer.ts +4398 -0
  80. package/src/sqlgenerator.ts +4212 -0
  81. package/src/statementCombiner.ts +597 -0
  82. package/src/utils/certs.ts +44 -0
  83. package/src/utils/words.ts +1333 -0
  84. package/src/utils.ts +370 -0
  85. package/tests/bin.test.ts +58 -0
  86. package/tests/cli/d1http.config.ts +12 -0
  87. package/tests/cli/drizzle.config.ts +9 -0
  88. package/tests/cli/durable-sqlite.config.ts +7 -0
  89. package/tests/cli/expo.config.ts +7 -0
  90. package/tests/cli/postgres.config.ts +13 -0
  91. package/tests/cli/postgres2.config.ts +17 -0
  92. package/tests/cli/schema.ts +1 -0
  93. package/tests/cli/turso.config.ts +10 -0
  94. package/tests/cli-export.test.ts +79 -0
  95. package/tests/cli-generate.test.ts +259 -0
  96. package/tests/cli-migrate.test.ts +103 -0
  97. package/tests/cli-push.test.ts +126 -0
  98. package/tests/common.ts +15 -0
  99. package/tests/indexes/common.ts +21 -0
  100. package/tests/indexes/pg.test.ts +245 -0
  101. package/tests/introspect/libsql.test.ts +35 -0
  102. package/tests/introspect/mysql.test.ts +319 -0
  103. package/tests/introspect/pg.test.ts +894 -0
  104. package/tests/introspect/singlestore.test.ts +275 -0
  105. package/tests/introspect/sqlite.test.ts +122 -0
  106. package/tests/libsql-checks.test.ts +308 -0
  107. package/tests/libsql-statements.test.ts +989 -0
  108. package/tests/libsql-views.test.ts +218 -0
  109. package/tests/migrate/libsq-schema.ts +6 -0
  110. package/tests/migrate/libsql-migrate.test.ts +58 -0
  111. package/tests/migrate/migrations/0000_little_blizzard.sql +4 -0
  112. package/tests/migrate/migrations/0001_nebulous_storm.sql +10 -0
  113. package/tests/migrate/migrations/meta/0000_snapshot.json +40 -0
  114. package/tests/migrate/migrations/meta/0001_snapshot.json +40 -0
  115. package/tests/migrate/migrations/meta/_journal.json +20 -0
  116. package/tests/mysql-checks.test.ts +291 -0
  117. package/tests/mysql-generated.test.ts +1290 -0
  118. package/tests/mysql-schemas.test.ts +156 -0
  119. package/tests/mysql-views.test.ts +553 -0
  120. package/tests/mysql.test.ts +863 -0
  121. package/tests/pg-array.test.ts +368 -0
  122. package/tests/pg-checks.test.ts +329 -0
  123. package/tests/pg-columns.test.ts +484 -0
  124. package/tests/pg-domains.test.ts +306 -0
  125. package/tests/pg-enums.test.ts +751 -0
  126. package/tests/pg-generated.test.ts +529 -0
  127. package/tests/pg-identity.test.ts +447 -0
  128. package/tests/pg-schemas.test.ts +105 -0
  129. package/tests/pg-sequences.test.ts +298 -0
  130. package/tests/pg-tables.test.ts +1021 -0
  131. package/tests/pg-views.test.ts +1929 -0
  132. package/tests/push/common.ts +58 -0
  133. package/tests/push/libsql.test.ts +1400 -0
  134. package/tests/push/mysql-push.test.ts +345 -0
  135. package/tests/push/mysql.test.ts +788 -0
  136. package/tests/push/pg.test.ts +4341 -0
  137. package/tests/push/singlestore-push.test.ts +894 -0
  138. package/tests/push/singlestore.test.ts +444 -0
  139. package/tests/push/sqlite.test.ts +1613 -0
  140. package/tests/rls/pg-policy.test.ts +1656 -0
  141. package/tests/rls/pg-role.test.ts +234 -0
  142. package/tests/schemaDiffer.ts +2852 -0
  143. package/tests/singlestore-generated.test.ts +1290 -0
  144. package/tests/singlestore-schemas.test.ts +155 -0
  145. package/tests/singlestore.test.ts +978 -0
  146. package/tests/sqlite-checks.test.ts +308 -0
  147. package/tests/sqlite-columns.test.ts +1049 -0
  148. package/tests/sqlite-generated.test.ts +1726 -0
  149. package/tests/sqlite-tables.test.ts +637 -0
  150. package/tests/sqlite-views.test.ts +218 -0
  151. package/tests/statements-combiner/libsql-statements-combiner.test.ts +1812 -0
  152. package/tests/statements-combiner/singlestore-statements-combiner.test.ts +882 -0
  153. package/tests/statements-combiner/sqlite-statements-combiner.test.ts +1211 -0
  154. package/tests/test/sqlite.test.ts +39 -0
  155. package/tests/testsinglestore.ts +29 -0
  156. package/tests/validations.test.ts +869 -0
  157. package/tests/wrap-param.test.ts +16 -0
  158. package/tsconfig.build.json +4 -0
  159. package/tsconfig.cli-types.json +9 -0
  160. package/tsconfig.json +28 -0
  161. package/vitest.config.ts +34 -0
@@ -0,0 +1,858 @@
1
+ import chalk from 'chalk';
2
+ import { existsSync } from 'fs';
3
+ import { render } from 'hanji';
4
+ import { join, resolve } from 'path';
5
+ import { object, string } from 'zod';
6
+ import { getTablesFilterByExtensions } from '../../extensions/getTablesFilterByExtensions';
7
+ import { assertUnreachable } from '../../global';
8
+ import { type Dialect, dialect } from '../../schemaValidator';
9
+ import { prepareFilenames } from '../../serializer';
10
+ import { Entities, pullParams, pushParams } from '../validations/cli';
11
+ import {
12
+ Casing,
13
+ CasingType,
14
+ CliConfig,
15
+ configCommonSchema,
16
+ configMigrations,
17
+ Driver,
18
+ Prefix,
19
+ wrapParam,
20
+ } from '../validations/common';
21
+ import { LibSQLCredentials, libSQLCredentials } from '../validations/libsql';
22
+ import { printConfigConnectionIssues as printIssuesLibSql } from '../validations/libsql';
23
+ import {
24
+ MysqlCredentials,
25
+ mysqlCredentials,
26
+ printConfigConnectionIssues as printIssuesMysql,
27
+ } from '../validations/mysql';
28
+ import { outputs } from '../validations/outputs';
29
+ import {
30
+ PostgresCredentials,
31
+ postgresCredentials,
32
+ printConfigConnectionIssues as printIssuesPg,
33
+ } from '../validations/postgres';
34
+ import {
35
+ printConfigConnectionIssues as printIssuesSingleStore,
36
+ SingleStoreCredentials,
37
+ singlestoreCredentials,
38
+ } from '../validations/singlestore';
39
+ import {
40
+ printConfigConnectionIssues as printIssuesSqlite,
41
+ SqliteCredentials,
42
+ sqliteCredentials,
43
+ } from '../validations/sqlite';
44
+ import { studioCliParams, studioConfig } from '../validations/studio';
45
+ import { error, grey } from '../views';
46
+
47
+ // NextJs default config is target: es5, which esbuild-register can't consume
48
+ const assertES5 = async (unregister: () => void) => {
49
+ try {
50
+ require('./_es5.ts');
51
+ } catch (e: any) {
52
+ if ('errors' in e && Array.isArray(e.errors) && e.errors.length > 0) {
53
+ const es5Error = (e.errors as any[]).filter((it) => it.text?.includes(`("es5") is not supported yet`)).length > 0;
54
+ if (es5Error) {
55
+ console.log(
56
+ error(
57
+ `Please change compilerOptions.target from 'es5' to 'es6' or above in your tsconfig.json`,
58
+ ),
59
+ );
60
+ process.exit(1);
61
+ }
62
+ }
63
+ console.error(e);
64
+ process.exit(1);
65
+ }
66
+ };
67
+
68
+ export const safeRegister = async () => {
69
+ const { register } = await import('esbuild-register/dist/node');
70
+ let res: { unregister: () => void };
71
+ try {
72
+ res = register({
73
+ format: 'cjs',
74
+ loader: 'ts',
75
+ });
76
+ } catch {
77
+ // tsx fallback
78
+ res = {
79
+ unregister: () => {},
80
+ };
81
+ }
82
+
83
+ // has to be outside try catch to be able to run with tsx
84
+ await assertES5(res.unregister);
85
+ return res;
86
+ };
87
+
88
+ export const prepareCheckParams = async (
89
+ options: {
90
+ config?: string;
91
+ dialect?: Dialect;
92
+ out?: string;
93
+ },
94
+ from: 'cli' | 'config',
95
+ ): Promise<{ out: string; dialect: Dialect }> => {
96
+ const config = from === 'config'
97
+ ? await drizzleConfigFromFile(options.config as string | undefined)
98
+ : options;
99
+
100
+ if (!config.out || !config.dialect) {
101
+ let text = `Please provide required params for AWS Data API driver:\n`;
102
+ console.log(error(text));
103
+ console.log(wrapParam('database', config.out));
104
+ console.log(wrapParam('secretArn', config.dialect));
105
+ process.exit(1);
106
+ }
107
+ return { out: config.out, dialect: config.dialect };
108
+ };
109
+
110
+ export const prepareDropParams = async (
111
+ options: {
112
+ config?: string;
113
+ out?: string;
114
+ driver?: Driver;
115
+ },
116
+ from: 'cli' | 'config',
117
+ ): Promise<{ out: string; bundle: boolean }> => {
118
+ const config = from === 'config'
119
+ ? await drizzleConfigFromFile(options.config as string | undefined)
120
+ : options;
121
+
122
+ return { out: config.out || 'drizzle', bundle: config.driver === 'expo' };
123
+ };
124
+
125
+ export type GenerateConfig = {
126
+ dialect: Dialect;
127
+ schema: string | string[];
128
+ out: string;
129
+ breakpoints: boolean;
130
+ name?: string;
131
+ prefix: Prefix;
132
+ custom: boolean;
133
+ bundle: boolean;
134
+ casing?: CasingType;
135
+ driver?: Driver;
136
+ };
137
+
138
+ export type ExportConfig = {
139
+ dialect: Dialect;
140
+ schema: string | string[];
141
+ sql: boolean;
142
+ };
143
+
144
+ export const prepareGenerateConfig = async (
145
+ options: {
146
+ config?: string;
147
+ schema?: string;
148
+ out?: string;
149
+ breakpoints?: boolean;
150
+ custom?: boolean;
151
+ name?: string;
152
+ dialect?: Dialect;
153
+ driver?: Driver;
154
+ prefix?: Prefix;
155
+ casing?: CasingType;
156
+ },
157
+ from: 'config' | 'cli',
158
+ ): Promise<GenerateConfig> => {
159
+ const config = from === 'config' ? await drizzleConfigFromFile(options.config) : options;
160
+
161
+ const { schema, out, breakpoints, dialect, driver, casing } = config;
162
+
163
+ if (!schema || !dialect) {
164
+ console.log(error('Please provide required params:'));
165
+ console.log(wrapParam('schema', schema));
166
+ console.log(wrapParam('dialect', dialect));
167
+ console.log(wrapParam('out', out, true));
168
+ process.exit(1);
169
+ }
170
+
171
+ const fileNames = prepareFilenames(schema);
172
+ if (fileNames.length === 0) {
173
+ render(`[${chalk.blue('i')}] No schema file in ${schema} was found`);
174
+ process.exit(0);
175
+ }
176
+
177
+ const prefix = ('migrations' in config ? config.migrations?.prefix : options.prefix)
178
+ || 'index';
179
+
180
+ return {
181
+ dialect: dialect,
182
+ name: options.name,
183
+ custom: options.custom || false,
184
+ prefix,
185
+ breakpoints: breakpoints ?? true,
186
+ schema: schema,
187
+ out: out || 'drizzle',
188
+ bundle: driver === 'expo' || driver === 'durable-sqlite',
189
+ casing,
190
+ driver,
191
+ };
192
+ };
193
+
194
+ export const prepareExportConfig = async (
195
+ options: {
196
+ config?: string;
197
+ schema?: string;
198
+ dialect?: Dialect;
199
+ sql: boolean;
200
+ },
201
+ from: 'config' | 'cli',
202
+ ): Promise<ExportConfig> => {
203
+ const config = from === 'config' ? await drizzleConfigFromFile(options.config, true) : options;
204
+
205
+ const { schema, dialect, sql } = config;
206
+
207
+ if (!schema || !dialect) {
208
+ console.log(error('Please provide required params:'));
209
+ console.log(wrapParam('schema', schema));
210
+ console.log(wrapParam('dialect', dialect));
211
+ process.exit(1);
212
+ }
213
+
214
+ const fileNames = prepareFilenames(schema);
215
+ if (fileNames.length === 0) {
216
+ render(`[${chalk.blue('i')}] No schema file in ${schema} was found`);
217
+ process.exit(0);
218
+ }
219
+ return {
220
+ dialect: dialect,
221
+ schema: schema,
222
+ sql: sql,
223
+ };
224
+ };
225
+
226
+ export const flattenDatabaseCredentials = (config: any) => {
227
+ if ('dbCredentials' in config) {
228
+ const { dbCredentials, ...rest } = config;
229
+ return {
230
+ ...rest,
231
+ ...dbCredentials,
232
+ };
233
+ }
234
+ return config;
235
+ };
236
+
237
+ const flattenPull = (config: any) => {
238
+ if ('dbCredentials' in config) {
239
+ const { dbCredentials, introspect, ...rest } = config;
240
+ return {
241
+ ...rest,
242
+ ...dbCredentials,
243
+ casing: introspect?.casing,
244
+ };
245
+ }
246
+ return config;
247
+ };
248
+
249
+ export const preparePushConfig = async (
250
+ options: Record<string, unknown>,
251
+ from: 'cli' | 'config',
252
+ ): Promise<
253
+ (
254
+ | {
255
+ dialect: 'mysql';
256
+ credentials: MysqlCredentials;
257
+ }
258
+ | {
259
+ dialect: 'postgresql';
260
+ credentials: PostgresCredentials;
261
+ }
262
+ | {
263
+ dialect: 'sqlite';
264
+ credentials: SqliteCredentials;
265
+ }
266
+ | {
267
+ dialect: 'turso';
268
+ credentials: LibSQLCredentials;
269
+ }
270
+ | {
271
+ dialect: 'singlestore';
272
+ credentials: SingleStoreCredentials;
273
+ }
274
+ ) & {
275
+ schemaPath: string | string[];
276
+ verbose: boolean;
277
+ strict: boolean;
278
+ force: boolean;
279
+ tablesFilter: string[];
280
+ schemasFilter: string[];
281
+ casing?: CasingType;
282
+ entities?: Entities;
283
+ }
284
+ > => {
285
+ const raw = flattenDatabaseCredentials(
286
+ from === 'config'
287
+ ? await drizzleConfigFromFile(options.config as string | undefined)
288
+ : options,
289
+ );
290
+
291
+ raw.verbose ||= options.verbose; // if provided in cli to debug
292
+ raw.strict ||= options.strict; // if provided in cli only
293
+
294
+ const parsed = pushParams.safeParse(raw);
295
+
296
+ if (parsed.error) {
297
+ console.log(error('Please provide required params:'));
298
+ console.log(wrapParam('dialect', raw.dialect));
299
+ console.log(wrapParam('schema', raw.schema));
300
+ process.exit(1);
301
+ }
302
+
303
+ const config = parsed.data;
304
+
305
+ const schemaFiles = prepareFilenames(config.schema);
306
+ if (schemaFiles.length === 0) {
307
+ render(`[${chalk.blue('i')}] No schema file in ${config.schema} was found`);
308
+ process.exit(0);
309
+ }
310
+
311
+ const tablesFilterConfig = config.tablesFilter;
312
+ const tablesFilter = tablesFilterConfig
313
+ ? typeof tablesFilterConfig === 'string'
314
+ ? [tablesFilterConfig]
315
+ : tablesFilterConfig
316
+ : [];
317
+
318
+ const schemasFilterConfig = config.schemaFilter;
319
+
320
+ const schemasFilter = schemasFilterConfig
321
+ ? typeof schemasFilterConfig === 'string'
322
+ ? [schemasFilterConfig]
323
+ : schemasFilterConfig
324
+ : [];
325
+
326
+ tablesFilter.push(...getTablesFilterByExtensions(config));
327
+
328
+ if (config.dialect === 'postgresql') {
329
+ const parsed = postgresCredentials.safeParse(config);
330
+ if (!parsed.success) {
331
+ printIssuesPg(config);
332
+ process.exit(1);
333
+ }
334
+
335
+ return {
336
+ dialect: 'postgresql',
337
+ schemaPath: config.schema,
338
+ strict: config.strict ?? false,
339
+ verbose: config.verbose ?? false,
340
+ force: (options.force as boolean) ?? false,
341
+ credentials: parsed.data,
342
+ casing: config.casing,
343
+ tablesFilter,
344
+ schemasFilter,
345
+ entities: config.entities,
346
+ };
347
+ }
348
+
349
+ if (config.dialect === 'mysql') {
350
+ const parsed = mysqlCredentials.safeParse(config);
351
+ if (!parsed.success) {
352
+ printIssuesMysql(config);
353
+ process.exit(1);
354
+ }
355
+ return {
356
+ dialect: 'mysql',
357
+ schemaPath: config.schema,
358
+ strict: config.strict ?? false,
359
+ verbose: config.verbose ?? false,
360
+ force: (options.force as boolean) ?? false,
361
+ credentials: parsed.data,
362
+ casing: config.casing,
363
+ tablesFilter,
364
+ schemasFilter,
365
+ };
366
+ }
367
+
368
+ if (config.dialect === 'singlestore') {
369
+ const parsed = singlestoreCredentials.safeParse(config);
370
+ if (!parsed.success) {
371
+ printIssuesSingleStore(config);
372
+ process.exit(1);
373
+ }
374
+
375
+ return {
376
+ dialect: 'singlestore',
377
+ schemaPath: config.schema,
378
+ strict: config.strict ?? false,
379
+ verbose: config.verbose ?? false,
380
+ force: (options.force as boolean) ?? false,
381
+ credentials: parsed.data,
382
+ tablesFilter,
383
+ schemasFilter,
384
+ };
385
+ }
386
+
387
+ if (config.dialect === 'sqlite') {
388
+ const parsed = sqliteCredentials.safeParse(config);
389
+ if (!parsed.success) {
390
+ printIssuesSqlite(config, 'pull');
391
+ process.exit(1);
392
+ }
393
+ return {
394
+ dialect: 'sqlite',
395
+ schemaPath: config.schema,
396
+ strict: config.strict ?? false,
397
+ verbose: config.verbose ?? false,
398
+ force: (options.force as boolean) ?? false,
399
+ credentials: parsed.data,
400
+ casing: config.casing,
401
+ tablesFilter,
402
+ schemasFilter,
403
+ };
404
+ }
405
+
406
+ if (config.dialect === 'turso') {
407
+ const parsed = libSQLCredentials.safeParse(config);
408
+ if (!parsed.success) {
409
+ printIssuesSqlite(config, 'pull');
410
+ process.exit(1);
411
+ }
412
+ return {
413
+ dialect: 'turso',
414
+ schemaPath: config.schema,
415
+ strict: config.strict ?? false,
416
+ verbose: config.verbose ?? false,
417
+ force: (options.force as boolean) ?? false,
418
+ credentials: parsed.data,
419
+ casing: config.casing,
420
+ tablesFilter,
421
+ schemasFilter,
422
+ };
423
+ }
424
+
425
+ assertUnreachable(config.dialect);
426
+ };
427
+
428
+ export const preparePullConfig = async (
429
+ options: Record<string, unknown>,
430
+ from: 'cli' | 'config',
431
+ ): Promise<
432
+ (
433
+ | {
434
+ dialect: 'mysql';
435
+ credentials: MysqlCredentials;
436
+ }
437
+ | {
438
+ dialect: 'postgresql';
439
+ credentials: PostgresCredentials;
440
+ }
441
+ | {
442
+ dialect: 'sqlite';
443
+ credentials: SqliteCredentials;
444
+ }
445
+ | {
446
+ dialect: 'turso';
447
+ credentials: LibSQLCredentials;
448
+ }
449
+ | {
450
+ dialect: 'singlestore';
451
+ credentials: SingleStoreCredentials;
452
+ }
453
+ ) & {
454
+ out: string;
455
+ breakpoints: boolean;
456
+ casing: Casing;
457
+ tablesFilter: string[];
458
+ schemasFilter: string[];
459
+ prefix: Prefix;
460
+ entities: Entities;
461
+ }
462
+ > => {
463
+ const raw = flattenPull(
464
+ from === 'config'
465
+ ? await drizzleConfigFromFile(options.config as string | undefined)
466
+ : options,
467
+ );
468
+ const parsed = pullParams.safeParse(raw);
469
+
470
+ if (parsed.error) {
471
+ console.log(error('Please provide required params:'));
472
+ console.log(wrapParam('dialect', raw.dialect));
473
+ process.exit(1);
474
+ }
475
+
476
+ const config = parsed.data;
477
+ const dialect = config.dialect;
478
+
479
+ const tablesFilterConfig = config.tablesFilter;
480
+ const tablesFilter = tablesFilterConfig
481
+ ? typeof tablesFilterConfig === 'string'
482
+ ? [tablesFilterConfig]
483
+ : tablesFilterConfig
484
+ : [];
485
+
486
+ if (config.extensionsFilters) {
487
+ if (
488
+ config.extensionsFilters.includes('postgis')
489
+ && dialect === 'postgresql'
490
+ ) {
491
+ tablesFilter.push(
492
+ ...['!geography_columns', '!geometry_columns', '!spatial_ref_sys'],
493
+ );
494
+ }
495
+ }
496
+
497
+ const schemasFilterConfig = config.schemaFilter; // TODO: consistent naming
498
+ const schemasFilter = schemasFilterConfig
499
+ ? typeof schemasFilterConfig === 'string'
500
+ ? [schemasFilterConfig]
501
+ : schemasFilterConfig
502
+ : [];
503
+
504
+ if (dialect === 'postgresql') {
505
+ const parsed = postgresCredentials.safeParse(config);
506
+ if (!parsed.success) {
507
+ printIssuesPg(config);
508
+ process.exit(1);
509
+ }
510
+
511
+ return {
512
+ dialect: 'postgresql',
513
+ out: config.out,
514
+ breakpoints: config.breakpoints,
515
+ casing: config.casing,
516
+ credentials: parsed.data,
517
+ tablesFilter,
518
+ schemasFilter,
519
+ prefix: config.migrations?.prefix || 'index',
520
+ entities: config.entities,
521
+ };
522
+ }
523
+
524
+ if (dialect === 'mysql') {
525
+ const parsed = mysqlCredentials.safeParse(config);
526
+ if (!parsed.success) {
527
+ printIssuesMysql(config);
528
+ process.exit(1);
529
+ }
530
+ return {
531
+ dialect: 'mysql',
532
+ out: config.out,
533
+ breakpoints: config.breakpoints,
534
+ casing: config.casing,
535
+ credentials: parsed.data,
536
+ tablesFilter,
537
+ schemasFilter,
538
+ prefix: config.migrations?.prefix || 'index',
539
+ entities: config.entities,
540
+ };
541
+ }
542
+
543
+ if (dialect === 'singlestore') {
544
+ const parsed = singlestoreCredentials.safeParse(config);
545
+ if (!parsed.success) {
546
+ printIssuesSingleStore(config);
547
+ process.exit(1);
548
+ }
549
+
550
+ return {
551
+ dialect: 'singlestore',
552
+ out: config.out,
553
+ breakpoints: config.breakpoints,
554
+ casing: config.casing,
555
+ credentials: parsed.data,
556
+ tablesFilter,
557
+ schemasFilter,
558
+ prefix: config.migrations?.prefix || 'index',
559
+ entities: config.entities,
560
+ };
561
+ }
562
+
563
+ if (dialect === 'sqlite') {
564
+ const parsed = sqliteCredentials.safeParse(config);
565
+ if (!parsed.success) {
566
+ printIssuesSqlite(config, 'pull');
567
+ process.exit(1);
568
+ }
569
+ return {
570
+ dialect: 'sqlite',
571
+ out: config.out,
572
+ breakpoints: config.breakpoints,
573
+ casing: config.casing,
574
+ credentials: parsed.data,
575
+ tablesFilter,
576
+ schemasFilter,
577
+ prefix: config.migrations?.prefix || 'index',
578
+ entities: config.entities,
579
+ };
580
+ }
581
+
582
+ if (dialect === 'turso') {
583
+ const parsed = libSQLCredentials.safeParse(config);
584
+ if (!parsed.success) {
585
+ printIssuesLibSql(config, 'pull');
586
+ process.exit(1);
587
+ }
588
+ return {
589
+ dialect,
590
+ out: config.out,
591
+ breakpoints: config.breakpoints,
592
+ casing: config.casing,
593
+ credentials: parsed.data,
594
+ tablesFilter,
595
+ schemasFilter,
596
+ prefix: config.migrations?.prefix || 'index',
597
+ entities: config.entities,
598
+ };
599
+ }
600
+
601
+ assertUnreachable(dialect);
602
+ };
603
+
604
+ export const prepareStudioConfig = async (options: Record<string, unknown>) => {
605
+ const params = studioCliParams.parse(options);
606
+ const config = await drizzleConfigFromFile(params.config);
607
+ const result = studioConfig.safeParse(config);
608
+ if (!result.success) {
609
+ if (!('dialect' in config)) {
610
+ console.log(outputs.studio.noDialect());
611
+ }
612
+ process.exit(1);
613
+ }
614
+
615
+ if (!('dbCredentials' in config)) {
616
+ console.log(outputs.studio.noCredentials());
617
+ process.exit(1);
618
+ }
619
+ const { host, port } = params;
620
+ const { dialect, schema } = result.data;
621
+ const flattened = flattenDatabaseCredentials(config);
622
+
623
+ if (dialect === 'postgresql') {
624
+ const parsed = postgresCredentials.safeParse(flattened);
625
+ if (!parsed.success) {
626
+ printIssuesPg(flattened as Record<string, unknown>);
627
+ process.exit(1);
628
+ }
629
+ const credentials = parsed.data;
630
+ return {
631
+ dialect,
632
+ schema,
633
+ host,
634
+ port,
635
+ credentials,
636
+ };
637
+ }
638
+
639
+ if (dialect === 'mysql') {
640
+ const parsed = mysqlCredentials.safeParse(flattened);
641
+ if (!parsed.success) {
642
+ printIssuesMysql(flattened as Record<string, unknown>);
643
+ process.exit(1);
644
+ }
645
+ const credentials = parsed.data;
646
+ return {
647
+ dialect,
648
+ schema,
649
+ host,
650
+ port,
651
+ credentials,
652
+ };
653
+ }
654
+
655
+ if (dialect === 'singlestore') {
656
+ const parsed = singlestoreCredentials.safeParse(flattened);
657
+ if (!parsed.success) {
658
+ printIssuesSingleStore(flattened as Record<string, unknown>);
659
+ process.exit(1);
660
+ }
661
+ const credentials = parsed.data;
662
+ return {
663
+ dialect,
664
+ schema,
665
+ host,
666
+ port,
667
+ credentials,
668
+ };
669
+ }
670
+
671
+ if (dialect === 'sqlite') {
672
+ const parsed = sqliteCredentials.safeParse(flattened);
673
+ if (!parsed.success) {
674
+ printIssuesSqlite(flattened as Record<string, unknown>, 'studio');
675
+ process.exit(1);
676
+ }
677
+ const credentials = parsed.data;
678
+ return {
679
+ dialect,
680
+ schema,
681
+ host,
682
+ port,
683
+ credentials,
684
+ };
685
+ }
686
+
687
+ if (dialect === 'turso') {
688
+ const parsed = libSQLCredentials.safeParse(flattened);
689
+ if (!parsed.success) {
690
+ printIssuesLibSql(flattened as Record<string, unknown>, 'studio');
691
+ process.exit(1);
692
+ }
693
+ const credentials = parsed.data;
694
+ return {
695
+ dialect,
696
+ schema,
697
+ host,
698
+ port,
699
+ credentials,
700
+ };
701
+ }
702
+
703
+ assertUnreachable(dialect);
704
+ };
705
+
706
+ export const migrateConfig = object({
707
+ dialect,
708
+ out: string().optional().default('drizzle'),
709
+ migrations: configMigrations,
710
+ });
711
+
712
+ export const prepareMigrateConfig = async (configPath: string | undefined) => {
713
+ const config = await drizzleConfigFromFile(configPath);
714
+ const parsed = migrateConfig.safeParse(config);
715
+ if (parsed.error) {
716
+ console.log(error('Please provide required params:'));
717
+ console.log(wrapParam('dialect', config.dialect));
718
+ process.exit(1);
719
+ }
720
+
721
+ const { dialect, out } = parsed.data;
722
+ const { schema, table } = parsed.data.migrations || {};
723
+ const flattened = flattenDatabaseCredentials(config);
724
+
725
+ if (dialect === 'postgresql') {
726
+ const parsed = postgresCredentials.safeParse(flattened);
727
+ if (!parsed.success) {
728
+ printIssuesPg(flattened as Record<string, unknown>);
729
+ process.exit(1);
730
+ }
731
+ const credentials = parsed.data;
732
+ return {
733
+ dialect,
734
+ out,
735
+ credentials,
736
+ schema,
737
+ table,
738
+ };
739
+ }
740
+
741
+ if (dialect === 'mysql') {
742
+ const parsed = mysqlCredentials.safeParse(flattened);
743
+ if (!parsed.success) {
744
+ printIssuesMysql(flattened as Record<string, unknown>);
745
+ process.exit(1);
746
+ }
747
+ const credentials = parsed.data;
748
+ return {
749
+ dialect,
750
+ out,
751
+ credentials,
752
+ schema,
753
+ table,
754
+ };
755
+ }
756
+
757
+ if (dialect === 'singlestore') {
758
+ const parsed = singlestoreCredentials.safeParse(flattened);
759
+ if (!parsed.success) {
760
+ printIssuesSingleStore(flattened as Record<string, unknown>);
761
+ process.exit(1);
762
+ }
763
+ const credentials = parsed.data;
764
+ return {
765
+ dialect,
766
+ out,
767
+ credentials,
768
+ schema,
769
+ table,
770
+ };
771
+ }
772
+
773
+ if (dialect === 'sqlite') {
774
+ const parsed = sqliteCredentials.safeParse(flattened);
775
+ if (!parsed.success) {
776
+ printIssuesSqlite(flattened as Record<string, unknown>, 'migrate');
777
+ process.exit(1);
778
+ }
779
+ const credentials = parsed.data;
780
+ return {
781
+ dialect,
782
+ out,
783
+ credentials,
784
+ schema,
785
+ table,
786
+ };
787
+ }
788
+ if (dialect === 'turso') {
789
+ const parsed = libSQLCredentials.safeParse(flattened);
790
+ if (!parsed.success) {
791
+ printIssuesLibSql(flattened as Record<string, unknown>, 'migrate');
792
+ process.exit(1);
793
+ }
794
+ const credentials = parsed.data;
795
+ return {
796
+ dialect,
797
+ out,
798
+ credentials,
799
+ schema,
800
+ table,
801
+ };
802
+ }
803
+
804
+ assertUnreachable(dialect);
805
+ };
806
+
807
+ export const drizzleConfigFromFile = async (
808
+ configPath?: string,
809
+ isExport?: boolean,
810
+ ): Promise<CliConfig> => {
811
+ const prefix = process.env.TEST_CONFIG_PATH_PREFIX || '';
812
+
813
+ const defaultTsConfigExists = existsSync(resolve(join(prefix, 'drizzle.config.ts')));
814
+ const defaultJsConfigExists = existsSync(resolve(join(prefix, 'drizzle.config.js')));
815
+ const defaultJsonConfigExists = existsSync(
816
+ join(resolve('drizzle.config.json')),
817
+ );
818
+
819
+ const defaultConfigPath = defaultTsConfigExists
820
+ ? 'drizzle.config.ts'
821
+ : defaultJsConfigExists
822
+ ? 'drizzle.config.js'
823
+ : 'drizzle.config.json';
824
+
825
+ if (!configPath && !isExport) {
826
+ console.log(
827
+ chalk.gray(
828
+ `No config path provided, using default '${defaultConfigPath}'`,
829
+ ),
830
+ );
831
+ }
832
+
833
+ const path: string = resolve(join(prefix, configPath ?? defaultConfigPath));
834
+
835
+ if (!existsSync(path)) {
836
+ console.log(`${path} file does not exist`);
837
+ process.exit(1);
838
+ }
839
+
840
+ if (!isExport) console.log(chalk.grey(`Reading config file '${path}'`));
841
+
842
+ const { unregister } = await safeRegister();
843
+ const required = require(`${path}`);
844
+ const content = required.default ?? required;
845
+ unregister();
846
+
847
+ // --- get response and then check by each dialect independently
848
+ const res = configCommonSchema.safeParse(content);
849
+ if (!res.success) {
850
+ console.log(res.error);
851
+ if (!('dialect' in content)) {
852
+ console.log(error("Please specify 'dialect' param in config file"));
853
+ }
854
+ process.exit(1);
855
+ }
856
+
857
+ return res.data;
858
+ };