@plexus-ms/cli 0.2.0 → 0.4.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.
Files changed (2) hide show
  1. package/dist/plx.js +2579 -1726
  2. package/package.json +8 -6
package/dist/plx.js CHANGED
@@ -38,171 +38,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
38
38
  mod
39
39
  ));
40
40
 
41
- // ../../node_modules/.pnpm/cli-width@4.1.0/node_modules/cli-width/index.js
42
- var require_cli_width = __commonJS({
43
- "../../node_modules/.pnpm/cli-width@4.1.0/node_modules/cli-width/index.js"(exports, module) {
44
- "use strict";
45
- module.exports = cliWidth2;
46
- function normalizeOpts(options) {
47
- const defaultOpts = {
48
- defaultWidth: 0,
49
- output: process.stdout,
50
- tty: __require("tty")
51
- };
52
- if (!options) {
53
- return defaultOpts;
54
- }
55
- Object.keys(defaultOpts).forEach(function(key) {
56
- if (!options[key]) {
57
- options[key] = defaultOpts[key];
58
- }
59
- });
60
- return options;
61
- }
62
- function cliWidth2(options) {
63
- const opts = normalizeOpts(options);
64
- if (opts.output.getWindowSize) {
65
- return opts.output.getWindowSize()[0] || opts.defaultWidth;
66
- }
67
- if (opts.tty.getWindowSize) {
68
- return opts.tty.getWindowSize()[1] || opts.defaultWidth;
69
- }
70
- if (opts.output.columns) {
71
- return opts.output.columns;
72
- }
73
- if (process.env.CLI_WIDTH) {
74
- const width = parseInt(process.env.CLI_WIDTH, 10);
75
- if (!isNaN(width) && width !== 0) {
76
- return width;
77
- }
78
- }
79
- return opts.defaultWidth;
80
- }
81
- }
82
- });
83
-
84
- // ../../node_modules/.pnpm/mute-stream@3.0.0/node_modules/mute-stream/lib/index.js
85
- var require_lib = __commonJS({
86
- "../../node_modules/.pnpm/mute-stream@3.0.0/node_modules/mute-stream/lib/index.js"(exports, module) {
87
- var Stream = __require("stream");
88
- var MuteStream2 = class extends Stream {
89
- #isTTY = null;
90
- constructor(opts = {}) {
91
- super(opts);
92
- this.writable = this.readable = true;
93
- this.muted = false;
94
- this.on("pipe", this._onpipe);
95
- this.replace = opts.replace;
96
- this._prompt = opts.prompt || null;
97
- this._hadControl = false;
98
- }
99
- #destSrc(key, def) {
100
- if (this._dest) {
101
- return this._dest[key];
102
- }
103
- if (this._src) {
104
- return this._src[key];
105
- }
106
- return def;
107
- }
108
- #proxy(method, ...args) {
109
- if (typeof this._dest?.[method] === "function") {
110
- this._dest[method](...args);
111
- }
112
- if (typeof this._src?.[method] === "function") {
113
- this._src[method](...args);
114
- }
115
- }
116
- get isTTY() {
117
- if (this.#isTTY !== null) {
118
- return this.#isTTY;
119
- }
120
- return this.#destSrc("isTTY", false);
121
- }
122
- // basically just get replace the getter/setter with a regular value
123
- set isTTY(val) {
124
- this.#isTTY = val;
125
- }
126
- get rows() {
127
- return this.#destSrc("rows");
128
- }
129
- get columns() {
130
- return this.#destSrc("columns");
131
- }
132
- mute() {
133
- this.muted = true;
134
- }
135
- unmute() {
136
- this.muted = false;
137
- }
138
- _onpipe(src) {
139
- this._src = src;
140
- }
141
- pipe(dest, options) {
142
- this._dest = dest;
143
- return super.pipe(dest, options);
144
- }
145
- pause() {
146
- if (this._src) {
147
- return this._src.pause();
148
- }
149
- }
150
- resume() {
151
- if (this._src) {
152
- return this._src.resume();
153
- }
154
- }
155
- write(c) {
156
- if (this.muted) {
157
- if (!this.replace) {
158
- return true;
159
- }
160
- if (c.match(/^\u001b/)) {
161
- if (c.indexOf(this._prompt) === 0) {
162
- c = c.slice(this._prompt.length);
163
- c = c.replace(/./g, this.replace);
164
- c = this._prompt + c;
165
- }
166
- this._hadControl = true;
167
- return this.emit("data", c);
168
- } else {
169
- if (this._prompt && this._hadControl && c.indexOf(this._prompt) === 0) {
170
- this._hadControl = false;
171
- this.emit("data", this._prompt);
172
- c = c.slice(this._prompt.length);
173
- }
174
- c = c.toString().replace(/./g, this.replace);
175
- }
176
- }
177
- this.emit("data", c);
178
- }
179
- end(c) {
180
- if (this.muted) {
181
- if (c && this.replace) {
182
- c = c.toString().replace(/./g, this.replace);
183
- } else {
184
- c = null;
185
- }
186
- }
187
- if (c) {
188
- this.emit("data", c);
189
- }
190
- this.emit("end");
191
- }
192
- destroy(...args) {
193
- return this.#proxy("destroy", ...args);
194
- }
195
- destroySoon(...args) {
196
- return this.#proxy("destroySoon", ...args);
197
- }
198
- close(...args) {
199
- return this.#proxy("close", ...args);
200
- }
201
- };
202
- module.exports = MuteStream2;
203
- }
204
- });
205
-
206
41
  // ../../node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/nodes/identity.js
