@montytools/cli 0.2.1 → 0.2.2

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.
Files changed (2) hide show
  1. package/bin/monty.mjs +42 -0
  2. package/package.json +1 -1
package/bin/monty.mjs CHANGED
@@ -376,6 +376,7 @@ function installDeps() {
376
376
  const pm = spawnSync("pnpm", ["--version"], { stdio: "ignore" }).status === 0 ? "pnpm" : "npm";
377
377
  run(appDir, "install", [pm, "install"],
378
378
  "Dependency install failed. Read the package manager error above; usually network or a bad package.json edit.");
379
+ ensureSdk(appDir);
379
380
  }
380
381
 
381
382
  function buildApp() {
@@ -420,6 +421,45 @@ async function freePort(start) {
420
421
  fail("NO_FREE_PORT", `No free port between ${start} and ${start + 49}. Pass --port <n>.`);
421
422
  }
422
423
 
424
+
425
+ // Apps pin @montytools/sdk at scaffold time and go stale — the CLI knows the
426
+ // minimum SDK its workflows need (e.g. tunnel-host allowlisting lives in the
427
+ // SDK's vite plugin) and upgrades the app automatically before dev/deploy.
428
+ const MIN_SDK = "0.1.1";
429
+
430
+ function installedSdkVersion(appDir) {
431
+ try {
432
+ return JSON.parse(
433
+ readFileSync(join(appDir, "node_modules", "@montytools", "sdk", "package.json"), "utf8"),
434
+ ).version;
435
+ } catch {
436
+ return null;
437
+ }
438
+ }
439
+
440
+ function semverLt(a, b) {
441
+ const pa = a.split(".").map(Number);
442
+ const pb = b.split(".").map(Number);
443
+ for (let i = 0; i < 3; i++) {
444
+ if ((pa[i] || 0) < (pb[i] || 0)) return true;
445
+ if ((pa[i] || 0) > (pb[i] || 0)) return false;
446
+ }
447
+ return false;
448
+ }
449
+
450
+ function ensureSdk(appDir) {
451
+ const v = installedSdkVersion(appDir);
452
+ if (v && !semverLt(v, MIN_SDK)) return;
453
+ console.log(
454
+ v
455
+ ? `sdk: installed ${v} < required ${MIN_SDK} — updating @montytools/sdk`
456
+ : "sdk: @montytools/sdk missing — installing",
457
+ );
458
+ const pm = spawnSync("pnpm", ["--version"], { stdio: "ignore" }).status === 0 ? "pnpm" : "npm";
459
+ run(appDir, "sdk-update", [pm, "install", "@montytools/sdk@latest"],
460
+ "Could not update @montytools/sdk. Run the install manually in the app folder, then retry.");
461
+ }
462
+
423
463
  // ── monty dev ──────────────────────────────────────────────────────────────
424
464
  // Development mode: vite locally + a Cloudflare quick tunnel registered as
425
465
  // the app's DEV channel, so workspace admins see the app live (HMR included)
@@ -428,6 +468,7 @@ async function freePort(start) {
428
468
  // clicks Publish in the workspace, this process builds + uploads for real.
429
469
  async function dev() {
430
470
  const appDir = requireAppDir("dev");
471
+ ensureSdk(appDir);
431
472
  const meta = await compileConfig(appDir);
432
473
  const cfg = loadConfig();
433
474
  const host = cfg?.host ?? DEFAULT_HOST;
@@ -711,6 +752,7 @@ async function docs() {
711
752
  // ── monty deploy ───────────────────────────────────────────────────────────
712
753
  async function deploy() {
713
754
  const appDir = requireAppDir("deploy");
755
+ ensureSdk(appDir);
714
756
  if (!rest.includes("--from-dev")) {
715
757
  console.log("note: direct deploy skips workspace review — the usual flow is `monty dev` + the Publish button in the workspace.");
716
758
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@montytools/cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "monty": "./bin/monty.mjs"