zenstack-kit 0.1.1 → 0.1.3

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 (52) hide show
  1. package/dist/cli/app.d.ts.map +1 -1
  2. package/dist/cli/app.js +9 -28
  3. package/dist/cli/commands.d.ts +3 -1
  4. package/dist/cli/commands.d.ts.map +1 -1
  5. package/dist/cli/commands.js +34 -1
  6. package/dist/cli/index.js +0 -0
  7. package/dist/cli/prompts.d.ts +9 -0
  8. package/dist/cli/prompts.d.ts.map +1 -1
  9. package/dist/cli/prompts.js +57 -1
  10. package/dist/migrations/prisma.d.ts +10 -0
  11. package/dist/migrations/prisma.d.ts.map +1 -1
  12. package/dist/migrations/prisma.js +85 -3
  13. package/package.json +1 -5
  14. package/dist/cli.d.ts +0 -12
  15. package/dist/cli.d.ts.map +0 -1
  16. package/dist/cli.js +0 -240
  17. package/dist/config-loader.d.ts +0 -6
  18. package/dist/config-loader.d.ts.map +0 -1
  19. package/dist/config-loader.js +0 -36
  20. package/dist/config.d.ts +0 -62
  21. package/dist/config.d.ts.map +0 -1
  22. package/dist/config.js +0 -44
  23. package/dist/init-prompts.d.ts +0 -13
  24. package/dist/init-prompts.d.ts.map +0 -1
  25. package/dist/init-prompts.js +0 -64
  26. package/dist/introspect.d.ts +0 -54
  27. package/dist/introspect.d.ts.map +0 -1
  28. package/dist/introspect.js +0 -75
  29. package/dist/kysely-adapter.d.ts +0 -49
  30. package/dist/kysely-adapter.d.ts.map +0 -1
  31. package/dist/kysely-adapter.js +0 -74
  32. package/dist/migrate-apply.d.ts +0 -18
  33. package/dist/migrate-apply.d.ts.map +0 -1
  34. package/dist/migrate-apply.js +0 -61
  35. package/dist/migrations.d.ts +0 -161
  36. package/dist/migrations.d.ts.map +0 -1
  37. package/dist/migrations.js +0 -620
  38. package/dist/prisma-migrations.d.ts +0 -160
  39. package/dist/prisma-migrations.d.ts.map +0 -1
  40. package/dist/prisma-migrations.js +0 -789
  41. package/dist/prompts.d.ts +0 -10
  42. package/dist/prompts.d.ts.map +0 -1
  43. package/dist/prompts.js +0 -41
  44. package/dist/pull.d.ts +0 -23
  45. package/dist/pull.d.ts.map +0 -1
  46. package/dist/pull.js +0 -424
  47. package/dist/schema-snapshot.d.ts +0 -45
  48. package/dist/schema-snapshot.d.ts.map +0 -1
  49. package/dist/schema-snapshot.js +0 -265
  50. package/dist/sql-compiler.d.ts +0 -74
  51. package/dist/sql-compiler.d.ts.map +0 -1
  52. package/dist/sql-compiler.js +0 -243
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/cli/app.tsx"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AAiVH,wBAAgB,MAAM,SAkBrB"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/cli/app.tsx"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AAuSH,wBAAgB,MAAM,SAkBrB"}
package/dist/cli/app.js CHANGED
@@ -13,7 +13,7 @@ import { useState, useEffect } from "react";
13
13
  import { render, Box, Text, useApp, useInput } from "ink";
14
14
  import SelectInput from "ink-select-input";
15
15
  import { runMigrateGenerate, runMigrateApply, runInit, runPull, CommandError, } from "./commands.js";
