@securitydept/client 0.3.0-beta.3 → 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.
- package/README.md +6 -0
- package/dist/create-99Ksgl_O.mjs +952 -0
- package/dist/create-99Ksgl_O.mjs.map +1 -0
- package/dist/handle-TnxwtQ4T.mjs +634 -0
- package/dist/handle-TnxwtQ4T.mjs.map +1 -0
- package/dist/index-Cg_iY2yY.d.mts +608 -0
- package/dist/index-DmIapvr-.d.mts +1669 -0
- package/dist/index-O1A3CdBV.d.mts +119 -0
- package/dist/index.d.mts +3 -353
- package/dist/index.mjs +1127 -364
- package/dist/index.mjs.map +1 -1
- package/dist/router-DUh3bhLy.mjs +245 -0
- package/dist/router-DUh3bhLy.mjs.map +1 -0
- package/dist/rx/index.d.mts +68 -0
- package/dist/rx/index.mjs +2 -0
- package/dist/rx-B3OU17wu.mjs +1105 -0
- package/dist/rx-B3OU17wu.mjs.map +1 -0
- package/dist/server/index.d.mts +20 -0
- package/dist/server/index.mjs +29 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/test/index.d.mts +101 -0
- package/dist/test/index.mjs +270 -0
- package/dist/test/index.mjs.map +1 -0
- package/dist/uri-string-BPNbIMgv.mjs +300 -0
- package/dist/uri-string-BPNbIMgv.mjs.map +1 -0
- package/dist/web/index.d.mts +93 -363
- package/dist/web/index.mjs +335 -428
- package/dist/web/index.mjs.map +1 -1
- package/dist/webext/index.d.mts +73 -0
- package/dist/webext/index.mjs +231 -0
- package/dist/webext/index.mjs.map +1 -0
- package/package.json +28 -21
- package/dist/auth-coordination/index.d.mts +0 -198
- package/dist/auth-coordination/index.mjs +0 -107
- package/dist/auth-coordination/index.mjs.map +0 -1
- package/dist/client-environment-CaumNmir.mjs +0 -812
- package/dist/client-environment-CaumNmir.mjs.map +0 -1
- package/dist/client-environment-CdHtVxKW.d.mts +0 -401
- package/dist/events/index.d.mts +0 -2
- package/dist/events/index.mjs +0 -2
- package/dist/events-BUlfsRfl.mjs +0 -127
- package/dist/events-BUlfsRfl.mjs.map +0 -1
- package/dist/index-C4xlKhG7.d.mts +0 -102
- package/dist/index-COUt5x9Z.d.mts +0 -39
- package/dist/persistence/index.d.mts +0 -3
- package/dist/persistence/index.mjs +0 -2
- package/dist/persistence/web/index.d.mts +0 -16
- package/dist/persistence/web/index.mjs +0 -2
- package/dist/persistence-CSB8770k.mjs +0 -108
- package/dist/persistence-CSB8770k.mjs.map +0 -1
- package/dist/planner-host-BTWie0lo.mjs +0 -197
- package/dist/planner-host-BTWie0lo.mjs.map +0 -1
- package/dist/planner-host-DN9dRsQx.d.mts +0 -190
- package/dist/types-BJqUdH2e.d.mts +0 -32
- package/dist/types-BwcnUGNl.d.mts +0 -52
- package/dist/web-DQmMqZnR.mjs +0 -51
- package/dist/web-DQmMqZnR.mjs.map +0 -1
- package/dist/web-router/index.d.mts +0 -259
- package/dist/web-router/index.mjs +0 -395
- package/dist/web-router/index.mjs.map +0 -1
package/dist/events-BUlfsRfl.mjs
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { Observable, ReplaySubject, Subject, merge } from "rxjs";
|
|
2
|
-
import { concatMap, debounceTime, exhaustMap, filter, finalize, map, share, shareReplay, switchMap, takeUntil, tap, throttleTime, withLatestFrom } from "rxjs/operators";
|
|
3
|
-
//#region src/events/event-stream.ts
|
|
4
|
-
const RX_OBSERVABLE = Symbol("securitydept.rxObservable");
|
|
5
|
-
/**
|
|
6
|
-
* Create a new event stream from a producer function.
|
|
7
|
-
*
|
|
8
|
-
* The producer receives an observer and should call `next()` to emit values,
|
|
9
|
-
* `error()` to signal an error, and `complete()` to signal completion.
|
|
10
|
-
* It may return a teardown function that will be called on unsubscribe.
|
|
11
|
-
*/
|
|
12
|
-
function createEventStream(producer) {
|
|
13
|
-
return fromRxObservable(new Observable((subscriber) => {
|
|
14
|
-
const teardown = producer({
|
|
15
|
-
next: (value) => subscriber.next(value),
|
|
16
|
-
error: (error) => subscriber.error(error),
|
|
17
|
-
complete: () => subscriber.complete()
|
|
18
|
-
});
|
|
19
|
-
return () => teardown?.();
|
|
20
|
-
}));
|
|
21
|
-
}
|
|
22
|
-
function createSubject() {
|
|
23
|
-
return wrapSubject(new Subject());
|
|
24
|
-
}
|
|
25
|
-
function createReplaySubject(bufferSize = 1) {
|
|
26
|
-
const subject = wrapSubject(new ReplaySubject(bufferSize));
|
|
27
|
-
return Object.assign(subject, { bufferSize });
|
|
28
|
-
}
|
|
29
|
-
function toRxObservable(stream) {
|
|
30
|
-
const maybeBacked = stream;
|
|
31
|
-
if (maybeBacked[RX_OBSERVABLE]) return maybeBacked[RX_OBSERVABLE];
|
|
32
|
-
return new Observable((subscriber) => {
|
|
33
|
-
const subscription = stream.subscribe({
|
|
34
|
-
next: (value) => subscriber.next(value),
|
|
35
|
-
error: (error) => subscriber.error(error),
|
|
36
|
-
complete: () => subscriber.complete()
|
|
37
|
-
});
|
|
38
|
-
return () => subscription.unsubscribe();
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
function fromRxObservable(observable) {
|
|
42
|
-
return {
|
|
43
|
-
[RX_OBSERVABLE]: observable,
|
|
44
|
-
subscribe(observer) {
|
|
45
|
-
const subscription = observable.subscribe({
|
|
46
|
-
next: (value) => observer.next?.(value),
|
|
47
|
-
error: (error) => observer.error?.(error),
|
|
48
|
-
complete: () => observer.complete?.()
|
|
49
|
-
});
|
|
50
|
-
return { unsubscribe: () => subscription.unsubscribe() };
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
function wrapSubject(subject) {
|
|
55
|
-
return Object.assign(fromRxObservable(subject.asObservable()), {
|
|
56
|
-
next: (value) => subject.next(value),
|
|
57
|
-
error: (error) => subject.error(error),
|
|
58
|
-
complete: () => subject.complete()
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
//#endregion
|
|
62
|
-
//#region src/events/operators.ts
|
|
63
|
-
function pipe(source, ...operators) {
|
|
64
|
-
return operators.reduce((acc, op) => op(acc), source);
|
|
65
|
-
}
|
|
66
|
-
function map$1(fn) {
|
|
67
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(map(fn)));
|
|
68
|
-
}
|
|
69
|
-
function filter$1(predicate) {
|
|
70
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(filter(predicate)));
|
|
71
|
-
}
|
|
72
|
-
function tap$1(fn) {
|
|
73
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(tap(fn)));
|
|
74
|
-
}
|
|
75
|
-
function takeUntil$1(notifier) {
|
|
76
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(takeUntil(toRxObservable(notifier))));
|
|
77
|
-
}
|
|
78
|
-
function finalize$1(fn) {
|
|
79
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(finalize(fn)));
|
|
80
|
-
}
|
|
81
|
-
function merge$1(...sources) {
|
|
82
|
-
return fromRxObservable(merge(...sources.map(toRxObservable)));
|
|
83
|
-
}
|
|
84
|
-
function share$1() {
|
|
85
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(share()));
|
|
86
|
-
}
|
|
87
|
-
function shareReplay$1(bufferSize = 1) {
|
|
88
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(shareReplay({
|
|
89
|
-
bufferSize,
|
|
90
|
-
refCount: true
|
|
91
|
-
})));
|
|
92
|
-
}
|
|
93
|
-
function switchMap$1(fn) {
|
|
94
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(switchMap((value) => toRxObservable(fn(value)))));
|
|
95
|
-
}
|
|
96
|
-
function concatMap$1(fn) {
|
|
97
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(concatMap((value) => toRxObservable(fn(value)))));
|
|
98
|
-
}
|
|
99
|
-
function exhaustMap$1(fn) {
|
|
100
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(exhaustMap((value) => toRxObservable(fn(value)))));
|
|
101
|
-
}
|
|
102
|
-
function debounceTime$1(durationMs) {
|
|
103
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(debounceTime(durationMs)));
|
|
104
|
-
}
|
|
105
|
-
function throttleTime$1(durationMs) {
|
|
106
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(throttleTime(durationMs)));
|
|
107
|
-
}
|
|
108
|
-
function withLatestFromSignal(signal) {
|
|
109
|
-
return (source) => fromRxObservable(toRxObservable(source).pipe(withLatestFrom(toRxObservable(createEventStream((observer) => {
|
|
110
|
-
observer.next?.(signal.get());
|
|
111
|
-
return signal.subscribe(() => observer.next?.(signal.get()));
|
|
112
|
-
})))));
|
|
113
|
-
}
|
|
114
|
-
//#endregion
|
|
115
|
-
//#region src/events/types.ts
|
|
116
|
-
const EventSourceKind = {
|
|
117
|
-
User: "user",
|
|
118
|
-
Timer: "timer",
|
|
119
|
-
Http: "http",
|
|
120
|
-
Storage: "storage",
|
|
121
|
-
Framework: "framework",
|
|
122
|
-
System: "system"
|
|
123
|
-
};
|
|
124
|
-
//#endregion
|
|
125
|
-
export { createEventStream as _, filter$1 as a, fromRxObservable as b, merge$1 as c, shareReplay$1 as d, switchMap$1 as f, withLatestFromSignal as g, throttleTime$1 as h, exhaustMap$1 as i, pipe as l, tap$1 as m, concatMap$1 as n, finalize$1 as o, takeUntil$1 as p, debounceTime$1 as r, map$1 as s, EventSourceKind as t, share$1 as u, createReplaySubject as v, toRxObservable as x, createSubject as y };
|
|
126
|
-
|
|
127
|
-
//# sourceMappingURL=events-BUlfsRfl.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"events-BUlfsRfl.mjs","names":["map","rxMap","filter","rxFilter","tap","rxTap","takeUntil","rxTakeUntil","finalize","rxFinalize","merge","rxMerge","share","rxShare","shareReplay","rxShareReplay","switchMap","rxSwitchMap","concatMap","rxConcatMap","exhaustMap","rxExhaustMap","debounceTime","rxDebounceTime","throttleTime","rxThrottleTime","rxWithLatestFrom"],"sources":["../src/events/event-stream.ts","../src/events/operators.ts","../src/events/types.ts"],"sourcesContent":["import { Observable, ReplaySubject, Subject } from \"rxjs\";\nimport type {\n\tEventObserver,\n\tEventStreamTrait,\n\tEventSubscriptionTrait,\n\tReplaySubjectTrait,\n\tSubjectTrait,\n} from \"./types\";\n\nconst RX_OBSERVABLE = Symbol(\"securitydept.rxObservable\");\n\ntype RxBackedEventStream<T> = EventStreamTrait<T> & {\n\treadonly [RX_OBSERVABLE]: Observable<T>;\n};\n\n/**\n * Create a new event stream from a producer function.\n *\n * The producer receives an observer and should call `next()` to emit values,\n * `error()` to signal an error, and `complete()` to signal completion.\n * It may return a teardown function that will be called on unsubscribe.\n */\nexport function createEventStream<T>(\n\tproducer: (observer: EventObserver<T>) => (() => void) | void,\n): EventStreamTrait<T> {\n\treturn fromRxObservable(\n\t\tnew Observable<T>((subscriber) => {\n\t\t\tconst teardown = producer({\n\t\t\t\tnext: (value) => subscriber.next(value),\n\t\t\t\terror: (error) => subscriber.error(error),\n\t\t\t\tcomplete: () => subscriber.complete(),\n\t\t\t});\n\t\t\treturn () => teardown?.();\n\t\t}),\n\t);\n}\n\nexport function createSubject<T>(): SubjectTrait<T> {\n\treturn wrapSubject(new Subject<T>());\n}\n\nexport function createReplaySubject<T>(bufferSize = 1): ReplaySubjectTrait<T> {\n\tconst subject = wrapSubject(new ReplaySubject<T>(bufferSize));\n\treturn Object.assign(subject, { bufferSize });\n}\n\nexport function toRxObservable<T>(stream: EventStreamTrait<T>): Observable<T> {\n\tconst maybeBacked = stream as Partial<RxBackedEventStream<T>>;\n\tif (maybeBacked[RX_OBSERVABLE]) {\n\t\treturn maybeBacked[RX_OBSERVABLE];\n\t}\n\n\treturn new Observable<T>((subscriber) => {\n\t\tconst subscription = stream.subscribe({\n\t\t\tnext: (value) => subscriber.next(value),\n\t\t\terror: (error) => subscriber.error(error),\n\t\t\tcomplete: () => subscriber.complete(),\n\t\t});\n\t\treturn () => subscription.unsubscribe();\n\t});\n}\n\nexport function fromRxObservable<T>(\n\tobservable: Observable<T>,\n): EventStreamTrait<T> {\n\treturn {\n\t\t[RX_OBSERVABLE]: observable,\n\t\tsubscribe(observer: EventObserver<T>): EventSubscriptionTrait {\n\t\t\tconst subscription = observable.subscribe({\n\t\t\t\tnext: (value) => observer.next?.(value),\n\t\t\t\terror: (error) => observer.error?.(error),\n\t\t\t\tcomplete: () => observer.complete?.(),\n\t\t\t});\n\t\t\treturn { unsubscribe: () => subscription.unsubscribe() };\n\t\t},\n\t} as RxBackedEventStream<T>;\n}\n\nfunction wrapSubject<T>(subject: Subject<T>): SubjectTrait<T> {\n\treturn Object.assign(fromRxObservable(subject.asObservable()), {\n\t\tnext: (value: T) => subject.next(value),\n\t\terror: (error: unknown) => subject.error(error),\n\t\tcomplete: () => subject.complete(),\n\t});\n}\n","import { merge as rxMerge } from \"rxjs\";\nimport {\n\tconcatMap as rxConcatMap,\n\tdebounceTime as rxDebounceTime,\n\texhaustMap as rxExhaustMap,\n\tfilter as rxFilter,\n\tfinalize as rxFinalize,\n\tmap as rxMap,\n\tshare as rxShare,\n\tshareReplay as rxShareReplay,\n\tswitchMap as rxSwitchMap,\n\ttakeUntil as rxTakeUntil,\n\ttap as rxTap,\n\tthrottleTime as rxThrottleTime,\n\twithLatestFrom as rxWithLatestFrom,\n} from \"rxjs/operators\";\nimport type { ReadableSignalTrait } from \"../signals\";\nimport {\n\tcreateEventStream,\n\tfromRxObservable,\n\ttoRxObservable,\n} from \"./event-stream\";\nimport type { EventStreamTrait } from \"./types\";\n\n// --- Operator types ---\n\nexport type EventOperator<A, B> = (\n\tsource: EventStreamTrait<A>,\n) => EventStreamTrait<B>;\n\n// --- pipe ---\n\nexport function pipe<A>(source: EventStreamTrait<A>): EventStreamTrait<A>;\nexport function pipe<A, B>(\n\tsource: EventStreamTrait<A>,\n\top1: EventOperator<A, B>,\n): EventStreamTrait<B>;\nexport function pipe<A, B, C>(\n\tsource: EventStreamTrait<A>,\n\top1: EventOperator<A, B>,\n\top2: EventOperator<B, C>,\n): EventStreamTrait<C>;\nexport function pipe<A, B, C, D>(\n\tsource: EventStreamTrait<A>,\n\top1: EventOperator<A, B>,\n\top2: EventOperator<B, C>,\n\top3: EventOperator<C, D>,\n): EventStreamTrait<D>;\nexport function pipe(\n\tsource: EventStreamTrait<unknown>,\n\t...operators: EventOperator<unknown, unknown>[]\n): EventStreamTrait<unknown> {\n\treturn operators.reduce((acc, op) => op(acc), source);\n}\n\n// --- map ---\n\nexport function map<A, B>(fn: (value: A) => B): EventOperator<A, B> {\n\treturn (source) => fromRxObservable(toRxObservable(source).pipe(rxMap(fn)));\n}\n\n// --- filter ---\n\nexport function filter<A>(\n\tpredicate: (value: A) => boolean,\n): EventOperator<A, A> {\n\treturn (source) =>\n\t\tfromRxObservable(toRxObservable(source).pipe(rxFilter(predicate)));\n}\n\n// --- tap ---\n\nexport function tap<A>(fn: (value: A) => void): EventOperator<A, A> {\n\treturn (source) => fromRxObservable(toRxObservable(source).pipe(rxTap(fn)));\n}\n\n// --- takeUntil ---\n\nexport function takeUntil<A>(\n\tnotifier: EventStreamTrait<unknown>,\n): EventOperator<A, A> {\n\treturn (source) =>\n\t\tfromRxObservable(\n\t\t\ttoRxObservable(source).pipe(rxTakeUntil(toRxObservable(notifier))),\n\t\t);\n}\n\n// --- finalize ---\n\nexport function finalize<A>(fn: () => void): EventOperator<A, A> {\n\treturn (source) =>\n\t\tfromRxObservable(toRxObservable(source).pipe(rxFinalize(fn)));\n}\n\n// --- merge ---\n\nexport function merge<A>(\n\t...sources: EventStreamTrait<A>[]\n): EventStreamTrait<A> {\n\treturn fromRxObservable(rxMerge(...sources.map(toRxObservable)));\n}\n\nexport function share<A>(): EventOperator<A, A> {\n\treturn (source) => fromRxObservable(toRxObservable(source).pipe(rxShare()));\n}\n\nexport function shareReplay<A>(bufferSize = 1): EventOperator<A, A> {\n\treturn (source) =>\n\t\tfromRxObservable(\n\t\t\ttoRxObservable(source).pipe(\n\t\t\t\trxShareReplay({ bufferSize, refCount: true }),\n\t\t\t),\n\t\t);\n}\n\nexport function switchMap<A, B>(\n\tfn: (value: A) => EventStreamTrait<B>,\n): EventOperator<A, B> {\n\treturn (source) =>\n\t\tfromRxObservable(\n\t\t\ttoRxObservable(source).pipe(\n\t\t\t\trxSwitchMap((value) => toRxObservable(fn(value))),\n\t\t\t),\n\t\t);\n}\n\nexport function concatMap<A, B>(\n\tfn: (value: A) => EventStreamTrait<B>,\n): EventOperator<A, B> {\n\treturn (source) =>\n\t\tfromRxObservable(\n\t\t\ttoRxObservable(source).pipe(\n\t\t\t\trxConcatMap((value) => toRxObservable(fn(value))),\n\t\t\t),\n\t\t);\n}\n\nexport function exhaustMap<A, B>(\n\tfn: (value: A) => EventStreamTrait<B>,\n): EventOperator<A, B> {\n\treturn (source) =>\n\t\tfromRxObservable(\n\t\t\ttoRxObservable(source).pipe(\n\t\t\t\trxExhaustMap((value) => toRxObservable(fn(value))),\n\t\t\t),\n\t\t);\n}\n\nexport function debounceTime<A>(durationMs: number): EventOperator<A, A> {\n\treturn (source) =>\n\t\tfromRxObservable(toRxObservable(source).pipe(rxDebounceTime(durationMs)));\n}\n\nexport function throttleTime<A>(durationMs: number): EventOperator<A, A> {\n\treturn (source) =>\n\t\tfromRxObservable(toRxObservable(source).pipe(rxThrottleTime(durationMs)));\n}\n\nexport function withLatestFromSignal<A, B>(\n\tsignal: ReadableSignalTrait<B>,\n): EventOperator<A, [A, B]> {\n\treturn (source) =>\n\t\tfromRxObservable(\n\t\t\ttoRxObservable(source).pipe(\n\t\t\t\trxWithLatestFrom(\n\t\t\t\t\ttoRxObservable(\n\t\t\t\t\t\tcreateEventStream<B>((observer) => {\n\t\t\t\t\t\t\tobserver.next?.(signal.get());\n\t\t\t\t\t\t\treturn signal.subscribe(() => observer.next?.(signal.get()));\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n}\n","// --- Event system trait types ---\n\n/** Subscription handle with explicit unsubscribe. */\nexport interface EventSubscriptionTrait {\n\tunsubscribe(): void;\n}\n\n/** Observer for event streams — mirrors the Observable observer pattern. */\nexport interface EventObserver<T> {\n\tnext?(value: T): void;\n\terror?(error: unknown): void;\n\tcomplete?(): void;\n}\n\n/** Read-only event stream — lazy push-based sequence. */\nexport interface EventStreamTrait<T> {\n\tsubscribe(observer: EventObserver<T>): EventSubscriptionTrait;\n}\n\n/** Hot event producer. */\nexport interface SubjectTrait<T> extends EventStreamTrait<T> {\n\tnext(value: T): void;\n\terror(error: unknown): void;\n\tcomplete(): void;\n}\n\n/** Hot event producer that replays recent values to late subscribers. */\nexport interface ReplaySubjectTrait<T> extends SubjectTrait<T> {\n\treadonly bufferSize: number;\n}\n\n// --- Event envelope ---\n\nexport const EventSourceKind = {\n\tUser: \"user\",\n\tTimer: \"timer\",\n\tHttp: \"http\",\n\tStorage: \"storage\",\n\tFramework: \"framework\",\n\tSystem: \"system\",\n} as const;\n\nexport type EventSourceKind =\n\t(typeof EventSourceKind)[keyof typeof EventSourceKind];\n\nexport type EventSource =\n\t| { kind: typeof EventSourceKind.User; actor?: string }\n\t| { kind: typeof EventSourceKind.Timer; timer: string }\n\t| { kind: typeof EventSourceKind.Http; requestId: string; endpoint?: string }\n\t| { kind: typeof EventSourceKind.Storage; operation: string }\n\t| { kind: typeof EventSourceKind.Framework; name: string }\n\t| { kind: typeof EventSourceKind.System; subsystem: string };\n\nexport interface RuntimeEventEnvelope<TType extends string, TPayload> {\n\tid: string;\n\ttype: TType;\n\tat: number;\n\tsource: EventSource;\n\tpayload: TPayload;\n}\n"],"mappings":"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"}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { n as ReadableSignalTrait } from "./types-BJqUdH2e.mjs";
|
|
2
|
-
import { Observable } from "rxjs";
|
|
3
|
-
|
|
4
|
-
//#region src/events/types.d.ts
|
|
5
|
-
/** Subscription handle with explicit unsubscribe. */
|
|
6
|
-
interface EventSubscriptionTrait {
|
|
7
|
-
unsubscribe(): void;
|
|
8
|
-
}
|
|
9
|
-
/** Observer for event streams — mirrors the Observable observer pattern. */
|
|
10
|
-
interface EventObserver<T> {
|
|
11
|
-
next?(value: T): void;
|
|
12
|
-
error?(error: unknown): void;
|
|
13
|
-
complete?(): void;
|
|
14
|
-
}
|
|
15
|
-
/** Read-only event stream — lazy push-based sequence. */
|
|
16
|
-
interface EventStreamTrait<T> {
|
|
17
|
-
subscribe(observer: EventObserver<T>): EventSubscriptionTrait;
|
|
18
|
-
}
|
|
19
|
-
/** Hot event producer. */
|
|
20
|
-
interface SubjectTrait<T> extends EventStreamTrait<T> {
|
|
21
|
-
next(value: T): void;
|
|
22
|
-
error(error: unknown): void;
|
|
23
|
-
complete(): void;
|
|
24
|
-
}
|
|
25
|
-
/** Hot event producer that replays recent values to late subscribers. */
|
|
26
|
-
interface ReplaySubjectTrait<T> extends SubjectTrait<T> {
|
|
27
|
-
readonly bufferSize: number;
|
|
28
|
-
}
|
|
29
|
-
declare const EventSourceKind: {
|
|
30
|
-
readonly User: "user";
|
|
31
|
-
readonly Timer: "timer";
|
|
32
|
-
readonly Http: "http";
|
|
33
|
-
readonly Storage: "storage";
|
|
34
|
-
readonly Framework: "framework";
|
|
35
|
-
readonly System: "system";
|
|
36
|
-
};
|
|
37
|
-
type EventSourceKind = (typeof EventSourceKind)[keyof typeof EventSourceKind];
|
|
38
|
-
type EventSource = {
|
|
39
|
-
kind: typeof EventSourceKind.User;
|
|
40
|
-
actor?: string;
|
|
41
|
-
} | {
|
|
42
|
-
kind: typeof EventSourceKind.Timer;
|
|
43
|
-
timer: string;
|
|
44
|
-
} | {
|
|
45
|
-
kind: typeof EventSourceKind.Http;
|
|
46
|
-
requestId: string;
|
|
47
|
-
endpoint?: string;
|
|
48
|
-
} | {
|
|
49
|
-
kind: typeof EventSourceKind.Storage;
|
|
50
|
-
operation: string;
|
|
51
|
-
} | {
|
|
52
|
-
kind: typeof EventSourceKind.Framework;
|
|
53
|
-
name: string;
|
|
54
|
-
} | {
|
|
55
|
-
kind: typeof EventSourceKind.System;
|
|
56
|
-
subsystem: string;
|
|
57
|
-
};
|
|
58
|
-
interface RuntimeEventEnvelope<TType extends string, TPayload> {
|
|
59
|
-
id: string;
|
|
60
|
-
type: TType;
|
|
61
|
-
at: number;
|
|
62
|
-
source: EventSource;
|
|
63
|
-
payload: TPayload;
|
|
64
|
-
}
|
|
65
|
-
//#endregion
|
|
66
|
-
//#region src/events/event-stream.d.ts
|
|
67
|
-
/**
|
|
68
|
-
* Create a new event stream from a producer function.
|
|
69
|
-
*
|
|
70
|
-
* The producer receives an observer and should call `next()` to emit values,
|
|
71
|
-
* `error()` to signal an error, and `complete()` to signal completion.
|
|
72
|
-
* It may return a teardown function that will be called on unsubscribe.
|
|
73
|
-
*/
|
|
74
|
-
declare function createEventStream<T>(producer: (observer: EventObserver<T>) => (() => void) | void): EventStreamTrait<T>;
|
|
75
|
-
declare function createSubject<T>(): SubjectTrait<T>;
|
|
76
|
-
declare function createReplaySubject<T>(bufferSize?: number): ReplaySubjectTrait<T>;
|
|
77
|
-
declare function toRxObservable<T>(stream: EventStreamTrait<T>): Observable<T>;
|
|
78
|
-
declare function fromRxObservable<T>(observable: Observable<T>): EventStreamTrait<T>;
|
|
79
|
-
//#endregion
|
|
80
|
-
//#region src/events/operators.d.ts
|
|
81
|
-
type EventOperator<A, B> = (source: EventStreamTrait<A>) => EventStreamTrait<B>;
|
|
82
|
-
declare function pipe<A>(source: EventStreamTrait<A>): EventStreamTrait<A>;
|
|
83
|
-
declare function pipe<A, B>(source: EventStreamTrait<A>, op1: EventOperator<A, B>): EventStreamTrait<B>;
|
|
84
|
-
declare function pipe<A, B, C>(source: EventStreamTrait<A>, op1: EventOperator<A, B>, op2: EventOperator<B, C>): EventStreamTrait<C>;
|
|
85
|
-
declare function pipe<A, B, C, D>(source: EventStreamTrait<A>, op1: EventOperator<A, B>, op2: EventOperator<B, C>, op3: EventOperator<C, D>): EventStreamTrait<D>;
|
|
86
|
-
declare function map<A, B>(fn: (value: A) => B): EventOperator<A, B>;
|
|
87
|
-
declare function filter<A>(predicate: (value: A) => boolean): EventOperator<A, A>;
|
|
88
|
-
declare function tap<A>(fn: (value: A) => void): EventOperator<A, A>;
|
|
89
|
-
declare function takeUntil<A>(notifier: EventStreamTrait<unknown>): EventOperator<A, A>;
|
|
90
|
-
declare function finalize<A>(fn: () => void): EventOperator<A, A>;
|
|
91
|
-
declare function merge$1<A>(...sources: EventStreamTrait<A>[]): EventStreamTrait<A>;
|
|
92
|
-
declare function share<A>(): EventOperator<A, A>;
|
|
93
|
-
declare function shareReplay<A>(bufferSize?: number): EventOperator<A, A>;
|
|
94
|
-
declare function switchMap<A, B>(fn: (value: A) => EventStreamTrait<B>): EventOperator<A, B>;
|
|
95
|
-
declare function concatMap<A, B>(fn: (value: A) => EventStreamTrait<B>): EventOperator<A, B>;
|
|
96
|
-
declare function exhaustMap<A, B>(fn: (value: A) => EventStreamTrait<B>): EventOperator<A, B>;
|
|
97
|
-
declare function debounceTime<A>(durationMs: number): EventOperator<A, A>;
|
|
98
|
-
declare function throttleTime<A>(durationMs: number): EventOperator<A, A>;
|
|
99
|
-
declare function withLatestFromSignal<A, B>(signal: ReadableSignalTrait<B>): EventOperator<A, [A, B]>;
|
|
100
|
-
//#endregion
|
|
101
|
-
export { EventSource as C, ReplaySubjectTrait as D, EventSubscriptionTrait as E, RuntimeEventEnvelope as O, EventObserver as S, EventStreamTrait as T, createEventStream as _, filter as a, fromRxObservable as b, merge$1 as c, shareReplay as d, switchMap as f, withLatestFromSignal as g, throttleTime as h, exhaustMap as i, SubjectTrait as k, pipe as l, tap as m, concatMap as n, finalize as o, takeUntil as p, debounceTime as r, map as s, EventOperator as t, share as u, createReplaySubject as v, EventSourceKind as w, toRxObservable as x, createSubject as y };
|
|
102
|
-
//# sourceMappingURL=index-C4xlKhG7.d.mts.map
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { a as RecordStore, n as EphemeralFlowStore, r as KeyedEphemeralFlowStore, t as Codec } from "./types-BwcnUGNl.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/persistence/ephemeral-flow-store.d.ts
|
|
4
|
-
interface CreateEphemeralFlowStoreOptions<T> {
|
|
5
|
-
store: RecordStore;
|
|
6
|
-
key: string;
|
|
7
|
-
codec?: Codec<T>;
|
|
8
|
-
}
|
|
9
|
-
interface CreateKeyedEphemeralFlowStoreOptions<T> {
|
|
10
|
-
store: RecordStore;
|
|
11
|
-
keyPrefix: string;
|
|
12
|
-
codec?: Codec<T>;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Create a typed ephemeral flow-state store backed by a low-level `RecordStore`.
|
|
16
|
-
*
|
|
17
|
-
* Intended for short-lived browser/session coordination state such as pending
|
|
18
|
-
* redirects or callback fragments.
|
|
19
|
-
*/
|
|
20
|
-
declare function createEphemeralFlowStore<T>(options: CreateEphemeralFlowStoreOptions<T>): EphemeralFlowStore<T>;
|
|
21
|
-
/**
|
|
22
|
-
* Create a typed keyed ephemeral flow-state store backed by a low-level
|
|
23
|
-
* `RecordStore`.
|
|
24
|
-
*
|
|
25
|
-
* Intended for short-lived browser/session coordination state where multiple
|
|
26
|
-
* pending records must coexist and be consumed independently.
|
|
27
|
-
*/
|
|
28
|
-
declare function createKeyedEphemeralFlowStore<T>(options: CreateKeyedEphemeralFlowStoreOptions<T>): KeyedEphemeralFlowStore<T>;
|
|
29
|
-
//#endregion
|
|
30
|
-
//#region src/persistence/json-codec.d.ts
|
|
31
|
-
/** Default JSON codec. */
|
|
32
|
-
declare function createJsonCodec<T>(): Codec<T>;
|
|
33
|
-
//#endregion
|
|
34
|
-
//#region src/persistence/memory-store.d.ts
|
|
35
|
-
/** In-memory `RecordStore` — useful for tests and SSR. */
|
|
36
|
-
declare function createInMemoryRecordStore(): RecordStore;
|
|
37
|
-
//#endregion
|
|
38
|
-
export { createEphemeralFlowStore as a, CreateKeyedEphemeralFlowStoreOptions as i, createJsonCodec as n, createKeyedEphemeralFlowStore as o, CreateEphemeralFlowStoreOptions as r, createInMemoryRecordStore as t };
|
|
39
|
-
//# sourceMappingURL=index-COUt5x9Z.d.mts.map
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { a as RecordStore, i as PersistentAuthStore, n as EphemeralFlowStore, o as RecoverableStateStore, r as KeyedEphemeralFlowStore, s as StoredEnvelope, t as Codec } from "../types-BwcnUGNl.mjs";
|
|
2
|
-
import { a as createEphemeralFlowStore, i as CreateKeyedEphemeralFlowStoreOptions, n as createJsonCodec, o as createKeyedEphemeralFlowStore, r as CreateEphemeralFlowStoreOptions, t as createInMemoryRecordStore } from "../index-COUt5x9Z.mjs";
|
|
3
|
-
export { Codec, CreateEphemeralFlowStoreOptions, CreateKeyedEphemeralFlowStoreOptions, EphemeralFlowStore, KeyedEphemeralFlowStore, PersistentAuthStore, RecordStore, RecoverableStateStore, StoredEnvelope, createEphemeralFlowStore, createInMemoryRecordStore, createJsonCodec, createKeyedEphemeralFlowStore };
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { i as createJsonCodec, n as createEphemeralFlowStore, r as createKeyedEphemeralFlowStore, t as createInMemoryRecordStore } from "../persistence-CSB8770k.mjs";
|
|
2
|
-
export { createEphemeralFlowStore, createInMemoryRecordStore, createJsonCodec, createKeyedEphemeralFlowStore };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { a as RecordStore } from "../../types-BwcnUGNl.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/persistence/web/stores.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* `RecordStore` backed by `localStorage`.
|
|
6
|
-
* @param prefix Optional key prefix to isolate the keyspace.
|
|
7
|
-
*/
|
|
8
|
-
declare function createLocalStorageStore(prefix?: string): RecordStore;
|
|
9
|
-
/**
|
|
10
|
-
* `RecordStore` backed by `sessionStorage`.
|
|
11
|
-
* @param prefix Optional key prefix to isolate the keyspace.
|
|
12
|
-
*/
|
|
13
|
-
declare function createSessionStorageStore(prefix?: string): RecordStore;
|
|
14
|
-
//#endregion
|
|
15
|
-
export { createLocalStorageStore, createSessionStorageStore };
|
|
16
|
-
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
//#region src/persistence/json-codec.ts
|
|
2
|
-
/** Default JSON codec. */
|
|
3
|
-
function createJsonCodec() {
|
|
4
|
-
return {
|
|
5
|
-
encode(value) {
|
|
6
|
-
return JSON.stringify(value);
|
|
7
|
-
},
|
|
8
|
-
decode(raw) {
|
|
9
|
-
return JSON.parse(raw);
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
//#endregion
|
|
14
|
-
//#region src/persistence/ephemeral-flow-store.ts
|
|
15
|
-
function resolveStorageKey(keyPrefix, key) {
|
|
16
|
-
return keyPrefix.length > 0 ? `${keyPrefix}:${key}` : key;
|
|
17
|
-
}
|
|
18
|
-
function requireRecordStoreTake(store) {
|
|
19
|
-
if (!store.take) throw new Error("Ephemeral flow stores require RecordStore.take() for atomic single-consume semantics");
|
|
20
|
-
return store.take.bind(store);
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Create a typed ephemeral flow-state store backed by a low-level `RecordStore`.
|
|
24
|
-
*
|
|
25
|
-
* Intended for short-lived browser/session coordination state such as pending
|
|
26
|
-
* redirects or callback fragments.
|
|
27
|
-
*/
|
|
28
|
-
function createEphemeralFlowStore(options) {
|
|
29
|
-
const codec = options.codec ?? createJsonCodec();
|
|
30
|
-
const storeTake = requireRecordStoreTake(options.store);
|
|
31
|
-
async function load() {
|
|
32
|
-
const raw = await options.store.get(options.key);
|
|
33
|
-
return raw === null ? null : codec.decode(raw);
|
|
34
|
-
}
|
|
35
|
-
async function save(value) {
|
|
36
|
-
await options.store.set(options.key, codec.encode(value));
|
|
37
|
-
}
|
|
38
|
-
async function consume() {
|
|
39
|
-
const raw = await storeTake(options.key);
|
|
40
|
-
return raw === null ? null : codec.decode(raw);
|
|
41
|
-
}
|
|
42
|
-
async function clear() {
|
|
43
|
-
await options.store.remove(options.key);
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
load,
|
|
47
|
-
save,
|
|
48
|
-
consume,
|
|
49
|
-
clear
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Create a typed keyed ephemeral flow-state store backed by a low-level
|
|
54
|
-
* `RecordStore`.
|
|
55
|
-
*
|
|
56
|
-
* Intended for short-lived browser/session coordination state where multiple
|
|
57
|
-
* pending records must coexist and be consumed independently.
|
|
58
|
-
*/
|
|
59
|
-
function createKeyedEphemeralFlowStore(options) {
|
|
60
|
-
const codec = options.codec ?? createJsonCodec();
|
|
61
|
-
const storeTake = requireRecordStoreTake(options.store);
|
|
62
|
-
async function load(key) {
|
|
63
|
-
const raw = await options.store.get(resolveStorageKey(options.keyPrefix, key));
|
|
64
|
-
return raw === null ? null : codec.decode(raw);
|
|
65
|
-
}
|
|
66
|
-
async function save(key, value) {
|
|
67
|
-
await options.store.set(resolveStorageKey(options.keyPrefix, key), codec.encode(value));
|
|
68
|
-
}
|
|
69
|
-
async function take(key) {
|
|
70
|
-
const raw = await storeTake(resolveStorageKey(options.keyPrefix, key));
|
|
71
|
-
return raw === null ? null : codec.decode(raw);
|
|
72
|
-
}
|
|
73
|
-
async function clear(key) {
|
|
74
|
-
await options.store.remove(resolveStorageKey(options.keyPrefix, key));
|
|
75
|
-
}
|
|
76
|
-
return {
|
|
77
|
-
load,
|
|
78
|
-
save,
|
|
79
|
-
take,
|
|
80
|
-
clear
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
//#endregion
|
|
84
|
-
//#region src/persistence/memory-store.ts
|
|
85
|
-
/** In-memory `RecordStore` — useful for tests and SSR. */
|
|
86
|
-
function createInMemoryRecordStore() {
|
|
87
|
-
const store = /* @__PURE__ */ new Map();
|
|
88
|
-
return {
|
|
89
|
-
async get(key) {
|
|
90
|
-
return store.get(key) ?? null;
|
|
91
|
-
},
|
|
92
|
-
async set(key, value) {
|
|
93
|
-
store.set(key, value);
|
|
94
|
-
},
|
|
95
|
-
async take(key) {
|
|
96
|
-
const value = store.get(key) ?? null;
|
|
97
|
-
if (value !== null) store.delete(key);
|
|
98
|
-
return value;
|
|
99
|
-
},
|
|
100
|
-
async remove(key) {
|
|
101
|
-
store.delete(key);
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
//#endregion
|
|
106
|
-
export { createJsonCodec as i, createEphemeralFlowStore as n, createKeyedEphemeralFlowStore as r, createInMemoryRecordStore as t };
|
|
107
|
-
|
|
108
|
-
//# sourceMappingURL=persistence-CSB8770k.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"persistence-CSB8770k.mjs","names":[],"sources":["../src/persistence/json-codec.ts","../src/persistence/ephemeral-flow-store.ts","../src/persistence/memory-store.ts"],"sourcesContent":["import type { Codec } from \"./types\";\n\n/** Default JSON codec. */\nexport function createJsonCodec<T>(): Codec<T> {\n\treturn {\n\t\tencode(value: T): string {\n\t\t\treturn JSON.stringify(value);\n\t\t},\n\t\tdecode(raw: string): T {\n\t\t\treturn JSON.parse(raw) as T;\n\t\t},\n\t};\n}\n","import { createJsonCodec } from \"./json-codec\";\nimport type {\n\tCodec,\n\tEphemeralFlowStore,\n\tKeyedEphemeralFlowStore,\n\tRecordStore,\n} from \"./types\";\n\nexport interface CreateEphemeralFlowStoreOptions<T> {\n\tstore: RecordStore;\n\tkey: string;\n\tcodec?: Codec<T>;\n}\n\nexport interface CreateKeyedEphemeralFlowStoreOptions<T> {\n\tstore: RecordStore;\n\tkeyPrefix: string;\n\tcodec?: Codec<T>;\n}\n\nfunction resolveStorageKey(keyPrefix: string, key: string): string {\n\treturn keyPrefix.length > 0 ? `${keyPrefix}:${key}` : key;\n}\n\nfunction requireRecordStoreTake(\n\tstore: RecordStore,\n): NonNullable<RecordStore[\"take\"]> {\n\tif (!store.take) {\n\t\tthrow new Error(\n\t\t\t\"Ephemeral flow stores require RecordStore.take() for atomic single-consume semantics\",\n\t\t);\n\t}\n\n\treturn store.take.bind(store);\n}\n\n/**\n * Create a typed ephemeral flow-state store backed by a low-level `RecordStore`.\n *\n * Intended for short-lived browser/session coordination state such as pending\n * redirects or callback fragments.\n */\nexport function createEphemeralFlowStore<T>(\n\toptions: CreateEphemeralFlowStoreOptions<T>,\n): EphemeralFlowStore<T> {\n\tconst codec = options.codec ?? createJsonCodec<T>();\n\tconst storeTake = requireRecordStoreTake(options.store);\n\n\tasync function load(): Promise<T | null> {\n\t\tconst raw = await options.store.get(options.key);\n\t\treturn raw === null ? null : codec.decode(raw);\n\t}\n\n\tasync function save(value: T): Promise<void> {\n\t\tawait options.store.set(options.key, codec.encode(value));\n\t}\n\n\tasync function consume(): Promise<T | null> {\n\t\tconst raw = await storeTake(options.key);\n\t\treturn raw === null ? null : codec.decode(raw);\n\t}\n\n\tasync function clear(): Promise<void> {\n\t\tawait options.store.remove(options.key);\n\t}\n\n\treturn {\n\t\tload,\n\t\tsave,\n\t\tconsume,\n\t\tclear,\n\t};\n}\n\n/**\n * Create a typed keyed ephemeral flow-state store backed by a low-level\n * `RecordStore`.\n *\n * Intended for short-lived browser/session coordination state where multiple\n * pending records must coexist and be consumed independently.\n */\nexport function createKeyedEphemeralFlowStore<T>(\n\toptions: CreateKeyedEphemeralFlowStoreOptions<T>,\n): KeyedEphemeralFlowStore<T> {\n\tconst codec = options.codec ?? createJsonCodec<T>();\n\tconst storeTake = requireRecordStoreTake(options.store);\n\n\tasync function load(key: string): Promise<T | null> {\n\t\tconst raw = await options.store.get(\n\t\t\tresolveStorageKey(options.keyPrefix, key),\n\t\t);\n\t\treturn raw === null ? null : codec.decode(raw);\n\t}\n\n\tasync function save(key: string, value: T): Promise<void> {\n\t\tawait options.store.set(\n\t\t\tresolveStorageKey(options.keyPrefix, key),\n\t\t\tcodec.encode(value),\n\t\t);\n\t}\n\n\tasync function take(key: string): Promise<T | null> {\n\t\tconst raw = await storeTake(resolveStorageKey(options.keyPrefix, key));\n\t\treturn raw === null ? null : codec.decode(raw);\n\t}\n\n\tasync function clear(key: string): Promise<void> {\n\t\tawait options.store.remove(resolveStorageKey(options.keyPrefix, key));\n\t}\n\n\treturn {\n\t\tload,\n\t\tsave,\n\t\ttake,\n\t\tclear,\n\t};\n}\n","import type { RecordStore } from \"./types\";\n\n/** In-memory `RecordStore` — useful for tests and SSR. */\nexport function createInMemoryRecordStore(): RecordStore {\n\tconst store = new Map<string, string>();\n\n\treturn {\n\t\tasync get(key: string): Promise<string | null> {\n\t\t\treturn store.get(key) ?? null;\n\t\t},\n\t\tasync set(key: string, value: string): Promise<void> {\n\t\t\tstore.set(key, value);\n\t\t},\n\t\tasync take(key: string): Promise<string | null> {\n\t\t\tconst value = store.get(key) ?? null;\n\t\t\tif (value !== null) {\n\t\t\t\tstore.delete(key);\n\t\t\t}\n\t\t\treturn value;\n\t\t},\n\t\tasync remove(key: string): Promise<void> {\n\t\t\tstore.delete(key);\n\t\t},\n\t};\n}\n"],"mappings":";;AAGA,SAAgB,kBAA+B;CAC9C,OAAO;EACN,OAAO,OAAkB;GACxB,OAAO,KAAK,UAAU,MAAM;;EAE7B,OAAO,KAAgB;GACtB,OAAO,KAAK,MAAM,IAAI;;EAEvB;;;;ACSF,SAAS,kBAAkB,WAAmB,KAAqB;CAClE,OAAO,UAAU,SAAS,IAAI,GAAG,UAAU,GAAG,QAAQ;;AAGvD,SAAS,uBACR,OACmC;CACnC,IAAI,CAAC,MAAM,MACV,MAAM,IAAI,MACT,uFACA;CAGF,OAAO,MAAM,KAAK,KAAK,MAAM;;;;;;;;AAS9B,SAAgB,yBACf,SACwB;CACxB,MAAM,QAAQ,QAAQ,SAAS,iBAAoB;CACnD,MAAM,YAAY,uBAAuB,QAAQ,MAAM;CAEvD,eAAe,OAA0B;EACxC,MAAM,MAAM,MAAM,QAAQ,MAAM,IAAI,QAAQ,IAAI;EAChD,OAAO,QAAQ,OAAO,OAAO,MAAM,OAAO,IAAI;;CAG/C,eAAe,KAAK,OAAyB;EAC5C,MAAM,QAAQ,MAAM,IAAI,QAAQ,KAAK,MAAM,OAAO,MAAM,CAAC;;CAG1D,eAAe,UAA6B;EAC3C,MAAM,MAAM,MAAM,UAAU,QAAQ,IAAI;EACxC,OAAO,QAAQ,OAAO,OAAO,MAAM,OAAO,IAAI;;CAG/C,eAAe,QAAuB;EACrC,MAAM,QAAQ,MAAM,OAAO,QAAQ,IAAI;;CAGxC,OAAO;EACN;EACA;EACA;EACA;EACA;;;;;;;;;AAUF,SAAgB,8BACf,SAC6B;CAC7B,MAAM,QAAQ,QAAQ,SAAS,iBAAoB;CACnD,MAAM,YAAY,uBAAuB,QAAQ,MAAM;CAEvD,eAAe,KAAK,KAAgC;EACnD,MAAM,MAAM,MAAM,QAAQ,MAAM,IAC/B,kBAAkB,QAAQ,WAAW,IAAI,CACzC;EACD,OAAO,QAAQ,OAAO,OAAO,MAAM,OAAO,IAAI;;CAG/C,eAAe,KAAK,KAAa,OAAyB;EACzD,MAAM,QAAQ,MAAM,IACnB,kBAAkB,QAAQ,WAAW,IAAI,EACzC,MAAM,OAAO,MAAM,CACnB;;CAGF,eAAe,KAAK,KAAgC;EACnD,MAAM,MAAM,MAAM,UAAU,kBAAkB,QAAQ,WAAW,IAAI,CAAC;EACtE,OAAO,QAAQ,OAAO,OAAO,MAAM,OAAO,IAAI;;CAG/C,eAAe,MAAM,KAA4B;EAChD,MAAM,QAAQ,MAAM,OAAO,kBAAkB,QAAQ,WAAW,IAAI,CAAC;;CAGtE,OAAO;EACN;EACA;EACA;EACA;EACA;;;;;AChHF,SAAgB,4BAAyC;CACxD,MAAM,wBAAQ,IAAI,KAAqB;CAEvC,OAAO;EACN,MAAM,IAAI,KAAqC;GAC9C,OAAO,MAAM,IAAI,IAAI,IAAI;;EAE1B,MAAM,IAAI,KAAa,OAA8B;GACpD,MAAM,IAAI,KAAK,MAAM;;EAEtB,MAAM,KAAK,KAAqC;GAC/C,MAAM,QAAQ,MAAM,IAAI,IAAI,IAAI;GAChC,IAAI,UAAU,MACb,MAAM,OAAO,IAAI;GAElB,OAAO;;EAER,MAAM,OAAO,KAA4B;GACxC,MAAM,OAAO,IAAI;;EAElB"}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
//#region src/auth-coordination/requirement-planner.ts
|
|
2
|
-
/** Outcome of resolving a single requirement. */
|
|
3
|
-
const ResolutionStatus = {
|
|
4
|
-
Fulfilled: "fulfilled",
|
|
5
|
-
Failed: "failed",
|
|
6
|
-
Skipped: "skipped"
|
|
7
|
-
};
|
|
8
|
-
/** Overall plan status. */
|
|
9
|
-
const PlanStatus = {
|
|
10
|
-
/** There are still pending requirements. */
|
|
11
|
-
Pending: "pending",
|
|
12
|
-
/** All requirements have been resolved. */
|
|
13
|
-
Settled: "settled"
|
|
14
|
-
};
|
|
15
|
-
/** Error thrown when a planner operation is invalid. */
|
|
16
|
-
var RequirementPlannerError = class extends Error {
|
|
17
|
-
constructor(message) {
|
|
18
|
-
super(message);
|
|
19
|
-
this.name = "RequirementPlannerError";
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Create a headless requirement planner.
|
|
24
|
-
*
|
|
25
|
-
* @see {@link RequirementPlanner} for usage.
|
|
26
|
-
*/
|
|
27
|
-
function createRequirementPlanner(options) {
|
|
28
|
-
if (options.requirements.length === 0) throw new RequirementPlannerError("Cannot create a planner with zero requirements");
|
|
29
|
-
const ids = /* @__PURE__ */ new Set();
|
|
30
|
-
for (const req of options.requirements) {
|
|
31
|
-
if (ids.has(req.id)) throw new RequirementPlannerError(`Duplicate requirement ID: "${req.id}"`);
|
|
32
|
-
ids.add(req.id);
|
|
33
|
-
}
|
|
34
|
-
let states = [];
|
|
35
|
-
/** Shallow-clone a requirement to prevent external mutation. */
|
|
36
|
-
function cloneRequirement(r) {
|
|
37
|
-
return {
|
|
38
|
-
...r,
|
|
39
|
-
attributes: r.attributes ? { ...r.attributes } : void 0
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
function initStates() {
|
|
43
|
-
states = options.requirements.map((r) => ({
|
|
44
|
-
requirement: cloneRequirement(r),
|
|
45
|
-
resolution: null
|
|
46
|
-
}));
|
|
47
|
-
}
|
|
48
|
-
initStates();
|
|
49
|
-
function findNextPending() {
|
|
50
|
-
return states.find((s) => s.resolution === null) ?? null;
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
snapshot() {
|
|
54
|
-
const next = findNextPending();
|
|
55
|
-
const resolutions = [];
|
|
56
|
-
for (const s of states) if (s.resolution !== null) resolutions.push({ ...s.resolution });
|
|
57
|
-
return {
|
|
58
|
-
status: next === null ? PlanStatus.Settled : PlanStatus.Pending,
|
|
59
|
-
nextPending: next ? cloneRequirement(next.requirement) : null,
|
|
60
|
-
resolutions,
|
|
61
|
-
total: states.length,
|
|
62
|
-
resolved: resolutions.length
|
|
63
|
-
};
|
|
64
|
-
},
|
|
65
|
-
resolve(resolution) {
|
|
66
|
-
const next = findNextPending();
|
|
67
|
-
if (next === null) throw new RequirementPlannerError("Cannot resolve: all requirements are already settled");
|
|
68
|
-
if (resolution.requirementId !== next.requirement.id) throw new RequirementPlannerError(`Cannot resolve requirement "${resolution.requirementId}": the next pending requirement is "${next.requirement.id}"`);
|
|
69
|
-
next.resolution = resolution;
|
|
70
|
-
},
|
|
71
|
-
reset() {
|
|
72
|
-
initStates();
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
//#endregion
|
|
77
|
-
//#region src/auth-coordination/planner-host.ts
|
|
78
|
-
/**
|
|
79
|
-
* How a child scope's requirements client set relates to its parent.
|
|
80
|
-
*
|
|
81
|
-
* - `inherit` — use the parent's set as-is (child adds nothing)
|
|
82
|
-
* - `merge` — inherit parent's options, then append/override with child's
|
|
83
|
-
* (child options with the same `requirementId` replace parent ones)
|
|
84
|
-
* - `replace` — discard parent's set entirely, use child's set only
|
|
85
|
-
*/
|
|
86
|
-
const RequirementsClientSetComposition = {
|
|
87
|
-
Inherit: "inherit",
|
|
88
|
-
Merge: "merge",
|
|
89
|
-
Replace: "replace"
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* Resolve the effective requirements client set by composing a parent set
|
|
93
|
-
* with a child scope's declaration.
|
|
94
|
-
*
|
|
95
|
-
* @param parentOptions - The parent scope's resolved options (or empty).
|
|
96
|
-
* @param child - The child scope's scoped set (with composition strategy).
|
|
97
|
-
* @returns The effective options after composition.
|
|
98
|
-
*/
|
|
99
|
-
function resolveEffectiveClientSet(parentOptions, child) {
|
|
100
|
-
switch (child.composition) {
|
|
101
|
-
case RequirementsClientSetComposition.Inherit: return [...parentOptions];
|
|
102
|
-
case RequirementsClientSetComposition.Merge: {
|
|
103
|
-
const merged = /* @__PURE__ */ new Map();
|
|
104
|
-
for (const opt of parentOptions) merged.set(opt.requirementId, opt);
|
|
105
|
-
for (const opt of child.options) merged.set(opt.requirementId, opt);
|
|
106
|
-
return [...merged.values()];
|
|
107
|
-
}
|
|
108
|
-
case RequirementsClientSetComposition.Replace: return [...child.options];
|
|
109
|
-
default: {
|
|
110
|
-
const _exhaustive = child.composition;
|
|
111
|
-
throw new Error(`[resolveEffectiveClientSet] Unknown composition: ${_exhaustive}`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Default candidate selector: picks the first unauthenticated candidate
|
|
117
|
-
* in declaration order (which aligns with RequirementPlanner's nextPending).
|
|
118
|
-
*/
|
|
119
|
-
function defaultSelectCandidate(unauthenticated) {
|
|
120
|
-
return unauthenticated[0];
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Create a planner-host instance backed by {@link createRequirementPlanner}.
|
|
124
|
-
*
|
|
125
|
-
* **How it works:**
|
|
126
|
-
*
|
|
127
|
-
* 1. `evaluate()` builds an `AuthRequirement[]` from `candidates`
|
|
128
|
-
* (using each candidate's `requirementId`, `requirementKind`, `label`,
|
|
129
|
-
* and `attributes`).
|
|
130
|
-
* 2. A `RequirementPlanner` is created for this evaluation cycle.
|
|
131
|
-
* 3. Already-authenticated requirements are auto-resolved as `Fulfilled`,
|
|
132
|
-
* respecting the planner's sequential discipline.
|
|
133
|
-
* 4. The planner's `nextPending` determines the first unresolved requirement
|
|
134
|
-
* in declaration order.
|
|
135
|
-
* 5. `selectCandidate` is called with all unauthenticated candidates so
|
|
136
|
-
* adopters can implement custom chooser strategies (e.g. UI dialog).
|
|
137
|
-
* The default strategy picks the first candidate (matching nextPending).
|
|
138
|
-
*
|
|
139
|
-
* `evaluate()` always returns a `Promise` to accommodate async selectors.
|
|
140
|
-
* For synchronous selectors the Promise resolves in the same microtask tick.
|
|
141
|
-
*
|
|
142
|
-
* @example
|
|
143
|
-
* ```ts
|
|
144
|
-
* import { createPlannerHost } from "@securitydept/client/auth-coordination";
|
|
145
|
-
*
|
|
146
|
-
* // Default sequential strategy (sync selector, wrapped in Promise)
|
|
147
|
-
* const host = createPlannerHost();
|
|
148
|
-
* const result = await host.evaluate(candidates);
|
|
149
|
-
*
|
|
150
|
-
* // Async chooser strategy — show a dialog and await user's pick
|
|
151
|
-
* const hostWithChooser = createPlannerHost({
|
|
152
|
-
* selectCandidate: async (candidates) => {
|
|
153
|
-
* return await showChooserDialog(candidates);
|
|
154
|
-
* },
|
|
155
|
-
* });
|
|
156
|
-
* ```
|
|
157
|
-
*/
|
|
158
|
-
function createPlannerHost(options) {
|
|
159
|
-
const selector = options?.selectCandidate ?? defaultSelectCandidate;
|
|
160
|
-
return { async evaluate(candidates) {
|
|
161
|
-
if (candidates.length === 0) return {
|
|
162
|
-
allAuthenticated: true,
|
|
163
|
-
unauthenticatedCandidates: [],
|
|
164
|
-
pendingCandidate: null
|
|
165
|
-
};
|
|
166
|
-
const planner = createRequirementPlanner({ requirements: candidates.map((c) => ({
|
|
167
|
-
id: c.requirementId,
|
|
168
|
-
kind: c.requirementKind,
|
|
169
|
-
label: c.label,
|
|
170
|
-
attributes: c.attributes
|
|
171
|
-
})) });
|
|
172
|
-
for (const candidate of candidates) {
|
|
173
|
-
const snap = planner.snapshot();
|
|
174
|
-
if (snap.status === PlanStatus.Settled) break;
|
|
175
|
-
if (snap.nextPending?.id === candidate.requirementId && candidate.checkAuthenticated()) planner.resolve({
|
|
176
|
-
requirementId: candidate.requirementId,
|
|
177
|
-
status: ResolutionStatus.Fulfilled
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
const finalSnap = planner.snapshot();
|
|
181
|
-
const unauthenticated = candidates.filter((c) => !c.checkAuthenticated());
|
|
182
|
-
if (finalSnap.status === PlanStatus.Settled || unauthenticated.length === 0) return {
|
|
183
|
-
allAuthenticated: true,
|
|
184
|
-
unauthenticatedCandidates: [],
|
|
185
|
-
pendingCandidate: null
|
|
186
|
-
};
|
|
187
|
-
return {
|
|
188
|
-
allAuthenticated: false,
|
|
189
|
-
unauthenticatedCandidates: unauthenticated,
|
|
190
|
-
pendingCandidate: await selector(unauthenticated)
|
|
191
|
-
};
|
|
192
|
-
} };
|
|
193
|
-
}
|
|
194
|
-
//#endregion
|
|
195
|
-
export { RequirementPlannerError as a, PlanStatus as i, createPlannerHost as n, ResolutionStatus as o, resolveEffectiveClientSet as r, createRequirementPlanner as s, RequirementsClientSetComposition as t };
|
|
196
|
-
|
|
197
|
-
//# sourceMappingURL=planner-host-BTWie0lo.mjs.map
|