@angular-architects/ngrx-toolkit 19.4.0 → 19.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs +119 -0
  2. package/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs.map +1 -0
  3. package/fesm2022/angular-architects-ngrx-toolkit.mjs +2108 -0
  4. package/fesm2022/angular-architects-ngrx-toolkit.mjs.map +1 -0
  5. package/{src/index.ts → index.d.ts} +5 -32
  6. package/lib/assertions/assertions.d.ts +2 -0
  7. package/{src/lib/devtools/features/with-disabled-name-indicies.ts → lib/devtools/features/with-disabled-name-indicies.d.ts} +1 -5
  8. package/{src/lib/devtools/features/with-glitch-tracking.ts → lib/devtools/features/with-glitch-tracking.d.ts} +1 -6
  9. package/{src/lib/devtools/features/with-mapper.ts → lib/devtools/features/with-mapper.d.ts} +1 -7
  10. package/lib/devtools/internal/current-action-names.d.ts +1 -0
  11. package/lib/devtools/internal/default-tracker.d.ts +13 -0
  12. package/lib/devtools/internal/devtools-feature.d.ts +24 -0
  13. package/lib/devtools/internal/devtools-syncer.service.d.ts +39 -0
  14. package/lib/devtools/internal/glitch-tracker.service.d.ts +18 -0
  15. package/lib/devtools/internal/models.d.ts +24 -0
  16. package/{src/lib/devtools/provide-devtools-config.ts → lib/devtools/provide-devtools-config.d.ts} +4 -16
  17. package/lib/devtools/rename-devtools-name.d.ts +7 -0
  18. package/lib/devtools/update-state.d.ts +15 -0
  19. package/{src/lib/devtools/with-dev-tools-stub.ts → lib/devtools/with-dev-tools-stub.d.ts} +1 -2
  20. package/lib/devtools/with-devtools.d.ts +24 -0
  21. package/lib/flattening-operator.d.ts +14 -0
  22. package/lib/immutable-state/deep-freeze.d.ts +11 -0
  23. package/lib/immutable-state/is-dev-mode.d.ts +1 -0
  24. package/lib/immutable-state/with-immutable-state.d.ts +60 -0
  25. package/lib/mutation/http-mutation.d.ts +86 -0
  26. package/lib/mutation/mutation.d.ts +20 -0
  27. package/lib/mutation/rx-mutation.d.ts +76 -0
  28. package/{src/lib/shared/signal-store-models.ts → lib/shared/signal-store-models.d.ts} +4 -8
  29. package/lib/shared/throw-if-null.d.ts +1 -0
  30. package/lib/storage-sync/features/with-indexed-db.d.ts +2 -0
  31. package/lib/storage-sync/features/with-local-storage.d.ts +3 -0
  32. package/lib/storage-sync/internal/indexeddb.service.d.ts +29 -0
  33. package/lib/storage-sync/internal/local-storage.service.d.ts +8 -0
  34. package/lib/storage-sync/internal/models.d.ts +45 -0
  35. package/lib/storage-sync/internal/session-storage.service.d.ts +8 -0
  36. package/lib/storage-sync/with-storage-sync.d.ts +45 -0
  37. package/lib/with-call-state.d.ts +58 -0
  38. package/{src/lib/with-conditional.ts → lib/with-conditional.d.ts} +7 -31
  39. package/lib/with-data-service.d.ts +109 -0
  40. package/{src/lib/with-feature-factory.ts → lib/with-feature-factory.d.ts} +4 -32
  41. package/lib/with-mutations.d.ts +51 -0
  42. package/lib/with-pagination.d.ts +98 -0
  43. package/lib/with-redux.d.ts +147 -0
  44. package/lib/with-reset.d.ts +29 -0
  45. package/lib/with-undo-redo.d.ts +31 -0
  46. package/package.json +21 -4
  47. package/redux-connector/index.d.ts +2 -0
  48. package/redux-connector/src/lib/create-redux.d.ts +13 -0
  49. package/redux-connector/src/lib/model.d.ts +40 -0
  50. package/redux-connector/src/lib/rxjs-interop/redux-method.d.ts +14 -0
  51. package/redux-connector/src/lib/signal-redux-store.d.ts +11 -0
  52. package/redux-connector/src/lib/util.d.ts +5 -0
  53. package/eslint.config.cjs +0 -43
  54. package/jest.config.ts +0 -22
  55. package/ng-package.json +0 -7
  56. package/project.json +0 -37
  57. package/redux-connector/docs/README.md +0 -131
  58. package/redux-connector/index.ts +0 -6
  59. package/redux-connector/ng-package.json +0 -5
  60. package/redux-connector/src/lib/create-redux.ts +0 -102
  61. package/redux-connector/src/lib/model.ts +0 -89
  62. package/redux-connector/src/lib/rxjs-interop/redux-method.ts +0 -66
  63. package/redux-connector/src/lib/signal-redux-store.ts +0 -59
  64. package/redux-connector/src/lib/util.ts +0 -22
  65. package/src/lib/assertions/assertions.ts +0 -9
  66. package/src/lib/devtools/internal/current-action-names.ts +0 -1
  67. package/src/lib/devtools/internal/default-tracker.ts +0 -60
  68. package/src/lib/devtools/internal/devtools-feature.ts +0 -37
  69. package/src/lib/devtools/internal/devtools-syncer.service.ts +0 -202
  70. package/src/lib/devtools/internal/glitch-tracker.service.ts +0 -61
  71. package/src/lib/devtools/internal/models.ts +0 -29
  72. package/src/lib/devtools/rename-devtools-name.ts +0 -21
  73. package/src/lib/devtools/tests/action-name.spec.ts +0 -48
  74. package/src/lib/devtools/tests/basic.spec.ts +0 -111
  75. package/src/lib/devtools/tests/connecting.spec.ts +0 -37
  76. package/src/lib/devtools/tests/helpers.spec.ts +0 -43
  77. package/src/lib/devtools/tests/naming.spec.ts +0 -216
  78. package/src/lib/devtools/tests/provide-devtools-config.spec.ts +0 -25
  79. package/src/lib/devtools/tests/types.spec.ts +0 -19
  80. package/src/lib/devtools/tests/update-state.spec.ts +0 -29
  81. package/src/lib/devtools/tests/with-devtools.spec.ts +0 -5
  82. package/src/lib/devtools/tests/with-glitch-tracking.spec.ts +0 -272
  83. package/src/lib/devtools/tests/with-mapper.spec.ts +0 -69
  84. package/src/lib/devtools/update-state.ts +0 -38
  85. package/src/lib/devtools/with-devtools.ts +0 -81
  86. package/src/lib/flattening-operator.ts +0 -42
  87. package/src/lib/immutable-state/deep-freeze.ts +0 -43
  88. package/src/lib/immutable-state/is-dev-mode.ts +0 -6
  89. package/src/lib/immutable-state/tests/with-immutable-state.spec.ts +0 -260
  90. package/src/lib/immutable-state/with-immutable-state.ts +0 -115
  91. package/src/lib/mutation/http-mutation.spec.ts +0 -473
  92. package/src/lib/mutation/http-mutation.ts +0 -172
  93. package/src/lib/mutation/mutation.ts +0 -26
  94. package/src/lib/mutation/rx-mutation.spec.ts +0 -594
  95. package/src/lib/mutation/rx-mutation.ts +0 -208
  96. package/src/lib/shared/prettify.ts +0 -3
  97. package/src/lib/shared/throw-if-null.ts +0 -7
  98. package/src/lib/storage-sync/features/with-indexed-db.ts +0 -81
  99. package/src/lib/storage-sync/features/with-local-storage.ts +0 -58
  100. package/src/lib/storage-sync/internal/indexeddb.service.ts +0 -124
  101. package/src/lib/storage-sync/internal/local-storage.service.ts +0 -19
  102. package/src/lib/storage-sync/internal/models.ts +0 -62
  103. package/src/lib/storage-sync/internal/session-storage.service.ts +0 -18
  104. package/src/lib/storage-sync/tests/indexeddb.service.spec.ts +0 -99
  105. package/src/lib/storage-sync/tests/with-storage-async.spec.ts +0 -308
  106. package/src/lib/storage-sync/tests/with-storage-sync.spec.ts +0 -268
  107. package/src/lib/storage-sync/with-storage-sync.ts +0 -233
  108. package/src/lib/with-call-state.spec.ts +0 -42
  109. package/src/lib/with-call-state.ts +0 -195
  110. package/src/lib/with-conditional.spec.ts +0 -125
  111. package/src/lib/with-data-service.spec.ts +0 -564
  112. package/src/lib/with-data-service.ts +0 -433
  113. package/src/lib/with-feature-factory.spec.ts +0 -69
  114. package/src/lib/with-mutations.spec.ts +0 -537
  115. package/src/lib/with-mutations.ts +0 -146
  116. package/src/lib/with-pagination.spec.ts +0 -90
  117. package/src/lib/with-pagination.ts +0 -353
  118. package/src/lib/with-redux.spec.ts +0 -258
  119. package/src/lib/with-redux.ts +0 -387
  120. package/src/lib/with-reset.spec.ts +0 -112
  121. package/src/lib/with-reset.ts +0 -62
  122. package/src/lib/with-undo-redo.spec.ts +0 -287
  123. package/src/lib/with-undo-redo.ts +0 -199
  124. package/src/test-setup.ts +0 -8
  125. package/tsconfig.json +0 -29
  126. package/tsconfig.lib.json +0 -17
  127. package/tsconfig.lib.prod.json +0 -9
  128. package/tsconfig.spec.json +0 -17
