cartethyia 2.4.4 → 2.4.5

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 (21) hide show
  1. package/dist/dashboard/assets/{BannedPage-TDue2X0p.js → BannedPage-DUrXpp-X.js} +1 -1
  2. package/dist/dashboard/assets/{CliToolDetailPage-qaHXuiI5.js → CliToolDetailPage-BzGevuql.js} +1 -1
  3. package/dist/dashboard/assets/{CliToolsPage-BFuQBKez.js → CliToolsPage-BaRM_7We.js} +1 -1
  4. package/dist/dashboard/assets/{ConsoleLogPage-vkZBxMVo.js → ConsoleLogPage-AisQzCI1.js} +1 -1
  5. package/dist/dashboard/assets/{CustomizationPage-BhglcqyR.js → CustomizationPage-DqUGcoH0.js} +1 -1
  6. package/dist/dashboard/assets/{HealthEventsModal-DDkHfwpV.js → HealthEventsModal-BNflDm_f.js} +1 -1
  7. package/dist/dashboard/assets/{LoginPage-CeqROJrT.js → LoginPage-DbhTGfhb.js} +1 -1
  8. package/dist/dashboard/assets/{OverviewPage-CRXSAITY.js → OverviewPage-C3NIzsDx.js} +1 -1
  9. package/dist/dashboard/assets/{ProviderDetailPage-cNAD_6uN.js → ProviderDetailPage-BK8i5B5X.js} +1 -1
  10. package/dist/dashboard/assets/{ProvidersPage-Cv5tdxlx.js → ProvidersPage-CvCVgm1e.js} +1 -1
  11. package/dist/dashboard/assets/{ProxyPage-CWvMfzjj.js → ProxyPage-DjabkuzP.js} +1 -1
  12. package/dist/dashboard/assets/{QuotaPage-IYQOOHR4.js → QuotaPage-Dxe0B0iu.js} +1 -1
  13. package/dist/dashboard/assets/{SetupPage-BPDNo3Ek.js → SetupPage-BaD4P_jW.js} +1 -1
  14. package/dist/dashboard/assets/{StudioPage-BE5DJONZ.js → StudioPage-CLP4le3U.js} +1 -1
  15. package/dist/dashboard/assets/{UsagePage-B6LA4ewF.js → UsagePage-Djes-Epy.js} +1 -1
  16. package/dist/dashboard/assets/{entry-DTiWhIY-.js → entry-Cpi0rph1.js} +3 -3
  17. package/dist/dashboard/assets/{index-BA_ni9Ix.js → index-C4hXfAMs.js} +2 -2
  18. package/dist/dashboard/index.html +1 -1
  19. package/package.json +1 -1
  20. package/scripts/cli/cli.ts +45 -40
  21. package/scripts/cli/version.ts +37 -66
@@ -9,7 +9,7 @@ import { MINIMUM_BUN_VERSION, bunVersionAtLeast } from "../shared/env";
9
9
  import { chooseFromMenu, confirmByTyping, confirmStep } from "./menu";
10
10
  import { ensureDrainToken, readPersistedDrainToken } from "./runtime-state";
11
11
  import { createTray } from "./tray";
12
- import { npmUpdate, readInstalledVersion, readLatestPublishedVersion } from "./version";
12
+ import { readInstalledVersion, readLatestPublishedVersion } from "./version";
13
13
  import { renderWordmark } from "./wordmark";
14
14
 
15
15
  process.env.CARTETHYIA_CONFIG_DIR ??= resolveUserConfigDir();
