@securitydept/client-react 0.3.0-beta.2 → 0.3.0-beta.5

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/index.mjs CHANGED
@@ -1,85 +1,418 @@
1
- import { createPlannerHost, resolveEffectiveClientSet } from "@securitydept/client/auth-coordination";
2
- import { createContext, useContext, useMemo } from "react";
1
+ import { ClientError, ClientErrorKind, ResourceStatus, SYMBOL_DISPOSE, SYMBOL_OBSERVABLE, SecurityDeptOptional, SecuritydeptDestroyRef, TIME_TRAIT_TOKEN, createCancellationTokenSource, createComputed, createFoundationEnvironment, createSignal, getSecuritydeptProviderToken, isInteropObservableTrait, whenResourceSnapshotValue } from "@securitydept/client";
2
+ import { RxEventStream, RxEventSubject, RxStateSignal, createAsyncSchedulerWithTimestampProvider } from "@securitydept/client/rx";
3
+ import { NEVER, combineLatest, defer, filter, finalize, firstValueFrom, from, map, skip, switchMap, take, takeUntil, timer } from "rxjs";
4
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useSyncExternalStore } from "react";
3
5
  import { jsx } from "react/jsx-runtime";
4
- //#region src/planner-host/index.tsx
5
- const PlannerHostContext = createContext(null);
6
- /**
7
- * Provide a {@link PlannerHost} at the current React tree scope.
8
- *
9
- * Use at the app level or at feature-route boundaries to establish
10
- * planner-host scopes. Child components inherit the nearest provider.
11
- *
12
- * @example
13
- * ```tsx
14
- * // App-level (default sequential strategy)
15
- * <AuthPlannerHostProvider>
16
- * <App />
17
- * </AuthPlannerHostProvider>
18
- *
19
- * // Feature-route with custom chooser
20
- * <AuthPlannerHostProvider selectCandidate={showChooser}>
21
- * <FeatureRoutes />
22
- * </AuthPlannerHostProvider>
23
- * ```
24
- */
25
- function AuthPlannerHostProvider({ selectCandidate, plannerHost, children }) {
26
- const host = useMemo(() => {
27
- if (plannerHost) return plannerHost;
28
- return createPlannerHost(selectCandidate ? { selectCandidate } : void 0);
29
- }, [plannerHost, selectCandidate]);
30
- return /* @__PURE__ */ jsx(PlannerHostContext.Provider, {
31
- value: host,
6
+ //#region src/injection/index.tsx
7
+ const SecuritydeptContext = createContext(null);
8
+ function SecuritydeptProvider({ injector, children }) {
9
+ return /* @__PURE__ */ jsx(SecuritydeptContext.Provider, {
10
+ value: injector,
32
11
  children
33
12
  });
34
13
  }
35
- /**
36
- * Look up the nearest {@link PlannerHost} from the React Context tree.
37
- *
38
- * Throws an explicit error if no provider is found, preventing
39
- * silent fallback behavior.
40
- */
41
- function useAuthPlannerHost() {
42
- const host = useContext(PlannerHostContext);
43
- if (!host) throw new Error("[useAuthPlannerHost] No AuthPlannerHostProvider found in the component tree. Wrap your app or route with <AuthPlannerHostProvider>.");
44
- return host;
14
+ function useSecuritydeptContext() {
15
+ const injector = useContext(SecuritydeptContext);
16
+ if (!injector) throw new Error("[useSecuritydeptContext] No SecuritydeptProvider found in the component tree.");
17
+ return injector;
45
18
  }
46
- const RequirementsClientSetContext = createContext([]);
47
- /**
48
- * Provide a {@link ScopedRequirementsClientSet} at the current React tree scope.
49
- *
50
- * Automatically resolves the effective client set by composing with the
51
- * parent scope's options according to the declared composition strategy.
52
- *
53
- * @example
54
- * ```tsx
55
- * // Feature route: merge OIDC requirement with parent's session requirement
56
- * <AuthRequirementsClientSetProvider
57
- * scopedSet={{
58
- * composition: RequirementsClientSetComposition.Merge,
59
- * options: [oidcClientOption],
60
- * }}
61
- * >
62
- * <ProtectedFeature />
63
- * </AuthRequirementsClientSetProvider>
64
- * ```
65
- */
66
- function AuthRequirementsClientSetProvider({ scopedSet, children }) {
67
- const parentOptions = useContext(RequirementsClientSetContext);
68
- const effective = useMemo(() => resolveEffectiveClientSet(parentOptions, scopedSet), [parentOptions, scopedSet]);
69
- return /* @__PURE__ */ jsx(RequirementsClientSetContext.Provider, {
70
- value: effective,
71
- children
19
+ //#endregion
20
+ //#region src/query-store.ts
21
+ const QUERY_STORE_ERROR_SOURCE = "client-react.query-store";
22
+ /** @internal */
23
+ const QueryResultStatus = {
24
+ Pending: "pending",
25
+ Resolved: "resolved",
26
+ Error: "error"
27
+ };
28
+ var QueryStore = class QueryStore {
29
+ static defaultOptions = Object.freeze({ gcTimeMs: 3e5 });
30
+ queries = /* @__PURE__ */ new Map();
31
+ weakKeyIds = /* @__PURE__ */ new WeakMap();
32
+ scheduler;
33
+ gcTimeMs;
34
+ nextWeakKeyId = 0;
35
+ disposed = false;
36
+ constructor(options) {
37
+ this.scheduler = createAsyncSchedulerWithTimestampProvider(options.time);
38
+ this.gcTimeMs = validateGcTime(options.gcTimeMs ?? QueryStore.defaultOptions.gcTimeMs);
39
+ }
40
+ getWeakKeyId(value) {
41
+ const existing = this.weakKeyIds.get(value);
42
+ if (existing !== void 0) return existing;
43
+ const id = `weak_${++this.nextWeakKeyId}`;
44
+ this.weakKeyIds.set(value, id);
45
+ return id;
46
+ }
47
+ dispose() {
48
+ if (this.disposed) return;
49
+ this.disposed = true;
50
+ for (const query of this.queries.values()) query.dispose();
51
+ this.queries.clear();
52
+ }
53
+ [SYMBOL_DISPOSE]() {
54
+ this.dispose();
55
+ }
56
+ /** @internal */
57
+ getOrCreateQuery(options) {
58
+ const existing = this.queries.get(options.hash);
59
+ const resolvedOptions = {
60
+ gcTimeMs: validateGcTime(options.gcTimeMs ?? this.gcTimeMs),
61
+ retainWhilePending: options.retainWhilePending ?? true
62
+ };
63
+ if (existing) {
64
+ existing.updateOptions(resolvedOptions);
65
+ return existing;
66
+ }
67
+ const query = new Query(options.hash, options.source(), resolvedOptions, this.scheduler);
68
+ this.queries.set(options.hash, query);
69
+ query.garbageCollected.subscribe({ next: () => this.removeQuery(query) });
70
+ return query;
71
+ }
72
+ removeQuery(query) {
73
+ if (this.queries.get(query.hash) !== query) return;
74
+ this.queries.delete(query.hash);
75
+ query.dispose();
76
+ }
77
+ };
78
+ function provideQueryStore(options = {}) {
79
+ return [{
80
+ provide: QueryStore,
81
+ useFactory: (time, destroyRef) => {
82
+ const queryStore = new QueryStore({
83
+ time,
84
+ gcTimeMs: options.gcTimeMs
85
+ });
86
+ destroyRef?.onDestroy(() => queryStore.dispose());
87
+ return queryStore;
88
+ },
89
+ deps: [TIME_TRAIT_TOKEN, [new SecurityDeptOptional(), SecuritydeptDestroyRef]]
90
+ }];
91
+ }
92
+ function useQueryStore() {
93
+ return useSecuritydeptContext().get(QueryStore);
94
+ }
95
+ /** @internal */
96
+ var QueryObserver = class {
97
+ store;
98
+ options;
99
+ subscribe = (listener) => {
100
+ const subscription = this.query().changes.subscribe({ next: listener });
101
+ return subscription.unsubscribe.bind(subscription);
102
+ };
103
+ getSnapshot = () => this.query().getResult();
104
+ getServerSnapshot = () => this.query().getResult();
105
+ constructor(store, options) {
106
+ this.store = store;
107
+ this.options = options;
108
+ }
109
+ query() {
110
+ return this.store.getOrCreateQuery(this.options);
111
+ }
112
+ };
113
+ var Query = class {
114
+ hash;
115
+ source;
116
+ scheduler;
117
+ changes;
118
+ garbageCollected;
119
+ state;
120
+ options;
121
+ subscriberCount = createSignal(0);
122
+ garbageCollectedSubject = new RxEventSubject();
123
+ destroyed = createSignal(false);
124
+ destroyed$ = from(this.destroyed).pipe(filter((destroyed) => destroyed), take(1));
125
+ constructor(hash, source, options, scheduler) {
126
+ this.hash = hash;
127
+ this.source = source;
128
+ this.scheduler = scheduler;
129
+ this.options = RxStateSignal.fromInitialValue(options);
130
+ this.garbageCollected = this.garbageCollectedSubject.asObservable();
131
+ const pendingPromise = firstValueFrom(RxEventStream.fromObservableInput(source.input).pipe(takeUntil(this.destroyed$)));
132
+ this.state = RxStateSignal.fromInitialValue({
133
+ status: QueryResultStatus.Pending,
134
+ promise: pendingPromise
135
+ });
136
+ this.changes = RxEventStream.fromObservableInput(defer(() => {
137
+ this.subscriberCount.set(this.subscriberCount.get() + 1);
138
+ return from(this.state).pipe(skip(1), map(() => void 0), takeUntil(this.destroyed$), finalize(() => {
139
+ this.subscriberCount.set(this.subscriberCount.get() - 1);
140
+ }));
141
+ }));
142
+ combineLatest([
143
+ from(this.subscriberCount),
144
+ from(this.state),
145
+ from(this.options)
146
+ ]).pipe(switchMap(([subscriberCount, state, gcOptions]) => {
147
+ if (subscriberCount !== 0 || state.status === QueryResultStatus.Pending && gcOptions.retainWhilePending || gcOptions.gcTimeMs === Number.POSITIVE_INFINITY) return NEVER;
148
+ return timer(gcOptions.gcTimeMs, this.scheduler).pipe(map(() => void 0));
149
+ }), takeUntil(this.destroyed$)).subscribe({ next: () => this.garbageCollectedSubject.next() });
150
+ pendingPromise.then((value) => {
151
+ this.state.set({
152
+ status: QueryResultStatus.Resolved,
153
+ value
154
+ });
155
+ }, (error) => {
156
+ this.state.set({
157
+ status: QueryResultStatus.Error,
158
+ error
159
+ });
160
+ });
161
+ }
162
+ updateOptions(options) {
163
+ const current = this.options.get();
164
+ this.options.set({
165
+ gcTimeMs: Math.max(current.gcTimeMs, options.gcTimeMs),
166
+ retainWhilePending: current.retainWhilePending || options.retainWhilePending
167
+ });
168
+ }
169
+ getResult() {
170
+ return this.state.get();
171
+ }
172
+ dispose() {
173
+ this.destroyed.set(true);
174
+ this.source.cancel();
175
+ }
176
+ [SYMBOL_DISPOSE]() {
177
+ this.dispose();
178
+ }
179
+ };
180
+ function validateGcTime(gcTimeMs) {
181
+ if (typeof gcTimeMs !== "number" || Number.isNaN(gcTimeMs) || gcTimeMs < 0) throw invalidQueryConfiguration("react.query.invalid_gc_time", "QueryStore gcTimeMs must be a non-negative number.");
182
+ return gcTimeMs;
183
+ }
184
+ /** @internal */
185
+ function hashQueryStoreKey(key) {
186
+ const ancestors = /* @__PURE__ */ new Set();
187
+ const normalize = (value) => {
188
+ if (value === null || typeof value === "boolean" || typeof value === "string") return value;
189
+ if (typeof value === "number") {
190
+ if (!Number.isFinite(value)) throw invalidQueryKey();
191
+ return value;
192
+ }
193
+ if (typeof value !== "object") throw invalidQueryKey();
194
+ if (ancestors.has(value)) throw invalidQueryKey();
195
+ ancestors.add(value);
196
+ try {
197
+ if (Array.isArray(value)) return value.map(normalize);
198
+ const prototype = Object.getPrototypeOf(value);
199
+ if (prototype !== Object.prototype && prototype !== null || Object.getOwnPropertySymbols(value).length !== 0) throw invalidQueryKey();
200
+ const normalized = Object.create(null);
201
+ for (const property of Object.keys(value).sort()) normalized[property] = normalize(value[property]);
202
+ return normalized;
203
+ } finally {
204
+ ancestors.delete(value);
205
+ }
206
+ };
207
+ return JSON.stringify(normalize(key));
208
+ }
209
+ function invalidQueryKey() {
210
+ return invalidQueryConfiguration("react.query.invalid_key", "Query keys must contain only finite JSON-compatible values.");
211
+ }
212
+ function invalidQueryConfiguration(code, message) {
213
+ return new ClientError({
214
+ kind: ClientErrorKind.Configuration,
215
+ code,
216
+ message,
217
+ source: QUERY_STORE_ERROR_SOURCE
72
218
  });
73
219
  }
220
+ //#endregion
221
+ //#region src/environment.ts
74
222
  /**
75
- * Get the effective requirements client set for the current React tree scope.
223
+ * Compose React-owned providers over a host or foundation environment creator.
76
224
  *
77
- * Returns the resolved options after applying all parent/child composition.
225
+ * React services are owned by the environment rather than the React fiber tree.
78
226
  */
79
- function useEffectiveClientSet() {
80
- return useContext(RequirementsClientSetContext);
227
+ function createEnvironmentForReact(options = {}) {
228
+ const { createBaseEnvironment = createFoundationEnvironment, providers = [], ...baseOptions } = options;
229
+ const reactProviders = new Set(providers.map((provider) => getSecuritydeptProviderToken(provider))).has(QueryStore) ? providers : [...provideQueryStore(), ...providers];
230
+ return createBaseEnvironment({
231
+ ...baseOptions,
232
+ providers: reactProviders
233
+ });
234
+ }
235
+ //#endregion
236
+ //#region src/hooks/use-initial-ref.ts
237
+ const UNINITIALIZED_REF = Symbol("securitydept.react.uninitialized_ref");
238
+ function useInitialRef(initialize) {
239
+ const ref = useRef(UNINITIALIZED_REF);
240
+ if (ref.current === UNINITIALIZED_REF) ref.current = initialize();
241
+ return ref;
242
+ }
243
+ //#endregion
244
+ //#region src/interop.ts
245
+ const EMPTY_DEPENDENCIES = [];
246
+ function useSignal(source) {
247
+ const subscribe = useCallback((listener) => {
248
+ const subscription = source.watchStream().subscribe({ next: listener });
249
+ return () => {
250
+ subscription.unsubscribe();
251
+ };
252
+ }, [source]);
253
+ const getSnapshot = useCallback(() => source.get(), [source]);
254
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
255
+ }
256
+ function useResourceSnapshot(source, dependencies) {
257
+ const computedSignal = useMemo(() => typeof source === "function" ? createComputed(source) : null, dependencies ?? EMPTY_DEPENDENCIES);
258
+ return useSignal(typeof source === "function" ? computedSignal : "snapshot" in source ? source.snapshot : source);
259
+ }
260
+ function useInteropObservable(source, options = {}) {
261
+ const initialValueProvided = Object.hasOwn(options, "initialValue");
262
+ const initialValue = options.initialValue;
263
+ const requireSync = options.requireSync;
264
+ const store = useMemo(() => createInteropObservableStore(source, {
265
+ initialValue,
266
+ initialValueProvided,
267
+ requireSync
268
+ }), [
269
+ source,
270
+ initialValue,
271
+ initialValueProvided,
272
+ requireSync
273
+ ]);
274
+ return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
275
+ }
276
+ function useEventStream(source, handler, options = {}) {
277
+ const handlerRef = useRef(handler);
278
+ handlerRef.current = handler;
279
+ useEffect(() => {
280
+ if (options.enabled === false) return;
281
+ const subscription = source.subscribe({ next: (event) => {
282
+ handlerRef.current(event);
283
+ } });
284
+ return () => {
285
+ subscription.unsubscribe();
286
+ };
287
+ }, [options.enabled, source]);
288
+ }
289
+ function createInteropObservableStore(source, options) {
290
+ const subscribable = isInteropObservableTrait(source) ? source[SYMBOL_OBSERVABLE]() : source;
291
+ let current = options.initialValueProvided ? options.initialValue : void 0;
292
+ let error;
293
+ if (options.requireSync === true) {
294
+ let syncEmitted = false;
295
+ subscribable.subscribe({
296
+ next(value) {
297
+ syncEmitted = true;
298
+ current = value;
299
+ },
300
+ error(nextError) {
301
+ error = nextError;
302
+ }
303
+ }).unsubscribe();
304
+ if (error !== void 0) throw error;
305
+ if (!syncEmitted) throw new Error("useInteropObservable() requires a synchronous emission.");
306
+ }
307
+ return {
308
+ getSnapshot() {
309
+ if (error !== void 0) throw error;
310
+ return current;
311
+ },
312
+ subscribe(listener) {
313
+ const subscription = subscribable.subscribe({
314
+ next(value) {
315
+ current = value;
316
+ listener();
317
+ },
318
+ error(nextError) {
319
+ error = nextError;
320
+ listener();
321
+ }
322
+ });
323
+ return () => {
324
+ subscription.unsubscribe();
325
+ };
326
+ }
327
+ };
328
+ }
329
+ //#endregion
330
+ //#region src/suspense-resource.ts
331
+ const SUSPENSE_RESOURCE_ERROR_SOURCE = "client-react.suspense-resource";
332
+ const BYPASSED_QUERY_STORE = Object.freeze({
333
+ subscribe: () => () => void 0,
334
+ getSnapshot: () => void 0,
335
+ getServerSnapshot: () => void 0
336
+ });
337
+ function useSuspenseResourceValue(source, options = {}) {
338
+ const queryStore = useQueryStore();
339
+ let hash;
340
+ let createSnapshotSignal;
341
+ let snapshotSignalDependencies;
342
+ if (typeof source === "function") {
343
+ const computedOptions = options;
344
+ const dependencies = computedOptions.dependencies;
345
+ if (!Array.isArray(dependencies)) throw new ClientError({
346
+ kind: ClientErrorKind.Configuration,
347
+ code: "react.query.computed_dependencies_required",
348
+ message: "useSuspenseResourceValue() requires dependencies for computed input.",
349
+ source: SUSPENSE_RESOURCE_ERROR_SOURCE
350
+ });
351
+ if (!Array.isArray(computedOptions.queryKey)) throw new ClientError({
352
+ kind: ClientErrorKind.Configuration,
353
+ code: "react.query.computed_query_key_required",
354
+ message: "useSuspenseResourceValue() requires a queryKey for computed input.",
355
+ source: SUSPENSE_RESOURCE_ERROR_SOURCE
356
+ });
357
+ hash = hashQueryStoreKey(["resource_compute", ...computedOptions.queryKey]);
358
+ createSnapshotSignal = () => createComputed(source);
359
+ snapshotSignalDependencies = dependencies;
360
+ } else {
361
+ const snapshotSignal = "snapshot" in source ? source.snapshot : source;
362
+ hash = hashQueryStoreKey([
363
+ "resource_snapshot",
364
+ { sourceId: queryStore.getWeakKeyId(snapshotSignal) },
365
+ ...options.queryKey ?? []
366
+ ]);
367
+ createSnapshotSignal = () => snapshotSignal;
368
+ snapshotSignalDependencies = [snapshotSignal];
369
+ }
370
+ const snapshotSignal = useMemo(createSnapshotSignal, snapshotSignalDependencies);
371
+ const snapshot = useResourceSnapshot(snapshotSignal);
372
+ const queryRequired = snapshot.status === ResourceStatus.Idle || snapshot.status === ResourceStatus.Loading;
373
+ const queryStoreBindings = useMemo(() => {
374
+ if (!queryRequired) return BYPASSED_QUERY_STORE;
375
+ const observer = new QueryObserver(queryStore, {
376
+ hash,
377
+ source: () => {
378
+ const cancellation = createCancellationTokenSource();
379
+ return {
380
+ cancel: () => cancellation.cancel(),
381
+ input: whenResourceSnapshotValue(snapshotSignal, { cancellationToken: cancellation.token })
382
+ };
383
+ },
384
+ gcTimeMs: options.gcTimeMs,
385
+ retainWhilePending: options.retainWhilePending
386
+ });
387
+ return {
388
+ subscribe: observer.subscribe,
389
+ getSnapshot: observer.getSnapshot,
390
+ getServerSnapshot: observer.getServerSnapshot
391
+ };
392
+ }, [
393
+ queryRequired,
394
+ queryStore,
395
+ hash,
396
+ options.gcTimeMs,
397
+ options.retainWhilePending,
398
+ snapshotSignal
399
+ ]);
400
+ const result = useSyncExternalStore(queryStoreBindings.subscribe, queryStoreBindings.getSnapshot, queryStoreBindings.getServerSnapshot);
401
+ switch (snapshot.status) {
402
+ case ResourceStatus.Idle:
403
+ case ResourceStatus.Loading: {
404
+ const queryResult = result;
405
+ if (queryResult.status === QueryResultStatus.Pending) throw queryResult.promise;
406
+ if (queryResult.status === QueryResultStatus.Error) throw queryResult.error;
407
+ return queryResult.value;
408
+ }
409
+ case ResourceStatus.LoadingError: throw snapshot.error;
410
+ case ResourceStatus.Reloading:
411
+ case ResourceStatus.Resolved:
412
+ case ResourceStatus.Error: return snapshot.value;
413
+ }
81
414
  }
82
415
  //#endregion
83
- export { AuthPlannerHostProvider, AuthRequirementsClientSetProvider, resolveEffectiveClientSet, useAuthPlannerHost, useEffectiveClientSet };
416
+ export { QueryStore, SecuritydeptContext, SecuritydeptProvider, createEnvironmentForReact, provideQueryStore, useEventStream, useInitialRef, useInteropObservable, useQueryStore, useResourceSnapshot, useSecuritydeptContext, useSignal, useSuspenseResourceValue };
84
417
 
85
418
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/planner-host/index.tsx"],"sourcesContent":["// React planner-host integration — Context-based planner provider / lookup\n//\n// Canonical import path:\n// import { AuthPlannerHostProvider, useAuthPlannerHost, ... } from \"@securitydept/client-react\"\n//\n// Provides React Context glue for the shared planner-host contract:\n// - AuthPlannerHostProvider: provides a PlannerHost at a React tree scope\n// - useAuthPlannerHost(): hook to look up the nearest PlannerHost (fail-fast)\n// - AuthRequirementsClientSetProvider: provides scoped requirement client sets\n// - useEffectiveClientSet(): resolves the current scope's effective client set\n//\n// Architecture boundary:\n// - Does NOT own the planner-host contract (that lives in @securitydept/client)\n// - Does NOT carry token-set-specific mapping\n// - Provides the React Context wiring for the shared contract\n//\n// Stability: provisional\n\nimport type {\n\tAuthGuardClientOption,\n\tCandidateSelector,\n\tPlannerHost,\n\tScopedRequirementsClientSet,\n} from \"@securitydept/client/auth-coordination\";\nimport {\n\tcreatePlannerHost,\n\tresolveEffectiveClientSet,\n} from \"@securitydept/client/auth-coordination\";\nimport { createContext, type ReactNode, useContext, useMemo } from \"react\";\n\n// ---------------------------------------------------------------------------\n// PlannerHost context\n// ---------------------------------------------------------------------------\n\nconst PlannerHostContext = createContext<PlannerHost | null>(null);\n\n/** Props for {@link AuthPlannerHostProvider}. */\nexport interface AuthPlannerHostProviderProps {\n\t/**\n\t * Custom candidate selection strategy.\n\t * @see {@link CandidateSelector}\n\t */\n\tselectCandidate?: CandidateSelector;\n\n\t/**\n\t * Pre-constructed PlannerHost instance to use.\n\t * If provided, `selectCandidate` is ignored.\n\t */\n\tplannerHost?: PlannerHost;\n\n\tchildren: ReactNode;\n}\n\n/**\n * Provide a {@link PlannerHost} at the current React tree scope.\n *\n * Use at the app level or at feature-route boundaries to establish\n * planner-host scopes. Child components inherit the nearest provider.\n *\n * @example\n * ```tsx\n * // App-level (default sequential strategy)\n * <AuthPlannerHostProvider>\n * <App />\n * </AuthPlannerHostProvider>\n *\n * // Feature-route with custom chooser\n * <AuthPlannerHostProvider selectCandidate={showChooser}>\n * <FeatureRoutes />\n * </AuthPlannerHostProvider>\n * ```\n */\nexport function AuthPlannerHostProvider({\n\tselectCandidate,\n\tplannerHost,\n\tchildren,\n}: AuthPlannerHostProviderProps) {\n\tconst host = useMemo(() => {\n\t\tif (plannerHost) return plannerHost;\n\t\treturn createPlannerHost(selectCandidate ? { selectCandidate } : undefined);\n\t}, [plannerHost, selectCandidate]);\n\n\treturn (\n\t\t<PlannerHostContext.Provider value={host}>\n\t\t\t{children}\n\t\t</PlannerHostContext.Provider>\n\t);\n}\n\n/**\n * Look up the nearest {@link PlannerHost} from the React Context tree.\n *\n * Throws an explicit error if no provider is found, preventing\n * silent fallback behavior.\n */\nexport function useAuthPlannerHost(): PlannerHost {\n\tconst host = useContext(PlannerHostContext);\n\tif (!host) {\n\t\tthrow new Error(\n\t\t\t\"[useAuthPlannerHost] No AuthPlannerHostProvider found in the component tree. \" +\n\t\t\t\t\"Wrap your app or route with <AuthPlannerHostProvider>.\",\n\t\t);\n\t}\n\treturn host;\n}\n\n// ---------------------------------------------------------------------------\n// Requirements client set context\n// ---------------------------------------------------------------------------\n\nconst RequirementsClientSetContext = createContext<\n\treadonly AuthGuardClientOption[]\n>([]);\n\n/** Props for {@link AuthRequirementsClientSetProvider}. */\nexport interface AuthRequirementsClientSetProviderProps {\n\t/** The scoped set to provide at this level. */\n\tscopedSet: ScopedRequirementsClientSet;\n\tchildren: ReactNode;\n}\n\n/**\n * Provide a {@link ScopedRequirementsClientSet} at the current React tree scope.\n *\n * Automatically resolves the effective client set by composing with the\n * parent scope's options according to the declared composition strategy.\n *\n * @example\n * ```tsx\n * // Feature route: merge OIDC requirement with parent's session requirement\n * <AuthRequirementsClientSetProvider\n * scopedSet={{\n * composition: RequirementsClientSetComposition.Merge,\n * options: [oidcClientOption],\n * }}\n * >\n * <ProtectedFeature />\n * </AuthRequirementsClientSetProvider>\n * ```\n */\nexport function AuthRequirementsClientSetProvider({\n\tscopedSet,\n\tchildren,\n}: AuthRequirementsClientSetProviderProps) {\n\tconst parentOptions = useContext(RequirementsClientSetContext);\n\tconst effective = useMemo(\n\t\t() => resolveEffectiveClientSet(parentOptions, scopedSet),\n\t\t[parentOptions, scopedSet],\n\t);\n\n\treturn (\n\t\t<RequirementsClientSetContext.Provider value={effective}>\n\t\t\t{children}\n\t\t</RequirementsClientSetContext.Provider>\n\t);\n}\n\n/**\n * Get the effective requirements client set for the current React tree scope.\n *\n * Returns the resolved options after applying all parent/child composition.\n */\nexport function useEffectiveClientSet(): readonly AuthGuardClientOption[] {\n\treturn useContext(RequirementsClientSetContext);\n}\n\n// Re-export composition constant for consumer convenience\nexport { resolveEffectiveClientSet };\n"],"mappings":";;;;AAkCA,MAAM,qBAAqB,cAAkC,KAAK;;;;;;;;;;;;;;;;;;;;AAsClE,SAAgB,wBAAwB,EACvC,iBACA,aACA,YACgC;CAChC,MAAM,OAAO,cAAc;AAC1B,MAAI,YAAa,QAAO;AACxB,SAAO,kBAAkB,kBAAkB,EAAE,iBAAiB,GAAG,KAAA,EAAU;IACzE,CAAC,aAAa,gBAAgB,CAAC;AAElC,QACC,oBAAC,mBAAmB,UAApB;EAA6B,OAAO;EAClC;EAC4B,CAAA;;;;;;;;AAUhC,SAAgB,qBAAkC;CACjD,MAAM,OAAO,WAAW,mBAAmB;AAC3C,KAAI,CAAC,KACJ,OAAM,IAAI,MACT,sIAEA;AAEF,QAAO;;AAOR,MAAM,+BAA+B,cAEnC,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;AA4BL,SAAgB,kCAAkC,EACjD,WACA,YAC0C;CAC1C,MAAM,gBAAgB,WAAW,6BAA6B;CAC9D,MAAM,YAAY,cACX,0BAA0B,eAAe,UAAU,EACzD,CAAC,eAAe,UAAU,CAC1B;AAED,QACC,oBAAC,6BAA6B,UAA9B;EAAuC,OAAO;EAC5C;EACsC,CAAA;;;;;;;AAS1C,SAAgB,wBAA0D;AACzE,QAAO,WAAW,6BAA6B"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/injection/index.tsx","../src/query-store.ts","../src/environment.ts","../src/hooks/use-initial-ref.ts","../src/interop.ts","../src/suspense-resource.ts"],"sourcesContent":["import { type SecuritydeptInjectorTrait } from \"@securitydept/client\";\nimport { createContext, type ReactNode, useContext } from \"react\";\n\nexport const SecuritydeptContext =\n\tcreateContext<SecuritydeptInjectorTrait | null>(null);\n\nexport interface SecuritydeptProviderProps {\n\treadonly injector: SecuritydeptInjectorTrait;\n\treadonly children?: ReactNode;\n}\n\nexport function SecuritydeptProvider({\n\tinjector,\n\tchildren,\n}: SecuritydeptProviderProps) {\n\treturn (\n\t\t<SecuritydeptContext.Provider value={injector}>\n\t\t\t{children}\n\t\t</SecuritydeptContext.Provider>\n\t);\n}\n\nexport function useSecuritydeptContext(): SecuritydeptInjectorTrait {\n\tconst injector = useContext(SecuritydeptContext);\n\tif (!injector) {\n\t\tthrow new Error(\n\t\t\t\"[useSecuritydeptContext] No SecuritydeptProvider found in the component tree.\",\n\t\t);\n\t}\n\treturn injector;\n}\n","import {\n\tClientError,\n\tClientErrorKind,\n\tcreateSignal,\n\ttype DisposableTrait,\n\ttype EventStreamTrait,\n\tSecurityDeptOptional,\n\tSecuritydeptDestroyRef,\n\ttype SecuritydeptProvider,\n\tSYMBOL_DISPOSE,\n\tTIME_TRAIT_TOKEN,\n\ttype TimeTrait,\n\ttype ToEventStreamInput,\n\ttype WritableSignalTrait,\n} from \"@securitydept/client\";\nimport {\n\tcreateAsyncSchedulerWithTimestampProvider,\n\tRxEventStream,\n\tRxEventSubject,\n\tRxStateSignal,\n} from \"@securitydept/client/rx\";\nimport {\n\tcombineLatest,\n\tdefer,\n\tfilter,\n\tfinalize,\n\tfirstValueFrom,\n\tfrom,\n\tmap,\n\tNEVER,\n\ttype SchedulerLike,\n\tskip,\n\tswitchMap,\n\ttake,\n\ttakeUntil,\n\ttimer,\n} from \"rxjs\";\nimport { useSecuritydeptContext } from \"./injection/index\";\n\nconst QUERY_STORE_ERROR_SOURCE = \"client-react.query-store\";\n\nexport type QueryStoreKeyValue =\n\t| null\n\t| boolean\n\t| number\n\t| string\n\t| readonly QueryStoreKeyValue[]\n\t| { readonly [key: string]: QueryStoreKeyValue };\n\nexport type QueryStoreKey = readonly QueryStoreKeyValue[];\n\nexport interface QueryStoreOptions {\n\treadonly time: TimeTrait;\n\treadonly gcTimeMs?: number;\n}\n\nexport interface ProvideQueryStoreOptions {\n\treadonly gcTimeMs?: number;\n}\n\n/** @internal */\nexport const QueryResultStatus = {\n\tPending: \"pending\",\n\tResolved: \"resolved\",\n\tError: \"error\",\n} as const;\n\n/** @internal */\nexport type QueryResult<T> =\n\t| {\n\t\t\treadonly status: typeof QueryResultStatus.Pending;\n\t\t\treadonly promise: Promise<T>;\n\t }\n\t| {\n\t\t\treadonly status: typeof QueryResultStatus.Resolved;\n\t\t\treadonly value: T;\n\t }\n\t| {\n\t\t\treadonly status: typeof QueryResultStatus.Error;\n\t\t\treadonly error: unknown;\n\t };\n\n/** @internal */\nexport type QueryInput<T> = ToEventStreamInput<T>;\n\n/** @internal */\nexport interface QuerySource<T> {\n\treadonly input: QueryInput<T>;\n\treadonly cancel: VoidFunction;\n}\n\n/** @internal */\nexport interface QueryStoreQueryOptions<T> {\n\treadonly hash: string;\n\treadonly source: () => QuerySource<T>;\n\treadonly gcTimeMs?: number;\n\treadonly retainWhilePending?: boolean;\n}\n\ninterface ResolvedQueryOptions {\n\treadonly gcTimeMs: number;\n\treadonly retainWhilePending: boolean;\n}\n\nexport class QueryStore implements DisposableTrait {\n\tstatic readonly defaultOptions = Object.freeze({\n\t\tgcTimeMs: 300_000,\n\t});\n\n\tprivate readonly queries = new Map<string, Query<unknown>>();\n\tprivate readonly weakKeyIds = new WeakMap<object, string>();\n\tprivate readonly scheduler: SchedulerLike;\n\tprivate readonly gcTimeMs: number;\n\tprivate nextWeakKeyId = 0;\n\tprivate disposed = false;\n\n\tconstructor(options: QueryStoreOptions) {\n\t\tthis.scheduler = createAsyncSchedulerWithTimestampProvider(options.time);\n\t\tthis.gcTimeMs = validateGcTime(\n\t\t\toptions.gcTimeMs ?? QueryStore.defaultOptions.gcTimeMs,\n\t\t);\n\t}\n\n\tgetWeakKeyId(value: object): string {\n\t\tconst existing = this.weakKeyIds.get(value);\n\t\tif (existing !== undefined) {\n\t\t\treturn existing;\n\t\t}\n\t\tconst id = `weak_${++this.nextWeakKeyId}`;\n\t\tthis.weakKeyIds.set(value, id);\n\t\treturn id;\n\t}\n\n\tdispose(): void {\n\t\tif (this.disposed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.disposed = true;\n\t\tfor (const query of this.queries.values()) {\n\t\t\tquery.dispose();\n\t\t}\n\t\tthis.queries.clear();\n\t}\n\n\t[SYMBOL_DISPOSE](): void {\n\t\tthis.dispose();\n\t}\n\n\t/** @internal */\n\tgetOrCreateQuery<T>(options: QueryStoreQueryOptions<T>): Query<T> {\n\t\tconst existing = this.queries.get(options.hash) as Query<T> | undefined;\n\t\tconst resolvedOptions = {\n\t\t\tgcTimeMs: validateGcTime(options.gcTimeMs ?? this.gcTimeMs),\n\t\t\tretainWhilePending: options.retainWhilePending ?? true,\n\t\t};\n\t\tif (existing) {\n\t\t\texisting.updateOptions(resolvedOptions);\n\t\t\treturn existing;\n\t\t}\n\t\tconst query = new Query(\n\t\t\toptions.hash,\n\t\t\toptions.source(),\n\t\t\tresolvedOptions,\n\t\t\tthis.scheduler,\n\t\t);\n\t\tthis.queries.set(options.hash, query as Query<unknown>);\n\t\tquery.garbageCollected.subscribe({\n\t\t\tnext: () => this.removeQuery(query as unknown as Query<unknown>),\n\t\t});\n\t\treturn query;\n\t}\n\n\tprivate removeQuery(query: Query<unknown>): void {\n\t\tif (this.queries.get(query.hash) !== query) {\n\t\t\treturn;\n\t\t}\n\t\tthis.queries.delete(query.hash);\n\t\tquery.dispose();\n\t}\n}\n\nexport function provideQueryStore(\n\toptions: ProvideQueryStoreOptions = {},\n): readonly SecuritydeptProvider[] {\n\treturn [\n\t\t{\n\t\t\tprovide: QueryStore,\n\t\t\tuseFactory: (\n\t\t\t\ttime: TimeTrait,\n\t\t\t\tdestroyRef: SecuritydeptDestroyRef | null,\n\t\t\t) => {\n\t\t\t\tconst queryStore = new QueryStore({\n\t\t\t\t\ttime,\n\t\t\t\t\tgcTimeMs: options.gcTimeMs,\n\t\t\t\t});\n\t\t\t\tdestroyRef?.onDestroy(() => queryStore.dispose());\n\t\t\t\treturn queryStore;\n\t\t\t},\n\t\t\tdeps: [\n\t\t\t\tTIME_TRAIT_TOKEN,\n\t\t\t\t[new SecurityDeptOptional(), SecuritydeptDestroyRef],\n\t\t\t],\n\t\t} satisfies SecuritydeptProvider,\n\t];\n}\n\nexport function useQueryStore(): QueryStore {\n\treturn useSecuritydeptContext().get(QueryStore);\n}\n\n/** @internal */\nexport class QueryObserver<T> {\n\treadonly subscribe = (listener: () => void): (() => void) => {\n\t\tconst subscription = this.query().changes.subscribe({ next: listener });\n\t\treturn subscription.unsubscribe.bind(subscription);\n\t};\n\treadonly getSnapshot = (): QueryResult<T> => this.query().getResult();\n\treadonly getServerSnapshot = (): QueryResult<T> => this.query().getResult();\n\n\tconstructor(\n\t\tprivate readonly store: QueryStore,\n\t\tprivate readonly options: QueryStoreQueryOptions<T>,\n\t) {}\n\n\tprivate query(): Query<T> {\n\t\treturn this.store.getOrCreateQuery(this.options);\n\t}\n}\n\nclass Query<T> implements DisposableTrait {\n\treadonly changes: EventStreamTrait<void>;\n\treadonly garbageCollected: EventStreamTrait<void>;\n\tprivate readonly state: WritableSignalTrait<QueryResult<T>>;\n\tprivate readonly options: WritableSignalTrait<ResolvedQueryOptions>;\n\tprivate readonly subscriberCount = createSignal<number>(0);\n\tprivate readonly garbageCollectedSubject = new RxEventSubject<void>();\n\tprivate readonly destroyed = createSignal<boolean>(false);\n\tprivate readonly destroyed$ = from(this.destroyed).pipe(\n\t\tfilter((destroyed) => destroyed),\n\t\ttake(1),\n\t);\n\n\tconstructor(\n\t\treadonly hash: string,\n\t\tprivate readonly source: QuerySource<T>,\n\t\toptions: ResolvedQueryOptions,\n\t\tprivate readonly scheduler: SchedulerLike,\n\t) {\n\t\tthis.options = RxStateSignal.fromInitialValue(options);\n\t\tthis.garbageCollected = this.garbageCollectedSubject.asObservable();\n\n\t\tconst pendingPromise = firstValueFrom(\n\t\t\tRxEventStream.fromObservableInput(source.input).pipe(\n\t\t\t\ttakeUntil(this.destroyed$),\n\t\t\t),\n\t\t);\n\t\tthis.state = RxStateSignal.fromInitialValue<QueryResult<T>>({\n\t\t\tstatus: QueryResultStatus.Pending,\n\t\t\tpromise: pendingPromise,\n\t\t});\n\n\t\tthis.changes = RxEventStream.fromObservableInput(\n\t\t\tdefer(() => {\n\t\t\t\tthis.subscriberCount.set(this.subscriberCount.get() + 1);\n\t\t\t\treturn from(this.state).pipe(\n\t\t\t\t\tskip(1),\n\t\t\t\t\tmap(() => undefined),\n\t\t\t\t\ttakeUntil(this.destroyed$),\n\t\t\t\t\tfinalize(() => {\n\t\t\t\t\t\tthis.subscriberCount.set(this.subscriberCount.get() - 1);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}),\n\t\t);\n\t\tcombineLatest([\n\t\t\tfrom(this.subscriberCount),\n\t\t\tfrom(this.state),\n\t\t\tfrom(this.options),\n\t\t])\n\t\t\t.pipe(\n\t\t\t\tswitchMap(([subscriberCount, state, gcOptions]) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\tsubscriberCount !== 0 ||\n\t\t\t\t\t\t(state.status === QueryResultStatus.Pending &&\n\t\t\t\t\t\t\tgcOptions.retainWhilePending) ||\n\t\t\t\t\t\tgcOptions.gcTimeMs === Number.POSITIVE_INFINITY\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn NEVER;\n\t\t\t\t\t}\n\t\t\t\t\treturn timer(gcOptions.gcTimeMs, this.scheduler).pipe(\n\t\t\t\t\t\tmap(() => undefined),\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t\ttakeUntil(this.destroyed$),\n\t\t\t)\n\t\t\t.subscribe({\n\t\t\t\tnext: () => this.garbageCollectedSubject.next(),\n\t\t\t});\n\n\t\tpendingPromise.then(\n\t\t\t(value) => {\n\t\t\t\tthis.state.set({ status: QueryResultStatus.Resolved, value });\n\t\t\t},\n\t\t\t(error) => {\n\t\t\t\tthis.state.set({ status: QueryResultStatus.Error, error });\n\t\t\t},\n\t\t);\n\t}\n\n\tupdateOptions(options: ResolvedQueryOptions): void {\n\t\tconst current = this.options.get();\n\t\tthis.options.set({\n\t\t\tgcTimeMs: Math.max(current.gcTimeMs, options.gcTimeMs),\n\t\t\tretainWhilePending:\n\t\t\t\tcurrent.retainWhilePending || options.retainWhilePending,\n\t\t});\n\t}\n\n\tgetResult(): QueryResult<T> {\n\t\treturn this.state.get();\n\t}\n\n\tdispose(): void {\n\t\tthis.destroyed.set(true);\n\t\tthis.source.cancel();\n\t}\n\n\t[SYMBOL_DISPOSE](): void {\n\t\tthis.dispose();\n\t}\n}\n\nfunction validateGcTime(gcTimeMs: number): number {\n\tif (typeof gcTimeMs !== \"number\" || Number.isNaN(gcTimeMs) || gcTimeMs < 0) {\n\t\tthrow invalidQueryConfiguration(\n\t\t\t\"react.query.invalid_gc_time\",\n\t\t\t\"QueryStore gcTimeMs must be a non-negative number.\",\n\t\t);\n\t}\n\treturn gcTimeMs;\n}\n\n/** @internal */\nexport function hashQueryStoreKey(key: QueryStoreKey): string {\n\tconst ancestors = new Set<object>();\n\tconst normalize = (value: unknown): QueryStoreKeyValue => {\n\t\tif (\n\t\t\tvalue === null ||\n\t\t\ttypeof value === \"boolean\" ||\n\t\t\ttypeof value === \"string\"\n\t\t) {\n\t\t\treturn value;\n\t\t}\n\t\tif (typeof value === \"number\") {\n\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\tthrow invalidQueryKey();\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tif (typeof value !== \"object\") {\n\t\t\tthrow invalidQueryKey();\n\t\t}\n\t\tif (ancestors.has(value)) {\n\t\t\tthrow invalidQueryKey();\n\t\t}\n\t\tancestors.add(value);\n\t\ttry {\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\treturn value.map(normalize);\n\t\t\t}\n\t\t\tconst prototype = Object.getPrototypeOf(value);\n\t\t\tif (\n\t\t\t\t(prototype !== Object.prototype && prototype !== null) ||\n\t\t\t\tObject.getOwnPropertySymbols(value).length !== 0\n\t\t\t) {\n\t\t\t\tthrow invalidQueryKey();\n\t\t\t}\n\t\t\tconst normalized: Record<string, QueryStoreKeyValue> =\n\t\t\t\tObject.create(null);\n\t\t\tfor (const property of Object.keys(value).sort()) {\n\t\t\t\tnormalized[property] = normalize(\n\t\t\t\t\t(value as Record<string, unknown>)[property],\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn normalized;\n\t\t} finally {\n\t\t\tancestors.delete(value);\n\t\t}\n\t};\n\treturn JSON.stringify(normalize(key));\n}\n\nfunction invalidQueryKey(): ClientError {\n\treturn invalidQueryConfiguration(\n\t\t\"react.query.invalid_key\",\n\t\t\"Query keys must contain only finite JSON-compatible values.\",\n\t);\n}\n\nfunction invalidQueryConfiguration(code: string, message: string): ClientError {\n\treturn new ClientError({\n\t\tkind: ClientErrorKind.Configuration,\n\t\tcode,\n\t\tmessage,\n\t\tsource: QUERY_STORE_ERROR_SOURCE,\n\t});\n}\n","import {\n\ttype CreateFoundationEnvironmentOptions,\n\tcreateFoundationEnvironment,\n\ttype FoundationEnvironment,\n\tgetSecuritydeptProviderToken,\n\ttype SecuritydeptProvider,\n} from \"@securitydept/client\";\nimport { provideQueryStore, QueryStore } from \"./query-store\";\n\nexport type ReactEnvironmentCreatorOptions = {\n\tproviders?: readonly SecuritydeptProvider[];\n};\n\nexport type ReactEnvironmentCreator<\n\tTOptions extends ReactEnvironmentCreatorOptions,\n\tTEnvironment extends FoundationEnvironment,\n> = (options: TOptions) => TEnvironment;\n\nexport interface CreateEnvironmentForReactOptions\n\textends CreateFoundationEnvironmentOptions {}\n\nexport type CreateEnvironmentForReactWithBaseOptions<\n\tTBaseOptions extends ReactEnvironmentCreatorOptions,\n\tTEnvironment extends FoundationEnvironment,\n> = Omit<TBaseOptions, \"providers\" | \"createBaseEnvironment\"> & {\n\tcreateBaseEnvironment: ReactEnvironmentCreator<TBaseOptions, TEnvironment>;\n\tproviders?: readonly SecuritydeptProvider[];\n};\n\nexport function createEnvironmentForReact(): FoundationEnvironment;\nexport function createEnvironmentForReact(\n\toptions: CreateEnvironmentForReactOptions,\n): FoundationEnvironment;\nexport function createEnvironmentForReact<\n\tTBaseOptions extends ReactEnvironmentCreatorOptions,\n\tTEnvironment extends FoundationEnvironment,\n>(\n\toptions: CreateEnvironmentForReactWithBaseOptions<TBaseOptions, TEnvironment>,\n): TEnvironment;\n/**\n * Compose React-owned providers over a host or foundation environment creator.\n *\n * React services are owned by the environment rather than the React fiber tree.\n */\nexport function createEnvironmentForReact(\n\toptions:\n\t\t| CreateEnvironmentForReactOptions\n\t\t| CreateEnvironmentForReactWithBaseOptions<\n\t\t\t\tReactEnvironmentCreatorOptions,\n\t\t\t\tFoundationEnvironment\n\t\t > = {},\n): FoundationEnvironment {\n\tconst {\n\t\tcreateBaseEnvironment = createFoundationEnvironment,\n\t\tproviders = [],\n\t\t...baseOptions\n\t} = options as CreateEnvironmentForReactWithBaseOptions<\n\t\tReactEnvironmentCreatorOptions,\n\t\tFoundationEnvironment\n\t> &\n\t\tCreateEnvironmentForReactOptions;\n\tconst providerTokens = new Set(\n\t\tproviders.map((provider) => getSecuritydeptProviderToken(provider)),\n\t);\n\tconst reactProviders = providerTokens.has(QueryStore)\n\t\t? providers\n\t\t: [...provideQueryStore(), ...providers];\n\n\treturn createBaseEnvironment({\n\t\t...(baseOptions as Omit<ReactEnvironmentCreatorOptions, \"providers\">),\n\t\tproviders: reactProviders,\n\t});\n}\n","import { type RefObject, useRef } from \"react\";\n\nconst UNINITIALIZED_REF = Symbol(\"securitydept.react.uninitialized_ref\");\n\nexport function useInitialRef<T>(initialize: () => T): RefObject<T> {\n\tconst ref = useRef<T | typeof UNINITIALIZED_REF>(UNINITIALIZED_REF);\n\tif (ref.current === UNINITIALIZED_REF) {\n\t\tref.current = initialize();\n\t}\n\treturn ref as RefObject<T>;\n}\n","import {\n\tcreateComputed,\n\ttype EventStreamTrait,\n\ttype InteropObservableTrait,\n\tisInteropObservableTrait,\n\ttype ReadableSignalTrait,\n\ttype ResourceSnapshot,\n\ttype ResourceTrait,\n\ttype SubscribableTrait,\n\tSYMBOL_OBSERVABLE,\n} from \"@securitydept/client\";\nimport {\n\ttype DependencyList,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseSyncExternalStore,\n} from \"react\";\n\nconst EMPTY_DEPENDENCIES: DependencyList = [];\n\nexport function useSignal<T>(source: ReadableSignalTrait<T>): T {\n\tconst subscribe = useCallback(\n\t\t(listener: () => void) => {\n\t\t\tconst subscription = source.watchStream().subscribe({\n\t\t\t\tnext: listener,\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tsubscription.unsubscribe();\n\t\t\t};\n\t\t},\n\t\t[source],\n\t);\n\tconst getSnapshot = useCallback(() => source.get(), [source]);\n\n\treturn useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nexport function useResourceSnapshot<T>(\n\tresource: ResourceTrait<T>,\n): ResourceSnapshot<T>;\nexport function useResourceSnapshot<T>(\n\tsnapshot: ReadableSignalTrait<ResourceSnapshot<T>>,\n): ResourceSnapshot<T>;\nexport function useResourceSnapshot<T>(\n\tcompute: () => ResourceSnapshot<T>,\n\tdependencies: DependencyList,\n): ResourceSnapshot<T>;\nexport function useResourceSnapshot<T>(\n\tsource:\n\t\t| ResourceTrait<T>\n\t\t| ReadableSignalTrait<ResourceSnapshot<T>>\n\t\t| (() => ResourceSnapshot<T>),\n\tdependencies?: DependencyList,\n): ResourceSnapshot<T> {\n\tconst computedSignal = useMemo(\n\t\t() => (typeof source === \"function\" ? createComputed(source) : null),\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: The caller owns the computation's React closure dependencies.\n\t\tdependencies ?? EMPTY_DEPENDENCIES,\n\t);\n\tconst snapshotSignal =\n\t\ttypeof source === \"function\"\n\t\t\t? (computedSignal as ReadableSignalTrait<ResourceSnapshot<T>>)\n\t\t\t: \"snapshot\" in source\n\t\t\t\t? source.snapshot\n\t\t\t\t: source;\n\treturn useSignal(snapshotSignal);\n}\n\nexport interface UseInteropObservableOptions<T> {\n\tinitialValue?: T;\n\trequireSync?: boolean;\n}\n\nexport function useInteropObservable<T>(\n\tsource: InteropObservableTrait<T> | SubscribableTrait<T>,\n): T | undefined;\nexport function useInteropObservable<T>(\n\tsource: InteropObservableTrait<T> | SubscribableTrait<T>,\n\toptions: UseInteropObservableOptions<T> & {\n\t\tinitialValue?: undefined;\n\t\trequireSync?: false;\n\t},\n): T | undefined;\nexport function useInteropObservable<T>(\n\tsource: InteropObservableTrait<T> | SubscribableTrait<T>,\n\toptions: UseInteropObservableOptions<T | null> & {\n\t\tinitialValue?: null;\n\t\trequireSync?: false;\n\t},\n): T | null;\nexport function useInteropObservable<T>(\n\tsource: InteropObservableTrait<T> | SubscribableTrait<T>,\n\toptions: UseInteropObservableOptions<T> & {\n\t\tinitialValue?: undefined;\n\t\trequireSync: true;\n\t},\n): T;\nexport function useInteropObservable<T, const U extends T>(\n\tsource: InteropObservableTrait<T> | SubscribableTrait<T>,\n\toptions: UseInteropObservableOptions<T | U> & {\n\t\tinitialValue: U;\n\t\trequireSync?: false;\n\t},\n): T | U;\nexport function useInteropObservable<T>(\n\tsource: InteropObservableTrait<T> | SubscribableTrait<T>,\n\toptions: UseInteropObservableOptions<T | undefined> = {},\n): T | undefined {\n\tconst initialValueProvided = Object.hasOwn(options, \"initialValue\");\n\tconst initialValue = options.initialValue;\n\tconst requireSync = options.requireSync;\n\tconst store = useMemo(\n\t\t() =>\n\t\t\tcreateInteropObservableStore(source, {\n\t\t\t\tinitialValue,\n\t\t\t\tinitialValueProvided,\n\t\t\t\trequireSync,\n\t\t\t}),\n\t\t[source, initialValue, initialValueProvided, requireSync],\n\t);\n\treturn useSyncExternalStore(\n\t\tstore.subscribe,\n\t\tstore.getSnapshot,\n\t\tstore.getSnapshot,\n\t);\n}\n\nexport function useEventStream<T>(\n\tsource: EventStreamTrait<T>,\n\thandler: (event: T) => void,\n\toptions: { enabled?: boolean } = {},\n): void {\n\tconst handlerRef = useRef(handler);\n\thandlerRef.current = handler;\n\n\tuseEffect(() => {\n\t\tif (options.enabled === false) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst subscription = source.subscribe({\n\t\t\tnext: (event) => {\n\t\t\t\thandlerRef.current(event);\n\t\t\t},\n\t\t});\n\n\t\treturn () => {\n\t\t\tsubscription.unsubscribe();\n\t\t};\n\t}, [options.enabled, source]);\n}\n\nfunction createInteropObservableStore<T>(\n\tsource: InteropObservableTrait<T> | SubscribableTrait<T>,\n\toptions: {\n\t\tinitialValue: T | undefined;\n\t\tinitialValueProvided: boolean;\n\t\trequireSync?: boolean;\n\t},\n): {\n\tgetSnapshot(): T | undefined;\n\tsubscribe(listener: () => void): () => void;\n} {\n\tconst subscribable = (\n\t\tisInteropObservableTrait(source) ? source[SYMBOL_OBSERVABLE]() : source\n\t) as SubscribableTrait<T>;\n\tlet current = options.initialValueProvided ? options.initialValue : undefined;\n\tlet error: unknown;\n\n\tif (options.requireSync === true) {\n\t\tlet syncEmitted = false;\n\t\tconst subscription = subscribable.subscribe({\n\t\t\tnext(value) {\n\t\t\t\tsyncEmitted = true;\n\t\t\t\tcurrent = value;\n\t\t\t},\n\t\t\terror(nextError) {\n\t\t\t\terror = nextError;\n\t\t\t},\n\t\t});\n\t\tsubscription.unsubscribe();\n\t\tif (error !== undefined) {\n\t\t\tthrow error;\n\t\t}\n\t\tif (!syncEmitted) {\n\t\t\tthrow new Error(\n\t\t\t\t\"useInteropObservable() requires a synchronous emission.\",\n\t\t\t);\n\t\t}\n\t}\n\n\treturn {\n\t\tgetSnapshot() {\n\t\t\tif (error !== undefined) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn current;\n\t\t},\n\t\tsubscribe(listener) {\n\t\t\tconst subscription = subscribable.subscribe({\n\t\t\t\tnext(value) {\n\t\t\t\t\tcurrent = value;\n\t\t\t\t\tlistener();\n\t\t\t\t},\n\t\t\t\terror(nextError) {\n\t\t\t\t\terror = nextError;\n\t\t\t\t\tlistener();\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tsubscription.unsubscribe();\n\t\t\t};\n\t\t},\n\t};\n}\n","import {\n\tClientError,\n\tClientErrorKind,\n\tcreateCancellationTokenSource,\n\tcreateComputed,\n\ttype ReadableSignalTrait,\n\ttype ResourceSnapshot,\n\tResourceStatus,\n\ttype ResourceTrait,\n\twhenResourceSnapshotValue,\n} from \"@securitydept/client\";\nimport { type DependencyList, useMemo, useSyncExternalStore } from \"react\";\nimport { useResourceSnapshot } from \"./interop\";\nimport {\n\thashQueryStoreKey,\n\tQueryObserver,\n\ttype QueryResult,\n\tQueryResultStatus,\n\ttype QueryStoreKey,\n\tuseQueryStore,\n} from \"./query-store\";\n\nconst SUSPENSE_RESOURCE_ERROR_SOURCE = \"client-react.suspense-resource\";\n\ninterface QueryExternalStore<T> {\n\treadonly subscribe: (listener: () => void) => () => void;\n\treadonly getSnapshot: () => QueryResult<T> | undefined;\n\treadonly getServerSnapshot: () => QueryResult<T> | undefined;\n}\n\nconst BYPASSED_QUERY_STORE = Object.freeze({\n\tsubscribe: () => () => undefined,\n\tgetSnapshot: () => undefined,\n\tgetServerSnapshot: () => undefined,\n});\n\nexport interface UseSuspenseResourceValueOptions {\n\treadonly queryKey?: QueryStoreKey;\n\treadonly gcTimeMs?: number;\n\treadonly retainWhilePending?: boolean;\n}\n\nexport interface UseSuspenseComputedResourceValueOptions\n\textends Omit<UseSuspenseResourceValueOptions, \"queryKey\"> {\n\treadonly dependencies: DependencyList;\n\treadonly queryKey: QueryStoreKey;\n}\n\nexport function useSuspenseResourceValue<T>(\n\tresource: ResourceTrait<T>,\n\toptions?: UseSuspenseResourceValueOptions,\n): T;\nexport function useSuspenseResourceValue<T>(\n\tsnapshot: ReadableSignalTrait<ResourceSnapshot<T>>,\n\toptions?: UseSuspenseResourceValueOptions,\n): T;\nexport function useSuspenseResourceValue<T>(\n\tcompute: () => ResourceSnapshot<T>,\n\toptions: UseSuspenseComputedResourceValueOptions,\n): T;\nexport function useSuspenseResourceValue<T>(\n\tsource:\n\t\t| ResourceTrait<T>\n\t\t| ReadableSignalTrait<ResourceSnapshot<T>>\n\t\t| (() => ResourceSnapshot<T>),\n\toptions:\n\t\t| UseSuspenseResourceValueOptions\n\t\t| UseSuspenseComputedResourceValueOptions = {},\n): T {\n\tconst queryStore = useQueryStore();\n\tlet hash: string;\n\tlet createSnapshotSignal: () => ReadableSignalTrait<ResourceSnapshot<T>>;\n\tlet snapshotSignalDependencies: DependencyList;\n\n\tif (typeof source === \"function\") {\n\t\tconst computedOptions = options as UseSuspenseComputedResourceValueOptions;\n\t\tconst dependencies = computedOptions.dependencies;\n\t\tif (!Array.isArray(dependencies)) {\n\t\t\tthrow new ClientError({\n\t\t\t\tkind: ClientErrorKind.Configuration,\n\t\t\t\tcode: \"react.query.computed_dependencies_required\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"useSuspenseResourceValue() requires dependencies for computed input.\",\n\t\t\t\tsource: SUSPENSE_RESOURCE_ERROR_SOURCE,\n\t\t\t});\n\t\t}\n\t\tif (!Array.isArray(computedOptions.queryKey)) {\n\t\t\tthrow new ClientError({\n\t\t\t\tkind: ClientErrorKind.Configuration,\n\t\t\t\tcode: \"react.query.computed_query_key_required\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"useSuspenseResourceValue() requires a queryKey for computed input.\",\n\t\t\t\tsource: SUSPENSE_RESOURCE_ERROR_SOURCE,\n\t\t\t});\n\t\t}\n\t\thash = hashQueryStoreKey([\"resource_compute\", ...computedOptions.queryKey]);\n\t\tcreateSnapshotSignal = () => createComputed(source);\n\t\tsnapshotSignalDependencies = dependencies;\n\t} else {\n\t\tconst snapshotSignal = \"snapshot\" in source ? source.snapshot : source;\n\t\thash = hashQueryStoreKey([\n\t\t\t\"resource_snapshot\",\n\t\t\t{ sourceId: queryStore.getWeakKeyId(snapshotSignal) },\n\t\t\t...(options.queryKey ?? []),\n\t\t]);\n\t\tcreateSnapshotSignal = () => snapshotSignal;\n\t\tsnapshotSignalDependencies = [snapshotSignal];\n\t}\n\tconst snapshotSignal = useMemo(\n\t\tcreateSnapshotSignal,\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: The caller owns the computed closure dependencies.\n\t\tsnapshotSignalDependencies,\n\t);\n\tconst snapshot = useResourceSnapshot(snapshotSignal);\n\tconst queryRequired =\n\t\tsnapshot.status === ResourceStatus.Idle ||\n\t\tsnapshot.status === ResourceStatus.Loading;\n\n\tconst queryStoreBindings = useMemo<QueryExternalStore<T>>(() => {\n\t\tif (!queryRequired) {\n\t\t\treturn BYPASSED_QUERY_STORE;\n\t\t}\n\n\t\tconst observer = new QueryObserver<T>(queryStore, {\n\t\t\thash,\n\t\t\tsource: () => {\n\t\t\t\tconst cancellation = createCancellationTokenSource();\n\t\t\t\treturn {\n\t\t\t\t\tcancel: () => cancellation.cancel(),\n\t\t\t\t\tinput: whenResourceSnapshotValue(snapshotSignal, {\n\t\t\t\t\t\tcancellationToken: cancellation.token,\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t},\n\t\t\tgcTimeMs: options.gcTimeMs,\n\t\t\tretainWhilePending: options.retainWhilePending,\n\t\t});\n\t\treturn {\n\t\t\tsubscribe: observer.subscribe,\n\t\t\tgetSnapshot: observer.getSnapshot,\n\t\t\tgetServerSnapshot: observer.getServerSnapshot,\n\t\t};\n\t}, [\n\t\tqueryRequired,\n\t\tqueryStore,\n\t\thash,\n\t\toptions.gcTimeMs,\n\t\toptions.retainWhilePending,\n\t\tsnapshotSignal,\n\t]);\n\tconst result = useSyncExternalStore(\n\t\tqueryStoreBindings.subscribe,\n\t\tqueryStoreBindings.getSnapshot,\n\t\tqueryStoreBindings.getServerSnapshot,\n\t);\n\n\tswitch (snapshot.status) {\n\t\tcase ResourceStatus.Idle:\n\t\tcase ResourceStatus.Loading: {\n\t\t\tconst queryResult = result as QueryResult<T>;\n\t\t\tif (queryResult.status === QueryResultStatus.Pending) {\n\t\t\t\tthrow queryResult.promise;\n\t\t\t}\n\t\t\tif (queryResult.status === QueryResultStatus.Error) {\n\t\t\t\tthrow queryResult.error;\n\t\t\t}\n\t\t\treturn queryResult.value;\n\t\t}\n\t\tcase ResourceStatus.LoadingError:\n\t\t\tthrow snapshot.error;\n\t\tcase ResourceStatus.Reloading:\n\t\tcase ResourceStatus.Resolved:\n\t\tcase ResourceStatus.Error:\n\t\t\treturn snapshot.value;\n\t}\n}\n"],"mappings":"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"}