@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 +118 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +115 -18
- package/dist/index.js.map +1 -1
- package/package.json +30 -15
package/dist/index.js
CHANGED
|
@@ -37,6 +37,8 @@ var CliError = class extends Error {
|
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
// src/actions/action-utils.ts
|
|
40
|
+
import terminalLink from "terminal-link";
|
|
41
|
+
import { z } from "zod";
|
|
40
42
|
function getSchemaFile(file) {
|
|
41
43
|
if (file) {
|
|
42
44
|
if (!fs.existsSync(file)) {
|
|
@@ -212,6 +214,58 @@ async function getZenStackPackages(searchPath) {
|
|
|
212
214
|
return result.filter((p) => !!p);
|
|
213
215
|
}
|
|
214
216
|
__name(getZenStackPackages, "getZenStackPackages");
|
|
217
|
+
var FETCH_CLI_MAX_TIME = 1e3;
|
|
218
|
+
var CLI_CONFIG_ENDPOINT = "https://zenstack.dev/config/cli-v3.json";
|
|
219
|
+
var usageTipsSchema = z.object({
|
|
220
|
+
notifications: z.array(z.object({
|
|
221
|
+
title: z.string(),
|
|
222
|
+
url: z.url().optional(),
|
|
223
|
+
active: z.boolean()
|
|
224
|
+
}))
|
|
225
|
+
});
|
|
226
|
+
function startUsageTipsFetch() {
|
|
227
|
+
let fetchedData = void 0;
|
|
228
|
+
let fetchComplete = false;
|
|
229
|
+
const start = Date.now();
|
|
230
|
+
const controller = new AbortController();
|
|
231
|
+
fetch(CLI_CONFIG_ENDPOINT, {
|
|
232
|
+
headers: {
|
|
233
|
+
accept: "application/json"
|
|
234
|
+
},
|
|
235
|
+
signal: controller.signal
|
|
236
|
+
}).then(async (res) => {
|
|
237
|
+
if (!res.ok) return;
|
|
238
|
+
const data = await res.json();
|
|
239
|
+
const parseResult = usageTipsSchema.safeParse(data);
|
|
240
|
+
if (parseResult.success) {
|
|
241
|
+
fetchedData = parseResult.data;
|
|
242
|
+
}
|
|
243
|
+
}).catch(() => {
|
|
244
|
+
}).finally(() => {
|
|
245
|
+
fetchComplete = true;
|
|
246
|
+
});
|
|
247
|
+
return async () => {
|
|
248
|
+
const elapsed = Date.now() - start;
|
|
249
|
+
if (!fetchComplete && elapsed < FETCH_CLI_MAX_TIME) {
|
|
250
|
+
await new Promise((resolve) => setTimeout(resolve, FETCH_CLI_MAX_TIME - elapsed));
|
|
251
|
+
}
|
|
252
|
+
if (!fetchComplete) {
|
|
253
|
+
controller.abort();
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (!fetchedData) return;
|
|
257
|
+
const activeItems = fetchedData.notifications.filter((item) => item.active);
|
|
258
|
+
if (activeItems.length > 0) {
|
|
259
|
+
const item = activeItems[Math.floor(Math.random() * activeItems.length)];
|
|
260
|
+
if (item.url) {
|
|
261
|
+
console.log(terminalLink(item.title, item.url));
|
|
262
|
+
} else {
|
|
263
|
+
console.log(item.title);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
__name(startUsageTipsFetch, "startUsageTipsFetch");
|
|
215
269
|
|
|
216
270
|
// src/actions/check.ts
|
|
217
271
|
async function run(options) {
|
|
@@ -2183,8 +2237,8 @@ var sqlite = {
|
|
|
2183
2237
|
return void 0;
|
|
2184
2238
|
},
|
|
2185
2239
|
async introspect(connectionString, _options) {
|
|
2186
|
-
const
|
|
2187
|
-
const db = new
|
|
2240
|
+
const SQLite = (await import("better-sqlite3")).default;
|
|
2241
|
+
const db = new SQLite(connectionString, {
|
|
2188
2242
|
readonly: true
|
|
2189
2243
|
});
|
|
2190
2244
|
try {
|
|
@@ -2881,13 +2935,14 @@ import { invariant, singleDebounce } from "@zenstackhq/common-helpers";
|
|
|
2881
2935
|
import { ZModelLanguageMetaData } from "@zenstackhq/language";
|
|
2882
2936
|
import { isPlugin } from "@zenstackhq/language/ast";
|
|
2883
2937
|
import { getLiteral, getLiteralArray as getLiteralArray2 } from "@zenstackhq/language/utils";
|
|
2938
|
+
import { watch } from "chokidar";
|
|
2884
2939
|
import colors6 from "colors";
|
|
2885
2940
|
import { createJiti } from "jiti";
|
|
2886
2941
|
import fs6 from "fs";
|
|
2887
2942
|
import path5 from "path";
|
|
2888
2943
|
import { pathToFileURL } from "url";
|
|
2889
|
-
import { watch } from "chokidar";
|
|
2890
2944
|
import ora2 from "ora";
|
|
2945
|
+
import semver from "semver";
|
|
2891
2946
|
|
|
2892
2947
|
// src/plugins/index.ts
|
|
2893
2948
|
var plugins_exports = {};
|
|
@@ -2942,25 +2997,30 @@ var plugin2 = {
|
|
|
2942
2997
|
if (importWithFileExtension && typeof importWithFileExtension !== "string") {
|
|
2943
2998
|
throw new Error('The "importWithFileExtension" option must be a string if specified.');
|
|
2944
2999
|
}
|
|
3000
|
+
const generateModelTypes = pluginOptions["generateModels"] !== false;
|
|
3001
|
+
const generateInputTypes = pluginOptions["generateInput"] !== false;
|
|
2945
3002
|
await new TsSchemaGenerator().generate(model, {
|
|
2946
3003
|
outDir,
|
|
2947
3004
|
lite,
|
|
2948
3005
|
liteOnly,
|
|
2949
|
-
importWithFileExtension
|
|
3006
|
+
importWithFileExtension,
|
|
3007
|
+
generateModelTypes,
|
|
3008
|
+
generateInputTypes
|
|
2950
3009
|
});
|
|
2951
3010
|
}
|
|
2952
3011
|
};
|
|
2953
3012
|
var typescript_default = plugin2;
|
|
2954
3013
|
|
|
2955
3014
|
// src/actions/generate.ts
|
|
2956
|
-
import semver from "semver";
|
|
2957
3015
|
async function run4(options) {
|
|
2958
3016
|
try {
|
|
2959
3017
|
await checkForMismatchedPackages(process.cwd());
|
|
2960
3018
|
} catch (err) {
|
|
2961
3019
|
console.warn(colors6.yellow(`Failed to check for mismatched ZenStack packages: ${err}`));
|
|
2962
3020
|
}
|
|
3021
|
+
const maybeShowUsageTips = options.tips && !options.silent && !options.watch ? startUsageTipsFetch() : void 0;
|
|
2963
3022
|
const model = await pureGenerate(options, false);
|
|
3023
|
+
await maybeShowUsageTips?.();
|
|
2964
3024
|
if (options.watch) {
|
|
2965
3025
|
const logsEnabled = !options.silent;
|
|
2966
3026
|
if (logsEnabled) {
|
|
@@ -3078,12 +3138,18 @@ async function runPlugins(schemaFile, model, outputPath, options) {
|
|
|
3078
3138
|
if (cliPlugin) {
|
|
3079
3139
|
const pluginOptions = getPluginOptions(plugin3);
|
|
3080
3140
|
if (provider === "@core/typescript") {
|
|
3081
|
-
if (
|
|
3141
|
+
if (options.lite !== void 0) {
|
|
3082
3142
|
pluginOptions["lite"] = options.lite;
|
|
3083
3143
|
}
|
|
3084
|
-
if (
|
|
3144
|
+
if (options.liteOnly !== void 0) {
|
|
3085
3145
|
pluginOptions["liteOnly"] = options.liteOnly;
|
|
3086
3146
|
}
|
|
3147
|
+
if (options.generateModels !== void 0) {
|
|
3148
|
+
pluginOptions["generateModels"] = options.generateModels;
|
|
3149
|
+
}
|
|
3150
|
+
if (options.generateInput !== void 0) {
|
|
3151
|
+
pluginOptions["generateInput"] = options.generateInput;
|
|
3152
|
+
}
|
|
3087
3153
|
}
|
|
3088
3154
|
processedPlugins.push({
|
|
3089
3155
|
cliPlugin,
|
|
@@ -3096,7 +3162,9 @@ async function runPlugins(schemaFile, model, outputPath, options) {
|
|
|
3096
3162
|
plugin: typescript_default,
|
|
3097
3163
|
options: {
|
|
3098
3164
|
lite: options.lite,
|
|
3099
|
-
liteOnly: options.liteOnly
|
|
3165
|
+
liteOnly: options.liteOnly,
|
|
3166
|
+
generateModels: options.generateModels,
|
|
3167
|
+
generateInput: options.generateInput
|
|
3100
3168
|
}
|
|
3101
3169
|
}
|
|
3102
3170
|
];
|
|
@@ -3514,14 +3582,11 @@ import { PostgresDialect } from "@zenstackhq/orm/dialects/postgres";
|
|
|
3514
3582
|
import { SqliteDialect } from "@zenstackhq/orm/dialects/sqlite";
|
|
3515
3583
|
import { RPCApiHandler } from "@zenstackhq/server/api";
|
|
3516
3584
|
import { ZenStackMiddleware } from "@zenstackhq/server/express";
|
|
3517
|
-
import SQLite from "better-sqlite3";
|
|
3518
3585
|
import colors11 from "colors";
|
|
3519
3586
|
import cors from "cors";
|
|
3520
3587
|
import express from "express";
|
|
3521
3588
|
import { createJiti as createJiti2 } from "jiti";
|
|
3522
|
-
import { createPool as createMysqlPool } from "mysql2";
|
|
3523
3589
|
import path9 from "path";
|
|
3524
|
-
import { Pool as PgPool } from "pg";
|
|
3525
3590
|
|
|
3526
3591
|
// src/utils/version-utils.ts
|
|
3527
3592
|
import colors10 from "colors";
|
|
@@ -3530,7 +3595,7 @@ import path8 from "path";
|
|
|
3530
3595
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3531
3596
|
import semver2 from "semver";
|
|
3532
3597
|
var CHECK_VERSION_TIMEOUT = 2e3;
|
|
3533
|
-
var VERSION_CHECK_TAG = "
|
|
3598
|
+
var VERSION_CHECK_TAG = "latest";
|
|
3534
3599
|
function getVersion() {
|
|
3535
3600
|
try {
|
|
3536
3601
|
const _dirname = typeof __dirname !== "undefined" ? __dirname : path8.dirname(fileURLToPath2(import.meta.url));
|
|
@@ -3595,7 +3660,7 @@ async function run9(options) {
|
|
|
3595
3660
|
databaseUrl = evaluateUrl(schemaUrl);
|
|
3596
3661
|
}
|
|
3597
3662
|
const provider = getStringLiteral2(dataSource?.fields.find((f) => f.name === "provider")?.value);
|
|
3598
|
-
const dialect = createDialect(provider, databaseUrl, outputPath);
|
|
3663
|
+
const dialect = await createDialect(provider, databaseUrl, outputPath);
|
|
3599
3664
|
const jiti = createJiti2(import.meta.url);
|
|
3600
3665
|
const schemaModule = await jiti.import(path9.join(outputPath, "schema"));
|
|
3601
3666
|
const schema = schemaModule.schema;
|
|
@@ -3655,9 +3720,15 @@ function redactDatabaseUrl(url) {
|
|
|
3655
3720
|
}
|
|
3656
3721
|
}
|
|
3657
3722
|
__name(redactDatabaseUrl, "redactDatabaseUrl");
|
|
3658
|
-
function createDialect(provider, databaseUrl, outputPath) {
|
|
3723
|
+
async function createDialect(provider, databaseUrl, outputPath) {
|
|
3659
3724
|
switch (provider) {
|
|
3660
3725
|
case "sqlite": {
|
|
3726
|
+
let SQLite;
|
|
3727
|
+
try {
|
|
3728
|
+
SQLite = (await import("better-sqlite3")).default;
|
|
3729
|
+
} catch {
|
|
3730
|
+
throw new CliError(`Package "better-sqlite3" is required for SQLite support. Please install it with: npm install better-sqlite3`);
|
|
3731
|
+
}
|
|
3661
3732
|
let resolvedUrl = databaseUrl.trim();
|
|
3662
3733
|
if (resolvedUrl.startsWith("file:")) {
|
|
3663
3734
|
const filePath = resolvedUrl.substring("file:".length);
|
|
@@ -3670,18 +3741,32 @@ function createDialect(provider, databaseUrl, outputPath) {
|
|
|
3670
3741
|
database: new SQLite(resolvedUrl)
|
|
3671
3742
|
});
|
|
3672
3743
|
}
|
|
3673
|
-
case "postgresql":
|
|
3744
|
+
case "postgresql": {
|
|
3745
|
+
let PgPool;
|
|
3746
|
+
try {
|
|
3747
|
+
PgPool = (await import("pg")).Pool;
|
|
3748
|
+
} catch {
|
|
3749
|
+
throw new CliError(`Package "pg" is required for PostgreSQL support. Please install it with: npm install pg`);
|
|
3750
|
+
}
|
|
3674
3751
|
console.log(colors11.gray(`Connecting to PostgreSQL database at: ${redactDatabaseUrl(databaseUrl)}`));
|
|
3675
3752
|
return new PostgresDialect({
|
|
3676
3753
|
pool: new PgPool({
|
|
3677
3754
|
connectionString: databaseUrl
|
|
3678
3755
|
})
|
|
3679
3756
|
});
|
|
3680
|
-
|
|
3757
|
+
}
|
|
3758
|
+
case "mysql": {
|
|
3759
|
+
let createMysqlPool;
|
|
3760
|
+
try {
|
|
3761
|
+
createMysqlPool = (await import("mysql2")).createPool;
|
|
3762
|
+
} catch {
|
|
3763
|
+
throw new CliError(`Package "mysql2" is required for MySQL support. Please install it with: npm install mysql2`);
|
|
3764
|
+
}
|
|
3681
3765
|
console.log(colors11.gray(`Connecting to MySQL database at: ${redactDatabaseUrl(databaseUrl)}`));
|
|
3682
3766
|
return new MysqlDialect({
|
|
3683
3767
|
pool: createMysqlPool(databaseUrl)
|
|
3684
3768
|
});
|
|
3769
|
+
}
|
|
3685
3770
|
default:
|
|
3686
3771
|
throw new CliError(`Unsupported database provider: ${provider}`);
|
|
3687
3772
|
}
|
|
@@ -3745,7 +3830,7 @@ import fs13 from "fs";
|
|
|
3745
3830
|
import * as os2 from "os";
|
|
3746
3831
|
|
|
3747
3832
|
// src/constants.ts
|
|
3748
|
-
var TELEMETRY_TRACKING_TOKEN = "
|
|
3833
|
+
var TELEMETRY_TRACKING_TOKEN = "74944eb779d7d3b4ce185be843fde9fc";
|
|
3749
3834
|
|
|
3750
3835
|
// src/utils/is-ci.ts
|
|
3751
3836
|
import { env } from "process";
|
|
@@ -4005,6 +4090,17 @@ var seedAction = /* @__PURE__ */ __name(async (options, args) => {
|
|
|
4005
4090
|
var proxyAction = /* @__PURE__ */ __name(async (options) => {
|
|
4006
4091
|
await telemetry.trackCommand("proxy", () => run9(options));
|
|
4007
4092
|
}, "proxyAction");
|
|
4093
|
+
function triStateBooleanOption(flag, description) {
|
|
4094
|
+
return new Option(flag, description).choices([
|
|
4095
|
+
"true",
|
|
4096
|
+
"false"
|
|
4097
|
+
]).argParser((value) => {
|
|
4098
|
+
if (value === void 0 || value === "true") return true;
|
|
4099
|
+
if (value === "false") return false;
|
|
4100
|
+
throw new CliError(`Invalid value for ${flag}: ${value}`);
|
|
4101
|
+
});
|
|
4102
|
+
}
|
|
4103
|
+
__name(triStateBooleanOption, "triStateBooleanOption");
|
|
4008
4104
|
function createProgram() {
|
|
4009
4105
|
const program = new Command("zen").alias("zenstack").helpOption("-h, --help", "Show this help message").version(getVersion(), "-v --version", "Show CLI version");
|
|
4010
4106
|
const schemaExtensions = ZModelLanguageMetaData2.fileExtensions.join(", ");
|
|
@@ -4013,7 +4109,8 @@ function createProgram() {
|
|
|
4013
4109
|
Documentation: https://zenstack.dev/docs`).showHelpAfterError().showSuggestionAfterError();
|
|
4014
4110
|
const schemaOption = new Option("--schema <file>", `schema file (with extension ${schemaExtensions}). Defaults to "zenstack/schema.zmodel" unless specified in package.json.`);
|
|
4015
4111
|
const noVersionCheckOption = new Option("--no-version-check", "do not check for new version");
|
|
4016
|
-
|
|
4112
|
+
const noTipsOption = new Option("--no-tips", "do not show usage tips");
|
|
4113
|
+
program.command("generate").description("Run code generation plugins").addOption(schemaOption).addOption(noVersionCheckOption).addOption(noTipsOption).addOption(new Option("-o, --output <path>", "default output directory for code generation")).addOption(new 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 Option("--silent", "suppress all output except errors").default(false)).action(generateAction);
|
|
4017
4114
|
const migrateCommand = program.command("migrate").description("Run database schema migration related tasks.");
|
|
4018
4115
|
const migrationsOption = new Option("--migrations <path>", 'path that contains the "migrations" directory');
|
|
4019
4116
|
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));
|