@zenstackhq/cli 3.4.0-beta.1 → 3.4.0-beta.3

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
@@ -26,6 +26,7 @@ import { isDataSource } from "@zenstackhq/language/ast";
26
26
  import { PrismaSchemaGenerator } from "@zenstackhq/sdk";
27
27
  import colors from "colors";
28
28
  import fs from "fs";
29
+ import { createRequire } from "module";
29
30
  import path from "path";
30
31
 
31
32
  // src/cli-error.ts
@@ -141,10 +142,10 @@ function findUp(names, cwd = process.cwd(), multiple = false, result = []) {
141
142
  }
142
143
  const target = names.find((name) => fs.existsSync(path.join(cwd, name)));
143
144
  if (multiple === false && target) {
144
- return path.join(cwd, target);
145
+ return path.resolve(cwd, target);
145
146
  }
146
147
  if (target) {
147
- result.push(path.join(cwd, target));
148
+ result.push(path.resolve(cwd, target));
148
149
  }
149
150
  const up = path.resolve(cwd, "..");
150
151
  if (up === cwd) {
@@ -173,6 +174,44 @@ function getOutputPath(options, schemaFile) {
173
174
  }
174
175
  }
175
176
  __name(getOutputPath, "getOutputPath");
177
+ async function getZenStackPackages(searchPath) {
178
+ const pkgJsonFile = findUp([
179
+ "package.json"
180
+ ], searchPath, false);
181
+ if (!pkgJsonFile) {
182
+ return [];
183
+ }
184
+ let pkgJson;
185
+ try {
186
+ pkgJson = JSON.parse(fs.readFileSync(pkgJsonFile, "utf8"));
187
+ } catch {
188
+ return [];
189
+ }
190
+ const packages = Array.from(new Set([
191
+ ...Object.keys(pkgJson.dependencies ?? {}),
192
+ ...Object.keys(pkgJson.devDependencies ?? {})
193
+ ].filter((p) => p.startsWith("@zenstackhq/")))).sort();
194
+ const require2 = createRequire(pkgJsonFile);
195
+ const result = packages.map((pkg) => {
196
+ try {
197
+ const depPkgJson = require2(`${pkg}/package.json`);
198
+ if (depPkgJson.private) {
199
+ return void 0;
200
+ }
201
+ return {
202
+ pkg,
203
+ version: depPkgJson.version
204
+ };
205
+ } catch {
206
+ return {
207
+ pkg,
208
+ version: void 0
209
+ };
210
+ }
211
+ });
212
+ return result.filter((p) => !!p);
213
+ }
214
+ __name(getZenStackPackages, "getZenStackPackages");
176
215
 
177
216
  // src/actions/check.ts
