@askrjs/askr 0.0.44 → 0.0.45

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.
Files changed (57) hide show
  1. package/dist/benchmark.js +2 -2
  2. package/dist/bin/askr-ssg.js.map +1 -1
  3. package/dist/boot/index.js.map +1 -1
  4. package/dist/common/env.js.map +1 -1
  5. package/dist/common/route-activity.js.map +1 -1
  6. package/dist/control/case.js.map +1 -1
  7. package/dist/control/show.js.map +1 -1
  8. package/dist/data/index.js.map +1 -1
  9. package/dist/foundations/icon/icon.js.map +1 -1
  10. package/dist/foundations/structures/layer.js.map +1 -1
  11. package/dist/foundations/structures/portal.js.map +1 -1
  12. package/dist/fx/fx.js.map +1 -1
  13. package/dist/fx/timing.js.map +1 -1
  14. package/dist/renderer/children.js.map +1 -1
  15. package/dist/renderer/cleanup.js.map +1 -1
  16. package/dist/renderer/dom.js.map +1 -1
  17. package/dist/renderer/evaluate.js.map +1 -1
  18. package/dist/renderer/fastpath.js.map +1 -1
  19. package/dist/renderer/for-commit.js.map +1 -1
  20. package/dist/renderer/keyed.js.map +1 -1
  21. package/dist/renderer/reconcile.js.map +1 -1
  22. package/dist/renderer/utils.js.map +1 -1
  23. package/dist/router/match.js.map +1 -1
  24. package/dist/router/navigate.js.map +1 -1
  25. package/dist/router/policy.js.map +1 -1
  26. package/dist/router/route.js.map +1 -1
  27. package/dist/runtime/component.d.ts +1 -0
  28. package/dist/runtime/component.d.ts.map +1 -1
  29. package/dist/runtime/component.js +16 -8
  30. package/dist/runtime/component.js.map +1 -1
  31. package/dist/runtime/context.js.map +1 -1
  32. package/dist/runtime/derive.js.map +1 -1
  33. package/dist/runtime/dev-namespace.js.map +1 -1
  34. package/dist/runtime/effect.js.map +1 -1
  35. package/dist/runtime/events.js.map +1 -1
  36. package/dist/runtime/fastlane.js.map +1 -1
  37. package/dist/runtime/for.js.map +1 -1
  38. package/dist/runtime/operations.js.map +1 -1
  39. package/dist/runtime/readable.d.ts +2 -1
  40. package/dist/runtime/readable.d.ts.map +1 -1
  41. package/dist/runtime/readable.js +41 -10
  42. package/dist/runtime/readable.js.map +1 -1
  43. package/dist/runtime/resource-cell.js.map +1 -1
  44. package/dist/runtime/scheduler.js.map +1 -1
  45. package/dist/runtime/selector.js.map +1 -1
  46. package/dist/ssg/batch-render.js.map +1 -1
  47. package/dist/ssg/create-static-gen.js.map +1 -1
  48. package/dist/ssg/generate-metadata.js.map +1 -1
  49. package/dist/ssg/incremental-manifest.js.map +1 -1
  50. package/dist/ssg/resolve-ssg-data.js.map +1 -1
  51. package/dist/ssg/write-static-files.js.map +1 -1
  52. package/dist/ssr/context.js.map +1 -1
  53. package/dist/ssr/escape.js.map +1 -1
  54. package/dist/ssr/index.js.map +1 -1
  55. package/dist/ssr/render-keys.js.map +1 -1
  56. package/dist/testing/index.js.map +1 -1
  57. package/package.json +3 -2
package/dist/benchmark.js CHANGED
@@ -10,8 +10,8 @@ import { BenchmarkTable } from "./bench/components/benchmark-table.js";
10
10
  installRendererBridge();
11
11
  const benchmarkMetadata = {
12
12
  packageName: "@askrjs/askr",
13
- packageVersion: "0.0.44",
14
- buildLabel: "0.0.44-local"
13
+ packageVersion: "0.0.45",
14
+ buildLabel: "0.0.45-local"
15
15
  };
