@askrjs/askr 0.0.39 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bench/components/benchmark-row.d.ts.map +1 -1
- package/dist/bench/components/benchmark-row.js.map +1 -1
- package/dist/bench/components/benchmark-table.js.map +1 -1
- package/dist/benchmark.d.ts.map +1 -1
- package/dist/benchmark.js +2 -2
- package/dist/benchmark.js.map +1 -1
- package/dist/bin/askr-ssg.d.ts.map +1 -1
- package/dist/bin/askr-ssg.js.map +1 -1
- package/dist/boot/index.d.ts +9 -6
- package/dist/boot/index.d.ts.map +1 -1
- package/dist/boot/index.js +210 -75
- package/dist/boot/index.js.map +1 -1
- package/dist/common/attr-names.js +17 -0
- package/dist/common/attr-names.js.map +1 -0
- package/dist/common/component.d.ts.map +1 -1
- package/dist/common/control.d.ts.map +1 -1
- package/dist/common/control.js.map +1 -1
- package/dist/common/env.js.map +1 -1
- package/dist/common/jsx.d.ts.map +1 -1
- package/dist/common/jsx.js.map +1 -1
- package/dist/common/promise.js +8 -0
- package/dist/common/promise.js.map +1 -0
- package/dist/common/props.d.ts +286 -1
- package/dist/common/props.d.ts.map +1 -1
- package/dist/common/router-internal.js +6 -0
- package/dist/common/router-internal.js.map +1 -0
- package/dist/common/router.d.ts +45 -36
- package/dist/common/router.d.ts.map +1 -1
- package/dist/common/ssr-errors.d.ts.map +1 -1
- package/dist/common/ssr-errors.js.map +1 -1
- package/dist/common/ssr.d.ts +1 -0
- package/dist/common/ssr.d.ts.map +1 -1
- package/dist/common/ssr.js +6 -0
- package/dist/common/ssr.js.map +1 -0
- package/dist/common/vnode.d.ts +2 -1
- package/dist/common/vnode.d.ts.map +1 -1
- package/dist/common/vnode.js.map +1 -1
- package/dist/components/error-boundary.d.ts +7 -4
- package/dist/components/error-boundary.d.ts.map +1 -1
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/link.d.ts +2 -1
- package/dist/components/link.d.ts.map +1 -1
- package/dist/components/link.js +10 -1
- package/dist/components/link.js.map +1 -1
- package/dist/control/case.d.ts +4 -2
- package/dist/control/case.d.ts.map +1 -1
- package/dist/control/case.js.map +1 -1
- package/dist/control/for.d.ts +2 -1
- package/dist/control/for.d.ts.map +1 -1
- package/dist/control/for.js.map +1 -1
- package/dist/control/shared.d.ts +9 -0
- package/dist/control/shared.d.ts.map +1 -0
- package/dist/control/shared.js.map +1 -1
- package/dist/control/show.d.ts +4 -3
- package/dist/control/show.d.ts.map +1 -1
- package/dist/control/show.js.map +1 -1
- package/dist/data/index.d.ts +94 -14
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +65 -14
- 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.map +1 -1
- package/dist/foundations/interactions/dismissable.d.ts +9 -3
- package/dist/foundations/interactions/dismissable.d.ts.map +1 -1
- package/dist/foundations/interactions/dismissable.js.map +1 -1
- package/dist/foundations/interactions/focusable.d.ts.map +1 -1
- package/dist/foundations/interactions/focusable.js.map +1 -1
- package/dist/foundations/interactions/hoverable.d.ts.map +1 -1
- package/dist/foundations/interactions/hoverable.js.map +1 -1
- package/dist/foundations/interactions/interaction-policy.d.ts +1 -1
- package/dist/foundations/interactions/interaction-policy.d.ts.map +1 -1
- package/dist/foundations/interactions/interaction-policy.js +3 -3
- package/dist/foundations/interactions/interaction-policy.js.map +1 -1
- package/dist/foundations/interactions/pressable.d.ts.map +1 -1
- package/dist/foundations/interactions/pressable.js.map +1 -1
- package/dist/foundations/interactions/roving-focus.d.ts.map +1 -1
- package/dist/foundations/interactions/roving-focus.js +8 -8
- package/dist/foundations/interactions/roving-focus.js.map +1 -1
- package/dist/foundations/state/controllable.d.ts.map +1 -1
- package/dist/foundations/state/controllable.js.map +1 -1
- package/dist/foundations/structures/collection.d.ts.map +1 -1
- package/dist/foundations/structures/collection.js.map +1 -1
- package/dist/foundations/structures/layer.d.ts.map +1 -1
- package/dist/foundations/structures/layer.js.map +1 -1
- package/dist/foundations/structures/layout.d.ts +4 -2
- package/dist/foundations/structures/layout.d.ts.map +1 -1
- package/dist/foundations/structures/layout.js.map +1 -1
- package/dist/foundations/structures/portal.d.ts +9 -25
- package/dist/foundations/structures/portal.d.ts.map +1 -1
- package/dist/foundations/structures/portal.js +98 -17
- package/dist/foundations/structures/portal.js.map +1 -1
- package/dist/foundations/structures/presence.d.ts +4 -3
- package/dist/foundations/structures/presence.d.ts.map +1 -1
- package/dist/foundations/structures/presence.js +2 -2
- package/dist/foundations/structures/presence.js.map +1 -1
- package/dist/foundations/structures/slot.d.ts +2 -1
- package/dist/foundations/structures/slot.d.ts.map +1 -1
- package/dist/foundations/structures/slot.js.map +1 -1
- package/dist/foundations/utilities/aria.d.ts.map +1 -1
- package/dist/foundations/utilities/aria.js.map +1 -1
- package/dist/foundations/utilities/compose-handlers.d.ts.map +1 -1
- package/dist/foundations/utilities/compose-handlers.js.map +1 -1
- package/dist/foundations/utilities/compose-ref.d.ts.map +1 -1
- package/dist/foundations/utilities/compose-ref.js.map +1 -1
- package/dist/foundations/utilities/event-types.d.ts.map +1 -1
- package/dist/foundations/utilities/merge-props.js.map +1 -1
- package/dist/foundations/utilities/use-id.d.ts.map +1 -1
- package/dist/foundations/utilities/use-id.js.map +1 -1
- package/dist/fx/fx.d.ts.map +1 -1
- package/dist/fx/fx.js.map +1 -1
- package/dist/fx/noop.js.map +1 -1
- package/dist/fx/timing.d.ts +5 -4
- package/dist/fx/timing.d.ts.map +1 -1
- package/dist/fx/timing.js +7 -4
- package/dist/fx/timing.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/jsx/types.d.ts +3 -3
- package/dist/jsx/types.d.ts.map +1 -1
- package/dist/jsx/utils.d.ts.map +1 -1
- package/dist/jsx/utils.js.map +1 -1
- package/dist/jsx-dev-runtime.d.ts +6 -2
- package/dist/jsx-dev-runtime.d.ts.map +1 -1
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.d.ts +16 -6
- package/dist/jsx-runtime.d.ts.map +1 -1
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/renderer/children.js.map +1 -1
- package/dist/renderer/cleanup.js +40 -13
- package/dist/renderer/cleanup.js.map +1 -1
- package/dist/renderer/dom.js +163 -63
- package/dist/renderer/dom.js.map +1 -1
- package/dist/renderer/evaluate.js +9 -6
- package/dist/renderer/evaluate.js.map +1 -1
- package/dist/renderer/fastpath.js.map +1 -1
- package/dist/renderer/for-commit.js +1 -0
- package/dist/renderer/for-commit.js.map +1 -1
- package/dist/renderer/index.js.map +1 -1
- package/dist/renderer/keyed.js.map +1 -1
- package/dist/renderer/reconcile.js +34 -0
- package/dist/renderer/reconcile.js.map +1 -1
- package/dist/renderer/utils.js +34 -3
- package/dist/renderer/utils.js.map +1 -1
- package/dist/router/index.d.ts +2 -2
- package/dist/router/match.js +16 -2
- package/dist/router/match.js.map +1 -1
- package/dist/router/navigate.d.ts +9 -1
- package/dist/router/navigate.d.ts.map +1 -1
- package/dist/router/navigate.js +235 -81
- package/dist/router/navigate.js.map +1 -1
- package/dist/router/policy.d.ts +7 -7
- package/dist/router/policy.d.ts.map +1 -1
- package/dist/router/policy.js +5 -7
- package/dist/router/policy.js.map +1 -1
- package/dist/router/route-context.js.map +1 -1
- package/dist/router/route.d.ts +20 -9
- package/dist/router/route.d.ts.map +1 -1
- package/dist/router/route.js +95 -29
- package/dist/router/route.js.map +1 -1
- package/dist/runtime/child-scope.d.ts.map +1 -1
- package/dist/runtime/child-scope.js +5 -1
- package/dist/runtime/child-scope.js.map +1 -1
- package/dist/runtime/component.d.ts +5 -2
- package/dist/runtime/component.d.ts.map +1 -1
- package/dist/runtime/component.js +85 -25
- package/dist/runtime/component.js.map +1 -1
- package/dist/runtime/context.d.ts +5 -2
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +5 -2
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/control.d.ts.map +1 -1
- package/dist/runtime/control.js.map +1 -1
- package/dist/runtime/derive.d.ts.map +1 -1
- package/dist/runtime/derive.js +3 -1
- 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 +17 -11
- package/dist/runtime/effect.js.map +1 -1
- package/dist/runtime/events.js +43 -1
- package/dist/runtime/events.js.map +1 -1
- package/dist/runtime/execution-model.js.map +1 -1
- package/dist/runtime/fastlane.js +2 -23
- package/dist/runtime/fastlane.js.map +1 -1
- package/dist/runtime/for-bench.d.ts.map +1 -1
- package/dist/runtime/for-bench.js.map +1 -1
- package/dist/runtime/for.d.ts +1 -1
- package/dist/runtime/for.d.ts.map +1 -1
- package/dist/runtime/for.js +36 -12
- package/dist/runtime/for.js.map +1 -1
- package/dist/runtime/operations.d.ts +3 -13
- package/dist/runtime/operations.d.ts.map +1 -1
- package/dist/runtime/operations.js +47 -39
- package/dist/runtime/operations.js.map +1 -1
- package/dist/runtime/perf-metrics.js.map +1 -1
- package/dist/runtime/readable.d.ts +1 -0
- package/dist/runtime/readable.d.ts.map +1 -1
- package/dist/runtime/readable.js +6 -1
- package/dist/runtime/readable.js.map +1 -1
- package/dist/runtime/resource-cell.js +13 -2
- package/dist/runtime/resource-cell.js.map +1 -1
- package/dist/runtime/scheduler.d.ts.map +1 -1
- package/dist/runtime/scheduler.js +8 -4
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/selector.d.ts.map +1 -1
- package/dist/runtime/selector.js +8 -2
- package/dist/runtime/selector.js.map +1 -1
- package/dist/runtime/snapshot-source.d.ts.map +1 -1
- package/dist/runtime/snapshot-source.js.map +1 -1
- package/dist/runtime/ssr-bridge.js.map +1 -1
- package/dist/runtime/state.d.ts +4 -3
- package/dist/runtime/state.d.ts.map +1 -1
- package/dist/runtime/state.js.map +1 -1
- package/dist/ssg/batch-render.js +4 -8
- package/dist/ssg/batch-render.js.map +1 -1
- package/dist/ssg/create-static-gen.d.ts +10 -2
- package/dist/ssg/create-static-gen.d.ts.map +1 -1
- package/dist/ssg/create-static-gen.js +5 -4
- 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/resolve-ssg-data.js +54 -12
- package/dist/ssg/resolve-ssg-data.js.map +1 -1
- package/dist/ssg/route-utils.js.map +1 -1
- package/dist/ssg/types.d.ts +8 -7
- package/dist/ssg/types.d.ts.map +1 -1
- package/dist/ssg/write-static-files.js.map +1 -1
- package/dist/ssr/attrs.js +3 -2
- package/dist/ssr/attrs.js.map +1 -1
- package/dist/ssr/context.d.ts +1 -0
- package/dist/ssr/context.d.ts.map +1 -1
- package/dist/ssr/context.js +1 -0
- package/dist/ssr/context.js.map +1 -1
- package/dist/ssr/errors.d.ts.map +1 -1
- package/dist/ssr/escape.js.map +1 -1
- package/dist/ssr/index.d.ts +8 -12
- package/dist/ssr/index.d.ts.map +1 -1
- package/dist/ssr/index.js +55 -30
- package/dist/ssr/index.js.map +1 -1
- package/dist/ssr/render-keys.js +15 -4
- package/dist/ssr/render-keys.js.map +1 -1
- package/dist/ssr/render-resolved.js +33 -0
- package/dist/ssr/render-resolved.js.map +1 -0
- package/dist/ssr/sink.js.map +1 -1
- package/dist/ssr/types.d.ts.map +1 -1
- package/dist/ssr/verify-hydration.js +5 -6
- package/dist/ssr/verify-hydration.js.map +1 -1
- package/package.json +12 -4
package/dist/data/index.d.ts
CHANGED
|
@@ -1,23 +1,103 @@
|
|
|
1
1
|
//#region src/data/index.d.ts
|
|
2
2
|
type QueryConsistency = 'fresh' | 'stale' | 'refreshing' | 'pending-write';
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
error: unknown | null;
|
|
6
|
-
loading: boolean;
|
|
7
|
-
refreshing: boolean;
|
|
8
|
-
stale: boolean;
|
|
9
|
-
consistency: QueryConsistency;
|
|
3
|
+
type QueryStaleReason = 'aborted' | 'error' | 'inconsistent';
|
|
4
|
+
type QueryControls = {
|
|
10
5
|
refresh(): Promise<void>;
|
|
11
6
|
};
|
|
12
|
-
type
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
type QueryLoading = {
|
|
8
|
+
data: null;
|
|
9
|
+
error: null;
|
|
10
|
+
loading: true;
|
|
11
|
+
refreshing: false;
|
|
12
|
+
stale: false;
|
|
13
|
+
consistency: 'fresh';
|
|
14
|
+
staleReason: null;
|
|
15
|
+
};
|
|
16
|
+
type QueryFresh<T> = {
|
|
17
|
+
data: T;
|
|
18
|
+
error: null;
|
|
19
|
+
loading: false;
|
|
20
|
+
refreshing: false;
|
|
21
|
+
stale: false;
|
|
22
|
+
consistency: 'fresh';
|
|
23
|
+
staleReason: null;
|
|
24
|
+
};
|
|
25
|
+
type QueryRefreshing<T> = {
|
|
26
|
+
data: T;
|
|
27
|
+
error: null;
|
|
28
|
+
loading: false;
|
|
29
|
+
refreshing: true;
|
|
30
|
+
stale: true;
|
|
31
|
+
consistency: 'refreshing';
|
|
32
|
+
staleReason: null;
|
|
33
|
+
};
|
|
34
|
+
type QueryPendingWrite<T> = {
|
|
35
|
+
data: T;
|
|
36
|
+
error: null;
|
|
37
|
+
loading: false;
|
|
38
|
+
refreshing: true;
|
|
39
|
+
stale: true;
|
|
40
|
+
consistency: 'pending-write';
|
|
41
|
+
staleReason: null;
|
|
42
|
+
};
|
|
43
|
+
type QueryStaleValue<T> = {
|
|
44
|
+
data: T;
|
|
45
|
+
error: null;
|
|
46
|
+
loading: false;
|
|
47
|
+
refreshing: false;
|
|
48
|
+
stale: true;
|
|
49
|
+
consistency: 'stale';
|
|
50
|
+
staleReason: 'aborted' | 'inconsistent';
|
|
51
|
+
};
|
|
52
|
+
type QueryStaleErrorWithValue<T> = {
|
|
53
|
+
data: T;
|
|
54
|
+
error: {};
|
|
55
|
+
loading: false;
|
|
56
|
+
refreshing: false;
|
|
57
|
+
stale: true;
|
|
58
|
+
consistency: 'stale';
|
|
59
|
+
staleReason: 'error';
|
|
60
|
+
};
|
|
61
|
+
type QueryStaleError = {
|
|
62
|
+
data: null;
|
|
63
|
+
error: {};
|
|
64
|
+
loading: false;
|
|
65
|
+
refreshing: false;
|
|
66
|
+
stale: true;
|
|
67
|
+
consistency: 'stale';
|
|
68
|
+
staleReason: 'error';
|
|
69
|
+
};
|
|
70
|
+
type Query<T extends {}> = QueryControls & (QueryLoading | QueryFresh<T> | QueryRefreshing<T> | QueryPendingWrite<T> | QueryStaleValue<T> | QueryStaleErrorWithValue<T> | QueryStaleError);
|
|
71
|
+
type MutationControls<TInput, TResult> = {
|
|
17
72
|
execute(input: TInput): Promise<TResult>;
|
|
18
73
|
abort(): void;
|
|
19
74
|
reset(): void;
|
|
20
75
|
};
|
|
76
|
+
type MutationIdle = {
|
|
77
|
+
status: 'idle';
|
|
78
|
+
pending: false;
|
|
79
|
+
error: null;
|
|
80
|
+
result: null;
|
|
81
|
+
};
|
|
82
|
+
type MutationPending = {
|
|
83
|
+
status: 'pending';
|
|
84
|
+
pending: true;
|
|
85
|
+
error: null;
|
|
86
|
+
result: null;
|
|
87
|
+
};
|
|
88
|
+
type MutationSuccess<TResult> = {
|
|
89
|
+
status: 'success';
|
|
90
|
+
pending: false;
|
|
91
|
+
error: null;
|
|
92
|
+
result: TResult;
|
|
93
|
+
};
|
|
94
|
+
type MutationError = {
|
|
95
|
+
status: 'error';
|
|
96
|
+
pending: false;
|
|
97
|
+
error: {};
|
|
98
|
+
result: null;
|
|
99
|
+
};
|
|
100
|
+
type Mutation<TInput, TResult> = MutationControls<TInput, TResult> & (MutationIdle | MutationPending | MutationSuccess<TResult> | MutationError);
|
|
21
101
|
type QueryOptions<T> = {
|
|
22
102
|
key: string;
|
|
23
103
|
fetch: (ctx: {
|
|
@@ -35,9 +115,9 @@ type MutationOptions<TInput, TResult> = {
|
|
|
35
115
|
affects?: (input: TInput, result: TResult) => string[];
|
|
36
116
|
afterSuccess?: 'invalidate';
|
|
37
117
|
};
|
|
38
|
-
declare function createQuery<T>(options: QueryOptions<T>): Query<T>;
|
|
118
|
+
declare function createQuery<T extends {}>(options: QueryOptions<T>): Query<T>;
|
|
39
119
|
declare function invalidate(prefix: string): void;
|
|
40
120
|
declare function createMutation<TInput, TResult>(options: MutationOptions<TInput, TResult>): Mutation<TInput, TResult>;
|
|
41
121
|
//#endregion
|
|
42
|
-
export { Mutation, Query, QueryConsistency, createMutation, createQuery, invalidate };
|
|
122
|
+
export { Mutation, Query, QueryConsistency, QueryStaleReason, createMutation, createQuery, invalidate };
|
|
43
123
|
//# sourceMappingURL=index.d.ts.map
|
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":";KAgBY,gBAAA;AAAA,KAMA,gBAAA;AAAA,KAEP,aAAA;EACH,OAAA,IAAW,OAAO;AAAA;AAAA,KAGf,YAAA;EACH,IAAA;EACA,KAAA;EACA,OAAA;EACA,UAAA;EACA,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,KAGG,UAAA;EACH,IAAA,EAAM,CAAC;EACP,KAAA;EACA,OAAA;EACA,UAAA;EACA,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,KAGG,eAAA;EACH,IAAA,EAAM,CAAC;EACP,KAAA;EACA,OAAA;EACA,UAAA;EACA,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,KAGG,iBAAA;EACH,IAAA,EAAM,CAAC;EACP,KAAA;EACA,OAAA;EACA,UAAA;EACA,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,KAGG,eAAA;EACH,IAAA,EAAM,CAAC;EACP,KAAA;EACA,OAAA;EACA,UAAA;EACA,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,KAGG,wBAAA;EACH,IAAA,EAAM,CAAC;EACP,KAAA;EACA,OAAA;EACA,UAAA;EACA,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,KAGG,eAAA;EACH,IAAA;EACA,KAAA;EACA,OAAA;EACA,UAAA;EACA,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,KAGU,KAAA,iBAAsB,aAAA,IAE5B,YAAA,GACA,UAAA,CAAW,CAAA,IACX,eAAA,CAAgB,CAAA,IAChB,iBAAA,CAAkB,CAAA,IAClB,eAAA,CAAgB,CAAA,IAChB,wBAAA,CAAyB,CAAA,IACzB,eAAA;AAAA,KAGD,gBAAA;EACH,OAAA,CAAQ,KAAA,EAAO,MAAA,GAAS,OAAA,CAAQ,OAAA;EAChC,KAAA;EACA,KAAA;AAAA;AAAA,KAGG,YAAA;EACH,MAAA;EACA,OAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,KAGG,eAAA;EACH,MAAA;EACA,OAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,KAGG,eAAA;EACH,MAAA;EACA,OAAA;EACA,KAAA;EACA,MAAA,EAAQ,OAAO;AAAA;AAAA,KAGZ,aAAA;EACH,MAAA;EACA,OAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,KAGU,QAAA,oBAA4B,gBAAA,CAAiB,MAAA,EAAQ,OAAA,KAC9D,YAAA,GAAe,eAAA,GAAkB,eAAA,CAAgB,OAAA,IAAW,aAAA;AAAA,KAQ1D,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,iBAkpBc,WAAA,cAAA,CAA0B,OAAA,EAAS,YAAA,CAAa,CAAA,IAAK,KAAA,CAAM,CAAA;AAAA,iBA8C3D,UAAA,CAAW,MAAc;AAAA,iBAIzB,cAAA,iBAAA,CACd,OAAA,EAAS,eAAA,CAAgB,MAAA,EAAQ,OAAA,IAChC,QAAA,CAAS,MAAA,EAAQ,OAAA"}
|
package/dist/data/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { logger } from "../dev/logger.js";
|
|
1
2
|
import { globalScheduler } from "../runtime/scheduler.js";
|
|
2
3
|
import { markReactivePropsDirtySource, markReadableDerivedSubscribersDirty, notifyReadableReaders, recordReadableRead } from "../runtime/readable.js";
|
|
3
4
|
import { claimHookIndex, getCurrentComponentInstance } from "../runtime/component.js";
|
|
@@ -70,6 +71,9 @@ function notifySource(source) {
|
|
|
70
71
|
function isAbortError(error, signal) {
|
|
71
72
|
return signal.aborted || error instanceof Error && error.name === "AbortError" || typeof DOMException !== "undefined" && error instanceof DOMException && error.name === "AbortError";
|
|
72
73
|
}
|
|
74
|
+
function normalizeAsyncDataError(error, fallbackMessage) {
|
|
75
|
+
return error ?? new Error(fallbackMessage);
|
|
76
|
+
}
|
|
73
77
|
function invalidateQueries(prefix, markPendingWrite) {
|
|
74
78
|
const cache = getQueryCache();
|
|
75
79
|
for (const [key, query] of cache) {
|
|
@@ -90,13 +94,15 @@ var QueryCell = class {
|
|
|
90
94
|
this.destroyed = false;
|
|
91
95
|
this.ownerCount = 0;
|
|
92
96
|
this.owners = /* @__PURE__ */ new Map();
|
|
97
|
+
this.warnedDefinitionConflictKeys = /* @__PURE__ */ new Set();
|
|
93
98
|
this.state = {
|
|
94
99
|
data: null,
|
|
95
100
|
error: null,
|
|
96
101
|
loading: true,
|
|
97
102
|
refreshing: false,
|
|
98
103
|
stale: false,
|
|
99
|
-
consistency: "fresh"
|
|
104
|
+
consistency: "fresh",
|
|
105
|
+
staleReason: null
|
|
100
106
|
};
|
|
101
107
|
this.options = options;
|
|
102
108
|
this.key = key;
|
|
@@ -119,6 +125,15 @@ var QueryCell = class {
|
|
|
119
125
|
if (hooks.size === 0) this.owners.delete(instance);
|
|
120
126
|
if (this.ownerCount <= 0) this.destroy();
|
|
121
127
|
}
|
|
128
|
+
warnOnConflictingDefinition(options) {
|
|
129
|
+
const conflicts = this.getDefinitionConflicts(options);
|
|
130
|
+
if (conflicts.length === 0) return;
|
|
131
|
+
const conflictKey = conflicts.join(",");
|
|
132
|
+
if (this.warnedDefinitionConflictKeys.has(conflictKey)) return;
|
|
133
|
+
this.warnedDefinitionConflictKeys.add(conflictKey);
|
|
134
|
+
const callbackLabel = conflicts.length === 1 ? `callback \`${conflicts[0]}\`` : `callbacks ${conflicts.map((field) => `\`${field}\``).join(", ")}`;
|
|
135
|
+
logger.warn(`[askr] Conflicting shared query definition for key "${this.key}". Shared queries are canonical by key, so reuse the same ${callbackLabel} for every reader of that key.`);
|
|
136
|
+
}
|
|
122
137
|
destroy() {
|
|
123
138
|
if (this.destroyed) return;
|
|
124
139
|
this.destroyed = true;
|
|
@@ -131,6 +146,13 @@ var QueryCell = class {
|
|
|
131
146
|
this.cache.delete(this.key);
|
|
132
147
|
this.finishPendingRefresh();
|
|
133
148
|
}
|
|
149
|
+
getDefinitionConflicts(options) {
|
|
150
|
+
const conflicts = [];
|
|
151
|
+
if (this.options.fetch !== options.fetch) conflicts.push("fetch");
|
|
152
|
+
if (this.options.isConsistent !== options.isConsistent) conflicts.push("isConsistent");
|
|
153
|
+
if (this.options.reconcile !== options.reconcile) conflicts.push("reconcile");
|
|
154
|
+
return conflicts;
|
|
155
|
+
}
|
|
134
156
|
get data() {
|
|
135
157
|
recordReadableRead(this.source);
|
|
136
158
|
return this.state.data;
|
|
@@ -155,6 +177,10 @@ var QueryCell = class {
|
|
|
155
177
|
recordReadableRead(this.source);
|
|
156
178
|
return this.state.consistency;
|
|
157
179
|
}
|
|
180
|
+
get staleReason() {
|
|
181
|
+
recordReadableRead(this.source);
|
|
182
|
+
return this.state.staleReason;
|
|
183
|
+
}
|
|
158
184
|
ensureStarted() {
|
|
159
185
|
if (this.destroyed || this.state.data !== null || this.pendingRefresh || this.startQueued) return;
|
|
160
186
|
this.queueStart("initial");
|
|
@@ -167,10 +193,14 @@ var QueryCell = class {
|
|
|
167
193
|
}
|
|
168
194
|
markPendingWrite() {
|
|
169
195
|
if (this.destroyed) return;
|
|
196
|
+
if (this.state.data === null) return;
|
|
170
197
|
this.setState({
|
|
198
|
+
loading: false,
|
|
199
|
+
error: null,
|
|
171
200
|
refreshing: true,
|
|
172
201
|
stale: true,
|
|
173
|
-
consistency: "pending-write"
|
|
202
|
+
consistency: "pending-write",
|
|
203
|
+
staleReason: null
|
|
174
204
|
});
|
|
175
205
|
}
|
|
176
206
|
queueStart(reason) {
|
|
@@ -217,7 +247,8 @@ var QueryCell = class {
|
|
|
217
247
|
refreshing: hasData,
|
|
218
248
|
stale: hasData,
|
|
219
249
|
consistency: reason === "pending-write" ? "pending-write" : hasData ? "refreshing" : "fresh",
|
|
220
|
-
error: null
|
|
250
|
+
error: null,
|
|
251
|
+
staleReason: null
|
|
221
252
|
});
|
|
222
253
|
let nextData;
|
|
223
254
|
try {
|
|
@@ -225,9 +256,20 @@ var QueryCell = class {
|
|
|
225
256
|
} catch (error) {
|
|
226
257
|
if (this.destroyed || this.generation !== generation || this.controller !== controller) return;
|
|
227
258
|
if (isAbortError(error, controller.signal)) {
|
|
228
|
-
this.setState({
|
|
259
|
+
this.setState(hasData ? {
|
|
229
260
|
loading: false,
|
|
230
|
-
refreshing: false
|
|
261
|
+
refreshing: false,
|
|
262
|
+
stale: true,
|
|
263
|
+
consistency: "stale",
|
|
264
|
+
error: null,
|
|
265
|
+
staleReason: "aborted"
|
|
266
|
+
} : {
|
|
267
|
+
loading: true,
|
|
268
|
+
refreshing: false,
|
|
269
|
+
stale: false,
|
|
270
|
+
consistency: "fresh",
|
|
271
|
+
error: null,
|
|
272
|
+
staleReason: null
|
|
231
273
|
});
|
|
232
274
|
return;
|
|
233
275
|
}
|
|
@@ -236,7 +278,8 @@ var QueryCell = class {
|
|
|
236
278
|
refreshing: false,
|
|
237
279
|
stale: true,
|
|
238
280
|
consistency: "stale",
|
|
239
|
-
error
|
|
281
|
+
error: normalizeAsyncDataError(error, "Unknown query error"),
|
|
282
|
+
staleReason: "error"
|
|
240
283
|
});
|
|
241
284
|
return;
|
|
242
285
|
}
|
|
@@ -247,7 +290,8 @@ var QueryCell = class {
|
|
|
247
290
|
loading: false,
|
|
248
291
|
refreshing: false,
|
|
249
292
|
stale: true,
|
|
250
|
-
consistency: "stale"
|
|
293
|
+
consistency: "stale",
|
|
294
|
+
staleReason: "inconsistent"
|
|
251
295
|
});
|
|
252
296
|
await this.reconcile(nextData);
|
|
253
297
|
return;
|
|
@@ -259,7 +303,8 @@ var QueryCell = class {
|
|
|
259
303
|
refreshing: false,
|
|
260
304
|
stale: false,
|
|
261
305
|
consistency: "fresh",
|
|
262
|
-
error: null
|
|
306
|
+
error: null,
|
|
307
|
+
staleReason: null
|
|
263
308
|
});
|
|
264
309
|
}
|
|
265
310
|
async reconcile(data) {
|
|
@@ -268,7 +313,8 @@ var QueryCell = class {
|
|
|
268
313
|
if (this.reconcileAttemptCount > RECONCILE_MAX_ATTEMPTS) {
|
|
269
314
|
this.setState({
|
|
270
315
|
consistency: "stale",
|
|
271
|
-
refreshing: false
|
|
316
|
+
refreshing: false,
|
|
317
|
+
staleReason: "inconsistent"
|
|
272
318
|
});
|
|
273
319
|
return;
|
|
274
320
|
}
|
|
@@ -344,7 +390,7 @@ var MutationCell = class {
|
|
|
344
390
|
}
|
|
345
391
|
this.setState({
|
|
346
392
|
status: "error",
|
|
347
|
-
error
|
|
393
|
+
error: normalizeAsyncDataError(error, "Unknown mutation error")
|
|
348
394
|
});
|
|
349
395
|
throw error;
|
|
350
396
|
}
|
|
@@ -361,12 +407,14 @@ var MutationCell = class {
|
|
|
361
407
|
return result;
|
|
362
408
|
}
|
|
363
409
|
abort() {
|
|
410
|
+
if (this.state.status !== "pending") return;
|
|
364
411
|
this.generation += 1;
|
|
365
412
|
this.controller?.abort();
|
|
366
413
|
this.controller = null;
|
|
367
414
|
this.setState({
|
|
368
415
|
status: "idle",
|
|
369
|
-
error: null
|
|
416
|
+
error: null,
|
|
417
|
+
result: null
|
|
370
418
|
});
|
|
371
419
|
}
|
|
372
420
|
reset() {
|
|
@@ -389,21 +437,24 @@ function createQuery(options) {
|
|
|
389
437
|
cell = new QueryCell(options, options.key, cache);
|
|
390
438
|
cache.set(options.key, cell);
|
|
391
439
|
cell.ensureStarted();
|
|
392
|
-
}
|
|
440
|
+
} else cell.warnOnConflictingDefinition(options);
|
|
393
441
|
return cell;
|
|
394
442
|
}
|
|
395
443
|
const hookIndex = claimHookIndex(instance, "query");
|
|
396
444
|
ensureQueryCleanup(instance);
|
|
397
445
|
const slotStore = getQuerySlotStore(instance);
|
|
398
446
|
const existingSlot = slotStore.get(hookIndex);
|
|
399
|
-
if (existingSlot && existingSlot.key === options.key)
|
|
447
|
+
if (existingSlot && existingSlot.key === options.key) {
|
|
448
|
+
existingSlot.cell.warnOnConflictingDefinition(options);
|
|
449
|
+
return existingSlot.cell;
|
|
450
|
+
}
|
|
400
451
|
if (existingSlot) existingSlot.cell.detach(instance, hookIndex);
|
|
401
452
|
let cell = cache.get(options.key);
|
|
402
453
|
if (!cell) {
|
|
403
454
|
cell = new QueryCell(options, options.key, cache);
|
|
404
455
|
cache.set(options.key, cell);
|
|
405
456
|
cell.ensureStarted();
|
|
406
|
-
}
|
|
457
|
+
} else cell.warnOnConflictingDefinition(options);
|
|
407
458
|
slotStore.set(hookIndex, {
|
|
408
459
|
key: options.key,
|
|
409
460
|
cell
|
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 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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"}
|
|
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';\n\nexport type QueryConsistency =\n | 'fresh'\n | 'stale'\n | 'refreshing'\n | 'pending-write';\n\nexport type QueryStaleReason = 'aborted' | 'error' | 'inconsistent';\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 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): 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) 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":"invariant.js","names":[],"sources":["../../src/dev/invariant.ts"],"sourcesContent":["/**\n * Invariant assertion utilities for correctness checking\n * Production-safe: invariants are enforced at build-time or with minimal overhead\n *\n * Core principle: fail fast when invariants are violated\n * All functions throw descriptive errors for debugging\n */\n\n/**\n * Assert a condition; throw with context if false\n * @internal\n */\nexport function invariant(\n condition: boolean,\n message: string,\n context?: Record<string, unknown>\n): asserts condition {\n if (!condition) {\n const contextStr = context ? '\\n' + JSON.stringify(context, null, 2) : '';\n throw new Error(`[Askr Invariant] ${message}${contextStr}`);\n }\n}\n\n/**\n * Assert object property exists and has correct type\n * @internal\n */\nexport function assertProperty<T extends object, K extends keyof T>(\n obj: T,\n prop: K,\n expectedType?: string\n): asserts obj is T & Required<Pick<T, K>> {\n invariant(prop in obj, `Object missing required property '${String(prop)}'`, {\n object: obj,\n });\n\n if (expectedType) {\n const actualType = typeof obj[prop];\n invariant(\n actualType === expectedType,\n `Property '${String(prop)}' has type '${actualType}', expected '${expectedType}'`,\n { value: obj[prop], expectedType }\n );\n }\n}\n\n/**\n * Assert a reference is not null/undefined\n * @internal\n */\nexport function assertDefined<T>(\n value: T | null | undefined,\n message: string\n): asserts value is T {\n invariant(value !== null && value !== undefined, message, { value });\n}\n\n/**\n * Assert a task runs exactly once atomically\n * Useful for verifying lifecycle events fire precisely when expected\n * @internal\n */\nexport class Once {\n private called = false;\n private calledAt: number | null = null;\n readonly name: string;\n\n constructor(name: string) {\n this.name = name;\n }\n\n check(): boolean {\n return this.called;\n }\n\n mark(): void {\n invariant(\n !this.called,\n `${this.name} called multiple times (previously at ${this.calledAt}ms)`,\n { now: Date.now() }\n );\n this.called = true;\n this.calledAt = Date.now();\n }\n\n reset(): void {\n this.called = false;\n this.calledAt = null;\n }\n}\n\n/**\n * Assert a value falls in an enumerated set\n * @internal\n */\nexport function assertEnum<T extends readonly unknown[]>(\n value: unknown,\n allowedValues: T,\n fieldName: string\n): asserts value is T[number] {\n invariant(\n allowedValues.includes(value),\n `${fieldName} must be one of [${allowedValues.join(', ')}], got ${JSON.stringify(value)}`,\n { value, allowed: allowedValues }\n );\n}\n\n/**\n * Assert execution context (scheduler, component, etc)\n * @internal\n */\nexport function assertContext(\n actual: unknown,\n expected: unknown,\n contextName: string\n): asserts actual is typeof expected {\n invariant(\n actual === expected,\n `Invalid ${contextName} context. Expected ${expected}, got ${actual}`,\n { expected, actual }\n );\n}\n\n/**\n * Assert scheduling precondition (not reentering, not during render, etc)\n * @internal\n */\nexport function assertSchedulingPrecondition(\n condition: boolean,\n violationMessage: string\n): asserts condition {\n invariant(condition, `[Scheduler Precondition] ${violationMessage}`);\n}\n\n/**\n * Assert state precondition\n * @internal\n */\nexport function assertStatePrecondition(\n condition: boolean,\n violationMessage: string\n): asserts condition {\n invariant(condition, `[State Precondition] ${violationMessage}`);\n}\n\n/**\n * Verify AbortController lifecycle\n * @internal\n */\nexport function assertAbortControllerState(\n signal: AbortSignal,\n expectedAborted: boolean,\n context: string\n): void {\n invariant(\n signal.aborted === expectedAborted,\n `AbortSignal ${expectedAborted ? 'should be' : 'should not be'} aborted in ${context}`,\n { actual: signal.aborted, expected: expectedAborted }\n );\n}\n\n/**\n * Guard: throw if callback is null when it shouldn't be\n * Used for notifyUpdate, event handlers, etc.\n * @internal\n */\nexport function assertCallbackAvailable<\n T extends (...args: unknown[]) => unknown,\n>(callback: T | null | undefined, callbackName: string): asserts callback is T {\n invariant(\n callback !== null && callback !== undefined,\n `${callbackName} callback is required but not available`,\n { callback }\n );\n}\n\n/**\n * Verify evaluation generation prevents stale evaluations\n * @internal\n */\nexport function assertEvaluationGeneration(\n current: number,\n latest: number,\n context: string\n): void {\n invariant(\n current === latest,\n `Stale evaluation generation in ${context}: current ${current}, latest ${latest}`,\n { current, latest }\n );\n}\n\n/**\n * Verify mounted flag state\n * @internal\n */\nexport function assertMountedState(\n mounted: boolean,\n expectedMounted: boolean,\n context: string\n): void {\n invariant(\n mounted === expectedMounted,\n `Invalid mounted state in ${context}: expected ${expectedMounted}, got ${mounted}`,\n { mounted, expected: expectedMounted }\n );\n}\n\n/**\n * Verify no null target when rendering\n * @internal\n */\nexport function assertRenderTarget(\n target: Element | null,\n context: string\n): asserts target is Element {\n invariant(target !== null, `Cannot render in ${context}: target is null`, {\n target,\n });\n}\n"],"mappings":";;;;;;;;;;;;AAYA,SAAgB,UACd,WACA,SACA,SACmB;CACnB,IAAI,CAAC,WAAW;EACd,MAAM,aAAa,UAAU,OAAO,KAAK,UAAU,SAAS,MAAM,
|
|
1
|
+
{"version":3,"file":"invariant.js","names":[],"sources":["../../src/dev/invariant.ts"],"sourcesContent":["/**\n * Invariant assertion utilities for correctness checking\n * Production-safe: invariants are enforced at build-time or with minimal overhead\n *\n * Core principle: fail fast when invariants are violated\n * All functions throw descriptive errors for debugging\n */\n\n/**\n * Assert a condition; throw with context if false\n * @internal\n */\nexport function invariant(\n condition: boolean,\n message: string,\n context?: Record<string, unknown>\n): asserts condition {\n if (!condition) {\n const contextStr = context ? '\\n' + JSON.stringify(context, null, 2) : '';\n throw new Error(`[Askr Invariant] ${message}${contextStr}`);\n }\n}\n\n/**\n * Assert object property exists and has correct type\n * @internal\n */\nexport function assertProperty<T extends object, K extends keyof T>(\n obj: T,\n prop: K,\n expectedType?: string\n): asserts obj is T & Required<Pick<T, K>> {\n invariant(prop in obj, `Object missing required property '${String(prop)}'`, {\n object: obj,\n });\n\n if (expectedType) {\n const actualType = typeof obj[prop];\n invariant(\n actualType === expectedType,\n `Property '${String(prop)}' has type '${actualType}', expected '${expectedType}'`,\n { value: obj[prop], expectedType }\n );\n }\n}\n\n/**\n * Assert a reference is not null/undefined\n * @internal\n */\nexport function assertDefined<T>(\n value: T | null | undefined,\n message: string\n): asserts value is T {\n invariant(value !== null && value !== undefined, message, { value });\n}\n\n/**\n * Assert a task runs exactly once atomically\n * Useful for verifying lifecycle events fire precisely when expected\n * @internal\n */\nexport class Once {\n private called = false;\n private calledAt: number | null = null;\n readonly name: string;\n\n constructor(name: string) {\n this.name = name;\n }\n\n check(): boolean {\n return this.called;\n }\n\n mark(): void {\n invariant(\n !this.called,\n `${this.name} called multiple times (previously at ${this.calledAt}ms)`,\n { now: Date.now() }\n );\n this.called = true;\n this.calledAt = Date.now();\n }\n\n reset(): void {\n this.called = false;\n this.calledAt = null;\n }\n}\n\n/**\n * Assert a value falls in an enumerated set\n * @internal\n */\nexport function assertEnum<T extends readonly unknown[]>(\n value: unknown,\n allowedValues: T,\n fieldName: string\n): asserts value is T[number] {\n invariant(\n allowedValues.includes(value),\n `${fieldName} must be one of [${allowedValues.join(', ')}], got ${JSON.stringify(value)}`,\n { value, allowed: allowedValues }\n );\n}\n\n/**\n * Assert execution context (scheduler, component, etc)\n * @internal\n */\nexport function assertContext(\n actual: unknown,\n expected: unknown,\n contextName: string\n): asserts actual is typeof expected {\n invariant(\n actual === expected,\n `Invalid ${contextName} context. Expected ${expected}, got ${actual}`,\n { expected, actual }\n );\n}\n\n/**\n * Assert scheduling precondition (not reentering, not during render, etc)\n * @internal\n */\nexport function assertSchedulingPrecondition(\n condition: boolean,\n violationMessage: string\n): asserts condition {\n invariant(condition, `[Scheduler Precondition] ${violationMessage}`);\n}\n\n/**\n * Assert state precondition\n * @internal\n */\nexport function assertStatePrecondition(\n condition: boolean,\n violationMessage: string\n): asserts condition {\n invariant(condition, `[State Precondition] ${violationMessage}`);\n}\n\n/**\n * Verify AbortController lifecycle\n * @internal\n */\nexport function assertAbortControllerState(\n signal: AbortSignal,\n expectedAborted: boolean,\n context: string\n): void {\n invariant(\n signal.aborted === expectedAborted,\n `AbortSignal ${expectedAborted ? 'should be' : 'should not be'} aborted in ${context}`,\n { actual: signal.aborted, expected: expectedAborted }\n );\n}\n\n/**\n * Guard: throw if callback is null when it shouldn't be\n * Used for notifyUpdate, event handlers, etc.\n * @internal\n */\nexport function assertCallbackAvailable<\n T extends (...args: unknown[]) => unknown,\n>(callback: T | null | undefined, callbackName: string): asserts callback is T {\n invariant(\n callback !== null && callback !== undefined,\n `${callbackName} callback is required but not available`,\n { callback }\n );\n}\n\n/**\n * Verify evaluation generation prevents stale evaluations\n * @internal\n */\nexport function assertEvaluationGeneration(\n current: number,\n latest: number,\n context: string\n): void {\n invariant(\n current === latest,\n `Stale evaluation generation in ${context}: current ${current}, latest ${latest}`,\n { current, latest }\n );\n}\n\n/**\n * Verify mounted flag state\n * @internal\n */\nexport function assertMountedState(\n mounted: boolean,\n expectedMounted: boolean,\n context: string\n): void {\n invariant(\n mounted === expectedMounted,\n `Invalid mounted state in ${context}: expected ${expectedMounted}, got ${mounted}`,\n { mounted, expected: expectedMounted }\n );\n}\n\n/**\n * Verify no null target when rendering\n * @internal\n */\nexport function assertRenderTarget(\n target: Element | null,\n context: string\n): asserts target is Element {\n invariant(target !== null, `Cannot render in ${context}: target is null`, {\n target,\n });\n}\n"],"mappings":";;;;;;;;;;;;AAYA,SAAgB,UACd,WACA,SACA,SACmB;CACnB,IAAI,CAAC,WAAW;EACd,MAAM,aAAa,UAAU,OAAO,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI;EACvE,MAAM,IAAI,MAAM,oBAAoB,UAAU,YAAY;CAC5D;AACF;;;;;AA0GA,SAAgB,6BACd,WACA,kBACmB;CACnB,UAAU,WAAW,4BAA4B,kBAAkB;AACrE"}
|
package/dist/dev/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","names":[],"sources":["../../src/dev/logger.ts"],"sourcesContent":["/**\n * Centralized logger interface\n * - Keeps production builds silent for debug/warn/info messages\n * - Ensures consistent behavior across the codebase\n * - Protects against missing `console` in some environments\n */\n\nimport { isProductionEnvironment } from '../common/env';\n\nfunction callConsole(method: string, args: unknown[]): void {\n const c = typeof console !== 'undefined' ? (console as unknown) : undefined;\n if (!c) return;\n const fn = (c as Record<string, unknown>)[method];\n if (typeof fn === 'function') {\n try {\n (fn as (...a: unknown[]) => unknown).apply(console, args as unknown[]);\n } catch {\n // ignore logging errors\n }\n }\n}\n\nexport const logger = {\n debug: (...args: unknown[]) => {\n if (isProductionEnvironment()) return;\n callConsole('debug', args);\n },\n\n info: (...args: unknown[]) => {\n if (isProductionEnvironment()) return;\n callConsole('info', args);\n },\n\n warn: (...args: unknown[]) => {\n if (isProductionEnvironment()) return;\n callConsole('warn', args);\n },\n\n error: (...args: unknown[]) => {\n callConsole('error', args);\n },\n};\n"],"mappings":";;;;;;;;AASA,SAAS,YAAY,QAAgB,MAAuB;CAC1D,MAAM,IAAI,OAAO,YAAY,cAAe,UAAsB;CAClE,IAAI,CAAC,GAAG;CACR,MAAM,KAAM,EAA8B;CAC1C,IAAI,OAAO,OAAO,YAChB,IAAI;EACF,GAAqC,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"logger.js","names":[],"sources":["../../src/dev/logger.ts"],"sourcesContent":["/**\n * Centralized logger interface\n * - Keeps production builds silent for debug/warn/info messages\n * - Ensures consistent behavior across the codebase\n * - Protects against missing `console` in some environments\n */\n\nimport { isProductionEnvironment } from '../common/env';\n\nfunction callConsole(method: string, args: unknown[]): void {\n const c = typeof console !== 'undefined' ? (console as unknown) : undefined;\n if (!c) return;\n const fn = (c as Record<string, unknown>)[method];\n if (typeof fn === 'function') {\n try {\n (fn as (...a: unknown[]) => unknown).apply(console, args as unknown[]);\n } catch {\n // ignore logging errors\n }\n }\n}\n\nexport const logger = {\n debug: (...args: unknown[]) => {\n if (isProductionEnvironment()) return;\n callConsole('debug', args);\n },\n\n info: (...args: unknown[]) => {\n if (isProductionEnvironment()) return;\n callConsole('info', args);\n },\n\n warn: (...args: unknown[]) => {\n if (isProductionEnvironment()) return;\n callConsole('warn', args);\n },\n\n error: (...args: unknown[]) => {\n callConsole('error', args);\n },\n};\n"],"mappings":";;;;;;;;AASA,SAAS,YAAY,QAAgB,MAAuB;CAC1D,MAAM,IAAI,OAAO,YAAY,cAAe,UAAsB;CAClE,IAAI,CAAC,GAAG;CACR,MAAM,KAAM,EAA8B;CAC1C,IAAI,OAAO,OAAO,YAChB,IAAI;EACF,GAAqC,MAAM,SAAS,IAAiB;CACvE,QAAQ,CAER;AAEJ;AAEA,MAAa,SAAS;CACpB,QAAQ,GAAG,SAAoB;EAC7B,IAAI,wBAAwB,GAAG;EAC/B,YAAY,SAAS,IAAI;CAC3B;CAEA,OAAO,GAAG,SAAoB;EAC5B,IAAI,wBAAwB,GAAG;EAC/B,YAAY,QAAQ,IAAI;CAC1B;CAEA,OAAO,GAAG,SAAoB;EAC5B,IAAI,wBAAwB,GAAG;EAC/B,YAAY,QAAQ,IAAI;CAC1B;CAEA,QAAQ,GAAG,SAAoB;EAC7B,YAAY,SAAS,IAAI;CAC3B;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon.d.ts","names":[],"sources":["../../../src/foundations/icon/icon.tsx"],"mappings":";;;;iBAOgB,eAAA,CAAgB,KAAA,YAAiB,KAAA,IAAS,
|
|
1
|
+
{"version":3,"file":"icon.d.ts","names":[],"sources":["../../../src/foundations/icon/icon.tsx"],"mappings":";;;;iBAOgB,eAAA,CAAgB,KAAA,YAAiB,KAAA,IAAS,aAAa;AAAA,iBAOvD,sBAAA,CAAuB,IAAqB;AAAA,iBAK5C,uBAAA,CAAwB,IAAqB;AAAA,iBAO7C,8BAAA,CACd,WAAA,UACA,SAAA,EAAW,aAAa;AAAA,iBAYV,kBAAA,CACd,KAA2C,WAA3B,eAAe;AAAA,iBAUjB,aAAA,CAAA,GACX,MAAA,EAAQ,KAAK;AAAA,iBAMF,oBAAA,CAAA;EACd,IAAA;EACA,WAAA;EACA,KAAA;EACA,KAAA;EACA,KAAA;EACA;AAAA,GACC,IAAA,CACD,SAAA;;;;;;;;;;;;;;;;;;;;;iBA4Cc,QAAA,CAAA;EACd,IAAA;EACA,WAAA;EACA,KAAA;EACA,KAAA;EACA,KAAA,EAAO,SAAA;EACP,KAAA;EACA,QAAA;EACA,QAAA;EACA,GAAA;EAAA,GACG;AAAA,GACF,SAAA,GAAY,UAAA"}
|
|
@@ -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;
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon.types.d.ts","names":[],"sources":["../../../src/foundations/icon/icon.types.ts"],"mappings":";;;;KAIY,aAAA;AAAA,KAEA,eAAA,GAAkB,
|
|
1
|
+
{"version":3,"file":"icon.types.d.ts","names":[],"sources":["../../../src/foundations/icon/icon.types.ts"],"mappings":";;;;KAIY,aAAA;AAAA,KAEA,eAAA,GAAkB,MAAM;AAAA,KAExB,YAAA;EACV,IAAA;EACA,WAAA;EACA,KAAA;EACA,KAAA;EACA,KAAA;EACA,KAAA,YAAiB,eAAe;EAChC,QAAA;AAAA;AAAA,KAGU,SAAA,GAAY,IAAA,CACtB,KAAA,0HAaA,YAAA;EACE,QAAA;EACA,GAAA,GAAM,GAAA,CAAI,aAAA;AAAA"}
|
|
@@ -16,7 +16,10 @@ import { KeyboardLikeEvent, PointerLikeEvent } from "../utilities/event-types.js
|
|
|
16
16
|
* DESIGN:
|
|
17
17
|
* - Returns standard event handler props (onKeyDown, onPointerDownCapture)
|
|
18
18
|
* - Composable via mergeProps with other foundations
|
|
19
|
-
* - Caller provides node reference for outside detection
|
|
19
|
+
* - Caller provides the protected node reference for outside detection
|
|
20
|
+
* - Returned capture props must be attached to a surface that can observe both
|
|
21
|
+
* the protected subtree and the outside interaction path (for example, an
|
|
22
|
+
* overlay or wrapper around the protected node)
|
|
20
23
|
* - Single onDismiss callback for all dismiss triggers
|
|
21
24
|
*
|
|
22
25
|
* PIT OF SUCCESS:
|
|
@@ -32,7 +35,9 @@ import { KeyboardLikeEvent, PointerLikeEvent } from "../utilities/event-types.js
|
|
|
32
35
|
* onDismiss: () => close()
|
|
33
36
|
* });
|
|
34
37
|
*
|
|
35
|
-
* <div
|
|
38
|
+
* <div {...props}>
|
|
39
|
+
* <div ref={elementRef}>Content</div>
|
|
40
|
+
* </div>
|
|
36
41
|
*
|
|
37
42
|
* MISUSE EXAMPLE (PREVENTED):
|
|
38
43
|
* ❌ Can't forget to check disabled - checked inside dismissable
|
|
@@ -41,7 +46,8 @@ import { KeyboardLikeEvent, PointerLikeEvent } from "../utilities/event-types.js
|
|
|
41
46
|
*/
|
|
42
47
|
interface DismissableOptions {
|
|
43
48
|
/**
|
|
44
|
-
* Reference to the element for outside click detection
|
|
49
|
+
* Reference to the protected element for outside click detection. Attach the
|
|
50
|
+
* returned capture props to a surface that encloses this node.
|
|
45
51
|
*/
|
|
46
52
|
node?: Node | null;
|
|
47
53
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dismissable.d.ts","names":[],"sources":["../../../src/foundations/interactions/dismissable.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"dismissable.d.ts","names":[],"sources":["../../../src/foundations/interactions/dismissable.ts"],"mappings":";;;;;;AA4CA;;;;;;;;;;AAe4C;AAQ5C;;;;;;;;;;;;;;;;;;;;;;;;;AAUuD;;;;UAjCtC,kBAAA;;;;;EAKf,IAAA,GAAO,IAAI;;;;EAKX,QAAA;;;;EAKA,SAAA,IAAa,OAAA;AAAA;AAAA,iBAQC,WAAA,CAAA;EAAc,IAAA;EAAM,QAAA;EAAU;AAAA,GAAa,kBAAA;iBAC/B,iBAAA;4BASW,gBAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dismissable.js","names":[],"sources":["../../../src/foundations/interactions/dismissable.ts"],"sourcesContent":["/**\n * dismissable\n *\n * THE dismissal primitive. Handles Escape key and outside interactions.\n *\n * INVARIANTS:\n * 1. Returns props that compose via mergeProps (no factories)\n * 2. Disabled state respected exactly once, here\n * 3. No side effects - pure props generation\n * 4. Outside detection requires explicit node reference\n * 5. This is the ONLY dismissal primitive - do not create alternatives\n *\n * DESIGN:\n * - Returns standard event handler props (onKeyDown, onPointerDownCapture)\n * - Composable via mergeProps with other foundations\n * - Caller provides node reference for outside detection\n * - Single onDismiss callback for all dismiss triggers\n *\n * PIT OF SUCCESS:\n * ✓ Can't accidentally bypass (only way to get dismiss behavior)\n * ✓ Can't duplicate (disabled checked once)\n * ✓ Composes via mergeProps (standard props)\n * ✓ Wrong usage is hard (no factories to misuse)\n *\n * USAGE:\n * const props = dismissable({\n * node: elementRef,\n * disabled: false,\n * onDismiss: () => close()\n * });\n *\n * <div ref={elementRef}
|
|
1
|
+
{"version":3,"file":"dismissable.js","names":[],"sources":["../../../src/foundations/interactions/dismissable.ts"],"sourcesContent":["/**\n * dismissable\n *\n * THE dismissal primitive. Handles Escape key and outside interactions.\n *\n * INVARIANTS:\n * 1. Returns props that compose via mergeProps (no factories)\n * 2. Disabled state respected exactly once, here\n * 3. No side effects - pure props generation\n * 4. Outside detection requires explicit node reference\n * 5. This is the ONLY dismissal primitive - do not create alternatives\n *\n * DESIGN:\n * - Returns standard event handler props (onKeyDown, onPointerDownCapture)\n * - Composable via mergeProps with other foundations\n * - Caller provides the protected node reference for outside detection\n * - Returned capture props must be attached to a surface that can observe both\n * the protected subtree and the outside interaction path (for example, an\n * overlay or wrapper around the protected node)\n * - Single onDismiss callback for all dismiss triggers\n *\n * PIT OF SUCCESS:\n * ✓ Can't accidentally bypass (only way to get dismiss behavior)\n * ✓ Can't duplicate (disabled checked once)\n * ✓ Composes via mergeProps (standard props)\n * ✓ Wrong usage is hard (no factories to misuse)\n *\n * USAGE:\n * const props = dismissable({\n * node: elementRef,\n * disabled: false,\n * onDismiss: () => close()\n * });\n *\n * <div {...props}>\n * <div ref={elementRef}>Content</div>\n * </div>\n *\n * MISUSE EXAMPLE (PREVENTED):\n * ❌ Can't forget to check disabled - checked inside dismissable\n * ❌ Can't create custom escape handler - this is the only one\n * ❌ Can't bypass via direct event listeners - mergeProps composes correctly\n */\n\nexport interface DismissableOptions {\n /**\n * Reference to the protected element for outside click detection. Attach the\n * returned capture props to a surface that encloses this node.\n */\n node?: Node | null;\n\n /**\n * Whether dismiss is disabled\n */\n disabled?: boolean;\n\n /**\n * Called when dismiss is triggered (Escape or outside click)\n */\n onDismiss?: (trigger: 'escape' | 'outside') => void;\n}\n\nimport type {\n KeyboardLikeEvent,\n PointerLikeEvent,\n} from '../utilities/event-types';\n\nexport function dismissable({ node, disabled, onDismiss }: DismissableOptions) {\n function handleKeyDown(e: KeyboardLikeEvent) {\n if (disabled) return;\n if (e.key === 'Escape') {\n e.preventDefault?.();\n e.stopPropagation?.();\n onDismiss?.('escape');\n }\n }\n\n function handlePointerDownCapture(e: PointerLikeEvent) {\n if (disabled) return;\n\n const target = e.target;\n if (!(target instanceof Node)) return;\n\n // If no node provided, can't detect outside clicks\n if (!node) return;\n\n // Check if click is outside the protected node\n if (!node.contains(target)) {\n onDismiss?.('outside');\n }\n }\n\n return {\n onKeyDown: handleKeyDown,\n // Use capture phase to catch events before they bubble\n onPointerDownCapture: handlePointerDownCapture,\n };\n}\n"],"mappings":";AAmEA,SAAgB,YAAY,EAAE,MAAM,UAAU,aAAiC;CAC7E,SAAS,cAAc,GAAsB;EAC3C,IAAI,UAAU;EACd,IAAI,EAAE,QAAQ,UAAU;GACtB,EAAE,iBAAiB;GACnB,EAAE,kBAAkB;GACpB,YAAY,QAAQ;EACtB;CACF;CAEA,SAAS,yBAAyB,GAAqB;EACrD,IAAI,UAAU;EAEd,MAAM,SAAS,EAAE;EACjB,IAAI,EAAE,kBAAkB,OAAO;EAG/B,IAAI,CAAC,MAAM;EAGX,IAAI,CAAC,KAAK,SAAS,MAAM,GACvB,YAAY,SAAS;CAEzB;CAEA,OAAO;EACL,WAAW;EAEX,sBAAsB;CACxB;AACF"}
|