@decohere/flux 0.0.1-dev.108 → 0.0.1-dev.11
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/commonjs/src/flux.command.js +2 -2
- package/commonjs/src/flux.module.js +7 -8
- package/commonjs/src/hot-reload-server.js +215 -302
- package/commonjs/src/index.js +2 -34
- package/commonjs/src/serve.action.js +5 -76
- package/commonjs/src/serve.command.js +3 -31
- package/es6/src/flux.command.js +2 -2
- package/es6/src/flux.module.js +7 -8
- package/es6/src/hot-reload-server.js +172 -283
- package/es6/src/index.js +3 -5
- package/es6/src/serve.action.js +7 -71
- package/es6/src/serve.command.js +3 -31
- package/package.json +6 -7
- package/types/src/flux.module.d.ts +0 -2
- package/types/src/hot-reload-server.d.ts +22 -55
- package/types/src/index.d.ts +1 -8
- package/types/src/serve.action.d.ts +1 -11
- package/types/src/serve.command.d.ts +0 -5
- package/README.md +0 -247
- package/commonjs/bench/load.bench.js +0 -145
- package/commonjs/src/deferred-script-runner.js +0 -56
- package/commonjs/src/flux.js +0 -56
- package/commonjs/src/rewrite-serve-specifier.js +0 -59
- package/commonjs/src/run.action.js +0 -47
- package/commonjs/src/run.command.js +0 -65
- package/commonjs/src/slice-serve.js +0 -130
- package/commonjs/src/source-module-loader.js +0 -237
- package/es6/bench/load.bench.js +0 -136
- package/es6/src/deferred-script-runner.js +0 -46
- package/es6/src/flux.js +0 -41
- package/es6/src/rewrite-serve-specifier.js +0 -49
- package/es6/src/run.action.js +0 -37
- package/es6/src/run.command.js +0 -55
- package/es6/src/slice-serve.js +0 -105
- package/es6/src/source-module-loader.js +0 -181
- package/types/bench/load.bench.d.ts +0 -1
- package/types/src/deferred-script-runner.d.ts +0 -18
- package/types/src/flux.d.ts +0 -43
- package/types/src/rewrite-serve-specifier.d.ts +0 -14
- package/types/src/run.action.d.ts +0 -15
- package/types/src/run.command.d.ts +0 -11
- package/types/src/slice-serve.d.ts +0 -52
- package/types/src/source-module-loader.d.ts +0 -58
|
@@ -1,243 +1,149 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
|
+
import { registerHooks } from "node:module";
|
|
2
3
|
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
+
import { BuildTargets, SwcTranspiler, WorkspaceDefaults } from "@decohere/forge";
|
|
5
|
+
import { WorkspaceFactory } from "@decohere/mesh";
|
|
6
|
+
import { FileEx, io } from "@decohere/nexus/io";
|
|
4
7
|
import { debounce } from "@decohere/nexus/system";
|
|
5
8
|
import { scribe } from "@decohere/scribe";
|
|
6
|
-
import { SourceModuleLoader } from "./source-module-loader.js";
|
|
7
9
|
const currentFilePath = io.fileUrlToPath(import.meta.url);
|
|
8
10
|
const VERSION_URL_PARAM = "version";
|
|
9
|
-
|
|
10
|
-
/** How many triggering paths to print on the info banner before `+N`. */ const MAX_REBOOT_TRIGGER_PATHS = 4;
|
|
11
|
-
export function resolveRebootDebounceMs(value) {
|
|
12
|
-
const delay = value ?? DEFAULT_REBOOT_DEBOUNCE_MS;
|
|
13
|
-
if (!Number.isFinite(delay) || delay < 0) {
|
|
14
|
-
throw new Error(`rebootDebounceMs must be a non-negative number, got ${String(value)}`);
|
|
15
|
-
}
|
|
16
|
-
return delay;
|
|
17
|
-
}
|
|
18
|
-
function formatTriggerList(triggers) {
|
|
19
|
-
if (triggers.length === 0) return undefined;
|
|
20
|
-
if (triggers.length <= MAX_REBOOT_TRIGGER_PATHS) return triggers.join(", ");
|
|
21
|
-
return `${triggers.slice(0, MAX_REBOOT_TRIGGER_PATHS).join(", ")}, +${triggers.length - MAX_REBOOT_TRIGGER_PATHS}`;
|
|
22
|
-
}
|
|
23
|
-
const BANNER_RULE = "═".repeat(56);
|
|
24
|
-
function wrapFluxBanner(title, details) {
|
|
25
|
-
const body = details.map((line)=>` ${line}`).join("\n");
|
|
26
|
-
return `\n${BANNER_RULE}\n ${title}\n${body}\n${BANNER_RULE}\n`;
|
|
27
|
-
}
|
|
28
|
-
/** Info-level HMR start block — keep `flux reboot` in the text so operators can search the buffer. */ export function formatFluxRebootStart(labels, triggers = []) {
|
|
29
|
-
const who = labels.join(", ") || "entry";
|
|
30
|
-
const files = formatTriggerList(triggers);
|
|
31
|
-
const details = files == null ? [
|
|
32
|
-
who
|
|
33
|
-
] : [
|
|
34
|
-
who,
|
|
35
|
-
files
|
|
36
|
-
];
|
|
37
|
-
return wrapFluxBanner("FLUX REBOOT", details);
|
|
38
|
-
}
|
|
39
|
-
/** Info-level HMR finish block. */ export function formatFluxRebootReady(labels, elapsedMs) {
|
|
40
|
-
const who = labels.join(", ") || "entry";
|
|
41
|
-
return wrapFluxBanner("FLUX READY", [
|
|
42
|
-
who,
|
|
43
|
-
`${Math.max(0, Math.round(elapsedMs))}ms`
|
|
44
|
-
]);
|
|
45
|
-
}
|
|
46
|
-
/** Process-wide: Node's ESM cache is process-global, including across HotReloadServer instances. */ let moduleVersionSeq = 0;
|
|
11
|
+
const REBOOT_DEBOUNCE_MS = 250;
|
|
47
12
|
export class HotReloadServer extends EventEmitter {
|
|
48
13
|
// ── State ────────────────────────────────────────────────────────────────
|
|
49
14
|
logger = scribe.logger(HotReloadServer.name);
|
|
50
|
-
loader = new SourceModuleLoader();
|
|
51
15
|
disposed = false;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
16
|
+
hooksRegistered = false;
|
|
17
|
+
entryModulePath;
|
|
18
|
+
entryModule;
|
|
19
|
+
workspace;
|
|
55
20
|
watchSubscription;
|
|
21
|
+
/** Map from absolute .ts source file path to project info */ fileInfoMap = new Map();
|
|
56
22
|
moduleCache = new Map();
|
|
57
23
|
dependencies = new Map();
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
rebootInFlight = false;
|
|
61
|
-
rebootFollowUp = false;
|
|
62
|
-
rebootQueued = false;
|
|
63
|
-
/** Modules whose reverse-graph edges are pruned at reboot, not on schedule. */ pendingGraphPrune = new Set();
|
|
64
|
-
scheduleReboot = ()=>{};
|
|
24
|
+
transpileCache = new Map();
|
|
25
|
+
transpiler = new SwcTranspiler();
|
|
65
26
|
// ── Public API ───────────────────────────────────────────────────────────
|
|
66
27
|
async start(options) {
|
|
67
28
|
this.disposed = false;
|
|
68
29
|
this.dependencies.clear();
|
|
69
30
|
this.moduleCache.clear();
|
|
70
|
-
this.
|
|
71
|
-
this.pendingEntryReboots.clear();
|
|
72
|
-
this.pendingTriggers.clear();
|
|
73
|
-
this.pendingGraphPrune.clear();
|
|
74
|
-
this.rebootTail = Promise.resolve();
|
|
75
|
-
this.rebootInFlight = false;
|
|
76
|
-
this.rebootFollowUp = false;
|
|
77
|
-
this.rebootQueued = false;
|
|
78
|
-
this.bindScheduleReboot(resolveRebootDebounceMs(options.rebootDebounceMs));
|
|
31
|
+
this.transpileCache.clear();
|
|
79
32
|
const { buildConfig } = options;
|
|
80
|
-
await this.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
});
|
|
86
|
-
const workspace = this.requireWorkspace();
|
|
87
|
-
const selected = this.resolveProjects(buildConfig, options);
|
|
88
|
-
for (const project of selected){
|
|
89
|
-
const entryPath = path.resolve(project.getSourceEntryPath());
|
|
90
|
-
this.entries.set(entryPath, {
|
|
91
|
-
path: entryPath,
|
|
92
|
-
label: project.name
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
this.loader.registerHooks();
|
|
33
|
+
this.workspace = await this.resolveWorkspace(options);
|
|
34
|
+
const project = this.resolveProject(buildConfig, options.project);
|
|
35
|
+
this.entryModulePath = path.resolve(project.getSourceEntryPath());
|
|
36
|
+
this.fileInfoMap = await this.buildFileInfoMap(buildConfig);
|
|
37
|
+
this.registerHooks();
|
|
96
38
|
this.invalidateAllSourceFiles();
|
|
97
|
-
await workspace.watch(buildConfig);
|
|
98
|
-
this.watchSubscription = workspace.projectFileChanged$.subscribe(this.onFileChange);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
await this.bootEntries([
|
|
103
|
-
...this.entries.keys()
|
|
104
|
-
]);
|
|
39
|
+
await this.workspace.watch(buildConfig);
|
|
40
|
+
this.watchSubscription = this.workspace.projectFileChanged$.subscribe(this.onFileChange);
|
|
41
|
+
this.logger.trace(`Serving ${this.entryModulePath}`);
|
|
42
|
+
await this.bootEntry();
|
|
105
43
|
this.emit("start");
|
|
106
44
|
}
|
|
107
45
|
async dispose() {
|
|
108
46
|
if (this.disposed) return;
|
|
109
47
|
this.disposed = true;
|
|
110
|
-
this.rebootDebounceGen += 1;
|
|
111
48
|
this.watchSubscription?.unsubscribe();
|
|
112
|
-
|
|
113
|
-
await this.
|
|
114
|
-
...this.entries.keys()
|
|
115
|
-
]);
|
|
116
|
-
this.loader.dispose();
|
|
49
|
+
this.workspace?.[Symbol.dispose]();
|
|
50
|
+
await this.disposeEntry();
|
|
117
51
|
}
|
|
118
52
|
async [Symbol.asyncDispose]() {
|
|
119
53
|
await this.dispose();
|
|
120
54
|
}
|
|
121
55
|
// ── Lifecycle ────────────────────────────────────────────────────────────
|
|
122
|
-
async
|
|
123
|
-
await Promise.all(entryPaths.map((entryPath)=>this.bootEntry(entryPath)));
|
|
124
|
-
}
|
|
125
|
-
async bootEntry(entryPath) {
|
|
126
|
-
const state = this.entries.get(entryPath);
|
|
127
|
-
if (state == null) return;
|
|
56
|
+
async bootEntry() {
|
|
128
57
|
try {
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
state.failed = false;
|
|
58
|
+
const url = this.versionModule(io.pathToFileUrl(this.entryModulePath));
|
|
59
|
+
this.entryModule = (await import(url))?.default;
|
|
132
60
|
} catch (error) {
|
|
133
|
-
state.module = undefined;
|
|
134
|
-
state.failed = true;
|
|
135
61
|
this.logger.error("There was an error booting the entry point. Your application may not function as expected", error);
|
|
136
62
|
}
|
|
137
63
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
this.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}, delayMs);
|
|
144
|
-
}
|
|
145
|
-
requestReboot() {
|
|
146
|
-
if (this.disposed) return;
|
|
147
|
-
if (this.rebootInFlight) {
|
|
148
|
-
this.rebootFollowUp = true;
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
if (this.rebootQueued) return;
|
|
152
|
-
this.rebootQueued = true;
|
|
153
|
-
this.rebootTail = this.rebootTail.then(()=>this.runReboot(), ()=>this.runReboot());
|
|
64
|
+
async reboot() {
|
|
65
|
+
this.logger.trace("Rebooting entry module");
|
|
66
|
+
await this.disposeEntry();
|
|
67
|
+
this.emit("reboot");
|
|
68
|
+
await this.bootEntry();
|
|
154
69
|
}
|
|
155
|
-
async
|
|
156
|
-
this.
|
|
157
|
-
if (this.disposed) return;
|
|
158
|
-
this.rebootInFlight = true;
|
|
159
|
-
try {
|
|
160
|
-
do {
|
|
161
|
-
this.rebootFollowUp = false;
|
|
162
|
-
if (this.disposed) return;
|
|
163
|
-
const toReboot = this.pendingEntryReboots.size > 0 ? [
|
|
164
|
-
...this.pendingEntryReboots
|
|
165
|
-
] : [
|
|
166
|
-
...this.entries.keys()
|
|
167
|
-
];
|
|
168
|
-
this.pendingEntryReboots.clear();
|
|
169
|
-
// Drop reverse edges only when rebooting so later saves in the debounce
|
|
170
|
-
// window can still walk the graph and reset the quiet timer.
|
|
171
|
-
this.prunePendingDependencyEdges();
|
|
172
|
-
const startedAt = Date.now();
|
|
173
|
-
const labels = this.labelsFor(toReboot);
|
|
174
|
-
const triggers = this.takeTriggers();
|
|
175
|
-
this.logger.info(formatFluxRebootStart(labels, triggers));
|
|
176
|
-
await this.disposeEntries(toReboot);
|
|
177
|
-
await this.bootEntries(toReboot);
|
|
178
|
-
this.logger.info(formatFluxRebootReady(labels, Date.now() - startedAt));
|
|
179
|
-
this.emit("reboot");
|
|
180
|
-
}while (this.rebootFollowUp && !this.disposed)
|
|
181
|
-
} finally{
|
|
182
|
-
const needsFollowUp = this.rebootFollowUp && !this.disposed;
|
|
183
|
-
this.rebootFollowUp = false;
|
|
184
|
-
this.rebootInFlight = false;
|
|
185
|
-
if (needsFollowUp) this.requestReboot();
|
|
186
|
-
}
|
|
70
|
+
async disposeEntry() {
|
|
71
|
+
await this.entryModule?.[Symbol.asyncDispose]();
|
|
187
72
|
}
|
|
188
|
-
|
|
189
|
-
|
|
73
|
+
scheduleReboot = debounce(()=>this.reboot(), REBOOT_DEBOUNCE_MS);
|
|
74
|
+
// ── Setup ────────────────────────────────────────────────────────────────
|
|
75
|
+
async resolveWorkspace(options) {
|
|
76
|
+
return options.workspace ?? WorkspaceFactory.create({
|
|
77
|
+
...WorkspaceDefaults,
|
|
78
|
+
rootDir: process.cwd()
|
|
79
|
+
});
|
|
190
80
|
}
|
|
191
|
-
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
];
|
|
197
|
-
for (const p of paths){
|
|
198
|
-
const state = this.entries.get(p);
|
|
199
|
-
if (state == null) continue;
|
|
200
|
-
const entry = state.module;
|
|
201
|
-
state.module = undefined;
|
|
202
|
-
try {
|
|
203
|
-
await entry?.[Symbol.asyncDispose]();
|
|
204
|
-
} catch (error) {
|
|
205
|
-
this.logger.error("Entry asyncDispose failed", error);
|
|
206
|
-
}
|
|
81
|
+
resolveProject(buildConfig, name) {
|
|
82
|
+
const projects = this.workspace?.getProjects(buildConfig) ?? [];
|
|
83
|
+
const found = name == null ? projects.at(0) : projects.find((p)=>p.name === name);
|
|
84
|
+
if (found == null) {
|
|
85
|
+
throw new Error(name == null ? `No projects found for configuration: ${buildConfig}` : `Project "${name}" not found in workspace`);
|
|
207
86
|
}
|
|
87
|
+
return found;
|
|
208
88
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
89
|
+
async buildFileInfoMap(buildConfig) {
|
|
90
|
+
const projects = this.workspace?.getProjects(buildConfig) ?? [];
|
|
91
|
+
const entries = await Promise.all(projects.map(async (project)=>{
|
|
92
|
+
const files = await project.getAllFiles();
|
|
93
|
+
return files.map((file)=>[
|
|
94
|
+
file.fullPath,
|
|
95
|
+
{
|
|
96
|
+
project
|
|
97
|
+
}
|
|
98
|
+
]);
|
|
99
|
+
}));
|
|
100
|
+
return new Map(entries.flat());
|
|
216
101
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
102
|
+
registerHooks() {
|
|
103
|
+
if (this.hooksRegistered) return;
|
|
104
|
+
this.hooksRegistered = true;
|
|
105
|
+
registerHooks({
|
|
106
|
+
resolve: (specifier, context, next)=>{
|
|
107
|
+
if (this.disposed) return next(specifier, context);
|
|
108
|
+
const parentUrl = context.parentURL ?? "";
|
|
109
|
+
const rewritten = this.rewriteJsToTs(specifier, parentUrl) ?? specifier;
|
|
110
|
+
const result = next(rewritten, context);
|
|
111
|
+
this.onPostResolve(result, parentUrl);
|
|
112
|
+
return result;
|
|
113
|
+
},
|
|
114
|
+
load: (url, context, next)=>{
|
|
115
|
+
if (this.disposed) return next(url, context);
|
|
116
|
+
const result = this.loadTs(url);
|
|
117
|
+
if (result != null) return {
|
|
118
|
+
format: "module",
|
|
119
|
+
source: result.source,
|
|
120
|
+
shortCircuit: true
|
|
121
|
+
};
|
|
122
|
+
return next(url, context);
|
|
236
123
|
}
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
return selected;
|
|
124
|
+
});
|
|
240
125
|
}
|
|
126
|
+
// ── Module hooks ─────────────────────────────────────────────────────────
|
|
127
|
+
/**
|
|
128
|
+
* Pre-next specifier rewriter: if specifier is a .js import that maps to a
|
|
129
|
+
* known .ts source file, returns the versioned .ts file URL so next() never
|
|
130
|
+
* tries to load a non-existent .js file from disk.
|
|
131
|
+
*/ rewriteJsToTs = (specifier, parentUrl)=>{
|
|
132
|
+
if (!specifier.endsWith(".js")) return null;
|
|
133
|
+
const parentClean = parentUrl.split("?")[0];
|
|
134
|
+
if (!parentClean) return null;
|
|
135
|
+
let jsPath;
|
|
136
|
+
try {
|
|
137
|
+
const resolved = new URL(specifier, parentClean);
|
|
138
|
+
jsPath = io.fileUrlToPath(resolved.toString());
|
|
139
|
+
} catch {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
if (!jsPath.endsWith(".js")) return null;
|
|
143
|
+
const tsPath = jsPath.replace(/\.js$/, ".ts");
|
|
144
|
+
if (!this.fileInfoMap.has(tsPath)) return null;
|
|
145
|
+
return this.getCachedOrNew(io.pathToFileUrl(tsPath));
|
|
146
|
+
};
|
|
241
147
|
/**
|
|
242
148
|
* Post-next dependency tracker: records which source files import which
|
|
243
149
|
* other source files so that reloadIfAffected can traverse the graph.
|
|
@@ -258,54 +164,68 @@ export class HotReloadServer extends EventEmitter {
|
|
|
258
164
|
} catch {
|
|
259
165
|
parentPath = "";
|
|
260
166
|
}
|
|
261
|
-
const isSource = this.
|
|
262
|
-
const parentIsSource = this.
|
|
167
|
+
const isSource = this.fileInfoMap.has(filePath);
|
|
168
|
+
const parentIsSource = this.fileInfoMap.has(parentPath);
|
|
263
169
|
if (isSource || parentIsSource) {
|
|
264
170
|
this.trackDependency(filePath, parentPath);
|
|
265
171
|
}
|
|
266
172
|
};
|
|
173
|
+
loadTs = (url)=>{
|
|
174
|
+
if (!url.startsWith("file:")) return null;
|
|
175
|
+
const cleanPath = new URL(url).pathname;
|
|
176
|
+
const fileInfo = this.fileInfoMap.get(cleanPath);
|
|
177
|
+
if (fileInfo == null) return null;
|
|
178
|
+
const cached = this.transpileCache.get(cleanPath);
|
|
179
|
+
if (cached != null) return {
|
|
180
|
+
source: cached
|
|
181
|
+
};
|
|
182
|
+
const { project } = fileInfo;
|
|
183
|
+
const tsConfig = project.getTsConfigSync();
|
|
184
|
+
const userConfig = project.getSwcConfigSync();
|
|
185
|
+
const file = new FileEx({
|
|
186
|
+
fullPath: cleanPath
|
|
187
|
+
});
|
|
188
|
+
const response = this.transpiler.transformFileSync(file, BuildTargets.es6, {
|
|
189
|
+
tsConfig,
|
|
190
|
+
aliasPaths: true,
|
|
191
|
+
userConfig
|
|
192
|
+
});
|
|
193
|
+
if (response.outcome !== "success") {
|
|
194
|
+
this.logger.error(`Failed to transpile ${cleanPath}`, response);
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
this.transpileCache.set(cleanPath, response.code);
|
|
198
|
+
return {
|
|
199
|
+
source: response.code
|
|
200
|
+
};
|
|
201
|
+
};
|
|
267
202
|
// ── File watching ────────────────────────────────────────────────────────
|
|
268
203
|
onFileChange = (evt)=>{
|
|
269
204
|
const { file, eventName, project } = evt;
|
|
270
205
|
const fullPath = file.fullPath;
|
|
271
206
|
this.logger.trace(`File ${eventName}: ${fullPath}`);
|
|
272
207
|
if (eventName === io.WatchEvents.unlink) {
|
|
273
|
-
this.
|
|
274
|
-
this.moduleCache.set(fullPath, null);
|
|
208
|
+
this.fileInfoMap.delete(fullPath);
|
|
275
209
|
return;
|
|
276
210
|
}
|
|
277
211
|
if (eventName === io.WatchEvents.add) {
|
|
278
212
|
if (project.isSourceFile(file)) {
|
|
279
|
-
this.
|
|
213
|
+
this.fileInfoMap.set(fullPath, {
|
|
214
|
+
project
|
|
215
|
+
});
|
|
280
216
|
this.moduleCache.set(fullPath, null);
|
|
281
217
|
this.reloadIfAffected(fullPath);
|
|
282
|
-
this.retryFailedEntries(fullPath);
|
|
283
218
|
}
|
|
284
219
|
return;
|
|
285
220
|
}
|
|
286
221
|
// change
|
|
287
222
|
if (!project.isSourceFile(file)) return;
|
|
288
|
-
this.
|
|
223
|
+
this.transpileCache.delete(fullPath);
|
|
224
|
+
this.transpiler.invalidateContentCache(new FileEx({
|
|
225
|
+
fullPath
|
|
226
|
+
}));
|
|
289
227
|
this.reloadIfAffected(fullPath);
|
|
290
|
-
this.retryFailedEntries(fullPath);
|
|
291
228
|
};
|
|
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
|
-
}
|
|
309
229
|
reloadIfAffected(fullPath) {
|
|
310
230
|
const deps = this.getDependencyGraph(fullPath);
|
|
311
231
|
const modules = [
|
|
@@ -314,44 +234,40 @@ export class HotReloadServer extends EventEmitter {
|
|
|
314
234
|
fullPath
|
|
315
235
|
])
|
|
316
236
|
];
|
|
317
|
-
|
|
318
|
-
...this.entries.keys()
|
|
319
|
-
].filter((entryPath)=>modules.includes(entryPath));
|
|
320
|
-
if (affectedEntries.length === 0) {
|
|
237
|
+
if (!modules.includes(this.entryModulePath)) {
|
|
321
238
|
this.logger.trace(`Change in ${fullPath} does not affect entry — skipping reload`);
|
|
322
239
|
return false;
|
|
323
240
|
}
|
|
324
241
|
this.logger.trace(`Change in ${fullPath} affects ${modules.length} module(s) — scheduling reload`);
|
|
325
|
-
this.
|
|
326
|
-
for (const module of modules){
|
|
327
|
-
this.pendingGraphPrune.add(module);
|
|
328
|
-
}
|
|
329
|
-
for (const entryPath of affectedEntries){
|
|
330
|
-
this.pendingEntryReboots.add(entryPath);
|
|
331
|
-
}
|
|
332
|
-
this.pendingTriggers.add(fullPath);
|
|
242
|
+
this.invalidateModule(...modules);
|
|
333
243
|
this.scheduleReboot();
|
|
334
244
|
return true;
|
|
335
245
|
}
|
|
336
246
|
// ── Dependency graph ─────────────────────────────────────────────────────
|
|
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) {
|
|
247
|
+
getDependencyGraph(moduleId, parentModules = []) {
|
|
341
248
|
if (this.isSelf(moduleId)) return [];
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
moduleId
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
249
|
+
const moduleDeps = this.dependencies.get(moduleId) ?? [];
|
|
250
|
+
if (parentModules.includes(moduleId)) {
|
|
251
|
+
this.logger.error(`Circular reference detected: ${moduleId}`);
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
let subDeps = [];
|
|
255
|
+
for (const dep of moduleDeps){
|
|
256
|
+
if (!this.fileInfoMap.has(dep)) continue;
|
|
257
|
+
const subs = this.getDependencyGraph(dep, [
|
|
258
|
+
moduleId,
|
|
259
|
+
...parentModules
|
|
260
|
+
]);
|
|
261
|
+
subDeps = [
|
|
262
|
+
...subDeps,
|
|
263
|
+
...subs
|
|
264
|
+
];
|
|
352
265
|
}
|
|
353
266
|
return [
|
|
354
|
-
...
|
|
267
|
+
...new Set([
|
|
268
|
+
...moduleDeps,
|
|
269
|
+
...subDeps
|
|
270
|
+
])
|
|
355
271
|
];
|
|
356
272
|
}
|
|
357
273
|
trackDependency(filePath, parentPath) {
|
|
@@ -375,24 +291,14 @@ export class HotReloadServer extends EventEmitter {
|
|
|
375
291
|
}
|
|
376
292
|
versionModule(moduleUrl) {
|
|
377
293
|
const versionedUrl = new URL(moduleUrl);
|
|
378
|
-
versionedUrl.searchParams.set(VERSION_URL_PARAM,
|
|
294
|
+
versionedUrl.searchParams.set(VERSION_URL_PARAM, Date.now().toString());
|
|
379
295
|
return versionedUrl.toString();
|
|
380
296
|
}
|
|
381
|
-
|
|
297
|
+
invalidateModule(...modules) {
|
|
382
298
|
for (const module of modules){
|
|
383
299
|
this.moduleCache.set(module, null);
|
|
384
|
-
this.
|
|
385
|
-
|
|
386
|
-
}
|
|
387
|
-
prunePendingDependencyEdges() {
|
|
388
|
-
const modules = [
|
|
389
|
-
...this.pendingGraphPrune
|
|
390
|
-
];
|
|
391
|
-
this.pendingGraphPrune.clear();
|
|
392
|
-
this.pruneDependencyParents(...modules);
|
|
393
|
-
}
|
|
394
|
-
/** Remove these modules as parents so boot can rebuild edges without stale importers. */ pruneDependencyParents(...modules) {
|
|
395
|
-
for (const module of modules){
|
|
300
|
+
this.transpileCache.delete(module);
|
|
301
|
+
// Prune stale outgoing edges: remove this module as a parent from all dependency lists
|
|
396
302
|
for (const [key, parents] of this.dependencies){
|
|
397
303
|
const filtered = parents.filter((p)=>p !== module);
|
|
398
304
|
if (filtered.length === 0) {
|
|
@@ -404,31 +310,14 @@ export class HotReloadServer extends EventEmitter {
|
|
|
404
310
|
}
|
|
405
311
|
}
|
|
406
312
|
invalidateAllSourceFiles() {
|
|
407
|
-
for (const filePath of this.
|
|
313
|
+
for (const filePath of this.fileInfoMap.keys()){
|
|
408
314
|
this.moduleCache.set(filePath, null);
|
|
409
315
|
}
|
|
410
316
|
}
|
|
317
|
+
// ── Utilities ────────────────────────────────────────────────────────────
|
|
411
318
|
isSelf(filePath) {
|
|
412
319
|
return currentFilePath === path.resolve(filePath);
|
|
413
320
|
}
|
|
414
|
-
labelsFor(entryPaths) {
|
|
415
|
-
return entryPaths.map((entryPath)=>this.entries.get(entryPath)?.label ?? path.basename(entryPath));
|
|
416
|
-
}
|
|
417
|
-
takeTriggers() {
|
|
418
|
-
const triggers = [
|
|
419
|
-
...this.pendingTriggers
|
|
420
|
-
].map((fullPath)=>this.formatTrigger(fullPath));
|
|
421
|
-
this.pendingTriggers.clear();
|
|
422
|
-
return triggers;
|
|
423
|
-
}
|
|
424
|
-
formatTrigger(fullPath) {
|
|
425
|
-
const root = this.loader.getWorkspace()?.rootDir;
|
|
426
|
-
if (root != null) {
|
|
427
|
-
const rel = path.relative(path.resolve(root), fullPath);
|
|
428
|
-
if (rel !== "" && !rel.startsWith("..") && !path.isAbsolute(rel)) {
|
|
429
|
-
return rel.replaceAll("\\", "/");
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return path.basename(fullPath);
|
|
433
|
-
}
|
|
434
321
|
}
|
|
322
|
+
|
|
323
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2ZsdXgvc3JjL2hvdC1yZWxvYWQtc2VydmVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gXCJub2RlOmV2ZW50c1wiO1xuaW1wb3J0IHR5cGUge1xuXHRMb2FkRm5PdXRwdXQsXG5cdExvYWRIb29rQ29udGV4dCxcblx0UmVzb2x2ZUZuT3V0cHV0LFxuXHRSZXNvbHZlSG9va0NvbnRleHQsXG59IGZyb20gXCJub2RlOm1vZHVsZVwiO1xuaW1wb3J0IHsgcmVnaXN0ZXJIb29rcyB9IGZyb20gXCJub2RlOm1vZHVsZVwiO1xuaW1wb3J0IHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgQnVpbGRUYXJnZXRzLCBTd2NUcmFuc3BpbGVyLCBXb3Jrc3BhY2VEZWZhdWx0cyB9IGZyb20gXCJAZGVjb2hlcmUvZm9yZ2VcIjtcbmltcG9ydCB0eXBlIHsgUHJvamVjdCwgUHJvamVjdEZpbGVFdmVudCwgV29ya3NwYWNlIH0gZnJvbSBcIkBkZWNvaGVyZS9tZXNoXCI7XG5pbXBvcnQgeyBXb3Jrc3BhY2VGYWN0b3J5IH0gZnJvbSBcIkBkZWNvaGVyZS9tZXNoXCI7XG5pbXBvcnQgeyBGaWxlRXgsIGlvIH0gZnJvbSBcIkBkZWNvaGVyZS9uZXh1cy9pb1wiO1xuaW1wb3J0IHsgZGVib3VuY2UgfSBmcm9tIFwiQGRlY29oZXJlL25leHVzL3N5c3RlbVwiO1xuaW1wb3J0IHsgdHlwZSBMb2dnZXIsIHNjcmliZSB9IGZyb20gXCJAZGVjb2hlcmUvc2NyaWJlXCI7XG5pbXBvcnQgdHlwZSB7IFN1YnNjcmlwdGlvbiB9IGZyb20gXCJyeGpzXCI7XG5cbnR5cGUgTG9hZERlbGVnYXRlID0gKHVybDogc3RyaW5nKSA9PiB7IHNvdXJjZTogc3RyaW5nIH0gfCBudWxsO1xuXG5jb25zdCBjdXJyZW50RmlsZVBhdGggPSBpby5maWxlVXJsVG9QYXRoKGltcG9ydC5tZXRhLnVybCk7XG5jb25zdCBWRVJTSU9OX1VSTF9QQVJBTSA9IFwidmVyc2lvblwiO1xuY29uc3QgUkVCT09UX0RFQk9VTkNFX01TID0gMjUwO1xuXG5leHBvcnQgaW50ZXJmYWNlIEhvdFJlbG9hZFNlcnZlckV2ZW50cyB7XG5cdHN0YXJ0OiBbXTtcblx0cmVib290OiBbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIb3RSZWxvYWRTZXJ2ZXJPcHRpb25zIHtcblx0LyoqIEJ1aWxkIGNvbmZpZ3VyYXRpb24gbmFtZS4gKi9cblx0YnVpbGRDb25maWc6IHN0cmluZztcblx0LyoqIE5hbWUgb2YgdGhlIHByb2plY3QgdG8gc2VydmUuIERlZmF1bHRzIHRvIHRoZSBmaXJzdCBwcm9qZWN0IGluIHRoZSB3b3Jrc3BhY2UuICovXG5cdHByb2plY3Q/OiBzdHJpbmc7XG5cdC8qKlxuXHQgKiBQcmUtYnVpbHQgV29ya3NwYWNlIGluc3RhbmNlIHRvIHVzZSBpbnN0ZWFkIG9mIHJ1bm5pbmcgV29ya3NwYWNlRmFjdG9yeS5cblx0ICogVXNlZnVsIGluIHRlc3RzIHRvIGJ5cGFzcyBmaWxlc3lzdGVtLWJhc2VkIHdvcmtzcGFjZSBkaXNjb3ZlcnkuXG5cdCAqL1xuXHR3b3Jrc3BhY2U/OiBXb3Jrc3BhY2U7XG59XG5cbnR5cGUgRmlsZUluZm8gPSB7IHByb2plY3Q6IFByb2plY3QgfTtcblxuZXhwb3J0IGNsYXNzIEhvdFJlbG9hZFNlcnZlciBleHRlbmRzIEV2ZW50RW1pdHRlcjxIb3RSZWxvYWRTZXJ2ZXJFdmVudHM+IHtcblx0Ly8g4pSA4pSAIFN0YXRlIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXHRwcml2YXRlIHJlYWRvbmx5IGxvZ2dlcjogTG9nZ2VyID0gc2NyaWJlLmxvZ2dlcihIb3RSZWxvYWRTZXJ2ZXIubmFtZSk7XG5cdHByaXZhdGUgZGlzcG9zZWQgPSBmYWxzZTtcblx0cHJpdmF0ZSBob29rc1JlZ2lzdGVyZWQgPSBmYWxzZTtcblx0cHJpdmF0ZSBlbnRyeU1vZHVsZVBhdGghOiBzdHJpbmc7XG5cdHByaXZhdGUgZW50cnlNb2R1bGU/OiBBc3luY0Rpc3Bvc2FibGU7XG5cdHByaXZhdGUgd29ya3NwYWNlPzogV29ya3NwYWNlO1xuXHRwcml2YXRlIHdhdGNoU3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uO1xuXHQvKiogTWFwIGZyb20gYWJzb2x1dGUgLnRzIHNvdXJjZSBmaWxlIHBhdGggdG8gcHJvamVjdCBpbmZvICovXG5cdHByaXZhdGUgZmlsZUluZm9NYXAgPSBuZXcgTWFwPHN0cmluZywgRmlsZUluZm8+KCk7XG5cdHByaXZhdGUgbW9kdWxlQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nIHwgbnVsbD4oKTtcblx0cHJpdmF0ZSBkZXBlbmRlbmNpZXMgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nW10+KCk7XG5cdHByaXZhdGUgdHJhbnNwaWxlQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuXHRwcml2YXRlIHRyYW5zcGlsZXIgPSBuZXcgU3djVHJhbnNwaWxlcigpO1xuXG5cdC8vIOKUgOKUgCBQdWJsaWMgQVBJIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG5cdHB1YmxpYyBhc3luYyBzdGFydChvcHRpb25zOiBIb3RSZWxvYWRTZXJ2ZXJPcHRpb25zKSB7XG5cdFx0dGhpcy5kaXNwb3NlZCA9IGZhbHNlO1xuXHRcdHRoaXMuZGVwZW5kZW5jaWVzLmNsZWFyKCk7XG5cdFx0dGhpcy5tb2R1bGVDYWNoZS5jbGVhcigpO1xuXHRcdHRoaXMudHJhbnNwaWxlQ2FjaGUuY2xlYXIoKTtcblxuXHRcdGNvbnN0IHsgYnVpbGRDb25maWcgfSA9IG9wdGlvbnM7XG5cdFx0dGhpcy53b3Jrc3BhY2UgPSBhd2FpdCB0aGlzLnJlc29sdmVXb3Jrc3BhY2Uob3B0aW9ucyk7XG5cdFx0Y29uc3QgcHJvamVjdCA9IHRoaXMucmVzb2x2ZVByb2plY3QoYnVpbGRDb25maWcsIG9wdGlvbnMucHJvamVjdCk7XG5cblx0XHR0aGlzLmVudHJ5TW9kdWxlUGF0aCA9IHBhdGgucmVzb2x2ZShwcm9qZWN0LmdldFNvdXJjZUVudHJ5UGF0aCgpKTtcblx0XHR0aGlzLmZpbGVJbmZvTWFwID0gYXdhaXQgdGhpcy5idWlsZEZpbGVJbmZvTWFwKGJ1aWxkQ29uZmlnKTtcblxuXHRcdHRoaXMucmVnaXN0ZXJIb29rcygpO1xuXHRcdHRoaXMuaW52YWxpZGF0ZUFsbFNvdXJjZUZpbGVzKCk7XG5cblx0XHRhd2FpdCB0aGlzLndvcmtzcGFjZS53YXRjaChidWlsZENvbmZpZyk7XG5cdFx0dGhpcy53YXRjaFN1YnNjcmlwdGlvbiA9IHRoaXMud29ya3NwYWNlLnByb2plY3RGaWxlQ2hhbmdlZCQuc3Vic2NyaWJlKHRoaXMub25GaWxlQ2hhbmdlKTtcblxuXHRcdHRoaXMubG9nZ2VyLnRyYWNlKGBTZXJ2aW5nICR7dGhpcy5lbnRyeU1vZHVsZVBhdGh9YCk7XG5cdFx0YXdhaXQgdGhpcy5ib290RW50cnkoKTtcblx0XHR0aGlzLmVtaXQoXCJzdGFydFwiKTtcblx0fVxuXG5cdHB1YmxpYyBhc3luYyBkaXNwb3NlKCkge1xuXHRcdGlmICh0aGlzLmRpc3Bvc2VkKSByZXR1cm47XG5cdFx0dGhpcy5kaXNwb3NlZCA9IHRydWU7XG5cdFx0dGhpcy53YXRjaFN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcblx0XHR0aGlzLndvcmtzcGFjZT8uW1N5bWJvbC5kaXNwb3NlXSgpO1xuXHRcdGF3YWl0IHRoaXMuZGlzcG9zZUVudHJ5KCk7XG5cdH1cblxuXHRwdWJsaWMgYXN5bmMgW1N5bWJvbC5hc3luY0Rpc3Bvc2VdKCkge1xuXHRcdGF3YWl0IHRoaXMuZGlzcG9zZSgpO1xuXHR9XG5cblx0Ly8g4pSA4pSAIExpZmVjeWNsZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuXHRwcml2YXRlIGFzeW5jIGJvb3RFbnRyeSgpIHtcblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgdXJsID0gdGhpcy52ZXJzaW9uTW9kdWxlKGlvLnBhdGhUb0ZpbGVVcmwodGhpcy5lbnRyeU1vZHVsZVBhdGgpKTtcblx0XHRcdHRoaXMuZW50cnlNb2R1bGUgPSAoYXdhaXQgaW1wb3J0KHVybCkpPy5kZWZhdWx0O1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihcblx0XHRcdFx0XCJUaGVyZSB3YXMgYW4gZXJyb3IgYm9vdGluZyB0aGUgZW50cnkgcG9pbnQuIFlvdXIgYXBwbGljYXRpb24gbWF5IG5vdCBmdW5jdGlvbiBhcyBleHBlY3RlZFwiLFxuXHRcdFx0XHRlcnJvcixcblx0XHRcdCk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBhc3luYyByZWJvb3QoKSB7XG5cdFx0dGhpcy5sb2dnZXIudHJhY2UoXCJSZWJvb3RpbmcgZW50cnkgbW9kdWxlXCIpO1xuXHRcdGF3YWl0IHRoaXMuZGlzcG9zZUVudHJ5KCk7XG5cdFx0dGhpcy5lbWl0KFwicmVib290XCIpO1xuXHRcdGF3YWl0IHRoaXMuYm9vdEVudHJ5KCk7XG5cdH1cblxuXHRwcml2YXRlIGFzeW5jIGRpc3Bvc2VFbnRyeSgpIHtcblx0XHRhd2FpdCB0aGlzLmVudHJ5TW9kdWxlPy5bU3ltYm9sLmFzeW5jRGlzcG9zZV0oKTtcblx0fVxuXG5cdHByaXZhdGUgc2NoZWR1bGVSZWJvb3QgPSBkZWJvdW5jZSgoKSA9PiB0aGlzLnJlYm9vdCgpLCBSRUJPT1RfREVCT1VOQ0VfTVMpO1xuXG5cdC8vIOKUgOKUgCBTZXR1cCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuXHRwcml2YXRlIGFzeW5jIHJlc29sdmVXb3Jrc3BhY2Uob3B0aW9uczogSG90UmVsb2FkU2VydmVyT3B0aW9ucyk6IFByb21pc2U8V29ya3NwYWNlPiB7XG5cdFx0cmV0dXJuIChcblx0XHRcdG9wdGlvbnMud29ya3NwYWNlID8/XG5cdFx0XHRXb3Jrc3BhY2VGYWN0b3J5LmNyZWF0ZSh7IC4uLldvcmtzcGFjZURlZmF1bHRzLCByb290RGlyOiBwcm9jZXNzLmN3ZCgpIH0pXG5cdFx0KTtcblx0fVxuXG5cdHByaXZhdGUgcmVzb2x2ZVByb2plY3QoYnVpbGRDb25maWc6IHN0cmluZywgbmFtZT86IHN0cmluZyk6IFByb2plY3Qge1xuXHRcdGNvbnN0IHByb2plY3RzID0gdGhpcy53b3Jrc3BhY2U/LmdldFByb2plY3RzKGJ1aWxkQ29uZmlnKSA/PyBbXTtcblx0XHRjb25zdCBmb3VuZCA9IG5hbWUgPT0gbnVsbCA/IHByb2plY3RzLmF0KDApIDogcHJvamVjdHMuZmluZCgocCkgPT4gcC5uYW1lID09PSBuYW1lKTtcblx0XHRpZiAoZm91bmQgPT0gbnVsbCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFxuXHRcdFx0XHRuYW1lID09IG51bGxcblx0XHRcdFx0XHQ/IGBObyBwcm9qZWN0cyBmb3VuZCBmb3IgY29uZmlndXJhdGlvbjogJHtidWlsZENvbmZpZ31gXG5cdFx0XHRcdFx0OiBgUHJvamVjdCBcIiR7bmFtZX1cIiBub3QgZm91bmQgaW4gd29ya3NwYWNlYCxcblx0XHRcdCk7XG5cdFx0fVxuXHRcdHJldHVybiBmb3VuZDtcblx0fVxuXG5cdHByaXZhdGUgYXN5bmMgYnVpbGRGaWxlSW5mb01hcChidWlsZENvbmZpZzogc3RyaW5nKTogUHJvbWlzZTxNYXA8c3RyaW5nLCBGaWxlSW5mbz4+IHtcblx0XHRjb25zdCBwcm9qZWN0cyA9IHRoaXMud29ya3NwYWNlPy5nZXRQcm9qZWN0cyhidWlsZENvbmZpZykgPz8gW107XG5cdFx0Y29uc3QgZW50cmllcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuXHRcdFx0cHJvamVjdHMubWFwKGFzeW5jIChwcm9qZWN0KSA9PiB7XG5cdFx0XHRcdGNvbnN0IGZpbGVzID0gYXdhaXQgcHJvamVjdC5nZXRBbGxGaWxlcygpO1xuXHRcdFx0XHRyZXR1cm4gZmlsZXMubWFwKChmaWxlKTogW3N0cmluZywgRmlsZUluZm9dID0+IFtmaWxlLmZ1bGxQYXRoLCB7IHByb2plY3QgfV0pO1xuXHRcdFx0fSksXG5cdFx0KTtcblx0XHRyZXR1cm4gbmV3IE1hcChlbnRyaWVzLmZsYXQoKSk7XG5cdH1cblxuXHRwcml2YXRlIHJlZ2lzdGVySG9va3MoKSB7XG5cdFx0aWYgKHRoaXMuaG9va3NSZWdpc3RlcmVkKSByZXR1cm47XG5cdFx0dGhpcy5ob29rc1JlZ2lzdGVyZWQgPSB0cnVlO1xuXHRcdHJlZ2lzdGVySG9va3Moe1xuXHRcdFx0cmVzb2x2ZTogKFxuXHRcdFx0XHRzcGVjaWZpZXI6IHN0cmluZyxcblx0XHRcdFx0Y29udGV4dDogUmVzb2x2ZUhvb2tDb250ZXh0LFxuXHRcdFx0XHRuZXh0OiAoc3BlY2lmaWVyOiBzdHJpbmcsIGNvbnRleHQ/OiBQYXJ0aWFsPFJlc29sdmVIb29rQ29udGV4dD4pID0+IFJlc29sdmVGbk91dHB1dCxcblx0XHRcdCkgPT4ge1xuXHRcdFx0XHRpZiAodGhpcy5kaXNwb3NlZCkgcmV0dXJuIG5leHQoc3BlY2lmaWVyLCBjb250ZXh0KTtcblx0XHRcdFx0Y29uc3QgcGFyZW50VXJsID0gY29udGV4dC5wYXJlbnRVUkwgPz8gXCJcIjtcblx0XHRcdFx0Y29uc3QgcmV3cml0dGVuID0gdGhpcy5yZXdyaXRlSnNUb1RzKHNwZWNpZmllciwgcGFyZW50VXJsKSA/PyBzcGVjaWZpZXI7XG5cdFx0XHRcdGNvbnN0IHJlc3VsdCA9IG5leHQocmV3cml0dGVuLCBjb250ZXh0KSBhcyBSZXNvbHZlRm5PdXRwdXQ7XG5cdFx0XHRcdHRoaXMub25Qb3N0UmVzb2x2ZShyZXN1bHQsIHBhcmVudFVybCk7XG5cdFx0XHRcdHJldHVybiByZXN1bHQ7XG5cdFx0XHR9LFxuXHRcdFx0bG9hZDogKFxuXHRcdFx0XHR1cmw6IHN0cmluZyxcblx0XHRcdFx0Y29udGV4dDogTG9hZEhvb2tDb250ZXh0LFxuXHRcdFx0XHRuZXh0OiAodXJsOiBzdHJpbmcsIGNvbnRleHQ/OiBQYXJ0aWFsPExvYWRIb29rQ29udGV4dD4pID0+IExvYWRGbk91dHB1dCxcblx0XHRcdCk6IExvYWRGbk91dHB1dCA9PiB7XG5cdFx0XHRcdGlmICh0aGlzLmRpc3Bvc2VkKSByZXR1cm4gbmV4dCh1cmwsIGNvbnRleHQpO1xuXHRcdFx0XHRjb25zdCByZXN1bHQgPSB0aGlzLmxvYWRUcyh1cmwpO1xuXHRcdFx0XHRpZiAocmVzdWx0ICE9IG51bGwpXG5cdFx0XHRcdFx0cmV0dXJuIHsgZm9ybWF0OiBcIm1vZHVsZVwiLCBzb3VyY2U6IHJlc3VsdC5zb3VyY2UsIHNob3J0Q2lyY3VpdDogdHJ1ZSB9O1xuXHRcdFx0XHRyZXR1cm4gbmV4dCh1cmwsIGNvbnRleHQpO1xuXHRcdFx0fSxcblx0XHR9KTtcblx0fVxuXG5cdC8vIOKUgOKUgCBNb2R1bGUgaG9va3Mg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cblx0LyoqXG5cdCAqIFByZS1uZXh0IHNwZWNpZmllciByZXdyaXRlcjogaWYgc3BlY2lmaWVyIGlzIGEgLmpzIGltcG9ydCB0aGF0IG1hcHMgdG8gYVxuXHQgKiBrbm93biAudHMgc291cmNlIGZpbGUsIHJldHVybnMgdGhlIHZlcnNpb25lZCAudHMgZmlsZSBVUkwgc28gbmV4dCgpIG5ldmVyXG5cdCAqIHRyaWVzIHRvIGxvYWQgYSBub24tZXhpc3RlbnQgLmpzIGZpbGUgZnJvbSBkaXNrLlxuXHQgKi9cblx0cHJpdmF0ZSByZXdyaXRlSnNUb1RzID0gKHNwZWNpZmllcjogc3RyaW5nLCBwYXJlbnRVcmw6IHN0cmluZyk6IHN0cmluZyB8IG51bGwgPT4ge1xuXHRcdGlmICghc3BlY2lmaWVyLmVuZHNXaXRoKFwiLmpzXCIpKSByZXR1cm4gbnVsbDtcblxuXHRcdGNvbnN0IHBhcmVudENsZWFuID0gcGFyZW50VXJsLnNwbGl0KFwiP1wiKVswXTtcblx0XHRpZiAoIXBhcmVudENsZWFuKSByZXR1cm4gbnVsbDtcblxuXHRcdGxldCBqc1BhdGg6IHN0cmluZztcblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgcmVzb2x2ZWQgPSBuZXcgVVJMKHNwZWNpZmllciwgcGFyZW50Q2xlYW4pO1xuXHRcdFx0anNQYXRoID0gaW8uZmlsZVVybFRvUGF0aChyZXNvbHZlZC50b1N0cmluZygpKTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdGlmICghanNQYXRoLmVuZHNXaXRoKFwiLmpzXCIpKSByZXR1cm4gbnVsbDtcblx0XHRjb25zdCB0c1BhdGggPSBqc1BhdGgucmVwbGFjZSgvXFwuanMkLywgXCIudHNcIik7XG5cdFx0aWYgKCF0aGlzLmZpbGVJbmZvTWFwLmhhcyh0c1BhdGgpKSByZXR1cm4gbnVsbDtcblxuXHRcdHJldHVybiB0aGlzLmdldENhY2hlZE9yTmV3KGlvLnBhdGhUb0ZpbGVVcmwodHNQYXRoKSk7XG5cdH07XG5cblx0LyoqXG5cdCAqIFBvc3QtbmV4dCBkZXBlbmRlbmN5IHRyYWNrZXI6IHJlY29yZHMgd2hpY2ggc291cmNlIGZpbGVzIGltcG9ydCB3aGljaFxuXHQgKiBvdGhlciBzb3VyY2UgZmlsZXMgc28gdGhhdCByZWxvYWRJZkFmZmVjdGVkIGNhbiB0cmF2ZXJzZSB0aGUgZ3JhcGguXG5cdCAqL1xuXHRwcml2YXRlIG9uUG9zdFJlc29sdmUgPSAocmVzdWx0OiBSZXNvbHZlRm5PdXRwdXQsIHBhcmVudFVybDogc3RyaW5nKSA9PiB7XG5cdFx0Y29uc3QgeyB1cmwgfSA9IHJlc3VsdDtcblx0XHRjb25zdCBwYXJlbnRVcmxDbGVhbiA9IHBhcmVudFVybC5zcGxpdChcIj9cIilbMF07XG5cblx0XHRsZXQgZmlsZVBhdGg6IHN0cmluZztcblx0XHRsZXQgcGFyZW50UGF0aDogc3RyaW5nO1xuXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHVybE9iaiA9IG5ldyBVUkwodXJsKTtcblx0XHRcdHVybE9iai5zZWFyY2ggPSBcIlwiO1xuXHRcdFx0ZmlsZVBhdGggPSBpby5maWxlVXJsVG9QYXRoKHVybE9iai50b1N0cmluZygpKTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0cnkge1xuXHRcdFx0cGFyZW50UGF0aCA9IGlvLmZpbGVVcmxUb1BhdGgocGFyZW50VXJsQ2xlYW4pO1xuXHRcdH0gY2F0Y2gge1xuXHRcdFx0cGFyZW50UGF0aCA9IFwiXCI7XG5cdFx0fVxuXG5cdFx0Y29uc3QgaXNTb3VyY2UgPSB0aGlzLmZpbGVJbmZvTWFwLmhhcyhmaWxlUGF0aCk7XG5cdFx0Y29uc3QgcGFyZW50SXNTb3VyY2UgPSB0aGlzLmZpbGVJbmZvTWFwLmhhcyhwYXJlbnRQYXRoKTtcblxuXHRcdGlmIChpc1NvdXJjZSB8fCBwYXJlbnRJc1NvdXJjZSkge1xuXHRcdFx0dGhpcy50cmFja0RlcGVuZGVuY3koZmlsZVBhdGgsIHBhcmVudFBhdGgpO1xuXHRcdH1cblx0fTtcblxuXHRwcml2YXRlIGxvYWRUczogTG9hZERlbGVnYXRlID0gKHVybDogc3RyaW5nKSA9PiB7XG5cdFx0aWYgKCF1cmwuc3RhcnRzV2l0aChcImZpbGU6XCIpKSByZXR1cm4gbnVsbDtcblxuXHRcdGNvbnN0IGNsZWFuUGF0aCA9IG5ldyBVUkwodXJsKS5wYXRobmFtZTtcblx0XHRjb25zdCBmaWxlSW5mbyA9IHRoaXMuZmlsZUluZm9NYXAuZ2V0KGNsZWFuUGF0aCk7XG5cdFx0aWYgKGZpbGVJbmZvID09IG51bGwpIHJldHVybiBudWxsO1xuXG5cdFx0Y29uc3QgY2FjaGVkID0gdGhpcy50cmFuc3BpbGVDYWNoZS5nZXQoY2xlYW5QYXRoKTtcblx0XHRpZiAoY2FjaGVkICE9IG51bGwpIHJldHVybiB7IHNvdXJjZTogY2FjaGVkIH07XG5cblx0XHRjb25zdCB7IHByb2plY3QgfSA9IGZpbGVJbmZvO1xuXHRcdGNvbnN0IHRzQ29uZmlnID0gcHJvamVjdC5nZXRUc0NvbmZpZ1N5bmMoKTtcblx0XHRjb25zdCB1c2VyQ29uZmlnID0gcHJvamVjdC5nZXRTd2NDb25maWdTeW5jKCk7XG5cblx0XHRjb25zdCBmaWxlID0gbmV3IEZpbGVFeCh7IGZ1bGxQYXRoOiBjbGVhblBhdGggfSk7XG5cdFx0Y29uc3QgcmVzcG9uc2UgPSB0aGlzLnRyYW5zcGlsZXIudHJhbnNmb3JtRmlsZVN5bmMoZmlsZSwgQnVpbGRUYXJnZXRzLmVzNiwge1xuXHRcdFx0dHNDb25maWcsXG5cdFx0XHRhbGlhc1BhdGhzOiB0cnVlLFxuXHRcdFx0dXNlckNvbmZpZyxcblx0XHR9KTtcblxuXHRcdGlmIChyZXNwb25zZS5vdXRjb21lICE9PSBcInN1Y2Nlc3NcIikge1xuXHRcdFx0dGhpcy5sb2dnZXIuZXJyb3IoYEZhaWxlZCB0byB0cmFuc3BpbGUgJHtjbGVhblBhdGh9YCwgcmVzcG9uc2UpO1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXG5cdFx0dGhpcy50cmFuc3BpbGVDYWNoZS5zZXQoY2xlYW5QYXRoLCByZXNwb25zZS5jb2RlKTtcblx0XHRyZXR1cm4geyBzb3VyY2U6IHJlc3BvbnNlLmNvZGUgfTtcblx0fTtcblxuXHQvLyDilIDilIAgRmlsZSB3YXRjaGluZyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuXHRwcml2YXRlIG9uRmlsZUNoYW5nZSA9IChldnQ6IFByb2plY3RGaWxlRXZlbnQpID0+IHtcblx0XHRjb25zdCB7IGZpbGUsIGV2ZW50TmFtZSwgcHJvamVjdCB9ID0gZXZ0O1xuXHRcdGNvbnN0IGZ1bGxQYXRoID0gZmlsZS5mdWxsUGF0aDtcblxuXHRcdHRoaXMubG9nZ2VyLnRyYWNlKGBGaWxlICR7ZXZlbnROYW1lfTogJHtmdWxsUGF0aH1gKTtcblxuXHRcdGlmIChldmVudE5hbWUgPT09IGlvLldhdGNoRXZlbnRzLnVubGluaykge1xuXHRcdFx0dGhpcy5maWxlSW5mb01hcC5kZWxldGUoZnVsbFBhdGgpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmIChldmVudE5hbWUgPT09IGlvLldhdGNoRXZlbnRzLmFkZCkge1xuXHRcdFx0aWYgKHByb2plY3QuaXNTb3VyY2VGaWxlKGZpbGUpKSB7XG5cdFx0XHRcdHRoaXMuZmlsZUluZm9NYXAuc2V0KGZ1bGxQYXRoLCB7IHByb2plY3QgfSk7XG5cdFx0XHRcdHRoaXMubW9kdWxlQ2FjaGUuc2V0KGZ1bGxQYXRoLCBudWxsKTtcblx0XHRcdFx0dGhpcy5yZWxvYWRJZkFmZmVjdGVkKGZ1bGxQYXRoKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBjaGFuZ2Vcblx0XHRpZiAoIXByb2plY3QuaXNTb3VyY2VGaWxlKGZpbGUpKSByZXR1cm47XG5cdFx0dGhpcy50cmFuc3BpbGVDYWNoZS5kZWxldGUoZnVsbFBhdGgpO1xuXHRcdHRoaXMudHJhbnNwaWxlci5pbnZhbGlkYXRlQ29udGVudENhY2hlKG5ldyBGaWxlRXgoeyBmdWxsUGF0aCB9KSk7XG5cdFx0dGhpcy5yZWxvYWRJZkFmZmVjdGVkKGZ1bGxQYXRoKTtcblx0fTtcblxuXHRwcml2YXRlIHJlbG9hZElmQWZmZWN0ZWQoZnVsbFBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRcdGNvbnN0IGRlcHMgPSB0aGlzLmdldERlcGVuZGVuY3lHcmFwaChmdWxsUGF0aCk7XG5cdFx0Y29uc3QgbW9kdWxlcyA9IFsuLi5uZXcgU2V0KFsuLi5kZXBzLCBmdWxsUGF0aF0pXTtcblxuXHRcdGlmICghbW9kdWxlcy5pbmNsdWRlcyh0aGlzLmVudHJ5TW9kdWxlUGF0aCkpIHtcblx0XHRcdHRoaXMubG9nZ2VyLnRyYWNlKGBDaGFuZ2UgaW4gJHtmdWxsUGF0aH0gZG9lcyBub3QgYWZmZWN0IGVudHJ5IOKAlCBza2lwcGluZyByZWxvYWRgKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHR0aGlzLmxvZ2dlci50cmFjZShcblx0XHRcdGBDaGFuZ2UgaW4gJHtmdWxsUGF0aH0gYWZmZWN0cyAke21vZHVsZXMubGVuZ3RofSBtb2R1bGUocykg4oCUIHNjaGVkdWxpbmcgcmVsb2FkYCxcblx0XHQpO1xuXHRcdHRoaXMuaW52YWxpZGF0ZU1vZHVsZSguLi5tb2R1bGVzKTtcblx0XHR0aGlzLnNjaGVkdWxlUmVib290KCk7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvLyDilIDilIAgRGVwZW5kZW5jeSBncmFwaCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuXHRwcml2YXRlIGdldERlcGVuZGVuY3lHcmFwaChtb2R1bGVJZDogc3RyaW5nLCBwYXJlbnRNb2R1bGVzOiBzdHJpbmdbXSA9IFtdKTogc3RyaW5nW10ge1xuXHRcdGlmICh0aGlzLmlzU2VsZihtb2R1bGVJZCkpIHJldHVybiBbXTtcblxuXHRcdGNvbnN0IG1vZHVsZURlcHMgPSB0aGlzLmRlcGVuZGVuY2llcy5nZXQobW9kdWxlSWQpID8/IFtdO1xuXHRcdGlmIChwYXJlbnRNb2R1bGVzLmluY2x1ZGVzKG1vZHVsZUlkKSkge1xuXHRcdFx0dGhpcy5sb2dnZXIuZXJyb3IoYENpcmN1bGFyIHJlZmVyZW5jZSBkZXRlY3RlZDogJHttb2R1bGVJZH1gKTtcblx0XHRcdHJldHVybiBbXTtcblx0XHR9XG5cblx0XHRsZXQgc3ViRGVwczogc3RyaW5nW10gPSBbXTtcblx0XHRmb3IgKGNvbnN0IGRlcCBvZiBtb2R1bGVEZXBzKSB7XG5cdFx0XHRpZiAoIXRoaXMuZmlsZUluZm9NYXAuaGFzKGRlcCkpIGNvbnRpbnVlO1xuXHRcdFx0Y29uc3Qgc3VicyA9IHRoaXMuZ2V0RGVwZW5kZW5jeUdyYXBoKGRlcCwgW21vZHVsZUlkLCAuLi5wYXJlbnRNb2R1bGVzXSk7XG5cdFx0XHRzdWJEZXBzID0gWy4uLnN1YkRlcHMsIC4uLnN1YnNdO1xuXHRcdH1cblxuXHRcdHJldHVybiBbLi4ubmV3IFNldChbLi4ubW9kdWxlRGVwcywgLi4uc3ViRGVwc10pXTtcblx0fVxuXG5cdHByaXZhdGUgdHJhY2tEZXBlbmRlbmN5KGZpbGVQYXRoOiBzdHJpbmcsIHBhcmVudFBhdGg6IHN0cmluZykge1xuXHRcdGlmICghcGFyZW50UGF0aCkgcmV0dXJuO1xuXHRcdGNvbnN0IGRlcHMgPSB0aGlzLmRlcGVuZGVuY2llcy5nZXQoZmlsZVBhdGgpID8/IFtdO1xuXHRcdGNvbnN0IHVwZGF0ZWREZXBzID0gbmV3IFNldChbLi4uZGVwcywgcGFyZW50UGF0aF0pO1xuXHRcdHRoaXMuZGVwZW5kZW5jaWVzLnNldChmaWxlUGF0aCwgWy4uLnVwZGF0ZWREZXBzXSk7XG5cdH1cblxuXHQvLyDilIDilIAgTW9kdWxlIGNhY2hlIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG5cdHByaXZhdGUgZ2V0Q2FjaGVkT3JOZXcobW9kdWxlVXJsOiBzdHJpbmcpIHtcblx0XHRjb25zdCBmaWxlUGF0aCA9IGlvLmZpbGVVcmxUb1BhdGgobW9kdWxlVXJsKTtcblx0XHRjb25zdCBjYWNoZWQgPSB0aGlzLm1vZHVsZUNhY2hlLmdldChmaWxlUGF0aCk7XG5cdFx0Y29uc3QgdmVyc2lvbmVkID0gY2FjaGVkID8/IHRoaXMudmVyc2lvbk1vZHVsZShtb2R1bGVVcmwpO1xuXHRcdHRoaXMubW9kdWxlQ2FjaGUuc2V0KGZpbGVQYXRoLCB2ZXJzaW9uZWQpO1xuXHRcdHJldHVybiB2ZXJzaW9uZWQ7XG5cdH1cblxuXHRwcml2YXRlIHZlcnNpb25Nb2R1bGUobW9kdWxlVXJsOiBzdHJpbmcpIHtcblx0XHRjb25zdCB2ZXJzaW9uZWRVcmwgPSBuZXcgVVJMKG1vZHVsZVVybCk7XG5cdFx0dmVyc2lvbmVkVXJsLnNlYXJjaFBhcmFtcy5zZXQoVkVSU0lPTl9VUkxfUEFSQU0sIERhdGUubm93KCkudG9TdHJpbmcoKSk7XG5cdFx0cmV0dXJuIHZlcnNpb25lZFVybC50b1N0cmluZygpO1xuXHR9XG5cblx0cHJpdmF0ZSBpbnZhbGlkYXRlTW9kdWxlKC4uLm1vZHVsZXM6IHN0cmluZ1tdKSB7XG5cdFx0Zm9yIChjb25zdCBtb2R1bGUgb2YgbW9kdWxlcykge1xuXHRcdFx0dGhpcy5tb2R1bGVDYWNoZS5zZXQobW9kdWxlLCBudWxsKTtcblx0XHRcdHRoaXMudHJhbnNwaWxlQ2FjaGUuZGVsZXRlKG1vZHVsZSk7XG5cdFx0XHQvLyBQcnVuZSBzdGFsZSBvdXRnb2luZyBlZGdlczogcmVtb3ZlIHRoaXMgbW9kdWxlIGFzIGEgcGFyZW50IGZyb20gYWxsIGRlcGVuZGVuY3kgbGlzdHNcblx0XHRcdGZvciAoY29uc3QgW2tleSwgcGFyZW50c10gb2YgdGhpcy5kZXBlbmRlbmNpZXMpIHtcblx0XHRcdFx0Y29uc3QgZmlsdGVyZWQgPSBwYXJlbnRzLmZpbHRlcigocCkgPT4gcCAhPT0gbW9kdWxlKTtcblx0XHRcdFx0aWYgKGZpbHRlcmVkLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0XHRcdHRoaXMuZGVwZW5kZW5jaWVzLmRlbGV0ZShrZXkpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMuZGVwZW5kZW5jaWVzLnNldChrZXksIGZpbHRlcmVkKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgaW52YWxpZGF0ZUFsbFNvdXJjZUZpbGVzKCkge1xuXHRcdGZvciAoY29uc3QgZmlsZVBhdGggb2YgdGhpcy5maWxlSW5mb01hcC5rZXlzKCkpIHtcblx0XHRcdHRoaXMubW9kdWxlQ2FjaGUuc2V0KGZpbGVQYXRoLCBudWxsKTtcblx0XHR9XG5cdH1cblxuXHQvLyDilIDilIAgVXRpbGl0aWVzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG5cdHByaXZhdGUgaXNTZWxmKGZpbGVQYXRoOiBzdHJpbmcpIHtcblx0XHRyZXR1cm4gY3VycmVudEZpbGVQYXRoID09PSBwYXRoLnJlc29sdmUoZmlsZVBhdGgpO1xuXHR9XG59XG4iXSwibmFtZXMiOlsiRXZlbnRFbWl0dGVyIiwicmVnaXN0ZXJIb29rcyIsInBhdGgiLCJCdWlsZFRhcmdldHMiLCJTd2NUcmFuc3BpbGVyIiwiV29ya3NwYWNlRGVmYXVsdHMiLCJXb3Jrc3BhY2VGYWN0b3J5IiwiRmlsZUV4IiwiaW8iLCJkZWJvdW5jZSIsInNjcmliZSIsImN1cnJlbnRGaWxlUGF0aCIsImZpbGVVcmxUb1BhdGgiLCJ1cmwiLCJWRVJTSU9OX1VSTF9QQVJBTSIsIlJFQk9PVF9ERUJPVU5DRV9NUyIsIkhvdFJlbG9hZFNlcnZlciIsImxvZ2dlciIsIm5hbWUiLCJkaXNwb3NlZCIsImhvb2tzUmVnaXN0ZXJlZCIsImVudHJ5TW9kdWxlUGF0aCIsImVudHJ5TW9kdWxlIiwid29ya3NwYWNlIiwid2F0Y2hTdWJzY3JpcHRpb24iLCJmaWxlSW5mb01hcCIsIk1hcCIsIm1vZHVsZUNhY2hlIiwiZGVwZW5kZW5jaWVzIiwidHJhbnNwaWxlQ2FjaGUiLCJ0cmFuc3BpbGVyIiwic3RhcnQiLCJvcHRpb25zIiwiY2xlYXIiLCJidWlsZENvbmZpZyIsInJlc29sdmVXb3Jrc3BhY2UiLCJwcm9qZWN0IiwicmVzb2x2ZVByb2plY3QiLCJyZXNvbHZlIiwiZ2V0U291cmNlRW50cnlQYXRoIiwiYnVpbGRGaWxlSW5mb01hcCIsImludmFsaWRhdGVBbGxTb3VyY2VGaWxlcyIsIndhdGNoIiwicHJvamVjdEZpbGVDaGFuZ2VkJCIsInN1YnNjcmliZSIsIm9uRmlsZUNoYW5nZSIsInRyYWNlIiwiYm9vdEVudHJ5IiwiZW1pdCIsImRpc3Bvc2UiLCJ1bnN1YnNjcmliZSIsIlN5bWJvbCIsImRpc3Bvc2VFbnRyeSIsImFzeW5jRGlzcG9zZSIsInZlcnNpb25Nb2R1bGUiLCJwYXRoVG9GaWxlVXJsIiwiZGVmYXVsdCIsImVycm9yIiwicmVib290Iiwic2NoZWR1bGVSZWJvb3QiLCJjcmVhdGUiLCJyb290RGlyIiwicHJvY2VzcyIsImN3ZCIsInByb2plY3RzIiwiZ2V0UHJvamVjdHMiLCJmb3VuZCIsImF0IiwiZmluZCIsInAiLCJFcnJvciIsImVudHJpZXMiLCJQcm9taXNlIiwiYWxsIiwibWFwIiwiZmlsZXMiLCJnZXRBbGxGaWxlcyIsImZpbGUiLCJmdWxsUGF0aCIsImZsYXQiLCJzcGVjaWZpZXIiLCJjb250ZXh0IiwibmV4dCIsInBhcmVudFVybCIsInBhcmVudFVSTCIsInJld3JpdHRlbiIsInJld3JpdGVKc1RvVHMiLCJyZXN1bHQiLCJvblBvc3RSZXNvbHZlIiwibG9hZCIsImxvYWRUcyIsImZvcm1hdCIsInNvdXJjZSIsInNob3J0Q2lyY3VpdCIsImVuZHNXaXRoIiwicGFyZW50Q2xlYW4iLCJzcGxpdCIsImpzUGF0aCIsInJlc29sdmVkIiwiVVJMIiwidG9TdHJpbmciLCJ0c1BhdGgiLCJyZXBsYWNlIiwiaGFzIiwiZ2V0Q2FjaGVkT3JOZXciLCJwYXJlbnRVcmxDbGVhbiIsImZpbGVQYXRoIiwicGFyZW50UGF0aCIsInVybE9iaiIsInNlYXJjaCIsImlzU291cmNlIiwicGFyZW50SXNTb3VyY2UiLCJ0cmFja0RlcGVuZGVuY3kiLCJzdGFydHNXaXRoIiwiY2xlYW5QYXRoIiwicGF0aG5hbWUiLCJmaWxlSW5mbyIsImdldCIsImNhY2hlZCIsInRzQ29uZmlnIiwiZ2V0VHNDb25maWdTeW5jIiwidXNlckNvbmZpZyIsImdldFN3Y0NvbmZpZ1N5bmMiLCJyZXNwb25zZSIsInRyYW5zZm9ybUZpbGVTeW5jIiwiZXM2IiwiYWxpYXNQYXRocyIsIm91dGNvbWUiLCJzZXQiLCJjb2RlIiwiZXZ0IiwiZXZlbnROYW1lIiwiV2F0Y2hFdmVudHMiLCJ1bmxpbmsiLCJkZWxldGUiLCJhZGQiLCJpc1NvdXJjZUZpbGUiLCJyZWxvYWRJZkFmZmVjdGVkIiwiaW52YWxpZGF0ZUNvbnRlbnRDYWNoZSIsImRlcHMiLCJnZXREZXBlbmRlbmN5R3JhcGgiLCJtb2R1bGVzIiwiU2V0IiwiaW5jbHVkZXMiLCJsZW5ndGgiLCJpbnZhbGlkYXRlTW9kdWxlIiwibW9kdWxlSWQiLCJwYXJlbnRNb2R1bGVzIiwiaXNTZWxmIiwibW9kdWxlRGVwcyIsInN1YkRlcHMiLCJkZXAiLCJzdWJzIiwidXBkYXRlZERlcHMiLCJtb2R1bGVVcmwiLCJ2ZXJzaW9uZWQiLCJ2ZXJzaW9uZWRVcmwiLCJzZWFyY2hQYXJhbXMiLCJEYXRlIiwibm93IiwibW9kdWxlIiwia2V5IiwicGFyZW50cyIsImZpbHRlcmVkIiwiZmlsdGVyIiwia2V5cyJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsWUFBWSxRQUFRLGNBQWM7QUFPM0MsU0FBU0MsYUFBYSxRQUFRLGNBQWM7QUFDNUMsT0FBT0MsVUFBVSxZQUFZO0FBQzdCLFNBQVNDLFlBQVksRUFBRUMsYUFBYSxFQUFFQyxpQkFBaUIsUUFBUSxrQkFBa0I7QUFFakYsU0FBU0MsZ0JBQWdCLFFBQVEsaUJBQWlCO0FBQ2xELFNBQVNDLE1BQU0sRUFBRUMsRUFBRSxRQUFRLHFCQUFxQjtBQUNoRCxTQUFTQyxRQUFRLFFBQVEseUJBQXlCO0FBQ2xELFNBQXNCQyxNQUFNLFFBQVEsbUJBQW1CO0FBS3ZELE1BQU1DLGtCQUFrQkgsR0FBR0ksYUFBYSxDQUFDLFlBQVlDLEdBQUc7QUFDeEQsTUFBTUMsb0JBQW9CO0FBQzFCLE1BQU1DLHFCQUFxQjtBQXFCM0IsT0FBTyxNQUFNQyx3QkFBd0JoQjtJQUNwQyw0RUFBNEU7SUFDM0RpQixTQUFpQlAsT0FBT08sTUFBTSxDQUFDRCxnQkFBZ0JFLElBQUksRUFBRTtJQUM5REMsV0FBVyxNQUFNO0lBQ2pCQyxrQkFBa0IsTUFBTTtJQUN4QkMsZ0JBQXlCO0lBQ3pCQyxZQUE4QjtJQUM5QkMsVUFBc0I7SUFDdEJDLGtCQUFpQztJQUN6QywyREFBMkQsR0FDM0QsQUFBUUMsY0FBYyxJQUFJQyxNQUF3QjtJQUMxQ0MsY0FBYyxJQUFJRCxNQUE2QjtJQUMvQ0UsZUFBZSxJQUFJRixNQUF3QjtJQUMzQ0cs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
|
package/es6/src/index.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export { DeferredScriptRunner } from "./deferred-script-runner.js";
|
|
2
|
-
export { flux } from "./flux.js";
|
|
3
1
|
export { FluxModule } from "./flux.module.js";
|
|
4
|
-
export {
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
export { HotReloadServer } from "./hot-reload-server.js";
|
|
3
|
+
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2ZsdXgvc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB7IEZsdXhNb2R1bGUgfSBmcm9tIFwiLi9mbHV4Lm1vZHVsZS5qc1wiO1xuZXhwb3J0IHR5cGUgeyBIb3RSZWxvYWRTZXJ2ZXJPcHRpb25zIH0gZnJvbSBcIi4vaG90LXJlbG9hZC1zZXJ2ZXIuanNcIjtcbmV4cG9ydCB7IEhvdFJlbG9hZFNlcnZlciB9IGZyb20gXCIuL2hvdC1yZWxvYWQtc2VydmVyLmpzXCI7XG5leHBvcnQgdHlwZSB7IFNlcnZlT3B0aW9ucyB9IGZyb20gXCIuL3NlcnZlLmFjdGlvbi5qc1wiO1xuIl0sIm5hbWVzIjpbIkZsdXhNb2R1bGUiLCJIb3RSZWxvYWRTZXJ2ZXIiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLFVBQVUsUUFBUSxtQkFBbUI7QUFFOUMsU0FBU0MsZUFBZSxRQUFRLHlCQUF5QiJ9
|