@plexus-ms/cli 0.2.0 → 0.3.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 +2662 -1960
  2. package/package.json +3 -3
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":
@@ -7533,1928 +7368,2735 @@ 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) {
7712
- withPointer((pointer) => {
7713
- const oldDeps = pointer.get();
7714
- const hasChanged = !Array.isArray(oldDeps) || depArray.some((dep, i) => !Object.is(dep, oldDeps[i]));
7715
- if (hasChanged) {
7716
- effectScheduler.queue(cb);
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);
7717
7653
  }
7718
- pointer.set(depArray);
7719
- });
7654
+ }
7655
+ return catalog;
7720
7656
  }
7721
7657
 
7722
- // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.1.2/node_modules/@inquirer/core/dist/lib/theme.js
7723
- import { styleText } from "node:util";
7658
+ // ../lib/dist/consumers.js
7659
+ import { relative } from "node:path";
7660
+ function expectedBranch(declaration) {
7661
+ if (!declaration)
7662
+ return void 0;
7663
+ if (declaration.modules.includes("PLX-Platform"))
7664
+ return "main";
7665
+ if (declaration.modules.includes("PLX-Repo"))
7666
+ return "develop";
7667
+ return void 0;
7668
+ }
7669
+ var presetSource = (preset) => `gh:plexus-ms/${preset}`;
7670
+ async function findConsumers(ctx, root, presets) {
7671
+ const sources = new Map(presets.map((p) => [presetSource(p), p]));
7672
+ const consumers = /* @__PURE__ */ new Map();
7673
+ const orphans = [];
7674
+ const visit = (dir, repo, inTemplate) => {
7675
+ const here = dir.git ? dir : repo;
7676
+ const template = inTemplate || Boolean(dir.template);
7677
+ const preset = dir.copier?.src ? sources.get(dir.copier.src) : void 0;
7678
+ if (preset && !template) {
7679
+ const site = { path: dir.path, rel: relative(root.path, dir.path) || ".", preset };
7680
+ if (!here)
7681
+ orphans.push(site);
7682
+ else {
7683
+ let consumer = consumers.get(here.path);
7684
+ if (!consumer) {
7685
+ consumer = {
7686
+ path: here.path,
7687
+ rel: relative(root.path, here.path) || ".",
7688
+ branch: here.git?.branch ?? "?",
7689
+ expected: expectedBranch(here.declaration),
7690
+ sites: []
7691
+ };
7692
+ consumers.set(here.path, consumer);
7693
+ }
7694
+ consumer.sites.push(site);
7695
+ }
7696
+ }
7697
+ for (const child of dir.children)
7698
+ visit(child, here, template);
7699
+ };
7700
+ visit(root, void 0, false);
7701
+ for (const site of orphans)
7702
+ ctx.say(`\u26A0 ${site.rel}: not inside a git repo \u2014 skipped`);
7703
+ for (const c of consumers.values()) {
7704
+ if (c.expected && c.branch !== c.expected) {
7705
+ c.skipped = `on '${c.branch}', expected '${c.expected}'`;
7706
+ continue;
7707
+ }
7708
+ const tracked = (await ctx.read("git", ["status", "--porcelain", "--untracked-files=no"], { cwd: c.path })).trim();
7709
+ if (tracked !== "")
7710
+ c.skipped = "has uncommitted changes";
7711
+ }
7712
+ return [...consumers.values()];
7713
+ }
7724
7714
 
7725
- // ../../node_modules/.pnpm/@inquirer+figures@2.0.9/node_modules/@inquirer/figures/dist/index.js
7726
- import process2 from "node:process";
7727
- function isUnicodeSupported() {
7728
- if (!process2.platform.startsWith("win")) {
7729
- return process2.env["TERM"] !== "linux";
7715
+ // ../lib/dist/io.js
7716
+ import { spawn } from "node:child_process";
7717
+ import { readdir, readFile, writeFile } from "node:fs/promises";
7718
+ var ExecError = class extends Error {
7719
+ command;
7720
+ code;
7721
+ stderr;
7722
+ constructor(command, code, stderr) {
7723
+ super(`${command} exited with ${code ?? "signal"}${stderr ? `
7724
+ ${stderr.trimEnd()}` : ""}`);
7725
+ this.command = command;
7726
+ this.code = code;
7727
+ this.stderr = stderr;
7730
7728
  }
7731
- return Boolean(process2.env["CI"]) || // CI environments generally support unicode
7732
- Boolean(process2.env["WT_SESSION"]) || // Windows Terminal
7733
- Boolean(process2.env["TERMINUS_SUBLIME"]) || // Terminus (<0.2.27)
7734
- process2.env["ConEmuTask"] === "{cmd::Cmder}" || // ConEmu and cmder
7735
- process2.env["TERM_PROGRAM"] === "Terminus-Sublime" || process2.env["TERM_PROGRAM"] === "vscode" || process2.env["TERM"] === "xterm-256color" || process2.env["TERM"] === "alacritty" || process2.env["TERMINAL_EMULATOR"] === "JetBrains-JediTerm";
7729
+ };
7730
+ var isInteractive = () => process.stdin.isTTY === true && process.stderr.isTTY === true;
7731
+ function realIo(prompt) {
7732
+ return {
7733
+ stdout: process.stdout,
7734
+ stderr: process.stderr,
7735
+ prompt: prompt && isInteractive() ? prompt : void 0,
7736
+ exec: (command, args, options = {}) => new Promise((resolve6, reject) => {
7737
+ const child = spawn(command, args, {
7738
+ cwd: options.cwd,
7739
+ env: options.env,
7740
+ stdio: [
7741
+ options.input !== void 0 ? "pipe" : options.inherit ? "inherit" : "ignore",
7742
+ options.inherit ? "inherit" : "pipe",
7743
+ "pipe"
7744
+ ]
7745
+ });
7746
+ let stdout = "";
7747
+ let stderr = "";
7748
+ child.stdout?.on("data", (chunk) => {
7749
+ stdout += chunk;
7750
+ });
7751
+ child.stderr?.on("data", (chunk) => {
7752
+ stderr += chunk;
7753
+ if (options.inherit)
7754
+ process.stderr.write(chunk);
7755
+ });
7756
+ child.on("error", reject);
7757
+ child.on("close", (code) => {
7758
+ if (code === 0)
7759
+ resolve6(stdout);
7760
+ else
7761
+ reject(new ExecError(render(command, args), code, stderr));
7762
+ });
7763
+ if (options.input !== void 0)
7764
+ child.stdin?.end(options.input);
7765
+ }),
7766
+ readFile: (path3) => readFile(path3, "utf8"),
7767
+ writeFile: (path3, content) => writeFile(path3, content),
7768
+ readDir: async (path3) => (await readdir(path3, { withFileTypes: true })).map((e) => ({ name: e.name, directory: e.isDirectory() }))
7769
+ };
7736
7770
  }
7737
- var common = {
7738
- circleQuestionMark: "(?)",
7739
- questionMarkPrefix: "(?)",
7740
- square: "\u2588",
7741
- squareDarkShade: "\u2593",
7742
- squareMediumShade: "\u2592",
7743
- squareLightShade: "\u2591",
7744
- squareTop: "\u2580",
7745
- squareBottom: "\u2584",
7746
- squareLeft: "\u258C",
7747
- squareRight: "\u2590",
7748
- squareCenter: "\u25A0",
7749
- bullet: "\u25CF",
7750
- dot: "\u2024",
7751
- ellipsis: "\u2026",
7752
- pointerSmall: "\u203A",
7753
- triangleUp: "\u25B2",
7754
- triangleUpSmall: "\u25B4",
7755
- triangleDown: "\u25BC",
7756
- triangleDownSmall: "\u25BE",
7757
- triangleLeftSmall: "\u25C2",
7758
- triangleRightSmall: "\u25B8",
7759
- home: "\u2302",
7760
- heart: "\u2665",
7761
- musicNote: "\u266A",
7762
- musicNoteBeamed: "\u266B",
7763
- arrowUp: "\u2191",
7764
- arrowDown: "\u2193",
7765
- arrowLeft: "\u2190",
7766
- arrowRight: "\u2192",
7767
- arrowLeftRight: "\u2194",
7768
- arrowUpDown: "\u2195",
7769
- almostEqual: "\u2248",
7770
- notEqual: "\u2260",
7771
- lessOrEqual: "\u2264",
7772
- greaterOrEqual: "\u2265",
7773
- identical: "\u2261",
7774
- infinity: "\u221E",
7775
- subscriptZero: "\u2080",
7776
- subscriptOne: "\u2081",
7777
- subscriptTwo: "\u2082",
7778
- subscriptThree: "\u2083",
7779
- subscriptFour: "\u2084",
7780
- subscriptFive: "\u2085",
7781
- subscriptSix: "\u2086",
7782
- subscriptSeven: "\u2087",
7783
- subscriptEight: "\u2088",
7784
- subscriptNine: "\u2089",
7785
- oneHalf: "\xBD",
7786
- oneThird: "\u2153",
7787
- oneQuarter: "\xBC",
7788
- oneFifth: "\u2155",
7789
- oneSixth: "\u2159",
7790
- oneEighth: "\u215B",
7791
- twoThirds: "\u2154",
7792
- twoFifths: "\u2156",
7793
- threeQuarters: "\xBE",
7794
- threeFifths: "\u2157",
7795
- threeEighths: "\u215C",
7796
- fourFifths: "\u2158",
7797
- fiveSixths: "\u215A",
7798
- fiveEighths: "\u215D",
7799
- sevenEighths: "\u215E",
7800
- line: "\u2500",
7801
- lineBold: "\u2501",
7802
- lineDouble: "\u2550",
7803
- lineDashed0: "\u2504",
7804
- lineDashed1: "\u2505",
7805
- lineDashed2: "\u2508",
7806
- lineDashed3: "\u2509",
7807
- lineDashed4: "\u254C",
7808
- lineDashed5: "\u254D",
7809
- lineDashed6: "\u2574",
7810
- lineDashed7: "\u2576",
7811
- lineDashed8: "\u2578",
7812
- lineDashed9: "\u257A",
7813
- lineDashed10: "\u257C",
7814
- lineDashed11: "\u257E",
7815
- lineDashed12: "\u2212",
7816
- lineDashed13: "\u2013",
7817
- lineDashed14: "\u2010",
7818
- lineDashed15: "\u2043",
7819
- lineVertical: "\u2502",
7820
- lineVerticalBold: "\u2503",
7821
- lineVerticalDouble: "\u2551",
7822
- lineVerticalDashed0: "\u2506",
7823
- lineVerticalDashed1: "\u2507",
7824
- lineVerticalDashed2: "\u250A",
7825
- lineVerticalDashed3: "\u250B",
7826
- lineVerticalDashed4: "\u254E",
7827
- lineVerticalDashed5: "\u254F",
7828
- lineVerticalDashed6: "\u2575",
7829
- lineVerticalDashed7: "\u2577",
7830
- lineVerticalDashed8: "\u2579",
7831
- lineVerticalDashed9: "\u257B",
7832
- lineVerticalDashed10: "\u257D",
7833
- lineVerticalDashed11: "\u257F",
7834
- lineDownLeft: "\u2510",
7835
- lineDownLeftArc: "\u256E",
7836
- lineDownBoldLeftBold: "\u2513",
7837
- lineDownBoldLeft: "\u2512",
7838
- lineDownLeftBold: "\u2511",
7839
- lineDownDoubleLeftDouble: "\u2557",
7840
- lineDownDoubleLeft: "\u2556",
7841
- lineDownLeftDouble: "\u2555",
7842
- lineDownRight: "\u250C",
7843
- lineDownRightArc: "\u256D",
7844
- lineDownBoldRightBold: "\u250F",
7845
- lineDownBoldRight: "\u250E",
7846
- lineDownRightBold: "\u250D",
7847
- lineDownDoubleRightDouble: "\u2554",
7848
- lineDownDoubleRight: "\u2553",
7849
- lineDownRightDouble: "\u2552",
7850
- lineUpLeft: "\u2518",
7851
- lineUpLeftArc: "\u256F",
7852
- lineUpBoldLeftBold: "\u251B",
7853
- lineUpBoldLeft: "\u251A",
7854
- lineUpLeftBold: "\u2519",
7855
- lineUpDoubleLeftDouble: "\u255D",
7856
- lineUpDoubleLeft: "\u255C",
7857
- lineUpLeftDouble: "\u255B",
7858
- lineUpRight: "\u2514",
7859
- lineUpRightArc: "\u2570",
7860
- lineUpBoldRightBold: "\u2517",
7861
- lineUpBoldRight: "\u2516",
7862
- lineUpRightBold: "\u2515",
7863
- lineUpDoubleRightDouble: "\u255A",
7864
- lineUpDoubleRight: "\u2559",
7865
- lineUpRightDouble: "\u2558",
7866
- lineUpDownLeft: "\u2524",
7867
- lineUpBoldDownBoldLeftBold: "\u252B",
7868
- lineUpBoldDownBoldLeft: "\u2528",
7869
- lineUpDownLeftBold: "\u2525",
7870
- lineUpBoldDownLeftBold: "\u2529",
7871
- lineUpDownBoldLeftBold: "\u252A",
7872
- lineUpDownBoldLeft: "\u2527",
7873
- lineUpBoldDownLeft: "\u2526",
7874
- lineUpDoubleDownDoubleLeftDouble: "\u2563",
7875
- lineUpDoubleDownDoubleLeft: "\u2562",
7876
- lineUpDownLeftDouble: "\u2561",
7877
- lineUpDownRight: "\u251C",
7878
- lineUpBoldDownBoldRightBold: "\u2523",
7879
- lineUpBoldDownBoldRight: "\u2520",
7880
- lineUpDownRightBold: "\u251D",
7881
- lineUpBoldDownRightBold: "\u2521",
7882
- lineUpDownBoldRightBold: "\u2522",
7883
- lineUpDownBoldRight: "\u251F",
7884
- lineUpBoldDownRight: "\u251E",
7885
- lineUpDoubleDownDoubleRightDouble: "\u2560",
7886
- lineUpDoubleDownDoubleRight: "\u255F",
7887
- lineUpDownRightDouble: "\u255E",
7888
- lineDownLeftRight: "\u252C",
7889
- lineDownBoldLeftBoldRightBold: "\u2533",
7890
- lineDownLeftBoldRightBold: "\u252F",
7891
- lineDownBoldLeftRight: "\u2530",
7892
- lineDownBoldLeftBoldRight: "\u2531",
7893
- lineDownBoldLeftRightBold: "\u2532",
7894
- lineDownLeftRightBold: "\u252E",
7895
- lineDownLeftBoldRight: "\u252D",
7896
- lineDownDoubleLeftDoubleRightDouble: "\u2566",
7897
- lineDownDoubleLeftRight: "\u2565",
7898
- lineDownLeftDoubleRightDouble: "\u2564",
7899
- lineUpLeftRight: "\u2534",
7900
- lineUpBoldLeftBoldRightBold: "\u253B",
7901
- lineUpLeftBoldRightBold: "\u2537",
7902
- lineUpBoldLeftRight: "\u2538",
7903
- lineUpBoldLeftBoldRight: "\u2539",
7904
- lineUpBoldLeftRightBold: "\u253A",
7905
- lineUpLeftRightBold: "\u2536",
7906
- lineUpLeftBoldRight: "\u2535",
7907
- lineUpDoubleLeftDoubleRightDouble: "\u2569",
7908
- lineUpDoubleLeftRight: "\u2568",
7909
- lineUpLeftDoubleRightDouble: "\u2567",
7910
- lineUpDownLeftRight: "\u253C",
7911
- lineUpBoldDownBoldLeftBoldRightBold: "\u254B",
7912
- lineUpDownBoldLeftBoldRightBold: "\u2548",
7913
- lineUpBoldDownLeftBoldRightBold: "\u2547",
7914
- lineUpBoldDownBoldLeftRightBold: "\u254A",
7915
- lineUpBoldDownBoldLeftBoldRight: "\u2549",
7916
- lineUpBoldDownLeftRight: "\u2540",
7917
- lineUpDownBoldLeftRight: "\u2541",
7918
- lineUpDownLeftBoldRight: "\u253D",
7919
- lineUpDownLeftRightBold: "\u253E",
7920
- lineUpBoldDownBoldLeftRight: "\u2542",
7921
- lineUpDownLeftBoldRightBold: "\u253F",
7922
- lineUpBoldDownLeftBoldRight: "\u2543",
7923
- lineUpBoldDownLeftRightBold: "\u2544",
7924
- lineUpDownBoldLeftBoldRight: "\u2545",
7925
- lineUpDownBoldLeftRightBold: "\u2546",
7926
- lineUpDoubleDownDoubleLeftDoubleRightDouble: "\u256C",
7927
- lineUpDoubleDownDoubleLeftRight: "\u256B",
7928
- lineUpDownLeftDoubleRightDouble: "\u256A",
7929
- lineCross: "\u2573",
7930
- lineBackslash: "\u2572",
7931
- lineSlash: "\u2571"
7932
- };
7933
- var specialMainSymbols = {
7934
- tick: "\u2714",
7935
- info: "\u2139",
7936
- warning: "\u26A0",
7937
- cross: "\u2718",
7938
- squareSmall: "\u25FB",
7939
- squareSmallFilled: "\u25FC",
7940
- circle: "\u25EF",
7941
- circleFilled: "\u25C9",
7942
- circleDotted: "\u25CC",
7943
- circleDouble: "\u25CE",
7944
- circleCircle: "\u24DE",
7945
- circleCross: "\u24E7",
7946
- circlePipe: "\u24BE",
7947
- radioOn: "\u25C9",
7948
- radioOff: "\u25EF",
7949
- checkboxOn: "\u2612",
7950
- checkboxOff: "\u2610",
7951
- checkboxCircleOn: "\u24E7",
7952
- checkboxCircleOff: "\u24BE",
7953
- pointer: "\u276F",
7954
- triangleUpOutline: "\u25B3",
7955
- triangleLeft: "\u25C0",
7956
- triangleRight: "\u25B6",
7957
- lozenge: "\u25C6",
7958
- lozengeOutline: "\u25C7",
7959
- hamburger: "\u2630",
7960
- smiley: "\u32E1",
7961
- mustache: "\u0DF4",
7962
- star: "\u2605",
7963
- play: "\u25B6",
7964
- nodejs: "\u2B22",
7965
- oneSeventh: "\u2150",
7966
- oneNinth: "\u2151",
7967
- oneTenth: "\u2152"
7968
- };
7969
- var specialFallbackSymbols = {
7970
- tick: "\u221A",
7971
- info: "i",
7972
- warning: "\u203C",
7973
- cross: "\xD7",
7974
- squareSmall: "\u25A1",
7975
- squareSmallFilled: "\u25A0",
7976
- circle: "( )",
7977
- circleFilled: "(*)",
7978
- circleDotted: "( )",
7979
- circleDouble: "( )",
7980
- circleCircle: "(\u25CB)",
7981
- circleCross: "(\xD7)",
7982
- circlePipe: "(\u2502)",
7983
- radioOn: "(*)",
7984
- radioOff: "( )",
7985
- checkboxOn: "[\xD7]",
7986
- checkboxOff: "[ ]",
7987
- checkboxCircleOn: "(\xD7)",
7988
- checkboxCircleOff: "( )",
7989
- pointer: ">",
7990
- 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
- };
7771
+ function render(command, args) {
7772
+ return [command, ...args].map(quote).join(" ");
7773
+ }
7774
+ function quote(arg) {
7775
+ return /^[\w./:@%+=,-]+$/.test(arg) ? arg : `'${arg.replaceAll("'", "'\\''")}'`;
8044
7776
  }
8045
7777
 
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);
7778
+ // ../lib/dist/plan.js
7779
+ var run = (command, args = [], options = {}) => ({
7780
+ kind: "run",
7781
+ command,
7782
+ args,
7783
+ ...options
7784
+ });
7785
+ var write = (path3, content) => ({ kind: "write", path: path3, content });
7786
+ function describe(step) {
7787
+ switch (step.kind) {
7788
+ case "run":
7789
+ return `$ ${step.cwd ? `(cd ${step.cwd} && ` : ""}${render(step.command, step.args)}${step.cwd ? ")" : ""}`;
7790
+ case "ssh":
7791
+ return `$ ${render("ssh", [step.host, "bash", "-s"])} <<'EOF'`;
7792
+ case "write":
7793
+ return `> ${step.path} (${Buffer.byteLength(step.content)} bytes)`;
8053
7794
  }
8054
- return Object.getPrototypeOf(value) === proto;
8055
7795
  }
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
- }
7796
+ function body(step) {
7797
+ switch (step.kind) {
7798
+ case "run":
7799
+ return step.input;
7800
+ case "ssh":
7801
+ return `${step.script.trimEnd()}
7802
+ EOF`;
7803
+ case "write":
7804
+ return step.content;
8063
7805
  }
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
7806
  }
8073
7807
 
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];
7808
+ // ../lib/dist/context.js
7809
+ var Context = class {
7810
+ dryRun;
7811
+ verbose;
7812
+ quiet;
7813
+ yes;
7814
+ json;
7815
+ io;
7816
+ constructor(options, io = realIo()) {
7817
+ this.io = io;
7818
+ this.dryRun = options.dryRun ?? false;
7819
+ this.quiet = options.quiet ?? false;
7820
+ this.verbose = this.quiet ? -1 : options.verbose ?? 0;
7821
+ this.yes = options.yes ?? false;
7822
+ this.json = options.json ?? false;
8100
7823
  }
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;
7824
+ // --- narration (stderr) ---------------------------------------------------
7825
+ /** One line, if the verbosity allows the level (0 normal, 1 verbose, 2 debug). */
7826
+ say(line, level = 0) {
7827
+ if (this.verbose >= level)
7828
+ this.io.stderr.write(`${line}
7829
+ `);
7830
+ }
7831
+ /** A final outcome line, `✓ ...` or `✗ ...`; shown even under --quiet. */
7832
+ done(line, ok = true) {
7833
+ this.io.stderr.write(`${ok ? "\u2713" : "\u2717"} ${line}
7834
+ `);
7835
+ }
7836
+ // --- results (stdout) -----------------------------------------------------
7837
+ /**
7838
+ * The command's product. `data` is what --json prints; `human` renders it
7839
+ * otherwise (default: strings as they are, arrays one item per line).
7840
+ */
7841
+ result(data, human = renderHuman) {
7842
+ const text = this.json ? JSON.stringify(data, null, 2) : human(data);
7843
+ this.io.stdout.write(text.endsWith("\n") ? text : `${text}
7844
+ `);
7845
+ }
7846
+ // --- reads: always performed ---------------------------------------------
7847
+ /** Run a command for its output. Changes nothing; narrated only when verbose. */
7848
+ read(command, args = [], options = {}) {
7849
+ this.say(`? ${describe({ kind: "run", command, args, ...options })}`, 1);
7850
+ return this.io.exec(command, args, options);
7851
+ }
7852
+ readFile(path3) {
7853
+ this.say(`? read ${path3}`, 1);
7854
+ return this.io.readFile(path3);
7855
+ }
7856
+ readDir(path3) {
7857
+ this.say(`? list ${path3}`, 2);
7858
+ return this.io.readDir(path3);
7859
+ }
7860
+ // --- effects: narrated always, performed unless --dry-run -----------------
7861
+ /**
7862
+ * Ask before applying. `--yes` and `--dry-run` answer yes; off a terminal
7863
+ * without `--yes` the answer is an error, never a hang.
7864
+ */
7865
+ async confirm(question) {
7866
+ if (this.yes || this.dryRun) {
7867
+ this.say(`? ${question} yes (${this.yes ? "--yes" : "--dry-run"})`, 1);
7868
+ return true;
8214
7869
  }
8215
- if (index >= length) {
8216
- break outer;
7870
+ if (!this.io.prompt)
7871
+ throw new Error(`cannot ask "${question}" without a terminal; pass --yes`);
7872
+ return this.io.prompt(question);
7873
+ }
7874
+ /** Narrate and perform each step in order; the first failure stops the run. */
7875
+ async apply(plan) {
7876
+ for (const step of plan) {
7877
+ this.say(`${this.dryRun ? "[dry-run] " : ""}${describe(step)}`);
7878
+ const input = body(step);
7879
+ if (input !== void 0)
7880
+ this.say(indent(input), step.kind === "write" ? 2 : 1);
7881
+ if (!this.dryRun)
7882
+ await this.perform(step);
8217
7883
  }
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
- }
7884
+ }
7885
+ /**
7886
+ * Perform a step on scratch state, whatever the mode: the one exception to
7887
+ * "a dry run performs no effect", for a preview that has to run a tool
7888
+ * against a throwaway copy to be honest. Resolves with the output of a run.
7889
+ */
7890
+ stage(step) {
7891
+ this.say(`? ${describe(step)}`, 1);
7892
+ const input = body(step);
7893
+ if (input !== void 0)
7894
+ this.say(indent(input), 2);
7895
+ return this.perform(step);
7896
+ }
7897
+ async perform(step) {
7898
+ const inherit = this.verbose >= 2 || step.kind === "run" && step.interactive === true;
7899
+ switch (step.kind) {
7900
+ case "run":
7901
+ return this.io.exec(step.command, step.args, { cwd: step.cwd, input: step.input, inherit });
7902
+ case "ssh":
7903
+ return this.io.exec("ssh", [step.host, "bash", "-s"], { input: step.script, inherit });
7904
+ case "write":
7905
+ await this.io.writeFile(step.path, step.content);
7906
+ return void 0;
8237
7907
  }
8238
- index += 1;
8239
7908
  }
8240
- return {
8241
- width: truncationEnabled ? truncationLimit : width,
8242
- index: truncationEnabled ? truncationIndex : length,
8243
- truncated: truncationEnabled,
8244
- ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
8245
- };
8246
7909
  };
