zenstack-kit 0.1.7 → 0.1.9

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 CHANGED
@@ -102,7 +102,10 @@ Migrations are tracked in the `_prisma_migrations` table, making them compatible
102
102
 
103
103
  ## CLI Commands
104
104
 
105
- Run `zenstack-kit` without arguments to launch the interactive menu, or run commands directly.
105
+ Run `zenstack-kit` without arguments to launch the interactive menu, or run commands directly. For CI or non-TTY environments, pass `--no-ui` to bypass Ink.
106
+
107
+ Global options:
108
+ - `--no-ui` - Disable Ink UI (useful for CI/non-TTY)
106
109
 
107
110
  ### `zenstack-kit init`
108
111
 
@@ -159,6 +162,19 @@ Options:
159
162
  - `--mark-applied` - Mark pending migrations as applied without running SQL
160
163
  - `-c, --config <path>` - Path to zenstack-kit config file
161
164
 
165
+ ### `zenstack-kit migrate rehash`
166
+
167
+ Rebuild the migration log checksums from the `migration.sql` files (useful after manual edits).
168
+
169
+ ```bash
170
+ zenstack-kit migrate rehash
171
+ ```
172
+
173
+ Options:
174
+ - `-m, --migrations <path>` - Migrations directory
175
+ - `--migration <name>` - Rehash a single migration folder
176
+ - `-c, --config <path>` - Path to zenstack-kit config file
177
+
162
178
  ### `zenstack-kit pull`
163
179
 
164
180
  Introspect an existing database and generate a ZenStack schema.
package/dist/cli/app.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  * Commands:
6
6
  * migrate create Generate a new SQL migration
7
7
  * migrate apply Apply pending migrations
8
+ * migrate rehash Rebuild migration log checksums from migration.sql files
8
9
  * init Initialize snapshot from existing schema
9
10
  * pull Introspect database and generate schema
10
11
  */
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/cli/app.tsx"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AA6SH,wBAAgB,MAAM,SAkBrB"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/cli/app.tsx"],"names":[],"mappings":";AAEA;;;;;;;;;GASG;AAgYH,wBAAgB,MAAM,SA4BrB"}
package/dist/cli/app.js CHANGED
@@ -6,17 +6,19 @@ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-run
6
6
  * Commands:
7
7
  * migrate create Generate a new SQL migration
8
8
  * migrate apply Apply pending migrations
9
+ * migrate rehash Rebuild migration log checksums from migration.sql files
9
10
  * init Initialize snapshot from existing schema
10
11
  * pull Introspect database and generate schema
11
12
  */
12
13
  import { useState, useEffect } from "react";
13
14
  import { render, Box, Text, useApp, useInput } from "ink";
14
15
  import SelectInput from "ink-select-input";
15
- import { runMigrateGenerate, runMigrateApply, runInit, runPull, CommandError, } from "./commands.js";
16
+ import { runMigrateGenerate, runMigrateApply, runMigrateRehash, runInit, runPull, CommandError, } from "./commands.js";
16
17
  import { promptSnapshotExists, promptFreshInit, promptPullConfirm, promptTableRename, promptColumnRename, promptMigrationName, promptMigrationConfirm, } from "./prompts.js";
