prisma-laravel-migrate 3.0.0 → 3.0.2
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/generator/migrator/PrismaToLaravelMigrationGenerator.js +2 -1
- package/dist/generator/migrator/column-definition.js +1 -0
- package/dist/generator/migrator/index.js +3 -3
- package/dist/generator/migrator/model-definition.js +41 -0
- package/dist/generator/migrator/rules.js +4 -0
- package/dist/utils/sort.js +6 -6
- package/package.json +1 -1
- package/small.prisma +626 -3299
- package/stubs/migration.stub +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ColumnDefinitionGenerator } from "./column-definition.js";
|
|
2
2
|
import { RuleResolver } from "./rule-definition.js";
|
|
3
|
-
import { isForMigrator, parseSilentDirective } from "../../utils/utils.js";
|
|
3
|
+
import { decorate, getConfig, isForMigrator, parseSilentDirective } from "../../utils/utils.js";
|
|
4
4
|
export class PrismaToLaravelMigrationGenerator {
|
|
5
5
|
dmmf;
|
|
6
6
|
columnGen;
|
|
@@ -62,6 +62,7 @@ export class PrismaToLaravelMigrationGenerator {
|
|
|
62
62
|
const isSilent = isForMigrator(parseSilentDirective(model.documentation ?? ""));
|
|
63
63
|
return {
|
|
64
64
|
tableName,
|
|
65
|
+
name: decorate(tableName, getConfig('migrator')),
|
|
65
66
|
isIgnored: isSilent,
|
|
66
67
|
local: isSilent,
|
|
67
68
|
definitions,
|
|
@@ -7,6 +7,7 @@ export class ColumnDefinitionGenerator {
|
|
|
7
7
|
dmmf;
|
|
8
8
|
// private storage for each model’s column definitions
|
|
9
9
|
#columns = {};
|
|
10
|
+
#indexes = {};
|
|
10
11
|
// build a mapping from tableName → ColumnDefinition[]
|
|
11
12
|
#build() {
|
|
12
13
|
return this.dmmf.datamodel.models.reduce((map, model) => {
|
|
@@ -95,15 +95,15 @@ export async function generateLaravelSchema(options) {
|
|
|
95
95
|
let seq = idx + 1;
|
|
96
96
|
let timestamp = formatLaravelTimestamp(now, seq, padWidth);
|
|
97
97
|
// 3) Check for an existing file (old path before sort/repath)
|
|
98
|
-
const existingFile = readdirSync(baseOut).find(f => f.endsWith(`_create_${mig.
|
|
98
|
+
const existingFile = readdirSync(baseOut).find(f => f.endsWith(`_create_${mig.name}_table.php`));
|
|
99
99
|
const existingPath = existingFile ? path.join(baseOut, existingFile) : undefined;
|
|
100
100
|
// 4) If creating new, ensure uniqueness (re-runs within same second)
|
|
101
|
-
let fileName = existingFile ?? `${timestamp}_create_${mig.
|
|
101
|
+
let fileName = existingFile ?? `${timestamp}_create_${mig.name}_table.php`;
|
|
102
102
|
let filePath = path.join(baseOut, fileName);
|
|
103
103
|
while (!existingFile && existsSync(filePath)) {
|
|
104
104
|
seq += 1;
|
|
105
105
|
timestamp = formatLaravelTimestamp(now, seq, padWidth);
|
|
106
|
-
fileName = `${timestamp}_create_${mig.
|
|
106
|
+
fileName = `${timestamp}_create_${mig.name}_table.php`;
|
|
107
107
|
filePath = path.join(baseOut, fileName);
|
|
108
108
|
}
|
|
109
109
|
// 5) Generate and write (merge from old path, write to new path)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export function buildCompositeFromIndexes(model) {
|
|
2
|
+
const raw = (model.indexes ?? []);
|
|
3
|
+
const isComposite = (i) => Array.isArray(i.fields) && i.fields.length > 1 && i.isDefinedOnField !== true;
|
|
4
|
+
const isPk = (i) => {
|
|
5
|
+
const t = (i.type || "").toLowerCase();
|
|
6
|
+
return t === "id" || t === "primary";
|
|
7
|
+
};
|
|
8
|
+
const isUnique = (i) => (typeof i.type === "string" && i.type.toLowerCase() === "unique") || i.isUnique === true;
|
|
9
|
+
const uniques = [];
|
|
10
|
+
const normals = [];
|
|
11
|
+
for (const i of raw) {
|
|
12
|
+
if (!isComposite(i) || isPk(i))
|
|
13
|
+
continue;
|
|
14
|
+
const spec = { fields: i.fields, name: i.name };
|
|
15
|
+
(isUnique(i) ? uniques : normals).push(spec);
|
|
16
|
+
}
|
|
17
|
+
// de-dupe by ordered field list (ignore name for dedupe)
|
|
18
|
+
const dedupe = (xs) => {
|
|
19
|
+
const seen = new Set();
|
|
20
|
+
return xs.filter(x => {
|
|
21
|
+
const key = x.fields.join("|");
|
|
22
|
+
if (seen.has(key))
|
|
23
|
+
return false;
|
|
24
|
+
seen.add(key);
|
|
25
|
+
return true;
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
return {
|
|
29
|
+
...model,
|
|
30
|
+
compositeUniques: dedupe(uniques),
|
|
31
|
+
compositeNormals: dedupe(normals),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Optional: build for all models in a DMMF document */
|
|
35
|
+
export function buildAllCompositeFromIndexes(doc) {
|
|
36
|
+
const out = {};
|
|
37
|
+
for (const m of doc.datamodel.models)
|
|
38
|
+
out[m.name] = buildCompositeFromIndexes(m);
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=model-definition.js.map
|
|
@@ -169,6 +169,10 @@ function runNormal(def, defaultMaps, snippet) {
|
|
|
169
169
|
? `, ${def.args.map(a => JSON.stringify(a)).join(", ")}`
|
|
170
170
|
: "";
|
|
171
171
|
let line = `$table->${def.migrationType}('${def.name}'${argsStr})`;
|
|
172
|
+
if (def.isUnique)
|
|
173
|
+
line += "->unique()";
|
|
174
|
+
if (def.isIndexed)
|
|
175
|
+
line += "->index()";
|
|
172
176
|
if (def.unsigned)
|
|
173
177
|
line += "->unsigned()";
|
|
174
178
|
if (def.nullable)
|
package/dist/utils/sort.js
CHANGED
|
@@ -6,10 +6,10 @@ export function sortMigrations(migrations) {
|
|
|
6
6
|
// ⬅️ NEW: drop migrations silenced for the migrator
|
|
7
7
|
migrations = migrations.filter(m => !m.local);
|
|
8
8
|
// 1) Build a map: tableName → Migration
|
|
9
|
-
const migMap = new Map(migrations.map(m => [m.
|
|
9
|
+
const migMap = new Map(migrations.map(m => [m.name, m]));
|
|
10
10
|
// 2) Collect “true” FKs only (skip back‐relation object fields)
|
|
11
11
|
const rawDeps = new Map();
|
|
12
|
-
for (const { tableName } of migrations) {
|
|
12
|
+
for (const { name: tableName } of migrations) {
|
|
13
13
|
rawDeps.set(tableName, new Set());
|
|
14
14
|
}
|
|
15
15
|
for (const m of migrations) {
|
|
@@ -24,9 +24,9 @@ export function sortMigrations(migrations) {
|
|
|
24
24
|
continue;
|
|
25
25
|
}
|
|
26
26
|
const parent = def.relationship.on;
|
|
27
|
-
if (!migMap.has(parent) || m.
|
|
27
|
+
if (!migMap.has(parent) || m.name === parent)
|
|
28
28
|
continue; // skip external/self
|
|
29
|
-
rawDeps.get(m.
|
|
29
|
+
rawDeps.get(m.name).add(parent);
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
// 3) Build adjacency (parent → dependents) and in-degree (table → count)
|
|
@@ -62,8 +62,8 @@ export function sortMigrations(migrations) {
|
|
|
62
62
|
// 5) Cycle check
|
|
63
63
|
if (sorted.length !== migrations.length) {
|
|
64
64
|
const cycle = migrations
|
|
65
|
-
.map(m => m.
|
|
66
|
-
.filter(t => !sorted.some(s => s.
|
|
65
|
+
.map(m => m.name)
|
|
66
|
+
.filter(t => !sorted.some(s => s.name === t));
|
|
67
67
|
throw new Error(`Cycle detected in migration dependencies: ${cycle.join(' → ')}`);
|
|
68
68
|
}
|
|
69
69
|
console.log('\n📦 Sorted Migration Tables:\n' +
|