@ngxs/store 21.0.0-dev.master-a4d1cfd → 21.0.0-dev.master-31acb66

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.
@@ -6,12 +6,28 @@ const isNumber = (value) => typeof value === 'number';
6
6
  const invalidIndex = (index) => Number.isNaN(index) || index === -1;
7
7
 
8
8
  /**
9
- * @param items - Specific items to append to the end of an array
9
+ * Adds items to the end of an array without mutating the original. Handles
10
+ * the case where the array property does not exist yet, so callers do not
11
+ * need to initialise it before appending. A `null`, `undefined`, or empty
12
+ * `items` argument is treated as a no-op to allow safe pass-through of
13
+ * optional data.
14
+ *
15
+ * @param items - Items to add to the end of the array.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * // Add a new zebra to the end of the list without touching the rest of state.
20
+ * ctx.setState(
21
+ * patch<AnimalsStateModel>({
22
+ * zebras: append<string>([action.payload])
23
+ * })
24
+ * );
25
+ * ```
10
26
  */
11
27
  function append(items) {
12
28
  return function appendOperator(existing) {
13
- // If `items` is `undefined` or `null` or `[]` but `existing` is provided
14
- // just return `existing`
29
+ // Nothing meaningful to append, so preserve the existing reference
30
+ // to avoid invalidating memoized selectors unnecessarily.
15
31
  const itemsNotProvidedButExistingIs = (!items || !items.length) && existing;
16
32
  if (itemsNotProvidedButExistingIs) {
17
33
  return existing;
@@ -19,12 +35,29 @@ function append(items) {
19
35
  if (isArray(existing)) {
20
36
  return existing.concat(items);
21
37
  }
22
- // For example if some property is added dynamically
23
- // and didn't exist before thus it's not `ArrayLike`
38
+ // The array property was never initialised, so `items` becomes the
39
+ // initial state rather than being appended to a non-existent array.
24
40
  return items;
25
41
  };
26
42
  }
27
43
 
44
+ /**
45
+ * Chains multiple state operators so they execute left-to-right, each
46
+ * receiving the output of the previous one. Useful when several independent
47
+ * transformations must be applied to the same state slice in a single atomic
48
+ * update, avoiding multiple `setState` calls.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * // Apply two independent array mutations in one atomic setState call.
53
+ * ctx.setState(
54
+ * compose<AnimalsStateModel>(
55
+ * patch({ zebras: append<string>([action.zebraName]) }),
56
+ * patch({ pandas: removeItem<string>(name => name === action.pandaToRemove) })
57
+ * )
58
+ * );
59
+ * ```
60
+ */
28
61
  function compose(...operators) {
29
62
  return function composeOperator(existing) {
30
63
  return operators.reduce((accumulator, operator) => operator(accumulator), existing);
@@ -32,32 +65,51 @@ function compose(...operators) {
32
65
  }
33
66
 
34
67
  function retrieveValue(operatorOrValue, existing) {
35
- // If state operator is a function
36
- // then call it with an original value
68
+ // Delegate to the operator so a derived transformation can be applied
69
+ // rather than substituting a static value.
37
70
  if (isStateOperator(operatorOrValue)) {
38
71
  const value = operatorOrValue(existing);
39
72
  return value;
40
73
  }
41
- // If operator or value was not provided
42
- // e.g. `elseOperatorOrValue` is `undefined`
43
- // then we just return an original value
74
+ // No else branch was provided, so leave the state unchanged.
44
75
  if (operatorOrValue === undefined) {
45
76
  return existing;
46
77
  }
47
78
  return operatorOrValue;
48
79
  }
49
80
  /**
50
- * @param condition - Condition can be a plain boolean value or a function,
51
- * that returns boolean, also this function can take a value as an argument
52
- * to which this state operator applies
53
- * @param trueOperatorOrValue - Any value or a state operator
54
- * @param elseOperatorOrValue - Any value or a state operator
81
+ * Applies one of two operators (or values) based on a condition, keeping
82
+ * conditional logic out of action handlers and inside the state mutation
83
+ * pipeline where it belongs.
84
+ *
85
+ * @param condition - A boolean or a predicate receiving the current state value.
86
+ * Use a predicate when the decision depends on the existing state rather than
87
+ * external data available at dispatch time.
88
+ * @param trueOperatorOrValue - Applied when `condition` is truthy.
89
+ * @param elseOperatorOrValue - Applied when `condition` is falsy. Omit to
90
+ * leave the state unchanged in the false branch.
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * // Only add a panda when the list has fewer than 5 — the cap is enforced
95
+ * // inside the operator so the action handler stays free of branching logic.
96
+ * ctx.setState(
97
+ * patch<AnimalsStateModel>({
98
+ * pandas: iif(
99
+ * pandas => pandas.length < 5,
100
+ * append<string>([action.payload])
101
+ * )
102
+ * })
103
+ * );
104
+ * ```
55
105
  */
56
106
  function iif(condition, trueOperatorOrValue, elseOperatorOrValue) {
57
107
  return function iifOperator(existing) {
58
- // Convert the value to a boolean
108
+ // Normalise to a boolean so both plain booleans and predicates
109
+ // share the same resolution path below.
59
110
  let result = !!condition;
60
- // but if it is a function then run it to get the result
111
+ // Predicates receive the current state value so the decision can be
112
+ // based on live state rather than values captured at dispatch time.
61
113
  if (isPredicate(condition)) {
62
114
  result = condition(existing);
63
115
  }
@@ -69,25 +121,51 @@ function iif(condition, trueOperatorOrValue, elseOperatorOrValue) {
69
121
  }
70
122
 
71
123
  /**
72
- * @param value - Value to insert
73
- * @param [beforePosition] - Specified index to insert value before, optional
124
+ * Inserts an item into an array without mutating the original, satisfying
125
+ * NGXS's immutability requirement. Handles the case where the array property
126
+ * does not exist yet, so callers do not need to initialise it first.
127
+ *
128
+ * @param value - The item to insert. A `null` or `undefined` value is a no-op
129
+ * so that callers can pass through optional data safely.
130
+ * @param beforePosition - Index before which to insert. Omit (or pass a
131
+ * non-positive number) to prepend to the beginning of the array.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * // Prepend a new zebra (no position = insert at index 0).
136
+ * ctx.setState(
137
+ * patch<AnimalsStateModel>({
138
+ * zebras: insertItem<string>(action.payload)
139
+ * })
140
+ * );
141
+ * ```
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * // Insert before index 2, shifting subsequent items right.
146
+ * ctx.setState(
147
+ * patch<AnimalsStateModel>({
148
+ * zebras: insertItem<string>(action.payload, 2)
149
+ * })
150
+ * );
151
+ * ```
74
152
  */
75
153
  function insertItem(value, beforePosition) {
76
154
  return function insertItemOperator(existing) {
77
- // Have to check explicitly for `null` and `undefined`
78
- // because `value` can be `0`, thus `!value` will return `true`
155
+ // `== null` covers both `null` and `undefined` while letting falsy
156
+ // values like `0` or `false` through, where `!value` would not.
79
157
  if (value == null && existing) {
80
158
  return existing;
81
159
  }
82
- // Property may be dynamic and might not existed before
160
+ // The array property may not have been initialised yet; treat it as
161
+ // empty so callers don't have to guard against that case themselves.
83
162
  if (!isArray(existing)) {
84
163
  return [value];
85
164
  }
86
165
  const clone = existing.slice();
87
166
  let index = 0;
88
- // No need to call `isNumber`
89
- // as we are checking `> 0` not `>= 0`
90
- // everything except number will return false here
167
+ // `> 0` rather than `>= 0` intentionally: non-numeric values coerce
168
+ // to NaN and fail this check, so no explicit `isNumber` call is needed.
91
169
  if (beforePosition > 0) {
92
170
  index = beforePosition;
93
171
  }
@@ -96,6 +174,40 @@ function insertItem(value, beforePosition) {
96
174
  };
97
175
  }
98
176
 
177
+ /**
178
+ * Applies a partial update to a state object, only cloning it when at least
179
+ * one property actually changes. This preserves referential equality for
180
+ * unchanged states, preventing unnecessary re-renders in `OnPush` components
181
+ * and keeping memoized selectors from recalculating.
182
+ *
183
+ * Each property in `patchObject` can itself be a state operator, enabling
184
+ * nested immutable updates without manually spreading every level of the tree.
185
+ *
186
+ * @example
187
+ * ```ts
188
+ * // Add an optional property to a state slice without touching existing ones.
189
+ * ctx.setState(
190
+ * patch<AnimalsStateModel>({ monkeys: [] })
191
+ * );
192
+ * ```
193
+ *
194
+ * @example
195
+ * ```ts
196
+ * // Deep update — specify explicit types at each level so TypeScript can
197
+ * // catch property name mistakes in nested patches.
198
+ * ctx.setState(
199
+ * patch<AddressStateModel>({
200
+ * country: patch<AddressStateModel['country']>({
201
+ * city: patch<AddressStateModel['country']['city']>({
202
+ * address: patch<AddressStateModel['country']['city']['address']>({
203
+ * line1: action.line1
204
+ * })
205
+ * })
206
+ * })
207
+ * })
208
+ * );
209
+ * ```
210
+ */
99
211
  function patch(patchObject) {
100
212
  return function patchStateOperator(existing) {
101
213
  let clone = null;
@@ -116,6 +228,24 @@ function patch(patchObject) {
116
228
  };
117
229
  }
118
230
 
231
+ /**
232
+ * Like `patch`, but safe to call when the state slice is `null` or
233
+ * `undefined`. Treats a missing slice as an empty object so the patch is
234
+ * applied against a clean baseline rather than throwing. Useful for lazily
235
+ * initialised state properties or optional sub-states that may not have been
236
+ * set yet.
237
+ *
238
+ * @example
239
+ * ```ts
240
+ * // Update a nested preferences slice that starts as null — no prior
241
+ * // null-check needed; safePatch treats null as an empty object.
242
+ * ctx.setState(
243
+ * patch<UserStateModel>({
244
+ * preferences: safePatch<UserPreferences>({ theme: action.theme })
245
+ * })
246
+ * );
247
+ * ```
248
+ */
119
249
  function safePatch(patchSpec) {
120
250
  const patcher = patch(patchSpec);
121
251
  return function patchSafely(existing) {
@@ -124,10 +254,30 @@ function safePatch(patchSpec) {
124
254
  }
125
255
 
126
256
  /**
127
- * @param selector - Index of item in the array or a predicate function
128
- * that can be provided in `Array.prototype.findIndex`
129
- * @param operatorOrValue - New value under the `selector` index or a
130
- * function that can be applied to an existing value
257
+ * Replaces or transforms a single array element without cloning elements that
258
+ * did not change, preserving referential equality for the rest of the array.
259
+ * Returns the original array reference when nothing changed, keeping
260
+ * memoized selectors and `OnPush` components from re-rendering unnecessarily.
261
+ *
262
+ * @param selector - The index to update, or a predicate used to locate the
263
+ * item. Prefer a predicate when the item's position may have shifted since the
264
+ * index was last known.
265
+ * @param operatorOrValue - The replacement value, or a state operator applied
266
+ * to the existing element when a derived update is needed.
267
+ *
268
+ * @example
269
+ * ```ts
270
+ * // Rename a panda — locate it by current name so the index doesn't need
271
+ * // to be known ahead of time.
272
+ * ctx.setState(
273
+ * patch<AnimalsStateModel>({
274
+ * pandas: updateItem<string>(
275
+ * name => name === action.payload.name,
276
+ * action.payload.newName
277
+ * )
278
+ * })
279
+ * );
280
+ * ```
131
281
  */
132
282
  function updateItem(selector, operatorOrValue) {
133
283
  return function updateItemOperator(existing) {
@@ -142,8 +292,8 @@ function updateItem(selector, operatorOrValue) {
142
292
  return existing;
143
293
  }
144
294
  let value = null;
145
- // Need to check if the new item value will change the existing item value
146
- // then, only if it will change it then clone the array and set the item
295
+ // Resolve the new value before touching the array so we can bail out
296
+ // early and skip the clone when nothing actually changed.
147
297
  const theOperatorOrValue = operatorOrValue;
148
298
  if (isStateOperator(theOperatorOrValue)) {
149
299
  value = theOperatorOrValue(existing[index]);
@@ -151,8 +301,8 @@ function updateItem(selector, operatorOrValue) {
151
301
  else {
152
302
  value = theOperatorOrValue;
153
303
  }
154
- // If the value hasn't been mutated
155
- // then we just return `existing` array
304
+ // Return the original reference to prevent memoized selectors and
305
+ // OnPush components from reacting to a no-op update.
156
306
  if (value === existing[index]) {
157
307
  return existing;
158
308
  }
@@ -163,7 +313,77 @@ function updateItem(selector, operatorOrValue) {
163
313
  }
164
314
 
165
315
  /**
166
- * @param selector - index or predicate to remove an item from an array by
316
+ * Replaces or transforms every array element that matches the predicate.
317
+ * Unlike `updateItem`, which stops at the first match, this operator walks
318
+ * the entire array so all qualifying elements are updated in one pass.
319
+ *
320
+ * Always returns a new array reference, even when no elements matched or the
321
+ * values produced by the operator are identical to the originals. Use
322
+ * `updateItem` instead when only a single element needs updating and
323
+ * referential equality on no-op updates matters.
324
+ *
325
+ * @param selector - Predicate used to decide which elements to update.
326
+ * @param operatorOrValue - Replacement value, or a state operator applied
327
+ * to each matching element when a derived update is needed.
328
+ *
329
+ * @example
330
+ * ```ts
331
+ * // Mark every inactive animal as active in one setState call.
332
+ * ctx.setState(
333
+ * patch<AnimalsStateModel>({
334
+ * animals: updateItems<Animal>(
335
+ * animal => !animal.active,
336
+ * patch({ active: true })
337
+ * )
338
+ * })
339
+ * );
340
+ * ```
341
+ */
342
+ function updateItems(selector, operatorOrValue) {
343
+ return function updateItemsOperator(existing) {
344
+ if (!Array.isArray(existing)) {
345
+ return [];
346
+ }
347
+ else if (existing.length === 0) {
348
+ return existing;
349
+ }
350
+ const clone = existing.slice();
351
+ for (let index = 0; index < clone.length; index++) {
352
+ let value = clone[index];
353
+ if (selector(value)) {
354
+ const theOperatorOrValue = operatorOrValue;
355
+ if (isStateOperator(theOperatorOrValue)) {
356
+ value = theOperatorOrValue(value);
357
+ }
358
+ else {
359
+ value = theOperatorOrValue;
360
+ }
361
+ clone[index] = value;
362
+ }
363
+ }
364
+ return clone;
365
+ };
366
+ }
367
+
368
+ /**
369
+ * Removes a single element from an array without mutating the original.
370
+ * Returns the original array reference when no matching item is found, so
371
+ * memoized selectors are not invalidated by a no-op removal.
372
+ *
373
+ * @param selector - The index to remove, or a predicate used to locate the
374
+ * item. Prefer a predicate when the item's position is not guaranteed to be
375
+ * stable across concurrent state updates.
376
+ *
377
+ * @example
378
+ * ```ts
379
+ * // Remove a panda by name — a predicate is safer than a hard-coded index
380
+ * // because the array order may change between dispatch and execution.
381
+ * ctx.setState(
382
+ * patch<AnimalsStateModel>({
383
+ * pandas: removeItem<string>(name => name === action.payload)
384
+ * })
385
+ * );
386
+ * ```
167
387
  */
168
388
  function removeItem(selector) {
169
389
  return function removeItemOperator(existing) {
@@ -193,5 +413,5 @@ function removeItem(selector) {
193
413
  * Generated bundle index. Do not edit.
194
414
  */
195
415
 
196
- export { append, compose, iif, insertItem, isPredicate, isStateOperator, patch, removeItem, safePatch, updateItem };
416
+ export { append, compose, iif, insertItem, isPredicate, isStateOperator, patch, removeItem, safePatch, updateItem, updateItems };
197
417
  //# sourceMappingURL=ngxs-store-operators.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ngxs-store-operators.mjs","sources":["../../../packages/store/operators/src/utils.ts","../../../packages/store/operators/src/append.ts","../../../packages/store/operators/src/compose.ts","../../../packages/store/operators/src/iif.ts","../../../packages/store/operators/src/insert-item.ts","../../../packages/store/operators/src/patch.ts","../../../packages/store/operators/src/safe-patch.ts","../../../packages/store/operators/src/update-item.ts","../../../packages/store/operators/src/remove-item.ts","../../../packages/store/operators/src/index.ts","../../../packages/store/operators/src/ngxs-store-operators.ts"],"sourcesContent":["import { StateOperator } from './types';\n\nexport const isArray = Array.isArray;\n\nexport type Predicate<T = any> = (value: T | Readonly<T>) => boolean;\n\nconst isFunction = (value: unknown) => typeof value == 'function';\n\nexport const isStateOperator = isFunction as <T>(\n value: T | StateOperator<T>\n) => value is StateOperator<T>;\n\nexport const isPredicate = isFunction as <T>(\n value: Predicate<T> | boolean | number\n) => value is Predicate<T>;\n\nexport const isNumber = (value: unknown): value is number => typeof value === 'number';\n\nexport const invalidIndex = (index: number) => Number.isNaN(index) || index === -1;\n","import { ExistingState, NoInfer, StateOperator } from './types';\nimport { isArray } from './utils';\n\n/**\n * @param items - Specific items to append to the end of an array\n */\nexport function append<T>(items: NoInfer<T[]>): StateOperator<T[]> {\n return function appendOperator(existing: ExistingState<T[]>): T[] {\n // If `items` is `undefined` or `null` or `[]` but `existing` is provided\n // just return `existing`\n const itemsNotProvidedButExistingIs = (!items || !items.length) && existing;\n if (itemsNotProvidedButExistingIs) {\n return existing as unknown as T[];\n }\n\n if (isArray(existing)) {\n return existing.concat(items as unknown as ExistingState<T[]>);\n }\n\n // For example if some property is added dynamically\n // and didn't exist before thus it's not `ArrayLike`\n return items as unknown as T[];\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\n\nexport function compose<T>(...operators: NoInfer<StateOperator<T>[]>): StateOperator<T> {\n return function composeOperator(existing: ExistingState<T>): T {\n return operators.reduce(\n (accumulator, operator) => operator(accumulator as ExistingState<T>),\n existing as T\n );\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\n\nimport { isStateOperator, isPredicate, Predicate } from './utils';\n\nfunction retrieveValue<T>(\n operatorOrValue: StateOperator<T> | T,\n existing: ExistingState<T>\n): T {\n // If state operator is a function\n // then call it with an original value\n if (isStateOperator(operatorOrValue)) {\n const value = operatorOrValue(existing);\n return value as T;\n }\n\n // If operator or value was not provided\n // e.g. `elseOperatorOrValue` is `undefined`\n // then we just return an original value\n if (operatorOrValue === undefined) {\n return existing as T;\n }\n\n return operatorOrValue as T;\n}\n\n/**\n * @param condition - Condition can be a plain boolean value or a function,\n * that returns boolean, also this function can take a value as an argument\n * to which this state operator applies\n * @param trueOperatorOrValue - Any value or a state operator\n * @param elseOperatorOrValue - Any value or a state operator\n */\nexport function iif<T>(\n condition: NoInfer<Predicate<T>> | boolean,\n trueOperatorOrValue: NoInfer<StateOperator<T> | T>,\n elseOperatorOrValue?: NoInfer<StateOperator<T> | T>\n): StateOperator<T> {\n return function iifOperator(existing: ExistingState<T>): T {\n // Convert the value to a boolean\n let result = !!condition;\n // but if it is a function then run it to get the result\n if (isPredicate(condition)) {\n result = condition(existing as T);\n }\n\n if (result) {\n return retrieveValue<T>(trueOperatorOrValue as StateOperator<T> | T, existing);\n }\n\n return retrieveValue<T>(elseOperatorOrValue! as StateOperator<T> | T, existing);\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\nimport { isArray } from './utils';\n\n/**\n * @param value - Value to insert\n * @param [beforePosition] - Specified index to insert value before, optional\n */\nexport function insertItem<T>(value: NoInfer<T>, beforePosition?: number): StateOperator<T[]> {\n return function insertItemOperator(existing: ExistingState<T[]>): T[] {\n // Have to check explicitly for `null` and `undefined`\n // because `value` can be `0`, thus `!value` will return `true`\n if (value == null && existing) {\n return existing as T[];\n }\n\n // Property may be dynamic and might not existed before\n if (!isArray(existing)) {\n return [value as unknown as T];\n }\n\n const clone = existing.slice();\n\n let index = 0;\n\n // No need to call `isNumber`\n // as we are checking `> 0` not `>= 0`\n // everything except number will return false here\n if (beforePosition! > 0) {\n index = beforePosition!;\n }\n\n clone.splice(index, 0, value as unknown as T);\n return clone;\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\nimport { isStateOperator } from './utils';\n\ntype NotUndefined<T> = T extends undefined ? never : T;\n\nexport type ɵPatchSpec<T> = { [P in keyof T]?: T[P] | StateOperator<NotUndefined<T[P]>> };\n\nexport function patch<T extends Record<string, any>>(\n patchObject: NoInfer<ɵPatchSpec<T>>\n): StateOperator<T> {\n return function patchStateOperator(existing: ExistingState<T>): T {\n let clone = null;\n for (const k in patchObject) {\n const newValue = patchObject[k];\n const existingPropValue = existing?.[k];\n const newPropValue = isStateOperator(newValue)\n ? newValue(<any>existingPropValue)\n : newValue;\n if (newPropValue !== existingPropValue) {\n if (!clone) {\n clone = { ...(<any>existing) };\n }\n clone[k] = newPropValue;\n }\n }\n return clone || existing;\n };\n}\n","import { patch, type ɵPatchSpec } from './patch';\nimport type { ExistingState, NoInfer, StateOperator } from './types';\n\nexport function safePatch<T extends object>(\n patchSpec: NoInfer<ɵPatchSpec<T>>\n): StateOperator<T> {\n const patcher = patch(patchSpec as ɵPatchSpec<T>) as unknown as StateOperator<\n Readonly<NonNullable<T>>\n >;\n return function patchSafely(existing: ExistingState<T>): T {\n return patcher(existing ?? ({} as ExistingState<Readonly<NonNullable<T>>>));\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\n\nimport { isStateOperator, isPredicate, isNumber, invalidIndex, Predicate } from './utils';\n\n/**\n * @param selector - Index of item in the array or a predicate function\n * that can be provided in `Array.prototype.findIndex`\n * @param operatorOrValue - New value under the `selector` index or a\n * function that can be applied to an existing value\n */\nexport function updateItem<T>(\n selector: number | NoInfer<Predicate<T>>,\n operatorOrValue: NoInfer<T> | NoInfer<StateOperator<T>>\n): StateOperator<T[]> {\n return function updateItemOperator(existing: ExistingState<T[]>): T[] {\n let index = -1;\n\n if (isPredicate(selector)) {\n index = existing.findIndex(selector as Predicate<T>);\n } else if (isNumber(selector)) {\n index = selector;\n }\n\n if (invalidIndex(index)) {\n return existing as T[];\n }\n\n let value: T = null!;\n // Need to check if the new item value will change the existing item value\n // then, only if it will change it then clone the array and set the item\n const theOperatorOrValue = operatorOrValue as T | StateOperator<T>;\n if (isStateOperator(theOperatorOrValue)) {\n value = theOperatorOrValue(existing[index] as ExistingState<T>);\n } else {\n value = theOperatorOrValue;\n }\n\n // If the value hasn't been mutated\n // then we just return `existing` array\n if (value === existing[index]) {\n return existing as T[];\n }\n\n const clone = existing.slice();\n clone[index] = value as T;\n return clone;\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\nimport { isPredicate, isNumber, invalidIndex, Predicate } from './utils';\n\n/**\n * @param selector - index or predicate to remove an item from an array by\n */\nexport function removeItem<T>(selector: number | NoInfer<Predicate<T>>): StateOperator<T[]> {\n return function removeItemOperator(existing: ExistingState<T[]>): T[] {\n let index = -1;\n\n if (isPredicate(selector)) {\n index = existing.findIndex(selector);\n } else if (isNumber(selector)) {\n index = selector;\n }\n\n if (invalidIndex(index)) {\n return existing as T[];\n }\n\n const clone = existing.slice();\n clone.splice(index, 1);\n return clone;\n };\n}\n","/**\n * @module\n * @description\n * Entry point for all public APIs of this package.\n */\nexport { append } from './append';\nexport { compose } from './compose';\nexport { iif } from './iif';\nexport { insertItem } from './insert-item';\nexport { patch, type ɵPatchSpec } from './patch';\nexport { safePatch } from './safe-patch';\nexport { isStateOperator, isPredicate, type Predicate } from './utils';\nexport { updateItem } from './update-item';\nexport { removeItem } from './remove-item';\nexport type { ExistingState, NoInfer, StateOperator } from './types';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngxs-store-operators.mjs","sources":["../../../packages/store/operators/src/utils.ts","../../../packages/store/operators/src/append.ts","../../../packages/store/operators/src/compose.ts","../../../packages/store/operators/src/iif.ts","../../../packages/store/operators/src/insert-item.ts","../../../packages/store/operators/src/patch.ts","../../../packages/store/operators/src/safe-patch.ts","../../../packages/store/operators/src/update-item.ts","../../../packages/store/operators/src/update-items.ts","../../../packages/store/operators/src/remove-item.ts","../../../packages/store/operators/src/index.ts","../../../packages/store/operators/src/ngxs-store-operators.ts"],"sourcesContent":["import { StateOperator } from './types';\n\nexport const isArray = Array.isArray;\n\nexport type Predicate<T = any> = (value: T | Readonly<T>) => boolean;\n\nconst isFunction = (value: unknown) => typeof value == 'function';\n\nexport const isStateOperator = isFunction as <T>(\n value: T | StateOperator<T>\n) => value is StateOperator<T>;\n\nexport const isPredicate = isFunction as <T>(\n value: Predicate<T> | boolean | number\n) => value is Predicate<T>;\n\nexport const isNumber = (value: unknown): value is number => typeof value === 'number';\n\nexport const invalidIndex = (index: number) => Number.isNaN(index) || index === -1;\n","import { ExistingState, NoInfer, StateOperator } from './types';\nimport { isArray } from './utils';\n\n/**\n * Adds items to the end of an array without mutating the original. Handles\n * the case where the array property does not exist yet, so callers do not\n * need to initialise it before appending. A `null`, `undefined`, or empty\n * `items` argument is treated as a no-op to allow safe pass-through of\n * optional data.\n *\n * @param items - Items to add to the end of the array.\n *\n * @example\n * ```ts\n * // Add a new zebra to the end of the list without touching the rest of state.\n * ctx.setState(\n * patch<AnimalsStateModel>({\n * zebras: append<string>([action.payload])\n * })\n * );\n * ```\n */\nexport function append<T>(items: NoInfer<T[]>): StateOperator<T[]> {\n return function appendOperator(existing: ExistingState<T[]>): T[] {\n // Nothing meaningful to append, so preserve the existing reference\n // to avoid invalidating memoized selectors unnecessarily.\n const itemsNotProvidedButExistingIs = (!items || !items.length) && existing;\n if (itemsNotProvidedButExistingIs) {\n return existing as unknown as T[];\n }\n\n if (isArray(existing)) {\n return existing.concat(items as unknown as ExistingState<T[]>);\n }\n\n // The array property was never initialised, so `items` becomes the\n // initial state rather than being appended to a non-existent array.\n return items as unknown as T[];\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\n\n/**\n * Chains multiple state operators so they execute left-to-right, each\n * receiving the output of the previous one. Useful when several independent\n * transformations must be applied to the same state slice in a single atomic\n * update, avoiding multiple `setState` calls.\n *\n * @example\n * ```ts\n * // Apply two independent array mutations in one atomic setState call.\n * ctx.setState(\n * compose<AnimalsStateModel>(\n * patch({ zebras: append<string>([action.zebraName]) }),\n * patch({ pandas: removeItem<string>(name => name === action.pandaToRemove) })\n * )\n * );\n * ```\n */\nexport function compose<T>(...operators: NoInfer<StateOperator<T>[]>): StateOperator<T> {\n return function composeOperator(existing: ExistingState<T>): T {\n return operators.reduce(\n (accumulator, operator) => operator(accumulator as ExistingState<T>),\n existing as T\n );\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\n\nimport { isStateOperator, isPredicate, Predicate } from './utils';\n\nfunction retrieveValue<T>(\n operatorOrValue: StateOperator<T> | T,\n existing: ExistingState<T>\n): T {\n // Delegate to the operator so a derived transformation can be applied\n // rather than substituting a static value.\n if (isStateOperator(operatorOrValue)) {\n const value = operatorOrValue(existing);\n return value as T;\n }\n\n // No else branch was provided, so leave the state unchanged.\n if (operatorOrValue === undefined) {\n return existing as T;\n }\n\n return operatorOrValue as T;\n}\n\n/**\n * Applies one of two operators (or values) based on a condition, keeping\n * conditional logic out of action handlers and inside the state mutation\n * pipeline where it belongs.\n *\n * @param condition - A boolean or a predicate receiving the current state value.\n * Use a predicate when the decision depends on the existing state rather than\n * external data available at dispatch time.\n * @param trueOperatorOrValue - Applied when `condition` is truthy.\n * @param elseOperatorOrValue - Applied when `condition` is falsy. Omit to\n * leave the state unchanged in the false branch.\n *\n * @example\n * ```ts\n * // Only add a panda when the list has fewer than 5 — the cap is enforced\n * // inside the operator so the action handler stays free of branching logic.\n * ctx.setState(\n * patch<AnimalsStateModel>({\n * pandas: iif(\n * pandas => pandas.length < 5,\n * append<string>([action.payload])\n * )\n * })\n * );\n * ```\n */\nexport function iif<T>(\n condition: NoInfer<Predicate<T>> | boolean,\n trueOperatorOrValue: NoInfer<StateOperator<T> | T>,\n elseOperatorOrValue?: NoInfer<StateOperator<T> | T>\n): StateOperator<T> {\n return function iifOperator(existing: ExistingState<T>): T {\n // Normalise to a boolean so both plain booleans and predicates\n // share the same resolution path below.\n let result = !!condition;\n // Predicates receive the current state value so the decision can be\n // based on live state rather than values captured at dispatch time.\n if (isPredicate(condition)) {\n result = condition(existing as T);\n }\n\n if (result) {\n return retrieveValue<T>(trueOperatorOrValue as StateOperator<T> | T, existing);\n }\n\n return retrieveValue<T>(elseOperatorOrValue! as StateOperator<T> | T, existing);\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\nimport { isArray } from './utils';\n\n/**\n * Inserts an item into an array without mutating the original, satisfying\n * NGXS's immutability requirement. Handles the case where the array property\n * does not exist yet, so callers do not need to initialise it first.\n *\n * @param value - The item to insert. A `null` or `undefined` value is a no-op\n * so that callers can pass through optional data safely.\n * @param beforePosition - Index before which to insert. Omit (or pass a\n * non-positive number) to prepend to the beginning of the array.\n *\n * @example\n * ```ts\n * // Prepend a new zebra (no position = insert at index 0).\n * ctx.setState(\n * patch<AnimalsStateModel>({\n * zebras: insertItem<string>(action.payload)\n * })\n * );\n * ```\n *\n * @example\n * ```ts\n * // Insert before index 2, shifting subsequent items right.\n * ctx.setState(\n * patch<AnimalsStateModel>({\n * zebras: insertItem<string>(action.payload, 2)\n * })\n * );\n * ```\n */\nexport function insertItem<T>(value: NoInfer<T>, beforePosition?: number): StateOperator<T[]> {\n return function insertItemOperator(existing: ExistingState<T[]>): T[] {\n // `== null` covers both `null` and `undefined` while letting falsy\n // values like `0` or `false` through, where `!value` would not.\n if (value == null && existing) {\n return existing as T[];\n }\n\n // The array property may not have been initialised yet; treat it as\n // empty so callers don't have to guard against that case themselves.\n if (!isArray(existing)) {\n return [value as unknown as T];\n }\n\n const clone = existing.slice();\n\n let index = 0;\n\n // `> 0` rather than `>= 0` intentionally: non-numeric values coerce\n // to NaN and fail this check, so no explicit `isNumber` call is needed.\n if (beforePosition! > 0) {\n index = beforePosition!;\n }\n\n clone.splice(index, 0, value as unknown as T);\n return clone;\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\nimport { isStateOperator } from './utils';\n\ntype NotUndefined<T> = T extends undefined ? never : T;\n\nexport type ɵPatchSpec<T> = { [P in keyof T]?: T[P] | StateOperator<NotUndefined<T[P]>> };\n\n/**\n * Applies a partial update to a state object, only cloning it when at least\n * one property actually changes. This preserves referential equality for\n * unchanged states, preventing unnecessary re-renders in `OnPush` components\n * and keeping memoized selectors from recalculating.\n *\n * Each property in `patchObject` can itself be a state operator, enabling\n * nested immutable updates without manually spreading every level of the tree.\n *\n * @example\n * ```ts\n * // Add an optional property to a state slice without touching existing ones.\n * ctx.setState(\n * patch<AnimalsStateModel>({ monkeys: [] })\n * );\n * ```\n *\n * @example\n * ```ts\n * // Deep update — specify explicit types at each level so TypeScript can\n * // catch property name mistakes in nested patches.\n * ctx.setState(\n * patch<AddressStateModel>({\n * country: patch<AddressStateModel['country']>({\n * city: patch<AddressStateModel['country']['city']>({\n * address: patch<AddressStateModel['country']['city']['address']>({\n * line1: action.line1\n * })\n * })\n * })\n * })\n * );\n * ```\n */\nexport function patch<T extends Record<string, any>>(\n patchObject: NoInfer<ɵPatchSpec<T>>\n): StateOperator<T> {\n return function patchStateOperator(existing: ExistingState<T>): T {\n let clone = null;\n for (const k in patchObject) {\n const newValue = patchObject[k];\n const existingPropValue = existing?.[k];\n const newPropValue = isStateOperator(newValue)\n ? newValue(<any>existingPropValue)\n : newValue;\n if (newPropValue !== existingPropValue) {\n if (!clone) {\n clone = { ...(<any>existing) };\n }\n clone[k] = newPropValue;\n }\n }\n return clone || existing;\n };\n}\n","import { patch, type ɵPatchSpec } from './patch';\nimport type { ExistingState, NoInfer, StateOperator } from './types';\n\n/**\n * Like `patch`, but safe to call when the state slice is `null` or\n * `undefined`. Treats a missing slice as an empty object so the patch is\n * applied against a clean baseline rather than throwing. Useful for lazily\n * initialised state properties or optional sub-states that may not have been\n * set yet.\n *\n * @example\n * ```ts\n * // Update a nested preferences slice that starts as null — no prior\n * // null-check needed; safePatch treats null as an empty object.\n * ctx.setState(\n * patch<UserStateModel>({\n * preferences: safePatch<UserPreferences>({ theme: action.theme })\n * })\n * );\n * ```\n */\nexport function safePatch<T extends object>(\n patchSpec: NoInfer<ɵPatchSpec<T>>\n): StateOperator<T> {\n const patcher = patch(patchSpec as ɵPatchSpec<T>) as unknown as StateOperator<\n Readonly<NonNullable<T>>\n >;\n return function patchSafely(existing: ExistingState<T>): T {\n return patcher(existing ?? ({} as ExistingState<Readonly<NonNullable<T>>>));\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\n\nimport { isStateOperator, isPredicate, isNumber, invalidIndex, Predicate } from './utils';\n\n/**\n * Replaces or transforms a single array element without cloning elements that\n * did not change, preserving referential equality for the rest of the array.\n * Returns the original array reference when nothing changed, keeping\n * memoized selectors and `OnPush` components from re-rendering unnecessarily.\n *\n * @param selector - The index to update, or a predicate used to locate the\n * item. Prefer a predicate when the item's position may have shifted since the\n * index was last known.\n * @param operatorOrValue - The replacement value, or a state operator applied\n * to the existing element when a derived update is needed.\n *\n * @example\n * ```ts\n * // Rename a panda — locate it by current name so the index doesn't need\n * // to be known ahead of time.\n * ctx.setState(\n * patch<AnimalsStateModel>({\n * pandas: updateItem<string>(\n * name => name === action.payload.name,\n * action.payload.newName\n * )\n * })\n * );\n * ```\n */\nexport function updateItem<T>(\n selector: number | NoInfer<Predicate<T>>,\n operatorOrValue: NoInfer<T> | NoInfer<StateOperator<T>>\n): StateOperator<T[]> {\n return function updateItemOperator(existing: ExistingState<T[]>): T[] {\n let index = -1;\n\n if (isPredicate(selector)) {\n index = existing.findIndex(selector as Predicate<T>);\n } else if (isNumber(selector)) {\n index = selector;\n }\n\n if (invalidIndex(index)) {\n return existing as T[];\n }\n\n let value: T = null!;\n // Resolve the new value before touching the array so we can bail out\n // early and skip the clone when nothing actually changed.\n const theOperatorOrValue = operatorOrValue as T | StateOperator<T>;\n if (isStateOperator(theOperatorOrValue)) {\n value = theOperatorOrValue(existing[index] as ExistingState<T>);\n } else {\n value = theOperatorOrValue;\n }\n\n // Return the original reference to prevent memoized selectors and\n // OnPush components from reacting to a no-op update.\n if (value === existing[index]) {\n return existing as T[];\n }\n\n const clone = existing.slice();\n clone[index] = value as T;\n return clone;\n };\n}\n","import { type StateOperator, type ExistingState, type NoInfer } from './types';\nimport { isStateOperator, type Predicate } from './utils';\n\n/**\n * Replaces or transforms every array element that matches the predicate.\n * Unlike `updateItem`, which stops at the first match, this operator walks\n * the entire array so all qualifying elements are updated in one pass.\n *\n * Always returns a new array reference, even when no elements matched or the\n * values produced by the operator are identical to the originals. Use\n * `updateItem` instead when only a single element needs updating and\n * referential equality on no-op updates matters.\n *\n * @param selector - Predicate used to decide which elements to update.\n * @param operatorOrValue - Replacement value, or a state operator applied\n * to each matching element when a derived update is needed.\n *\n * @example\n * ```ts\n * // Mark every inactive animal as active in one setState call.\n * ctx.setState(\n * patch<AnimalsStateModel>({\n * animals: updateItems<Animal>(\n * animal => !animal.active,\n * patch({ active: true })\n * )\n * })\n * );\n * ```\n */\nexport function updateItems<T>(\n selector: NoInfer<Predicate<T>>,\n operatorOrValue: NoInfer<T> | NoInfer<StateOperator<T>>\n) {\n return function updateItemsOperator(existing: ExistingState<T[]>): T[] {\n if (!Array.isArray(existing)) {\n return [] as T[];\n } else if (existing.length === 0) {\n return existing as T[];\n }\n\n const clone = existing.slice();\n for (let index = 0; index < clone.length; index++) {\n let value = clone[index];\n if (selector(value)) {\n const theOperatorOrValue = operatorOrValue as T | StateOperator<T>;\n if (isStateOperator(theOperatorOrValue)) {\n value = theOperatorOrValue(value as ExistingState<T>);\n } else {\n value = theOperatorOrValue;\n }\n clone[index] = value;\n }\n }\n return clone;\n };\n}\n","import { ExistingState, NoInfer, StateOperator } from './types';\nimport { isPredicate, isNumber, invalidIndex, Predicate } from './utils';\n\n/**\n * Removes a single element from an array without mutating the original.\n * Returns the original array reference when no matching item is found, so\n * memoized selectors are not invalidated by a no-op removal.\n *\n * @param selector - The index to remove, or a predicate used to locate the\n * item. Prefer a predicate when the item's position is not guaranteed to be\n * stable across concurrent state updates.\n *\n * @example\n * ```ts\n * // Remove a panda by name — a predicate is safer than a hard-coded index\n * // because the array order may change between dispatch and execution.\n * ctx.setState(\n * patch<AnimalsStateModel>({\n * pandas: removeItem<string>(name => name === action.payload)\n * })\n * );\n * ```\n */\nexport function removeItem<T>(selector: number | NoInfer<Predicate<T>>): StateOperator<T[]> {\n return function removeItemOperator(existing: ExistingState<T[]>): T[] {\n let index = -1;\n\n if (isPredicate(selector)) {\n index = existing.findIndex(selector);\n } else if (isNumber(selector)) {\n index = selector;\n }\n\n if (invalidIndex(index)) {\n return existing as T[];\n }\n\n const clone = existing.slice();\n clone.splice(index, 1);\n return clone;\n };\n}\n","/**\n * @module\n * @description\n * Entry point for all public APIs of this package.\n */\nexport { append } from './append';\nexport { compose } from './compose';\nexport { iif } from './iif';\nexport { insertItem } from './insert-item';\nexport { patch, type ɵPatchSpec } from './patch';\nexport { safePatch } from './safe-patch';\nexport { isStateOperator, isPredicate, type Predicate } from './utils';\nexport { updateItem } from './update-item';\nexport { updateItems } from './update-items';\nexport { removeItem } from './remove-item';\nexport type { ExistingState, NoInfer, StateOperator } from './types';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -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,22 +162,140 @@ 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
 
201
+ /**
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
+ */
89
219
  declare function safePatch<T extends object>(patchSpec: NoInfer<ɵPatchSpec<T>>): StateOperator<T>;
90
220
 
91
221
  /**
92
- * @param selector - Index of item in the array or a predicate function
93
- * that can be provided in `Array.prototype.findIndex`
94
- * @param operatorOrValue - New value under the `selector` index or a
95
- * function that can be applied to an existing value
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
+ * ```
96
246
  */
97
247
  declare function updateItem<T>(selector: number | NoInfer<Predicate<T>>, operatorOrValue: NoInfer<T> | NoInfer<StateOperator<T>>): StateOperator<T[]>;
98
248
 
99
249
  /**
100
- * @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
+ * Always returns a new array reference, even when no elements matched or the
255
+ * values produced by the operator are identical to the originals. Use
256
+ * `updateItem` instead when only a single element needs updating and
257
+ * referential equality on no-op updates matters.
258
+ *
259
+ * @param selector - Predicate used to decide which elements to update.
260
+ * @param operatorOrValue - Replacement value, or a state operator applied
261
+ * to each matching element when a derived update is needed.
262
+ *
263
+ * @example
264
+ * ```ts
265
+ * // Mark every inactive animal as active in one setState call.
266
+ * ctx.setState(
267
+ * patch<AnimalsStateModel>({
268
+ * animals: updateItems<Animal>(
269
+ * animal => !animal.active,
270
+ * patch({ active: true })
271
+ * )
272
+ * })
273
+ * );
274
+ * ```
275
+ */
276
+ declare function updateItems<T>(selector: NoInfer<Predicate<T>>, operatorOrValue: NoInfer<T> | NoInfer<StateOperator<T>>): (existing: ExistingState<T[]>) => T[];
277
+
278
+ /**
279
+ * Removes a single element from an array without mutating the original.
280
+ * Returns the original array reference when no matching item is found, so
281
+ * memoized selectors are not invalidated by a no-op removal.
282
+ *
283
+ * @param selector - The index to remove, or a predicate used to locate the
284
+ * item. Prefer a predicate when the item's position is not guaranteed to be
285
+ * stable across concurrent state updates.
286
+ *
287
+ * @example
288
+ * ```ts
289
+ * // Remove a panda by name — a predicate is safer than a hard-coded index
290
+ * // because the array order may change between dispatch and execution.
291
+ * ctx.setState(
292
+ * patch<AnimalsStateModel>({
293
+ * pandas: removeItem<string>(name => name === action.payload)
294
+ * })
295
+ * );
296
+ * ```
101
297
  */
102
298
  declare function removeItem<T>(selector: number | NoInfer<Predicate<T>>): StateOperator<T[]>;
103
299
 
104
- export { append, compose, iif, insertItem, isPredicate, isStateOperator, patch, removeItem, safePatch, updateItem };
300
+ export { append, compose, iif, insertItem, isPredicate, isStateOperator, patch, removeItem, safePatch, updateItem, updateItems };
105
301
  export type { ExistingState, NoInfer, Predicate, StateOperator, ɵPatchSpec };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngxs/store",
3
- "version": "21.0.0-dev.master-a4d1cfd",
3
+ "version": "21.0.0-dev.master-31acb66",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
@@ -18,14 +18,14 @@
18
18
  "types": "./index.d.ts",
19
19
  "default": "./fesm2022/ngxs-store.mjs"
20
20
  },
21
- "./experimental": {
22
- "types": "./experimental/index.d.ts",
23
- "default": "./fesm2022/ngxs-store-experimental.mjs"
24
- },
25
21
  "./internals": {
26
22
  "types": "./internals/index.d.ts",
27
23
  "default": "./fesm2022/ngxs-store-internals.mjs"
28
24
  },
25
+ "./experimental": {
26
+ "types": "./experimental/index.d.ts",
27
+ "default": "./fesm2022/ngxs-store-experimental.mjs"
28
+ },
29
29
  "./operators": {
30
30
  "types": "./operators/index.d.ts",
31
31
  "default": "./fesm2022/ngxs-store-operators.mjs"