@graftland/hmr 0.2.0-beta.1 → 0.2.0-beta.2
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/README.md +4 -3
- package/README.zh-CN.md +1 -1
- package/README.zh-TW.md +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -5
- package/dist/index.js.map +1 -1
- package/dist/internal/changes.js +11 -2
- package/dist/internal/changes.js.map +1 -1
- package/dist/internal/modules.js +7 -0
- package/dist/internal/modules.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +45 -15
- package/src/internal/changes.ts +37 -10
- package/src/internal/modules.ts +8 -0
package/README.md
CHANGED
|
@@ -180,9 +180,10 @@ a mapping that can be represented. Validation and alias publication share the
|
|
|
180
180
|
core replacement transaction.
|
|
181
181
|
|
|
182
182
|
Native watcher producers observe their complete Exit after source cleanup and
|
|
183
|
-
before entering background stream merging.
|
|
184
|
-
|
|
185
|
-
failures
|
|
183
|
+
before entering background stream merging. Only cancellation requested by the
|
|
184
|
+
observer with a matching cause is silent. Resource cleanup interruption and
|
|
185
|
+
mixed failures are logged with their full Cause. Ordinary backend failures still
|
|
186
|
+
propagate to the consumer without duplicate logging.
|
|
186
187
|
|
|
187
188
|
## Long development sessions
|
|
188
189
|
|
package/README.zh-CN.md
CHANGED
|
@@ -95,7 +95,7 @@ map 或裸包解析的变化。
|
|
|
95
95
|
将观察租约与候选导入的临时资源分开。`ModuleResolver`
|
|
96
96
|
通过 importer 的第二个参数传递这个 scope。失败条目等待重试时应保留它,替换观察尝试或移除条目时关闭它;候选资源仍在失败时立即清理。省略该选项时使用调用方的 scope。
|
|
97
97
|
|
|
98
|
-
原生 watcher 在源资源清理完成后、进入后台合并边界之前观察完整 Exit
|
|
98
|
+
原生 watcher 在源资源清理完成后、进入后台合并边界之前观察完整 Exit。只有观察者主动发起且来源匹配的取消保持静默。资源清理自身产生的中断和混合失败都会记录完整 Cause;普通后端失败继续交给消费方处理,不重复记录。
|
|
99
99
|
|
|
100
100
|
CLI 把这个 importer 传给
|
|
101
101
|
`ModuleResolver`。它的入口 scope 在配置更新、激活失败或激活等待期间保持存活,并在入口被移除时关闭。
|
package/README.zh-TW.md
CHANGED
|
@@ -95,7 +95,7 @@ map 或裸套件解析的變化。
|
|
|
95
95
|
將觀察租約與候選匯入的暫時資源分開。`ModuleResolver`
|
|
96
96
|
透過 importer 的第二個參數傳遞這個 scope。失敗項目等待重試時應保留它,取代觀察嘗試或移除項目時關閉它;候選資源仍在失敗時立即清理。省略此選項時使用呼叫端的 scope。
|
|
97
97
|
|
|
98
|
-
原生 watcher 在來源資源清理完成後、進入背景合併邊界之前觀察完整 Exit
|
|
98
|
+
原生 watcher 在來源資源清理完成後、進入背景合併邊界之前觀察完整 Exit。只有觀察者主動發起且來源相符的取消不記錄錯誤。資源清理自身產生的中斷和混合失敗都會記錄完整 Cause;一般後端失敗繼續交給消費端處理,不重複記錄。
|
|
99
99
|
|
|
100
100
|
CLI 把這個 importer 傳給
|
|
101
101
|
`ModuleResolver`。它的入口 scope 在設定更新、啟用失敗或啟用等待期間保持存活,並在入口被移除時關閉。
|
package/dist/index.d.ts
CHANGED
|
@@ -54,6 +54,8 @@ export interface ImportOptions {
|
|
|
54
54
|
export interface Hmr {
|
|
55
55
|
/** Keeps imported entries registered until this HMR session closes. */
|
|
56
56
|
readonly importer: (specifier: string) => Promise<unknown>;
|
|
57
|
+
/** Uses the application context and Node cache, without watching or replacing the module. */
|
|
58
|
+
readonly importModule: (specifier: string) => Effect.Effect<unknown, HmrError>;
|
|
57
59
|
/** Registers an observation lease in observationScope, or the caller's scope when omitted. */
|
|
58
60
|
readonly importerScoped: (specifier: string, options?: ImportOptions) => Effect.Effect<unknown, HmrError, Scope.Scope>;
|
|
59
61
|
/** Imports every entry before replacing anything. Activation failures belong to Graft. */
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;WAsCmB;;qBAFN,iBAAiB;MAQhB;;YAKF,cAAc,KAAK;EAC9B;aAAqB,SAAS;;EAC9B;aACU,SAAS;aACT;;EAGV;aAAmB,OAAO,MAAM,MAAM;;;qBAG1B,aAAW,KAAA,WAAA;;WAHG,OAAA,MAAM,MAAM;;;WANR,SAAA;;;WAEX,SAAA;WAEjB;;YAOS,eAAe,QAAQ;WAAwB;;iBAE1C;;WAEP;;WAEA,WAAW;;iBAGJ,qBAAqB,WAAW;WACvC,WAAW,SAAS;;WAEpB,UAAU;;;iBAIH;WACP,kBAAkB,MAAM;;iBAGjB;;WAEP,WAAW,sBAAsB;;WAEjC,iBACR,mBACA,UAAU,kBACN,OAAO,gBAAgB,UAAU,MAAM;;WAEnC,QAAQ,OAAO,OAAO,cAAc;;;;;;WAMpC,QACR,OAAO,uBACP,UAAU,iBACN,OAAO,OACX,aACA,cAAc,eACd,WAAW;;;;;;qBAQA,OAAI,SACP,YACP,OAAO,OAAO,YAAY,MAAM,QAAQ,MAAM"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;WAsCmB;;qBAFN,iBAAiB;MAQhB;;YAKF,cAAc,KAAK;EAC9B;aAAqB,SAAS;;EAC9B;aACU,SAAS;aACT;;EAGV;aAAmB,OAAO,MAAM,MAAM;;;qBAG1B,aAAW,KAAA,WAAA;;WAHG,OAAA,MAAM,MAAM;;;WANR,SAAA;;;WAEX,SAAA;WAEjB;;YAOS,eAAe,QAAQ;WAAwB;;iBAE1C;;WAEP;;WAEA,WAAW;;iBAGJ,qBAAqB,WAAW;WACvC,WAAW,SAAS;;WAEpB,UAAU;;;iBAIH;WACP,kBAAkB,MAAM;;iBAGjB;;WAEP,WAAW,sBAAsB;;WAEjC,eAAe,sBAAsB,OAAO,gBAAgB;;WAE5D,iBACR,mBACA,UAAU,kBACN,OAAO,gBAAgB,UAAU,MAAM;;WAEnC,QAAQ,OAAO,OAAO,cAAc;;;;;;WAMpC,QACR,OAAO,uBACP,UAAU,iBACN,OAAO,OACX,aACA,cAAc,eACd,WAAW;;;;;;qBAQA,OAAI,SACP,YACP,OAAO,OAAO,YAAY,MAAM,QAAQ,MAAM"}
|
package/dist/index.js
CHANGED
|
@@ -196,9 +196,21 @@ const make = (options) => Effect.gen(function* () {
|
|
|
196
196
|
})
|
|
197
197
|
}));
|
|
198
198
|
}).pipe(Effect.ensuring(collect)))).pipe(Effect.flatMap(({ exit }) => exit), preserveExit);
|
|
199
|
+
const importModule = (specifier) => serial(checkOpen.pipe(Effect.andThen(Effect.tryPromise({
|
|
200
|
+
try: () => import(
|
|
201
|
+
/* @vite-ignore */
|
|
202
|
+
hooks.rawRequest(specifier)
|
|
203
|
+
),
|
|
204
|
+
catch: (cause) => HmrError.make({
|
|
205
|
+
stage: "import",
|
|
206
|
+
specifier,
|
|
207
|
+
cause
|
|
208
|
+
})
|
|
209
|
+
}))));
|
|
199
210
|
const importerScoped = (specifier, options) => options === void 0 ? importWithLease(specifier) : importWithLease(specifier).pipe(Scope.provide(options.observationScope));
|
|
200
211
|
const importer = (specifier) => Ref.getUnsafe(closed) ? Promise.reject(closedError()) : run(importerScoped(specifier).pipe(Effect.provideService(Scope.Scope, imports)));
|
|
201
|
-
const
|
|
212
|
+
const unsupportedAttempts = (attempts) => Array.reduce(attempts, HashSet.empty(), (all, attempt) => HashSet.union(all, hooks.unsupported(attempt.generation, [attempt.url])));
|
|
213
|
+
const unsupportedModules = Ref.get(owners).pipe(Effect.map((owned) => unsupportedAttempts(Array.getSomes(Array.map(HashMap.toValues(owned), (owner) => owner.active)))));
|
|
202
214
|
const reloadChanged = (dirty) => serial(Effect.gen(function* () {
|
|
203
215
|
yield* checkOpen;
|
|
204
216
|
const fullRetry = yield* Ref.get(retryAll);
|
|
@@ -261,14 +273,17 @@ const make = (options) => Effect.gen(function* () {
|
|
|
261
273
|
plugin,
|
|
262
274
|
leases
|
|
263
275
|
}]));
|
|
264
|
-
const next = HashMap.union(
|
|
276
|
+
const next = HashMap.union(entries, replacements);
|
|
265
277
|
const pairs = Array.map(candidates, ({ previous, plugin }) => [previous, plugin]);
|
|
266
278
|
const changed = yield* changedResolutions;
|
|
267
279
|
if (changed.length > 0) return WatchResult.Skipped({
|
|
268
280
|
reason: "restart-required",
|
|
269
281
|
modules: changed
|
|
270
282
|
});
|
|
271
|
-
const unsafe =
|
|
283
|
+
const unsafe = unsupportedAttempts(Array.map(active, (attempt) => HashMap.has(replacements, attempt.url) ? {
|
|
284
|
+
...attempt,
|
|
285
|
+
generation: candidate
|
|
286
|
+
} : attempt));
|
|
272
287
|
if (HashSet.size(unsafe) > 0) return WatchResult.Skipped({
|
|
273
288
|
reason: "restart-required",
|
|
274
289
|
modules: Array.fromIterable(unsafe)
|
|
@@ -290,10 +305,10 @@ const make = (options) => Effect.gen(function* () {
|
|
|
290
305
|
entries: next,
|
|
291
306
|
generation: candidate
|
|
292
307
|
});
|
|
293
|
-
yield* Ref.
|
|
308
|
+
yield* Ref.update(cached, (cached) => HashMap.union(HashMap.filter(cached, (_, url) => HashMap.has(next, url)), HashMap.map(replacements, (_, url) => ({
|
|
294
309
|
url,
|
|
295
310
|
generation: candidate
|
|
296
|
-
})));
|
|
311
|
+
}))));
|
|
297
312
|
yield* Ref.set(retryDirty, HashSet.empty());
|
|
298
313
|
yield* Ref.set(retryAll, false);
|
|
299
314
|
return WatchResult.Reloaded({ entries: Array.map(candidates, (candidate) => candidate.url) });
|
|
@@ -305,6 +320,7 @@ const make = (options) => Effect.gen(function* () {
|
|
|
305
320
|
return {
|
|
306
321
|
importer,
|
|
307
322
|
importerScoped,
|
|
323
|
+
importModule,
|
|
308
324
|
reload: reloadChanged(),
|
|
309
325
|
watch: (paths, watchOptions) => paths.length === 0 ? Stream.empty : changes((use) => Ref.get(owners).pipe(Effect.map((owners) => hooks.files([...Array.getSomes(Array.map(HashMap.toValues(owners), (owner) => owner.active)), ...Array.getSomes(Array.map(HashMap.toValues(owners), (owner) => owner.pending))])), Effect.flatMap(use), semaphore.withPermits(1)), paths, watchOptions).pipe(Stream.mapEffect((dirty) => Effect.map(Effect.exit(reloadChanged(dirty)), (exit) => Exit.isSuccess(exit) ? exit.value : WatchResult.Failed({ cause: exit.cause }))), Stream.merge(Stream.tick("1 second").pipe(Stream.mapEffect(() => unsupportedModules.pipe(semaphore.withPermits(1))), Stream.changes, Stream.filter((modules) => HashSet.size(modules) > 0), Stream.map((modules) => WatchResult.Skipped({
|
|
310
326
|
reason: "restart-required",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Hot module replacement for Graft plugins on Node.js.\n */\n// @effect-diagnostics-next-line nodeBuiltinImport:off -- native import resolution must work without requiring a platform layer\nimport { realpath } from \"node:fs/promises\"\nimport { fileURLToPath, pathToFileURL } from \"node:url\"\nimport { Graft, Plugin } from \"@graftland/graft\"\nimport {\n\tArray,\n\tCause,\n\tData,\n\tDeferred,\n\tEffect,\n\tExit,\n\tFiberSet,\n\tFileSystem,\n\tHashMap,\n\tHashSet,\n\tOption,\n\tRef,\n\tResult,\n\tString,\n\tSchema,\n\tSemaphore,\n\tStream,\n\tScope,\n} from \"effect\"\nimport type { Duration, PlatformError } from \"effect\"\nimport { changes } from \"./internal/changes\"\nimport {\n\tisMissingEntry,\n\tmodules,\n\tRestartRequired,\n\ttype Attempt,\n} from \"./internal/modules\"\n\nexport class HmrError extends Schema.TaggedError<\n\tHmrError,\n\t{ readonly brand: unique symbol }\n>()(\"HmrError\", {\n\tstage: Schema.Literals([\"import\", \"exports\", \"closed\"]),\n\tspecifier: Schema.String,\n\tcause: Schema.Unknown,\n}) {\n\toverride get message(): string {\n\t\treturn `HMR ${this.stage} failed for ${this.specifier || \"the closed session\"}`\n\t}\n}\n\nexport type WatchResult = Data.TaggedEnum<{\n\tReloaded: { readonly entries: ReadonlyArray<string> }\n\tSkipped: {\n\t\treadonly modules: ReadonlyArray<string>\n\t\treadonly reason:\n\t\t\t\"restart-required\" | \"ambiguous-exports\" | \"identity-conflict\"\n\t}\n\tFailed: { readonly cause: Cause.Cause<HmrError> }\n}>\n\nexport const WatchResult = Data.taggedEnum<WatchResult>()\n\nexport type ReloadResult = Exclude<WatchResult, { readonly _tag: \"Failed\" }>\n\nexport interface Options {\n\t/** Application module URL, usually import.meta.url; used for bare and relative resolution. */\n\treadonly base: string\n\t/** Files to version. Defaults to file URLs outside node_modules. Entries are always included. */\n\treadonly include?: (url: string) => boolean\n}\n\nexport interface WatchOptions extends FileSystem.WatchOptions {\n\treadonly debounce?: Duration.Input\n\t/** Receives an absolute file path; applies to native events and reconciliation. */\n\treadonly filter?: (path: string) => boolean\n}\n\n/** Separates retry observations from an importer's temporary resource scope. */\nexport interface ImportOptions {\n\treadonly observationScope: Scope.Scope\n}\n\nexport interface Hmr {\n\t/** Keeps imported entries registered until this HMR session closes. */\n\treadonly importer: (specifier: string) => Promise<unknown>\n\t/** Registers an observation lease in observationScope, or the caller's scope when omitted. */\n\treadonly importerScoped: (\n\t\tspecifier: string,\n\t\toptions?: ImportOptions,\n\t) => Effect.Effect<unknown, HmrError, Scope.Scope>\n\t/** Imports every entry before replacing anything. Activation failures belong to Graft. */\n\treadonly reload: Effect.Effect<ReloadResult, HmrError>\n\t/**\n\t * Consuming this stream installs graph-driven directory watchers, polls stat once\n\t * per second, and audits contents every ten seconds to recover missed events. Known native loading limitations emit\n\t * Skipped even without a file event. The consumer owns the stream's lifetimes.\n\t */\n\treadonly watch: (\n\t\tpaths: ReadonlyArray<string>,\n\t\toptions?: WatchOptions,\n\t) => Stream.Stream<\n\t\tWatchResult,\n\t\tPlatformError.PlatformError,\n\t\tFileSystem.FileSystem\n\t>\n}\n\n/**\n * Installs Node module hooks until the enclosing scope closes. Module evaluation\n * must be side-effect free. Versioned ESM cache entries are not reclaimed.\n */\nexport const make = (\n\toptions: Options,\n): Effect.Effect<Hmr, never, Graft.Graft | Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst graft = yield* Graft.Graft\n\t\tconst semaphore = yield* Semaphore.make(1)\n\t\t// A lease owns both the running graph and its latest uncommitted attempt.\n\t\tconst owners = yield* Ref.make(\n\t\t\tHashMap.empty<\n\t\t\t\tsymbol,\n\t\t\t\t{\n\t\t\t\t\treadonly active: Option.Option<Attempt>\n\t\t\t\t\treadonly pending: Option.Option<Attempt>\n\t\t\t\t}\n\t\t\t>(),\n\t\t)\n\t\tconst closed = yield* Ref.make(false)\n\t\tconst session = yield* Effect.scope\n\t\t// Transfer the complete Exit before restoring interruption. Effect may replace\n\t\t// a failed masked operation with pending interruption at that boundary.\n\t\tconst preserveExit = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst completed = yield* Deferred.make<Exit.Exit<A, E>>()\n\t\t\t\treturn yield* effect.pipe(\n\t\t\t\t\tEffect.exit,\n\t\t\t\t\tEffect.tap((exit) => Deferred.succeed(completed, exit)),\n\t\t\t\t\tEffect.uninterruptible,\n\t\t\t\t\tEffect.flatten,\n\t\t\t\t\tEffect.onExit((exit) =>\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\tif (Exit.isSuccess(exit) || !Cause.hasInterrupts(exit.cause))\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\tconst saved = yield* Deferred.poll(completed)\n\t\t\t\t\t\t\tif (Option.isNone(saved)) return\n\t\t\t\t\t\t\tconst original = yield* saved.value\n\t\t\t\t\t\t\tif (Exit.isFailure(original))\n\t\t\t\t\t\t\t\tyield* Effect.logError(\n\t\t\t\t\t\t\t\t\t\"HMR operation failed during cancellation\",\n\t\t\t\t\t\t\t\t\toriginal.cause,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t})\n\t\t// Native imports cannot be cancelled: keep the lock until their promises settle.\n\t\tconst serial = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n\t\t\teffect.pipe(preserveExit, semaphore.withPermits(1))\n\t\tconst hooks = yield* Effect.acquireRelease(\n\t\t\tEffect.sync(() =>\n\t\t\t\tmodules(\n\t\t\t\t\toptions.base,\n\t\t\t\t\toptions.include ??\n\t\t\t\t\t\t((url) =>\n\t\t\t\t\t\t\t!String.includes(\"/node_modules/\")(new URL(url).pathname)),\n\t\t\t\t),\n\t\t\t),\n\t\t\t(hooks) =>\n\t\t\t\tserial(\n\t\t\t\t\tRef.set(closed, true).pipe(Effect.andThen(Effect.sync(hooks.close))),\n\t\t\t\t),\n\t\t)\n\t\t// Node can return a cached entry after its last observation lease closes.\n\t\t// Keep current entry attempts without polling or reloading unleased entries.\n\t\t// The hooks also retain cached instance facts for older resolution views.\n\t\tconst cached = yield* Ref.make(HashMap.empty<string, Attempt>())\n\n\t\tconst retryDirty = yield* Ref.make(HashSet.empty<string>())\n\t\tconst retryAll = yield* Ref.make(false)\n\t\tconst observations = Ref.get(owners).pipe(\n\t\t\tEffect.map((owners) =>\n\t\t\t\tArray.flatMap(HashMap.toValues(owners), (owner) =>\n\t\t\t\t\tArray.getSomes([owner.active, owner.pending]),\n\t\t\t\t),\n\t\t\t),\n\t\t)\n\t\tconst collect = Effect.gen(function* () {\n\t\t\tconst attempts = yield* observations\n\t\t\tconst currentCache = yield* Ref.get(cached)\n\t\t\thooks.collect([...attempts, ...HashMap.toValues(currentCache)])\n\t\t\tconst files = hooks.files(attempts)\n\t\t\tyield* Ref.update(\n\t\t\t\tretryDirty,\n\t\t\t\tHashSet.filter((url) => HashMap.has(files, url)),\n\t\t\t)\n\t\t\tif (attempts.length === 0) yield* Ref.set(retryAll, false)\n\t\t})\n\n\t\tconst state = yield* Ref.make({\n\t\t\tgeneration: hooks.prepare(),\n\t\t\tentries: HashMap.empty<\n\t\t\t\tstring,\n\t\t\t\t{\n\t\t\t\t\treadonly plugin: Plugin.Plugin\n\t\t\t\t\treadonly leases: HashSet.HashSet<symbol>\n\t\t\t\t}\n\t\t\t>(),\n\t\t})\n\t\t// Stop Promise-backed operations before releasing their leases. Otherwise\n\t\t// a lease finalizer could wait on an import before its owner interrupts it.\n\t\tconst imports = yield* Scope.fork(session)\n\t\tconst run = yield* FiberSet.makeRuntimePromise<never, unknown, HmrError>()\n\t\tconst closedError = () =>\n\t\t\tHmrError.make({\n\t\t\t\tstage: \"closed\",\n\t\t\t\tspecifier: \"\",\n\t\t\t\tcause: \"HMR scope is closed\",\n\t\t\t})\n\t\tconst checkOpen = Ref.get(closed).pipe(\n\t\t\tEffect.flatMap((closed) =>\n\t\t\t\tclosed ? Effect.fail(closedError()) : Effect.void,\n\t\t\t),\n\t\t)\n\t\tconst physicalTarget = (request: string) =>\n\t\t\tEffect.tryPromise({\n\t\t\t\ttry: () => realpath(fileURLToPath(request)),\n\t\t\t\tcatch: (cause) =>\n\t\t\t\t\tHmrError.make({ stage: \"import\", specifier: request, cause }),\n\t\t\t}).pipe(\n\t\t\t\tEffect.map((path) => pathToFileURL(path).href),\n\t\t\t\tEffect.catchIf(\n\t\t\t\t\t(error) => isMissingEntry(request, error.cause),\n\t\t\t\t\t() => Effect.undefined,\n\t\t\t\t),\n\t\t\t)\n\t\tconst changedResolution = Effect.fnUntraced(function* (\n\t\t\tattempt: Pick<Attempt, \"url\" | \"request\">,\n\t\t) {\n\t\t\tif (attempt.request === undefined) return Option.none<string>()\n\t\t\tconst request = attempt.request\n\t\t\tconst expected = pathToFileURL(fileURLToPath(attempt.url)).href\n\t\t\tconst actual = yield* physicalTarget(request)\n\t\t\tif (actual === expected) return Option.none<string>()\n\t\t\t// If both paths disappeared, this is ordinary entry deletion. A\n\t\t\t// missing link with a surviving old target must never reload that target.\n\t\t\tif (actual === undefined) {\n\t\t\t\tconst remaining = yield* physicalTarget(attempt.url)\n\t\t\t\tif (remaining === undefined) return Option.none<string>()\n\t\t\t}\n\t\t\treturn Option.some(request)\n\t\t})\n\n\t\tconst changedResolutions = Effect.gen(function* () {\n\t\t\tconst current = yield* Ref.get(owners)\n\t\t\tconst attempts = hooks.resolutions(\n\t\t\t\tArray.flatMap(HashMap.toValues(current), (owner) =>\n\t\t\t\t\tArray.getSomes([owner.active, owner.pending]),\n\t\t\t\t),\n\t\t\t)\n\t\t\tconst requests = HashSet.fromIterable(\n\t\t\t\tArray.filterMap(attempts, (attempt) =>\n\t\t\t\t\tattempt.request === undefined\n\t\t\t\t\t\t? Result.fail(undefined)\n\t\t\t\t\t\t: Result.succeed(attempt.request),\n\t\t\t\t),\n\t\t\t)\n\t\t\tconst resolveAll = (requests: HashSet.HashSet<string>) =>\n\t\t\t\tEffect.forEach(\n\t\t\t\t\trequests,\n\t\t\t\t\t(request) =>\n\t\t\t\t\t\tphysicalTarget(request).pipe(\n\t\t\t\t\t\t\tEffect.map((target) => [request, target] as const),\n\t\t\t\t\t\t),\n\t\t\t\t\t{ concurrency: 8 },\n\t\t\t\t).pipe(Effect.map(HashMap.fromIterable))\n\t\t\tconst actual = yield* resolveAll(requests)\n\t\t\tconst missingTargets = HashSet.fromIterable(\n\t\t\t\tArray.filterMap(attempts, (attempt) =>\n\t\t\t\t\tattempt.request !== undefined &&\n\t\t\t\t\tOption.getOrUndefined(HashMap.get(actual, attempt.request)) ===\n\t\t\t\t\t\tundefined &&\n\t\t\t\t\t!HashMap.has(actual, attempt.url)\n\t\t\t\t\t\t? Result.succeed(attempt.url)\n\t\t\t\t\t\t: Result.fail(undefined),\n\t\t\t\t),\n\t\t\t)\n\t\t\tconst remaining = yield* resolveAll(missingTargets)\n\t\t\tconst targets = HashMap.union(actual, remaining)\n\n\t\t\treturn Array.fromIterable(\n\t\t\t\tHashSet.fromIterable(\n\t\t\t\t\tArray.filterMap(attempts, (attempt) => {\n\t\t\t\t\t\tif (attempt.request === undefined) return Result.fail(undefined)\n\t\t\t\t\t\tconst actual = Option.getOrUndefined(\n\t\t\t\t\t\t\tHashMap.get(targets, attempt.request),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst expected = pathToFileURL(fileURLToPath(attempt.url)).href\n\t\t\t\t\t\treturn actual === expected ||\n\t\t\t\t\t\t\t(actual === undefined &&\n\t\t\t\t\t\t\t\tOption.getOrUndefined(HashMap.get(targets, attempt.url)) ===\n\t\t\t\t\t\t\t\t\tundefined)\n\t\t\t\t\t\t\t? Result.fail(undefined)\n\t\t\t\t\t\t\t: Result.succeed(attempt.request)\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t)\n\t\t})\n\n\t\tconst load = Effect.fnUntraced(function* (specifier: string) {\n\t\t\tconst namespace = yield* Effect.tryPromise({\n\t\t\t\ttry: () => import(/* @vite-ignore */ hooks.request(specifier)),\n\t\t\t\tcatch: (cause) => HmrError.make({ stage: \"import\", specifier, cause }),\n\t\t\t})\n\t\t\tconst plugin = Plugin.fromModule(namespace)\n\t\t\tif (Option.isNone(plugin))\n\t\t\t\treturn yield* HmrError.make({\n\t\t\t\t\tstage: \"exports\",\n\t\t\t\t\tspecifier,\n\t\t\t\t\tcause: \"Expected a default or named plugin export\",\n\t\t\t\t})\n\t\t\tconst url = yield* Effect.fromOption(hooks.resolved()).pipe(\n\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\tHmrError.make({ stage: \"import\", specifier, cause }),\n\t\t\t\t),\n\t\t\t)\n\t\t\tconst request = hooks.fileRequest(specifier)\n\t\t\tconst attempt = {\n\t\t\t\turl,\n\t\t\t\t...Option.match(request, {\n\t\t\t\t\tonNone: () => ({}),\n\t\t\t\t\tonSome: (request) => ({ request }),\n\t\t\t\t}),\n\t\t\t}\n\t\t\tconst changed = yield* changedResolution(attempt)\n\t\t\tif (Option.isSome(changed))\n\t\t\t\treturn yield* HmrError.make({\n\t\t\t\t\tstage: \"import\",\n\t\t\t\t\tspecifier,\n\t\t\t\t\tcause: RestartRequired.make({ url: changed.value }),\n\t\t\t\t})\n\t\t\treturn { namespace, plugin: plugin.value, url }\n\t\t})\n\t\tconst importWithLease = (specifier: string) =>\n\t\t\tEffect.acquireRelease(\n\t\t\t\tserial(\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tyield* checkOpen\n\t\t\t\t\t\tconst current = yield* Ref.get(state)\n\t\t\t\t\t\thooks.start(current.generation)\n\t\t\t\t\t\t// Acquire an owner for either Exit. Rethrow only after its finalizer\n\t\t\t\t\t\t// is registered, so failed imports remain available for scoped retry.\n\t\t\t\t\t\tconst exit = yield* Effect.exit(load(specifier))\n\t\t\t\t\t\tconst token: symbol = Symbol()\n\t\t\t\t\t\tconst root = Option.orElse(hooks.resolved(), () =>\n\t\t\t\t\t\t\tString.startsWith(\"file:\")(specifier)\n\t\t\t\t\t\t\t\t? Option.some(specifier)\n\t\t\t\t\t\t\t\t: Option.none(),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst attempt = Option.map(root, (url) => ({\n\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\tgeneration: current.generation,\n\t\t\t\t\t\t\t...Option.match(hooks.fileRequest(specifier), {\n\t\t\t\t\t\t\t\tonNone: () => ({}),\n\t\t\t\t\t\t\t\tonSome: (request) => ({ request }),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t}))\n\t\t\t\t\t\tif (Option.isSome(attempt))\n\t\t\t\t\t\t\tyield* Ref.update(\n\t\t\t\t\t\t\t\tcached,\n\t\t\t\t\t\t\t\tHashMap.set(attempt.value.url, attempt.value),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\tyield* Ref.update(\n\t\t\t\t\t\t\towners,\n\t\t\t\t\t\t\tHashMap.set(token, {\n\t\t\t\t\t\t\t\tactive: Exit.isSuccess(exit) ? attempt : Option.none(),\n\t\t\t\t\t\t\t\tpending: Exit.isFailure(exit) ? attempt : Option.none(),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (Exit.isSuccess(exit)) {\n\t\t\t\t\t\t\tconst entry = exit.value\n\t\t\t\t\t\t\tconst previous = HashMap.get(current.entries, entry.url)\n\t\t\t\t\t\t\tconst leases = Option.match(previous, {\n\t\t\t\t\t\t\t\tonNone: () => HashSet.empty<symbol>(),\n\t\t\t\t\t\t\t\tonSome: (entry) => entry.leases,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tyield* Ref.set(state, {\n\t\t\t\t\t\t\t\t...current,\n\t\t\t\t\t\t\t\tentries: HashMap.set(current.entries, entry.url, {\n\t\t\t\t\t\t\t\t\tplugin: entry.plugin,\n\t\t\t\t\t\t\t\t\tleases: HashSet.add(leases, token),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn { token, exit: Exit.map(exit, (entry) => entry.namespace) }\n\t\t\t\t\t}).pipe(\n\t\t\t\t\t\tEffect.ensuring(Effect.sync(hooks.discard)),\n\t\t\t\t\t\tEffect.ensuring(collect),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\t({ token }) =>\n\t\t\t\t\tserial(\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\tyield* Ref.update(owners, HashMap.remove(token))\n\t\t\t\t\t\t\tyield* Ref.update(state, (current) => ({\n\t\t\t\t\t\t\t\t...current,\n\t\t\t\t\t\t\t\tentries: HashMap.filterMap(current.entries, (entry) => {\n\t\t\t\t\t\t\t\t\tconst leases = HashSet.remove(entry.leases, token)\n\t\t\t\t\t\t\t\t\treturn HashSet.size(leases) === 0\n\t\t\t\t\t\t\t\t\t\t? Result.fail(undefined)\n\t\t\t\t\t\t\t\t\t\t: Result.succeed({ ...entry, leases })\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t}).pipe(Effect.ensuring(collect)),\n\t\t\t\t\t),\n\t\t\t).pipe(\n\t\t\t\tEffect.flatMap(({ exit }) => exit),\n\t\t\t\tpreserveExit,\n\t\t\t)\n\n\t\tconst importerScoped: Hmr[\"importerScoped\"] = (specifier, options) =>\n\t\t\toptions === undefined\n\t\t\t\t? importWithLease(specifier)\n\t\t\t\t: importWithLease(specifier).pipe(\n\t\t\t\t\t\tScope.provide(options.observationScope),\n\t\t\t\t\t)\n\n\t\tconst importer = (specifier: string): Promise<unknown> =>\n\t\t\t// A closed FiberSet interrupts new work before checkOpen can execute.\n\t\t\tRef.getUnsafe(closed)\n\t\t\t\t? Promise.reject(closedError())\n\t\t\t\t: run(\n\t\t\t\t\t\timporterScoped(specifier).pipe(\n\t\t\t\t\t\t\tEffect.provideService(Scope.Scope, imports),\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\n\t\tconst unsupportedModules = Ref.get(state).pipe(\n\t\t\tEffect.map(({ generation, entries }) =>\n\t\t\t\thooks.unsupported(\n\t\t\t\t\tgeneration,\n\t\t\t\t\tArray.fromIterable(HashMap.keys(entries)),\n\t\t\t\t),\n\t\t\t),\n\t\t)\n\n\t\tconst reloadChanged = (dirty?: HashSet.HashSet<string>) =>\n\t\t\tserial(\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tyield* checkOpen\n\t\t\t\t\tconst fullRetry = yield* Ref.get(retryAll)\n\t\t\t\t\tconst force = dirty === undefined || fullRetry\n\t\t\t\t\tconst pendingDirty = yield* Ref.get(retryDirty)\n\t\t\t\t\tconst changedFiles =\n\t\t\t\t\t\tdirty === undefined\n\t\t\t\t\t\t\t? pendingDirty\n\t\t\t\t\t\t\t: HashSet.union(pendingDirty, dirty)\n\t\t\t\t\tyield* Ref.set(retryDirty, changedFiles)\n\t\t\t\t\tyield* Ref.set(retryAll, force)\n\t\t\t\t\tconst changed = yield* changedResolutions\n\t\t\t\t\tif (changed.length > 0)\n\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\tmodules: changed,\n\t\t\t\t\t\t})\n\t\t\t\t\tconst { entries } = yield* Ref.get(state)\n\t\t\t\t\tconst unsupported = yield* unsupportedModules\n\t\t\t\t\tif (HashSet.size(unsupported) > 0)\n\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\tmodules: Array.fromIterable(unsupported),\n\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t})\n\t\t\t\t\tconst owned = yield* Ref.get(owners)\n\t\t\t\t\tconst attempts = Array.flatMap(HashMap.toValues(owned), (owner) =>\n\t\t\t\t\t\tArray.getSomes([owner.active, owner.pending]),\n\t\t\t\t\t)\n\t\t\t\t\tconst active = Array.getSomes(\n\t\t\t\t\t\tArray.map(HashMap.toValues(owned), (owner) => owner.active),\n\t\t\t\t\t)\n\t\t\t\t\tlet selected = entries\n\t\t\t\t\tlet invalid = HashSet.empty<string>()\n\t\t\t\t\tif (!force) {\n\t\t\t\t\t\tlet affected = changedFiles\n\t\t\t\t\t\t// Plugin identity groups and importer closure can expand each other.\n\t\t\t\t\t\t// Reach a fixed point before allocating any candidate instance.\n\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\tinvalid = hooks.invalidated(attempts, affected)\n\t\t\t\t\t\t\tconst plugins = HashSet.fromIterable(\n\t\t\t\t\t\t\t\tArray.filterMap(Array.fromIterable(entries), ([url, entry]) =>\n\t\t\t\t\t\t\t\t\tHashSet.has(affected, url) ||\n\t\t\t\t\t\t\t\t\tArray.some(Array.fromIterable(entry.leases), (token) =>\n\t\t\t\t\t\t\t\t\t\tOption.exists(HashMap.get(owned, token), (owner) =>\n\t\t\t\t\t\t\t\t\t\t\tArray.some(\n\t\t\t\t\t\t\t\t\t\t\t\tArray.getSomes([owner.active, owner.pending]),\n\t\t\t\t\t\t\t\t\t\t\t\t(attempt) => hooks.affected(attempt, invalid),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t? Result.succeed(entry.plugin)\n\t\t\t\t\t\t\t\t\t\t: Result.fail(undefined),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tselected = HashMap.filter(entries, (entry) =>\n\t\t\t\t\t\t\t\tHashSet.has(plugins, entry.plugin),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tconst expanded = HashSet.union(\n\t\t\t\t\t\t\t\taffected,\n\t\t\t\t\t\t\t\tHashSet.fromIterable(HashMap.keys(selected)),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tif (HashSet.size(expanded) === HashSet.size(affected)) break\n\t\t\t\t\t\t\taffected = expanded\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Advance even without entries so retries bypass cached failed imports.\n\t\t\t\t\tconst candidate = force\n\t\t\t\t\t\t? hooks.prepare()\n\t\t\t\t\t\t: hooks.prepare(active, invalid)\n\n\t\t\t\t\thooks.start(candidate, true)\n\t\t\t\t\treturn yield* Effect.gen(function* () {\n\t\t\t\t\t\tconst loaded = yield* Effect.forEach(selected, ([url, previous]) =>\n\t\t\t\t\t\t\tRef.update(\n\t\t\t\t\t\t\t\towners,\n\t\t\t\t\t\t\t\tHashMap.map((owner, token) =>\n\t\t\t\t\t\t\t\t\tHashSet.has(previous.leases, token)\n\t\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\t...owner,\n\t\t\t\t\t\t\t\t\t\t\t\tpending: Option.map(owner.active, (attempt) => ({\n\t\t\t\t\t\t\t\t\t\t\t\t\t...attempt,\n\t\t\t\t\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\t\t\t\t\tgeneration: candidate,\n\t\t\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t: owner,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t).pipe(\n\t\t\t\t\t\t\t\tEffect.andThen(load(url)),\n\t\t\t\t\t\t\t\tEffect.map((entry) =>\n\t\t\t\t\t\t\t\t\tOption.some({\n\t\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\t\tprevious: previous.plugin,\n\t\t\t\t\t\t\t\t\t\tleases: previous.leases,\n\t\t\t\t\t\t\t\t\t\tplugin: entry.plugin,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tEffect.catchIf(\n\t\t\t\t\t\t\t\t\t(error) =>\n\t\t\t\t\t\t\t\t\t\terror.stage === \"import\" &&\n\t\t\t\t\t\t\t\t\t\tisMissingEntry(url, error.cause),\n\t\t\t\t\t\t\t\t\t() => Effect.succeedNone,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst candidates = Array.getSomes(loaded)\n\t\t\t\t\t\tconst alternatives = Array.reduce(\n\t\t\t\t\t\t\tcandidates,\n\t\t\t\t\t\t\tHashMap.empty<Plugin.Plugin, HashSet.HashSet<Plugin.Plugin>>(),\n\t\t\t\t\t\t\t(groups, { previous, plugin }) =>\n\t\t\t\t\t\t\t\tHashMap.set(\n\t\t\t\t\t\t\t\t\tgroups,\n\t\t\t\t\t\t\t\t\tprevious,\n\t\t\t\t\t\t\t\t\tHashSet.add(\n\t\t\t\t\t\t\t\t\t\tOption.getOrElse(\n\t\t\t\t\t\t\t\t\t\t\tHashMap.get(groups, previous),\n\t\t\t\t\t\t\t\t\t\t\tHashSet.empty<Plugin.Plugin>,\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\tplugin,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst ambiguous = Array.filter(candidates, ({ previous }) =>\n\t\t\t\t\t\t\tOption.exists(\n\t\t\t\t\t\t\t\tHashMap.get(alternatives, previous),\n\t\t\t\t\t\t\t\t(plugins) => HashSet.size(plugins) > 1,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (ambiguous.length > 0)\n\t\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\t\treason: \"ambiguous-exports\",\n\t\t\t\t\t\t\t\tmodules: Array.map(ambiguous, ({ url }) => url),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\tconst replacements = HashMap.fromIterable(\n\t\t\t\t\t\t\tArray.map(\n\t\t\t\t\t\t\t\tcandidates,\n\t\t\t\t\t\t\t\t({ url, plugin, leases }) => [url, { plugin, leases }] as const,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst next = HashMap.union(\n\t\t\t\t\t\t\tHashMap.filter(entries, (_, url) => !HashMap.has(selected, url)),\n\t\t\t\t\t\t\treplacements,\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tconst pairs = Array.map(\n\t\t\t\t\t\t\tcandidates,\n\t\t\t\t\t\t\t({ previous, plugin }) => [previous, plugin] as const,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst changed = yield* changedResolutions\n\t\t\t\t\t\tif (changed.length > 0)\n\t\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\t\tmodules: changed,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t// A reused instance can acquire a native loading capability while the\n\t\t\t\t\t\t// candidate imports. Observe it without throwing into concurrent old code.\n\t\t\t\t\t\tconst unsafe = hooks.unsupported(\n\t\t\t\t\t\t\tcandidate,\n\t\t\t\t\t\t\tArray.fromIterable(HashMap.keys(next)),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (HashSet.size(unsafe) > 0)\n\t\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\t\tmodules: Array.fromIterable(unsafe),\n\t\t\t\t\t\t\t})\n\n\t\t\t\t\t\tconst replacement = yield* Graft.replace(pairs).pipe(\n\t\t\t\t\t\t\tEffect.provideService(Graft.Graft, graft),\n\t\t\t\t\t\t\tEffect.result,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (Result.isFailure(replacement))\n\t\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\t\treason: \"identity-conflict\",\n\t\t\t\t\t\t\t\tmodules: Array.filterMap(candidates, ({ url }, index) =>\n\t\t\t\t\t\t\t\t\tArray.contains(replacement.failure.indices, index)\n\t\t\t\t\t\t\t\t\t\t? Result.succeed(url)\n\t\t\t\t\t\t\t\t\t\t: Result.fail(undefined),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\tyield* Ref.update(owners, (owners) =>\n\t\t\t\t\t\t\tArray.reduce(candidates, owners, (owners, { url, leases }) =>\n\t\t\t\t\t\t\t\tHashMap.map(owners, (owner, token) =>\n\t\t\t\t\t\t\t\t\tHashSet.has(leases, token)\n\t\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\tactive: Option.map(owner.pending, (attempt) => ({\n\t\t\t\t\t\t\t\t\t\t\t\t\t...attempt,\n\t\t\t\t\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\t\t\t\t\tgeneration: candidate,\n\t\t\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t\t\t\tpending: Option.none(),\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t: owner,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tyield* Ref.set(state, { entries: next, generation: candidate })\n\t\t\t\t\t\tyield* Ref.set(\n\t\t\t\t\t\t\tcached,\n\t\t\t\t\t\t\tHashMap.map(next, (_, url) => ({ url, generation: candidate })),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tyield* Ref.set(retryDirty, HashSet.empty())\n\t\t\t\t\t\tyield* Ref.set(retryAll, false)\n\t\t\t\t\t\treturn WatchResult.Reloaded({\n\t\t\t\t\t\t\tentries: Array.map(candidates, (candidate) => candidate.url),\n\t\t\t\t\t\t})\n\t\t\t\t\t}).pipe(\n\t\t\t\t\t\tEffect.catchIf(\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t): error is HmrError & { readonly cause: RestartRequired } =>\n\t\t\t\t\t\t\t\tSchema.is(RestartRequired)(error.cause),\n\t\t\t\t\t\t\t(error) =>\n\t\t\t\t\t\t\t\tEffect.succeed(\n\t\t\t\t\t\t\t\t\tWatchResult.Skipped({\n\t\t\t\t\t\t\t\t\t\tmodules: Array.fromIterable(\n\t\t\t\t\t\t\t\t\t\t\tHashSet.add(\n\t\t\t\t\t\t\t\t\t\t\t\thooks.unsupported(candidate),\n\t\t\t\t\t\t\t\t\t\t\t\terror.cause.url,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tEffect.ensuring(Effect.sync(hooks.discard)),\n\t\t\t\t\t\tEffect.ensuring(collect),\n\t\t\t\t\t)\n\t\t\t\t}),\n\t\t\t)\n\t\treturn {\n\t\t\timporter,\n\t\t\timporterScoped,\n\t\t\treload: reloadChanged(),\n\t\t\twatch: (paths, watchOptions) =>\n\t\t\t\tpaths.length === 0\n\t\t\t\t\t? Stream.empty\n\t\t\t\t\t: changes(\n\t\t\t\t\t\t\t(use) =>\n\t\t\t\t\t\t\t\tRef.get(owners).pipe(\n\t\t\t\t\t\t\t\t\tEffect.map((owners) =>\n\t\t\t\t\t\t\t\t\t\thooks.files([\n\t\t\t\t\t\t\t\t\t\t\t...Array.getSomes(\n\t\t\t\t\t\t\t\t\t\t\t\tArray.map(\n\t\t\t\t\t\t\t\t\t\t\t\t\tHashMap.toValues(owners),\n\t\t\t\t\t\t\t\t\t\t\t\t\t(owner) => owner.active,\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t...Array.getSomes(\n\t\t\t\t\t\t\t\t\t\t\t\tArray.map(\n\t\t\t\t\t\t\t\t\t\t\t\t\tHashMap.toValues(owners),\n\t\t\t\t\t\t\t\t\t\t\t\t\t(owner) => owner.pending,\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tEffect.flatMap(use),\n\t\t\t\t\t\t\t\t\t// Only snapshot and validation callbacks run under the lock.\n\t\t\t\t\t\t\t\t\t// File reads operate on the retained immutable snapshot outside it.\n\t\t\t\t\t\t\t\t\tsemaphore.withPermits(1),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tpaths,\n\t\t\t\t\t\t\twatchOptions,\n\t\t\t\t\t\t).pipe(\n\t\t\t\t\t\t\tStream.mapEffect((dirty) =>\n\t\t\t\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t\t\t\tEffect.exit(reloadChanged(dirty)),\n\t\t\t\t\t\t\t\t\t(exit): WatchResult =>\n\t\t\t\t\t\t\t\t\t\tExit.isSuccess(exit)\n\t\t\t\t\t\t\t\t\t\t\t? exit.value\n\t\t\t\t\t\t\t\t\t\t\t: WatchResult.Failed({ cause: exit.cause }),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t// Native caches may hide both dependency edges and the first save.\n\t\t\t\t\t\t\t// Report known restart requirements independently of filesystem events.\n\t\t\t\t\t\t\tStream.merge(\n\t\t\t\t\t\t\t\tStream.tick(\"1 second\").pipe(\n\t\t\t\t\t\t\t\t\tStream.mapEffect(() =>\n\t\t\t\t\t\t\t\t\t\tunsupportedModules.pipe(semaphore.withPermits(1)),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tStream.changes,\n\t\t\t\t\t\t\t\t\tStream.filter((modules) => HashSet.size(modules) > 0),\n\t\t\t\t\t\t\t\t\tStream.map((modules) =>\n\t\t\t\t\t\t\t\t\t\tWatchResult.Skipped({\n\t\t\t\t\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\t\t\t\t\tmodules: Array.fromIterable(modules),\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t}\n\t})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Hot module replacement for Graft plugins on Node.js.\n */\n// @effect-diagnostics-next-line nodeBuiltinImport:off -- native import resolution must work without requiring a platform layer\nimport { realpath } from \"node:fs/promises\"\nimport { fileURLToPath, pathToFileURL } from \"node:url\"\nimport { Graft, Plugin } from \"@graftland/graft\"\nimport {\n\tArray,\n\tCause,\n\tData,\n\tDeferred,\n\tEffect,\n\tExit,\n\tFiberSet,\n\tFileSystem,\n\tHashMap,\n\tHashSet,\n\tOption,\n\tRef,\n\tResult,\n\tString,\n\tSchema,\n\tSemaphore,\n\tStream,\n\tScope,\n} from \"effect\"\nimport type { Duration, PlatformError } from \"effect\"\nimport { changes } from \"./internal/changes\"\nimport {\n\tisMissingEntry,\n\tmodules,\n\tRestartRequired,\n\ttype Attempt,\n} from \"./internal/modules\"\n\nexport class HmrError extends Schema.TaggedError<\n\tHmrError,\n\t{ readonly brand: unique symbol }\n>()(\"HmrError\", {\n\tstage: Schema.Literals([\"import\", \"exports\", \"closed\"]),\n\tspecifier: Schema.String,\n\tcause: Schema.Unknown,\n}) {\n\toverride get message(): string {\n\t\treturn `HMR ${this.stage} failed for ${this.specifier || \"the closed session\"}`\n\t}\n}\n\nexport type WatchResult = Data.TaggedEnum<{\n\tReloaded: { readonly entries: ReadonlyArray<string> }\n\tSkipped: {\n\t\treadonly modules: ReadonlyArray<string>\n\t\treadonly reason:\n\t\t\t\"restart-required\" | \"ambiguous-exports\" | \"identity-conflict\"\n\t}\n\tFailed: { readonly cause: Cause.Cause<HmrError> }\n}>\n\nexport const WatchResult = Data.taggedEnum<WatchResult>()\n\nexport type ReloadResult = Exclude<WatchResult, { readonly _tag: \"Failed\" }>\n\nexport interface Options {\n\t/** Application module URL, usually import.meta.url; used for bare and relative resolution. */\n\treadonly base: string\n\t/** Files to version. Defaults to file URLs outside node_modules. Entries are always included. */\n\treadonly include?: (url: string) => boolean\n}\n\nexport interface WatchOptions extends FileSystem.WatchOptions {\n\treadonly debounce?: Duration.Input\n\t/** Receives an absolute file path; applies to native events and reconciliation. */\n\treadonly filter?: (path: string) => boolean\n}\n\n/** Separates retry observations from an importer's temporary resource scope. */\nexport interface ImportOptions {\n\treadonly observationScope: Scope.Scope\n}\n\nexport interface Hmr {\n\t/** Keeps imported entries registered until this HMR session closes. */\n\treadonly importer: (specifier: string) => Promise<unknown>\n\t/** Uses the application context and Node cache, without watching or replacing the module. */\n\treadonly importModule: (specifier: string) => Effect.Effect<unknown, HmrError>\n\t/** Registers an observation lease in observationScope, or the caller's scope when omitted. */\n\treadonly importerScoped: (\n\t\tspecifier: string,\n\t\toptions?: ImportOptions,\n\t) => Effect.Effect<unknown, HmrError, Scope.Scope>\n\t/** Imports every entry before replacing anything. Activation failures belong to Graft. */\n\treadonly reload: Effect.Effect<ReloadResult, HmrError>\n\t/**\n\t * Consuming this stream installs graph-driven directory watchers, polls stat once\n\t * per second, and audits contents every ten seconds to recover missed events. Known native loading limitations emit\n\t * Skipped even without a file event. The consumer owns the stream's lifetimes.\n\t */\n\treadonly watch: (\n\t\tpaths: ReadonlyArray<string>,\n\t\toptions?: WatchOptions,\n\t) => Stream.Stream<\n\t\tWatchResult,\n\t\tPlatformError.PlatformError,\n\t\tFileSystem.FileSystem\n\t>\n}\n\n/**\n * Installs Node module hooks until the enclosing scope closes. Module evaluation\n * must be side-effect free. Versioned ESM cache entries are not reclaimed.\n */\nexport const make = (\n\toptions: Options,\n): Effect.Effect<Hmr, never, Graft.Graft | Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst graft = yield* Graft.Graft\n\t\tconst semaphore = yield* Semaphore.make(1)\n\t\t// A lease owns both the running graph and its latest uncommitted attempt.\n\t\tconst owners = yield* Ref.make(\n\t\t\tHashMap.empty<\n\t\t\t\tsymbol,\n\t\t\t\t{\n\t\t\t\t\treadonly active: Option.Option<Attempt>\n\t\t\t\t\treadonly pending: Option.Option<Attempt>\n\t\t\t\t}\n\t\t\t>(),\n\t\t)\n\t\tconst closed = yield* Ref.make(false)\n\t\tconst session = yield* Effect.scope\n\t\t// Transfer the complete Exit before restoring interruption. Effect may replace\n\t\t// a failed masked operation with pending interruption at that boundary.\n\t\tconst preserveExit = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst completed = yield* Deferred.make<Exit.Exit<A, E>>()\n\t\t\t\treturn yield* effect.pipe(\n\t\t\t\t\tEffect.exit,\n\t\t\t\t\tEffect.tap((exit) => Deferred.succeed(completed, exit)),\n\t\t\t\t\tEffect.uninterruptible,\n\t\t\t\t\tEffect.flatten,\n\t\t\t\t\tEffect.onExit((exit) =>\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\tif (Exit.isSuccess(exit) || !Cause.hasInterrupts(exit.cause))\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\tconst saved = yield* Deferred.poll(completed)\n\t\t\t\t\t\t\tif (Option.isNone(saved)) return\n\t\t\t\t\t\t\tconst original = yield* saved.value\n\t\t\t\t\t\t\tif (Exit.isFailure(original))\n\t\t\t\t\t\t\t\tyield* Effect.logError(\n\t\t\t\t\t\t\t\t\t\"HMR operation failed during cancellation\",\n\t\t\t\t\t\t\t\t\toriginal.cause,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t})\n\t\t// Native imports cannot be cancelled: keep the lock until their promises settle.\n\t\tconst serial = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n\t\t\teffect.pipe(preserveExit, semaphore.withPermits(1))\n\t\tconst hooks = yield* Effect.acquireRelease(\n\t\t\tEffect.sync(() =>\n\t\t\t\tmodules(\n\t\t\t\t\toptions.base,\n\t\t\t\t\toptions.include ??\n\t\t\t\t\t\t((url) =>\n\t\t\t\t\t\t\t!String.includes(\"/node_modules/\")(new URL(url).pathname)),\n\t\t\t\t),\n\t\t\t),\n\t\t\t(hooks) =>\n\t\t\t\tserial(\n\t\t\t\t\tRef.set(closed, true).pipe(Effect.andThen(Effect.sync(hooks.close))),\n\t\t\t\t),\n\t\t)\n\t\t// Node can return a cached entry after its last observation lease closes.\n\t\t// Keep current entry attempts without polling or reloading unleased entries.\n\t\t// The hooks also retain cached instance facts for older resolution views.\n\t\tconst cached = yield* Ref.make(HashMap.empty<string, Attempt>())\n\n\t\tconst retryDirty = yield* Ref.make(HashSet.empty<string>())\n\t\tconst retryAll = yield* Ref.make(false)\n\t\tconst observations = Ref.get(owners).pipe(\n\t\t\tEffect.map((owners) =>\n\t\t\t\tArray.flatMap(HashMap.toValues(owners), (owner) =>\n\t\t\t\t\tArray.getSomes([owner.active, owner.pending]),\n\t\t\t\t),\n\t\t\t),\n\t\t)\n\t\tconst collect = Effect.gen(function* () {\n\t\t\tconst attempts = yield* observations\n\t\t\tconst currentCache = yield* Ref.get(cached)\n\t\t\thooks.collect([...attempts, ...HashMap.toValues(currentCache)])\n\t\t\tconst files = hooks.files(attempts)\n\t\t\tyield* Ref.update(\n\t\t\t\tretryDirty,\n\t\t\t\tHashSet.filter((url) => HashMap.has(files, url)),\n\t\t\t)\n\t\t\tif (attempts.length === 0) yield* Ref.set(retryAll, false)\n\t\t})\n\n\t\tconst state = yield* Ref.make({\n\t\t\tgeneration: hooks.prepare(),\n\t\t\tentries: HashMap.empty<\n\t\t\t\tstring,\n\t\t\t\t{\n\t\t\t\t\treadonly plugin: Plugin.Plugin\n\t\t\t\t\treadonly leases: HashSet.HashSet<symbol>\n\t\t\t\t}\n\t\t\t>(),\n\t\t})\n\t\t// Stop Promise-backed operations before releasing their leases. Otherwise\n\t\t// a lease finalizer could wait on an import before its owner interrupts it.\n\t\tconst imports = yield* Scope.fork(session)\n\t\tconst run = yield* FiberSet.makeRuntimePromise<never, unknown, HmrError>()\n\t\tconst closedError = () =>\n\t\t\tHmrError.make({\n\t\t\t\tstage: \"closed\",\n\t\t\t\tspecifier: \"\",\n\t\t\t\tcause: \"HMR scope is closed\",\n\t\t\t})\n\t\tconst checkOpen = Ref.get(closed).pipe(\n\t\t\tEffect.flatMap((closed) =>\n\t\t\t\tclosed ? Effect.fail(closedError()) : Effect.void,\n\t\t\t),\n\t\t)\n\t\tconst physicalTarget = (request: string) =>\n\t\t\tEffect.tryPromise({\n\t\t\t\ttry: () => realpath(fileURLToPath(request)),\n\t\t\t\tcatch: (cause) =>\n\t\t\t\t\tHmrError.make({ stage: \"import\", specifier: request, cause }),\n\t\t\t}).pipe(\n\t\t\t\tEffect.map((path) => pathToFileURL(path).href),\n\t\t\t\tEffect.catchIf(\n\t\t\t\t\t(error) => isMissingEntry(request, error.cause),\n\t\t\t\t\t() => Effect.undefined,\n\t\t\t\t),\n\t\t\t)\n\t\tconst changedResolution = Effect.fnUntraced(function* (\n\t\t\tattempt: Pick<Attempt, \"url\" | \"request\">,\n\t\t) {\n\t\t\tif (attempt.request === undefined) return Option.none<string>()\n\t\t\tconst request = attempt.request\n\t\t\tconst expected = pathToFileURL(fileURLToPath(attempt.url)).href\n\t\t\tconst actual = yield* physicalTarget(request)\n\t\t\tif (actual === expected) return Option.none<string>()\n\t\t\t// If both paths disappeared, this is ordinary entry deletion. A\n\t\t\t// missing link with a surviving old target must never reload that target.\n\t\t\tif (actual === undefined) {\n\t\t\t\tconst remaining = yield* physicalTarget(attempt.url)\n\t\t\t\tif (remaining === undefined) return Option.none<string>()\n\t\t\t}\n\t\t\treturn Option.some(request)\n\t\t})\n\n\t\tconst changedResolutions = Effect.gen(function* () {\n\t\t\tconst current = yield* Ref.get(owners)\n\t\t\tconst attempts = hooks.resolutions(\n\t\t\t\tArray.flatMap(HashMap.toValues(current), (owner) =>\n\t\t\t\t\tArray.getSomes([owner.active, owner.pending]),\n\t\t\t\t),\n\t\t\t)\n\t\t\tconst requests = HashSet.fromIterable(\n\t\t\t\tArray.filterMap(attempts, (attempt) =>\n\t\t\t\t\tattempt.request === undefined\n\t\t\t\t\t\t? Result.fail(undefined)\n\t\t\t\t\t\t: Result.succeed(attempt.request),\n\t\t\t\t),\n\t\t\t)\n\t\t\tconst resolveAll = (requests: HashSet.HashSet<string>) =>\n\t\t\t\tEffect.forEach(\n\t\t\t\t\trequests,\n\t\t\t\t\t(request) =>\n\t\t\t\t\t\tphysicalTarget(request).pipe(\n\t\t\t\t\t\t\tEffect.map((target) => [request, target] as const),\n\t\t\t\t\t\t),\n\t\t\t\t\t{ concurrency: 8 },\n\t\t\t\t).pipe(Effect.map(HashMap.fromIterable))\n\t\t\tconst actual = yield* resolveAll(requests)\n\t\t\tconst missingTargets = HashSet.fromIterable(\n\t\t\t\tArray.filterMap(attempts, (attempt) =>\n\t\t\t\t\tattempt.request !== undefined &&\n\t\t\t\t\tOption.getOrUndefined(HashMap.get(actual, attempt.request)) ===\n\t\t\t\t\t\tundefined &&\n\t\t\t\t\t!HashMap.has(actual, attempt.url)\n\t\t\t\t\t\t? Result.succeed(attempt.url)\n\t\t\t\t\t\t: Result.fail(undefined),\n\t\t\t\t),\n\t\t\t)\n\t\t\tconst remaining = yield* resolveAll(missingTargets)\n\t\t\tconst targets = HashMap.union(actual, remaining)\n\n\t\t\treturn Array.fromIterable(\n\t\t\t\tHashSet.fromIterable(\n\t\t\t\t\tArray.filterMap(attempts, (attempt) => {\n\t\t\t\t\t\tif (attempt.request === undefined) return Result.fail(undefined)\n\t\t\t\t\t\tconst actual = Option.getOrUndefined(\n\t\t\t\t\t\t\tHashMap.get(targets, attempt.request),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst expected = pathToFileURL(fileURLToPath(attempt.url)).href\n\t\t\t\t\t\treturn actual === expected ||\n\t\t\t\t\t\t\t(actual === undefined &&\n\t\t\t\t\t\t\t\tOption.getOrUndefined(HashMap.get(targets, attempt.url)) ===\n\t\t\t\t\t\t\t\t\tundefined)\n\t\t\t\t\t\t\t? Result.fail(undefined)\n\t\t\t\t\t\t\t: Result.succeed(attempt.request)\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t)\n\t\t})\n\n\t\tconst load = Effect.fnUntraced(function* (specifier: string) {\n\t\t\tconst namespace = yield* Effect.tryPromise({\n\t\t\t\ttry: () => import(/* @vite-ignore */ hooks.request(specifier)),\n\t\t\t\tcatch: (cause) => HmrError.make({ stage: \"import\", specifier, cause }),\n\t\t\t})\n\t\t\tconst plugin = Plugin.fromModule(namespace)\n\t\t\tif (Option.isNone(plugin))\n\t\t\t\treturn yield* HmrError.make({\n\t\t\t\t\tstage: \"exports\",\n\t\t\t\t\tspecifier,\n\t\t\t\t\tcause: \"Expected a default or named plugin export\",\n\t\t\t\t})\n\t\t\tconst url = yield* Effect.fromOption(hooks.resolved()).pipe(\n\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\tHmrError.make({ stage: \"import\", specifier, cause }),\n\t\t\t\t),\n\t\t\t)\n\t\t\tconst request = hooks.fileRequest(specifier)\n\t\t\tconst attempt = {\n\t\t\t\turl,\n\t\t\t\t...Option.match(request, {\n\t\t\t\t\tonNone: () => ({}),\n\t\t\t\t\tonSome: (request) => ({ request }),\n\t\t\t\t}),\n\t\t\t}\n\t\t\tconst changed = yield* changedResolution(attempt)\n\t\t\tif (Option.isSome(changed))\n\t\t\t\treturn yield* HmrError.make({\n\t\t\t\t\tstage: \"import\",\n\t\t\t\t\tspecifier,\n\t\t\t\t\tcause: RestartRequired.make({ url: changed.value }),\n\t\t\t\t})\n\t\t\treturn { namespace, plugin: plugin.value, url }\n\t\t})\n\t\tconst importWithLease = (specifier: string) =>\n\t\t\tEffect.acquireRelease(\n\t\t\t\tserial(\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tyield* checkOpen\n\t\t\t\t\t\tconst current = yield* Ref.get(state)\n\t\t\t\t\t\thooks.start(current.generation)\n\t\t\t\t\t\t// Acquire an owner for either Exit. Rethrow only after its finalizer\n\t\t\t\t\t\t// is registered, so failed imports remain available for scoped retry.\n\t\t\t\t\t\tconst exit = yield* Effect.exit(load(specifier))\n\t\t\t\t\t\tconst token: symbol = Symbol()\n\t\t\t\t\t\tconst root = Option.orElse(hooks.resolved(), () =>\n\t\t\t\t\t\t\tString.startsWith(\"file:\")(specifier)\n\t\t\t\t\t\t\t\t? Option.some(specifier)\n\t\t\t\t\t\t\t\t: Option.none(),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst attempt = Option.map(root, (url) => ({\n\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\tgeneration: current.generation,\n\t\t\t\t\t\t\t...Option.match(hooks.fileRequest(specifier), {\n\t\t\t\t\t\t\t\tonNone: () => ({}),\n\t\t\t\t\t\t\t\tonSome: (request) => ({ request }),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t}))\n\t\t\t\t\t\tif (Option.isSome(attempt))\n\t\t\t\t\t\t\tyield* Ref.update(\n\t\t\t\t\t\t\t\tcached,\n\t\t\t\t\t\t\t\tHashMap.set(attempt.value.url, attempt.value),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\tyield* Ref.update(\n\t\t\t\t\t\t\towners,\n\t\t\t\t\t\t\tHashMap.set(token, {\n\t\t\t\t\t\t\t\tactive: Exit.isSuccess(exit) ? attempt : Option.none(),\n\t\t\t\t\t\t\t\tpending: Exit.isFailure(exit) ? attempt : Option.none(),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (Exit.isSuccess(exit)) {\n\t\t\t\t\t\t\tconst entry = exit.value\n\t\t\t\t\t\t\tconst previous = HashMap.get(current.entries, entry.url)\n\t\t\t\t\t\t\tconst leases = Option.match(previous, {\n\t\t\t\t\t\t\t\tonNone: () => HashSet.empty<symbol>(),\n\t\t\t\t\t\t\t\tonSome: (entry) => entry.leases,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tyield* Ref.set(state, {\n\t\t\t\t\t\t\t\t...current,\n\t\t\t\t\t\t\t\tentries: HashMap.set(current.entries, entry.url, {\n\t\t\t\t\t\t\t\t\tplugin: entry.plugin,\n\t\t\t\t\t\t\t\t\tleases: HashSet.add(leases, token),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn { token, exit: Exit.map(exit, (entry) => entry.namespace) }\n\t\t\t\t\t}).pipe(\n\t\t\t\t\t\tEffect.ensuring(Effect.sync(hooks.discard)),\n\t\t\t\t\t\tEffect.ensuring(collect),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\t({ token }) =>\n\t\t\t\t\tserial(\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\tyield* Ref.update(owners, HashMap.remove(token))\n\t\t\t\t\t\t\tyield* Ref.update(state, (current) => ({\n\t\t\t\t\t\t\t\t...current,\n\t\t\t\t\t\t\t\tentries: HashMap.filterMap(current.entries, (entry) => {\n\t\t\t\t\t\t\t\t\tconst leases = HashSet.remove(entry.leases, token)\n\t\t\t\t\t\t\t\t\treturn HashSet.size(leases) === 0\n\t\t\t\t\t\t\t\t\t\t? Result.fail(undefined)\n\t\t\t\t\t\t\t\t\t\t: Result.succeed({ ...entry, leases })\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t}).pipe(Effect.ensuring(collect)),\n\t\t\t\t\t),\n\t\t\t).pipe(\n\t\t\t\tEffect.flatMap(({ exit }) => exit),\n\t\t\t\tpreserveExit,\n\t\t\t)\n\n\t\tconst importModule: Hmr[\"importModule\"] = (specifier) =>\n\t\t\tserial(\n\t\t\t\tcheckOpen.pipe(\n\t\t\t\t\tEffect.andThen(\n\t\t\t\t\t\tEffect.tryPromise({\n\t\t\t\t\t\t\ttry: () => import(/* @vite-ignore */ hooks.rawRequest(specifier)),\n\t\t\t\t\t\t\tcatch: (cause) =>\n\t\t\t\t\t\t\t\tHmrError.make({ stage: \"import\", specifier, cause }),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\n\t\tconst importerScoped: Hmr[\"importerScoped\"] = (specifier, options) =>\n\t\t\toptions === undefined\n\t\t\t\t? importWithLease(specifier)\n\t\t\t\t: importWithLease(specifier).pipe(\n\t\t\t\t\t\tScope.provide(options.observationScope),\n\t\t\t\t\t)\n\n\t\tconst importer = (specifier: string): Promise<unknown> =>\n\t\t\t// A closed FiberSet interrupts new work before checkOpen can execute.\n\t\t\tRef.getUnsafe(closed)\n\t\t\t\t? Promise.reject(closedError())\n\t\t\t\t: run(\n\t\t\t\t\t\timporterScoped(specifier).pipe(\n\t\t\t\t\t\t\tEffect.provideService(Scope.Scope, imports),\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\n\t\tconst unsupportedAttempts = (attempts: ReadonlyArray<Attempt>) =>\n\t\t\tArray.reduce(attempts, HashSet.empty<string>(), (all, attempt) =>\n\t\t\t\tHashSet.union(\n\t\t\t\t\tall,\n\t\t\t\t\thooks.unsupported(attempt.generation, [attempt.url]),\n\t\t\t\t),\n\t\t\t)\n\t\tconst unsupportedModules = Ref.get(owners).pipe(\n\t\t\tEffect.map((owned) =>\n\t\t\t\tunsupportedAttempts(\n\t\t\t\t\tArray.getSomes(\n\t\t\t\t\t\tArray.map(HashMap.toValues(owned), (owner) => owner.active),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t)\n\n\t\tconst reloadChanged = (dirty?: HashSet.HashSet<string>) =>\n\t\t\tserial(\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tyield* checkOpen\n\t\t\t\t\tconst fullRetry = yield* Ref.get(retryAll)\n\t\t\t\t\tconst force = dirty === undefined || fullRetry\n\t\t\t\t\tconst pendingDirty = yield* Ref.get(retryDirty)\n\t\t\t\t\tconst changedFiles =\n\t\t\t\t\t\tdirty === undefined\n\t\t\t\t\t\t\t? pendingDirty\n\t\t\t\t\t\t\t: HashSet.union(pendingDirty, dirty)\n\t\t\t\t\tyield* Ref.set(retryDirty, changedFiles)\n\t\t\t\t\tyield* Ref.set(retryAll, force)\n\t\t\t\t\tconst changed = yield* changedResolutions\n\t\t\t\t\tif (changed.length > 0)\n\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\tmodules: changed,\n\t\t\t\t\t\t})\n\t\t\t\t\tconst { entries } = yield* Ref.get(state)\n\t\t\t\t\tconst unsupported = yield* unsupportedModules\n\t\t\t\t\tif (HashSet.size(unsupported) > 0)\n\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\tmodules: Array.fromIterable(unsupported),\n\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t})\n\t\t\t\t\tconst owned = yield* Ref.get(owners)\n\t\t\t\t\tconst attempts = Array.flatMap(HashMap.toValues(owned), (owner) =>\n\t\t\t\t\t\tArray.getSomes([owner.active, owner.pending]),\n\t\t\t\t\t)\n\t\t\t\t\tconst active = Array.getSomes(\n\t\t\t\t\t\tArray.map(HashMap.toValues(owned), (owner) => owner.active),\n\t\t\t\t\t)\n\t\t\t\t\tlet selected = entries\n\t\t\t\t\tlet invalid = HashSet.empty<string>()\n\t\t\t\t\tif (!force) {\n\t\t\t\t\t\tlet affected = changedFiles\n\t\t\t\t\t\t// Plugin identity groups and importer closure can expand each other.\n\t\t\t\t\t\t// Reach a fixed point before allocating any candidate instance.\n\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\tinvalid = hooks.invalidated(attempts, affected)\n\t\t\t\t\t\t\tconst plugins = HashSet.fromIterable(\n\t\t\t\t\t\t\t\tArray.filterMap(Array.fromIterable(entries), ([url, entry]) =>\n\t\t\t\t\t\t\t\t\tHashSet.has(affected, url) ||\n\t\t\t\t\t\t\t\t\tArray.some(Array.fromIterable(entry.leases), (token) =>\n\t\t\t\t\t\t\t\t\t\tOption.exists(HashMap.get(owned, token), (owner) =>\n\t\t\t\t\t\t\t\t\t\t\tArray.some(\n\t\t\t\t\t\t\t\t\t\t\t\tArray.getSomes([owner.active, owner.pending]),\n\t\t\t\t\t\t\t\t\t\t\t\t(attempt) => hooks.affected(attempt, invalid),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t? Result.succeed(entry.plugin)\n\t\t\t\t\t\t\t\t\t\t: Result.fail(undefined),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tselected = HashMap.filter(entries, (entry) =>\n\t\t\t\t\t\t\t\tHashSet.has(plugins, entry.plugin),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tconst expanded = HashSet.union(\n\t\t\t\t\t\t\t\taffected,\n\t\t\t\t\t\t\t\tHashSet.fromIterable(HashMap.keys(selected)),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tif (HashSet.size(expanded) === HashSet.size(affected)) break\n\t\t\t\t\t\t\taffected = expanded\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Advance even without entries so retries bypass cached failed imports.\n\t\t\t\t\tconst candidate = force\n\t\t\t\t\t\t? hooks.prepare()\n\t\t\t\t\t\t: hooks.prepare(active, invalid)\n\n\t\t\t\t\thooks.start(candidate, true)\n\t\t\t\t\treturn yield* Effect.gen(function* () {\n\t\t\t\t\t\tconst loaded = yield* Effect.forEach(selected, ([url, previous]) =>\n\t\t\t\t\t\t\tRef.update(\n\t\t\t\t\t\t\t\towners,\n\t\t\t\t\t\t\t\tHashMap.map((owner, token) =>\n\t\t\t\t\t\t\t\t\tHashSet.has(previous.leases, token)\n\t\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\t...owner,\n\t\t\t\t\t\t\t\t\t\t\t\tpending: Option.map(owner.active, (attempt) => ({\n\t\t\t\t\t\t\t\t\t\t\t\t\t...attempt,\n\t\t\t\t\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\t\t\t\t\tgeneration: candidate,\n\t\t\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t: owner,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t).pipe(\n\t\t\t\t\t\t\t\tEffect.andThen(load(url)),\n\t\t\t\t\t\t\t\tEffect.map((entry) =>\n\t\t\t\t\t\t\t\t\tOption.some({\n\t\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\t\tprevious: previous.plugin,\n\t\t\t\t\t\t\t\t\t\tleases: previous.leases,\n\t\t\t\t\t\t\t\t\t\tplugin: entry.plugin,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tEffect.catchIf(\n\t\t\t\t\t\t\t\t\t(error) =>\n\t\t\t\t\t\t\t\t\t\terror.stage === \"import\" &&\n\t\t\t\t\t\t\t\t\t\tisMissingEntry(url, error.cause),\n\t\t\t\t\t\t\t\t\t() => Effect.succeedNone,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst candidates = Array.getSomes(loaded)\n\t\t\t\t\t\tconst alternatives = Array.reduce(\n\t\t\t\t\t\t\tcandidates,\n\t\t\t\t\t\t\tHashMap.empty<Plugin.Plugin, HashSet.HashSet<Plugin.Plugin>>(),\n\t\t\t\t\t\t\t(groups, { previous, plugin }) =>\n\t\t\t\t\t\t\t\tHashMap.set(\n\t\t\t\t\t\t\t\t\tgroups,\n\t\t\t\t\t\t\t\t\tprevious,\n\t\t\t\t\t\t\t\t\tHashSet.add(\n\t\t\t\t\t\t\t\t\t\tOption.getOrElse(\n\t\t\t\t\t\t\t\t\t\t\tHashMap.get(groups, previous),\n\t\t\t\t\t\t\t\t\t\t\tHashSet.empty<Plugin.Plugin>,\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\tplugin,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst ambiguous = Array.filter(candidates, ({ previous }) =>\n\t\t\t\t\t\t\tOption.exists(\n\t\t\t\t\t\t\t\tHashMap.get(alternatives, previous),\n\t\t\t\t\t\t\t\t(plugins) => HashSet.size(plugins) > 1,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (ambiguous.length > 0)\n\t\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\t\treason: \"ambiguous-exports\",\n\t\t\t\t\t\t\t\tmodules: Array.map(ambiguous, ({ url }) => url),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\tconst replacements = HashMap.fromIterable(\n\t\t\t\t\t\t\tArray.map(\n\t\t\t\t\t\t\t\tcandidates,\n\t\t\t\t\t\t\t\t({ url, plugin, leases }) => [url, { plugin, leases }] as const,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t// A missing entry still owns its running plugin until the last lease closes.\n\t\t\t\t\t\tconst next = HashMap.union(entries, replacements)\n\n\t\t\t\t\t\tconst pairs = Array.map(\n\t\t\t\t\t\t\tcandidates,\n\t\t\t\t\t\t\t({ previous, plugin }) => [previous, plugin] as const,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst changed = yield* changedResolutions\n\t\t\t\t\t\tif (changed.length > 0)\n\t\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\t\tmodules: changed,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t// A reused instance can acquire a native loading capability while the\n\t\t\t\t\t\t// candidate imports. Observe it without throwing into concurrent old code.\n\t\t\t\t\t\tconst unsafe = unsupportedAttempts(\n\t\t\t\t\t\t\tArray.map(active, (attempt) =>\n\t\t\t\t\t\t\t\tHashMap.has(replacements, attempt.url)\n\t\t\t\t\t\t\t\t\t? { ...attempt, generation: candidate }\n\t\t\t\t\t\t\t\t\t: attempt,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (HashSet.size(unsafe) > 0)\n\t\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\t\tmodules: Array.fromIterable(unsafe),\n\t\t\t\t\t\t\t})\n\n\t\t\t\t\t\tconst replacement = yield* Graft.replace(pairs).pipe(\n\t\t\t\t\t\t\tEffect.provideService(Graft.Graft, graft),\n\t\t\t\t\t\t\tEffect.result,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (Result.isFailure(replacement))\n\t\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\t\treason: \"identity-conflict\",\n\t\t\t\t\t\t\t\tmodules: Array.filterMap(candidates, ({ url }, index) =>\n\t\t\t\t\t\t\t\t\tArray.contains(replacement.failure.indices, index)\n\t\t\t\t\t\t\t\t\t\t? Result.succeed(url)\n\t\t\t\t\t\t\t\t\t\t: Result.fail(undefined),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\tyield* Ref.update(owners, (owners) =>\n\t\t\t\t\t\t\tArray.reduce(candidates, owners, (owners, { url, leases }) =>\n\t\t\t\t\t\t\t\tHashMap.map(owners, (owner, token) =>\n\t\t\t\t\t\t\t\t\tHashSet.has(leases, token)\n\t\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\tactive: Option.map(owner.pending, (attempt) => ({\n\t\t\t\t\t\t\t\t\t\t\t\t\t...attempt,\n\t\t\t\t\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\t\t\t\t\tgeneration: candidate,\n\t\t\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t\t\t\tpending: Option.none(),\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t: owner,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tyield* Ref.set(state, { entries: next, generation: candidate })\n\t\t\t\t\t\tyield* Ref.update(cached, (cached) =>\n\t\t\t\t\t\t\tHashMap.union(\n\t\t\t\t\t\t\t\tHashMap.filter(cached, (_, url) => HashMap.has(next, url)),\n\t\t\t\t\t\t\t\tHashMap.map(replacements, (_, url) => ({\n\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\tgeneration: candidate,\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tyield* Ref.set(retryDirty, HashSet.empty())\n\t\t\t\t\t\tyield* Ref.set(retryAll, false)\n\t\t\t\t\t\treturn WatchResult.Reloaded({\n\t\t\t\t\t\t\tentries: Array.map(candidates, (candidate) => candidate.url),\n\t\t\t\t\t\t})\n\t\t\t\t\t}).pipe(\n\t\t\t\t\t\tEffect.catchIf(\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t): error is HmrError & { readonly cause: RestartRequired } =>\n\t\t\t\t\t\t\t\tSchema.is(RestartRequired)(error.cause),\n\t\t\t\t\t\t\t(error) =>\n\t\t\t\t\t\t\t\tEffect.succeed(\n\t\t\t\t\t\t\t\t\tWatchResult.Skipped({\n\t\t\t\t\t\t\t\t\t\tmodules: Array.fromIterable(\n\t\t\t\t\t\t\t\t\t\t\tHashSet.add(\n\t\t\t\t\t\t\t\t\t\t\t\thooks.unsupported(candidate),\n\t\t\t\t\t\t\t\t\t\t\t\terror.cause.url,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tEffect.ensuring(Effect.sync(hooks.discard)),\n\t\t\t\t\t\tEffect.ensuring(collect),\n\t\t\t\t\t)\n\t\t\t\t}),\n\t\t\t)\n\t\treturn {\n\t\t\timporter,\n\t\t\timporterScoped,\n\t\t\timportModule,\n\t\t\treload: reloadChanged(),\n\t\t\twatch: (paths, watchOptions) =>\n\t\t\t\tpaths.length === 0\n\t\t\t\t\t? Stream.empty\n\t\t\t\t\t: changes(\n\t\t\t\t\t\t\t(use) =>\n\t\t\t\t\t\t\t\tRef.get(owners).pipe(\n\t\t\t\t\t\t\t\t\tEffect.map((owners) =>\n\t\t\t\t\t\t\t\t\t\thooks.files([\n\t\t\t\t\t\t\t\t\t\t\t...Array.getSomes(\n\t\t\t\t\t\t\t\t\t\t\t\tArray.map(\n\t\t\t\t\t\t\t\t\t\t\t\t\tHashMap.toValues(owners),\n\t\t\t\t\t\t\t\t\t\t\t\t\t(owner) => owner.active,\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t...Array.getSomes(\n\t\t\t\t\t\t\t\t\t\t\t\tArray.map(\n\t\t\t\t\t\t\t\t\t\t\t\t\tHashMap.toValues(owners),\n\t\t\t\t\t\t\t\t\t\t\t\t\t(owner) => owner.pending,\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tEffect.flatMap(use),\n\t\t\t\t\t\t\t\t\t// Only snapshot and validation callbacks run under the lock.\n\t\t\t\t\t\t\t\t\t// File reads operate on the retained immutable snapshot outside it.\n\t\t\t\t\t\t\t\t\tsemaphore.withPermits(1),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tpaths,\n\t\t\t\t\t\t\twatchOptions,\n\t\t\t\t\t\t).pipe(\n\t\t\t\t\t\t\tStream.mapEffect((dirty) =>\n\t\t\t\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t\t\t\tEffect.exit(reloadChanged(dirty)),\n\t\t\t\t\t\t\t\t\t(exit): WatchResult =>\n\t\t\t\t\t\t\t\t\t\tExit.isSuccess(exit)\n\t\t\t\t\t\t\t\t\t\t\t? exit.value\n\t\t\t\t\t\t\t\t\t\t\t: WatchResult.Failed({ cause: exit.cause }),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t// Native caches may hide both dependency edges and the first save.\n\t\t\t\t\t\t\t// Report known restart requirements independently of filesystem events.\n\t\t\t\t\t\t\tStream.merge(\n\t\t\t\t\t\t\t\tStream.tick(\"1 second\").pipe(\n\t\t\t\t\t\t\t\t\tStream.mapEffect(() =>\n\t\t\t\t\t\t\t\t\t\tunsupportedModules.pipe(semaphore.withPermits(1)),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tStream.changes,\n\t\t\t\t\t\t\t\t\tStream.filter((modules) => HashSet.size(modules) > 0),\n\t\t\t\t\t\t\t\t\tStream.map((modules) =>\n\t\t\t\t\t\t\t\t\t\tWatchResult.Skipped({\n\t\t\t\t\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\t\t\t\t\tmodules: Array.fromIterable(modules),\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t}\n\t})\n"],"mappings":";;;;;;;;;;AAoCA,IAAa,WAAb,cAA8B,OAAO,YAGnC,CAAC,CAAC,YAAY;CACf,OAAO,OAAO,SAAS;EAAC;EAAU;EAAW;CAAQ,CAAC;CACtD,WAAW,OAAO;CAClB,OAAO,OAAO;AACf,CAAC,CAAC,CAAC;CACF,IAAa,UAAkB;EAC9B,OAAO,OAAO,KAAK,MAAM,cAAc,KAAK,aAAa;CAC1D;AACD;AAYA,MAAa,cAAc,KAAK,WAAwB;;;;;AAqDxD,MAAa,QACZ,YAEA,OAAO,IAAI,aAAa;CACvB,MAAM,QAAQ,OAAO,MAAM;CAC3B,MAAM,YAAY,OAAO,UAAU,KAAK,CAAC;CAEzC,MAAM,SAAS,OAAO,IAAI,KACzB,QAAQ,MAMN,CACH;CACA,MAAM,SAAS,OAAO,IAAI,KAAK,KAAK;CACpC,MAAM,UAAU,OAAO,OAAO;CAG9B,MAAM,gBAAyB,WAC9B,OAAO,IAAI,aAAa;EACvB,MAAM,YAAY,OAAO,SAAS,KAAsB;EACxD,OAAO,OAAO,OAAO,KACpB,OAAO,MACP,OAAO,KAAK,SAAS,SAAS,QAAQ,WAAW,IAAI,CAAC,GACtD,OAAO,iBACP,OAAO,SACP,OAAO,QAAQ,SACd,OAAO,IAAI,aAAa;GACvB,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,cAAc,KAAK,KAAK,GAC1D;GACD,MAAM,QAAQ,OAAO,SAAS,KAAK,SAAS;GAC5C,IAAI,OAAO,OAAO,KAAK,GAAG;GAC1B,MAAM,WAAW,OAAO,MAAM;GAC9B,IAAI,KAAK,UAAU,QAAQ,GAC1B,OAAO,OAAO,SACb,4CACA,SAAS,KACV;EACF,CAAC,CACF,CACD;CACD,CAAC;CAEF,MAAM,UAAmB,WACxB,OAAO,KAAK,cAAc,UAAU,YAAY,CAAC,CAAC;CACnD,MAAM,QAAQ,OAAO,OAAO,eAC3B,OAAO,WACN,QACC,QAAQ,MACR,QAAQ,aACL,QACD,CAAC,OAAO,SAAS,gBAAgB,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,QAAQ,EAC3D,CACD,IACC,UACA,OACC,IAAI,IAAI,QAAQ,IAAI,CAAC,CAAC,KAAK,OAAO,QAAQ,OAAO,KAAK,MAAM,KAAK,CAAC,CAAC,CACpE,CACF;CAIA,MAAM,SAAS,OAAO,IAAI,KAAK,QAAQ,MAAuB,CAAC;CAE/D,MAAM,aAAa,OAAO,IAAI,KAAK,QAAQ,MAAc,CAAC;CAC1D,MAAM,WAAW,OAAO,IAAI,KAAK,KAAK;CACtC,MAAM,eAAe,IAAI,IAAI,MAAM,CAAC,CAAC,KACpC,OAAO,KAAK,WACX,MAAM,QAAQ,QAAQ,SAAS,MAAM,IAAI,UACxC,MAAM,SAAS,CAAC,MAAM,QAAQ,MAAM,OAAO,CAAC,CAC7C,CACD,CACD;CACA,MAAM,UAAU,OAAO,IAAI,aAAa;EACvC,MAAM,WAAW,OAAO;EACxB,MAAM,eAAe,OAAO,IAAI,IAAI,MAAM;EAC1C,MAAM,QAAQ,CAAC,GAAG,UAAU,GAAG,QAAQ,SAAS,YAAY,CAAC,CAAC;EAC9D,MAAM,QAAQ,MAAM,MAAM,QAAQ;EAClC,OAAO,IAAI,OACV,YACA,QAAQ,QAAQ,QAAQ,QAAQ,IAAI,OAAO,GAAG,CAAC,CAChD;EACA,IAAI,SAAS,WAAW,GAAG,OAAO,IAAI,IAAI,UAAU,KAAK;CAC1D,CAAC;CAED,MAAM,QAAQ,OAAO,IAAI,KAAK;EAC7B,YAAY,MAAM,QAAQ;EAC1B,SAAS,QAAQ,MAMf;CACH,CAAC;CAGD,MAAM,UAAU,OAAO,MAAM,KAAK,OAAO;CACzC,MAAM,MAAM,OAAO,SAAS,mBAA6C;CACzE,MAAM,oBACL,SAAS,KAAK;EACb,OAAO;EACP,WAAW;EACX,OAAO;CACR,CAAC;CACF,MAAM,YAAY,IAAI,IAAI,MAAM,CAAC,CAAC,KACjC,OAAO,SAAS,WACf,SAAS,OAAO,KAAK,YAAY,CAAC,IAAI,OAAO,IAC9C,CACD;CACA,MAAM,kBAAkB,YACvB,OAAO,WAAW;EACjB,WAAW,SAAS,cAAc,OAAO,CAAC;EAC1C,QAAQ,UACP,SAAS,KAAK;GAAE,OAAO;GAAU,WAAW;GAAS;EAAM,CAAC;CAC9D,CAAC,CAAC,CAAC,KACF,OAAO,KAAK,SAAS,cAAc,IAAI,CAAC,CAAC,IAAI,GAC7C,OAAO,SACL,UAAU,eAAe,SAAS,MAAM,KAAK,SACxC,OAAO,SACd,CACD;CACD,MAAM,oBAAoB,OAAO,WAAW,WAC3C,SACC;EACD,IAAI,QAAQ,YAAY,KAAA,GAAW,OAAO,OAAO,KAAa;EAC9D,MAAM,UAAU,QAAQ;EACxB,MAAM,WAAW,cAAc,cAAc,QAAQ,GAAG,CAAC,CAAC,CAAC;EAC3D,MAAM,SAAS,OAAO,eAAe,OAAO;EAC5C,IAAI,WAAW,UAAU,OAAO,OAAO,KAAa;EAGpD,IAAI,WAAW,KAAA,GAEV;QAAA,OADqB,eAAe,QAAQ,GAAG,OACjC,KAAA,GAAW,OAAO,OAAO,KAAa;EAAA;EAEzD,OAAO,OAAO,KAAK,OAAO;CAC3B,CAAC;CAED,MAAM,qBAAqB,OAAO,IAAI,aAAa;EAClD,MAAM,UAAU,OAAO,IAAI,IAAI,MAAM;EACrC,MAAM,WAAW,MAAM,YACtB,MAAM,QAAQ,QAAQ,SAAS,OAAO,IAAI,UACzC,MAAM,SAAS,CAAC,MAAM,QAAQ,MAAM,OAAO,CAAC,CAC7C,CACD;EACA,MAAM,WAAW,QAAQ,aACxB,MAAM,UAAU,WAAW,YAC1B,QAAQ,YAAY,KAAA,IACjB,OAAO,KAAK,KAAA,CAAS,IACrB,OAAO,QAAQ,QAAQ,OAAO,CAClC,CACD;EACA,MAAM,cAAc,aACnB,OAAO,QACN,WACC,YACA,eAAe,OAAO,CAAC,CAAC,KACvB,OAAO,KAAK,WAAW,CAAC,SAAS,MAAM,CAAU,CAClD,GACD,EAAE,aAAa,EAAE,CAClB,CAAC,CAAC,KAAK,OAAO,IAAI,QAAQ,YAAY,CAAC;EACxC,MAAM,SAAS,OAAO,WAAW,QAAQ;EAWzC,MAAM,YAAY,OAAO,WAVF,QAAQ,aAC9B,MAAM,UAAU,WAAW,YAC1B,QAAQ,YAAY,KAAA,KACpB,OAAO,eAAe,QAAQ,IAAI,QAAQ,QAAQ,OAAO,CAAC,MACzD,KAAA,KACD,CAAC,QAAQ,IAAI,QAAQ,QAAQ,GAAG,IAC7B,OAAO,QAAQ,QAAQ,GAAG,IAC1B,OAAO,KAAK,KAAA,CAAS,CACzB,CAEgD,CAAC;EAClD,MAAM,UAAU,QAAQ,MAAM,QAAQ,SAAS;EAE/C,OAAO,MAAM,aACZ,QAAQ,aACP,MAAM,UAAU,WAAW,YAAY;GACtC,IAAI,QAAQ,YAAY,KAAA,GAAW,OAAO,OAAO,KAAK,KAAA,CAAS;GAC/D,MAAM,SAAS,OAAO,eACrB,QAAQ,IAAI,SAAS,QAAQ,OAAO,CACrC;GAEA,OAAO,WADU,cAAc,cAAc,QAAQ,GAAG,CAAC,CAAC,CAAC,QAEzD,WAAW,KAAA,KACX,OAAO,eAAe,QAAQ,IAAI,SAAS,QAAQ,GAAG,CAAC,MACtD,KAAA,IACA,OAAO,KAAK,KAAA,CAAS,IACrB,OAAO,QAAQ,QAAQ,OAAO;EAClC,CAAC,CACF,CACD;CACD,CAAC;CAED,MAAM,OAAO,OAAO,WAAW,WAAW,WAAmB;EAC5D,MAAM,YAAY,OAAO,OAAO,WAAW;GAC1C,WAAW;;IAA0B,MAAM,QAAQ,SAAS;;GAC5D,QAAQ,UAAU,SAAS,KAAK;IAAE,OAAO;IAAU;IAAW;GAAM,CAAC;EACtE,CAAC;EACD,MAAM,SAAS,OAAO,WAAW,SAAS;EAC1C,IAAI,OAAO,OAAO,MAAM,GACvB,OAAO,OAAO,SAAS,KAAK;GAC3B,OAAO;GACP;GACA,OAAO;EACR,CAAC;EACF,MAAM,MAAM,OAAO,OAAO,WAAW,MAAM,SAAS,CAAC,CAAC,CAAC,KACtD,OAAO,UAAU,UAChB,SAAS,KAAK;GAAE,OAAO;GAAU;GAAW;EAAM,CAAC,CACpD,CACD;EACA,MAAM,UAAU,MAAM,YAAY,SAAS;EAC3C,MAAM,UAAU;GACf;GACA,GAAG,OAAO,MAAM,SAAS;IACxB,eAAe,CAAC;IAChB,SAAS,aAAa,EAAE,QAAQ;GACjC,CAAC;EACF;EACA,MAAM,UAAU,OAAO,kBAAkB,OAAO;EAChD,IAAI,OAAO,OAAO,OAAO,GACxB,OAAO,OAAO,SAAS,KAAK;GAC3B,OAAO;GACP;GACA,OAAO,gBAAgB,KAAK,EAAE,KAAK,QAAQ,MAAM,CAAC;EACnD,CAAC;EACF,OAAO;GAAE;GAAW,QAAQ,OAAO;GAAO;EAAI;CAC/C,CAAC;CACD,MAAM,mBAAmB,cACxB,OAAO,eACN,OACC,OAAO,IAAI,aAAa;EACvB,OAAO;EACP,MAAM,UAAU,OAAO,IAAI,IAAI,KAAK;EACpC,MAAM,MAAM,QAAQ,UAAU;EAG9B,MAAM,OAAO,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC;EAC/C,MAAM,QAAgB,OAAO;EAC7B,MAAM,OAAO,OAAO,OAAO,MAAM,SAAS,SACzC,OAAO,WAAW,OAAO,CAAC,CAAC,SAAS,IACjC,OAAO,KAAK,SAAS,IACrB,OAAO,KAAK,CAChB;EACA,MAAM,UAAU,OAAO,IAAI,OAAO,SAAS;GAC1C;GACA,YAAY,QAAQ;GACpB,GAAG,OAAO,MAAM,MAAM,YAAY,SAAS,GAAG;IAC7C,eAAe,CAAC;IAChB,SAAS,aAAa,EAAE,QAAQ;GACjC,CAAC;EACF,EAAE;EACF,IAAI,OAAO,OAAO,OAAO,GACxB,OAAO,IAAI,OACV,QACA,QAAQ,IAAI,QAAQ,MAAM,KAAK,QAAQ,KAAK,CAC7C;EACD,OAAO,IAAI,OACV,QACA,QAAQ,IAAI,OAAO;GAClB,QAAQ,KAAK,UAAU,IAAI,IAAI,UAAU,OAAO,KAAK;GACrD,SAAS,KAAK,UAAU,IAAI,IAAI,UAAU,OAAO,KAAK;EACvD,CAAC,CACF;EACA,IAAI,KAAK,UAAU,IAAI,GAAG;GACzB,MAAM,QAAQ,KAAK;GACnB,MAAM,WAAW,QAAQ,IAAI,QAAQ,SAAS,MAAM,GAAG;GACvD,MAAM,SAAS,OAAO,MAAM,UAAU;IACrC,cAAc,QAAQ,MAAc;IACpC,SAAS,UAAU,MAAM;GAC1B,CAAC;GACD,OAAO,IAAI,IAAI,OAAO;IACrB,GAAG;IACH,SAAS,QAAQ,IAAI,QAAQ,SAAS,MAAM,KAAK;KAChD,QAAQ,MAAM;KACd,QAAQ,QAAQ,IAAI,QAAQ,KAAK;IAClC,CAAC;GACF,CAAC;EACF;EACA,OAAO;GAAE;GAAO,MAAM,KAAK,IAAI,OAAO,UAAU,MAAM,SAAS;EAAE;CAClE,CAAC,CAAC,CAAC,KACF,OAAO,SAAS,OAAO,KAAK,MAAM,OAAO,CAAC,GAC1C,OAAO,SAAS,OAAO,CACxB,CACD,IACC,EAAE,YACF,OACC,OAAO,IAAI,aAAa;EACvB,OAAO,IAAI,OAAO,QAAQ,QAAQ,OAAO,KAAK,CAAC;EAC/C,OAAO,IAAI,OAAO,QAAQ,aAAa;GACtC,GAAG;GACH,SAAS,QAAQ,UAAU,QAAQ,UAAU,UAAU;IACtD,MAAM,SAAS,QAAQ,OAAO,MAAM,QAAQ,KAAK;IACjD,OAAO,QAAQ,KAAK,MAAM,MAAM,IAC7B,OAAO,KAAK,KAAA,CAAS,IACrB,OAAO,QAAQ;KAAE,GAAG;KAAO;IAAO,CAAC;GACvC,CAAC;EACF,EAAE;CACH,CAAC,CAAC,CAAC,KAAK,OAAO,SAAS,OAAO,CAAC,CACjC,CACF,CAAC,CAAC,KACD,OAAO,SAAS,EAAE,WAAW,IAAI,GACjC,YACD;CAED,MAAM,gBAAqC,cAC1C,OACC,UAAU,KACT,OAAO,QACN,OAAO,WAAW;EACjB,WAAW;;GAA0B,MAAM,WAAW,SAAS;;EAC/D,QAAQ,UACP,SAAS,KAAK;GAAE,OAAO;GAAU;GAAW;EAAM,CAAC;CACrD,CAAC,CACF,CACD,CACD;CAED,MAAM,kBAAyC,WAAW,YACzD,YAAY,KAAA,IACT,gBAAgB,SAAS,IACzB,gBAAgB,SAAS,CAAC,CAAC,KAC3B,MAAM,QAAQ,QAAQ,gBAAgB,CACvC;CAEH,MAAM,YAAY,cAEjB,IAAI,UAAU,MAAM,IACjB,QAAQ,OAAO,YAAY,CAAC,IAC5B,IACA,eAAe,SAAS,CAAC,CAAC,KACzB,OAAO,eAAe,MAAM,OAAO,OAAO,CAC3C,CACD;CAEH,MAAM,uBAAuB,aAC5B,MAAM,OAAO,UAAU,QAAQ,MAAc,IAAI,KAAK,YACrD,QAAQ,MACP,KACA,MAAM,YAAY,QAAQ,YAAY,CAAC,QAAQ,GAAG,CAAC,CACpD,CACD;CACD,MAAM,qBAAqB,IAAI,IAAI,MAAM,CAAC,CAAC,KAC1C,OAAO,KAAK,UACX,oBACC,MAAM,SACL,MAAM,IAAI,QAAQ,SAAS,KAAK,IAAI,UAAU,MAAM,MAAM,CAC3D,CACD,CACD,CACD;CAEA,MAAM,iBAAiB,UACtB,OACC,OAAO,IAAI,aAAa;EACvB,OAAO;EACP,MAAM,YAAY,OAAO,IAAI,IAAI,QAAQ;EACzC,MAAM,QAAQ,UAAU,KAAA,KAAa;EACrC,MAAM,eAAe,OAAO,IAAI,IAAI,UAAU;EAC9C,MAAM,eACL,UAAU,KAAA,IACP,eACA,QAAQ,MAAM,cAAc,KAAK;EACrC,OAAO,IAAI,IAAI,YAAY,YAAY;EACvC,OAAO,IAAI,IAAI,UAAU,KAAK;EAC9B,MAAM,UAAU,OAAO;EACvB,IAAI,QAAQ,SAAS,GACpB,OAAO,YAAY,QAAQ;GAC1B,QAAQ;GACR,SAAS;EACV,CAAC;EACF,MAAM,EAAE,YAAY,OAAO,IAAI,IAAI,KAAK;EACxC,MAAM,cAAc,OAAO;EAC3B,IAAI,QAAQ,KAAK,WAAW,IAAI,GAC/B,OAAO,YAAY,QAAQ;GAC1B,SAAS,MAAM,aAAa,WAAW;GACvC,QAAQ;EACT,CAAC;EACF,MAAM,QAAQ,OAAO,IAAI,IAAI,MAAM;EACnC,MAAM,WAAW,MAAM,QAAQ,QAAQ,SAAS,KAAK,IAAI,UACxD,MAAM,SAAS,CAAC,MAAM,QAAQ,MAAM,OAAO,CAAC,CAC7C;EACA,MAAM,SAAS,MAAM,SACpB,MAAM,IAAI,QAAQ,SAAS,KAAK,IAAI,UAAU,MAAM,MAAM,CAC3D;EACA,IAAI,WAAW;EACf,IAAI,UAAU,QAAQ,MAAc;EACpC,IAAI,CAAC,OAAO;GACX,IAAI,WAAW;GAGf,OAAO,MAAM;IACZ,UAAU,MAAM,YAAY,UAAU,QAAQ;IAC9C,MAAM,UAAU,QAAQ,aACvB,MAAM,UAAU,MAAM,aAAa,OAAO,IAAI,CAAC,KAAK,WACnD,QAAQ,IAAI,UAAU,GAAG,KACzB,MAAM,KAAK,MAAM,aAAa,MAAM,MAAM,IAAI,UAC7C,OAAO,OAAO,QAAQ,IAAI,OAAO,KAAK,IAAI,UACzC,MAAM,KACL,MAAM,SAAS,CAAC,MAAM,QAAQ,MAAM,OAAO,CAAC,IAC3C,YAAY,MAAM,SAAS,SAAS,OAAO,CAC7C,CACD,CACD,IACG,OAAO,QAAQ,MAAM,MAAM,IAC3B,OAAO,KAAK,KAAA,CAAS,CACzB,CACD;IACA,WAAW,QAAQ,OAAO,UAAU,UACnC,QAAQ,IAAI,SAAS,MAAM,MAAM,CAClC;IACA,MAAM,WAAW,QAAQ,MACxB,UACA,QAAQ,aAAa,QAAQ,KAAK,QAAQ,CAAC,CAC5C;IACA,IAAI,QAAQ,KAAK,QAAQ,MAAM,QAAQ,KAAK,QAAQ,GAAG;IACvD,WAAW;GACZ;EACD;EAEA,MAAM,YAAY,QACf,MAAM,QAAQ,IACd,MAAM,QAAQ,QAAQ,OAAO;EAEhC,MAAM,MAAM,WAAW,IAAI;EAC3B,OAAO,OAAO,OAAO,IAAI,aAAa;GACrC,MAAM,SAAS,OAAO,OAAO,QAAQ,WAAW,CAAC,KAAK,cACrD,IAAI,OACH,QACA,QAAQ,KAAK,OAAO,UACnB,QAAQ,IAAI,SAAS,QAAQ,KAAK,IAC/B;IACA,GAAG;IACH,SAAS,OAAO,IAAI,MAAM,SAAS,aAAa;KAC/C,GAAG;KACH;KACA,YAAY;IACb,EAAE;GACH,IACC,KACJ,CACD,CAAC,CAAC,KACD,OAAO,QAAQ,KAAK,GAAG,CAAC,GACxB,OAAO,KAAK,UACX,OAAO,KAAK;IACX;IACA,UAAU,SAAS;IACnB,QAAQ,SAAS;IACjB,QAAQ,MAAM;GACf,CAAC,CACF,GACA,OAAO,SACL,UACA,MAAM,UAAU,YAChB,eAAe,KAAK,MAAM,KAAK,SAC1B,OAAO,WACd,CACD,CACD;GACA,MAAM,aAAa,MAAM,SAAS,MAAM;GACxC,MAAM,eAAe,MAAM,OAC1B,YACA,QAAQ,MAAqD,IAC5D,QAAQ,EAAE,UAAU,aACpB,QAAQ,IACP,QACA,UACA,QAAQ,IACP,OAAO,UACN,QAAQ,IAAI,QAAQ,QAAQ,GAC5B,QAAQ,KACT,GACA,MACD,CACD,CACF;GACA,MAAM,YAAY,MAAM,OAAO,aAAa,EAAE,eAC7C,OAAO,OACN,QAAQ,IAAI,cAAc,QAAQ,IACjC,YAAY,QAAQ,KAAK,OAAO,IAAI,CACtC,CACD;GACA,IAAI,UAAU,SAAS,GACtB,OAAO,YAAY,QAAQ;IAC1B,QAAQ;IACR,SAAS,MAAM,IAAI,YAAY,EAAE,UAAU,GAAG;GAC/C,CAAC;GACF,MAAM,eAAe,QAAQ,aAC5B,MAAM,IACL,aACC,EAAE,KAAK,QAAQ,aAAa,CAAC,KAAK;IAAE;IAAQ;GAAO,CAAC,CACtD,CACD;GAEA,MAAM,OAAO,QAAQ,MAAM,SAAS,YAAY;GAEhD,MAAM,QAAQ,MAAM,IACnB,aACC,EAAE,UAAU,aAAa,CAAC,UAAU,MAAM,CAC5C;GACA,MAAM,UAAU,OAAO;GACvB,IAAI,QAAQ,SAAS,GACpB,OAAO,YAAY,QAAQ;IAC1B,QAAQ;IACR,SAAS;GACV,CAAC;GAGF,MAAM,SAAS,oBACd,MAAM,IAAI,SAAS,YAClB,QAAQ,IAAI,cAAc,QAAQ,GAAG,IAClC;IAAE,GAAG;IAAS,YAAY;GAAU,IACpC,OACJ,CACD;GACA,IAAI,QAAQ,KAAK,MAAM,IAAI,GAC1B,OAAO,YAAY,QAAQ;IAC1B,QAAQ;IACR,SAAS,MAAM,aAAa,MAAM;GACnC,CAAC;GAEF,MAAM,cAAc,OAAO,MAAM,QAAQ,KAAK,CAAC,CAAC,KAC/C,OAAO,eAAe,MAAM,OAAO,KAAK,GACxC,OAAO,MACR;GACA,IAAI,OAAO,UAAU,WAAW,GAC/B,OAAO,YAAY,QAAQ;IAC1B,QAAQ;IACR,SAAS,MAAM,UAAU,aAAa,EAAE,OAAO,UAC9C,MAAM,SAAS,YAAY,QAAQ,SAAS,KAAK,IAC9C,OAAO,QAAQ,GAAG,IAClB,OAAO,KAAK,KAAA,CAAS,CACzB;GACD,CAAC;GACF,OAAO,IAAI,OAAO,SAAS,WAC1B,MAAM,OAAO,YAAY,SAAS,QAAQ,EAAE,KAAK,aAChD,QAAQ,IAAI,SAAS,OAAO,UAC3B,QAAQ,IAAI,QAAQ,KAAK,IACtB;IACA,QAAQ,OAAO,IAAI,MAAM,UAAU,aAAa;KAC/C,GAAG;KACH;KACA,YAAY;IACb,EAAE;IACF,SAAS,OAAO,KAAK;GACtB,IACC,KACJ,CACD,CACD;GACA,OAAO,IAAI,IAAI,OAAO;IAAE,SAAS;IAAM,YAAY;GAAU,CAAC;GAC9D,OAAO,IAAI,OAAO,SAAS,WAC1B,QAAQ,MACP,QAAQ,OAAO,SAAS,GAAG,QAAQ,QAAQ,IAAI,MAAM,GAAG,CAAC,GACzD,QAAQ,IAAI,eAAe,GAAG,SAAS;IACtC;IACA,YAAY;GACb,EAAE,CACH,CACD;GACA,OAAO,IAAI,IAAI,YAAY,QAAQ,MAAM,CAAC;GAC1C,OAAO,IAAI,IAAI,UAAU,KAAK;GAC9B,OAAO,YAAY,SAAS,EAC3B,SAAS,MAAM,IAAI,aAAa,cAAc,UAAU,GAAG,EAC5D,CAAC;EACF,CAAC,CAAC,CAAC,KACF,OAAO,SAEL,UAEA,OAAO,GAAG,eAAe,CAAC,CAAC,MAAM,KAAK,IACtC,UACA,OAAO,QACN,YAAY,QAAQ;GACnB,SAAS,MAAM,aACd,QAAQ,IACP,MAAM,YAAY,SAAS,GAC3B,MAAM,MAAM,GACb,CACD;GACA,QAAQ;EACT,CAAC,CACF,CACF,GACA,OAAO,SAAS,OAAO,KAAK,MAAM,OAAO,CAAC,GAC1C,OAAO,SAAS,OAAO,CACxB;CACD,CAAC,CACF;CACD,OAAO;EACN;EACA;EACA;EACA,QAAQ,cAAc;EACtB,QAAQ,OAAO,iBACd,MAAM,WAAW,IACd,OAAO,QACP,SACC,QACA,IAAI,IAAI,MAAM,CAAC,CAAC,KACf,OAAO,KAAK,WACX,MAAM,MAAM,CACX,GAAG,MAAM,SACR,MAAM,IACL,QAAQ,SAAS,MAAM,IACtB,UAAU,MAAM,MAClB,CACD,GACA,GAAG,MAAM,SACR,MAAM,IACL,QAAQ,SAAS,MAAM,IACtB,UAAU,MAAM,OAClB,CACD,CACD,CAAC,CACF,GACA,OAAO,QAAQ,GAAG,GAGlB,UAAU,YAAY,CAAC,CACxB,GACD,OACA,YACD,CAAC,CAAC,KACD,OAAO,WAAW,UACjB,OAAO,IACN,OAAO,KAAK,cAAc,KAAK,CAAC,IAC/B,SACA,KAAK,UAAU,IAAI,IAChB,KAAK,QACL,YAAY,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,CAC7C,CACD,GAGA,OAAO,MACN,OAAO,KAAK,UAAU,CAAC,CAAC,KACvB,OAAO,gBACN,mBAAmB,KAAK,UAAU,YAAY,CAAC,CAAC,CACjD,GACA,OAAO,SACP,OAAO,QAAQ,YAAY,QAAQ,KAAK,OAAO,IAAI,CAAC,GACpD,OAAO,KAAK,YACX,YAAY,QAAQ;GACnB,QAAQ;GACR,SAAS,MAAM,aAAa,OAAO;EACpC,CAAC,CACF,CACD,CACD,CACD;CACJ;AACD,CAAC"}
|
package/dist/internal/changes.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { digest } from "./digest.js";
|
|
2
2
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
|
-
import { Array, Cause, Clock, Effect, Equal, Exit, FileSystem, HashMap, HashSet, Option, Queue, Ref, Stream, String } from "effect";
|
|
3
|
+
import { Array, Cause, Clock, Effect, Equal, Exit, Fiber, FileSystem, HashMap, HashSet, Option, Queue, Ref, Stream, String } from "effect";
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
5
|
// src/internal/changes.ts
|
|
6
6
|
/** Observe the producer after its resource scope closes, before merge can discard its Exit. */
|
|
7
|
-
const observeSource = (source) => Stream.callback((queue) =>
|
|
7
|
+
const observeSource = (source) => Stream.callback((queue) => Effect.scoped(Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
|
|
8
|
+
const id = yield* Effect.withFiber((self) => Effect.succeed(self.id));
|
|
9
|
+
const producer = yield* Effect.forkScoped(restore(source.pipe(Stream.runForEachArray((values) => Queue.offerAll(queue, values)), Effect.scoped)));
|
|
10
|
+
const waiting = yield* Effect.exit(restore(Fiber.await(producer)));
|
|
11
|
+
if (Exit.isFailure(waiting)) yield* Fiber.interrupt(producer);
|
|
12
|
+
const exit = yield* Fiber.await(producer);
|
|
13
|
+
if (Exit.isFailure(exit) && Cause.hasInterrupts(exit.cause) && !(Exit.isFailure(waiting) && Array.every(exit.cause.reasons, (reason) => reason._tag === "Interrupt" && reason.fiberId === id))) yield* Effect.logError("Native watcher failed during cancellation", exit.cause);
|
|
14
|
+
yield* exit;
|
|
15
|
+
yield* Queue.end(queue);
|
|
16
|
+
}))), { bufferSize: 16 });
|
|
8
17
|
/** Compare immutable observation tokens again after filesystem I/O releases the lock. */
|
|
9
18
|
const sameVersion = (a, b) => a.generation === b.generation && a.content === b.content && a.resolution === b.resolution;
|
|
10
19
|
/** Reconcile owned modules because native watchers can silently miss events. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changes.js","names":[],"sources":["../../src/internal/changes.ts"],"sourcesContent":["// @effect-diagnostics-next-line nodeBuiltinImport:off -- watcher paths use host-platform syntax without adding a Path service requirement\nimport { dirname, resolve } from \"node:path\"\nimport type { FileVersion } from \"./modules\"\nimport type { WatchOptions } from \"../index\"\nimport { digest } from \"./digest\"\nimport { fileURLToPath, pathToFileURL } from \"node:url\"\nimport {\n\tArray,\n\tCause,\n\tExit,\n\tEffect,\n\tFileSystem,\n\tHashMap,\n\tHashSet,\n\tEqual,\n\tClock,\n\tRef,\n\tQueue,\n\tOption,\n\tStream,\n\tString,\n} from \"effect\"\n\nexport type WithFiles = <A, E, R>(\n\tuse: (files: HashMap.HashMap<string, FileVersion>) => Effect.Effect<A, E, R>,\n) => Effect.Effect<A, E, R>\n\n/** Observe the producer after its resource scope closes, before merge can discard its Exit. */\nconst observeSource = <A, E, R>(source: Stream.Stream<A, E, R>) =>\n\tStream.callback<A, E, R>(\n\t\t(queue) =>\n\t\t\tsource.pipe(\n\t\t\t\tStream.runForEachArray((values) => Queue.offerAll(queue, values)),\n\t\t\t\tEffect.scoped,\n\t\t\t\tEffect.onExit((exit) =>\n\t\t\t\t\tExit.isFailure(exit) &&\n\t\t\t\t\tCause.hasInterrupts(exit.cause) &&\n\t\t\t\t\t!Cause.hasInterruptsOnly(exit.cause)\n\t\t\t\t\t\t? Effect.logError(\n\t\t\t\t\t\t\t\t\"Native watcher failed during cancellation\",\n\t\t\t\t\t\t\t\texit.cause,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: Effect.void,\n\t\t\t\t),\n\t\t\t\tEffect.andThen(Queue.end(queue)),\n\t\t\t),\n\t\t{ bufferSize: 16 },\n\t)\n\n/** Compare immutable observation tokens again after filesystem I/O releases the lock. */\nconst sameVersion = (a: FileVersion, b: FileVersion) =>\n\ta.generation === b.generation &&\n\ta.content === b.content &&\n\ta.resolution === b.resolution\n\n/** Reconcile owned modules because native watchers can silently miss events. */\nexport const changes = (\n\twithFiles: WithFiles,\n\tpaths: ReadonlyArray<string>,\n\toptions?: WatchOptions,\n) =>\n\tStream.unwrap(\n\t\tEffect.gen(function* () {\n\t\t\tif (paths.length === 0) return Stream.empty\n\t\t\tconst fs = yield* FileSystem.FileSystem\n\t\t\tconst roots = yield* Effect.forEach(paths, (path) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst canonical = yield* fs.realPath(path)\n\t\t\t\t\tconst info = yield* fs.stat(canonical)\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpath: canonical,\n\t\t\t\t\t\turls: [\n\t\t\t\t\t\t\tpathToFileURL(canonical).href,\n\t\t\t\t\t\t\tpathToFileURL(resolve(path)).href,\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdirectory: info.type === \"Directory\",\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t)\n\t\t\tconst accepted = (path: string) => options?.filter?.(path) ?? true\n\t\t\tconst watched = (url: string) =>\n\t\t\t\taccepted(fileURLToPath(url)) &&\n\t\t\t\tArray.some(roots, ({ urls, directory }) =>\n\t\t\t\t\tArray.some(urls, (root) => {\n\t\t\t\t\t\tconst prefix = String.endsWith(\"/\")(root) ? root : `${root}/`\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tfileURLToPath(url) === fileURLToPath(root) ||\n\t\t\t\t\t\t\t(directory &&\n\t\t\t\t\t\t\t\t(options?.recursive === true\n\t\t\t\t\t\t\t\t\t? String.startsWith(prefix)(url)\n\t\t\t\t\t\t\t\t\t: new URL(\".\", url).href === prefix))\n\t\t\t\t\t\t)\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\tconst files = withFiles((loaded) =>\n\t\t\t\tEffect.succeed(HashMap.filter(loaded, (_, url) => watched(url))),\n\t\t\t)\n\t\t\tconst missing = <\n\t\t\t\tA,\n\t\t\t\tE extends import(\"effect\").PlatformError.PlatformError,\n\t\t\t\tR,\n\t\t\t>(\n\t\t\t\teffect: Effect.Effect<A, E, R>,\n\t\t\t) =>\n\t\t\t\teffect.pipe(\n\t\t\t\t\tEffect.catchIf(\n\t\t\t\t\t\t(error) => error.reason._tag === \"NotFound\",\n\t\t\t\t\t\t() => Effect.undefined,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t// Watch only graph directories, never recursively traverse an application root.\n\t\t\t// Missing descendants use their nearest existing ancestor until they appear.\n\t\t\tconst existingDirectory = (\n\t\t\t\tpath: string,\n\t\t\t): Effect.Effect<string, import(\"effect\").PlatformError.PlatformError> =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst info = yield* missing(fs.stat(path))\n\t\t\t\t\treturn info?.type === \"Directory\" || dirname(path) === path\n\t\t\t\t\t\t? path\n\t\t\t\t\t\t: yield* existingDirectory(dirname(path))\n\t\t\t\t})\n\t\t\tconst directories = Effect.gen(function* () {\n\t\t\t\tconst loaded = yield* files\n\t\t\t\tconst requested = HashSet.fromIterable([\n\t\t\t\t\t...Array.map(roots, (root) =>\n\t\t\t\t\t\troot.directory ? root.path : dirname(root.path),\n\t\t\t\t\t),\n\t\t\t\t\t...Array.map(Array.fromIterable(HashMap.keys(loaded)), (url) =>\n\t\t\t\t\t\tdirname(fileURLToPath(url)),\n\t\t\t\t\t),\n\t\t\t\t])\n\t\t\t\tconst existing = yield* Effect.forEach(requested, existingDirectory, {\n\t\t\t\t\tconcurrency: 8,\n\t\t\t\t})\n\t\t\t\treturn HashSet.fromIterable(existing)\n\t\t\t})\n\t\t\tconst dirty = yield* Ref.make(HashSet.empty<string>())\n\t\t\tconst native = Stream.tick(\"1 second\").pipe(\n\t\t\t\tStream.mapEffect(() => directories),\n\t\t\t\tStream.changesWith((a, b) => Equal.equals(a, b)),\n\t\t\t\tStream.switchMap((directories) =>\n\t\t\t\t\tStream.mergeAll(\n\t\t\t\t\t\tArray.map(Array.fromIterable(directories), (directory) =>\n\t\t\t\t\t\t\tfs.watch(directory, { ...options, recursive: false }).pipe(\n\t\t\t\t\t\t\t\tobserveSource,\n\t\t\t\t\t\t\t\tStream.map((event) => resolve(directory, event.path || \".\")),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t{ concurrency: \"unbounded\" },\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tStream.tap((path) => Ref.update(dirty, HashSet.add(path))),\n\t\t\t\tStream.debounce(options?.debounce ?? \"50 millis\"),\n\t\t\t\tStream.mapEffect(() => Ref.getAndSet(dirty, HashSet.empty<string>())),\n\t\t\t)\n\t\t\tinterface Observation {\n\t\t\t\treadonly baseline: FileVersion\n\t\t\t\treadonly content: string | undefined\n\t\t\t\treadonly resolution: string | undefined\n\t\t\t\treadonly stat: string\n\t\t\t\treadonly checked: number\n\t\t\t}\n\t\t\tconst observed = yield* Ref.make(HashMap.empty<string, Observation>())\n\t\t\tconst scan = (events: HashSet.HashSet<string> | undefined) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst loaded = yield* files\n\t\t\t\t\tconst before = yield* Ref.get(observed)\n\t\t\t\t\tconst now = yield* Clock.currentTimeMillis\n\t\t\t\t\tconst selected = Array.filter(\n\t\t\t\t\t\tArray.fromIterable(loaded),\n\t\t\t\t\t\t([url]) =>\n\t\t\t\t\t\t\tevents === undefined ||\n\t\t\t\t\t\t\tArray.some(Array.fromIterable(events), (path) => {\n\t\t\t\t\t\t\t\tconst file = fileURLToPath(url)\n\t\t\t\t\t\t\t\treturn file === path || String.startsWith(`${path}/`)(file)\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t\tconst checked = yield* Effect.forEach(\n\t\t\t\t\t\tselected,\n\t\t\t\t\t\t([url, baseline]) =>\n\t\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\t\tconst path = fileURLToPath(url)\n\t\t\t\t\t\t\t\tconst previous = Option.getOrUndefined(HashMap.get(before, url))\n\t\t\t\t\t\t\t\tconst info = yield* missing(fs.stat(path))\n\t\t\t\t\t\t\t\tconst stat =\n\t\t\t\t\t\t\t\t\tinfo === undefined\n\t\t\t\t\t\t\t\t\t\t? \"missing\"\n\t\t\t\t\t\t\t\t\t\t: `${info.size}:${Option.getOrUndefined(info.mtime)?.getTime()}:${Option.getOrUndefined(info.ino)}`\n\t\t\t\t\t\t\t\tconst resolution =\n\t\t\t\t\t\t\t\t\tbaseline.resolution === undefined\n\t\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t\t: yield* missing(fs.realPath(path)).pipe(\n\t\t\t\t\t\t\t\t\t\t\t\tEffect.map((path) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\tpath === undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: pathToFileURL(path).href,\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tconst audit =\n\t\t\t\t\t\t\t\t\tevents !== undefined ||\n\t\t\t\t\t\t\t\t\tprevious === undefined ||\n\t\t\t\t\t\t\t\t\t!sameVersion(previous.baseline, baseline) ||\n\t\t\t\t\t\t\t\t\tprevious.stat !== stat ||\n\t\t\t\t\t\t\t\t\tnow - previous.checked >= 10000\n\t\t\t\t\t\t\t\tconst content = audit\n\t\t\t\t\t\t\t\t\t? yield* missing(fs.readFile(path)).pipe(\n\t\t\t\t\t\t\t\t\t\t\tEffect.map((bytes) =>\n\t\t\t\t\t\t\t\t\t\t\t\tbytes === undefined ? undefined : digest(bytes),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t: previous.content\n\t\t\t\t\t\t\t\tconst expected =\n\t\t\t\t\t\t\t\t\tprevious === undefined\n\t\t\t\t\t\t\t\t\t\t? baseline\n\t\t\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\t\t\tcontent:\n\t\t\t\t\t\t\t\t\t\t\t\t\tbaseline.content === undefined ||\n\t\t\t\t\t\t\t\t\t\t\t\t\tsameVersion(previous.baseline, baseline)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? previous.content\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: baseline.content,\n\t\t\t\t\t\t\t\t\t\t\t\tresolution: sameVersion(previous.baseline, baseline)\n\t\t\t\t\t\t\t\t\t\t\t\t\t? previous.resolution\n\t\t\t\t\t\t\t\t\t\t\t\t\t: baseline.resolution,\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\tobservation: {\n\t\t\t\t\t\t\t\t\t\tbaseline,\n\t\t\t\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\t\t\t\tresolution,\n\t\t\t\t\t\t\t\t\t\tstat,\n\t\t\t\t\t\t\t\t\t\tchecked: audit ? now : previous.checked,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tchanged:\n\t\t\t\t\t\t\t\t\t\texpected.content !== content ||\n\t\t\t\t\t\t\t\t\t\texpected.resolution !== resolution,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t{ concurrency: 8 },\n\t\t\t\t\t)\n\t\t\t\t\t// The immutable snapshot keeps its bytes alive while owners can be released.\n\t\t\t\t\t// A stale result cannot acknowledge a newer import, even when bytes coincide.\n\t\t\t\t\treturn yield* withFiles((current) =>\n\t\t\t\t\t\tRef.modify(observed, (seen) => {\n\t\t\t\t\t\t\tlet next = HashMap.filter(seen, (_, url) =>\n\t\t\t\t\t\t\t\tHashMap.has(current, url),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tlet changed = HashSet.empty<string>()\n\t\t\t\t\t\t\tfor (const { url, observation, changed: differs } of checked) {\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t!Option.exists(HashMap.get(current, url), (version) =>\n\t\t\t\t\t\t\t\t\t\tsameVersion(version, observation.baseline),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t\tnext = HashMap.set(next, url, observation)\n\t\t\t\t\t\t\t\tif (differs) changed = HashSet.add(changed, url)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn [changed, next]\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\treturn Stream.merge(\n\t\t\t\tnative,\n\t\t\t\tStream.tick(\"1 second\").pipe(\n\t\t\t\t\tStream.drop(1),\n\t\t\t\t\tStream.map(() => undefined),\n\t\t\t\t),\n\t\t\t).pipe(\n\t\t\t\tStream.mapEffect(scan),\n\t\t\t\tStream.filter((changed) => HashSet.size(changed) > 0),\n\t\t\t)\n\t\t}),\n\t)\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"changes.js","names":[],"sources":["../../src/internal/changes.ts"],"sourcesContent":["// @effect-diagnostics-next-line nodeBuiltinImport:off -- watcher paths use host-platform syntax without adding a Path service requirement\nimport { dirname, resolve } from \"node:path\"\nimport type { FileVersion } from \"./modules\"\nimport type { WatchOptions } from \"../index\"\nimport { digest } from \"./digest\"\nimport { fileURLToPath, pathToFileURL } from \"node:url\"\nimport {\n\tArray,\n\tCause,\n\tExit,\n\tEffect,\n\tFiber,\n\tFileSystem,\n\tHashMap,\n\tHashSet,\n\tEqual,\n\tClock,\n\tRef,\n\tQueue,\n\tOption,\n\tStream,\n\tString,\n} from \"effect\"\n\nexport type WithFiles = <A, E, R>(\n\tuse: (files: HashMap.HashMap<string, FileVersion>) => Effect.Effect<A, E, R>,\n) => Effect.Effect<A, E, R>\n\n/** Observe the producer after its resource scope closes, before merge can discard its Exit. */\nconst observeSource = <A, E, R>(source: Stream.Stream<A, E, R>) =>\n\tStream.callback<A, E, R>(\n\t\t(queue) =>\n\t\t\tEffect.scoped(\n\t\t\t\tEffect.uninterruptibleMask((restore) =>\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst id = yield* Effect.withFiber((self) =>\n\t\t\t\t\t\t\tEffect.succeed(self.id),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst producer = yield* Effect.forkScoped(\n\t\t\t\t\t\t\trestore(\n\t\t\t\t\t\t\t\tsource.pipe(\n\t\t\t\t\t\t\t\t\tStream.runForEachArray((values) =>\n\t\t\t\t\t\t\t\t\t\tQueue.offerAll(queue, values),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tEffect.scoped,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst waiting = yield* Effect.exit(restore(Fiber.await(producer)))\n\t\t\t\t\t\tif (Exit.isFailure(waiting)) yield* Fiber.interrupt(producer)\n\t\t\t\t\t\tconst exit = yield* Fiber.await(producer)\n\t\t\t\t\t\t// Only our own cancellation is expected; nested finalizers may contribute other interrupts.\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tExit.isFailure(exit) &&\n\t\t\t\t\t\t\tCause.hasInterrupts(exit.cause) &&\n\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\tExit.isFailure(waiting) &&\n\t\t\t\t\t\t\t\tArray.every(\n\t\t\t\t\t\t\t\t\texit.cause.reasons,\n\t\t\t\t\t\t\t\t\t(reason) =>\n\t\t\t\t\t\t\t\t\t\treason._tag === \"Interrupt\" && reason.fiberId === id,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\tyield* Effect.logError(\n\t\t\t\t\t\t\t\t\"Native watcher failed during cancellation\",\n\t\t\t\t\t\t\t\texit.cause,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\tyield* exit\n\t\t\t\t\t\tyield* Queue.end(queue)\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t{ bufferSize: 16 },\n\t)\n\n/** Compare immutable observation tokens again after filesystem I/O releases the lock. */\nconst sameVersion = (a: FileVersion, b: FileVersion) =>\n\ta.generation === b.generation &&\n\ta.content === b.content &&\n\ta.resolution === b.resolution\n\n/** Reconcile owned modules because native watchers can silently miss events. */\nexport const changes = (\n\twithFiles: WithFiles,\n\tpaths: ReadonlyArray<string>,\n\toptions?: WatchOptions,\n) =>\n\tStream.unwrap(\n\t\tEffect.gen(function* () {\n\t\t\tif (paths.length === 0) return Stream.empty\n\t\t\tconst fs = yield* FileSystem.FileSystem\n\t\t\tconst roots = yield* Effect.forEach(paths, (path) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst canonical = yield* fs.realPath(path)\n\t\t\t\t\tconst info = yield* fs.stat(canonical)\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpath: canonical,\n\t\t\t\t\t\turls: [\n\t\t\t\t\t\t\tpathToFileURL(canonical).href,\n\t\t\t\t\t\t\tpathToFileURL(resolve(path)).href,\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdirectory: info.type === \"Directory\",\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t)\n\t\t\tconst accepted = (path: string) => options?.filter?.(path) ?? true\n\t\t\tconst watched = (url: string) =>\n\t\t\t\taccepted(fileURLToPath(url)) &&\n\t\t\t\tArray.some(roots, ({ urls, directory }) =>\n\t\t\t\t\tArray.some(urls, (root) => {\n\t\t\t\t\t\tconst prefix = String.endsWith(\"/\")(root) ? root : `${root}/`\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tfileURLToPath(url) === fileURLToPath(root) ||\n\t\t\t\t\t\t\t(directory &&\n\t\t\t\t\t\t\t\t(options?.recursive === true\n\t\t\t\t\t\t\t\t\t? String.startsWith(prefix)(url)\n\t\t\t\t\t\t\t\t\t: new URL(\".\", url).href === prefix))\n\t\t\t\t\t\t)\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\tconst files = withFiles((loaded) =>\n\t\t\t\tEffect.succeed(HashMap.filter(loaded, (_, url) => watched(url))),\n\t\t\t)\n\t\t\tconst missing = <\n\t\t\t\tA,\n\t\t\t\tE extends import(\"effect\").PlatformError.PlatformError,\n\t\t\t\tR,\n\t\t\t>(\n\t\t\t\teffect: Effect.Effect<A, E, R>,\n\t\t\t) =>\n\t\t\t\teffect.pipe(\n\t\t\t\t\tEffect.catchIf(\n\t\t\t\t\t\t(error) => error.reason._tag === \"NotFound\",\n\t\t\t\t\t\t() => Effect.undefined,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t// Watch only graph directories, never recursively traverse an application root.\n\t\t\t// Missing descendants use their nearest existing ancestor until they appear.\n\t\t\tconst existingDirectory = (\n\t\t\t\tpath: string,\n\t\t\t): Effect.Effect<string, import(\"effect\").PlatformError.PlatformError> =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst info = yield* missing(fs.stat(path))\n\t\t\t\t\treturn info?.type === \"Directory\" || dirname(path) === path\n\t\t\t\t\t\t? path\n\t\t\t\t\t\t: yield* existingDirectory(dirname(path))\n\t\t\t\t})\n\t\t\tconst directories = Effect.gen(function* () {\n\t\t\t\tconst loaded = yield* files\n\t\t\t\tconst requested = HashSet.fromIterable([\n\t\t\t\t\t...Array.map(roots, (root) =>\n\t\t\t\t\t\troot.directory ? root.path : dirname(root.path),\n\t\t\t\t\t),\n\t\t\t\t\t...Array.map(Array.fromIterable(HashMap.keys(loaded)), (url) =>\n\t\t\t\t\t\tdirname(fileURLToPath(url)),\n\t\t\t\t\t),\n\t\t\t\t])\n\t\t\t\tconst existing = yield* Effect.forEach(requested, existingDirectory, {\n\t\t\t\t\tconcurrency: 8,\n\t\t\t\t})\n\t\t\t\treturn HashSet.fromIterable(existing)\n\t\t\t})\n\t\t\tconst dirty = yield* Ref.make(HashSet.empty<string>())\n\t\t\tconst native = Stream.tick(\"1 second\").pipe(\n\t\t\t\tStream.mapEffect(() => directories),\n\t\t\t\tStream.changesWith((a, b) => Equal.equals(a, b)),\n\t\t\t\tStream.switchMap((directories) =>\n\t\t\t\t\tStream.mergeAll(\n\t\t\t\t\t\tArray.map(Array.fromIterable(directories), (directory) =>\n\t\t\t\t\t\t\tfs.watch(directory, { ...options, recursive: false }).pipe(\n\t\t\t\t\t\t\t\tobserveSource,\n\t\t\t\t\t\t\t\tStream.map((event) => resolve(directory, event.path || \".\")),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t{ concurrency: \"unbounded\" },\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tStream.tap((path) => Ref.update(dirty, HashSet.add(path))),\n\t\t\t\tStream.debounce(options?.debounce ?? \"50 millis\"),\n\t\t\t\tStream.mapEffect(() => Ref.getAndSet(dirty, HashSet.empty<string>())),\n\t\t\t)\n\t\t\tinterface Observation {\n\t\t\t\treadonly baseline: FileVersion\n\t\t\t\treadonly content: string | undefined\n\t\t\t\treadonly resolution: string | undefined\n\t\t\t\treadonly stat: string\n\t\t\t\treadonly checked: number\n\t\t\t}\n\t\t\tconst observed = yield* Ref.make(HashMap.empty<string, Observation>())\n\t\t\tconst scan = (events: HashSet.HashSet<string> | undefined) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst loaded = yield* files\n\t\t\t\t\tconst before = yield* Ref.get(observed)\n\t\t\t\t\tconst now = yield* Clock.currentTimeMillis\n\t\t\t\t\tconst selected = Array.filter(\n\t\t\t\t\t\tArray.fromIterable(loaded),\n\t\t\t\t\t\t([url]) =>\n\t\t\t\t\t\t\tevents === undefined ||\n\t\t\t\t\t\t\tArray.some(Array.fromIterable(events), (path) => {\n\t\t\t\t\t\t\t\tconst file = fileURLToPath(url)\n\t\t\t\t\t\t\t\treturn file === path || String.startsWith(`${path}/`)(file)\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t\tconst checked = yield* Effect.forEach(\n\t\t\t\t\t\tselected,\n\t\t\t\t\t\t([url, baseline]) =>\n\t\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\t\tconst path = fileURLToPath(url)\n\t\t\t\t\t\t\t\tconst previous = Option.getOrUndefined(HashMap.get(before, url))\n\t\t\t\t\t\t\t\tconst info = yield* missing(fs.stat(path))\n\t\t\t\t\t\t\t\tconst stat =\n\t\t\t\t\t\t\t\t\tinfo === undefined\n\t\t\t\t\t\t\t\t\t\t? \"missing\"\n\t\t\t\t\t\t\t\t\t\t: `${info.size}:${Option.getOrUndefined(info.mtime)?.getTime()}:${Option.getOrUndefined(info.ino)}`\n\t\t\t\t\t\t\t\tconst resolution =\n\t\t\t\t\t\t\t\t\tbaseline.resolution === undefined\n\t\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t\t: yield* missing(fs.realPath(path)).pipe(\n\t\t\t\t\t\t\t\t\t\t\t\tEffect.map((path) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\tpath === undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: pathToFileURL(path).href,\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tconst audit =\n\t\t\t\t\t\t\t\t\tevents !== undefined ||\n\t\t\t\t\t\t\t\t\tprevious === undefined ||\n\t\t\t\t\t\t\t\t\t!sameVersion(previous.baseline, baseline) ||\n\t\t\t\t\t\t\t\t\tprevious.stat !== stat ||\n\t\t\t\t\t\t\t\t\tnow - previous.checked >= 10000\n\t\t\t\t\t\t\t\tconst content = audit\n\t\t\t\t\t\t\t\t\t? yield* missing(fs.readFile(path)).pipe(\n\t\t\t\t\t\t\t\t\t\t\tEffect.map((bytes) =>\n\t\t\t\t\t\t\t\t\t\t\t\tbytes === undefined ? undefined : digest(bytes),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t: previous.content\n\t\t\t\t\t\t\t\tconst expected =\n\t\t\t\t\t\t\t\t\tprevious === undefined\n\t\t\t\t\t\t\t\t\t\t? baseline\n\t\t\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\t\t\tcontent:\n\t\t\t\t\t\t\t\t\t\t\t\t\tbaseline.content === undefined ||\n\t\t\t\t\t\t\t\t\t\t\t\t\tsameVersion(previous.baseline, baseline)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? previous.content\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: baseline.content,\n\t\t\t\t\t\t\t\t\t\t\t\tresolution: sameVersion(previous.baseline, baseline)\n\t\t\t\t\t\t\t\t\t\t\t\t\t? previous.resolution\n\t\t\t\t\t\t\t\t\t\t\t\t\t: baseline.resolution,\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\tobservation: {\n\t\t\t\t\t\t\t\t\t\tbaseline,\n\t\t\t\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\t\t\t\tresolution,\n\t\t\t\t\t\t\t\t\t\tstat,\n\t\t\t\t\t\t\t\t\t\tchecked: audit ? now : previous.checked,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tchanged:\n\t\t\t\t\t\t\t\t\t\texpected.content !== content ||\n\t\t\t\t\t\t\t\t\t\texpected.resolution !== resolution,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t{ concurrency: 8 },\n\t\t\t\t\t)\n\t\t\t\t\t// The immutable snapshot keeps its bytes alive while owners can be released.\n\t\t\t\t\t// A stale result cannot acknowledge a newer import, even when bytes coincide.\n\t\t\t\t\treturn yield* withFiles((current) =>\n\t\t\t\t\t\tRef.modify(observed, (seen) => {\n\t\t\t\t\t\t\tlet next = HashMap.filter(seen, (_, url) =>\n\t\t\t\t\t\t\t\tHashMap.has(current, url),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tlet changed = HashSet.empty<string>()\n\t\t\t\t\t\t\tfor (const { url, observation, changed: differs } of checked) {\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t!Option.exists(HashMap.get(current, url), (version) =>\n\t\t\t\t\t\t\t\t\t\tsameVersion(version, observation.baseline),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t\tnext = HashMap.set(next, url, observation)\n\t\t\t\t\t\t\t\tif (differs) changed = HashSet.add(changed, url)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn [changed, next]\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\treturn Stream.merge(\n\t\t\t\tnative,\n\t\t\t\tStream.tick(\"1 second\").pipe(\n\t\t\t\t\tStream.drop(1),\n\t\t\t\t\tStream.map(() => undefined),\n\t\t\t\t),\n\t\t\t).pipe(\n\t\t\t\tStream.mapEffect(scan),\n\t\t\t\tStream.filter((changed) => HashSet.size(changed) > 0),\n\t\t\t)\n\t\t}),\n\t)\n"],"mappings":"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"}
|
package/dist/internal/modules.js
CHANGED
|
@@ -21,6 +21,8 @@ const fileRequest = (specifier, parent) => {
|
|
|
21
21
|
const modules = (base, include) => {
|
|
22
22
|
const key = `graft-hmr-${++sessions}`;
|
|
23
23
|
const prefix = `${key}:`;
|
|
24
|
+
const rawPrefix = `${key}:raw:`;
|
|
25
|
+
/** What `request` produces: the generation that imports a specifier. */
|
|
24
26
|
const decodeRequest = Schema.decodeUnknownOption(Schema.TemplateLiteralParser([
|
|
25
27
|
prefix,
|
|
26
28
|
Schema.String.check(Schema.isPattern(/^\d+$/)),
|
|
@@ -139,6 +141,10 @@ const modules = (base, include) => {
|
|
|
139
141
|
};
|
|
140
142
|
const hooks = registerHooks({
|
|
141
143
|
resolve(specifier, context, nextResolve) {
|
|
144
|
+
if (String.startsWith(rawPrefix)(specifier)) return nextResolve(String.slice(rawPrefix.length)(specifier), {
|
|
145
|
+
...context,
|
|
146
|
+
parentURL: base
|
|
147
|
+
});
|
|
142
148
|
const parentNode = context.parentURL;
|
|
143
149
|
const request = decodeRequest(specifier);
|
|
144
150
|
const entry = Option.isSome(request);
|
|
@@ -261,6 +267,7 @@ const modules = (base, include) => {
|
|
|
261
267
|
resolved = void 0;
|
|
262
268
|
return `${prefix}${importing.generation.id}:${specifier}`;
|
|
263
269
|
},
|
|
270
|
+
rawRequest: (specifier) => `${rawPrefix}${specifier}`,
|
|
264
271
|
resolved: () => Option.fromUndefinedOr(resolved),
|
|
265
272
|
close: () => {
|
|
266
273
|
hooks.deregister();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modules.js","names":[],"sources":["../../src/internal/modules.ts"],"sourcesContent":["// Node's synchronous module hooks have no Effect equivalent.\nimport { digest } from \"./digest\"\nimport { registerHooks } from \"node:module\"\nimport { fileURLToPath, pathToFileURL } from \"node:url\"\nimport {\n\tArray,\n\tChunk,\n\tHashMap,\n\tHashSet,\n\tOption,\n\tPredicate,\n\tSchema,\n\tString,\n} from \"effect\"\n\nexport class RestartRequired extends Schema.TaggedError<\n\tRestartRequired,\n\t{ readonly brand: unique symbol }\n>()(\"RestartRequired\", { url: Schema.String }) {}\n\n// Only a missing entry is disposable; missing dependencies still fail the reload.\nexport const isMissingEntry = (url: string, cause: unknown): boolean =>\n\tString.startsWith(\"file:\")(url) &&\n\tPredicate.hasProperty(cause, \"code\") &&\n\t((cause.code === \"ERR_MODULE_NOT_FOUND\" &&\n\t\tPredicate.hasProperty(cause, \"url\") &&\n\t\tcause.url === url) ||\n\t\t(cause.code === \"ENOENT\" &&\n\t\t\tPredicate.hasProperty(cause, \"path\") &&\n\t\t\tcause.path === fileURLToPath(url)))\n\n// Allocated only when a session starts; importing this module performs no I/O.\nlet sessions = 0\n\n/** A resolution view that allocates fresh URLs for new or invalidated instances. */\nexport interface Generation {\n\treadonly id: number\n}\n\n/** Digest of the bytes actually loaded by a concrete module instance. */\nexport interface FileVersion {\n\treadonly generation: number\n\treadonly content: string | undefined\n\treadonly resolution?: string\n}\n\nexport interface Attempt {\n\treadonly generation: Generation\n\treadonly url: string\n\treadonly request?: string\n}\n\ninterface Dependency extends Attempt {\n\treadonly node: string\n}\n\n/** Resolve local requests lexically; Node's cached physical target is a separate fact. */\nconst fileRequest = (\n\tspecifier: string,\n\tparent: string,\n): Option.Option<string> => {\n\tif (\n\t\t!Array.some([\"file:\", \"./\", \"../\", \"/\"], (prefix) =>\n\t\t\tString.startsWith(prefix)(specifier),\n\t\t)\n\t)\n\t\treturn Option.none()\n\tconst url = new URL(specifier, parent)\n\treturn url.protocol === \"file:\" ? Option.some(url.href) : Option.none()\n}\n\n/** A scoped Node hook. Mutable bindings bridge synchronous hooks to Effect. */\nexport const modules = (base: string, include: (url: string) => boolean) => {\n\tconst key = `graft-hmr-${++sessions}`\n\tconst prefix = `${key}:`\n\tconst decodeRequest = Schema.decodeUnknownOption(\n\t\tSchema.TemplateLiteralParser([\n\t\t\tprefix,\n\t\t\tSchema.String.check(Schema.isPattern(/^\\d+$/)),\n\t\t\t\":\",\n\t\t\tSchema.String,\n\t\t]),\n\t)\n\tlet revision = 0\n\tlet importing:\n\t\t{ readonly generation: Generation; readonly reload: boolean } | undefined\n\tlet resolved: string | undefined\n\t// Resolution views contain only routing identities. Old code can execute after\n\t// replacement (including teardown), so these persistent maps live until close.\n\t// Cached instances also retain their facts: Node does not replay static imports.\n\t// Leases restrict observation, not the lifetime of old routing targets.\n\tlet views = HashMap.empty<number, HashMap.HashMap<string, string>>()\n\tlet edges = HashMap.empty<string, HashMap.HashMap<string, Dependency>>()\n\tlet sources = HashMap.empty<string, string>()\n\tlet dependencies = HashSet.empty<string>()\n\tlet reachCache = HashMap.empty<string, HashSet.HashSet<string>>()\n\tlet retained = HashSet.empty<string>()\n\tlet instantiatedViews = HashSet.empty<number>()\n\tconst clean = (url: string): string => {\n\t\tconst value = new URL(url)\n\t\tvalue.searchParams.delete(key)\n\t\treturn value.href\n\t}\n\tconst version = (url: string | undefined): number | undefined => {\n\t\tif (url === undefined) return undefined\n\t\tconst value = new URL(url).searchParams.get(key)\n\t\treturn value === null ? undefined : Number(value)\n\t}\n\tconst tag = (url: string, id: number) => {\n\t\tconst value = new URL(url)\n\t\tvalue.searchParams.set(key, String.String(id))\n\t\treturn value.href\n\t}\n\tconst route = (url: string, id: number): string =>\n\t\tOption.getOrElse(\n\t\t\tHashMap.get(\n\t\t\t\tOption.getOrElse(HashMap.get(views, id), HashMap.empty<string, string>),\n\t\t\t\turl,\n\t\t\t),\n\t\t\t() => tag(url, id),\n\t\t)\n\n\tconst root = (attempt: Attempt) => route(attempt.url, attempt.generation.id)\n\tconst children = (node: string) =>\n\t\tOption.getOrElse(\n\t\t\tHashMap.get(edges, node),\n\t\t\tHashMap.empty<string, Dependency>,\n\t\t)\n\tconst reachable = (node: string) => {\n\t\tconst cached = HashMap.get(reachCache, node)\n\t\tif (Option.isSome(cached)) return cached.value\n\t\tlet seen = HashSet.empty<string>()\n\t\tlet pending: Chunk.Chunk<string> = Chunk.of(node)\n\t\twhile (Chunk.isNonEmpty(pending)) {\n\t\t\tconst current = Chunk.headNonEmpty(pending)\n\t\t\tpending = Chunk.drop(pending, 1)\n\t\t\tif (HashSet.has(seen, current)) continue\n\t\t\tseen = HashSet.add(seen, current)\n\t\t\tfor (const edge of HashMap.values(children(current)))\n\t\t\t\tpending = Chunk.prepend(pending, edge.node)\n\t\t}\n\t\treachCache = HashMap.set(reachCache, node, seen)\n\t\treturn seen\n\t}\n\tconst usedBy = (attempts: ReadonlyArray<Attempt>) => {\n\t\tconst roots = HashSet.fromIterable(Array.map(attempts, root))\n\t\tlet used = HashSet.empty<string>()\n\t\tfor (const node of roots) used = HashSet.union(used, reachable(node))\n\t\treturn used\n\t}\n\tconst link = (parent: string, node: string, request?: string) => {\n\t\tif (\n\t\t\timporting === undefined &&\n\t\t\t!HashSet.has(retained, parent) &&\n\t\t\t!HashSet.has(instantiatedViews, version(parent)!)\n\t\t)\n\t\t\treturn\n\t\tretained = HashSet.add(retained, node)\n\t\tconst url = clean(node)\n\t\tconst edge = {\n\t\t\tnode,\n\t\t\turl,\n\t\t\tgeneration: { id: version(node)! },\n\t\t\t...(request === undefined ? {} : { request }),\n\t\t}\n\t\tconst previous = HashMap.get(children(parent), request ?? url)\n\t\tif (\n\t\t\tOption.exists(\n\t\t\t\tprevious,\n\t\t\t\t(previous) => previous.node === node && previous.request === request,\n\t\t\t)\n\t\t)\n\t\t\treturn\n\t\tedges = HashMap.set(\n\t\t\tedges,\n\t\t\tparent,\n\t\t\tHashMap.set(children(parent), request ?? url, edge),\n\t\t)\n\t\treachCache = HashMap.empty()\n\t}\n\tconst resolutions = (\n\t\tattempts: ReadonlyArray<Attempt>,\n\t): ReadonlyArray<Attempt> => [\n\t\t...Array.filter(attempts, (attempt) => attempt.request !== undefined),\n\t\t...Array.flatMap(Array.fromIterable(usedBy(attempts)), (node) =>\n\t\t\tArray.filter(\n\t\t\t\tHashMap.toValues(children(node)),\n\t\t\t\t(edge) => edge.request !== undefined,\n\t\t\t),\n\t\t),\n\t]\n\tconst unsupported = (url: string, format: string | null | undefined) =>\n\t\tformat === \"commonjs\" ||\n\t\tformat === \"commonjs-typescript\" ||\n\t\tformat === \"addon\" ||\n\t\tString.endsWith(\".node\")(new URL(url).pathname)\n\tconst requireRestart = (node: string) => {\n\t\tif (importing !== undefined || HashSet.has(retained, node))\n\t\t\tdependencies = HashSet.add(dependencies, node)\n\t\tif (importing?.reload === true && importing.generation.id === version(node))\n\t\t\tthrow RestartRequired.make({ url: clean(node) })\n\t}\n\tconst record = (node: string, format: string | null | undefined) => {\n\t\tif (unsupported(clean(node), format)) requireRestart(node)\n\t}\n\t// One reverse traversal closes cycles and all importers of every dirty instance.\n\tconst invalidated = (\n\t\tattempts: ReadonlyArray<Attempt>,\n\t\tdirty: HashSet.HashSet<string>,\n\t) => {\n\t\tconst used = usedBy(attempts)\n\t\tlet parents = HashMap.empty<string, HashSet.HashSet<string>>()\n\t\tlet pending = Chunk.empty<string>()\n\t\tfor (const node of used) {\n\t\t\tif (HashSet.has(dirty, clean(node)))\n\t\t\t\tpending = Chunk.prepend(pending, node)\n\t\t\tfor (const edge of HashMap.values(children(node))) {\n\t\t\t\tparents = HashMap.set(\n\t\t\t\t\tparents,\n\t\t\t\t\tedge.node,\n\t\t\t\t\tHashSet.add(\n\t\t\t\t\t\tOption.getOrElse(\n\t\t\t\t\t\t\tHashMap.get(parents, edge.node),\n\t\t\t\t\t\t\tHashSet.empty<string>,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnode,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\tif (edge.request !== undefined && HashSet.has(dirty, edge.request))\n\t\t\t\t\tpending = Chunk.prepend(pending, edge.node)\n\t\t\t}\n\t\t}\n\t\tfor (const attempt of attempts)\n\t\t\tif (attempt.request !== undefined && HashSet.has(dirty, attempt.request))\n\t\t\t\tpending = Chunk.prepend(pending, root(attempt))\n\t\tlet invalid = HashSet.empty<string>()\n\t\twhile (Chunk.isNonEmpty(pending)) {\n\t\t\tconst node = Chunk.headNonEmpty(pending)\n\t\t\tpending = Chunk.drop(pending, 1)\n\t\t\tif (HashSet.has(invalid, node)) continue\n\t\t\tinvalid = HashSet.add(invalid, node)\n\t\t\tfor (const parent of Option.getOrElse(\n\t\t\t\tHashMap.get(parents, node),\n\t\t\t\tHashSet.empty<string>,\n\t\t\t))\n\t\t\t\tpending = Chunk.prepend(pending, parent)\n\t\t}\n\t\treturn invalid\n\t}\n\tconst prepare = (\n\t\tattempts: ReadonlyArray<Attempt> = [],\n\t\tinvalid = HashSet.empty<string>(),\n\t): Generation => {\n\t\tconst id = ++revision\n\t\tconst seed = Array.reduce(attempts, 0, (id, attempt) =>\n\t\t\tMath.max(id, attempt.generation.id),\n\t\t)\n\t\tlet view = Option.getOrElse(\n\t\t\tHashMap.get(views, seed),\n\t\t\tHashMap.empty<string, string>,\n\t\t)\n\t\tconst used = usedBy(attempts)\n\t\t// Retain HAMT structure between views. Default routes need no stored entry;\n\t\t// only modules reused from older views need an explicit override.\n\t\tfor (const [url, node] of view)\n\t\t\tif (!HashSet.has(used, node) || HashSet.has(invalid, node))\n\t\t\t\tview = HashMap.remove(view, url)\n\t\tfor (const node of used) {\n\t\t\tif (HashSet.has(invalid, node)) continue\n\t\t\tconst url = clean(node)\n\t\t\tconst previous = HashMap.get(view, url)\n\t\t\tif (Option.isNone(previous) || version(previous.value)! < version(node)!)\n\t\t\t\tview = HashMap.set(view, url, node)\n\t\t}\n\n\t\tviews = HashMap.set(views, id, view)\n\t\treturn { id }\n\t}\n\tconst hooks = registerHooks({\n\t\tresolve(specifier, context, nextResolve) {\n\t\t\tconst parentNode = context.parentURL\n\t\t\tconst request = decodeRequest(specifier)\n\t\t\tconst entry = Option.isSome(request)\n\t\t\tconst id = Option.match(request, {\n\t\t\t\tonNone: () => version(context.parentURL),\n\t\t\t\tonSome: ([, id]) => Number(id),\n\t\t\t})\n\t\t\tif (id === undefined) return nextResolve(specifier, context)\n\t\t\tconst target = Option.match(request, {\n\t\t\t\tonNone: () => specifier,\n\t\t\t\tonSome: ([, , , target]) => target,\n\t\t\t})\n\t\t\tconst parent = entry ? base : clean(context.parentURL!)\n\t\t\tconst lexical = Option.getOrUndefined(fileRequest(target, parent))\n\t\t\tconst result = (() => {\n\t\t\t\ttry {\n\t\t\t\t\treturn nextResolve(target, { ...context, parentURL: parent })\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tPredicate.hasProperty(cause, \"url\") &&\n\t\t\t\t\t\ttypeof cause.url === \"string\" &&\n\t\t\t\t\t\tString.startsWith(\"file:\")(cause.url)\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (entry) resolved = cause.url\n\t\t\t\t\t\telse if (include(cause.url))\n\t\t\t\t\t\t\tlink(parentNode!, route(cause.url, id), lexical)\n\t\t\t\t\t}\n\t\t\t\t\tthrow cause\n\t\t\t\t}\n\t\t\t})()\n\t\t\tif (entry) resolved = result.url\n\t\t\tif (!entry && result.url === \"node:module\") {\n\t\t\t\tconst node = route(result.url, id)\n\t\t\t\tlink(parentNode!, node)\n\t\t\t\trequireRestart(node)\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!String.startsWith(\"file:\")(result.url) ||\n\t\t\t\t(!entry && !include(result.url))\n\t\t\t)\n\t\t\t\treturn result\n\t\t\tconst node = route(result.url, id)\n\t\t\tif (!entry) link(parentNode!, node, lexical)\n\t\t\tconst required = Array.contains(context.conditions, \"require\")\n\t\t\tif (required) requireRestart(node)\n\t\t\telse record(node, result.format)\n\t\t\treturn required || unsupported(result.url, result.format)\n\t\t\t\t? result\n\t\t\t\t: { ...result, url: node }\n\t\t},\n\t\tload(url, context, nextLoad) {\n\t\t\tconst id = version(url)\n\t\t\tif (id === undefined) return nextLoad(url, context)\n\t\t\tinstantiatedViews = HashSet.add(instantiatedViews, id)\n\t\t\tconst original = clean(url)\n\t\t\trecord(url, context.format)\n\t\t\tconst result = nextLoad(original, context)\n\t\t\tconst source = result.source\n\t\t\tif (source !== undefined && source !== null) {\n\t\t\t\tconst bytes =\n\t\t\t\t\ttypeof source === \"string\"\n\t\t\t\t\t\t? source\n\t\t\t\t\t\t: ArrayBuffer.isView(source)\n\t\t\t\t\t\t\t? new Uint8Array(\n\t\t\t\t\t\t\t\t\tsource.buffer,\n\t\t\t\t\t\t\t\t\tsource.byteOffset,\n\t\t\t\t\t\t\t\t\tsource.byteLength,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: new Uint8Array(source)\n\t\t\t\tif (importing !== undefined || HashSet.has(retained, url))\n\t\t\t\t\tsources = HashMap.set(sources, url, digest(bytes))\n\t\t\t}\n\t\t\trecord(url, result.format)\n\t\t\treturn result\n\t\t},\n\t})\n\tconst files = (attempts: ReadonlyArray<Attempt>) => {\n\t\tlet files = HashMap.empty<string, FileVersion>()\n\t\tconst put = (url: string, node: string, resolution?: string) => {\n\t\t\tif (!String.startsWith(\"file:\")(url) || HashSet.has(dependencies, node))\n\t\t\t\treturn\n\t\t\tconst generation = version(node)!\n\t\t\tconst previous = HashMap.get(files, url)\n\t\t\tif (\n\t\t\t\tOption.exists(\n\t\t\t\t\tprevious,\n\t\t\t\t\t(previous) =>\n\t\t\t\t\t\tprevious.generation > generation ||\n\t\t\t\t\t\t(previous.generation === generation &&\n\t\t\t\t\t\t\tprevious.resolution !== undefined),\n\t\t\t\t)\n\t\t\t)\n\t\t\t\treturn\n\t\t\tfiles = HashMap.set(files, url, {\n\t\t\t\tgeneration,\n\t\t\t\tcontent: Option.getOrUndefined(HashMap.get(sources, node)),\n\t\t\t\t...(resolution === undefined ? {} : { resolution }),\n\t\t\t})\n\t\t}\n\t\tfor (const node of usedBy(attempts)) put(clean(node), node)\n\t\tfor (const attempt of resolutions(attempts))\n\t\t\tif (attempt.request !== undefined)\n\t\t\t\tput(\n\t\t\t\t\tattempt.request,\n\t\t\t\t\troot(attempt),\n\t\t\t\t\tpathToFileURL(fileURLToPath(attempt.url)).href,\n\t\t\t\t)\n\t\treturn files\n\t}\n\treturn {\n\t\tprepare,\n\t\tfiles,\n\t\tresolutions,\n\t\tinvalidated,\n\t\taffected: (attempt: Attempt, invalid: HashSet.HashSet<string>) =>\n\t\t\tHashSet.has(invalid, root(attempt)),\n\t\tfileRequest: (specifier: string) => fileRequest(specifier, base),\n\t\tunsupported: (generation: Generation, roots?: ReadonlyArray<string>) => {\n\t\t\tconst used =\n\t\t\t\troots === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: usedBy(Array.map(roots, (url) => ({ url, generation })))\n\t\t\treturn HashSet.fromIterable(\n\t\t\t\tArray.map(\n\t\t\t\t\tArray.filter(Array.fromIterable(dependencies), (node) =>\n\t\t\t\t\t\tused === undefined\n\t\t\t\t\t\t\t? version(node) === generation.id\n\t\t\t\t\t\t\t: HashSet.has(used, node),\n\t\t\t\t\t),\n\t\t\t\t\tclean,\n\t\t\t\t),\n\t\t\t)\n\t\t},\n\t\tcollect: (attempts: ReadonlyArray<Attempt>) => {\n\t\t\tconst used = usedBy(attempts)\n\t\t\tconst ownedViews = HashSet.fromIterable(\n\t\t\t\tArray.map(attempts, (attempt) => attempt.generation.id),\n\t\t\t)\n\t\t\tviews = HashMap.filter(\n\t\t\t\tviews,\n\t\t\t\t(_, id) =>\n\t\t\t\t\tid === revision ||\n\t\t\t\t\tHashSet.has(instantiatedViews, id) ||\n\t\t\t\t\tHashSet.has(ownedViews, id),\n\t\t\t)\n\t\t\t// Old code can reach any default route in its instantiated view, even\n\t\t\t// after every lease on that target closed. Preserve its complete graph,\n\t\t\t// source baseline and native capabilities until the session closes.\n\t\t\tconst keep = (node: string) =>\n\t\t\t\tHashSet.has(used, node) ||\n\t\t\t\tHashSet.has(instantiatedViews, version(node)!)\n\t\t\tretained = used\n\t\t\tsources = HashMap.filter(sources, (_, node) => keep(node))\n\t\t\tedges = HashMap.filter(edges, (_, node) => keep(node))\n\t\t\tdependencies = HashSet.filter(dependencies, keep)\n\t\t\treachCache = HashMap.filter(reachCache, (_, node) =>\n\t\t\t\tHashSet.has(used, node),\n\t\t\t)\n\t\t},\n\t\t// Internal counters support deterministic retention tests and external benchmarks.\n\t\tcounts: () => ({\n\t\t\tsources: HashMap.size(sources),\n\t\t\tedges: HashMap.size(edges),\n\t\t\tdependencies: HashSet.size(dependencies),\n\t\t\tviews: HashMap.size(views),\n\t\t}),\n\t\tstart: (generation: Generation, reload = false) => {\n\t\t\timporting = { generation, reload }\n\t\t},\n\t\tdiscard: () => {\n\t\t\timporting = undefined\n\t\t},\n\t\trequest: (specifier: string) => {\n\t\t\tresolved = undefined\n\t\t\treturn `${prefix}${importing!.generation.id}:${specifier}`\n\t\t},\n\t\tresolved: () => Option.fromUndefinedOr(resolved),\n\t\tclose: () => {\n\t\t\thooks.deregister()\n\t\t\tviews = HashMap.empty()\n\t\t\tsources = HashMap.empty()\n\t\t\tedges = HashMap.empty()\n\t\t\tdependencies = HashSet.empty()\n\t\t\treachCache = HashMap.empty()\n\t\t\tretained = HashSet.empty()\n\t\t\tinstantiatedViews = HashSet.empty()\n\t\t},\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"modules.js","names":[],"sources":["../../src/internal/modules.ts"],"sourcesContent":["// Node's synchronous module hooks have no Effect equivalent.\nimport { digest } from \"./digest\"\nimport { registerHooks } from \"node:module\"\nimport { fileURLToPath, pathToFileURL } from \"node:url\"\nimport {\n\tArray,\n\tChunk,\n\tHashMap,\n\tHashSet,\n\tOption,\n\tPredicate,\n\tSchema,\n\tString,\n} from \"effect\"\n\nexport class RestartRequired extends Schema.TaggedError<\n\tRestartRequired,\n\t{ readonly brand: unique symbol }\n>()(\"RestartRequired\", { url: Schema.String }) {}\n\n// Only a missing entry is disposable; missing dependencies still fail the reload.\nexport const isMissingEntry = (url: string, cause: unknown): boolean =>\n\tString.startsWith(\"file:\")(url) &&\n\tPredicate.hasProperty(cause, \"code\") &&\n\t((cause.code === \"ERR_MODULE_NOT_FOUND\" &&\n\t\tPredicate.hasProperty(cause, \"url\") &&\n\t\tcause.url === url) ||\n\t\t(cause.code === \"ENOENT\" &&\n\t\t\tPredicate.hasProperty(cause, \"path\") &&\n\t\t\tcause.path === fileURLToPath(url)))\n\n// Allocated only when a session starts; importing this module performs no I/O.\nlet sessions = 0\n\n/** A resolution view that allocates fresh URLs for new or invalidated instances. */\nexport interface Generation {\n\treadonly id: number\n}\n\n/** Digest of the bytes actually loaded by a concrete module instance. */\nexport interface FileVersion {\n\treadonly generation: number\n\treadonly content: string | undefined\n\treadonly resolution?: string\n}\n\nexport interface Attempt {\n\treadonly generation: Generation\n\treadonly url: string\n\treadonly request?: string\n}\n\ninterface Dependency extends Attempt {\n\treadonly node: string\n}\n\n/** Resolve local requests lexically; Node's cached physical target is a separate fact. */\nconst fileRequest = (\n\tspecifier: string,\n\tparent: string,\n): Option.Option<string> => {\n\tif (\n\t\t!Array.some([\"file:\", \"./\", \"../\", \"/\"], (prefix) =>\n\t\t\tString.startsWith(prefix)(specifier),\n\t\t)\n\t)\n\t\treturn Option.none()\n\tconst url = new URL(specifier, parent)\n\treturn url.protocol === \"file:\" ? Option.some(url.href) : Option.none()\n}\n\n/** A scoped Node hook. Mutable bindings bridge synchronous hooks to Effect. */\nexport const modules = (base: string, include: (url: string) => boolean) => {\n\tconst key = `graft-hmr-${++sessions}`\n\tconst prefix = `${key}:`\n\tconst rawPrefix = `${key}:raw:`\n\t/** What `request` produces: the generation that imports a specifier. */\n\tconst decodeRequest = Schema.decodeUnknownOption(\n\t\tSchema.TemplateLiteralParser([\n\t\t\tprefix,\n\t\t\tSchema.String.check(Schema.isPattern(/^\\d+$/)),\n\t\t\t\":\",\n\t\t\tSchema.String,\n\t\t]),\n\t)\n\tlet revision = 0\n\tlet importing:\n\t\t{ readonly generation: Generation; readonly reload: boolean } | undefined\n\tlet resolved: string | undefined\n\t// Resolution views contain only routing identities. Old code can execute after\n\t// replacement (including teardown), so these persistent maps live until close.\n\t// Cached instances also retain their facts: Node does not replay static imports.\n\t// Leases restrict observation, not the lifetime of old routing targets.\n\tlet views = HashMap.empty<number, HashMap.HashMap<string, string>>()\n\tlet edges = HashMap.empty<string, HashMap.HashMap<string, Dependency>>()\n\tlet sources = HashMap.empty<string, string>()\n\tlet dependencies = HashSet.empty<string>()\n\tlet reachCache = HashMap.empty<string, HashSet.HashSet<string>>()\n\tlet retained = HashSet.empty<string>()\n\tlet instantiatedViews = HashSet.empty<number>()\n\tconst clean = (url: string): string => {\n\t\tconst value = new URL(url)\n\t\tvalue.searchParams.delete(key)\n\t\treturn value.href\n\t}\n\tconst version = (url: string | undefined): number | undefined => {\n\t\tif (url === undefined) return undefined\n\t\tconst value = new URL(url).searchParams.get(key)\n\t\treturn value === null ? undefined : Number(value)\n\t}\n\tconst tag = (url: string, id: number) => {\n\t\tconst value = new URL(url)\n\t\tvalue.searchParams.set(key, String.String(id))\n\t\treturn value.href\n\t}\n\tconst route = (url: string, id: number): string =>\n\t\tOption.getOrElse(\n\t\t\tHashMap.get(\n\t\t\t\tOption.getOrElse(HashMap.get(views, id), HashMap.empty<string, string>),\n\t\t\t\turl,\n\t\t\t),\n\t\t\t() => tag(url, id),\n\t\t)\n\n\tconst root = (attempt: Attempt) => route(attempt.url, attempt.generation.id)\n\tconst children = (node: string) =>\n\t\tOption.getOrElse(\n\t\t\tHashMap.get(edges, node),\n\t\t\tHashMap.empty<string, Dependency>,\n\t\t)\n\tconst reachable = (node: string) => {\n\t\tconst cached = HashMap.get(reachCache, node)\n\t\tif (Option.isSome(cached)) return cached.value\n\t\tlet seen = HashSet.empty<string>()\n\t\tlet pending: Chunk.Chunk<string> = Chunk.of(node)\n\t\twhile (Chunk.isNonEmpty(pending)) {\n\t\t\tconst current = Chunk.headNonEmpty(pending)\n\t\t\tpending = Chunk.drop(pending, 1)\n\t\t\tif (HashSet.has(seen, current)) continue\n\t\t\tseen = HashSet.add(seen, current)\n\t\t\tfor (const edge of HashMap.values(children(current)))\n\t\t\t\tpending = Chunk.prepend(pending, edge.node)\n\t\t}\n\t\treachCache = HashMap.set(reachCache, node, seen)\n\t\treturn seen\n\t}\n\tconst usedBy = (attempts: ReadonlyArray<Attempt>) => {\n\t\tconst roots = HashSet.fromIterable(Array.map(attempts, root))\n\t\tlet used = HashSet.empty<string>()\n\t\tfor (const node of roots) used = HashSet.union(used, reachable(node))\n\t\treturn used\n\t}\n\tconst link = (parent: string, node: string, request?: string) => {\n\t\tif (\n\t\t\timporting === undefined &&\n\t\t\t!HashSet.has(retained, parent) &&\n\t\t\t!HashSet.has(instantiatedViews, version(parent)!)\n\t\t)\n\t\t\treturn\n\t\tretained = HashSet.add(retained, node)\n\t\tconst url = clean(node)\n\t\tconst edge = {\n\t\t\tnode,\n\t\t\turl,\n\t\t\tgeneration: { id: version(node)! },\n\t\t\t...(request === undefined ? {} : { request }),\n\t\t}\n\t\tconst previous = HashMap.get(children(parent), request ?? url)\n\t\tif (\n\t\t\tOption.exists(\n\t\t\t\tprevious,\n\t\t\t\t(previous) => previous.node === node && previous.request === request,\n\t\t\t)\n\t\t)\n\t\t\treturn\n\t\tedges = HashMap.set(\n\t\t\tedges,\n\t\t\tparent,\n\t\t\tHashMap.set(children(parent), request ?? url, edge),\n\t\t)\n\t\treachCache = HashMap.empty()\n\t}\n\tconst resolutions = (\n\t\tattempts: ReadonlyArray<Attempt>,\n\t): ReadonlyArray<Attempt> => [\n\t\t...Array.filter(attempts, (attempt) => attempt.request !== undefined),\n\t\t...Array.flatMap(Array.fromIterable(usedBy(attempts)), (node) =>\n\t\t\tArray.filter(\n\t\t\t\tHashMap.toValues(children(node)),\n\t\t\t\t(edge) => edge.request !== undefined,\n\t\t\t),\n\t\t),\n\t]\n\tconst unsupported = (url: string, format: string | null | undefined) =>\n\t\tformat === \"commonjs\" ||\n\t\tformat === \"commonjs-typescript\" ||\n\t\tformat === \"addon\" ||\n\t\tString.endsWith(\".node\")(new URL(url).pathname)\n\tconst requireRestart = (node: string) => {\n\t\tif (importing !== undefined || HashSet.has(retained, node))\n\t\t\tdependencies = HashSet.add(dependencies, node)\n\t\tif (importing?.reload === true && importing.generation.id === version(node))\n\t\t\tthrow RestartRequired.make({ url: clean(node) })\n\t}\n\tconst record = (node: string, format: string | null | undefined) => {\n\t\tif (unsupported(clean(node), format)) requireRestart(node)\n\t}\n\t// One reverse traversal closes cycles and all importers of every dirty instance.\n\tconst invalidated = (\n\t\tattempts: ReadonlyArray<Attempt>,\n\t\tdirty: HashSet.HashSet<string>,\n\t) => {\n\t\tconst used = usedBy(attempts)\n\t\tlet parents = HashMap.empty<string, HashSet.HashSet<string>>()\n\t\tlet pending = Chunk.empty<string>()\n\t\tfor (const node of used) {\n\t\t\tif (HashSet.has(dirty, clean(node)))\n\t\t\t\tpending = Chunk.prepend(pending, node)\n\t\t\tfor (const edge of HashMap.values(children(node))) {\n\t\t\t\tparents = HashMap.set(\n\t\t\t\t\tparents,\n\t\t\t\t\tedge.node,\n\t\t\t\t\tHashSet.add(\n\t\t\t\t\t\tOption.getOrElse(\n\t\t\t\t\t\t\tHashMap.get(parents, edge.node),\n\t\t\t\t\t\t\tHashSet.empty<string>,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnode,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\tif (edge.request !== undefined && HashSet.has(dirty, edge.request))\n\t\t\t\t\tpending = Chunk.prepend(pending, edge.node)\n\t\t\t}\n\t\t}\n\t\tfor (const attempt of attempts)\n\t\t\tif (attempt.request !== undefined && HashSet.has(dirty, attempt.request))\n\t\t\t\tpending = Chunk.prepend(pending, root(attempt))\n\t\tlet invalid = HashSet.empty<string>()\n\t\twhile (Chunk.isNonEmpty(pending)) {\n\t\t\tconst node = Chunk.headNonEmpty(pending)\n\t\t\tpending = Chunk.drop(pending, 1)\n\t\t\tif (HashSet.has(invalid, node)) continue\n\t\t\tinvalid = HashSet.add(invalid, node)\n\t\t\tfor (const parent of Option.getOrElse(\n\t\t\t\tHashMap.get(parents, node),\n\t\t\t\tHashSet.empty<string>,\n\t\t\t))\n\t\t\t\tpending = Chunk.prepend(pending, parent)\n\t\t}\n\t\treturn invalid\n\t}\n\tconst prepare = (\n\t\tattempts: ReadonlyArray<Attempt> = [],\n\t\tinvalid = HashSet.empty<string>(),\n\t): Generation => {\n\t\tconst id = ++revision\n\t\tconst seed = Array.reduce(attempts, 0, (id, attempt) =>\n\t\t\tMath.max(id, attempt.generation.id),\n\t\t)\n\t\tlet view = Option.getOrElse(\n\t\t\tHashMap.get(views, seed),\n\t\t\tHashMap.empty<string, string>,\n\t\t)\n\t\tconst used = usedBy(attempts)\n\t\t// Retain HAMT structure between views. Default routes need no stored entry;\n\t\t// only modules reused from older views need an explicit override.\n\t\tfor (const [url, node] of view)\n\t\t\tif (!HashSet.has(used, node) || HashSet.has(invalid, node))\n\t\t\t\tview = HashMap.remove(view, url)\n\t\tfor (const node of used) {\n\t\t\tif (HashSet.has(invalid, node)) continue\n\t\t\tconst url = clean(node)\n\t\t\tconst previous = HashMap.get(view, url)\n\t\t\tif (Option.isNone(previous) || version(previous.value)! < version(node)!)\n\t\t\t\tview = HashMap.set(view, url, node)\n\t\t}\n\n\t\tviews = HashMap.set(views, id, view)\n\t\treturn { id }\n\t}\n\tconst hooks = registerHooks({\n\t\tresolve(specifier, context, nextResolve) {\n\t\t\tif (String.startsWith(rawPrefix)(specifier))\n\t\t\t\treturn nextResolve(String.slice(rawPrefix.length)(specifier), {\n\t\t\t\t\t...context,\n\t\t\t\t\tparentURL: base,\n\t\t\t\t})\n\t\t\tconst parentNode = context.parentURL\n\t\t\tconst request = decodeRequest(specifier)\n\t\t\tconst entry = Option.isSome(request)\n\t\t\tconst id = Option.match(request, {\n\t\t\t\tonNone: () => version(context.parentURL),\n\t\t\t\tonSome: ([, id]) => Number(id),\n\t\t\t})\n\t\t\tif (id === undefined) return nextResolve(specifier, context)\n\t\t\tconst target = Option.match(request, {\n\t\t\t\tonNone: () => specifier,\n\t\t\t\tonSome: ([, , , target]) => target,\n\t\t\t})\n\t\t\tconst parent = entry ? base : clean(context.parentURL!)\n\t\t\tconst lexical = Option.getOrUndefined(fileRequest(target, parent))\n\t\t\tconst result = (() => {\n\t\t\t\ttry {\n\t\t\t\t\treturn nextResolve(target, { ...context, parentURL: parent })\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tPredicate.hasProperty(cause, \"url\") &&\n\t\t\t\t\t\ttypeof cause.url === \"string\" &&\n\t\t\t\t\t\tString.startsWith(\"file:\")(cause.url)\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (entry) resolved = cause.url\n\t\t\t\t\t\telse if (include(cause.url))\n\t\t\t\t\t\t\tlink(parentNode!, route(cause.url, id), lexical)\n\t\t\t\t\t}\n\t\t\t\t\tthrow cause\n\t\t\t\t}\n\t\t\t})()\n\t\t\tif (entry) resolved = result.url\n\t\t\tif (!entry && result.url === \"node:module\") {\n\t\t\t\tconst node = route(result.url, id)\n\t\t\t\tlink(parentNode!, node)\n\t\t\t\trequireRestart(node)\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!String.startsWith(\"file:\")(result.url) ||\n\t\t\t\t(!entry && !include(result.url))\n\t\t\t)\n\t\t\t\treturn result\n\t\t\tconst node = route(result.url, id)\n\t\t\tif (!entry) link(parentNode!, node, lexical)\n\t\t\tconst required = Array.contains(context.conditions, \"require\")\n\t\t\tif (required) requireRestart(node)\n\t\t\telse record(node, result.format)\n\t\t\treturn required || unsupported(result.url, result.format)\n\t\t\t\t? result\n\t\t\t\t: { ...result, url: node }\n\t\t},\n\t\tload(url, context, nextLoad) {\n\t\t\tconst id = version(url)\n\t\t\tif (id === undefined) return nextLoad(url, context)\n\t\t\tinstantiatedViews = HashSet.add(instantiatedViews, id)\n\t\t\tconst original = clean(url)\n\t\t\trecord(url, context.format)\n\t\t\tconst result = nextLoad(original, context)\n\t\t\tconst source = result.source\n\t\t\tif (source !== undefined && source !== null) {\n\t\t\t\tconst bytes =\n\t\t\t\t\ttypeof source === \"string\"\n\t\t\t\t\t\t? source\n\t\t\t\t\t\t: ArrayBuffer.isView(source)\n\t\t\t\t\t\t\t? new Uint8Array(\n\t\t\t\t\t\t\t\t\tsource.buffer,\n\t\t\t\t\t\t\t\t\tsource.byteOffset,\n\t\t\t\t\t\t\t\t\tsource.byteLength,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: new Uint8Array(source)\n\t\t\t\tif (importing !== undefined || HashSet.has(retained, url))\n\t\t\t\t\tsources = HashMap.set(sources, url, digest(bytes))\n\t\t\t}\n\t\t\trecord(url, result.format)\n\t\t\treturn result\n\t\t},\n\t})\n\tconst files = (attempts: ReadonlyArray<Attempt>) => {\n\t\tlet files = HashMap.empty<string, FileVersion>()\n\t\tconst put = (url: string, node: string, resolution?: string) => {\n\t\t\tif (!String.startsWith(\"file:\")(url) || HashSet.has(dependencies, node))\n\t\t\t\treturn\n\t\t\tconst generation = version(node)!\n\t\t\tconst previous = HashMap.get(files, url)\n\t\t\tif (\n\t\t\t\tOption.exists(\n\t\t\t\t\tprevious,\n\t\t\t\t\t(previous) =>\n\t\t\t\t\t\tprevious.generation > generation ||\n\t\t\t\t\t\t(previous.generation === generation &&\n\t\t\t\t\t\t\tprevious.resolution !== undefined),\n\t\t\t\t)\n\t\t\t)\n\t\t\t\treturn\n\t\t\tfiles = HashMap.set(files, url, {\n\t\t\t\tgeneration,\n\t\t\t\tcontent: Option.getOrUndefined(HashMap.get(sources, node)),\n\t\t\t\t...(resolution === undefined ? {} : { resolution }),\n\t\t\t})\n\t\t}\n\t\tfor (const node of usedBy(attempts)) put(clean(node), node)\n\t\tfor (const attempt of resolutions(attempts))\n\t\t\tif (attempt.request !== undefined)\n\t\t\t\tput(\n\t\t\t\t\tattempt.request,\n\t\t\t\t\troot(attempt),\n\t\t\t\t\tpathToFileURL(fileURLToPath(attempt.url)).href,\n\t\t\t\t)\n\t\treturn files\n\t}\n\treturn {\n\t\tprepare,\n\t\tfiles,\n\t\tresolutions,\n\t\tinvalidated,\n\t\taffected: (attempt: Attempt, invalid: HashSet.HashSet<string>) =>\n\t\t\tHashSet.has(invalid, root(attempt)),\n\t\tfileRequest: (specifier: string) => fileRequest(specifier, base),\n\t\tunsupported: (generation: Generation, roots?: ReadonlyArray<string>) => {\n\t\t\tconst used =\n\t\t\t\troots === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: usedBy(Array.map(roots, (url) => ({ url, generation })))\n\t\t\treturn HashSet.fromIterable(\n\t\t\t\tArray.map(\n\t\t\t\t\tArray.filter(Array.fromIterable(dependencies), (node) =>\n\t\t\t\t\t\tused === undefined\n\t\t\t\t\t\t\t? version(node) === generation.id\n\t\t\t\t\t\t\t: HashSet.has(used, node),\n\t\t\t\t\t),\n\t\t\t\t\tclean,\n\t\t\t\t),\n\t\t\t)\n\t\t},\n\t\tcollect: (attempts: ReadonlyArray<Attempt>) => {\n\t\t\tconst used = usedBy(attempts)\n\t\t\tconst ownedViews = HashSet.fromIterable(\n\t\t\t\tArray.map(attempts, (attempt) => attempt.generation.id),\n\t\t\t)\n\t\t\tviews = HashMap.filter(\n\t\t\t\tviews,\n\t\t\t\t(_, id) =>\n\t\t\t\t\tid === revision ||\n\t\t\t\t\tHashSet.has(instantiatedViews, id) ||\n\t\t\t\t\tHashSet.has(ownedViews, id),\n\t\t\t)\n\t\t\t// Old code can reach any default route in its instantiated view, even\n\t\t\t// after every lease on that target closed. Preserve its complete graph,\n\t\t\t// source baseline and native capabilities until the session closes.\n\t\t\tconst keep = (node: string) =>\n\t\t\t\tHashSet.has(used, node) ||\n\t\t\t\tHashSet.has(instantiatedViews, version(node)!)\n\t\t\tretained = used\n\t\t\tsources = HashMap.filter(sources, (_, node) => keep(node))\n\t\t\tedges = HashMap.filter(edges, (_, node) => keep(node))\n\t\t\tdependencies = HashSet.filter(dependencies, keep)\n\t\t\treachCache = HashMap.filter(reachCache, (_, node) =>\n\t\t\t\tHashSet.has(used, node),\n\t\t\t)\n\t\t},\n\t\t// Internal counters support deterministic retention tests and external benchmarks.\n\t\tcounts: () => ({\n\t\t\tsources: HashMap.size(sources),\n\t\t\tedges: HashMap.size(edges),\n\t\t\tdependencies: HashSet.size(dependencies),\n\t\t\tviews: HashMap.size(views),\n\t\t}),\n\t\tstart: (generation: Generation, reload = false) => {\n\t\t\timporting = { generation, reload }\n\t\t},\n\t\tdiscard: () => {\n\t\t\timporting = undefined\n\t\t},\n\t\trequest: (specifier: string) => {\n\t\t\tresolved = undefined\n\t\t\treturn `${prefix}${importing!.generation.id}:${specifier}`\n\t\t},\n\t\trawRequest: (specifier: string) => `${rawPrefix}${specifier}`,\n\t\tresolved: () => Option.fromUndefinedOr(resolved),\n\t\tclose: () => {\n\t\t\thooks.deregister()\n\t\t\tviews = HashMap.empty()\n\t\t\tsources = HashMap.empty()\n\t\t\tedges = HashMap.empty()\n\t\t\tdependencies = HashSet.empty()\n\t\t\treachCache = HashMap.empty()\n\t\t\tretained = HashSet.empty()\n\t\t\tinstantiatedViews = HashSet.empty()\n\t\t},\n\t}\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graftland/hmr",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.19.0"
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"vitest": "5.1.0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@graftland/graft": "0.2.0-beta.
|
|
36
|
+
"@graftland/graft": "0.2.0-beta.2"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsdown",
|
package/src/index.ts
CHANGED
|
@@ -82,6 +82,8 @@ export interface ImportOptions {
|
|
|
82
82
|
export interface Hmr {
|
|
83
83
|
/** Keeps imported entries registered until this HMR session closes. */
|
|
84
84
|
readonly importer: (specifier: string) => Promise<unknown>
|
|
85
|
+
/** Uses the application context and Node cache, without watching or replacing the module. */
|
|
86
|
+
readonly importModule: (specifier: string) => Effect.Effect<unknown, HmrError>
|
|
85
87
|
/** Registers an observation lease in observationScope, or the caller's scope when omitted. */
|
|
86
88
|
readonly importerScoped: (
|
|
87
89
|
specifier: string,
|
|
@@ -416,6 +418,19 @@ export const make = (
|
|
|
416
418
|
preserveExit,
|
|
417
419
|
)
|
|
418
420
|
|
|
421
|
+
const importModule: Hmr["importModule"] = (specifier) =>
|
|
422
|
+
serial(
|
|
423
|
+
checkOpen.pipe(
|
|
424
|
+
Effect.andThen(
|
|
425
|
+
Effect.tryPromise({
|
|
426
|
+
try: () => import(/* @vite-ignore */ hooks.rawRequest(specifier)),
|
|
427
|
+
catch: (cause) =>
|
|
428
|
+
HmrError.make({ stage: "import", specifier, cause }),
|
|
429
|
+
}),
|
|
430
|
+
),
|
|
431
|
+
),
|
|
432
|
+
)
|
|
433
|
+
|
|
419
434
|
const importerScoped: Hmr["importerScoped"] = (specifier, options) =>
|
|
420
435
|
options === undefined
|
|
421
436
|
? importWithLease(specifier)
|
|
@@ -433,11 +448,19 @@ export const make = (
|
|
|
433
448
|
),
|
|
434
449
|
)
|
|
435
450
|
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
451
|
+
const unsupportedAttempts = (attempts: ReadonlyArray<Attempt>) =>
|
|
452
|
+
Array.reduce(attempts, HashSet.empty<string>(), (all, attempt) =>
|
|
453
|
+
HashSet.union(
|
|
454
|
+
all,
|
|
455
|
+
hooks.unsupported(attempt.generation, [attempt.url]),
|
|
456
|
+
),
|
|
457
|
+
)
|
|
458
|
+
const unsupportedModules = Ref.get(owners).pipe(
|
|
459
|
+
Effect.map((owned) =>
|
|
460
|
+
unsupportedAttempts(
|
|
461
|
+
Array.getSomes(
|
|
462
|
+
Array.map(HashMap.toValues(owned), (owner) => owner.active),
|
|
463
|
+
),
|
|
441
464
|
),
|
|
442
465
|
),
|
|
443
466
|
)
|
|
@@ -583,10 +606,8 @@ export const make = (
|
|
|
583
606
|
({ url, plugin, leases }) => [url, { plugin, leases }] as const,
|
|
584
607
|
),
|
|
585
608
|
)
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
replacements,
|
|
589
|
-
)
|
|
609
|
+
// A missing entry still owns its running plugin until the last lease closes.
|
|
610
|
+
const next = HashMap.union(entries, replacements)
|
|
590
611
|
|
|
591
612
|
const pairs = Array.map(
|
|
592
613
|
candidates,
|
|
@@ -600,9 +621,12 @@ export const make = (
|
|
|
600
621
|
})
|
|
601
622
|
// A reused instance can acquire a native loading capability while the
|
|
602
623
|
// candidate imports. Observe it without throwing into concurrent old code.
|
|
603
|
-
const unsafe =
|
|
604
|
-
|
|
605
|
-
|
|
624
|
+
const unsafe = unsupportedAttempts(
|
|
625
|
+
Array.map(active, (attempt) =>
|
|
626
|
+
HashMap.has(replacements, attempt.url)
|
|
627
|
+
? { ...attempt, generation: candidate }
|
|
628
|
+
: attempt,
|
|
629
|
+
),
|
|
606
630
|
)
|
|
607
631
|
if (HashSet.size(unsafe) > 0)
|
|
608
632
|
return WatchResult.Skipped({
|
|
@@ -640,9 +664,14 @@ export const make = (
|
|
|
640
664
|
),
|
|
641
665
|
)
|
|
642
666
|
yield* Ref.set(state, { entries: next, generation: candidate })
|
|
643
|
-
yield* Ref.
|
|
644
|
-
|
|
645
|
-
|
|
667
|
+
yield* Ref.update(cached, (cached) =>
|
|
668
|
+
HashMap.union(
|
|
669
|
+
HashMap.filter(cached, (_, url) => HashMap.has(next, url)),
|
|
670
|
+
HashMap.map(replacements, (_, url) => ({
|
|
671
|
+
url,
|
|
672
|
+
generation: candidate,
|
|
673
|
+
})),
|
|
674
|
+
),
|
|
646
675
|
)
|
|
647
676
|
yield* Ref.set(retryDirty, HashSet.empty())
|
|
648
677
|
yield* Ref.set(retryAll, false)
|
|
@@ -676,6 +705,7 @@ export const make = (
|
|
|
676
705
|
return {
|
|
677
706
|
importer,
|
|
678
707
|
importerScoped,
|
|
708
|
+
importModule,
|
|
679
709
|
reload: reloadChanged(),
|
|
680
710
|
watch: (paths, watchOptions) =>
|
|
681
711
|
paths.length === 0
|
package/src/internal/changes.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
Cause,
|
|
10
10
|
Exit,
|
|
11
11
|
Effect,
|
|
12
|
+
Fiber,
|
|
12
13
|
FileSystem,
|
|
13
14
|
HashMap,
|
|
14
15
|
HashSet,
|
|
@@ -29,20 +30,46 @@ export type WithFiles = <A, E, R>(
|
|
|
29
30
|
const observeSource = <A, E, R>(source: Stream.Stream<A, E, R>) =>
|
|
30
31
|
Stream.callback<A, E, R>(
|
|
31
32
|
(queue) =>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
Effect.scoped(
|
|
34
|
+
Effect.uninterruptibleMask((restore) =>
|
|
35
|
+
Effect.gen(function* () {
|
|
36
|
+
const id = yield* Effect.withFiber((self) =>
|
|
37
|
+
Effect.succeed(self.id),
|
|
38
|
+
)
|
|
39
|
+
const producer = yield* Effect.forkScoped(
|
|
40
|
+
restore(
|
|
41
|
+
source.pipe(
|
|
42
|
+
Stream.runForEachArray((values) =>
|
|
43
|
+
Queue.offerAll(queue, values),
|
|
44
|
+
),
|
|
45
|
+
Effect.scoped,
|
|
46
|
+
),
|
|
47
|
+
),
|
|
48
|
+
)
|
|
49
|
+
const waiting = yield* Effect.exit(restore(Fiber.await(producer)))
|
|
50
|
+
if (Exit.isFailure(waiting)) yield* Fiber.interrupt(producer)
|
|
51
|
+
const exit = yield* Fiber.await(producer)
|
|
52
|
+
// Only our own cancellation is expected; nested finalizers may contribute other interrupts.
|
|
53
|
+
if (
|
|
54
|
+
Exit.isFailure(exit) &&
|
|
55
|
+
Cause.hasInterrupts(exit.cause) &&
|
|
56
|
+
!(
|
|
57
|
+
Exit.isFailure(waiting) &&
|
|
58
|
+
Array.every(
|
|
59
|
+
exit.cause.reasons,
|
|
60
|
+
(reason) =>
|
|
61
|
+
reason._tag === "Interrupt" && reason.fiberId === id,
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
yield* Effect.logError(
|
|
40
66
|
"Native watcher failed during cancellation",
|
|
41
67
|
exit.cause,
|
|
42
68
|
)
|
|
43
|
-
|
|
69
|
+
yield* exit
|
|
70
|
+
yield* Queue.end(queue)
|
|
71
|
+
}),
|
|
44
72
|
),
|
|
45
|
-
Effect.andThen(Queue.end(queue)),
|
|
46
73
|
),
|
|
47
74
|
{ bufferSize: 16 },
|
|
48
75
|
)
|
package/src/internal/modules.ts
CHANGED
|
@@ -73,6 +73,8 @@ const fileRequest = (
|
|
|
73
73
|
export const modules = (base: string, include: (url: string) => boolean) => {
|
|
74
74
|
const key = `graft-hmr-${++sessions}`
|
|
75
75
|
const prefix = `${key}:`
|
|
76
|
+
const rawPrefix = `${key}:raw:`
|
|
77
|
+
/** What `request` produces: the generation that imports a specifier. */
|
|
76
78
|
const decodeRequest = Schema.decodeUnknownOption(
|
|
77
79
|
Schema.TemplateLiteralParser([
|
|
78
80
|
prefix,
|
|
@@ -278,6 +280,11 @@ export const modules = (base: string, include: (url: string) => boolean) => {
|
|
|
278
280
|
}
|
|
279
281
|
const hooks = registerHooks({
|
|
280
282
|
resolve(specifier, context, nextResolve) {
|
|
283
|
+
if (String.startsWith(rawPrefix)(specifier))
|
|
284
|
+
return nextResolve(String.slice(rawPrefix.length)(specifier), {
|
|
285
|
+
...context,
|
|
286
|
+
parentURL: base,
|
|
287
|
+
})
|
|
281
288
|
const parentNode = context.parentURL
|
|
282
289
|
const request = decodeRequest(specifier)
|
|
283
290
|
const entry = Option.isSome(request)
|
|
@@ -454,6 +461,7 @@ export const modules = (base: string, include: (url: string) => boolean) => {
|
|
|
454
461
|
resolved = undefined
|
|
455
462
|
return `${prefix}${importing!.generation.id}:${specifier}`
|
|
456
463
|
},
|
|
464
|
+
rawRequest: (specifier: string) => `${rawPrefix}${specifier}`,
|
|
457
465
|
resolved: () => Option.fromUndefinedOr(resolved),
|
|
458
466
|
close: () => {
|
|
459
467
|
hooks.deregister()
|