zenstack-kit 0.1.1 → 0.1.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.
Files changed (49) 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 +17 -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/package.json +1 -5
  11. package/dist/cli.d.ts +0 -12
  12. package/dist/cli.d.ts.map +0 -1
  13. package/dist/cli.js +0 -240
  14. package/dist/config-loader.d.ts +0 -6
  15. package/dist/config-loader.d.ts.map +0 -1
  16. package/dist/config-loader.js +0 -36
  17. package/dist/config.d.ts +0 -62
  18. package/dist/config.d.ts.map +0 -1
  19. package/dist/config.js +0 -44
  20. package/dist/init-prompts.d.ts +0 -13
  21. package/dist/init-prompts.d.ts.map +0 -1
  22. package/dist/init-prompts.js +0 -64
  23. package/dist/introspect.d.ts +0 -54
  24. package/dist/introspect.d.ts.map +0 -1
  25. package/dist/introspect.js +0 -75
  26. package/dist/kysely-adapter.d.ts +0 -49
  27. package/dist/kysely-adapter.d.ts.map +0 -1
  28. package/dist/kysely-adapter.js +0 -74
  29. package/dist/migrate-apply.d.ts +0 -18
  30. package/dist/migrate-apply.d.ts.map +0 -1
  31. package/dist/migrate-apply.js +0 -61
  32. package/dist/migrations.d.ts +0 -161
  33. package/dist/migrations.d.ts.map +0 -1
  34. package/dist/migrations.js +0 -620
  35. package/dist/prisma-migrations.d.ts +0 -160
  36. package/dist/prisma-migrations.d.ts.map +0 -1
  37. package/dist/prisma-migrations.js +0 -789
  38. package/dist/prompts.d.ts +0 -10
  39. package/dist/prompts.d.ts.map +0 -1
  40. package/dist/prompts.js +0 -41
  41. package/dist/pull.d.ts +0 -23
  42. package/dist/pull.d.ts.map +0 -1
  43. package/dist/pull.js +0 -424
  44. package/dist/schema-snapshot.d.ts +0 -45
  45. package/dist/schema-snapshot.d.ts.map +0 -1
  46. package/dist/schema-snapshot.js +0 -265
  47. package/dist/sql-compiler.d.ts +0 -74
  48. package/dist/sql-compiler.d.ts.map +0 -1
  49. 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,
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
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zenstack-kit",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
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"}
package/dist/cli.js DELETED
@@ -1,240 +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
- import { Command } from "commander";
12
- import chalk from "chalk";
13
- import { loadConfig } from "./config-loader.js";
14
- import { getPromptProvider } from "./prompts.js";
15
- import { pullSchema } from "./pull.js";
16
- import { createPrismaMigration, applyPrismaMigrations, hasPrismaSchemaChanges, hasSnapshot, scanMigrationFolders, writeMigrationLog, initializeSnapshot, createInitialMigration, } from "./prisma-migrations.js";
17
- import { promptSnapshotExists, promptFreshInit } from "./init-prompts.js";
18
- const program = new Command();
19
- program
20
- .name("zenstack-kit")
21
- .description("Drizzle-kit like CLI tooling for ZenStack schemas with Kysely support")
22
- .version("0.1.0");
23
- program
24
- .command("migrate:generate")
25
- .description("Generate a new SQL migration file")
26
- .option("-n, --name <name>", "Migration name")
27
- .option("-s, --schema <path>", "Path to ZenStack schema")
28
- .option("-m, --migrations <path>", "Migrations directory")
29
- .option("--dialect <dialect>", "Database dialect (sqlite, postgres, mysql)")
30
- .action(async (options) => {
31
- console.log(chalk.blue("Generating migration..."));
32
- try {
33
- const config = await loadConfig(process.cwd());
34
- const schemaPath = options.schema ?? config?.schema ?? "./schema.zmodel";
35
- const outputPath = options.migrations ?? config?.migrations?.migrationsFolder ?? "./prisma/migrations";
36
- const dialect = (options.dialect ?? config?.dialect ?? "sqlite");
37
- // Check for changes first
38
- const hasChanges = await hasPrismaSchemaChanges({
39
- schemaPath,
40
- outputPath,
41
- });
42
- if (!hasChanges) {
43
- console.log(chalk.yellow("No schema changes detected"));
44
- return;
45
- }
46
- // Get migration name
47
- const name = options.name ?? (await promptForMigrationName("migration"));
48
- // TODO: Add rename prompts and destructive change confirmation
49
- // For now, we generate without prompts
50
- const migration = await createPrismaMigration({
51
- name,
52
- schemaPath,
53
- outputPath,
54
- dialect,
55
- });
56
- if (!migration) {
57
- console.log(chalk.yellow("No schema changes detected"));
58
- return;
59
- }
60
- console.log(chalk.green(`✓ Migration created: ${migration.folderName}/migration.sql`));
61
- console.log(chalk.gray(` Path: ${migration.folderPath}`));
62
- }
63
- catch (error) {
64
- console.error(chalk.red("Error creating migration:"), error);
65
- process.exit(1);
66
- }
67
- });
68
- program
69
- .command("migrate:apply")
70
- .description("Apply pending SQL migrations")
71
- .option("-m, --migrations <path>", "Migrations directory")
72
- .option("--dialect <dialect>", "Database dialect (sqlite, postgres, mysql)")
73
- .option("--url <url>", "Database connection URL")
74
- .option("--table <name>", "Migrations table name (default: _prisma_migrations)")
75
- .option("--schema <name>", "Migrations schema (PostgreSQL only, default: public)")
76
- .action(async (options) => {
77
- console.log(chalk.blue("Applying migrations..."));
78
- try {
79
- const config = await loadConfig(process.cwd());
80
- const outputPath = options.migrations ?? config?.migrations?.migrationsFolder ?? "./prisma/migrations";
81
- const dialect = (options.dialect ?? config?.dialect ?? "sqlite");
82
- const connectionUrl = options.url ?? config?.dbCredentials?.url;
83
- const migrationsTable = options.table ?? config?.migrations?.migrationsTable ?? "_prisma_migrations";
84
- const migrationsSchema = options.schema ?? config?.migrations?.migrationsSchema ?? "public";
85
- if (dialect !== "sqlite" && !connectionUrl) {
86
- throw new Error("Database connection URL is required for non-sqlite dialects");
87
- }
88
- const databasePath = dialect === "sqlite" ? resolveSqlitePath(connectionUrl) : undefined;
89
- const result = await applyPrismaMigrations({
90
- migrationsFolder: outputPath,
91
- dialect,
92
- connectionUrl,
93
- databasePath,
94
- migrationsTable,
95
- migrationsSchema,
96
- });
97
- if (result.applied.length === 0 && !result.failed) {
98
- console.log(chalk.yellow("No pending migrations"));
99
- if (result.alreadyApplied.length > 0) {
100
- console.log(chalk.gray(` ${result.alreadyApplied.length} migration(s) already applied`));
101
- }
102
- return;
103
- }
104
- for (const item of result.applied) {
105
- console.log(chalk.green(`✓ Applied: ${item.migrationName} (${item.duration}ms)`));
106
- }
107
- if (result.failed) {
108
- console.log(chalk.red(`✗ Failed: ${result.failed.migrationName}`));
109
- console.log(chalk.red(` Error: ${result.failed.error}`));
110
- process.exit(1);
111
- }
112
- }
113
- catch (error) {
114
- console.error(chalk.red("Error applying migrations:"), error);
115
- process.exit(1);
116
- }
117
- });
118
- program
119
- .command("init")
120
- .description("Initialize snapshot from existing schema (baseline for migrations)")
121
- .option("-s, --schema <path>", "Path to ZenStack schema")
122
- .option("-m, --migrations <path>", "Migrations directory")
123
- .option("--dialect <dialect>", "Database dialect (sqlite, postgres, mysql)")
124
- .action(async (options) => {
125
- try {
126
- const config = await loadConfig(process.cwd());
127
- const schemaPath = options.schema ?? config?.schema ?? "./schema.zmodel";
128
- const outputPath = options.migrations ?? config?.migrations?.migrationsFolder ?? "./prisma/migrations";
129
- const dialect = (options.dialect ?? config?.dialect ?? "sqlite");
130
- // Scan current state
131
- const snapshotExists = await hasSnapshot(outputPath);
132
- const existingMigrations = await scanMigrationFolders(outputPath);
133
- // CASE A: Snapshot already exists
134
- if (snapshotExists) {
135
- const choice = await promptSnapshotExists();
136
- if (choice === "skip") {
137
- console.log(chalk.yellow("Skipped - no changes made"));
138
- return;
139
- }
140
- // Reinitialize: overwrite snapshot, rebuild migration log
141
- console.log(chalk.blue("Reinitializing..."));
142
- const result = await initializeSnapshot({ schemaPath, outputPath });
143
- // Rebuild migration log from existing folders
144
- const migrations = await scanMigrationFolders(outputPath);
145
- await writeMigrationLog(outputPath, migrations);
146
- console.log(chalk.green(`✓ Snapshot recreated: ${result.snapshotPath}`));
147
- console.log(chalk.green(`✓ Migration log rebuilt with ${migrations.length} migration(s)`));
148
- console.log(chalk.gray(` ${result.tableCount} table(s) captured`));
149
- return;
150
- }
151
- // CASE B: No snapshot but migrations exist (takeover mode)
152
- if (existingMigrations.length > 0) {
153
- console.log(chalk.blue("Initializing snapshot..."));
154
- console.log(chalk.yellow(`Found ${existingMigrations.length} existing migration(s) without snapshot.`));
155
- console.log(chalk.gray(" Taking over from existing migrations..."));
156
- for (const migration of existingMigrations) {
157
- console.log(chalk.gray(` ✓ ${migration.name} (${migration.checksum.slice(0, 8)}...)`));
158
- }
159
- const result = await initializeSnapshot({ schemaPath, outputPath });
160
- await writeMigrationLog(outputPath, existingMigrations);
161
- console.log(chalk.green(`✓ Snapshot created: ${result.snapshotPath}`));
162
- console.log(chalk.green(`✓ Migration log created with ${existingMigrations.length} migration(s)`));
163
- console.log(chalk.gray(` ${result.tableCount} table(s) captured`));
164
- return;
165
- }
166
- // CASE C: Fresh init (no snapshot, no migrations)
167
- const choice = await promptFreshInit();
168
- if (choice === "baseline") {
169
- // Baseline only: create snapshot, empty migration log
170
- console.log(chalk.blue("Creating baseline snapshot..."));
171
- const result = await initializeSnapshot({ schemaPath, outputPath });
172
- await writeMigrationLog(outputPath, []);
173
- console.log(chalk.green(`✓ Snapshot created: ${result.snapshotPath}`));
174
- console.log(chalk.green(`✓ Empty migration log created`));
175
- console.log(chalk.gray(` ${result.tableCount} table(s) captured`));
176
- console.log(chalk.gray(" Baselined. Future changes will generate migrations."));
177
- return;
178
- }
179
- // Create initial migration
180
- console.log(chalk.blue("Creating initial migration..."));
181
- const migration = await createInitialMigration({
182
- name: "init",
183
- schemaPath,
184
- outputPath,
185
- dialect,
186
- });
187
- console.log(chalk.green(`✓ Initial migration created: ${migration.folderName}/migration.sql`));
188
- console.log(chalk.gray(` Path: ${migration.folderPath}`));
189
- console.log(chalk.gray(" Run migrate:apply to set up the database."));
190
- }
191
- catch (error) {
192
- console.error(chalk.red("Error initializing:"), error);
193
- process.exit(1);
194
- }
195
- });
196
- program
197
- .command("pull")
198
- .description("Introspect database and generate ZenStack schema")
199
- .option("-o, --output <path>", "Output path for schema", "./schema.zmodel")
200
- .option("--dialect <dialect>", "Database dialect (sqlite, postgres, mysql)")
201
- .option("--url <url>", "Database connection URL")
202
- .action(async (options) => {
203
- console.log(chalk.blue("Pulling schema from database..."));
204
- try {
205
- const config = await loadConfig(process.cwd());
206
- const dialect = (options.dialect ?? config?.dialect ?? "sqlite");
207
- const connectionUrl = options.url ?? config?.dbCredentials?.url;
208
- if (dialect !== "sqlite" && !connectionUrl) {
209
- throw new Error("Database connection URL is required for non-sqlite dialects");
210
- }
211
- const databasePath = dialect === "sqlite" ? resolveSqlitePath(connectionUrl) : undefined;
212
- const result = await pullSchema({
213
- dialect,
214
- connectionUrl,
215
- databasePath,
216
- outputPath: options.output,
217
- });
218
- console.log(chalk.green(`✓ Schema generated: ${result.outputPath}`));
219
- console.log(chalk.gray(` ${result.tableCount} table(s) introspected`));
220
- }
221
- catch (error) {
222
- console.error(chalk.red("Error pulling schema:"), error);
223
- process.exit(1);
224
- }
225
- });
226
- program.parse();
227
- async function promptForMigrationName(defaultName) {
228
- const prompt = getPromptProvider();
229
- const answer = await prompt.question(`Migration name (${defaultName}): `);
230
- const trimmed = answer.trim();
231
- return trimmed.length > 0 ? trimmed : defaultName;
232
- }
233
- function resolveSqlitePath(url) {
234
- if (!url)
235
- return undefined;
236
- if (url.startsWith("file:")) {
237
- return url.slice("file:".length);
238
- }
239
- return url;
240
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Configuration loader for zenstack-kit
3
- */
4
- import type { ZenStackKitConfig } from "./config.js";
5
- export declare function loadConfig(cwd: string): Promise<ZenStackKitConfig | null>;
6
- //# sourceMappingURL=config-loader.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAUrD,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAuB/E"}
@@ -1,36 +0,0 @@
1
- /**
2
- * Configuration loader for zenstack-kit
3
- */
4
- import * as fs from "fs";
5
- import * as path from "path";
6
- import { createRequire } from "module";
7
- const CONFIG_FILES = [
8
- "zenstack-kit.config.ts",
9
- "zenstack-kit.config.js",
10
- "zenstack-kit.config.mjs",
11
- "zenstack-kit.config.cjs",
12
- ];
13
- export async function loadConfig(cwd) {
14
- const configPath = CONFIG_FILES.map((file) => path.join(cwd, file)).find((file) => fs.existsSync(file));
15
- if (!configPath) {
16
- return null;
17
- }
18
- const ext = path.extname(configPath);
19
- if (ext === ".cjs") {
20
- const require = createRequire(import.meta.url);
21
- const loaded = require(configPath);
22
- return (loaded.default ?? loaded);
23
- }
24
- if (ext === ".js" || ext === ".mjs") {
25
- const loaded = await import(pathToFileUrl(configPath));
26
- return (loaded.default ?? loaded);
27
- }
28
- const { default: jiti } = await import("jiti");
29
- const loader = jiti(import.meta.url, { interopDefault: true });
30
- const loaded = loader(configPath);
31
- return (loaded.default ?? loaded);
32
- }
33
- function pathToFileUrl(filePath) {
34
- const resolved = path.resolve(filePath);
35
- return new URL(`file://${resolved}`).href;
36
- }
package/dist/config.d.ts DELETED
@@ -1,62 +0,0 @@
1
- /**
2
- * Configuration utilities for zenstack-kit
3
- *
4
- * Provides a type-safe way to define configuration similar to drizzle-kit's config.
5
- */
6
- export interface ZenStackKitConfig {
7
- /** Path to ZenStack schema file */
8
- schema: string;
9
- /** Output directory for generated files */
10
- out: string;
11
- /** Database dialect */
12
- dialect?: "sqlite" | "postgres" | "mysql";
13
- /** Database connection string */
14
- dbCredentials?: {
15
- url?: string;
16
- host?: string;
17
- port?: number;
18
- user?: string;
19
- password?: string;
20
- database?: string;
21
- };
22
- /** Migration settings */
23
- migrations?: {
24
- /** Directory for migration files (default: ./prisma/migrations) */
25
- migrationsFolder?: string;
26
- /** Table name for migration metadata (default: _prisma_migrations) */
27
- migrationsTable?: string;
28
- /** Database schema for migrations table (PostgreSQL only, default: public) */
29
- migrationsSchema?: string;
30
- };
31
- /** Code generation settings */
32
- codegen?: {
33
- /** Use camelCase for column names */
34
- camelCase?: boolean;
35
- /** Generate index file */
36
- generateIndex?: boolean;
37
- };
38
- /** Enable verbose logging */
39
- verbose?: boolean;
40
- /** Enable strict mode */
41
- strict?: boolean;
42
- }
43
- /**
44
- * Define zenstack-kit configuration
45
- *
46
- * @example
47
- * ```ts
48
- * // zenstack-kit.config.ts
49
- * import { defineConfig } from "zenstack-kit";
50
- *
51
- * export default defineConfig({
52
- * schema: "./prisma/schema.zmodel",
53
- * out: "./src/db",
54
- * dialect: "postgres",
55
- * dbCredentials: {
56
- * url: process.env.DATABASE_URL,
57
- * },
58
- * });
59
- * ```
60
- */
61
- export declare function defineConfig(config: ZenStackKitConfig): ZenStackKitConfig;
62
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,uBAAuB;IACvB,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;IAC1C,iCAAiC;IACjC,aAAa,CAAC,EAAE;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,yBAAyB;IACzB,UAAU,CAAC,EAAE;QACX,mEAAmE;QACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,sEAAsE;QACtE,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,8EAA8E;QAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IACF,+BAA+B;IAC/B,OAAO,CAAC,EAAE;QACR,qCAAqC;QACrC,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,0BAA0B;QAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,CAoBzE"}