@async/framework 0.10.0 → 0.10.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/browser.min.js CHANGED
@@ -1 +1 @@
1
- const __asyncSignalModule = (() => { const asyncSignalKind = Symbol.for("@async/framework.asyncSignal"); function asyncSignal(id, fn) { if (typeof id !== "string" || id.length === 0) { throw new TypeError("asyncSignal(id, fn) requires a non-empty string id."); } if (typeof fn !== "function") { throw new TypeError("asyncSignal(id, fn) requires a function."); } let value; let loading = false; let error = null; let status = "idle"; let version = 0; let registry; let registeredId = id; let activeController; let activeAbort; const subscribers = new Set(); const dependencyCleanups = new Set(); const state = { [asyncSignalKind]: true, kind: "async-signal", get id() { return registeredId; }, get value() { return value; }, get loading() { return loading; }, get error() { return error; }, get status() { return status; }, get version() { return version; }, set(nextValue) { value = nextValue; loading = false; error = null; status = "ready"; notify(); return value; }, refresh() { if (!registry) { throw new Error(`Async signal "${registeredId}" is not registered.`); } if (activeAbort && !activeAbort.aborted) { activeAbort.cancel(new Error(`Async signal "${registeredId}" refreshed.`)); } const runVersion = version + 1; version = runVersion; loading = true; error = null; status = "loading"; const controller = new AbortController(); activeController = controller; activeAbort = controller.signal; attachCancel(activeAbort, controller); notify(); const context = { signals: registry, id: registeredId, get server() { const context = registry._context?.() ?? {}; const server = context.server; if (typeof server?._withContext === "function") { return server._withContext({ signals: registry, router: context.router, loader: context.loader, cache: context.cache, abort: activeAbort, scheduler: context.scheduler }); } return server; }, get router() { return registry._context?.().router; }, get loader() { return registry._context?.().loader; }, get cache() { return registry._context?.().cache; }, get scheduler() { return registry._context?.().scheduler; }, get version() { return runVersion; }, get abort() { return activeAbort; }, refresh() { return state.refresh(); } }; let outcome; try { outcome = registry._collectDependencies(() => fn.call(context)); } catch (cause) { finishError(runVersion, cause); return Promise.reject(cause); } syncDependencies(outcome.dependencies); return Promise.resolve(outcome.value).then( (nextValue) => { if (!isCurrent(runVersion)) { return value; } value = nextValue; loading = false; error = null; status = "ready"; notify(); return value; }, (cause) => { if (!isCurrent(runVersion)) { return value; } if (activeAbort?.aborted) { loading = false; status = value === undefined ? "idle" : "ready"; notify(); return value; } finishError(runVersion, cause); return value; } ); }, cancel(reason) { if (activeAbort && !activeAbort.aborted) { activeAbort.cancel(reason); } }, subscribe(fn) { if (typeof fn !== "function") { throw new TypeError("subscribe(fn) requires a function."); } subscribers.add(fn); return () => subscribers.delete(fn); }, snapshot() { return { value, loading, error, status, version }; }, _bindRegistry(nextRegistry, nextId) { registry = nextRegistry; registeredId = nextId; const start = () => { if (registry === nextRegistry && status === "idle") { state.refresh(); } }; const scheduler = registry._context?.().scheduler; if (scheduler) { scheduler.enqueue("async", start, { scope: registeredId, key: `asyncSignal:${registeredId}:initial` }); } else { queueMicrotask(start); } }, _dispose() { state.cancel(new Error(`Async signal "${registeredId}" disposed.`)); for (const cleanup of dependencyCleanups) { cleanup(); } dependencyCleanups.clear(); subscribers.clear(); } }; function finishError(runVersion, cause) { if (!isCurrent(runVersion)) { return; } loading = false; error = cause; status = "error"; notify(); } function isCurrent(runVersion) { return runVersion === version && activeController?.signal === activeAbort; } function syncDependencies(dependencies) { for (const cleanup of dependencyCleanups) { cleanup(); } dependencyCleanups.clear(); for (const dependency of dependencies) { const dependencyId = String(dependency).split(".")[0]; if (dependencyId && dependencyId !== registeredId) { dependencyCleanups.add(registry.subscribe(dependency, () => scheduleRefresh())); } } } function scheduleRefresh() { if (activeAbort && !activeAbort.aborted) { activeAbort.cancel(new Error(`Async signal "${registeredId}" dependency changed.`)); } const scheduler = registry?._context?.().scheduler; if (!scheduler) { state.refresh(); return; } scheduler.enqueue("async", () => state.refresh(), { scope: registeredId, key: `asyncSignal:${registeredId}:refresh` }); } function notify() { for (const subscriber of [...subscribers]) { subscriber(state); } } return state; } function isAsyncSignal(value) { return Boolean(value?.[asyncSignalKind]); } function attachCancel(signal, controller) { Object.defineProperty(signal, "cancel", { configurable: true, enumerable: false, value(reason) { controller.abort(reason); } }); } return { asyncSignal, isAsyncSignal }; })(); const __lazyRegistryModule = (() => { const descriptorTypes = new Set(["handler", "component", "asyncSignal", "partial", "route"]); const defaultBaseUrl = "_async"; function defineRegistrySnapshot(snapshot = {}) { if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot)) { throw new TypeError("defineRegistrySnapshot(snapshot) requires an object."); } return snapshot; } function createLazyRegistry(options = {}) { const registryAssets = normalizeRegistryAssets(options.registryAssets ?? options.assets); const importModule = options.importModule ?? ((url) => import(url)); const moduleCache = new Map(); const exportCache = new Map(); return { registryAssets, resolveUrl(type, id, descriptor) { return resolveDescriptorUrl(type, id, descriptor, registryAssets); }, async resolve(type, id, descriptor) { if (!isLazyDescriptor(descriptor)) { return descriptor; } const cacheKey = `${type}:${id}`; if (exportCache.has(cacheKey)) { return exportCache.get(cacheKey); } const resolved = resolveDescriptorUrl(type, id, descriptor, registryAssets); let modulePromise = moduleCache.get(resolved.moduleUrl); if (!modulePromise) { modulePromise = Promise.resolve(importModule(resolved.moduleUrl)); moduleCache.set(resolved.moduleUrl, modulePromise); } const module = await modulePromise; const value = resolveExport(module, resolved.exportNames, type, id); exportCache.set(cacheKey, value); return value; }, inspect() { return { registryAssets, modules: [...moduleCache.keys()], exports: [...exportCache.keys()] }; } }; } function normalizeRegistryAssets(options = {}) { const baseUrl = normalizeBaseUrl(options.baseUrl ?? defaultBaseUrl); const paths = { component: "component", handler: "handler", asyncSignal: "asyncSignal", partial: "partial", route: "route", ...(options.paths ?? {}) }; for (const [type, value] of Object.entries(paths)) { if (!descriptorTypes.has(type)) { continue; } if (typeof value !== "string" || value.length === 0) { throw new TypeError(`Registry asset path for "${type}" must be a non-empty string.`); } } return { baseUrl, paths }; } function isLazyDescriptor(value) { return Boolean( value && typeof value === "object" && !Array.isArray(value) && typeof value.url === "string" ); } function sameRegistryValue(left, right) { if (left === right) { return true; } if (isLazyDescriptor(left) && isLazyDescriptor(right)) { return stableStringify(left) === stableStringify(right); } return false; } function publicRegistryValue(value, id) { if (isLazyDescriptor(value)) { return { ...value }; } return { id }; } function resolveDescriptorUrl(type, id, descriptor, registryAssets) { if (!descriptorTypes.has(type)) { throw new Error(`Registry type "${type}" does not support lazy descriptors.`); } if (!isLazyDescriptor(descriptor)) { throw new TypeError(`Registry descriptor for "${type}:${id}" requires a url.`); } const { path, hash } = splitHash(descriptor.url); const moduleUrl = resolveModuleUrl(type, path, registryAssets); const exportNames = hash ? [hash] : inferredExportNames(id, path); return { moduleUrl, exportNames, url: hash ? `${moduleUrl}#${hash}` : moduleUrl }; } function resolveModuleUrl(type, path, registryAssets) { if (isAbsoluteUrl(path) || path.startsWith("/") || path.startsWith("./") || path.startsWith("../")) { return path; } const typePath = registryAssets.paths[type] ?? type; return joinUrl(registryAssets.baseUrl, typePath, path); } function resolveExport(module, exportNames, type, id) { for (const name of exportNames) { if (name in module) { return module[name]; } } throw new Error(`Lazy ${type} "${id}" did not export ${exportNames.map((name) => `"${name}"`).join(", ")}.`); } function inferredExportNames(id, path) { const names = []; const leaf = id.split(".").filter(Boolean).at(-1); const basename = path .split("/") .filter(Boolean) .at(-1) ?.replace(/\.[^.]+$/, ""); for (const name of [leaf, basename, "default"]) { if (name && !names.includes(name)) { names.push(name); } } return names; } function splitHash(url) { const index = url.indexOf("#"); if (index === -1) { return { path: url, hash: "" }; } return { path: url.slice(0, index), hash: url.slice(index + 1) }; } function normalizeBaseUrl(baseUrl) { if (typeof baseUrl !== "string" || baseUrl.length === 0) { throw new TypeError("registryAssets.baseUrl must be a non-empty string."); } if (isAbsoluteUrl(baseUrl) || baseUrl.startsWith("/") || baseUrl.startsWith("./") || baseUrl.startsWith("../")) { return stripTrailingSlash(baseUrl); } return `/${stripSlashes(baseUrl)}`; } function joinUrl(...parts) { const [first, ...rest] = parts; return [stripTrailingSlash(first), ...rest.map(stripSlashes)].filter(Boolean).join("/"); } function stripSlashes(value) { return String(value).replace(/^\/+|\/+$/g, ""); } function stripTrailingSlash(value) { return String(value).replace(/\/+$/g, ""); } function isAbsoluteUrl(value) { return /^[A-Za-z][A-Za-z\d+.-]*:/.test(value); } function stableStringify(value) { if (!value || typeof value !== "object" || Array.isArray(value)) { return JSON.stringify(value); } return JSON.stringify(Object.keys(value).sort().map((key) => [key, value[key]])); } return { defineRegistrySnapshot, createLazyRegistry, normalizeRegistryAssets, isLazyDescriptor, sameRegistryValue, publicRegistryValue }; })(); const __registryStoreModule = (() => { const { publicRegistryValue } = __lazyRegistryModule; const declarationTypes = new Set(["signal", "handler", "server", "partial", "route", "component", "asyncSignal"]); const cacheTypes = new Set(["cache.browser", "cache.server"]); const cacheEntryTypes = new Set(["cache.browser.entries", "cache.server.entries"]); const allTypes = new Set([...declarationTypes, ...cacheTypes, ...cacheEntryTypes]); function createRegistryStore(initial = {}, options = {}) { const backing = options.backing ?? createBacking(); const target = options.target ?? "server"; const registry = { target, register(type, id, value) { const map = registry._map(type); assertId(type, id); if (map.has(id)) { throw new Error(`${type} "${id}" is already registered.`); } map.set(id, value); return id; }, registerMany(type, map = {}) { for (const [id, value] of Object.entries(map ?? {})) { registry.register(type, id, value); } return registry; }, set(type, id, value) { const map = registry._map(type); assertId(type, id); map.set(id, value); return value; }, unregister(type, id) { return registry.delete(type, id); }, delete(type, id) { return registry._map(type).delete(id); }, keys(type) { if (isHiddenInBrowser(type, target)) { return []; } return [...registry._map(type).keys()]; }, entries(type, entryOptions = {}) { const normalized = normalizeType(type); if (isHiddenInBrowser(normalized, entryOptions.target ?? target)) { return []; } return [...registry._map(normalized)].map(([id, value]) => [ id, publicValue(normalized, id, value, { target, ...entryOptions }) ]); }, has(type, id) { assertId(type, id); if (isHiddenInBrowser(type, target)) { return false; } return registry._map(type).has(id); }, get(type, id, getOptions = {}) { assertId(type, id); const normalized = normalizeType(type); if (isHiddenInBrowser(normalized, getOptions.target ?? target)) { return undefined; } const value = registry._map(normalized).get(id); if (value === undefined) { return undefined; } return publicValue(normalized, id, value, { target, ...getOptions }); }, snapshot(snapshotOptions = {}) { const snapshotTarget = snapshotOptions.target ?? target; return { signal: snapshotSignals(backing.signal), handler: snapshotDescriptors(backing.handler), server: snapshotDescriptors(backing.server), partial: snapshotDescriptors(backing.partial), route: snapshotPlain(backing.route), component: snapshotDescriptors(backing.component), asyncSignal: snapshotDescriptors(backing.asyncSignal), cache: { browser: snapshotPlain(backing.cache.browser), server: snapshotPlain(backing.cache.server) }, entries: { browser: snapshotCacheEntries(backing.cacheEntries.browser), server: snapshotTarget === "browser" ? {} : snapshotCacheEntries(backing.cacheEntries.server) } }; }, rawSnapshot() { return { signal: Object.fromEntries(backing.signal), handler: Object.fromEntries(backing.handler), server: Object.fromEntries(backing.server), partial: Object.fromEntries(backing.partial), route: Object.fromEntries(backing.route), component: Object.fromEntries(backing.component), asyncSignal: Object.fromEntries(backing.asyncSignal), cache: { browser: Object.fromEntries(backing.cache.browser), server: Object.fromEntries(backing.cache.server) } }; }, view(viewOptions = {}) { return createRegistryStore(undefined, { backing, target: viewOptions.target ?? target }); }, _map(type) { const normalized = normalizeType(type); if (declarationTypes.has(normalized)) { return backing[normalized]; } if (normalized === "cache.browser") { return backing.cache.browser; } if (normalized === "cache.server") { return backing.cache.server; } if (normalized === "cache.browser.entries") { return backing.cacheEntries.browser; } if (normalized === "cache.server.entries") { return backing.cacheEntries.server; } throw new Error(`Unknown Async registry type "${type}".`); } }; applyInitial(registry, initial); return registry; } function attachRegistryInspection(target, registry, type) { Object.defineProperty(target, "registry", { configurable: true, enumerable: true, value: registry }); target.keys = () => registry.keys(type); target.entries = () => registry.entries(type); target.inspect = () => registry.entries(type); return target; } function createBacking() { return { signal: new Map(), handler: new Map(), server: new Map(), partial: new Map(), route: new Map(), component: new Map(), asyncSignal: new Map(), cache: { browser: new Map(), server: new Map() }, cacheEntries: { browser: new Map(), server: new Map() } }; } function applyInitial(registry, initial = {}) { registry.registerMany("signal", initial.signal); registry.registerMany("handler", initial.handler); registry.registerMany("server", initial.server); registry.registerMany("partial", initial.partial); registry.registerMany("route", initial.route); registry.registerMany("component", initial.component); registry.registerMany("asyncSignal", initial.asyncSignal); registry.registerMany("cache.browser", initial.cache?.browser); registry.registerMany("cache.server", initial.cache?.server); const entries = initial.entries ?? {}; for (const [key, value] of Object.entries(entries.browser ?? {})) { registry.set("cache.browser.entries", key, cacheEntry(value)); } for (const [key, value] of Object.entries(entries.server ?? {})) { registry.set("cache.server.entries", key, cacheEntry(value)); } } function normalizeType(type) { if (!allTypes.has(type)) { throw new Error(`Unknown Async registry type "${type}".`); } return type; } function assertId(type, id) { if (typeof id !== "string" || id.length === 0) { throw new TypeError(`${type} id must be a non-empty string.`); } } function publicValue(type, id, value, options) { if (type === "server" && options.target === "browser") { return publicRegistryValue(value, id); } if (cacheEntryTypes.has(type)) { return value?.value; } return value; } function isHiddenInBrowser(type, target) { return type === "cache.server.entries" && target === "browser"; } function snapshotSignals(map) { const snapshot = {}; for (const [id, entry] of map) { snapshot[id] = typeof entry?.snapshot === "function" ? entry.snapshot() : entry?.value ?? entry; } return snapshot; } function snapshotDescriptors(map) { const snapshot = {}; for (const [id, value] of map) { snapshot[id] = publicRegistryValue(value, id); } return snapshot; } function snapshotPlain(map) { return Object.fromEntries(map); } function snapshotCacheEntries(map) { const snapshot = {}; for (const [id, entry] of map) { snapshot[id] = entry?.value; } return snapshot; } function cacheEntry(value) { if (value && typeof value === "object" && Object.hasOwn(value, "value")) { return value; } return { value }; } return { createRegistryStore, attachRegistryInspection }; })(); const __cacheModule = (() => { const { attachRegistryInspection, createRegistryStore } = __registryStoreModule; const cacheDefinitionKind = Symbol.for("@async/framework.cacheDefinition"); function defineCache(options = {}) { return { [cacheDefinitionKind]: true, kind: "cache-definition", store: options.store ?? "memory", ttl: options.ttl }; } function createCacheRegistry(initialMap = {}, { now = () => Date.now(), registry, type = "cache.browser" } = {}) { const registryStore = registry ?? createRegistryStore(); const definitions = registryStore._map(type); const entries = registryStore._map(`${type}.entries`); const pending = new Map(); const registryApi = attachRegistryInspection({ register(id, definition = defineCache()) { assertId(id); const normalized = normalizeDefinition(definition); if (definitions.has(id)) { throw new Error(`Cache "${id}" is already registered.`); } definitions.set(id, normalized); return id; }, registerMany(map) { for (const [id, definition] of Object.entries(map ?? {})) { registryApi.register(id, definition); } return registryApi; }, unregister(id) { assertId(id); return definitions.delete(id); }, resolve(id) { assertId(id); return definitions.get(id); }, get(key) { assertKey(key); const entry = entries.get(key); if (!entry) { return undefined; } if (entry.expiresAt !== undefined && entry.expiresAt <= now()) { entries.delete(key); return undefined; } return entry.value; }, set(key, value, options = {}) { assertKey(key); const ttl = options.ttl ?? resolvePolicy(key, options.cache)?.ttl; entries.set(key, { value, expiresAt: ttl === undefined ? undefined : now() + ttl }); return value; }, async getOrSet(key, fn, options = {}) { assertKey(key); if (typeof fn !== "function") { throw new TypeError("cache.getOrSet(key, fn) requires a function."); } const cached = registryApi.get(key); if (cached !== undefined) { return cached; } if (pending.has(key)) { return pending.get(key); } let promise; promise = Promise.resolve() .then(fn) .then((value) => { if (pending.get(key) === promise) { registryApi.set(key, value, options); } return value; }) .finally(() => { if (pending.get(key) === promise) { pending.delete(key); } }); pending.set(key, promise); return promise; }, delete(key) { assertKey(key); pending.delete(key); return entries.delete(key); }, clear(prefix) { if (prefix === undefined) { entries.clear(); pending.clear(); return registryApi; } for (const key of [...entries.keys()]) { if (key.startsWith(prefix)) { entries.delete(key); } } for (const key of [...pending.keys()]) { if (key.startsWith(prefix)) { pending.delete(key); } } return registryApi; }, snapshot() { const snapshot = {}; for (const [key] of entries) { const value = registryApi.get(key); if (value !== undefined) { snapshot[key] = value; } } return snapshot; }, restore(snapshot = {}) { for (const [key, value] of Object.entries(snapshot ?? {})) { registryApi.set(key, value); } return registryApi; }, entryKeys() { return [...entries.keys()]; }, entryEntries() { return registryStore.entries(`${type}.entries`); }, _adoptMany() { return registryApi; } }, registryStore, type); registryApi.registerMany(initialMap); return registryApi; function resolvePolicy(key, explicitId) { if (explicitId !== undefined) { return definitions.get(explicitId); } if (definitions.has(key)) { return definitions.get(key); } const prefix = key.split(":")[0]; return definitions.get(prefix); } } function normalizeDefinition(definition) { if (definition?.[cacheDefinitionKind]) { return definition; } return defineCache(definition); } function assertId(id) { if (typeof id !== "string" || id.length === 0) { throw new TypeError("Cache id must be a non-empty string."); } } function assertKey(key) { if (typeof key !== "string" || key.length === 0) { throw new TypeError("Cache key must be a non-empty string."); } } return { defineCache, createCacheRegistry }; })(); const __attributesModule = (() => { const defaultPrefixes = Object.freeze({ async: ["async:"], class: ["class:"], signal: ["signal:"], on: ["on:"] }); function defineAttributeConfig(config = {}) { return normalizeAttributeConfig(config); } function normalizeAttributeConfig(config = {}) { return { async: normalizePrefixes(config.async, defaultPrefixes.async), class: normalizePrefixes(config.class, defaultPrefixes.class), signal: normalizePrefixes(config.signal, defaultPrefixes.signal), on: normalizePrefixes(config.on, defaultPrefixes.on) }; } function attributeName(attributes, type, name) { return normalizeAttributeConfig(attributes)[type][0] + name; } function readAttribute(element, attributes, type, name) { for (const prefix of normalizeAttributeConfig(attributes)[type]) { const attr = `${prefix}${name}`; if (element.hasAttribute?.(attr)) { return element.getAttribute(attr); } } return null; } function matchAttribute(name, attributes, type) { for (const prefix of normalizeAttributeConfig(attributes)[type]) { if (name.startsWith(prefix)) { return name.slice(prefix.length); } } return null; } function normalizePrefixes(value, fallback) { const prefixes = value == null ? fallback : Array.isArray(value) ? value : [value]; return prefixes.map((prefix) => { if (typeof prefix !== "string" || prefix.length === 0) { throw new TypeError("Attribute prefixes must be non-empty strings."); } return prefix; }); } return { defineAttributeConfig, normalizeAttributeConfig, attributeName, readAttribute, matchAttribute }; })(); const __signalsModule = (() => { const { asyncSignal: createAsyncSignal, isAsyncSignal } = __asyncSignalModule; const { attachRegistryInspection, createRegistryStore } = __registryStoreModule; const { createLazyRegistry, isLazyDescriptor } = __lazyRegistryModule; const signalKind = Symbol.for("@async/framework.signal"); const computedKind = Symbol.for("@async/framework.computed"); const effectKind = Symbol.for("@async/framework.effect"); const refKind = Symbol.for("@async/framework.signalRef"); const dependencyFrames = []; function createSignal(initial) { let value = initial; const subscribers = new Set(); return { [signalKind]: true, kind: "signal", get value() { return value; }, set value(nextValue) { this.set(nextValue); }, set(nextValue) { if (Object.is(value, nextValue)) { return value; } value = nextValue; notify(); return value; }, update(fn) { return this.set(fn(value)); }, subscribe(fn) { if (typeof fn !== "function") { throw new TypeError("subscribe(fn) requires a function."); } subscribers.add(fn); return () => subscribers.delete(fn); }, snapshot() { return value; } }; function notify() { for (const subscriber of [...subscribers]) { subscriber(value); } } } const signal = createSignal; function computed(fn) { if (typeof fn !== "function") { throw new TypeError("computed(fn) requires a function."); } const backing = createSignal(undefined); return { [computedKind]: true, kind: "computed", get value() { return backing.value; }, set(nextValue) { return backing.set(nextValue); }, update(fn) { return backing.update(fn); }, subscribe(fn) { return backing.subscribe(fn); }, snapshot() { return backing.snapshot(); }, _bindRegistry(registry, id) { return registry.effect(() => { backing.set(fn.call({ signals: registry, id, server: registry._context?.().server, router: registry._context?.().router, loader: registry._context?.().loader, cache: registry._context?.().cache, scheduler: registry._context?.().scheduler })); }); } }; } function effect(fn) { if (typeof fn !== "function") { throw new TypeError("effect(fn) requires a function."); } return { [effectKind]: true, kind: "effect", fn, _bindRegistry(registry) { return registry.effect(fn); } }; } function createSignalRegistry(initialMap = {}, options = {}) { const registryStore = options.registry ?? createRegistryStore(); const type = options.type ?? "signal"; const entries = registryStore._map(type); const asyncDescriptors = registryStore._map("asyncSignal"); const lazyRegistry = options.lazyRegistry ?? createLazyRegistry(options); const registryCleanups = new Map(); const runtimeContext = {}; const boundEntries = new Set(); let subscriptionCounter = 0; let effectCounter = 0; const registry = attachRegistryInspection({ register(id, signalLike) { assertId(id); if (entries.has(id)) { throw new Error(`Signal "${id}" is already registered.`); } const entry = normalizeSignal(signalLike); entries.set(id, entry); bindEntry(id, entry); return registry.ref(id); }, registerMany(map) { for (const [id, signalLike] of Object.entries(map ?? {})) { registry.register(id, signalLike); } return registry; }, unregister(id) { assertId(id); if (!entries.has(id)) { return false; } registryCleanups.get(id)?.(); registryCleanups.delete(id); entries.get(id)?._dispose?.(); entries.delete(id); boundEntries.delete(id); return true; }, ensure(id, initial) { assertId(id); materializeAsyncSignal(id); if (!entries.has(id)) { registry.register(id, createSignal(initial)); } return registry.ref(id); }, has(id) { return entries.has(id) || asyncDescriptors.has(id); }, get(path) { const parsed = parseRegistryPath(path); track(parsed.path); const entry = requireEntry(entries, parsed.id); return readEntry(entry, parsed.parts); }, set(path, value) { const parsed = parseRegistryPath(path); const entry = requireEntry(entries, parsed.id); if (parsed.parts.length === 0) { return entry.set(value); } const nextValue = setPath(entry.value, parsed.parts, value); entry.set(nextValue); return value; }, update(path, fn) { if (typeof fn !== "function") { throw new TypeError("update(path, fn) requires a function."); } return registry.set(path, fn(registry.get(path))); }, ref(id) { assertId(id); materializeAsyncSignal(id); return createRef(registry, id); }, subscribe(path, fn, options = {}) { if (typeof fn !== "function") { throw new TypeError("subscribe(path, fn) requires a function."); } const parsed = parseRegistryPath(path); const entry = requireEntry(entries, parsed.id); const subscriptionId = ++subscriptionCounter; return entry.subscribe(() => { scheduleCallback(() => fn(registry.get(parsed.path), { id: parsed.id, path: parsed.path, signal: entry }), { ...options, key: options.key ?? `signal:${parsed.path}:${subscriptionId}` }); }); }, snapshot() { const snapshot = {}; for (const [id, entry] of entries) { snapshot[id] = typeof entry.snapshot === "function" ? entry.snapshot() : entry.value; } return snapshot; }, asyncSignal(id, fn) { registry.register(id, createAsyncSignal(id, fn)); return registry.ref(id); }, effect(fn, options = {}) { let cleanup; let dependencyCleanups = []; let stopped = false; const scheduler = options.scheduler; const effectId = ++effectCounter; const run = () => { if (stopped) { return; } if (typeof cleanup === "function") { cleanup(); } for (const stop of dependencyCleanups) { stop(); } dependencyCleanups = []; const outcome = registry._collectDependencies(() => fn.call({ signals: registry, server: runtimeContext.server, router: runtimeContext.router, loader: runtimeContext.loader, cache: runtimeContext.cache, scheduler: runtimeContext.scheduler })); cleanup = outcome.value; dependencyCleanups = outcome.dependencies.map((dependency) => registry.subscribe(dependency, scheduleRun)); }; const scheduleRun = () => { if (!scheduler) { run(); return; } scheduler.enqueue(options.phase ?? "effect", run, { scope: options.scope, key: options.key ?? `effect:${effectId}` }); }; run(); return () => { stopped = true; if (typeof cleanup === "function") { cleanup(); } for (const stop of dependencyCleanups) { stop(); } }; }, destroy() { for (const cleanup of registryCleanups.values()) { cleanup(); } registryCleanups.clear(); for (const entry of entries.values()) { entry._dispose?.(); } entries.clear(); }, _collectDependencies(fn) { const frame = new Set(); dependencyFrames.push(frame); try { const value = fn(); return { value, dependencies: [...frame] }; } finally { dependencyFrames.pop(); } }, _entry(id) { materializeAsyncSignal(id); return requireEntry(entries, id); }, _setContext(context = {}) { Object.assign(runtimeContext, context); return registry; }, _context() { return runtimeContext; }, _adoptMany(map = {}) { for (const id of Object.keys(map ?? {})) { if (entries.has(id)) { bindEntry(id, entries.get(id)); } } return registry; } }, registryStore, type); for (const [id, entry] of entries) { bindEntry(id, entry); } registry.registerMany(initialMap); return registry; function bindEntry(id, entry) { if (boundEntries.has(id) || typeof entry?._bindRegistry !== "function") { return; } boundEntries.add(id); const cleanup = entry._bindRegistry(registry, id); if (typeof cleanup === "function") { registryCleanups.set(id, cleanup); } } function parseRegistryPath(path) { if (typeof path !== "string" || path.length === 0) { throw new TypeError("Signal path must be a non-empty string."); } const segments = path.split("."); for (let end = segments.length; end > 0; end -= 1) { const id = segments.slice(0, end).join("."); if (entries.has(id) || asyncDescriptors.has(id)) { materializeAsyncSignal(id); return { id, parts: segments.slice(end), path }; } } const [id, ...parts] = segments; return { id, parts, path }; } function materializeAsyncSignal(id) { if (entries.has(id) || !asyncDescriptors.has(id)) { return; } const descriptor = asyncDescriptors.get(id); if (!isLazyDescriptor(descriptor) && typeof descriptor !== "function") { throw new TypeError(`Async signal "${id}" must be a function or lazy descriptor.`); } const loader = async function runLazyAsyncSignal(...args) { const resolved = await lazyRegistry.resolve("asyncSignal", id, descriptor); if (typeof resolved !== "function") { throw new TypeError(`Async signal "${id}" did not resolve to a function.`); } return resolved.apply(this, args); }; const entry = createAsyncSignal(id, loader); entries.set(id, entry); bindEntry(id, entry); } function scheduleCallback(fn, options = {}) { const scheduler = options.scheduler; if (!scheduler || options.phase === "sync") { return fn(); } return scheduler.enqueue(options.phase ?? "effect", fn, { scope: options.scope, key: options.key }); } } function normalizeSignal(signalLike) { if (isSignalLike(signalLike)) { return signalLike; } return createSignal(signalLike); } function isSignalLike(value) { return Boolean(value && typeof value === "object" && typeof value.subscribe === "function"); } function createRef(registry, id) { return { [refKind]: true, kind: "signal-ref", id, get value() { return registry.get(id); }, set value(nextValue) { registry.set(id, nextValue); }, get loading() { return registry._entry(id).loading ?? false; }, get error() { return registry._entry(id).error ?? null; }, get status() { return registry._entry(id).status ?? "ready"; }, get version() { return registry._entry(id).version ?? 0; }, get() { return registry.get(id); }, set(nextValue) { return registry.set(id, nextValue); }, update(fn) { return registry.update(id, fn); }, subscribe(fn) { return registry.subscribe(id, fn); }, refresh() { const entry = registry._entry(id); if (typeof entry.refresh !== "function") { throw new Error(`Signal "${id}" cannot refresh.`); } return entry.refresh(); }, cancel(reason) { const entry = registry._entry(id); if (typeof entry.cancel !== "function") { throw new Error(`Signal "${id}" cannot cancel.`); } return entry.cancel(reason); }, toString() { return id; }, [Symbol.toPrimitive]() { return id; } }; } function isSignalRef(value) { return Boolean(value?.[refKind]); } function parsePath(path, entries) { if (typeof path !== "string" || path.length === 0) { throw new TypeError("Signal path must be a non-empty string."); } const segments = path.split("."); for (let end = segments.length; end > 0; end -= 1) { const id = segments.slice(0, end).join("."); if (entries.has(id)) { return { id, parts: segments.slice(end), path }; } } const [id, ...parts] = segments; return { id, parts, path }; } function readEntry(entry, parts) { if (isAsyncSignal(entry) && parts[0]?.startsWith("$")) { const metadata = readAsyncMetadata(entry, parts[0]); return readPath(metadata, parts.slice(1)); } return readPath(entry.value, parts); } function readAsyncMetadata(entry, part) { switch (part) { case "$value": return entry.value; case "$loading": return entry.loading; case "$error": return entry.error; case "$status": return entry.status; case "$version": return entry.version; default: return undefined; } } function readPath(value, parts) { let cursor = value; for (const part of parts) { if (cursor == null) { return undefined; } cursor = cursor[part]; } return cursor; } function setPath(value, parts, nextValue) { const root = cloneContainer(value, parts[0]); let cursor = root; for (let index = 0; index < parts.length - 1; index += 1) { const part = parts[index]; const nextPart = parts[index + 1]; cursor[part] = cloneContainer(cursor[part], nextPart); cursor = cursor[part]; } cursor[parts.at(-1)] = nextValue; return root; } function cloneContainer(value, nextPart) { if (Array.isArray(value)) { return [...value]; } if (value && typeof value === "object") { return { ...value }; } return isArrayIndex(nextPart) ? [] : {}; } function isArrayIndex(part) { return String(Number(part)) === String(part); } function requireEntry(entries, id) { const entry = entries.get(id); if (!entry) { throw new Error(`Signal "${id}" is not registered.`); } return entry; } function assertId(id) { if (typeof id !== "string" || id.length === 0) { throw new TypeError("Signal id must be a non-empty string."); } } function track(path) { const frame = dependencyFrames.at(-1); if (frame) { frame.add(path); } } return { createSignal, computed, effect, createSignalRegistry, isSignalRef, signal }; })(); const __htmlModule = (() => { const { isSignalRef } = __signalsModule; const { attributeName, matchAttribute, normalizeAttributeConfig } = __attributesModule; const templateKind = Symbol.for("@async/framework.template"); const rawKind = Symbol.for("@async/framework.rawHtml"); function html(strings, ...values) { return { [templateKind]: true, strings, values }; } function isTemplateResult(value) { return Boolean(value?.[templateKind]); } function rawHtml(value) { return { [rawKind]: true, html: String(value ?? "") }; } function renderTemplate(value, options = {}) { if (isTemplateResult(value)) { const context = createRenderContext(options); let output = ""; for (let index = 0; index < value.strings.length; index += 1) { output += value.strings[index]; if (index < value.values.length) { output += renderValue(value.values[index], { ...context, attribute: readAttributeContext(value.strings[index]) }); } } return output; } return renderValue(value, createRenderContext(options)); } function renderValue(value, context = createRenderContext()) { if (value?.[rawKind]) { return value.html; } if (isTemplateResult(value)) { return renderTemplate(value, context); } if (context.attribute) { return renderAttributeValue(value, context); } if (Array.isArray(value)) { return value.map((item) => renderValue(item, context)).join(""); } if (isSignalRef(value)) { return escapeHtml(value.value); } if (value == null || value === false) { return ""; } return escapeHtml(value); } function renderAttributeValue(value, context) { const signalName = matchAttribute(context.attribute.name, context.attributes, "signal"); const className = matchAttribute(context.attribute.name, context.attributes, "class"); const signalPath = signalPathFor(value, context); if (context.attribute.name === "value" && signalPath) { const currentValue = readSignalValue(value, context); const signalValueAttribute = attributeName(context.attributes, "signal", "value"); return `${escapeHtml(currentValue)}${context.attribute.quote} ${signalValueAttribute}=${context.attribute.quote}${escapeHtml(signalPath)}`; } if (signalName != null || className != null) { if (signalPath) { return escapeHtml(signalPath); } if (isInlineBindingValue(value)) { return escapeHtml(registerInlineBinding(value, context)); } } return renderValueAsAttributeLiteral(value, context); } function renderValueAsAttributeLiteral(value, context) { if (Array.isArray(value)) { return value.map((item) => renderValueAsAttributeLiteral(item, context)).join(""); } if (isSignalRef(value)) { return escapeHtml(value.value); } if (value == null || value === false) { return ""; } return escapeHtml(value); } function createRenderContext(options = {}) { return { ...options, attributes: normalizeAttributeConfig(options.attributes) }; } function readAttributeContext(source) { const match = source.match(/(?:^|[\s<])([^\s"'=<>`]+)\s*=\s*(["'])$/); if (!match) { return null; } return { name: match[1], quote: match[2] }; } function signalPathFor(value, context) { if (isSignalRef(value)) { return value.id; } if (typeof value === "string" && context.signals?.has?.(value)) { return value; } return null; } function readSignalValue(value, context) { if (isSignalRef(value)) { return value.value; } if (typeof value === "string" && context.signals?.has?.(value)) { return context.signals.get(value); } return value; } function isInlineBindingValue(value) { return Boolean(value && typeof value === "object"); } function registerInlineBinding(value, context) { if (typeof context.bind !== "function") { return value; } return context.bind(value); } function escapeHtml(value) { return String(value) .replaceAll("&", "&amp;") .replaceAll("<", "&lt;") .replaceAll(">", "&gt;") .replaceAll('"', "&quot;") .replaceAll("'", "&#39;"); } return { html, isTemplateResult, rawHtml, renderTemplate, escapeHtml }; })(); const __componentModule = (() => { const { attributeName } = __attributesModule; const { escapeHtml, rawHtml, renderTemplate } = __htmlModule; const { attachRegistryInspection, createRegistryStore } = __registryStoreModule; const { createLazyRegistry, isLazyDescriptor } = __lazyRegistryModule; const componentKind = Symbol.for("@async/framework.component"); let componentCounter = 0; function defineComponent(fn) { if (typeof fn !== "function") { throw new TypeError("defineComponent(fn) requires a function."); } Object.defineProperty(fn, componentKind, { configurable: true, value: true }); return fn; } const component = defineComponent; function createComponentRegistry(initialMap = {}, options = {}) { const registryStore = options.registry ?? createRegistryStore(); const type = options.type ?? "component"; const entries = registryStore._map(type); const lazyRegistry = options.lazyRegistry ?? createLazyRegistry(options); const lazyComponents = new Map(); const registry = attachRegistryInspection({ register(id, Component) { if (typeof id !== "string" || id.length === 0) { throw new TypeError("Component id must be a non-empty string."); } if (!isComponent(Component) && typeof Component !== "function" && !isLazyDescriptor(Component)) { throw new TypeError(`Component "${id}" must be a component function.`); } if (entries.has(id)) { throw new Error(`Component "${id}" is already registered.`); } entries.set(id, Component); return id; }, registerMany(map) { for (const [id, Component] of Object.entries(map ?? {})) { registry.register(id, Component); } return registry; }, unregister(id) { if (typeof id !== "string" || id.length === 0) { throw new TypeError("Component id must be a non-empty string."); } lazyComponents.delete(id); return entries.delete(id); }, resolve(id) { if (typeof id !== "string" || id.length === 0) { throw new TypeError("Component id must be a non-empty string."); } const Component = entries.get(id); if (!isLazyDescriptor(Component)) { return Component; } if (!lazyComponents.has(id)) { lazyComponents.set(id, async function LazyComponent(...args) { const resolved = await lazyRegistry.resolve(type, id, Component); if (typeof resolved !== "function") { throw new TypeError(`Component "${id}" did not resolve to a function.`); } return resolved.apply(this, args); }); } return lazyComponents.get(id); }, _adoptMany() { return registry; } }, registryStore, type); registry.registerMany(initialMap); return registry; } function isComponent(value) { return Boolean(value?.[componentKind]); } function renderComponent(Component, props = {}, runtime, parentScope = "component") { if (!isComponent(Component) && typeof Component !== "function") { throw new TypeError("renderComponent(Component) requires a component function."); } const scope = `${parentScope}.${componentName(Component)}.${++componentCounter}`; const cleanups = []; const attachHooks = []; const visibleHooks = []; const destroyHooks = []; const bindingIds = []; const templateOptions = { attributes: runtime.attributes, signals: runtime.signals, bind(value) { const id = runtime.loader?._registerBinding?.(value); if (!id) { throw new Error("Inline template bindings require a Loader."); } bindingIds.push(id); return id; } }; const renderScopedTemplate = (value) => renderTemplate(value, templateOptions); const context = createComponentContext({ runtime, scope, cleanups, attachHooks, visibleHooks, destroyHooks, renderScopedTemplate }); const output = Component.call(context, props); const html = renderScopedTemplate(output); return { html, attach(target) { for (const hook of attachHooks) { runtime.scheduler?.enqueue("lifecycle", () => { const cleanup = hook(target); if (typeof cleanup === "function") { cleanups.push(cleanup); } }, { scope, key: `attach:${attachHooks.indexOf(hook)}` }) ?? runAttachHook(hook, target); } }, mount(target) { this.attach(target); }, visible(target, observeVisible) { for (const hook of visibleHooks) { const cleanup = observeVisible(target, () => { runtime.scheduler?.enqueue("lifecycle", () => { const hookCleanup = hook(target); if (typeof hookCleanup === "function") { cleanups.push(hookCleanup); } }, { scope, key: `visible:${visibleHooks.indexOf(hook)}` }) ?? runVisibleHook(hook, target); }); if (typeof cleanup === "function") { cleanups.push(cleanup); } } }, cleanup() { while (destroyHooks.length > 0) { destroyHooks.pop()?.(); } runtime.scheduler?.markScopeDestroyed(scope); while (cleanups.length > 0) { cleanups.pop()?.(); } while (bindingIds.length > 0) { runtime.loader?._releaseBinding?.(bindingIds.pop()); } } }; function runAttachHook(hook, target) { const cleanup = hook(target); if (typeof cleanup === "function") { cleanups.push(cleanup); } } function runVisibleHook(hook, target) { const cleanup = hook(target); if (typeof cleanup === "function") { cleanups.push(cleanup); } } } function createComponentContext({ runtime, scope, cleanups, attachHooks, visibleHooks, destroyHooks, renderScopedTemplate }) { const { signals, handlers, loader, server, router, cache, scheduler } = runtime; const generatedHandlers = new WeakMap(); let generatedHandlerCounter = 0; let generatedSignalCounter = 0; const context = { scope, signals, handlers, loader, server, router, cache, scheduler, signal(name, initial) { if (arguments.length === 1) { const id = scoped(scope, `signal.${++generatedSignalCounter}`); const ref = signals.ensure(id, name); cleanups.push(() => signals.unregister?.(id)); return ref; } const id = scoped(scope, name); const created = !signals.has(id); const ref = signals.ensure(id, initial); if (created) { cleanups.push(() => signals.unregister?.(id)); } return ref; }, computed(name, fn) { const id = scoped(scope, name); const created = !signals.has(id); const ref = signals.ensure(id, undefined); if (created) { cleanups.push(() => signals.unregister?.(id)); } const cleanup = signals.effect(() => { signals.set(id, fn.call(context)); }); cleanups.push(cleanup); return ref; }, asyncSignal(name, fn) { const id = scoped(scope, name); const created = !signals.has(id); if (!signals.has(id)) { signals.asyncSignal(id, fn); } if (created) { cleanups.push(() => signals.unregister?.(id)); } return signals.ref(id); }, effect(fn) { const cleanup = signals.effect(() => fn.call(context), { scheduler, phase: "effect", scope }); cleanups.push(cleanup); return cleanup; }, handler(name, fn) { if (typeof name === "function" && fn === undefined) { const inlineFn = name; if (generatedHandlers.has(inlineFn)) { return generatedHandlers.get(inlineFn); } const id = registerScopedHandler(`handler.${++generatedHandlerCounter}`, inlineFn); generatedHandlers.set(inlineFn, id); return id; } if (typeof fn !== "function") { throw new TypeError("this.handler(name, fn) or this.handler(fn) requires a function."); } return registerScopedHandler(name, fn); }, render(Child, childProps = {}) { const child = renderComponent(Child, childProps, runtime, scope); cleanups.push(child.cleanup); attachHooks.push((target) => child.attach(target)); visibleHooks.push((target) => child.visible(target, loader._observeVisible)); return rawHtml(child.html); }, suspense(signalRef, views) { const id = signalRef?.id; if (!id) { throw new TypeError("this.suspense(signalRef, views) requires a signal ref."); } const normalized = normalizeSuspenseViews(views); const chunks = []; for (const state of ["loading", "ready", "error"]) { const view = normalized[state]; if (!view) { continue; } const attr = attributeName(runtime.attributes, "async", state); const body = renderScopedTemplate(view.call(context, signalRef)); chunks.push(`<template ${attr}="${escapeHtml(id)}">${body}</template>`); } return rawHtml(chunks.join("")); }, on(eventName, fn) { if (typeof eventName !== "string" || eventName.length === 0) { throw new TypeError("Component lifecycle event must be a non-empty string."); } if (typeof fn !== "function") { throw new TypeError(`Component lifecycle "${eventName}" requires a function.`); } const event = eventName === "mount" ? "attach" : eventName; if (event === "attach") { attachHooks.push((target) => fn.call(context, target)); return; } if (event === "visible") { visibleHooks.push((target) => fn.call(context, target)); return; } if (event === "destroy") { destroyHooks.push(() => fn.call(context)); return; } throw new Error(`Unsupported component lifecycle event "${eventName}".`); }, onMount(fn) { context.on("attach", fn); }, onVisible(fn) { context.on("visible", fn); } }; return context; function registerScopedHandler(name, fn) { const id = scoped(scope, name); handlers.register(id, function runComponentHandler(handlerContext) { return fn.call({ ...context, ...handlerContext }, handlerContext); }); cleanups.push(() => handlers.unregister?.(id)); return id; } } function scoped(scope, name) { if (typeof name !== "string" || name.length === 0) { throw new TypeError("Scoped signal or handler name must be a non-empty string."); } return `${scope}.${name}`; } function normalizeSuspenseViews(views) { const normalized = typeof views === "function" ? { ready: views } : views; if (!normalized || typeof normalized !== "object" || Array.isArray(normalized)) { throw new TypeError("this.suspense(signalRef, views) requires views to be a function or object."); } for (const state of ["loading", "ready", "error"]) { if (Object.hasOwn(normalized, state) && normalized[state] !== undefined && typeof normalized[state] !== "function") { throw new TypeError(`this.suspense(signalRef, views) view "${state}" must be a function.`); } } return normalized; } function componentName(Component) { return Component.displayName || Component.name || "anonymous"; } return { defineComponent, createComponentRegistry, isComponent, renderComponent, component }; })(); const __serverModule = (() => { const serverEnvelopeKeys = new Set(["value", "signals", "boundary", "html", "redirect", "error"]); const appliedServerResult = Symbol.for("@async/framework.appliedServerResult"); const appliedServerValues = new WeakSet(); function createServerProxy({ endpoint = "/__async/server", fetch: fetchImpl = globalThis.fetch?.bind(globalThis), signals, loader, router, cache, scheduler, headers = {} } = {}) { if (typeof fetchImpl !== "function") { throw new TypeError("createServerProxy(...) requires fetch to be available."); } const defaults = { signals, loader, router, cache, scheduler }; async function run(id, args = [], context = {}) { assertServerId(id); const runContext = { ...defaults, ...context }; const body = { args, input: context.input ?? defaultInput(runContext), signals: context.signalValues ?? snapshotSignalPaths(context.signalPaths, runContext.signals) }; assertJsonTransportable(body); const response = await fetchImpl(joinEndpoint(endpoint, id), { method: "POST", headers: { "content-type": "application/json", ...headers }, body: JSON.stringify(body), signal: context.abort }); if (!response.ok) { throw new Error(`Server function "${id}" failed with ${response.status}.`); } const result = await readServerResponse(response); await applyServerResult(result, runContext); return markAppliedServerValue(unwrapServerResult(result)); } return createServerNamespace(run, { run, _setContext(context = {}) { Object.assign(defaults, context); } }, () => defaults); } function resolveServerCommandArguments(args, context = {}) { const resolved = []; const signalValues = {}; const signalPaths = []; for (const arg of args) { if (arg.type === "local") { resolved.push(resolveLocal(arg.name, context, { forServer: true })); continue; } const value = readSignal(context.signals, arg.path); resolved.push(value); signalValues[arg.path] = value; signalPaths.push(arg.path); } return { args: resolved, signalValues, signalPaths }; } async function applyServerResult(result, context = {}) { if (!isServerEnvelope(result)) { return result; } if (result[appliedServerResult] || appliedServerValues.has(result)) { return result; } if (result.signals && context.signals) { for (const [path, value] of Object.entries(result.signals)) { context.signals.set?.(path, value); } } if (result.cache?.browser && context.cache?.restore) { context.cache.restore(result.cache.browser); } if (result.boundary && Object.hasOwn(result, "html")) { context.loader?.swap?.(result.boundary, result.html); } if (result.redirect) { await context.router?.navigate?.(result.redirect); } if (result.error) { throw toError(result.error); } Object.defineProperty(result, appliedServerResult, { configurable: true, enumerable: false, value: true }); return result; } function unwrapServerResult(result) { if (isServerEnvelope(result) && Object.hasOwn(result, "value")) { return result.value; } return result; } function markAppliedServerValue(value) { if (value && typeof value === "object") { appliedServerValues.add(value); } return value; } function defaultInput(context = {}) { const form = findForm(context); if (form) { return formDataToObject(new form.ownerDocument.defaultView.FormData(form)); } const element = context.element ?? context.el ?? context.event?.target; if (!element) { return {}; } return { value: "value" in element ? element.value : undefined, checked: "checked" in element ? element.checked : undefined, dataset: element.dataset ? { ...element.dataset } : {} }; } function createServerNamespace(run, root = {}, contextProvider = () => ({})) { const cache = new Map(); function namespace(parts) { const cacheKey = parts.join("."); if (cache.has(cacheKey)) { return cache.get(cacheKey); } const callable = async (...args) => { if (parts.length === 0) { throw new Error("Server namespace is not directly callable."); } const context = contextProvider() ?? {}; const result = await run(parts.join("."), args, context); await applyServerResult(result, context); return unwrapServerResult(result); }; const proxy = new Proxy(callable, { get(_target, prop) { if (prop === "then") { return undefined; } if (prop in _target) { return _target[prop]; } if (parts.length === 0 && prop === "_withContext") { return (context = {}) => createServerNamespace(run, root, () => ({ ...(contextProvider() ?? {}), ...context })); } if (parts.length === 0 && prop === "run" && typeof root.run === "function") { return (id, args = [], context = {}) => root.run(id, args, { ...(contextProvider() ?? {}), ...context }); } if (parts.length === 0 && Object.hasOwn(root, prop)) { return root[prop]; } if (prop === Symbol.toStringTag) { return "AsyncServerNamespace"; } if (prop === "toString") { return () => parts.length === 0 ? "server" : `server.${parts.join(".")}`; } return namespace([...parts, String(prop)]); } }); cache.set(cacheKey, proxy); return proxy; } return namespace([]); } async function readServerResponse(response) { const type = response.headers.get("content-type") ?? ""; if (type.includes("application/json")) { return response.json(); } return { value: await response.text() }; } function snapshotSignalPaths(paths = [], signals) { const snapshot = {}; for (const path of paths) { snapshot[path] = readSignal(signals, path); } return snapshot; } function readSignal(signals, path) { if (!signals || typeof signals.get !== "function") { throw new Error(`Signal "${path}" cannot be read without a signal registry.`); } return signals.get(path); } function createSignalReader(signals) { if (!signals || typeof signals.get === "function") { return signals; } return { get(path) { return readPath(signals, path); }, snapshot() { return { ...signals }; } }; } function readPath(source, path) { return String(path) .split(".") .reduce((value, part) => value?.[part], source); } function resolveLocal(name, context, { forServer } = {}) { if ((name === "$event" || name === "$el") && forServer) { throw new Error(`${name} cannot be passed to a server command.`); } if (name === "$event") { return context.event; } if (name === "$el") { return context.element ?? context.el; } if (name === "$value") { const element = context.element ?? context.el ?? context.event?.target; return element?.value; } if (name === "$checked") { const element = context.element ?? context.el ?? context.event?.target; return element?.checked; } if (name === "$form") { const form = findForm(context); return form ? formDataToObject(new form.ownerDocument.defaultView.FormData(form)) : {}; } if (name === "$dataset") { const element = context.element ?? context.el ?? context.event?.target; return element?.dataset ? { ...element.dataset } : {}; } throw new Error(`Event local "${name}" is not supported.`); } function findForm(context) { const event = context.event; const element = context.element ?? context.el ?? event?.target; if (element?.tagName === "FORM") { return element; } if (event?.type === "submit" && event.target?.tagName === "FORM") { return event.target; } if (event?.type === "submit" && element?.form) { return element.form; } return null; } function formDataToObject(formData) { const output = {}; for (const [key, value] of formData.entries()) { if (Object.hasOwn(output, key)) { output[key] = Array.isArray(output[key]) ? [...output[key], value] : [output[key], value]; continue; } output[key] = value; } return output; } function assertJsonTransportable(value, seen = new Set()) { if (value == null || typeof value !== "object") { return; } if (seen.has(value)) { return; } seen.add(value); const tag = Object.prototype.toString.call(value); if (tag === "[object File]" || tag === "[object Blob]" || tag === "[object FormData]") { throw new Error("Server proxy JSON transport does not support File, Blob, or FormData values yet."); } if (Array.isArray(value)) { for (const item of value) { assertJsonTransportable(item, seen); } return; } for (const item of Object.values(value)) { assertJsonTransportable(item, seen); } } function joinEndpoint(endpoint, id) { return `${String(endpoint).replace(/\/$/, "")}/${encodeURIComponent(id)}`; } function isServerEnvelope(value) { if (!value || typeof value !== "object" || Array.isArray(value)) { return false; } return Object.keys(value).some((key) => serverEnvelopeKeys.has(key)); } function toError(value) { if (value instanceof Error) { return value; } if (value && typeof value === "object" && typeof value.message === "string") { return Object.assign(new Error(value.message), value); } return new Error(String(value)); } function assertServerId(id) { if (typeof id !== "string" || id.length === 0) { throw new TypeError("Server function id must be a non-empty string."); } } return { createServerProxy, resolveServerCommandArguments, applyServerResult, unwrapServerResult, defaultInput, createServerNamespace, createSignalReader, assertServerId }; })(); const __handlersModule = (() => { const { applyServerResult, defaultInput, resolveServerCommandArguments, unwrapServerResult } = __serverModule; const { attachRegistryInspection, createRegistryStore } = __registryStoreModule; const { createLazyRegistry, isLazyDescriptor } = __lazyRegistryModule; const builtInTokens = new Set(["prevent", "preventDefault", "stopPropagation", "stopImmediatePropagation"]); const builtInHandlers = { prevent: preventDefault, preventDefault, stopPropagation() { this.event?.stopPropagation?.(); }, stopImmediatePropagation() { this.event?.stopImmediatePropagation?.(); } }; function preventDefault() { this.event?.preventDefault?.(); } function createHandlerRegistry(initialMap = {}, options = {}) { const registryStore = options.registry ?? createRegistryStore(); const type = options.type ?? "handler"; const handlers = registryStore._map(type); const lazyRegistry = options.lazyRegistry ?? createLazyRegistry(options); const lazyHandlers = new Map(); const registry = attachRegistryInspection({ register(id, fn) { assertId(id); if (typeof fn !== "function" && !isLazyDescriptor(fn)) { throw new TypeError(`Handler "${id}" must be a function.`); } if (handlers.has(id)) { throw new Error(`Handler "${id}" is already registered.`); } handlers.set(id, fn); return id; }, registerMany(map) { for (const [id, fn] of Object.entries(map ?? {})) { registry.register(id, fn); } return registry; }, unregister(id) { assertId(id); lazyHandlers.delete(id); return handlers.delete(id); }, resolve(id) { assertId(id); const handler = handlers.get(id); if (!isLazyDescriptor(handler)) { return handler; } if (!lazyHandlers.has(id)) { lazyHandlers.set(id, async function runLazyHandler(...args) { const resolved = await lazyRegistry.resolve(type, id, handler); if (typeof resolved !== "function") { throw new TypeError(`Handler "${id}" did not resolve to a function.`); } return resolved.apply(this, args); }); } return lazyHandlers.get(id); }, async run(ref, context = {}) { const steps = parseHandlerRef(ref); const results = []; let stopped = false; const runContext = { ...context, handlers: registry, input: context.input ?? defaultInput(context), stop() { stopped = true; } }; for (const step of steps) { if (stopped) { break; } if (step.type === "server") { if (!runContext.server || typeof runContext.server.run !== "function") { throw new Error(`Server command "${step.id}" cannot run without a server registry.`); } const resolved = resolveServerCommandArguments(step.args, runContext); const result = await runContext.server.run(step.id, resolved.args, { ...runContext, signalPaths: resolved.signalPaths, signalValues: resolved.signalValues }); await applyServerResult(result, runContext); results.push(unwrapServerResult(result)); continue; } const handler = registry.resolve(step.id); if (!handler) { throw new Error(`Handler "${step.id}" is not registered.`); } const value = await handler.call(runContext, runContext); if (!(builtInTokens.has(step.id) && handler === builtInHandlers[step.id])) { results.push(value); } } return results; }, _adoptMany() { return registry; } }, registryStore, type); registerBuiltIns(registry, handlers); registry.registerMany(initialMap); return registry; } function registerBuiltIns(registry, handlers) { for (const [id, fn] of Object.entries(builtInHandlers)) { if (!handlers.has(id)) { registry.register(id, fn); continue; } if (handlers.get(id) !== fn) { throw new Error(`Handler "${id}" is already registered.`); } } } function parseHandlerRef(ref) { if (typeof ref !== "string" || ref.trim().length === 0) { throw new TypeError("Handler ref must be a non-empty string."); } return ref .split(";") .map((part) => part.trim()) .filter(Boolean) .map(parseCommand); } function isHandlerToken(value) { return builtInTokens.has(value); } function assertId(id) { if (typeof id !== "string" || id.length === 0) { throw new TypeError("Handler id must be a non-empty string."); } } function parseCommand(command) { if (command.startsWith("server.")) { return parseServerCommand(command); } if (command.includes("(") || command.includes(")")) { throw new Error(`Command "${command}" is not supported.`); } return { type: "handler", id: command }; } function parseServerCommand(command) { const open = command.indexOf("("); if (open === -1 || !command.endsWith(")")) { throw new Error(`Server command "${command}" must be called with parentheses.`); } const id = command.slice("server.".length, open).trim(); if (!isServerCommandId(id)) { throw new Error(`Server command "${command}" has an invalid function id.`); } return { type: "server", id, args: parseArguments(command.slice(open + 1, -1)) }; } function parseArguments(source) { if (source.trim().length === 0) { return []; } return source .split(",") .map((part) => part.trim()) .filter(Boolean) .map(parseArgument); } function parseArgument(token) { if (!/^[^\s,();]+$/.test(token)) { throw new Error(`Argument "${token}" is not supported.`); } if (token.startsWith("$")) { return { type: "local", name: token }; } return { type: "signal", path: token }; } function isServerCommandId(id) { return /^[^.\s();]+(?:\.[^.\s();]+)*$/.test(id); } return { createHandlerRegistry, parseHandlerRef, isHandlerToken }; })(); const __schedulerModule = (() => { const defaultPhases = ["binding", "lifecycle", "effect", "async", "post"]; function createScheduler(options = {}) { const phases = [...(options.phases ?? defaultPhases)]; const queues = new Map(phases.map((phase) => [phase, []])); const keyedJobs = new Map(); const destroyedScopes = new Set(); const objectScopeIds = new WeakMap(); const onError = typeof options.onError === "function" ? options.onError : undefined; const maxDepth = options.maxDepth ?? 100; const strategy = options.strategy ?? "microtask"; let destroyed = false; let flushing = false; let scheduled = false; let batchDepth = 0; let jobCounter = 0; let scopeCounter = 0; const api = { strategy, phases, batch(fn) { if (typeof fn !== "function") { throw new TypeError("scheduler.batch(fn) requires a function."); } assertActive(); batchDepth += 1; let asyncBatch = false; try { const value = fn(); if (value && typeof value.then === "function") { asyncBatch = true; return value.finally(() => { batchDepth -= 1; requestFlush(); }); } return value; } finally { if (!asyncBatch && batchDepth > 0) { batchDepth -= 1; requestFlush(); } } }, enqueue(phase, fn, options = {}) { assertActive(); assertPhase(phase); if (typeof fn !== "function") { throw new TypeError("scheduler.enqueue(phase, fn) requires a function."); } const scope = options.scope; if (scope !== undefined && destroyedScopes.has(scope)) { return noop; } const dedupeKey = options.key === undefined ? undefined : `${phase}:${scopeKey(scope)}:${String(options.key)}`; if (dedupeKey && keyedJobs.has(dedupeKey)) { return keyedJobs.get(dedupeKey).cancel; } const job = { id: ++jobCounter, phase, fn, scope, boundary: options.boundary, key: dedupeKey, canceled: false, cancel() { job.canceled = true; if (job.key) { keyedJobs.delete(job.key); } } }; queues.get(phase).push(job); if (job.key) { keyedJobs.set(job.key, job); } requestFlush(); return job.cancel; }, afterFlush(fn, options = {}) { return api.enqueue("post", fn, options); }, async flush() { assertActive(); if (flushing) { return; } scheduled = false; flushing = true; let depth = 0; try { while (hasJobs()) { depth += 1; if (depth > maxDepth) { throw new Error(`Scheduler exceeded maxDepth ${maxDepth}.`); } for (const phase of phases) { await flushPhase(phase); } } } finally { flushing = false; if (hasJobs()) { requestFlush(); } } }, async flushScope(scope) { assertActive(); if (flushing) { return; } scheduled = false; flushing = true; let depth = 0; try { while (hasJobsForScope(scope)) { depth += 1; if (depth > maxDepth) { throw new Error(`Scheduler exceeded maxDepth ${maxDepth}.`); } for (const phase of phases) { await flushPhase(phase, scope); } } } finally { flushing = false; if (hasJobs()) { requestFlush(); } } }, cancelScope(scope) { if (scope === undefined) { return api; } for (const queue of queues.values()) { for (const job of queue) { if (job.scope === scope) { job.cancel(); } } } return api; }, markScopeDestroyed(scope) { if (scope !== undefined) { destroyedScopes.add(scope); api.cancelScope(scope); } return api; }, isScopeDestroyed(scope) { return scope !== undefined && destroyedScopes.has(scope); }, inspect() { const counts = {}; for (const [phase, queue] of queues) { counts[phase] = queue.filter((job) => !job.canceled).length; } return { strategy, phases: [...phases], pending: counts, scopesDestroyed: destroyedScopes.size, flushing, scheduled }; }, destroy() { destroyed = true; for (const queue of queues.values()) { for (const job of queue) { job.cancel(); } queue.length = 0; } keyedJobs.clear(); destroyedScopes.clear(); } }; return api; function requestFlush() { if (strategy === "manual" || destroyed || flushing || batchDepth > 0 || scheduled) { return; } scheduled = true; scheduleMicrotask(() => { if (!destroyed) { void api.flush(); } }); } async function flushPhase(phase, scope) { const queue = queues.get(phase); const remaining = []; const runnable = []; for (const job of queue.splice(0)) { if (job.canceled) { continue; } if (scope !== undefined && job.scope !== scope) { remaining.push(job); continue; } runnable.push(job); } queue.push(...remaining); for (const job of runnable) { if (job.key) { keyedJobs.delete(job.key); } if (job.canceled || (job.scope !== undefined && destroyedScopes.has(job.scope))) { continue; } try { await job.fn(); } catch (error) { if (onError) { onError(error, job); } else { throw error; } } } } function hasJobs() { for (const queue of queues.values()) { if (queue.some((job) => !job.canceled)) { return true; } } return false; } function hasJobsForScope(scope) { for (const queue of queues.values()) { if (queue.some((job) => !job.canceled && job.scope === scope)) { return true; } } return false; } function assertActive() { if (destroyed) { throw new Error("Scheduler has been destroyed."); } } function assertPhase(phase) { if (!queues.has(phase)) { throw new Error(`Unknown scheduler phase "${phase}".`); } } function scopeKey(scope) { if (scope === undefined) { return "global"; } if ((typeof scope === "object" && scope !== null) || typeof scope === "function") { if (!objectScopeIds.has(scope)) { objectScopeIds.set(scope, `scope:${++scopeCounter}`); } return objectScopeIds.get(scope); } return String(scope); } } function scheduleMicrotask(fn) { if (typeof queueMicrotask === "function") { queueMicrotask(fn); return; } Promise.resolve().then(fn); } function noop() {} return { createScheduler }; })(); const __loaderModule = (() => { const { renderComponent } = __componentModule; const { createHandlerRegistry } = __handlersModule; const { createScheduler } = __schedulerModule; const { createSignalRegistry, isSignalRef } = __signalsModule; const { matchAttribute, normalizeAttributeConfig, readAttribute } = __attributesModule; const inlineBindingPrefix = "__async:inline:"; function Loader({ root, signals, handlers, server, router, cache, attributes, scheduler } = {}) { const documentRef = root?.ownerDocument ?? root ?? globalThis.document; const rootNode = root ?? documentRef; const signalRegistry = signals ?? createSignalRegistry(); const handlerRegistry = handlers ?? createHandlerRegistry(); const schedulerInstance = scheduler ?? createScheduler(); const ownsScheduler = !scheduler; const attributeConfig = normalizeAttributeConfig(attributes); const cleanups = new Set(); const eventBindings = new WeakMap(); const signalBindings = new WeakMap(); const mountedElements = new WeakSet(); const visibleElements = new WeakSet(); const boundaryState = new WeakMap(); const renderingBoundaries = new WeakSet(); const inlineBindings = new Map(); const scopedCleanups = new WeakMap(); let inlineBindingCounter = 0; let destroyed = false; const api = { root: rootNode, signals: signalRegistry, handlers: handlerRegistry, server, router, cache, scheduler: schedulerInstance, attributes: attributeConfig, start() { assertActive(); api.scan(rootNode); return api; }, scan(rootOrFragment = rootNode) { assertActive(); bindSignalAttributes(rootOrFragment); bindClassAttributes(rootOrFragment); bindEventAttributes(rootOrFragment); bindBoundaries(rootOrFragment); runPseudoEvents(rootOrFragment); return api; }, swap(boundaryId, fragmentOrTemplate) { assertActive(); const boundary = findBoundary(rootNode, boundaryId, attributeConfig); if (!boundary) { throw new Error(`Boundary "${boundaryId}" was not found.`); } cleanupChildren(boundary); boundary.replaceChildren(toFragment(fragmentOrTemplate, documentRef)); api.scan(boundary); return boundary; }, mount(target, Component, props = {}) { assertActive(); const rendered = renderComponent(Component, props, { signals: signalRegistry, handlers: handlerRegistry, loader: api, server: api.server, router: api.router, cache: api.cache, scheduler: schedulerInstance, attributes: attributeConfig }); cleanupChildren(target); target.replaceChildren(toFragment(rendered.html, target.ownerDocument)); api.scan(target); rendered.mount(target); rendered.visible(target, api._observeVisible); addCleanup(rendered.cleanup, target, "children"); return rendered; }, destroy() { if (destroyed) { return; } destroyed = true; for (const cleanup of [...cleanups]) { runCleanup(cleanup); } cleanups.clear(); if (ownsScheduler) { schedulerInstance.destroy(); } }, _observeVisible(target, fn) { return observeVisible(target, fn); }, _registerBinding(value) { const id = `${inlineBindingPrefix}${++inlineBindingCounter}`; inlineBindings.set(id, value); return id; }, _releaseBinding(id) { inlineBindings.delete(id); } }; signalRegistry._setContext?.({ server: api.server, router: api.router, loader: api, cache: api.cache, scheduler: schedulerInstance }); api.server?._setContext?.({ signals: signalRegistry, handlers: handlerRegistry, loader: api, router: api.router, cache: api.cache, scheduler: schedulerInstance }); function bindEventAttributes(scope) { for (const element of elementsIn(scope)) { if (typeof element.getAttributeNames !== "function") { continue; } for (const name of element.getAttributeNames()) { const eventName = matchAttribute(name, attributeConfig, "on"); if (!eventName) { continue; } if (eventName === "attach" || eventName === "mount" || eventName === "visible") { continue; } bindEvent(element, eventName, element.getAttribute(name)); } } } function bindEvent(element, eventName, ref) { const key = `${eventName}:${ref}`; const bound = eventBindings.get(element) ?? new Set(); if (bound.has(key)) { return; } bound.add(key); eventBindings.set(element, bound); const listener = async (event) => { try { await schedulerInstance.batch(() => handlerRegistry.run(ref, { signals: signalRegistry, handlers: handlerRegistry, loader: api, server: api.server, router: api.router, cache: api.cache, scheduler: schedulerInstance, event, element, el: element, root: rootNode })); } catch (error) { dispatchAsyncError(element, error); } }; element.addEventListener(eventName, listener); addCleanup(() => element.removeEventListener(eventName, listener), element); } function bindSignalAttributes(scope) { for (const element of elementsIn(scope)) { for (const name of element.getAttributeNames?.() ?? []) { const signalName = matchAttribute(name, attributeConfig, "signal"); if (!signalName) { continue; } if (signalName === "text") { const path = element.getAttribute(name); bindSignal(element, `text:${path}`, path, (value) => { element.textContent = value ?? ""; }); continue; } if (signalName === "value") { const path = element.getAttribute(name); bindSignal(element, `value:${path}`, path, (value) => { if ("value" in element && element.value !== String(value ?? "")) { element.value = value ?? ""; } else if (!("value" in element)) { element.setAttribute("value", value ?? ""); } }); bindValueWriter(element, path); continue; } if (signalName.startsWith("attr:")) { const attr = signalName.slice("attr:".length); const path = element.getAttribute(name); bindSignal(element, `attr:${attr}:${path}`, path, (value) => updateAttribute(element, attr, value)); continue; } if (signalName.startsWith("prop:")) { const prop = signalName.slice("prop:".length); const path = element.getAttribute(name); bindSignal(element, `prop:${prop}:${path}`, path, (value) => updateProperty(element, prop, value)); continue; } if (signalName.startsWith("class:")) { const className = signalName.slice("class:".length); const path = element.getAttribute(name); if (className === "" || className === "{}") { bindClass(element, className, path); } else { bindSignal(element, `class:${className}:${path}`, path, (value) => { element.classList.toggle(className, Boolean(value)); }); } continue; } if (signalName === "class") { const path = element.getAttribute(name); bindClass(element, "{}", path); } } } } function bindClassAttributes(scope) { for (const element of elementsIn(scope)) { for (const name of element.getAttributeNames?.() ?? []) { const className = matchAttribute(name, attributeConfig, "class"); if (className == null) { continue; } bindClass(element, className, element.getAttribute(name)); } } } function bindClass(element, className, path) { if (className === "" || className === "{}") { const staticClasses = readClassTokens(element); let previous = new Set(); bindSignal(element, `class:{}:${path}`, path, (value) => { const next = normalizeClassTokens(value); const current = readClassTokens(element); for (const token of previous) { if (!next.has(token) && !staticClasses.has(token)) { current.delete(token); } } for (const token of next) { current.add(token); } writeClassTokens(element, current); previous = next; }, { rawInline: true }); return; } bindSignal(element, `class:${className}:${path}`, path, (value) => { updateClassToken(element, className, Boolean(value)); }); } function bindSignal(element, key, path, apply, options = {}) { const bound = signalBindings.get(element) ?? new Set(); if (bound.has(key)) { return; } bound.add(key); signalBindings.set(element, bound); const read = () => readBinding(path, options); apply(read()); addCleanup(subscribeBinding(path, () => { schedulerInstance.enqueue("binding", () => apply(read()), { scope: element, key }); }), element); } function bindValueWriter(element, path) { bindEvent(element, "input", `__async:set:${path}`); bindEvent(element, "change", `__async:set:${path}`); if (!handlerRegistry.resolve(`__async:set:${path}`)) { handlerRegistry.register(`__async:set:${path}`, function writeValue({ element }) { writeBinding(path, element.value); }); } } function readBinding(path, options = {}) { if (isInlineBinding(path)) { const value = inlineBindings.get(path); return options.rawInline ? value : resolveInlineValue(value); } return signalRegistry.get(path); } function writeBinding(path, value) { if (!isInlineBinding(path)) { return signalRegistry.set(path, value); } const binding = inlineBindings.get(path); if (isSignalRef(binding)) { return binding.set(value); } throw new Error(`Inline binding "${path}" is not writable.`); } function subscribeBinding(path, fn) { if (!isInlineBinding(path)) { return signalRegistry.subscribe(path, fn); } const cleanups = collectSignalRefs(inlineBindings.get(path)).map((ref) => ref.subscribe(fn)); return () => { for (const cleanup of cleanups) { cleanup(); } }; } function bindBoundaries(scope) { for (const boundary of elementsIn(scope)) { if (renderingBoundaries.has(boundary)) { continue; } const id = boundaryIdFor(boundary, attributeConfig); if (id == null) { continue; } if (!boundaryState.has(boundary)) { const templates = collectBoundaryTemplates(boundary, id, attributeConfig); if (Object.keys(templates).length === 0 || !signalRegistry.has(id)) { continue; } const state = { id, templates, cleanup: signalRegistry.subscribe(`${id}.$status`, () => { schedulerInstance.enqueue("binding", () => renderBoundary(boundary), { scope: boundary, key: `boundary:${id}` }); }) }; boundaryState.set(boundary, state); addCleanup(state.cleanup, boundary); } renderBoundary(boundary); } } function renderBoundary(boundary) { const state = boundaryState.get(boundary); if (!state) { return; } const status = signalRegistry.get(`${state.id}.$status`); const template = chooseBoundaryTemplate(state.templates, status); if (!template) { return; } cleanupChildren(boundary); boundary.replaceChildren(template.content.cloneNode(true)); renderingBoundaries.add(boundary); try { api.scan(boundary); } finally { renderingBoundaries.delete(boundary); } } function runPseudoEvents(scope) { for (const element of elementsIn(scope)) { const refs = readPseudoRefs(element, ["attach", "mount"]); if (refs.length === 0) { continue; } if (mountedElements.has(element)) { continue; } mountedElements.add(element); for (const ref of refs) { scheduleLifecycle(element, () => runPseudo(element, ref), `attach:${ref}`); } } for (const element of elementsIn(scope)) { const ref = readAttribute(element, attributeConfig, "on", "visible"); if (ref == null) { continue; } if (visibleElements.has(element)) { continue; } visibleElements.add(element); addCleanup(observeVisible(element, () => scheduleLifecycle(element, () => runPseudo(element, ref), `visible:${ref}`)), element); } } function readPseudoRefs(element, names) { const refs = []; for (const name of names) { const ref = readAttribute(element, attributeConfig, "on", name); if (ref != null) { refs.push(ref); } } return refs; } async function runPseudo(element, ref) { try { const results = await handlerRegistry.run(ref, { signals: signalRegistry, handlers: handlerRegistry, loader: api, server: api.server, router: api.router, cache: api.cache, scheduler: schedulerInstance, element, el: element, root: rootNode }); for (const result of results) { if (typeof result === "function") { addCleanup(result, element); } } } catch (error) { dispatchAsyncError(element, error); } } function observeVisible(target, fn) { const ownerWindow = target.ownerDocument?.defaultView ?? globalThis; const Observer = ownerWindow.IntersectionObserver ?? globalThis.IntersectionObserver; if (!Observer) { schedulerInstance.enqueue("lifecycle", () => { if (!destroyed) { fn(target); } }, { scope: target, key: "visible:fallback" }); return () => {}; } const observer = new Observer((entries) => { if (entries.some((entry) => entry.isIntersecting)) { observer.disconnect(); fn(target); } }); observer.observe(target); return () => observer.disconnect(); } function assertActive() { if (destroyed) { throw new Error("Loader has been destroyed."); } } function addCleanup(cleanup, owner, mode = "self") { if (typeof cleanup !== "function") { return cleanup; } cleanups.add(cleanup); if (owner) { const records = scopedCleanups.get(owner) ?? []; records.push({ cleanup, mode }); scopedCleanups.set(owner, records); } return cleanup; } function runCleanup(cleanup) { if (typeof cleanup !== "function" || !cleanups.has(cleanup)) { return; } cleanups.delete(cleanup); cleanup(); } function cleanupChildren(container) { runScopedCleanups(container, "children"); for (const child of [...(container.childNodes ?? [])]) { cleanupNode(child); } } function cleanupNode(node) { if (node.nodeType !== 1) { return; } for (const element of elementsIn(node)) { runScopedCleanups(element); schedulerInstance.markScopeDestroyed(element); } } function runScopedCleanups(element, mode) { const records = scopedCleanups.get(element); if (!records) { return; } const remaining = []; for (const record of records) { if (mode && record.mode !== mode) { remaining.push(record); continue; } runCleanup(record.cleanup); } if (remaining.length > 0) { scopedCleanups.set(element, remaining); } else { scopedCleanups.delete(element); } } function scheduleLifecycle(element, fn, key) { schedulerInstance.enqueue("lifecycle", fn, { scope: element, key }); } return api; } const AsyncLoader = Loader; function normalizeClassTokens(value, tokens = new Set()) { if (value == null || value === false) { return tokens; } if (isSignalRef(value)) { const signalValue = value.value; if (signalValue === true) { tokens.add(signalClassName(value.id)); return tokens; } return normalizeClassTokens(signalValue, tokens); } if (typeof value === "string") { for (const token of value.split(/\s+/).filter(Boolean)) { tokens.add(token); } return tokens; } if (Array.isArray(value)) { for (const item of value) { normalizeClassTokens(item, tokens); } return tokens; } if (typeof value === "object") { for (const [token, enabled] of Object.entries(value)) { const value = isSignalRef(enabled) ? enabled.value : enabled; if (value) { normalizeClassTokens(token, tokens); } } return tokens; } if (value !== true) { tokens.add(String(value)); } return tokens; } function resolveInlineValue(value) { if (isSignalRef(value)) { return value.value; } if (Array.isArray(value)) { return value.map(resolveInlineValue); } if (value && typeof value === "object") { return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, resolveInlineValue(entry)])); } return value; } function collectSignalRefs(value, refs = new Map()) { if (isSignalRef(value)) { refs.set(value.id, value); return [...refs.values()]; } if (Array.isArray(value)) { for (const item of value) { collectSignalRefs(item, refs); } return [...refs.values()]; } if (value && typeof value === "object") { for (const item of Object.values(value)) { collectSignalRefs(item, refs); } } return [...refs.values()]; } function isInlineBinding(value) { return typeof value === "string" && value.startsWith(inlineBindingPrefix); } function signalClassName(id) { return id.split(".").at(-1); } function updateClassToken(element, className, enabled) { const tokens = readClassTokens(element); for (const token of normalizeClassTokens(className)) { if (enabled) { tokens.add(token); } else { tokens.delete(token); } } writeClassTokens(element, tokens); } function readClassTokens(element) { return normalizeClassTokens(element.getAttribute("class") ?? ""); } function writeClassTokens(element, tokens) { const value = [...tokens].join(" "); if (value.length === 0) { element.removeAttribute("class"); return; } element.setAttribute("class", value); } function collectBoundaryTemplates(boundary, id, attributeConfig) { const templates = {}; for (const template of [...boundary.children].filter((child) => child.tagName === "TEMPLATE")) { if (templateMatchesState(template, "loading", id, boundary, attributeConfig)) { templates.loading = template; } if (templateMatchesState(template, "ready", id, boundary, attributeConfig)) { templates.ready = template; } if (templateMatchesState(template, "error", id, boundary, attributeConfig)) { templates.error = template; } } return templates; } function templateMatchesState(template, state, id, boundary, attributeConfig) { if (readAttribute(template, attributeConfig, "async", state) === id) { return true; } return isAsyncSuspense(boundary) && template.hasAttribute?.(state); } function chooseBoundaryTemplate(templates, status) { if (status === "ready") { return templates.ready ?? templates.loading ?? templates.error; } if (status === "error") { return templates.error ?? templates.ready ?? templates.loading; } return templates.loading ?? templates.ready ?? templates.error; } function updateAttribute(element, attr, value) { if (value === false || value == null) { element.removeAttribute(attr); if (attr in element) { element[attr] = false; } return; } element.setAttribute(attr, value === true ? "" : String(value)); if (attr in element) { element[attr] = value; } } function updateProperty(element, prop, value) { if (value == null) { element[prop] = ""; return; } element[prop] = value; } function selectAll(scope, selector) { const elements = []; if (scope?.nodeType === 1 && scope.matches?.(selector)) { elements.push(scope); } elements.push(...(scope?.querySelectorAll?.(selector) ?? [])); return elements; } function elementsIn(scope) { return selectAll(scope, "*"); } function findBoundary(root, boundaryId, attributeConfig) { for (const element of elementsIn(root)) { if (boundaryIdFor(element, attributeConfig) === String(boundaryId)) { return element; } } return null; } function boundaryIdFor(element, attributeConfig) { if (isAsyncSuspense(element) && element.hasAttribute?.("for")) { return element.getAttribute("for"); } return readAttribute(element, attributeConfig, "async", "boundary"); } function isAsyncSuspense(element) { return element?.tagName === "ASYNC-SUSPENSE"; } function toFragment(value, documentRef) { if (value?.nodeType === 11) { return value; } if (value?.tagName === "TEMPLATE") { return value.content.cloneNode(true); } if (value?.nodeType) { const fragment = documentRef.createDocumentFragment(); fragment.append(value); return fragment; } const template = documentRef.createElement("template"); template.innerHTML = String(value ?? ""); return template.content.cloneNode(true); } function dispatchAsyncError(element, error) { const EventCtor = element.ownerDocument?.defaultView?.CustomEvent ?? globalThis.CustomEvent; element.dispatchEvent( new EventCtor("async:error", { bubbles: true, detail: { error } }) ); } return { Loader, AsyncLoader }; })(); const __partialsModule = (() => { const { isTemplateResult, renderTemplate } = __htmlModule; const { attachRegistryInspection, createRegistryStore } = __registryStoreModule; const { createLazyRegistry, isLazyDescriptor } = __lazyRegistryModule; function createPartialRegistry(initialMap = {}, options = {}) { const registryStore = options.registry ?? createRegistryStore(); const type = options.type ?? "partial"; const entries = registryStore._map(type); const lazyRegistry = options.lazyRegistry ?? createLazyRegistry(options); const lazyPartials = new Map(); const registry = attachRegistryInspection({ register(id, fn) { assertId(id); if (typeof fn !== "function" && !isLazyDescriptor(fn)) { throw new TypeError(`Partial "${id}" must be a function.`); } if (entries.has(id)) { throw new Error(`Partial "${id}" is already registered.`); } entries.set(id, fn); return id; }, registerMany(map) { for (const [id, fn] of Object.entries(map ?? {})) { registry.register(id, fn); } return registry; }, unregister(id) { assertId(id); lazyPartials.delete(id); return entries.delete(id); }, resolve(id) { assertId(id); const partial = entries.get(id); if (!isLazyDescriptor(partial)) { return partial; } if (!lazyPartials.has(id)) { lazyPartials.set(id, async function runLazyPartial(...args) { const resolved = await lazyRegistry.resolve(type, id, partial); if (typeof resolved !== "function") { throw new TypeError(`Partial "${id}" did not resolve to a function.`); } return resolved.apply(this, args); }); } return lazyPartials.get(id); }, async render(id, props = {}, context = {}) { assertId(id); const fn = registry.resolve(id); if (!fn) { throw new Error(`Partial "${id}" is not registered.`); } const partialContext = { ...context, id, props, cache: context.cache, partials: registry }; const result = await fn.call(partialContext, props); return normalizePartialResult(result, partialContext); }, _adoptMany() { return registry; } }, registryStore, type); registry.registerMany(initialMap); return registry; } function normalizePartialResult(result, context = {}) { if (isPartialEnvelope(result)) { return { ...result, html: Object.hasOwn(result, "html") ? renderPartialValue(result.html, context) : result.html }; } return { html: renderPartialValue(result, context) }; } function renderPartialValue(value, context) { if (value?.nodeType) { return value; } if (typeof value === "string") { return value; } if (isTemplateResult(value)) { return renderTemplate(value, templateRenderOptions(context)); } return renderTemplate(value, templateRenderOptions(context)); } function templateRenderOptions(context) { return { attributes: context.loader?.attributes, signals: context.signals, bind: context.loader?._registerBinding?.bind(context.loader) }; } function isPartialEnvelope(value) { return Boolean( value && typeof value === "object" && !Array.isArray(value) && (Object.hasOwn(value, "html") || Object.hasOwn(value, "signals") || Object.hasOwn(value, "boundary") || Object.hasOwn(value, "redirect") || Object.hasOwn(value, "status") || Object.hasOwn(value, "cache")) ); } function assertId(id) { if (typeof id !== "string" || id.length === 0) { throw new TypeError("Partial id must be a non-empty string."); } } return { createPartialRegistry, normalizePartialResult }; })(); const __routerModule = (() => { const { Loader } = __loaderModule; const { createHandlerRegistry } = __handlersModule; const { createScheduler } = __schedulerModule; const { createSignalRegistry } = __signalsModule; const { applyServerResult } = __serverModule; const { createRegistryStore } = __registryStoreModule; const { normalizeAttributeConfig } = __attributesModule; function defineRoute(partial, options = {}) { return { ...options, partial }; } const route = defineRoute; function createRouteRegistry(initialMap = {}, options = {}) { const registryStore = options.registry ?? createRegistryStore(); const type = options.type ?? "route"; const entries = registryStore._map(type); const routes = []; const registry = { registry: registryStore, register(pattern, definition) { assertPattern(pattern); if (routes.some((candidate) => candidate.pattern === pattern)) { throw new Error(`Route "${pattern}" is already registered.`); } const nextRoute = normalizeRoute(pattern, definition); entries.set(pattern, nextRoute.definition); routes.push(nextRoute); sortRoutes(routes); return nextRoute; }, registerMany(map) { for (const [pattern, definition] of Object.entries(map ?? {})) { registry.register(pattern, definition); } return registry; }, unregister(pattern) { assertPattern(pattern); const index = routes.findIndex((candidate) => candidate.pattern === pattern); if (index !== -1) { routes.splice(index, 1); } return entries.delete(pattern); }, match(url) { const path = toUrl(url).pathname; for (const candidate of routes) { const match = candidate.regex.exec(path); if (!match) { continue; } const params = {}; candidate.keys.forEach((key, index) => { params[key] = decodeURIComponent(match[index + 1] ?? ""); }); return { pattern: candidate.pattern, params, route: candidate.definition }; } return null; }, entries() { return routes.map(({ pattern, definition }) => ({ pattern, route: definition })); }, keys() { return [...entries.keys()]; }, inspect() { return registryStore.entries(type); }, _adoptMany(map = {}) { for (const pattern of Object.keys(map ?? {})) { adoptRoute(pattern, entries.get(pattern)); } return registry; } }; for (const [pattern, definition] of entries) { adoptRoute(pattern, definition); } registry.registerMany(initialMap); return registry; function adoptRoute(pattern, definition) { if (routes.some((candidate) => candidate.pattern === pattern)) { return; } const nextRoute = normalizeRoute(pattern, definition); entries.set(pattern, nextRoute.definition); routes.push(nextRoute); sortRoutes(routes); } } function createRouter({ mode = "ssr-spa", root, boundary = "route", routes = createRouteRegistry(), loader, signals, handlers, server, cache, partials, fetch: fetchImpl = globalThis.fetch?.bind(globalThis), routeEndpoint = "/__async/route", attributes, scheduler } = {}) { const documentRef = root?.ownerDocument ?? root ?? globalThis.document; const rootNode = root ?? documentRef; const signalRegistry = signals ?? loader?.signals ?? createSignalRegistry(); const handlerRegistry = handlers ?? loader?.handlers ?? createHandlerRegistry(); const schedulerInstance = scheduler ?? loader?.scheduler ?? createScheduler(); const ownsScheduler = !scheduler && !loader?.scheduler; const attributeConfig = normalizeAttributeConfig(attributes ?? loader?.attributes); const loaderInstance = loader ?? Loader({ root: rootNode, signals: signalRegistry, handlers: handlerRegistry, server, cache, scheduler: schedulerInstance, attributes: attributeConfig }); const ownsLoader = !loader; const cleanups = new Set(); let destroyed = false; let navigationVersion = 0; let activeNavigation; const api = { mode, root: rootNode, boundary, routes, loader: loaderInstance, signals: signalRegistry, handlers: handlerRegistry, server, cache, partials, scheduler: schedulerInstance, attributes: attributeConfig, start() { assertActive(); loaderInstance.router = api; signalRegistry._setContext?.({ router: api, loader: loaderInstance, server, cache, scheduler: schedulerInstance }); if (ownsLoader) { loaderInstance.start(); } if (mode === "mpa" || mode === "ssr") { updateStateFromLocation(); return api; } bindNavigation(); if (mode === "csr") { void api.navigate(currentUrl(), { replace: true, initial: true, source: "client" }).catch(() => {}); return api; } updateStateFromLocation(); return api; }, match(url) { return routes.match(resolveUrl(url)); }, prefetch(url) { assertActive(); if (mode === "ssr-spa" && typeof fetchImpl === "function") { return fetchRoute(url, { prefetch: true }); } const matched = api.match(url); if (matched?.route?.partial && partials?.resolve?.(matched.route.partial)) { return partials.render(matched.route.partial, matched.params, contextFor(matched)); } if (typeof fetchImpl === "function") { return fetchRoute(url, { prefetch: true }); } return Promise.resolve(null); }, async navigate(url, options = {}) { assertActive(); if (mode === "mpa" || mode === "ssr") { documentRef.defaultView?.location?.assign?.(url); return null; } const target = resolveUrl(url); if (mode === "ssr-spa") { return fetchRoutePartial(target, options); } return renderLocalRoutePartial(target, options); }, destroy() { if (destroyed) { return; } destroyed = true; activeNavigation?.controller.abort(new Error("Router has been destroyed.")); for (const cleanup of cleanups) { cleanup(); } cleanups.clear(); if (ownsScheduler) { schedulerInstance.destroy(); } } }; return api; function bindNavigation() { const click = (event) => { const anchor = closest(event.target, "a[href]"); if (!anchor || shouldIgnoreLink(event, anchor)) { return; } event.preventDefault(); api.navigate(anchor.href); }; const submit = (event) => { const form = closest(event.target, "form"); if (!form || shouldIgnoreForm(form)) { return; } event.preventDefault(); api.navigate(formActionUrl(form)); }; const popstate = () => api.navigate(currentUrl(), { history: false }); rootNode.addEventListener?.("click", click); rootNode.addEventListener?.("submit", submit); documentRef.defaultView?.addEventListener?.("popstate", popstate); cleanups.add(() => rootNode.removeEventListener?.("click", click)); cleanups.add(() => rootNode.removeEventListener?.("submit", submit)); cleanups.add(() => documentRef.defaultView?.removeEventListener?.("popstate", popstate)); } async function renderLocalRoutePartial(target, options = {}) { const matched = api.match(target); if (!matched) { beginNavigation(target, null); setNoRouteError(target); return null; } const navigation = beginNavigation(target, matched); setMatchedRouterState(target, matched, { pending: true, error: null }); try { if (!matched.route?.partial || !partials?.resolve?.(matched.route.partial)) { const error = new Error(`Route "${target.pathname}" does not have a registered partial.`); if (isActiveNavigation(navigation)) { setRouterState({ pending: false, error }); } return null; } const result = await partials.render(matched.route.partial, matched.params, contextFor(matched, navigation)); if (!isActiveNavigation(navigation)) { return null; } await applyNavigationResult(result, target, options, navigation); if (!isActiveNavigation(navigation)) { return null; } setRouterState({ pending: false, error: null }); return result; } catch (error) { if (!isActiveNavigation(navigation)) { return null; } setRouterState({ pending: false, error }); throw error; } } async function fetchRoutePartial(target, options = {}) { const matched = api.match(target); const navigation = beginNavigation(target, matched); setMatchedRouterState(target, matched, { pending: true, error: null }); try { const result = await fetchRoute(target.href, { signal: navigation.abort }); if (!isActiveNavigation(navigation)) { return null; } await applyNavigationResult(result, target, options, navigation); if (!isActiveNavigation(navigation)) { return null; } setRouterState({ pending: false, error: null }); return result; } catch (error) { if (!isActiveNavigation(navigation)) { return null; } setRouterState({ pending: false, error }); throw error; } } async function applyNavigationResult(result, target, options, navigation) { if (!isActiveNavigation(navigation)) { return; } await applyServerResult(result, { signals: signalRegistry, loader: loaderInstance, router: api, cache, scheduler: schedulerInstance, abort: navigation?.abort }); await schedulerInstance.flush(); if (!isActiveNavigation(navigation)) { return; } if (result?.html != null && !result.boundary && !result.redirect) { loaderInstance.swap(boundary, result.html); await schedulerInstance.flush(); } if (result?.redirect || options.history === false) { return; } if (options.replace) { documentRef.defaultView?.history?.replaceState?.({}, "", target.href); return; } documentRef.defaultView?.history?.pushState?.({}, "", target.href); } async function fetchRoute(url, { prefetch = false, signal } = {}) { if (typeof fetchImpl !== "function") { throw new Error("Router navigation requires a partial registry or fetch."); } const response = await fetchImpl(`${routeEndpoint}?to=${encodeURIComponent(String(url))}`, { headers: { accept: "application/json, text/html" }, signal }); if (!response.ok) { throw new Error(`Route "${url}" failed with ${response.status}.`); } if (prefetch) { return response; } const type = response.headers.get("content-type") ?? ""; if (type.includes("application/json")) { return response.json(); } return { boundary, html: await response.text() }; } function contextFor(matched, navigation) { return { params: matched.params, route: matched.route, router: api, signals: signalRegistry, handlers: handlerRegistry, loader: loaderInstance, server, cache, scheduler: schedulerInstance, abort: navigation?.abort }; } function beginNavigation(target, matched) { activeNavigation?.controller.abort(new Error(`Router navigation superseded by ${target.pathname}${target.search}.`)); const controller = new AbortController(); const navigation = { id: ++navigationVersion, controller, abort: controller.signal, target, matched }; activeNavigation = navigation; return navigation; } function isActiveNavigation(navigation) { return !destroyed && navigation && activeNavigation?.id === navigation.id && !navigation.abort.aborted; } function updateStateFromLocation() { const url = currentUrl(); const matched = api.match(url); setMatchedRouterState(url, matched, { pending: false, error: null }); } function setMatchedRouterState(url, matched, patch = {}) { signalRegistry.ensure("router", {}); setRouterState({ url: url.href, path: url.pathname, query: queryObject(url), params: matched?.params ?? {}, route: matched?.route ?? null, ...patch }); } function setNoRouteError(url) { const error = new Error(`No route matched ${url.pathname}${url.search}`); setMatchedRouterState(url, null, { pending: false, error }); } function setRouterState(patch) { signalRegistry.ensure("router", {}); for (const [key, value] of Object.entries(patch)) { signalRegistry.set(`router.${key}`, value); } } function currentUrl() { return resolveUrl(documentRef.defaultView?.location?.href ?? "http://localhost/"); } function resolveUrl(url) { if (url instanceof URL) { return url; } return new URL(String(url), documentRef.defaultView?.location?.href ?? "http://localhost/"); } function assertActive() { if (destroyed) { throw new Error("Router has been destroyed."); } } } function normalizeRoute(pattern, definition) { const normalized = typeof definition === "string" ? defineRoute(definition) : definition; const { regex, keys } = compilePattern(pattern); return { pattern, regex, keys, score: routeScore(pattern), definition: normalized }; } function compilePattern(pattern) { const keys = []; if (pattern === "*") { return { regex: /^.*$/, keys }; } if (pattern === "/") { return { regex: /^\/$/, keys }; } const source = pattern .split("/") .map((segment) => { if (segment.startsWith(":")) { keys.push(segment.slice(1)); return "([^/]+)"; } return escapeRegExp(segment); }) .join("/"); return { regex: new RegExp(`^${source}$`), keys }; } function shouldIgnoreLink(event, anchor) { if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) { return true; } if (anchor.target || anchor.hasAttribute("download")) { return true; } return toUrl(anchor.href).origin !== toUrl(anchor.ownerDocument.defaultView.location.href).origin; } function shouldIgnoreForm(form) { const method = String(form.method || "get").toLowerCase(); return method !== "get" || toUrl(form.action).origin !== toUrl(form.ownerDocument.defaultView.location.href).origin; } function formActionUrl(form) { const url = toUrl(form.action || form.ownerDocument.defaultView.location.href); const formData = new form.ownerDocument.defaultView.FormData(form); url.search = new URLSearchParams(formData).toString(); return url.href; } function closest(target, selector) { return target?.closest?.(selector); } function toUrl(url) { if (url instanceof URL) { return url; } return new URL(String(url), globalThis.location?.href ?? "http://localhost/"); } function queryObject(url) { return Object.fromEntries(url.searchParams.entries()); } function escapeRegExp(value) { return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } function sortRoutes(routes) { routes.sort((left, right) => right.score - left.score || right.pattern.length - left.pattern.length); } function routeScore(pattern) { if (pattern === "*") { return -1; } return pattern .split("/") .filter(Boolean) .reduce((score, segment) => { if (segment === "*") { return score; } if (segment.startsWith(":")) { return score + 2; } return score + 4; }, pattern === "/" ? 3 : 0); } function assertPattern(pattern) { if (typeof pattern !== "string" || (pattern !== "*" && !pattern.startsWith("/"))) { throw new TypeError("Route pattern must be a path string or \"*\"."); } } return { defineRoute, createRouteRegistry, createRouter, route }; })(); const __appModule = (() => { const { createCacheRegistry } = __cacheModule; const { createComponentRegistry } = __componentModule; const { createHandlerRegistry } = __handlersModule; const { Loader } = __loaderModule; const { createPartialRegistry } = __partialsModule; const { createRouteRegistry, createRouter } = __routerModule; const { createScheduler } = __schedulerModule; const { createServerNamespace } = __serverModule; const { createSignal, createSignalRegistry } = __signalsModule; const { createRegistryStore } = __registryStoreModule; const { attributeName, normalizeAttributeConfig } = __attributesModule; const { createLazyRegistry, defineRegistrySnapshot, sameRegistryValue } = __lazyRegistryModule; const registryTypes = new Set(["signal", "handler", "server", "partial", "route", "component", "asyncSignal"]); function defineApp(initial, options = {}) { const registry = createRegistryStore(undefined, { target: "browser" }); const runtimes = new Set(); const createRuntime = options.createRuntime ?? createApp; const app = { registry, use(typeOrModule, entries) { const normalized = normalizeUse(typeOrModule, entries); appendDeclarations(registry, normalized); for (const runtime of runtimes) { runtime._applyUse(normalized); } return app; }, snapshot() { return registry.rawSnapshot(); }, start(options = {}) { const runtime = createRuntime(app, options).start(); app.runtime = runtime; return runtime; }, attachRoot(root) { return ensureRuntime(app).attachRoot(root); }, detachRoot(root) { return app.runtime?.detachRoot(root) ?? app; }, applySnapshot(snapshot, snapshotOptions = {}) { if (app.runtime) { app.runtime.applySnapshot(snapshot, snapshotOptions); return app; } appendSnapshotDeclarations(registry, snapshot, snapshotOptions); return app; }, inspectRoots() { return app.runtime?.inspectRoots() ?? { count: 0, roots: [] }; }, _attach(runtime) { runtimes.add(runtime); return () => app._detach(runtime); }, _detach(runtime) { runtimes.delete(runtime); } }; if (initial) { app.use(initial); } return app; } function createApp(appOrDefinition = Async, options = {}) { const app = isAppHub(appOrDefinition) ? appOrDefinition : defineApp(appOrDefinition ?? {}); const target = options.target ?? "browser"; const scheduler = options.scheduler ?? options.loader?.scheduler ?? createScheduler({ strategy: target === "server" ? "manual" : "microtask" }); const ownsScheduler = !options.scheduler && !options.loader?.scheduler; const attributes = normalizeAttributeConfig(options.attributes); const lazyRegistry = options.lazyRegistry ?? createLazyRegistry({ registryAssets: options.registryAssets, importModule: options.importModule }); const registry = options.registry ?? app.registry.view({ target }); const signals = options.signals ?? createSignalRegistry(undefined, { registry, type: "signal", lazyRegistry }); const handlers = options.handlers ?? createHandlerRegistry(undefined, { registry, type: "handler", lazyRegistry }); const serverCache = createCacheRegistry(undefined, { registry, type: "cache.server" }); const browserCache = createCacheRegistry(undefined, { registry, type: "cache.browser" }); const serverFactory = options.serverFactory ?? createServerReferenceRegistry; const server = options.server ?? serverFactory(undefined, { registry, type: "server" }); const partials = options.partials ?? createPartialRegistry(undefined, { registry, type: "partial", lazyRegistry }); const routes = options.routes ?? createRouteRegistry(undefined, { registry, type: "route" }); const components = options.components ?? createComponentRegistry(undefined, { registry, type: "component", lazyRegistry }); const hasStartupRoot = options.loader || Object.hasOwn(options, "root"); const startupRoot = hasStartupRoot ? options.root : null; let loader = options.loader; let router = options.router; let routerStarted = false; let detach = () => {}; let started = false; let destroyed = false; const rootLoaders = new Map(); const snapshotRoot = startupRoot ?? globalThis.document; const initialSnapshot = options.snapshot ?? (target === "browser" ? readSnapshot(snapshotRoot, { attributes }) : undefined); attachServerCache(server, serverCache); const runtime = { app, registry, target, signals, handlers, server, partials, routes, components, browser: { cache: browserCache }, loader, router, scheduler, attributes, start() { assertActive(); if (started) { return runtime; } started = true; if (target !== "server") { configureServerContext({ cache: browserCache }); signals._setContext?.({ server, loader, cache: browserCache, scheduler }); if (loader) { registerRootLoader(loader.root, loader); loader.start(); startRouterFor(loader.root); } else if (startupRoot != null) { runtime.attachRoot(startupRoot); } } else { configureServerContext({ cache: serverCache }); signals._setContext?.({ server, cache: serverCache, scheduler }); } return runtime; }, use(typeOrModule, entries) { app.use(typeOrModule, entries); return runtime; }, attachRoot(root) { assertActive(); if (target === "server") { throw new Error("Server runtimes cannot attach DOM roots."); } if (!root) { throw new TypeError("runtime.attachRoot(root) requires a root."); } if (rootLoaders.has(root)) { return runtime; } const rootLoader = rootLoaders.size === 0 && loader ? loader : Loader({ root, signals, handlers, server, cache: browserCache, scheduler, attributes }); registerRootLoader(root, rootLoader); rootLoader.start(); configureServerContext({ cache: browserCache }); signals._setContext?.({ server, loader: runtime.loader, cache: browserCache, scheduler }); startRouterFor(root); return runtime; }, detachRoot(root) { assertActive(); if (target === "server") { return runtime; } if (root == null) { for (const rootLoader of new Set(rootLoaders.values())) { rootLoader.destroy?.(); } rootLoaders.clear(); router?.destroy?.(); router = undefined; routerStarted = false; loader = undefined; runtime.loader = undefined; runtime.router = undefined; return runtime; } const rootLoader = rootLoaders.get(root); if (!rootLoader) { return runtime; } rootLoader.destroy?.(); rootLoaders.delete(root); if (loader === rootLoader) { router?.destroy?.(); router = undefined; routerStarted = false; const next = rootLoaders.values().next().value; loader = next; runtime.loader = next; runtime.router = undefined; if (next) { startRouterFor(next.root); } } return runtime; }, inspectRoots() { return { count: rootLoaders.size, roots: [...rootLoaders].map(([root, rootLoader]) => ({ root, loader: rootLoader, primary: rootLoader === loader })) }; }, applySnapshot(snapshot, snapshotOptions = {}) { applySnapshotToRuntime(runtime, snapshot, snapshotOptions); return runtime; }, async render(url) { assertActive(); configureServerContext({ cache: serverCache }); signals._setContext?.({ server, cache: serverCache, scheduler }); const matched = routes.match(url); if (!matched) { await scheduler.flush(); return { html: renderDocument("", { status: 404, signals, browserCache, boundary: options.boundary ?? "route", attributes }), status: 404, signals: signals.snapshot(), cache: { browser: browserCache.snapshot() } }; } const partialId = matched.route.partial; const result = partialId && partials.resolve(partialId) ? await partials.render(partialId, matched.params, { params: matched.params, route: matched.route, signals, handlers, server, cache: serverCache, browserCache, partials, scheduler, ...currentRequestContext() }) : { html: "" }; if (result.signals) { for (const [path, value] of Object.entries(result.signals)) { setOrRegisterSignal(signals, path, value); } } if (result.cache?.browser) { browserCache.restore(result.cache.browser); } await scheduler.flush(); const status = result.status ?? 200; return { html: renderDocument(result.html, { status, signals, browserCache, boundary: result.boundary ?? options.boundary ?? "route", attributes }), status, signals: signals.snapshot(), cache: { browser: browserCache.snapshot() } }; }, destroy() { if (destroyed) { return; } destroyed = true; detach(); router?.destroy?.(); const destroyedLoaders = new Set(rootLoaders.values()); for (const rootLoader of destroyedLoaders) { rootLoader.destroy?.(); } rootLoaders.clear(); if (loader && !destroyedLoaders.has(loader)) { loader?.destroy?.(); } signals.destroy?.(); if (ownsScheduler) { scheduler.destroy(); } }, _applyUse(normalized) { applyUseToRuntime(runtime, normalized); } }; server.cache = serverCache; runtime.server.cache = serverCache; runtime.applySnapshot(initialSnapshot, { strict: options.strictSnapshots ?? true }); detach = app._attach(runtime); return runtime; function registerRootLoader(root, rootLoader) { rootLoaders.set(root, rootLoader); if (!loader) { loader = rootLoader; runtime.loader = rootLoader; } rootLoader.server = server; rootLoader.cache = browserCache; rootLoader.scheduler = scheduler; } function startRouterFor(root) { if (router === false || routerStarted || !(router || shouldStartRouter(routes, options)) || !runtime.loader) { return; } router = router ?? createRouter({ mode: options.mode ?? "ssr-spa", root, boundary: options.boundary ?? "route", routes, loader: runtime.loader, signals, handlers, server, cache: browserCache, partials, scheduler, fetch: options.fetch, routeEndpoint: options.routeEndpoint, attributes }); runtime.router = router; runtime.loader.router = router; configureServerContext({ cache: browserCache, router }); router.start(); routerStarted = true; } function configureServerContext(extra = {}) { const cache = isLocalServerRegistry(server) ? serverCache : extra.cache; server._setContext?.({ signals, loader, router, cache, scheduler, requestContext: options.requestContext, ...currentRequestContext() }); } function currentRequestContext() { const context = readRequestContextLike(options.requestContext); return { requestContext: context, request: context.request ?? options.request, headers: context.headers ?? options.headers, cookies: context.cookies ?? options.cookies, locals: context.locals ?? options.locals }; } function assertActive() { if (destroyed) { throw new Error("Async app runtime has been destroyed."); } } } const Async = defineApp(); function readSnapshot(root = globalThis.document, { attributes } = {}) { const attributeConfig = normalizeAttributeConfig(attributes); const snapshotAttr = attributeName(attributeConfig, "async", "snapshot"); const documentRef = root?.ownerDocument ?? root ?? globalThis.document; const rootNode = root ?? documentRef; if (!rootNode?.querySelectorAll && !documentRef?.querySelectorAll) { return {}; } const merged = {}; for (const searchRoot of new Set([rootNode, documentRef])) { if (!searchRoot?.querySelectorAll) { continue; } for (const script of searchRoot.querySelectorAll("script[type='application/json'], script")) { if (!script.hasAttribute?.(snapshotAttr)) { continue; } const source = script.textContent?.trim() ?? ""; if (!source) { continue; } let parsed; try { parsed = JSON.parse(source); } catch (cause) { throw new Error(`Could not parse Async snapshot: ${cause instanceof Error ? cause.message : String(cause)}`); } mergeSnapshot(merged, parsed, { strict: true }); } } return merged; } function applyUseToRuntime(runtime, normalized) { applyRegistryUse(runtime.signals, runtime.registry, normalized.signal); applyRegistryUse(runtime.handlers, runtime.registry, normalized.handler); applyRegistryUse(runtime.server, runtime.registry, normalized.server); applyRegistryUse(runtime.partials, runtime.registry, normalized.partial); applyRegistryUse(runtime.routes, runtime.registry, normalized.route); applyRegistryUse(runtime.components, runtime.registry, normalized.component); applyRegistryStoreUse(runtime.registry, "asyncSignal", normalized.asyncSignal); applyRegistryUse(runtime.browser.cache, runtime.registry, normalized.cache.browser); applyRegistryUse(runtime.server.cache, runtime.registry, normalized.cache.server); } function applyRegistryStoreUse(registry, type, entries) { if (!entries || Object.keys(entries).length === 0) { return; } for (const [id, value] of Object.entries(entries)) { if (!registry.has(type, id)) { registry.register(type, id, value); } } } function applyRegistryUse(registry, runtimeRegistry, entries) { if (!entries || Object.keys(entries).length === 0) { return; } if (registry?.registry === runtimeRegistry) { registry._adoptMany?.(entries); return; } registry?.registerMany?.(entries); } function emptyDeclarations() { return { signal: {}, handler: {}, server: {}, partial: {}, route: {}, component: {}, asyncSignal: {}, cache: { browser: {}, server: {} } }; } function normalizeUse(typeOrModule, entries) { const normalized = emptyDeclarations(); if (typeof typeOrModule === "string") { if (!registryTypes.has(typeOrModule)) { throw new Error(`Unknown Async registry type "${typeOrModule}".`); } normalized[typeOrModule] = normalizeEntries(typeOrModule, entries); return normalized; } if (!typeOrModule || typeof typeOrModule !== "object") { throw new TypeError("Async.use(...) requires a registry type or module object."); } for (const [type, value] of Object.entries(typeOrModule)) { if (type === "cache") { normalized.cache.browser = { ...(value?.browser ?? {}) }; normalized.cache.server = { ...(value?.server ?? {}) }; continue; } if (!registryTypes.has(type)) { throw new Error(`Unknown Async registry type "${type}".`); } normalized[type] = normalizeEntries(type, value); } return normalized; } function appendDeclarations(target, source) { for (const type of registryTypes) { addEntries(target, type, source[type]); } addEntries(target, "cache.browser", source.cache.browser); addEntries(target, "cache.server", source.cache.server); } function addEntries(registry, type, source) { for (const [id, value] of Object.entries(source ?? {})) { registry.register(type, id, value); } } function isAppHub(value) { return Boolean(value && typeof value.use === "function" && typeof value.snapshot === "function" && value.registry); } function ensureRuntime(app) { if (!app.runtime) { app.start(); } return app.runtime; } function applySnapshotToRuntime(runtime, snapshot = {}, options = {}) { const normalized = normalizeSnapshot(snapshot); for (const [path, value] of Object.entries(normalized.signal)) { setOrRegisterSignal(runtime.signals, path, value); } runtime.browser.cache.restore(normalized.cache.browser); mergeRegistryEntries(runtime, "handler", normalized.handler, runtime.handlers, options); mergeRegistryEntries(runtime, "server", normalized.server, runtime.server, options); mergeRegistryEntries(runtime, "partial", normalized.partial, runtime.partials, options); mergeRegistryEntries(runtime, "route", normalized.route, runtime.routes, options); mergeRegistryEntries(runtime, "component", normalized.component, runtime.components, options); mergeRegistryEntries(runtime, "asyncSignal", normalized.asyncSignal, null, options); return runtime; } function appendSnapshotDeclarations(registry, snapshot = {}, options = {}) { const normalized = normalizeSnapshot(snapshot); for (const [id, value] of Object.entries(normalized.signal)) { registerSnapshotEntry(registry, "signal", id, createSignal(value), options); } for (const type of ["handler", "server", "partial", "route", "component", "asyncSignal"]) { for (const [id, value] of Object.entries(normalized[type])) { registerSnapshotEntry(registry, type, id, value, options); } } } function mergeRegistryEntries(runtime, type, entries, concreteRegistry, options = {}) { if (!entries || Object.keys(entries).length === 0) { return; } for (const [id, value] of Object.entries(entries)) { registerSnapshotEntry(runtime.registry, type, id, value, options); } concreteRegistry?._adoptMany?.(entries); } function registerSnapshotEntry(registry, type, id, value, options = {}) { const strict = options.strict ?? true; const map = registry._map(type); if (map.has(id)) { if (sameRegistryValue(map.get(id), value) || sameSnapshotValue(map.get(id), value)) { return; } if (strict) { throw new Error(`${type} "${id}" is already registered with a different value.`); } return; } registry.set(type, id, value); } function normalizeSnapshot(snapshot = {}) { const normalized = { signal: { ...(snapshot.signals ?? {}), ...(snapshot.signal ?? {}) }, handler: { ...(snapshot.handler ?? {}) }, server: { ...(snapshot.server ?? {}) }, partial: { ...(snapshot.partial ?? {}) }, route: { ...(snapshot.route ?? {}) }, component: { ...(snapshot.component ?? {}) }, asyncSignal: { ...(snapshot.asyncSignal ?? {}) }, cache: { browser: { ...(snapshot.entries?.browser ?? {}), ...(snapshot.cache?.browser ?? {}) } } }; return normalized; } function mergeSnapshot(target, source, options = {}) { const normalized = normalizeSnapshot(defineRegistrySnapshot(source)); target.signal = { ...(target.signal ?? target.signals ?? {}), ...normalized.signal }; target.signals = target.signal; target.cache = { ...(target.cache ?? {}), browser: { ...(target.cache?.browser ?? {}), ...normalized.cache.browser } }; for (const type of ["handler", "server", "partial", "route", "component", "asyncSignal"]) { target[type] = target[type] ?? {}; for (const [id, value] of Object.entries(normalized[type])) { if (Object.hasOwn(target[type], id)) { if (sameRegistryValue(target[type][id], value) || sameSnapshotValue(target[type][id], value)) { continue; } if (options.strict ?? true) { throw new Error(`${type} "${id}" is already declared with a different value.`); } continue; } target[type][id] = value; } } return target; } function sameSnapshotValue(left, right) { if (left === right) { return true; } try { return JSON.stringify(left) === JSON.stringify(right); } catch { return false; } } function setOrRegisterSignal(signals, path, value) { const id = String(path).split(".")[0]; if (signals.has?.(id)) { signals.set(path, value); return; } signals.register(id, createSignal(path === id ? value : {})); if (path !== id) { signals.set(path, value); } } function attachServerCache(server, cache) { try { server.cache = cache; } catch { } } function createServerReferenceRegistry(initialMap = {}, options = {}) { const registry = options.registry ?? createRegistryStore(); const type = options.type ?? "server"; const defaults = {}; const reference = { registry, register(id, value) { registry.register(type, id, value); return id; }, registerMany(map) { for (const [id, value] of Object.entries(map ?? {})) { reference.register(id, value); } return reference; }, unregister(id) { return registry.unregister(type, id); }, resolve() { return undefined; }, async run(id) { throw new Error(`Server command "${id}" cannot run without a server proxy or server registry.`); }, keys() { return registry.keys(type); }, entries() { return registry.entries(type); }, inspect() { return registry.entries(type); }, _setContext(context = {}) { Object.assign(defaults, context); return reference; }, _adoptMany() { return reference; } }; reference.registerMany(initialMap); return createServerNamespace((id, args, context) => reference.run(id, args, context), reference, () => defaults); } function readRequestContextLike(store) { if (!store) { return {}; } if (typeof store.get === "function") { return store.get() ?? {}; } if (typeof store.getStore === "function") { return store.getStore() ?? {}; } return {}; } function normalizeEntries(type, entries = {}) { if (type !== "signal") { return { ...(entries ?? {}) }; } const normalized = {}; for (const [id, value] of Object.entries(entries ?? {})) { normalized[id] = normalizeSignalDeclaration(value); } return normalized; } function normalizeSignalDeclaration(value) { if (value && typeof value === "object" && typeof value.subscribe === "function") { return value; } return createSignal(value); } function isLocalServerRegistry(server) { return typeof server?.registerMany === "function"; } function shouldStartRouter(routes, options) { return Boolean(options.routerOptions || options.mode || routes.entries().length > 0); } function renderDocument(routeHtml, { signals, browserCache, boundary, attributes }) { const snapshot = { signals: signals.snapshot(), cache: { browser: browserCache.snapshot() } }; const boundaryAttr = attributeName(attributes, "async", "boundary"); const snapshotAttr = attributeName(attributes, "async", "snapshot"); return `<section ${boundaryAttr}="${escapeAttribute(boundary)}">${routeHtml ?? ""}</section><script type="application/json" ${snapshotAttr}>${escapeScriptJson(snapshot)}</script>`; } function escapeAttribute(value) { return String(value) .replaceAll("&", "&amp;") .replaceAll('"', "&quot;") .replaceAll("<", "&lt;"); } function escapeScriptJson(value) { return JSON.stringify(value).replaceAll("<", "\\u003c"); } return { defineApp, createApp, readSnapshot, Async }; })(); const __boundaryReceiverModule = (() => { const defaultRecentLimit = 50; function createBoundaryReceiver(options = {}) { const loader = options.loader; const signals = options.signals ?? loader?.signals; const cache = options.cache ?? loader?.cache; const scheduler = options.scheduler ?? loader?.scheduler; const router = options.router ?? loader?.router; const recentLimit = options.recentLimit ?? defaultRecentLimit; const throwOnError = options.throwOnError === true; const onApply = typeof options.onApply === "function" ? options.onApply : undefined; const onIgnore = typeof options.onIgnore === "function" ? options.onIgnore : undefined; const onError = typeof options.onError === "function" ? options.onError : undefined; const isScopeDestroyed = typeof options.isScopeDestroyed === "function" ? options.isScopeDestroyed : (scope) => scheduler?.isScopeDestroyed?.(scope) ?? scheduler?.inspectDestroyed?.(scope) ?? false; if (!loader || typeof loader.swap !== "function") { throw new TypeError("createBoundaryReceiver(...) requires a loader with swap(boundary, html)."); } if (!Number.isInteger(recentLimit) || recentLimit < 0) { throw new TypeError("createBoundaryReceiver(...) recentLimit must be a non-negative integer."); } const boundaries = new Map(); const recent = []; let destroyed = false; const receiver = { async apply(patch) { if (destroyed) { throw new Error("Boundary receiver has been destroyed."); } const normalized = validatePatch(patch); const record = boundaryRecord(normalized.boundary); if (normalized.seq <= record.lastSeq) { const result = { status: "ignored-stale", boundary: normalized.boundary, seq: normalized.seq, lastSeq: record.lastSeq }; record.ignored += 1; record.lastStatus = result.status; remember(result); onIgnore?.(result, patch); return result; } if (normalized.parentScope !== undefined && isScopeDestroyed(normalized.parentScope)) { const result = { status: "ignored-destroyed", boundary: normalized.boundary, seq: normalized.seq, parentScope: normalized.parentScope }; record.ignored += 1; record.lastStatus = result.status; remember(result); onIgnore?.(result, patch); return result; } record.lastSeq = normalized.seq; if (Object.hasOwn(normalized, "error")) { const error = toStableError(normalized.error); const result = { status: "errored", boundary: normalized.boundary, seq: normalized.seq, error }; record.errored += 1; record.lastStatus = result.status; remember(result); onError?.(error, result, patch); if (throwOnError) { throw error; } return result; } if (normalized.signals) { if (!signals || typeof signals.set !== "function") { throw new Error("Boundary patch includes signals, but no signal registry is available."); } for (const [path, value] of Object.entries(normalized.signals)) { signals.set(path, value); } } if (normalized.cache?.browser) { if (!cache || typeof cache.restore !== "function") { throw new Error("Boundary patch includes browser cache, but no cache registry is available."); } cache.restore(normalized.cache.browser); } if (normalized.html != null) { loader.swap(normalized.boundary, normalized.html); } await flushScheduler(scheduler, normalized.scope); if (normalized.redirect) { await followRedirect(normalized.redirect, router, loader); const result = { status: "redirected", boundary: normalized.boundary, seq: normalized.seq, redirect: normalized.redirect }; record.applied += 1; record.lastStatus = result.status; remember(result); onApply?.(result, patch); return result; } const result = { status: "applied", boundary: normalized.boundary, seq: normalized.seq }; record.applied += 1; record.lastStatus = result.status; remember(result); onApply?.(result, patch); return result; }, inspect() { const snapshot = {}; for (const [boundary, record] of boundaries) { snapshot[boundary] = { lastSeq: record.lastSeq, applied: record.applied, ignored: record.ignored, lastStatus: record.lastStatus }; if (record.errored > 0) { snapshot[boundary].errored = record.errored; } } return { destroyed, boundaries: snapshot, recent: recent.map((entry) => ({ ...entry })) }; }, reset(boundary) { if (boundary === undefined) { boundaries.clear(); recent.length = 0; return receiver; } assertBoundary(boundary); boundaries.delete(boundary); for (let index = recent.length - 1; index >= 0; index -= 1) { if (recent[index].boundary === boundary) { recent.splice(index, 1); } } return receiver; }, destroy() { destroyed = true; boundaries.clear(); recent.length = 0; } }; return receiver; function boundaryRecord(boundary) { if (!boundaries.has(boundary)) { boundaries.set(boundary, { lastSeq: -Infinity, applied: 0, ignored: 0, errored: 0, lastStatus: undefined }); } return boundaries.get(boundary); } function remember(result) { if (recentLimit === 0) { return; } recent.push(toRecentEntry(result)); while (recent.length > recentLimit) { recent.shift(); } } } function validatePatch(patch) { if (!patch || typeof patch !== "object" || Array.isArray(patch)) { throw new TypeError("receiver.apply(patch) requires a boundary patch object."); } assertBoundary(patch.boundary); if (typeof patch.seq !== "number" || !Number.isFinite(patch.seq)) { throw new TypeError("Boundary patch seq must be a finite number."); } if (patch.signals !== undefined && !isPlainObject(patch.signals)) { throw new TypeError("Boundary patch signals must be an object."); } if (patch.cache !== undefined && !isPlainObject(patch.cache)) { throw new TypeError("Boundary patch cache must be an object."); } if (patch.cache?.browser !== undefined && !isPlainObject(patch.cache.browser)) { throw new TypeError("Boundary patch cache.browser must be an object."); } if (patch.redirect !== undefined && (typeof patch.redirect !== "string" || patch.redirect.length === 0)) { throw new TypeError("Boundary patch redirect must be a non-empty string."); } if (patch.parentScope !== undefined && typeof patch.parentScope !== "string") { throw new TypeError("Boundary patch parentScope must be a string."); } if (patch.scope !== undefined && typeof patch.scope !== "string") { throw new TypeError("Boundary patch scope must be a string."); } const hasHtml = Object.hasOwn(patch, "html") && patch.html != null; const hasSignals = patch.signals && Object.keys(patch.signals).length > 0; const hasBrowserCache = patch.cache?.browser && Object.keys(patch.cache.browser).length > 0; const hasRedirect = Boolean(patch.redirect); const hasError = Object.hasOwn(patch, "error"); if (!hasHtml && !hasSignals && !hasBrowserCache && !hasRedirect && !hasError) { throw new TypeError("Boundary patch must include html, signals, cache.browser, redirect, or error."); } return patch; } function assertBoundary(boundary) { if (typeof boundary !== "string" || boundary.length === 0) { throw new TypeError("Boundary patch boundary must be a non-empty string."); } } async function flushScheduler(scheduler, scope) { if (!scheduler) { return; } if (scope !== undefined && typeof scheduler.flushScope === "function") { await scheduler.flushScope(scope); return; } if (typeof scheduler.flush === "function") { await scheduler.flush(); } } async function followRedirect(redirect, router, loader) { if (router && typeof router.navigate === "function") { await router.navigate(redirect); return; } const location = loader?.root?.ownerDocument?.defaultView?.location ?? globalThis.location; location?.assign?.(redirect); } function toStableError(value) { if (value instanceof Error) { return value; } if (value && typeof value === "object" && typeof value.message === "string") { return Object.assign(new Error(value.message), value); } return new Error(String(value)); } function toRecentEntry(result) { const entry = { boundary: result.boundary, seq: result.seq, status: result.status }; if (result.status === "ignored-stale") { entry.lastSeq = result.lastSeq; } if (result.status === "ignored-destroyed" && result.parentScope !== undefined) { entry.parentScope = result.parentScope; } if (result.status === "redirected") { entry.redirect = result.redirect; } return entry; } function isPlainObject(value) { return Boolean(value && typeof value === "object" && !Array.isArray(value)); } return { createBoundaryReceiver }; })(); const __delayModule = (() => { function delay(ms, signal) { if (signal?.aborted) { return Promise.reject(abortReason(signal)); } return new Promise((resolve, reject) => { let timer = setTimeout(done, ms); function done() { timer = undefined; signal?.removeEventListener?.("abort", aborted); resolve(); } function aborted() { if (timer !== undefined) { clearTimeout(timer); } timer = undefined; signal?.removeEventListener?.("abort", aborted); reject(abortReason(signal)); } signal?.addEventListener?.("abort", aborted, { once: true }); }); } function abortReason(signal) { return signal?.reason ?? new Error("Operation aborted"); } return { delay }; })(); const __elementsModule = (() => { const { Async } = __appModule; function defineAsyncContainerElement(options = {}) { const tagName = options.tagName ?? "async-container"; const registry = options.customElements ?? globalThis.customElements; if (!registry) { throw new Error("defineAsyncContainerElement(...) requires customElements."); } const existing = registry.get(tagName); if (existing) { return existing; } const app = options.app ?? options.Async ?? Async; const HTMLElementBase = options.HTMLElement ?? options.window?.HTMLElement ?? globalThis.HTMLElement; if (!HTMLElementBase) { throw new Error("defineAsyncContainerElement(...) requires HTMLElement."); } class AsyncContainerElement extends HTMLElementBase { connectedCallback() { if (this.__asyncAttached) { return; } const runtime = app.runtime ?? app.start?.(); runtime?.attachRoot?.(this); this.__asyncRuntime = runtime; this.__asyncAttached = true; } disconnectedCallback() { if (!this.__asyncAttached) { return; } this.__asyncRuntime?.detachRoot?.(this); this.__asyncRuntime = undefined; this.__asyncAttached = false; } } registry.define(tagName, AsyncContainerElement); return AsyncContainerElement; } function defineAsyncSuspenseElement(options = {}) { const tagName = options.tagName ?? "async-suspense"; const registry = options.customElements ?? globalThis.customElements; if (!registry) { throw new Error("defineAsyncSuspenseElement(...) requires customElements."); } const existing = registry.get(tagName); if (existing) { return existing; } const HTMLElementBase = options.HTMLElement ?? options.window?.HTMLElement ?? globalThis.HTMLElement; if (!HTMLElementBase) { throw new Error("defineAsyncSuspenseElement(...) requires HTMLElement."); } class AsyncSuspenseElement extends HTMLElementBase {} registry.define(tagName, AsyncSuspenseElement); return AsyncSuspenseElement; } return { defineAsyncContainerElement, defineAsyncSuspenseElement }; })(); const { asyncSignal: asyncSignal } = __asyncSignalModule; const { Async: Async } = __appModule; const { createApp: createApp } = __appModule; const { defineApp: defineApp } = __appModule; const { readSnapshot: readSnapshot } = __appModule; const { attributeName: attributeName } = __attributesModule; const { defineAttributeConfig: defineAttributeConfig } = __attributesModule; const { createBoundaryReceiver: createBoundaryReceiver } = __boundaryReceiverModule; const { createCacheRegistry: createCacheRegistry } = __cacheModule; const { defineCache: defineCache } = __cacheModule; const { component: component } = __componentModule; const { createComponentRegistry: createComponentRegistry } = __componentModule; const { defineComponent: defineComponent } = __componentModule; const { delay: delay } = __delayModule; const { defineAsyncContainerElement: defineAsyncContainerElement } = __elementsModule; const { defineAsyncSuspenseElement: defineAsyncSuspenseElement } = __elementsModule; const { createHandlerRegistry: createHandlerRegistry } = __handlersModule; const { html: html } = __htmlModule; const { createLazyRegistry: createLazyRegistry } = __lazyRegistryModule; const { defineRegistrySnapshot: defineRegistrySnapshot } = __lazyRegistryModule; const { Loader: Loader } = __loaderModule; const { AsyncLoader: AsyncLoader } = __loaderModule; const { createPartialRegistry: createPartialRegistry } = __partialsModule; const { createRegistryStore: createRegistryStore } = __registryStoreModule; const { createRouteRegistry: createRouteRegistry } = __routerModule; const { createRouter: createRouter } = __routerModule; const { defineRoute: defineRoute } = __routerModule; const { route: route } = __routerModule; const { createScheduler: createScheduler } = __schedulerModule; const { applyServerResult: applyServerResult } = __serverModule; const { createServerProxy: createServerProxy } = __serverModule; const { resolveServerCommandArguments: resolveServerCommandArguments } = __serverModule; const { unwrapServerResult: unwrapServerResult } = __serverModule; const { computed: computed } = __signalsModule; const { createSignal: createSignal } = __signalsModule; const { createSignalRegistry: createSignalRegistry } = __signalsModule; const { effect: effect } = __signalsModule; const { signal: signal } = __signalsModule; export { asyncSignal, Async, createApp, defineApp, readSnapshot, attributeName, defineAttributeConfig, createBoundaryReceiver, createCacheRegistry, defineCache, component, createComponentRegistry, defineComponent, delay, defineAsyncContainerElement, defineAsyncSuspenseElement, createHandlerRegistry, html, createLazyRegistry, defineRegistrySnapshot, Loader, AsyncLoader, createPartialRegistry, createRegistryStore, createRouteRegistry, createRouter, defineRoute, route, createScheduler, applyServerResult, createServerProxy, resolveServerCommandArguments, unwrapServerResult, computed, createSignal, createSignalRegistry, effect, signal };
1
+ const e=(()=>{const e=Symbol.for("@async/framework.asyncSignal");return{asyncSignal:(t,r)=>{if("string"!=typeof t||0===t.length)throw new TypeError("asyncSignal(id, fn) requires a non-empty string id.");if("function"!=typeof r)throw new TypeError("asyncSignal(id, fn) requires a function.");let n,o,s,a,i=!1,c=null,u="idle",l=0,f=t;const p=new Set,h=new Set,d={[e]:!0,kind:"async-signal",get id(){return f},get value(){return n},get loading(){return i},get error(){return c},get status(){return u},get version(){return l},set:e=>(n=e,i=!1,c=null,u="ready",m(),n),refresh(){if(!o)throw new Error(`Async signal "${f}" is not registered.`);a&&!a.aborted&&a.cancel(new Error(`Async signal "${f}" refreshed.`));const e=l+1;l=e,i=!0,c=null,u="loading";const t=new AbortController;s=t,a=t.signal,((e,t)=>{Object.defineProperty(e,"cancel",{configurable:!0,enumerable:!1,value(e){t.abort(e)}})})(a,t),m();const p={signals:o,id:f,get server(){const e=o._context?.()??{},t=e.server;return"function"==typeof t?._withContext?t._withContext({signals:o,router:e.router,loader:e.loader,cache:e.cache,abort:a,scheduler:e.scheduler}):t},get router(){return o._context?.().router},get loader(){return o._context?.().loader},get cache(){return o._context?.().cache},get scheduler(){return o._context?.().scheduler},get version(){return e},get abort(){return a},refresh:()=>d.refresh()};let b;try{b=o._collectDependencies(()=>r.call(p))}catch(t){return y(e,t),Promise.reject(t)}return(e=>{for(const e of h)e();h.clear();for(const t of e){const e=String(t).split(".")[0];e&&e!==f&&h.add(o.subscribe(t,()=>w()))}})(b.dependencies),Promise.resolve(b.value).then(t=>g(e)?(n=t,i=!1,c=null,u="ready",m(),n):n,t=>g(e)?a?.aborted?(i=!1,u=void 0===n?"idle":"ready",m(),n):(y(e,t),n):n)},cancel(e){a&&!a.aborted&&a.cancel(e)},subscribe(e){if("function"!=typeof e)throw new TypeError("subscribe(fn) requires a function.");return p.add(e),()=>p.delete(e)},snapshot:()=>({value:n,loading:i,error:c,status:u,version:l}),_bindRegistry(e,t){o=e,f=t;const r=()=>{o===e&&"idle"===u&&d.refresh()},n=o._context?.().scheduler;n?n.enqueue("async",r,{scope:f,key:`asyncSignal:${f}:initial`}):queueMicrotask(r)},_dispose(){d.cancel(new Error(`Async signal "${f}" disposed.`));for(const e of h)e();h.clear(),p.clear()}};function y(e,t){g(e)&&(i=!1,c=t,u="error",m())}function g(e){return e===l&&s?.signal===a}function w(){a&&!a.aborted&&a.cancel(new Error(`Async signal "${f}" dependency changed.`));const e=o?._context?.().scheduler;e?e.enqueue("async",()=>d.refresh(),{scope:f,key:`asyncSignal:${f}:refresh`}):d.refresh()}function m(){for(const e of[...p])e(d)}return d},isAsyncSignal:t=>Boolean(t?.[e])}})(),t=(()=>{const e=new Set(["handler","component","asyncSignal","partial","route"]);function t(t={}){const r=(e=>{if("string"!=typeof e||0===e.length)throw new TypeError("registryAssets.baseUrl must be a non-empty string.");return a(e)||e.startsWith("/")||e.startsWith("./")||e.startsWith("../")?s(e):`/${o(e)}`})(t.baseUrl??"_async"),n={component:"component",handler:"handler",asyncSignal:"asyncSignal",partial:"partial",route:"route",...t.paths??{}};for(const[t,r]of Object.entries(n))if(e.has(t)&&("string"!=typeof r||0===r.length))throw new TypeError(`Registry asset path for "${t}" must be a non-empty string.`);return{baseUrl:r,paths:n}}function r(e){return Boolean(e&&"object"==typeof e&&!Array.isArray(e)&&"string"==typeof e.url)}function n(t,n,i,c){if(!e.has(t))throw new Error(`Registry type "${t}" does not support lazy descriptors.`);if(!r(i))throw new TypeError(`Registry descriptor for "${t}:${n}" requires a url.`);const{path:u,hash:l}=(e=>{const t=e.indexOf("#");return-1===t?{path:e,hash:""}:{path:e.slice(0,t),hash:e.slice(t+1)}})(i.url),f=((e,t,r)=>{if(a(t)||t.startsWith("/")||t.startsWith("./")||t.startsWith("../"))return t;const n=r.paths[e]??e;return((...e)=>{const[t,...r]=e;return[s(t),...r.map(o)].filter(Boolean).join("/")})(r.baseUrl,n,t)})(t,u,c),p=l?[l]:((e,t)=>{const r=[],n=e.split(".").filter(Boolean).at(-1),o=t.split("/").filter(Boolean).at(-1)?.replace(/\.[^.]+$/,"");for(const e of[n,o,"default"])e&&!r.includes(e)&&r.push(e);return r})(n,u);return{moduleUrl:f,exportNames:p,url:l?`${f}#${l}`:f}}function o(e){return String(e).replace(/^\/+|\/+$/g,"")}function s(e){return String(e).replace(/\/+$/g,"")}function a(e){return/^[A-Za-z][A-Za-z\d+.-]*:/.test(e)}function i(e){return!e||"object"!=typeof e||Array.isArray(e)?JSON.stringify(e):JSON.stringify(Object.keys(e).sort().map(t=>[t,e[t]]))}return{defineRegistrySnapshot:(e={})=>{if(!e||"object"!=typeof e||Array.isArray(e))throw new TypeError("defineRegistrySnapshot(snapshot) requires an object.");return e},createLazyRegistry:(e={})=>{const o=t(e.registryAssets??e.assets),s=e.importModule??(e=>import(e)),a=new Map,i=new Map;return{registryAssets:o,resolveUrl:(e,t,r)=>n(e,t,r,o),async resolve(e,t,c){if(!r(c))return c;const u=`${e}:${t}`;if(i.has(u))return i.get(u);const l=n(e,t,c,o);let f,p=a.get(l.moduleUrl);p||(p=Promise.resolve().then(()=>s(l.moduleUrl)),a.set(l.moduleUrl,p));try{f=await p}catch(r){throw a.get(l.moduleUrl)===p&&a.delete(l.moduleUrl),new Error(`Lazy ${e} "${t}" failed to import ${l.moduleUrl}: ${h=r,h instanceof Error?h.message:String(h)}`,{cause:r})}var h;const d=((e,t,r,n)=>{for(const r of t)if(r in e)return e[r];throw new Error(`Lazy ${r} "${n}" did not export ${t.map(e=>`"${e}"`).join(", ")}.`)})(f,l.exportNames,e,t);return i.set(u,d),d},inspect:()=>({registryAssets:o,modules:[...a.keys()],exports:[...i.keys()]})}},normalizeRegistryAssets:t,isLazyDescriptor:r,sameRegistryValue:(e,t)=>e===t||!(!r(e)||!r(t))&&i(e)===i(t),publicRegistryValue:(e,t)=>r(e)?{...e}:{id:t}}})(),r=(()=>{const{publicRegistryValue:e}=t,r=new Set(["signal","handler","server","partial","route","component","asyncSignal"]),n=new Set(["cache.browser","cache.server"]),o=new Set(["cache.browser.entries","cache.server.entries"]),s=new Set([...r,...n,...o]);function a(e){if(!s.has(e))throw new Error(`Unknown Async registry type "${e}".`);return e}function i(e,t){if("string"!=typeof t||0===t.length)throw new TypeError(`${e} id must be a non-empty string.`)}function c(t,r,n,s){return"server"===t&&"browser"===s.target?e(n,r):o.has(t)?n?.value:n}function u(e,t){return"cache.server.entries"===e&&"browser"===t}function l(e){const t={};for(const[r,n]of e)t[r]="function"==typeof n?.snapshot?n.snapshot():n?.value??n;return t}function f(t){const r={};for(const[n,o]of t)r[n]=e(o,n);return r}function p(e){return Object.fromEntries(e)}function h(e){const t={};for(const[r,n]of e)t[r]=n?.value;return t}function d(e){return e&&"object"==typeof e&&Object.hasOwn(e,"value")?e:{value:e}}return{createRegistryStore:function e(t={},n={}){const o=n.backing??{signal:new Map,handler:new Map,server:new Map,partial:new Map,route:new Map,component:new Map,asyncSignal:new Map,cache:{browser:new Map,server:new Map},cacheEntries:{browser:new Map,server:new Map}},s=n.target??"server",y={target:s,register(e,t,r){const n=y._map(e);if(i(e,t),n.has(t))throw new Error(`${e} "${t}" is already registered.`);return n.set(t,r),t},registerMany(e,t={}){for(const[r,n]of Object.entries(t??{}))y.register(e,r,n);return y},set(e,t,r){const n=y._map(e);return i(e,t),n.set(t,r),r},unregister:(e,t)=>y.delete(e,t),delete:(e,t)=>y._map(e).delete(t),keys:e=>u(e,s)?[]:[...y._map(e).keys()],entries(e,t={}){const r=a(e);return u(r,t.target??s)?[]:[...y._map(r)].map(([e,n])=>[e,c(r,e,n,{target:s,...t})])},has:(e,t)=>(i(e,t),!u(e,s)&&y._map(e).has(t)),get(e,t,r={}){i(e,t);const n=a(e);if(u(n,r.target??s))return;const o=y._map(n).get(t);return void 0!==o?c(n,t,o,{target:s,...r}):void 0},snapshot(e={}){const t=e.target??s;return{signal:l(o.signal),handler:f(o.handler),server:f(o.server),partial:f(o.partial),route:p(o.route),component:f(o.component),asyncSignal:f(o.asyncSignal),cache:{browser:p(o.cache.browser),server:p(o.cache.server)},entries:{browser:h(o.cacheEntries.browser),server:"browser"===t?{}:h(o.cacheEntries.server)}}},rawSnapshot:()=>({signal:Object.fromEntries(o.signal),handler:Object.fromEntries(o.handler),server:Object.fromEntries(o.server),partial:Object.fromEntries(o.partial),route:Object.fromEntries(o.route),component:Object.fromEntries(o.component),asyncSignal:Object.fromEntries(o.asyncSignal),cache:{browser:Object.fromEntries(o.cache.browser),server:Object.fromEntries(o.cache.server)}}),view:(t={})=>e(void 0,{backing:o,target:t.target??s}),_map(e){const t=a(e);if(r.has(t))return o[t];if("cache.browser"===t)return o.cache.browser;if("cache.server"===t)return o.cache.server;if("cache.browser.entries"===t)return o.cacheEntries.browser;if("cache.server.entries"===t)return o.cacheEntries.server;throw new Error(`Unknown Async registry type "${e}".`)}};return((e,t={})=>{e.registerMany("signal",t.signal),e.registerMany("handler",t.handler),e.registerMany("server",t.server),e.registerMany("partial",t.partial),e.registerMany("route",t.route),e.registerMany("component",t.component),e.registerMany("asyncSignal",t.asyncSignal),e.registerMany("cache.browser",t.cache?.browser),e.registerMany("cache.server",t.cache?.server);const r=t.entries??{};for(const[t,n]of Object.entries(r.browser??{}))e.set("cache.browser.entries",t,d(n));for(const[t,n]of Object.entries(r.server??{}))e.set("cache.server.entries",t,d(n))})(y,t),y},attachRegistryInspection:(e,t,r)=>(Object.defineProperty(e,"registry",{configurable:!0,enumerable:!0,value:t}),e.keys=()=>t.keys(r),e.entries=()=>t.entries(r),e.inspect=()=>t.entries(r),e)}})(),n=(()=>{const{attachRegistryInspection:e,createRegistryStore:t}=r,n=Symbol.for("@async/framework.cacheDefinition");function o(e={}){return{[n]:!0,kind:"cache-definition",store:e.store??"memory",ttl:e.ttl}}function s(e){if("string"!=typeof e||0===e.length)throw new TypeError("Cache id must be a non-empty string.")}function a(e){if("string"!=typeof e||0===e.length)throw new TypeError("Cache key must be a non-empty string.")}return{defineCache:o,createCacheRegistry:(r={},{now:i=()=>Date.now(),registry:c,type:u="cache.browser"}={})=>{const l=c??t(),f=l._map(u),p=l._map(`${u}.entries`),h=new Map,d=e({register(e,t=o()){s(e);const r=(e=>e?.[n]?e:o(e))(t);if(f.has(e))throw new Error(`Cache "${e}" is already registered.`);return f.set(e,r),e},registerMany(e){for(const[t,r]of Object.entries(e??{}))d.register(t,r);return d},unregister:e=>(s(e),f.delete(e)),resolve:e=>(s(e),f.get(e)),get:e=>(a(e),y(e).value),set(e,t,r={}){a(e);const n=r.ttl??((e,t)=>{if(void 0!==t)return f.get(t);if(f.has(e))return f.get(e);const r=e.split(":")[0];return f.get(r)})(e,r.cache)?.ttl;return p.set(e,{value:t,expiresAt:void 0===n?void 0:i()+n}),t},async getOrSet(e,t,r={}){if(a(e),"function"!=typeof t)throw new TypeError("cache.getOrSet(key, fn) requires a function.");const n=y(e);if(n.found)return n.value;if(h.has(e))return h.get(e);let o;return o=Promise.resolve().then(t).then(t=>(h.get(e)===o&&d.set(e,t,r),t)).finally(()=>{h.get(e)===o&&h.delete(e)}),h.set(e,o),o},delete:e=>(a(e),h.delete(e),p.delete(e)),clear(e){if(void 0===e)return p.clear(),h.clear(),d;for(const t of[...p.keys()])t.startsWith(e)&&p.delete(t);for(const t of[...h.keys()])t.startsWith(e)&&h.delete(t);return d},snapshot(){const e={};for(const[t]of p){const{found:r,value:n}=y(t);r&&void 0!==n&&(e[t]=n)}return e},restore(e={}){for(const[t,r]of Object.entries(e??{}))d.set(t,r);return d},entryKeys:()=>[...p.keys()],entryEntries:()=>l.entries(`${u}.entries`),_adoptMany:()=>d},l,u);return d.registerMany(r),d;function y(e){const t=p.get(e);return t?void 0!==t.expiresAt&&t.expiresAt<=i()?(p.delete(e),{found:!1,value:void 0}):{found:!0,value:t.value}:{found:!1,value:void 0}}}}})(),o=(()=>{const e=Object.freeze({async:["async:"],class:["class:"],signal:["signal:"],on:["on:"]});function t(t={}){return{async:r(t.async,e.async),class:r(t.class,e.class),signal:r(t.signal,e.signal),on:r(t.on,e.on)}}function r(e,t){return(null==e?t:Array.isArray(e)?e:[e]).map(e=>{if("string"!=typeof e||0===e.length)throw new TypeError("Attribute prefixes must be non-empty strings.");return e})}return{defineAttributeConfig:(e={})=>t(e),normalizeAttributeConfig:t,attributeName:(e,r,n)=>t(e)[r][0]+n,readAttribute:(e,r,n,o)=>{for(const s of t(r)[n]){const t=`${s}${o}`;if(e.hasAttribute?.(t))return e.getAttribute(t)}return null},matchAttribute:(e,r,n)=>{for(const o of t(r)[n])if(e.startsWith(o))return e.slice(o.length);return null}}})(),s=(()=>{const{asyncSignal:n,isAsyncSignal:o}=e,{attachRegistryInspection:s,createRegistryStore:a}=r,{createLazyRegistry:i,isLazyDescriptor:c}=t,u=Symbol.for("@async/framework.signal"),l=Symbol.for("@async/framework.computed"),f=Symbol.for("@async/framework.effect"),p=Symbol.for("@async/framework.signalRef"),h=[];function d(e){let t=e;const r=new Set;return{[u]:!0,kind:"signal",get value(){return t},set value(e){this.set(e)},set:e=>(Object.is(t,e)||(t=e,(()=>{for(const e of[...r])e(t)})()),t),update(e){return this.set(e(t))},subscribe(e){if("function"!=typeof e)throw new TypeError("subscribe(fn) requires a function.");return r.add(e),()=>r.delete(e)},snapshot:()=>t}}function y(e,t){let r=e;for(const e of t){if(null==r)return;r=r[e]}return r}function g(e,t){return Array.isArray(e)?[...e]:e&&"object"==typeof e?{...e}:(r=t,String(Number(r))===String(r)?[]:{});var r}function w(e,t){const r=e.get(t);if(!r)throw new Error(`Signal "${t}" is not registered.`);return r}function m(e){if("string"!=typeof e||0===e.length)throw new TypeError("Signal id must be a non-empty string.")}return{createSignal:d,computed:e=>{if("function"!=typeof e)throw new TypeError("computed(fn) requires a function.");const t=d(void 0);return{[l]:!0,kind:"computed",get value(){return t.value},set:e=>t.set(e),update:e=>t.update(e),subscribe:e=>t.subscribe(e),snapshot:()=>t.snapshot(),_bindRegistry:(r,n)=>r.effect(()=>{t.set(e.call({signals:r,id:n,server:r._context?.().server,router:r._context?.().router,loader:r._context?.().loader,cache:r._context?.().cache,scheduler:r._context?.().scheduler}))})}},effect:e=>{if("function"!=typeof e)throw new TypeError("effect(fn) requires a function.");return{[f]:!0,kind:"effect",fn:e,_bindRegistry:t=>t.effect(e)}},createSignalRegistry:function(e={},t={}){const r=t.registry??a(),u=t.type??"signal",l=r._map(u),f=r._map("asyncSignal"),b=t.lazyRegistry??i(t),v=new Map,S={},E=new Set;let $=0,A=0;const R=s({register(e,t){if(m(e),l.has(e))throw new Error(`Signal "${e}" is already registered.`);const r=(e=>{return t=e,Boolean(t&&"object"==typeof t&&"function"==typeof t.subscribe)?e:d(e);var t})(t);return l.set(e,r),j(e,r),R.ref(e)},registerMany(e){for(const[t,r]of Object.entries(e??{}))R.register(t,r);return R},unregister:e=>(m(e),!!l.has(e)&&(v.get(e)?.(),v.delete(e),l.get(e)?._dispose?.(),l.delete(e),E.delete(e),!0)),ensure:(e,t)=>(m(e),k(e),l.has(e)||R.register(e,d(t)),R.ref(e)),has:e=>l.has(e)||f.has(e),get(e){const t=O(e);return(e=>{const t=h.at(-1);t&&t.add(e)})(t.path),((e,t)=>{if(o(e)&&t[0]?.startsWith("$")){const r=((e,t)=>{switch(t){case"$value":return e.value;case"$loading":return e.loading;case"$error":return e.error;case"$status":return e.status;case"$version":return e.version;default:return}})(e,t[0]);return y(r,t.slice(1))}return y(e.value,t)})(w(l,t.id),t.parts)},set(e,t){const r=O(e),n=w(l,r.id);if(0===r.parts.length)return n.set(t);const o=((e,t,r)=>{const n=g(e,t[0]);let o=n;for(let e=0;e<t.length-1;e+=1){const r=t[e],n=t[e+1];o[r]=g(o[r],n),o=o[r]}return o[t.at(-1)]=r,n})(n.value,r.parts,t);return n.set(o),t},update(e,t){if("function"!=typeof t)throw new TypeError("update(path, fn) requires a function.");return R.set(e,t(R.get(e)))},ref:e=>(m(e),k(e),((e,t)=>({[p]:!0,kind:"signal-ref",id:t,get value(){return e.get(t)},set value(r){e.set(t,r)},get loading(){return e._entry(t).loading??!1},get error(){return e._entry(t).error??null},get status(){return e._entry(t).status??"ready"},get version(){return e._entry(t).version??0},get:()=>e.get(t),set:r=>e.set(t,r),update:r=>e.update(t,r),subscribe:r=>e.subscribe(t,r),refresh(){const r=e._entry(t);if("function"!=typeof r.refresh)throw new Error(`Signal "${t}" cannot refresh.`);return r.refresh()},cancel(r){const n=e._entry(t);if("function"!=typeof n.cancel)throw new Error(`Signal "${t}" cannot cancel.`);return n.cancel(r)},toString:()=>t,[Symbol.toPrimitive]:()=>t}))(R,e)),subscribe(e,t,r={}){if("function"!=typeof t)throw new TypeError("subscribe(path, fn) requires a function.");const n=O(e),o=w(l,n.id),s=++$;return o.subscribe(()=>{((e,t={})=>{const r=t.scheduler;if(!r||"sync"===t.phase)return e();r.enqueue(t.phase??"effect",e,{scope:t.scope,key:t.key})})(()=>t(R.get(n.path),{id:n.id,path:n.path,signal:o}),{...r,key:r.key??`signal:${n.path}:${s}`})})},snapshot(){const e={};for(const[t,r]of l)e[t]="function"==typeof r.snapshot?r.snapshot():r.value;return e},asyncSignal:(e,t)=>(R.register(e,n(e,t)),R.ref(e)),effect(e,t={}){let r,n=[],o=!1;const s=t.scheduler,a=++A,i=()=>{if(o)return;"function"==typeof r&&r();for(const e of n)e();n=[];const t=R._collectDependencies(()=>e.call({signals:R,server:S.server,router:S.router,loader:S.loader,cache:S.cache,scheduler:S.scheduler}));r=t.value,n=t.dependencies.map(e=>R.subscribe(e,c))},c=()=>{s?s.enqueue(t.phase??"effect",i,{scope:t.scope,key:t.key??`effect:${a}`}):i()};return i(),()=>{o=!0,"function"==typeof r&&r();for(const e of n)e()}},destroy(){for(const e of v.values())e();v.clear();for(const e of l.values())e._dispose?.();l.clear()},_collectDependencies(e){const t=new Set;h.push(t);try{return{value:e(),dependencies:[...t]}}finally{h.pop()}},_entry:e=>(k(e),w(l,e)),_setContext:(e={})=>(Object.assign(S,e),R),_context:()=>S,_adoptMany(e={}){for(const t of Object.keys(e??{}))l.has(t)&&j(t,l.get(t));return R}},r,u);for(const[e,t]of l)j(e,t);return R.registerMany(e),R;function j(e,t){if(E.has(e)||"function"!=typeof t?._bindRegistry)return;E.add(e);const r=t._bindRegistry(R,e);"function"==typeof r&&v.set(e,r)}function O(e){if("string"!=typeof e||0===e.length)throw new TypeError("Signal path must be a non-empty string.");const t=e.split(".");for(let r=t.length;r>0;r-=1){const n=t.slice(0,r).join(".");if(l.has(n)||f.has(n))return k(n),{id:n,parts:t.slice(r),path:e}}const[r,...n]=t;return{id:r,parts:n,path:e}}function k(e){if(l.has(e)||!f.has(e))return;const t=f.get(e);if(!c(t)&&"function"!=typeof t)throw new TypeError(`Async signal "${e}" must be a function or lazy descriptor.`);const r=n(e,async function(...r){const n=await b.resolve("asyncSignal",e,t);if("function"!=typeof n)throw new TypeError(`Async signal "${e}" did not resolve to a function.`);return n.apply(this,r)});l.set(e,r),j(e,r)}},isSignalRef:e=>Boolean(e?.[p]),signal:d}})(),a=(()=>{const{isSignalRef:e}=s,{attributeName:t,matchAttribute:r,normalizeAttributeConfig:n}=o,a=Symbol.for("@async/framework.template"),i=Symbol.for("@async/framework.rawHtml");function c(e){return Boolean(e?.[a])}function u(e,t={}){if(c(e)){const r=p(t);let n="";for(let t=0;t<e.strings.length;t+=1)n+=e.strings[t],t<e.values.length&&(n+=l(e.values[t],{...r,attribute:h(e.strings[t])}));return n}return l(e,p(t))}function l(n,o=p()){return n?.[i]?n.html:c(n)?u(n,o):o.attribute?((n,o)=>{const s=r(o.attribute.name,o.attributes,"signal"),a=r(o.attribute.name,o.attributes,"class"),i=((t,r)=>e(t)?t.id:"string"==typeof t&&r.signals?.has?.(t)?t:null)(n,o);if("value"===o.attribute.name&&i){const r=((t,r)=>e(t)?t.value:"string"==typeof t&&r.signals?.has?.(t)?r.signals.get(t):t)(n,o),s=t(o.attributes,"signal","value");return`${d(r)}${o.attribute.quote} ${s}=${o.attribute.quote}${d(i)}`}if(null!=s||null!=a){if(i)return d(i);if((e=>Boolean(e&&"object"==typeof e))(n))return d(((e,t)=>"function"!=typeof t.bind?e:t.bind(e))(n,o))}return f(n,o)})(n,o):Array.isArray(n)?n.map(e=>l(e,o)).join(""):e(n)?d(n.value):null==n||!1===n?"":d(n)}function f(t,r){return Array.isArray(t)?t.map(e=>f(e,r)).join(""):e(t)?d(t.value):null==t||!1===t?"":d(t)}function p(e={}){return{...e,attributes:n(e.attributes)}}function h(e){const t=e.match(/(?:^|[\s<])([^\s"'=<>`]+)\s*=\s*(["'])$/);return t?{name:t[1],quote:t[2]}:null}function d(e){return String(e).replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#39;")}return{html:(e,...t)=>({[a]:!0,strings:e,values:t}),isTemplateResult:c,rawHtml:e=>({[i]:!0,html:String(e??"")}),renderTemplate:u,escapeHtml:d}})(),i=(()=>{const{attributeName:e}=o,{escapeHtml:n,rawHtml:s,renderTemplate:i}=a,{attachRegistryInspection:c,createRegistryStore:u}=r,{createLazyRegistry:l,isLazyDescriptor:f}=t,p=Symbol.for("@async/framework.component");let h=0;function d(e){if("function"!=typeof e)throw new TypeError("defineComponent(fn) requires a function.");return Object.defineProperty(e,p,{configurable:!0,value:!0}),e}function y(e){return Boolean(e?.[p])}function g(e,t){if("string"!=typeof t||0===t.length)throw new TypeError("Scoped signal or handler name must be a non-empty string.");return`${e}.${t}`}return{defineComponent:d,createComponentRegistry:function(e={},t={}){const r=t.registry??u(),n=t.type??"component",o=r._map(n),s=t.lazyRegistry??l(t),a=new Map,i=c({register(e,t){if("string"!=typeof e||0===e.length)throw new TypeError("Component id must be a non-empty string.");if(!y(t)&&"function"!=typeof t&&!f(t))throw new TypeError(`Component "${e}" must be a component function.`);if(o.has(e))throw new Error(`Component "${e}" is already registered.`);return o.set(e,t),e},registerMany(e){for(const[t,r]of Object.entries(e??{}))i.register(t,r);return i},unregister(e){if("string"!=typeof e||0===e.length)throw new TypeError("Component id must be a non-empty string.");return a.delete(e),o.delete(e)},resolve(e){if("string"!=typeof e||0===e.length)throw new TypeError("Component id must be a non-empty string.");const t=o.get(e);return f(t)?(a.has(e)||a.set(e,async function(...r){const o=await s.resolve(n,e,t);if("function"!=typeof o)throw new TypeError(`Component "${e}" did not resolve to a function.`);return o.apply(this,r)}),a.get(e)):t},_adoptMany:()=>i},r,n);return i.registerMany(e),i},isComponent:y,renderComponent:function t(r,o={},a,c="component"){if(!y(r)&&"function"!=typeof r)throw new TypeError("renderComponent(Component) requires a component function.");const u=`${c}.${(e=>e.displayName||e.name||"anonymous")(r)}.${++h}`,l=[],f=[],p=[],d=[],w=[],m={attributes:a.attributes,signals:a.signals,bind(e){const t=a.loader?._registerBinding?.(e);if(!t)throw new Error("Inline template bindings require a Loader.");return w.push(t),t}},b=e=>i(e,m),v=(({runtime:r,scope:o,cleanups:a,attachHooks:i,visibleHooks:c,destroyHooks:u,renderScopedTemplate:l})=>{const{signals:f,handlers:p,loader:h,server:d,router:y,cache:w,scheduler:m}=r,b=new WeakMap;let v=0,S=0;const E={scope:o,signals:f,handlers:p,loader:h,server:d,router:y,cache:w,scheduler:m,signal(e,t){if(1===arguments.length){const t=g(o,"signal."+ ++S),r=f.ensure(t,e);return a.push(()=>f.unregister?.(t)),r}const r=g(o,e),n=!f.has(r),s=f.ensure(r,t);return n&&a.push(()=>f.unregister?.(r)),s},computed(e,t){const r=g(o,e),n=!f.has(r),s=f.ensure(r,void 0);n&&a.push(()=>f.unregister?.(r));const i=f.effect(()=>{f.set(r,t.call(E))});return a.push(i),s},asyncSignal(e,t){const r=g(o,e),n=!f.has(r);return f.has(r)||f.asyncSignal(r,t),n&&a.push(()=>f.unregister?.(r)),f.ref(r)},effect(e){const t=f.effect(()=>e.call(E),{scheduler:m,phase:"effect",scope:o});return a.push(t),t},handler(e,t){if("function"==typeof e&&void 0===t){const t=e;if(b.has(t))return b.get(t);const r=$("handler."+ ++v,t);return b.set(t,r),r}if("function"!=typeof t)throw new TypeError("this.handler(name, fn) or this.handler(fn) requires a function.");return $(e,t)},render(e,n={}){const u=t(e,n,r,o);return a.push(u.cleanup),i.push(e=>u.attach(e)),c.push(e=>u.visible(e,h._observeVisible)),s(u.html)},suspense(t,o){const a=t?.id;if(!a)throw new TypeError("this.suspense(signalRef, views) requires a signal ref.");const i=(e=>{const t="function"==typeof e?{ready:e}:e;if(!t||"object"!=typeof t||Array.isArray(t))throw new TypeError("this.suspense(signalRef, views) requires views to be a function or object.");for(const e of["loading","ready","error"])if(Object.hasOwn(t,e)&&void 0!==t[e]&&"function"!=typeof t[e])throw new TypeError(`this.suspense(signalRef, views) view "${e}" must be a function.`);return t})(o),c=[];for(const o of["loading","ready","error"]){const s=i[o];if(!s)continue;const u=e(r.attributes,"async",o),f=l(s.call(E,t));c.push(`<template ${u}="${n(a)}">${f}</template>`)}return s(c.join(""))},on(e,t){if("string"!=typeof e||0===e.length)throw new TypeError("Component lifecycle event must be a non-empty string.");if("function"!=typeof t)throw new TypeError(`Component lifecycle "${e}" requires a function.`);const r="mount"===e?"attach":e;if("attach"!==r)if("visible"!==r){if("destroy"!==r)throw new Error(`Unsupported component lifecycle event "${e}".`);u.push(()=>t.call(E))}else c.push(e=>t.call(E,e));else i.push(e=>t.call(E,e))},onMount(e){E.on("attach",e)},onVisible(e){E.on("visible",e)}};return E;function $(e,t){const r=g(o,e);return p.register(r,e=>t.call({...E,...e},e)),a.push(()=>p.unregister?.(r)),r}})({runtime:a,scope:u,cleanups:l,attachHooks:f,visibleHooks:p,destroyHooks:d,renderScopedTemplate:b});return{html:b(r.call(v,o)),attach(e){for(const t of f)a.scheduler?.enqueue("lifecycle",()=>{const r=t(e);"function"==typeof r&&l.push(r)},{scope:u,key:`attach:${f.indexOf(t)}`})??S(t,e)},mount(e){this.attach(e)},visible(e,t){for(const r of p){const n=t(e,()=>{a.scheduler?.enqueue("lifecycle",()=>{const t=r(e);"function"==typeof t&&l.push(t)},{scope:u,key:`visible:${p.indexOf(r)}`})??E(r,e)});"function"==typeof n&&l.push(n)}},cleanup(){for(;d.length>0;)d.pop()?.();for(a.scheduler?.markScopeDestroyed(u);l.length>0;)l.pop()?.();for(;w.length>0;)a.loader?._releaseBinding?.(w.pop())}};function S(e,t){const r=e(t);"function"==typeof r&&l.push(r)}function E(e,t){const r=e(t);"function"==typeof r&&l.push(r)}},component:d}})(),c=(()=>{const e=new Set(["value","signals","boundary","html","redirect","error"]),t=Symbol.for("@async/framework.appliedServerResult"),r=new WeakSet;async function n(e,n={}){if(!h(e))return e;if(e[t]||r.has(e))return e;if(e.signals&&n.signals)for(const[t,r]of Object.entries(e.signals))n.signals.set?.(t,r);if(e.cache?.browser&&n.cache?.restore&&n.cache.restore(e.cache.browser),e.boundary&&Object.hasOwn(e,"html")&&n.loader?.swap?.(e.boundary,e.html),e.redirect&&await(n.router?.navigate?.(e.redirect)),e.error)throw(o=e.error)instanceof Error?o:o&&"object"==typeof o&&"string"==typeof o.message?Object.assign(new Error(o.message),o):new Error(String(o));var o;return Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:!0}),e}function o(e){return h(e)&&Object.hasOwn(e,"value")?e.value:e}function s(e={}){const t=l(e);if(t)return f(new t.ownerDocument.defaultView.FormData(t));const r=e.element??e.el??e.event?.target;return r?{value:"value"in r?r.value:void 0,checked:"checked"in r?r.checked:void 0,dataset:r.dataset?{...r.dataset}:{}}:{}}function a(e,t={},r=()=>({})){const s=new Map;return function i(c){const u=c.join(".");if(s.has(u))return s.get(u);const l=new Proxy(async(...t)=>{if(0===c.length)throw new Error("Server namespace is not directly callable.");const s=r()??{},a=await e(c.join("."),t,s);return await n(a,s),o(a)},{get(n,o){if("then"!==o)return o in n?n[o]:0===c.length&&"_withContext"===o?(n={})=>a(e,t,()=>({...r()??{},...n})):0===c.length&&"run"===o&&"function"==typeof t.run?(e,n=[],o={})=>t.run(e,n,{...r()??{},...o}):0===c.length&&Object.hasOwn(t,o)?t[o]:o===Symbol.toStringTag?"AsyncServerNamespace":"toString"===o?()=>0===c.length?"server":`server.${c.join(".")}`:i([...c,String(o)])}});return s.set(u,l),l}([])}function i(e=[],t){const r={};for(const n of e)r[n]=c(t,n);return r}function c(e,t){if(!e||"function"!=typeof e.get)throw new Error(`Signal "${t}" cannot be read without a signal registry.`);return e.get(t)}function u(e,t,{forServer:r}={}){if(("$event"===e||"$el"===e)&&r)throw new Error(`${e} cannot be passed to a server command.`);if("$event"===e)return t.event;if("$el"===e)return t.element??t.el;if("$value"===e){const e=t.element??t.el??t.event?.target;return e?.value}if("$checked"===e){const e=t.element??t.el??t.event?.target;return e?.checked}if("$form"===e){const e=l(t);return e?f(new e.ownerDocument.defaultView.FormData(e)):{}}if("$dataset"===e){const e=t.element??t.el??t.event?.target;return e?.dataset?{...e.dataset}:{}}throw new Error(`Event local "${e}" is not supported.`)}function l(e){const t=e.event,r=e.element??e.el??t?.target;return"FORM"===r?.tagName?r:"submit"===t?.type&&"FORM"===t.target?.tagName?t.target:"submit"===t?.type&&r?.form?r.form:null}function f(e){const t={};for(const[r,n]of e.entries())Object.hasOwn(t,r)?t[r]=Array.isArray(t[r])?[...t[r],n]:[t[r],n]:t[r]=n;return t}function p(e,t=new Set){if("bigint"==typeof e)throw new Error("Server proxy JSON transport does not support BigInt values.");if(null==e||"object"!=typeof e)return;if(t.has(e))throw new Error("Server proxy JSON transport does not support circular values.");t.add(e);const r=Object.prototype.toString.call(e);if("[object File]"===r||"[object Blob]"===r||"[object FormData]"===r)throw new Error("Server proxy JSON transport does not support File, Blob, or FormData values yet.");if(Array.isArray(e)){for(const r of e)p(r,t);t.delete(e)}else{for(const r of Object.values(e))p(r,t);t.delete(e)}}function h(t){return!(!t||"object"!=typeof t||Array.isArray(t))&&Object.keys(t).some(t=>e.has(t))}function d(e){if("string"!=typeof e||0===e.length)throw new TypeError("Server function id must be a non-empty string.")}return{createServerProxy:({endpoint:e="/__async/server",fetch:t=globalThis.fetch?.bind(globalThis),signals:c,loader:u,router:l,cache:f,scheduler:h,headers:y={}}={})=>{if("function"!=typeof t)throw new TypeError("createServerProxy(...) requires fetch to be available.");const g={signals:c,loader:u,router:l,cache:f,scheduler:h};async function w(a,c=[],u={}){d(a);const l={...g,...u},f={args:c,input:u.input??s(l),signals:u.signalValues??i(u.signalPaths,l.signals)};p(f);const h=await t(((e,t)=>`${String(e).replace(/\/$/,"")}/${encodeURIComponent(t)}`)(e,a),{method:"POST",headers:{"content-type":"application/json",...y},body:JSON.stringify(f),signal:u.abort});if(!h.ok)throw new Error(`Server function "${a}" failed with ${h.status}.`);const w=await(async e=>(e.headers.get("content-type")??"").includes("application/json")?e.json():{value:await e.text()})(h);return await n(w,l),(m=o(w))&&"object"==typeof m&&r.add(m),m;var m}return a(w,{run:w,_setContext(e={}){Object.assign(g,e)}},()=>g)},resolveServerCommandArguments:(e,t={})=>{const r=[],n={},o=[];for(const s of e){if("local"===s.type){r.push(u(s.name,t,{forServer:!0}));continue}const e=c(t.signals,s.path);r.push(e),n[s.path]=e,o.push(s.path)}return{args:r,signalValues:n,signalPaths:o}},applyServerResult:n,unwrapServerResult:o,defaultInput:s,createServerNamespace:a,createSignalReader:e=>e&&"function"!=typeof e.get?{get:t=>((e,t)=>String(t).split(".").reduce((e,t)=>e?.[t],e))(e,t),snapshot:()=>({...e})}:e,assertServerId:d}})(),u=(()=>{const{applyServerResult:e,defaultInput:n,resolveServerCommandArguments:o,unwrapServerResult:s}=c,{attachRegistryInspection:a,createRegistryStore:i}=r,{createLazyRegistry:u,isLazyDescriptor:l}=t,f=new Set(["prevent","preventDefault","stopPropagation","stopImmediatePropagation"]),p={prevent:h,preventDefault:h,stopPropagation(){this.event?.stopPropagation?.()},stopImmediatePropagation(){this.event?.stopImmediatePropagation?.()}};function h(){this.event?.preventDefault?.()}function d(e){if("string"!=typeof e||0===e.trim().length)throw new TypeError("Handler ref must be a non-empty string.");return e.split(";").map(e=>e.trim()).filter(Boolean).map(g)}function y(e){if("string"!=typeof e||0===e.length)throw new TypeError("Handler id must be a non-empty string.")}function g(e){if(e.startsWith("server."))return(e=>{const t=e.indexOf("(");if(-1===t||!e.endsWith(")"))throw new Error(`Server command "${e}" must be called with parentheses.`);const r=e.slice(7,t).trim();if(!(e=>/^[^.\s();]+(?:\.[^.\s();]+)*$/.test(e))(r))throw new Error(`Server command "${e}" has an invalid function id.`);return{type:"server",id:r,args:(n=e.slice(t+1,-1),0===n.trim().length?[]:n.split(",").map(e=>e.trim()).filter(Boolean).map(w))};var n})(e);if(e.includes("(")||e.includes(")"))throw new Error(`Command "${e}" is not supported.`);return{type:"handler",id:e}}function w(e){if(!/^[^\s,();]+$/.test(e))throw new Error(`Argument "${e}" is not supported.`);return e.startsWith("$")?{type:"local",name:e}:{type:"signal",path:e}}return{createHandlerRegistry:function(t={},r={}){const c=r.registry??i(),h=r.type??"handler",g=c._map(h),w=r.lazyRegistry??u(r),m=new Map,b=a({register(e,t){if(y(e),"function"!=typeof t&&!l(t))throw new TypeError(`Handler "${e}" must be a function.`);if(g.has(e))throw new Error(`Handler "${e}" is already registered.`);return g.set(e,t),e},registerMany(e){for(const[t,r]of Object.entries(e??{}))b.register(t,r);return b},unregister:e=>(y(e),m.delete(e),g.delete(e)),resolve(e){y(e);const t=g.get(e);return l(t)?(m.has(e)||m.set(e,async function(...r){const n=await w.resolve(h,e,t);if("function"!=typeof n)throw new TypeError(`Handler "${e}" did not resolve to a function.`);return n.apply(this,r)}),m.get(e)):t},async run(t,r={}){const a=d(t),i=[];let c=!1;const u={...r,handlers:b,input:r.input??n(r),stop(){c=!0}};for(const t of a){if(c)break;if("server"===t.type){if(!u.server||"function"!=typeof u.server.run)throw new Error(`Server command "${t.id}" cannot run without a server registry.`);const r=o(t.args,u),n=await u.server.run(t.id,r.args,{...u,signalPaths:r.signalPaths,signalValues:r.signalValues});await e(n,u),i.push(s(n));continue}const r=b.resolve(t.id);if(!r)throw new Error(`Handler "${t.id}" is not registered.`);const n=await r.call(u,u);f.has(t.id)&&r===p[t.id]||i.push(n)}return i},_adoptMany:()=>b},c,h);return((e,t)=>{for(const[r,n]of Object.entries(p))if(t.has(r)){if(t.get(r)!==n)throw new Error(`Handler "${r}" is already registered.`)}else e.register(r,n)})(b,g),b.registerMany(t),b},parseHandlerRef:d,isHandlerToken:e=>f.has(e)}})(),l=(()=>{const e=["binding","lifecycle","effect","async","post"];function t(){}return{createScheduler:(r={})=>{const n=[...r.phases??e],o=new Map(n.map(e=>[e,[]])),s=new Map,a=new Set,i=new WeakMap,c="function"==typeof r.onError?r.onError:void 0,u=r.maxDepth??100,l=r.strategy??"microtask";let f=!1,p=!1,h=!1,d=0,y=0,g=0;const w={strategy:l,phases:n,batch(e){if("function"!=typeof e)throw new TypeError("scheduler.batch(fn) requires a function.");E(),d+=1;let t=!1;try{const r=e();return r&&"function"==typeof r.then?(t=!0,r.finally(()=>{d-=1,m()})):r}finally{!t&&d>0&&(d-=1,m())}},enqueue(e,r,n={}){if(E(),(e=>{if(!o.has(e))throw new Error(`Unknown scheduler phase "${e}".`)})(e),"function"!=typeof r)throw new TypeError("scheduler.enqueue(phase, fn) requires a function.");const c=n.scope;if(void 0!==c&&a.has(c))return t;const u=void 0===n.key?void 0:`${e}:${(e=>void 0===e?"global":"object"==typeof e&&null!==e||"function"==typeof e?(i.has(e)||i.set(e,"scope:"+ ++g),i.get(e)):String(e))(c)}:${String(n.key)}`;if(u&&s.has(u))return s.get(u).cancel;const l={id:++y,phase:e,fn:r,scope:c,boundary:n.boundary,key:u,canceled:!1,cancel(){l.canceled=!0,l.key&&s.delete(l.key)}};return o.get(e).push(l),l.key&&s.set(l.key,l),m(),l.cancel},afterFlush:(e,t={})=>w.enqueue("post",e,t),async flush(){if(E(),p)return;h=!1,p=!0;let e=0;try{for(;v();){if(e+=1,e>u)throw new Error(`Scheduler exceeded maxDepth ${u}.`);for(const e of n)await b(e)}}finally{p=!1,v()&&m()}},async flushScope(e){if(E(),p)return;h=!1,p=!0;let t=0;try{for(;S(e);){if(t+=1,t>u)throw new Error(`Scheduler exceeded maxDepth ${u}.`);for(const t of n)await b(t,e)}}finally{p=!1,v()&&m()}},cancelScope(e){if(void 0===e)return w;for(const t of o.values())for(const r of t)r.scope===e&&r.cancel();return w},markScopeDestroyed:e=>(void 0!==e&&(a.add(e),w.cancelScope(e)),w),isScopeDestroyed:e=>void 0!==e&&a.has(e),inspect(){const e={};for(const[t,r]of o)e[t]=r.filter(e=>!e.canceled).length;return{strategy:l,phases:[...n],pending:e,scopesDestroyed:a.size,flushing:p,scheduled:h}},destroy(){f=!0;for(const e of o.values()){for(const t of e)t.cancel();e.length=0}s.clear(),a.clear()}};return w;function m(){var e;"manual"===l||f||p||d>0||h||(h=!0,e=()=>{f||w.flush()},"function"!=typeof queueMicrotask?Promise.resolve().then(e):queueMicrotask(e))}async function b(e,t){const r=o.get(e),n=[],i=[];for(const e of r.splice(0))e.canceled||(void 0===t||e.scope===t?i.push(e):n.push(e));r.push(...n);for(const e of i)if(e.key&&s.delete(e.key),!(e.canceled||void 0!==e.scope&&a.has(e.scope)))try{await e.fn()}catch(t){if(!c)throw t;c(t,e)}}function v(){for(const e of o.values())if(e.some(e=>!e.canceled))return!0;return!1}function S(e){for(const t of o.values())if(t.some(t=>!t.canceled&&t.scope===e))return!0;return!1}function E(){if(f)throw new Error("Scheduler has been destroyed.")}}}})(),f=(()=>{const{renderComponent:e}=i,{createHandlerRegistry:t}=u,{createScheduler:r}=l,{createSignalRegistry:n,isSignalRef:a}=s,{matchAttribute:c,normalizeAttributeConfig:f,readAttribute:p}=o,h="__async:inline:";function d({root:o,signals:s,handlers:i,server:u,router:l,cache:d,attributes:E,scheduler:O}={}){const T=o?.ownerDocument??o??globalThis.document,q=o??T,M=s??n(),C=i??t(),x=O??r(),L=!O,D=f(E),B=new Set,P=new WeakMap,N=new WeakMap,z=new WeakSet,H=new WeakSet,W=new WeakMap,U=new WeakSet,I=new Map,V=new WeakMap;let F=0,J=!1;const K={root:q,signals:M,handlers:C,server:u,router:l,cache:d,scheduler:x,attributes:D,start:()=>(ne(),K.scan(q),K),scan:(e=q)=>(ne(),(e=>{for(const t of R(e))for(const e of t.getAttributeNames?.()??[]){const r=c(e,D,"signal");if(r){if("text"===r){const r=t.getAttribute(e);G(t,`text:${r}`,r,e=>{t.textContent=e??""});continue}if("value"===r){const r=t.getAttribute(e);G(t,`value:${r}`,r,e=>{"value"in t&&t.value!==String(e??"")?t.value=e??"":"value"in t||t.setAttribute("value",e??"")}),Q(t,r);continue}if(r.startsWith("attr:")){const n=r.slice(5),o=t.getAttribute(e);G(t,`attr:${n}:${o}`,o,e=>$(t,n,e));continue}if(r.startsWith("prop:")){const n=r.slice(5),o=t.getAttribute(e);G(t,`prop:${n}:${o}`,o,e=>A(t,n,e));continue}if(r.startsWith("class:")){const n=r.slice(6),o=t.getAttribute(e);""===n||"{}"===n?Y(t,n,o):G(t,`class:${n}:${o}`,o,e=>{t.classList.toggle(n,Boolean(e))});continue}if("class"===r){const r=t.getAttribute(e);Y(t,"{}",r)}}}})(e),(e=>{for(const t of R(e))for(const e of t.getAttributeNames?.()??[]){const r=c(e,D,"class");null!=r&&Y(t,r,t.getAttribute(e))}})(e),(e=>{for(const t of R(e))if("function"==typeof t.getAttributeNames)for(const e of t.getAttributeNames()){const r=c(e,D,"on");r&&"attach"!==r&&"mount"!==r&&"visible"!==r&&Z(t,r,t.getAttribute(e))}})(e),(e=>{for(const t of R(e)){if(U.has(t))continue;const e=j(t,D);if(null!=e){if(!W.has(t)){const r=S(t,e,D);if(0===Object.keys(r).length||!M.has(e))continue;const n={id:e,templates:r,cleanup:M.subscribe(`${e}.$status`,()=>{x.enqueue("binding",()=>X(t),{scope:t,key:`boundary:${e}`})})};W.set(t,n),oe(n.cleanup,t)}X(t)}}})(e),(e=>{for(const t of R(e)){const e=ee(t,["attach","mount"]);if(0!==e.length&&!z.has(t)){z.add(t);for(const r of e)ue(t,()=>te(t,r),`attach:${r}`)}}for(const t of R(e)){const e=p(t,D,"on","visible");null!=e&&(H.has(t)||(H.add(t),oe(re(t,()=>ue(t,()=>te(t,e),`visible:${e}`)),t)))}})(e),K),swap(e,t){ne();const r=((e,t,r)=>{for(const n of R(e))if(j(n,r)===String(t))return n;return null})(q,e,D);if(!r)throw new Error(`Boundary "${e}" was not found.`);return ae(r),r.replaceChildren(k(t,T)),K.scan(r),r},mount(t,r,n={}){ne();const o=e(r,n,{signals:M,handlers:C,loader:K,server:K.server,router:K.router,cache:K.cache,scheduler:x,attributes:D});return ae(t),t.replaceChildren(k(o.html,t.ownerDocument)),K.scan(t),o.mount(t),o.visible(t,K._observeVisible),oe(o.cleanup,t,"children"),o},destroy(){if(!J){J=!0,(e=>{for(const t of R(e))x.markScopeDestroyed(t)})(q);for(const e of[...B])se(e);B.clear(),L&&x.destroy()}},_observeVisible:(e,t)=>re(e,t),_registerBinding(e){const t=`${h}${++F}`;return I.set(t,e),t},_releaseBinding(e){I.delete(e)}};function Z(e,t,r){const n=`${t}:${r}`,o=P.get(e)??new Set;if(o.has(n))return;o.add(n),P.set(e,o);const s=async t=>{try{await x.batch(()=>C.run(r,{signals:M,handlers:C,loader:K,server:K.server,router:K.router,cache:K.cache,scheduler:x,event:t,element:e,el:e,root:q}))}catch(t){_(e,t)}};e.addEventListener(t,s),oe(()=>e.removeEventListener(t,s),e)}function Y(e,t,r){if(""===t||"{}"===t){const t=b(e);let n=new Set;return void G(e,`class:{}:${r}`,r,r=>{const o=y(r),s=b(e);for(const e of n)o.has(e)||t.has(e)||s.delete(e);for(const e of o)s.add(e);v(e,s),n=o},{rawInline:!0})}G(e,`class:${t}:${r}`,r,r=>{((e,t,r)=>{const n=b(e);for(const e of y(t))r?n.add(e):n.delete(e);v(e,n)})(e,t,Boolean(r))})}function G(e,t,r,n,o={}){const s=N.get(e)??new Set;if(s.has(t))return;s.add(t),N.set(e,s);const a=()=>((e,t={})=>{if(m(e)){const r=I.get(e);return t.rawInline?r:g(r)}return M.get(e)})(r,o);n(a()),oe(((e,t)=>{if(!m(e))return M.subscribe(e,t);const r=w(I.get(e)).map(e=>e.subscribe(t));return()=>{for(const e of r)e()}})(r,()=>{x.enqueue("binding",()=>n(a()),{scope:e,key:t})}),e)}function Q(e,t){Z(e,"input",`__async:set:${t}`),Z(e,"change",`__async:set:${t}`),C.resolve(`__async:set:${t}`)||C.register(`__async:set:${t}`,({element:e})=>{((e,t)=>{if(!m(e))return M.set(e,t);const r=I.get(e);if(a(r))return r.set(t);throw new Error(`Inline binding "${e}" is not writable.`)})(t,e.value)})}function X(e){const t=W.get(e);if(!t)return;const r=M.get(`${t.id}.$status`),n=((e,t)=>"ready"===t?e.ready??e.loading??e.error:"error"===t?e.error??e.ready??e.loading:e.loading??e.ready??e.error)(t.templates,r);if(n){ae(e),e.replaceChildren(n.content.cloneNode(!0)),U.add(e);try{K.scan(e)}finally{U.delete(e)}}}function ee(e,t){const r=[];for(const n of t){const t=p(e,D,"on",n);null!=t&&r.push(t)}return r}async function te(e,t){try{const r=await C.run(t,{signals:M,handlers:C,loader:K,server:K.server,router:K.router,cache:K.cache,scheduler:x,element:e,el:e,root:q});for(const t of r)"function"==typeof t&&oe(t,e)}catch(t){_(e,t)}}function re(e,t){const r=(e.ownerDocument?.defaultView??globalThis).IntersectionObserver??globalThis.IntersectionObserver;if(!r)return x.enqueue("lifecycle",()=>{J||t(e)},{scope:e,key:"visible:fallback"}),()=>{};const n=new r(r=>{r.some(e=>e.isIntersecting)&&(n.disconnect(),t(e))});return n.observe(e),()=>n.disconnect()}function ne(){if(J)throw new Error("Loader has been destroyed.")}function oe(e,t,r="self"){if("function"!=typeof e)return e;if(B.add(e),t){const n=V.get(t)??[];n.push({cleanup:e,mode:r}),V.set(t,n)}return e}function se(e){"function"==typeof e&&B.has(e)&&(B.delete(e),e())}function ae(e){ce(e,"children");for(const t of[...e.childNodes??[]])ie(t)}function ie(e){if(1===e.nodeType)for(const t of R(e))ce(t),x.markScopeDestroyed(t)}function ce(e,t){const r=V.get(e);if(!r)return;const n=[];for(const e of r)t&&e.mode!==t?n.push(e):se(e.cleanup);n.length>0?V.set(e,n):V.delete(e)}function ue(e,t,r){x.enqueue("lifecycle",t,{scope:e,key:r})}return M._setContext?.({server:K.server,router:K.router,loader:K,cache:K.cache,scheduler:x}),K.server?._setContext?.({signals:M,handlers:C,loader:K,router:K.router,cache:K.cache,scheduler:x}),K}function y(e,t=new Set){if(null==e||!1===e)return t;if(a(e)){const r=e.value;return!0===r?(t.add(e.id.split(".").at(-1)),t):y(r,t)}if("string"==typeof e){for(const r of e.split(/\s+/).filter(Boolean))t.add(r);return t}if(Array.isArray(e)){for(const r of e)y(r,t);return t}if("object"==typeof e){for(const[r,n]of Object.entries(e))(a(n)?n.value:n)&&y(r,t);return t}return!0!==e&&t.add(String(e)),t}function g(e){return a(e)?e.value:Array.isArray(e)?e.map(g):e&&"object"==typeof e?Object.fromEntries(Object.entries(e).map(([e,t])=>[e,g(t)])):e}function w(e,t=new Map){if(a(e))return t.set(e.id,e),[...t.values()];if(Array.isArray(e)){for(const r of e)w(r,t);return[...t.values()]}if(e&&"object"==typeof e)for(const r of Object.values(e))w(r,t);return[...t.values()]}function m(e){return"string"==typeof e&&e.startsWith(h)}function b(e){return y(e.getAttribute("class")??"")}function v(e,t){const r=[...t].join(" ");0!==r.length?e.setAttribute("class",r):e.removeAttribute("class")}function S(e,t,r){const n={};for(const o of[...e.children].filter(e=>"TEMPLATE"===e.tagName))E(o,"loading",t,e,r)&&(n.loading=o),E(o,"ready",t,e,r)&&(n.ready=o),E(o,"error",t,e,r)&&(n.error=o);return n}function E(e,t,r,n,o){return p(e,o,"async",t)===r||O(n)&&e.hasAttribute?.(t)}function $(e,t,r){if(!1===r||null==r)return e.removeAttribute(t),void(t in e&&(e[t]=!1));e.setAttribute(t,!0===r?"":String(r)),t in e&&(e[t]=r)}function A(e,t,r){e[t]=null!=r?r:""}function R(e){return(e=>{const t=[];return 1===e?.nodeType&&e.matches?.("*")&&t.push(e),t.push(...e?.querySelectorAll?.("*")??[]),t})(e)}function j(e,t){return O(e)&&e.hasAttribute?.("for")?e.getAttribute("for"):p(e,t,"async","boundary")}function O(e){return"ASYNC-SUSPENSE"===e?.tagName}function k(e,t){if(11===e?.nodeType)return e;if("TEMPLATE"===e?.tagName)return e.content.cloneNode(!0);if(e?.nodeType){const r=t.createDocumentFragment();return r.append(e),r}const r=t.createElement("template");return r.innerHTML=String(e??""),r.content.cloneNode(!0)}function _(e,t){const r=e.ownerDocument?.defaultView?.CustomEvent??globalThis.CustomEvent;e.dispatchEvent(new r("async:error",{bubbles:!0,detail:{error:t}}))}return{Loader:d,AsyncLoader:d}})(),p=(()=>{const{isTemplateResult:e,renderTemplate:n}=a,{attachRegistryInspection:o,createRegistryStore:s}=r,{createLazyRegistry:i,isLazyDescriptor:c}=t;function u(e,t={}){return r=e,Boolean(r&&"object"==typeof r&&!Array.isArray(r)&&(Object.hasOwn(r,"html")||Object.hasOwn(r,"signals")||Object.hasOwn(r,"boundary")||Object.hasOwn(r,"redirect")||Object.hasOwn(r,"status")||Object.hasOwn(r,"cache")))?{...e,html:Object.hasOwn(e,"html")?l(e.html,t):e.html}:{html:l(e,t)};var r}function l(t,r){return t?.nodeType||"string"==typeof t?t:(e(t),n(t,function(e){return{attributes:e.loader?.attributes,signals:e.signals,bind:e.loader?._registerBinding?.bind(e.loader)}}(r)))}function f(e){if("string"!=typeof e||0===e.length)throw new TypeError("Partial id must be a non-empty string.")}return{createPartialRegistry:function(e={},t={}){const r=t.registry??s(),n=t.type??"partial",a=r._map(n),l=t.lazyRegistry??i(t),p=new Map,h=o({register(e,t){if(f(e),"function"!=typeof t&&!c(t))throw new TypeError(`Partial "${e}" must be a function.`);if(a.has(e))throw new Error(`Partial "${e}" is already registered.`);return a.set(e,t),e},registerMany(e){for(const[t,r]of Object.entries(e??{}))h.register(t,r);return h},unregister:e=>(f(e),p.delete(e),a.delete(e)),resolve(e){f(e);const t=a.get(e);return c(t)?(p.has(e)||p.set(e,async function(...r){const o=await l.resolve(n,e,t);if("function"!=typeof o)throw new TypeError(`Partial "${e}" did not resolve to a function.`);return o.apply(this,r)}),p.get(e)):t},async render(e,t={},r={}){f(e);const n=h.resolve(e);if(!n)throw new Error(`Partial "${e}" is not registered.`);const o={...r,id:e,props:t,cache:r.cache,partials:h};return u(await n.call(o,t),o)},_adoptMany:()=>h},r,n);return h.registerMany(e),h},normalizePartialResult:u}})(),h=(()=>{const{Loader:e}=f,{createHandlerRegistry:t}=u,{createScheduler:n}=l,{createSignalRegistry:a}=s,{applyServerResult:i}=c,{createRegistryStore:p}=r,{normalizeAttributeConfig:h}=o;function d(e,t={}){return{...t,partial:e}}function y(e={},t={}){const r=t.registry??p(),n=t.type??"route",o=r._map(n),s=[],a={registry:r,register(e,t){if(E(e),s.some(t=>t.pattern===e))throw new Error(`Route "${e}" is already registered.`);const r=g(e,t);return o.set(e,r.definition),s.push(r),v(s),r},registerMany(e){for(const[t,r]of Object.entries(e??{}))a.register(t,r);return a},unregister(e){E(e);const t=s.findIndex(t=>t.pattern===e);return-1!==t&&s.splice(t,1),o.delete(e)},match(e){const t=(e=>e instanceof URL?e:new URL(String(e),globalThis.location?.href??"http://localhost/"))(e).pathname;for(const e of s){const r=e.regex.exec(t);if(!r)continue;const n={};return e.keys.forEach((e,t)=>{n[e]=b(r[t+1]??"")}),{pattern:e.pattern,params:n,route:e.definition}}return null},entries:()=>s.map(({pattern:e,definition:t})=>({pattern:e,route:t})),keys:()=>[...o.keys()],inspect:()=>r.entries(n),_adoptMany(e={}){for(const t of Object.keys(e??{}))i(t,o.get(t));return a}};for(const[e,t]of o)i(e,t);return a.registerMany(e),a;function i(e,t){if(s.some(t=>t.pattern===e))return;const r=g(e,t);o.set(e,r.definition),s.push(r),v(s)}}function g(e,t){const r="string"==typeof t?d(t):t,{regex:n,keys:o}=(e=>{const t=[];if("*"===e)return{regex:/^.*$/,keys:t};if("/"===e)return{regex:/^\/$/,keys:t};const r=e.split("/").map(e=>e.startsWith(":")?(t.push(e.slice(1)),"([^/]+)"):String(e).replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("/");return{regex:new RegExp(`^${r}$`),keys:t}})(e);return{pattern:e,regex:n,keys:o,score:S(e),definition:r}}function w(e,t){return e?.closest?.(t)}function m(e){return Object.fromEntries(e.searchParams.entries())}function b(e){try{return decodeURIComponent(e)}catch{return e}}function v(e){e.sort((e,t)=>t.score-e.score||t.pattern.length-e.pattern.length)}function S(e){return"*"===e?-1:e.split("/").filter(Boolean).reduce((e,t)=>"*"===t?e:t.startsWith(":")?e+2:e+4,"/"===e?3:0)}function E(e){if("string"!=typeof e||"*"!==e&&!e.startsWith("/"))throw new TypeError('Route pattern must be a path string or "*".')}return{defineRoute:d,createRouteRegistry:y,createRouter:({mode:r="ssr-spa",root:o,boundary:s="route",routes:c=y(),loader:u,signals:l,handlers:f,server:p,cache:d,partials:g,fetch:b=globalThis.fetch?.bind(globalThis),routeEndpoint:v="/__async/route",attributes:S,scheduler:E}={})=>{const $=o?.ownerDocument??o??globalThis.document,A=o??$,R=l??u?.signals??a(),j=f??u?.handlers??t(),O=E??u?.scheduler??n(),k=!E&&!u?.scheduler,_=h(S??u?.attributes),T=u??e({root:A,signals:R,handlers:j,server:p,cache:d,scheduler:O,attributes:_}),q=!u,M=new Set;let C,x=!1,L=0;const D={mode:r,root:A,boundary:s,routes:c,loader:T,signals:R,handlers:j,server:p,cache:d,partials:g,scheduler:O,attributes:_,start:()=>(K(),T.router=D,R._setContext?.({router:D,loader:T,server:p,cache:d,scheduler:O}),q&&T.start(),"mpa"===r||"ssr"===r?(W(),D):((()=>{const e=e=>{const t=w(e.target,"a[href]");t&&!((e,t)=>{if(e.defaultPrevented||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return!0;if(t.target||t.hasAttribute("download"))return!0;const r=J(t.href),n=F();return r.origin!==n.origin||((e,t,r)=>e.origin===t.origin&&e.pathname===t.pathname&&e.search===t.search&&(e.hash!==t.hash||!0===r.getAttribute?.("href")?.startsWith("#")))(r,n,t)})(e,t)&&(e.preventDefault(),V(D.navigate(t.href)))},t=e=>{const t=w(e.target,"form");t&&!(e=>"get"!==String(e.method||"get").toLowerCase()||J(e.action).origin!==F().origin)(t)&&(e.preventDefault(),V(D.navigate((e=>{const t=J(e.action||e.ownerDocument.defaultView.location.href),r=new e.ownerDocument.defaultView.FormData(e);return t.search=new URLSearchParams(r).toString(),t.href})(t))))},r=()=>V(D.navigate(F(),{history:!1}));A.addEventListener?.("click",e),A.addEventListener?.("submit",t),$.defaultView?.addEventListener?.("popstate",r),M.add(()=>A.removeEventListener?.("click",e)),M.add(()=>A.removeEventListener?.("submit",t)),M.add(()=>$.defaultView?.removeEventListener?.("popstate",r))})(),"csr"===r?(V(D.navigate(F(),{replace:!0,initial:!0,source:"client"})),D):(W(),D))),match:e=>c.match(J(e)),prefetch(e){if(K(),"ssr-spa"===r&&"function"==typeof b)return P(e,{prefetch:!0});const t=D.match(e);return t?.route?.partial&&g?.resolve?.(t.route.partial)?g.render(t.route.partial,t.params,N(t)):"function"==typeof b?P(e,{prefetch:!0}):Promise.resolve(null)},async navigate(e,t={}){if(K(),"mpa"===r||"ssr"===r)return $.defaultView?.location?.assign?.(e),null;const n=J(e);return"ssr-spa"===r?(async(e,t={})=>{const r=D.match(e),n=z(e,r);U(e,r,{pending:!0,error:null});try{const r=await P(e.href,{signal:n.abort});return H(n)?(await B(r,e,t,n),H(n)?(I({pending:!1,error:null}),r):null):null}catch(e){if(!H(n))return null;throw I({pending:!1,error:e}),e}})(n,t):(async(e,t={})=>{const r=D.match(e);if(!r)return z(e,null),(e=>{U(e,null,{pending:!1,error:new Error(`No route matched ${e.pathname}${e.search}`)})})(e),null;const n=z(e,r);U(e,r,{pending:!0,error:null});try{if(!r.route?.partial||!g?.resolve?.(r.route.partial)){const t=new Error(`Route "${e.pathname}" does not have a registered partial.`);return H(n)&&I({pending:!1,error:t}),null}const o=await g.render(r.route.partial,r.params,N(r,n));return H(n)?(await B(o,e,t,n),H(n)?(I({pending:!1,error:null}),o):null):null}catch(e){if(!H(n))return null;throw I({pending:!1,error:e}),e}})(n,t)},destroy(){if(!x){x=!0,C?.controller.abort(new Error("Router has been destroyed."));for(const e of M)e();M.clear(),k&&O.destroy()}}};return D;async function B(e,t,r,n){H(n)&&(await i(e,{signals:R,loader:T,router:D,cache:d,scheduler:O,abort:n?.abort}),await O.flush(),H(n)&&(null==e?.html||e.boundary||e.redirect||(T.swap(s,e.html),await O.flush()),e?.redirect||!1===r.history||(r.replace?$.defaultView?.history?.replaceState?.({},"",t.href):$.defaultView?.history?.pushState?.({},"",t.href))))}async function P(e,{prefetch:t=!1,signal:r}={}){if("function"!=typeof b)throw new Error("Router navigation requires a partial registry or fetch.");const n=await b(`${v}?to=${encodeURIComponent(String(e))}`,{headers:{accept:"application/json, text/html"},signal:r});if(!n.ok)throw new Error(`Route "${e}" failed with ${n.status}.`);return t?n:(n.headers.get("content-type")??"").includes("application/json")?n.json():{boundary:s,html:await n.text()}}function N(e,t){return{params:e.params,route:e.route,router:D,signals:R,handlers:j,loader:T,server:p,cache:d,scheduler:O,abort:t?.abort}}function z(e,t){C?.controller.abort(new Error(`Router navigation superseded by ${e.pathname}${e.search}.`));const r=new AbortController,n={id:++L,controller:r,abort:r.signal,target:e,matched:t};return C=n,n}function H(e){return!x&&e&&C?.id===e.id&&!e.abort.aborted}function W(){const e=F();U(e,D.match(e),{pending:!1,error:null})}function U(e,t,r={}){R.ensure("router",{}),I({url:e.href,path:e.pathname,query:m(e),params:t?.params??{},route:t?.route??null,...r})}function I(e){R.ensure("router",{});for(const[t,r]of Object.entries(e))R.set(`router.${t}`,r)}function V(e){e.catch(e=>{x||(I({pending:!1,error:e}),((e,t)=>{const r=e.ownerDocument?.defaultView?.CustomEvent??globalThis.CustomEvent;"function"==typeof r&&e.dispatchEvent?.(new r("async:error",{bubbles:!0,detail:{error:t}}))})(A,e))})}function F(){return J($.defaultView?.location?.href??"http://localhost/")}function J(e){return e instanceof URL?e:new URL(String(e),$.defaultView?.location?.href??"http://localhost/")}function K(){if(x)throw new Error("Router has been destroyed.")}},route:d}})(),d=(()=>{const{createCacheRegistry:e}=n,{createComponentRegistry:a}=i,{createHandlerRegistry:d}=u,{Loader:y}=f,{createPartialRegistry:g}=p,{createRouteRegistry:w,createRouter:m}=h,{createScheduler:b}=l,{createServerNamespace:v}=c,{createSignal:S,createSignalRegistry:E}=s,{createRegistryStore:$}=r,{attributeName:A,normalizeAttributeConfig:R}=o,{createLazyRegistry:j,defineRegistrySnapshot:O,sameRegistryValue:k}=t,_=new Set(["signal","handler","server","partial","route","component","asyncSignal"]);function T(e,t={}){const r=$(void 0,{target:"browser"}),n=new Set,o=t.createRuntime??q,s={registry:r,use(e,t){const o=((e,t)=>{const r={signal:{},handler:{},server:{},partial:{},route:{},component:{},asyncSignal:{},cache:{browser:{},server:{}}};if("string"==typeof e){if(!_.has(e))throw new Error(`Unknown Async registry type "${e}".`);return r[e]=U(e,t),r}if(!e||"object"!=typeof e)throw new TypeError("Async.use(...) requires a registry type or module object.");for(const[t,n]of Object.entries(e))if("cache"!==t){if(!_.has(t))throw new Error(`Unknown Async registry type "${t}".`);r[t]=U(t,n)}else r.cache.browser={...n?.browser??{}},r.cache.server={...n?.server??{}};return r})(e,t);((e,t)=>{for(const r of _)L(e,r,t[r]);L(e,"cache.browser",t.cache.browser),L(e,"cache.server",t.cache.server)})(r,o);for(const e of n)e._applyUse(o);return s},snapshot:()=>r.rawSnapshot(),start(e={}){const t=o(s,e).start();return s.runtime=t,t},attachRoot:e=>(e=>(e.runtime||e.start(),e.runtime))(s).attachRoot(e),detachRoot:e=>s.runtime?.detachRoot(e)??s,applySnapshot:(e,t={})=>s.runtime?(s.runtime.applySnapshot(e,t),s):(((e,t={},r={})=>{const n=P(t);for(const[t,o]of Object.entries(n.signal))B(e,"signal",t,S(o),r);for(const t of["handler","server","partial","route","component","asyncSignal"])for(const[o,s]of Object.entries(n[t]))B(e,t,o,s,r)})(r,e,t),s),inspectRoots:()=>s.runtime?.inspectRoots()??{count:0,roots:[]},_attach:e=>(n.add(e),()=>s._detach(e)),_detach(e){n.delete(e)}};return e&&s.use(e),s}function q(t=M,r={}){const n=(o=t,Boolean(o&&"function"==typeof o.use&&"function"==typeof o.snapshot&&o.registry)?t:T(t??{}));var o;const s=r.target??"browser",i=r.scheduler??r.loader?.scheduler??b({strategy:"server"===s?"manual":"microtask"}),c=!r.scheduler&&!r.loader?.scheduler,u=R(r.attributes),l=r.lazyRegistry??j({registryAssets:r.registryAssets,importModule:r.importModule}),f=r.registry??n.registry.view({target:s}),p=r.signals??E(void 0,{registry:f,type:"signal",lazyRegistry:l}),h=r.handlers??d(void 0,{registry:f,type:"handler",lazyRegistry:l}),v=e(void 0,{registry:f,type:"cache.server"}),S=e(void 0,{registry:f,type:"cache.browser"}),$=r.serverFactory??W,A=r.server??$(void 0,{registry:f,type:"server"}),O=r.partials??g(void 0,{registry:f,type:"partial",lazyRegistry:l}),k=r.routes??w(void 0,{registry:f,type:"route"}),_=r.components??a(void 0,{registry:f,type:"component",lazyRegistry:l}),q=r.loader||Object.hasOwn(r,"root")?r.root:null;let L=r.loader,B=r.router,N=!1,z=()=>{},U=!1,I=!1;const F=new Map,J=q??globalThis.document,K=r.snapshot??("browser"===s?C(J,{attributes:u}):void 0);((e,t)=>{try{e.cache=t}catch{}})(A,v);const Z={app:n,registry:f,target:s,signals:p,handlers:h,server:A,partials:O,routes:k,components:_,browser:{cache:S},loader:L,router:B,scheduler:i,attributes:u,start:()=>(ee(),U||(U=!0,"server"!==s?(Q({cache:S}),p._setContext?.({server:A,loader:L,cache:S,scheduler:i}),L?(Y(L.root,L),L.start(),G(L.root)):null!=q&&Z.attachRoot(q)):(Q({cache:v}),p._setContext?.({server:A,cache:v,scheduler:i}))),Z),use:(e,t)=>(n.use(e,t),Z),attachRoot(e){if(ee(),"server"===s)throw new Error("Server runtimes cannot attach DOM roots.");if(!e)throw new TypeError("runtime.attachRoot(root) requires a root.");if(F.has(e))return Z;const t=0===F.size&&L?L:y({root:e,signals:p,handlers:h,server:A,cache:S,scheduler:i,attributes:u});return Y(e,t),t.start(),Q({cache:S}),p._setContext?.({server:A,loader:Z.loader,cache:S,scheduler:i}),G(e),Z},detachRoot(e){if(ee(),"server"===s)return Z;if(null==e){for(const e of new Set(F.values()))e.destroy?.();return F.clear(),B?.destroy?.(),B=void 0,N=!1,L=void 0,Z.loader=void 0,Z.router=void 0,Z}const t=F.get(e);if(!t)return Z;if(t.destroy?.(),F.delete(e),L===t){B?.destroy?.(),B=void 0,N=!1;const e=F.values().next().value;L=e,Z.loader=e,Z.router=void 0,e&&G(e.root)}return Z},inspectRoots:()=>({count:F.size,roots:[...F].map(([e,t])=>({root:e,loader:t,primary:t===L}))}),applySnapshot:(e,t={})=>(((e,t={},r={})=>{const n=P(t);for(const[t,r]of Object.entries(n.signal))H(e.signals,t,r);e.browser.cache.restore(n.cache.browser),D(e,"handler",n.handler,e.handlers,r),D(e,"server",n.server,e.server,r),D(e,"partial",n.partial,e.partials,r),D(e,"route",n.route,e.routes,r),D(e,"component",n.component,e.components,r),D(e,"asyncSignal",n.asyncSignal,null,r)})(Z,e,t),Z),async render(e){ee(),Q({cache:v}),p._setContext?.({server:A,cache:v,scheduler:i});const t=k.match(e);if(!t)return await i.flush(),{html:V("",{status:404,signals:p,browserCache:S,boundary:r.boundary??"route",attributes:u}),status:404,signals:p.snapshot(),cache:{browser:S.snapshot()}};const n=t.route.partial,o=n&&O.resolve(n)?await O.render(n,t.params,{params:t.params,route:t.route,signals:p,handlers:h,server:A,cache:v,browserCache:S,partials:O,scheduler:i,...X()}):{html:""};if(o.signals)for(const[e,t]of Object.entries(o.signals))H(p,e,t);o.cache?.browser&&S.restore(o.cache.browser),await i.flush();const s=o.status??200;return{html:V(o.html,{status:s,signals:p,browserCache:S,boundary:o.boundary??r.boundary??"route",attributes:u}),status:s,signals:p.snapshot(),cache:{browser:S.snapshot()}}},destroy(){if(I)return;I=!0,z(),B?.destroy?.();const e=new Set(F.values());for(const t of e)t.destroy?.();F.clear(),L&&!e.has(L)&&L?.destroy?.(),p.destroy?.(),c&&i.destroy()},_applyUse(e){((e,t)=>{x(e.signals,e.registry,t.signal),x(e.handlers,e.registry,t.handler),x(e.server,e.registry,t.server),x(e.partials,e.registry,t.partial),x(e.routes,e.registry,t.route),x(e.components,e.registry,t.component),((e,t,r)=>{if(r&&0!==Object.keys(r).length)for(const[n,o]of Object.entries(r))e.has(t,n)||e.register(t,n,o)})(e.registry,"asyncSignal",t.asyncSignal),x(e.browser.cache,e.registry,t.cache.browser),x(e.server.cache,e.registry,t.cache.server)})(Z,e)}};return A.cache=v,Z.server.cache=v,Z.applySnapshot(K,{strict:r.strictSnapshots??!0}),z=n._attach(Z),Z;function Y(e,t){F.set(e,t),L||(L=t,Z.loader=t),t.server=A,t.cache=S,t.scheduler=i}function G(e){!1!==B&&!N&&(B||((e,t)=>Boolean(t.routerOptions||t.mode||e.entries().length>0))(k,r))&&Z.loader&&(B=B??m({mode:r.mode??"ssr-spa",root:e,boundary:r.boundary??"route",routes:k,loader:Z.loader,signals:p,handlers:h,server:A,cache:S,partials:O,scheduler:i,fetch:r.fetch,routeEndpoint:r.routeEndpoint,attributes:u}),Z.router=B,Z.loader.router=B,Q({cache:S,router:B}),B.start(),N=!0)}function Q(e={}){const t=(e=>"function"==typeof e?.registerMany)(A)?v:e.cache;A._setContext?.({signals:p,loader:L,router:B,cache:t,scheduler:i,requestContext:r.requestContext,...X()})}function X(){const e=(t=r.requestContext)?"function"==typeof t.get?t.get()??{}:"function"==typeof t.getStore?t.getStore()??{}:{}:{};var t;return{requestContext:e,request:e.request??r.request,headers:e.headers??r.headers,cookies:e.cookies??r.cookies,locals:e.locals??r.locals}}function ee(){if(I)throw new Error("Async app runtime has been destroyed.")}}const M=T();function C(e=globalThis.document,{attributes:t}={}){const r=R(t),n=A(r,"async","snapshot"),o=e?.ownerDocument??e??globalThis.document,s=e??o;if(!s?.querySelectorAll&&!o?.querySelectorAll)return{};const a={};for(const e of new Set([s,o]))if(e?.querySelectorAll)for(const t of e.querySelectorAll("script[type='application/json'], script")){if(!t.hasAttribute?.(n))continue;const e=t.textContent?.trim()??"";if(!e)continue;let r;try{r=JSON.parse(e)}catch(e){throw new Error(`Could not parse Async snapshot: ${e instanceof Error?e.message:String(e)}`)}N(a,r,{strict:!0})}return a}function x(e,t,r){r&&0!==Object.keys(r).length&&(e?.registry!==t?e?.registerMany?.(r):e._adoptMany?.(r))}function L(e,t,r){for(const[n,o]of Object.entries(r??{}))e.register(t,n,o)}function D(e,t,r,n,o={}){if(r&&0!==Object.keys(r).length){for(const[n,s]of Object.entries(r))B(e.registry,t,n,s,o);n?._adoptMany?.(r)}}function B(e,t,r,n,o={}){const s=o.strict??!0,a=e._map(t);if(a.has(r)){if(k(a.get(r),n)||z(a.get(r),n))return;if(s)throw new Error(`${t} "${r}" is already registered with a different value.`)}else e.set(t,r,n)}function P(e={}){return{signal:{...e.signals??{},...e.signal??{}},handler:{...e.handler??{}},server:{...e.server??{}},partial:{...e.partial??{}},route:{...e.route??{}},component:{...e.component??{}},asyncSignal:{...e.asyncSignal??{}},cache:{browser:{...e.entries?.browser??{},...e.cache?.browser??{}}}}}function N(e,t,r={}){const n=P(O(t));e.signal={...e.signal??e.signals??{},...n.signal},e.signals=e.signal,e.cache={...e.cache??{},browser:{...e.cache?.browser??{},...n.cache.browser}};for(const t of["handler","server","partial","route","component","asyncSignal"]){e[t]=e[t]??{};for(const[o,s]of Object.entries(n[t]))if(Object.hasOwn(e[t],o)){if(k(e[t][o],s)||z(e[t][o],s))continue;if(r.strict??1)throw new Error(`${t} "${o}" is already declared with a different value.`)}else e[t][o]=s}return e}function z(e,t){if(e===t)return!0;try{return JSON.stringify(e)===JSON.stringify(t)}catch{return!1}}function H(e,t,r){const n=String(t).split(".")[0];e.has?.(n)?e.set(t,r):(e.register(n,S(t===n?r:{})),t!==n&&e.set(t,r))}function W(e={},t={}){const r=t.registry??$(),n=t.type??"server",o={},s={registry:r,register:(e,t)=>(r.register(n,e,t),e),registerMany(e){for(const[t,r]of Object.entries(e??{}))s.register(t,r);return s},unregister:e=>r.unregister(n,e),resolve(){},async run(e){throw new Error(`Server command "${e}" cannot run without a server proxy or server registry.`)},keys:()=>r.keys(n),entries:()=>r.entries(n),inspect:()=>r.entries(n),_setContext:(e={})=>(Object.assign(o,e),s),_adoptMany:()=>s};return s.registerMany(e),v((e,t,r)=>s.run(e,t,r),s,()=>o)}function U(e,t={}){if("signal"!==e)return{...t??{}};const r={};for(const[e,n]of Object.entries(t??{}))r[e]=I(n);return r}function I(e){return e&&"object"==typeof e&&"function"==typeof e.subscribe?e:S(e)}function V(e,{signals:t,browserCache:r,boundary:n,attributes:o}){const s={signals:t.snapshot(),cache:{browser:r.snapshot()}},a=A(o,"async","boundary"),i=A(o,"async","snapshot");return`<section ${a}="${c=n,String(c).replaceAll("&","&amp;").replaceAll('"',"&quot;").replaceAll("<","&lt;")}">${e??""}</section><script type="application/json" ${i}>${(e=>JSON.stringify(e).replaceAll("<","\\u003c"))(s)}<\/script>`;var c}return{defineApp:T,createApp:q,readSnapshot:C,Async:M}})(),y=(()=>{function e(e){if("string"!=typeof e||0===e.length)throw new TypeError("Boundary patch boundary must be a non-empty string.")}function t(e){return Boolean(e&&"object"==typeof e&&!Array.isArray(e))}return{createBoundaryReceiver:(r={})=>{const n=r.loader,o=r.signals??n?.signals,s=r.cache??n?.cache,a=r.scheduler??n?.scheduler,i=r.router??n?.router,c=r.recentLimit??50,u=!0===r.throwOnError,l="function"==typeof r.onApply?r.onApply:void 0,f="function"==typeof r.onIgnore?r.onIgnore:void 0,p="function"==typeof r.onError?r.onError:void 0,h="function"==typeof r.isScopeDestroyed?r.isScopeDestroyed:e=>a?.isScopeDestroyed?.(e)??a?.inspectDestroyed?.(e)??!1;if(!n||"function"!=typeof n.swap)throw new TypeError("createBoundaryReceiver(...) requires a loader with swap(boundary, html).");if(!Number.isInteger(c)||c<0)throw new TypeError("createBoundaryReceiver(...) recentLimit must be a non-negative integer.");const d=new Map,y=[];let g=!1;const w={async apply(r){if(g)throw new Error("Boundary receiver has been destroyed.");const c=(r=>{if(!r||"object"!=typeof r||Array.isArray(r))throw new TypeError("receiver.apply(patch) requires a boundary patch object.");if(e(r.boundary),"number"!=typeof r.seq||!Number.isFinite(r.seq))throw new TypeError("Boundary patch seq must be a finite number.");if(void 0!==r.signals&&!t(r.signals))throw new TypeError("Boundary patch signals must be an object.");if(void 0!==r.cache&&!t(r.cache))throw new TypeError("Boundary patch cache must be an object.");if(void 0!==r.cache?.browser&&!t(r.cache.browser))throw new TypeError("Boundary patch cache.browser must be an object.");if(void 0!==r.redirect&&("string"!=typeof r.redirect||0===r.redirect.length))throw new TypeError("Boundary patch redirect must be a non-empty string.");if(void 0!==r.parentScope&&"string"!=typeof r.parentScope)throw new TypeError("Boundary patch parentScope must be a string.");if(void 0!==r.scope&&"string"!=typeof r.scope)throw new TypeError("Boundary patch scope must be a string.");const n=Object.hasOwn(r,"html")&&null!=r.html,o=r.signals&&Object.keys(r.signals).length>0,s=r.cache?.browser&&Object.keys(r.cache.browser).length>0,a=Boolean(r.redirect),i=Object.hasOwn(r,"error");if(!(n||o||s||a||i))throw new TypeError("Boundary patch must include html, signals, cache.browser, redirect, or error.");return r})(r),y=(w=c.boundary,d.has(w)||d.set(w,{lastSeq:-1/0,applied:0,ignored:0,errored:0,lastStatus:void 0}),d.get(w));var w,b;if(c.seq<=y.lastSeq){const e={status:"ignored-stale",boundary:c.boundary,seq:c.seq,lastSeq:y.lastSeq};return y.ignored+=1,y.lastStatus=e.status,m(e),f?.(e,r),e}if(void 0!==c.parentScope&&h(c.parentScope)){const e={status:"ignored-destroyed",boundary:c.boundary,seq:c.seq,parentScope:c.parentScope};return y.ignored+=1,y.lastStatus=e.status,m(e),f?.(e,r),e}if(y.lastSeq=c.seq,Object.hasOwn(c,"error")){const e=(b=c.error)instanceof Error?b:b&&"object"==typeof b&&"string"==typeof b.message?Object.assign(new Error(b.message),b):new Error(String(b)),t={status:"errored",boundary:c.boundary,seq:c.seq,error:e};if(y.errored+=1,y.lastStatus=t.status,m(t),p?.(e,t,r),u)throw e;return t}if(c.signals){if(!o||"function"!=typeof o.set)throw new Error("Boundary patch includes signals, but no signal registry is available.");for(const[e,t]of Object.entries(c.signals))o.set(e,t)}if(c.cache?.browser){if(!s||"function"!=typeof s.restore)throw new Error("Boundary patch includes browser cache, but no cache registry is available.");s.restore(c.cache.browser)}if(null!=c.html&&n.swap(c.boundary,c.html),await(async(e,t)=>{e&&(void 0===t||"function"!=typeof e.flushScope?"function"==typeof e.flush&&await e.flush():await e.flushScope(t))})(a,c.scope),c.redirect){await(async(e,t,r)=>{if(t&&"function"==typeof t.navigate)return void await t.navigate(e);const n=r?.root?.ownerDocument?.defaultView?.location??globalThis.location;n?.assign?.(e)})(c.redirect,i,n);const e={status:"redirected",boundary:c.boundary,seq:c.seq,redirect:c.redirect};return y.applied+=1,y.lastStatus=e.status,m(e),l?.(e,r),e}const v={status:"applied",boundary:c.boundary,seq:c.seq};return y.applied+=1,y.lastStatus=v.status,m(v),l?.(v,r),v},inspect(){const e={};for(const[t,r]of d)e[t]={lastSeq:r.lastSeq,applied:r.applied,ignored:r.ignored,lastStatus:r.lastStatus},r.errored>0&&(e[t].errored=r.errored);return{destroyed:g,boundaries:e,recent:y.map(e=>({...e}))}},reset(t){if(void 0===t)return d.clear(),y.length=0,w;e(t),d.delete(t);for(let e=y.length-1;e>=0;e-=1)y[e].boundary===t&&y.splice(e,1);return w},destroy(){g=!0,d.clear(),y.length=0}};return w;function m(e){if(0!==c)for(y.push((e=>{const t={boundary:e.boundary,seq:e.seq,status:e.status};return"ignored-stale"===e.status&&(t.lastSeq=e.lastSeq),"ignored-destroyed"===e.status&&void 0!==e.parentScope&&(t.parentScope=e.parentScope),"redirected"===e.status&&(t.redirect=e.redirect),t})(e));y.length>c;)y.shift()}}}})(),g=(()=>{function e(e){return e?.reason??new Error("Operation aborted")}return{delay:(t,r)=>r?.aborted?Promise.reject(e(r)):new Promise((n,o)=>{let s=setTimeout(()=>{s=void 0,r?.removeEventListener?.("abort",a),n()},t);function a(){void 0!==s&&clearTimeout(s),s=void 0,r?.removeEventListener?.("abort",a),o(e(r))}r?.addEventListener?.("abort",a,{once:!0})})}})(),w=(()=>{const{Async:e}=d;return{defineAsyncContainerElement:function(t={}){const r=t.tagName??"async-container",n=t.customElements??globalThis.customElements;if(!n)throw new Error("defineAsyncContainerElement(...) requires customElements.");const o=n.get(r);if(o)return o;const s=t.app??t.Async??e,a=t.HTMLElement??t.window?.HTMLElement??globalThis.HTMLElement;if(!a)throw new Error("defineAsyncContainerElement(...) requires HTMLElement.");class i extends a{connectedCallback(){if(this.__asyncAttached)return;const e=s.runtime??s.start?.();e?.attachRoot?.(this),this.__asyncRuntime=e,this.__asyncAttached=!0}disconnectedCallback(){this.__asyncAttached&&(this.__asyncRuntime?.detachRoot?.(this),this.__asyncRuntime=void 0,this.__asyncAttached=!1)}}return n.define(r,i),i},defineAsyncSuspenseElement:(e={})=>{const t=e.tagName??"async-suspense",r=e.customElements??globalThis.customElements;if(!r)throw new Error("defineAsyncSuspenseElement(...) requires customElements.");const n=r.get(t);if(n)return n;const o=e.HTMLElement??e.window?.HTMLElement??globalThis.HTMLElement;if(!o)throw new Error("defineAsyncSuspenseElement(...) requires HTMLElement.");class s extends o{}return r.define(t,s),s}}})(),{asyncSignal:m}=e,{Async:b}=d,{createApp:v}=d,{defineApp:S}=d,{readSnapshot:E}=d,{attributeName:$}=o,{defineAttributeConfig:A}=o,{createBoundaryReceiver:R}=y,{createCacheRegistry:j}=n,{defineCache:O}=n,{component:k}=i,{createComponentRegistry:_}=i,{defineComponent:T}=i,{delay:q}=g,{defineAsyncContainerElement:M}=w,{defineAsyncSuspenseElement:C}=w,{createHandlerRegistry:x}=u,{html:L}=a,{createLazyRegistry:D}=t,{defineRegistrySnapshot:B}=t,{Loader:P}=f,{AsyncLoader:N}=f,{createPartialRegistry:z}=p,{createRegistryStore:H}=r,{createRouteRegistry:W}=h,{createRouter:U}=h,{defineRoute:I}=h,{route:V}=h,{createScheduler:F}=l,{applyServerResult:J}=c,{createServerProxy:K}=c,{resolveServerCommandArguments:Z}=c,{unwrapServerResult:Y}=c,{computed:G}=s,{createSignal:Q}=s,{createSignalRegistry:X}=s,{effect:ee}=s,{signal:te}=s;export{m as asyncSignal,b as Async,v as createApp,S as defineApp,E as readSnapshot,$ as attributeName,A as defineAttributeConfig,R as createBoundaryReceiver,j as createCacheRegistry,O as defineCache,k as component,_ as createComponentRegistry,T as defineComponent,q as delay,M as defineAsyncContainerElement,C as defineAsyncSuspenseElement,x as createHandlerRegistry,L as html,D as createLazyRegistry,B as defineRegistrySnapshot,P as Loader,N as AsyncLoader,z as createPartialRegistry,H as createRegistryStore,W as createRouteRegistry,U as createRouter,I as defineRoute,V as route,F as createScheduler,J as applyServerResult,K as createServerProxy,Z as resolveServerCommandArguments,Y as unwrapServerResult,G as computed,Q as createSignal,X as createSignalRegistry,ee as effect,te as signal};