@securitydept/client 0.3.0-beta.3 → 0.3.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/create-Bm-XRA3G.mjs +1573 -0
- package/dist/create-Bm-XRA3G.mjs.map +1 -0
- package/dist/index-BT-u3qNI.d.mts +133 -0
- package/dist/index-Ch8lrE44.d.mts +625 -0
- package/dist/index-D5mW18cM.d.mts +1648 -0
- package/dist/index.d.mts +3 -353
- package/dist/index.mjs +1124 -362
- package/dist/index.mjs.map +1 -1
- package/dist/router-BJ8LqNJ1.mjs +245 -0
- package/dist/router-BJ8LqNJ1.mjs.map +1 -0
- package/dist/rx/index.d.mts +69 -0
- package/dist/rx/index.mjs +2 -0
- package/dist/rx-BoB32Dzg.mjs +1106 -0
- package/dist/rx-BoB32Dzg.mjs.map +1 -0
- package/dist/server/index.d.mts +21 -0
- package/dist/server/index.mjs +29 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/test/index.d.mts +102 -0
- package/dist/test/index.mjs +270 -0
- package/dist/test/index.mjs.map +1 -0
- package/dist/uri-string-BfnIT4gJ.mjs +298 -0
- package/dist/uri-string-BfnIT4gJ.mjs.map +1 -0
- package/dist/web/index.d.mts +82 -364
- package/dist/web/index.mjs +329 -428
- package/dist/web/index.mjs.map +1 -1
- package/dist/webext/index.d.mts +74 -0
- package/dist/webext/index.mjs +229 -0
- package/dist/webext/index.mjs.map +1 -0
- package/package.json +28 -21
- package/dist/auth-coordination/index.d.mts +0 -198
- package/dist/auth-coordination/index.mjs +0 -107
- package/dist/auth-coordination/index.mjs.map +0 -1
- package/dist/client-environment-CaumNmir.mjs +0 -812
- package/dist/client-environment-CaumNmir.mjs.map +0 -1
- package/dist/client-environment-CdHtVxKW.d.mts +0 -401
- package/dist/events/index.d.mts +0 -2
- package/dist/events/index.mjs +0 -2
- package/dist/events-BUlfsRfl.mjs +0 -127
- package/dist/events-BUlfsRfl.mjs.map +0 -1
- package/dist/index-C4xlKhG7.d.mts +0 -102
- package/dist/index-COUt5x9Z.d.mts +0 -39
- package/dist/persistence/index.d.mts +0 -3
- package/dist/persistence/index.mjs +0 -2
- package/dist/persistence/web/index.d.mts +0 -16
- package/dist/persistence/web/index.mjs +0 -2
- package/dist/persistence-CSB8770k.mjs +0 -108
- package/dist/persistence-CSB8770k.mjs.map +0 -1
- package/dist/planner-host-BTWie0lo.mjs +0 -197
- package/dist/planner-host-BTWie0lo.mjs.map +0 -1
- package/dist/planner-host-DN9dRsQx.d.mts +0 -190
- package/dist/types-BJqUdH2e.d.mts +0 -32
- package/dist/types-BwcnUGNl.d.mts +0 -52
- package/dist/web-DQmMqZnR.mjs +0 -51
- package/dist/web-DQmMqZnR.mjs.map +0 -1
- package/dist/web-router/index.d.mts +0 -259
- package/dist/web-router/index.mjs +0 -395
- package/dist/web-router/index.mjs.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/cancellation/cancellation-token.ts","../src/cancellation/linked-cancellation-token.ts","../src/errors/presentation-descriptor.ts","../src/identity/principal.ts","../src/logging/console-logger.ts","../src/logging/noop-logger.ts","../src/logging/trace-timeline-store.ts","../src/signals/computed.ts","../src/signals/signal.ts","../src/validation/index.ts"],"sourcesContent":["import { ClientError } from \"../errors/client-error\";\nimport { ClientErrorKind } from \"../errors/types\";\nimport type {\n\tCancellationTokenSourceTrait,\n\tCancellationTokenTrait,\n\tDisposableTrait,\n} from \"./types\";\n\nclass CancellationToken implements CancellationTokenTrait {\n\tprivate _isCancelled = false;\n\tprivate _reason: unknown;\n\tprivate readonly _listeners = new Set<(reason: unknown) => void>();\n\n\tget isCancellationRequested(): boolean {\n\t\treturn this._isCancelled;\n\t}\n\n\tget reason(): unknown {\n\t\treturn this._reason;\n\t}\n\n\t/** @internal — called by `CancellationTokenSource`. */\n\t_cancel(reason: unknown): void {\n\t\tif (this._isCancelled) return;\n\t\tthis._isCancelled = true;\n\t\tthis._reason = reason;\n\t\tfor (const listener of this._listeners) {\n\t\t\tlistener(reason);\n\t\t}\n\t\tthis._listeners.clear();\n\t}\n\n\tonCancellationRequested(\n\t\tlistener: (reason: unknown) => void,\n\t): DisposableTrait {\n\t\tif (this._isCancelled) {\n\t\t\t// Already cancelled — invoke immediately.\n\t\t\tlistener(this._reason);\n\t\t\treturn { dispose() {} };\n\t\t}\n\t\tthis._listeners.add(listener);\n\t\treturn {\n\t\t\tdispose: () => {\n\t\t\t\tthis._listeners.delete(listener);\n\t\t\t},\n\t\t};\n\t}\n\n\tthrowIfCancellationRequested(): void {\n\t\tif (this._isCancelled) {\n\t\t\tthrow new ClientError({\n\t\t\t\tkind: ClientErrorKind.Cancelled,\n\t\t\t\tmessage: \"Operation was cancelled\",\n\t\t\t\tcause: this._reason,\n\t\t\t});\n\t\t}\n\t}\n}\n\n/**\n * Create a `CancellationTokenSource` that produces a cooperative cancellation token.\n */\nexport function createCancellationTokenSource(): CancellationTokenSourceTrait {\n\tconst ct = new CancellationToken();\n\tlet disposed = false;\n\n\treturn {\n\t\tget token(): CancellationTokenTrait {\n\t\t\treturn ct;\n\t\t},\n\t\tcancel(reason?: unknown) {\n\t\t\tif (!disposed) ct._cancel(reason);\n\t\t},\n\t\tdispose() {\n\t\t\tif (!disposed) {\n\t\t\t\tdisposed = true;\n\t\t\t\tct._cancel(\n\t\t\t\t\tnew ClientError({\n\t\t\t\t\t\tkind: ClientErrorKind.Cancelled,\n\t\t\t\t\t\tmessage: \"Disposed\",\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t};\n}\n","import { createCancellationTokenSource } from \"./cancellation-token\";\nimport type { CancellationTokenTrait } from \"./types\";\n\n/**\n * Create a cancellation token that fires when ANY of the given source tokens\n * is cancelled.\n *\n * - Zero sources → returns a token that is never cancelled.\n * - One source → returns that source directly (no allocation).\n * - N sources → creates a linked source, subscribes to all, and cleans up\n * subscriptions once the linked token fires.\n *\n * @example\n * const cts = createCancellationTokenSource();\n * const linked = createLinkedCancellationToken(clientRoot.token, cts.token);\n * await transport.execute({ ..., cancellationToken: linked });\n */\nexport function createLinkedCancellationToken(\n\t...sources: CancellationTokenTrait[]\n): CancellationTokenTrait {\n\t// Zero sources — return a token that is never cancelled.\n\tif (sources.length === 0) {\n\t\treturn createCancellationTokenSource().token;\n\t}\n\n\t// One source — return directly; no allocation needed.\n\tif (sources.length === 1) {\n\t\treturn sources[0];\n\t}\n\n\t// Fast-path: return the first already-cancelled source immediately.\n\tfor (const source of sources) {\n\t\tif (source.isCancellationRequested) return source;\n\t}\n\n\tconst linked = createCancellationTokenSource();\n\tconst subscriptions = sources.map((source) =>\n\t\tsource.onCancellationRequested((reason) => linked.cancel(reason)),\n\t);\n\n\t// Clean up all subscriptions once the linked token fires.\n\tlinked.token.onCancellationRequested(() => {\n\t\tfor (const sub of subscriptions) sub.dispose();\n\t});\n\n\treturn linked.token;\n}\n","import { ClientError } from \"./client-error\";\nimport {\n\tClientErrorKind,\n\ttype ErrorPresentation,\n\ttype ErrorPresentationActionDescriptor,\n\ttype ErrorPresentationDescriptor,\n\tErrorPresentationTone,\n\ttype ReadErrorPresentationDescriptorOptions,\n\tUserRecovery,\n} from \"./types\";\n\ninterface ClientErrorLike {\n\tcode: string | null;\n\tkind: ClientErrorKind | null;\n\tmessage: string;\n\trecovery: UserRecovery;\n\tretryable: boolean;\n\tsource?: string;\n\tpresentation?: ErrorPresentation;\n}\n\nconst DEFAULT_RECOVERY_LABELS: Record<UserRecovery, string> = {\n\t[UserRecovery.None]: \"\",\n\t[UserRecovery.Retry]: \"Try again\",\n\t[UserRecovery.RestartFlow]: \"Restart flow\",\n\t[UserRecovery.Reauthenticate]: \"Sign in again\",\n\t[UserRecovery.ContactSupport]: \"Contact support\",\n};\n\nconst POPUP_PRESENTATIONS = {\n\t\"popup.blocked\": {\n\t\ttitle: \"Popup was blocked\",\n\t\tdescription:\n\t\t\t\"The browser blocked the popup window before the login flow could start. Allow popups for this site, then try again.\",\n\t\ttone: ErrorPresentationTone.Warning,\n\t},\n\t\"popup.closed_by_user\": {\n\t\ttitle: \"Popup login was closed\",\n\t\tdescription:\n\t\t\t\"The popup window was closed before the OIDC provider returned a callback. Start the login flow again to continue.\",\n\t\ttone: ErrorPresentationTone.Warning,\n\t},\n\t\"popup.relay_timeout\": {\n\t\ttitle: \"Popup relay timed out\",\n\t\tdescription:\n\t\t\t\"The popup callback never relayed back to the opener before the timeout window expired.\",\n\t\ttone: ErrorPresentationTone.Warning,\n\t},\n\t\"popup.relay_error\": {\n\t\ttitle: \"Popup relay failed\",\n\t\tdescription:\n\t\t\t\"The popup callback page returned an error instead of a callback payload.\",\n\t\ttone: ErrorPresentationTone.Danger,\n\t},\n} as const;\n\nexport function readErrorPresentationDescriptor(\n\terror: unknown,\n\toptions: ReadErrorPresentationDescriptorOptions = {},\n): ErrorPresentationDescriptor {\n\tif (error instanceof ClientError) {\n\t\treturn describeClientErrorPresentation(error, options);\n\t}\n\n\tconst clientErrorLike = coerceClientErrorLike(error);\n\tif (clientErrorLike) {\n\t\treturn describeClientErrorLikePresentation(clientErrorLike, options);\n\t}\n\n\tif (error instanceof Error) {\n\t\treturn {\n\t\t\tcode: null,\n\t\t\tkind: null,\n\t\t\ttitle: options.fallbackTitle ?? \"Operation failed\",\n\t\t\tdescription:\n\t\t\t\terror.message ||\n\t\t\t\toptions.fallbackDescription ||\n\t\t\t\t\"An unexpected error prevented the operation from completing.\",\n\t\t\trecovery: UserRecovery.None,\n\t\t\tretryable: false,\n\t\t\ttone: ErrorPresentationTone.Danger,\n\t\t\tprimaryAction: null,\n\t\t};\n\t}\n\n\treturn {\n\t\tcode: null,\n\t\tkind: null,\n\t\ttitle: options.fallbackTitle ?? \"Operation failed\",\n\t\tdescription:\n\t\t\toptions.fallbackDescription ??\n\t\t\t\"An unexpected error prevented the operation from completing.\",\n\t\trecovery: UserRecovery.None,\n\t\tretryable: false,\n\t\ttone: ErrorPresentationTone.Danger,\n\t\tprimaryAction: null,\n\t};\n}\n\nfunction describeClientErrorPresentation(\n\terror: ClientError,\n\toptions: ReadErrorPresentationDescriptorOptions,\n): ErrorPresentationDescriptor {\n\treturn describeClientErrorLikePresentation(\n\t\t{\n\t\t\tcode: error.code,\n\t\t\tkind: error.kind,\n\t\t\tmessage: error.message,\n\t\t\trecovery: error.recovery,\n\t\t\tretryable: error.retryable,\n\t\t\tsource: error.source,\n\t\t\tpresentation: error.presentation,\n\t\t},\n\t\toptions,\n\t);\n}\n\nfunction describeClientErrorLikePresentation(\n\terror: ClientErrorLike,\n\toptions: ReadErrorPresentationDescriptorOptions,\n): ErrorPresentationDescriptor {\n\tconst popupPresentation =\n\t\tPOPUP_PRESENTATIONS[error.code as keyof typeof POPUP_PRESENTATIONS];\n\tconst title = popupPresentation?.title ?? readClientErrorTitle(error);\n\tconst description =\n\t\tpopupPresentation?.description ??\n\t\terror.presentation?.message ??\n\t\terror.message ??\n\t\toptions.fallbackDescription ??\n\t\t\"The operation could not complete.\";\n\n\treturn {\n\t\tcode: error.code,\n\t\tkind: error.kind,\n\t\tsource: error.source,\n\t\ttitle,\n\t\tdescription,\n\t\trecovery: error.recovery,\n\t\tretryable: error.retryable,\n\t\ttone: popupPresentation?.tone ?? readClientErrorTone(error),\n\t\tprimaryAction: readPrimaryAction(error.recovery, options),\n\t};\n}\n\nfunction readClientErrorTitle(\n\terror: Pick<ClientErrorLike, \"kind\" | \"recovery\">,\n): string {\n\tif (error.kind === ClientErrorKind.Unauthenticated) {\n\t\treturn \"Authentication required\";\n\t}\n\n\tif (error.kind === ClientErrorKind.Unauthorized) {\n\t\treturn \"Access denied\";\n\t}\n\n\tif (error.kind === ClientErrorKind.Cancelled) {\n\t\treturn \"Operation cancelled\";\n\t}\n\n\tif (error.kind === ClientErrorKind.Timeout) {\n\t\treturn \"Request timed out\";\n\t}\n\n\tif (error.kind === ClientErrorKind.Configuration) {\n\t\treturn \"Configuration error\";\n\t}\n\n\tif (error.kind === ClientErrorKind.Validation) {\n\t\treturn \"Validation failed\";\n\t}\n\n\tif (error.kind === ClientErrorKind.Storage) {\n\t\treturn \"Browser storage failed\";\n\t}\n\n\tif (\n\t\terror.kind === ClientErrorKind.Authorization &&\n\t\terror.recovery === UserRecovery.RestartFlow\n\t) {\n\t\treturn \"Flow needs to restart\";\n\t}\n\n\tif (error.kind === ClientErrorKind.Transport) {\n\t\treturn \"Network request failed\";\n\t}\n\n\tif (error.kind === ClientErrorKind.Server) {\n\t\treturn \"Server request failed\";\n\t}\n\n\tif (error.kind === ClientErrorKind.Protocol) {\n\t\treturn \"Request failed\";\n\t}\n\n\treturn \"Operation failed\";\n}\n\nfunction readClientErrorTone(\n\terror: Pick<ClientErrorLike, \"kind\" | \"recovery\">,\n) {\n\tif (error.kind === ClientErrorKind.Cancelled) {\n\t\treturn ErrorPresentationTone.Neutral;\n\t}\n\n\tif (\n\t\terror.kind === ClientErrorKind.Unauthenticated ||\n\t\terror.kind === ClientErrorKind.Timeout ||\n\t\terror.kind === ClientErrorKind.Transport ||\n\t\terror.kind === ClientErrorKind.Server ||\n\t\terror.recovery === UserRecovery.Retry ||\n\t\terror.recovery === UserRecovery.RestartFlow ||\n\t\terror.recovery === UserRecovery.Reauthenticate\n\t) {\n\t\treturn ErrorPresentationTone.Warning;\n\t}\n\n\treturn ErrorPresentationTone.Danger;\n}\n\nfunction coerceClientErrorLike(error: unknown): ClientErrorLike | null {\n\tif (typeof error !== \"object\" || error === null) {\n\t\treturn null;\n\t}\n\n\tconst candidate = error as Record<string, unknown>;\n\tif (typeof candidate.message !== \"string\") {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tcode: typeof candidate.code === \"string\" ? candidate.code : null,\n\t\tkind:\n\t\t\ttypeof candidate.kind === \"string\"\n\t\t\t\t? (candidate.kind as ClientErrorKind)\n\t\t\t\t: null,\n\t\tmessage: candidate.message,\n\t\trecovery:\n\t\t\ttypeof candidate.recovery === \"string\"\n\t\t\t\t? (candidate.recovery as UserRecovery)\n\t\t\t\t: UserRecovery.None,\n\t\tretryable: candidate.retryable === true,\n\t\tsource: typeof candidate.source === \"string\" ? candidate.source : undefined,\n\t\tpresentation: isErrorPresentation(candidate.presentation)\n\t\t\t? candidate.presentation\n\t\t\t: undefined,\n\t};\n}\n\nfunction isErrorPresentation(value: unknown): value is ErrorPresentation {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\ttypeof (value as Record<string, unknown>).code === \"string\" &&\n\t\ttypeof (value as Record<string, unknown>).message === \"string\" &&\n\t\ttypeof (value as Record<string, unknown>).recovery === \"string\"\n\t);\n}\n\nfunction readPrimaryAction(\n\trecovery: UserRecovery,\n\toptions: ReadErrorPresentationDescriptorOptions,\n): ErrorPresentationActionDescriptor | null {\n\tif (recovery === UserRecovery.None) {\n\t\treturn null;\n\t}\n\n\tconst label =\n\t\toptions.recoveryLabels?.[recovery] ?? DEFAULT_RECOVERY_LABELS[recovery];\n\tif (!label) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\trecovery,\n\t\tlabel,\n\t\thref: options.recoveryLinks?.[recovery] ?? null,\n\t};\n}\n","export interface AuthenticatedPrincipal {\n\tsubject: string;\n\tdisplayName: string;\n\tpicture?: string;\n\tissuer?: string;\n\tclaims?: Record<string, unknown>;\n}\n\ntype PrincipalObject = Record<string, unknown>;\n\nfunction readClaimsBag(value: unknown): Record<string, unknown> | undefined {\n\treturn typeof value === \"object\" && value !== null\n\t\t? (value as Record<string, unknown>)\n\t\t: undefined;\n}\n\nfunction readOptionalString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction resolveDisplayName(displayName: unknown, subject: string): string {\n\tif (typeof displayName === \"string\" && displayName.trim().length > 0) {\n\t\treturn displayName;\n\t}\n\n\treturn subject;\n}\n\nexport function normalizeAuthenticatedPrincipal(\n\tinput: PrincipalObject,\n): AuthenticatedPrincipal | null {\n\tif (typeof input.subject !== \"string\" || input.subject.trim().length === 0) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tsubject: input.subject,\n\t\tdisplayName: resolveDisplayName(input.displayName, input.subject),\n\t\tpicture: readOptionalString(input.picture),\n\t\tissuer: readOptionalString(input.issuer),\n\t\tclaims: readClaimsBag(input.claims),\n\t};\n}\n\nexport function normalizeAuthenticatedPrincipalWire(\n\tinput: PrincipalObject,\n): AuthenticatedPrincipal | null {\n\tif (typeof input.subject !== \"string\" || input.subject.trim().length === 0) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tsubject: input.subject,\n\t\tdisplayName: resolveDisplayName(input.display_name, input.subject),\n\t\tpicture: readOptionalString(input.picture),\n\t\tissuer: readOptionalString(input.issuer),\n\t\tclaims: readClaimsBag(input.claims),\n\t};\n}\n\nexport interface ProjectAuthenticatedPrincipalOptions {\n\tprincipal?: AuthenticatedPrincipal | null;\n\tfallbackDisplayName?: string;\n\tfallbackSubject?: string;\n\tfallbackIssuer?: string;\n\tfallbackClaims?: Record<string, unknown>;\n}\n\nexport function projectAuthenticatedPrincipal(\n\toptions: ProjectAuthenticatedPrincipalOptions,\n): AuthenticatedPrincipal {\n\tconst principal = options.principal;\n\tconst subject =\n\t\tprincipal?.subject ?? options.fallbackSubject ?? \"context.anonymous\";\n\tconst displayName =\n\t\tprincipal?.displayName?.trim() || options.fallbackDisplayName || subject;\n\n\treturn {\n\t\tsubject,\n\t\tdisplayName,\n\t\tpicture: principal?.picture,\n\t\tissuer: principal?.issuer ?? options.fallbackIssuer,\n\t\tclaims: principal?.claims ?? options.fallbackClaims,\n\t};\n}\n","import type { LogEntry, LoggerTrait } from \"./types\";\n\n/** Simple console-based logger implementation. */\nexport function createConsoleLogger(scope?: string): LoggerTrait {\n\treturn {\n\t\tlog(entry: LogEntry) {\n\t\t\tconst prefix = entry.scope ?? scope ?? \"securitydept\";\n\t\t\tconst label = `[${prefix}]`;\n\n\t\t\tswitch (entry.level) {\n\t\t\t\tcase \"debug\":\n\t\t\t\t\tconsole.debug(label, entry.message, entry.attributes ?? \"\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"info\":\n\t\t\t\t\tconsole.info(label, entry.message, entry.attributes ?? \"\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"warn\":\n\t\t\t\t\tconsole.warn(label, entry.message, entry.attributes ?? \"\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"error\":\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\tlabel,\n\t\t\t\t\t\tentry.message,\n\t\t\t\t\t\tentry.error ?? \"\",\n\t\t\t\t\t\tentry.attributes ?? \"\",\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t};\n}\n","import type { LoggerTrait } from \"./types\";\n\n/** No-op logger — default when no logger is provided. */\nexport function createNoopLogger(): LoggerTrait {\n\treturn {\n\t\tlog() {},\n\t};\n}\n","import type { TraceEvent, TraceEventSinkTrait } from \"./types\";\n\nexport interface TraceTimelineEntry extends TraceEvent {\n\tid: number;\n\trecordedAtIso: string;\n}\n\nexport interface TraceTimelineStore extends TraceEventSinkTrait {\n\tget(): readonly TraceTimelineEntry[];\n\tsubscribe(listener: () => void): () => void;\n\tclear(): void;\n}\n\nexport function createTraceTimelineStore(limit = 200): TraceTimelineStore {\n\tlet nextId = 1;\n\tlet entries: TraceTimelineEntry[] = [];\n\tconst listeners = new Set<() => void>();\n\n\tfunction readRecordedAtIso(at: number): string {\n\t\tif (!Number.isFinite(at)) {\n\t\t\treturn \"invalid-timestamp\";\n\t\t}\n\n\t\tconst date = new Date(at);\n\t\tconst timestamp = date.getTime();\n\t\tif (!Number.isFinite(timestamp)) {\n\t\t\treturn \"invalid-timestamp\";\n\t\t}\n\n\t\treturn date.toISOString();\n\t}\n\n\tfunction notify() {\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n\n\treturn {\n\t\trecord(event) {\n\t\t\tconst entry: TraceTimelineEntry = {\n\t\t\t\t...event,\n\t\t\t\tid: nextId++,\n\t\t\t\trecordedAtIso: readRecordedAtIso(event.at),\n\t\t\t};\n\t\t\tentries = [...entries, entry].slice(-limit);\n\t\t\tnotify();\n\t\t},\n\t\tget() {\n\t\t\treturn entries;\n\t\t},\n\t\tsubscribe(listener) {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tclear() {\n\t\t\tif (entries.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tentries = [];\n\t\t\tnotify();\n\t\t},\n\t};\n}\n","import type { ComputedSignalTrait, ReadableSignalTrait } from \"./types\";\n\n/**\n * Create a computed signal that derives its value from other signals.\n *\n * Semantics: lazy + cached.\n * - The compute function is NOT called at construction time.\n * - `get()` recomputes only when dirty (a dependency changed since last read).\n * - Subscribers are notified only when a dependency changes (dirty-flagged),\n * and the next `get()` will produce the fresh value.\n *\n * Dependency subscriptions are permanent for the lifetime of the computed signal.\n */\nexport function createComputed<T>(\n\tcompute: () => T,\n\tdeps: ReadableSignalTrait<unknown>[],\n): ComputedSignalTrait<T> {\n\tlet cached: T | undefined;\n\tlet dirty = true;\n\tconst listeners = new Set<() => void>();\n\n\tconst markDirty = () => {\n\t\tif (!dirty) {\n\t\t\tdirty = true;\n\t\t\tfor (const listener of listeners) {\n\t\t\t\tlistener();\n\t\t\t}\n\t\t}\n\t};\n\n\t// Dependency subscriptions are permanent.\n\tfor (const dep of deps) {\n\t\tdep.subscribe(markDirty);\n\t}\n\n\treturn {\n\t\tget() {\n\t\t\tif (dirty) {\n\t\t\t\tcached = compute();\n\t\t\t\tdirty = false;\n\t\t\t}\n\t\t\treturn cached as T;\n\t\t},\n\t\tsubscribe(listener: () => void): () => void {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t};\n}\n","import type { ReadableSignalTrait, WritableSignalTrait } from \"./types\";\n\n/**\n * Minimal writable signal implementation.\n * Snapshot-first: values are immutable snapshots, mutations go through `set()`.\n */\nexport function createSignal<T>(initial: T): WritableSignalTrait<T> {\n\tlet current = initial;\n\tconst listeners = new Set<() => void>();\n\n\treturn {\n\t\tget() {\n\t\t\treturn current;\n\t\t},\n\t\tset(value: T) {\n\t\t\tif (Object.is(current, value)) return;\n\t\t\tcurrent = value;\n\t\t\tfor (const listener of listeners) {\n\t\t\t\tlistener();\n\t\t\t}\n\t\t},\n\t\tsubscribe(listener: () => void): () => void {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t};\n}\n\n/**\n * Create a read-only view of a writable signal.\n */\nexport function readonlySignal<T>(\n\tsignal: WritableSignalTrait<T>,\n): ReadableSignalTrait<T> {\n\treturn {\n\t\tget: () => signal.get(),\n\t\tsubscribe: (listener) => signal.subscribe(listener),\n\t};\n}\n","// @securitydept/client — Foundation validation baseline\n//\n// Provides a vendor-neutral validation entry aligned with @standard-schema/spec.\n// Any StandardSchemaV1-compatible schema (zod, valibot, arktype, etc.) can be\n// used as the validation contract.\n//\n// Design principles:\n// - The foundation owns the validate-and-interpret contract\n// - Individual SDK packages supply schemas that implement StandardSchemaV1\n// - Consumers never need to know which validation library produced the schema\n\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n// ---------------------------------------------------------------------------\n// Result types\n// ---------------------------------------------------------------------------\n\n/**\n * Successful validation result.\n *\n * Contains the parsed, typed output value from the schema.\n */\nexport interface ValidationSuccess<T> {\n\treadonly success: true;\n\treadonly value: T;\n}\n\n/**\n * Failed validation result.\n *\n * Contains the list of issues reported by the schema.\n */\nexport interface ValidationFailure {\n\treadonly success: false;\n\treadonly issues: ReadonlyArray<StandardSchemaV1.Issue>;\n}\n\n/**\n * Discriminated union of validation outcomes.\n *\n * Consumers can narrow on `success` to access either the typed value\n * or the issue list.\n */\nexport type ValidationResult<T> = ValidationSuccess<T> | ValidationFailure;\n\n// ---------------------------------------------------------------------------\n// Core validation function\n// ---------------------------------------------------------------------------\n\n/**\n * Validate an unknown input against a `@standard-schema`-compatible schema.\n *\n * This is the foundation-level entry point for SDK validation. It accepts\n * any schema implementing `StandardSchemaV1` and returns a discriminated\n * `ValidationResult`.\n *\n * @example\n * ```ts\n * import { validateWithSchema } from \"@securitydept/client\";\n * import { z } from \"zod\";\n *\n * const UserSchema = z.object({ name: z.string() });\n * const result = await validateWithSchema(UserSchema, { name: \"Alice\" });\n * if (result.success) {\n * console.log(result.value.name);\n * } else {\n * console.error(result.issues);\n * }\n * ```\n */\nexport async function validateWithSchema<I, O>(\n\tschema: StandardSchemaV1<I, O>,\n\tinput: unknown,\n): Promise<ValidationResult<O>> {\n\tconst result = await schema[\"~standard\"].validate(input);\n\n\tif (\"value\" in result) {\n\t\treturn { success: true, value: result.value };\n\t}\n\n\treturn { success: false, issues: result.issues };\n}\n\n/**\n * Validate an unknown input synchronously against a `@standard-schema`-compatible schema.\n *\n * Only use this when you know the schema's validate function returns synchronously.\n * Throws if the schema returns a Promise.\n */\nexport function validateWithSchemaSync<I, O>(\n\tschema: StandardSchemaV1<I, O>,\n\tinput: unknown,\n): ValidationResult<O> {\n\tconst result = schema[\"~standard\"].validate(input);\n\n\tif (result instanceof Promise) {\n\t\tthrow new Error(\n\t\t\t\"validateWithSchemaSync: schema returned a Promise. Use validateWithSchema instead.\",\n\t\t);\n\t}\n\n\tif (\"value\" in result) {\n\t\treturn { success: true, value: result.value };\n\t}\n\n\treturn { success: false, issues: result.issues };\n}\n\n// ---------------------------------------------------------------------------\n// Schema creation helper (minimal, vendor-neutral)\n// ---------------------------------------------------------------------------\n\n/**\n * Options for creating a foundation schema.\n */\nexport interface CreateSchemaOptions<O> {\n\t/** Validation function: returns typed output or returns issues. */\n\treadonly validate: (\n\t\tinput: unknown,\n\t) =>\n\t\t| { readonly value: O }\n\t\t| { readonly issues: ReadonlyArray<StandardSchemaV1.Issue> };\n}\n\n/**\n * Create a minimal `@standard-schema`-compatible schema without requiring\n * an external validation library.\n *\n * This is useful for SDK-internal schemas where pulling in zod/valibot\n * would be excessive. For adopter-facing schemas, prefer a real validation\n * library.\n *\n * @example\n * ```ts\n * import { createSchema, validateWithSchema } from \"@securitydept/client\";\n *\n * const NameSchema = createSchema<unknown, { name: string }>({\n * validate(input) {\n * if (typeof input === \"object\" && input !== null && \"name\" in input &&\n * typeof (input as any).name === \"string\") {\n * return { value: { name: (input as any).name } };\n * }\n * return { issues: [{ message: \"Expected object with string 'name'\" }] };\n * },\n * });\n *\n * const result = await validateWithSchema(NameSchema, { name: \"Alice\" });\n * ```\n */\nexport function createSchema<O>(\n\toptions: CreateSchemaOptions<O>,\n): StandardSchemaV1<unknown, O> {\n\treturn {\n\t\t\"~standard\": {\n\t\t\tversion: 1,\n\t\t\tvendor: \"securitydept\",\n\t\t\tvalidate: options.validate,\n\t\t},\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["uuidv7","runtimeInject","runtimeRunInInjectionContext","defineType","defineType"],"sources":["../src/auth-coordination/contract.ts","../src/errors/error-attributes.ts","../src/compat/base64.ts","../src/compat/generator.ts","../src/injection/context.ts","../src/injection/destroy.ts","../src/validation/schemas/uri.ts","../src/cancellation/linked.ts","../src/signals/computed.ts","../src/signals/resource.ts","../src/router/metadata.ts","../src/std/transport/authorization-interceptor.ts","../src/tracing/operation-runner.ts","../src/tracing/operation-method.ts","../src/tracing/subscriber/console.ts","../src/tracing/subscriber/timeline-store.ts","../src/auth-coordination/planner-host.ts","../src/auth-coordination/planner/base-planner.ts","../src/auth-coordination/planner/merge-planner.ts","../src/auth-coordination/planner/route-composition-planner.ts","../src/auth-coordination/planner/static-planner.ts","../src/events/create.ts","../src/events/interop.ts","../src/identity/schemas.ts","../src/identity/parsers.ts","../src/protocol/jwt/error.ts","../src/protocol/jwt/decode.ts","../src/scheduling/duration.ts","../src/storage/json-codec.ts","../src/storage/ephemeral-flow-store.ts","../src/struct/async-lock.ts","../src/transport/url.ts"],"sourcesContent":["// Auth coordination contracts — serializable types and pure composition helpers\n//\n// Canonical public export: @securitydept/client\n//\n// This module owns the headless, framework-agnostic vocabulary shared across\n// the requirement planner host and planner variants:\n// - AuthRequirement declarations (serializable)\n// - Resolution / status value domains\n// - Behaviour callback signatures (implemented by RequirementPlannerHost)\n// - Route composition strategy and the pure folding function\n// - Pipeline result shapes\n//\n// It contains no runtime coordination logic — only types, value constants,\n// frozen factories, and the side-effect-free composition function.\n\nimport { v7 as uuidv7 } from \"uuid\";\nimport { type FoundationEnvironment } from \"../environment\";\n\n// ---------------------------------------------------------------------------\n// Requirement declaration\n// ---------------------------------------------------------------------------\nexport interface AuthRequirement {\n\t/** Unique entity id for this requirement within the plan. */\n\treadonly id: string;\n\t/** Human-readable label (for logging / debugging). */\n\treadonly label?: string;\n}\n\nexport interface StaticAttrsAuthRequirementInput<\n\tTAttributes = Record<string, unknown>,\n> {\n\treadonly id?: string;\n\treadonly label?: string;\n\treadonly attributes?: TAttributes;\n}\n\nexport class StaticAttrsAuthRequirement<TAttributes = Record<string, unknown>>\n\timplements AuthRequirement\n{\n\tprotected constructor(\n\t\treadonly id: string,\n\t\treadonly label: string | undefined,\n\t\treadonly attributes: TAttributes | undefined,\n\t) {\n\t\tObject.freeze(this);\n\t}\n\n\tpublic static create<TAttributes = Record<string, unknown>>(\n\t\tinput?: StaticAttrsAuthRequirementInput<TAttributes>,\n\t): StaticAttrsAuthRequirement<TAttributes> {\n\t\treturn new StaticAttrsAuthRequirement<TAttributes>(\n\t\t\tinput?.id ?? uuidv7(),\n\t\t\tinput?.label,\n\t\t\tinput?.attributes ? Object.freeze(input.attributes) : undefined,\n\t\t);\n\t}\n\n\tpublic static createList<TAttributes = Record<string, unknown>>(\n\t\tinputs: readonly StaticAttrsAuthRequirementInput<TAttributes>[],\n\t): readonly StaticAttrsAuthRequirement<TAttributes>[] {\n\t\treturn inputs.map((input) => StaticAttrsAuthRequirement.create(input));\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Resolution and status\n// ---------------------------------------------------------------------------\n\n/** Outcome of resolving a single requirement. */\nexport const ResolutionStatus = {\n\tFulfilled: \"fulfilled\",\n\tFailed: \"failed\",\n\tSkipped: \"skipped\",\n} as const;\n\nexport type ResolutionStatus =\n\t(typeof ResolutionStatus)[keyof typeof ResolutionStatus];\n\n/** The resolution result for a single requirement. */\nexport interface RequirementResolution {\n\t/** The requirement ID this resolution applies to. */\n\trequirementId: string;\n\t/** Outcome status. */\n\tstatus: ResolutionStatus;\n\t/** Optional error or reason for failure/skip. */\n\treason?: string;\n}\n\n/** Overall plan status. */\nexport const PlanStatus = {\n\t/** There are still pending requirements. */\n\tPending: \"pending\",\n\t/** All requirements have been resolved. */\n\tSettled: \"settled\",\n} as const;\n\nexport type PlanStatus = (typeof PlanStatus)[keyof typeof PlanStatus];\n\n/** Error thrown when a planner contract is violated (e.g. duplicate ids). */\nexport class RequirementPlannerError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"RequirementPlannerError\";\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Behaviour callbacks (implemented by RequirementPlannerHost)\n// ---------------------------------------------------------------------------\n\n/** Result of an authentication check. */\nexport type AuthenticatedCheck = boolean | Promise<boolean>;\n\n/**\n * Return value of an unauthenticated handler.\n *\n * - `true` — the requirement is now satisfied (resolved as fulfilled);\n * the pipeline records the resolution and may continue.\n * - `false` — block: the requirement cannot proceed.\n * - `string` — redirect to the given location.\n * - A never-settling `Promise` — used when a full-page external redirect has\n * started; the step intentionally never resolves so the host navigation is\n * not finalized while the page is leaving.\n */\nexport type UnauthenticatedAction =\n\t| boolean\n\t| string\n\t| Promise<boolean | string>;\n\n/**\n * Behaviour evaluation context handed to every behaviour callback.\n *\n * Reflects the planner state at the moment the callback is invoked.\n */\nexport type RequirementBehaviourContext<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n> = {\n\treadonly planContext: TPlanContext;\n\treadonly environment: FoundationEnvironment;\n\t/** The full effective requirement list for the active plan. */\n\treadonly requirements: readonly TAuthRequirement[];\n\t/** Resolutions collected so far (in requirement order). */\n\treadonly resolutionList: readonly RequirementResolution[];\n};\n\n/** Stream of unauthenticated requirements discovered by the planner. */\nexport type RequirementCandidateGenerator<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n> = AsyncGenerator<TAuthRequirement, void, unknown>;\n\n/**\n * Context handed to candidate selection.\n *\n * `candidateList` is intentionally a stream: selectors that can act on the\n * first available unauthenticated requirement do not need to wait for all\n * checks to complete, while chooser-style selectors can still collect the full\n * stream with `for await`.\n */\nexport type RequirementCandidateSelectionContext<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n> = RequirementBehaviourContext<TAuthRequirement, TPlanContext> & {\n\t/** Requirements not yet satisfied, yielded as their checks complete. */\n\treadonly candidateList: RequirementCandidateGenerator<TAuthRequirement>;\n};\n\n/** Decide whether a single requirement is already satisfied. */\nexport type CheckAuthenticated<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n> = (\n\trequirement: TAuthRequirement,\n\tcontext: RequirementBehaviourContext<TAuthRequirement, TPlanContext>,\n) => AuthenticatedCheck;\n\n/** Decide what to do when a selected requirement is unauthenticated. */\nexport type OnUnauthenticated<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n> = (\n\trequirement: TAuthRequirement,\n\tcontext: RequirementBehaviourContext<TAuthRequirement, TPlanContext>,\n) => UnauthenticatedAction;\n\n/**\n * Reduce the candidate set to the single requirement to act on next.\n *\n * The default strategy picks the first unauthenticated candidate yielded by the\n * stream. Chooser-style strategies may collect the full stream when they need\n * a complete candidate set.\n */\nexport type SelectCandidate<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n> = (\n\tcontext: RequirementCandidateSelectionContext<TAuthRequirement, TPlanContext>,\n) => TAuthRequirement | undefined | Promise<TAuthRequirement | undefined>;\n\n/** The full behaviour contract resolved by a planner host. */\nexport interface RequirementBehaviour<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n> {\n\tcheckAuthenticated: CheckAuthenticated<TAuthRequirement, TPlanContext>;\n\tonUnauthenticated: OnUnauthenticated<TAuthRequirement, TPlanContext>;\n\tselectCandidate: SelectCandidate<TAuthRequirement, TPlanContext>;\n}\n\nexport interface RouteStateSnapshotTrait {\n\treadonly url: string;\n}\n\nexport interface RouteBehaviourContextExtra {\n\treadonly routeState: RouteStateSnapshotTrait;\n}\n\nexport function isRouteStateSnapshotTrait(\n\tvalue: unknown,\n): value is RouteStateSnapshotTrait {\n\treturn typeof value === \"object\" && value !== null && \"url\" in value;\n}\n\nexport function isRouteBehaviourContextExtra(\n\tvalue: unknown,\n): value is RouteBehaviourContextExtra {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"routeState\" in value &&\n\t\tisRouteStateSnapshotTrait(value.routeState)\n\t);\n}\n\nexport type RequirementBehaviourWithRouteContext<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n> = RequirementBehaviour<TAuthRequirement, RouteBehaviourContextExtra>;\n\n// ---------------------------------------------------------------------------\n// Pipeline results\n// ---------------------------------------------------------------------------\n\n/** Outcome of a pipeline step or run. */\nexport const PipelineOutcome = {\n\t/** No candidates remain — the plan is satisfied. */\n\tSettled: \"settled\",\n\t/** A candidate was resolved as fulfilled; more may remain. */\n\tResolved: \"resolved\",\n\t/** A candidate's handler blocked progress. */\n\tBlocked: \"blocked\",\n\t/** A candidate's handler requested a redirect. */\n\tRedirect: \"redirect\",\n} as const;\n\nexport type PipelineOutcome =\n\t(typeof PipelineOutcome)[keyof typeof PipelineOutcome];\n\n/** Result of a single {@link BaseRequirementPlanner.runStep}. */\nexport type PipelineStepResult<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n> =\n\t| { outcome: typeof PipelineOutcome.Settled }\n\t| { outcome: typeof PipelineOutcome.Resolved; requirement: TAuthRequirement }\n\t| { outcome: typeof PipelineOutcome.Blocked; requirement: TAuthRequirement }\n\t| {\n\t\t\toutcome: typeof PipelineOutcome.Redirect;\n\t\t\trequirement: TAuthRequirement;\n\t\t\tlocation: string;\n\t };\n\n/** Result of {@link BaseRequirementPlanner.runUntilSettled}. */\nexport type PipelineRunResult<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n> =\n\t| {\n\t\t\toutcome: typeof PipelineOutcome.Settled;\n\t\t\tresolutions: readonly RequirementResolution[];\n\t }\n\t| { outcome: typeof PipelineOutcome.Blocked; requirement: TAuthRequirement }\n\t| {\n\t\t\toutcome: typeof PipelineOutcome.Redirect;\n\t\t\trequirement: TAuthRequirement;\n\t\t\tlocation: string;\n\t };\n\n// ---------------------------------------------------------------------------\n// Route composition\n// ---------------------------------------------------------------------------\n\n/**\n * How a route segment's requirements compose with the inherited parent chain.\n *\n * - `inherit` — keep the parent requirements unchanged (segment adds nothing)\n * - `merge` — inherit parent requirements, then append/override with the\n * segment's own (same-id entries replace the parent's)\n * - `replace` — discard the parent chain, use only the segment's requirements\n */\nexport const RequirementsComposition = {\n\tInherit: \"inherit\",\n\tMerge: \"merge\",\n\tReplace: \"replace\",\n} as const;\n\nexport type RequirementsComposition =\n\t(typeof RequirementsComposition)[keyof typeof RequirementsComposition];\n\n/** A single node in a matched route chain. */\nexport interface RouteTreeSegment<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n> {\n\t/** Route segment identifier (e.g. route name or path pattern). */\n\trouteId: string;\n\t/** Auth requirements declared on this route segment. */\n\trequirements: readonly TAuthRequirement[];\n\t/** Composition strategy against the inherited chain. Defaults to `merge`. */\n\tcomposition?: RequirementsComposition;\n}\n\n/** A requirements declaration annotated with its composition strategy. */\nexport interface RouteRequirementsDeclaration<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n> {\n\tcomposition: RequirementsComposition;\n\trequirements: readonly TAuthRequirement[];\n}\n\n/**\n * Apply a route requirements declaration onto an effective requirement map.\n *\n * Reuse `effective` across a route chain so merge/replace fold in O(total\n * requirements) without rebuilding parent state each segment. When omitted, a\n * fresh map is created for one-shot composition.\n */\nexport function resolveEffectiveRequirements<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n>(\n\tchild: RouteRequirementsDeclaration<TAuthRequirement>,\n\teffective: Map<string, TAuthRequirement> = new Map(),\n): Map<string, TAuthRequirement> {\n\tswitch (child.composition) {\n\t\tcase RequirementsComposition.Inherit:\n\t\t\treturn effective;\n\n\t\tcase RequirementsComposition.Merge:\n\t\t\tfor (const requirement of child.requirements) {\n\t\t\t\teffective.set(requirement.id, requirement);\n\t\t\t}\n\t\t\treturn effective;\n\n\t\tcase RequirementsComposition.Replace:\n\t\t\teffective.clear();\n\t\t\tfor (const requirement of child.requirements) {\n\t\t\t\teffective.set(requirement.id, requirement);\n\t\t\t}\n\t\t\treturn effective;\n\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = child.composition;\n\t\t\tthrow new RequirementPlannerError(\n\t\t\t\t`Unknown requirements composition: ${String(_exhaustive)}`,\n\t\t\t);\n\t\t}\n\t}\n}\n","import { ClientError } from \"./client-error\";\nimport { type ClientErrorKind, type UserRecovery } from \"./types\";\n\nexport interface ErrorSummary {\n\terrorName: string;\n\terrorKind?: ClientErrorKind;\n\terrorCode?: string;\n\trecovery?: UserRecovery;\n}\n\n/** Extract secret-safe diagnostic attributes without copying runtime messages. */\nexport function describeError(error: unknown): ErrorSummary {\n\tif (error instanceof ClientError) {\n\t\treturn {\n\t\t\terrorName: error.name,\n\t\t\terrorKind: error.kind,\n\t\t\terrorCode: error.code,\n\t\t\trecovery: error.recovery,\n\t\t};\n\t}\n\n\treturn {\n\t\terrorName: error instanceof Error ? error.name : typeof error,\n\t};\n}\n","import { ClientError, ClientErrorKind } from \"../errors\";\n\nexport const Base64CompatErrorCode = {\n\tEncoderUnavailable: \"compat.base64.encoder_unavailable\",\n\tDecoderUnavailable: \"compat.base64.decoder_unavailable\",\n} as const;\n\nexport type Base64CompatErrorCode =\n\t(typeof Base64CompatErrorCode)[keyof typeof Base64CompatErrorCode];\n\ntype Uint8ArrayConstructorWithBase64 = typeof Uint8Array & {\n\treadonly prototype: Uint8Array & {\n\t\ttoBase64?: () => string;\n\t};\n\tfromBase64?: (value: string) => Uint8Array;\n};\n\ninterface BufferConstructorLike {\n\tfrom(value: Uint8Array): { toString(encoding: \"base64\"): string };\n\tfrom(value: string, encoding: \"base64\"): Uint8Array;\n}\n\nexport function encodeUint8ArrayToBase64(value: Uint8Array): string {\n\tconst Uint8ArrayConstructor =\n\t\tglobalThis.Uint8Array as Uint8ArrayConstructorWithBase64;\n\tconst toBase64 = Uint8ArrayConstructor.prototype.toBase64;\n\tif (typeof toBase64 === \"function\") {\n\t\treturn toBase64.call(value);\n\t}\n\n\tif (typeof globalThis.btoa === \"function\") {\n\t\tlet binary = \"\";\n\t\tfor (const byte of value) {\n\t\t\tbinary += String.fromCharCode(byte);\n\t\t}\n\t\treturn globalThis.btoa(binary);\n\t}\n\n\tconst BufferConstructor = Reflect.get(globalThis, \"Buffer\") as\n\t\t| BufferConstructorLike\n\t\t| undefined;\n\tif (typeof BufferConstructor?.from === \"function\") {\n\t\treturn BufferConstructor.from(value).toString(\"base64\");\n\t}\n\n\tthrow new ClientError({\n\t\tkind: ClientErrorKind.Configuration,\n\t\tcode: Base64CompatErrorCode.EncoderUnavailable,\n\t\tmessage: \"The current realm does not provide a Base64 encoder.\",\n\t\tsource: \"compat.base64\",\n\t});\n}\n\nexport function decodeBase64ToUint8Array(value: string): Uint8Array {\n\tconst Uint8ArrayConstructor =\n\t\tglobalThis.Uint8Array as Uint8ArrayConstructorWithBase64;\n\tif (typeof Uint8ArrayConstructor.fromBase64 === \"function\") {\n\t\treturn Uint8ArrayConstructor.fromBase64(value);\n\t}\n\n\tif (typeof globalThis.atob === \"function\") {\n\t\tconst binary = globalThis.atob(value);\n\t\tconst bytes = new Uint8Array(binary.length);\n\t\tfor (let index = 0; index < binary.length; index += 1) {\n\t\t\tbytes[index] = binary.charCodeAt(index);\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tconst BufferConstructor = Reflect.get(globalThis, \"Buffer\") as\n\t\t| BufferConstructorLike\n\t\t| undefined;\n\tif (typeof BufferConstructor?.from === \"function\") {\n\t\treturn Uint8ArrayConstructor.from(BufferConstructor.from(value, \"base64\"));\n\t}\n\n\tthrow new ClientError({\n\t\tkind: ClientErrorKind.Configuration,\n\t\tcode: Base64CompatErrorCode.DecoderUnavailable,\n\t\tmessage: \"The current realm does not provide a Base64 decoder.\",\n\t\tsource: \"compat.base64\",\n\t});\n}\n","export async function* promisesToRacedAsyncGenerator<T>(\n\tpromises: Promise<T>[],\n): AsyncGenerator<T, void, unknown> {\n\tconst pending = new Map(\n\t\tpromises.map((promise, index) => [\n\t\t\tindex,\n\t\t\tpromise.then((value) => ({ value, index }) as const),\n\t\t]),\n\t);\n\twhile (pending.size > 0) {\n\t\tconst next = await Promise.race(pending.values());\n\t\tpending.delete(next.index);\n\t\tyield next.value;\n\t}\n}\n","import {\n\tinject as runtimeInject,\n\trunInInjectionContext as runtimeRunInInjectionContext,\n} from \"injection-js\";\nimport { toRuntimeInjector } from \"./injector\";\nimport {\n\ttype SecuritydeptDependencyToken,\n\ttype SecuritydeptInjectorTrait,\n} from \"./types\";\n\nexport interface SecuritydeptInjectOptions {\n\toptional?: boolean;\n}\n\nexport function inject<T>(\n\ttoken: SecuritydeptDependencyToken<T>,\n\toptions?: SecuritydeptInjectOptions & { optional?: false },\n): T;\nexport function inject<T>(\n\ttoken: SecuritydeptDependencyToken<T>,\n\toptions?: SecuritydeptInjectOptions & { optional?: true },\n): T | null;\nexport function inject<T>(\n\ttoken: SecuritydeptDependencyToken<T>,\n\toptions?: SecuritydeptInjectOptions,\n): T | null {\n\tif (options?.optional === true) {\n\t\treturn runtimeInject(token, {\n\t\t\toptional: true,\n\t\t});\n\t}\n\n\treturn runtimeInject(token);\n}\n\nexport function tryInjectInInjectionContext<T>(\n\ttoken: SecuritydeptDependencyToken<T>,\n\toptions?: SecuritydeptInjectOptions,\n): T | null {\n\ttry {\n\t\tif (options?.optional === true) {\n\t\t\treturn inject(token, { optional: true });\n\t\t}\n\n\t\treturn inject(token);\n\t} catch (error) {\n\t\tif (isMissingInjectionContextError(error)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n\nexport function runInInjectionContext<ReturnT>(\n\tinjector: SecuritydeptInjectorTrait,\n\tfn: () => ReturnT,\n): ReturnT {\n\treturn runtimeRunInInjectionContext(toRuntimeInjector(injector), fn);\n}\n\nfunction isMissingInjectionContextError(error: unknown): boolean {\n\treturn (\n\t\terror instanceof Error &&\n\t\terror.message.includes(\"can only be used within an injection context\")\n\t);\n}\n","import { filter, from, take } from \"rxjs\";\nimport { type DisposableTrait, SYMBOL_DISPOSE } from \"../compat/disposable\";\nimport { createSignal } from \"../signals/signal\";\n\nexport abstract class SecuritydeptDestroyRef implements DisposableTrait {\n\tabstract readonly destroyed: boolean;\n\tabstract onDestroy(callback: () => void): () => void;\n\tabstract dispose(): void;\n\n\t[SYMBOL_DISPOSE](): void {\n\t\tthis.dispose();\n\t}\n}\n\nclass ManagedSecuritydeptDestroyRef extends SecuritydeptDestroyRef {\n\tprivate readonly destroyedSignal = createSignal(false);\n\n\tget destroyed(): boolean {\n\t\treturn this.destroyedSignal.get();\n\t}\n\n\tonDestroy(callback: () => void): () => void {\n\t\tif (this.destroyedSignal.get()) {\n\t\t\tcallback();\n\t\t\treturn () => undefined;\n\t\t}\n\n\t\tconst subscription = from(this.destroyedSignal)\n\t\t\t.pipe(\n\t\t\t\tfilter((destroyed): destroyed is true => destroyed),\n\t\t\t\ttake(1),\n\t\t\t)\n\t\t\t.subscribe({\n\t\t\t\tnext: callback,\n\t\t\t});\n\t\treturn () => {\n\t\t\tsubscription.unsubscribe();\n\t\t};\n\t}\n\n\tdispose(): void {\n\t\tif (this.destroyedSignal.get()) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.destroyedSignal.set(true);\n\t}\n\n\tdestroy(): void {\n\t\tthis.dispose();\n\t}\n}\n\nexport function createSecuritydeptDestroyRef(): SecuritydeptDestroyRef {\n\treturn new ManagedSecuritydeptDestroyRef();\n}\n","import { type as defineType } from \"arktype\";\nimport {\n\tUriReferenceString,\n\tUriRelativeString,\n\tUriString,\n} from \"../../struct/uri-string\";\n\nexport const UriStringSchema = defineType(\"string\").narrow((value, context) =>\n\tUriString.tryParse(value) == null\n\t\t? context.reject(\"an absolute URI string\")\n\t\t: true,\n);\n\nexport const BaseURIStringSchema = UriStringSchema;\n\nexport const UriRelativeStringSchema = defineType(\"string\").narrow(\n\t(value, context) =>\n\t\tUriRelativeString.tryParse(value) == null\n\t\t\t? context.reject(\"a relative URI reference string\")\n\t\t\t: true,\n);\n\nexport const UriReferenceStringSchema = defineType(\"string\").narrow(\n\t(value, context) =>\n\t\tUriReferenceString.tryParse(value) == null\n\t\t\t? context.reject(\"a URI reference string\")\n\t\t\t: true,\n);\n","import { merge, ReplaySubject, take, takeUntil } from \"rxjs\";\nimport {\n\ttype DisposableTrait,\n\ttype SubscribableTrait,\n\tSYMBOL_DISPOSE,\n\tSYMBOL_OBSERVABLE,\n} from \"../compat\";\nimport { type ClientError } from \"../errors\";\nimport { CancellationToken } from \"./create\";\nimport {\n\ttype CancellationTokenErrorData,\n\ttype CancellationTokenTrait,\n} from \"./types\";\n\nexport class LinkedCancellationToken\n\timplements CancellationTokenTrait, DisposableTrait\n{\n\tdestoryed$ = new ReplaySubject<boolean>(1);\n\tprotected readonly token: CancellationTokenTrait;\n\n\tconstructor(protected readonly sources: CancellationTokenTrait[]) {\n\t\tif (sources.length === 0) {\n\t\t\tthis.token = new CancellationToken();\n\t\t}\n\n\t\t// One source — return directly; no allocation needed.\n\t\tif (sources.length === 1) {\n\t\t\tthis.token = sources[0];\n\t\t}\n\n\t\t// Fast-path: return the first already-cancelled source immediately.\n\t\tfor (const source of sources) {\n\t\t\tif (source.isCancellationRequested) {\n\t\t\t\tthis.token = source;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst newToken = new CancellationToken();\n\n\t\tmerge(...sources)\n\t\t\t.pipe(take(1), takeUntil(this.destoryed$))\n\t\t\t.subscribe(({ reason }) => {\n\t\t\t\tnewToken._cancel(reason);\n\t\t\t});\n\n\t\tthis.token = newToken;\n\t}\n\tget isCancellationRequested(): boolean {\n\t\treturn this.token.isCancellationRequested;\n\t}\n\tget cancellationError(): ClientError | undefined {\n\t\treturn this.token.cancellationError;\n\t}\n\tget reason(): unknown {\n\t\treturn this.token.reason;\n\t}\n\tonCancellationRequested(\n\t\tlistener: (data: CancellationTokenErrorData) => void,\n\t): DisposableTrait {\n\t\treturn this.token.onCancellationRequested(listener);\n\t}\n\tthrowIfCancellationRequested(): void {\n\t\tthis.token.throwIfCancellationRequested();\n\t}\n\n\tdispose() {\n\t\tthis.destoryed$.next(true);\n\t}\n\n\t[SYMBOL_DISPOSE]() {\n\t\tthis.dispose();\n\t}\n\n\t[SYMBOL_OBSERVABLE](): SubscribableTrait<CancellationTokenErrorData> {\n\t\treturn this.token[SYMBOL_OBSERVABLE]();\n\t}\n}\n\n/**\n * Create a cancellation token that fires when ANY of the given source tokens\n * is cancelled.\n *\n * - Zero sources → returns a token that is never cancelled.\n * - One source → returns that source directly (no allocation).\n * - N sources → creates a linked source, subscribes to all, and cleans up\n * subscriptions once the linked token fires.\n *\n * @example\n * const cts = createCancellationTokenSource();\n * const linked = createLinkedCancellationToken(clientRoot.token, cts.token);\n * await transport.execute({ ..., cancellationToken: linked });\n */\nexport function createLinkedCancellationToken(\n\t...sources: readonly (CancellationTokenTrait | undefined | null)[]\n): CancellationTokenTrait & DisposableTrait {\n\treturn new LinkedCancellationToken(\n\t\tsources.filter((s): s is CancellationTokenTrait => !!s),\n\t);\n}\n","import { RxComputedSignal } from \"../rx/signal\";\nimport { type ComputedSignalTrait, type SignalOptions } from \"./types\";\n\n/**\n * Create a lazy computed signal.\n *\n * Dependencies are collected dynamically while `compute()` runs.\n */\nexport function createComputed<T>(\n\tcompute: () => T,\n\toptions?: SignalOptions<T>,\n): ComputedSignalTrait<T> {\n\treturn RxComputedSignal.computed(compute, options);\n}\n","import { from } from \"rxjs\";\nimport { type ToEventStreamInput } from \"../events/interop\";\nimport { mapResource, resourceFromSnapshots, rxResource } from \"../rx/resource\";\nimport {\n\ttype ReadableSignalTrait,\n\ttype ResourceSnapshot,\n\ttype ResourceTrait,\n} from \"./types\";\n\nexport interface ResourceStreamContext<T, R> {\n\treadonly request: R;\n\treadonly previous: ResourceSnapshot<T>;\n}\n\nexport interface CreateResourceOptions<T, R = undefined> {\n\treadonly request?: ReadableSignalTrait<R | undefined> | (() => R | undefined);\n\treadonly stream: (\n\t\tcontext: ResourceStreamContext<T, R>,\n\t) => ToEventStreamInput<T>;\n}\n\nexport function createResource<T, R = undefined>(\n\toptions: CreateResourceOptions<T, R>,\n): ResourceTrait<T> {\n\treturn rxResource({\n\t\t...options,\n\t\tstream: (context) => from(options.stream(context)),\n\t});\n}\n\nexport { mapResource, resourceFromSnapshots };\n","// Router metadata — framework-agnostic route security declaration storage\n//\n// Canonical public export: @securitydept/client\n//\n// Serializable auth requirement metadata for router integrations is stored\n// under a single namespaced key in each framework's route-data bag (Angular\n// `Route.data`, TanStack `staticData`, etc.). Adopters should read/write only\n// through {@link readSecuritydeptRouteMetadata} and\n// {@link writeSecuritydeptRouteMetadata}.\n\nimport {\n\ttype AuthRequirement,\n\ttype RequirementsComposition,\n} from \"../auth-coordination/contract\";\n\n/** Route-data key holding the SecurityDept metadata blob for a segment. */\nexport const SECURITYDEPT_ROUTE_METADATA_KEY = \"__securitydept__\";\n\n/** Serializable SecurityDept route metadata. */\nexport interface SecuritydeptRouteMetadata<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n> {\n\trequirements?: readonly TAuthRequirement[];\n\tcomposition?: RequirementsComposition;\n}\n\n/** Read SecurityDept route metadata from a route `data` bag. */\nexport function readSecuritydeptRouteMetadata<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n>(\n\tdata: object | undefined,\n): SecuritydeptRouteMetadata<TAuthRequirement> | undefined {\n\tconst raw = (data as Record<string, unknown> | undefined)?.[\n\t\tSECURITYDEPT_ROUTE_METADATA_KEY\n\t];\n\tif (raw === undefined || raw === null) {\n\t\treturn undefined;\n\t}\n\treturn raw as SecuritydeptRouteMetadata<TAuthRequirement>;\n}\n\n/** Merge SecurityDept route metadata into a route `data` bag. */\nexport function writeSecuritydeptRouteMetadata<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n>(\n\tbase: object | undefined,\n\tpatch: SecuritydeptRouteMetadata<TAuthRequirement>,\n): Record<string, unknown> {\n\tconst data: Record<string, unknown> = { ...(base ?? {}) };\n\tconst previous =\n\t\t(data[SECURITYDEPT_ROUTE_METADATA_KEY] as\n\t\t\t| SecuritydeptRouteMetadata<TAuthRequirement>\n\t\t\t| undefined) ?? {};\n\tdata[SECURITYDEPT_ROUTE_METADATA_KEY] = { ...previous, ...patch };\n\treturn data;\n}\n","import { type ReadableSignalTrait, type ResourceTrait } from \"../../signals\";\n\nexport type AuthorizationSignal =\n\t| ReadableSignalTrait<string | null | undefined>\n\t| ResourceTrait<string | null | undefined>;\n\nexport type AuthorizationInterceptedFetchPredicate = (\n\tinput: RequestInfo | URL,\n\tinit: RequestInit | undefined,\n) => boolean | Promise<boolean>;\n\nexport interface CreateAuthorizationInterceptedFetchOptions {\n\treadonly predicate: AuthorizationInterceptedFetchPredicate;\n\treadonly authorization: AuthorizationSignal;\n}\n\nexport function createAuthorizationInterceptedFetch(\n\tfetchImpl: typeof fetch,\n\toptions: CreateAuthorizationInterceptedFetchOptions,\n): typeof fetch {\n\treturn async (input, init) => {\n\t\tif (!(await options.predicate(input, init))) {\n\t\t\treturn fetchImpl(input, init);\n\t\t}\n\t\tconst authorization =\n\t\t\t\"whenValue\" in options.authorization\n\t\t\t\t? await options.authorization.whenValue()\n\t\t\t\t: options.authorization.get();\n\t\tif (!authorization) {\n\t\t\treturn fetchImpl(input, init);\n\t\t}\n\t\tconst headers = new Headers(\n\t\t\ttypeof Request !== \"undefined\" && input instanceof Request\n\t\t\t\t? input.headers\n\t\t\t\t: undefined,\n\t\t);\n\t\tif (init?.headers) {\n\t\t\tnew Headers(init.headers).forEach((value, key) => {\n\t\t\t\theaders.set(key, value);\n\t\t\t});\n\t\t}\n\t\theaders.set(\"authorization\", authorization);\n\t\treturn fetchImpl(input, {\n\t\t\t...init,\n\t\t\theaders,\n\t\t});\n\t};\n}\n","import { isPromise } from \"es-toolkit/predicate\";\n\nimport { describeError } from \"../errors\";\nimport { type TimestampProviderTrait } from \"../scheduling/types\";\nimport {\n\ttype MutableSpanCreateOptions,\n\ttype MutableSpanTrait,\n\ttype OperationSpanTrait,\n\ttype SpanCreateOptions,\n\ttype SpanTrait,\n} from \"../span/types\";\nimport {\n\tOperationTraceEventType,\n\tTracingLevel,\n\ttype TracingTrait,\n} from \"./types\";\n\nexport interface RunOperationEnvironment {\n\tenvironment: {\n\t\ttime: TimestampProviderTrait;\n\t\ttracing: TracingTrait;\n\t};\n}\nexport interface RunOperationOptionsBase extends RunOperationEnvironment {\n\tspan: SpanTrait;\n\tname: string;\n\ttarget: string;\n\tfields?: Record<string, unknown>;\n\tidFactory?: () => string;\n\tnormalizeError?: (error: unknown) => unknown;\n}\n\nexport interface RunOperationOptions<T> extends RunOperationOptionsBase {\n\texecute: (span: OperationSpanTrait) => T;\n}\n\nexport class OperationSpan implements OperationSpanTrait {\n\tprivate constructor(\n\t\tprivate readonly _span: MutableSpanTrait,\n\t\tprivate readonly _environment: RunOperationEnvironment[\"environment\"],\n\t\tprivate readonly _name: string,\n\t\tprivate readonly _target: string,\n\t) {}\n\n\tstatic start(options: RunOperationOptionsBase): OperationSpan {\n\t\tconst operationSpan = new OperationSpan(\n\t\t\toptions.span.fork({\n\t\t\t\tmutable: true,\n\t\t\t\tidFactory: options.idFactory,\n\t\t\t\tattributes: options.fields,\n\t\t\t}),\n\t\t\toptions.environment,\n\t\t\toptions.name,\n\t\t\toptions.target,\n\t\t);\n\t\toperationSpan.recordStarted();\n\t\treturn operationSpan;\n\t}\n\n\tget id(): string {\n\t\treturn this._span.id;\n\t}\n\n\tget parent(): SpanTrait | undefined {\n\t\treturn this._span.parent;\n\t}\n\n\tget attributes(): Readonly<Record<string, unknown>> {\n\t\treturn this._span.attributes;\n\t}\n\n\tfork(options: MutableSpanCreateOptions): MutableSpanTrait;\n\tfork(options?: SpanCreateOptions): SpanTrait;\n\tfork(\n\t\toptions: SpanCreateOptions | MutableSpanCreateOptions = {},\n\t): SpanTrait | MutableSpanTrait {\n\t\treturn this._span.fork(options);\n\t}\n\n\tsetAttributes(attributes: Record<string, unknown>): void {\n\t\tthis._span.setAttributes(attributes);\n\t}\n\n\taddEvent(name: string, fields?: Record<string, unknown>): void {\n\t\tthis._record(OperationTraceEventType.Event, TracingLevel.Info, {\n\t\t\teventName: name,\n\t\t\t...(fields ?? {}),\n\t\t});\n\t}\n\n\trecordError(error: unknown, fields?: Record<string, unknown>): void {\n\t\tthis._record(OperationTraceEventType.Error, TracingLevel.Error, {\n\t\t\t...describeError(error),\n\t\t\t...(fields ?? {}),\n\t\t});\n\t}\n\n\trecordStarted(): void {\n\t\tthis._record(OperationTraceEventType.Started, TracingLevel.Info);\n\t}\n\n\trecordEnded(outcome: \"succeeded\" | \"failed\"): void {\n\t\tthis._record(\n\t\t\tOperationTraceEventType.Ended,\n\t\t\toutcome === \"succeeded\" ? TracingLevel.Info : TracingLevel.Error,\n\t\t\t{ outcome },\n\t\t);\n\t}\n\n\tprivate _record(\n\t\tname: string,\n\t\tlevel: TracingLevel,\n\t\tfields?: Record<string, unknown>,\n\t): void {\n\t\tthis._environment.tracing.record({\n\t\t\tname,\n\t\t\tat: this._environment.time.now(),\n\t\t\tspan: this,\n\t\t\tlevel,\n\t\t\ttarget: this._target,\n\t\t\tfields: {\n\t\t\t\toperationName: this._name,\n\t\t\t\t...this.attributes,\n\t\t\t\t...(fields ?? {}),\n\t\t\t},\n\t\t});\n\t}\n}\n\nexport function runOperation<T>(options: RunOperationOptions<T>): T;\nexport function runOperation<T>(\n\toptions: RunOperationOptions<Promise<T>>,\n): Promise<T>;\nexport function runOperation<T>(\n\toptions: RunOperationOptions<T | Promise<T>>,\n): T | Promise<T> {\n\tconst operationSpan = OperationSpan.start(options);\n\tconst complete = (result: T): T => {\n\t\toperationSpan.recordEnded(\"succeeded\");\n\t\treturn result;\n\t};\n\tconst fail = (error: unknown): never => {\n\t\tconst normalizedError = options.normalizeError?.(error) ?? error;\n\t\toperationSpan.recordError(normalizedError);\n\t\toperationSpan.recordEnded(\"failed\");\n\t\tthrow normalizedError;\n\t};\n\n\tconst invoke = () => options.execute(operationSpan);\n\ttry {\n\t\tconst result = invoke();\n\t\tif (isPromise(result)) {\n\t\t\treturn result.then(complete, fail);\n\t\t}\n\t\treturn complete(result);\n\t} catch (error) {\n\t\treturn fail(error);\n\t}\n}\n","import { type OperationSpanTrait } from \"../span/types\";\nimport { type RunOperationOptionsBase, runOperation } from \"./operation-runner\";\n\nexport interface InstrumentMethodThisContext<TArgs extends unknown[]> {\n\targs: TArgs;\n\tmethodName: string;\n}\n\nexport interface InstrumentMethodResolvedOptions\n\textends Omit<RunOperationOptionsBase, \"name\"> {\n\tname?: string;\n}\n\nexport type InstrumentMethodThisResolver<\n\tTThis extends object,\n\tTArgs extends unknown[],\n> = (\n\tthis: TThis,\n\tcontext: InstrumentMethodThisContext<TArgs>,\n) => InstrumentMethodResolvedOptions;\n\nexport interface DefineInstrumentMethodDecoratorContext<\n\tTFactoryArgs extends unknown[],\n> {\n\tfactoryArgs: TFactoryArgs;\n\tmethodName: string;\n}\n\nexport type DefineInstrumentMethodDecoratorFactory<\n\tTFactoryArgs extends unknown[],\n\tTBaseThis extends object = object,\n> = <TThis extends TBaseThis, TArgs extends unknown[]>(\n\tcontext: DefineInstrumentMethodDecoratorContext<TFactoryArgs>,\n) => InstrumentMethodThisResolver<TThis, TArgs>;\n\nexport function defineInstrumentMethodDecorator<\n\tTFactoryArgs extends unknown[],\n\tTBaseThis extends object = object,\n>(factory: DefineInstrumentMethodDecoratorFactory<TFactoryArgs, TBaseThis>) {\n\treturn (...factoryArgs: TFactoryArgs) =>\n\t\t<TThis extends TBaseThis, TArgs extends unknown[], TReturn>(\n\t\t\ttarget: (this: TThis, ...args: TArgs) => TReturn,\n\t\t\tcontext: ClassMethodDecoratorContext<\n\t\t\t\tTThis,\n\t\t\t\t(this: TThis, ...args: TArgs) => TReturn\n\t\t\t>,\n\t\t) => {\n\t\t\tconst methodName = String(context.name);\n\t\t\tconst resolve = factory<TThis, TArgs>({\n\t\t\t\tfactoryArgs,\n\t\t\t\tmethodName,\n\t\t\t});\n\t\t\treturn function (this: TThis, ...args: TArgs): TReturn {\n\t\t\t\tconst resolvedOptions = resolve.call(this, {\n\t\t\t\t\targs,\n\t\t\t\t\tmethodName,\n\t\t\t\t});\n\t\t\t\treturn runOperation({\n\t\t\t\t\tenvironment: resolvedOptions.environment,\n\t\t\t\t\tspan: resolvedOptions.span,\n\t\t\t\t\tname: resolvedOptions.name ?? methodName,\n\t\t\t\t\ttarget: resolvedOptions.target,\n\t\t\t\t\tfields: resolvedOptions.fields,\n\t\t\t\t\tidFactory: resolvedOptions.idFactory,\n\t\t\t\t\tnormalizeError: resolvedOptions.normalizeError,\n\t\t\t\t\texecute: (span) =>\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\ttarget as unknown as (\n\t\t\t\t\t\t\t\tthis: TThis,\n\t\t\t\t\t\t\t\t...args: [...TArgs, OperationSpanTrait]\n\t\t\t\t\t\t\t) => TReturn\n\t\t\t\t\t\t).call(this, ...args, span),\n\t\t\t\t}) as TReturn;\n\t\t\t};\n\t\t};\n}\n","import { type TracingSubscriberTrait } from \"./types\";\n\nexport function createConsoleTracingSubscriber(): TracingSubscriberTrait {\n\treturn {\n\t\trecord(event) {\n\t\t\tconst label = `[${event.target}] ${event.name}`;\n\t\t\tswitch (event.level) {\n\t\t\t\tcase \"debug\":\n\t\t\t\t\tconsole.debug(label, event.fields ?? {});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"info\":\n\t\t\t\t\tconsole.info(label, event.fields ?? {});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"warn\":\n\t\t\t\t\tconsole.warn(label, event.fields ?? {});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"error\":\n\t\t\t\t\tconsole.error(label, event.fields ?? {});\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t};\n}\n","import { type TracingEvent } from \"../types\";\nimport { type TracingSubscriberTrait } from \"./types\";\n\nexport interface TraceTimelineEntry extends TracingEvent {\n\tid: number;\n\trecordedAtIso: string;\n}\n\nexport interface TraceTimelineStore extends TracingSubscriberTrait {\n\tget(): readonly TraceTimelineEntry[];\n\tsubscribe(listener: () => void): () => void;\n\tclear(): void;\n}\n\n/**\n * Create a subscriber-side trace timeline store.\n *\n * This store consumes tracing events through `record(event)` and keeps a\n * bounded local timeline for tests and UI surfaces. It is not the tracing\n * runtime itself.\n */\nexport function createTraceTimelineStore(limit = 200): TraceTimelineStore {\n\tlet nextId = 1;\n\tlet entries: TraceTimelineEntry[] = [];\n\tconst listeners = new Set<() => void>();\n\n\tfunction readRecordedAtIso(at: number): string {\n\t\tif (!Number.isFinite(at)) {\n\t\t\treturn \"invalid-timestamp\";\n\t\t}\n\n\t\tconst date = new Date(at);\n\t\tconst timestamp = date.getTime();\n\t\tif (!Number.isFinite(timestamp)) {\n\t\t\treturn \"invalid-timestamp\";\n\t\t}\n\n\t\treturn date.toISOString();\n\t}\n\n\tfunction notify() {\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n\n\treturn {\n\t\trecord(event) {\n\t\t\tconst entry: TraceTimelineEntry = {\n\t\t\t\t...event,\n\t\t\t\tid: nextId++,\n\t\t\t\trecordedAtIso: readRecordedAtIso(event.at),\n\t\t\t};\n\t\t\tentries = [...entries, entry].slice(-limit);\n\t\t\tnotify();\n\t\t},\n\t\tget() {\n\t\t\treturn entries;\n\t\t},\n\t\tsubscribe(listener) {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tclear() {\n\t\t\tif (entries.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tentries = [];\n\t\t\tnotify();\n\t\t},\n\t};\n}\n","// Requirement planner host — non-serializable behaviour resolution\n//\n// Canonical public export: @securitydept/client\n//\n// A RequirementPlannerHost carries the runtime, typically non-serializable\n// behaviour for a coordination scope: how to check whether a requirement is\n// satisfied, how to react when it is not, and how to pick the next candidate\n// to act on.\n//\n// Hosts form a parent chain. A leaf host (e.g. a route scope) resolves each\n// behaviour by walking from itself toward the root and using the nearest\n// definition. This mirrors hierarchical route/DI scoping without depending on\n// any framework. Adapters map their DI containers onto this chain.\n//\n// Future global, behavioural (usually non-serializable) information can be\n// carried here as additional fields without touching the serializable\n// contract layer.\n\nimport { ENVIRONMENT_TOKEN, type FoundationEnvironment } from \"../environment\";\nimport {\n\tPARENT_INJECTOR_TOKEN,\n\tSecurityDeptOptional,\n\tSecuritydeptInjectionToken,\n\ttype SecuritydeptInjectorTrait,\n\ttype SecuritydeptProvider,\n} from \"../injection\";\nimport {\n\ttype AuthRequirement,\n\ttype RequirementBehaviour,\n\ttype RequirementCandidateSelectionContext,\n\ttype SelectCandidate,\n} from \"./contract\";\n\nexport const REQUIREMENT_PLANNER_HOST = new SecuritydeptInjectionToken<\n\tRequirementPlannerHost<unknown>\n>(\"REQUIREMENT_PLANNER_HOST\");\n\nexport type RequirementPlannerHostBehaviour<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviour<TAuthRequirement, TPlanContext>\n\t> = Partial<RequirementBehaviour<TAuthRequirement, TPlanContext>>,\n> = TBehaviour | (() => TBehaviour);\n\nexport interface ProvideRequirementPlannerHostOptions<\n\tTBehaviour = Partial<RequirementBehaviour>,\n> {\n\treadonly parent?: RequirementPlannerHost<TBehaviour>;\n\treadonly environment?: FoundationEnvironment;\n}\n\nexport interface InjectRequirementPlannerHostOptions {\n\treadonly injector: SecuritydeptInjectorTrait;\n}\n\n/**\n * Default candidate selector: first unauthenticated candidate as soon as it is\n * discovered.\n *\n * If every requirement is already fulfilled the stream completes and the\n * selector returns `undefined`.\n */\nexport function defaultSelectCandidate<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n>(): SelectCandidate<TAuthRequirement, TPlanContext> {\n\treturn async function selectFirstCandidate(\n\t\tcontext: RequirementCandidateSelectionContext<\n\t\t\tTAuthRequirement,\n\t\t\tTPlanContext\n\t\t>,\n\t): Promise<TAuthRequirement | undefined> {\n\t\tconst result = await context.candidateList.next();\n\t\treturn result.done ? undefined : result.value;\n\t};\n}\n\n/** Options for {@link RequirementPlannerHost.fromBehaviour}. */\nexport interface RequirementPlannerHostOptions<\n\tTRequirementBehaviour = Partial<RequirementBehaviour>,\n> {\n\t/** Parent host to inherit unspecified behaviour from. */\n\tparent?: RequirementPlannerHost<TRequirementBehaviour>;\n\tenvironment?: FoundationEnvironment;\n}\n\n/**\n * A coordination-scope host that resolves behaviour through a parent chain.\n *\n * Construct via {@link RequirementPlannerHost.fromBehaviour}. Each behaviour\n * field is optional at host construction time; missing required behaviour is\n * resolved from `parent` and fails fast during planner build if no host in the\n * chain provides it.\n *\n * @example\n * ```ts\n * const root = RequirementPlannerHost.fromBehaviour({\n * checkAuthenticated: (req) => isAuthenticated(req),\n * onUnauthenticated: (req) => `/login/${req.id}`,\n * });\n *\n * // Feature scope overrides only the chooser, inheriting the rest.\n * const feature = RequirementPlannerHost.fromBehaviour(\n * { selectCandidate: async (ctx) => showChooser(ctx.candidateList) },\n * { parent: root },\n * );\n * ```\n */\nexport class RequirementPlannerHost<\n\tTBehaviour = Partial<RequirementBehaviour>,\n> {\n\t/** The parent host, or undefined at the root. */\n\tprivate readonly _behaviour: TBehaviour;\n\n\tprotected constructor(\n\t\tbehaviour: TBehaviour,\n\t\treadonly environment: FoundationEnvironment | undefined,\n\t\treadonly parent: RequirementPlannerHost<TBehaviour> | undefined,\n\t) {\n\t\tthis._behaviour = behaviour;\n\t}\n\n\t/** Create a host scope from a partial behaviour and optional parent. */\n\tstatic fromBehaviour<TBehaviour = Partial<RequirementBehaviour>>(\n\t\tbehaviour: TBehaviour,\n\t\toptions: RequirementPlannerHostOptions<TBehaviour> = {},\n\t): RequirementPlannerHost<TBehaviour> {\n\t\treturn new RequirementPlannerHost(\n\t\t\tbehaviour,\n\t\t\toptions.environment,\n\t\t\toptions.parent,\n\t\t);\n\t}\n\n\tasync resolveBehaviourOptionFor<K extends keyof TBehaviour>(\n\t\tkey: K,\n\t): Promise<TBehaviour[K] | undefined> {\n\t\treturn (\n\t\t\tthis._behaviour[key] ??\n\t\t\t(await this.parent?.resolveBehaviourOptionFor(key))\n\t\t);\n\t}\n\tasync resolveBehaviourFor<K extends keyof TBehaviour>(\n\t\tkey: K,\n\t\tdefaultValue: () =>\n\t\t\t| NonNullable<TBehaviour[K]>\n\t\t\t| Promise<NonNullable<TBehaviour[K]>>,\n\t): Promise<NonNullable<TBehaviour[K]>> {\n\t\treturn (\n\t\t\t(await this.resolveBehaviourOptionFor(key)) ?? (await defaultValue())\n\t\t);\n\t}\n\n\tasync resolveEnvironmentOption(): Promise<FoundationEnvironment | undefined> {\n\t\treturn this.environment ?? (await this.parent?.resolveEnvironmentOption());\n\t}\n\n\tasync resolveEnvironment(\n\t\tdefaultValue: () => FoundationEnvironment | Promise<FoundationEnvironment>,\n\t): Promise<FoundationEnvironment> {\n\t\treturn (await this.resolveEnvironmentOption()) ?? (await defaultValue());\n\t}\n}\n\nexport function provideRequirementPlannerHost<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviour<TAuthRequirement, TPlanContext>\n\t> = Partial<RequirementBehaviour<TAuthRequirement, TPlanContext>>,\n>(\n\tbehaviour: RequirementPlannerHostBehaviour<\n\t\tTAuthRequirement,\n\t\tTPlanContext,\n\t\tTBehaviour\n\t>,\n\toptions: ProvideRequirementPlannerHostOptions<TBehaviour> = {},\n): SecuritydeptProvider<RequirementPlannerHost<TBehaviour>> {\n\treturn {\n\t\tprovide: REQUIREMENT_PLANNER_HOST,\n\t\tuseFactory: (\n\t\t\tparentInjector: SecuritydeptInjectorTrait | null,\n\t\t\tenvironment: FoundationEnvironment | null,\n\t\t) => {\n\t\t\tconst parent =\n\t\t\t\toptions.parent ??\n\t\t\t\t(parentInjector?.get(\n\t\t\t\t\tREQUIREMENT_PLANNER_HOST,\n\t\t\t\t\tnull,\n\t\t\t\t) as RequirementPlannerHost<TBehaviour> | null) ??\n\t\t\t\tundefined;\n\t\t\tconst resolved =\n\t\t\t\ttypeof behaviour === \"function\" ? behaviour() : behaviour;\n\t\t\treturn RequirementPlannerHost.fromBehaviour(resolved, {\n\t\t\t\tparent,\n\t\t\t\tenvironment: options.environment ?? environment ?? undefined,\n\t\t\t});\n\t\t},\n\t\tdeps: [\n\t\t\t[new SecurityDeptOptional(), PARENT_INJECTOR_TOKEN],\n\t\t\t[new SecurityDeptOptional(), ENVIRONMENT_TOKEN],\n\t\t],\n\t};\n}\n\nexport function injectRequirementPlannerHost<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviour<TAuthRequirement, TPlanContext>\n\t> = Partial<RequirementBehaviour<TAuthRequirement, TPlanContext>>,\n>(\n\toptions: InjectRequirementPlannerHostOptions,\n): RequirementPlannerHost<TBehaviour> | null {\n\treturn options.injector.get(\n\t\tREQUIREMENT_PLANNER_HOST,\n\t\tnull,\n\t) as RequirementPlannerHost<TBehaviour> | null;\n}\n","// Base requirement planner — pipeline owner\n//\n// Canonical public export: @securitydept/client\n//\n// Pipeline:\n// 0. buildPlan() — resolve host behaviour + materialize requirements into a\n// RequirementPlan (fixed for this run until the next buildPlan)\n// 1. runStep(plan) — race checkAuthenticated, select the first actionable\n// unauthenticated candidate, then onUnauthenticated\n// 2. reduce — update plan.resolutionList\n//\n// runUntilSettled() calls buildPlan() then runUntilSettledWithPlan(plan).\n\nimport { promisesToRacedAsyncGenerator } from \"../../compat\";\nimport { type FoundationEnvironment } from \"../../environment\";\nimport {\n\ttype AuthRequirement,\n\tPipelineOutcome,\n\ttype PipelineRunResult,\n\ttype PipelineStepResult,\n\ttype RequirementBehaviour,\n\ttype RequirementCandidateGenerator,\n\tRequirementPlannerError,\n\ttype RequirementResolution,\n\tResolutionStatus,\n\ttype UnauthenticatedAction,\n} from \"../contract\";\nimport {\n\tdefaultSelectCandidate,\n\ttype RequirementPlannerHost,\n} from \"../planner-host\";\n\n/**\n * Mutable pipeline state for one run: bound behaviour plus requirement list\n * and evolving resolutions.\n */\nexport interface RequirementPlan<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n> extends Readonly<RequirementBehaviour<TAuthRequirement, TPlanContext>> {\n\treadonly planContext: TPlanContext;\n\treadonly environment: FoundationEnvironment;\n\treadonly requirements: readonly TAuthRequirement[];\n\tresolutionList: RequirementResolution[];\n}\n\ninterface RequirementCheckResult<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n> {\n\treadonly requirement: TAuthRequirement;\n\treadonly satisfied: boolean;\n}\n\n/**\n * Abstract base for all requirement planners.\n *\n * Subclasses supply requirements via {@link buildRequirementList}. Pipeline\n * state lives on {@link RequirementPlan}, produced by {@link buildPlan}.\n */\nexport abstract class BaseRequirementPlanner<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviour<TAuthRequirement, TPlanContext>\n\t> = Partial<RequirementBehaviour<TAuthRequirement, TPlanContext>>,\n> {\n\tprotected readonly host: RequirementPlannerHost<TBehaviour>;\n\tprotected initialResolutions: readonly RequirementResolution[];\n\n\tabstract get planContext(): TPlanContext;\n\n\tprotected constructor(\n\t\thost: RequirementPlannerHost<TBehaviour>,\n\t\tinitialResolutions: readonly RequirementResolution[] = [],\n\t) {\n\t\tthis.host = host;\n\t\tthis.initialResolutions = initialResolutions.map((resolution) =>\n\t\t\tObject.freeze({ ...resolution }),\n\t\t);\n\t}\n\n\t// --- Pipeline step 0 -----------------------------------------------------\n\n\t/**\n\t * Pipeline step 0: resolve host behaviour and materialize requirements into\n\t * a {@link RequirementPlan}.\n\t *\n\t * Behaviour and the requirement list stay fixed on the returned plan until\n\t * the next `buildPlan()` call. Resolve host parent chains (and any\n\t * injection-context capture) here — not between async steps.\n\t */\n\tpublic async buildPlan(): Promise<\n\t\tRequirementPlan<TAuthRequirement, TPlanContext>\n\t> {\n\t\treturn {\n\t\t\tplanContext: this.planContext,\n\t\t\tenvironment: await this.host.resolveEnvironment(() => {\n\t\t\t\tthrow new RequirementPlannerError(\"No environment resolved\");\n\t\t\t}),\n\t\t\tcheckAuthenticated: await this.host.resolveBehaviourFor(\n\t\t\t\t\"checkAuthenticated\",\n\t\t\t\t() => {\n\t\t\t\t\tthrow new RequirementPlannerError(\"No checkAuthenticated resolved\");\n\t\t\t\t},\n\t\t\t),\n\t\t\tonUnauthenticated: await this.host.resolveBehaviourFor(\n\t\t\t\t\"onUnauthenticated\",\n\t\t\t\t() => {\n\t\t\t\t\tthrow new RequirementPlannerError(\n\t\t\t\t\t\t\"No onUnauthenticated behaviour resolved\",\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t),\n\t\t\tselectCandidate: await this.host.resolveBehaviourFor(\n\t\t\t\t\"selectCandidate\",\n\t\t\t\tdefaultSelectCandidate<TAuthRequirement, TPlanContext>,\n\t\t\t),\n\t\t\trequirements: await this.resolveRequirementList(),\n\t\t\tresolutionList: [...this.initialResolutions],\n\t\t};\n\t}\n\n\t// --- Pipeline step 1 -----------------------------------------------------\n\n\t/**\n\t * Return the effective requirement map for this planner.\n\t *\n\t * Keys are requirement ids; {@link Map} insertion order defines evaluation\n\t * order. Subclasses own deduplication policy when folding multiple sources.\n\t */\n\tprotected abstract buildRequirementList():\n\t\t| Map<string, TAuthRequirement>\n\t\t| Promise<Map<string, TAuthRequirement>>;\n\n\t/**\n\t * Materialize the effective requirement list (also invoked by {@link buildPlan}).\n\t */\n\tpublic async resolveRequirementList(): Promise<readonly TAuthRequirement[]> {\n\t\tconst requirements = await this.buildRequirementList();\n\t\treturn [...requirements.values()];\n\t}\n\t/**\n\t * Pipeline step 1 — one loop iteration: select a candidate, run\n\t * `onUnauthenticated`, then reduce `plan` state.\n\t */\n\tasync runStep(\n\t\tplan: RequirementPlan<TAuthRequirement, TPlanContext>,\n\t): Promise<PipelineStepResult<TAuthRequirement>> {\n\t\tconst candidate = await plan.selectCandidate({\n\t\t\t...plan,\n\t\t\tcandidateList: this.createCandidateStream(plan),\n\t\t});\n\t\tif (!candidate) {\n\t\t\treturn { outcome: PipelineOutcome.Settled };\n\t\t}\n\t\tconst action = await plan.onUnauthenticated(candidate, plan);\n\n\t\treturn this.reduceFromAction(plan, candidate, action);\n\t}\n\n\tprotected reduceFromAction(\n\t\tplan: RequirementPlan<TAuthRequirement, TPlanContext>,\n\t\tcandidate: TAuthRequirement,\n\t\taction: Exclude<UnauthenticatedAction, Promise<unknown>>,\n\t): PipelineStepResult<TAuthRequirement> {\n\t\tif (action === true) {\n\t\t\tthis.recordFulfilled(plan, candidate);\n\t\t\treturn { outcome: PipelineOutcome.Resolved, requirement: candidate };\n\t\t}\n\t\tif (action === false) {\n\t\t\treturn { outcome: PipelineOutcome.Blocked, requirement: candidate };\n\t\t}\n\t\treturn {\n\t\t\toutcome: PipelineOutcome.Redirect,\n\t\t\trequirement: candidate,\n\t\t\tlocation: action,\n\t\t};\n\t}\n\n\t// --- Pipeline orchestration ---------------------------------------------\n\n\t/**\n\t * Run the full pipeline: {@link buildPlan}, step 1, then loop step 2 until\n\t * settled or a terminal outcome (`blocked`, `redirect`, or a never-settling\n\t * action).\n\t */\n\tasync runUntilSettled(): Promise<PipelineRunResult<TAuthRequirement>> {\n\t\tconst plan = await this.buildPlan();\n\t\treturn this.runUntilSettledWithPlan(plan);\n\t}\n\n\tasync runUntilSettledWithPlan(\n\t\tplan: RequirementPlan<TAuthRequirement, TPlanContext>,\n\t): Promise<PipelineRunResult<TAuthRequirement>> {\n\t\twhile (true) {\n\t\t\tconst step = await this.runStep(plan);\n\n\t\t\tif (step.outcome === PipelineOutcome.Settled) {\n\t\t\t\treturn {\n\t\t\t\t\toutcome: PipelineOutcome.Settled,\n\t\t\t\t\tresolutions: plan.resolutionList,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (step.outcome === PipelineOutcome.Resolved) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (step.outcome === PipelineOutcome.Blocked) {\n\t\t\t\treturn step;\n\t\t\t}\n\t\t\tif (step.outcome === PipelineOutcome.Redirect) {\n\t\t\t\treturn step;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async *createCandidateStream(\n\t\tplan: RequirementPlan<TAuthRequirement, TPlanContext>,\n\t): RequirementCandidateGenerator<TAuthRequirement> {\n\t\tconst context = {\n\t\t\tplanContext: this.planContext,\n\t\t\trequirements: plan.requirements,\n\t\t\tresolutionList: plan.resolutionList,\n\t\t\tenvironment: plan.environment,\n\t\t};\n\t\tconst checked = plan.requirements\n\t\t\t.filter(\n\t\t\t\t(requirement) =>\n\t\t\t\t\t!plan.resolutionList.some(\n\t\t\t\t\t\t(resolution) => resolution.requirementId === requirement.id,\n\t\t\t\t\t),\n\t\t\t)\n\t\t\t.map(\n\t\t\t\tasync (\n\t\t\t\t\trequirement,\n\t\t\t\t): Promise<RequirementCheckResult<TAuthRequirement>> => {\n\t\t\t\t\tconst satisfied = await plan.checkAuthenticated(requirement, context);\n\t\t\t\t\treturn { requirement, satisfied };\n\t\t\t\t},\n\t\t\t);\n\n\t\tfor await (const {\n\t\t\trequirement,\n\t\t\tsatisfied,\n\t\t} of promisesToRacedAsyncGenerator(checked)) {\n\t\t\tif (satisfied) {\n\t\t\t\tthis.recordFulfilled(plan, requirement);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tyield requirement;\n\t\t}\n\t}\n\n\tprivate recordFulfilled(\n\t\tplan: RequirementPlan<TAuthRequirement, TPlanContext>,\n\t\trequirement: TAuthRequirement,\n\t): void {\n\t\tif (\n\t\t\tplan.resolutionList.some(\n\t\t\t\t(resolution) => resolution.requirementId === requirement.id,\n\t\t\t)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tplan.resolutionList.push(\n\t\t\tObject.freeze({\n\t\t\t\trequirementId: requirement.id,\n\t\t\t\tstatus: ResolutionStatus.Fulfilled,\n\t\t\t}),\n\t\t);\n\t}\n}\n","// Merge requirement planner — concatenation of multiple planners\n//\n// Canonical public export: @securitydept/client\n//\n// Concatenates source planners in order. Overlapping ids follow Map semantics:\n// the later source wins for the same key.\n\nimport { type AuthRequirement, type RequirementBehaviour } from \"../contract\";\nimport { type RequirementPlannerHost } from \"../planner-host\";\nimport { BaseRequirementPlanner } from \"./base-planner\";\n\n/**\n * A planner whose effective requirements are the ordered union of its source\n * planners. Overlapping ids follow Map semantics (later source wins).\n *\n * @example\n * ```ts\n * const planner = MergeRequirementPlanner.fromPlanners(host, [\n * sessionPlanner,\n * oidcPlanner,\n * ]);\n * ```\n */\nexport class MergeRequirementPlanner<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTPlanContext = {},\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviour<TAuthRequirement, TPlanContext>\n\t> = Partial<RequirementBehaviour<TAuthRequirement, TPlanContext>>,\n> extends BaseRequirementPlanner<TAuthRequirement, TPlanContext, TBehaviour> {\n\tprivate readonly sources: readonly BaseRequirementPlanner<\n\t\tTAuthRequirement,\n\t\tTPlanContext,\n\t\tTBehaviour\n\t>[];\n\n\tget planContext(): TPlanContext {\n\t\treturn Object.assign(\n\t\t\t{},\n\t\t\t...this.sources.map((source) => source.planContext),\n\t\t);\n\t}\n\n\tprotected constructor(\n\t\thost: RequirementPlannerHost<TBehaviour>,\n\t\tsources: readonly BaseRequirementPlanner<\n\t\t\tTAuthRequirement,\n\t\t\tTPlanContext,\n\t\t\tTBehaviour\n\t\t>[],\n\t) {\n\t\tsuper(host);\n\t\tthis.sources = sources;\n\t}\n\n\t/** Create a merge planner from an ordered list of source planners. */\n\tstatic fromPlanners<\n\t\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\t\tTPlanContext = {},\n\t\tTBehaviour extends Partial<\n\t\t\tRequirementBehaviour<TAuthRequirement, TPlanContext>\n\t\t> = Partial<RequirementBehaviour<TAuthRequirement, TPlanContext>>,\n\t>(\n\t\thost: RequirementPlannerHost<TBehaviour>,\n\t\tplanners: readonly BaseRequirementPlanner<\n\t\t\tTAuthRequirement,\n\t\t\tTPlanContext,\n\t\t\tTBehaviour\n\t\t>[],\n\t): MergeRequirementPlanner<TAuthRequirement, TPlanContext, TBehaviour> {\n\t\treturn new MergeRequirementPlanner(host, planners);\n\t}\n\n\tprotected async buildRequirementList(): Promise<\n\t\tMap<string, TAuthRequirement>\n\t> {\n\t\tconst map = new Map<string, TAuthRequirement>();\n\t\tfor (const source of this.sources) {\n\t\t\tfor (const requirement of await source.resolveRequirementList()) {\n\t\t\t\tmap.set(requirement.id, requirement);\n\t\t\t}\n\t\t}\n\t\treturn map;\n\t}\n}\n","// Route composition requirement planner — matched route chain folding\n//\n// Canonical public export: @securitydept/client\n//\n// Folds a matched route chain (root -> leaf) into a single effective\n// requirement list, applying each segment's inherit/merge/replace composition.\n//\n// Route transitions are modeled as immutable construction: there is no in-place\n// reset. A fresh instance is produced from the previous one, preserving the\n// resolutions for the shared requirement prefix so cross-navigation progress is\n// not lost while diverging requirements are re-planned.\n\nimport {\n\ttype AuthRequirement,\n\ttype RequirementBehaviourWithRouteContext,\n\ttype RequirementResolution,\n\tRequirementsComposition,\n\ttype RouteBehaviourContextExtra,\n\ttype RouteStateSnapshotTrait,\n\ttype RouteTreeSegment,\n\tresolveEffectiveRequirements,\n} from \"../contract\";\nimport { type RequirementPlannerHost } from \"../planner-host\";\nimport { BaseRequirementPlanner, type RequirementPlan } from \"./base-planner\";\n\n/** Fold a matched route chain into its effective requirement list. */\nfunction foldSegments<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n>(\n\tsegments: readonly RouteTreeSegment<TAuthRequirement>[],\n): readonly TAuthRequirement[] {\n\tconst effective = new Map<string, TAuthRequirement>();\n\tfor (const segment of segments) {\n\t\tresolveEffectiveRequirements(\n\t\t\t{\n\t\t\t\tcomposition: segment.composition ?? RequirementsComposition.Merge,\n\t\t\t\trequirements: segment.requirements,\n\t\t\t},\n\t\t\teffective,\n\t\t);\n\t}\n\treturn [...effective.values()];\n}\n\n/** Length of the shared requirement-id prefix between two effective lists. */\nfunction sharedPrefixLength(\n\tprevious: readonly AuthRequirement[],\n\tnext: readonly AuthRequirement[],\n): number {\n\tconst limit = Math.min(previous.length, next.length);\n\tlet shared = 0;\n\twhile (shared < limit && previous[shared].id === next[shared].id) {\n\t\tshared += 1;\n\t}\n\treturn shared;\n}\n\n/**\n * A planner driven by a matched route chain with composition semantics.\n *\n * Construct via {@link fromRouteSegments} for a matched route chain, or\n * {@link fromRouteTransition} for a transition that preserves shared-prefix\n * resolutions from the previous planner instance.\n */\nexport class RouteCompositionRequirementPlanner<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<\n\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n> extends BaseRequirementPlanner<\n\tTAuthRequirement,\n\tRouteBehaviourContextExtra,\n\tTBehaviour\n> {\n\tprivate readonly _segments: readonly RouteTreeSegment<TAuthRequirement>[];\n\tprivate readonly _effective: readonly TAuthRequirement[];\n\tprivate readonly _planContext: RouteBehaviourContextExtra;\n\n\tprotected constructor(\n\t\thost: RequirementPlannerHost<TBehaviour>,\n\t\tsegments: readonly RouteTreeSegment<TAuthRequirement>[],\n\t\trouteState: RouteStateSnapshotTrait,\n\t\tpreservedResolutions: readonly RequirementResolution[] = [],\n\t) {\n\t\tsuper(host, preservedResolutions);\n\t\tthis._segments = segments;\n\t\tthis._effective = foldSegments(segments);\n\t\tthis._planContext = Object.freeze({\n\t\t\trouteState: Object.freeze({ ...routeState }),\n\t\t});\n\t}\n\n\t/** Build a planner from a matched route chain. */\n\tstatic fromRouteSegments<\n\t\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\t\tTBehaviour extends Partial<\n\t\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n\t>(\n\t\thost: RequirementPlannerHost<TBehaviour>,\n\t\tsegments: readonly RouteTreeSegment<TAuthRequirement>[],\n\t\trouteState: RouteStateSnapshotTrait,\n\t): RouteCompositionRequirementPlanner<TAuthRequirement, TBehaviour> {\n\t\treturn new RouteCompositionRequirementPlanner(host, segments, routeState);\n\t}\n\n\t/**\n\t * Build a planner for a route transition, preserving resolutions for the\n\t * shared requirement prefix carried over from `previousPlan`.\n\t */\n\tstatic fromRouteTransition<\n\t\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\t\tTBehaviour extends Partial<\n\t\t\tRequirementBehaviourWithRouteContext<TAuthRequirement>\n\t\t> = Partial<RequirementBehaviourWithRouteContext<TAuthRequirement>>,\n\t>(\n\t\thost: RequirementPlannerHost<TBehaviour>,\n\t\tcurrentSegments: readonly RouteTreeSegment<TAuthRequirement>[],\n\t\trouteState: RouteStateSnapshotTrait,\n\t\tpreviousPlanner: RouteCompositionRequirementPlanner<\n\t\t\tTAuthRequirement,\n\t\t\tTBehaviour\n\t\t>,\n\t\tpreviousPlan: RequirementPlan<TAuthRequirement, RouteBehaviourContextExtra>,\n\t): RouteCompositionRequirementPlanner<TAuthRequirement, TBehaviour> {\n\t\tconst nextEffective = foldSegments(currentSegments);\n\t\tconst shared = sharedPrefixLength(\n\t\t\tpreviousPlanner.effectiveRequirements,\n\t\t\tnextEffective,\n\t\t);\n\t\tconst sharedIds = new Set(\n\t\t\tnextEffective.slice(0, shared).map((requirement) => requirement.id),\n\t\t);\n\t\tconst preserved = previousPlan.resolutionList.filter((resolution) =>\n\t\t\tsharedIds.has(resolution.requirementId),\n\t\t);\n\t\treturn new RouteCompositionRequirementPlanner(\n\t\t\thost,\n\t\t\tcurrentSegments,\n\t\t\trouteState,\n\t\t\tpreserved,\n\t\t);\n\t}\n\n\tget planContext(): RouteBehaviourContextExtra {\n\t\treturn this._planContext;\n\t}\n\n\t/** The matched route chain backing this planner. */\n\tget segments(): readonly RouteTreeSegment<TAuthRequirement>[] {\n\t\treturn this._segments;\n\t}\n\n\t/** The folded effective requirement list (composition applied). */\n\tget effectiveRequirements(): readonly TAuthRequirement[] {\n\t\treturn this._effective;\n\t}\n\n\tprotected buildRequirementList(): Map<string, TAuthRequirement> {\n\t\treturn new Map(\n\t\t\tthis._effective.map((requirement) => [requirement.id, requirement]),\n\t\t);\n\t}\n}\n","// Static requirement planner — fixed requirement list\n//\n// Canonical public export: @securitydept/client\n\nimport { type AuthRequirement, type RequirementBehaviour } from \"../contract\";\nimport { type RequirementPlannerHost } from \"../planner-host\";\nimport { BaseRequirementPlanner } from \"./base-planner\";\n\n/**\n * A planner whose effective requirement list is a fixed array supplied at\n * construction time.\n *\n * @example\n * ```ts\n * const planner = StaticRequirementPlanner.fromRequirements(host, [\n * StaticAttrsAuthRequirement.create({ id: \"session\" }),\n * ] as Readonly<AuthRequirement[]>);\n * const plan = await planner.buildPlan();\n * const step = await planner.runStep(plan);\n * // or: const result = await planner.runUntilSettled();\n * ```\n */\nexport class StaticRequirementPlanner<\n\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\tTBehaviour extends Partial<RequirementBehaviour<TAuthRequirement>> = Partial<\n\t\tRequirementBehaviour<TAuthRequirement>\n\t>,\n> extends BaseRequirementPlanner<TAuthRequirement, {}, TBehaviour> {\n\tprivate readonly staticRequirements: readonly TAuthRequirement[];\n\n\tget planContext(): {} {\n\t\treturn {};\n\t}\n\n\tprotected constructor(\n\t\thost: RequirementPlannerHost<TBehaviour>,\n\t\trequirements: readonly TAuthRequirement[],\n\t) {\n\t\tsuper(host);\n\t\tthis.staticRequirements = requirements;\n\t}\n\n\t/** Create a static planner from an ordered requirement list. */\n\tstatic fromRequirements<\n\t\tTAuthRequirement extends AuthRequirement = AuthRequirement,\n\t\tTBehaviour extends Partial<\n\t\t\tRequirementBehaviour<TAuthRequirement>\n\t\t> = Partial<RequirementBehaviour<TAuthRequirement>>,\n\t>(\n\t\thost: RequirementPlannerHost<TBehaviour>,\n\t\trequirements: readonly TAuthRequirement[],\n\t): StaticRequirementPlanner<TAuthRequirement, TBehaviour> {\n\t\treturn new StaticRequirementPlanner(host, requirements);\n\t}\n\n\tprotected buildRequirementList(): Map<string, TAuthRequirement> {\n\t\tconst map = new Map<string, TAuthRequirement>();\n\t\tfor (const requirement of this.staticRequirements) {\n\t\t\tmap.set(requirement.id, requirement);\n\t\t}\n\t\treturn map;\n\t}\n}\n","import { EMPTY, NEVER } from \"rxjs\";\nimport {\n\tRxEventReplaySubject,\n\tRxEventStream,\n\tRxEventSubject,\n} from \"../rx/event\";\nimport {\n\ttype EventObserverTrait,\n\ttype EventStreamTrait,\n\ttype EventSubjectTrait,\n} from \"./types\";\n\n/**\n * Create a new event stream from a producer function.\n *\n * The producer receives an observer and should call `next()` to emit values,\n * `error()` to signal an error, and `complete()` to signal completion.\n * It may return a teardown function that will be called on unsubscribe.\n */\nexport function createEventStream<T>(\n\tproducer: (observer: EventObserverTrait<T>) => (() => void) | void,\n): EventStreamTrait<T> {\n\treturn new RxEventStream(producer);\n}\n\nexport function createEventSubject<T>(): EventSubjectTrait<T> {\n\treturn new RxEventSubject<T>();\n}\n\nexport function createEventReplaySubject<T>(\n\tbufferSize = Infinity,\n): EventSubjectTrait<T> {\n\treturn new RxEventReplaySubject<T>(bufferSize);\n}\n\nexport function createEmptyEventStream<T>(): EventStreamTrait<T> {\n\treturn RxEventStream.fromObservableInput(EMPTY);\n}\n\nexport function createNeverEventStream<T>(): EventStreamTrait<T> {\n\treturn RxEventStream.fromObservableInput(NEVER);\n}\n","import { from } from \"rxjs\";\nimport { type InteropObservableTrait } from \"../compat\";\nimport { RxEventStream } from \"../rx/event\";\nimport { type ReadableSignalTrait } from \"../signals/types\";\nimport { type EventStreamTrait, isEventStreamTrait } from \"./types\";\n\nexport type ToEventStreamInput<T> =\n\t| InteropObservableTrait<T>\n\t| Promise<T>\n\t| AsyncIterable<T>\n\t| PromiseLike<T>\n\t| ArrayLike<T>\n\t| Iterable<T>\n\t| EventStreamTrait<T>\n\t| ReadableSignalTrait<T>;\n\nexport function toEventStream<T>(\n\tinput: ToEventStreamInput<T>,\n): EventStreamTrait<T> {\n\tif (isEventStreamTrait(input)) {\n\t\treturn input;\n\t}\n\treturn RxEventStream.fromObservableInput(from(input));\n}\n","import { type as defineType } from \"arktype\";\nimport { type IdentityPrincipal } from \"./contracts\";\n\nexport const IdentityPrincipalSchema = defineType({\n\tsubject: \"string > 0\",\n\t\"displayName?\": \"string | null | undefined\",\n\t\"picture?\": \"string | null | undefined\",\n\t\"issuer?\": \"string | null | undefined\",\n\t\"claims?\": \"object | null | undefined\",\n}).pipe(\n\t(input): IdentityPrincipal => ({\n\t\tsubject: input.subject,\n\t\tdisplayName:\n\t\t\ttypeof input.displayName === \"string\" &&\n\t\t\tinput.displayName.trim().length > 0\n\t\t\t\t? input.displayName\n\t\t\t\t: input.subject,\n\t\tpicture: input.picture ?? undefined,\n\t\tissuer: input.issuer ?? undefined,\n\t\tclaims: (input.claims ?? undefined) as Record<string, unknown> | undefined,\n\t}),\n);\n\nexport const IdentityPrincipalWireSchema = defineType({\n\tsubject: \"string > 0\",\n\t\"display_name?\": \"string | null | undefined\",\n\t\"picture?\": \"string | null | undefined\",\n\t\"issuer?\": \"string | null | undefined\",\n\t\"claims?\": \"object | null | undefined\",\n}).pipe(\n\t(input): IdentityPrincipal => ({\n\t\tsubject: input.subject,\n\t\tdisplayName:\n\t\t\ttypeof input.display_name === \"string\" &&\n\t\t\tinput.display_name.trim().length > 0\n\t\t\t\t? input.display_name\n\t\t\t\t: input.subject,\n\t\tpicture: input.picture ?? undefined,\n\t\tissuer: input.issuer ?? undefined,\n\t\tclaims: (input.claims ?? undefined) as Record<string, unknown> | undefined,\n\t}),\n);\n","import { ClientError, ClientErrorKind } from \"../errors\";\nimport {\n\tformatValidationFailure,\n\ttype ValidationFailure,\n\tvalidateWithSchemaSync,\n} from \"../validation\";\nimport {\n\ttype IdentityPrincipal,\n\ttype ProjectIdentityPrincipalOptions,\n} from \"./contracts\";\nimport {\n\tIdentityPrincipalSchema,\n\tIdentityPrincipalWireSchema,\n} from \"./schemas\";\n\nfunction throwIdentityPrincipalParseError(options: {\n\tcode: string;\n\tmessagePrefix: string;\n\tfailure: ValidationFailure;\n}): never {\n\tthrow new ClientError({\n\t\tkind: ClientErrorKind.Protocol,\n\t\tcode: options.code,\n\t\tmessage: `${options.messagePrefix}: ${formatValidationFailure(options.failure) ?? \"schema validation failed\"}.`,\n\t\tsource: \"identity\",\n\t\tcause: options.failure.issues,\n\t});\n}\n\nexport function parseIdentityPrincipal(input: unknown): IdentityPrincipal {\n\tconst result = validateWithSchemaSync(IdentityPrincipalSchema, input);\n\tif (result.success) {\n\t\treturn result.value;\n\t}\n\tthrowIdentityPrincipalParseError({\n\t\tcode: \"identity.invalid_principal\",\n\t\tmessagePrefix: \"Identity principal payload is invalid\",\n\t\tfailure: result,\n\t});\n}\n\nexport function parseIdentityPrincipalWire(input: unknown): IdentityPrincipal {\n\tconst result = validateWithSchemaSync(IdentityPrincipalWireSchema, input);\n\tif (result.success) {\n\t\treturn result.value;\n\t}\n\tthrowIdentityPrincipalParseError({\n\t\tcode: \"identity.invalid_principal_wire\",\n\t\tmessagePrefix: \"Identity principal wire payload is invalid\",\n\t\tfailure: result,\n\t});\n}\n\nexport function projectIdentityPrincipal(\n\toptions: ProjectIdentityPrincipalOptions,\n): IdentityPrincipal {\n\tconst principal = options.principal;\n\tconst subject =\n\t\tprincipal?.subject ?? options.fallbackSubject ?? \"context.anonymous\";\n\tconst displayName =\n\t\tprincipal?.displayName?.trim() || options.fallbackDisplayName || subject;\n\n\treturn {\n\t\tsubject,\n\t\tdisplayName,\n\t\tpicture: principal?.picture,\n\t\tissuer: principal?.issuer ?? options.fallbackIssuer,\n\t\tclaims: principal?.claims ?? options.fallbackClaims,\n\t};\n}\n","import { ClientError, ClientErrorKind } from \"../../errors\";\n\nexport const JwtDecodeErrorCode = {\n\tInvalidFormat: \"protocol.jwt.invalid_format\",\n\tInvalidPayload: \"protocol.jwt.invalid_payload\",\n\tInvalidClaim: \"protocol.jwt.invalid_claim\",\n} as const;\n\nexport type JwtDecodeErrorCode =\n\t(typeof JwtDecodeErrorCode)[keyof typeof JwtDecodeErrorCode];\n\nexport class JwtDecodeError extends ClientError {\n\toverride readonly code: JwtDecodeErrorCode;\n\n\tconstructor(options: {\n\t\tcode: JwtDecodeErrorCode;\n\t\tmessage: string;\n\t\tcause?: unknown;\n\t}) {\n\t\tsuper({\n\t\t\tkind: ClientErrorKind.Protocol,\n\t\t\tcode: options.code,\n\t\t\tmessage: options.message,\n\t\t\tsource: \"protocol.jwt\",\n\t\t\tcause: options.cause,\n\t\t});\n\t\tthis.name = \"JwtDecodeError\";\n\t\tthis.code = options.code;\n\t}\n}\n","import { JwtDecodeError, JwtDecodeErrorCode } from \"./error\";\nimport { type DecodeJwtPayloadOptions, type JwtClaimsSet } from \"./types\";\n\nexport function decodeJwtPayload(\n\tjwt: string,\n\toptions: DecodeJwtPayloadOptions = {},\n): JwtClaimsSet {\n\tconst label = options.label ?? \"JWT\";\n\tconst parts = jwt.split(\".\");\n\tif (parts.length !== 3) {\n\t\tthrow new JwtDecodeError({\n\t\t\tcode: JwtDecodeErrorCode.InvalidFormat,\n\t\t\tmessage: `${label} must use compact JWS serialization`,\n\t\t});\n\t}\n\n\tconst claims = parseBase64UrlJsonObject(parts[1], `${label} payload`);\n\tvalidateRegisteredClaimTypes(claims, label);\n\treturn claims;\n}\n\nfunction parseBase64UrlJsonObject(value: string, label: string): JwtClaimsSet {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(decodeBase64UrlUtf8(value));\n\t} catch (cause) {\n\t\tthrow new JwtDecodeError({\n\t\t\tcode: JwtDecodeErrorCode.InvalidPayload,\n\t\t\tmessage: `${label} must be base64url-encoded JSON`,\n\t\t\tcause,\n\t\t});\n\t}\n\n\tif (!isJsonObject(parsed)) {\n\t\tthrow new JwtDecodeError({\n\t\t\tcode: JwtDecodeErrorCode.InvalidPayload,\n\t\t\tmessage: `${label} must be a JSON object`,\n\t\t});\n\t}\n\treturn parsed;\n}\n\nfunction decodeBase64UrlUtf8(value: string): string {\n\tconst base64 = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\tconst padded = base64 + \"=\".repeat((4 - (base64.length % 4)) % 4);\n\tconst binary = atob(padded);\n\tconst bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));\n\treturn new TextDecoder().decode(bytes);\n}\n\nfunction validateRegisteredClaimTypes(\n\tclaims: JwtClaimsSet,\n\tlabel: string,\n): void {\n\tif (claims.exp !== undefined && typeof claims.exp !== \"number\") {\n\t\tthrow new JwtDecodeError({\n\t\t\tcode: JwtDecodeErrorCode.InvalidClaim,\n\t\t\tmessage: `${label} \"exp\" claim must be a number`,\n\t\t});\n\t}\n\tif (claims.iat !== undefined && typeof claims.iat !== \"number\") {\n\t\tthrow new JwtDecodeError({\n\t\t\tcode: JwtDecodeErrorCode.InvalidClaim,\n\t\t\tmessage: `${label} \"iat\" claim must be a number`,\n\t\t});\n\t}\n\tif (claims.nbf !== undefined && typeof claims.nbf !== \"number\") {\n\t\tthrow new JwtDecodeError({\n\t\t\tcode: JwtDecodeErrorCode.InvalidClaim,\n\t\t\tmessage: `${label} \"nbf\" claim must be a number`,\n\t\t});\n\t}\n\tif (claims.iss !== undefined && typeof claims.iss !== \"string\") {\n\t\tthrow new JwtDecodeError({\n\t\t\tcode: JwtDecodeErrorCode.InvalidClaim,\n\t\t\tmessage: `${label} \"iss\" claim must be a string`,\n\t\t});\n\t}\n\tif (\n\t\tclaims.aud !== undefined &&\n\t\ttypeof claims.aud !== \"string\" &&\n\t\t!isStringArray(claims.aud)\n\t) {\n\t\tthrow new JwtDecodeError({\n\t\t\tcode: JwtDecodeErrorCode.InvalidClaim,\n\t\t\tmessage: `${label} \"aud\" claim must be a string or string array`,\n\t\t});\n\t}\n}\n\nfunction isJsonObject(value: unknown): value is JwtClaimsSet {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isStringArray(value: unknown): value is readonly string[] {\n\treturn (\n\t\tArray.isArray(value) && value.every((item) => typeof item === \"string\")\n\t);\n}\n","/**\n * Parse a human-readable duration string (for example `5m` or `300s`) into\n * milliseconds.\n */\nexport function parseDurationToMs(duration: string): number {\n\tconst match = duration.match(/^(\\d+(?:\\.\\d+)?)\\s*(s|ms|m|h)$/);\n\tif (!match) {\n\t\treturn 0;\n\t}\n\tconst value = Number(match[1]);\n\n\tswitch (match[2]) {\n\t\tcase \"ms\":\n\t\t\treturn value;\n\t\tcase \"s\":\n\t\t\treturn value * 1000;\n\t\tcase \"m\":\n\t\t\treturn value * 60 * 1000;\n\t\tcase \"h\":\n\t\t\treturn value * 60 * 60 * 1000;\n\t\tdefault:\n\t\t\treturn 0;\n\t}\n}\n","import { type Codec } from \"./types\";\n\n/** Default JSON codec. */\nexport function createJsonCodec<T>(): Codec<T> {\n\treturn {\n\t\tencode(value: T): string {\n\t\t\treturn JSON.stringify(value);\n\t\t},\n\t\tdecode(raw: string): T {\n\t\t\treturn JSON.parse(raw) as T;\n\t\t},\n\t};\n}\n","import { createJsonCodec } from \"./json-codec\";\nimport {\n\ttype Codec,\n\ttype EphemeralFlowStore,\n\ttype KeyedEphemeralFlowStore,\n\ttype StorageTrait,\n} from \"./types\";\n\nexport interface CreateEphemeralFlowStoreOptions<T> {\n\tstore: StorageTrait;\n\tkey: string;\n\tcodec?: Codec<T>;\n}\n\nexport interface CreateKeyedEphemeralFlowStoreOptions<T> {\n\tstore: StorageTrait;\n\tkeyPrefix: string;\n\tcodec?: Codec<T>;\n}\n\nfunction resolveStorageKey(keyPrefix: string, key: string): string {\n\treturn keyPrefix.length > 0 ? `${keyPrefix}:${key}` : key;\n}\n\nfunction requireRecordStoreTake(\n\tstore: StorageTrait,\n): NonNullable<StorageTrait[\"take\"]> {\n\tif (!store.take) {\n\t\tthrow new ClientError({\n\t\t\tkind: ClientErrorKind.Configuration,\n\t\t\tcode: \"storage.ephemeral.take_unavailable\",\n\t\t\tmessage:\n\t\t\t\t\"Ephemeral flow stores require StorageTrait.take() for atomic single-consume semantics\",\n\t\t\tsource: \"storage.ephemeral\",\n\t\t});\n\t}\n\n\treturn store.take.bind(store);\n}\n\nasync function executeStorageOperation<T>(\n\toperation: () => T | Promise<T>,\n): Promise<T> {\n\ttry {\n\t\treturn await operation();\n\t} catch (error) {\n\t\tif (error instanceof ClientError) {\n\t\t\tthrow error;\n\t\t}\n\t\tthrow new ClientError({\n\t\t\tkind: ClientErrorKind.Storage,\n\t\t\tcode: \"storage.ephemeral.io_failed\",\n\t\t\tmessage: \"The ephemeral flow store operation failed\",\n\t\t\tsource: \"storage.ephemeral\",\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\nfunction decodeStoredValue<T>(codec: Codec<T>, value: string): T {\n\ttry {\n\t\treturn codec.decode(value);\n\t} catch (error) {\n\t\tthrow new ClientError({\n\t\t\tkind: ClientErrorKind.Protocol,\n\t\t\tcode: \"storage.ephemeral.invalid_payload\",\n\t\t\tmessage: \"The ephemeral flow store payload is invalid\",\n\t\t\tsource: \"storage.ephemeral\",\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\n/**\n * Create a typed ephemeral flow-state store backed by a low-level `StorageTrait`.\n *\n * Intended for short-lived browser/session coordination state such as pending\n * redirects or callback fragments.\n */\nexport function createEphemeralFlowStore<T>(\n\toptions: CreateEphemeralFlowStoreOptions<T>,\n): EphemeralFlowStore<T> {\n\tconst codec = options.codec ?? createJsonCodec<T>();\n\tconst storeTake = requireRecordStoreTake(options.store);\n\n\tasync function load(): Promise<T | null> {\n\t\tconst raw = await executeStorageOperation(() =>\n\t\t\toptions.store.get(options.key),\n\t\t);\n\t\treturn raw === null ? null : decodeStoredValue(codec, raw);\n\t}\n\n\tasync function save(value: T): Promise<void> {\n\t\tawait executeStorageOperation(() =>\n\t\t\toptions.store.set(options.key, codec.encode(value)),\n\t\t);\n\t}\n\n\tasync function consume(): Promise<T | null> {\n\t\tconst raw = await executeStorageOperation(() => storeTake(options.key));\n\t\treturn raw === null ? null : decodeStoredValue(codec, raw);\n\t}\n\n\tasync function clear(): Promise<void> {\n\t\tawait executeStorageOperation(() => options.store.remove(options.key));\n\t}\n\n\treturn {\n\t\tload,\n\t\tsave,\n\t\tconsume,\n\t\tclear,\n\t};\n}\n\n/**\n * Create a typed keyed ephemeral flow-state store backed by a low-level\n * `StorageTrait`.\n *\n * Intended for short-lived browser/session coordination state where multiple\n * pending records must coexist and be consumed independently.\n */\nexport function createKeyedEphemeralFlowStore<T>(\n\toptions: CreateKeyedEphemeralFlowStoreOptions<T>,\n): KeyedEphemeralFlowStore<T> {\n\tconst codec = options.codec ?? createJsonCodec<T>();\n\tconst storeTake = requireRecordStoreTake(options.store);\n\n\tasync function load(key: string): Promise<T | null> {\n\t\tconst raw = await executeStorageOperation(() =>\n\t\t\toptions.store.get(resolveStorageKey(options.keyPrefix, key)),\n\t\t);\n\t\treturn raw === null ? null : decodeStoredValue(codec, raw);\n\t}\n\n\tasync function save(key: string, value: T): Promise<void> {\n\t\tawait executeStorageOperation(() =>\n\t\t\toptions.store.set(\n\t\t\t\tresolveStorageKey(options.keyPrefix, key),\n\t\t\t\tcodec.encode(value),\n\t\t\t),\n\t\t);\n\t}\n\n\tasync function take(key: string): Promise<T | null> {\n\t\tconst raw = await executeStorageOperation(() =>\n\t\t\tstoreTake(resolveStorageKey(options.keyPrefix, key)),\n\t\t);\n\t\treturn raw === null ? null : decodeStoredValue(codec, raw);\n\t}\n\n\tasync function clear(key: string): Promise<void> {\n\t\tawait executeStorageOperation(() =>\n\t\t\toptions.store.remove(resolveStorageKey(options.keyPrefix, key)),\n\t\t);\n\t}\n\n\treturn {\n\t\tload,\n\t\tsave,\n\t\ttake,\n\t\tclear,\n\t};\n}\n\nimport { ClientError, ClientErrorKind } from \"../errors\";\n","import { SYMBOL_OBSERVABLE } from \"../compat\";\nimport { createSignal, type ReadableSignalTrait } from \"../signals\";\n\nexport const OnceAsyncLockState = {\n\tInit: \"init\",\n\tRunning: \"running\",\n\tSuccess: \"success\",\n\tError: \"error\",\n} as const;\n\nexport type OnceAsyncLockState =\n\t(typeof OnceAsyncLockState)[keyof typeof OnceAsyncLockState];\n\nexport type OnceAsyncLockInit = {\n\treadonly state: typeof OnceAsyncLockState.Init;\n\treadonly promise?: never;\n};\n\nexport type OnceAsyncLockRunning = {\n\treadonly state: typeof OnceAsyncLockState.Running;\n\treadonly promise: Promise<unknown>;\n};\n\nexport type OnceAsyncLockSuccess<T> = {\n\treadonly state: typeof OnceAsyncLockState.Success;\n\treadonly data: T;\n};\n\nexport type OnceAsyncLockError<E> = {\n\treadonly state: typeof OnceAsyncLockState.Error;\n\treadonly error: E;\n};\n\nexport type OnceAsyncLock<T, E> =\n\t| OnceAsyncLockInit\n\t| OnceAsyncLockRunning\n\t| OnceAsyncLockSuccess<T>\n\t| OnceAsyncLockError<E>;\n\nexport type OnceAsyncLockCallable<\n\tF extends (...args: any[]) => PromiseLike<any>,\n\tE = unknown,\n> = F &\n\tOnceAsyncLock<Awaited<ReturnType<F>>, E> &\n\tReadableSignalTrait<OnceAsyncLock<Awaited<ReturnType<F>>, E>>;\n\nexport function createOnceAsyncLockCallable<\n\tF extends (...args: any[]) => PromiseLike<any>,\n\tE = unknown,\n>(fn: F): OnceAsyncLockCallable<F, E> {\n\tconst internalStateSignal = createSignal({\n\t\tstate: OnceAsyncLockState.Init,\n\t} as OnceAsyncLock<Awaited<ReturnType<F>>, E>);\n\n\tconst coreFn = async function (\n\t\tthis: any,\n\t\t...args: Parameters<F>\n\t): Promise<Awaited<ReturnType<F>>> {\n\t\tconst internalState = internalStateSignal.get();\n\t\tif (internalState.state === OnceAsyncLockState.Running) {\n\t\t\treturn internalState.promise as Promise<Awaited<ReturnType<F>>>;\n\t\t}\n\t\tif (internalState.state === OnceAsyncLockState.Success) {\n\t\t\treturn internalState.data;\n\t\t}\n\n\t\tlet resolvePromise!: (value: Awaited<ReturnType<F>>) => void;\n\t\tlet rejectPromise!: (reason: any) => void;\n\n\t\tconst promise = new Promise<Awaited<ReturnType<F>>>((res, rej) => {\n\t\t\tresolvePromise = res;\n\t\t\trejectPromise = rej;\n\t\t});\n\t\tpromise.catch(() => undefined);\n\n\t\tinternalStateSignal.set({ state: OnceAsyncLockState.Running, promise });\n\n\t\ttry {\n\t\t\tconst result = await fn.apply(this, args);\n\t\t\tinternalStateSignal.set({\n\t\t\t\tstate: OnceAsyncLockState.Success,\n\t\t\t\tdata: result,\n\t\t\t});\n\t\t\tresolvePromise(result);\n\t\t\treturn result;\n\t\t} catch (err) {\n\t\t\tinternalStateSignal.set({\n\t\t\t\tstate: OnceAsyncLockState.Error,\n\t\t\t\terror: err as E,\n\t\t\t});\n\t\t\trejectPromise(err);\n\t\t\tthrow err;\n\t\t}\n\t};\n\n\treturn new Proxy(coreFn, {\n\t\tget(target, prop, receiver) {\n\t\t\t// if accessing state, promise, data, error, map directly from internalState\n\t\t\tconst internalState = internalStateSignal.get();\n\t\t\tif (prop in internalState) {\n\t\t\t\treturn Reflect.get(internalState, prop);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tprop === \"get\" ||\n\t\t\t\tprop === \"watchStream\" ||\n\t\t\t\tprop === SYMBOL_OBSERVABLE\n\t\t\t) {\n\t\t\t\tconst value = Reflect.get(\n\t\t\t\t\tinternalStateSignal,\n\t\t\t\t\tprop,\n\t\t\t\t\tinternalStateSignal,\n\t\t\t\t);\n\t\t\t\treturn typeof value === \"function\"\n\t\t\t\t\t? value.bind(internalStateSignal)\n\t\t\t\t\t: value;\n\t\t\t}\n\t\t\t// other properties (like function's name, length, toString, etc.) retain original function behavior\n\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t},\n\t\t// intercept assignment operations to ensure state is read-only and prevent malicious or accidental modifications from outside\n\t\tset() {\n\t\t\treturn false; // in strict mode, this will throw a TypeError, preventing modification\n\t\t},\n\t}) as unknown as OnceAsyncLockCallable<F, E>;\n}\n","/**\n * Returns `true` for loopback HTTP URLs that browsers and local tooling often\n * permit during development flows.\n */\nexport function isLoopbackHttpUrl(url: URL): boolean {\n\treturn (\n\t\turl.protocol === \"http:\" &&\n\t\t(url.hostname === \"localhost\" ||\n\t\t\turl.hostname === \"127.0.0.1\" ||\n\t\t\turl.hostname === \"::1\" ||\n\t\t\turl.hostname === \"[::1]\")\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { H as ClientErrorKind, V as ClientError, k as RxEventStream } from "./rx-BoB32Dzg.mjs";
|
|
2
|
+
import { D as RouterNavigationMode, G as validateWithSchemaSync, H as throwValidationClientError, U as validateTraitInput } from "./create-Bm-XRA3G.mjs";
|
|
3
|
+
import { n as UriReferenceString } from "./uri-string-BfnIT4gJ.mjs";
|
|
4
|
+
import { defer, distinctUntilChanged, filter, fromEventPattern, map, merge } from "rxjs";
|
|
5
|
+
import { type } from "arktype";
|
|
6
|
+
//#region src/web/events/page-resume.ts
|
|
7
|
+
const PageResumeTriggerKind = {
|
|
8
|
+
Visibility: "visibility",
|
|
9
|
+
PageShow: "pageshow",
|
|
10
|
+
Focus: "focus",
|
|
11
|
+
Online: "online"
|
|
12
|
+
};
|
|
13
|
+
function createPageResumeSource(options) {
|
|
14
|
+
return RxEventStream.fromObservableInput(defer(() => {
|
|
15
|
+
const { documentTarget, windowTarget } = options;
|
|
16
|
+
const streams = [];
|
|
17
|
+
if (documentTarget) streams.push(fromEventPattern((handler) => documentTarget.addEventListener("visibilitychange", handler), (handler) => documentTarget.removeEventListener("visibilitychange", handler)).pipe(map(() => documentTarget.visibilityState), distinctUntilChanged(), filter((visibilityState) => visibilityState === "visible"), map(() => ({ trigger: PageResumeTriggerKind.Visibility }))));
|
|
18
|
+
if (windowTarget) {
|
|
19
|
+
streams.push(fromEventPattern((handler) => windowTarget.addEventListener("pageshow", handler), (handler) => windowTarget.removeEventListener("pageshow", handler)).pipe(map((event) => ({
|
|
20
|
+
trigger: PageResumeTriggerKind.PageShow,
|
|
21
|
+
persisted: Boolean(event.persisted)
|
|
22
|
+
}))));
|
|
23
|
+
streams.push(fromEventPattern((handler) => windowTarget.addEventListener("focus", handler), (handler) => windowTarget.removeEventListener("focus", handler)).pipe(map(() => ({ trigger: PageResumeTriggerKind.Focus }))));
|
|
24
|
+
streams.push(fromEventPattern((handler) => windowTarget.addEventListener("online", handler), (handler) => windowTarget.removeEventListener("online", handler)).pipe(map(() => ({ trigger: PageResumeTriggerKind.Online }))));
|
|
25
|
+
}
|
|
26
|
+
return merge(...streams);
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/web/page.ts
|
|
31
|
+
const PageResumeDocumentTargetSchema = type({
|
|
32
|
+
addEventListener: "Function",
|
|
33
|
+
removeEventListener: "Function",
|
|
34
|
+
visibilityState: "string"
|
|
35
|
+
});
|
|
36
|
+
const PageResumeWindowTargetSchema = type({
|
|
37
|
+
addEventListener: "Function",
|
|
38
|
+
removeEventListener: "Function"
|
|
39
|
+
});
|
|
40
|
+
const PageLifecycleForNativeWebUnavailableProbeSchema = type({
|
|
41
|
+
document: "null | undefined",
|
|
42
|
+
window: "null | undefined"
|
|
43
|
+
});
|
|
44
|
+
const PageLifecycleForNativeWebCreateOptionsSchema = type({
|
|
45
|
+
document: PageResumeDocumentTargetSchema.or("null").or("undefined"),
|
|
46
|
+
window: PageResumeWindowTargetSchema.or("null").or("undefined")
|
|
47
|
+
});
|
|
48
|
+
function createPageLifecycleForNativeWeb(options = {}) {
|
|
49
|
+
const { validators, ...createOptions } = options;
|
|
50
|
+
const global = globalThis;
|
|
51
|
+
const resolvedCreateOptions = {
|
|
52
|
+
document: global.document ?? null,
|
|
53
|
+
window: global.window ?? null,
|
|
54
|
+
...createOptions
|
|
55
|
+
};
|
|
56
|
+
if (validateWithSchemaSync(PageLifecycleForNativeWebUnavailableProbeSchema, resolvedCreateOptions).success) return null;
|
|
57
|
+
validateTraitInput({
|
|
58
|
+
value: resolvedCreateOptions,
|
|
59
|
+
bundledSchema: PageLifecycleForNativeWebCreateOptionsSchema,
|
|
60
|
+
validator: validators?.pageLifecycle,
|
|
61
|
+
onInvalid: (failure) => throwValidationClientError({
|
|
62
|
+
code: "web.page.invalid_native_web_page_lifecycle_options",
|
|
63
|
+
source: "web",
|
|
64
|
+
messagePrefix: "createPageLifecycleForNativeWeb could not validate pageLifecycleForNativeWebCreateOptions",
|
|
65
|
+
failure
|
|
66
|
+
})
|
|
67
|
+
});
|
|
68
|
+
return { resume: createPageResumeSource({
|
|
69
|
+
documentTarget: resolvedCreateOptions.document ?? null,
|
|
70
|
+
windowTarget: resolvedCreateOptions.window ?? null
|
|
71
|
+
}) };
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/web/router/router.ts
|
|
75
|
+
const NativeWebNavigationLikeSchema = type({
|
|
76
|
+
navigate: "Function",
|
|
77
|
+
addEventListener: "Function?",
|
|
78
|
+
removeEventListener: "Function?"
|
|
79
|
+
});
|
|
80
|
+
const NativeWebLocationLikeSchema = type({ href: "string" });
|
|
81
|
+
const NativeWebHistoryLikeSchema = type({
|
|
82
|
+
pushState: "Function",
|
|
83
|
+
replaceState: "Function"
|
|
84
|
+
});
|
|
85
|
+
const NativeWebWindowLikeSchema = type({
|
|
86
|
+
location: NativeWebLocationLikeSchema.optional(),
|
|
87
|
+
history: NativeWebHistoryLikeSchema.optional(),
|
|
88
|
+
open: "Function?"
|
|
89
|
+
});
|
|
90
|
+
const NullableNativeWebHistoryLikeSchema = NativeWebHistoryLikeSchema.or("null").or("undefined");
|
|
91
|
+
const NullableNativeWebWindowLikeSchema = NativeWebWindowLikeSchema.or("null").or("undefined");
|
|
92
|
+
const RouterForNativeWebCreateOptionsSchema = type({
|
|
93
|
+
navigation: NativeWebNavigationLikeSchema,
|
|
94
|
+
location: NativeWebLocationLikeSchema.or("null").or("undefined"),
|
|
95
|
+
history: NullableNativeWebHistoryLikeSchema,
|
|
96
|
+
window: NullableNativeWebWindowLikeSchema
|
|
97
|
+
}).or({
|
|
98
|
+
navigation: "null | undefined",
|
|
99
|
+
location: NativeWebLocationLikeSchema,
|
|
100
|
+
history: NullableNativeWebHistoryLikeSchema,
|
|
101
|
+
window: NullableNativeWebWindowLikeSchema
|
|
102
|
+
});
|
|
103
|
+
const RouterForNativeWebUnavailableProbeSchema = type({
|
|
104
|
+
navigation: "null | undefined",
|
|
105
|
+
location: "null | undefined",
|
|
106
|
+
history: "null | undefined",
|
|
107
|
+
window: "null | undefined"
|
|
108
|
+
});
|
|
109
|
+
function createRouterForNativeWeb(options = {}) {
|
|
110
|
+
const resolvedCreateOptions = resolveRouterForNativeWebCreateOptions(options);
|
|
111
|
+
if (validateWithSchemaSync(RouterForNativeWebUnavailableProbeSchema, resolvedCreateOptions).success) return null;
|
|
112
|
+
validateTraitInput({
|
|
113
|
+
value: resolvedCreateOptions,
|
|
114
|
+
bundledSchema: RouterForNativeWebCreateOptionsSchema,
|
|
115
|
+
validator: options.validators?.router,
|
|
116
|
+
onInvalid: (failure) => throwValidationClientError({
|
|
117
|
+
code: "web.router.invalid_native_web_router_options",
|
|
118
|
+
source: "web",
|
|
119
|
+
messagePrefix: "createRouterForNativeWeb could not validate routerForNativeWebCreateOptions",
|
|
120
|
+
failure
|
|
121
|
+
})
|
|
122
|
+
});
|
|
123
|
+
const router = new NativeWebRouter(resolvedCreateOptions);
|
|
124
|
+
return {
|
|
125
|
+
currentUrl() {
|
|
126
|
+
return router.currentUrl();
|
|
127
|
+
},
|
|
128
|
+
navigate(request) {
|
|
129
|
+
return router.navigate(request);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
var NativeWebRouter = class {
|
|
134
|
+
router;
|
|
135
|
+
constructor(options) {
|
|
136
|
+
this.router = options.navigation ? new WebNavigationRouter(options) : new WebLegacyRouter(options);
|
|
137
|
+
}
|
|
138
|
+
currentUrl() {
|
|
139
|
+
return this.router.currentUrl();
|
|
140
|
+
}
|
|
141
|
+
navigate(request) {
|
|
142
|
+
return this.router.navigate(request);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
var NativeWebRouterBase = class {
|
|
146
|
+
location;
|
|
147
|
+
constructor(options) {
|
|
148
|
+
this.location = options.location;
|
|
149
|
+
}
|
|
150
|
+
currentUrl() {
|
|
151
|
+
return this.location?.href ? UriReferenceString.parse(this.location.href) : null;
|
|
152
|
+
}
|
|
153
|
+
resolveNavigationTarget(request) {
|
|
154
|
+
return request.url.toString();
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
var WebNavigationRouter = class extends NativeWebRouterBase {
|
|
158
|
+
navigation;
|
|
159
|
+
history;
|
|
160
|
+
constructor(options) {
|
|
161
|
+
if (!options.navigation) throw new ClientError({
|
|
162
|
+
kind: ClientErrorKind.Configuration,
|
|
163
|
+
code: "web.router.navigation_unavailable",
|
|
164
|
+
message: "WebNavigationRouter requires the Navigation API",
|
|
165
|
+
source: "web.router"
|
|
166
|
+
});
|
|
167
|
+
super(options);
|
|
168
|
+
this.navigation = options.navigation;
|
|
169
|
+
this.history = options.history;
|
|
170
|
+
}
|
|
171
|
+
async navigate(request) {
|
|
172
|
+
const target = this.resolveNavigationTarget(request);
|
|
173
|
+
if (request.mode === RouterNavigationMode.External) {
|
|
174
|
+
if (this.location) {
|
|
175
|
+
this.location.href = target;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
throw new ClientError({
|
|
179
|
+
kind: ClientErrorKind.Configuration,
|
|
180
|
+
code: "web.router.location_unavailable",
|
|
181
|
+
message: "Native web router cannot perform external navigation without location",
|
|
182
|
+
source: "web.router"
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
if (this.history && this.isSameOriginNavigation(request.url)) {
|
|
186
|
+
if (request.mode === RouterNavigationMode.Replace) this.history.replaceState(request.state ?? null, "", target);
|
|
187
|
+
else this.history.pushState(request.state ?? null, "", target);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
await this.navigation.navigate(target, {
|
|
191
|
+
history: request.mode === RouterNavigationMode.Replace ? RouterNavigationMode.Replace : RouterNavigationMode.Push,
|
|
192
|
+
state: request.state
|
|
193
|
+
})?.committed;
|
|
194
|
+
}
|
|
195
|
+
isSameOriginNavigation(url) {
|
|
196
|
+
const current = this.currentUrl();
|
|
197
|
+
if (!current) return false;
|
|
198
|
+
if (url.isAbsolute() && current.isAbsolute()) return url.origin === current.origin;
|
|
199
|
+
return url.isRelative();
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
var WebLegacyRouter = class extends NativeWebRouterBase {
|
|
203
|
+
history;
|
|
204
|
+
constructor(options) {
|
|
205
|
+
super(options);
|
|
206
|
+
this.history = options.history;
|
|
207
|
+
}
|
|
208
|
+
async navigate(request) {
|
|
209
|
+
const target = this.resolveNavigationTarget(request);
|
|
210
|
+
if (request.mode === RouterNavigationMode.External) {
|
|
211
|
+
if (this.location) {
|
|
212
|
+
this.location.href = target;
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
throw new ClientError({
|
|
216
|
+
kind: ClientErrorKind.Configuration,
|
|
217
|
+
code: "web.router.location_unavailable",
|
|
218
|
+
message: "Native web router cannot perform external navigation without location",
|
|
219
|
+
source: "web.router"
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
if (!this.history) throw new ClientError({
|
|
223
|
+
kind: ClientErrorKind.Configuration,
|
|
224
|
+
code: "web.router.history_unavailable",
|
|
225
|
+
message: "Native web router requires history for in-page navigation",
|
|
226
|
+
source: "web.router"
|
|
227
|
+
});
|
|
228
|
+
if (request.mode === RouterNavigationMode.Replace) this.history.replaceState(request.state ?? null, "", target);
|
|
229
|
+
else this.history.pushState(request.state ?? null, "", target);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
function resolveRouterForNativeWebCreateOptions(options = {}) {
|
|
233
|
+
const global = globalThis;
|
|
234
|
+
const windowLike = Object.hasOwn(options, "window") ? options.window ?? null : global.window ?? null;
|
|
235
|
+
return {
|
|
236
|
+
window: windowLike,
|
|
237
|
+
navigation: Object.hasOwn(options, "navigation") ? options.navigation ?? null : global.navigation ?? null,
|
|
238
|
+
location: Object.hasOwn(options, "location") ? options.location ?? null : windowLike?.location ?? global.location ?? null,
|
|
239
|
+
history: Object.hasOwn(options, "history") ? options.history ?? null : windowLike?.history ?? global.history ?? null
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
export { createPageLifecycleForNativeWeb as a, createRouterForNativeWeb as i, WebLegacyRouter as n, PageResumeTriggerKind as o, WebNavigationRouter as r, createPageResumeSource as s, NativeWebRouter as t };
|
|
244
|
+
|
|
245
|
+
//# sourceMappingURL=router-BJ8LqNJ1.mjs.map
|