@isomorph.ai/cli 0.4.0-rc.1 → 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.
|
@@ -11,7 +11,7 @@ import { appRoot, requestResourceName } from "./kit.js";
|
|
|
11
11
|
import { initKit } from "./starter.js";
|
|
12
12
|
import { agentPaths, agentSetup } from "./agent-setup.js";
|
|
13
13
|
import { detachDev, startDev } from "./dev.js";
|
|
14
|
-
import { ensureSdk, LocalRuntime, readDevLock, releaseDevLock, runCommand } from "./local-runtime.js";
|
|
14
|
+
import { endProcess, ensureSdk, LocalRuntime, readDevLock, releaseDevLock, runCommand } from "./local-runtime.js";
|
|
15
15
|
import { CHECKS_FAILED_HINT, checksFailedMessage, runChecks } from "./check.js";
|
|
16
16
|
import { assertDeployReady, companySystemsLine, GovernanceClient, groupGrants, IDENTITY_WORDS, integrationsCatalog, integrationsStatus, renderGrantGroup, renderIntegrationsCatalog, requestIntegrations } from "./integrations.js";
|
|
17
17
|
import { runJob } from "./jobs.js";
|
|
@@ -144,12 +144,14 @@ else {
|
|
|
144
144
|
else if (command === "stop") {
|
|
145
145
|
const runtime = new LocalRuntime(target);
|
|
146
146
|
const lock = await readDevLock(target);
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
147
|
+
// The dev process first (its own shutdown ends what it can), then the
|
|
148
|
+
// children it recorded, then Postgres by its controller: after a
|
|
149
|
+
// terminated dev on Windows, or `dev --detach`, nothing else ends them.
|
|
150
|
+
if (lock && lock.pid !== process.pid)
|
|
151
|
+
await endProcess(lock.pid);
|
|
152
|
+
for (const pid of Object.values(lock?.children ?? {}))
|
|
153
|
+
if (pid && pid !== process.pid)
|
|
154
|
+
await endProcess(pid);
|
|
153
155
|
const stopped = await runtime.stop();
|
|
154
156
|
await releaseDevLock(target);
|
|
155
157
|
emit(summaryEnvelope({ project: runtime.project, stopped: stopped.stopped, volumesRetained: true }));
|
|
@@ -5,7 +5,7 @@ import { join } from "node:path";
|
|
|
5
5
|
import { createForwarder } from "./forwarder.js";
|
|
6
6
|
import { readKitLock } from "./kit.js";
|
|
7
7
|
import { GovernanceClient, ensureLinkedApp, fileDeclaredRequests, IDENTITY_WORDS, renderGrantGroup } from "./integrations.js";
|
|
8
|
-
import { acquireDevLock, allocatePorts, ensureSdk, LocalRuntime, nodePackageCommand, pidAlive, readDevLock, releaseDevLock, runCommand } from "./local-runtime.js";
|
|
8
|
+
import { acquireDevLock, allocatePorts, ensureSdk, LocalRuntime, nodePackageCommand, pidAlive, readDevLock, recordDevChildren, releaseDevLock, runCommand } from "./local-runtime.js";
|
|
9
9
|
import { kitPaths } from "./kit.js";
|
|
10
10
|
import { CliError, safeError } from "./output.js";
|
|
11
11
|
/**
|
|
@@ -76,6 +76,7 @@ export async function startDev(root, options) {
|
|
|
76
76
|
const npm = nodePackageCommand("npm", ["run", "dev"]);
|
|
77
77
|
vite = spawn(npm.command, npm.args, { cwd: root, env: { ...env, ISOMORPH_LOCAL_ORIGIN: origin, ISOMORPH_VITE_PORT: String(ports.vite) }, stdio: ["ignore", "inherit", "inherit"] });
|
|
78
78
|
vite.on("error", () => options.output("Vite could not be started; is npm installed and `npm install` done?"));
|
|
79
|
+
await recordDevChildren(root, { ...(vite.pid ? { vite: vite.pid } : {}), ...(runtime.gatewayPid ? { gateway: runtime.gatewayPid } : {}) });
|
|
79
80
|
const company = options.company;
|
|
80
81
|
let warnedAuth = false;
|
|
81
82
|
let lockAppId = (await readKitLock(root))?.appId || undefined;
|
|
@@ -133,6 +133,28 @@ export async function readDevLock(root) {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
export async function releaseDevLock(root) { await rm(kitPaths(root).devLock, { force: true }); }
|
|
136
|
+
/** Records the child processes of a running dev session in its lock (see `DevLock.children`). */
|
|
137
|
+
export async function recordDevChildren(root, children) {
|
|
138
|
+
const lock = await readDevLock(root);
|
|
139
|
+
if (!lock)
|
|
140
|
+
return;
|
|
141
|
+
await writeFile(kitPaths(root).devLock, JSON.stringify({ ...lock, children: { ...lock.children, ...children } }));
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Ends a process this CLI started from another process: SIGTERM where a signal
|
|
145
|
+
* reaches a shutdown handler, `taskkill /t` on Windows where it does not and
|
|
146
|
+
* the process tree (npm → vite → esbuild) would otherwise survive.
|
|
147
|
+
*/
|
|
148
|
+
export async function endProcess(pid, platform = process.platform) {
|
|
149
|
+
if (platform === "win32") {
|
|
150
|
+
await runWindowsController("taskkill", ["/pid", String(pid), "/f", "/t"]);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
process.kill(pid, "SIGTERM");
|
|
155
|
+
}
|
|
156
|
+
catch { /* already gone */ }
|
|
157
|
+
}
|
|
136
158
|
/** The running dev origin for this app, if its lock holder is alive. */
|
|
137
159
|
export async function runningOrigin(root, isAlive = pidAlive) {
|
|
138
160
|
const lock = await readDevLock(root);
|
|
@@ -162,6 +184,8 @@ export class LocalRuntime {
|
|
|
162
184
|
this.run = run;
|
|
163
185
|
this.project = project;
|
|
164
186
|
}
|
|
187
|
+
/** The App Gateway process this runtime started, for the dev lock. */
|
|
188
|
+
get gatewayPid() { return this.gateway?.pid; }
|
|
165
189
|
async writeFiles(bundle, ports) {
|
|
166
190
|
const paths = kitPaths(this.root);
|
|
167
191
|
await mkdir(paths.state, { recursive: true });
|
|
@@ -270,11 +294,22 @@ export class LocalRuntime {
|
|
|
270
294
|
this.gateway?.kill("SIGTERM");
|
|
271
295
|
for (const child of this.gates.values())
|
|
272
296
|
child.kill("SIGTERM");
|
|
297
|
+
const dataDir = join(kitPaths(this.root).state, "postgres");
|
|
273
298
|
if (this.windowsPgCtl) {
|
|
274
|
-
await runWindowsController(this.windowsPgCtl, ["stop", "-w", "-D",
|
|
299
|
+
await runWindowsController(this.windowsPgCtl, ["stop", "-w", "-D", dataDir, "-m", "fast"]);
|
|
300
|
+
}
|
|
301
|
+
else if (this.postgres) {
|
|
302
|
+
await this.postgres.stop().catch(() => undefined);
|
|
275
303
|
}
|
|
276
|
-
else {
|
|
277
|
-
|
|
304
|
+
else if (await exists(join(dataDir, "postmaster.pid"))) {
|
|
305
|
+
// A fresh process (`isomorph stop` after `dev --detach`, or after a
|
|
306
|
+
// terminated dev on Windows) owns no Postgres handle: the bundled
|
|
307
|
+
// controller stops the server the data directory says is running.
|
|
308
|
+
try {
|
|
309
|
+
const { pg_ctl } = await hydrateEmbeddedPostgres(this.run);
|
|
310
|
+
await this.run(pg_ctl, ["stop", "-w", "-D", dataDir, "-m", "fast"], { quiet: true });
|
|
311
|
+
}
|
|
312
|
+
catch { /* no controller for this platform: nothing more to stop */ }
|
|
278
313
|
}
|
|
279
314
|
return true;
|
|
280
315
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = "0.4.0
|
|
1
|
+
export const CLI_VERSION = "0.4.0";
|