@mutmutco/installer-launcher 0.1.10 → 0.1.11

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.
package/dist/launcher.js CHANGED
@@ -311,7 +311,7 @@ import { appendFileSync as appendFileSync2 } from "node:fs";
311
311
  // ../face/src/outcome.ts
312
312
  import { readFileSync, writeFileSync } from "node:fs";
313
313
  var counts = ["total", "updated", "failed"];
314
- var strings = ["version", "retry", "detail"];
314
+ var strings = ["version", "retry", "detail", "logPath"];
315
315
  var flags = ["dryRun", "installed", "deferred", "operationFailed"];
316
316
  function validateInstallerOutcome(value) {
317
317
  const invalid = () => {
@@ -319,12 +319,15 @@ function validateInstallerOutcome(value) {
319
319
  };
320
320
  if (!value || typeof value !== "object" || Array.isArray(value)) return invalid();
321
321
  const facts = value;
322
- const allowed = [...counts, ...strings, ...flags];
322
+ const allowed = [...counts, ...strings, ...flags, "rollback", "logState"];
323
323
  if (Object.keys(facts).some((key) => !allowed.includes(key))) return invalid();
324
324
  for (const key of counts) if (!Number.isSafeInteger(facts[key]) || facts[key] < 0) return invalid();
325
325
  if (facts.updated + facts.failed > facts.total) return invalid();
326
326
  for (const key of strings) if (facts[key] !== void 0 && (typeof facts[key] !== "string" || facts[key].length > 4096)) return invalid();
327
327
  for (const key of flags) if (facts[key] !== void 0 && typeof facts[key] !== "boolean") return invalid();
328
+ if (facts.rollback !== void 0 && !["completed", "partial", "not-needed", "unknown"].includes(facts.rollback)) return invalid();
329
+ if (facts.logState !== void 0 && !["unavailable", "omitted"].includes(facts.logState)) return invalid();
330
+ if (facts.logPath !== void 0 && (!facts.logPath.trim() || /[\x00-\x1f\x7f]/u.test(facts.logPath))) return invalid();
328
331
  return { ...facts };
329
332
  }
330
333
  function writeInstallerOutcome(path, value) {
@@ -397,7 +400,8 @@ var PHASES = {
397
400
  verify: ["Verifying the payload", "Verified the payload"],
398
401
  install: ["Installing the product", "Installed the product"],
399
402
  activate: ["Activating surfaces", "Activated surfaces"],
400
- doctor: ["Checking health", "Checked health"]
403
+ doctor: ["Checking health", "Checked health"],
404
+ rollback: ["Restoring the previous version", "Restored the previous version"]
401
405
  };
402
406
  function createInstallerRun(value, options = {}) {
403
407
  const declaration = validateInstallerProduct(value);
@@ -410,9 +414,16 @@ function createInstallerRun(value, options = {}) {
410
414
  env,
411
415
  color: tty && options.color !== false && env.NO_COLOR === void 0
412
416
  });
413
- const write = options.write ?? ((text, channel) => {
417
+ const errors = [];
418
+ const write = options.write ? (text, channel) => {
419
+ try {
420
+ options.write(text, channel);
421
+ } catch (error) {
422
+ errors.push(`installer output observer: ${error instanceof Error ? error.message : String(error)}`);
423
+ }
424
+ } : (text, channel) => {
414
425
  (channel === "stdout" ? process.stdout : process.stderr).write(text);
415
- });
426
+ };
416
427
  const emit = (text, channel = "stdout", recorded = text) => {
417
428
  if (!text) return;
418
429
  write(text, channel);
@@ -447,6 +458,9 @@ function createInstallerRun(value, options = {}) {
447
458
  if (rendered) lines([tty ? rendered : `${kind === "fail" ? "Failed: " : ""}${title}${measure === null ? "" : ` (${typeof measure === "number" ? `${Math.max(0, Math.round(measure))}s` : measure})`}`]);
448
459
  };
449
460
  const run2 = {
461
+ get errors() {
462
+ return [...errors];
463
+ },
450
464
  start,
451
465
  phase(id, facts = {}) {
452
466
  if (finished) throw new Error("installer run already finished");
@@ -512,7 +526,9 @@ function createInstallerRun(value, options = {}) {
512
526
  changed,
513
527
  ...facts.failed ? [`Failed ${facts.failed} of ${facts.total} surfaces.`] : [],
514
528
  ...facts.detail ? [facts.detail] : [],
515
- facts.retry && facts.failed ? `Retry: ${facts.retry}` : `Check health any time: ${declaration.doctor}`
529
+ ...facts.rollback ? [`Rollback: ${facts.rollback}`] : [],
530
+ ...facts.logPath ? [`Log: ${facts.logPath}`] : facts.logState ? [`Log: ${facts.logState}`] : [],
531
+ facts.retry && (facts.failed > 0 || facts.operationFailed) ? `Retry: ${facts.retry}` : `Check health any time: ${declaration.doctor}`
516
532
  ];
517
533
  if (!face.nested || !env.MM_INSTALLER_OUTCOME_FILE && (facts.failed > 0 || facts.operationFailed)) {
518
534
  lines(tty ? face.receipt(body, { ready }) : body.map((row) => row.replace(/^[✔✖●] /u, "")));
@@ -1253,7 +1269,7 @@ function wipeProductDir(dir) {
1253
1269
  }
1254
1270
 
1255
1271
  // src/index.ts
1256
- var LAUNCHER_VERSION = true ? "0.1.10" : readVersionFromPackage();
1272
+ var LAUNCHER_VERSION = true ? "0.1.11" : readVersionFromPackage();
1257
1273
  function defaultPrint(message) {
1258
1274
  process.stdout.write(`${message}
1259
1275
  `);
@@ -1538,10 +1554,7 @@ async function installOrUpdate(config, dir, options, print, update) {
1538
1554
  operation: update ? "update" : "install",
1539
1555
  tty: options.tty,
1540
1556
  animate: !options.print && Boolean(process.stderr.isTTY),
1541
- write: (text, channel) => {
1542
- if (options.print) print(text.replace(/\n$/, ""));
1543
- else (channel === "stdout" ? process.stdout : process.stderr).write(text);
1544
- }
1557
+ ...options.print ? { write: (text) => print(text.replace(/\n$/, "")) } : {}
1545
1558
  });
1546
1559
  const fetchImpl = options.fetchImpl ?? fetch;
1547
1560
  let version = readState(dir)?.version ?? "unknown";
@@ -342,7 +342,7 @@ var import_node_fs4 = require("node:fs");
342
342
  // ../face/src/outcome.ts
343
343
  var import_node_fs3 = require("node:fs");
344
344
  var counts = ["total", "updated", "failed"];
345
- var strings = ["version", "retry", "detail"];
345
+ var strings = ["version", "retry", "detail", "logPath"];
346
346
  var flags = ["dryRun", "installed", "deferred", "operationFailed"];
347
347
  function validateInstallerOutcome(value) {
348
348
  const invalid = () => {
@@ -350,12 +350,15 @@ function validateInstallerOutcome(value) {
350
350
  };
351
351
  if (!value || typeof value !== "object" || Array.isArray(value)) return invalid();
352
352
  const facts = value;
353
- const allowed = [...counts, ...strings, ...flags];
353
+ const allowed = [...counts, ...strings, ...flags, "rollback", "logState"];
354
354
  if (Object.keys(facts).some((key) => !allowed.includes(key))) return invalid();
355
355
  for (const key of counts) if (!Number.isSafeInteger(facts[key]) || facts[key] < 0) return invalid();
356
356
  if (facts.updated + facts.failed > facts.total) return invalid();
357
357
  for (const key of strings) if (facts[key] !== void 0 && (typeof facts[key] !== "string" || facts[key].length > 4096)) return invalid();
358
358
  for (const key of flags) if (facts[key] !== void 0 && typeof facts[key] !== "boolean") return invalid();
359
+ if (facts.rollback !== void 0 && !["completed", "partial", "not-needed", "unknown"].includes(facts.rollback)) return invalid();
360
+ if (facts.logState !== void 0 && !["unavailable", "omitted"].includes(facts.logState)) return invalid();
361
+ if (facts.logPath !== void 0 && (!facts.logPath.trim() || /[\x00-\x1f\x7f]/u.test(facts.logPath))) return invalid();
359
362
  return { ...facts };
360
363
  }
361
364
  function writeInstallerOutcome(path, value) {
@@ -428,7 +431,8 @@ var PHASES = {
428
431
  verify: ["Verifying the payload", "Verified the payload"],
429
432
  install: ["Installing the product", "Installed the product"],
430
433
  activate: ["Activating surfaces", "Activated surfaces"],
431
- doctor: ["Checking health", "Checked health"]
434
+ doctor: ["Checking health", "Checked health"],
435
+ rollback: ["Restoring the previous version", "Restored the previous version"]
432
436
  };
433
437
  function createInstallerRun(value, options = {}) {
434
438
  const declaration = validateInstallerProduct(value);
@@ -441,9 +445,16 @@ function createInstallerRun(value, options = {}) {
441
445
  env,
442
446
  color: tty && options.color !== false && env.NO_COLOR === void 0
443
447
  });
444
- const write = options.write ?? ((text, channel) => {
448
+ const errors = [];
449
+ const write = options.write ? (text, channel) => {
450
+ try {
451
+ options.write(text, channel);
452
+ } catch (error) {
453
+ errors.push(`installer output observer: ${error instanceof Error ? error.message : String(error)}`);
454
+ }
455
+ } : (text, channel) => {
445
456
  (channel === "stdout" ? process.stdout : process.stderr).write(text);
446
- });
457
+ };
447
458
  const emit = (text, channel = "stdout", recorded = text) => {
448
459
  if (!text) return;
449
460
  write(text, channel);
@@ -478,6 +489,9 @@ function createInstallerRun(value, options = {}) {
478
489
  if (rendered) lines([tty ? rendered : `${kind === "fail" ? "Failed: " : ""}${title}${measure === null ? "" : ` (${typeof measure === "number" ? `${Math.max(0, Math.round(measure))}s` : measure})`}`]);
479
490
  };
480
491
  const run2 = {
492
+ get errors() {
493
+ return [...errors];
494
+ },
481
495
  start,
482
496
  phase(id, facts = {}) {
483
497
  if (finished) throw new Error("installer run already finished");
@@ -543,7 +557,9 @@ function createInstallerRun(value, options = {}) {
543
557
  changed,
544
558
  ...facts.failed ? [`Failed ${facts.failed} of ${facts.total} surfaces.`] : [],
545
559
  ...facts.detail ? [facts.detail] : [],
546
- facts.retry && facts.failed ? `Retry: ${facts.retry}` : `Check health any time: ${declaration.doctor}`
560
+ ...facts.rollback ? [`Rollback: ${facts.rollback}`] : [],
561
+ ...facts.logPath ? [`Log: ${facts.logPath}`] : facts.logState ? [`Log: ${facts.logState}`] : [],
562
+ facts.retry && (facts.failed > 0 || facts.operationFailed) ? `Retry: ${facts.retry}` : `Check health any time: ${declaration.doctor}`
547
563
  ];
548
564
  if (!face.nested || !env.MM_INSTALLER_OUTCOME_FILE && (facts.failed > 0 || facts.operationFailed)) {
549
565
  lines(tty ? face.receipt(body, { ready }) : body.map((row) => row.replace(/^[✔✖●] /u, "")));
@@ -1285,7 +1301,7 @@ function wipeProductDir(dir) {
1285
1301
  }
1286
1302
 
1287
1303
  // src/index.ts
1288
- var LAUNCHER_VERSION = true ? "0.1.10" : readVersionFromPackage();
1304
+ var LAUNCHER_VERSION = true ? "0.1.11" : readVersionFromPackage();
1289
1305
  function defaultPrint(message) {
1290
1306
  process.stdout.write(`${message}
1291
1307
  `);
@@ -1570,10 +1586,7 @@ async function installOrUpdate(config, dir, options, print, update) {
1570
1586
  operation: update ? "update" : "install",
1571
1587
  tty: options.tty,
1572
1588
  animate: !options.print && Boolean(process.stderr.isTTY),
1573
- write: (text, channel) => {
1574
- if (options.print) print(text.replace(/\n$/, ""));
1575
- else (channel === "stdout" ? process.stdout : process.stderr).write(text);
1576
- }
1589
+ ...options.print ? { write: (text) => print(text.replace(/\n$/, "")) } : {}
1577
1590
  });
1578
1591
  const fetchImpl = options.fetchImpl ?? fetch;
1579
1592
  let version = readState(dir)?.version ?? "unknown";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/installer-launcher",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Single-executable (SEA) launcher: sign-in, gated payload fetch, self-update. One copy ships per product.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",