178
217
  async function run(options) {
@@ -252,6 +291,14 @@ import { lowerCaseFirst } from "@zenstackhq/common-helpers";
252
291
  // src/actions/pull/utils.ts
253
292
  import { isInvocationExpr } from "@zenstackhq/language/ast";
254
293
  import { getLiteralArray, getStringLiteral } from "@zenstackhq/language/utils";
294
+ function isDatabaseManagedAttribute(name) {
295
+ return [
296
+ "@relation",
297
+ "@id",
298
+ "@unique"
299
+ ].includes(name) || name.startsWith("@db.");
300
+ }
301
+ __name(isDatabaseManagedAttribute, "isDatabaseManagedAttribute");
255
302
  function getDatasource(model) {
256
303
  const datasource = model.declarations.find((d) => d.$type === "DataSource");
257
304
  if (!datasource) {
@@ -714,12 +761,84 @@ function syncRelation({ model, relation, services, options, selfRelation, simila
714
761
  });
715
762
  sourceModel.fields.splice(firstSourceFieldId, 0, sourceFieldFactory.node);
716
763
  const oppositeFieldPrefix = /[0-9]/g.test(targetModel.name.charAt(0)) ? "_" : "";
717
- const { name: oppositeFieldName } = resolveNameCasing(options.fieldCasing, similarRelations > 0 ? `${oppositeFieldPrefix}${lowerCaseFirst(sourceModel.name)}_${firstColumn}` : `${lowerCaseFirst(resolveNameCasing(options.fieldCasing, sourceModel.name).name)}${relation.references.type === "many" ? "s" : ""}`);
764
+ let { name: oppositeFieldName } = resolveNameCasing(options.fieldCasing, similarRelations > 0 ? `${oppositeFieldPrefix}${lowerCaseFirst(sourceModel.name)}_${firstColumn}` : `${lowerCaseFirst(resolveNameCasing(options.fieldCasing, sourceModel.name).name)}${relation.references.type === "many" ? "s" : ""}`);
765
+ if (targetModel.fields.find((f) => f.name === oppositeFieldName)) {
766
+ ({ name: oppositeFieldName } = resolveNameCasing(options.fieldCasing, `${lowerCaseFirst(sourceModel.name)}_${firstColumn}To${relation.references.table}_${relation.references.columns[0]}`));
767
+ }
718
768
  const targetFieldFactory = new DataFieldFactory().setContainer(targetModel).setName(oppositeFieldName).setType((tb) => tb.setOptional(relation.references.type === "one").setArray(relation.references.type === "many").setReference(sourceModel));
719
769
  if (includeRelationName) targetFieldFactory.addAttribute((ab) => ab.setDecl(relationAttribute).addArg((ab2) => ab2.StringLiteral.setValue(relationName)));
720
770
  targetModel.fields.push(targetFieldFactory.node);
721
771
  }
722
772
  __name(syncRelation, "syncRelation");
773
+ function consolidateEnums({ newModel, oldModel }) {
774
+ const newEnums = newModel.declarations.filter((d) => isEnum(d));
775
+ const newDataModels = newModel.declarations.filter((d) => d.$type === "DataModel");
776
+ const oldDataModels = oldModel.declarations.filter((d) => d.$type === "DataModel");
777
+ const enumMapping = /* @__PURE__ */ new Map();
778
+ for (const newEnum of newEnums) {
779
+ for (const newDM of newDataModels) {
780
+ for (const field of newDM.fields) {
781
+ if (field.$type !== "DataField" || field.type.reference?.ref !== newEnum) continue;
782
+ const oldDM = oldDataModels.find((d) => getDbName(d) === getDbName(newDM));
783
+ if (!oldDM) continue;
784
+ const oldField = oldDM.fields.find((f) => getDbName(f) === getDbName(field));
785
+ if (!oldField || oldField.$type !== "DataField" || !oldField.type.reference?.ref) continue;
786
+ const oldEnum = oldField.type.reference.ref;
787
+ if (!isEnum(oldEnum)) continue;
788
+ enumMapping.set(newEnum, oldEnum);
789
+ break;
790
+ }
791
+ if (enumMapping.has(newEnum)) break;
792
+ }
793
+ }
794
+ const reverseMapping = /* @__PURE__ */ new Map();
795
+ for (const [newEnum, oldEnum] of enumMapping) {
796
+ if (!reverseMapping.has(oldEnum)) {
797
+ reverseMapping.set(oldEnum, []);
798
+ }
799
+ reverseMapping.get(oldEnum).push(newEnum);
800
+ }
801
+ for (const [oldEnum, newEnumsGroup] of reverseMapping) {
802
+ const keepEnum = newEnumsGroup[0];
803
+ if (newEnumsGroup.length === 1 && keepEnum.name === oldEnum.name) continue;
804
+ const oldValues = new Set(oldEnum.fields.map((f) => getDbName(f)));
805
+ const allMatch = newEnumsGroup.every((ne) => {
806
+ const newValues = new Set(ne.fields.map((f) => getDbName(f)));
807
+ return oldValues.size === newValues.size && [
808
+ ...oldValues
809
+ ].every((v) => newValues.has(v));
810
+ });
811
+ if (!allMatch) continue;
812
+ keepEnum.name = oldEnum.name;
813
+ keepEnum.attributes = oldEnum.attributes.map((attr) => {
814
+ const copy = {
815
+ ...attr,
816
+ $container: keepEnum
817
+ };
818
+ return copy;
819
+ });
820
+ for (let i = 1; i < newEnumsGroup.length; i++) {
821
+ const idx = newModel.declarations.indexOf(newEnumsGroup[i]);
822
+ if (idx >= 0) {
823
+ newModel.declarations.splice(idx, 1);
824
+ }
825
+ }
826
+ for (const newDM of newDataModels) {
827
+ for (const field of newDM.fields) {
828
+ if (field.$type !== "DataField") continue;
829
+ const ref = field.type.reference?.ref;
830
+ if (ref && newEnumsGroup.includes(ref)) {
831
+ field.type.reference = {
832
+ ref: keepEnum,
833
+ $refText: keepEnum.name
834
+ };
835
+ }
836
+ }
837
+ }
838
+ console.log(colors3.gray(`Consolidated enum${newEnumsGroup.length > 1 ? "s" : ""} ${newEnumsGroup.map((e) => e.name).join(", ")} \u2192 ${oldEnum.name}`));
839
+ }
840
+ }
841
+ __name(consolidateEnums, "consolidateEnums");
723
842
 
724
843
  // src/actions/pull/provider/mysql.ts
725
844
  import { DataFieldAttributeFactory as DataFieldAttributeFactory2 } from "@zenstackhq/language/factory";
@@ -977,6 +1096,10 @@ var mysql = {
977
1096
  return (ab) => ab.InvocationExpr.setFunction(getFunctionRef("uuid", services));
978
1097
  }
979
1098
  return (ab) => ab.StringLiteral.setValue(val);
1099
+ case "Json":
1100
+ return (ab) => ab.StringLiteral.setValue(val);
1101
+ case "Bytes":
1102
+ return (ab) => ab.StringLiteral.setValue(val);
980
1103
  }
981
1104
  if (val.includes("(") && val.includes(")")) {
982
1105
  return (ab) => ab.InvocationExpr.setFunction(getFunctionRef("dbgenerated", services)).addArg((a) => a.setValue((v) => v.StringLiteral.setValue(val)));
@@ -1575,6 +1698,26 @@ var postgresql = {
1575
1698
  return (ab) => ab.StringLiteral.setValue(val.slice(1, -1).replace(/''/g, "'"));
1576
1699
  }
1577
1700
  return (ab) => ab.StringLiteral.setValue(val);
1701
+ case "Json":
1702
+ if (val.includes("::")) {
1703
+ return typeCastingConvert({
1704
+ defaultValue,
1705
+ enums,
1706
+ val,
1707
+ services
1708
+ });
1709
+ }
1710
+ return (ab) => ab.StringLiteral.setValue(val);
1711
+ case "Bytes":
1712
+ if (val.includes("::")) {
1713
+ return typeCastingConvert({
1714
+ defaultValue,
1715
+ enums,
1716
+ val,
1717
+ services
1718
+ });
1719
+ }
1720
+ return (ab) => ab.StringLiteral.setValue(val);
1578
1721
  }
1579
1722
  if (val.includes("(") && val.includes(")")) {
1580
1723
  return (ab) => ab.InvocationExpr.setFunction(getFunctionRef("dbgenerated", services)).addArg((a) => a.setValue((v) => v.StringLiteral.setValue(val)));
@@ -2210,6 +2353,10 @@ var sqlite = {
2210
2353
  return (ab) => ab.StringLiteral.setValue(strippedName);
2211
2354
  }
2212
2355
  return (ab) => ab.StringLiteral.setValue(val);
2356
+ case "Json":
2357
+ return (ab) => ab.StringLiteral.setValue(val);
2358
+ case "Bytes":
2359
+ return (ab) => ab.StringLiteral.setValue(val);
2213
2360
  }
2214
2361
  console.warn(`Unsupported default value type: "${defaultValue}" for field type "${fieldType}". Skipping default value.`);
2215
2362
  return null;
@@ -2385,6 +2532,10 @@ async function runPull(options) {
2385
2532
  similarRelations
2386
2533
  });