8247
- var dist_default2 = getStringTruncatedWidth;
7910
+ function renderHuman(data) {
7911
+ if (typeof data === "string")
7912
+ return data;
7913
+ if (Array.isArray(data))
7914
+ return data.map(String).join("\n");
7915
+ return JSON.stringify(data, null, 2);
7916
+ }
7917
+ function indent(text) {
7918
+ return text.trimEnd().split("\n").map((l) => ` ${l}`).join("\n");
7919
+ }
8248
7920
 
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
8254
- };
8255
- var fastStringWidth = (input, options = {}) => {
8256
- return dist_default2(input, NO_TRUNCATION2, options).width;
8257
- };
8258
- var dist_default3 = fastStringWidth;
7921
+ // ../lib/dist/copier.js
7922
+ var import_yaml2 = __toESM(require_dist(), 1);
7923
+ var ANSWERS_FILE = ".copier-answers.yml";
7924
+ var TEMPLATE_FILES = ["copier.yml", "copier.yaml"];
7925
+ function parseAnswers(text) {
7926
+ const data = (0, import_yaml2.parse)(text);
7927
+ if (data === null || typeof data !== "object" || Array.isArray(data))
7928
+ throw new Error("answers file is not a mapping");
7929
+ const { _commit, _src_path, ...answers } = data;
7930
+ return {
7931
+ commit: _commit === void 0 ? void 0 : String(_commit),
7932
+ src: _src_path === void 0 ? void 0 : String(_src_path),
7933
+ answers
7934
+ };
7935
+ }
8259
7936
 
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
- }
7937
+ // ../lib/dist/doctor.js
7938
+ import { relative as relative2 } from "node:path";
7939
+ function diagnose(root, catalog) {
7940
+ const units = collect(root, []);
7941
+ const declarations = units.map((u) => diagnoseUnit(u, units, catalog, root.path));
7942
+ return { declarations, stale: declarations.filter((d) => d.findings.length > 0).length };
7943
+ }
7944
+ function collect(dir, ancestors, parent) {
7945
+ const here = dir.declaration || dir.problems?.some((p) => p.startsWith("PLEXUS.md")) ? [{ dir, ancestors, parent }] : [];
7946
+ const below = dir.declaration ? [...ancestors, dir] : ancestors;
7947
+ return [...here, ...dir.children.flatMap((c) => collect(c, below, dir))];
7948
+ }
7949
+ function diagnoseUnit(unit, units, catalog, root) {
7950
+ const { dir } = unit;
7951
+ const path3 = relative2(root, dir.path) || ".";
7952
+ const problem = dir.problems?.find((p) => p.startsWith("PLEXUS.md"));
7953
+ if (!dir.declaration)
7954
+ return { path: path3, modules: [], findings: [problem?.replace(/^PLEXUS\.md: /, "") ?? "unreadable marker"] };
7955
+ const { plexus, modules } = dir.declaration;
7956
+ const context = new Set(contextOf(unit, units).flatMap((d) => d.declaration?.modules ?? []));
7957
+ const findings = [];
7958
+ for (const code of modules) {
7959
+ const module = catalog.get(code);
7960
+ if (!module) {
7961
+ findings.push(`declares ${code}, which no module carries`);
7962
+ continue;
8334
7963
  }
8335
- currentCharacter = nextCharacter;
8336
- nextCharacter = characters.next();
8337
- rawCharacterIndex += character.length;
7964
+ if (module.changed && compareTrains(module.changed, plexus) > 0)
7965
+ findings.push(`${code} changed in ${module.changed}, declared at ${plexus}`);
7966
+ for (const dep of module.depends)
7967
+ if (!modules.includes(dep) && !context.has(dep))
7968
+ findings.push(`${code} depends on ${dep}, declared neither here nor by an enclosing or contained declaration`);
8338
7969
  }
8339
- lastRow = rows.at(-1);
8340
- if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
8341
- rows[rows.length - 2] += rows.pop();
7970
+ return { path: path3, plexus, modules, findings };
7971
+ }
7972
+ function contextOf(unit, units) {
7973
+ const { dir, ancestors } = unit;
7974
+ const context = [...ancestors, ...descendants(dir)];
7975
+ const repo = ancestors[0] ?? dir;
7976
+ const repoParent = units.find((u) => u.dir === repo)?.parent;
7977
+ const siblings = repoParent?.children.filter((c) => c !== repo && c.declaration) ?? [];
7978
+ const isTenancy = (d) => d.declaration?.modules.includes("PLX-Tenancy") ?? false;
7979
+ context.push(...siblings.filter(isTenancy));
7980
+ if (isTenancy(dir))
7981
+ context.push(...siblings);
7982
+ return context;
7983
+ }
7984
+ function descendants(dir) {
7985
+ return dir.children.flatMap((c) => [...c.declaration ? [c] : [], ...descendants(c)]);
7986
+ }
7987
+ function compareTrains(a, b) {
7988
+ const nums = (v) => v.split(".").slice(0, 3).map((p) => Number.parseInt(p, 10) || 0);
7989
+ const [x, y] = [nums(a), nums(b)];
7990
+ for (let i = 0; i < 3; i++)
7991
+ if ((x[i] ?? 0) !== (y[i] ?? 0))
7992
+ return (x[i] ?? 0) > (y[i] ?? 0) ? 1 : -1;
7993
+ return 0;
7994
+ }
7995
+
7996
+ // ../lib/dist/model.js
7997
+ function kindOf(declaration) {
7998
+ const has = (code) => declaration.modules.includes(code);
7999
+ if (has("PLX-App"))
8000
+ return "app";
8001
+ if (has("PLX-Platform"))
8002
+ return "platform";
8003
+ if (has("PLX-Repo"))
8004
+ return "repo";
8005
+ return void 0;
8006
+ }
8007
+ function shortRemote(url) {
8008
+ const bare = url.replace(/\.git$/, "").replace(/\/$/, "");
8009
+ const m = /^(?:git@github\.com:|github\.com:|ssh:\/\/git@github\.com\/|https?:\/\/github\.com\/)(.+)$/.exec(bare);
8010
+ return m ? `gh:${m[1]}` : bare;
8011
+ }
8012
+ function isNotable(dir) {
8013
+ return Boolean(dir.git || dir.template || dir.copier || dir.declaration || dir.problems?.length);
8014
+ }
8015
+
8016
+ // ../lib/dist/overview.js
8017
+ import { join as join2 } from "node:path";
8018
+ var PRUNED = /* @__PURE__ */ new Set([
8019
+ "node_modules",
8020
+ ".hg",
8021
+ ".svn",
8022
+ ".next",
8023
+ ".nuxt",
8024
+ ".turbo",
8025
+ ".svelte-kit",
8026
+ "dist",
8027
+ "build",
8028
+ "out",
8029
+ ".output",
8030
+ ".venv",
8031
+ "venv",
8032
+ "__pycache__",
8033
+ "target",
8034
+ ".cache",
8035
+ ".pnpm-store",
8036
+ "coverage",
8037
+ "vendor",
8038
+ ".terraform",
8039
+ ".gradle"
8040
+ ]);
8041
+ function overview(ctx, root, options = {}) {
8042
+ return walk(ctx, root, root.replace(/\/+$/, "").split("/").pop() || root, { git: true, ...options });
8043
+ }
8044
+ async function walk(ctx, path3, name, options) {
8045
+ const entries = await ctx.readDir(path3);
8046
+ const files = new Set(entries.filter((e) => !e.directory).map((e) => e.name));
8047
+ const names = new Set(entries.map((e) => e.name));
8048
+ const dir = { name, path: path3, children: [] };
8049
+ if (names.has(".git") && options.git)
8050
+ dir.git = await gitFacet(ctx, path3);
8051
+ if (TEMPLATE_FILES.some((f) => files.has(f)))
8052
+ dir.template = options.git ? await templateFacet(ctx, path3) : {};
8053
+ if (files.has(ANSWERS_FILE)) {
8054
+ await facet(ctx, dir, ANSWERS_FILE, (text) => {
8055
+ dir.copier = parseAnswers(text);
8056
+ });
8342
8057
  }
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])) {
8058
+ if (files.has(MARKER_FILE)) {
8059
+ await facet(ctx, dir, MARKER_FILE, (text) => {
8060
+ dir.declaration = parseMarker(text);
8061
+ });
8062
+ }
8063
+ const subdirs = entries.filter((e) => e.directory && e.name !== ".git" && !PRUNED.has(e.name)).map((e) => e.name).sort();
8064
+ for (const sub of subdirs) {
8065
+ const child = await walk(ctx, join2(path3, sub), sub, options);
8066
+ if (isNotable(child) || child.children.length > 0)
8067
+ dir.children.push(child);
8068
+ }
8069
+ return dir;
8070
+ }
8071
+ async function facet(ctx, dir, file, read) {
8072
+ try {
8073
+ read(await ctx.readFile(join2(dir.path, file)));
8074
+ } catch (error) {
8075
+ dir.problems ??= [];
8076
+ dir.problems.push(`${file}: ${error instanceof Error ? error.message : String(error)}`);
8077
+ }
8078
+ }
8079
+ async function git(ctx, cwd, args) {
8080
+ try {
8081
+ const out = (await ctx.read("git", args, { cwd })).trim();
8082
+ return out === "" ? void 0 : out;
8083
+ } catch {
8084
+ return void 0;
8085
+ }
8086
+ }
8087
+ async function gitFacet(ctx, cwd) {
8088
+ const branch = await git(ctx, cwd, ["symbolic-ref", "--short", "-q", "HEAD"]) ?? await git(ctx, cwd, ["rev-parse", "--short", "HEAD"]) ?? "?";
8089
+ const dirty = await git(ctx, cwd, ["status", "--porcelain"]) !== void 0;
8090
+ const remote = await git(ctx, cwd, ["remote", "get-url", "origin"]);
8091
+ let defaultRef = await git(ctx, cwd, ["symbolic-ref", "--short", "-q", "refs/remotes/origin/HEAD"]);
8092
+ for (const b of ["main", "master"]) {
8093
+ if (defaultRef)
8349
8094
  break;
8350
- }
8351
- last--;
8095
+ if (await git(ctx, cwd, ["rev-parse", "--verify", "-q", `refs/heads/${b}`]))
8096
+ defaultRef = b;
8352
8097
  }
