@zenstackhq/cli 3.0.0-alpha.3 → 3.0.0-alpha.30

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/dist/index.js CHANGED
@@ -1,86 +1,17 @@
1
1
  var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
- }) : x)(function(x) {
7
- if (typeof require !== "undefined") return require.apply(this, arguments);
8
- throw Error('Dynamic require of "' + x + '" is not supported');
9
- });
10
- var __commonJS = (cb, mod) => function __require2() {
11
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
12
6
  };
13
7
 
14
- // package.json
15
- var require_package = __commonJS({
16
- "package.json"(exports, module) {
17
- module.exports = {
18
- name: "@zenstackhq/cli",
19
- publisher: "zenstack",
20
- displayName: "ZenStack CLI",
21
- description: "FullStack database toolkit with built-in access control and automatic API generation.",
22
- version: "3.0.0-alpha.3",
23
- type: "module",
24
- author: {
25
- name: "ZenStack Team"
26
- },
27
- homepage: "https://zenstack.dev",
28
- license: "MIT",
29
- keywords: [
30
- "orm",
31
- "fullstack",
32
- "react",
33
- "typescript",
34
- "data modeling"
35
- ],
36
- bin: {
37
- zenstack: "bin/cli"
38
- },
39
- scripts: {
40
- build: "tsup-node",
41
- watch: "tsup-node --watch",
42
- lint: "eslint src --ext ts",
43
- test: "vitest",
44
- pack: "pnpm pack"
45
- },
46
- dependencies: {
47
- "@types/node": "^20.0.0",
48
- "@zenstackhq/language": "workspace:*",
49
- "@zenstackhq/sdk": "workspace:*",
50
- "async-exit-hook": "^2.0.1",
51
- colors: "1.4.0",
52
- commander: "^8.3.0",
53
- langium: "~3.3.0",
54
- ora: "^5.4.1",
55
- "package-manager-detector": "^1.3.0",
56
- "tiny-invariant": "^1.3.3",
57
- "ts-pattern": "^4.3.0"
58
- },
59
- peerDependencies: {
60
- prisma: "^6.0.0",
61
- typescript: "^5.0.0"
62
- },
63
- devDependencies: {
64
- "@types/async-exit-hook": "^2.0.0",
65
- "@types/better-sqlite3": "^7.6.13",
66
- "@types/semver": "^7.3.13",
67
- "@types/tmp": "^0.2.6",
68
- "@zenstackhq/runtime": "workspace:*",
69
- "@zenstackhq/testtools": "workspace:*",
70
- "better-sqlite3": "^11.8.1",
71
- tmp: "^0.2.3"
72
- }
73
- };
74
- }
75
- });
76
-
77
8
  // src/index.ts
78
9
  import { ZModelLanguageMetaData } from "@zenstackhq/language";
79
- import colors5 from "colors";
80
- import { Command, Option } from "commander";
10
+ import colors6 from "colors";
11
+ import { Command, CommanderError, Option } from "commander";
81
12
 
82
13
  // src/actions/db.ts
83
- import path2 from "node:path";
14
+ import fs2 from "fs";
84
15
 
85
16
  // src/utils/exec-utils.ts
86
17
  import { execSync as _exec } from "child_process";
