opacacms 0.3.2 → 0.3.3
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/dist/admin/index.js +1 -1
- package/dist/admin/react.js +1 -1
- package/dist/admin/vue.js +1 -1
- package/dist/admin/webcomponent.js +35 -37
- package/dist/{chunk-g9bxb6h0.js → chunk-2fm4kv2q.js} +1 -1
- package/dist/chunk-2vbfc4q8.js +6 -0
- package/dist/{chunk-adq2b75c.js → chunk-40tky6qh.js} +2 -2
- package/dist/{chunk-e0g6gn7n.js → chunk-49e16hjg.js} +3 -3
- package/dist/{chunk-fnsf1dfm.js → chunk-526a3gqx.js} +1 -1
- package/dist/{chunk-sqsfk9p4.js → chunk-6m1jhxmd.js} +1 -1
- package/dist/{chunk-6bywt602.js → chunk-8sqjbsgt.js} +1 -26
- package/dist/{chunk-n1twhqmf.js → chunk-acghejk8.js} +1 -1
- package/dist/{chunk-m24yqkeq.js → chunk-b1g8jmth.js} +3 -3
- package/dist/{chunk-5422w4eq.js → chunk-cm5rvcnn.js} +5 -5
- package/dist/{chunk-941zxavt.js → chunk-h2y2t07h.js} +4 -4
- package/dist/{chunk-6qs0g65f.js → chunk-h8v093av.js} +1 -1
- package/dist/{chunk-m5ems3hh.js → chunk-hthm9srb.js} +1 -1
- package/dist/{chunk-2k3ysje3.js → chunk-nch158fe.js} +1 -1
- package/dist/{chunk-naqcqj8n.js → chunk-pj31j6j0.js} +4 -4
- package/dist/{chunk-qsh2nqz3.js → chunk-pw2a9war.js} +3 -3
- package/dist/{chunk-j8js1y0h.js → chunk-r5k7jw66.js} +1 -1
- package/dist/{chunk-48ywpd0a.js → chunk-vmz9ncf1.js} +1 -1
- package/dist/{chunk-qhdsjek6.js → chunk-wry3rqh0.js} +3 -3
- package/dist/cli/index.js +6793 -6
- package/dist/client.js +3 -3
- package/dist/db/better-sqlite.js +4 -4
- package/dist/db/bun-sqlite.js +4 -4
- package/dist/db/d1.js +4 -4
- package/dist/db/index.js +8 -8
- package/dist/db/postgres.js +4 -4
- package/dist/db/sqlite.js +4 -4
- package/dist/index.js +7 -7
- package/dist/runtimes/bun.js +6 -6
- package/dist/runtimes/cloudflare-workers.js +6 -6
- package/dist/runtimes/next.js +6 -6
- package/dist/runtimes/node.js +6 -6
- package/dist/schema/index.js +3 -3
- package/dist/server.js +6 -6
- package/dist/storage/index.js +1 -1
- package/package.json +11 -10
- package/dist/chunk-0hxz770x.js +0 -10
- package/dist/chunk-2gdsy99f.js +0 -581
- package/dist/chunk-3j9zjfmn.js +0 -376
- package/dist/chunk-5b8r0v8c.js +0 -47
- package/dist/chunk-71wwx9vj.js +0 -413
- package/dist/chunk-9by912e9.js +0 -318
- package/dist/chunk-f3dg5dq4.js +0 -75
- package/dist/chunk-g17v7yfr.js +0 -237
- package/dist/chunk-gzdfc1ct.js +0 -1137
- package/dist/chunk-h6dhexzr.js +0 -94
- package/dist/chunk-jvv72110.js +0 -98
- package/dist/chunk-rg3jrfgg.js +0 -93
- package/dist/chunk-rjvcp6ph.js +0 -95
- package/dist/chunk-v0nazhmk.js +0 -263
- package/dist/chunk-wqvdwck9.js +0 -326
- package/dist/chunk-x7bnzswh.js +0 -174
- package/dist/chunk-y4e9twg2.js +0 -76
package/dist/chunk-2gdsy99f.js
DELETED
|
@@ -1,581 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Ct,
|
|
3
|
-
Jt,
|
|
4
|
-
Rt,
|
|
5
|
-
Wt
|
|
6
|
-
} from "./chunk-gzdfc1ct.js";
|
|
7
|
-
import {
|
|
8
|
-
flattenFields,
|
|
9
|
-
getRelationalFields,
|
|
10
|
-
mapFieldToPostgresType,
|
|
11
|
-
mapFieldToSQLiteType,
|
|
12
|
-
toSnakeCase
|
|
13
|
-
} from "./chunk-qxt9vge8.js";
|
|
14
|
-
import {
|
|
15
|
-
getSystemCollections,
|
|
16
|
-
init_system_schema
|
|
17
|
-
} from "./chunk-6qs0g65f.js";
|
|
18
|
-
|
|
19
|
-
// src/db/kysely/snapshot/snapshot-manager.ts
|
|
20
|
-
init_system_schema();
|
|
21
|
-
import fs from "node:fs";
|
|
22
|
-
import { resolve } from "node:path";
|
|
23
|
-
function createSchemaSnapshot(collections, globals, dialect) {
|
|
24
|
-
const allSchemas = [...getSystemCollections(), ...collections, ...globals];
|
|
25
|
-
const mapType = dialect === "postgres" ? mapFieldToPostgresType : mapFieldToSQLiteType;
|
|
26
|
-
const snapshot = { tables: {} };
|
|
27
|
-
for (const collection of allSchemas) {
|
|
28
|
-
const tableName = toSnakeCase(collection.slug);
|
|
29
|
-
const table = { name: tableName, columns: {} };
|
|
30
|
-
table.columns["id"] = { name: "id", type: "text", required: true, unique: true };
|
|
31
|
-
const flattenedFields = flattenFields(collection.fields);
|
|
32
|
-
for (const field of flattenedFields) {
|
|
33
|
-
if (field.type === "relationship" && "hasMany" in field && field.hasMany)
|
|
34
|
-
continue;
|
|
35
|
-
const colName = toSnakeCase(field.name);
|
|
36
|
-
if (colName === "id")
|
|
37
|
-
continue;
|
|
38
|
-
table.columns[colName] = {
|
|
39
|
-
name: colName,
|
|
40
|
-
type: mapType(field),
|
|
41
|
-
required: field.required || false,
|
|
42
|
-
unique: field.unique || false,
|
|
43
|
-
defaultValue: field.defaultValue
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
if (collection.timestamps !== false) {
|
|
47
|
-
const config = typeof collection.timestamps === "object" ? collection.timestamps : {};
|
|
48
|
-
const createdField = toSnakeCase(config.createdAt || "createdAt");
|
|
49
|
-
const updatedField = toSnakeCase(config.updatedAt || "updatedAt");
|
|
50
|
-
const tsType = dialect === "postgres" ? "timestamp with time zone" : "text";
|
|
51
|
-
table.columns[createdField] = {
|
|
52
|
-
name: createdField,
|
|
53
|
-
type: tsType,
|
|
54
|
-
required: false,
|
|
55
|
-
unique: false
|
|
56
|
-
};
|
|
57
|
-
table.columns[updatedField] = {
|
|
58
|
-
name: updatedField,
|
|
59
|
-
type: tsType,
|
|
60
|
-
required: false,
|
|
61
|
-
unique: false
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
const versions = collection.versions;
|
|
65
|
-
if (versions?.drafts) {
|
|
66
|
-
table.columns["_status"] = {
|
|
67
|
-
name: "_status",
|
|
68
|
-
type: "text",
|
|
69
|
-
required: false,
|
|
70
|
-
unique: false,
|
|
71
|
-
defaultValue: "draft"
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
snapshot.tables[tableName] = table;
|
|
75
|
-
const relationalFields = getRelationalFields(collection.fields);
|
|
76
|
-
for (const field of relationalFields) {
|
|
77
|
-
if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
|
|
78
|
-
const colName = toSnakeCase(field.name);
|
|
79
|
-
const joinTableName = `${tableName}_${colName}_relations`.toLowerCase();
|
|
80
|
-
snapshot.tables[joinTableName] = {
|
|
81
|
-
name: joinTableName,
|
|
82
|
-
columns: {
|
|
83
|
-
id: { name: "id", type: "text", required: true, unique: true },
|
|
84
|
-
source_id: { name: "source_id", type: "text", required: true, unique: false },
|
|
85
|
-
target_id: { name: "target_id", type: "text", required: true, unique: false },
|
|
86
|
-
order: {
|
|
87
|
-
name: "order",
|
|
88
|
-
type: "integer",
|
|
89
|
-
required: false,
|
|
90
|
-
unique: false,
|
|
91
|
-
defaultValue: 0
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
for (const field of relationalFields) {
|
|
98
|
-
if (field.type === "blocks" && field.blocks && Array.isArray(field.blocks)) {
|
|
99
|
-
for (const block of field.blocks) {
|
|
100
|
-
const blockName = toSnakeCase(field.name);
|
|
101
|
-
const blockSlug = toSnakeCase(block.slug);
|
|
102
|
-
const blockTableName = `${tableName}_${blockName}_${blockSlug}`.toLowerCase();
|
|
103
|
-
const blockTable = {
|
|
104
|
-
name: blockTableName,
|
|
105
|
-
columns: {
|
|
106
|
-
id: { name: "id", type: "text", required: true, unique: true },
|
|
107
|
-
_parent_id: { name: "_parent_id", type: "text", required: true, unique: false },
|
|
108
|
-
_order: {
|
|
109
|
-
name: "_order",
|
|
110
|
-
type: "integer",
|
|
111
|
-
required: false,
|
|
112
|
-
unique: false,
|
|
113
|
-
defaultValue: 0
|
|
114
|
-
},
|
|
115
|
-
block_type: {
|
|
116
|
-
name: "block_type",
|
|
117
|
-
type: "text",
|
|
118
|
-
required: true,
|
|
119
|
-
unique: false,
|
|
120
|
-
defaultValue: block.slug
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
const blockFlattened = flattenFields(block.fields);
|
|
125
|
-
for (const bField of blockFlattened) {
|
|
126
|
-
const bColName = toSnakeCase(bField.name);
|
|
127
|
-
if (bColName === "id")
|
|
128
|
-
continue;
|
|
129
|
-
blockTable.columns[bColName] = {
|
|
130
|
-
name: bColName,
|
|
131
|
-
type: mapType(bField),
|
|
132
|
-
required: bField.required || false,
|
|
133
|
-
unique: bField.unique || false,
|
|
134
|
-
defaultValue: bField.defaultValue
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
const tsType = dialect === "postgres" ? "timestamp with time zone" : "text";
|
|
138
|
-
blockTable.columns["created_at"] = {
|
|
139
|
-
name: "created_at",
|
|
140
|
-
type: tsType,
|
|
141
|
-
required: false,
|
|
142
|
-
unique: false
|
|
143
|
-
};
|
|
144
|
-
blockTable.columns["updated_at"] = {
|
|
145
|
-
name: "updated_at",
|
|
146
|
-
type: tsType,
|
|
147
|
-
required: false,
|
|
148
|
-
unique: false
|
|
149
|
-
};
|
|
150
|
-
snapshot.tables[blockTableName] = blockTable;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return snapshot;
|
|
156
|
-
}
|
|
157
|
-
function saveSnapshot(migrationDir, snapshotName, snapshot) {
|
|
158
|
-
const metaDir = resolve(process.cwd(), migrationDir, "meta");
|
|
159
|
-
if (!fs.existsSync(metaDir)) {
|
|
160
|
-
fs.mkdirSync(metaDir, { recursive: true });
|
|
161
|
-
}
|
|
162
|
-
const filePath = resolve(metaDir, `${snapshotName}.json`);
|
|
163
|
-
fs.writeFileSync(filePath, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
164
|
-
const lastPath = resolve(metaDir, `_journal.json`);
|
|
165
|
-
let journal = { snapshots: [] };
|
|
166
|
-
if (fs.existsSync(lastPath)) {
|
|
167
|
-
try {
|
|
168
|
-
journal = JSON.parse(fs.readFileSync(lastPath, "utf-8"));
|
|
169
|
-
} catch (e) {}
|
|
170
|
-
}
|
|
171
|
-
journal.snapshots.push(snapshotName);
|
|
172
|
-
fs.writeFileSync(lastPath, JSON.stringify(journal, null, 2), "utf-8");
|
|
173
|
-
}
|
|
174
|
-
function loadLastSnapshot(migrationDir) {
|
|
175
|
-
const metaDir = resolve(process.cwd(), migrationDir, "meta");
|
|
176
|
-
const lastPath = resolve(metaDir, `_journal.json`);
|
|
177
|
-
if (!fs.existsSync(lastPath))
|
|
178
|
-
return null;
|
|
179
|
-
try {
|
|
180
|
-
const journal = JSON.parse(fs.readFileSync(lastPath, "utf-8"));
|
|
181
|
-
const lastSnapshotName = journal.snapshots[journal.snapshots.length - 1];
|
|
182
|
-
if (!lastSnapshotName)
|
|
183
|
-
return null;
|
|
184
|
-
const snapshotPath = resolve(metaDir, `${lastSnapshotName}.json`);
|
|
185
|
-
if (!fs.existsSync(snapshotPath))
|
|
186
|
-
return null;
|
|
187
|
-
return JSON.parse(fs.readFileSync(snapshotPath, "utf-8"));
|
|
188
|
-
} catch (e) {
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// src/cli/core/migrations/schema-diff-engine.ts
|
|
194
|
-
async function compareSchemas(previous, current, interactive = true) {
|
|
195
|
-
const actions = [];
|
|
196
|
-
const prevTableNames = Object.keys(previous.tables);
|
|
197
|
-
const currTableNames = Object.keys(current.tables);
|
|
198
|
-
const missingTables = prevTableNames.filter((t) => !currTableNames.includes(t));
|
|
199
|
-
const newTables = currTableNames.filter((t) => !prevTableNames.includes(t));
|
|
200
|
-
const resolvedMissingTables = new Set;
|
|
201
|
-
const resolvedNewTables = new Set;
|
|
202
|
-
if (interactive) {
|
|
203
|
-
for (const newTable of newTables) {
|
|
204
|
-
if (missingTables.length > 0) {
|
|
205
|
-
const options = missingTables.filter((t) => !resolvedMissingTables.has(t)).map((t) => ({ value: t, label: t }));
|
|
206
|
-
if (options.length > 0) {
|
|
207
|
-
Wt(`Detecting that collection '${newTable}' was added.`);
|
|
208
|
-
const answer = await Jt({
|
|
209
|
-
message: `Is the collection '${newTable}' a rename of any removed collection?`,
|
|
210
|
-
options: [{ value: "none", label: "No, it's a new collection." }, ...options]
|
|
211
|
-
});
|
|
212
|
-
if (!Ct(answer) && answer !== "none") {
|
|
213
|
-
const oldTableName = answer;
|
|
214
|
-
actions.push({
|
|
215
|
-
type: "rename_table",
|
|
216
|
-
tableName: oldTableName,
|
|
217
|
-
newName: newTable
|
|
218
|
-
});
|
|
219
|
-
resolvedMissingTables.add(oldTableName);
|
|
220
|
-
resolvedNewTables.add(newTable);
|
|
221
|
-
const oldTableSnap = previous.tables[oldTableName];
|
|
222
|
-
const newTableSnap = current.tables[newTable];
|
|
223
|
-
if (oldTableSnap && newTableSnap) {
|
|
224
|
-
await compareColumns(newTable, oldTableSnap.columns, newTableSnap.columns, actions, interactive);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
for (const newTable of newTables) {
|
|
232
|
-
if (!resolvedNewTables.has(newTable)) {
|
|
233
|
-
actions.push({
|
|
234
|
-
type: "create_table",
|
|
235
|
-
tableName: newTable,
|
|
236
|
-
tableSnapshot: current.tables[newTable]
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
for (const missingTable of missingTables) {
|
|
241
|
-
if (!resolvedMissingTables.has(missingTable)) {
|
|
242
|
-
let confirmed = false;
|
|
243
|
-
if (interactive) {
|
|
244
|
-
const result = await Rt({
|
|
245
|
-
message: `Collection '${missingTable}' was removed from collections array. Do you want to drop it from the database? (This WILL cause data loss)`,
|
|
246
|
-
initialValue: false
|
|
247
|
-
});
|
|
248
|
-
if (!Ct(result)) {
|
|
249
|
-
confirmed = result;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
actions.push({
|
|
253
|
-
type: "drop_table",
|
|
254
|
-
tableName: missingTable,
|
|
255
|
-
confirmed
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
for (const tableName of currTableNames) {
|
|
260
|
-
if (prevTableNames.includes(tableName)) {
|
|
261
|
-
const oldTableSnap = previous.tables[tableName];
|
|
262
|
-
const newTableSnap = current.tables[tableName];
|
|
263
|
-
if (oldTableSnap && newTableSnap) {
|
|
264
|
-
await compareColumns(tableName, oldTableSnap.columns, newTableSnap.columns, actions, interactive);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
return actions;
|
|
269
|
-
}
|
|
270
|
-
async function compareColumns(tableName, prevCols, currCols, actions, interactive) {
|
|
271
|
-
const prevColNames = Object.keys(prevCols);
|
|
272
|
-
const currColNames = Object.keys(currCols);
|
|
273
|
-
const missingCols = prevColNames.filter((c) => !currColNames.includes(c));
|
|
274
|
-
const newCols = currColNames.filter((c) => !prevColNames.includes(c));
|
|
275
|
-
const resolvedMissingCols = new Set;
|
|
276
|
-
const resolvedNewCols = new Set;
|
|
277
|
-
if (interactive) {
|
|
278
|
-
for (const newCol of newCols) {
|
|
279
|
-
if (missingCols.length > 0) {
|
|
280
|
-
const options = missingCols.filter((c) => !resolvedMissingCols.has(c)).map((c) => ({ value: c, label: c }));
|
|
281
|
-
if (options.length > 0) {
|
|
282
|
-
const answer = await Jt({
|
|
283
|
-
message: `In table '${tableName}', is the column '${newCol}' a rename of any removed column?`,
|
|
284
|
-
options: [{ value: "none", label: "No, it's a new column." }, ...options]
|
|
285
|
-
});
|
|
286
|
-
if (!Ct(answer) && answer !== "none") {
|
|
287
|
-
const oldColName = answer;
|
|
288
|
-
actions.push({
|
|
289
|
-
type: "rename_column",
|
|
290
|
-
tableName,
|
|
291
|
-
columnName: oldColName,
|
|
292
|
-
newColumnName: newCol
|
|
293
|
-
});
|
|
294
|
-
resolvedMissingCols.add(oldColName);
|
|
295
|
-
resolvedNewCols.add(newCol);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
for (const newCol of newCols) {
|
|
302
|
-
if (!resolvedNewCols.has(newCol)) {
|
|
303
|
-
actions.push({
|
|
304
|
-
type: "add_column",
|
|
305
|
-
tableName,
|
|
306
|
-
columnName: newCol,
|
|
307
|
-
columnSnapshot: currCols[newCol]
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
for (const missingCol of missingCols) {
|
|
312
|
-
if (!resolvedMissingCols.has(missingCol)) {
|
|
313
|
-
let confirmed = false;
|
|
314
|
-
if (interactive) {
|
|
315
|
-
const result = await Rt({
|
|
316
|
-
message: `In table '${tableName}', column '${missingCol}' was removed. Do you want to drop it from the database?`,
|
|
317
|
-
initialValue: false
|
|
318
|
-
});
|
|
319
|
-
if (!Ct(result)) {
|
|
320
|
-
confirmed = result;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
actions.push({
|
|
324
|
-
type: "drop_column",
|
|
325
|
-
tableName,
|
|
326
|
-
columnName: missingCol,
|
|
327
|
-
confirmed
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
for (const colName of currColNames) {
|
|
332
|
-
if (prevColNames.includes(colName)) {
|
|
333
|
-
const prev = prevCols[colName];
|
|
334
|
-
const curr = currCols[colName];
|
|
335
|
-
if (prev && curr) {
|
|
336
|
-
if (prev.type !== curr.type || prev.required !== curr.required || prev.unique !== curr.unique || JSON.stringify(prev.defaultValue) !== JSON.stringify(curr.defaultValue)) {
|
|
337
|
-
actions.push({
|
|
338
|
-
type: "change_column",
|
|
339
|
-
tableName,
|
|
340
|
-
columnName: colName,
|
|
341
|
-
columnSnapshot: curr
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// src/cli/core/migrations/schema-diff.ts
|
|
350
|
-
async function generateDiffCode(opaca, dialect, migrationDir, snapshotName, options = {
|
|
351
|
-
saveSnapshot: true,
|
|
352
|
-
interactive: true
|
|
353
|
-
}) {
|
|
354
|
-
const collections = opaca.collections || [];
|
|
355
|
-
const globals = opaca.globals || [];
|
|
356
|
-
const currentSnapshot = createSchemaSnapshot(collections, globals, dialect);
|
|
357
|
-
let previousSnapshot = loadLastSnapshot(migrationDir);
|
|
358
|
-
let isInitial = false;
|
|
359
|
-
if (!previousSnapshot) {
|
|
360
|
-
isInitial = true;
|
|
361
|
-
previousSnapshot = { tables: {} };
|
|
362
|
-
}
|
|
363
|
-
const actions = await compareSchemas(previousSnapshot, currentSnapshot, options.interactive);
|
|
364
|
-
if (actions.length === 0) {
|
|
365
|
-
return { hasChanges: false, upCode: "", downCode: "" };
|
|
366
|
-
}
|
|
367
|
-
let upCode = "";
|
|
368
|
-
let downCode = "";
|
|
369
|
-
for (const action of actions) {
|
|
370
|
-
if (action.type === "create_table") {
|
|
371
|
-
const table = action.tableSnapshot;
|
|
372
|
-
if (dialect === "d1") {
|
|
373
|
-
upCode += `CREATE TABLE "${table.name}" (
|
|
374
|
-
`;
|
|
375
|
-
const cols = Object.values(table.columns);
|
|
376
|
-
const colDefs = cols.map((c) => {
|
|
377
|
-
let def = ` "${c.name}" ${c.type.toUpperCase()}`;
|
|
378
|
-
if (c.name === "id")
|
|
379
|
-
def += " PRIMARY KEY";
|
|
380
|
-
if (c.required && c.name !== "id")
|
|
381
|
-
def += " NOT NULL";
|
|
382
|
-
if (c.unique && c.name !== "id")
|
|
383
|
-
def += " UNIQUE";
|
|
384
|
-
if (c.defaultValue !== undefined) {
|
|
385
|
-
let val = c.defaultValue;
|
|
386
|
-
if (typeof val === "string")
|
|
387
|
-
val = `'${val}'`;
|
|
388
|
-
else if (typeof val === "boolean")
|
|
389
|
-
val = val ? 1 : 0;
|
|
390
|
-
def += ` DEFAULT ${val}`;
|
|
391
|
-
}
|
|
392
|
-
if ((c.name === "created_at" || c.name === "updated_at") && c.defaultValue === undefined) {
|
|
393
|
-
def += ` DEFAULT CURRENT_TIMESTAMP`;
|
|
394
|
-
}
|
|
395
|
-
return def;
|
|
396
|
-
});
|
|
397
|
-
upCode += colDefs.join(`,
|
|
398
|
-
`) + `
|
|
399
|
-
);
|
|
400
|
-
|
|
401
|
-
`;
|
|
402
|
-
downCode = `DROP TABLE "${table.name}";
|
|
403
|
-
|
|
404
|
-
` + downCode;
|
|
405
|
-
} else {
|
|
406
|
-
upCode += ` await db.schema.createTable('${table.name}')
|
|
407
|
-
`;
|
|
408
|
-
for (const c of Object.values(table.columns)) {
|
|
409
|
-
if (c.name === "id") {
|
|
410
|
-
upCode += ` .addColumn('id', 'text', (col) => col.primaryKey())
|
|
411
|
-
`;
|
|
412
|
-
continue;
|
|
413
|
-
}
|
|
414
|
-
let constraints = "";
|
|
415
|
-
if (c.required)
|
|
416
|
-
constraints += ".notNull()";
|
|
417
|
-
if (c.unique)
|
|
418
|
-
constraints += ".unique()";
|
|
419
|
-
if (c.defaultValue !== undefined) {
|
|
420
|
-
let val = c.defaultValue;
|
|
421
|
-
if (typeof val === "string")
|
|
422
|
-
val = `'${val}'`;
|
|
423
|
-
else if (typeof val === "boolean")
|
|
424
|
-
val = dialect === "sqlite" ? val ? 1 : 0 : val;
|
|
425
|
-
constraints += `.defaultTo(${val})`;
|
|
426
|
-
}
|
|
427
|
-
if ((c.name === "created_at" || c.name === "updated_at" || c.name === "createdAt" || c.name === "updatedAt") && c.defaultValue === undefined) {
|
|
428
|
-
constraints += ".defaultTo(sql`CURRENT_TIMESTAMP`)";
|
|
429
|
-
}
|
|
430
|
-
upCode += ` .addColumn('${c.name}', '${c.type}', (col) => col${constraints})
|
|
431
|
-
`;
|
|
432
|
-
}
|
|
433
|
-
upCode += ` .execute();
|
|
434
|
-
|
|
435
|
-
`;
|
|
436
|
-
downCode = ` await db.schema.dropTable('${table.name}').execute();
|
|
437
|
-
` + downCode;
|
|
438
|
-
}
|
|
439
|
-
} else if (action.type === "drop_table") {
|
|
440
|
-
if (dialect === "d1") {
|
|
441
|
-
if (action.confirmed) {
|
|
442
|
-
upCode += `DROP TABLE "${action.tableName}";
|
|
443
|
-
|
|
444
|
-
`;
|
|
445
|
-
} else {
|
|
446
|
-
upCode += ` -- Data Loss Prevention: Review before dropping table
|
|
447
|
-
`;
|
|
448
|
-
upCode += ` -- DROP TABLE "${action.tableName}";
|
|
449
|
-
|
|
450
|
-
`;
|
|
451
|
-
}
|
|
452
|
-
} else {
|
|
453
|
-
if (action.confirmed) {
|
|
454
|
-
upCode += ` await db.schema.dropTable('${action.tableName}').execute();
|
|
455
|
-
|
|
456
|
-
`;
|
|
457
|
-
} else {
|
|
458
|
-
upCode += ` // Data Loss Prevention: Review before dropping table
|
|
459
|
-
`;
|
|
460
|
-
upCode += ` // await db.schema.dropTable('${action.tableName}').execute();
|
|
461
|
-
|
|
462
|
-
`;
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
} else if (action.type === "rename_table") {
|
|
466
|
-
if (dialect === "d1") {
|
|
467
|
-
upCode += `ALTER TABLE "${action.tableName}" RENAME TO "${action.newName}";
|
|
468
|
-
|
|
469
|
-
`;
|
|
470
|
-
downCode = `ALTER TABLE "${action.newName}" RENAME TO "${action.tableName}";
|
|
471
|
-
|
|
472
|
-
` + downCode;
|
|
473
|
-
} else {
|
|
474
|
-
upCode += ` await db.schema.alterTable('${action.tableName}').renameTo('${action.newName}').execute();
|
|
475
|
-
|
|
476
|
-
`;
|
|
477
|
-
downCode = ` await db.schema.alterTable('${action.newName}').renameTo('${action.tableName}').execute();
|
|
478
|
-
|
|
479
|
-
` + downCode;
|
|
480
|
-
}
|
|
481
|
-
} else if (action.type === "add_column") {
|
|
482
|
-
const c = action.columnSnapshot;
|
|
483
|
-
if (dialect === "d1") {
|
|
484
|
-
let def = `ALTER TABLE "${action.tableName}" ADD COLUMN "${c.name}" ${c.type.toUpperCase()}`;
|
|
485
|
-
if (c.defaultValue !== undefined) {
|
|
486
|
-
let val = c.defaultValue;
|
|
487
|
-
if (typeof val === "string")
|
|
488
|
-
val = `'${val}'`;
|
|
489
|
-
else if (typeof val === "boolean")
|
|
490
|
-
val = val ? 1 : 0;
|
|
491
|
-
def += ` DEFAULT ${val}`;
|
|
492
|
-
} else if (c.name === "created_at" || c.name === "updated_at" || c.name === "createdAt" || c.name === "updatedAt") {
|
|
493
|
-
def += ` DEFAULT CURRENT_TIMESTAMP`;
|
|
494
|
-
}
|
|
495
|
-
upCode += `${def};
|
|
496
|
-
`;
|
|
497
|
-
downCode = `-- ALTER TABLE "${action.tableName}" DROP COLUMN "${c.name}"; -- Note: D1 does not support DROP COLUMN
|
|
498
|
-
` + downCode;
|
|
499
|
-
} else {
|
|
500
|
-
let constraints = "";
|
|
501
|
-
if (c.required)
|
|
502
|
-
constraints += ".notNull()";
|
|
503
|
-
if (c.unique)
|
|
504
|
-
constraints += ".unique()";
|
|
505
|
-
if (c.defaultValue !== undefined) {
|
|
506
|
-
let val = c.defaultValue;
|
|
507
|
-
if (typeof val === "string")
|
|
508
|
-
val = `'${val}'`;
|
|
509
|
-
else if (typeof val === "boolean")
|
|
510
|
-
val = dialect === "sqlite" ? val ? 1 : 0 : val;
|
|
511
|
-
constraints += `.defaultTo(${val})`;
|
|
512
|
-
}
|
|
513
|
-
if ((c.name === "created_at" || c.name === "updated_at" || c.name === "createdAt" || c.name === "updatedAt") && c.defaultValue === undefined) {
|
|
514
|
-
constraints += ".defaultTo(sql`CURRENT_TIMESTAMP`)";
|
|
515
|
-
}
|
|
516
|
-
upCode += ` await db.schema.alterTable('${action.tableName}')
|
|
517
|
-
.addColumn('${c.name}', '${c.type}', (col) => col${constraints})
|
|
518
|
-
.execute();
|
|
519
|
-
|
|
520
|
-
`;
|
|
521
|
-
downCode = ` await db.schema.alterTable('${action.tableName}')
|
|
522
|
-
.dropColumn('${c.name}')
|
|
523
|
-
.execute();
|
|
524
|
-
|
|
525
|
-
` + downCode;
|
|
526
|
-
}
|
|
527
|
-
} else if (action.type === "drop_column") {
|
|
528
|
-
if (dialect === "d1") {
|
|
529
|
-
if (action.confirmed) {
|
|
530
|
-
upCode += `ALTER TABLE "${action.tableName}" DROP COLUMN "${action.columnName}";
|
|
531
|
-
|
|
532
|
-
`;
|
|
533
|
-
} else {
|
|
534
|
-
upCode += ` -- Data Loss Prevention: Review before dropping column
|
|
535
|
-
`;
|
|
536
|
-
upCode += ` -- ALTER TABLE "${action.tableName}" DROP COLUMN "${action.columnName}";
|
|
537
|
-
|
|
538
|
-
`;
|
|
539
|
-
}
|
|
540
|
-
} else {
|
|
541
|
-
if (action.confirmed) {
|
|
542
|
-
upCode += ` await db.schema.alterTable('${action.tableName}').dropColumn('${action.columnName}').execute();
|
|
543
|
-
|
|
544
|
-
`;
|
|
545
|
-
} else {
|
|
546
|
-
upCode += ` // Data Loss Prevention: Review before dropping column
|
|
547
|
-
`;
|
|
548
|
-
upCode += ` // await db.schema.alterTable('${action.tableName}').dropColumn('${action.columnName}').execute();
|
|
549
|
-
|
|
550
|
-
`;
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
} else if (action.type === "rename_column") {
|
|
554
|
-
if (dialect === "d1") {
|
|
555
|
-
upCode += `ALTER TABLE "${action.tableName}" RENAME COLUMN "${action.columnName}" TO "${action.newColumnName}";
|
|
556
|
-
|
|
557
|
-
`;
|
|
558
|
-
downCode = `ALTER TABLE "${action.tableName}" RENAME COLUMN "${action.newColumnName}" TO "${action.columnName}";
|
|
559
|
-
|
|
560
|
-
` + downCode;
|
|
561
|
-
} else {
|
|
562
|
-
upCode += ` await db.schema.alterTable('${action.tableName}').renameColumn('${action.columnName}', '${action.newColumnName}').execute();
|
|
563
|
-
|
|
564
|
-
`;
|
|
565
|
-
downCode = ` await db.schema.alterTable('${action.tableName}').renameColumn('${action.newColumnName}', '${action.columnName}').execute();
|
|
566
|
-
|
|
567
|
-
` + downCode;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
if (options.saveSnapshot) {
|
|
572
|
-
saveSnapshot(migrationDir, snapshotName, currentSnapshot);
|
|
573
|
-
}
|
|
574
|
-
return {
|
|
575
|
-
hasChanges: true,
|
|
576
|
-
upCode: upCode.trimEnd(),
|
|
577
|
-
downCode: downCode.trimEnd()
|
|
578
|
-
};
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
export { generateDiffCode };
|