8353
- if (last === words.length) {
8354
- return string;
8098
+ const tag = defaultRef ? await git(ctx, cwd, ["describe", "--tags", "--abbrev=0", defaultRef]) : void 0;
8099
+ const facet2 = { branch, dirty };
8100
+ if (tag)
8101
+ facet2.tag = tag;
8102
+ if (remote)
8103
+ facet2.remote = shortRemote(remote);
8104
+ return facet2;
8105
+ }
8106
+ async function templateFacet(ctx, cwd) {
8107
+ const tag = await git(ctx, cwd, ["describe", "--tags", "--abbrev=0"]) ?? (await git(ctx, cwd, ["tag", "--list", "--sort=-v:refname"]))?.split("\n")[0];
8108
+ return tag ? { tag } : {};
8109
+ }
8110
+
8111
+ // ../lib/dist/propagate.js
8112
+ import { join as join4, relative as relative3 } from "node:path";
8113
+
8114
+ // ../lib/dist/train.js
8115
+ import { join as join3 } from "node:path";
8116
+ var TRAIN_REPOS = [
8117
+ "platform",
8118
+ "ci-cd",
8119
+ "preset-repo-web",
8120
+ "preset-app-nextjs",
8121
+ "preset-repo-platform",
8122
+ "compendium"
8123
+ ];
8124
+ var UPSTREAM = "plexus-ms";
8125
+ var isTrainVersion = (v) => /^\d+\.\d+\.\d+$/.test(v);
8126
+ function nextMinor(version2) {
8127
+ const [major = "0", minor = "0"] = version2.split(".");
8128
+ return `${major}.${Number(minor) + 1}.0`;
8129
+ }
8130
+ function latestTag(tags) {
8131
+ return tags.filter((t) => /^v?\d/.test(t)).sort((a, b) => compareTrains(a.replace(/^v/, ""), b.replace(/^v/, ""))).at(-1);
8132
+ }
8133
+ async function readTrain(ctx, upstream) {
8134
+ const repos = [];
8135
+ const all = /* @__PURE__ */ new Set();
8136
+ for (const name of TRAIN_REPOS) {
8137
+ const path3 = join3(upstream, name);
8138
+ try {
8139
+ await ctx.read("git", ["rev-parse", "--git-dir"], { cwd: path3 });
8140
+ } catch {
8141
+ throw new Error(`${path3} is not a git repo`);
8142
+ }
8143
+ try {
8144
+ await ctx.read("git", ["fetch", "origin", "--tags", "--quiet"], { cwd: path3 });
8145
+ } catch {
8146
+ throw new Error(`${name}: fetch from origin failed`);
8147
+ }
8148
+ const tags = (await ctx.read("git", ["tag", "--list", "v*", "[0-9]*"], { cwd: path3 })).split("\n").filter(Boolean);
8149
+ for (const t of tags)
8150
+ all.add(t.replace(/^v/, ""));
8151
+ const tag = latestTag(tags);
8152
+ const range = tag ? `${tag}..HEAD` : "HEAD";
8153
+ const pending = (await ctx.read("git", ["log", "--oneline", range], { cwd: path3 })).split("\n").filter(Boolean);
8154
+ repos.push({ name, path: path3, tag, latest: tag?.replace(/^v/, ""), pending });
8155
+ }
8156
+ const latest = repos.map((r) => r.latest);
8157
+ return { repos, last: latestTag([...all]), skew: latest.some((l) => l !== latest[0]) };
8158
+ }
8159
+ async function preflightRelease(ctx, train) {
8160
+ for (const { name, path: path3 } of train.repos) {
8161
+ const branch = (await ctx.read("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: path3 })).trim();
8162
+ if (branch !== "main")
8163
+ throw new Error(`${name} is on '${branch}', trains cut from main`);
8164
+ if ((await ctx.read("git", ["status", "--porcelain"], { cwd: path3 })).trim() !== "")
8165
+ throw new Error(`${name} has uncommitted changes \u2014 commit first`);
8166
+ const behind = (await ctx.read("git", ["rev-list", "--count", "main..origin/main"], { cwd: path3 })).trim();
8167
+ if (behind !== "0")
8168
+ throw new Error(`${name} is ${behind} commit(s) behind origin/main \u2014 pull first, or the tag lands on a stale commit`);
8355
8169
  }
8356
- return words.slice(0, last).join(" ") + words.slice(last).join("");
8170
+ }
8171
+ function resolveVersion(train, explicit, propagateOnly) {
8172
+ if (explicit !== void 0 && !isTrainVersion(explicit))
8173
+ throw new UsageError(`'${explicit}' is not plain semver (X.Y.Z, no v)`);
8174
+ if (propagateOnly) {
8175
+ const v = explicit ?? train.last;
8176
+ if (!v)
8177
+ throw new Error("no train version found to propagate");
8178
+ return v;
8179
+ }
8180
+ if (explicit)
8181
+ return explicit;
8182
+ if (train.skew) {
8183
+ const report = train.repos.map((r) => ` ${r.name}: ${r.latest ?? "none"}`).join("\n");
8184
+ throw new Error(`the train repos' latest tags disagree:
8185
+ ${report}
8186
+ pass the version explicitly (--train ${train.last}) to finish the half-tagged train, or a higher one to start a new one`);
8187
+ }
8188
+ return train.last ? nextMinor(train.last) : "0.1.0";
8189
+ }
8190
+ var UsageError = class extends Error {
8357
8191
  };
8358
- var exec = (string, columns, options = {}) => {
8359
- if (options.trim !== false && string.trim() === "") {
8360
- return "";
8192
+
8193
+ // ../lib/dist/propagate.js
8194
+ var isClean = (s) => s.conflicted.length === 0 && s.failed.length === 0 && s.skipped.length === 0;
8195
+ var PREVIEW_BASE = "ship-base";
8196
+ async function propagate(ctx, workspace, train) {
8197
+ const summary = { train, preview: ctx.dryRun, clean: [], conflicted: [], failed: [], skipped: [] };
8198
+ const upstream = join4(workspace, UPSTREAM);
8199
+ const tree = await overview(ctx, workspace);
8200
+ const upstreamDir = tree.children.find((c) => c.path === upstream);
8201
+ const presets = TRAIN_REPOS.filter((r) => upstreamDir?.children.some((c) => c.name === r && c.template));
8202
+ const consumers = await findConsumers(ctx, tree, presets);
8203
+ for (const c of consumers) {
8204
+ if (!c.skipped)
8205
+ continue;
8206
+ ctx.say(`\u26A0 ${c.rel}: ${c.skipped} \u2014 skipped (fix it, then re-run propagate)`);
8207
+ summary.skipped.push({ path: c.rel, reason: c.skipped });
8208
+ }
8209
+ const active = consumers.filter((c) => !c.skipped);
8210
+ const scratch = ctx.dryRun ? (await ctx.stage(run("mktemp", ["-d"])))?.trim() : void 0;
8211
+ const clones = /* @__PURE__ */ new Map();
8212
+ const cloneOf = async (consumer) => {
8213
+ let clone = clones.get(consumer.path);
8214
+ if (!clone) {
8215
+ clone = join4(scratch ?? "", consumer.rel);
8216
+ await ctx.stage(run("git", ["clone", "--quiet", consumer.path, clone]));
8217
+ await ctx.stage(run("git", ["tag", PREVIEW_BASE], { cwd: clone }));
8218
+ clones.set(consumer.path, clone);
8219
+ }
8220
+ return clone;
8221
+ };
8222
+ const previewCommit = (clone, message) => ctx.stage(run("git", ["add", "-A"], { cwd: clone })).then(() => ctx.stage(run("git", [
8223
+ "-c",
8224
+ "commit.gpgsign=false",
8225
+ "-c",
8226
+ "user.name=plx",
8227
+ "-c",
8228
+ "user.email=plx@localhost",
8229
+ "commit",
8230
+ "--quiet",
8231
+ "--no-verify",
8232
+ "--allow-empty",
8233
+ "-m",
8234
+ message
8235
+ ], { cwd: clone })));
8236
+ try {
8237
+ for (const preset of presets) {
8238
+ const sites = active.flatMap((c) => c.sites.filter((s) => s.preset === preset).map((s) => [c, s]));
8239
+ if (sites.length === 0)
8240
+ ctx.say(`\u2022 no consumers of ${presetSource(preset)} found under ${workspace}`);
8241
+ for (const [consumer, site] of sites)
8242
+ await updateSite(ctx, consumer, site, join4(upstream, preset), summary, cloneOf, previewCommit);
8243
+ }
8244
+ await refreshLockfiles(ctx, active, summary, clones);
8245
+ await bumpConsumerRefs(ctx, consumers, train);
8246
+ } finally {
8247
+ if (scratch)
8248
+ await ctx.stage(run("rm", ["-rf", scratch]));
8249
+ }
8250
+ return summary;
8251
+ }
8252
+ async function updateSite(ctx, consumer, site, localPreset, summary, cloneOf, previewCommit) {
8253
+ let repo = consumer.path;
8254
+ let target = site.path;
8255
+ try {
8256
+ if (ctx.dryRun) {
8257
+ ctx.say(`\u2192 ${site.rel}: copier update (preview from ${localPreset}@main)`);
8258
+ repo = await cloneOf(consumer);
8259
+ target = join4(repo, relative3(consumer.path, site.path));
8260
+ const answers = await ctx.readFile(join4(site.path, ANSWERS_FILE));
8261
+ await ctx.stage(write(join4(target, ANSWERS_FILE), answers.replace(/^_src_path: .*$/m, `_src_path: ${localPreset}`)));
8262
+ await previewCommit(repo, `plx preview: ${site.rel} reads ${localPreset} from the local checkout`);
8263
+ await ctx.stage(run("copier", ["update", "--skip-answered", "--trust", "--defaults", "--skip-tasks", "--vcs-ref", "main"], {
8264
+ cwd: target
8265
+ }));
8266
+ } else {
8267
+ ctx.say(`\u2192 ${site.rel}: copier update`);
8268
+ const args = ["update", "--skip-answered", "--trust", ...ctx.yes ? ["--defaults"] : []];
8269
+ await ctx.apply([run("copier", args, { cwd: target, interactive: true })]);
8270
+ }
8271
+ } catch (error) {
8272
+ ctx.say(` \u2717 FAILED \u2014 copier update exited nonzero${detail(error)}`);
8273
+ summary.failed.push(site.rel);
8274
+ return;
8275
+ }
8276
+ const status = await ctx.read("git", ["status", "--porcelain"], { cwd: repo });
8277
+ let conflict = hasUnmergedEntries(status);
8278
+ const changed = (await ctx.read("git", ["diff", "--name-only"], { cwd: repo })).split("\n").filter(Boolean);
8279
+ for (const f of changed) {
8280
+ const text = await ctx.readFile(join4(repo, f)).catch(() => "");
8281
+ if (hasConflictMarkers(text))
8282
+ conflict = true;
8283
+ }
8284
+ await syncSiteMarker(ctx, site, target);
8285
+ if (conflict) {
8286
+ ctx.say(" \u2717 CONFLICTS \u2014 resolve the <<<<<<< markers, then git add:");
8287
+ summary.conflicted.push(site.rel);
8288
+ } else {
8289
+ ctx.say(" \u2713 merged clean:");
8290
+ summary.clean.push(site.rel);
8361
8291
  }
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
- }
8292
+ for (const line of status.split("\n").filter(Boolean))
8293
+ ctx.say(` ${line}`);
8294
+ if (ctx.dryRun)
8295
+ await previewCommit(repo, `plx preview: ${site.rel} updated`);
8296
+ }
8297
+ async function syncSiteMarker(ctx, site, target) {
8298
+ const marker = await ctx.readFile(join4(target, MARKER_FILE)).catch(() => void 0);
8299
+ if (marker === void 0)
8300
+ return;
8301
+ const { commit } = parseAnswers(await ctx.readFile(join4(target, ANSWERS_FILE)));
8302
+ if (!commit)
8303
+ return;
8304
+ const synced = syncMarker(marker, commit);
8305
+ if (synced === marker)
8306
+ return;
8307
+ ctx.say(` marker: plexus \u2192 ${commit} in ${site.rel}/${MARKER_FILE}`);
8308
+ const step = write(join4(target, MARKER_FILE), synced);
8309
+ if (ctx.dryRun)
8310
+ await ctx.stage(step);
8311
+ else
8312
+ await ctx.apply([step]);
8313
+ }
8314
+ async function refreshLockfiles(ctx, consumers, summary, clones) {
8315
+ const manifests = ["*package.json", "pnpm-workspace.yaml"];
8316
+ for (const c of consumers) {
8317
+ if (await ctx.readFile(join4(c.path, "pnpm-workspace.yaml")).catch(() => void 0) === void 0)
8318
+ continue;
8319
+ const repo = ctx.dryRun ? clones.get(c.path) : c.path;
8320
+ if (!repo)
8321
+ continue;
8322
+ const range = ctx.dryRun ? [PREVIEW_BASE] : [];
8323
+ const unchanged = await ctx.read("git", ["diff", "--quiet", ...range, "--", ...manifests], { cwd: repo }).then(() => true).catch(() => false);
8324
+ if (unchanged)
8325
+ continue;
8326
+ ctx.say(`\u2192 ${c.rel}: pnpm install (manifests changed)`);
8327
+ try {
8328
+ await ctx.apply([run("mise", ["exec", "--", "pnpm", "install", "--reporter=silent"], { cwd: c.path })]);
8329
+ } catch (error) {
8330
+ ctx.say(` \u2717 pnpm install failed${detail(error)}`);
8331
+ summary.failed.push(`${c.rel}/pnpm-lock.yaml`);
8387
8332
  }
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) ?? "");
8333
+ }
8334
+ }
8335
+ async function bumpConsumerRefs(ctx, consumers, train) {
8336
+ for (const c of consumers) {
8337
+ const dir = join4(c.path, ".github", "workflows");
8338
+ const entries = await ctx.readDir(dir).catch(() => []);
8339
+ const files = entries.filter((e) => !e.directory && /\.ya?ml$/.test(e.name)).map((e) => e.name).sort();
8340
+ if (files.length === 0)
8341
+ continue;
8342
+ if (c.skipped) {
8343
+ ctx.say(`\u26A0 ${c.rel}: workflow refs not bumped (skipped above)`);
8398
8344
  continue;
8399
8345
  }
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) ?? "");
8346
+ for (const f of files) {
8347
+ const text = await ctx.readFile(join4(dir, f));
8348
+ if (!text.includes(WORKFLOW_REF))
8404
8349
  continue;
8405
- }
8406
- rows.push("");
8407
- rowLength = 0;
8350
+ const bumped = bumpWorkflowRefs(text, train);
8351
+ if (bumped === text)
8352
+ continue;
8353
+ ctx.say(`\u2192 ${c.rel}: ${f} ci-cd refs \u2192 @${train}`);
8354
+ await ctx.apply([write(join4(dir, f), bumped)]);
8408
8355
  }
