@securitydept/client 0.3.0-beta.5 → 0.3.0-beta.6

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.
Files changed (32) hide show
  1. package/dist/{create-Bm-XRA3G.mjs → create-99Ksgl_O.mjs} +13 -634
  2. package/dist/create-99Ksgl_O.mjs.map +1 -0
  3. package/dist/handle-TnxwtQ4T.mjs +634 -0
  4. package/dist/handle-TnxwtQ4T.mjs.map +1 -0
  5. package/dist/{index-Ch8lrE44.d.mts → index-Cg_iY2yY.d.mts} +4 -21
  6. package/dist/{index-D5mW18cM.d.mts → index-DmIapvr-.d.mts} +50 -29
  7. package/dist/{index-BT-u3qNI.d.mts → index-O1A3CdBV.d.mts} +4 -18
  8. package/dist/index.d.mts +3 -3
  9. package/dist/index.mjs +9 -8
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/{router-BJ8LqNJ1.mjs → router-DUh3bhLy.mjs} +4 -4
  12. package/dist/{router-BJ8LqNJ1.mjs.map → router-DUh3bhLy.mjs.map} +1 -1
  13. package/dist/rx/index.d.mts +1 -2
  14. package/dist/rx/index.mjs +1 -1
  15. package/dist/{rx-BoB32Dzg.mjs → rx-B3OU17wu.mjs} +1 -2
  16. package/dist/{rx-BoB32Dzg.mjs.map → rx-B3OU17wu.mjs.map} +1 -1
  17. package/dist/server/index.d.mts +1 -2
  18. package/dist/server/index.mjs +1 -1
  19. package/dist/server/index.mjs.map +1 -1
  20. package/dist/test/index.d.mts +2 -3
  21. package/dist/test/index.mjs +3 -3
  22. package/dist/test/index.mjs.map +1 -1
  23. package/dist/{uri-string-BfnIT4gJ.mjs → uri-string-BPNbIMgv.mjs} +5 -3
  24. package/dist/{uri-string-BfnIT4gJ.mjs.map → uri-string-BPNbIMgv.mjs.map} +1 -1
  25. package/dist/web/index.d.mts +16 -4
  26. package/dist/web/index.mjs +27 -21
  27. package/dist/web/index.mjs.map +1 -1
  28. package/dist/webext/index.d.mts +2 -3
  29. package/dist/webext/index.mjs +12 -10
  30. package/dist/webext/index.mjs.map +1 -1
  31. package/package.json +5 -5
  32. package/dist/create-Bm-XRA3G.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["defineType","defineType"],"sources":["../../src/test/time.ts","../../src/test/environment.ts","../../src/test/idle-callback.ts","../../src/test/page-lifecycle.ts","../../src/test/popup.ts","../../src/test/router.ts","../../src/test/storage.ts","../../src/test/transport.ts"],"sourcesContent":["import { type as defineType } from \"arktype\";\nimport { type EnvironmentValidators } from \"../environment/types\";\nimport { type TimeTrait } from \"../scheduling/types\";\nimport {\n\tthrowValidationClientError,\n\tvalidateTraitInput,\n\ttype WithTraitInputValidator,\n} from \"../validation\";\n\nexport interface TestTimeTrait extends TimeTrait {\n\tadvance(ms: number): void;\n\tflush(): void;\n\tadvanceAndFlush(ms: number): void;\n\tget pendingCount(): number;\n}\n\nexport interface TimeForTestCreateOptions {\n\tinitialNow?: number;\n}\n\nconst TimeForTestCreateOptionsSchema = defineType({\n\tinitialNow: \"number\",\n});\n\nexport function createTimeForTest(\n\toptions: TimeForTestCreateOptions &\n\t\tWithTraitInputValidator<Pick<EnvironmentValidators, \"time\">> = {},\n): TestTimeTrait {\n\tconst { validators, ...createOptions } = options;\n\tconst resolvedCreateOptions = {\n\t\tinitialNow: createOptions.initialNow ?? 0,\n\t};\n\tvalidateTraitInput({\n\t\tvalue: resolvedCreateOptions,\n\t\tbundledSchema: TimeForTestCreateOptionsSchema,\n\t\tvalidator: validators?.time,\n\t\tonInvalid: (failure) =>\n\t\t\tthrowValidationClientError({\n\t\t\t\tcode: \"test.time.invalid_options\",\n\t\t\t\tsource: \"test\",\n\t\t\t\tmessagePrefix: \"createTimeForTest could not validate time\",\n\t\t\t\tfailure,\n\t\t\t}),\n\t});\n\tlet now = resolvedCreateOptions.initialNow;\n\tlet nextId = 1;\n\tconst tasks = new Map<number, { at: number; handler: () => void }>();\n\treturn {\n\t\tnow: () => now,\n\t\tsetTimeout(handler, delayMs) {\n\t\t\tconst id = nextId++;\n\t\t\ttasks.set(id, { at: now + Math.max(0, delayMs), handler });\n\t\t\treturn id;\n\t\t},\n\t\tclearTimeout(handle) {\n\t\t\tif (typeof handle === \"number\") {\n\t\t\t\ttasks.delete(handle);\n\t\t\t}\n\t\t},\n\t\tadvance(ms) {\n\t\t\tnow += ms;\n\t\t},\n\t\tflush() {\n\t\t\tlet progressed = true;\n\t\t\twhile (progressed) {\n\t\t\t\tprogressed = false;\n\t\t\t\tconst ready = [...tasks.entries()]\n\t\t\t\t\t.filter(([, task]) => task.at <= now)\n\t\t\t\t\t.sort((a, b) => a[1].at - b[1].at);\n\t\t\t\tfor (const [id, task] of ready) {\n\t\t\t\t\ttasks.delete(id);\n\t\t\t\t\ttask.handler();\n\t\t\t\t\tprogressed = true;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tadvanceAndFlush(ms) {\n\t\t\tthis.advance(ms);\n\t\t\tthis.flush();\n\t\t},\n\t\tget pendingCount() {\n\t\t\treturn tasks.size;\n\t\t},\n\t};\n}\n","import {\n\ttype CreateFoundationEnvironmentOptions,\n\tcreateFoundationEnvironment,\n} from \"../environment/create\";\nimport { type FoundationEnvironment } from \"../environment/types\";\nimport {\n\tcreateProviderIfTokenMissing,\n\tgetSecuritydeptProviderToken,\n\tnotMissingProvider,\n\ttype SecuritydeptProvider,\n} from \"../injection\";\nimport { TIME_TRAIT_TOKEN, type TimeTrait } from \"../scheduling/types\";\nimport {\n\ttype BaseTransportTrait,\n\tTRANSPORT_TRAIT_TOKEN,\n} from \"../transport/types\";\nimport { createTimeForTest } from \"./time\";\n\nexport type EnvironmentCreatorOptions = {\n\tproviders?: readonly SecuritydeptProvider[];\n};\n\nexport type EnvironmentCreator<\n\tTOptions extends EnvironmentCreatorOptions,\n\tTEnvironment extends FoundationEnvironment,\n> = (options: TOptions) => TEnvironment;\n\nexport interface CreateEnvironmentForTestOptions\n\textends Omit<CreateFoundationEnvironmentOptions, \"transport\"> {\n\ttransport?: BaseTransportTrait;\n\ttime?: TimeTrait;\n}\n\nexport type CreateEnvironmentForTestWithBaseOptions<\n\tTBaseOptions extends EnvironmentCreatorOptions,\n\tTEnvironment extends FoundationEnvironment,\n> = Omit<TBaseOptions, \"providers\" | \"transport\" | \"createBaseEnvironment\"> & {\n\tcreateBaseEnvironment: EnvironmentCreator<TBaseOptions, TEnvironment>;\n\ttransport?: BaseTransportTrait;\n\tproviders?: readonly SecuritydeptProvider[];\n};\n\nexport function createEnvironmentForTest(): FoundationEnvironment;\nexport function createEnvironmentForTest(\n\toptions: CreateEnvironmentForTestOptions,\n): FoundationEnvironment;\nexport function createEnvironmentForTest<\n\tTBaseOptions extends EnvironmentCreatorOptions,\n\tTEnvironment extends FoundationEnvironment,\n>(\n\toptions: CreateEnvironmentForTestWithBaseOptions<TBaseOptions, TEnvironment>,\n): TEnvironment;\nexport function createEnvironmentForTest(\n\toptions:\n\t\t| CreateEnvironmentForTestOptions\n\t\t| CreateEnvironmentForTestWithBaseOptions<\n\t\t\t\tEnvironmentCreatorOptions,\n\t\t\t\tFoundationEnvironment\n\t\t > = {},\n): FoundationEnvironment {\n\tconst {\n\t\tcreateBaseEnvironment = createFoundationEnvironment,\n\t\ttransport,\n\t\tproviders = [],\n\t\t...baseOptions\n\t} = options as CreateEnvironmentForTestWithBaseOptions<\n\t\tEnvironmentCreatorOptions,\n\t\tFoundationEnvironment\n\t> &\n\t\tCreateEnvironmentForTestOptions;\n\tconst externalProviderTokens = new Set(\n\t\tproviders.map((provider) => getSecuritydeptProviderToken(provider)),\n\t);\n\tconst testProviders: SecuritydeptProvider[] = [\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tTRANSPORT_TRAIT_TOKEN,\n\t\t\t() => ({\n\t\t\t\tprovide: TRANSPORT_TRAIT_TOKEN,\n\t\t\t\tuseValue: transport ?? createMissingTransportForTest(),\n\t\t\t}),\n\t\t),\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tTIME_TRAIT_TOKEN,\n\t\t\t() => ({\n\t\t\t\tprovide: TIME_TRAIT_TOKEN,\n\t\t\t\tuseValue:\n\t\t\t\t\tbaseOptions.time ?? createTimeForTest({ initialNow: Date.now() }),\n\t\t\t}),\n\t\t),\n\t].filter(notMissingProvider) as SecuritydeptProvider[];\n\n\treturn createBaseEnvironment({\n\t\t...(baseOptions as unknown as Omit<EnvironmentCreatorOptions, \"providers\">),\n\t\tproviders: [...testProviders, ...providers],\n\t});\n}\n\nfunction createMissingTransportForTest(): BaseTransportTrait {\n\treturn {\n\t\tasync execute() {\n\t\t\tthrow new Error(\"Test environment transport was not provided.\");\n\t\t},\n\t};\n}\n","import { type IdleCallbackTrait } from \"../scheduling/types\";\n\nexport interface TestIdleCallbackTrait extends IdleCallbackTrait {\n\tflush(): void;\n\tget pendingCount(): number;\n}\n\nexport function createIdleCallbackForTest(): TestIdleCallbackTrait {\n\tlet nextId = 1;\n\tconst callbacks = new Map<number, () => void>();\n\treturn {\n\t\trequestIdleCallback(callback) {\n\t\t\tconst id = nextId++;\n\t\t\tcallbacks.set(id, callback);\n\t\t\treturn id;\n\t\t},\n\t\tcancelIdleCallback(handle) {\n\t\t\tif (typeof handle === \"number\") {\n\t\t\t\tcallbacks.delete(handle);\n\t\t\t}\n\t\t},\n\t\tflush() {\n\t\t\tconst ready = [...callbacks.entries()];\n\t\t\tcallbacks.clear();\n\t\t\tfor (const [, callback] of ready) {\n\t\t\t\tcallback();\n\t\t\t}\n\t\t},\n\t\tget pendingCount() {\n\t\t\treturn callbacks.size;\n\t\t},\n\t};\n}\n","import { SYMBOL_OBSERVABLE } from \"../compat/observable\";\nimport {\n\ttype EventObserverTrait,\n\ttype EventSubjectTrait,\n\ttype EventSubscriptionTrait,\n} from \"../events/types\";\nimport { type PageLifecycleTrait } from \"../page\";\n\nexport interface TestEventSubjectTrait<T> extends EventSubjectTrait<T> {\n\tget observerCount(): number;\n}\n\nexport interface TestPageLifecycleTrait<TResumeEvent = unknown>\n\textends PageLifecycleTrait<TResumeEvent> {\n\treadonly resume: TestEventSubjectTrait<TResumeEvent>;\n}\n\nexport function createPageLifecycleForTest<\n\tTResumeEvent = unknown,\n>(): TestPageLifecycleTrait<TResumeEvent> {\n\treturn {\n\t\tresume: createEventSubjectForTest<TResumeEvent>(),\n\t};\n}\n\nexport function createEventSubjectForTest<T>(): TestEventSubjectTrait<T> {\n\tconst observers = new Set<Partial<EventObserverTrait<T>>>();\n\tconst stream = {\n\t\tsubscribe(observer) {\n\t\t\tobservers.add(observer);\n\t\t\treturn {\n\t\t\t\tunsubscribe() {\n\t\t\t\t\tobservers.delete(observer);\n\t\t\t\t},\n\t\t\t} satisfies EventSubscriptionTrait;\n\t\t},\n\t\tnext(value) {\n\t\t\tfor (const observer of [...observers]) {\n\t\t\t\tobserver.next?.(value);\n\t\t\t}\n\t\t},\n\t\terror(error) {\n\t\t\tfor (const observer of [...observers]) {\n\t\t\t\tobserver.error?.(error);\n\t\t\t}\n\t\t},\n\t\tcomplete() {\n\t\t\tfor (const observer of [...observers]) {\n\t\t\t\tobserver.complete?.();\n\t\t\t}\n\t\t\tobservers.clear();\n\t\t},\n\t\tget observerCount() {\n\t\t\treturn observers.size;\n\t\t},\n\t\t[SYMBOL_OBSERVABLE]() {\n\t\t\treturn this;\n\t\t},\n\t} satisfies TestEventSubjectTrait<T>;\n\treturn stream;\n}\n","import { ClientError, ClientErrorKind } from \"../errors\";\nimport {\n\tPopupAttachFailureReason,\n\ttype PopupAttachResult,\n\ttype PopupOpenOptions,\n\ttype PopupTrait,\n} from \"../popup\";\n\nexport interface PopupForTestOpenCall {\n\turl: string;\n\toptions?: PopupOpenOptions;\n}\n\nexport interface PopupForTestCreateOptions {\n\tattachResult?: PopupAttachResult;\n}\n\nexport interface TestPopupTrait extends PopupTrait {\n\treadonly openCalls: readonly PopupForTestOpenCall[];\n\tsetAttachResult(result: PopupAttachResult): void;\n}\n\nexport function createPopupForTest(\n\toptions: PopupForTestCreateOptions = {},\n): TestPopupTrait {\n\tconst openCalls: PopupForTestOpenCall[] = [];\n\tlet attachResult = options.attachResult ?? createMissingOpenerAttachFailure();\n\treturn {\n\t\topen(url, openOptions) {\n\t\t\topenCalls.push({ url, options: openOptions });\n\t\t\tthrow new Error(\"Test popup open was not configured.\");\n\t\t},\n\t\tattach() {\n\t\t\treturn attachResult;\n\t\t},\n\t\tget openCalls() {\n\t\t\treturn openCalls;\n\t\t},\n\t\tsetAttachResult(result) {\n\t\t\tattachResult = result;\n\t\t},\n\t};\n}\n\nfunction createMissingOpenerAttachFailure(): PopupAttachResult {\n\treturn {\n\t\tkind: \"failure\",\n\t\treason: PopupAttachFailureReason.MissingOpener,\n\t\terror: new ClientError({\n\t\t\tkind: ClientErrorKind.Configuration,\n\t\t\tcode: \"test.popup.missing_opener\",\n\t\t\tsource: \"test\",\n\t\t\tmessage: \"Test popup attach was not configured.\",\n\t\t}),\n\t};\n}\n","import {\n\tRouterNavigationMode,\n\ttype RouterNavigationRequest,\n\ttype RouterTrait,\n} from \"../router/router\";\nimport { UriReferenceString } from \"../struct/uri-string\";\n\nexport interface RouterForTestCreateOptions {\n\tcurrentUrl?: string | UriReferenceString | null;\n\tonNavigate?: (request: RouterNavigationRequest) => void | Promise<void>;\n}\n\nexport interface TestRouterTrait extends RouterTrait {\n\treadonly navigations: readonly RouterNavigationRequest[];\n\tsetCurrentUrl(url: string | UriReferenceString | null): void;\n}\n\nexport function createRouterForTest(\n\toptions: RouterForTestCreateOptions = {},\n): TestRouterTrait {\n\tlet currentUrl =\n\t\toptions.currentUrl == null\n\t\t\t? null\n\t\t\t: UriReferenceString.parse(options.currentUrl);\n\tconst navigations: RouterNavigationRequest[] = [];\n\treturn {\n\t\tcurrentUrl() {\n\t\t\treturn currentUrl;\n\t\t},\n\t\tsetCurrentUrl(url) {\n\t\t\tcurrentUrl = url == null ? null : UriReferenceString.parse(url);\n\t\t},\n\t\tget navigations() {\n\t\t\treturn navigations;\n\t\t},\n\t\tasync navigate(request) {\n\t\t\tnavigations.push(request);\n\t\t\tif (\n\t\t\t\trequest.mode === RouterNavigationMode.Push ||\n\t\t\t\trequest.mode === RouterNavigationMode.Replace\n\t\t\t) {\n\t\t\t\tcurrentUrl = request.url;\n\t\t\t}\n\t\t\tawait options.onNavigate?.(request);\n\t\t},\n\t};\n}\n","import { type as defineType } from \"arktype\";\nimport { type EnvironmentValidators } from \"../environment/types\";\nimport { createInMemoryRecordStore } from \"../storage/memory-store\";\nimport { type SyncStorageTrait } from \"../storage/types\";\nimport {\n\tthrowValidationClientError,\n\tvalidateTraitInput,\n\ttype WithTraitInputValidator,\n} from \"../validation\";\n\nexport interface StorageForTestCreateOptions {\n\tinitialEntries?: Record<string, string>;\n\tvalidatorKey?: \"persistentStorage\" | \"sessionStorage\";\n}\n\nconst StorageForTestCreateOptionsSchema = defineType({\n\tinitialEntries: \"object\",\n\tvalidatorKey: \"'persistentStorage' | 'sessionStorage'\",\n});\n\nexport function createStorageForTest(\n\toptions: StorageForTestCreateOptions &\n\t\tWithTraitInputValidator<\n\t\t\tPick<EnvironmentValidators, \"persistentStorage\" | \"sessionStorage\">\n\t\t> = {},\n): SyncStorageTrait {\n\tconst { validators, ...createOptions } = options;\n\tconst validatorKey = options.validatorKey ?? \"persistentStorage\";\n\tconst resolvedCreateOptions = {\n\t\tinitialEntries: createOptions.initialEntries ?? {},\n\t\tvalidatorKey,\n\t};\n\tvalidateTraitInput({\n\t\tvalue: resolvedCreateOptions,\n\t\tbundledSchema: StorageForTestCreateOptionsSchema,\n\t\tvalidator: validators?.[validatorKey],\n\t\tonInvalid: (failure) =>\n\t\t\tthrowValidationClientError({\n\t\t\t\tcode: \"test.storage.invalid_options\",\n\t\t\t\tsource: \"test\",\n\t\t\t\tmessagePrefix: `createStorageForTest could not validate ${validatorKey}`,\n\t\t\t\tfailure,\n\t\t\t}),\n\t});\n\tconst storage = createInMemoryRecordStore();\n\tfor (const [key, value] of Object.entries(\n\t\tresolvedCreateOptions.initialEntries,\n\t)) {\n\t\tstorage.set(key, value);\n\t}\n\treturn storage;\n}\n","import {\n\ttype BaseTransportTrait,\n\ttype HttpRequest,\n\ttype HttpResponse,\n} from \"../transport/types\";\n\nexport interface TransportForTestRoute {\n\tpredicate: (request: HttpRequest) => boolean;\n\thandler: (request: HttpRequest) => HttpResponse | Promise<HttpResponse>;\n}\n\nexport interface TransportForTestCreateOptions {\n\troutes?: readonly TransportForTestRoute[];\n\tfallback?: HttpResponse;\n}\n\nexport interface TestTransportTrait extends BaseTransportTrait {\n\ton(\n\t\tpredicate: (request: HttpRequest) => boolean,\n\t\thandler: (request: HttpRequest) => HttpResponse | Promise<HttpResponse>,\n\t): this;\n\tonRequest(method: string, urlPrefix: string, response: HttpResponse): this;\n\tsetFallback(response: HttpResponse): this;\n\treset(): void;\n\treadonly history: readonly HttpRequest[];\n}\n\nexport function createTransportForTest(\n\toptions: TransportForTestCreateOptions = {},\n): TestTransportTrait {\n\tconst routes = [...(options.routes ?? [])];\n\tconst history: HttpRequest[] = [];\n\tlet fallback = options.fallback ?? createNotFoundResponseForTest();\n\treturn {\n\t\ton(predicate, handler) {\n\t\t\troutes.push({ predicate, handler });\n\t\t\treturn this;\n\t\t},\n\t\tonRequest(method, urlPrefix, response) {\n\t\t\treturn this.on(\n\t\t\t\t(request) =>\n\t\t\t\t\trequest.method.toUpperCase() === method.toUpperCase() &&\n\t\t\t\t\trequest.url.startsWith(urlPrefix),\n\t\t\t\t() => response,\n\t\t\t);\n\t\t},\n\t\tsetFallback(response) {\n\t\t\tfallback = response;\n\t\t\treturn this;\n\t\t},\n\t\treset() {\n\t\t\troutes.length = 0;\n\t\t\thistory.length = 0;\n\t\t},\n\t\tget history() {\n\t\t\treturn history;\n\t\t},\n\t\tasync execute(request) {\n\t\t\thistory.push(request);\n\t\t\tfor (const route of routes) {\n\t\t\t\tif (route.predicate(request)) {\n\t\t\t\t\treturn route.handler(request);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fallback;\n\t\t},\n\t};\n}\n\nfunction createNotFoundResponseForTest(): HttpResponse {\n\treturn {\n\t\tstatus: 404,\n\t\theaders: {},\n\t\tbody: { error: \"No matching test transport route\" },\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["defineType","defineType"],"sources":["../../src/test/time.ts","../../src/test/environment.ts","../../src/test/idle-callback.ts","../../src/test/page-lifecycle.ts","../../src/test/popup.ts","../../src/test/router.ts","../../src/test/storage.ts","../../src/test/transport.ts"],"sourcesContent":["import { type as defineType } from \"arktype\";\nimport { type EnvironmentValidators } from \"../environment/types\";\nimport { type TimeTrait } from \"../scheduling/types\";\nimport {\n\tthrowValidationClientError,\n\tvalidateTraitInput,\n\ttype WithTraitInputValidator,\n} from \"../validation\";\n\nexport interface TestTimeTrait extends TimeTrait {\n\tadvance(ms: number): void;\n\tflush(): void;\n\tadvanceAndFlush(ms: number): void;\n\tget pendingCount(): number;\n}\n\nexport interface TimeForTestCreateOptions {\n\tinitialNow?: number;\n}\n\nconst TimeForTestCreateOptionsSchema = defineType({\n\tinitialNow: \"number\",\n});\n\nexport function createTimeForTest(\n\toptions: TimeForTestCreateOptions &\n\t\tWithTraitInputValidator<Pick<EnvironmentValidators, \"time\">> = {},\n): TestTimeTrait {\n\tconst { validators, ...createOptions } = options;\n\tconst resolvedCreateOptions = {\n\t\tinitialNow: createOptions.initialNow ?? 0,\n\t};\n\tvalidateTraitInput({\n\t\tvalue: resolvedCreateOptions,\n\t\tbundledSchema: TimeForTestCreateOptionsSchema,\n\t\tvalidator: validators?.time,\n\t\tonInvalid: (failure) =>\n\t\t\tthrowValidationClientError({\n\t\t\t\tcode: \"test.time.invalid_options\",\n\t\t\t\tsource: \"test\",\n\t\t\t\tmessagePrefix: \"createTimeForTest could not validate time\",\n\t\t\t\tfailure,\n\t\t\t}),\n\t});\n\tlet now = resolvedCreateOptions.initialNow;\n\tlet nextId = 1;\n\tconst tasks = new Map<number, { at: number; handler: () => void }>();\n\treturn {\n\t\tnow: () => now,\n\t\tsetTimeout(handler, delayMs) {\n\t\t\tconst id = nextId++;\n\t\t\ttasks.set(id, { at: now + Math.max(0, delayMs), handler });\n\t\t\treturn id;\n\t\t},\n\t\tclearTimeout(handle) {\n\t\t\tif (typeof handle === \"number\") {\n\t\t\t\ttasks.delete(handle);\n\t\t\t}\n\t\t},\n\t\tadvance(ms) {\n\t\t\tnow += ms;\n\t\t},\n\t\tflush() {\n\t\t\tlet progressed = true;\n\t\t\twhile (progressed) {\n\t\t\t\tprogressed = false;\n\t\t\t\tconst ready = [...tasks.entries()]\n\t\t\t\t\t.filter(([, task]) => task.at <= now)\n\t\t\t\t\t.sort((a, b) => a[1].at - b[1].at);\n\t\t\t\tfor (const [id, task] of ready) {\n\t\t\t\t\ttasks.delete(id);\n\t\t\t\t\ttask.handler();\n\t\t\t\t\tprogressed = true;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tadvanceAndFlush(ms) {\n\t\t\tthis.advance(ms);\n\t\t\tthis.flush();\n\t\t},\n\t\tget pendingCount() {\n\t\t\treturn tasks.size;\n\t\t},\n\t};\n}\n","import {\n\ttype CreateFoundationEnvironmentOptions,\n\tcreateFoundationEnvironment,\n} from \"../environment/create\";\nimport { type FoundationEnvironment } from \"../environment/types\";\nimport {\n\tcreateProviderIfTokenMissing,\n\tgetSecuritydeptProviderToken,\n\tnotMissingProvider,\n\ttype SecuritydeptProvider,\n} from \"../injection\";\nimport { TIME_TRAIT_TOKEN, type TimeTrait } from \"../scheduling/types\";\nimport {\n\ttype BaseTransportTrait,\n\tTRANSPORT_TRAIT_TOKEN,\n} from \"../transport/types\";\nimport { createTimeForTest } from \"./time\";\n\nexport type EnvironmentCreatorOptions = {\n\tproviders?: readonly SecuritydeptProvider[];\n};\n\nexport type EnvironmentCreator<\n\tTOptions extends EnvironmentCreatorOptions,\n\tTEnvironment extends FoundationEnvironment,\n> = (options: TOptions) => TEnvironment;\n\nexport interface CreateEnvironmentForTestOptions\n\textends Omit<CreateFoundationEnvironmentOptions, \"transport\"> {\n\ttransport?: BaseTransportTrait;\n\ttime?: TimeTrait;\n}\n\nexport type CreateEnvironmentForTestWithBaseOptions<\n\tTBaseOptions extends EnvironmentCreatorOptions,\n\tTEnvironment extends FoundationEnvironment,\n> = Omit<TBaseOptions, \"providers\" | \"transport\" | \"createBaseEnvironment\"> & {\n\tcreateBaseEnvironment: EnvironmentCreator<TBaseOptions, TEnvironment>;\n\ttransport?: BaseTransportTrait;\n\tproviders?: readonly SecuritydeptProvider[];\n};\n\nexport function createEnvironmentForTest(): FoundationEnvironment;\nexport function createEnvironmentForTest(\n\toptions: CreateEnvironmentForTestOptions,\n): FoundationEnvironment;\nexport function createEnvironmentForTest<\n\tTBaseOptions extends EnvironmentCreatorOptions,\n\tTEnvironment extends FoundationEnvironment,\n>(\n\toptions: CreateEnvironmentForTestWithBaseOptions<TBaseOptions, TEnvironment>,\n): TEnvironment;\nexport function createEnvironmentForTest(\n\toptions:\n\t\t| CreateEnvironmentForTestOptions\n\t\t| CreateEnvironmentForTestWithBaseOptions<\n\t\t\t\tEnvironmentCreatorOptions,\n\t\t\t\tFoundationEnvironment\n\t\t > = {},\n): FoundationEnvironment {\n\tconst {\n\t\tcreateBaseEnvironment = createFoundationEnvironment,\n\t\ttransport,\n\t\tproviders = [],\n\t\t...baseOptions\n\t} = options as CreateEnvironmentForTestWithBaseOptions<\n\t\tEnvironmentCreatorOptions,\n\t\tFoundationEnvironment\n\t> &\n\t\tCreateEnvironmentForTestOptions;\n\tconst externalProviderTokens = new Set(\n\t\tproviders.map((provider) => getSecuritydeptProviderToken(provider)),\n\t);\n\tconst testProviders: SecuritydeptProvider[] = [\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tTRANSPORT_TRAIT_TOKEN,\n\t\t\t() => ({\n\t\t\t\tprovide: TRANSPORT_TRAIT_TOKEN,\n\t\t\t\tuseValue: transport ?? createMissingTransportForTest(),\n\t\t\t}),\n\t\t),\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tTIME_TRAIT_TOKEN,\n\t\t\t() => ({\n\t\t\t\tprovide: TIME_TRAIT_TOKEN,\n\t\t\t\tuseValue:\n\t\t\t\t\tbaseOptions.time ?? createTimeForTest({ initialNow: Date.now() }),\n\t\t\t}),\n\t\t),\n\t].filter(notMissingProvider) as SecuritydeptProvider[];\n\n\treturn createBaseEnvironment({\n\t\t...(baseOptions as unknown as Omit<EnvironmentCreatorOptions, \"providers\">),\n\t\tproviders: [...testProviders, ...providers],\n\t});\n}\n\nfunction createMissingTransportForTest(): BaseTransportTrait {\n\treturn {\n\t\tasync execute() {\n\t\t\tthrow new Error(\"Test environment transport was not provided.\");\n\t\t},\n\t};\n}\n","import { type IdleCallbackTrait } from \"../scheduling/types\";\n\nexport interface TestIdleCallbackTrait extends IdleCallbackTrait {\n\tflush(): void;\n\tget pendingCount(): number;\n}\n\nexport function createIdleCallbackForTest(): TestIdleCallbackTrait {\n\tlet nextId = 1;\n\tconst callbacks = new Map<number, () => void>();\n\treturn {\n\t\trequestIdleCallback(callback) {\n\t\t\tconst id = nextId++;\n\t\t\tcallbacks.set(id, callback);\n\t\t\treturn id;\n\t\t},\n\t\tcancelIdleCallback(handle) {\n\t\t\tif (typeof handle === \"number\") {\n\t\t\t\tcallbacks.delete(handle);\n\t\t\t}\n\t\t},\n\t\tflush() {\n\t\t\tconst ready = [...callbacks.entries()];\n\t\t\tcallbacks.clear();\n\t\t\tfor (const [, callback] of ready) {\n\t\t\t\tcallback();\n\t\t\t}\n\t\t},\n\t\tget pendingCount() {\n\t\t\treturn callbacks.size;\n\t\t},\n\t};\n}\n","import { SYMBOL_OBSERVABLE } from \"../compat/observable\";\nimport {\n\ttype EventObserverTrait,\n\ttype EventSubjectTrait,\n\ttype EventSubscriptionTrait,\n} from \"../events/types\";\nimport { type PageLifecycleTrait } from \"../page\";\n\nexport interface TestEventSubjectTrait<T> extends EventSubjectTrait<T> {\n\tget observerCount(): number;\n}\n\nexport interface TestPageLifecycleTrait<TResumeEvent = unknown>\n\textends PageLifecycleTrait<TResumeEvent> {\n\treadonly resume: TestEventSubjectTrait<TResumeEvent>;\n}\n\nexport function createPageLifecycleForTest<\n\tTResumeEvent = unknown,\n>(): TestPageLifecycleTrait<TResumeEvent> {\n\treturn {\n\t\tresume: createEventSubjectForTest<TResumeEvent>(),\n\t};\n}\n\nexport function createEventSubjectForTest<T>(): TestEventSubjectTrait<T> {\n\tconst observers = new Set<Partial<EventObserverTrait<T>>>();\n\tconst stream = {\n\t\tsubscribe(observer) {\n\t\t\tobservers.add(observer);\n\t\t\treturn {\n\t\t\t\tunsubscribe() {\n\t\t\t\t\tobservers.delete(observer);\n\t\t\t\t},\n\t\t\t} satisfies EventSubscriptionTrait;\n\t\t},\n\t\tnext(value) {\n\t\t\tfor (const observer of [...observers]) {\n\t\t\t\tobserver.next?.(value);\n\t\t\t}\n\t\t},\n\t\terror(error) {\n\t\t\tfor (const observer of [...observers]) {\n\t\t\t\tobserver.error?.(error);\n\t\t\t}\n\t\t},\n\t\tcomplete() {\n\t\t\tfor (const observer of [...observers]) {\n\t\t\t\tobserver.complete?.();\n\t\t\t}\n\t\t\tobservers.clear();\n\t\t},\n\t\tget observerCount() {\n\t\t\treturn observers.size;\n\t\t},\n\t\t[SYMBOL_OBSERVABLE]() {\n\t\t\treturn this;\n\t\t},\n\t} satisfies TestEventSubjectTrait<T>;\n\treturn stream;\n}\n","import { ClientError, ClientErrorKind } from \"../errors\";\nimport {\n\tPopupAttachFailureReason,\n\ttype PopupAttachResult,\n\ttype PopupOpenOptions,\n\ttype PopupTrait,\n} from \"../popup\";\n\nexport interface PopupForTestOpenCall {\n\turl: string;\n\toptions?: PopupOpenOptions;\n}\n\nexport interface PopupForTestCreateOptions {\n\tattachResult?: PopupAttachResult;\n}\n\nexport interface TestPopupTrait extends PopupTrait {\n\treadonly openCalls: readonly PopupForTestOpenCall[];\n\tsetAttachResult(result: PopupAttachResult): void;\n}\n\nexport function createPopupForTest(\n\toptions: PopupForTestCreateOptions = {},\n): TestPopupTrait {\n\tconst openCalls: PopupForTestOpenCall[] = [];\n\tlet attachResult = options.attachResult ?? createMissingOpenerAttachFailure();\n\treturn {\n\t\topen(url, openOptions) {\n\t\t\topenCalls.push({ url, options: openOptions });\n\t\t\tthrow new Error(\"Test popup open was not configured.\");\n\t\t},\n\t\tattach() {\n\t\t\treturn attachResult;\n\t\t},\n\t\tget openCalls() {\n\t\t\treturn openCalls;\n\t\t},\n\t\tsetAttachResult(result) {\n\t\t\tattachResult = result;\n\t\t},\n\t};\n}\n\nfunction createMissingOpenerAttachFailure(): PopupAttachResult {\n\treturn {\n\t\tkind: \"failure\",\n\t\treason: PopupAttachFailureReason.MissingOpener,\n\t\terror: new ClientError({\n\t\t\tkind: ClientErrorKind.Configuration,\n\t\t\tcode: \"test.popup.missing_opener\",\n\t\t\tsource: \"test\",\n\t\t\tmessage: \"Test popup attach was not configured.\",\n\t\t}),\n\t};\n}\n","import {\n\tRouterNavigationMode,\n\ttype RouterNavigationRequest,\n\ttype RouterTrait,\n} from \"../router/router\";\nimport { UriReferenceString } from \"../struct/uri-string\";\n\nexport interface RouterForTestCreateOptions {\n\tcurrentUrl?: string | UriReferenceString | null;\n\tonNavigate?: (request: RouterNavigationRequest) => void | Promise<void>;\n}\n\nexport interface TestRouterTrait extends RouterTrait {\n\treadonly navigations: readonly RouterNavigationRequest[];\n\tsetCurrentUrl(url: string | UriReferenceString | null): void;\n}\n\nexport function createRouterForTest(\n\toptions: RouterForTestCreateOptions = {},\n): TestRouterTrait {\n\tlet currentUrl =\n\t\toptions.currentUrl == null\n\t\t\t? null\n\t\t\t: UriReferenceString.parse(options.currentUrl);\n\tconst navigations: RouterNavigationRequest[] = [];\n\treturn {\n\t\tcurrentUrl() {\n\t\t\treturn currentUrl;\n\t\t},\n\t\tsetCurrentUrl(url) {\n\t\t\tcurrentUrl = url == null ? null : UriReferenceString.parse(url);\n\t\t},\n\t\tget navigations() {\n\t\t\treturn navigations;\n\t\t},\n\t\tasync navigate(request) {\n\t\t\tnavigations.push(request);\n\t\t\tif (\n\t\t\t\trequest.mode === RouterNavigationMode.Push ||\n\t\t\t\trequest.mode === RouterNavigationMode.Replace\n\t\t\t) {\n\t\t\t\tcurrentUrl = request.url;\n\t\t\t}\n\t\t\tawait options.onNavigate?.(request);\n\t\t},\n\t};\n}\n","import { type as defineType } from \"arktype\";\nimport { type EnvironmentValidators } from \"../environment/types\";\nimport { createInMemoryRecordStore } from \"../storage/memory-store\";\nimport { type SyncStorageTrait } from \"../storage/types\";\nimport {\n\tthrowValidationClientError,\n\tvalidateTraitInput,\n\ttype WithTraitInputValidator,\n} from \"../validation\";\n\nexport interface StorageForTestCreateOptions {\n\tinitialEntries?: Record<string, string>;\n\tvalidatorKey?: \"persistentStorage\" | \"sessionStorage\";\n}\n\nconst StorageForTestCreateOptionsSchema = defineType({\n\tinitialEntries: \"object\",\n\tvalidatorKey: \"'persistentStorage' | 'sessionStorage'\",\n});\n\nexport function createStorageForTest(\n\toptions: StorageForTestCreateOptions &\n\t\tWithTraitInputValidator<\n\t\t\tPick<EnvironmentValidators, \"persistentStorage\" | \"sessionStorage\">\n\t\t> = {},\n): SyncStorageTrait {\n\tconst { validators, ...createOptions } = options;\n\tconst validatorKey = options.validatorKey ?? \"persistentStorage\";\n\tconst resolvedCreateOptions = {\n\t\tinitialEntries: createOptions.initialEntries ?? {},\n\t\tvalidatorKey,\n\t};\n\tvalidateTraitInput({\n\t\tvalue: resolvedCreateOptions,\n\t\tbundledSchema: StorageForTestCreateOptionsSchema,\n\t\tvalidator: validators?.[validatorKey],\n\t\tonInvalid: (failure) =>\n\t\t\tthrowValidationClientError({\n\t\t\t\tcode: \"test.storage.invalid_options\",\n\t\t\t\tsource: \"test\",\n\t\t\t\tmessagePrefix: `createStorageForTest could not validate ${validatorKey}`,\n\t\t\t\tfailure,\n\t\t\t}),\n\t});\n\tconst storage = createInMemoryRecordStore();\n\tfor (const [key, value] of Object.entries(\n\t\tresolvedCreateOptions.initialEntries,\n\t)) {\n\t\tstorage.set(key, value);\n\t}\n\treturn storage;\n}\n","import {\n\ttype BaseTransportTrait,\n\ttype HttpRequest,\n\ttype HttpResponse,\n} from \"../transport/types\";\n\nexport interface TransportForTestRoute {\n\tpredicate: (request: HttpRequest) => boolean;\n\thandler: (request: HttpRequest) => HttpResponse | Promise<HttpResponse>;\n}\n\nexport interface TransportForTestCreateOptions {\n\troutes?: readonly TransportForTestRoute[];\n\tfallback?: HttpResponse;\n}\n\nexport interface TestTransportTrait extends BaseTransportTrait {\n\ton(\n\t\tpredicate: (request: HttpRequest) => boolean,\n\t\thandler: (request: HttpRequest) => HttpResponse | Promise<HttpResponse>,\n\t): this;\n\tonRequest(method: string, urlPrefix: string, response: HttpResponse): this;\n\tsetFallback(response: HttpResponse): this;\n\treset(): void;\n\treadonly history: readonly HttpRequest[];\n}\n\nexport function createTransportForTest(\n\toptions: TransportForTestCreateOptions = {},\n): TestTransportTrait {\n\tconst routes = [...(options.routes ?? [])];\n\tconst history: HttpRequest[] = [];\n\tlet fallback = options.fallback ?? createNotFoundResponseForTest();\n\treturn {\n\t\ton(predicate, handler) {\n\t\t\troutes.push({ predicate, handler });\n\t\t\treturn this;\n\t\t},\n\t\tonRequest(method, urlPrefix, response) {\n\t\t\treturn this.on(\n\t\t\t\t(request) =>\n\t\t\t\t\trequest.method.toUpperCase() === method.toUpperCase() &&\n\t\t\t\t\trequest.url.startsWith(urlPrefix),\n\t\t\t\t() => response,\n\t\t\t);\n\t\t},\n\t\tsetFallback(response) {\n\t\t\tfallback = response;\n\t\t\treturn this;\n\t\t},\n\t\treset() {\n\t\t\troutes.length = 0;\n\t\t\thistory.length = 0;\n\t\t},\n\t\tget history() {\n\t\t\treturn history;\n\t\t},\n\t\tasync execute(request) {\n\t\t\thistory.push(request);\n\t\t\tfor (const route of routes) {\n\t\t\t\tif (route.predicate(request)) {\n\t\t\t\t\treturn route.handler(request);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fallback;\n\t\t},\n\t};\n}\n\nfunction createNotFoundResponseForTest(): HttpResponse {\n\treturn {\n\t\tstatus: 404,\n\t\theaders: {},\n\t\tbody: { error: \"No matching test transport route\" },\n\t};\n}\n"],"mappings":"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"}