207
42
  var require_identity = __commonJS({
208
43
  "../../node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/nodes/identity.js"(exports) {
@@ -6517,15 +6352,15 @@ var require_parser = __commonJS({
6517
6352
  var node_process = __require("process");
6518
6353
  var cst = require_cst();
6519
6354
  var lexer = require_lexer();
6520
- function includesToken(list, type) {
6521
- for (let i = 0; i < list.length; ++i)
6522
- if (list[i].type === type)
6355
+ function includesToken(list2, type) {
6356
+ for (let i = 0; i < list2.length; ++i)
6357
+ if (list2[i].type === type)
6523
6358
  return true;
6524
6359
  return false;
6525
6360
  }
6526
- function findNonEmptyIndex(list) {
6527
- for (let i = 0; i < list.length; ++i) {
6528
- switch (list[i].type) {
6361
+ function findNonEmptyIndex(list2) {
6362
+ for (let i = 0; i < list2.length; ++i) {
6363
+ switch (list2[i].type) {
6529
6364
  case "space":
6530
6365
  case "comment":
6531
6366
  case "newline":
@@ -7433,7 +7268,7 @@ var require_public_api = __commonJS({
7433
7268
  }
7434
7269
  return doc;
7435
7270
  }
7436
- function parse3(src, reviver, options) {
7271
+ function parse4(src, reviver, options) {
7437
7272
  let _reviver = void 0;
7438
7273
  if (typeof reviver === "function") {
7439
7274
  _reviver = reviver;
@@ -7474,7 +7309,7 @@ var require_public_api = __commonJS({
7474
7309
  return value.toString(options);
7475
7310
  return new Document.Document(value, _replacer, options).toString(options);
7476
7311
  }
7477
- exports.parse = parse3;
7312
+ exports.parse = parse4;
7478
7313
  exports.parseAllDocuments = parseAllDocuments;
7479
7314
  exports.parseDocument = parseDocument;
7480
7315
  exports.stringify = stringify;
@@ -7533,182 +7368,1554 @@ var require_dist = __commonJS({
7533
7368
  }
7534
7369
  });
7535
7370
 
7536
- // src/program.ts
7537
- import { createRequire } from "node:module";
7538
-
7539
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/key.js
7540
- var keybindings = ["emacs", "vim"];
7541
- var keybindingLookup = new Set(keybindings);
7542
- function isKeybinding(value) {
7543
- return keybindingLookup.has(value);
7544
- }
7545
- function getDefaultKeybindings() {
7546
- const env = process.env["INQUIRER_KEYBINDINGS"];
7547
- if (!env)
7548
- return [];
7549
- return Array.from(new Set(env.toLowerCase().split(/[\s,]+/).filter(isKeybinding)));
7550
- }
7551
- var isTabKey = (key) => key.name === "tab";
7552
- var isEnterKey = (key) => key.name === "enter" || key.name === "return";
7553
-
7554
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/errors.js
7555
- var AbortPromptError = class extends Error {
7556
- name = "AbortPromptError";
7557
- message = "Prompt was aborted";
7558
- constructor(options) {
7559
- super();
7560
- this.cause = options?.cause;
7371
+ // ../../node_modules/.pnpm/cli-width@4.1.0/node_modules/cli-width/index.js
7372
+ var require_cli_width = __commonJS({
7373
+ "../../node_modules/.pnpm/cli-width@4.1.0/node_modules/cli-width/index.js"(exports, module) {
7374
+ "use strict";
7375
+ module.exports = cliWidth2;
7376
+ function normalizeOpts(options) {
7377
+ const defaultOpts = {
7378
+ defaultWidth: 0,
7379
+ output: process.stdout,
7380
+ tty: __require("tty")
7381
+ };
7382
+ if (!options) {
7383
+ return defaultOpts;
7384
+ }
7385
+ Object.keys(defaultOpts).forEach(function(key) {
7386
+ if (!options[key]) {
7387
+ options[key] = defaultOpts[key];
7388
+ }
7389
+ });
7390
+ return options;
7391
+ }
7392
+ function cliWidth2(options) {
7393
+ const opts = normalizeOpts(options);
7394
+ if (opts.output.getWindowSize) {
7395
+ return opts.output.getWindowSize()[0] || opts.defaultWidth;
7396
+ }
7397
+ if (opts.tty.getWindowSize) {
7398
+ return opts.tty.getWindowSize()[1] || opts.defaultWidth;
7399
+ }
7400
+ if (opts.output.columns) {
7401
+ return opts.output.columns;
7402
+ }
7403
+ if (process.env.CLI_WIDTH) {
7404
+ const width = parseInt(process.env.CLI_WIDTH, 10);
7405
+ if (!isNaN(width) && width !== 0) {
7406
+ return width;
7407
+ }
7408
+ }
7409
+ return opts.defaultWidth;
7410
+ }
7561
7411
  }
7562
- };
7563
- var CancelPromptError = class extends Error {
7564
- name = "CancelPromptError";
7565
- message = "Prompt was canceled";
7566
- };
7567
- var ExitPromptError = class extends Error {
7568
- name = "ExitPromptError";
7569
- };
7570
- var HookError = class extends Error {
7571
- name = "HookError";
7572
- };
7573
- var ValidationError = class extends Error {
7574
- name = "ValidationError";
7575
- };
7576
-
7577
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/use-state.js
7578
- import { AsyncResource as AsyncResource2 } from "node:async_hooks";
7412
+ });
7579
7413
 
7580
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/hook-engine.js
7581
- import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
7582
- var hookStorage = new AsyncLocalStorage();
7583
- function createStore(rl) {
7584
- const store = {
7585
- rl,
7586
- hooks: [],
7587
- hooksCleanup: [],
7588
- hooksEffect: [],
7589
- index: 0,
7590
- handleChange() {
7591
- }
7592
- };
7593
- return store;
7594
- }
7595
- function withHooks(rl, cb) {
7596
- const store = createStore(rl);
7597
- function cycle(render2) {
7598
- store.handleChange = () => {
7599
- store.index = 0;
7600
- render2();
7414
+ // ../../node_modules/.pnpm/mute-stream@3.0.0/node_modules/mute-stream/lib/index.js
7415
+ var require_lib = __commonJS({
7416
+ "../../node_modules/.pnpm/mute-stream@3.0.0/node_modules/mute-stream/lib/index.js"(exports, module) {
7417
+ var Stream = __require("stream");
7418
+ var MuteStream2 = class extends Stream {
7419
+ #isTTY = null;
7420
+ constructor(opts = {}) {
7421
+ super(opts);
7422
+ this.writable = this.readable = true;
7423
+ this.muted = false;
7424
+ this.on("pipe", this._onpipe);
7425
+ this.replace = opts.replace;
7426
+ this._prompt = opts.prompt || null;
7427
+ this._hadControl = false;
7428
+ }
7429
+ #destSrc(key, def) {
7430
+ if (this._dest) {
7431
+ return this._dest[key];
7432
+ }
7433
+ if (this._src) {
7434
+ return this._src[key];
7435
+ }
7436
+ return def;
7437
+ }
7438
+ #proxy(method, ...args) {
7439
+ if (typeof this._dest?.[method] === "function") {
7440
+ this._dest[method](...args);
7441
+ }
7442
+ if (typeof this._src?.[method] === "function") {
7443
+ this._src[method](...args);
7444
+ }
7445
+ }
7446
+ get isTTY() {
7447
+ if (this.#isTTY !== null) {
7448
+ return this.#isTTY;
7449
+ }
7450
+ return this.#destSrc("isTTY", false);
7451
+ }
7452
+ // basically just get replace the getter/setter with a regular value
7453
+ set isTTY(val) {
7454
+ this.#isTTY = val;
7455
+ }
7456
+ get rows() {
7457
+ return this.#destSrc("rows");
7458
+ }
7459
+ get columns() {
7460
+ return this.#destSrc("columns");
7461
+ }
7462
+ mute() {
7463
+ this.muted = true;
7464
+ }
7465
+ unmute() {
7466
+ this.muted = false;
7467
+ }
7468
+ _onpipe(src) {
7469
+ this._src = src;
7470
+ }
7471
+ pipe(dest, options) {
7472
+ this._dest = dest;
7473
+ return super.pipe(dest, options);
7474
+ }
7475
+ pause() {
7476
+ if (this._src) {
7477
+ return this._src.pause();
7478
+ }
7479
+ }
7480
+ resume() {
7481
+ if (this._src) {
7482
+ return this._src.resume();
7483
+ }
7484
+ }
7485
+ write(c) {
7486
+ if (this.muted) {
7487
+ if (!this.replace) {
7488
+ return true;
7489
+ }
7490
+ if (c.match(/^\u001b/)) {
7491
+ if (c.indexOf(this._prompt) === 0) {
7492
+ c = c.slice(this._prompt.length);
7493
+ c = c.replace(/./g, this.replace);
7494
+ c = this._prompt + c;
7495
+ }
7496
+ this._hadControl = true;
7497
+ return this.emit("data", c);
7498
+ } else {
7499
+ if (this._prompt && this._hadControl && c.indexOf(this._prompt) === 0) {
7500
+ this._hadControl = false;
7501
+ this.emit("data", this._prompt);
7502
+ c = c.slice(this._prompt.length);
7503
+ }
7504
+ c = c.toString().replace(/./g, this.replace);
7505
+ }
7506
+ }
7507
+ this.emit("data", c);
7508
+ }
7509
+ end(c) {
7510
+ if (this.muted) {
7511
+ if (c && this.replace) {
7512
+ c = c.toString().replace(/./g, this.replace);
7513
+ } else {
7514
+ c = null;
7515
+ }
7516
+ }
7517
+ if (c) {
7518
+ this.emit("data", c);
7519
+ }
7520
+ this.emit("end");
7521
+ }
7522
+ destroy(...args) {
7523
+ return this.#proxy("destroy", ...args);
7524
+ }
7525
+ destroySoon(...args) {
7526
+ return this.#proxy("destroySoon", ...args);
7527
+ }
7528
+ close(...args) {
7529
+ return this.#proxy("close", ...args);
7530
+ }
7601
7531
  };
7602
- store.handleChange();
7532
+ module.exports = MuteStream2;
7603
7533
  }
7604
- return hookStorage.run(store, () => cb(cycle));
7534
+ });
7535
+
7536
+ // ../lib/dist/frontmatter.js
7537
+ function frontmatterLines(lines) {
7538
+ if (lines[0] !== "---")
7539
+ return void 0;
7540
+ const end = lines.findIndex((l, i) => i > 0 && l === "---");
7541
+ return end === -1 ? void 0 : { start: 1, end };
7605
7542
  }
7606
- function getStore() {
7607
- const store = hookStorage.getStore();
7608
- if (!store) {
7609
- throw new HookError("[Inquirer] Hook functions can only be called from within a prompt");
7543
+ function setFrontmatterField(text, key, value, options = {}) {
7544
+ const lines = text.split("\n");
7545
+ const fm = frontmatterLines(lines);
7546
+ if (!fm)
7547
+ throw new Error("no frontmatter: expected a `---` block at the top");
7548
+ const line = `${key}: ${value}`;
7549
+ const isKey = (l) => l.startsWith(`${key}:`);
7550
+ const existing = lines.findIndex((l, i) => i >= fm.start && i < fm.end && isKey(l));
7551
+ if (existing !== -1) {
7552
+ lines[existing] = line;
7553
+ } else {
7554
+ const anchor = options.after ? lines.findIndex((l, i) => i >= fm.start && i < fm.end && l.startsWith(`${options.after}:`)) : -1;
7555
+ lines.splice(anchor === -1 ? fm.end : anchor + 1, 0, line);
7610
7556
  }
7611
- return store;
7557
+ return lines.join("\n");
7612
7558
  }
7613
- function readline() {
7614
- return getStore().rl;
7559
+ function frontmatterField(text, key) {
7560
+ const lines = text.split("\n");
7561
+ const fm = frontmatterLines(lines);
7562
+ if (!fm)
7563
+ return void 0;
7564
+ const line = lines.slice(fm.start, fm.end).find((l) => l.startsWith(`${key}:`));
7565
+ return line?.slice(key.length + 1).trim();
7615
7566
  }
7616
- function withUpdates(fn) {
7617
- const wrapped = (...args) => {
7618
- const store = getStore();
7619
- let shouldUpdate = false;
7620
- const oldHandleChange = store.handleChange;
7621
- store.handleChange = () => {
7622
- shouldUpdate = true;
7623
- };
7624
- const returnValue = fn(...args);
7625
- if (shouldUpdate) {
7626
- oldHandleChange();
7567
+
7568
+ // ../lib/dist/bookkeeping.js
7569
+ var bumpGalaxyVersion = (text, train) => text.replace(/^(version: )\d+\.\d+\.\d+/m, `$1${train}`);
7570
+ function bumpCollectionPin(text, train) {
7571
+ const lines = text.split("\n");
7572
+ const start = lines.findIndex((l) => l.includes("plexus-ms/platform.git"));
7573
+ if (start === -1)
7574
+ return text;
7575
+ for (let i = start; i < lines.length; i++) {
7576
+ const m = /^(\s*version: )v?[\d.]+$/.exec(lines[i] ?? "");
7577
+ if (m) {
7578
+ lines[i] = `${m[1]}${train}`;
7579
+ break;
7627
7580
  }
7628
- store.handleChange = oldHandleChange;
7629
- return returnValue;
7630
- };
7631
- return AsyncResource.bind(wrapped);
7581
+ }
7582
+ return lines.join("\n");
7632
7583
  }
7633
- function withPointer(cb) {
7634
- const store = getStore();
7635
- const { index } = store;
7636
- const pointer = {
7637
- get() {
7638
- return store.hooks[index];
7639
- },
7640
- set(value) {
7641
- store.hooks[index] = value;
7642
- },
7643
- initialized: index in store.hooks
7644
- };
7645
- const returnValue = cb(pointer);
7646
- store.index++;
7647
- return returnValue;
7584
+ var WORKFLOW_REF = "plexus-ms/ci-cd/.github/workflows/";
7585
+ var bumpWorkflowRefs = (text, train) => text.replace(/(plexus-ms\/ci-cd\/\.github\/workflows\/[A-Za-z0-9._-]+)@v?[0-9.]+/g, `$1@${train}`);
7586
+ var stampStandard = (text, train, today2) => setFrontmatterField(setFrontmatterField(text, "version", train), "timestamp", today2);
7587
+ var stampChanged = (text, train) => setFrontmatterField(text, "changed", train, { after: "binds" });
7588
+ var hasConflictMarkers = (text) => /^<<<<<<< /m.test(text);
7589
+ var hasUnmergedEntries = (porcelain) => /^(UU|AA|DU|UD)/m.test(porcelain);
7590
+ function syncMarker(marker, commit) {
7591
+ if (hasConflictMarkers(marker))
7592
+ return marker;
7593
+ return setFrontmatterField(marker, "plexus", commit);
7648
7594
  }
7649
- function handleChange() {
7650
- getStore().handleChange();
7595
+ function today(now = /* @__PURE__ */ new Date()) {
7596
+ const pad = (n) => String(n).padStart(2, "0");
7597
+ return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
7651
7598
  }
7652
- var effectScheduler = {
7653
- queue(cb) {
7654
- const store = getStore();
7655
- const { index } = store;
7656
- store.hooksEffect.push(() => {
7657
- store.hooksCleanup[index]?.();
7658
- const cleanFn = cb(readline());
7659
- if (cleanFn != null && typeof cleanFn !== "function") {
7660
- throw new ValidationError("useEffect return value must be a cleanup function or nothing.");
7661
- }
7662
- store.hooksCleanup[index] = cleanFn;
7663
- });
7664
- },
7665
- run() {
7666
- const store = getStore();
7667
- withUpdates(() => {
7668
- store.hooksEffect.forEach((effect) => {
7669
- effect();
7670
- });
7671
- store.hooksEffect.length = 0;
7672
- })();
7673
- },
7674
- clearAll() {
7675
- const store = getStore();
7676
- store.hooksCleanup.forEach((cleanFn) => {
7677
- cleanFn?.();
7678
- });
7679
- store.hooksEffect.length = 0;
7680
- store.hooksCleanup.length = 0;
7681
- }
7682
- };
7683
7599
 
7684
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/use-state.js
7685
- function isFactory(value) {
7686
- return typeof value === "function";
7687
- }
7688
- function isReducer(value) {
7689
- return typeof value === "function";
7600
+ // ../lib/dist/catalog.js
7601
+ import { join } from "node:path";
7602
+
7603
+ // ../lib/dist/marker.js
7604
+ var import_yaml = __toESM(require_dist(), 1);
7605
+ var MARKER_FILE = "PLEXUS.md";
7606
+ function parseMarker(text) {
7607
+ const { data, body: body2 } = splitFrontmatter(text);
7608
+ const plexus = data.plexus;
7609
+ const modules = data.modules;
7610
+ if (typeof plexus !== "string" && typeof plexus !== "number")
7611
+ throw new Error("marker: `plexus` must be a version");
7612
+ if (!Array.isArray(modules) || !modules.every((m) => typeof m === "string"))
7613
+ throw new Error("marker: `modules` must be a list of module codes");
7614
+ return { plexus: String(plexus), modules, body: body2 };
7690
7615
  }
7691
- function useState(defaultValue) {
7692
- return withPointer((pointer) => {
7693
- const setState = AsyncResource2.bind(function setState2(newValue) {
7694
- const currentValue = pointer.get();
7695
- const nextValue = isReducer(newValue) ? newValue(currentValue) : newValue;
7696
- if (!Object.is(currentValue, nextValue)) {
7697
- pointer.set(nextValue);
7698
- handleChange();
7699
- }
7700
- });
7701
- if (pointer.initialized) {
7702
- return [pointer.get(), setState];
7703
- }
7704
- const value = isFactory(defaultValue) ? defaultValue() : defaultValue;
7705
- pointer.set(value);
7706
- return [value, setState];
7707
- });
7616
+ function splitFrontmatter(text) {
7617
+ const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)([\s\S]*)$/.exec(text);
7618
+ if (!match)
7619
+ throw new Error("no frontmatter: expected a `---` block at the top");
7620
+ const data = (0, import_yaml.parse)(match[1] ?? "");
7621
+ if (data === null || typeof data !== "object" || Array.isArray(data))
7622
+ throw new Error("frontmatter is not a mapping");
7623
+ return { data, body: match[2] ?? "" };
7708
7624
  }
7709
7625
 
7710
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/use-effect.js
7711
- function useEffect(cb, depArray) {
7626
+ // ../lib/dist/catalog.js
7627
+ var CATALOG_DIRS = { contracts: "contract", approaches: "approach" };
7628
+ function parseModule(text, kind) {
7629
+ const { data } = splitFrontmatter(text);
7630
+ if (typeof data.code !== "string")
7631
+ return void 0;
7632
+ return {
7633
+ code: data.code,
7634
+ kind,
7635
+ maturity: String(data.maturity ?? ""),
7636
+ binds: String(data.binds ?? ""),
7637
+ changed: data.changed === void 0 ? void 0 : String(data.changed),
7638
+ depends: codes(data.depends),
7639
+ consumes: codes(data.consumes)
7640
+ };
7641
+ }
7642
+ function codes(value) {
7643
+ return Array.isArray(value) ? value.map(String) : [];
7644
+ }
7645
+ async function readCatalog(ctx, compendium) {
7646
+ const catalog = /* @__PURE__ */ new Map();
7647
+ for (const [dir, kind] of Object.entries(CATALOG_DIRS)) {
7648
+ const entries = await ctx.readDir(join(compendium, dir));
7649
+ for (const e of entries.filter((e2) => !e2.directory && e2.name.endsWith(".md") && e2.name !== "index.md").sort()) {
7650
+ const module = parseModule(await ctx.readFile(join(compendium, dir, e.name)), kind);
7651
+ if (module)
7652
+ catalog.set(module.code, module);
7653
+ }
7654
+ }
7655
+ return catalog;
7656
+ }
7657
+
7658
+ // ../lib/dist/changeset.js
7659
+ var import_yaml2 = __toESM(require_dist(), 1);
7660
+ import { join as join2 } from "node:path";
7661
+
7662
+ // ../lib/dist/io.js
7663
+ import { spawn } from "node:child_process";
7664
+ import { readdir, readFile, writeFile } from "node:fs/promises";
7665
+ var ExecError = class extends Error {
7666
+ command;
7667
+ code;
7668
+ stderr;
7669
+ constructor(command, code, stderr) {
7670
+ super(`${command} exited with ${code ?? "signal"}${stderr ? `
7671
+ ${stderr.trimEnd()}` : ""}`);
7672
+ this.command = command;
7673
+ this.code = code;
7674
+ this.stderr = stderr;
7675
+ }
7676
+ };
7677
+ var isInteractive = () => process.stdin.isTTY === true && process.stderr.isTTY === true;
7678
+ function realIo(prompt) {
7679
+ return {
7680
+ stdout: process.stdout,
7681
+ stderr: process.stderr,
7682
+ prompt: prompt && isInteractive() ? prompt : void 0,
7683
+ exec: (command, args, options = {}) => new Promise((resolve7, reject) => {
7684
+ const child = spawn(command, args, {
7685
+ cwd: options.cwd,
7686
+ env: options.env,
7687
+ stdio: [
7688
+ options.input !== void 0 ? "pipe" : options.inherit ? "inherit" : "ignore",
7689
+ options.inherit ? process.stderr.fd : "pipe",
7690
+ "pipe"
7691
+ ]
7692
+ });
7693
+ let stdout = "";
7694
+ let stderr = "";
7695
+ child.stdout?.on("data", (chunk) => {
7696
+ stdout += chunk;
7697
+ });
7698
+ child.stderr?.on("data", (chunk) => {
7699
+ stderr += chunk;
7700
+ if (options.inherit)
7701
+ process.stderr.write(chunk);
7702
+ });
7703
+ child.on("error", reject);
7704
+ child.on("close", (code) => {
7705
+ if (code === 0)
7706
+ resolve7(stdout);
7707
+ else
7708
+ reject(new ExecError(render(command, args), code, stderr));
7709
+ });
7710
+ if (options.input !== void 0)
7711
+ child.stdin?.end(options.input);
7712
+ }),
7713
+ readFile: (path3) => readFile(path3, "utf8"),
7714
+ writeFile: (path3, content) => writeFile(path3, content),
7715
+ readDir: async (path3) => (await readdir(path3, { withFileTypes: true })).map((e) => ({ name: e.name, directory: e.isDirectory() }))
7716
+ };
7717
+ }
7718
+ function render(command, args) {
7719
+ return [command, ...args].map(quote).join(" ");
7720
+ }
7721
+ function quote(arg) {
7722
+ return /^[\w./:@%+=,-]+$/.test(arg) ? arg : `'${arg.replaceAll("'", "'\\''")}'`;
7723
+ }
7724
+
7725
+ // ../lib/dist/plan.js
7726
+ var run = (command, args = [], options = {}) => ({
7727
+ kind: "run",
7728
+ command,
7729
+ args,
7730
+ ...options
7731
+ });
7732
+ var write = (path3, content) => ({ kind: "write", path: path3, content });
7733
+ function describe(step) {
7734
+ switch (step.kind) {
7735
+ case "run":
7736
+ return `$ ${step.cwd ? `(cd ${step.cwd} && ` : ""}${render(step.command, step.args)}${step.cwd ? ")" : ""}`;
7737
+ case "ssh":
7738
+ return `$ ${render("ssh", [step.host, "bash", "-s"])} <<'EOF'`;
7739
+ case "write":
7740
+ return `> ${step.path} (${Buffer.byteLength(step.content)} bytes)`;
7741
+ }
7742
+ }
7743
+ function body(step) {
7744
+ switch (step.kind) {
7745
+ case "run":
7746
+ return step.input;
7747
+ case "ssh":
7748
+ return `${step.script.trimEnd()}
7749
+ EOF`;
7750
+ case "write":
7751
+ return step.content;
7752
+ }
7753
+ }
7754
+
7755
+ // ../lib/dist/changeset.js
7756
+ var CHANGESET_DIR = ".changeset";
7757
+ var FIELDS = ["dependencies", "optionalDependencies", "peerDependencies"];
7758
+ function changesetPath(branch) {
7759
+ const slug = branch.replace(/^(renovate|dependabot)\//, "").replace(/[^a-z0-9]+/gi, "-").replace(/^-|-$/g, "").toLowerCase();
7760
+ return `${CHANGESET_DIR}/bot-${slug || "branch"}.md`;
7761
+ }
7762
+ function planChangeset(input) {
7763
+ const path3 = changesetPath(input.branch);
7764
+ const changes = [];
7765
+ const releases = {};
7766
+ for (const diff of input.packages) {
7767
+ const { before, after } = diff;
7768
+ if (!before || !after?.name || after.private || input.ignore.includes(after.name))
7769
+ continue;
7770
+ for (const field of FIELDS) {
7771
+ const names = /* @__PURE__ */ new Set([...Object.keys(before[field] ?? {}), ...Object.keys(after[field] ?? {})]);
7772
+ for (const dependency of [...names].sort()) {
7773
+ const from = resolveRange(before[field]?.[dependency], dependency, input.catalogsBefore);
7774
+ const to = resolveRange(after[field]?.[dependency], dependency, input.catalogsAfter);
7775
+ if (from === to)
7776
+ continue;
7777
+ changes.push({ package: after.name, dependency, field, from, to });
7778
+ const bump = field === "peerDependencies" ? "major" : "patch";
7779
+ if (releases[after.name] !== "major")
7780
+ releases[after.name] = bump;
7781
+ }
7782
+ }
7783
+ }
7784
+ const root = input.root;
7785
+ if (changes.length === 0) {
7786
+ const remove = run("rm", ["-f", path3], root ? { cwd: root } : {});
7787
+ return { path: path3, releases, changes, plan: input.exists ? [remove] : [] };
7788
+ }
7789
+ const header = Object.entries(releases).sort(([a], [b]) => a.localeCompare(b)).map(([name, bump]) => `'${name}': ${bump}`);
7790
+ const lines = [...new Set(changes.map(describeChange))].sort((a, b) => a.localeCompare(b));
7791
+ const content = `---
7792
+ ${header.join("\n")}
7793
+ ---
7794
+
7795
+ ${lines.join("\n")}
7796
+ `;
7797
+ return { path: path3, releases, changes, content, plan: [write(root ? join2(root, path3) : path3, content)] };
7798
+ }
7799
+ function describeChange(c) {
7800
+ const peer = c.field === "peerDependencies" ? " (peer)" : "";
7801
+ if (c.from === void 0)
7802
+ return `Add \`${c.dependency}\`${peer} at ${c.to}`;
7803
+ if (c.to === void 0)
7804
+ return `Remove \`${c.dependency}\`${peer}`;
7805
+ return `Update \`${c.dependency}\`${peer} from ${c.from} to ${c.to}`;
7806
+ }
7807
+ function resolveRange(value, dependency, catalogs) {
7808
+ if (value === void 0)
7809
+ return void 0;
7810
+ if (value === "catalog:" || value === "catalog:default")
7811
+ return catalogs.default[dependency] ?? value;
7812
+ if (value.startsWith("catalog:"))
7813
+ return catalogs.named[value.slice("catalog:".length)]?.[dependency] ?? value;
7814
+ return value;
7815
+ }
7816
+ function parseCatalogs(text) {
7817
+ const data = text === void 0 ? void 0 : (0, import_yaml2.parse)(text);
7818
+ const ws = data !== null && typeof data === "object" ? data : {};
7819
+ const map = (v) => v !== null && typeof v === "object" ? Object.fromEntries(Object.entries(v).map(([k, r]) => [k, String(r)])) : {};
7820
+ const named = ws.catalogs !== null && typeof ws.catalogs === "object" ? ws.catalogs : {};
7821
+ return {
7822
+ default: map(ws.catalog),
7823
+ named: Object.fromEntries(Object.entries(named).map(([name, entries]) => [name, map(entries)]))
7824
+ };
7825
+ }
7826
+ function workspaceGlobs(text) {
7827
+ const data = text === void 0 ? void 0 : (0, import_yaml2.parse)(text);
7828
+ const globs = data !== null && typeof data === "object" ? data.packages : void 0;
7829
+ return Array.isArray(globs) ? globs.map(String).filter((g) => !g.startsWith("!")) : [];
7830
+ }
7831
+ async function readChangeset(ctx, dir, base, branch) {
7832
+ const git2 = (args) => ctx.read("git", args, { cwd: dir });
7833
+ const head = branch ?? (await git2(["rev-parse", "--abbrev-ref", "HEAD"])).trim();
7834
+ const mergeBase = (await git2(["merge-base", base, "HEAD"])).trim();
7835
+ const show = async (path4) => {
7836
+ try {
7837
+ return await git2(["show", `${mergeBase}:${path4}`]);
7838
+ } catch (error) {
7839
+ if (error instanceof ExecError)
7840
+ return void 0;
7841
+ throw error;
7842
+ }
7843
+ };
7844
+ const current = async (path4) => {
7845
+ try {
7846
+ return await ctx.readFile(join2(dir, path4));
7847
+ } catch {
7848
+ return void 0;
7849
+ }
7850
+ };
7851
+ const workspaceAfter = await current("pnpm-workspace.yaml");
7852
+ const packages = [];
7853
+ for (const glob of workspaceGlobs(workspaceAfter)) {
7854
+ for (const pkgDir of await expand(ctx, dir, glob)) {
7855
+ const path4 = `${pkgDir}/package.json`;
7856
+ const [before, after] = await Promise.all([show(path4), current(path4)]);
7857
+ packages.push({ path: path4, before: manifest(before), after: manifest(after) });
7858
+ }
7859
+ }
7860
+ const config = await current(`${CHANGESET_DIR}/config.json`);
7861
+ const ignore = config ? JSON.parse(config).ignore ?? [] : [];
7862
+ const entries = await ctx.readDir(join2(dir, CHANGESET_DIR)).catch(() => []);
7863
+ const path3 = changesetPath(head);
7864
+ return planChangeset({
7865
+ branch: head,
7866
+ packages,
7867
+ catalogsBefore: parseCatalogs(await show("pnpm-workspace.yaml")),
7868
+ catalogsAfter: parseCatalogs(workspaceAfter),
7869
+ ignore,
7870
+ exists: entries.some((e) => !e.directory && `${CHANGESET_DIR}/${e.name}` === path3),
7871
+ root: dir
7872
+ });
7873
+ }
7874
+ function manifest(text) {
7875
+ return text === void 0 ? void 0 : JSON.parse(text);
7876
+ }
7877
+ async function expand(ctx, root, glob) {
7878
+ const star = glob.indexOf("*");
7879
+ if (star < 0)
7880
+ return [glob.replace(/\/$/, "")];
7881
+ const parent = glob.slice(0, star).replace(/\/$/, "");
7882
+ const entries = await ctx.readDir(join2(root, parent)).catch(() => []);
7883
+ return entries.filter((e) => e.directory && !e.name.startsWith(".")).map((e) => parent ? `${parent}/${e.name}` : e.name).sort();
7884
+ }
7885
+
7886
+ // ../lib/dist/consumers.js
7887
+ import { relative } from "node:path";
7888
+ function expectedBranch(declaration) {
7889
+ if (!declaration)
7890
+ return void 0;
7891
+ if (declaration.modules.includes("PLX-Platform"))
7892
+ return "main";
7893
+ if (declaration.modules.includes("PLX-Repo"))
7894
+ return "develop";
7895
+ return void 0;
7896
+ }
7897
+ var presetSource = (preset) => `gh:plexus-ms/${preset}`;
7898
+ async function findConsumers(ctx, root, presets) {
7899
+ const sources = new Map(presets.map((p) => [presetSource(p), p]));
7900
+ const consumers = /* @__PURE__ */ new Map();
7901
+ const orphans = [];
7902
+ const visit = (dir, repo, inTemplate) => {
7903
+ const here = dir.git ? dir : repo;
7904
+ const template = inTemplate || Boolean(dir.template);
7905
+ const preset = dir.copier?.src ? sources.get(dir.copier.src) : void 0;
7906
+ if (preset && !template) {
7907
+ const site = { path: dir.path, rel: relative(root.path, dir.path) || ".", preset };
7908
+ if (!here)
7909
+ orphans.push(site);
7910
+ else {
7911
+ let consumer = consumers.get(here.path);
7912
+ if (!consumer) {
7913
+ consumer = {
7914
+ path: here.path,
7915
+ rel: relative(root.path, here.path) || ".",
7916
+ branch: here.git?.branch ?? "?",
7917
+ expected: expectedBranch(here.declaration),
7918
+ sites: []
7919
+ };
7920
+ consumers.set(here.path, consumer);
7921
+ }
7922
+ consumer.sites.push(site);
7923
+ }
7924
+ }
7925
+ for (const child of dir.children)
7926
+ visit(child, here, template);
7927
+ };
7928
+ visit(root, void 0, false);
7929
+ for (const site of orphans)
7930
+ ctx.say(`\u26A0 ${site.rel}: not inside a git repo \u2014 skipped`);
7931
+ for (const c of consumers.values()) {
7932
+ if (c.expected && c.branch !== c.expected) {
7933
+ c.skipped = `on '${c.branch}', expected '${c.expected}'`;
7934
+ continue;
7935
+ }
7936
+ const tracked = (await ctx.read("git", ["status", "--porcelain", "--untracked-files=no"], { cwd: c.path })).trim();
7937
+ if (tracked !== "")
7938
+ c.skipped = "has uncommitted changes";
7939
+ }
7940
+ return [...consumers.values()];
7941
+ }
7942
+
7943
+ // ../lib/dist/context.js
7944
+ var Context = class {
7945
+ dryRun;
7946
+ verbose;
7947
+ quiet;
7948
+ yes;
7949
+ json;
7950
+ io;
7951
+ constructor(options, io = realIo()) {
7952
+ this.io = io;
7953
+ this.dryRun = options.dryRun ?? false;
7954
+ this.quiet = options.quiet ?? false;
7955
+ this.verbose = this.quiet ? -1 : options.verbose ?? 0;
7956
+ this.yes = options.yes ?? false;
7957
+ this.json = options.json ?? false;
7958
+ }
7959
+ // --- narration (stderr) ---------------------------------------------------
7960
+ /** One line, if the verbosity allows the level (0 normal, 1 verbose, 2 debug). */
7961
+ say(line, level = 0) {
7962
+ if (this.verbose >= level)
7963
+ this.io.stderr.write(`${line}
7964
+ `);
7965
+ }
7966
+ /** A final outcome line, `✓ ...` or `✗ ...`; shown even under --quiet. */
7967
+ done(line, ok = true) {
7968
+ this.io.stderr.write(`${ok ? "\u2713" : "\u2717"} ${line}
7969
+ `);
7970
+ }
7971
+ // --- results (stdout) -----------------------------------------------------
7972
+ /**
7973
+ * The command's product. `data` is what --json prints; `human` renders it
7974
+ * otherwise (default: strings as they are, arrays one item per line).
7975
+ */
7976
+ result(data, human = renderHuman) {
7977
+ const text = this.json ? JSON.stringify(data, null, 2) : human(data);
7978
+ this.io.stdout.write(text.endsWith("\n") ? text : `${text}
7979
+ `);
7980
+ }
7981
+ // --- reads: always performed ---------------------------------------------
7982
+ /** Run a command for its output. Changes nothing; narrated only when verbose. */
7983
+ read(command, args = [], options = {}) {
7984
+ this.say(`? ${describe({ kind: "run", command, args, ...options })}`, 1);
7985
+ return this.io.exec(command, args, options);
7986
+ }
7987
+ readFile(path3) {
7988
+ this.say(`? read ${path3}`, 1);
7989
+ return this.io.readFile(path3);
7990
+ }
7991
+ readDir(path3) {
7992
+ this.say(`? list ${path3}`, 2);
7993
+ return this.io.readDir(path3);
7994
+ }
7995
+ // --- effects: narrated always, performed unless --dry-run -----------------
7996
+ /**
7997
+ * Ask before applying. `--yes` and `--dry-run` answer yes; off a terminal
7998
+ * without `--yes` the answer is an error, never a hang.
7999
+ */
8000
+ async confirm(question) {
8001
+ if (this.yes || this.dryRun) {
8002
+ this.say(`? ${question} yes (${this.yes ? "--yes" : "--dry-run"})`, 1);
8003
+ return true;
8004
+ }
8005
+ if (!this.io.prompt)
8006
+ throw new Error(`cannot ask "${question}" without a terminal; pass --yes`);
8007
+ return this.io.prompt(question);
8008
+ }
8009
+ /** Narrate and perform each step in order; the first failure stops the run. */
8010
+ async apply(plan) {
8011
+ for (const step of plan) {
8012
+ this.say(`${this.dryRun ? "[dry-run] " : ""}${describe(step)}`);
8013
+ const input = body(step);
8014
+ if (input !== void 0)
8015
+ this.say(indent(input), step.kind === "write" ? 2 : 1);
8016
+ if (!this.dryRun)
8017
+ await this.perform(step);
8018
+ }
8019
+ }
8020
+ /**
8021
+ * Perform a step on scratch state, whatever the mode: the one exception to
8022
+ * "a dry run performs no effect", for a preview that has to run a tool
8023
+ * against a throwaway copy to be honest. Resolves with the output of a run.
8024
+ */
8025
+ stage(step) {
8026
+ this.say(`? ${describe(step)}`, 1);
8027
+ const input = body(step);
8028
+ if (input !== void 0)
8029
+ this.say(indent(input), 2);
8030
+ return this.perform(step);
8031
+ }
8032
+ async perform(step) {
8033
+ const inherit = this.verbose >= 2 || step.kind === "run" && step.interactive === true;
8034
+ switch (step.kind) {
8035
+ case "run":
8036
+ return this.io.exec(step.command, step.args, { cwd: step.cwd, input: step.input, inherit });
8037
+ case "ssh":
8038
+ return this.io.exec("ssh", [step.host, "bash", "-s"], { input: step.script, inherit });
8039
+ case "write":
8040
+ await this.io.writeFile(step.path, step.content);
8041
+ return void 0;
8042
+ }
8043
+ }
8044
+ };
8045
+ function renderHuman(data) {
8046
+ if (typeof data === "string")
8047
+ return data;
8048
+ if (Array.isArray(data))
8049
+ return data.map(String).join("\n");
8050
+ return JSON.stringify(data, null, 2);
8051
+ }
8052
+ function indent(text) {
8053
+ return text.trimEnd().split("\n").map((l) => ` ${l}`).join("\n");
8054
+ }
8055
+
8056
+ // ../lib/dist/copier.js
8057
+ var import_yaml3 = __toESM(require_dist(), 1);
8058
+ var ANSWERS_FILE = ".copier-answers.yml";
8059
+ var TEMPLATE_FILES = ["copier.yml", "copier.yaml"];
8060
+ function parseAnswers(text) {
8061
+ const data = (0, import_yaml3.parse)(text);
8062
+ if (data === null || typeof data !== "object" || Array.isArray(data))
8063
+ throw new Error("answers file is not a mapping");
8064
+ const { _commit, _src_path, ...answers } = data;
8065
+ return {
8066
+ commit: _commit === void 0 ? void 0 : String(_commit),
8067
+ src: _src_path === void 0 ? void 0 : String(_src_path),
8068
+ answers
8069
+ };
8070
+ }
8071
+
8072
+ // ../lib/dist/doctor.js
8073
+ import { relative as relative2 } from "node:path";
8074
+ function diagnose(root, catalog) {
8075
+ const units = collect(root, []);
8076
+ const declarations = units.map((u) => diagnoseUnit(u, units, catalog, root.path));
8077
+ return { declarations, stale: declarations.filter((d) => d.findings.length > 0).length };
8078
+ }
8079
+ function collect(dir, ancestors, parent) {
8080
+ const here = dir.declaration || dir.problems?.some((p) => p.startsWith("PLEXUS.md")) ? [{ dir, ancestors, parent }] : [];
8081
+ const below = dir.declaration ? [...ancestors, dir] : ancestors;
8082
+ return [...here, ...dir.children.flatMap((c) => collect(c, below, dir))];
8083
+ }
8084
+ function diagnoseUnit(unit, units, catalog, root) {
8085
+ const { dir } = unit;
8086
+ const path3 = relative2(root, dir.path) || ".";
8087
+ const problem = dir.problems?.find((p) => p.startsWith("PLEXUS.md"));
8088
+ if (!dir.declaration)
8089
+ return { path: path3, modules: [], findings: [problem?.replace(/^PLEXUS\.md: /, "") ?? "unreadable marker"] };
8090
+ const { plexus, modules } = dir.declaration;
8091
+ const context = new Set(contextOf(unit, units).flatMap((d) => d.declaration?.modules ?? []));
8092
+ const findings = [];
8093
+ for (const code of modules) {
8094
+ const module = catalog.get(code);
8095
+ if (!module) {
8096
+ findings.push(`declares ${code}, which no module carries`);
8097
+ continue;
8098
+ }
8099
+ if (module.changed && compareTrains(module.changed, plexus) > 0)
8100
+ findings.push(`${code} changed in ${module.changed}, declared at ${plexus}`);
8101
+ for (const dep of module.depends)
8102
+ if (!modules.includes(dep) && !context.has(dep))
8103
+ findings.push(`${code} depends on ${dep}, declared neither here nor by an enclosing or contained declaration`);
8104
+ }
8105
+ return { path: path3, plexus, modules, findings };
8106
+ }
8107
+ function contextOf(unit, units) {
8108
+ const { dir, ancestors } = unit;
8109
+ const context = [...ancestors, ...descendants(dir)];
8110
+ const repo = ancestors[0] ?? dir;
8111
+ const repoParent = units.find((u) => u.dir === repo)?.parent;
8112
+ const siblings = repoParent?.children.filter((c) => c !== repo && c.declaration) ?? [];
8113
+ const isTenancy = (d) => d.declaration?.modules.includes("PLX-Tenancy") ?? false;
8114
+ context.push(...siblings.filter(isTenancy));
8115
+ if (isTenancy(dir))
8116
+ context.push(...siblings);
8117
+ return context;
8118
+ }
8119
+ function descendants(dir) {
8120
+ return dir.children.flatMap((c) => [...c.declaration ? [c] : [], ...descendants(c)]);
8121
+ }
8122
+ function compareTrains(a, b) {
8123
+ const nums = (v) => v.split(".").slice(0, 3).map((p) => Number.parseInt(p, 10) || 0);
8124
+ const [x, y] = [nums(a), nums(b)];
8125
+ for (let i = 0; i < 3; i++)
8126
+ if ((x[i] ?? 0) !== (y[i] ?? 0))
8127
+ return (x[i] ?? 0) > (y[i] ?? 0) ? 1 : -1;
8128
+ return 0;
8129
+ }
8130
+
8131
+ // ../lib/dist/model.js
8132
+ function kindOf(declaration) {
8133
+ const has = (code) => declaration.modules.includes(code);
8134
+ if (has("PLX-App"))
8135
+ return "app";
8136
+ if (has("PLX-Platform"))
8137
+ return "platform";
8138
+ if (has("PLX-Repo"))
8139
+ return "repo";
8140
+ return void 0;
8141
+ }
8142
+ function shortRemote(url) {
8143
+ const bare = url.replace(/\.git$/, "").replace(/\/$/, "");
8144
+ const m = /^(?:git@github\.com:|github\.com:|ssh:\/\/git@github\.com\/|https?:\/\/github\.com\/)(.+)$/.exec(bare);
8145
+ return m ? `gh:${m[1]}` : bare;
8146
+ }
8147
+ function isNotable(dir) {
8148
+ return Boolean(dir.git || dir.template || dir.copier || dir.declaration || dir.problems?.length);
8149
+ }
8150
+
8151
+ // ../lib/dist/overview.js
8152
+ import { join as join3 } from "node:path";
8153
+ var PRUNED = /* @__PURE__ */ new Set([
8154
+ "node_modules",
8155
+ ".hg",
8156
+ ".svn",
8157
+ ".next",
8158
+ ".nuxt",
8159
+ ".turbo",
8160
+ ".svelte-kit",
8161
+ "dist",
8162
+ "build",
8163
+ "out",
8164
+ ".output",
8165
+ ".venv",
8166
+ "venv",
8167
+ "__pycache__",
8168
+ "target",
8169
+ ".cache",
8170
+ ".pnpm-store",
8171
+ "coverage",
8172
+ "vendor",
8173
+ ".terraform",
8174
+ ".gradle"
8175
+ ]);
8176
+ function overview(ctx, root, options = {}) {
8177
+ return walk(ctx, root, root.replace(/\/+$/, "").split("/").pop() || root, { git: true, ...options });
8178
+ }
8179
+ async function walk(ctx, path3, name, options) {
8180
+ const entries = await ctx.readDir(path3);
8181
+ const files = new Set(entries.filter((e) => !e.directory).map((e) => e.name));
8182
+ const names = new Set(entries.map((e) => e.name));
8183
+ const dir = { name, path: path3, children: [] };
8184
+ if (names.has(".git") && options.git)
8185
+ dir.git = await gitFacet(ctx, path3);
8186
+ if (TEMPLATE_FILES.some((f) => files.has(f)))
8187
+ dir.template = options.git ? await templateFacet(ctx, path3) : {};
8188
+ if (files.has(ANSWERS_FILE)) {
8189
+ await facet(ctx, dir, ANSWERS_FILE, (text) => {
8190
+ dir.copier = parseAnswers(text);
8191
+ });
8192
+ }
8193
+ if (files.has(MARKER_FILE)) {
8194
+ await facet(ctx, dir, MARKER_FILE, (text) => {
8195
+ dir.declaration = parseMarker(text);
8196
+ });
8197
+ }
8198
+ const subdirs = entries.filter((e) => e.directory && e.name !== ".git" && !PRUNED.has(e.name)).map((e) => e.name).sort();
8199
+ for (const sub of subdirs) {
8200
+ const child = await walk(ctx, join3(path3, sub), sub, options);
8201
+ if (isNotable(child) || child.children.length > 0)
8202
+ dir.children.push(child);
8203
+ }
8204
+ return dir;
8205
+ }
8206
+ async function facet(ctx, dir, file, read) {
8207
+ try {
8208
+ read(await ctx.readFile(join3(dir.path, file)));
8209
+ } catch (error) {
8210
+ dir.problems ??= [];
8211
+ dir.problems.push(`${file}: ${error instanceof Error ? error.message : String(error)}`);
8212
+ }
8213
+ }
8214
+ async function git(ctx, cwd, args) {
8215
+ try {
8216
+ const out = (await ctx.read("git", args, { cwd })).trim();
8217
+ return out === "" ? void 0 : out;
8218
+ } catch {
8219
+ return void 0;
8220
+ }
8221
+ }
8222
+ async function gitFacet(ctx, cwd) {
8223
+ const branch = await git(ctx, cwd, ["symbolic-ref", "--short", "-q", "HEAD"]) ?? await git(ctx, cwd, ["rev-parse", "--short", "HEAD"]) ?? "?";
8224
+ const dirty = await git(ctx, cwd, ["status", "--porcelain"]) !== void 0;
8225
+ const remote = await git(ctx, cwd, ["remote", "get-url", "origin"]);
8226
+ let defaultRef = await git(ctx, cwd, ["symbolic-ref", "--short", "-q", "refs/remotes/origin/HEAD"]);
8227
+ for (const b of ["main", "master"]) {
8228
+ if (defaultRef)
8229
+ break;
8230
+ if (await git(ctx, cwd, ["rev-parse", "--verify", "-q", `refs/heads/${b}`]))
8231
+ defaultRef = b;
8232
+ }
8233
+ const tag = defaultRef ? await git(ctx, cwd, ["describe", "--tags", "--abbrev=0", defaultRef]) : void 0;
8234
+ const facet2 = { branch, dirty };
8235
+ if (tag)
8236
+ facet2.tag = tag;
8237
+ if (remote)
8238
+ facet2.remote = shortRemote(remote);
8239
+ return facet2;
8240
+ }
8241
+ async function templateFacet(ctx, cwd) {
8242
+ const tag = await git(ctx, cwd, ["describe", "--tags", "--abbrev=0"]) ?? (await git(ctx, cwd, ["tag", "--list", "--sort=-v:refname"]))?.split("\n")[0];
8243
+ return tag ? { tag } : {};
8244
+ }
8245
+
8246
+ // ../lib/dist/propagate.js
8247
+ import { join as join5, relative as relative3 } from "node:path";
8248
+
8249
+ // ../lib/dist/train.js
8250
+ import { join as join4 } from "node:path";
8251
+ var TRAIN_REPOS = [
8252
+ "platform",
8253
+ "ci-cd",
8254
+ "preset-repo-web",
8255
+ "preset-app-nextjs",
8256
+ "preset-repo-platform",
8257
+ "compendium"
8258
+ ];
8259
+ var UPSTREAM = "plexus-ms";
8260
+ var isTrainVersion = (v) => /^\d+\.\d+\.\d+$/.test(v);
8261
+ function nextMinor(version2) {
8262
+ const [major = "0", minor = "0"] = version2.split(".");
8263
+ return `${major}.${Number(minor) + 1}.0`;
8264
+ }
8265
+ function latestTag(tags) {
8266
+ return tags.filter((t) => /^v?\d/.test(t)).sort((a, b) => compareTrains(a.replace(/^v/, ""), b.replace(/^v/, ""))).at(-1);
8267
+ }
8268
+ async function readTrain(ctx, upstream) {
8269
+ const repos = [];
8270
+ const all = /* @__PURE__ */ new Set();
8271
+ for (const name of TRAIN_REPOS) {
8272
+ const path3 = join4(upstream, name);
8273
+ try {
8274
+ await ctx.read("git", ["rev-parse", "--git-dir"], { cwd: path3 });
8275
+ } catch {
8276
+ throw new Error(`${path3} is not a git repo`);
8277
+ }
8278
+ try {
8279
+ await ctx.read("git", ["fetch", "origin", "--tags", "--quiet"], { cwd: path3 });
8280
+ } catch {
8281
+ throw new Error(`${name}: fetch from origin failed`);
8282
+ }
8283
+ const tags = (await ctx.read("git", ["tag", "--list", "v*", "[0-9]*"], { cwd: path3 })).split("\n").filter(Boolean);
8284
+ for (const t of tags)
8285
+ all.add(t.replace(/^v/, ""));
8286
+ const tag = latestTag(tags);
8287
+ const range = tag ? `${tag}..HEAD` : "HEAD";
8288
+ const pending = (await ctx.read("git", ["log", "--oneline", range], { cwd: path3 })).split("\n").filter(Boolean);
8289
+ repos.push({ name, path: path3, tag, latest: tag?.replace(/^v/, ""), pending });
8290
+ }
8291
+ const latest = repos.map((r) => r.latest);
8292
+ return { repos, last: latestTag([...all]), skew: latest.some((l) => l !== latest[0]) };
8293
+ }
8294
+ async function preflightRelease(ctx, train) {
8295
+ for (const { name, path: path3 } of train.repos) {
8296
+ const branch = (await ctx.read("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: path3 })).trim();
8297
+ if (branch !== "main")
8298
+ throw new Error(`${name} is on '${branch}', trains cut from main`);
8299
+ if ((await ctx.read("git", ["status", "--porcelain"], { cwd: path3 })).trim() !== "")
8300
+ throw new Error(`${name} has uncommitted changes \u2014 commit first`);
8301
+ const behind = (await ctx.read("git", ["rev-list", "--count", "main..origin/main"], { cwd: path3 })).trim();
8302
+ if (behind !== "0")
8303
+ throw new Error(`${name} is ${behind} commit(s) behind origin/main \u2014 pull first, or the tag lands on a stale commit`);
8304
+ }
8305
+ }
8306
+ function resolveVersion(train, explicit, propagateOnly) {
8307
+ if (explicit !== void 0 && !isTrainVersion(explicit))
8308
+ throw new UsageError(`'${explicit}' is not plain semver (X.Y.Z, no v)`);
8309
+ if (propagateOnly) {
8310
+ const v = explicit ?? train.last;
8311
+ if (!v)
8312
+ throw new Error("no train version found to propagate");
8313
+ return v;
8314
+ }
8315
+ if (explicit)
8316
+ return explicit;
8317
+ if (train.skew) {
8318
+ const report = train.repos.map((r) => ` ${r.name}: ${r.latest ?? "none"}`).join("\n");
8319
+ throw new Error(`the train repos' latest tags disagree:
8320
+ ${report}
8321
+ pass the version explicitly (--train ${train.last}) to finish the half-tagged train, or a higher one to start a new one`);
8322
+ }
8323
+ return train.last ? nextMinor(train.last) : "0.1.0";
8324
+ }
8325
+ var UsageError = class extends Error {
8326
+ };
8327
+
8328
+ // ../lib/dist/propagate.js
8329
+ var isClean = (s) => s.conflicted.length === 0 && s.failed.length === 0 && s.skipped.length === 0;
8330
+ var PREVIEW_BASE = "ship-base";
8331
+ async function propagate(ctx, workspace, train) {
8332
+ const summary = { train, preview: ctx.dryRun, clean: [], conflicted: [], failed: [], skipped: [] };
8333
+ const upstream = join5(workspace, UPSTREAM);
8334
+ const tree = await overview(ctx, workspace);
8335
+ const upstreamDir = tree.children.find((c) => c.path === upstream);
8336
+ const presets = TRAIN_REPOS.filter((r) => upstreamDir?.children.some((c) => c.name === r && c.template));
8337
+ const consumers = await findConsumers(ctx, tree, presets);
8338
+ for (const c of consumers) {
8339
+ if (!c.skipped)
8340
+ continue;
8341
+ ctx.say(`\u26A0 ${c.rel}: ${c.skipped} \u2014 skipped (fix it, then re-run propagate)`);
8342
+ summary.skipped.push({ path: c.rel, reason: c.skipped });
8343
+ }
8344
+ const active = consumers.filter((c) => !c.skipped);
8345
+ const scratch = ctx.dryRun ? (await ctx.stage(run("mktemp", ["-d"])))?.trim() : void 0;
8346
+ const clones = /* @__PURE__ */ new Map();
8347
+ const cloneOf = async (consumer) => {
8348
+ let clone = clones.get(consumer.path);
8349
+ if (!clone) {
8350
+ clone = join5(scratch ?? "", consumer.rel);
8351
+ await ctx.stage(run("git", ["clone", "--quiet", consumer.path, clone]));
8352
+ await ctx.stage(run("git", ["tag", PREVIEW_BASE], { cwd: clone }));
8353
+ clones.set(consumer.path, clone);
8354
+ }
8355
+ return clone;
8356
+ };
8357
+ const previewCommit = (clone, message) => ctx.stage(run("git", ["add", "-A"], { cwd: clone })).then(() => ctx.stage(run("git", [
8358
+ "-c",
8359
+ "commit.gpgsign=false",
8360
+ "-c",
8361
+ "user.name=plx",
8362
+ "-c",
8363
+ "user.email=plx@localhost",
8364
+ "commit",
8365
+ "--quiet",
8366
+ "--no-verify",
8367
+ "--allow-empty",
8368
+ "-m",
8369
+ message
8370
+ ], { cwd: clone })));
8371
+ try {
8372
+ for (const preset of presets) {
8373
+ const sites = active.flatMap((c) => c.sites.filter((s) => s.preset === preset).map((s) => [c, s]));
8374
+ if (sites.length === 0)
8375
+ ctx.say(`\u2022 no consumers of ${presetSource(preset)} found under ${workspace}`);
8376
+ for (const [consumer, site] of sites)
8377
+ await updateSite(ctx, consumer, site, join5(upstream, preset), summary, cloneOf, previewCommit);
8378
+ }
8379
+ await refreshLockfiles(ctx, active, summary, clones);
8380
+ await bumpConsumerRefs(ctx, consumers, train);
8381
+ } finally {
8382
+ if (scratch)
8383
+ await ctx.stage(run("rm", ["-rf", scratch]));
8384
+ }
8385
+ return summary;
8386
+ }
8387
+ async function updateSite(ctx, consumer, site, localPreset, summary, cloneOf, previewCommit) {
8388
+ let repo = consumer.path;
8389
+ let target = site.path;
8390
+ try {
8391
+ if (ctx.dryRun) {
8392
+ ctx.say(`\u2192 ${site.rel}: copier update (preview from ${localPreset}@main)`);
8393
+ repo = await cloneOf(consumer);
8394
+ target = join5(repo, relative3(consumer.path, site.path));
8395
+ const answers = await ctx.readFile(join5(site.path, ANSWERS_FILE));
8396
+ await ctx.stage(write(join5(target, ANSWERS_FILE), answers.replace(/^_src_path: .*$/m, `_src_path: ${localPreset}`)));
8397
+ await previewCommit(repo, `plx preview: ${site.rel} reads ${localPreset} from the local checkout`);
8398
+ await ctx.stage(run("copier", ["update", "--skip-answered", "--trust", "--defaults", "--skip-tasks", "--vcs-ref", "main"], {
8399
+ cwd: target
8400
+ }));
8401
+ } else {
8402
+ ctx.say(`\u2192 ${site.rel}: copier update`);
8403
+ const args = ["update", "--skip-answered", "--trust", ...ctx.yes ? ["--defaults"] : []];
8404
+ await ctx.apply([run("copier", args, { cwd: target, interactive: true })]);
8405
+ }
8406
+ } catch (error) {
8407
+ ctx.say(` \u2717 FAILED \u2014 copier update exited nonzero${detail(error)}`);
8408
+ summary.failed.push(site.rel);
8409
+ return;
8410
+ }
8411
+ const status = await ctx.read("git", ["status", "--porcelain"], { cwd: repo });
8412
+ let conflict = hasUnmergedEntries(status);
8413
+ const changed = (await ctx.read("git", ["diff", "--name-only"], { cwd: repo })).split("\n").filter(Boolean);
8414
+ for (const f of changed) {
8415
+ const text = await ctx.readFile(join5(repo, f)).catch(() => "");
8416
+ if (hasConflictMarkers(text))
8417
+ conflict = true;
8418
+ }
8419
+ await syncSiteMarker(ctx, site, target);
8420
+ if (conflict) {
8421
+ ctx.say(" \u2717 CONFLICTS \u2014 resolve the <<<<<<< markers, then git add:");
8422
+ summary.conflicted.push(site.rel);
8423
+ } else {
8424
+ ctx.say(" \u2713 merged clean:");
8425
+ summary.clean.push(site.rel);
8426
+ }
8427
+ for (const line of status.split("\n").filter(Boolean))
8428
+ ctx.say(` ${line}`);
8429
+ if (ctx.dryRun)
8430
+ await previewCommit(repo, `plx preview: ${site.rel} updated`);
8431
+ }
8432
+ async function syncSiteMarker(ctx, site, target) {
8433
+ const marker = await ctx.readFile(join5(target, MARKER_FILE)).catch(() => void 0);
8434
+ if (marker === void 0)
8435
+ return;
8436
+ const { commit } = parseAnswers(await ctx.readFile(join5(target, ANSWERS_FILE)));
8437
+ if (!commit)
8438
+ return;
8439
+ const synced = syncMarker(marker, commit);
8440
+ if (synced === marker)
8441
+ return;
8442
+ ctx.say(` marker: plexus \u2192 ${commit} in ${site.rel}/${MARKER_FILE}`);
8443
+ const step = write(join5(target, MARKER_FILE), synced);
8444
+ if (ctx.dryRun)
8445
+ await ctx.stage(step);
8446
+ else
8447
+ await ctx.apply([step]);
8448
+ }
8449
+ async function refreshLockfiles(ctx, consumers, summary, clones) {
8450
+ const manifests = ["*package.json", "pnpm-workspace.yaml"];
8451
+ for (const c of consumers) {
8452
+ if (await ctx.readFile(join5(c.path, "pnpm-workspace.yaml")).catch(() => void 0) === void 0)
8453
+ continue;
8454
+ const repo = ctx.dryRun ? clones.get(c.path) : c.path;
8455
+ if (!repo)
8456
+ continue;
8457
+ const range = ctx.dryRun ? [PREVIEW_BASE] : [];
8458
+ const unchanged = await ctx.read("git", ["diff", "--quiet", ...range, "--", ...manifests], { cwd: repo }).then(() => true).catch(() => false);
8459
+ if (unchanged)
8460
+ continue;
8461
+ ctx.say(`\u2192 ${c.rel}: pnpm install (manifests changed)`);
8462
+ try {
8463
+ await ctx.apply([run("mise", ["exec", "--", "pnpm", "install", "--reporter=silent"], { cwd: c.path })]);
8464
+ } catch (error) {
8465
+ ctx.say(` \u2717 pnpm install failed${detail(error)}`);
8466
+ summary.failed.push(`${c.rel}/pnpm-lock.yaml`);
8467
+ }
8468
+ }
8469
+ }
8470
+ async function bumpConsumerRefs(ctx, consumers, train) {
8471
+ for (const c of consumers) {
8472
+ const dir = join5(c.path, ".github", "workflows");
8473
+ const entries = await ctx.readDir(dir).catch(() => []);
8474
+ const files = entries.filter((e) => !e.directory && /\.ya?ml$/.test(e.name)).map((e) => e.name).sort();
8475
+ if (files.length === 0)
8476
+ continue;
8477
+ if (c.skipped) {
8478
+ ctx.say(`\u26A0 ${c.rel}: workflow refs not bumped (skipped above)`);
8479
+ continue;
8480
+ }
8481
+ for (const f of files) {
8482
+ const text = await ctx.readFile(join5(dir, f));
8483
+ if (!text.includes(WORKFLOW_REF))
8484
+ continue;
8485
+ const bumped = bumpWorkflowRefs(text, train);
8486
+ if (bumped === text)
8487
+ continue;
8488
+ ctx.say(`\u2192 ${c.rel}: ${f} ci-cd refs \u2192 @${train}`);
8489
+ await ctx.apply([write(join5(dir, f), bumped)]);
8490
+ }
8491
+ }
8492
+ }
8493
+ var detail = (error) => {
8494
+ const message = error instanceof Error ? error.message : String(error);
8495
+ const last = message.trim().split("\n").at(-1) ?? "";
8496
+ return last && !/exited with/.test(last) ? `: ${last}` : "";
8497
+ };
8498
+
8499
+ // ../lib/dist/requirements.js
8500
+ import { join as join6 } from "node:path";
8501
+ var KEYWORD = /MUST|SHOULD|MAY/;
8502
+ var hasKeyword = (line) => KEYWORD.test(line.replace(/MUSTs|SHOULDs|MAYs/g, ""));
8503
+ var list = (value) => value.replace(/^\s*\[/, "").replace(/\].*$/, "").split(",").map((s) => s.trim()).filter(Boolean);
8504
+ function scanPage(text, name, mode) {
8505
+ const scan = { defects: [], requirements: [], depends: [], consumes: [] };
8506
+ const lines = text.split("\n");
8507
+ const defect = (n, msg) => scan.defects.push(`\u2717 ${name}: line ${n + 1}: ${msg}`);
8508
+ let i = 0;
8509
+ if (lines[0] === "---") {
8510
+ for (i = 1; i < lines.length && lines[i] !== "---"; i++) {
8511
+ const line = lines[i] ?? "";
8512
+ const [key = "", ...rest] = line.split(/\s+/);
8513
+ const value = rest.join(" ");
8514
+ if (key === "maturity:")
8515
+ scan.maturity = rest[0];
8516
+ else if (key === "code:")
8517
+ scan.code = rest[0];
8518
+ else if (key === "binds:")
8519
+ scan.binds = rest[0];
8520
+ else if (key === "depends:")
8521
+ scan.depends = list(value);
8522
+ else if (key === "consumes:")
8523
+ scan.consumes = list(value);
8524
+ else if (key === "kind:")
8525
+ defect(i, "kind is the folder, contracts/ or approaches/, not a field");
8526
+ }
8527
+ i++;
8528
+ }
8529
+ let inCode = false;
8530
+ let maintaining = false;
8531
+ let started = false;
8532
+ let section = "";
8533
+ for (; i < lines.length; i++) {
8534
+ const line = lines[i] ?? "";
8535
+ if (line.startsWith("```")) {
8536
+ inCode = !inCode;
8537
+ continue;
8538
+ }
8539
+ if (inCode)
8540
+ continue;
8541
+ if (line === "## Maintaining") {
8542
+ maintaining = true;
8543
+ section = "";
8544
+ continue;
8545
+ }
8546
+ const heading = /^#+ § (\S+)/.exec(line);
8547
+ if (heading) {
8548
+ if (maintaining)
8549
+ defect(i, "numbered section after Maintaining");
8550
+ section = heading[1] ?? "";
8551
+ started = true;
8552
+ continue;
8553
+ }
8554
+ if (line.startsWith("> - ")) {
8555
+ if (mode === "map")
8556
+ defect(i, `requirement in the map: ${line}`);
8557
+ else if (scan.maturity !== "standard")
8558
+ defect(i, `requirement in a module at ${scan.maturity} maturity: ${line}`);
8559
+ else if (maintaining)
8560
+ defect(i, `requirement under Maintaining: ${line}`);
8561
+ else if (!started)
8562
+ defect(i, "requirement before the first \xA7 heading");
8563
+ else
8564
+ scan.requirements.push(`\xA7 ${section} ${line.slice(4)}`);
8565
+ continue;
8566
+ }
8567
+ if (line.startsWith(">")) {
8568
+ defect(i, 'blockquote line is not a "> - " requirement bullet');
8569
+ continue;
8570
+ }
8571
+ if (hasKeyword(line))
8572
+ defect(i, `BCP 14 keyword outside a requirement: ${line}`);
8573
+ }
8574
+ if (mode === "module") {
8575
+ const { maturity = "", binds = "", code = "" } = scan;
8576
+ const n = text.endsWith("\n") ? lines.length - 1 : lines.length;
8577
+ if (!/^(note|candidate|standard)$/.test(maturity))
8578
+ defect(n - 1, `maturity must be note, candidate or standard, not "${maturity}"`);
8579
+ if (!/^(repo|app|host|organisation)$/.test(binds))
8580
+ defect(n - 1, `binds must be repo, app, host or organisation, not "${binds}"`);
8581
+ if (maturity === "note" && code !== "")
8582
+ defect(n - 1, "a note carries no code");
8583
+ if (maturity !== "note" && !/^PLX-[A-Z][A-Za-z]+$/.test(code))
8584
+ defect(n - 1, `code must be PLX- plus one capitalised word, not "${code}"`);
8585
+ }
8586
+ return scan;
8587
+ }
8588
+ var extractRequirements = (text) => scanPage(text, "", "module").requirements;
8589
+ var MAP_PAGE = "essentials/standard.md";
8590
+ async function modulePages(ctx, compendium) {
8591
+ const pages = [];
8592
+ for (const dir of Object.keys(CATALOG_DIRS)) {
8593
+ const entries = await ctx.readDir(join6(compendium, dir));
8594
+ for (const e of entries.filter((e2) => !e2.directory && e2.name.endsWith(".md") && e2.name !== "index.md").sort())
8595
+ pages.push(`${dir}/${e.name}`);
8596
+ }
8597
+ return pages;
8598
+ }
8599
+ async function checkCompendium(ctx, compendium) {
8600
+ const defects = [];
8601
+ defects.push(...scanPage(await ctx.readFile(join6(compendium, MAP_PAGE)), MAP_PAGE, "map").defects);
8602
+ const pages = await modulePages(ctx, compendium);
8603
+ const scans = /* @__PURE__ */ new Map();
8604
+ for (const page of pages) {
8605
+ const scan = scanPage(await ctx.readFile(join6(compendium, page)), page, "module");
8606
+ defects.push(...scan.defects);
8607
+ scans.set(page, scan);
8608
+ }
8609
+ const byCode = /* @__PURE__ */ new Map();
8610
+ for (const [page, s] of scans)
8611
+ if (s.code)
8612
+ byCode.set(s.code, [...byCode.get(s.code) ?? [], page]);
8613
+ for (const [code, where] of byCode)
8614
+ if (where.length > 1)
8615
+ defects.push(`\u2717 duplicate module code: ${code}`);
8616
+ for (const s of scans.values())
8617
+ for (const dep of s.depends)
8618
+ if (!byCode.has(dep))
8619
+ defects.push(`\u2717 unknown module in depends: ${dep}`);
8620
+ const kindOf2 = (page) => page.startsWith("contracts/") ? "contract" : "approach";
8621
+ const side = (binds2) => binds2 === "repo" || binds2 === "app" ? "dev" : "ops";
8622
+ const kinds = new Map([...byCode].map(([code, [page = ""]]) => [code, kindOf2(page)]));
8623
+ const binds = new Map([...byCode].map(([code, [page = ""]]) => [code, scans.get(page)?.binds ?? ""]));
8624
+ for (const [page, s] of scans) {
8625
+ const m = s.code ?? page.replace(/.*\//, "");
8626
+ const kind = kindOf2(page);
8627
+ for (const c of s.consumes) {
8628
+ if (kind === "contract")
8629
+ defects.push(`\u2717 ${m} is a contract and consumes ${c}; a contract has no other side to consume`);
8630
+ else if (kinds.has(c) && kinds.get(c) !== "contract")
8631
+ defects.push(`\u2717 ${m} consumes ${c}, which is an approach; only a contract is consumed across a seam`);
8632
+ else if (!kinds.has(c))
8633
+ defects.push(`\u2717 ${m} consumes unknown module ${c}`);
8634
+ }
8635
+ for (const d of s.depends) {
8636
+ if (!kinds.has(d))
8637
+ continue;
8638
+ if (kind === "contract" && kinds.get(d) !== "contract")
8639
+ defects.push(`\u2717 ${m} is a contract and depends on the approach ${d}`);
8640
+ if (side(s.binds ?? "") !== side(binds.get(d) ?? "") && kinds.get(d) !== "contract")
8641
+ defects.push(`\u2717 ${m} (${s.binds}) depends on ${d} (${binds.get(d)}) across the dev/ops seam; only a contract may be depended on across a seam`);
8642
+ }
8643
+ }
8644
+ return {
8645
+ defects,
8646
+ contracts: pages.filter((p) => p.startsWith("contracts/")).length,
8647
+ approaches: pages.filter((p) => p.startsWith("approaches/")).length
8648
+ };
8649
+ }
8650
+
8651
+ // ../lib/dist/ship.js
8652
+ import { join as join7 } from "node:path";
8653
+ async function ship(ctx, options) {
8654
+ const upstream = join7(options.workspace, UPSTREAM);
8655
+ const propagateOnly = options.propagateOnly ?? false;
8656
+ const train = await readTrain(ctx, upstream);
8657
+ if (!propagateOnly)
8658
+ await preflightRelease(ctx, train);
8659
+ const next = resolveVersion(train, options.train, propagateOnly);
8660
+ if (!propagateOnly)
8661
+ await release(ctx, train, next, options.today ?? today());
8662
+ const summary = await propagate(ctx, options.workspace, next);
8663
+ return { ...summary, released: !propagateOnly };
8664
+ }
8665
+ async function release(ctx, train, next, today2) {
8666
+ ctx.say(`\u2192 train ${train.last ?? "none"} \u2192 ${next}`);
8667
+ for (const repo of train.repos) {
8668
+ if (repo.pending.length === 0)
8669
+ ctx.say(` ${repo.name}: no changes since ${repo.latest} \u2014 tag only`);
8670
+ else {
8671
+ ctx.say(` ${repo.name} (since ${repo.latest ?? "the beginning"}):`);
8672
+ for (const line of repo.pending)
8673
+ ctx.say(` ${line}`);
8674
+ }
8675
+ }
8676
+ if (!await ctx.confirm(`tag all ${train.repos.length} repos as ${next} and push?`))
8677
+ throw new Error("aborted");
8678
+ try {
8679
+ const plan = await planBookkeeping(ctx, train, next, today2);
8680
+ await ctx.apply(plan);
8681
+ for (const repo of train.repos) {
8682
+ const tagged = await ctx.read("git", ["rev-parse", "-q", "--verify", `refs/tags/${next}`], { cwd: repo.path }).then(() => true).catch(() => false);
8683
+ if (tagged)
8684
+ ctx.say(`\u2022 ${repo.name}: already tagged ${next}`);
8685
+ else
8686
+ await ctx.apply([run("git", ["tag", "-a", next, "-m", `train ${next}`], { cwd: repo.path })]);
8687
+ await ctx.apply([run("git", ["push", "origin", "main", next], { cwd: repo.path })]);
8688
+ }
8689
+ } catch (error) {
8690
+ const message = error instanceof Error ? error.message : String(error);
8691
+ throw new Error(`${message}
8692
+ \u2717 ship stopped during the release; re-run with --train ${next} to finish it (tagged repos are skipped)`);
8693
+ }
8694
+ }
8695
+ async function planBookkeeping(ctx, train, next, today2) {
8696
+ const plan = [];
8697
+ const touched = /* @__PURE__ */ new Set();
8698
+ const repo = (name) => {
8699
+ const r = train.repos.find((r2) => r2.name === name);
8700
+ if (!r)
8701
+ throw new Error(`${name} is not a train repo`);
8702
+ return r;
8703
+ };
8704
+ const edit = async (r, rel, what, transform) => {
8705
+ const path3 = join7(r.path, rel);
8706
+ const text = await ctx.readFile(path3).catch(() => void 0);
8707
+ if (text === void 0)
8708
+ return;
8709
+ const edited = transform(text);
8710
+ if (edited === text)
8711
+ return;
8712
+ ctx.say(` ${r.name}: ${rel}: ${what}`);
8713
+ plan.push(write(path3, edited));
8714
+ touched.add(r);
8715
+ };
8716
+ await edit(repo("platform"), "ansible/galaxy.yml", `version \u2192 ${next}`, (t) => bumpGalaxyVersion(t, next));
8717
+ await edit(repo("preset-repo-platform"), "template/requirements.yml", `plexus.platform pin \u2192 ${next}`, (t) => bumpCollectionPin(t, next));
8718
+ for (const r of train.repos) {
8719
+ const files = await ctx.read("git", ["grep", "-l", WORKFLOW_REF, "--", "*.yml", "*.yaml", "*.jinja"], { cwd: r.path }).catch(() => "");
8720
+ for (const f of files.split("\n").filter(Boolean))
8721
+ await edit(r, f, `ci-cd refs \u2192 @${next}`, (t) => bumpWorkflowRefs(t, next));
8722
+ }
8723
+ const comp = repo("compendium");
8724
+ await edit(comp, MAP_PAGE, `version \u2192 ${next}, timestamp \u2192 ${today2}`, (t) => stampStandard(t, next, today2));
8725
+ for (const page of await modulePages(ctx, comp.path)) {
8726
+ const text = await ctx.readFile(join7(comp.path, page));
8727
+ if (frontmatterField(text, "maturity") !== "standard")
8728
+ continue;
8729
+ const previous = comp.tag ? await ctx.read("git", ["show", `${comp.tag}:${page}`], { cwd: comp.path }).catch(() => "") : "";
8730
+ if (extractRequirements(text).join("\n") === extractRequirements(previous).join("\n"))
8731
+ continue;
8732
+ await edit(comp, page, `requirements changed since ${comp.latest ?? "the beginning"} \u2192 changed: ${next}`, (t) => stampChanged(t, next));
8733
+ }
8734
+ for (const r of train.repos) {
8735
+ if (!touched.has(r))
8736
+ continue;
8737
+ plan.push(run("git", ["add", "-A"], { cwd: r.path }));
8738
+ plan.push(run("git", ["commit", "--quiet", "-m", `chore: train ${next} bookkeeping`], { cwd: r.path }));
8739
+ }
8740
+ return plan;
8741
+ }
8742
+
8743
+ // src/program.ts
8744
+ import { createRequire } from "node:module";
8745
+
8746
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/key.js
8747
+ var keybindings = ["emacs", "vim"];
8748
+ var keybindingLookup = new Set(keybindings);
8749
+ function isKeybinding(value) {
8750
+ return keybindingLookup.has(value);
8751
+ }
8752
+ function getDefaultKeybindings() {
8753
+ const env = process.env["INQUIRER_KEYBINDINGS"];
8754
+ if (!env)
8755
+ return [];
8756
+ return Array.from(new Set(env.toLowerCase().split(/[\s,]+/).filter(isKeybinding)));
8757
+ }
8758
+ var isTabKey = (key) => key.name === "tab";
8759
+ var isEnterKey = (key) => key.name === "enter" || key.name === "return";
8760
+
8761
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/errors.js
8762
+ var AbortPromptError = class extends Error {
8763
+ name = "AbortPromptError";
8764
+ message = "Prompt was aborted";
8765
+ constructor(options) {
8766
+ super();
8767
+ this.cause = options?.cause;
8768
+ }
8769
+ };
8770
+ var CancelPromptError = class extends Error {
8771
+ name = "CancelPromptError";
8772
+ message = "Prompt was canceled";
8773
+ };
8774
+ var ExitPromptError = class extends Error {
8775
+ name = "ExitPromptError";
8776
+ };
8777
+ var HookError = class extends Error {
8778
+ name = "HookError";
8779
+ };
8780
+ var ValidationError = class extends Error {
8781
+ name = "ValidationError";
8782
+ };
8783
+
8784
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-state.js
8785
+ import { AsyncResource as AsyncResource2 } from "node:async_hooks";
8786
+
8787
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/hook-engine.js
8788
+ import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
8789
+ var hookStorage = new AsyncLocalStorage();
8790
+ function createStore(rl) {
8791
+ const store = {
8792
+ rl,
8793
+ hooks: [],
8794
+ hooksCleanup: [],
8795
+ hooksEffect: [],
8796
+ index: 0,
8797
+ handleChange() {
8798
+ }
8799
+ };
8800
+ return store;
8801
+ }
8802
+ function withHooks(rl, cb) {
8803
+ const store = createStore(rl);
8804
+ function cycle(render2) {
8805
+ store.handleChange = () => {
8806
+ store.index = 0;
8807
+ render2();
8808
+ };
8809
+ store.handleChange();
8810
+ }
8811
+ return hookStorage.run(store, () => cb(cycle));
8812
+ }
8813
+ function getStore() {
8814
+ const store = hookStorage.getStore();
8815
+ if (!store) {
8816
+ throw new HookError("[Inquirer] Hook functions can only be called from within a prompt");
8817
+ }
8818
+ return store;
8819
+ }
8820
+ function readline() {
8821
+ return getStore().rl;
8822
+ }
8823
+ function withUpdates(fn) {
8824
+ const wrapped = (...args) => {
8825
+ const store = getStore();
8826
+ let shouldUpdate = false;
8827
+ const oldHandleChange = store.handleChange;
8828
+ store.handleChange = () => {
8829
+ shouldUpdate = true;
8830
+ };
8831
+ const returnValue = fn(...args);
8832
+ if (shouldUpdate) {
8833
+ oldHandleChange();
8834
+ }
8835
+ store.handleChange = oldHandleChange;
8836
+ return returnValue;
8837
+ };
8838
+ return AsyncResource.bind(wrapped);
8839
+ }
8840
+ function withPointer(cb) {
8841
+ const store = getStore();
8842
+ const { index } = store;
8843
+ const pointer = {
8844
+ get() {
8845
+ return store.hooks[index];
8846
+ },
8847
+ set(value) {
8848
+ store.hooks[index] = value;
8849
+ },
8850
+ initialized: index in store.hooks
8851
+ };
8852
+ const returnValue = cb(pointer);
8853
+ store.index++;
8854
+ return returnValue;
8855
+ }
8856
+ function handleChange() {
8857
+ getStore().handleChange();
8858
+ }
8859
+ var effectScheduler = {
8860
+ queue(cb) {
8861
+ const store = getStore();
8862
+ const { index } = store;
8863
+ store.hooksEffect.push(() => {
8864
+ store.hooksCleanup[index]?.();
8865
+ const cleanFn = cb(readline());
8866
+ if (cleanFn != null && typeof cleanFn !== "function") {
8867
+ throw new ValidationError("useEffect return value must be a cleanup function or nothing.");
8868
+ }
8869
+ store.hooksCleanup[index] = cleanFn;
8870
+ });
8871
+ },
8872
+ run() {
8873
+ const store = getStore();
8874
+ withUpdates(() => {
8875
+ store.hooksEffect.forEach((effect) => {
8876
+ effect();
8877
+ });
8878
+ store.hooksEffect.length = 0;
8879
+ })();
8880
+ },
8881
+ clearAll() {
8882
+ const store = getStore();
8883
+ store.hooksCleanup.forEach((cleanFn) => {
8884
+ cleanFn?.();
8885
+ });
8886
+ store.hooksEffect.length = 0;
8887
+ store.hooksCleanup.length = 0;
8888
+ }
8889
+ };
8890
+
8891
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-state.js
8892
+ function isFactory(value) {
8893
+ return typeof value === "function";
8894
+ }
8895
+ function isReducer(value) {
8896
+ return typeof value === "function";
8897
+ }
8898
+ function useState(defaultValue) {
8899
+ return withPointer((pointer) => {
8900
+ const setState = AsyncResource2.bind(function setState2(newValue) {
8901
+ const currentValue = pointer.get();
8902
+ const nextValue = isReducer(newValue) ? newValue(currentValue) : newValue;
8903
+ if (!Object.is(currentValue, nextValue)) {
8904
+ pointer.set(nextValue);
8905
+ handleChange();
8906
+ }
8907
+ });
8908
+ if (pointer.initialized) {
8909
+ return [pointer.get(), setState];
8910
+ }
8911
+ const value = isFactory(defaultValue) ? defaultValue() : defaultValue;
8912
+ pointer.set(value);
8913
+ return [value, setState];
8914
+ });
8915
+ }
8916
+
8917
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-effect.js
8918
+ function useEffect(cb, depArray) {
7712
8919
  withPointer((pointer) => {
7713
8920
  const oldDeps = pointer.get();
7714
8921
  const hasChanged = !Array.isArray(oldDeps) || depArray.some((dep, i) => !Object.is(dep, oldDeps[i]));
@@ -7719,7 +8926,7 @@ function useEffect(cb, depArray) {
7719
8926
  });
7720
8927
  }
7721
8928
 
7722
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/theme.js
8929
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/theme.js
7723
8930
  import { styleText } from "node:util";
7724
8931
 
7725
8932
  // ../../node_modules/.pnpm/@inquirer+figures@2.0.9/node_modules/@inquirer/figures/dist/index.js
@@ -7988,1474 +9195,1044 @@ var specialFallbackSymbols = {
7988
9195
  checkboxCircleOff: "( )",
7989
9196
  pointer: ">",
7990
9197
  triangleUpOutline: "\u2206",
7991
- triangleLeft: "\u25C4",
7992
- triangleRight: "\u25BA",
7993
- lozenge: "\u2666",
7994
- lozengeOutline: "\u25CA",
7995
- hamburger: "\u2261",
7996
- smiley: "\u263A",
7997
- mustache: "\u250C\u2500\u2510",
7998
- star: "\u2736",
7999
- play: "\u25BA",
8000
- nodejs: "\u2666",
8001
- oneSeventh: "1/7",
8002
- oneNinth: "1/9",
8003
- oneTenth: "1/10"
8004
- };
8005
- var mainSymbols = {
8006
- ...common,
8007
- ...specialMainSymbols
8008
- };
8009
- var fallbackSymbols = {
8010
- ...common,
8011
- ...specialFallbackSymbols
8012
- };
8013
- var shouldUseMain = isUnicodeSupported();
8014
- var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
8015
- var dist_default = figures;
8016
- var replacements = Object.entries(specialMainSymbols);
8017
-
8018
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/theme.js
8019
- var defaultTheme = {
8020
- prefix: {
8021
- idle: styleText("blue", "?"),
8022
- done: styleText("green", dist_default.tick)
8023
- },
8024
- spinner: {
8025
- interval: 80,
8026
- frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"].map((frame) => styleText("yellow", frame))
8027
- },
8028
- keybindings: [],
8029
- style: {
8030
- answer: (text) => styleText("cyan", text),
8031
- message: (text) => styleText("bold", text),
8032
- error: (text) => styleText("red", `> ${text}`),
8033
- defaultAnswer: (text) => styleText("dim", `(${text})`),
8034
- help: (text) => styleText("dim", text),
8035
- highlight: (text) => styleText("cyan", text),
8036
- key: (text) => styleText("cyan", styleText("bold", `<${text}>`))
8037
- }
8038
- };
8039
- function getDefaultTheme() {
8040
- return {
8041
- ...defaultTheme,
8042
- keybindings: getDefaultKeybindings()
8043
- };
8044
- }
8045
-
8046
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/make-theme.js
8047
- function isPlainObject(value) {
8048
- if (typeof value !== "object" || value === null)
8049
- return false;
8050
- let proto = value;
8051
- while (Object.getPrototypeOf(proto) !== null) {
8052
- proto = Object.getPrototypeOf(proto);
8053
- }
8054
- return Object.getPrototypeOf(value) === proto;
8055
- }
8056
- function deepMerge(...objects) {
8057
- const output = {};
8058
- for (const obj of objects) {
8059
- for (const [key, value] of Object.entries(obj)) {
8060
- const prevValue = output[key];
8061
- output[key] = isPlainObject(prevValue) && isPlainObject(value) ? deepMerge(prevValue, value) : value;
8062
- }
8063
- }
8064
- return output;
8065
- }
8066
- function makeTheme(...themes) {
8067
- const themesToMerge = [
8068
- getDefaultTheme(),
8069
- ...themes.filter((theme) => theme != null)
8070
- ];
8071
- return deepMerge(...themesToMerge);
8072
- }
8073
-
8074
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/use-prefix.js
8075
- function usePrefix({ status = "idle", theme }) {
8076
- const [showLoader, setShowLoader] = useState(false);
8077
- const [tick, setTick] = useState(0);
8078
- const { prefix, spinner } = makeTheme(theme);
8079
- useEffect(() => {
8080
- if (status === "loading") {
8081
- let tickInterval;
8082
- let inc = -1;
8083
- const delayTimeout = setTimeout(() => {
8084
- setShowLoader(true);
8085
- tickInterval = setInterval(() => {
8086
- inc = inc + 1;
8087
- setTick(inc % spinner.frames.length);
8088
- }, spinner.interval);
8089
- }, 300);
8090
- return () => {
8091
- clearTimeout(delayTimeout);
8092
- clearInterval(tickInterval);
8093
- };
8094
- } else {
8095
- setShowLoader(false);
8096
- }
8097
- }, [status]);
8098
- if (showLoader) {
8099
- return spinner.frames[tick];
8100
- }
8101
- const iconName = status === "loading" ? "idle" : status;
8102
- return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
8103
- }
8104
-
8105
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/use-ref.js
8106
- function useRef(val) {
8107
- return useState({ current: val })[0];
8108
- }
8109
-
8110
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/use-keypress.js
8111
- function useKeypress(userHandler) {
8112
- const signal = useRef(userHandler);
8113
- signal.current = userHandler;
8114
- useEffect((rl) => {
8115
- let ignore = false;
8116
- const handler = withUpdates((_input, event) => {
8117
- if (ignore)
8118
- return;
8119
- void signal.current(event, rl);
8120
- });
8121
- rl.input.on("keypress", handler);
8122
- return () => {
8123
- ignore = true;
8124
- rl.input.removeListener("keypress", handler);
8125
- };
8126
- }, []);
8127
- }
8128
-
8129
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/utils.js
8130
- var import_cli_width = __toESM(require_cli_width(), 1);
8131
-
8132
- // ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
8133
- var getCodePointsLength = /* @__PURE__ */ (() => {
8134
- const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
8135
- return (input) => {
8136
- let surrogatePairsNr = 0;
8137
- SURROGATE_PAIR_RE.lastIndex = 0;
8138
- while (SURROGATE_PAIR_RE.test(input)) {
8139
- surrogatePairsNr += 1;
8140
- }
8141
- return input.length - surrogatePairsNr;
8142
- };
8143
- })();
8144
- var isFullWidth = (x) => {
8145
- return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
8146
- };
8147
- var isWideNotCJKTNotEmoji = (x) => {
8148
- return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
8149
- };
8150
-
8151
- // ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
8152
- var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
8153
- var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
8154
- var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
8155
- var TAB_RE = /\t{1,1000}/y;
8156
- var EMOJI_RE = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
8157
- var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
8158
- var MODIFIER_RE = new RegExp("\\p{M}+", "gu");
8159
- var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
8160
- var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
8161
- const LIMIT = truncationOptions.limit ?? Infinity;
8162
- const ELLIPSIS = truncationOptions.ellipsis ?? "";
8163
- const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
8164
- const ANSI_WIDTH = 0;
8165
- const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
8166
- const TAB_WIDTH = widthOptions.tabWidth ?? 8;
8167
- const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
8168
- const FULL_WIDTH_WIDTH = 2;
8169
- const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
8170
- const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
8171
- const PARSE_BLOCKS = [
8172
- [LATIN_RE, REGULAR_WIDTH],
8173
- [ANSI_RE, ANSI_WIDTH],
8174
- [CONTROL_RE, CONTROL_WIDTH],
8175
- [TAB_RE, TAB_WIDTH],
8176
- [EMOJI_RE, EMOJI_WIDTH],
8177
- [CJKT_WIDE_RE, WIDE_WIDTH]
8178
- ];
8179
- let indexPrev = 0;
8180
- let index = 0;
8181
- let length = input.length;
8182
- let lengthExtra = 0;
8183
- let truncationEnabled = false;
8184
- let truncationIndex = length;
8185
- let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
8186
- let unmatchedStart = 0;
8187
- let unmatchedEnd = 0;
8188
- let width = 0;
8189
- let widthExtra = 0;
8190
- outer: while (true) {
8191
- if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
8192
- const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
8193
- lengthExtra = 0;
8194
- for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
8195
- const codePoint = char.codePointAt(0) || 0;
8196
- if (isFullWidth(codePoint)) {
8197
- widthExtra = FULL_WIDTH_WIDTH;
8198
- } else if (isWideNotCJKTNotEmoji(codePoint)) {
8199
- widthExtra = WIDE_WIDTH;
8200
- } else {
8201
- widthExtra = REGULAR_WIDTH;
8202
- }
8203
- if (width + widthExtra > truncationLimit) {
8204
- truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
8205
- }
8206
- if (width + widthExtra > LIMIT) {
8207
- truncationEnabled = true;
8208
- break outer;
8209
- }
8210
- lengthExtra += char.length;
8211
- width += widthExtra;
8212
- }
8213
- unmatchedStart = unmatchedEnd = 0;
8214
- }
8215
- if (index >= length) {
8216
- break outer;
8217
- }
8218
- for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
8219
- const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
8220
- BLOCK_RE.lastIndex = index;
8221
- if (BLOCK_RE.test(input)) {
8222
- lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
8223
- widthExtra = lengthExtra * BLOCK_WIDTH;
8224
- if (width + widthExtra > truncationLimit) {
8225
- truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
8226
- }
8227
- if (width + widthExtra > LIMIT) {
8228
- truncationEnabled = true;
8229
- break outer;
8230
- }
8231
- width += widthExtra;
8232
- unmatchedStart = indexPrev;
8233
- unmatchedEnd = index;
8234
- index = indexPrev = BLOCK_RE.lastIndex;
8235
- continue outer;
8236
- }
8237
- }
8238
- index += 1;
8239
- }
8240
- return {
8241
- width: truncationEnabled ? truncationLimit : width,
8242
- index: truncationEnabled ? truncationIndex : length,
8243
- truncated: truncationEnabled,
8244
- ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
8245
- };
9198
+ triangleLeft: "\u25C4",
9199
+ triangleRight: "\u25BA",
9200
+ lozenge: "\u2666",
9201
+ lozengeOutline: "\u25CA",
9202
+ hamburger: "\u2261",
9203
+ smiley: "\u263A",
9204
+ mustache: "\u250C\u2500\u2510",
9205
+ star: "\u2736",
9206
+ play: "\u25BA",
9207
+ nodejs: "\u2666",
9208
+ oneSeventh: "1/7",
9209
+ oneNinth: "1/9",
9210
+ oneTenth: "1/10"
8246
9211
  };
8247
- var dist_default2 = getStringTruncatedWidth;
8248
-
8249
- // ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
8250
- var NO_TRUNCATION2 = {
8251
- limit: Infinity,
8252
- ellipsis: "",
8253
- ellipsisWidth: 0
9212
+ var mainSymbols = {
9213
+ ...common,
9214
+ ...specialMainSymbols
8254
9215
  };
8255
- var fastStringWidth = (input, options = {}) => {
8256
- return dist_default2(input, NO_TRUNCATION2, options).width;
9216
+ var fallbackSymbols = {
9217
+ ...common,
9218
+ ...specialFallbackSymbols
8257
9219
  };
8258
- var dist_default3 = fastStringWidth;
9220
+ var shouldUseMain = isUnicodeSupported();
9221
+ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
9222
+ var dist_default = figures;
9223
+ var replacements = Object.entries(specialMainSymbols);
8259
9224
 
8260
- // ../../node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
8261
- var ESC = "\x1B";
8262
- var CSI = "\x9B";
8263
- var END_CODE = 39;
8264
- var ANSI_ESCAPE_BELL = "\x07";
8265
- var ANSI_CSI = "[";
8266
- var ANSI_OSC = "]";
8267
- var ANSI_SGR_TERMINATOR = "m";
8268
- var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
8269
- var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
8270
- var getClosingCode = (openingCode) => {
8271
- if (openingCode >= 30 && openingCode <= 37)
8272
- return 39;
8273
- if (openingCode >= 90 && openingCode <= 97)
8274
- return 39;
8275
- if (openingCode >= 40 && openingCode <= 47)
8276
- return 49;
8277
- if (openingCode >= 100 && openingCode <= 107)
8278
- return 49;
8279
- if (openingCode === 1 || openingCode === 2)
8280
- return 22;
8281
- if (openingCode === 3)
8282
- return 23;
8283
- if (openingCode === 4)
8284
- return 24;
8285
- if (openingCode === 7)
8286
- return 27;
8287
- if (openingCode === 8)
8288
- return 28;
8289
- if (openingCode === 9)
8290
- return 29;
8291
- if (openingCode === 0)
8292
- return 0;
8293
- return void 0;
8294
- };
8295
- var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
8296
- var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
8297
- var wrapWord = (rows, word, columns) => {
8298
- const characters = word[Symbol.iterator]();
8299
- let isInsideEscape = false;
8300
- let isInsideLinkEscape = false;
8301
- let lastRow = rows.at(-1);
8302
- let visible = lastRow === void 0 ? 0 : dist_default3(lastRow);
8303
- let currentCharacter = characters.next();
8304
- let nextCharacter = characters.next();
8305
- let rawCharacterIndex = 0;
8306
- while (!currentCharacter.done) {
8307
- const character = currentCharacter.value;
8308
- const characterLength = dist_default3(character);
8309
- if (visible + characterLength <= columns) {
8310
- rows[rows.length - 1] += character;
8311
- } else {
8312
- rows.push(character);
8313
- visible = 0;
8314
- }
8315
- if (character === ESC || character === CSI) {
8316
- isInsideEscape = true;
8317
- isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
8318
- }
8319
- if (isInsideEscape) {
8320
- if (isInsideLinkEscape) {
8321
- if (character === ANSI_ESCAPE_BELL) {
8322
- isInsideEscape = false;
8323
- isInsideLinkEscape = false;
8324
- }
8325
- } else if (character === ANSI_SGR_TERMINATOR) {
8326
- isInsideEscape = false;
8327
- }
8328
- } else {
8329
- visible += characterLength;
8330
- if (visible === columns && !nextCharacter.done) {
8331
- rows.push("");
8332
- visible = 0;
8333
- }
8334
- }
8335
- currentCharacter = nextCharacter;
8336
- nextCharacter = characters.next();
8337
- rawCharacterIndex += character.length;
8338
- }
8339
- lastRow = rows.at(-1);
8340
- if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
8341
- rows[rows.length - 2] += rows.pop();
8342
- }
8343
- };
8344
- var stringVisibleTrimSpacesRight = (string) => {
8345
- const words = string.split(" ");
8346
- let last = words.length;
8347
- while (last) {
8348
- if (dist_default3(words[last - 1])) {
8349
- break;
8350
- }
8351
- last--;
8352
- }
8353
- if (last === words.length) {
8354
- return string;
8355
- }
8356
- return words.slice(0, last).join(" ") + words.slice(last).join("");
8357
- };
8358
- var exec = (string, columns, options = {}) => {
8359
- if (options.trim !== false && string.trim() === "") {
8360
- return "";
8361
- }
8362
- let returnValue = "";
8363
- let escapeCode;
8364
- let escapeUrl;
8365
- const words = string.split(" ");
8366
- let rows = [""];
8367
- let rowLength = 0;
8368
- for (let index = 0; index < words.length; index++) {
8369
- const word = words[index];
8370
- if (options.trim !== false) {
8371
- const row = rows.at(-1) ?? "";
8372
- const trimmed = row.trimStart();
8373
- if (row.length !== trimmed.length) {
8374
- rows[rows.length - 1] = trimmed;
8375
- rowLength = dist_default3(trimmed);
8376
- }
8377
- }
8378
- if (index !== 0) {
8379
- if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
8380
- rows.push("");
8381
- rowLength = 0;
8382
- }
8383
- if (rowLength || options.trim === false) {
8384
- rows[rows.length - 1] += " ";
8385
- rowLength++;
8386
- }
8387
- }
8388
- const wordLength = dist_default3(word);
8389
- if (options.hard && wordLength > columns) {
8390
- const remainingColumns = columns - rowLength;
8391
- const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
8392
- const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
8393
- if (breaksStartingNextLine < breaksStartingThisLine) {
8394
- rows.push("");
8395
- }
8396
- wrapWord(rows, word, columns);
8397
- rowLength = dist_default3(rows.at(-1) ?? "");
8398
- continue;
8399
- }
8400
- if (rowLength + wordLength > columns && rowLength && wordLength) {
8401
- if (options.wordWrap === false && rowLength < columns) {
8402
- wrapWord(rows, word, columns);
8403
- rowLength = dist_default3(rows.at(-1) ?? "");
8404
- continue;
8405
- }
8406
- rows.push("");
8407
- rowLength = 0;
8408
- }
8409
- if (rowLength + wordLength > columns && options.wordWrap === false) {
8410
- wrapWord(rows, word, columns);
8411
- rowLength = dist_default3(rows.at(-1) ?? "");
8412
- continue;
8413
- }
8414
- rows[rows.length - 1] += word;
8415
- rowLength += wordLength;
8416
- }
8417
- if (options.trim !== false) {
8418
- rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
8419
- }
8420
- const preString = rows.join("\n");
8421
- let inSurrogate = false;
8422
- for (let i = 0; i < preString.length; i++) {
8423
- const character = preString[i];
8424
- returnValue += character;
8425
- if (!inSurrogate) {
8426
- inSurrogate = character >= "\uD800" && character <= "\uDBFF";
8427
- if (inSurrogate) {
8428
- continue;
8429
- }
8430
- } else {
8431
- inSurrogate = false;
8432
- }
8433
- if (character === ESC || character === CSI) {
8434
- GROUP_REGEX.lastIndex = i + 1;
8435
- const groupsResult = GROUP_REGEX.exec(preString);
8436
- const groups = groupsResult?.groups;
8437
- if (groups?.code !== void 0) {
8438
- const code = Number.parseFloat(groups.code);
8439
- escapeCode = code === END_CODE ? void 0 : code;
8440
- } else if (groups?.uri !== void 0) {
8441
- escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
8442
- }
8443
- }
8444
- if (preString[i + 1] === "\n") {
8445
- if (escapeUrl) {
8446
- returnValue += wrapAnsiHyperlink("");
8447
- }
8448
- const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
8449
- if (escapeCode && closingCode) {
8450
- returnValue += wrapAnsiCode(closingCode);
8451
- }
8452
- } else if (character === "\n") {
8453
- if (escapeCode && getClosingCode(escapeCode)) {
8454
- returnValue += wrapAnsiCode(escapeCode);
8455
- }
8456
- if (escapeUrl) {
8457
- returnValue += wrapAnsiHyperlink(escapeUrl);
8458
- }
8459
- }
9225
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/theme.js
9226
+ var defaultTheme = {
9227
+ prefix: {
9228
+ idle: styleText("blue", "?"),
9229
+ done: styleText("green", dist_default.tick)
9230
+ },
9231
+ spinner: {
9232
+ interval: 80,
9233
+ frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"].map((frame) => styleText("yellow", frame))
9234
+ },
9235
+ keybindings: [],
9236
+ style: {
9237
+ answer: (text) => styleText("cyan", text),
9238
+ message: (text) => styleText("bold", text),
9239
+ error: (text) => styleText("red", `> ${text}`),
9240
+ defaultAnswer: (text) => styleText("dim", `(${text})`),
9241
+ help: (text) => styleText("dim", text),
9242
+ highlight: (text) => styleText("cyan", text),
9243
+ key: (text) => styleText("cyan", styleText("bold", `<${text}>`))
8460
9244
  }
8461
- return returnValue;
8462
9245
  };
8463
- var CRLF_OR_LF = /\r?\n/;
8464
- function wrapAnsi(string, columns, options) {
8465
- return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
9246
+ function getDefaultTheme() {
9247
+ return {
9248
+ ...defaultTheme,
9249
+ keybindings: getDefaultKeybindings()
9250
+ };
8466
9251
  }
8467
9252
 
8468
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/utils.js
8469
- function breakLines(content, width) {
8470
- return content.split("\n").flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false }).split("\n").map((str) => str.trimEnd())).join("\n");
9253
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/make-theme.js
9254
+ function isPlainObject(value) {
9255
+ if (typeof value !== "object" || value === null)
9256
+ return false;
9257
+ let proto = value;
9258
+ while (Object.getPrototypeOf(proto) !== null) {
9259
+ proto = Object.getPrototypeOf(proto);
9260
+ }
9261
+ return Object.getPrototypeOf(value) === proto;
8471
9262
  }
8472
- function readlineWidth() {
8473
- return (0, import_cli_width.default)({ defaultWidth: 80, output: readline().output });
9263
+ function deepMerge(...objects) {
9264
+ const output = {};
9265
+ for (const obj of objects) {
9266
+ for (const [key, value] of Object.entries(obj)) {
9267
+ const prevValue = output[key];
9268
+ output[key] = isPlainObject(prevValue) && isPlainObject(value) ? deepMerge(prevValue, value) : value;
9269
+ }
9270
+ }
9271
+ return output;
8474
9272
  }
8475
-
8476
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/create-prompt.js
8477
- import * as readline2 from "node:readline";
8478
- import { AsyncResource as AsyncResource3 } from "node:async_hooks";
8479
-
8480
- // ../../node_modules/.pnpm/@inquirer+type@4.2.0_@types+node@26.1.2/node_modules/@inquirer/type/dist/utils.js
8481
- function withResolver() {
8482
- let resolve3;
8483
- let reject;
8484
- const promise = new Promise((res, rej) => {
8485
- resolve3 = res;
8486
- reject = rej;
8487
- });
8488
- return { promise, resolve: resolve3, reject };
9273
+ function makeTheme(...themes) {
9274
+ const themesToMerge = [
9275
+ getDefaultTheme(),
9276
+ ...themes.filter((theme) => theme != null)
9277
+ ];
9278
+ return deepMerge(...themesToMerge);
8489
9279
  }
8490
9280
 
8491
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/create-prompt.js
8492
- var import_mute_stream = __toESM(require_lib(), 1);
8493
-
8494
- // ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js
8495
- var signals = [];
8496
- signals.push("SIGHUP", "SIGINT", "SIGTERM");
8497
- if (process.platform !== "win32") {
8498
- signals.push(
8499
- "SIGALRM",
8500
- "SIGABRT",
8501
- "SIGVTALRM",
8502
- "SIGXCPU",
8503
- "SIGXFSZ",
8504
- "SIGUSR2",
8505
- "SIGTRAP",
8506
- "SIGSYS",
8507
- "SIGQUIT",
8508
- "SIGIOT"
8509
- // should detect profiler and enable/disable accordingly.
8510
- // see #21
8511
- // 'SIGPROF'
8512
- );
9281
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-prefix.js
9282
+ function usePrefix({ status = "idle", theme }) {
9283
+ const [showLoader, setShowLoader] = useState(false);
9284
+ const [tick, setTick] = useState(0);
9285
+ const { prefix, spinner } = makeTheme(theme);
9286
+ useEffect(() => {
9287
+ if (status === "loading") {
9288
+ let tickInterval;
9289
+ let inc = -1;
9290
+ const delayTimeout = setTimeout(() => {
9291
+ setShowLoader(true);
9292
+ tickInterval = setInterval(() => {
9293
+ inc = inc + 1;
9294
+ setTick(inc % spinner.frames.length);
9295
+ }, spinner.interval);
9296
+ }, 300);
9297
+ return () => {
9298
+ clearTimeout(delayTimeout);
9299
+ clearInterval(tickInterval);
9300
+ };
9301
+ } else {
9302
+ setShowLoader(false);
9303
+ }
9304
+ }, [status]);
9305
+ if (showLoader) {
9306
+ return spinner.frames[tick];
9307
+ }
9308
+ const iconName = status === "loading" ? "idle" : status;
9309
+ return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
8513
9310
  }
8514
- if (process.platform === "linux") {
8515
- signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
9311
+
9312
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-ref.js
9313
+ function useRef(val) {
9314
+ return useState({ current: val })[0];
8516
9315
  }
8517
9316
 
8518
- // ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js
8519
- var processOk = (process5) => !!process5 && typeof process5 === "object" && typeof process5.removeListener === "function" && typeof process5.emit === "function" && typeof process5.reallyExit === "function" && typeof process5.listeners === "function" && typeof process5.kill === "function" && typeof process5.pid === "number" && typeof process5.on === "function";
8520
- var kExitEmitter = /* @__PURE__ */ Symbol.for("signal-exit emitter");
8521
- var global = globalThis;
8522
- var ObjectDefineProperty = Object.defineProperty.bind(Object);
8523
- var Emitter = class {
8524
- emitted = {
8525
- afterExit: false,
8526
- exit: false
8527
- };
8528
- listeners = {
8529
- afterExit: [],
8530
- exit: []
8531
- };
8532
- count = 0;
8533
- id = Math.random();
8534
- constructor() {
8535
- if (global[kExitEmitter]) {
8536
- return global[kExitEmitter];
8537
- }
8538
- ObjectDefineProperty(global, kExitEmitter, {
8539
- value: this,
8540
- writable: false,
8541
- enumerable: false,
8542
- configurable: false
9317
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-keypress.js
9318
+ function useKeypress(userHandler) {
9319
+ const signal = useRef(userHandler);
9320
+ signal.current = userHandler;
9321
+ useEffect((rl) => {
9322
+ let ignore = false;
9323
+ const handler = withUpdates((_input, event) => {
9324
+ if (ignore)
9325
+ return;
9326
+ void signal.current(event, rl);
8543
9327
  });
8544
- }
8545
- on(ev, fn) {
8546
- this.listeners[ev].push(fn);
8547
- }
8548
- removeListener(ev, fn) {
8549
- const list = this.listeners[ev];
8550
- const i = list.indexOf(fn);
8551
- if (i === -1) {
8552
- return;
8553
- }
8554
- if (i === 0 && list.length === 1) {
8555
- list.length = 0;
8556
- } else {
8557
- list.splice(i, 1);
8558
- }
8559
- }
8560
- emit(ev, code, signal) {
8561
- if (this.emitted[ev]) {
8562
- return false;
8563
- }
8564
- this.emitted[ev] = true;
8565
- let ret = false;
8566
- for (const fn of this.listeners[ev]) {
8567
- ret = fn(code, signal) === true || ret;
8568
- }
8569
- if (ev === "exit") {
8570
- ret = this.emit("afterExit", code, signal) || ret;
8571
- }
8572
- return ret;
8573
- }
8574
- };
8575
- var SignalExitBase = class {
8576
- };
8577
- var signalExitWrap = (handler) => {
8578
- return {
8579
- onExit(cb, opts) {
8580
- return handler.onExit(cb, opts);
8581
- },
8582
- load() {
8583
- return handler.load();
8584
- },
8585
- unload() {
8586
- return handler.unload();
9328
+ rl.input.on("keypress", handler);
9329
+ return () => {
9330
+ ignore = true;
9331
+ rl.input.removeListener("keypress", handler);
9332
+ };
9333
+ }, []);
9334
+ }
9335
+
9336
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/utils.js
9337
+ var import_cli_width = __toESM(require_cli_width(), 1);
9338
+
9339
+ // ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
9340
+ var getCodePointsLength = /* @__PURE__ */ (() => {
9341
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
9342
+ return (input) => {
9343
+ let surrogatePairsNr = 0;
9344
+ SURROGATE_PAIR_RE.lastIndex = 0;
9345
+ while (SURROGATE_PAIR_RE.test(input)) {
9346
+ surrogatePairsNr += 1;
8587
9347
  }
9348
+ return input.length - surrogatePairsNr;
8588
9349
  };
9350
+ })();
9351
+ var isFullWidth = (x) => {
9352
+ return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
8589
9353
  };
8590
- var SignalExitFallback = class extends SignalExitBase {
8591
- onExit() {
8592
- return () => {
8593
- };
8594
- }
8595
- load() {
8596
- }
8597
- unload() {
8598
- }
9354
+ var isWideNotCJKTNotEmoji = (x) => {
9355
+ return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
8599
9356
  };
8600
- var SignalExit = class extends SignalExitBase {
8601
- // "SIGHUP" throws an `ENOSYS` error on Windows,
8602
- // so use a supported signal instead
8603
- /* c8 ignore start */
8604
- #hupSig = process3.platform === "win32" ? "SIGINT" : "SIGHUP";
8605
- /* c8 ignore stop */
8606
- #emitter = new Emitter();
8607
- #process;
8608
- #originalProcessEmit;
8609
- #originalProcessReallyExit;
8610
- #sigListeners = {};
8611
- #loaded = false;
8612
- constructor(process5) {
8613
- super();
8614
- this.#process = process5;
8615
- this.#sigListeners = {};
8616
- for (const sig of signals) {
8617
- this.#sigListeners[sig] = () => {
8618
- const listeners = this.#process.listeners(sig);
8619
- let { count } = this.#emitter;
8620
- const p = process5;
8621
- if (typeof p.__signal_exit_emitter__ === "object" && typeof p.__signal_exit_emitter__.count === "number") {
8622
- count += p.__signal_exit_emitter__.count;
9357
+
9358
+ // ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
9359
+ var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
9360
+ var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
9361
+ var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
9362
+ var TAB_RE = /\t{1,1000}/y;
9363
+ var EMOJI_RE = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
9364
+ var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
9365
+ var MODIFIER_RE = new RegExp("\\p{M}+", "gu");
9366
+ var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
9367
+ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
9368
+ const LIMIT = truncationOptions.limit ?? Infinity;
9369
+ const ELLIPSIS = truncationOptions.ellipsis ?? "";
9370
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
9371
+ const ANSI_WIDTH = 0;
9372
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
9373
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
9374
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
9375
+ const FULL_WIDTH_WIDTH = 2;
9376
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
9377
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
9378
+ const PARSE_BLOCKS = [
9379
+ [LATIN_RE, REGULAR_WIDTH],
9380
+ [ANSI_RE, ANSI_WIDTH],
9381
+ [CONTROL_RE, CONTROL_WIDTH],
9382
+ [TAB_RE, TAB_WIDTH],
9383
+ [EMOJI_RE, EMOJI_WIDTH],
9384
+ [CJKT_WIDE_RE, WIDE_WIDTH]
9385
+ ];
9386
+ let indexPrev = 0;
9387
+ let index = 0;
9388
+ let length = input.length;
9389
+ let lengthExtra = 0;
9390
+ let truncationEnabled = false;
9391
+ let truncationIndex = length;
9392
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
9393
+ let unmatchedStart = 0;
9394
+ let unmatchedEnd = 0;
9395
+ let width = 0;
9396
+ let widthExtra = 0;
9397
+ outer: while (true) {
9398
+ if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
9399
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
9400
+ lengthExtra = 0;
9401
+ for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
9402
+ const codePoint = char.codePointAt(0) || 0;
9403
+ if (isFullWidth(codePoint)) {
9404
+ widthExtra = FULL_WIDTH_WIDTH;
9405
+ } else if (isWideNotCJKTNotEmoji(codePoint)) {
9406
+ widthExtra = WIDE_WIDTH;
9407
+ } else {
9408
+ widthExtra = REGULAR_WIDTH;
8623
9409
  }
8624
- if (listeners.length === count) {
8625
- this.unload();
8626
- const ret = this.#emitter.emit("exit", null, sig);
8627
- const s = sig === "SIGHUP" ? this.#hupSig : sig;
8628
- if (!ret)
8629
- process5.kill(process5.pid, s);
9410
+ if (width + widthExtra > truncationLimit) {
9411
+ truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
8630
9412
  }
8631
- };
8632
- }
8633
- this.#originalProcessReallyExit = process5.reallyExit;
8634
- this.#originalProcessEmit = process5.emit;
8635
- }
8636
- onExit(cb, opts) {
8637
- if (!processOk(this.#process)) {
8638
- return () => {
8639
- };
8640
- }
8641
- if (this.#loaded === false) {
8642
- this.load();
8643
- }
8644
- const ev = opts?.alwaysLast ? "afterExit" : "exit";
8645
- this.#emitter.on(ev, cb);
8646
- return () => {
8647
- this.#emitter.removeListener(ev, cb);
8648
- if (this.#emitter.listeners["exit"].length === 0 && this.#emitter.listeners["afterExit"].length === 0) {
8649
- this.unload();
8650
- }
8651
- };
8652
- }
8653
- load() {
8654
- if (this.#loaded) {
8655
- return;
8656
- }
8657
- this.#loaded = true;
8658
- this.#emitter.count += 1;
8659
- for (const sig of signals) {
8660
- try {
8661
- const fn = this.#sigListeners[sig];
8662
- if (fn)
8663
- this.#process.on(sig, fn);
8664
- } catch (_) {
9413
+ if (width + widthExtra > LIMIT) {
9414
+ truncationEnabled = true;
9415
+ break outer;
9416
+ }
9417
+ lengthExtra += char.length;
9418
+ width += widthExtra;
8665
9419
  }
9420
+ unmatchedStart = unmatchedEnd = 0;
8666
9421
  }
8667
- this.#process.emit = (ev, ...a) => {
8668
- return this.#processEmit(ev, ...a);
8669
- };
8670
- this.#process.reallyExit = (code) => {
8671
- return this.#processReallyExit(code);
8672
- };
8673
- }
8674
- unload() {
8675
- if (!this.#loaded) {
8676
- return;
8677
- }
8678
- this.#loaded = false;
8679
- signals.forEach((sig) => {
8680
- const listener = this.#sigListeners[sig];
8681
- if (!listener) {
8682
- throw new Error("Listener not defined for signal: " + sig);
8683
- }
8684
- try {
8685
- this.#process.removeListener(sig, listener);
8686
- } catch (_) {
8687
- }
8688
- });
8689
- this.#process.emit = this.#originalProcessEmit;
8690
- this.#process.reallyExit = this.#originalProcessReallyExit;
8691
- this.#emitter.count -= 1;
8692
- }
8693
- #processReallyExit(code) {
8694
- if (!processOk(this.#process)) {
8695
- return 0;
9422
+ if (index >= length) {
9423
+ break outer;
8696
9424
  }
8697
- this.#process.exitCode = code || 0;
8698
- this.#emitter.emit("exit", this.#process.exitCode, null);
8699
- return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode);
8700
- }
8701
- #processEmit(ev, ...args) {
8702
- const og = this.#originalProcessEmit;
8703
- if (ev === "exit" && processOk(this.#process)) {
8704
- if (typeof args[0] === "number") {
8705
- this.#process.exitCode = args[0];
9425
+ for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
9426
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
9427
+ BLOCK_RE.lastIndex = index;
9428
+ if (BLOCK_RE.test(input)) {
9429
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
9430
+ widthExtra = lengthExtra * BLOCK_WIDTH;
9431
+ if (width + widthExtra > truncationLimit) {
9432
+ truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
9433
+ }
9434
+ if (width + widthExtra > LIMIT) {
9435
+ truncationEnabled = true;
9436
+ break outer;
9437
+ }
9438
+ width += widthExtra;
9439
+ unmatchedStart = indexPrev;
9440
+ unmatchedEnd = index;
9441
+ index = indexPrev = BLOCK_RE.lastIndex;
9442
+ continue outer;
8706
9443
  }
8707
- const ret = og.call(this.#process, ev, ...args);
8708
- this.#emitter.emit("exit", this.#process.exitCode, null);
8709
- return ret;
8710
- } else {
8711
- return og.call(this.#process, ev, ...args);
8712
9444
  }
9445
+ index += 1;
8713
9446
  }
9447
+ return {
9448
+ width: truncationEnabled ? truncationLimit : width,
9449
+ index: truncationEnabled ? truncationIndex : length,
9450
+ truncated: truncationEnabled,
9451
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
9452
+ };
8714
9453
  };
8715
- var process3 = globalThis.process;
8716
- var {
8717
- /**
8718
- * Called when the process is exiting, whether via signal, explicit
8719
- * exit, or running out of stuff to do.
8720
- *
8721
- * If the global process object is not suitable for instrumentation,
8722
- * then this will be a no-op.
8723
- *
8724
- * Returns a function that may be used to unload signal-exit.
8725
- */
8726
- onExit,
8727
- /**
8728
- * Load the listeners. Likely you never need to call this, unless
8729
- * doing a rather deep integration with signal-exit functionality.
8730
- * Mostly exposed for the benefit of testing.
8731
- *
8732
- * @internal
8733
- */
8734
- load,
8735
- /**
8736
- * Unload the listeners. Likely you never need to call this, unless
8737
- * doing a rather deep integration with signal-exit functionality.
8738
- * Mostly exposed for the benefit of testing.
8739
- *
8740
- * @internal
8741
- */
8742
- unload
8743
- } = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback());
8744
-
8745
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/screen-manager.js
8746
- import { stripVTControlCharacters } from "node:util";
9454
+ var dist_default2 = getStringTruncatedWidth;
8747
9455
 
8748
- // ../../node_modules/.pnpm/@inquirer+ansi@2.0.9/node_modules/@inquirer/ansi/dist/index.js
8749
- var ESC2 = "\x1B[";
8750
- var cursorLeft = ESC2 + "G";
8751
- var cursorHide = ESC2 + "?25l";
8752
- var cursorShow = ESC2 + "?25h";
8753
- var cursorUp = (rows = 1) => rows > 0 ? `${ESC2}${rows}A` : "";
8754
- var cursorDown = (rows = 1) => rows > 0 ? `${ESC2}${rows}B` : "";
8755
- var cursorTo = (x, y) => {
8756
- if (typeof y === "number" && !Number.isNaN(y)) {
8757
- return `${ESC2}${y + 1};${x + 1}H`;
8758
- }
8759
- return `${ESC2}${x + 1}G`;
9456
+ // ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
9457
+ var NO_TRUNCATION2 = {
9458
+ limit: Infinity,
9459
+ ellipsis: "",
9460
+ ellipsisWidth: 0
8760
9461
  };
8761
- var eraseLine = ESC2 + "2K";
8762
- var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
9462
+ var fastStringWidth = (input, options = {}) => {
9463
+ return dist_default2(input, NO_TRUNCATION2, options).width;
9464
+ };
9465
+ var dist_default3 = fastStringWidth;
8763
9466
 
8764
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/screen-manager.js
8765
- var height = (content) => content.split("\n").length;
8766
- var lastLine = (content) => content.split("\n").pop() ?? "";
8767
- var ScreenManager = class {
8768
- // These variables are keeping information to allow correct prompt re-rendering
8769
- height = 0;
8770
- extraLinesUnderPrompt = 0;
8771
- cursorPos;
8772
- rl;
8773
- constructor(rl) {
8774
- this.rl = rl;
8775
- this.cursorPos = rl.getCursorPos();
8776
- }
8777
- write(content) {
8778
- this.rl.output.unmute();
8779
- this.rl.output.write(content);
8780
- this.rl.output.mute();
8781
- }
8782
- render(content, bottomContent = "") {
8783
- const promptLine = lastLine(content);
8784
- const rawPromptLine = stripVTControlCharacters(promptLine);
8785
- let prompt = rawPromptLine;
8786
- if (this.rl.line.length > 0) {
8787
- prompt = prompt.slice(0, -this.rl.line.length);
9467
+ // ../../node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
9468
+ var ESC = "\x1B";
9469
+ var CSI = "\x9B";
9470
+ var END_CODE = 39;
9471
+ var ANSI_ESCAPE_BELL = "\x07";
9472
+ var ANSI_CSI = "[";
9473
+ var ANSI_OSC = "]";
9474
+ var ANSI_SGR_TERMINATOR = "m";
9475
+ var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
9476
+ var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
9477
+ var getClosingCode = (openingCode) => {
9478
+ if (openingCode >= 30 && openingCode <= 37)
9479
+ return 39;
9480
+ if (openingCode >= 90 && openingCode <= 97)
9481
+ return 39;
9482
+ if (openingCode >= 40 && openingCode <= 47)
9483
+ return 49;
9484
+ if (openingCode >= 100 && openingCode <= 107)
9485
+ return 49;
9486
+ if (openingCode === 1 || openingCode === 2)
9487
+ return 22;
9488
+ if (openingCode === 3)
9489
+ return 23;
9490
+ if (openingCode === 4)
9491
+ return 24;
9492
+ if (openingCode === 7)
9493
+ return 27;
9494
+ if (openingCode === 8)
9495
+ return 28;
9496
+ if (openingCode === 9)
9497
+ return 29;
9498
+ if (openingCode === 0)
9499
+ return 0;
9500
+ return void 0;
9501
+ };
9502
+ var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
9503
+ var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
9504
+ var wrapWord = (rows, word, columns) => {
9505
+ const characters = word[Symbol.iterator]();
9506
+ let isInsideEscape = false;
9507
+ let isInsideLinkEscape = false;
9508
+ let lastRow = rows.at(-1);
9509
+ let visible = lastRow === void 0 ? 0 : dist_default3(lastRow);
9510
+ let currentCharacter = characters.next();
9511
+ let nextCharacter = characters.next();
9512
+ let rawCharacterIndex = 0;
9513
+ while (!currentCharacter.done) {
9514
+ const character = currentCharacter.value;
9515
+ const characterLength = dist_default3(character);
9516
+ if (visible + characterLength <= columns) {
9517
+ rows[rows.length - 1] += character;
9518
+ } else {
9519
+ rows.push(character);
9520
+ visible = 0;
8788
9521
  }
8789
- this.rl.setPrompt(prompt);
8790
- this.cursorPos = this.rl.getCursorPos();
8791
- const width = readlineWidth();
8792
- content = breakLines(content, width);
8793
- bottomContent = breakLines(bottomContent, width);
8794
- if (rawPromptLine.length % width === 0) {
8795
- content += "\n";
9522
+ if (character === ESC || character === CSI) {
9523
+ isInsideEscape = true;
9524
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
8796
9525
  }
8797
- let output = content + (bottomContent ? "\n" + bottomContent : "");
8798
- const promptLineUpDiff = Math.floor(rawPromptLine.length / width) - this.cursorPos.rows;
8799
- const bottomContentHeight = promptLineUpDiff + (bottomContent ? height(bottomContent) : 0);
8800
- if (bottomContentHeight > 0)
8801
- output += cursorUp(bottomContentHeight);
8802
- output += cursorTo(this.cursorPos.cols);
8803
- this.write(cursorDown(this.extraLinesUnderPrompt) + eraseLines(this.height) + output);
8804
- this.extraLinesUnderPrompt = bottomContentHeight;
8805
- this.height = height(output);
8806
- }
8807
- checkCursorPos() {
8808
- const cursorPos = this.rl.getCursorPos();
8809
- if (cursorPos.cols !== this.cursorPos.cols) {
8810
- this.write(cursorTo(cursorPos.cols));
8811
- this.cursorPos = cursorPos;
9526
+ if (isInsideEscape) {
9527
+ if (isInsideLinkEscape) {
9528
+ if (character === ANSI_ESCAPE_BELL) {
9529
+ isInsideEscape = false;
9530
+ isInsideLinkEscape = false;
9531
+ }
9532
+ } else if (character === ANSI_SGR_TERMINATOR) {
9533
+ isInsideEscape = false;
9534
+ }
9535
+ } else {
9536
+ visible += characterLength;
9537
+ if (visible === columns && !nextCharacter.done) {
9538
+ rows.push("");
9539
+ visible = 0;
9540
+ }
8812
9541
  }
9542
+ currentCharacter = nextCharacter;
9543
+ nextCharacter = characters.next();
9544
+ rawCharacterIndex += character.length;
8813
9545
  }
8814
- done({ clearContent }) {
8815
- this.rl.setPrompt("");
8816
- let output = cursorDown(this.extraLinesUnderPrompt);
8817
- output += clearContent ? eraseLines(this.height) : "\n";
8818
- output += cursorLeft;
8819
- output += cursorShow;
8820
- this.write(output);
8821
- this.rl.close();
9546
+ lastRow = rows.at(-1);
9547
+ if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
9548
+ rows[rows.length - 2] += rows.pop();
8822
9549
  }
8823
9550
  };
8824
-
8825
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/create-prompt.js
8826
- import path from "node:path";
8827
- var nativeSetImmediate = globalThis.setImmediate;
8828
- var nativeClearImmediate = globalThis.clearImmediate;
8829
- function listenTo(target, event, listener) {
8830
- if ("on" in target) {
8831
- target.on(event, listener);
8832
- return () => target.removeListener(event, listener);
9551
+ var stringVisibleTrimSpacesRight = (string) => {
9552
+ const words = string.split(" ");
9553
+ let last = words.length;
9554
+ while (last) {
9555
+ if (dist_default3(words[last - 1])) {
9556
+ break;
9557
+ }
9558
+ last--;
8833
9559
  }
8834
- target.addEventListener(event, listener);
8835
- return () => target.removeEventListener(event, listener);
8836
- }
8837
- function getCallSites() {
8838
- const savedPrepareStackTrace = Error.prepareStackTrace;
8839
- let result = [];
8840
- try {
8841
- Error.prepareStackTrace = (_, callSites) => {
8842
- const callSitesWithoutCurrent = callSites.slice(1);
8843
- result = callSitesWithoutCurrent;
8844
- return callSitesWithoutCurrent;
8845
- };
8846
- new Error().stack;
8847
- } catch {
8848
- return result;
9560
+ if (last === words.length) {
9561
+ return string;
8849
9562
  }
8850
- Error.prepareStackTrace = savedPrepareStackTrace;
8851
- return result;
8852
- }
8853
- function createPrompt(view) {
8854
- const callSites = getCallSites();
8855
- const prompt = (config, context = {}) => {
8856
- const { input = process.stdin, signal } = context;
8857
- const cleanups = /* @__PURE__ */ new Set();
8858
- const output = new import_mute_stream.default();
8859
- output.pipe(context.output ?? process.stdout);
8860
- const rl = readline2.createInterface({
8861
- terminal: true,
8862
- input,
8863
- output
8864
- });
8865
- output.mute();
8866
- const screen = new ScreenManager(rl);
8867
- const { promise, resolve: resolve3, reject } = withResolver();
8868
- return withHooks(rl, (cycle) => {
8869
- const clearEffects = AsyncResource3.bind(() => effectScheduler.clearAll());
8870
- const settlePrompt = (settle) => {
8871
- try {
8872
- clearEffects();
8873
- settle();
8874
- } catch (error) {
8875
- reject(error);
8876
- }
8877
- };
8878
- const resolvePrompt = (value) => settlePrompt(() => resolve3(value));
8879
- const rejectPrompt = (error) => settlePrompt(() => reject(error));
8880
- const promptPromise = Object.assign(promise.finally(() => {
8881
- cleanups.forEach((cleanup) => cleanup());
8882
- screen.done({ clearContent: Boolean(context.clearPromptOnDone) });
8883
- output.end();
8884
- }).then(() => promise), { cancel: () => rejectPrompt(new CancelPromptError()) });
8885
- if (signal) {
8886
- const abort = () => rejectPrompt(new AbortPromptError({ cause: signal.reason }));
8887
- if (signal.aborted) {
8888
- abort();
8889
- return promptPromise;
8890
- }
8891
- cleanups.add(listenTo(signal, "abort", abort));
9563
+ return words.slice(0, last).join(" ") + words.slice(last).join("");
9564
+ };
9565
+ var exec = (string, columns, options = {}) => {
9566
+ if (options.trim !== false && string.trim() === "") {
9567
+ return "";
9568
+ }
9569
+ let returnValue = "";
9570
+ let escapeCode;
9571
+ let escapeUrl;
9572
+ const words = string.split(" ");
9573
+ let rows = [""];
9574
+ let rowLength = 0;
9575
+ for (let index = 0; index < words.length; index++) {
9576
+ const word = words[index];
9577
+ if (options.trim !== false) {
9578
+ const row = rows.at(-1) ?? "";
9579
+ const trimmed = row.trimStart();
9580
+ if (row.length !== trimmed.length) {
9581
+ rows[rows.length - 1] = trimmed;
9582
+ rowLength = dist_default3(trimmed);
8892
9583
  }
8893
- cleanups.add(onExit((code, signal2) => {
8894
- rejectPrompt(new ExitPromptError(`User force closed the prompt with ${code} ${signal2}`));
8895
- }));
8896
- cleanups.add(listenTo(rl, "SIGINT", () => rejectPrompt(new ExitPromptError(`User force closed the prompt with SIGINT`))));
8897
- cleanups.add(listenTo(rl, "close", clearEffects));
8898
- const startCycle = () => {
8899
- cleanups.add(listenTo(rl.input, "keypress", () => screen.checkCursorPos()));
8900
- let pendingDone = null;
8901
- cycle(() => {
8902
- let effectsSettled = false;
8903
- try {
8904
- const nextView = view(config, (value) => {
8905
- if (effectsSettled) {
8906
- resolvePrompt(value);
8907
- } else {
8908
- pendingDone = { value };
8909
- }
8910
- });
8911
- if (nextView === void 0) {
8912
- let callerFilename = callSites[1]?.getFileName();
8913
- if (callerFilename && !callerFilename.startsWith("file://")) {
8914
- callerFilename = path.resolve(callerFilename);
8915
- }
8916
- throw new Error(`Prompt functions must return a string.
8917
- at ${callerFilename}`);
8918
- }
8919
- const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
8920
- screen.render(content, bottomContent);
8921
- effectScheduler.run();
8922
- } catch (error) {
8923
- rejectPrompt(error);
8924
- }
8925
- effectsSettled = true;
8926
- if (pendingDone !== null) {
8927
- const { value } = pendingDone;
8928
- pendingDone = null;
8929
- resolvePrompt(value);
8930
- }
8931
- });
8932
- };
8933
- if ("readableFlowing" in input) {
8934
- const immediate = nativeSetImmediate(startCycle);
8935
- cleanups.add(() => nativeClearImmediate(immediate));
8936
- } else {
8937
- startCycle();
9584
+ }
9585
+ if (index !== 0) {
9586
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
9587
+ rows.push("");
9588
+ rowLength = 0;
8938
9589
  }
8939
- return promptPromise;
8940
- });
8941
- };
8942
- return prompt;
8943
- }
8944
-
8945
- // ../../node_modules/.pnpm/@inquirer+confirm@6.3.4_@types+node@26.1.2/node_modules/@inquirer/confirm/dist/index.js
8946
- import { styleText as styleText2 } from "node:util";
8947
- var confirmTheme = {
8948
- keywords: {
8949
- yes: "Yes",
8950
- no: "No",
8951
- error: ({ yes, no }) => `You must answer with "${yes}" or "${no}"`
8952
- },
8953
- style: {
8954
- confirmDefault: (text) => {
8955
- const first = text[0] ?? "";
8956
- if (first.toLowerCase() === first.toUpperCase()) {
8957
- return styleText2("cyan", text);
9590
+ if (rowLength || options.trim === false) {
9591
+ rows[rows.length - 1] += " ";
9592
+ rowLength++;
8958
9593
  }
8959
- return first.toUpperCase() + text.slice(1);
8960
9594
  }
9595
+ const wordLength = dist_default3(word);
9596
+ if (options.hard && wordLength > columns) {
9597
+ const remainingColumns = columns - rowLength;
9598
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
9599
+ const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
9600
+ if (breaksStartingNextLine < breaksStartingThisLine) {
9601
+ rows.push("");
9602
+ }
9603
+ wrapWord(rows, word, columns);
9604
+ rowLength = dist_default3(rows.at(-1) ?? "");
9605
+ continue;
9606
+ }
9607
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
9608
+ if (options.wordWrap === false && rowLength < columns) {
9609
+ wrapWord(rows, word, columns);
9610
+ rowLength = dist_default3(rows.at(-1) ?? "");
9611
+ continue;
9612
+ }
9613
+ rows.push("");
9614
+ rowLength = 0;
9615
+ }
9616
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
9617
+ wrapWord(rows, word, columns);
9618
+ rowLength = dist_default3(rows.at(-1) ?? "");
9619
+ continue;
9620
+ }
9621
+ rows[rows.length - 1] += word;
9622
+ rowLength += wordLength;
8961
9623
  }
8962
- };
8963
- var dist_default4 = createPrompt((config, done) => {
8964
- const [status, setStatus] = useState("idle");
8965
- const [value, setValue] = useState("");
8966
- const [errorMsg, setError] = useState();
8967
- const theme = makeTheme(confirmTheme, config.theme);
8968
- const prefix = usePrefix({ status, theme });
8969
- const { yes, no } = theme.keywords;
8970
- const yesHint = (yes[0] ?? "").toLowerCase();
8971
- const noHint = (no[0] ?? "").toLowerCase();
8972
- const hint = config.default === false ? `${yesHint}/${theme.style.confirmDefault(noHint)}` : `${theme.style.confirmDefault(yesHint)}/${noHint}`;
8973
- function boolToString(value2) {
8974
- return value2 ? yes : no;
8975
- }
8976
- const { transformer = boolToString } = config;
8977
- function getBooleanValue(value2) {
8978
- const v = value2.trim().toLowerCase();
8979
- if (v === "")
8980
- return config.default !== false;
8981
- if (yes.toLowerCase().startsWith(v))
8982
- return true;
8983
- if (no.toLowerCase().startsWith(v))
8984
- return false;
8985
- if ("yes".startsWith(v))
8986
- return true;
8987
- if ("no".startsWith(v))
8988
- return false;
8989
- return void 0;
9624
+ if (options.trim !== false) {
9625
+ rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
8990
9626
  }
8991
- useKeypress((key, rl) => {
8992
- if (status !== "idle")
8993
- return;
8994
- if (isEnterKey(key)) {
8995
- const answer = getBooleanValue(value);
8996
- if (answer === void 0) {
8997
- rl.write(value);
8998
- setError(theme.keywords.error({ yes, no }));
8999
- return;
9627
+ const preString = rows.join("\n");
9628
+ let inSurrogate = false;
9629
+ for (let i = 0; i < preString.length; i++) {
9630
+ const character = preString[i];
9631
+ returnValue += character;
9632
+ if (!inSurrogate) {
9633
+ inSurrogate = character >= "\uD800" && character <= "\uDBFF";
9634
+ if (inSurrogate) {
9635
+ continue;
9000
9636
  }
9001
- setValue(transformer(answer));
9002
- setStatus("done");
9003
- done(answer);
9004
- } else if (isTabKey(key)) {
9005
- const answer = boolToString(!(getBooleanValue(value) ?? config.default !== false));
9006
- rl.clearLine(0);
9007
- rl.write(answer);
9008
- setValue(answer);
9009
9637
  } else {
9010
- setValue(rl.line);
9011
- setError(void 0);
9638
+ inSurrogate = false;
9012
9639
  }
9013
- });
9014
- let formattedValue = value;
9015
- let defaultValue = "";
9016
- if (status === "done") {
9017
- formattedValue = theme.style.answer(value);
9018
- } else {
9019
- defaultValue = ` ${theme.style.defaultAnswer(hint)}`;
9020
- }
9021
- const message = theme.style.message(config.message, status);
9022
- let error = "";
9023
- if (errorMsg) {
9024
- error = theme.style.error(errorMsg);
9025
- }
9026
- return [`${prefix} ${message}${defaultValue} ${formattedValue}`, error];
9027
- });
9028
-
9029
- // ../lib/dist/catalog.js
9030
- import { join } from "node:path";
9031
-
9032
- // ../lib/dist/marker.js
9033
- var import_yaml = __toESM(require_dist(), 1);
9034
- var MARKER_FILE = "PLEXUS.md";
9035
- function parseMarker(text) {
9036
- const { data, body: body2 } = splitFrontmatter(text);
9037
- const plexus = data.plexus;
9038
- const modules = data.modules;
9039
- if (typeof plexus !== "string" && typeof plexus !== "number")
9040
- throw new Error("marker: `plexus` must be a version");
9041
- if (!Array.isArray(modules) || !modules.every((m) => typeof m === "string"))
9042
- throw new Error("marker: `modules` must be a list of module codes");
9043
- return { plexus: String(plexus), modules, body: body2 };
9044
- }
9045
- function splitFrontmatter(text) {
9046
- const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)([\s\S]*)$/.exec(text);
9047
- if (!match)
9048
- throw new Error("no frontmatter: expected a `---` block at the top");
9049
- const data = (0, import_yaml.parse)(match[1] ?? "");
9050
- if (data === null || typeof data !== "object" || Array.isArray(data))
9051
- throw new Error("frontmatter is not a mapping");
9052
- return { data, body: match[2] ?? "" };
9053
- }
9054
-
9055
- // ../lib/dist/catalog.js
9056
- var CATALOG_DIRS = { contracts: "contract", approaches: "approach" };
9057
- function parseModule(text, kind) {
9058
- const { data } = splitFrontmatter(text);
9059
- if (typeof data.code !== "string")
9060
- return void 0;
9061
- return {
9062
- code: data.code,
9063
- kind,
9064
- maturity: String(data.maturity ?? ""),
9065
- binds: String(data.binds ?? ""),
9066
- changed: data.changed === void 0 ? void 0 : String(data.changed),
9067
- depends: codes(data.depends),
9068
- consumes: codes(data.consumes)
9069
- };
9070
- }
9071
- function codes(value) {
9072
- return Array.isArray(value) ? value.map(String) : [];
9073
- }
9074
- async function readCatalog(ctx, compendium) {
9075
- const catalog = /* @__PURE__ */ new Map();
9076
- for (const [dir, kind] of Object.entries(CATALOG_DIRS)) {
9077
- const entries = await ctx.readDir(join(compendium, dir));
9078
- for (const e of entries.filter((e2) => !e2.directory && e2.name.endsWith(".md") && e2.name !== "index.md").sort()) {
9079
- const module = parseModule(await ctx.readFile(join(compendium, dir, e.name)), kind);
9080
- if (module)
9081
- catalog.set(module.code, module);
9640
+ if (character === ESC || character === CSI) {
9641
+ GROUP_REGEX.lastIndex = i + 1;
9642
+ const groupsResult = GROUP_REGEX.exec(preString);
9643
+ const groups = groupsResult?.groups;
9644
+ if (groups?.code !== void 0) {
9645
+ const code = Number.parseFloat(groups.code);
9646
+ escapeCode = code === END_CODE ? void 0 : code;
9647
+ } else if (groups?.uri !== void 0) {
9648
+ escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
9649
+ }
9650
+ }
9651
+ if (preString[i + 1] === "\n") {
9652
+ if (escapeUrl) {
9653
+ returnValue += wrapAnsiHyperlink("");
9654
+ }
9655
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
9656
+ if (escapeCode && closingCode) {
9657
+ returnValue += wrapAnsiCode(closingCode);
9658
+ }
9659
+ } else if (character === "\n") {
9660
+ if (escapeCode && getClosingCode(escapeCode)) {
9661
+ returnValue += wrapAnsiCode(escapeCode);
9662
+ }
9663
+ if (escapeUrl) {
9664
+ returnValue += wrapAnsiHyperlink(escapeUrl);
9665
+ }
9082
9666
  }
9083
9667
  }
9084
- return catalog;
9668
+ return returnValue;
9669
+ };
9670
+ var CRLF_OR_LF = /\r?\n/;
9671
+ function wrapAnsi(string, columns, options) {
9672
+ return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
9085
9673
  }
9086
9674
 
9087
- // ../lib/dist/io.js
9088
- import { spawn } from "node:child_process";
9089
- import { readdir, readFile, writeFile } from "node:fs/promises";
9090
- var ExecError = class extends Error {
9091
- command;
9092
- code;
9093
- stderr;
9094
- constructor(command, code, stderr) {
9095
- super(`${command} exited with ${code ?? "signal"}${stderr ? `
9096
- ${stderr.trimEnd()}` : ""}`);
9097
- this.command = command;
9098
- this.code = code;
9099
- this.stderr = stderr;
9100
- }
9101
- };
9102
- var isInteractive = () => process.stdin.isTTY === true && process.stderr.isTTY === true;
9103
- function realIo(prompt) {
9104
- return {
9105
- stdout: process.stdout,
9106
- stderr: process.stderr,
9107
- prompt: prompt && isInteractive() ? prompt : void 0,
9108
- exec: (command, args, options = {}) => new Promise((resolve3, reject) => {
9109
- const child = spawn(command, args, {
9110
- cwd: options.cwd,
9111
- env: options.env,
9112
- stdio: [options.input === void 0 ? "ignore" : "pipe", options.inherit ? "inherit" : "pipe", "pipe"]
9113
- });
9114
- let stdout = "";
9115
- let stderr = "";
9116
- child.stdout?.on("data", (chunk) => {
9117
- stdout += chunk;
9118
- });
9119
- child.stderr?.on("data", (chunk) => {
9120
- stderr += chunk;
9121
- if (options.inherit)
9122
- process.stderr.write(chunk);
9123
- });
9124
- child.on("error", reject);
9125
- child.on("close", (code) => {
9126
- if (code === 0)
9127
- resolve3(stdout);
9128
- else
9129
- reject(new ExecError(render(command, args), code, stderr));
9130
- });
9131
- if (options.input !== void 0)
9132
- child.stdin?.end(options.input);
9133
- }),
9134
- readFile: (path3) => readFile(path3, "utf8"),
9135
- writeFile: (path3, content) => writeFile(path3, content),
9136
- readDir: async (path3) => (await readdir(path3, { withFileTypes: true })).map((e) => ({ name: e.name, directory: e.isDirectory() }))
9137
- };
9675
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/utils.js
9676
+ function breakLines(content, width) {
9677
+ return content.split("\n").flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false }).split("\n").map((str) => str.trimEnd())).join("\n");
9138
9678
  }
9139
- function render(command, args) {
9140
- return [command, ...args].map(quote).join(" ");
9679
+ function readlineWidth() {
9680
+ return (0, import_cli_width.default)({ defaultWidth: 80, output: readline().output });
9141
9681
  }
9142
- function quote(arg) {
9143
- return /^[\w./:@%+=,-]+$/.test(arg) ? arg : `'${arg.replaceAll("'", "'\\''")}'`;
9682
+
9683
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/create-prompt.js
9684
+ import * as readline2 from "node:readline";
9685
+ import { AsyncResource as AsyncResource3 } from "node:async_hooks";
9686
+
9687
+ // ../../node_modules/.pnpm/@inquirer+type@4.2.0_@types+node@26.6.5/node_modules/@inquirer/type/dist/utils.js
9688
+ function withResolver() {
9689
+ let resolve7;
9690
+ let reject;
9691
+ const promise = new Promise((res, rej) => {
9692
+ resolve7 = res;
9693
+ reject = rej;
9694
+ });
9695
+ return { promise, resolve: resolve7, reject };
9144
9696
  }
9145
9697
 
9146
- // ../lib/dist/plan.js
9147
- function describe(step) {
9148
- switch (step.kind) {
9149
- case "run":
9150
- return `$ ${step.cwd ? `(cd ${step.cwd} && ` : ""}${render(step.command, step.args)}${step.cwd ? ")" : ""}`;
9151
- case "ssh":
9152
- return `$ ${render("ssh", [step.host, "bash", "-s"])} <<'EOF'`;
9153
- case "write":
9154
- return `> ${step.path} (${Buffer.byteLength(step.content)} bytes)`;
9155
- }
9698
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/create-prompt.js
9699
+ var import_mute_stream = __toESM(require_lib(), 1);
9700
+
9701
+ // ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js
9702
+ var signals = [];
9703
+ signals.push("SIGHUP", "SIGINT", "SIGTERM");
9704
+ if (process.platform !== "win32") {
9705
+ signals.push(
9706
+ "SIGALRM",
9707
+ "SIGABRT",
9708
+ "SIGVTALRM",
9709
+ "SIGXCPU",
9710
+ "SIGXFSZ",
9711
+ "SIGUSR2",
9712
+ "SIGTRAP",
9713
+ "SIGSYS",
9714
+ "SIGQUIT",
9715
+ "SIGIOT"
9716
+ // should detect profiler and enable/disable accordingly.
9717
+ // see #21
9718
+ // 'SIGPROF'
9719
+ );
9156
9720
  }
9157
- function body(step) {
9158
- switch (step.kind) {
9159
- case "run":
9160
- return step.input;
9161
- case "ssh":
9162
- return `${step.script.trimEnd()}
9163
- EOF`;
9164
- case "write":
9165
- return step.content;
9166
- }
9721
+ if (process.platform === "linux") {
9722
+ signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
9167
9723
  }
9168
9724
 
9169
- // ../lib/dist/context.js
9170
- var Context = class {
9171
- dryRun;
9172
- verbose;
9173
- quiet;
9174
- yes;
9175
- json;
9176
- io;
9177
- constructor(options, io = realIo()) {
9178
- this.io = io;
9179
- this.dryRun = options.dryRun ?? false;
9180
- this.quiet = options.quiet ?? false;
9181
- this.verbose = this.quiet ? -1 : options.verbose ?? 0;
9182
- this.yes = options.yes ?? false;
9183
- this.json = options.json ?? false;
9725
+ // ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js
9726
+ var processOk = (process5) => !!process5 && typeof process5 === "object" && typeof process5.removeListener === "function" && typeof process5.emit === "function" && typeof process5.reallyExit === "function" && typeof process5.listeners === "function" && typeof process5.kill === "function" && typeof process5.pid === "number" && typeof process5.on === "function";
9727
+ var kExitEmitter = /* @__PURE__ */ Symbol.for("signal-exit emitter");
9728
+ var global = globalThis;
9729
+ var ObjectDefineProperty = Object.defineProperty.bind(Object);
9730
+ var Emitter = class {
9731
+ emitted = {
9732
+ afterExit: false,
9733
+ exit: false
9734
+ };
9735
+ listeners = {
9736
+ afterExit: [],
9737
+ exit: []
9738
+ };
9739
+ count = 0;
9740
+ id = Math.random();
9741
+ constructor() {
9742
+ if (global[kExitEmitter]) {
9743
+ return global[kExitEmitter];
9744
+ }
9745
+ ObjectDefineProperty(global, kExitEmitter, {
9746
+ value: this,
9747
+ writable: false,
9748
+ enumerable: false,
9749
+ configurable: false
9750
+ });
9184
9751
  }
9185
- // --- narration (stderr) ---------------------------------------------------
9186
- /** One line, if the verbosity allows the level (0 normal, 1 verbose, 2 debug). */
9187
- say(line, level = 0) {
9188
- if (this.verbose >= level)
9189
- this.io.stderr.write(`${line}
9190
- `);
9752
+ on(ev, fn) {
9753
+ this.listeners[ev].push(fn);
9191
9754
  }
9192
- /** A final outcome line, `✓ ...` or `✗ ...`; shown even under --quiet. */
9193
- done(line, ok = true) {
9194
- this.io.stderr.write(`${ok ? "\u2713" : "\u2717"} ${line}
9195
- `);
9755
+ removeListener(ev, fn) {
9756
+ const list2 = this.listeners[ev];
9757
+ const i = list2.indexOf(fn);
9758
+ if (i === -1) {
9759
+ return;
9760
+ }
9761
+ if (i === 0 && list2.length === 1) {
9762
+ list2.length = 0;
9763
+ } else {
9764
+ list2.splice(i, 1);
9765
+ }
9196
9766
  }
9197
- // --- results (stdout) -----------------------------------------------------
9198
- /**
9199
- * The command's product. `data` is what --json prints; `human` renders it
9200
- * otherwise (default: strings as they are, arrays one item per line).
9201
- */
9202
- result(data, human = renderHuman) {
9203
- const text = this.json ? JSON.stringify(data, null, 2) : human(data);
9204
- this.io.stdout.write(text.endsWith("\n") ? text : `${text}
9205
- `);
9767
+ emit(ev, code, signal) {
9768
+ if (this.emitted[ev]) {
9769
+ return false;
9770
+ }
9771
+ this.emitted[ev] = true;
9772
+ let ret = false;
9773
+ for (const fn of this.listeners[ev]) {
9774
+ ret = fn(code, signal) === true || ret;
9775
+ }
9776
+ if (ev === "exit") {
9777
+ ret = this.emit("afterExit", code, signal) || ret;
9778
+ }
9779
+ return ret;
9206
9780
  }
9207
- // --- reads: always performed ---------------------------------------------
9208
- /** Run a command for its output. Changes nothing; narrated only when verbose. */
9209
- read(command, args = [], options = {}) {
9210
- this.say(`? ${describe({ kind: "run", command, args, ...options })}`, 1);
9211
- return this.io.exec(command, args, options);
9781
+ };
9782
+ var SignalExitBase = class {
9783
+ };
9784
+ var signalExitWrap = (handler) => {
9785
+ return {
9786
+ onExit(cb, opts) {
9787
+ return handler.onExit(cb, opts);
9788
+ },
9789
+ load() {
9790
+ return handler.load();
9791
+ },
9792
+ unload() {
9793
+ return handler.unload();
9794
+ }
9795
+ };
9796
+ };
9797
+ var SignalExitFallback = class extends SignalExitBase {
9798
+ onExit() {
9799
+ return () => {
9800
+ };
9212
9801
  }
9213
- readFile(path3) {
9214
- this.say(`? read ${path3}`, 1);
9215
- return this.io.readFile(path3);
9802
+ load() {
9216
9803
  }
9217
- readDir(path3) {
9218
- this.say(`? list ${path3}`, 2);
9219
- return this.io.readDir(path3);
9804
+ unload() {
9220
9805
  }
9221
- // --- effects: narrated always, performed unless --dry-run -----------------
9222
- /**
9223
- * Ask before applying. `--yes` and `--dry-run` answer yes; off a terminal
9224
- * without `--yes` the answer is an error, never a hang.
9225
- */
9226
- async confirm(question) {
9227
- if (this.yes || this.dryRun) {
9228
- this.say(`? ${question} yes (${this.yes ? "--yes" : "--dry-run"})`, 1);
9229
- return true;
9806
+ };
9807
+ var SignalExit = class extends SignalExitBase {
9808
+ // "SIGHUP" throws an `ENOSYS` error on Windows,
9809
+ // so use a supported signal instead
9810
+ /* c8 ignore start */
9811
+ #hupSig = process3.platform === "win32" ? "SIGINT" : "SIGHUP";
9812
+ /* c8 ignore stop */
9813
+ #emitter = new Emitter();
9814
+ #process;
9815
+ #originalProcessEmit;
9816
+ #originalProcessReallyExit;
9817
+ #sigListeners = {};
9818
+ #loaded = false;
9819
+ constructor(process5) {
9820
+ super();
9821
+ this.#process = process5;
9822
+ this.#sigListeners = {};
9823
+ for (const sig of signals) {
9824
+ this.#sigListeners[sig] = () => {
9825
+ const listeners = this.#process.listeners(sig);
9826
+ let { count } = this.#emitter;
9827
+ const p = process5;
9828
+ if (typeof p.__signal_exit_emitter__ === "object" && typeof p.__signal_exit_emitter__.count === "number") {
9829
+ count += p.__signal_exit_emitter__.count;
9830
+ }
9831
+ if (listeners.length === count) {
9832
+ this.unload();
9833
+ const ret = this.#emitter.emit("exit", null, sig);
9834
+ const s = sig === "SIGHUP" ? this.#hupSig : sig;
9835
+ if (!ret)
9836
+ process5.kill(process5.pid, s);
9837
+ }
9838
+ };
9230
9839
  }
9231
- if (!this.io.prompt)
9232
- throw new Error(`cannot ask "${question}" without a terminal; pass --yes`);
9233
- return this.io.prompt(question);
9840
+ this.#originalProcessReallyExit = process5.reallyExit;
9841
+ this.#originalProcessEmit = process5.emit;
9234
9842
  }
9235
- /** Narrate and perform each step in order; the first failure stops the run. */
9236
- async apply(plan) {
9237
- for (const step of plan) {
9238
- this.say(`${this.dryRun ? "[dry-run] " : ""}${describe(step)}`);
9239
- const input = body(step);
9240
- if (input !== void 0)
9241
- this.say(indent(input), step.kind === "write" ? 2 : 1);
9242
- if (!this.dryRun)
9243
- await this.perform(step);
9843
+ onExit(cb, opts) {
9844
+ if (!processOk(this.#process)) {
9845
+ return () => {
9846
+ };
9847
+ }
9848
+ if (this.#loaded === false) {
9849
+ this.load();
9244
9850
  }
9851
+ const ev = opts?.alwaysLast ? "afterExit" : "exit";
9852
+ this.#emitter.on(ev, cb);
9853
+ return () => {
9854
+ this.#emitter.removeListener(ev, cb);
9855
+ if (this.#emitter.listeners["exit"].length === 0 && this.#emitter.listeners["afterExit"].length === 0) {
9856
+ this.unload();
9857
+ }
9858
+ };
9245
9859
  }
9246
- perform(step) {
9247
- const inherit = this.verbose >= 2;
9248
- switch (step.kind) {
9249
- case "run":
9250
- return this.io.exec(step.command, step.args, { cwd: step.cwd, input: step.input, inherit });
9251
- case "ssh":
9252
- return this.io.exec("ssh", [step.host, "bash", "-s"], { input: step.script, inherit });
9253
- case "write":
9254
- return this.io.writeFile(step.path, step.content);
9860
+ load() {
9861
+ if (this.#loaded) {
9862
+ return;
9863
+ }
9864
+ this.#loaded = true;
9865
+ this.#emitter.count += 1;
9866
+ for (const sig of signals) {
9867
+ try {
9868
+ const fn = this.#sigListeners[sig];
9869
+ if (fn)
9870
+ this.#process.on(sig, fn);
9871
+ } catch (_) {
9872
+ }
9873
+ }
9874
+ this.#process.emit = (ev, ...a) => {
9875
+ return this.#processEmit(ev, ...a);
9876
+ };
9877
+ this.#process.reallyExit = (code) => {
9878
+ return this.#processReallyExit(code);
9879
+ };
9880
+ }
9881
+ unload() {
9882
+ if (!this.#loaded) {
9883
+ return;
9884
+ }
9885
+ this.#loaded = false;
9886
+ signals.forEach((sig) => {
9887
+ const listener = this.#sigListeners[sig];
9888
+ if (!listener) {
9889
+ throw new Error("Listener not defined for signal: " + sig);
9890
+ }
9891
+ try {
9892
+ this.#process.removeListener(sig, listener);
9893
+ } catch (_) {
9894
+ }
9895
+ });
9896
+ this.#process.emit = this.#originalProcessEmit;
9897
+ this.#process.reallyExit = this.#originalProcessReallyExit;
9898
+ this.#emitter.count -= 1;
9899
+ }
9900
+ #processReallyExit(code) {
9901
+ if (!processOk(this.#process)) {
9902
+ return 0;
9903
+ }
9904
+ this.#process.exitCode = code || 0;
9905
+ this.#emitter.emit("exit", this.#process.exitCode, null);
9906
+ return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode);
9907
+ }
9908
+ #processEmit(ev, ...args) {
9909
+ const og = this.#originalProcessEmit;
9910
+ if (ev === "exit" && processOk(this.#process)) {
9911
+ if (typeof args[0] === "number") {
9912
+ this.#process.exitCode = args[0];
9913
+ }
9914
+ const ret = og.call(this.#process, ev, ...args);
9915
+ this.#emitter.emit("exit", this.#process.exitCode, null);
9916
+ return ret;
9917
+ } else {
9918
+ return og.call(this.#process, ev, ...args);
9255
9919
  }
9256
9920
  }
9257
9921
  };
9258
- function renderHuman(data) {
9259
- if (typeof data === "string")
9260
- return data;
9261
- if (Array.isArray(data))
9262
- return data.map(String).join("\n");
9263
- return JSON.stringify(data, null, 2);
9264
- }
9265
- function indent(text) {
9266
- return text.trimEnd().split("\n").map((l) => ` ${l}`).join("\n");
9267
- }
9922
+ var process3 = globalThis.process;
9923
+ var {
9924
+ /**
9925
+ * Called when the process is exiting, whether via signal, explicit
9926
+ * exit, or running out of stuff to do.
9927
+ *
9928
+ * If the global process object is not suitable for instrumentation,
9929
+ * then this will be a no-op.
9930
+ *
9931
+ * Returns a function that may be used to unload signal-exit.
9932
+ */
9933
+ onExit,
9934
+ /**
9935
+ * Load the listeners. Likely you never need to call this, unless
9936
+ * doing a rather deep integration with signal-exit functionality.
9937
+ * Mostly exposed for the benefit of testing.
9938
+ *
9939
+ * @internal
9940
+ */
9941
+ load,
9942
+ /**
9943
+ * Unload the listeners. Likely you never need to call this, unless
9944
+ * doing a rather deep integration with signal-exit functionality.
9945
+ * Mostly exposed for the benefit of testing.
9946
+ *
9947
+ * @internal
9948
+ */
9949
+ unload
9950
+ } = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback());
9268
9951
 
9269
- // ../lib/dist/copier.js
9270
- var import_yaml2 = __toESM(require_dist(), 1);
9271
- var ANSWERS_FILE = ".copier-answers.yml";
9272
- var TEMPLATE_FILES = ["copier.yml", "copier.yaml"];
9273
- function parseAnswers(text) {
9274
- const data = (0, import_yaml2.parse)(text);
9275
- if (data === null || typeof data !== "object" || Array.isArray(data))
9276
- throw new Error("answers file is not a mapping");
9277
- const { _commit, _src_path, ...answers } = data;
9278
- return {
9279
- commit: _commit === void 0 ? void 0 : String(_commit),
9280
- src: _src_path === void 0 ? void 0 : String(_src_path),
9281
- answers
9282
- };
9283
- }
9952
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/screen-manager.js
9953
+ import { stripVTControlCharacters } from "node:util";
9284
9954
 
9285
- // ../lib/dist/doctor.js
9286
- import { relative } from "node:path";
9287
- function diagnose(root, catalog) {
9288
- const units = collect(root, []);
9289
- const declarations = units.map((u) => diagnoseUnit(u, units, catalog, root.path));
9290
- return { declarations, stale: declarations.filter((d) => d.findings.length > 0).length };
9291
- }
9292
- function collect(dir, ancestors, parent) {
9293
- const here = dir.declaration || dir.problems?.some((p) => p.startsWith("PLEXUS.md")) ? [{ dir, ancestors, parent }] : [];
9294
- const below = dir.declaration ? [...ancestors, dir] : ancestors;
9295
- return [...here, ...dir.children.flatMap((c) => collect(c, below, dir))];
9296
- }
9297
- function diagnoseUnit(unit, units, catalog, root) {
9298
- const { dir } = unit;
9299
- const path3 = relative(root, dir.path) || ".";
9300
- const problem = dir.problems?.find((p) => p.startsWith("PLEXUS.md"));
9301
- if (!dir.declaration)
9302
- return { path: path3, modules: [], findings: [problem?.replace(/^PLEXUS\.md: /, "") ?? "unreadable marker"] };
9303
- const { plexus, modules } = dir.declaration;
9304
- const context = new Set(contextOf(unit, units).flatMap((d) => d.declaration?.modules ?? []));
9305
- const findings = [];
9306
- for (const code of modules) {
9307
- const module = catalog.get(code);
9308
- if (!module) {
9309
- findings.push(`declares ${code}, which no module carries`);
9310
- continue;
9311
- }
9312
- if (module.changed && compareTrains(module.changed, plexus) > 0)
9313
- findings.push(`${code} changed in ${module.changed}, declared at ${plexus}`);
9314
- for (const dep of module.depends)
9315
- if (!modules.includes(dep) && !context.has(dep))
9316
- findings.push(`${code} depends on ${dep}, declared neither here nor by an enclosing or contained declaration`);
9955
+ // ../../node_modules/.pnpm/@inquirer+ansi@2.0.9/node_modules/@inquirer/ansi/dist/index.js
9956
+ var ESC2 = "\x1B[";
9957
+ var cursorLeft = ESC2 + "G";
9958
+ var cursorHide = ESC2 + "?25l";
9959
+ var cursorShow = ESC2 + "?25h";
9960
+ var cursorUp = (rows = 1) => rows > 0 ? `${ESC2}${rows}A` : "";
9961
+ var cursorDown = (rows = 1) => rows > 0 ? `${ESC2}${rows}B` : "";
9962
+ var cursorTo = (x, y) => {
9963
+ if (typeof y === "number" && !Number.isNaN(y)) {
9964
+ return `${ESC2}${y + 1};${x + 1}H`;
9317
9965
  }
9318
- return { path: path3, plexus, modules, findings };
9319
- }
9320
- function contextOf(unit, units) {
9321
- const { dir, ancestors } = unit;
9322
- const context = [...ancestors, ...descendants(dir)];
9323
- const repo = ancestors[0] ?? dir;
9324
- const repoParent = units.find((u) => u.dir === repo)?.parent;
9325
- const siblings = repoParent?.children.filter((c) => c !== repo && c.declaration) ?? [];
9326
- const isTenancy = (d) => d.declaration?.modules.includes("PLX-Tenancy") ?? false;
9327
- context.push(...siblings.filter(isTenancy));
9328
- if (isTenancy(dir))
9329
- context.push(...siblings);
9330
- return context;
9331
- }
9332
- function descendants(dir) {
9333
- return dir.children.flatMap((c) => [...c.declaration ? [c] : [], ...descendants(c)]);
9334
- }
9335
- function compareTrains(a, b) {
9336
- const nums = (v) => v.split(".").slice(0, 3).map((p) => Number.parseInt(p, 10) || 0);
9337
- const [x, y] = [nums(a), nums(b)];
9338
- for (let i = 0; i < 3; i++)
9339
- if ((x[i] ?? 0) !== (y[i] ?? 0))
9340
- return (x[i] ?? 0) > (y[i] ?? 0) ? 1 : -1;
9341
- return 0;
9342
- }
9343
-
9344
- // ../lib/dist/model.js
9345
- function kindOf(declaration) {
9346
- const has = (code) => declaration.modules.includes(code);
9347
- if (has("PLX-App"))
9348
- return "app";
9349
- if (has("PLX-Platform"))
9350
- return "platform";
9351
- if (has("PLX-Repo"))
9352
- return "repo";
9353
- return void 0;
9354
- }
9355
- function shortRemote(url) {
9356
- const bare = url.replace(/\.git$/, "").replace(/\/$/, "");
9357
- const m = /^(?:git@github\.com:|github\.com:|ssh:\/\/git@github\.com\/|https?:\/\/github\.com\/)(.+)$/.exec(bare);
9358
- return m ? `gh:${m[1]}` : bare;
9359
- }
9360
- function isNotable(dir) {
9361
- return Boolean(dir.git || dir.template || dir.copier || dir.declaration || dir.problems?.length);
9362
- }
9966
+ return `${ESC2}${x + 1}G`;
9967
+ };
9968
+ var eraseLine = ESC2 + "2K";
9969
+ var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
9363
9970
 
9364
- // ../lib/dist/overview.js
9365
- import { join as join2 } from "node:path";
9366
- var PRUNED = /* @__PURE__ */ new Set([
9367
- "node_modules",
9368
- ".hg",
9369
- ".svn",
9370
- ".next",
9371
- ".nuxt",
9372
- ".turbo",
9373
- ".svelte-kit",
9374
- "dist",
9375
- "build",
9376
- "out",
9377
- ".output",
9378
- ".venv",
9379
- "venv",
9380
- "__pycache__",
9381
- "target",
9382
- ".cache",
9383
- ".pnpm-store",
9384
- "coverage",
9385
- "vendor",
9386
- ".terraform",
9387
- ".gradle"
9388
- ]);
9389
- function overview(ctx, root, options = {}) {
9390
- return walk(ctx, root, root.replace(/\/+$/, "").split("/").pop() || root, { git: true, ...options });
9391
- }
9392
- async function walk(ctx, path3, name, options) {
9393
- const entries = await ctx.readDir(path3);
9394
- const files = new Set(entries.filter((e) => !e.directory).map((e) => e.name));
9395
- const names = new Set(entries.map((e) => e.name));
9396
- const dir = { name, path: path3, children: [] };
9397
- if (names.has(".git") && options.git)
9398
- dir.git = await gitFacet(ctx, path3);
9399
- if (TEMPLATE_FILES.some((f) => files.has(f)))
9400
- dir.template = options.git ? await templateFacet(ctx, path3) : {};
9401
- if (files.has(ANSWERS_FILE)) {
9402
- await facet(ctx, dir, ANSWERS_FILE, (text) => {
9403
- dir.copier = parseAnswers(text);
9404
- });
9971
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/screen-manager.js
9972
+ var height = (content) => content.split("\n").length;
9973
+ var lastLine = (content) => content.split("\n").pop() ?? "";
9974
+ var ScreenManager = class {
9975
+ // These variables are keeping information to allow correct prompt re-rendering
9976
+ height = 0;
9977
+ extraLinesUnderPrompt = 0;
9978
+ cursorPos;
9979
+ rl;
9980
+ constructor(rl) {
9981
+ this.rl = rl;
9982
+ this.cursorPos = rl.getCursorPos();
9405
9983
  }
9406
- if (files.has(MARKER_FILE)) {
9407
- await facet(ctx, dir, MARKER_FILE, (text) => {
9408
- dir.declaration = parseMarker(text);
9409
- });
9984
+ write(content) {
9985
+ this.rl.output.unmute();
9986
+ this.rl.output.write(content);
9987
+ this.rl.output.mute();
9410
9988
  }
9411
- const subdirs = entries.filter((e) => e.directory && e.name !== ".git" && !PRUNED.has(e.name)).map((e) => e.name).sort();
9412
- for (const sub of subdirs) {
9413
- const child = await walk(ctx, join2(path3, sub), sub, options);
9414
- if (isNotable(child) || child.children.length > 0)
9415
- dir.children.push(child);
9989
+ render(content, bottomContent = "") {
9990
+ const promptLine = lastLine(content);
9991
+ const rawPromptLine = stripVTControlCharacters(promptLine);
9992
+ let prompt = rawPromptLine;
9993
+ if (this.rl.line.length > 0) {
9994
+ prompt = prompt.slice(0, -this.rl.line.length);
9995
+ }
9996
+ this.rl.setPrompt(prompt);
9997
+ this.cursorPos = this.rl.getCursorPos();
9998
+ const width = readlineWidth();
9999
+ content = breakLines(content, width);
10000
+ bottomContent = breakLines(bottomContent, width);
10001
+ if (rawPromptLine.length % width === 0) {
10002
+ content += "\n";
10003
+ }
10004
+ let output = content + (bottomContent ? "\n" + bottomContent : "");
10005
+ const promptLineUpDiff = Math.floor(rawPromptLine.length / width) - this.cursorPos.rows;
10006
+ const bottomContentHeight = promptLineUpDiff + (bottomContent ? height(bottomContent) : 0);
10007
+ if (bottomContentHeight > 0)
10008
+ output += cursorUp(bottomContentHeight);
10009
+ output += cursorTo(this.cursorPos.cols);
10010
+ this.write(cursorDown(this.extraLinesUnderPrompt) + eraseLines(this.height) + output);
10011
+ this.extraLinesUnderPrompt = bottomContentHeight;
10012
+ this.height = height(output);
10013
+ }
10014
+ checkCursorPos() {
10015
+ const cursorPos = this.rl.getCursorPos();
10016
+ if (cursorPos.cols !== this.cursorPos.cols) {
10017
+ this.write(cursorTo(cursorPos.cols));
10018
+ this.cursorPos = cursorPos;
10019
+ }
10020
+ }
10021
+ done({ clearContent }) {
10022
+ this.rl.setPrompt("");
10023
+ let output = cursorDown(this.extraLinesUnderPrompt);
10024
+ output += clearContent ? eraseLines(this.height) : "\n";
10025
+ output += cursorLeft;
10026
+ output += cursorShow;
10027
+ this.write(output);
10028
+ this.rl.close();
9416
10029
  }
9417
- return dir;
9418
- }
9419
- async function facet(ctx, dir, file, read) {
9420
- try {
9421
- read(await ctx.readFile(join2(dir.path, file)));
9422
- } catch (error) {
9423
- dir.problems ??= [];
9424
- dir.problems.push(`${file}: ${error instanceof Error ? error.message : String(error)}`);
10030
+ };
10031
+
10032
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/create-prompt.js
10033
+ import path from "node:path";
10034
+ var nativeSetImmediate = globalThis.setImmediate;
10035
+ var nativeClearImmediate = globalThis.clearImmediate;
10036
+ function listenTo(target, event, listener) {
10037
+ if ("on" in target) {
10038
+ target.on(event, listener);
10039
+ return () => target.removeListener(event, listener);
9425
10040
  }
10041
+ target.addEventListener(event, listener);
10042
+ return () => target.removeEventListener(event, listener);
9426
10043
  }
9427
- async function git(ctx, cwd, args) {
10044
+ function getCallSites() {
10045
+ const savedPrepareStackTrace = Error.prepareStackTrace;
10046
+ let result = [];
9428
10047
  try {
9429
- const out = (await ctx.read("git", args, { cwd })).trim();
9430
- return out === "" ? void 0 : out;
10048
+ Error.prepareStackTrace = (_, callSites) => {
10049
+ const callSitesWithoutCurrent = callSites.slice(1);
10050
+ result = callSitesWithoutCurrent;
10051
+ return callSitesWithoutCurrent;
10052
+ };
10053
+ new Error().stack;
9431
10054
  } catch {
9432
- return void 0;
9433
- }
9434
- }
9435
- async function gitFacet(ctx, cwd) {
9436
- const branch = await git(ctx, cwd, ["symbolic-ref", "--short", "-q", "HEAD"]) ?? await git(ctx, cwd, ["rev-parse", "--short", "HEAD"]) ?? "?";
9437
- const dirty = await git(ctx, cwd, ["status", "--porcelain"]) !== void 0;
9438
- const remote = await git(ctx, cwd, ["remote", "get-url", "origin"]);
9439
- let defaultRef = await git(ctx, cwd, ["symbolic-ref", "--short", "-q", "refs/remotes/origin/HEAD"]);
9440
- for (const b of ["main", "master"]) {
9441
- if (defaultRef)
9442
- break;
9443
- if (await git(ctx, cwd, ["rev-parse", "--verify", "-q", `refs/heads/${b}`]))
9444
- defaultRef = b;
10055
+ return result;
9445
10056
  }
9446
- const tag = defaultRef ? await git(ctx, cwd, ["describe", "--tags", "--abbrev=0", defaultRef]) : void 0;
9447
- const facet2 = { branch, dirty };
9448
- if (tag)
9449
- facet2.tag = tag;
9450
- if (remote)
9451
- facet2.remote = shortRemote(remote);
9452
- return facet2;
10057
+ Error.prepareStackTrace = savedPrepareStackTrace;
10058
+ return result;
9453
10059
  }
9454
- async function templateFacet(ctx, cwd) {
9455
- const tag = await git(ctx, cwd, ["describe", "--tags", "--abbrev=0"]) ?? (await git(ctx, cwd, ["tag", "--list", "--sort=-v:refname"]))?.split("\n")[0];
9456
- return tag ? { tag } : {};
10060
+ function createPrompt(view) {
10061
+ const callSites = getCallSites();
10062
+ const prompt = (config, context = {}) => {
10063
+ const { input = process.stdin, signal } = context;
10064
+ const cleanups = /* @__PURE__ */ new Set();
10065
+ const output = new import_mute_stream.default();
10066
+ output.pipe(context.output ?? process.stdout);
10067
+ const rl = readline2.createInterface({
10068
+ terminal: true,
10069
+ input,
10070
+ output
10071
+ });
10072
+ output.mute();
10073
+ const screen = new ScreenManager(rl);
10074
+ const { promise, resolve: resolve7, reject } = withResolver();
10075
+ return withHooks(rl, (cycle) => {
10076
+ const clearEffects = AsyncResource3.bind(() => effectScheduler.clearAll());
10077
+ const settlePrompt = (settle) => {
10078
+ try {
10079
+ clearEffects();
10080
+ settle();
10081
+ } catch (error) {
10082
+ reject(error);
10083
+ }
10084
+ };
10085
+ const resolvePrompt = (value) => settlePrompt(() => resolve7(value));
10086
+ const rejectPrompt = (error) => settlePrompt(() => reject(error));
10087
+ const promptPromise = Object.assign(promise.finally(() => {
10088
+ cleanups.forEach((cleanup) => cleanup());
10089
+ screen.done({ clearContent: Boolean(context.clearPromptOnDone) });
10090
+ output.end();
10091
+ }).then(() => promise), { cancel: () => rejectPrompt(new CancelPromptError()) });
10092
+ if (signal) {
10093
+ const abort = () => rejectPrompt(new AbortPromptError({ cause: signal.reason }));
10094
+ if (signal.aborted) {
10095
+ abort();
10096
+ return promptPromise;
10097
+ }
10098
+ cleanups.add(listenTo(signal, "abort", abort));
10099
+ }
10100
+ cleanups.add(onExit((code, signal2) => {
10101
+ rejectPrompt(new ExitPromptError(`User force closed the prompt with ${code} ${signal2}`));
10102
+ }));
10103
+ cleanups.add(listenTo(rl, "SIGINT", () => rejectPrompt(new ExitPromptError(`User force closed the prompt with SIGINT`))));
10104
+ cleanups.add(listenTo(rl, "close", clearEffects));
10105
+ const startCycle = () => {
10106
+ cleanups.add(listenTo(rl.input, "keypress", () => screen.checkCursorPos()));
10107
+ let pendingDone = null;
10108
+ cycle(() => {
10109
+ let effectsSettled = false;
10110
+ try {
10111
+ const nextView = view(config, (value) => {
10112
+ if (effectsSettled) {
10113
+ resolvePrompt(value);
10114
+ } else {
10115
+ pendingDone = { value };
10116
+ }
10117
+ });
10118
+ if (nextView === void 0) {
10119
+ let callerFilename = callSites[1]?.getFileName();
10120
+ if (callerFilename && !callerFilename.startsWith("file://")) {
10121
+ callerFilename = path.resolve(callerFilename);
10122
+ }
10123
+ throw new Error(`Prompt functions must return a string.
10124
+ at ${callerFilename}`);
10125
+ }
10126
+ const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
10127
+ screen.render(content, bottomContent);
10128
+ effectScheduler.run();
10129
+ } catch (error) {
10130
+ rejectPrompt(error);
10131
+ }
10132
+ effectsSettled = true;
10133
+ if (pendingDone !== null) {
10134
+ const { value } = pendingDone;
10135
+ pendingDone = null;
10136
+ resolvePrompt(value);
10137
+ }
10138
+ });
10139
+ };
10140
+ if ("readableFlowing" in input) {
10141
+ const immediate = nativeSetImmediate(startCycle);
10142
+ cleanups.add(() => nativeClearImmediate(immediate));
10143
+ } else {
10144
+ startCycle();
10145
+ }
10146
+ return promptPromise;
10147
+ });
10148
+ };
10149
+ return prompt;
9457
10150
  }
9458
10151
 
10152
+ // ../../node_modules/.pnpm/@inquirer+confirm@6.3.4_@types+node@26.6.5/node_modules/@inquirer/confirm/dist/index.js
10153
+ import { styleText as styleText2 } from "node:util";
10154
+ var confirmTheme = {
10155
+ keywords: {
10156
+ yes: "Yes",
10157
+ no: "No",
10158
+ error: ({ yes, no }) => `You must answer with "${yes}" or "${no}"`
10159
+ },
10160
+ style: {
10161
+ confirmDefault: (text) => {
10162
+ const first = text[0] ?? "";
10163
+ if (first.toLowerCase() === first.toUpperCase()) {
10164
+ return styleText2("cyan", text);
10165
+ }
10166
+ return first.toUpperCase() + text.slice(1);
10167
+ }
10168
+ }
10169
+ };
10170
+ var dist_default4 = createPrompt((config, done) => {
10171
+ const [status, setStatus] = useState("idle");
10172
+ const [value, setValue] = useState("");
10173
+ const [errorMsg, setError] = useState();
10174
+ const theme = makeTheme(confirmTheme, config.theme);
10175
+ const prefix = usePrefix({ status, theme });
10176
+ const { yes, no } = theme.keywords;
10177
+ const yesHint = (yes[0] ?? "").toLowerCase();
10178
+ const noHint = (no[0] ?? "").toLowerCase();
10179
+ const hint = config.default === false ? `${yesHint}/${theme.style.confirmDefault(noHint)}` : `${theme.style.confirmDefault(yesHint)}/${noHint}`;
10180
+ function boolToString(value2) {
10181
+ return value2 ? yes : no;
10182
+ }
10183
+ const { transformer = boolToString } = config;
10184
+ function getBooleanValue(value2) {
10185
+ const v = value2.trim().toLowerCase();
10186
+ if (v === "")
10187
+ return config.default !== false;
10188
+ if (yes.toLowerCase().startsWith(v))
10189
+ return true;
10190
+ if (no.toLowerCase().startsWith(v))
10191
+ return false;
10192
+ if ("yes".startsWith(v))
10193
+ return true;
10194
+ if ("no".startsWith(v))
10195
+ return false;
10196
+ return void 0;
10197
+ }
10198
+ useKeypress((key, rl) => {
10199
+ if (status !== "idle")
10200
+ return;
10201
+ if (isEnterKey(key)) {
10202
+ const answer = getBooleanValue(value);
10203
+ if (answer === void 0) {
10204
+ rl.write(value);
10205
+ setError(theme.keywords.error({ yes, no }));
10206
+ return;
10207
+ }
10208
+ setValue(transformer(answer));
10209
+ setStatus("done");
10210
+ done(answer);
10211
+ } else if (isTabKey(key)) {
10212
+ const answer = boolToString(!(getBooleanValue(value) ?? config.default !== false));
10213
+ rl.clearLine(0);
10214
+ rl.write(answer);
10215
+ setValue(answer);
10216
+ } else {
10217
+ setValue(rl.line);
10218
+ setError(void 0);
10219
+ }
10220
+ });
10221
+ let formattedValue = value;
10222
+ let defaultValue = "";
10223
+ if (status === "done") {
10224
+ formattedValue = theme.style.answer(value);
10225
+ } else {
10226
+ defaultValue = ` ${theme.style.defaultAnswer(hint)}`;
10227
+ }
10228
+ const message = theme.style.message(config.message, status);
10229
+ let error = "";
10230
+ if (errorMsg) {
10231
+ error = theme.style.error(errorMsg);
10232
+ }
10233
+ return [`${prefix} ${message}${defaultValue} ${formattedValue}`, error];
10234
+ });
10235
+
9459
10236
  // ../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js
9460
10237
  var CommanderError = class extends Error {
9461
10238
  /**
@@ -10885,8 +11662,8 @@ var Command = class _Command extends EventEmitter {
10885
11662
  * @return {Command} `this` command for chaining
10886
11663
  */
10887
11664
  arguments(names) {
10888
- names.trim().split(/ +/).forEach((detail) => {
10889
- this.argument(detail);
11665
+ names.trim().split(/ +/).forEach((detail2) => {
11666
+ this.argument(detail2);
10890
11667
  });
10891
11668
  return this;
10892
11669
  }
@@ -12824,9 +13601,25 @@ function useColor() {
12824
13601
  // ../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/index.js
12825
13602
  var program = new Command();
12826
13603
 
13604
+ // src/commands/changeset.ts
13605
+ import { resolve } from "node:path";
13606
+ function register(program2) {
13607
+ program2.command("changeset").description("write the changeset a dependency bump owes: a patch per package whose runtime dependencies moved").argument("[dir]", "a checkout of the package repo, on the bump branch", ".").option("--base <ref>", "the trunk the branch is diffed against, at the merge base", "origin/main").option("--branch <name>", "the branch name that names the file (default: the checked-out branch)").action(async (dir, opts, command) => {
13608
+ const ctx = contextOf2(command);
13609
+ const changeset = await readChangeset(ctx, resolve(dir), opts.base, opts.branch);
13610
+ await ctx.apply(changeset.plan);
13611
+ ctx.result(changeset, renderChangeset);
13612
+ });
13613
+ }
13614
+ function renderChangeset(c) {
13615
+ const releases = Object.entries(c.releases);
13616
+ if (releases.length === 0) return `\u2713 nothing owed; no ${c.path}`;
13617
+ return [`\u2713 ${c.path}`, ...releases.map(([name, bump]) => ` ${name}: ${bump}`)].join("\n");
13618
+ }
13619
+
12827
13620
  // src/commands/doctor.ts
12828
13621
  import { existsSync } from "node:fs";
12829
- import { join as join3, resolve } from "node:path";
13622
+ import { join as join8, resolve as resolve2 } from "node:path";
12830
13623
 
12831
13624
  // src/style.ts
12832
13625
  function style(enabled) {
@@ -12837,15 +13630,15 @@ var colorByDefault = () => process.stdout.isTTY === true && !process.env.NO_COLO
12837
13630
 
12838
13631
  // src/commands/doctor.ts
12839
13632
  var WORKSPACE_COMPENDIUM = "plexus-ms/compendium";
12840
- function register(program2) {
13633
+ function register2(program2) {
12841
13634
  program2.command("doctor").description("check every PLEXUS.md under a directory for modules that changed since and dependencies not declared").argument("[dir]", "directory to check", ".").option(
12842
13635
  "--compendium <path>",
12843
13636
  `compendium checkout to read the modules from (default: <dir>/${WORKSPACE_COMPENDIUM})`
12844
13637
  ).option("--color", "colour the report even when piped").option("--no-color", "never colour the report").action(async (dir, opts, command) => {
12845
13638
  const ctx = contextOf2(command);
12846
- const root = resolve(dir);
12847
- const compendium = resolve(opts.compendium ?? join3(root, WORKSPACE_COMPENDIUM));
12848
- if (!existsSync(join3(compendium, "contracts")))
13639
+ const root = resolve2(dir);
13640
+ const compendium = resolve2(opts.compendium ?? join8(root, WORKSPACE_COMPENDIUM));
13641
+ if (!existsSync(join8(compendium, "contracts")))
12849
13642
  throw new Error(
12850
13643
  `no compendium at ${compendium}; pass --compendium <path to a checkout of plexus-ms/compendium>`
12851
13644
  );
@@ -12873,11 +13666,11 @@ function renderReport(report, s, showCurrent) {
12873
13666
  }
12874
13667
 
12875
13668
  // src/commands/overview.ts
12876
- import { resolve as resolve2 } from "node:path";
12877
- function register2(program2) {
13669
+ import { resolve as resolve3 } from "node:path";
13670
+ function register3(program2) {
12878
13671
  program2.command("overview").description("map the git repos, copier templates and projects, and Plexus units under a directory").argument("[dir]", "directory to map", ".").option("--color", "colour the tree even when piped").option("--no-color", "never colour the tree").action(async (dir, opts, command) => {
12879
13672
  const ctx = contextOf2(command);
12880
- const tree = await overview(ctx, resolve2(dir));
13673
+ const tree = await overview(ctx, resolve3(dir));
12881
13674
  const s = style(opts.color ?? colorByDefault());
12882
13675
  ctx.result(tree, (t) => renderTree(t, s, ctx.verbose >= 1));
12883
13676
  });
@@ -12919,8 +13712,68 @@ function annotate(dir, s, modules) {
12919
13712
  return tags.length ? ` ${tags.join(" ")}` : "";
12920
13713
  }
12921
13714
 
13715
+ // src/commands/propagate.ts
13716
+ import { resolve as resolve5 } from "node:path";
13717
+
13718
+ // src/commands/ship.ts
13719
+ import { resolve as resolve4 } from "node:path";
13720
+ function register4(program2) {
13721
+ program2.command("ship").description("release the train: tag every train repo identically, then copier-update every consumer").argument("[dir]", "the workspace: plexus-ms/ and the consumers sit under it", ".").option("--train <version>", "the train version, plain semver (default: minor+1 over the latest train)").action(async (dir, opts, command) => {
13722
+ const ctx = contextOf2(command);
13723
+ const result = await ship(ctx, { workspace: resolve4(dir), train: opts.train });
13724
+ ctx.result(result, (r) => renderSummary(r, `plx -y ship --train ${r.train} ${dir}`));
13725
+ if (!isClean(result)) process.exitCode = 1;
13726
+ });
13727
+ }
13728
+ function renderSummary(s, realCommand) {
13729
+ const lines = ["\u2500\u2500 summary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"];
13730
+ for (const p of s.clean) lines.push(` \u2713 clean: ${p}`);
13731
+ for (const p of s.conflicted) lines.push(` \u2717 conflicts: ${p}`);
13732
+ for (const p of s.failed) lines.push(` \u2717 failed: ${p}`);
13733
+ for (const { path: path3, reason } of s.skipped) lines.push(` \u26A0 skipped: ${path3} (${reason})`);
13734
+ const clean = isClean(s);
13735
+ if (s.preview) {
13736
+ lines.push(" (preview only \u2014 nothing was changed)");
13737
+ if (clean) lines.push(`\u2713 dry run clean \u2014 run it for real: ${realCommand}`);
13738
+ } else if (clean) {
13739
+ lines.push("\u2713 done \u2014 review consumer diffs, commit (web repos on develop, platform repos on main), push");
13740
+ }
13741
+ if (!clean) lines.push("\u2717 needs attention \u2014 see above; fix the consumer, then re-run propagate");
13742
+ return lines.join("\n");
13743
+ }
13744
+
13745
+ // src/commands/propagate.ts
13746
+ function register5(program2) {
13747
+ program2.command("propagate").description("copier-update every consumer of the presets to the current train, and pin their ci-cd workflow refs").argument("[dir]", "the workspace: plexus-ms/ and the consumers sit under it", ".").option("--train <version>", "the train to propagate (default: the current one)").action(async (dir, opts, command) => {
13748
+ const ctx = contextOf2(command);
13749
+ const result = await ship(ctx, { workspace: resolve5(dir), train: opts.train, propagateOnly: true });
13750
+ ctx.result(result, (r) => renderSummary(r, `plx -y propagate --train ${r.train} ${dir}`));
13751
+ if (!isClean(result)) process.exitCode = 1;
13752
+ });
13753
+ }
13754
+
13755
+ // src/commands/requirements.ts
13756
+ import { join as join9, resolve as resolve6 } from "node:path";
13757
+ function register6(program2) {
13758
+ program2.command("requirements").description("lint the standard's map and module pages, or extract one module's requirement lines").argument("[dir]", "a checkout of the compendium", ".").option("--extract <page>", "print a module page's requirement lines instead of linting (path relative to dir)").action(async (dir, opts, command) => {
13759
+ const ctx = contextOf2(command);
13760
+ const compendium = resolve6(dir);
13761
+ if (opts.extract) {
13762
+ ctx.result(extractRequirements(await ctx.readFile(join9(compendium, opts.extract))));
13763
+ return;
13764
+ }
13765
+ const check = await checkCompendium(ctx, compendium);
13766
+ ctx.result(check, renderCheck);
13767
+ if (check.defects.length > 0) process.exitCode = 1;
13768
+ });
13769
+ }
13770
+ function renderCheck(c) {
13771
+ if (c.defects.length > 0) return c.defects.join("\n");
13772
+ return `\u2713 the map, ${c.contracts} contracts and ${c.approaches} approaches are well-formed`;
13773
+ }
13774
+
12922
13775
  // src/commands/index.ts
12923
- var commands = [register2, register];
13776
+ var commands = [register3, register2, register4, register5, register6, register];
12924
13777
 
12925
13778
  // src/program.ts
12926
13779
  var { version, description } = createRequire(import.meta.url)("../package.json");
@@ -12929,7 +13782,7 @@ function buildProgram() {
12929
13782
  program2.addOption(new Option("-n, --dry-run", "print every effect this run would have, perform none").env("PLX_DRY_RUN")).addOption(
12930
13783
  new Option("-v, --verbose", "say more: once for reads and inputs, twice for command output").argParser((_value, previous) => previous + 1).default(0)
12931
13784
  ).addOption(new Option("-q, --quiet", "say nothing but results and errors").env("PLX_QUIET")).addOption(new Option("-y, --yes", "answer every confirmation with yes (needed off a terminal)").env("PLX_YES")).addOption(new Option("--json", "print results as JSON").env("PLX_JSON"));
12932
- for (const register3 of commands) register3(program2);
13785
+ for (const register7 of commands) register7(program2);
12933
13786
  return program2;
12934
13787
  }
12935
13788
  function contextOf2(command) {
@@ -12947,5 +13800,5 @@ try {
12947
13800
  const message = error instanceof Error ? error.message : String(error);
12948
13801
  process.stderr.write(`\u2717 ${message}
12949
13802
  `);
12950
- process.exitCode = 1;
13803
+ process.exitCode = error instanceof UsageError ? 2 : 1;
12951
13804
  }