8409
- if (rowLength + wordLength > columns && options.wordWrap === false) {
8410
- wrapWord(rows, word, columns);
8411
- rowLength = dist_default3(rows.at(-1) ?? "");
8356
+ }
8357
+ }
8358
+ var detail = (error) => {
8359
+ const message = error instanceof Error ? error.message : String(error);
8360
+ const last = message.trim().split("\n").at(-1) ?? "";
8361
+ return last && !/exited with/.test(last) ? `: ${last}` : "";
8362
+ };
8363
+
8364
+ // ../lib/dist/requirements.js
8365
+ import { join as join5 } from "node:path";
8366
+ var KEYWORD = /MUST|SHOULD|MAY/;
8367
+ var hasKeyword = (line) => KEYWORD.test(line.replace(/MUSTs|SHOULDs|MAYs/g, ""));
8368
+ var list = (value) => value.replace(/^\s*\[/, "").replace(/\].*$/, "").split(",").map((s) => s.trim()).filter(Boolean);
8369
+ function scanPage(text, name, mode) {
8370
+ const scan = { defects: [], requirements: [], depends: [], consumes: [] };
8371
+ const lines = text.split("\n");
8372
+ const defect = (n, msg) => scan.defects.push(`\u2717 ${name}: line ${n + 1}: ${msg}`);
8373
+ let i = 0;
8374
+ if (lines[0] === "---") {
8375
+ for (i = 1; i < lines.length && lines[i] !== "---"; i++) {
8376
+ const line = lines[i] ?? "";
8377
+ const [key = "", ...rest] = line.split(/\s+/);
8378
+ const value = rest.join(" ");
8379
+ if (key === "maturity:")
8380
+ scan.maturity = rest[0];
8381
+ else if (key === "code:")
8382
+ scan.code = rest[0];
8383
+ else if (key === "binds:")
8384
+ scan.binds = rest[0];
8385
+ else if (key === "depends:")
8386
+ scan.depends = list(value);
8387
+ else if (key === "consumes:")
8388
+ scan.consumes = list(value);
8389
+ else if (key === "kind:")
8390
+ defect(i, "kind is the folder, contracts/ or approaches/, not a field");
8391
+ }
8392
+ i++;
8393
+ }
8394
+ let inCode = false;
8395
+ let maintaining = false;
8396
+ let started = false;
8397
+ let section = "";
8398
+ for (; i < lines.length; i++) {
8399
+ const line = lines[i] ?? "";
8400
+ if (line.startsWith("```")) {
8401
+ inCode = !inCode;
8412
8402
  continue;
8413
8403
  }
8414
- rows[rows.length - 1] += word;
8415
- rowLength += wordLength;
8404
+ if (inCode)
8405
+ continue;
8406
+ if (line === "## Maintaining") {
8407
+ maintaining = true;
8408
+ section = "";
8409
+ continue;
8410
+ }
8411
+ const heading = /^#+ § (\S+)/.exec(line);
8412
+ if (heading) {
8413
+ if (maintaining)
8414
+ defect(i, "numbered section after Maintaining");
8415
+ section = heading[1] ?? "";
8416
+ started = true;
8417
+ continue;
8418
+ }
8419
+ if (line.startsWith("> - ")) {
8420
+ if (mode === "map")
8421
+ defect(i, `requirement in the map: ${line}`);
8422
+ else if (scan.maturity !== "standard")
8423
+ defect(i, `requirement in a module at ${scan.maturity} maturity: ${line}`);
8424
+ else if (maintaining)
8425
+ defect(i, `requirement under Maintaining: ${line}`);
8426
+ else if (!started)
8427
+ defect(i, "requirement before the first \xA7 heading");
8428
+ else
8429
+ scan.requirements.push(`\xA7 ${section} ${line.slice(4)}`);
8430
+ continue;
8431
+ }
8432
+ if (line.startsWith(">")) {
8433
+ defect(i, 'blockquote line is not a "> - " requirement bullet');
8434
+ continue;
8435
+ }
8436
+ if (hasKeyword(line))
8437
+ defect(i, `BCP 14 keyword outside a requirement: ${line}`);
8438
+ }
8439
+ if (mode === "module") {
8440
+ const { maturity = "", binds = "", code = "" } = scan;
8441
+ const n = text.endsWith("\n") ? lines.length - 1 : lines.length;
8442
+ if (!/^(note|candidate|standard)$/.test(maturity))
8443
+ defect(n - 1, `maturity must be note, candidate or standard, not "${maturity}"`);
8444
+ if (!/^(repo|app|host|organisation)$/.test(binds))
8445
+ defect(n - 1, `binds must be repo, app, host or organisation, not "${binds}"`);
8446
+ if (maturity === "note" && code !== "")
8447
+ defect(n - 1, "a note carries no code");
8448
+ if (maturity !== "note" && !/^PLX-[A-Z][A-Za-z]+$/.test(code))
8449
+ defect(n - 1, `code must be PLX- plus one capitalised word, not "${code}"`);
8450
+ }
8451
+ return scan;
8452
+ }
8453
+ var extractRequirements = (text) => scanPage(text, "", "module").requirements;
8454
+ var MAP_PAGE = "essentials/standard.md";
8455
+ async function modulePages(ctx, compendium) {
8456
+ const pages = [];
8457
+ for (const dir of Object.keys(CATALOG_DIRS)) {
8458
+ const entries = await ctx.readDir(join5(compendium, dir));
8459
+ for (const e of entries.filter((e2) => !e2.directory && e2.name.endsWith(".md") && e2.name !== "index.md").sort())
8460
+ pages.push(`${dir}/${e.name}`);
8461
+ }
8462
+ return pages;
8463
+ }
8464
+ async function checkCompendium(ctx, compendium) {
8465
+ const defects = [];
8466
+ defects.push(...scanPage(await ctx.readFile(join5(compendium, MAP_PAGE)), MAP_PAGE, "map").defects);
8467
+ const pages = await modulePages(ctx, compendium);
8468
+ const scans = /* @__PURE__ */ new Map();
8469
+ for (const page of pages) {
8470
+ const scan = scanPage(await ctx.readFile(join5(compendium, page)), page, "module");
8471
+ defects.push(...scan.defects);
8472
+ scans.set(page, scan);
8473
+ }
8474
+ const byCode = /* @__PURE__ */ new Map();
8475
+ for (const [page, s] of scans)
8476
+ if (s.code)
8477
+ byCode.set(s.code, [...byCode.get(s.code) ?? [], page]);
8478
+ for (const [code, where] of byCode)
8479
+ if (where.length > 1)
8480
+ defects.push(`\u2717 duplicate module code: ${code}`);
8481
+ for (const s of scans.values())
8482
+ for (const dep of s.depends)
8483
+ if (!byCode.has(dep))
8484
+ defects.push(`\u2717 unknown module in depends: ${dep}`);
8485
+ const kindOf2 = (page) => page.startsWith("contracts/") ? "contract" : "approach";
8486
+ const side = (binds2) => binds2 === "repo" || binds2 === "app" ? "dev" : "ops";
8487
+ const kinds = new Map([...byCode].map(([code, [page = ""]]) => [code, kindOf2(page)]));
8488
+ const binds = new Map([...byCode].map(([code, [page = ""]]) => [code, scans.get(page)?.binds ?? ""]));
8489
+ for (const [page, s] of scans) {
8490
+ const m = s.code ?? page.replace(/.*\//, "");
8491
+ const kind = kindOf2(page);
8492
+ for (const c of s.consumes) {
8493
+ if (kind === "contract")
8494
+ defects.push(`\u2717 ${m} is a contract and consumes ${c}; a contract has no other side to consume`);
8495
+ else if (kinds.has(c) && kinds.get(c) !== "contract")
8496
+ defects.push(`\u2717 ${m} consumes ${c}, which is an approach; only a contract is consumed across a seam`);
8497
+ else if (!kinds.has(c))
8498
+ defects.push(`\u2717 ${m} consumes unknown module ${c}`);
8499
+ }
8500
+ for (const d of s.depends) {
8501
+ if (!kinds.has(d))
8502
+ continue;
8503
+ if (kind === "contract" && kinds.get(d) !== "contract")
8504
+ defects.push(`\u2717 ${m} is a contract and depends on the approach ${d}`);
8505
+ if (side(s.binds ?? "") !== side(binds.get(d) ?? "") && kinds.get(d) !== "contract")
8506
+ 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`);
8507
+ }
8416
8508
  }
8417
- if (options.trim !== false) {
8418
- rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
8509
+ return {
8510
+ defects,
8511
+ contracts: pages.filter((p) => p.startsWith("contracts/")).length,
8512
+ approaches: pages.filter((p) => p.startsWith("approaches/")).length
8513
+ };
8514
+ }
8515
+
8516
+ // ../lib/dist/ship.js
8517
+ import { join as join6 } from "node:path";
8518
+ async function ship(ctx, options) {
8519
+ const upstream = join6(options.workspace, UPSTREAM);
8520
+ const propagateOnly = options.propagateOnly ?? false;
8521
+ const train = await readTrain(ctx, upstream);
8522
+ if (!propagateOnly)
8523
+ await preflightRelease(ctx, train);
8524
+ const next = resolveVersion(train, options.train, propagateOnly);
8525
+ if (!propagateOnly)
8526
+ await release(ctx, train, next, options.today ?? today());
8527
+ const summary = await propagate(ctx, options.workspace, next);
8528
+ return { ...summary, released: !propagateOnly };
8529
+ }
8530
+ async function release(ctx, train, next, today2) {
8531
+ ctx.say(`\u2192 train ${train.last ?? "none"} \u2192 ${next}`);
8532
+ for (const repo of train.repos) {
8533
+ if (repo.pending.length === 0)
8534
+ ctx.say(` ${repo.name}: no changes since ${repo.latest} \u2014 tag only`);
8535
+ else {
8536
+ ctx.say(` ${repo.name} (since ${repo.latest ?? "the beginning"}):`);
8537
+ for (const line of repo.pending)
8538
+ ctx.say(` ${line}`);
8539
+ }
8540
+ }
8541
+ if (!await ctx.confirm(`tag all ${train.repos.length} repos as ${next} and push?`))
8542
+ throw new Error("aborted");
8543
+ try {
8544
+ const plan = await planBookkeeping(ctx, train, next, today2);
8545
+ await ctx.apply(plan);
8546
+ for (const repo of train.repos) {
8547
+ const tagged = await ctx.read("git", ["rev-parse", "-q", "--verify", `refs/tags/${next}`], { cwd: repo.path }).then(() => true).catch(() => false);
8548
+ if (tagged)
8549
+ ctx.say(`\u2022 ${repo.name}: already tagged ${next}`);
8550
+ else
8551
+ await ctx.apply([run("git", ["tag", "-a", next, "-m", `train ${next}`], { cwd: repo.path })]);
8552
+ await ctx.apply([run("git", ["push", "origin", "main", next], { cwd: repo.path })]);
8553
+ }
8554
+ } catch (error) {
8555
+ const message = error instanceof Error ? error.message : String(error);
8556
+ throw new Error(`${message}
8557
+ \u2717 ship stopped during the release; re-run with --train ${next} to finish it (tagged repos are skipped)`);
8419
8558
  }
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;
8559
+ }
8560
+ async function planBookkeeping(ctx, train, next, today2) {
8561
+ const plan = [];
8562
+ const touched = /* @__PURE__ */ new Set();
8563
+ const repo = (name) => {
8564
+ const r = train.repos.find((r2) => r2.name === name);
8565
+ if (!r)
8566
+ throw new Error(`${name} is not a train repo`);
8567
+ return r;
8568
+ };
8569
+ const edit = async (r, rel, what, transform) => {
8570
+ const path3 = join6(r.path, rel);
8571
+ const text = await ctx.readFile(path3).catch(() => void 0);
8572
+ if (text === void 0)
8573
+ return;
8574
+ const edited = transform(text);
8575
+ if (edited === text)
8576
+ return;
8577
+ ctx.say(` ${r.name}: ${rel}: ${what}`);
8578
+ plan.push(write(path3, edited));
8579
+ touched.add(r);
8580
+ };
8581
+ await edit(repo("platform"), "ansible/galaxy.yml", `version \u2192 ${next}`, (t) => bumpGalaxyVersion(t, next));
8582
+ await edit(repo("preset-repo-platform"), "template/requirements.yml", `plexus.platform pin \u2192 ${next}`, (t) => bumpCollectionPin(t, next));
8583
+ for (const r of train.repos) {
8584
+ const files = await ctx.read("git", ["grep", "-l", WORKFLOW_REF, "--", "*.yml", "*.yaml", "*.jinja"], { cwd: r.path }).catch(() => "");
8585
+ for (const f of files.split("\n").filter(Boolean))
8586
+ await edit(r, f, `ci-cd refs \u2192 @${next}`, (t) => bumpWorkflowRefs(t, next));
8587
+ }
8588
+ const comp = repo("compendium");
8589
+ await edit(comp, MAP_PAGE, `version \u2192 ${next}, timestamp \u2192 ${today2}`, (t) => stampStandard(t, next, today2));
8590
+ for (const page of await modulePages(ctx, comp.path)) {
8591
+ const text = await ctx.readFile(join6(comp.path, page));
8592
+ if (frontmatterField(text, "maturity") !== "standard")
8593
+ continue;
8594
+ const previous = comp.tag ? await ctx.read("git", ["show", `${comp.tag}:${page}`], { cwd: comp.path }).catch(() => "") : "";
8595
+ if (extractRequirements(text).join("\n") === extractRequirements(previous).join("\n"))
8596
+ continue;
8597
+ await edit(comp, page, `requirements changed since ${comp.latest ?? "the beginning"} \u2192 changed: ${next}`, (t) => stampChanged(t, next));
8598
+ }
8599
+ for (const r of train.repos) {
8600
+ if (!touched.has(r))
8601
+ continue;
8602
+ plan.push(run("git", ["add", "-A"], { cwd: r.path }));
8603
+ plan.push(run("git", ["commit", "--quiet", "-m", `chore: train ${next} bookkeeping`], { cwd: r.path }));
8604
+ }
8605
+ return plan;
8606
+ }
8607
+
8608
+ // src/program.ts
8609
+ import { createRequire } from "node:module";
8610
+
8611
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/key.js
8612
+ var keybindings = ["emacs", "vim"];
8613
+ var keybindingLookup = new Set(keybindings);
8614
+ function isKeybinding(value) {
8615
+ return keybindingLookup.has(value);
8616
+ }
8617
+ function getDefaultKeybindings() {
8618
+ const env = process.env["INQUIRER_KEYBINDINGS"];
8619
+ if (!env)
8620
+ return [];
8621
+ return Array.from(new Set(env.toLowerCase().split(/[\s,]+/).filter(isKeybinding)));
8622
+ }
8623
+ var isTabKey = (key) => key.name === "tab";
8624
+ var isEnterKey = (key) => key.name === "enter" || key.name === "return";
8625
+
8626
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/errors.js
8627
+ var AbortPromptError = class extends Error {
8628
+ name = "AbortPromptError";
8629
+ message = "Prompt was aborted";
8630
+ constructor(options) {
8631
+ super();
8632
+ this.cause = options?.cause;
8633
+ }
8634
+ };
8635
+ var CancelPromptError = class extends Error {
8636
+ name = "CancelPromptError";
8637
+ message = "Prompt was canceled";
8638
+ };
8639
+ var ExitPromptError = class extends Error {
8640
+ name = "ExitPromptError";
8641
+ };
8642
+ var HookError = class extends Error {
8643
+ name = "HookError";
8644
+ };
8645
+ var ValidationError = class extends Error {
8646
+ name = "ValidationError";
8647
+ };
8648
+
8649
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-state.js
8650
+ import { AsyncResource as AsyncResource2 } from "node:async_hooks";
8651
+
8652
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/hook-engine.js
8653
+ import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
8654
+ var hookStorage = new AsyncLocalStorage();
8655
+ function createStore(rl) {
8656
+ const store = {
8657
+ rl,
8658
+ hooks: [],
8659
+ hooksCleanup: [],
8660
+ hooksEffect: [],
8661
+ index: 0,
8662
+ handleChange() {
8432
8663
  }
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
- }
8664
+ };
8665
+ return store;
8666
+ }
8667
+ function withHooks(rl, cb) {
8668
+ const store = createStore(rl);
8669
+ function cycle(render2) {
8670
+ store.handleChange = () => {
8671
+ store.index = 0;
8672
+ render2();
8673
+ };
8674
+ store.handleChange();
8675
+ }
8676
+ return hookStorage.run(store, () => cb(cycle));
8677
+ }
8678
+ function getStore() {
8679
+ const store = hookStorage.getStore();
8680
+ if (!store) {
8681
+ throw new HookError("[Inquirer] Hook functions can only be called from within a prompt");
8682
+ }
8683
+ return store;
8684
+ }
8685
+ function readline() {
8686
+ return getStore().rl;
8687
+ }
8688
+ function withUpdates(fn) {
8689
+ const wrapped = (...args) => {
8690
+ const store = getStore();
8691
+ let shouldUpdate = false;
8692
+ const oldHandleChange = store.handleChange;
8693
+ store.handleChange = () => {
8694
+ shouldUpdate = true;
8695
+ };
8696
+ const returnValue = fn(...args);
8697
+ if (shouldUpdate) {
8698
+ oldHandleChange();
8443
8699
  }
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);
8700
+ store.handleChange = oldHandleChange;
8701
+ return returnValue;
8702
+ };
8703
+ return AsyncResource.bind(wrapped);
8704
+ }
8705
+ function withPointer(cb) {
8706
+ const store = getStore();
8707
+ const { index } = store;
8708
+ const pointer = {
8709
+ get() {
8710
+ return store.hooks[index];
8711
+ },
8712
+ set(value) {
8713
+ store.hooks[index] = value;
8714
+ },
8715
+ initialized: index in store.hooks
8716
+ };
8717
+ const returnValue = cb(pointer);
8718
+ store.index++;
8719
+ return returnValue;
8720
+ }
8721
+ function handleChange() {
8722
+ getStore().handleChange();
8723
+ }
8724
+ var effectScheduler = {
8725
+ queue(cb) {
8726
+ const store = getStore();
8727
+ const { index } = store;
8728
+ store.hooksEffect.push(() => {
8729
+ store.hooksCleanup[index]?.();
8730
+ const cleanFn = cb(readline());
8731
+ if (cleanFn != null && typeof cleanFn !== "function") {
8732
+ throw new ValidationError("useEffect return value must be a cleanup function or nothing.");
8458
8733
  }
8459
- }
8734
+ store.hooksCleanup[index] = cleanFn;
8735
+ });
8736
+ },
8737
+ run() {
8738
+ const store = getStore();
8739
+ withUpdates(() => {
8740
+ store.hooksEffect.forEach((effect) => {
8741
+ effect();
8742
+ });
8743
+ store.hooksEffect.length = 0;
8744
+ })();
8745
+ },
8746
+ clearAll() {
8747
+ const store = getStore();
8748
+ store.hooksCleanup.forEach((cleanFn) => {
8749
+ cleanFn?.();
8750
+ });
8751
+ store.hooksEffect.length = 0;
8752
+ store.hooksCleanup.length = 0;
8753
+ }
8754
+ };
8755
+
8756
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-state.js
8757
+ function isFactory(value) {
8758
+ return typeof value === "function";
8759
+ }
8760
+ function isReducer(value) {
8761
+ return typeof value === "function";
8762
+ }
8763
+ function useState(defaultValue) {
8764
+ return withPointer((pointer) => {
8765
+ const setState = AsyncResource2.bind(function setState2(newValue) {
8766
+ const currentValue = pointer.get();
8767
+ const nextValue = isReducer(newValue) ? newValue(currentValue) : newValue;
8768
+ if (!Object.is(currentValue, nextValue)) {
8769
+ pointer.set(nextValue);
8770
+ handleChange();
8771
+ }
8772
+ });
8773
+ if (pointer.initialized) {
8774
+ return [pointer.get(), setState];
8775
+ }
8776
+ const value = isFactory(defaultValue) ? defaultValue() : defaultValue;
8777
+ pointer.set(value);
8778
+ return [value, setState];
8779
+ });
8780
+ }
8781
+
8782
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-effect.js
8783
+ function useEffect(cb, depArray) {
8784
+ withPointer((pointer) => {
8785
+ const oldDeps = pointer.get();
8786
+ const hasChanged = !Array.isArray(oldDeps) || depArray.some((dep, i) => !Object.is(dep, oldDeps[i]));
8787
+ if (hasChanged) {
8788
+ effectScheduler.queue(cb);
8789
+ }
8790
+ pointer.set(depArray);
8791
+ });
8792
+ }
8793
+
8794
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/theme.js
8795
+ import { styleText } from "node:util";
8796
+
8797
+ // ../../node_modules/.pnpm/@inquirer+figures@2.0.9/node_modules/@inquirer/figures/dist/index.js
8798
+ import process2 from "node:process";
8799
+ function isUnicodeSupported() {
8800
+ if (!process2.platform.startsWith("win")) {
8801
+ return process2.env["TERM"] !== "linux";
8802
+ }
8803
+ return Boolean(process2.env["CI"]) || // CI environments generally support unicode
8804
+ Boolean(process2.env["WT_SESSION"]) || // Windows Terminal
8805
+ Boolean(process2.env["TERMINUS_SUBLIME"]) || // Terminus (<0.2.27)
8806
+ process2.env["ConEmuTask"] === "{cmd::Cmder}" || // ConEmu and cmder
8807
+ process2.env["TERM_PROGRAM"] === "Terminus-Sublime" || process2.env["TERM_PROGRAM"] === "vscode" || process2.env["TERM"] === "xterm-256color" || process2.env["TERM"] === "alacritty" || process2.env["TERMINAL_EMULATOR"] === "JetBrains-JediTerm";
8808
+ }
8809
+ var common = {
8810
+ circleQuestionMark: "(?)",
8811
+ questionMarkPrefix: "(?)",
8812
+ square: "\u2588",
8813
+ squareDarkShade: "\u2593",
8814
+ squareMediumShade: "\u2592",
8815
+ squareLightShade: "\u2591",
8816
+ squareTop: "\u2580",
8817
+ squareBottom: "\u2584",
8818
+ squareLeft: "\u258C",
8819
+ squareRight: "\u2590",
8820
+ squareCenter: "\u25A0",
8821
+ bullet: "\u25CF",
8822
+ dot: "\u2024",
8823
+ ellipsis: "\u2026",
8824
+ pointerSmall: "\u203A",
8825
+ triangleUp: "\u25B2",
8826
+ triangleUpSmall: "\u25B4",
8827
+ triangleDown: "\u25BC",
8828
+ triangleDownSmall: "\u25BE",
8829
+ triangleLeftSmall: "\u25C2",
8830
+ triangleRightSmall: "\u25B8",
8831
+ home: "\u2302",
8832
+ heart: "\u2665",
8833
+ musicNote: "\u266A",
8834
+ musicNoteBeamed: "\u266B",
8835
+ arrowUp: "\u2191",
8836
+ arrowDown: "\u2193",
8837
+ arrowLeft: "\u2190",
8838
+ arrowRight: "\u2192",
8839
+ arrowLeftRight: "\u2194",
8840
+ arrowUpDown: "\u2195",
8841
+ almostEqual: "\u2248",
8842
+ notEqual: "\u2260",
8843
+ lessOrEqual: "\u2264",
8844
+ greaterOrEqual: "\u2265",
8845
+ identical: "\u2261",
8846
+ infinity: "\u221E",
8847
+ subscriptZero: "\u2080",
8848
+ subscriptOne: "\u2081",
8849
+ subscriptTwo: "\u2082",
8850
+ subscriptThree: "\u2083",
8851
+ subscriptFour: "\u2084",
8852
+ subscriptFive: "\u2085",
8853
+ subscriptSix: "\u2086",
8854
+ subscriptSeven: "\u2087",
8855
+ subscriptEight: "\u2088",
8856
+ subscriptNine: "\u2089",
8857
+ oneHalf: "\xBD",
8858
+ oneThird: "\u2153",
8859
+ oneQuarter: "\xBC",
8860
+ oneFifth: "\u2155",
8861
+ oneSixth: "\u2159",
8862
+ oneEighth: "\u215B",
8863
+ twoThirds: "\u2154",
8864
+ twoFifths: "\u2156",
8865
+ threeQuarters: "\xBE",
8866
+ threeFifths: "\u2157",
8867
+ threeEighths: "\u215C",
8868
+ fourFifths: "\u2158",
8869
+ fiveSixths: "\u215A",
8870
+ fiveEighths: "\u215D",
8871
+ sevenEighths: "\u215E",
8872
+ line: "\u2500",
8873
+ lineBold: "\u2501",
8874
+ lineDouble: "\u2550",
8875
+ lineDashed0: "\u2504",
8876
+ lineDashed1: "\u2505",
8877
+ lineDashed2: "\u2508",
8878
+ lineDashed3: "\u2509",
8879
+ lineDashed4: "\u254C",
8880
+ lineDashed5: "\u254D",
8881
+ lineDashed6: "\u2574",
8882
+ lineDashed7: "\u2576",
8883
+ lineDashed8: "\u2578",
8884
+ lineDashed9: "\u257A",
8885
+ lineDashed10: "\u257C",
8886
+ lineDashed11: "\u257E",
8887
+ lineDashed12: "\u2212",
8888
+ lineDashed13: "\u2013",
8889
+ lineDashed14: "\u2010",
8890
+ lineDashed15: "\u2043",
8891
+ lineVertical: "\u2502",
8892
+ lineVerticalBold: "\u2503",
8893
+ lineVerticalDouble: "\u2551",
8894
+ lineVerticalDashed0: "\u2506",
8895
+ lineVerticalDashed1: "\u2507",
8896
+ lineVerticalDashed2: "\u250A",
8897
+ lineVerticalDashed3: "\u250B",
8898
+ lineVerticalDashed4: "\u254E",
8899
+ lineVerticalDashed5: "\u254F",
8900
+ lineVerticalDashed6: "\u2575",
8901
+ lineVerticalDashed7: "\u2577",
8902
+ lineVerticalDashed8: "\u2579",
8903
+ lineVerticalDashed9: "\u257B",
8904
+ lineVerticalDashed10: "\u257D",
8905
+ lineVerticalDashed11: "\u257F",
8906
+ lineDownLeft: "\u2510",
8907
+ lineDownLeftArc: "\u256E",
8908
+ lineDownBoldLeftBold: "\u2513",
8909
+ lineDownBoldLeft: "\u2512",
8910
+ lineDownLeftBold: "\u2511",
8911
+ lineDownDoubleLeftDouble: "\u2557",
8912
+ lineDownDoubleLeft: "\u2556",
8913
+ lineDownLeftDouble: "\u2555",
8914
+ lineDownRight: "\u250C",
8915
+ lineDownRightArc: "\u256D",
8916
+ lineDownBoldRightBold: "\u250F",
8917
+ lineDownBoldRight: "\u250E",
8918
+ lineDownRightBold: "\u250D",
8919
+ lineDownDoubleRightDouble: "\u2554",
8920
+ lineDownDoubleRight: "\u2553",
8921
+ lineDownRightDouble: "\u2552",
8922
+ lineUpLeft: "\u2518",
8923
+ lineUpLeftArc: "\u256F",
8924
+ lineUpBoldLeftBold: "\u251B",
8925
+ lineUpBoldLeft: "\u251A",
8926
+ lineUpLeftBold: "\u2519",
8927
+ lineUpDoubleLeftDouble: "\u255D",
8928
+ lineUpDoubleLeft: "\u255C",
8929
+ lineUpLeftDouble: "\u255B",
8930
+ lineUpRight: "\u2514",
8931
+ lineUpRightArc: "\u2570",
8932
+ lineUpBoldRightBold: "\u2517",
8933
+ lineUpBoldRight: "\u2516",
8934
+ lineUpRightBold: "\u2515",
8935
+ lineUpDoubleRightDouble: "\u255A",
8936
+ lineUpDoubleRight: "\u2559",
8937
+ lineUpRightDouble: "\u2558",
8938
+ lineUpDownLeft: "\u2524",
8939
+ lineUpBoldDownBoldLeftBold: "\u252B",
8940
+ lineUpBoldDownBoldLeft: "\u2528",
8941
+ lineUpDownLeftBold: "\u2525",
8942
+ lineUpBoldDownLeftBold: "\u2529",
8943
+ lineUpDownBoldLeftBold: "\u252A",
8944
+ lineUpDownBoldLeft: "\u2527",
8945
+ lineUpBoldDownLeft: "\u2526",
8946
+ lineUpDoubleDownDoubleLeftDouble: "\u2563",
8947
+ lineUpDoubleDownDoubleLeft: "\u2562",
8948
+ lineUpDownLeftDouble: "\u2561",
8949
+ lineUpDownRight: "\u251C",
8950
+ lineUpBoldDownBoldRightBold: "\u2523",
8951
+ lineUpBoldDownBoldRight: "\u2520",
8952
+ lineUpDownRightBold: "\u251D",
8953
+ lineUpBoldDownRightBold: "\u2521",
8954
+ lineUpDownBoldRightBold: "\u2522",
8955
+ lineUpDownBoldRight: "\u251F",
8956
+ lineUpBoldDownRight: "\u251E",
8957
+ lineUpDoubleDownDoubleRightDouble: "\u2560",
8958
+ lineUpDoubleDownDoubleRight: "\u255F",
8959
+ lineUpDownRightDouble: "\u255E",
8960
+ lineDownLeftRight: "\u252C",
8961
+ lineDownBoldLeftBoldRightBold: "\u2533",
8962
+ lineDownLeftBoldRightBold: "\u252F",
8963
+ lineDownBoldLeftRight: "\u2530",
8964
+ lineDownBoldLeftBoldRight: "\u2531",
8965
+ lineDownBoldLeftRightBold: "\u2532",
8966
+ lineDownLeftRightBold: "\u252E",
8967
+ lineDownLeftBoldRight: "\u252D",
8968
+ lineDownDoubleLeftDoubleRightDouble: "\u2566",
8969
+ lineDownDoubleLeftRight: "\u2565",
8970
+ lineDownLeftDoubleRightDouble: "\u2564",
8971
+ lineUpLeftRight: "\u2534",
8972
+ lineUpBoldLeftBoldRightBold: "\u253B",
8973
+ lineUpLeftBoldRightBold: "\u2537",
8974
+ lineUpBoldLeftRight: "\u2538",
8975
+ lineUpBoldLeftBoldRight: "\u2539",
8976
+ lineUpBoldLeftRightBold: "\u253A",
8977
+ lineUpLeftRightBold: "\u2536",
8978
+ lineUpLeftBoldRight: "\u2535",
8979
+ lineUpDoubleLeftDoubleRightDouble: "\u2569",
8980
+ lineUpDoubleLeftRight: "\u2568",
8981
+ lineUpLeftDoubleRightDouble: "\u2567",
8982
+ lineUpDownLeftRight: "\u253C",
8983
+ lineUpBoldDownBoldLeftBoldRightBold: "\u254B",
8984
+ lineUpDownBoldLeftBoldRightBold: "\u2548",
8985
+ lineUpBoldDownLeftBoldRightBold: "\u2547",
8986
+ lineUpBoldDownBoldLeftRightBold: "\u254A",
8987
+ lineUpBoldDownBoldLeftBoldRight: "\u2549",
8988
+ lineUpBoldDownLeftRight: "\u2540",
8989
+ lineUpDownBoldLeftRight: "\u2541",
8990
+ lineUpDownLeftBoldRight: "\u253D",
8991
+ lineUpDownLeftRightBold: "\u253E",
8992
+ lineUpBoldDownBoldLeftRight: "\u2542",
8993
+ lineUpDownLeftBoldRightBold: "\u253F",
8994
+ lineUpBoldDownLeftBoldRight: "\u2543",
8995
+ lineUpBoldDownLeftRightBold: "\u2544",
8996
+ lineUpDownBoldLeftBoldRight: "\u2545",
8997
+ lineUpDownBoldLeftRightBold: "\u2546",
8998
+ lineUpDoubleDownDoubleLeftDoubleRightDouble: "\u256C",
8999
+ lineUpDoubleDownDoubleLeftRight: "\u256B",
9000
+ lineUpDownLeftDoubleRightDouble: "\u256A",
9001
+ lineCross: "\u2573",
9002
+ lineBackslash: "\u2572",
9003
+ lineSlash: "\u2571"
9004
+ };
9005
+ var specialMainSymbols = {
9006
+ tick: "\u2714",
9007
+ info: "\u2139",
9008
+ warning: "\u26A0",
9009
+ cross: "\u2718",
9010
+ squareSmall: "\u25FB",
9011
+ squareSmallFilled: "\u25FC",
9012
+ circle: "\u25EF",
9013
+ circleFilled: "\u25C9",
9014
+ circleDotted: "\u25CC",
9015
+ circleDouble: "\u25CE",
9016
+ circleCircle: "\u24DE",
9017
+ circleCross: "\u24E7",
9018
+ circlePipe: "\u24BE",
9019
+ radioOn: "\u25C9",
9020
+ radioOff: "\u25EF",
9021
+ checkboxOn: "\u2612",
9022
+ checkboxOff: "\u2610",
9023
+ checkboxCircleOn: "\u24E7",
9024
+ checkboxCircleOff: "\u24BE",
9025
+ pointer: "\u276F",
9026
+ triangleUpOutline: "\u25B3",
9027
+ triangleLeft: "\u25C0",
9028
+ triangleRight: "\u25B6",
9029
+ lozenge: "\u25C6",
9030
+ lozengeOutline: "\u25C7",
9031
+ hamburger: "\u2630",
9032
+ smiley: "\u32E1",
9033
+ mustache: "\u0DF4",
9034
+ star: "\u2605",
9035
+ play: "\u25B6",
9036
+ nodejs: "\u2B22",
9037
+ oneSeventh: "\u2150",
9038
+ oneNinth: "\u2151",
9039
+ oneTenth: "\u2152"
9040
+ };
9041
+ var specialFallbackSymbols = {
9042
+ tick: "\u221A",
9043
+ info: "i",
9044
+ warning: "\u203C",
9045
+ cross: "\xD7",
9046
+ squareSmall: "\u25A1",
9047
+ squareSmallFilled: "\u25A0",
9048
+ circle: "( )",
9049
+ circleFilled: "(*)",
9050
+ circleDotted: "( )",
9051
+ circleDouble: "( )",
9052
+ circleCircle: "(\u25CB)",
9053
+ circleCross: "(\xD7)",
9054
+ circlePipe: "(\u2502)",
9055
+ radioOn: "(*)",
9056
+ radioOff: "( )",
9057
+ checkboxOn: "[\xD7]",
9058
+ checkboxOff: "[ ]",
9059
+ checkboxCircleOn: "(\xD7)",
9060
+ checkboxCircleOff: "( )",
9061
+ pointer: ">",
9062
+ triangleUpOutline: "\u2206",
9063
+ triangleLeft: "\u25C4",
9064
+ triangleRight: "\u25BA",
9065
+ lozenge: "\u2666",
9066
+ lozengeOutline: "\u25CA",
9067
+ hamburger: "\u2261",
9068
+ smiley: "\u263A",
9069
+ mustache: "\u250C\u2500\u2510",
9070
+ star: "\u2736",
9071
+ play: "\u25BA",
9072
+ nodejs: "\u2666",
9073
+ oneSeventh: "1/7",
9074
+ oneNinth: "1/9",
9075
+ oneTenth: "1/10"
9076
+ };
9077
+ var mainSymbols = {
9078
+ ...common,
9079
+ ...specialMainSymbols
9080
+ };
9081
+ var fallbackSymbols = {
9082
+ ...common,
9083
+ ...specialFallbackSymbols
9084
+ };
9085
+ var shouldUseMain = isUnicodeSupported();
9086
+ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
9087
+ var dist_default = figures;
9088
+ var replacements = Object.entries(specialMainSymbols);
9089
+
9090
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/theme.js
9091
+ var defaultTheme = {
9092
+ prefix: {
9093
+ idle: styleText("blue", "?"),
9094
+ done: styleText("green", dist_default.tick)
9095
+ },
9096
+ spinner: {
9097
+ interval: 80,
9098
+ frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"].map((frame) => styleText("yellow", frame))
9099
+ },
9100
+ keybindings: [],
9101
+ style: {
9102
+ answer: (text) => styleText("cyan", text),
9103
+ message: (text) => styleText("bold", text),
9104
+ error: (text) => styleText("red", `> ${text}`),
9105
+ defaultAnswer: (text) => styleText("dim", `(${text})`),
9106
+ help: (text) => styleText("dim", text),
9107
+ highlight: (text) => styleText("cyan", text),
9108
+ key: (text) => styleText("cyan", styleText("bold", `<${text}>`))
8460
9109
  }
8461
- return returnValue;
8462
9110
  };
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");
9111
+ function getDefaultTheme() {
9112
+ return {
9113
+ ...defaultTheme,
9114
+ keybindings: getDefaultKeybindings()
9115
+ };
8466
9116
  }
8467
9117
 
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");
9118
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/make-theme.js
9119
+ function isPlainObject(value) {
9120
+ if (typeof value !== "object" || value === null)
9121
+ return false;
9122
+ let proto = value;
9123
+ while (Object.getPrototypeOf(proto) !== null) {
9124
+ proto = Object.getPrototypeOf(proto);
9125
+ }
9126
+ return Object.getPrototypeOf(value) === proto;
8471
9127
  }
8472
- function readlineWidth() {
8473
- return (0, import_cli_width.default)({ defaultWidth: 80, output: readline().output });
9128
+ function deepMerge(...objects) {
9129
+ const output = {};
9130
+ for (const obj of objects) {
9131
+ for (const [key, value] of Object.entries(obj)) {
9132
+ const prevValue = output[key];
9133
+ output[key] = isPlainObject(prevValue) && isPlainObject(value) ? deepMerge(prevValue, value) : value;
9134
+ }
9135
+ }
9136
+ return output;
8474
9137
  }
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 };
9138
+ function makeTheme(...themes) {
9139
+ const themesToMerge = [
9140
+ getDefaultTheme(),
9141
+ ...themes.filter((theme) => theme != null)
9142
+ ];
9143
+ return deepMerge(...themesToMerge);
8489
9144
  }
8490
9145
 
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
- );
9146
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-prefix.js
9147
+ function usePrefix({ status = "idle", theme }) {
9148
+ const [showLoader, setShowLoader] = useState(false);
9149
+ const [tick, setTick] = useState(0);
9150
+ const { prefix, spinner } = makeTheme(theme);
9151
+ useEffect(() => {
9152
+ if (status === "loading") {
9153
+ let tickInterval;
9154
+ let inc = -1;
9155
+ const delayTimeout = setTimeout(() => {
9156
+ setShowLoader(true);
9157
+ tickInterval = setInterval(() => {
9158
+ inc = inc + 1;
9159
+ setTick(inc % spinner.frames.length);
9160
+ }, spinner.interval);
9161
+ }, 300);
9162
+ return () => {
9163
+ clearTimeout(delayTimeout);
9164
+ clearInterval(tickInterval);
9165
+ };
9166
+ } else {
9167
+ setShowLoader(false);
9168
+ }
9169
+ }, [status]);
9170
+ if (showLoader) {
9171
+ return spinner.frames[tick];
9172
+ }
9173
+ const iconName = status === "loading" ? "idle" : status;
9174
+ return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
8513
9175
  }
8514
- if (process.platform === "linux") {
8515
- signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
9176
+
9177
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-ref.js
9178
+ function useRef(val) {
9179
+ return useState({ current: val })[0];
8516
9180
  }
8517
9181
 
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
9182
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-keypress.js
9183
+ function useKeypress(userHandler) {
9184
+ const signal = useRef(userHandler);
9185
+ signal.current = userHandler;
9186
+ useEffect((rl) => {
9187
+ let ignore = false;
9188
+ const handler = withUpdates((_input, event) => {
9189
+ if (ignore)
9190
+ return;
9191
+ void signal.current(event, rl);
8543
9192
  });
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();
9193
+ rl.input.on("keypress", handler);
9194
+ return () => {
9195
+ ignore = true;
9196
+ rl.input.removeListener("keypress", handler);
9197
+ };
9198
+ }, []);
9199
+ }
9200
+
9201
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/utils.js
9202
+ var import_cli_width = __toESM(require_cli_width(), 1);
9203
+
9204
+ // ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
9205
+ var getCodePointsLength = /* @__PURE__ */ (() => {
9206
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
9207
+ return (input) => {
9208
+ let surrogatePairsNr = 0;
9209
+ SURROGATE_PAIR_RE.lastIndex = 0;
9210
+ while (SURROGATE_PAIR_RE.test(input)) {
9211
+ surrogatePairsNr += 1;
8587
9212
  }
9213
+ return input.length - surrogatePairsNr;
8588
9214
  };
9215
+ })();
9216
+ var isFullWidth = (x) => {
9217
+ return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
8589
9218
  };
8590
- var SignalExitFallback = class extends SignalExitBase {
8591
- onExit() {
8592
- return () => {
8593
- };
8594
- }
8595
- load() {
8596
- }
8597
- unload() {
8598
- }
9219
+ var isWideNotCJKTNotEmoji = (x) => {
9220
+ 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
9221
  };
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;
9222
+
9223
+ // ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
9224
+ var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
9225
+ var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
9226
+ 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;
9227
+ var TAB_RE = /\t{1,1000}/y;
9228
+ 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");
9229
+ var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
9230
+ var MODIFIER_RE = new RegExp("\\p{M}+", "gu");
9231
+ var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
9232
+ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
9233
+ const LIMIT = truncationOptions.limit ?? Infinity;
9234
+ const ELLIPSIS = truncationOptions.ellipsis ?? "";
9235
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
9236
+ const ANSI_WIDTH = 0;
9237
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
9238
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
9239
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
9240
+ const FULL_WIDTH_WIDTH = 2;
9241
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
9242
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
9243
+ const PARSE_BLOCKS = [
9244
+ [LATIN_RE, REGULAR_WIDTH],
9245
+ [ANSI_RE, ANSI_WIDTH],
9246
+ [CONTROL_RE, CONTROL_WIDTH],
9247
+ [TAB_RE, TAB_WIDTH],
9248
+ [EMOJI_RE, EMOJI_WIDTH],
9249
+ [CJKT_WIDE_RE, WIDE_WIDTH]
9250
+ ];
9251
+ let indexPrev = 0;
9252
+ let index = 0;
9253
+ let length = input.length;
9254
+ let lengthExtra = 0;
9255
+ let truncationEnabled = false;
9256
+ let truncationIndex = length;
9257
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
9258
+ let unmatchedStart = 0;
9259
+ let unmatchedEnd = 0;
9260
+ let width = 0;
9261
+ let widthExtra = 0;
9262
+ outer: while (true) {
9263
+ if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
9264
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
9265
+ lengthExtra = 0;
9266
+ for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
9267
+ const codePoint = char.codePointAt(0) || 0;
9268
+ if (isFullWidth(codePoint)) {
9269
+ widthExtra = FULL_WIDTH_WIDTH;
9270
+ } else if (isWideNotCJKTNotEmoji(codePoint)) {
9271
+ widthExtra = WIDE_WIDTH;
9272
+ } else {
9273
+ widthExtra = REGULAR_WIDTH;
8623
9274
  }
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);
9275
+ if (width + widthExtra > truncationLimit) {
9276
+ truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
8630
9277
  }
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 (_) {
9278
+ if (width + widthExtra > LIMIT) {
9279
+ truncationEnabled = true;
9280
+ break outer;
9281
+ }
9282
+ lengthExtra += char.length;
9283
+ width += widthExtra;
8665
9284
  }
9285
+ unmatchedStart = unmatchedEnd = 0;
8666
9286
  }
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;
9287
+ if (index >= length) {
9288
+ break outer;
8696
9289
  }
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];
9290
+ for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
9291
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
9292
+ BLOCK_RE.lastIndex = index;
9293
+ if (BLOCK_RE.test(input)) {
9294
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
9295
+ widthExtra = lengthExtra * BLOCK_WIDTH;
9296
+ if (width + widthExtra > truncationLimit) {
9297
+ truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
9298
+ }
9299
+ if (width + widthExtra > LIMIT) {
9300
+ truncationEnabled = true;
9301
+ break outer;
9302
+ }
9303
+ width += widthExtra;
9304
+ unmatchedStart = indexPrev;
9305
+ unmatchedEnd = index;
9306
+ index = indexPrev = BLOCK_RE.lastIndex;
9307
+ continue outer;
8706
9308
  }
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
9309
  }
9310
+ index += 1;
8713
9311
  }
9312
+ return {
9313
+ width: truncationEnabled ? truncationLimit : width,
9314
+ index: truncationEnabled ? truncationIndex : length,
9315
+ truncated: truncationEnabled,
9316
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
9317
+ };
8714
9318
  };
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";
9319
+ var dist_default2 = getStringTruncatedWidth;
8747
9320
 
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`;
9321
+ // ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
9322
+ var NO_TRUNCATION2 = {
9323
+ limit: Infinity,
9324
+ ellipsis: "",
9325
+ ellipsisWidth: 0
8760
9326
  };
8761
- var eraseLine = ESC2 + "2K";
8762
- var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
9327
+ var fastStringWidth = (input, options = {}) => {
9328
+ return dist_default2(input, NO_TRUNCATION2, options).width;
9329
+ };
9330
+ var dist_default3 = fastStringWidth;
8763
9331
 
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);
9332
+ // ../../node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
9333
+ var ESC = "\x1B";
9334
+ var CSI = "\x9B";
9335
+ var END_CODE = 39;
9336
+ var ANSI_ESCAPE_BELL = "\x07";
9337
+ var ANSI_CSI = "[";
9338
+ var ANSI_OSC = "]";
9339
+ var ANSI_SGR_TERMINATOR = "m";
9340
+ var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
9341
+ var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
9342
+ var getClosingCode = (openingCode) => {
9343
+ if (openingCode >= 30 && openingCode <= 37)
9344
+ return 39;
9345
+ if (openingCode >= 90 && openingCode <= 97)
9346
+ return 39;
9347
+ if (openingCode >= 40 && openingCode <= 47)
9348
+ return 49;
9349
+ if (openingCode >= 100 && openingCode <= 107)
9350
+ return 49;
9351
+ if (openingCode === 1 || openingCode === 2)
9352
+ return 22;
9353
+ if (openingCode === 3)
9354
+ return 23;
9355
+ if (openingCode === 4)
9356
+ return 24;
9357
+ if (openingCode === 7)
9358
+ return 27;
9359
+ if (openingCode === 8)
9360
+ return 28;
9361
+ if (openingCode === 9)
9362
+ return 29;
9363
+ if (openingCode === 0)
9364
+ return 0;
9365
+ return void 0;
9366
+ };
9367
+ var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
9368
+ var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
9369
+ var wrapWord = (rows, word, columns) => {
9370
+ const characters = word[Symbol.iterator]();
9371
+ let isInsideEscape = false;
9372
+ let isInsideLinkEscape = false;
9373
+ let lastRow = rows.at(-1);
9374
+ let visible = lastRow === void 0 ? 0 : dist_default3(lastRow);
9375
+ let currentCharacter = characters.next();
9376
+ let nextCharacter = characters.next();
9377
+ let rawCharacterIndex = 0;
9378
+ while (!currentCharacter.done) {
9379
+ const character = currentCharacter.value;
9380
+ const characterLength = dist_default3(character);
9381
+ if (visible + characterLength <= columns) {
9382
+ rows[rows.length - 1] += character;
9383
+ } else {
9384
+ rows.push(character);
9385
+ visible = 0;
8788
9386
  }
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";
9387
+ if (character === ESC || character === CSI) {
9388
+ isInsideEscape = true;
9389
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
8796
9390
  }
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;
9391
+ if (isInsideEscape) {
9392
+ if (isInsideLinkEscape) {
9393
+ if (character === ANSI_ESCAPE_BELL) {
9394
+ isInsideEscape = false;
9395
+ isInsideLinkEscape = false;
9396
+ }
9397
+ } else if (character === ANSI_SGR_TERMINATOR) {
9398
+ isInsideEscape = false;
9399
+ }
9400
+ } else {
9401
+ visible += characterLength;
9402
+ if (visible === columns && !nextCharacter.done) {
9403
+ rows.push("");
9404
+ visible = 0;
9405
+ }
8812
9406
  }
9407
+ currentCharacter = nextCharacter;
9408
+ nextCharacter = characters.next();
9409
+ rawCharacterIndex += character.length;
8813
9410
  }
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();
9411
+ lastRow = rows.at(-1);
9412
+ if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
9413
+ rows[rows.length - 2] += rows.pop();
8822
9414
  }
8823
9415
  };
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);
9416
+ var stringVisibleTrimSpacesRight = (string) => {
9417
+ const words = string.split(" ");
9418
+ let last = words.length;
9419
+ while (last) {
9420
+ if (dist_default3(words[last - 1])) {
9421
+ break;
9422
+ }
9423
+ last--;
8833
9424
  }
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;
9425
+ if (last === words.length) {
9426
+ return string;
8849
9427
  }
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));
9428
+ return words.slice(0, last).join(" ") + words.slice(last).join("");
9429
+ };
9430
+ var exec = (string, columns, options = {}) => {
9431
+ if (options.trim !== false && string.trim() === "") {
9432
+ return "";
9433
+ }
9434
+ let returnValue = "";
9435
+ let escapeCode;
9436
+ let escapeUrl;
9437
+ const words = string.split(" ");
9438
+ let rows = [""];
9439
+ let rowLength = 0;
9440
+ for (let index = 0; index < words.length; index++) {
9441
+ const word = words[index];
9442
+ if (options.trim !== false) {
9443
+ const row = rows.at(-1) ?? "";
9444
+ const trimmed = row.trimStart();
9445
+ if (row.length !== trimmed.length) {
9446
+ rows[rows.length - 1] = trimmed;
9447
+ rowLength = dist_default3(trimmed);
8892
9448
  }
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();
9449
+ }
9450
+ if (index !== 0) {
9451
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
9452
+ rows.push("");
9453
+ rowLength = 0;
8938
9454
  }
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);
9455
+ if (rowLength || options.trim === false) {
9456
+ rows[rows.length - 1] += " ";
9457
+ rowLength++;
9458
+ }
9459
+ }
9460
+ const wordLength = dist_default3(word);
9461
+ if (options.hard && wordLength > columns) {
9462
+ const remainingColumns = columns - rowLength;
9463
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
9464
+ const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
9465
+ if (breaksStartingNextLine < breaksStartingThisLine) {
9466
+ rows.push("");
9467
+ }
9468
+ wrapWord(rows, word, columns);
9469
+ rowLength = dist_default3(rows.at(-1) ?? "");
9470
+ continue;
9471
+ }
9472
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
9473
+ if (options.wordWrap === false && rowLength < columns) {
9474
+ wrapWord(rows, word, columns);
9475
+ rowLength = dist_default3(rows.at(-1) ?? "");
9476
+ continue;
8958
9477
  }
