@askrjs/askr 0.0.35 → 0.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -9
- package/dist/bench/components/benchmark-row.js.map +1 -1
- package/dist/bench/components/benchmark-table.js +1 -1
- package/dist/bench/components/benchmark-table.js.map +1 -1
- package/dist/benchmark.js +3 -3
- package/dist/benchmark.js.map +1 -1
- package/dist/bin/askr-ssg.js.map +1 -1
- package/dist/boot/index.d.ts +1 -7
- package/dist/boot/index.d.ts.map +1 -1
- package/dist/boot/index.js +31 -42
- package/dist/boot/index.js.map +1 -1
- package/dist/common/control.js.map +1 -1
- package/dist/common/env.js.map +1 -1
- package/dist/common/ssr-errors.js.map +1 -1
- package/dist/common/vnode.js.map +1 -1
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +2 -0
- package/dist/components/link.d.ts +4 -5
- package/dist/components/link.d.ts.map +1 -1
- package/dist/components/link.js +2 -1
- package/dist/components/link.js.map +1 -1
- package/dist/control/case.js.map +1 -1
- package/dist/control/for.js.map +1 -1
- package/dist/control/shared.js.map +1 -1
- package/dist/control/show.js.map +1 -1
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +165 -23
- package/dist/data/index.js.map +1 -1
- package/dist/dev/invariant.js.map +1 -1
- package/dist/dev/logger.js.map +1 -1
- package/dist/foundations/icon/icon.d.ts.map +1 -1
- package/dist/foundations/icon/icon.js.map +1 -1
- package/dist/foundations/icon/icon.types.d.ts +2 -1
- package/dist/foundations/icon/icon.types.d.ts.map +1 -1
- package/dist/foundations/icon/index.d.ts +3 -0
- package/dist/foundations/icon/index.js +2 -0
- package/dist/foundations/index.d.ts +1 -18
- package/dist/foundations/index.js +2 -18
- package/dist/foundations/interactions/dismissable.js.map +1 -1
- package/dist/foundations/interactions/focusable.js.map +1 -1
- package/dist/foundations/interactions/hoverable.js.map +1 -1
- package/dist/foundations/interactions/index.d.ts +7 -0
- package/dist/foundations/interactions/index.js +7 -0
- package/dist/foundations/interactions/interaction-policy.js +2 -2
- package/dist/foundations/interactions/interaction-policy.js.map +1 -1
- package/dist/foundations/interactions/pressable.js.map +1 -1
- package/dist/foundations/interactions/roving-focus.js.map +1 -1
- package/dist/foundations/state/controllable.js.map +1 -1
- package/dist/foundations/state/index.d.ts +2 -0
- package/dist/foundations/state/index.js +2 -0
- package/dist/foundations/structures/collection.js.map +1 -1
- package/dist/foundations/structures/index.d.ts +8 -0
- package/dist/foundations/structures/index.js +7 -0
- package/dist/foundations/structures/layer.js.map +1 -1
- package/dist/foundations/structures/layout.js.map +1 -1
- package/dist/foundations/structures/portal.js.map +1 -1
- package/dist/foundations/structures/presence.js.map +1 -1
- package/dist/foundations/structures/slot.js.map +1 -1
- package/dist/foundations/utilities/aria.js.map +1 -1
- package/dist/foundations/utilities/compose-handlers.js.map +1 -1
- package/dist/foundations/utilities/compose-ref.js.map +1 -1
- package/dist/foundations/utilities/index.d.ts +7 -0
- package/dist/foundations/utilities/index.js +6 -0
- package/dist/foundations/utilities/merge-props.js.map +1 -1
- package/dist/foundations/utilities/use-id.js.map +1 -1
- package/dist/fx/fx.js.map +1 -1
- package/dist/fx/timing.js.map +1 -1
- package/dist/index.d.ts +2 -16
- package/dist/index.js +1 -17
- package/dist/index.js.map +1 -1
- package/dist/jsx/utils.js.map +1 -1
- package/dist/jsx-dev-runtime.d.ts +1 -1
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/renderer/children.js.map +1 -1
- package/dist/renderer/cleanup.js.map +1 -1
- package/dist/renderer/dom.js +92 -357
- package/dist/renderer/dom.js.map +1 -1
- package/dist/renderer/evaluate.js +7 -0
- package/dist/renderer/evaluate.js.map +1 -1
- package/dist/renderer/fastpath.js +20 -18
- package/dist/renderer/fastpath.js.map +1 -1
- package/dist/renderer/for-commit.js +486 -0
- package/dist/renderer/for-commit.js.map +1 -0
- package/dist/renderer/index.js.map +1 -1
- package/dist/renderer/keyed.js +84 -23
- package/dist/renderer/keyed.js.map +1 -1
- package/dist/renderer/reconcile.js +11 -18
- package/dist/renderer/reconcile.js.map +1 -1
- package/dist/renderer/utils.js +5 -1
- package/dist/renderer/utils.js.map +1 -1
- package/dist/resources/index.d.ts +1 -2
- package/dist/resources/index.js +1 -2
- package/dist/router/index.d.ts +2 -2
- package/dist/router/index.js +2 -2
- package/dist/router/match.js.map +1 -1
- package/dist/router/navigate.d.ts.map +1 -1
- package/dist/router/navigate.js +4 -2
- package/dist/router/navigate.js.map +1 -1
- package/dist/router/policy.js.map +1 -1
- package/dist/router/route-context.js.map +1 -1
- package/dist/router/route.d.ts +1 -1
- package/dist/router/route.d.ts.map +1 -1
- package/dist/router/route.js +2 -33
- package/dist/router/route.js.map +1 -1
- package/dist/runtime/child-scope.d.ts +1 -0
- package/dist/runtime/child-scope.d.ts.map +1 -1
- package/dist/runtime/child-scope.js +2 -0
- package/dist/runtime/child-scope.js.map +1 -1
- package/dist/runtime/component.js +1 -1
- package/dist/runtime/component.js.map +1 -1
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/control.js.map +1 -1
- package/dist/runtime/derive.d.ts +2 -1
- package/dist/runtime/derive.d.ts.map +1 -1
- package/dist/runtime/derive.js +15 -10
- package/dist/runtime/derive.js.map +1 -1
- package/dist/runtime/dev-namespace.js.map +1 -1
- package/dist/runtime/effect.d.ts.map +1 -1
- package/dist/runtime/effect.js +34 -9
- package/dist/runtime/effect.js.map +1 -1
- package/dist/runtime/events.js.map +1 -1
- package/dist/runtime/execution-model.js.map +1 -1
- package/dist/runtime/fastlane.js.map +1 -1
- package/dist/runtime/for-bench.d.ts +1 -1
- package/dist/runtime/for-bench.d.ts.map +1 -1
- package/dist/runtime/for-bench.js +15 -14
- package/dist/runtime/for-bench.js.map +1 -1
- package/dist/runtime/for.d.ts +1 -0
- package/dist/runtime/for.d.ts.map +1 -1
- package/dist/runtime/for.js +90 -31
- package/dist/runtime/for.js.map +1 -1
- package/dist/runtime/operations.d.ts.map +1 -1
- package/dist/runtime/operations.js +10 -8
- package/dist/runtime/operations.js.map +1 -1
- package/dist/runtime/perf-metrics.js +8 -2
- package/dist/runtime/perf-metrics.js.map +1 -1
- package/dist/runtime/readable.js.map +1 -1
- package/dist/runtime/resource-cell.js +3 -2
- package/dist/runtime/resource-cell.js.map +1 -1
- package/dist/runtime/scheduler.d.ts +0 -1
- package/dist/runtime/scheduler.d.ts.map +1 -1
- package/dist/runtime/scheduler.js +6 -19
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/selector.d.ts.map +1 -1
- package/dist/runtime/selector.js +182 -103
- package/dist/runtime/selector.js.map +1 -1
- package/dist/runtime/snapshot-source.d.ts +10 -0
- package/dist/runtime/snapshot-source.d.ts.map +1 -0
- package/dist/runtime/snapshot-source.js +17 -0
- package/dist/runtime/snapshot-source.js.map +1 -0
- package/dist/runtime/ssr-bridge.js.map +1 -1
- package/dist/runtime/state.d.ts.map +1 -1
- package/dist/runtime/state.js +1 -5
- package/dist/runtime/state.js.map +1 -1
- package/dist/ssg/batch-render.js.map +1 -1
- package/dist/ssg/create-static-gen.js.map +1 -1
- package/dist/ssg/generate-metadata.js.map +1 -1
- package/dist/ssg/incremental-manifest.js.map +1 -1
- package/dist/ssg/index.d.ts +1 -6
- package/dist/ssg/index.js +1 -6
- package/dist/ssg/resolve-ssg-data.js.map +1 -1
- package/dist/ssg/route-utils.js.map +1 -1
- package/dist/ssg/write-static-files.js.map +1 -1
- package/dist/ssr/attrs.js.map +1 -1
- package/dist/ssr/context.d.ts +3 -1
- package/dist/ssr/context.d.ts.map +1 -1
- package/dist/ssr/context.js +31 -11
- package/dist/ssr/context.js.map +1 -1
- package/dist/ssr/escape.js +56 -16
- package/dist/ssr/escape.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -31
- package/dist/ssr/index.d.ts.map +1 -1
- package/dist/ssr/index.js +19 -49
- package/dist/ssr/index.js.map +1 -1
- package/dist/ssr/render-keys.js +1 -12
- package/dist/ssr/render-keys.js.map +1 -1
- package/dist/ssr/sink.js.map +1 -1
- package/dist/ssr/verify-hydration.js +25 -0
- package/dist/ssr/verify-hydration.js.map +1 -0
- package/package.json +44 -19
- package/dist/_virtual/_rolldown/runtime.js +0 -7
- package/dist/foundations/core.d.ts +0 -15
- package/dist/foundations/core.js +0 -13
- package/dist/foundations/structures.d.ts +0 -7
- package/dist/foundations/structures.js +0 -6
- package/dist/ssg/batch-render.d.ts +0 -16
- package/dist/ssg/batch-render.d.ts.map +0 -1
- package/dist/ssg/generate-metadata.d.ts +0 -24
- package/dist/ssg/generate-metadata.d.ts.map +0 -1
- package/dist/ssg/resolve-ssg-data.d.ts +0 -23
- package/dist/ssg/resolve-ssg-data.d.ts.map +0 -1
- package/dist/ssg/route-utils.d.ts +0 -16
- package/dist/ssg/route-utils.d.ts.map +0 -1
- package/dist/ssg/write-static-files.d.ts +0 -15
- package/dist/ssg/write-static-files.d.ts.map +0 -1
- package/dist/ssr/render-keys.d.ts +0 -37
- package/dist/ssr/render-keys.d.ts.map +0 -1
- package/dist/ssr/stream-render.js +0 -76
- package/dist/ssr/stream-render.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-boundary.js","names":[],"sources":["../../src/components/error-boundary.tsx"],"sourcesContent":["import type { Props } from '../common/props';\nimport { ELEMENT_TYPE, type JSXElement } from '../common/jsx';\nimport { __ERROR_BOUNDARY__ } from '../common/vnode';\nimport {\n getCurrentComponentInstance,\n type ComponentInstance,\n} from '../runtime/component';\nimport { logger } from '../dev/logger';\nimport { isDevelopmentEnvironment } from '../common/env';\n\nexport type ErrorBoundaryFallbackRender = (\n error: unknown,\n reset: () => void\n) => unknown;\n\nexport interface ErrorBoundaryProps extends Props {\n children?: unknown;\n fallback?: unknown | ErrorBoundaryFallbackRender;\n onError?: (error: unknown) => void;\n resetKey?: unknown;\n}\n\ntype ErrorBoundaryState = NonNullable<ComponentInstance['errorBoundaryState']>;\n\ntype ErrorBoundaryVNode = JSXElement & {\n __instance?: ComponentInstance;\n};\n\nfunction getBoundaryMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message || error.name || 'Unknown error';\n }\n\n if (typeof error === 'string') {\n return error;\n }\n\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n}\n\nfunction ensureBoundaryState(\n instance: ComponentInstance,\n resetKey: unknown\n): ErrorBoundaryState {\n const boundaryState =\n instance.errorBoundaryState ??\n (instance.errorBoundaryState = {\n error: null,\n resetKey,\n notified: false,\n });\n\n if (!Object.is(boundaryState.resetKey, resetKey)) {\n boundaryState.error = null;\n boundaryState.resetKey = resetKey;\n boundaryState.notified = false;\n }\n\n return boundaryState;\n}\n\nfunction createBoundaryVNode(\n instance: ComponentInstance,\n props: ErrorBoundaryProps\n): ErrorBoundaryVNode {\n const key =\n typeof props.key === 'symbol'\n ? null\n : ((props.key ?? null) as string | number | null);\n\n return {\n $$typeof: ELEMENT_TYPE,\n type: __ERROR_BOUNDARY__,\n props: {\n children: props.children,\n fallback: props.fallback,\n onError: props.onError,\n resetKey: props.resetKey,\n },\n key,\n __instance: instance,\n };\n}\n\nexport function ErrorBoundary(props: ErrorBoundaryProps): JSXElement {\n const instance = getCurrentComponentInstance();\n if (!instance) {\n throw new Error(\n '[Askr] ErrorBoundary() can only be used during component render execution.'\n );\n }\n\n ensureBoundaryState(instance, props.resetKey);\n return createBoundaryVNode(instance, props);\n}\n\nexport function isErrorBoundaryVNode(\n value: unknown\n): value is ErrorBoundaryVNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as ErrorBoundaryVNode).type === __ERROR_BOUNDARY__\n );\n}\n\nexport function resolveErrorBoundaryState(\n vnode: ErrorBoundaryVNode\n): ErrorBoundaryState | null {\n return vnode.__instance?.errorBoundaryState ?? null;\n}\n\nexport function resolveErrorBoundaryFallback(\n fallback: ErrorBoundaryProps['fallback'],\n error: unknown,\n reset: () => void\n): unknown {\n if (typeof fallback === 'function') {\n return fallback(error, reset);\n }\n\n if (fallback !== undefined) {\n return fallback;\n }\n\n const message = getBoundaryMessage(error);\n const wrapper = document.createElement('div');\n wrapper.setAttribute('role', 'alert');\n wrapper.setAttribute('data-askr-error-boundary', 'true');\n wrapper.style.boxSizing = 'border-box';\n wrapper.style.padding = '1rem';\n wrapper.style.border = '1px solid currentColor';\n wrapper.style.borderRadius = '0.75rem';\n wrapper.style.display = 'grid';\n wrapper.style.gap = '0.75rem';\n wrapper.style.maxWidth = '100%';\n\n const title = document.createElement('strong');\n title.textContent = 'Something went wrong while rendering this view.';\n\n const summary = document.createElement('p');\n summary.textContent =\n 'The app recovered into a visible fallback so the error is not hidden in the console.';\n summary.style.margin = '0';\n\n const details = document.createElement('details');\n details.open = isDevelopmentEnvironment();\n\n const detailsSummary = document.createElement('summary');\n detailsSummary.textContent = 'Error details';\n\n const pre = document.createElement('pre');\n pre.textContent = message;\n pre.style.margin = '0';\n pre.style.whiteSpace = 'pre-wrap';\n pre.style.wordBreak = 'break-word';\n\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = 'Try again';\n button.addEventListener('click', () => reset());\n\n details.append(detailsSummary, pre);\n wrapper.append(title, summary, details, button);\n return wrapper;\n}\n\nexport function createBoundaryReset(instance: ComponentInstance): () => void {\n return () => {\n const boundaryState = instance.errorBoundaryState;\n if (!boundaryState) {\n return;\n }\n boundaryState.error = null;\n boundaryState.notified = false;\n queueMicrotask(() => {\n instance._enqueueRun?.();\n });\n };\n}\n\nexport function reportBoundaryError(\n instance: ComponentInstance,\n error: unknown,\n onError?: (error: unknown) => void\n): void {\n const boundaryState = instance.errorBoundaryState;\n if (\n boundaryState &&\n Object.is(boundaryState.error, error) &&\n boundaryState.notified\n ) {\n return;\n }\n\n if (boundaryState) {\n boundaryState.error = error;\n boundaryState.notified = true;\n }\n\n try {\n onError?.(error);\n } catch (hookError) {\n logger.error('[Askr] ErrorBoundary onError handler threw:', hookError);\n }\n\n logger.error('[Askr] ErrorBoundary caught render error:', error);\n}\n"],"mappings":";;;;;;AA4BA,SAAS,mBAAmB,OAAwB;
|
|
1
|
+
{"version":3,"file":"error-boundary.js","names":[],"sources":["../../src/components/error-boundary.tsx"],"sourcesContent":["import type { Props } from '../common/props';\nimport { ELEMENT_TYPE, type JSXElement } from '../common/jsx';\nimport { __ERROR_BOUNDARY__ } from '../common/vnode';\nimport {\n getCurrentComponentInstance,\n type ComponentInstance,\n} from '../runtime/component';\nimport { logger } from '../dev/logger';\nimport { isDevelopmentEnvironment } from '../common/env';\n\nexport type ErrorBoundaryFallbackRender = (\n error: unknown,\n reset: () => void\n) => unknown;\n\nexport interface ErrorBoundaryProps extends Props {\n children?: unknown;\n fallback?: unknown | ErrorBoundaryFallbackRender;\n onError?: (error: unknown) => void;\n resetKey?: unknown;\n}\n\ntype ErrorBoundaryState = NonNullable<ComponentInstance['errorBoundaryState']>;\n\ntype ErrorBoundaryVNode = JSXElement & {\n __instance?: ComponentInstance;\n};\n\nfunction getBoundaryMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message || error.name || 'Unknown error';\n }\n\n if (typeof error === 'string') {\n return error;\n }\n\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n}\n\nfunction ensureBoundaryState(\n instance: ComponentInstance,\n resetKey: unknown\n): ErrorBoundaryState {\n const boundaryState =\n instance.errorBoundaryState ??\n (instance.errorBoundaryState = {\n error: null,\n resetKey,\n notified: false,\n });\n\n if (!Object.is(boundaryState.resetKey, resetKey)) {\n boundaryState.error = null;\n boundaryState.resetKey = resetKey;\n boundaryState.notified = false;\n }\n\n return boundaryState;\n}\n\nfunction createBoundaryVNode(\n instance: ComponentInstance,\n props: ErrorBoundaryProps\n): ErrorBoundaryVNode {\n const key =\n typeof props.key === 'symbol'\n ? null\n : ((props.key ?? null) as string | number | null);\n\n return {\n $$typeof: ELEMENT_TYPE,\n type: __ERROR_BOUNDARY__,\n props: {\n children: props.children,\n fallback: props.fallback,\n onError: props.onError,\n resetKey: props.resetKey,\n },\n key,\n __instance: instance,\n };\n}\n\nexport function ErrorBoundary(props: ErrorBoundaryProps): JSXElement {\n const instance = getCurrentComponentInstance();\n if (!instance) {\n throw new Error(\n '[Askr] ErrorBoundary() can only be used during component render execution.'\n );\n }\n\n ensureBoundaryState(instance, props.resetKey);\n return createBoundaryVNode(instance, props);\n}\n\nexport function isErrorBoundaryVNode(\n value: unknown\n): value is ErrorBoundaryVNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as ErrorBoundaryVNode).type === __ERROR_BOUNDARY__\n );\n}\n\nexport function resolveErrorBoundaryState(\n vnode: ErrorBoundaryVNode\n): ErrorBoundaryState | null {\n return vnode.__instance?.errorBoundaryState ?? null;\n}\n\nexport function resolveErrorBoundaryFallback(\n fallback: ErrorBoundaryProps['fallback'],\n error: unknown,\n reset: () => void\n): unknown {\n if (typeof fallback === 'function') {\n return fallback(error, reset);\n }\n\n if (fallback !== undefined) {\n return fallback;\n }\n\n const message = getBoundaryMessage(error);\n const wrapper = document.createElement('div');\n wrapper.setAttribute('role', 'alert');\n wrapper.setAttribute('data-askr-error-boundary', 'true');\n wrapper.style.boxSizing = 'border-box';\n wrapper.style.padding = '1rem';\n wrapper.style.border = '1px solid currentColor';\n wrapper.style.borderRadius = '0.75rem';\n wrapper.style.display = 'grid';\n wrapper.style.gap = '0.75rem';\n wrapper.style.maxWidth = '100%';\n\n const title = document.createElement('strong');\n title.textContent = 'Something went wrong while rendering this view.';\n\n const summary = document.createElement('p');\n summary.textContent =\n 'The app recovered into a visible fallback so the error is not hidden in the console.';\n summary.style.margin = '0';\n\n const details = document.createElement('details');\n details.open = isDevelopmentEnvironment();\n\n const detailsSummary = document.createElement('summary');\n detailsSummary.textContent = 'Error details';\n\n const pre = document.createElement('pre');\n pre.textContent = message;\n pre.style.margin = '0';\n pre.style.whiteSpace = 'pre-wrap';\n pre.style.wordBreak = 'break-word';\n\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = 'Try again';\n button.addEventListener('click', () => reset());\n\n details.append(detailsSummary, pre);\n wrapper.append(title, summary, details, button);\n return wrapper;\n}\n\nexport function createBoundaryReset(instance: ComponentInstance): () => void {\n return () => {\n const boundaryState = instance.errorBoundaryState;\n if (!boundaryState) {\n return;\n }\n boundaryState.error = null;\n boundaryState.notified = false;\n queueMicrotask(() => {\n instance._enqueueRun?.();\n });\n };\n}\n\nexport function reportBoundaryError(\n instance: ComponentInstance,\n error: unknown,\n onError?: (error: unknown) => void\n): void {\n const boundaryState = instance.errorBoundaryState;\n if (\n boundaryState &&\n Object.is(boundaryState.error, error) &&\n boundaryState.notified\n ) {\n return;\n }\n\n if (boundaryState) {\n boundaryState.error = error;\n boundaryState.notified = true;\n }\n\n try {\n onError?.(error);\n } catch (hookError) {\n logger.error('[Askr] ErrorBoundary onError handler threw:', hookError);\n }\n\n logger.error('[Askr] ErrorBoundary caught render error:', error);\n}\n"],"mappings":";;;;;;AA4BA,SAAS,mBAAmB,OAAwB;CAClD,IAAI,iBAAiB,OACnB,OAAO,MAAM,WAAW,MAAM,QAAQ;CAGxC,IAAI,OAAO,UAAU,UACnB,OAAO;CAGT,IAAI;EACF,OAAO,KAAK,UAAU,MAAM;SACtB;EACN,OAAO,OAAO,MAAM;;;AAIxB,SAAS,oBACP,UACA,UACoB;CACpB,MAAM,gBACJ,SAAS,uBACR,SAAS,qBAAqB;EAC7B,OAAO;EACP;EACA,UAAU;EACX;CAEH,IAAI,CAAC,OAAO,GAAG,cAAc,UAAU,SAAS,EAAE;EAChD,cAAc,QAAQ;EACtB,cAAc,WAAW;EACzB,cAAc,WAAW;;CAG3B,OAAO;;AAGT,SAAS,oBACP,UACA,OACoB;CACpB,MAAM,MACJ,OAAO,MAAM,QAAQ,WACjB,OACE,MAAM,OAAO;CAErB,OAAO;EACL,UAAU;EACV,MAAM;EACN,OAAO;GACL,UAAU,MAAM;GAChB,UAAU,MAAM;GAChB,SAAS,MAAM;GACf,UAAU,MAAM;GACjB;EACD;EACA,YAAY;EACb;;AAGH,SAAgB,cAAc,OAAuC;CACnE,MAAM,WAAW,6BAA6B;CAC9C,IAAI,CAAC,UACH,MAAM,IAAI,MACR,6EACD;CAGH,oBAAoB,UAAU,MAAM,SAAS;CAC7C,OAAO,oBAAoB,UAAU,MAAM;;AAmB7C,SAAgB,6BACd,UACA,OACA,OACS;CACT,IAAI,OAAO,aAAa,YACtB,OAAO,SAAS,OAAO,MAAM;CAG/B,IAAI,aAAa,QACf,OAAO;CAGT,MAAM,UAAU,mBAAmB,MAAM;CACzC,MAAM,UAAU,SAAS,cAAc,MAAM;CAC7C,QAAQ,aAAa,QAAQ,QAAQ;CACrC,QAAQ,aAAa,4BAA4B,OAAO;CACxD,QAAQ,MAAM,YAAY;CAC1B,QAAQ,MAAM,UAAU;CACxB,QAAQ,MAAM,SAAS;CACvB,QAAQ,MAAM,eAAe;CAC7B,QAAQ,MAAM,UAAU;CACxB,QAAQ,MAAM,MAAM;CACpB,QAAQ,MAAM,WAAW;CAEzB,MAAM,QAAQ,SAAS,cAAc,SAAS;CAC9C,MAAM,cAAc;CAEpB,MAAM,UAAU,SAAS,cAAc,IAAI;CAC3C,QAAQ,cACN;CACF,QAAQ,MAAM,SAAS;CAEvB,MAAM,UAAU,SAAS,cAAc,UAAU;CACjD,QAAQ,OAAO,0BAA0B;CAEzC,MAAM,iBAAiB,SAAS,cAAc,UAAU;CACxD,eAAe,cAAc;CAE7B,MAAM,MAAM,SAAS,cAAc,MAAM;CACzC,IAAI,cAAc;CAClB,IAAI,MAAM,SAAS;CACnB,IAAI,MAAM,aAAa;CACvB,IAAI,MAAM,YAAY;CAEtB,MAAM,SAAS,SAAS,cAAc,SAAS;CAC/C,OAAO,OAAO;CACd,OAAO,cAAc;CACrB,OAAO,iBAAiB,eAAe,OAAO,CAAC;CAE/C,QAAQ,OAAO,gBAAgB,IAAI;CACnC,QAAQ,OAAO,OAAO,SAAS,SAAS,OAAO;CAC/C,OAAO;;AAGT,SAAgB,oBAAoB,UAAyC;CAC3E,aAAa;EACX,MAAM,gBAAgB,SAAS;EAC/B,IAAI,CAAC,eACH;EAEF,cAAc,QAAQ;EACtB,cAAc,WAAW;EACzB,qBAAqB;GACnB,SAAS,eAAe;IACxB;;;AAIN,SAAgB,oBACd,UACA,OACA,SACM;CACN,MAAM,gBAAgB,SAAS;CAC/B,IACE,iBACA,OAAO,GAAG,cAAc,OAAO,MAAM,IACrC,cAAc,UAEd;CAGF,IAAI,eAAe;EACjB,cAAc,QAAQ;EACtB,cAAc,WAAW;;CAG3B,IAAI;EACF,UAAU,MAAM;UACT,WAAW;EAClB,OAAO,MAAM,+CAA+C,UAAU;;CAGxE,OAAO,MAAM,6CAA6C,MAAM"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { Props } from "../common/props.js";
|
|
2
|
+
import { JSXElement } from "../common/jsx.js";
|
|
1
3
|
//#region src/components/link.d.ts
|
|
2
|
-
|
|
3
|
-
* Link component for client-side navigation
|
|
4
|
-
*/
|
|
5
|
-
type LinkProps = Omit<JSX.IntrinsicElements['a'], 'children' | 'href' | 'class' | 'rel' | 'target' | 'aria-current' | 'aria-label'> & {
|
|
4
|
+
type LinkProps = Omit<Props, 'children' | 'href' | 'class' | 'rel' | 'target' | 'aria-current' | 'aria-label'> & {
|
|
6
5
|
href: string;
|
|
7
6
|
class?: string;
|
|
8
7
|
children?: unknown;
|
|
@@ -62,7 +61,7 @@ declare function Link({
|
|
|
62
61
|
'aria-current': ariaCurrent,
|
|
63
62
|
'aria-label': ariaLabel,
|
|
64
63
|
...rest
|
|
65
|
-
}: LinkProps):
|
|
64
|
+
}: LinkProps): JSXElement;
|
|
66
65
|
//#endregion
|
|
67
66
|
export { Link, LinkProps };
|
|
68
67
|
//# sourceMappingURL=link.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.d.ts","names":[],"sources":["../../src/components/link.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"link.d.ts","names":[],"sources":["../../src/components/link.tsx"],"mappings":";;;KAWY,SAAA,GAAY,IAAA,CACtB,KAAA;EASA,IAAA;EACA,KAAA;EACA,QAAA;EAXA;;;;EAgBA,GAAA;EAKA;;;;EAAA,MAAA;EA8Cc;;;;EAzCd,cAAA;EA4CA;;;EAjCA,YAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8Bc,IAAA,CAAA;EACd,IAAA;EACA,KAAA,EAAO,SAAA;EACP,QAAA;EACA,GAAA;EACA,MAAA;EAAA,gBACgB,WAAA;EAAA,cACF,SAAA;EAAA,GACX;AAAA,GACF,SAAA,GAAY,UAAA"}
|
package/dist/components/link.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import "../jsx/types.js";
|
|
1
2
|
import { jsx } from "../jsx-runtime.js";
|
|
3
|
+
import "../jsx-runtime2.js";
|
|
2
4
|
import { navigate } from "../router/navigate.js";
|
|
3
5
|
import { mergeProps } from "../foundations/utilities/merge-props.js";
|
|
4
6
|
import { applyInteractionPolicy } from "../foundations/interactions/interaction-policy.js";
|
|
5
|
-
import "../jsx-runtime2.js";
|
|
6
7
|
//#region src/components/link.tsx
|
|
7
8
|
/**
|
|
8
9
|
* Link component for client-side navigation
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","names":[],"sources":["../../src/components/link.tsx"],"sourcesContent":["/**\n * Link component for client-side navigation\n */\n\nimport { navigate } from '../router/navigate';\nimport { applyInteractionPolicy } from '../foundations/interactions/interaction-policy';\nimport { mergeProps } from '../foundations/utilities/merge-props';\n\nexport type LinkProps = Omit<\n
|
|
1
|
+
{"version":3,"file":"link.js","names":[],"sources":["../../src/components/link.tsx"],"sourcesContent":["/**\n * Link component for client-side navigation\n */\n\nimport '../jsx/types';\nimport type { JSXElement } from '../common/jsx';\nimport type { Props } from '../common/props';\nimport { navigate } from '../router/navigate';\nimport { applyInteractionPolicy } from '../foundations/interactions/interaction-policy';\nimport { mergeProps } from '../foundations/utilities/merge-props';\n\nexport type LinkProps = Omit<\n Props,\n | 'children'\n | 'href'\n | 'class'\n | 'rel'\n | 'target'\n | 'aria-current'\n | 'aria-label'\n> & {\n href: string;\n class?: string;\n children?: unknown;\n /**\n * Optional rel attribute for link relationships.\n * Common values: \"noopener\", \"noreferrer\", \"nofollow\"\n */\n rel?: string;\n /**\n * Optional target attribute.\n * Use \"_blank\" for new tab/window.\n */\n target?: string;\n /**\n * Optional aria-current attribute for indicating current page/location.\n * Use \"page\" for the current page in navigation.\n */\n 'aria-current'?:\n | 'page'\n | 'step'\n | 'location'\n | 'date'\n | 'time'\n | 'true'\n | 'false';\n /**\n * Optional aria-label for accessibility when link text isn't descriptive enough.\n */\n 'aria-label'?: string;\n};\n\n/**\n * Link component that prevents default navigation and uses navigate()\n * Provides declarative way to navigate between routes\n *\n * Accessibility features:\n * - Proper semantic <a> element (not a button)\n * - Supports aria-current for indicating active page\n * - Supports aria-label for descriptive labels\n * - Keyboard accessible (Enter key handled by native <a> element)\n *\n * Respects native browser behaviors:\n * - Middle-click (opens in new tab)\n * - Ctrl/Cmd+click (opens in new tab)\n * - Shift+click (opens in new window)\n * - Alt+click (downloads link)\n * - Right-click context menu\n *\n * Best practices:\n * - Use target=\"_blank\" with rel=\"noopener noreferrer\" for external links\n * - Use aria-current=\"page\" for the current page in navigation\n * - Provide descriptive link text or aria-label\n *\n * Uses applyInteractionPolicy to enforce pit-of-success principles:\n * - Interaction behavior centralized in foundations\n * - Keyboard handling automatic\n * - Composable via mergeProps\n */\nexport function Link({\n href,\n class: className,\n children,\n rel,\n target,\n 'aria-current': ariaCurrent,\n 'aria-label': ariaLabel,\n ...rest\n}: LinkProps): JSXElement {\n const interaction = applyInteractionPolicy({\n isNative: true,\n disabled: false,\n onPress: (e: Event) => {\n const event = e as MouseEvent;\n\n // Only intercept left-click without modifiers\n // Default button to 0 if undefined (for mock events in tests)\n const button = event.button ?? 0;\n if (\n button !== 0 || // not left-click\n event.ctrlKey || // Ctrl/Cmd+click\n event.metaKey || // Cmd on Mac\n event.shiftKey || // Shift+click\n event.altKey // Alt+click\n ) {\n return; // Let browser handle it (new tab, etc.)\n }\n\n // Don't intercept external links or explicit target\n if (target) {\n return; // Let browser handle it\n }\n\n event.preventDefault();\n navigate(href);\n },\n });\n\n const props = mergeProps(rest, {\n ...interaction,\n href,\n class: className,\n rel,\n target,\n 'aria-current': ariaCurrent,\n 'aria-label': ariaLabel,\n });\n\n return <a {...props}>{children}</a>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+EA,SAAgB,KAAK,EACnB,MACA,OAAO,WACP,UACA,KACA,QACA,gBAAgB,aAChB,cAAc,WACd,GAAG,QACqB;CAwCxB,OAAO,oBAAC,KAAD;EAAG,GAVI,WAAW,MAAM;GAC7B,GA9BkB,uBAAuB;IACzC,UAAU;IACV,UAAU;IACV,UAAU,MAAa;KACrB,MAAM,QAAQ;KAKd,KADe,MAAM,UAAU,OAElB,KACX,MAAM,WACN,MAAM,WACN,MAAM,YACN,MAAM,QAEN;KAIF,IAAI,QACF;KAGF,MAAM,gBAAgB;KACtB,SAAS,KAAK;;IAEjB,CAGI;GACH;GACA,OAAO;GACP;GACA;GACA,gBAAgB;GAChB,cAAc;GACf,CAEa;EAAQ;EAAa,CAAA"}
|
package/dist/control/case.js.map
CHANGED
|
@@ -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 { normalizeBoundaryChild } from './shared';\n\nexport type MatchProps = {\n key?: string | number | null;\n when: unknown;\n children: unknown;\n};\n\nexport type CaseProps = {\n fallback?: unknown;\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(fallback: unknown): (() => 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((props.children as () => VNode)()) 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":";;;;;;AA0BA,SAAS,gBAAgB,UAA8B;
|
|
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 { normalizeBoundaryChild } from './shared';\n\nexport type MatchProps = {\n key?: string | number | null;\n when: unknown;\n children: unknown;\n};\n\nexport type CaseProps = {\n fallback?: unknown;\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(fallback: unknown): (() => 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((props.children as () => VNode)()) 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":";;;;;;AA0BA,SAAS,gBAAgB,UAA8B;CACrD,IAAI,CAAC,MAAM,QAAQ,SAAS,EAC1B,OAAO,YAAY,QAAQ,aAAa,QAAQ,EAAE,GAAG,CAAC,SAAS;CAGjE,MAAM,SAAoB,EAAE;CAC5B,KAAK,MAAM,SAAS,UAAU;EAC5B,IAAI,MAAM,QAAQ,MAAM,EAAE;GACxB,OAAO,KAAK,GAAG,gBAAgB,MAAM,CAAC;GACtC;;EAEF,OAAO,KAAK,MAAM;;CAEpB,OAAO;;AAGT,SAAgB,MAAM,QAA0B;CAC9C,IAAI,0BAA0B,EAC5B,MAAM,IAAI,MACR,+DACD;CAEH,OAAO;;AAGT,SAAS,2BAA2B,UAAyC;CAC3E,MAAM,qBAAqB,uBAAuB,SAAS;CAC3D,IAAI,sBAAsB,QAAQ,uBAAuB,OACvD,OAAO;CAET,aAAa;;AAGf,SAAS,qBACP,KACA,OACiB;CACjB,IAAI,OAAO,MACT,OAAO;CAET,OAAO,SAAS,MAAM,GAAG,OAAO,IAAI,GAAG,OAAO,IAAI;;AAGpD,SAAS,kBAAkB,UAAkC;CAC3D,MAAM,WAA0B,EAAE;CAClC,MAAM,eAAe,gBAAgB,SAAS;CAE9C,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,EAAE;GAClC,MAAM,MAAM,qBAAqB,QAAQ,KAAK,MAAM;GACpD,MAAM,SACJ,OAAO,MAAM,aAAa,mBAEpB,uBAAwB,MAAM,UAA0B,CAAC,SACrD,uBAAuB,MAAM,SAAS;GAClD,SAAS,KAAK;IACZ;IACA;IACA,MAAM,MAAM;IACb,CAAC;GACF;;EAGF,IAAI,0BAA0B,EAC5B,MAAM,IAAI,MAAM,+CAA+C;;CAInE,OAAO;;AAGT,SAAS,cAAc,OAA8B;CACnD,MAAM,UAAU,kBAAkB,MAAM,SAAS;CACjD,MAAM,WAAW,2BAA2B,MAAM,SAAS;CAK3D,MAAM,YAHqB,MACzB,gBAAgB,SAAS,SAAS,CAElB,EAAoB;CAEtC,UAAU,UAAU;CACpB,UAAU,WAAW;CAErB,OAAO;EACL,MAAM;EACN,eAAe;EAChB;;AAGH,MAAa,OAAO,0BAClB,cACD"}
|
package/dist/control/for.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"for.js","names":[],"sources":["../../src/control/for.ts"],"sourcesContent":["/**\n * For JSX primitive\n *\n * Creates a keyed child-scope boundary for efficient list rendering.\n */\n\nimport {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { DOMElement, VNode } from '../common/vnode';\nimport { createFineGrainedEffect } from '../runtime/effect';\nimport { type ForState, useForState } from '../runtime/for';\nimport { normalizeBoundaryChild } from './shared';\n\nexport type ForEachSource<T> = T[] | (() => T[]);\n\ntype ForBaseProps<T> = {\n each: ForEachSource<T>;\n fallback?: unknown;\n children: (item: T, index: () => number) => VNode;\n};\n\ntype KeyedForProps<T, K extends string | number> = ForBaseProps<T> & {\n by: (item: T, index: number) => K;\n byIndex?: never;\n};\n\ntype IndexedForProps<T> = ForBaseProps<T> & {\n by?: never;\n byIndex: true;\n};\n\nexport type ForProps<T, K extends string | number = string | number> =\n | KeyedForProps<T, K>\n | IndexedForProps<T>;\n\nfunction resolveEach<T>(each: ForEachSource<T>): T[] {\n const resolved = typeof each === 'function' ? each() : each;\n if (!Array.isArray(resolved)) {\n throw new Error('For each must resolve to an array.');\n }\n return resolved;\n}\n\nfunction resolveKeyFn<T>(\n props: ForProps<T>\n): (item: T, index: number) => string | number {\n if ('by' in props && typeof props.by === 'function') {\n return props.by;\n }\n if ('byIndex' in props && props.byIndex === true) {\n return (_item, index) => index;\n }\n throw new Error(\n '[askr] <For> requires a stable `by` key function. Use `byIndex` only as an explicit positional escape hatch.'\n );\n}\n\nfunction createForBoundary<T>(props: ForProps<T>): DOMElement {\n if ('by' in props && typeof props.by === 'function' && 'byIndex' in props) {\n throw new Error('[askr] <For> accepts either `by` or `byIndex`, not both.');\n }\n\n const byFn = resolveKeyFn(props);\n const fallback = normalizeBoundaryChild(props.fallback);\n const forState = useForState(props.each, byFn, props.children, fallback);\n\n const computeItems = () => resolveEach(forState.eachSource);\n if (!forState._sourceEffect) {\n forState._suspendSourceCommit = true;\n forState._sourceEffect = createFineGrainedEffect({\n lane: 'reactive',\n compute: computeItems,\n commit: (items) => {\n forState.currentItems = items;\n\n if (forState._suspendSourceCommit) {\n return;\n }\n\n forState._needsSourceReconcile = true;\n\n if (forState._enqueueBoundaryCommit) {\n forState._enqueueBoundaryCommit();\n return;\n }\n\n forState.parentInstance?._enqueueRun?.();\n },\n });\n forState._suspendSourceCommit = false;\n } else {\n forState._suspendSourceCommit = true;\n forState._sourceEffect.updateCompute(computeItems);\n forState._suspendSourceCommit = false;\n }\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: forState as unknown as ForState<unknown>,\n _forState: forState as unknown as ForState<unknown>,\n };\n}\n\nfunction ForPrimitive<T>(props: ForProps<T>): JSXElement {\n return createForBoundary(props) as unknown as JSXElement;\n}\n\nexport const For = markEagerControlPrimitive(\n ForPrimitive as <T, K extends string | number = string | number>(\n props: ForProps<T, K>\n ) => JSXElement\n) as <T, K extends string | number = string | number>(\n props: ForProps<T, K>\n) => JSXElement;\n"],"mappings":";;;;;;;;;;AAsCA,SAAS,YAAe,MAA6B;CACnD,MAAM,WAAW,OAAO,SAAS,aAAa,MAAM,GAAG;
|
|
1
|
+
{"version":3,"file":"for.js","names":[],"sources":["../../src/control/for.ts"],"sourcesContent":["/**\n * For JSX primitive\n *\n * Creates a keyed child-scope boundary for efficient list rendering.\n */\n\nimport {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { DOMElement, VNode } from '../common/vnode';\nimport { createFineGrainedEffect } from '../runtime/effect';\nimport { type ForState, useForState } from '../runtime/for';\nimport { normalizeBoundaryChild } from './shared';\n\nexport type ForEachSource<T> = T[] | (() => T[]);\n\ntype ForBaseProps<T> = {\n each: ForEachSource<T>;\n fallback?: unknown;\n children: (item: T, index: () => number) => VNode;\n};\n\ntype KeyedForProps<T, K extends string | number> = ForBaseProps<T> & {\n by: (item: T, index: number) => K;\n byIndex?: never;\n};\n\ntype IndexedForProps<T> = ForBaseProps<T> & {\n by?: never;\n byIndex: true;\n};\n\nexport type ForProps<T, K extends string | number = string | number> =\n | KeyedForProps<T, K>\n | IndexedForProps<T>;\n\nfunction resolveEach<T>(each: ForEachSource<T>): T[] {\n const resolved = typeof each === 'function' ? each() : each;\n if (!Array.isArray(resolved)) {\n throw new Error('For each must resolve to an array.');\n }\n return resolved;\n}\n\nfunction resolveKeyFn<T>(\n props: ForProps<T>\n): (item: T, index: number) => string | number {\n if ('by' in props && typeof props.by === 'function') {\n return props.by;\n }\n if ('byIndex' in props && props.byIndex === true) {\n return (_item, index) => index;\n }\n throw new Error(\n '[askr] <For> requires a stable `by` key function. Use `byIndex` only as an explicit positional escape hatch.'\n );\n}\n\nfunction createForBoundary<T>(props: ForProps<T>): DOMElement {\n if ('by' in props && typeof props.by === 'function' && 'byIndex' in props) {\n throw new Error('[askr] <For> accepts either `by` or `byIndex`, not both.');\n }\n\n const byFn = resolveKeyFn(props);\n const fallback = normalizeBoundaryChild(props.fallback);\n const forState = useForState(props.each, byFn, props.children, fallback);\n\n const computeItems = () => resolveEach(forState.eachSource);\n if (!forState._sourceEffect) {\n forState._suspendSourceCommit = true;\n forState._sourceEffect = createFineGrainedEffect({\n lane: 'reactive',\n compute: computeItems,\n commit: (items) => {\n forState.currentItems = items;\n\n if (forState._suspendSourceCommit) {\n return;\n }\n\n forState._needsSourceReconcile = true;\n\n if (forState._enqueueBoundaryCommit) {\n forState._enqueueBoundaryCommit();\n return;\n }\n\n forState.parentInstance?._enqueueRun?.();\n },\n });\n forState._suspendSourceCommit = false;\n } else {\n forState._suspendSourceCommit = true;\n forState._sourceEffect.updateCompute(computeItems);\n forState._suspendSourceCommit = false;\n }\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: forState as unknown as ForState<unknown>,\n _forState: forState as unknown as ForState<unknown>,\n };\n}\n\nfunction ForPrimitive<T>(props: ForProps<T>): JSXElement {\n return createForBoundary(props) as unknown as JSXElement;\n}\n\nexport const For = markEagerControlPrimitive(\n ForPrimitive as <T, K extends string | number = string | number>(\n props: ForProps<T, K>\n ) => JSXElement\n) as <T, K extends string | number = string | number>(\n props: ForProps<T, K>\n) => JSXElement;\n"],"mappings":";;;;;;;;;;AAsCA,SAAS,YAAe,MAA6B;CACnD,MAAM,WAAW,OAAO,SAAS,aAAa,MAAM,GAAG;CACvD,IAAI,CAAC,MAAM,QAAQ,SAAS,EAC1B,MAAM,IAAI,MAAM,qCAAqC;CAEvD,OAAO;;AAGT,SAAS,aACP,OAC6C;CAC7C,IAAI,QAAQ,SAAS,OAAO,MAAM,OAAO,YACvC,OAAO,MAAM;CAEf,IAAI,aAAa,SAAS,MAAM,YAAY,MAC1C,QAAQ,OAAO,UAAU;CAE3B,MAAM,IAAI,MACR,+GACD;;AAGH,SAAS,kBAAqB,OAAgC;CAC5D,IAAI,QAAQ,SAAS,OAAO,MAAM,OAAO,cAAc,aAAa,OAClE,MAAM,IAAI,MAAM,2DAA2D;CAG7E,MAAM,OAAO,aAAa,MAAM;CAChC,MAAM,WAAW,uBAAuB,MAAM,SAAS;CACvD,MAAM,WAAW,YAAY,MAAM,MAAM,MAAM,MAAM,UAAU,SAAS;CAExE,MAAM,qBAAqB,YAAY,SAAS,WAAW;CAC3D,IAAI,CAAC,SAAS,eAAe;EAC3B,SAAS,uBAAuB;EAChC,SAAS,gBAAgB,wBAAwB;GAC/C,MAAM;GACN,SAAS;GACT,SAAS,UAAU;IACjB,SAAS,eAAe;IAExB,IAAI,SAAS,sBACX;IAGF,SAAS,wBAAwB;IAEjC,IAAI,SAAS,wBAAwB;KACnC,SAAS,wBAAwB;KACjC;;IAGF,SAAS,gBAAgB,eAAe;;GAE3C,CAAC;EACF,SAAS,uBAAuB;QAC3B;EACL,SAAS,uBAAuB;EAChC,SAAS,cAAc,cAAc,aAAa;EAClD,SAAS,uBAAuB;;CAGlC,OAAO;EACL,MAAM;EACN,eAAe;EACf,WAAW;EACZ;;AAGH,SAAS,aAAgB,OAAgC;CACvD,OAAO,kBAAkB,MAAM;;AAGjC,MAAa,MAAM,0BACjB,aAGD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","names":[],"sources":["../../src/control/shared.ts"],"sourcesContent":["import { Fragment } from '../common/jsx';\nimport type { DOMElement, VNode } from '../common/vnode';\n\nexport function normalizeBoundaryChild(value: unknown): VNode | null {\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return null;\n }\n if (value.length === 1) {\n return normalizeBoundaryChild(value[0]);\n }\n return {\n type: Fragment,\n props: {\n children: value,\n },\n } as DOMElement;\n }\n\n return (value ?? null) as VNode | null;\n}\n\nexport function resolveMaybeAccessor<T>(value: T | (() => T)): T {\n return typeof value === 'function' ? (value as () => T)() : value;\n}\n"],"mappings":";;AAGA,SAAgB,uBAAuB,OAA8B;
|
|
1
|
+
{"version":3,"file":"shared.js","names":[],"sources":["../../src/control/shared.ts"],"sourcesContent":["import { Fragment } from '../common/jsx';\nimport type { DOMElement, VNode } from '../common/vnode';\n\nexport function normalizeBoundaryChild(value: unknown): VNode | null {\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return null;\n }\n if (value.length === 1) {\n return normalizeBoundaryChild(value[0]);\n }\n return {\n type: Fragment,\n props: {\n children: value,\n },\n } as DOMElement;\n }\n\n return (value ?? null) as VNode | null;\n}\n\nexport function resolveMaybeAccessor<T>(value: T | (() => T)): T {\n return typeof value === 'function' ? (value as () => T)() : value;\n}\n"],"mappings":";;AAGA,SAAgB,uBAAuB,OAA8B;CACnE,IAAI,MAAM,QAAQ,MAAM,EAAE;EACxB,IAAI,MAAM,WAAW,GACnB,OAAO;EAET,IAAI,MAAM,WAAW,GACnB,OAAO,uBAAuB,MAAM,GAAG;EAEzC,OAAO;GACL,MAAM;GACN,OAAO,EACL,UAAU,OACX;GACF;;CAGH,OAAQ,SAAS;;AAGnB,SAAgB,qBAAwB,OAAyB;CAC/D,OAAO,OAAO,UAAU,aAAc,OAAmB,GAAG"}
|
package/dist/control/show.js.map
CHANGED
|
@@ -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 { normalizeBoundaryChild, resolveMaybeAccessor } from './shared';\n\ntype ShowSource<T> = T | (() => T);\n\nexport type ShowProps<T> = {\n when: ShowSource<T>;\n fallback?: unknown;\n children: unknown | ((value: NonNullable<T>) => VNode);\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: NonNullable<T>) => VNode)(\n value as NonNullable<T>\n )\n ) as VNode;\n }\n\n const staticChild = normalizeBoundaryChild(props.children);\n return () => staticChild as VNode;\n}\n\nfunction createFallbackRenderer(fallback: unknown): (() => 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":";;;;;AAkBA,SAAS,qBACP,OAC2B;
|
|
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 { normalizeBoundaryChild, resolveMaybeAccessor } from './shared';\n\ntype ShowSource<T> = T | (() => T);\n\nexport type ShowProps<T> = {\n when: ShowSource<T>;\n fallback?: unknown;\n children: unknown | ((value: NonNullable<T>) => VNode);\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: NonNullable<T>) => VNode)(\n value as NonNullable<T>\n )\n ) as VNode;\n }\n\n const staticChild = normalizeBoundaryChild(props.children);\n return () => staticChild as VNode;\n}\n\nfunction createFallbackRenderer(fallback: unknown): (() => 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":";;;;;AAkBA,SAAS,qBACP,OAC2B;CAC3B,IAAI,OAAO,MAAM,aAAa,YAC5B,QAAQ,UACN,uBACG,MAAM,SACL,MACD,CACF;CAGL,MAAM,cAAc,uBAAuB,MAAM,SAAS;CAC1D,aAAa;;AAGf,SAAS,uBAAuB,UAAyC;CACvE,MAAM,qBAAqB,uBAAuB,SAAS;CAC3D,IAAI,sBAAsB,QAAQ,uBAAuB,OACvD,OAAO;CAET,aAAa;;AAGf,SAAS,cAAiB,OAAiC;CACzD,MAAM,gBAAgB,qBAAqB,MAAM,KAAK;CACtD,MAAM,eAAe,qBAAqB,MAAM;CAChD,MAAM,iBAAiB,uBAAuB,MAAM,SAAS;CAK7D,MAAM,YAHqB,MACzB,gBAAgB,eAAe,cAAc,eAAe,CAE5C,EAAoB;CAEtC,UAAU,gBAAgB;CAC1B,UAAU,eAAe;CACzB,UAAU,iBAAiB;CAE3B,OAAO;EACL,MAAM;EACN,eAAe;EAChB;;AAGH,MAAa,OAAO,0BAClB,cACD"}
|
package/dist/data/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/data/index.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/data/index.ts"],"mappings":";KAeY,gBAAA;AAAA,KAMA,KAAA;EACV,IAAA,EAAM,CAAA;EACN,KAAA;EACA,OAAA;EACA,UAAA;EACA,KAAA;EACA,WAAA,EAAa,gBAAA;EAEb,OAAA,IAAW,OAAA;AAAA;AAAA,KAGD,QAAA;EACV,MAAA;EACA,OAAA;EACA,KAAA;EACA,MAAA,EAAQ,OAAA;EAER,OAAA,CAAQ,KAAA,EAAO,MAAA,GAAS,OAAA,CAAQ,OAAA;EAChC,KAAA;EACA,KAAA;AAAA;AAAA,KAGG,YAAA;EACH,GAAA;EACA,KAAA,GAAQ,GAAA;IAAO,MAAA,EAAQ,WAAA;EAAA,MAAkB,OAAA,CAAQ,CAAA;EACjD,YAAA,IAAgB,IAAA,EAAM,CAAA;EACtB,SAAA,IAAa,IAAA,EAAM,CAAA,EAAG,GAAA;IAAO,GAAA;EAAA,MAAkB,OAAA;AAAA;AAAA,KAG5C,eAAA;EACH,MAAA,GAAS,KAAA,EAAO,MAAA,EAAQ,GAAA;IAAO,MAAA,EAAQ,WAAA;EAAA,MAAkB,OAAA,CAAQ,OAAA;EACjE,OAAA,IAAW,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,OAAA;EAClC,YAAA;AAAA;AAAA,iBAqjBc,WAAA,GAAA,CAAe,OAAA,EAAS,YAAA,CAAa,CAAA,IAAK,KAAA,CAAM,CAAA;AAAA,iBAyChD,UAAA,CAAW,MAAA;AAAA,iBAIX,cAAA,iBAAA,CACd,OAAA,EAAS,eAAA,CAAgB,MAAA,EAAQ,OAAA,IAChC,QAAA,CAAS,MAAA,EAAQ,OAAA"}
|
package/dist/data/index.js
CHANGED
|
@@ -1,9 +1,67 @@
|
|
|
1
1
|
import { globalScheduler } from "../runtime/scheduler.js";
|
|
2
2
|
import { markReactivePropsDirtySource, markReadableDerivedSubscribersDirty, notifyReadableReaders, recordReadableRead } from "../runtime/readable.js";
|
|
3
|
+
import { claimHookIndex, getCurrentComponentInstance } from "../runtime/component.js";
|
|
4
|
+
import { getRenderContext } from "../ssr/context.js";
|
|
3
5
|
//#region src/data/index.ts
|
|
6
|
+
const RECONCILE_MAX_ATTEMPTS = 3;
|
|
7
|
+
const RECONCILE_RETRY_DELAY_MS = 25;
|
|
8
|
+
const globalQueryCache = /* @__PURE__ */ new Map();
|
|
9
|
+
const querySlotsByInstance = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
const mutationSlotsByInstance = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
const queryCleanupRegistered = /* @__PURE__ */ new WeakSet();
|
|
12
|
+
const mutationCleanupRegistered = /* @__PURE__ */ new WeakSet();
|
|
4
13
|
function createReadableSource() {
|
|
5
14
|
return (() => void 0);
|
|
6
15
|
}
|
|
16
|
+
function getQueryCache() {
|
|
17
|
+
return getRenderContext()?.queryCache ?? globalQueryCache;
|
|
18
|
+
}
|
|
19
|
+
function getQuerySlotStore(instance) {
|
|
20
|
+
let store = querySlotsByInstance.get(instance);
|
|
21
|
+
if (!store) {
|
|
22
|
+
store = /* @__PURE__ */ new Map();
|
|
23
|
+
querySlotsByInstance.set(instance, store);
|
|
24
|
+
}
|
|
25
|
+
return store;
|
|
26
|
+
}
|
|
27
|
+
function getMutationSlotStore(instance) {
|
|
28
|
+
let store = mutationSlotsByInstance.get(instance);
|
|
29
|
+
if (!store) {
|
|
30
|
+
store = /* @__PURE__ */ new Map();
|
|
31
|
+
mutationSlotsByInstance.set(instance, store);
|
|
32
|
+
}
|
|
33
|
+
return store;
|
|
34
|
+
}
|
|
35
|
+
function ensureQueryCleanup(instance) {
|
|
36
|
+
if (queryCleanupRegistered.has(instance)) return;
|
|
37
|
+
queryCleanupRegistered.add(instance);
|
|
38
|
+
instance.cleanupFns.push(() => {
|
|
39
|
+
const slots = querySlotsByInstance.get(instance);
|
|
40
|
+
if (!slots) {
|
|
41
|
+
queryCleanupRegistered.delete(instance);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
for (const [hookIndex, slot] of slots) slot.cell.detach(instance, hookIndex);
|
|
45
|
+
slots.clear();
|
|
46
|
+
querySlotsByInstance.delete(instance);
|
|
47
|
+
queryCleanupRegistered.delete(instance);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function ensureMutationCleanup(instance) {
|
|
51
|
+
if (mutationCleanupRegistered.has(instance)) return;
|
|
52
|
+
mutationCleanupRegistered.add(instance);
|
|
53
|
+
instance.cleanupFns.push(() => {
|
|
54
|
+
const slots = mutationSlotsByInstance.get(instance);
|
|
55
|
+
if (!slots) {
|
|
56
|
+
mutationCleanupRegistered.delete(instance);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
for (const cell of slots.values()) cell.abort();
|
|
60
|
+
slots.clear();
|
|
61
|
+
mutationSlotsByInstance.delete(instance);
|
|
62
|
+
mutationCleanupRegistered.delete(instance);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
7
65
|
function notifySource(source) {
|
|
8
66
|
markReadableDerivedSubscribersDirty(source);
|
|
9
67
|
markReactivePropsDirtySource(source);
|
|
@@ -12,22 +70,26 @@ function notifySource(source) {
|
|
|
12
70
|
function isAbortError(error, signal) {
|
|
13
71
|
return signal.aborted || error instanceof Error && error.name === "AbortError" || typeof DOMException !== "undefined" && error instanceof DOMException && error.name === "AbortError";
|
|
14
72
|
}
|
|
15
|
-
const queryCache = /* @__PURE__ */ new Map();
|
|
16
73
|
function invalidateQueries(prefix, markPendingWrite) {
|
|
17
|
-
|
|
74
|
+
const cache = getQueryCache();
|
|
75
|
+
for (const [key, query] of cache) {
|
|
18
76
|
if (!key.startsWith(prefix)) continue;
|
|
19
77
|
if (markPendingWrite) query.markPendingWrite();
|
|
20
78
|
query.refresh();
|
|
21
79
|
}
|
|
22
80
|
}
|
|
23
81
|
var QueryCell = class {
|
|
24
|
-
constructor(options) {
|
|
82
|
+
constructor(options, key, cache) {
|
|
25
83
|
this.source = createReadableSource();
|
|
26
84
|
this.controller = null;
|
|
27
85
|
this.generation = 0;
|
|
28
86
|
this.startQueued = false;
|
|
29
87
|
this.pendingRefresh = null;
|
|
88
|
+
this.pendingRefreshResolve = null;
|
|
30
89
|
this.reconcileAttemptCount = 0;
|
|
90
|
+
this.destroyed = false;
|
|
91
|
+
this.ownerCount = 0;
|
|
92
|
+
this.owners = /* @__PURE__ */ new Map();
|
|
31
93
|
this.state = {
|
|
32
94
|
data: null,
|
|
33
95
|
error: null,
|
|
@@ -37,9 +99,37 @@ var QueryCell = class {
|
|
|
37
99
|
consistency: "fresh"
|
|
38
100
|
};
|
|
39
101
|
this.options = options;
|
|
102
|
+
this.key = key;
|
|
103
|
+
this.cache = cache;
|
|
40
104
|
}
|
|
41
|
-
|
|
42
|
-
|
|
105
|
+
attach(instance, hookIndex) {
|
|
106
|
+
let hooks = this.owners.get(instance);
|
|
107
|
+
if (!hooks) {
|
|
108
|
+
hooks = /* @__PURE__ */ new Set();
|
|
109
|
+
this.owners.set(instance, hooks);
|
|
110
|
+
}
|
|
111
|
+
if (hooks.has(hookIndex)) return;
|
|
112
|
+
hooks.add(hookIndex);
|
|
113
|
+
this.ownerCount += 1;
|
|
114
|
+
}
|
|
115
|
+
detach(instance, hookIndex) {
|
|
116
|
+
const hooks = this.owners.get(instance);
|
|
117
|
+
if (!hooks || !hooks.delete(hookIndex)) return;
|
|
118
|
+
this.ownerCount -= 1;
|
|
119
|
+
if (hooks.size === 0) this.owners.delete(instance);
|
|
120
|
+
if (this.ownerCount <= 0) this.destroy();
|
|
121
|
+
}
|
|
122
|
+
destroy() {
|
|
123
|
+
if (this.destroyed) return;
|
|
124
|
+
this.destroyed = true;
|
|
125
|
+
this.controller?.abort();
|
|
126
|
+
this.controller = null;
|
|
127
|
+
this.startQueued = false;
|
|
128
|
+
this.reconcileAttemptCount = 0;
|
|
129
|
+
this.ownerCount = 0;
|
|
130
|
+
this.owners.clear();
|
|
131
|
+
this.cache.delete(this.key);
|
|
132
|
+
this.finishPendingRefresh();
|
|
43
133
|
}
|
|
44
134
|
get data() {
|
|
45
135
|
recordReadableRead(this.source);
|
|
@@ -66,15 +156,17 @@ var QueryCell = class {
|
|
|
66
156
|
return this.state.consistency;
|
|
67
157
|
}
|
|
68
158
|
ensureStarted() {
|
|
69
|
-
if (this.state.data !== null || this.pendingRefresh || this.startQueued) return;
|
|
159
|
+
if (this.destroyed || this.state.data !== null || this.pendingRefresh || this.startQueued) return;
|
|
70
160
|
this.queueStart("initial");
|
|
71
161
|
}
|
|
72
162
|
refresh() {
|
|
163
|
+
if (this.destroyed) return Promise.resolve();
|
|
73
164
|
if (this.pendingRefresh) return this.pendingRefresh;
|
|
74
165
|
this.queueStart("manual");
|
|
75
166
|
return this.pendingRefresh ?? Promise.resolve();
|
|
76
167
|
}
|
|
77
168
|
markPendingWrite() {
|
|
169
|
+
if (this.destroyed) return;
|
|
78
170
|
this.setState({
|
|
79
171
|
refreshing: true,
|
|
80
172
|
stale: true,
|
|
@@ -82,18 +174,30 @@ var QueryCell = class {
|
|
|
82
174
|
});
|
|
83
175
|
}
|
|
84
176
|
queueStart(reason) {
|
|
177
|
+
if (this.destroyed) return;
|
|
85
178
|
this.startQueued = true;
|
|
86
179
|
this.pendingRefresh = new Promise((resolve) => {
|
|
180
|
+
this.pendingRefreshResolve = resolve;
|
|
87
181
|
globalScheduler.enqueue(() => {
|
|
88
182
|
this.startQueued = false;
|
|
183
|
+
if (this.destroyed) {
|
|
184
|
+
this.finishPendingRefresh();
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
89
187
|
this.start(reason).finally(() => {
|
|
90
|
-
this.
|
|
91
|
-
resolve();
|
|
188
|
+
this.finishPendingRefresh();
|
|
92
189
|
});
|
|
93
190
|
});
|
|
94
191
|
});
|
|
95
192
|
}
|
|
193
|
+
finishPendingRefresh() {
|
|
194
|
+
const resolve = this.pendingRefreshResolve;
|
|
195
|
+
this.pendingRefresh = null;
|
|
196
|
+
this.pendingRefreshResolve = null;
|
|
197
|
+
resolve?.();
|
|
198
|
+
}
|
|
96
199
|
setState(next) {
|
|
200
|
+
if (this.destroyed) return;
|
|
97
201
|
this.state = {
|
|
98
202
|
...this.state,
|
|
99
203
|
...next
|
|
@@ -101,6 +205,7 @@ var QueryCell = class {
|
|
|
101
205
|
notifySource(this.source);
|
|
102
206
|
}
|
|
103
207
|
async start(reason) {
|
|
208
|
+
if (this.destroyed) return;
|
|
104
209
|
this.generation += 1;
|
|
105
210
|
const generation = this.generation;
|
|
106
211
|
this.controller?.abort();
|
|
@@ -118,7 +223,7 @@ var QueryCell = class {
|
|
|
118
223
|
try {
|
|
119
224
|
nextData = await this.options.fetch({ signal: controller.signal });
|
|
120
225
|
} catch (error) {
|
|
121
|
-
if (this.generation !== generation || this.controller !== controller) return;
|
|
226
|
+
if (this.destroyed || this.generation !== generation || this.controller !== controller) return;
|
|
122
227
|
if (isAbortError(error, controller.signal)) {
|
|
123
228
|
this.setState({
|
|
124
229
|
loading: false,
|
|
@@ -135,7 +240,7 @@ var QueryCell = class {
|
|
|
135
240
|
});
|
|
136
241
|
return;
|
|
137
242
|
}
|
|
138
|
-
if (this.generation !== generation || this.controller !== controller) return;
|
|
243
|
+
if (this.destroyed || this.generation !== generation || this.controller !== controller) return;
|
|
139
244
|
if (!(this.options.isConsistent?.(nextData) ?? true)) {
|
|
140
245
|
this.setState({
|
|
141
246
|
data: nextData,
|
|
@@ -158,17 +263,17 @@ var QueryCell = class {
|
|
|
158
263
|
});
|
|
159
264
|
}
|
|
160
265
|
async reconcile(data) {
|
|
161
|
-
if (!(this.options.reconcile?.(data, { key: this.options.key }) ?? false)) return;
|
|
266
|
+
if (!(this.options.reconcile?.(data, { key: this.options.key }) ?? false) || this.destroyed) return;
|
|
162
267
|
this.reconcileAttemptCount += 1;
|
|
163
|
-
if (this.reconcileAttemptCount >
|
|
268
|
+
if (this.reconcileAttemptCount > RECONCILE_MAX_ATTEMPTS) {
|
|
164
269
|
this.setState({
|
|
165
270
|
consistency: "stale",
|
|
166
271
|
refreshing: false
|
|
167
272
|
});
|
|
168
273
|
return;
|
|
169
274
|
}
|
|
170
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
171
|
-
if (this.state.consistency === "fresh") return;
|
|
275
|
+
await new Promise((resolve) => setTimeout(resolve, RECONCILE_RETRY_DELAY_MS));
|
|
276
|
+
if (this.destroyed || this.state.consistency === "fresh") return;
|
|
172
277
|
await this.refresh();
|
|
173
278
|
}
|
|
174
279
|
};
|
|
@@ -186,6 +291,11 @@ var MutationCell = class {
|
|
|
186
291
|
this.affects = options.affects;
|
|
187
292
|
this.afterSuccess = options.afterSuccess;
|
|
188
293
|
}
|
|
294
|
+
setOptions(options) {
|
|
295
|
+
this.action = options.action;
|
|
296
|
+
this.affects = options.affects;
|
|
297
|
+
this.afterSuccess = options.afterSuccess;
|
|
298
|
+
}
|
|
189
299
|
get status() {
|
|
190
300
|
recordReadableRead(this.source);
|
|
191
301
|
return this.state.status;
|
|
@@ -271,21 +381,53 @@ var MutationCell = class {
|
|
|
271
381
|
}
|
|
272
382
|
};
|
|
273
383
|
function createQuery(options) {
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
384
|
+
const instance = getCurrentComponentInstance();
|
|
385
|
+
const cache = getQueryCache();
|
|
386
|
+
if (!instance) {
|
|
387
|
+
let cell = cache.get(options.key);
|
|
388
|
+
if (!cell) {
|
|
389
|
+
cell = new QueryCell(options, options.key, cache);
|
|
390
|
+
cache.set(options.key, cell);
|
|
391
|
+
cell.ensureStarted();
|
|
392
|
+
}
|
|
393
|
+
return cell;
|
|
278
394
|
}
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
395
|
+
const hookIndex = claimHookIndex(instance, "query");
|
|
396
|
+
ensureQueryCleanup(instance);
|
|
397
|
+
const slotStore = getQuerySlotStore(instance);
|
|
398
|
+
const existingSlot = slotStore.get(hookIndex);
|
|
399
|
+
if (existingSlot && existingSlot.key === options.key) return existingSlot.cell;
|
|
400
|
+
if (existingSlot) existingSlot.cell.detach(instance, hookIndex);
|
|
401
|
+
let cell = cache.get(options.key);
|
|
402
|
+
if (!cell) {
|
|
403
|
+
cell = new QueryCell(options, options.key, cache);
|
|
404
|
+
cache.set(options.key, cell);
|
|
405
|
+
cell.ensureStarted();
|
|
406
|
+
}
|
|
407
|
+
slotStore.set(hookIndex, {
|
|
408
|
+
key: options.key,
|
|
409
|
+
cell
|
|
410
|
+
});
|
|
411
|
+
cell.attach(instance, hookIndex);
|
|
412
|
+
return cell;
|
|
283
413
|
}
|
|
284
414
|
function invalidate(prefix) {
|
|
285
415
|
invalidateQueries(prefix, false);
|
|
286
416
|
}
|
|
287
417
|
function createMutation(options) {
|
|
288
|
-
|
|
418
|
+
const instance = getCurrentComponentInstance();
|
|
419
|
+
if (!instance) return new MutationCell(options);
|
|
420
|
+
const hookIndex = claimHookIndex(instance, "mutation");
|
|
421
|
+
ensureMutationCleanup(instance);
|
|
422
|
+
const slotStore = getMutationSlotStore(instance);
|
|
423
|
+
const existing = slotStore.get(hookIndex);
|
|
424
|
+
if (existing) {
|
|
425
|
+
existing.setOptions(options);
|
|
426
|
+
return existing;
|
|
427
|
+
}
|
|
428
|
+
const created = new MutationCell(options);
|
|
429
|
+
slotStore.set(hookIndex, created);
|
|
430
|
+
return created;
|
|
289
431
|
}
|
|
290
432
|
//#endregion
|
|
291
433
|
export { createMutation, createQuery, invalidate };
|
package/dist/data/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/data/index.ts"],"sourcesContent":["import { globalScheduler } from '../runtime/scheduler';\nimport {\n markReadableDerivedSubscribersDirty,\n markReactivePropsDirtySource,\n notifyReadableReaders,\n recordReadableRead,\n type ReadableSource,\n} from '../runtime/readable';\n\nexport type QueryConsistency =\n | 'fresh'\n | 'stale'\n | 'refreshing'\n | 'pending-write';\n\nexport type Query<T> = {\n data: T | null;\n error: unknown | null;\n loading: boolean;\n refreshing: boolean;\n stale: boolean;\n consistency: QueryConsistency;\n\n refresh(): Promise<void>;\n};\n\nexport type Mutation<TInput, TResult> = {\n status: 'idle' | 'pending' | 'success' | 'error';\n pending: boolean;\n error: unknown | null;\n result: TResult | null;\n\n execute(input: TInput): Promise<TResult>;\n abort(): void;\n reset(): void;\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: unknown | null;\n loading: boolean;\n refreshing: boolean;\n stale: boolean;\n consistency: QueryConsistency;\n};\n\ntype MutationState<TResult> = {\n status: 'idle' | 'pending' | 'success' | 'error';\n error: unknown | null;\n result: TResult | null;\n};\n\nfunction createReadableSource(): ReadableSource<unknown> {\n return (() => undefined) as ReadableSource<unknown>;\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\nconst queryCache = new Map<string, QueryCell<unknown>>();\n\nfunction invalidateQueries(prefix: string, markPendingWrite: boolean): void {\n for (const [key, query] of queryCache) {\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> implements Query<T> {\n private readonly source = createReadableSource();\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 reconcileAttemptCount = 0;\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 };\n\n constructor(options: QueryOptions<T>) {\n this.options = options;\n }\n\n setOptions(options: QueryOptions<T>): void {\n this.options = options;\n }\n\n get data(): T | null {\n recordReadableRead(this.source);\n return this.state.data;\n }\n\n get error(): unknown | 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 ensureStarted(): void {\n if (this.state.data !== null || this.pendingRefresh || this.startQueued) {\n return;\n }\n\n this.queueStart('initial');\n }\n\n refresh(): Promise<void> {\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 this.setState({\n refreshing: true,\n stale: true,\n consistency: 'pending-write',\n });\n }\n\n private queueStart(\n reason: 'initial' | 'manual' | 'invalidate' | 'pending-write'\n ): void {\n this.startQueued = true;\n this.pendingRefresh = new Promise<void>((resolve) => {\n globalScheduler.enqueue(() => {\n this.startQueued = false;\n void this.start(reason).finally(() => {\n this.pendingRefresh = null;\n resolve();\n });\n });\n });\n }\n\n private setState(next: Partial<QueryState<T>>): void {\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 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 });\n\n let nextData: T;\n try {\n nextData = await this.options.fetch({ signal: controller.signal });\n } catch (error) {\n if (this.generation !== generation || this.controller !== controller) {\n return;\n }\n\n if (isAbortError(error, controller.signal)) {\n this.setState({ loading: false, refreshing: false });\n return;\n }\n\n this.setState({\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n error,\n });\n return;\n }\n\n if (this.generation !== generation || this.controller !== controller) {\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 });\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 });\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) {\n return;\n }\n\n this.reconcileAttemptCount += 1;\n if (this.reconcileAttemptCount > 3) {\n this.setState({ consistency: 'stale', refreshing: false });\n return;\n }\n\n await new Promise<void>((resolve) => setTimeout(resolve, 25));\n if (this.state.consistency === 'fresh') {\n return;\n }\n\n await this.refresh();\n }\n}\n\nclass MutationCell<TInput, TResult> implements Mutation<TInput, TResult> {\n private readonly source = createReadableSource();\n private readonly action: MutationOptions<TInput, TResult>['action'];\n private readonly affects?: MutationOptions<TInput, TResult>['affects'];\n private readonly afterSuccess?: MutationOptions<\n TInput,\n TResult\n >['afterSuccess'];\n private controller: AbortController | null = null;\n private generation = 0;\n\n private state: MutationState<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 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(): unknown | 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<MutationState<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({ status: 'error', error });\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 this.generation += 1;\n this.controller?.abort();\n this.controller = null;\n this.setState({ status: 'idle', error: 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>(options: QueryOptions<T>): Query<T> {\n const existing = queryCache.get(options.key) as QueryCell<T> | undefined;\n if (existing) {\n existing.setOptions(options);\n return existing;\n }\n\n const created = new QueryCell(options);\n queryCache.set(options.key, created as QueryCell<unknown>);\n created.ensureStarted();\n return created;\n}\n\nexport function invalidate(prefix: string): void {\n invalidateQueries(prefix, false);\n}\n\nexport function createMutation<TInput, TResult>(\n options: MutationOptions<TInput, TResult>\n): Mutation<TInput, TResult> {\n return new MutationCell(options);\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';\n\nexport type QueryConsistency =\n | 'fresh'\n | 'stale'\n | 'refreshing'\n | 'pending-write';\n\nexport type Query<T> = {\n data: T | null;\n error: unknown | null;\n loading: boolean;\n refreshing: boolean;\n stale: boolean;\n consistency: QueryConsistency;\n\n refresh(): Promise<void>;\n};\n\nexport type Mutation<TInput, TResult> = {\n status: 'idle' | 'pending' | 'success' | 'error';\n pending: boolean;\n error: unknown | null;\n result: TResult | null;\n\n execute(input: TInput): Promise<TResult>;\n abort(): void;\n reset(): void;\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: unknown | null;\n loading: boolean;\n refreshing: boolean;\n stale: boolean;\n consistency: QueryConsistency;\n};\n\ntype MutationState<TResult> = {\n status: 'idle' | 'pending' | 'success' | 'error';\n error: unknown | null;\n result: TResult | null;\n};\n\ntype QuerySlot = {\n key: string;\n cell: QueryCell<unknown>;\n};\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 invalidateQueries(prefix: string, markPendingWrite: boolean): void {\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> implements Query<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\n private state: QueryState<T> = {\n data: null,\n error: null,\n loading: true,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\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 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 get data(): T | null {\n recordReadableRead(this.source);\n return this.state.data;\n }\n\n get error(): unknown | 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 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 this.setState({\n refreshing: true,\n stale: true,\n consistency: 'pending-write',\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 });\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({ loading: false, refreshing: false });\n return;\n }\n\n this.setState({\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n 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 });\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 });\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({ consistency: 'stale', refreshing: false });\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> implements Mutation<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: MutationState<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(): unknown | 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<MutationState<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({ status: 'error', error });\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 this.generation += 1;\n this.controller?.abort();\n this.controller = null;\n this.setState({ status: 'idle', error: 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>(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 }\n return cell;\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 return existingSlot.cell as QueryCell<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 }\n\n slotStore.set(hookIndex, {\n key: options.key,\n cell: cell as QueryCell<unknown>,\n });\n cell.attach(instance, hookIndex);\n return cell;\n}\n\nexport function invalidate(prefix: string): void {\n invalidateQueries(prefix, false);\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);\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;\n }\n\n const created = new MutationCell(options);\n slotStore.set(hookIndex, created as MutationCell<unknown, unknown>);\n return created;\n}\n"],"mappings":"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"}
|