@spencer-kit/coder-studio 0.4.2 → 0.4.4

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.
@@ -5,12 +5,26 @@ import { spawn } from "node:child_process";
5
5
  import { createWriteStream } from "node:fs";
6
6
  import { mkdir } from "node:fs/promises";
7
7
  import { dirname } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ var RESTART_HANDOFF_MODE = "restart-handoff";
10
+ var DEFAULT_MODE = "install";
11
+ var RESTART_HANDOFF_WAIT_MS = 5e3;
12
+ var WORKER_ENTRY_PATH = fileURLToPath(import.meta.url);
8
13
  async function writeState(filePath, value) {
9
14
  await mkdir(dirname(filePath), { recursive: true });
10
15
  await import("node:fs/promises").then(
11
16
  ({ writeFile }) => writeFile(filePath, JSON.stringify(value, null, 2) + "\n", "utf-8")
12
17
  );
13
18
  }
19
+ function closeLogStream(stream) {
20
+ return new Promise((resolve, reject) => {
21
+ stream.once("error", reject);
22
+ stream.end(() => {
23
+ stream.off("error", reject);
24
+ resolve();
25
+ });
26
+ });
27
+ }
14
28
  function parseJsonArray(value, fallback) {
15
29
  if (!value) {
16
30
  return fallback;
@@ -55,11 +69,93 @@ function buildManualCommand(input) {
55
69
  `${input.cliCommand} ${input.restartArgs.join(" ")}`
56
70
  ].join("\n");
57
71
  }
72
+ function readWorkerMode(env = process.env) {
73
+ return env.CODER_STUDIO_UPDATE_WORKER_MODE === RESTART_HANDOFF_MODE ? RESTART_HANDOFF_MODE : DEFAULT_MODE;
74
+ }
75
+ function readRestartParentPid(env = process.env) {
76
+ const raw = env.CODER_STUDIO_UPDATE_PARENT_PID;
77
+ if (!raw) {
78
+ return null;
79
+ }
80
+ const pid = Number.parseInt(raw, 10);
81
+ return Number.isInteger(pid) && pid > 0 ? pid : null;
82
+ }
83
+ var INTERNAL_ENV_KEYS = /* @__PURE__ */ new Set([
84
+ "CODER_STUDIO_RUNTIME_JSON_PATH",
85
+ "CODER_STUDIO_SESSION_ID",
86
+ "NODE_APP_INSTANCE",
87
+ "NODE_CHANNEL_FD",
88
+ "NODE_CHANNEL_SERIALIZATION_MODE",
89
+ "PM2_INTERACTOR_PROCESSING",
90
+ "PM2_JSON_PROCESSING",
91
+ "PM2_PROGRAMMATIC"
92
+ ]);
93
+ function buildChildProcessEnv(env = process.env) {
94
+ const nextEnv = { ...env };
95
+ for (const key of Object.keys(nextEnv)) {
96
+ if (INTERNAL_ENV_KEYS.has(key)) {
97
+ delete nextEnv[key];
98
+ continue;
99
+ }
100
+ if (key.startsWith("CODER_STUDIO_UPDATE_") || key.startsWith("pm_")) {
101
+ delete nextEnv[key];
102
+ }
103
+ }
104
+ return nextEnv;
105
+ }
106
+ function buildWorkerEnv(input) {
107
+ return {
108
+ CODER_STUDIO_UPDATE_STATE_PATH: input.stateFilePath,
109
+ CODER_STUDIO_UPDATE_LOG_PATH: input.logFilePath,
110
+ CODER_STUDIO_UPDATE_PACKAGE_NAME: input.packageName,
111
+ CODER_STUDIO_UPDATE_TARGET_VERSION: input.targetVersion,
112
+ CODER_STUDIO_UPDATE_CLI_COMMAND: input.cliCommand,
113
+ CODER_STUDIO_UPDATE_CURRENT_VERSION: input.currentVersion,
114
+ CODER_STUDIO_UPDATE_NPM_COMMAND: input.npmCommand,
115
+ CODER_STUDIO_UPDATE_RESTART_ARGS: JSON.stringify(input.restartArgs),
116
+ CODER_STUDIO_UPDATE_INSTALL_ARGS_PREFIX: JSON.stringify(input.installArgsPrefix)
117
+ };
118
+ }
119
+ function spawnDetachedProcess(command, args, env) {
120
+ return new Promise((resolve, reject) => {
121
+ const child = spawn(command, args, {
122
+ detached: true,
123
+ stdio: "ignore",
124
+ env
125
+ });
126
+ child.on("error", reject);
127
+ child.unref();
128
+ resolve();
129
+ });
130
+ }
131
+ var isMissingProcessError = (error) => Boolean(
132
+ error && typeof error === "object" && "code" in error && error.code === "ESRCH"
133
+ );
134
+ async function waitForProcessExit(pid, waitMs = RESTART_HANDOFF_WAIT_MS) {
135
+ const deadline = Date.now() + waitMs;
136
+ while (Date.now() <= deadline) {
137
+ try {
138
+ process.kill(pid, 0);
139
+ } catch (error) {
140
+ if (isMissingProcessError(error)) {
141
+ return;
142
+ }
143
+ throw error;
144
+ }
145
+ const remainingMs = deadline - Date.now();
146
+ if (remainingMs <= 0) {
147
+ break;
148
+ }
149
+ await new Promise((resolve) => {
150
+ setTimeout(resolve, Math.min(100, remainingMs));
151
+ });
152
+ }
153
+ }
58
154
  function runCommand(command, args, options) {
59
155
  return new Promise((resolve, reject) => {
60
156
  const child = spawn(command, args, {
61
157
  stdio: options?.stdio === "ignore" ? "ignore" : "pipe",
62
- env: process.env
158
+ env: options?.env ?? process.env
63
159
  });
64
160
  if (options?.logStream && child.stdout) {
65
161
  child.stdout.pipe(options.logStream, { end: false });
@@ -82,11 +178,14 @@ async function runUpdateWorker(input = readEnv(), deps) {
82
178
  await mkdir(dirname(input.logFilePath), { recursive: true });
83
179
  const logStream = createWriteStream(input.logFilePath, { flags: "a" });
84
180
  const execute = deps?.runCommand ?? runCommand;
181
+ const childEnv = buildChildProcessEnv(process.env);
182
+ const processId = deps?.processId ?? process.pid;
183
+ const spawnRestartHandoff = deps?.spawnDetachedProcess ?? spawnDetachedProcess;
85
184
  try {
86
185
  await execute(
87
186
  input.npmCommand,
88
187
  [...input.installArgsPrefix, `${input.packageName}@${input.targetVersion}`],
89
- { logStream }
188
+ { logStream, env: childEnv }
90
189
  );
91
190
  } catch (error) {
92
191
  const message = error instanceof Error ? error.message : String(error);
@@ -105,7 +204,7 @@ async function runUpdateWorker(input = readEnv(), deps) {
105
204
  manualCommand: permissionRelated ? buildManualCommand(input) : null,
106
205
  errorSummary: message
107
206
  });
108
- logStream.end();
207
+ await closeLogStream(logStream);
109
208
  return;
110
209
  }
111
210
  await writeState(input.stateFilePath, {
@@ -123,7 +222,45 @@ async function runUpdateWorker(input = readEnv(), deps) {
123
222
  errorSummary: null
124
223
  });
125
224
  try {
126
- await execute(input.cliCommand, input.restartArgs, { logStream });
225
+ await spawnRestartHandoff(process.execPath, [WORKER_ENTRY_PATH], {
226
+ ...childEnv,
227
+ ...buildWorkerEnv(input),
228
+ CODER_STUDIO_UPDATE_WORKER_MODE: RESTART_HANDOFF_MODE,
229
+ CODER_STUDIO_UPDATE_PARENT_PID: String(processId)
230
+ });
231
+ } catch (error) {
232
+ const message = error instanceof Error ? error.message : String(error);
233
+ await writeState(input.stateFilePath, {
234
+ version: 1,
235
+ currentVersion: input.currentVersion,
236
+ latestVersion: input.targetVersion,
237
+ availability: "update_available",
238
+ updateStatus: "failed",
239
+ lastCheckedAt: now(),
240
+ targetVersion: input.targetVersion,
241
+ startedAt: now(),
242
+ finishedAt: now(),
243
+ requiresManualStep: true,
244
+ manualCommand: `${input.cliCommand} ${input.restartArgs.join(" ")}`,
245
+ errorSummary: `new version installed but service restart failed: ${message}`
246
+ });
247
+ } finally {
248
+ await closeLogStream(logStream);
249
+ }
250
+ }
251
+ async function runRestartHandoff(input = readEnv(), deps) {
252
+ const now = deps?.now ?? Date.now;
253
+ await mkdir(dirname(input.logFilePath), { recursive: true });
254
+ const logStream = createWriteStream(input.logFilePath, { flags: "a" });
255
+ const execute = deps?.runCommand ?? runCommand;
256
+ const waitForParentExit = deps?.waitForProcessExit ?? waitForProcessExit;
257
+ const childEnv = buildChildProcessEnv(process.env);
258
+ const restartParentPid = deps?.restartParentPid ?? readRestartParentPid(process.env);
259
+ try {
260
+ if (restartParentPid !== null) {
261
+ await waitForParentExit(restartParentPid);
262
+ }
263
+ await execute(input.cliCommand, input.restartArgs, { logStream, env: childEnv });
127
264
  } catch (error) {
128
265
  const message = error instanceof Error ? error.message : String(error);
129
266
  await writeState(input.stateFilePath, {
@@ -141,16 +278,18 @@ async function runUpdateWorker(input = readEnv(), deps) {
141
278
  errorSummary: `new version installed but service restart failed: ${message}`
142
279
  });
143
280
  } finally {
144
- logStream.end();
281
+ await closeLogStream(logStream);
145
282
  }
146
283
  }
147
284
  if (process.env.CODER_STUDIO_UPDATE_STATE_PATH) {
148
- void runUpdateWorker().catch((error) => {
285
+ const run = readWorkerMode(process.env) === RESTART_HANDOFF_MODE ? runRestartHandoff : runUpdateWorker;
286
+ void run().catch((error) => {
149
287
  console.error("[update-worker]", error);
150
288
  process.exitCode = 1;
151
289
  });
152
290
  }
153
291
  export {
292
+ runRestartHandoff,
154
293
  runUpdateWorker
155
294
  };
156
295
  //# sourceMappingURL=update-worker.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/update-worker.ts"],
4
- "sourcesContent": ["import { spawn } from \"node:child_process\";\nimport { createWriteStream } from \"node:fs\";\nimport { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\ninterface UpdateStateSnapshot {\n version: 1;\n currentVersion: string;\n latestVersion: string | null;\n availability: \"unknown\" | \"up_to_date\" | \"update_available\" | \"check_failed\";\n updateStatus:\n | \"idle\"\n | \"checking\"\n | \"installing\"\n | \"restarting\"\n | \"succeeded\"\n | \"failed\"\n | \"manual_required\";\n lastCheckedAt: number | null;\n targetVersion: string | null;\n startedAt: number | null;\n finishedAt: number | null;\n requiresManualStep: boolean;\n manualCommand: string | null;\n errorSummary: string | null;\n}\n\ninterface WorkerEnv {\n stateFilePath: string;\n logFilePath: string;\n packageName: string;\n targetVersion: string;\n cliCommand: string;\n currentVersion: string;\n npmCommand: string;\n restartArgs: string[];\n installArgsPrefix: string[];\n}\n\nasync function writeState(filePath: string, value: UpdateStateSnapshot): Promise<void> {\n await mkdir(dirname(filePath), { recursive: true });\n await import(\"node:fs/promises\").then(({ writeFile }) =>\n writeFile(filePath, JSON.stringify(value, null, 2) + \"\\n\", \"utf-8\")\n );\n}\n\nfunction parseJsonArray(value: string | undefined, fallback: string[]): string[] {\n if (!value) {\n return fallback;\n }\n try {\n const parsed = JSON.parse(value) as unknown;\n if (Array.isArray(parsed) && parsed.every((item) => typeof item === \"string\")) {\n return parsed;\n }\n } catch {}\n return fallback;\n}\n\nfunction readEnv(env = process.env): WorkerEnv {\n const stateFilePath = env.CODER_STUDIO_UPDATE_STATE_PATH;\n const logFilePath = env.CODER_STUDIO_UPDATE_LOG_PATH;\n const packageName = env.CODER_STUDIO_UPDATE_PACKAGE_NAME;\n const targetVersion = env.CODER_STUDIO_UPDATE_TARGET_VERSION;\n const cliCommand = env.CODER_STUDIO_UPDATE_CLI_COMMAND;\n const currentVersion = env.CODER_STUDIO_UPDATE_CURRENT_VERSION;\n if (\n !stateFilePath ||\n !logFilePath ||\n !packageName ||\n !targetVersion ||\n !cliCommand ||\n !currentVersion\n ) {\n throw new Error(\"Missing detached update worker environment\");\n }\n return {\n stateFilePath,\n logFilePath,\n packageName,\n targetVersion,\n cliCommand,\n currentVersion,\n npmCommand: env.CODER_STUDIO_UPDATE_NPM_COMMAND || \"npm\",\n restartArgs: parseJsonArray(env.CODER_STUDIO_UPDATE_RESTART_ARGS, [\"serve\", \"--restart\"]),\n installArgsPrefix: parseJsonArray(env.CODER_STUDIO_UPDATE_INSTALL_ARGS_PREFIX, [\n \"install\",\n \"-g\",\n ]),\n };\n}\n\nfunction buildManualCommand(input: WorkerEnv): string {\n return [\n `${input.npmCommand} ${[...input.installArgsPrefix, `${input.packageName}@${input.targetVersion}`].join(\" \")}`,\n `${input.cliCommand} ${input.restartArgs.join(\" \")}`,\n ].join(\"\\n\");\n}\n\nfunction runCommand(\n command: string,\n args: string[],\n options?: { stdio?: \"ignore\" | \"pipe\"; logStream?: NodeJS.WritableStream }\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: options?.stdio === \"ignore\" ? \"ignore\" : \"pipe\",\n env: process.env,\n });\n\n if (options?.logStream && child.stdout) {\n child.stdout.pipe(options.logStream, { end: false });\n }\n if (options?.logStream && child.stderr) {\n child.stderr.pipe(options.logStream, { end: false });\n }\n\n child.on(\"error\", reject);\n child.on(\"exit\", (code) => {\n if (code === 0) {\n resolve();\n return;\n }\n reject(new Error(`${command} exited with code ${code ?? 1}`));\n });\n });\n}\n\nexport async function runUpdateWorker(\n input = readEnv(),\n deps?: {\n runCommand?: typeof runCommand;\n now?: () => number;\n }\n): Promise<void> {\n const now = deps?.now ?? Date.now;\n await mkdir(dirname(input.logFilePath), { recursive: true });\n const logStream = createWriteStream(input.logFilePath, { flags: \"a\" });\n const execute = deps?.runCommand ?? runCommand;\n\n try {\n await execute(\n input.npmCommand,\n [...input.installArgsPrefix, `${input.packageName}@${input.targetVersion}`],\n { logStream }\n );\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const permissionRelated =\n /EACCES|EPERM|permission|not permitted/i.test(message) ||\n /requires elevated privileges/i.test(message);\n await writeState(input.stateFilePath, {\n version: 1,\n currentVersion: input.currentVersion,\n latestVersion: input.targetVersion,\n availability: \"update_available\",\n updateStatus: permissionRelated ? \"manual_required\" : \"failed\",\n lastCheckedAt: now(),\n targetVersion: input.targetVersion,\n startedAt: now(),\n finishedAt: now(),\n requiresManualStep: permissionRelated,\n manualCommand: permissionRelated ? buildManualCommand(input) : null,\n errorSummary: message,\n });\n logStream.end();\n return;\n }\n\n await writeState(input.stateFilePath, {\n version: 1,\n currentVersion: input.currentVersion,\n latestVersion: input.targetVersion,\n availability: \"update_available\",\n updateStatus: \"restarting\",\n lastCheckedAt: now(),\n targetVersion: input.targetVersion,\n startedAt: now(),\n finishedAt: null,\n requiresManualStep: false,\n manualCommand: null,\n errorSummary: null,\n });\n\n try {\n await execute(input.cliCommand, input.restartArgs, { logStream });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n await writeState(input.stateFilePath, {\n version: 1,\n currentVersion: input.currentVersion,\n latestVersion: input.targetVersion,\n availability: \"update_available\",\n updateStatus: \"failed\",\n lastCheckedAt: now(),\n targetVersion: input.targetVersion,\n startedAt: now(),\n finishedAt: now(),\n requiresManualStep: true,\n manualCommand: `${input.cliCommand} ${input.restartArgs.join(\" \")}`,\n errorSummary: `new version installed but service restart failed: ${message}`,\n });\n } finally {\n logStream.end();\n }\n}\n\nif (process.env.CODER_STUDIO_UPDATE_STATE_PATH) {\n void runUpdateWorker().catch((error) => {\n console.error(\"[update-worker]\", error);\n process.exitCode = 1;\n });\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { spawn } from \"node:child_process\";\nimport { createWriteStream } from \"node:fs\";\nimport { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\ninterface UpdateStateSnapshot {\n version: 1;\n currentVersion: string;\n latestVersion: string | null;\n availability: \"unknown\" | \"up_to_date\" | \"update_available\" | \"check_failed\";\n updateStatus:\n | \"idle\"\n | \"checking\"\n | \"installing\"\n | \"restarting\"\n | \"succeeded\"\n | \"failed\"\n | \"manual_required\";\n lastCheckedAt: number | null;\n targetVersion: string | null;\n startedAt: number | null;\n finishedAt: number | null;\n requiresManualStep: boolean;\n manualCommand: string | null;\n errorSummary: string | null;\n}\n\ninterface WorkerEnv {\n stateFilePath: string;\n logFilePath: string;\n packageName: string;\n targetVersion: string;\n cliCommand: string;\n currentVersion: string;\n npmCommand: string;\n restartArgs: string[];\n installArgsPrefix: string[];\n}\n\ntype WorkerMode = \"install\" | \"restart-handoff\";\n\nconst RESTART_HANDOFF_MODE: WorkerMode = \"restart-handoff\";\nconst DEFAULT_MODE: WorkerMode = \"install\";\nconst RESTART_HANDOFF_WAIT_MS = 5_000;\nconst WORKER_ENTRY_PATH = fileURLToPath(import.meta.url);\n\nasync function writeState(filePath: string, value: UpdateStateSnapshot): Promise<void> {\n await mkdir(dirname(filePath), { recursive: true });\n await import(\"node:fs/promises\").then(({ writeFile }) =>\n writeFile(filePath, JSON.stringify(value, null, 2) + \"\\n\", \"utf-8\")\n );\n}\n\nfunction closeLogStream(stream: NodeJS.WritableStream): Promise<void> {\n return new Promise((resolve, reject) => {\n stream.once(\"error\", reject);\n stream.end(() => {\n stream.off(\"error\", reject);\n resolve();\n });\n });\n}\n\nfunction parseJsonArray(value: string | undefined, fallback: string[]): string[] {\n if (!value) {\n return fallback;\n }\n try {\n const parsed = JSON.parse(value) as unknown;\n if (Array.isArray(parsed) && parsed.every((item) => typeof item === \"string\")) {\n return parsed;\n }\n } catch {}\n return fallback;\n}\n\nfunction readEnv(env = process.env): WorkerEnv {\n const stateFilePath = env.CODER_STUDIO_UPDATE_STATE_PATH;\n const logFilePath = env.CODER_STUDIO_UPDATE_LOG_PATH;\n const packageName = env.CODER_STUDIO_UPDATE_PACKAGE_NAME;\n const targetVersion = env.CODER_STUDIO_UPDATE_TARGET_VERSION;\n const cliCommand = env.CODER_STUDIO_UPDATE_CLI_COMMAND;\n const currentVersion = env.CODER_STUDIO_UPDATE_CURRENT_VERSION;\n if (\n !stateFilePath ||\n !logFilePath ||\n !packageName ||\n !targetVersion ||\n !cliCommand ||\n !currentVersion\n ) {\n throw new Error(\"Missing detached update worker environment\");\n }\n return {\n stateFilePath,\n logFilePath,\n packageName,\n targetVersion,\n cliCommand,\n currentVersion,\n npmCommand: env.CODER_STUDIO_UPDATE_NPM_COMMAND || \"npm\",\n restartArgs: parseJsonArray(env.CODER_STUDIO_UPDATE_RESTART_ARGS, [\"serve\", \"--restart\"]),\n installArgsPrefix: parseJsonArray(env.CODER_STUDIO_UPDATE_INSTALL_ARGS_PREFIX, [\n \"install\",\n \"-g\",\n ]),\n };\n}\n\nfunction buildManualCommand(input: WorkerEnv): string {\n return [\n `${input.npmCommand} ${[...input.installArgsPrefix, `${input.packageName}@${input.targetVersion}`].join(\" \")}`,\n `${input.cliCommand} ${input.restartArgs.join(\" \")}`,\n ].join(\"\\n\");\n}\n\nfunction readWorkerMode(env = process.env): WorkerMode {\n return env.CODER_STUDIO_UPDATE_WORKER_MODE === RESTART_HANDOFF_MODE\n ? RESTART_HANDOFF_MODE\n : DEFAULT_MODE;\n}\n\nfunction readRestartParentPid(env = process.env): number | null {\n const raw = env.CODER_STUDIO_UPDATE_PARENT_PID;\n if (!raw) {\n return null;\n }\n\n const pid = Number.parseInt(raw, 10);\n return Number.isInteger(pid) && pid > 0 ? pid : null;\n}\n\nconst INTERNAL_ENV_KEYS = new Set([\n \"CODER_STUDIO_RUNTIME_JSON_PATH\",\n \"CODER_STUDIO_SESSION_ID\",\n \"NODE_APP_INSTANCE\",\n \"NODE_CHANNEL_FD\",\n \"NODE_CHANNEL_SERIALIZATION_MODE\",\n \"PM2_INTERACTOR_PROCESSING\",\n \"PM2_JSON_PROCESSING\",\n \"PM2_PROGRAMMATIC\",\n]);\n\nfunction buildChildProcessEnv(env = process.env): NodeJS.ProcessEnv {\n const nextEnv: NodeJS.ProcessEnv = { ...env };\n\n for (const key of Object.keys(nextEnv)) {\n if (INTERNAL_ENV_KEYS.has(key)) {\n delete nextEnv[key];\n continue;\n }\n\n if (key.startsWith(\"CODER_STUDIO_UPDATE_\") || key.startsWith(\"pm_\")) {\n delete nextEnv[key];\n }\n }\n\n return nextEnv;\n}\n\nfunction buildWorkerEnv(input: WorkerEnv): NodeJS.ProcessEnv {\n return {\n CODER_STUDIO_UPDATE_STATE_PATH: input.stateFilePath,\n CODER_STUDIO_UPDATE_LOG_PATH: input.logFilePath,\n CODER_STUDIO_UPDATE_PACKAGE_NAME: input.packageName,\n CODER_STUDIO_UPDATE_TARGET_VERSION: input.targetVersion,\n CODER_STUDIO_UPDATE_CLI_COMMAND: input.cliCommand,\n CODER_STUDIO_UPDATE_CURRENT_VERSION: input.currentVersion,\n CODER_STUDIO_UPDATE_NPM_COMMAND: input.npmCommand,\n CODER_STUDIO_UPDATE_RESTART_ARGS: JSON.stringify(input.restartArgs),\n CODER_STUDIO_UPDATE_INSTALL_ARGS_PREFIX: JSON.stringify(input.installArgsPrefix),\n };\n}\n\nfunction spawnDetachedProcess(\n command: string,\n args: string[],\n env: NodeJS.ProcessEnv\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n detached: true,\n stdio: \"ignore\",\n env,\n });\n\n child.on(\"error\", reject);\n child.unref();\n resolve();\n });\n}\n\nconst isMissingProcessError = (error: unknown): boolean =>\n Boolean(\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n (error as NodeJS.ErrnoException).code === \"ESRCH\"\n );\n\nasync function waitForProcessExit(pid: number, waitMs = RESTART_HANDOFF_WAIT_MS): Promise<void> {\n const deadline = Date.now() + waitMs;\n\n while (Date.now() <= deadline) {\n try {\n process.kill(pid, 0);\n } catch (error) {\n if (isMissingProcessError(error)) {\n return;\n }\n\n throw error;\n }\n\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) {\n break;\n }\n\n await new Promise((resolve) => {\n setTimeout(resolve, Math.min(100, remainingMs));\n });\n }\n}\n\nfunction runCommand(\n command: string,\n args: string[],\n options?: {\n stdio?: \"ignore\" | \"pipe\";\n logStream?: NodeJS.WritableStream;\n env?: NodeJS.ProcessEnv;\n }\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: options?.stdio === \"ignore\" ? \"ignore\" : \"pipe\",\n env: options?.env ?? process.env,\n });\n\n if (options?.logStream && child.stdout) {\n child.stdout.pipe(options.logStream, { end: false });\n }\n if (options?.logStream && child.stderr) {\n child.stderr.pipe(options.logStream, { end: false });\n }\n\n child.on(\"error\", reject);\n child.on(\"exit\", (code) => {\n if (code === 0) {\n resolve();\n return;\n }\n reject(new Error(`${command} exited with code ${code ?? 1}`));\n });\n });\n}\n\nexport async function runUpdateWorker(\n input = readEnv(),\n deps?: {\n runCommand?: typeof runCommand;\n now?: () => number;\n processId?: number;\n spawnDetachedProcess?: typeof spawnDetachedProcess;\n }\n): Promise<void> {\n const now = deps?.now ?? Date.now;\n await mkdir(dirname(input.logFilePath), { recursive: true });\n const logStream = createWriteStream(input.logFilePath, { flags: \"a\" });\n const execute = deps?.runCommand ?? runCommand;\n const childEnv = buildChildProcessEnv(process.env);\n const processId = deps?.processId ?? process.pid;\n const spawnRestartHandoff = deps?.spawnDetachedProcess ?? spawnDetachedProcess;\n\n try {\n await execute(\n input.npmCommand,\n [...input.installArgsPrefix, `${input.packageName}@${input.targetVersion}`],\n { logStream, env: childEnv }\n );\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const permissionRelated =\n /EACCES|EPERM|permission|not permitted/i.test(message) ||\n /requires elevated privileges/i.test(message);\n await writeState(input.stateFilePath, {\n version: 1,\n currentVersion: input.currentVersion,\n latestVersion: input.targetVersion,\n availability: \"update_available\",\n updateStatus: permissionRelated ? \"manual_required\" : \"failed\",\n lastCheckedAt: now(),\n targetVersion: input.targetVersion,\n startedAt: now(),\n finishedAt: now(),\n requiresManualStep: permissionRelated,\n manualCommand: permissionRelated ? buildManualCommand(input) : null,\n errorSummary: message,\n });\n await closeLogStream(logStream);\n return;\n }\n\n await writeState(input.stateFilePath, {\n version: 1,\n currentVersion: input.currentVersion,\n latestVersion: input.targetVersion,\n availability: \"update_available\",\n updateStatus: \"restarting\",\n lastCheckedAt: now(),\n targetVersion: input.targetVersion,\n startedAt: now(),\n finishedAt: null,\n requiresManualStep: false,\n manualCommand: null,\n errorSummary: null,\n });\n\n try {\n await spawnRestartHandoff(process.execPath, [WORKER_ENTRY_PATH], {\n ...childEnv,\n ...buildWorkerEnv(input),\n CODER_STUDIO_UPDATE_WORKER_MODE: RESTART_HANDOFF_MODE,\n CODER_STUDIO_UPDATE_PARENT_PID: String(processId),\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n await writeState(input.stateFilePath, {\n version: 1,\n currentVersion: input.currentVersion,\n latestVersion: input.targetVersion,\n availability: \"update_available\",\n updateStatus: \"failed\",\n lastCheckedAt: now(),\n targetVersion: input.targetVersion,\n startedAt: now(),\n finishedAt: now(),\n requiresManualStep: true,\n manualCommand: `${input.cliCommand} ${input.restartArgs.join(\" \")}`,\n errorSummary: `new version installed but service restart failed: ${message}`,\n });\n } finally {\n await closeLogStream(logStream);\n }\n}\n\nexport async function runRestartHandoff(\n input = readEnv(),\n deps?: {\n runCommand?: typeof runCommand;\n now?: () => number;\n waitForProcessExit?: typeof waitForProcessExit;\n restartParentPid?: number | null;\n }\n): Promise<void> {\n const now = deps?.now ?? Date.now;\n await mkdir(dirname(input.logFilePath), { recursive: true });\n const logStream = createWriteStream(input.logFilePath, { flags: \"a\" });\n const execute = deps?.runCommand ?? runCommand;\n const waitForParentExit = deps?.waitForProcessExit ?? waitForProcessExit;\n const childEnv = buildChildProcessEnv(process.env);\n const restartParentPid = deps?.restartParentPid ?? readRestartParentPid(process.env);\n\n try {\n if (restartParentPid !== null) {\n await waitForParentExit(restartParentPid);\n }\n\n await execute(input.cliCommand, input.restartArgs, { logStream, env: childEnv });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n await writeState(input.stateFilePath, {\n version: 1,\n currentVersion: input.currentVersion,\n latestVersion: input.targetVersion,\n availability: \"update_available\",\n updateStatus: \"failed\",\n lastCheckedAt: now(),\n targetVersion: input.targetVersion,\n startedAt: now(),\n finishedAt: now(),\n requiresManualStep: true,\n manualCommand: `${input.cliCommand} ${input.restartArgs.join(\" \")}`,\n errorSummary: `new version installed but service restart failed: ${message}`,\n });\n } finally {\n await closeLogStream(logStream);\n }\n}\n\nif (process.env.CODER_STUDIO_UPDATE_STATE_PATH) {\n const run =\n readWorkerMode(process.env) === RESTART_HANDOFF_MODE ? runRestartHandoff : runUpdateWorker;\n\n void run().catch((error) => {\n console.error(\"[update-worker]\", error);\n process.exitCode = 1;\n });\n}\n"],
5
+ "mappings": ";;;AAAA,SAAS,aAAa;AACtB,SAAS,yBAAyB;AAClC,SAAS,aAAa;AACtB,SAAS,eAAe;AACxB,SAAS,qBAAqB;AAsC9B,IAAM,uBAAmC;AACzC,IAAM,eAA2B;AACjC,IAAM,0BAA0B;AAChC,IAAM,oBAAoB,cAAc,YAAY,GAAG;AAEvD,eAAe,WAAW,UAAkB,OAA2C;AACrF,QAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,QAAM,OAAO,kBAAkB,EAAE;AAAA,IAAK,CAAC,EAAE,UAAU,MACjD,UAAU,UAAU,KAAK,UAAU,OAAO,MAAM,CAAC,IAAI,MAAM,OAAO;AAAA,EACpE;AACF;AAEA,SAAS,eAAe,QAA8C;AACpE,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,WAAO,KAAK,SAAS,MAAM;AAC3B,WAAO,IAAI,MAAM;AACf,aAAO,IAAI,SAAS,MAAM;AAC1B,cAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;AAEA,SAAS,eAAe,OAA2B,UAA8B;AAC/E,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,QAAI,MAAM,QAAQ,MAAM,KAAK,OAAO,MAAM,CAAC,SAAS,OAAO,SAAS,QAAQ,GAAG;AAC7E,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAAC;AACT,SAAO;AACT;AAEA,SAAS,QAAQ,MAAM,QAAQ,KAAgB;AAC7C,QAAM,gBAAgB,IAAI;AAC1B,QAAM,cAAc,IAAI;AACxB,QAAM,cAAc,IAAI;AACxB,QAAM,gBAAgB,IAAI;AAC1B,QAAM,aAAa,IAAI;AACvB,QAAM,iBAAiB,IAAI;AAC3B,MACE,CAAC,iBACD,CAAC,eACD,CAAC,eACD,CAAC,iBACD,CAAC,cACD,CAAC,gBACD;AACA,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,IAAI,mCAAmC;AAAA,IACnD,aAAa,eAAe,IAAI,kCAAkC,CAAC,SAAS,WAAW,CAAC;AAAA,IACxF,mBAAmB,eAAe,IAAI,yCAAyC;AAAA,MAC7E;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,SAAS,mBAAmB,OAA0B;AACpD,SAAO;AAAA,IACL,GAAG,MAAM,UAAU,IAAI,CAAC,GAAG,MAAM,mBAAmB,GAAG,MAAM,WAAW,IAAI,MAAM,aAAa,EAAE,EAAE,KAAK,GAAG,CAAC;AAAA,IAC5G,GAAG,MAAM,UAAU,IAAI,MAAM,YAAY,KAAK,GAAG,CAAC;AAAA,EACpD,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,eAAe,MAAM,QAAQ,KAAiB;AACrD,SAAO,IAAI,oCAAoC,uBAC3C,uBACA;AACN;AAEA,SAAS,qBAAqB,MAAM,QAAQ,KAAoB;AAC9D,QAAM,MAAM,IAAI;AAChB,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,OAAO,SAAS,KAAK,EAAE;AACnC,SAAO,OAAO,UAAU,GAAG,KAAK,MAAM,IAAI,MAAM;AAClD;AAEA,IAAM,oBAAoB,oBAAI,IAAI;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,qBAAqB,MAAM,QAAQ,KAAwB;AAClE,QAAM,UAA6B,EAAE,GAAG,IAAI;AAE5C,aAAW,OAAO,OAAO,KAAK,OAAO,GAAG;AACtC,QAAI,kBAAkB,IAAI,GAAG,GAAG;AAC9B,aAAO,QAAQ,GAAG;AAClB;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,sBAAsB,KAAK,IAAI,WAAW,KAAK,GAAG;AACnE,aAAO,QAAQ,GAAG;AAAA,IACpB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,OAAqC;AAC3D,SAAO;AAAA,IACL,gCAAgC,MAAM;AAAA,IACtC,8BAA8B,MAAM;AAAA,IACpC,kCAAkC,MAAM;AAAA,IACxC,oCAAoC,MAAM;AAAA,IAC1C,iCAAiC,MAAM;AAAA,IACvC,qCAAqC,MAAM;AAAA,IAC3C,iCAAiC,MAAM;AAAA,IACvC,kCAAkC,KAAK,UAAU,MAAM,WAAW;AAAA,IAClE,yCAAyC,KAAK,UAAU,MAAM,iBAAiB;AAAA,EACjF;AACF;AAEA,SAAS,qBACP,SACA,MACA,KACe;AACf,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,QAAQ,MAAM,SAAS,MAAM;AAAA,MACjC,UAAU;AAAA,MACV,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AAED,UAAM,GAAG,SAAS,MAAM;AACxB,UAAM,MAAM;AACZ,YAAQ;AAAA,EACV,CAAC;AACH;AAEA,IAAM,wBAAwB,CAAC,UAC7B;AAAA,EACE,SACE,OAAO,UAAU,YACjB,UAAU,SACT,MAAgC,SAAS;AAC9C;AAEF,eAAe,mBAAmB,KAAa,SAAS,yBAAwC;AAC9F,QAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,SAAO,KAAK,IAAI,KAAK,UAAU;AAC7B,QAAI;AACF,cAAQ,KAAK,KAAK,CAAC;AAAA,IACrB,SAAS,OAAO;AACd,UAAI,sBAAsB,KAAK,GAAG;AAChC;AAAA,MACF;AAEA,YAAM;AAAA,IACR;AAEA,UAAM,cAAc,WAAW,KAAK,IAAI;AACxC,QAAI,eAAe,GAAG;AACpB;AAAA,IACF;AAEA,UAAM,IAAI,QAAQ,CAAC,YAAY;AAC7B,iBAAW,SAAS,KAAK,IAAI,KAAK,WAAW,CAAC;AAAA,IAChD,CAAC;AAAA,EACH;AACF;AAEA,SAAS,WACP,SACA,MACA,SAKe;AACf,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,QAAQ,MAAM,SAAS,MAAM;AAAA,MACjC,OAAO,SAAS,UAAU,WAAW,WAAW;AAAA,MAChD,KAAK,SAAS,OAAO,QAAQ;AAAA,IAC/B,CAAC;AAED,QAAI,SAAS,aAAa,MAAM,QAAQ;AACtC,YAAM,OAAO,KAAK,QAAQ,WAAW,EAAE,KAAK,MAAM,CAAC;AAAA,IACrD;AACA,QAAI,SAAS,aAAa,MAAM,QAAQ;AACtC,YAAM,OAAO,KAAK,QAAQ,WAAW,EAAE,KAAK,MAAM,CAAC;AAAA,IACrD;AAEA,UAAM,GAAG,SAAS,MAAM;AACxB,UAAM,GAAG,QAAQ,CAAC,SAAS;AACzB,UAAI,SAAS,GAAG;AACd,gBAAQ;AACR;AAAA,MACF;AACA,aAAO,IAAI,MAAM,GAAG,OAAO,qBAAqB,QAAQ,CAAC,EAAE,CAAC;AAAA,IAC9D,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAsB,gBACpB,QAAQ,QAAQ,GAChB,MAMe;AACf,QAAM,MAAM,MAAM,OAAO,KAAK;AAC9B,QAAM,MAAM,QAAQ,MAAM,WAAW,GAAG,EAAE,WAAW,KAAK,CAAC;AAC3D,QAAM,YAAY,kBAAkB,MAAM,aAAa,EAAE,OAAO,IAAI,CAAC;AACrE,QAAM,UAAU,MAAM,cAAc;AACpC,QAAM,WAAW,qBAAqB,QAAQ,GAAG;AACjD,QAAM,YAAY,MAAM,aAAa,QAAQ;AAC7C,QAAM,sBAAsB,MAAM,wBAAwB;AAE1D,MAAI;AACF,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,CAAC,GAAG,MAAM,mBAAmB,GAAG,MAAM,WAAW,IAAI,MAAM,aAAa,EAAE;AAAA,MAC1E,EAAE,WAAW,KAAK,SAAS;AAAA,IAC7B;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,oBACJ,yCAAyC,KAAK,OAAO,KACrD,gCAAgC,KAAK,OAAO;AAC9C,UAAM,WAAW,MAAM,eAAe;AAAA,MACpC,SAAS;AAAA,MACT,gBAAgB,MAAM;AAAA,MACtB,eAAe,MAAM;AAAA,MACrB,cAAc;AAAA,MACd,cAAc,oBAAoB,oBAAoB;AAAA,MACtD,eAAe,IAAI;AAAA,MACnB,eAAe,MAAM;AAAA,MACrB,WAAW,IAAI;AAAA,MACf,YAAY,IAAI;AAAA,MAChB,oBAAoB;AAAA,MACpB,eAAe,oBAAoB,mBAAmB,KAAK,IAAI;AAAA,MAC/D,cAAc;AAAA,IAChB,CAAC;AACD,UAAM,eAAe,SAAS;AAC9B;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,eAAe;AAAA,IACpC,SAAS;AAAA,IACT,gBAAgB,MAAM;AAAA,IACtB,eAAe,MAAM;AAAA,IACrB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,eAAe,IAAI;AAAA,IACnB,eAAe,MAAM;AAAA,IACrB,WAAW,IAAI;AAAA,IACf,YAAY;AAAA,IACZ,oBAAoB;AAAA,IACpB,eAAe;AAAA,IACf,cAAc;AAAA,EAChB,CAAC;AAED,MAAI;AACF,UAAM,oBAAoB,QAAQ,UAAU,CAAC,iBAAiB,GAAG;AAAA,MAC/D,GAAG;AAAA,MACH,GAAG,eAAe,KAAK;AAAA,MACvB,iCAAiC;AAAA,MACjC,gCAAgC,OAAO,SAAS;AAAA,IAClD,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,WAAW,MAAM,eAAe;AAAA,MACpC,SAAS;AAAA,MACT,gBAAgB,MAAM;AAAA,MACtB,eAAe,MAAM;AAAA,MACrB,cAAc;AAAA,MACd,cAAc;AAAA,MACd,eAAe,IAAI;AAAA,MACnB,eAAe,MAAM;AAAA,MACrB,WAAW,IAAI;AAAA,MACf,YAAY,IAAI;AAAA,MAChB,oBAAoB;AAAA,MACpB,eAAe,GAAG,MAAM,UAAU,IAAI,MAAM,YAAY,KAAK,GAAG,CAAC;AAAA,MACjE,cAAc,qDAAqD,OAAO;AAAA,IAC5E,CAAC;AAAA,EACH,UAAE;AACA,UAAM,eAAe,SAAS;AAAA,EAChC;AACF;AAEA,eAAsB,kBACpB,QAAQ,QAAQ,GAChB,MAMe;AACf,QAAM,MAAM,MAAM,OAAO,KAAK;AAC9B,QAAM,MAAM,QAAQ,MAAM,WAAW,GAAG,EAAE,WAAW,KAAK,CAAC;AAC3D,QAAM,YAAY,kBAAkB,MAAM,aAAa,EAAE,OAAO,IAAI,CAAC;AACrE,QAAM,UAAU,MAAM,cAAc;AACpC,QAAM,oBAAoB,MAAM,sBAAsB;AACtD,QAAM,WAAW,qBAAqB,QAAQ,GAAG;AACjD,QAAM,mBAAmB,MAAM,oBAAoB,qBAAqB,QAAQ,GAAG;AAEnF,MAAI;AACF,QAAI,qBAAqB,MAAM;AAC7B,YAAM,kBAAkB,gBAAgB;AAAA,IAC1C;AAEA,UAAM,QAAQ,MAAM,YAAY,MAAM,aAAa,EAAE,WAAW,KAAK,SAAS,CAAC;AAAA,EACjF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,WAAW,MAAM,eAAe;AAAA,MACpC,SAAS;AAAA,MACT,gBAAgB,MAAM;AAAA,MACtB,eAAe,MAAM;AAAA,MACrB,cAAc;AAAA,MACd,cAAc;AAAA,MACd,eAAe,IAAI;AAAA,MACnB,eAAe,MAAM;AAAA,MACrB,WAAW,IAAI;AAAA,MACf,YAAY,IAAI;AAAA,MAChB,oBAAoB;AAAA,MACpB,eAAe,GAAG,MAAM,UAAU,IAAI,MAAM,YAAY,KAAK,GAAG,CAAC;AAAA,MACjE,cAAc,qDAAqD,OAAO;AAAA,IAC5E,CAAC;AAAA,EACH,UAAE;AACA,UAAM,eAAe,SAAS;AAAA,EAChC;AACF;AAEA,IAAI,QAAQ,IAAI,gCAAgC;AAC9C,QAAM,MACJ,eAAe,QAAQ,GAAG,MAAM,uBAAuB,oBAAoB;AAE7E,OAAK,IAAI,EAAE,MAAM,CAAC,UAAU;AAC1B,YAAQ,MAAM,mBAAmB,KAAK;AACtC,YAAQ,WAAW;AAAA,EACrB,CAAC;AACH;",
6
6
  "names": []
7
7
  }