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

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.d.mts CHANGED
@@ -1,8 +1,5 @@
1
1
  import { CreateFoundationEnvironmentOptions, DisposableTrait, EventStreamTrait, FoundationEnvironment, InteropObservableTrait, ReadableSignalTrait, ResourceSnapshot, ResourceTrait, SYMBOL_DISPOSE, SecuritydeptInjectorTrait, SecuritydeptProvider as SecuritydeptProvider$1, SubscribableTrait, TimeTrait } from "@securitydept/client";
2
- import * as _$react from "react";
3
2
  import { DependencyList, ReactNode, RefObject } from "react";
4
- import * as _$react_jsx_runtime0 from "react/jsx-runtime";
5
-
6
3
  //#region src/environment.d.ts
7
4
  type ReactEnvironmentCreatorOptions = {
8
5
  providers?: readonly SecuritydeptProvider$1[];
@@ -21,15 +18,12 @@ declare function createEnvironmentForReact<TBaseOptions extends ReactEnvironment
21
18
  declare function useInitialRef<T>(initialize: () => T): RefObject<T>;
22
19
  //#endregion
23
20
  //#region src/injection/index.d.ts
24
- declare const SecuritydeptContext: _$react.Context<any>;
21
+ declare const SecuritydeptContext: import("react").Context<any>;
25
22
  interface SecuritydeptProviderProps {
26
23
  readonly injector: SecuritydeptInjectorTrait;
27
24
  readonly children?: ReactNode;
28
25
  }
29
- declare function SecuritydeptProvider({
30
- injector,
31
- children
32
- }: SecuritydeptProviderProps): _$react_jsx_runtime0.JSX.Element;
26
+ declare function SecuritydeptProvider({ injector, children }: SecuritydeptProviderProps): import("react").JSX.Element;
33
27
  declare function useSecuritydeptContext(): SecuritydeptInjectorTrait;
34
28
  //#endregion
35
29
  //#region src/interop.d.ts
@@ -1 +1 @@
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":";;;;;;AAGA,MAAa,sBACZ,cAAgD,KAAK;AAOtD,SAAgB,qBAAqB,EACpC,UACA,YAC6B;CAC7B,OACC,oBAAC,oBAAoB,UAArB;EAA8B,OAAO;EACnC;EAC6B,CAAA;;AAIjC,SAAgB,yBAAoD;CACnE,MAAM,WAAW,WAAW,oBAAoB;CAChD,IAAI,CAAC,UACJ,MAAM,IAAI,MACT,gFACA;CAEF,OAAO;;;;ACUR,MAAM,2BAA2B;;AAsBjC,MAAa,oBAAoB;CAChC,SAAS;CACT,UAAU;CACV,OAAO;CACP;AAuCD,IAAa,aAAb,MAAa,WAAsC;CAClD,OAAgB,iBAAiB,OAAO,OAAO,EAC9C,UAAU,KACV,CAAC;CAEF,0BAA2B,IAAI,KAA6B;CAC5D,6BAA8B,IAAI,SAAyB;CAC3D;CACA;CACA,gBAAwB;CACxB,WAAmB;CAEnB,YAAY,SAA4B;EACvC,KAAK,YAAY,0CAA0C,QAAQ,KAAK;EACxE,KAAK,WAAW,eACf,QAAQ,YAAY,WAAW,eAAe,SAC9C;;CAGF,aAAa,OAAuB;EACnC,MAAM,WAAW,KAAK,WAAW,IAAI,MAAM;EAC3C,IAAI,aAAa,KAAA,GAChB,OAAO;EAER,MAAM,KAAK,QAAQ,EAAE,KAAK;EAC1B,KAAK,WAAW,IAAI,OAAO,GAAG;EAC9B,OAAO;;CAGR,UAAgB;EACf,IAAI,KAAK,UACR;EAED,KAAK,WAAW;EAChB,KAAK,MAAM,SAAS,KAAK,QAAQ,QAAQ,EACxC,MAAM,SAAS;EAEhB,KAAK,QAAQ,OAAO;;CAGrB,CAAC,kBAAwB;EACxB,KAAK,SAAS;;;CAIf,iBAAoB,SAA8C;EACjE,MAAM,WAAW,KAAK,QAAQ,IAAI,QAAQ,KAAK;EAC/C,MAAM,kBAAkB;GACvB,UAAU,eAAe,QAAQ,YAAY,KAAK,SAAS;GAC3D,oBAAoB,QAAQ,sBAAsB;GAClD;EACD,IAAI,UAAU;GACb,SAAS,cAAc,gBAAgB;GACvC,OAAO;;EAER,MAAM,QAAQ,IAAI,MACjB,QAAQ,MACR,QAAQ,QAAQ,EAChB,iBACA,KAAK,UACL;EACD,KAAK,QAAQ,IAAI,QAAQ,MAAM,MAAwB;EACvD,MAAM,iBAAiB,UAAU,EAChC,YAAY,KAAK,YAAY,MAAmC,EAChE,CAAC;EACF,OAAO;;CAGR,YAAoB,OAA6B;EAChD,IAAI,KAAK,QAAQ,IAAI,MAAM,KAAK,KAAK,OACpC;EAED,KAAK,QAAQ,OAAO,MAAM,KAAK;EAC/B,MAAM,SAAS;;;AAIjB,SAAgB,kBACf,UAAoC,EAAE,EACJ;CAClC,OAAO,CACN;EACC,SAAS;EACT,aACC,MACA,eACI;GACJ,MAAM,aAAa,IAAI,WAAW;IACjC;IACA,UAAU,QAAQ;IAClB,CAAC;GACF,YAAY,gBAAgB,WAAW,SAAS,CAAC;GACjD,OAAO;;EAER,MAAM,CACL,kBACA,CAAC,IAAI,sBAAsB,EAAE,uBAAuB,CACpD;EACD,CACD;;AAGF,SAAgB,gBAA4B;CAC3C,OAAO,wBAAwB,CAAC,IAAI,WAAW;;;AAIhD,IAAa,gBAAb,MAA8B;CASX;CACA;CATlB,aAAsB,aAAuC;EAC5D,MAAM,eAAe,KAAK,OAAO,CAAC,QAAQ,UAAU,EAAE,MAAM,UAAU,CAAC;EACvE,OAAO,aAAa,YAAY,KAAK,aAAa;;CAEnD,oBAA6C,KAAK,OAAO,CAAC,WAAW;CACrE,0BAAmD,KAAK,OAAO,CAAC,WAAW;CAE3E,YACC,OACA,SACC;EAFgB,KAAA,QAAA;EACA,KAAA,UAAA;;CAGlB,QAA0B;EACzB,OAAO,KAAK,MAAM,iBAAiB,KAAK,QAAQ;;;AAIlD,IAAM,QAAN,MAA0C;CAc/B;CACQ;CAEA;CAhBlB;CACA;CACA;CACA;CACA,kBAAmC,aAAqB,EAAE;CAC1D,0BAA2C,IAAI,gBAAsB;CACrE,YAA6B,aAAsB,MAAM;CACzD,aAA8B,KAAK,KAAK,UAAU,CAAC,KAClD,QAAQ,cAAc,UAAU,EAChC,KAAK,EAAE,CACP;CAED,YACC,MACA,QACA,SACA,WACC;EAJQ,KAAA,OAAA;EACQ,KAAA,SAAA;EAEA,KAAA,YAAA;EAEjB,KAAK,UAAU,cAAc,iBAAiB,QAAQ;EACtD,KAAK,mBAAmB,KAAK,wBAAwB,cAAc;EAEnE,MAAM,iBAAiB,eACtB,cAAc,oBAAoB,OAAO,MAAM,CAAC,KAC/C,UAAU,KAAK,WAAW,CAC1B,CACD;EACD,KAAK,QAAQ,cAAc,iBAAiC;GAC3D,QAAQ,kBAAkB;GAC1B,SAAS;GACT,CAAC;EAEF,KAAK,UAAU,cAAc,oBAC5B,YAAY;GACX,KAAK,gBAAgB,IAAI,KAAK,gBAAgB,KAAK,GAAG,EAAE;GACxD,OAAO,KAAK,KAAK,MAAM,CAAC,KACvB,KAAK,EAAE,EACP,UAAU,KAAA,EAAU,EACpB,UAAU,KAAK,WAAW,EAC1B,eAAe;IACd,KAAK,gBAAgB,IAAI,KAAK,gBAAgB,KAAK,GAAG,EAAE;KACvD,CACF;IACA,CACF;EACD,cAAc;GACb,KAAK,KAAK,gBAAgB;GAC1B,KAAK,KAAK,MAAM;GAChB,KAAK,KAAK,QAAQ;GAClB,CAAC,CACA,KACA,WAAW,CAAC,iBAAiB,OAAO,eAAe;GAClD,IACC,oBAAoB,KACnB,MAAM,WAAW,kBAAkB,WACnC,UAAU,sBACX,UAAU,aAAa,OAAO,mBAE9B,OAAO;GAER,OAAO,MAAM,UAAU,UAAU,KAAK,UAAU,CAAC,KAChD,UAAU,KAAA,EAAU,CACpB;IACA,EACF,UAAU,KAAK,WAAW,CAC1B,CACA,UAAU,EACV,YAAY,KAAK,wBAAwB,MAAM,EAC/C,CAAC;EAEH,eAAe,MACb,UAAU;GACV,KAAK,MAAM,IAAI;IAAE,QAAQ,kBAAkB;IAAU;IAAO,CAAC;MAE7D,UAAU;GACV,KAAK,MAAM,IAAI;IAAE,QAAQ,kBAAkB;IAAO;IAAO,CAAC;IAE3D;;CAGF,cAAc,SAAqC;EAClD,MAAM,UAAU,KAAK,QAAQ,KAAK;EAClC,KAAK,QAAQ,IAAI;GAChB,UAAU,KAAK,IAAI,QAAQ,UAAU,QAAQ,SAAS;GACtD,oBACC,QAAQ,sBAAsB,QAAQ;GACvC,CAAC;;CAGH,YAA4B;EAC3B,OAAO,KAAK,MAAM,KAAK;;CAGxB,UAAgB;EACf,KAAK,UAAU,IAAI,KAAK;EACxB,KAAK,OAAO,QAAQ;;CAGrB,CAAC,kBAAwB;EACxB,KAAK,SAAS;;;AAIhB,SAAS,eAAe,UAA0B;CACjD,IAAI,OAAO,aAAa,YAAY,OAAO,MAAM,SAAS,IAAI,WAAW,GACxE,MAAM,0BACL,+BACA,qDACA;CAEF,OAAO;;;AAIR,SAAgB,kBAAkB,KAA4B;CAC7D,MAAM,4BAAY,IAAI,KAAa;CACnC,MAAM,aAAa,UAAuC;EACzD,IACC,UAAU,QACV,OAAO,UAAU,aACjB,OAAO,UAAU,UAEjB,OAAO;EAER,IAAI,OAAO,UAAU,UAAU;GAC9B,IAAI,CAAC,OAAO,SAAS,MAAM,EAC1B,MAAM,iBAAiB;GAExB,OAAO;;EAER,IAAI,OAAO,UAAU,UACpB,MAAM,iBAAiB;EAExB,IAAI,UAAU,IAAI,MAAM,EACvB,MAAM,iBAAiB;EAExB,UAAU,IAAI,MAAM;EACpB,IAAI;GACH,IAAI,MAAM,QAAQ,MAAM,EACvB,OAAO,MAAM,IAAI,UAAU;GAE5B,MAAM,YAAY,OAAO,eAAe,MAAM;GAC9C,IACE,cAAc,OAAO,aAAa,cAAc,QACjD,OAAO,sBAAsB,MAAM,CAAC,WAAW,GAE/C,MAAM,iBAAiB;GAExB,MAAM,aACL,OAAO,OAAO,KAAK;GACpB,KAAK,MAAM,YAAY,OAAO,KAAK,MAAM,CAAC,MAAM,EAC/C,WAAW,YAAY,UACrB,MAAkC,UACnC;GAEF,OAAO;YACE;GACT,UAAU,OAAO,MAAM;;;CAGzB,OAAO,KAAK,UAAU,UAAU,IAAI,CAAC;;AAGtC,SAAS,kBAA+B;CACvC,OAAO,0BACN,2BACA,8DACA;;AAGF,SAAS,0BAA0B,MAAc,SAA8B;CAC9E,OAAO,IAAI,YAAY;EACtB,MAAM,gBAAgB;EACtB;EACA;EACA,QAAQ;EACR,CAAC;;;;;;;;;ACzWH,SAAgB,0BACf,UAKO,EAAE,EACe;CACxB,MAAM,EACL,wBAAwB,6BACxB,YAAY,EAAE,EACd,GAAG,gBACA;CAQJ,MAAM,iBAAiB,IAHI,IAC1B,UAAU,KAAK,aAAa,6BAA6B,SAAS,CAAC,CAE/B,CAAC,IAAI,WAAW,GAClD,YACA,CAAC,GAAG,mBAAmB,EAAE,GAAG,UAAU;CAEzC,OAAO,sBAAsB;EAC5B,GAAI;EACJ,WAAW;EACX,CAAC;;;;ACrEH,MAAM,oBAAoB,OAAO,uCAAuC;AAExE,SAAgB,cAAiB,YAAmC;CACnE,MAAM,MAAM,OAAqC,kBAAkB;CACnE,IAAI,IAAI,YAAY,mBACnB,IAAI,UAAU,YAAY;CAE3B,OAAO;;;;ACWR,MAAM,qBAAqC,EAAE;AAE7C,SAAgB,UAAa,QAAmC;CAC/D,MAAM,YAAY,aAChB,aAAyB;EACzB,MAAM,eAAe,OAAO,aAAa,CAAC,UAAU,EACnD,MAAM,UACN,CAAC;EACF,aAAa;GACZ,aAAa,aAAa;;IAG5B,CAAC,OAAO,CACR;CACD,MAAM,cAAc,kBAAkB,OAAO,KAAK,EAAE,CAAC,OAAO,CAAC;CAE7D,OAAO,qBAAqB,WAAW,aAAa,YAAY;;AAajE,SAAgB,oBACf,QAIA,cACsB;CACtB,MAAM,iBAAiB,cACf,OAAO,WAAW,aAAa,eAAe,OAAO,GAAG,MAE/D,gBAAgB,mBAChB;CAOD,OAAO,UALN,OAAO,WAAW,aACd,iBACD,cAAc,SACb,OAAO,WACP,OAC2B;;AAuCjC,SAAgB,qBACf,QACA,UAAsD,EAAE,EACxC;CAChB,MAAM,uBAAuB,OAAO,OAAO,SAAS,eAAe;CACnE,MAAM,eAAe,QAAQ;CAC7B,MAAM,cAAc,QAAQ;CAC5B,MAAM,QAAQ,cAEZ,6BAA6B,QAAQ;EACpC;EACA;EACA;EACA,CAAC,EACH;EAAC;EAAQ;EAAc;EAAsB;EAAY,CACzD;CACD,OAAO,qBACN,MAAM,WACN,MAAM,aACN,MAAM,YACN;;AAGF,SAAgB,eACf,QACA,SACA,UAAiC,EAAE,EAC5B;CACP,MAAM,aAAa,OAAO,QAAQ;CAClC,WAAW,UAAU;CAErB,gBAAgB;EACf,IAAI,QAAQ,YAAY,OACvB;EAGD,MAAM,eAAe,OAAO,UAAU,EACrC,OAAO,UAAU;GAChB,WAAW,QAAQ,MAAM;KAE1B,CAAC;EAEF,aAAa;GACZ,aAAa,aAAa;;IAEzB,CAAC,QAAQ,SAAS,OAAO,CAAC;;AAG9B,SAAS,6BACR,QACA,SAQC;CACD,MAAM,eACL,yBAAyB,OAAO,GAAG,OAAO,oBAAoB,GAAG;CAElE,IAAI,UAAU,QAAQ,uBAAuB,QAAQ,eAAe,KAAA;CACpE,IAAI;CAEJ,IAAI,QAAQ,gBAAgB,MAAM;EACjC,IAAI,cAAc;EAUlB,aATkC,UAAU;GAC3C,KAAK,OAAO;IACX,cAAc;IACd,UAAU;;GAEX,MAAM,WAAW;IAChB,QAAQ;;GAET,CACW,CAAC,aAAa;EAC1B,IAAI,UAAU,KAAA,GACb,MAAM;EAEP,IAAI,CAAC,aACJ,MAAM,IAAI,MACT,0DACA;;CAIH,OAAO;EACN,cAAc;GACb,IAAI,UAAU,KAAA,GACb,MAAM;GAEP,OAAO;;EAER,UAAU,UAAU;GACnB,MAAM,eAAe,aAAa,UAAU;IAC3C,KAAK,OAAO;KACX,UAAU;KACV,UAAU;;IAEX,MAAM,WAAW;KAChB,QAAQ;KACR,UAAU;;IAEX,CAAC;GACF,aAAa;IACZ,aAAa,aAAa;;;EAG5B;;;;ACjMF,MAAM,iCAAiC;AAQvC,MAAM,uBAAuB,OAAO,OAAO;CAC1C,uBAAuB,KAAA;CACvB,mBAAmB,KAAA;CACnB,yBAAyB,KAAA;CACzB,CAAC;AA0BF,SAAgB,yBACf,QAIA,UAE6C,EAAE,EAC3C;CACJ,MAAM,aAAa,eAAe;CAClC,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,IAAI,OAAO,WAAW,YAAY;EACjC,MAAM,kBAAkB;EACxB,MAAM,eAAe,gBAAgB;EACrC,IAAI,CAAC,MAAM,QAAQ,aAAa,EAC/B,MAAM,IAAI,YAAY;GACrB,MAAM,gBAAgB;GACtB,MAAM;GACN,SACC;GACD,QAAQ;GACR,CAAC;EAEH,IAAI,CAAC,MAAM,QAAQ,gBAAgB,SAAS,EAC3C,MAAM,IAAI,YAAY;GACrB,MAAM,gBAAgB;GACtB,MAAM;GACN,SACC;GACD,QAAQ;GACR,CAAC;EAEH,OAAO,kBAAkB,CAAC,oBAAoB,GAAG,gBAAgB,SAAS,CAAC;EAC3E,6BAA6B,eAAe,OAAO;EACnD,6BAA6B;QACvB;EACN,MAAM,iBAAiB,cAAc,SAAS,OAAO,WAAW;EAChE,OAAO,kBAAkB;GACxB;GACA,EAAE,UAAU,WAAW,aAAa,eAAe,EAAE;GACrD,GAAI,QAAQ,YAAY,EAAE;GAC1B,CAAC;EACF,6BAA6B;EAC7B,6BAA6B,CAAC,eAAe;;CAE9C,MAAM,iBAAiB,QACtB,sBAEA,2BACA;CACD,MAAM,WAAW,oBAAoB,eAAe;CACpD,MAAM,gBACL,SAAS,WAAW,eAAe,QACnC,SAAS,WAAW,eAAe;CAEpC,MAAM,qBAAqB,cAAqC;EAC/D,IAAI,CAAC,eACJ,OAAO;EAGR,MAAM,WAAW,IAAI,cAAiB,YAAY;GACjD;GACA,cAAc;IACb,MAAM,eAAe,+BAA+B;IACpD,OAAO;KACN,cAAc,aAAa,QAAQ;KACnC,OAAO,0BAA0B,gBAAgB,EAChD,mBAAmB,aAAa,OAChC,CAAC;KACF;;GAEF,UAAU,QAAQ;GAClB,oBAAoB,QAAQ;GAC5B,CAAC;EACF,OAAO;GACN,WAAW,SAAS;GACpB,aAAa,SAAS;GACtB,mBAAmB,SAAS;GAC5B;IACC;EACF;EACA;EACA;EACA,QAAQ;EACR,QAAQ;EACR;EACA,CAAC;CACF,MAAM,SAAS,qBACd,mBAAmB,WACnB,mBAAmB,aACnB,mBAAmB,kBACnB;CAED,QAAQ,SAAS,QAAjB;EACC,KAAK,eAAe;EACpB,KAAK,eAAe,SAAS;GAC5B,MAAM,cAAc;GACpB,IAAI,YAAY,WAAW,kBAAkB,SAC5C,MAAM,YAAY;GAEnB,IAAI,YAAY,WAAW,kBAAkB,OAC5C,MAAM,YAAY;GAEnB,OAAO,YAAY;;EAEpB,KAAK,eAAe,cACnB,MAAM,SAAS;EAChB,KAAK,eAAe;EACpB,KAAK,eAAe;EACpB,KAAK,eAAe,OACnB,OAAO,SAAS"}
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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"}
@@ -1,5 +1,5 @@
1
1
  import { AuthRequirement, EnvironmentValidators, FoundationEnvironment, RequirementBehaviourWithRouteContext, RequirementPlannerHost, RequirementPlannerHostBehaviour, RequirementsComposition, RouteBehaviourContextExtra, RouteTreeSegment, RouterTrait, SecuritydeptInjectorTrait, WithTraitInputValidator } from "@securitydept/client";
2
-
2
+ import { AnyRouter, NavigateOptions } from "@tanstack/react-router";
3
3
  //#region src/tanstack-router/auth-coordination/route-metadata.d.ts
4
4
  interface TanStackRouteMatchLike {
5
5
  readonly id?: string;
@@ -72,12 +72,9 @@ interface TanStackRouterNavigationLike {
72
72
  readonly state?: {
73
73
  readonly location?: TanStackRouterLocationLike;
74
74
  };
75
- navigate(options: {
76
- to: string;
77
- replace?: boolean;
78
- state?: unknown;
79
- }): Promise<unknown> | unknown;
75
+ navigate(options: TanStackRouterNavigateOptions): Promise<unknown> | unknown;
80
76
  }
77
+ type TanStackRouterNavigateOptions = NavigateOptions<AnyRouter, string, string | undefined, string, "">;
81
78
  interface CreateRouterForTanStackRouterOptions {
82
79
  readonly router: TanStackRouterNavigationLike;
83
80
  readonly currentUrl?: string | null;
@@ -88,5 +85,5 @@ interface ResolvedRouterForTanStackRouterCreateOptions {
88
85
  }
89
86
  declare function createRouterForTanStackRouter(options: CreateRouterForTanStackRouterOptions & WithTraitInputValidator<Pick<EnvironmentValidators, "router">>): RouterTrait;
90
87
  //#endregion
91
- export { CreateRouterForTanStackRouterOptions, CreateTanStackBeforeLoadOptions, CreateTanStackBeforeLoadWithBehaviourOptions, CreateTanStackBeforeLoadWithPlannerHostOptions, CreateTanStackRouteSecurityPatchOptions, CreateTanStackRouterContextOptions, ResolvedRouterForTanStackRouterCreateOptions, SecuritydeptTanStackRouterContext, TanStackBeforeLoadContextLike, TanStackRouteMatchLike, TanStackRouteRootSecurityPatch, TanStackRouteSecurityBlockedError, TanStackRouteSecurityOptions, TanStackRouteSecurityPatch, TanStackRouterLocationLike, TanStackRouterNavigationLike, createRouterForTanStackRouter, createTanStackBeforeLoad, createTanStackRouterContext, projectTanStackRouteSegments, secureRoute, secureRouteRoot };
88
+ export { CreateRouterForTanStackRouterOptions, CreateTanStackBeforeLoadOptions, CreateTanStackBeforeLoadWithBehaviourOptions, CreateTanStackBeforeLoadWithPlannerHostOptions, CreateTanStackRouteSecurityPatchOptions, CreateTanStackRouterContextOptions, ResolvedRouterForTanStackRouterCreateOptions, SecuritydeptTanStackRouterContext, TanStackBeforeLoadContextLike, TanStackRouteMatchLike, TanStackRouteRootSecurityPatch, TanStackRouteSecurityBlockedError, TanStackRouteSecurityOptions, TanStackRouteSecurityPatch, TanStackRouterLocationLike, TanStackRouterNavigateOptions, TanStackRouterNavigationLike, createRouterForTanStackRouter, createTanStackBeforeLoad, createTanStackRouterContext, projectTanStackRouteSegments, secureRoute, secureRouteRoot };
92
89
  //# sourceMappingURL=index.d.mts.map
@@ -65,11 +65,12 @@ function writeRequirementStaticData(security, base) {
65
65
  }
66
66
  //#endregion
67
67
  //#region src/tanstack-router/router.ts
68
+ const TanStackRouterNavigationLikeSchema = type({
69
+ state: "object?",
70
+ navigate: "Function"
71
+ });
68
72
  const ResolvedRouterForTanStackRouterCreateOptionsSchema = type({
69
- router: type({
70
- state: "object?",
71
- navigate: "Function"
72
- }),
73
+ router: TanStackRouterNavigationLikeSchema,
73
74
  currentUrl: UriReferenceStringSchema.or("null")
74
75
  });
75
76
  function createRouterForTanStackRouter(options) {
@@ -99,6 +100,10 @@ function createRouterForTanStackRouter(options) {
99
100
  return currentUrl == null ? null : UriReferenceString.parse(currentUrl);
100
101
  },
101
102
  async navigate(request) {
103
+ if (request.mode === RouterNavigationMode.External) {
104
+ await router.navigate({ href: request.url.toString() });
105
+ return;
106
+ }
102
107
  await router.navigate({
103
108
  to: request.url.toString(),
104
109
  replace: request.mode === RouterNavigationMode.Replace,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["defineType"],"sources":["../../src/tanstack-router/auth-coordination/route-metadata.ts","../../src/tanstack-router/auth-coordination/route-guard.ts","../../src/tanstack-router/auth-coordination/secure-routes.ts","../../src/tanstack-router/router.ts"],"sourcesContent":["import {\n\ttype AuthRequirement,\n\ttype RouteTreeSegment,\n\treadSecuritydeptRouteMetadata,\n} from \"@securitydept/client\";\n\nexport interface TanStackRouteMatchLike {\n\treadonly id?: string;\n\treadonly routeId?: string;\n\treadonly pathname?: string;\n\treadonly staticData?: object;\n}\n\nexport function projectTanStackRouteSegments<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n>(\n\tmatches: readonly TanStackRouteMatchLike[],\n): RouteTreeSegment<TAuthRequirement>[] {\n\treturn matches.map((match, index) => {\n\t\tconst metadata = readSecuritydeptRouteMetadata<TAuthRequirement>(\n\t\t\tmatch.staticData,\n\t\t);\n\t\treturn {\n\t\t\trouteId:\n\t\t\t\tmatch.routeId ??\n\t\t\t\tmatch.id ??\n\t\t\t\tmatch.pathname ??\n\t\t\t\t`tanstack-route-${index}`,\n\t\t\trequirements: metadata?.requirements ?? [],\n\t\t\tcomposition: metadata?.composition,\n\t\t};\n\t});\n}\n","import {\n\ttype AuthRequirement,\n\tENVIRONMENT_TOKEN,\n\tinjectRequirementPlannerHost,\n\tPipelineOutcome,\n\ttype RequirementBehaviourWithRouteContext,\n\tRequirementPlannerHost,\n\ttype RequirementPlannerHostBehaviour,\n\ttype RouteBehaviourContextExtra,\n\tRouteCompositionRequirementPlanner,\n\ttype SecuritydeptInjectorTrait,\n} from \"@securitydept/client\";\nimport { redirect } from \"@tanstack/react-router\";\nimport {\n\tprojectTanStackRouteSegments,\n\ttype TanStackRouteMatchLike,\n} from \"./route-metadata\";\n\nexport interface SecuritydeptTanStackRouterContext {\n\treadonly securitydeptInjector: SecuritydeptInjectorTrait;\n\treadonly router?: {\n\t\treadonly state: {\n\t\t\treadonly matches: readonly TanStackRouteMatchLike[];\n\t\t};\n\t};\n}\n\nexport interface TanStackBeforeLoadContextLike {\n\treadonly context: SecuritydeptTanStackRouterContext;\n\treadonly matches: readonly TanStackRouteMatchLike[];\n\treadonly location: {\n\t\treadonly href: string;\n\t};\n}\n\nexport interface CreateTanStackBeforeLoadWithPlannerHostOptions<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n> {\n\treadonly plannerHost: RequirementPlannerHost<TBehaviour>;\n\treadonly behaviour?: never;\n}\n\nexport interface CreateTanStackBeforeLoadWithBehaviourOptions<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n> {\n\treadonly plannerHost?: never;\n\treadonly behaviour?: RequirementPlannerHostBehaviour<\n\t\tTAuthRequirement,\n\t\tRouteBehaviourContextExtra,\n\t\tTBehaviour\n\t>;\n}\n\nexport type CreateTanStackBeforeLoadOptions<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n> =\n\t| CreateTanStackBeforeLoadWithPlannerHostOptions<TAuthRequirement, TBehaviour>\n\t| CreateTanStackBeforeLoadWithBehaviourOptions<TAuthRequirement, TBehaviour>;\n\nexport class TanStackRouteSecurityBlockedError extends Error {\n\tconstructor(readonly requirement: AuthRequirement) {\n\t\tsuper(`TanStack route security blocked requirement: ${requirement.id}`);\n\t\tthis.name = \"TanStackRouteSecurityBlockedError\";\n\t}\n}\n\nexport function createTanStackBeforeLoad<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n>(options?: CreateTanStackBeforeLoadOptions<TAuthRequirement, TBehaviour>) {\n\treturn async (context: TanStackBeforeLoadContextLike): Promise<void> => {\n\t\tconst injector = context.context.securitydeptInjector;\n\t\tconst parentHost = injectRequirementPlannerHost<\n\t\t\tTAuthRequirement,\n\t\t\tRouteBehaviourContextExtra,\n\t\t\tTBehaviour\n\t\t>({ injector });\n\t\tconst host =\n\t\t\toptions?.plannerHost ??\n\t\t\t(options?.behaviour\n\t\t\t\t? RequirementPlannerHost.fromBehaviour(\n\t\t\t\t\t\ttypeof options.behaviour === \"function\"\n\t\t\t\t\t\t\t? options.behaviour()\n\t\t\t\t\t\t\t: options.behaviour,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tparent: parentHost ?? undefined,\n\t\t\t\t\t\t\tenvironment: injector.get(ENVIRONMENT_TOKEN, null) ?? undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t: parentHost) ??\n\t\t\tRequirementPlannerHost.fromBehaviour({} as TBehaviour);\n\t\tconst segments = projectTanStackRouteSegments<TAuthRequirement>(\n\t\t\tcontext.matches,\n\t\t);\n\t\tconst planner = RouteCompositionRequirementPlanner.fromRouteSegments(\n\t\t\thost,\n\t\t\tsegments,\n\t\t\t{\n\t\t\t\turl: context.location.href,\n\t\t\t},\n\t\t);\n\t\tconst result = await planner.runUntilSettled();\n\t\tswitch (result.outcome) {\n\t\t\tcase PipelineOutcome.Settled:\n\t\t\t\treturn;\n\t\t\tcase PipelineOutcome.Blocked:\n\t\t\t\tthrow new TanStackRouteSecurityBlockedError(result.requirement);\n\t\t\tcase PipelineOutcome.Redirect:\n\t\t\t\tthrow redirect({ to: result.location });\n\t\t}\n\t};\n}\n","import {\n\ttype AuthRequirement,\n\ttype FoundationEnvironment,\n\ttype RequirementBehaviourWithRouteContext,\n\ttype RequirementPlannerHost,\n\ttype RequirementPlannerHostBehaviour,\n\ttype RequirementsComposition,\n\ttype RouteBehaviourContextExtra,\n\ttype SecuritydeptInjectorTrait,\n\ttype SecuritydeptRouteMetadata,\n\twriteSecuritydeptRouteMetadata,\n} from \"@securitydept/client\";\nimport {\n\tcreateTanStackBeforeLoad,\n\ttype SecuritydeptTanStackRouterContext,\n\ttype TanStackBeforeLoadContextLike,\n} from \"./route-guard\";\n\nexport interface CreateTanStackRouterContextOptions {\n\treadonly environment?: FoundationEnvironment;\n\treadonly injector?: SecuritydeptInjectorTrait;\n}\n\nexport interface TanStackRouteSecurityOptions<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n> {\n\treadonly requirements?: readonly TAuthRequirement[];\n\treadonly composition?: RequirementsComposition;\n\treadonly plannerHost?: RequirementPlannerHost<TBehaviour>;\n\treadonly behaviour?: RequirementPlannerHostBehaviour<\n\t\tTAuthRequirement,\n\t\tRouteBehaviourContextExtra,\n\t\tTBehaviour\n\t>;\n}\n\nexport interface CreateTanStackRouteSecurityPatchOptions {\n\treadonly staticData?: object;\n}\n\nexport interface TanStackRouteSecurityPatch {\n\treadonly staticData: Record<string, unknown>;\n}\n\nexport interface TanStackRouteRootSecurityPatch\n\textends TanStackRouteSecurityPatch {\n\treadonly beforeLoad: (\n\t\tcontext: TanStackBeforeLoadContextLike,\n\t) => Promise<void>;\n}\n\nexport function createTanStackRouterContext(\n\toptions: CreateTanStackRouterContextOptions = {},\n): Pick<SecuritydeptTanStackRouterContext, \"securitydeptInjector\"> {\n\tconst securitydeptInjector =\n\t\toptions.injector ?? options.environment?.injector;\n\tif (!securitydeptInjector) {\n\t\tthrow new Error(\n\t\t\t\"[createTanStackRouterContext] Missing SecurityDept injector. Pass `injector` or `environment`.\",\n\t\t);\n\t}\n\treturn { securitydeptInjector };\n}\n\nexport function secureRoute<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n>(\n\tsecurity: TanStackRouteSecurityOptions<TAuthRequirement, TBehaviour>,\n\toptions: CreateTanStackRouteSecurityPatchOptions = {},\n): TanStackRouteSecurityPatch {\n\treturn {\n\t\tstaticData: writeRequirementStaticData(security, options.staticData),\n\t};\n}\n\nexport function secureRouteRoot<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n>(\n\tsecurity: TanStackRouteSecurityOptions<TAuthRequirement, TBehaviour>,\n\toptions: CreateTanStackRouteSecurityPatchOptions = {},\n): TanStackRouteRootSecurityPatch {\n\tconst securityBeforeLoad = createTanStackBeforeLoad<\n\t\tTAuthRequirement,\n\t\tTBehaviour\n\t>(\n\t\tsecurity.plannerHost\n\t\t\t? { plannerHost: security.plannerHost }\n\t\t\t: security.behaviour\n\t\t\t\t? { behaviour: security.behaviour }\n\t\t\t\t: undefined,\n\t);\n\treturn {\n\t\tstaticData: writeRequirementStaticData(security, options.staticData),\n\t\tbeforeLoad: securityBeforeLoad,\n\t};\n}\n\nfunction writeRequirementStaticData<\n\tTAuthRequirement extends AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t>,\n>(\n\tsecurity: TanStackRouteSecurityOptions<TAuthRequirement, TBehaviour>,\n\tbase: object | undefined,\n): Record<string, unknown> {\n\tconst patch: SecuritydeptRouteMetadata<TAuthRequirement> = {};\n\tif (security.requirements !== undefined) {\n\t\tpatch.requirements = security.requirements;\n\t}\n\tif (security.composition !== undefined) {\n\t\tpatch.composition = security.composition;\n\t}\n\tif (Object.keys(patch).length === 0) {\n\t\treturn { ...(base ?? {}) };\n\t}\n\treturn writeSecuritydeptRouteMetadata(base, patch);\n}\n","import {\n\ttype EnvironmentValidators,\n\tRouterNavigationMode,\n\ttype RouterNavigationRequest,\n\ttype RouterTrait,\n\tthrowValidationClientError,\n\tUriReferenceString,\n\tUriReferenceStringSchema,\n\tvalidateTraitInput,\n\ttype WithTraitInputValidator,\n} from \"@securitydept/client\";\nimport { type as defineType } from \"arktype\";\n\nexport interface TanStackRouterLocationLike {\n\treadonly href: string;\n}\n\nexport interface TanStackRouterNavigationLike {\n\treadonly state?: {\n\t\treadonly location?: TanStackRouterLocationLike;\n\t};\n\tnavigate(options: {\n\t\tto: string;\n\t\treplace?: boolean;\n\t\tstate?: unknown;\n\t}): Promise<unknown> | unknown;\n}\n\nexport interface CreateRouterForTanStackRouterOptions {\n\treadonly router: TanStackRouterNavigationLike;\n\treadonly currentUrl?: string | null;\n}\n\nexport interface ResolvedRouterForTanStackRouterCreateOptions {\n\treadonly router: TanStackRouterNavigationLike;\n\treadonly currentUrl: string | null;\n}\n\nconst TanStackRouterNavigationLikeSchema = defineType({\n\tstate: \"object?\",\n\tnavigate: \"Function\",\n});\n\nconst ResolvedRouterForTanStackRouterCreateOptionsSchema = defineType({\n\trouter: TanStackRouterNavigationLikeSchema,\n\tcurrentUrl: UriReferenceStringSchema.or(\"null\"),\n});\n\nexport function createRouterForTanStackRouter(\n\toptions: CreateRouterForTanStackRouterOptions &\n\t\tWithTraitInputValidator<Pick<EnvironmentValidators, \"router\">>,\n): RouterTrait {\n\tconst routerInput = options.router as\n\t\t| TanStackRouterNavigationLike\n\t\t| null\n\t\t| undefined;\n\tconst resolvedCreateOptions: ResolvedRouterForTanStackRouterCreateOptions = {\n\t\trouter: options.router,\n\t\tget currentUrl() {\n\t\t\tif (Object.hasOwn(options, \"currentUrl\")) {\n\t\t\t\treturn options.currentUrl ?? null;\n\t\t\t}\n\n\t\t\treturn routerInput?.state?.location?.href ?? null;\n\t\t},\n\t};\n\n\tvalidateTraitInput({\n\t\tvalue: resolvedCreateOptions,\n\t\tbundledSchema: ResolvedRouterForTanStackRouterCreateOptionsSchema,\n\t\tvalidator: options.validators?.router,\n\t\tonInvalid: (failure) =>\n\t\t\tthrowValidationClientError({\n\t\t\t\tcode: \"client_react.tanstack_router.invalid_router_options\",\n\t\t\t\tsource: \"client-react\",\n\t\t\t\tmessagePrefix:\n\t\t\t\t\t\"createRouterForTanStackRouter could not validate routerForTanStackRouterCreateOptions\",\n\t\t\t\tfailure,\n\t\t\t}),\n\t});\n\n\tconst { router } = resolvedCreateOptions;\n\treturn {\n\t\tcurrentUrl() {\n\t\t\tconst currentUrl = resolvedCreateOptions.currentUrl;\n\t\t\treturn currentUrl == null ? null : UriReferenceString.parse(currentUrl);\n\t\t},\n\t\tasync navigate(request: RouterNavigationRequest) {\n\t\t\tawait router.navigate({\n\t\t\t\tto: request.url.toString(),\n\t\t\t\treplace: request.mode === RouterNavigationMode.Replace,\n\t\t\t\tstate: request.state,\n\t\t\t});\n\t\t},\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["defineType"],"sources":["../../src/tanstack-router/auth-coordination/route-metadata.ts","../../src/tanstack-router/auth-coordination/route-guard.ts","../../src/tanstack-router/auth-coordination/secure-routes.ts","../../src/tanstack-router/router.ts"],"sourcesContent":["import {\n\ttype AuthRequirement,\n\ttype RouteTreeSegment,\n\treadSecuritydeptRouteMetadata,\n} from \"@securitydept/client\";\n\nexport interface TanStackRouteMatchLike {\n\treadonly id?: string;\n\treadonly routeId?: string;\n\treadonly pathname?: string;\n\treadonly staticData?: object;\n}\n\nexport function projectTanStackRouteSegments<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n>(\n\tmatches: readonly TanStackRouteMatchLike[],\n): RouteTreeSegment<TAuthRequirement>[] {\n\treturn matches.map((match, index) => {\n\t\tconst metadata = readSecuritydeptRouteMetadata<TAuthRequirement>(\n\t\t\tmatch.staticData,\n\t\t);\n\t\treturn {\n\t\t\trouteId:\n\t\t\t\tmatch.routeId ??\n\t\t\t\tmatch.id ??\n\t\t\t\tmatch.pathname ??\n\t\t\t\t`tanstack-route-${index}`,\n\t\t\trequirements: metadata?.requirements ?? [],\n\t\t\tcomposition: metadata?.composition,\n\t\t};\n\t});\n}\n","import {\n\ttype AuthRequirement,\n\tENVIRONMENT_TOKEN,\n\tinjectRequirementPlannerHost,\n\tPipelineOutcome,\n\ttype RequirementBehaviourWithRouteContext,\n\tRequirementPlannerHost,\n\ttype RequirementPlannerHostBehaviour,\n\ttype RouteBehaviourContextExtra,\n\tRouteCompositionRequirementPlanner,\n\ttype SecuritydeptInjectorTrait,\n} from \"@securitydept/client\";\nimport { redirect } from \"@tanstack/react-router\";\nimport {\n\tprojectTanStackRouteSegments,\n\ttype TanStackRouteMatchLike,\n} from \"./route-metadata\";\n\nexport interface SecuritydeptTanStackRouterContext {\n\treadonly securitydeptInjector: SecuritydeptInjectorTrait;\n\treadonly router?: {\n\t\treadonly state: {\n\t\t\treadonly matches: readonly TanStackRouteMatchLike[];\n\t\t};\n\t};\n}\n\nexport interface TanStackBeforeLoadContextLike {\n\treadonly context: SecuritydeptTanStackRouterContext;\n\treadonly matches: readonly TanStackRouteMatchLike[];\n\treadonly location: {\n\t\treadonly href: string;\n\t};\n}\n\nexport interface CreateTanStackBeforeLoadWithPlannerHostOptions<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n> {\n\treadonly plannerHost: RequirementPlannerHost<TBehaviour>;\n\treadonly behaviour?: never;\n}\n\nexport interface CreateTanStackBeforeLoadWithBehaviourOptions<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n> {\n\treadonly plannerHost?: never;\n\treadonly behaviour?: RequirementPlannerHostBehaviour<\n\t\tTAuthRequirement,\n\t\tRouteBehaviourContextExtra,\n\t\tTBehaviour\n\t>;\n}\n\nexport type CreateTanStackBeforeLoadOptions<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n> =\n\t| CreateTanStackBeforeLoadWithPlannerHostOptions<TAuthRequirement, TBehaviour>\n\t| CreateTanStackBeforeLoadWithBehaviourOptions<TAuthRequirement, TBehaviour>;\n\nexport class TanStackRouteSecurityBlockedError extends Error {\n\tconstructor(readonly requirement: AuthRequirement) {\n\t\tsuper(`TanStack route security blocked requirement: ${requirement.id}`);\n\t\tthis.name = \"TanStackRouteSecurityBlockedError\";\n\t}\n}\n\nexport function createTanStackBeforeLoad<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n>(options?: CreateTanStackBeforeLoadOptions<TAuthRequirement, TBehaviour>) {\n\treturn async (context: TanStackBeforeLoadContextLike): Promise<void> => {\n\t\tconst injector = context.context.securitydeptInjector;\n\t\tconst parentHost = injectRequirementPlannerHost<\n\t\t\tTAuthRequirement,\n\t\t\tRouteBehaviourContextExtra,\n\t\t\tTBehaviour\n\t\t>({ injector });\n\t\tconst host =\n\t\t\toptions?.plannerHost ??\n\t\t\t(options?.behaviour\n\t\t\t\t? RequirementPlannerHost.fromBehaviour(\n\t\t\t\t\t\ttypeof options.behaviour === \"function\"\n\t\t\t\t\t\t\t? options.behaviour()\n\t\t\t\t\t\t\t: options.behaviour,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tparent: parentHost ?? undefined,\n\t\t\t\t\t\t\tenvironment: injector.get(ENVIRONMENT_TOKEN, null) ?? undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t: parentHost) ??\n\t\t\tRequirementPlannerHost.fromBehaviour({} as TBehaviour);\n\t\tconst segments = projectTanStackRouteSegments<TAuthRequirement>(\n\t\t\tcontext.matches,\n\t\t);\n\t\tconst planner = RouteCompositionRequirementPlanner.fromRouteSegments(\n\t\t\thost,\n\t\t\tsegments,\n\t\t\t{\n\t\t\t\turl: context.location.href,\n\t\t\t},\n\t\t);\n\t\tconst result = await planner.runUntilSettled();\n\t\tswitch (result.outcome) {\n\t\t\tcase PipelineOutcome.Settled:\n\t\t\t\treturn;\n\t\t\tcase PipelineOutcome.Blocked:\n\t\t\t\tthrow new TanStackRouteSecurityBlockedError(result.requirement);\n\t\t\tcase PipelineOutcome.Redirect:\n\t\t\t\tthrow redirect({ to: result.location });\n\t\t}\n\t};\n}\n","import {\n\ttype AuthRequirement,\n\ttype FoundationEnvironment,\n\ttype RequirementBehaviourWithRouteContext,\n\ttype RequirementPlannerHost,\n\ttype RequirementPlannerHostBehaviour,\n\ttype RequirementsComposition,\n\ttype RouteBehaviourContextExtra,\n\ttype SecuritydeptInjectorTrait,\n\ttype SecuritydeptRouteMetadata,\n\twriteSecuritydeptRouteMetadata,\n} from \"@securitydept/client\";\nimport {\n\tcreateTanStackBeforeLoad,\n\ttype SecuritydeptTanStackRouterContext,\n\ttype TanStackBeforeLoadContextLike,\n} from \"./route-guard\";\n\nexport interface CreateTanStackRouterContextOptions {\n\treadonly environment?: FoundationEnvironment;\n\treadonly injector?: SecuritydeptInjectorTrait;\n}\n\nexport interface TanStackRouteSecurityOptions<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n> {\n\treadonly requirements?: readonly TAuthRequirement[];\n\treadonly composition?: RequirementsComposition;\n\treadonly plannerHost?: RequirementPlannerHost<TBehaviour>;\n\treadonly behaviour?: RequirementPlannerHostBehaviour<\n\t\tTAuthRequirement,\n\t\tRouteBehaviourContextExtra,\n\t\tTBehaviour\n\t>;\n}\n\nexport interface CreateTanStackRouteSecurityPatchOptions {\n\treadonly staticData?: object;\n}\n\nexport interface TanStackRouteSecurityPatch {\n\treadonly staticData: Record<string, unknown>;\n}\n\nexport interface TanStackRouteRootSecurityPatch\n\textends TanStackRouteSecurityPatch {\n\treadonly beforeLoad: (\n\t\tcontext: TanStackBeforeLoadContextLike,\n\t) => Promise<void>;\n}\n\nexport function createTanStackRouterContext(\n\toptions: CreateTanStackRouterContextOptions = {},\n): Pick<SecuritydeptTanStackRouterContext, \"securitydeptInjector\"> {\n\tconst securitydeptInjector =\n\t\toptions.injector ?? options.environment?.injector;\n\tif (!securitydeptInjector) {\n\t\tthrow new Error(\n\t\t\t\"[createTanStackRouterContext] Missing SecurityDept injector. Pass `injector` or `environment`.\",\n\t\t);\n\t}\n\treturn { securitydeptInjector };\n}\n\nexport function secureRoute<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n>(\n\tsecurity: TanStackRouteSecurityOptions<TAuthRequirement, TBehaviour>,\n\toptions: CreateTanStackRouteSecurityPatchOptions = {},\n): TanStackRouteSecurityPatch {\n\treturn {\n\t\tstaticData: writeRequirementStaticData(security, options.staticData),\n\t};\n}\n\nexport function secureRouteRoot<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n>(\n\tsecurity: TanStackRouteSecurityOptions<TAuthRequirement, TBehaviour>,\n\toptions: CreateTanStackRouteSecurityPatchOptions = {},\n): TanStackRouteRootSecurityPatch {\n\tconst securityBeforeLoad = createTanStackBeforeLoad<\n\t\tTAuthRequirement,\n\t\tTBehaviour\n\t>(\n\t\tsecurity.plannerHost\n\t\t\t? { plannerHost: security.plannerHost }\n\t\t\t: security.behaviour\n\t\t\t\t? { behaviour: security.behaviour }\n\t\t\t\t: undefined,\n\t);\n\treturn {\n\t\tstaticData: writeRequirementStaticData(security, options.staticData),\n\t\tbeforeLoad: securityBeforeLoad,\n\t};\n}\n\nfunction writeRequirementStaticData<\n\tTAuthRequirement extends AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t>,\n>(\n\tsecurity: TanStackRouteSecurityOptions<TAuthRequirement, TBehaviour>,\n\tbase: object | undefined,\n): Record<string, unknown> {\n\tconst patch: SecuritydeptRouteMetadata<TAuthRequirement> = {};\n\tif (security.requirements !== undefined) {\n\t\tpatch.requirements = security.requirements;\n\t}\n\tif (security.composition !== undefined) {\n\t\tpatch.composition = security.composition;\n\t}\n\tif (Object.keys(patch).length === 0) {\n\t\treturn { ...(base ?? {}) };\n\t}\n\treturn writeSecuritydeptRouteMetadata(base, patch);\n}\n","import {\n\ttype EnvironmentValidators,\n\tRouterNavigationMode,\n\ttype RouterNavigationRequest,\n\ttype RouterTrait,\n\tthrowValidationClientError,\n\tUriReferenceString,\n\tUriReferenceStringSchema,\n\tvalidateTraitInput,\n\ttype WithTraitInputValidator,\n} from \"@securitydept/client\";\nimport { type AnyRouter, type NavigateOptions } from \"@tanstack/react-router\";\nimport { type as defineType } from \"arktype\";\n\nexport interface TanStackRouterLocationLike {\n\treadonly href: string;\n}\n\nexport interface TanStackRouterNavigationLike {\n\treadonly state?: {\n\t\treadonly location?: TanStackRouterLocationLike;\n\t};\n\tnavigate(options: TanStackRouterNavigateOptions): Promise<unknown> | unknown;\n}\n\nexport type TanStackRouterNavigateOptions = NavigateOptions<\n\tAnyRouter,\n\tstring,\n\tstring | undefined,\n\tstring,\n\t\"\"\n>;\n\nexport interface CreateRouterForTanStackRouterOptions {\n\treadonly router: TanStackRouterNavigationLike;\n\treadonly currentUrl?: string | null;\n}\n\nexport interface ResolvedRouterForTanStackRouterCreateOptions {\n\treadonly router: TanStackRouterNavigationLike;\n\treadonly currentUrl: string | null;\n}\n\nconst TanStackRouterNavigationLikeSchema = defineType({\n\tstate: \"object?\",\n\tnavigate: \"Function\",\n});\n\nconst ResolvedRouterForTanStackRouterCreateOptionsSchema = defineType({\n\trouter: TanStackRouterNavigationLikeSchema,\n\tcurrentUrl: UriReferenceStringSchema.or(\"null\"),\n});\n\nexport function createRouterForTanStackRouter(\n\toptions: CreateRouterForTanStackRouterOptions &\n\t\tWithTraitInputValidator<Pick<EnvironmentValidators, \"router\">>,\n): RouterTrait {\n\tconst routerInput = options.router as\n\t\t| TanStackRouterNavigationLike\n\t\t| null\n\t\t| undefined;\n\tconst resolvedCreateOptions: ResolvedRouterForTanStackRouterCreateOptions = {\n\t\trouter: options.router,\n\t\tget currentUrl() {\n\t\t\tif (Object.hasOwn(options, \"currentUrl\")) {\n\t\t\t\treturn options.currentUrl ?? null;\n\t\t\t}\n\n\t\t\treturn routerInput?.state?.location?.href ?? null;\n\t\t},\n\t};\n\n\tvalidateTraitInput({\n\t\tvalue: resolvedCreateOptions,\n\t\tbundledSchema: ResolvedRouterForTanStackRouterCreateOptionsSchema,\n\t\tvalidator: options.validators?.router,\n\t\tonInvalid: (failure) =>\n\t\t\tthrowValidationClientError({\n\t\t\t\tcode: \"client_react.tanstack_router.invalid_router_options\",\n\t\t\t\tsource: \"client-react\",\n\t\t\t\tmessagePrefix:\n\t\t\t\t\t\"createRouterForTanStackRouter could not validate routerForTanStackRouterCreateOptions\",\n\t\t\t\tfailure,\n\t\t\t}),\n\t});\n\n\tconst { router } = resolvedCreateOptions;\n\treturn {\n\t\tcurrentUrl() {\n\t\t\tconst currentUrl = resolvedCreateOptions.currentUrl;\n\t\t\treturn currentUrl == null ? null : UriReferenceString.parse(currentUrl);\n\t\t},\n\t\tasync navigate(request: RouterNavigationRequest) {\n\t\t\tif (request.mode === RouterNavigationMode.External) {\n\t\t\t\tawait router.navigate({ href: request.url.toString() });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait router.navigate({\n\t\t\t\tto: request.url.toString(),\n\t\t\t\treplace: request.mode === RouterNavigationMode.Replace,\n\t\t\t\tstate: request.state as TanStackRouterNavigateOptions[\"state\"],\n\t\t\t});\n\t\t},\n\t};\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@securitydept/client-react",
3
- "version": "0.3.0-beta.5",
3
+ "version": "0.3.0-beta.7",
4
4
  "description": "Client React of the SecurityDept TypeScript SDK, a layered authentication and authorization toolkit built as reusable Rust crates, a TypeScript client SDK workspace, and reference server/web apps.",
5
5
  "author": "Zhou Yeheng <root@aitiotekt.com>",
6
6
  "license": "MIT",
@@ -41,14 +41,14 @@
41
41
  "dist"
42
42
  ],
43
43
  "dependencies": {
44
- "arktype": "^2.2.0",
45
- "es-toolkit": "^1.49.0",
44
+ "arktype": "^2.2.3",
45
+ "es-toolkit": "^1.50.0",
46
46
  "rxjs": "^7.8.2",
47
- "@securitydept/client": "0.3.0-beta.5"
47
+ "@securitydept/client": "0.3.0-beta.7"
48
48
  },
49
49
  "peerDependencies": {
50
- "react": ">=19.0.0",
51
- "@tanstack/react-router": ">=1.0.0"
50
+ "@tanstack/react-router": ">=1.0.0",
51
+ "react": ">=19.0.0"
52
52
  },
53
53
  "peerDependenciesMeta": {
54
54
  "@tanstack/react-router": {
@@ -57,8 +57,8 @@
57
57
  },
58
58
  "devDependencies": {
59
59
  "@tanstack/react-router": "^1.170.18",
60
- "react": "^19.2.6",
61
- "vitest": "^4.1.6"
60
+ "react": "^19.2.8",
61
+ "vitest": "^4.1.10"
62
62
  },
63
63
  "scripts": {
64
64
  "build": "tsdown",