ngx-extra 20.0.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/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # ngx-extra
2
+
3
+ Utility functions for Angular applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install ngx-extra
9
+ ```
10
+
11
+ ## API
12
+
13
+ ### `reactiveQueryParam()`
14
+
15
+ Synchronize Angular signals with URL query parameters. Supports compression, serialization, and reactive updates.
16
+
17
+ ### `createSignalChangeNotifier()`
18
+
19
+ Create a signal-based notification system with `notify()` and `listen` methods.
20
+
21
+ ### `debouncedSignal()`
22
+
23
+ Debounce signal updates by a specified time interval.
24
+
25
+ ### `duringDestroy()`
26
+
27
+ Execute a callback when the injection context is destroyed.
28
+
29
+ ### `rxSubscriber()`
30
+
31
+ Subscribe to observables with automatic cleanup on component destruction.
32
+
33
+ ### `throwResourceError()`
34
+
35
+ Throw errors from `HttpResourceRef` when the status is error.
@@ -0,0 +1,253 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, inject, effect, untracked, Injectable, isDevMode, assertInInjectionContext, Injector, runInInjectionContext, DestroyRef, isSignal } from '@angular/core';
3
+ import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
4
+ import { Router, ActivatedRoute } from '@angular/router';
5
+ import LzString from 'lz-string';
6
+ import { map, filter, Observable, debounceTime } from 'rxjs';
7
+
8
+ function createSignalChangeNotifier() {
9
+ const sourceSignal = signal(null, ...(ngDevMode ? [{ debugName: "sourceSignal" }] : []));
10
+ return {
11
+ notify: () => {
12
+ sourceSignal.update((v) => (v === null ? 1 : v + 1));
13
+ },
14
+ listen: sourceSignal.asReadonly()
15
+ };
16
+ }
17
+
18
+ function cleanNullishFromObject(obj) {
19
+ if (obj === undefined) {
20
+ return {};
21
+ }
22
+ return Object.fromEntries(Object.entries(obj).filter(([, v]) => v != null));
23
+ }
24
+ function hasNullishInObject(obj) {
25
+ return Object.values(obj).some((val) => val === null || val === undefined);
26
+ }
27
+
28
+ class ReactiveQueryParamGlobalHandler {
29
+ router = inject(Router);
30
+ schedulerNotifier = createSignalChangeNotifier();
31
+ currentKeys = {};
32
+ navigationExtras = {};
33
+ constructor() {
34
+ effect(() => {
35
+ if (!this.schedulerNotifier.listen()) {
36
+ return;
37
+ }
38
+ untracked(() => {
39
+ this.router
40
+ .navigate([], {
41
+ queryParams: this.currentKeys,
42
+ ...this.navigationExtras
43
+ })
44
+ .then(() => {
45
+ this.currentKeys = {};
46
+ this.navigationExtras = {};
47
+ });
48
+ });
49
+ });
50
+ }
51
+ scheduleNavigation(key, value, navOptions) {
52
+ this.currentKeys[key] = value;
53
+ this.setCurrentNavigationExtras(navOptions);
54
+ this.schedulerNotifier.notify();
55
+ }
56
+ setCurrentNavigationExtras(config = {}) {
57
+ const { queryParamsHandling, onSameUrlNavigation, replaceUrl, skipLocationChange, preserveFragment } = config;
58
+ if (queryParamsHandling || queryParamsHandling === "") {
59
+ this.navigationExtras.queryParamsHandling = queryParamsHandling;
60
+ }
61
+ if (onSameUrlNavigation) {
62
+ this.navigationExtras.onSameUrlNavigation = onSameUrlNavigation;
63
+ }
64
+ if (replaceUrl) {
65
+ this.navigationExtras.replaceUrl = replaceUrl;
66
+ }
67
+ if (skipLocationChange) {
68
+ this.navigationExtras.skipLocationChange = skipLocationChange;
69
+ }
70
+ if (preserveFragment) {
71
+ this.navigationExtras.preserveFragment = preserveFragment;
72
+ }
73
+ }
74
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ReactiveQueryParamGlobalHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
75
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ReactiveQueryParamGlobalHandler, providedIn: "root" });
76
+ }
77
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ReactiveQueryParamGlobalHandler, decorators: [{
78
+ type: Injectable,
79
+ args: [{ providedIn: "root" }]
80
+ }], ctorParameters: () => [] });
81
+ function reactiveQueryParam(options) {
82
+ if (isDevMode() && !options?.injector) {
83
+ assertInInjectionContext(reactiveQueryParam);
84
+ }
85
+ const assertedInjector = options.injector ?? inject(Injector);
86
+ const blackList = options.queryParamOptions?.blackListedValues ?? [null, undefined, ""];
87
+ const useEncoding = !options?.base64EncodingOptions?.disableEncoding;
88
+ const useStringifyOnNoEncoding = !options?.base64EncodingOptions?.disableJsonStringifyWhenNoEncoding;
89
+ const deserialize = (payload) => {
90
+ if (useEncoding) {
91
+ const decoded = LzString.decompressFromEncodedURIComponent(payload);
92
+ return JSON.parse(decoded);
93
+ }
94
+ if (!useEncoding && useStringifyOnNoEncoding) {
95
+ return JSON.parse(payload);
96
+ }
97
+ else {
98
+ try {
99
+ return JSON.parse(payload);
100
+ }
101
+ catch {
102
+ return payload;
103
+ }
104
+ }
105
+ };
106
+ const serialize = (value) => {
107
+ if (blackList.some((elem) => elem === value)) {
108
+ return null;
109
+ }
110
+ if (useEncoding) {
111
+ return LzString.compressToEncodedURIComponent(JSON.stringify(value));
112
+ }
113
+ if (!useEncoding && useStringifyOnNoEncoding) {
114
+ return JSON.stringify(value);
115
+ }
116
+ else {
117
+ if (typeof value === "string") {
118
+ return value;
119
+ }
120
+ else {
121
+ return JSON.stringify(value);
122
+ }
123
+ }
124
+ };
125
+ runInInjectionContext(assertedInjector, () => {
126
+ const globalHandler = inject(ReactiveQueryParamGlobalHandler);
127
+ const route = inject(ActivatedRoute);
128
+ const destroyRef = inject(DestroyRef);
129
+ // Handle initial snapshot
130
+ const payloadFromSnapshot = route.snapshot.queryParamMap.get(options.queryParamKey);
131
+ if (payloadFromSnapshot !== null &&
132
+ payloadFromSnapshot !== "" &&
133
+ options.handleInitialSnapshot) {
134
+ const deserialized = deserialize(payloadFromSnapshot);
135
+ if (!options.parse) {
136
+ options.handleInitialSnapshot(deserialized);
137
+ }
138
+ else {
139
+ try {
140
+ const parsedValue = options.parse(deserialized);
141
+ if (parsedValue !== null) {
142
+ options.handleInitialSnapshot(parsedValue);
143
+ }
144
+ }
145
+ catch (error) {
146
+ console.error(error);
147
+ }
148
+ }
149
+ }
150
+ // Handle query param stream
151
+ route.queryParamMap
152
+ .pipe(map((params) => params.get(options.queryParamKey)), filter((value) => value !== null), filter((value) => value !== ""), takeUntilDestroyed(destroyRef))
153
+ .subscribe((payloadFromStream) => {
154
+ if (!options.handleStream) {
155
+ return;
156
+ }
157
+ const deserialized = deserialize(payloadFromStream);
158
+ if (!options.parse) {
159
+ options.handleStream(deserialized);
160
+ }
161
+ else {
162
+ try {
163
+ const parsedValue = options.parse(deserialized);
164
+ if (parsedValue !== null) {
165
+ options.handleStream(parsedValue);
166
+ }
167
+ }
168
+ catch (error) {
169
+ console.error(error);
170
+ }
171
+ }
172
+ });
173
+ // Handle source changes
174
+ let source$;
175
+ if (isSignal(options.source)) {
176
+ source$ = toObservable(options.source);
177
+ }
178
+ else if (options.source instanceof Observable) {
179
+ source$ = options.source;
180
+ }
181
+ else {
182
+ throw new Error("Invalid source");
183
+ }
184
+ source$.pipe(takeUntilDestroyed(destroyRef)).subscribe((value) => {
185
+ const serializedValue = serialize(value);
186
+ if (serializedValue === null && options?.queryParamOptions?.preserveStaleOnBlacklistedValue) {
187
+ return;
188
+ }
189
+ globalHandler.scheduleNavigation(options.queryParamKey, serializedValue, {
190
+ ...cleanNullishFromObject(options?.routerOptions),
191
+ queryParamsHandling: options.routerOptions?.queryParamsHandling ?? "merge"
192
+ });
193
+ });
194
+ });
195
+ }
196
+
197
+ function debouncedSignal(source, ms, injector) {
198
+ if (isDevMode() && !injector) {
199
+ assertInInjectionContext(debouncedSignal);
200
+ }
201
+ const assertedInjector = injector ?? inject(Injector);
202
+ return runInInjectionContext(assertedInjector, () => {
203
+ if (isSignal(source)) {
204
+ return toSignal(toObservable(source).pipe(debounceTime(ms), takeUntilDestroyed()));
205
+ }
206
+ else {
207
+ throw new Error("Invalid source");
208
+ }
209
+ });
210
+ }
211
+
212
+ function duringDestroy(fn, injector) {
213
+ if (isDevMode() && !injector) {
214
+ assertInInjectionContext(duringDestroy);
215
+ }
216
+ const assertedInjector = injector ?? inject(Injector);
217
+ runInInjectionContext(assertedInjector, () => {
218
+ inject(DestroyRef).onDestroy(fn);
219
+ });
220
+ }
221
+
222
+ function rxSubscriber(source, next, options) {
223
+ if (isDevMode() && !options?.injector) {
224
+ assertInInjectionContext(rxSubscriber);
225
+ }
226
+ const assertedInjector = options?.injector ?? inject(Injector);
227
+ runInInjectionContext(assertedInjector, () => {
228
+ source.pipe(takeUntilDestroyed()).subscribe((payloadFromStream) => {
229
+ next(payloadFromStream);
230
+ });
231
+ });
232
+ }
233
+
234
+ function throwResourceError(resorce, injector) {
235
+ if (isDevMode() && !injector) {
236
+ assertInInjectionContext(throwResourceError);
237
+ }
238
+ const assertedInjector = injector ?? inject(Injector);
239
+ runInInjectionContext(assertedInjector, () => {
240
+ effect(() => {
241
+ if (resorce.status() === "error") {
242
+ throw resorce.error();
243
+ }
244
+ });
245
+ });
246
+ }
247
+
248
+ /**
249
+ * Generated bundle index. Do not edit.
250
+ */
251
+
252
+ export { createSignalChangeNotifier, debouncedSignal, duringDestroy, reactiveQueryParam, rxSubscriber, throwResourceError };
253
+ //# sourceMappingURL=ngx-extra.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-extra.mjs","sources":["../../../projects/ngx-extra/src/lib/create-signal-change-notifier.ts","../../../projects/ngx-extra/src/lib/helpers.ts","../../../projects/ngx-extra/src/lib/reactive-query-param.ts","../../../projects/ngx-extra/src/lib/debounced-signal.ts","../../../projects/ngx-extra/src/lib/during-destroy.ts","../../../projects/ngx-extra/src/lib/rx-subscriber.ts","../../../projects/ngx-extra/src/lib/throw-resource-error.ts","../../../projects/ngx-extra/src/ngx-extra.ts"],"sourcesContent":["import { signal } from \"@angular/core\";\n\nexport function createSignalChangeNotifier() {\n const sourceSignal = signal<number | null>(null);\n\n return {\n notify: () => {\n sourceSignal.update((v) => (v === null ? 1 : v + 1));\n },\n listen: sourceSignal.asReadonly()\n };\n}\n","export function cleanNullishFromObject(obj?: object): Record<string, any> {\n if (obj === undefined) {\n return {};\n }\n\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v != null));\n}\n\nexport function hasNullishInObject(obj: object): boolean {\n return Object.values(obj).some((val) => val === null || val === undefined);\n}\n","import {\n DestroyRef,\n Injectable,\n Injector,\n Signal,\n assertInInjectionContext,\n effect,\n inject,\n isDevMode,\n isSignal,\n runInInjectionContext,\n untracked\n} from \"@angular/core\";\nimport { takeUntilDestroyed, toObservable } from \"@angular/core/rxjs-interop\";\nimport { ActivatedRoute, NavigationExtras, Router } from \"@angular/router\";\nimport LzString from \"lz-string\";\nimport { Observable, filter, map } from \"rxjs\";\nimport { createSignalChangeNotifier } from \"./create-signal-change-notifier\";\nimport { cleanNullishFromObject } from \"./helpers\";\n\nexport type SlimNavigationExtras = Pick<\n NavigationExtras,\n | \"queryParamsHandling\"\n | \"onSameUrlNavigation\"\n | \"replaceUrl\"\n | \"skipLocationChange\"\n | \"preserveFragment\"\n>;\n\nexport type ReactiveQueryParamOptions<T> = {\n queryParamKey: string;\n source: Signal<T> | Observable<T>;\n parse?: (rawData: any) => T | null;\n handleInitialSnapshot?: (payload: T) => void;\n handleStream?: (payload: T) => void;\n injector?: Injector;\n routerOptions?: SlimNavigationExtras;\n base64EncodingOptions?: {\n disableEncoding?: boolean;\n disableJsonStringifyWhenNoEncoding?: boolean;\n };\n queryParamOptions?: {\n blackListedValues?: any[];\n preserveStaleOnBlacklistedValue?: boolean;\n };\n};\n\n@Injectable({ providedIn: \"root\" })\nclass ReactiveQueryParamGlobalHandler {\n private router = inject(Router);\n\n private schedulerNotifier = createSignalChangeNotifier();\n private currentKeys: Record<string, string | null> = {};\n private navigationExtras: SlimNavigationExtras = {};\n\n constructor() {\n effect(() => {\n if (!this.schedulerNotifier.listen()) {\n return;\n }\n untracked(() => {\n this.router\n .navigate([], {\n queryParams: this.currentKeys,\n ...this.navigationExtras\n })\n .then(() => {\n this.currentKeys = {};\n this.navigationExtras = {};\n });\n });\n });\n }\n\n scheduleNavigation(key: string, value: string | null, navOptions: SlimNavigationExtras) {\n this.currentKeys[key] = value;\n this.setCurrentNavigationExtras(navOptions);\n this.schedulerNotifier.notify();\n }\n\n private setCurrentNavigationExtras(config: Partial<SlimNavigationExtras> = {}) {\n const {\n queryParamsHandling,\n onSameUrlNavigation,\n replaceUrl,\n skipLocationChange,\n preserveFragment\n } = config;\n\n if (queryParamsHandling || queryParamsHandling === \"\") {\n this.navigationExtras.queryParamsHandling = queryParamsHandling;\n }\n if (onSameUrlNavigation) {\n this.navigationExtras.onSameUrlNavigation = onSameUrlNavigation;\n }\n if (replaceUrl) {\n this.navigationExtras.replaceUrl = replaceUrl;\n }\n if (skipLocationChange) {\n this.navigationExtras.skipLocationChange = skipLocationChange;\n }\n if (preserveFragment) {\n this.navigationExtras.preserveFragment = preserveFragment;\n }\n }\n}\n\nexport function reactiveQueryParam<T>(options: ReactiveQueryParamOptions<T>) {\n if (isDevMode() && !options?.injector) {\n assertInInjectionContext(reactiveQueryParam);\n }\n\n const assertedInjector = options.injector ?? inject(Injector);\n\n const blackList = options.queryParamOptions?.blackListedValues ?? [null, undefined, \"\"];\n\n const useEncoding = !options?.base64EncodingOptions?.disableEncoding;\n\n const useStringifyOnNoEncoding =\n !options?.base64EncodingOptions?.disableJsonStringifyWhenNoEncoding;\n\n const deserialize = (payload: string): T => {\n if (useEncoding) {\n const decoded = LzString.decompressFromEncodedURIComponent(payload);\n return JSON.parse(decoded);\n }\n\n if (!useEncoding && useStringifyOnNoEncoding) {\n return JSON.parse(payload);\n } else {\n try {\n return JSON.parse(payload);\n } catch {\n return payload as T;\n }\n }\n };\n\n const serialize = (value: T | null | undefined): string | null => {\n if (blackList.some((elem) => elem === value)) {\n return null;\n }\n if (useEncoding) {\n return LzString.compressToEncodedURIComponent(JSON.stringify(value));\n }\n\n if (!useEncoding && useStringifyOnNoEncoding) {\n return JSON.stringify(value);\n } else {\n if (typeof value === \"string\") {\n return value;\n } else {\n return JSON.stringify(value);\n }\n }\n };\n\n runInInjectionContext(assertedInjector, () => {\n const globalHandler = inject(ReactiveQueryParamGlobalHandler);\n const route = inject(ActivatedRoute);\n const destroyRef = inject(DestroyRef);\n\n // Handle initial snapshot\n const payloadFromSnapshot = route.snapshot.queryParamMap.get(options.queryParamKey);\n\n if (\n payloadFromSnapshot !== null &&\n payloadFromSnapshot !== \"\" &&\n options.handleInitialSnapshot\n ) {\n const deserialized = deserialize(payloadFromSnapshot);\n if (!options.parse) {\n options.handleInitialSnapshot(deserialized);\n } else {\n try {\n const parsedValue = options.parse(deserialized);\n if (parsedValue !== null) {\n options.handleInitialSnapshot(parsedValue);\n }\n } catch (error) {\n console.error(error);\n }\n }\n }\n\n // Handle query param stream\n route.queryParamMap\n .pipe(\n map((params) => params.get(options.queryParamKey)),\n filter((value) => value !== null),\n filter((value) => value !== \"\"),\n takeUntilDestroyed(destroyRef)\n )\n .subscribe((payloadFromStream) => {\n if (!options.handleStream) {\n return;\n }\n const deserialized = deserialize(payloadFromStream);\n if (!options.parse) {\n options.handleStream(deserialized);\n } else {\n try {\n const parsedValue = options.parse(deserialized);\n if (parsedValue !== null) {\n options.handleStream(parsedValue);\n }\n } catch (error) {\n console.error(error);\n }\n }\n });\n\n // Handle source changes\n let source$: Observable<T>;\n\n if (isSignal(options.source)) {\n source$ = toObservable(options.source);\n } else if (options.source instanceof Observable) {\n source$ = options.source;\n } else {\n throw new Error(\"Invalid source\");\n }\n\n source$.pipe(takeUntilDestroyed(destroyRef)).subscribe((value) => {\n const serializedValue = serialize(value);\n if (serializedValue === null && options?.queryParamOptions?.preserveStaleOnBlacklistedValue) {\n return;\n }\n\n globalHandler.scheduleNavigation(options.queryParamKey, serializedValue, {\n ...cleanNullishFromObject(options?.routerOptions),\n queryParamsHandling: options.routerOptions?.queryParamsHandling ?? \"merge\"\n });\n });\n });\n}\n","import {\n Signal,\n Injector,\n isDevMode,\n assertInInjectionContext,\n inject,\n runInInjectionContext,\n isSignal\n} from \"@angular/core\";\nimport { toSignal, toObservable, takeUntilDestroyed } from \"@angular/core/rxjs-interop\";\nimport { debounceTime } from \"rxjs\";\n\nexport function debouncedSignal<T>(source: Signal<T>, ms: number, injector?: Injector) {\n if (isDevMode() && !injector) {\n assertInInjectionContext(debouncedSignal);\n }\n const assertedInjector = injector ?? inject(Injector);\n\n return runInInjectionContext(assertedInjector, () => {\n if (isSignal(source)) {\n return toSignal(toObservable(source).pipe(debounceTime(ms), takeUntilDestroyed()));\n } else {\n throw new Error(\"Invalid source\");\n }\n });\n}\n","import {\n Injector,\n isDevMode,\n assertInInjectionContext,\n inject,\n runInInjectionContext,\n DestroyRef\n} from \"@angular/core\";\n\nexport function duringDestroy(fn: () => void, injector?: Injector) {\n if (isDevMode() && !injector) {\n assertInInjectionContext(duringDestroy);\n }\n const assertedInjector = injector ?? inject(Injector);\n\n runInInjectionContext(assertedInjector, () => {\n inject(DestroyRef).onDestroy(fn);\n });\n}\n","import {\n assertInInjectionContext,\n inject,\n Injector,\n isDevMode,\n runInInjectionContext\n} from \"@angular/core\";\nimport { takeUntilDestroyed } from \"@angular/core/rxjs-interop\";\nimport { Observable } from \"rxjs\";\n\nexport type RxSubscriberOptions = {\n injector?: Injector;\n};\n\nexport function rxSubscriber<T>(\n source: Observable<T>,\n next: (payload: T) => void,\n options?: RxSubscriberOptions\n) {\n if (isDevMode() && !options?.injector) {\n assertInInjectionContext(rxSubscriber);\n }\n const assertedInjector = options?.injector ?? inject(Injector);\n\n runInInjectionContext(assertedInjector, () => {\n source.pipe(takeUntilDestroyed()).subscribe((payloadFromStream) => {\n next(payloadFromStream);\n });\n });\n}\n","import { HttpResourceRef } from \"@angular/common/http\";\nimport {\n Injector,\n assertInInjectionContext,\n inject,\n runInInjectionContext,\n effect,\n isDevMode\n} from \"@angular/core\";\n\nexport function throwResourceError<T = any>(resorce: HttpResourceRef<T>, injector?: Injector) {\n if (isDevMode() && !injector) {\n assertInInjectionContext(throwResourceError);\n }\n const assertedInjector = injector ?? inject(Injector);\n runInInjectionContext(assertedInjector, () => {\n effect(() => {\n if (resorce.status() === \"error\") {\n throw resorce.error();\n }\n });\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/index.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { Signal, Injector } from '@angular/core';
3
+ import { NavigationExtras } from '@angular/router';
4
+ import { Observable } from 'rxjs';
5
+ import { HttpResourceRef } from '@angular/common/http';
6
+
7
+ type SlimNavigationExtras = Pick<NavigationExtras, "queryParamsHandling" | "onSameUrlNavigation" | "replaceUrl" | "skipLocationChange" | "preserveFragment">;
8
+ type ReactiveQueryParamOptions<T> = {
9
+ queryParamKey: string;
10
+ source: Signal<T> | Observable<T>;
11
+ parse?: (rawData: any) => T | null;
12
+ handleInitialSnapshot?: (payload: T) => void;
13
+ handleStream?: (payload: T) => void;
14
+ injector?: Injector;
15
+ routerOptions?: SlimNavigationExtras;
16
+ base64EncodingOptions?: {
17
+ disableEncoding?: boolean;
18
+ disableJsonStringifyWhenNoEncoding?: boolean;
19
+ };
20
+ queryParamOptions?: {
21
+ blackListedValues?: any[];
22
+ preserveStaleOnBlacklistedValue?: boolean;
23
+ };
24
+ };
25
+ declare function reactiveQueryParam<T>(options: ReactiveQueryParamOptions<T>): void;
26
+
27
+ declare function createSignalChangeNotifier(): {
28
+ notify: () => void;
29
+ listen: _angular_core.Signal<number | null>;
30
+ };
31
+
32
+ declare function debouncedSignal<T>(source: Signal<T>, ms: number, injector?: Injector): Signal<T | undefined>;
33
+
34
+ declare function duringDestroy(fn: () => void, injector?: Injector): void;
35
+
36
+ type RxSubscriberOptions = {
37
+ injector?: Injector;
38
+ };
39
+ declare function rxSubscriber<T>(source: Observable<T>, next: (payload: T) => void, options?: RxSubscriberOptions): void;
40
+
41
+ declare function throwResourceError<T = any>(resorce: HttpResourceRef<T>, injector?: Injector): void;
42
+
43
+ export { createSignalChangeNotifier, debouncedSignal, duringDestroy, reactiveQueryParam, rxSubscriber, throwResourceError };
44
+ export type { ReactiveQueryParamOptions, RxSubscriberOptions, SlimNavigationExtras };
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "ngx-extra",
3
+ "version": "20.0.1",
4
+ "peerDependencies": {
5
+ "@angular/common": "^20.3.12",
6
+ "@angular/core": "^20.3.0",
7
+ "lz-string": "^1.5.0"
8
+ },
9
+ "dependencies": {
10
+ "tslib": "^2.8.1"
11
+ },
12
+ "sideEffects": false,
13
+ "module": "fesm2022/ngx-extra.mjs",
14
+ "typings": "index.d.ts",
15
+ "exports": {
16
+ "./package.json": {
17
+ "default": "./package.json"
18
+ },
19
+ ".": {
20
+ "types": "./index.d.ts",
21
+ "default": "./fesm2022/ngx-extra.mjs"
22
+ }
23
+ }
24
+ }