@securitydept/client 0.3.0-beta.1 → 0.3.0-beta.10

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 (59) hide show
  1. package/README.md +6 -0
  2. package/dist/create-i5VyYgN6.mjs +989 -0
  3. package/dist/create-i5VyYgN6.mjs.map +1 -0
  4. package/dist/handle-DwMgqe7R.mjs +638 -0
  5. package/dist/handle-DwMgqe7R.mjs.map +1 -0
  6. package/dist/index-Bo1BtjZH.d.mts +132 -0
  7. package/dist/index-CFAJ969E.d.mts +674 -0
  8. package/dist/index-CbeZ3AfB.d.mts +1680 -0
  9. package/dist/index.d.mts +3 -353
  10. package/dist/index.mjs +1196 -401
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/router-at5bTdJQ.mjs +245 -0
  13. package/dist/router-at5bTdJQ.mjs.map +1 -0
  14. package/dist/rx/index.d.mts +68 -0
  15. package/dist/rx/index.mjs +2 -0
  16. package/dist/rx-DM6Ouv-m.mjs +1119 -0
  17. package/dist/rx-DM6Ouv-m.mjs.map +1 -0
  18. package/dist/server/index.d.mts +20 -0
  19. package/dist/server/index.mjs +29 -0
  20. package/dist/server/index.mjs.map +1 -0
  21. package/dist/test/index.d.mts +101 -0
  22. package/dist/test/index.mjs +270 -0
  23. package/dist/test/index.mjs.map +1 -0
  24. package/dist/uri-string-BPNbIMgv.mjs +300 -0
  25. package/dist/uri-string-BPNbIMgv.mjs.map +1 -0
  26. package/dist/web/index.d.mts +82 -337
  27. package/dist/web/index.mjs +334 -337
  28. package/dist/web/index.mjs.map +1 -1
  29. package/dist/webext/index.d.mts +73 -0
  30. package/dist/webext/index.mjs +231 -0
  31. package/dist/webext/index.mjs.map +1 -0
  32. package/package.json +28 -21
  33. package/dist/auth-coordination/index.d.mts +0 -198
  34. package/dist/auth-coordination/index.mjs +0 -107
  35. package/dist/auth-coordination/index.mjs.map +0 -1
  36. package/dist/events/index.d.mts +0 -2
  37. package/dist/events/index.mjs +0 -2
  38. package/dist/events-BUlfsRfl.mjs +0 -127
  39. package/dist/events-BUlfsRfl.mjs.map +0 -1
  40. package/dist/fetch-transport-Bd5RyWj2.d.mts +0 -339
  41. package/dist/fetch-transport-DtnSRWAH.mjs +0 -631
  42. package/dist/fetch-transport-DtnSRWAH.mjs.map +0 -1
  43. package/dist/index-C_wgl6dW.d.mts +0 -102
  44. package/dist/index-DbYSFHDe.d.mts +0 -39
  45. package/dist/persistence/index.d.mts +0 -3
  46. package/dist/persistence/index.mjs +0 -2
  47. package/dist/persistence/web/index.d.mts +0 -16
  48. package/dist/persistence/web/index.mjs +0 -51
  49. package/dist/persistence/web/index.mjs.map +0 -1
  50. package/dist/persistence-CSB8770k.mjs +0 -108
  51. package/dist/persistence-CSB8770k.mjs.map +0 -1
  52. package/dist/planner-host-CPyGNyQV.d.mts +0 -190
  53. package/dist/planner-host-CV38bMSn.mjs +0 -195
  54. package/dist/planner-host-CV38bMSn.mjs.map +0 -1
  55. package/dist/types-C59fcM5W.d.mts +0 -52
  56. package/dist/types-DQc088ZP.d.mts +0 -32
  57. package/dist/web-router/index.d.mts +0 -259
  58. package/dist/web-router/index.mjs +0 -395
  59. package/dist/web-router/index.mjs.map +0 -1