8959
- return first.toUpperCase() + text.slice(1);
9478
+ rows.push("");
9479
+ rowLength = 0;
8960
9480
  }
9481
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
9482
+ wrapWord(rows, word, columns);
9483
+ rowLength = dist_default3(rows.at(-1) ?? "");
9484
+ continue;
9485
+ }
9486
+ rows[rows.length - 1] += word;
9487
+ rowLength += wordLength;
8961
9488
  }
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;
9489
+ if (options.trim !== false) {
9490
+ rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
8990
9491
  }
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;
9492
+ const preString = rows.join("\n");
9493
+ let inSurrogate = false;
9494
+ for (let i = 0; i < preString.length; i++) {
9495
+ const character = preString[i];
9496
+ returnValue += character;
9497
+ if (!inSurrogate) {
9498
+ inSurrogate = character >= "\uD800" && character <= "\uDBFF";
9499
+ if (inSurrogate) {
9500
+ continue;
9000
9501
  }
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
9502
  } else {
9010
- setValue(rl.line);
9011
- setError(void 0);
9503
+ inSurrogate = false;
9504
+ }
9505
+ if (character === ESC || character === CSI) {
9506
+ GROUP_REGEX.lastIndex = i + 1;
9507
+ const groupsResult = GROUP_REGEX.exec(preString);
9508
+ const groups = groupsResult?.groups;
9509
+ if (groups?.code !== void 0) {
9510
+ const code = Number.parseFloat(groups.code);
9511
+ escapeCode = code === END_CODE ? void 0 : code;
9512
+ } else if (groups?.uri !== void 0) {
9513
+ escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
9514
+ }
9515
+ }
9516
+ if (preString[i + 1] === "\n") {
9517
+ if (escapeUrl) {
9518
+ returnValue += wrapAnsiHyperlink("");
9519
+ }
9520
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
9521
+ if (escapeCode && closingCode) {
9522
+ returnValue += wrapAnsiCode(closingCode);
9523
+ }
9524
+ } else if (character === "\n") {
9525
+ if (escapeCode && getClosingCode(escapeCode)) {
9526
+ returnValue += wrapAnsiCode(escapeCode);
9527
+ }
9528
+ if (escapeUrl) {
9529
+ returnValue += wrapAnsiHyperlink(escapeUrl);
9530
+ }
9012
9531
  }
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
9532
  }
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] ?? "" };
9533
+ return returnValue;
9534
+ };
9535
+ var CRLF_OR_LF = /\r?\n/;
9536
+ function wrapAnsi(string, columns, options) {
9537
+ return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
9053
9538
  }
