@decohere/flux 0.0.1-dev.95 → 0.0.1-dev.97
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.
|
@@ -160,8 +160,10 @@ class HotReloadServer extends _nodeevents.EventEmitter {
|
|
|
160
160
|
try {
|
|
161
161
|
const mod = await this.loader.importEntry(entryPath);
|
|
162
162
|
state.module = mod?.default;
|
|
163
|
+
state.failed = false;
|
|
163
164
|
} catch (error) {
|
|
164
165
|
state.module = undefined;
|
|
166
|
+
state.failed = true;
|
|
165
167
|
this.logger.error("There was an error booting the entry point. Your application may not function as expected", error);
|
|
166
168
|
}
|
|
167
169
|
}
|
|
@@ -309,6 +311,7 @@ class HotReloadServer extends _nodeevents.EventEmitter {
|
|
|
309
311
|
this.loader.setSourceFile(fullPath, project);
|
|
310
312
|
this.moduleCache.set(fullPath, null);
|
|
311
313
|
this.reloadIfAffected(fullPath);
|
|
314
|
+
this.retryFailedEntries(fullPath);
|
|
312
315
|
}
|
|
313
316
|
return;
|
|
314
317
|
}
|
|
@@ -316,7 +319,25 @@ class HotReloadServer extends _nodeevents.EventEmitter {
|
|
|
316
319
|
if (!project.isSourceFile(file)) return;
|
|
317
320
|
this.loader.invalidateTranspile(fullPath);
|
|
318
321
|
this.reloadIfAffected(fullPath);
|
|
322
|
+
this.retryFailedEntries(fullPath);
|
|
319
323
|
};
|
|
324
|
+
/**
|
|
325
|
+
* A failed boot (e.g. importing a file that doesn't exist yet) may have recorded no
|
|
326
|
+
* dependency edges, so the graph can't tell whether this save fixes it. Any source
|
|
327
|
+
* add or change retries failed entries (#512).
|
|
328
|
+
*/ retryFailedEntries(fullPath) {
|
|
329
|
+
const failed = [
|
|
330
|
+
...this.entries.values()
|
|
331
|
+
].filter((entry)=>entry.failed);
|
|
332
|
+
if (failed.length === 0) return;
|
|
333
|
+
for (const entry of failed){
|
|
334
|
+
// New URL version: Node caches the failed load and would replay the same error.
|
|
335
|
+
this.invalidateModuleCaches(entry.path);
|
|
336
|
+
this.pendingEntryReboots.add(entry.path);
|
|
337
|
+
}
|
|
338
|
+
this.pendingTriggers.add(fullPath);
|
|
339
|
+
this.scheduleReboot();
|
|
340
|
+
}
|
|
320
341
|
reloadIfAffected(fullPath) {
|
|
321
342
|
const deps = this.getDependencyGraph(fullPath);
|
|
322
343
|
const modules = [
|
|
@@ -345,30 +366,24 @@ class HotReloadServer extends _nodeevents.EventEmitter {
|
|
|
345
366
|
return true;
|
|
346
367
|
}
|
|
347
368
|
// ── Dependency graph ─────────────────────────────────────────────────────
|
|
348
|
-
|
|
369
|
+
/**
|
|
370
|
+
* Every module that imports `moduleId`, directly or transitively. Visits each module
|
|
371
|
+
* once: import graphs share modules (diamonds) and may legally contain cycles (#515).
|
|
372
|
+
*/ getDependencyGraph(moduleId) {
|
|
349
373
|
if (this.isSelf(moduleId)) return [];
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
...parentModules
|
|
361
|
-
]);
|
|
362
|
-
subDeps = [
|
|
363
|
-
...subDeps,
|
|
364
|
-
...subs
|
|
365
|
-
];
|
|
374
|
+
const found = new Set();
|
|
375
|
+
const queue = [
|
|
376
|
+
moduleId
|
|
377
|
+
];
|
|
378
|
+
for(let next = queue.shift(); next != null; next = queue.shift()){
|
|
379
|
+
for (const importer of this.dependencies.get(next) ?? []){
|
|
380
|
+
if (found.has(importer)) continue;
|
|
381
|
+
found.add(importer);
|
|
382
|
+
if (this.loader.hasSourceFile(importer) && !this.isSelf(importer)) queue.push(importer);
|
|
383
|
+
}
|
|
366
384
|
}
|
|
367
385
|
return [
|
|
368
|
-
...
|
|
369
|
-
...moduleDeps,
|
|
370
|
-
...subDeps
|
|
371
|
-
])
|
|
386
|
+
...found
|
|
372
387
|
];
|
|
373
388
|
}
|
|
374
389
|
trackDependency(filePath, parentPath) {
|
|
@@ -128,8 +128,10 @@ export class HotReloadServer extends EventEmitter {
|
|
|
128
128
|
try {
|
|
129
129
|
const mod = await this.loader.importEntry(entryPath);
|
|
130
130
|
state.module = mod?.default;
|
|
131
|
+
state.failed = false;
|
|
131
132
|
} catch (error) {
|
|
132
133
|
state.module = undefined;
|
|
134
|
+
state.failed = true;
|
|
133
135
|
this.logger.error("There was an error booting the entry point. Your application may not function as expected", error);
|
|
134
136
|
}
|
|
135
137
|
}
|
|
@@ -277,6 +279,7 @@ export class HotReloadServer extends EventEmitter {
|
|
|
277
279
|
this.loader.setSourceFile(fullPath, project);
|
|
278
280
|
this.moduleCache.set(fullPath, null);
|
|
279
281
|
this.reloadIfAffected(fullPath);
|
|
282
|
+
this.retryFailedEntries(fullPath);
|
|
280
283
|
}
|
|
281
284
|
return;
|
|
282
285
|
}
|
|
@@ -284,7 +287,25 @@ export class HotReloadServer extends EventEmitter {
|
|
|
284
287
|
if (!project.isSourceFile(file)) return;
|
|
285
288
|
this.loader.invalidateTranspile(fullPath);
|
|
286
289
|
this.reloadIfAffected(fullPath);
|
|
290
|
+
this.retryFailedEntries(fullPath);
|
|
287
291
|
};
|
|
292
|
+
/**
|
|
293
|
+
* A failed boot (e.g. importing a file that doesn't exist yet) may have recorded no
|
|
294
|
+
* dependency edges, so the graph can't tell whether this save fixes it. Any source
|
|
295
|
+
* add or change retries failed entries (#512).
|
|
296
|
+
*/ retryFailedEntries(fullPath) {
|
|
297
|
+
const failed = [
|
|
298
|
+
...this.entries.values()
|
|
299
|
+
].filter((entry)=>entry.failed);
|
|
300
|
+
if (failed.length === 0) return;
|
|
301
|
+
for (const entry of failed){
|
|
302
|
+
// New URL version: Node caches the failed load and would replay the same error.
|
|
303
|
+
this.invalidateModuleCaches(entry.path);
|
|
304
|
+
this.pendingEntryReboots.add(entry.path);
|
|
305
|
+
}
|
|
306
|
+
this.pendingTriggers.add(fullPath);
|
|
307
|
+
this.scheduleReboot();
|
|
308
|
+
}
|
|
288
309
|
reloadIfAffected(fullPath) {
|
|
289
310
|
const deps = this.getDependencyGraph(fullPath);
|
|
290
311
|
const modules = [
|
|
@@ -313,30 +334,24 @@ export class HotReloadServer extends EventEmitter {
|
|
|
313
334
|
return true;
|
|
314
335
|
}
|
|
315
336
|
// ── Dependency graph ─────────────────────────────────────────────────────
|
|
316
|
-
|
|
337
|
+
/**
|
|
338
|
+
* Every module that imports `moduleId`, directly or transitively. Visits each module
|
|
339
|
+
* once: import graphs share modules (diamonds) and may legally contain cycles (#515).
|
|
340
|
+
*/ getDependencyGraph(moduleId) {
|
|
317
341
|
if (this.isSelf(moduleId)) return [];
|
|
318
|
-
const
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
...parentModules
|
|
329
|
-
]);
|
|
330
|
-
subDeps = [
|
|
331
|
-
...subDeps,
|
|
332
|
-
...subs
|
|
333
|
-
];
|
|
342
|
+
const found = new Set();
|
|
343
|
+
const queue = [
|
|
344
|
+
moduleId
|
|
345
|
+
];
|
|
346
|
+
for(let next = queue.shift(); next != null; next = queue.shift()){
|
|
347
|
+
for (const importer of this.dependencies.get(next) ?? []){
|
|
348
|
+
if (found.has(importer)) continue;
|
|
349
|
+
found.add(importer);
|
|
350
|
+
if (this.loader.hasSourceFile(importer) && !this.isSelf(importer)) queue.push(importer);
|
|
351
|
+
}
|
|
334
352
|
}
|
|
335
353
|
return [
|
|
336
|
-
...
|
|
337
|
-
...moduleDeps,
|
|
338
|
-
...subDeps
|
|
339
|
-
])
|
|
354
|
+
...found
|
|
340
355
|
];
|
|
341
356
|
}
|
|
342
357
|
trackDependency(filePath, parentPath) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decohere/flux",
|
|
3
|
-
"version": "0.0.1-dev.
|
|
3
|
+
"version": "0.0.1-dev.97",
|
|
4
4
|
"description": "Hot module reload server for Node.js ESM applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@decohere/crucible": "0.0.1-dev.
|
|
29
|
-
"@decohere/forge": "0.0.1-dev.
|
|
30
|
-
"@decohere/mesh": "0.0.1-dev.
|
|
31
|
-
"@decohere/nexus": "0.0.1-dev.
|
|
32
|
-
"@decohere/scribe": "0.0.1-dev.
|
|
28
|
+
"@decohere/crucible": "0.0.1-dev.97",
|
|
29
|
+
"@decohere/forge": "0.0.1-dev.97",
|
|
30
|
+
"@decohere/mesh": "0.0.1-dev.97",
|
|
31
|
+
"@decohere/nexus": "0.0.1-dev.97",
|
|
32
|
+
"@decohere/scribe": "0.0.1-dev.97",
|
|
33
33
|
"commander": "^13.1.0",
|
|
34
34
|
"rxjs": "^7.8.2"
|
|
35
35
|
},
|
|
@@ -70,7 +70,17 @@ export declare class HotReloadServer extends EventEmitter<HotReloadServerEvents>
|
|
|
70
70
|
*/
|
|
71
71
|
private onPostResolve;
|
|
72
72
|
private onFileChange;
|
|
73
|
+
/**
|
|
74
|
+
* A failed boot (e.g. importing a file that doesn't exist yet) may have recorded no
|
|
75
|
+
* dependency edges, so the graph can't tell whether this save fixes it. Any source
|
|
76
|
+
* add or change retries failed entries (#512).
|
|
77
|
+
*/
|
|
78
|
+
private retryFailedEntries;
|
|
73
79
|
private reloadIfAffected;
|
|
80
|
+
/**
|
|
81
|
+
* Every module that imports `moduleId`, directly or transitively. Visits each module
|
|
82
|
+
* once: import graphs share modules (diamonds) and may legally contain cycles (#515).
|
|
83
|
+
*/
|
|
74
84
|
private getDependencyGraph;
|
|
75
85
|
private trackDependency;
|
|
76
86
|
private getCachedOrNew;
|