zenstack-kit 0.1.4 → 0.1.7
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 +18 -6
- package/dist/cli/app.d.ts.map +1 -1
- package/dist/cli/app.js +7 -1
- package/dist/cli/commands.d.ts +2 -0
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +97 -6
- package/dist/cli/prompts.d.ts.map +1 -1
- package/dist/cli/prompts.js +1 -3
- package/dist/config/loader.d.ts +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +11 -9
- package/dist/migrations/prisma/apply.d.ts +54 -0
- package/dist/migrations/prisma/apply.d.ts.map +1 -0
- package/dist/migrations/prisma/apply.js +384 -0
- package/dist/migrations/prisma/create.d.ts +63 -0
- package/dist/migrations/prisma/create.d.ts.map +1 -0
- package/dist/migrations/prisma/create.js +119 -0
- package/dist/migrations/prisma/diff.d.ts +104 -0
- package/dist/migrations/prisma/diff.d.ts.map +1 -0
- package/dist/migrations/prisma/diff.js +442 -0
- package/dist/migrations/prisma/log.d.ts +31 -0
- package/dist/migrations/prisma/log.d.ts.map +1 -0
- package/dist/migrations/prisma/log.js +101 -0
- package/dist/migrations/prisma/rename.d.ts +23 -0
- package/dist/migrations/prisma/rename.d.ts.map +1 -0
- package/dist/migrations/prisma/rename.js +57 -0
- package/dist/migrations/prisma/snapshot.d.ts +32 -0
- package/dist/migrations/prisma/snapshot.d.ts.map +1 -0
- package/dist/migrations/prisma/snapshot.js +65 -0
- package/dist/migrations/prisma.d.ts +5 -202
- package/dist/migrations/prisma.d.ts.map +1 -1
- package/dist/migrations/prisma.js +5 -1168
- package/dist/schema/pull.d.ts +2 -0
- package/dist/schema/pull.d.ts.map +1 -1
- package/dist/schema/pull.js +102 -4
- package/package.json +1 -1
package/dist/schema/pull.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/schema/pull.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEnF,MAAM,WAAW,WAAW;IAC1B,uBAAuB;IACvB,OAAO,EAAE,aAAa,CAAC;IACvB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/schema/pull.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEnF,MAAM,WAAW,WAAW;IAC1B,uBAAuB;IACvB,OAAO,EAAE,aAAa,CAAC;IACvB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AA8lBD,wBAAsB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA4C1E"}
|
package/dist/schema/pull.js
CHANGED
|
@@ -52,6 +52,10 @@ function normalizeType(dataType) {
|
|
|
52
52
|
const isArray = lower.endsWith("[]");
|
|
53
53
|
const base = isArray ? lower.slice(0, -2) : lower;
|
|
54
54
|
const normalized = base.replace(/\(.+\)/, "").trim();
|
|
55
|
+
if (normalized.includes("uuid") || normalized.includes("citext"))
|
|
56
|
+
return { type: "String", isArray };
|
|
57
|
+
if (normalized.includes("jsonb"))
|
|
58
|
+
return { type: "Json", isArray };
|
|
55
59
|
if (normalized.includes("bigint"))
|
|
56
60
|
return { type: "BigInt", isArray };
|
|
57
61
|
if (normalized.includes("int"))
|
|
@@ -87,7 +91,7 @@ function buildDatasourceBlock(dialect) {
|
|
|
87
91
|
].join("\n");
|
|
88
92
|
}
|
|
89
93
|
function buildModelBlock(options) {
|
|
90
|
-
const { table, foreignKeys, indexes, primaryKeys, allTables } = options;
|
|
94
|
+
const { table, foreignKeys, indexes, primaryKeys, allTables, columnDefaults } = options;
|
|
91
95
|
const modelName = toPascalCase(table.name) || "Model";
|
|
92
96
|
const fieldLines = [];
|
|
93
97
|
// Get primary key columns for this table
|
|
@@ -123,6 +127,45 @@ function buildModelBlock(options) {
|
|
|
123
127
|
}
|
|
124
128
|
}
|
|
125
129
|
}
|
|
130
|
+
const getDefaultExpr = (columnName) => columnDefaults.get(columnName) ?? null;
|
|
131
|
+
const buildDefaultAttribute = (defaultExpr, dataType) => {
|
|
132
|
+
if (!defaultExpr)
|
|
133
|
+
return null;
|
|
134
|
+
const normalized = defaultExpr.trim();
|
|
135
|
+
if (!normalized || normalized.toLowerCase() === "null")
|
|
136
|
+
return null;
|
|
137
|
+
const lower = normalized.toLowerCase();
|
|
138
|
+
if (lower.includes("nextval("))
|
|
139
|
+
return null;
|
|
140
|
+
if (lower === "current_timestamp" ||
|
|
141
|
+
lower === "current_timestamp()" ||
|
|
142
|
+
lower === "now()" ||
|
|
143
|
+
lower.includes("datetime('now") ||
|
|
144
|
+
lower.includes("now()")) {
|
|
145
|
+
return "@default(now())";
|
|
146
|
+
}
|
|
147
|
+
if (lower.includes("uuid_generate_v4()") || lower.includes("gen_random_uuid()") || lower === "uuid()") {
|
|
148
|
+
return "@default(uuid())";
|
|
149
|
+
}
|
|
150
|
+
if (lower === "true" || lower === "false") {
|
|
151
|
+
return `@default(${lower})`;
|
|
152
|
+
}
|
|
153
|
+
if ((lower === "0" || lower === "1") && dataType.toLowerCase().includes("bool")) {
|
|
154
|
+
return `@default(${lower === "1" ? "true" : "false"})`;
|
|
155
|
+
}
|
|
156
|
+
if (/^-?\d+(\.\d+)?$/.test(normalized)) {
|
|
157
|
+
return `@default(${normalized})`;
|
|
158
|
+
}
|
|
159
|
+
if ((normalized.startsWith("'") && normalized.endsWith("'")) ||
|
|
160
|
+
(normalized.startsWith("\"") && normalized.endsWith("\""))) {
|
|
161
|
+
const unquoted = normalized
|
|
162
|
+
.slice(1, -1)
|
|
163
|
+
.replace(/''/g, "'")
|
|
164
|
+
.replace(/\\"/g, "\"");
|
|
165
|
+
return `@default(${JSON.stringify(unquoted)})`;
|
|
166
|
+
}
|
|
167
|
+
return "@default(dbgenerated())";
|
|
168
|
+
};
|
|
126
169
|
const sortedColumns = [...table.columns].sort((a, b) => a.name.localeCompare(b.name));
|
|
127
170
|
for (const column of sortedColumns) {
|
|
128
171
|
const fieldName = toCamelCase(column.name) || column.name;
|
|
@@ -146,7 +189,13 @@ function buildModelBlock(options) {
|
|
|
146
189
|
modifiers.push(`@map("${column.name}")`);
|
|
147
190
|
}
|
|
148
191
|
if (column.hasDefaultValue && !modifiers.some((m) => m.includes("@default"))) {
|
|
149
|
-
|
|
192
|
+
const attr = buildDefaultAttribute(getDefaultExpr(column.name), column.dataType);
|
|
193
|
+
if (attr) {
|
|
194
|
+
modifiers.push(attr);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
modifiers.push("@default(dbgenerated())");
|
|
198
|
+
}
|
|
150
199
|
}
|
|
151
200
|
const typeSuffix = isArray ? "[]" : "";
|
|
152
201
|
const modifierText = modifiers.length > 0 ? ` ${modifiers.join(" ")}` : "";
|
|
@@ -389,6 +438,51 @@ async function extractPrimaryKeys(db, dialect, tableNames) {
|
|
|
389
438
|
}
|
|
390
439
|
return primaryKeys;
|
|
391
440
|
}
|
|
441
|
+
async function extractColumnDefaults(db, dialect, tableNames) {
|
|
442
|
+
const defaultsByTable = new Map();
|
|
443
|
+
const tableSet = new Set(tableNames);
|
|
444
|
+
const setDefault = (table, column, value) => {
|
|
445
|
+
if (!defaultsByTable.has(table)) {
|
|
446
|
+
defaultsByTable.set(table, new Map());
|
|
447
|
+
}
|
|
448
|
+
defaultsByTable.get(table).set(column, value);
|
|
449
|
+
};
|
|
450
|
+
if (dialect === "sqlite") {
|
|
451
|
+
for (const tableName of tableNames) {
|
|
452
|
+
const result = await sql `
|
|
453
|
+
PRAGMA table_info(${sql.raw(`"${tableName}"`)})
|
|
454
|
+
`.execute(db);
|
|
455
|
+
for (const row of result.rows) {
|
|
456
|
+
setDefault(tableName, row.name, row.dflt_value);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
else if (dialect === "postgres") {
|
|
461
|
+
const result = await sql `
|
|
462
|
+
SELECT table_name, column_name, column_default
|
|
463
|
+
FROM information_schema.columns
|
|
464
|
+
WHERE table_schema = 'public'
|
|
465
|
+
`.execute(db);
|
|
466
|
+
for (const row of result.rows) {
|
|
467
|
+
if (!tableSet.has(row.table_name))
|
|
468
|
+
continue;
|
|
469
|
+
setDefault(row.table_name, row.column_name, row.column_default);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
else if (dialect === "mysql") {
|
|
473
|
+
const result = await sql `
|
|
474
|
+
SELECT TABLE_NAME, COLUMN_NAME, COLUMN_DEFAULT
|
|
475
|
+
FROM information_schema.COLUMNS
|
|
476
|
+
WHERE TABLE_SCHEMA = DATABASE()
|
|
477
|
+
`.execute(db);
|
|
478
|
+
for (const row of result.rows) {
|
|
479
|
+
if (!tableSet.has(row.TABLE_NAME))
|
|
480
|
+
continue;
|
|
481
|
+
setDefault(row.TABLE_NAME, row.COLUMN_NAME, row.COLUMN_DEFAULT);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
return defaultsByTable;
|
|
485
|
+
}
|
|
392
486
|
export async function pullSchema(options) {
|
|
393
487
|
const { db, destroy } = await createKyselyAdapter({
|
|
394
488
|
dialect: options.dialect,
|
|
@@ -403,16 +497,20 @@ export async function pullSchema(options) {
|
|
|
403
497
|
const foreignKeys = await extractForeignKeys(db, options.dialect);
|
|
404
498
|
const indexes = await extractIndexes(db, options.dialect, tableNames);
|
|
405
499
|
const primaryKeys = await extractPrimaryKeys(db, options.dialect, tableNames);
|
|
500
|
+
const columnDefaultsByTable = await extractColumnDefaults(db, options.dialect, tableNames);
|
|
406
501
|
const blocks = filtered.map((table) => buildModelBlock({
|
|
407
502
|
table,
|
|
408
503
|
foreignKeys,
|
|
409
504
|
indexes,
|
|
410
505
|
primaryKeys,
|
|
411
506
|
allTables,
|
|
507
|
+
columnDefaults: columnDefaultsByTable.get(table.name) ?? new Map(),
|
|
412
508
|
}));
|
|
413
509
|
const schema = [buildDatasourceBlock(options.dialect), ...blocks].join("\n\n");
|
|
414
|
-
|
|
415
|
-
|
|
510
|
+
if (options.writeFile !== false) {
|
|
511
|
+
await fs.mkdir(path.dirname(options.outputPath), { recursive: true });
|
|
512
|
+
await fs.writeFile(options.outputPath, schema.trimEnd() + "\n", "utf-8");
|
|
513
|
+
}
|
|
416
514
|
return {
|
|
417
515
|
outputPath: options.outputPath,
|
|
418
516
|
schema,
|