17
18
  const commands = [
18
19
  { label: "migrate create", value: "migrate create", description: "Generate a new SQL migration file" },
19
20
  { label: "migrate apply", value: "migrate apply", description: "Apply pending SQL migrations" },
21
+ { label: "migrate rehash", value: "migrate rehash", description: "Rebuild migration log checksums" },
20
22
  { label: "init", value: "init", description: "Initialize snapshot from existing schema" },
21
23
  { label: "pull", value: "pull", description: "Introspect database and generate schema" },
22
24
  { label: "help", value: "help", description: "Show help information" },
@@ -29,7 +31,7 @@ function parseArgs() {
29
31
  let command;
30
32
  for (let i = 0; i < args.length; i++) {
31
33
  const arg = args[i];
32
- // Handle "migrate create" and "migrate apply" subcommands
34
+ // Handle "migrate create", "migrate apply", and "migrate rehash" subcommands
33
35
  if (arg === "migrate" && args[i + 1] === "create") {
34
36
  command = "migrate create";
35
37
  i++; // Skip the next argument
@@ -38,6 +40,10 @@ function parseArgs() {
38
40
  command = "migrate apply";
39
41
  i++; // Skip the next argument
40
42
  }
43
+ else if (arg === "migrate" && args[i + 1] === "rehash") {
44
+ command = "migrate rehash";
45
+ i++; // Skip the next argument
46
+ }
41
47
  else if (arg === "init" || arg === "pull" || arg === "help") {
42
48
  command = arg;
43
49
  }
@@ -50,6 +56,12 @@ function parseArgs() {
50
56
  else if (arg === "--migrations" || arg === "-m") {
51
57
  options.migrations = args[++i];
52
58
  }
59
+ else if (arg === "--migration") {
60
+ options.migration = args[++i];
61
+ }
62
+ else if (arg === "--no-ui") {
63
+ options.noUi = true;
64
+ }
53
65
  else if (arg === "--dialect") {
54
66
  options.dialect = args[++i];
55
67
  }
@@ -104,7 +116,7 @@ function Status({ type, message }) {
104
116
  }
105
117
  // Help display component
106
118
  function HelpDisplay() {
107
- return (_jsxs(Box, { flexDirection: "column", paddingY: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "zenstack-kit" }), _jsx(Text, { dimColor: true, children: "Database tooling for ZenStack schemas" }), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "Commands:" }), commands.filter(c => c.value !== "exit").map((cmd) => (_jsxs(Box, { marginLeft: 2, children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: cmd.label }) }), _jsx(Text, { dimColor: true, children: cmd.description })] }, cmd.value))), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "Options:" }), _jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "-s, --schema <path> Path to ZenStack schema" }), _jsx(Text, { dimColor: true, children: "-m, --migrations <path> Migrations directory" }), _jsx(Text, { dimColor: true, children: "-n, --name <name> Migration name" }), _jsx(Text, { dimColor: true, children: "--dialect <dialect> Database dialect (sqlite, postgres, mysql)" }), _jsx(Text, { dimColor: true, children: "--url <url> Database connection URL" }), _jsx(Text, { dimColor: true, children: "--create-initial Create initial migration (skip prompt)" }), _jsx(Text, { dimColor: true, children: "--baseline Create baseline only (skip prompt)" }), _jsx(Text, { dimColor: true, children: "--preview Preview pending migrations without applying" }), _jsx(Text, { dimColor: true, children: "--mark-applied Mark pending migrations as applied without running SQL" }), _jsx(Text, { dimColor: true, children: "-f, --force Force operation without confirmation" }), _jsx(Text, { dimColor: true, children: "-c, --config <path> Path to zenstack-kit config file" })] })] }));
119
+ return (_jsxs(Box, { flexDirection: "column", paddingY: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "zenstack-kit" }), _jsx(Text, { dimColor: true, children: "Database tooling for ZenStack schemas" }), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "Commands:" }), commands.filter(c => c.value !== "exit").map((cmd) => (_jsxs(Box, { marginLeft: 2, children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: cmd.label }) }), _jsx(Text, { dimColor: true, children: cmd.description })] }, cmd.value))), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "Options:" }), _jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "-s, --schema <path> Path to ZenStack schema" }), _jsx(Text, { dimColor: true, children: "-m, --migrations <path> Migrations directory" }), _jsx(Text, { dimColor: true, children: "-n, --name <name> Migration name" }), _jsx(Text, { dimColor: true, children: "--dialect <dialect> Database dialect (sqlite, postgres, mysql)" }), _jsx(Text, { dimColor: true, children: "--url <url> Database connection URL" }), _jsx(Text, { dimColor: true, children: "--migration <name> Target a single migration (rehash only)" }), _jsx(Text, { dimColor: true, children: "--no-ui Disable Ink UI (useful for CI/non-TTY)" }), _jsx(Text, { dimColor: true, children: "--create-initial Create initial migration (skip prompt)" }), _jsx(Text, { dimColor: true, children: "--baseline Create baseline only (skip prompt)" }), _jsx(Text, { dimColor: true, children: "--preview Preview pending migrations without applying" }), _jsx(Text, { dimColor: true, children: "--mark-applied Mark pending migrations as applied without running SQL" }), _jsx(Text, { dimColor: true, children: "-f, --force Force operation without confirmation" }), _jsx(Text, { dimColor: true, children: "-c, --config <path> Path to zenstack-kit config file" })] })] }));
108
120
  }
