@angular-architects/ngrx-toolkit 19.3.0 → 19.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.
- package/fesm2022/angular-architects-ngrx-toolkit.mjs +158 -30
- package/fesm2022/angular-architects-ngrx-toolkit.mjs.map +1 -1
- package/index.d.ts +3 -1
- package/lib/mutation/http-mutation.d.ts +86 -0
- package/lib/mutation/mutation.d.ts +20 -0
- package/lib/mutation/rx-mutation.d.ts +76 -0
- package/lib/with-mutations.d.ts +1 -16
- package/package.json +1 -1
- package/lib/rx-mutation.d.ts +0 -58
|
@@ -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 } 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) {
|
|
@@ -1809,47 +1810,73 @@ const exhaustOp = {
|
|
|
1809
1810
|
*
|
|
1810
1811
|
* The `operation` is the only mandatory option.
|
|
1811
1812
|
*
|
|
1813
|
+
* The returned mutation can be called as an async function and returns a Promise.
|
|
1814
|
+
* This promise informs about whether the mutation was successful, failed, or aborted
|
|
1815
|
+
* (due to switchMap or exhaustMap semantics).
|
|
1816
|
+
*
|
|
1817
|
+
* The mutation also provides several Signals such as error, status or isPending (see below).
|
|
1818
|
+
*
|
|
1819
|
+
* Example usage without Store:
|
|
1820
|
+
*
|
|
1812
1821
|
* ```typescript
|
|
1813
|
-
*
|
|
1814
|
-
* value: number;
|
|
1815
|
-
* };
|
|
1822
|
+
* const counterSignal = signal(0);
|
|
1816
1823
|
*
|
|
1817
|
-
*
|
|
1818
|
-
*
|
|
1819
|
-
*
|
|
1820
|
-
*
|
|
1821
|
-
*
|
|
1822
|
-
*
|
|
1823
|
-
*
|
|
1824
|
-
*
|
|
1825
|
-
*
|
|
1826
|
-
*
|
|
1827
|
-
*
|
|
1828
|
-
*
|
|
1829
|
-
*
|
|
1830
|
-
*
|
|
1831
|
-
*
|
|
1832
|
-
*
|
|
1833
|
-
*
|
|
1834
|
-
*
|
|
1835
|
-
*
|
|
1824
|
+
* const increment = rxMutation({
|
|
1825
|
+
* operation: (param: Param) => {
|
|
1826
|
+
* return calcSum(this.counterSignal(), param.value);
|
|
1827
|
+
* },
|
|
1828
|
+
* operator: concatOp,
|
|
1829
|
+
* onSuccess: (result) => {
|
|
1830
|
+
* this.counterSignal.set(result);
|
|
1831
|
+
* },
|
|
1832
|
+
* onError: (error) => {
|
|
1833
|
+
* console.error('Error occurred:', error);
|
|
1834
|
+
* },
|
|
1835
|
+
* });
|
|
1836
|
+
*
|
|
1837
|
+
* const error = increment.error;
|
|
1838
|
+
* const isPending = increment.isPending;
|
|
1839
|
+
* const status = increment.status;
|
|
1840
|
+
* const value = increment.value;
|
|
1841
|
+
* const hasValue = increment.hasValue;
|
|
1842
|
+
*
|
|
1843
|
+
* async function incrementCounter() {
|
|
1844
|
+
* const result = await increment({ value: 1 });
|
|
1845
|
+
* if (result.status === 'success') {
|
|
1846
|
+
* console.log('Success:', result.value);
|
|
1847
|
+
* }
|
|
1848
|
+
* if (result.status === 'error') {
|
|
1849
|
+
* console.log('Error:', result.error);
|
|
1850
|
+
* }
|
|
1851
|
+
* if (result.status === 'aborted') {
|
|
1852
|
+
* console.log('Operation aborted');
|
|
1853
|
+
* }
|
|
1854
|
+
* }
|
|
1836
1855
|
*
|
|
1837
1856
|
* function calcSum(a: number, b: number): Observable<number> {
|
|
1838
|
-
* return of(
|
|
1857
|
+
* return of(result).pipe(delay(500));
|
|
1839
1858
|
* }
|
|
1840
1859
|
* ```
|
|
1841
1860
|
*
|
|
1842
1861
|
* @param options
|
|
1843
|
-
* @returns
|
|
1862
|
+
* @returns the actual mutation function along tracking data as properties/methods
|
|
1844
1863
|
*/
|
|
1845
|
-
function rxMutation(
|
|
1864
|
+
function rxMutation(optionsOrOperation) {
|
|
1846
1865
|
const inputSubject = new Subject();
|
|
1866
|
+
const options = typeof optionsOrOperation === 'function'
|
|
1867
|
+
? { operation: optionsOrOperation }
|
|
1868
|
+
: optionsOrOperation;
|
|
1847
1869
|
const flatteningOp = options.operator ?? concatOp;
|
|
1848
1870
|
const destroyRef = options.injector?.get(DestroyRef) ?? inject(DestroyRef);
|
|
1849
1871
|
const callCount = signal(0);
|
|
1850
1872
|
const errorSignal = signal(undefined);
|
|
1851
1873
|
const idle = signal(true);
|
|
1852
1874
|
const isPending = computed(() => callCount() > 0);
|
|
1875
|
+
const value = signal(undefined);
|
|
1876
|
+
const isSuccess = computed(() => !idle() && !isPending() && !errorSignal());
|
|
1877
|
+
const hasValue = function () {
|
|
1878
|
+
return typeof value() !== 'undefined';
|
|
1879
|
+
};
|
|
1853
1880
|
const status = computed(() => {
|
|
1854
1881
|
if (idle()) {
|
|
1855
1882
|
return 'idle';
|
|
@@ -1864,7 +1891,6 @@ function rxMutation(options) {
|
|
|
1864
1891
|
});
|
|
1865
1892
|
const initialInnerStatus = 'idle';
|
|
1866
1893
|
let innerStatus = initialInnerStatus;
|
|
1867
|
-
let lastResult;
|
|
1868
1894
|
inputSubject
|
|
1869
1895
|
.pipe(flatteningOp.rxJsOperator((input) => defer(() => {
|
|
1870
1896
|
callCount.update((c) => c + 1);
|
|
@@ -1873,10 +1899,11 @@ function rxMutation(options) {
|
|
|
1873
1899
|
options.onSuccess?.(result, input.param);
|
|
1874
1900
|
innerStatus = 'success';
|
|
1875
1901
|
errorSignal.set(undefined);
|
|
1876
|
-
|
|
1902
|
+
value.set(result);
|
|
1877
1903
|
}), catchError((error) => {
|
|
1878
1904
|
options.onError?.(error, input.param);
|
|
1879
1905
|
errorSignal.set(error);
|
|
1906
|
+
value.set(undefined);
|
|
1880
1907
|
innerStatus = 'error';
|
|
1881
1908
|
return EMPTY;
|
|
1882
1909
|
}), finalize(() => {
|
|
@@ -1884,7 +1911,7 @@ function rxMutation(options) {
|
|
|
1884
1911
|
if (innerStatus === 'success') {
|
|
1885
1912
|
input.resolve({
|
|
1886
1913
|
status: 'success',
|
|
1887
|
-
value:
|
|
1914
|
+
value: value(),
|
|
1888
1915
|
});
|
|
1889
1916
|
}
|
|
1890
1917
|
else if (innerStatus === 'error') {
|
|
@@ -1921,6 +1948,9 @@ function rxMutation(options) {
|
|
|
1921
1948
|
mutation.status = status;
|
|
1922
1949
|
mutation.isPending = isPending;
|
|
1923
1950
|
mutation.error = errorSignal;
|
|
1951
|
+
mutation.value = value;
|
|
1952
|
+
mutation.hasValue = hasValue;
|
|
1953
|
+
mutation.isSuccess = isSuccess;
|
|
1924
1954
|
return mutation;
|
|
1925
1955
|
}
|
|
1926
1956
|
|
|
@@ -1959,9 +1989,107 @@ function createMutationsFeature(mutations) {
|
|
|
1959
1989
|
return feature;
|
|
1960
1990
|
}
|
|
1961
1991
|
|
|
1992
|
+
/**
|
|
1993
|
+
* Creates an HTTP mutation.
|
|
1994
|
+
*
|
|
1995
|
+
* export type Params = {
|
|
1996
|
+
* value: number;
|
|
1997
|
+
* };
|
|
1998
|
+
*
|
|
1999
|
+
* export type CounterResponse = {
|
|
2000
|
+
* // httpbin.org echos the request using the
|
|
2001
|
+
* // json property
|
|
2002
|
+
* json: { counter: number };
|
|
2003
|
+
* };
|
|
2004
|
+
*
|
|
2005
|
+
* const simpleSaveUser = httpMutation({
|
|
2006
|
+
* request: (userData: AddUserEntry) => ({
|
|
2007
|
+
* url: 'api/users',
|
|
2008
|
+
* body: userData,
|
|
2009
|
+
* }),
|
|
2010
|
+
* parse: Boolean,
|
|
2011
|
+
* })
|
|
2012
|
+
*
|
|
2013
|
+
* const saveUser = httpMutation({
|
|
2014
|
+
* request: (p: Params) => ({
|
|
2015
|
+
* url: `https://httpbin.org/post`,
|
|
2016
|
+
* method: 'POST',
|
|
2017
|
+
* body: { counter: p.value },
|
|
2018
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
2019
|
+
* }),
|
|
2020
|
+
* onSuccess: (response: CounterResponse) => {
|
|
2021
|
+
* console.log('Counter sent to server:', response);
|
|
2022
|
+
* },
|
|
2023
|
+
* onError: (error) => {
|
|
2024
|
+
* console.error('Failed to send counter:', error);
|
|
2025
|
+
* },
|
|
2026
|
+
* });
|
|
2027
|
+
*
|
|
2028
|
+
* ...
|
|
2029
|
+
*
|
|
2030
|
+
* const result = await this.saveUser({ value: 17 });
|
|
2031
|
+
* if (result.status === 'success') {
|
|
2032
|
+
* console.log('Successfully saved to server:', result.value);
|
|
2033
|
+
* }
|
|
2034
|
+
* else if (result.status === 'error') {
|
|
2035
|
+
* console.log('Failed to save:', result.error);
|
|
2036
|
+
* }
|
|
2037
|
+
* else {
|
|
2038
|
+
* console.log('Operation aborted');
|
|
2039
|
+
* }
|
|
2040
|
+
*
|
|
2041
|
+
* @param options The options for the HTTP mutation.
|
|
2042
|
+
* @returns The HTTP mutation.
|
|
2043
|
+
*/
|
|
2044
|
+
function httpMutation(optionsOrRequest) {
|
|
2045
|
+
const httpClient = inject(HttpClient);
|
|
2046
|
+
const options = typeof optionsOrRequest === 'function'
|
|
2047
|
+
? { request: optionsOrRequest }
|
|
2048
|
+
: optionsOrRequest;
|
|
2049
|
+
const parse = options.parse ?? ((raw) => raw);
|
|
2050
|
+
const uploadProgress = signal(undefined);
|
|
2051
|
+
const downloadProgress = signal(undefined);
|
|
2052
|
+
const headers = signal(undefined);
|
|
2053
|
+
const statusCode = signal(undefined);
|
|
2054
|
+
const mutation = rxMutation({
|
|
2055
|
+
...options,
|
|
2056
|
+
operation: (param) => {
|
|
2057
|
+
const httpRequest = options.request(param);
|
|
2058
|
+
return defer(() => {
|
|
2059
|
+
uploadProgress.set(undefined);
|
|
2060
|
+
downloadProgress.set(undefined);
|
|
2061
|
+
headers.set(undefined);
|
|
2062
|
+
statusCode.set(undefined);
|
|
2063
|
+
return httpClient
|
|
2064
|
+
.request(httpRequest.method, httpRequest.url, {
|
|
2065
|
+
...httpRequest,
|
|
2066
|
+
observe: 'events',
|
|
2067
|
+
responseType: 'json',
|
|
2068
|
+
})
|
|
2069
|
+
.pipe(tap((response) => {
|
|
2070
|
+
if (response.type === HttpEventType.UploadProgress) {
|
|
2071
|
+
uploadProgress.set(response);
|
|
2072
|
+
}
|
|
2073
|
+
else if (response.type === HttpEventType.DownloadProgress) {
|
|
2074
|
+
downloadProgress.set(response);
|
|
2075
|
+
}
|
|
2076
|
+
}), filter((event) => event instanceof HttpResponse), tap((response) => {
|
|
2077
|
+
headers.set(response.headers);
|
|
2078
|
+
statusCode.set(response.status.toString());
|
|
2079
|
+
}), map((event) => parse(event.body)));
|
|
2080
|
+
});
|
|
2081
|
+
},
|
|
2082
|
+
});
|
|
2083
|
+
mutation.uploadProgress = uploadProgress;
|
|
2084
|
+
mutation.downloadProgress = downloadProgress;
|
|
2085
|
+
mutation.statusCode = statusCode;
|
|
2086
|
+
mutation.headers = headers;
|
|
2087
|
+
return mutation;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
1962
2090
|
/**
|
|
1963
2091
|
* Generated bundle index. Do not edit.
|
|
1964
2092
|
*/
|
|
1965
2093
|
|
|
1966
|
-
export { capitalize, concatOp, createEffects, createPageArray, createReducer, deriveCallStateKeys, emptyFeature, exhaustOp, firstPage, getCallStateKeys, getCollectionArray, getDataServiceKeys, getUndoRedoKeys, gotoPage, 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, withSessionStorage, withStorageSync, withUndoRedo };
|
|
2094
|
+
export { capitalize, concatOp, createEffects, createPageArray, createReducer, deriveCallStateKeys, emptyFeature, exhaustOp, firstPage, getCallStateKeys, getCollectionArray, getDataServiceKeys, getUndoRedoKeys, gotoPage, httpMutation, 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, withSessionStorage, withStorageSync, withUndoRedo };
|
|
1967
2095
|
//# sourceMappingURL=angular-architects-ngrx-toolkit.mjs.map
|