@@ -356,23 +356,22 @@ async function startMenu(): Promise<void> {
356
356
  async () => openUrl(repositoryUrl),
357
357
  async () => {
358
358
  if (upToDate) return;
359
- // npm cannot replace the package directory while a process is running
360
- // from it: on Windows the rename fails with EBUSY and npm exits 14.
361
- // The gateway has to be stopped before the install, not after.
362
- console.log("Stopping the gateway so npm can replace its files…");
359
+ // npm cannot replace this package's directory while this process is
360
+ // running out of it: on Windows the rename fails with EBUSY and npm
361
+ // exits 14. Even with the gateway stopped, the CLI itself is executing
362
+ // from that directory, so an in-process install can never succeed.
363
+ // Print the command and exit, the way 9router does.
363
364
  await shutDown();
364
- const code = await npmUpdate();
365
- if (code !== 0) {
366
- console.log(`Update failed (npm exited ${code}). Restarting the current version.`);
367
- const restored = await startGateway(port, drainToken);
368
- restored.unref();
369
- return;
370
- }
371
- const restarted = await startGateway(port, drainToken);
372
- restarted.unref();
373
- const installed = await readInstalledVersion();
374
- console.log(`Cartethyia updated and restarted on ${installed} at ${dashboardUrl}`);
375
- latestVersion = await readLatestPublishedVersion();
365
+ console.log("");
366
+ console.log(`Update available: ${currentVersion} \u2192 ${latestVersion}`);
367
+ console.log("");
368
+ console.log("Run this now that Cartethyia has stopped:");
369
+ console.log("");
370
+ console.log(` ${updateCommand()}`);
371
+ console.log("");
372
+ running = false;
373
+ process.exitCode = 0;
374
+ return;
376
375
  },
377
376
  async () => {
378
377
  // Start a detached `tray` process that owns the gateway from scratch,
@@ -436,6 +435,11 @@ async function startMenu(): Promise<void> {
436
435
  * connection and the schema is dialect-dependent, so reading the tables from
437
436
  * this process would need a second implementation of both.
438
437
  */
438
+ /** The command an operator runs to update, printed instead of run in-process. */
439
+ function updateCommand(): string {
440
+ return "npm install --global cartethyia@latest --prefer-online";
441
+ }
442
+
439
443
  async function exportBackup(
440
444
  port: number,
441
445
  token: string,
@@ -631,26 +635,20 @@ async function startTray(): Promise<void> {
631
635
  const runUpdate = async (): Promise<void> => {
632
636
  if (busy) return;
633
637
  busy = true;
634
- // npm cannot replace the package directory while a process is running from
635
- // it: on Windows the rename fails with EBUSY and npm exits 14. Stop first.
636
- tray.update("update", "Stopping to update\u2026", false);
637
- const current = gateway;
638
- gateway = null;
639
- if (current) await stopGateway(current, port, drainToken);
640
-
641
- tray.update("update", "Updating Cartethyia\u2026", false);
642
- const code = await npmUpdate();
643
- if (code !== 0) {
644
- gateway = await startGateway(port, drainToken);
645
- busy = false;
646
- tray.update("update", `Update failed (npm ${code}) \u2014 retry`, true);
647
- return;
648
- }
649
- gateway = await startGateway(port, drainToken);
650
- busy = false;
651
- const installed = await readInstalledVersion();
652
- tray.update("update", `Cartethyia ${installed} \u00b7 up to date`, false);
653
- console.log(`Cartethyia updated and restarted on ${installed} at ${dashboardUrl}`);
638
+ // npm cannot replace this package's directory while this process is
639
+ // running out of it: on Windows the rename fails with EBUSY and npm exits
640
+ // 14, and stopping only the gateway is not enough because the tray itself
641
+ // is executing from that directory. Stop everything and print the command.
642
+ const latest = await readLatestPublishedVersion();
643
+ await close();
644
+ console.log("");
645
+ console.log(`Update available: ${currentVersion} \u2192 ${latest ?? "latest"}`);
646
+ console.log("");
647
+ console.log("Run this now that Cartethyia has stopped:");
648
+ console.log("");
649
+ console.log(` ${updateCommand()}`);
650
+ console.log("");
651
+ process.exit(0);
654
652
  };
655
653
 
656
654
  async function handleSelect(id: string): Promise<void> {
@@ -742,9 +740,16 @@ async function main(): Promise<void> {
742
740
  process.exitCode = await stopRunningGateway();
743
741
  return;
744
742
  case "update": {
745
- const code = await npmUpdate();
746
- if (code !== 0) process.exitCode = code;
747
- else console.log("Cartethyia is up to date.");
743
+ // Running the install from here can never work: this process is itself
744
+ // executing out of the package directory npm would have to rename, and on
745
+ // Windows that rename fails with EBUSY. Stop any running gateway and print
746
+ // the command instead.
747
+ process.exitCode = await stopRunningGateway();
748
+ console.log("");
749
+ console.log("Now run:");
750
+ console.log("");
751
+ console.log(` ${updateCommand()}`);
752
+ console.log("");
748
753
  return;
749
754
  }
750
755
  case "--help":
@@ -1,66 +1,37 @@
1
- import { spawn } from "node:child_process";
2
- import { tmpdir } from "node:os";
3
- import { resolvePackagePath } from "../../src/config/package-paths";
4
-
5
- /** Reads the version from the installed package manifest. */
6
- export async function readInstalledVersion(): Promise<string> {
7
- const metadata: unknown = await Bun.file(resolvePackagePath("package.json")).json();
8
- if (
9
- metadata === null ||
10
- typeof metadata !== "object" ||
11
- !("version" in metadata) ||
12
- typeof metadata.version !== "string"
13
- ) {
14
- throw new Error("Cartethyia package version is unavailable");
15
- }
16
- return metadata.version;
17
- }
18
-
19
- /** Asks the npm registry for the newest published version, or null on failure. */
20
- export async function readLatestPublishedVersion(): Promise<string | null> {
21
- try {
22
- const response = await fetch("https://registry.npmjs.org/cartethyia/latest", {
23
- signal: AbortSignal.timeout(4_000),
24
- });
25
- if (!response.ok) return null;
26
- const metadata: unknown = await response.json();
27
- if (
28
- metadata !== null &&
29
- typeof metadata === "object" &&
30
- "version" in metadata &&
31
- typeof metadata.version === "string"
32
- ) {
33
- return metadata.version;
34
- }
35
- return null;
36
- } catch {
37
- return null;
38
- }
39
- }
40
-
41
- /**
42
- * Runs `npm install --global cartethyia@latest`. On Windows npm is a shell
43
- * script, so it has to go through cmd.exe rather than being spawned directly.
44
- */
45
- export function npmUpdate(): Promise<number> {
46
- return new Promise((resolveExit) => {
47
- const command = process.platform === "win32" ? "cmd.exe" : "npm";
48
- const args =
49
- process.platform === "win32"
50
- ? ["/d", "/s", "/c", "npm install --global cartethyia@latest"]
51
- : ["install", "--global", "cartethyia@latest"];
52
- let child;
53
- try {
54
- child = spawn(command, args, { cwd: tmpdir(), stdio: "inherit" });
55
- } catch {
56
- console.error("Could not start npm. Install Node.js with npm, then retry the update.");
57
- resolveExit(1);
58
- return;
59
- }
60
- child.once("error", () => {
61
- console.error("Could not start npm. Install Node.js with npm, then retry the update.");
62
- resolveExit(1);
63
- });
64
- child.once("exit", (code) => resolveExit(code ?? 1));
65
- });
66
- }
1
+ import { resolvePackagePath } from "../../src/config/package-paths";
2
+
3
+ /** Reads the version from the installed package manifest. */
4
+ export async function readInstalledVersion(): Promise<string> {
5
+ const metadata: unknown = await Bun.file(resolvePackagePath("package.json")).json();
6
+ if (
7
+ metadata === null ||
8
+ typeof metadata !== "object" ||
9
+ !("version" in metadata) ||
10
+ typeof metadata.version !== "string"
11
+ ) {
12
+ throw new Error("Cartethyia package version is unavailable");
13
+ }
14
+ return metadata.version;
15
+ }
16
+
17
+ /** Asks the npm registry for the newest published version, or null on failure. */
18
+ export async function readLatestPublishedVersion(): Promise<string | null> {
19
+ try {
20
+ const response = await fetch("https://registry.npmjs.org/cartethyia/latest", {
21
+ signal: AbortSignal.timeout(4_000),
22
+ });
23
+ if (!response.ok) return null;
24
+ const metadata: unknown = await response.json();
25
+ if (
26
+ metadata !== null &&
27
+ typeof metadata === "object" &&
28
+ "version" in metadata &&
29
+ typeof metadata.version === "string"
30
+ ) {
31
+ return metadata.version;
32
+ }
33
+ return null;
34
+ } catch {
35
+ return null;
36
+ }
37
+ }