16
- import { promptSnapshotExists, promptFreshInit, promptPullConfirm, promptTableRename, promptColumnRename, } from "./prompts.js";
16
+ import { promptSnapshotExists, promptFreshInit, promptPullConfirm, promptTableRename, promptColumnRename, promptMigrationName, promptMigrationConfirm, } from "./prompts.js";
17
17
  const commands = [
18
18
  { label: "migrate create", value: "migrate create", description: "Generate a new SQL migration file" },
19
19
  { label: "migrate apply", value: "migrate apply", description: "Apply pending SQL migrations" },
@@ -100,22 +100,6 @@ function Status({ type, message }) {
100
100
  function HelpDisplay() {
101
101
  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: "-f, --force Force operation without confirmation" })] })] }));
102
102
  }
103
- // Text input component for migration name
104
- function TextInput({ prompt, defaultValue, onSubmit }) {
105
- const [value, setValue] = useState("");
106
- useInput((input, key) => {
107
- if (key.return) {
108
- onSubmit(value.trim() || defaultValue);
109
- }
110
- else if (key.backspace || key.delete) {
111
- setValue((prev) => prev.slice(0, -1));
112
- }
113
- else if (!key.ctrl && !key.meta && input) {
114
- setValue((prev) => prev + input);
115
- }
116
- });
117
- return (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: "? " }), _jsxs(Text, { children: [prompt, " "] }), _jsxs(Text, { dimColor: true, children: ["(", defaultValue, "): "] }), _jsx(Text, { children: value }), _jsx(Text, { color: "gray", children: "\u2588" })] }));
118
- }
119
103
  function CliApp({ initialCommand, options }) {
120
104
  const { exit } = useApp();
121
105
  const [command, setCommand] = useState(initialCommand || null);
@@ -137,16 +121,7 @@ function CliApp({ initialCommand, options }) {
137
121
  return;
138
122
  }
139
123
  setCommand(item.value);
140
- if (item.value === "migrate create" && !migrationName) {
141
- setPhase("input");
142
- }
143
- else {
144
- setPhase("running");
145
- }
146
- };
147
- // Handle migration name input
148
- const handleNameSubmit = (name) => {
149
- setMigrationName(name);
124
+ // Always go to running - migration name prompt now happens after disambiguation
150
125
  setPhase("running");
151
126
  };
152
127
  // Execute commands
@@ -175,6 +150,12 @@ function CliApp({ initialCommand, options }) {
175
150
  promptColumnRename: async (table, from, to) => {
176
151
  return await promptColumnRename(table, from, to);
177
152
  },
153
+ promptMigrationName: async (defaultName) => {
154
+ return await promptMigrationName(defaultName);
155
+ },
156
+ promptMigrationConfirm: async (migrationPath) => {
157
+ return await promptMigrationConfirm(migrationPath);
158
+ },
178
159
  };
179
160
  try {
180
161
  if (command === "migrate create") {
@@ -232,7 +213,7 @@ function CliApp({ initialCommand, options }) {
232
213
  }
233
214
  }
234
215
  });
235
- 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 })] })), phase === "input" && command === "migrate create" && (_jsx(TextInput, { prompt: "Migration name", defaultValue: "migration", onSubmit: handleNameSubmit })), 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" }) }))] }));
216
+ 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" }) }))] }));
236
217
  }
237
218
  // Entry point
