@zenstackhq/cli 3.0.0-alpha.0 → 3.0.0-alpha.10

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,78 +1,5 @@
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;
12
- };
13
-
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.0",
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
3
 
77
4
  // src/index.ts
78
5
  import { ZModelLanguageMetaData } from "@zenstackhq/language";
@@ -80,7 +7,7 @@ import colors5 from "colors";
80
7
  import { Command, Option } from "commander";
81
8
 
82
9
  // src/actions/db.ts
83
- import path2 from "node:path";
10
+ import fs2 from "fs";
84
11
 
85
12
  // src/utils/exec-utils.ts
86
13
  import { execSync as _exec } from "child_process";
@@ -105,7 +32,12 @@ function execPackage(cmd, options) {
105
32
  __name(execPackage, "execPackage");
106
33
 
107
34
  // src/actions/action-utils.ts
108
- import fs from "node:fs";
35
+ import { findUp } from "@zenstackhq/common-helpers";
36
+ import { loadDocument } from "@zenstackhq/language";
37
+ import { PrismaSchemaGenerator } from "@zenstackhq/sdk";
38
+ import colors from "colors";
39
+ import fs from "fs";
40
+ import path from "path";
109
41
 
110
42
  // src/cli-error.ts
111
43
  var CliError = class extends Error {
@@ -115,8 +47,6 @@ var CliError = class extends Error {
115
47
  };
116
48
 
117
49
  // src/actions/action-utils.ts
118
- import { loadDocument } from "@zenstackhq/language";
119
- import colors from "colors";
120
50
  function getSchemaFile(file) {
121
51
  if (file) {
122
52
  if (!fs.existsSync(file)) {
@@ -124,6 +54,13 @@ function getSchemaFile(file) {
124
54
  }
125
55
  return file;
126
56
  }
57
+ const pkgJsonConfig = getPkgJsonConfig(process.cwd());
58
+ if (pkgJsonConfig.schema) {
59
+ if (!fs.existsSync(pkgJsonConfig.schema)) {
60
+ throw new CliError(`Schema file not found: ${pkgJsonConfig.schema}`);
61
+ }
62
+ return pkgJsonConfig.schema;
63
+ }
127
64
  if (fs.existsSync("./zenstack/schema.zmodel")) {
128
65
  return "./zenstack/schema.zmodel";
129
66
  } else if (fs.existsSync("./schema.zmodel")) {
@@ -153,37 +90,125 @@ function handleSubProcessError(err) {
153
90
  }
154
91
  }
155
92
  __name(handleSubProcessError, "handleSubProcessError");
93
+ async function generateTempPrismaSchema(zmodelPath) {
94
+ const model = await loadSchemaDocument(zmodelPath);
95
+ const prismaSchema = await new PrismaSchemaGenerator(model).generate();
96
+ const prismaSchemaFile = path.resolve(path.dirname(zmodelPath), "~schema.prisma");
97
+ fs.writeFileSync(prismaSchemaFile, prismaSchema);
98
+ return prismaSchemaFile;
99
+ }
100
+ __name(generateTempPrismaSchema, "generateTempPrismaSchema");
101
+ function getPkgJsonConfig(startPath) {
102
+ const result = {
103
+ schema: void 0,
104
+ output: void 0
105
+ };
106
+ const pkgJsonFile = findUp([
107
+ "package.json"
108
+ ], startPath, false);
109
+ if (!pkgJsonFile) {
110
+ return result;
111
+ }
112
+ let pkgJson = void 0;
113
+ try {
114
+ pkgJson = JSON.parse(fs.readFileSync(pkgJsonFile, "utf8"));
115
+ } catch {
116
+ return result;
117
+ }
118
+ if (pkgJson.zenstack && typeof pkgJson.zenstack === "object") {
119
+ result.schema = pkgJson.zenstack.schema && path.resolve(path.dirname(pkgJsonFile), pkgJson.zenstack.schema);
120
+ result.output = pkgJson.zenstack.output && path.resolve(path.dirname(pkgJsonFile), pkgJson.zenstack.output);
121
+ }
122
+ return result;
123
+ }
124
+ __name(getPkgJsonConfig, "getPkgJsonConfig");
125
+
126
+ // src/actions/db.ts
127
+ async function run(command, options) {
128
+ switch (command) {
129
+ case "push":
130
+ await runPush(options);
131
+ break;
132
+ }
133
+ }
134
+ __name(run, "run");
135
+ async function runPush(options) {
136
+ const schemaFile = getSchemaFile(options.schema);
137
+ const prismaSchemaFile = await generateTempPrismaSchema(schemaFile);
138
+ try {
139
+ const cmd = [
140
+ "prisma db push",
141
+ ` --schema "${prismaSchemaFile}"`,
142
+ options.acceptDataLoss ? " --accept-data-loss" : "",
143
+ options.forceReset ? " --force-reset" : "",
144
+ " --skip-generate"
145
+ ].join("");
146
+ try {
147
+ await execPackage(cmd);
148
+ } catch (err) {
149
+ handleSubProcessError(err);
150
+ }
151
+ } finally {
152
+ if (fs2.existsSync(prismaSchemaFile)) {
153
+ fs2.unlinkSync(prismaSchemaFile);
154
+ }
155
+ }
156
+ }
157
+ __name(runPush, "runPush");
156
158
 
157
159
  // src/actions/generate.ts
160
+ import { invariant } from "@zenstackhq/common-helpers";
158
161
  import { isPlugin } from "@zenstackhq/language/ast";
159
- import { PrismaSchemaGenerator, TsSchemaGenerator } from "@zenstackhq/sdk";
162
+ import { PrismaSchemaGenerator as PrismaSchemaGenerator2, TsSchemaGenerator } from "@zenstackhq/sdk";
160
163
  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) {
164
+ import fs3 from "fs";
165
+ import path2 from "path";
166
+ async function run2(options) {
165
167
  const schemaFile = getSchemaFile(options.schema);
166
168
  const model = await loadSchemaDocument(schemaFile);
167
- const outputPath = options.output ?? path.dirname(schemaFile);
168
- const tsSchemaFile = path.join(outputPath, "schema.ts");
169
+ const outputPath = getOutputPath(options, schemaFile);
170
+ const tsSchemaFile = path2.join(outputPath, "schema.ts");
169
171
  await new TsSchemaGenerator().generate(schemaFile, [], tsSchemaFile);
170
172
  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.savePrismaSchema) {
174
+ const prismaSchema = await new PrismaSchemaGenerator2(model).generate();
175
+ let prismaSchemaFile = path2.join(outputPath, "schema.prisma");
176
+ if (typeof options.savePrismaSchema === "string") {
177
+ prismaSchemaFile = path2.resolve(outputPath, options.savePrismaSchema);
178
+ fs3.mkdirSync(path2.dirname(prismaSchemaFile), {
179
+ recursive: true
180
+ });
181
+ }
182
+ fs3.writeFileSync(prismaSchemaFile, prismaSchema);
183
+ }
173
184
  if (!options.silent) {
174
185
  console.log(colors2.green("Generation completed successfully."));
175
186
  console.log(`You can now create a ZenStack client with it.
176
187
 
177
- \`\`\`
188
+ \`\`\`ts
178
189
  import { ZenStackClient } from '@zenstackhq/runtime';
179
190
  import { schema } from '${outputPath}/schema';
180
191
 
181
- const client = new ZenStackClient(schema);
192
+ const client = new ZenStackClient(schema, {
193
+ dialectConfig: { ... }
194
+ });
182
195
  \`\`\`
183
196
  `);
184
197
  }
185
198
  }
186
- __name(run, "run");
199
+ __name(run2, "run");
200
+ function getOutputPath(options, schemaFile) {
201
+ if (options.output) {
202
+ return options.output;
203
+ }
204
+ const pkgJsonConfig = getPkgJsonConfig(process.cwd());
205
+ if (pkgJsonConfig.output) {
206
+ return pkgJsonConfig.output;
207
+ } else {
208
+ return path2.dirname(schemaFile);
209
+ }
210
+ }
211
+ __name(getOutputPath, "getOutputPath");
187
212
  async function runPlugins(model, outputPath, tsSchemaFile) {
188
213
  const plugins = model.declarations.filter(isPlugin);
189
214
  for (const plugin of plugins) {
@@ -205,36 +230,9 @@ async function runPlugins(model, outputPath, tsSchemaFile) {
205
230
  }
206
231
  __name(runPlugins, "runPlugins");
207
232
 
208
- // src/actions/db.ts
209
- async function run2(command, options) {
210
- const schemaFile = getSchemaFile(options.schema);
211
- await run({
212
- schema: schemaFile,
213
- silent: true
214
- });
215
- const prismaSchemaFile = path2.join(path2.dirname(schemaFile), "schema.prisma");
216
- switch (command) {
217
- case "push":
218
- await runPush(prismaSchemaFile, options);
219
- break;
220
- }
221
- }
222
- __name(run2, "run");
223
- async function runPush(prismaSchemaFile, options) {
224
- const cmd = `prisma db push --schema "${prismaSchemaFile}"${options.acceptDataLoss ? " --accept-data-loss" : ""}${options.forceReset ? " --force-reset" : ""} --skip-generate`;
225
- try {
226
- await execPackage(cmd, {
227
- stdio: "inherit"
228
- });
229
- } catch (err) {
230
- handleSubProcessError(err);
231
- }
232
- }
233
- __name(runPush, "runPush");
234
-
235
233
  // src/actions/info.ts
236
234
  import colors3 from "colors";
237
- import path3 from "node:path";
235
+ import path3 from "path";
238
236
  async function run3(projectPath) {
239
237
  const packages = await getZenStackPackages(projectPath);
240
238
  if (!packages) {
@@ -263,7 +261,7 @@ async function getZenStackPackages(projectPath) {
263
261
  type: "json"
264
262
  }
265
263
  })).default;
266
- } catch (err) {
264
+ } catch {
267
265
  return [];
268
266
  }
269
267
  const packages = Array.from(new Set([
@@ -294,8 +292,8 @@ __name(getZenStackPackages, "getZenStackPackages");
294
292
 
295
293
  // src/actions/init.ts
296
294
  import colors4 from "colors";
297
- import fs3 from "node:fs";
298
- import path4 from "node:path";
295
+ import fs4 from "fs";
296
+ import path4 from "path";
299
297
  import ora from "ora";
300
298
  import { detect, resolveCommand } from "package-manager-detector";
301
299
 
@@ -332,11 +330,11 @@ model Post {
332
330
  async function run4(projectPath) {
333
331
  const packages = [
334
332
  {
335
- name: "@zenstackhq/cli",
333
+ name: "@zenstackhq/cli@next",
336
334
  dev: true
337
335
  },
338
336
  {
339
- name: "@zenstackhq/runtime",
337
+ name: "@zenstackhq/runtime@next",
340
338
  dev: false
341
339
  }
342
340
  ];
@@ -370,11 +368,11 @@ async function run4(projectPath) {
370
368
  }
371
369
  }
372
370
  const generationFolder = "zenstack";
373
- if (!fs3.existsSync(path4.join(projectPath, generationFolder))) {
374
- fs3.mkdirSync(path4.join(projectPath, generationFolder));
371
+ if (!fs4.existsSync(path4.join(projectPath, generationFolder))) {
372
+ fs4.mkdirSync(path4.join(projectPath, generationFolder));
375
373
  }
376
- if (!fs3.existsSync(path4.join(projectPath, generationFolder, "schema.zmodel"))) {
377
- fs3.writeFileSync(path4.join(projectPath, generationFolder, "schema.zmodel"), STARTER_ZMODEL);
374
+ if (!fs4.existsSync(path4.join(projectPath, generationFolder, "schema.zmodel"))) {
375
+ fs4.writeFileSync(path4.join(projectPath, generationFolder, "schema.zmodel"), STARTER_ZMODEL);
378
376
  } else {
379
377
  console.log(colors4.yellow("Schema file already exists. Skipping generation of sample."));
380
378
  }
@@ -385,35 +383,42 @@ async function run4(projectPath) {
385
383
  __name(run4, "run");
386
384
 
387
385
  // src/actions/migrate.ts
388
- import path5 from "node:path";
386
+ import fs5 from "fs";
389
387
  async function run5(command, options) {
390
388
  const schemaFile = getSchemaFile(options.schema);
391
- await run({
392
- schema: schemaFile,
393
- silent: true
394
- });
395
- const prismaSchemaFile = path5.join(path5.dirname(schemaFile), "schema.prisma");
396
- switch (command) {
397
- case "dev":
398
- await runDev(prismaSchemaFile, options);
399
- break;
400
- case "reset":
401
- await runReset(prismaSchemaFile, options);
402
- break;
403
- case "deploy":
404
- await runDeploy(prismaSchemaFile, options);
405
- break;
406
- case "status":
407
- await runStatus(prismaSchemaFile, options);
408
- break;
389
+ const prismaSchemaFile = await generateTempPrismaSchema(schemaFile);
390
+ try {
391
+ switch (command) {
392
+ case "dev":
393
+ await runDev(prismaSchemaFile, options);
394
+ break;
395
+ case "reset":
396
+ await runReset(prismaSchemaFile, options);
397
+ break;
398
+ case "deploy":
399
+ await runDeploy(prismaSchemaFile, options);
400
+ break;
401
+ case "status":
402
+ await runStatus(prismaSchemaFile, options);
403
+ break;
404
+ }
405
+ } finally {
406
+ if (fs5.existsSync(prismaSchemaFile)) {
407
+ fs5.unlinkSync(prismaSchemaFile);
408
+ }
409
409
  }
410
410
  }
411
411
  __name(run5, "run");
412
- async function runDev(prismaSchemaFile, _options) {
412
+ async function runDev(prismaSchemaFile, options) {
413
413
  try {
414
- await execPackage(`prisma migrate dev --schema "${prismaSchemaFile}" --skip-generate`, {
415
- stdio: "inherit"
416
- });
414
+ const cmd = [
415
+ "prisma migrate dev",
416
+ ` --schema "${prismaSchemaFile}"`,
417
+ " --skip-generate",
418
+ options.name ? ` --name ${options.name}` : "",
419
+ options.createOnly ? " --create-only" : ""
420
+ ].join("");
421
+ await execPackage(cmd);
417
422
  } catch (err) {
418
423
  handleSubProcessError2(err);
419
424
  }
@@ -421,9 +426,12 @@ async function runDev(prismaSchemaFile, _options) {
421
426
  __name(runDev, "runDev");
422
427
  async function runReset(prismaSchemaFile, options) {
423
428
  try {
424
- await execPackage(`prisma migrate reset --schema "${prismaSchemaFile}"${options.force ? " --force" : ""}`, {
425
- stdio: "inherit"
426
- });
429
+ const cmd = [
430
+ "prisma migrate reset",
431
+ ` --schema "${prismaSchemaFile}"`,
432
+ options.force ? " --force" : ""
433
+ ].join("");
434
+ await execPackage(cmd);
427
435
  } catch (err) {
428
436
  handleSubProcessError2(err);
429
437
  }
@@ -431,9 +439,11 @@ async function runReset(prismaSchemaFile, options) {
431
439
  __name(runReset, "runReset");
432
440
  async function runDeploy(prismaSchemaFile, _options) {
433
441
  try {
434
- await execPackage(`prisma migrate deploy --schema "${prismaSchemaFile}"`, {
435
- stdio: "inherit"
436
- });
442
+ const cmd = [
443
+ "prisma migrate deploy",
444
+ ` --schema "${prismaSchemaFile}"`
445
+ ].join("");
446
+ await execPackage(cmd);
437
447
  } catch (err) {
438
448
  handleSubProcessError2(err);
439
449
  }
@@ -441,9 +451,7 @@ async function runDeploy(prismaSchemaFile, _options) {
441
451
  __name(runDeploy, "runDeploy");
442
452
  async function runStatus(prismaSchemaFile, _options) {
443
453
  try {
444
- await execPackage(`prisma migrate status --schema "${prismaSchemaFile}"`, {
445
- stdio: "inherit"
446
- });
454
+ await execPackage(`prisma migrate status --schema "${prismaSchemaFile}"`);
447
455
  } catch (err) {
448
456
  handleSubProcessError2(err);
449
457
  }
@@ -459,28 +467,28 @@ function handleSubProcessError2(err) {
459
467
  __name(handleSubProcessError2, "handleSubProcessError");
460
468
 
461
469
  // src/utils/version-utils.ts
470
+ import fs6 from "fs";
471
+ import path5 from "path";
472
+ import { fileURLToPath } from "url";
462
473
  function getVersion() {
463
474
  try {
464
- return __require("../package.json").version;
475
+ const _dirname = typeof __dirname !== "undefined" ? __dirname : path5.dirname(fileURLToPath(import.meta.url));
476
+ return JSON.parse(fs6.readFileSync(path5.join(_dirname, "../package.json"), "utf8")).version;
465
477
  } catch {
466
- try {
467
- return require_package().version;
468
- } catch {
469
- return void 0;
470
- }
478
+ return void 0;
471
479
  }
472
480
  }
473
481
  __name(getVersion, "getVersion");
474
482
 
475
483
  // src/index.ts
476
484
  var generateAction = /* @__PURE__ */ __name(async (options) => {
477
- await run(options);
485
+ await run2(options);
478
486
  }, "generateAction");
479
487
  var migrateAction = /* @__PURE__ */ __name(async (command, options) => {
480
488
  await run5(command, options);
481
489
  }, "migrateAction");
482
490
  var dbAction = /* @__PURE__ */ __name(async (command, options) => {
483
- await run2(command, options);
491
+ await run(command, options);
484
492
  }, "dbAction");
485
493
  var infoAction = /* @__PURE__ */ __name(async (projectPath) => {
486
494
  await run3(projectPath);
@@ -496,7 +504,7 @@ function createProgram() {
496
504
 
497
505
  Documentation: https://zenstack.dev.`).showHelpAfterError().showSuggestionAfterError();
498
506
  const schemaOption = new Option("--schema <file>", `schema file (with extension ${schemaExtensions}). Defaults to "schema.zmodel" unless specified in package.json.`);
499
- program2.command("generate").description("Run code generation.").addOption(schemaOption).addOption(new Option("-o, --output <path>", "default output directory for core plugins")).action(generateAction);
507
+ program2.command("generate").description("Run code generation.").addOption(schemaOption).addOption(new Option("--silent", "do not print any output")).addOption(new Option("--save-prisma-schema [path]", "save a Prisma schema file, by default into the output directory")).addOption(new Option("-o, --output <path>", "default output directory for core plugins")).action(generateAction);
500
508
  const migrateCommand = program2.command("migrate").description("Update the database schema with migrations.");
501
509
  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));
502
510
  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));