workerdeck 2.7.2 → 2.9.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.
@@ -393,7 +393,7 @@ async function loadApnsKey(keyFile) {
393
393
  } catch (error) {
394
394
  throw new Error(`apns: ${keyFile} is not a private key (${error instanceof Error ? error.message : String(error)})`, { cause: error });
395
395
  }
396
- if (key.asymmetricKeyType !== "ec") throw new Error(`apns: ${keyFile} is a ${key.asymmetricKeyType ?? "unknown"} key, not EC — an APNs auth key is the .p8 downloaded from Keys in the developer portal, not a certificate`);
396
+ if (key.asymmetricKeyType !== "ec") throw new Error(`apns: ${keyFile} is a ${key.asymmetricKeyType ?? "unknown"} key, not EC - an APNs auth key is the .p8 downloaded from Keys in the developer portal, not a certificate`);
397
397
  return key;
398
398
  }
399
399
  function createProviderToken(key, keyId, teamId) {
@@ -834,10 +834,10 @@ const COLLAPSE_PREFIX = {
834
834
  };
835
835
  function titleFor(notification, name) {
836
836
  switch (notification.type) {
837
- case "permission_requested": return `Approval needed — ${name}`;
838
- case "turn_completed": return notification.result?.isError === true ? `Turn failed — ${name}` : name;
839
- case "session_error": return `Session error — ${name}`;
840
- case "session_closed": return `Session ended — ${name}`;
837
+ case "permission_requested": return `Approval needed - ${name}`;
838
+ case "turn_completed": return notification.result?.isError === true ? `Turn failed - ${name}` : name;
839
+ case "session_error": return `Session error - ${name}`;
840
+ case "session_closed": return `Session ended - ${name}`;
841
841
  default: return name;
842
842
  }
843
843
  }
@@ -1241,7 +1241,7 @@ async function materializeAuthKey(stateDir, options = {}) {
1241
1241
  if (key !== null) {
1242
1242
  try {
1243
1243
  const { mode } = await stat(path);
1244
- if ((mode & 63) !== 0) warn(`auth key file ${path} is readable by other users (mode ${(mode & 511).toString(8)}) — run: chmod 600 ${path}`);
1244
+ if ((mode & 63) !== 0) warn(`auth key file ${path} is readable by other users (mode ${(mode & 511).toString(8)}) - run: chmod 600 ${path}`);
1245
1245
  } catch {}
1246
1246
  return {
1247
1247
  key,
@@ -1295,7 +1295,7 @@ async function createAuthSessionStore(options) {
1295
1295
  initial = parseSessions(await readFile(path, "utf8"), now());
1296
1296
  try {
1297
1297
  const { mode } = await stat(path);
1298
- if ((mode & 63) !== 0) warn(`session file ${path} is readable by other users (mode ${(mode & 511).toString(8)}) — run: chmod 600 ${path}`);
1298
+ if ((mode & 63) !== 0) warn(`session file ${path} is readable by other users (mode ${(mode & 511).toString(8)}) - run: chmod 600 ${path}`);
1299
1299
  } catch {}
1300
1300
  } catch {
1301
1301
  initial = [];
@@ -1353,7 +1353,7 @@ function sha256(value) {
1353
1353
  function createCliAuth(options = {}) {
1354
1354
  const { secret } = options;
1355
1355
  const enabled = secret !== void 0;
1356
- if (secret !== void 0 && secret.length < MIN_SECRET_LENGTH) throw new Error(`createCliAuth: secret must be at least ${MIN_SECRET_LENGTH} characters — use a long random value, or leave it unset to run without auth on loopback`);
1356
+ if (secret !== void 0 && secret.length < MIN_SECRET_LENGTH) throw new Error(`createCliAuth: secret must be at least ${MIN_SECRET_LENGTH} characters - use a long random value, or leave it unset to run without auth on loopback`);
1357
1357
  const cookieName = options.cookieName ?? DEFAULT_COOKIE_NAME;
1358
1358
  const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
1359
1359
  if (!(ttlMs > 0)) throw new Error("createCliAuth: ttlMs must be positive");
@@ -1666,7 +1666,7 @@ var ConfigError = class extends Error {};
1666
1666
  function parseDuration(raw, source) {
1667
1667
  if (raw === "none" || raw === "never") return null;
1668
1668
  const match = /^(\d+(?:\.\d+)?)(ms|s|m|h)?$/.exec(raw);
1669
- if (!match) throw new ConfigError(`${source}: expected a duration like 300000, 30s, 5m — or 'none'; got: ${raw}`);
1669
+ if (!match) throw new ConfigError(`${source}: expected a duration like 300000, 30s, 5m - or 'none'; got: ${raw}`);
1670
1670
  const scale = {
1671
1671
  ms: 1,
1672
1672
  s: 1e3,
@@ -1803,6 +1803,9 @@ function parseArgs(argv) {
1803
1803
  case "--open":
1804
1804
  flags.open = true;
1805
1805
  break;
1806
+ case "--hot-reload":
1807
+ flags.hotReload = true;
1808
+ break;
1806
1809
  default: throw new ConfigError(`unknown option: ${arg}`);
1807
1810
  }
1808
1811
  }
@@ -1866,7 +1869,7 @@ function normalizeInsecureHost(raw) {
1866
1869
  } catch {
1867
1870
  throw new ConfigError(`not a host name or address in insecureHosts: ${JSON.stringify(raw)}`);
1868
1871
  }
1869
- if (url.port !== "") throw new ConfigError(`insecureHosts entry ${JSON.stringify(raw)} carries a port — name the host alone; the bind host and the Host header are both compared portless`);
1872
+ if (url.port !== "") throw new ConfigError(`insecureHosts entry ${JSON.stringify(raw)} carries a port - name the host alone; the bind host and the Host header are both compared portless`);
1870
1873
  return url.hostname.replace(/^\[|\]$/g, "").toLowerCase();
1871
1874
  }
1872
1875
  function resolveInstanceConfig(flags, loaded, env = process.env, cwd = process.cwd()) {
@@ -2071,11 +2074,9 @@ function lockCommand(pid) {
2071
2074
  }
2072
2075
  function driveWakeLock(source, lock) {
2073
2076
  const sync = () => lock.set(sessionsNeedTheMachine(source.list()));
2074
- source.observe((runner) => {
2075
- runner.subscribe((event) => {
2076
- if (event.type === "status_changed" || event.type === "session_closed" || event.type === "session_error") sync();
2077
- }, runner.info().lastSeq);
2078
- });
2077
+ source.observe((runner) => runner.subscribe((event) => {
2078
+ if (event.type === "status_changed" || event.type === "session_closed" || event.type === "session_error") sync();
2079
+ }, runner.info().lastSeq));
2079
2080
  sync();
2080
2081
  }
2081
2082
  function createWakeLock(options = {}) {
@@ -2284,8 +2285,8 @@ async function startInstance(config, options = {}) {
2284
2285
  ...authOptions,
2285
2286
  sessions
2286
2287
  } : authOptions);
2287
- if (config.allowedHosts === null && !config.hostAuthenticates && !auth.enabled) throw new Error("refusing to serve: the resolved config expects auth but no shared secret was materialized — this instance would be open while believing itself authenticated");
2288
- if (config.corsOrigins.length > 0 && !config.hostAuthenticates && !auth.enabled) throw new Error("refusing to serve: corsOrigins is set but this instance has no auth — a cross-origin page could drive it with no credential. Set --auth-key.");
2288
+ if (config.allowedHosts === null && !config.hostAuthenticates && !auth.enabled) throw new Error("refusing to serve: the resolved config expects auth but no shared secret was materialized - this instance would be open while believing itself authenticated");
2289
+ if (config.corsOrigins.length > 0 && !config.hostAuthenticates && !auth.enabled) throw new Error("refusing to serve: corsOrigins is set but this instance has no auth - a cross-origin page could drive it with no credential. Set --auth-key.");
2289
2290
  const hostAllowed = createHostGuard(config.allowedHosts);
2290
2291
  const authenticateHost = (req) => hostAllowed(req) ? auth.authenticate(req) : null;
2291
2292
  const apns = config.apns === void 0 ? void 0 : await createApnsForwarder({
@@ -2335,7 +2336,16 @@ async function startInstance(config, options = {}) {
2335
2336
  target: apns.activity
2336
2337
  });
2337
2338
  }
2338
- const { port } = await server.listen(config.port, config.host);
2339
+ const adopted = [];
2340
+ for (const carried of options.carried ?? []) if (server.adoptSession(carried)) adopted.push(carried);
2341
+ let port;
2342
+ try {
2343
+ ({port} = await server.listen(config.port, config.host));
2344
+ } catch (error) {
2345
+ for (const carried of adopted) server.releaseSession(carried.runner.id);
2346
+ await server.close();
2347
+ throw error;
2348
+ }
2339
2349
  const displayHost = config.host === "0.0.0.0" || config.host === "::" ? "localhost" : config.host;
2340
2350
  const url = `http://${displayHost.includes(":") ? `[${displayHost}]` : displayHost}:${port}`;
2341
2351
  let resolveClosed = () => {};
@@ -2349,27 +2359,28 @@ async function startInstance(config, options = {}) {
2349
2359
  if (config.hostAuthenticates) line(" auth: the config file supplies its own `authenticate`");
2350
2360
  else if (generated?.source === "created") {
2351
2361
  line(` auth: generated key ${generated.key}`);
2352
- line(` stored in ${generated.path} — later starts reuse it without printing it`);
2362
+ line(` stored in ${generated.path} - later starts reuse it without printing it`);
2353
2363
  } else if (generated?.source === "ephemeral") {
2354
2364
  line(` auth: generated key ${generated.key}`);
2355
- line(" ephemeral — no state dir to keep it, so the next start mints a new one");
2365
+ line(" ephemeral - no state dir to keep it, so the next start mints a new one");
2356
2366
  } else if (generated?.source === "stored") line(` auth: shared key from ${generated.path}`);
2357
- else if (auth.enabled) line(" auth: shared key — browsers sign in, services send a header");
2358
- else line(" NO AUTH — anyone who can reach this port gets a session");
2359
- if (!config.web) line(" dashboard: off — bare gateway, /v1 and /auth only");
2360
- if (!config.keepAwake) line(" keep-awake: off — this machine may sleep mid-turn");
2367
+ else if (auth.enabled) line(" auth: shared key - browsers sign in, services send a header");
2368
+ else line(" NO AUTH - anyone who can reach this port gets a session");
2369
+ if (!config.web) line(" dashboard: off - bare gateway, /v1 and /auth only");
2370
+ if (!config.keepAwake) line(" keep-awake: off - this machine may sleep mid-turn");
2361
2371
  if (config.corsOrigins.length) line(` cors: ${config.corsOrigins.join(", ")} may call /v1 (still key-gated)`);
2362
- line(config.stateDir ? ` parked sessions persist in ${join(config.stateDir, "parked")}` : " parked sessions are in memory only — a restart drops them");
2372
+ line(config.stateDir ? ` parked sessions persist in ${join(config.stateDir, "parked")}` : " parked sessions are in memory only - a restart drops them");
2363
2373
  if (apns) {
2364
2374
  const count = apns.deviceCount();
2365
2375
  const cards = apns.activity.count();
2366
- line(` push: APNs forwarder on ${config.apns?.topic} — ${count === 0 ? "no devices registered yet" : `${count} device(s)`}${cards === 0 ? "" : `, ${cards} live card(s)`}`);
2376
+ line(` push: APNs forwarder on ${config.apns?.topic} - ${count === 0 ? "no devices registered yet" : `${count} device(s)`}${cards === 0 ? "" : `, ${cards} live card(s)`}`);
2367
2377
  }
2368
2378
  if (config.configPath) line(` config ${config.configPath}`);
2369
2379
  line("");
2370
2380
  }
2371
2381
  return {
2372
2382
  server,
2383
+ adopted: adopted.map((carried) => carried.runner.id),
2373
2384
  url,
2374
2385
  port,
2375
2386
  closed,
@@ -2389,4 +2400,4 @@ async function startInstance(config, options = {}) {
2389
2400
  //#endregion
2390
2401
  export { createActivityRegistry as C, createDeviceRoute as S, createApnsForwarder as _, ConfigError as a, createApnsRoute as b, isLoopback as c, parseArgs as d, resolveInstanceConfig as f, buildPush as g, materializeAuthKey as h, renderLoginPage as i, isLoopbackHostname as l, createAuthSessionStore as m, resolveWebRoot as n, defaultStateDir as o, createCliAuth as p, startInstance as r, hostnameOf as s, createHostGuard as t, loadConfigFile as u, createApnsClient as v, createActivityRoute as w, createDeviceRegistry as x, loadApnsKey as y };
2391
2402
 
2392
- //# sourceMappingURL=instance-DP3af4H-.mjs.map
2403
+ //# sourceMappingURL=instance-vQe2VlGq.mjs.map