ngx-signal-plus 2.6.0 → 2.8.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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Angular 16-21](https://img.shields.io/badge/Angular-16--21-dd0031)](https://angular.dev/)
4
4
  [![npm version](https://img.shields.io/npm/v/ngx-signal-plus.svg)](https://www.npmjs.com/package/ngx-signal-plus)
5
- ![Coverage](https://img.shields.io/badge/coverage-90.44%25-brightgreen)
5
+ ![Coverage](https://img.shields.io/badge/coverage-91.04%25-brightgreen)
6
6
 
7
7
  Bring validation, persistence, undo/redo, and reactive queries to Angular Signals on Angular 16+.
8
8
 
@@ -70,10 +70,10 @@ export class CounterComponent {
70
70
  - Signal creation: `sp`, `spCounter`, `spToggle`, `spForm`, `spComputed`
71
71
  - Signal enhancement: `enhance`
72
72
  - Operators: `spMap`, `spFilter`, `spDebounceTime`, `spThrottleTime`, `spDelay`, `spDistinctUntilChanged`
73
- - Developer experience: `spCombine`, `spAll`, `spAny`, `spEffect`, `spDebug`, `sp().debug(label)`
73
+ - Developer experience: `spCombine`, `spAll`, `spAny`, `spEffect`, `spDebug`, `spMonitor`, `sp().debug(label)`, `sp().monitor(options)`
74
74
  - Forms and groups: `spForm`, `spFormGroup`
75
75
  - Async helpers: `spAsync`, `spCollection`
76
- - Reactive queries: `spQuery`, `spMutation`, `QueryClient`, `setGlobalQueryClient`
76
+ - Reactive queries: `spQuery`, `createDependentQuery`, `spInfiniteQuery`, `spMutation`, `QueryClient`, `setGlobalQueryClient`, `getGlobalQueryClient`
77
77
  - Transactions: `spTransaction`, `spBatch`
78
78
  - Schema validation: `spSchema`, `spSchemaValidator`
79
79
  - Middleware: `spUseMiddleware`, `spRemoveMiddleware`, `spLoggerMiddleware`, `spAnalyticsMiddleware`
@@ -82,6 +82,8 @@ export class CounterComponent {
82
82
 
83
83
  - `spComputed()` now exposes a read-only surface via `ReadonlySignalPlus<T>`.
84
84
  - `SignalPlus<T>` now includes `errors: Signal<string[]>` for consistent validation error access.
85
+ - Builder monitoring is available via `sp().monitor(options)` and records updates through `spMonitor`.
86
+ - Registered middleware now runs in normal `set`/`setValue`/`update` runtime paths for built signals.
85
87
 
86
88
  ## Comparisons
87
89
 
@@ -118,3 +120,8 @@ export class CounterComponent {
118
120
  ## License
119
121
 
120
122
  MIT
123
+
124
+
125
+
126
+
127
+
@@ -264,7 +264,7 @@ function safeAddEventListener(event, handler) {
264
264
  }
265
265
 
266
266
  const states = new Map();
267
- let globalEnabled = true;
267
+ let globalEnabled$1 = true;
268
268
  const ensureState = (name) => {
269
269
  const existing = states.get(name);
270
270
  if (existing) {
@@ -291,7 +291,7 @@ const spDebug = {
291
291
  recordUpdate(name, value) {
292
292
  const state = ensureState(name);
293
293
  state.lastValue = value;
294
- if (!globalEnabled || !state.enabled) {
294
+ if (!globalEnabled$1 || !state.enabled) {
295
295
  return;
296
296
  }
297
297
  state.updates += 1;
@@ -304,10 +304,10 @@ const spDebug = {
304
304
  ensureState(name).enabled = false;
305
305
  },
306
306
  enableAll() {
307
- globalEnabled = true;
307
+ globalEnabled$1 = true;
308
308
  },
309
309
  disableAll() {
310
- globalEnabled = false;
310
+ globalEnabled$1 = false;
311
311
  },
312
312
  getActiveSignals() {
313
313
  return Array.from(states.values())
@@ -319,10 +319,142 @@ const spDebug = {
319
319
  },
320
320
  clear() {
321
321
  states.clear();
322
+ globalEnabled$1 = true;
323
+ },
324
+ };
325
+
326
+ const metrics = new Map();
327
+ let globalEnabled = true;
328
+ const ensureMetric = (name) => {
329
+ const existing = metrics.get(name);
330
+ if (existing) {
331
+ return existing;
332
+ }
333
+ const created = {
334
+ name,
335
+ updates: 0,
336
+ enabled: true,
337
+ totalDurationMs: 0,
338
+ averageDurationMs: 0,
339
+ maxDurationMs: 0,
340
+ lastDurationMs: 0,
341
+ lastUpdated: null,
342
+ };
343
+ metrics.set(name, created);
344
+ return created;
345
+ };
346
+ const spMonitor = {
347
+ trackSignal(name) {
348
+ ensureMetric(name);
349
+ },
350
+ recordUpdate(name, durationMs = 0) {
351
+ const metric = ensureMetric(name);
352
+ if (!globalEnabled || !metric.enabled) {
353
+ return;
354
+ }
355
+ metric.updates += 1;
356
+ metric.lastDurationMs = durationMs;
357
+ metric.totalDurationMs += durationMs;
358
+ metric.averageDurationMs = metric.totalDurationMs / metric.updates;
359
+ metric.maxDurationMs = Math.max(metric.maxDurationMs, durationMs);
360
+ metric.lastUpdated = Date.now();
361
+ },
362
+ enable(name) {
363
+ ensureMetric(name).enabled = true;
364
+ },
365
+ disable(name) {
366
+ ensureMetric(name).enabled = false;
367
+ },
368
+ enableAll() {
369
+ globalEnabled = true;
370
+ },
371
+ disableAll() {
372
+ globalEnabled = false;
373
+ },
374
+ getHotSignals(limit = 10) {
375
+ return Array.from(metrics.values())
376
+ .filter((metric) => metric.enabled)
377
+ .sort((a, b) => b.updates - a.updates)
378
+ .slice(0, limit)
379
+ .map((metric) => ({ ...metric }));
380
+ },
381
+ getSlowSignals(thresholdMs = 16) {
382
+ return Array.from(metrics.values())
383
+ .filter((metric) => metric.enabled && metric.averageDurationMs >= thresholdMs)
384
+ .sort((a, b) => b.averageDurationMs - a.averageDurationMs)
385
+ .map((metric) => ({ ...metric }));
386
+ },
387
+ exportMetrics(format = 'object') {
388
+ const exported = Array.from(metrics.values()).map((metric) => ({ ...metric }));
389
+ return format === 'json' ? JSON.stringify(exported) : exported;
390
+ },
391
+ clear() {
392
+ metrics.clear();
322
393
  globalEnabled = true;
323
394
  },
324
395
  };
325
396
 
397
+ /**
398
+ * Middleware system for intercepting signal operations.
399
+ */
400
+ const middlewareRegistry = [];
401
+ function spUseMiddleware(middleware) {
402
+ if (!middlewareRegistry.some((m) => m.name === middleware.name)) {
403
+ middlewareRegistry.push(middleware);
404
+ }
405
+ }
406
+ function spRemoveMiddleware(name) {
407
+ const index = middlewareRegistry.findIndex((m) => m.name === name);
408
+ if (index === -1)
409
+ return false;
410
+ middlewareRegistry.splice(index, 1);
411
+ return true;
412
+ }
413
+ function spClearMiddleware() {
414
+ middlewareRegistry.length = 0;
415
+ }
416
+ function spGetMiddlewareCount() {
417
+ return middlewareRegistry.length;
418
+ }
419
+ function spRunMiddleware(context) {
420
+ for (const m of middlewareRegistry) {
421
+ try {
422
+ m.onSet?.(context);
423
+ }
424
+ catch {
425
+ /* ignore */
426
+ }
427
+ }
428
+ }
429
+ function spRunMiddlewareError(error, context) {
430
+ for (const m of middlewareRegistry) {
431
+ try {
432
+ m.onError?.(error, context);
433
+ }
434
+ catch {
435
+ /* ignore */
436
+ }
437
+ }
438
+ }
439
+ function spLoggerMiddleware(prefix = '[Signal]') {
440
+ return {
441
+ name: 'sp-logger',
442
+ onSet: (ctx) => console.log(`${prefix} ${ctx.signalName || 'signal'}: ${JSON.stringify(ctx.oldValue)} -> ${JSON.stringify(ctx.newValue)}`),
443
+ onError: (error, ctx) => console.error(`${prefix} Error in ${ctx.signalName || 'signal'}:`, error.message),
444
+ };
445
+ }
446
+ function spAnalyticsMiddleware(tracker) {
447
+ return {
448
+ name: 'sp-analytics',
449
+ onSet: (ctx) => tracker({
450
+ name: ctx.signalName || 'unknown',
451
+ oldValue: ctx.oldValue,
452
+ newValue: ctx.newValue,
453
+ timestamp: ctx.timestamp,
454
+ }),
455
+ };
456
+ }
457
+
326
458
  /**
327
459
  * @fileoverview Builder class for creating enhanced Angular signals
328
460
  * Provides a fluent API for configuring signals with features like:
@@ -345,6 +477,7 @@ const spDebug = {
345
477
  */
346
478
  class SignalBuilder {
347
479
  options;
480
+ static monitorCounter = 0;
348
481
  /**
349
482
  * Creates a new SignalBuilder instance
350
483
  * @param initialValue Initial value for the signal
@@ -448,6 +581,10 @@ class SignalBuilder {
448
581
  this.options.debugLabel = label;
449
582
  return this;
450
583
  }
584
+ monitor(options = {}) {
585
+ this.options.monitorOptions = { ...options };
586
+ return this;
587
+ }
451
588
  /**
452
589
  * Transforms signal value to a different type
453
590
  * @param fn Transform function from T to R
@@ -479,6 +616,9 @@ class SignalBuilder {
479
616
  newBuilder.options.storageKey = this.options.storageKey;
480
617
  newBuilder.options.debounceTime = this.options.debounceTime;
481
618
  newBuilder.options.autoCleanup = this.options.autoCleanup;
619
+ newBuilder.options.monitorOptions = this.options.monitorOptions
620
+ ? { ...this.options.monitorOptions }
621
+ : undefined;
482
622
  return newBuilder;
483
623
  }
484
624
  /**
@@ -549,6 +689,20 @@ class SignalBuilder {
549
689
  const asyncErrorsSignal = signal([], ...(ngDevMode ? [{ debugName: "asyncErrorsSignal" }] : []));
550
690
  const enforceHistorySize = (histArray) => this.limitByHistorySize(histArray, this.options.historySize);
551
691
  const enforceRedoStackSize = (redoArray) => this.limitByHistorySize(redoArray, this.options.historySize);
692
+ const monitorOptions = this.options.monitorOptions;
693
+ const monitorEnabled = Boolean(monitorOptions &&
694
+ ((monitorOptions.trackUpdates ?? true) || monitorOptions.trackPerformance));
695
+ const trackPerformance = Boolean(monitorOptions?.trackPerformance);
696
+ const signalName = monitorOptions?.label ||
697
+ this.options.debugLabel ||
698
+ this.options.storageKey ||
699
+ `signal-${SignalBuilder.monitorCounter++}`;
700
+ const createMiddlewareContext = (oldValue, newValue) => ({
701
+ signalName,
702
+ oldValue,
703
+ newValue,
704
+ timestamp: Date.now(),
705
+ });
552
706
  /**
553
707
  * Helper function to run async validation with debouncing and cancellation
554
708
  * @param value The value to validate
@@ -803,21 +957,20 @@ class SignalBuilder {
803
957
  }
804
958
  // Only update if value has changed
805
959
  if (hasChanged) {
806
- previousValue = conditionalClone(writable());
960
+ const oldValue = conditionalClone(writable());
961
+ spRunMiddleware(createMiddlewareContext(oldValue, conditionalClone(transformedValue)));
962
+ const monitorStart = monitorEnabled && trackPerformance ? performance.now() : 0;
963
+ previousValue = oldValue;
807
964
  writable.set(transformedValue);
808
- // Update history if enabled and value has changed
809
965
  if (this.options.enableHistory && !isProcessingDebounce) {
810
- // Clear redo stack when new value is set
811
966
  redoStack = [];
812
967
  const currentHistory = history();
813
968
  const newHistory = [
814
969
  ...currentHistory,
815
970
  conditionalClone(transformedValue),
816
971
  ];
817
- // Enforce history size limit using helper function
818
972
  history.set(enforceHistorySize(newHistory));
819
973
  }
820
- // Handle storage
821
974
  if (this.options.storageKey && isBrowser()) {
822
975
  try {
823
976
  isProcessingStorage = true;
@@ -835,7 +988,10 @@ class SignalBuilder {
835
988
  isProcessingStorage = false;
836
989
  }
837
990
  }
838
- // Only notify subscribers if not cleaned up
991
+ if (monitorEnabled) {
992
+ const duration = trackPerformance ? performance.now() - monitorStart : 0;
993
+ spMonitor.recordUpdate(signalName, duration);
994
+ }
839
995
  if (!isCleanedUp) {
840
996
  notifySubscribers(transformedValue);
841
997
  }
@@ -851,6 +1007,9 @@ class SignalBuilder {
851
1007
  if (this.options.debugLabel) {
852
1008
  spDebug.trackSignal(this.options.debugLabel, writable());
853
1009
  }
1010
+ if (monitorEnabled) {
1011
+ spMonitor.trackSignal(signalName);
1012
+ }
854
1013
  const processValue = (value) => {
855
1014
  // Prevent setValue after destroy
856
1015
  if (isCleanedUp) {
@@ -896,6 +1055,7 @@ class SignalBuilder {
896
1055
  }
897
1056
  }
898
1057
  catch (error) {
1058
+ spRunMiddlewareError(error, createMiddlewareContext(conditionalClone(writable()), conditionalClone(value)));
899
1059
  this.handleError(error);
900
1060
  throw error;
901
1061
  }
@@ -915,14 +1075,16 @@ class SignalBuilder {
915
1075
  set: processValue,
916
1076
  setValue: processValue,
917
1077
  update: (fn) => {
1078
+ let newValue;
918
1079
  try {
919
- const newValue = fn(writable());
920
- processValue(newValue);
1080
+ newValue = fn(writable());
921
1081
  }
922
1082
  catch (error) {
1083
+ spRunMiddlewareError(error, createMiddlewareContext(conditionalClone(writable()), conditionalClone(writable())));
923
1084
  this.handleError(error);
924
1085
  throw error;
925
1086
  }
1087
+ processValue(newValue);
926
1088
  },
927
1089
  reset: () => {
928
1090
  try {
@@ -4556,67 +4718,6 @@ function spFormGroup(config, options) {
4556
4718
  };
4557
4719
  }
4558
4720
 
4559
- /**
4560
- * Middleware system for intercepting signal operations.
4561
- */
4562
- const middlewareRegistry = [];
4563
- function spUseMiddleware(middleware) {
4564
- if (!middlewareRegistry.some((m) => m.name === middleware.name)) {
4565
- middlewareRegistry.push(middleware);
4566
- }
4567
- }
4568
- function spRemoveMiddleware(name) {
4569
- const index = middlewareRegistry.findIndex((m) => m.name === name);
4570
- if (index === -1)
4571
- return false;
4572
- middlewareRegistry.splice(index, 1);
4573
- return true;
4574
- }
4575
- function spClearMiddleware() {
4576
- middlewareRegistry.length = 0;
4577
- }
4578
- function spGetMiddlewareCount() {
4579
- return middlewareRegistry.length;
4580
- }
4581
- function spRunMiddleware(context) {
4582
- for (const m of middlewareRegistry) {
4583
- try {
4584
- m.onSet?.(context);
4585
- }
4586
- catch {
4587
- /* ignore */
4588
- }
4589
- }
4590
- }
4591
- function spRunMiddlewareError(error, context) {
4592
- for (const m of middlewareRegistry) {
4593
- try {
4594
- m.onError?.(error, context);
4595
- }
4596
- catch {
4597
- /* ignore */
4598
- }
4599
- }
4600
- }
4601
- function spLoggerMiddleware(prefix = '[Signal]') {
4602
- return {
4603
- name: 'sp-logger',
4604
- onSet: (ctx) => console.log(`${prefix} ${ctx.signalName || 'signal'}: ${JSON.stringify(ctx.oldValue)} -> ${JSON.stringify(ctx.newValue)}`),
4605
- onError: (error, ctx) => console.error(`${prefix} Error in ${ctx.signalName || 'signal'}:`, error.message),
4606
- };
4607
- }
4608
- function spAnalyticsMiddleware(tracker) {
4609
- return {
4610
- name: 'sp-analytics',
4611
- onSet: (ctx) => tracker({
4612
- name: ctx.signalName || 'unknown',
4613
- oldValue: ctx.oldValue,
4614
- newValue: ctx.newValue,
4615
- timestamp: ctx.timestamp,
4616
- }),
4617
- };
4618
- }
4619
-
4620
4721
  function extractErrorMessages(error) {
4621
4722
  if (!error) {
4622
4723
  return [];
@@ -5739,6 +5840,7 @@ function spMutation(options) {
5739
5840
  catch {
5740
5841
  // Not in injection context - cleanup will be manual via reset()
5741
5842
  }
5843
+ const queryClient = getGlobalQueryClient();
5742
5844
  const dataSignal = signal(undefined, ...(ngDevMode ? [{ debugName: "dataSignal" }] : []));
5743
5845
  const errorSignal = signal(null, ...(ngDevMode ? [{ debugName: "errorSignal" }] : []));
5744
5846
  const isLoadingSignal = signal(false, ...(ngDevMode ? [{ debugName: "isLoadingSignal" }] : []));
@@ -5782,6 +5884,12 @@ function spMutation(options) {
5782
5884
  const { retry = 0, retryDelay = 10 } = options;
5783
5885
  let attempt = 0;
5784
5886
  let lastError = null;
5887
+ let optimisticPreviousData;
5888
+ const optimistic = options.optimisticUpdate;
5889
+ if (optimistic) {
5890
+ optimisticPreviousData = queryClient.getQueryData(optimistic.queryKey);
5891
+ queryClient.setQueryData(optimistic.queryKey, (oldValue) => optimistic.updater(oldValue, variables));
5892
+ }
5785
5893
  if (options.onMutate) {
5786
5894
  await options.onMutate(variables);
5787
5895
  }
@@ -5801,6 +5909,9 @@ function spMutation(options) {
5801
5909
  if (options.onSettled) {
5802
5910
  options.onSettled(result, null, variables);
5803
5911
  }
5912
+ if (optimistic?.invalidateOnSettled) {
5913
+ queryClient.invalidateQueries(optimistic.queryKey);
5914
+ }
5804
5915
  return result;
5805
5916
  }
5806
5917
  catch (error) {
@@ -5810,6 +5921,9 @@ function spMutation(options) {
5810
5921
  ? retry(attempt, lastError)
5811
5922
  : attempt <= retry;
5812
5923
  if (!shouldRetry) {
5924
+ if (optimistic && optimistic.rollbackOnError !== false) {
5925
+ queryClient.setQueryData(optimistic.queryKey, optimisticPreviousData);
5926
+ }
5813
5927
  updateState({
5814
5928
  error: lastError,
5815
5929
  isLoading: false,
@@ -5823,6 +5937,9 @@ function spMutation(options) {
5823
5937
  if (options.onSettled) {
5824
5938
  options.onSettled(undefined, lastError, variables);
5825
5939
  }
5940
+ if (optimistic?.invalidateOnSettled) {
5941
+ queryClient.invalidateQueries(optimistic.queryKey);
5942
+ }
5826
5943
  throw lastError;
5827
5944
  }
5828
5945
  const delay = typeof retryDelay === 'function'
@@ -6066,6 +6183,18 @@ function createQuery(queryKey, queryFn, options) {
6066
6183
  ...options,
6067
6184
  });
6068
6185
  }
6186
+ function createDependentQuery(queryKey, queryFn, dependencies, options) {
6187
+ const enabled = computed(() => dependencies.every((dependency) => {
6188
+ const value = dependency();
6189
+ return value !== undefined && value !== null && value !== false;
6190
+ }), ...(ngDevMode ? [{ debugName: "enabled" }] : []));
6191
+ return spQuery({
6192
+ queryKey,
6193
+ queryFn,
6194
+ ...options,
6195
+ enabled,
6196
+ });
6197
+ }
6069
6198
 
6070
6199
  /**
6071
6200
  * Reactive Queries Interfaces
@@ -6073,6 +6202,138 @@ function createQuery(queryKey, queryFn, options) {
6073
6202
  * This module exports all interface definitions for reactive queries
6074
6203
  */
6075
6204
 
6205
+ function spInfiniteQuery(options) {
6206
+ const queryClient = getGlobalQueryClient();
6207
+ let destroyRef = null;
6208
+ try {
6209
+ destroyRef = inject(DestroyRef, { optional: true });
6210
+ }
6211
+ catch {
6212
+ // Not in injection context
6213
+ }
6214
+ const queryKey = Array.isArray(options.queryKey)
6215
+ ? options.queryKey
6216
+ : options.queryKey.key;
6217
+ const pagesSignal = signal([], ...(ngDevMode ? [{ debugName: "pagesSignal" }] : []));
6218
+ const errorSignal = signal(null, ...(ngDevMode ? [{ debugName: "errorSignal" }] : []));
6219
+ const isLoadingSignal = signal(false, ...(ngDevMode ? [{ debugName: "isLoadingSignal" }] : []));
6220
+ const isFetchingSignal = signal(false, ...(ngDevMode ? [{ debugName: "isFetchingSignal" }] : []));
6221
+ const isFetchingNextPageSignal = signal(false, ...(ngDevMode ? [{ debugName: "isFetchingNextPageSignal" }] : []));
6222
+ const hasNextPageSignal = signal(true, ...(ngDevMode ? [{ debugName: "hasNextPageSignal" }] : []));
6223
+ const setPages = (pages) => {
6224
+ untracked(() => {
6225
+ pagesSignal.set(pages);
6226
+ const lastPage = pages.length > 0 ? pages[pages.length - 1] : undefined;
6227
+ hasNextPageSignal.set(lastPage !== undefined
6228
+ ? options.getNextPageParam(lastPage, pages) !== undefined
6229
+ : true);
6230
+ });
6231
+ };
6232
+ const runPageFetch = async (pageParam) => {
6233
+ isFetchingSignal.set(true);
6234
+ errorSignal.set(null);
6235
+ try {
6236
+ return await options.queryFn(pageParam);
6237
+ }
6238
+ catch (error) {
6239
+ errorSignal.set(error);
6240
+ throw error;
6241
+ }
6242
+ finally {
6243
+ isFetchingSignal.set(false);
6244
+ }
6245
+ };
6246
+ const refetch = async () => {
6247
+ isLoadingSignal.set(true);
6248
+ try {
6249
+ const firstPage = await runPageFetch(options.initialPageParam);
6250
+ setPages([firstPage]);
6251
+ queryClient.setQueryData(queryKey, [firstPage]);
6252
+ }
6253
+ finally {
6254
+ isLoadingSignal.set(false);
6255
+ }
6256
+ };
6257
+ const fetchNextPage = async () => {
6258
+ const pages = pagesSignal();
6259
+ const lastPage = pages[pages.length - 1];
6260
+ const nextPageParam = pages.length === 0
6261
+ ? options.initialPageParam
6262
+ : options.getNextPageParam(lastPage, pages);
6263
+ if (nextPageParam === undefined) {
6264
+ hasNextPageSignal.set(false);
6265
+ return;
6266
+ }
6267
+ isFetchingNextPageSignal.set(true);
6268
+ try {
6269
+ const page = await runPageFetch(nextPageParam);
6270
+ const nextPages = [...pagesSignal(), page];
6271
+ setPages(nextPages);
6272
+ queryClient.setQueryData(queryKey, nextPages);
6273
+ }
6274
+ finally {
6275
+ isFetchingNextPageSignal.set(false);
6276
+ }
6277
+ };
6278
+ let enabledWatcher = null;
6279
+ let previousEnabledState = false;
6280
+ const getEnabled = () => {
6281
+ if (typeof options.enabled === 'boolean') {
6282
+ return options.enabled;
6283
+ }
6284
+ if (options.enabled) {
6285
+ return options.enabled();
6286
+ }
6287
+ return true;
6288
+ };
6289
+ const runIfEnabled = () => {
6290
+ const enabled = getEnabled();
6291
+ if (!enabled) {
6292
+ previousEnabledState = false;
6293
+ return;
6294
+ }
6295
+ if (previousEnabledState) {
6296
+ return;
6297
+ }
6298
+ previousEnabledState = true;
6299
+ const cached = queryClient.getQueryData(queryKey);
6300
+ if (cached && cached.length > 0) {
6301
+ setPages(cached);
6302
+ return;
6303
+ }
6304
+ refetch().catch(() => undefined);
6305
+ };
6306
+ runIfEnabled();
6307
+ if (typeof options.enabled !== 'boolean' && options.enabled) {
6308
+ enabledWatcher = setInterval(runIfEnabled, 100);
6309
+ }
6310
+ if (destroyRef) {
6311
+ destroyRef.onDestroy(() => {
6312
+ if (enabledWatcher) {
6313
+ clearInterval(enabledWatcher);
6314
+ enabledWatcher = null;
6315
+ }
6316
+ });
6317
+ }
6318
+ return {
6319
+ pages: computed(() => pagesSignal()),
6320
+ error: computed(() => errorSignal()),
6321
+ isLoading: computed(() => isLoadingSignal()),
6322
+ isFetching: computed(() => isFetchingSignal()),
6323
+ isFetchingNextPage: computed(() => isFetchingNextPageSignal()),
6324
+ hasNextPage: computed(() => hasNextPageSignal()),
6325
+ refetch,
6326
+ fetchNextPage,
6327
+ };
6328
+ }
6329
+ function createInfiniteQuery(queryKey, queryFn, options) {
6330
+ return spInfiniteQuery({
6331
+ ...options,
6332
+ queryKey,
6333
+ queryFn,
6334
+ });
6335
+ }
6336
+
6076
6337
  /**
6077
6338
  * Public API Surface of ngx-signal-plus
6078
6339
  *
@@ -6085,5 +6346,5 @@ function createQuery(queryKey, queryFn, options) {
6085
6346
  * Generated bundle index. Do not edit.
6086
6347
  */
6087
6348
 
6088
- export { QueryClient, SP_ERRORS, SpError, createMutation, createQuery, enhance, formatSpError, getGlobalQueryClient, setGlobalQueryClient, sp, spAll, spAnalyticsMiddleware, spAny, spAsync, spBatch, spClearMiddleware, spCollection, spCombine, combineLatest as spCombineLatest, spComputed, spCounter, spCreateError, debounceTime as spDebounceTime, spDebug, delay$1 as spDelay, distinctUntilChanged as spDistinctUntilChanged, spEffect, filter as spFilter, spForm, spFormGroup, spGetMiddlewareCount, spGetModifiedSignals, HistoryManager as spHistoryManager, spIsInBatch, spIsInTransaction, spIsTransactionActive, spLoggerMiddleware, map as spMap, merge as spMerge, spMutation, presets as spPresets, spQuery, spRemoveMiddleware, spSchema, spSchemaValidator, spSchemaWithErrors, SignalBuilder as spSignalBuilder, SignalPlusComponent as spSignalPlusComponent, SignalPlusService as spSignalPlusService, skip as spSkip, StorageManager as spStorageManager, take as spTake, throttleTime as spThrottleTime, spToggle, spTransaction, spUseMiddleware, validators as spValidators };
6349
+ export { QueryClient, SP_ERRORS, SpError, createDependentQuery, createInfiniteQuery, createMutation, createQuery, enhance, formatSpError, getGlobalQueryClient, setGlobalQueryClient, sp, spAll, spAnalyticsMiddleware, spAny, spAsync, spBatch, spClearMiddleware, spCollection, spCombine, combineLatest as spCombineLatest, spComputed, spCounter, spCreateError, debounceTime as spDebounceTime, spDebug, delay$1 as spDelay, distinctUntilChanged as spDistinctUntilChanged, spEffect, filter as spFilter, spForm, spFormGroup, spGetMiddlewareCount, spGetModifiedSignals, HistoryManager as spHistoryManager, spInfiniteQuery, spIsInBatch, spIsInTransaction, spIsTransactionActive, spLoggerMiddleware, map as spMap, merge as spMerge, spMonitor, spMutation, presets as spPresets, spQuery, spRemoveMiddleware, spSchema, spSchemaValidator, spSchemaWithErrors, SignalBuilder as spSignalBuilder, SignalPlusComponent as spSignalPlusComponent, SignalPlusService as spSignalPlusService, skip as spSkip, StorageManager as spStorageManager, take as spTake, throttleTime as spThrottleTime, spToggle, spTransaction, spUseMiddleware, validators as spValidators };
6089
6350
  //# sourceMappingURL=ngx-signal-plus.mjs.map