238
219
  export function runCli() {
@@ -4,7 +4,7 @@
4
4
  * These functions contain the core logic and can be tested independently
5
5
  * from the CLI/UI layer.
6
6
  */
7
- import type { RenameChoice } from "./prompts.js";
7
+ import type { RenameChoice, MigrationConfirmChoice } from "./prompts.js";
8
8
  import type { ZenStackKitConfig } from "../config/index.js";
9
9
  export type LogFn = (type: "info" | "success" | "error" | "warning", message: string) => void;
10
10
  export interface CommandOptions {
@@ -30,6 +30,8 @@ export interface CommandContext {
30
30
  promptPullConfirm?: (existingFiles: string[]) => Promise<boolean>;
31
31
  promptTableRename?: (from: string, to: string) => Promise<RenameChoice>;
32
32
  promptColumnRename?: (table: string, from: string, to: string) => Promise<RenameChoice>;
33
+ promptMigrationName?: (defaultName: string) => Promise<string>;
34
+ promptMigrationConfirm?: (migrationPath: string) => Promise<MigrationConfirmChoice>;
33
35
  }
34
36
  export declare class CommandError extends Error {
35
37
  constructor(message: string);
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkBH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,MAAM,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAE9F,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,cAAc,CAAC;IACxB,GAAG,EAAE,KAAK,CAAC;IACX,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,cAAc,CAAC,CAAC;IAC9D,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,UAAU,GAAG,gBAAgB,CAAC,CAAC;IAC/D,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAClE,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IACxE,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CACzF;AAED,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;IAChE,MAAM,EAAE,iBAAiB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;CAC1C,CAAC,CAkBD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAI7D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,GACvC,MAAM,GAAG,SAAS,CAKpB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAkE3E;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAiFxE;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA0FhE;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEhE"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
@@ -90,7 +90,23 @@ export async function runMigrateGenerate(ctx) {
90
90
  }
91
91
  }
92
92
  }
93
- const name = ctx.options.name || "migration";
93
+ // Prompt for migration name if not provided via flag
94
+ let name = ctx.options.name;
95
+ if (!name && ctx.promptMigrationName) {
96
+ name = await ctx.promptMigrationName("migration");
97
+ }
98
+ name = name || "migration";
99
+ // Compute expected migration path for confirmation
100
+ const safeName = name.replace(/[^a-z0-9]/gi, "_").toLowerCase();
101
+ const expectedPath = path.join(outputPath, `<timestamp>_${safeName}`, "migration.sql");
102
+ // Prompt for confirmation before creating
103
+ if (ctx.promptMigrationConfirm) {
104
+ const confirmChoice = await ctx.promptMigrationConfirm(expectedPath);
105
+ if (confirmChoice === "cancel") {
106
+ ctx.log("warning", "Migration creation cancelled");
107
+ return;
108
+ }
109
+ }
94
110
  const migration = await createPrismaMigration({
95
111
  name,
96
112
  schemaPath,
@@ -161,6 +177,23 @@ export async function runMigrateApply(ctx) {
161
177
  migrationsTable,
162
178
  migrationsSchema,
163
179
  });
180
+ // Handle coherence errors
181
+ if (result.coherenceErrors && result.coherenceErrors.length > 0) {
182
+ ctx.log("error", "Migration history is inconsistent");
183
+ ctx.log("error", "");
184
+ ctx.log("error", "The following issues were found:");
185
+ for (const err of result.coherenceErrors) {
186
+ ctx.log("error", ` - ${err.details}`);
187
+ }
188
+ ctx.log("error", "");
189
+ ctx.log("error", "This can happen when:");
190
+ ctx.log("error", " - Migrations were applied manually without using zenstack-kit");
191
+ ctx.log("error", " - The migration log file was modified or deleted");
192
+ ctx.log("error", " - Different migration histories exist across environments");
193
+ ctx.log("error", "");
194
+ ctx.log("error", "To resolve, ensure your migration log matches your database state.");
195
+ throw new CommandError("Migration history is inconsistent");
196
+ }
164
197
  if (result.applied.length === 0 && !result.failed) {
165
198
  ctx.log("warning", "No pending migrations");
166
199
  if (result.alreadyApplied.length > 0) {
package/dist/cli/index.js CHANGED
File without changes
@@ -16,6 +16,15 @@ export declare function promptFreshInit(): Promise<InitChoice>;
16
16
  */
17
17
  export declare function promptPullConfirm(existingFiles: string[]): Promise<boolean>;
18
18
  export type RenameChoice = "rename" | "delete_create";
19
+ /**
20
+ * Prompt user for migration name
21
+ */
22
+ export declare function promptMigrationName(defaultName?: string): Promise<string>;
23
+ export type MigrationConfirmChoice = "create" | "cancel";
24
+ /**
25
+ * Prompt user to confirm migration creation
26
+ */
27
+ export declare function promptMigrationConfirm(migrationPath: string): Promise<MigrationConfirmChoice>;
19
28
  /**
20
29
  * Prompt user to disambiguate a potential table rename
21
30
  */
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/cli/prompts.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,cAAc,GAAG,UAAU,GAAG,gBAAgB,CAAC;AACjF,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,IAAI,CAAC;AAsCzC;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,UAAU,CAAC,CAyBhE;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,CAAC,CAyB3D;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CA+BjF;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,eAAe,CAAC;AAEtD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAyBvF;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,YAAY,CAAC,CAyBvB"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/cli/prompts.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,cAAc,GAAG,UAAU,GAAG,gBAAgB,CAAC;AACjF,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,IAAI,CAAC;AAsCzC;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,UAAU,CAAC,CAyBhE;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,CAAC,CAyB3D;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CA+BjF;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,eAAe,CAAC;AA2CtD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,WAAW,GAAE,MAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAc5F;AAED,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEzD;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAkCnG;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAyBvF;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,YAAY,CAAC,CAyBvB"}
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /**
3
3
  * Interactive prompts for the init command using ink
4
4
  */
5
- import { useState } from "react";
5
+ import React, { useState } from "react";
6
6
  import { render, Box, Text } from "ink";
7
7
  import SelectInput from "ink-select-input";
8
8
  function SelectPrompt({ message, items, onSelect }) {
@@ -85,6 +85,62 @@ export async function promptPullConfirm(existingFiles) {
85
85
  waitUntilExit();
86
86
  });
87
87
  }
88
+ /**
89
+ * Text input component for prompting user input
90
+ */
91
+ function TextInputPrompt({ message, placeholder, onSubmit, }) {
92
+ const [value, setValue] = React.useState("");
93
+ const handleInput = (input, key) => {
94
+ if (key.return) {
95
+ onSubmit(value.trim() || placeholder);
96
+ }
97
+ else if (key.backspace || key.delete) {
98
+ setValue((prev) => prev.slice(0, -1));
99
+ }
100
+ else if (!key.ctrl && !key.meta && input) {
101
+ setValue((prev) => prev + input);
102
+ }
103
+ };
104
+ // Use ink's useInput hook
105
+ const { useInput } = require("ink");
106
+ useInput(handleInput);
107
+ return (_jsx(Box, { flexDirection: "column", children: _jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: "? " }), _jsxs(Text, { children: [message, " "] }), _jsxs(Text, { dimColor: true, children: ["(", placeholder, "): "] }), _jsx(Text, { children: value }), _jsx(Text, { color: "gray", children: "\u2588" })] }) }));
108
+ }
109
+ /**
110
+ * Prompt user for migration name
111
+ */
112
+ export async function promptMigrationName(defaultName = "migration") {
113
+ return new Promise((resolve) => {
114
+ const { unmount, waitUntilExit } = render(_jsx(TextInputPrompt, { message: "Migration name", placeholder: defaultName, onSubmit: (value) => {
115
+ unmount();
116
+ resolve(value);
117
+ } }));
118
+ waitUntilExit();
119
+ });
120
+ }
121
+ /**
122
+ * Prompt user to confirm migration creation
123
+ */
124
+ export async function promptMigrationConfirm(migrationPath) {
125
+ return new Promise((resolve) => {
126
+ const { unmount, waitUntilExit } = render(_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "cyan", children: "? " }), _jsx(Text, { children: "Create migration at:" })] }), _jsx(Box, { marginBottom: 1, marginLeft: 2, children: _jsx(Text, { color: "yellow", children: migrationPath }) }), _jsx(SelectPrompt, { message: "", items: [
127
+ {
128
+ label: "Create migration",
129
+ value: "create",
130
+ description: "Generate the migration file",
131
+ },
132
+ {
133
+ label: "Cancel",
134
+ value: "cancel",
135
+ description: "Abort without creating migration",
136
+ },
137
+ ], onSelect: (value) => {
138
+ unmount();
139
+ resolve(value);
140
+ } })] }));
141
+ waitUntilExit();
142
+ });
143
+ }
88
144
  /**
89
145
  * Prompt user to disambiguate a potential table rename
90
146
  */
