@telperion/ng-pack 1.4.1 → 1.5.0
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 +2 -1
- package/fesm2022/telperion-ng-pack-sse-client.mjs +32 -1
- package/fesm2022/telperion-ng-pack-sse-client.mjs.map +1 -1
- package/fesm2022/telperion-ng-pack-storage-signals.mjs.map +1 -1
- package/fesm2022/telperion-ng-pack-utils.mjs +1 -1
- package/fesm2022/telperion-ng-pack-utils.mjs.map +1 -1
- package/package.json +3 -3
- package/sse-client/README.md +37 -0
- package/types/telperion-ng-pack-sse-client.d.ts +17 -1
- package/types/telperion-ng-pack-storage-signals.d.ts +1 -1
package/README.md
CHANGED
|
@@ -126,11 +126,12 @@ Angular service for Server-Sent Events (SSE) with RxJS Observables and HttpClien
|
|
|
126
126
|
|
|
127
127
|
```typescript
|
|
128
128
|
import { ApplicationConfig } from '@angular/core';
|
|
129
|
-
import { provideSseClient, withSseInterceptors } from '@telperion/ng-pack/sse-client';
|
|
129
|
+
import { provideSseClient, withSseInterceptors, withBaseInit } from '@telperion/ng-pack/sse-client';
|
|
130
130
|
|
|
131
131
|
export const appConfig: ApplicationConfig = {
|
|
132
132
|
providers: [
|
|
133
133
|
provideSseClient(
|
|
134
|
+
withBaseInit({ withCredentials: true }),
|
|
134
135
|
withSseInterceptors(loggingInterceptor, authInterceptor)
|
|
135
136
|
),
|
|
136
137
|
]
|
|
@@ -10,6 +10,37 @@ var SseFeatureKind;
|
|
|
10
10
|
SseFeatureKind[SseFeatureKind["InterceptorFunction"] = 0] = "InterceptorFunction";
|
|
11
11
|
})(SseFeatureKind || (SseFeatureKind = {}));
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Configures default EventSource initialization options for the SSE client.
|
|
15
|
+
* Merges the provided options into every SSE request's `init` via an interceptor.
|
|
16
|
+
*
|
|
17
|
+
* @param init - Partial EventSource initialization options to apply as defaults
|
|
18
|
+
* @returns Array of SSE features to be used with `provideSseClient()`
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* provideSseClient(
|
|
23
|
+
* withBaseInit({ withCredentials: true })
|
|
24
|
+
* )
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
function withBaseInit(init) {
|
|
28
|
+
return [
|
|
29
|
+
{
|
|
30
|
+
kind: SseFeatureKind.InterceptorFunction,
|
|
31
|
+
interceptor(req, next) {
|
|
32
|
+
return next({
|
|
33
|
+
...req,
|
|
34
|
+
init: {
|
|
35
|
+
...req.init,
|
|
36
|
+
...init
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
|
|
13
44
|
/**
|
|
14
45
|
* Configures functional interceptors for the SSE client.
|
|
15
46
|
* Interceptors are executed in the order they are provided.
|
|
@@ -148,5 +179,5 @@ function provideSseClient(...features) {
|
|
|
148
179
|
* Generated bundle index. Do not edit.
|
|
149
180
|
*/
|
|
150
181
|
|
|
151
|
-
export { SSE_INTERCEPTORS, SseClient, SseFeatureKind, provideSseClient, withSseInterceptors };
|
|
182
|
+
export { SSE_INTERCEPTORS, SseClient, SseFeatureKind, provideSseClient, withBaseInit, withSseInterceptors };
|
|
152
183
|
//# sourceMappingURL=telperion-ng-pack-sse-client.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telperion-ng-pack-sse-client.mjs","sources":["../../sse-client/src/features/feature.ts","../../sse-client/src/features/with-interceptors.ts","../../sse-client/src/interceptor.ts","../../sse-client/src/client.ts","../../sse-client/src/provider.ts","../../sse-client/src/telperion-ng-pack-sse-client.ts"],"sourcesContent":["/**\r\n * Enum identifying different types of SSE features.\r\n */\r\nexport enum SseFeatureKind {\r\n InterceptorFunction\r\n}\r\n\r\n/**\r\n * Base interface for SSE feature configurations.\r\n */\r\nexport interface SseFeature {\r\n kind: SseFeatureKind;\r\n}\r\n","import { SseInterceptorFn } from \"../interceptor\";\r\nimport { SseFeature, SseFeatureKind } from \"./feature\";\r\n\r\n/**\r\n * Feature interface for functional interceptors.\r\n * @internal\r\n */\r\nexport interface SseInterceptorFunctionFeature extends SseFeature {\r\n kind: SseFeatureKind.InterceptorFunction;\r\n interceptor: SseInterceptorFn<unknown>;\r\n}\r\n\r\n/**\r\n * Configures functional interceptors for the SSE client.\r\n * Interceptors are executed in the order they are provided.\r\n *\r\n * @param interceptors - One or more functional interceptor functions\r\n * @returns Array of SSE features to be used with provideSseClient()\r\n *\r\n * @example\r\n * ```typescript\r\n * const loggingInterceptor: SseInterceptorFn<any> = (req, next) => {\r\n * console.log('Connecting to:', req.url);\r\n * return next(req);\r\n * };\r\n *\r\n * provideSseClient(\r\n * withSseInterceptors(loggingInterceptor)\r\n * )\r\n * ```\r\n */\r\nexport function withSseInterceptors<T = unknown>(...interceptors: SseInterceptorFn<T>[]): SseFeature[] {\r\n return interceptors.map(interceptor => ({\r\n kind: SseFeatureKind.InterceptorFunction,\r\n interceptor,\r\n }));\r\n}\r\n","import { InjectionToken } from \"@angular/core\";\r\nimport type { Observable } from \"rxjs\";\r\n\r\n/**\r\n * Represents an SSE request with URL and initialization options.\r\n */\r\nexport interface SseRequest {\r\n url: string;\r\n init: EventSourceInit;\r\n}\r\n\r\n/**\r\n * Function type for passing the request to the next handler in the interceptor chain.\r\n */\r\nexport type SseNextFn<T> = (request: SseRequest) => Observable<T>;\r\n\r\n/**\r\n * Functional interceptor type for intercepting SSE requests.\r\n * Interceptors can modify requests, handle errors, add logging, etc.\r\n *\r\n * @example\r\n * ```typescript\r\n * const loggingInterceptor: SseInterceptorFn<any> = (req, next) => {\r\n * console.log('SSE Request:', req.url);\r\n * return next(req);\r\n * };\r\n * ```\r\n */\r\nexport type SseInterceptorFn<T> = (\r\n request: SseRequest,\r\n next: SseNextFn<T>\r\n) => Observable<T>;\r\n\r\n/**\r\n * Class-based interceptor interface for SSE requests.\r\n * Implements the same pattern as Angular's HttpInterceptor.\r\n */\r\nexport interface SseInterceptor<T = unknown> {\r\n sseIntercept<U = T>(...args: Parameters<SseInterceptorFn<U>>): ReturnType<SseInterceptorFn<U>>;\r\n}\r\n\r\n/**\r\n * Injection token for providing SSE interceptors.\r\n * Use with multi: true to provide multiple interceptors.\r\n */\r\nexport const SSE_INTERCEPTORS = new InjectionToken<SseInterceptor<unknown>[]>('Telperion/SSE_INTERCEPTORS');\r\n","import { inject, Injectable } from \"@angular/core\";\r\nimport { Observable } from \"rxjs\";\r\n\r\nimport { SSE_INTERCEPTORS, SseRequest } from \"./interceptor\";\r\n\r\n/**\r\n * Angular service for managing Server-Sent Events (SSE) connections.\r\n * Wraps the EventSource API with RxJS Observables and an HttpClient-inspired interceptor chain.\r\n *\r\n * @example\r\n * ```typescript\r\n * class MyComponent {\r\n * private sseClient = inject(SseClient);\r\n *\r\n * messages$ = this.sseClient.start<string>('/api/events');\r\n * }\r\n * ```\r\n */\r\n@Injectable()\r\nexport class SseClient {\r\n #interceptors = inject(SSE_INTERCEPTORS, { optional: true }) ?? [];\r\n\r\n constructor() {\r\n if (!(this.#interceptors instanceof Array)) {\r\n throw new Error('SSE_INTERCEPTORS must be provided as an array. Please ensure you are using multi: true when providing interceptors.');\r\n }\r\n }\r\n\r\n /**\r\n * Starts a new Server-Sent Events connection and returns an Observable stream.\r\n *\r\n * @param url - The URL endpoint for the SSE connection\r\n * @param init - Optional EventSource initialization configuration\r\n * @returns Observable stream of server-sent events\r\n *\r\n * @example\r\n * ```typescript\r\n * this.sseClient.start<MessageData>('/api/notifications', { withCredentials: true })\r\n * .subscribe(data => console.log('Received:', data));\r\n * ```\r\n */\r\n start<T>(url: string, init: EventSourceInit = {}): Observable<T> {\r\n return this.#interceptors.reduceRight(\r\n (next, interceptor) => (req) => interceptor.sseIntercept(req, next),\r\n (req: SseRequest) => this.#createEventSource(req) as Observable<T>\r\n )({ url, init });\r\n }\r\n\r\n #createEventSource<T>(request: SseRequest): Observable<T> {\r\n return new Observable<T>((subscriber) => {\r\n const eventSource = new EventSource(request.url, request.init);\r\n\r\n function handleMessage(event: MessageEvent) {\r\n subscriber.next(event.data);\r\n }\r\n\r\n function handleError(err: Event) {\r\n subscriber.error(err);\r\n eventSource.close();\r\n }\r\n\r\n eventSource.addEventListener('message', handleMessage);\r\n eventSource.addEventListener('error', handleError);\r\n\r\n return () => {\r\n eventSource.removeEventListener('message', handleMessage);\r\n eventSource.removeEventListener('error', handleError);\r\n eventSource.close();\r\n };\r\n });\r\n }\r\n}\r\n","import { Provider } from \"@angular/core\";\r\n\r\nimport { SseClient } from \"./client\";\r\nimport { SseFeature, SseFeatureKind, SseInterceptorFunctionFeature } from \"./features\";\r\nimport { SSE_INTERCEPTORS } from \"./interceptor\";\r\n\r\n/**\r\n * Provides the SseClient service with optional features.\r\n * Configure SSE client with interceptors and other features using a functional API.\r\n *\r\n * @param features - Optional feature configurations (e.g., withSseInterceptors())\r\n * @returns Array of Angular providers\r\n *\r\n * @example\r\n * ```typescript\r\n * import { provideSseClient, withSseInterceptors } from '@telperion/ng-pack/sse-client';\r\n *\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideSseClient(\r\n * withSseInterceptors(loggingInterceptor, authInterceptor)\r\n * )\r\n * ]\r\n * };\r\n * ```\r\n */\r\nexport function provideSseClient(...features: SseFeature[][]): Provider[] {\r\n const interceptorFns = features\r\n .flat()\r\n .filter(feature => feature.kind === SseFeatureKind.InterceptorFunction)\r\n .map(feature => ({\r\n provide: SSE_INTERCEPTORS,\r\n useValue: {\r\n sseIntercept: (feature as SseInterceptorFunctionFeature).interceptor,\r\n },\r\n multi: true,\r\n }));\r\n\r\n return [\r\n {\r\n provide: SseClient,\r\n useClass: SseClient\r\n },\r\n ...interceptorFns\r\n ];\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"telperion-ng-pack-sse-client.mjs","sources":["../../sse-client/src/features/feature.ts","../../sse-client/src/features/with-base-init.ts","../../sse-client/src/features/with-interceptors.ts","../../sse-client/src/interceptor.ts","../../sse-client/src/client.ts","../../sse-client/src/provider.ts","../../sse-client/src/telperion-ng-pack-sse-client.ts"],"sourcesContent":["/**\r\n * Enum identifying different types of SSE features.\r\n */\r\nexport enum SseFeatureKind {\r\n InterceptorFunction\r\n}\r\n\r\n/**\r\n * Base interface for SSE feature configurations.\r\n */\r\nexport interface SseFeature {\r\n kind: SseFeatureKind;\r\n}\r\n","import { SseFeature, SseFeatureKind } from \"./feature\";\r\nimport { SseInterceptorFunctionFeature } from \"./with-interceptors\";\r\n\r\n/**\r\n * Configures default EventSource initialization options for the SSE client.\r\n * Merges the provided options into every SSE request's `init` via an interceptor.\r\n *\r\n * @param init - Partial EventSource initialization options to apply as defaults\r\n * @returns Array of SSE features to be used with `provideSseClient()`\r\n *\r\n * @example\r\n * ```typescript\r\n * provideSseClient(\r\n * withBaseInit({ withCredentials: true })\r\n * )\r\n * ```\r\n */\r\nexport function withBaseInit(init: Partial<EventSourceInit>): SseFeature[] {\r\n return [\r\n <SseInterceptorFunctionFeature>{\r\n kind: SseFeatureKind.InterceptorFunction,\r\n interceptor(req, next) {\r\n return next({\r\n ...req,\r\n init: {\r\n ...req.init,\r\n ...init\r\n }\r\n })\r\n }\r\n }\r\n ]\r\n}\r\n","import { SseInterceptorFn } from \"../interceptor\";\r\nimport { SseFeature, SseFeatureKind } from \"./feature\";\r\n\r\n/**\r\n * Feature interface for functional interceptors.\r\n * @internal\r\n */\r\nexport interface SseInterceptorFunctionFeature extends SseFeature {\r\n kind: SseFeatureKind.InterceptorFunction;\r\n interceptor: SseInterceptorFn<unknown>;\r\n}\r\n\r\n/**\r\n * Configures functional interceptors for the SSE client.\r\n * Interceptors are executed in the order they are provided.\r\n *\r\n * @param interceptors - One or more functional interceptor functions\r\n * @returns Array of SSE features to be used with provideSseClient()\r\n *\r\n * @example\r\n * ```typescript\r\n * const loggingInterceptor: SseInterceptorFn<any> = (req, next) => {\r\n * console.log('Connecting to:', req.url);\r\n * return next(req);\r\n * };\r\n *\r\n * provideSseClient(\r\n * withSseInterceptors(loggingInterceptor)\r\n * )\r\n * ```\r\n */\r\nexport function withSseInterceptors<T = unknown>(...interceptors: SseInterceptorFn<T>[]): SseFeature[] {\r\n return interceptors.map(interceptor => ({\r\n kind: SseFeatureKind.InterceptorFunction,\r\n interceptor,\r\n }));\r\n}\r\n","import { InjectionToken } from \"@angular/core\";\r\nimport type { Observable } from \"rxjs\";\r\n\r\n/**\r\n * Represents an SSE request with URL and initialization options.\r\n */\r\nexport interface SseRequest {\r\n url: string;\r\n init: EventSourceInit;\r\n}\r\n\r\n/**\r\n * Function type for passing the request to the next handler in the interceptor chain.\r\n */\r\nexport type SseNextFn<T> = (request: SseRequest) => Observable<T>;\r\n\r\n/**\r\n * Functional interceptor type for intercepting SSE requests.\r\n * Interceptors can modify requests, handle errors, add logging, etc.\r\n *\r\n * @example\r\n * ```typescript\r\n * const loggingInterceptor: SseInterceptorFn<any> = (req, next) => {\r\n * console.log('SSE Request:', req.url);\r\n * return next(req);\r\n * };\r\n * ```\r\n */\r\nexport type SseInterceptorFn<T> = (\r\n request: SseRequest,\r\n next: SseNextFn<T>\r\n) => Observable<T>;\r\n\r\n/**\r\n * Class-based interceptor interface for SSE requests.\r\n * Implements the same pattern as Angular's HttpInterceptor.\r\n */\r\nexport interface SseInterceptor<T = unknown> {\r\n sseIntercept<U = T>(...args: Parameters<SseInterceptorFn<U>>): ReturnType<SseInterceptorFn<U>>;\r\n}\r\n\r\n/**\r\n * Injection token for providing SSE interceptors.\r\n * Use with multi: true to provide multiple interceptors.\r\n */\r\nexport const SSE_INTERCEPTORS = new InjectionToken<SseInterceptor<unknown>[]>('Telperion/SSE_INTERCEPTORS');\r\n","import { inject, Injectable } from \"@angular/core\";\r\nimport { Observable } from \"rxjs\";\r\n\r\nimport { SSE_INTERCEPTORS, SseRequest } from \"./interceptor\";\r\n\r\n/**\r\n * Angular service for managing Server-Sent Events (SSE) connections.\r\n * Wraps the EventSource API with RxJS Observables and an HttpClient-inspired interceptor chain.\r\n *\r\n * @example\r\n * ```typescript\r\n * class MyComponent {\r\n * private sseClient = inject(SseClient);\r\n *\r\n * messages$ = this.sseClient.start<string>('/api/events');\r\n * }\r\n * ```\r\n */\r\n@Injectable()\r\nexport class SseClient {\r\n #interceptors = inject(SSE_INTERCEPTORS, { optional: true }) ?? [];\r\n\r\n constructor() {\r\n if (!(this.#interceptors instanceof Array)) {\r\n throw new Error('SSE_INTERCEPTORS must be provided as an array. Please ensure you are using multi: true when providing interceptors.');\r\n }\r\n }\r\n\r\n /**\r\n * Starts a new Server-Sent Events connection and returns an Observable stream.\r\n *\r\n * @param url - The URL endpoint for the SSE connection\r\n * @param init - Optional EventSource initialization configuration\r\n * @returns Observable stream of server-sent events\r\n *\r\n * @example\r\n * ```typescript\r\n * this.sseClient.start<MessageData>('/api/notifications', { withCredentials: true })\r\n * .subscribe(data => console.log('Received:', data));\r\n * ```\r\n */\r\n start<T>(url: string, init: EventSourceInit = {}): Observable<T> {\r\n return this.#interceptors.reduceRight(\r\n (next, interceptor) => (req) => interceptor.sseIntercept(req, next),\r\n (req: SseRequest) => this.#createEventSource(req) as Observable<T>\r\n )({ url, init });\r\n }\r\n\r\n #createEventSource<T>(request: SseRequest): Observable<T> {\r\n return new Observable<T>((subscriber) => {\r\n const eventSource = new EventSource(request.url, request.init);\r\n\r\n function handleMessage(event: MessageEvent) {\r\n subscriber.next(event.data);\r\n }\r\n\r\n function handleError(err: Event) {\r\n subscriber.error(err);\r\n eventSource.close();\r\n }\r\n\r\n eventSource.addEventListener('message', handleMessage);\r\n eventSource.addEventListener('error', handleError);\r\n\r\n return () => {\r\n eventSource.removeEventListener('message', handleMessage);\r\n eventSource.removeEventListener('error', handleError);\r\n eventSource.close();\r\n };\r\n });\r\n }\r\n}\r\n","import { Provider } from \"@angular/core\";\r\n\r\nimport { SseClient } from \"./client\";\r\nimport { SseFeature, SseFeatureKind, SseInterceptorFunctionFeature } from \"./features\";\r\nimport { SSE_INTERCEPTORS } from \"./interceptor\";\r\n\r\n/**\r\n * Provides the SseClient service with optional features.\r\n * Configure SSE client with interceptors and other features using a functional API.\r\n *\r\n * @param features - Optional feature configurations (e.g., withSseInterceptors())\r\n * @returns Array of Angular providers\r\n *\r\n * @example\r\n * ```typescript\r\n * import { provideSseClient, withSseInterceptors } from '@telperion/ng-pack/sse-client';\r\n *\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideSseClient(\r\n * withSseInterceptors(loggingInterceptor, authInterceptor)\r\n * )\r\n * ]\r\n * };\r\n * ```\r\n */\r\nexport function provideSseClient(...features: SseFeature[][]): Provider[] {\r\n const interceptorFns = features\r\n .flat()\r\n .filter(feature => feature.kind === SseFeatureKind.InterceptorFunction)\r\n .map(feature => ({\r\n provide: SSE_INTERCEPTORS,\r\n useValue: {\r\n sseIntercept: (feature as SseInterceptorFunctionFeature).interceptor,\r\n },\r\n multi: true,\r\n }));\r\n\r\n return [\r\n {\r\n provide: SseClient,\r\n useClass: SseClient\r\n },\r\n ...interceptorFns\r\n ];\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telperion-ng-pack-storage-signals.mjs","sources":["../../storage-signals/src/storage.ts","../../storage-signals/src/local-storage.ts","../../storage-signals/src/session-storage.ts","../../storage-signals/src/cookie-storage.ts","../../storage-signals/src/telperion-ng-pack-storage-signals.ts"],"sourcesContent":["import { toSignal } from \"@angular/core/rxjs-interop\";\r\nimport { ReactiveStorage } from '@telperion/reactive-storage';\r\nimport { StorageSignal } from \"./storage-signal\";\r\n\r\n/**\r\n * Creates a StorageSignal from a ReactiveStorage instance.\r\n *\r\n * @template T - The type of value stored\r\n * @param storage - The ReactiveStorage instance (localStorage, sessionStorage, or cookie storage)\r\n * @param store - The storage namespace/store name\r\n * @param key - The key within the store\r\n * @returns A StorageSignal that provides reactive access to the stored value\r\n *\r\n * @remarks\r\n * This is a low-level factory function that bridges Angular signals with ReactiveStorage.\r\n * Most applications should use the higher-level functions:\r\n * - {@link localStorageSignal} for localStorage\r\n * - {@link sessionStorageSignal} for sessionStorage\r\n * - {@link cookieStorageSignal} for cookies\r\n *\r\n * The function:\r\n * 1. Converts the ReactiveStorage Observable into an Angular signal using `toSignal`\r\n * 2. Creates a Proxy that intercepts calls to add `set`, `update`, and `delete` methods\r\n * 3. Ensures all storage operations propagate to both the underlying storage and the signal\r\n *\r\n * **Proxy Pattern:**\r\n * The returned signal is a Proxy that:\r\n * - Delegates reading to the underlying signal\r\n * - Provides `set()` to write values\r\n * - Provides `update()` for functional updates\r\n * - Provides `delete()` to remove the value\r\n *\r\n * @example\r\n * ```typescript\r\n * // Typically used internally by specialized signal creators\r\n * import { ReactiveWebLocalStorage } from '@telperion/reactive-storage';\r\n *\r\n * const storage = new ReactiveWebLocalStorage('my-app');\r\n * const userSignal = storageSignal<User>(storage, 'users', 'current');\r\n *\r\n * userSignal.set({ id: 1, name: 'Alice' });\r\n * console.log(userSignal()); // { id: 1, name: 'Alice' }\r\n *\r\n * userSignal.update(user => ({ ...user, name: 'Bob' }));\r\n * userSignal.delete();\r\n * ```\r\n *\r\n * @internal This is primarily for internal use. Use the specialized signal creators instead.\r\n */\r\nexport function storageSignal<T>(storage: ReactiveStorage, store: string, key: string): StorageSignal<T> {\r\n const source = toSignal(storage.get<T>(store, key));\r\n\r\n function setter(value: T | null | undefined) {\r\n storage.set(store, key, value);\r\n }\r\n\r\n function updater(updaterFn: (value: T | null | undefined) => T | null | undefined) {\r\n const currentValue = source();\r\n const newValue = updaterFn(currentValue);\r\n\r\n storage.set(store, key, newValue);\r\n }\r\n\r\n function deleter() {\r\n storage.delete(store, key);\r\n }\r\n\r\n return new Proxy(source as StorageSignal<T>, {\r\n apply() {\r\n return source();\r\n },\r\n get(target, prop, receiver) {\r\n switch (prop) {\r\n case 'set':\r\n return setter;\r\n case 'update':\r\n return updater;\r\n case 'delete':\r\n return deleter;\r\n default:\r\n return Reflect.get(target, prop, receiver);\r\n }\r\n }\r\n })\r\n}\r\n","import { inject, InjectionToken, Provider } from \"@angular/core\";\r\nimport { ReactiveWebLocalStorage } from '@telperion/reactive-storage';\r\n\r\nimport { storageSignal } from \"./storage\";\r\nimport { StorageSignal } from \"./storage-signal\";\r\n\r\n/**\r\n * Injection token for the ReactiveWebLocalStorage singleton.\r\n * @internal\r\n */\r\nconst LOCAL_STORAGE = new InjectionToken<ReactiveWebLocalStorage>('Telperion Local Storage');\r\n\r\n/**\r\n * Provides a ReactiveWebLocalStorage instance for dependency injection.\r\n *\r\n * @param appName - Optional application name for namespacing localStorage keys\r\n * @returns An Angular provider configuration\r\n *\r\n * @remarks\r\n * This provider creates a singleton ReactiveWebLocalStorage instance that can be injected\r\n * throughout your application. All `localStorageSignal` calls will use this shared instance,\r\n * ensuring consistent storage access and change detection.\r\n *\r\n * **Namespacing:**\r\n * The `appName` parameter prefixes all localStorage keys to prevent conflicts:\r\n * - With appName: `my-app:store:key`\r\n * - Without appName: `store:key`\r\n *\r\n * **Singleton Pattern:**\r\n * Only one instance is created per application, ensuring:\r\n * - Consistent storage access across components\r\n * - Efficient memory usage\r\n * - Reliable cross-component synchronization\r\n *\r\n * @example\r\n * ```typescript\r\n * // app.config.ts\r\n * import { ApplicationConfig } from '@angular/core';\r\n * import { provideLocalStorage } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideLocalStorage('my-app'),\r\n * // ... other providers\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // Without namespace (keys are not prefixed)\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideLocalStorage(),\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @public\r\n */\r\nexport function provideLocalStorage(appName?: string): Provider {\r\n return {\r\n provide: LOCAL_STORAGE,\r\n useValue: new ReactiveWebLocalStorage(appName)\r\n };\r\n}\r\n\r\n/**\r\n * Creates a reactive signal connected to browser's localStorage.\r\n *\r\n * @template T - The type of value stored\r\n * @param store - The storage namespace/store name\r\n * @param key - The key within the store\r\n * @returns A StorageSignal that reactively tracks the localStorage value\r\n *\r\n * @remarks\r\n * This function creates an Angular signal that automatically syncs with localStorage.\r\n * Any changes to the value (via `set`, `update`, or `delete`) are immediately persisted\r\n * to localStorage and propagate to all components using the same signal.\r\n *\r\n * **Requirements:**\r\n * Must call {@link provideLocalStorage} in application config before using this function.\r\n *\r\n * **Storage Key:**\r\n * The actual localStorage key is formed as:\r\n * - With app name: `appName:store:key`\r\n * - Without app name: `store:key`\r\n *\r\n * **Type Safety:**\r\n * Values are automatically serialized/deserialized as JSON:\r\n * - Objects and arrays are preserved\r\n * - Primitives (string, number, boolean) work correctly\r\n * - Functions and undefined values are not supported\r\n *\r\n * **Cross-Component Sync:**\r\n * All components using the same `store` and `key` share the same signal state.\r\n * Changes in one component immediately reflect in others.\r\n *\r\n * @example\r\n * ```typescript\r\n * import { Component } from '@angular/core';\r\n * import { localStorageSignal } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * @Component({\r\n * selector: 'app-settings',\r\n * template: `\r\n * <div>\r\n * <p>Theme: {{ theme() }}</p>\r\n * <button (click)=\"theme.set('dark')\">Dark</button>\r\n * <button (click)=\"theme.set('light')\">Light</button>\r\n * <button (click)=\"theme.delete()\">Reset</button>\r\n * </div>\r\n * `\r\n * })\r\n * export class SettingsComponent {\r\n * theme = localStorageSignal<string>('settings', 'theme');\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // Complex types\r\n * interface UserPreferences {\r\n * theme: 'light' | 'dark';\r\n * fontSize: number;\r\n * notifications: boolean;\r\n * }\r\n *\r\n * const prefs = localStorageSignal<UserPreferences>('user', 'preferences');\r\n *\r\n * // Set entire object\r\n * prefs.set({ theme: 'dark', fontSize: 14, notifications: true });\r\n *\r\n * // Update specific property\r\n * prefs.update(current => ({\r\n * ...current,\r\n * theme: current?.theme === 'dark' ? 'light' : 'dark'\r\n * }));\r\n * ```\r\n *\r\n * @throws Error if {@link provideLocalStorage} was not called in application config\r\n *\r\n * @public\r\n */\r\nexport function localStorageSignal<T>(store: string, key: string): StorageSignal<T> {\r\n const storage = inject(LOCAL_STORAGE);\r\n\r\n return storageSignal(storage, store, key);\r\n}\r\n","import { inject, InjectionToken, Provider } from \"@angular/core\";\r\nimport { ReactiveWebSessionStorage } from '@telperion/reactive-storage';\r\n\r\nimport { storageSignal } from \"./storage\";\r\nimport { StorageSignal } from \"./storage-signal\";\r\n\r\n/**\r\n * Injection token for the ReactiveWebSessionStorage singleton.\r\n * @internal\r\n */\r\nconst SESSION_STORAGE = new InjectionToken<ReactiveWebSessionStorage>('Telperion Session Storage');\r\n\r\n/**\r\n * Provides a ReactiveWebSessionStorage instance for dependency injection.\r\n *\r\n * @param appName - Optional application name for namespacing sessionStorage keys\r\n * @returns An Angular provider configuration\r\n *\r\n * @remarks\r\n * This provider creates a singleton ReactiveWebSessionStorage instance that can be injected\r\n * throughout your application. All `sessionStorageSignal` calls will use this shared instance,\r\n * ensuring consistent storage access and change detection.\r\n *\r\n * **SessionStorage vs LocalStorage:**\r\n * - **sessionStorage**: Data persists only for the browser tab/window session (cleared on close)\r\n * - **localStorage**: Data persists indefinitely until explicitly cleared\r\n *\r\n * **Use Cases for sessionStorage:**\r\n * - Multi-step form wizards\r\n * - Temporary authentication tokens\r\n * - Per-session user preferences\r\n * - Shopping cart for current session\r\n * - Tab-specific state isolation\r\n *\r\n * **Namespacing:**\r\n * The `appName` parameter prefixes all sessionStorage keys to prevent conflicts:\r\n * - With appName: `my-app:store:key`\r\n * - Without appName: `store:key`\r\n *\r\n * **Singleton Pattern:**\r\n * Only one instance is created per application, ensuring:\r\n * - Consistent storage access across components\r\n * - Efficient memory usage\r\n * - Reliable cross-component synchronization\r\n *\r\n * @example\r\n * ```typescript\r\n * // app.config.ts\r\n * import { ApplicationConfig } from '@angular/core';\r\n * import { provideSessionStorage } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideSessionStorage('my-app'),\r\n * // ... other providers\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // Without namespace\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideSessionStorage(),\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @public\r\n */\r\nexport function provideSessionStorage(appName?: string): Provider {\r\n return {\r\n provide: SESSION_STORAGE,\r\n useValue: new ReactiveWebSessionStorage(appName)\r\n };\r\n}\r\n\r\n/**\r\n * Creates a reactive signal connected to browser's sessionStorage.\r\n *\r\n * @template T - The type of value stored\r\n * @param store - The storage namespace/store name\r\n * @param key - The key within the store\r\n * @returns A StorageSignal that reactively tracks the sessionStorage value\r\n *\r\n * @remarks\r\n * This function creates an Angular signal that automatically syncs with sessionStorage.\r\n * Any changes to the value (via `set`, `update`, or `delete`) are immediately persisted\r\n * to sessionStorage and propagate to all components using the same signal.\r\n *\r\n * **Session Lifecycle:**\r\n * - Data is cleared when the browser tab/window is closed\r\n * - Each tab has its own independent sessionStorage\r\n * - Opening a page in a new tab creates fresh sessionStorage (even for same URL)\r\n * - Refreshing the page preserves sessionStorage data\r\n *\r\n * **Requirements:**\r\n * Must call {@link provideSessionStorage} in application config before using this function.\r\n *\r\n * **Storage Key:**\r\n * The actual sessionStorage key is formed as:\r\n * - With app name: `appName:store:key`\r\n * - Without app name: `store:key`\r\n *\r\n * **Type Safety:**\r\n * Values are automatically serialized/deserialized as JSON:\r\n * - Objects and arrays are preserved\r\n * - Primitives (string, number, boolean) work correctly\r\n * - Functions and undefined values are not supported\r\n *\r\n * **Cross-Component Sync:**\r\n * All components in the same tab using the same `store` and `key` share the same signal state.\r\n * Changes in one component immediately reflect in others within the same tab.\r\n * Different tabs do NOT share sessionStorage.\r\n *\r\n * @example\r\n * ```typescript\r\n * import { Component } from '@angular/core';\r\n * import { sessionStorageSignal } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * @Component({\r\n * selector: 'app-wizard',\r\n * template: `\r\n * <div>\r\n * <p>Current Step: {{ currentStep() }}</p>\r\n * <button (click)=\"nextStep()\">Next</button>\r\n * <button (click)=\"currentStep.delete()\">Reset</button>\r\n * </div>\r\n * `\r\n * })\r\n * export class WizardComponent {\r\n * currentStep = sessionStorageSignal<number>('wizard', 'step');\r\n *\r\n * nextStep() {\r\n * this.currentStep.update(step => (step ?? 0) + 1);\r\n * }\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // Form data that shouldn't persist across sessions\r\n * interface FormData {\r\n * email: string;\r\n * message: string;\r\n * }\r\n *\r\n * const formData = sessionStorageSignal<FormData>('contact', 'draft');\r\n *\r\n * // Auto-save form data (cleared when tab closes)\r\n * formData.set({ email: 'user@example.com', message: 'Hello!' });\r\n *\r\n * // Update specific field\r\n * formData.update(current => ({\r\n * ...current,\r\n * message: 'Updated message'\r\n * }));\r\n * ```\r\n *\r\n * @throws Error if {@link provideSessionStorage} was not called in application config\r\n *\r\n * @public\r\n */\r\nexport function sessionStorageSignal<T>(store: string, key: string): StorageSignal<T> {\r\n const storage = inject(SESSION_STORAGE);\r\n\r\n return storageSignal(storage, store, key);\r\n}\r\n","import { inject, Provider } from '@angular/core';\r\nimport { ReactiveCookieStorage, ReactiveCookieStorageOptions } from '@telperion/reactive-storage';\r\nimport { storageSignal } from './storage';\r\n\r\n/**\r\n * Internal provider that manages ReactiveCookieStorage instances with different configurations.\r\n *\r\n * @remarks\r\n * This class implements a registry pattern to ensure that cookie storages with identical\r\n * configurations share the same underlying ReactiveCookieStorage instance. This is critical for:\r\n * - Preventing duplicate cookie writes\r\n * - Ensuring consistent change detection across components\r\n * - Optimizing memory usage\r\n *\r\n * **Linker Pattern:**\r\n * All instances created by this provider share a common linker (Symbol) to enable\r\n * cross-instance synchronization even when using different option combinations.\r\n *\r\n * **Instance Deduplication:**\r\n * Two `cookieStorageSignal` calls with the same options will reuse the same storage instance,\r\n * preventing redundant cookie operations.\r\n *\r\n * @internal This class is not exported publicly\r\n */\r\nclass CookieStorageProvider {\r\n /**\r\n * Valid cookie option keys that can be used to configure cookie storage.\r\n * Filters out any invalid properties from being passed to cookie operations.\r\n */\r\n static #VALID_OPTIONS = ['path', 'domain', 'secure', 'sameSite', 'expires', 'maxAge'] as (keyof ReactiveCookieStorageOptions)[];\r\n\r\n /**\r\n * Shared linker symbol used to synchronize all cookie storage instances\r\n * created by this provider, enabling cross-instance change notifications.\r\n */\r\n #linker = Symbol('ReactiveCookieStorage Linker');\r\n\r\n /**\r\n * Registry of ReactiveCookieStorage instances keyed by their configuration options.\r\n * Ensures instances with identical options are reused.\r\n */\r\n #stores = new Map<ReactiveCookieStorageOptions, ReactiveCookieStorage>();\r\n\r\n /**\r\n * Creates a new CookieStorageProvider with base configuration.\r\n *\r\n * @param appName - Optional application name for namespacing cookie keys\r\n * @param baseOptions - Default cookie options applied to all storage instances\r\n */\r\n constructor(\r\n private appName?: string,\r\n private baseOptions: ReactiveCookieStorageOptions = {}\r\n ) {\r\n const parsedOptions = this.#parseOptions(baseOptions);\r\n\r\n this.#stores.set(parsedOptions, new ReactiveCookieStorage(appName, parsedOptions, this.#linker));\r\n }\r\n\r\n /**\r\n * Gets or creates a ReactiveCookieStorage instance with the specified options.\r\n *\r\n * @param options - Cookie options to override base options\r\n * @returns A ReactiveCookieStorage instance (reused if options match existing instance)\r\n *\r\n * @remarks\r\n * This method implements option merging and instance deduplication:\r\n * 1. Merges provided options with base options (provided options take precedence)\r\n * 2. Checks if an instance with these exact options already exists\r\n * 3. Returns existing instance if found, otherwise creates and caches a new one\r\n *\r\n * All instances share the same linker for cross-instance synchronization.\r\n */\r\n getStore(options: ReactiveCookieStorageOptions = {}): ReactiveCookieStorage {\r\n const parsedOptions = this.#parseOptions({...this.baseOptions, ...options});\r\n let existingKey = this.#getStoredOptions(parsedOptions);\r\n\r\n if (!existingKey) {\r\n this.#stores.set(parsedOptions, new ReactiveCookieStorage(this.appName, parsedOptions, this.#linker));\r\n existingKey = parsedOptions;\r\n }\r\n\r\n return this.#stores.get(existingKey)!;\r\n }\r\n\r\n /**\r\n * Filters cookie options to include only valid properties.\r\n *\r\n * @param options - Raw options object that may contain invalid properties\r\n * @returns Filtered options containing only valid cookie configuration properties\r\n */\r\n #parseOptions(options: ReactiveCookieStorageOptions) {\r\n return Object.fromEntries(\r\n Object.entries(options).filter(([key]) => CookieStorageProvider.#VALID_OPTIONS.includes(key as keyof ReactiveCookieStorageOptions))\r\n ) as ReactiveCookieStorageOptions;\r\n }\r\n\r\n /**\r\n * Searches the registry for an existing options object that matches the provided options.\r\n *\r\n * @param options - Cookie options to search for\r\n * @returns The stored options object if found, undefined otherwise\r\n *\r\n * @remarks\r\n * Two options objects are considered equal if all valid cookie properties have identical values.\r\n */\r\n #getStoredOptions(options: ReactiveCookieStorageOptions): ReactiveCookieStorageOptions | undefined {\r\n const stored = this.#stores.keys();\r\n\r\n return stored.find(storedOpts => {\r\n return CookieStorageProvider.#VALID_OPTIONS.every(key => storedOpts[key] === options[key]);\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Provides a CookieStorageProvider instance for dependency injection.\r\n *\r\n * @param appName - Optional application name for namespacing cookie keys\r\n * @param options - Default cookie options applied to all cookie storage signals\r\n * @returns An Angular provider configuration\r\n *\r\n * @remarks\r\n * This provider creates a singleton CookieStorageProvider that manages all cookie storage\r\n * instances in your application. All `cookieStorageSignal` calls will use this shared provider.\r\n *\r\n * **Cookie Namespacing:**\r\n * The `appName` parameter prefixes all cookie names to prevent conflicts:\r\n * - With appName: `my-app:store:key`\r\n * - Without appName: `store:key`\r\n *\r\n * **Base Options:**\r\n * The `options` parameter provides default cookie configuration for all signals.\r\n * Individual signals can override these options when created.\r\n *\r\n * **Common Options:**\r\n * - `path` - Cookie path (default: current path)\r\n * - `domain` - Cookie domain (default: current domain)\r\n * - `secure` - Require HTTPS (recommended for production)\r\n * - `sameSite` - CSRF protection ('strict' | 'lax' | 'none')\r\n * - `maxAge` - Expiry time in seconds\r\n * - `expires` - Expiry as Date object\r\n *\r\n * **Instance Management:**\r\n * The provider automatically deduplicates storage instances:\r\n * - Signals with identical options share the same storage instance\r\n * - All instances are linked for cross-instance synchronization\r\n * - Memory-efficient for applications with many cookie signals\r\n *\r\n * @example\r\n * ```typescript\r\n * // app.config.ts\r\n * import { ApplicationConfig } from '@angular/core';\r\n * import { provideCookieStorage } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideCookieStorage('my-app', {\r\n * path: '/',\r\n * secure: true,\r\n * sameSite: 'strict',\r\n * maxAge: 86400 // 24 hours\r\n * }),\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // Minimal configuration\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideCookieStorage('my-app'),\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @public\r\n */\r\nexport function provideCookieStorage(\r\n appName?: string,\r\n options?: ReactiveCookieStorageOptions\r\n): Provider {\r\n return {\r\n provide: CookieStorageProvider,\r\n useValue: new CookieStorageProvider(appName, options)\r\n };\r\n}\r\n\r\n/**\r\n * Creates a reactive signal connected to browser cookies.\r\n *\r\n * @template T - The type of value stored\r\n * @param store - The cookie namespace/store name\r\n * @param key - The cookie key within the store\r\n * @param options - Optional cookie-specific options that override provider defaults\r\n * @returns A StorageSignal that reactively tracks the cookie value\r\n *\r\n * @remarks\r\n * This function creates an Angular signal that automatically syncs with browser cookies.\r\n * Any changes to the value (via `set`, `update`, or `delete`) are immediately written\r\n * to cookies and propagate to all components using the same signal.\r\n *\r\n * **Requirements:**\r\n * Must call {@link provideCookieStorage} in application config before using this function.\r\n *\r\n * **Cookie Name:**\r\n * The actual cookie name is formed as:\r\n * - With app name: `appName:store:key`\r\n * - Without app name: `store:key`\r\n *\r\n * **Size Limitations:**\r\n * Cookies have a ~4KB size limit. The underlying ReactiveCookieStorage enforces a 4000 byte\r\n * limit and throws an error if exceeded. Use localStorage for larger data.\r\n *\r\n * **Options Merging:**\r\n * Cookie options are merged in this order (later overrides earlier):\r\n * 1. Provider base options (from `provideCookieStorage`)\r\n * 2. Signal-specific options (from this function's `options` parameter)\r\n *\r\n * **Instance Deduplication:**\r\n * Signals with identical merged options share the same underlying storage instance:\r\n * ```typescript\r\n * // These share the same storage instance\r\n * const token1 = cookieStorageSignal('auth', 'token', { secure: true });\r\n * const token2 = cookieStorageSignal('auth', 'token', { secure: true });\r\n *\r\n * // These use different instances (different options)\r\n * const temp = cookieStorageSignal('auth', 'token', { maxAge: 300 });\r\n * ```\r\n *\r\n * **Type Safety:**\r\n * Values are automatically serialized/deserialized as JSON:\r\n * - Objects and arrays are preserved\r\n * - Primitives (string, number, boolean) work correctly\r\n * - Functions and undefined values are not supported\r\n *\r\n * **Security Best Practices:**\r\n * - Use `secure: true` in production (HTTPS only)\r\n * - Use `sameSite: 'strict'` for CSRF protection\r\n * - Set appropriate `maxAge` or `expires` for sensitive data\r\n * - Never store sensitive data in cookies without encryption\r\n *\r\n * @example\r\n * ```typescript\r\n * import { Component } from '@angular/core';\r\n * import { cookieStorageSignal } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * @Component({\r\n * selector: 'app-auth',\r\n * template: `\r\n * <div>\r\n * <p>Token: {{ authToken() }}</p>\r\n * <button (click)=\"login()\">Login</button>\r\n * <button (click)=\"logout()\">Logout</button>\r\n * </div>\r\n * `\r\n * })\r\n * export class AuthComponent {\r\n * // Secure cookie with 1 hour expiry\r\n * authToken = cookieStorageSignal<string>('auth', 'token', {\r\n * secure: true,\r\n * sameSite: 'strict',\r\n * maxAge: 3600\r\n * });\r\n *\r\n * login() {\r\n * this.authToken.set('abc123');\r\n * }\r\n *\r\n * logout() {\r\n * this.authToken.delete();\r\n * }\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // User preferences with different cookie lifetimes\r\n * const theme = cookieStorageSignal<string>('prefs', 'theme', {\r\n * maxAge: 31536000 // 1 year\r\n * });\r\n *\r\n * const tempSetting = cookieStorageSignal<boolean>('prefs', 'banner-dismissed', {\r\n * maxAge: 86400 // 1 day\r\n * });\r\n *\r\n * theme.set('dark');\r\n * tempSetting.set(true);\r\n * ```\r\n *\r\n * @throws Error if {@link provideCookieStorage} was not called in application config\r\n * @throws Error if the serialized value exceeds 4000 bytes\r\n *\r\n * @public\r\n */\r\nexport function cookieStorageSignal<T>(store: string, key: string, options?: ReactiveCookieStorageOptions) {\r\n const provider = inject(CookieStorageProvider);\r\n const storage = provider.getStore(options);\r\n\r\n return storageSignal(storage, store, key);\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"telperion-ng-pack-storage-signals.mjs","sources":["../../storage-signals/src/storage.ts","../../storage-signals/src/local-storage.ts","../../storage-signals/src/session-storage.ts","../../storage-signals/src/cookie-storage.ts","../../storage-signals/src/telperion-ng-pack-storage-signals.ts"],"sourcesContent":["import { toSignal } from \"@angular/core/rxjs-interop\";\r\nimport { ReactiveStorage } from '@telperion/reactive-storage';\r\nimport { StorageSignal } from \"./storage-signal\";\r\n\r\n/**\r\n * Creates a StorageSignal from a ReactiveStorage instance.\r\n *\r\n * @template T - The type of value stored\r\n * @param storage - The ReactiveStorage instance (localStorage, sessionStorage, or cookie storage)\r\n * @param store - The storage namespace/store name\r\n * @param key - The key within the store\r\n * @returns A StorageSignal that provides reactive access to the stored value\r\n *\r\n * @remarks\r\n * This is a low-level factory function that bridges Angular signals with ReactiveStorage.\r\n * Most applications should use the higher-level functions:\r\n * - {@link localStorageSignal} for localStorage\r\n * - {@link sessionStorageSignal} for sessionStorage\r\n * - {@link cookieStorageSignal} for cookies\r\n *\r\n * The function:\r\n * 1. Converts the ReactiveStorage Observable into an Angular signal using `toSignal`\r\n * 2. Creates a Proxy that intercepts calls to add `set`, `update`, and `delete` methods\r\n * 3. Ensures all storage operations propagate to both the underlying storage and the signal\r\n *\r\n * **Proxy Pattern:**\r\n * The returned signal is a Proxy that:\r\n * - Delegates reading to the underlying signal\r\n * - Provides `set()` to write values\r\n * - Provides `update()` for functional updates\r\n * - Provides `delete()` to remove the value\r\n *\r\n * @example\r\n * ```typescript\r\n * // Typically used internally by specialized signal creators\r\n * import { ReactiveWebLocalStorage } from '@telperion/reactive-storage';\r\n *\r\n * const storage = new ReactiveWebLocalStorage('my-app');\r\n * const userSignal = storageSignal<User>(storage, 'users', 'current');\r\n *\r\n * userSignal.set({ id: 1, name: 'Alice' });\r\n * console.log(userSignal()); // { id: 1, name: 'Alice' }\r\n *\r\n * userSignal.update(user => ({ ...user, name: 'Bob' }));\r\n * userSignal.delete();\r\n * ```\r\n *\r\n * @internal This is primarily for internal use. Use the specialized signal creators instead.\r\n */\r\nexport function storageSignal<T>(storage: ReactiveStorage, store: string, key: string): StorageSignal<T> {\r\n const source = toSignal(storage.get<T>(store, key));\r\n\r\n function setter(value: T | null | undefined) {\r\n storage.set(store, key, value);\r\n }\r\n\r\n function updater(updaterFn: (value: T | null | undefined) => T | null | undefined) {\r\n const currentValue = source();\r\n const newValue = updaterFn(currentValue);\r\n\r\n storage.set(store, key, newValue);\r\n }\r\n\r\n function deleter() {\r\n storage.delete(store, key);\r\n }\r\n\r\n return new Proxy(source as StorageSignal<T>, {\r\n apply() {\r\n return source();\r\n },\r\n get(target, prop, receiver) {\r\n switch (prop) {\r\n case 'set':\r\n return setter;\r\n case 'update':\r\n return updater;\r\n case 'delete':\r\n return deleter;\r\n default:\r\n return Reflect.get(target, prop, receiver);\r\n }\r\n }\r\n })\r\n}\r\n","import { inject, InjectionToken, Provider } from \"@angular/core\";\r\nimport { ReactiveWebLocalStorage } from '@telperion/reactive-storage';\r\n\r\nimport { storageSignal } from \"./storage\";\r\nimport { StorageSignal } from \"./storage-signal\";\r\n\r\n/**\r\n * Injection token for the ReactiveWebLocalStorage singleton.\r\n * @internal\r\n */\r\nconst LOCAL_STORAGE = new InjectionToken<ReactiveWebLocalStorage>('Telperion Local Storage');\r\n\r\n/**\r\n * Provides a ReactiveWebLocalStorage instance for dependency injection.\r\n *\r\n * @param appName - Optional application name for namespacing localStorage keys\r\n * @returns An Angular provider configuration\r\n *\r\n * @remarks\r\n * This provider creates a singleton ReactiveWebLocalStorage instance that can be injected\r\n * throughout your application. All `localStorageSignal` calls will use this shared instance,\r\n * ensuring consistent storage access and change detection.\r\n *\r\n * **Namespacing:**\r\n * The `appName` parameter prefixes all localStorage keys to prevent conflicts:\r\n * - With appName: `my-app:store:key`\r\n * - Without appName: `store:key`\r\n *\r\n * **Singleton Pattern:**\r\n * Only one instance is created per application, ensuring:\r\n * - Consistent storage access across components\r\n * - Efficient memory usage\r\n * - Reliable cross-component synchronization\r\n *\r\n * @example\r\n * ```typescript\r\n * // app.config.ts\r\n * import { ApplicationConfig } from '@angular/core';\r\n * import { provideLocalStorage } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideLocalStorage('my-app'),\r\n * // ... other providers\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // Without namespace (keys are not prefixed)\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideLocalStorage(),\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @public\r\n */\r\nexport function provideLocalStorage(appName?: string): Provider {\r\n return {\r\n provide: LOCAL_STORAGE,\r\n useValue: new ReactiveWebLocalStorage(appName)\r\n };\r\n}\r\n\r\n/**\r\n * Creates a reactive signal connected to browser's localStorage.\r\n *\r\n * @template T - The type of value stored\r\n * @param store - The storage namespace/store name\r\n * @param key - The key within the store\r\n * @returns A StorageSignal that reactively tracks the localStorage value\r\n *\r\n * @remarks\r\n * This function creates an Angular signal that automatically syncs with localStorage.\r\n * Any changes to the value (via `set`, `update`, or `delete`) are immediately persisted\r\n * to localStorage and propagate to all components using the same signal.\r\n *\r\n * **Requirements:**\r\n * Must call {@link provideLocalStorage} in application config before using this function.\r\n *\r\n * **Storage Key:**\r\n * The actual localStorage key is formed as:\r\n * - With app name: `appName:store:key`\r\n * - Without app name: `store:key`\r\n *\r\n * **Type Safety:**\r\n * Values are automatically serialized/deserialized as JSON:\r\n * - Objects and arrays are preserved\r\n * - Primitives (string, number, boolean) work correctly\r\n * - Functions and undefined values are not supported\r\n *\r\n * **Cross-Component Sync:**\r\n * All components using the same `store` and `key` share the same signal state.\r\n * Changes in one component immediately reflect in others.\r\n *\r\n * @example\r\n * ```typescript\r\n * import { Component } from '@angular/core';\r\n * import { localStorageSignal } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * @Component({\r\n * selector: 'app-settings',\r\n * template: `\r\n * <div>\r\n * <p>Theme: {{ theme() }}</p>\r\n * <button (click)=\"theme.set('dark')\">Dark</button>\r\n * <button (click)=\"theme.set('light')\">Light</button>\r\n * <button (click)=\"theme.delete()\">Reset</button>\r\n * </div>\r\n * `\r\n * })\r\n * export class SettingsComponent {\r\n * theme = localStorageSignal<string>('settings', 'theme');\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // Complex types\r\n * interface UserPreferences {\r\n * theme: 'light' | 'dark';\r\n * fontSize: number;\r\n * notifications: boolean;\r\n * }\r\n *\r\n * const prefs = localStorageSignal<UserPreferences>('user', 'preferences');\r\n *\r\n * // Set entire object\r\n * prefs.set({ theme: 'dark', fontSize: 14, notifications: true });\r\n *\r\n * // Update specific property\r\n * prefs.update(current => ({\r\n * ...current,\r\n * theme: current?.theme === 'dark' ? 'light' : 'dark'\r\n * }));\r\n * ```\r\n *\r\n * @throws Error if {@link provideLocalStorage} was not called in application config\r\n *\r\n * @public\r\n */\r\nexport function localStorageSignal<T>(store: string, key: string): StorageSignal<T> {\r\n const storage = inject(LOCAL_STORAGE);\r\n\r\n return storageSignal(storage, store, key);\r\n}\r\n","import { inject, InjectionToken, Provider } from \"@angular/core\";\r\nimport { ReactiveWebSessionStorage } from '@telperion/reactive-storage';\r\n\r\nimport { storageSignal } from \"./storage\";\r\nimport { StorageSignal } from \"./storage-signal\";\r\n\r\n/**\r\n * Injection token for the ReactiveWebSessionStorage singleton.\r\n * @internal\r\n */\r\nconst SESSION_STORAGE = new InjectionToken<ReactiveWebSessionStorage>('Telperion Session Storage');\r\n\r\n/**\r\n * Provides a ReactiveWebSessionStorage instance for dependency injection.\r\n *\r\n * @param appName - Optional application name for namespacing sessionStorage keys\r\n * @returns An Angular provider configuration\r\n *\r\n * @remarks\r\n * This provider creates a singleton ReactiveWebSessionStorage instance that can be injected\r\n * throughout your application. All `sessionStorageSignal` calls will use this shared instance,\r\n * ensuring consistent storage access and change detection.\r\n *\r\n * **SessionStorage vs LocalStorage:**\r\n * - **sessionStorage**: Data persists only for the browser tab/window session (cleared on close)\r\n * - **localStorage**: Data persists indefinitely until explicitly cleared\r\n *\r\n * **Use Cases for sessionStorage:**\r\n * - Multi-step form wizards\r\n * - Temporary authentication tokens\r\n * - Per-session user preferences\r\n * - Shopping cart for current session\r\n * - Tab-specific state isolation\r\n *\r\n * **Namespacing:**\r\n * The `appName` parameter prefixes all sessionStorage keys to prevent conflicts:\r\n * - With appName: `my-app:store:key`\r\n * - Without appName: `store:key`\r\n *\r\n * **Singleton Pattern:**\r\n * Only one instance is created per application, ensuring:\r\n * - Consistent storage access across components\r\n * - Efficient memory usage\r\n * - Reliable cross-component synchronization\r\n *\r\n * @example\r\n * ```typescript\r\n * // app.config.ts\r\n * import { ApplicationConfig } from '@angular/core';\r\n * import { provideSessionStorage } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideSessionStorage('my-app'),\r\n * // ... other providers\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // Without namespace\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideSessionStorage(),\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @public\r\n */\r\nexport function provideSessionStorage(appName?: string): Provider {\r\n return {\r\n provide: SESSION_STORAGE,\r\n useValue: new ReactiveWebSessionStorage(appName)\r\n };\r\n}\r\n\r\n/**\r\n * Creates a reactive signal connected to browser's sessionStorage.\r\n *\r\n * @template T - The type of value stored\r\n * @param store - The storage namespace/store name\r\n * @param key - The key within the store\r\n * @returns A StorageSignal that reactively tracks the sessionStorage value\r\n *\r\n * @remarks\r\n * This function creates an Angular signal that automatically syncs with sessionStorage.\r\n * Any changes to the value (via `set`, `update`, or `delete`) are immediately persisted\r\n * to sessionStorage and propagate to all components using the same signal.\r\n *\r\n * **Session Lifecycle:**\r\n * - Data is cleared when the browser tab/window is closed\r\n * - Each tab has its own independent sessionStorage\r\n * - Opening a page in a new tab creates fresh sessionStorage (even for same URL)\r\n * - Refreshing the page preserves sessionStorage data\r\n *\r\n * **Requirements:**\r\n * Must call {@link provideSessionStorage} in application config before using this function.\r\n *\r\n * **Storage Key:**\r\n * The actual sessionStorage key is formed as:\r\n * - With app name: `appName:store:key`\r\n * - Without app name: `store:key`\r\n *\r\n * **Type Safety:**\r\n * Values are automatically serialized/deserialized as JSON:\r\n * - Objects and arrays are preserved\r\n * - Primitives (string, number, boolean) work correctly\r\n * - Functions and undefined values are not supported\r\n *\r\n * **Cross-Component Sync:**\r\n * All components in the same tab using the same `store` and `key` share the same signal state.\r\n * Changes in one component immediately reflect in others within the same tab.\r\n * Different tabs do NOT share sessionStorage.\r\n *\r\n * @example\r\n * ```typescript\r\n * import { Component } from '@angular/core';\r\n * import { sessionStorageSignal } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * @Component({\r\n * selector: 'app-wizard',\r\n * template: `\r\n * <div>\r\n * <p>Current Step: {{ currentStep() }}</p>\r\n * <button (click)=\"nextStep()\">Next</button>\r\n * <button (click)=\"currentStep.delete()\">Reset</button>\r\n * </div>\r\n * `\r\n * })\r\n * export class WizardComponent {\r\n * currentStep = sessionStorageSignal<number>('wizard', 'step');\r\n *\r\n * nextStep() {\r\n * this.currentStep.update(step => (step ?? 0) + 1);\r\n * }\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // Form data that shouldn't persist across sessions\r\n * interface FormData {\r\n * email: string;\r\n * message: string;\r\n * }\r\n *\r\n * const formData = sessionStorageSignal<FormData>('contact', 'draft');\r\n *\r\n * // Auto-save form data (cleared when tab closes)\r\n * formData.set({ email: 'user@example.com', message: 'Hello!' });\r\n *\r\n * // Update specific field\r\n * formData.update(current => ({\r\n * ...current,\r\n * message: 'Updated message'\r\n * }));\r\n * ```\r\n *\r\n * @throws Error if {@link provideSessionStorage} was not called in application config\r\n *\r\n * @public\r\n */\r\nexport function sessionStorageSignal<T>(store: string, key: string): StorageSignal<T> {\r\n const storage = inject(SESSION_STORAGE);\r\n\r\n return storageSignal(storage, store, key);\r\n}\r\n","import { inject, Provider } from '@angular/core';\r\nimport { ReactiveCookieStorage, ReactiveCookieStorageOptions } from '@telperion/reactive-storage';\r\nimport { storageSignal } from './storage';\r\n\r\n/**\r\n * Internal provider that manages ReactiveCookieStorage instances with different configurations.\r\n *\r\n * @remarks\r\n * This class implements a registry pattern to ensure that cookie storages with identical\r\n * configurations share the same underlying ReactiveCookieStorage instance. This is critical for:\r\n * - Preventing duplicate cookie writes\r\n * - Ensuring consistent change detection across components\r\n * - Optimizing memory usage\r\n *\r\n * **Linker Pattern:**\r\n * All instances created by this provider share a common linker (Symbol) to enable\r\n * cross-instance synchronization even when using different option combinations.\r\n *\r\n * **Instance Deduplication:**\r\n * Two `cookieStorageSignal` calls with the same options will reuse the same storage instance,\r\n * preventing redundant cookie operations.\r\n *\r\n * @internal This class is not exported publicly\r\n */\r\nclass CookieStorageProvider {\r\n /**\r\n * Valid cookie option keys that can be used to configure cookie storage.\r\n * Filters out any invalid properties from being passed to cookie operations.\r\n */\r\n static #VALID_OPTIONS = ['path', 'domain', 'secure', 'sameSite', 'expires', 'maxAge'] as (keyof ReactiveCookieStorageOptions)[];\r\n\r\n /**\r\n * Shared linker symbol used to synchronize all cookie storage instances\r\n * created by this provider, enabling cross-instance change notifications.\r\n */\r\n #linker = Symbol('ReactiveCookieStorage Linker');\r\n\r\n /**\r\n * Registry of ReactiveCookieStorage instances keyed by their configuration options.\r\n * Ensures instances with identical options are reused.\r\n */\r\n #stores = new Map<ReactiveCookieStorageOptions, ReactiveCookieStorage>();\r\n\r\n /**\r\n * Creates a new CookieStorageProvider with base configuration.\r\n *\r\n * @param appName - Optional application name for namespacing cookie keys\r\n * @param baseOptions - Default cookie options applied to all storage instances\r\n */\r\n constructor(\r\n private appName?: string,\r\n private baseOptions: ReactiveCookieStorageOptions = {}\r\n ) {\r\n const parsedOptions = this.#parseOptions(baseOptions);\r\n\r\n this.#stores.set(parsedOptions, new ReactiveCookieStorage(appName, parsedOptions, this.#linker));\r\n }\r\n\r\n /**\r\n * Gets or creates a ReactiveCookieStorage instance with the specified options.\r\n *\r\n * @param options - Cookie options to override base options\r\n * @returns A ReactiveCookieStorage instance (reused if options match existing instance)\r\n *\r\n * @remarks\r\n * This method implements option merging and instance deduplication:\r\n * 1. Merges provided options with base options (provided options take precedence)\r\n * 2. Checks if an instance with these exact options already exists\r\n * 3. Returns existing instance if found, otherwise creates and caches a new one\r\n *\r\n * All instances share the same linker for cross-instance synchronization.\r\n */\r\n getStore(options: ReactiveCookieStorageOptions = {}): ReactiveCookieStorage {\r\n const parsedOptions = this.#parseOptions({...this.baseOptions, ...options});\r\n let existingKey = this.#getStoredOptions(parsedOptions);\r\n\r\n if (!existingKey) {\r\n this.#stores.set(parsedOptions, new ReactiveCookieStorage(this.appName, parsedOptions, this.#linker));\r\n existingKey = parsedOptions;\r\n }\r\n\r\n return this.#stores.get(existingKey)!;\r\n }\r\n\r\n /**\r\n * Filters cookie options to include only valid properties.\r\n *\r\n * @param options - Raw options object that may contain invalid properties\r\n * @returns Filtered options containing only valid cookie configuration properties\r\n */\r\n #parseOptions(options: ReactiveCookieStorageOptions) {\r\n return Object.fromEntries(\r\n Object.entries(options).filter(([key]) => CookieStorageProvider.#VALID_OPTIONS.includes(key as keyof ReactiveCookieStorageOptions))\r\n ) as ReactiveCookieStorageOptions;\r\n }\r\n\r\n /**\r\n * Searches the registry for an existing options object that matches the provided options.\r\n *\r\n * @param options - Cookie options to search for\r\n * @returns The stored options object if found, undefined otherwise\r\n *\r\n * @remarks\r\n * Two options objects are considered equal if all valid cookie properties have identical values.\r\n */\r\n #getStoredOptions(options: ReactiveCookieStorageOptions): ReactiveCookieStorageOptions | undefined {\r\n const stored = this.#stores.keys();\r\n\r\n return stored.find(storedOpts => {\r\n return CookieStorageProvider.#VALID_OPTIONS.every(key => storedOpts[key] === options[key]);\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Provides a CookieStorageProvider instance for dependency injection.\r\n *\r\n * @param appName - Optional application name for namespacing cookie keys\r\n * @param options - Default cookie options applied to all cookie storage signals\r\n * @returns An Angular provider configuration\r\n *\r\n * @remarks\r\n * This provider creates a singleton CookieStorageProvider that manages all cookie storage\r\n * instances in your application. All `cookieStorageSignal` calls will use this shared provider.\r\n *\r\n * **Cookie Namespacing:**\r\n * The `appName` parameter prefixes all cookie names to prevent conflicts:\r\n * - With appName: `my-app:store:key`\r\n * - Without appName: `store:key`\r\n *\r\n * **Base Options:**\r\n * The `options` parameter provides default cookie configuration for all signals.\r\n * Individual signals can override these options when created.\r\n *\r\n * **Common Options:**\r\n * - `path` - Cookie path (default: current path)\r\n * - `domain` - Cookie domain (default: current domain)\r\n * - `secure` - Require HTTPS (recommended for production)\r\n * - `sameSite` - CSRF protection ('strict' | 'lax' | 'none')\r\n * - `maxAge` - Expiry time in seconds\r\n * - `expires` - Expiry as Date object\r\n *\r\n * **Instance Management:**\r\n * The provider automatically deduplicates storage instances:\r\n * - Signals with identical options share the same storage instance\r\n * - All instances are linked for cross-instance synchronization\r\n * - Memory-efficient for applications with many cookie signals\r\n *\r\n * @example\r\n * ```typescript\r\n * // app.config.ts\r\n * import { ApplicationConfig } from '@angular/core';\r\n * import { provideCookieStorage } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideCookieStorage('my-app', {\r\n * path: '/',\r\n * secure: true,\r\n * sameSite: 'strict',\r\n * maxAge: 86400 // 24 hours\r\n * }),\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // Minimal configuration\r\n * export const appConfig: ApplicationConfig = {\r\n * providers: [\r\n * provideCookieStorage('my-app'),\r\n * ]\r\n * };\r\n * ```\r\n *\r\n * @public\r\n */\r\nexport function provideCookieStorage(\r\n appName?: string,\r\n options?: ReactiveCookieStorageOptions\r\n): Provider {\r\n return {\r\n provide: CookieStorageProvider,\r\n useValue: new CookieStorageProvider(appName, options)\r\n };\r\n}\r\n\r\n/**\r\n * Creates a reactive signal connected to browser cookies.\r\n *\r\n * @template T - The type of value stored\r\n * @param store - The cookie namespace/store name\r\n * @param key - The cookie key within the store\r\n * @param options - Optional cookie-specific options that override provider defaults\r\n * @returns A StorageSignal that reactively tracks the cookie value\r\n *\r\n * @remarks\r\n * This function creates an Angular signal that automatically syncs with browser cookies.\r\n * Any changes to the value (via `set`, `update`, or `delete`) are immediately written\r\n * to cookies and propagate to all components using the same signal.\r\n *\r\n * **Requirements:**\r\n * Must call {@link provideCookieStorage} in application config before using this function.\r\n *\r\n * **Cookie Name:**\r\n * The actual cookie name is formed as:\r\n * - With app name: `appName:store:key`\r\n * - Without app name: `store:key`\r\n *\r\n * **Size Limitations:**\r\n * Cookies have a ~4KB size limit. The underlying ReactiveCookieStorage enforces a 4000 byte\r\n * limit and throws an error if exceeded. Use localStorage for larger data.\r\n *\r\n * **Options Merging:**\r\n * Cookie options are merged in this order (later overrides earlier):\r\n * 1. Provider base options (from `provideCookieStorage`)\r\n * 2. Signal-specific options (from this function's `options` parameter)\r\n *\r\n * **Instance Deduplication:**\r\n * Signals with identical merged options share the same underlying storage instance:\r\n * ```typescript\r\n * // These share the same storage instance\r\n * const token1 = cookieStorageSignal('auth', 'token', { secure: true });\r\n * const token2 = cookieStorageSignal('auth', 'token', { secure: true });\r\n *\r\n * // These use different instances (different options)\r\n * const temp = cookieStorageSignal('auth', 'token', { maxAge: 300 });\r\n * ```\r\n *\r\n * **Type Safety:**\r\n * Values are automatically serialized/deserialized as JSON:\r\n * - Objects and arrays are preserved\r\n * - Primitives (string, number, boolean) work correctly\r\n * - Functions and undefined values are not supported\r\n *\r\n * **Security Best Practices:**\r\n * - Use `secure: true` in production (HTTPS only)\r\n * - Use `sameSite: 'strict'` for CSRF protection\r\n * - Set appropriate `maxAge` or `expires` for sensitive data\r\n * - Never store sensitive data in cookies without encryption\r\n *\r\n * @example\r\n * ```typescript\r\n * import { Component } from '@angular/core';\r\n * import { cookieStorageSignal } from '@telperion/ng-pack/storage-signals';\r\n *\r\n * @Component({\r\n * selector: 'app-auth',\r\n * template: `\r\n * <div>\r\n * <p>Token: {{ authToken() }}</p>\r\n * <button (click)=\"login()\">Login</button>\r\n * <button (click)=\"logout()\">Logout</button>\r\n * </div>\r\n * `\r\n * })\r\n * export class AuthComponent {\r\n * // Secure cookie with 1 hour expiry\r\n * authToken = cookieStorageSignal<string>('auth', 'token', {\r\n * secure: true,\r\n * sameSite: 'strict',\r\n * maxAge: 3600\r\n * });\r\n *\r\n * login() {\r\n * this.authToken.set('abc123');\r\n * }\r\n *\r\n * logout() {\r\n * this.authToken.delete();\r\n * }\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * // User preferences with different cookie lifetimes\r\n * const theme = cookieStorageSignal<string>('prefs', 'theme', {\r\n * maxAge: 31536000 // 1 year\r\n * });\r\n *\r\n * const tempSetting = cookieStorageSignal<boolean>('prefs', 'banner-dismissed', {\r\n * maxAge: 86400 // 1 day\r\n * });\r\n *\r\n * theme.set('dark');\r\n * tempSetting.set(true);\r\n * ```\r\n *\r\n * @throws Error if {@link provideCookieStorage} was not called in application config\r\n * @throws Error if the serialized value exceeds 4000 bytes\r\n *\r\n * @public\r\n */\r\nexport function cookieStorageSignal<T>(store: string, key: string, options?: ReactiveCookieStorageOptions) {\r\n const provider = inject(CookieStorageProvider);\r\n const storage = provider.getStore(options);\r\n\r\n return storageSignal<T>(storage, store, key);\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { forwardRef, Inject, Injectable, inject } from '@angular/core';
|
|
|
3
3
|
import { DOCUMENT } from '@angular/common';
|
|
4
4
|
import { EventManagerPlugin, EVENT_MANAGER_PLUGINS } from '@angular/platform-browser';
|
|
5
5
|
import { HttpClient } from '@angular/common/http';
|
|
6
|
-
import { tryCatch } from '@
|
|
6
|
+
import { tryCatch } from '@telperion/js-utils/promise/try-catch';
|
|
7
7
|
import { firstValueFrom } from 'rxjs';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telperion-ng-pack-utils.mjs","sources":["../../utils/src/provide-service-directive.ts","../../utils/src/event-modifiers.plugin.ts","../../utils/src/construct-fetcher.ts","../../utils/src/telperion-ng-pack-utils.ts"],"sourcesContent":["import { forwardRef, InjectionToken, Provider, Type } from \"@angular/core\";\r\n\r\n/**\r\n * Utility function to create a provider for a directive/component that can be injected as a service.\r\n * This is useful for cases where you want to inject a directive/component instance into another directive/component.\r\n *\r\n * Example usage:\r\n *\r\n * files:\r\n * - parent.directive.ts\r\n * - child.directive.ts\r\n * - parent.service.ts\r\n *\r\n * parent.service.ts:\r\n * ```\r\n * import { InjectionToken } from \"@angular/core\";\r\n * import type { ParentDirective } from \"./parent.directive\";\r\n *\r\n * export const ParentService = new InjectionToken<ParentDirective>(\"ParentService\");\r\n * ```\r\n *\r\n * parent.directive.ts:\r\n * ```\r\n * @Directive({\r\n * selector: 'parent',\r\n * providers: [provideServiceDirective(ParentService, ParentDirective)],\r\n * })\r\n * export class ParentDirective {...}\r\n * ```\r\n * child.directive.ts:\r\n * ```\r\n * @Directive({\r\n * selector: 'child',\r\n * })\r\n * export class ChildDirective {\r\n * #parent = inject(ParentService);\r\n * }\r\n * ```\r\n *\r\n * @param token - The injection token to provide.\r\n * @param directive - The directive/component class that will be provided.\r\n * @returns A provider object that can be used in the providers array of an Angular module or component.\r\n */\r\nexport function provideServiceDirective<T>(\r\n token: InjectionToken<T>,\r\n directive: Type<NoInfer<T>>\r\n): Provider {\r\n return {\r\n provide: token,\r\n useExisting: forwardRef(() => directive)\r\n }\r\n}\r\n","/**\r\n * Angular Event Manager Plugin that enables event modifier syntax in templates.\r\n *\r\n * @example\r\n * ```html\r\n * <form (submit.pd)=\"onSubmit()\">...</form>\r\n * <div (click.sp)=\"handleClick()\">...</div>\r\n * <button (click.pd.sp)=\"handleButtonClick()\">Click me</button>\r\n * ```\r\n */\r\n\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { Inject, Injectable, Provider } from '@angular/core';\r\nimport { EVENT_MANAGER_PLUGINS, EventManagerPlugin } from '@angular/platform-browser';\r\n\r\n/**\r\n * Event Manager Plugin that adds support for event modifiers.\r\n * @internal\r\n */\r\n@Injectable()\r\nexport class EventModifiersPlugin extends EventManagerPlugin {\r\n /**\r\n * Supported modifiers: `pd` (preventDefault), `sp` (stopPropagation)\r\n */\r\n private static modifierMap: { [key: string]: (e: Event) => void } = {\r\n 'pd': (e: Event) => e.preventDefault(),\r\n 'sp': (e: Event) => e.stopPropagation(),\r\n };\r\n\r\n constructor(@Inject(DOCUMENT) doc: Document) {\r\n super(doc);\r\n }\r\n\r\n supports(eventName: string): boolean {\r\n return eventName.includes('.') &&\r\n eventName.split('.').some(part => part in EventModifiersPlugin.modifierMap);\r\n }\r\n\r\n addEventListener(element: HTMLElement, eventName: string, handler: (event: Event) => void): () => void {\r\n const parts = eventName.split('.');\r\n const domEventName = parts[0];\r\n const modifiers = parts.slice(1).filter(m => m in EventModifiersPlugin.modifierMap);\r\n\r\n const wrappedHandler = (event: Event) => {\r\n modifiers.forEach(mod => EventModifiersPlugin.modifierMap[mod](event));\r\n\r\n return handler(event);\r\n };\r\n\r\n element.addEventListener(domEventName, wrappedHandler);\r\n\r\n return () => element.removeEventListener(domEventName, wrappedHandler);\r\n }\r\n}\r\n\r\n/**\r\n * Provides the Event Modifiers Plugin.\r\n *\r\n * @example\r\n * ```typescript\r\n * bootstrapApplication(AppComponent, {\r\n * providers: [provideEventModifiersPlugin()]\r\n * });\r\n * ```\r\n */\r\nexport function provideEventModifiersPlugin(): Provider {\r\n return {\r\n provide: EVENT_MANAGER_PLUGINS,\r\n useClass: EventModifiersPlugin,\r\n multi: true\r\n };\r\n}\r\n","import { HttpClient } from \"@angular/common/http\";\nimport { inject } from \"@angular/core\";\nimport { AnyFunction } from '@
|
|
1
|
+
{"version":3,"file":"telperion-ng-pack-utils.mjs","sources":["../../utils/src/provide-service-directive.ts","../../utils/src/event-modifiers.plugin.ts","../../utils/src/construct-fetcher.ts","../../utils/src/telperion-ng-pack-utils.ts"],"sourcesContent":["import { forwardRef, InjectionToken, Provider, Type } from \"@angular/core\";\r\n\r\n/**\r\n * Utility function to create a provider for a directive/component that can be injected as a service.\r\n * This is useful for cases where you want to inject a directive/component instance into another directive/component.\r\n *\r\n * Example usage:\r\n *\r\n * files:\r\n * - parent.directive.ts\r\n * - child.directive.ts\r\n * - parent.service.ts\r\n *\r\n * parent.service.ts:\r\n * ```\r\n * import { InjectionToken } from \"@angular/core\";\r\n * import type { ParentDirective } from \"./parent.directive\";\r\n *\r\n * export const ParentService = new InjectionToken<ParentDirective>(\"ParentService\");\r\n * ```\r\n *\r\n * parent.directive.ts:\r\n * ```\r\n * @Directive({\r\n * selector: 'parent',\r\n * providers: [provideServiceDirective(ParentService, ParentDirective)],\r\n * })\r\n * export class ParentDirective {...}\r\n * ```\r\n * child.directive.ts:\r\n * ```\r\n * @Directive({\r\n * selector: 'child',\r\n * })\r\n * export class ChildDirective {\r\n * #parent = inject(ParentService);\r\n * }\r\n * ```\r\n *\r\n * @param token - The injection token to provide.\r\n * @param directive - The directive/component class that will be provided.\r\n * @returns A provider object that can be used in the providers array of an Angular module or component.\r\n */\r\nexport function provideServiceDirective<T>(\r\n token: InjectionToken<T>,\r\n directive: Type<NoInfer<T>>\r\n): Provider {\r\n return {\r\n provide: token,\r\n useExisting: forwardRef(() => directive)\r\n }\r\n}\r\n","/**\r\n * Angular Event Manager Plugin that enables event modifier syntax in templates.\r\n *\r\n * @example\r\n * ```html\r\n * <form (submit.pd)=\"onSubmit()\">...</form>\r\n * <div (click.sp)=\"handleClick()\">...</div>\r\n * <button (click.pd.sp)=\"handleButtonClick()\">Click me</button>\r\n * ```\r\n */\r\n\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { Inject, Injectable, Provider } from '@angular/core';\r\nimport { EVENT_MANAGER_PLUGINS, EventManagerPlugin } from '@angular/platform-browser';\r\n\r\n/**\r\n * Event Manager Plugin that adds support for event modifiers.\r\n * @internal\r\n */\r\n@Injectable()\r\nexport class EventModifiersPlugin extends EventManagerPlugin {\r\n /**\r\n * Supported modifiers: `pd` (preventDefault), `sp` (stopPropagation)\r\n */\r\n private static modifierMap: { [key: string]: (e: Event) => void } = {\r\n 'pd': (e: Event) => e.preventDefault(),\r\n 'sp': (e: Event) => e.stopPropagation(),\r\n };\r\n\r\n constructor(@Inject(DOCUMENT) doc: Document) {\r\n super(doc);\r\n }\r\n\r\n supports(eventName: string): boolean {\r\n return eventName.includes('.') &&\r\n eventName.split('.').some(part => part in EventModifiersPlugin.modifierMap);\r\n }\r\n\r\n addEventListener(element: HTMLElement, eventName: string, handler: (event: Event) => void): () => void {\r\n const parts = eventName.split('.');\r\n const domEventName = parts[0];\r\n const modifiers = parts.slice(1).filter(m => m in EventModifiersPlugin.modifierMap);\r\n\r\n const wrappedHandler = (event: Event) => {\r\n modifiers.forEach(mod => EventModifiersPlugin.modifierMap[mod](event));\r\n\r\n return handler(event);\r\n };\r\n\r\n element.addEventListener(domEventName, wrappedHandler);\r\n\r\n return () => element.removeEventListener(domEventName, wrappedHandler);\r\n }\r\n}\r\n\r\n/**\r\n * Provides the Event Modifiers Plugin.\r\n *\r\n * @example\r\n * ```typescript\r\n * bootstrapApplication(AppComponent, {\r\n * providers: [provideEventModifiersPlugin()]\r\n * });\r\n * ```\r\n */\r\nexport function provideEventModifiersPlugin(): Provider {\r\n return {\r\n provide: EVENT_MANAGER_PLUGINS,\r\n useClass: EventModifiersPlugin,\r\n multi: true\r\n };\r\n}\r\n","import { HttpClient } from \"@angular/common/http\";\nimport { inject } from \"@angular/core\";\nimport { AnyFunction } from '@telperion/extra-ts-types';\nimport { tryCatch } from \"@telperion/js-utils/promise/try-catch\";\nimport { firstValueFrom, Observable } from 'rxjs';\n\nexport type Fetcher = {\n [P in keyof HttpClient]: HttpClient[P] extends (...args: infer A) => Observable<unknown> ? <T>(...args: A) => Promise<[unknown, T]> : never;\n}\n\n/**\n * Constructs a Fetcher that proxies HttpClient methods and returns a tuple of [error, response].\n * If the HttpClient method throws an error, it will be caught and returned as the first element of the tuple.\n * If the HttpClient method succeeds, the response will be returned as the second element of the tuple.\n * Example usage:\n * ```\n * @Component({\n * selector: 'app-example',\n * template: `<button (click)=\"fetchData()\">Fetch Data</button>`,\n * })\n * export class ExampleComponent {\n * private fetcher = constructFetcher();\n *\n * async fetchData() {\n * const [error, response] = await this.fetcher.get('/api/data');\n *\n* if (error) {\n* console.error('Error fetching data:', error);\n* } else {\n* console.log('Fetched data:', response);\n* }\n * }\n * }\n * ```\n */\nexport function constructFetcher() {\n const client = inject(HttpClient);\n\n return new Proxy({} as Fetcher, {\n get(target, prop) {\n if (prop in client) {\n return (...args: any[]) => {\n const method = (client as any)[prop] as AnyFunction;\n\n return tryCatch(firstValueFrom(method.apply(client, args)));\n }\n }\n\n throw new Error(`HttpClient does not have method ${String(prop)}`);\n }\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telperion/ng-pack",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Collection of Angular utilities and libraries organized as secondary entry points. Includes signal-based storage (localStorage/sessionStorage/cookieStorage), SSE client with HttpClient-inspired interceptors, event modifier plugins, and more. Built with TypeScript, RxJS, and Angular Signals for modern Angular applications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"rxjs": "^7.8.1"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@
|
|
36
|
-
"@
|
|
35
|
+
"@telperion/extra-ts-types": "^1.5.0",
|
|
36
|
+
"@telperion/js-utils": "^3.5.0",
|
|
37
37
|
"@telperion/reactive-storage": "^1.2.0",
|
|
38
38
|
"tslib": "^2.3.0"
|
|
39
39
|
},
|
package/sse-client/README.md
CHANGED
|
@@ -373,6 +373,25 @@ export class SecureFeedComponent {
|
|
|
373
373
|
}
|
|
374
374
|
```
|
|
375
375
|
|
|
376
|
+
#### Base Init Configuration
|
|
377
|
+
|
|
378
|
+
Use `withBaseInit()` to set default `EventSourceInit` options for all SSE connections:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
import { ApplicationConfig } from '@angular/core';
|
|
382
|
+
import { provideSseClient, withBaseInit } from '@telperion/ng-pack/sse-client';
|
|
383
|
+
|
|
384
|
+
export const appConfig: ApplicationConfig = {
|
|
385
|
+
providers: [
|
|
386
|
+
provideSseClient(
|
|
387
|
+
withBaseInit({ withCredentials: true })
|
|
388
|
+
)
|
|
389
|
+
]
|
|
390
|
+
};
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Options provided via `withBaseInit()` are merged into every request and can be overridden per-call through `SseClient.start()`.
|
|
394
|
+
|
|
376
395
|
## API Reference
|
|
377
396
|
|
|
378
397
|
### `provideSseClient(...features: SseFeature[][]): Provider[]`
|
|
@@ -435,6 +454,24 @@ withSseInterceptors(
|
|
|
435
454
|
|
|
436
455
|
---
|
|
437
456
|
|
|
457
|
+
### `withBaseInit(init: Partial<EventSourceInit>): SseFeature[]`
|
|
458
|
+
|
|
459
|
+
Configures default `EventSourceInit` options that are merged into every SSE request.
|
|
460
|
+
|
|
461
|
+
**Parameters:**
|
|
462
|
+
- `init` - Partial EventSource initialization options (e.g., `{ withCredentials: true }`)
|
|
463
|
+
|
|
464
|
+
**Returns:** Array of SSE features to be used with `provideSseClient()`
|
|
465
|
+
|
|
466
|
+
**Example:**
|
|
467
|
+
```typescript
|
|
468
|
+
provideSseClient(
|
|
469
|
+
withBaseInit({ withCredentials: true })
|
|
470
|
+
)
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
438
475
|
### `SseInterceptorFn<T>`
|
|
439
476
|
|
|
440
477
|
Type definition for functional interceptors.
|
|
@@ -15,6 +15,22 @@ interface SseFeature {
|
|
|
15
15
|
kind: SseFeatureKind;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Configures default EventSource initialization options for the SSE client.
|
|
20
|
+
* Merges the provided options into every SSE request's `init` via an interceptor.
|
|
21
|
+
*
|
|
22
|
+
* @param init - Partial EventSource initialization options to apply as defaults
|
|
23
|
+
* @returns Array of SSE features to be used with `provideSseClient()`
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* provideSseClient(
|
|
28
|
+
* withBaseInit({ withCredentials: true })
|
|
29
|
+
* )
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
declare function withBaseInit(init: Partial<EventSourceInit>): SseFeature[];
|
|
33
|
+
|
|
18
34
|
/**
|
|
19
35
|
* Represents an SSE request with URL and initialization options.
|
|
20
36
|
*/
|
|
@@ -137,5 +153,5 @@ declare class SseClient {
|
|
|
137
153
|
*/
|
|
138
154
|
declare function provideSseClient(...features: SseFeature[][]): Provider[];
|
|
139
155
|
|
|
140
|
-
export { SSE_INTERCEPTORS, SseClient, SseFeatureKind, provideSseClient, withSseInterceptors };
|
|
156
|
+
export { SSE_INTERCEPTORS, SseClient, SseFeatureKind, provideSseClient, withBaseInit, withSseInterceptors };
|
|
141
157
|
export type { SseFeature, SseInterceptor, SseInterceptorFn, SseInterceptorFunctionFeature, SseNextFn, SseRequest };
|
|
@@ -509,6 +509,6 @@ declare function provideCookieStorage(appName?: string, options?: ReactiveCookie
|
|
|
509
509
|
*
|
|
510
510
|
* @public
|
|
511
511
|
*/
|
|
512
|
-
declare function cookieStorageSignal<T>(store: string, key: string, options?: ReactiveCookieStorageOptions): StorageSignal<
|
|
512
|
+
declare function cookieStorageSignal<T>(store: string, key: string, options?: ReactiveCookieStorageOptions): StorageSignal<T>;
|
|
513
513
|
|
|
514
514
|
export { cookieStorageSignal, localStorageSignal, provideCookieStorage, provideLocalStorage, provideSessionStorage, sessionStorageSignal };
|