maraj 2.5.1 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,19 +5,19 @@ A fast lightweight utility for creating **immutable updates**. Fully typed. Only
5
5
 
6
6
  ### Features
7
7
 
8
- - updateImmutably and modifyImmutably.
8
+ - Update and ExtendableUpdate.
9
+ - Usefull utilities like "remove", "select".
9
10
  - Full typescript support.
10
11
  - Correct type inference.
11
12
  - Multiple and concurrent updates.
12
- - Functional updates.
13
- - Includes usefull utilities like "remove", "select".
13
+ - Nested functional updates.
14
14
 
15
- **<u>_For Typescript:_</u>** in tsconfig.json set **"strictNullChecks"** and **"noUncheckedIndexedAccess"** to **true** to be able to infer correctly the type of optional properties and properties with posible undefined value. ({key?: ''} !== {key: '' | undefined})
15
+ <u>**For Typescript:**</u> in tsconfig.json set **"strictNullChecks"** and **"noUncheckedIndexedAccess"** to **true** to be able to infer correctly the type of optional properties and properties with posible undefined value. ({key?: ''} !== {key: '' | undefined})
16
16
 
17
17
  ```ts
18
18
  const originalValue = { name: 'one', lastname: 'two' modified: false, files: [{ filename: 'one' }] }
19
19
 
20
- const updatedValue = updateImmutably(orignalValue, {
20
+ const updatedValue = update(orignalValue, {
21
21
  'name': 'updated',
22
22
  'modified': (value, fullObject) => !value,
23
23
  'files.0.filename': 'zero',
@@ -25,7 +25,7 @@ const updatedValue = updateImmutably(orignalValue, {
25
25
  // updatedValue = { name: 'updated', lastname: 'two' modified: true, files: [{ filename: 'zero' }] }
26
26
  originalValue.files[1] === updatedValue.files[1] // true
27
27
 
28
- const newValue = modifyImmutably(orignalValue, {
28
+ const newValue = extendableUpdate(orignalValue, {
29
29
  'newProp': 'new',
30
30
  'data.0.name': 'dataName'
31
31
  })
@@ -35,23 +35,29 @@ originalValue.files[1] === newValue.files[1] // true
35
35
 
36
36
  ### Limitations
37
37
 
38
- - In "modifyImmutably", **numbers** inside path will **always** create an **array** if the array/object doesnt exist beforehand. If you want an object instead of an array, add it beforehand.
38
+ - Can work with keys containing dots ({ "this.is.dotted.key": 123 }), however those keys (keys containing dots) must exist in the object beforehand (hasOwnProperty) and also must have a non-literal-object/array value to behave properly; like primitives, sets, maps, and so on. For example the path "a.b.c.d" will work properly in the following scenarios:
39
+ - { "a.b.c.d": ... }
40
+ - { a: { "b.c.d": ... } }
41
+ - { a: { b: {"c.d": ... } } }
42
+ - { a: { b: {"c": { d: ... } } } }
43
+
44
+ - In "extendableUpdate", **numbers** inside path will **always** create a mutable **array** if the array/object doesnt exist beforehand. If you want an object/tuple/readonlyArray instead of an array, add it beforehand as type.
39
45
 
40
46
  ```ts