9054
9539
 
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) : [];
9540
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/utils.js
9541
+ function breakLines(content, width) {
9542
+ return content.split("\n").flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false }).split("\n").map((str) => str.trimEnd())).join("\n");
9073
9543
  }
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);
9082
- }
9083
- }
9084
- return catalog;
9544
+ function readlineWidth() {
9545
+ return (0, import_cli_width.default)({ defaultWidth: 80, output: readline().output });
9085
9546
  }
9086
9547
 
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
- };
9138
- }
9139
- function render(command, args) {
9140
- return [command, ...args].map(quote).join(" ");
9548
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/create-prompt.js
9549
+ import * as readline2 from "node:readline";
9550
+ import { AsyncResource as AsyncResource3 } from "node:async_hooks";
9551
+
9552
+ // ../../node_modules/.pnpm/@inquirer+type@4.2.0_@types+node@26.6.5/node_modules/@inquirer/type/dist/utils.js
9553
+ function withResolver() {
9554
+ let resolve6;
9555
+ let reject;
9556
+ const promise = new Promise((res, rej) => {
9557
+ resolve6 = res;
9558
+ reject = rej;
9559
+ });
9560
+ return { promise, resolve: resolve6, reject };
9141
9561
  }
9142
- function quote(arg) {
9143
- return /^[\w./:@%+=,-]+$/.test(arg) ? arg : `'${arg.replaceAll("'", "'\\''")}'`;
9562
+
9563
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/create-prompt.js
9564
+ var import_mute_stream = __toESM(require_lib(), 1);
9565
+
9566
+ // ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js
9567
+ var signals = [];
9568
+ signals.push("SIGHUP", "SIGINT", "SIGTERM");
9569
+ if (process.platform !== "win32") {
9570
+ signals.push(
9571
+ "SIGALRM",
9572
+ "SIGABRT",
9573
+ "SIGVTALRM",
9574
+ "SIGXCPU",
9575
+ "SIGXFSZ",
9576
+ "SIGUSR2",
9577
+ "SIGTRAP",
9578
+ "SIGSYS",
9579
+ "SIGQUIT",
9580
+ "SIGIOT"
9581
+ // should detect profiler and enable/disable accordingly.
9582
+ // see #21
9583
+ // 'SIGPROF'
9584
+ );
9585
+ }
9586
+ if (process.platform === "linux") {
9587
+ signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
9144
9588
  }
9145
9589
 
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)`;
9590
+ // ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js
9591
+ 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";
9592
+ var kExitEmitter = /* @__PURE__ */ Symbol.for("signal-exit emitter");
9593
+ var global = globalThis;
9594
+ var ObjectDefineProperty = Object.defineProperty.bind(Object);
9595
+ var Emitter = class {
9596
+ emitted = {
9597
+ afterExit: false,
9598
+ exit: false
9599
+ };
9600
+ listeners = {
9601
+ afterExit: [],
9602
+ exit: []
9603
+ };
9604
+ count = 0;
9605
+ id = Math.random();
9606
+ constructor() {
9607
+ if (global[kExitEmitter]) {
9608
+ return global[kExitEmitter];
9609
+ }
9610
+ ObjectDefineProperty(global, kExitEmitter, {
9611
+ value: this,
9612
+ writable: false,
9613
+ enumerable: false,
9614
+ configurable: false
9615
+ });
9155
9616
  }
9156
- }
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;
9617
+ on(ev, fn) {
9618
+ this.listeners[ev].push(fn);
9166
9619
  }
9167
- }
9168
-
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;
9620
+ removeListener(ev, fn) {
9621
+ const list2 = this.listeners[ev];
9622
+ const i = list2.indexOf(fn);
9623
+ if (i === -1) {
9624
+ return;
9625
+ }
9626
+ if (i === 0 && list2.length === 1) {
9627
+ list2.length = 0;
9628
+ } else {
9629
+ list2.splice(i, 1);
9630
+ }
9184
9631
  }
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
- `);
9632
+ emit(ev, code, signal) {
9633
+ if (this.emitted[ev]) {
9634
+ return false;
9635
+ }
9636
+ this.emitted[ev] = true;
9637
+ let ret = false;
9638
+ for (const fn of this.listeners[ev]) {
9639
+ ret = fn(code, signal) === true || ret;
9640
+ }
9641
+ if (ev === "exit") {
9642
+ ret = this.emit("afterExit", code, signal) || ret;
9643
+ }
9644
+ return ret;
9191
9645
  }
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
- `);
9646
+ };
9647
+ var SignalExitBase = class {
9648
+ };
9649
+ var signalExitWrap = (handler) => {
9650
+ return {
9651
+ onExit(cb, opts) {
9652
+ return handler.onExit(cb, opts);
9653
+ },
9654
+ load() {
9655
+ return handler.load();
9656
+ },
9657
+ unload() {
9658
+ return handler.unload();
9659
+ }
9660
+ };
9661
+ };
9662
+ var SignalExitFallback = class extends SignalExitBase {
9663
+ onExit() {
9664
+ return () => {
9665
+ };
9196
9666
  }
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
- `);
9667
+ load() {
9206
9668
  }
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);
9669
+ unload() {
9212
9670
  }