109
121
  function CliApp({ initialCommand, options }) {
110
122
  const { exit } = useApp();
@@ -170,6 +182,9 @@ function CliApp({ initialCommand, options }) {
170
182
  else if (command === "migrate apply") {
171
183
  await runMigrateApply(ctx);
172
184
  }
185
+ else if (command === "migrate rehash") {
186
+ await runMigrateRehash(ctx);
187
+ }
173
188
  else if (command === "init") {
174
189
  await runInit(ctx);
175
190
  }
@@ -221,9 +236,83 @@ function CliApp({ initialCommand, options }) {
221
236
  });
222
237
  return (_jsxs(Box, { flexDirection: "column", paddingY: 1, children: [phase === "select" && (_jsxs(_Fragment, { children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "zenstack-kit" }), _jsx(Text, { dimColor: true, children: " - Select a command" })] }), _jsx(SelectInput, { items: commands, onSelect: handleSelect })] })), command === "help" && _jsx(HelpDisplay, {}), logs.map((l, i) => (_jsx(Status, { type: l.type, message: l.message }, i))), phase === "done" && command !== "help" && !initialCommand && !logs.some((l) => l.type === "error") && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press Enter to continue, 'q' or Escape to exit" }) }))] }));
223
238
  }
239
+ function printHelpText() {
240
+ const lines = [
241
+ "zenstack-kit",
242
+ "Database tooling for ZenStack schemas",
243
+ "",
244
+ "Commands:",
245
+ " migrate create Generate a new SQL migration file",
246
+ " migrate apply Apply pending SQL migrations",
247
+ " migrate rehash Rebuild migration log checksums",
248
+ " init Initialize snapshot from existing schema",
249
+ " pull Introspect database and generate schema",
250
+ " help Show help information",
251
+ "",
252
+ "Options:",
253
+ " -s, --schema <path> Path to ZenStack schema",
254
+ " -m, --migrations <path> Migrations directory",
255
+ " -n, --name <name> Migration name",
256
+ " --dialect <dialect> Database dialect (sqlite, postgres, mysql)",
257
+ " --url <url> Database connection URL",
258
+ " --migration <name> Target a single migration (rehash only)",
259
+ " --no-ui Disable Ink UI (useful for CI/non-TTY)",
260
+ " --create-initial Create initial migration (skip prompt)",
261
+ " --baseline Create baseline only (skip prompt)",
262
+ " --preview Preview pending migrations without applying",
263
+ " --mark-applied Mark pending migrations as applied without running SQL",
264
+ " -f, --force Force operation without confirmation",
265
+ " -c, --config <path> Path to zenstack-kit config file",
266
+ ];
267
+ console.log(lines.join("\n"));
268
+ }
269
+ async function runCommandDirect(command, options) {
270
+ const log = (type, message) => {
271
+ const prefix = type === "error" ? "✗" : type === "success" ? "✓" : type === "warning" ? "⚠" : "ℹ";
272
+ const line = `${prefix} ${message}`;
273
+ if (type === "error") {
274
+ console.error(line);
275
+ }
276
+ else {
277
+ console.log(line);
278
+ }
279
+ };
280
+ const ctx = {
281
+ cwd: process.cwd(),
282
+ options,
283
+ log,
284
+ };
285
+ try {
286
+ if (command === "migrate create") {
287
+ await runMigrateGenerate(ctx);
288
+ }
289
+ else if (command === "migrate apply") {
290
+ await runMigrateApply(ctx);
291
+ }
292
+ else if (command === "migrate rehash") {
293
+ await runMigrateRehash(ctx);
294
+ }
295
+ else if (command === "init") {
296
+ await runInit(ctx);
297
+ }
298
+ else if (command === "pull") {
299
+ await runPull(ctx);
300
+ }
301
+ }
302
+ catch (err) {
303
+ if (err instanceof CommandError) {
304
+ log("error", err.message);
305
+ }
306
+ else {
307
+ log("error", `Error: ${err instanceof Error ? err.message : String(err)}`);
308
+ }
309
+ process.exitCode = 1;
310
+ }
311
+ }
224
312
  // Entry point
