@effect-app/vue 4.0.0-beta.99 → 4.0.0
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/CHANGELOG.md +2701 -0
- package/dist/atomQuery.d.ts +120 -0
- package/dist/atomQuery.d.ts.map +1 -0
- package/dist/atomQuery.js +434 -0
- package/dist/commander.d.ts +318 -43
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +593 -81
- package/dist/confirm.d.ts +5 -3
- package/dist/confirm.d.ts.map +1 -1
- package/dist/confirm.js +12 -14
- package/dist/dependencyMetadata.d.ts +18 -0
- package/dist/dependencyMetadata.d.ts.map +1 -0
- package/dist/dependencyMetadata.js +67 -0
- package/dist/errorReporter.d.ts +6 -4
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +14 -19
- package/dist/form.d.ts +5 -5
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +16 -10
- package/dist/internal/tanstackQuery.d.ts +9 -0
- package/dist/internal/tanstackQuery.d.ts.map +1 -0
- package/dist/internal/tanstackQuery.js +204 -0
- package/dist/intl.d.ts +4 -4
- package/dist/intl.d.ts.map +1 -1
- package/dist/intl.js +2 -2
- package/dist/lib.d.ts +8 -10
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +37 -12
- package/dist/liveQueryInvalidation.d.ts +16 -0
- package/dist/liveQueryInvalidation.d.ts.map +1 -0
- package/dist/liveQueryInvalidation.js +115 -0
- package/dist/makeClient.d.ts +232 -109
- package/dist/makeClient.d.ts.map +1 -1
- package/dist/makeClient.js +416 -84
- package/dist/makeContext.d.ts.map +1 -1
- package/dist/makeIntl.d.ts.map +1 -1
- package/dist/makeUseCommand.d.ts +3 -2
- package/dist/makeUseCommand.d.ts.map +1 -1
- package/dist/makeUseCommand.js +2 -2
- package/dist/mutate.d.ts +110 -41
- package/dist/mutate.d.ts.map +1 -1
- package/dist/mutate.js +236 -59
- package/dist/query.d.ts +161 -44
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +382 -113
- package/dist/queryLifetime.d.ts +25 -0
- package/dist/queryLifetime.d.ts.map +1 -0
- package/dist/queryLifetime.js +54 -0
- package/dist/routeParams.d.ts +4 -4
- package/dist/routeParams.d.ts.map +1 -1
- package/dist/routeParams.js +4 -3
- package/dist/runtime.d.ts +1 -17
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +2 -38
- package/dist/suspense.d.ts +19 -0
- package/dist/suspense.d.ts.map +1 -0
- package/dist/suspense.js +38 -0
- package/dist/toast.d.ts +1 -45
- package/dist/toast.d.ts.map +1 -1
- package/dist/toast.js +2 -32
- package/dist/withToast.d.ts +1 -24
- package/dist/withToast.d.ts.map +1 -1
- package/dist/withToast.js +2 -45
- package/docs/atom-query-api-redesign.md +207 -0
- package/docs/mutation-command-atoms.md +40 -0
- package/docs/query-key-invalidation.md +107 -0
- package/examples/streamMutation.ts +72 -0
- package/package.json +35 -94
- package/src/atomQuery.ts +600 -0
- package/src/commander.ts +1064 -116
- package/src/confirm.ts +12 -14
- package/src/dependencyMetadata.ts +84 -0
- package/src/errorReporter.ts +65 -75
- package/src/form.ts +22 -15
- package/src/index.ts +7 -7
- package/src/internal/tanstackQuery.ts +308 -0
- package/src/intl.ts +2 -2
- package/src/lib.ts +51 -23
- package/src/liveQueryInvalidation.ts +138 -0
- package/src/makeClient.ts +972 -263
- package/src/makeIntl.ts +2 -2
- package/src/makeUseCommand.ts +8 -5
- package/src/mutate.ts +407 -154
- package/src/query.ts +758 -242
- package/src/queryLifetime.ts +74 -0
- package/src/routeParams.ts +7 -7
- package/src/runtime.ts +1 -54
- package/src/suspense.ts +43 -0
- package/src/toast.ts +1 -52
- package/src/withToast.ts +1 -99
- package/test/Mutation.test.ts +104 -17
- package/test/dependencyInvalidation.test.ts +444 -0
- package/test/dist/dependencyInvalidation.test.d.ts.map +1 -0
- package/test/dist/form.test.d.ts.map +1 -1
- package/test/dist/inactiveInvalidation.test.d.ts.map +1 -0
- package/test/dist/interrupt-refetch-repro.test.d.ts.map +1 -0
- package/test/dist/lib.test.d.ts.map +1 -0
- package/test/dist/liveQueryInvalidation.test.d.ts.map +1 -0
- package/test/dist/query-span.test.d.ts.map +1 -0
- package/test/dist/queryOptions.test.d.ts.map +1 -0
- package/test/dist/streamFinal.test.d.ts.map +1 -0
- package/test/dist/streamFn.test.d.ts.map +1 -0
- package/test/dist/stubs.d.ts +3681 -256
- package/test/dist/stubs.d.ts.map +1 -1
- package/test/dist/stubs.js +166 -25
- package/test/dist/suspense-regression.test.d.ts.map +1 -0
- package/test/dist/suspense.test.d.ts.map +1 -0
- package/test/form-validation-errors.test.ts +2 -1
- package/test/form.test.ts +2 -1
- package/test/inactiveInvalidation.test.ts +172 -0
- package/test/interrupt-refetch-repro.test.ts +625 -0
- package/test/lib.test.ts +240 -0
- package/test/liveQueryInvalidation.test.ts +108 -0
- package/test/makeClient.test.ts +414 -32
- package/test/query-span.test.ts +92 -0
- package/test/queryOptions.test.ts +88 -0
- package/test/streamFinal.test.ts +64 -0
- package/test/streamFn.test.ts +457 -0
- package/test/stubs.ts +194 -36
- package/test/suspense-regression.test.ts +168 -0
- package/test/suspense.test.ts +160 -0
- package/tsconfig.examples.json +20 -0
- package/tsconfig.json +9 -1
- package/tsconfig.src.json +34 -34
- package/tsconfig.test.json +2 -2
- package/vitest.config.ts +5 -5
- package/eslint.config.mjs +0 -24
- package/tsconfig.json.bak +0 -12
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { ClientForOptions } from "effect-app/client/clientFor";
|
|
2
|
+
import * as Effect from "effect-app/Effect";
|
|
3
|
+
import * as Cause from "effect/Cause";
|
|
4
|
+
import * as Duration from "effect/Duration";
|
|
5
|
+
import type * as Layer from "effect/Layer";
|
|
6
|
+
import * as AsyncResult from "effect/reactivity/AsyncResult";
|
|
7
|
+
import * as Atom from "effect/reactivity/Atom";
|
|
8
|
+
import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
9
|
+
import * as Stream from "effect/Stream";
|
|
10
|
+
import { type QueryInvalidationMode } from "./dependencyMetadata.js";
|
|
11
|
+
import { type LiveQueryOptions } from "./liveQueryInvalidation.js";
|
|
12
|
+
/** Refresh observed query atoms without making the triggering mutation await them. */
|
|
13
|
+
export declare const invalidateSoft: (keys: ReadonlyArray<unknown>) => Effect.Effect<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Invalidate the given keys and AWAIT the result. `keyAtoms` resolves all matching hierarchical
|
|
16
|
+
* keys to a deduplicated set of query atoms. Refresh that set directly: sending the whole key set
|
|
17
|
+
* through `Reactivity.invalidate` invokes one atom's registered callback once per matching key,
|
|
18
|
+
* repeatedly superseding the same fetch when a mutation carries many row/prefix keys.
|
|
19
|
+
*
|
|
20
|
+
* Resolves once every **observed** matching query has settled, so a mutation can
|
|
21
|
+
* `yield*` this and know the on-screen data is fresh. Idle (observers === 0)
|
|
22
|
+
* matches are only marked stale — they do not block the mutation. Soft
|
|
23
|
+
* invalidation (`invalidateSoft`) still fires without awaiting.
|
|
24
|
+
*/
|
|
25
|
+
export declare const invalidateAndAwait: (keys: ReadonlyArray<unknown>) => Effect.Effect<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Structural sharing (tanstack `replaceEqualDeep`): walk `next` against `prev` and reuse `prev`'s
|
|
28
|
+
* reference for any unchanged array/object sub-tree, so unchanged data keeps referential identity
|
|
29
|
+
* (Vue skips re-rendering it). Leaves — including decoded Schema CLASS INSTANCES — are compared with
|
|
30
|
+
* Effect `Equal.equals` (structural), which reuses equal instances that tanstack's `===` could not.
|
|
31
|
+
*/
|
|
32
|
+
export declare const replaceEqualDeep: (prev: any, next: any) => any;
|
|
33
|
+
export interface AtomClientRuntime {
|
|
34
|
+
readonly runtime: Atom.AtomRuntime<any, never>;
|
|
35
|
+
readonly factory: Atom.RuntimeFactory;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build one AtomRuntime (and its factory) from an already-built app context.
|
|
39
|
+
* Shares the ManagedRuntime's `memoMap` so layers are not built twice, and so
|
|
40
|
+
* query-registration and mutation-invalidation resolve the SAME `Reactivity`.
|
|
41
|
+
*/
|
|
42
|
+
export declare const makeAtomClientRuntime: <R>(getContext: () => Layer.Layer<R, never, never>, memoMap: Layer.MemoMap) => AtomClientRuntime;
|
|
43
|
+
export interface AtomQueryOptions {
|
|
44
|
+
/** background-refresh threshold (TanStack staleTime; default 5s) */
|
|
45
|
+
readonly staleTime?: Duration.Input;
|
|
46
|
+
/** dispose-when-idle (TanStack gcTime; default 5min). "infinity" => keepAlive */
|
|
47
|
+
readonly gcTime?: Duration.Input | "infinity";
|
|
48
|
+
readonly invalidation?: QueryInvalidationMode;
|
|
49
|
+
/**
|
|
50
|
+
* Revalidate a stale query on window focus AND on network reconnect (default on, matching
|
|
51
|
+
* tanstack refetchOnWindowFocus + refetchOnReconnect).
|
|
52
|
+
*/
|
|
53
|
+
readonly revalidateOnFocus?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Reuse references of unchanged sub-trees across refetches (default on, matching tanstack
|
|
56
|
+
* structuralSharing). Uses Effect `Equal` so decoded Schema instances share too — more effective
|
|
57
|
+
* than tanstack's `===`, but a deep compare per refetch (O(rows·fields)). Set `false` for very
|
|
58
|
+
* large or mostly-changing result sets where the compare costs more than the saved re-renders.
|
|
59
|
+
*/
|
|
60
|
+
readonly structuralSharing?: boolean;
|
|
61
|
+
/** poll: re-fetch every N ms (tanstack refetchInterval). */
|
|
62
|
+
readonly refetchInterval?: number;
|
|
63
|
+
/** Refresh when writes intersect the dependencies recorded by this query. */
|
|
64
|
+
readonly live?: boolean | LiveQueryOptions;
|
|
65
|
+
}
|
|
66
|
+
export interface AtomQueryMetadata {
|
|
67
|
+
readonly staleTimeMs: number;
|
|
68
|
+
}
|
|
69
|
+
export declare const queryKeyForAtom: <A, E>(atom: Atom.Atom<AsyncResult.AsyncResult<A, E>>) => ReadonlyArray<unknown> | undefined;
|
|
70
|
+
export declare const captureAtomQueryParentSpan: <A, E>(atom: Atom.Atom<AsyncResult.AsyncResult<A, E>>) => Effect.Effect<void>;
|
|
71
|
+
export declare const refreshAtomWithCurrentSpan: <A, E>(registry: AtomRegistry.AtomRegistry, atom: Atom.Atom<AsyncResult.AsyncResult<A, E>>) => Effect.Effect<void>;
|
|
72
|
+
export declare const getAtomQueryMetadata: <A, E>(atom: Atom.Atom<AsyncResult.AsyncResult<A, E>>) => AtomQueryMetadata | undefined;
|
|
73
|
+
/** Exported so the vue hook can do refetch-on-mount-per-observer with the same rule as swr. */
|
|
74
|
+
export declare const isStaleResult: (r: AsyncResult.AsyncResult<any, any>, staleTimeMs: number) => boolean;
|
|
75
|
+
export declare const staleTimeMsOf: (opts: AtomQueryOptions) => number;
|
|
76
|
+
export interface QueryFetchState {
|
|
77
|
+
inFlight: number;
|
|
78
|
+
recovering: boolean;
|
|
79
|
+
}
|
|
80
|
+
export declare const queryFetchStates: WeakMap<Atom.Atom<any>, QueryFetchState>;
|
|
81
|
+
export declare const withQueryOptions: <A, E>(self: Atom.Atom<AsyncResult.AsyncResult<A, E>>, opts?: AtomQueryOptions, liveKey?: ReadonlyArray<unknown>) => Atom.Atom<AsyncResult.AsyncResult<A, E>>;
|
|
82
|
+
/** Constant atom for disabled / `mode:"optional"`-None queries: stays Initial, never fetches. */
|
|
83
|
+
export declare const disabledQueryAtom: Atom.Atom<AsyncResult.AsyncResult<any, any>>;
|
|
84
|
+
/**
|
|
85
|
+
* Build the per-input atom family for a request handler — the query CACHE IDENTITY.
|
|
86
|
+
*
|
|
87
|
+
* This is the TanStack `queryKey = [handler, input]` equivalent and the piece that makes
|
|
88
|
+
* caching cross-component: `Atom.family` memoizes one atom per structurally-distinct input
|
|
89
|
+
* (v4 hashes the input via Hash/Equal), so every component querying the same handler+input
|
|
90
|
+
* reads the SAME atom instance => one fetch, one shared result in the global registry,
|
|
91
|
+
* ref-counted and GC'd on idle ttl. (The registry + ttl give lifetime; reactivity keys give
|
|
92
|
+
* invalidation; the family gives identity/sharing — all three are needed.)
|
|
93
|
+
*
|
|
94
|
+
* The family is created once per handler (see query.ts's per-handler cache), so it is shared
|
|
95
|
+
* process-wide via the registry.
|
|
96
|
+
*
|
|
97
|
+
* Invalidation is hierarchical: each atom registers under EVERY prefix of its full key
|
|
98
|
+
* `[...makeQueryKey(self), input]`. Since reactivity matches keys by exact hash, registering
|
|
99
|
+
* all prefixes means `invalidate(P)` refreshes every atom whose key starts with `P` — e.g.
|
|
100
|
+
* `["$X"]` refreshes all inputs, `["$X","$List",input]` only that input. (`makeQueryKey`'s
|
|
101
|
+
* collapsed form `getQueryKey` — what mutations invalidate by default — is one of the prefixes.)
|
|
102
|
+
*/
|
|
103
|
+
export declare const buildQueryFamily: <I, A, E>(rt: AtomClientRuntime, self: {
|
|
104
|
+
readonly id: string;
|
|
105
|
+
readonly handler: (i: I) => Effect.Effect<A, E, any>;
|
|
106
|
+
readonly options?: ClientForOptions;
|
|
107
|
+
readonly queryKeyProjectionHash?: string;
|
|
108
|
+
}) => (arg: I) => Atom.Atom<AsyncResult.AsyncResult<A, E>>;
|
|
109
|
+
export declare const buildStreamQueryFamily: <I, A, E>(rt: AtomClientRuntime, self: {
|
|
110
|
+
readonly id: string;
|
|
111
|
+
readonly handler: (i: I) => Stream.Stream<A, E, any>;
|
|
112
|
+
readonly options?: ClientForOptions;
|
|
113
|
+
readonly queryKeyProjectionHash?: string;
|
|
114
|
+
}) => (arg: I) => Atom.Atom<AsyncResult.AsyncResult<{
|
|
115
|
+
readonly done: boolean;
|
|
116
|
+
readonly items: [A, ...A[]];
|
|
117
|
+
}, E | Cause.NoSuchElementError>>;
|
|
118
|
+
/** Await the first resolved (non-Waiting) result of an atom. Failing query results fail the Effect. */
|
|
119
|
+
export declare const awaitAtomResult: <A, E>(registry: AtomRegistry.AtomRegistry, atom: Atom.Atom<AsyncResult.AsyncResult<A, E>>) => Effect.Effect<A, E, never>;
|
|
120
|
+
//# sourceMappingURL=atomQuery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomQuery.d.ts","sourceRoot":"","sources":["../src/atomQuery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
/**
|
|
3
|
+
* Shared atom core for the query/mutation engine (used by query.ts + mutate.ts).
|
|
4
|
+
*
|
|
5
|
+
* Replaces the @tanstack/vue-query engine with Effect `Atom`, keeping the public
|
|
6
|
+
* `.query()/.suspense()/.mutate()` contract unchanged:
|
|
7
|
+
* - cache identity = the atom reference (one per [handler, input], via Atom.family)
|
|
8
|
+
* - invalidation key = reactivity keys (= the app's existing namespace query keys)
|
|
9
|
+
* - SWR + focus = Atom.swr (+ windowFocusSignal)
|
|
10
|
+
* - gcTime = Atom.setIdleTTL / Atom.keepAlive
|
|
11
|
+
* - retry = Effect.retry inside the atom effect
|
|
12
|
+
*
|
|
13
|
+
* Built over the app's RPC client through the existing `RequestHandlerWithInput`
|
|
14
|
+
* abstraction (mirrors AtomRpc's recipe; see docs/atom-query-plan.md).
|
|
15
|
+
*/
|
|
16
|
+
import { defaultRegistry } from "@effect/atom-vue";
|
|
17
|
+
import { DataDependencies, makeQueryKey } from "effect-app/client";
|
|
18
|
+
import { ServiceUnavailableError } from "effect-app/client/errors";
|
|
19
|
+
import * as Effect from "effect-app/Effect";
|
|
20
|
+
import * as Option from "effect-app/Option";
|
|
21
|
+
import * as S from "effect-app/Schema";
|
|
22
|
+
import * as Cause from "effect/Cause";
|
|
23
|
+
import * as Duration from "effect/Duration";
|
|
24
|
+
import * as Equal from "effect/Equal";
|
|
25
|
+
import * as Hash from "effect/Hash";
|
|
26
|
+
import { isHttpClientError } from "effect/http/HttpClientError";
|
|
27
|
+
import * as AsyncResult from "effect/reactivity/AsyncResult";
|
|
28
|
+
import * as Atom from "effect/reactivity/Atom";
|
|
29
|
+
import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
30
|
+
import * as Ref from "effect/Ref";
|
|
31
|
+
import * as Stream from "effect/Stream";
|
|
32
|
+
import { clearQueryReadDependencies, getQueryReadDependencies, registerQueryInvalidationMode, setQueryReadDependencies } from "./dependencyMetadata.js";
|
|
33
|
+
import { reportRuntimeError } from "./lib.js";
|
|
34
|
+
import { beginLiveQueryFetch, endLiveQueryFetch, registerLiveQuery } from "./liveQueryInvalidation.js";
|
|
35
|
+
import { atomsToRefetch, observeQueryAtom } from "./queryLifetime.js";
|
|
36
|
+
/** All non-empty prefixes of a key, longest last. `[a,b,c]` -> `[[a],[a,b],[a,b,c]]`. */
|
|
37
|
+
const prefixesOf = (key) => key.map((_, i) => key.slice(0, i + 1));
|
|
38
|
+
const uniqueKeys = (keys) => {
|
|
39
|
+
const out = [];
|
|
40
|
+
const seen = new Set();
|
|
41
|
+
for (const key of keys) {
|
|
42
|
+
const hash = Hash.hash(key);
|
|
43
|
+
if (seen.has(hash))
|
|
44
|
+
continue;
|
|
45
|
+
seen.add(hash);
|
|
46
|
+
out.push(key);
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
};
|
|
50
|
+
// --- awaitable invalidation -------------------------------------------------------------------
|
|
51
|
+
// keyHash -> query atoms registered under that key. A query atom stays in the map while it is
|
|
52
|
+
// alive in the registry (mounted OR cached within idle-ttl). Invalidation *marks* every matching
|
|
53
|
+
// atom stale; it only *refetches* atoms that currently have observers (TanStack refetchType:
|
|
54
|
+
// "active"). Idle cache entries refetch on the next mount.
|
|
55
|
+
const keyAtoms = new Map();
|
|
56
|
+
const trackByKeys = (keys) => (atom) => Atom.transform(atom, (get) => {
|
|
57
|
+
for (const key of keys) {
|
|
58
|
+
const h = Hash.hash(key);
|
|
59
|
+
let set = keyAtoms.get(h);
|
|
60
|
+
if (!set)
|
|
61
|
+
keyAtoms.set(h, set = new Set());
|
|
62
|
+
set.add(atom);
|
|
63
|
+
get.addFinalizer(() => {
|
|
64
|
+
set.delete(atom);
|
|
65
|
+
if (set.size === 0)
|
|
66
|
+
keyAtoms.delete(h);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return get(atom);
|
|
70
|
+
}, { initialValueTarget: atom });
|
|
71
|
+
const trackWritableByKeys = (keys) => (atom) => {
|
|
72
|
+
const tracked = trackByKeys(keys)(atom);
|
|
73
|
+
return Atom.writable((get) => get(tracked), (ctx, value) => ctx.set(atom, value), (refresh) => refresh(tracked));
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Keep a query's recorded read-dependencies registered for as long as it is alive, and drop them when
|
|
77
|
+
* its atom is GC'd (mirrors `trackByKeys`).
|
|
78
|
+
*
|
|
79
|
+
* `recordReads` only stores the deps on an actual fetch. A query that unmounts and later remounts from
|
|
80
|
+
* cache (within idle-ttl) does NOT re-run the handler, so its registry entry — cleared by the previous
|
|
81
|
+
* teardown's finalizer — would never be restored, and a subsequent mutation could not derive it as an
|
|
82
|
+
* invalidation target. Re-asserting the last-known reads on every (re)subscribe closes that gap, so the
|
|
83
|
+
* registry mirrors the live query even across cache-hit remounts.
|
|
84
|
+
*/
|
|
85
|
+
const trackReadDependencies = (key, getReads) => (atom) => Atom.transform(atom, (get) => {
|
|
86
|
+
const reads = getReads();
|
|
87
|
+
if (DataDependencies.isNonEmpty(reads))
|
|
88
|
+
setQueryReadDependencies(key, reads);
|
|
89
|
+
get.addFinalizer(() => clearQueryReadDependencies(key));
|
|
90
|
+
return get(atom);
|
|
91
|
+
}, { initialValueTarget: atom });
|
|
92
|
+
const atomsForKeys = (keys) => {
|
|
93
|
+
const atoms = new Set();
|
|
94
|
+
for (const key of keys) {
|
|
95
|
+
const set = keyAtoms.get(Hash.hash(key));
|
|
96
|
+
if (set) {
|
|
97
|
+
for (const a of set)
|
|
98
|
+
atoms.add(a);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return [...atoms];
|
|
102
|
+
};
|
|
103
|
+
/** Refresh observed query atoms without making the triggering mutation await them. */
|
|
104
|
+
export const invalidateSoft = (keys) => Effect
|
|
105
|
+
.gen(function* () {
|
|
106
|
+
const atoms = atomsToRefetch(atomsForKeys(keys));
|
|
107
|
+
yield* Effect.forEach(atoms, captureAtomQueryParentSpan, { discard: true, concurrency: "unbounded" });
|
|
108
|
+
if (atoms.length === 0)
|
|
109
|
+
return;
|
|
110
|
+
yield* Effect.forEach(atoms, (atom) => Effect.sync(() => defaultRegistry.refresh(atom)), {
|
|
111
|
+
discard: true
|
|
112
|
+
});
|
|
113
|
+
})
|
|
114
|
+
.pipe(Effect.orDie);
|
|
115
|
+
/**
|
|
116
|
+
* Invalidate the given keys and AWAIT the result. `keyAtoms` resolves all matching hierarchical
|
|
117
|
+
* keys to a deduplicated set of query atoms. Refresh that set directly: sending the whole key set
|
|
118
|
+
* through `Reactivity.invalidate` invokes one atom's registered callback once per matching key,
|
|
119
|
+
* repeatedly superseding the same fetch when a mutation carries many row/prefix keys.
|
|
120
|
+
*
|
|
121
|
+
* Resolves once every **observed** matching query has settled, so a mutation can
|
|
122
|
+
* `yield*` this and know the on-screen data is fresh. Idle (observers === 0)
|
|
123
|
+
* matches are only marked stale — they do not block the mutation. Soft
|
|
124
|
+
* invalidation (`invalidateSoft`) still fires without awaiting.
|
|
125
|
+
*/
|
|
126
|
+
export const invalidateAndAwait = (keys) => Effect
|
|
127
|
+
.gen(function* () {
|
|
128
|
+
const atoms = atomsToRefetch(atomsForKeys(keys));
|
|
129
|
+
yield* Effect.forEach(atoms, captureAtomQueryParentSpan, { discard: true, concurrency: "unbounded" });
|
|
130
|
+
if (atoms.length === 0)
|
|
131
|
+
return;
|
|
132
|
+
yield* Effect.forEach(atoms, (atom) => Effect.sync(() => defaultRegistry.refresh(atom)), {
|
|
133
|
+
discard: true
|
|
134
|
+
});
|
|
135
|
+
// Contract: observers > 0 ⇒ wait for this refresh to finish.
|
|
136
|
+
yield* Effect.forEach(atoms, (a) => awaitAtomResult(defaultRegistry, a).pipe(Effect.exit));
|
|
137
|
+
})
|
|
138
|
+
.pipe(Effect.orDie);
|
|
139
|
+
const isPlainObject = (o) => {
|
|
140
|
+
if (typeof o !== "object" || o === null)
|
|
141
|
+
return false;
|
|
142
|
+
const proto = Object.getPrototypeOf(o);
|
|
143
|
+
return proto === Object.prototype || proto === null;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Structural sharing (tanstack `replaceEqualDeep`): walk `next` against `prev` and reuse `prev`'s
|
|
147
|
+
* reference for any unchanged array/object sub-tree, so unchanged data keeps referential identity
|
|
148
|
+
* (Vue skips re-rendering it). Leaves — including decoded Schema CLASS INSTANCES — are compared with
|
|
149
|
+
* Effect `Equal.equals` (structural), which reuses equal instances that tanstack's `===` could not.
|
|
150
|
+
*/
|
|
151
|
+
export const replaceEqualDeep = (prev, next) => {
|
|
152
|
+
if (prev === next)
|
|
153
|
+
return prev;
|
|
154
|
+
const bothArrays = Array.isArray(prev) && Array.isArray(next);
|
|
155
|
+
if (bothArrays || (isPlainObject(prev) && isPlainObject(next))) {
|
|
156
|
+
const a = prev;
|
|
157
|
+
const b = next;
|
|
158
|
+
const copy = bothArrays ? [] : {};
|
|
159
|
+
const nextKeys = bothArrays ? b.map((_, i) => i) : Object.keys(b);
|
|
160
|
+
const nextSize = nextKeys.length;
|
|
161
|
+
const prevSize = bothArrays ? a.length : Object.keys(a).length;
|
|
162
|
+
let equalItems = 0;
|
|
163
|
+
for (let i = 0; i < nextSize; i++) {
|
|
164
|
+
const key = nextKeys[i];
|
|
165
|
+
copy[key] = replaceEqualDeep(a[key], b[key]);
|
|
166
|
+
if (copy[key] === a[key] && a[key] !== undefined)
|
|
167
|
+
equalItems++;
|
|
168
|
+
}
|
|
169
|
+
return prevSize === nextSize && equalItems === prevSize ? prev : copy;
|
|
170
|
+
}
|
|
171
|
+
return Equal.equals(prev, next) ? prev : next;
|
|
172
|
+
};
|
|
173
|
+
/** Atom combinator: share each new `Success` value structurally against the previous one. */
|
|
174
|
+
const structuralShare = (self) => Atom.transform(self, (get) => {
|
|
175
|
+
const next = get(self);
|
|
176
|
+
if (next._tag !== "Success")
|
|
177
|
+
return next;
|
|
178
|
+
const prev = Option.flatMap(get.self(), AsyncResult.value);
|
|
179
|
+
if (Option.isNone(prev))
|
|
180
|
+
return next;
|
|
181
|
+
const shared = replaceEqualDeep(prev.value, next.value);
|
|
182
|
+
return shared === next.value
|
|
183
|
+
? next
|
|
184
|
+
: AsyncResult.success(shared, { waiting: next.waiting, timestamp: next.timestamp });
|
|
185
|
+
}, { initialValueTarget: self });
|
|
186
|
+
/**
|
|
187
|
+
* Build one AtomRuntime (and its factory) from an already-built app context.
|
|
188
|
+
* Shares the ManagedRuntime's `memoMap` so layers are not built twice, and so
|
|
189
|
+
* query-registration and mutation-invalidation resolve the SAME `Reactivity`.
|
|
190
|
+
*/
|
|
191
|
+
export const makeAtomClientRuntime = (getContext, memoMap) => {
|
|
192
|
+
const factory = Atom.context({ memoMap });
|
|
193
|
+
const runtime = factory((_get) => getContext());
|
|
194
|
+
return { runtime, factory };
|
|
195
|
+
};
|
|
196
|
+
const isRetryable = (e) => isHttpClientError(e)
|
|
197
|
+
|| S.is(ServiceUnavailableError)(e)
|
|
198
|
+
|| (typeof e === "object" && e !== null && e._tag === "RpcClientError");
|
|
199
|
+
const defaults = { staleTime: Duration.seconds(5), gcTime: Duration.minutes(5) };
|
|
200
|
+
const atomQueryMetadata = new WeakMap();
|
|
201
|
+
const atomQueryParentSpans = new WeakMap();
|
|
202
|
+
const atomQueryKeys = new WeakMap();
|
|
203
|
+
export const queryKeyForAtom = (atom) => atomQueryKeys.get(atom);
|
|
204
|
+
const atomSpanTarget = (atom) => {
|
|
205
|
+
let target = atom;
|
|
206
|
+
while (target.initialValueTarget !== undefined) {
|
|
207
|
+
target = target.initialValueTarget;
|
|
208
|
+
}
|
|
209
|
+
return target;
|
|
210
|
+
};
|
|
211
|
+
const takeAtomQueryParentSpan = (atom) => {
|
|
212
|
+
const target = atomSpanTarget(atom);
|
|
213
|
+
const span = atomQueryParentSpans.get(target);
|
|
214
|
+
if (span !== undefined)
|
|
215
|
+
atomQueryParentSpans.delete(target);
|
|
216
|
+
return span;
|
|
217
|
+
};
|
|
218
|
+
const setAtomQueryParentSpan = (atom, span) => {
|
|
219
|
+
atomQueryParentSpans.set(atomSpanTarget(atom), span);
|
|
220
|
+
};
|
|
221
|
+
export const captureAtomQueryParentSpan = (atom) => Effect.currentParentSpan.pipe(Effect.tap((span) => Effect.sync(() => setAtomQueryParentSpan(atom, span))), Effect.ignore);
|
|
222
|
+
export const refreshAtomWithCurrentSpan = (registry, atom) => captureAtomQueryParentSpan(atom).pipe(Effect.andThen(Effect.sync(() => registry.refresh(atom))));
|
|
223
|
+
const setAtomQueryMetadata = (atom, opts = {}) => {
|
|
224
|
+
const staleTimeMs = staleTimeMsOf(opts);
|
|
225
|
+
const previous = atomQueryMetadata.get(atom);
|
|
226
|
+
atomQueryMetadata.set(atom, {
|
|
227
|
+
staleTimeMs: previous === undefined ? staleTimeMs : Math.min(previous.staleTimeMs, staleTimeMs)
|
|
228
|
+
});
|
|
229
|
+
return atom;
|
|
230
|
+
};
|
|
231
|
+
export const getAtomQueryMetadata = (atom) => atomQueryMetadata.get(atom);
|
|
232
|
+
/** Exported so the vue hook can do refetch-on-mount-per-observer with the same rule as swr. */
|
|
233
|
+
export const isStaleResult = (r, staleTimeMs) => {
|
|
234
|
+
if (r.waiting)
|
|
235
|
+
return false;
|
|
236
|
+
const ts = r._tag === "Success"
|
|
237
|
+
? r.timestamp
|
|
238
|
+
: r._tag === "Failure"
|
|
239
|
+
? Option.getOrUndefined(Option.map(r.previousSuccess, (s) => s.timestamp))
|
|
240
|
+
: undefined;
|
|
241
|
+
if (ts === undefined)
|
|
242
|
+
return r._tag !== "Initial";
|
|
243
|
+
return Date.now() - ts >= staleTimeMs;
|
|
244
|
+
};
|
|
245
|
+
export const staleTimeMsOf = (opts) => Duration.toMillis(Duration.fromInputUnsafe(opts.staleTime ?? defaults.staleTime));
|
|
246
|
+
export const queryFetchStates = new WeakMap();
|
|
247
|
+
const recoverStuckWaitingOnMount = (familyAtom) => (wrapped) => Atom.transform(wrapped, (get) => {
|
|
248
|
+
const current = get.once(wrapped);
|
|
249
|
+
get.subscribe(wrapped, (value) => get.setSelf(value));
|
|
250
|
+
const state = queryFetchStates.get(familyAtom);
|
|
251
|
+
const waiting = current?.waiting === true;
|
|
252
|
+
// Stuck: the result says `waiting` yet nothing is in-flight — an interrupt was hidden and left
|
|
253
|
+
// `waiting` dangling. Treat it as not-yet-fetched and refetch; a live fetch (`inFlight > 0`) is
|
|
254
|
+
// joined, not superseded. `recovering` prevents concurrent mounts from issuing more than one
|
|
255
|
+
// recovery fetch (cleared once a fetch is actually running again).
|
|
256
|
+
if (state && waiting && state.inFlight === 0 && !state.recovering) {
|
|
257
|
+
state.recovering = true;
|
|
258
|
+
get.refresh(familyAtom);
|
|
259
|
+
}
|
|
260
|
+
return current;
|
|
261
|
+
}, { initialValueTarget: wrapped });
|
|
262
|
+
export const withQueryOptions = (self, opts = {}, liveKey) => {
|
|
263
|
+
setAtomQueryMetadata(self, opts);
|
|
264
|
+
const staleTime = opts.staleTime ?? defaults.staleTime;
|
|
265
|
+
let atom = self;
|
|
266
|
+
if (liveKey !== undefined) {
|
|
267
|
+
atom = Atom.transform(atom, (get) => {
|
|
268
|
+
const unregister = registerQueryInvalidationMode(liveKey, opts.invalidation ?? "await");
|
|
269
|
+
get.addFinalizer(unregister);
|
|
270
|
+
return get(self);
|
|
271
|
+
}, { initialValueTarget: self });
|
|
272
|
+
}
|
|
273
|
+
if (opts.live && liveKey !== undefined) {
|
|
274
|
+
const liveOptions = opts.live === true ? {} : opts.live;
|
|
275
|
+
atom = Atom.transform(atom, (get) => {
|
|
276
|
+
const unregister = registerLiveQuery(liveKey, () => getQueryReadDependencies(liveKey), liveOptions);
|
|
277
|
+
get.addFinalizer(unregister);
|
|
278
|
+
return get(self);
|
|
279
|
+
}, { initialValueTarget: self });
|
|
280
|
+
}
|
|
281
|
+
const revalidateOnFocus = opts.revalidateOnFocus ?? true;
|
|
282
|
+
atom = Atom.swr({
|
|
283
|
+
staleTime,
|
|
284
|
+
revalidateOnFocus,
|
|
285
|
+
focusSignal: revalidateOnFocus ? focusOrReconnectSignal : undefined
|
|
286
|
+
})(atom);
|
|
287
|
+
atom = recoverStuckWaitingOnMount(self)(atom);
|
|
288
|
+
if (opts.refetchInterval)
|
|
289
|
+
atom = Atom.withRefresh(Duration.millis(opts.refetchInterval))(atom);
|
|
290
|
+
if (opts.structuralSharing ?? true)
|
|
291
|
+
atom = structuralShare(atom);
|
|
292
|
+
return atom;
|
|
293
|
+
};
|
|
294
|
+
/** Constant atom for disabled / `mode:"optional"`-None queries: stays Initial, never fetches. */
|
|
295
|
+
export const disabledQueryAtom = Atom.readable(() => AsyncResult.initial(false));
|
|
296
|
+
/**
|
|
297
|
+
* Bumps when the browser regains connectivity (the `online` event) — the tanstack
|
|
298
|
+
* `refetchOnReconnect` trigger. One shared listener (module-level). SSR-guarded.
|
|
299
|
+
*/
|
|
300
|
+
const onlineSignal = Atom.readable((get) => {
|
|
301
|
+
let count = 0;
|
|
302
|
+
if (typeof window === "undefined")
|
|
303
|
+
return count;
|
|
304
|
+
const update = () => {
|
|
305
|
+
if (navigator.onLine)
|
|
306
|
+
get.setSelf(++count);
|
|
307
|
+
};
|
|
308
|
+
window.addEventListener("online", update);
|
|
309
|
+
get.addFinalizer(() => window.removeEventListener("online", update));
|
|
310
|
+
return count;
|
|
311
|
+
});
|
|
312
|
+
/**
|
|
313
|
+
* Focus OR reconnect, as a single signal for `swr` — both should stale-revalidate a query.
|
|
314
|
+
* swr takes one `focusSignal`, so we fold window-focus + reconnect into one derived atom;
|
|
315
|
+
* a bump from either triggers swr's stale check.
|
|
316
|
+
*/
|
|
317
|
+
const focusOrReconnectSignal = Atom.make((get) => get(Atom.windowFocusSignal) + get(onlineSignal));
|
|
318
|
+
/**
|
|
319
|
+
* Build the per-input atom family for a request handler — the query CACHE IDENTITY.
|
|
320
|
+
*
|
|
321
|
+
* This is the TanStack `queryKey = [handler, input]` equivalent and the piece that makes
|
|
322
|
+
* caching cross-component: `Atom.family` memoizes one atom per structurally-distinct input
|
|
323
|
+
* (v4 hashes the input via Hash/Equal), so every component querying the same handler+input
|
|
324
|
+
* reads the SAME atom instance => one fetch, one shared result in the global registry,
|
|
325
|
+
* ref-counted and GC'd on idle ttl. (The registry + ttl give lifetime; reactivity keys give
|
|
326
|
+
* invalidation; the family gives identity/sharing — all three are needed.)
|
|
327
|
+
*
|
|
328
|
+
* The family is created once per handler (see query.ts's per-handler cache), so it is shared
|
|
329
|
+
* process-wide via the registry.
|
|
330
|
+
*
|
|
331
|
+
* Invalidation is hierarchical: each atom registers under EVERY prefix of its full key
|
|
332
|
+
* `[...makeQueryKey(self), input]`. Since reactivity matches keys by exact hash, registering
|
|
333
|
+
* all prefixes means `invalidate(P)` refreshes every atom whose key starts with `P` — e.g.
|
|
334
|
+
* `["$X"]` refreshes all inputs, `["$X","$List",input]` only that input. (`makeQueryKey`'s
|
|
335
|
+
* collapsed form `getQueryKey` — what mutations invalidate by default — is one of the prefixes.)
|
|
336
|
+
*/
|
|
337
|
+
export const buildQueryFamily = (rt, self) => {
|
|
338
|
+
const baseKey = makeQueryKey(self); // hierarchical, input-independent
|
|
339
|
+
return Atom.family((input) => {
|
|
340
|
+
const fullKey = [...baseKey, input];
|
|
341
|
+
// Record the repository/server read-dependencies seen while fetching, keyed by `fullKey`, so a
|
|
342
|
+
// later mutation whose writes intersect them can derive this query as an invalidation target.
|
|
343
|
+
// The last recorded reads are retained on the (memoized) family atom so `trackReadDependencies`
|
|
344
|
+
// can re-assert them on a cache-hit remount that never re-runs the handler.
|
|
345
|
+
let lastReads = DataDependencies.empty();
|
|
346
|
+
// Fetch bookkeeping read by `recoverStuckWaitingOnMount`. `inFlight` counts live computes, so a
|
|
347
|
+
// `waiting` result with `inFlight === 0` is a stuck/hidden interrupt. `recovering` guards the
|
|
348
|
+
// recovery refresh against concurrent mounts; a running fetch clears it.
|
|
349
|
+
const fetchState = { inFlight: 0, recovering: false };
|
|
350
|
+
let atom;
|
|
351
|
+
atom = rt.runtime.atom(Effect.suspend(() => {
|
|
352
|
+
// A fetch is now running: the atom is not stuck, and any pending recovery is fulfilled.
|
|
353
|
+
fetchState.recovering = false;
|
|
354
|
+
fetchState.inFlight++;
|
|
355
|
+
const recordReads = Effect
|
|
356
|
+
.gen(function* () {
|
|
357
|
+
const readsRef = yield* Ref.make(DataDependencies.empty());
|
|
358
|
+
const writesRef = yield* Ref.make(DataDependencies.empty());
|
|
359
|
+
const recorder = DataDependencies.makeDataDependencyRecorder(readsRef, writesRef);
|
|
360
|
+
const result = yield* self
|
|
361
|
+
.handler(input)
|
|
362
|
+
.pipe(Effect.provideService(DataDependencies.DataDependencyRecorder, recorder));
|
|
363
|
+
lastReads = yield* Ref.get(readsRef);
|
|
364
|
+
setQueryReadDependencies(fullKey, lastReads);
|
|
365
|
+
return result;
|
|
366
|
+
});
|
|
367
|
+
let liveFetch = false;
|
|
368
|
+
const effect = Effect
|
|
369
|
+
.gen(function* () {
|
|
370
|
+
liveFetch = yield* Effect.promise(() => beginLiveQueryFetch(fullKey));
|
|
371
|
+
return yield* recordReads.pipe(Effect.retry({ times: 5, while: isRetryable }));
|
|
372
|
+
})
|
|
373
|
+
.pipe(Effect.ensuring(Effect.sync(() => endLiveQueryFetch(liveFetch))), Effect.tapCauseIf(Cause.hasDies, (cause) => reportRuntimeError(cause)),
|
|
374
|
+
// On exit, the compute is no longer in-flight. An interrupt (subscriber lost interest / a
|
|
375
|
+
// superseding refresh) may leave the result at `waiting`; with `inFlight` back at 0 that
|
|
376
|
+
// reads as "stuck", so the next mount recovers it (`recoverStuckWaitingOnMount`). We do not
|
|
377
|
+
// re-fire here — the interrupt was intentional; recovery is driven by a genuine (re)mount.
|
|
378
|
+
Effect.onExit(() => Effect.sync(() => {
|
|
379
|
+
fetchState.inFlight = Math.max(0, fetchState.inFlight - 1);
|
|
380
|
+
})), Effect.withSpan(`query ${self.id}`, {}, { captureStackTrace: false }));
|
|
381
|
+
const parentSpan = takeAtomQueryParentSpan(atom);
|
|
382
|
+
return parentSpan === undefined
|
|
383
|
+
? effect
|
|
384
|
+
: effect.pipe(Effect.withParentSpan(parentSpan, { captureStackTrace: false }));
|
|
385
|
+
}));
|
|
386
|
+
// Register under every prefix of the full key => hierarchical (prefix) invalidation. Two roles:
|
|
387
|
+
// - withReactivity: `Reactivity.invalidate(key)` refreshes this atom (the actual refetch).
|
|
388
|
+
// - trackByKeys: records the atom in `keyAtoms` so the mutation can AWAIT its settle.
|
|
389
|
+
const projectedFullKey = self.queryKeyProjectionHash === undefined
|
|
390
|
+
? fullKey
|
|
391
|
+
: [...baseKey, self.queryKeyProjectionHash, input];
|
|
392
|
+
const reactivityKeys = uniqueKeys([...prefixesOf(fullKey), ...prefixesOf(projectedFullKey)]);
|
|
393
|
+
atom = rt.factory.withReactivity(reactivityKeys)(atom);
|
|
394
|
+
atom = trackByKeys(reactivityKeys)(atom);
|
|
395
|
+
atom = trackReadDependencies(fullKey, () => lastReads)(atom);
|
|
396
|
+
// gcTime LAST so the whole chain (incl. the registration + tracking) stays alive through the
|
|
397
|
+
// idle window. Invalidation still finds the cached atom and marks it stale; it does not
|
|
398
|
+
// refetch until an observer remounts (TanStack refetchType: "active").
|
|
399
|
+
atom = Atom.setIdleTTL(atom, defaults.gcTime);
|
|
400
|
+
const registered = setAtomQueryMetadata(Atom.withLabel(`query:${self.id}`)(atom));
|
|
401
|
+
const writable = Atom.writable((get) => {
|
|
402
|
+
const current = get.once(registered);
|
|
403
|
+
get.subscribe(registered, (value) => get.setSelf(value));
|
|
404
|
+
return current;
|
|
405
|
+
}, (ctx, value) => ctx.setSelf(value), (refresh) => refresh(registered));
|
|
406
|
+
const writableWithTarget = Object.assign(writable, { initialValueTarget: registered });
|
|
407
|
+
const result = setAtomQueryMetadata(Atom.withLabel(`query-cache:${self.id}`)(writableWithTarget));
|
|
408
|
+
// Key the fetch state by the atom `withQueryOptions` receives, so its mount hook can find it.
|
|
409
|
+
const observed = observeQueryAtom(result);
|
|
410
|
+
queryFetchStates.set(result, fetchState);
|
|
411
|
+
queryFetchStates.set(observed, fetchState);
|
|
412
|
+
atomQueryKeys.set(result, fullKey);
|
|
413
|
+
atomQueryKeys.set(observed, fullKey);
|
|
414
|
+
return observed;
|
|
415
|
+
});
|
|
416
|
+
};
|
|
417
|
+
export const buildStreamQueryFamily = (rt, self) => {
|
|
418
|
+
const baseKey = makeQueryKey(self);
|
|
419
|
+
return Atom.family((input) => {
|
|
420
|
+
let atom = rt.runtime.pull(self.handler(input).pipe(Stream.tapCause((cause) => Cause.hasDies(cause) ? reportRuntimeError(cause) : Effect.void)));
|
|
421
|
+
const fullKey = [...baseKey, input];
|
|
422
|
+
const projectedFullKey = self.queryKeyProjectionHash === undefined
|
|
423
|
+
? fullKey
|
|
424
|
+
: [...baseKey, self.queryKeyProjectionHash, input];
|
|
425
|
+
const reactivityKeys = uniqueKeys([...prefixesOf(fullKey), ...prefixesOf(projectedFullKey)]);
|
|
426
|
+
atom = rt.factory.withReactivity(reactivityKeys)(atom);
|
|
427
|
+
atom = trackWritableByKeys(reactivityKeys)(atom);
|
|
428
|
+
atom = Atom.setIdleTTL(atom, defaults.gcTime);
|
|
429
|
+
return observeQueryAtom(setAtomQueryMetadata(Atom.withLabel(`stream-query:${self.id}`)(atom)));
|
|
430
|
+
});
|
|
431
|
+
};
|
|
432
|
+
/** Await the first resolved (non-Waiting) result of an atom. Failing query results fail the Effect. */
|
|
433
|
+
export const awaitAtomResult = (registry, atom) => AtomRegistry.getResult(registry, atom, { suspendOnWaiting: true });
|
|
434
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRvbVF1ZXJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2F0b21RdWVyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx1REFBdUQ7QUFDdkQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUNsRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFFbEUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDbEUsT0FBTyxLQUFLLE1BQU0sTUFBTSxtQkFBbUIsQ0FBQTtBQUMzQyxPQUFPLEtBQUssTUFBTSxNQUFNLG1CQUFtQixDQUFBO0FBQzNDLE9BQU8sS0FBSyxDQUFDLE1BQU0sbUJBQW1CLENBQUE7QUFDdEMsT0FBTyxLQUFLLEtBQUssTUFBTSxjQUFjLENBQUE7QUFDckMsT0FBTyxLQUFLLFFBQVEsTUFBTSxpQkFBaUIsQ0FBQTtBQUMzQyxPQUFPLEtBQUssS0FBSyxNQUFNLGNBQWMsQ0FBQTtBQUNyQyxPQUFPLEtBQUssSUFBSSxNQUFNLGFBQWEsQ0FBQTtBQUNuQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQTtBQUUvRCxPQUFPLEtBQUssV0FBVyxNQUFNLCtCQUErQixDQUFBO0FBQzVELE9BQU8sS0FBSyxJQUFJLE1BQU0sd0JBQXdCLENBQUE7QUFDOUMsT0FBTyxLQUFLLFlBQVksTUFBTSxnQ0FBZ0MsQ0FBQTtBQUM5RCxPQUFPLEtBQUssR0FBRyxNQUFNLFlBQVksQ0FBQTtBQUNqQyxPQUFPLEtBQUssTUFBTSxNQUFNLGVBQWUsQ0FBQTtBQUV2QyxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsd0JBQXdCLEVBQThCLDZCQUE2QixFQUFFLHdCQUF3QixFQUFFLE1BQU0seUJBQXlCLENBQUE7QUFDbkwsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sVUFBVSxDQUFB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
|