@zenstackhq/cli 3.0.0-beta.9 → 3.1.0

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,5 +1,11 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
+ }) : x)(function(x) {
6
+ if (typeof require !== "undefined") return require.apply(this, arguments);
7
+ throw Error('Dynamic require of "' + x + '" is not supported');
8
+ });
3
9
  var __export = (target, all) => {
4
10
  for (var name in all)
5
11
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -7,33 +13,11 @@ var __export = (target, all) => {
7
13
 
8
14
  // src/index.ts
9
15
  import { ZModelLanguageMetaData } from "@zenstackhq/language";
10
- import colors7 from "colors";
16
+ import colors9 from "colors";
11
17
  import { Command, CommanderError, Option } from "commander";
12
18
 
13
- // src/actions/db.ts
14
- import fs2 from "fs";
15
-
16
- // src/utils/exec-utils.ts
17
- import { execSync as _exec } from "child_process";
18
- function execSync(cmd, options) {
19
- const { env: env2, ...restOptions } = options ?? {};
20
- const mergedEnv = env2 ? {
21
- ...process.env,
22
- ...env2
23
- } : void 0;
24
- _exec(cmd, {
25
- encoding: "utf-8",
26
- stdio: options?.stdio ?? "inherit",
27
- env: mergedEnv,
28
- ...restOptions
29
- });
30
- }
31
- __name(execSync, "execSync");
32
- function execPackage(cmd, options) {
33
- const packageManager = process?.versions?.["bun"] ? "bunx" : "npx";
34
- execSync(`${packageManager} ${cmd}`, options);
35
- }
36
- __name(execPackage, "execPackage");
19
+ // src/actions/check.ts
20
+ import colors2 from "colors";
37
21
 
38
22
  // src/actions/action-utils.ts
39
23
  import { loadDocument } from "@zenstackhq/language";
@@ -63,14 +47,22 @@ function getSchemaFile(file) {
63
47
  if (!fs.existsSync(pkgJsonConfig.schema)) {
64
48
  throw new CliError(`Schema file not found: ${pkgJsonConfig.schema}`);
65
49
  }
66
- return pkgJsonConfig.schema;
50
+ if (fs.statSync(pkgJsonConfig.schema).isDirectory()) {
51
+ const schemaPath = path.join(pkgJsonConfig.schema, "schema.zmodel");
52
+ if (!fs.existsSync(schemaPath)) {
53
+ throw new CliError(`Schema file not found: ${schemaPath}`);
54
+ }
55
+ return schemaPath;
56
+ } else {
57
+ return pkgJsonConfig.schema;
58
+ }
67
59
  }
68
- if (fs.existsSync("./zenstack/schema.zmodel")) {
69
- return "./zenstack/schema.zmodel";
70
- } else if (fs.existsSync("./schema.zmodel")) {
60
+ if (fs.existsSync("./schema.zmodel")) {
71
61
  return "./schema.zmodel";
62
+ } else if (fs.existsSync("./zenstack/schema.zmodel")) {
63
+ return "./zenstack/schema.zmodel";
72
64
  } else {
73
- throw new CliError('Schema file not found in default locations ("./zenstack/schema.zmodel" or "./schema.zmodel").');
65
+ throw new CliError('Schema file not found in default locations ("./schema.zmodel" or "./zenstack/schema.zmodel").');
74
66
  }
75
67
  }
76
68
  __name(getSchemaFile, "getSchemaFile");
@@ -113,7 +105,8 @@ __name(generateTempPrismaSchema, "generateTempPrismaSchema");
113
105
  function getPkgJsonConfig(startPath) {
114
106
  const result = {
115
107
  schema: void 0,
116
- output: void 0
108
+ output: void 0,
109
+ seed: void 0
117
110
  };
118
111
  const pkgJsonFile = findUp([
119
112
  "package.json"
@@ -128,8 +121,9 @@ function getPkgJsonConfig(startPath) {
128
121
  return result;
129
122
  }
130
123
  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);
124
+ result.schema = pkgJson.zenstack.schema && typeof pkgJson.zenstack.schema === "string" ? path.resolve(path.dirname(pkgJsonFile), pkgJson.zenstack.schema) : void 0;
125
+ result.output = pkgJson.zenstack.output && typeof pkgJson.zenstack.output === "string" ? path.resolve(path.dirname(pkgJsonFile), pkgJson.zenstack.output) : void 0;
126
+ result.seed = typeof pkgJson.zenstack.seed === "string" && pkgJson.zenstack.seed ? pkgJson.zenstack.seed : void 0;
133
127
  }
134
128
  return result;
135
129
  }
@@ -152,29 +146,101 @@ function findUp(names, cwd = process.cwd(), multiple = false, result = []) {
152
146
  return findUp(names, up, multiple, result);
153
147
  }
154
148
  __name(findUp, "findUp");
149
+ async function requireDataSourceUrl(schemaFile) {
150
+ const zmodel = await loadSchemaDocument(schemaFile);
151
+ const dataSource = zmodel.declarations.find(isDataSource);
152
+ if (!dataSource?.fields.some((f) => f.name === "url")) {
153
+ throw new CliError(`The schema's "datasource" must have a "url" field to use this command.`);
154
+ }
155
+ }
156
+ __name(requireDataSourceUrl, "requireDataSourceUrl");
157
+
158
+ // src/actions/check.ts
159
+ async function run(options) {
160
+ const schemaFile = getSchemaFile(options.schema);
161
+ try {
162
+ await loadSchemaDocument(schemaFile);
163
+ console.log(colors2.green("\u2713 Schema validation completed successfully."));
164
+ } catch (error) {
165
+ console.error(colors2.red("\u2717 Schema validation failed."));
166
+ throw error;
167
+ }
168
+ }
169
+ __name(run, "run");
170
+
171
+ // src/actions/db.ts
172
+ import fs2 from "fs";
173
+
174
+ // src/utils/exec-utils.ts
175
+ import { execSync as _exec } from "child_process";
176
+ import { fileURLToPath } from "url";
177
+ function execSync(cmd, options) {
178
+ const { env: env2, ...restOptions } = options ?? {};
179
+ const mergedEnv = env2 ? {
180
+ ...process.env,
181
+ ...env2
182
+ } : void 0;
183
+ _exec(cmd, {
184
+ encoding: "utf-8",
185
+ stdio: options?.stdio ?? "inherit",
186
+ env: mergedEnv,
187
+ ...restOptions
188
+ });
189
+ }
190
+ __name(execSync, "execSync");
191
+ function execPackage(cmd, options) {
192
+ const packageManager = process?.versions?.["bun"] ? "bunx" : "npx";
193
+ execSync(`${packageManager} ${cmd}`, options);
194
+ }
195
+ __name(execPackage, "execPackage");
196
+ function execPrisma(args, options) {
197
+ let prismaPath;
198
+ try {
199
+ if (typeof import.meta.resolve === "function") {
200
+ prismaPath = fileURLToPath(import.meta.resolve("prisma/build/index.js"));
201
+ } else {
202
+ prismaPath = __require.resolve("prisma/build/index.js");
203
+ }
204
+ } catch {
205
+ }
206
+ const _options = {
207
+ ...options,
208
+ env: {
209
+ ...options?.env,
210
+ PRISMA_HIDE_UPDATE_MESSAGE: "1"
211
+ }
212
+ };
213
+ if (!prismaPath) {
214
+ execPackage(`prisma ${args}`, _options);
215
+ return;
216
+ }
217
+ execSync(`node ${prismaPath} ${args}`, _options);
218
+ }
219
+ __name(execPrisma, "execPrisma");
155
220
 
156
221
  // src/actions/db.ts
157
- async function run(command, options) {
222
+ async function run2(command, options) {
158
223
  switch (command) {
159
224
  case "push":
160
225
  await runPush(options);
161
226
  break;
162
227
  }
163
228
  }
164
- __name(run, "run");
229
+ __name(run2, "run");
165
230
  async function runPush(options) {
166
231
  const schemaFile = getSchemaFile(options.schema);
232
+ await requireDataSourceUrl(schemaFile);
167
233
  const prismaSchemaFile = await generateTempPrismaSchema(schemaFile);
168
234
  try {
169
235
  const cmd = [
170
- "prisma db push",
236
+ "db push",
171
237
  ` --schema "${prismaSchemaFile}"`,
172
238
  options.acceptDataLoss ? " --accept-data-loss" : "",
173
239
  options.forceReset ? " --force-reset" : "",
174
240
  " --skip-generate"
175
241
  ].join("");
176
242
  try {
177
- await execPackage(cmd);
243
+ execPrisma(cmd);
178
244
  } catch (err) {
179
245
  handleSubProcessError(err);
180
246
  }
@@ -186,12 +252,33 @@ async function runPush(options) {
186
252
  }
187
253
  __name(runPush, "runPush");
188
254
 
255
+ // src/actions/format.ts
256
+ import { formatDocument } from "@zenstackhq/language";
257
+ import colors3 from "colors";
258
+ import fs3 from "fs";
259
+ async function run3(options) {
260
+ const schemaFile = getSchemaFile(options.schema);
261
+ let formattedContent;
262
+ try {
263
+ formattedContent = await formatDocument(fs3.readFileSync(schemaFile, "utf-8"));
264
+ } catch (error) {
265
+ console.error(colors3.red("\u2717 Schema formatting failed."));
266
+ throw error;
267
+ }
268
+ fs3.writeFileSync(schemaFile, formattedContent, "utf-8");
269
+ console.log(colors3.green("\u2713 Schema formatting completed successfully."));
270
+ }
271
+ __name(run3, "run");
272
+
189
273
  // src/actions/generate.ts
190
274
  import { invariant } from "@zenstackhq/common-helpers";
191
275
  import { isPlugin } from "@zenstackhq/language/ast";
192
276
  import { getLiteral, getLiteralArray } from "@zenstackhq/language/utils";
193
- import colors2 from "colors";
277
+ import colors4 from "colors";
278
+ import { createJiti } from "jiti";
279
+ import fs6 from "fs";
194
280
  import path4 from "path";
281
+ import { pathToFileURL } from "url";
195
282
  import ora from "ora";
196
283
 
197
284
  // src/plugins/index.ts
@@ -203,7 +290,7 @@ __export(plugins_exports, {
203
290
 
204
291
  // src/plugins/prisma.ts
205
292
  import { PrismaSchemaGenerator as PrismaSchemaGenerator2 } from "@zenstackhq/sdk";
206
- import fs3 from "fs";
293
+ import fs4 from "fs";
207
294
  import path2 from "path";
208
295
  var plugin = {
209
296
  name: "Prisma Schema Generator",
@@ -212,21 +299,21 @@ var plugin = {
212
299
  let outFile = path2.join(defaultOutputPath, "schema.prisma");
213
300
  if (typeof pluginOptions["output"] === "string") {
214
301
  outFile = path2.resolve(defaultOutputPath, pluginOptions["output"]);
215
- if (!fs3.existsSync(path2.dirname(outFile))) {
216
- fs3.mkdirSync(path2.dirname(outFile), {
302
+ if (!fs4.existsSync(path2.dirname(outFile))) {
303
+ fs4.mkdirSync(path2.dirname(outFile), {
217
304
  recursive: true
218
305
  });
219
306
  }
220
307
  }
221
308
  const prismaSchema = await new PrismaSchemaGenerator2(model).generate();
222
- fs3.writeFileSync(outFile, prismaSchema);
309
+ fs4.writeFileSync(outFile, prismaSchema);
223
310
  }
224
311
  };
225
312
  var prisma_default = plugin;
226
313
 
227
314
  // src/plugins/typescript.ts
228
315
  import { TsSchemaGenerator } from "@zenstackhq/sdk";
229
- import fs4 from "fs";
316
+ import fs5 from "fs";
230
317
  import path3 from "path";
231
318
  var plugin2 = {
232
319
  name: "TypeScript Schema Generator",
@@ -235,42 +322,53 @@ var plugin2 = {
235
322
  let outDir = defaultOutputPath;
236
323
  if (typeof pluginOptions["output"] === "string") {
237
324
  outDir = path3.resolve(defaultOutputPath, pluginOptions["output"]);
238
- if (!fs4.existsSync(outDir)) {
239
- fs4.mkdirSync(outDir, {
325
+ if (!fs5.existsSync(outDir)) {
326
+ fs5.mkdirSync(outDir, {
240
327
  recursive: true
241
328
  });
242
329
  }
243
330
  }
244
- await new TsSchemaGenerator().generate(model, outDir);
331
+ const lite = pluginOptions["lite"] === true;
332
+ const liteOnly = pluginOptions["liteOnly"] === true;
333
+ const importWithFileExtension = pluginOptions["importWithFileExtension"];
334
+ if (importWithFileExtension && typeof importWithFileExtension !== "string") {
335
+ throw new Error('The "importWithFileExtension" option must be a string if specified.');
336
+ }
337
+ await new TsSchemaGenerator().generate(model, {
338
+ outDir,
339
+ lite,
340
+ liteOnly,
341
+ importWithFileExtension
342
+ });
245
343
  }
246
344
  };
247
345
  var typescript_default = plugin2;
248
346
 
249
347
  // src/actions/generate.ts
250
- async function run2(options) {
348
+ async function run4(options) {
251
349
  const start = Date.now();
252
350
  const schemaFile = getSchemaFile(options.schema);
253
351
  const model = await loadSchemaDocument(schemaFile);
254
352
  const outputPath = getOutputPath(options, schemaFile);
255
353
  await runPlugins(schemaFile, model, outputPath, options);
256
354
  if (!options.silent) {
257
- console.log(colors2.green(`Generation completed successfully in ${Date.now() - start}ms.
355
+ console.log(colors4.green(`Generation completed successfully in ${Date.now() - start}ms.
258
356
  `));
259
357
  console.log(`You can now create a ZenStack client with it.
260
358
 
261
359
  \`\`\`ts
262
- import { ZenStackClient } from '@zenstackhq/runtime';
263
- import { schema } from '${outputPath}/schema';
360
+ import { ZenStackClient } from '@zenstackhq/orm';
361
+ import { schema } from '${path4.relative(".", outputPath)}/schema';
264
362
 
265
363
  const client = new ZenStackClient(schema, {
266
364
  dialect: { ... }
267
365
  });
268
366
  \`\`\`
269
367
 
270
- Check documentation: https://zenstack.dev/docs/3.x`);
368
+ Check documentation: https://zenstack.dev/docs/`);
271
369
  }
272
370
  }
273
- __name(run2, "run");
371
+ __name(run4, "run");
274
372
  function getOutputPath(options, schemaFile) {
275
373
  if (options.output) {
276
374
  return options.output;
@@ -295,29 +393,38 @@ async function runPlugins(schemaFile, model, outputPath, options) {
295
393
  throw new CliError(`Unknown core plugin: ${provider}`);
296
394
  }
297
395
  } else {
298
- let moduleSpec = provider;
299
- if (moduleSpec.startsWith(".")) {
300
- moduleSpec = path4.resolve(path4.dirname(schemaFile), moduleSpec);
301
- }
302
- try {
303
- cliPlugin = (await import(moduleSpec)).default;
304
- } catch (error) {
305
- throw new CliError(`Failed to load plugin ${provider}: ${error}`);
396
+ cliPlugin = await loadPluginModule(provider, path4.dirname(schemaFile));
397
+ }
398
+ if (cliPlugin) {
399
+ const pluginOptions = getPluginOptions(plugin3);
400
+ if (provider === "@core/typescript") {
401
+ if (pluginOptions["lite"] === void 0) {
402
+ pluginOptions["lite"] = options.lite;
403
+ }
404
+ if (pluginOptions["liteOnly"] === void 0) {
405
+ pluginOptions["liteOnly"] = options.liteOnly;
406
+ }
306
407
  }
408
+ processedPlugins.push({
409
+ cliPlugin,
410
+ pluginOptions
411
+ });
307
412
  }
308
- processedPlugins.push({
309
- cliPlugin,
310
- pluginOptions: getPluginOptions(plugin3)
311
- });
312
413
  }
313
414
  const defaultPlugins = [
314
- typescript_default
315
- ].reverse();
316
- defaultPlugins.forEach((d) => {
317
- if (!processedPlugins.some((p) => p.cliPlugin === d)) {
318
- processedPlugins.push({
319
- cliPlugin: d,
320
- pluginOptions: {}
415
+ {
416
+ plugin: typescript_default,
417
+ options: {
418
+ lite: options.lite,
419
+ liteOnly: options.liteOnly
420
+ }
421
+ }
422
+ ];
423
+ defaultPlugins.forEach(({ plugin: plugin3, options: options2 }) => {
424
+ if (!processedPlugins.some((p) => p.cliPlugin === plugin3)) {
425
+ processedPlugins.unshift({
426
+ cliPlugin: plugin3,
427
+ pluginOptions: options2
321
428
  });
322
429
  }
323
430
  });
@@ -365,11 +472,70 @@ function getPluginOptions(plugin3) {
365
472
  return result;
366
473
  }
367
474
  __name(getPluginOptions, "getPluginOptions");
475
+ async function loadPluginModule(provider, basePath) {
476
+ let moduleSpec = provider;
477
+ if (moduleSpec.startsWith(".")) {
478
+ moduleSpec = path4.resolve(basePath, moduleSpec);
479
+ }
480
+ const importAsEsm = /* @__PURE__ */ __name(async (spec) => {
481
+ try {
482
+ const result = (await import(spec)).default;
483
+ return result;
484
+ } catch (err) {
485
+ throw new CliError(`Failed to load plugin module from ${spec}: ${err.message}`);
486
+ }
487
+ }, "importAsEsm");
488
+ const jiti = createJiti(pathToFileURL(basePath).toString());
489
+ const importAsTs = /* @__PURE__ */ __name(async (spec) => {
490
+ try {
491
+ const result = await jiti.import(spec, {
492
+ default: true
493
+ });
494
+ return result;
495
+ } catch (err) {
496
+ throw new CliError(`Failed to load plugin module from ${spec}: ${err.message}`);
497
+ }
498
+ }, "importAsTs");
499
+ const esmSuffixes = [
500
+ ".js",
501
+ ".mjs"
502
+ ];
503
+ const tsSuffixes = [
504
+ ".ts",
505
+ ".mts"
506
+ ];
507
+ if (fs6.existsSync(moduleSpec) && fs6.statSync(moduleSpec).isFile()) {
508
+ if (esmSuffixes.some((suffix) => moduleSpec.endsWith(suffix))) {
509
+ return await importAsEsm(pathToFileURL(moduleSpec).toString());
510
+ }
511
+ if (tsSuffixes.some((suffix) => moduleSpec.endsWith(suffix))) {
512
+ return await importAsTs(moduleSpec);
513
+ }
514
+ }
515
+ for (const suffix of esmSuffixes) {
516
+ const indexPath = path4.join(moduleSpec, `index${suffix}`);
517
+ if (fs6.existsSync(indexPath)) {
518
+ return await importAsEsm(pathToFileURL(indexPath).toString());
519
+ }
520
+ }
521
+ for (const suffix of tsSuffixes) {
522
+ const indexPath = path4.join(moduleSpec, `index${suffix}`);
523
+ if (fs6.existsSync(indexPath)) {
524
+ return await importAsTs(indexPath);
525
+ }
526
+ }
527
+ try {
528
+ return (await import(moduleSpec)).default;
529
+ } catch {
530
+ return void 0;
531
+ }
532
+ }
533
+ __name(loadPluginModule, "loadPluginModule");
368
534
 
369
535
  // src/actions/info.ts
370
- import colors3 from "colors";
536
+ import colors5 from "colors";
371
537
  import path5 from "path";
372
- async function run3(projectPath) {
538
+ async function run5(projectPath) {
373
539
  const packages = await getZenStackPackages(projectPath);
374
540
  if (!packages) {
375
541
  console.error("Unable to locate package.json. Are you in a valid project directory?");
@@ -381,13 +547,13 @@ async function run3(projectPath) {
381
547
  if (version2) {
382
548
  versions.add(version2);
383
549
  }
384
- console.log(` ${colors3.green(pkg.padEnd(20))} ${version2}`);
550
+ console.log(` ${colors5.green(pkg.padEnd(20))} ${version2}`);
385
551
  }
386
552
  if (versions.size > 1) {
387
- console.warn(colors3.yellow("WARNING: Multiple versions of Zenstack packages detected. This may cause issues."));
553
+ console.warn(colors5.yellow("WARNING: Multiple versions of Zenstack packages detected. This may cause issues."));
388
554
  }
389
555
  }
390
- __name(run3, "run");
556
+ __name(run5, "run");
391
557
  async function getZenStackPackages(projectPath) {
392
558
  let pkgJson;
393
559
  const resolvedPath = path5.resolve(projectPath);
@@ -430,8 +596,8 @@ async function getZenStackPackages(projectPath) {
430
596
  __name(getZenStackPackages, "getZenStackPackages");
431
597
 
432
598
  // src/actions/init.ts
433
- import colors4 from "colors";
434
- import fs5 from "fs";
599
+ import colors6 from "colors";
600
+ import fs7 from "fs";
435
601
  import path6 from "path";
436
602
  import ora2 from "ora";
437
603
  import { detect, resolveCommand } from "package-manager-detector";
@@ -460,20 +626,20 @@ model Post {
460
626
  title String @length(1, 256)
461
627
  content String
462
628
  published Boolean @default(false)
463
- author User @relation(fields: [authorId], references: [id])
629
+ author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
464
630
  authorId String
465
631
  }
466
632
  `;
467
633
 
468
634
  // src/actions/init.ts
469
- async function run4(projectPath) {
635
+ async function run6(projectPath) {
470
636
  const packages = [
471
637
  {
472
- name: "@zenstackhq/cli@next",
638
+ name: "@zenstackhq/cli@latest",
473
639
  dev: true
474
640
  },
475
641
  {
476
- name: "@zenstackhq/runtime@next",
642
+ name: "@zenstackhq/orm@latest",
477
643
  dev: false
478
644
  }
479
645
  ];
@@ -484,12 +650,12 @@ async function run4(projectPath) {
484
650
  name: "npm"
485
651
  };
486
652
  }
487
- console.log(colors4.gray(`Using package manager: ${pm.agent}`));
653
+ console.log(colors6.gray(`Using package manager: ${pm.agent}`));
488
654
  for (const pkg of packages) {
489
- const resolved = resolveCommand(pm.agent, "install", [
655
+ const resolved = resolveCommand(pm.agent, "add", [
490
656
  pkg.name,
491
657
  ...pkg.dev ? [
492
- pm.agent === "yarn" ? "--dev" : "--save-dev"
658
+ pm.agent.startsWith("yarn") || pm.agent === "bun" ? "--dev" : "--save-dev"
493
659
  ] : []
494
660
  ]);
495
661
  if (!resolved) {
@@ -507,25 +673,55 @@ async function run4(projectPath) {
507
673
  }
508
674
  }
509
675
  const generationFolder = "zenstack";
510
- if (!fs5.existsSync(path6.join(projectPath, generationFolder))) {
511
- fs5.mkdirSync(path6.join(projectPath, generationFolder));
676
+ if (!fs7.existsSync(path6.join(projectPath, generationFolder))) {
677
+ fs7.mkdirSync(path6.join(projectPath, generationFolder));
512
678
  }
513
- if (!fs5.existsSync(path6.join(projectPath, generationFolder, "schema.zmodel"))) {
514
- fs5.writeFileSync(path6.join(projectPath, generationFolder, "schema.zmodel"), STARTER_ZMODEL);
679
+ if (!fs7.existsSync(path6.join(projectPath, generationFolder, "schema.zmodel"))) {
680
+ fs7.writeFileSync(path6.join(projectPath, generationFolder, "schema.zmodel"), STARTER_ZMODEL);
515
681
  } else {
516
- console.log(colors4.yellow("Schema file already exists. Skipping generation of sample."));
682
+ console.log(colors6.yellow("Schema file already exists. Skipping generation of sample."));
517
683
  }
518
- console.log(colors4.green("ZenStack project initialized successfully!"));
519
- console.log(colors4.gray(`See "${generationFolder}/schema.zmodel" for your database schema.`));
520
- console.log(colors4.gray("Run `zenstack generate` to compile the the schema into a TypeScript file."));
684
+ console.log(colors6.green("ZenStack project initialized successfully!"));
685
+ console.log(colors6.gray(`See "${generationFolder}/schema.zmodel" for your database schema.`));
686
+ console.log(colors6.gray("Run `zenstack generate` to compile the the schema into a TypeScript file."));
521
687
  }
522
- __name(run4, "run");
688
+ __name(run6, "run");
523
689
 
524
690
  // src/actions/migrate.ts
525
- import fs6 from "fs";
691
+ import fs8 from "fs";
526
692
  import path7 from "path";
527
- async function run5(command, options) {
693
+
694
+ // src/actions/seed.ts
695
+ import colors7 from "colors";
696
+ import { execaCommand } from "execa";
697
+ async function run7(options, args) {
698
+ const pkgJsonConfig = getPkgJsonConfig(process.cwd());
699
+ if (!pkgJsonConfig.seed) {
700
+ if (!options.noWarnings) {
701
+ console.warn(colors7.yellow("No seed script defined in package.json. Skipping seeding."));
702
+ }
703
+ return;
704
+ }
705
+ const command = `${pkgJsonConfig.seed}${args.length > 0 ? " " + args.join(" ") : ""}`;
706
+ if (options.printStatus) {
707
+ console.log(colors7.gray(`Running seed script "${command}"...`));
708
+ }
709
+ try {
710
+ await execaCommand(command, {
711
+ stdout: "inherit",
712
+ stderr: "inherit"
713
+ });
714
+ } catch (err) {
715
+ console.error(colors7.red(err instanceof Error ? err.message : String(err)));
716
+ throw new CliError("Failed to seed the database. Please check the error message above for details.");
717
+ }
718
+ }
719
+ __name(run7, "run");
720
+
721
+ // src/actions/migrate.ts
722
+ async function run8(command, options) {
528
723
  const schemaFile = getSchemaFile(options.schema);
724
+ await requireDataSourceUrl(schemaFile);
529
725
  const prismaSchemaDir = options.migrations ? path7.dirname(options.migrations) : void 0;
530
726
  const prismaSchemaFile = await generateTempPrismaSchema(schemaFile, prismaSchemaDir);
531
727
  try {
@@ -547,22 +743,23 @@ async function run5(command, options) {
547
743
  break;
548
744
  }
549
745
  } finally {
550
- if (fs6.existsSync(prismaSchemaFile)) {
551
- fs6.unlinkSync(prismaSchemaFile);
746
+ if (fs8.existsSync(prismaSchemaFile)) {
747
+ fs8.unlinkSync(prismaSchemaFile);
552
748
  }
553
749
  }
554
750
  }
555
- __name(run5, "run");
556
- async function runDev(prismaSchemaFile, options) {
751
+ __name(run8, "run");
752
+ function runDev(prismaSchemaFile, options) {
557
753
  try {
558
754
  const cmd = [
559
- "prisma migrate dev",
755
+ "migrate dev",
560
756
  ` --schema "${prismaSchemaFile}"`,
561
757
  " --skip-generate",
562
- options.name ? ` --name ${options.name}` : "",
758
+ " --skip-seed",
759
+ options.name ? ` --name "${options.name}"` : "",
563
760
  options.createOnly ? " --create-only" : ""
564
761
  ].join("");
565
- await execPackage(cmd);
762
+ execPrisma(cmd);
566
763
  } catch (err) {
567
764
  handleSubProcessError2(err);
568
765
  }
@@ -571,48 +768,56 @@ __name(runDev, "runDev");
571
768
  async function runReset(prismaSchemaFile, options) {
572
769
  try {
573
770
  const cmd = [
574
- "prisma migrate reset",
771
+ "migrate reset",
575
772
  ` --schema "${prismaSchemaFile}"`,
773
+ " --skip-generate",
774
+ " --skip-seed",
576
775
  options.force ? " --force" : ""
577
776
  ].join("");
578
- await execPackage(cmd);
777
+ execPrisma(cmd);
579
778
  } catch (err) {
580
779
  handleSubProcessError2(err);
581
780
  }
781
+ if (!options.skipSeed) {
782
+ await run7({
783
+ noWarnings: true,
784
+ printStatus: true
785
+ }, []);
786
+ }
582
787
  }
583
788
  __name(runReset, "runReset");
584
- async function runDeploy(prismaSchemaFile, _options) {
789
+ function runDeploy(prismaSchemaFile, _options) {
585
790
  try {
586
791
  const cmd = [
587
- "prisma migrate deploy",
792
+ "migrate deploy",
588
793
  ` --schema "${prismaSchemaFile}"`
589
794
  ].join("");
590
- await execPackage(cmd);
795
+ execPrisma(cmd);
591
796
  } catch (err) {
592
797
  handleSubProcessError2(err);
593
798
  }
594
799
  }
595
800
  __name(runDeploy, "runDeploy");
596
- async function runStatus(prismaSchemaFile, _options) {
801
+ function runStatus(prismaSchemaFile, _options) {
597
802
  try {
598
- await execPackage(`prisma migrate status --schema "${prismaSchemaFile}"`);
803
+ execPrisma(`migrate status --schema "${prismaSchemaFile}"`);
599
804
  } catch (err) {
600
805
  handleSubProcessError2(err);
601
806
  }
602
807
  }
603
808
  __name(runStatus, "runStatus");
604
- async function runResolve(prismaSchemaFile, options) {
809
+ function runResolve(prismaSchemaFile, options) {
605
810
  if (!options.applied && !options.rolledBack) {
606
811
  throw new CliError("Either --applied or --rolled-back option must be provided");
607
812
  }
608
813
  try {
609
814
  const cmd = [
610
- "prisma migrate resolve",
815
+ "migrate resolve",
611
816
  ` --schema "${prismaSchemaFile}"`,
612
- options.applied ? ` --applied ${options.applied}` : "",
613
- options.rolledBack ? ` --rolled-back ${options.rolledBack}` : ""
817
+ options.applied ? ` --applied "${options.applied}"` : "",
818
+ options.rolledBack ? ` --rolled-back "${options.rolledBack}"` : ""
614
819
  ].join("");
615
- await execPackage(cmd);
820
+ execPrisma(cmd);
616
821
  } catch (err) {
617
822
  handleSubProcessError2(err);
618
823
  }
@@ -627,24 +832,10 @@ function handleSubProcessError2(err) {
627
832
  }
628
833
  __name(handleSubProcessError2, "handleSubProcessError");
629
834
 
630
- // src/actions/check.ts
631
- import colors5 from "colors";
632
- async function run6(options) {
633
- const schemaFile = getSchemaFile(options.schema);
634
- try {
635
- await loadSchemaDocument(schemaFile);
636
- console.log(colors5.green("\u2713 Schema validation completed successfully."));
637
- } catch (error) {
638
- console.error(colors5.red("\u2717 Schema validation failed."));
639
- throw error;
640
- }
641
- }
642
- __name(run6, "run");
643
-
644
835
  // src/telemetry.ts
645
836
  import { init } from "mixpanel";
646
837
  import { randomUUID as randomUUID2 } from "crypto";
647
- import fs11 from "fs";
838
+ import fs13 from "fs";
648
839
  import * as os2 from "os";
649
840
 
650
841
  // src/constants.ts
@@ -655,14 +846,14 @@ import { env } from "process";
655
846
  var isInCi = env["CI"] !== "0" && env["CI"] !== "false" && ("CI" in env || "CONTINUOUS_INTEGRATION" in env || Object.keys(env).some((key) => key.startsWith("CI_")));
656
847
 
657
848
  // src/utils/is-container.ts
658
- import fs8 from "fs";
849
+ import fs10 from "fs";
659
850
 
660
851
  // src/utils/is-docker.ts
661
- import fs7 from "fs";
852
+ import fs9 from "fs";
662
853
  var isDockerCached;
663
854
  function hasDockerEnv() {
664
855
  try {
665
- fs7.statSync("/.dockerenv");
856
+ fs9.statSync("/.dockerenv");
666
857
  return true;
667
858
  } catch {
668
859
  return false;
@@ -671,7 +862,7 @@ function hasDockerEnv() {
671
862
  __name(hasDockerEnv, "hasDockerEnv");
672
863
  function hasDockerCGroup() {
673
864
  try {
674
- return fs7.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
865
+ return fs9.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
675
866
  } catch {
676
867
  return false;
677
868
  }
@@ -689,7 +880,7 @@ __name(isDocker, "isDocker");
689
880
  var cachedResult;
690
881
  var hasContainerEnv = /* @__PURE__ */ __name(() => {
691
882
  try {
692
- fs8.statSync("/run/.containerenv");
883
+ fs10.statSync("/run/.containerenv");
693
884
  return true;
694
885
  } catch {
695
886
  return false;
@@ -706,7 +897,7 @@ __name(isInContainer, "isInContainer");
706
897
  // src/utils/is-wsl.ts
707
898
  import process2 from "process";
708
899
  import os from "os";
709
- import fs9 from "fs";
900
+ import fs11 from "fs";
710
901
  var isWsl = /* @__PURE__ */ __name(() => {
711
902
  if (process2.platform !== "linux") {
712
903
  return false;
@@ -715,7 +906,7 @@ var isWsl = /* @__PURE__ */ __name(() => {
715
906
  return true;
716
907
  }
717
908
  try {
718
- return fs9.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft");
909
+ return fs11.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft");
719
910
  } catch {
720
911
  return false;
721
912
  }
@@ -779,17 +970,17 @@ function getMachineId() {
779
970
  __name(getMachineId, "getMachineId");
780
971
 
781
972
  // src/utils/version-utils.ts
782
- import colors6 from "colors";
783
- import fs10 from "fs";
973
+ import colors8 from "colors";
974
+ import fs12 from "fs";
784
975
  import path8 from "path";
785
- import { fileURLToPath } from "url";
976
+ import { fileURLToPath as fileURLToPath2 } from "url";
786
977
  import semver from "semver";
787
978
  var CHECK_VERSION_TIMEOUT = 2e3;
788
979
  var VERSION_CHECK_TAG = "next";
789
980
  function getVersion() {
790
981
  try {
791
- const _dirname = typeof __dirname !== "undefined" ? __dirname : path8.dirname(fileURLToPath(import.meta.url));
792
- return JSON.parse(fs10.readFileSync(path8.join(_dirname, "../package.json"), "utf8")).version;
982
+ const _dirname = typeof __dirname !== "undefined" ? __dirname : path8.dirname(fileURLToPath2(import.meta.url));
983
+ return JSON.parse(fs12.readFileSync(path8.join(_dirname, "../package.json"), "utf8")).version;
793
984
  } catch {
794
985
  return void 0;
795
986
  }
@@ -804,7 +995,7 @@ async function checkNewVersion() {
804
995
  return;
805
996
  }
806
997
  if (latestVersion && currVersion && semver.gt(latestVersion, currVersion)) {
807
- console.log(`A newer version ${colors6.cyan(latestVersion)} is available.`);
998
+ console.log(`A newer version ${colors8.cyan(latestVersion)} is available.`);
808
999
  }
809
1000
  }
810
1001
  __name(checkNewVersion, "checkNewVersion");
@@ -919,7 +1110,7 @@ var Telemetry = class {
919
1110
  try {
920
1111
  const packageJsonPath = import.meta.resolve("prisma/package.json");
921
1112
  const packageJsonUrl = new URL(packageJsonPath);
922
- const packageJson = JSON.parse(fs11.readFileSync(packageJsonUrl, "utf8"));
1113
+ const packageJson = JSON.parse(fs13.readFileSync(packageJsonUrl, "utf8"));
923
1114
  return packageJson.version;
924
1115
  } catch {
925
1116
  return void 0;
@@ -930,45 +1121,62 @@ var telemetry = new Telemetry();
930
1121
 
931
1122
  // src/index.ts
932
1123
  var generateAction = /* @__PURE__ */ __name(async (options) => {
933
- await telemetry.trackCommand("generate", () => run2(options));
1124
+ await telemetry.trackCommand("generate", () => run4(options));
934
1125
  }, "generateAction");
935
1126
  var migrateAction = /* @__PURE__ */ __name(async (subCommand, options) => {
936
- await telemetry.trackCommand(`migrate ${subCommand}`, () => run5(subCommand, options));
1127
+ await telemetry.trackCommand(`migrate ${subCommand}`, () => run8(subCommand, options));
937
1128
  }, "migrateAction");
938
1129
  var dbAction = /* @__PURE__ */ __name(async (subCommand, options) => {
939
- await telemetry.trackCommand(`db ${subCommand}`, () => run(subCommand, options));
1130
+ await telemetry.trackCommand(`db ${subCommand}`, () => run2(subCommand, options));
940
1131
  }, "dbAction");
941
1132
  var infoAction = /* @__PURE__ */ __name(async (projectPath) => {
942
- await telemetry.trackCommand("info", () => run3(projectPath));
1133
+ await telemetry.trackCommand("info", () => run5(projectPath));
943
1134
  }, "infoAction");
944
1135
  var initAction = /* @__PURE__ */ __name(async (projectPath) => {
945
- await telemetry.trackCommand("init", () => run4(projectPath));
1136
+ await telemetry.trackCommand("init", () => run6(projectPath));
946
1137
  }, "initAction");
947
1138
  var checkAction = /* @__PURE__ */ __name(async (options) => {
948
- await telemetry.trackCommand("check", () => run6(options));
1139
+ await telemetry.trackCommand("check", () => run(options));
949
1140
  }, "checkAction");
1141
+ var formatAction = /* @__PURE__ */ __name(async (options) => {
1142
+ await telemetry.trackCommand("format", () => run3(options));
1143
+ }, "formatAction");
1144
+ var seedAction = /* @__PURE__ */ __name(async (options, args) => {
1145
+ await telemetry.trackCommand("db seed", () => run7(options, args));
1146
+ }, "seedAction");
950
1147
  function createProgram() {
951
- const program = new Command("zen");
952
- program.version(getVersion(), "-v --version", "display CLI version");
1148
+ const program = new Command("zen").alias("zenstack").helpOption("-h, --help", "Show this help message").version(getVersion(), "-v --version", "Show CLI version");
953
1149
  const schemaExtensions = ZModelLanguageMetaData.fileExtensions.join(", ");
954
- program.description(`${colors7.bold.blue("\u03B6")} ZenStack is the data layer for modern TypeScript apps.
1150
+ program.description(`${colors9.bold.blue("\u03B6")} ZenStack is the modern data layer for TypeScript apps.
955
1151
 
956
- Documentation: https://zenstack.dev/docs/3.x`).showHelpAfterError().showSuggestionAfterError();
1152
+ Documentation: https://zenstack.dev/docs`).showHelpAfterError().showSuggestionAfterError();
957
1153
  const schemaOption = new Option("--schema <file>", `schema file (with extension ${schemaExtensions}). Defaults to "zenstack/schema.zmodel" unless specified in package.json.`);
958
1154
  const noVersionCheckOption = new Option("--no-version-check", "do not check for new version");
959
- program.command("generate").description("Run code generation plugins.").addOption(schemaOption).addOption(noVersionCheckOption).addOption(new Option("-o, --output <path>", "default output directory for code generation")).addOption(new Option("--silent", "suppress all output except errors").default(false)).action(generateAction);
1155
+ program.command("generate").description("Run code generation plugins").addOption(schemaOption).addOption(noVersionCheckOption).addOption(new Option("-o, --output <path>", "default output directory for code generation")).addOption(new Option("--lite", "also generate a lite version of schema without attributes").default(false)).addOption(new Option("--lite-only", "only generate lite version of schema without attributes").default(false)).addOption(new Option("--silent", "suppress all output except errors").default(false)).action(generateAction);
960
1156
  const migrateCommand = program.command("migrate").description("Run database schema migration related tasks.");
961
1157
  const migrationsOption = new Option("--migrations <path>", 'path that contains the "migrations" directory');
962
- migrateCommand.command("dev").addOption(schemaOption).addOption(noVersionCheckOption).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));
963
- migrateCommand.command("reset").addOption(schemaOption).addOption(new Option("--force", "skip the confirmation prompt")).addOption(migrationsOption).addOption(noVersionCheckOption).description("Reset your database and apply all migrations, all data will be lost.").action((options) => migrateAction("reset", options));
964
- migrateCommand.command("deploy").addOption(schemaOption).addOption(noVersionCheckOption).addOption(migrationsOption).description("Deploy your pending migrations to your production/staging database.").action((options) => migrateAction("deploy", options));
965
- migrateCommand.command("status").addOption(schemaOption).addOption(noVersionCheckOption).addOption(migrationsOption).description("Check the status of your database migrations.").action((options) => migrateAction("status", options));
966
- migrateCommand.command("resolve").addOption(schemaOption).addOption(noVersionCheckOption).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));
967
- const dbCommand = program.command("db").description("Manage your database schema during development.");
968
- dbCommand.command("push").description("Push the state from your schema to your database.").addOption(schemaOption).addOption(noVersionCheckOption).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));
969
- program.command("info").description("Get information of installed ZenStack packages.").argument("[path]", "project path", ".").addOption(noVersionCheckOption).action(infoAction);
970
- program.command("init").description("Initialize an existing project for ZenStack.").argument("[path]", "project path", ".").addOption(noVersionCheckOption).action(initAction);
971
- program.command("check").description("Check a ZModel schema for syntax or semantic errors.").addOption(schemaOption).addOption(noVersionCheckOption).action(checkAction);
1158
+ migrateCommand.command("dev").addOption(schemaOption).addOption(noVersionCheckOption).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));
1159
+ migrateCommand.command("reset").addOption(schemaOption).addOption(new Option("--force", "skip the confirmation prompt")).addOption(migrationsOption).addOption(new Option("--skip-seed", "skip seeding the database after reset")).addOption(noVersionCheckOption).description("Reset your database and apply all migrations, all data will be lost").addHelpText("after", "\nIf there is a seed script defined in package.json, it will be run after the reset. Use --skip-seed to skip it.").action((options) => migrateAction("reset", options));
1160
+ migrateCommand.command("deploy").addOption(schemaOption).addOption(noVersionCheckOption).addOption(migrationsOption).description("Deploy your pending migrations to your production/staging database").action((options) => migrateAction("deploy", options));
1161
+ migrateCommand.command("status").addOption(schemaOption).addOption(noVersionCheckOption).addOption(migrationsOption).description("Check the status of your database migrations").action((options) => migrateAction("status", options));
1162
+ migrateCommand.command("resolve").addOption(schemaOption).addOption(noVersionCheckOption).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));
1163
+ const dbCommand = program.command("db").description("Manage your database schema during development");
1164
+ dbCommand.command("push").description("Push the state from your schema to your database").addOption(schemaOption).addOption(noVersionCheckOption).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));
1165
+ dbCommand.command("seed").description("Seed the database").allowExcessArguments(true).addHelpText("after", `
1166
+ Seed script is configured under the "zenstack.seed" field in package.json.
1167
+ E.g.:
1168
+ {
1169
+ "zenstack": {
1170
+ "seed": "ts-node ./zenstack/seed.ts"
1171
+ }
1172
+ }
1173
+
1174
+ Arguments following -- are passed to the seed script. E.g.: "zen db seed -- --users 10"`).addOption(noVersionCheckOption).action((options, command) => seedAction(options, command.args));
1175
+ program.command("info").description("Get information of installed ZenStack packages").argument("[path]", "project path", ".").addOption(noVersionCheckOption).action(infoAction);
1176
+ program.command("init").description("Initialize an existing project for ZenStack").argument("[path]", "project path", ".").addOption(noVersionCheckOption).action(initAction);
1177
+ program.command("check").description("Check a ZModel schema for syntax or semantic errors").addOption(schemaOption).addOption(noVersionCheckOption).action(checkAction);
1178
+ program.command("format").description("Format a ZModel schema file").addOption(schemaOption).addOption(noVersionCheckOption).action(formatAction);
1179
+ program.addHelpCommand("help [command]", "Display help for a command");
972
1180
  program.hook("preAction", async (_thisCommand, actionCommand) => {
973
1181
  if (actionCommand.getOptionValue("versionCheck") !== false) {
974
1182
  await checkNewVersion();
@@ -989,10 +1197,10 @@ async function main() {
989
1197
  if (e instanceof CommanderError) {
990
1198
  exitCode = e.exitCode;
991
1199
  } else if (e instanceof CliError) {
992
- console.error(colors7.red(e.message));
1200
+ console.error(colors9.red(e.message));
993
1201
  exitCode = 1;
994
1202
  } else {
995
- console.error(colors7.red(`Unhandled error: ${e}`));
1203
+ console.error(colors9.red(`Unhandled error: ${e}`));
996
1204
  exitCode = 1;
997
1205
  }
998
1206
  }