9213
- readFile(path3) {
9214
- this.say(`? read ${path3}`, 1);
9215
- return this.io.readFile(path3);
9671
+ };
9672
+ var SignalExit = class extends SignalExitBase {
9673
+ // "SIGHUP" throws an `ENOSYS` error on Windows,
9674
+ // so use a supported signal instead
9675
+ /* c8 ignore start */
9676
+ #hupSig = process3.platform === "win32" ? "SIGINT" : "SIGHUP";
9677
+ /* c8 ignore stop */
9678
+ #emitter = new Emitter();
9679
+ #process;
9680
+ #originalProcessEmit;
9681
+ #originalProcessReallyExit;
9682
+ #sigListeners = {};
9683
+ #loaded = false;
9684
+ constructor(process5) {
9685
+ super();
9686
+ this.#process = process5;
9687
+ this.#sigListeners = {};
9688
+ for (const sig of signals) {
9689
+ this.#sigListeners[sig] = () => {
9690
+ const listeners = this.#process.listeners(sig);
9691
+ let { count } = this.#emitter;
9692
+ const p = process5;
9693
+ if (typeof p.__signal_exit_emitter__ === "object" && typeof p.__signal_exit_emitter__.count === "number") {
9694
+ count += p.__signal_exit_emitter__.count;
9695
+ }
9696
+ if (listeners.length === count) {
9697
+ this.unload();
9698
+ const ret = this.#emitter.emit("exit", null, sig);
9699
+ const s = sig === "SIGHUP" ? this.#hupSig : sig;
9700
+ if (!ret)
9701
+ process5.kill(process5.pid, s);
9702
+ }
9703
+ };
9704
+ }
9705
+ this.#originalProcessReallyExit = process5.reallyExit;
9706
+ this.#originalProcessEmit = process5.emit;
9216
9707
  }
9217
- readDir(path3) {
9218
- this.say(`? list ${path3}`, 2);
9219
- return this.io.readDir(path3);
9708
+ onExit(cb, opts) {
9709
+ if (!processOk(this.#process)) {
9710
+ return () => {
9711
+ };
9712
+ }
9713
+ if (this.#loaded === false) {
9714
+ this.load();
9715
+ }
9716
+ const ev = opts?.alwaysLast ? "afterExit" : "exit";
9717
+ this.#emitter.on(ev, cb);
9718
+ return () => {
9719
+ this.#emitter.removeListener(ev, cb);
9720
+ if (this.#emitter.listeners["exit"].length === 0 && this.#emitter.listeners["afterExit"].length === 0) {
9721
+ this.unload();
9722
+ }
9723
+ };
9220
9724
  }
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;
9725
+ load() {
9726
+ if (this.#loaded) {
9727
+ return;
9230
9728
  }
9231
- if (!this.io.prompt)
9232
- throw new Error(`cannot ask "${question}" without a terminal; pass --yes`);
9233
- return this.io.prompt(question);
9729
+ this.#loaded = true;
9730
+ this.#emitter.count += 1;
9731
+ for (const sig of signals) {
9732
+ try {
9733
+ const fn = this.#sigListeners[sig];
9734
+ if (fn)
9735
+ this.#process.on(sig, fn);
9736
+ } catch (_) {
9737
+ }
9738
+ }
9739
+ this.#process.emit = (ev, ...a) => {
9740
+ return this.#processEmit(ev, ...a);
9741
+ };
9742
+ this.#process.reallyExit = (code) => {
9743
+ return this.#processReallyExit(code);
9744
+ };
9234
9745
  }
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);
9746
+ unload() {
9747
+ if (!this.#loaded) {
9748
+ return;
9244
9749
  }
9750
+ this.#loaded = false;
9751
+ signals.forEach((sig) => {
9752
+ const listener = this.#sigListeners[sig];
9753
+ if (!listener) {
9754
+ throw new Error("Listener not defined for signal: " + sig);
9755
+ }
9756
+ try {
9757
+ this.#process.removeListener(sig, listener);
9758
+ } catch (_) {
9759
+ }
9760
+ });
9761
+ this.#process.emit = this.#originalProcessEmit;
9762
+ this.#process.reallyExit = this.#originalProcessReallyExit;
9763
+ this.#emitter.count -= 1;
9245
9764
  }
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);
9765
+ #processReallyExit(code) {
9766
+ if (!processOk(this.#process)) {
9767
+ return 0;
9768
+ }
9769
+ this.#process.exitCode = code || 0;
9770
+ this.#emitter.emit("exit", this.#process.exitCode, null);
9771
+ return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode);
9772
+ }
9773
+ #processEmit(ev, ...args) {
9774
+ const og = this.#originalProcessEmit;
9775
+ if (ev === "exit" && processOk(this.#process)) {
9776
+ if (typeof args[0] === "number") {
9777
+ this.#process.exitCode = args[0];
9778
+ }
9779
+ const ret = og.call(this.#process, ev, ...args);
9780
+ this.#emitter.emit("exit", this.#process.exitCode, null);
9781
+ return ret;
9782
+ } else {
9783
+ return og.call(this.#process, ev, ...args);
9255
9784
  }
9256
9785
  }
9257
9786
  };
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
- }
9787
+ var process3 = globalThis.process;
9788
+ var {
9789
+ /**
9790
+ * Called when the process is exiting, whether via signal, explicit
9791
+ * exit, or running out of stuff to do.
9792
+ *
9793
+ * If the global process object is not suitable for instrumentation,
9794
+ * then this will be a no-op.
9795
+ *
9796
+ * Returns a function that may be used to unload signal-exit.
9797
+ */
9798
+ onExit,
9799
+ /**
9800
+ * Load the listeners. Likely you never need to call this, unless
9801
+ * doing a rather deep integration with signal-exit functionality.
9802
+ * Mostly exposed for the benefit of testing.
9803
+ *
9804
+ * @internal
9805
+ */
9806
+ load,
9807
+ /**
9808
+ * Unload the listeners. Likely you never need to call this, unless
9809
+ * doing a rather deep integration with signal-exit functionality.
9810
+ * Mostly exposed for the benefit of testing.
9811
+ *
9812
+ * @internal
9813
+ */
9814
+ unload
9815
+ } = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback());
9268
9816
 
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
- }
9817
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/screen-manager.js
9818
+ import { stripVTControlCharacters } from "node:util";
9284
9819
 
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`);
9820
+ // ../../node_modules/.pnpm/@inquirer+ansi@2.0.9/node_modules/@inquirer/ansi/dist/index.js
9821
+ var ESC2 = "\x1B[";
9822
+ var cursorLeft = ESC2 + "G";
9823
+ var cursorHide = ESC2 + "?25l";
9824
+ var cursorShow = ESC2 + "?25h";
9825
+ var cursorUp = (rows = 1) => rows > 0 ? `${ESC2}${rows}A` : "";
9826
+ var cursorDown = (rows = 1) => rows > 0 ? `${ESC2}${rows}B` : "";
9827
+ var cursorTo = (x, y) => {
9828
+ if (typeof y === "number" && !Number.isNaN(y)) {
9829
+ return `${ESC2}${y + 1};${x + 1}H`;
9317
9830
  }
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
- }
9831
+ return `${ESC2}${x + 1}G`;
9832
+ };
9833
+ var eraseLine = ESC2 + "2K";
9834
+ var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
9363
9835
 
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
- });
9836
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/screen-manager.js
9837
+ var height = (content) => content.split("\n").length;
9838
+ var lastLine = (content) => content.split("\n").pop() ?? "";
9839
+ var ScreenManager = class {
9840
+ // These variables are keeping information to allow correct prompt re-rendering
9841
+ height = 0;
9842
+ extraLinesUnderPrompt = 0;
9843
+ cursorPos;
9844
+ rl;
9845
+ constructor(rl) {
9846
+ this.rl = rl;
9847
+ this.cursorPos = rl.getCursorPos();
9405
9848
  }
9406
- if (files.has(MARKER_FILE)) {
9407
- await facet(ctx, dir, MARKER_FILE, (text) => {
9408
- dir.declaration = parseMarker(text);
9409
- });
9849
+ write(content) {
9850
+ this.rl.output.unmute();
9851
+ this.rl.output.write(content);
9852
+ this.rl.output.mute();
9853
+ }
9854
+ render(content, bottomContent = "") {
9855
+ const promptLine = lastLine(content);
9856
+ const rawPromptLine = stripVTControlCharacters(promptLine);
9857
+ let prompt = rawPromptLine;
9858
+ if (this.rl.line.length > 0) {
9859
+ prompt = prompt.slice(0, -this.rl.line.length);
9860
+ }
9861
+ this.rl.setPrompt(prompt);
9862
+ this.cursorPos = this.rl.getCursorPos();
9863
+ const width = readlineWidth();
9864
+ content = breakLines(content, width);
9865
+ bottomContent = breakLines(bottomContent, width);
9866
+ if (rawPromptLine.length % width === 0) {
9867
+ content += "\n";
9868
+ }
9869
+ let output = content + (bottomContent ? "\n" + bottomContent : "");
9870
+ const promptLineUpDiff = Math.floor(rawPromptLine.length / width) - this.cursorPos.rows;
9871
+ const bottomContentHeight = promptLineUpDiff + (bottomContent ? height(bottomContent) : 0);
9872
+ if (bottomContentHeight > 0)
9873
+ output += cursorUp(bottomContentHeight);
9874
+ output += cursorTo(this.cursorPos.cols);
9875
+ this.write(cursorDown(this.extraLinesUnderPrompt) + eraseLines(this.height) + output);
9876
+ this.extraLinesUnderPrompt = bottomContentHeight;
9877
+ this.height = height(output);
9878
+ }
9879
+ checkCursorPos() {
9880
+ const cursorPos = this.rl.getCursorPos();
9881
+ if (cursorPos.cols !== this.cursorPos.cols) {
9882
+ this.write(cursorTo(cursorPos.cols));
9883
+ this.cursorPos = cursorPos;
9884
+ }
9885
+ }
9886
+ done({ clearContent }) {
9887
+ this.rl.setPrompt("");
9888
+ let output = cursorDown(this.extraLinesUnderPrompt);
9889
+ output += clearContent ? eraseLines(this.height) : "\n";
9890
+ output += cursorLeft;
9891
+ output += cursorShow;
9892
+ this.write(output);
9893
+ this.rl.close();
9410
9894
  }
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);
9895
+ };
9896
+
9897
+ // ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/create-prompt.js
9898
+ import path from "node:path";
9899
+ var nativeSetImmediate = globalThis.setImmediate;
9900
+ var nativeClearImmediate = globalThis.clearImmediate;
9901
+ function listenTo(target, event, listener) {
9902
+ if ("on" in target) {
9903
+ target.on(event, listener);
9904
+ return () => target.removeListener(event, listener);
9416
9905
  }
9417
- return dir;
9906
+ target.addEventListener(event, listener);
9907
+ return () => target.removeEventListener(event, listener);
9418
9908
  }
9419
- async function facet(ctx, dir, file, read) {
9909
+ function getCallSites() {
9910
+ const savedPrepareStackTrace = Error.prepareStackTrace;
9911
+ let result = [];
9420
9912
  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)}`);