@@ -0,0 +1,989 @@
1
+ import { A as RxEventSubject, F as SYMBOL_DISPOSE, H as ClientError, K as UserRecovery, M as isInteropObservableTrait, U as ClientErrorKind, W as ClientErrorSource, j as SYMBOL_OBSERVABLE, k as RxEventStream } from "./rx-DM6Ouv-m.mjs";
2
+ import { v7 } from "uuid";
3
+ import { InjectionToken, Injector, Optional, ReflectiveInjector } from "injection-js";
4
+ import { EMPTY, from, fromEventPattern, map, merge, of } from "rxjs";
5
+ import { type } from "arktype";
6
+ //#region src/injection/types.ts
7
+ var SecuritydeptInjectionToken = class extends InjectionToken {};
8
+ const SecurityDeptOptional = Optional;
9
+ function getSecuritydeptProviderToken(provider) {
10
+ if (typeof provider === "function") return provider;
11
+ return provider.provide;
12
+ }
13
+ function createProviderIfTokenMissing(providedTokens, token, createProvider) {
14
+ return providedTokens.has(token) ? null : createProvider();
15
+ }
16
+ function notMissingProvider(provider) {
17
+ return provider !== null;
18
+ }
19
+ //#endregion
20
+ //#region src/injection/injector.ts
21
+ var SecuritydeptInjector = class SecuritydeptInjector {
22
+ runtimeInjector;
23
+ static resolveAndCreate(providers) {
24
+ const normalized = normalizeProviders([...providers, createInjectorSelfProvider()]);
25
+ return getSecuritydeptInjectorFromRuntime(ReflectiveInjector.resolveAndCreate(normalized.providers));
26
+ }
27
+ static fromParentInjector(parent, providers) {
28
+ const normalized = normalizeProviders([
29
+ {
30
+ provide: PARENT_INJECTOR_TOKEN,
31
+ useValue: parent
32
+ },
33
+ ...providers,
34
+ createInjectorSelfProvider()
35
+ ]);
36
+ return getSecuritydeptInjectorFromRuntime(ReflectiveInjector.resolveAndCreate(normalized.providers, toRuntimeInjector(parent)));
37
+ }
38
+ static fromRuntimeInjector(runtimeInjector) {
39
+ return new SecuritydeptInjector(runtimeInjector);
40
+ }
41
+ constructor(runtimeInjector) {
42
+ this.runtimeInjector = runtimeInjector;
43
+ }
44
+ get(token, notFoundValue) {
45
+ try {
46
+ if (arguments.length === 1) return this.runtimeInjector.get(token);
47
+ return this.runtimeInjector.get(token, notFoundValue);
48
+ } catch (error) {
49
+ throw createInjectorResolutionError(token, error);
50
+ }
51
+ }
52
+ };
53
+ const INJECTOR_TOKEN = new SecuritydeptInjectionToken("INJECTOR_TOKEN");
54
+ const PARENT_INJECTOR_TOKEN = new SecuritydeptInjectionToken("PARENT_INJECTOR_TOKEN");
55
+ function normalizeProviders(providers) {
56
+ return { providers: providers.map((provider) => {
57
+ if (typeof provider === "function") return provider;
58
+ if ("useValue" in provider) return {
59
+ provide: provider.provide,
60
+ useValue: provider.useValue
61
+ };
62
+ if ("useClass" in provider) return {
63
+ provide: provider.provide,
64
+ useFactory: (...deps) => new provider.useClass(...deps),
65
+ deps: provider.deps ? [...provider.deps] : void 0
66
+ };
67
+ if ("useExisting" in provider) return {
68
+ provide: provider.provide,
69
+ useExisting: provider.useExisting
70
+ };
71
+ return {
72
+ provide: provider.provide,
73
+ useFactory: provider.useFactory,
74
+ deps: provider.deps ? [...provider.deps] : void 0
75
+ };
76
+ }) };
77
+ }
78
+ function createInjectorSelfProvider() {
79
+ return {
80
+ provide: INJECTOR_TOKEN,
81
+ useFactory: (runtimeInjector) => SecuritydeptInjector.fromRuntimeInjector(runtimeInjector),
82
+ deps: [Injector]
83
+ };
84
+ }
85
+ function getSecuritydeptInjectorFromRuntime(runtimeInjector) {
86
+ return runtimeInjector.get(INJECTOR_TOKEN);
87
+ }
88
+ var SecuritydeptRuntimeParentAdapter = class extends Injector {
89
+ parent;
90
+ constructor(parent) {
91
+ super();
92
+ this.parent = parent;
93
+ }
94
+ get(token, notFoundValue) {
95
+ if (arguments.length === 1) return this.parent.get(token);
96
+ return this.parent.get(token, notFoundValue);
97
+ }
98
+ };
99
+ function toRuntimeInjector(parent) {
100
+ return new SecuritydeptRuntimeParentAdapter(parent);
101
+ }
102
+ function createInjectorResolutionError(token, error) {
103
+ const tokenLabel = describeDependencyToken(token);
104
+ const originalMessage = error instanceof Error ? error.message : String(error);
105
+ const message = /No provider/i.test(originalMessage) ? `[SecuritydeptInjector] No provider found for ${tokenLabel}.` : `[SecuritydeptInjector] Failed to resolve ${tokenLabel}: ${originalMessage}`;
106
+ return new Error(message, { cause: error instanceof Error ? error : void 0 });
107
+ }
108
+ function describeDependencyToken(token) {
109
+ if (token instanceof InjectionToken) return token.toString().replace(/^InjectionToken\s+/, "Token ");
110
+ if (typeof token === "function" && token.name) return token.name;
111
+ return String(token);
112
+ }
113
+ //#endregion
114
+ //#region src/events/types.ts
115
+ const EventStreamTraitSchema = type({ subscribe: "Function" });
116
+ const EventSourceKind = {
117
+ User: "user",
118
+ Timer: "timer",
119
+ Http: "http",
120
+ Storage: "storage",
121
+ Framework: "framework",
122
+ System: "system"
123
+ };
124
+ function isEventStreamTrait(value) {
125
+ return typeof value === "object" && value !== null && typeof value.subscribe === "function" && isInteropObservableTrait(value);
126
+ }
127
+ //#endregion
128
+ //#region src/page/index.ts
129
+ const PageLifecycleTraitSchema = type({ resume: EventStreamTraitSchema });
130
+ const PAGE_LIFECYCLE_TRAIT_TOKEN = new SecuritydeptInjectionToken("PAGE_LIFECYCLE_TRAIT_TOKEN");
131
+ //#endregion
132
+ //#region src/validation/validator.ts
133
+ function formatValidationFailure(failure) {
134
+ if (!failure) return null;
135
+ const summary = failure.issues.map((issue) => issue.path && issue.path.length > 0 ? `${issue.path.join(".")}: ${issue.message}` : issue.message).join("; ");
136
+ return summary.length > 0 ? summary : null;
137
+ }
138
+ function throwValidationClientError(options) {
139
+ const issueSummary = formatValidationFailure(options.failure);
140
+ throw new ClientError({
141
+ kind: ClientErrorKind.Configuration,
142
+ code: options.code,
143
+ message: issueSummary ? `${options.messagePrefix}: ${issueSummary}.` : `${options.messagePrefix}.`,
144
+ recovery: UserRecovery.RestartFlow,
145
+ source: options.source,
146
+ cause: options.failure?.issues
147
+ });
148
+ }
149
+ /**
150
+ * Validate an unknown input against a `@standard-schema`-compatible schema.
151
+ *
152
+ * This is the foundation-level entry point for SDK validation. It accepts
153
+ * any schema implementing `StandardSchemaV1` and returns a discriminated
154
+ * `ValidationResult`.
155
+ *
156
+ * @example
157
+ * ```ts
158
+ * import { validateWithSchema } from "@securitydept/client";
159
+ * import { z } from "zod";
160
+ *
161
+ * const UserSchema = z.object({ name: z.string() });
162
+ * const result = await validateWithSchema(UserSchema, { name: "Alice" });
163
+ * if (result.success) {
164
+ * console.log(result.value.name);
165
+ * } else {
166
+ * console.error(result.issues);
167
+ * }
168
+ * ```
169
+ */
170
+ async function validateWithSchema(schema, input) {
171
+ const result = await schema["~standard"].validate(input);
172
+ if ("value" in result) return {
173
+ success: true,
174
+ value: result.value
175
+ };
176
+ return {
177
+ success: false,
178
+ issues: result.issues
179
+ };
180
+ }
181
+ /**
182
+ * Validate an unknown input synchronously against a `@standard-schema`-compatible schema.
183
+ *
184
+ * Only use this when you know the schema's validate function returns synchronously.
185
+ * Throws if the schema returns a Promise.
186
+ */
187
+ function validateWithSchemaSync(schema, input) {
188
+ const result = schema["~standard"].validate(input);
189
+ if (result instanceof Promise) throw new Error("validateWithSchemaSync: schema returned a Promise. Use validateWithSchema instead.");
190
+ if ("value" in result) return {
191
+ success: true,
192
+ value: result.value
193
+ };
194
+ return {
195
+ success: false,
196
+ issues: result.issues
197
+ };
198
+ }
199
+ function validateTraitInput(options) {
200
+ if (options.optional === true && (options.value === void 0 || options.value === null)) return;
201
+ const result = validateWithSchemaSync(options.validator ?? options.bundledSchema, options.value);
202
+ if (result.success) return;
203
+ options.onInvalid(result);
204
+ }
205
+ //#endregion
206
+ //#region src/popup/index.ts
207
+ const PopupAttachFailureReason = {
208
+ MissingOpener: "missing_opener",
209
+ MissingOrigin: "missing_origin"
210
+ };
211
+ const PopupTraitSchema = type({
212
+ open: "Function",
213
+ attach: "Function"
214
+ });
215
+ const POPUP_TRAIT_TOKEN = new SecuritydeptInjectionToken("POPUP_TRAIT_TOKEN");
216
+ //#endregion
217
+ //#region src/protocol/compat-fragment.ts
218
+ const SECURITYDEPT_COMPAT_FRAGMENT_VERSION = "v1";
219
+ function appendOrReplaceCompatFragment(input, options, update) {
220
+ const blocks = splitFragmentBlocks(readUriFragmentHash(input));
221
+ if (isCompatFragmentBlock(blocks.at(-1) ?? "")) blocks.pop();
222
+ blocks.push(buildCompatFragmentBlock(options));
223
+ const fragment = joinFragmentBlocks(blocks);
224
+ return {
225
+ fragment,
226
+ url: update(input, fragment)
227
+ };
228
+ }
229
+ function parseCompatFragment(input) {
230
+ const block = splitFragmentBlocks(readUriFragmentHash(input)).at(-1);
231
+ if (!block || !isCompatFragmentBlock(block)) return null;
232
+ const blockParameters = new URLSearchParams(block);
233
+ blockParameters.delete("securitydept");
234
+ const parameters = {};
235
+ blockParameters.forEach((value, key) => {
236
+ parameters[key] = value;
237
+ });
238
+ return {
239
+ payload: blockParameters.toString(),
240
+ parameters
241
+ };
242
+ }
243
+ function takeCompatFragment(input, options) {
244
+ const currentFragment = readUriFragmentHash(input);
245
+ const blocks = splitFragmentBlocks(currentFragment);
246
+ const block = blocks.at(-1);
247
+ if (!block || !isCompatFragmentBlock(block)) return {
248
+ compatFragment: null,
249
+ fragment: currentFragment,
250
+ url: input
251
+ };
252
+ const compatFragment = parseCompatFragment(block);
253
+ if (!compatFragment || options.condition && !options.condition(compatFragment)) return {
254
+ compatFragment: null,
255
+ fragment: currentFragment,
256
+ url: input
257
+ };
258
+ blocks.pop();
259
+ const fragment = joinFragmentBlocks(blocks);
260
+ return {
261
+ compatFragment,
262
+ fragment,
263
+ url: options.update(input, fragment)
264
+ };
265
+ }
266
+ function isCompatFragmentBlock(block) {
267
+ return new URLSearchParams(block.startsWith("#") ? block.slice(1) : block).get("securitydept") === "v1";
268
+ }
269
+ function readUriFragmentHash(input) {
270
+ if (typeof input === "string") return input.startsWith("#") ? input : `#${input}`;
271
+ return input.hash;
272
+ }
273
+ function joinFragmentBlocks(blocks) {
274
+ return blocks.length > 0 ? `#${blocks.join("#")}` : "";
275
+ }
276
+ function splitFragmentBlocks(fragment) {
277
+ if (fragment === "#") return [""];
278
+ const normalized = fragment.startsWith("#") ? fragment.slice(1) : fragment;
279
+ return normalized ? normalized.split("#") : [];
280
+ }
281
+ function buildCompatFragmentBlock(options) {
282
+ const block = new URLSearchParams();
283
+ block.set("securitydept", "v1");
284
+ const payload = typeof options.payload === "string" ? new URLSearchParams(options.payload.startsWith("#") ? options.payload.slice(1) : options.payload) : new URLSearchParams(options.payload);
285
+ for (const [key, value] of payload) if (key !== "securitydept") block.append(key, value);
286
+ return block.toString();
287
+ }
288
+ //#endregion
289
+ //#region src/router/router.ts
290
+ const RouterNavigationIntent = {
291
+ AuthRedirect: "auth_redirect",
292
+ PostAuthRedirect: "post_auth_redirect",
293
+ CallbackCleanup: "callback_cleanup",
294
+ ExternalOpen: "external_open"
295
+ };
296
+ const RouterNavigationMode = {
297
+ Push: "push",
298
+ Replace: "replace",
299
+ External: "external"
300
+ };
301
+ async function takeCompatFragmentFromRouter(router, options = {}) {
302
+ const currentUrl = router.currentUrl();
303
+ if (!currentUrl) return null;
304
+ const { compatFragment, url: cleanedUrl } = takeCompatFragment(currentUrl, {
305
+ condition: options.condition,
306
+ update: (ref, hash) => ref.setHash(hash)
307
+ });
308
+ if (!compatFragment) return null;
309
+ await router.navigate({
310
+ url: cleanedUrl,
311
+ intent: RouterNavigationIntent.CallbackCleanup,
312
+ mode: RouterNavigationMode.Replace
313
+ });
314
+ return compatFragment;
315
+ }
316
+ const RouterTraitSchema = type({
317
+ currentUrl: "Function",
318
+ navigate: "Function"
319
+ });
320
+ const ROUTER_TRAIT_TOKEN = new SecuritydeptInjectionToken("ROUTER_TRAIT_TOKEN");
321
+ //#endregion
322
+ //#region src/scheduling/types.ts
323
+ const TimeTraitSchema = type({
324
+ now: "Function",
325
+ setTimeout: "Function",
326
+ clearTimeout: "Function"
327
+ });
328
+ const TIME_TRAIT_TOKEN = new SecuritydeptInjectionToken("TIME_TRAIT_TOKEN");
329
+ const IDLE_CALLBACK_TRAIT_TOKEN = new SecuritydeptInjectionToken("IDLE_CALLBACK_TRAIT_TOKEN");
330
+ const IdleCallbackTraitSchema = type({
331
+ requestIdleCallback: "Function",
332
+ cancelIdleCallback: "Function"
333
+ });
334
+ //#endregion
335
+ //#region src/span/types.ts
336
+ const SpanCreateOptionsSchema = type({
337
+ idFactory: "Function",
338
+ attributes: "object"
339
+ });
340
+ const SpanTraitSchema = type({
341
+ id: "string",
342
+ fork: "Function",
343
+ getAttributes: "Function",
344
+ getRootToNodePath: "Function",
345
+ getRootToNodeAttributes: "Function"
346
+ });
347
+ const SPAN_TRAIT_TOKEN = new SecuritydeptInjectionToken("SPAN_TRAIT_TOKEN");
348
+ //#endregion
349
+ //#region src/span/span.ts
350
+ function createDefaultSpanId() {
351
+ return `span_${v7()}`;
352
+ }
353
+ var DefaultSpan = class DefaultSpan {
354
+ id;
355
+ parent;
356
+ _sharedAttributes;
357
+ _providerAttributes = /* @__PURE__ */ new Map();
358
+ _idFactory;
359
+ constructor(parent, idFactory, attributes) {
360
+ this._idFactory = idFactory;
361
+ this.id = idFactory();
362
+ this.parent = parent;
363
+ this._sharedAttributes = attributes;
364
+ }
365
+ static root(options = {}) {
366
+ return new DefaultSpan(void 0, options.idFactory ?? createDefaultSpanId, { ...options.attributes ?? {} });
367
+ }
368
+ fork(options = {}) {
369
+ return new DefaultSpan(this, options.idFactory ?? this._idFactory, { ...options.attributes });
370
+ }
371
+ getAttributes(options) {
372
+ if (!options) return this._sharedAttributes;
373
+ const providerAttributes = this._providerAttributes.get(options.providerId) ?? {};
374
+ if (options.withShared === false) return providerAttributes;
375
+ return {
376
+ ...this._sharedAttributes,
377
+ ...providerAttributes
378
+ };
379
+ }
380
+ getRootToNodePath(options = {}) {
381
+ const path = [];
382
+ let current = options.skipSelf ? this.parent : this;
383
+ while (current) {
384
+ path.push(current);
385
+ current = current.parent;
386
+ }
387
+ return path.reverse();
388
+ }
389
+ getRootToNodeAttributes(options = {}) {
390
+ const path = this.getRootToNodePath({ skipSelf: options.skipSelf });
391
+ const frames = [];
392
+ for (const span of path) {
393
+ const attributes = options.providerId !== void 0 ? span.getAttributes({ providerId: options.providerId }) : span.getAttributes();
394
+ if (Object.keys(attributes).length === 0) continue;
395
+ frames.push({
396
+ spanId: span.id,
397
+ ...span.parent ? { parentSpanId: span.parent.id } : {},
398
+ attributes
399
+ });
400
+ }
401
+ return frames;
402
+ }
403
+ setAttributes(attributes, options = {}) {
404
+ if (options.providerId === void 0) {
405
+ this._sharedAttributes = {
406
+ ...this._sharedAttributes,
407
+ ...attributes
408
+ };
409
+ return;
410
+ }
411
+ this._providerAttributes.set(options.providerId, {
412
+ ...this._providerAttributes.get(options.providerId),
413
+ ...attributes
414
+ });
415
+ }
416
+ };
417
+ function createRootSpan(options = {}) {
418
+ const { validators, ...resolvedOptions } = options;
419
+ const resolvedCreateOptions = {
420
+ idFactory: resolvedOptions.idFactory ?? createDefaultSpanId,
421
+ attributes: resolvedOptions.attributes ?? {}
422
+ };
423
+ validateTraitInput({
424
+ value: resolvedCreateOptions,
425
+ bundledSchema: SpanCreateOptionsSchema,
426
+ validator: validators,
427
+ onInvalid: (failure) => throwValidationClientError({
428
+ code: "span.invalid_options",
429
+ source: "span",
430
+ messagePrefix: "createRootSpan could not validate spanCreateOptions",
431
+ failure
432
+ })
433
+ });
434
+ return DefaultSpan.root(resolvedCreateOptions);
435
+ }
436
+ //#endregion
437
+ //#region src/std/events/from-abort.ts
438
+ /**
439
+ * Adapt an `AbortSignal`-like source into an event stream of abort reasons.
440
+ */
441
+ function abortSignalToEventStream(signal) {
442
+ return RxEventStream.fromObservableInput(merge(signal.aborted ? of(signal.reason) : EMPTY, fromEventPattern((handler) => {
443
+ signal.addEventListener?.("abort", handler);
444
+ }, (handler) => {
445
+ signal.removeEventListener?.("abort", handler);
446
+ }).pipe(map(() => signal.reason))));
447
+ }
448
+ //#endregion
449
+ //#region src/std/cancellation/abort-signal.ts
450
+ function abortSignalToCancellationToken(signal) {
451
+ if (!signal) return;
452
+ return {
453
+ get isCancellationRequested() {
454
+ return signal.aborted;
455
+ },
456
+ get reason() {
457
+ return signal.reason;
458
+ },
459
+ get cancellationError() {
460
+ return signal.aborted ? new ClientError({
461
+ kind: ClientErrorKind.Cancelled,
462
+ message: "Request was cancelled via AbortSignal",
463
+ code: "client.cancelled",
464
+ source: ClientErrorSource.Transport,
465
+ cause: signal.reason
466
+ }) : void 0;
467
+ },
468
+ onCancellationRequested(listener) {
469
+ const subscription = abortSignalToEventStream(signal).subscribe({ next: (reason) => listener({
470
+ reason,
471
+ cancellationError: new ClientError({
472
+ kind: ClientErrorKind.Cancelled,
473
+ message: "Request was cancelled via AbortSignal",
474
+ code: "client.cancelled",
475
+ source: ClientErrorSource.Transport,
476
+ cause: reason
477
+ })
478
+ }) });
479
+ return {
480
+ dispose() {
481
+ subscription.unsubscribe();
482
+ },
483
+ [SYMBOL_DISPOSE]: () => {
484
+ subscription.unsubscribe();
485
+ }
486
+ };
487
+ },
488
+ [SYMBOL_OBSERVABLE]() {
489
+ return from(abortSignalToEventStream(signal)).pipe(map((reason) => ({
490
+ reason,
491
+ cancellationError: new ClientError({
492
+ kind: ClientErrorKind.Cancelled,
493
+ message: "Request was cancelled via AbortSignal",
494
+ code: "client.cancelled",
495
+ source: ClientErrorSource.Transport,
496
+ cause: reason
497
+ })
498
+ })));
499
+ },
500
+ throwIfCancellationRequested() {
501
+ if (signal.aborted) throw new ClientError({
502
+ kind: ClientErrorKind.Cancelled,
503
+ message: "Request was cancelled via AbortSignal",
504
+ code: "client.cancelled",
505
+ source: ClientErrorSource.Transport,
506
+ cause: signal.reason
507
+ });
508
+ }
509
+ };
510
+ }
511
+ function cancellationTokenToAbortSignal(token) {
512
+ if (!token) return;
513
+ const controller = new AbortController();
514
+ if (token.isCancellationRequested) controller.abort(token.reason);
515
+ let subscription = token.onCancellationRequested(({ reason }) => {
516
+ controller.abort(reason);
517
+ });
518
+ const dispose = () => {
519
+ if (subscription) {
520
+ subscription.dispose();
521
+ subscription = null;
522
+ }
523
+ };
524
+ return {
525
+ signal: controller.signal,
526
+ dispose,
527
+ [SYMBOL_DISPOSE]: dispose
528
+ };
529
+ }
530
+ function normalizeAbortError(token, error) {
531
+ if (!isAbortError(error) && !token?.isCancellationRequested) return error;
532
+ if (token?.cancellationError) return token.cancellationError;
533
+ return new ClientError({
534
+ kind: ClientErrorKind.Cancelled,
535
+ message: "HTTP request was cancelled",
536
+ code: "client.cancelled",
537
+ source: ClientErrorSource.Transport,
538
+ cause: token?.reason ?? error
539
+ });
540
+ }
541
+ function isAbortError(error) {
542
+ return typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
543
+ }
544
+ //#endregion
545
+ //#region src/std/time.ts
546
+ const TimeTraitStdHostSchema = type({
547
+ Date: type({ now: "Function" }),
548
+ setTimeout: "Function",
549
+ clearTimeout: "Function"
550
+ });
551
+ const TimeForStdCreateOptionsSchema = type({ host: TimeTraitStdHostSchema });
552
+ function createTimeForStd(options = {}) {
553
+ const { validators, ...createOptions } = options;
554
+ const resolvedCreateOptions = { host: createOptions.host ?? globalThis };
555
+ validateTraitInput({
556
+ value: resolvedCreateOptions,
557
+ bundledSchema: TimeForStdCreateOptionsSchema,
558
+ validator: validators,
559
+ onInvalid: (failure) => throwValidationClientError({
560
+ code: "time.invalid_std_options",
561
+ source: "time",
562
+ messagePrefix: "createTimeForStd could not validate timeForStdCreateOptions",
563
+ failure
564
+ })
565
+ });
566
+ const host = resolvedCreateOptions.host;
567
+ return {
568
+ now: () => host.Date.now(),
569
+ setTimeout: (handler, delayMs) => host.setTimeout(handler, delayMs),
570
+ clearTimeout: (handle) => host.clearTimeout(handle)
571
+ };
572
+ }
573
+ //#endregion
574
+ //#region src/transport/types.ts
575
+ const TransportErrorCode = {
576
+ RequestFailed: "transport.request_failed",
577
+ ResponseDecodeFailed: "transport.response_decode_failed",
578
+ InvalidStdFetchOptions: "transport.invalid_std_fetch_options",
579
+ InvalidAngularOptions: "transport.invalid_angular_options"
580
+ };
581
+ const BaseTransportTraitSchema = type({ execute: "Function" });
582
+ const TRANSPORT_TRAIT_TOKEN = new SecuritydeptInjectionToken("TRANSPORT_TRAIT_TOKEN");
583
+ //#endregion
584
+ //#region src/std/transport/base-transport.ts
585
+ const FetchTransportRedirectKind = {
586
+ Follow: "follow",
587
+ Manual: "manual"
588
+ };
589
+ const BaseTransportForStdFetchCreateOptionsSchema = type({
590
+ redirect: "\"follow\" | \"manual\"",
591
+ fetch: "Function",
592
+ baseUrl: "unknown"
593
+ });
594
+ /**
595
+ * Default `BaseTransportTrait` backed by the global `fetch` API.
596
+ *
597
+ * The caller is responsible for ensuring `fetch` is available in the runtime.
598
+ * No polyfill is injected.
599
+ */
600
+ function createBaseTransportForStdFetch(options = {}) {
601
+ const { validators, ...createOptions } = options;
602
+ const resolvedCreateOptions = {
603
+ redirect: createOptions.redirect ?? FetchTransportRedirectKind.Manual,
604
+ fetch: createOptions.fetch ?? fetch,
605
+ baseUrl: createOptions.baseUrl
606
+ };
607
+ validateTraitInput({
608
+ value: resolvedCreateOptions,
609
+ bundledSchema: BaseTransportForStdFetchCreateOptionsSchema,
610
+ validator: validators,
611
+ onInvalid: (failure) => throwValidationClientError({
612
+ code: TransportErrorCode.InvalidStdFetchOptions,
613
+ source: "transport",
614
+ messagePrefix: "createBaseTransportForStdFetch could not validate transportForStdFetchCreateOptions",
615
+ failure
616
+ })
617
+ });
618
+ const redirect = resolvedCreateOptions.redirect;
619
+ const fetchImpl = resolvedCreateOptions.fetch;
620
+ const baseUrl = resolvedCreateOptions.baseUrl;
621
+ return { async execute(request) {
622
+ const requestUrl = baseUrl ? new URL(request.url, baseUrl).toString() : request.url;
623
+ const abortBridge = cancellationTokenToAbortSignal(request.cancellationToken);
624
+ const init = {
625
+ method: request.method,
626
+ headers: request.headers,
627
+ redirect,
628
+ signal: abortBridge?.signal
629
+ };
630
+ if (request.body !== void 0 && request.method !== "GET" && request.method !== "HEAD") init.body = typeof request.body === "string" ? request.body : JSON.stringify(request.body);
631
+ try {
632
+ let res;
633
+ try {
634
+ res = await fetchImpl(requestUrl, init);
635
+ } catch (error) {
636
+ const normalized = normalizeAbortError(request.cancellationToken, error);
637
+ if (normalized instanceof ClientError) throw normalized;
638
+ throw new ClientError({
639
+ kind: ClientErrorKind.Transport,
640
+ message: "The HTTP request could not reach the remote service",
641
+ code: TransportErrorCode.RequestFailed,
642
+ source: ClientErrorSource.Transport,
643
+ retryable: true,
644
+ cause: error
645
+ });
646
+ }
647
+ const responseHeaders = {};
648
+ res.headers.forEach((value, key) => {
649
+ responseHeaders[key] = value;
650
+ });
651
+ let body;
652
+ try {
653
+ if (res.headers.get("content-type")?.includes("application/json")) body = await res.json();
654
+ else if (res.status !== 302 && res.status !== 303 && res.status !== 301) body = await res.text();
655
+ } catch (error) {
656
+ throw new ClientError({
657
+ kind: ClientErrorKind.Protocol,
658
+ message: "The HTTP response body could not be decoded",
659
+ code: TransportErrorCode.ResponseDecodeFailed,
660
+ source: ClientErrorSource.Transport,
661
+ cause: error
662
+ });
663
+ }
664
+ return {
665
+ status: res.status,
666
+ headers: responseHeaders,
667
+ body
668
+ };
669
+ } finally {
670
+ abortBridge?.dispose();
671
+ }
672
+ } };
673
+ }
674
+ //#endregion
675
+ //#region src/storage/types.ts
676
+ const StorageChangeEventOrigin = {
677
+ Local: "local",
678
+ External: "external"
679
+ };
680
+ const StorageTraitSchema = type({
681
+ "storageEvent?": { subscribe: "Function" },
682
+ get: "Function",
683
+ set: "Function",
684
+ take: "Function?",
685
+ remove: "Function"
686
+ });
687
+ const REALM_STORAGE_TRAIT_TOKEN = new SecuritydeptInjectionToken("REALM_STORAGE_TRAIT_TOKEN");
688
+ const PERSISTENT_STORAGE_TRAIT_TOKEN = new SecuritydeptInjectionToken("PERSISTENT_STORAGE_TRAIT_TOKEN");
689
+ const SESSION_STORAGE_TRAIT_TOKEN = new SecuritydeptInjectionToken("SESSION_STORAGE_TRAIT_TOKEN");
690
+ //#endregion
691
+ //#region src/storage/memory-store.ts
692
+ /** In-memory `SyncStorageTrait` — useful for realm state, tests, and SSR. */
693
+ function createInMemoryRecordStore() {
694
+ const store = /* @__PURE__ */ new Map();
695
+ const storageEvent = new RxEventSubject();
696
+ return {
697
+ storageEvent,
698
+ get(key) {
699
+ return store.get(key) ?? null;
700
+ },
701
+ set(key, value) {
702
+ const oldValue = store.get(key) ?? null;
703
+ store.set(key, value);
704
+ storageEvent.next({
705
+ origin: StorageChangeEventOrigin.Local,
706
+ key,
707
+ oldValue,
708
+ newValue: value
709
+ });
710
+ },
711
+ take(key) {
712
+ const value = store.get(key) ?? null;
713
+ if (value !== null) {
714
+ store.delete(key);
715
+ storageEvent.next({
716
+ origin: StorageChangeEventOrigin.Local,
717
+ key,
718
+ oldValue: value,
719
+ newValue: null
720
+ });
721
+ }
722
+ return value;
723
+ },
724
+ remove(key) {
725
+ const oldValue = store.get(key) ?? null;
726
+ if (oldValue !== null) {
727
+ store.delete(key);
728
+ storageEvent.next({
729
+ origin: StorageChangeEventOrigin.Local,
730
+ key,
731
+ oldValue,
732
+ newValue: null
733
+ });
734
+ }
735
+ }
736
+ };
737
+ }
738
+ //#endregion
739
+ //#region src/tracing/subscriber/types.ts
740
+ const TracingSubscriberTraitSchema = type({ record: "Function" });
741
+ //#endregion
742
+ //#region src/tracing/create.ts
743
+ const TracingCreateOptionsSchema = type({ subscribers: TracingSubscriberTraitSchema.array() });
744
+ function createTracing(options) {
745
+ const { validators, ...resolvedOptions } = options ?? {};
746
+ const resolvedCreateOptions = { subscribers: resolvedOptions.subscribers ?? [] };
747
+ validateTraitInput({
748
+ value: resolvedCreateOptions,
749
+ bundledSchema: TracingCreateOptionsSchema,
750
+ validator: validators,
751
+ onInvalid: (failure) => throwValidationClientError({
752
+ code: "tracing.invalid_options",
753
+ source: "tracing",
754
+ messagePrefix: "createTracing could not validate tracingCreateOptions",
755
+ failure
756
+ })
757
+ });
758
+ const subject = new RxEventSubject();
759
+ let subscribers = resolvedCreateOptions.subscribers;
760
+ return {
761
+ record(event) {
762
+ for (const subscriber of subscribers) subscriber.record(event);
763
+ subject.next(event);
764
+ },
765
+ events: subject,
766
+ dispose() {
767
+ subscribers = [];
768
+ },
769
+ [SYMBOL_DISPOSE]() {
770
+ this.dispose();
771
+ }
772
+ };
773
+ }
774
+ //#endregion
775
+ //#region src/tracing/types.ts
776
+ const TracingLevel = {
777
+ Debug: "debug",
778
+ Info: "info",
779
+ Warn: "warn",
780
+ Error: "error"
781
+ };
782
+ const OperationTraceEventType = {
783
+ Started: "operation.started",
784
+ Event: "operation.event",
785
+ Error: "operation.error",
786
+ Ended: "operation.ended"
787
+ };
788
+ const TRACING_SPAN_ATTRIBUTE_PROVIDER_ID = "@securitydept/client/tracing";
789
+ const TracingTraitSchema = type({
790
+ record: "Function",
791
+ dispose: "Function",
792
+ events: EventStreamTraitSchema
793
+ });
794
+ const TRACING_TRAIT_TOKEN = new SecuritydeptInjectionToken("TRACING_TRAIT_TOKEN");
795
+ //#endregion
796
+ //#region src/environment/types.ts
797
+ const ENVIRONMENT_TOKEN = new SecuritydeptInjectionToken("ENVIRONMENT_TOKEN");
798
+ //#endregion
799
+ //#region src/environment/create.ts
800
+ /**
801
+ * Create a `FoundationEnvironment` from explicit trait units and defaults.
802
+ *
803
+ * This helper owns foundation-wide baseline resolution and trait-graph wiring.
804
+ *
805
+ * It may resolve:
806
+ * - public std adapters such as
807
+ * `transportForStdFetchCreateOptions -> transport` and `timeForStdCreateOptions -> time`
808
+ * - public hostless baseline constructors such as
809
+ * `spanCreateOptions -> span` and `tracingCreateOptions -> tracing`
810
+ *
811
+ * Host-material discovery such as resolving `window`, `location`, `history`,
812
+ * or browser storage handles belongs to explicit host adapters such as
813
+ * `@securitydept/client/web`, which must first resolve those inputs into
814
+ * concrete traits before calling this helper.
815
+ */
816
+ function createFoundationEnvironment(overrides) {
817
+ const providers = overrides.providers ?? [];
818
+ const externalProviderTokens = new Set(providers.map((provider) => getSecuritydeptProviderToken(provider)));
819
+ if (externalProviderTokens.has(ENVIRONMENT_TOKEN)) throwValidationClientError({
820
+ code: "environment.foundation_provider_reserved",
821
+ source: "environment",
822
+ messagePrefix: "createFoundationEnvironment does not allow overriding ENVIRONMENT_TOKEN"
823
+ });
824
+ return SecuritydeptInjector.resolveAndCreate([
825
+ ...createBuiltInTraitUnits(overrides, externalProviderTokens),
826
+ ...providers,
827
+ createFoundationEnvironmentUnit()
828
+ ]).get(ENVIRONMENT_TOKEN);
829
+ }
830
+ function createBuiltInTraitUnits(overrides, externalProviderTokens) {
831
+ return [
832
+ createProviderIfTokenMissing(externalProviderTokens, TRANSPORT_TRAIT_TOKEN, () => createBuiltInTraitUnit({
833
+ token: TRANSPORT_TRAIT_TOKEN,
834
+ traitName: "transport",
835
+ bundledSchema: BaseTransportTraitSchema,
836
+ validator: overrides.validators?.transport,
837
+ createValue: () => overrides.transport ?? createBaseTransportForStdFetch({
838
+ ...overrides.transportForStdFetchCreateOptions,
839
+ validators: overrides.validators?.transportForStdFetchCreateOptions
840
+ })
841
+ })),
842
+ createProviderIfTokenMissing(externalProviderTokens, TIME_TRAIT_TOKEN, () => createBuiltInTraitUnit({
843
+ token: TIME_TRAIT_TOKEN,
844
+ traitName: "time",
845
+ bundledSchema: TimeTraitSchema,
846
+ validator: overrides.validators?.time,
847
+ createValue: () => overrides.time ?? createTimeForStd({
848
+ ...overrides.timeForStdCreateOptions,
849
+ validators: overrides.validators?.timeForStdCreateOptions
850
+ })
851
+ })),
852
+ createProviderIfTokenMissing(externalProviderTokens, REALM_STORAGE_TRAIT_TOKEN, () => createBuiltInTraitUnit({
853
+ token: REALM_STORAGE_TRAIT_TOKEN,
854
+ traitName: "realmStorage",
855
+ bundledSchema: StorageTraitSchema,
856
+ validator: overrides.validators?.realmStorage,
857
+ createValue: () => overrides.realmStorage ?? createInMemoryRecordStore()
858
+ })),
859
+ createProviderIfTokenMissing(externalProviderTokens, SPAN_TRAIT_TOKEN, () => createBuiltInTraitUnit({
860
+ token: SPAN_TRAIT_TOKEN,
861
+ traitName: "span",
862
+ bundledSchema: SpanTraitSchema,
863
+ validator: overrides.validators?.span,
864
+ createValue: () => overrides.span ?? createRootSpan({
865
+ ...overrides.spanCreateOptions,
866
+ validators: overrides.validators?.spanCreateOptions
867
+ })
868
+ })),
869
+ createProviderIfTokenMissing(externalProviderTokens, TRACING_TRAIT_TOKEN, () => createBuiltInTraitUnit({
870
+ token: TRACING_TRAIT_TOKEN,
871
+ traitName: "tracing",
872
+ bundledSchema: TracingTraitSchema,
873
+ validator: overrides.validators?.tracing,
874
+ createValue: () => overrides.tracing ?? createTracing({
875
+ ...overrides.tracingCreateOptions,
876
+ validators: overrides.validators?.tracingCreateOptions
877
+ })
878
+ })),
879
+ createProviderIfTokenMissing(externalProviderTokens, IDLE_CALLBACK_TRAIT_TOKEN, () => createBuiltInTraitUnit({
880
+ token: IDLE_CALLBACK_TRAIT_TOKEN,
881
+ traitName: "idleCallback",
882
+ bundledSchema: IdleCallbackTraitSchema,
883
+ validator: overrides.validators?.idleCallback,
884
+ optional: true,
885
+ createValue: () => overrides.idleCallback ?? null
886
+ })),
887
+ createProviderIfTokenMissing(externalProviderTokens, PERSISTENT_STORAGE_TRAIT_TOKEN, () => createBuiltInTraitUnit({
888
+ token: PERSISTENT_STORAGE_TRAIT_TOKEN,
889
+ traitName: "persistentStorage",
890
+ bundledSchema: StorageTraitSchema,
891
+ validator: overrides.validators?.persistentStorage,
892
+ optional: true,
893
+ createValue: () => overrides.persistentStorage ?? null
894
+ })),
895
+ createProviderIfTokenMissing(externalProviderTokens, SESSION_STORAGE_TRAIT_TOKEN, () => createBuiltInTraitUnit({
896
+ token: SESSION_STORAGE_TRAIT_TOKEN,
897
+ traitName: "sessionStorage",
898
+ bundledSchema: StorageTraitSchema,
899
+ validator: overrides.validators?.sessionStorage,
900
+ optional: true,
901
+ createValue: () => overrides.sessionStorage ?? null
902
+ })),
903
+ createProviderIfTokenMissing(externalProviderTokens, ROUTER_TRAIT_TOKEN, () => createBuiltInTraitUnit({
904
+ token: ROUTER_TRAIT_TOKEN,
905
+ traitName: "router",
906
+ bundledSchema: RouterTraitSchema,
907
+ validator: overrides.validators?.router,
908
+ optional: true,
909
+ createValue: () => overrides.router ?? null
910
+ })),
911
+ createProviderIfTokenMissing(externalProviderTokens, PAGE_LIFECYCLE_TRAIT_TOKEN, () => createBuiltInTraitUnit({
912
+ token: PAGE_LIFECYCLE_TRAIT_TOKEN,
913
+ traitName: "pageLifecycle",
914
+ bundledSchema: PageLifecycleTraitSchema,
915
+ validator: overrides.validators?.pageLifecycle,
916
+ optional: true,
917
+ createValue: () => overrides.pageLifecycle ?? null
918
+ })),
919
+ createProviderIfTokenMissing(externalProviderTokens, POPUP_TRAIT_TOKEN, () => createBuiltInTraitUnit({
920
+ token: POPUP_TRAIT_TOKEN,
921
+ traitName: "popup",
922
+ bundledSchema: PopupTraitSchema,
923
+ validator: overrides.validators?.popup,
924
+ optional: true,
925
+ createValue: () => overrides.popup ?? null
926
+ }))
927
+ ].filter(notMissingProvider);
928
+ }
929
+ function createBuiltInTraitUnit(options) {
930
+ return {
931
+ provide: options.token,
932
+ useFactory: ((...deps) => {
933
+ const value = options.createValue(...deps);
934
+ validateTraitInput({
935
+ value,
936
+ bundledSchema: options.bundledSchema,
937
+ validator: options.validator,
938
+ optional: options.optional,
939
+ onInvalid: (failure) => throwValidationClientError({
940
+ code: "environment.trait_validation_failed",
941
+ source: "environment",
942
+ messagePrefix: `createFoundationEnvironment could not validate ${options.traitName}`,
943
+ failure
944
+ })
945
+ });
946
+ return value;
947
+ }),
948
+ deps: options.deps
949
+ };
950
+ }
951
+ function createFoundationEnvironmentUnit() {
952
+ return {
953
+ provide: ENVIRONMENT_TOKEN,
954
+ useFactory: ((injector, transport, time, realmStorage, span, tracing, idleCallback, persistentStorage, sessionStorage, router, pageLifecycle, popup) => {
955
+ return {
956
+ injector,
957
+ transport,
958
+ time,
959
+ realmStorage,
960
+ idleCallback: idleCallback ?? void 0,
961
+ persistentStorage: persistentStorage ?? void 0,
962
+ sessionStorage: sessionStorage ?? void 0,
963
+ span,
964
+ tracing,
965
+ router: router ?? void 0,
966
+ pageLifecycle: pageLifecycle ?? void 0,
967
+ popup: popup ?? void 0
968
+ };
969
+ }),
970
+ deps: [
971
+ INJECTOR_TOKEN,
972
+ TRANSPORT_TRAIT_TOKEN,
973
+ TIME_TRAIT_TOKEN,
974
+ REALM_STORAGE_TRAIT_TOKEN,
975
+ SPAN_TRAIT_TOKEN,
976
+ TRACING_TRAIT_TOKEN,
977
+ IDLE_CALLBACK_TRAIT_TOKEN,
978
+ PERSISTENT_STORAGE_TRAIT_TOKEN,
979
+ SESSION_STORAGE_TRAIT_TOKEN,
980
+ ROUTER_TRAIT_TOKEN,
981
+ PAGE_LIFECYCLE_TRAIT_TOKEN,
982
+ POPUP_TRAIT_TOKEN
983
+ ]
984
+ };
985
+ }
986
+ //#endregion
987
+ export { notMissingProvider as $, SECURITYDEPT_COMPAT_FRAGMENT_VERSION as A, validateWithSchema as B, SPAN_TRAIT_TOKEN as C, RouterNavigationIntent as D, ROUTER_TRAIT_TOKEN as E, POPUP_TRAIT_TOKEN as F, INJECTOR_TOKEN as G, PAGE_LIFECYCLE_TRAIT_TOKEN as H, PopupAttachFailureReason as I, toRuntimeInjector as J, PARENT_INJECTOR_TOKEN as K, formatValidationFailure as L, isCompatFragmentBlock as M, parseCompatFragment as N, RouterNavigationMode as O, takeCompatFragment as P, getSecuritydeptProviderToken as Q, throwValidationClientError as R, createRootSpan as S, TIME_TRAIT_TOKEN as T, EventSourceKind as U, validateWithSchemaSync as V, isEventStreamTrait as W, SecuritydeptInjectionToken as X, SecurityDeptOptional as Y, createProviderIfTokenMissing as Z, createTimeForStd as _, TRACING_TRAIT_TOKEN as a, normalizeAbortError as b, createInMemoryRecordStore as c, SESSION_STORAGE_TRAIT_TOKEN as d, StorageChangeEventOrigin as f, TransportErrorCode as g, TRANSPORT_TRAIT_TOKEN as h, TRACING_SPAN_ATTRIBUTE_PROVIDER_ID as i, appendOrReplaceCompatFragment as j, takeCompatFragmentFromRouter as k, PERSISTENT_STORAGE_TRAIT_TOKEN as l, createBaseTransportForStdFetch as m, ENVIRONMENT_TOKEN as n, TracingLevel as o, FetchTransportRedirectKind as p, SecuritydeptInjector as q, OperationTraceEventType as r, createTracing as s, createFoundationEnvironment as t, REALM_STORAGE_TRAIT_TOKEN as u, abortSignalToCancellationToken as v, IDLE_CALLBACK_TRAIT_TOKEN as w, abortSignalToEventStream as x, cancellationTokenToAbortSignal as y, validateTraitInput as z };
988
+
989
+ //# sourceMappingURL=create-i5VyYgN6.mjs.map