16
16
  function getBenchmarkMetadata() {
17
17
  return { ...benchmarkMetadata };
@@ -1 +1 @@
1
- {"version":3,"file":"askr-ssg.js","names":[],"sources":["../../src/bin/askr-ssg.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * askr-ssg CLI\n *\n * Usage: askr-ssg --config path/to/config.ts --output dist/static\n */\n\nimport * as pathModule from 'path';\nimport * as fsModule from 'fs';\nimport { createStaticGen } from '../ssg/index';\nimport type { RouteConfig } from '../ssg/types';\nimport type { SSGGenerateOptions, SSGResult } from '../ssg/types';\n\nconst { resolve } = pathModule;\nconst { existsSync } = fsModule;\n\nfunction toFileUrl(filePath: string): string {\n const normalized = resolve(filePath).replace(/\\\\/g, '/');\n const leadingSlash = normalized.startsWith('/') ? '' : '/';\n return `file://${leadingSlash}${encodeURI(normalized)}`;\n}\n\nexport interface ParsedCliArgs {\n configPath: string;\n outputDir: string;\n workers: number | 'auto';\n incremental: boolean;\n changedKeys: string[];\n changedRoutes: string[];\n forceFull: boolean;\n help: boolean;\n}\n\ninterface CliIo {\n log: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n}\n\ninterface CliDeps {\n cwd: () => string;\n now: () => number;\n existsSync: (path: string) => boolean;\n importConfig: (path: string) => Promise<Record<string, unknown>>;\n createStaticGen: typeof createStaticGen;\n}\n\ninterface CliConfig {\n routes: RouteConfig[];\n seed?: number;\n dataOverrides?: Record<string, unknown>;\n concurrency?: number;\n}\n\nconst defaultCliDeps: CliDeps = {\n cwd: () => process.cwd(),\n now: () => performance.now(),\n existsSync,\n importConfig: async (path: string) =>\n (await import(toFileUrl(path))) as Record<string, unknown>,\n createStaticGen,\n};\n\nconst helpText = `\naskr-ssg - Static Site Generation for Askr\n\nUsage:\n askr-ssg --config <path> --output <dir> [--incremental]\n\nOptions:\n --config <path> Path to SSG config file (TypeScript module)\n --output <dir> Output directory for generated HTML\n --workers <n|auto> Preferred render worker count for SSG throughput\n --incremental Use incremental generation if a manifest exists\n --changed-key <key> Mark an invalidation key as changed (repeatable)\n --changed-route <path> Mark a concrete route path as changed (repeatable)\n --force-full Force a full rebuild even with incremental flags\n --help Show this help message\n\nExample:\n askr-ssg --config ./ssg.config.ts --output ./dist/static --incremental --changed-key blog/post-123\n\nTypeScript config execution:\n Use tsx to run the CLI with TS config loading:\n tsx node_modules/@askrjs/askr/dist/bin/askr-ssg.js --config ./ssg.config.ts --output ./dist/static\n`;\n\nexport function parseCliArgs(args: string[]): ParsedCliArgs {\n const parsed: ParsedCliArgs = {\n configPath: '',\n outputDir: '',\n workers: 1,\n incremental: false,\n changedKeys: [],\n changedRoutes: [],\n forceFull: false,\n help: false,\n };\n\n for (let i = 0; i < args.length; i++) {\n if (args[i] === '--config' && i + 1 < args.length) {\n parsed.configPath = args[i + 1];\n i++;\n } else if (args[i] === '--output' && i + 1 < args.length) {\n parsed.outputDir = args[i + 1];\n i++;\n } else if (args[i] === '--workers' && i + 1 < args.length) {\n parsed.workers = args[i + 1] === 'auto' ? 'auto' : Number(args[i + 1]);\n i++;\n } else if (args[i] === '--changed-key' && i + 1 < args.length) {\n parsed.changedKeys.push(args[i + 1]);\n i++;\n } else if (args[i] === '--changed-route' && i + 1 < args.length) {\n parsed.changedRoutes.push(args[i + 1]);\n i++;\n } else if (args[i] === '--incremental') {\n parsed.incremental = true;\n } else if (args[i] === '--force-full') {\n parsed.forceFull = true;\n } else if (args[i] === '--help' || args[i] === '-h') {\n parsed.help = true;\n }\n }\n\n return parsed;\n}\n\nfunction toGenerateOptions(args: ParsedCliArgs): SSGGenerateOptions {\n return {\n mode: args.incremental ? 'incremental' : 'full',\n changedKeys: args.changedKeys,\n changedRoutes: args.changedRoutes,\n forceFull: args.forceFull,\n };\n}\n\nfunction printSummary(\n io: CliIo,\n outputDir: string,\n durationSeconds: string,\n result: SSGResult\n) {\n io.log('');\n io.log(`Generation complete in ${durationSeconds}s`);\n io.log(` Mode: ${result.mode}`);\n io.log(` Generated: ${result.successful}/${result.totalRoutes} routes`);\n io.log(` Failed: ${result.failed} routes`);\n io.log(` Rebuilt: ${result.rebuilt} routes`);\n io.log(` Skipped: ${result.skipped} routes`);\n io.log(` Removed: ${result.removed} routes`);\n io.log(` CacheHit: ${result.cacheHits} routes`);\n io.log(` Output: ${outputDir}`);\n io.log(` Metadata: ${outputDir}/metadata.json`);\n io.log('');\n}\n\nexport async function runCli(\n args: string[],\n deps: Partial<CliDeps> = {},\n io: CliIo = console\n): Promise<number> {\n const parsed = parseCliArgs(args);\n if (parsed.help) {\n io.log(helpText);\n return 0;\n }\n\n if (!parsed.configPath) {\n io.error('Error: --config argument is required');\n return 1;\n }\n\n if (!parsed.configPath.endsWith('.ts')) {\n io.error('Error: --config must point to a TypeScript file (.ts)');\n return 1;\n }\n\n if (!parsed.outputDir) {\n io.error('Error: --output argument is required');\n return 1;\n }\n\n const resolvedDeps = { ...defaultCliDeps, ...deps };\n const resolvedConfigPath = resolve(resolvedDeps.cwd(), parsed.configPath);\n const resolvedOutputDir = resolve(resolvedDeps.cwd(), parsed.outputDir);\n\n if (!resolvedDeps.existsSync(resolvedConfigPath)) {\n io.error(`Error: Config file not found: ${resolvedConfigPath}`);\n return 1;\n }\n\n try {\n io.log(`Loading config: ${resolvedConfigPath}`);\n\n const configModule = await resolvedDeps.importConfig(resolvedConfigPath);\n const config = (configModule.default || configModule) as Partial<CliConfig>;\n\n if (!Array.isArray(config.routes)) {\n io.error('Error: Config must export routes array');\n return 1;\n }\n\n io.log(`Generating ${config.routes.length} routes...`);\n\n const ssg = resolvedDeps.createStaticGen({\n routes: config.routes,\n outputDir: resolvedOutputDir,\n seed: config.seed,\n dataOverrides: config.dataOverrides,\n concurrency: config.concurrency,\n parallelism: parsed.workers,\n });\n\n const startTime = resolvedDeps.now();\n const result = await ssg.generate(toGenerateOptions(parsed));\n const duration = ((resolvedDeps.now() - startTime) / 1000).toFixed(2);\n\n printSummary(io, resolvedOutputDir, duration, result);\n\n if (result.failed > 0) {\n io.log('Errors encountered:');\n for (const route of result.routes) {\n if (route.status === 'error') {\n io.log(` ${route.path}: ${route.error}`);\n }\n }\n io.log('');\n return 1;\n }\n\n return 0;\n } catch (error) {\n io.error('Generation failed:');\n io.error(error instanceof Error ? error.message : String(error));\n if (error instanceof Error && error.stack) {\n io.error(error.stack);\n }\n return 1;\n }\n}\n\nasync function main() {\n const exitCode = await runCli(process.argv.slice(2));\n process.exit(exitCode);\n}\n\nif (process.argv[1] && import.meta.url === toFileUrl(process.argv[1])) {\n void main();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"askr-ssg.js","names":[],"sources":["../../src/bin/askr-ssg.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * askr-ssg CLI\n *\n * Usage: askr-ssg --config path/to/config.ts --output dist/static\n */\n\nimport * as pathModule from 'path';\nimport * as fsModule from 'fs';\nimport { createStaticGen } from '../ssg/index';\nimport type { RouteConfig } from '../ssg/types';\nimport type { SSGGenerateOptions, SSGResult } from '../ssg/types';\n\nconst { resolve } = pathModule;\nconst { existsSync } = fsModule;\n\nfunction toFileUrl(filePath: string): string {\n const normalized = resolve(filePath).replace(/\\\\/g, '/');\n const leadingSlash = normalized.startsWith('/') ? '' : '/';\n return `file://${leadingSlash}${encodeURI(normalized)}`;\n}\n\nexport interface ParsedCliArgs {\n configPath: string;\n outputDir: string;\n workers: number | 'auto';\n incremental: boolean;\n changedKeys: string[];\n changedRoutes: string[];\n forceFull: boolean;\n help: boolean;\n}\n\ninterface CliIo {\n log: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n}\n\ninterface CliDeps {\n cwd: () => string;\n now: () => number;\n existsSync: (path: string) => boolean;\n importConfig: (path: string) => Promise<Record<string, unknown>>;\n createStaticGen: typeof createStaticGen;\n}\n\ninterface CliConfig {\n routes: RouteConfig[];\n seed?: number;\n dataOverrides?: Record<string, unknown>;\n concurrency?: number;\n}\n\nconst defaultCliDeps: CliDeps = {\n cwd: () => process.cwd(),\n now: () => performance.now(),\n existsSync,\n importConfig: async (path: string) =>\n (await import(toFileUrl(path))) as Record<string, unknown>,\n createStaticGen,\n};\n\nconst helpText = `\naskr-ssg - Static Site Generation for Askr\n\nUsage:\n askr-ssg --config <path> --output <dir> [--incremental]\n\nOptions:\n --config <path> Path to SSG config file (TypeScript module)\n --output <dir> Output directory for generated HTML\n --workers <n|auto> Preferred render worker count for SSG throughput\n --incremental Use incremental generation if a manifest exists\n --changed-key <key> Mark an invalidation key as changed (repeatable)\n --changed-route <path> Mark a concrete route path as changed (repeatable)\n --force-full Force a full rebuild even with incremental flags\n --help Show this help message\n\nExample:\n askr-ssg --config ./ssg.config.ts --output ./dist/static --incremental --changed-key blog/post-123\n\nTypeScript config execution:\n Use tsx to run the CLI with TS config loading:\n tsx node_modules/@askrjs/askr/dist/bin/askr-ssg.js --config ./ssg.config.ts --output ./dist/static\n`;\n\nexport function parseCliArgs(args: string[]): ParsedCliArgs {\n const parsed: ParsedCliArgs = {\n configPath: '',\n outputDir: '',\n workers: 1,\n incremental: false,\n changedKeys: [],\n changedRoutes: [],\n forceFull: false,\n help: false,\n };\n\n for (let i = 0; i < args.length; i++) {\n if (args[i] === '--config' && i + 1 < args.length) {\n parsed.configPath = args[i + 1];\n i++;\n } else if (args[i] === '--output' && i + 1 < args.length) {\n parsed.outputDir = args[i + 1];\n i++;\n } else if (args[i] === '--workers' && i + 1 < args.length) {\n parsed.workers = args[i + 1] === 'auto' ? 'auto' : Number(args[i + 1]);\n i++;\n } else if (args[i] === '--changed-key' && i + 1 < args.length) {\n parsed.changedKeys.push(args[i + 1]);\n i++;\n } else if (args[i] === '--changed-route' && i + 1 < args.length) {\n parsed.changedRoutes.push(args[i + 1]);\n i++;\n } else if (args[i] === '--incremental') {\n parsed.incremental = true;\n } else if (args[i] === '--force-full') {\n parsed.forceFull = true;\n } else if (args[i] === '--help' || args[i] === '-h') {\n parsed.help = true;\n }\n }\n\n return parsed;\n}\n\nfunction toGenerateOptions(args: ParsedCliArgs): SSGGenerateOptions {\n return {\n mode: args.incremental ? 'incremental' : 'full',\n changedKeys: args.changedKeys,\n changedRoutes: args.changedRoutes,\n forceFull: args.forceFull,\n };\n}\n\nfunction printSummary(\n io: CliIo,\n outputDir: string,\n durationSeconds: string,\n result: SSGResult\n) {\n io.log('');\n io.log(`Generation complete in ${durationSeconds}s`);\n io.log(` Mode: ${result.mode}`);\n io.log(` Generated: ${result.successful}/${result.totalRoutes} routes`);\n io.log(` Failed: ${result.failed} routes`);\n io.log(` Rebuilt: ${result.rebuilt} routes`);\n io.log(` Skipped: ${result.skipped} routes`);\n io.log(` Removed: ${result.removed} routes`);\n io.log(` CacheHit: ${result.cacheHits} routes`);\n io.log(` Output: ${outputDir}`);\n io.log(` Metadata: ${outputDir}/metadata.json`);\n io.log('');\n}\n\nexport async function runCli(\n args: string[],\n deps: Partial<CliDeps> = {},\n io: CliIo = console\n): Promise<number> {\n const parsed = parseCliArgs(args);\n if (parsed.help) {\n io.log(helpText);\n return 0;\n }\n\n if (!parsed.configPath) {\n io.error('Error: --config argument is required');\n return 1;\n }\n\n if (!parsed.configPath.endsWith('.ts')) {\n io.error('Error: --config must point to a TypeScript file (.ts)');\n return 1;\n }\n\n if (!parsed.outputDir) {\n io.error('Error: --output argument is required');\n return 1;\n }\n\n const resolvedDeps = { ...defaultCliDeps, ...deps };\n const resolvedConfigPath = resolve(resolvedDeps.cwd(), parsed.configPath);\n const resolvedOutputDir = resolve(resolvedDeps.cwd(), parsed.outputDir);\n\n if (!resolvedDeps.existsSync(resolvedConfigPath)) {\n io.error(`Error: Config file not found: ${resolvedConfigPath}`);\n return 1;\n }\n\n try {\n io.log(`Loading config: ${resolvedConfigPath}`);\n\n const configModule = await resolvedDeps.importConfig(resolvedConfigPath);\n const config = (configModule.default || configModule) as Partial<CliConfig>;\n\n if (!Array.isArray(config.routes)) {\n io.error('Error: Config must export routes array');\n return 1;\n }\n\n io.log(`Generating ${config.routes.length} routes...`);\n\n const ssg = resolvedDeps.createStaticGen({\n routes: config.routes,\n outputDir: resolvedOutputDir,\n seed: config.seed,\n dataOverrides: config.dataOverrides,\n concurrency: config.concurrency,\n parallelism: parsed.workers,\n });\n\n const startTime = resolvedDeps.now();\n const result = await ssg.generate(toGenerateOptions(parsed));\n const duration = ((resolvedDeps.now() - startTime) / 1000).toFixed(2);\n\n printSummary(io, resolvedOutputDir, duration, result);\n\n if (result.failed > 0) {\n io.log('Errors encountered:');\n for (const route of result.routes) {\n if (route.status === 'error') {\n io.log(` ${route.path}: ${route.error}`);\n }\n }\n io.log('');\n return 1;\n }\n\n return 0;\n } catch (error) {\n io.error('Generation failed:');\n io.error(error instanceof Error ? error.message : String(error));\n if (error instanceof Error && error.stack) {\n io.error(error.stack);\n }\n return 1;\n }\n}\n\nasync function main() {\n const exitCode = await runCli(process.argv.slice(2));\n process.exit(exitCode);\n}\n\nif (process.argv[1] && import.meta.url === toFileUrl(process.argv[1])) {\n void main();\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/boot/index.ts"],"sourcesContent":["/**\n * App bootstrap and mount\n */\n\nimport {\n createComponentInstance,\n mountComponent,\n cleanupComponent,\n type ComponentFunction,\n type ComponentInstance,\n} from '../runtime/component';\nimport {\n isDevelopmentEnvironment,\n isProductionEnvironment,\n} from '../common/env';\nimport { logger } from '../dev/logger';\nimport {\n initializeNavigation,\n registerAppInstance,\n unregisterAppInstance,\n} from '../router/navigate';\nimport {\n configureScrollRestoration,\n type ScrollRestorationOptions,\n} from '../router/navigate';\nimport {\n _applyManifest,\n _drainLazy,\n _setActiveRouteAuthOptions,\n _snapshotLazy,\n clearRoutes,\n lockRouteRegistration,\n resolveRouteRequest,\n route as registerRoute,\n setServerLocation,\n} from '../router/route';\nimport { globalScheduler } from '../runtime/scheduler';\nimport { assertExecutionModel } from '../runtime/execution-model';\nimport { setStaticChildSlotsCacheEnabled } from '../renderer/dom';\nimport { isPromiseLike } from '../common/promise';\nimport { SSR_RENDER_DATA_ATTR, type SSRData } from '../common/ssr';\nimport {\n startHydrationRenderPhase,\n stopHydrationRenderPhase,\n} from '../ssr/render-keys';\n\nconst HAS_ROUTES_KEY = Symbol.for('__ASKR_HAS_ROUTES__');\n\nlet componentIdCounter = 0;\n\n// Track instances by root element to support multiple createIsland calls on same root\nconst instancesByRoot = new WeakMap<Element, ComponentInstance>();\n\n// Symbol for storing cleanup on elements\nconst CLEANUP_SYMBOL = Symbol.for('__askrCleanup__');\nconst ROOT_CLEANUP_CALLBACKS_SYMBOL = Symbol.for(\n '__askrRootCleanupCallbacks__'\n);\n\ntype RootCleanupOptions = {\n preserveInstance?: boolean;\n};\n\n// Type for elements that have cleanup functions attached\ninterface ElementWithCleanup extends Element {\n [CLEANUP_SYMBOL]?: (options?: RootCleanupOptions) => void;\n [ROOT_CLEANUP_CALLBACKS_SYMBOL]?: Set<() => void>;\n}\n\nfunction takeHydrationRenderData(rootElement: Element): SSRData | null {\n for (const child of Array.from(rootElement.children)) {\n if (\n child instanceof HTMLScriptElement &&\n child.getAttribute(SSR_RENDER_DATA_ATTR) === 'true'\n ) {\n const raw = child.textContent ?? '';\n child.remove();\n if (!raw) {\n return {};\n }\n\n try {\n return JSON.parse(raw) as SSRData;\n } catch (err) {\n throw new Error(\n '[Askr] Failed to parse embedded SSR render data during hydration.',\n { cause: err }\n );\n }\n }\n }\n\n return null;\n}\n\nfunction clearRootCleanupCallbacks(rootElement: Element): void {\n try {\n delete (rootElement as ElementWithCleanup)[ROOT_CLEANUP_CALLBACKS_SYMBOL];\n } catch {\n (rootElement as ElementWithCleanup)[ROOT_CLEANUP_CALLBACKS_SYMBOL]?.clear();\n }\n}\n\nfunction registerRootCleanupCallback(\n rootElement: Element,\n callback: () => void\n): () => void {\n const elementWithCleanup = rootElement as ElementWithCleanup;\n const callbacks =\n elementWithCleanup[ROOT_CLEANUP_CALLBACKS_SYMBOL] ?? new Set();\n callbacks.add(callback);\n elementWithCleanup[ROOT_CLEANUP_CALLBACKS_SYMBOL] = callbacks;\n\n return () => {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n clearRootCleanupCallbacks(rootElement);\n }\n };\n}\n\nfunction runRootCleanupCallbacks(\n rootElement: Element,\n errors: unknown[]\n): void {\n const callbacks = (rootElement as ElementWithCleanup)[\n ROOT_CLEANUP_CALLBACKS_SYMBOL\n ];\n if (!callbacks || callbacks.size === 0) {\n clearRootCleanupCallbacks(rootElement);\n return;\n }\n\n clearRootCleanupCallbacks(rootElement);\n for (const callback of callbacks) {\n try {\n callback();\n } catch (e) {\n errors.push(e);\n }\n }\n}\n\nfunction cleanupRootInstance(\n rootElement: Element,\n instance: ComponentInstance,\n options?: RootCleanupOptions\n) {\n // Attempt to remove listeners and cleanup instances under the root.\n // In non-strict mode we preserve previous behavior by swallowing errors\n // (but logging in dev); in strict mode we aggregate and re-throw.\n const errors: unknown[] = [];\n try {\n teardownNodeSubtree(rootElement);\n } catch (e) {\n errors.push(e);\n }\n\n try {\n cleanupComponent(instance);\n } catch (e) {\n errors.push(e);\n }\n\n runRootCleanupCallbacks(rootElement, errors);\n\n if (!options?.preserveInstance) {\n unregisterAppInstance(instance);\n instancesByRoot.delete(rootElement);\n clearRootCleanupCallbacks(rootElement);\n try {\n delete (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n } catch {\n // Ignore cleanup marker removal failures.\n }\n }\n\n if (errors.length > 0) {\n if (instance.cleanupStrict) {\n throw new AggregateError(errors, `cleanup failed for app root`);\n } else if (isDevelopmentEnvironment()) {\n for (const err of errors) logger.warn('[Askr] cleanup error:', err);\n }\n }\n}\n\nfunction attachCleanupForRoot(\n rootElement: Element,\n instance: ComponentInstance\n) {\n (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL] = (options) => {\n cleanupRootInstance(rootElement, instance, options);\n };\n\n try {\n const descriptor =\n Object.getOwnPropertyDescriptor(rootElement, 'innerHTML') ||\n Object.getOwnPropertyDescriptor(\n Object.getPrototypeOf(rootElement),\n 'innerHTML'\n ) ||\n Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');\n\n if (descriptor && (descriptor.get || descriptor.set)) {\n Object.defineProperty(rootElement, 'innerHTML', {\n get: descriptor.get\n ? function (this: Element) {\n return descriptor.get!.call(this);\n }\n : undefined,\n set: function (this: Element, value: string) {\n if (value === '' && instancesByRoot.get(this) === instance) {\n cleanupRootInstance(rootElement, instance);\n }\n if (descriptor.set) {\n return descriptor.set.call(this, value);\n }\n },\n configurable: true,\n });\n }\n } catch {\n // If Object.defineProperty fails, ignore\n }\n}\n\nimport { Fragment, ELEMENT_TYPE } from '../jsx';\n\nimport { DefaultPortal } from '../foundations/structures/portal';\nimport { disposeDefaultPortalScope } from '../foundations/structures/portal';\n\nfunction mountOrUpdate(\n rootElement: Element,\n componentFn: ComponentFunction,\n options?: { cleanupStrict?: boolean }\n) {\n // Ensure root component always includes a DefaultPortal host by wrapping it.\n const wrappedFn: ComponentFunction = (props, ctx) => {\n const out = componentFn(props, ctx);\n if (isPromiseLike(out)) {\n throw new Error(\n 'Async components are not supported. Components must return synchronously.'\n );\n }\n const portalVNode = {\n $$typeof: ELEMENT_TYPE,\n type: DefaultPortal,\n props: {},\n key: '__default_portal',\n } as unknown;\n return {\n $$typeof: ELEMENT_TYPE,\n type: Fragment,\n props: {\n children:\n out === undefined || out === null\n ? [portalVNode]\n : [out, portalVNode],\n },\n } as unknown as ReturnType<ComponentFunction>;\n };\n // Preserve the original component name for debugging/dev warnings\n Object.defineProperty(wrappedFn, 'name', {\n value: componentFn.name || 'Component',\n });\n\n // Clean up existing cleanup function before mounting new one\n const existingCleanup = (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n const reusedExistingInstance = typeof existingCleanup === 'function';\n if (reusedExistingInstance) {\n existingCleanup({ preserveInstance: true });\n }\n\n let instance = instancesByRoot.get(rootElement);\n\n if (instance) {\n const shouldResetHookState = instance.fn.name !== wrappedFn.name;\n\n if (!reusedExistingInstance) {\n removeAllListeners(rootElement);\n try {\n cleanupComponent(instance);\n } catch (e) {\n // If previous cleanup threw in strict mode, log but continue mounting new instance\n if (isDevelopmentEnvironment()) {\n logger.warn('[Askr] prior cleanup threw:', e);\n }\n }\n }\n\n instance.fn = wrappedFn;\n instance.evaluationGeneration++;\n instance.mounted = false;\n instance.expectedStateIndices = [];\n instance.firstRenderComplete = false;\n instance.isRoot = true;\n instance.portalScope = instance;\n\n if (shouldResetHookState) {\n instance.stateValues = [];\n instance.hasPendingUpdate = false;\n instance.notifyUpdate = null;\n instance.stateIndexCheck = -1;\n instance.mountOperations = [];\n instance.commitOperations = [];\n instance.lifecycleSlots = [];\n instance.cleanupFns = [];\n instance._currentRenderToken = undefined;\n instance.lastRenderToken = 0;\n instance._pendingReadSources = undefined;\n instance._lastReadSources = undefined;\n instance._placeholder = undefined;\n instance.errorBoundaryState = undefined;\n instance.devWarningsEmitted = undefined;\n }\n\n // Update strict flag if provided\n if (options && typeof options.cleanupStrict === 'boolean') {\n instance.cleanupStrict = options.cleanupStrict;\n }\n } else {\n const componentId = String(++componentIdCounter);\n instance = createComponentInstance(componentId, wrappedFn, {}, rootElement);\n instancesByRoot.set(rootElement, instance);\n instance.isRoot = true;\n instance.portalScope = instance;\n // Initialize strict flag from options\n if (options && typeof options.cleanupStrict === 'boolean') {\n instance.cleanupStrict = options.cleanupStrict;\n }\n }\n\n attachCleanupForRoot(rootElement, instance);\n registerRootCleanupCallback(rootElement, () => {\n disposeDefaultPortalScope(instance.portalScope ?? instance);\n });\n mountComponent(instance);\n globalScheduler.flush();\n}\n\nfunction bindResolvedRouteHandler(resolved: ResolvedRoute): ComponentFunction {\n return () =>\n resolved.handler(resolved.params) as ReturnType<ComponentFunction>;\n}\n\nfunction bindDeniedStatus(status: number): ComponentFunction {\n return () => ({\n type: 'div',\n props: {\n 'data-route-denied': String(status),\n },\n children: [String(status)],\n });\n}\n\n// New strongly-typed init functions\nimport type {\n Route,\n RouteManifest,\n ResolvedRoute,\n RouteAuthOptions,\n RouteRequestResult,\n} from '../common/router';\nimport {\n installRendererBridge,\n removeAllListeners,\n teardownNodeSubtree,\n} from '../renderer';\ninstallRendererBridge();\n\nexport type IslandConfig = {\n root: Element | string;\n component: ComponentFunction;\n // Optional: surface cleanup errors during teardown for this island\n cleanupStrict?: boolean;\n // Explicitly disallow routes on islands at type level\n routes?: never;\n};\n\nexport type IslandsConfig = {\n islands: IslandConfig[];\n};\n\ntype BootRouteSource =\n | {\n manifest: RouteManifest;\n routes?: Route[];\n }\n | {\n manifest?: RouteManifest;\n routes: Route[];\n };\n\nexport type SPAConfig = BootRouteSource & {\n root: Element | string;\n /**\n * Preferred: pass the route manifest built via `registerRoutes(() => { ... })`.\n * ```ts\n * import { getManifest } from '@askrjs/askr/router';\n * await createSPA({ root: '#app', manifest: getManifest() });\n * ```\n */\n auth?: RouteAuthOptions;\n scrollRestoration?: boolean | ScrollRestorationOptions;\n cleanupStrict?: boolean;\n component?: never;\n};\n\nexport type HydrateSPAConfig = BootRouteSource & {\n root: Element | string;\n /** Preferred manifest input — see `SPAConfig.manifest`. */\n auth?: RouteAuthOptions;\n scrollRestoration?: boolean | ScrollRestorationOptions;\n cleanupStrict?: boolean;\n hydrate?: {\n verifyMarkup?: boolean;\n deferUntilIdle?: boolean;\n deferBelowFold?: boolean;\n foldThreshold?: number;\n skipSelectors?: string[];\n };\n};\n\nconst MAX_INITIAL_ROUTE_REDIRECTS = 20;\n\nasync function resolveInitialRoute(\n auth?: RouteAuthOptions\n): Promise<{ path: string; href: string; resolved: RouteRequestResult }> {\n let path = typeof window !== 'undefined' ? window.location.pathname : '/';\n let href =\n typeof window !== 'undefined'\n ? `${window.location.pathname}${window.location.search}${window.location.hash}`\n : path;\n const visited = new Set<string>();\n\n for (\n let redirects = 0;\n redirects <= MAX_INITIAL_ROUTE_REDIRECTS;\n redirects++\n ) {\n if (visited.has(href)) {\n throw new Error(`[Askr] Route redirect cycle detected at ${href}.`);\n }\n visited.add(href);\n\n const resolved = await resolveRouteRequest(href, { auth });\n if (\n typeof window === 'undefined' ||\n !resolved ||\n resolved.kind !== 'redirect'\n ) {\n return { path, href, resolved };\n }\n\n const redirectTarget = new URL(resolved.to, window.location.href);\n const redirectHref = `${redirectTarget.pathname}${redirectTarget.search}${redirectTarget.hash}`;\n window.history.replaceState({ path: redirectHref }, '', redirectHref);\n path = redirectTarget.pathname;\n href = redirectHref;\n }\n\n throw new Error(\n `[Askr] Route redirect limit exceeded (${MAX_INITIAL_ROUTE_REDIRECTS}).`\n );\n}\n\n/**\n * createIsland: Enhances existing DOM (no router, mounts once)\n */\nexport function createIsland(config: IslandConfig): void {\n assertExecutionModel('islands');\n if (!config || typeof config !== 'object') {\n throw new Error('createIsland requires a config object');\n }\n if (typeof config.component !== 'function') {\n throw new Error('createIsland: component must be a function');\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n\n // Islands must not initialize router or routes\n if ('routes' in config) {\n throw new Error(\n 'createIsland does not accept routes; use createSPA for routed apps'\n );\n }\n\n // Routes are never supported with islands.\n // If routes were registered (even at module load time), fail fast to avoid\n // surprising partial router behavior.\n try {\n const g = globalThis as unknown as Record<string | symbol, unknown>;\n if (g[HAS_ROUTES_KEY]) {\n throw new Error(\n 'Routes are not supported with islands. Use createSPA (client) or createSSR (server) instead.'\n );\n }\n } catch {\n // ignore\n }\n\n mountOrUpdate(rootElement, config.component, {\n cleanupStrict: config.cleanupStrict,\n });\n}\n\n/**\n * createIslands: Enhances one or more existing DOM roots (no router).\n * The only public islands constructor.\n */\nexport function createIslands(config: IslandsConfig): void {\n assertExecutionModel('islands');\n if (!config || typeof config !== 'object') {\n throw new Error('createIslands requires a config object');\n }\n if (!Array.isArray(config.islands) || config.islands.length === 0) {\n throw new Error('createIslands requires a non-empty islands array');\n }\n for (const island of config.islands) {\n createIsland(island);\n }\n}\n\n/**\n * createSPA: Initializes router and mounts the app with the provided route manifest or route table.\n *\n * Preferred usage with manifest:\n * ```ts\n * import { getManifest } from '@askrjs/askr/router';\n * await createSPA({ root: '#app', manifest: getManifest() });\n * ```\n *\n * Legacy usage with plain routes array (still supported):\n * ```ts\n * await createSPA({ root: '#app', routes: getRoutes() });\n * ```\n */\nexport async function createSPA(config: SPAConfig): Promise<void> {\n assertExecutionModel('spa');\n if (!config || typeof config !== 'object') {\n throw new Error('createSPA requires a config object');\n }\n\n const hasManifest =\n config.manifest != null && config.manifest.records.length > 0;\n const hasRoutes = Array.isArray(config.routes) && config.routes.length > 0;\n\n if (!hasManifest && !hasRoutes) {\n throw new Error(\n 'createSPA requires a route manifest or route table. ' +\n 'Pass `manifest: getManifest()` or `routes: getRoutes()`. ' +\n 'If you are enhancing existing HTML, use createIsland instead.'\n );\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n\n const pendingLazyAtBoot = _snapshotLazy();\n\n configureScrollRestoration(config.scrollRestoration);\n\n clearRoutes();\n\n if (hasManifest) {\n // Preferred path: apply pre-built manifest records directly\n _applyManifest(config.manifest!);\n } else {\n // Legacy path: register plain Route objects (no layout metadata)\n for (const r of config.routes!) {\n registerRoute(r.path, r.handler as Parameters<typeof registerRoute>[1]);\n }\n }\n\n const routeAuth = config.auth ?? config.manifest?.auth;\n _setActiveRouteAuthOptions(routeAuth);\n\n // Drain any lazy() imports so all split chunks are ready before mounting\n await _drainLazy(pendingLazyAtBoot);\n\n // Lock registration in production to prevent late registration surprises\n if (isProductionEnvironment()) lockRouteRegistration();\n\n // Mount the currently-resolved route handler (if any)\n const { path, resolved } = await resolveInitialRoute(routeAuth);\n\n if (!resolved) {\n mountOrUpdate(rootElement, () => ({ type: 'div', children: [] }), {\n cleanupStrict: config.cleanupStrict,\n });\n\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: routeAuth,\n });\n return;\n }\n\n if (resolved.kind === 'redirect') {\n mountOrUpdate(rootElement, () => ({ type: 'div', children: [] }), {\n cleanupStrict: config.cleanupStrict,\n });\n\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: routeAuth,\n });\n return;\n }\n\n mountOrUpdate(\n rootElement,\n resolved.kind === 'deny'\n ? bindDeniedStatus(resolved.status)\n : bindResolvedRouteHandler({\n handler: resolved.handler,\n params: resolved.params,\n }),\n {\n cleanupStrict: config.cleanupStrict,\n }\n );\n\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: routeAuth,\n });\n}\n\n/**\n * Mark elements that should be skipped during hydration\n */\nfunction markSkippedElements(root: Element, skipSelectors: string[]): void {\n if (skipSelectors.length === 0) {\n return;\n }\n\n const uniqueSelectors = Array.from(new Set(skipSelectors));\n const selectorList = uniqueSelectors.join(', ');\n const elements = root.querySelectorAll(selectorList);\n elements.forEach((el) => el.setAttribute('data-skip-hydrate', 'true'));\n}\n\nfunction collectDeferredBelowFoldBoundaries(\n root: Element,\n foldY: number\n): Element[] {\n const boundaries: Element[] = [];\n const stack: Element[] = [];\n\n for (let index = root.children.length - 1; index >= 0; index -= 1) {\n stack.push(root.children[index]);\n }\n\n while (stack.length > 0) {\n const element = stack.pop()!;\n\n if (element.hasAttribute('data-skip-hydrate')) {\n continue;\n }\n\n const rect = element.getBoundingClientRect();\n if (rect.top >= foldY) {\n element.setAttribute('data-skip-hydrate', 'true');\n boundaries.push(element);\n continue;\n }\n\n for (let index = element.children.length - 1; index >= 0; index -= 1) {\n stack.push(element.children[index]);\n }\n }\n\n return boundaries;\n}\n\nfunction activateVisibleDeferredBoundaries(\n boundaries: Element[],\n foldY: number\n): { activated: boolean; remaining: number } {\n let activated = false;\n let remaining = 0;\n\n for (const element of boundaries) {\n if (!element.hasAttribute('data-skip-hydrate')) {\n continue;\n }\n\n const rect = element.getBoundingClientRect();\n if (rect.top < foldY) {\n element.removeAttribute('data-skip-hydrate');\n activated = true;\n } else {\n remaining += 1;\n }\n }\n\n return { activated, remaining };\n}\n\nfunction queueIdleWork(work: () => void): Promise<void> {\n return new Promise((resolve) => {\n if (typeof requestIdleCallback !== 'undefined') {\n requestIdleCallback(\n () => {\n work();\n resolve();\n },\n { timeout: 2000 }\n );\n return;\n }\n\n setTimeout(() => {\n work();\n resolve();\n }, 0);\n });\n}\n\nfunction flushHydrationActivation(rootElement: Element): void {\n const instance = instancesByRoot.get(rootElement);\n if (!instance) return;\n instance._enqueueRun?.();\n globalScheduler.flush();\n}\n\nfunction shouldVerifyHydrationMarkup(config: HydrateSPAConfig): boolean {\n const explicit = config.hydrate?.verifyMarkup;\n if (typeof explicit === 'boolean') {\n return explicit;\n }\n\n return !isProductionEnvironment();\n}\n\nasync function registerAppNavigation(\n rootElement: Element,\n path: string,\n source?: {\n manifest?: RouteManifest;\n routes?: Route[];\n auth?: RouteAuthOptions;\n }\n) {\n const instance = instancesByRoot.get(rootElement);\n if (!instance) throw new Error('Internal error: app instance missing');\n registerAppInstance(instance as ComponentInstance, path, source);\n initializeNavigation();\n}\n\n/**\n * Apply selective hydration with deferral options\n */\nasync function applySelectiveHydration(\n rootElement: Element,\n resolved: { handler: ComponentFunction; params: Record<string, unknown> },\n path: string,\n cleanupStrict: boolean | undefined,\n hydrateOptions: NonNullable<HydrateSPAConfig['hydrate']>\n): Promise<void> {\n const hasPermanentSkips = (hydrateOptions.skipSelectors?.length ?? 0) > 0;\n const hasBelowFoldDeferral = !!hydrateOptions.deferBelowFold;\n const hasSelectiveBoundaries = hasPermanentSkips || hasBelowFoldDeferral;\n let staticChildSlotsCacheSuspended = false;\n let releaseSelectiveHydrationResources = () => {};\n\n const restoreStaticChildSlotsCache = () => {\n if (!staticChildSlotsCacheSuspended) {\n return;\n }\n\n setStaticChildSlotsCacheEnabled(true);\n staticChildSlotsCacheSuspended = false;\n };\n\n if (hydrateOptions.skipSelectors?.length) {\n markSkippedElements(rootElement, hydrateOptions.skipSelectors);\n }\n\n let deferredBoundaries: Element[] = [];\n if (hydrateOptions.deferBelowFold) {\n setStaticChildSlotsCacheEnabled(false);\n staticChildSlotsCacheSuspended = true;\n const foldY = hydrateOptions.foldThreshold ?? window.innerHeight;\n deferredBoundaries = collectDeferredBelowFoldBoundaries(rootElement, foldY);\n\n let selectiveHydrationResourcesReleased = false;\n let unregisterRootCleanupCallback = () => {};\n\n function handleScroll() {\n const { activated, remaining } = activateVisibleDeferredBoundaries(\n deferredBoundaries,\n foldY\n );\n\n if (!activated) {\n return;\n }\n\n flushHydrationActivation(rootElement);\n\n if (remaining === 0) {\n releaseSelectiveHydrationResources();\n }\n }\n\n releaseSelectiveHydrationResources = () => {\n if (selectiveHydrationResourcesReleased) {\n return;\n }\n\n selectiveHydrationResourcesReleased = true;\n unregisterRootCleanupCallback();\n window.removeEventListener('scroll', handleScroll);\n restoreStaticChildSlotsCache();\n };\n\n unregisterRootCleanupCallback = registerRootCleanupCallback(\n rootElement,\n releaseSelectiveHydrationResources\n );\n\n window.addEventListener('scroll', handleScroll, { passive: true });\n }\n\n if (hydrateOptions.deferUntilIdle && !hasSelectiveBoundaries) {\n await queueIdleWork(() => {\n mountOrUpdate(\n rootElement,\n (() => resolved.handler(resolved.params)) as ComponentFunction,\n {\n cleanupStrict,\n }\n );\n });\n await registerAppNavigation(rootElement, path);\n return;\n }\n\n try {\n mountOrUpdate(\n rootElement,\n (() => resolved.handler(resolved.params)) as ComponentFunction,\n {\n cleanupStrict,\n }\n );\n await registerAppNavigation(rootElement, path);\n } catch (error) {\n releaseSelectiveHydrationResources();\n throw error;\n }\n\n if (hydrateOptions.deferUntilIdle && deferredBoundaries.length > 0) {\n await queueIdleWork(() => {\n try {\n const { activated } = activateVisibleDeferredBoundaries(\n deferredBoundaries,\n Number.POSITIVE_INFINITY\n );\n if (activated) {\n flushHydrationActivation(rootElement);\n }\n } finally {\n releaseSelectiveHydrationResources();\n }\n });\n }\n\n if (deferredBoundaries.length === 0) {\n releaseSelectiveHydrationResources();\n }\n}\n\n/**\n * hydrateSPA: Hydrate server-rendered HTML.\n * Accepts either a `manifest` (preferred) or a legacy `routes` array.\n */\nexport async function hydrateSPA(config: HydrateSPAConfig): Promise<void> {\n assertExecutionModel('spa');\n if (!config || typeof config !== 'object') {\n throw new Error('hydrateSPA requires a config object');\n }\n\n const hasManifest =\n config.manifest != null && config.manifest.records.length > 0;\n const hasRoutes = Array.isArray(config.routes) && config.routes.length > 0;\n\n if (!hasManifest && !hasRoutes) {\n throw new Error(\n 'hydrateSPA requires a route manifest or route table. ' +\n 'Pass `manifest: getManifest()` or `routes: getRoutes()`. ' +\n 'If you are enhancing existing HTML, use createIsland instead.'\n );\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n const hydrationRenderData = takeHydrationRenderData(rootElement);\n\n const pendingLazyAtHydrationBoot = _snapshotLazy();\n\n configureScrollRestoration(config.scrollRestoration);\n\n clearRoutes();\n\n if (hasManifest) {\n _applyManifest(config.manifest!);\n } else {\n for (const r of config.routes!) {\n registerRoute(r.path, r.handler as Parameters<typeof registerRoute>[1]);\n }\n }\n\n _setActiveRouteAuthOptions(config.auth ?? config.manifest?.auth);\n\n // Drain any lazy() imports so all split chunks are ready before mounting\n await _drainLazy(pendingLazyAtHydrationBoot);\n\n const {\n path,\n href: currentUrl,\n resolved,\n } = await resolveInitialRoute(config.auth ?? config.manifest?.auth);\n setServerLocation(currentUrl);\n if (isProductionEnvironment()) lockRouteRegistration();\n\n if (!resolved) {\n throw new Error(`hydrateSPA: no route found for current path (${path}).`);\n }\n\n if (resolved.kind === 'redirect') {\n throw new Error(\n `hydrateSPA: unresolved redirect for current path (${path}).`\n );\n }\n\n const hydrationResolved: ResolvedRoute =\n resolved.kind === 'deny'\n ? { handler: bindDeniedStatus(resolved.status), params: {} }\n : { handler: resolved.handler, params: resolved.params };\n\n if (shouldVerifyHydrationMarkup(config)) {\n const legacyRouteTable = hasManifest\n ? config.manifest!.records.map((r) => ({\n path: r.path,\n handler: r.handler,\n namespace: r.options.namespace,\n }))\n : config.routes!;\n\n const { verifyHydrationSyncForUrl } =\n await import('../ssr/verify-hydration');\n if (\n !verifyHydrationSyncForUrl({\n root: rootElement,\n url: currentUrl,\n routes: legacyRouteTable,\n resolved: hydrationResolved,\n options: {\n data: hydrationRenderData ?? undefined,\n },\n })\n ) {\n throw new Error(\n '[Askr] Hydration mismatch detected. Server HTML does not match expected server-render output.'\n );\n }\n }\n\n const hydrateOptions = config.hydrate;\n if (hydrateOptions) {\n if (hydrateOptions.deferUntilIdle || hydrateOptions.deferBelowFold) {\n if (hydrationRenderData) {\n startHydrationRenderPhase(hydrationRenderData);\n }\n try {\n await applySelectiveHydration(\n rootElement,\n hydrationResolved,\n path,\n config.cleanupStrict,\n hydrateOptions\n );\n } finally {\n if (hydrationRenderData) {\n stopHydrationRenderPhase();\n }\n }\n return;\n }\n\n if (hydrateOptions.skipSelectors?.length) {\n markSkippedElements(rootElement, hydrateOptions.skipSelectors);\n }\n }\n\n if (hydrationRenderData) {\n startHydrationRenderPhase(hydrationRenderData);\n }\n try {\n mountOrUpdate(\n rootElement,\n resolved.kind === 'deny'\n ? bindDeniedStatus(resolved.status)\n : bindResolvedRouteHandler(hydrationResolved),\n {\n cleanupStrict: config.cleanupStrict,\n }\n );\n } finally {\n if (hydrationRenderData) {\n stopHydrationRenderPhase();\n }\n }\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: config.auth ?? config.manifest?.auth,\n });\n}\n\n/**\n * Cleanup an app mounted on a root element (element or id).\n * Safe to call multiple times — no-op when nothing is mounted.\n */\nexport function cleanupApp(root: Element | string): void {\n const rootElement =\n typeof root === 'string' ? document.getElementById(root) : root;\n\n if (!rootElement) return;\n\n const cleanupFn = (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n try {\n if (typeof cleanupFn === 'function') {\n cleanupFn();\n }\n } finally {\n instancesByRoot.delete(rootElement);\n clearRootCleanupCallbacks(rootElement);\n try {\n delete (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n } catch {\n // Ignore cleanup marker removal failures.\n }\n }\n}\n\n/**\n * Check whether an app is mounted on the given root\n */\nexport function hasApp(root: Element | string): boolean {\n const rootElement =\n typeof root === 'string' ? document.getElementById(root) : root;\n\n if (!rootElement) return false;\n return instancesByRoot.has(rootElement);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/boot/index.ts"],"sourcesContent":["/**\n * App bootstrap and mount\n */\n\nimport {\n createComponentInstance,\n mountComponent,\n cleanupComponent,\n type ComponentFunction,\n type ComponentInstance,\n} from '../runtime/component';\nimport {\n isDevelopmentEnvironment,\n isProductionEnvironment,\n} from '../common/env';\nimport { logger } from '../dev/logger';\nimport {\n initializeNavigation,\n registerAppInstance,\n unregisterAppInstance,\n} from '../router/navigate';\nimport {\n configureScrollRestoration,\n type ScrollRestorationOptions,\n} from '../router/navigate';\nimport {\n _applyManifest,\n _drainLazy,\n _setActiveRouteAuthOptions,\n _snapshotLazy,\n clearRoutes,\n lockRouteRegistration,\n resolveRouteRequest,\n route as registerRoute,\n setServerLocation,\n} from '../router/route';\nimport { globalScheduler } from '../runtime/scheduler';\nimport { assertExecutionModel } from '../runtime/execution-model';\nimport { setStaticChildSlotsCacheEnabled } from '../renderer/dom';\nimport { isPromiseLike } from '../common/promise';\nimport { SSR_RENDER_DATA_ATTR, type SSRData } from '../common/ssr';\nimport {\n startHydrationRenderPhase,\n stopHydrationRenderPhase,\n} from '../ssr/render-keys';\n\nconst HAS_ROUTES_KEY = Symbol.for('__ASKR_HAS_ROUTES__');\n\nlet componentIdCounter = 0;\n\n// Track instances by root element to support multiple createIsland calls on same root\nconst instancesByRoot = new WeakMap<Element, ComponentInstance>();\n\n// Symbol for storing cleanup on elements\nconst CLEANUP_SYMBOL = Symbol.for('__askrCleanup__');\nconst ROOT_CLEANUP_CALLBACKS_SYMBOL = Symbol.for(\n '__askrRootCleanupCallbacks__'\n);\n\ntype RootCleanupOptions = {\n preserveInstance?: boolean;\n};\n\n// Type for elements that have cleanup functions attached\ninterface ElementWithCleanup extends Element {\n [CLEANUP_SYMBOL]?: (options?: RootCleanupOptions) => void;\n [ROOT_CLEANUP_CALLBACKS_SYMBOL]?: Set<() => void>;\n}\n\nfunction takeHydrationRenderData(rootElement: Element): SSRData | null {\n for (const child of Array.from(rootElement.children)) {\n if (\n child instanceof HTMLScriptElement &&\n child.getAttribute(SSR_RENDER_DATA_ATTR) === 'true'\n ) {\n const raw = child.textContent ?? '';\n child.remove();\n if (!raw) {\n return {};\n }\n\n try {\n return JSON.parse(raw) as SSRData;\n } catch (err) {\n throw new Error(\n '[Askr] Failed to parse embedded SSR render data during hydration.',\n { cause: err }\n );\n }\n }\n }\n\n return null;\n}\n\nfunction clearRootCleanupCallbacks(rootElement: Element): void {\n try {\n delete (rootElement as ElementWithCleanup)[ROOT_CLEANUP_CALLBACKS_SYMBOL];\n } catch {\n (rootElement as ElementWithCleanup)[ROOT_CLEANUP_CALLBACKS_SYMBOL]?.clear();\n }\n}\n\nfunction registerRootCleanupCallback(\n rootElement: Element,\n callback: () => void\n): () => void {\n const elementWithCleanup = rootElement as ElementWithCleanup;\n const callbacks =\n elementWithCleanup[ROOT_CLEANUP_CALLBACKS_SYMBOL] ?? new Set();\n callbacks.add(callback);\n elementWithCleanup[ROOT_CLEANUP_CALLBACKS_SYMBOL] = callbacks;\n\n return () => {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n clearRootCleanupCallbacks(rootElement);\n }\n };\n}\n\nfunction runRootCleanupCallbacks(\n rootElement: Element,\n errors: unknown[]\n): void {\n const callbacks = (rootElement as ElementWithCleanup)[\n ROOT_CLEANUP_CALLBACKS_SYMBOL\n ];\n if (!callbacks || callbacks.size === 0) {\n clearRootCleanupCallbacks(rootElement);\n return;\n }\n\n clearRootCleanupCallbacks(rootElement);\n for (const callback of callbacks) {\n try {\n callback();\n } catch (e) {\n errors.push(e);\n }\n }\n}\n\nfunction cleanupRootInstance(\n rootElement: Element,\n instance: ComponentInstance,\n options?: RootCleanupOptions\n) {\n // Attempt to remove listeners and cleanup instances under the root.\n // In non-strict mode we preserve previous behavior by swallowing errors\n // (but logging in dev); in strict mode we aggregate and re-throw.\n const errors: unknown[] = [];\n try {\n teardownNodeSubtree(rootElement);\n } catch (e) {\n errors.push(e);\n }\n\n try {\n cleanupComponent(instance);\n } catch (e) {\n errors.push(e);\n }\n\n runRootCleanupCallbacks(rootElement, errors);\n\n if (!options?.preserveInstance) {\n unregisterAppInstance(instance);\n instancesByRoot.delete(rootElement);\n clearRootCleanupCallbacks(rootElement);\n try {\n delete (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n } catch {\n // Ignore cleanup marker removal failures.\n }\n }\n\n if (errors.length > 0) {\n if (instance.cleanupStrict) {\n throw new AggregateError(errors, `cleanup failed for app root`);\n } else if (isDevelopmentEnvironment()) {\n for (const err of errors) logger.warn('[Askr] cleanup error:', err);\n }\n }\n}\n\nfunction attachCleanupForRoot(\n rootElement: Element,\n instance: ComponentInstance\n) {\n (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL] = (options) => {\n cleanupRootInstance(rootElement, instance, options);\n };\n\n try {\n const descriptor =\n Object.getOwnPropertyDescriptor(rootElement, 'innerHTML') ||\n Object.getOwnPropertyDescriptor(\n Object.getPrototypeOf(rootElement),\n 'innerHTML'\n ) ||\n Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');\n\n if (descriptor && (descriptor.get || descriptor.set)) {\n Object.defineProperty(rootElement, 'innerHTML', {\n get: descriptor.get\n ? function (this: Element) {\n return descriptor.get!.call(this);\n }\n : undefined,\n set: function (this: Element, value: string) {\n if (value === '' && instancesByRoot.get(this) === instance) {\n cleanupRootInstance(rootElement, instance);\n }\n if (descriptor.set) {\n return descriptor.set.call(this, value);\n }\n },\n configurable: true,\n });\n }\n } catch {\n // If Object.defineProperty fails, ignore\n }\n}\n\nimport { Fragment, ELEMENT_TYPE } from '../jsx';\n\nimport { DefaultPortal } from '../foundations/structures/portal';\nimport { disposeDefaultPortalScope } from '../foundations/structures/portal';\n\nfunction mountOrUpdate(\n rootElement: Element,\n componentFn: ComponentFunction,\n options?: { cleanupStrict?: boolean }\n) {\n // Ensure root component always includes a DefaultPortal host by wrapping it.\n const wrappedFn: ComponentFunction = (props, ctx) => {\n const out = componentFn(props, ctx);\n if (isPromiseLike(out)) {\n throw new Error(\n 'Async components are not supported. Components must return synchronously.'\n );\n }\n const portalVNode = {\n $$typeof: ELEMENT_TYPE,\n type: DefaultPortal,\n props: {},\n key: '__default_portal',\n } as unknown;\n return {\n $$typeof: ELEMENT_TYPE,\n type: Fragment,\n props: {\n children:\n out === undefined || out === null\n ? [portalVNode]\n : [out, portalVNode],\n },\n } as unknown as ReturnType<ComponentFunction>;\n };\n // Preserve the original component name for debugging/dev warnings\n Object.defineProperty(wrappedFn, 'name', {\n value: componentFn.name || 'Component',\n });\n\n // Clean up existing cleanup function before mounting new one\n const existingCleanup = (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n const reusedExistingInstance = typeof existingCleanup === 'function';\n if (reusedExistingInstance) {\n existingCleanup({ preserveInstance: true });\n }\n\n let instance = instancesByRoot.get(rootElement);\n\n if (instance) {\n const shouldResetHookState = instance.fn.name !== wrappedFn.name;\n\n if (!reusedExistingInstance) {\n removeAllListeners(rootElement);\n try {\n cleanupComponent(instance);\n } catch (e) {\n // If previous cleanup threw in strict mode, log but continue mounting new instance\n if (isDevelopmentEnvironment()) {\n logger.warn('[Askr] prior cleanup threw:', e);\n }\n }\n }\n\n instance.fn = wrappedFn;\n instance.evaluationGeneration++;\n instance.mounted = false;\n instance.expectedStateIndices = [];\n instance.firstRenderComplete = false;\n instance.isRoot = true;\n instance.portalScope = instance;\n\n if (shouldResetHookState) {\n instance.stateValues = [];\n instance.hasPendingUpdate = false;\n instance.notifyUpdate = null;\n instance.stateIndexCheck = -1;\n instance.mountOperations = [];\n instance.commitOperations = [];\n instance.lifecycleSlots = [];\n instance.cleanupFns = [];\n instance._currentRenderToken = undefined;\n instance.lastRenderToken = 0;\n instance._pendingReadSources = undefined;\n instance._lastReadSources = undefined;\n instance._placeholder = undefined;\n instance.errorBoundaryState = undefined;\n instance.devWarningsEmitted = undefined;\n }\n\n // Update strict flag if provided\n if (options && typeof options.cleanupStrict === 'boolean') {\n instance.cleanupStrict = options.cleanupStrict;\n }\n } else {\n const componentId = String(++componentIdCounter);\n instance = createComponentInstance(componentId, wrappedFn, {}, rootElement);\n instancesByRoot.set(rootElement, instance);\n instance.isRoot = true;\n instance.portalScope = instance;\n // Initialize strict flag from options\n if (options && typeof options.cleanupStrict === 'boolean') {\n instance.cleanupStrict = options.cleanupStrict;\n }\n }\n\n attachCleanupForRoot(rootElement, instance);\n registerRootCleanupCallback(rootElement, () => {\n disposeDefaultPortalScope(instance.portalScope ?? instance);\n });\n mountComponent(instance);\n globalScheduler.flush();\n}\n\nfunction bindResolvedRouteHandler(resolved: ResolvedRoute): ComponentFunction {\n return () =>\n resolved.handler(resolved.params) as ReturnType<ComponentFunction>;\n}\n\nfunction bindDeniedStatus(status: number): ComponentFunction {\n return () => ({\n type: 'div',\n props: {\n 'data-route-denied': String(status),\n },\n children: [String(status)],\n });\n}\n\n// New strongly-typed init functions\nimport type {\n Route,\n RouteManifest,\n ResolvedRoute,\n RouteAuthOptions,\n RouteRequestResult,\n} from '../common/router';\nimport {\n installRendererBridge,\n removeAllListeners,\n teardownNodeSubtree,\n} from '../renderer';\ninstallRendererBridge();\n\nexport type IslandConfig = {\n root: Element | string;\n component: ComponentFunction;\n // Optional: surface cleanup errors during teardown for this island\n cleanupStrict?: boolean;\n // Explicitly disallow routes on islands at type level\n routes?: never;\n};\n\nexport type IslandsConfig = {\n islands: IslandConfig[];\n};\n\ntype BootRouteSource =\n | {\n manifest: RouteManifest;\n routes?: Route[];\n }\n | {\n manifest?: RouteManifest;\n routes: Route[];\n };\n\nexport type SPAConfig = BootRouteSource & {\n root: Element | string;\n /**\n * Preferred: pass the route manifest built via `registerRoutes(() => { ... })`.\n * ```ts\n * import { getManifest } from '@askrjs/askr/router';\n * await createSPA({ root: '#app', manifest: getManifest() });\n * ```\n */\n auth?: RouteAuthOptions;\n scrollRestoration?: boolean | ScrollRestorationOptions;\n cleanupStrict?: boolean;\n component?: never;\n};\n\nexport type HydrateSPAConfig = BootRouteSource & {\n root: Element | string;\n /** Preferred manifest input — see `SPAConfig.manifest`. */\n auth?: RouteAuthOptions;\n scrollRestoration?: boolean | ScrollRestorationOptions;\n cleanupStrict?: boolean;\n hydrate?: {\n verifyMarkup?: boolean;\n deferUntilIdle?: boolean;\n deferBelowFold?: boolean;\n foldThreshold?: number;\n skipSelectors?: string[];\n };\n};\n\nconst MAX_INITIAL_ROUTE_REDIRECTS = 20;\n\nasync function resolveInitialRoute(\n auth?: RouteAuthOptions\n): Promise<{ path: string; href: string; resolved: RouteRequestResult }> {\n let path = typeof window !== 'undefined' ? window.location.pathname : '/';\n let href =\n typeof window !== 'undefined'\n ? `${window.location.pathname}${window.location.search}${window.location.hash}`\n : path;\n const visited = new Set<string>();\n\n for (\n let redirects = 0;\n redirects <= MAX_INITIAL_ROUTE_REDIRECTS;\n redirects++\n ) {\n if (visited.has(href)) {\n throw new Error(`[Askr] Route redirect cycle detected at ${href}.`);\n }\n visited.add(href);\n\n const resolved = await resolveRouteRequest(href, { auth });\n if (\n typeof window === 'undefined' ||\n !resolved ||\n resolved.kind !== 'redirect'\n ) {\n return { path, href, resolved };\n }\n\n const redirectTarget = new URL(resolved.to, window.location.href);\n const redirectHref = `${redirectTarget.pathname}${redirectTarget.search}${redirectTarget.hash}`;\n window.history.replaceState({ path: redirectHref }, '', redirectHref);\n path = redirectTarget.pathname;\n href = redirectHref;\n }\n\n throw new Error(\n `[Askr] Route redirect limit exceeded (${MAX_INITIAL_ROUTE_REDIRECTS}).`\n );\n}\n\n/**\n * createIsland: Enhances existing DOM (no router, mounts once)\n */\nexport function createIsland(config: IslandConfig): void {\n assertExecutionModel('islands');\n if (!config || typeof config !== 'object') {\n throw new Error('createIsland requires a config object');\n }\n if (typeof config.component !== 'function') {\n throw new Error('createIsland: component must be a function');\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n\n // Islands must not initialize router or routes\n if ('routes' in config) {\n throw new Error(\n 'createIsland does not accept routes; use createSPA for routed apps'\n );\n }\n\n // Routes are never supported with islands.\n // If routes were registered (even at module load time), fail fast to avoid\n // surprising partial router behavior.\n try {\n const g = globalThis as unknown as Record<string | symbol, unknown>;\n if (g[HAS_ROUTES_KEY]) {\n throw new Error(\n 'Routes are not supported with islands. Use createSPA (client) or createSSR (server) instead.'\n );\n }\n } catch {\n // ignore\n }\n\n mountOrUpdate(rootElement, config.component, {\n cleanupStrict: config.cleanupStrict,\n });\n}\n\n/**\n * createIslands: Enhances one or more existing DOM roots (no router).\n * The only public islands constructor.\n */\nexport function createIslands(config: IslandsConfig): void {\n assertExecutionModel('islands');\n if (!config || typeof config !== 'object') {\n throw new Error('createIslands requires a config object');\n }\n if (!Array.isArray(config.islands) || config.islands.length === 0) {\n throw new Error('createIslands requires a non-empty islands array');\n }\n for (const island of config.islands) {\n createIsland(island);\n }\n}\n\n/**\n * createSPA: Initializes router and mounts the app with the provided route manifest or route table.\n *\n * Preferred usage with manifest:\n * ```ts\n * import { getManifest } from '@askrjs/askr/router';\n * await createSPA({ root: '#app', manifest: getManifest() });\n * ```\n *\n * Legacy usage with plain routes array (still supported):\n * ```ts\n * await createSPA({ root: '#app', routes: getRoutes() });\n * ```\n */\nexport async function createSPA(config: SPAConfig): Promise<void> {\n assertExecutionModel('spa');\n if (!config || typeof config !== 'object') {\n throw new Error('createSPA requires a config object');\n }\n\n const hasManifest =\n config.manifest != null && config.manifest.records.length > 0;\n const hasRoutes = Array.isArray(config.routes) && config.routes.length > 0;\n\n if (!hasManifest && !hasRoutes) {\n throw new Error(\n 'createSPA requires a route manifest or route table. ' +\n 'Pass `manifest: getManifest()` or `routes: getRoutes()`. ' +\n 'If you are enhancing existing HTML, use createIsland instead.'\n );\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n\n const pendingLazyAtBoot = _snapshotLazy();\n\n configureScrollRestoration(config.scrollRestoration);\n\n clearRoutes();\n\n if (hasManifest) {\n // Preferred path: apply pre-built manifest records directly\n _applyManifest(config.manifest!);\n } else {\n // Legacy path: register plain Route objects (no layout metadata)\n for (const r of config.routes!) {\n registerRoute(r.path, r.handler as Parameters<typeof registerRoute>[1]);\n }\n }\n\n const routeAuth = config.auth ?? config.manifest?.auth;\n _setActiveRouteAuthOptions(routeAuth);\n\n // Drain any lazy() imports so all split chunks are ready before mounting\n await _drainLazy(pendingLazyAtBoot);\n\n // Lock registration in production to prevent late registration surprises\n if (isProductionEnvironment()) lockRouteRegistration();\n\n // Mount the currently-resolved route handler (if any)\n const { path, resolved } = await resolveInitialRoute(routeAuth);\n\n if (!resolved) {\n mountOrUpdate(rootElement, () => ({ type: 'div', children: [] }), {\n cleanupStrict: config.cleanupStrict,\n });\n\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: routeAuth,\n });\n return;\n }\n\n if (resolved.kind === 'redirect') {\n mountOrUpdate(rootElement, () => ({ type: 'div', children: [] }), {\n cleanupStrict: config.cleanupStrict,\n });\n\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: routeAuth,\n });\n return;\n }\n\n mountOrUpdate(\n rootElement,\n resolved.kind === 'deny'\n ? bindDeniedStatus(resolved.status)\n : bindResolvedRouteHandler({\n handler: resolved.handler,\n params: resolved.params,\n }),\n {\n cleanupStrict: config.cleanupStrict,\n }\n );\n\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: routeAuth,\n });\n}\n\n/**\n * Mark elements that should be skipped during hydration\n */\nfunction markSkippedElements(root: Element, skipSelectors: string[]): void {\n if (skipSelectors.length === 0) {\n return;\n }\n\n const uniqueSelectors = Array.from(new Set(skipSelectors));\n const selectorList = uniqueSelectors.join(', ');\n const elements = root.querySelectorAll(selectorList);\n elements.forEach((el) => el.setAttribute('data-skip-hydrate', 'true'));\n}\n\nfunction collectDeferredBelowFoldBoundaries(\n root: Element,\n foldY: number\n): Element[] {\n const boundaries: Element[] = [];\n const stack: Element[] = [];\n\n for (let index = root.children.length - 1; index >= 0; index -= 1) {\n stack.push(root.children[index]);\n }\n\n while (stack.length > 0) {\n const element = stack.pop()!;\n\n if (element.hasAttribute('data-skip-hydrate')) {\n continue;\n }\n\n const rect = element.getBoundingClientRect();\n if (rect.top >= foldY) {\n element.setAttribute('data-skip-hydrate', 'true');\n boundaries.push(element);\n continue;\n }\n\n for (let index = element.children.length - 1; index >= 0; index -= 1) {\n stack.push(element.children[index]);\n }\n }\n\n return boundaries;\n}\n\nfunction activateVisibleDeferredBoundaries(\n boundaries: Element[],\n foldY: number\n): { activated: boolean; remaining: number } {\n let activated = false;\n let remaining = 0;\n\n for (const element of boundaries) {\n if (!element.hasAttribute('data-skip-hydrate')) {\n continue;\n }\n\n const rect = element.getBoundingClientRect();\n if (rect.top < foldY) {\n element.removeAttribute('data-skip-hydrate');\n activated = true;\n } else {\n remaining += 1;\n }\n }\n\n return { activated, remaining };\n}\n\nfunction queueIdleWork(work: () => void): Promise<void> {\n return new Promise((resolve) => {\n if (typeof requestIdleCallback !== 'undefined') {\n requestIdleCallback(\n () => {\n work();\n resolve();\n },\n { timeout: 2000 }\n );\n return;\n }\n\n setTimeout(() => {\n work();\n resolve();\n }, 0);\n });\n}\n\nfunction flushHydrationActivation(rootElement: Element): void {\n const instance = instancesByRoot.get(rootElement);\n if (!instance) return;\n instance._enqueueRun?.();\n globalScheduler.flush();\n}\n\nfunction shouldVerifyHydrationMarkup(config: HydrateSPAConfig): boolean {\n const explicit = config.hydrate?.verifyMarkup;\n if (typeof explicit === 'boolean') {\n return explicit;\n }\n\n return !isProductionEnvironment();\n}\n\nasync function registerAppNavigation(\n rootElement: Element,\n path: string,\n source?: {\n manifest?: RouteManifest;\n routes?: Route[];\n auth?: RouteAuthOptions;\n }\n) {\n const instance = instancesByRoot.get(rootElement);\n if (!instance) throw new Error('Internal error: app instance missing');\n registerAppInstance(instance as ComponentInstance, path, source);\n initializeNavigation();\n}\n\n/**\n * Apply selective hydration with deferral options\n */\nasync function applySelectiveHydration(\n rootElement: Element,\n resolved: { handler: ComponentFunction; params: Record<string, unknown> },\n path: string,\n cleanupStrict: boolean | undefined,\n hydrateOptions: NonNullable<HydrateSPAConfig['hydrate']>\n): Promise<void> {\n const hasPermanentSkips = (hydrateOptions.skipSelectors?.length ?? 0) > 0;\n const hasBelowFoldDeferral = !!hydrateOptions.deferBelowFold;\n const hasSelectiveBoundaries = hasPermanentSkips || hasBelowFoldDeferral;\n let staticChildSlotsCacheSuspended = false;\n let releaseSelectiveHydrationResources = () => {};\n\n const restoreStaticChildSlotsCache = () => {\n if (!staticChildSlotsCacheSuspended) {\n return;\n }\n\n setStaticChildSlotsCacheEnabled(true);\n staticChildSlotsCacheSuspended = false;\n };\n\n if (hydrateOptions.skipSelectors?.length) {\n markSkippedElements(rootElement, hydrateOptions.skipSelectors);\n }\n\n let deferredBoundaries: Element[] = [];\n if (hydrateOptions.deferBelowFold) {\n setStaticChildSlotsCacheEnabled(false);\n staticChildSlotsCacheSuspended = true;\n const foldY = hydrateOptions.foldThreshold ?? window.innerHeight;\n deferredBoundaries = collectDeferredBelowFoldBoundaries(rootElement, foldY);\n\n let selectiveHydrationResourcesReleased = false;\n let unregisterRootCleanupCallback = () => {};\n\n function handleScroll() {\n const { activated, remaining } = activateVisibleDeferredBoundaries(\n deferredBoundaries,\n foldY\n );\n\n if (!activated) {\n return;\n }\n\n flushHydrationActivation(rootElement);\n\n if (remaining === 0) {\n releaseSelectiveHydrationResources();\n }\n }\n\n releaseSelectiveHydrationResources = () => {\n if (selectiveHydrationResourcesReleased) {\n return;\n }\n\n selectiveHydrationResourcesReleased = true;\n unregisterRootCleanupCallback();\n window.removeEventListener('scroll', handleScroll);\n restoreStaticChildSlotsCache();\n };\n\n unregisterRootCleanupCallback = registerRootCleanupCallback(\n rootElement,\n releaseSelectiveHydrationResources\n );\n\n window.addEventListener('scroll', handleScroll, { passive: true });\n }\n\n if (hydrateOptions.deferUntilIdle && !hasSelectiveBoundaries) {\n await queueIdleWork(() => {\n mountOrUpdate(\n rootElement,\n (() => resolved.handler(resolved.params)) as ComponentFunction,\n {\n cleanupStrict,\n }\n );\n });\n await registerAppNavigation(rootElement, path);\n return;\n }\n\n try {\n mountOrUpdate(\n rootElement,\n (() => resolved.handler(resolved.params)) as ComponentFunction,\n {\n cleanupStrict,\n }\n );\n await registerAppNavigation(rootElement, path);\n } catch (error) {\n releaseSelectiveHydrationResources();\n throw error;\n }\n\n if (hydrateOptions.deferUntilIdle && deferredBoundaries.length > 0) {\n await queueIdleWork(() => {\n try {\n const { activated } = activateVisibleDeferredBoundaries(\n deferredBoundaries,\n Number.POSITIVE_INFINITY\n );\n if (activated) {\n flushHydrationActivation(rootElement);\n }\n } finally {\n releaseSelectiveHydrationResources();\n }\n });\n }\n\n if (deferredBoundaries.length === 0) {\n releaseSelectiveHydrationResources();\n }\n}\n\n/**\n * hydrateSPA: Hydrate server-rendered HTML.\n * Accepts either a `manifest` (preferred) or a legacy `routes` array.\n */\nexport async function hydrateSPA(config: HydrateSPAConfig): Promise<void> {\n assertExecutionModel('spa');\n if (!config || typeof config !== 'object') {\n throw new Error('hydrateSPA requires a config object');\n }\n\n const hasManifest =\n config.manifest != null && config.manifest.records.length > 0;\n const hasRoutes = Array.isArray(config.routes) && config.routes.length > 0;\n\n if (!hasManifest && !hasRoutes) {\n throw new Error(\n 'hydrateSPA requires a route manifest or route table. ' +\n 'Pass `manifest: getManifest()` or `routes: getRoutes()`. ' +\n 'If you are enhancing existing HTML, use createIsland instead.'\n );\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n const hydrationRenderData = takeHydrationRenderData(rootElement);\n\n const pendingLazyAtHydrationBoot = _snapshotLazy();\n\n configureScrollRestoration(config.scrollRestoration);\n\n clearRoutes();\n\n if (hasManifest) {\n _applyManifest(config.manifest!);\n } else {\n for (const r of config.routes!) {\n registerRoute(r.path, r.handler as Parameters<typeof registerRoute>[1]);\n }\n }\n\n _setActiveRouteAuthOptions(config.auth ?? config.manifest?.auth);\n\n // Drain any lazy() imports so all split chunks are ready before mounting\n await _drainLazy(pendingLazyAtHydrationBoot);\n\n const {\n path,\n href: currentUrl,\n resolved,\n } = await resolveInitialRoute(config.auth ?? config.manifest?.auth);\n setServerLocation(currentUrl);\n if (isProductionEnvironment()) lockRouteRegistration();\n\n if (!resolved) {\n throw new Error(`hydrateSPA: no route found for current path (${path}).`);\n }\n\n if (resolved.kind === 'redirect') {\n throw new Error(\n `hydrateSPA: unresolved redirect for current path (${path}).`\n );\n }\n\n const hydrationResolved: ResolvedRoute =\n resolved.kind === 'deny'\n ? { handler: bindDeniedStatus(resolved.status), params: {} }\n : { handler: resolved.handler, params: resolved.params };\n\n if (shouldVerifyHydrationMarkup(config)) {\n const legacyRouteTable = hasManifest\n ? config.manifest!.records.map((r) => ({\n path: r.path,\n handler: r.handler,\n namespace: r.options.namespace,\n }))\n : config.routes!;\n\n const { verifyHydrationSyncForUrl } =\n await import('../ssr/verify-hydration');\n if (\n !verifyHydrationSyncForUrl({\n root: rootElement,\n url: currentUrl,\n routes: legacyRouteTable,\n resolved: hydrationResolved,\n options: {\n data: hydrationRenderData ?? undefined,\n },\n })\n ) {\n throw new Error(\n '[Askr] Hydration mismatch detected. Server HTML does not match expected server-render output.'\n );\n }\n }\n\n const hydrateOptions = config.hydrate;\n if (hydrateOptions) {\n if (hydrateOptions.deferUntilIdle || hydrateOptions.deferBelowFold) {\n if (hydrationRenderData) {\n startHydrationRenderPhase(hydrationRenderData);\n }\n try {\n await applySelectiveHydration(\n rootElement,\n hydrationResolved,\n path,\n config.cleanupStrict,\n hydrateOptions\n );\n } finally {\n if (hydrationRenderData) {\n stopHydrationRenderPhase();\n }\n }\n return;\n }\n\n if (hydrateOptions.skipSelectors?.length) {\n markSkippedElements(rootElement, hydrateOptions.skipSelectors);\n }\n }\n\n if (hydrationRenderData) {\n startHydrationRenderPhase(hydrationRenderData);\n }\n try {\n mountOrUpdate(\n rootElement,\n resolved.kind === 'deny'\n ? bindDeniedStatus(resolved.status)\n : bindResolvedRouteHandler(hydrationResolved),\n {\n cleanupStrict: config.cleanupStrict,\n }\n );\n } finally {\n if (hydrationRenderData) {\n stopHydrationRenderPhase();\n }\n }\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: config.auth ?? config.manifest?.auth,\n });\n}\n\n/**\n * Cleanup an app mounted on a root element (element or id).\n * Safe to call multiple times — no-op when nothing is mounted.\n */\nexport function cleanupApp(root: Element | string): void {\n const rootElement =\n typeof root === 'string' ? document.getElementById(root) : root;\n\n if (!rootElement) return;\n\n const cleanupFn = (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n try {\n if (typeof cleanupFn === 'function') {\n cleanupFn();\n }\n } finally {\n instancesByRoot.delete(rootElement);\n clearRootCleanupCallbacks(rootElement);\n try {\n delete (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n } catch {\n // Ignore cleanup marker removal failures.\n }\n }\n}\n\n/**\n * Check whether an app is mounted on the given root\n */\nexport function hasApp(root: Element | string): boolean {\n const rootElement =\n typeof root === 'string' ? document.getElementById(root) : root;\n\n if (!rootElement) return false;\n return instancesByRoot.has(rootElement);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"env.js","names":[],"sources":["../../src/common/env.ts"],"sourcesContent":["export type RuntimeEnv = Record<string, string | undefined>;\n\ntype RuntimeEnvGlobal = typeof globalThis & {\n process?: {\n env?: RuntimeEnv;\n };\n};\n\ntype BuildTimeEnv = Record<string, unknown> & {\n NODE_ENV?: unknown;\n MODE?: unknown;\n PROD?: unknown;\n DEV?: unknown;\n};\n\nfunction normalizeEnv(source?: Record<string, unknown>): RuntimeEnv {\n if (!source) {\n return {};\n }\n\n const normalized: RuntimeEnv = {};\n for (const [key, value] of Object.entries(source)) {\n if (typeof value === 'string') {\n normalized[key] = value;\n } else if (typeof value === 'boolean' || typeof value === 'number') {\n normalized[key] = String(value);\n }\n }\n\n return normalized;\n}\n\nfunction getBuildTimeEnv(): RuntimeEnv {\n const metaEnv = (import.meta as ImportMeta & { env?: BuildTimeEnv }).env;\n const normalized = normalizeEnv(metaEnv);\n\n if (normalized.NODE_ENV == null && metaEnv) {\n if (typeof metaEnv.MODE === 'string' && metaEnv.MODE.length > 0) {\n normalized.NODE_ENV = metaEnv.MODE;\n } else if (metaEnv.PROD === true || metaEnv.PROD === 'true') {\n normalized.NODE_ENV = 'production';\n } else if (metaEnv.DEV === true || metaEnv.DEV === 'true') {\n normalized.NODE_ENV = 'development';\n }\n }\n\n return normalized;\n}\n\nfunction resolveNodeEnv(\n processNodeEnv: string | undefined,\n buildNodeEnv: string | undefined\n): string | undefined {\n if (buildNodeEnv === 'production') {\n return 'production';\n }\n\n if (processNodeEnv != null) {\n return processNodeEnv;\n }\n\n if (buildNodeEnv === 'development') {\n return 'development';\n }\n\n return buildNodeEnv === 'test' ? undefined : buildNodeEnv;\n}\n\nexport function getRuntimeEnv(): RuntimeEnv {\n const processEnv = (globalThis as RuntimeEnvGlobal).process?.env ?? {};\n const buildTimeEnv = getBuildTimeEnv();\n\n return {\n ...processEnv,\n ...buildTimeEnv,\n NODE_ENV: resolveNodeEnv(processEnv.NODE_ENV, buildTimeEnv.NODE_ENV),\n };\n}\n\nexport function isProductionEnvironment(): boolean {\n return getRuntimeEnv().NODE_ENV === 'production';\n}\n\nexport function isDevelopmentEnvironment(): boolean {\n return !isProductionEnvironment();\n}\n\nexport function isRuntimeEnvFlagEnabled(name: string): boolean {\n const value = getRuntimeEnv()[name];\n return value === '1' || value === 'true';\n}\n"],"mappings":";AAeA,SAAS,aAAa,QAA8C;CAClE,IAAI,CAAC,QACH,OAAO,CAAC;CAGV,MAAM,aAAyB,CAAC;CAChC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,OAAO,UAAU,UACnB,WAAW,OAAO;MACb,IAAI,OAAO,UAAU,aAAa,OAAO,UAAU,UACxD,WAAW,OAAO,OAAO,KAAK;CAIlC,OAAO;AACT;AAEA,SAAS,kBAA8B;CACrC,MAAM,UAAW,OAAO,KAA6C;CACrE,MAAM,aAAa,aAAa,OAAO;CAEvC,IAAI,WAAW,YAAY,QAAQ,SACjC;MAAI,OAAO,QAAQ,SAAS,YAAY,QAAQ,KAAK,SAAS,GAC5D,WAAW,WAAW,QAAQ;OACzB,IAAI,QAAQ,SAAS,QAAQ,QAAQ,SAAS,QACnD,WAAW,WAAW;OACjB,IAAI,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QACjD,WAAW,WAAW;CACxB;CAGF,OAAO;AACT;AAEA,SAAS,eACP,gBACA,cACoB;CACpB,IAAI,iBAAiB,cACnB,OAAO;CAGT,IAAI,kBAAkB,MACpB,OAAO;CAGT,IAAI,iBAAiB,eACnB,OAAO;CAGT,OAAO,iBAAiB,SAAS,SAAY;AAC/C;AAEA,SAAgB,gBAA4B;CAC1C,MAAM,aAAc,WAAgC,SAAS,OAAO,CAAC;CACrE,MAAM,eAAe,gBAAgB;CAErC,OAAO;EACL,GAAG;EACH,GAAG;EACH,UAAU,eAAe,WAAW,UAAU,aAAa,QAAQ;CACrE;AACF;AAEA,SAAgB,0BAAmC;CACjD,OAAO,cAAc,EAAE,aAAa;AACtC;AAEA,SAAgB,2BAAoC;CAClD,OAAO,CAAC,wBAAwB;AAClC;AAEA,SAAgB,wBAAwB,MAAuB;CAC7D,MAAM,QAAQ,cAAc,EAAE;CAC9B,OAAO,UAAU,OAAO,UAAU;AACpC"}
1
+ {"version":3,"file":"env.js","names":[],"sources":["../../src/common/env.ts"],"sourcesContent":["export type RuntimeEnv = Record<string, string | undefined>;\n\ntype RuntimeEnvGlobal = typeof globalThis & {\n process?: {\n env?: RuntimeEnv;\n };\n};\n\ntype BuildTimeEnv = Record<string, unknown> & {\n NODE_ENV?: unknown;\n MODE?: unknown;\n PROD?: unknown;\n DEV?: unknown;\n};\n\nfunction normalizeEnv(source?: Record<string, unknown>): RuntimeEnv {\n if (!source) {\n return {};\n }\n\n const normalized: RuntimeEnv = {};\n for (const [key, value] of Object.entries(source)) {\n if (typeof value === 'string') {\n normalized[key] = value;\n } else if (typeof value === 'boolean' || typeof value === 'number') {\n normalized[key] = String(value);\n }\n }\n\n return normalized;\n}\n\nfunction getBuildTimeEnv(): RuntimeEnv {\n const metaEnv = (import.meta as ImportMeta & { env?: BuildTimeEnv }).env;\n const normalized = normalizeEnv(metaEnv);\n\n if (normalized.NODE_ENV == null && metaEnv) {\n if (typeof metaEnv.MODE === 'string' && metaEnv.MODE.length > 0) {\n normalized.NODE_ENV = metaEnv.MODE;\n } else if (metaEnv.PROD === true || metaEnv.PROD === 'true') {\n normalized.NODE_ENV = 'production';\n } else if (metaEnv.DEV === true || metaEnv.DEV === 'true') {\n normalized.NODE_ENV = 'development';\n }\n }\n\n return normalized;\n}\n\nfunction resolveNodeEnv(\n processNodeEnv: string | undefined,\n buildNodeEnv: string | undefined\n): string | undefined {\n if (buildNodeEnv === 'production') {\n return 'production';\n }\n\n if (processNodeEnv != null) {\n return processNodeEnv;\n }\n\n if (buildNodeEnv === 'development') {\n return 'development';\n }\n\n return buildNodeEnv === 'test' ? undefined : buildNodeEnv;\n}\n\nexport function getRuntimeEnv(): RuntimeEnv {\n const processEnv = (globalThis as RuntimeEnvGlobal).process?.env ?? {};\n const buildTimeEnv = getBuildTimeEnv();\n\n return {\n ...processEnv,\n ...buildTimeEnv,\n NODE_ENV: resolveNodeEnv(processEnv.NODE_ENV, buildTimeEnv.NODE_ENV),\n };\n}\n\nexport function isProductionEnvironment(): boolean {\n return getRuntimeEnv().NODE_ENV === 'production';\n}\n\nexport function isDevelopmentEnvironment(): boolean {\n return !isProductionEnvironment();\n}\n\nexport function isRuntimeEnvFlagEnabled(name: string): boolean {\n const value = getRuntimeEnv()[name];\n return value === '1' || value === 'true';\n}\n"],"mappings":";AAeA,SAAS,aAAa,QAA8C;CAClE,IAAI,CAAC,QACH,OAAO,CAAC;CAGV,MAAM,aAAyB,CAAC;CAChC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,OAAO,UAAU,UACnB,WAAW,OAAO;MACb,IAAI,OAAO,UAAU,aAAa,OAAO,UAAU,UACxD,WAAW,OAAO,OAAO,KAAK;CAIlC,OAAO;AACT;AAEA,SAAS,kBAA8B;CACrC,MAAM,UAAW,OAAO,KAA6C;CACrE,MAAM,aAAa,aAAa,OAAO;CAEvC,IAAI,WAAW,YAAY,QAAQ,SACjC;MAAI,OAAO,QAAQ,SAAS,YAAY,QAAQ,KAAK,SAAS,GAC5D,WAAW,WAAW,QAAQ;OACzB,IAAI,QAAQ,SAAS,QAAQ,QAAQ,SAAS,QACnD,WAAW,WAAW;OACjB,IAAI,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QACjD,WAAW,WAAW;CACxB;CAGF,OAAO;AACT;AAEA,SAAS,eACP,gBACA,cACoB;CACpB,IAAI,iBAAiB,cACnB,OAAO;CAGT,IAAI,kBAAkB,MACpB,OAAO;CAGT,IAAI,iBAAiB,eACnB,OAAO;CAGT,OAAO,iBAAiB,SAAS,SAAY;AAC/C;AAEA,SAAgB,gBAA4B;CAC1C,MAAM,aAAc,WAAgC,SAAS,OAAO,CAAC;CACrE,MAAM,eAAe,gBAAgB;CAErC,OAAO;EACL,GAAG;EACH,GAAG;EACH,UAAU,eAAe,WAAW,UAAU,aAAa,QAAQ;CACrE;AACF;AAEA,SAAgB,0BAAmC;CACjD,OAAO,cAAc,CAAC,CAAC,aAAa;AACtC;AAEA,SAAgB,2BAAoC;CAClD,OAAO,CAAC,wBAAwB;AAClC;AAEA,SAAgB,wBAAwB,MAAuB;CAC7D,MAAM,QAAQ,cAAc,CAAC,CAAC;CAC9B,OAAO,UAAU,OAAO,UAAU;AACpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"route-activity.js","names":[],"sources":["../../src/common/route-activity.ts"],"sourcesContent":["import type { RouteMatch } from './router';\n\nexport type RouteActivityMatch = Pick<RouteMatch, 'path'>;\n\ntype RouteActivitySnapshot = {\n path: string;\n matches: readonly RouteActivityMatch[];\n};\n\nlet currentRouteActivity: RouteActivitySnapshot = {\n path: '/',\n matches: [],\n};\n\nfunction normalizeRouteActivityPath(path: string): string {\n const withoutHash = path.split('#', 1)[0] ?? '';\n const withoutSearch = withoutHash.split('?', 1)[0] ?? '';\n const pathname = withoutSearch || '/';\n const absolutePathname = pathname.startsWith('/') ? pathname : `/${pathname}`;\n\n return absolutePathname.endsWith('/') && absolutePathname !== '/'\n ? absolutePathname.slice(0, -1)\n : absolutePathname;\n}\n\nfunction readActivePathname(): string {\n if (typeof window !== 'undefined' && window.location) {\n return window.location.pathname || '/';\n }\n\n return currentRouteActivity.path;\n}\n\nexport function syncRouteActivitySnapshot(\n pathname: string,\n matches: readonly RouteActivityMatch[] = []\n): void {\n currentRouteActivity = {\n path: normalizeRouteActivityPath(pathname),\n matches: Object.freeze([...matches]),\n };\n}\n\nexport function isRouteActivityActive(\n pathOrPaths: string | readonly string[]\n): boolean {\n const candidates = new Set(\n (Array.isArray(pathOrPaths) ? pathOrPaths : [pathOrPaths]).map(\n normalizeRouteActivityPath\n )\n );\n\n const activePath = normalizeRouteActivityPath(readActivePathname());\n if (candidates.has(activePath)) {\n return true;\n }\n\n return currentRouteActivity.matches.some((match) =>\n candidates.has(normalizeRouteActivityPath(match.path))\n );\n}\n"],"mappings":";AASA,IAAI,uBAA8C;CAChD,MAAM;CACN,SAAS,CAAC;AACZ;AAEA,SAAS,2BAA2B,MAAsB;CAGxD,MAAM,aAFc,KAAK,MAAM,KAAK,CAAC,EAAE,MAAM,IACX,MAAM,KAAK,CAAC,EAAE,MAAM,OACpB;CAClC,MAAM,mBAAmB,SAAS,WAAW,GAAG,IAAI,WAAW,IAAI;CAEnE,OAAO,iBAAiB,SAAS,GAAG,KAAK,qBAAqB,MAC1D,iBAAiB,MAAM,GAAG,EAAE,IAC5B;AACN;AAEA,SAAS,qBAA6B;CACpC,IAAI,OAAO,WAAW,eAAe,OAAO,UAC1C,OAAO,OAAO,SAAS,YAAY;CAGrC,OAAO,qBAAqB;AAC9B;AAEA,SAAgB,0BACd,UACA,UAAyC,CAAC,GACpC;CACN,uBAAuB;EACrB,MAAM,2BAA2B,QAAQ;EACzC,SAAS,OAAO,OAAO,CAAC,GAAG,OAAO,CAAC;CACrC;AACF;AAEA,SAAgB,sBACd,aACS;CACT,MAAM,aAAa,IAAI,KACpB,MAAM,QAAQ,WAAW,IAAI,cAAc,CAAC,WAAW,GAAG,IACzD,0BACF,CACF;CAEA,MAAM,aAAa,2BAA2B,mBAAmB,CAAC;CAClE,IAAI,WAAW,IAAI,UAAU,GAC3B,OAAO;CAGT,OAAO,qBAAqB,QAAQ,MAAM,UACxC,WAAW,IAAI,2BAA2B,MAAM,IAAI,CAAC,CACvD;AACF"}
1
+ {"version":3,"file":"route-activity.js","names":[],"sources":["../../src/common/route-activity.ts"],"sourcesContent":["import type { RouteMatch } from './router';\n\nexport type RouteActivityMatch = Pick<RouteMatch, 'path'>;\n\ntype RouteActivitySnapshot = {\n path: string;\n matches: readonly RouteActivityMatch[];\n};\n\nlet currentRouteActivity: RouteActivitySnapshot = {\n path: '/',\n matches: [],\n};\n\nfunction normalizeRouteActivityPath(path: string): string {\n const withoutHash = path.split('#', 1)[0] ?? '';\n const withoutSearch = withoutHash.split('?', 1)[0] ?? '';\n const pathname = withoutSearch || '/';\n const absolutePathname = pathname.startsWith('/') ? pathname : `/${pathname}`;\n\n return absolutePathname.endsWith('/') && absolutePathname !== '/'\n ? absolutePathname.slice(0, -1)\n : absolutePathname;\n}\n\nfunction readActivePathname(): string {\n if (typeof window !== 'undefined' && window.location) {\n return window.location.pathname || '/';\n }\n\n return currentRouteActivity.path;\n}\n\nexport function syncRouteActivitySnapshot(\n pathname: string,\n matches: readonly RouteActivityMatch[] = []\n): void {\n currentRouteActivity = {\n path: normalizeRouteActivityPath(pathname),\n matches: Object.freeze([...matches]),\n };\n}\n\nexport function isRouteActivityActive(\n pathOrPaths: string | readonly string[]\n): boolean {\n const candidates = new Set(\n (Array.isArray(pathOrPaths) ? pathOrPaths : [pathOrPaths]).map(\n normalizeRouteActivityPath\n )\n );\n\n const activePath = normalizeRouteActivityPath(readActivePathname());\n if (candidates.has(activePath)) {\n return true;\n }\n\n return currentRouteActivity.matches.some((match) =>\n candidates.has(normalizeRouteActivityPath(match.path))\n );\n}\n"],"mappings":";AASA,IAAI,uBAA8C;CAChD,MAAM;CACN,SAAS,CAAC;AACZ;AAEA,SAAS,2BAA2B,MAAsB;CAGxD,MAAM,aAFc,KAAK,MAAM,KAAK,CAAC,CAAC,CAAC,MAAM,GACvB,CAAY,MAAM,KAAK,CAAC,CAAC,CAAC,MAAM,OACpB;CAClC,MAAM,mBAAmB,SAAS,WAAW,GAAG,IAAI,WAAW,IAAI;CAEnE,OAAO,iBAAiB,SAAS,GAAG,KAAK,qBAAqB,MAC1D,iBAAiB,MAAM,GAAG,EAAE,IAC5B;AACN;AAEA,SAAS,qBAA6B;CACpC,IAAI,OAAO,WAAW,eAAe,OAAO,UAC1C,OAAO,OAAO,SAAS,YAAY;CAGrC,OAAO,qBAAqB;AAC9B;AAEA,SAAgB,0BACd,UACA,UAAyC,CAAC,GACpC;CACN,uBAAuB;EACrB,MAAM,2BAA2B,QAAQ;EACzC,SAAS,OAAO,OAAO,CAAC,GAAG,OAAO,CAAC;CACrC;AACF;AAEA,SAAgB,sBACd,aACS;CACT,MAAM,aAAa,IAAI,KACpB,MAAM,QAAQ,WAAW,IAAI,cAAc,CAAC,WAAW,EAAA,CAAG,IACzD,0BACF,CACF;CAEA,MAAM,aAAa,2BAA2B,mBAAmB,CAAC;CAClE,IAAI,WAAW,IAAI,UAAU,GAC3B,OAAO;CAGT,OAAO,qBAAqB,QAAQ,MAAM,UACxC,WAAW,IAAI,2BAA2B,MAAM,IAAI,CAAC,CACvD;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"case.js","names":[],"sources":["../../src/control/case.ts"],"sourcesContent":["import {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { VNode } from '../common/vnode';\nimport { isDevelopmentEnvironment } from '../common/env';\nimport {\n createCaseState,\n type CaseState,\n type MatchBranch,\n} from '../runtime/control';\nimport { state } from '../runtime/state';\nimport { type BoundaryChild, normalizeBoundaryChild } from './shared';\n\ntype MatchChild = BoundaryChild | (() => BoundaryChild);\n\nexport type MatchProps = {\n key?: string | number | null;\n when: unknown;\n children: MatchChild;\n};\n\nexport type CaseProps = {\n fallback?: BoundaryChild;\n children?: unknown;\n};\n\nfunction flattenChildren(children: unknown): unknown[] {\n if (!Array.isArray(children)) {\n return children == null || children === false ? [] : [children];\n }\n\n const result: unknown[] = [];\n for (const child of children) {\n if (Array.isArray(child)) {\n result.push(...flattenChildren(child));\n continue;\n }\n result.push(child);\n }\n return result;\n}\n\nexport function Match(_props: MatchProps): null {\n if (isDevelopmentEnvironment()) {\n throw new Error(\n '[askr] <Match> may only be used as a direct child of <Case>.'\n );\n }\n return null;\n}\n\nfunction createCaseFallbackRenderer(\n fallback: BoundaryChild | undefined\n): (() => VNode) | null {\n const normalizedFallback = normalizeBoundaryChild(fallback);\n if (normalizedFallback == null || normalizedFallback === false) {\n return null;\n }\n return () => normalizedFallback;\n}\n\nfunction createMatchBranchKey(\n key: string | number | null | undefined,\n index: number\n): string | number {\n if (key == null) {\n return index;\n }\n return `match:${index}:${typeof key}:${String(key)}`;\n}\n\nfunction readMatchBranches(children: unknown): MatchBranch[] {\n const branches: MatchBranch[] = [];\n const flatChildren = flattenChildren(children);\n\n for (let index = 0; index < flatChildren.length; index += 1) {\n const child = flatChildren[index];\n if (child == null || child === false) {\n continue;\n }\n\n if (\n typeof child === 'object' &&\n child !== null &&\n 'type' in child &&\n (child as JSXElement).type === Match\n ) {\n const element = child as JSXElement;\n const props = (element.props ?? {}) as MatchProps;\n const key = createMatchBranchKey(element.key, index);\n const render =\n typeof props.children === 'function'\n ? () =>\n normalizeBoundaryChild(\n (props.children as () => BoundaryChild)()\n ) as VNode\n : () => normalizeBoundaryChild(props.children) as VNode;\n branches.push({\n key,\n render,\n when: props.when,\n });\n continue;\n }\n\n if (isDevelopmentEnvironment()) {\n throw new Error('[askr] <Case> only accepts <Match> children.');\n }\n }\n\n return branches;\n}\n\nfunction CasePrimitive(props: CaseProps): JSXElement {\n const matches = readMatchBranches(props.children);\n const fallback = createCaseFallbackRenderer(props.fallback);\n\n const caseStateContainer = state<CaseState>(\n createCaseState(matches, fallback)\n );\n const caseState = caseStateContainer();\n\n caseState.matches = matches;\n caseState.fallback = fallback;\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: caseState,\n } as unknown as JSXElement;\n}\n\nexport const Case = markEagerControlPrimitive(\n CasePrimitive as (props: CaseProps) => JSXElement\n) as (props: CaseProps) => JSXElement;\n"],"mappings":";;;;;;AA4BA,SAAS,gBAAgB,UAA8B;CACrD,IAAI,CAAC,MAAM,QAAQ,QAAQ,GACzB,OAAO,YAAY,QAAQ,aAAa,QAAQ,CAAC,IAAI,CAAC,QAAQ;CAGhE,MAAM,SAAoB,CAAC;CAC3B,KAAK,MAAM,SAAS,UAAU;EAC5B,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,OAAO,KAAK,GAAG,gBAAgB,KAAK,CAAC;GACrC;EACF;EACA,OAAO,KAAK,KAAK;CACnB;CACA,OAAO;AACT;AAEA,SAAgB,MAAM,QAA0B;CAC9C,IAAI,yBAAyB,GAC3B,MAAM,IAAI,MACR,8DACF;CAEF,OAAO;AACT;AAEA,SAAS,2BACP,UACsB;CACtB,MAAM,qBAAqB,uBAAuB,QAAQ;CAC1D,IAAI,sBAAsB,QAAQ,uBAAuB,OACvD,OAAO;CAET,aAAa;AACf;AAEA,SAAS,qBACP,KACA,OACiB;CACjB,IAAI,OAAO,MACT,OAAO;CAET,OAAO,SAAS,MAAM,GAAG,OAAO,IAAI,GAAG,OAAO,GAAG;AACnD;AAEA,SAAS,kBAAkB,UAAkC;CAC3D,MAAM,WAA0B,CAAC;CACjC,MAAM,eAAe,gBAAgB,QAAQ;CAE7C,KAAK,IAAI,QAAQ,GAAG,QAAQ,aAAa,QAAQ,SAAS,GAAG;EAC3D,MAAM,QAAQ,aAAa;EAC3B,IAAI,SAAS,QAAQ,UAAU,OAC7B;EAGF,IACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACT,MAAqB,SAAS,OAC/B;GACA,MAAM,UAAU;GAChB,MAAM,QAAS,QAAQ,SAAS,CAAC;GACjC,MAAM,MAAM,qBAAqB,QAAQ,KAAK,KAAK;GACnD,MAAM,SACJ,OAAO,MAAM,aAAa,mBAEpB,uBACG,MAAM,SAAiC,CAC1C,UACI,uBAAuB,MAAM,QAAQ;GACjD,SAAS,KAAK;IACZ;IACA;IACA,MAAM,MAAM;GACd,CAAC;GACD;EACF;EAEA,IAAI,yBAAyB,GAC3B,MAAM,IAAI,MAAM,8CAA8C;CAElE;CAEA,OAAO;AACT;AAEA,SAAS,cAAc,OAA8B;CACnD,MAAM,UAAU,kBAAkB,MAAM,QAAQ;CAChD,MAAM,WAAW,2BAA2B,MAAM,QAAQ;CAK1D,MAAM,YAHqB,MACzB,gBAAgB,SAAS,QAAQ,CAEjB,EAAmB;CAErC,UAAU,UAAU;CACpB,UAAU,WAAW;CAErB,OAAO;EACL,MAAM;EACN,eAAe;CACjB;AACF;AAEA,MAAa,OAAO,0BAClB,aACF"}
1
+ {"version":3,"file":"case.js","names":[],"sources":["../../src/control/case.ts"],"sourcesContent":["import {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { VNode } from '../common/vnode';\nimport { isDevelopmentEnvironment } from '../common/env';\nimport {\n createCaseState,\n type CaseState,\n type MatchBranch,\n} from '../runtime/control';\nimport { state } from '../runtime/state';\nimport { type BoundaryChild, normalizeBoundaryChild } from './shared';\n\ntype MatchChild = BoundaryChild | (() => BoundaryChild);\n\nexport type MatchProps = {\n key?: string | number | null;\n when: unknown;\n children: MatchChild;\n};\n\nexport type CaseProps = {\n fallback?: BoundaryChild;\n children?: unknown;\n};\n\nfunction flattenChildren(children: unknown): unknown[] {\n if (!Array.isArray(children)) {\n return children == null || children === false ? [] : [children];\n }\n\n const result: unknown[] = [];\n for (const child of children) {\n if (Array.isArray(child)) {\n result.push(...flattenChildren(child));\n continue;\n }\n result.push(child);\n }\n return result;\n}\n\nexport function Match(_props: MatchProps): null {\n if (isDevelopmentEnvironment()) {\n throw new Error(\n '[askr] <Match> may only be used as a direct child of <Case>.'\n );\n }\n return null;\n}\n\nfunction createCaseFallbackRenderer(\n fallback: BoundaryChild | undefined\n): (() => VNode) | null {\n const normalizedFallback = normalizeBoundaryChild(fallback);\n if (normalizedFallback == null || normalizedFallback === false) {\n return null;\n }\n return () => normalizedFallback;\n}\n\nfunction createMatchBranchKey(\n key: string | number | null | undefined,\n index: number\n): string | number {\n if (key == null) {\n return index;\n }\n return `match:${index}:${typeof key}:${String(key)}`;\n}\n\nfunction readMatchBranches(children: unknown): MatchBranch[] {\n const branches: MatchBranch[] = [];\n const flatChildren = flattenChildren(children);\n\n for (let index = 0; index < flatChildren.length; index += 1) {\n const child = flatChildren[index];\n if (child == null || child === false) {\n continue;\n }\n\n if (\n typeof child === 'object' &&\n child !== null &&\n 'type' in child &&\n (child as JSXElement).type === Match\n ) {\n const element = child as JSXElement;\n const props = (element.props ?? {}) as MatchProps;\n const key = createMatchBranchKey(element.key, index);\n const render =\n typeof props.children === 'function'\n ? () =>\n normalizeBoundaryChild(\n (props.children as () => BoundaryChild)()\n ) as VNode\n : () => normalizeBoundaryChild(props.children) as VNode;\n branches.push({\n key,\n render,\n when: props.when,\n });\n continue;\n }\n\n if (isDevelopmentEnvironment()) {\n throw new Error('[askr] <Case> only accepts <Match> children.');\n }\n }\n\n return branches;\n}\n\nfunction CasePrimitive(props: CaseProps): JSXElement {\n const matches = readMatchBranches(props.children);\n const fallback = createCaseFallbackRenderer(props.fallback);\n\n const caseStateContainer = state<CaseState>(\n createCaseState(matches, fallback)\n );\n const caseState = caseStateContainer();\n\n caseState.matches = matches;\n caseState.fallback = fallback;\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: caseState,\n } as unknown as JSXElement;\n}\n\nexport const Case = markEagerControlPrimitive(\n CasePrimitive as (props: CaseProps) => JSXElement\n) as (props: CaseProps) => JSXElement;\n"],"mappings":";;;;;;AA4BA,SAAS,gBAAgB,UAA8B;CACrD,IAAI,CAAC,MAAM,QAAQ,QAAQ,GACzB,OAAO,YAAY,QAAQ,aAAa,QAAQ,CAAC,IAAI,CAAC,QAAQ;CAGhE,MAAM,SAAoB,CAAC;CAC3B,KAAK,MAAM,SAAS,UAAU;EAC5B,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,OAAO,KAAK,GAAG,gBAAgB,KAAK,CAAC;GACrC;EACF;EACA,OAAO,KAAK,KAAK;CACnB;CACA,OAAO;AACT;AAEA,SAAgB,MAAM,QAA0B;CAC9C,IAAI,yBAAyB,GAC3B,MAAM,IAAI,MACR,8DACF;CAEF,OAAO;AACT;AAEA,SAAS,2BACP,UACsB;CACtB,MAAM,qBAAqB,uBAAuB,QAAQ;CAC1D,IAAI,sBAAsB,QAAQ,uBAAuB,OACvD,OAAO;CAET,aAAa;AACf;AAEA,SAAS,qBACP,KACA,OACiB;CACjB,IAAI,OAAO,MACT,OAAO;CAET,OAAO,SAAS,MAAM,GAAG,OAAO,IAAI,GAAG,OAAO,GAAG;AACnD;AAEA,SAAS,kBAAkB,UAAkC;CAC3D,MAAM,WAA0B,CAAC;CACjC,MAAM,eAAe,gBAAgB,QAAQ;CAE7C,KAAK,IAAI,QAAQ,GAAG,QAAQ,aAAa,QAAQ,SAAS,GAAG;EAC3D,MAAM,QAAQ,aAAa;EAC3B,IAAI,SAAS,QAAQ,UAAU,OAC7B;EAGF,IACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACT,MAAqB,SAAS,OAC/B;GACA,MAAM,UAAU;GAChB,MAAM,QAAS,QAAQ,SAAS,CAAC;GACjC,MAAM,MAAM,qBAAqB,QAAQ,KAAK,KAAK;GACnD,MAAM,SACJ,OAAO,MAAM,aAAa,mBAEpB,uBACG,MAAM,SAAiC,CAC1C,UACI,uBAAuB,MAAM,QAAQ;GACjD,SAAS,KAAK;IACZ;IACA;IACA,MAAM,MAAM;GACd,CAAC;GACD;EACF;EAEA,IAAI,yBAAyB,GAC3B,MAAM,IAAI,MAAM,8CAA8C;CAElE;CAEA,OAAO;AACT;AAEA,SAAS,cAAc,OAA8B;CACnD,MAAM,UAAU,kBAAkB,MAAM,QAAQ;CAChD,MAAM,WAAW,2BAA2B,MAAM,QAAQ;CAK1D,MAAM,YAHqB,MACzB,gBAAgB,SAAS,QAAQ,CAEjB,CAAA,CAAmB;CAErC,UAAU,UAAU;CACpB,UAAU,WAAW;CAErB,OAAO;EACL,MAAM;EACN,eAAe;CACjB;AACF;AAEA,MAAa,OAAO,0BAClB,aACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"show.js","names":[],"sources":["../../src/control/show.ts"],"sourcesContent":["import {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { VNode } from '../common/vnode';\nimport { createShowState, type ShowState } from '../runtime/control';\nimport { state } from '../runtime/state';\nimport {\n type BoundaryChild,\n normalizeBoundaryChild,\n resolveMaybeAccessor,\n} from './shared';\n\ntype ShowSource<T> = T | (() => T);\ntype Truthy<T> = T extends false | '' | 0 | 0n | null | undefined ? never : T;\n\nexport type ShowProps<T> = {\n when: ShowSource<T>;\n fallback?: BoundaryChild;\n children: BoundaryChild | ((value: Truthy<T>) => BoundaryChild);\n};\n\nfunction createTruthyRenderer<T>(\n props: ShowProps<T>\n): ShowState['renderTruthy'] {\n if (typeof props.children === 'function') {\n return (value: unknown) =>\n normalizeBoundaryChild(\n (props.children as (resolved: Truthy<T>) => VNode)(value as Truthy<T>)\n ) as VNode;\n }\n\n const staticChild = normalizeBoundaryChild(props.children);\n return () => staticChild as VNode;\n}\n\nfunction createFallbackRenderer(\n fallback: BoundaryChild | undefined\n): (() => VNode) | null {\n const normalizedFallback = normalizeBoundaryChild(fallback);\n if (normalizedFallback == null || normalizedFallback === false) {\n return null;\n }\n return () => normalizedFallback;\n}\n\nfunction ShowPrimitive<T>(props: ShowProps<T>): JSXElement {\n const selectedValue = resolveMaybeAccessor(props.when);\n const renderTruthy = createTruthyRenderer(props);\n const renderFallback = createFallbackRenderer(props.fallback);\n\n const showStateContainer = state<ShowState>(\n createShowState(selectedValue, renderTruthy, renderFallback)\n );\n const showState = showStateContainer();\n\n showState.selectedValue = selectedValue;\n showState.renderTruthy = renderTruthy;\n showState.renderFallback = renderFallback;\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: showState,\n } as unknown as JSXElement;\n}\n\nexport const Show = markEagerControlPrimitive(\n ShowPrimitive as <T>(props: ShowProps<T>) => JSXElement\n) as <T>(props: ShowProps<T>) => JSXElement;\n"],"mappings":";;;;;AAuBA,SAAS,qBACP,OAC2B;CAC3B,IAAI,OAAO,MAAM,aAAa,YAC5B,QAAQ,UACN,uBACG,MAAM,SAA4C,KAAkB,CACvE;CAGJ,MAAM,cAAc,uBAAuB,MAAM,QAAQ;CACzD,aAAa;AACf;AAEA,SAAS,uBACP,UACsB;CACtB,MAAM,qBAAqB,uBAAuB,QAAQ;CAC1D,IAAI,sBAAsB,QAAQ,uBAAuB,OACvD,OAAO;CAET,aAAa;AACf;AAEA,SAAS,cAAiB,OAAiC;CACzD,MAAM,gBAAgB,qBAAqB,MAAM,IAAI;CACrD,MAAM,eAAe,qBAAqB,KAAK;CAC/C,MAAM,iBAAiB,uBAAuB,MAAM,QAAQ;CAK5D,MAAM,YAHqB,MACzB,gBAAgB,eAAe,cAAc,cAAc,CAE3C,EAAmB;CAErC,UAAU,gBAAgB;CAC1B,UAAU,eAAe;CACzB,UAAU,iBAAiB;CAE3B,OAAO;EACL,MAAM;EACN,eAAe;CACjB;AACF;AAEA,MAAa,OAAO,0BAClB,aACF"}
1
+ {"version":3,"file":"show.js","names":[],"sources":["../../src/control/show.ts"],"sourcesContent":["import {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { VNode } from '../common/vnode';\nimport { createShowState, type ShowState } from '../runtime/control';\nimport { state } from '../runtime/state';\nimport {\n type BoundaryChild,\n normalizeBoundaryChild,\n resolveMaybeAccessor,\n} from './shared';\n\ntype ShowSource<T> = T | (() => T);\ntype Truthy<T> = T extends false | '' | 0 | 0n | null | undefined ? never : T;\n\nexport type ShowProps<T> = {\n when: ShowSource<T>;\n fallback?: BoundaryChild;\n children: BoundaryChild | ((value: Truthy<T>) => BoundaryChild);\n};\n\nfunction createTruthyRenderer<T>(\n props: ShowProps<T>\n): ShowState['renderTruthy'] {\n if (typeof props.children === 'function') {\n return (value: unknown) =>\n normalizeBoundaryChild(\n (props.children as (resolved: Truthy<T>) => VNode)(value as Truthy<T>)\n ) as VNode;\n }\n\n const staticChild = normalizeBoundaryChild(props.children);\n return () => staticChild as VNode;\n}\n\nfunction createFallbackRenderer(\n fallback: BoundaryChild | undefined\n): (() => VNode) | null {\n const normalizedFallback = normalizeBoundaryChild(fallback);\n if (normalizedFallback == null || normalizedFallback === false) {\n return null;\n }\n return () => normalizedFallback;\n}\n\nfunction ShowPrimitive<T>(props: ShowProps<T>): JSXElement {\n const selectedValue = resolveMaybeAccessor(props.when);\n const renderTruthy = createTruthyRenderer(props);\n const renderFallback = createFallbackRenderer(props.fallback);\n\n const showStateContainer = state<ShowState>(\n createShowState(selectedValue, renderTruthy, renderFallback)\n );\n const showState = showStateContainer();\n\n showState.selectedValue = selectedValue;\n showState.renderTruthy = renderTruthy;\n showState.renderFallback = renderFallback;\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: showState,\n } as unknown as JSXElement;\n}\n\nexport const Show = markEagerControlPrimitive(\n ShowPrimitive as <T>(props: ShowProps<T>) => JSXElement\n) as <T>(props: ShowProps<T>) => JSXElement;\n"],"mappings":";;;;;AAuBA,SAAS,qBACP,OAC2B;CAC3B,IAAI,OAAO,MAAM,aAAa,YAC5B,QAAQ,UACN,uBACG,MAAM,SAA4C,KAAkB,CACvE;CAGJ,MAAM,cAAc,uBAAuB,MAAM,QAAQ;CACzD,aAAa;AACf;AAEA,SAAS,uBACP,UACsB;CACtB,MAAM,qBAAqB,uBAAuB,QAAQ;CAC1D,IAAI,sBAAsB,QAAQ,uBAAuB,OACvD,OAAO;CAET,aAAa;AACf;AAEA,SAAS,cAAiB,OAAiC;CACzD,MAAM,gBAAgB,qBAAqB,MAAM,IAAI;CACrD,MAAM,eAAe,qBAAqB,KAAK;CAC/C,MAAM,iBAAiB,uBAAuB,MAAM,QAAQ;CAK5D,MAAM,YAHqB,MACzB,gBAAgB,eAAe,cAAc,cAAc,CAE3C,CAAA,CAAmB;CAErC,UAAU,gBAAgB;CAC1B,UAAU,eAAe;CACzB,UAAU,iBAAiB;CAE3B,OAAO;EACL,MAAM;EACN,eAAe;CACjB;AACF;AAEA,MAAa,OAAO,0BAClB,aACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/data/index.ts"],"sourcesContent":["import { globalScheduler } from '../runtime/scheduler';\nimport {\n claimHookIndex,\n getCurrentComponentInstance,\n type ComponentInstance,\n} from '../runtime/component';\nimport {\n markReadableDerivedSubscribersDirty,\n markReactivePropsDirtySource,\n notifyReadableReaders,\n recordReadableRead,\n type ReadableSource,\n} from '../runtime/readable';\nimport { getRenderContext } from '../ssr/context';\nimport { logger } from '../dev/logger';\nimport { emitInvalidation } from './invalidation-listeners';\nimport {\n documentVisible,\n routeActive,\n timer,\n windowFocused,\n type ActivityPredicate,\n} from '../runtime/operations';\n\nexport type QueryConsistency =\n | 'fresh'\n | 'stale'\n | 'refreshing'\n | 'pending-write';\n\nexport type QueryStaleReason = 'aborted' | 'error' | 'inconsistent';\n\nexport interface InvalidateOptions {\n markPendingWrite?: boolean;\n}\n\nexport interface InvalidateOnIntervalOptions extends InvalidateOptions {\n intervalMs: number;\n activeOn?: string | readonly string[];\n visibleOnly?: boolean;\n focusedOnly?: boolean;\n}\n\nexport type QueryKeyPart =\n | string\n | number\n | boolean\n | null\n | undefined\n | readonly QueryKeyPart[]\n | { readonly [key: string]: QueryKeyPart };\n\nexport interface QueryScope {\n key(...parts: QueryKeyPart[]): string;\n prefix(...parts: QueryKeyPart[]): string;\n invalidate(parts: readonly QueryKeyPart[], options?: InvalidateOptions): void;\n}\n\ntype QueryControls = {\n refresh(): Promise<void>;\n};\n\ntype QueryLoading = {\n data: null;\n error: null;\n loading: true;\n refreshing: false;\n stale: false;\n consistency: 'fresh';\n staleReason: null;\n};\n\ntype QueryFresh<T> = {\n data: T;\n error: null;\n loading: false;\n refreshing: false;\n stale: false;\n consistency: 'fresh';\n staleReason: null;\n};\n\ntype QueryRefreshing<T> = {\n data: T;\n error: null;\n loading: false;\n refreshing: true;\n stale: true;\n consistency: 'refreshing';\n staleReason: null;\n};\n\ntype QueryPendingWrite<T> = {\n data: T;\n error: null;\n loading: false;\n refreshing: true;\n stale: true;\n consistency: 'pending-write';\n staleReason: null;\n};\n\ntype QueryStaleValue<T> = {\n data: T;\n error: null;\n loading: false;\n refreshing: false;\n stale: true;\n consistency: 'stale';\n staleReason: 'aborted' | 'inconsistent';\n};\n\ntype QueryStaleErrorWithValue<T> = {\n data: T;\n error: {};\n loading: false;\n refreshing: false;\n stale: true;\n consistency: 'stale';\n staleReason: 'error';\n};\n\ntype QueryStaleError = {\n data: null;\n error: {};\n loading: false;\n refreshing: false;\n stale: true;\n consistency: 'stale';\n staleReason: 'error';\n};\n\nexport type Query<T extends {}> = QueryControls &\n (\n | QueryLoading\n | QueryFresh<T>\n | QueryRefreshing<T>\n | QueryPendingWrite<T>\n | QueryStaleValue<T>\n | QueryStaleErrorWithValue<T>\n | QueryStaleError\n );\n\ntype MutationControls<TInput, TResult> = {\n execute(input: TInput): Promise<TResult>;\n abort(): void;\n reset(): void;\n};\n\ntype MutationIdle = {\n status: 'idle';\n pending: false;\n error: null;\n result: null;\n};\n\ntype MutationPending = {\n status: 'pending';\n pending: true;\n error: null;\n result: null;\n};\n\ntype MutationSuccess<TResult> = {\n status: 'success';\n pending: false;\n error: null;\n result: TResult;\n};\n\ntype MutationError = {\n status: 'error';\n pending: false;\n error: {};\n result: null;\n};\n\nexport type Mutation<TInput, TResult> = MutationControls<TInput, TResult> &\n (MutationIdle | MutationPending | MutationSuccess<TResult> | MutationError);\n\ntype MutationRecord<TResult> = {\n status: 'idle' | 'pending' | 'success' | 'error';\n error: {} | null;\n result: TResult | null;\n};\n\ntype QueryOptions<T> = {\n key: string;\n fetch: (ctx: { signal: AbortSignal }) => Promise<T>;\n isConsistent?: (data: T) => boolean;\n reconcile?: (data: T, ctx: { key: string }) => Promise<boolean> | boolean;\n};\n\ntype MutationOptions<TInput, TResult> = {\n action: (input: TInput, ctx: { signal: AbortSignal }) => Promise<TResult>;\n affects?: (input: TInput, result: TResult) => string[];\n afterSuccess?: 'invalidate';\n};\n\ntype QueryState<T> = {\n data: T | null;\n error: {} | null;\n loading: boolean;\n refreshing: boolean;\n stale: boolean;\n consistency: QueryConsistency;\n staleReason: QueryStaleReason | null;\n};\n\ntype QuerySlot = {\n key: string;\n cell: QueryCell<unknown>;\n};\n\ntype QueryDefinitionField = 'fetch' | 'isConsistent' | 'reconcile';\n\nconst RECONCILE_MAX_ATTEMPTS = 3;\nconst RECONCILE_RETRY_DELAY_MS = 25;\nconst globalQueryCache = new Map<string, QueryCell<unknown>>();\nconst querySlotsByInstance = new WeakMap<\n ComponentInstance,\n Map<number, QuerySlot>\n>();\nconst mutationSlotsByInstance = new WeakMap<\n ComponentInstance,\n Map<number, MutationCell<unknown, unknown>>\n>();\nconst queryCleanupRegistered = new WeakSet<ComponentInstance>();\nconst mutationCleanupRegistered = new WeakSet<ComponentInstance>();\n\nfunction createReadableSource(): ReadableSource<unknown> {\n return (() => undefined) as ReadableSource<unknown>;\n}\n\nfunction getQueryCache(): Map<string, QueryCell<unknown>> {\n return (\n (getRenderContext()?.queryCache as Map<\n string,\n QueryCell<unknown>\n > | null) ?? globalQueryCache\n );\n}\n\nfunction getQuerySlotStore(\n instance: ComponentInstance\n): Map<number, QuerySlot> {\n let store = querySlotsByInstance.get(instance);\n if (!store) {\n store = new Map();\n querySlotsByInstance.set(instance, store);\n }\n return store;\n}\n\nfunction getMutationSlotStore(\n instance: ComponentInstance\n): Map<number, MutationCell<unknown, unknown>> {\n let store = mutationSlotsByInstance.get(instance);\n if (!store) {\n store = new Map();\n mutationSlotsByInstance.set(instance, store);\n }\n return store;\n}\n\nfunction ensureQueryCleanup(instance: ComponentInstance): void {\n if (queryCleanupRegistered.has(instance)) {\n return;\n }\n\n queryCleanupRegistered.add(instance);\n instance.cleanupFns.push(() => {\n const slots = querySlotsByInstance.get(instance);\n if (!slots) {\n queryCleanupRegistered.delete(instance);\n return;\n }\n\n for (const [hookIndex, slot] of slots) {\n slot.cell.detach(instance, hookIndex);\n }\n\n slots.clear();\n querySlotsByInstance.delete(instance);\n queryCleanupRegistered.delete(instance);\n });\n}\n\nfunction ensureMutationCleanup(instance: ComponentInstance): void {\n if (mutationCleanupRegistered.has(instance)) {\n return;\n }\n\n mutationCleanupRegistered.add(instance);\n instance.cleanupFns.push(() => {\n const slots = mutationSlotsByInstance.get(instance);\n if (!slots) {\n mutationCleanupRegistered.delete(instance);\n return;\n }\n\n for (const cell of slots.values()) {\n cell.abort();\n }\n\n slots.clear();\n mutationSlotsByInstance.delete(instance);\n mutationCleanupRegistered.delete(instance);\n });\n}\n\nfunction notifySource(source: ReadableSource<unknown>): void {\n markReadableDerivedSubscribersDirty(source);\n markReactivePropsDirtySource(source);\n notifyReadableReaders(source);\n}\n\nfunction isAbortError(error: unknown, signal: AbortSignal): boolean {\n return (\n signal.aborted ||\n (error instanceof Error && error.name === 'AbortError') ||\n (typeof DOMException !== 'undefined' &&\n error instanceof DOMException &&\n error.name === 'AbortError')\n );\n}\n\nfunction normalizeAsyncDataError(error: unknown, fallbackMessage: string): {} {\n return error ?? new Error(fallbackMessage);\n}\n\nfunction invalidateQueries(prefix: string, markPendingWrite: boolean): void {\n emitInvalidation({ prefix, markPendingWrite });\n\n const cache = getQueryCache();\n\n for (const [key, query] of cache) {\n if (!key.startsWith(prefix)) {\n continue;\n }\n\n if (markPendingWrite) {\n query.markPendingWrite();\n }\n\n void query.refresh();\n }\n}\n\nclass QueryCell<T> {\n private readonly source = createReadableSource();\n private readonly key: string;\n private readonly cache: Map<string, QueryCell<unknown>>;\n private options: QueryOptions<T>;\n private controller: AbortController | null = null;\n private generation = 0;\n private startQueued = false;\n private pendingRefresh: Promise<void> | null = null;\n private pendingRefreshResolve: (() => void) | null = null;\n private reconcileAttemptCount = 0;\n private destroyed = false;\n private ownerCount = 0;\n private readonly owners = new Map<ComponentInstance, Set<number>>();\n private readonly warnedDefinitionConflictKeys = new Set<string>();\n\n private state: QueryState<T> = {\n data: null,\n error: null,\n loading: true,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n staleReason: null,\n };\n\n constructor(\n options: QueryOptions<T>,\n key: string,\n cache: Map<string, QueryCell<unknown>>\n ) {\n this.options = options;\n this.key = key;\n this.cache = cache;\n }\n\n attach(instance: ComponentInstance, hookIndex: number): void {\n let hooks = this.owners.get(instance);\n if (!hooks) {\n hooks = new Set();\n this.owners.set(instance, hooks);\n }\n\n if (hooks.has(hookIndex)) {\n return;\n }\n\n hooks.add(hookIndex);\n this.ownerCount += 1;\n }\n\n detach(instance: ComponentInstance, hookIndex: number): void {\n const hooks = this.owners.get(instance);\n if (!hooks || !hooks.delete(hookIndex)) {\n return;\n }\n\n this.ownerCount -= 1;\n if (hooks.size === 0) {\n this.owners.delete(instance);\n }\n\n if (this.ownerCount <= 0) {\n this.destroy();\n }\n }\n\n warnOnConflictingDefinition(options: QueryOptions<T>): void {\n const conflicts = this.getDefinitionConflicts(options);\n if (conflicts.length === 0) {\n return;\n }\n\n const conflictKey = conflicts.join(',');\n if (this.warnedDefinitionConflictKeys.has(conflictKey)) {\n return;\n }\n\n this.warnedDefinitionConflictKeys.add(conflictKey);\n\n const callbackLabel =\n conflicts.length === 1\n ? `callback \\`${conflicts[0]}\\``\n : `callbacks ${conflicts.map((field) => `\\`${field}\\``).join(', ')}`;\n\n logger.warn(\n `[askr] Conflicting shared query definition for key \"${this.key}\". ` +\n `Shared queries are canonical by key, so reuse the same ${callbackLabel} ` +\n 'for every reader of that key.'\n );\n }\n\n private destroy(): void {\n if (this.destroyed) {\n return;\n }\n\n this.destroyed = true;\n this.controller?.abort();\n this.controller = null;\n this.startQueued = false;\n this.reconcileAttemptCount = 0;\n this.ownerCount = 0;\n this.owners.clear();\n this.cache.delete(this.key);\n this.finishPendingRefresh();\n }\n\n private getDefinitionConflicts(\n options: QueryOptions<T>\n ): QueryDefinitionField[] {\n const conflicts: QueryDefinitionField[] = [];\n\n if (this.options.fetch !== options.fetch) {\n conflicts.push('fetch');\n }\n\n if (this.options.isConsistent !== options.isConsistent) {\n conflicts.push('isConsistent');\n }\n\n if (this.options.reconcile !== options.reconcile) {\n conflicts.push('reconcile');\n }\n\n return conflicts;\n }\n\n get data(): T | null {\n recordReadableRead(this.source);\n return this.state.data;\n }\n\n get error(): {} | null {\n recordReadableRead(this.source);\n return this.state.error;\n }\n\n get loading(): boolean {\n recordReadableRead(this.source);\n return this.state.loading;\n }\n\n get refreshing(): boolean {\n recordReadableRead(this.source);\n return this.state.refreshing;\n }\n\n get stale(): boolean {\n recordReadableRead(this.source);\n return this.state.stale;\n }\n\n get consistency(): QueryConsistency {\n recordReadableRead(this.source);\n return this.state.consistency;\n }\n\n get staleReason(): QueryStaleReason | null {\n recordReadableRead(this.source);\n return this.state.staleReason;\n }\n\n ensureStarted(): void {\n if (\n this.destroyed ||\n this.state.data !== null ||\n this.pendingRefresh ||\n this.startQueued\n ) {\n return;\n }\n\n this.queueStart('initial');\n }\n\n refresh(): Promise<void> {\n if (this.destroyed) {\n return Promise.resolve();\n }\n\n if (this.pendingRefresh) {\n return this.pendingRefresh;\n }\n\n this.queueStart('manual');\n return this.pendingRefresh ?? Promise.resolve();\n }\n\n markPendingWrite(): void {\n if (this.destroyed) {\n return;\n }\n\n if (this.state.data === null) {\n return;\n }\n\n this.setState({\n loading: false,\n error: null,\n refreshing: true,\n stale: true,\n consistency: 'pending-write',\n staleReason: null,\n });\n }\n\n private queueStart(\n reason: 'initial' | 'manual' | 'invalidate' | 'pending-write'\n ): void {\n if (this.destroyed) {\n return;\n }\n\n this.startQueued = true;\n this.pendingRefresh = new Promise<void>((resolve) => {\n this.pendingRefreshResolve = resolve;\n globalScheduler.enqueue(() => {\n this.startQueued = false;\n if (this.destroyed) {\n this.finishPendingRefresh();\n return;\n }\n void this.start(reason).finally(() => {\n this.finishPendingRefresh();\n });\n });\n });\n }\n\n private finishPendingRefresh(): void {\n const resolve = this.pendingRefreshResolve;\n this.pendingRefresh = null;\n this.pendingRefreshResolve = null;\n resolve?.();\n }\n\n private setState(next: Partial<QueryState<T>>): void {\n if (this.destroyed) {\n return;\n }\n\n this.state = {\n ...this.state,\n ...next,\n };\n notifySource(this.source);\n }\n\n private async start(\n reason: 'initial' | 'manual' | 'invalidate' | 'pending-write'\n ): Promise<void> {\n if (this.destroyed) {\n return;\n }\n\n this.generation += 1;\n const generation = this.generation;\n\n this.controller?.abort();\n const controller = new AbortController();\n this.controller = controller;\n\n const hasData = this.state.data !== null;\n this.setState({\n loading: !hasData,\n refreshing: hasData,\n stale: hasData,\n consistency:\n reason === 'pending-write'\n ? 'pending-write'\n : hasData\n ? 'refreshing'\n : 'fresh',\n error: null,\n staleReason: null,\n });\n\n let nextData: T;\n try {\n nextData = await this.options.fetch({ signal: controller.signal });\n } catch (error) {\n if (\n this.destroyed ||\n this.generation !== generation ||\n this.controller !== controller\n ) {\n return;\n }\n\n if (isAbortError(error, controller.signal)) {\n this.setState(\n hasData\n ? {\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n error: null,\n staleReason: 'aborted',\n }\n : {\n loading: true,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n error: null,\n staleReason: null,\n }\n );\n return;\n }\n\n this.setState({\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n error: normalizeAsyncDataError(error, 'Unknown query error'),\n staleReason: 'error',\n });\n return;\n }\n\n if (\n this.destroyed ||\n this.generation !== generation ||\n this.controller !== controller\n ) {\n return;\n }\n\n const isConsistent = this.options.isConsistent?.(nextData) ?? true;\n if (!isConsistent) {\n this.setState({\n data: nextData,\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n staleReason: 'inconsistent',\n });\n await this.reconcile(nextData);\n return;\n }\n\n this.reconcileAttemptCount = 0;\n this.setState({\n data: nextData,\n loading: false,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n error: null,\n staleReason: null,\n });\n }\n\n private async reconcile(data: T): Promise<void> {\n const shouldRetry =\n this.options.reconcile?.(data, { key: this.options.key }) ?? false;\n\n if (!shouldRetry || this.destroyed) {\n return;\n }\n\n this.reconcileAttemptCount += 1;\n if (this.reconcileAttemptCount > RECONCILE_MAX_ATTEMPTS) {\n this.setState({\n consistency: 'stale',\n refreshing: false,\n staleReason: 'inconsistent',\n });\n return;\n }\n\n await new Promise<void>((resolve) =>\n setTimeout(resolve, RECONCILE_RETRY_DELAY_MS)\n );\n if (this.destroyed || this.state.consistency === 'fresh') {\n return;\n }\n\n await this.refresh();\n }\n}\n\nclass MutationCell<TInput, TResult> {\n private readonly source = createReadableSource();\n private action: MutationOptions<TInput, TResult>['action'];\n private affects?: MutationOptions<TInput, TResult>['affects'];\n private afterSuccess?: MutationOptions<TInput, TResult>['afterSuccess'];\n private controller: AbortController | null = null;\n private generation = 0;\n\n private state: MutationRecord<TResult> = {\n status: 'idle',\n error: null,\n result: null,\n };\n\n constructor(options: MutationOptions<TInput, TResult>) {\n this.action = options.action;\n this.affects = options.affects;\n this.afterSuccess = options.afterSuccess;\n }\n\n setOptions(options: MutationOptions<TInput, TResult>): void {\n this.action = options.action;\n this.affects = options.affects;\n this.afterSuccess = options.afterSuccess;\n }\n\n get status(): 'idle' | 'pending' | 'success' | 'error' {\n recordReadableRead(this.source);\n return this.state.status;\n }\n\n get pending(): boolean {\n recordReadableRead(this.source);\n return this.state.status === 'pending';\n }\n\n get error(): {} | null {\n recordReadableRead(this.source);\n return this.state.error;\n }\n\n get result(): TResult | null {\n recordReadableRead(this.source);\n return this.state.result;\n }\n\n private setState(next: Partial<MutationRecord<TResult>>): void {\n this.state = {\n ...this.state,\n ...next,\n };\n notifySource(this.source);\n }\n\n async execute(input: TInput): Promise<TResult> {\n this.generation += 1;\n const generation = this.generation;\n\n this.controller?.abort();\n const controller = new AbortController();\n this.controller = controller;\n\n this.setState({ status: 'pending', error: null, result: null });\n\n let result: TResult;\n try {\n result = await this.action(input, { signal: controller.signal });\n } catch (error) {\n if (this.generation !== generation || this.controller !== controller) {\n throw error;\n }\n\n if (isAbortError(error, controller.signal)) {\n this.setState({ status: 'idle', error: null });\n throw error;\n }\n\n this.setState({\n status: 'error',\n error: normalizeAsyncDataError(error, 'Unknown mutation error'),\n });\n throw error;\n }\n\n if (this.generation !== generation || this.controller !== controller) {\n return result;\n }\n\n this.setState({ status: 'success', error: null, result });\n\n if (this.afterSuccess === 'invalidate') {\n const prefixes = this.affects?.(input, result) ?? [];\n for (const prefix of new Set(prefixes)) {\n invalidateQueries(prefix, true);\n }\n }\n\n return result;\n }\n\n abort(): void {\n if (this.state.status !== 'pending') {\n return;\n }\n\n this.generation += 1;\n this.controller?.abort();\n this.controller = null;\n this.setState({ status: 'idle', error: null, result: null });\n }\n\n reset(): void {\n this.generation += 1;\n this.controller?.abort();\n this.controller = null;\n this.setState({ status: 'idle', error: null, result: null });\n }\n}\n\nexport function createQuery<T extends {}>(options: QueryOptions<T>): Query<T> {\n const instance = getCurrentComponentInstance();\n const cache = getQueryCache();\n if (!instance) {\n let cell = cache.get(options.key) as QueryCell<T> | undefined;\n if (!cell) {\n cell = new QueryCell(options, options.key, cache);\n cache.set(options.key, cell as QueryCell<unknown>);\n cell.ensureStarted();\n } else {\n cell.warnOnConflictingDefinition(options);\n }\n return cell as unknown as Query<T>;\n }\n\n const hookIndex = claimHookIndex(instance, 'query');\n ensureQueryCleanup(instance);\n\n const slotStore = getQuerySlotStore(instance);\n const existingSlot = slotStore.get(hookIndex);\n if (existingSlot && existingSlot.key === options.key) {\n (existingSlot.cell as QueryCell<T>).warnOnConflictingDefinition(options);\n return existingSlot.cell as unknown as Query<T>;\n }\n\n if (existingSlot) {\n existingSlot.cell.detach(instance, hookIndex);\n }\n\n let cell = cache.get(options.key) as QueryCell<T> | undefined;\n if (!cell) {\n cell = new QueryCell(options, options.key, cache);\n cache.set(options.key, cell as QueryCell<unknown>);\n cell.ensureStarted();\n } else {\n cell.warnOnConflictingDefinition(options);\n }\n\n slotStore.set(hookIndex, {\n key: options.key,\n cell: cell as QueryCell<unknown>,\n });\n cell.attach(instance, hookIndex);\n return cell as unknown as Query<T>;\n}\n\nexport function invalidate(prefix: string, options?: InvalidateOptions): void {\n invalidateQueries(prefix, options?.markPendingWrite ?? false);\n}\n\nfunction serializeQueryKeyNumber(part: number): string {\n if (Number.isNaN(part)) {\n return 'NaN';\n }\n\n if (Object.is(part, -0)) {\n return '-0';\n }\n\n if (part === Infinity) {\n return 'Infinity';\n }\n\n if (part === -Infinity) {\n return '-Infinity';\n }\n\n return String(part);\n}\n\nfunction serializeQueryKeyPart(part: QueryKeyPart): string {\n if (typeof (part as unknown) === 'symbol') {\n throw new Error('[Askr] queryScope() key parts cannot be symbols.');\n }\n\n if (part === null) {\n return 'null';\n }\n\n if (part === undefined) {\n return 'undefined';\n }\n\n switch (typeof part) {\n case 'string':\n return `s=${encodeURIComponent(part)}`;\n case 'number':\n return `n=${serializeQueryKeyNumber(part)}`;\n case 'boolean':\n return `b=${part ? '1' : '0'}`;\n case 'object':\n if (Array.isArray(part)) {\n return `a[${part.map((item) => serializeQueryKeyPart(item)).join(',')}]`;\n }\n\n return `o{${Object.keys(part)\n .sort()\n .map(\n (key) =>\n `${encodeURIComponent(key)}=${serializeQueryKeyPart(part[key])}`\n )\n .join(',')}}`;\n default:\n return String(part);\n }\n}\n\nexport function queryScope(namespace: string): QueryScope {\n if (typeof namespace !== 'string' || namespace.trim().length === 0) {\n throw new Error(\n '[Askr] queryScope() requires a non-empty namespace string.'\n );\n }\n\n const build = (parts: readonly QueryKeyPart[]): string =>\n [namespace, ...parts].map(serializeQueryKeyPart).join(':') + ':';\n\n return {\n key(...parts) {\n return build(parts);\n },\n\n prefix(...parts) {\n return build(parts);\n },\n\n invalidate(parts, options) {\n invalidate(build(parts), options);\n },\n };\n}\n\nconst INVALIDATE_ON_INTERVAL_OPTIONS_ERROR =\n '[Askr] invalidateOnInterval() requires an options object with a finite numeric intervalMs.';\n\nexport function invalidateOnInterval(\n prefix: string,\n options: InvalidateOnIntervalOptions\n): void {\n if (\n !options ||\n typeof options !== 'object' ||\n typeof options.intervalMs !== 'number' ||\n !Number.isFinite(options.intervalMs)\n ) {\n throw new Error(INVALIDATE_ON_INTERVAL_OPTIONS_ERROR);\n }\n\n const when: ActivityPredicate[] = [];\n\n if (options.activeOn) {\n when.push(routeActive(options.activeOn));\n }\n\n if (options.visibleOnly) {\n when.push(documentVisible());\n }\n\n if (options.focusedOnly) {\n when.push(windowFocused());\n }\n\n timer(\n options.intervalMs,\n () => {\n invalidate(prefix, {\n markPendingWrite: options.markPendingWrite,\n });\n },\n when.length > 0 ? { when } : undefined\n );\n}\n\nexport function createMutation<TInput, TResult>(\n options: MutationOptions<TInput, TResult>\n): Mutation<TInput, TResult> {\n const instance = getCurrentComponentInstance();\n\n if (!instance) {\n return new MutationCell(options) as unknown as Mutation<TInput, TResult>;\n }\n\n const hookIndex = claimHookIndex(instance, 'mutation');\n ensureMutationCleanup(instance);\n\n const slotStore = getMutationSlotStore(instance);\n const existing = slotStore.get(hookIndex) as\n | MutationCell<TInput, TResult>\n | undefined;\n if (existing) {\n existing.setOptions(options);\n return existing as unknown as Mutation<TInput, TResult>;\n }\n\n const created = new MutationCell(options);\n slotStore.set(hookIndex, created as MutationCell<unknown, unknown>);\n return created as unknown as Mutation<TInput, TResult>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/data/index.ts"],"sourcesContent":["import { globalScheduler } from '../runtime/scheduler';\nimport {\n claimHookIndex,\n getCurrentComponentInstance,\n type ComponentInstance,\n} from '../runtime/component';\nimport {\n markReadableDerivedSubscribersDirty,\n markReactivePropsDirtySource,\n notifyReadableReaders,\n recordReadableRead,\n type ReadableSource,\n} from '../runtime/readable';\nimport { getRenderContext } from '../ssr/context';\nimport { logger } from '../dev/logger';\nimport { emitInvalidation } from './invalidation-listeners';\nimport {\n documentVisible,\n routeActive,\n timer,\n windowFocused,\n type ActivityPredicate,\n} from '../runtime/operations';\n\nexport type QueryConsistency =\n | 'fresh'\n | 'stale'\n | 'refreshing'\n | 'pending-write';\n\nexport type QueryStaleReason = 'aborted' | 'error' | 'inconsistent';\n\nexport interface InvalidateOptions {\n markPendingWrite?: boolean;\n}\n\nexport interface InvalidateOnIntervalOptions extends InvalidateOptions {\n intervalMs: number;\n activeOn?: string | readonly string[];\n visibleOnly?: boolean;\n focusedOnly?: boolean;\n}\n\nexport type QueryKeyPart =\n | string\n | number\n | boolean\n | null\n | undefined\n | readonly QueryKeyPart[]\n | { readonly [key: string]: QueryKeyPart };\n\nexport interface QueryScope {\n key(...parts: QueryKeyPart[]): string;\n prefix(...parts: QueryKeyPart[]): string;\n invalidate(parts: readonly QueryKeyPart[], options?: InvalidateOptions): void;\n}\n\ntype QueryControls = {\n refresh(): Promise<void>;\n};\n\ntype QueryLoading = {\n data: null;\n error: null;\n loading: true;\n refreshing: false;\n stale: false;\n consistency: 'fresh';\n staleReason: null;\n};\n\ntype QueryFresh<T> = {\n data: T;\n error: null;\n loading: false;\n refreshing: false;\n stale: false;\n consistency: 'fresh';\n staleReason: null;\n};\n\ntype QueryRefreshing<T> = {\n data: T;\n error: null;\n loading: false;\n refreshing: true;\n stale: true;\n consistency: 'refreshing';\n staleReason: null;\n};\n\ntype QueryPendingWrite<T> = {\n data: T;\n error: null;\n loading: false;\n refreshing: true;\n stale: true;\n consistency: 'pending-write';\n staleReason: null;\n};\n\ntype QueryStaleValue<T> = {\n data: T;\n error: null;\n loading: false;\n refreshing: false;\n stale: true;\n consistency: 'stale';\n staleReason: 'aborted' | 'inconsistent';\n};\n\ntype QueryStaleErrorWithValue<T> = {\n data: T;\n error: {};\n loading: false;\n refreshing: false;\n stale: true;\n consistency: 'stale';\n staleReason: 'error';\n};\n\ntype QueryStaleError = {\n data: null;\n error: {};\n loading: false;\n refreshing: false;\n stale: true;\n consistency: 'stale';\n staleReason: 'error';\n};\n\nexport type Query<T extends {}> = QueryControls &\n (\n | QueryLoading\n | QueryFresh<T>\n | QueryRefreshing<T>\n | QueryPendingWrite<T>\n | QueryStaleValue<T>\n | QueryStaleErrorWithValue<T>\n | QueryStaleError\n );\n\ntype MutationControls<TInput, TResult> = {\n execute(input: TInput): Promise<TResult>;\n abort(): void;\n reset(): void;\n};\n\ntype MutationIdle = {\n status: 'idle';\n pending: false;\n error: null;\n result: null;\n};\n\ntype MutationPending = {\n status: 'pending';\n pending: true;\n error: null;\n result: null;\n};\n\ntype MutationSuccess<TResult> = {\n status: 'success';\n pending: false;\n error: null;\n result: TResult;\n};\n\ntype MutationError = {\n status: 'error';\n pending: false;\n error: {};\n result: null;\n};\n\nexport type Mutation<TInput, TResult> = MutationControls<TInput, TResult> &\n (MutationIdle | MutationPending | MutationSuccess<TResult> | MutationError);\n\ntype MutationRecord<TResult> = {\n status: 'idle' | 'pending' | 'success' | 'error';\n error: {} | null;\n result: TResult | null;\n};\n\ntype QueryOptions<T> = {\n key: string;\n fetch: (ctx: { signal: AbortSignal }) => Promise<T>;\n isConsistent?: (data: T) => boolean;\n reconcile?: (data: T, ctx: { key: string }) => Promise<boolean> | boolean;\n};\n\ntype MutationOptions<TInput, TResult> = {\n action: (input: TInput, ctx: { signal: AbortSignal }) => Promise<TResult>;\n affects?: (input: TInput, result: TResult) => string[];\n afterSuccess?: 'invalidate';\n};\n\ntype QueryState<T> = {\n data: T | null;\n error: {} | null;\n loading: boolean;\n refreshing: boolean;\n stale: boolean;\n consistency: QueryConsistency;\n staleReason: QueryStaleReason | null;\n};\n\ntype QuerySlot = {\n key: string;\n cell: QueryCell<unknown>;\n};\n\ntype QueryDefinitionField = 'fetch' | 'isConsistent' | 'reconcile';\n\nconst RECONCILE_MAX_ATTEMPTS = 3;\nconst RECONCILE_RETRY_DELAY_MS = 25;\nconst globalQueryCache = new Map<string, QueryCell<unknown>>();\nconst querySlotsByInstance = new WeakMap<\n ComponentInstance,\n Map<number, QuerySlot>\n>();\nconst mutationSlotsByInstance = new WeakMap<\n ComponentInstance,\n Map<number, MutationCell<unknown, unknown>>\n>();\nconst queryCleanupRegistered = new WeakSet<ComponentInstance>();\nconst mutationCleanupRegistered = new WeakSet<ComponentInstance>();\n\nfunction createReadableSource(): ReadableSource<unknown> {\n return (() => undefined) as ReadableSource<unknown>;\n}\n\nfunction getQueryCache(): Map<string, QueryCell<unknown>> {\n return (\n (getRenderContext()?.queryCache as Map<\n string,\n QueryCell<unknown>\n > | null) ?? globalQueryCache\n );\n}\n\nfunction getQuerySlotStore(\n instance: ComponentInstance\n): Map<number, QuerySlot> {\n let store = querySlotsByInstance.get(instance);\n if (!store) {\n store = new Map();\n querySlotsByInstance.set(instance, store);\n }\n return store;\n}\n\nfunction getMutationSlotStore(\n instance: ComponentInstance\n): Map<number, MutationCell<unknown, unknown>> {\n let store = mutationSlotsByInstance.get(instance);\n if (!store) {\n store = new Map();\n mutationSlotsByInstance.set(instance, store);\n }\n return store;\n}\n\nfunction ensureQueryCleanup(instance: ComponentInstance): void {\n if (queryCleanupRegistered.has(instance)) {\n return;\n }\n\n queryCleanupRegistered.add(instance);\n instance.cleanupFns.push(() => {\n const slots = querySlotsByInstance.get(instance);\n if (!slots) {\n queryCleanupRegistered.delete(instance);\n return;\n }\n\n for (const [hookIndex, slot] of slots) {\n slot.cell.detach(instance, hookIndex);\n }\n\n slots.clear();\n querySlotsByInstance.delete(instance);\n queryCleanupRegistered.delete(instance);\n });\n}\n\nfunction ensureMutationCleanup(instance: ComponentInstance): void {\n if (mutationCleanupRegistered.has(instance)) {\n return;\n }\n\n mutationCleanupRegistered.add(instance);\n instance.cleanupFns.push(() => {\n const slots = mutationSlotsByInstance.get(instance);\n if (!slots) {\n mutationCleanupRegistered.delete(instance);\n return;\n }\n\n for (const cell of slots.values()) {\n cell.abort();\n }\n\n slots.clear();\n mutationSlotsByInstance.delete(instance);\n mutationCleanupRegistered.delete(instance);\n });\n}\n\nfunction notifySource(source: ReadableSource<unknown>): void {\n markReadableDerivedSubscribersDirty(source);\n markReactivePropsDirtySource(source);\n notifyReadableReaders(source);\n}\n\nfunction isAbortError(error: unknown, signal: AbortSignal): boolean {\n return (\n signal.aborted ||\n (error instanceof Error && error.name === 'AbortError') ||\n (typeof DOMException !== 'undefined' &&\n error instanceof DOMException &&\n error.name === 'AbortError')\n );\n}\n\nfunction normalizeAsyncDataError(error: unknown, fallbackMessage: string): {} {\n return error ?? new Error(fallbackMessage);\n}\n\nfunction invalidateQueries(prefix: string, markPendingWrite: boolean): void {\n emitInvalidation({ prefix, markPendingWrite });\n\n const cache = getQueryCache();\n\n for (const [key, query] of cache) {\n if (!key.startsWith(prefix)) {\n continue;\n }\n\n if (markPendingWrite) {\n query.markPendingWrite();\n }\n\n void query.refresh();\n }\n}\n\nclass QueryCell<T> {\n private readonly source = createReadableSource();\n private readonly key: string;\n private readonly cache: Map<string, QueryCell<unknown>>;\n private options: QueryOptions<T>;\n private controller: AbortController | null = null;\n private generation = 0;\n private startQueued = false;\n private pendingRefresh: Promise<void> | null = null;\n private pendingRefreshResolve: (() => void) | null = null;\n private reconcileAttemptCount = 0;\n private destroyed = false;\n private ownerCount = 0;\n private readonly owners = new Map<ComponentInstance, Set<number>>();\n private readonly warnedDefinitionConflictKeys = new Set<string>();\n\n private state: QueryState<T> = {\n data: null,\n error: null,\n loading: true,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n staleReason: null,\n };\n\n constructor(\n options: QueryOptions<T>,\n key: string,\n cache: Map<string, QueryCell<unknown>>\n ) {\n this.options = options;\n this.key = key;\n this.cache = cache;\n }\n\n attach(instance: ComponentInstance, hookIndex: number): void {\n let hooks = this.owners.get(instance);\n if (!hooks) {\n hooks = new Set();\n this.owners.set(instance, hooks);\n }\n\n if (hooks.has(hookIndex)) {\n return;\n }\n\n hooks.add(hookIndex);\n this.ownerCount += 1;\n }\n\n detach(instance: ComponentInstance, hookIndex: number): void {\n const hooks = this.owners.get(instance);\n if (!hooks || !hooks.delete(hookIndex)) {\n return;\n }\n\n this.ownerCount -= 1;\n if (hooks.size === 0) {\n this.owners.delete(instance);\n }\n\n if (this.ownerCount <= 0) {\n this.destroy();\n }\n }\n\n warnOnConflictingDefinition(options: QueryOptions<T>): void {\n const conflicts = this.getDefinitionConflicts(options);\n if (conflicts.length === 0) {\n return;\n }\n\n const conflictKey = conflicts.join(',');\n if (this.warnedDefinitionConflictKeys.has(conflictKey)) {\n return;\n }\n\n this.warnedDefinitionConflictKeys.add(conflictKey);\n\n const callbackLabel =\n conflicts.length === 1\n ? `callback \\`${conflicts[0]}\\``\n : `callbacks ${conflicts.map((field) => `\\`${field}\\``).join(', ')}`;\n\n logger.warn(\n `[askr] Conflicting shared query definition for key \"${this.key}\". ` +\n `Shared queries are canonical by key, so reuse the same ${callbackLabel} ` +\n 'for every reader of that key.'\n );\n }\n\n private destroy(): void {\n if (this.destroyed) {\n return;\n }\n\n this.destroyed = true;\n this.controller?.abort();\n this.controller = null;\n this.startQueued = false;\n this.reconcileAttemptCount = 0;\n this.ownerCount = 0;\n this.owners.clear();\n this.cache.delete(this.key);\n this.finishPendingRefresh();\n }\n\n private getDefinitionConflicts(\n options: QueryOptions<T>\n ): QueryDefinitionField[] {\n const conflicts: QueryDefinitionField[] = [];\n\n if (this.options.fetch !== options.fetch) {\n conflicts.push('fetch');\n }\n\n if (this.options.isConsistent !== options.isConsistent) {\n conflicts.push('isConsistent');\n }\n\n if (this.options.reconcile !== options.reconcile) {\n conflicts.push('reconcile');\n }\n\n return conflicts;\n }\n\n get data(): T | null {\n recordReadableRead(this.source);\n return this.state.data;\n }\n\n get error(): {} | null {\n recordReadableRead(this.source);\n return this.state.error;\n }\n\n get loading(): boolean {\n recordReadableRead(this.source);\n return this.state.loading;\n }\n\n get refreshing(): boolean {\n recordReadableRead(this.source);\n return this.state.refreshing;\n }\n\n get stale(): boolean {\n recordReadableRead(this.source);\n return this.state.stale;\n }\n\n get consistency(): QueryConsistency {\n recordReadableRead(this.source);\n return this.state.consistency;\n }\n\n get staleReason(): QueryStaleReason | null {\n recordReadableRead(this.source);\n return this.state.staleReason;\n }\n\n ensureStarted(): void {\n if (\n this.destroyed ||\n this.state.data !== null ||\n this.pendingRefresh ||\n this.startQueued\n ) {\n return;\n }\n\n this.queueStart('initial');\n }\n\n refresh(): Promise<void> {\n if (this.destroyed) {\n return Promise.resolve();\n }\n\n if (this.pendingRefresh) {\n return this.pendingRefresh;\n }\n\n this.queueStart('manual');\n return this.pendingRefresh ?? Promise.resolve();\n }\n\n markPendingWrite(): void {\n if (this.destroyed) {\n return;\n }\n\n if (this.state.data === null) {\n return;\n }\n\n this.setState({\n loading: false,\n error: null,\n refreshing: true,\n stale: true,\n consistency: 'pending-write',\n staleReason: null,\n });\n }\n\n private queueStart(\n reason: 'initial' | 'manual' | 'invalidate' | 'pending-write'\n ): void {\n if (this.destroyed) {\n return;\n }\n\n this.startQueued = true;\n this.pendingRefresh = new Promise<void>((resolve) => {\n this.pendingRefreshResolve = resolve;\n globalScheduler.enqueue(() => {\n this.startQueued = false;\n if (this.destroyed) {\n this.finishPendingRefresh();\n return;\n }\n void this.start(reason).finally(() => {\n this.finishPendingRefresh();\n });\n });\n });\n }\n\n private finishPendingRefresh(): void {\n const resolve = this.pendingRefreshResolve;\n this.pendingRefresh = null;\n this.pendingRefreshResolve = null;\n resolve?.();\n }\n\n private setState(next: Partial<QueryState<T>>): void {\n if (this.destroyed) {\n return;\n }\n\n this.state = {\n ...this.state,\n ...next,\n };\n notifySource(this.source);\n }\n\n private async start(\n reason: 'initial' | 'manual' | 'invalidate' | 'pending-write'\n ): Promise<void> {\n if (this.destroyed) {\n return;\n }\n\n this.generation += 1;\n const generation = this.generation;\n\n this.controller?.abort();\n const controller = new AbortController();\n this.controller = controller;\n\n const hasData = this.state.data !== null;\n this.setState({\n loading: !hasData,\n refreshing: hasData,\n stale: hasData,\n consistency:\n reason === 'pending-write'\n ? 'pending-write'\n : hasData\n ? 'refreshing'\n : 'fresh',\n error: null,\n staleReason: null,\n });\n\n let nextData: T;\n try {\n nextData = await this.options.fetch({ signal: controller.signal });\n } catch (error) {\n if (\n this.destroyed ||\n this.generation !== generation ||\n this.controller !== controller\n ) {\n return;\n }\n\n if (isAbortError(error, controller.signal)) {\n this.setState(\n hasData\n ? {\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n error: null,\n staleReason: 'aborted',\n }\n : {\n loading: true,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n error: null,\n staleReason: null,\n }\n );\n return;\n }\n\n this.setState({\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n error: normalizeAsyncDataError(error, 'Unknown query error'),\n staleReason: 'error',\n });\n return;\n }\n\n if (\n this.destroyed ||\n this.generation !== generation ||\n this.controller !== controller\n ) {\n return;\n }\n\n const isConsistent = this.options.isConsistent?.(nextData) ?? true;\n if (!isConsistent) {\n this.setState({\n data: nextData,\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n staleReason: 'inconsistent',\n });\n await this.reconcile(nextData);\n return;\n }\n\n this.reconcileAttemptCount = 0;\n this.setState({\n data: nextData,\n loading: false,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n error: null,\n staleReason: null,\n });\n }\n\n private async reconcile(data: T): Promise<void> {\n const shouldRetry =\n this.options.reconcile?.(data, { key: this.options.key }) ?? false;\n\n if (!shouldRetry || this.destroyed) {\n return;\n }\n\n this.reconcileAttemptCount += 1;\n if (this.reconcileAttemptCount > RECONCILE_MAX_ATTEMPTS) {\n this.setState({\n consistency: 'stale',\n refreshing: false,\n staleReason: 'inconsistent',\n });\n return;\n }\n\n await new Promise<void>((resolve) =>\n setTimeout(resolve, RECONCILE_RETRY_DELAY_MS)\n );\n if (this.destroyed || this.state.consistency === 'fresh') {\n return;\n }\n\n await this.refresh();\n }\n}\n\nclass MutationCell<TInput, TResult> {\n private readonly source = createReadableSource();\n private action: MutationOptions<TInput, TResult>['action'];\n private affects?: MutationOptions<TInput, TResult>['affects'];\n private afterSuccess?: MutationOptions<TInput, TResult>['afterSuccess'];\n private controller: AbortController | null = null;\n private generation = 0;\n\n private state: MutationRecord<TResult> = {\n status: 'idle',\n error: null,\n result: null,\n };\n\n constructor(options: MutationOptions<TInput, TResult>) {\n this.action = options.action;\n this.affects = options.affects;\n this.afterSuccess = options.afterSuccess;\n }\n\n setOptions(options: MutationOptions<TInput, TResult>): void {\n this.action = options.action;\n this.affects = options.affects;\n this.afterSuccess = options.afterSuccess;\n }\n\n get status(): 'idle' | 'pending' | 'success' | 'error' {\n recordReadableRead(this.source);\n return this.state.status;\n }\n\n get pending(): boolean {\n recordReadableRead(this.source);\n return this.state.status === 'pending';\n }\n\n get error(): {} | null {\n recordReadableRead(this.source);\n return this.state.error;\n }\n\n get result(): TResult | null {\n recordReadableRead(this.source);\n return this.state.result;\n }\n\n private setState(next: Partial<MutationRecord<TResult>>): void {\n this.state = {\n ...this.state,\n ...next,\n };\n notifySource(this.source);\n }\n\n async execute(input: TInput): Promise<TResult> {\n this.generation += 1;\n const generation = this.generation;\n\n this.controller?.abort();\n const controller = new AbortController();\n this.controller = controller;\n\n this.setState({ status: 'pending', error: null, result: null });\n\n let result: TResult;\n try {\n result = await this.action(input, { signal: controller.signal });\n } catch (error) {\n if (this.generation !== generation || this.controller !== controller) {\n throw error;\n }\n\n if (isAbortError(error, controller.signal)) {\n this.setState({ status: 'idle', error: null });\n throw error;\n }\n\n this.setState({\n status: 'error',\n error: normalizeAsyncDataError(error, 'Unknown mutation error'),\n });\n throw error;\n }\n\n if (this.generation !== generation || this.controller !== controller) {\n return result;\n }\n\n this.setState({ status: 'success', error: null, result });\n\n if (this.afterSuccess === 'invalidate') {\n const prefixes = this.affects?.(input, result) ?? [];\n for (const prefix of new Set(prefixes)) {\n invalidateQueries(prefix, true);\n }\n }\n\n return result;\n }\n\n abort(): void {\n if (this.state.status !== 'pending') {\n return;\n }\n\n this.generation += 1;\n this.controller?.abort();\n this.controller = null;\n this.setState({ status: 'idle', error: null, result: null });\n }\n\n reset(): void {\n this.generation += 1;\n this.controller?.abort();\n this.controller = null;\n this.setState({ status: 'idle', error: null, result: null });\n }\n}\n\nexport function createQuery<T extends {}>(options: QueryOptions<T>): Query<T> {\n const instance = getCurrentComponentInstance();\n const cache = getQueryCache();\n if (!instance) {\n let cell = cache.get(options.key) as QueryCell<T> | undefined;\n if (!cell) {\n cell = new QueryCell(options, options.key, cache);\n cache.set(options.key, cell as QueryCell<unknown>);\n cell.ensureStarted();\n } else {\n cell.warnOnConflictingDefinition(options);\n }\n return cell as unknown as Query<T>;\n }\n\n const hookIndex = claimHookIndex(instance, 'query');\n ensureQueryCleanup(instance);\n\n const slotStore = getQuerySlotStore(instance);\n const existingSlot = slotStore.get(hookIndex);\n if (existingSlot && existingSlot.key === options.key) {\n (existingSlot.cell as QueryCell<T>).warnOnConflictingDefinition(options);\n return existingSlot.cell as unknown as Query<T>;\n }\n\n if (existingSlot) {\n existingSlot.cell.detach(instance, hookIndex);\n }\n\n let cell = cache.get(options.key) as QueryCell<T> | undefined;\n if (!cell) {\n cell = new QueryCell(options, options.key, cache);\n cache.set(options.key, cell as QueryCell<unknown>);\n cell.ensureStarted();\n } else {\n cell.warnOnConflictingDefinition(options);\n }\n\n slotStore.set(hookIndex, {\n key: options.key,\n cell: cell as QueryCell<unknown>,\n });\n cell.attach(instance, hookIndex);\n return cell as unknown as Query<T>;\n}\n\nexport function invalidate(prefix: string, options?: InvalidateOptions): void {\n invalidateQueries(prefix, options?.markPendingWrite ?? false);\n}\n\nfunction serializeQueryKeyNumber(part: number): string {\n if (Number.isNaN(part)) {\n return 'NaN';\n }\n\n if (Object.is(part, -0)) {\n return '-0';\n }\n\n if (part === Infinity) {\n return 'Infinity';\n }\n\n if (part === -Infinity) {\n return '-Infinity';\n }\n\n return String(part);\n}\n\nfunction serializeQueryKeyPart(part: QueryKeyPart): string {\n if (typeof (part as unknown) === 'symbol') {\n throw new Error('[Askr] queryScope() key parts cannot be symbols.');\n }\n\n if (part === null) {\n return 'null';\n }\n\n if (part === undefined) {\n return 'undefined';\n }\n\n switch (typeof part) {\n case 'string':\n return `s=${encodeURIComponent(part)}`;\n case 'number':\n return `n=${serializeQueryKeyNumber(part)}`;\n case 'boolean':\n return `b=${part ? '1' : '0'}`;\n case 'object':\n if (Array.isArray(part)) {\n return `a[${part.map((item) => serializeQueryKeyPart(item)).join(',')}]`;\n }\n\n return `o{${Object.keys(part)\n .sort()\n .map(\n (key) =>\n `${encodeURIComponent(key)}=${serializeQueryKeyPart(part[key])}`\n )\n .join(',')}}`;\n default:\n return String(part);\n }\n}\n\nexport function queryScope(namespace: string): QueryScope {\n if (typeof namespace !== 'string' || namespace.trim().length === 0) {\n throw new Error(\n '[Askr] queryScope() requires a non-empty namespace string.'\n );\n }\n\n const build = (parts: readonly QueryKeyPart[]): string =>\n [namespace, ...parts].map(serializeQueryKeyPart).join(':') + ':';\n\n return {\n key(...parts) {\n return build(parts);\n },\n\n prefix(...parts) {\n return build(parts);\n },\n\n invalidate(parts, options) {\n invalidate(build(parts), options);\n },\n };\n}\n\nconst INVALIDATE_ON_INTERVAL_OPTIONS_ERROR =\n '[Askr] invalidateOnInterval() requires an options object with a finite numeric intervalMs.';\n\nexport function invalidateOnInterval(\n prefix: string,\n options: InvalidateOnIntervalOptions\n): void {\n if (\n !options ||\n typeof options !== 'object' ||\n typeof options.intervalMs !== 'number' ||\n !Number.isFinite(options.intervalMs)\n ) {\n throw new Error(INVALIDATE_ON_INTERVAL_OPTIONS_ERROR);\n }\n\n const when: ActivityPredicate[] = [];\n\n if (options.activeOn) {\n when.push(routeActive(options.activeOn));\n }\n\n if (options.visibleOnly) {\n when.push(documentVisible());\n }\n\n if (options.focusedOnly) {\n when.push(windowFocused());\n }\n\n timer(\n options.intervalMs,\n () => {\n invalidate(prefix, {\n markPendingWrite: options.markPendingWrite,\n });\n },\n when.length > 0 ? { when } : undefined\n );\n}\n\nexport function createMutation<TInput, TResult>(\n options: MutationOptions<TInput, TResult>\n): Mutation<TInput, TResult> {\n const instance = getCurrentComponentInstance();\n\n if (!instance) {\n return new MutationCell(options) as unknown as Mutation<TInput, TResult>;\n }\n\n const hookIndex = claimHookIndex(instance, 'mutation');\n ensureMutationCleanup(instance);\n\n const slotStore = getMutationSlotStore(instance);\n const existing = slotStore.get(hookIndex) as\n | MutationCell<TInput, TResult>\n | undefined;\n if (existing) {\n existing.setOptions(options);\n return existing as unknown as Mutation<TInput, TResult>;\n }\n\n const created = new MutationCell(options);\n slotStore.set(hookIndex, created as MutationCell<unknown, unknown>);\n return created as unknown as Mutation<TInput, TResult>;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"icon.js","names":[],"sources":["../../../src/foundations/icon/icon.tsx"],"sourcesContent":["/* eslint-disable askr/no-hardcoded-theme-tokens -- Icon exposes a stable CSS variable contract consumed by themes. */\nimport { jsx, jsxs } from '../../jsx/jsx-runtime';\nimport type { JSXElement } from '../../common/jsx';\nimport type { IconProps, IconSizeToken, IconStyleObject } from './icon.types';\n\nconst ICON_SIZE_TOKENS: readonly IconSizeToken[] = ['sm', 'md', 'lg', 'xl'];\n\nexport function isIconSizeToken(value: unknown): value is IconSizeToken {\n return (\n typeof value === 'string' &&\n ICON_SIZE_TOKENS.includes(value as IconSizeToken)\n );\n}\n\nexport function normalizeIconSizeValue(size: number | string): string {\n if (typeof size === 'number') return `${size}px`;\n return size;\n}\n\nexport function resolveIconSizeVariable(size: number | string): string {\n if (isIconSizeToken(size)) {\n return `var(--ak-icon-size-${size}, var(--ak-icon-size-md, 1.25rem))`;\n }\n return normalizeIconSizeValue(size);\n}\n\nexport function resolveIconStrokeWidthVariable(\n strokeWidth: number,\n sizeToken: IconSizeToken | undefined\n): string {\n if (sizeToken) {\n return `var(--ak-icon-stroke-width-${sizeToken}, var(--ak-icon-stroke-width-md, ${strokeWidth}))`;\n }\n return `var(--ak-icon-stroke-width-md, ${strokeWidth})`;\n}\n\nfunction camelToKebab(key: string): string {\n return key.replace(/([A-Z])/g, (match) => `-${match.toLowerCase()}`);\n}\n\nexport function serializeIconStyle(\n style: string | IconStyleObject | undefined\n): string {\n if (!style) return '';\n if (typeof style === 'string') return style.trim();\n return Object.entries(style)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([key, value]) => `${camelToKebab(key)}:${String(value)}`)\n .join(';');\n}\n\nexport function joinIconStyle(\n ...styles: Array<string | undefined>\n): string | undefined {\n const merged = styles.map((style) => style?.trim()).filter(Boolean);\n return merged.length > 0 ? merged.join(';') : undefined;\n}\n\nexport function getIconContractProps({\n size = 20,\n strokeWidth = 2,\n color = 'currentColor',\n title,\n style,\n iconName,\n}: Pick<\n IconProps,\n 'color' | 'iconName' | 'size' | 'strokeWidth' | 'style' | 'title'\n>) {\n const sizeToken = isIconSizeToken(size) ? size : undefined;\n const decorative = title ? undefined : 'true';\n const resolvedSize = resolveIconSizeVariable(size);\n const resolvedStrokeWidth = resolveIconStrokeWidthVariable(\n strokeWidth,\n sizeToken\n );\n const iconStyle = joinIconStyle(\n `--ak-icon-size:${resolvedSize}`,\n `--ak-icon-stroke-width:${resolvedStrokeWidth}`,\n 'display:inline-block',\n 'flex-shrink:0',\n 'width:var(--ak-icon-size)',\n 'height:var(--ak-icon-size)',\n 'stroke-width:var(--ak-icon-stroke-width)',\n serializeIconStyle(style)\n );\n\n return {\n sizeToken,\n decorative,\n iconStyle,\n attrs: {\n xmlns: 'http://www.w3.org/2000/svg',\n width: '24',\n height: '24',\n fill: 'none',\n stroke: color,\n 'stroke-width': 'var(--ak-icon-stroke-width)',\n role: 'img',\n 'aria-hidden': title ? undefined : 'true',\n style: iconStyle,\n 'data-slot': 'icon',\n 'data-icon': iconName,\n 'data-size': sizeToken,\n 'data-decorative': decorative,\n 'data-color': color === 'currentColor' ? 'current' : undefined,\n },\n };\n}\n\nexport function IconBase({\n size = 20,\n strokeWidth = 2,\n color = 'currentColor',\n title,\n class: className,\n style,\n iconName,\n children,\n ref,\n ...rest\n}: IconProps): JSXElement {\n const { attrs } = getIconContractProps({\n size,\n strokeWidth,\n color,\n title,\n style,\n iconName,\n });\n\n const finalChildren = title\n ? [jsx('title', { children: title }), children]\n : children;\n\n return jsxs('svg', {\n ...rest,\n ...attrs,\n viewBox: rest.viewBox ?? '0 0 24 24',\n 'stroke-linecap': rest['stroke-linecap'] ?? 'round',\n 'stroke-linejoin': rest['stroke-linejoin'] ?? 'round',\n class: className,\n ref,\n children: finalChildren,\n });\n}\n"],"mappings":";;AAKA,MAAM,mBAA6C;CAAC;CAAM;CAAM;CAAM;AAAI;AAE1E,SAAgB,gBAAgB,OAAwC;CACtE,OACE,OAAO,UAAU,YACjB,iBAAiB,SAAS,KAAsB;AAEpD;AAEA,SAAgB,uBAAuB,MAA+B;CACpE,IAAI,OAAO,SAAS,UAAU,OAAO,GAAG,KAAK;CAC7C,OAAO;AACT;AAEA,SAAgB,wBAAwB,MAA+B;CACrE,IAAI,gBAAgB,IAAI,GACtB,OAAO,sBAAsB,KAAK;CAEpC,OAAO,uBAAuB,IAAI;AACpC;AAEA,SAAgB,+BACd,aACA,WACQ;CACR,IAAI,WACF,OAAO,8BAA8B,UAAU,mCAAmC,YAAY;CAEhG,OAAO,kCAAkC,YAAY;AACvD;AAEA,SAAS,aAAa,KAAqB;CACzC,OAAO,IAAI,QAAQ,aAAa,UAAU,IAAI,MAAM,YAAY,GAAG;AACrE;AAEA,SAAgB,mBACd,OACQ;CACR,IAAI,CAAC,OAAO,OAAO;CACnB,IAAI,OAAO,UAAU,UAAU,OAAO,MAAM,KAAK;CACjD,OAAO,OAAO,QAAQ,KAAK,EACxB,QAAQ,GAAG,WAAW,UAAU,UAAa,UAAU,IAAI,EAC3D,KAAK,CAAC,KAAK,WAAW,GAAG,aAAa,GAAG,EAAE,GAAG,OAAO,KAAK,GAAG,EAC7D,KAAK,GAAG;AACb;AAEA,SAAgB,cACd,GAAG,QACiB;CACpB,MAAM,SAAS,OAAO,KAAK,UAAU,OAAO,KAAK,CAAC,EAAE,OAAO,OAAO;CAClE,OAAO,OAAO,SAAS,IAAI,OAAO,KAAK,GAAG,IAAI;AAChD;AAEA,SAAgB,qBAAqB,EACnC,OAAO,IACP,cAAc,GACd,QAAQ,gBACR,OACA,OACA,YAIC;CACD,MAAM,YAAY,gBAAgB,IAAI,IAAI,OAAO;CACjD,MAAM,aAAa,QAAQ,SAAY;CACvC,MAAM,eAAe,wBAAwB,IAAI;CACjD,MAAM,sBAAsB,+BAC1B,aACA,SACF;CACA,MAAM,YAAY,cAChB,kBAAkB,gBAClB,0BAA0B,uBAC1B,wBACA,iBACA,6BACA,8BACA,4CACA,mBAAmB,KAAK,CAC1B;CAEA,OAAO;EACL;EACA;EACA;EACA,OAAO;GACL,OAAO;GACP,OAAO;GACP,QAAQ;GACR,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,MAAM;GACN,eAAe,QAAQ,SAAY;GACnC,OAAO;GACP,aAAa;GACb,aAAa;GACb,aAAa;GACb,mBAAmB;GACnB,cAAc,UAAU,iBAAiB,YAAY;EACvD;CACF;AACF;AAEA,SAAgB,SAAS,EACvB,OAAO,IACP,cAAc,GACd,QAAQ,gBACR,OACA,OAAO,WACP,OACA,UACA,UACA,KACA,GAAG,QACqB;CACxB,MAAM,EAAE,UAAU,qBAAqB;EACrC;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,gBAAgB,QAClB,CAAC,IAAI,SAAS,EAAE,UAAU,MAAM,CAAC,GAAG,QAAQ,IAC5C;CAEJ,OAAO,KAAK,OAAO;EACjB,GAAG;EACH,GAAG;EACH,SAAS,KAAK,WAAW;EACzB,kBAAkB,KAAK,qBAAqB;EAC5C,mBAAmB,KAAK,sBAAsB;EAC9C,OAAO;EACP;EACA,UAAU;CACZ,CAAC;AACH"}
1
+ {"version":3,"file":"icon.js","names":[],"sources":["../../../src/foundations/icon/icon.tsx"],"sourcesContent":["/* eslint-disable askr/no-hardcoded-theme-tokens -- Icon exposes a stable CSS variable contract consumed by themes. */\nimport { jsx, jsxs } from '../../jsx/jsx-runtime';\nimport type { JSXElement } from '../../common/jsx';\nimport type { IconProps, IconSizeToken, IconStyleObject } from './icon.types';\n\nconst ICON_SIZE_TOKENS: readonly IconSizeToken[] = ['sm', 'md', 'lg', 'xl'];\n\nexport function isIconSizeToken(value: unknown): value is IconSizeToken {\n return (\n typeof value === 'string' &&\n ICON_SIZE_TOKENS.includes(value as IconSizeToken)\n );\n}\n\nexport function normalizeIconSizeValue(size: number | string): string {\n if (typeof size === 'number') return `${size}px`;\n return size;\n}\n\nexport function resolveIconSizeVariable(size: number | string): string {\n if (isIconSizeToken(size)) {\n return `var(--ak-icon-size-${size}, var(--ak-icon-size-md, 1.25rem))`;\n }\n return normalizeIconSizeValue(size);\n}\n\nexport function resolveIconStrokeWidthVariable(\n strokeWidth: number,\n sizeToken: IconSizeToken | undefined\n): string {\n if (sizeToken) {\n return `var(--ak-icon-stroke-width-${sizeToken}, var(--ak-icon-stroke-width-md, ${strokeWidth}))`;\n }\n return `var(--ak-icon-stroke-width-md, ${strokeWidth})`;\n}\n\nfunction camelToKebab(key: string): string {\n return key.replace(/([A-Z])/g, (match) => `-${match.toLowerCase()}`);\n}\n\nexport function serializeIconStyle(\n style: string | IconStyleObject | undefined\n): string {\n if (!style) return '';\n if (typeof style === 'string') return style.trim();\n return Object.entries(style)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([key, value]) => `${camelToKebab(key)}:${String(value)}`)\n .join(';');\n}\n\nexport function joinIconStyle(\n ...styles: Array<string | undefined>\n): string | undefined {\n const merged = styles.map((style) => style?.trim()).filter(Boolean);\n return merged.length > 0 ? merged.join(';') : undefined;\n}\n\nexport function getIconContractProps({\n size = 20,\n strokeWidth = 2,\n color = 'currentColor',\n title,\n style,\n iconName,\n}: Pick<\n IconProps,\n 'color' | 'iconName' | 'size' | 'strokeWidth' | 'style' | 'title'\n>) {\n const sizeToken = isIconSizeToken(size) ? size : undefined;\n const decorative = title ? undefined : 'true';\n const resolvedSize = resolveIconSizeVariable(size);\n const resolvedStrokeWidth = resolveIconStrokeWidthVariable(\n strokeWidth,\n sizeToken\n );\n const iconStyle = joinIconStyle(\n `--ak-icon-size:${resolvedSize}`,\n `--ak-icon-stroke-width:${resolvedStrokeWidth}`,\n 'display:inline-block',\n 'flex-shrink:0',\n 'width:var(--ak-icon-size)',\n 'height:var(--ak-icon-size)',\n 'stroke-width:var(--ak-icon-stroke-width)',\n serializeIconStyle(style)\n );\n\n return {\n sizeToken,\n decorative,\n iconStyle,\n attrs: {\n xmlns: 'http://www.w3.org/2000/svg',\n width: '24',\n height: '24',\n fill: 'none',\n stroke: color,\n 'stroke-width': 'var(--ak-icon-stroke-width)',\n role: 'img',\n 'aria-hidden': title ? undefined : 'true',\n style: iconStyle,\n 'data-slot': 'icon',\n 'data-icon': iconName,\n 'data-size': sizeToken,\n 'data-decorative': decorative,\n 'data-color': color === 'currentColor' ? 'current' : undefined,\n },\n };\n}\n\nexport function IconBase({\n size = 20,\n strokeWidth = 2,\n color = 'currentColor',\n title,\n class: className,\n style,\n iconName,\n children,\n ref,\n ...rest\n}: IconProps): JSXElement {\n const { attrs } = getIconContractProps({\n size,\n strokeWidth,\n color,\n title,\n style,\n iconName,\n });\n\n const finalChildren = title\n ? [jsx('title', { children: title }), children]\n : children;\n\n return jsxs('svg', {\n ...rest,\n ...attrs,\n viewBox: rest.viewBox ?? '0 0 24 24',\n 'stroke-linecap': rest['stroke-linecap'] ?? 'round',\n 'stroke-linejoin': rest['stroke-linejoin'] ?? 'round',\n class: className,\n ref,\n children: finalChildren,\n });\n}\n"],"mappings":";;AAKA,MAAM,mBAA6C;CAAC;CAAM;CAAM;CAAM;AAAI;AAE1E,SAAgB,gBAAgB,OAAwC;CACtE,OACE,OAAO,UAAU,YACjB,iBAAiB,SAAS,KAAsB;AAEpD;AAEA,SAAgB,uBAAuB,MAA+B;CACpE,IAAI,OAAO,SAAS,UAAU,OAAO,GAAG,KAAK;CAC7C,OAAO;AACT;AAEA,SAAgB,wBAAwB,MAA+B;CACrE,IAAI,gBAAgB,IAAI,GACtB,OAAO,sBAAsB,KAAK;CAEpC,OAAO,uBAAuB,IAAI;AACpC;AAEA,SAAgB,+BACd,aACA,WACQ;CACR,IAAI,WACF,OAAO,8BAA8B,UAAU,mCAAmC,YAAY;CAEhG,OAAO,kCAAkC,YAAY;AACvD;AAEA,SAAS,aAAa,KAAqB;CACzC,OAAO,IAAI,QAAQ,aAAa,UAAU,IAAI,MAAM,YAAY,GAAG;AACrE;AAEA,SAAgB,mBACd,OACQ;CACR,IAAI,CAAC,OAAO,OAAO;CACnB,IAAI,OAAO,UAAU,UAAU,OAAO,MAAM,KAAK;CACjD,OAAO,OAAO,QAAQ,KAAK,CAAC,CACzB,QAAQ,GAAG,WAAW,UAAU,UAAa,UAAU,IAAI,CAAC,CAC5D,KAAK,CAAC,KAAK,WAAW,GAAG,aAAa,GAAG,EAAE,GAAG,OAAO,KAAK,GAAG,CAAC,CAC9D,KAAK,GAAG;AACb;AAEA,SAAgB,cACd,GAAG,QACiB;CACpB,MAAM,SAAS,OAAO,KAAK,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO;CAClE,OAAO,OAAO,SAAS,IAAI,OAAO,KAAK,GAAG,IAAI;AAChD;AAEA,SAAgB,qBAAqB,EACnC,OAAO,IACP,cAAc,GACd,QAAQ,gBACR,OACA,OACA,YAIC;CACD,MAAM,YAAY,gBAAgB,IAAI,IAAI,OAAO;CACjD,MAAM,aAAa,QAAQ,SAAY;CACvC,MAAM,eAAe,wBAAwB,IAAI;CACjD,MAAM,sBAAsB,+BAC1B,aACA,SACF;CACA,MAAM,YAAY,cAChB,kBAAkB,gBAClB,0BAA0B,uBAC1B,wBACA,iBACA,6BACA,8BACA,4CACA,mBAAmB,KAAK,CAC1B;CAEA,OAAO;EACL;EACA;EACA;EACA,OAAO;GACL,OAAO;GACP,OAAO;GACP,QAAQ;GACR,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,MAAM;GACN,eAAe,QAAQ,SAAY;GACnC,OAAO;GACP,aAAa;GACb,aAAa;GACb,aAAa;GACb,mBAAmB;GACnB,cAAc,UAAU,iBAAiB,YAAY;EACvD;CACF;AACF;AAEA,SAAgB,SAAS,EACvB,OAAO,IACP,cAAc,GACd,QAAQ,gBACR,OACA,OAAO,WACP,OACA,UACA,UACA,KACA,GAAG,QACqB;CACxB,MAAM,EAAE,UAAU,qBAAqB;EACrC;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,gBAAgB,QAClB,CAAC,IAAI,SAAS,EAAE,UAAU,MAAM,CAAC,GAAG,QAAQ,IAC5C;CAEJ,OAAO,KAAK,OAAO;EACjB,GAAG;EACH,GAAG;EACH,SAAS,KAAK,WAAW;EACzB,kBAAkB,KAAK,qBAAqB;EAC5C,mBAAmB,KAAK,sBAAsB;EAC9C,OAAO;EACP;EACA,UAAU;CACZ,CAAC;AACH"}