225
313
  export function runCli() {
226
314
  const { command, options } = parseArgs();
315
+ const isInteractive = Boolean(process.stdout.isTTY) && !options.noUi;
227
316
  // Show version
228
317
  if (process.argv.includes("--version") || process.argv.includes("-v")) {
229
318
  console.log("0.1.0");
@@ -231,8 +320,17 @@ export function runCli() {
231
320
  }
232
321
  // Show help if no command or --help/-h flag
233
322
  if (!command || process.argv.includes("--help") || process.argv.includes("-h")) {
234
- const { waitUntilExit } = render(_jsx(HelpDisplay, {}));
235
- waitUntilExit().then(() => process.exit(0));
323
+ if (isInteractive) {
324
+ const { waitUntilExit } = render(_jsx(HelpDisplay, {}));
325
+ waitUntilExit().then(() => process.exit(0));
326
+ }
327
+ else {
328
+ printHelpText();
329
+ }
330
+ return;
331
+ }
332
+ if (!isInteractive) {
333
+ void runCommandDirect(command, options);
236
334
  return;
237
335
  }
238
336
  const { waitUntilExit } = render(_jsx(CliApp, { initialCommand: command, options: options }));
@@ -11,6 +11,8 @@ export interface CommandOptions {
11
11
  schema?: string;
12
12
  migrations?: string;
13
13
  name?: string;
14
+ migration?: string;
15
+ noUi?: boolean;
14
16
  dialect?: string;
15
17
  url?: string;
16
18
  output?: string;
@@ -64,6 +66,10 @@ export declare function runMigrateGenerate(ctx: CommandContext): Promise<void>;
64
66
  * migrate:apply command
65
67
  */
66
68
  export declare function runMigrateApply(ctx: CommandContext): Promise<void>;
69
+ /**
70
+ * migrate:rehash command
71
+ */
72
+ export declare function runMigrateRehash(ctx: CommandContext): Promise<void>;
67
73
  /**
68
74
  * init command
69
75
  */
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@ import * as os from "os";
10
10
  import { execFileSync } from "child_process";
11
11
  import { loadConfig } from "../config/loader.js";
12
12
  import { pullSchema } from "../schema/pull.js";
13
- import { createPrismaMigration, applyPrismaMigrations, previewPrismaMigrations, hasPrismaSchemaChanges, hasSnapshot, scanMigrationFolders, writeMigrationLog, initializeSnapshot, createInitialMigration, detectPotentialRenames, } from "../migrations/prisma.js";
13
+ import { createPrismaMigration, applyPrismaMigrations, previewPrismaMigrations, hasPrismaSchemaChanges, hasSnapshot, scanMigrationFolders, readMigrationLog, writeMigrationLog, getMigrationLogPath, calculateChecksum, initializeSnapshot, createInitialMigration, detectPotentialRenames, } from "../migrations/prisma.js";
14
14
  export class CommandError extends Error {
15
15
  constructor(message) {
16
16
  super(message);
@@ -213,8 +213,10 @@ export async function runMigrateApply(ctx) {
213
213
  ctx.log("error", " - Migrations were applied manually without using zenstack-kit");
214
214
  ctx.log("error", " - The migration log file was modified or deleted");
215
215
  ctx.log("error", " - Different migration histories exist across environments");
216
+ ctx.log("error", " - Migration.sql files were edited after being logged");
216
217
  ctx.log("error", "");
217
218
  ctx.log("error", "To resolve, ensure your migration log matches your database state.");
219
+ ctx.log("error", "If you edited migration.sql files, run 'zenstack-kit migrate rehash' to rebuild log checksums.");
218
220
  throw new CommandError("Migration history is inconsistent");
219
221
  }
220
222
  if (result.applied.length === 0 && !result.failed) {
@@ -232,6 +234,45 @@ export async function runMigrateApply(ctx) {
232
234
  throw new CommandError(`Migration failed: ${result.failed.migrationName} - ${result.failed.error}`);
233
235
  }
234
236
  }
237
+ /**
238
+ * migrate:rehash command
239
+ */
240
+ export async function runMigrateRehash(ctx) {
241
+ const { outputPath } = await resolveConfig(ctx);
242
+ const targetMigration = ctx.options.migration;
243
+ if (targetMigration) {
244
+ const sqlPath = path.join(outputPath, targetMigration, "migration.sql");
245
+ if (!fs.existsSync(sqlPath)) {
246
+ throw new CommandError(`Migration not found: ${targetMigration}`);
247
+ }
248
+ const sqlContent = await fs.promises.readFile(sqlPath, "utf-8");
249
+ const checksum = calculateChecksum(sqlContent);
250
+ const entries = await readMigrationLog(outputPath);
251
+ const existingIndex = entries.findIndex((e) => e.name === targetMigration);
252
+ if (existingIndex === -1) {
253
+ entries.push({ name: targetMigration, checksum });
254
+ }
255
+ else {
256
+ entries[existingIndex] = { name: targetMigration, checksum };
257
+ }
258
+ await writeMigrationLog(outputPath, entries);
259
+ const logPath = getMigrationLogPath(outputPath);
260
+ ctx.log("success", `Updated checksum for ${targetMigration}`);
261
+ ctx.log("info", `Log: ${logPath}`);
262
+ ctx.log("warning", "If this migration was already applied, make sure the database checksum matches the updated log.");
263
+ return;
264
+ }
265
+ const migrations = await scanMigrationFolders(outputPath);
266
+ if (migrations.length === 0) {
267
+ ctx.log("warning", "No migrations found.");
268
+ return;
269
+ }
270
+ await writeMigrationLog(outputPath, migrations);
271
+ const logPath = getMigrationLogPath(outputPath);
272
+ ctx.log("success", `Migration log rebuilt with ${migrations.length} migration(s)`);
273
+ ctx.log("info", `Log: ${logPath}`);
274
+ ctx.log("warning", "If these migrations were already applied, make sure the database checksums match the updated log.");
275
+ }
235
276
  /**
236
277
  * init command
237
278
  */
@@ -5,6 +5,7 @@
5
5
  * Commands:
6
6
  * migrate:generate Generate a new SQL migration
7
7
  * migrate:apply Apply pending migrations
8
+ * migrate:rehash Rebuild migration log checksums
8
9
  * init Initialize snapshot from existing schema
9
10
  * pull Introspect database and generate schema
10
11
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;GASG"}
package/dist/cli/index.js CHANGED
@@ -5,6 +5,7 @@
5
5
  * Commands:
6
6
  * migrate:generate Generate a new SQL migration
7
7
  * migrate:apply Apply pending migrations
8
+ * migrate:rehash Rebuild migration log checksums
8
9
  * init Initialize snapshot from existing schema
9
10
  * pull Introspect database and generate schema
10
11
  */
@@ -1 +1 @@
1
- {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/migrations/prisma/apply.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAIjE,MAAM,WAAW,4BAA4B;IAC3C,6BAA6B;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,OAAO,EAAE,aAAa,CAAC;IACvB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,KAAK,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,eAAe,CAAC,EAAE,uBAAuB,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,gBAAgB,GAAG,mBAAmB,CAAC;IAC5G,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,uBAAuB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AA2QD;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,2BAA2B,CAAC,CAyHtC;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,6BAA6B,CAAC,CA0DxC"}
1
+ {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/migrations/prisma/apply.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAIjE,MAAM,WAAW,4BAA4B;IAC3C,6BAA6B;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,OAAO,EAAE,aAAa,CAAC;IACvB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,KAAK,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,eAAe,CAAC,EAAE,uBAAuB,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,gBAAgB,GAAG,mBAAmB,CAAC;IAC5G,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,uBAAuB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AA2QD;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,2BAA2B,CAAC,CA0HtC;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,6BAA6B,CAAC,CA0DxC"}
@@ -298,7 +298,8 @@ export async function applyPrismaMigrations(options) {
298
298
  error: `Checksum mismatch for migration ${folderName}.\n` +
299
299
  `Expected: ${logEntry.checksum}\n` +
300
300
  `Found: ${checksum}\n` +
301
- `The migration file may have been modified after generation.`,
301
+ `The migration file may have been modified after generation.\n` +
302
+ `If you intended this, run 'zenstack-kit migrate rehash' to rebuild log checksums.`,
302
303
  };
303
304
  break;
304
305
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zenstack-kit",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Drizzle-kit like CLI tooling for ZenStack schemas with Kysely support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",