@@ -105,7 +36,12 @@ function execPackage(cmd, options) {
105
36
  __name(execPackage, "execPackage");
106
37
 
107
38
  // src/actions/action-utils.ts
108
- import fs from "node:fs";
39
+ import { loadDocument } from "@zenstackhq/language";
40
+ import { isDataSource } from "@zenstackhq/language/ast";
41
+ import { PrismaSchemaGenerator } from "@zenstackhq/sdk";
42
+ import colors from "colors";
43
+ import fs from "fs";
44
+ import path from "path";
109
45
 
110
46
  // src/cli-error.ts
111
47
  var CliError = class extends Error {
@@ -115,8 +51,6 @@ var CliError = class extends Error {
115
51
  };
116
52
 
117
53
  // src/actions/action-utils.ts
118
- import { loadDocument } from "@zenstackhq/language";
119
- import colors from "colors";
120
54
  function getSchemaFile(file) {
121
55
  if (file) {
122
56
  if (!fs.existsSync(file)) {
@@ -124,6 +58,13 @@ function getSchemaFile(file) {
124
58
  }
125
59
  return file;
126
60
  }
61
+ const pkgJsonConfig = getPkgJsonConfig(process.cwd());
62
+ if (pkgJsonConfig.schema) {
63
+ if (!fs.existsSync(pkgJsonConfig.schema)) {
64
+ throw new CliError(`Schema file not found: ${pkgJsonConfig.schema}`);
65
+ }
66
+ return pkgJsonConfig.schema;
67
+ }
127
68
  if (fs.existsSync("./zenstack/schema.zmodel")) {
128
69
  return "./zenstack/schema.zmodel";
129
70
  } else if (fs.existsSync("./schema.zmodel")) {
@@ -136,12 +77,14 @@ __name(getSchemaFile, "getSchemaFile");
136
77
  async function loadSchemaDocument(schemaFile) {
137
78
  const loadResult = await loadDocument(schemaFile);
138
79
  if (!loadResult.success) {
139
- console.error(colors.red("Error loading schema:"));
140
80
  loadResult.errors.forEach((err) => {
141
81
  console.error(colors.red(err));
142
82
  });
143
- throw new CliError("Failed to load schema");
83
+ throw new CliError("Schema contains errors. See above for details.");
144
84
  }
85
+ loadResult.warnings.forEach((warn) => {
86
+ console.warn(colors.yellow(warn));
87
+ });
145
88
  return loadResult.model;
146
89
  }
147
90
  __name(loadSchemaDocument, "loadSchemaDocument");
@@ -153,90 +96,272 @@ function handleSubProcessError(err) {
153
96
  }
154
97
  }
155
98
  __name(handleSubProcessError, "handleSubProcessError");
99
+ async function generateTempPrismaSchema(zmodelPath, folder) {
100
+ const model = await loadSchemaDocument(zmodelPath);
101
+ if (!model.declarations.some(isDataSource)) {
102
+ throw new CliError("Schema must define a datasource");
103
+ }
104
+ const prismaSchema = await new PrismaSchemaGenerator(model).generate();
105
+ if (!folder) {
106
+ folder = path.dirname(zmodelPath);
107
+ }
108
+ const prismaSchemaFile = path.resolve(folder, "~schema.prisma");
109
+ fs.writeFileSync(prismaSchemaFile, prismaSchema);
110
+ return prismaSchemaFile;
111
+ }
112
+ __name(generateTempPrismaSchema, "generateTempPrismaSchema");
113
+ function getPkgJsonConfig(startPath) {
114
+ const result = {
115
+ schema: void 0,
116
+ output: void 0
117
+ };
118
+ const pkgJsonFile = findUp([
119
+ "package.json"
120
+ ], startPath, false);
121
+ if (!pkgJsonFile) {
122
+ return result;
123
+ }
124
+ let pkgJson = void 0;
125
+ try {
126
+ pkgJson = JSON.parse(fs.readFileSync(pkgJsonFile, "utf8"));
127
+ } catch {
128
+ return result;
129
+ }
130
+ if (pkgJson.zenstack && typeof pkgJson.zenstack === "object") {
131
+ result.schema = pkgJson.zenstack.schema && path.resolve(path.dirname(pkgJsonFile), pkgJson.zenstack.schema);
132
+ result.output = pkgJson.zenstack.output && path.resolve(path.dirname(pkgJsonFile), pkgJson.zenstack.output);
133
+ }
134
+ return result;
135
+ }
136
+ __name(getPkgJsonConfig, "getPkgJsonConfig");
137
+ function findUp(names, cwd = process.cwd(), multiple = false, result = []) {
138
+ if (!names.some((name) => !!name)) {
139
+ return void 0;
140
+ }
141
+ const target = names.find((name) => fs.existsSync(path.join(cwd, name)));
142
+ if (multiple === false && target) {
143
+ return path.join(cwd, target);
144
+ }
145
+ if (target) {
146
+ result.push(path.join(cwd, target));
147
+ }
148
+ const up = path.resolve(cwd, "..");
149
+ if (up === cwd) {
150
+ return multiple && result.length > 0 ? result : void 0;
151
+ }
152
+ return findUp(names, up, multiple, result);
153
+ }
154
+ __name(findUp, "findUp");
155
+
156
+ // src/actions/db.ts
157
+ async function run(command, options) {
158
+ switch (command) {
159
+ case "push":
160
+ await runPush(options);
161
+ break;
162
+ }
163
+ }
164
+ __name(run, "run");
165
+ async function runPush(options) {
166
+ const schemaFile = getSchemaFile(options.schema);
167
+ const prismaSchemaFile = await generateTempPrismaSchema(schemaFile);
168
+ try {
169
+ const cmd = [
170
+ "prisma db push",
171
+ ` --schema "${prismaSchemaFile}"`,
172
+ options.acceptDataLoss ? " --accept-data-loss" : "",
173
+ options.forceReset ? " --force-reset" : "",
174
+ " --skip-generate"
175
+ ].join("");
176
+ try {
177
+ await execPackage(cmd);
178
+ } catch (err) {
179
+ handleSubProcessError(err);
180
+ }
181
+ } finally {
182
+ if (fs2.existsSync(prismaSchemaFile)) {
183
+ fs2.unlinkSync(prismaSchemaFile);
184
+ }
185
+ }
186
+ }
187
+ __name(runPush, "runPush");
156
188
 
157
189
  // src/actions/generate.ts
190
+ import { invariant } from "@zenstackhq/common-helpers";
158
191
  import { isPlugin } from "@zenstackhq/language/ast";
159
- import { PrismaSchemaGenerator, TsSchemaGenerator } from "@zenstackhq/sdk";
192
+ import { getLiteral, getLiteralArray } from "@zenstackhq/language/utils";
160
193
  import colors2 from "colors";
161
- import fs2 from "node:fs";
162
- import path from "node:path";
163
- import invariant from "tiny-invariant";
164
- async function run(options) {
194
+ import path4 from "path";
195
+ import ora from "ora";
196
+
197
+ // src/plugins/index.ts
198
+ var plugins_exports = {};
199
+ __export(plugins_exports, {
200
+ prisma: () => prisma_default,
201
+ typescript: () => typescript_default
202
+ });
203
+
204
+ // src/plugins/prisma.ts
205
+ import { PrismaSchemaGenerator as PrismaSchemaGenerator2 } from "@zenstackhq/sdk";
206
+ import fs3 from "fs";
207
+ import path2 from "path";
208
+ var plugin = {
209
+ name: "Prisma Schema Generator",
210
+ statusText: "Generating Prisma schema",
211
+ async generate({ model, schemaFile, defaultOutputPath, pluginOptions }) {
212
+ let outFile = path2.join(defaultOutputPath, "schema.prisma");
213
+ if (typeof pluginOptions["output"] === "string") {
214
+ outFile = path2.resolve(path2.dirname(schemaFile), pluginOptions["output"]);
215
+ if (!fs3.existsSync(path2.dirname(outFile))) {
216
+ fs3.mkdirSync(path2.dirname(outFile), {
217
+ recursive: true
218
+ });
219
+ }
220
+ }
221
+ const prismaSchema = await new PrismaSchemaGenerator2(model).generate();
222
+ fs3.writeFileSync(outFile, prismaSchema);
223
+ }
224
+ };
225
+ var prisma_default = plugin;
226
+
227
+ // src/plugins/typescript.ts
228
+ import { TsSchemaGenerator } from "@zenstackhq/sdk";
229
+ import fs4 from "fs";
230
+ import path3 from "path";
231
+ var plugin2 = {
232
+ name: "TypeScript Schema Generator",
233
+ statusText: "Generating TypeScript schema",
234
+ async generate({ model, defaultOutputPath, pluginOptions }) {
235
+ let outDir = defaultOutputPath;
236
+ if (typeof pluginOptions["output"] === "string") {
237
+ outDir = path3.resolve(defaultOutputPath, pluginOptions["output"]);
238
+ if (!fs4.existsSync(outDir)) {
239
+ fs4.mkdirSync(outDir, {
240
+ recursive: true
241
+ });
242
+ }
243
+ }
244
+ await new TsSchemaGenerator().generate(model, outDir);
245
+ }
246
+ };
247
+ var typescript_default = plugin2;
248
+
249
+ // src/actions/generate.ts
250
+ async function run2(options) {
251
+ const start = Date.now();
165
252
  const schemaFile = getSchemaFile(options.schema);
166
253
  const model = await loadSchemaDocument(schemaFile);
167
- const outputPath = options.output ?? path.dirname(schemaFile);
168
- const tsSchemaFile = path.join(outputPath, "schema.ts");
169
- await new TsSchemaGenerator().generate(schemaFile, [], tsSchemaFile);
170
- await runPlugins(model, outputPath, tsSchemaFile);
171
- const prismaSchema = await new PrismaSchemaGenerator(model).generate();
172
- fs2.writeFileSync(path.join(outputPath, "schema.prisma"), prismaSchema);
173
- if (!options.silent) {
174
- console.log(colors2.green("Generation completed successfully."));
175
- console.log(`You can now create a ZenStack client with it.
254
+ const outputPath = getOutputPath(options, schemaFile);
255
+ await runPlugins(schemaFile, model, outputPath);
256
+ console.log(colors2.green(`Generation completed successfully in ${Date.now() - start}ms.
257
+ `));
258
+ console.log(`You can now create a ZenStack client with it.
176
259
 
177
260
  \`\`\`ts
178
261
  import { ZenStackClient } from '@zenstackhq/runtime';
179
262
  import { schema } from '${outputPath}/schema';
180
263
 
181
264
  const client = new ZenStackClient(schema, {
182
- dialectConfig: { ... }
265
+ dialect: { ... }
183
266
  });
184
- \`\`\`
185
- `);
267
+ \`\`\``);
268
+ }
269
+ __name(run2, "run");
270
+ function getOutputPath(options, schemaFile) {
271
+ if (options.output) {
272
+ return options.output;
273
+ }
274
+ const pkgJsonConfig = getPkgJsonConfig(process.cwd());
275
+ if (pkgJsonConfig.output) {
276
+ return pkgJsonConfig.output;
277
+ } else {
278
+ return path4.dirname(schemaFile);
186
279
  }
187
280
  }
188
- __name(run, "run");
189
- async function runPlugins(model, outputPath, tsSchemaFile) {
281
+ __name(getOutputPath, "getOutputPath");
282
+ async function runPlugins(schemaFile, model, outputPath) {
190
283
  const plugins = model.declarations.filter(isPlugin);
191
- for (const plugin of plugins) {
192
- const providerField = plugin.fields.find((f) => f.name === "provider");
193
- invariant(providerField, `Plugin ${plugin.name} does not have a provider field`);
194
- const provider = providerField.value.value;
195
- let useProvider = provider;
196
- if (useProvider.startsWith("@core/")) {
197
- useProvider = `@zenstackhq/runtime/plugins/${useProvider.slice(6)}`;
284
+ const processedPlugins = [];
285
+ for (const plugin3 of plugins) {
286
+ const provider = getPluginProvider(plugin3);
287
+ let cliPlugin;
288
+ if (provider.startsWith("@core/")) {
289
+ cliPlugin = plugins_exports[provider.slice("@core/".length)];
290
+ if (!cliPlugin) {
291
+ throw new CliError(`Unknown core plugin: ${provider}`);
292
+ }
293
+ } else {
294
+ let moduleSpec = provider;
295
+ if (moduleSpec.startsWith(".")) {
296
+ moduleSpec = path4.resolve(path4.dirname(schemaFile), moduleSpec);
297
+ }
298
+ try {
299
+ cliPlugin = (await import(moduleSpec)).default;
300
+ } catch (error) {
301
+ throw new CliError(`Failed to load plugin ${provider}: ${error}`);
302
+ }
198
303
  }
199
- const generator = (await import(useProvider)).default;
200
- console.log("Running generator:", provider);
201
- await generator({
202
- model,
203
- outputPath,
204
- tsSchemaFile
304
+ processedPlugins.push({
305
+ cliPlugin,
306
+ pluginOptions: getPluginOptions(plugin3)
205
307
  });
206
308
  }
207
- }
208
- __name(runPlugins, "runPlugins");
209
-
210
- // src/actions/db.ts
211
- async function run2(command, options) {
212
- const schemaFile = getSchemaFile(options.schema);
213
- await run({
214
- schema: schemaFile,
215
- silent: true
309
+ const defaultPlugins = [
310
+ typescript_default
311
+ ].reverse();
312
+ defaultPlugins.forEach((d) => {
313
+ if (!processedPlugins.some((p) => p.cliPlugin === d)) {
314
+ processedPlugins.push({
315
+ cliPlugin: d,
316
+ pluginOptions: {}
317
+ });
318
+ }
216
319
  });
217
- const prismaSchemaFile = path2.join(path2.dirname(schemaFile), "schema.prisma");
218
- switch (command) {
219
- case "push":
220
- await runPush(prismaSchemaFile, options);
221
- break;
320
+ for (const { cliPlugin, pluginOptions } of processedPlugins) {
321
+ invariant(typeof cliPlugin.generate === "function", `Plugin ${cliPlugin.name} does not have a generate function`);
322
+ const spinner = ora(cliPlugin.statusText ?? `Running plugin ${cliPlugin.name}`).start();
323
+ try {
324
+ await cliPlugin.generate({
325
+ schemaFile,
326
+ model,
327
+ defaultOutputPath: outputPath,
328
+ pluginOptions
329
+ });
330
+ spinner.succeed();
331
+ } catch (err) {
332
+ spinner.fail();
333
+ console.error(err);
334
+ }
222
335
  }
223
336
  }
224
- __name(run2, "run");
225
- async function runPush(prismaSchemaFile, options) {
226
- const cmd = `prisma db push --schema "${prismaSchemaFile}"${options.acceptDataLoss ? " --accept-data-loss" : ""}${options.forceReset ? " --force-reset" : ""} --skip-generate`;
227
- try {
228
- await execPackage(cmd, {
229
- stdio: "inherit"
230
- });
231
- } catch (err) {
232
- handleSubProcessError(err);
337
+ __name(runPlugins, "runPlugins");
338
+ function getPluginProvider(plugin3) {
339
+ const providerField = plugin3.fields.find((f) => f.name === "provider");
340
+ invariant(providerField, `Plugin ${plugin3.name} does not have a provider field`);
341
+ const provider = providerField.value.value;
342
+ return provider;
343
+ }
344
+ __name(getPluginProvider, "getPluginProvider");
345
+ function getPluginOptions(plugin3) {
346
+ const result = {};
347
+ for (const field of plugin3.fields) {
348
+ if (field.name === "provider") {
349
+ continue;
350
+ }
351
+ const value = getLiteral(field.value) ?? getLiteralArray(field.value);
352
+ if (value === void 0) {
353
+ console.warn(`Plugin "${plugin3.name}" option "${field.name}" has unsupported value, skipping`);
354
+ continue;
355
+ }
356
+ result[field.name] = value;
233
357
  }
358
+ return result;
234
359
  }
235
- __name(runPush, "runPush");
360
+ __name(getPluginOptions, "getPluginOptions");
236
361
 
237
362
  // src/actions/info.ts
238
363
  import colors3 from "colors";
239
- import path3 from "node:path";
364
+ import path5 from "path";
240
365
  async function run3(projectPath) {
241
366
  const packages = await getZenStackPackages(projectPath);
242
367
  if (!packages) {
@@ -258,14 +383,14 @@ async function run3(projectPath) {
258
383
  __name(run3, "run");
259
384
  async function getZenStackPackages(projectPath) {
260
385
  let pkgJson;
261
- const resolvedPath = path3.resolve(projectPath);
386
+ const resolvedPath = path5.resolve(projectPath);
262
387
  try {
263
- pkgJson = (await import(path3.join(resolvedPath, "package.json"), {
388
+ pkgJson = (await import(path5.join(resolvedPath, "package.json"), {
264
389
  with: {
265
390
  type: "json"
266
391
  }
267
392
  })).default;
268
- } catch (err) {
393
+ } catch {
269
394
  return [];
270
395
  }
271
396
  const packages = Array.from(new Set([
@@ -296,9 +421,9 @@ __name(getZenStackPackages, "getZenStackPackages");
296
421
 
297
422
  // src/actions/init.ts
298
423
  import colors4 from "colors";
299
- import fs3 from "node:fs";
300
- import path4 from "node:path";
301
- import ora from "ora";
424
+ import fs5 from "fs";
425
+ import path6 from "path";
426
+ import ora2 from "ora";
302
427
  import { detect, resolveCommand } from "package-manager-detector";
303
428
 
304
429
  // src/actions/templates.ts
@@ -360,7 +485,7 @@ async function run4(projectPath) {
360
485
  if (!resolved) {
361
486
  throw new CliError(`Unable to determine how to install package "${pkg.name}". Please install it manually.`);
362
487
  }
363
- const spinner = ora(`Installing "${pkg.name}"`).start();
488
+ const spinner = ora2(`Installing "${pkg.name}"`).start();
364
489
  try {
365
490
  execSync(`${resolved.command} ${resolved.args.join(" ")}`, {
366
491
  cwd: projectPath
@@ -372,11 +497,11 @@ async function run4(projectPath) {
372
497
  }
373
498
  }
374
499
  const generationFolder = "zenstack";
375
- if (!fs3.existsSync(path4.join(projectPath, generationFolder))) {
376
- fs3.mkdirSync(path4.join(projectPath, generationFolder));
500
+ if (!fs5.existsSync(path6.join(projectPath, generationFolder))) {
501
+ fs5.mkdirSync(path6.join(projectPath, generationFolder));
377
502
  }
378
- if (!fs3.existsSync(path4.join(projectPath, generationFolder, "schema.zmodel"))) {
379
- fs3.writeFileSync(path4.join(projectPath, generationFolder, "schema.zmodel"), STARTER_ZMODEL);
503
+ if (!fs5.existsSync(path6.join(projectPath, generationFolder, "schema.zmodel"))) {
504
+ fs5.writeFileSync(path6.join(projectPath, generationFolder, "schema.zmodel"), STARTER_ZMODEL);
380
505
  } else {
381
506
  console.log(colors4.yellow("Schema file already exists. Skipping generation of sample."));
382
507
  }
@@ -387,35 +512,47 @@ async function run4(projectPath) {
387
512
  __name(run4, "run");
388
513
 
389
514
  // src/actions/migrate.ts
390
- import path5 from "node:path";
515
+ import fs6 from "fs";
516
+ import path7 from "path";
391
517
  async function run5(command, options) {
392
518
  const schemaFile = getSchemaFile(options.schema);
393
- await run({
394
- schema: schemaFile,
395
- silent: true
396
- });
397
- const prismaSchemaFile = path5.join(path5.dirname(schemaFile), "schema.prisma");
398
- switch (command) {
399
- case "dev":
400
- await runDev(prismaSchemaFile, options);
401
- break;
402
- case "reset":
403
- await runReset(prismaSchemaFile, options);
404
- break;
405
- case "deploy":
406
- await runDeploy(prismaSchemaFile, options);
407
- break;
408
- case "status":
409
- await runStatus(prismaSchemaFile, options);
410
- break;
519
+ const prismaSchemaDir = options.migrations ? path7.dirname(options.migrations) : void 0;
520
+ const prismaSchemaFile = await generateTempPrismaSchema(schemaFile, prismaSchemaDir);
521
+ try {
522
+ switch (command) {
523
+ case "dev":
524
+ await runDev(prismaSchemaFile, options);
525
+ break;
526
+ case "reset":
527
+ await runReset(prismaSchemaFile, options);
528
+ break;
529
+ case "deploy":
530
+ await runDeploy(prismaSchemaFile, options);
531
+ break;
532
+ case "status":
533
+ await runStatus(prismaSchemaFile, options);
534
+ break;
535
+ case "resolve":
536
+ await runResolve(prismaSchemaFile, options);
537
+ break;
538
+ }
539
+ } finally {
540
+ if (fs6.existsSync(prismaSchemaFile)) {
541
+ fs6.unlinkSync(prismaSchemaFile);
542
+ }
411
543
  }
412
544
  }
413
545
  __name(run5, "run");
414
- async function runDev(prismaSchemaFile, _options) {
546
+ async function runDev(prismaSchemaFile, options) {
415
547
  try {
416
- await execPackage(`prisma migrate dev --schema "${prismaSchemaFile}" --skip-generate`, {
417
- stdio: "inherit"
418
- });
548
+ const cmd = [
549
+ "prisma migrate dev",
550
+ ` --schema "${prismaSchemaFile}"`,
551
+ " --skip-generate",
552
+ options.name ? ` --name ${options.name}` : "",
553
+ options.createOnly ? " --create-only" : ""
554
+ ].join("");
555
+ await execPackage(cmd);
419
556
  } catch (err) {
420
557
  handleSubProcessError2(err);
421
558
  }
@@ -423,9 +560,12 @@ async function runDev(prismaSchemaFile, _options) {
423
560
  __name(runDev, "runDev");
424
561
  async function runReset(prismaSchemaFile, options) {
425
562
  try {
426
- await execPackage(`prisma migrate reset --schema "${prismaSchemaFile}"${options.force ? " --force" : ""}`, {
427
- stdio: "inherit"
428
- });
563
+ const cmd = [
564
+ "prisma migrate reset",
565
+ ` --schema "${prismaSchemaFile}"`,
566
+ options.force ? " --force" : ""
567
+ ].join("");
568
+ await execPackage(cmd);
429
569
  } catch (err) {
430
570
  handleSubProcessError2(err);
431
571
  }
@@ -433,9 +573,11 @@ async function runReset(prismaSchemaFile, options) {
433
573
  __name(runReset, "runReset");
434
574
  async function runDeploy(prismaSchemaFile, _options) {
435
575
  try {
436
- await execPackage(`prisma migrate deploy --schema "${prismaSchemaFile}"`, {
437
- stdio: "inherit"
438
- });
576
+ const cmd = [
577
+ "prisma migrate deploy",
578
+ ` --schema "${prismaSchemaFile}"`
579
+ ].join("");
580
+ await execPackage(cmd);
439
581
  } catch (err) {
440
582
  handleSubProcessError2(err);
441
583
  }
@@ -443,14 +585,29 @@ async function runDeploy(prismaSchemaFile, _options) {
443
585
  __name(runDeploy, "runDeploy");
444
586
  async function runStatus(prismaSchemaFile, _options) {
445
587
  try {
446
- await execPackage(`prisma migrate status --schema "${prismaSchemaFile}"`, {
447
- stdio: "inherit"
448
- });
588
+ await execPackage(`prisma migrate status --schema "${prismaSchemaFile}"`);
449
589
  } catch (err) {
450
590
  handleSubProcessError2(err);
451
591
  }
452
592
  }
453
593
  __name(runStatus, "runStatus");
594
+ async function runResolve(prismaSchemaFile, options) {
595
+ if (!options.applied && !options.rolledBack) {
596
+ throw new CliError("Either --applied or --rolled-back option must be provided");
597
+ }
598
+ try {
599
+ const cmd = [
600
+ "prisma migrate resolve",
601
+ ` --schema "${prismaSchemaFile}"`,
602
+ options.applied ? ` --applied ${options.applied}` : "",
603
+ options.rolledBack ? ` --rolled-back ${options.rolledBack}` : ""
604
+ ].join("");
605
+ await execPackage(cmd);
606
+ } catch (err) {
607
+ handleSubProcessError2(err);
608
+ }
609
+ }
610
+ __name(runResolve, "runResolve");
454
611
  function handleSubProcessError2(err) {
455
612
  if (err instanceof Error && "status" in err && typeof err.status === "number") {
456
613
  process.exit(err.status);
@@ -460,29 +617,43 @@ function handleSubProcessError2(err) {
460
617
  }
461
618
  __name(handleSubProcessError2, "handleSubProcessError");
462
619
 
620
+ // src/actions/check.ts
621
+ import colors5 from "colors";
622
+ async function run6(options) {
623
+ const schemaFile = getSchemaFile(options.schema);
624
+ try {
625
+ await loadSchemaDocument(schemaFile);
626
+ console.log(colors5.green("\u2713 Schema validation completed successfully."));
627
+ } catch (error) {
628
+ console.error(colors5.red("\u2717 Schema validation failed."));
629
+ throw error;
630
+ }
631
+ }
632
+ __name(run6, "run");
633
+
463
634
  // src/utils/version-utils.ts
635
+ import fs7 from "fs";
636
+ import path8 from "path";
637
+ import { fileURLToPath } from "url";
464
638
  function getVersion() {
465
639
  try {
466
- return __require("../package.json").version;
640
+ const _dirname = typeof __dirname !== "undefined" ? __dirname : path8.dirname(fileURLToPath(import.meta.url));
641
+ return JSON.parse(fs7.readFileSync(path8.join(_dirname, "../package.json"), "utf8")).version;
467
642
  } catch {
468
- try {
469
- return require_package().version;
470
- } catch {
471
- return void 0;
472
- }
643
+ return void 0;
473
644
  }
474
645
  }
475
646
  __name(getVersion, "getVersion");
476
647
 
477
648
  // src/index.ts
478
649
  var generateAction = /* @__PURE__ */ __name(async (options) => {
479
- await run(options);
650
+ await run2(options);
480
651
  }, "generateAction");
481
652
  var migrateAction = /* @__PURE__ */ __name(async (command, options) => {
482
653
  await run5(command, options);
483
654
  }, "migrateAction");
484
655
  var dbAction = /* @__PURE__ */ __name(async (command, options) => {
485
- await run2(command, options);
656
+ await run(command, options);
486
657
  }, "dbAction");
487
658
  var infoAction = /* @__PURE__ */ __name(async (projectPath) => {
488
659
  await run3(projectPath);
@@ -490,29 +661,46 @@ var infoAction = /* @__PURE__ */ __name(async (projectPath) => {
490
661
  var initAction = /* @__PURE__ */ __name(async (projectPath) => {
491
662
  await run4(projectPath);
492
663
  }, "initAction");
664
+ var checkAction = /* @__PURE__ */ __name(async (options) => {
665
+ await run6(options);
666
+ }, "checkAction");
493
667
  function createProgram() {
494
668
  const program2 = new Command("zenstack");
495
669
  program2.version(getVersion(), "-v --version", "display CLI version");
496
670
  const schemaExtensions = ZModelLanguageMetaData.fileExtensions.join(", ");
497
- program2.description(`${colors5.bold.blue("\u03B6")} ZenStack is a Prisma power pack for building full-stack apps.
671
+ program2.description(`${colors6.bold.blue("\u03B6")} ZenStack is the data layer for modern TypeScript apps.
498
672
 
499
673
  Documentation: https://zenstack.dev.`).showHelpAfterError().showSuggestionAfterError();
500
- const schemaOption = new Option("--schema <file>", `schema file (with extension ${schemaExtensions}). Defaults to "schema.zmodel" unless specified in package.json.`);
501
- program2.command("generate").description("Run code generation.").addOption(schemaOption).addOption(new Option("-o, --output <path>", "default output directory for core plugins")).action(generateAction);
502
- const migrateCommand = program2.command("migrate").description("Update the database schema with migrations.");
503
- migrateCommand.command("dev").addOption(schemaOption).addOption(new Option("-n, --name <name>", "migration name")).addOption(new Option("--create-only", "only create migration, do not apply")).description("Create a migration from changes in schema and apply it to the database.").action((options) => migrateAction("dev", options));
504
- migrateCommand.command("reset").addOption(schemaOption).addOption(new Option("--force", "skip the confirmation prompt")).description("Reset your database and apply all migrations, all data will be lost.").action((options) => migrateAction("reset", options));
505
- migrateCommand.command("deploy").addOption(schemaOption).description("Deploy your pending migrations to your production/staging database.").action((options) => migrateAction("deploy", options));
506
- migrateCommand.command("status").addOption(schemaOption).description("check the status of your database migrations.").action((options) => migrateAction("status", options));
674
+ const schemaOption = new Option("--schema <file>", `schema file (with extension ${schemaExtensions}). Defaults to "zenstack/schema.zmodel" unless specified in package.json.`);
675
+ program2.command("generate").description("Run code generation plugins.").addOption(schemaOption).addOption(new Option("-o, --output <path>", "default output directory for code generation")).action(generateAction);
676
+ const migrateCommand = program2.command("migrate").description("Run database schema migration related tasks.");
677
+ const migrationsOption = new Option("--migrations <path>", 'path that contains the "migrations" directory');
678
+ migrateCommand.command("dev").addOption(schemaOption).addOption(new Option("-n, --name <name>", "migration name")).addOption(new Option("--create-only", "only create migration, do not apply")).addOption(migrationsOption).description("Create a migration from changes in schema and apply it to the database.").action((options) => migrateAction("dev", options));
679
+ migrateCommand.command("reset").addOption(schemaOption).addOption(new Option("--force", "skip the confirmation prompt")).addOption(migrationsOption).description("Reset your database and apply all migrations, all data will be lost.").action((options) => migrateAction("reset", options));
680
+ migrateCommand.command("deploy").addOption(schemaOption).addOption(migrationsOption).description("Deploy your pending migrations to your production/staging database.").action((options) => migrateAction("deploy", options));
681
+ migrateCommand.command("status").addOption(schemaOption).addOption(migrationsOption).description("Check the status of your database migrations.").action((options) => migrateAction("status", options));
682
+ migrateCommand.command("resolve").addOption(schemaOption).addOption(migrationsOption).addOption(new Option("--applied <migration>", "record a specific migration as applied")).addOption(new Option("--rolled-back <migration>", "record a specific migration as rolled back")).description("Resolve issues with database migrations in deployment databases.").action((options) => migrateAction("resolve", options));
507
683
  const dbCommand = program2.command("db").description("Manage your database schema during development.");
508
- dbCommand.command("push").description("Push the state from your schema to your database").addOption(schemaOption).addOption(new Option("--accept-data-loss", "ignore data loss warnings")).addOption(new Option("--force-reset", "force a reset of the database before push")).action((options) => dbAction("push", options));
509
- program2.command("info").description("Get information of installed ZenStack and related packages.").argument("[path]", "project path", ".").action(infoAction);
684
+ dbCommand.command("push").description("Push the state from your schema to your database.").addOption(schemaOption).addOption(new Option("--accept-data-loss", "ignore data loss warnings")).addOption(new Option("--force-reset", "force a reset of the database before push")).action((options) => dbAction("push", options));
685
+ program2.command("info").description("Get information of installed ZenStack packages.").argument("[path]", "project path", ".").action(infoAction);
510
686
  program2.command("init").description("Initialize an existing project for ZenStack.").argument("[path]", "project path", ".").action(initAction);
687
+ program2.command("check").description("Check a ZModel schema for syntax or semantic errors.").addOption(schemaOption).action(checkAction);
511
688
  return program2;
512
689
  }
513
690
  __name(createProgram, "createProgram");
514
691
  var program = createProgram();
515
- program.parse(process.argv);
692
+ program.parseAsync().catch((err) => {
693
+ if (err instanceof CliError) {
694
+ console.error(colors6.red(err.message));
695
+ process.exit(1);
696
+ } else if (err instanceof CommanderError) {
697
+ process.exit(err.exitCode);
698
+ } else {
699
+ console.error(colors6.red("An unexpected error occurred:"));
700
+ console.error(err);
701
+ process.exit(1);
702
+ }
703
+ });
516
704
  export {
517
705
  createProgram
518
706
  };