@moxxy/plugin-self-update 0.26.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 +21 -0
- package/dist/classify.d.ts +33 -0
- package/dist/classify.d.ts.map +1 -0
- package/dist/classify.js +177 -0
- package/dist/classify.js.map +1 -0
- package/dist/core-tools/apply.d.ts +4 -0
- package/dist/core-tools/apply.d.ts.map +1 -0
- package/dist/core-tools/apply.js +43 -0
- package/dist/core-tools/apply.js.map +1 -0
- package/dist/core-tools/begin.d.ts +4 -0
- package/dist/core-tools/begin.d.ts.map +1 -0
- package/dist/core-tools/begin.js +76 -0
- package/dist/core-tools/begin.js.map +1 -0
- package/dist/core-tools/edit.d.ts +4 -0
- package/dist/core-tools/edit.d.ts.map +1 -0
- package/dist/core-tools/edit.js +33 -0
- package/dist/core-tools/edit.js.map +1 -0
- package/dist/core-tools/index.d.ts +11 -0
- package/dist/core-tools/index.d.ts.map +1 -0
- package/dist/core-tools/index.js +28 -0
- package/dist/core-tools/index.js.map +1 -0
- package/dist/core-tools/preflight.d.ts +4 -0
- package/dist/core-tools/preflight.d.ts.map +1 -0
- package/dist/core-tools/preflight.js +14 -0
- package/dist/core-tools/preflight.js.map +1 -0
- package/dist/core-tools/rollback.d.ts +4 -0
- package/dist/core-tools/rollback.d.ts.map +1 -0
- package/dist/core-tools/rollback.js +30 -0
- package/dist/core-tools/rollback.js.map +1 -0
- package/dist/core-tools/shared.d.ts +16 -0
- package/dist/core-tools/shared.d.ts.map +1 -0
- package/dist/core-tools/shared.js +12 -0
- package/dist/core-tools/shared.js.map +1 -0
- package/dist/core-tools/status.d.ts +4 -0
- package/dist/core-tools/status.d.ts.map +1 -0
- package/dist/core-tools/status.js +25 -0
- package/dist/core-tools/status.js.map +1 -0
- package/dist/core-tools/verify.d.ts +4 -0
- package/dist/core-tools/verify.d.ts.map +1 -0
- package/dist/core-tools/verify.js +39 -0
- package/dist/core-tools/verify.js.map +1 -0
- package/dist/core-tools/write.d.ts +4 -0
- package/dist/core-tools/write.d.ts.map +1 -0
- package/dist/core-tools/write.js +28 -0
- package/dist/core-tools/write.js.map +1 -0
- package/dist/core-update.d.ts +173 -0
- package/dist/core-update.d.ts.map +1 -0
- package/dist/core-update.js +626 -0
- package/dist/core-update.js.map +1 -0
- package/dist/deps.d.ts +49 -0
- package/dist/deps.d.ts.map +1 -0
- package/dist/deps.js +30 -0
- package/dist/deps.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +349 -0
- package/dist/index.js.map +1 -0
- package/dist/transaction.d.ts +80 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +188 -0
- package/dist/transaction.js.map +1 -0
- package/dist/verify.d.ts +23 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +164 -0
- package/dist/verify.js.map +1 -0
- package/package.json +61 -0
- package/src/classify.test.ts +176 -0
- package/src/classify.ts +221 -0
- package/src/core-tools/apply.ts +44 -0
- package/src/core-tools/begin.ts +94 -0
- package/src/core-tools/edit.ts +33 -0
- package/src/core-tools/index.ts +33 -0
- package/src/core-tools/preflight.ts +15 -0
- package/src/core-tools/rollback.ts +30 -0
- package/src/core-tools/shared.test.ts +16 -0
- package/src/core-tools/shared.ts +24 -0
- package/src/core-tools/status.ts +26 -0
- package/src/core-tools/verify.ts +39 -0
- package/src/core-tools/write.ts +30 -0
- package/src/core-update.test.ts +542 -0
- package/src/core-update.ts +744 -0
- package/src/deps.ts +84 -0
- package/src/discovery.test.ts +40 -0
- package/src/index.test.ts +299 -0
- package/src/index.ts +441 -0
- package/src/transaction.test.ts +143 -0
- package/src/transaction.ts +254 -0
- package/src/verify.test.ts +82 -0
- package/src/verify.ts +200 -0
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { existsSync, lstatSync, promises as fs, readFileSync, realpathSync } from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { writeFileAtomic } from '@moxxy/sdk/server';
|
|
6
|
+
import { newTxnId } from './transaction.js';
|
|
7
|
+
/**
|
|
8
|
+
* Tier-2: patch moxxy's OWN compiled framework packages in a global npm
|
|
9
|
+
* install. Unlike Tier 1 (plugins/skills, hot-reloaded), a core change cannot
|
|
10
|
+
* be hot-swapped — @moxxy/core is imported once into the live process — so the
|
|
11
|
+
* flow is: provision a source clone at the EXACT published commit, edit + build
|
|
12
|
+
* + test it there, then atomically overlay the built `dist/` into the live
|
|
13
|
+
* install (snapshotting the previous dist) and require a restart. A boot-time
|
|
14
|
+
* finalize hook commits or rolls back.
|
|
15
|
+
*
|
|
16
|
+
* Everything here is filesystem + child-process only; no moxxy core import.
|
|
17
|
+
*/
|
|
18
|
+
const SCOPE = '@moxxy/';
|
|
19
|
+
const BUILD_TIMEOUT_MS = 12 * 60_000;
|
|
20
|
+
/**
|
|
21
|
+
* Cap on the child-process output we retain in memory. A long, model-triggered
|
|
22
|
+
* `pnpm build/typecheck/test` (turbo fan-out, a looping test, a tool dumping a
|
|
23
|
+
* large file) can emit hundreds of MB; holding it all in the LIVE process would
|
|
24
|
+
* OOM-kill the host mid-update. Callers only ever read the trailing ~1.5KB, so a
|
|
25
|
+
* sliding tail is lossless for them.
|
|
26
|
+
*/
|
|
27
|
+
const MAX_RUN_OUTPUT_BYTES = 512 * 1024;
|
|
28
|
+
/** A full git commit sha — the source-pin must compare exact 40-hex shas, never a prefix. */
|
|
29
|
+
const FULL_SHA_RE = /^[0-9a-f]{40}$/;
|
|
30
|
+
export function shortName(pkg) {
|
|
31
|
+
return pkg.startsWith(SCOPE) ? pkg.slice(SCOPE.length) : pkg;
|
|
32
|
+
}
|
|
33
|
+
export function run(cmd, args, cwd, timeoutMs = BUILD_TIMEOUT_MS) {
|
|
34
|
+
return new Promise((resolve) => {
|
|
35
|
+
// `detached` puts the child in its own process group so a timeout can kill
|
|
36
|
+
// the WHOLE subtree (pnpm/turbo/vitest fan out to many grandchildren that
|
|
37
|
+
// SIGKILL on the immediate child would orphan).
|
|
38
|
+
const child = spawn(cmd, [...args], { cwd, stdio: ['ignore', 'pipe', 'pipe'], detached: true });
|
|
39
|
+
const tail = new TailBuffer(MAX_RUN_OUTPUT_BYTES);
|
|
40
|
+
const onData = (d) => tail.push(d);
|
|
41
|
+
child.stdout.on('data', onData);
|
|
42
|
+
child.stderr.on('data', onData);
|
|
43
|
+
const timer = setTimeout(() => killTree(child), timeoutMs);
|
|
44
|
+
let settled = false;
|
|
45
|
+
const finish = (r) => {
|
|
46
|
+
if (settled)
|
|
47
|
+
return;
|
|
48
|
+
settled = true;
|
|
49
|
+
clearTimeout(timer);
|
|
50
|
+
child.stdout.off('data', onData);
|
|
51
|
+
child.stderr.off('data', onData);
|
|
52
|
+
resolve(r);
|
|
53
|
+
};
|
|
54
|
+
child.on('error', (err) => finish({ code: -1, output: `${cmd} failed to start: ${err.message}` }));
|
|
55
|
+
child.on('close', (code) => finish({ code: code ?? -1, output: tail.toString() }));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Bounded sliding-tail accumulator: keeps at most `cap` bytes of the most recent
|
|
60
|
+
* output. Once the cap is exceeded it trims from the front so memory stays
|
|
61
|
+
* O(cap) regardless of how much the child emits.
|
|
62
|
+
*/
|
|
63
|
+
class TailBuffer {
|
|
64
|
+
cap;
|
|
65
|
+
buf = '';
|
|
66
|
+
constructor(cap) {
|
|
67
|
+
this.cap = cap;
|
|
68
|
+
}
|
|
69
|
+
push(d) {
|
|
70
|
+
this.buf += d.toString('utf8');
|
|
71
|
+
if (this.buf.length > this.cap)
|
|
72
|
+
this.buf = this.buf.slice(this.buf.length - this.cap);
|
|
73
|
+
}
|
|
74
|
+
toString() {
|
|
75
|
+
return this.buf;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** SIGKILL a detached child's whole process group, tolerating an already-dead group. */
|
|
79
|
+
function killTree(child) {
|
|
80
|
+
try {
|
|
81
|
+
if (child.pid != null)
|
|
82
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
83
|
+
else
|
|
84
|
+
child.kill('SIGKILL');
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// ESRCH: the group already exited. Fall back to the direct kill just in case.
|
|
88
|
+
try {
|
|
89
|
+
child.kill('SIGKILL');
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
/* already gone */
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function trunc(s, n = 1500) {
|
|
97
|
+
return s.length <= n ? s : `…${s.slice(s.length - n)}`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Memoize the resolution per `fromUrl`: the live install root cannot move
|
|
101
|
+
* underneath a running process, yet detectCoreInstall is called from many tool
|
|
102
|
+
* handlers (preflight/begin/verify/apply/rollback) and does synchronous blocking
|
|
103
|
+
* I/O (readFileSync + an existsSync walk). Caching keeps that off the hot path.
|
|
104
|
+
* `null` results are cached too so repeated misses stay cheap.
|
|
105
|
+
*/
|
|
106
|
+
const coreInstallCache = new Map();
|
|
107
|
+
/**
|
|
108
|
+
* Resolve the live `@moxxy/core` install to learn its version, the commit it
|
|
109
|
+
* was published from (npm writes `gitHead` on publish), and the on-disk root
|
|
110
|
+
* to overlay into.
|
|
111
|
+
*/
|
|
112
|
+
export function detectCoreInstall(fromUrl) {
|
|
113
|
+
if (coreInstallCache.has(fromUrl))
|
|
114
|
+
return coreInstallCache.get(fromUrl) ?? null;
|
|
115
|
+
const info = detectCoreInstallUncached(fromUrl);
|
|
116
|
+
coreInstallCache.set(fromUrl, info);
|
|
117
|
+
return info;
|
|
118
|
+
}
|
|
119
|
+
function detectCoreInstallUncached(fromUrl) {
|
|
120
|
+
try {
|
|
121
|
+
// `require.resolve('@moxxy/core')` is unreliable — core's `exports` map has
|
|
122
|
+
// no "." main. Instead locate the `@moxxy` scope dir by walking up from the
|
|
123
|
+
// caller and reading core/package.json directly.
|
|
124
|
+
const scopeDir = findCoreScopeDir(fileURLToPath(fromUrl));
|
|
125
|
+
if (!scopeDir)
|
|
126
|
+
return null;
|
|
127
|
+
const pkg = JSON.parse(readFileSync(path.join(scopeDir, 'core', 'package.json'), 'utf8'));
|
|
128
|
+
const repoUrl = typeof pkg.repository === 'string' ? pkg.repository : pkg.repository?.url;
|
|
129
|
+
return {
|
|
130
|
+
version: pkg.version ?? '0.0.0',
|
|
131
|
+
...(pkg.gitHead ? { gitHead: pkg.gitHead } : {}),
|
|
132
|
+
...(repoUrl ? { repoUrl: normalizeGitUrl(repoUrl) } : {}),
|
|
133
|
+
scopeDir,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Find the `@moxxy` scope dir containing `core/package.json`, by walking up
|
|
142
|
+
* ancestors of `start`. Handles both the global install (the file lives under
|
|
143
|
+
* `node_modules/@moxxy/<pkg>`, so a parent IS the scope dir) and a workspace
|
|
144
|
+
* (an ancestor has `node_modules/@moxxy`).
|
|
145
|
+
*/
|
|
146
|
+
function findCoreScopeDir(start) {
|
|
147
|
+
let dir = start;
|
|
148
|
+
for (let i = 0; i < 16; i++) {
|
|
149
|
+
if (path.basename(dir) === '@moxxy' && existsSync(path.join(dir, 'core', 'package.json'))) {
|
|
150
|
+
return dir;
|
|
151
|
+
}
|
|
152
|
+
const nm = path.join(dir, 'node_modules', '@moxxy');
|
|
153
|
+
if (existsSync(path.join(nm, 'core', 'package.json')))
|
|
154
|
+
return nm;
|
|
155
|
+
const parent = path.dirname(dir);
|
|
156
|
+
if (parent === dir)
|
|
157
|
+
break;
|
|
158
|
+
dir = parent;
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
function normalizeGitUrl(url) {
|
|
163
|
+
return url.replace(/^git\+/, '').replace(/^git:\/\//, 'https://');
|
|
164
|
+
}
|
|
165
|
+
export async function corePreflight(install) {
|
|
166
|
+
const checks = [];
|
|
167
|
+
const git = await run('git', ['--version'], process.cwd(), 10_000);
|
|
168
|
+
checks.push({ id: 'git', ok: git.code === 0, detail: git.code === 0 ? git.output.trim() : 'git not found' });
|
|
169
|
+
const pnpm = await run('pnpm', ['--version'], process.cwd(), 10_000);
|
|
170
|
+
checks.push({ id: 'pnpm', ok: pnpm.code === 0, detail: pnpm.code === 0 ? `pnpm ${pnpm.output.trim()}` : 'pnpm not found' });
|
|
171
|
+
checks.push({ id: 'install', ok: Boolean(install), detail: install ? `@moxxy/core@${install.version}` : 'could not resolve @moxxy/core' });
|
|
172
|
+
checks.push({
|
|
173
|
+
id: 'provenance',
|
|
174
|
+
ok: Boolean(install?.gitHead),
|
|
175
|
+
detail: install?.gitHead ? `gitHead ${install.gitHead.slice(0, 10)}` : 'no gitHead in published metadata — cannot pin source',
|
|
176
|
+
});
|
|
177
|
+
checks.push({
|
|
178
|
+
id: 'repo',
|
|
179
|
+
ok: Boolean(install?.repoUrl),
|
|
180
|
+
detail: install?.repoUrl ?? 'no repository url in @moxxy/core package.json',
|
|
181
|
+
});
|
|
182
|
+
return { ok: checks.every((c) => c.ok), checks };
|
|
183
|
+
}
|
|
184
|
+
export function coreTxnRoot(moxxyDir) {
|
|
185
|
+
return path.join(moxxyDir, 'self-update', 'core-txns');
|
|
186
|
+
}
|
|
187
|
+
export function coreTxnDir(moxxyDir, txnId) {
|
|
188
|
+
return path.join(coreTxnRoot(moxxyDir), txnId);
|
|
189
|
+
}
|
|
190
|
+
export function repoDir(moxxyDir) {
|
|
191
|
+
return path.join(moxxyDir, 'self-update', 'repo');
|
|
192
|
+
}
|
|
193
|
+
export async function writeCoreJournal(moxxyDir, j) {
|
|
194
|
+
j.updatedAt = new Date().toISOString();
|
|
195
|
+
const file = path.join(coreTxnDir(moxxyDir, j.txnId), 'journal.json');
|
|
196
|
+
await writeFileAtomic(file, JSON.stringify(j, null, 2) + '\n');
|
|
197
|
+
}
|
|
198
|
+
export async function readCoreJournal(moxxyDir, txnId) {
|
|
199
|
+
return JSON.parse(await fs.readFile(path.join(coreTxnDir(moxxyDir, txnId), 'journal.json'), 'utf8'));
|
|
200
|
+
}
|
|
201
|
+
export async function listCoreTxns(moxxyDir) {
|
|
202
|
+
let ids;
|
|
203
|
+
try {
|
|
204
|
+
ids = (await fs.readdir(coreTxnRoot(moxxyDir), { withFileTypes: true }))
|
|
205
|
+
.filter((e) => e.isDirectory())
|
|
206
|
+
.map((e) => e.name);
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
211
|
+
const out = [];
|
|
212
|
+
for (const id of ids) {
|
|
213
|
+
try {
|
|
214
|
+
out.push(await readCoreJournal(moxxyDir, id));
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
/* skip corrupt */
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return out.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Count core-txn dirs whose `journal.json` is present but unparseable. A corrupt
|
|
224
|
+
* (or hand-edited / half-written) journal would silently VANISH from
|
|
225
|
+
* listCoreTxns — making the begin serialization guard fail OPEN and let a second
|
|
226
|
+
* concurrent core txn clobber the shared repoDir. The guard uses this to instead
|
|
227
|
+
* fail CLOSED. A missing journal.json (a dir mid-create) is NOT corruption and
|
|
228
|
+
* is ignored.
|
|
229
|
+
*/
|
|
230
|
+
export async function countCorruptCoreTxns(moxxyDir) {
|
|
231
|
+
let ids;
|
|
232
|
+
try {
|
|
233
|
+
ids = (await fs.readdir(coreTxnRoot(moxxyDir), { withFileTypes: true }))
|
|
234
|
+
.filter((e) => e.isDirectory())
|
|
235
|
+
.map((e) => e.name);
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
let corrupt = 0;
|
|
241
|
+
for (const id of ids) {
|
|
242
|
+
const file = path.join(coreTxnDir(moxxyDir, id), 'journal.json');
|
|
243
|
+
let raw;
|
|
244
|
+
try {
|
|
245
|
+
raw = await fs.readFile(file, 'utf8');
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
continue; // no journal yet — not corruption.
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
JSON.parse(raw);
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
corrupt++;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return corrupt;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Ensure a buildable clone exists at exactly `install.gitHead`. Clones on first
|
|
261
|
+
* use, otherwise fetches; always checks out the pinned commit and verifies HEAD
|
|
262
|
+
* matches — this is the integrity guarantee that the source equals the binary.
|
|
263
|
+
*/
|
|
264
|
+
export async function provisionWorkspace(opts) {
|
|
265
|
+
const dir = repoDir(opts.moxxyDir);
|
|
266
|
+
const url = opts.repoUrlOverride ?? opts.install.repoUrl;
|
|
267
|
+
const ref = opts.install.gitHead;
|
|
268
|
+
if (!url)
|
|
269
|
+
return { ok: false, message: 'no repository url to clone from', repoDir: dir };
|
|
270
|
+
if (!ref)
|
|
271
|
+
return { ok: false, message: 'no gitHead — cannot pin source to the installed version', repoDir: dir };
|
|
272
|
+
const hasClone = await fs
|
|
273
|
+
.access(path.join(dir, '.git'))
|
|
274
|
+
.then(() => true)
|
|
275
|
+
.catch(() => false);
|
|
276
|
+
if (!hasClone) {
|
|
277
|
+
await fs.mkdir(path.dirname(dir), { recursive: true });
|
|
278
|
+
const clone = await run('git', ['clone', url, dir], path.dirname(dir));
|
|
279
|
+
if (clone.code !== 0)
|
|
280
|
+
return { ok: false, message: `git clone failed: ${trunc(clone.output, 400)}`, repoDir: dir };
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
await run('git', ['fetch', '--all', '--tags'], dir);
|
|
284
|
+
}
|
|
285
|
+
const checkout = await run('git', ['checkout', '--force', ref], dir);
|
|
286
|
+
if (checkout.code !== 0) {
|
|
287
|
+
const fetched = await run('git', ['fetch', 'origin', ref], dir);
|
|
288
|
+
if (fetched.code === 0)
|
|
289
|
+
await run('git', ['checkout', '--force', ref], dir);
|
|
290
|
+
}
|
|
291
|
+
// Resolve the pinned ref to a full sha so a short/abbreviated gitHead can't
|
|
292
|
+
// prefix-match a DIFFERENT commit and defeat the source-equals-binary pin.
|
|
293
|
+
const refFull = (await run('git', ['rev-parse', ref], dir)).output.trim();
|
|
294
|
+
const head = (await run('git', ['rev-parse', 'HEAD'], dir)).output.trim();
|
|
295
|
+
if (!FULL_SHA_RE.test(head) || !FULL_SHA_RE.test(refFull) || head !== refFull) {
|
|
296
|
+
return {
|
|
297
|
+
ok: false,
|
|
298
|
+
message: `source mismatch: clone HEAD ${head.slice(0, 10)} ≠ installed gitHead ${ref.slice(0, 10)}`,
|
|
299
|
+
repoDir: dir,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
await run('git', ['clean', '-fdx', 'packages'], dir).catch(() => undefined);
|
|
303
|
+
await run('git', ['checkout', '--', '.'], dir).catch(() => undefined);
|
|
304
|
+
const install = await run('pnpm', ['install', '--frozen-lockfile'], dir);
|
|
305
|
+
if (install.code !== 0) {
|
|
306
|
+
const loose = await run('pnpm', ['install'], dir);
|
|
307
|
+
if (loose.code !== 0)
|
|
308
|
+
return { ok: false, message: `pnpm install failed: ${trunc(loose.output, 400)}`, repoDir: dir };
|
|
309
|
+
}
|
|
310
|
+
return { ok: true, message: 'workspace provisioned', repoDir: dir };
|
|
311
|
+
}
|
|
312
|
+
// ── repo package layout ──────────────────────────────────────────────────────────
|
|
313
|
+
/** Find the clone's package directory whose package.json `name` === pkgName. */
|
|
314
|
+
export async function findRepoPkgDir(repo, pkgName) {
|
|
315
|
+
const pkgsRoot = path.join(repo, 'packages');
|
|
316
|
+
let entries;
|
|
317
|
+
try {
|
|
318
|
+
entries = (await fs.readdir(pkgsRoot, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
for (const name of entries) {
|
|
324
|
+
const dir = path.join(pkgsRoot, name);
|
|
325
|
+
try {
|
|
326
|
+
const pkg = JSON.parse(await fs.readFile(path.join(dir, 'package.json'), 'utf8'));
|
|
327
|
+
if (pkg.name === pkgName)
|
|
328
|
+
return dir;
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
/* skip */
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
export async function verifyCorePackages(repo, install, pkgNames) {
|
|
337
|
+
const stages = [];
|
|
338
|
+
// `...` expands the turbo filter to include dependents, so a change that
|
|
339
|
+
// breaks a downstream package is caught.
|
|
340
|
+
const filters = pkgNames.flatMap((p) => ['--filter', `${p}...`]);
|
|
341
|
+
for (const task of ['build', 'typecheck', 'test']) {
|
|
342
|
+
const r = await run('pnpm', [...filters, task], repo);
|
|
343
|
+
stages.push({ stage: task, ok: r.code === 0, message: r.code === 0 ? `${task} ok` : trunc(r.output) });
|
|
344
|
+
if (r.code !== 0)
|
|
345
|
+
return { ok: false, stages, newDeps: [] };
|
|
346
|
+
}
|
|
347
|
+
const newDeps = await detectNewDeps(repo, install, pkgNames);
|
|
348
|
+
if (newDeps.length > 0) {
|
|
349
|
+
stages.push({
|
|
350
|
+
stage: 'deps',
|
|
351
|
+
ok: false,
|
|
352
|
+
message: `patch adds runtime dependencies not in the live install: ${newDeps.join(', ')} — a dist overlay can't install these. Escalate.`,
|
|
353
|
+
});
|
|
354
|
+
return { ok: false, stages, newDeps };
|
|
355
|
+
}
|
|
356
|
+
return { ok: true, stages, newDeps: [] };
|
|
357
|
+
}
|
|
358
|
+
/** Runtime deps the patched clone declares that aren't present in the live install. */
|
|
359
|
+
export async function detectNewDeps(repo, install, pkgNames) {
|
|
360
|
+
const missing = new Set();
|
|
361
|
+
for (const pkgName of pkgNames) {
|
|
362
|
+
const dir = await findRepoPkgDir(repo, pkgName);
|
|
363
|
+
if (!dir)
|
|
364
|
+
continue;
|
|
365
|
+
let deps = {};
|
|
366
|
+
try {
|
|
367
|
+
const pkg = JSON.parse(await fs.readFile(path.join(dir, 'package.json'), 'utf8'));
|
|
368
|
+
deps = pkg.dependencies ?? {};
|
|
369
|
+
}
|
|
370
|
+
catch {
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
// The live node_modules root is the parent of the `@moxxy` scope dir.
|
|
374
|
+
const nmRoot = path.dirname(install.scopeDir);
|
|
375
|
+
for (const [dep, spec] of Object.entries(deps)) {
|
|
376
|
+
if (spec.startsWith('workspace:'))
|
|
377
|
+
continue; // resolved internally at build
|
|
378
|
+
const present = await exists(path.join(nmRoot, dep));
|
|
379
|
+
if (!present)
|
|
380
|
+
missing.add(dep);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return [...missing];
|
|
384
|
+
}
|
|
385
|
+
// ── overlay / restore ────────────────────────────────────────────────────────────
|
|
386
|
+
/**
|
|
387
|
+
* Swap each package's freshly-built `dist/` into the live install, keeping the
|
|
388
|
+
* previous dist as a snapshot for rollback. Renames are atomic on the same fs.
|
|
389
|
+
*
|
|
390
|
+
* Crash-atomicity across packages: a multi-package overlay must not leave the
|
|
391
|
+
* install with a NEW core dist but an OLD cli dist (a version-skewed, possibly
|
|
392
|
+
* non-bootable combo) if the process is killed mid-loop. So we work in phases:
|
|
393
|
+
* 1. validate every package + snapshot every old dist,
|
|
394
|
+
* 2. stage every new dist (`dist.new`) — nothing live is touched yet,
|
|
395
|
+
* 3. write a `pending.json` intent recording the full set + staged paths,
|
|
396
|
+
* 4. swap all dists in a tight loop, then write `applied.json`.
|
|
397
|
+
* If the process dies between 3 and the final `applied.json`, a leftover
|
|
398
|
+
* `pending.json` lets {@link reconcileOverlay} (run on boot) complete or undo
|
|
399
|
+
* the partial set instead of stranding a mixed core.
|
|
400
|
+
*/
|
|
401
|
+
export async function overlayPackages(opts) {
|
|
402
|
+
await fs.mkdir(opts.snapshotDir, { recursive: true });
|
|
403
|
+
// Phase 1 + 2: validate, snapshot old, stage new. No live dist is swapped yet,
|
|
404
|
+
// so a failure here leaves the install untouched (only orphaned dist.new dirs).
|
|
405
|
+
const planned = [];
|
|
406
|
+
for (const pkgName of opts.pkgNames) {
|
|
407
|
+
const repoPkg = await findRepoPkgDir(opts.repo, pkgName);
|
|
408
|
+
if (!repoPkg) {
|
|
409
|
+
await cleanupStaged(planned);
|
|
410
|
+
return { ok: false, message: `package not found in clone: ${pkgName}`, applied: [] };
|
|
411
|
+
}
|
|
412
|
+
const srcDist = path.join(repoPkg, 'dist');
|
|
413
|
+
if (!(await exists(srcDist))) {
|
|
414
|
+
await cleanupStaged(planned);
|
|
415
|
+
return { ok: false, message: `no built dist for ${pkgName}`, applied: [] };
|
|
416
|
+
}
|
|
417
|
+
const destPkg = path.join(opts.install.scopeDir, shortName(pkgName));
|
|
418
|
+
const destDist = path.join(destPkg, 'dist');
|
|
419
|
+
if (await exists(destDist)) {
|
|
420
|
+
await fs.cp(destDist, path.join(opts.snapshotDir, shortName(pkgName)), { recursive: true });
|
|
421
|
+
}
|
|
422
|
+
const staged = path.join(destPkg, 'dist.new');
|
|
423
|
+
await fs.rm(staged, { recursive: true, force: true });
|
|
424
|
+
await fs.cp(srcDist, staged, { recursive: true });
|
|
425
|
+
planned.push({ pkgName, destDist, staged });
|
|
426
|
+
}
|
|
427
|
+
// Phase 3: record the intent so an interrupted phase-4 swap is reconcilable.
|
|
428
|
+
await writeFileAtomic(path.join(opts.snapshotDir, 'pending.json'), JSON.stringify({ packages: planned.map((p) => p.pkgName), at: new Date().toISOString() }, null, 2));
|
|
429
|
+
// Phase 4: swap each staged dist into place. Atomic per package; the pending
|
|
430
|
+
// marker covers the (tiny) window where the set is only partially swapped.
|
|
431
|
+
const applied = [];
|
|
432
|
+
for (const { pkgName, destDist, staged } of planned) {
|
|
433
|
+
const bak = `${destDist}.bak`;
|
|
434
|
+
await fs.rm(bak, { recursive: true, force: true });
|
|
435
|
+
if (await exists(destDist))
|
|
436
|
+
await fs.rename(destDist, bak);
|
|
437
|
+
await fs.rename(staged, destDist);
|
|
438
|
+
await fs.rm(bak, { recursive: true, force: true });
|
|
439
|
+
applied.push(pkgName);
|
|
440
|
+
}
|
|
441
|
+
await writeFileAtomic(path.join(opts.snapshotDir, 'applied.json'), JSON.stringify({ packages: applied, at: new Date().toISOString() }, null, 2));
|
|
442
|
+
// The swap completed; the pending intent is now satisfied.
|
|
443
|
+
await fs.rm(path.join(opts.snapshotDir, 'pending.json'), { force: true }).catch(() => undefined);
|
|
444
|
+
return { ok: true, message: `overlaid ${applied.length} package(s)`, applied };
|
|
445
|
+
}
|
|
446
|
+
/** Remove any staged `dist.new` dirs from an aborted overlay plan. */
|
|
447
|
+
async function cleanupStaged(planned) {
|
|
448
|
+
for (const { staged } of planned) {
|
|
449
|
+
await fs.rm(staged, { recursive: true, force: true }).catch(() => undefined);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Reconcile an overlay that was interrupted between intent and completion. If a
|
|
454
|
+
* `pending.json` exists without a matching `applied.json`, the swap loop may
|
|
455
|
+
* have run partially (some live dists new, some old) and left orphaned
|
|
456
|
+
* `dist.new`/`dist.bak`. Restoring from the snapshot returns every package to
|
|
457
|
+
* its pre-overlay dist so the install is internally consistent again; the caller
|
|
458
|
+
* marks the txn rolled_back. No-op when the overlay completed cleanly.
|
|
459
|
+
*/
|
|
460
|
+
export async function reconcileOverlay(opts) {
|
|
461
|
+
const pendingFile = path.join(opts.snapshotDir, 'pending.json');
|
|
462
|
+
if (!(await exists(pendingFile)))
|
|
463
|
+
return { reconciled: false };
|
|
464
|
+
if (await exists(path.join(opts.snapshotDir, 'applied.json'))) {
|
|
465
|
+
// The full set landed; the pending marker is just stale. Clear it.
|
|
466
|
+
await fs.rm(pendingFile, { force: true }).catch(() => undefined);
|
|
467
|
+
return { reconciled: false };
|
|
468
|
+
}
|
|
469
|
+
await restoreOverlay(opts);
|
|
470
|
+
// Drop any orphaned staging dirs from the interrupted swap.
|
|
471
|
+
for (const pkgName of opts.pkgNames) {
|
|
472
|
+
const destPkg = path.join(opts.install.scopeDir, shortName(pkgName));
|
|
473
|
+
await fs.rm(path.join(destPkg, 'dist.new'), { recursive: true, force: true }).catch(() => undefined);
|
|
474
|
+
await fs.rm(path.join(destPkg, 'dist.bak'), { recursive: true, force: true }).catch(() => undefined);
|
|
475
|
+
}
|
|
476
|
+
await fs.rm(pendingFile, { force: true }).catch(() => undefined);
|
|
477
|
+
return { reconciled: true };
|
|
478
|
+
}
|
|
479
|
+
/** Reverse an overlay: restore each package's dist from the snapshot. */
|
|
480
|
+
export async function restoreOverlay(opts) {
|
|
481
|
+
for (const pkgName of opts.pkgNames) {
|
|
482
|
+
const snap = path.join(opts.snapshotDir, shortName(pkgName));
|
|
483
|
+
if (!(await exists(snap)))
|
|
484
|
+
continue;
|
|
485
|
+
const destDist = path.join(opts.install.scopeDir, shortName(pkgName), 'dist');
|
|
486
|
+
await fs.rm(destDist, { recursive: true, force: true });
|
|
487
|
+
await fs.cp(snap, destDist, { recursive: true });
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
async function exists(p) {
|
|
491
|
+
return fs.access(p).then(() => true).catch(() => false);
|
|
492
|
+
}
|
|
493
|
+
// ── boot-time finalize ────────────────────────────────────────────────────────────
|
|
494
|
+
/** Whether the snapshot dir holds a consistent, fully-applied overlay for `pkgNames`. */
|
|
495
|
+
async function overlayApplied(snapshotDir, pkgNames) {
|
|
496
|
+
try {
|
|
497
|
+
const applied = JSON.parse(await fs.readFile(path.join(snapshotDir, 'applied.json'), 'utf8'));
|
|
498
|
+
const got = new Set(applied.packages ?? []);
|
|
499
|
+
return pkgNames.every((p) => got.has(p));
|
|
500
|
+
}
|
|
501
|
+
catch {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Called early on every CLI boot. Reaching this point means the (possibly
|
|
507
|
+
* overlaid) core code imported successfully, so a cleanly-applied
|
|
508
|
+
* `staged_restart` txn is committed. The primary defense against a bad patch is
|
|
509
|
+
* the pre-overlay build+typecheck+test in verify; this adds two boot-time
|
|
510
|
+
* safety nets when an `install` is supplied:
|
|
511
|
+
* - reconcile an overlay interrupted mid-swap (partial dist set) by restoring
|
|
512
|
+
* the snapshot, and mark that txn rolled_back rather than committing a mixed
|
|
513
|
+
* core that merely imported far enough to reach this hook;
|
|
514
|
+
* - refuse to commit unless `applied.json` records every journal package, so an
|
|
515
|
+
* inconsistent overlay keeps its rollback snapshot instead of GC-ing it.
|
|
516
|
+
* Without `install` it stays best-effort (commits any staged txn) for callers
|
|
517
|
+
* that cannot resolve the live install.
|
|
518
|
+
*/
|
|
519
|
+
export async function finalizeStagedCoreUpdate(moxxyDir, install, keepTerminal = 5) {
|
|
520
|
+
const committed = [];
|
|
521
|
+
for (const j of await listCoreTxns(moxxyDir)) {
|
|
522
|
+
if (j.state !== 'staged_restart')
|
|
523
|
+
continue;
|
|
524
|
+
const snapDir = path.join(coreTxnDir(moxxyDir, j.txnId), 'snapshot');
|
|
525
|
+
if (install) {
|
|
526
|
+
const recon = await reconcileOverlay({
|
|
527
|
+
install,
|
|
528
|
+
pkgNames: j.packages,
|
|
529
|
+
snapshotDir: snapDir,
|
|
530
|
+
}).catch(() => ({ reconciled: false }));
|
|
531
|
+
if (recon.reconciled) {
|
|
532
|
+
j.state = 'rolled_back';
|
|
533
|
+
await writeCoreJournal(moxxyDir, j).catch(() => undefined);
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
if (!(await overlayApplied(snapDir, j.packages))) {
|
|
537
|
+
// The overlay never recorded a complete apply — restore and back out
|
|
538
|
+
// rather than commit (and then GC) a possibly-broken core.
|
|
539
|
+
await restoreOverlay({ install, pkgNames: j.packages, snapshotDir: snapDir }).catch(() => undefined);
|
|
540
|
+
j.state = 'rolled_back';
|
|
541
|
+
await writeCoreJournal(moxxyDir, j).catch(() => undefined);
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
j.state = 'committed';
|
|
546
|
+
await writeCoreJournal(moxxyDir, j).catch(() => undefined);
|
|
547
|
+
committed.push(j.txnId);
|
|
548
|
+
}
|
|
549
|
+
// Reclaim disk: every core txn parks a full pre-overlay dist snapshot, so old
|
|
550
|
+
// terminal txns would otherwise accumulate unbounded. Boot is the safe, single
|
|
551
|
+
// place to prune (all staged txns above are now terminal). Best-effort.
|
|
552
|
+
await gcCoreTxns(moxxyDir, keepTerminal).catch(() => undefined);
|
|
553
|
+
return committed;
|
|
554
|
+
}
|
|
555
|
+
export function newCoreTxnId(now = new Date()) {
|
|
556
|
+
return `core-${newTxnId(now)}`;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Prune old terminal core transactions. Each core txn parks a full pre-overlay
|
|
560
|
+
* `dist` snapshot of every patched package (tens of MB), and nothing else ever
|
|
561
|
+
* deletes them — left unbounded they accumulate on disk across every
|
|
562
|
+
* apply/rollback cycle. Keep only the most recent `keep` terminal
|
|
563
|
+
* (committed / rolled_back) txns; never touch a non-terminal one (an open /
|
|
564
|
+
* provisioned / verified / staged_restart txn whose snapshot finalize or a
|
|
565
|
+
* rollback may still need). Best-effort: a failed delete is ignored.
|
|
566
|
+
*/
|
|
567
|
+
export async function gcCoreTxns(moxxyDir, keep) {
|
|
568
|
+
const all = await listCoreTxns(moxxyDir);
|
|
569
|
+
const terminal = all.filter((j) => j.state === 'committed' || j.state === 'rolled_back');
|
|
570
|
+
for (const j of terminal.slice(Math.max(0, keep))) {
|
|
571
|
+
await fs.rm(coreTxnDir(moxxyDir, j.txnId), { recursive: true, force: true }).catch(() => undefined);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Resolve a clone-relative path, refusing anything that escapes the repo —
|
|
576
|
+
* including via a symlink. `path.resolve` collapses literal `..`, but the clone
|
|
577
|
+
* is git-controlled and can contain symlinks, and core_write/core_edit follow
|
|
578
|
+
* them (fs.writeFile/readFile dereference), so a path that textually stays inside
|
|
579
|
+
* the repo but traverses a symlink could read or clobber files outside the clone
|
|
580
|
+
* (the live install, ~/.ssh, …). We therefore (1) keep the cheap textual gate,
|
|
581
|
+
* then (2) re-check against the realpath of the repo root and reject if any
|
|
582
|
+
* existing component of the target is a symlink.
|
|
583
|
+
*/
|
|
584
|
+
export function safeRepoPath(repo, rel) {
|
|
585
|
+
const root = path.resolve(repo);
|
|
586
|
+
const resolved = path.resolve(repo, rel);
|
|
587
|
+
if (resolved !== root && !resolved.startsWith(root + path.sep)) {
|
|
588
|
+
throw new Error(`path escapes the provisioned repo: ${rel}`);
|
|
589
|
+
}
|
|
590
|
+
// Resolve the repo root through any symlinks once; everything must stay under it.
|
|
591
|
+
let realRoot;
|
|
592
|
+
try {
|
|
593
|
+
realRoot = realpathSync(root);
|
|
594
|
+
}
|
|
595
|
+
catch {
|
|
596
|
+
// Repo root not provisioned yet — the textual gate is the best we can do.
|
|
597
|
+
return resolved;
|
|
598
|
+
}
|
|
599
|
+
// The portion *inside* the repo is the path relative to the (textual) root —
|
|
600
|
+
// computed from `resolved`, NOT by re-resolving `rel` against realRoot. An
|
|
601
|
+
// absolute `rel` (legitimately repo-prefixed) makes `path.resolve(realRoot,
|
|
602
|
+
// rel)` ignore realRoot, and when the root traverses a symlink (e.g. macOS
|
|
603
|
+
// /var→/private/var, or a symlinked $HOME) the relative diff is then all `..`
|
|
604
|
+
// and a valid in-repo absolute path is wrongly rejected. Anchoring the
|
|
605
|
+
// already-validated in-repo segments onto realRoot avoids that.
|
|
606
|
+
const relParts = path.relative(root, resolved).split(path.sep).filter(Boolean);
|
|
607
|
+
if (relParts.some((p) => p === '..')) {
|
|
608
|
+
throw new Error(`path escapes the provisioned repo: ${rel}`);
|
|
609
|
+
}
|
|
610
|
+
let cur = realRoot;
|
|
611
|
+
for (const part of relParts) {
|
|
612
|
+
cur = path.join(cur, part);
|
|
613
|
+
let st;
|
|
614
|
+
try {
|
|
615
|
+
st = lstatSync(cur);
|
|
616
|
+
}
|
|
617
|
+
catch {
|
|
618
|
+
break; // component doesn't exist yet (the file we're about to create) — stop.
|
|
619
|
+
}
|
|
620
|
+
if (st.isSymbolicLink()) {
|
|
621
|
+
throw new Error(`path traverses a symlink, refusing: ${rel}`);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
return path.join(realRoot, ...relParts);
|
|
625
|
+
}
|
|
626
|
+
//# sourceMappingURL=core-update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core-update.js","sourceRoot":"","sources":["../src/core-update.ts"],"names":[],"mappings":"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"}
|