@ngxs/store 21.0.0 → 22.0.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/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { ModuleWithProviders, Signal, EnvironmentProviders, Type } from '@angular/core';
3
- import { ɵActionOptions as _ActionOptions, StateToken, ɵSharedSelectorOptions as _SharedSelectorOptions, ɵStateClass as _StateClass, ɵStoreOptions as _StoreOptions } from '@ngxs/store/internals';
3
+ import { ɵSharedSelectorOptions as _SharedSelectorOptions, ɵStateClass as _StateClass, ɵActionOptions as _ActionOptions, StateToken, ɵStoreOptions as _StoreOptions, ɵPlainObjectOf as _PlainObjectOf, ɵActionHandlerMetaData as _ActionHandlerMetaData, ɵStateClassInternal as _StateClassInternal } from '@ngxs/store/internals';
4
4
  export { ɵActionOptions as ActionOptions, StateToken } from '@ngxs/store/internals';
5
- import * as rxjs from 'rxjs';
6
5
  import { Observable, Subscription, OperatorFunction } from 'rxjs';
7
6
  import { StateOperator } from '@ngxs/store/operators';
8
7
  export { StateOperator } from '@ngxs/store/operators';
@@ -118,8 +117,17 @@ declare class NgxsFeatureModule {
118
117
  static ɵinj: i0.ɵɵInjectorDeclaration<NgxsFeatureModule>;
119
118
  }
120
119
 