9913
+ Error.prepareStackTrace = (_, callSites) => {
9914
+ const callSitesWithoutCurrent = callSites.slice(1);
9915
+ result = callSitesWithoutCurrent;
9916
+ return callSitesWithoutCurrent;
9917
+ };
9918
+ new Error().stack;
9919
+ } catch {
9920
+ return result;
9425
9921
  }
9922
+ Error.prepareStackTrace = savedPrepareStackTrace;
9923
+ return result;
9426
9924
  }
9427
- async function git(ctx, cwd, args) {
9428
- try {
9429
- const out = (await ctx.read("git", args, { cwd })).trim();
9430
- return out === "" ? void 0 : out;
9431
- } catch {
9925
+ function createPrompt(view) {
9926
+ const callSites = getCallSites();
9927
+ const prompt = (config, context = {}) => {
9928
+ const { input = process.stdin, signal } = context;
9929
+ const cleanups = /* @__PURE__ */ new Set();
9930
+ const output = new import_mute_stream.default();
9931
+ output.pipe(context.output ?? process.stdout);
9932
+ const rl = readline2.createInterface({
9933
+ terminal: true,
9934
+ input,
9935
+ output
9936
+ });
9937
+ output.mute();
9938
+ const screen = new ScreenManager(rl);
9939
+ const { promise, resolve: resolve6, reject } = withResolver();
9940
+ return withHooks(rl, (cycle) => {
9941
+ const clearEffects = AsyncResource3.bind(() => effectScheduler.clearAll());
9942
+ const settlePrompt = (settle) => {
9943
+ try {
9944
+ clearEffects();
9945
+ settle();
9946
+ } catch (error) {
9947
+ reject(error);
9948
+ }
9949
+ };
9950
+ const resolvePrompt = (value) => settlePrompt(() => resolve6(value));
9951
+ const rejectPrompt = (error) => settlePrompt(() => reject(error));
9952
+ const promptPromise = Object.assign(promise.finally(() => {
9953
+ cleanups.forEach((cleanup) => cleanup());
9954
+ screen.done({ clearContent: Boolean(context.clearPromptOnDone) });
9955
+ output.end();
9956
+ }).then(() => promise), { cancel: () => rejectPrompt(new CancelPromptError()) });
9957
+ if (signal) {
9958
+ const abort = () => rejectPrompt(new AbortPromptError({ cause: signal.reason }));
9959
+ if (signal.aborted) {
9960
+ abort();
9961
+ return promptPromise;
9962
+ }
9963
+ cleanups.add(listenTo(signal, "abort", abort));
9964
+ }
9965
+ cleanups.add(onExit((code, signal2) => {
9966
+ rejectPrompt(new ExitPromptError(`User force closed the prompt with ${code} ${signal2}`));
9967
+ }));
9968
+ cleanups.add(listenTo(rl, "SIGINT", () => rejectPrompt(new ExitPromptError(`User force closed the prompt with SIGINT`))));
9969
+ cleanups.add(listenTo(rl, "close", clearEffects));
9970
+ const startCycle = () => {
9971
+ cleanups.add(listenTo(rl.input, "keypress", () => screen.checkCursorPos()));
9972
+ let pendingDone = null;
9973
+ cycle(() => {
9974
+ let effectsSettled = false;
9975
+ try {
9976
+ const nextView = view(config, (value) => {
9977
+ if (effectsSettled) {
9978
+ resolvePrompt(value);
9979
+ } else {
9980
+ pendingDone = { value };
9981
+ }
9982
+ });
9983
+ if (nextView === void 0) {
9984
+ let callerFilename = callSites[1]?.getFileName();
9985
+ if (callerFilename && !callerFilename.startsWith("file://")) {
9986
+ callerFilename = path.resolve(callerFilename);
9987
+ }
9988
+ throw new Error(`Prompt functions must return a string.
9989
+ at ${callerFilename}`);
9990
+ }
9991
+ const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
9992
+ screen.render(content, bottomContent);
9993
+ effectScheduler.run();
9994
+ } catch (error) {
9995
+ rejectPrompt(error);
9996
+ }
9997
+ effectsSettled = true;
9998
+ if (pendingDone !== null) {
9999
+ const { value } = pendingDone;
10000
+ pendingDone = null;
10001
+ resolvePrompt(value);
10002
+ }
10003
+ });
10004
+ };
10005
+ if ("readableFlowing" in input) {
10006
+ const immediate = nativeSetImmediate(startCycle);
10007
+ cleanups.add(() => nativeClearImmediate(immediate));
10008
+ } else {
10009
+ startCycle();
10010
+ }
10011
+ return promptPromise;
10012
+ });
10013
+ };
10014
+ return prompt;
10015
+ }
10016
+
10017
+ // ../../node_modules/.pnpm/@inquirer+confirm@6.3.4_@types+node@26.6.5/node_modules/@inquirer/confirm/dist/index.js
10018
+ import { styleText as styleText2 } from "node:util";
10019
+ var confirmTheme = {
10020
+ keywords: {
10021
+ yes: "Yes",
10022
+ no: "No",
10023
+ error: ({ yes, no }) => `You must answer with "${yes}" or "${no}"`
10024
+ },
10025
+ style: {
10026
+ confirmDefault: (text) => {
10027
+ const first = text[0] ?? "";
10028
+ if (first.toLowerCase() === first.toUpperCase()) {
10029
+ return styleText2("cyan", text);
10030
+ }
10031
+ return first.toUpperCase() + text.slice(1);
10032
+ }
10033
+ }
10034
+ };
10035
+ var dist_default4 = createPrompt((config, done) => {
10036
+ const [status, setStatus] = useState("idle");
10037
+ const [value, setValue] = useState("");
10038
+ const [errorMsg, setError] = useState();
10039
+ const theme = makeTheme(confirmTheme, config.theme);
10040
+ const prefix = usePrefix({ status, theme });
10041
+ const { yes, no } = theme.keywords;
10042
+ const yesHint = (yes[0] ?? "").toLowerCase();
10043
+ const noHint = (no[0] ?? "").toLowerCase();
10044
+ const hint = config.default === false ? `${yesHint}/${theme.style.confirmDefault(noHint)}` : `${theme.style.confirmDefault(yesHint)}/${noHint}`;
10045
+ function boolToString(value2) {
10046
+ return value2 ? yes : no;
10047
+ }
10048
+ const { transformer = boolToString } = config;
10049
+ function getBooleanValue(value2) {
10050
+ const v = value2.trim().toLowerCase();
10051
+ if (v === "")
10052
+ return config.default !== false;
10053
+ if (yes.toLowerCase().startsWith(v))
10054
+ return true;
10055
+ if (no.toLowerCase().startsWith(v))
10056
+ return false;
10057
+ if ("yes".startsWith(v))
10058
+ return true;
10059
+ if ("no".startsWith(v))
10060
+ return false;
9432
10061
  return void 0;
9433
10062
  }
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;
10063
+ useKeypress((key, rl) => {
10064
+ if (status !== "idle")
10065
+ return;
10066
+ if (isEnterKey(key)) {
10067
+ const answer = getBooleanValue(value);
10068
+ if (answer === void 0) {
10069
+ rl.write(value);
10070
+ setError(theme.keywords.error({ yes, no }));
10071
+ return;
10072
+ }
10073
+ setValue(transformer(answer));
10074
+ setStatus("done");
10075
+ done(answer);
10076
+ } else if (isTabKey(key)) {
10077
+ const answer = boolToString(!(getBooleanValue(value) ?? config.default !== false));
10078
+ rl.clearLine(0);
10079
+ rl.write(answer);
10080
+ setValue(answer);
10081
+ } else {
10082
+ setValue(rl.line);
10083
+ setError(void 0);
10084
+ }
10085
+ });
10086
+ let formattedValue = value;
10087
+ let defaultValue = "";
10088
+ if (status === "done") {
10089
+ formattedValue = theme.style.answer(value);
10090
+ } else {
10091
+ defaultValue = ` ${theme.style.defaultAnswer(hint)}`;
9445
10092
  }
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;
9453
- }
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 } : {};
9457
- }
10093
+ const message = theme.style.message(config.message, status);
10094
+ let error = "";
10095
+ if (errorMsg) {
10096
+ error = theme.style.error(errorMsg);
10097
+ }
10098
+ return [`${prefix} ${message}${defaultValue} ${formattedValue}`, error];
10099
+ });
9458
10100
 
9459
10101
  // ../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js
9460
10102
  var CommanderError = class extends Error {
@@ -10885,8 +11527,8 @@ var Command = class _Command extends EventEmitter {
10885
11527
  * @return {Command} `this` command for chaining
10886
11528
  */
10887
11529
  arguments(names) {
10888
- names.trim().split(/ +/).forEach((detail) => {
10889
- this.argument(detail);
11530
+ names.trim().split(/ +/).forEach((detail2) => {
11531
+ this.argument(detail2);
10890
11532
  });
10891
11533
  return this;
10892
11534
  }
@@ -12826,7 +13468,7 @@ var program = new Command();
12826
13468
 
12827
13469
  // src/commands/doctor.ts
12828
13470
  import { existsSync } from "node:fs";
12829
- import { join as join3, resolve } from "node:path";
13471
+ import { join as join7, resolve } from "node:path";
12830
13472
 
12831
13473
  // src/style.ts
12832
13474
  function style(enabled) {
@@ -12844,8 +13486,8 @@ function register(program2) {
12844
13486
  ).option("--color", "colour the report even when piped").option("--no-color", "never colour the report").action(async (dir, opts, command) => {
12845
13487
  const ctx = contextOf2(command);
12846
13488
  const root = resolve(dir);
12847
- const compendium = resolve(opts.compendium ?? join3(root, WORKSPACE_COMPENDIUM));
12848
- if (!existsSync(join3(compendium, "contracts")))
13489
+ const compendium = resolve(opts.compendium ?? join7(root, WORKSPACE_COMPENDIUM));
13490
+ if (!existsSync(join7(compendium, "contracts")))
12849
13491
  throw new Error(
12850
13492
  `no compendium at ${compendium}; pass --compendium <path to a checkout of plexus-ms/compendium>`
12851
13493
  );
@@ -12919,8 +13561,68 @@ function annotate(dir, s, modules) {
12919
13561
  return tags.length ? ` ${tags.join(" ")}` : "";
12920
13562
  }
12921
13563
 
13564
+ // src/commands/propagate.ts
13565
+ import { resolve as resolve4 } from "node:path";
13566
+
13567
+ // src/commands/ship.ts
13568
+ import { resolve as resolve3 } from "node:path";
13569
+ function register3(program2) {
13570
+ 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) => {
13571
+ const ctx = contextOf2(command);
13572
+ const result = await ship(ctx, { workspace: resolve3(dir), train: opts.train });
13573
+ ctx.result(result, (r) => renderSummary(r, `plx -y ship --train ${r.train} ${dir}`));
13574
+ if (!isClean(result)) process.exitCode = 1;
13575
+ });
13576
+ }
13577
+ function renderSummary(s, realCommand) {
13578
+ 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"];
13579
+ for (const p of s.clean) lines.push(` \u2713 clean: ${p}`);
13580
+ for (const p of s.conflicted) lines.push(` \u2717 conflicts: ${p}`);
13581
+ for (const p of s.failed) lines.push(` \u2717 failed: ${p}`);
13582
+ for (const { path: path3, reason } of s.skipped) lines.push(` \u26A0 skipped: ${path3} (${reason})`);
13583
+ const clean = isClean(s);
13584
+ if (s.preview) {
13585
+ lines.push(" (preview only \u2014 nothing was changed)");
13586
+ if (clean) lines.push(`\u2713 dry run clean \u2014 run it for real: ${realCommand}`);
13587
+ } else if (clean) {
13588
+ lines.push("\u2713 done \u2014 review consumer diffs, commit (web repos on develop, platform repos on main), push");
13589
+ }
13590
+ if (!clean) lines.push("\u2717 needs attention \u2014 see above; fix the consumer, then re-run propagate");
13591
+ return lines.join("\n");
13592
+ }
13593
+
13594
+ // src/commands/propagate.ts
13595
+ function register4(program2) {
13596
+ 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) => {
13597
+ const ctx = contextOf2(command);
13598
+ const result = await ship(ctx, { workspace: resolve4(dir), train: opts.train, propagateOnly: true });
13599
+ ctx.result(result, (r) => renderSummary(r, `plx -y propagate --train ${r.train} ${dir}`));
13600
+ if (!isClean(result)) process.exitCode = 1;
13601
+ });
13602
+ }
13603
+
13604
+ // src/commands/requirements.ts
13605
+ import { join as join8, resolve as resolve5 } from "node:path";
13606
+ function register5(program2) {
13607
+ 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) => {
13608
+ const ctx = contextOf2(command);
13609
+ const compendium = resolve5(dir);
13610
+ if (opts.extract) {
13611
+ ctx.result(extractRequirements(await ctx.readFile(join8(compendium, opts.extract))));
13612
+ return;
13613
+ }
13614
+ const check = await checkCompendium(ctx, compendium);
13615
+ ctx.result(check, renderCheck);
13616
+ if (check.defects.length > 0) process.exitCode = 1;
13617
+ });
13618
+ }
13619
+ function renderCheck(c) {
13620
+ if (c.defects.length > 0) return c.defects.join("\n");
13621
+ return `\u2713 the map, ${c.contracts} contracts and ${c.approaches} approaches are well-formed`;
13622
+ }
13623
+
12922
13624
  // src/commands/index.ts
12923
- var commands = [register2, register];
13625
+ var commands = [register2, register, register3, register4, register5];
12924
13626
 
12925
13627
  // src/program.ts
12926
13628
  var { version, description } = createRequire(import.meta.url)("../package.json");
@@ -12929,7 +13631,7 @@ function buildProgram() {
12929
13631
  program2.addOption(new Option("-n, --dry-run", "print every effect this run would have, perform none").env("PLX_DRY_RUN")).addOption(
12930
13632
  new Option("-v, --verbose", "say more: once for reads and inputs, twice for command output").argParser((_value, previous) => previous + 1).default(0)
12931
13633
  ).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);
13634
+ for (const register6 of commands) register6(program2);
12933
13635
  return program2;
12934
13636
  }
12935
13637
  function contextOf2(command) {
@@ -12947,5 +13649,5 @@ try {
12947
13649
  const message = error instanceof Error ? error.message : String(error);
12948
13650
  process.stderr.write(`\u2717 ${message}
12949
13651
  `);
12950
- process.exitCode = 1;
13652
+ process.exitCode = error instanceof UsageError ? 2 : 1;
12951
13653
  }