@graftland/hmr 0.2.0-beta.0 → 0.2.0-beta.1

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/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 watchers and checks loaded module contents once\n\t * per second 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\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 = Ref.get(owners).pipe(\n\t\t\tEffect.flatMap((owners) =>\n\t\t\t\tEffect.forEach(\n\t\t\t\t\thooks.resolutions(\n\t\t\t\t\t\tArray.flatMap(HashMap.toValues(owners), (owner) =>\n\t\t\t\t\t\t\tArray.getSomes([owner.active, owner.pending]),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t\tchangedResolution,\n\t\t\t\t),\n\t\t\t),\n\t\t\tEffect.map((changes) =>\n\t\t\t\tArray.fromIterable(HashSet.fromIterable(Array.getSomes(changes))),\n\t\t\t),\n\t\t)\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\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(Effect.ensuring(Effect.sync(hooks.discard))),\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}),\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 reload = serial(\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* checkOpen\n\t\t\t\tconst changed = yield* changedResolutions\n\t\t\t\tif (changed.length > 0)\n\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\tmodules: changed,\n\t\t\t\t\t})\n\t\t\t\tconst { entries } = yield* Ref.get(state)\n\t\t\t\tconst unsupported = yield* unsupportedModules\n\t\t\t\tif (HashSet.size(unsupported) > 0)\n\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\tmodules: Array.fromIterable(unsupported),\n\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t})\n\t\t\t\t// Advance even without entries so retries bypass cached failed imports.\n\t\t\t\tconst candidate = hooks.prepare()\n\t\t\t\thooks.start(candidate, true)\n\t\t\t\treturn yield* Effect.gen(function* () {\n\t\t\t\t\tconst loaded = yield* Effect.forEach(entries, ([url, previous]) =>\n\t\t\t\t\t\tRef.update(\n\t\t\t\t\t\t\towners,\n\t\t\t\t\t\t\tHashMap.map((owner, token) =>\n\t\t\t\t\t\t\t\tHashSet.has(previous.leases, token)\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t...owner,\n\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...attempt,\n\t\t\t\t\t\t\t\t\t\t\t\turl,\n\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})),\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: owner,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t).pipe(\n\t\t\t\t\t\t\tEffect.andThen(load(url)),\n\t\t\t\t\t\t\tEffect.map((entry) =>\n\t\t\t\t\t\t\t\tOption.some({\n\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\tprevious: previous.plugin,\n\t\t\t\t\t\t\t\t\tleases: previous.leases,\n\t\t\t\t\t\t\t\t\tplugin: entry.plugin,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tEffect.catchIf(\n\t\t\t\t\t\t\t\t(error) =>\n\t\t\t\t\t\t\t\t\terror.stage === \"import\" && isMissingEntry(url, error.cause),\n\t\t\t\t\t\t\t\t() => Effect.succeedNone,\n\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\tconst candidates = Array.getSomes(loaded)\n\t\t\t\t\tconst alternatives = Array.reduce(\n\t\t\t\t\t\tcandidates,\n\t\t\t\t\t\tHashMap.empty<Plugin.Plugin, HashSet.HashSet<Plugin.Plugin>>(),\n\t\t\t\t\t\t(groups, { previous, plugin }) =>\n\t\t\t\t\t\t\tHashMap.set(\n\t\t\t\t\t\t\t\tgroups,\n\t\t\t\t\t\t\t\tprevious,\n\t\t\t\t\t\t\t\tHashSet.add(\n\t\t\t\t\t\t\t\t\tOption.getOrElse(\n\t\t\t\t\t\t\t\t\t\tHashMap.get(groups, previous),\n\t\t\t\t\t\t\t\t\t\tHashSet.empty<Plugin.Plugin>,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tplugin,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\tconst ambiguous = Array.filter(candidates, ({ previous }) =>\n\t\t\t\t\t\tOption.exists(\n\t\t\t\t\t\t\tHashMap.get(alternatives, previous),\n\t\t\t\t\t\t\t(plugins) => HashSet.size(plugins) > 1,\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\tif (ambiguous.length > 0)\n\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\treason: \"ambiguous-exports\",\n\t\t\t\t\t\t\tmodules: Array.map(ambiguous, ({ url }) => url),\n\t\t\t\t\t\t})\n\t\t\t\t\tconst next = HashMap.fromIterable(\n\t\t\t\t\t\tArray.map(\n\t\t\t\t\t\t\tcandidates,\n\t\t\t\t\t\t\t({ url, plugin, leases }) => [url, { plugin, leases }] as const,\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\tconst pairs = Array.map(\n\t\t\t\t\t\tcandidates,\n\t\t\t\t\t\t({ previous, plugin }) => [previous, plugin] as const,\n\t\t\t\t\t)\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 replacement = yield* Graft.replace(pairs).pipe(\n\t\t\t\t\t\tEffect.provideService(Graft.Graft, graft),\n\t\t\t\t\t\tEffect.result,\n\t\t\t\t\t)\n\t\t\t\t\tif (Result.isFailure(replacement))\n\t\t\t\t\t\treturn WatchResult.Skipped({\n\t\t\t\t\t\t\treason: \"identity-conflict\",\n\t\t\t\t\t\t\tmodules: Array.filterMap(candidates, ({ url }, index) =>\n\t\t\t\t\t\t\t\tArray.contains(replacement.failure.indices, index)\n\t\t\t\t\t\t\t\t\t? Result.succeed(url)\n\t\t\t\t\t\t\t\t\t: Result.fail(undefined),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t})\n\t\t\t\t\tyield* Ref.update(owners, (owners) =>\n\t\t\t\t\t\tArray.reduce(candidates, owners, (owners, { url, leases }) =>\n\t\t\t\t\t\t\tHashMap.map(owners, (owner, token) =>\n\t\t\t\t\t\t\t\tHashSet.has(leases, token)\n\t\t\t\t\t\t\t\t\t? {\n\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...attempt,\n\t\t\t\t\t\t\t\t\t\t\t\turl,\n\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})),\n\t\t\t\t\t\t\t\t\t\t\tpending: Option.none(),\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: owner,\n\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\tyield* Ref.set(state, { entries: next, generation: candidate })\n\t\t\t\t\treturn WatchResult.Reloaded({\n\t\t\t\t\t\tentries: Array.fromIterable(HashMap.keys(next)),\n\t\t\t\t\t})\n\t\t\t\t}).pipe(\n\t\t\t\t\tEffect.catchIf(\n\t\t\t\t\t\t(error): error is HmrError & { readonly cause: RestartRequired } =>\n\t\t\t\t\t\t\tSchema.is(RestartRequired)(error.cause),\n\t\t\t\t\t\t(error) =>\n\t\t\t\t\t\t\tEffect.succeed(\n\t\t\t\t\t\t\t\tWatchResult.Skipped({\n\t\t\t\t\t\t\t\t\tmodules: Array.fromIterable(\n\t\t\t\t\t\t\t\t\t\tHashSet.add(hooks.unsupported(candidate), error.cause.url),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\treason: \"restart-required\",\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.ensuring(Effect.sync(hooks.discard)),\n\t\t\t\t)\n\t\t\t}),\n\t\t)\n\t\treturn {\n\t\t\timporter,\n\t\t\timporterScoped,\n\t\t\treload,\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// Hold ownership through the reads, so release cannot leave\n\t\t\t\t\t\t\t\t\t// an in-flight snapshot reading a retired path.\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.debounce(watchOptions?.debounce ?? \"50 millis\"),\n\t\t\t\t\t\t\tStream.mapEffect(() =>\n\t\t\t\t\t\t\t\tEffect.map(Effect.exit(reload), (exit): WatchResult =>\n\t\t\t\t\t\t\t\t\tExit.isSuccess(exit)\n\t\t\t\t\t\t\t\t\t\t? exit.value\n\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/** 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,11 +1,13 @@
1
+ import { digest } from "./digest.js";
1
2
  import { fileURLToPath, pathToFileURL } from "node:url";