41
- const updatedValue = modifyImmutably({}, {
47
+ const updatedValue = extendableUpdate({}, {
42
48
  'files.1.name': 'new name',
43
49
  })
44
50
  // The "files" prop is an array. updatedValue = { files: [<empty>, { name: 'new name' }] }
45
51
 
46
52
  // To get an object instead of an array create an object beforehand
47
- const updatedValue2 = modifyImmutably({}, {
53
+ const updatedValue2 = extendableUpdate({}, {
48
54
  'files': {}, // add an object first, so then i can add props as numbers after it
49
55
  'files.1.name': 'new name',
50
56
  })
51
57
  // updatedValue2 = { files: { '1': { name: 'new name' } } }
52
58
  ```
53
59
 
54
- - The type "UpdateDotPathObject" (the type used as second parameter in the updateImmutably function) if used to create new update objects using computed properties { [key]: value } will always throw a ts error even if the typing is correct. [Playground simple explanation](https://www.typescriptlang.org/play?ts=5.3.2#code/LAKALgngDgpgBAGQJYGcxwLxwOQENtwA+cABgCQDeAdgK4C2ARjAE4C+JooksiqYASjADGAe2YATTHApwA2gGk4SKrzQBdAPwAuOItacQoqmjhDmMXGBiDREqQB4AKnBgAPK1XEpVYAHwAKAGsYCB1HAEpMX2lQODijE3MhHWQ0GzFJLApYuNyAejy4AD0wbxZmMR0UZSF4ADcAFgA6AGYmgFYldAB3JAAbPrgwAAsK7rhcFXKxCfQhYeFA5QBzUxE6KBorSWCIb0nJOtw+mhhvGmqqVasNvst4PqQrZmOyupgVJAAzIYWh6BWSm8tiSYByuTkuzUOl24P0IFy5jANGYKiSoFYQA)
60
+ - The type "UpdateDotPathObject" (the type of the object provided containing the updates, the one used as second parameter in the update function) if used to create new update objects using computed properties { [key]: value } (middlewares for example) will always throw a ts error even if the typing is correct. [Playground simple explanation](https://www.typescriptlang.org/play?ts=5.3.2#code/LAKALgngDgpgBAGQJYGcxwLxwOQENtwA+cABgCQDeAdgK4C2ARjAE4C+JooksiqYASjADGAe2YATTHApwA2gGk4SKrzQBdAPwAuOItacQoqmjhDmMXGBiDREqQB4AKnBgAPK1XEpVYAHwAKAGsYCB1HAEpMX2lQODijE3MhHWQ0GzFJLApYuNyAejy4AD0wbxZmMR0UZSF4ADcAFgA6AGYmgFYldAB3JAAbPrgwAAsK7rhcFXKxCfQhYeFA5QBzUxE6KBorSWCIb0nJOtw+mhhvGmqqVasNvst4PqQrZmOyupgVJAAzIYWh6BWSm8tiSYByuTkuzUOl24P0IFy5jANGYKiSoFYQA)
55
61
 
56
62
  ```ts
57
63
  const updateFieldStore = <TPath extends DotPaths<Store>>(
@@ -69,7 +75,7 @@ const updateFieldStore = <TPath extends DotPaths<Store>>(
69
75
  - Use the "set" utility if typescript doesn't infer properly _"an optional field"_ vs a _"field which can have 'undefined' as type"_. Usually happens in optional nested props inside arrays.
70
76
 
71
77
  ```ts
72
- const updatedValue = updateImmutably(data, {
78
+ const updatedValue = update(data, {
73
79
  'files.0.nonOptionalProperty': 'new name',
74
80
  'files.1.nonOptionalProperty': undefined, //no ts error
75
81
  'files.0.nonOptionalProperty': set('new name'),
@@ -83,11 +89,15 @@ Arguments:
83
89
 
84
90
  - Original Object
85
91
  - Update Object
92
+ - Options (to change JS behaviour on non existing props and indexes)
93
+ - 'add': Adds non existing property/index.
94
+ - 'skip': Skips the update in the non-existing prop/index and still applies the rest of the possible updates.
95
+ - 'throw': Throws a JS error, usefull working with indexes making sure there are no "empty" indexes created if a new index is added which is bigger than the length of the current array.
86
96
 
87
97
  ## Example
88
98
 
89
99
  ```js
90
- import { updateImmutably } from "maraj";
100
+ import { update } from "maraj";
91
101
 
92
102
  const data = {
93
103
  profile: { name: "Lukasz" },
@@ -98,7 +108,7 @@ const data = {
98
108
  ]
99
109
  }
100
110
 
101
- const newUpdatedObject = updateImmutably(data, {
111
+ const newUpdatedObject = update(data, {
102
112
  "profile.name": "Lucas", //update values
103
113
  "works.1": "gs", //nested array update
104
114
  "history.1.available": (currentValue) => (!currentValue), //functional update
@@ -116,7 +126,7 @@ Arguments:
116
126
  ## Example
117
127
 
118
128
  ```js
119
- import { modifyImmutably } from "maraj";
129
+ import { extendableUpdate } from "maraj";
120
130
 
121
131
  const data = {
122
132
  profile: { name: "Lukasz" },
@@ -127,7 +137,7 @@ const data = {
127
137
  ]
128
138
  }
129
139
 
130
- const newUpdatedObject = modifyImmutably(data, {
140
+ const newUpdatedObject = extendableUpdate(data, {
131
141
  "profile.age": 28, //add new property
132
142
  "profile.name": "Lucas", //update values
133
143
  "works.10": "gs", //increases the array (filling it up with empty/undefined) and sets the value in the index of 10 to "gs"
@@ -136,12 +146,12 @@ const newUpdatedObject = modifyImmutably(data, {
136
146
 
137
147
  ## Remove Utility
138
148
 
139
- Removes the **key of an object** or the **index of an array** in the key provided in the **updateImmutably.**
149
+ Removes the **key of an object** or the **index of an array** in the key provided in the **update.**
140
150
 
141
151
  ```js
142
152
  import {remove} from 'maraj'
143
153
 
144
- const newUpdatedObject = updateImmutably(person,{
154
+ const newUpdatedObject = update(person,{
145
155
  'profile': (value) => remove(value, 'name'), // returns new value without the "name" prop
146
156
  'profile': (value) => remove(value, ['name', 'lastname']), // returns new value without the "name" and "lastname" prop
147
157
  'works': (value) => remove(value, 1), // returns new array without the provided index (1)
@@ -185,7 +195,7 @@ const [remainingPath, lastKey] = splitPathAtLastKey(stringPath)
185
195
  In some unusual cases (usually when updating an optional object prop inside an array) typescript infers incorrectly the optional key vs a key with undefined value. To fix this typing issue, use the "set" function so it correctly infers the type in the field.
186
196
 
187
197
  ```ts
188
- const updatedValue = updateImmutably(data, {
198
+ const updatedValue = update(data, {
189
199
  'files.0.optionalProperty': 'new name',
190
200
  'files.1.optionalProperty': undefined, //no ts error
191
201
  'files.0.optionalProperty': set('new name'),
package/dist/index.d.mts CHANGED
@@ -1,24 +1,46 @@
1
+ /** Returns only the optional keys of an object. */
2
+ type OptionalKeys<T> = {
3
+ [K in keyof T]-?: {} extends Pick<T, K> ? K : never;
4
+ }[keyof T];
5
+ /** Removes properties or indexes, order doesn't matter. */
6
+ type Remove = <T extends object>(value: T, keys: T extends any[] ? (number | `${number}` | (number | `${number}`)[]) : OptionalKeys<T> | (OptionalKeys<T>)[]) => T;
7
+ /**
8
+ * Removes properties or indexes, order doesn't matter.
9
+ * @param value Object/array from where to remove keys/indexes shallowly.
10
+ * @param keys Keys to remove.
11
+ * @returns New object/array without the provided keys/indexes.
12
+ */
13
+ declare const remove: Remove;
14
+
1
15
  /** Index literal type to improve DX at managing updates. */
2
16
  declare const LITERAL_INDEX = "${number}";
3
17
  type LiteralIndex = typeof LITERAL_INDEX;
4
- type UpdateImmutably = <T extends object>(state: T, updates: DotPathUpdateObject<T>) => T;
18
+ type OptionValues = 'error' | 'skip' | 'add';
19
+ type Options = {
20
+ onNewProps?: OptionValues;
21
+ onNewIndexes?: OptionValues;
22
+ };
23
+ type ImmutableUpdate = <TObject extends Record<PropertyKey, any>>(state: TObject, dotPathUpdateObject: UpdateObject<TObject>, options?: Options) => TObject;
5
24
  /**
6
- * Creates a new object applying strict immutable updates using dot-path syntax. Can't add new props or indexes.
25
+ * Creates a new object applying immutable updates using dot-path syntax.
26
+ * Can add or skip new props or indexes depending on options.
27
+ * TYPESCRIPT: Dot-Path Update Object type must STRICTLY match the type of state.
7
28
  * @param state Original State Object.
8
- * @param updates Dot Path Update Object.
9
- * @param addNonExistentPropsAndIndexes If it should or not create non-existent fields.
29
+ * @param dotPathUpdateObject Dot Path Update Object.
30
+ * @param options Options to change JS behaviour on non-existent fields.
10
31
  * @returns New Updated Object.
11
32
  */
12
- declare const updateImmutably: UpdateImmutably;
13
- type ModifyImmutably = <T extends object>(state: T, updates: DotPathUpdateObject<T> | Record<string, any>) => T;
33
+ declare const update: ImmutableUpdate;
34
+ type ExtendableImmutableUpdate = <TObject extends Record<PropertyKey, any>, TUpdateObject extends UpdateObject<TObject>>(state: TObject, dotPathUpdateObject: TUpdateObject) => ExtendedUpdate<TObject, TUpdateObject>;
14
35
  /**
15
- * Creates a new object applying immutable modifications using dot-path syntax. It will add non-existent props or indexes if provided.
36
+ * Creates a new object applying immutable updates using dot-path syntax.
37
+ * It will always add non-existent props or indexes if provided.
38
+ * TYPESCRIPT: Dot-Path Update Object type extends from the type of state and you can add new non-existent properties.
16
39
  * @param state Original State Object.
17
- * @param updates Dot Path Update Object.
18
- * @param addNonExistentPropsAndIndexes If it should or not create non-existent fields.
40
+ * @param dotPathUpdateObject Dot Path Update Object.
19
41
  * @returns New Updated Object.
20
42
  */
21
- declare const modifyImmutably: ModifyImmutably;
43
+ declare const extendableUpdate: ExtendableImmutableUpdate;
22
44
 
23
45
  /**
24
46
  * --------------------------------------------
@@ -37,11 +59,11 @@ type IsTuple<T extends ReadonlyArray<any>> = number extends T['length'] ? false
37
59
  * --------------------------------------------
38
60
  */
39
61
  /** Dot-paths of an array. */
40
- type ArrayPaths<TInnerType, TAllowedTypes> = TInnerType extends TAllowedTypes ? TInnerType extends PrimitivesAndNativeObjects ? `${ArrayIndexes}` : `${ArrayIndexes}` | `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}` : `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}`;
62
+ type ArrayPaths<TInnerType, TAllowedTypes> = TInnerType extends TAllowedTypes ? TInnerType extends PrimitivesAndNativeObjects ? number | `${ArrayIndexes}` : number | `${ArrayIndexes}` | `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}` : `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}`;
41
63
  /** Dot-paths of an object. */
42
64
  type ObjectPaths<T, TAllowedTypes> = {
43
- [Key in keyof T & string]: T[Key] extends TAllowedTypes ? T[Key] extends PrimitivesAndNativeObjects ? `${Key}` : `${Key}` | `${Key}.${DotPaths<T[Key], TAllowedTypes>}` : `${Key}.${DotPaths<T[Key], TAllowedTypes>}`;
44
- }[keyof T & string];
65
+ [Key in keyof T & (string | number)]: T[Key] extends TAllowedTypes ? T[Key] extends PrimitivesAndNativeObjects ? `${Key}` : `${Key}` | `${Key}.${DotPaths<T[Key], TAllowedTypes>}` : `${Key}.${DotPaths<T[Key], TAllowedTypes>}`;
66
+ }[keyof T & (string | number)];
45
67
  /** Dot-paths of a tuple. */
46
68
  type TuplePaths<T, TAllowedTypes> = ObjectPaths<Omit<T, keyof any[]>, TAllowedTypes>;
47
69
  /** Literal union of all posible dot-paths which satisfy provided types as second argument (default: any). */
@@ -52,53 +74,70 @@ type DotPaths<T, TAllowedTypes = any> = T extends ReadonlyArray<infer U> ? IsTup
52
74
  * --------------------------------------------
53
75
  */
54
76
  /** Nested type implementation. */
55
- type NestedType<TObject, TPath> = TPath extends '' ? TObject : TPath extends keyof TObject ? TObject[TPath] : TPath extends LiteralIndex ? never : TPath extends `${number}` ? TObject extends ReadonlyArray<infer U> ? U : never : TPath extends `${infer K}.${infer R}` ? K extends keyof TObject ? NestedType<TObject[K], R> : K extends LiteralIndex ? never : K extends `${number}` ? TObject extends ReadonlyArray<infer U> ? NestedType<U, R> : never : never : never;
56
- /** Value of a nested property of a given dot-path. */
57
- type ValueInDotPath<TObject, TPath extends DotPaths<TObject> | ''> = NestedType<TObject, TPath>;
77
+ type ValueInPath<TObject, TPath> = TPath extends '' ? TObject : TPath extends keyof TObject ? TObject[TPath] : TPath extends LiteralIndex ? never : TPath extends `${number}` ? TObject extends ReadonlyArray<infer U> ? U : never : TPath extends `${infer K}.${infer R}` ? K extends keyof TObject ? ValueInPath<TObject[K], R> : K extends LiteralIndex ? never : K extends `${number}` ? TObject extends ReadonlyArray<infer U> ? ValueInPath<U, R> : never : never : never;
58
78
  /**
59
79
  * --------------------------------------------
60
80
  * RETURNED VALUE OF A NESTED PROPERTY PROVIDING A DOT PATH
61
81
  * --------------------------------------------
62
82
  */
63
83
  /** Returned nested type implementation. */
64
- type ReturnedNestedValue<TObject, TPath> = TPath extends '' ? TObject : TPath extends keyof TObject ? TObject[TPath] : TPath extends LiteralIndex ? never : TPath extends `${number}` ? TObject extends ReadonlyArray<infer U> ? (U | undefined) : never : TPath extends `${infer K}.${infer R}` ? K extends keyof TObject ? ReturnedNestedValue<TObject[K], R> : K extends LiteralIndex ? never : K extends `${number}` ? TObject extends ReadonlyArray<infer U> ? (ReturnedNestedValue<U, R> | undefined) : never : never : never;
65
- /** Value of a RETURNED nested property of a given dot-path (so when accessing arrays can be undefined). */
66
- type ReturnedValueInDotPath<TObject, TPath extends DotPaths<TObject> | ''> = ReturnedNestedValue<TObject, TPath>;
84
+ type ReturnedValueInPath<TObject, TPath> = TPath extends '' ? TObject : TPath extends keyof TObject ? TPath extends number ? TObject extends ReadonlyArray<infer U> ? (U | undefined) : TObject[TPath] : TObject[TPath] : TPath extends `${number}` ? TObject extends ReadonlyArray<infer U> ? (U | undefined) : never : TPath extends LiteralIndex ? never : TPath extends `${infer K}.${infer R}` ? K extends keyof TObject ? ReturnedValueInPath<TObject[K], R> : K extends LiteralIndex ? never : K extends `${number}` ? TObject extends ReadonlyArray<infer U> ? (ReturnedValueInPath<U, R> | undefined) : never : never : never;
67
85
  /**
68
86
  * --------------------------------------------
69
87
  * UPDATE OBJECT WITH DOT PATH IMPLEMENTATION
70
88
  * --------------------------------------------
71
89
  */
72
90
  /** Value of a dot-path update object, can be the value or a function. */
73
- type DotPathUpdateValue<TObject, TPath extends DotPaths<TObject>> = ValueInDotPath<TObject, TPath> | ((fieldValue: ValueInDotPath<TObject, TPath>, fullObject: TObject) => ValueInDotPath<TObject, TPath>);
91
+ type UpdateValue<TObject, TPath> = ValueInPath<TObject, TPath> | ((fieldValue: ValueInPath<TObject, TPath>) => ValueInPath<TObject, TPath>);
74
92
  /** Dot-path update object, used to give updates to the updateImmutably function. */
75
- type DotPathUpdateObject<TObject> = {
76
- [TPath in DotPaths<TObject>]?: ValueInDotPath<TObject, TPath> | ((fieldValue: ValueInDotPath<TObject, TPath>, fullObject: TObject) => ValueInDotPath<TObject, TPath>);
93
+ type UpdateObject<TObject> = {
94
+ [TPath in DotPaths<TObject>]?: ValueInPath<TObject, TPath> | ((fieldValue: ValueInPath<TObject, TPath>) => ValueInPath<TObject, TPath>);
77
95
  };
78
96
  /**
79
97
  * --------------------------------------------
80
- * REQUIRED OR OPTIONAL KEYS
98
+ * EXTRACT TYPE FROM DOT-PATH UPDATE OBJECT
81
99
  * --------------------------------------------
82
100
  */
83
- /** Returns only the optional keys of an object. */
84
- type OptionalKeys<T> = {
85
- [K in keyof T]-?: {} extends Pick<T, K> ? K : never;
101
+ /** Merging two objects */
102
+ /** Keys which arent dot-path keys */
103
+ type NonDotPathKeys<T> = {
104
+ [Key in keyof T]: Key extends `${infer K}.${string}` ? K : Key;
86
105
  }[keyof T];
87
- /** Returns only the required keys of an object. */
88
- type RequiredKeys<T> = {
89
- [K in keyof T]-?: {} extends Pick<T, K> ? never : K;
106
+ /** Keys which are an index */
107
+ type KeysRepresentingAnIndex<T> = {
108
+ [Key in keyof T]: Key extends `${number}.${string}` ? never : Key;
90
109
  }[keyof T];
110
+ /** Keys which start with an index */
111
+ type KeyPathsStartingWithAnIndex<T> = {
112
+ [Key in keyof T]: Key extends `${number}.${string}` ? Key : never;
113
+ }[keyof T];
114
+ /** Keys which are paths and its first key-path is removed */
115
+ type NestedPathKeys<T, K extends string | number> = {
116
+ [Key in keyof T]: Key extends `${K}.${infer U}` ? U : never;
117
+ }[keyof T];
118
+ /** Extract value if its a function */
119
+ type Value<T> = T extends (...args: any) => any ? ReturnType<T> : T;
120
+ /** To check if an empty object is provided */
121
+ type EmptyObject = Record<string | number | symbol, never>;
122
+ /** Used to extract the type from a dot-path update object. */
123
+ type ExtractTypeFromDotPathUpdateObject<T extends Record<string, any>> = T extends EmptyObject ? {} : keyof T extends LiteralIndex | number | `${number}` | `${number}.${infer U}` ? Value<T[KeyPathsStartingWithAnIndex<T>]> extends never ? Array<Value<T[KeysRepresentingAnIndex<T>]>> : Array<Value<T[KeysRepresentingAnIndex<T>]> | {
124
+ [Key2 in U]: Value<T[KeyPathsStartingWithAnIndex<T>]>;
125
+ }> : {
126
+ [Key1 in NonDotPathKeys<T> & string]: Key1 extends keyof T ? Value<T[Key1]> extends Array<infer U> ? ExtractTypeFromDotPathUpdateObject<{
127
+ [Key2 in NestedPathKeys<T, Key1>]: Value<T[`${Key1}.${Key2}`]>;
128
+ }> extends Array<infer W> ? Array<U | W> : Array<U> & ExtractTypeFromDotPathUpdateObject<{
129
+ [Key2 in NestedPathKeys<T, Key1>]: Value<T[`${Key1}.${Key2}`]>;
130
+ }> : Value<T[Key1]> : ExtractTypeFromDotPathUpdateObject<{
131
+ [Key2 in NestedPathKeys<T, Key1>]: Value<T[`${Key1}.${Key2}`]>;
132
+ }>;
133
+ } & unknown;
134
+ /** New expanded value after aplying updates including new properties */
135
+ type ExtendedUpdate<TObject extends Record<string | number | symbol, any>, TDotPathUpdateObject extends Record<string | number | symbol, any>> = TObject extends Array<infer U> ? ExtractTypeFromDotPathUpdateObject<TDotPathUpdateObject> extends Array<infer W> ? Array<U | W> : TObject & ExtractTypeFromDotPathUpdateObject<TDotPathUpdateObject> : ExtractTypeFromDotPathUpdateObject<TObject & TDotPathUpdateObject>;
91
136
 
92
- type Remove = <T extends object>(value: T, keys: T extends any[] ? (number | `${number}` | (number | `${number}`)[]) : OptionalKeys<T> | (OptionalKeys<T>)[]) => T;
93
- /**
94
- * Removes properties or indexes, order doesn't matter.
95
- * @param value Object/array from where to remove keys/indexes shallowly.
96
- * @param keys Keys to remove.
97
- * @returns New object/array without the provided keys/indexes.
98
- */
99
- declare const remove: Remove;
100
-
101
- type Select = <TObject, TPath extends DotPaths<TObject> | ''>(state: TObject, path: TPath) => ReturnedValueInDotPath<TObject, TPath>;
137
+ type Select = {
138
+ <T, TPath extends DotPaths<T>>(state: T, path: TPath): ReturnedValueInPath<T, TPath>;
139
+ <T, TPath extends ''>(state: T, path: TPath): T;
140
+ };
102
141
  /**
103
142
  * Returns the value from a given dot path of an object/array or undefined if doesn't exist.
104
143
  * @param state State from which retrieve the value.
@@ -131,4 +170,4 @@ declare const isObjectLiteral: (valueToTest: any) => boolean;
131
170
  declare const parseStringIndex: (v: string) => number | null;
132
171
  declare const isStringIndex: (v: string) => boolean;
133
172
 
134
- export { type DotPathUpdateObject, type DotPathUpdateValue, type DotPaths, type OptionalKeys, type PrimitivesAndNativeObjects, type RequiredKeys, type ReturnedValueInDotPath, type ValueInDotPath, isObjectLiteral, isStringIndex, modifyImmutably, parseStringIndex, remove, select, set, splitPathAtLastKey, updateImmutably };
173
+ export { type DotPaths, type LiteralIndex, type ReturnedValueInPath, type UpdateObject, type UpdateValue, type ValueInPath, extendableUpdate, isObjectLiteral, isStringIndex, parseStringIndex, remove, select, set, splitPathAtLastKey, update };
package/dist/index.d.ts CHANGED
@@ -1,24 +1,46 @@
1
+ /** Returns only the optional keys of an object. */
2
+ type OptionalKeys<T> = {
3
+ [K in keyof T]-?: {} extends Pick<T, K> ? K : never;
4
+ }[keyof T];
5
+ /** Removes properties or indexes, order doesn't matter. */
6
+ type Remove = <T extends object>(value: T, keys: T extends any[] ? (number | `${number}` | (number | `${number}`)[]) : OptionalKeys<T> | (OptionalKeys<T>)[]) => T;
7
+ /**
8
+ * Removes properties or indexes, order doesn't matter.
9
+ * @param value Object/array from where to remove keys/indexes shallowly.
10
+ * @param keys Keys to remove.
11
+ * @returns New object/array without the provided keys/indexes.
12
+ */
13
+ declare const remove: Remove;
14
+
1
15
  /** Index literal type to improve DX at managing updates. */
2
16
  declare const LITERAL_INDEX = "${number}";
3
17
  type LiteralIndex = typeof LITERAL_INDEX;
4
- type UpdateImmutably = <T extends object>(state: T, updates: DotPathUpdateObject<T>) => T;
18
+ type OptionValues = 'error' | 'skip' | 'add';
19
+ type Options = {
20
+ onNewProps?: OptionValues;
21
+ onNewIndexes?: OptionValues;
22
+ };
23
+ type ImmutableUpdate = <TObject extends Record<PropertyKey, any>>(state: TObject, dotPathUpdateObject: UpdateObject<TObject>, options?: Options) => TObject;
5
24
  /**
6
- * Creates a new object applying strict immutable updates using dot-path syntax. Can't add new props or indexes.
25
+ * Creates a new object applying immutable updates using dot-path syntax.
26
+ * Can add or skip new props or indexes depending on options.
27
+ * TYPESCRIPT: Dot-Path Update Object type must STRICTLY match the type of state.
7
28
  * @param state Original State Object.
8
- * @param updates Dot Path Update Object.
9
- * @param addNonExistentPropsAndIndexes If it should or not create non-existent fields.
29
+ * @param dotPathUpdateObject Dot Path Update Object.
30
+ * @param options Options to change JS behaviour on non-existent fields.
10
31
  * @returns New Updated Object.
11
32
  */
12
- declare const updateImmutably: UpdateImmutably;
13
- type ModifyImmutably = <T extends object>(state: T, updates: DotPathUpdateObject<T> | Record<string, any>) => T;
33
+ declare const update: ImmutableUpdate;
34
+ type ExtendableImmutableUpdate = <TObject extends Record<PropertyKey, any>, TUpdateObject extends UpdateObject<TObject>>(state: TObject, dotPathUpdateObject: TUpdateObject) => ExtendedUpdate<TObject, TUpdateObject>;
14
35
  /**
15
- * Creates a new object applying immutable modifications using dot-path syntax. It will add non-existent props or indexes if provided.
36
+ * Creates a new object applying immutable updates using dot-path syntax.
37
+ * It will always add non-existent props or indexes if provided.
38
+ * TYPESCRIPT: Dot-Path Update Object type extends from the type of state and you can add new non-existent properties.
16
39
  * @param state Original State Object.
17
- * @param updates Dot Path Update Object.
18
- * @param addNonExistentPropsAndIndexes If it should or not create non-existent fields.
40
+ * @param dotPathUpdateObject Dot Path Update Object.
19
41
  * @returns New Updated Object.
20
42
  */
21
- declare const modifyImmutably: ModifyImmutably;
43
+ declare const extendableUpdate: ExtendableImmutableUpdate;
22
44
 
23
45
  /**
24
46
  * --------------------------------------------
@@ -37,11 +59,11 @@ type IsTuple<T extends ReadonlyArray<any>> = number extends T['length'] ? false
37
59
  * --------------------------------------------
38
60
  */
39
61
  /** Dot-paths of an array. */
40
- type ArrayPaths<TInnerType, TAllowedTypes> = TInnerType extends TAllowedTypes ? TInnerType extends PrimitivesAndNativeObjects ? `${ArrayIndexes}` : `${ArrayIndexes}` | `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}` : `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}`;
62
+ type ArrayPaths<TInnerType, TAllowedTypes> = TInnerType extends TAllowedTypes ? TInnerType extends PrimitivesAndNativeObjects ? number | `${ArrayIndexes}` : number | `${ArrayIndexes}` | `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}` : `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}`;
41
63
  /** Dot-paths of an object. */
42
64
  type ObjectPaths<T, TAllowedTypes> = {
43
- [Key in keyof T & string]: T[Key] extends TAllowedTypes ? T[Key] extends PrimitivesAndNativeObjects ? `${Key}` : `${Key}` | `${Key}.${DotPaths<T[Key], TAllowedTypes>}` : `${Key}.${DotPaths<T[Key], TAllowedTypes>}`;
44
- }[keyof T & string];
65
+ [Key in keyof T & (string | number)]: T[Key] extends TAllowedTypes ? T[Key] extends PrimitivesAndNativeObjects ? `${Key}` : `${Key}` | `${Key}.${DotPaths<T[Key], TAllowedTypes>}` : `${Key}.${DotPaths<T[Key], TAllowedTypes>}`;
66
+ }[keyof T & (string | number)];
45
67
  /** Dot-paths of a tuple. */
46
68
  type TuplePaths<T, TAllowedTypes> = ObjectPaths<Omit<T, keyof any[]>, TAllowedTypes>;
47
69
  /** Literal union of all posible dot-paths which satisfy provided types as second argument (default: any). */
@@ -52,53 +74,70 @@ type DotPaths<T, TAllowedTypes = any> = T extends ReadonlyArray<infer U> ? IsTup
52
74
  * --------------------------------------------
53
75
  */
54
76
  /** Nested type implementation. */
55
- type NestedType<TObject, TPath> = TPath extends '' ? TObject : TPath extends keyof TObject ? TObject[TPath] : TPath extends LiteralIndex ? never : TPath extends `${number}` ? TObject extends ReadonlyArray<infer U> ? U : never : TPath extends `${infer K}.${infer R}` ? K extends keyof TObject ? NestedType<TObject[K], R> : K extends LiteralIndex ? never : K extends `${number}` ? TObject extends ReadonlyArray<infer U> ? NestedType<U, R> : never : never : never;
56
- /** Value of a nested property of a given dot-path. */
57
- type ValueInDotPath<TObject, TPath extends DotPaths<TObject> | ''> = NestedType<TObject, TPath>;
77
+ type ValueInPath<TObject, TPath> = TPath extends '' ? TObject : TPath extends keyof TObject ? TObject[TPath] : TPath extends LiteralIndex ? never : TPath extends `${number}` ? TObject extends ReadonlyArray<infer U> ? U : never : TPath extends `${infer K}.${infer R}` ? K extends keyof TObject ? ValueInPath<TObject[K], R> : K extends LiteralIndex ? never : K extends `${number}` ? TObject extends ReadonlyArray<infer U> ? ValueInPath<U, R> : never : never : never;
58
78
  /**
59
79
  * --------------------------------------------
60
80
  * RETURNED VALUE OF A NESTED PROPERTY PROVIDING A DOT PATH
61
81
  * --------------------------------------------
62
82
  */
63
83
  /** Returned nested type implementation. */
64
- type ReturnedNestedValue<TObject, TPath> = TPath extends '' ? TObject : TPath extends keyof TObject ? TObject[TPath] : TPath extends LiteralIndex ? never : TPath extends `${number}` ? TObject extends ReadonlyArray<infer U> ? (U | undefined) : never : TPath extends `${infer K}.${infer R}` ? K extends keyof TObject ? ReturnedNestedValue<TObject[K], R> : K extends LiteralIndex ? never : K extends `${number}` ? TObject extends ReadonlyArray<infer U> ? (ReturnedNestedValue<U, R> | undefined) : never : never : never;
65
- /** Value of a RETURNED nested property of a given dot-path (so when accessing arrays can be undefined). */
66
- type ReturnedValueInDotPath<TObject, TPath extends DotPaths<TObject> | ''> = ReturnedNestedValue<TObject, TPath>;
84
+ type ReturnedValueInPath<TObject, TPath> = TPath extends '' ? TObject : TPath extends keyof TObject ? TPath extends number ? TObject extends ReadonlyArray<infer U> ? (U | undefined) : TObject[TPath] : TObject[TPath] : TPath extends `${number}` ? TObject extends ReadonlyArray<infer U> ? (U | undefined) : never : TPath extends LiteralIndex ? never : TPath extends `${infer K}.${infer R}` ? K extends keyof TObject ? ReturnedValueInPath<TObject[K], R> : K extends LiteralIndex ? never : K extends `${number}` ? TObject extends ReadonlyArray<infer U> ? (ReturnedValueInPath<U, R> | undefined) : never : never : never;
67
85
  /**
68
86
  * --------------------------------------------
69
87
  * UPDATE OBJECT WITH DOT PATH IMPLEMENTATION
70
88
  * --------------------------------------------
71
89
  */
72
90
  /** Value of a dot-path update object, can be the value or a function. */
73
- type DotPathUpdateValue<TObject, TPath extends DotPaths<TObject>> = ValueInDotPath<TObject, TPath> | ((fieldValue: ValueInDotPath<TObject, TPath>, fullObject: TObject) => ValueInDotPath<TObject, TPath>);
91
+ type UpdateValue<TObject, TPath> = ValueInPath<TObject, TPath> | ((fieldValue: ValueInPath<TObject, TPath>) => ValueInPath<TObject, TPath>);
74
92
  /** Dot-path update object, used to give updates to the updateImmutably function. */
75
- type DotPathUpdateObject<TObject> = {
76
- [TPath in DotPaths<TObject>]?: ValueInDotPath<TObject, TPath> | ((fieldValue: ValueInDotPath<TObject, TPath>, fullObject: TObject) => ValueInDotPath<TObject, TPath>);
93
+ type UpdateObject<TObject> = {
94
+ [TPath in DotPaths<TObject>]?: ValueInPath<TObject, TPath> | ((fieldValue: ValueInPath<TObject, TPath>) => ValueInPath<TObject, TPath>);
77
95
  };
78
96
  /**
79
97
  * --------------------------------------------
80
- * REQUIRED OR OPTIONAL KEYS
98
+ * EXTRACT TYPE FROM DOT-PATH UPDATE OBJECT
81
99
  * --------------------------------------------
82
100
  */
83
- /** Returns only the optional keys of an object. */
84
- type OptionalKeys<T> = {
85
- [K in keyof T]-?: {} extends Pick<T, K> ? K : never;
101
+ /** Merging two objects */
102
+ /** Keys which arent dot-path keys */
103
+ type NonDotPathKeys<T> = {
104
+ [Key in keyof T]: Key extends `${infer K}.${string}` ? K : Key;
86
105
  }[keyof T];
87
- /** Returns only the required keys of an object. */
88
- type RequiredKeys<T> = {
89
- [K in keyof T]-?: {} extends Pick<T, K> ? never : K;
106
+ /** Keys which are an index */
107
+ type KeysRepresentingAnIndex<T> = {
108
+ [Key in keyof T]: Key extends `${number}.${string}` ? never : Key;
90
109
  }[keyof T];
110
+ /** Keys which start with an index */
111
+ type KeyPathsStartingWithAnIndex<T> = {
112
+ [Key in keyof T]: Key extends `${number}.${string}` ? Key : never;
113
+ }[keyof T];
114
+ /** Keys which are paths and its first key-path is removed */
115
+ type NestedPathKeys<T, K extends string | number> = {
116
+ [Key in keyof T]: Key extends `${K}.${infer U}` ? U : never;
117
+ }[keyof T];
118
+ /** Extract value if its a function */
119
+ type Value<T> = T extends (...args: any) => any ? ReturnType<T> : T;
120
+ /** To check if an empty object is provided */
121
+ type EmptyObject = Record<string | number | symbol, never>;
122
+ /** Used to extract the type from a dot-path update object. */
123
+ type ExtractTypeFromDotPathUpdateObject<T extends Record<string, any>> = T extends EmptyObject ? {} : keyof T extends LiteralIndex | number | `${number}` | `${number}.${infer U}` ? Value<T[KeyPathsStartingWithAnIndex<T>]> extends never ? Array<Value<T[KeysRepresentingAnIndex<T>]>> : Array<Value<T[KeysRepresentingAnIndex<T>]> | {
124
+ [Key2 in U]: Value<T[KeyPathsStartingWithAnIndex<T>]>;
125
+ }> : {
126
+ [Key1 in NonDotPathKeys<T> & string]: Key1 extends keyof T ? Value<T[Key1]> extends Array<infer U> ? ExtractTypeFromDotPathUpdateObject<{
127
+ [Key2 in NestedPathKeys<T, Key1>]: Value<T[`${Key1}.${Key2}`]>;
128
+ }> extends Array<infer W> ? Array<U | W> : Array<U> & ExtractTypeFromDotPathUpdateObject<{
129
+ [Key2 in NestedPathKeys<T, Key1>]: Value<T[`${Key1}.${Key2}`]>;
130
+ }> : Value<T[Key1]> : ExtractTypeFromDotPathUpdateObject<{
131
+ [Key2 in NestedPathKeys<T, Key1>]: Value<T[`${Key1}.${Key2}`]>;
132
+ }>;
133
+ } & unknown;
134
+ /** New expanded value after aplying updates including new properties */
135
+ type ExtendedUpdate<TObject extends Record<string | number | symbol, any>, TDotPathUpdateObject extends Record<string | number | symbol, any>> = TObject extends Array<infer U> ? ExtractTypeFromDotPathUpdateObject<TDotPathUpdateObject> extends Array<infer W> ? Array<U | W> : TObject & ExtractTypeFromDotPathUpdateObject<TDotPathUpdateObject> : ExtractTypeFromDotPathUpdateObject<TObject & TDotPathUpdateObject>;
91
136
 
92
- type Remove = <T extends object>(value: T, keys: T extends any[] ? (number | `${number}` | (number | `${number}`)[]) : OptionalKeys<T> | (OptionalKeys<T>)[]) => T;
93
- /**
94
- * Removes properties or indexes, order doesn't matter.
95
- * @param value Object/array from where to remove keys/indexes shallowly.
96
- * @param keys Keys to remove.
97
- * @returns New object/array without the provided keys/indexes.
98
- */
99
- declare const remove: Remove;
100
-
101
- type Select = <TObject, TPath extends DotPaths<TObject> | ''>(state: TObject, path: TPath) => ReturnedValueInDotPath<TObject, TPath>;
137
+ type Select = {
138
+ <T, TPath extends DotPaths<T>>(state: T, path: TPath): ReturnedValueInPath<T, TPath>;
139
+ <T, TPath extends ''>(state: T, path: TPath): T;
140
+ };
102
141
  /**
103
142
  * Returns the value from a given dot path of an object/array or undefined if doesn't exist.
104
143
  * @param state State from which retrieve the value.
@@ -131,4 +170,4 @@ declare const isObjectLiteral: (valueToTest: any) => boolean;
131
170
  declare const parseStringIndex: (v: string) => number | null;
132
171
  declare const isStringIndex: (v: string) => boolean;
133
172
 
134
- export { type DotPathUpdateObject, type DotPathUpdateValue, type DotPaths, type OptionalKeys, type PrimitivesAndNativeObjects, type RequiredKeys, type ReturnedValueInDotPath, type ValueInDotPath, isObjectLiteral, isStringIndex, modifyImmutably, parseStringIndex, remove, select, set, splitPathAtLastKey, updateImmutably };
173
+ export { type DotPaths, type LiteralIndex, type ReturnedValueInPath, type UpdateObject, type UpdateValue, type ValueInPath, extendableUpdate, isObjectLiteral, isStringIndex, parseStringIndex, remove, select, set, splitPathAtLastKey, update };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var b=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var E=Object.prototype.hasOwnProperty;var R=(t,e)=>{for(var r in e)b(t,r,{get:e[r],enumerable:!0})},$=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of w(e))!E.call(t,n)&&n!==r&&b(t,n,{get:()=>e[n],enumerable:!(o=S(e,n))||o.enumerable});return t};var U=t=>$(b({},"__esModule",{value:!0}),t);var V={};R(V,{isObjectLiteral:()=>d,isStringIndex:()=>h,modifyImmutably:()=>D,parseStringIndex:()=>g,remove:()=>I,select:()=>T,set:()=>O,splitPathAtLastKey:()=>P,updateImmutably:()=>K});module.exports=U(V);var I=(t,e)=>{if(!Array.isArray(t)&&t?.constructor!==Object)throw'Wrong type provided in "remove" function';let r=Array.isArray(e)?e:[e];if(Array.isArray(t)){let n=Symbol(),p=[...t];return r.forEach(a=>{p[a]=n}),p.filter(a=>a!==n)}let o={...t};return r.forEach(n=>delete o[n]),o};var T=(t,e)=>!e||typeof e!="string"?t:e.split(".").reduce((r,o)=>{if(r?.hasOwnProperty(o))return r[o]},t);var P=t=>{if(typeof t!="string")throw new Error(`Wrong dotPath type: ${t}`);let e=t.lastIndexOf(".")+1,r=e?t.slice(0,e-1):"",o=t.slice(e);return[r,o]};var O=t=>()=>t;var d=t=>!!t&&Object.getPrototypeOf(t)===Object.prototype;var g=t=>{let e=parseInt(t);return e.toString()===t?e:null},h=t=>parseInt(t).toString()===t;var A="${number}",j=(t,e,r)=>{if(!d(t)&&!Array.isArray(t))throw new Error(`"${t}" is not an literalObject/array`);if(!e)return t;let o=Array.isArray(t)?[...t]:{...t},n={};for(let[p,m]of Object.entries(e)){if(!p)continue;let a=p.split(".");if(a.includes(A))throw new Error(`"${A}" inside "${p}"`);let i=a.pop(),l=n,y=o;for(let u=0;u<a.length;u++){let s=a[u],c=y[s],L=d(c)||Array.isArray(c),x=r&&c===void 0;if(!L&&!x)throw new Error(`"${s}" doesnt exist in "${a.slice(0,u+1).join(".")}"`);l[s]||(x?y[s]=h(a[u+1]??i)?[]:{}:y[s]=Array.isArray(c)?[...c]:{...c},l[s]={}),y=y[s],l=l[s]}let f=y;if(!r&&!f.hasOwnProperty(i))throw new Error(`Property/Index "${i}" doesnt exist in the path "${a.join(".")+"."+i}". Its value is: "${f}"`);f[i]=typeof m=="function"?m(f[i],o):m,delete l[i]}return o},K=(t,e)=>j(t,e,!1),D=(t,e)=>j(t,e,!0);0&&(module.exports={isObjectLiteral,isStringIndex,modifyImmutably,parseStringIndex,remove,select,set,splitPathAtLastKey,updateImmutably});
1
+ "use strict";var m=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var v=(e,t)=>{for(var r in t)m(e,r,{get:t[r],enumerable:!0})},C=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $(t))!k.call(e,o)&&o!==r&&m(e,o,{get:()=>t[o],enumerable:!(n=R(t,o))||n.enumerable});return e};var N=e=>C(m({},"__esModule",{value:!0}),e);var W={};v(W,{extendableUpdate:()=>L,isObjectLiteral:()=>d,isStringIndex:()=>y,parseStringIndex:()=>U,remove:()=>I,select:()=>j,set:()=>K,splitPathAtLastKey:()=>w,update:()=>E});module.exports=N(W);var I=(e,t)=>{if(!Array.isArray(e)&&e?.constructor!==Object)throw'Wrong type provided in "remove" function';let r=Array.isArray(t)?t:[t];if(Array.isArray(e)){let o=Symbol(),p=[...e];return r.forEach(s=>{p[s]=o}),p.filter(s=>s!==o)}let n={...e};return r.forEach(o=>delete n[o]),n};var j=(e,t)=>{if(typeof t!="string")throw new Error("path is not a string");if(!t)return e;let r=t.split("."),n=e;for(;r.length;){let o=r.join(".");if(n?.hasOwnProperty(o))return n[o];if(!n?.hasOwnProperty(r[0]))return;n=n[r[0]],r.shift()}return n};var w=e=>{if(typeof e!="string")throw new Error(`Wrong dotPath type: ${e}`);let t=e.lastIndexOf(".")+1,r=t?e.slice(0,t-1):"",n=e.slice(t);return[r,n]};var K=e=>()=>e;var d=e=>!!e&&Object.getPrototypeOf(e)===Object.prototype;var U=e=>{let t=parseInt(e);return t.toString()===e?t:null},y=e=>parseInt(e).toString()===e;var A=e=>JSON.stringify(e),h=e=>Array.isArray(e),g=(e,t,r={})=>{if(!d(e)&&!h(e))throw new Error(`"${A(e)}" is not an literalObject/array`);if(!d(t))throw new Error('wrong "updateObject" type provided');let n=Array.isArray(e)?[...e]:{...e},o={};for(let[p,x]of Object.entries(t)){if(p==="")continue;let s=p.split("."),l=o,i=n;for(;s.length>1;){let b=s.join(".");if(Object.hasOwn(i,b)){s=[b];break}let a=s[0],f=i[a],S=d(f),T=h(f),O=f===void 0;if(!S&&!T&&!O)throw new Error(`Property "${a}" in "${p}" is a primitive`);if(!l[a]){if(O){let V=h(i)&&y(a),D=y(s[1]),P=V?r.onNewIndexes:r.onNewProps;if(P==="error")throw new Error(`${a} doesn't exist in "${p}"`);if(P==="skip")continue;i[a]=D?[]:{}}else i[a]=T?[...f]:{...f};l[a]={}}i=i[a],l=l[a],s.shift()}let c=s[0],u=i;if(!Object.hasOwn(u,c)){let a=h(u)&&y(c)?r.onNewIndexes:r.onNewProps;if(a==="error")throw new Error(`Property/Index "${c}" doesnt exist in the path "${p}". Its value is: "${A(u)}"`);if(a==="skip")continue}u[c]=typeof x=="function"?x(u[c]):x,delete l[c]}return n},E=(e,t,r)=>g(e,t,r),L=(e,t)=>g(e,t);0&&(module.exports={extendableUpdate,isObjectLiteral,isStringIndex,parseStringIndex,remove,select,set,splitPathAtLastKey,update});
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- var P=(t,e)=>{if(!Array.isArray(t)&&t?.constructor!==Object)throw'Wrong type provided in "remove" function';let r=Array.isArray(e)?e:[e];if(Array.isArray(t)){let i=Symbol(),p=[...t];return r.forEach(n=>{p[n]=i}),p.filter(n=>n!==i)}let o={...t};return r.forEach(i=>delete o[i]),o};var O=(t,e)=>!e||typeof e!="string"?t:e.split(".").reduce((r,o)=>{if(r?.hasOwnProperty(o))return r[o]},t);var g=t=>{if(typeof t!="string")throw new Error(`Wrong dotPath type: ${t}`);let e=t.lastIndexOf(".")+1,r=e?t.slice(0,e-1):"",o=t.slice(e);return[r,o]};var A=t=>()=>t;var f=t=>!!t&&Object.getPrototypeOf(t)===Object.prototype;var j=t=>{let e=parseInt(t);return e.toString()===t?e:null},h=t=>parseInt(t).toString()===t;var x="${number}",I=(t,e,r)=>{if(!f(t)&&!Array.isArray(t))throw new Error(`"${t}" is not an literalObject/array`);if(!e)return t;let o=Array.isArray(t)?[...t]:{...t},i={};for(let[p,d]of Object.entries(e)){if(!p)continue;let n=p.split(".");if(n.includes(x))throw new Error(`"${x}" inside "${p}"`);let s=n.pop(),l=i,y=o;for(let u=0;u<n.length;u++){let a=n[u],c=y[a],T=f(c)||Array.isArray(c),b=r&&c===void 0;if(!T&&!b)throw new Error(`"${a}" doesnt exist in "${n.slice(0,u+1).join(".")}"`);l[a]||(b?y[a]=h(n[u+1]??s)?[]:{}:y[a]=Array.isArray(c)?[...c]:{...c},l[a]={}),y=y[a],l=l[a]}let m=y;if(!r&&!m.hasOwnProperty(s))throw new Error(`Property/Index "${s}" doesnt exist in the path "${n.join(".")+"."+s}". Its value is: "${m}"`);m[s]=typeof d=="function"?d(m[s],o):d,delete l[s]}return o},K=(t,e)=>I(t,e,!1),D=(t,e)=>I(t,e,!0);export{f as isObjectLiteral,h as isStringIndex,D as modifyImmutably,j as parseStringIndex,P as remove,O as select,A as set,g as splitPathAtLastKey,K as updateImmutably};
1
+ var U=(e,t)=>{if(!Array.isArray(e)&&e?.constructor!==Object)throw'Wrong type provided in "remove" function';let r=Array.isArray(t)?t:[t];if(Array.isArray(e)){let s=Symbol(),p=[...e];return r.forEach(a=>{p[a]=s}),p.filter(a=>a!==s)}let n={...e};return r.forEach(s=>delete n[s]),n};var A=(e,t)=>{if(typeof t!="string")throw new Error("path is not a string");if(!t)return e;let r=t.split("."),n=e;for(;r.length;){let s=r.join(".");if(n?.hasOwnProperty(s))return n[s];if(!n?.hasOwnProperty(r[0]))return;n=n[r[0]],r.shift()}return n};var g=e=>{if(typeof e!="string")throw new Error(`Wrong dotPath type: ${e}`);let t=e.lastIndexOf(".")+1,r=t?e.slice(0,t-1):"",n=e.slice(t);return[r,n]};var E=e=>()=>e;var u=e=>!!e&&Object.getPrototypeOf(e)===Object.prototype;var L=e=>{let t=parseInt(e);return t.toString()===e?t:null},f=e=>parseInt(e).toString()===e;var P=e=>JSON.stringify(e),h=e=>Array.isArray(e),I=(e,t,r={})=>{if(!u(e)&&!h(e))throw new Error(`"${P(e)}" is not an literalObject/array`);if(!u(t))throw new Error('wrong "updateObject" type provided');let n=Array.isArray(e)?[...e]:{...e},s={};for(let[p,x]of Object.entries(t)){if(p==="")continue;let a=p.split("."),d=s,i=n;for(;a.length>1;){let b=a.join(".");if(Object.hasOwn(i,b)){a=[b];break}let o=a[0],l=i[o],j=u(l),m=h(l),T=l===void 0;if(!j&&!m&&!T)throw new Error(`Property "${o}" in "${p}" is a primitive`);if(!d[o]){if(T){let w=h(i)&&f(o),K=f(a[1]),O=w?r.onNewIndexes:r.onNewProps;if(O==="error")throw new Error(`${o} doesn't exist in "${p}"`);if(O==="skip")continue;i[o]=K?[]:{}}else i[o]=m?[...l]:{...l};d[o]={}}i=i[o],d=d[o],a.shift()}let c=a[0],y=i;if(!Object.hasOwn(y,c)){let o=h(y)&&f(c)?r.onNewIndexes:r.onNewProps;if(o==="error")throw new Error(`Property/Index "${c}" doesnt exist in the path "${p}". Its value is: "${P(y)}"`);if(o==="skip")continue}y[c]=typeof x=="function"?x(y[c]):x,delete d[c]}return n},S=(e,t,r)=>I(e,t,r),V=(e,t)=>I(e,t);export{V as extendableUpdate,u as isObjectLiteral,f as isStringIndex,L as parseStringIndex,U as remove,A as select,E as set,g as splitPathAtLastKey,S as update};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maraj",
3
- "version": "2.5.1",
3
+ "version": "2.7.0",
4
4
  "description": "A lightweight 600 bytes gzipped alternative for immutable updates while dealing with objects and arrays",
5
5
  "keywords": [
6
6
  "shallow",