2387
2534
  }
2535
+ consolidateEnums({
2536
+ newModel,
2537
+ oldModel: model
2538
+ });
2388
2539
  console.log(colors4.blue("Schema synced"));
2389
2540
  const baseDir = path2.dirname(path2.resolve(schemaFile));
2390
2541
  const baseDirUrlPath = new URL(`file://${baseDir}`).pathname;
@@ -2560,23 +2711,13 @@ async function runPull(options) {
2560
2711
  }
2561
2712
  return;
2562
2713
  }
2563
- originalField.attributes.filter((attr) => !f.attributes.find((d) => d.decl.$refText === attr.decl.$refText) && ![
2564
- "@map",
2565
- "@@map",
2566
- "@default",
2567
- "@updatedAt"
2568
- ].includes(attr.decl.$refText)).forEach((attr) => {
2714
+ originalField.attributes.filter((attr) => !f.attributes.find((d) => d.decl.$refText === attr.decl.$refText) && isDatabaseManagedAttribute(attr.decl.$refText)).forEach((attr) => {
2569
2715
  const field = attr.$container;
2570
2716
  const index = field.attributes.findIndex((d) => d === attr);
2571
2717
  field.attributes.splice(index, 1);
2572
2718
  getModelChanges(originalDataModel.name).deletedAttributes.push(colors4.yellow(`- ${attr.decl.$refText} from field: ${originalDataModel.name}.${field.name}`));
2573
2719
  });
2574
- f.attributes.filter((attr) => !originalField.attributes.find((d) => d.decl.$refText === attr.decl.$refText) && ![
2575
- "@map",
2576
- "@@map",
2577
- "@default",
2578
- "@updatedAt"
2579
- ].includes(attr.decl.$refText)).forEach((attr) => {
2720
+ f.attributes.filter((attr) => !originalField.attributes.find((d) => d.decl.$refText === attr.decl.$refText) && isDatabaseManagedAttribute(attr.decl.$refText)).forEach((attr) => {
2580
2721
  const cloned = {
2581
2722
  ...attr,
2582
2723
  $container: originalField
@@ -2674,8 +2815,8 @@ async function runPull(options) {
2674
2815
  });
2675
2816
  }
2676
2817
  const generator = new ZModelCodeGenerator({
2677
- quote: options.quote,
2678
- indent: options.indent
2818
+ quote: options.quote ?? "single",
2819
+ indent: options.indent ?? 4
2679
2820
  });
2680
2821
  if (options.output) {
2681
2822
  if (treatAsFile) {
@@ -2812,7 +2953,13 @@ var plugin2 = {
2812
2953
  var typescript_default = plugin2;
2813
2954
 
2814
2955
  // src/actions/generate.ts
2956
+ import semver from "semver";
2815
2957
  async function run4(options) {
2958
+ try {
2959
+ await checkForMismatchedPackages(process.cwd());
2960
+ } catch (err) {
2961
+ console.warn(colors6.yellow(`Failed to check for mismatched ZenStack packages: ${err}`));
2962
+ }
2816
2963
  const model = await pureGenerate(options, false);
2817
2964
  if (options.watch) {
2818
2965
  const logsEnabled = !options.silent;
@@ -3064,13 +3211,46 @@ async function loadPluginModule(provider, basePath) {
3064
3211
  }
3065
3212
  }
3066
3213
  __name(loadPluginModule, "loadPluginModule");
3214
+ async function checkForMismatchedPackages(projectPath) {
3215
+ const packages = await getZenStackPackages(projectPath);
3216
+ if (!packages.length) {
3217
+ return false;
3218
+ }
3219
+ const versions = /* @__PURE__ */ new Set();
3220
+ for (const { version: version2 } of packages) {
3221
+ if (version2) {
3222
+ versions.add(version2);
3223
+ }
3224
+ }
3225
+ if (versions.size > 1) {
3226
+ const message = "WARNING: Multiple versions of ZenStack packages detected.\n This will probably cause issues and break your types.";
3227
+ const slashes = "/".repeat(73);
3228
+ const latestVersion = semver.sort(Array.from(versions)).reverse()[0];
3229
+ console.warn(colors6.yellow(`${slashes}
3230
+
3231
+ ${message}
3232
+ `));
3233
+ for (const { pkg, version: version2 } of packages) {
3234
+ if (!version2) continue;
3235
+ if (version2 === latestVersion) {
3236
+ console.log(` ${pkg.padEnd(32)} ${colors6.green(version2)}`);
3237
+ } else {
3238
+ console.log(` ${pkg.padEnd(32)} ${colors6.yellow(version2)}`);
3239
+ }
3240
+ }
3241
+ console.warn(`
3242
+ ${colors6.yellow(slashes)}`);
3243
+ return true;
3244
+ }
3245
+ return false;
3246
+ }
3247
+ __name(checkForMismatchedPackages, "checkForMismatchedPackages");
3067
3248
 
3068
3249
  // src/actions/info.ts
3069
3250
  import colors7 from "colors";
3070
- import path6 from "path";
3071
3251
  async function run5(projectPath) {
3072
3252
  const packages = await getZenStackPackages(projectPath);
3073
- if (!packages) {
3253
+ if (!packages.length) {
3074
3254
  console.error("Unable to locate package.json. Are you in a valid project directory?");
3075
3255
  return;
3076
3256
  }
@@ -3087,51 +3267,11 @@ async function run5(projectPath) {
3087
3267
  }
3088
3268
  }
3089
3269
  __name(run5, "run");
3090
- async function getZenStackPackages(projectPath) {
3091
- let pkgJson;
3092
- const resolvedPath = path6.resolve(projectPath);
3093
- try {
3094
- pkgJson = (await import(path6.join(resolvedPath, "package.json"), {
3095
- with: {
3096
- type: "json"
3097
- }
3098
- })).default;
3099
- } catch {
3100
- return [];
3101
- }
3102
- const packages = Array.from(new Set([
3103
- ...Object.keys(pkgJson.dependencies ?? {}),
3104
- ...Object.keys(pkgJson.devDependencies ?? {})
3105
- ].filter((p) => p.startsWith("@zenstackhq/") || p === "zenstack"))).sort();
3106
- const result = await Promise.all(packages.map(async (pkg) => {
3107
- try {
3108
- const depPkgJson = (await import(`${pkg}/package.json`, {
3109
- with: {
3110
- type: "json"
3111
- }
3112
- })).default;
3113
- if (depPkgJson.private) {
3114
- return void 0;
3115
- }
3116
- return {
3117
- pkg,
3118
- version: depPkgJson.version
3119
- };
3120
- } catch {
3121
- return {
3122
- pkg,
3123
- version: void 0
3124
- };
3125
- }
3126
- }));
3127
- return result.filter((p) => !!p);
3128
- }
3129
- __name(getZenStackPackages, "getZenStackPackages");
3130
3270
 
3131
3271
  // src/actions/init.ts
3132
3272
  import colors8 from "colors";
3133
3273
  import fs7 from "fs";
3134
- import path7 from "path";
3274
+ import path6 from "path";
3135
3275
  import ora3 from "ora";
3136
3276
  import { detect, resolveCommand } from "package-manager-detector";
3137
3277
 
@@ -3206,11 +3346,11 @@ async function run6(projectPath) {
3206
3346
  }
3207
3347
  }
3208
3348
  const generationFolder = "zenstack";
3209
- if (!fs7.existsSync(path7.join(projectPath, generationFolder))) {
3210
- fs7.mkdirSync(path7.join(projectPath, generationFolder));
3349
+ if (!fs7.existsSync(path6.join(projectPath, generationFolder))) {
3350
+ fs7.mkdirSync(path6.join(projectPath, generationFolder));
3211
3351
  }
3212
- if (!fs7.existsSync(path7.join(projectPath, generationFolder, "schema.zmodel"))) {
3213
- fs7.writeFileSync(path7.join(projectPath, generationFolder, "schema.zmodel"), STARTER_ZMODEL);
3352
+ if (!fs7.existsSync(path6.join(projectPath, generationFolder, "schema.zmodel"))) {
3353
+ fs7.writeFileSync(path6.join(projectPath, generationFolder, "schema.zmodel"), STARTER_ZMODEL);
3214
3354
  } else {
3215
3355
  console.log(colors8.yellow("Schema file already exists. Skipping generation of sample."));
3216
3356
  }
@@ -3222,7 +3362,7 @@ __name(run6, "run");
3222
3362
 
3223
3363
  // src/actions/migrate.ts
3224
3364
  import fs8 from "fs";
3225
- import path8 from "path";
3365
+ import path7 from "path";
3226
3366
 
3227
3367
  // src/actions/seed.ts
3228
3368
  import colors9 from "colors";
@@ -3255,7 +3395,7 @@ __name(run7, "run");
3255
3395
  async function run8(command, options) {
3256
3396
  const schemaFile = getSchemaFile(options.schema);
3257
3397
  await requireDataSourceUrl(schemaFile);
3258
- const prismaSchemaDir = options.migrations ? path8.dirname(options.migrations) : void 0;
3398
+ const prismaSchemaDir = options.migrations ? path7.dirname(options.migrations) : void 0;
3259
3399
  const prismaSchemaFile = await generateTempPrismaSchema(schemaFile, prismaSchemaDir);
3260
3400
  try {
3261
3401
  switch (command) {
@@ -3380,21 +3520,21 @@ import cors from "cors";
3380
3520
  import express from "express";
3381
3521
  import { createJiti as createJiti2 } from "jiti";
3382
3522
  import { createPool as createMysqlPool } from "mysql2";
3383
- import path10 from "path";
3523
+ import path9 from "path";
3384
3524
  import { Pool as PgPool } from "pg";
3385
3525
 
3386
3526
  // src/utils/version-utils.ts
3387
3527
  import colors10 from "colors";
3388
3528
  import fs9 from "fs";
3389
- import path9 from "path";
3529
+ import path8 from "path";
3390
3530
  import { fileURLToPath as fileURLToPath2 } from "url";
3391
- import semver from "semver";
3531
+ import semver2 from "semver";
3392
3532
  var CHECK_VERSION_TIMEOUT = 2e3;
3393
3533
  var VERSION_CHECK_TAG = "next";
3394
3534
  function getVersion() {
3395
3535
  try {
3396
- const _dirname = typeof __dirname !== "undefined" ? __dirname : path9.dirname(fileURLToPath2(import.meta.url));
3397
- return JSON.parse(fs9.readFileSync(path9.join(_dirname, "../package.json"), "utf8")).version;
3536
+ const _dirname = typeof __dirname !== "undefined" ? __dirname : path8.dirname(fileURLToPath2(import.meta.url));
3537
+ return JSON.parse(fs9.readFileSync(path8.join(_dirname, "../package.json"), "utf8")).version;
3398
3538
  } catch {
3399
3539
  return void 0;
3400
3540
  }
@@ -3408,7 +3548,7 @@ async function checkNewVersion() {
3408
3548
  } catch {
3409
3549
  return;
3410
3550
  }
3411
- if (latestVersion && currVersion && semver.gt(latestVersion, currVersion)) {
3551
+ if (latestVersion && currVersion && semver2.gt(latestVersion, currVersion)) {
3412
3552
  console.log(`A newer version ${colors10.cyan(latestVersion)} is available.`);
3413
3553
  }
3414
3554
  }
@@ -3423,7 +3563,7 @@ async function getLatestVersion() {
3423
3563
  if (fetchResult.ok) {
3424
3564
  const data = await fetchResult.json();
3425
3565
  const latestVersion = data?.version;
3426
- if (typeof latestVersion === "string" && semver.valid(latestVersion)) {
3566
+ if (typeof latestVersion === "string" && semver2.valid(latestVersion)) {
3427
3567
  return latestVersion;
3428
3568
  }
3429
3569
  }
@@ -3441,8 +3581,8 @@ async function run9(options) {
3441
3581
  const schemaFile = getSchemaFile(options.schema);
3442
3582
  console.log(colors11.gray(`Loading ZModel schema from: ${schemaFile}`));
3443
3583
  let outputPath = getOutputPath(options, schemaFile);
3444
- if (!path10.isAbsolute(outputPath)) {
3445
- outputPath = path10.resolve(process.cwd(), outputPath);
3584
+ if (!path9.isAbsolute(outputPath)) {
3585
+ outputPath = path9.resolve(process.cwd(), outputPath);
3446
3586
  }
3447
3587
  const model = await loadSchemaDocument(schemaFile);
3448
3588
  const dataSource = model.declarations.find(isDataSource2);
@@ -3457,7 +3597,7 @@ async function run9(options) {
3457
3597
  const provider = getStringLiteral2(dataSource?.fields.find((f) => f.name === "provider")?.value);
3458
3598
  const dialect = createDialect(provider, databaseUrl, outputPath);
3459
3599
  const jiti = createJiti2(import.meta.url);
3460
- const schemaModule = await jiti.import(path10.join(outputPath, "schema"));
3600
+ const schemaModule = await jiti.import(path9.join(outputPath, "schema"));
3461
3601
  const schema = schemaModule.schema;
3462
3602
  const omit = {};
3463
3603
  for (const [modelName, modelDef] of Object.entries(schema.models)) {
@@ -3521,8 +3661,8 @@ function createDialect(provider, databaseUrl, outputPath) {
3521
3661
  let resolvedUrl = databaseUrl.trim();
3522
3662
  if (resolvedUrl.startsWith("file:")) {
3523
3663
  const filePath = resolvedUrl.substring("file:".length);
3524
- if (!path10.isAbsolute(filePath)) {
3525
- resolvedUrl = path10.join(outputPath, filePath);
3664
+ if (!path9.isAbsolute(filePath)) {
3665
+ resolvedUrl = path9.join(outputPath, filePath);
3526
3666
  }
3527
3667
  }
3528
3668
  console.log(colors11.gray(`Connecting to SQLite database at: ${resolvedUrl}`));
@@ -3883,7 +4023,7 @@ Documentation: https://zenstack.dev/docs`).showHelpAfterError().showSuggestionAf
3883
4023
  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));
3884
4024
  const dbCommand = program.command("db").description("Manage your database schema during development");
3885
4025
  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));
3886
- dbCommand.command("pull").description("Introspect your database.").addOption(schemaOption).addOption(noVersionCheckOption).addOption(new Option("-o, --output <path>", "set custom output path for the introspected schema. If a file path is provided, all schemas are merged into that single file. If a directory path is provided, files are written to the directory and imports are kept.")).addOption(new Option("--model-casing <pascal|camel|snake|none>", "set the casing of generated models").default("pascal")).addOption(new Option("--field-casing <pascal|camel|snake|none>", "set the casing of generated fields").default("camel")).addOption(new Option("--always-map", "always add @map and @@map attributes to models and fields").default(false)).addOption(new Option("--quote <double|single>", "set the quote style of generated schema files").default("single")).addOption(new Option("--indent <number>", "set the indentation of the generated schema files").default(4).argParser(parseInt)).action((options) => dbAction("pull", options));
4026
+ dbCommand.command("pull").description("Introspect your database.").addOption(schemaOption).addOption(noVersionCheckOption).addOption(new Option("-o, --output <path>", "set custom output path for the introspected schema. If a file path is provided, all schemas are merged into that single file. If a directory path is provided, files are written to the directory and imports are kept.")).addOption(new Option("--model-casing <pascal|camel|snake|none>", "set the casing of generated models").default("pascal")).addOption(new Option("--field-casing <pascal|camel|snake|none>", "set the casing of generated fields").default("camel")).addOption(new Option("--always-map", "always add @map and @@map attributes to models and fields").default(false)).addOption(new Option("--quote <double|single>", "set the quote style of generated schema files").default("single")).addOption(new Option("--indent <number>", "set the indentation of the generated schema files").default(4)).action((options) => dbAction("pull", options));
3887
4027
  dbCommand.command("seed").description("Seed the database").allowExcessArguments(true).addHelpText("after", `
3888
4028
  Seed script is configured under the "zenstack.seed" field in package.json.
3889
4029
  E.g.: