@remix-run/data-table 0.1.0 → 0.2.0
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.
- package/README.md +306 -55
- package/dist/index.d.ts +9 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/lib/adapter.d.ts +386 -16
- package/dist/lib/adapter.d.ts.map +1 -1
- package/dist/lib/column.d.ts +193 -0
- package/dist/lib/column.d.ts.map +1 -0
- package/dist/lib/column.js +302 -0
- package/dist/lib/database/execution-context.d.ts +10 -0
- package/dist/lib/database/execution-context.d.ts.map +1 -0
- package/dist/lib/database/execution-context.js +1 -0
- package/dist/lib/database/helpers.d.ts +26 -0
- package/dist/lib/database/helpers.d.ts.map +1 -0
- package/dist/lib/database/helpers.js +116 -0
- package/dist/lib/database/query-execution.d.ts +7 -0
- package/dist/lib/database/query-execution.d.ts.map +1 -0
- package/dist/lib/database/query-execution.js +401 -0
- package/dist/lib/database/relations.d.ts +4 -0
- package/dist/lib/database/relations.d.ts.map +1 -0
- package/dist/lib/database/relations.js +207 -0
- package/dist/lib/database/write-lifecycle.d.ts +13 -0
- package/dist/lib/database/write-lifecycle.d.ts.map +1 -0
- package/dist/lib/database/write-lifecycle.js +279 -0
- package/dist/lib/database.d.ts +141 -238
- package/dist/lib/database.d.ts.map +1 -1
- package/dist/lib/database.js +73 -1122
- package/dist/lib/errors.d.ts +9 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +9 -0
- package/dist/lib/migrations/filename.d.ts +12 -0
- package/dist/lib/migrations/filename.d.ts.map +1 -0
- package/dist/lib/migrations/filename.js +20 -0
- package/dist/lib/migrations/helpers.d.ts +11 -0
- package/dist/lib/migrations/helpers.d.ts.map +1 -0
- package/dist/lib/migrations/helpers.js +77 -0
- package/dist/lib/migrations/journal-store.d.ts +15 -0
- package/dist/lib/migrations/journal-store.d.ts.map +1 -0
- package/dist/lib/migrations/journal-store.js +83 -0
- package/dist/lib/migrations/registry.d.ts +27 -0
- package/dist/lib/migrations/registry.d.ts.map +1 -0
- package/dist/lib/migrations/registry.js +51 -0
- package/dist/lib/migrations/runner.d.ts +20 -0
- package/dist/lib/migrations/runner.d.ts.map +1 -0
- package/dist/lib/migrations/runner.js +273 -0
- package/dist/lib/migrations/schema-api.d.ts +7 -0
- package/dist/lib/migrations/schema-api.d.ts.map +1 -0
- package/dist/lib/migrations/schema-api.js +326 -0
- package/dist/lib/migrations-node.d.ts +17 -0
- package/dist/lib/migrations-node.d.ts.map +1 -0
- package/dist/lib/migrations-node.js +65 -0
- package/dist/lib/migrations.d.ts +292 -0
- package/dist/lib/migrations.d.ts.map +1 -0
- package/dist/lib/migrations.js +38 -0
- package/dist/lib/operators.d.ts +3 -0
- package/dist/lib/operators.d.ts.map +1 -1
- package/dist/lib/query.d.ts +159 -0
- package/dist/lib/query.d.ts.map +1 -0
- package/dist/lib/query.js +401 -0
- package/dist/lib/references.d.ts +0 -1
- package/dist/lib/references.d.ts.map +1 -1
- package/dist/lib/sql-helpers.d.ts +50 -0
- package/dist/lib/sql-helpers.d.ts.map +1 -0
- package/dist/lib/sql-helpers.js +111 -0
- package/dist/lib/sql.d.ts +23 -6
- package/dist/lib/sql.d.ts.map +1 -1
- package/dist/lib/sql.js +19 -5
- package/dist/lib/table.d.ts +355 -40
- package/dist/lib/table.d.ts.map +1 -1
- package/dist/lib/table.js +113 -90
- package/dist/migrations/node.d.ts +2 -0
- package/dist/migrations/node.d.ts.map +1 -0
- package/dist/migrations/node.js +1 -0
- package/dist/migrations.d.ts +8 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +5 -0
- package/dist/operators.d.ts +3 -0
- package/dist/operators.d.ts.map +1 -0
- package/dist/operators.js +1 -0
- package/dist/sql-helpers.d.ts +3 -0
- package/dist/sql-helpers.d.ts.map +1 -0
- package/dist/sql-helpers.js +1 -0
- package/package.json +23 -8
- package/src/index.ts +93 -10
- package/src/lib/adapter.ts +469 -25
- package/src/lib/column.ts +384 -0
- package/src/lib/database/execution-context.ts +15 -0
- package/src/lib/database/helpers.ts +216 -0
- package/src/lib/database/query-execution.ts +638 -0
- package/src/lib/database/relations.ts +332 -0
- package/src/lib/database/write-lifecycle.ts +487 -0
- package/src/lib/database.ts +246 -1848
- package/src/lib/errors.ts +10 -0
- package/src/lib/migrations/filename.ts +25 -0
- package/src/lib/migrations/helpers.ts +108 -0
- package/src/lib/migrations/journal-store.ts +122 -0
- package/src/lib/migrations/registry.ts +62 -0
- package/src/lib/migrations/runner.ts +374 -0
- package/src/lib/migrations/schema-api.ts +417 -0
- package/src/lib/migrations-node.ts +71 -0
- package/src/lib/migrations.ts +328 -0
- package/src/lib/operators.ts +3 -0
- package/src/lib/query.ts +958 -0
- package/src/lib/references.ts +0 -1
- package/src/lib/sql-helpers.ts +146 -0
- package/src/lib/sql.ts +23 -6
- package/src/lib/table.ts +484 -156
- package/src/migrations/node.ts +1 -0
- package/src/migrations.ts +26 -0
- package/src/operators.ts +18 -0
- package/src/sql-helpers.ts +9 -0
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import type { Database } from '../database.ts'
|
|
2
|
+
import type {
|
|
3
|
+
AlterTableChange,
|
|
4
|
+
CheckConstraint,
|
|
5
|
+
ColumnDefinition,
|
|
6
|
+
CreateTableOperation,
|
|
7
|
+
DataMigrationOperation,
|
|
8
|
+
ForeignKeyConstraint,
|
|
9
|
+
PrimaryKeyConstraint,
|
|
10
|
+
TableRef,
|
|
11
|
+
TransactionToken,
|
|
12
|
+
UniqueConstraint,
|
|
13
|
+
} from '../adapter.ts'
|
|
14
|
+
import { rawSql } from '../sql.ts'
|
|
15
|
+
import { getTableColumnDefinitions, getTableName, getTablePrimaryKey } from '../table.ts'
|
|
16
|
+
import type { AnyTable } from '../table.ts'
|
|
17
|
+
import type {
|
|
18
|
+
AlterTableBuilder,
|
|
19
|
+
CreateIndexOptions,
|
|
20
|
+
ForeignKeyOptions,
|
|
21
|
+
KeyColumns,
|
|
22
|
+
MigrationSchema,
|
|
23
|
+
NamedConstraintOptions,
|
|
24
|
+
TableInput,
|
|
25
|
+
} from '../migrations.ts'
|
|
26
|
+
|
|
27
|
+
import { ColumnBuilder } from '../column.ts'
|
|
28
|
+
import {
|
|
29
|
+
createCheckName,
|
|
30
|
+
createForeignKeyName,
|
|
31
|
+
createIndexName,
|
|
32
|
+
createPrimaryKeyName,
|
|
33
|
+
createUniqueName,
|
|
34
|
+
normalizeIndexColumns,
|
|
35
|
+
normalizeKeyColumns,
|
|
36
|
+
toTableRef,
|
|
37
|
+
} from './helpers.ts'
|
|
38
|
+
|
|
39
|
+
function asColumnDefinition(definition: ColumnDefinition | ColumnBuilder): ColumnDefinition {
|
|
40
|
+
if (definition instanceof ColumnBuilder) {
|
|
41
|
+
return definition.build()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return definition
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function asTableRef(value: TableInput): TableRef {
|
|
48
|
+
if (typeof value === 'string') {
|
|
49
|
+
return toTableRef(value)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return toTableRef(getTableName(value))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function lowerTableForCreate(table: AnyTable): CreateTableOperation {
|
|
56
|
+
let tableRef = toTableRef(getTableName(table))
|
|
57
|
+
let sourceColumnDefinitions = getTableColumnDefinitions(table)
|
|
58
|
+
let columns: Record<string, ColumnDefinition> = {}
|
|
59
|
+
let uniques: UniqueConstraint[] = []
|
|
60
|
+
let checks: CheckConstraint[] = []
|
|
61
|
+
let foreignKeys: ForeignKeyConstraint[] = []
|
|
62
|
+
|
|
63
|
+
for (let columnName in sourceColumnDefinitions) {
|
|
64
|
+
if (!Object.prototype.hasOwnProperty.call(sourceColumnDefinitions, columnName)) {
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let sourceDefinition = sourceColumnDefinitions[columnName]
|
|
69
|
+
let columnDefinition: ColumnDefinition = {
|
|
70
|
+
...sourceDefinition,
|
|
71
|
+
checks: undefined,
|
|
72
|
+
references: undefined,
|
|
73
|
+
primaryKey: undefined,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let unique = sourceDefinition.unique
|
|
77
|
+
|
|
78
|
+
if (unique) {
|
|
79
|
+
let uniqueName =
|
|
80
|
+
typeof unique === 'object' && unique.name
|
|
81
|
+
? unique.name
|
|
82
|
+
: createUniqueName(tableRef, [columnName])
|
|
83
|
+
uniques.push({
|
|
84
|
+
name: uniqueName,
|
|
85
|
+
columns: [columnName],
|
|
86
|
+
})
|
|
87
|
+
columnDefinition.unique = undefined
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (sourceDefinition.checks) {
|
|
91
|
+
for (let check of sourceDefinition.checks) {
|
|
92
|
+
checks.push({
|
|
93
|
+
name: check.name || createCheckName(tableRef, check.expression),
|
|
94
|
+
expression: check.expression,
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (sourceDefinition.references) {
|
|
100
|
+
let referenceColumns = [...sourceDefinition.references.columns]
|
|
101
|
+
let referencesTable = { ...sourceDefinition.references.table }
|
|
102
|
+
foreignKeys.push({
|
|
103
|
+
name:
|
|
104
|
+
sourceDefinition.references.name ||
|
|
105
|
+
createForeignKeyName(tableRef, [columnName], referencesTable, referenceColumns),
|
|
106
|
+
columns: [columnName],
|
|
107
|
+
references: {
|
|
108
|
+
table: referencesTable,
|
|
109
|
+
columns: referenceColumns,
|
|
110
|
+
},
|
|
111
|
+
onDelete: sourceDefinition.references.onDelete,
|
|
112
|
+
onUpdate: sourceDefinition.references.onUpdate,
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
columns[columnName] = columnDefinition
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let primaryKeyColumns = [...getTablePrimaryKey(table)]
|
|
120
|
+
let primaryKey: PrimaryKeyConstraint | undefined
|
|
121
|
+
|
|
122
|
+
if (primaryKeyColumns.length > 0) {
|
|
123
|
+
primaryKey = {
|
|
124
|
+
columns: primaryKeyColumns,
|
|
125
|
+
name: createPrimaryKeyName(tableRef),
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
kind: 'createTable',
|
|
131
|
+
table: tableRef,
|
|
132
|
+
columns,
|
|
133
|
+
primaryKey,
|
|
134
|
+
uniques: uniques.length > 0 ? uniques : undefined,
|
|
135
|
+
checks: checks.length > 0 ? checks : undefined,
|
|
136
|
+
foreignKeys: foreignKeys.length > 0 ? foreignKeys : undefined,
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
class AlterTableBuilderRuntime implements AlterTableBuilder {
|
|
141
|
+
alterChanges: AlterTableChange[] = []
|
|
142
|
+
extraStatements: DataMigrationOperation[] = []
|
|
143
|
+
table: TableRef
|
|
144
|
+
|
|
145
|
+
constructor(table: TableRef) {
|
|
146
|
+
this.table = table
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
addColumn(name: string, definition: ColumnDefinition | ColumnBuilder): void {
|
|
150
|
+
this.alterChanges.push({
|
|
151
|
+
kind: 'addColumn',
|
|
152
|
+
column: name,
|
|
153
|
+
definition: asColumnDefinition(definition),
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
changeColumn(name: string, definition: ColumnDefinition | ColumnBuilder): void {
|
|
158
|
+
this.alterChanges.push({
|
|
159
|
+
kind: 'changeColumn',
|
|
160
|
+
column: name,
|
|
161
|
+
definition: asColumnDefinition(definition),
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
renameColumn(from: string, to: string): void {
|
|
166
|
+
this.alterChanges.push({ kind: 'renameColumn', from, to })
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
dropColumn(name: string, options?: { ifExists?: boolean }): void {
|
|
170
|
+
this.alterChanges.push({ kind: 'dropColumn', column: name, ifExists: options?.ifExists })
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
addPrimaryKey(columns: KeyColumns, options?: NamedConstraintOptions): void {
|
|
174
|
+
let normalizedColumns = normalizeKeyColumns(columns)
|
|
175
|
+
this.alterChanges.push({
|
|
176
|
+
kind: 'addPrimaryKey',
|
|
177
|
+
constraint: {
|
|
178
|
+
columns: normalizedColumns,
|
|
179
|
+
name: options?.name ?? createPrimaryKeyName(this.table),
|
|
180
|
+
},
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
dropPrimaryKey(name: string): void {
|
|
185
|
+
this.alterChanges.push({ kind: 'dropPrimaryKey', name })
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
addUnique(columns: KeyColumns, options?: NamedConstraintOptions): void {
|
|
189
|
+
let normalizedColumns = normalizeKeyColumns(columns)
|
|
190
|
+
this.alterChanges.push({
|
|
191
|
+
kind: 'addUnique',
|
|
192
|
+
constraint: {
|
|
193
|
+
columns: normalizedColumns,
|
|
194
|
+
name: options?.name ?? createUniqueName(this.table, normalizedColumns),
|
|
195
|
+
},
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
dropUnique(name: string): void {
|
|
200
|
+
this.alterChanges.push({ kind: 'dropUnique', name })
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
addForeignKey(
|
|
204
|
+
columns: KeyColumns,
|
|
205
|
+
refTable: TableInput,
|
|
206
|
+
refColumns?: KeyColumns,
|
|
207
|
+
options?: ForeignKeyOptions,
|
|
208
|
+
): void {
|
|
209
|
+
let normalizedColumns = normalizeKeyColumns(columns)
|
|
210
|
+
let normalizedReferenceColumns = refColumns ? normalizeKeyColumns(refColumns) : ['id']
|
|
211
|
+
let referenceTable = asTableRef(refTable)
|
|
212
|
+
this.alterChanges.push({
|
|
213
|
+
kind: 'addForeignKey',
|
|
214
|
+
constraint: {
|
|
215
|
+
columns: normalizedColumns,
|
|
216
|
+
references: {
|
|
217
|
+
table: referenceTable,
|
|
218
|
+
columns: normalizedReferenceColumns,
|
|
219
|
+
},
|
|
220
|
+
name:
|
|
221
|
+
options?.name ??
|
|
222
|
+
createForeignKeyName(
|
|
223
|
+
this.table,
|
|
224
|
+
normalizedColumns,
|
|
225
|
+
referenceTable,
|
|
226
|
+
normalizedReferenceColumns,
|
|
227
|
+
),
|
|
228
|
+
onDelete: options?.onDelete,
|
|
229
|
+
onUpdate: options?.onUpdate,
|
|
230
|
+
},
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
dropForeignKey(name: string): void {
|
|
235
|
+
this.alterChanges.push({ kind: 'dropForeignKey', name })
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
addCheck(expression: string, options?: NamedConstraintOptions): void {
|
|
239
|
+
this.alterChanges.push({
|
|
240
|
+
kind: 'addCheck',
|
|
241
|
+
constraint: {
|
|
242
|
+
expression,
|
|
243
|
+
name: options?.name ?? createCheckName(this.table, expression),
|
|
244
|
+
},
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
dropCheck(name: string): void {
|
|
249
|
+
this.alterChanges.push({ kind: 'dropCheck', name })
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
addIndex(columns: string | string[], options?: CreateIndexOptions): void {
|
|
253
|
+
let normalizedColumns = normalizeIndexColumns(columns)
|
|
254
|
+
let { name, ifNotExists, ...indexOptions } = options ?? {}
|
|
255
|
+
this.extraStatements.push({
|
|
256
|
+
kind: 'createIndex',
|
|
257
|
+
index: {
|
|
258
|
+
table: this.table,
|
|
259
|
+
name: name ?? createIndexName(this.table, normalizedColumns),
|
|
260
|
+
columns: normalizedColumns,
|
|
261
|
+
...indexOptions,
|
|
262
|
+
},
|
|
263
|
+
ifNotExists,
|
|
264
|
+
})
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
dropIndex(name: string): void {
|
|
268
|
+
this.extraStatements.push({
|
|
269
|
+
kind: 'dropIndex',
|
|
270
|
+
table: this.table,
|
|
271
|
+
name,
|
|
272
|
+
})
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
comment(text: string): void {
|
|
276
|
+
this.alterChanges.push({ kind: 'setTableComment', comment: text })
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function createMigrationSchema(
|
|
281
|
+
db: Database,
|
|
282
|
+
emit: (operation: DataMigrationOperation) => Promise<void>,
|
|
283
|
+
options?: { transaction?: TransactionToken },
|
|
284
|
+
): MigrationSchema {
|
|
285
|
+
return {
|
|
286
|
+
async createTable(table, options) {
|
|
287
|
+
let operation = lowerTableForCreate(table)
|
|
288
|
+
operation.ifNotExists = options?.ifNotExists
|
|
289
|
+
await emit(operation)
|
|
290
|
+
},
|
|
291
|
+
async alterTable(input, migrate, options) {
|
|
292
|
+
let tableRef = asTableRef(input)
|
|
293
|
+
let builder = new AlterTableBuilderRuntime(tableRef)
|
|
294
|
+
migrate(builder)
|
|
295
|
+
|
|
296
|
+
if (builder.alterChanges.length > 0) {
|
|
297
|
+
await emit({
|
|
298
|
+
kind: 'alterTable',
|
|
299
|
+
table: tableRef,
|
|
300
|
+
changes: builder.alterChanges,
|
|
301
|
+
ifExists: options?.ifExists,
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
for (let operation of builder.extraStatements) {
|
|
306
|
+
await emit(operation)
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
async renameTable(from, to) {
|
|
310
|
+
await emit({ kind: 'renameTable', from: asTableRef(from), to: toTableRef(to) })
|
|
311
|
+
},
|
|
312
|
+
async dropTable(table, options) {
|
|
313
|
+
await emit({
|
|
314
|
+
kind: 'dropTable',
|
|
315
|
+
table: asTableRef(table),
|
|
316
|
+
ifExists: options?.ifExists,
|
|
317
|
+
cascade: options?.cascade,
|
|
318
|
+
})
|
|
319
|
+
},
|
|
320
|
+
async createIndex(table, columns, options) {
|
|
321
|
+
let tableRef = asTableRef(table)
|
|
322
|
+
let normalizedColumns = normalizeIndexColumns(columns)
|
|
323
|
+
let { name, ifNotExists, ...indexOptions } = options ?? {}
|
|
324
|
+
await emit({
|
|
325
|
+
kind: 'createIndex',
|
|
326
|
+
index: {
|
|
327
|
+
table: tableRef,
|
|
328
|
+
name: name ?? createIndexName(tableRef, normalizedColumns),
|
|
329
|
+
columns: normalizedColumns,
|
|
330
|
+
...indexOptions,
|
|
331
|
+
},
|
|
332
|
+
ifNotExists,
|
|
333
|
+
})
|
|
334
|
+
},
|
|
335
|
+
async dropIndex(table, name, options) {
|
|
336
|
+
await emit({
|
|
337
|
+
kind: 'dropIndex',
|
|
338
|
+
table: asTableRef(table),
|
|
339
|
+
name,
|
|
340
|
+
ifExists: options?.ifExists,
|
|
341
|
+
})
|
|
342
|
+
},
|
|
343
|
+
async renameIndex(table, from, to) {
|
|
344
|
+
await emit({
|
|
345
|
+
kind: 'renameIndex',
|
|
346
|
+
table: asTableRef(table),
|
|
347
|
+
from,
|
|
348
|
+
to,
|
|
349
|
+
})
|
|
350
|
+
},
|
|
351
|
+
async addForeignKey(table, columns, refTable, refColumns, options) {
|
|
352
|
+
let tableRef = asTableRef(table)
|
|
353
|
+
let normalizedColumns = normalizeKeyColumns(columns)
|
|
354
|
+
let referenceTable = asTableRef(refTable)
|
|
355
|
+
let normalizedReferenceColumns = refColumns ? normalizeKeyColumns(refColumns) : ['id']
|
|
356
|
+
await emit({
|
|
357
|
+
kind: 'addForeignKey',
|
|
358
|
+
table: tableRef,
|
|
359
|
+
constraint: {
|
|
360
|
+
columns: normalizedColumns,
|
|
361
|
+
references: {
|
|
362
|
+
table: referenceTable,
|
|
363
|
+
columns: normalizedReferenceColumns,
|
|
364
|
+
},
|
|
365
|
+
name:
|
|
366
|
+
options?.name ??
|
|
367
|
+
createForeignKeyName(
|
|
368
|
+
tableRef,
|
|
369
|
+
normalizedColumns,
|
|
370
|
+
referenceTable,
|
|
371
|
+
normalizedReferenceColumns,
|
|
372
|
+
),
|
|
373
|
+
onDelete: options?.onDelete,
|
|
374
|
+
onUpdate: options?.onUpdate,
|
|
375
|
+
},
|
|
376
|
+
})
|
|
377
|
+
},
|
|
378
|
+
async dropForeignKey(table, name) {
|
|
379
|
+
await emit({
|
|
380
|
+
kind: 'dropForeignKey',
|
|
381
|
+
table: asTableRef(table),
|
|
382
|
+
name,
|
|
383
|
+
})
|
|
384
|
+
},
|
|
385
|
+
async addCheck(table, expression, options) {
|
|
386
|
+
let tableRef = asTableRef(table)
|
|
387
|
+
await emit({
|
|
388
|
+
kind: 'addCheck',
|
|
389
|
+
table: tableRef,
|
|
390
|
+
constraint: {
|
|
391
|
+
expression,
|
|
392
|
+
name: options?.name ?? createCheckName(tableRef, expression),
|
|
393
|
+
},
|
|
394
|
+
})
|
|
395
|
+
},
|
|
396
|
+
async dropCheck(table, name) {
|
|
397
|
+
await emit({
|
|
398
|
+
kind: 'dropCheck',
|
|
399
|
+
table: asTableRef(table),
|
|
400
|
+
name,
|
|
401
|
+
})
|
|
402
|
+
},
|
|
403
|
+
async plan(sql) {
|
|
404
|
+
let statement = typeof sql === 'string' ? rawSql(sql) : sql
|
|
405
|
+
await emit({
|
|
406
|
+
kind: 'raw',
|
|
407
|
+
sql: statement,
|
|
408
|
+
})
|
|
409
|
+
},
|
|
410
|
+
async hasTable(table) {
|
|
411
|
+
return db.adapter.hasTable(asTableRef(table), options?.transaction)
|
|
412
|
+
},
|
|
413
|
+
async hasColumn(table, columnName) {
|
|
414
|
+
return db.adapter.hasColumn(asTableRef(table), columnName, options?.transaction)
|
|
415
|
+
},
|
|
416
|
+
}
|
|
417
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { promises as fs } from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { pathToFileURL } from 'node:url'
|
|
5
|
+
import type { Migration, MigrationDescriptor } from './migrations.ts'
|
|
6
|
+
import { parseMigrationFilename } from './migrations/filename.ts'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Loads migration modules from a directory on Node.js.
|
|
10
|
+
*
|
|
11
|
+
* Filenames are used to infer migration `id` and `name`.
|
|
12
|
+
* Each file must default-export `createMigration(...)`.
|
|
13
|
+
* @param directory Absolute or relative directory containing migration files.
|
|
14
|
+
* @returns A sorted list of loaded migration descriptors.
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { loadMigrations } from 'remix/data-table/migrations/node'
|
|
18
|
+
*
|
|
19
|
+
* let migrations = await loadMigrations('./app/db/migrations')
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export async function loadMigrations(directory: string): Promise<MigrationDescriptor[]> {
|
|
23
|
+
let allFiles = (await fs.readdir(directory, { withFileTypes: true }))
|
|
24
|
+
.filter((entry) => entry.isFile())
|
|
25
|
+
.map((entry) => entry.name)
|
|
26
|
+
.sort((left, right) => left.localeCompare(right))
|
|
27
|
+
let files: Array<{ file: string; id: string; name: string }> = []
|
|
28
|
+
|
|
29
|
+
for (let file of allFiles) {
|
|
30
|
+
if (!/\.(?:m?ts|m?js|cts|cjs)$/.test(file)) {
|
|
31
|
+
continue
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let parsed = parseMigrationFilename(file)
|
|
35
|
+
files.push({ file, id: parsed.id, name: parsed.name })
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let migrations: MigrationDescriptor[] = []
|
|
39
|
+
let seenIds = new Set<string>()
|
|
40
|
+
|
|
41
|
+
for (let entry of files) {
|
|
42
|
+
if (seenIds.has(entry.id)) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
'Duplicate migration id "' + entry.id + '" inferred from filename "' + entry.file + '"',
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
seenIds.add(entry.id)
|
|
49
|
+
let fullPath = path.join(directory, entry.file)
|
|
50
|
+
let source = await fs.readFile(fullPath, 'utf8')
|
|
51
|
+
let checksum = createHash('sha256').update(source).digest('hex')
|
|
52
|
+
let module = (await import(pathToFileURL(fullPath).href)) as { default?: Migration }
|
|
53
|
+
let migration = module.default
|
|
54
|
+
|
|
55
|
+
if (!migration || typeof migration.up !== 'function' || typeof migration.down !== 'function') {
|
|
56
|
+
throw new Error(
|
|
57
|
+
'Migration file "' + entry.file + '" must default-export createMigration(...)',
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
migrations.push({
|
|
62
|
+
id: entry.id,
|
|
63
|
+
name: entry.name,
|
|
64
|
+
path: fullPath,
|
|
65
|
+
checksum,
|
|
66
|
+
migration,
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return migrations
|
|
71
|
+
}
|