@plexus-ms/lib 0.1.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.
- package/LICENSE +674 -0
- package/dist/bookkeeping.d.ts +26 -0
- package/dist/bookkeeping.d.ts.map +1 -0
- package/dist/bookkeeping.js +51 -0
- package/dist/bookkeeping.js.map +1 -0
- package/dist/catalog.d.ts +23 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +38 -0
- package/dist/catalog.js.map +1 -0
- package/dist/consumers.d.ts +31 -0
- package/dist/consumers.d.ts.map +1 -0
- package/dist/consumers.js +70 -0
- package/dist/consumers.js.map +1 -0
- package/dist/context.d.ts +7 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +19 -3
- package/dist/context.js.map +1 -1
- package/dist/doctor.d.ts +19 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +79 -0
- package/dist/doctor.js.map +1 -0
- package/dist/frontmatter.d.ts +9 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +42 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/io.d.ts +5 -1
- package/dist/io.d.ts.map +1 -1
- package/dist/io.js +5 -1
- package/dist/io.js.map +1 -1
- package/dist/overview.d.ts +5 -1
- package/dist/overview.d.ts.map +1 -1
- package/dist/overview.js +6 -7
- package/dist/overview.js.map +1 -1
- package/dist/plan.d.ts +2 -0
- package/dist/plan.d.ts.map +1 -1
- package/dist/plan.js.map +1 -1
- package/dist/propagate.d.ts +20 -0
- package/dist/propagate.d.ts.map +1 -0
- package/dist/propagate.js +226 -0
- package/dist/propagate.js.map +1 -0
- package/dist/requirements.d.ts +27 -0
- package/dist/requirements.d.ts.map +1 -0
- package/dist/requirements.js +188 -0
- package/dist/requirements.js.map +1 -0
- package/dist/ship.d.ts +18 -0
- package/dist/ship.d.ts.map +1 -0
- package/dist/ship.js +131 -0
- package/dist/ship.js.map +1 -0
- package/dist/train.d.ts +45 -0
- package/dist/train.d.ts.map +1 -0
- package/dist/train.js +102 -0
- package/dist/train.js.map +1 -0
- package/package.json +9 -10
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// The requirements check (§ 1.8 PLX), the compendium's `requirements.sh`
|
|
2
|
+
// moved: a verb, not a system.
|
|
3
|
+
//
|
|
4
|
+
// scanPage one page: its defects, and for a standard module its
|
|
5
|
+
// requirement lines, `§ <section> <text>`, in page order
|
|
6
|
+
// checkCompendium the map and every module page, plus the cross-page rules:
|
|
7
|
+
// unique codes, known dependencies, dependencies that respect
|
|
8
|
+
// the seams (§ 1.3 PLX)
|
|
9
|
+
//
|
|
10
|
+
// The map carries no requirements and no BCP 14 keyword. A module at standard
|
|
11
|
+
// maturity carries its requirements as blockquoted bullets ("> - ") under
|
|
12
|
+
// numbered section headings; a keyword anywhere else, a blockquote that is not
|
|
13
|
+
// such a bullet, or any keyword or blockquote in a module below standard
|
|
14
|
+
// maturity is a defect. The trailing "## Maintaining" section is prose
|
|
15
|
+
// throughout. Extraction is structural: no classification, no heuristics.
|
|
16
|
+
// `ship` compares a module's extracted lines across trains to stamp `changed`,
|
|
17
|
+
// so the extractor and the linter are one function and cannot disagree.
|
|
18
|
+
//
|
|
19
|
+
// plx requirements <compendium> # lint; exit 1 on any defect
|
|
20
|
+
// plx requirements --extract contracts/app.md
|
|
21
|
+
import { join } from 'node:path';
|
|
22
|
+
import { CATALOG_DIRS } from "./catalog.js";
|
|
23
|
+
const KEYWORD = /MUST|SHOULD|MAY/;
|
|
24
|
+
/** A BCP 14 keyword in a line, the informal plurals (MUSTs, SHOULDs, MAYs) not counting. */
|
|
25
|
+
const hasKeyword = (line) => KEYWORD.test(line.replace(/MUSTs|SHOULDs|MAYs/g, ''));
|
|
26
|
+
/** A bracketed, comma-separated list as the frontmatter writes it: `[A, B]`. */
|
|
27
|
+
const list = (value) => value
|
|
28
|
+
.replace(/^\s*\[/, '')
|
|
29
|
+
.replace(/\].*$/, '')
|
|
30
|
+
.split(',')
|
|
31
|
+
.map((s) => s.trim())
|
|
32
|
+
.filter(Boolean);
|
|
33
|
+
export function scanPage(text, name, mode) {
|
|
34
|
+
const scan = { defects: [], requirements: [], depends: [], consumes: [] };
|
|
35
|
+
const lines = text.split('\n');
|
|
36
|
+
const defect = (n, msg) => scan.defects.push(`✗ ${name}: line ${n + 1}: ${msg}`);
|
|
37
|
+
let i = 0;
|
|
38
|
+
if (lines[0] === '---') {
|
|
39
|
+
for (i = 1; i < lines.length && lines[i] !== '---'; i++) {
|
|
40
|
+
const line = lines[i] ?? '';
|
|
41
|
+
const [key = '', ...rest] = line.split(/\s+/);
|
|
42
|
+
const value = rest.join(' ');
|
|
43
|
+
if (key === 'maturity:')
|
|
44
|
+
scan.maturity = rest[0];
|
|
45
|
+
else if (key === 'code:')
|
|
46
|
+
scan.code = rest[0];
|
|
47
|
+
else if (key === 'binds:')
|
|
48
|
+
scan.binds = rest[0];
|
|
49
|
+
else if (key === 'depends:')
|
|
50
|
+
scan.depends = list(value);
|
|
51
|
+
else if (key === 'consumes:')
|
|
52
|
+
scan.consumes = list(value);
|
|
53
|
+
else if (key === 'kind:')
|
|
54
|
+
defect(i, 'kind is the folder, contracts/ or approaches/, not a field');
|
|
55
|
+
}
|
|
56
|
+
i++;
|
|
57
|
+
}
|
|
58
|
+
let inCode = false;
|
|
59
|
+
let maintaining = false;
|
|
60
|
+
let started = false;
|
|
61
|
+
let section = '';
|
|
62
|
+
for (; i < lines.length; i++) {
|
|
63
|
+
const line = lines[i] ?? '';
|
|
64
|
+
if (line.startsWith('```')) {
|
|
65
|
+
inCode = !inCode;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (inCode)
|
|
69
|
+
continue;
|
|
70
|
+
if (line === '## Maintaining') {
|
|
71
|
+
maintaining = true;
|
|
72
|
+
section = '';
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const heading = /^#+ § (\S+)/.exec(line);
|
|
76
|
+
if (heading) {
|
|
77
|
+
if (maintaining)
|
|
78
|
+
defect(i, 'numbered section after Maintaining');
|
|
79
|
+
section = heading[1] ?? '';
|
|
80
|
+
started = true;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (line.startsWith('> - ')) {
|
|
84
|
+
if (mode === 'map')
|
|
85
|
+
defect(i, `requirement in the map: ${line}`);
|
|
86
|
+
else if (scan.maturity !== 'standard')
|
|
87
|
+
defect(i, `requirement in a module at ${scan.maturity} maturity: ${line}`);
|
|
88
|
+
else if (maintaining)
|
|
89
|
+
defect(i, `requirement under Maintaining: ${line}`);
|
|
90
|
+
else if (!started)
|
|
91
|
+
defect(i, 'requirement before the first § heading');
|
|
92
|
+
else
|
|
93
|
+
scan.requirements.push(`§ ${section} ${line.slice(4)}`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (line.startsWith('>')) {
|
|
97
|
+
defect(i, 'blockquote line is not a "> - " requirement bullet');
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (hasKeyword(line))
|
|
101
|
+
defect(i, `BCP 14 keyword outside a requirement: ${line}`);
|
|
102
|
+
}
|
|
103
|
+
if (mode === 'module') {
|
|
104
|
+
const { maturity = '', binds = '', code = '' } = scan;
|
|
105
|
+
// Reported at the page's last line, like awk's NR at END.
|
|
106
|
+
const n = text.endsWith('\n') ? lines.length - 1 : lines.length;
|
|
107
|
+
if (!/^(note|candidate|standard)$/.test(maturity))
|
|
108
|
+
defect(n - 1, `maturity must be note, candidate or standard, not "${maturity}"`);
|
|
109
|
+
if (!/^(repo|app|host|organisation)$/.test(binds))
|
|
110
|
+
defect(n - 1, `binds must be repo, app, host or organisation, not "${binds}"`);
|
|
111
|
+
if (maturity === 'note' && code !== '')
|
|
112
|
+
defect(n - 1, 'a note carries no code');
|
|
113
|
+
if (maturity !== 'note' && !/^PLX-[A-Z][A-Za-z]+$/.test(code))
|
|
114
|
+
defect(n - 1, `code must be PLX- plus one capitalised word, not "${code}"`);
|
|
115
|
+
}
|
|
116
|
+
return scan;
|
|
117
|
+
}
|
|
118
|
+
/** The requirement lines of a page, defects ignored: what `changed` compares across trains. */
|
|
119
|
+
export const extractRequirements = (text) => scanPage(text, '', 'module').requirements;
|
|
120
|
+
export const MAP_PAGE = 'essentials/standard.md';
|
|
121
|
+
/** Every module page of a compendium checkout: `<dir>/<file>`, sorted, index pages left out. */
|
|
122
|
+
export async function modulePages(ctx, compendium) {
|
|
123
|
+
const pages = [];
|
|
124
|
+
for (const dir of Object.keys(CATALOG_DIRS)) {
|
|
125
|
+
const entries = await ctx.readDir(join(compendium, dir));
|
|
126
|
+
for (const e of entries.filter((e) => !e.directory && e.name.endsWith('.md') && e.name !== 'index.md').sort())
|
|
127
|
+
pages.push(`${dir}/${e.name}`);
|
|
128
|
+
}
|
|
129
|
+
return pages;
|
|
130
|
+
}
|
|
131
|
+
export async function checkCompendium(ctx, compendium) {
|
|
132
|
+
const defects = [];
|
|
133
|
+
defects.push(...scanPage(await ctx.readFile(join(compendium, MAP_PAGE)), MAP_PAGE, 'map').defects);
|
|
134
|
+
const pages = await modulePages(ctx, compendium);
|
|
135
|
+
const scans = new Map();
|
|
136
|
+
for (const page of pages) {
|
|
137
|
+
const scan = scanPage(await ctx.readFile(join(compendium, page)), page, 'module');
|
|
138
|
+
defects.push(...scan.defects);
|
|
139
|
+
scans.set(page, scan);
|
|
140
|
+
}
|
|
141
|
+
// Module codes are unique across pages.
|
|
142
|
+
const byCode = new Map();
|
|
143
|
+
for (const [page, s] of scans)
|
|
144
|
+
if (s.code)
|
|
145
|
+
byCode.set(s.code, [...(byCode.get(s.code) ?? []), page]);
|
|
146
|
+
for (const [code, where] of byCode)
|
|
147
|
+
if (where.length > 1)
|
|
148
|
+
defects.push(`✗ duplicate module code: ${code}`);
|
|
149
|
+
// Every declared dependency names a module that exists.
|
|
150
|
+
for (const s of scans.values())
|
|
151
|
+
for (const dep of s.depends)
|
|
152
|
+
if (!byCode.has(dep))
|
|
153
|
+
defects.push(`✗ unknown module in depends: ${dep}`);
|
|
154
|
+
// Dependencies respect the seams (§ 1.3 PLX): a contract depends only on
|
|
155
|
+
// contracts, a dependency never crosses from the dev side (repo, app) to the
|
|
156
|
+
// ops side (host, organisation) or back, and what crosses a seam is listed
|
|
157
|
+
// under consumes and is a contract.
|
|
158
|
+
const kindOf = (page) => (page.startsWith('contracts/') ? 'contract' : 'approach');
|
|
159
|
+
const side = (binds) => (binds === 'repo' || binds === 'app' ? 'dev' : 'ops');
|
|
160
|
+
const kinds = new Map([...byCode].map(([code, [page = '']]) => [code, kindOf(page)]));
|
|
161
|
+
const binds = new Map([...byCode].map(([code, [page = '']]) => [code, scans.get(page)?.binds ?? '']));
|
|
162
|
+
for (const [page, s] of scans) {
|
|
163
|
+
const m = s.code ?? page.replace(/.*\//, '');
|
|
164
|
+
const kind = kindOf(page);
|
|
165
|
+
for (const c of s.consumes) {
|
|
166
|
+
if (kind === 'contract')
|
|
167
|
+
defects.push(`✗ ${m} is a contract and consumes ${c}; a contract has no other side to consume`);
|
|
168
|
+
else if (kinds.has(c) && kinds.get(c) !== 'contract')
|
|
169
|
+
defects.push(`✗ ${m} consumes ${c}, which is an approach; only a contract is consumed across a seam`);
|
|
170
|
+
else if (!kinds.has(c))
|
|
171
|
+
defects.push(`✗ ${m} consumes unknown module ${c}`);
|
|
172
|
+
}
|
|
173
|
+
for (const d of s.depends) {
|
|
174
|
+
if (!kinds.has(d))
|
|
175
|
+
continue;
|
|
176
|
+
if (kind === 'contract' && kinds.get(d) !== 'contract')
|
|
177
|
+
defects.push(`✗ ${m} is a contract and depends on the approach ${d}`);
|
|
178
|
+
if (side(s.binds ?? '') !== side(binds.get(d) ?? '') && kinds.get(d) !== 'contract')
|
|
179
|
+
defects.push(`✗ ${m} (${s.binds}) depends on ${d} (${binds.get(d)}) across the dev/ops seam; only a contract may be depended on across a seam`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
defects,
|
|
184
|
+
contracts: pages.filter((p) => p.startsWith('contracts/')).length,
|
|
185
|
+
approaches: pages.filter((p) => p.startsWith('approaches/')).length,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=requirements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements.js","sourceRoot":"","sources":["../src/requirements.ts"],"names":[],"mappings":"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"}
|
package/dist/ship.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Context } from './context.ts';
|
|
2
|
+
import { type Summary } from './propagate.ts';
|
|
3
|
+
export interface ShipOptions {
|
|
4
|
+
/** The workspace: the upstream umbrella and the consumers sit under it. */
|
|
5
|
+
workspace: string;
|
|
6
|
+
/** The train version; default: minor+1 over the latest, or the current one when only propagating. */
|
|
7
|
+
train?: string;
|
|
8
|
+
/** Skip the release; only propagate to the consumers. */
|
|
9
|
+
propagateOnly?: boolean;
|
|
10
|
+
/** The date stamped on the map, `YYYY-MM-DD`; default: today. */
|
|
11
|
+
today?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ShipResult extends Summary {
|
|
14
|
+
/** The version released, or already current when only propagating. */
|
|
15
|
+
released: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function ship(ctx: Context, options: ShipOptions): Promise<ShipResult>;
|
|
18
|
+
//# sourceMappingURL=ship.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ship.d.ts","sourceRoot":"","sources":["../src/ship.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,OAAO,EAAa,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAIzD,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,qGAAqG;IACrG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAW,SAAQ,OAAO;IACzC,sEAAsE;IACtE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CASlF"}
|
package/dist/ship.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// ship: the release train (§ 1.5 PLX). Every train repo ships under ONE
|
|
2
|
+
// version, tagged identically whether or not it changed:
|
|
3
|
+
//
|
|
4
|
+
// preflight (every train repo on main, clean, not behind origin, the latest
|
|
5
|
+
// tags in agreement) → write the train bookkeeping (bookkeeping.ts: galaxy
|
|
6
|
+
// version, the preset's collection pin, workflow-ref examples, the map's
|
|
7
|
+
// version and timestamp, `changed` on every standard module whose extracted
|
|
8
|
+
// requirements moved) and commit it → tag every train repo → push →
|
|
9
|
+
// propagate to every consumer (propagate.ts).
|
|
10
|
+
//
|
|
11
|
+
// Substance commits stay human; ship writes only the mechanical bookkeeping.
|
|
12
|
+
// A failure between the first tag and the last push leaves a half-tagged
|
|
13
|
+
// train; the recovery is a re-run naming the same version, which skips the
|
|
14
|
+
// repos already tagged and pushes the rest.
|
|
15
|
+
//
|
|
16
|
+
// plx ship ~/dev # next train = minor+1 over the latest
|
|
17
|
+
// plx ship ~/dev --train 1.0.0 # explicit train version
|
|
18
|
+
// plx -n ship ~/dev # preview: list the bookkeeping, tags and
|
|
19
|
+
// # the propagation in scratch clones
|
|
20
|
+
// plx -y ship ~/dev # unattended: no prompt, copier takes defaults
|
|
21
|
+
import { join } from 'node:path';
|
|
22
|
+
import { bumpCollectionPin, bumpGalaxyVersion, bumpWorkflowRefs, stampChanged, stampStandard, today as todayOf, WORKFLOW_REF, } from "./bookkeeping.js";
|
|
23
|
+
import { frontmatterField } from "./frontmatter.js";
|
|
24
|
+
import { run, write } from "./plan.js";
|
|
25
|
+
import { propagate } from "./propagate.js";
|
|
26
|
+
import { extractRequirements, MAP_PAGE, modulePages } from "./requirements.js";
|
|
27
|
+
import { preflightRelease, readTrain, resolveVersion, UPSTREAM } from "./train.js";
|
|
28
|
+
export async function ship(ctx, options) {
|
|
29
|
+
const upstream = join(options.workspace, UPSTREAM);
|
|
30
|
+
const propagateOnly = options.propagateOnly ?? false;
|
|
31
|
+
const train = await readTrain(ctx, upstream);
|
|
32
|
+
if (!propagateOnly)
|
|
33
|
+
await preflightRelease(ctx, train);
|
|
34
|
+
const next = resolveVersion(train, options.train, propagateOnly);
|
|
35
|
+
if (!propagateOnly)
|
|
36
|
+
await release(ctx, train, next, options.today ?? todayOf());
|
|
37
|
+
const summary = await propagate(ctx, options.workspace, next);
|
|
38
|
+
return { ...summary, released: !propagateOnly };
|
|
39
|
+
}
|
|
40
|
+
async function release(ctx, train, next, today) {
|
|
41
|
+
ctx.say(`→ train ${train.last ?? 'none'} → ${next}`);
|
|
42
|
+
for (const repo of train.repos) {
|
|
43
|
+
if (repo.pending.length === 0)
|
|
44
|
+
ctx.say(` ${repo.name}: no changes since ${repo.latest} — tag only`);
|
|
45
|
+
else {
|
|
46
|
+
ctx.say(` ${repo.name} (since ${repo.latest ?? 'the beginning'}):`);
|
|
47
|
+
for (const line of repo.pending)
|
|
48
|
+
ctx.say(` ${line}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (!(await ctx.confirm(`tag all ${train.repos.length} repos as ${next} and push?`)))
|
|
52
|
+
throw new Error('aborted');
|
|
53
|
+
try {
|
|
54
|
+
const plan = await planBookkeeping(ctx, train, next, today);
|
|
55
|
+
await ctx.apply(plan);
|
|
56
|
+
for (const repo of train.repos) {
|
|
57
|
+
const tagged = await ctx
|
|
58
|
+
.read('git', ['rev-parse', '-q', '--verify', `refs/tags/${next}`], { cwd: repo.path })
|
|
59
|
+
.then(() => true)
|
|
60
|
+
.catch(() => false);
|
|
61
|
+
if (tagged)
|
|
62
|
+
ctx.say(`• ${repo.name}: already tagged ${next}`);
|
|
63
|
+
else
|
|
64
|
+
await ctx.apply([run('git', ['tag', '-a', next, '-m', `train ${next}`], { cwd: repo.path })]);
|
|
65
|
+
await ctx.apply([run('git', ['push', 'origin', 'main', next], { cwd: repo.path })]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
70
|
+
throw new Error(`${message}\n✗ ship stopped during the release; re-run with --train ${next} to finish it (tagged repos are skipped)`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** The bookkeeping writes, then one commit per train repo that has any. */
|
|
74
|
+
async function planBookkeeping(ctx, train, next, today) {
|
|
75
|
+
const plan = [];
|
|
76
|
+
const touched = new Set();
|
|
77
|
+
const repo = (name) => {
|
|
78
|
+
const r = train.repos.find((r) => r.name === name);
|
|
79
|
+
if (!r)
|
|
80
|
+
throw new Error(`${name} is not a train repo`);
|
|
81
|
+
return r;
|
|
82
|
+
};
|
|
83
|
+
/** Plan a write when the transform changes the file, saying what it does; a missing file is left alone. */
|
|
84
|
+
const edit = async (r, rel, what, transform) => {
|
|
85
|
+
const path = join(r.path, rel);
|
|
86
|
+
const text = await ctx.readFile(path).catch(() => undefined);
|
|
87
|
+
if (text === undefined)
|
|
88
|
+
return;
|
|
89
|
+
const edited = transform(text);
|
|
90
|
+
if (edited === text)
|
|
91
|
+
return;
|
|
92
|
+
ctx.say(` ${r.name}: ${rel}: ${what}`);
|
|
93
|
+
plan.push(write(path, edited));
|
|
94
|
+
touched.add(r);
|
|
95
|
+
};
|
|
96
|
+
await edit(repo('platform'), 'ansible/galaxy.yml', `version → ${next}`, (t) => bumpGalaxyVersion(t, next));
|
|
97
|
+
// Only the plexus.platform collection's pin: a second collection in the same file stays untouched.
|
|
98
|
+
await edit(repo('preset-repo-platform'), 'template/requirements.yml', `plexus.platform pin → ${next}`, (t) => bumpCollectionPin(t, next));
|
|
99
|
+
for (const r of train.repos) {
|
|
100
|
+
const files = await ctx
|
|
101
|
+
.read('git', ['grep', '-l', WORKFLOW_REF, '--', '*.yml', '*.yaml', '*.jinja'], { cwd: r.path })
|
|
102
|
+
.catch(() => '');
|
|
103
|
+
for (const f of files.split('\n').filter(Boolean))
|
|
104
|
+
await edit(r, f, `ci-cd refs → @${next}`, (t) => bumpWorkflowRefs(t, next));
|
|
105
|
+
}
|
|
106
|
+
// The map carries the train version and the date it was cut (§ 1.5 PLX); a
|
|
107
|
+
// standard module is stamped `changed` when its extracted requirement lines
|
|
108
|
+
// differ from the previous train's, read with the same extractor the
|
|
109
|
+
// compendium's check runs, so the two never disagree.
|
|
110
|
+
const comp = repo('compendium');
|
|
111
|
+
await edit(comp, MAP_PAGE, `version → ${next}, timestamp → ${today}`, (t) => stampStandard(t, next, today));
|
|
112
|
+
for (const page of await modulePages(ctx, comp.path)) {
|
|
113
|
+
const text = await ctx.readFile(join(comp.path, page));
|
|
114
|
+
if (frontmatterField(text, 'maturity') !== 'standard')
|
|
115
|
+
continue;
|
|
116
|
+
const previous = comp.tag
|
|
117
|
+
? await ctx.read('git', ['show', `${comp.tag}:${page}`], { cwd: comp.path }).catch(() => '')
|
|
118
|
+
: '';
|
|
119
|
+
if (extractRequirements(text).join('\n') === extractRequirements(previous).join('\n'))
|
|
120
|
+
continue;
|
|
121
|
+
await edit(comp, page, `requirements changed since ${comp.latest ?? 'the beginning'} → changed: ${next}`, (t) => stampChanged(t, next));
|
|
122
|
+
}
|
|
123
|
+
for (const r of train.repos) {
|
|
124
|
+
if (!touched.has(r))
|
|
125
|
+
continue;
|
|
126
|
+
plan.push(run('git', ['add', '-A'], { cwd: r.path }));
|
|
127
|
+
plan.push(run('git', ['commit', '--quiet', '-m', `chore: train ${next} bookkeeping`], { cwd: r.path }));
|
|
128
|
+
}
|
|
129
|
+
return plan;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=ship.js.map
|
package/dist/ship.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ship.js","sourceRoot":"","sources":["../src/ship.ts"],"names":[],"mappings":"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"}
|
package/dist/train.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Context } from './context.ts';
|
|
2
|
+
/** The repos stamped with the train tag, in release order. */
|
|
3
|
+
export declare const TRAIN_REPOS: readonly ["platform", "ci-cd", "preset-repo-web", "preset-app-nextjs", "preset-repo-platform", "compendium"];
|
|
4
|
+
/** The umbrella directory holding the train repos, relative to the workspace. */
|
|
5
|
+
export declare const UPSTREAM = "plexus-ms";
|
|
6
|
+
/** A train version is plain semver, no `v` prefix (§ 1.5 PLX). */
|
|
7
|
+
export declare const isTrainVersion: (v: string) => boolean;
|
|
8
|
+
export declare function nextMinor(version: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* The newest tag of a repo across both eras (`v0.21` and `0.22.0`), compared
|
|
11
|
+
* numerically on the v-stripped form: a plain version sort would rank every
|
|
12
|
+
* v-tag above every plain tag.
|
|
13
|
+
*/
|
|
14
|
+
export declare function latestTag(tags: string[]): string | undefined;
|
|
15
|
+
export interface TrainRepo {
|
|
16
|
+
name: string;
|
|
17
|
+
path: string;
|
|
18
|
+
/** The latest tag as git has it; undefined for a repo never tagged. */
|
|
19
|
+
tag?: string;
|
|
20
|
+
/** The same, v-stripped: the train version it names. */
|
|
21
|
+
latest?: string;
|
|
22
|
+
/** `git log --oneline` since the latest tag. */
|
|
23
|
+
pending: string[];
|
|
24
|
+
}
|
|
25
|
+
export interface Train {
|
|
26
|
+
repos: TrainRepo[];
|
|
27
|
+
/** The highest tag across all repos, v-stripped. */
|
|
28
|
+
last?: string;
|
|
29
|
+
/** True when the repos' latest tags disagree: a run that stopped mid-tag. */
|
|
30
|
+
skew: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** Fetch every train repo and read its tags and pending commits. */
|
|
33
|
+
export declare function readTrain(ctx: Context, upstream: string): Promise<Train>;
|
|
34
|
+
/** Every train repo on main, clean, and not behind origin; throws naming the first offender. */
|
|
35
|
+
export declare function preflightRelease(ctx: Context, train: Train): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* The version a run releases or propagates. `propagateOnly` takes the current
|
|
38
|
+
* train; a release takes the explicit version or the next minor, refusing to
|
|
39
|
+
* derive one while the repos' tags disagree.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveVersion(train: Train, explicit: string | undefined, propagateOnly: boolean): string;
|
|
42
|
+
/** A mistake in the arguments, as opposed to a failed run: exit code 2 in the CLI. */
|
|
43
|
+
export declare class UsageError extends Error {
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=train.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"train.d.ts","sourceRoot":"","sources":["../src/train.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,8DAA8D;AAC9D,eAAO,MAAM,WAAW,8GAOd,CAAC;AAEX,iFAAiF;AACjF,eAAO,MAAM,QAAQ,cAAc,CAAC;AAEpC,kEAAkE;AAClE,eAAO,MAAM,cAAc,GAAI,GAAG,MAAM,KAAG,OAAoC,CAAC;AAEhF,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAK5D;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,IAAI,EAAE,OAAO,CAAC;CACf;AAED,oEAAoE;AACpE,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAwB9E;AAED,gGAAgG;AAChG,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,aAAa,EAAE,OAAO,GAAG,MAAM,CAgBzG;AAED,sFAAsF;AACtF,qBAAa,UAAW,SAAQ,KAAK;CAAG"}
|
package/dist/train.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// The train (§ 1.5 PLX): one version, tagged identically on every train repo
|
|
2
|
+
// whether or not it changed. This file reads the train's state from the
|
|
3
|
+
// upstream umbrella (the `plexus-ms` directory of a workspace) and decides the
|
|
4
|
+
// next version; `ship` acts on it.
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { compareTrains } from "./doctor.js";
|
|
7
|
+
/** The repos stamped with the train tag, in release order. */
|
|
8
|
+
export const TRAIN_REPOS = [
|
|
9
|
+
'platform',
|
|
10
|
+
'ci-cd',
|
|
11
|
+
'preset-repo-web',
|
|
12
|
+
'preset-app-nextjs',
|
|
13
|
+
'preset-repo-platform',
|
|
14
|
+
'compendium',
|
|
15
|
+
];
|
|
16
|
+
/** The umbrella directory holding the train repos, relative to the workspace. */
|
|
17
|
+
export const UPSTREAM = 'plexus-ms';
|
|
18
|
+
/** A train version is plain semver, no `v` prefix (§ 1.5 PLX). */
|
|
19
|
+
export const isTrainVersion = (v) => /^\d+\.\d+\.\d+$/.test(v);
|
|
20
|
+
export function nextMinor(version) {
|
|
21
|
+
const [major = '0', minor = '0'] = version.split('.');
|
|
22
|
+
return `${major}.${Number(minor) + 1}.0`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The newest tag of a repo across both eras (`v0.21` and `0.22.0`), compared
|
|
26
|
+
* numerically on the v-stripped form: a plain version sort would rank every
|
|
27
|
+
* v-tag above every plain tag.
|
|
28
|
+
*/
|
|
29
|
+
export function latestTag(tags) {
|
|
30
|
+
return tags
|
|
31
|
+
.filter((t) => /^v?\d/.test(t))
|
|
32
|
+
.sort((a, b) => compareTrains(a.replace(/^v/, ''), b.replace(/^v/, '')))
|
|
33
|
+
.at(-1);
|
|
34
|
+
}
|
|
35
|
+
/** Fetch every train repo and read its tags and pending commits. */
|
|
36
|
+
export async function readTrain(ctx, upstream) {
|
|
37
|
+
const repos = [];
|
|
38
|
+
const all = new Set();
|
|
39
|
+
for (const name of TRAIN_REPOS) {
|
|
40
|
+
const path = join(upstream, name);
|
|
41
|
+
try {
|
|
42
|
+
await ctx.read('git', ['rev-parse', '--git-dir'], { cwd: path });
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
throw new Error(`${path} is not a git repo`);
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
await ctx.read('git', ['fetch', 'origin', '--tags', '--quiet'], { cwd: path });
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
throw new Error(`${name}: fetch from origin failed`);
|
|
52
|
+
}
|
|
53
|
+
const tags = (await ctx.read('git', ['tag', '--list', 'v*', '[0-9]*'], { cwd: path })).split('\n').filter(Boolean);
|
|
54
|
+
for (const t of tags)
|
|
55
|
+
all.add(t.replace(/^v/, ''));
|
|
56
|
+
const tag = latestTag(tags);
|
|
57
|
+
const range = tag ? `${tag}..HEAD` : 'HEAD';
|
|
58
|
+
const pending = (await ctx.read('git', ['log', '--oneline', range], { cwd: path })).split('\n').filter(Boolean);
|
|
59
|
+
repos.push({ name, path, tag, latest: tag?.replace(/^v/, ''), pending });
|
|
60
|
+
}
|
|
61
|
+
const latest = repos.map((r) => r.latest);
|
|
62
|
+
return { repos, last: latestTag([...all]), skew: latest.some((l) => l !== latest[0]) };
|
|
63
|
+
}
|
|
64
|
+
/** Every train repo on main, clean, and not behind origin; throws naming the first offender. */
|
|
65
|
+
export async function preflightRelease(ctx, train) {
|
|
66
|
+
for (const { name, path } of train.repos) {
|
|
67
|
+
const branch = (await ctx.read('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: path })).trim();
|
|
68
|
+
if (branch !== 'main')
|
|
69
|
+
throw new Error(`${name} is on '${branch}', trains cut from main`);
|
|
70
|
+
if ((await ctx.read('git', ['status', '--porcelain'], { cwd: path })).trim() !== '')
|
|
71
|
+
throw new Error(`${name} has uncommitted changes — commit first`);
|
|
72
|
+
const behind = (await ctx.read('git', ['rev-list', '--count', 'main..origin/main'], { cwd: path })).trim();
|
|
73
|
+
if (behind !== '0')
|
|
74
|
+
throw new Error(`${name} is ${behind} commit(s) behind origin/main — pull first, or the tag lands on a stale commit`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The version a run releases or propagates. `propagateOnly` takes the current
|
|
79
|
+
* train; a release takes the explicit version or the next minor, refusing to
|
|
80
|
+
* derive one while the repos' tags disagree.
|
|
81
|
+
*/
|
|
82
|
+
export function resolveVersion(train, explicit, propagateOnly) {
|
|
83
|
+
if (explicit !== undefined && !isTrainVersion(explicit))
|
|
84
|
+
throw new UsageError(`'${explicit}' is not plain semver (X.Y.Z, no v)`);
|
|
85
|
+
if (propagateOnly) {
|
|
86
|
+
const v = explicit ?? train.last;
|
|
87
|
+
if (!v)
|
|
88
|
+
throw new Error('no train version found to propagate');
|
|
89
|
+
return v;
|
|
90
|
+
}
|
|
91
|
+
if (explicit)
|
|
92
|
+
return explicit;
|
|
93
|
+
if (train.skew) {
|
|
94
|
+
const report = train.repos.map((r) => ` ${r.name}: ${r.latest ?? 'none'}`).join('\n');
|
|
95
|
+
throw new Error(`the train repos' latest tags disagree:\n${report}\npass the version explicitly (--train ${train.last}) to finish the half-tagged train, or a higher one to start a new one`);
|
|
96
|
+
}
|
|
97
|
+
return train.last ? nextMinor(train.last) : '0.1.0';
|
|
98
|
+
}
|
|
99
|
+
/** A mistake in the arguments, as opposed to a failed run: exit code 2 in the CLI. */
|
|
100
|
+
export class UsageError extends Error {
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=train.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"train.js","sourceRoot":"","sources":["../src/train.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,wEAAwE;AACxE,+EAA+E;AAC/E,mCAAmC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,8DAA8D;AAC9D,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,UAAU;IACV,OAAO;IACP,iBAAiB;IACjB,mBAAmB;IACnB,sBAAsB;IACtB,YAAY;CACJ,CAAC;AAEX,iFAAiF;AACjF,MAAM,CAAC,MAAM,QAAQ,GAAG,WAAW,CAAC;AAEpC,kEAAkE;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAS,EAAW,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhF,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,MAAM,CAAC,KAAK,GAAG,GAAG,EAAE,KAAK,GAAG,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,OAAO,IAAI;SACR,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAC9B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;SACvE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACZ,CAAC;AAqBD,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAY,EAAE,QAAgB;IAC5D,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,oBAAoB,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QACjF,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,4BAA4B,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACnH,KAAK,MAAM,CAAC,IAAI,IAAI;YAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5C,MAAM,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAChH,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACzF,CAAC;AAED,gGAAgG;AAChG,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAY,EAAE,KAAY;IAC/D,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpG,IAAI,MAAM,KAAK,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,WAAW,MAAM,yBAAyB,CAAC,CAAC;QAC1F,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;YACjF,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,yCAAyC,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,mBAAmB,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3G,IAAI,MAAM,KAAK,GAAG;YAChB,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,OAAO,MAAM,gFAAgF,CACrG,CAAC;IACN,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,QAA4B,EAAE,aAAsB;IAC/F,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC;QACrD,MAAM,IAAI,UAAU,CAAC,IAAI,QAAQ,qCAAqC,CAAC,CAAC;IAC1E,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,CAAC,GAAG,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC;QACjC,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC/D,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvF,MAAM,IAAI,KAAK,CACb,2CAA2C,MAAM,0CAA0C,KAAK,CAAC,IAAI,uEAAuE,CAC7K,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACtD,CAAC;AAED,sFAAsF;AACtF,MAAM,OAAO,UAAW,SAAQ,KAAK;CAAG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plexus-ms/lib",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The Plexus verbs as a library: the plan-then-apply core behind plx, and the one parser of Plexus's own file shapes",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -26,17 +26,16 @@
|
|
|
26
26
|
"engines": {
|
|
27
27
|
"node": ">=24"
|
|
28
28
|
},
|
|
29
|
-
"scripts": {
|
|
30
|
-
"build": "tsc",
|
|
31
|
-
"check": "tsc --noEmit",
|
|
32
|
-
"test": "node --test",
|
|
33
|
-
"prepack": "tsc"
|
|
34
|
-
},
|
|
35
29
|
"dependencies": {
|
|
36
30
|
"yaml": "^2.9.1"
|
|
37
31
|
},
|
|
38
32
|
"devDependencies": {
|
|
39
|
-
"@types/node": "^26.
|
|
40
|
-
"typescript": "
|
|
33
|
+
"@types/node": "^26.6.5",
|
|
34
|
+
"typescript": "^6.0.3"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"check": "tsc --noEmit",
|
|
39
|
+
"test": "node --test"
|
|
41
40
|
}
|
|
42
|
-
}
|
|
41
|
+
}
|