@zenstackhq/cli 3.4.0-beta.3 → 3.4.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.cjs CHANGED
@@ -53,6 +53,8 @@ var CliError = class extends Error {
53
53
  };
54
54
 
55
55
  // src/actions/action-utils.ts
56
+ var import_terminal_link = __toESM(require("terminal-link"), 1);
57
+ var import_zod = require("zod");
56
58
  function getSchemaFile(file) {
57
59
  if (file) {
58
60
  if (!import_node_fs.default.existsSync(file)) {
@@ -228,6 +230,58 @@ async function getZenStackPackages(searchPath) {
228
230
  return result.filter((p) => !!p);
229
231
  }
230
232
  __name(getZenStackPackages, "getZenStackPackages");
233
+ var FETCH_CLI_MAX_TIME = 1e3;
234
+ var CLI_CONFIG_ENDPOINT = "https://zenstack.dev/config/cli-v3.json";
235
+ var usageTipsSchema = import_zod.z.object({
236
+ notifications: import_zod.z.array(import_zod.z.object({
237
+ title: import_zod.z.string(),
238
+ url: import_zod.z.url().optional(),
239
+ active: import_zod.z.boolean()
240
+ }))
241
+ });
242
+ function startUsageTipsFetch() {
243
+ let fetchedData = void 0;
244
+ let fetchComplete = false;
245
+ const start = Date.now();
246
+ const controller = new AbortController();
247
+ fetch(CLI_CONFIG_ENDPOINT, {
248
+ headers: {
249
+ accept: "application/json"
250
+ },
251
+ signal: controller.signal
252
+ }).then(async (res) => {
253
+ if (!res.ok) return;
254
+ const data = await res.json();
255
+ const parseResult = usageTipsSchema.safeParse(data);
256
+ if (parseResult.success) {
257
+ fetchedData = parseResult.data;
258
+ }
259
+ }).catch(() => {
260
+ }).finally(() => {
261
+ fetchComplete = true;
262
+ });
263
+ return async () => {
264
+ const elapsed = Date.now() - start;
265
+ if (!fetchComplete && elapsed < FETCH_CLI_MAX_TIME) {
266
+ await new Promise((resolve) => setTimeout(resolve, FETCH_CLI_MAX_TIME - elapsed));
267
+ }
268
+ if (!fetchComplete) {
269
+ controller.abort();
270
+ return;
271
+ }
272
+ if (!fetchedData) return;
273
+ const activeItems = fetchedData.notifications.filter((item) => item.active);
274
+ if (activeItems.length > 0) {
275
+ const item = activeItems[Math.floor(Math.random() * activeItems.length)];
276
+ if (item.url) {
277
+ console.log((0, import_terminal_link.default)(item.title, item.url));
278
+ } else {
279
+ console.log(item.title);
280
+ }
281
+ }
282
+ };
283
+ }
284
+ __name(startUsageTipsFetch, "startUsageTipsFetch");
231
285
 
232
286
  // src/actions/check.ts
233
287
  async function run(options) {
@@ -2200,8 +2254,8 @@ var sqlite = {
2200
2254
  return void 0;
2201
2255
  },
2202
2256
  async introspect(connectionString, _options) {
2203
- const SQLite2 = (await import("better-sqlite3")).default;
2204
- const db = new SQLite2(connectionString, {
2257
+ const SQLite = (await import("better-sqlite3")).default;
2258
+ const db = new SQLite(connectionString, {
2205
2259
  readonly: true
2206
2260
  });
2207
2261
  try {
@@ -2898,13 +2952,14 @@ var import_common_helpers2 = require("@zenstackhq/common-helpers");
2898
2952
  var import_language4 = require("@zenstackhq/language");
2899
2953
  var import_ast5 = require("@zenstackhq/language/ast");
2900
2954
  var import_utils7 = require("@zenstackhq/language/utils");
2955
+ var import_chokidar = require("chokidar");
2901
2956
  var import_colors6 = __toESM(require("colors"), 1);
2902
2957
  var import_jiti = require("jiti");
2903
2958
  var import_node_fs6 = __toESM(require("fs"), 1);
2904
2959
  var import_node_path5 = __toESM(require("path"), 1);
2905
2960
  var import_node_url = require("url");
2906
- var import_chokidar = require("chokidar");
2907
2961
  var import_ora2 = __toESM(require("ora"), 1);
2962
+ var import_semver = __toESM(require("semver"), 1);
2908
2963
 
2909
2964
  // src/plugins/index.ts
2910
2965
  var plugins_exports = {};
@@ -2959,25 +3014,30 @@ var plugin2 = {
2959
3014
  if (importWithFileExtension && typeof importWithFileExtension !== "string") {
2960
3015
  throw new Error('The "importWithFileExtension" option must be a string if specified.');
2961
3016
  }
3017
+ const generateModelTypes = pluginOptions["generateModels"] !== false;
3018
+ const generateInputTypes = pluginOptions["generateInput"] !== false;
2962
3019
  await new import_sdk3.TsSchemaGenerator().generate(model, {
2963
3020
  outDir,
2964
3021
  lite,
2965
3022
  liteOnly,
2966
- importWithFileExtension
3023
+ importWithFileExtension,
3024
+ generateModelTypes,
3025
+ generateInputTypes
2967
3026
  });
2968
3027
  }
2969
3028
  };
2970
3029
  var typescript_default = plugin2;
2971
3030
 
2972
3031
  // src/actions/generate.ts
2973
- var import_semver = __toESM(require("semver"), 1);
2974
3032
  async function run4(options) {
2975
3033
  try {
2976
3034
  await checkForMismatchedPackages(process.cwd());
2977
3035
  } catch (err) {
2978
3036
  console.warn(import_colors6.default.yellow(`Failed to check for mismatched ZenStack packages: ${err}`));
2979
3037
  }
3038
+ const maybeShowUsageTips = options.tips && !options.silent && !options.watch ? startUsageTipsFetch() : void 0;
2980
3039
  const model = await pureGenerate(options, false);
3040
+ await maybeShowUsageTips?.();
2981
3041
  if (options.watch) {
2982
3042
  const logsEnabled = !options.silent;
2983
3043
  if (logsEnabled) {
@@ -3095,12 +3155,18 @@ async function runPlugins(schemaFile, model, outputPath, options) {
3095
3155
  if (cliPlugin) {
3096
3156
  const pluginOptions = getPluginOptions(plugin3);
3097
3157
  if (provider === "@core/typescript") {
3098
- if (pluginOptions["lite"] === void 0) {
3158
+ if (options.lite !== void 0) {
3099
3159
  pluginOptions["lite"] = options.lite;
3100
3160
  }
3101
- if (pluginOptions["liteOnly"] === void 0) {
3161
+ if (options.liteOnly !== void 0) {
3102
3162
  pluginOptions["liteOnly"] = options.liteOnly;
3103
3163
  }
3164
+ if (options.generateModels !== void 0) {
3165
+ pluginOptions["generateModels"] = options.generateModels;
3166
+ }
3167
+ if (options.generateInput !== void 0) {
3168
+ pluginOptions["generateInput"] = options.generateInput;
3169
+ }
3104
3170
  }
3105
3171
  processedPlugins.push({
3106
3172
  cliPlugin,
@@ -3113,7 +3179,9 @@ async function runPlugins(schemaFile, model, outputPath, options) {
3113
3179
  plugin: typescript_default,
3114
3180
  options: {
3115
3181
  lite: options.lite,
3116
- liteOnly: options.liteOnly
3182
+ liteOnly: options.liteOnly,
3183
+ generateModels: options.generateModels,
3184
+ generateInput: options.generateInput
3117
3185
  }
3118
3186
  }
3119
3187
  ];
@@ -3531,14 +3599,11 @@ var import_postgres = require("@zenstackhq/orm/dialects/postgres");
3531
3599
  var import_sqlite2 = require("@zenstackhq/orm/dialects/sqlite");
3532
3600
  var import_api = require("@zenstackhq/server/api");
3533
3601
  var import_express = require("@zenstackhq/server/express");
3534
- var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
3535
3602
  var import_colors11 = __toESM(require("colors"), 1);
3536
3603
  var import_cors = __toESM(require("cors"), 1);
3537
3604
  var import_express2 = __toESM(require("express"), 1);
3538
3605
  var import_jiti2 = require("jiti");
3539
- var import_mysql22 = require("mysql2");
3540
3606
  var import_node_path9 = __toESM(require("path"), 1);
3541
- var import_pg2 = require("pg");
3542
3607
 
3543
3608
  // src/utils/version-utils.ts
3544
3609
  var import_colors10 = __toESM(require("colors"), 1);
@@ -3548,7 +3613,7 @@ var import_node_url2 = require("url");
3548
3613
  var import_semver2 = __toESM(require("semver"), 1);
3549
3614
  var import_meta2 = {};
3550
3615
  var CHECK_VERSION_TIMEOUT = 2e3;
3551
- var VERSION_CHECK_TAG = "next";
3616
+ var VERSION_CHECK_TAG = "latest";
3552
3617
  function getVersion() {
3553
3618
  try {
3554
3619
  const _dirname = typeof __dirname !== "undefined" ? __dirname : import_node_path8.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
@@ -3614,7 +3679,7 @@ async function run9(options) {
3614
3679
  databaseUrl = evaluateUrl(schemaUrl);
3615
3680
  }
3616
3681
  const provider = (0, import_utils8.getStringLiteral)(dataSource?.fields.find((f) => f.name === "provider")?.value);
3617
- const dialect = createDialect(provider, databaseUrl, outputPath);
3682
+ const dialect = await createDialect(provider, databaseUrl, outputPath);
3618
3683
  const jiti = (0, import_jiti2.createJiti)(import_meta3.url);
3619
3684
  const schemaModule = await jiti.import(import_node_path9.default.join(outputPath, "schema"));
3620
3685
  const schema = schemaModule.schema;
@@ -3674,9 +3739,15 @@ function redactDatabaseUrl(url) {
3674
3739
  }
3675
3740
  }
3676
3741
  __name(redactDatabaseUrl, "redactDatabaseUrl");
3677
- function createDialect(provider, databaseUrl, outputPath) {
3742
+ async function createDialect(provider, databaseUrl, outputPath) {
3678
3743
  switch (provider) {
3679
3744
  case "sqlite": {
3745
+ let SQLite;
3746
+ try {
3747
+ SQLite = (await import("better-sqlite3")).default;
3748
+ } catch {
3749
+ throw new CliError(`Package "better-sqlite3" is required for SQLite support. Please install it with: npm install better-sqlite3`);
3750
+ }
3680
3751
  let resolvedUrl = databaseUrl.trim();
3681
3752
  if (resolvedUrl.startsWith("file:")) {
3682
3753
  const filePath = resolvedUrl.substring("file:".length);
@@ -3686,21 +3757,35 @@ function createDialect(provider, databaseUrl, outputPath) {
3686
3757
  }
3687
3758
  console.log(import_colors11.default.gray(`Connecting to SQLite database at: ${resolvedUrl}`));
3688
3759
  return new import_sqlite2.SqliteDialect({
3689
- database: new import_better_sqlite3.default(resolvedUrl)
3760
+ database: new SQLite(resolvedUrl)
3690
3761
  });
3691
3762
  }
3692
- case "postgresql":
3763
+ case "postgresql": {
3764
+ let PgPool;
3765
+ try {
3766
+ PgPool = (await import("pg")).Pool;
3767
+ } catch {
3768
+ throw new CliError(`Package "pg" is required for PostgreSQL support. Please install it with: npm install pg`);
3769
+ }
3693
3770
  console.log(import_colors11.default.gray(`Connecting to PostgreSQL database at: ${redactDatabaseUrl(databaseUrl)}`));
3694
3771
  return new import_postgres.PostgresDialect({
3695
- pool: new import_pg2.Pool({
3772
+ pool: new PgPool({
3696
3773
  connectionString: databaseUrl
3697
3774
  })
3698
3775
  });
3699
- case "mysql":
3776
+ }
3777
+ case "mysql": {
3778
+ let createMysqlPool;
3779
+ try {
3780
+ createMysqlPool = (await import("mysql2")).createPool;
3781
+ } catch {
3782
+ throw new CliError(`Package "mysql2" is required for MySQL support. Please install it with: npm install mysql2`);
3783
+ }
3700
3784
  console.log(import_colors11.default.gray(`Connecting to MySQL database at: ${redactDatabaseUrl(databaseUrl)}`));
3701
3785
  return new import_mysql2.MysqlDialect({
3702
- pool: (0, import_mysql22.createPool)(databaseUrl)
3786
+ pool: createMysqlPool(databaseUrl)
3703
3787
  });
3788
+ }
3704
3789
  default:
3705
3790
  throw new CliError(`Unsupported database provider: ${provider}`);
3706
3791
  }
@@ -3764,7 +3849,7 @@ var import_node_fs13 = __toESM(require("fs"), 1);
3764
3849
  var os2 = __toESM(require("os"), 1);
3765
3850
 
3766
3851
  // src/constants.ts
3767
- var TELEMETRY_TRACKING_TOKEN = "<TELEMETRY_TRACKING_TOKEN>";
3852
+ var TELEMETRY_TRACKING_TOKEN = "74944eb779d7d3b4ce185be843fde9fc";
3768
3853
 
3769
3854
  // src/utils/is-ci.ts
3770
3855
  var import_node_process = require("process");
@@ -4025,6 +4110,17 @@ var seedAction = /* @__PURE__ */ __name(async (options, args) => {
4025
4110
  var proxyAction = /* @__PURE__ */ __name(async (options) => {
4026
4111
  await telemetry.trackCommand("proxy", () => run9(options));
4027
4112
  }, "proxyAction");
4113
+ function triStateBooleanOption(flag, description) {
4114
+ return new import_commander.Option(flag, description).choices([
4115
+ "true",
4116
+ "false"
4117
+ ]).argParser((value) => {
4118
+ if (value === void 0 || value === "true") return true;
4119
+ if (value === "false") return false;
4120
+ throw new CliError(`Invalid value for ${flag}: ${value}`);
4121
+ });
4122
+ }
4123
+ __name(triStateBooleanOption, "triStateBooleanOption");
4028
4124
  function createProgram() {
4029
4125
  const program = new import_commander.Command("zen").alias("zenstack").helpOption("-h, --help", "Show this help message").version(getVersion(), "-v --version", "Show CLI version");
4030
4126
  const schemaExtensions = import_language5.ZModelLanguageMetaData.fileExtensions.join(", ");
@@ -4033,7 +4129,8 @@ function createProgram() {
4033
4129
  Documentation: https://zenstack.dev/docs`).showHelpAfterError().showSuggestionAfterError();
4034
4130
  const schemaOption = new import_commander.Option("--schema <file>", `schema file (with extension ${schemaExtensions}). Defaults to "zenstack/schema.zmodel" unless specified in package.json.`);
4035
4131
  const noVersionCheckOption = new import_commander.Option("--no-version-check", "do not check for new version");
4036
- program.command("generate").description("Run code generation plugins").addOption(schemaOption).addOption(noVersionCheckOption).addOption(new import_commander.Option("-o, --output <path>", "default output directory for code generation")).addOption(new import_commander.Option("-w, --watch", "enable watch mode").default(false)).addOption(new import_commander.Option("--lite", "also generate a lite version of schema without attributes").default(false)).addOption(new import_commander.Option("--lite-only", "only generate lite version of schema without attributes").default(false)).addOption(new import_commander.Option("--silent", "suppress all output except errors").default(false)).action(generateAction);
4132
+ const noTipsOption = new import_commander.Option("--no-tips", "do not show usage tips");
4133
+ program.command("generate").description("Run code generation plugins").addOption(schemaOption).addOption(noVersionCheckOption).addOption(noTipsOption).addOption(new import_commander.Option("-o, --output <path>", "default output directory for code generation")).addOption(new import_commander.Option("-w, --watch", "enable watch mode").default(false)).addOption(triStateBooleanOption("--lite [boolean]", "also generate a lite version of schema without attributes, defaults to false")).addOption(triStateBooleanOption("--lite-only [boolean]", "only generate lite version of schema without attributes, defaults to false")).addOption(triStateBooleanOption("--generate-models [boolean]", "generate models.ts file, defaults to true")).addOption(triStateBooleanOption("--generate-input [boolean]", "generate input.ts file, defaults to true")).addOption(new import_commander.Option("--silent", "suppress all output except errors").default(false)).action(generateAction);
4037
4134
  const migrateCommand = program.command("migrate").description("Run database schema migration related tasks.");
4038
4135
  const migrationsOption = new import_commander.Option("--migrations <path>", 'path that contains the "migrations" directory');
4039
4136
  migrateCommand.command("dev").addOption(schemaOption).addOption(noVersionCheckOption).addOption(new import_commander.Option("-n, --name <name>", "migration name")).addOption(new import_commander.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));