@@ -181,7 +181,8 @@ var UriString = class UriString extends UriReferenceString {
181
181
  static tryParse(input) {
182
182
  if (input instanceof UriString) return input;
183
183
  try {
184
- return new UriString(input, new URL(input));
184
+ const parsed = new URL(input);
185
+ return new UriString(input, parsed);
185
186
  } catch {
186
187
  return null;
187
188
  }
@@ -260,7 +261,8 @@ var UriRelativeString = class UriRelativeString extends UriReferenceString {
260
261
  return null;
261
262
  } catch {}
262
263
  try {
263
- return new UriRelativeString(input, new URL(input, RELATIVE_URI_SENTINEL_BASE));
264
+ const parsed = new URL(input, RELATIVE_URI_SENTINEL_BASE);
265
+ return new UriRelativeString(input, parsed);
264
266
  } catch {
265
267
  return null;
266
268
  }
@@ -295,4 +297,4 @@ var UriRelativeString = class UriRelativeString extends UriReferenceString {
295
297
  //#endregion
296
298
  export { UriString as i, UriReferenceString as n, UriRelativeString as r, UriParseError as t };
297
299
 
298
- //# sourceMappingURL=uri-string-BfnIT4gJ.mjs.map
300
+ //# sourceMappingURL=uri-string-BPNbIMgv.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"uri-string-BfnIT4gJ.mjs","names":[],"sources":["../src/struct/uri-string.ts"],"sourcesContent":["// Sentinel base used internally to parse relative URIs via the URL constructor.\n// The specific value is never exposed; it only serves as a structural anchor\n// so that `new URL(relativeInput, SENTINEL_BASE)` succeeds.\nconst RELATIVE_URI_SENTINEL_BASE = \"http://localhost\";\n\n/**\n * Thrown when a string cannot be parsed into the requested URI variant.\n */\nexport class UriParseError extends Error {\n\treadonly input: string;\n\treadonly kind: string;\n\n\tconstructor(input: string, kind: string, options?: ErrorOptions) {\n\t\tsuper(`Failed to parse \"${input}\" as ${kind}`, options);\n\t\tthis.name = \"UriParseError\";\n\t\tthis.input = input;\n\t\tthis.kind = kind;\n\t}\n}\n\n/**\n * The relative components of a URL — pathname, search, and hash.\n *\n * All fields use the same format as the native `URL` accessors:\n * - `pathname` starts with `/` (e.g. `\"/path\"`).\n * - `search` includes the leading `?` when present (e.g. `\"?q=1\"`).\n * - `hash` includes the leading `#` when present (e.g. `\"#section\"`).\n */\nexport interface UriRelativeParts {\n\treadonly pathname: string;\n\treadonly search: string;\n\treadonly hash: string;\n}\n\n/**\n * Minimal structural type for URI fragment parsing.\n *\n * Matches any value that exposes a URL-style `hash` accessor — for example\n * `URL`, `Location`, or {@link UriReferenceString}.\n */\nexport interface UriFragmentPart {\n\treadonly hash: string;\n}\n\n/**\n * Minimal structural type for URI reference parsing.\n *\n * Matches any value that can be serialized via `toString()` — for example\n * native `URL`, `Location`, or {@link UriReferenceString}.\n */\nexport interface UriReferenceStringLike {\n\ttoString(): string;\n}\n\nexport type UriReferenceStringInput = string | UriReferenceStringLike;\n\nexport type UriSearchParamsInit = NonNullable<\n\tConstructorParameters<typeof URLSearchParams>[0]\n>;\n\n// ---------------------------------------------------------------------------\n// UriReferenceString — the URI-reference supertype (absolute | relative)\n// ---------------------------------------------------------------------------\n\n/**\n * Immutable wrapper around a URI-reference string.\n *\n * A URI-reference (RFC 3986 §4.1) is either an absolute URI or a relative\n * reference. Concrete subclasses {@link UriString} and\n * {@link UriRelativeString} carry the additional type-level guarantee of\n * which variant they hold.\n *\n * Instances created via `UriReferenceString.parse` / `.tryParse` are always\n * one of the two subclasses, so {@link isAbsolute} and {@link isRelative}\n * narrow correctly.\n */\nexport class UriReferenceString {\n\t/** The original, unmodified input string. */\n\tprotected readonly _raw: string;\n\n\t/**\n\t * Eagerly parsed URL helper.\n\t *\n\t * - Absolute URIs: `new URL(raw)`.\n\t * - Relative URIs: `new URL(raw, RELATIVE_URI_SENTINEL_BASE)`.\n\t *\n\t * For relative URIs the scheme and host originate from the sentinel and\n\t * MUST NOT be used for origin-sensitive operations.\n\t */\n\tprotected readonly _parsed: URL;\n\n\tprotected readonly _isAbsolute: boolean;\n\n\tprotected constructor(raw: string, parsed: URL, isAbsolute: boolean) {\n\t\tthis._raw = raw;\n\t\tthis._parsed = parsed;\n\t\tthis._isAbsolute = isAbsolute;\n\t}\n\n\t// ---- Static factories ------------------------------------------------\n\n\t/**\n\t * Parse any valid URI reference (absolute or relative).\n\t *\n\t * The returned instance is always a {@link UriString} or\n\t * {@link UriRelativeString}.\n\t *\n\t * @throws {UriParseError} when the input is not a valid URI reference.\n\t */\n\tstatic parse(input: UriReferenceStringInput): UriReferenceString {\n\t\tconst result = UriReferenceString.tryParse(input);\n\t\tif (!result) {\n\t\t\tthrow new UriParseError(\n\t\t\t\ttypeof input === \"string\" ? input : input.toString(),\n\t\t\t\t\"URI reference\",\n\t\t\t);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Try to parse a URI reference, returning `null` on failure.\n\t *\n\t * The returned instance is always a {@link UriString} or\n\t * {@link UriRelativeString}.\n\t */\n\tstatic tryParse(input: UriReferenceStringInput): UriReferenceString | null {\n\t\tif (input instanceof UriReferenceString) {\n\t\t\treturn input;\n\t\t}\n\t\tconst source = typeof input === \"string\" ? input : input.toString();\n\t\treturn UriString.tryParse(source) ?? UriRelativeString.tryParse(source);\n\t}\n\n\t/** Create from a native `URL`. Always produces a {@link UriString}. */\n\tstatic fromURL(url: URL): UriString {\n\t\treturn UriString.fromURL(url);\n\t}\n\n\t/**\n\t * Create from the relative components of a URL.\n\t * Always produces a {@link UriRelativeString}.\n\t */\n\tstatic fromURLRelative(parts: UriRelativeParts): UriRelativeString {\n\t\treturn UriRelativeString.fromURLRelative(parts);\n\t}\n\n\t// ---- Accessors -------------------------------------------------------\n\n\t/** The original input string. */\n\tget raw(): string {\n\t\treturn this._raw;\n\t}\n\n\tget pathname(): string {\n\t\treturn this._parsed.pathname;\n\t}\n\n\tget hash(): string {\n\t\treturn this._parsed.hash;\n\t}\n\n\tget search(): string {\n\t\treturn this._parsed.search;\n\t}\n\n\tget searchParams(): URLSearchParams {\n\t\treturn this._parsed.searchParams;\n\t}\n\n\t// ---- Type narrowing --------------------------------------------------\n\n\t/** Type-guard: narrows to {@link UriString} when the reference is absolute. */\n\tisAbsolute(): this is UriString {\n\t\treturn this._isAbsolute;\n\t}\n\n\t/** Type-guard: narrows to {@link UriRelativeString} when the reference is relative. */\n\tisRelative(): this is UriRelativeString {\n\t\treturn !this._isAbsolute;\n\t}\n\n\t/** Narrow to {@link UriString} or return `null`. */\n\tasAbsolute(): UriString | null {\n\t\treturn this.isAbsolute() ? this : null;\n\t}\n\n\t/** Narrow to {@link UriRelativeString} or return `null`. */\n\tasRelative(): UriRelativeString | null {\n\t\treturn this.isRelative() ? this : null;\n\t}\n\n\t// ---- Mutation (immutable) --------------------------------------------\n\n\t/**\n\t * Returns a new instance with `hash` replaced.\n\t *\n\t * @param value URL-style hash, including a leading `#` when non-empty.\n\t */\n\tsetHash(value: string): this {\n\t\tconst hashIndex = this._raw.indexOf(\"#\");\n\t\tconst base = hashIndex >= 0 ? this._raw.slice(0, hashIndex) : this._raw;\n\t\treturn UriReferenceString.parse(`${base}${value}`) as this;\n\t}\n\n\t/** Returns a new instance with the complete query parameter set replaced. */\n\tsetSearchParams(init?: UriSearchParamsInit): this {\n\t\tconst hashIndex = this._raw.indexOf(\"#\");\n\t\tconst hash = hashIndex >= 0 ? this._raw.slice(hashIndex) : \"\";\n\t\tconst withoutHash =\n\t\t\thashIndex >= 0 ? this._raw.slice(0, hashIndex) : this._raw;\n\t\tconst searchIndex = withoutHash.indexOf(\"?\");\n\t\tconst base =\n\t\t\tsearchIndex >= 0 ? withoutHash.slice(0, searchIndex) : withoutHash;\n\t\tconst search = new URLSearchParams(init).toString();\n\t\treturn UriReferenceString.parse(\n\t\t\t`${base}${search.length > 0 ? `?${search}` : \"\"}${hash}`,\n\t\t) as this;\n\t}\n\n\t// ---- Conversion ------------------------------------------------------\n\n\t/**\n\t * Convert to a native `URL`.\n\t *\n\t * A `base` is required when the reference is relative; it is ignored\n\t * for absolute references.\n\t *\n\t * @throws {TypeError} when the reference is relative and no base is provided.\n\t */\n\ttoURL(base?: string | URL): URL {\n\t\tif (this._isAbsolute) {\n\t\t\treturn new URL(this._parsed.href);\n\t\t}\n\t\tif (base == null) {\n\t\t\tthrow new TypeError(\n\t\t\t\t\"A base URL is required to convert a relative URI reference to a URL\",\n\t\t\t);\n\t\t}\n\t\treturn new URL(this._raw, base);\n\t}\n\n\ttoString(): string {\n\t\treturn this._raw;\n\t}\n\n\tvalueOf(): string {\n\t\treturn this._raw;\n\t}\n\n\ttoJSON(): string {\n\t\treturn this._raw;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// UriString — absolute URI (must include a scheme)\n// ---------------------------------------------------------------------------\n\n/**\n * Immutable wrapper around an absolute URI string.\n *\n * An absolute URI (RFC 3986 §4.3) always starts with a scheme component\n * (e.g. `https://example.com/path`).\n */\nexport class UriString extends UriReferenceString {\n\tprotected constructor(raw: string, parsed: URL) {\n\t\tsuper(raw, parsed, true);\n\t}\n\n\t// ---- Static factories ------------------------------------------------\n\n\t/**\n\t * Parse an absolute URI string.\n\t *\n\t * @throws {UriParseError} when the input is not a valid absolute URI.\n\t */\n\tstatic override parse(input: string): UriString {\n\t\tconst result = UriString.tryParse(input);\n\t\tif (!result) {\n\t\t\tthrow new UriParseError(input, \"absolute URI\");\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Try to parse an absolute URI, returning `null` if the input is not\n\t * a valid absolute URI.\n\t */\n\tstatic override tryParse(input: string | UriString): UriString | null {\n\t\tif (input instanceof UriString) {\n\t\t\treturn input;\n\t\t}\n\t\ttry {\n\t\t\tconst parsed = new URL(input);\n\t\t\treturn new UriString(input, parsed);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/** Create from a native `URL`, using its `href` as the raw string. */\n\tstatic override fromURL(url: URL): UriString {\n\t\treturn new UriString(url.href, new URL(url.href));\n\t}\n\n\t/**\n\t * Not supported — relative parts cannot produce an absolute URI.\n\t *\n\t * @throws {TypeError} unconditionally.\n\t */\n\tstatic override fromURLRelative(_parts: UriRelativeParts): never {\n\t\tthrow new TypeError(\n\t\t\t\"Cannot create a UriString from relative URL parts. \" +\n\t\t\t\t\"Use UriRelativeString.fromURLRelative() or UriReferenceString.fromURLRelative() instead.\",\n\t\t);\n\t}\n\n\t// ---- Accessors -------------------------------------------------------\n\n\tget host(): string {\n\t\treturn this._parsed.host;\n\t}\n\n\tget hostname(): string {\n\t\treturn this._parsed.hostname;\n\t}\n\n\tget origin(): string {\n\t\treturn this._parsed.origin;\n\t}\n\n\tget password(): string {\n\t\treturn this._parsed.password;\n\t}\n\n\tget port(): string {\n\t\treturn this._parsed.port;\n\t}\n\n\tget protocol(): string {\n\t\treturn this._parsed.protocol;\n\t}\n\n\tget username(): string {\n\t\treturn this._parsed.username;\n\t}\n\n\t// ---- Conversion ------------------------------------------------------\n\n\t/** Convert to a native `URL`. No base is required for absolute URIs. */\n\toverride toURL(): URL {\n\t\treturn new URL(this.raw);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// UriRelativeString — relative URI reference (no scheme)\n// ---------------------------------------------------------------------------\n\n/**\n * Immutable wrapper around a relative URI reference string.\n *\n * A relative reference (RFC 3986 §4.2) has no scheme and must be resolved\n * against a base URI to obtain an absolute URI.\n *\n * Internally, the raw string is parsed against a sentinel base\n * (`http://localhost`) to enable eager validation and URL-component\n * extraction. The sentinel origin is never leaked through the public API.\n */\nexport class UriRelativeString extends UriReferenceString {\n\tprotected constructor(raw: string, parsed: URL) {\n\t\tsuper(raw, parsed, false);\n\t}\n\n\t// ---- Static factories ------------------------------------------------\n\n\t/**\n\t * Parse a relative URI reference.\n\t *\n\t * @throws {UriParseError} when the input is absolute or not a valid\n\t * relative URI reference.\n\t */\n\tstatic override parse(input: string): UriRelativeString {\n\t\tconst result = UriRelativeString.tryParse(input);\n\t\tif (!result) {\n\t\t\tthrow new UriParseError(input, \"relative URI reference\");\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Try to parse a relative URI reference, returning `null` if the input\n\t * is an absolute URI or otherwise invalid.\n\t */\n\tstatic override tryParse(\n\t\tinput: string | UriRelativeString,\n\t): UriRelativeString | null {\n\t\tif (input instanceof UriRelativeString) {\n\t\t\treturn input;\n\t\t}\n\t\t// Reject absolute URIs — they belong in UriString.\n\t\ttry {\n\t\t\tnew URL(input);\n\t\t\treturn null;\n\t\t} catch {\n\t\t\t// Not absolute — fall through to relative parsing.\n\t\t}\n\t\ttry {\n\t\t\tconst parsed = new URL(input, RELATIVE_URI_SENTINEL_BASE);\n\t\t\treturn new UriRelativeString(input, parsed);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Not supported — a native `URL` is always absolute and cannot be\n\t * represented as a relative URI reference.\n\t *\n\t * @throws {TypeError} unconditionally.\n\t */\n\tstatic override fromURL(_url: URL): never {\n\t\tthrow new TypeError(\n\t\t\t\"Cannot create a UriRelativeString from a URL; URLs are always absolute. \" +\n\t\t\t\t\"Use UriString.fromURL() or UriReferenceString.fromURL() instead.\",\n\t\t);\n\t}\n\n\t/**\n\t * Create from the relative components of a URL.\n\t *\n\t * Concatenates `pathname + search + hash` into a relative URI string.\n\t */\n\tstatic override fromURLRelative(parts: UriRelativeParts): UriRelativeString {\n\t\tconst raw = `${parts.pathname}${parts.search}${parts.hash}`;\n\t\treturn UriRelativeString.parse(raw);\n\t}\n\n\t// ---- Conversion ------------------------------------------------------\n\n\t/**\n\t * Convert to a native `URL` by resolving against the given base.\n\t *\n\t * @param base - The base URL to resolve against (required).\n\t */\n\toverride toURL(base: string | URL): URL {\n\t\treturn new URL(this.raw, base);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"uri-string-BPNbIMgv.mjs","names":[],"sources":["../src/struct/uri-string.ts"],"sourcesContent":["// Sentinel base used internally to parse relative URIs via the URL constructor.\n// The specific value is never exposed; it only serves as a structural anchor\n// so that `new URL(relativeInput, SENTINEL_BASE)` succeeds.\nconst RELATIVE_URI_SENTINEL_BASE = \"http://localhost\";\n\n/**\n * Thrown when a string cannot be parsed into the requested URI variant.\n */\nexport class UriParseError extends Error {\n\treadonly input: string;\n\treadonly kind: string;\n\n\tconstructor(input: string, kind: string, options?: ErrorOptions) {\n\t\tsuper(`Failed to parse \"${input}\" as ${kind}`, options);\n\t\tthis.name = \"UriParseError\";\n\t\tthis.input = input;\n\t\tthis.kind = kind;\n\t}\n}\n\n/**\n * The relative components of a URL — pathname, search, and hash.\n *\n * All fields use the same format as the native `URL` accessors:\n * - `pathname` starts with `/` (e.g. `\"/path\"`).\n * - `search` includes the leading `?` when present (e.g. `\"?q=1\"`).\n * - `hash` includes the leading `#` when present (e.g. `\"#section\"`).\n */\nexport interface UriRelativeParts {\n\treadonly pathname: string;\n\treadonly search: string;\n\treadonly hash: string;\n}\n\n/**\n * Minimal structural type for URI fragment parsing.\n *\n * Matches any value that exposes a URL-style `hash` accessor — for example\n * `URL`, `Location`, or {@link UriReferenceString}.\n */\nexport interface UriFragmentPart {\n\treadonly hash: string;\n}\n\n/**\n * Minimal structural type for URI reference parsing.\n *\n * Matches any value that can be serialized via `toString()` — for example\n * native `URL`, `Location`, or {@link UriReferenceString}.\n */\nexport interface UriReferenceStringLike {\n\ttoString(): string;\n}\n\nexport type UriReferenceStringInput = string | UriReferenceStringLike;\n\nexport type UriSearchParamsInit = NonNullable<\n\tConstructorParameters<typeof URLSearchParams>[0]\n>;\n\n// ---------------------------------------------------------------------------\n// UriReferenceString — the URI-reference supertype (absolute | relative)\n// ---------------------------------------------------------------------------\n\n/**\n * Immutable wrapper around a URI-reference string.\n *\n * A URI-reference (RFC 3986 §4.1) is either an absolute URI or a relative\n * reference. Concrete subclasses {@link UriString} and\n * {@link UriRelativeString} carry the additional type-level guarantee of\n * which variant they hold.\n *\n * Instances created via `UriReferenceString.parse` / `.tryParse` are always\n * one of the two subclasses, so {@link isAbsolute} and {@link isRelative}\n * narrow correctly.\n */\nexport class UriReferenceString {\n\t/** The original, unmodified input string. */\n\tprotected readonly _raw: string;\n\n\t/**\n\t * Eagerly parsed URL helper.\n\t *\n\t * - Absolute URIs: `new URL(raw)`.\n\t * - Relative URIs: `new URL(raw, RELATIVE_URI_SENTINEL_BASE)`.\n\t *\n\t * For relative URIs the scheme and host originate from the sentinel and\n\t * MUST NOT be used for origin-sensitive operations.\n\t */\n\tprotected readonly _parsed: URL;\n\n\tprotected readonly _isAbsolute: boolean;\n\n\tprotected constructor(raw: string, parsed: URL, isAbsolute: boolean) {\n\t\tthis._raw = raw;\n\t\tthis._parsed = parsed;\n\t\tthis._isAbsolute = isAbsolute;\n\t}\n\n\t// ---- Static factories ------------------------------------------------\n\n\t/**\n\t * Parse any valid URI reference (absolute or relative).\n\t *\n\t * The returned instance is always a {@link UriString} or\n\t * {@link UriRelativeString}.\n\t *\n\t * @throws {UriParseError} when the input is not a valid URI reference.\n\t */\n\tstatic parse(input: UriReferenceStringInput): UriReferenceString {\n\t\tconst result = UriReferenceString.tryParse(input);\n\t\tif (!result) {\n\t\t\tthrow new UriParseError(\n\t\t\t\ttypeof input === \"string\" ? input : input.toString(),\n\t\t\t\t\"URI reference\",\n\t\t\t);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Try to parse a URI reference, returning `null` on failure.\n\t *\n\t * The returned instance is always a {@link UriString} or\n\t * {@link UriRelativeString}.\n\t */\n\tstatic tryParse(input: UriReferenceStringInput): UriReferenceString | null {\n\t\tif (input instanceof UriReferenceString) {\n\t\t\treturn input;\n\t\t}\n\t\tconst source = typeof input === \"string\" ? input : input.toString();\n\t\treturn UriString.tryParse(source) ?? UriRelativeString.tryParse(source);\n\t}\n\n\t/** Create from a native `URL`. Always produces a {@link UriString}. */\n\tstatic fromURL(url: URL): UriString {\n\t\treturn UriString.fromURL(url);\n\t}\n\n\t/**\n\t * Create from the relative components of a URL.\n\t * Always produces a {@link UriRelativeString}.\n\t */\n\tstatic fromURLRelative(parts: UriRelativeParts): UriRelativeString {\n\t\treturn UriRelativeString.fromURLRelative(parts);\n\t}\n\n\t// ---- Accessors -------------------------------------------------------\n\n\t/** The original input string. */\n\tget raw(): string {\n\t\treturn this._raw;\n\t}\n\n\tget pathname(): string {\n\t\treturn this._parsed.pathname;\n\t}\n\n\tget hash(): string {\n\t\treturn this._parsed.hash;\n\t}\n\n\tget search(): string {\n\t\treturn this._parsed.search;\n\t}\n\n\tget searchParams(): URLSearchParams {\n\t\treturn this._parsed.searchParams;\n\t}\n\n\t// ---- Type narrowing --------------------------------------------------\n\n\t/** Type-guard: narrows to {@link UriString} when the reference is absolute. */\n\tisAbsolute(): this is UriString {\n\t\treturn this._isAbsolute;\n\t}\n\n\t/** Type-guard: narrows to {@link UriRelativeString} when the reference is relative. */\n\tisRelative(): this is UriRelativeString {\n\t\treturn !this._isAbsolute;\n\t}\n\n\t/** Narrow to {@link UriString} or return `null`. */\n\tasAbsolute(): UriString | null {\n\t\treturn this.isAbsolute() ? this : null;\n\t}\n\n\t/** Narrow to {@link UriRelativeString} or return `null`. */\n\tasRelative(): UriRelativeString | null {\n\t\treturn this.isRelative() ? this : null;\n\t}\n\n\t// ---- Mutation (immutable) --------------------------------------------\n\n\t/**\n\t * Returns a new instance with `hash` replaced.\n\t *\n\t * @param value URL-style hash, including a leading `#` when non-empty.\n\t */\n\tsetHash(value: string): this {\n\t\tconst hashIndex = this._raw.indexOf(\"#\");\n\t\tconst base = hashIndex >= 0 ? this._raw.slice(0, hashIndex) : this._raw;\n\t\treturn UriReferenceString.parse(`${base}${value}`) as this;\n\t}\n\n\t/** Returns a new instance with the complete query parameter set replaced. */\n\tsetSearchParams(init?: UriSearchParamsInit): this {\n\t\tconst hashIndex = this._raw.indexOf(\"#\");\n\t\tconst hash = hashIndex >= 0 ? this._raw.slice(hashIndex) : \"\";\n\t\tconst withoutHash =\n\t\t\thashIndex >= 0 ? this._raw.slice(0, hashIndex) : this._raw;\n\t\tconst searchIndex = withoutHash.indexOf(\"?\");\n\t\tconst base =\n\t\t\tsearchIndex >= 0 ? withoutHash.slice(0, searchIndex) : withoutHash;\n\t\tconst search = new URLSearchParams(init).toString();\n\t\treturn UriReferenceString.parse(\n\t\t\t`${base}${search.length > 0 ? `?${search}` : \"\"}${hash}`,\n\t\t) as this;\n\t}\n\n\t// ---- Conversion ------------------------------------------------------\n\n\t/**\n\t * Convert to a native `URL`.\n\t *\n\t * A `base` is required when the reference is relative; it is ignored\n\t * for absolute references.\n\t *\n\t * @throws {TypeError} when the reference is relative and no base is provided.\n\t */\n\ttoURL(base?: string | URL): URL {\n\t\tif (this._isAbsolute) {\n\t\t\treturn new URL(this._parsed.href);\n\t\t}\n\t\tif (base == null) {\n\t\t\tthrow new TypeError(\n\t\t\t\t\"A base URL is required to convert a relative URI reference to a URL\",\n\t\t\t);\n\t\t}\n\t\treturn new URL(this._raw, base);\n\t}\n\n\ttoString(): string {\n\t\treturn this._raw;\n\t}\n\n\tvalueOf(): string {\n\t\treturn this._raw;\n\t}\n\n\ttoJSON(): string {\n\t\treturn this._raw;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// UriString — absolute URI (must include a scheme)\n// ---------------------------------------------------------------------------\n\n/**\n * Immutable wrapper around an absolute URI string.\n *\n * An absolute URI (RFC 3986 §4.3) always starts with a scheme component\n * (e.g. `https://example.com/path`).\n */\nexport class UriString extends UriReferenceString {\n\tprotected constructor(raw: string, parsed: URL) {\n\t\tsuper(raw, parsed, true);\n\t}\n\n\t// ---- Static factories ------------------------------------------------\n\n\t/**\n\t * Parse an absolute URI string.\n\t *\n\t * @throws {UriParseError} when the input is not a valid absolute URI.\n\t */\n\tstatic override parse(input: string): UriString {\n\t\tconst result = UriString.tryParse(input);\n\t\tif (!result) {\n\t\t\tthrow new UriParseError(input, \"absolute URI\");\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Try to parse an absolute URI, returning `null` if the input is not\n\t * a valid absolute URI.\n\t */\n\tstatic override tryParse(input: string | UriString): UriString | null {\n\t\tif (input instanceof UriString) {\n\t\t\treturn input;\n\t\t}\n\t\ttry {\n\t\t\tconst parsed = new URL(input);\n\t\t\treturn new UriString(input, parsed);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/** Create from a native `URL`, using its `href` as the raw string. */\n\tstatic override fromURL(url: URL): UriString {\n\t\treturn new UriString(url.href, new URL(url.href));\n\t}\n\n\t/**\n\t * Not supported — relative parts cannot produce an absolute URI.\n\t *\n\t * @throws {TypeError} unconditionally.\n\t */\n\tstatic override fromURLRelative(_parts: UriRelativeParts): never {\n\t\tthrow new TypeError(\n\t\t\t\"Cannot create a UriString from relative URL parts. \" +\n\t\t\t\t\"Use UriRelativeString.fromURLRelative() or UriReferenceString.fromURLRelative() instead.\",\n\t\t);\n\t}\n\n\t// ---- Accessors -------------------------------------------------------\n\n\tget host(): string {\n\t\treturn this._parsed.host;\n\t}\n\n\tget hostname(): string {\n\t\treturn this._parsed.hostname;\n\t}\n\n\tget origin(): string {\n\t\treturn this._parsed.origin;\n\t}\n\n\tget password(): string {\n\t\treturn this._parsed.password;\n\t}\n\n\tget port(): string {\n\t\treturn this._parsed.port;\n\t}\n\n\tget protocol(): string {\n\t\treturn this._parsed.protocol;\n\t}\n\n\tget username(): string {\n\t\treturn this._parsed.username;\n\t}\n\n\t// ---- Conversion ------------------------------------------------------\n\n\t/** Convert to a native `URL`. No base is required for absolute URIs. */\n\toverride toURL(): URL {\n\t\treturn new URL(this.raw);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// UriRelativeString — relative URI reference (no scheme)\n// ---------------------------------------------------------------------------\n\n/**\n * Immutable wrapper around a relative URI reference string.\n *\n * A relative reference (RFC 3986 §4.2) has no scheme and must be resolved\n * against a base URI to obtain an absolute URI.\n *\n * Internally, the raw string is parsed against a sentinel base\n * (`http://localhost`) to enable eager validation and URL-component\n * extraction. The sentinel origin is never leaked through the public API.\n */\nexport class UriRelativeString extends UriReferenceString {\n\tprotected constructor(raw: string, parsed: URL) {\n\t\tsuper(raw, parsed, false);\n\t}\n\n\t// ---- Static factories ------------------------------------------------\n\n\t/**\n\t * Parse a relative URI reference.\n\t *\n\t * @throws {UriParseError} when the input is absolute or not a valid\n\t * relative URI reference.\n\t */\n\tstatic override parse(input: string): UriRelativeString {\n\t\tconst result = UriRelativeString.tryParse(input);\n\t\tif (!result) {\n\t\t\tthrow new UriParseError(input, \"relative URI reference\");\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Try to parse a relative URI reference, returning `null` if the input\n\t * is an absolute URI or otherwise invalid.\n\t */\n\tstatic override tryParse(\n\t\tinput: string | UriRelativeString,\n\t): UriRelativeString | null {\n\t\tif (input instanceof UriRelativeString) {\n\t\t\treturn input;\n\t\t}\n\t\t// Reject absolute URIs — they belong in UriString.\n\t\ttry {\n\t\t\tnew URL(input);\n\t\t\treturn null;\n\t\t} catch {\n\t\t\t// Not absolute — fall through to relative parsing.\n\t\t}\n\t\ttry {\n\t\t\tconst parsed = new URL(input, RELATIVE_URI_SENTINEL_BASE);\n\t\t\treturn new UriRelativeString(input, parsed);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Not supported — a native `URL` is always absolute and cannot be\n\t * represented as a relative URI reference.\n\t *\n\t * @throws {TypeError} unconditionally.\n\t */\n\tstatic override fromURL(_url: URL): never {\n\t\tthrow new TypeError(\n\t\t\t\"Cannot create a UriRelativeString from a URL; URLs are always absolute. \" +\n\t\t\t\t\"Use UriString.fromURL() or UriReferenceString.fromURL() instead.\",\n\t\t);\n\t}\n\n\t/**\n\t * Create from the relative components of a URL.\n\t *\n\t * Concatenates `pathname + search + hash` into a relative URI string.\n\t */\n\tstatic override fromURLRelative(parts: UriRelativeParts): UriRelativeString {\n\t\tconst raw = `${parts.pathname}${parts.search}${parts.hash}`;\n\t\treturn UriRelativeString.parse(raw);\n\t}\n\n\t// ---- Conversion ------------------------------------------------------\n\n\t/**\n\t * Convert to a native `URL` by resolving against the given base.\n\t *\n\t * @param base - The base URL to resolve against (required).\n\t */\n\toverride toURL(base: string | URL): URL {\n\t\treturn new URL(this.raw, base);\n\t}\n}\n"],"mappings":"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"}
@@ -1,7 +1,19 @@
1
- import { E as TimeTrait, Xt as WithTraitDeps, ct as EventStreamTrait } from "../index-Ch8lrE44.mjs";
2
- import { Dn as WithTraitInputValidator, Lt as EnvironmentValidators, Pt as CreateFoundationEnvironmentOptions, Rt as FoundationEnvironment, Tr as PopupTrait, Vn as RouterTrait, on as SyncStorageTrait } from "../index-D5mW18cM.mjs";
3
- import { _ as createPageResumeSource, a as NativeWebWindowLike, b as fromStorageEvent, c as WebNavigationRouter, d as createPageLifecycleForNativeWeb, f as CreatePageResumeSourceOptions, g as PageResumeWindowTarget, h as PageResumeTriggerKind, i as NativeWebRouter, l as createRouterForNativeWeb, m as PageResumeEvent, n as NativeWebLocationLike, o as RouterForNativeWebCreateOptions, p as PageResumeDocumentTarget, r as NativeWebNavigationLike, s as WebLegacyRouter, t as NativeWebHistoryLike, u as PageLifecycleForNativeWebCreateOptions, v as FromStorageEventOptions, y as StorageEventTarget } from "../index-BT-u3qNI.mjs";
4
-
1
+ import { T as TimeTrait, qt as WithTraitDeps, st as EventStreamTrait } from "../index-Cg_iY2yY.mjs";
2
+ import { Er as PopupTrait, Ft as CreateFoundationEnvironmentOptions, Hn as RouterTrait, On as WithTraitInputValidator, Rt as EnvironmentValidators, sn as SyncStorageTrait, zt as FoundationEnvironment } from "../index-DmIapvr-.mjs";
3
+ import { _ as createPageResumeSource, a as NativeWebWindowLike, c as WebNavigationRouter, d as createPageLifecycleForNativeWeb, f as CreatePageResumeSourceOptions, g as PageResumeWindowTarget, h as PageResumeTriggerKind, i as NativeWebRouter, l as createRouterForNativeWeb, m as PageResumeEvent, n as NativeWebLocationLike, o as RouterForNativeWebCreateOptions, p as PageResumeDocumentTarget, r as NativeWebNavigationLike, s as WebLegacyRouter, t as NativeWebHistoryLike, u as PageLifecycleForNativeWebCreateOptions } from "../index-O1A3CdBV.mjs";
4
+ //#region src/web/events/from-storage.d.ts
5
+ interface StorageEventTarget {
6
+ addEventListener(type: "storage", listener: EventListener): void;
7
+ removeEventListener(type: "storage", listener: EventListener): void;
8
+ }
9
+ interface FromStorageEventOptions {
10
+ storageEventTarget: StorageEventTarget;
11
+ }
12
+ /**
13
+ * Adapt browser `storage` events into an event stream.
14
+ */
15
+ declare function fromStorageEvent(options: FromStorageEventOptions): EventStreamTrait<StorageEvent>;
16
+ //#endregion
5
17
  //#region src/web/popup.d.ts
6
18
  interface PopupForNativeWebCreateOptions {
7
19
  window?: unknown;
@@ -1,6 +1,7 @@
1
- import { A as RxEventSubject, G as UserRecovery, H as ClientErrorKind, V as ClientError, h as createAsyncSchedulerWithTimestampProvider, k as RxEventStream } from "../rx-BoB32Dzg.mjs";
2
- import { F as PopupAttachFailureReason, G as validateWithSchemaSync, H as throwValidationClientError, I as PopupClientWindowHandle, J as PAGE_LIFECYCLE_TRAIT_TOKEN, K as PopupErrorCode, L as PopupServerWindowHandle, P as POPUP_TRAIT_TOKEN, T as ROUTER_TRAIT_TOKEN, U as validateTraitInput, at as createProviderIfTokenMissing, c as PERSISTENT_STORAGE_TRAIT_TOKEN, d as StorageChangeEventOrigin, ot as getSecuritydeptProviderToken, st as notMissingProvider, t as createFoundationEnvironment, u as SESSION_STORAGE_TRAIT_TOKEN, w as TIME_TRAIT_TOKEN } from "../create-Bm-XRA3G.mjs";
3
- import { a as createPageLifecycleForNativeWeb, i as createRouterForNativeWeb, n as WebLegacyRouter, o as PageResumeTriggerKind, r as WebNavigationRouter, s as createPageResumeSource, t as NativeWebRouter } from "../router-BJ8LqNJ1.mjs";
1
+ import { A as RxEventSubject, G as UserRecovery, H as ClientErrorKind, V as ClientError, h as createAsyncSchedulerWithTimestampProvider, k as RxEventStream } from "../rx-B3OU17wu.mjs";
2
+ import { n as PopupServerWindowHandle, o as PopupErrorCode, t as PopupClientWindowHandle } from "../handle-TnxwtQ4T.mjs";
3
+ import { B as validateWithSchemaSync, F as PopupAttachFailureReason, L as throwValidationClientError, P as POPUP_TRAIT_TOKEN, Q as notMissingProvider, R as validateTraitInput, T as ROUTER_TRAIT_TOKEN, V as PAGE_LIFECYCLE_TRAIT_TOKEN, X as createProviderIfTokenMissing, Z as getSecuritydeptProviderToken, c as PERSISTENT_STORAGE_TRAIT_TOKEN, d as StorageChangeEventOrigin, t as createFoundationEnvironment, u as SESSION_STORAGE_TRAIT_TOKEN, w as TIME_TRAIT_TOKEN } from "../create-99Ksgl_O.mjs";
4
+ import { a as createPageLifecycleForNativeWeb, i as createRouterForNativeWeb, n as WebLegacyRouter, o as PageResumeTriggerKind, r as WebNavigationRouter, s as createPageResumeSource, t as NativeWebRouter } from "../router-DUh3bhLy.mjs";
4
5
  import { filter, from, fromEventPattern, map, merge, take, timer } from "rxjs";
5
6
  import { type } from "arktype";
6
7
  //#region src/web/events/from-storage.ts
@@ -123,6 +124,14 @@ function attachPopupWindowToOpenerForNativeWeb(options) {
123
124
  source: "popup"
124
125
  })
125
126
  };
127
+ const incoming = RxEventStream.fromObservableInput(fromEventPattern((handler) => {
128
+ currentWindow.addEventListener("message", handler);
129
+ }, (handler) => {
130
+ currentWindow.removeEventListener("message", handler);
131
+ }).pipe(filter((event) => event.origin === allowedParentOrigin && event.source === opener), map((event) => event.data)));
132
+ const outgoing = createPostMessageSubject((message) => {
133
+ opener.postMessage(message, allowedParentOrigin);
134
+ });
126
135
  return {
127
136
  kind: "success",
128
137
  handle: new PopupServerWindowHandle({
@@ -130,14 +139,8 @@ function attachPopupWindowToOpenerForNativeWeb(options) {
130
139
  currentWindow.close();
131
140
  },
132
141
  messaging: {
133
- incoming: RxEventStream.fromObservableInput(fromEventPattern((handler) => {
134
- currentWindow.addEventListener("message", handler);
135
- }, (handler) => {
136
- currentWindow.removeEventListener("message", handler);
137
- }).pipe(filter((event) => event.origin === allowedParentOrigin && event.source === opener), map((event) => event.data))),
138
- outgoing: createPostMessageSubject((message) => {
139
- opener.postMessage(message, allowedParentOrigin);
140
- })
142
+ incoming,
143
+ outgoing
141
144
  }
142
145
  })
143
146
  };
@@ -151,16 +154,18 @@ function createPostMessageSubject(send) {
151
154
  }
152
155
  //#endregion
153
156
  //#region src/web/storage.ts
157
+ const NativeWebStorageLikeSchema = type({
158
+ getItem: "Function",
159
+ setItem: "Function",
160
+ removeItem: "Function"
161
+ });
162
+ const StorageEventTargetSchema = type({
163
+ addEventListener: "Function",
164
+ removeEventListener: "Function"
165
+ });
154
166
  const StorageForNativeWebCreateOptionsSchema = type({
155
- storage: type({
156
- getItem: "Function",
157
- setItem: "Function",
158
- removeItem: "Function"
159
- }),
160
- storageEventTarget: type({
161
- addEventListener: "Function",
162
- removeEventListener: "Function"
163
- }).or("null").or("undefined"),
167
+ storage: NativeWebStorageLikeSchema,
168
+ storageEventTarget: StorageEventTargetSchema.or("null").or("undefined"),
164
169
  prefix: "string | undefined",
165
170
  validatorKey: "'persistentStorage' | 'sessionStorage'"
166
171
  });
@@ -261,8 +266,9 @@ function createSessionStorageForNativeWeb(options) {
261
266
  //#region src/web/environment.ts
262
267
  function createEnvironmentForNativeWeb(options) {
263
268
  const userProviders = options.providers ?? [];
269
+ const providers = [...createNativeWebTraitProviders(options, new Set(userProviders.map((provider) => getSecuritydeptProviderToken(provider)))), ...userProviders];
264
270
  return createFoundationEnvironment({
265
- providers: [...createNativeWebTraitProviders(options, new Set(userProviders.map((provider) => getSecuritydeptProviderToken(provider)))), ...userProviders],
271
+ providers,
266
272
  transport: options.transport,
267
273
  transportForStdFetchCreateOptions: options.transportForStdFetchCreateOptions,
268
274
  time: options.time,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["defineType","global","defineType"],"sources":["../../src/web/events/from-storage.ts","../../src/web/popup.ts","../../src/web/storage.ts","../../src/web/environment.ts","../../src/web/sync/cross-tab-sync.ts"],"sourcesContent":["import { fromEventPattern } from \"rxjs\";\nimport { type EventStreamTrait } from \"../../events\";\nimport { RxEventStream } from \"../../rx\";\n\nexport interface StorageEventTarget {\n\taddEventListener(type: \"storage\", listener: EventListener): void;\n\tremoveEventListener(type: \"storage\", listener: EventListener): void;\n}\n\nexport interface FromStorageEventOptions {\n\tstorageEventTarget: StorageEventTarget;\n}\n\n/**\n * Adapt browser `storage` events into an event stream.\n */\nexport function fromStorageEvent(\n\toptions: FromStorageEventOptions,\n): EventStreamTrait<StorageEvent> {\n\tconst { storageEventTarget } = options;\n\n\treturn RxEventStream.fromObservableInput(\n\t\tfromEventPattern<StorageEvent>(\n\t\t\t(handler) => {\n\t\t\t\tstorageEventTarget.addEventListener(\"storage\", handler);\n\t\t\t},\n\t\t\t(handler) => {\n\t\t\t\tstorageEventTarget.removeEventListener(\"storage\", handler);\n\t\t\t},\n\t\t),\n\t);\n}\n","import { type as defineType } from \"arktype\";\nimport { filter, fromEventPattern, map, take, timer } from \"rxjs\";\nimport { type EnvironmentValidators } from \"../environment/types\";\nimport { ClientError, ClientErrorKind, UserRecovery } from \"../errors\";\nimport { type EventSubjectTrait } from \"../events\";\nimport { type WithTraitDeps } from \"../injection\";\nimport {\n\tPopupAttachFailureReason,\n\ttype PopupAttachResult,\n\tPopupClientWindowHandle,\n\ttype PopupClientWindowHandleTrait,\n\tPopupErrorCode,\n\ttype PopupOpenOptions,\n\tPopupServerWindowHandle,\n\ttype PopupTrait,\n} from \"../popup\";\nimport { type JsonRpcMessage } from \"../protocol/json-rpc\";\nimport {\n\tcreateAsyncSchedulerWithTimestampProvider,\n\tRxEventStream,\n\tRxEventSubject,\n} from \"../rx\";\nimport { type TimeTrait } from \"../scheduling/types\";\nimport {\n\tthrowValidationClientError,\n\tvalidateTraitInput,\n\tvalidateWithSchemaSync,\n\ttype WithTraitInputValidator,\n} from \"../validation\";\n\nexport interface PopupForNativeWebCreateOptions {\n\twindow?: unknown;\n}\n\nexport interface PopupFeaturesOptions {\n\twidth?: number;\n\theight?: number;\n}\n\nexport interface NativeWebPopupWindowLike {\n\tclosed: boolean;\n\tclose(): void;\n\tpostMessage(message: unknown, targetOrigin: string): void;\n}\n\nexport type NativeWebPopupContextWindowLike = NativeWebWindowLike &\n\tNativeWebPopupWindowLike;\n\nexport interface NativeWebWindowLike {\n\topen(\n\t\turl: string,\n\t\ttarget?: string,\n\t\tfeatures?: string,\n\t): NativeWebPopupWindowLike | null;\n\taddEventListener(\n\t\ttype: \"message\",\n\t\thandler: (event: MessageEvent) => void,\n\t): void;\n\tremoveEventListener(\n\t\ttype: \"message\",\n\t\thandler: (event: MessageEvent) => void,\n\t): void;\n\tlocation?: {\n\t\thref?: string;\n\t\torigin?: string;\n\t};\n\tscreenX?: number;\n\tscreenY?: number;\n\tinnerWidth?: number;\n\tinnerHeight?: number;\n\tclose?(): void;\n\topener?: {\n\t\tpostMessage(message: unknown, targetOrigin: string): void;\n\t} | null;\n}\n\ninterface CreatePopupClientWindowHandleForNativeWebOptions\n\textends PopupFeaturesOptions,\n\t\tPopupOpenOptions {\n\turl: string;\n\ttime: TimeTrait;\n\twindow: NativeWebWindowLike;\n\texpectedOrigin?: string;\n\tpollIntervalMs?: number;\n}\n\nconst PopupForNativeWebCreateOptionsSchema = defineType({\n\twindow: {\n\t\topen: \"Function\",\n\t\taddEventListener: \"Function\",\n\t\tremoveEventListener: \"Function\",\n\t},\n});\n\nconst PopupForNativeWebUnavailableProbeSchema = defineType({\n\twindow: \"null | undefined\",\n});\n\nexport function createPopupForNativeWeb(\n\toptions: PopupForNativeWebCreateOptions &\n\t\tWithTraitInputValidator<Pick<EnvironmentValidators, \"popup\">> &\n\t\tWithTraitDeps<{ time: TimeTrait }>,\n): PopupTrait | null {\n\tconst { validators, time, ...createOptions } = options;\n\tconst global = globalThis as { window?: NativeWebWindowLike };\n\tconst resolvedCreateOptions = {\n\t\twindow: global.window ?? null,\n\t\t...createOptions,\n\t};\n\tconst unavailableProbeResult = validateWithSchemaSync(\n\t\tPopupForNativeWebUnavailableProbeSchema,\n\t\tresolvedCreateOptions,\n\t);\n\tif (unavailableProbeResult.success) {\n\t\treturn null;\n\t}\n\tvalidateTraitInput({\n\t\tvalue: resolvedCreateOptions,\n\t\tbundledSchema: PopupForNativeWebCreateOptionsSchema,\n\t\tvalidator: validators?.popup,\n\t\tonInvalid: (failure) =>\n\t\t\tthrowValidationClientError({\n\t\t\t\tcode: \"web.popup.invalid_native_web_popup_options\",\n\t\t\t\tsource: \"web\",\n\t\t\t\tmessagePrefix:\n\t\t\t\t\t\"createPopupForNativeWeb could not validate popupForNativeWebCreateOptions\",\n\t\t\t\tfailure,\n\t\t\t}),\n\t});\n\tconst nativeWebWindow = resolvedCreateOptions.window as NativeWebWindowLike;\n\treturn {\n\t\topen(url, openOptions) {\n\t\t\treturn createPopupClientWindowHandleForNativeWeb({\n\t\t\t\turl,\n\t\t\t\ttime,\n\t\t\t\twindow: nativeWebWindow,\n\t\t\t\t...openOptions,\n\t\t\t});\n\t\t},\n\t\tattach() {\n\t\t\treturn attachPopupWindowToOpenerForNativeWeb({\n\t\t\t\ttime,\n\t\t\t\twindow: nativeWebWindow,\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport function computePopupFeatures(\n\toptions: PopupFeaturesOptions = {},\n\twindowLike: Pick<\n\t\tNativeWebWindowLike,\n\t\t\"screenX\" | \"screenY\" | \"innerWidth\" | \"innerHeight\"\n\t> = globalThis as NativeWebWindowLike,\n): string {\n\tconst width = options.width ?? 500;\n\tconst height = options.height ?? 600;\n\tconst left = Math.max(\n\t\t0,\n\t\tMath.round(\n\t\t\t(windowLike.screenX ?? 0) +\n\t\t\t\t((windowLike.innerWidth ?? width) - width) / 2,\n\t\t),\n\t);\n\tconst top = Math.max(\n\t\t0,\n\t\tMath.round(\n\t\t\t(windowLike.screenY ?? 0) +\n\t\t\t\t((windowLike.innerHeight ?? height) - height) / 2,\n\t\t),\n\t);\n\n\treturn `width=${width},height=${height},left=${left},top=${top},popup=yes,toolbar=no,menubar=no`;\n}\n\nfunction createPopupClientWindowHandleForNativeWeb(\n\toptions: CreatePopupClientWindowHandleForNativeWebOptions,\n): PopupClientWindowHandleTrait {\n\tconst hostWindow = options.window;\n\tconst features = computePopupFeatures(options, hostWindow);\n\tconst target = options.target ?? \"_blank\";\n\tconst popupWindow = hostWindow.open(options.url, target, features);\n\n\tif (!popupWindow || popupWindow.closed) {\n\t\tthrow new ClientError({\n\t\t\tkind: ClientErrorKind.Authorization,\n\t\t\tcode: PopupErrorCode.Blocked,\n\t\t\tmessage:\n\t\t\t\t\"Popup window was blocked by the browser. Please allow popups for this site.\",\n\t\t\trecovery: UserRecovery.Retry,\n\t\t\tsource: \"popup\",\n\t\t});\n\t}\n\n\tconst resolvedBaseHref = hostWindow.location?.href ?? \"http://localhost\";\n\tconst expectedOrigin =\n\t\toptions.expectedOrigin ?? new URL(options.url, resolvedBaseHref).origin;\n\tconst incoming = RxEventStream.fromObservableInput(\n\t\tfromEventPattern<MessageEvent>(\n\t\t\t(handler) => {\n\t\t\t\thostWindow.addEventListener(\"message\", handler);\n\t\t\t},\n\t\t\t(handler) => {\n\t\t\t\thostWindow.removeEventListener(\"message\", handler);\n\t\t\t},\n\t\t).pipe(\n\t\t\tfilter(\n\t\t\t\t(event) =>\n\t\t\t\t\tevent.origin === expectedOrigin && event.source === popupWindow,\n\t\t\t),\n\t\t\tmap((event) => event.data),\n\t\t),\n\t);\n\tconst outgoing = createPostMessageSubject((message) => {\n\t\tpopupWindow.postMessage(message, expectedOrigin);\n\t});\n\tconst closedStream = RxEventStream.fromObservableInput(\n\t\ttimer(\n\t\t\toptions.pollIntervalMs ?? 500,\n\t\t\toptions.pollIntervalMs ?? 500,\n\t\t\tcreateAsyncSchedulerWithTimestampProvider(options.time),\n\t\t).pipe(\n\t\t\tfilter(() => popupWindow.closed),\n\t\t\tmap(() => true),\n\t\t\ttake(1),\n\t\t),\n\t);\n\n\treturn new PopupClientWindowHandle({\n\t\tclose() {\n\t\t\tpopupWindow.close();\n\t\t},\n\t\tmessaging: {\n\t\t\tincoming,\n\t\t\toutgoing,\n\t\t},\n\t\ttime: options.time,\n\t\tclosedStream,\n\t});\n}\n\nfunction attachPopupWindowToOpenerForNativeWeb(options: {\n\ttime: TimeTrait;\n\twindow: NativeWebWindowLike;\n}): PopupAttachResult {\n\tconst currentWindow = options.window as NativeWebPopupContextWindowLike;\n\tconst opener = currentWindow.opener;\n\tif (!opener) {\n\t\treturn {\n\t\t\tkind: \"failure\",\n\t\t\treason: PopupAttachFailureReason.MissingOpener,\n\t\t\terror: new ClientError({\n\t\t\t\tkind: ClientErrorKind.Configuration,\n\t\t\t\tmessage:\n\t\t\t\t\t\"Current page is not attached to a popup opener and cannot attach popup messaging.\",\n\t\t\t\trecovery: UserRecovery.RestartFlow,\n\t\t\t\tsource: \"popup\",\n\t\t\t}),\n\t\t};\n\t}\n\n\tconst allowedParentOrigin = currentWindow.location?.origin ?? undefined;\n\tif (!allowedParentOrigin) {\n\t\treturn {\n\t\t\tkind: \"failure\",\n\t\t\treason: PopupAttachFailureReason.MissingOrigin,\n\t\t\terror: new ClientError({\n\t\t\t\tkind: ClientErrorKind.Configuration,\n\t\t\t\tmessage:\n\t\t\t\t\t\"Current page has no origin information and cannot attach popup messaging.\",\n\t\t\t\trecovery: UserRecovery.RestartFlow,\n\t\t\t\tsource: \"popup\",\n\t\t\t}),\n\t\t};\n\t}\n\n\tconst incoming = RxEventStream.fromObservableInput(\n\t\tfromEventPattern<MessageEvent>(\n\t\t\t(handler) => {\n\t\t\t\tcurrentWindow.addEventListener(\"message\", handler);\n\t\t\t},\n\t\t\t(handler) => {\n\t\t\t\tcurrentWindow.removeEventListener(\"message\", handler);\n\t\t\t},\n\t\t).pipe(\n\t\t\tfilter(\n\t\t\t\t(event) =>\n\t\t\t\t\tevent.origin === allowedParentOrigin && event.source === opener,\n\t\t\t),\n\t\t\tmap((event) => event.data),\n\t\t),\n\t);\n\tconst outgoing = createPostMessageSubject((message) => {\n\t\topener.postMessage(message, allowedParentOrigin);\n\t});\n\n\treturn {\n\t\tkind: \"success\",\n\t\thandle: new PopupServerWindowHandle({\n\t\t\tclose() {\n\t\t\t\tcurrentWindow.close();\n\t\t\t},\n\t\t\tmessaging: {\n\t\t\t\tincoming,\n\t\t\t\toutgoing,\n\t\t\t},\n\t\t}),\n\t};\n}\n\nfunction createPostMessageSubject(\n\tsend: (message: JsonRpcMessage) => void,\n): EventSubjectTrait<JsonRpcMessage> {\n\tconst outgoing = new RxEventSubject<JsonRpcMessage>();\n\toutgoing.subscribe({\n\t\tnext(message) {\n\t\t\tsend(message);\n\t\t},\n\t});\n\treturn outgoing;\n}\n","import { type as defineType } from \"arktype\";\nimport { filter, from, map, merge } from \"rxjs\";\nimport { type EnvironmentValidators } from \"../environment/types\";\nimport { RxEventStream, RxEventSubject } from \"../rx\";\nimport {\n\ttype StorageChangeEvent,\n\tStorageChangeEventOrigin,\n\ttype SyncStorageTrait,\n} from \"../storage/types\";\nimport {\n\tthrowValidationClientError,\n\tvalidateTraitInput,\n\tvalidateWithSchemaSync,\n\ttype WithTraitInputValidator,\n} from \"../validation\";\nimport {\n\tfromStorageEvent,\n\ttype StorageEventTarget,\n} from \"./events/from-storage\";\n\nexport interface NativeWebStorageLike {\n\tgetItem(key: string): string | null;\n\tsetItem(key: string, value: string): void;\n\tremoveItem(key: string): void;\n}\n\nconst NativeWebStorageLikeSchema = defineType({\n\tgetItem: \"Function\",\n\tsetItem: \"Function\",\n\tremoveItem: \"Function\",\n});\n\nconst StorageEventTargetSchema = defineType({\n\taddEventListener: \"Function\",\n\tremoveEventListener: \"Function\",\n});\n\nconst StorageForNativeWebCreateOptionsSchema = defineType({\n\tstorage: NativeWebStorageLikeSchema,\n\tstorageEventTarget: StorageEventTargetSchema.or(\"null\").or(\"undefined\"),\n\tprefix: \"string | undefined\",\n\tvalidatorKey: \"'persistentStorage' | 'sessionStorage'\",\n});\n\nconst StorageForNativeWebUnavailableProbeSchema = defineType({\n\tstorage: \"null | undefined\",\n\tstorageEventTarget: \"unknown\",\n\tprefix: \"string | undefined\",\n\tvalidatorKey: \"'persistentStorage' | 'sessionStorage'\",\n});\n\nexport interface StorageForNativeWebCreateOptions {\n\tstorage?: NativeWebStorageLike | null;\n\tstorageEventTarget?: StorageEventTarget | null;\n\tprefix?: string;\n\tvalidatorKey: \"persistentStorage\" | \"sessionStorage\";\n}\n\nconst DEFAULT_PERSISTENT_STORAGE_PREFIX = \"securitydept.web.client:\";\nconst DEFAULT_SESSION_STORAGE_PREFIX = \"securitydept.web.client:\";\n\nexport function createStorageForNativeWeb(\n\toptions: StorageForNativeWebCreateOptions &\n\t\tWithTraitInputValidator<\n\t\t\tPick<EnvironmentValidators, \"persistentStorage\" | \"sessionStorage\">\n\t\t>,\n): SyncStorageTrait | null {\n\tconst { validators, ...createOptions } = options;\n\tconst global = globalThis as {\n\t\tlocalStorage?: NativeWebStorageLike;\n\t\tsessionStorage?: NativeWebStorageLike;\n\t\taddEventListener?: StorageEventTarget[\"addEventListener\"];\n\t\tremoveEventListener?: StorageEventTarget[\"removeEventListener\"];\n\t};\n\tconst resolvedCreateOptions = {\n\t\tstorage:\n\t\t\toptions.validatorKey === \"persistentStorage\"\n\t\t\t\t? (global.localStorage ?? null)\n\t\t\t\t: (global.sessionStorage ?? null),\n\t\t...createOptions,\n\t\tstorageEventTarget:\n\t\t\tcreateOptions.storageEventTarget === undefined\n\t\t\t\t? typeof global.addEventListener === \"function\" &&\n\t\t\t\t\ttypeof global.removeEventListener === \"function\"\n\t\t\t\t\t? (global as StorageEventTarget)\n\t\t\t\t\t: null\n\t\t\t\t: createOptions.storageEventTarget,\n\t\tprefix:\n\t\t\tcreateOptions.prefix ??\n\t\t\t(options.validatorKey === \"persistentStorage\"\n\t\t\t\t? DEFAULT_PERSISTENT_STORAGE_PREFIX\n\t\t\t\t: DEFAULT_SESSION_STORAGE_PREFIX),\n\t};\n\tconst unavailableProbeResult = validateWithSchemaSync(\n\t\tStorageForNativeWebUnavailableProbeSchema,\n\t\tresolvedCreateOptions,\n\t);\n\tif (unavailableProbeResult.success) {\n\t\treturn null;\n\t}\n\tvalidateTraitInput({\n\t\tvalue: resolvedCreateOptions,\n\t\tbundledSchema: StorageForNativeWebCreateOptionsSchema,\n\t\tvalidator: validators?.[options.validatorKey],\n\t\tonInvalid: (failure) =>\n\t\t\tthrowValidationClientError({\n\t\t\t\tcode: \"web.storage.invalid_native_web_storage_options\",\n\t\t\t\tsource: \"web\",\n\t\t\t\tmessagePrefix: `createStorageForNativeWeb could not validate ${options.validatorKey}ForNativeWebCreateOptions`,\n\t\t\t\tfailure,\n\t\t\t}),\n\t});\n\tconst storage = resolvedCreateOptions.storage as NativeWebStorageLike;\n\tconst prefix = resolvedCreateOptions.prefix;\n\tconst localStorageEvent = new RxEventSubject<StorageChangeEvent>();\n\tconst externalStorageEvent = resolvedCreateOptions.storageEventTarget\n\t\t? from(\n\t\t\t\tfromStorageEvent({\n\t\t\t\t\tstorageEventTarget: resolvedCreateOptions.storageEventTarget,\n\t\t\t\t}),\n\t\t\t).pipe(\n\t\t\t\tfilter(\n\t\t\t\t\t(event) =>\n\t\t\t\t\t\t(event.storageArea === null || event.storageArea === storage) &&\n\t\t\t\t\t\t(event.key === null || event.key.startsWith(prefix)),\n\t\t\t\t),\n\t\t\t\tmap(\n\t\t\t\t\t(event): StorageChangeEvent => ({\n\t\t\t\t\t\torigin: StorageChangeEventOrigin.External,\n\t\t\t\t\t\tkey: event.key === null ? null : event.key.slice(prefix.length),\n\t\t\t\t\t\toldValue: event.oldValue,\n\t\t\t\t\t\tnewValue: event.newValue,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t)\n\t\t: null;\n\tconst storageEvent = RxEventStream.fromObservableInput(\n\t\texternalStorageEvent\n\t\t\t? merge(localStorageEvent, externalStorageEvent)\n\t\t\t: localStorageEvent,\n\t);\n\n\treturn {\n\t\tstorageEvent,\n\t\tget(key) {\n\t\t\treturn storage.getItem(prefix + key);\n\t\t},\n\t\tset(key, value) {\n\t\t\tconst storageKey = prefix + key;\n\t\t\tconst oldValue = storage.getItem(storageKey);\n\t\t\tstorage.setItem(storageKey, value);\n\t\t\tlocalStorageEvent.next({\n\t\t\t\torigin: StorageChangeEventOrigin.Local,\n\t\t\t\tkey,\n\t\t\t\toldValue,\n\t\t\t\tnewValue: value,\n\t\t\t});\n\t\t},\n\t\ttake(key) {\n\t\t\tconst storageKey = prefix + key;\n\t\t\tconst value = storage.getItem(storageKey);\n\t\t\tif (value !== null) {\n\t\t\t\tstorage.removeItem(storageKey);\n\t\t\t\tlocalStorageEvent.next({\n\t\t\t\t\torigin: StorageChangeEventOrigin.Local,\n\t\t\t\t\tkey,\n\t\t\t\t\toldValue: value,\n\t\t\t\t\tnewValue: null,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn value;\n\t\t},\n\t\tremove(key) {\n\t\t\tconst storageKey = prefix + key;\n\t\t\tconst oldValue = storage.getItem(storageKey);\n\t\t\tstorage.removeItem(storageKey);\n\t\t\tif (oldValue !== null) {\n\t\t\t\tlocalStorageEvent.next({\n\t\t\t\t\torigin: StorageChangeEventOrigin.Local,\n\t\t\t\t\tkey,\n\t\t\t\t\toldValue,\n\t\t\t\t\tnewValue: null,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createPersistentStorageForNativeWeb(\n\toptions: Omit<StorageForNativeWebCreateOptions, \"validatorKey\"> &\n\t\tWithTraitInputValidator<\n\t\t\tPick<EnvironmentValidators, \"persistentStorage\" | \"sessionStorage\">\n\t\t>,\n): SyncStorageTrait | null {\n\treturn createStorageForNativeWeb({\n\t\t...options,\n\t\tvalidatorKey: \"persistentStorage\",\n\t});\n}\n\nexport function createSessionStorageForNativeWeb(\n\toptions: Omit<StorageForNativeWebCreateOptions, \"validatorKey\"> &\n\t\tWithTraitInputValidator<\n\t\t\tPick<EnvironmentValidators, \"persistentStorage\" | \"sessionStorage\">\n\t\t>,\n): SyncStorageTrait | null {\n\treturn createStorageForNativeWeb({\n\t\t...options,\n\t\tvalidatorKey: \"sessionStorage\",\n\t});\n}\n","import {\n\ttype CreateFoundationEnvironmentOptions,\n\tcreateFoundationEnvironment,\n} from \"../environment/create\";\nimport { type FoundationEnvironment } from \"../environment/types\";\nimport {\n\tcreateProviderIfTokenMissing,\n\tgetSecuritydeptProviderToken,\n\tnotMissingProvider,\n\ttype SecuritydeptDependencyDescriptor,\n\ttype SecuritydeptFactoryProvider,\n\ttype SecuritydeptProvider,\n\ttype SecuritydeptValueProvider,\n} from \"../injection\";\nimport { PAGE_LIFECYCLE_TRAIT_TOKEN } from \"../page\";\nimport { POPUP_TRAIT_TOKEN } from \"../popup\";\nimport { ROUTER_TRAIT_TOKEN, type RouterTrait } from \"../router\";\nimport { TIME_TRAIT_TOKEN, type TimeTrait } from \"../scheduling/types\";\nimport {\n\tPERSISTENT_STORAGE_TRAIT_TOKEN,\n\tSESSION_STORAGE_TRAIT_TOKEN,\n} from \"../storage/types\";\nimport {\n\tcreatePageLifecycleForNativeWeb,\n\ttype PageLifecycleForNativeWebCreateOptions,\n} from \"./page\";\nimport {\n\tcreatePopupForNativeWeb,\n\ttype PopupForNativeWebCreateOptions,\n} from \"./popup\";\nimport {\n\tcreateRouterForNativeWeb,\n\ttype RouterForNativeWebCreateOptions,\n} from \"./router\";\nimport {\n\tcreatePersistentStorageForNativeWeb,\n\tcreateSessionStorageForNativeWeb,\n\ttype StorageForNativeWebCreateOptions,\n} from \"./storage\";\n\nexport { type FoundationEnvironment } from \"../environment/types\";\n\nexport interface NativeWebEnvironment extends FoundationEnvironment {\n\trouter: RouterTrait;\n}\n\nexport interface CreateEnvironmentForNativeWebOptions\n\textends CreateFoundationEnvironmentOptions {\n\trouterForNativeWebCreateOptions?: RouterForNativeWebCreateOptions;\n\tpageLifecycleForNativeWebCreateOptions?: PageLifecycleForNativeWebCreateOptions;\n\tpopupForNativeWebCreateOptions?: PopupForNativeWebCreateOptions;\n\tpersistentStorageForNativeWebCreateOptions?: Omit<\n\t\tStorageForNativeWebCreateOptions,\n\t\t\"validatorKey\"\n\t>;\n\tsessionStorageForNativeWebCreateOptions?: Omit<\n\t\tStorageForNativeWebCreateOptions,\n\t\t\"validatorKey\"\n\t>;\n}\n\nexport function createEnvironmentForNativeWeb(\n\toptions: CreateEnvironmentForNativeWebOptions,\n): NativeWebEnvironment {\n\tconst userProviders = options.providers ?? [];\n\tconst externalProviderTokens = new Set(\n\t\tuserProviders.map((provider) => getSecuritydeptProviderToken(provider)),\n\t);\n\tconst providers = [\n\t\t...createNativeWebTraitProviders(options, externalProviderTokens),\n\t\t...userProviders,\n\t];\n\treturn createFoundationEnvironment({\n\t\tproviders,\n\t\ttransport: options.transport,\n\t\ttransportForStdFetchCreateOptions:\n\t\t\toptions.transportForStdFetchCreateOptions,\n\t\ttime: options.time,\n\t\ttimeForStdCreateOptions: options.timeForStdCreateOptions,\n\t\trealmStorage: options.realmStorage,\n\t\tidleCallback: options.idleCallback,\n\t\tspan: options.span,\n\t\tspanCreateOptions: options.spanCreateOptions,\n\t\ttracing: options.tracing,\n\t\ttracingCreateOptions: options.tracingCreateOptions,\n\t\tvalidators: options.validators,\n\t}) as NativeWebEnvironment;\n}\n\nfunction createNativeWebTraitProviders(\n\toptions: CreateEnvironmentForNativeWebOptions,\n\texternalProviderTokens: ReadonlySet<\n\t\tSecuritydeptValueProvider<unknown>[\"provide\"]\n\t>,\n): SecuritydeptProvider[] {\n\treturn [\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tROUTER_TRAIT_TOKEN,\n\t\t\t() =>\n\t\t\t\tcreateNativeWebTraitUnit({\n\t\t\t\t\tprovide: ROUTER_TRAIT_TOKEN,\n\t\t\t\t\tvalue: options.router,\n\t\t\t\t\tcreateValue: () =>\n\t\t\t\t\t\tcreateRouterForNativeWeb({\n\t\t\t\t\t\t\t...options.routerForNativeWebCreateOptions,\n\t\t\t\t\t\t\tvalidators: options.validators,\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t),\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tPAGE_LIFECYCLE_TRAIT_TOKEN,\n\t\t\t() =>\n\t\t\t\tcreateNativeWebTraitUnit({\n\t\t\t\t\tprovide: PAGE_LIFECYCLE_TRAIT_TOKEN,\n\t\t\t\t\tvalue: options.pageLifecycle,\n\t\t\t\t\tcreateValue: () =>\n\t\t\t\t\t\tcreatePageLifecycleForNativeWeb({\n\t\t\t\t\t\t\t...options.pageLifecycleForNativeWebCreateOptions,\n\t\t\t\t\t\t\tvalidators: options.validators,\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t),\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tPOPUP_TRAIT_TOKEN,\n\t\t\t() =>\n\t\t\t\tcreateNativeWebTraitUnit({\n\t\t\t\t\tprovide: POPUP_TRAIT_TOKEN,\n\t\t\t\t\tvalue: options.popup,\n\t\t\t\t\tcreateValue: (time: TimeTrait) =>\n\t\t\t\t\t\tcreatePopupForNativeWeb({\n\t\t\t\t\t\t\ttime,\n\t\t\t\t\t\t\t...options.popupForNativeWebCreateOptions,\n\t\t\t\t\t\t\tvalidators: options.validators,\n\t\t\t\t\t\t}),\n\t\t\t\t\tdeps: [TIME_TRAIT_TOKEN],\n\t\t\t\t}),\n\t\t),\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tPERSISTENT_STORAGE_TRAIT_TOKEN,\n\t\t\t() =>\n\t\t\t\tcreateNativeWebTraitUnit({\n\t\t\t\t\tprovide: PERSISTENT_STORAGE_TRAIT_TOKEN,\n\t\t\t\t\tvalue: options.persistentStorage,\n\t\t\t\t\tcreateValue: () =>\n\t\t\t\t\t\tcreatePersistentStorageForNativeWeb({\n\t\t\t\t\t\t\t...options.persistentStorageForNativeWebCreateOptions,\n\t\t\t\t\t\t\tvalidators: options.validators,\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t),\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tSESSION_STORAGE_TRAIT_TOKEN,\n\t\t\t() =>\n\t\t\t\tcreateNativeWebTraitUnit({\n\t\t\t\t\tprovide: SESSION_STORAGE_TRAIT_TOKEN,\n\t\t\t\t\tvalue: options.sessionStorage,\n\t\t\t\t\tcreateValue: () =>\n\t\t\t\t\t\tcreateSessionStorageForNativeWeb({\n\t\t\t\t\t\t\t...options.sessionStorageForNativeWebCreateOptions,\n\t\t\t\t\t\t\tvalidators: options.validators,\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t),\n\t].filter(notMissingProvider);\n}\n\nfunction createNativeWebTraitUnit<T>(options: {\n\tprovide: SecuritydeptValueProvider<T | null>[\"provide\"];\n\tvalue: T | null | undefined;\n\tdeps?: readonly SecuritydeptDependencyDescriptor<unknown>[];\n\tcreateValue(...deps: readonly unknown[]): T | null;\n}): SecuritydeptProvider {\n\tif (options.value !== undefined) {\n\t\treturn {\n\t\t\tprovide: options.provide,\n\t\t\tuseValue: options.value,\n\t\t} satisfies SecuritydeptValueProvider<T | null>;\n\t}\n\n\treturn {\n\t\tprovide: options.provide,\n\t\tuseFactory: options.createValue as (...deps: never[]) => T | null,\n\t\tdeps: options.deps,\n\t} satisfies SecuritydeptFactoryProvider<T | null>;\n}\n","import { filter, map } from \"rxjs\";\nimport { type EventStreamTrait } from \"../../events\";\nimport { RxEventStream } from \"../../rx\";\nimport {\n\tfromStorageEvent,\n\ttype StorageEventTarget,\n} from \"../events/from-storage\";\n\n// Cross-tab auth state sync — minimal baseline using storage events\n//\n// Provides a minimal, composable cross-tab sync mechanism for auth state.\n// When another tab writes to the auth persistence key (via localStorage),\n// this listener detects the change and notifies the current tab so it can\n// reconcile its in-memory state.\n//\n// This is intentionally thin — it adapts the browser `storage` event into an\n// event stream. The reconciliation subscriber is the adopter's responsibility\n// (e.g. re-read from persistence, compare with in-memory state, and update).\n//\n// Architecture boundary:\n// - This module does NOT own the persistence store.\n// - It only publishes cross-tab mutations as a stream.\n// - The adopter wires this to their auth state owner.\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Event emitted when a cross-tab storage change is detected for the watched key. */\nexport interface CrossTabSyncEvent {\n\t/** The new value written by the other tab, or null if the key was removed. */\n\tnewValue: string | null;\n\t/** The old value before the other tab's write. */\n\toldValue: string | null;\n}\n\n/** Options for {@link createCrossTabSync}. */\nexport interface CreateCrossTabSyncOptions {\n\t/** The localStorage key to watch for cross-tab changes. */\n\tkey: string;\n\n\tstorageEventTarget: StorageEventTarget;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Create a cross-tab sync listener for a specific localStorage key.\n *\n * The browser `storage` event fires on ALL tabs EXCEPT the one that made the\n * change. This makes it a natural primitive for cross-tab state notification.\n *\n * @example\n * ```ts\n * const subscription = createCrossTabSync({\n * key: \"auth:v1\",\n * storageEventTarget: window,\n * }).subscribe({\n * next: ({ newValue }) => {\n * if (newValue) {\n * // Another tab updated auth state — reconcile\n * client.restorePersistedState();\n * } else {\n * // Another tab cleared auth state — log out\n * controller.clearState({ persistPolicy: \"skip\" });\n * }\n * },\n * });\n * // Later:\n * subscription.unsubscribe();\n * ```\n */\nexport function createCrossTabSync(\n\toptions: CreateCrossTabSyncOptions,\n): EventStreamTrait<CrossTabSyncEvent> {\n\treturn RxEventStream.fromObservableInput(\n\t\tfromStorageEvent({\n\t\t\tstorageEventTarget: options.storageEventTarget,\n\t\t}),\n\t).pipe(\n\t\tfilter((storageEvent) => storageEvent.key === options.key),\n\t\tmap((storageEvent) => ({\n\t\t\tnewValue: storageEvent.newValue,\n\t\t\toldValue: storageEvent.oldValue,\n\t\t})),\n\t);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["defineType","global","defineType"],"sources":["../../src/web/events/from-storage.ts","../../src/web/popup.ts","../../src/web/storage.ts","../../src/web/environment.ts","../../src/web/sync/cross-tab-sync.ts"],"sourcesContent":["import { fromEventPattern } from \"rxjs\";\nimport { type EventStreamTrait } from \"../../events\";\nimport { RxEventStream } from \"../../rx\";\n\nexport interface StorageEventTarget {\n\taddEventListener(type: \"storage\", listener: EventListener): void;\n\tremoveEventListener(type: \"storage\", listener: EventListener): void;\n}\n\nexport interface FromStorageEventOptions {\n\tstorageEventTarget: StorageEventTarget;\n}\n\n/**\n * Adapt browser `storage` events into an event stream.\n */\nexport function fromStorageEvent(\n\toptions: FromStorageEventOptions,\n): EventStreamTrait<StorageEvent> {\n\tconst { storageEventTarget } = options;\n\n\treturn RxEventStream.fromObservableInput(\n\t\tfromEventPattern<StorageEvent>(\n\t\t\t(handler) => {\n\t\t\t\tstorageEventTarget.addEventListener(\"storage\", handler);\n\t\t\t},\n\t\t\t(handler) => {\n\t\t\t\tstorageEventTarget.removeEventListener(\"storage\", handler);\n\t\t\t},\n\t\t),\n\t);\n}\n","import { type as defineType } from \"arktype\";\nimport { filter, fromEventPattern, map, take, timer } from \"rxjs\";\nimport { type EnvironmentValidators } from \"../environment/types\";\nimport { ClientError, ClientErrorKind, UserRecovery } from \"../errors\";\nimport { type EventSubjectTrait } from \"../events\";\nimport { type WithTraitDeps } from \"../injection\";\nimport {\n\tPopupAttachFailureReason,\n\ttype PopupAttachResult,\n\tPopupClientWindowHandle,\n\ttype PopupClientWindowHandleTrait,\n\tPopupErrorCode,\n\ttype PopupOpenOptions,\n\tPopupServerWindowHandle,\n\ttype PopupTrait,\n} from \"../popup\";\nimport { type JsonRpcMessage } from \"../protocol/json-rpc\";\nimport {\n\tcreateAsyncSchedulerWithTimestampProvider,\n\tRxEventStream,\n\tRxEventSubject,\n} from \"../rx\";\nimport { type TimeTrait } from \"../scheduling/types\";\nimport {\n\tthrowValidationClientError,\n\tvalidateTraitInput,\n\tvalidateWithSchemaSync,\n\ttype WithTraitInputValidator,\n} from \"../validation\";\n\nexport interface PopupForNativeWebCreateOptions {\n\twindow?: unknown;\n}\n\nexport interface PopupFeaturesOptions {\n\twidth?: number;\n\theight?: number;\n}\n\nexport interface NativeWebPopupWindowLike {\n\tclosed: boolean;\n\tclose(): void;\n\tpostMessage(message: unknown, targetOrigin: string): void;\n}\n\nexport type NativeWebPopupContextWindowLike = NativeWebWindowLike &\n\tNativeWebPopupWindowLike;\n\nexport interface NativeWebWindowLike {\n\topen(\n\t\turl: string,\n\t\ttarget?: string,\n\t\tfeatures?: string,\n\t): NativeWebPopupWindowLike | null;\n\taddEventListener(\n\t\ttype: \"message\",\n\t\thandler: (event: MessageEvent) => void,\n\t): void;\n\tremoveEventListener(\n\t\ttype: \"message\",\n\t\thandler: (event: MessageEvent) => void,\n\t): void;\n\tlocation?: {\n\t\thref?: string;\n\t\torigin?: string;\n\t};\n\tscreenX?: number;\n\tscreenY?: number;\n\tinnerWidth?: number;\n\tinnerHeight?: number;\n\tclose?(): void;\n\topener?: {\n\t\tpostMessage(message: unknown, targetOrigin: string): void;\n\t} | null;\n}\n\ninterface CreatePopupClientWindowHandleForNativeWebOptions\n\textends PopupFeaturesOptions,\n\t\tPopupOpenOptions {\n\turl: string;\n\ttime: TimeTrait;\n\twindow: NativeWebWindowLike;\n\texpectedOrigin?: string;\n\tpollIntervalMs?: number;\n}\n\nconst PopupForNativeWebCreateOptionsSchema = defineType({\n\twindow: {\n\t\topen: \"Function\",\n\t\taddEventListener: \"Function\",\n\t\tremoveEventListener: \"Function\",\n\t},\n});\n\nconst PopupForNativeWebUnavailableProbeSchema = defineType({\n\twindow: \"null | undefined\",\n});\n\nexport function createPopupForNativeWeb(\n\toptions: PopupForNativeWebCreateOptions &\n\t\tWithTraitInputValidator<Pick<EnvironmentValidators, \"popup\">> &\n\t\tWithTraitDeps<{ time: TimeTrait }>,\n): PopupTrait | null {\n\tconst { validators, time, ...createOptions } = options;\n\tconst global = globalThis as { window?: NativeWebWindowLike };\n\tconst resolvedCreateOptions = {\n\t\twindow: global.window ?? null,\n\t\t...createOptions,\n\t};\n\tconst unavailableProbeResult = validateWithSchemaSync(\n\t\tPopupForNativeWebUnavailableProbeSchema,\n\t\tresolvedCreateOptions,\n\t);\n\tif (unavailableProbeResult.success) {\n\t\treturn null;\n\t}\n\tvalidateTraitInput({\n\t\tvalue: resolvedCreateOptions,\n\t\tbundledSchema: PopupForNativeWebCreateOptionsSchema,\n\t\tvalidator: validators?.popup,\n\t\tonInvalid: (failure) =>\n\t\t\tthrowValidationClientError({\n\t\t\t\tcode: \"web.popup.invalid_native_web_popup_options\",\n\t\t\t\tsource: \"web\",\n\t\t\t\tmessagePrefix:\n\t\t\t\t\t\"createPopupForNativeWeb could not validate popupForNativeWebCreateOptions\",\n\t\t\t\tfailure,\n\t\t\t}),\n\t});\n\tconst nativeWebWindow = resolvedCreateOptions.window as NativeWebWindowLike;\n\treturn {\n\t\topen(url, openOptions) {\n\t\t\treturn createPopupClientWindowHandleForNativeWeb({\n\t\t\t\turl,\n\t\t\t\ttime,\n\t\t\t\twindow: nativeWebWindow,\n\t\t\t\t...openOptions,\n\t\t\t});\n\t\t},\n\t\tattach() {\n\t\t\treturn attachPopupWindowToOpenerForNativeWeb({\n\t\t\t\ttime,\n\t\t\t\twindow: nativeWebWindow,\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport function computePopupFeatures(\n\toptions: PopupFeaturesOptions = {},\n\twindowLike: Pick<\n\t\tNativeWebWindowLike,\n\t\t\"screenX\" | \"screenY\" | \"innerWidth\" | \"innerHeight\"\n\t> = globalThis as NativeWebWindowLike,\n): string {\n\tconst width = options.width ?? 500;\n\tconst height = options.height ?? 600;\n\tconst left = Math.max(\n\t\t0,\n\t\tMath.round(\n\t\t\t(windowLike.screenX ?? 0) +\n\t\t\t\t((windowLike.innerWidth ?? width) - width) / 2,\n\t\t),\n\t);\n\tconst top = Math.max(\n\t\t0,\n\t\tMath.round(\n\t\t\t(windowLike.screenY ?? 0) +\n\t\t\t\t((windowLike.innerHeight ?? height) - height) / 2,\n\t\t),\n\t);\n\n\treturn `width=${width},height=${height},left=${left},top=${top},popup=yes,toolbar=no,menubar=no`;\n}\n\nfunction createPopupClientWindowHandleForNativeWeb(\n\toptions: CreatePopupClientWindowHandleForNativeWebOptions,\n): PopupClientWindowHandleTrait {\n\tconst hostWindow = options.window;\n\tconst features = computePopupFeatures(options, hostWindow);\n\tconst target = options.target ?? \"_blank\";\n\tconst popupWindow = hostWindow.open(options.url, target, features);\n\n\tif (!popupWindow || popupWindow.closed) {\n\t\tthrow new ClientError({\n\t\t\tkind: ClientErrorKind.Authorization,\n\t\t\tcode: PopupErrorCode.Blocked,\n\t\t\tmessage:\n\t\t\t\t\"Popup window was blocked by the browser. Please allow popups for this site.\",\n\t\t\trecovery: UserRecovery.Retry,\n\t\t\tsource: \"popup\",\n\t\t});\n\t}\n\n\tconst resolvedBaseHref = hostWindow.location?.href ?? \"http://localhost\";\n\tconst expectedOrigin =\n\t\toptions.expectedOrigin ?? new URL(options.url, resolvedBaseHref).origin;\n\tconst incoming = RxEventStream.fromObservableInput(\n\t\tfromEventPattern<MessageEvent>(\n\t\t\t(handler) => {\n\t\t\t\thostWindow.addEventListener(\"message\", handler);\n\t\t\t},\n\t\t\t(handler) => {\n\t\t\t\thostWindow.removeEventListener(\"message\", handler);\n\t\t\t},\n\t\t).pipe(\n\t\t\tfilter(\n\t\t\t\t(event) =>\n\t\t\t\t\tevent.origin === expectedOrigin && event.source === popupWindow,\n\t\t\t),\n\t\t\tmap((event) => event.data),\n\t\t),\n\t);\n\tconst outgoing = createPostMessageSubject((message) => {\n\t\tpopupWindow.postMessage(message, expectedOrigin);\n\t});\n\tconst closedStream = RxEventStream.fromObservableInput(\n\t\ttimer(\n\t\t\toptions.pollIntervalMs ?? 500,\n\t\t\toptions.pollIntervalMs ?? 500,\n\t\t\tcreateAsyncSchedulerWithTimestampProvider(options.time),\n\t\t).pipe(\n\t\t\tfilter(() => popupWindow.closed),\n\t\t\tmap(() => true),\n\t\t\ttake(1),\n\t\t),\n\t);\n\n\treturn new PopupClientWindowHandle({\n\t\tclose() {\n\t\t\tpopupWindow.close();\n\t\t},\n\t\tmessaging: {\n\t\t\tincoming,\n\t\t\toutgoing,\n\t\t},\n\t\ttime: options.time,\n\t\tclosedStream,\n\t});\n}\n\nfunction attachPopupWindowToOpenerForNativeWeb(options: {\n\ttime: TimeTrait;\n\twindow: NativeWebWindowLike;\n}): PopupAttachResult {\n\tconst currentWindow = options.window as NativeWebPopupContextWindowLike;\n\tconst opener = currentWindow.opener;\n\tif (!opener) {\n\t\treturn {\n\t\t\tkind: \"failure\",\n\t\t\treason: PopupAttachFailureReason.MissingOpener,\n\t\t\terror: new ClientError({\n\t\t\t\tkind: ClientErrorKind.Configuration,\n\t\t\t\tmessage:\n\t\t\t\t\t\"Current page is not attached to a popup opener and cannot attach popup messaging.\",\n\t\t\t\trecovery: UserRecovery.RestartFlow,\n\t\t\t\tsource: \"popup\",\n\t\t\t}),\n\t\t};\n\t}\n\n\tconst allowedParentOrigin = currentWindow.location?.origin ?? undefined;\n\tif (!allowedParentOrigin) {\n\t\treturn {\n\t\t\tkind: \"failure\",\n\t\t\treason: PopupAttachFailureReason.MissingOrigin,\n\t\t\terror: new ClientError({\n\t\t\t\tkind: ClientErrorKind.Configuration,\n\t\t\t\tmessage:\n\t\t\t\t\t\"Current page has no origin information and cannot attach popup messaging.\",\n\t\t\t\trecovery: UserRecovery.RestartFlow,\n\t\t\t\tsource: \"popup\",\n\t\t\t}),\n\t\t};\n\t}\n\n\tconst incoming = RxEventStream.fromObservableInput(\n\t\tfromEventPattern<MessageEvent>(\n\t\t\t(handler) => {\n\t\t\t\tcurrentWindow.addEventListener(\"message\", handler);\n\t\t\t},\n\t\t\t(handler) => {\n\t\t\t\tcurrentWindow.removeEventListener(\"message\", handler);\n\t\t\t},\n\t\t).pipe(\n\t\t\tfilter(\n\t\t\t\t(event) =>\n\t\t\t\t\tevent.origin === allowedParentOrigin && event.source === opener,\n\t\t\t),\n\t\t\tmap((event) => event.data),\n\t\t),\n\t);\n\tconst outgoing = createPostMessageSubject((message) => {\n\t\topener.postMessage(message, allowedParentOrigin);\n\t});\n\n\treturn {\n\t\tkind: \"success\",\n\t\thandle: new PopupServerWindowHandle({\n\t\t\tclose() {\n\t\t\t\tcurrentWindow.close();\n\t\t\t},\n\t\t\tmessaging: {\n\t\t\t\tincoming,\n\t\t\t\toutgoing,\n\t\t\t},\n\t\t}),\n\t};\n}\n\nfunction createPostMessageSubject(\n\tsend: (message: JsonRpcMessage) => void,\n): EventSubjectTrait<JsonRpcMessage> {\n\tconst outgoing = new RxEventSubject<JsonRpcMessage>();\n\toutgoing.subscribe({\n\t\tnext(message) {\n\t\t\tsend(message);\n\t\t},\n\t});\n\treturn outgoing;\n}\n","import { type as defineType } from \"arktype\";\nimport { filter, from, map, merge } from \"rxjs\";\nimport { type EnvironmentValidators } from \"../environment/types\";\nimport { RxEventStream, RxEventSubject } from \"../rx\";\nimport {\n\ttype StorageChangeEvent,\n\tStorageChangeEventOrigin,\n\ttype SyncStorageTrait,\n} from \"../storage/types\";\nimport {\n\tthrowValidationClientError,\n\tvalidateTraitInput,\n\tvalidateWithSchemaSync,\n\ttype WithTraitInputValidator,\n} from \"../validation\";\nimport {\n\tfromStorageEvent,\n\ttype StorageEventTarget,\n} from \"./events/from-storage\";\n\nexport interface NativeWebStorageLike {\n\tgetItem(key: string): string | null;\n\tsetItem(key: string, value: string): void;\n\tremoveItem(key: string): void;\n}\n\nconst NativeWebStorageLikeSchema = defineType({\n\tgetItem: \"Function\",\n\tsetItem: \"Function\",\n\tremoveItem: \"Function\",\n});\n\nconst StorageEventTargetSchema = defineType({\n\taddEventListener: \"Function\",\n\tremoveEventListener: \"Function\",\n});\n\nconst StorageForNativeWebCreateOptionsSchema = defineType({\n\tstorage: NativeWebStorageLikeSchema,\n\tstorageEventTarget: StorageEventTargetSchema.or(\"null\").or(\"undefined\"),\n\tprefix: \"string | undefined\",\n\tvalidatorKey: \"'persistentStorage' | 'sessionStorage'\",\n});\n\nconst StorageForNativeWebUnavailableProbeSchema = defineType({\n\tstorage: \"null | undefined\",\n\tstorageEventTarget: \"unknown\",\n\tprefix: \"string | undefined\",\n\tvalidatorKey: \"'persistentStorage' | 'sessionStorage'\",\n});\n\nexport interface StorageForNativeWebCreateOptions {\n\tstorage?: NativeWebStorageLike | null;\n\tstorageEventTarget?: StorageEventTarget | null;\n\tprefix?: string;\n\tvalidatorKey: \"persistentStorage\" | \"sessionStorage\";\n}\n\nconst DEFAULT_PERSISTENT_STORAGE_PREFIX = \"securitydept.web.client:\";\nconst DEFAULT_SESSION_STORAGE_PREFIX = \"securitydept.web.client:\";\n\nexport function createStorageForNativeWeb(\n\toptions: StorageForNativeWebCreateOptions &\n\t\tWithTraitInputValidator<\n\t\t\tPick<EnvironmentValidators, \"persistentStorage\" | \"sessionStorage\">\n\t\t>,\n): SyncStorageTrait | null {\n\tconst { validators, ...createOptions } = options;\n\tconst global = globalThis as {\n\t\tlocalStorage?: NativeWebStorageLike;\n\t\tsessionStorage?: NativeWebStorageLike;\n\t\taddEventListener?: StorageEventTarget[\"addEventListener\"];\n\t\tremoveEventListener?: StorageEventTarget[\"removeEventListener\"];\n\t};\n\tconst resolvedCreateOptions = {\n\t\tstorage:\n\t\t\toptions.validatorKey === \"persistentStorage\"\n\t\t\t\t? (global.localStorage ?? null)\n\t\t\t\t: (global.sessionStorage ?? null),\n\t\t...createOptions,\n\t\tstorageEventTarget:\n\t\t\tcreateOptions.storageEventTarget === undefined\n\t\t\t\t? typeof global.addEventListener === \"function\" &&\n\t\t\t\t\ttypeof global.removeEventListener === \"function\"\n\t\t\t\t\t? (global as StorageEventTarget)\n\t\t\t\t\t: null\n\t\t\t\t: createOptions.storageEventTarget,\n\t\tprefix:\n\t\t\tcreateOptions.prefix ??\n\t\t\t(options.validatorKey === \"persistentStorage\"\n\t\t\t\t? DEFAULT_PERSISTENT_STORAGE_PREFIX\n\t\t\t\t: DEFAULT_SESSION_STORAGE_PREFIX),\n\t};\n\tconst unavailableProbeResult = validateWithSchemaSync(\n\t\tStorageForNativeWebUnavailableProbeSchema,\n\t\tresolvedCreateOptions,\n\t);\n\tif (unavailableProbeResult.success) {\n\t\treturn null;\n\t}\n\tvalidateTraitInput({\n\t\tvalue: resolvedCreateOptions,\n\t\tbundledSchema: StorageForNativeWebCreateOptionsSchema,\n\t\tvalidator: validators?.[options.validatorKey],\n\t\tonInvalid: (failure) =>\n\t\t\tthrowValidationClientError({\n\t\t\t\tcode: \"web.storage.invalid_native_web_storage_options\",\n\t\t\t\tsource: \"web\",\n\t\t\t\tmessagePrefix: `createStorageForNativeWeb could not validate ${options.validatorKey}ForNativeWebCreateOptions`,\n\t\t\t\tfailure,\n\t\t\t}),\n\t});\n\tconst storage = resolvedCreateOptions.storage as NativeWebStorageLike;\n\tconst prefix = resolvedCreateOptions.prefix;\n\tconst localStorageEvent = new RxEventSubject<StorageChangeEvent>();\n\tconst externalStorageEvent = resolvedCreateOptions.storageEventTarget\n\t\t? from(\n\t\t\t\tfromStorageEvent({\n\t\t\t\t\tstorageEventTarget: resolvedCreateOptions.storageEventTarget,\n\t\t\t\t}),\n\t\t\t).pipe(\n\t\t\t\tfilter(\n\t\t\t\t\t(event) =>\n\t\t\t\t\t\t(event.storageArea === null || event.storageArea === storage) &&\n\t\t\t\t\t\t(event.key === null || event.key.startsWith(prefix)),\n\t\t\t\t),\n\t\t\t\tmap(\n\t\t\t\t\t(event): StorageChangeEvent => ({\n\t\t\t\t\t\torigin: StorageChangeEventOrigin.External,\n\t\t\t\t\t\tkey: event.key === null ? null : event.key.slice(prefix.length),\n\t\t\t\t\t\toldValue: event.oldValue,\n\t\t\t\t\t\tnewValue: event.newValue,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t)\n\t\t: null;\n\tconst storageEvent = RxEventStream.fromObservableInput(\n\t\texternalStorageEvent\n\t\t\t? merge(localStorageEvent, externalStorageEvent)\n\t\t\t: localStorageEvent,\n\t);\n\n\treturn {\n\t\tstorageEvent,\n\t\tget(key) {\n\t\t\treturn storage.getItem(prefix + key);\n\t\t},\n\t\tset(key, value) {\n\t\t\tconst storageKey = prefix + key;\n\t\t\tconst oldValue = storage.getItem(storageKey);\n\t\t\tstorage.setItem(storageKey, value);\n\t\t\tlocalStorageEvent.next({\n\t\t\t\torigin: StorageChangeEventOrigin.Local,\n\t\t\t\tkey,\n\t\t\t\toldValue,\n\t\t\t\tnewValue: value,\n\t\t\t});\n\t\t},\n\t\ttake(key) {\n\t\t\tconst storageKey = prefix + key;\n\t\t\tconst value = storage.getItem(storageKey);\n\t\t\tif (value !== null) {\n\t\t\t\tstorage.removeItem(storageKey);\n\t\t\t\tlocalStorageEvent.next({\n\t\t\t\t\torigin: StorageChangeEventOrigin.Local,\n\t\t\t\t\tkey,\n\t\t\t\t\toldValue: value,\n\t\t\t\t\tnewValue: null,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn value;\n\t\t},\n\t\tremove(key) {\n\t\t\tconst storageKey = prefix + key;\n\t\t\tconst oldValue = storage.getItem(storageKey);\n\t\t\tstorage.removeItem(storageKey);\n\t\t\tif (oldValue !== null) {\n\t\t\t\tlocalStorageEvent.next({\n\t\t\t\t\torigin: StorageChangeEventOrigin.Local,\n\t\t\t\t\tkey,\n\t\t\t\t\toldValue,\n\t\t\t\t\tnewValue: null,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createPersistentStorageForNativeWeb(\n\toptions: Omit<StorageForNativeWebCreateOptions, \"validatorKey\"> &\n\t\tWithTraitInputValidator<\n\t\t\tPick<EnvironmentValidators, \"persistentStorage\" | \"sessionStorage\">\n\t\t>,\n): SyncStorageTrait | null {\n\treturn createStorageForNativeWeb({\n\t\t...options,\n\t\tvalidatorKey: \"persistentStorage\",\n\t});\n}\n\nexport function createSessionStorageForNativeWeb(\n\toptions: Omit<StorageForNativeWebCreateOptions, \"validatorKey\"> &\n\t\tWithTraitInputValidator<\n\t\t\tPick<EnvironmentValidators, \"persistentStorage\" | \"sessionStorage\">\n\t\t>,\n): SyncStorageTrait | null {\n\treturn createStorageForNativeWeb({\n\t\t...options,\n\t\tvalidatorKey: \"sessionStorage\",\n\t});\n}\n","import {\n\ttype CreateFoundationEnvironmentOptions,\n\tcreateFoundationEnvironment,\n} from \"../environment/create\";\nimport { type FoundationEnvironment } from \"../environment/types\";\nimport {\n\tcreateProviderIfTokenMissing,\n\tgetSecuritydeptProviderToken,\n\tnotMissingProvider,\n\ttype SecuritydeptDependencyDescriptor,\n\ttype SecuritydeptFactoryProvider,\n\ttype SecuritydeptProvider,\n\ttype SecuritydeptValueProvider,\n} from \"../injection\";\nimport { PAGE_LIFECYCLE_TRAIT_TOKEN } from \"../page\";\nimport { POPUP_TRAIT_TOKEN } from \"../popup\";\nimport { ROUTER_TRAIT_TOKEN, type RouterTrait } from \"../router\";\nimport { TIME_TRAIT_TOKEN, type TimeTrait } from \"../scheduling/types\";\nimport {\n\tPERSISTENT_STORAGE_TRAIT_TOKEN,\n\tSESSION_STORAGE_TRAIT_TOKEN,\n} from \"../storage/types\";\nimport {\n\tcreatePageLifecycleForNativeWeb,\n\ttype PageLifecycleForNativeWebCreateOptions,\n} from \"./page\";\nimport {\n\tcreatePopupForNativeWeb,\n\ttype PopupForNativeWebCreateOptions,\n} from \"./popup\";\nimport {\n\tcreateRouterForNativeWeb,\n\ttype RouterForNativeWebCreateOptions,\n} from \"./router\";\nimport {\n\tcreatePersistentStorageForNativeWeb,\n\tcreateSessionStorageForNativeWeb,\n\ttype StorageForNativeWebCreateOptions,\n} from \"./storage\";\n\nexport { type FoundationEnvironment } from \"../environment/types\";\n\nexport interface NativeWebEnvironment extends FoundationEnvironment {\n\trouter: RouterTrait;\n}\n\nexport interface CreateEnvironmentForNativeWebOptions\n\textends CreateFoundationEnvironmentOptions {\n\trouterForNativeWebCreateOptions?: RouterForNativeWebCreateOptions;\n\tpageLifecycleForNativeWebCreateOptions?: PageLifecycleForNativeWebCreateOptions;\n\tpopupForNativeWebCreateOptions?: PopupForNativeWebCreateOptions;\n\tpersistentStorageForNativeWebCreateOptions?: Omit<\n\t\tStorageForNativeWebCreateOptions,\n\t\t\"validatorKey\"\n\t>;\n\tsessionStorageForNativeWebCreateOptions?: Omit<\n\t\tStorageForNativeWebCreateOptions,\n\t\t\"validatorKey\"\n\t>;\n}\n\nexport function createEnvironmentForNativeWeb(\n\toptions: CreateEnvironmentForNativeWebOptions,\n): NativeWebEnvironment {\n\tconst userProviders = options.providers ?? [];\n\tconst externalProviderTokens = new Set(\n\t\tuserProviders.map((provider) => getSecuritydeptProviderToken(provider)),\n\t);\n\tconst providers = [\n\t\t...createNativeWebTraitProviders(options, externalProviderTokens),\n\t\t...userProviders,\n\t];\n\treturn createFoundationEnvironment({\n\t\tproviders,\n\t\ttransport: options.transport,\n\t\ttransportForStdFetchCreateOptions:\n\t\t\toptions.transportForStdFetchCreateOptions,\n\t\ttime: options.time,\n\t\ttimeForStdCreateOptions: options.timeForStdCreateOptions,\n\t\trealmStorage: options.realmStorage,\n\t\tidleCallback: options.idleCallback,\n\t\tspan: options.span,\n\t\tspanCreateOptions: options.spanCreateOptions,\n\t\ttracing: options.tracing,\n\t\ttracingCreateOptions: options.tracingCreateOptions,\n\t\tvalidators: options.validators,\n\t}) as NativeWebEnvironment;\n}\n\nfunction createNativeWebTraitProviders(\n\toptions: CreateEnvironmentForNativeWebOptions,\n\texternalProviderTokens: ReadonlySet<\n\t\tSecuritydeptValueProvider<unknown>[\"provide\"]\n\t>,\n): SecuritydeptProvider[] {\n\treturn [\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tROUTER_TRAIT_TOKEN,\n\t\t\t() =>\n\t\t\t\tcreateNativeWebTraitUnit({\n\t\t\t\t\tprovide: ROUTER_TRAIT_TOKEN,\n\t\t\t\t\tvalue: options.router,\n\t\t\t\t\tcreateValue: () =>\n\t\t\t\t\t\tcreateRouterForNativeWeb({\n\t\t\t\t\t\t\t...options.routerForNativeWebCreateOptions,\n\t\t\t\t\t\t\tvalidators: options.validators,\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t),\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tPAGE_LIFECYCLE_TRAIT_TOKEN,\n\t\t\t() =>\n\t\t\t\tcreateNativeWebTraitUnit({\n\t\t\t\t\tprovide: PAGE_LIFECYCLE_TRAIT_TOKEN,\n\t\t\t\t\tvalue: options.pageLifecycle,\n\t\t\t\t\tcreateValue: () =>\n\t\t\t\t\t\tcreatePageLifecycleForNativeWeb({\n\t\t\t\t\t\t\t...options.pageLifecycleForNativeWebCreateOptions,\n\t\t\t\t\t\t\tvalidators: options.validators,\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t),\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tPOPUP_TRAIT_TOKEN,\n\t\t\t() =>\n\t\t\t\tcreateNativeWebTraitUnit({\n\t\t\t\t\tprovide: POPUP_TRAIT_TOKEN,\n\t\t\t\t\tvalue: options.popup,\n\t\t\t\t\tcreateValue: (time: TimeTrait) =>\n\t\t\t\t\t\tcreatePopupForNativeWeb({\n\t\t\t\t\t\t\ttime,\n\t\t\t\t\t\t\t...options.popupForNativeWebCreateOptions,\n\t\t\t\t\t\t\tvalidators: options.validators,\n\t\t\t\t\t\t}),\n\t\t\t\t\tdeps: [TIME_TRAIT_TOKEN],\n\t\t\t\t}),\n\t\t),\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tPERSISTENT_STORAGE_TRAIT_TOKEN,\n\t\t\t() =>\n\t\t\t\tcreateNativeWebTraitUnit({\n\t\t\t\t\tprovide: PERSISTENT_STORAGE_TRAIT_TOKEN,\n\t\t\t\t\tvalue: options.persistentStorage,\n\t\t\t\t\tcreateValue: () =>\n\t\t\t\t\t\tcreatePersistentStorageForNativeWeb({\n\t\t\t\t\t\t\t...options.persistentStorageForNativeWebCreateOptions,\n\t\t\t\t\t\t\tvalidators: options.validators,\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t),\n\t\tcreateProviderIfTokenMissing(\n\t\t\texternalProviderTokens,\n\t\t\tSESSION_STORAGE_TRAIT_TOKEN,\n\t\t\t() =>\n\t\t\t\tcreateNativeWebTraitUnit({\n\t\t\t\t\tprovide: SESSION_STORAGE_TRAIT_TOKEN,\n\t\t\t\t\tvalue: options.sessionStorage,\n\t\t\t\t\tcreateValue: () =>\n\t\t\t\t\t\tcreateSessionStorageForNativeWeb({\n\t\t\t\t\t\t\t...options.sessionStorageForNativeWebCreateOptions,\n\t\t\t\t\t\t\tvalidators: options.validators,\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t),\n\t].filter(notMissingProvider);\n}\n\nfunction createNativeWebTraitUnit<T>(options: {\n\tprovide: SecuritydeptValueProvider<T | null>[\"provide\"];\n\tvalue: T | null | undefined;\n\tdeps?: readonly SecuritydeptDependencyDescriptor<unknown>[];\n\tcreateValue(...deps: readonly unknown[]): T | null;\n}): SecuritydeptProvider {\n\tif (options.value !== undefined) {\n\t\treturn {\n\t\t\tprovide: options.provide,\n\t\t\tuseValue: options.value,\n\t\t} satisfies SecuritydeptValueProvider<T | null>;\n\t}\n\n\treturn {\n\t\tprovide: options.provide,\n\t\tuseFactory: options.createValue as (...deps: never[]) => T | null,\n\t\tdeps: options.deps,\n\t} satisfies SecuritydeptFactoryProvider<T | null>;\n}\n","import { filter, map } from \"rxjs\";\nimport { type EventStreamTrait } from \"../../events\";\nimport { RxEventStream } from \"../../rx\";\nimport {\n\tfromStorageEvent,\n\ttype StorageEventTarget,\n} from \"../events/from-storage\";\n\n// Cross-tab auth state sync — minimal baseline using storage events\n//\n// Provides a minimal, composable cross-tab sync mechanism for auth state.\n// When another tab writes to the auth persistence key (via localStorage),\n// this listener detects the change and notifies the current tab so it can\n// reconcile its in-memory state.\n//\n// This is intentionally thin — it adapts the browser `storage` event into an\n// event stream. The reconciliation subscriber is the adopter's responsibility\n// (e.g. re-read from persistence, compare with in-memory state, and update).\n//\n// Architecture boundary:\n// - This module does NOT own the persistence store.\n// - It only publishes cross-tab mutations as a stream.\n// - The adopter wires this to their auth state owner.\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Event emitted when a cross-tab storage change is detected for the watched key. */\nexport interface CrossTabSyncEvent {\n\t/** The new value written by the other tab, or null if the key was removed. */\n\tnewValue: string | null;\n\t/** The old value before the other tab's write. */\n\toldValue: string | null;\n}\n\n/** Options for {@link createCrossTabSync}. */\nexport interface CreateCrossTabSyncOptions {\n\t/** The localStorage key to watch for cross-tab changes. */\n\tkey: string;\n\n\tstorageEventTarget: StorageEventTarget;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Create a cross-tab sync listener for a specific localStorage key.\n *\n * The browser `storage` event fires on ALL tabs EXCEPT the one that made the\n * change. This makes it a natural primitive for cross-tab state notification.\n *\n * @example\n * ```ts\n * const subscription = createCrossTabSync({\n * key: \"auth:v1\",\n * storageEventTarget: window,\n * }).subscribe({\n * next: ({ newValue }) => {\n * if (newValue) {\n * // Another tab updated auth state — reconcile\n * client.restorePersistedState();\n * } else {\n * // Another tab cleared auth state — log out\n * controller.clearState({ persistPolicy: \"skip\" });\n * }\n * },\n * });\n * // Later:\n * subscription.unsubscribe();\n * ```\n */\nexport function createCrossTabSync(\n\toptions: CreateCrossTabSyncOptions,\n): EventStreamTrait<CrossTabSyncEvent> {\n\treturn RxEventStream.fromObservableInput(\n\t\tfromStorageEvent({\n\t\t\tstorageEventTarget: options.storageEventTarget,\n\t\t}),\n\t).pipe(\n\t\tfilter((storageEvent) => storageEvent.key === options.key),\n\t\tmap((storageEvent) => ({\n\t\t\tnewValue: storageEvent.newValue,\n\t\t\toldValue: storageEvent.oldValue,\n\t\t})),\n\t);\n}\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
- import { Dn as WithTraitInputValidator, Lt as EnvironmentValidators, Pt as CreateFoundationEnvironmentOptions, Rt as FoundationEnvironment, Vn as RouterTrait, in as StorageTrait } from "../index-D5mW18cM.mjs";
2
- import { o as RouterForNativeWebCreateOptions, u as PageLifecycleForNativeWebCreateOptions } from "../index-BT-u3qNI.mjs";
3
-
1
+ import { Ft as CreateFoundationEnvironmentOptions, Hn as RouterTrait, On as WithTraitInputValidator, Rt as EnvironmentValidators, an as StorageTrait, zt as FoundationEnvironment } from "../index-DmIapvr-.mjs";
2
+ import { o as RouterForNativeWebCreateOptions, u as PageLifecycleForNativeWebCreateOptions } from "../index-O1A3CdBV.mjs";
4
3
  //#region src/webext/router.d.ts
5
4
  interface WebExtRouterBrowserLike {
6
5
  runtime?: {
@@ -1,6 +1,6 @@
1
- import { H as ClientErrorKind, V as ClientError } from "../rx-BoB32Dzg.mjs";
2
- import { G as validateWithSchemaSync, H as throwValidationClientError, J as PAGE_LIFECYCLE_TRAIT_TOKEN, T as ROUTER_TRAIT_TOKEN, U as validateTraitInput, at as createProviderIfTokenMissing, c as PERSISTENT_STORAGE_TRAIT_TOKEN, ot as getSecuritydeptProviderToken, st as notMissingProvider, t as createFoundationEnvironment, u as SESSION_STORAGE_TRAIT_TOKEN } from "../create-Bm-XRA3G.mjs";
3
- import { a as createPageLifecycleForNativeWeb, i as createRouterForNativeWeb } from "../router-BJ8LqNJ1.mjs";
1
+ import { H as ClientErrorKind, V as ClientError } from "../rx-B3OU17wu.mjs";
2
+ import { B as validateWithSchemaSync, L as throwValidationClientError, Q as notMissingProvider, R as validateTraitInput, T as ROUTER_TRAIT_TOKEN, V as PAGE_LIFECYCLE_TRAIT_TOKEN, X as createProviderIfTokenMissing, Z as getSecuritydeptProviderToken, c as PERSISTENT_STORAGE_TRAIT_TOKEN, t as createFoundationEnvironment, u as SESSION_STORAGE_TRAIT_TOKEN } from "../create-99Ksgl_O.mjs";
3
+ import { a as createPageLifecycleForNativeWeb, i as createRouterForNativeWeb } from "../router-DUh3bhLy.mjs";
4
4
  import { type } from "arktype";
5
5
  //#region src/webext/router.ts
6
6
  const WebExtRuntimeRouterLikeSchema = type({ getURL: "Function" });
@@ -58,12 +58,13 @@ function createRouterForWebExt(options = {}) {
58
58
  }
59
59
  //#endregion
60
60
  //#region src/webext/storage.ts
61
+ const WebExtStorageAreaLikeSchema = type({
62
+ get: "Function",
63
+ set: "Function",
64
+ remove: "Function"
65
+ });
61
66
  const StorageForWebExtCreateOptionsSchema = type({
62
- storageArea: type({
63
- get: "Function",
64
- set: "Function",
65
- remove: "Function"
66
- }),
67
+ storageArea: WebExtStorageAreaLikeSchema,
67
68
  prefix: "string | undefined",
68
69
  validatorKey: "'persistentStorage' | 'sessionStorage'"
69
70
  });
@@ -136,8 +137,9 @@ function createSessionStorageForWebExt(options = {}) {
136
137
  //#region src/webext/environment.ts
137
138
  function createEnvironmentForWebExtCore(options) {
138
139
  const userProviders = options.providers ?? [];
140
+ const externalProviderTokens = new Set(userProviders.map((provider) => getSecuritydeptProviderToken(provider)));
139
141
  return createFoundationEnvironment({
140
- providers: [...createWebExtTraitProviders(options, new Set(userProviders.map((provider) => getSecuritydeptProviderToken(provider)))), ...userProviders],
142
+ providers: [...createWebExtTraitProviders(options, externalProviderTokens), ...userProviders],
141
143
  transport: options.transport,
142
144
  transportForStdFetchCreateOptions: options.transportForStdFetchCreateOptions,
143
145
  time: options.time,
@@ -157,7 +159,7 @@ function createEnvironmentForWebExtUI(options) {
157
159
  const userProviders = options.providers ?? [];
158
160
  const userProviderTokens = new Set(userProviders.map((provider) => getSecuritydeptProviderToken(provider)));
159
161
  const uiProviders = createWebExtUITraitProviders(options, userProviderTokens);
160
- const externalProviderTokens = new Set([...userProviderTokens, ...uiProviders.map((provider) => getSecuritydeptProviderToken(provider))]);
162
+ const externalProviderTokens = /* @__PURE__ */ new Set([...userProviderTokens, ...uiProviders.map((provider) => getSecuritydeptProviderToken(provider))]);
161
163
  return createFoundationEnvironment({
162
164
  ...options,
163
165
  providers: [