@mmstack/resource 21.1.1 → 21.1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmstack/resource",
3
- "version": "21.1.1",
3
+ "version": "21.1.2",
4
4
  "keywords": [
5
5
  "angular",
6
6
  "signals",
@@ -37,5 +37,6 @@
37
37
  "types": "./types/mmstack-resource.d.ts",
38
38
  "default": "./fesm2022/mmstack-resource.mjs"
39
39
  }
40
- }
40
+ },
41
+ "type": "module"
41
42
  }
@@ -142,6 +142,24 @@ declare class Cache<T> {
142
142
  * @param key - The key of the entry to invalidate.
143
143
  */
144
144
  invalidate(key: string): void;
145
+ /**
146
+ * Invalidates every cache entry whose key starts with `prefix`. Common after a
147
+ * list-mutating operation (e.g. invalidate every paginated `GET /api/posts*`
148
+ * after a POST). Returns the number of entries removed.
149
+ *
150
+ * @example
151
+ * cache.invalidatePrefix('GET https://api.example.com/posts');
152
+ */
153
+ invalidatePrefix(prefix: string): number;
154
+ /**
155
+ * Invalidates every cache entry whose key matches the predicate. Use for
156
+ * arbitrary bulk invalidation that doesn't fit prefix matching (e.g.
157
+ * "everything containing `userId=42`"). Returns the number of entries removed.
158
+ *
159
+ * @example
160
+ * cache.invalidateWhere((key) => key.includes('/me/'));
161
+ */
162
+ invalidateWhere(predicate: (key: string) => boolean): number;
145
163
  private invalidateInternal;
146
164
  /** @internal */
147
165
  private cleanup;
@@ -295,6 +313,13 @@ type CircuitBreaker = {
295
313
  * to test if the underlying issue has been resolved after the circuit breaker has been open.
296
314
  */
297
315
  halfOpen: () => void;
316
+ /**
317
+ * Fully resets the breaker state — clears the failure count, drops the half-open
318
+ * flag, and lifts a permanent open caused by `shouldFailForever`. Use after the
319
+ * underlying condition has been resolved (e.g. user re-authenticated after a
320
+ * 401-triggered permanent open).
321
+ */
322
+ hardReset: () => void;
298
323
  /**
299
324
  * Destroys the circuit breaker & initiates related cleanup
300
325
  */
@@ -308,6 +333,10 @@ type CreateCircuitBreakerOptions = {
308
333
  * The number of failures that will cause the circuit breaker to open.
309
334
  * @default 5
310
335
  */
336
+ threshold?: number;
337
+ /**
338
+ * @deprecated Misspelled — use `threshold` instead. Kept for backwards compatibility; will be removed in a future major.
339
+ */
311
340
  treshold?: number;
312
341
  /**
313
342
  * The time in milliseconds after which the circuit breaker will reset and allow operations to proceed again.
@@ -321,6 +350,7 @@ type CreateCircuitBreakerOptions = {
321
350
  shouldFail?: (err?: Error) => boolean;
322
351
  /**
323
352
  * A function that determines whether an error should cause the circuit breaker to be open forever.
353
+ * `hardReset()` is required to lift this state.
324
354
  * @default Always returns false
325
355
  */
326
356
  shouldFailForever?: (err?: Error) => boolean;
@@ -330,16 +360,39 @@ type CreateCircuitBreakerOptions = {
330
360
  * - `false`: Disables circuit breaker functionality (always open).
331
361
  * - true: Creates a new circuit breaker with default options.
332
362
  * - `CircuitBreaker`: Provides an existing `CircuitBreaker` instance to use.
333
- * - `{ treshold?: number; timeout?: number; }`: Creates a new circuit breaker with the specified options.
363
+ * - `{ threshold?: number; timeout?: number; }`: Creates a new circuit breaker with the specified options.
334
364
  */
335
365
  type CircuitBreakerOptions = false | CircuitBreaker | CreateCircuitBreakerOptions;
366
+ /**
367
+ * Provides application-wide default options for {@link createCircuitBreaker}.
368
+ * Any `createCircuitBreaker()` call without explicit options (or with only
369
+ * partial options) merges these defaults in, so you can centralize threshold /
370
+ * timeout / failure-classifier behavior in one place.
371
+ *
372
+ * Per-call options always win over the provided defaults.
373
+ *
374
+ * @example
375
+ * ```ts
376
+ * bootstrapApplication(AppComponent, {
377
+ * providers: [
378
+ * provideCircuitBreakerDefaultOptions({
379
+ * threshold: 10,
380
+ * timeout: 60_000,
381
+ * shouldFailForever: (err) =>
382
+ * err instanceof HttpErrorResponse && [401, 403].includes(err.status),
383
+ * }),
384
+ * ],
385
+ * });
386
+ * ```
387
+ */
336
388
  declare function provideCircuitBreakerDefaultOptions(options: CircuitBreakerOptions): Provider;
337
389
  /**
338
390
  * Creates a circuit breaker instance.
339
391
  *
340
392
  * @param options - Configuration options for the circuit breaker. Can be:
341
- * - `undefined`: Creates a "no-op" circuit breaker that is always open (never trips).
342
- * - `true`: Creates a circuit breaker with default settings (threshold: 5, timeout: 30000ms).
393
+ * - `undefined`: Uses defaults (threshold: 5, timeout: 30000ms) or provided defaults via {@link provideCircuitBreakerDefaultOptions}.
394
+ * - `false`: Creates a "no-op" circuit breaker that is always closed (never trips).
395
+ * - `true`: Creates a circuit breaker with default settings.
343
396
  * - `CircuitBreaker`: Reuses an existing `CircuitBreaker` instance.
344
397
  * - `{ threshold?: number; timeout?: number; }`: Creates a circuit breaker with the specified threshold and timeout.
345
398
  *
@@ -475,10 +528,16 @@ type QueryResourceOptions<TResult, TRaw = TResult> = HttpResourceOptions<TResult
475
528
  */
476
529
  retry?: RetryOptions;
477
530
  /**
478
- * An optional error handler callback. This function will be called whenever the
479
- * underlying HTTP request fails. Useful for displaying toasts or other error messages.
531
+ * Called on every failed attempt, including each retry.
532
+ *
533
+ * @param err - The error from the underlying HTTP request.
534
+ * @param retryCount - The number of retries that already happened before
535
+ * this error (`0` on the original failure, `1` after the first retry, etc.).
536
+ * @param isFinal - `true` when no further retry will be scheduled — either
537
+ * because retries are exhausted or `retry` was unset/0. Branch on this for
538
+ * "user actually needs to know" side effects (toasts, error reporting).
480
539
  */
481
- onError?: (err: unknown) => void;
540
+ onError?: (err: unknown, retryCount: number, isFinal: boolean) => void;
482
541
  /**
483
542
  * Options for configuring a circuit breaker for the resource.
484
543
  */
@@ -493,6 +552,12 @@ type QueryResourceOptions<TResult, TRaw = TResult> = HttpResourceOptions<TResult
493
552
  */
494
553
  triggerOnSameRequest?: boolean;
495
554
  };
555
+ /**
556
+ * The reason a query resource is currently in the `disabled` state, or `null`
557
+ * if it is enabled. Useful for branching UI on cause (e.g. "offline" vs
558
+ * "circuit tripped" vs "nothing to fetch yet").
559
+ */
560
+ type DisabledReason = 'offline' | 'circuit-open' | 'no-request';
496
561
  /**
497
562
  * Represents a resource created by `queryResource`. Extends `HttpResourceRef` with additional properties.
498
563
  */
@@ -506,9 +571,14 @@ type QueryResourceRef<TResult> = Omit<HttpResourceRef<TResult>, 'headers' | 'sta
506
571
  */
507
572
  readonly statusCode: WritableSignal<number | undefined>;
508
573
  /**
509
- * A signal indicating whether the resource is currently disabled (due to circuit breaker or undefined request).
574
+ * A signal indicating whether the resource is currently disabled (due to circuit breaker, offline, or undefined request).
510
575
  */
511
576
  disabled: Signal<boolean>;
577
+ /**
578
+ * Why the resource is currently disabled, or `null` if it is enabled.
579
+ * Maps to one of: `'offline'`, `'circuit-open'`, `'no-request'`.
580
+ */
581
+ disabledReason: Signal<DisabledReason | null>;
512
582
  /**
513
583
  * Prefetches data for the resource, populating the cache if caching is enabled. This can be
514
584
  * used to proactively load data before it's needed. If a slow connection is detected, prefetching is skipped.
@@ -673,4 +743,4 @@ type MutationResourceRef<TResult, TMutation = TResult, TICTX = void> = Omit<Quer
673
743
  declare function mutationResource<TResult, TRaw = TResult, TMutation = TResult, TCTX = void, TICTX = TCTX, TMethod extends HttpResourceRequest['method'] = HttpResourceRequest['method']>(request: (params: TMutation) => Omit<NextRequest<TMethod, TMutation>, 'body'> | undefined | void, options?: MutationResourceOptions<TResult, TRaw, TMutation, TCTX, TICTX>): MutationResourceRef<TResult, TMutation, TICTX>;
674
744
 
675
745
  export { Cache, createCacheInterceptor, createCircuitBreaker, createDedupeRequestsInterceptor, injectQueryCache, manualQueryResource, mutationResource, noDedupe, provideCircuitBreakerDefaultOptions, provideQueryCache, queryResource };
676
- export type { ManualQueryResourceRef, MutationResourceOptions, MutationResourceRef, QueryResourceOptions, QueryResourceRef };
746
+ export type { DisabledReason, ManualQueryResourceRef, MutationResourceOptions, MutationResourceRef, QueryResourceOptions, QueryResourceRef };