2
- import { Array, Cause, Effect, Exit, FileSystem, HashMap, Option, Queue, Ref, Stream, String } from "effect";
3
- import { resolve } from "node:path";
4
- import { Base64 } from "effect/encoding";
3
+ import { Array, Cause, Clock, Effect, Equal, Exit, FileSystem, HashMap, HashSet, Option, Queue, Ref, Stream, String } from "effect";
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
7
  const observeSource = (source) => Stream.callback((queue) => source.pipe(Stream.runForEachArray((values) => Queue.offerAll(queue, values)), Effect.scoped, Effect.onExit((exit) => Exit.isFailure(exit) && Cause.hasInterrupts(exit.cause) && !Cause.hasInterruptsOnly(exit.cause) ? Effect.logError("Native watcher failed during cancellation", exit.cause) : Effect.void), Effect.andThen(Queue.end(queue))), { bufferSize: 16 });
8
- /** Reconcile loaded modules because native watchers can silently miss events. */
8
+ /** Compare immutable observation tokens again after filesystem I/O releases the lock. */
9
+ const sameVersion = (a, b) => a.generation === b.generation && a.content === b.content && a.resolution === b.resolution;
10
+ /** Reconcile owned modules because native watchers can silently miss events. */
9
11
  const changes = (withFiles, paths, options) => Stream.unwrap(Effect.gen(function* () {
10
12
  if (paths.length === 0) return Stream.empty;
11
13
  const fs = yield* FileSystem.FileSystem;
@@ -19,40 +21,71 @@ const changes = (withFiles, paths, options) => Stream.unwrap(Effect.gen(function
19
21
  };
20
22
  }));
21
23
  const accepted = (path) => options?.filter?.(path) ?? true;
22
- const watched = (url) => accepted(fileURLToPath(url)) && Array.some(roots, ({ urls }) => Array.some(urls, (root) => {
23
- const directory = String.endsWith("/")(root) ? root : `${root}/`;
24
- return fileURLToPath(url) === fileURLToPath(root) || (options?.recursive === true ? String.startsWith(directory)(url) : new URL(".", url).href === directory);
24
+ const watched = (url) => accepted(fileURLToPath(url)) && Array.some(roots, ({ urls, directory }) => Array.some(urls, (root) => {
25
+ const prefix = String.endsWith("/")(root) ? root : `${root}/`;
26
+ return fileURLToPath(url) === fileURLToPath(root) || directory && (options?.recursive === true ? String.startsWith(prefix)(url) : new URL(".", url).href === prefix);
25
27
  }));
26
- const snapshot = withFiles((loaded) => Effect.forEach(Array.filter(Array.fromIterable(loaded), ([url]) => watched(url)), ([url, baseline]) => Effect.gen(function* () {
27
- const resolution = baseline.resolution === void 0 ? void 0 : yield* fs.realPath(fileURLToPath(url)).pipe(Effect.map((path) => pathToFileURL(path).href), Effect.catchIf((error) => error.reason._tag === "NotFound", () => Effect.undefined));
28
- return {
29
- url,
30
- baseline,
31
- content: yield* fs.readFile(fileURLToPath(url)).pipe(Effect.map(Base64.encode), Effect.catchIf((error) => error.reason._tag === "NotFound", () => Effect.undefined)),
32
- resolution
33
- };
34
- })));
28
+ const files = withFiles((loaded) => Effect.succeed(HashMap.filter(loaded, (_, url) => watched(url))));
29
+ const missing = (effect) => effect.pipe(Effect.catchIf((error) => error.reason._tag === "NotFound", () => Effect.undefined));
30
+ const existingDirectory = (path) => Effect.gen(function* () {
31
+ return (yield* missing(fs.stat(path)))?.type === "Directory" || dirname(path) === path ? path : yield* existingDirectory(dirname(path));
32
+ });
33
+ const directories = Effect.gen(function* () {
34
+ const loaded = yield* files;
35
+ const requested = HashSet.fromIterable([...Array.map(roots, (root) => root.directory ? root.path : dirname(root.path)), ...Array.map(Array.fromIterable(HashMap.keys(loaded)), (url) => dirname(fileURLToPath(url)))]);
36
+ const existing = yield* Effect.forEach(requested, existingDirectory, { concurrency: 8 });
37
+ return HashSet.fromIterable(existing);
38
+ });
39
+ const dirty = yield* Ref.make(HashSet.empty());
40
+ const native = Stream.tick("1 second").pipe(Stream.mapEffect(() => directories), Stream.changesWith((a, b) => Equal.equals(a, b)), Stream.switchMap((directories) => Stream.mergeAll(Array.map(Array.fromIterable(directories), (directory) => fs.watch(directory, {
41
+ ...options,
42
+ recursive: false
43
+ }).pipe(observeSource, Stream.map((event) => resolve(directory, event.path || ".")))), { concurrency: "unbounded" })), Stream.tap((path) => Ref.update(dirty, HashSet.add(path))), Stream.debounce(options?.debounce ?? "50 millis"), Stream.mapEffect(() => Ref.getAndSet(dirty, HashSet.empty())));
35
44
  const observed = yield* Ref.make(HashMap.empty());
36
- return Stream.mergeAll([...Array.map(roots, (root) => fs.watch(root.path, options).pipe(observeSource, Stream.filter((event) => accepted(root.directory ? resolve(root.path, event.path) : root.path)), Stream.map(() => true))), Stream.tick("1 second").pipe(Stream.drop(1), Stream.map(() => false))], { concurrency: "unbounded" }).pipe(Stream.mapEffect((event) => snapshot.pipe(Effect.flatMap((current) => Ref.modify(observed, (before) => [event || Array.some(current, ({ url, baseline, content, resolution }) => {
37
- const expected = Option.match(HashMap.get(before, url), {
38
- onNone: () => ({
39
- content: baseline.content,
40
- resolution: baseline.resolution
41
- }),
42
- onSome: (seen) => {
43
- const same = seen.baseline.generation === baseline.generation && seen.baseline.content === baseline.content && seen.baseline.resolution === baseline.resolution;
44
- return {
45
- content: baseline.content === void 0 || same ? seen.content : baseline.content,
46
- resolution: same ? seen.resolution : baseline.resolution
47
- };
45
+ const scan = (events) => Effect.gen(function* () {
46
+ const loaded = yield* files;
47
+ const before = yield* Ref.get(observed);
48
+ const now = yield* Clock.currentTimeMillis;
49
+ const selected = Array.filter(Array.fromIterable(loaded), ([url]) => events === void 0 || Array.some(Array.fromIterable(events), (path) => {
50
+ const file = fileURLToPath(url);
51
+ return file === path || String.startsWith(`${path}/`)(file);
52
+ }));
53
+ const checked = yield* Effect.forEach(selected, ([url, baseline]) => Effect.gen(function* () {
54
+ const path = fileURLToPath(url);
55
+ const previous = Option.getOrUndefined(HashMap.get(before, url));
56
+ const info = yield* missing(fs.stat(path));
57
+ const stat = info === void 0 ? "missing" : `${info.size}:${Option.getOrUndefined(info.mtime)?.getTime()}:${Option.getOrUndefined(info.ino)}`;
58
+ const resolution = baseline.resolution === void 0 ? void 0 : yield* missing(fs.realPath(path)).pipe(Effect.map((path) => path === void 0 ? void 0 : pathToFileURL(path).href));
59
+ const audit = events !== void 0 || previous === void 0 || !sameVersion(previous.baseline, baseline) || previous.stat !== stat || now - previous.checked >= 1e4;
60
+ const content = audit ? yield* missing(fs.readFile(path)).pipe(Effect.map((bytes) => bytes === void 0 ? void 0 : digest(bytes))) : previous.content;
61
+ const expected = previous === void 0 ? baseline : {
62
+ content: baseline.content === void 0 || sameVersion(previous.baseline, baseline) ? previous.content : baseline.content,
63
+ resolution: sameVersion(previous.baseline, baseline) ? previous.resolution : baseline.resolution
64
+ };
65
+ return {
66
+ url,
67
+ observation: {
68
+ baseline,
69
+ content,
70
+ resolution,
71
+ stat,
72
+ checked: audit ? now : previous.checked
73
+ },
74
+ changed: expected.content !== content || expected.resolution !== resolution
75
+ };
76
+ }), { concurrency: 8 });
77
+ return yield* withFiles((current) => Ref.modify(observed, (seen) => {
78
+ let next = HashMap.filter(seen, (_, url) => HashMap.has(current, url));
79
+ let changed = HashSet.empty();
80
+ for (const { url, observation, changed: differs } of checked) {
81
+ if (!Option.exists(HashMap.get(current, url), (version) => sameVersion(version, observation.baseline))) continue;
82
+ next = HashMap.set(next, url, observation);
83
+ if (differs) changed = HashSet.add(changed, url);
48
84
  }
49
- });
50
- return expected.content !== content || expected.resolution !== resolution;
51
- }), HashMap.fromIterable(Array.map(current, ({ url, baseline, content, resolution }) => [url, {
52
- baseline,
53
- content,
54
- resolution
55
- }]))])))), Stream.filter(Boolean), Stream.map(() => void 0));
85
+ return [changed, next];
86
+ }));
87
+ });
88
+ return Stream.merge(native, Stream.tick("1 second").pipe(Stream.drop(1), Stream.map(() => void 0))).pipe(Stream.mapEffect(scan), Stream.filter((changed) => HashSet.size(changed) > 0));
56
89
  }));
57
90
  export { changes };
58
91
 
@@ -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 { resolve } from \"node:path\"\nimport type { FileVersion } from \"./modules\"\nimport type { WatchOptions } from \"../index\"\nimport { Base64 } from \"effect/encoding\"\nimport { fileURLToPath, pathToFileURL } from \"node:url\"\nimport {\n\tArray,\n\tCause,\n\tExit,\n\tEffect,\n\tFileSystem,\n\tHashMap,\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/** Reconcile loaded 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 }) =>\n\t\t\t\t\tArray.some(urls, (root) => {\n\t\t\t\t\t\tconst directory = 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(options?.recursive === true\n\t\t\t\t\t\t\t\t? String.startsWith(directory)(url)\n\t\t\t\t\t\t\t\t: new URL(\".\", url).href === directory)\n\t\t\t\t\t\t)\n\t\t\t\t\t}),\n\t\t\t\t)\n\n\t\t\tconst snapshot = withFiles((loaded) =>\n\t\t\t\tEffect.forEach(\n\t\t\t\t\tArray.filter(Array.fromIterable(loaded), ([url]) => watched(url)),\n\t\t\t\t\t([url, baseline]) =>\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\tconst resolution =\n\t\t\t\t\t\t\t\tbaseline.resolution === undefined\n\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t: yield* fs.realPath(fileURLToPath(url)).pipe(\n\t\t\t\t\t\t\t\t\t\t\tEffect.map((path) => pathToFileURL(path).href),\n\t\t\t\t\t\t\t\t\t\t\tEffect.catchIf(\n\t\t\t\t\t\t\t\t\t\t\t\t(error) => error.reason._tag === \"NotFound\",\n\t\t\t\t\t\t\t\t\t\t\t\t() => Effect.undefined,\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\tconst content = yield* fs.readFile(fileURLToPath(url)).pipe(\n\t\t\t\t\t\t\t\tEffect.map(Base64.encode),\n\t\t\t\t\t\t\t\t// Deletion is a change; other I/O failures belong to the consumer.\n\t\t\t\t\t\t\t\tEffect.catchIf(\n\t\t\t\t\t\t\t\t\t(error) => error.reason._tag === \"NotFound\",\n\t\t\t\t\t\t\t\t\t() => Effect.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\treturn { url, baseline, content, resolution }\n\t\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t)\n\t\t\t// An observation acknowledges disk bytes only for the import version\n\t\t\t// it reconciled. A new attempt must be checked against its own bytes.\n\t\t\tconst observed = yield* Ref.make(\n\t\t\t\tHashMap.empty<\n\t\t\t\t\tstring,\n\t\t\t\t\t{\n\t\t\t\t\t\treadonly baseline: FileVersion\n\t\t\t\t\t\treadonly content: string | undefined\n\t\t\t\t\t\treadonly resolution: string | undefined\n\t\t\t\t\t}\n\t\t\t\t>(),\n\t\t\t)\n\t\t\treturn Stream.mergeAll(\n\t\t\t\t[\n\t\t\t\t\t...Array.map(roots, (root) =>\n\t\t\t\t\t\tfs.watch(root.path, options).pipe(\n\t\t\t\t\t\t\tobserveSource,\n\t\t\t\t\t\t\tStream.filter((event) =>\n\t\t\t\t\t\t\t\taccepted(\n\t\t\t\t\t\t\t\t\troot.directory ? resolve(root.path, event.path) : root.path,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tStream.map(() => true),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t\tStream.tick(\"1 second\").pipe(\n\t\t\t\t\t\tStream.drop(1),\n\t\t\t\t\t\tStream.map(() => false),\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t\t{ concurrency: \"unbounded\" },\n\t\t\t).pipe(\n\t\t\t\t// One consumer serializes snapshots from events and polling. A native\n\t\t\t\t// event also advances the baseline, avoiding a second reload on the next tick.\n\t\t\t\tStream.mapEffect((event) =>\n\t\t\t\t\tsnapshot.pipe(\n\t\t\t\t\t\tEffect.flatMap((current) =>\n\t\t\t\t\t\t\tRef.modify(observed, (before) => [\n\t\t\t\t\t\t\t\tevent ||\n\t\t\t\t\t\t\t\t\tArray.some(\n\t\t\t\t\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t\t\t\t\t({ url, baseline, content, resolution }) => {\n\t\t\t\t\t\t\t\t\t\t\tconst expected = Option.match(HashMap.get(before, url), {\n\t\t\t\t\t\t\t\t\t\t\t\tonNone: () => ({\n\t\t\t\t\t\t\t\t\t\t\t\t\tcontent: baseline.content,\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolution: baseline.resolution,\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\tonSome: (seen) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst same =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tseen.baseline.generation === baseline.generation &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tseen.baseline.content === baseline.content &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tseen.baseline.resolution === baseline.resolution\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Failed attempts without source bytes keep the last\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// observation acknowledged until another save.\n\t\t\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\t\t\tbaseline.content === undefined || same\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? seen.content\n\t\t\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\t\t\tresolution: same\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? seen.resolution\n\t\t\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\t\t}\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\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\texpected.content !== content ||\n\t\t\t\t\t\t\t\t\t\t\t\texpected.resolution !== resolution\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\tHashMap.fromIterable(\n\t\t\t\t\t\t\t\t\tArray.map(\n\t\t\t\t\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t\t\t\t\t({ url, baseline, content, resolution }) =>\n\t\t\t\t\t\t\t\t\t\t\t[url, { baseline, content, resolution }] as const,\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\t\t\t),\n\t\t\t\t),\n\t\t\t\tStream.filter(Boolean),\n\t\t\t\tStream.map(() => undefined),\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\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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"}
@@ -0,0 +1,6 @@
1
+ import { createHash } from "node:crypto";
2
+ // src/internal/digest.ts
3
+ const digest = (bytes) => createHash("sha256").update(bytes).digest("hex");
4
+ export { digest };
5
+
6
+ //# sourceMappingURL=digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.js","names":[],"sources":["../../src/internal/digest.ts"],"sourcesContent":["// @effect-diagnostics-next-line nodeBuiltinImport:off -- synchronous Node hooks need a synchronous digest of the bytes actually loaded\nimport { createHash } from \"node:crypto\"\n\nexport const digest = (bytes: string | Uint8Array): string =>\n\tcreateHash(\"sha256\").update(bytes).digest(\"hex\")\n"],"mappings":";;AAGA,MAAa,UAAU,UACtB,WAAW,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,KAAK"}