@akanjs/cli 2.4.1-rc.3 → 2.4.1-rc.5
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/.build-stamp +1 -0
- package/{agent.command-h4afc69n.js → agent.command-t4346579.js} +6 -6
- package/{application.command-jkmbsd1x.js → application.command-zkmeemdt.js} +5 -4
- package/{applicationBuildRunner-ny84tjhc.js → applicationBuildRunner-5w8j9yp7.js} +2 -1
- package/buildBatch.proc.js +20 -3
- package/{capacitorApp-y0h6cgft.js → capacitorApp-wnxzrppx.js} +2 -2
- package/{cloud.command-53j76grx.js → cloud.command-5ztqxppm.js} +8 -7
- package/{context.command-ds3mka9p.js → context.command-smwxwgwf.js} +13 -13
- package/{guideline.command-ya0dh44f.js → guideline.command-1r0esdjs.js} +3 -3
- package/incrementalBuilder.proc.js +90 -34
- package/index-0fn1r7gg.js +466 -0
- package/{index-1fpjvqhs.js → index-0jwvs8vp.js} +11 -11
- package/{index-a6sbyy0b.js → index-0t7pwff2.js} +3 -0
- package/{index-h6ca6qg0.js → index-2v10yr8g.js} +1 -1
- package/{index-m9pca6jv.js → index-2v6a4wd5.js} +4 -4
- package/{index-45aj5ry0.js → index-3sd2vape.js} +3 -3
- package/{index-gb26e7z0.js → index-ahpcr9ss.js} +3 -3
- package/{index-8rc0bm04.js → index-eay4t1te.js} +2 -2
- package/{index-qaq13qk3.js → index-eqxmxan6.js} +1 -1
- package/{index-pmm9e2jf.js → index-fh990y67.js} +2 -2
- package/{index-dynknvzd.js → index-gr4cjv99.js} +3 -3
- package/{index-1xdrsbry.js → index-hk58kr1m.js} +1 -1
- package/{index-85msc0wg.js → index-jbtn8h1y.js} +3 -3
- package/{index-q7zcac6n.js → index-khzzttv1.js} +108 -191
- package/{index-rgfxj6qc.js → index-n5y2gbf2.js} +307 -15
- package/{index-n6h3482q.js → index-nv7et4t3.js} +2 -2
- package/{index-hwzpw9c1.js → index-pya1h7wx.js} +3 -3
- package/{index-hdqztm58.js → index-qpz4csbs.js} +1 -1
- package/{index-0hjg9qs5.js → index-s9yajzkj.js} +5 -5
- package/{index-fmky5k3p.js → index-wh201a76.js} +5 -5
- package/{index-swf4bmbg.js → index-y4kg682s.js} +1 -1
- package/index.js +18 -18
- package/{library.command-r15zdqvp.js → library.command-jrew04m6.js} +3 -3
- package/{localRegistry.command-25sv5hmt.js → localRegistry.command-m08dkm1b.js} +7 -6
- package/{module.command-tnj2bzst.js → module.command-p98t7522.js} +6 -6
- package/{package.command-5x5m0ej1.js → package.command-57dyrfmn.js} +3 -3
- package/package.json +2 -2
- package/{page.command-c6xdx0xm.js → page.command-tas6f3na.js} +3 -3
- package/{primitive.command-q1ycj5vr.js → primitive.command-bjrbsakw.js} +7 -7
- package/{quality.command-es67wvdp.js → quality.command-zavaafbw.js} +2 -2
- package/{repair.command-677675vw.js → repair.command-je57wx67.js} +5 -5
- package/{scalar.command-bmrmp8n4.js → scalar.command-gqqyy1kr.js} +5 -5
- package/{workflow.command-64550hka.js → workflow.command-d6mrc47s.js} +10 -10
- package/{workspace.command-pmfxxfew.js → workspace.command-bbg96z8k.js} +20 -19
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// pkgs/@akanjs/devkit/frontendBuild/hmrWatcher.ts
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path3 from "path";
|
|
5
|
+
|
|
6
|
+
// pkgs/@akanjs/devkit/frontendBuild/hmrChangeClassifier.ts
|
|
7
|
+
import path from "path";
|
|
8
|
+
var SOURCE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
9
|
+
var CSS_EXTS = new Set([".css"]);
|
|
10
|
+
var CONFIG_BASENAMES = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
|
|
11
|
+
|
|
12
|
+
class HmrChangeClassifier {
|
|
13
|
+
classify(abs) {
|
|
14
|
+
if (this.#isUninteresting(abs))
|
|
15
|
+
return "ignore";
|
|
16
|
+
const base = path.basename(abs);
|
|
17
|
+
if (CONFIG_BASENAMES.has(base))
|
|
18
|
+
return "config";
|
|
19
|
+
const ext = path.extname(abs).toLowerCase();
|
|
20
|
+
if (CSS_EXTS.has(ext))
|
|
21
|
+
return "css";
|
|
22
|
+
if (SOURCE_EXTS.has(ext))
|
|
23
|
+
return "code";
|
|
24
|
+
return "ignore";
|
|
25
|
+
}
|
|
26
|
+
#isUninteresting(abs) {
|
|
27
|
+
const base = path.basename(abs);
|
|
28
|
+
if (!base)
|
|
29
|
+
return true;
|
|
30
|
+
if (base.startsWith("."))
|
|
31
|
+
return true;
|
|
32
|
+
if (base.endsWith("~") || base.endsWith(".swp") || base.endsWith(".swx") || base.endsWith(".tmp"))
|
|
33
|
+
return true;
|
|
34
|
+
if (abs.includes(`${path.sep}node_modules${path.sep}`))
|
|
35
|
+
return true;
|
|
36
|
+
if (abs.includes(`${path.sep}.akan${path.sep}`))
|
|
37
|
+
return true;
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// pkgs/@akanjs/devkit/frontendBuild/sourceMtimeIndex.ts
|
|
43
|
+
import { readdir, stat } from "fs/promises";
|
|
44
|
+
import path2 from "path";
|
|
45
|
+
var UNREADABLE = Number.NaN;
|
|
46
|
+
|
|
47
|
+
class SourceMtimeIndex {
|
|
48
|
+
#roots;
|
|
49
|
+
#classifier;
|
|
50
|
+
#files = new Map;
|
|
51
|
+
#dirs = new Map;
|
|
52
|
+
#unreadable = new Map;
|
|
53
|
+
#primed = false;
|
|
54
|
+
#queue = Promise.resolve();
|
|
55
|
+
constructor({ roots, classifier }) {
|
|
56
|
+
this.#roots = SourceMtimeIndex.#pruneNestedRoots(roots);
|
|
57
|
+
this.#classifier = classifier ?? new HmrChangeClassifier;
|
|
58
|
+
}
|
|
59
|
+
get primed() {
|
|
60
|
+
return this.#primed;
|
|
61
|
+
}
|
|
62
|
+
get trackedFileCount() {
|
|
63
|
+
return this.#files.size;
|
|
64
|
+
}
|
|
65
|
+
get coverageGaps() {
|
|
66
|
+
return [...this.#unreadable].map(([file, code]) => ({ path: file, code }));
|
|
67
|
+
}
|
|
68
|
+
async prime() {
|
|
69
|
+
await this.#serialize(async () => {
|
|
70
|
+
this.#files.clear();
|
|
71
|
+
this.#dirs.clear();
|
|
72
|
+
this.#unreadable.clear();
|
|
73
|
+
await Promise.all(this.#roots.map((root) => this.#walk(root, null)));
|
|
74
|
+
this.#primed = true;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
async collectChanges() {
|
|
78
|
+
return this.#serialize(async () => {
|
|
79
|
+
if (!this.#primed)
|
|
80
|
+
return [];
|
|
81
|
+
const changed = new Set;
|
|
82
|
+
await this.#collectFileChanges(changed);
|
|
83
|
+
await this.#collectDirChanges(changed);
|
|
84
|
+
return [...changed];
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async#serialize(work) {
|
|
88
|
+
const run = this.#queue.then(work, work);
|
|
89
|
+
this.#queue = run.catch(() => {
|
|
90
|
+
return;
|
|
91
|
+
});
|
|
92
|
+
return run;
|
|
93
|
+
}
|
|
94
|
+
async absorb(paths) {
|
|
95
|
+
await this.#serialize(async () => {
|
|
96
|
+
if (!this.#primed)
|
|
97
|
+
return;
|
|
98
|
+
await Promise.all(paths.map(async (file) => {
|
|
99
|
+
const abs = path2.resolve(file);
|
|
100
|
+
const stats = await stat(abs).catch(() => null);
|
|
101
|
+
if (!stats?.isFile()) {
|
|
102
|
+
this.#files.delete(abs);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.#files.set(abs, { mtimeMs: stats.mtimeMs, size: stats.size });
|
|
106
|
+
}));
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async#collectFileChanges(changed) {
|
|
110
|
+
await Promise.all([...this.#files.keys()].map(async (abs) => {
|
|
111
|
+
const { stats, err } = await SourceMtimeIndex.#statPath(abs);
|
|
112
|
+
if (!stats) {
|
|
113
|
+
if (err && !SourceMtimeIndex.#isMissing(err)) {
|
|
114
|
+
this.#unreadable.set(abs, err.code ?? "EUNKNOWN");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.#files.delete(abs);
|
|
118
|
+
this.#unreadable.delete(abs);
|
|
119
|
+
changed.add(abs);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.#unreadable.delete(abs);
|
|
123
|
+
if (!stats.isFile()) {
|
|
124
|
+
this.#files.delete(abs);
|
|
125
|
+
changed.add(abs);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const known = this.#files.get(abs);
|
|
129
|
+
if (known && known.mtimeMs === stats.mtimeMs && known.size === stats.size)
|
|
130
|
+
return;
|
|
131
|
+
this.#files.set(abs, { mtimeMs: stats.mtimeMs, size: stats.size });
|
|
132
|
+
changed.add(abs);
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
async#collectDirChanges(changed) {
|
|
136
|
+
const moved = [];
|
|
137
|
+
const gone = [];
|
|
138
|
+
await Promise.all([...this.#dirs.entries()].map(async ([dir, mtimeMs]) => {
|
|
139
|
+
const { stats, err } = await SourceMtimeIndex.#statPath(dir);
|
|
140
|
+
if (!stats?.isDirectory()) {
|
|
141
|
+
if (err && !SourceMtimeIndex.#isMissing(err)) {
|
|
142
|
+
this.#markUnreadable(dir, err);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
gone.push(dir);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (stats.mtimeMs !== mtimeMs)
|
|
149
|
+
moved.push(dir);
|
|
150
|
+
}));
|
|
151
|
+
for (const dir of gone)
|
|
152
|
+
this.#forget(dir);
|
|
153
|
+
for (const dir of moved)
|
|
154
|
+
await this.#walk(dir, changed);
|
|
155
|
+
}
|
|
156
|
+
async#walk(dir, changed) {
|
|
157
|
+
const [listing, dirStat] = await Promise.all([SourceMtimeIndex.#readdirPath(dir), SourceMtimeIndex.#statPath(dir)]);
|
|
158
|
+
const entries = listing.entries;
|
|
159
|
+
const dirStats = dirStat.stats;
|
|
160
|
+
if (!entries || !dirStats?.isDirectory()) {
|
|
161
|
+
const err = listing.err ?? dirStat.err;
|
|
162
|
+
if (err && !SourceMtimeIndex.#isMissing(err)) {
|
|
163
|
+
this.#markUnreadable(dir, err);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
this.#forget(dir);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const known = this.#dirs.has(dir);
|
|
170
|
+
this.#dirs.set(dir, dirStats.mtimeMs);
|
|
171
|
+
this.#unreadable.delete(dir);
|
|
172
|
+
const descend = [];
|
|
173
|
+
const present = new Set;
|
|
174
|
+
let blind = false;
|
|
175
|
+
for (const entry of entries) {
|
|
176
|
+
if (SourceMtimeIndex.#skipDirent(entry.name))
|
|
177
|
+
continue;
|
|
178
|
+
const abs = path2.join(dir, entry.name);
|
|
179
|
+
if (entry.isDirectory()) {
|
|
180
|
+
descend.push(abs);
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (!entry.isFile())
|
|
184
|
+
continue;
|
|
185
|
+
if (this.#classifier.classify(abs) === "ignore")
|
|
186
|
+
continue;
|
|
187
|
+
present.add(abs);
|
|
188
|
+
const { stats, err } = await SourceMtimeIndex.#statPath(abs);
|
|
189
|
+
if (!stats?.isFile()) {
|
|
190
|
+
if (err && !SourceMtimeIndex.#isMissing(err)) {
|
|
191
|
+
this.#unreadable.set(abs, err.code ?? "EUNKNOWN");
|
|
192
|
+
blind = true;
|
|
193
|
+
}
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
this.#unreadable.delete(abs);
|
|
197
|
+
const previous = this.#files.get(abs);
|
|
198
|
+
if (previous && previous.mtimeMs === stats.mtimeMs && previous.size === stats.size)
|
|
199
|
+
continue;
|
|
200
|
+
this.#files.set(abs, { mtimeMs: stats.mtimeMs, size: stats.size });
|
|
201
|
+
changed?.add(abs);
|
|
202
|
+
}
|
|
203
|
+
if (known) {
|
|
204
|
+
for (const abs of [...this.#files.keys()]) {
|
|
205
|
+
if (present.has(abs) || path2.dirname(abs) !== dir)
|
|
206
|
+
continue;
|
|
207
|
+
this.#files.delete(abs);
|
|
208
|
+
changed?.add(abs);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (blind)
|
|
212
|
+
this.#dirs.set(dir, UNREADABLE);
|
|
213
|
+
await Promise.all(descend.filter((sub) => !this.#dirs.has(sub)).map((sub) => this.#walk(sub, changed)));
|
|
214
|
+
}
|
|
215
|
+
#markUnreadable(dir, err) {
|
|
216
|
+
this.#dirs.set(dir, UNREADABLE);
|
|
217
|
+
this.#unreadable.set(dir, err.code ?? "EUNKNOWN");
|
|
218
|
+
}
|
|
219
|
+
#forget(dir) {
|
|
220
|
+
const prefix = `${dir}${path2.sep}`;
|
|
221
|
+
this.#dirs.delete(dir);
|
|
222
|
+
this.#unreadable.delete(dir);
|
|
223
|
+
for (const known of [...this.#dirs.keys()])
|
|
224
|
+
if (known.startsWith(prefix))
|
|
225
|
+
this.#dirs.delete(known);
|
|
226
|
+
for (const known of [...this.#unreadable.keys()])
|
|
227
|
+
if (known.startsWith(prefix))
|
|
228
|
+
this.#unreadable.delete(known);
|
|
229
|
+
}
|
|
230
|
+
static async#statPath(abs) {
|
|
231
|
+
try {
|
|
232
|
+
return { stats: await stat(abs), err: null };
|
|
233
|
+
} catch (err) {
|
|
234
|
+
return { stats: null, err };
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
static async#readdirPath(dir) {
|
|
238
|
+
try {
|
|
239
|
+
return { entries: await readdir(dir, { withFileTypes: true }), err: null };
|
|
240
|
+
} catch (err) {
|
|
241
|
+
return { entries: null, err };
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
static #isMissing(err) {
|
|
245
|
+
return err.code === "ENOENT" || err.code === "ENOTDIR";
|
|
246
|
+
}
|
|
247
|
+
static #skipDirent(name) {
|
|
248
|
+
return !name || name.startsWith(".") || name === "node_modules";
|
|
249
|
+
}
|
|
250
|
+
static #pruneNestedRoots(roots) {
|
|
251
|
+
const resolved = [...new Set(roots.map((root) => path2.resolve(root)))].sort();
|
|
252
|
+
return resolved.filter((root) => !resolved.some((other) => other !== root && root.startsWith(`${other}${path2.sep}`)));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// pkgs/@akanjs/devkit/frontendBuild/hmrWatcher.ts
|
|
257
|
+
class HmrWatcher {
|
|
258
|
+
#roots;
|
|
259
|
+
#debounceMs;
|
|
260
|
+
#verifyDelayMs;
|
|
261
|
+
#onBatch;
|
|
262
|
+
#logger;
|
|
263
|
+
#watchers = [];
|
|
264
|
+
#pending = new Map;
|
|
265
|
+
#hinted = new Set;
|
|
266
|
+
#classifier = new HmrChangeClassifier;
|
|
267
|
+
#index;
|
|
268
|
+
#timer = null;
|
|
269
|
+
#verifyTimer = null;
|
|
270
|
+
#stopped = false;
|
|
271
|
+
#flushing = false;
|
|
272
|
+
#unreportedChanges = 0;
|
|
273
|
+
#reportedCompensating = false;
|
|
274
|
+
#reportedGaps = "";
|
|
275
|
+
constructor(opts) {
|
|
276
|
+
this.#roots = [...new Set(opts.roots.map((r) => path3.resolve(r)))];
|
|
277
|
+
this.#debounceMs = opts.debounceMs ?? 80;
|
|
278
|
+
this.#verifyDelayMs = opts.verifyDelayMs ?? 250;
|
|
279
|
+
this.#onBatch = opts.onBatch;
|
|
280
|
+
this.#logger = opts.logger;
|
|
281
|
+
this.#index = new SourceMtimeIndex({ roots: this.#roots, classifier: this.#classifier });
|
|
282
|
+
}
|
|
283
|
+
get unreportedChanges() {
|
|
284
|
+
return this.#unreportedChanges;
|
|
285
|
+
}
|
|
286
|
+
async start() {
|
|
287
|
+
for (const root of this.#roots) {
|
|
288
|
+
try {
|
|
289
|
+
const w = fs.watch(root, { recursive: true, persistent: false }, (_event, filename) => {
|
|
290
|
+
if (!filename)
|
|
291
|
+
return;
|
|
292
|
+
const abs = path3.resolve(root, filename.toString());
|
|
293
|
+
this.#queue(abs);
|
|
294
|
+
});
|
|
295
|
+
this.#watchers.push(w);
|
|
296
|
+
this.#logger.verbose(`[hmr] watching ${root}`);
|
|
297
|
+
} catch (err) {
|
|
298
|
+
this.#logger.error(`[hmr] failed to watch ${root}: ${err.message}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
try {
|
|
302
|
+
await this.#index.prime();
|
|
303
|
+
this.#reportCoverageGaps();
|
|
304
|
+
this.#logger.verbose(`[hmr] tracking ${this.#index.trackedFileCount} source files for change verification`);
|
|
305
|
+
} catch (err) {
|
|
306
|
+
this.#logger.error(`[hmr] mtime index unavailable; falling back to watcher events alone, which drop concurrent saves: ${err.message}`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
stop() {
|
|
310
|
+
this.#stopped = true;
|
|
311
|
+
if (this.#timer)
|
|
312
|
+
clearTimeout(this.#timer);
|
|
313
|
+
if (this.#verifyTimer)
|
|
314
|
+
clearTimeout(this.#verifyTimer);
|
|
315
|
+
for (const w of this.#watchers) {
|
|
316
|
+
try {
|
|
317
|
+
w.close();
|
|
318
|
+
} catch {}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
async absorb(paths) {
|
|
322
|
+
if (paths.length === 0)
|
|
323
|
+
return;
|
|
324
|
+
await this.#index.absorb(paths);
|
|
325
|
+
}
|
|
326
|
+
#queue(abs) {
|
|
327
|
+
const kind = this.#classifier.classify(abs);
|
|
328
|
+
if (!this.#index.primed) {
|
|
329
|
+
if (kind === "ignore")
|
|
330
|
+
return;
|
|
331
|
+
this.#pending.set(abs, kind);
|
|
332
|
+
this.#scheduleFlush();
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
if (kind === "ignore") {
|
|
336
|
+
this.#scheduleVerify();
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
this.#hinted.add(abs);
|
|
340
|
+
this.#scheduleFlush();
|
|
341
|
+
}
|
|
342
|
+
#scheduleFlush() {
|
|
343
|
+
if (this.#flushing)
|
|
344
|
+
return;
|
|
345
|
+
if (this.#timer)
|
|
346
|
+
clearTimeout(this.#timer);
|
|
347
|
+
this.#timer = setTimeout(() => this.#flush(), this.#debounceMs);
|
|
348
|
+
}
|
|
349
|
+
#flush() {
|
|
350
|
+
this.#timer = null;
|
|
351
|
+
if (this.#stopped || this.#flushing)
|
|
352
|
+
return;
|
|
353
|
+
this.#drain();
|
|
354
|
+
}
|
|
355
|
+
async#drain() {
|
|
356
|
+
this.#flushing = true;
|
|
357
|
+
try {
|
|
358
|
+
while (!this.#stopped) {
|
|
359
|
+
await this.#mergeDetectedChanges();
|
|
360
|
+
if (this.#pending.size === 0)
|
|
361
|
+
break;
|
|
362
|
+
const files = Array.from(this.#pending.keys());
|
|
363
|
+
const kinds = new Set(this.#pending.values());
|
|
364
|
+
this.#pending.clear();
|
|
365
|
+
this.#hinted.clear();
|
|
366
|
+
try {
|
|
367
|
+
await this.#onBatch({ files, kinds });
|
|
368
|
+
} catch (e) {
|
|
369
|
+
this.#logger.error(`[hmr] onBatch error: ${e.message}`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
} finally {
|
|
373
|
+
this.#flushing = false;
|
|
374
|
+
if (!this.#stopped && this.#pending.size > 0)
|
|
375
|
+
this.#timer = setTimeout(() => this.#flush(), this.#debounceMs);
|
|
376
|
+
else
|
|
377
|
+
this.#scheduleVerify();
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
async#mergeDetectedChanges() {
|
|
381
|
+
const detected = await this.#index.collectChanges().catch((err) => {
|
|
382
|
+
this.#logger.error(`[hmr] mtime scan failed: ${err.message}`);
|
|
383
|
+
return [];
|
|
384
|
+
});
|
|
385
|
+
this.#reportCoverageGaps();
|
|
386
|
+
let unreported = 0;
|
|
387
|
+
for (const abs of detected) {
|
|
388
|
+
const kind = this.#classifier.classify(abs);
|
|
389
|
+
if (kind === "ignore")
|
|
390
|
+
continue;
|
|
391
|
+
if (!this.#hinted.has(abs))
|
|
392
|
+
unreported += 1;
|
|
393
|
+
this.#pending.set(abs, kind);
|
|
394
|
+
}
|
|
395
|
+
if (unreported === 0)
|
|
396
|
+
return;
|
|
397
|
+
this.#unreportedChanges += unreported;
|
|
398
|
+
if (!this.#reportedCompensating) {
|
|
399
|
+
this.#reportedCompensating = true;
|
|
400
|
+
this.#logger.info(`[hmr] recovered ${unreported} change(s) that fs.watch did not report; Bun coalesces concurrent saves and drops all but one, so changes are resolved by mtime`);
|
|
401
|
+
}
|
|
402
|
+
this.#logger.verbose(`[hmr] mtime scan found ${unreported} change(s) fs.watch never reported (${this.#unreportedChanges} total)`);
|
|
403
|
+
}
|
|
404
|
+
#reportCoverageGaps() {
|
|
405
|
+
const gaps = this.#index.coverageGaps;
|
|
406
|
+
const key = gaps.map((gap) => `${gap.code}:${gap.path}`).sort().join("|");
|
|
407
|
+
if (key === this.#reportedGaps)
|
|
408
|
+
return;
|
|
409
|
+
this.#reportedGaps = key;
|
|
410
|
+
if (gaps.length === 0) {
|
|
411
|
+
this.#logger.info("[hmr] all watch roots readable again; change detection is complete");
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
const shown = gaps.slice(0, 3).map((gap) => `${gap.path} (${gap.code})`).join(", ");
|
|
415
|
+
const rest = gaps.length > 3 ? ` and ${gaps.length - 3} more` : "";
|
|
416
|
+
this.#logger.warn(`[hmr] cannot read ${gaps.length} path(s), so edits underneath them will not rebuild: ${shown}${rest}`);
|
|
417
|
+
}
|
|
418
|
+
#scheduleVerify() {
|
|
419
|
+
if (this.#stopped || this.#verifyDelayMs <= 0)
|
|
420
|
+
return;
|
|
421
|
+
if (this.#verifyTimer)
|
|
422
|
+
clearTimeout(this.#verifyTimer);
|
|
423
|
+
this.#verifyTimer = setTimeout(() => {
|
|
424
|
+
this.#verifyTimer = null;
|
|
425
|
+
this.#verify();
|
|
426
|
+
}, this.#verifyDelayMs);
|
|
427
|
+
}
|
|
428
|
+
async#verify() {
|
|
429
|
+
if (this.#stopped || this.#flushing)
|
|
430
|
+
return;
|
|
431
|
+
await this.#mergeDetectedChanges();
|
|
432
|
+
if (this.#pending.size > 0)
|
|
433
|
+
await this.#drain();
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// pkgs/@akanjs/devkit/frontendBuild/watchRootResolver.ts
|
|
438
|
+
import fs2 from "fs";
|
|
439
|
+
import path4 from "path";
|
|
440
|
+
|
|
441
|
+
class WatchRootResolver {
|
|
442
|
+
#app;
|
|
443
|
+
constructor(app) {
|
|
444
|
+
this.#app = app;
|
|
445
|
+
}
|
|
446
|
+
async resolve() {
|
|
447
|
+
const tsconfig = await this.#app.getTsConfig();
|
|
448
|
+
const set = new Set;
|
|
449
|
+
set.add(path4.resolve(`${this.#app.cwdPath}/page`));
|
|
450
|
+
for (const targets of Object.values(tsconfig.compilerOptions.paths ?? {})) {
|
|
451
|
+
for (const target of targets) {
|
|
452
|
+
if (!target)
|
|
453
|
+
continue;
|
|
454
|
+
if (path4.isAbsolute(target))
|
|
455
|
+
continue;
|
|
456
|
+
const cleaned = target.replace(/\/?\*+.*$/, "").replace(/\/[^/]+\.[^/]+$/, "");
|
|
457
|
+
const resolved = path4.resolve(this.#app.workspace.workspaceRoot, cleaned);
|
|
458
|
+
if (fs2.existsSync(resolved))
|
|
459
|
+
set.add(resolved);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return [...set];
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
export { HmrWatcher, WatchRootResolver };
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
RepairRunner
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-jbtn8h1y.js";
|
|
5
5
|
import {
|
|
6
6
|
WorkflowRunner
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-3sd2vape.js";
|
|
8
8
|
import {
|
|
9
9
|
ScalarScript
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-ahpcr9ss.js";
|
|
11
11
|
import {
|
|
12
12
|
PrimitiveScript
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-2v6a4wd5.js";
|
|
14
14
|
import {
|
|
15
15
|
ModuleScript
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-wh201a76.js";
|
|
17
17
|
import {
|
|
18
18
|
isPlaceholderAppId
|
|
19
|
-
} from "./index-
|
|
19
|
+
} from "./index-hk58kr1m.js";
|
|
20
20
|
import {
|
|
21
21
|
AkanContextAnalyzer,
|
|
22
22
|
akanMcpInstallConfigPaths,
|
|
@@ -27,17 +27,17 @@ import {
|
|
|
27
27
|
renderDoctorText,
|
|
28
28
|
resourceList,
|
|
29
29
|
upsertCodexMcpServerBlock
|
|
30
|
-
} from "./index-
|
|
30
|
+
} from "./index-eay4t1te.js";
|
|
31
31
|
import {
|
|
32
32
|
buildAkanModuleContextIndex,
|
|
33
33
|
createWorkflowBaselineSummary,
|
|
34
34
|
createWorkflowStepRegistry,
|
|
35
35
|
jsonText,
|
|
36
36
|
toolingRolloutGate
|
|
37
|
-
} from "./index-
|
|
37
|
+
} from "./index-2v10yr8g.js";
|
|
38
38
|
import {
|
|
39
39
|
Prompter
|
|
40
|
-
} from "./index-
|
|
40
|
+
} from "./index-eqxmxan6.js";
|
|
41
41
|
import {
|
|
42
42
|
getMobileTargets
|
|
43
43
|
} from "./index-76rn3g2c.js";
|
|
@@ -45,10 +45,10 @@ import {
|
|
|
45
45
|
CommandContainer,
|
|
46
46
|
runner,
|
|
47
47
|
script
|
|
48
|
-
} from "./index-
|
|
48
|
+
} from "./index-qpz4csbs.js";
|
|
49
49
|
import {
|
|
50
50
|
AppExecutor
|
|
51
|
-
} from "./index-
|
|
51
|
+
} from "./index-0t7pwff2.js";
|
|
52
52
|
|
|
53
53
|
// pkgs/@akanjs/cli/context/context.script.ts
|
|
54
54
|
import { Logger } from "akanjs/common";
|
|
@@ -2369,6 +2369,9 @@ class AppExecutor extends SysExecutor {
|
|
|
2369
2369
|
return WorkspaceExecutor.getBaseDevEnv().env;
|
|
2370
2370
|
}
|
|
2371
2371
|
async getDevPort() {
|
|
2372
|
+
const pinned = Number(process.env.AKAN_DEV_PORT);
|
|
2373
|
+
if (Number.isInteger(pinned) && pinned > 0 && pinned <= 65535)
|
|
2374
|
+
return pinned;
|
|
2372
2375
|
const basePort = 8282;
|
|
2373
2376
|
const appNames = (await this.workspace.getApps()).sort((a, b) => a.localeCompare(b));
|
|
2374
2377
|
const appIndex = Math.max(appNames.indexOf(this.name), 0);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
ModuleScript
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-wh201a76.js";
|
|
5
5
|
import {
|
|
6
6
|
addFieldUiPolicyForType,
|
|
7
7
|
coerceFieldDefault,
|
|
@@ -34,15 +34,15 @@ import {
|
|
|
34
34
|
sourceFile,
|
|
35
35
|
validationCommandsForTarget,
|
|
36
36
|
viaBuilderParameterName
|
|
37
|
-
} from "./index-
|
|
37
|
+
} from "./index-2v10yr8g.js";
|
|
38
38
|
import {
|
|
39
39
|
script
|
|
40
|
-
} from "./index-
|
|
40
|
+
} from "./index-qpz4csbs.js";
|
|
41
41
|
import {
|
|
42
42
|
AppExecutor,
|
|
43
43
|
LibExecutor,
|
|
44
44
|
ModuleExecutor
|
|
45
|
-
} from "./index-
|
|
45
|
+
} from "./index-0t7pwff2.js";
|
|
46
46
|
|
|
47
47
|
// pkgs/@akanjs/cli/primitive/primitive.script.ts
|
|
48
48
|
import { capitalize } from "akanjs/common";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AkanContextAnalyzer
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-eay4t1te.js";
|
|
5
5
|
import {
|
|
6
6
|
WorkflowExecutor,
|
|
7
7
|
compactWorkflowInputs,
|
|
@@ -23,10 +23,10 @@ import {
|
|
|
23
23
|
workflowCommandsForPlan,
|
|
24
24
|
workflowPlanApproval,
|
|
25
25
|
writeWorkflowRunArtifact
|
|
26
|
-
} from "./index-
|
|
26
|
+
} from "./index-2v10yr8g.js";
|
|
27
27
|
import {
|
|
28
28
|
runner
|
|
29
|
-
} from "./index-
|
|
29
|
+
} from "./index-qpz4csbs.js";
|
|
30
30
|
|
|
31
31
|
// pkgs/@akanjs/cli/workflow/workflow.runner.ts
|
|
32
32
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
@@ -6,17 +6,17 @@ import {
|
|
|
6
6
|
createPassedPrimitiveReport,
|
|
7
7
|
generatedFilesForSync,
|
|
8
8
|
scalarChangedFiles
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-2v10yr8g.js";
|
|
10
10
|
import {
|
|
11
11
|
Prompter
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-eqxmxan6.js";
|
|
13
13
|
import {
|
|
14
14
|
AiSession
|
|
15
15
|
} from "./index-5vvwc0cz.js";
|
|
16
16
|
import {
|
|
17
17
|
runner,
|
|
18
18
|
script
|
|
19
|
-
} from "./index-
|
|
19
|
+
} from "./index-qpz4csbs.js";
|
|
20
20
|
|
|
21
21
|
// pkgs/@akanjs/cli/scalar/scalar.prompt.ts
|
|
22
22
|
import { input } from "@inquirer/prompts";
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
workflowRunArtifactPath,
|
|
4
4
|
workflowSyncDir
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-2v10yr8g.js";
|
|
6
6
|
import {
|
|
7
7
|
AppExecutor,
|
|
8
8
|
LibExecutor
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-0t7pwff2.js";
|
|
10
10
|
import {
|
|
11
11
|
FileSys
|
|
12
12
|
} from "./index-61keag0s.js";
|
|
@@ -7,14 +7,14 @@ import {
|
|
|
7
7
|
} from "./index-5vvwc0cz.js";
|
|
8
8
|
import {
|
|
9
9
|
openBrowser
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-n5y2gbf2.js";
|
|
11
11
|
import {
|
|
12
12
|
runner
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-qpz4csbs.js";
|
|
14
14
|
import {
|
|
15
15
|
AppExecutor,
|
|
16
16
|
WorkspaceExecutor
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-0t7pwff2.js";
|
|
18
18
|
|
|
19
19
|
// pkgs/@akanjs/cli/cloud/cloud.runner.ts
|
|
20
20
|
import path from "path";
|