@@ -1,208 +0,0 @@
1
- import { computed, DestroyRef, inject, Injector, signal } from '@angular/core';
2
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
- import {
4
- catchError,
5
- defer,
6
- EMPTY,
7
- finalize,
8
- Observable,
9
- Subject,
10
- tap,
11
- } from 'rxjs';
12
-
13
- import { concatOp, FlatteningOperator } from '../flattening-operator';
14
- import { Mutation, MutationResult, MutationStatus } from './mutation';
15
-
16
- export type Operation<Parameter, Result> = (param: Parameter) => Result;
17
-
18
- export interface RxMutationOptions<Parameter, Result> {
19
- operation: Operation<Parameter, Observable<Result>>;
20
- onSuccess?: (result: Result, param: Parameter) => void;
21
- onError?: (error: unknown, param: Parameter) => void;
22
- operator?: FlatteningOperator;
23
- injector?: Injector;
24
- }
25
-
26
- /**
27
- * Creates a mutation that leverages RxJS.
28
- *
29
- * For each mutation the following options can be defined:
30
- * - `operation`: A function that defines the mutation logic. It returns an Observable.
31
- * - `onSuccess`: A callback that is called when the mutation is successful.
32
- * - `onError`: A callback that is called when the mutation fails.
33
- * - `operator`: An optional wrapper of an RxJS flattening operator. By default `concat` sematics are used.
34
- * - `injector`: An optional Angular injector to use for dependency injection.
35
- *
36
- * The `operation` is the only mandatory option.
37
- *
38
- * The returned mutation can be called as an async function and returns a Promise.
39
- * This promise informs about whether the mutation was successful, failed, or aborted
40
- * (due to switchMap or exhaustMap semantics).
41
- *
42
- * The mutation also provides several Signals such as error, status or isPending (see below).
43
- *
44
- * Example usage without Store:
45
- *
46
- * ```typescript
47
- * const counterSignal = signal(0);
48
- *
49
- * const increment = rxMutation({
50
- * operation: (param: Param) => {
51
- * return calcSum(this.counterSignal(), param.value);
52
- * },
53
- * operator: concatOp,
54
- * onSuccess: (result) => {
55
- * this.counterSignal.set(result);
56
- * },
57
- * onError: (error) => {
58
- * console.error('Error occurred:', error);
59
- * },
60
- * });
61
- *
62
- * const error = increment.error;
63
- * const isPending = increment.isPending;
64
- * const status = increment.status;
65
- * const value = increment.value;
66
- * const hasValue = increment.hasValue;
67
- *
68
- * async function incrementCounter() {
69
- * const result = await increment({ value: 1 });
70
- * if (result.status === 'success') {
71
- * console.log('Success:', result.value);
72
- * }
73
- * if (result.status === 'error') {
74
- * console.log('Error:', result.error);
75
- * }
76
- * if (result.status === 'aborted') {
77
- * console.log('Operation aborted');
78
- * }
79
- * }
80
- *
81
- * function calcSum(a: number, b: number): Observable<number> {
82
- * return of(result).pipe(delay(500));
83
- * }
84
- * ```
85
- *
86
- * @param options
87
- * @returns the actual mutation function along tracking data as properties/methods
88
- */
89
- export function rxMutation<Parameter, Result>(
90
- optionsOrOperation:
91
- | RxMutationOptions<Parameter, Result>
92
- | Operation<Parameter, Observable<Result>>,
93
- ): Mutation<Parameter, Result> {
94
- const inputSubject = new Subject<{
95
- param: Parameter;
96
- resolve: (result: MutationResult<Result>) => void;
97
- }>();
98
-
99
- const options =
100
- typeof optionsOrOperation === 'function'
101
- ? { operation: optionsOrOperation }
102
- : optionsOrOperation;
103
-
104
- const flatteningOp = options.operator ?? concatOp;
105
-
106
- const destroyRef = options.injector?.get(DestroyRef) ?? inject(DestroyRef);
107
-
108
- const callCount = signal(0);
109
- const errorSignal = signal<unknown>(undefined);
110
- const idle = signal(true);
111
- const isPending = computed(() => callCount() > 0);
112
- const value = signal<Result | undefined>(undefined);
113
- const isSuccess = computed(() => !idle() && !isPending() && !errorSignal());
114
-
115
- const hasValue = function (
116
- this: Mutation<Parameter, Result>,
117
- ): this is Mutation<Exclude<Parameter, undefined>, Result> {
118
- return typeof value() !== 'undefined';
119
- };
120
-
121
- const status = computed<MutationStatus>(() => {
122
- if (idle()) {
123
- return 'idle';
124
- }
125
- if (callCount() > 0) {
126
- return 'pending';
127
- }
128
- if (errorSignal()) {
129
- return 'error';
130
- }
131
- return 'success';
132
- });
133
-
134
- const initialInnerStatus: MutationStatus = 'idle';
135
- let innerStatus: MutationStatus = initialInnerStatus;
136
-
137
- inputSubject
138
- .pipe(
139
- flatteningOp.rxJsOperator((input) =>
140
- defer(() => {
141
- callCount.update((c) => c + 1);
142
- idle.set(false);
143
- return options.operation(input.param).pipe(
144
- tap((result: Result) => {
145
- options.onSuccess?.(result, input.param);
146
- innerStatus = 'success';
147
- errorSignal.set(undefined);
148
- value.set(result);
149
- }),
150
- catchError((error: unknown) => {
151
- options.onError?.(error, input.param);
152
- errorSignal.set(error);
153
- value.set(undefined);
154
- innerStatus = 'error';
155
- return EMPTY;
156
- }),
157
- finalize(() => {
158
- callCount.update((c) => c - 1);
159
-
160
- if (innerStatus === 'success') {
161
- input.resolve({
162
- status: 'success',
163
- value: value() as Result,
164
- });
165
- } else if (innerStatus === 'error') {
166
- input.resolve({
167
- status: 'error',
168
- error: errorSignal(),
169
- });
170
- } else {
171
- input.resolve({
172
- status: 'aborted',
173
- });
174
- }
175
-
176
- innerStatus = initialInnerStatus;
177
- }),
178
- );
179
- }),
180
- ),
181
- takeUntilDestroyed(destroyRef),
182
- )
183
- .subscribe();
184
-
185
- const mutationFn = (param: Parameter) => {
186
- return new Promise<MutationResult<Result>>((resolve) => {
187
- if (callCount() > 0 && flatteningOp.exhaustSemantics) {
188
- resolve({
189
- status: 'aborted',
190
- });
191
- } else {
192
- inputSubject.next({
193
- param,
194
- resolve,
195
- });
196
- }
197
- });
198
- };
199
-
200
- const mutation = mutationFn as Mutation<Parameter, Result>;
201
- mutation.status = status;
202
- mutation.isPending = isPending;
203
- mutation.error = errorSignal;
204
- mutation.value = value;
205
- mutation.hasValue = hasValue;
206
- mutation.isSuccess = isSuccess;
207
- return mutation;
208
- }
@@ -1,3 +0,0 @@
1
- export type Prettify<Type extends object> = {
2
- [Key in keyof Type]: Type[Key];
3
- };
@@ -1,7 +0,0 @@
1
- export function throwIfNull<T>(obj: T): NonNullable<T> {
2
- if (obj === null || obj === undefined) {
3
- throw new Error('');
4
- }
5
-
6
- return obj;
7
- }
@@ -1,81 +0,0 @@
1
- import { inject } from '@angular/core';
2
- import { getState, patchState } from '@ngrx/signals';
3
- import { IndexedDBService } from '../internal/indexeddb.service';
4
- import {
5
- AsyncMethods,
6
- AsyncStorageStrategy,
7
- AsyncStoreForFactory,
8
- SYNC_STATUS,
9
- } from '../internal/models';
10
- import { SyncConfig } from '../with-storage-sync';
11
-
12
- export function withIndexedDB<
13
- State extends object,
14
- >(): AsyncStorageStrategy<State> {
15
- function factory(
16
- { key, parse, select, stringify }: Required<SyncConfig<State>>,
17
- store: AsyncStoreForFactory<State>,
18
- useStubs: boolean,
19
- ): AsyncMethods {
20
- if (useStubs) {
21
- return {
22
- clearStorage: () => Promise.resolve(),
23
- readFromStorage: () => Promise.resolve(),
24
- writeToStorage: () => Promise.resolve(),
25
- };
26
- }
27
-
28
- const indexeddbService = inject(IndexedDBService);
29
-
30
- function warnOnSyncing(mode: 'read' | 'write'): void {
31
- if (store[SYNC_STATUS]() === 'syncing') {
32
- const prettyMode = mode === 'read' ? 'Reading' : 'Writing';
33
- console.warn(
34
- `${prettyMode} to Store (${key}) happened during an ongoing synchronization process.`,
35
- 'Please ensure that the store is not in syncing state via `store.whenSynced()`.',
36
- 'Alternatively, you can disable the autoSync by passing `autoSync: false` in the config.',
37
- );
38
- }
39
- }
40
-
41
- return {
42
- /**
43
- * Removes the item stored in storage.
44
- */
45
- async clearStorage(): Promise<void> {
46
- warnOnSyncing('write');
47
- store[SYNC_STATUS].set('syncing');
48
- patchState(store, {});
49
- await indexeddbService.clear(key);
50
- store[SYNC_STATUS].set('synced');
51
- },
52
-
53
- /**
54
- * Reads item from storage and patches the state.
55
- */
56
- async readFromStorage(): Promise<void> {
57
- warnOnSyncing('read');
58
- store[SYNC_STATUS].set('syncing');
59
- const stateString = await indexeddbService.getItem(key);
60
- if (stateString) {
61
- patchState(store, parse(stateString));
62
- }
63
- store[SYNC_STATUS].set('synced');
64
- },
65
-
66
- /**
67
- * Writes selected portion to storage.
68
- */
69
- async writeToStorage(): Promise<void> {
70
- warnOnSyncing('write');
71
- store[SYNC_STATUS].set('syncing');
72
- const slicedState = select(getState(store)) as State;
73
- await indexeddbService.setItem(key, stringify(slicedState));
74
- store[SYNC_STATUS].set('synced');
75
- },
76
- };
77
- }
78
- factory.type = 'async' as const;
79
-
80
- return factory;
81
- }
@@ -1,58 +0,0 @@
1
- import { inject, Type } from '@angular/core';
2
- import { getState, patchState } from '@ngrx/signals';
3
- import { LocalStorageService } from '../internal/local-storage.service';
4
- import { SyncStorageStrategy, SyncStoreForFactory } from '../internal/models';
5
- import { SessionStorageService } from '../internal/session-storage.service';
6
- import { SyncConfig } from '../with-storage-sync';
7
-
8
- export function withLocalStorage<
9
- State extends object,
10
- >(): SyncStorageStrategy<State> {
11
- return createSyncMethods<State>(LocalStorageService);
12
- }
13
-
14
- export function withSessionStorage<State extends object>() {
15
- return createSyncMethods<State>(SessionStorageService);
16
- }
17
-
18
- function createSyncMethods<State extends object>(
19
- Storage: Type<LocalStorageService | SessionStorageService>,
20
- ): SyncStorageStrategy<State> {
21
- function factory(
22
- { key, parse, select, stringify }: Required<SyncConfig<State>>,
23
- store: SyncStoreForFactory<State>,
24
- useStubs: boolean,
25
- ) {
26
- if (useStubs) {
27
- return {
28
- clearStorage: () => undefined,
29
- readFromStorage: () => undefined,
30
- writeToStorage: () => undefined,
31
- };
32
- }
33
-
34
- const storage = inject(Storage);
35
-
36
- return {
37
- clearStorage(): void {
38
- storage.clear(key);
39
- },
40
-
41
- readFromStorage(): void {
42
- const stateString = storage.getItem(key);
43
-
44
- if (stateString) {
45
- patchState(store, parse(stateString));
46
- }
47
- },
48
-
49
- writeToStorage() {
50
- const slicedState = select(getState(store)) as State;
51
- storage.setItem(key, stringify(slicedState));
52
- },
53
- };
54
- }
55
- factory.type = 'sync' as const;
56
-
57
- return factory;
58
- }
@@ -1,124 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
-
3
- export const keyPath = 'ngrxToolkitKeyPath';
4
-
5
- export const dbName = 'ngrxToolkitDb';
6
-
7
- export const storeName = 'ngrxToolkitStore';
8
-
9
- export const VERSION: number = 1 as const;
10
-
11
- @Injectable({ providedIn: 'root' })
12
- export class IndexedDBService {
13
- /**
14
- * write to indexedDB
15
- * @param key
16
- * @param data
17
- */
18
- async setItem(key: string, data: string): Promise<void> {
19
- const db = await this.openDB();
20
-
21
- const tx = db.transaction(storeName, 'readwrite');
22
-
23
- const store = tx.objectStore(storeName);
24
-
25
- store.put({
26
- [keyPath]: key,
27
- value: data,
28
- });
29
-
30
- return new Promise((resolve, reject) => {
31
- tx.oncomplete = (): void => {
32
- db.close();
33
- resolve();
34
- };
35
-
36
- tx.onerror = (): void => {
37
- db.close();
38
- reject();
39
- };
40
- });
41
- }
42
-
43
- /**
44
- * read from indexedDB
45
- * @param key
46
- */
47
- async getItem(key: string): Promise<string | null> {
48
- const db = await this.openDB();
49
-
50
- const tx = db.transaction(storeName, 'readonly');
51
-
52
- const store = tx.objectStore(storeName);
53
-
54
- const request = store.get(key);
55
-
56
- return new Promise((resolve, reject) => {
57
- request.onsuccess = (): void => {
58
- db.close();
59
- // localStorage(sessionStorage) returns null if the key does not exist
60
- // Similarly, indexedDB should return null
61
- if (request.result === undefined) {
62
- resolve(null);
63
- }
64
- resolve(request.result?.['value']);
65
- };
66
-
67
- request.onerror = (): void => {
68
- db.close();
69
- reject();
70
- };
71
- });
72
- }
73
-
74
- /**
75
- * delete indexedDB
76
- * @param key
77
- */
78
- async clear(key: string): Promise<void> {
79
- const db = await this.openDB();
80
-
81
- const tx = db.transaction(storeName, 'readwrite');
82
-
83
- const store = tx.objectStore(storeName);
84
-
85
- const request = store.delete(key);
86
-
87
- return new Promise((resolve, reject) => {
88
- request.onsuccess = (): void => {
89
- db.close();
90
- resolve();
91
- };
92
-
93
- request.onerror = (): void => {
94
- db.close();
95
- reject();
96
- };
97
- });
98
- }
99
-
100
- /**
101
- * open indexedDB
102
- */
103
- private async openDB(): Promise<IDBDatabase> {
104
- return new Promise((resolve, reject) => {
105
- const request = indexedDB.open(dbName, VERSION);
106
-
107
- request.onupgradeneeded = () => {
108
- const db = request.result;
109
-
110
- if (!db.objectStoreNames.contains(storeName)) {
111
- db.createObjectStore(storeName, { keyPath });
112
- }
113
- };
114
-
115
- request.onsuccess = (): void => {
116
- resolve(request.result);
117
- };
118
-
119
- request.onerror = (): void => {
120
- reject(request.error);
121
- };
122
- });
123
- }
124
- }
@@ -1,19 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
- import {} from './models';
3
-
4
- @Injectable({
5
- providedIn: 'root',
6
- })
7
- export class LocalStorageService {
8
- getItem(key: string): string | null {
9
- return localStorage.getItem(key);
10
- }
11
-
12
- setItem(key: string, data: string): void {
13
- return localStorage.setItem(key, data);
14
- }
15
-
16
- clear(key: string): void {
17
- return localStorage.removeItem(key);
18
- }
19
- }
@@ -1,62 +0,0 @@
1
- import { Signal, WritableSignal } from '@angular/core';
2
- import { EmptyFeatureResult, WritableStateSource } from '@ngrx/signals';
3
- import { SyncConfig } from '../with-storage-sync';
4
-
5
- export type SyncMethods = {
6
- clearStorage(): void;
7
- readFromStorage(): void;
8
- writeToStorage(): void;
9
- };
10
-
11
- export type SyncFeatureResult = EmptyFeatureResult & {
12
- methods: SyncMethods;
13
- };
14
-
15
- export type SyncStoreForFactory<State extends object> =
16
- WritableStateSource<State>;
17
-
18
- export type SyncStorageStrategy<State extends object> = ((
19
- config: Required<SyncConfig<State>>,
20
- store: SyncStoreForFactory<State>,
21
- useStubs: boolean,
22
- ) => SyncMethods) & { type: 'sync' };
23
-
24
- export type AsyncMethods = {
25
- clearStorage(): Promise<void>;
26
- readFromStorage(): Promise<void>;
27
- writeToStorage(): Promise<void>;
28
- };
29
-
30
- /**
31
- * AsyncFeatureResult is used as the public interface that users interact with
32
- * when calling `withIndexedDB`. It intentionally omits the internal SYNC_STATUS
33
- * property to avoid TypeScript error TS4058 (return type of public method
34
- * includes private type).
35
- *
36
- * For internal implementation, we use AsyncStoreForFactory which includes
37
- * the SYNC_STATUS property needed for state management.
38
- */
39
- export const SYNC_STATUS = Symbol('SYNC_STATUS');
40
- export type SyncStatus = 'idle' | 'syncing' | 'synced';
41
-
42
- // Keeping it internal avoids TS4058 error
43
- export type InternalAsyncProps = AsyncFeatureResult['props'] & {
44
- [SYNC_STATUS]: WritableSignal<SyncStatus>;
45
- };
46
-
47
- export type AsyncFeatureResult = EmptyFeatureResult & {
48
- methods: AsyncMethods;
49
- props: {
50
- isSynced: Signal<boolean>;
51
- whenSynced: () => Promise<void>;
52
- };
53
- };
54
-
55
- export type AsyncStoreForFactory<State extends object> =
56
- WritableStateSource<State> & InternalAsyncProps;
57
-
58
- export type AsyncStorageStrategy<State extends object> = ((
59
- config: Required<SyncConfig<State>>,
60
- store: AsyncStoreForFactory<State>,
61
- useStubs: boolean,
62
- ) => AsyncMethods) & { type: 'async' };
@@ -1,18 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
-
3
- @Injectable({
4
- providedIn: 'root',
5
- })
6
- export class SessionStorageService {
7
- getItem(key: string): string | null {
8
- return sessionStorage.getItem(key);
9
- }
10
-
11
- setItem(key: string, data: string): void {
12
- return sessionStorage.setItem(key, data);
13
- }
14
-
15
- clear(key: string): void {
16
- return sessionStorage.removeItem(key);
17
- }
18
- }
@@ -1,99 +0,0 @@
1
- import 'fake-indexeddb/auto';
2
- import { IndexedDBService } from '../internal/indexeddb.service';
3
-
4
- describe('IndexedDBService', () => {
5
- const sampleData = JSON.stringify({
6
- foo: 'bar',
7
- users: [
8
- { name: 'John', age: 30, isAdmin: true },
9
- { name: 'Jane', age: 25, isAdmin: false },
10
- ],
11
- });
12
-
13
- let indexedDBService: IndexedDBService;
14
-
15
- beforeEach(() => {
16
- indexedDBService = new IndexedDBService();
17
- });
18
-
19
- it('It should be possible to write data using write() and then read the data using read()', async (): Promise<void> => {
20
- const key = 'users';
21
-
22
- const expectedData = sampleData;
23
-
24
- await indexedDBService.setItem(key, sampleData);
25
-
26
- const receivedData = await indexedDBService.getItem(key);
27
-
28
- expect(receivedData).toEqual(expectedData);
29
- });
30
-
31
- it('It should be possible to delete data using clear()', async (): Promise<void> => {
32
- const key = 'sample';
33
-
34
- await indexedDBService.setItem(key, sampleData);
35
-
36
- await indexedDBService.clear(key);
37
-
38
- const receivedData = await indexedDBService.getItem(key);
39
-
40
- expect(receivedData).toEqual(null);
41
- });
42
-
43
- it('When there is no data, read() should return null', async (): Promise<void> => {
44
- const key = 'nullData';
45
-
46
- const receivedData = await indexedDBService.getItem(key);
47
-
48
- expect(receivedData).toEqual(null);
49
- });
50
-
51
- it('write() should handle null data', async (): Promise<void> => {
52
- const key = 'nullData';
53
-
54
- await indexedDBService.setItem(key, JSON.stringify(null));
55
-
56
- const receivedData = await indexedDBService.getItem(key);
57
-
58
- expect(receivedData).toEqual('null');
59
- });
60
-
61
- it('write() should handle empty object data', async (): Promise<void> => {
62
- const key = 'emptyData';
63
-
64
- const emptyData = JSON.stringify({});
65
- const expectedData = emptyData;
66
-
67
- await indexedDBService.setItem(key, emptyData);
68
-
69
- const receivedData = await indexedDBService.getItem(key);
70
-
71
- expect(receivedData).toEqual(expectedData);
72
- });
73
-
74
- it('write() should handle large data objects', async (): Promise<void> => {
75
- const key = 'largeData';
76
-
77
- const largeData = JSON.stringify({ foo: 'a'.repeat(100000) });
78
- const expectedData = largeData;
79
-
80
- await indexedDBService.setItem(key, largeData);
81
-
82
- const receivedData = await indexedDBService.getItem(key);
83
-
84
- expect(receivedData).toEqual(expectedData);
85
- });
86
-
87
- it('write() should handle special characters in data', async (): Promise<void> => {
88
- const key = 'specialCharData';
89
-
90
- const specialCharData = JSON.stringify({ foo: 'bar!@#$%^&*()_+{}:"<>?' });
91
- const expectedData = specialCharData;
92
-
93
- await indexedDBService.setItem(key, specialCharData);
94
-
95
- const receivedData = await indexedDBService.getItem(key);
96
-
97
- expect(receivedData).toEqual(expectedData);
98
- });
99
- });