@famgia/omnify-laravel 0.0.13 → 0.0.15
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/chunk-REDFZUQY.js +2239 -0
- package/dist/chunk-REDFZUQY.js.map +1 -0
- package/dist/index.cjs +1203 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/plugin.cjs +1201 -36
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +44 -3
- package/dist/plugin.d.ts +44 -3
- package/dist/plugin.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-G4UAJVC2.js +0 -1072
- package/dist/chunk-G4UAJVC2.js.map +0 -1
package/dist/chunk-G4UAJVC2.js
DELETED
|
@@ -1,1072 +0,0 @@
|
|
|
1
|
-
// src/migration/schema-builder.ts
|
|
2
|
-
var TYPE_METHOD_MAP = {
|
|
3
|
-
String: "string",
|
|
4
|
-
Int: "integer",
|
|
5
|
-
BigInt: "bigInteger",
|
|
6
|
-
Float: "double",
|
|
7
|
-
Decimal: "decimal",
|
|
8
|
-
Boolean: "boolean",
|
|
9
|
-
Text: "text",
|
|
10
|
-
LongText: "longText",
|
|
11
|
-
Date: "date",
|
|
12
|
-
Time: "time",
|
|
13
|
-
Timestamp: "timestamp",
|
|
14
|
-
Json: "json",
|
|
15
|
-
Email: "string",
|
|
16
|
-
Password: "string",
|
|
17
|
-
Enum: "enum"
|
|
18
|
-
// Note: File type is now polymorphic - no column generated, uses files table
|
|
19
|
-
};
|
|
20
|
-
var PK_METHOD_MAP = {
|
|
21
|
-
Int: "increments",
|
|
22
|
-
BigInt: "bigIncrements",
|
|
23
|
-
Uuid: "uuid",
|
|
24
|
-
String: "string"
|
|
25
|
-
};
|
|
26
|
-
function getIdType(schema) {
|
|
27
|
-
return schema.options?.idType ?? "BigInt";
|
|
28
|
-
}
|
|
29
|
-
function hasAutoId(schema) {
|
|
30
|
-
return schema.options?.id !== false;
|
|
31
|
-
}
|
|
32
|
-
function toColumnName(propertyName) {
|
|
33
|
-
return propertyName.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
34
|
-
}
|
|
35
|
-
function toTableName(schemaName) {
|
|
36
|
-
const snakeCase = schemaName.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
37
|
-
if (snakeCase.endsWith("y")) {
|
|
38
|
-
return snakeCase.slice(0, -1) + "ies";
|
|
39
|
-
} else if (snakeCase.endsWith("s") || snakeCase.endsWith("x") || snakeCase.endsWith("ch") || snakeCase.endsWith("sh")) {
|
|
40
|
-
return snakeCase + "es";
|
|
41
|
-
} else {
|
|
42
|
-
return snakeCase + "s";
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function propertyToColumnMethod(propertyName, property) {
|
|
46
|
-
if (property.type === "Association") {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
if (property.type === "File") {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
const columnName = toColumnName(propertyName);
|
|
53
|
-
const method = TYPE_METHOD_MAP[property.type] ?? "string";
|
|
54
|
-
const args = [columnName];
|
|
55
|
-
const modifiers = [];
|
|
56
|
-
const propWithLength = property;
|
|
57
|
-
if (method === "string" && propWithLength.length) {
|
|
58
|
-
args.push(propWithLength.length);
|
|
59
|
-
}
|
|
60
|
-
if (property.type === "Decimal") {
|
|
61
|
-
const decimalProp = property;
|
|
62
|
-
const precision = decimalProp.precision ?? 8;
|
|
63
|
-
const scale = decimalProp.scale ?? 2;
|
|
64
|
-
args.push(precision, scale);
|
|
65
|
-
}
|
|
66
|
-
if (property.type === "Enum") {
|
|
67
|
-
const enumProp = property;
|
|
68
|
-
if (enumProp.enum && enumProp.enum.length > 0) {
|
|
69
|
-
args.push(enumProp.enum);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
const baseProp = property;
|
|
73
|
-
if (baseProp.nullable) {
|
|
74
|
-
modifiers.push({ method: "nullable" });
|
|
75
|
-
}
|
|
76
|
-
if (baseProp.unique) {
|
|
77
|
-
modifiers.push({ method: "unique" });
|
|
78
|
-
}
|
|
79
|
-
if (baseProp.default !== void 0) {
|
|
80
|
-
const defaultValue = typeof baseProp.default === "string" ? baseProp.default : JSON.stringify(baseProp.default);
|
|
81
|
-
modifiers.push({ method: "default", args: [defaultValue] });
|
|
82
|
-
}
|
|
83
|
-
if (baseProp.unsigned && (method === "integer" || method === "bigInteger")) {
|
|
84
|
-
modifiers.push({ method: "unsigned" });
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
name: columnName,
|
|
88
|
-
method,
|
|
89
|
-
args,
|
|
90
|
-
modifiers
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
function generatePrimaryKeyColumn(pkType = "BigInt") {
|
|
94
|
-
const method = PK_METHOD_MAP[pkType] ?? "bigIncrements";
|
|
95
|
-
if (pkType === "Uuid") {
|
|
96
|
-
return {
|
|
97
|
-
name: "id",
|
|
98
|
-
method: "uuid",
|
|
99
|
-
args: ["id"],
|
|
100
|
-
modifiers: [{ method: "primary" }]
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
if (pkType === "String") {
|
|
104
|
-
return {
|
|
105
|
-
name: "id",
|
|
106
|
-
method: "string",
|
|
107
|
-
args: ["id", 255],
|
|
108
|
-
modifiers: [{ method: "primary" }]
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
return {
|
|
112
|
-
name: "id",
|
|
113
|
-
method,
|
|
114
|
-
args: ["id"],
|
|
115
|
-
modifiers: []
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
function generateTimestampColumns() {
|
|
119
|
-
return [
|
|
120
|
-
{
|
|
121
|
-
name: "created_at",
|
|
122
|
-
method: "timestamp",
|
|
123
|
-
args: ["created_at"],
|
|
124
|
-
modifiers: [{ method: "nullable" }]
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
name: "updated_at",
|
|
128
|
-
method: "timestamp",
|
|
129
|
-
args: ["updated_at"],
|
|
130
|
-
modifiers: [{ method: "nullable" }]
|
|
131
|
-
}
|
|
132
|
-
];
|
|
133
|
-
}
|
|
134
|
-
function generateSoftDeleteColumn() {
|
|
135
|
-
return {
|
|
136
|
-
name: "deleted_at",
|
|
137
|
-
method: "timestamp",
|
|
138
|
-
args: ["deleted_at"],
|
|
139
|
-
modifiers: [{ method: "nullable" }]
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
function generatePolymorphicColumns(propertyName, property, allSchemas) {
|
|
143
|
-
if (property.type !== "Association") {
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
const assocProp = property;
|
|
147
|
-
if (assocProp.relation !== "MorphTo") {
|
|
148
|
-
return null;
|
|
149
|
-
}
|
|
150
|
-
const targets = assocProp.targets;
|
|
151
|
-
if (!targets || targets.length === 0) {
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
const columnBaseName = toColumnName(propertyName);
|
|
155
|
-
const typeColumnName = `${columnBaseName}_type`;
|
|
156
|
-
const idColumnName = `${columnBaseName}_id`;
|
|
157
|
-
const typeColumn = {
|
|
158
|
-
name: typeColumnName,
|
|
159
|
-
method: "enum",
|
|
160
|
-
args: [typeColumnName, targets],
|
|
161
|
-
modifiers: [{ method: "nullable" }]
|
|
162
|
-
};
|
|
163
|
-
let idMethod = "unsignedBigInteger";
|
|
164
|
-
for (const targetName of targets) {
|
|
165
|
-
const targetSchema = allSchemas[targetName];
|
|
166
|
-
if (targetSchema) {
|
|
167
|
-
const targetIdType = targetSchema.options?.idType ?? "BigInt";
|
|
168
|
-
if (targetIdType === "Uuid") {
|
|
169
|
-
idMethod = "uuid";
|
|
170
|
-
break;
|
|
171
|
-
} else if (targetIdType === "String") {
|
|
172
|
-
idMethod = "string";
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
const idColumn = {
|
|
177
|
-
name: idColumnName,
|
|
178
|
-
method: idMethod,
|
|
179
|
-
args: idMethod === "string" ? [idColumnName, 255] : [idColumnName],
|
|
180
|
-
modifiers: [{ method: "nullable" }]
|
|
181
|
-
};
|
|
182
|
-
const indexes = [
|
|
183
|
-
{
|
|
184
|
-
columns: [typeColumnName, idColumnName],
|
|
185
|
-
unique: false
|
|
186
|
-
}
|
|
187
|
-
];
|
|
188
|
-
return { typeColumn, idColumn, indexes };
|
|
189
|
-
}
|
|
190
|
-
function generateForeignKey(propertyName, property, allSchemas) {
|
|
191
|
-
if (property.type !== "Association") {
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
const assocProp = property;
|
|
195
|
-
if (assocProp.relation !== "ManyToOne" && assocProp.relation !== "OneToOne") {
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
|
-
if (assocProp.mappedBy) {
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
const columnName = toColumnName(propertyName) + "_id";
|
|
202
|
-
const targetSchema = assocProp.target ? allSchemas[assocProp.target] : void 0;
|
|
203
|
-
const targetTable = assocProp.target ? toTableName(assocProp.target) : "unknown";
|
|
204
|
-
const targetPkType = targetSchema ? getIdType(targetSchema) : "BigInt";
|
|
205
|
-
let method = "unsignedBigInteger";
|
|
206
|
-
if (targetPkType === "Int") {
|
|
207
|
-
method = "unsignedInteger";
|
|
208
|
-
} else if (targetPkType === "Uuid") {
|
|
209
|
-
method = "uuid";
|
|
210
|
-
} else if (targetPkType === "String") {
|
|
211
|
-
method = "string";
|
|
212
|
-
}
|
|
213
|
-
const column = {
|
|
214
|
-
name: columnName,
|
|
215
|
-
method,
|
|
216
|
-
args: [columnName],
|
|
217
|
-
modifiers: assocProp.relation === "ManyToOne" ? [{ method: "nullable" }] : []
|
|
218
|
-
};
|
|
219
|
-
const foreignKey = {
|
|
220
|
-
columns: [columnName],
|
|
221
|
-
references: "id",
|
|
222
|
-
on: [targetTable],
|
|
223
|
-
onDelete: assocProp.onDelete ?? "restrict",
|
|
224
|
-
onUpdate: assocProp.onUpdate ?? "cascade"
|
|
225
|
-
};
|
|
226
|
-
const index = {
|
|
227
|
-
columns: [columnName],
|
|
228
|
-
unique: false
|
|
229
|
-
};
|
|
230
|
-
return { column, foreignKey, index };
|
|
231
|
-
}
|
|
232
|
-
function schemaToBlueprint(schema, allSchemas) {
|
|
233
|
-
const tableName = toTableName(schema.name);
|
|
234
|
-
const columns = [];
|
|
235
|
-
const foreignKeys = [];
|
|
236
|
-
const indexes = [];
|
|
237
|
-
if (hasAutoId(schema)) {
|
|
238
|
-
const pkType = getIdType(schema);
|
|
239
|
-
columns.push(generatePrimaryKeyColumn(pkType));
|
|
240
|
-
}
|
|
241
|
-
if (schema.properties) {
|
|
242
|
-
for (const [propName, property] of Object.entries(schema.properties)) {
|
|
243
|
-
const columnMethod = propertyToColumnMethod(propName, property);
|
|
244
|
-
if (columnMethod) {
|
|
245
|
-
columns.push(columnMethod);
|
|
246
|
-
}
|
|
247
|
-
const fkResult = generateForeignKey(propName, property, allSchemas);
|
|
248
|
-
if (fkResult) {
|
|
249
|
-
columns.push(fkResult.column);
|
|
250
|
-
foreignKeys.push(fkResult.foreignKey);
|
|
251
|
-
indexes.push(fkResult.index);
|
|
252
|
-
}
|
|
253
|
-
const polyResult = generatePolymorphicColumns(propName, property, allSchemas);
|
|
254
|
-
if (polyResult) {
|
|
255
|
-
columns.push(polyResult.typeColumn);
|
|
256
|
-
columns.push(polyResult.idColumn);
|
|
257
|
-
indexes.push(...polyResult.indexes);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
if (schema.options?.timestamps !== false) {
|
|
262
|
-
columns.push(...generateTimestampColumns());
|
|
263
|
-
}
|
|
264
|
-
if (schema.options?.softDelete) {
|
|
265
|
-
columns.push(generateSoftDeleteColumn());
|
|
266
|
-
}
|
|
267
|
-
if (schema.options?.indexes) {
|
|
268
|
-
for (const index of schema.options.indexes) {
|
|
269
|
-
indexes.push({
|
|
270
|
-
name: index.name,
|
|
271
|
-
columns: index.columns.map(toColumnName),
|
|
272
|
-
unique: index.unique ?? false
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
if (schema.options?.unique) {
|
|
277
|
-
const uniqueConstraints = Array.isArray(schema.options.unique[0]) ? schema.options.unique : [schema.options.unique];
|
|
278
|
-
for (const constraint of uniqueConstraints) {
|
|
279
|
-
indexes.push({
|
|
280
|
-
columns: constraint.map(toColumnName),
|
|
281
|
-
unique: true
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return {
|
|
286
|
-
tableName,
|
|
287
|
-
columns,
|
|
288
|
-
primaryKey: ["id"],
|
|
289
|
-
foreignKeys,
|
|
290
|
-
indexes
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
function formatColumnMethod(column) {
|
|
294
|
-
const args = column.args.map((arg) => {
|
|
295
|
-
if (typeof arg === "string") {
|
|
296
|
-
return `'${arg}'`;
|
|
297
|
-
}
|
|
298
|
-
if (Array.isArray(arg)) {
|
|
299
|
-
return `[${arg.map((v) => `'${v}'`).join(", ")}]`;
|
|
300
|
-
}
|
|
301
|
-
return String(arg);
|
|
302
|
-
}).join(", ");
|
|
303
|
-
let code = `$table->${column.method}(${args})`;
|
|
304
|
-
for (const modifier of column.modifiers) {
|
|
305
|
-
if (modifier.args && modifier.args.length > 0) {
|
|
306
|
-
const modArgs = modifier.args.map((arg) => {
|
|
307
|
-
if (typeof arg === "string") {
|
|
308
|
-
return `'${arg}'`;
|
|
309
|
-
}
|
|
310
|
-
return String(arg);
|
|
311
|
-
}).join(", ");
|
|
312
|
-
code += `->${modifier.method}(${modArgs})`;
|
|
313
|
-
} else {
|
|
314
|
-
code += `->${modifier.method}()`;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
return code + ";";
|
|
318
|
-
}
|
|
319
|
-
function formatForeignKey(fk) {
|
|
320
|
-
const column = fk.columns[0];
|
|
321
|
-
const table = fk.on[0];
|
|
322
|
-
let code = `$table->foreign('${column}')->references('${fk.references}')->on('${table}')`;
|
|
323
|
-
if (fk.onDelete) {
|
|
324
|
-
code += `->onDelete('${fk.onDelete}')`;
|
|
325
|
-
}
|
|
326
|
-
if (fk.onUpdate) {
|
|
327
|
-
code += `->onUpdate('${fk.onUpdate}')`;
|
|
328
|
-
}
|
|
329
|
-
return code + ";";
|
|
330
|
-
}
|
|
331
|
-
function formatIndex(index) {
|
|
332
|
-
const columns = index.columns.length === 1 ? `'${index.columns[0]}'` : `[${index.columns.map((c) => `'${c}'`).join(", ")}]`;
|
|
333
|
-
const method = index.unique ? "unique" : "index";
|
|
334
|
-
const name = index.name ? `, '${index.name}'` : "";
|
|
335
|
-
return `$table->${method}(${columns}${name});`;
|
|
336
|
-
}
|
|
337
|
-
function generatePivotTableName(sourceTable, targetTable, customName) {
|
|
338
|
-
if (customName) {
|
|
339
|
-
return customName;
|
|
340
|
-
}
|
|
341
|
-
const tables = [sourceTable, targetTable].sort();
|
|
342
|
-
const singular1 = tables[0].replace(/ies$/, "y").replace(/s$/, "");
|
|
343
|
-
const singular2 = tables[1].replace(/ies$/, "y").replace(/s$/, "");
|
|
344
|
-
return `${singular1}_${singular2}`;
|
|
345
|
-
}
|
|
346
|
-
function extractManyToManyRelations(schema, allSchemas) {
|
|
347
|
-
const pivotTables = [];
|
|
348
|
-
if (!schema.properties) {
|
|
349
|
-
return pivotTables;
|
|
350
|
-
}
|
|
351
|
-
const sourceTable = toTableName(schema.name);
|
|
352
|
-
const sourcePkType = getIdType(schema);
|
|
353
|
-
for (const [, property] of Object.entries(schema.properties)) {
|
|
354
|
-
if (property.type !== "Association") {
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
const assocProp = property;
|
|
358
|
-
if (assocProp.relation !== "ManyToMany") {
|
|
359
|
-
continue;
|
|
360
|
-
}
|
|
361
|
-
const targetName = assocProp.target;
|
|
362
|
-
if (!targetName) {
|
|
363
|
-
continue;
|
|
364
|
-
}
|
|
365
|
-
const targetSchema = allSchemas[targetName];
|
|
366
|
-
const targetTable = toTableName(targetName);
|
|
367
|
-
const targetPkType = targetSchema ? getIdType(targetSchema) : "BigInt";
|
|
368
|
-
const isOwningSide = assocProp.owning ?? schema.name < targetName;
|
|
369
|
-
if (!isOwningSide) {
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
const pivotTableName = generatePivotTableName(sourceTable, targetTable, assocProp.joinTable);
|
|
373
|
-
const sourceColumn = sourceTable.replace(/ies$/, "y").replace(/s$/, "") + "_id";
|
|
374
|
-
const targetColumn = targetTable.replace(/ies$/, "y").replace(/s$/, "") + "_id";
|
|
375
|
-
pivotTables.push({
|
|
376
|
-
tableName: pivotTableName,
|
|
377
|
-
sourceTable,
|
|
378
|
-
targetTable,
|
|
379
|
-
sourceColumn,
|
|
380
|
-
targetColumn,
|
|
381
|
-
sourcePkType,
|
|
382
|
-
targetPkType,
|
|
383
|
-
onDelete: assocProp.onDelete,
|
|
384
|
-
onUpdate: assocProp.onUpdate
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
return pivotTables;
|
|
388
|
-
}
|
|
389
|
-
function generatePivotTableBlueprint(pivot) {
|
|
390
|
-
const columns = [];
|
|
391
|
-
const foreignKeys = [];
|
|
392
|
-
const indexes = [];
|
|
393
|
-
const getMethodForPkType = (pkType) => {
|
|
394
|
-
switch (pkType) {
|
|
395
|
-
case "Int":
|
|
396
|
-
return "unsignedInteger";
|
|
397
|
-
case "Uuid":
|
|
398
|
-
return "uuid";
|
|
399
|
-
case "String":
|
|
400
|
-
return "string";
|
|
401
|
-
default:
|
|
402
|
-
return "unsignedBigInteger";
|
|
403
|
-
}
|
|
404
|
-
};
|
|
405
|
-
columns.push({
|
|
406
|
-
name: pivot.sourceColumn,
|
|
407
|
-
method: getMethodForPkType(pivot.sourcePkType),
|
|
408
|
-
args: [pivot.sourceColumn],
|
|
409
|
-
modifiers: []
|
|
410
|
-
});
|
|
411
|
-
columns.push({
|
|
412
|
-
name: pivot.targetColumn,
|
|
413
|
-
method: getMethodForPkType(pivot.targetPkType),
|
|
414
|
-
args: [pivot.targetColumn],
|
|
415
|
-
modifiers: []
|
|
416
|
-
});
|
|
417
|
-
foreignKeys.push({
|
|
418
|
-
columns: [pivot.sourceColumn],
|
|
419
|
-
references: "id",
|
|
420
|
-
on: [pivot.sourceTable],
|
|
421
|
-
onDelete: pivot.onDelete ?? "cascade",
|
|
422
|
-
onUpdate: pivot.onUpdate ?? "cascade"
|
|
423
|
-
});
|
|
424
|
-
foreignKeys.push({
|
|
425
|
-
columns: [pivot.targetColumn],
|
|
426
|
-
references: "id",
|
|
427
|
-
on: [pivot.targetTable],
|
|
428
|
-
onDelete: pivot.onDelete ?? "cascade",
|
|
429
|
-
onUpdate: pivot.onUpdate ?? "cascade"
|
|
430
|
-
});
|
|
431
|
-
indexes.push({
|
|
432
|
-
columns: [pivot.sourceColumn, pivot.targetColumn],
|
|
433
|
-
unique: true
|
|
434
|
-
});
|
|
435
|
-
indexes.push({
|
|
436
|
-
columns: [pivot.sourceColumn],
|
|
437
|
-
unique: false
|
|
438
|
-
});
|
|
439
|
-
indexes.push({
|
|
440
|
-
columns: [pivot.targetColumn],
|
|
441
|
-
unique: false
|
|
442
|
-
});
|
|
443
|
-
return {
|
|
444
|
-
tableName: pivot.tableName,
|
|
445
|
-
columns,
|
|
446
|
-
primaryKey: [pivot.sourceColumn, pivot.targetColumn],
|
|
447
|
-
foreignKeys,
|
|
448
|
-
indexes
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// src/migration/generator.ts
|
|
453
|
-
function generateTimestamp() {
|
|
454
|
-
const now = /* @__PURE__ */ new Date();
|
|
455
|
-
const year = now.getFullYear();
|
|
456
|
-
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
457
|
-
const day = String(now.getDate()).padStart(2, "0");
|
|
458
|
-
const hours = String(now.getHours()).padStart(2, "0");
|
|
459
|
-
const minutes = String(now.getMinutes()).padStart(2, "0");
|
|
460
|
-
const seconds = String(now.getSeconds()).padStart(2, "0");
|
|
461
|
-
return `${year}_${month}_${day}_${hours}${minutes}${seconds}`;
|
|
462
|
-
}
|
|
463
|
-
function toClassName(tableName, type) {
|
|
464
|
-
const pascalCase = tableName.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
465
|
-
switch (type) {
|
|
466
|
-
case "create":
|
|
467
|
-
return `Create${pascalCase}Table`;
|
|
468
|
-
case "alter":
|
|
469
|
-
return `Alter${pascalCase}Table`;
|
|
470
|
-
case "drop":
|
|
471
|
-
return `Drop${pascalCase}Table`;
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
function generateFileName(tableName, type, timestamp) {
|
|
475
|
-
const ts = timestamp ?? generateTimestamp();
|
|
476
|
-
const action = type === "create" ? "create" : type === "drop" ? "drop" : "update";
|
|
477
|
-
return `${ts}_${action}_${tableName}_table.php`;
|
|
478
|
-
}
|
|
479
|
-
function renderCreateTableUp(blueprint) {
|
|
480
|
-
const lines = [];
|
|
481
|
-
for (const column of blueprint.columns) {
|
|
482
|
-
lines.push(` ${formatColumnMethod(column)}`);
|
|
483
|
-
}
|
|
484
|
-
return lines.join("\n");
|
|
485
|
-
}
|
|
486
|
-
function renderForeignKeys(blueprint) {
|
|
487
|
-
if (blueprint.foreignKeys.length === 0) {
|
|
488
|
-
return "";
|
|
489
|
-
}
|
|
490
|
-
const lines = blueprint.foreignKeys.map((fk) => ` ${formatForeignKey(fk)}`);
|
|
491
|
-
return "\n" + lines.join("\n");
|
|
492
|
-
}
|
|
493
|
-
function renderIndexes(blueprint) {
|
|
494
|
-
const customIndexes = blueprint.indexes.filter((idx) => {
|
|
495
|
-
if (idx.unique && idx.columns.length === 1) {
|
|
496
|
-
return false;
|
|
497
|
-
}
|
|
498
|
-
return true;
|
|
499
|
-
});
|
|
500
|
-
if (customIndexes.length === 0) {
|
|
501
|
-
return "";
|
|
502
|
-
}
|
|
503
|
-
const lines = customIndexes.map((idx) => ` ${formatIndex(idx)}`);
|
|
504
|
-
return "\n" + lines.join("\n");
|
|
505
|
-
}
|
|
506
|
-
function generateCreateMigration(blueprint, options = {}) {
|
|
507
|
-
const className = toClassName(blueprint.tableName, "create");
|
|
508
|
-
const fileName = generateFileName(blueprint.tableName, "create", options.timestamp);
|
|
509
|
-
const connection = options.connection ? `
|
|
510
|
-
protected $connection = '${options.connection}';
|
|
511
|
-
` : "";
|
|
512
|
-
const upContent = renderCreateTableUp(blueprint);
|
|
513
|
-
const foreignKeyContent = renderForeignKeys(blueprint);
|
|
514
|
-
const indexContent = renderIndexes(blueprint);
|
|
515
|
-
const content = `<?php
|
|
516
|
-
|
|
517
|
-
use Illuminate\\Database\\Migrations\\Migration;
|
|
518
|
-
use Illuminate\\Database\\Schema\\Blueprint;
|
|
519
|
-
use Illuminate\\Support\\Facades\\Schema;
|
|
520
|
-
|
|
521
|
-
return new class extends Migration
|
|
522
|
-
{${connection}
|
|
523
|
-
/**
|
|
524
|
-
* Run the migrations.
|
|
525
|
-
*/
|
|
526
|
-
public function up(): void
|
|
527
|
-
{
|
|
528
|
-
Schema::create('${blueprint.tableName}', function (Blueprint $table) {
|
|
529
|
-
${upContent}${foreignKeyContent}${indexContent}
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* Reverse the migrations.
|
|
535
|
-
*/
|
|
536
|
-
public function down(): void
|
|
537
|
-
{
|
|
538
|
-
Schema::dropIfExists('${blueprint.tableName}');
|
|
539
|
-
}
|
|
540
|
-
};
|
|
541
|
-
`;
|
|
542
|
-
return {
|
|
543
|
-
fileName,
|
|
544
|
-
className,
|
|
545
|
-
content,
|
|
546
|
-
tables: [blueprint.tableName],
|
|
547
|
-
type: "create"
|
|
548
|
-
};
|
|
549
|
-
}
|
|
550
|
-
function generateDropMigration(tableName, options = {}) {
|
|
551
|
-
const className = toClassName(tableName, "drop");
|
|
552
|
-
const fileName = generateFileName(tableName, "drop", options.timestamp);
|
|
553
|
-
const connection = options.connection ? `
|
|
554
|
-
protected $connection = '${options.connection}';
|
|
555
|
-
` : "";
|
|
556
|
-
const content = `<?php
|
|
557
|
-
|
|
558
|
-
use Illuminate\\Database\\Migrations\\Migration;
|
|
559
|
-
use Illuminate\\Database\\Schema\\Blueprint;
|
|
560
|
-
use Illuminate\\Support\\Facades\\Schema;
|
|
561
|
-
|
|
562
|
-
return new class extends Migration
|
|
563
|
-
{${connection}
|
|
564
|
-
/**
|
|
565
|
-
* Run the migrations.
|
|
566
|
-
*/
|
|
567
|
-
public function up(): void
|
|
568
|
-
{
|
|
569
|
-
Schema::dropIfExists('${tableName}');
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
/**
|
|
573
|
-
* Reverse the migrations.
|
|
574
|
-
*/
|
|
575
|
-
public function down(): void
|
|
576
|
-
{
|
|
577
|
-
// Cannot recreate table without schema information
|
|
578
|
-
// This is a one-way migration
|
|
579
|
-
}
|
|
580
|
-
};
|
|
581
|
-
`;
|
|
582
|
-
return {
|
|
583
|
-
fileName,
|
|
584
|
-
className,
|
|
585
|
-
content,
|
|
586
|
-
tables: [tableName],
|
|
587
|
-
type: "drop"
|
|
588
|
-
};
|
|
589
|
-
}
|
|
590
|
-
function extractDependencies(schema) {
|
|
591
|
-
const deps = [];
|
|
592
|
-
if (!schema.properties) {
|
|
593
|
-
return deps;
|
|
594
|
-
}
|
|
595
|
-
for (const property of Object.values(schema.properties)) {
|
|
596
|
-
if (property.type !== "Association") {
|
|
597
|
-
continue;
|
|
598
|
-
}
|
|
599
|
-
const assocProp = property;
|
|
600
|
-
if ((assocProp.relation === "ManyToOne" || assocProp.relation === "OneToOne") && !assocProp.mappedBy && assocProp.target) {
|
|
601
|
-
deps.push(assocProp.target);
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
return deps;
|
|
605
|
-
}
|
|
606
|
-
function topologicalSort(schemas) {
|
|
607
|
-
const schemaList = Object.values(schemas).filter((s) => s.kind !== "enum");
|
|
608
|
-
const sorted = [];
|
|
609
|
-
const visited = /* @__PURE__ */ new Set();
|
|
610
|
-
const visiting = /* @__PURE__ */ new Set();
|
|
611
|
-
function visit(schema) {
|
|
612
|
-
if (visited.has(schema.name)) {
|
|
613
|
-
return;
|
|
614
|
-
}
|
|
615
|
-
if (visiting.has(schema.name)) {
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
visiting.add(schema.name);
|
|
619
|
-
const deps = extractDependencies(schema);
|
|
620
|
-
for (const depName of deps) {
|
|
621
|
-
const depSchema = schemas[depName];
|
|
622
|
-
if (depSchema && depSchema.kind !== "enum") {
|
|
623
|
-
visit(depSchema);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
visiting.delete(schema.name);
|
|
627
|
-
visited.add(schema.name);
|
|
628
|
-
sorted.push(schema);
|
|
629
|
-
}
|
|
630
|
-
for (const schema of schemaList) {
|
|
631
|
-
visit(schema);
|
|
632
|
-
}
|
|
633
|
-
return sorted;
|
|
634
|
-
}
|
|
635
|
-
function generateMigrations(schemas, options = {}) {
|
|
636
|
-
const migrations = [];
|
|
637
|
-
const pivotTablesGenerated = /* @__PURE__ */ new Set();
|
|
638
|
-
let timestampOffset = 0;
|
|
639
|
-
const sortedSchemas = topologicalSort(schemas);
|
|
640
|
-
for (const schema of sortedSchemas) {
|
|
641
|
-
const timestamp = options.timestamp ?? generateTimestamp();
|
|
642
|
-
const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);
|
|
643
|
-
timestampOffset++;
|
|
644
|
-
const blueprint = schemaToBlueprint(schema, schemas);
|
|
645
|
-
const migration = generateCreateMigration(blueprint, {
|
|
646
|
-
...options,
|
|
647
|
-
timestamp: offsetTimestamp
|
|
648
|
-
});
|
|
649
|
-
migrations.push(migration);
|
|
650
|
-
}
|
|
651
|
-
for (const schema of sortedSchemas) {
|
|
652
|
-
const pivotTables = extractManyToManyRelations(schema, schemas);
|
|
653
|
-
for (const pivot of pivotTables) {
|
|
654
|
-
if (pivotTablesGenerated.has(pivot.tableName)) {
|
|
655
|
-
continue;
|
|
656
|
-
}
|
|
657
|
-
pivotTablesGenerated.add(pivot.tableName);
|
|
658
|
-
const timestamp = options.timestamp ?? generateTimestamp();
|
|
659
|
-
const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);
|
|
660
|
-
timestampOffset++;
|
|
661
|
-
const blueprint = generatePivotTableBlueprint(pivot);
|
|
662
|
-
const migration = generateCreateMigration(blueprint, {
|
|
663
|
-
...options,
|
|
664
|
-
timestamp: offsetTimestamp
|
|
665
|
-
});
|
|
666
|
-
migrations.push(migration);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
return migrations;
|
|
670
|
-
}
|
|
671
|
-
function incrementTimestamp(timestamp, seconds) {
|
|
672
|
-
if (seconds === 0) return timestamp;
|
|
673
|
-
const parts = timestamp.split("_");
|
|
674
|
-
if (parts.length < 4) {
|
|
675
|
-
return timestamp;
|
|
676
|
-
}
|
|
677
|
-
const yearPart = parts[0] ?? "2024";
|
|
678
|
-
const monthPart = parts[1] ?? "01";
|
|
679
|
-
const dayPart = parts[2] ?? "01";
|
|
680
|
-
const timePart = parts[3] ?? "000000";
|
|
681
|
-
const year = parseInt(yearPart, 10);
|
|
682
|
-
const month = parseInt(monthPart, 10) - 1;
|
|
683
|
-
const day = parseInt(dayPart, 10);
|
|
684
|
-
const hours = parseInt(timePart.substring(0, 2), 10);
|
|
685
|
-
const minutes = parseInt(timePart.substring(2, 4), 10);
|
|
686
|
-
const secs = parseInt(timePart.substring(4, 6), 10);
|
|
687
|
-
const date = new Date(year, month, day, hours, minutes, secs + seconds);
|
|
688
|
-
const newYear = date.getFullYear();
|
|
689
|
-
const newMonth = String(date.getMonth() + 1).padStart(2, "0");
|
|
690
|
-
const newDay = String(date.getDate()).padStart(2, "0");
|
|
691
|
-
const newHours = String(date.getHours()).padStart(2, "0");
|
|
692
|
-
const newMinutes = String(date.getMinutes()).padStart(2, "0");
|
|
693
|
-
const newSecs = String(date.getSeconds()).padStart(2, "0");
|
|
694
|
-
return `${newYear}_${newMonth}_${newDay}_${newHours}${newMinutes}${newSecs}`;
|
|
695
|
-
}
|
|
696
|
-
function generateMigrationFromSchema(schema, allSchemas, options = {}) {
|
|
697
|
-
const blueprint = schemaToBlueprint(schema, allSchemas);
|
|
698
|
-
return generateCreateMigration(blueprint, options);
|
|
699
|
-
}
|
|
700
|
-
function generateDropMigrationForTable(tableName, options = {}) {
|
|
701
|
-
return generateDropMigration(tableName, options);
|
|
702
|
-
}
|
|
703
|
-
function formatMigrationFile(migration) {
|
|
704
|
-
return migration.content;
|
|
705
|
-
}
|
|
706
|
-
function getMigrationPath(migration, outputDir = "database/migrations") {
|
|
707
|
-
return `${outputDir}/${migration.fileName}`;
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
// src/migration/alter-generator.ts
|
|
711
|
-
var TYPE_METHOD_MAP2 = {
|
|
712
|
-
String: "string",
|
|
713
|
-
Int: "integer",
|
|
714
|
-
BigInt: "bigInteger",
|
|
715
|
-
Float: "double",
|
|
716
|
-
Decimal: "decimal",
|
|
717
|
-
Boolean: "boolean",
|
|
718
|
-
Text: "text",
|
|
719
|
-
LongText: "longText",
|
|
720
|
-
Date: "date",
|
|
721
|
-
Time: "time",
|
|
722
|
-
Timestamp: "timestamp",
|
|
723
|
-
Json: "json",
|
|
724
|
-
Email: "string",
|
|
725
|
-
Password: "string",
|
|
726
|
-
File: "string",
|
|
727
|
-
MultiFile: "json",
|
|
728
|
-
Enum: "enum",
|
|
729
|
-
Select: "string",
|
|
730
|
-
Lookup: "unsignedBigInteger"
|
|
731
|
-
};
|
|
732
|
-
function generateTimestamp2() {
|
|
733
|
-
const now = /* @__PURE__ */ new Date();
|
|
734
|
-
const year = now.getFullYear();
|
|
735
|
-
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
736
|
-
const day = String(now.getDate()).padStart(2, "0");
|
|
737
|
-
const hours = String(now.getHours()).padStart(2, "0");
|
|
738
|
-
const minutes = String(now.getMinutes()).padStart(2, "0");
|
|
739
|
-
const seconds = String(now.getSeconds()).padStart(2, "0");
|
|
740
|
-
return `${year}_${month}_${day}_${hours}${minutes}${seconds}`;
|
|
741
|
-
}
|
|
742
|
-
function formatAddColumn(columnName, prop) {
|
|
743
|
-
const snakeColumn = toColumnName(columnName);
|
|
744
|
-
const method = TYPE_METHOD_MAP2[prop.type] ?? "string";
|
|
745
|
-
let code;
|
|
746
|
-
if (prop.type === "Decimal") {
|
|
747
|
-
const precision = prop.precision ?? 8;
|
|
748
|
-
const scale = prop.scale ?? 2;
|
|
749
|
-
code = `$table->${method}('${snakeColumn}', ${precision}, ${scale})`;
|
|
750
|
-
} else {
|
|
751
|
-
code = `$table->${method}('${snakeColumn}')`;
|
|
752
|
-
}
|
|
753
|
-
if (prop.nullable) code += "->nullable()";
|
|
754
|
-
if (prop.unique) code += "->unique()";
|
|
755
|
-
if (prop.default !== void 0) {
|
|
756
|
-
const defaultValue = typeof prop.default === "string" ? `'${prop.default}'` : JSON.stringify(prop.default);
|
|
757
|
-
code += `->default(${defaultValue})`;
|
|
758
|
-
}
|
|
759
|
-
return code + ";";
|
|
760
|
-
}
|
|
761
|
-
function formatDropColumn(columnName) {
|
|
762
|
-
const snakeColumn = toColumnName(columnName);
|
|
763
|
-
return `$table->dropColumn('${snakeColumn}');`;
|
|
764
|
-
}
|
|
765
|
-
function formatRenameColumn(oldName, newName) {
|
|
766
|
-
const oldSnake = toColumnName(oldName);
|
|
767
|
-
const newSnake = toColumnName(newName);
|
|
768
|
-
return `$table->renameColumn('${oldSnake}', '${newSnake}');`;
|
|
769
|
-
}
|
|
770
|
-
function formatModifyColumn(columnName, _prevProp, currProp) {
|
|
771
|
-
const snakeColumn = toColumnName(columnName);
|
|
772
|
-
const method = TYPE_METHOD_MAP2[currProp.type] ?? "string";
|
|
773
|
-
let code;
|
|
774
|
-
if (currProp.type === "Decimal") {
|
|
775
|
-
const precision = currProp.precision ?? 8;
|
|
776
|
-
const scale = currProp.scale ?? 2;
|
|
777
|
-
code = `$table->${method}('${snakeColumn}', ${precision}, ${scale})`;
|
|
778
|
-
} else {
|
|
779
|
-
code = `$table->${method}('${snakeColumn}')`;
|
|
780
|
-
}
|
|
781
|
-
if (currProp.nullable) code += "->nullable()";
|
|
782
|
-
if (currProp.unique) code += "->unique()";
|
|
783
|
-
if (currProp.default !== void 0) {
|
|
784
|
-
const defaultValue = typeof currProp.default === "string" ? `'${currProp.default}'` : JSON.stringify(currProp.default);
|
|
785
|
-
code += `->default(${defaultValue})`;
|
|
786
|
-
}
|
|
787
|
-
return code + "->change();";
|
|
788
|
-
}
|
|
789
|
-
function formatAddIndex(columns, unique) {
|
|
790
|
-
const snakeColumns = columns.map(toColumnName);
|
|
791
|
-
const method = unique ? "unique" : "index";
|
|
792
|
-
const colsArg = snakeColumns.length === 1 ? `'${snakeColumns[0]}'` : `[${snakeColumns.map((c) => `'${c}'`).join(", ")}]`;
|
|
793
|
-
return `$table->${method}(${colsArg});`;
|
|
794
|
-
}
|
|
795
|
-
function formatDropIndex(tableName, columns, unique) {
|
|
796
|
-
const snakeColumns = columns.map(toColumnName);
|
|
797
|
-
const method = unique ? "dropUnique" : "dropIndex";
|
|
798
|
-
const suffix = unique ? "unique" : "index";
|
|
799
|
-
const indexName = `${tableName}_${snakeColumns.join("_")}_${suffix}`;
|
|
800
|
-
return `$table->${method}('${indexName}');`;
|
|
801
|
-
}
|
|
802
|
-
function generateAlterMigrationContent(tableName, change, options = {}) {
|
|
803
|
-
const upLines = [];
|
|
804
|
-
const downLines = [];
|
|
805
|
-
if (change.columnChanges) {
|
|
806
|
-
for (const col of change.columnChanges) {
|
|
807
|
-
if (col.changeType === "added" && col.currentDef) {
|
|
808
|
-
upLines.push(` ${formatAddColumn(col.column, col.currentDef)}`);
|
|
809
|
-
downLines.push(` ${formatDropColumn(col.column)}`);
|
|
810
|
-
} else if (col.changeType === "removed" && col.previousDef) {
|
|
811
|
-
upLines.push(` ${formatDropColumn(col.column)}`);
|
|
812
|
-
downLines.push(` ${formatAddColumn(col.column, col.previousDef)}`);
|
|
813
|
-
} else if (col.changeType === "modified" && col.previousDef && col.currentDef) {
|
|
814
|
-
upLines.push(` ${formatModifyColumn(col.column, col.previousDef, col.currentDef)}`);
|
|
815
|
-
downLines.push(` ${formatModifyColumn(col.column, col.currentDef, col.previousDef)}`);
|
|
816
|
-
} else if (col.changeType === "renamed" && col.previousColumn) {
|
|
817
|
-
upLines.push(` ${formatRenameColumn(col.previousColumn, col.column)}`);
|
|
818
|
-
downLines.push(` ${formatRenameColumn(col.column, col.previousColumn)}`);
|
|
819
|
-
if (col.modifications && col.modifications.length > 0 && col.previousDef && col.currentDef) {
|
|
820
|
-
upLines.push(` ${formatModifyColumn(col.column, col.previousDef, col.currentDef)}`);
|
|
821
|
-
downLines.push(` ${formatModifyColumn(col.column, col.currentDef, col.previousDef)}`);
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
if (change.indexChanges) {
|
|
827
|
-
for (const idx of change.indexChanges) {
|
|
828
|
-
if (idx.changeType === "added") {
|
|
829
|
-
upLines.push(` ${formatAddIndex(idx.index.columns, idx.index.unique)}`);
|
|
830
|
-
downLines.push(` ${formatDropIndex(tableName, idx.index.columns, idx.index.unique)}`);
|
|
831
|
-
} else {
|
|
832
|
-
upLines.push(` ${formatDropIndex(tableName, idx.index.columns, idx.index.unique)}`);
|
|
833
|
-
downLines.push(` ${formatAddIndex(idx.index.columns, idx.index.unique)}`);
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
if (change.optionChanges) {
|
|
838
|
-
if (change.optionChanges.timestamps) {
|
|
839
|
-
const { from, to } = change.optionChanges.timestamps;
|
|
840
|
-
if (to && !from) {
|
|
841
|
-
upLines.push(` $table->timestamps();`);
|
|
842
|
-
downLines.push(` $table->dropTimestamps();`);
|
|
843
|
-
} else if (from && !to) {
|
|
844
|
-
upLines.push(` $table->dropTimestamps();`);
|
|
845
|
-
downLines.push(` $table->timestamps();`);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
if (change.optionChanges.softDelete) {
|
|
849
|
-
const { from, to } = change.optionChanges.softDelete;
|
|
850
|
-
if (to && !from) {
|
|
851
|
-
upLines.push(` $table->softDeletes();`);
|
|
852
|
-
downLines.push(` $table->dropSoftDeletes();`);
|
|
853
|
-
} else if (from && !to) {
|
|
854
|
-
upLines.push(` $table->dropSoftDeletes();`);
|
|
855
|
-
downLines.push(` $table->softDeletes();`);
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
const connection = options.connection ? `
|
|
860
|
-
protected $connection = '${options.connection}';
|
|
861
|
-
` : "";
|
|
862
|
-
return `<?php
|
|
863
|
-
|
|
864
|
-
use Illuminate\\Database\\Migrations\\Migration;
|
|
865
|
-
use Illuminate\\Database\\Schema\\Blueprint;
|
|
866
|
-
use Illuminate\\Support\\Facades\\Schema;
|
|
867
|
-
|
|
868
|
-
return new class extends Migration
|
|
869
|
-
{${connection}
|
|
870
|
-
/**
|
|
871
|
-
* Run the migrations.
|
|
872
|
-
*/
|
|
873
|
-
public function up(): void
|
|
874
|
-
{
|
|
875
|
-
Schema::table('${tableName}', function (Blueprint $table) {
|
|
876
|
-
${upLines.join("\n")}
|
|
877
|
-
});
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
/**
|
|
881
|
-
* Reverse the migrations.
|
|
882
|
-
*/
|
|
883
|
-
public function down(): void
|
|
884
|
-
{
|
|
885
|
-
Schema::table('${tableName}', function (Blueprint $table) {
|
|
886
|
-
${downLines.join("\n")}
|
|
887
|
-
});
|
|
888
|
-
}
|
|
889
|
-
};
|
|
890
|
-
`;
|
|
891
|
-
}
|
|
892
|
-
function generateAlterMigration(change, options = {}) {
|
|
893
|
-
if (change.changeType !== "modified") {
|
|
894
|
-
return null;
|
|
895
|
-
}
|
|
896
|
-
const hasChanges = change.columnChanges && change.columnChanges.length > 0 || change.indexChanges && change.indexChanges.length > 0 || change.optionChanges && (change.optionChanges.timestamps || change.optionChanges.softDelete);
|
|
897
|
-
if (!hasChanges) {
|
|
898
|
-
return null;
|
|
899
|
-
}
|
|
900
|
-
const tableName = toTableName(change.schemaName);
|
|
901
|
-
const timestamp = options.timestamp ?? generateTimestamp2();
|
|
902
|
-
const fileName = `${timestamp}_update_${tableName}_table.php`;
|
|
903
|
-
const content = generateAlterMigrationContent(tableName, change, options);
|
|
904
|
-
return {
|
|
905
|
-
fileName,
|
|
906
|
-
className: `Update${change.schemaName}Table`,
|
|
907
|
-
content,
|
|
908
|
-
tables: [tableName],
|
|
909
|
-
type: "alter"
|
|
910
|
-
};
|
|
911
|
-
}
|
|
912
|
-
function generateDropTableMigration(schemaName, options = {}) {
|
|
913
|
-
const tableName = toTableName(schemaName);
|
|
914
|
-
const timestamp = options.timestamp ?? generateTimestamp2();
|
|
915
|
-
const fileName = `${timestamp}_drop_${tableName}_table.php`;
|
|
916
|
-
const connection = options.connection ? `
|
|
917
|
-
protected $connection = '${options.connection}';
|
|
918
|
-
` : "";
|
|
919
|
-
const content = `<?php
|
|
920
|
-
|
|
921
|
-
use Illuminate\\Database\\Migrations\\Migration;
|
|
922
|
-
use Illuminate\\Database\\Schema\\Blueprint;
|
|
923
|
-
use Illuminate\\Support\\Facades\\Schema;
|
|
924
|
-
|
|
925
|
-
return new class extends Migration
|
|
926
|
-
{${connection}
|
|
927
|
-
/**
|
|
928
|
-
* Run the migrations.
|
|
929
|
-
*/
|
|
930
|
-
public function up(): void
|
|
931
|
-
{
|
|
932
|
-
Schema::dropIfExists('${tableName}');
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
/**
|
|
936
|
-
* Reverse the migrations.
|
|
937
|
-
*/
|
|
938
|
-
public function down(): void
|
|
939
|
-
{
|
|
940
|
-
// Cannot recreate table without full schema
|
|
941
|
-
// Consider restoring from backup if needed
|
|
942
|
-
}
|
|
943
|
-
};
|
|
944
|
-
`;
|
|
945
|
-
return {
|
|
946
|
-
fileName,
|
|
947
|
-
className: `Drop${schemaName}Table`,
|
|
948
|
-
content,
|
|
949
|
-
tables: [tableName],
|
|
950
|
-
type: "drop"
|
|
951
|
-
};
|
|
952
|
-
}
|
|
953
|
-
function generateMigrationsFromChanges(changes, options = {}) {
|
|
954
|
-
const migrations = [];
|
|
955
|
-
let timestampOffset = 0;
|
|
956
|
-
const getNextTimestamp = () => {
|
|
957
|
-
const ts = options.timestamp ?? generateTimestamp2();
|
|
958
|
-
const offset = timestampOffset++;
|
|
959
|
-
if (offset === 0) return ts;
|
|
960
|
-
const parts = ts.split("_");
|
|
961
|
-
if (parts.length >= 4) {
|
|
962
|
-
const timePart = parts[3] ?? "000000";
|
|
963
|
-
const secs = parseInt(timePart.substring(4, 6), 10) + offset;
|
|
964
|
-
const newSecs = String(secs % 60).padStart(2, "0");
|
|
965
|
-
parts[3] = timePart.substring(0, 4) + newSecs;
|
|
966
|
-
return parts.join("_");
|
|
967
|
-
}
|
|
968
|
-
return ts;
|
|
969
|
-
};
|
|
970
|
-
for (const change of changes) {
|
|
971
|
-
if (change.changeType === "modified") {
|
|
972
|
-
const migration = generateAlterMigration(change, {
|
|
973
|
-
...options,
|
|
974
|
-
timestamp: getNextTimestamp()
|
|
975
|
-
});
|
|
976
|
-
if (migration) {
|
|
977
|
-
migrations.push(migration);
|
|
978
|
-
}
|
|
979
|
-
} else if (change.changeType === "removed") {
|
|
980
|
-
migrations.push(
|
|
981
|
-
generateDropTableMigration(change.schemaName, {
|
|
982
|
-
...options,
|
|
983
|
-
timestamp: getNextTimestamp()
|
|
984
|
-
})
|
|
985
|
-
);
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
return migrations;
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
// src/plugin.ts
|
|
992
|
-
var LARAVEL_CONFIG_SCHEMA = {
|
|
993
|
-
fields: [
|
|
994
|
-
{
|
|
995
|
-
key: "migrationsPath",
|
|
996
|
-
type: "path",
|
|
997
|
-
label: "Migrations Path",
|
|
998
|
-
description: "Directory for Laravel migration files",
|
|
999
|
-
default: "database/migrations",
|
|
1000
|
-
group: "output"
|
|
1001
|
-
},
|
|
1002
|
-
{
|
|
1003
|
-
key: "connection",
|
|
1004
|
-
type: "string",
|
|
1005
|
-
label: "Database Connection",
|
|
1006
|
-
description: "Laravel database connection name (optional)",
|
|
1007
|
-
placeholder: "mysql",
|
|
1008
|
-
group: "options"
|
|
1009
|
-
}
|
|
1010
|
-
]
|
|
1011
|
-
};
|
|
1012
|
-
function resolveOptions(options) {
|
|
1013
|
-
return {
|
|
1014
|
-
migrationsPath: options?.migrationsPath ?? "database/migrations",
|
|
1015
|
-
connection: options?.connection,
|
|
1016
|
-
timestamp: options?.timestamp
|
|
1017
|
-
};
|
|
1018
|
-
}
|
|
1019
|
-
function laravelPlugin(options) {
|
|
1020
|
-
const resolved = resolveOptions(options);
|
|
1021
|
-
return {
|
|
1022
|
-
name: "@famgia/omnify-laravel",
|
|
1023
|
-
version: "0.0.13",
|
|
1024
|
-
configSchema: LARAVEL_CONFIG_SCHEMA,
|
|
1025
|
-
generators: [
|
|
1026
|
-
{
|
|
1027
|
-
name: "laravel-migrations",
|
|
1028
|
-
description: "Generate Laravel migration files",
|
|
1029
|
-
generate: async (ctx) => {
|
|
1030
|
-
const migrationOptions = {
|
|
1031
|
-
connection: resolved.connection,
|
|
1032
|
-
timestamp: resolved.timestamp
|
|
1033
|
-
};
|
|
1034
|
-
const migrations = generateMigrations(ctx.schemas, migrationOptions);
|
|
1035
|
-
return migrations.map((migration) => ({
|
|
1036
|
-
path: getMigrationPath(migration, resolved.migrationsPath),
|
|
1037
|
-
content: migration.content,
|
|
1038
|
-
type: "migration",
|
|
1039
|
-
metadata: {
|
|
1040
|
-
tableName: migration.tables[0],
|
|
1041
|
-
migrationType: migration.type
|
|
1042
|
-
}
|
|
1043
|
-
}));
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
]
|
|
1047
|
-
};
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
export {
|
|
1051
|
-
toColumnName,
|
|
1052
|
-
toTableName,
|
|
1053
|
-
propertyToColumnMethod,
|
|
1054
|
-
generatePrimaryKeyColumn,
|
|
1055
|
-
generateTimestampColumns,
|
|
1056
|
-
generateSoftDeleteColumn,
|
|
1057
|
-
generateForeignKey,
|
|
1058
|
-
schemaToBlueprint,
|
|
1059
|
-
formatColumnMethod,
|
|
1060
|
-
formatForeignKey,
|
|
1061
|
-
formatIndex,
|
|
1062
|
-
generateMigrations,
|
|
1063
|
-
generateMigrationFromSchema,
|
|
1064
|
-
generateDropMigrationForTable,
|
|
1065
|
-
formatMigrationFile,
|
|
1066
|
-
getMigrationPath,
|
|
1067
|
-
generateAlterMigration,
|
|
1068
|
-
generateDropTableMigration,
|
|
1069
|
-
generateMigrationsFromChanges,
|
|
1070
|
-
laravelPlugin
|
|
1071
|
-
};
|
|
1072
|
-
//# sourceMappingURL=chunk-G4UAJVC2.js.map
|