@jsorm/cli 0.3.3 → 0.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/README.md CHANGED
@@ -74,6 +74,15 @@ The engine lives in `~/.jsorm/engines/v<version>/` (owner-only). Before every ru
74
74
 
75
75
  ---
76
76
 
77
+ ## Environment
78
+
79
+ | Variable | Effect |
80
+ |---|---|
81
+ | `JSORM_NO_UPDATE_CHECK=1` | Skips the update check while an engine is installed (useful in CI) |
82
+ | `JSORM_DEV_ENGINE=1` | Runs the engine built in this repository instead of the signed release. It only works inside a JSORM source checkout whose `engine/target/debug/jsorm` or `engine/target/release/jsorm` exists, and it never runs a binary from `node_modules`. The local engine is not signed or verified, so leave it unset outside monorepo development |
83
+
84
+ ---
85
+
77
86
  ## Requirements
78
87
 
79
88
  - Node.js 22+
package/dist/index.d.mts CHANGED
@@ -1 +1 @@
1
- import "./rolldown-runtime-ClRpJifh.js";
1
+ import "./rolldown-runtime-CPxUEhZH.js";
package/dist/index.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { execFileSync, spawn } from "node:child_process";
3
- import { chmodSync, createReadStream, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
4
- import { dirname, join } from "node:path";
3
+ import { chmodSync, createReadStream, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
4
+ import { dirname, join, resolve, sep } from "node:path";
5
5
  import { homedir } from "node:os";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { createHash, createPublicKey, verify } from "node:crypto";
8
8
  import { Readable } from "node:stream";
9
9
  import { pipeline } from "node:stream/promises";
10
- //#region src/platform.ts
10
+ // src/platform.ts
11
11
  function detectPlatform() {
12
12
  switch (process.platform) {
13
13
  case "linux": return "linux";
@@ -93,8 +93,7 @@ function detectFramework() {
93
93
  }
94
94
  return "none";
95
95
  }
96
- //#endregion
97
- //#region src/version.ts
96
+ // src/version.ts
98
97
  function compareVersions(a, b) {
99
98
  const pa = a.split(".").map(Number);
100
99
  const pb = b.split(".").map(Number);
@@ -115,8 +114,7 @@ function releaseLine(version) {
115
114
  function isCompatibleEngine(cliVersion, engineVersion) {
116
115
  return releaseLine(cliVersion) === releaseLine(engineVersion);
117
116
  }
118
- //#endregion
119
- //#region src/install.ts
117
+ // src/install.ts
120
118
  function getVersionDir(enginesDir, version) {
121
119
  return join(enginesDir, `v${version}`);
122
120
  }
@@ -221,8 +219,44 @@ async function installEngine(options) {
221
219
  });
222
220
  }
223
221
  }
224
- //#endregion
225
- //#region src/manifest.ts
222
+ // src/dev-engine.ts
223
+ /** Binary produced by `cargo build` in `engine/`; not the published, target-suffixed name. */
224
+ const DEV_BINARY = "jsorm";
225
+ const DEV_ROOT_MARKER = join("engine", "Cargo.toml");
226
+ const PROFILES = ["debug", "release"];
227
+ /**
228
+ * Returns the engine compiled in this checkout, or `null`.
229
+ *
230
+ * Development mode is opt-in: it requires `JSORM_DEV_ENGINE=1`, a source
231
+ * checkout of this monorepo, and a regular binary inside `engine/target`.
232
+ * A path that resolves under a `node_modules` directory is never accepted:
233
+ * that directory belongs to the project being built, so an installed CLI
234
+ * must not run an engine taken from it.
235
+ */
236
+ function resolveDevEnginePath({ moduleDir, env = process.env }) {
237
+ if (env.JSORM_DEV_ENGINE !== "1") return null;
238
+ const root = resolve(moduleDir, "..", "..", "..");
239
+ if (root.split(sep).includes("node_modules")) return null;
240
+ if (!existsSync(join(root, DEV_ROOT_MARKER))) return null;
241
+ const targetDir = join(root, "engine", "target");
242
+ for (const profile of PROFILES) {
243
+ const candidate = join(targetDir, profile, DEV_BINARY);
244
+ if (isFileInside(targetDir, candidate)) return candidate;
245
+ }
246
+ return null;
247
+ }
248
+ /** True when `candidate` resolves to a regular file inside `dir`, following symlinks. */
249
+ function isFileInside(dir, candidate) {
250
+ try {
251
+ const realDir = realpathSync(dir);
252
+ const real = realpathSync(candidate);
253
+ if (!statSync(real).isFile()) return false;
254
+ return real.startsWith(realDir.endsWith(sep) ? realDir : `${realDir}${sep}`);
255
+ } catch {
256
+ return false;
257
+ }
258
+ }
259
+ // src/manifest.ts
226
260
  const EMBEDDED_PUBLIC_KEY_B64 = "6AUQMvF7jBV+S8yv9K8hnnoYzIznQw4nf5x5LAuEsfM=";
227
261
  function getSpkiPublicKey(rawKeyB64 = EMBEDDED_PUBLIC_KEY_B64) {
228
262
  const rawKey = Buffer.from(rawKeyB64, "base64");
@@ -296,8 +330,7 @@ async function fetchManifest(url, publicKey = getSpkiPublicKey()) {
296
330
  }
297
331
  return parseSignedEnvelope(envelope, publicKey);
298
332
  }
299
- //#endregion
300
- //#region src/verify.ts
333
+ // src/verify.ts
301
334
  const SHA256_HEX = /^[0-9a-f]{64}$/;
302
335
  /**
303
336
  * Checks an installed engine before it runs: its stored envelope must be
@@ -339,8 +372,7 @@ async function verifyInstalledEngine(enginesDir, version, binaryName, publicKey)
339
372
  };
340
373
  return { ok: true };
341
374
  }
342
- //#endregion
343
- //#region src/resolve.ts
375
+ // src/resolve.ts
344
376
  const DAY_MS = 864e5;
345
377
  const LAST_CHECK_FILE = ".last-check";
346
378
  function readLastCheck(enginesDir) {
@@ -478,8 +510,7 @@ async function checkForUpdate(options) {
478
510
  updateAvailable: latestCompatible && (installed === null || compareVersions(manifest.version, installed) > 0)
479
511
  };
480
512
  }
481
- //#endregion
482
- //#region src/update.ts
513
+ // src/update.ts
483
514
  /**
484
515
  * `jsorm update`: checks the live manifest now, installs the newest
485
516
  * compatible engine (again when `force`), and removes every other installed
@@ -522,8 +553,7 @@ async function reportUpdate(options) {
522
553
  else if (status.updateAvailable) log(` Update available. Run: jsorm update`);
523
554
  else log(` ✓ Up to date`);
524
555
  }
525
- //#endregion
526
- //#region src/index.ts
556
+ // src/index.ts
527
557
  const __filename = fileURLToPath(import.meta.url);
528
558
  const __dirname = dirname(__filename);
529
559
  const ENGINES_DIR = join(homedir(), ".jsorm", "engines");
@@ -537,13 +567,6 @@ function readVersion() {
537
567
  return "unknown";
538
568
  }
539
569
  }
540
- function getLocalDevEnginePath() {
541
- const debug = join(__dirname, "..", "..", "..", "engine", "target", "debug", "jsorm");
542
- if (existsSync(debug)) return debug;
543
- const release = join(__dirname, "..", "..", "..", "engine", "target", "release", "jsorm");
544
- if (existsSync(release)) return release;
545
- return null;
546
- }
547
570
  function executeEngine(enginePath, args) {
548
571
  const engineArgs = [
549
572
  ...args,
@@ -566,16 +589,26 @@ function executeEngine(enginePath, args) {
566
589
  process.exit(code ?? 0);
567
590
  });
568
591
  }
569
- async function main() {
570
- const args = process.argv.slice(2);
571
- if (args.includes("--version") || args.includes("-v") || args.includes("-V")) {
592
+ /** The local engine is unverified by design, so say so before it runs. */
593
+ function runDevEngine(enginePath, args, execute) {
594
+ console.error(` ⚠ JSORM_DEV_ENGINE=1: running the unverified engine at ${enginePath}`);
595
+ execute(enginePath, args);
596
+ }
597
+ async function main(argv = process.argv.slice(2), deps = {}) {
598
+ const env = deps.env ?? process.env;
599
+ const execute = deps.execute ?? executeEngine;
600
+ const enginesDir = deps.enginesDir ?? ENGINES_DIR;
601
+ if (argv.includes("--version") || argv.includes("-v") || argv.includes("-V")) {
572
602
  console.log(readVersion());
573
603
  return;
574
604
  }
575
- if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
576
- const localEnginePath = getLocalDevEnginePath();
577
- if (localEnginePath) {
578
- executeEngine(localEnginePath, args);
605
+ const devEnginePath = resolveDevEnginePath({
606
+ moduleDir: deps.moduleDir ?? __dirname,
607
+ env
608
+ });
609
+ if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
610
+ if (devEnginePath) {
611
+ runDevEngine(devEnginePath, argv, execute);
579
612
  return;
580
613
  }
581
614
  console.log(`jsorm ${readVersion()}`);
@@ -596,45 +629,55 @@ async function main() {
596
629
  console.log();
597
630
  console.log("Environment:");
598
631
  console.log(" JSORM_NO_UPDATE_CHECK=1 Skip engine update checks while an engine is installed");
632
+ console.log(" JSORM_DEV_ENGINE=1 Run the engine built in this checkout (never an installed package)");
599
633
  return;
600
634
  }
601
635
  try {
602
- ensureOwnerOnlyDir(dirname(ENGINES_DIR));
636
+ ensureOwnerOnlyDir(dirname(enginesDir));
603
637
  } catch (err) {
604
- console.error(` ⚠ Could not restrict ${dirname(ENGINES_DIR)}: ${err instanceof Error ? err.message : err}`);
638
+ console.error(` ⚠ Could not restrict ${dirname(enginesDir)}: ${err instanceof Error ? err.message : err}`);
605
639
  }
606
640
  const resolveOptions = {
607
- enginesDir: ENGINES_DIR,
641
+ enginesDir,
608
642
  binaryName: getEngineBinaryName(),
609
643
  manifestUrl: STABLE_MANIFEST_URL,
610
644
  downloadUrl: STABLE_DOWNLOAD_URL,
611
645
  cliVersion: readVersion(),
612
- skipUpdateCheck: process.env.JSORM_NO_UPDATE_CHECK === "1",
646
+ skipUpdateCheck: env.JSORM_NO_UPDATE_CHECK === "1",
613
647
  updateCommand: `${cliRunner(detectPackageManager())} update`,
614
648
  log: console.log
615
649
  };
616
650
  try {
617
- if (args[0] === "update") {
618
- const invalid = validateUpdateArgs(args.slice(1));
651
+ if (argv[0] === "update") {
652
+ const invalid = validateUpdateArgs(argv.slice(1));
619
653
  if (invalid) throw new Error(invalid);
620
- if (args.includes("--check")) await reportUpdate(resolveOptions);
654
+ if (argv.includes("--check")) await reportUpdate(resolveOptions);
621
655
  else await updateEngine({
622
656
  ...resolveOptions,
623
- force: args.includes("--force")
657
+ force: argv.includes("--force")
624
658
  });
625
659
  return;
626
660
  }
627
- const localEnginePath = getLocalDevEnginePath();
628
- if (localEnginePath) {
629
- executeEngine(localEnginePath, args);
661
+ if (devEnginePath) {
662
+ runDevEngine(devEnginePath, argv, execute);
630
663
  return;
631
664
  }
632
- executeEngine(await resolveEngine(resolveOptions), args);
665
+ execute(await resolveEngine(resolveOptions), argv);
633
666
  } catch (err) {
634
667
  console.error(` ✖ ${err instanceof Error ? err.message : err}`);
635
668
  process.exit(1);
636
669
  }
637
670
  }
638
- main();
639
- //#endregion
640
- export {};
671
+ /** True when this module is the executable, not a module imported by a test. */
672
+ function isEntryPoint() {
673
+ const invoked = process.argv[1];
674
+ if (!invoked) return false;
675
+ const self = fileURLToPath(import.meta.url);
676
+ try {
677
+ return resolve(invoked) === resolve(self) || realpathSync(invoked) === realpathSync(self);
678
+ } catch {
679
+ return false;
680
+ }
681
+ }
682
+ if (isEntryPoint()) main();
683
+ export { main };
package/dist/index2.d.mts CHANGED
@@ -1 +1,13 @@
1
- import "./rolldown-runtime-ClRpJifh.js";
1
+ import "./rolldown-runtime-CPxUEhZH.js";
2
+ interface CliDeps {
3
+ /** Environment read for `JSORM_DEV_ENGINE` and the update check. Defaults to `process.env`. */
4
+ env?: NodeJS.ProcessEnv;
5
+ /** Replaced in tests to observe which engine would run. */
6
+ execute?: (enginePath: string, args: string[]) => void;
7
+ /** Directory of this module; defaults to the running file's directory. */
8
+ moduleDir?: string;
9
+ /** Engines directory; defaults to `~/.jsorm/engines`. */
10
+ enginesDir?: string;
11
+ }
12
+ export declare function main(argv?: string[], deps?: CliDeps): Promise<void>;
13
+ export {};
package/package.json CHANGED
@@ -1,8 +1,19 @@
1
1
  {
2
2
  "name": "@jsorm/cli",
3
3
  "type": "module",
4
- "version": "0.3.3",
4
+ "version": "0.4.0",
5
5
  "description": "CLI de JSORM",
6
+ "keywords": [
7
+ "jsorm",
8
+ "orm",
9
+ "cli",
10
+ "codegen",
11
+ "typescript",
12
+ "schema",
13
+ "migrations",
14
+ "postgresql",
15
+ "sqlite"
16
+ ],
6
17
  "license": "MPL-2.0",
7
18
  "repository": {
8
19
  "type": "git",
@@ -12,7 +23,7 @@
12
23
  "bugs": {
13
24
  "url": "https://github.com/jsorm/jsorm-monorepo/issues"
14
25
  },
15
- "homepage": "https://github.com/jsorm/jsorm-monorepo/tree/main/packages/cli#readme",
26
+ "homepage": "https://jsorm.dev",
16
27
  "files": [
17
28
  "dist"
18
29
  ],
@@ -35,14 +46,14 @@
35
46
  "access": "public"
36
47
  },
37
48
  "dependencies": {
38
- "@jsorm/core": "1.3.3"
49
+ "@jsorm/core": "1.4.0"
39
50
  },
40
51
  "devDependencies": {
41
52
  "@types/node": "^26.1.1",
42
- "rolldown": "1.2.3",
43
- "rolldown-plugin-dts": "0.28.0",
44
- "typescript": "6.0.3",
45
- "vitest": "4.1.10"
53
+ "rolldown": "1.2.16",
54
+ "rolldown-plugin-dts": "0.29.0",
55
+ "typescript": "7.0.2",
56
+ "vitest": "5.1.0"
46
57
  },
47
58
  "scripts": {
48
59
  "build": "rm -rf dist/ && rolldown -c rolldown.config.ts && rolldown -c rolldown.dts.config.ts",