@zenstackhq/cli 3.0.0-beta.24 → 3.0.0-beta.26
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/.turbo/turbo-build.log +8 -8
- package/dist/index.cjs +76 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +76 -14
- package/dist/index.js.map +1 -1
- package/package.json +11 -12
- package/src/actions/action-utils.ts +23 -3
- package/src/actions/db.ts +6 -2
- package/src/actions/index.ts +2 -1
- package/src/actions/migrate.ts +14 -2
- package/src/actions/seed.ts +38 -0
- package/src/index.ts +29 -0
- package/test/db.test.ts +43 -0
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ var __export = (target, all) => {
|
|
|
13
13
|
|
|
14
14
|
// src/index.ts
|
|
15
15
|
import { ZModelLanguageMetaData } from "@zenstackhq/language";
|
|
16
|
-
import
|
|
16
|
+
import colors9 from "colors";
|
|
17
17
|
import { Command, CommanderError, Option } from "commander";
|
|
18
18
|
|
|
19
19
|
// src/actions/check.ts
|
|
@@ -105,7 +105,8 @@ __name(generateTempPrismaSchema, "generateTempPrismaSchema");
|
|
|
105
105
|
function getPkgJsonConfig(startPath) {
|
|
106
106
|
const result = {
|
|
107
107
|
schema: void 0,
|
|
108
|
-
output: void 0
|
|
108
|
+
output: void 0,
|
|
109
|
+
seed: void 0
|
|
109
110
|
};
|
|
110
111
|
const pkgJsonFile = findUp([
|
|
111
112
|
"package.json"
|
|
@@ -120,8 +121,9 @@ function getPkgJsonConfig(startPath) {
|
|
|
120
121
|
return result;
|
|
121
122
|
}
|
|
122
123
|
if (pkgJson.zenstack && typeof pkgJson.zenstack === "object") {
|
|
123
|
-
result.schema = pkgJson.zenstack.schema && path.resolve(path.dirname(pkgJsonFile), pkgJson.zenstack.schema);
|
|
124
|
-
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;
|
|
125
127
|
}
|
|
126
128
|
return result;
|
|
127
129
|
}
|
|
@@ -144,6 +146,14 @@ function findUp(names, cwd = process.cwd(), multiple = false, result = []) {
|
|
|
144
146
|
return findUp(names, up, multiple, result);
|
|
145
147
|
}
|
|
146
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");
|
|
147
157
|
|
|
148
158
|
// src/actions/check.ts
|
|
149
159
|
async function run(options) {
|
|
@@ -212,6 +222,7 @@ async function run2(command, options) {
|
|
|
212
222
|
__name(run2, "run");
|
|
213
223
|
async function runPush(options) {
|
|
214
224
|
const schemaFile = getSchemaFile(options.schema);
|
|
225
|
+
await requireDataSourceUrl(schemaFile);
|
|
215
226
|
const prismaSchemaFile = await generateTempPrismaSchema(schemaFile);
|
|
216
227
|
try {
|
|
217
228
|
const cmd = [
|
|
@@ -617,8 +628,38 @@ __name(run6, "run");
|
|
|
617
628
|
// src/actions/migrate.ts
|
|
618
629
|
import fs7 from "fs";
|
|
619
630
|
import path7 from "path";
|
|
620
|
-
|
|
631
|
+
|
|
632
|
+
// src/actions/seed.ts
|
|
633
|
+
import colors7 from "colors";
|
|
634
|
+
import { execaCommand } from "execa";
|
|
635
|
+
async function run7(options, args) {
|
|
636
|
+
const pkgJsonConfig = getPkgJsonConfig(process.cwd());
|
|
637
|
+
if (!pkgJsonConfig.seed) {
|
|
638
|
+
if (!options.noWarnings) {
|
|
639
|
+
console.warn(colors7.yellow("No seed script defined in package.json. Skipping seeding."));
|
|
640
|
+
}
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
const command = `${pkgJsonConfig.seed}${args.length > 0 ? " " + args.join(" ") : ""}`;
|
|
644
|
+
if (options.printStatus) {
|
|
645
|
+
console.log(colors7.gray(`Running seed script "${command}"...`));
|
|
646
|
+
}
|
|
647
|
+
try {
|
|
648
|
+
await execaCommand(command, {
|
|
649
|
+
stdout: "inherit",
|
|
650
|
+
stderr: "inherit"
|
|
651
|
+
});
|
|
652
|
+
} catch (err) {
|
|
653
|
+
console.error(colors7.red(err instanceof Error ? err.message : String(err)));
|
|
654
|
+
throw new CliError("Failed to seed the database. Please check the error message above for details.");
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
__name(run7, "run");
|
|
658
|
+
|
|
659
|
+
// src/actions/migrate.ts
|
|
660
|
+
async function run8(command, options) {
|
|
621
661
|
const schemaFile = getSchemaFile(options.schema);
|
|
662
|
+
await requireDataSourceUrl(schemaFile);
|
|
622
663
|
const prismaSchemaDir = options.migrations ? path7.dirname(options.migrations) : void 0;
|
|
623
664
|
const prismaSchemaFile = await generateTempPrismaSchema(schemaFile, prismaSchemaDir);
|
|
624
665
|
try {
|
|
@@ -645,13 +686,14 @@ async function run7(command, options) {
|
|
|
645
686
|
}
|
|
646
687
|
}
|
|
647
688
|
}
|
|
648
|
-
__name(
|
|
689
|
+
__name(run8, "run");
|
|
649
690
|
function runDev(prismaSchemaFile, options) {
|
|
650
691
|
try {
|
|
651
692
|
const cmd = [
|
|
652
693
|
"migrate dev",
|
|
653
694
|
` --schema "${prismaSchemaFile}"`,
|
|
654
695
|
" --skip-generate",
|
|
696
|
+
" --skip-seed",
|
|
655
697
|
options.name ? ` --name "${options.name}"` : "",
|
|
656
698
|
options.createOnly ? " --create-only" : ""
|
|
657
699
|
].join("");
|
|
@@ -661,18 +703,25 @@ function runDev(prismaSchemaFile, options) {
|
|
|
661
703
|
}
|
|
662
704
|
}
|
|
663
705
|
__name(runDev, "runDev");
|
|
664
|
-
function runReset(prismaSchemaFile, options) {
|
|
706
|
+
async function runReset(prismaSchemaFile, options) {
|
|
665
707
|
try {
|
|
666
708
|
const cmd = [
|
|
667
709
|
"migrate reset",
|
|
668
710
|
` --schema "${prismaSchemaFile}"`,
|
|
669
711
|
" --skip-generate",
|
|
712
|
+
" --skip-seed",
|
|
670
713
|
options.force ? " --force" : ""
|
|
671
714
|
].join("");
|
|
672
715
|
execPrisma(cmd);
|
|
673
716
|
} catch (err) {
|
|
674
717
|
handleSubProcessError2(err);
|
|
675
718
|
}
|
|
719
|
+
if (!options.skipSeed) {
|
|
720
|
+
await run7({
|
|
721
|
+
noWarnings: true,
|
|
722
|
+
printStatus: true
|
|
723
|
+
}, []);
|
|
724
|
+
}
|
|
676
725
|
}
|
|
677
726
|
__name(runReset, "runReset");
|
|
678
727
|
function runDeploy(prismaSchemaFile, _options) {
|
|
@@ -859,7 +908,7 @@ function getMachineId() {
|
|
|
859
908
|
__name(getMachineId, "getMachineId");
|
|
860
909
|
|
|
861
910
|
// src/utils/version-utils.ts
|
|
862
|
-
import
|
|
911
|
+
import colors8 from "colors";
|
|
863
912
|
import fs11 from "fs";
|
|
864
913
|
import path8 from "path";
|
|
865
914
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -884,7 +933,7 @@ async function checkNewVersion() {
|
|
|
884
933
|
return;
|
|
885
934
|
}
|
|
886
935
|
if (latestVersion && currVersion && semver.gt(latestVersion, currVersion)) {
|
|
887
|
-
console.log(`A newer version ${
|
|
936
|
+
console.log(`A newer version ${colors8.cyan(latestVersion)} is available.`);
|
|
888
937
|
}
|
|
889
938
|
}
|
|
890
939
|
__name(checkNewVersion, "checkNewVersion");
|
|
@@ -1013,7 +1062,7 @@ var generateAction = /* @__PURE__ */ __name(async (options) => {
|
|
|
1013
1062
|
await telemetry.trackCommand("generate", () => run4(options));
|
|
1014
1063
|
}, "generateAction");
|
|
1015
1064
|
var migrateAction = /* @__PURE__ */ __name(async (subCommand, options) => {
|
|
1016
|
-
await telemetry.trackCommand(`migrate ${subCommand}`, () =>
|
|
1065
|
+
await telemetry.trackCommand(`migrate ${subCommand}`, () => run8(subCommand, options));
|
|
1017
1066
|
}, "migrateAction");
|
|
1018
1067
|
var dbAction = /* @__PURE__ */ __name(async (subCommand, options) => {
|
|
1019
1068
|
await telemetry.trackCommand(`db ${subCommand}`, () => run2(subCommand, options));
|
|
@@ -1030,10 +1079,13 @@ var checkAction = /* @__PURE__ */ __name(async (options) => {
|
|
|
1030
1079
|
var formatAction = /* @__PURE__ */ __name(async (options) => {
|
|
1031
1080
|
await telemetry.trackCommand("format", () => run3(options));
|
|
1032
1081
|
}, "formatAction");
|
|
1082
|
+
var seedAction = /* @__PURE__ */ __name(async (options, args) => {
|
|
1083
|
+
await telemetry.trackCommand("db seed", () => run7(options, args));
|
|
1084
|
+
}, "seedAction");
|
|
1033
1085
|
function createProgram() {
|
|
1034
1086
|
const program = new Command("zen").alias("zenstack").helpOption("-h, --help", "Show this help message").version(getVersion(), "-v --version", "Show CLI version");
|
|
1035
1087
|
const schemaExtensions = ZModelLanguageMetaData.fileExtensions.join(", ");
|
|
1036
|
-
program.description(`${
|
|
1088
|
+
program.description(`${colors9.bold.blue("\u03B6")} ZenStack is the data layer for modern TypeScript apps.
|
|
1037
1089
|
|
|
1038
1090
|
Documentation: https://zenstack.dev/docs/3.x`).showHelpAfterError().showSuggestionAfterError();
|
|
1039
1091
|
const schemaOption = new Option("--schema <file>", `schema file (with extension ${schemaExtensions}). Defaults to "zenstack/schema.zmodel" unless specified in package.json.`);
|
|
@@ -1042,12 +1094,22 @@ Documentation: https://zenstack.dev/docs/3.x`).showHelpAfterError().showSuggesti
|
|
|
1042
1094
|
const migrateCommand = program.command("migrate").description("Run database schema migration related tasks.");
|
|
1043
1095
|
const migrationsOption = new Option("--migrations <path>", 'path that contains the "migrations" directory');
|
|
1044
1096
|
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));
|
|
1045
|
-
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));
|
|
1097
|
+
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));
|
|
1046
1098
|
migrateCommand.command("deploy").addOption(schemaOption).addOption(noVersionCheckOption).addOption(migrationsOption).description("Deploy your pending migrations to your production/staging database").action((options) => migrateAction("deploy", options));
|
|
1047
1099
|
migrateCommand.command("status").addOption(schemaOption).addOption(noVersionCheckOption).addOption(migrationsOption).description("Check the status of your database migrations").action((options) => migrateAction("status", options));
|
|
1048
1100
|
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));
|
|
1049
1101
|
const dbCommand = program.command("db").description("Manage your database schema during development");
|
|
1050
1102
|
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));
|
|
1103
|
+
dbCommand.command("seed").description("Seed the database").allowExcessArguments(true).addHelpText("after", `
|
|
1104
|
+
Seed script is configured under the "zenstack.seed" field in package.json.
|
|
1105
|
+
E.g.:
|
|
1106
|
+
{
|
|
1107
|
+
"zenstack": {
|
|
1108
|
+
"seed": "ts-node ./zenstack/seed.ts"
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
Arguments following -- are passed to the seed script. E.g.: "zen db seed -- --users 10"`).addOption(noVersionCheckOption).action((options, command) => seedAction(options, command.args));
|
|
1051
1113
|
program.command("info").description("Get information of installed ZenStack packages").argument("[path]", "project path", ".").addOption(noVersionCheckOption).action(infoAction);
|
|
1052
1114
|
program.command("init").description("Initialize an existing project for ZenStack").argument("[path]", "project path", ".").addOption(noVersionCheckOption).action(initAction);
|
|
1053
1115
|
program.command("check").description("Check a ZModel schema for syntax or semantic errors").addOption(schemaOption).addOption(noVersionCheckOption).action(checkAction);
|
|
@@ -1073,10 +1135,10 @@ async function main() {
|
|
|
1073
1135
|
if (e instanceof CommanderError) {
|
|
1074
1136
|
exitCode = e.exitCode;
|
|
1075
1137
|
} else if (e instanceof CliError) {
|
|
1076
|
-
console.error(
|
|
1138
|
+
console.error(colors9.red(e.message));
|
|
1077
1139
|
exitCode = 1;
|
|
1078
1140
|
} else {
|
|
1079
|
-
console.error(
|
|
1141
|
+
console.error(colors9.red(`Unhandled error: ${e}`));
|
|
1080
1142
|
exitCode = 1;
|
|
1081
1143
|
}
|
|
1082
1144
|
}
|