@cabane/companion 0.6.32 → 0.6.34

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.
@@ -160,10 +160,11 @@ var companionConfigSchema = z2.object({
160
160
  // device with no device-level entry behaves exactly as it did before. A hook
161
161
  // that fails still fails the dispatch loudly, as now.
162
162
  prepareHook: prepareHookSchema.optional(),
163
- // Dashboard settings (all optional). dashboardPort: preferred bind port (next
164
- // free one if taken); autoOpen: whether `start` opens the browser (the
165
- // `--no-open` flag / `COMPANION_NO_OPEN=1` override per-run); logLevel: pino
166
- // level, live-editable from the dashboard settings panel.
163
+ // CT1085 §9: `dashboardPort` and `autoOpen` are READ AND IGNORED by the CLI —
164
+ // it binds no port and opens no browser. They stay in the schema (rather than
165
+ // becoming a strict-mode parse error on an existing config file) and still mean
166
+ // what they say to the Electron shell, the one front-end that renders a
167
+ // dashboard. `logLevel` is unaffected: pino level, live-editable.
167
168
  dashboardPort: z2.number().int().min(1).max(65535).optional(),
168
169
  autoOpen: z2.boolean().optional(),
169
170
  logLevel: z2.enum(["warn", "info", "debug"]).optional(),
@@ -326,6 +327,18 @@ function saveConfig(cfg) {
326
327
  }
327
328
 
328
329
  // src/enrollment.ts
330
+ var EnrollmentExpiredError = class extends CompanionError {
331
+ constructor() {
332
+ super("this pairing code expired before it was confirmed.");
333
+ this.name = "EnrollmentExpiredError";
334
+ }
335
+ };
336
+ var EnrollmentCancelledError = class extends CompanionError {
337
+ constructor() {
338
+ super("pairing was cancelled.");
339
+ this.name = "EnrollmentCancelledError";
340
+ }
341
+ };
329
342
  function trimBase(baseUrl) {
330
343
  return baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
331
344
  }
@@ -362,18 +375,20 @@ async function postJson(baseUrl, path, body) {
362
375
  }
363
376
  return parsed;
364
377
  }
365
- function requestEnrollmentCode(baseUrl) {
366
- return postJson(baseUrl, "/api/device-enrollment/code", {});
378
+ function requestEnrollmentCode(baseUrl, opts = {}) {
379
+ return postJson(baseUrl, "/api/device-enrollment/code", {
380
+ ...opts.label ? { label: opts.label } : {}
381
+ });
367
382
  }
368
383
  function pollOnce(baseUrl, deviceCode) {
369
384
  return postJson(baseUrl, "/api/device-enrollment/poll", { deviceCode });
370
385
  }
371
386
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
372
387
  async function runDeviceFlow(baseUrl, print, opts = {}) {
373
- const now = opts.now ?? (() => Date.now());
374
- const wait = opts.sleepMs ?? sleep;
375
- if (opts.signal?.aborted) throw new CompanionError("pairing was cancelled.");
376
- const code = await requestEnrollmentCode(baseUrl);
388
+ if (opts.signal?.aborted) throw new EnrollmentCancelledError();
389
+ const code = await requestEnrollmentCode(baseUrl, {
390
+ ...opts.label ? { label: opts.label } : {}
391
+ });
377
392
  if (opts.onCode) await opts.onCode(code);
378
393
  print("");
379
394
  print(` Enter this code at ${code.verificationUri}`);
@@ -382,12 +397,17 @@ async function runDeviceFlow(baseUrl, print, opts = {}) {
382
397
  print("");
383
398
  print(` or open: ${code.verificationUriComplete}`);
384
399
  print("");
385
- print("Waiting for you to confirm it in cabane\u2026");
400
+ print("Waiting for you to confirm it in Cabane\u2026");
401
+ return awaitEnrollment(baseUrl, code, opts);
402
+ }
403
+ async function awaitEnrollment(baseUrl, code, opts = {}) {
404
+ const now = opts.now ?? (() => Date.now());
405
+ const wait = opts.sleepMs ?? sleep;
386
406
  const deadline = now() + code.expiresIn * 1e3;
387
407
  let intervalMs = Math.max(1, code.interval) * 1e3;
388
408
  while (now() < deadline) {
389
409
  await wait(intervalMs);
390
- if (opts.signal?.aborted) throw new CompanionError("pairing was cancelled.");
410
+ if (opts.signal?.aborted) throw new EnrollmentCancelledError();
391
411
  const res = await pollOnce(baseUrl, code.deviceCode);
392
412
  if (res.status === "complete") {
393
413
  if (!res.deviceToken || !res.baseUrl) {
@@ -397,19 +417,14 @@ async function runDeviceFlow(baseUrl, print, opts = {}) {
397
417
  baseUrl: res.baseUrl,
398
418
  deviceToken: res.deviceToken,
399
419
  ...res.deviceId ? { deviceId: res.deviceId } : {},
400
- ...res.deviceLabel ? { deviceLabel: res.deviceLabel } : {}
420
+ ...res.deviceLabel ? { deviceLabel: res.deviceLabel } : {},
421
+ ...res.ownerName ? { ownerName: res.ownerName } : {}
401
422
  };
402
423
  }
403
- if (res.status === "expired") {
404
- throw new CompanionError(
405
- "this pairing code expired before it was confirmed. Run `cabane-companion pair` again for a fresh one."
406
- );
407
- }
424
+ if (res.status === "expired") throw new EnrollmentExpiredError();
408
425
  if (res.status === "slow_down") intervalMs += 1e3;
409
426
  }
410
- throw new CompanionError(
411
- "this pairing code expired before it was confirmed. Run `cabane-companion pair` again for a fresh one."
412
- );
427
+ throw new EnrollmentExpiredError();
413
428
  }
414
429
 
415
430
  // src/pairing-config.ts