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.
Files changed (36) hide show
  1. package/README.md +18 -6
  2. package/dist/cli/app.d.ts.map +1 -1
  3. package/dist/cli/app.js +7 -1
  4. package/dist/cli/commands.d.ts +2 -0
  5. package/dist/cli/commands.d.ts.map +1 -1
  6. package/dist/cli/commands.js +97 -6
  7. package/dist/cli/prompts.d.ts.map +1 -1
  8. package/dist/cli/prompts.js +1 -3
  9. package/dist/config/loader.d.ts +1 -1
  10. package/dist/config/loader.d.ts.map +1 -1
  11. package/dist/config/loader.js +11 -9
  12. package/dist/migrations/prisma/apply.d.ts +54 -0
  13. package/dist/migrations/prisma/apply.d.ts.map +1 -0
  14. package/dist/migrations/prisma/apply.js +384 -0
  15. package/dist/migrations/prisma/create.d.ts +63 -0
  16. package/dist/migrations/prisma/create.d.ts.map +1 -0
  17. package/dist/migrations/prisma/create.js +119 -0
  18. package/dist/migrations/prisma/diff.d.ts +104 -0
  19. package/dist/migrations/prisma/diff.d.ts.map +1 -0
  20. package/dist/migrations/prisma/diff.js +442 -0
  21. package/dist/migrations/prisma/log.d.ts +31 -0
  22. package/dist/migrations/prisma/log.d.ts.map +1 -0
  23. package/dist/migrations/prisma/log.js +101 -0
  24. package/dist/migrations/prisma/rename.d.ts +23 -0
  25. package/dist/migrations/prisma/rename.d.ts.map +1 -0
  26. package/dist/migrations/prisma/rename.js +57 -0
  27. package/dist/migrations/prisma/snapshot.d.ts +32 -0
  28. package/dist/migrations/prisma/snapshot.d.ts.map +1 -0
  29. package/dist/migrations/prisma/snapshot.js +65 -0
  30. package/dist/migrations/prisma.d.ts +5 -202
  31. package/dist/migrations/prisma.d.ts.map +1 -1
  32. package/dist/migrations/prisma.js +5 -1168
  33. package/dist/schema/pull.d.ts +2 -0
  34. package/dist/schema/pull.d.ts.map +1 -1
  35. package/dist/schema/pull.js +102 -4
  36. package/package.json +1 -1
@@ -13,6 +13,8 @@ export interface PullOptions {
13
13
  databasePath?: string;
14
14
  /** Output path for schema */
15
15
  outputPath: string;
16
+ /** Write the schema to outputPath (default: true) */
17
+ writeFile?: boolean;
16
18
  }
17
19
  export interface PullResult {
18
20
  outputPath: string;
@@ -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;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAofD,wBAAsB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAwC1E"}
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"}
@@ -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
- modifiers.push("@default(dbgenerated())");
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
- await fs.mkdir(path.dirname(options.outputPath), { recursive: true });
415
- await fs.writeFile(options.outputPath, schema.trimEnd() + "\n", "utf-8");
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zenstack-kit",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "description": "Drizzle-kit like CLI tooling for ZenStack schemas with Kysely support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",