@angular-architects/ngrx-toolkit 20.3.0 → 20.4.1
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.
|
@@ -2,9 +2,10 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { Injectable, InjectionToken, signal, effect, inject, PLATFORM_ID, computed, isSignal, untracked, isDevMode as isDevMode$1, DestroyRef } from '@angular/core';
|
|
3
3
|
import { watchState, getState, signalStoreFeature, withMethods, withHooks, patchState as patchState$1, withState, withComputed, withProps, withLinkedState } from '@ngrx/signals';
|
|
4
4
|
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
|
|
5
|
-
import { Subject, switchMap, mergeMap, concatMap, exhaustMap, defer, tap, catchError, EMPTY, finalize } from 'rxjs';
|
|
5
|
+
import { Subject, switchMap, mergeMap, concatMap, exhaustMap, defer, tap, catchError, EMPTY, finalize, filter, map } from 'rxjs';
|
|
6
6
|
import { removeEntity, setAllEntities, updateEntity, addEntity } from '@ngrx/signals/entities';
|
|
7
7
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
8
|
+
import { HttpClient, HttpEventType, HttpResponse } from '@angular/common/http';
|
|
8
9
|
|
|
9
10
|
const DEVTOOLS_FEATURE = Symbol('DEVTOOLS_FEATURE');
|
|
10
11
|
function createDevtoolsFeature(options) {
|
|
@@ -341,7 +342,7 @@ Enable automatic indexing via withDevTools('${storeName}', { indexNames: true })
|
|
|
341
342
|
}, {});
|
|
342
343
|
this.#currentState = Object.entries(this.#currentState).reduce((newState, [storeName, state]) => {
|
|
343
344
|
if (storeName !== name) {
|
|
344
|
-
newState[
|
|
345
|
+
newState[storeName] = state;
|
|
345
346
|
}
|
|
346
347
|
return newState;
|
|
347
348
|
}, {});
|
|
@@ -349,18 +350,31 @@ Enable automatic indexing via withDevTools('${storeName}', { indexNames: true })
|
|
|
349
350
|
tracker.removeStore(id);
|
|
350
351
|
}
|
|
351
352
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
353
|
+
/**
|
|
354
|
+
* Renames a store identified by its internal id. If the store has already
|
|
355
|
+
* been removed (e.g. due to component destruction), this is a no-op.
|
|
356
|
+
*/
|
|
357
|
+
renameStore(id, newName) {
|
|
358
|
+
const storeEntry = this.#stores[id];
|
|
359
|
+
if (!storeEntry) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
const oldName = storeEntry.name;
|
|
363
|
+
if (oldName === newName) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
const otherStoreNames = Object.entries(this.#stores)
|
|
367
|
+
.filter(([entryId]) => entryId !== id)
|
|
368
|
+
.map(([, s]) => s.name);
|
|
369
|
+
if (otherStoreNames.includes(newName)) {
|
|
356
370
|
throw new Error(`NgRx Toolkit/DevTools: cannot rename from ${oldName} to ${newName}. ${newName} is already assigned to another SignalStore instance.`);
|
|
357
371
|
}
|
|
358
|
-
this.#stores = Object.entries(this.#stores).reduce((newStore, [
|
|
359
|
-
if (
|
|
360
|
-
newStore[
|
|
372
|
+
this.#stores = Object.entries(this.#stores).reduce((newStore, [entryId, value]) => {
|
|
373
|
+
if (entryId === id) {
|
|
374
|
+
newStore[entryId] = { ...value, name: newName };
|
|
361
375
|
}
|
|
362
376
|
else {
|
|
363
|
-
newStore[
|
|
377
|
+
newStore[entryId] = value;
|
|
364
378
|
}
|
|
365
379
|
return newStore;
|
|
366
380
|
}, {});
|
|
@@ -405,7 +419,7 @@ function withDevtools(name, ...features) {
|
|
|
405
419
|
// TODO: use withProps and symbols
|
|
406
420
|
return {
|
|
407
421
|
[renameDevtoolsMethodName]: (newName) => {
|
|
408
|
-
syncer.renameStore(
|
|
422
|
+
syncer.renameStore(id, newName);
|
|
409
423
|
},
|
|
410
424
|
[uniqueDevtoolsId]: () => id,
|
|
411
425
|
};
|
|
@@ -1811,47 +1825,73 @@ const exhaustOp = {
|
|
|
1811
1825
|
*
|
|
1812
1826
|
* The `operation` is the only mandatory option.
|
|
1813
1827
|
*
|
|
1828
|
+
* The returned mutation can be called as an async function and returns a Promise.
|
|
1829
|
+
* This promise informs about whether the mutation was successful, failed, or aborted
|
|
1830
|
+
* (due to switchMap or exhaustMap semantics).
|
|
1831
|
+
*
|
|
1832
|
+
* The mutation also provides several Signals such as error, status or isPending (see below).
|
|
1833
|
+
*
|
|
1834
|
+
* Example usage without Store:
|
|
1835
|
+
*
|
|
1814
1836
|
* ```typescript
|
|
1815
|
-
*
|
|
1816
|
-
* value: number;
|
|
1817
|
-
* };
|
|
1837
|
+
* const counterSignal = signal(0);
|
|
1818
1838
|
*
|
|
1819
|
-
*
|
|
1820
|
-
*
|
|
1821
|
-
*
|
|
1822
|
-
*
|
|
1823
|
-
*
|
|
1824
|
-
*
|
|
1825
|
-
*
|
|
1826
|
-
*
|
|
1827
|
-
*
|
|
1828
|
-
*
|
|
1829
|
-
*
|
|
1830
|
-
*
|
|
1831
|
-
*
|
|
1832
|
-
*
|
|
1833
|
-
*
|
|
1834
|
-
*
|
|
1835
|
-
*
|
|
1836
|
-
*
|
|
1837
|
-
*
|
|
1839
|
+
* const increment = rxMutation({
|
|
1840
|
+
* operation: (param: Param) => {
|
|
1841
|
+
* return calcSum(this.counterSignal(), param.value);
|
|
1842
|
+
* },
|
|
1843
|
+
* operator: concatOp,
|
|
1844
|
+
* onSuccess: (result) => {
|
|
1845
|
+
* this.counterSignal.set(result);
|
|
1846
|
+
* },
|
|
1847
|
+
* onError: (error) => {
|
|
1848
|
+
* console.error('Error occurred:', error);
|
|
1849
|
+
* },
|
|
1850
|
+
* });
|
|
1851
|
+
*
|
|
1852
|
+
* const error = increment.error;
|
|
1853
|
+
* const isPending = increment.isPending;
|
|
1854
|
+
* const status = increment.status;
|
|
1855
|
+
* const value = increment.value;
|
|
1856
|
+
* const hasValue = increment.hasValue;
|
|
1857
|
+
*
|
|
1858
|
+
* async function incrementCounter() {
|
|
1859
|
+
* const result = await increment({ value: 1 });
|
|
1860
|
+
* if (result.status === 'success') {
|
|
1861
|
+
* console.log('Success:', result.value);
|
|
1862
|
+
* }
|
|
1863
|
+
* if (result.status === 'error') {
|
|
1864
|
+
* console.log('Error:', result.error);
|
|
1865
|
+
* }
|
|
1866
|
+
* if (result.status === 'aborted') {
|
|
1867
|
+
* console.log('Operation aborted');
|
|
1868
|
+
* }
|
|
1869
|
+
* }
|
|
1838
1870
|
*
|
|
1839
1871
|
* function calcSum(a: number, b: number): Observable<number> {
|
|
1840
|
-
* return of(
|
|
1872
|
+
* return of(result).pipe(delay(500));
|
|
1841
1873
|
* }
|
|
1842
1874
|
* ```
|
|
1843
1875
|
*
|
|
1844
1876
|
* @param options
|
|
1845
|
-
* @returns
|
|
1877
|
+
* @returns the actual mutation function along tracking data as properties/methods
|
|
1846
1878
|
*/
|
|
1847
|
-
function rxMutation(
|
|
1879
|
+
function rxMutation(optionsOrOperation) {
|
|
1848
1880
|
const inputSubject = new Subject();
|
|
1881
|
+
const options = typeof optionsOrOperation === 'function'
|
|
1882
|
+
? { operation: optionsOrOperation }
|
|
1883
|
+
: optionsOrOperation;
|
|
1849
1884
|
const flatteningOp = options.operator ?? concatOp;
|
|
1850
1885
|
const destroyRef = options.injector?.get(DestroyRef) ?? inject(DestroyRef);
|
|
1851
1886
|
const callCount = signal(0, ...(ngDevMode ? [{ debugName: "callCount" }] : []));
|
|
1852
1887
|
const errorSignal = signal(undefined, ...(ngDevMode ? [{ debugName: "errorSignal" }] : []));
|
|
1853
1888
|
const idle = signal(true, ...(ngDevMode ? [{ debugName: "idle" }] : []));
|
|
1854
1889
|
const isPending = computed(() => callCount() > 0, ...(ngDevMode ? [{ debugName: "isPending" }] : []));
|
|
1890
|
+
const value = signal(undefined, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
1891
|
+
const isSuccess = computed(() => !idle() && !isPending() && !errorSignal(), ...(ngDevMode ? [{ debugName: "isSuccess" }] : []));
|
|
1892
|
+
const hasValue = function () {
|
|
1893
|
+
return typeof value() !== 'undefined';
|
|
1894
|
+
};
|
|
1855
1895
|
const status = computed(() => {
|
|
1856
1896
|
if (idle()) {
|
|
1857
1897
|
return 'idle';
|
|
@@ -1866,7 +1906,6 @@ function rxMutation(options) {
|
|
|
1866
1906
|
}, ...(ngDevMode ? [{ debugName: "status" }] : []));
|
|
1867
1907
|
const initialInnerStatus = 'idle';
|
|
1868
1908
|
let innerStatus = initialInnerStatus;
|
|
1869
|
-
let lastResult;
|
|
1870
1909
|
inputSubject
|
|
1871
1910
|
.pipe(flatteningOp.rxJsOperator((input) => defer(() => {
|
|
1872
1911
|
callCount.update((c) => c + 1);
|
|
@@ -1875,10 +1914,11 @@ function rxMutation(options) {
|
|
|
1875
1914
|
options.onSuccess?.(result, input.param);
|
|
1876
1915
|
innerStatus = 'success';
|
|
1877
1916
|
errorSignal.set(undefined);
|
|
1878
|
-
|
|
1917
|
+
value.set(result);
|
|
1879
1918
|
}), catchError((error) => {
|
|
1880
1919
|
options.onError?.(error, input.param);
|
|
1881
1920
|
errorSignal.set(error);
|
|
1921
|
+
value.set(undefined);
|
|
1882
1922
|
innerStatus = 'error';
|
|
1883
1923
|
return EMPTY;
|
|
1884
1924
|
}), finalize(() => {
|
|
@@ -1886,7 +1926,7 @@ function rxMutation(options) {
|
|
|
1886
1926
|
if (innerStatus === 'success') {
|
|
1887
1927
|
input.resolve({
|
|
1888
1928
|
status: 'success',
|
|
1889
|
-
value:
|
|
1929
|
+
value: value(),
|
|
1890
1930
|
});
|
|
1891
1931
|
}
|
|
1892
1932
|
else if (innerStatus === 'error') {
|
|
@@ -1923,6 +1963,9 @@ function rxMutation(options) {
|
|
|
1923
1963
|
mutation.status = status;
|
|
1924
1964
|
mutation.isPending = isPending;
|
|
1925
1965
|
mutation.error = errorSignal;
|
|
1966
|
+
mutation.value = value;
|
|
1967
|
+
mutation.hasValue = hasValue;
|
|
1968
|
+
mutation.isSuccess = isSuccess;
|
|
1926
1969
|
return mutation;
|
|
1927
1970
|
}
|
|
1928
1971
|
|
|
@@ -2060,9 +2103,107 @@ function mapToResource(store, name) {
|
|
|
2060
2103
|
};
|
|
2061
2104
|
}
|
|
2062
2105
|
|
|
2106
|
+
/**
|
|
2107
|
+
* Creates an HTTP mutation.
|
|
2108
|
+
*
|
|
2109
|
+
* ```typescript
|
|
2110
|
+
* export type Params = {
|
|
2111
|
+
* value: number;
|
|
2112
|
+
* };
|
|
2113
|
+
*
|
|
2114
|
+
* export type CounterResponse = {
|
|
2115
|
+
* // httpbin.org echos the request using the
|
|
2116
|
+
* // json property
|
|
2117
|
+
* json: { counter: number };
|
|
2118
|
+
* };
|
|
2119
|
+
*
|
|
2120
|
+
* const simpleSaveUser = httpMutation({
|
|
2121
|
+
* request: (userData: AddUserEntry) => ({
|
|
2122
|
+
* url: 'api/users',
|
|
2123
|
+
* body: userData,
|
|
2124
|
+
* }),
|
|
2125
|
+
* parse: Boolean,
|
|
2126
|
+
* })
|
|
2127
|
+
*
|
|
2128
|
+
* const saveUser = httpMutation({
|
|
2129
|
+
* request: (p: Params) => ({
|
|
2130
|
+
* url: `https://httpbin.org/post`,
|
|
2131
|
+
* method: 'POST',
|
|
2132
|
+
* body: { counter: p.value },
|
|
2133
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
2134
|
+
* }),
|
|
2135
|
+
* onSuccess: (response: CounterResponse) => {
|
|
2136
|
+
* console.log('Counter sent to server:', response);
|
|
2137
|
+
* },
|
|
2138
|
+
* onError: (error) => {
|
|
2139
|
+
* console.error('Failed to send counter:', error);
|
|
2140
|
+
* },
|
|
2141
|
+
* });
|
|
2142
|
+
*
|
|
2143
|
+
* const result = await this.saveUser({ value: 17 });
|
|
2144
|
+
* if (result.status === 'success') {
|
|
2145
|
+
* console.log('Successfully saved to server:', result.value);
|
|
2146
|
+
* }
|
|
2147
|
+
* else if (result.status === 'error') {
|
|
2148
|
+
* console.log('Failed to save:', result.error);
|
|
2149
|
+
* }
|
|
2150
|
+
* else {
|
|
2151
|
+
* console.log('Operation aborted');
|
|
2152
|
+
* }
|
|
2153
|
+
* ```
|
|
2154
|
+
*
|
|
2155
|
+
* @param options The options for the HTTP mutation.
|
|
2156
|
+
* @returns The HTTP mutation.
|
|
2157
|
+
*/
|
|
2158
|
+
function httpMutation(optionsOrRequest) {
|
|
2159
|
+
const httpClient = inject(HttpClient);
|
|
2160
|
+
const options = typeof optionsOrRequest === 'function'
|
|
2161
|
+
? { request: optionsOrRequest }
|
|
2162
|
+
: optionsOrRequest;
|
|
2163
|
+
const parse = options.parse ?? ((raw) => raw);
|
|
2164
|
+
const uploadProgress = signal(undefined, ...(ngDevMode ? [{ debugName: "uploadProgress" }] : []));
|
|
2165
|
+
const downloadProgress = signal(undefined, ...(ngDevMode ? [{ debugName: "downloadProgress" }] : []));
|
|
2166
|
+
const headers = signal(undefined, ...(ngDevMode ? [{ debugName: "headers" }] : []));
|
|
2167
|
+
const statusCode = signal(undefined, ...(ngDevMode ? [{ debugName: "statusCode" }] : []));
|
|
2168
|
+
const mutation = rxMutation({
|
|
2169
|
+
...options,
|
|
2170
|
+
operation: (param) => {
|
|
2171
|
+
const httpRequest = options.request(param);
|
|
2172
|
+
return defer(() => {
|
|
2173
|
+
uploadProgress.set(undefined);
|
|
2174
|
+
downloadProgress.set(undefined);
|
|
2175
|
+
headers.set(undefined);
|
|
2176
|
+
statusCode.set(undefined);
|
|
2177
|
+
return httpClient
|
|
2178
|
+
.request(httpRequest.method, httpRequest.url, {
|
|
2179
|
+
...httpRequest,
|
|
2180
|
+
observe: 'events',
|
|
2181
|
+
responseType: 'json',
|
|
2182
|
+
})
|
|
2183
|
+
.pipe(tap((response) => {
|
|
2184
|
+
if (response.type === HttpEventType.UploadProgress) {
|
|
2185
|
+
uploadProgress.set(response);
|
|
2186
|
+
}
|
|
2187
|
+
else if (response.type === HttpEventType.DownloadProgress) {
|
|
2188
|
+
downloadProgress.set(response);
|
|
2189
|
+
}
|
|
2190
|
+
}), filter((event) => event instanceof HttpResponse), tap((response) => {
|
|
2191
|
+
headers.set(response.headers);
|
|
2192
|
+
statusCode.set(response.status.toString());
|
|
2193
|
+
}), map((event) => parse(event.body)));
|
|
2194
|
+
});
|
|
2195
|
+
},
|
|
2196
|
+
});
|
|
2197
|
+
mutation.uploadProgress = uploadProgress;
|
|
2198
|
+
mutation.downloadProgress = downloadProgress;
|
|
2199
|
+
mutation.statusCode = statusCode;
|
|
2200
|
+
mutation.headers = headers;
|
|
2201
|
+
return mutation;
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2063
2204
|
/**
|
|
2064
2205
|
* Generated bundle index. Do not edit.
|
|
2065
2206
|
*/
|
|
2066
2207
|
|
|
2067
|
-
export { capitalize, concatOp, createEffects, createPageArray, createReducer, deriveCallStateKeys, emptyFeature, exhaustOp, firstPage, getCallStateKeys, getCollectionArray, getDataServiceKeys, getUndoRedoKeys, gotoPage, mapToResource, mergeOp, nextPage, noPayload, patchState, payload, previousPage, provideDevtoolsConfig, renameDevtoolsName, rxMutation, setError, setLoaded, setLoading, setMaxPageNavigationArrayItems, setPageSize, setResetState, switchOp, updateState, withCallState, withConditional, withDataService, withDevToolsStub, withDevtools, withDisabledNameIndices, withFeatureFactory, withGlitchTracking, withImmutableState, withIndexedDB, withIndexedDB as withIndexeddb, withLocalStorage, withMapper, withMutations, withPagination, withRedux, withReset, withResource, withSessionStorage, withStorageSync, withUndoRedo };
|
|
2208
|
+
export { capitalize, concatOp, createEffects, createPageArray, createReducer, deriveCallStateKeys, emptyFeature, exhaustOp, firstPage, getCallStateKeys, getCollectionArray, getDataServiceKeys, getUndoRedoKeys, gotoPage, httpMutation, mapToResource, mergeOp, nextPage, noPayload, patchState, payload, previousPage, provideDevtoolsConfig, renameDevtoolsName, rxMutation, setError, setLoaded, setLoading, setMaxPageNavigationArrayItems, setPageSize, setResetState, switchOp, updateState, withCallState, withConditional, withDataService, withDevToolsStub, withDevtools, withDisabledNameIndices, withFeatureFactory, withGlitchTracking, withImmutableState, withIndexedDB, withIndexedDB as withIndexeddb, withLocalStorage, withMapper, withMutations, withPagination, withRedux, withReset, withResource, withSessionStorage, withStorageSync, withUndoRedo };
|
|
2068
2209
|
//# sourceMappingURL=angular-architects-ngrx-toolkit.mjs.map
|