@spencer-kit/coder-studio 0.4.3 → 0.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.
@@ -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,6 +69,17 @@ 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
+ }
58
83
  var INTERNAL_ENV_KEYS = /* @__PURE__ */ new Set([
59
84
  "CODER_STUDIO_RUNTIME_JSON_PATH",
60
85
  "CODER_STUDIO_SESSION_ID",
@@ -78,6 +103,54 @@ function buildChildProcessEnv(env = process.env) {
78
103
  }
79
104
  return nextEnv;
80
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
+ }
81
154
  function runCommand(command, args, options) {
82
155
  return new Promise((resolve, reject) => {
83
156
  const child = spawn(command, args, {
@@ -106,6 +179,8 @@ async function runUpdateWorker(input = readEnv(), deps) {
106
179
  const logStream = createWriteStream(input.logFilePath, { flags: "a" });
107
180
  const execute = deps?.runCommand ?? runCommand;
108
181
  const childEnv = buildChildProcessEnv(process.env);
182
+ const processId = deps?.processId ?? process.pid;
183
+ const spawnRestartHandoff = deps?.spawnDetachedProcess ?? spawnDetachedProcess;
109
184
  try {
110
185
  await execute(
111
186
  input.npmCommand,
@@ -129,7 +204,7 @@ async function runUpdateWorker(input = readEnv(), deps) {
129
204
  manualCommand: permissionRelated ? buildManualCommand(input) : null,
130
205
  errorSummary: message
131
206
  });
132
- logStream.end();
207
+ await closeLogStream(logStream);
133
208
  return;
134
209
  }
135
210
  await writeState(input.stateFilePath, {
@@ -147,6 +222,44 @@ async function runUpdateWorker(input = readEnv(), deps) {
147
222
  errorSummary: null
148
223
  });
149
224
  try {
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
+ }
150
263
  await execute(input.cliCommand, input.restartArgs, { logStream, env: childEnv });
151
264
  } catch (error) {
152
265
  const message = error instanceof Error ? error.message : String(error);
@@ -165,16 +278,18 @@ async function runUpdateWorker(input = readEnv(), deps) {
165
278
  errorSummary: `new version installed but service restart failed: ${message}`
166
279
  });
167
280
  } finally {
168
- logStream.end();
281
+ await closeLogStream(logStream);
169
282
  }
170
283
  }
171
284
  if (process.env.CODER_STUDIO_UPDATE_STATE_PATH) {
172
- void runUpdateWorker().catch((error) => {
285
+ const run = readWorkerMode(process.env) === RESTART_HANDOFF_MODE ? runRestartHandoff : runUpdateWorker;
286
+ void run().catch((error) => {
173
287
  console.error("[update-worker]", error);
174
288
  process.exitCode = 1;
175
289
  });
176
290
  }
177
291
  export {
292
+ runRestartHandoff,
178
293
  runUpdateWorker
179
294
  };
180
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\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 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 }\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\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 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, 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 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": "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",
6
6
  "names": []
7
7
  }