120
+ /**
121
+ * @deprecated Use `provideStore()` and `provideStates()` instead.
122
+ */
121
123
  declare class NgxsModule {
124
+ /**
125
+ * @deprecated Use `provideStore()` instead.
126
+ */
122
127
  static forRoot(states?: _StateClass[], options?: NgxsModuleOptions): ModuleWithProviders<NgxsRootModule>;
128
+ /**
129
+ * @deprecated Use `provideStates()` instead.
130
+ */
123
131
  static forFeature(states?: _StateClass[]): ModuleWithProviders<NgxsFeatureModule>;
124
132
  static ɵfac: i0.ɵɵFactoryDeclaration<NgxsModule, never>;
125
133
  static ɵmod: i0.ɵɵNgModuleDeclaration<NgxsModule, never, never, never>;
@@ -176,10 +184,7 @@ type MappedResult<TSelectorMap> = {
176
184
  };
177
185
  declare function createModelSelector<T extends SelectorMap$1>(selectorMap: T): ModelSelector<T>;
178
186
 
179
- type KeysToValues<T, Keys extends (keyof T)[]> = {
180
- [Index in keyof Keys]: Keys[Index] extends keyof T ? T[Keys[Index]] : never;
181
- };
182
- declare function createPickSelector<TModel, Keys extends (keyof TModel)[]>(selector: TypedSelector<TModel>, keys: [...Keys]): (...props: KeysToValues<TModel, Keys>) => Pick<TModel, Keys[number]>;
187
+ declare function createPickSelector<TModel, Keys extends (keyof TModel)[]>(selector: TypedSelector<TModel>, keys: [...Keys]): (...props: (NonNullable<TModel>[Keys[number]] | undefined)[]) => Pick<TModel, Keys[number]>;
183
188
 
184
189
  type PropertySelectors<TModel> = {
185
190
  [P in keyof NonNullable<TModel>]-?: (model: TModel) => TModel extends null | undefined ? undefined : NonNullable<TModel>[P];
@@ -199,18 +204,13 @@ type SelectorArg = ɵSelectorDef<any>;
199
204
  * @param originalFn The original function being made into a selector
200
205
  * @param creationMetadata
201
206
  */
202
- declare function createSelector<S1 extends SelectorArg, TProjector extends (s1: ɵSelectorReturnType<S1>) => any>(selectors: [S1], projector: TProjector, creationMetadata?: Partial<CreationMetadata>): TProjector;
203
- declare function createSelector<S1 extends SelectorArg, S2 extends SelectorArg, TProjector extends (s1: ɵSelectorReturnType<S1>, s2: ɵSelectorReturnType<S2>) => any>(selectors: [S1, S2], projector: TProjector, creationMetadata?: Partial<CreationMetadata>): TProjector;
204
- declare function createSelector<S1 extends SelectorArg, S2 extends SelectorArg, S3 extends SelectorArg, TProjector extends (s1: ɵSelectorReturnType<S1>, s2: ɵSelectorReturnType<S2>, s3: ɵSelectorReturnType<S3>) => any>(selectors: [S1, S2, S3], projector: TProjector, creationMetadata?: Partial<CreationMetadata>): TProjector;
205
- declare function createSelector<S1 extends SelectorArg, S2 extends SelectorArg, S3 extends SelectorArg, S4 extends SelectorArg, TProjector extends (s1: ɵSelectorReturnType<S1>, s2: ɵSelectorReturnType<S2>, s3: ɵSelectorReturnType<S3>, s4: ɵSelectorReturnType<S4>) => any>(selectors: [S1, S2, S3, S4], projector: TProjector, creationMetadata?: Partial<CreationMetadata>): TProjector;
206
- declare function createSelector<S1 extends SelectorArg, S2 extends SelectorArg, S3 extends SelectorArg, S4 extends SelectorArg, S5 extends SelectorArg, TProjector extends (s1: ɵSelectorReturnType<S1>, s2: ɵSelectorReturnType<S2>, s3: ɵSelectorReturnType<S3>, s4: ɵSelectorReturnType<S4>, s5: ɵSelectorReturnType<S5>) => any>(selectors: [S1, S2, S3, S4, S5], projector: TProjector, creationMetadata?: Partial<CreationMetadata>): TProjector;
207
- declare function createSelector<S1 extends SelectorArg, S2 extends SelectorArg, S3 extends SelectorArg, S4 extends SelectorArg, S5 extends SelectorArg, S6 extends SelectorArg, TProjector extends (s1: ɵSelectorReturnType<S1>, s2: ɵSelectorReturnType<S2>, s3: ɵSelectorReturnType<S3>, s4: ɵSelectorReturnType<S4>, s5: ɵSelectorReturnType<S5>, s6: ɵSelectorReturnType<S6>) => any>(selectors: [S1, S2, S3, S4, S5, S6], projector: TProjector, creationMetadata?: Partial<CreationMetadata>): TProjector;
208
- declare function createSelector<S1 extends SelectorArg, S2 extends SelectorArg, S3 extends SelectorArg, S4 extends SelectorArg, S5 extends SelectorArg, S6 extends SelectorArg, S7 extends SelectorArg, TProjector extends (s1: ɵSelectorReturnType<S1>, s2: ɵSelectorReturnType<S2>, s3: ɵSelectorReturnType<S3>, s4: ɵSelectorReturnType<S4>, s5: ɵSelectorReturnType<S5>, s6: ɵSelectorReturnType<S6>, s7: ɵSelectorReturnType<S7>) => any>(selectors: [S1, S2, S3, S4, S5, S6, S7], projector: TProjector, creationMetadata?: Partial<CreationMetadata>): TProjector;
209
- declare function createSelector<S1 extends SelectorArg, S2 extends SelectorArg, S3 extends SelectorArg, S4 extends SelectorArg, S5 extends SelectorArg, S6 extends SelectorArg, S7 extends SelectorArg, S8 extends SelectorArg, TProjector extends (s1: ɵSelectorReturnType<S1>, s2: ɵSelectorReturnType<S2>, s3: ɵSelectorReturnType<S3>, s4: ɵSelectorReturnType<S4>, s5: ɵSelectorReturnType<S5>, s6: ɵSelectorReturnType<S6>, s7: ɵSelectorReturnType<S7>, s8: ɵSelectorReturnType<S8>) => any>(selectors: [S1, S2, S3, S4, S5, S6, S7, S8], projector: TProjector, creationMetadata?: Partial<CreationMetadata>): TProjector;
210
- declare function createSelector<T extends (...args: any[]) => any>(selectors: SelectorArg[] | undefined, projector: T, creationMetadata?: Partial<CreationMetadata>): T;
207
+ declare function createSelector<Selectors extends SelectorArg[], TProjector extends (...selectorResult: {
208
+ [K in keyof Selectors]: ɵSelectorReturnType<Selectors[K]>;
209
+ }) => any>(selectors: [...Selectors], projector: TProjector, creationMetadata?: Partial<CreationMetadata>): TProjector;
211
210
 
212
211
  type ActionOrArrayOfActions<T> = T extends (infer U)[] ? NonNullable<U>[] : NonNullable<T>;
213
212
  declare class Store {
213
+ private _injector?;
214
214
  private _stateStream;
215
215
  private _internalStateOperations;
216
216
  private _config;
@@ -466,12 +466,21 @@ declare class NgxsUnhandledErrorHandler {
466
466
  }
467
467
 
468
468
  interface NgxsDevelopmentOptions {
469
+ warnOnNewReferenceWithIdenticalValue?: {
470
+ isEqual: (a: unknown, b: unknown) => boolean;
471
+ };
469
472
  warnOnUnhandledActions: true | {
470
473
  ignore: ActionType[];
471
474
  };
472
475
  }
473
476
 
477
+ /**
478
+ * @deprecated Use `withNgxsDevelopmentOptions()` instead.
479
+ */
474
480
  declare class NgxsDevelopmentModule {
481
+ /**
482
+ * @deprecated Use `withNgxsDevelopmentOptions()` instead.
483
+ */
475
484
  static forRoot(options: NgxsDevelopmentOptions): ModuleWithProviders<NgxsDevelopmentModule>;
476
485
  static ɵfac: i0.ɵɵFactoryDeclaration<NgxsDevelopmentModule, never>;
477
486
  static ɵmod: i0.ɵɵNgModuleDeclaration<NgxsDevelopmentModule, never, never, never>;
@@ -516,6 +525,12 @@ declare function withNgxsNoopExecutionStrategy(): i0.EnvironmentProviders;
516
525
  */
517
526
  declare function withNgxsPendingTasks(): i0.EnvironmentProviders;
518
527
 
528
+ declare class StateContextDestroyedError extends Error {
529
+ readonly path: string;
530
+ readonly name = "StateContextDestroyedError";
531
+ constructor(path: string);
532
+ }
533
+
519
534
  /**
520
535
  * This function provides global store providers and initializes the store.
521
536
  *
@@ -609,7 +624,12 @@ declare function withNgxsPreboot(prebootFn: VoidFunction): i0.EnvironmentProvide
609
624
  */
610
625
  declare function select<T>(selector: TypedSelector<T>): Signal<T>;
611
626
 
612
- declare function dispatch<TArgs extends any[]>(ActionType: ActionDef<TArgs>): (...args: TArgs) => rxjs.Observable<void>;
627
+ declare class AsyncReturnType<T> extends Observable<T> implements PromiseLike<void> {
628
+ private dispatchResult$;
629
+ constructor(dispatchResult$: Observable<T>);
630
+ then<TResult1 = void, TResult2 = never>(onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): PromiseLike<TResult1 | TResult2>;
631
+ }
632
+ declare function dispatch<TArgs extends any[]>(ActionType: ActionDef<TArgs>): (...args: TArgs) => AsyncReturnType<void>;
613
633
 
614
634
  type SelectorMap = Record<string, TypedSelector<unknown>>;
615
635
  declare function createSelectMap<T extends SelectorMap>(selectorMap: T): { readonly [K in keyof T]: Signal<ɵSelectorReturnType<T[K]>>; };
@@ -650,7 +670,93 @@ interface DefaultExport<T> {
650
670
  */
651
671
  declare function lazyProvider(factory: () => Promise<EnvironmentProviders | DefaultExport<EnvironmentProviders>>): () => Promise<boolean>;
652
672
 
673
+ /**
674
+ * Dynamically registers an NGXS plugin in the current injection context.
675
+ *
676
+ * This function allows you to register NGXS plugins at runtime, creating an isolated
677
+ * environment injector for the plugin. The plugin is automatically cleaned up when
678
+ * the injection context is destroyed. In development mode, the function validates
679
+ * that the same plugin is not registered multiple times.
680
+ *
681
+ * @param plugin - The NGXS plugin to register. Can be either a class type implementing
682
+ * `NgxsPlugin` or a plugin function (`NgxsPluginFn`).
683
+ *
684
+ * @throws {Error} Throws an error if called outside of an injection context.
685
+ * @throws {Error} In development mode, throws an error if the plugin has already been registered.
686
+ *
687
+ * @remarks
688
+ * - Must be called within an injection context (e.g., constructor, field initializer, or `runInInjectionContext`).
689
+ * - The created environment injector is automatically destroyed when the parent context is destroyed.
690
+ * - Duplicate plugin registration is only checked in development mode for performance reasons.
691
+ *
692
+ * @example
693
+ * ```ts
694
+ * // Register a plugin class
695
+ * import { MyThirdPartyIntegrationPlugin } from './plugins/third-party.plugin';
696
+ *
697
+ * @Component({
698
+ * selector: 'app-root',
699
+ * template: '...'
700
+ * })
701
+ * export class AppComponent {
702
+ * constructor() {
703
+ * registerNgxsPlugin(MyThirdPartyIntegrationPlugin);
704
+ * }
705
+ * }
706
+ * ```
707
+ *
708
+ * @example
709
+ * ```ts
710
+ * // Register a plugin function
711
+ * import { myThirdPartyIntegrationPluginFn } from './plugins/third-party.plugin';
712
+ *
713
+ * @Component({
714
+ * selector: 'app-feature',
715
+ * template: '...'
716
+ * })
717
+ * export class FeatureComponent {
718
+ * constructor() {
719
+ * registerNgxsPlugin(myThirdPartyIntegrationPluginFn);
720
+ * }
721
+ * }
722
+ * ```
723
+ *
724
+ * @example
725
+ * ```ts
726
+ * // Register conditionally based on environment
727
+ * import { MyDevtoolsPlugin } from './plugins/devtools.plugin';
728
+ *
729
+ * @Component({
730
+ * selector: 'app-root',
731
+ * template: '...'
732
+ * })
733
+ * export class AppComponent {
734
+ * constructor() {
735
+ * if (ngDevMode) {
736
+ * registerNgxsPlugin(MyDevtoolsPlugin);
737
+ * }
738
+ * }
739
+ * }
740
+ * ```
741
+ */
742
+ declare function registerNgxsPlugin(plugin: Type<NgxsPlugin> | NgxsPluginFn): void;
743
+
744
+ type StatesByName = _PlainObjectOf<_StateClassInternal>;
745
+ interface MappedStore {
746
+ name: string;
747
+ isInitialised: boolean;
748
+ actions: _PlainObjectOf<_ActionHandlerMetaData[]>;
749
+ defaults: any;
750
+ instance: any;
751
+ path: string;
752
+ }
753
+
653
754
  declare function ɵprovideNgxsInternalStateTokens(): i0.EnvironmentProviders;
755
+ declare function ɵgetTypedNgxsStateFactory(stateFactory: any): {
756
+ states: MappedStore[];
757
+ statesByName: StatesByName;
758
+ statePaths: _PlainObjectOf<string>;
759
+ };
654
760
 
655
- export { Action, ActionDirector, ActionStatus, Actions, NgxsConfig, NgxsDevelopmentModule, NgxsModule, NgxsSimpleChange, NgxsUnhandledActionsLogger, NgxsUnhandledErrorHandler, Select, Selector, SelectorOptions, State, Store, createDispatchMap, createModelSelector, createPickSelector, createPropertySelectors, createSelectMap, createSelector, dispatch, lazyProvider, ofAction, ofActionCanceled, ofActionCompleted, ofActionDispatched, ofActionErrored, ofActionSuccessful, provideStates, provideStore, select, withNgxsDevelopmentOptions, withNgxsNoopExecutionStrategy, withNgxsPendingTasks, withNgxsPlugin, withNgxsPreboot, NgxsFeatureModule as ɵNgxsFeatureModule, NgxsRootModule as ɵNgxsRootModule, ɵprovideNgxsInternalStateTokens };
761
+ export { Action, ActionDirector, ActionStatus, Actions, AsyncReturnType, NgxsConfig, NgxsDevelopmentModule, NgxsModule, NgxsSimpleChange, NgxsUnhandledActionsLogger, NgxsUnhandledErrorHandler, Select, Selector, SelectorOptions, State, StateContextDestroyedError, Store, createDispatchMap, createModelSelector, createPickSelector, createPropertySelectors, createSelectMap, createSelector, dispatch, lazyProvider, ofAction, ofActionCanceled, ofActionCompleted, ofActionDispatched, ofActionErrored, ofActionSuccessful, provideStates, provideStore, registerNgxsPlugin, select, withNgxsDevelopmentOptions, withNgxsNoopExecutionStrategy, withNgxsPendingTasks, withNgxsPlugin, withNgxsPreboot, NgxsFeatureModule as ɵNgxsFeatureModule, NgxsRootModule as ɵNgxsRootModule, ɵgetTypedNgxsStateFactory, ɵprovideNgxsInternalStateTokens };
656
762
  export type { ActionCompletion, ActionContext, ActionDef, ActionMap, ActionType, NgxsAfterBootstrap, NgxsDevelopmentOptions, NgxsModuleOptions, NgxsOnChanges, NgxsOnInit, NgxsUnhandledErrorContext, PropertySelectors, SelectorMap, StateContext, TypedSelector, ɵSelectorDef, ɵSelectorFunc, ɵSelectorReturnType, ɵStateSelector };
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Signal } from '@angular/core';
3
- import { Observable, BehaviorSubject, Subject, MonoTypeOperatorFunction } from 'rxjs';
3
+ import { BehaviorSubject, Subject, MonoTypeOperatorFunction, Observable } from 'rxjs';
4
4
 
5
5
  declare class StateToken<T = void> {
6
6
  private readonly _name;
@@ -127,7 +127,7 @@ declare function ɵgetSelectorMetadata(target: any): ɵSelectorMetaDataModel;
127
127
  *
128
128
  * @ignore
129
129
  */
130
- declare function ɵmemoize<T extends (...args: any[]) => any>(func: T, equalityCheck?: (value1: any, value2: any) => boolean): T;
130
+ declare function ɵmemoize<T extends (...args: any[]) => any>(fn: T, originalFn?: T): T;
131
131
 
132
132
  declare class ɵInitialState {
133
133
  private static _value;
@@ -136,12 +136,7 @@ declare class ɵInitialState {
136
136
  }
137
137
  declare const ɵINITIAL_STATE_TOKEN: InjectionToken<ɵPlainObject>;
138
138
 
139
- declare class ɵNgxsAppBootstrappedState extends BehaviorSubject<boolean> {
140
- constructor();
141
- bootstrap(): void;
142
- static ɵfac: i0.ɵɵFactoryDeclaration<ɵNgxsAppBootstrappedState, never>;
143
- static ɵprov: i0.ɵɵInjectableDeclaration<ɵNgxsAppBootstrappedState>;
144
- }
139
+ declare const ɵNGXS_APP_BOOTSTRAP_STATE: InjectionToken<i0.WritableSignal<boolean>>;
145
140
 
146
141
  declare const ɵNGXS_STATE_FACTORY: InjectionToken<any>;
147
142
  declare const ɵNGXS_STATE_CONTEXT_FACTORY: InjectionToken<any>;
@@ -214,5 +209,5 @@ declare class ɵNgxsActionRegistry {
214
209
  static ɵprov: i0.ɵɵInjectableDeclaration<ɵNgxsActionRegistry>;
215
210
  }
216
211
 
217
- export { StateToken, ɵINITIAL_STATE_TOKEN, ɵInitialState, ɵMETA_KEY, ɵMETA_OPTIONS_KEY, ɵNGXS_STATE_CONTEXT_FACTORY, ɵNGXS_STATE_FACTORY, ɵNgxsActionRegistry, ɵNgxsAppBootstrappedState, ɵOrderedBehaviorSubject, ɵOrderedSubject, ɵSELECTOR_META_KEY, ɵStateStream, ɵdefineProperty, ɵensureSelectorMetadata, ɵensureStoreMetadata, ɵgetSelectorMetadata, ɵgetStoreMetadata, ɵhasOwnProperty, ɵmemoize, ɵwrapObserverCalls };
212
+ export { StateToken, ɵINITIAL_STATE_TOKEN, ɵInitialState, ɵMETA_KEY, ɵMETA_OPTIONS_KEY, ɵNGXS_APP_BOOTSTRAP_STATE, ɵNGXS_STATE_CONTEXT_FACTORY, ɵNGXS_STATE_FACTORY, ɵNgxsActionRegistry, ɵOrderedBehaviorSubject, ɵOrderedSubject, ɵSELECTOR_META_KEY, ɵStateStream, ɵdefineProperty, ɵensureSelectorMetadata, ɵensureStoreMetadata, ɵgetSelectorMetadata, ɵgetStoreMetadata, ɵhasOwnProperty, ɵmemoize, ɵwrapObserverCalls };
218
213
  export type { ɵActionHandlerMetaData, ɵActionOptions, ɵExtractTokenType, ɵMetaDataModel, ɵPlainObject, ɵPlainObjectOf, ɵRuntimeSelectorContext, ɵSelectFromRootState, ɵSelectorFactory, ɵSelectorMetaDataModel, ɵSharedSelectorOptions, ɵStateClass, ɵStateClassInternal, ɵStateToken, ɵStoreOptions, ɵTokenName };
@@ -1,6 +1,6 @@
1
1
  import { NgxsModuleOptions, Store } from '@ngxs/store';
2
2
  import * as i0 from '@angular/core';
3
- import { EnvironmentProviders, ModuleWithProviders } from '@angular/core';
3
+ import { ModuleWithProviders, EnvironmentProviders } from '@angular/core';
4
4
  import { TestBedStatic } from '@angular/core/testing';
5
5
  import { ɵStateClass as _StateClass } from '@ngxs/store/internals';
6
6
 
@@ -55,10 +55,43 @@ type ExistingState<T> = T extends any ? ɵAsReadonly<T> : never;
55
55
  type StateOperator<T> = (existing: ExistingState<T>) => T;
56
56
 
57
57
  /**
58
- * @param items - Specific items to append to the end of an array
58
+ * Adds items to the end of an array without mutating the original. Handles
59
+ * the case where the array property does not exist yet, so callers do not
60
+ * need to initialise it before appending. A `null`, `undefined`, or empty
61
+ * `items` argument is treated as a no-op to allow safe pass-through of
62
+ * optional data.
63
+ *
64
+ * @param items - Items to add to the end of the array.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * // Add a new zebra to the end of the list without touching the rest of state.
69
+ * ctx.setState(
70
+ * patch<AnimalsStateModel>({
71
+ * zebras: append<string>([action.payload])
72
+ * })
73
+ * );
74
+ * ```
59
75
  */
60
76
  declare function append<T>(items: NoInfer<T[]>): StateOperator<T[]>;
61
77
 
78
+ /**
79
+ * Chains multiple state operators so they execute left-to-right, each
80
+ * receiving the output of the previous one. Useful when several independent
81
+ * transformations must be applied to the same state slice in a single atomic
82
+ * update, avoiding multiple `setState` calls.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * // Apply two independent array mutations in one atomic setState call.
87
+ * ctx.setState(
88
+ * compose<AnimalsStateModel>(
89
+ * patch({ zebras: append<string>([action.zebraName]) }),
90
+ * patch({ pandas: removeItem<string>(name => name === action.pandaToRemove) })
91
+ * )
92
+ * );
93
+ * ```
94
+ */
62
95
  declare function compose<T>(...operators: NoInfer<StateOperator<T>[]>): StateOperator<T>;
63
96
 
64
97
  type Predicate<T = any> = (value: T | Readonly<T>) => boolean;
@@ -66,17 +99,62 @@ declare const isStateOperator: <T>(value: T | StateOperator<T>) => value is Stat
66
99
  declare const isPredicate: <T>(value: Predicate<T> | boolean | number) => value is Predicate<T>;
67
100
 
68
101
  /**
69
- * @param condition - Condition can be a plain boolean value or a function,
70
- * that returns boolean, also this function can take a value as an argument
71
- * to which this state operator applies
72
- * @param trueOperatorOrValue - Any value or a state operator
73
- * @param elseOperatorOrValue - Any value or a state operator
102
+ * Applies one of two operators (or values) based on a condition, keeping
103
+ * conditional logic out of action handlers and inside the state mutation
104
+ * pipeline where it belongs.
105
+ *
106
+ * @param condition - A boolean or a predicate receiving the current state value.
107
+ * Use a predicate when the decision depends on the existing state rather than
108
+ * external data available at dispatch time.
109
+ * @param trueOperatorOrValue - Applied when `condition` is truthy.
110
+ * @param elseOperatorOrValue - Applied when `condition` is falsy. Omit to
111
+ * leave the state unchanged in the false branch.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * // Only add a panda when the list has fewer than 5 — the cap is enforced
116
+ * // inside the operator so the action handler stays free of branching logic.
117
+ * ctx.setState(
118
+ * patch<AnimalsStateModel>({
119
+ * pandas: iif(
120
+ * pandas => pandas.length < 5,
121
+ * append<string>([action.payload])
122
+ * )
123
+ * })
124
+ * );
125
+ * ```
74
126
  */
75
127
  declare function iif<T>(condition: NoInfer<Predicate<T>> | boolean, trueOperatorOrValue: NoInfer<StateOperator<T> | T>, elseOperatorOrValue?: NoInfer<StateOperator<T> | T>): StateOperator<T>;
76
128
 
77
129
  /**
78
- * @param value - Value to insert
79
- * @param [beforePosition] - Specified index to insert value before, optional
130
+ * Inserts an item into an array without mutating the original, satisfying
131
+ * NGXS's immutability requirement. Handles the case where the array property
132
+ * does not exist yet, so callers do not need to initialise it first.
133
+ *
134
+ * @param value - The item to insert. A `null` or `undefined` value is a no-op
135
+ * so that callers can pass through optional data safely.
136
+ * @param beforePosition - Index before which to insert. Omit (or pass a
137
+ * non-positive number) to prepend to the beginning of the array.
138
+ *
139
+ * @example
140
+ * ```ts
141
+ * // Prepend a new zebra (no position = insert at index 0).
142
+ * ctx.setState(
143
+ * patch<AnimalsStateModel>({
144
+ * zebras: insertItem<string>(action.payload)
145
+ * })
146
+ * );
147
+ * ```
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * // Insert before index 2, shifting subsequent items right.
152
+ * ctx.setState(
153
+ * patch<AnimalsStateModel>({
154
+ * zebras: insertItem<string>(action.payload, 2)
155
+ * })
156
+ * );
157
+ * ```
80
158
  */
81
159
  declare function insertItem<T>(value: NoInfer<T>, beforePosition?: number): StateOperator<T[]>;
82
160
 
@@ -84,20 +162,162 @@ type NotUndefined<T> = T extends undefined ? never : T;
84
162
  type ɵPatchSpec<T> = {
85
163
  [P in keyof T]?: T[P] | StateOperator<NotUndefined<T[P]>>;
86
164
  };
165
+ /**
166
+ * Applies a partial update to a state object, only cloning it when at least
167
+ * one property actually changes. This preserves referential equality for
168
+ * unchanged states, preventing unnecessary re-renders in `OnPush` components
169
+ * and keeping memoized selectors from recalculating.
170
+ *
171
+ * Each property in `patchObject` can itself be a state operator, enabling
172
+ * nested immutable updates without manually spreading every level of the tree.
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * // Add an optional property to a state slice without touching existing ones.
177
+ * ctx.setState(
178
+ * patch<AnimalsStateModel>({ monkeys: [] })
179
+ * );
180
+ * ```
181
+ *
182
+ * @example
183
+ * ```ts
184
+ * // Deep update — specify explicit types at each level so TypeScript can
185
+ * // catch property name mistakes in nested patches.
186
+ * ctx.setState(
187
+ * patch<AddressStateModel>({
188
+ * country: patch<AddressStateModel['country']>({
189
+ * city: patch<AddressStateModel['country']['city']>({
190
+ * address: patch<AddressStateModel['country']['city']['address']>({
191
+ * line1: action.line1
192
+ * })
193
+ * })
194
+ * })
195
+ * })
196
+ * );
197
+ * ```
198
+ */
87
199
  declare function patch<T extends Record<string, any>>(patchObject: NoInfer<ɵPatchSpec<T>>): StateOperator<T>;
88
200
 
89
201
  /**
90
- * @param selector - Index of item in the array or a predicate function
91
- * that can be provided in `Array.prototype.findIndex`
92
- * @param operatorOrValue - New value under the `selector` index or a
93
- * function that can be applied to an existing value
202
+ * Like `patch`, but safe to call when the state slice is `null` or
203
+ * `undefined`. Treats a missing slice as an empty object so the patch is
204
+ * applied against a clean baseline rather than throwing. Useful for lazily
205
+ * initialised state properties or optional sub-states that may not have been
206
+ * set yet.
207
+ *
208
+ * @example
209
+ * ```ts
210
+ * // Update a nested preferences slice that starts as null — no prior
211
+ * // null-check needed; safePatch treats null as an empty object.
212
+ * ctx.setState(
213
+ * patch<UserStateModel>({
214
+ * preferences: safePatch<UserPreferences>({ theme: action.theme })
215
+ * })
216
+ * );
217
+ * ```
218
+ */
219
+ declare function safePatch<T extends object>(patchSpec: NoInfer<ɵPatchSpec<T>>): StateOperator<T>;
220
+
221
+ /**
222
+ * Replaces or transforms a single array element without cloning elements that
223
+ * did not change, preserving referential equality for the rest of the array.
224
+ * Returns the original array reference when nothing changed, keeping
225
+ * memoized selectors and `OnPush` components from re-rendering unnecessarily.
226
+ *
227
+ * @param selector - The index to update, or a predicate used to locate the
228
+ * item. Prefer a predicate when the item's position may have shifted since the
229
+ * index was last known.
230
+ * @param operatorOrValue - The replacement value, or a state operator applied
231
+ * to the existing element when a derived update is needed.
232
+ *
233
+ * @example
234
+ * ```ts
235
+ * // Rename a panda — locate it by current name so the index doesn't need
236
+ * // to be known ahead of time.
237
+ * ctx.setState(
238
+ * patch<AnimalsStateModel>({
239
+ * pandas: updateItem<string>(
240
+ * name => name === action.payload.name,
241
+ * action.payload.newName
242
+ * )
243
+ * })
244
+ * );
245
+ * ```
94
246
  */
95
247
  declare function updateItem<T>(selector: number | NoInfer<Predicate<T>>, operatorOrValue: NoInfer<T> | NoInfer<StateOperator<T>>): StateOperator<T[]>;
96
248
 
97
249
  /**
98
- * @param selector - index or predicate to remove an item from an array by
250
+ * Replaces or transforms every array element that matches the predicate.
251
+ * Unlike `updateItem`, which stops at the first match, this operator walks
252
+ * the entire array so all qualifying elements are updated in one pass.
253
+ *
254
+ * Returns the original array reference unchanged when no elements match the
255
+ * predicate, preserving referential equality for memoized selectors. A new
256
+ * array is returned only when at least one element was actually updated.
257
+ *
258
+ * @param selector - Predicate used to decide which elements to update.
259
+ * @param operatorOrValue - Replacement value, or a state operator applied
260
+ * to each matching element when a derived update is needed.
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * // Mark every inactive animal as active in one setState call.
265
+ * ctx.setState(
266
+ * patch<AnimalsStateModel>({
267
+ * animals: updateItems<Animal>(
268
+ * animal => !animal.active,
269
+ * patch({ active: true })
270
+ * )
271
+ * })
272
+ * );
273
+ * ```
274
+ */
275
+ declare function updateItems<T>(selector: NoInfer<Predicate<T>>, operatorOrValue: NoInfer<T> | NoInfer<StateOperator<T>>): (existing: ExistingState<T[]>) => T[];
276
+
277
+ /**
278
+ * Removes a single element from an array without mutating the original.
279
+ * Returns the original array reference when no matching item is found, so
280
+ * memoized selectors are not invalidated by a no-op removal.
281
+ *
282
+ * @param selector - The index to remove, or a predicate used to locate the
283
+ * item. Prefer a predicate when the item's position is not guaranteed to be
284
+ * stable across concurrent state updates.
285
+ *
286
+ * @example
287
+ * ```ts
288
+ * // Remove a panda by name — a predicate is safer than a hard-coded index
289
+ * // because the array order may change between dispatch and execution.
290
+ * ctx.setState(
291
+ * patch<AnimalsStateModel>({
292
+ * pandas: removeItem<string>(name => name === action.payload)
293
+ * })
294
+ * );
295
+ * ```
99
296
  */
100
297
  declare function removeItem<T>(selector: number | NoInfer<Predicate<T>>): StateOperator<T[]>;
101
298
 
102
- export { append, compose, iif, insertItem, isPredicate, isStateOperator, patch, removeItem, updateItem };
299
+ /**
300
+ * Removes every array element that matches the predicate. Unlike `removeItem`,
301
+ * which stops at the first match, this operator walks the entire array so all
302
+ * qualifying elements are eliminated in one pass.
303
+ *
304
+ * Returns the original array reference when no elements matched, so memoized
305
+ * selectors are not invalidated by a no-op removal.
306
+ *
307
+ * @param selector - Predicate used to decide which elements to remove.
308
+ * Elements for which the predicate returns `true` are dropped; the rest are kept.
309
+ *
310
+ * @example
311
+ * ```ts
312
+ * // Remove all inactive animals in one setState call.
313
+ * ctx.setState(
314
+ * patch<AnimalsStateModel>({
315
+ * animals: removeItems<Animal>(animal => !animal.active)
316
+ * })
317
+ * );
318
+ * ```
319
+ */
320
+ declare function removeItems<T>(selector: NoInfer<Predicate<T>>): (existing: ExistingState<T[]>) => T[];
321
+
322
+ export { append, compose, iif, insertItem, isPredicate, isStateOperator, patch, removeItem, removeItems, safePatch, updateItem, updateItems };
103
323
  export type { ExistingState, NoInfer, Predicate, StateOperator, ɵPatchSpec };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@ngxs/store",
3
- "version": "21.0.0",
3
+ "version": "22.0.0",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@angular/core": ">=21.0.0 <22.0.0",
7
+ "@angular/core": ">=22.0.0 <23.0.0",
8
8
  "rxjs": ">=7.0.0"
9
9
  },
10
10
  "schematics": "./schematics/collection.json",
@@ -26,14 +26,14 @@
26
26
  "types": "./internals/index.d.ts",
27
27
  "default": "./fesm2022/ngxs-store-internals.mjs"
28
28
  },
29
- "./operators": {
30
- "types": "./operators/index.d.ts",
31
- "default": "./fesm2022/ngxs-store-operators.mjs"
32
- },
33
29
  "./plugins": {
34
30
  "types": "./plugins/index.d.ts",
35
31
  "default": "./fesm2022/ngxs-store-plugins.mjs"
36
32
  },
33
+ "./operators": {
34
+ "types": "./operators/index.d.ts",
35
+ "default": "./fesm2022/ngxs-store-operators.mjs"
36
+ },
37
37
  "./internals/testing": {
38
38
  "types": "./internals/testing/index.d.ts",
39
39
  "default": "./fesm2022/ngxs-store-internals-testing.mjs"
@@ -61,18 +61,9 @@
61
61
  ],
62
62
  "author": "Austin McDaniel",
63
63
  "contributors": [
64
- {
65
- "name": "Danny Blue"
66
- },
67
- {
68
- "name": "Leon Radley"
69
- },
70
64
  {
71
65
  "name": "Mark Whitfeld"
72
66
  },
73
- {
74
- "name": "Maxim Ivanov"
75
- },
76
67
  {
77
68
  "name": "Artur Androsovych"
78
69
  }
@@ -85,4 +76,4 @@
85
76
  "type": "opencollective",
86
77
  "url": "https://opencollective.com/ngxs"
87
78
  }
88
- }
79
+ }
@@ -1,3 +1,3 @@
1
1
  {
2
- "@ngxs/store": "21.0.0"
2
+ "@ngxs/store": "22.0.0"
3
3
  }