@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,355 @@
1
+ import chalk from 'chalk';
2
+
3
+ import { JsonStatement } from 'src/jsonStatements';
4
+ import { findAddedAndRemoved, SQLiteDB } from 'src/utils';
5
+ import { SQLiteSchemaInternal, SQLiteSchemaSquashed, SQLiteSquasher } from '../../serializer/sqliteSchema';
6
+ import {
7
+ CreateSqliteIndexConvertor,
8
+ fromJson,
9
+ LibSQLModifyColumn,
10
+ SQLiteCreateTableConvertor,
11
+ SQLiteDropTableConvertor,
12
+ SqliteRenameTableConvertor,
13
+ } from '../../sqlgenerator';
14
+
15
+ export const getOldTableName = (
16
+ tableName: string,
17
+ meta: SQLiteSchemaInternal['_meta'],
18
+ ) => {
19
+ for (const key of Object.keys(meta.tables)) {
20
+ const value = meta.tables[key];
21
+ if (`"${tableName}"` === value) {
22
+ return key.substring(1, key.length - 1);
23
+ }
24
+ }
25
+ return tableName;
26
+ };
27
+
28
+ export const _moveDataStatements = (
29
+ tableName: string,
30
+ json: SQLiteSchemaSquashed,
31
+ dataLoss: boolean = false,
32
+ ) => {
33
+ const statements: string[] = [];
34
+
35
+ const newTableName = `__new_${tableName}`;
36
+
37
+ // create table statement from a new json2 with proper name
38
+ const tableColumns = Object.values(json.tables[tableName].columns);
39
+ const referenceData = Object.values(json.tables[tableName].foreignKeys);
40
+ const compositePKs = Object.values(
41
+ json.tables[tableName].compositePrimaryKeys,
42
+ ).map((it) => SQLiteSquasher.unsquashPK(it));
43
+ const checkConstraints = Object.values(json.tables[tableName].checkConstraints);
44
+
45
+ const fks = referenceData.map((it) => SQLiteSquasher.unsquashPushFK(it));
46
+
47
+ const mappedCheckConstraints: string[] = checkConstraints.map((it) =>
48
+ it.replaceAll(`"${tableName}".`, `"${newTableName}".`)
49
+ .replaceAll(`\`${tableName}\`.`, `\`${newTableName}\`.`)
50
+ .replaceAll(`${tableName}.`, `${newTableName}.`)
51
+ .replaceAll(`'${tableName}'.`, `\`${newTableName}\`.`)
52
+ );
53
+
54
+ // create new table
55
+ statements.push(
56
+ new SQLiteCreateTableConvertor().convert({
57
+ type: 'sqlite_create_table',
58
+ tableName: newTableName,
59
+ columns: tableColumns,
60
+ referenceData: fks,
61
+ compositePKs,
62
+ checkConstraints: mappedCheckConstraints,
63
+ }),
64
+ );
65
+
66
+ // move data
67
+ if (!dataLoss) {
68
+ const columns = Object.keys(json.tables[tableName].columns).map(
69
+ (c) => `"${c}"`,
70
+ );
71
+
72
+ statements.push(
73
+ `INSERT INTO \`${newTableName}\`(${
74
+ columns.join(
75
+ ', ',
76
+ )
77
+ }) SELECT ${columns.join(', ')} FROM \`${tableName}\`;`,
78
+ );
79
+ }
80
+
81
+ statements.push(
82
+ new SQLiteDropTableConvertor().convert({
83
+ type: 'drop_table',
84
+ tableName: tableName,
85
+ schema: '',
86
+ }),
87
+ );
88
+
89
+ // rename table
90
+ statements.push(
91
+ new SqliteRenameTableConvertor().convert({
92
+ fromSchema: '',
93
+ tableNameFrom: newTableName,
94
+ tableNameTo: tableName,
95
+ toSchema: '',
96
+ type: 'rename_table',
97
+ }),
98
+ );
99
+
100
+ for (const idx of Object.values(json.tables[tableName].indexes)) {
101
+ statements.push(
102
+ new CreateSqliteIndexConvertor().convert({
103
+ type: 'create_index',
104
+ tableName: tableName,
105
+ schema: '',
106
+ data: idx,
107
+ }),
108
+ );
109
+ }
110
+ return statements;
111
+ };
112
+
113
+ export const libSqlLogSuggestionsAndReturn = async (
114
+ connection: SQLiteDB,
115
+ statements: JsonStatement[],
116
+ json1: SQLiteSchemaSquashed,
117
+ json2: SQLiteSchemaSquashed,
118
+ meta: SQLiteSchemaInternal['_meta'],
119
+ ) => {
120
+ let shouldAskForApprove = false;
121
+ const statementsToExecute: string[] = [];
122
+ const infoToPrint: string[] = [];
123
+
124
+ const tablesToRemove: string[] = [];
125
+ const columnsToRemove: string[] = [];
126
+ const tablesToTruncate: string[] = [];
127
+
128
+ for (const statement of statements) {
129
+ if (statement.type === 'drop_table') {
130
+ const res = await connection.query<{ count: string }>(
131
+ `select count(*) as count from \`${statement.tableName}\``,
132
+ );
133
+ const count = Number(res[0].count);
134
+ if (count > 0) {
135
+ infoToPrint.push(
136
+ `· You're about to delete ${
137
+ chalk.underline(
138
+ statement.tableName,
139
+ )
140
+ } table with ${count} items`,
141
+ );
142
+ tablesToRemove.push(statement.tableName);
143
+ shouldAskForApprove = true;
144
+ }
145
+ const fromJsonStatement = fromJson([statement], 'turso', 'push', json2);
146
+ statementsToExecute.push(
147
+ ...(Array.isArray(fromJsonStatement) ? fromJsonStatement : [fromJsonStatement]),
148
+ );
149
+ } else if (statement.type === 'alter_table_drop_column') {
150
+ const tableName = statement.tableName;
151
+
152
+ const res = await connection.query<{ count: string }>(
153
+ `select count(*) as count from \`${tableName}\``,
154
+ );
155
+ const count = Number(res[0].count);
156
+ if (count > 0) {
157
+ infoToPrint.push(
158
+ `· You're about to delete ${
159
+ chalk.underline(
160
+ statement.columnName,
161
+ )
162
+ } column in ${tableName} table with ${count} items`,
163
+ );
164
+ columnsToRemove.push(`${tableName}_${statement.columnName}`);
165
+ shouldAskForApprove = true;
166
+ }
167
+
168
+ const fromJsonStatement = fromJson([statement], 'turso', 'push', json2);
169
+ statementsToExecute.push(
170
+ ...(Array.isArray(fromJsonStatement) ? fromJsonStatement : [fromJsonStatement]),
171
+ );
172
+ } else if (
173
+ statement.type === 'sqlite_alter_table_add_column'
174
+ && statement.column.notNull
175
+ && !statement.column.default
176
+ ) {
177
+ const newTableName = statement.tableName;
178
+ const res = await connection.query<{ count: string }>(
179
+ `select count(*) as count from \`${newTableName}\``,
180
+ );
181
+ const count = Number(res[0].count);
182
+ if (count > 0) {
183
+ infoToPrint.push(
184
+ `· You're about to add not-null ${
185
+ chalk.underline(
186
+ statement.column.name,
187
+ )
188
+ } column without default value, which contains ${count} items`,
189
+ );
190
+
191
+ tablesToTruncate.push(newTableName);
192
+ statementsToExecute.push(`delete from ${newTableName};`);
193
+
194
+ shouldAskForApprove = true;
195
+ }
196
+
197
+ const fromJsonStatement = fromJson([statement], 'turso', 'push', json2);
198
+ statementsToExecute.push(
199
+ ...(Array.isArray(fromJsonStatement) ? fromJsonStatement : [fromJsonStatement]),
200
+ );
201
+ } else if (statement.type === 'alter_table_alter_column_set_notnull') {
202
+ const tableName = statement.tableName;
203
+
204
+ if (
205
+ statement.type === 'alter_table_alter_column_set_notnull'
206
+ && typeof statement.columnDefault === 'undefined'
207
+ ) {
208
+ const res = await connection.query<{ count: string }>(
209
+ `select count(*) as count from \`${tableName}\``,
210
+ );
211
+ const count = Number(res[0].count);
212
+ if (count > 0) {
213
+ infoToPrint.push(
214
+ `· You're about to add not-null constraint to ${
215
+ chalk.underline(
216
+ statement.columnName,
217
+ )
218
+ } column without default value, which contains ${count} items`,
219
+ );
220
+
221
+ tablesToTruncate.push(tableName);
222
+ statementsToExecute.push(`delete from \`${tableName}\``);
223
+ shouldAskForApprove = true;
224
+ }
225
+ }
226
+
227
+ const modifyStatements = new LibSQLModifyColumn().convert(statement, json2);
228
+
229
+ statementsToExecute.push(
230
+ ...(Array.isArray(modifyStatements) ? modifyStatements : [modifyStatements]),
231
+ );
232
+ } else if (statement.type === 'recreate_table') {
233
+ const tableName = statement.tableName;
234
+
235
+ let dataLoss = false;
236
+
237
+ const oldTableName = getOldTableName(tableName, meta);
238
+
239
+ const prevColumnNames = Object.keys(json1.tables[oldTableName].columns);
240
+ const currentColumnNames = Object.keys(json2.tables[tableName].columns);
241
+ const { removedColumns, addedColumns } = findAddedAndRemoved(
242
+ prevColumnNames,
243
+ currentColumnNames,
244
+ );
245
+
246
+ if (removedColumns.length) {
247
+ for (const removedColumn of removedColumns) {
248
+ const res = await connection.query<{ count: string }>(
249
+ `select count(\`${tableName}\`.\`${removedColumn}\`) as count from \`${tableName}\``,
250
+ );
251
+
252
+ const count = Number(res[0].count);
253
+ if (count > 0) {
254
+ infoToPrint.push(
255
+ `· You're about to delete ${
256
+ chalk.underline(
257
+ removedColumn,
258
+ )
259
+ } column in ${tableName} table with ${count} items`,
260
+ );
261
+ columnsToRemove.push(removedColumn);
262
+ shouldAskForApprove = true;
263
+ }
264
+ }
265
+ }
266
+
267
+ if (addedColumns.length) {
268
+ for (const addedColumn of addedColumns) {
269
+ const [res] = await connection.query<{ count: string }>(
270
+ `select count(*) as count from \`${tableName}\``,
271
+ );
272
+
273
+ const columnConf = json2.tables[tableName].columns[addedColumn];
274
+
275
+ const count = Number(res.count);
276
+ if (count > 0 && columnConf.notNull && !columnConf.default) {
277
+ dataLoss = true;
278
+
279
+ infoToPrint.push(
280
+ `· You're about to add not-null ${
281
+ chalk.underline(
282
+ addedColumn,
283
+ )
284
+ } column without default value to table, which contains ${count} items`,
285
+ );
286
+ shouldAskForApprove = true;
287
+ tablesToTruncate.push(tableName);
288
+
289
+ statementsToExecute.push(`DELETE FROM \`${tableName}\`;`);
290
+ }
291
+ }
292
+ }
293
+
294
+ // check if some tables referencing current for pragma
295
+ const tablesReferencingCurrent: string[] = [];
296
+
297
+ for (const table of Object.values(json2.tables)) {
298
+ const tablesRefs = Object.values(json2.tables[table.name].foreignKeys)
299
+ .filter((t) => SQLiteSquasher.unsquashPushFK(t).tableTo === tableName)
300
+ .map((it) => SQLiteSquasher.unsquashPushFK(it).tableFrom);
301
+
302
+ tablesReferencingCurrent.push(...tablesRefs);
303
+ }
304
+
305
+ if (!tablesReferencingCurrent.length) {
306
+ statementsToExecute.push(..._moveDataStatements(tableName, json2, dataLoss));
307
+ continue;
308
+ }
309
+
310
+ // recreate table
311
+ statementsToExecute.push(
312
+ ..._moveDataStatements(tableName, json2, dataLoss),
313
+ );
314
+ } else if (
315
+ statement.type === 'alter_table_alter_column_set_generated'
316
+ || statement.type === 'alter_table_alter_column_drop_generated'
317
+ ) {
318
+ const tableName = statement.tableName;
319
+
320
+ const res = await connection.query<{ count: string }>(
321
+ `select count("${statement.columnName}") as count from \`${tableName}\``,
322
+ );
323
+ const count = Number(res[0].count);
324
+ if (count > 0) {
325
+ infoToPrint.push(
326
+ `· You're about to delete ${
327
+ chalk.underline(
328
+ statement.columnName,
329
+ )
330
+ } column in ${tableName} table with ${count} items`,
331
+ );
332
+ columnsToRemove.push(`${tableName}_${statement.columnName}`);
333
+ shouldAskForApprove = true;
334
+ }
335
+ const fromJsonStatement = fromJson([statement], 'turso', 'push', json2);
336
+ statementsToExecute.push(
337
+ ...(Array.isArray(fromJsonStatement) ? fromJsonStatement : [fromJsonStatement]),
338
+ );
339
+ } else {
340
+ const fromJsonStatement = fromJson([statement], 'turso', 'push', json2);
341
+ statementsToExecute.push(
342
+ ...(Array.isArray(fromJsonStatement) ? fromJsonStatement : [fromJsonStatement]),
343
+ );
344
+ }
345
+ }
346
+
347
+ return {
348
+ statementsToExecute: [...new Set(statementsToExecute)],
349
+ shouldAskForApprove,
350
+ infoToPrint,
351
+ columnsToRemove: [...new Set(columnsToRemove)],
352
+ tablesToTruncate: [...new Set(tablesToTruncate)],
353
+ tablesToRemove: [...new Set(tablesToRemove)],
354
+ };
355
+ };