@@ -63,6 +63,16 @@ export interface ApplyPrismaMigrationsResult {
63
63
  migrationName: string;
64
64
  error: string;
65
65
  };
66
+ coherenceErrors?: MigrationCoherenceError[];
67
+ }
68
+ export interface MigrationCoherenceError {
69
+ type: "missing_from_log" | "missing_from_db" | "order_mismatch" | "checksum_mismatch";
70
+ migrationName: string;
71
+ details: string;
72
+ }
73
+ export interface MigrationCoherenceResult {
74
+ isCoherent: boolean;
75
+ errors: MigrationCoherenceError[];
66
76
  }
67
77
  export interface PreviewPrismaMigrationsResult {
68
78
  pending: Array<{
@@ -1 +1 @@
1
- {"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/migrations/prisma.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/migrations/prisma.ts"],"names":[],"mappings":"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"}
@@ -554,6 +554,70 @@ async function recordMigration(db, tableName, schema, dialect, migrationName, ch
554
554
  export function calculateChecksum(sql) {
555
555
  return crypto.createHash("sha256").update(sql).digest("hex");
556
556
  }
557
+ /**
558
+ * Validate that the database's applied migrations are coherent with the migration log.
559
+ *
560
+ * Coherence rules:
561
+ * 1. Every migration applied in the DB must exist in the migration log
562
+ * 2. Applied migrations must be a prefix of the log (no gaps)
563
+ * 3. Checksums must match for applied migrations
564
+ */
565
+ function validateMigrationCoherence(appliedMigrations, migrationLog, migrationFolders) {
566
+ const errors = [];
567
+ // Build a set of log migration names for quick lookup
568
+ const logMigrationNames = new Set(migrationLog.map((e) => e.name));
569
+ const logMigrationMap = new Map(migrationLog.map((e) => [e.name, e]));
570
+ // Check 1: Every applied migration must exist in the log
571
+ for (const [migrationName, row] of appliedMigrations) {
572
+ if (!logMigrationNames.has(migrationName)) {
573
+ errors.push({
574
+ type: "missing_from_log",
575
+ migrationName,
576
+ details: `Migration "${migrationName}" exists in database but not in migration log`,
577
+ });
578
+ }
579
+ }
580
+ // If there are migrations missing from the log, return early
581
+ // (other checks don't make sense if the log is incomplete)
582
+ if (errors.length > 0) {
583
+ return { isCoherent: false, errors };
584
+ }
585
+ // Check 2: Applied migrations should be a continuous prefix of the log
586
+ // i.e., if migration N is applied, all migrations before N in the log must also be applied
587
+ let lastAppliedIndex = -1;
588
+ for (let i = 0; i < migrationLog.length; i++) {
589
+ const logEntry = migrationLog[i];
590
+ const isApplied = appliedMigrations.has(logEntry.name);
591
+ if (isApplied) {
592
+ // Check for gaps: if this is applied, all previous should be applied
593
+ if (lastAppliedIndex !== i - 1) {
594
+ // There's a gap - find the missing migrations
595
+ for (let j = lastAppliedIndex + 1; j < i; j++) {
596
+ const missing = migrationLog[j];
597
+ errors.push({
598
+ type: "order_mismatch",
599
+ migrationName: missing.name,
600
+ details: `Migration "${missing.name}" is in the log but not applied, yet later migration "${logEntry.name}" is applied`,
601
+ });
602
+ }
603
+ }
604
+ lastAppliedIndex = i;
605
+ // Check 3: Checksum validation for applied migrations
606
+ const dbRow = appliedMigrations.get(logEntry.name);
607
+ if (dbRow.checksum !== logEntry.checksum) {
608
+ errors.push({
609
+ type: "checksum_mismatch",
610
+ migrationName: logEntry.name,
611
+ details: `Checksum mismatch for "${logEntry.name}": database has ${dbRow.checksum.slice(0, 8)}..., log has ${logEntry.checksum.slice(0, 8)}...`,
612
+ });
613
+ }
614
+ }
615
+ }
616
+ return {
617
+ isCoherent: errors.length === 0,
618
+ errors,
619
+ };
620
+ }
557
621
  /**
558
622
  * Execute raw SQL using the database driver directly
559
623
  * This bypasses Kysely for DDL statements which don't work reliably with sql.raw()
@@ -573,10 +637,19 @@ async function executeRawSql(dialect, sqlContent, options) {
573
637
  else if (dialect === "postgres") {
574
638
  const { Pool } = await import("pg");
575
639
  const pool = new Pool({ connectionString: options.connectionUrl });
640
+ const client = await pool.connect();
576
641
  try {
577
- await pool.query(sqlContent);
642
+ // PostgreSQL supports transactional DDL, so wrap migration in a transaction
643
+ await client.query("BEGIN");
644
+ await client.query(sqlContent);
645
+ await client.query("COMMIT");
646
+ }
647
+ catch (error) {
648
+ await client.query("ROLLBACK");
649
+ throw error;
578
650
  }
579
651
  finally {
652
+ client.release();
580
653
  await pool.end();
581
654
  }
582
655
  }
@@ -622,6 +695,16 @@ export async function applyPrismaMigrations(options) {
622
695
  .filter((e) => e.isDirectory() && /^\d{14}_/.test(e.name))
623
696
  .map((e) => e.name)
624
697
  .sort();
698
+ // Read migration log and validate coherence
699
+ const migrationLog = await readMigrationLog(options.migrationsFolder);
700
+ const coherence = validateMigrationCoherence(appliedMigrations, migrationLog, migrationFolders);
701
+ if (!coherence.isCoherent) {
702
+ return {
703
+ applied: [],
704
+ alreadyApplied: [],
705
+ coherenceErrors: coherence.errors,
706
+ };
707
+ }
625
708
  const result = {
626
709
  applied: [],
627
710
  alreadyApplied: [],
@@ -640,8 +723,7 @@ export async function applyPrismaMigrations(options) {
640
723
  continue; // Skip if no migration.sql
641
724
  }
642
725
  const checksum = calculateChecksum(sqlContent);
643
- // Verify checksum against migration log
644
- const migrationLog = await readMigrationLog(options.migrationsFolder);
726
+ // Verify checksum against migration log (migrationLog already read above)
645
727
  const logEntry = migrationLog.find((m) => m.name === folderName);
646
728
  if (logEntry && logEntry.checksum !== checksum) {
647
729
  result.failed = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zenstack-kit",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Drizzle-kit like CLI tooling for ZenStack schemas with Kysely support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -57,7 +57,6 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "@zenstackhq/language": "^3.1.0",
60
- "chalk": "^5.3.0",
61
60
  "ink": "^6.6.0",
62
61
  "ink-select-input": "^6.2.0",
63
62
  "jiti": "^2.4.2",
@@ -68,13 +67,10 @@
68
67
  "@types/node": "^22.0.0",
69
68
  "@types/pg": "^8.11.10",
70
69
  "@types/react": "^19.2.7",
71
- "@zenstackhq/cli": "^3.1.0",
72
70
  "@zenstackhq/orm": "^3.1.0",
73
71
  "better-sqlite3": "^12.5.0",
74
72
  "kysely": "^0.28.9",
75
73
  "pg": "^8.13.1",
76
- "prisma": "^7.2.0",
77
- "tsx": "^4.21.0",
78
74
  "typescript": "^5.9.3",
79
75
  "vitest": "^4.0.16"
80
76
  }
package/dist/cli.d.ts DELETED
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * zenstack-kit CLI - Database tooling for ZenStack schemas
4
- *
5
- * Commands:
6
- * migrate:generate Generate a new SQL migration
7
- * migrate:apply Apply pending migrations
8
- * init Initialize snapshot from existing schema
9
- * pull Introspect database and generate schema
10
- */
11
- export {};
12
- //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}