maraj 2.6.0 → 2.7.1
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 +28 -18
- package/dist/index.d.mts +14 -16
- package/dist/index.d.ts +14 -16
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
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
|
-
-
|
|
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
|
-
-
|
|
13
|
-
- Includes usefull utilities like "remove", "select".
|
|
13
|
+
- Nested functional updates.
|
|
14
14
|
|
|
15
|
-
|
|
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?: ... } is not equal to { 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 =
|
|
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 =
|
|
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
|
-
-
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 {
|
|
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 =
|
|
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 {
|
|
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 =
|
|
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 **
|
|
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 =
|
|
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 =
|
|
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
|
@@ -15,13 +15,12 @@ declare const remove: Remove;
|
|
|
15
15
|
/** Index literal type to improve DX at managing updates. */
|
|
16
16
|
declare const LITERAL_INDEX = "${number}";
|
|
17
17
|
type LiteralIndex = typeof LITERAL_INDEX;
|
|
18
|
-
type ObjectOrArray = Record<string | number | symbol, any>;
|
|
19
18
|
type OptionValues = 'error' | 'skip' | 'add';
|
|
20
19
|
type Options = {
|
|
21
20
|
onNewProps?: OptionValues;
|
|
22
21
|
onNewIndexes?: OptionValues;
|
|
23
22
|
};
|
|
24
|
-
type ImmutableUpdate = <TObject extends
|
|
23
|
+
type ImmutableUpdate = <TObject extends Record<PropertyKey, any>>(state: TObject, dotPathUpdateObject: UpdateObject<TObject>, options?: Options) => TObject;
|
|
25
24
|
/**
|
|
26
25
|
* Creates a new object applying immutable updates using dot-path syntax.
|
|
27
26
|
* Can add or skip new props or indexes depending on options.
|
|
@@ -32,7 +31,7 @@ type ImmutableUpdate = <TObject extends ObjectOrArray>(state: TObject, dotPathUp
|
|
|
32
31
|
* @returns New Updated Object.
|
|
33
32
|
*/
|
|
34
33
|
declare const update: ImmutableUpdate;
|
|
35
|
-
type ExtendableImmutableUpdate = <TObject extends
|
|
34
|
+
type ExtendableImmutableUpdate = <TObject extends Record<PropertyKey, any>, TUpdateObject extends UpdateObject<TObject>>(state: TObject, dotPathUpdateObject: TUpdateObject) => ExtendedUpdate<TObject, TUpdateObject>;
|
|
36
35
|
/**
|
|
37
36
|
* Creates a new object applying immutable updates using dot-path syntax.
|
|
38
37
|
* It will always add non-existent props or indexes if provided.
|
|
@@ -63,8 +62,8 @@ type IsTuple<T extends ReadonlyArray<any>> = number extends T['length'] ? false
|
|
|
63
62
|
type ArrayPaths<TInnerType, TAllowedTypes> = TInnerType extends TAllowedTypes ? TInnerType extends PrimitivesAndNativeObjects ? number | `${ArrayIndexes}` : number | `${ArrayIndexes}` | `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}` : `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}`;
|
|
64
63
|
/** Dot-paths of an object. */
|
|
65
64
|
type ObjectPaths<T, TAllowedTypes> = {
|
|
66
|
-
[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>}`;
|
|
67
|
-
}[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)];
|
|
68
67
|
/** Dot-paths of a tuple. */
|
|
69
68
|
type TuplePaths<T, TAllowedTypes> = ObjectPaths<Omit<T, keyof any[]>, TAllowedTypes>;
|
|
70
69
|
/** Literal union of all posible dot-paths which satisfy provided types as second argument (default: any). */
|
|
@@ -75,28 +74,24 @@ type DotPaths<T, TAllowedTypes = any> = T extends ReadonlyArray<infer U> ? IsTup
|
|
|
75
74
|
* --------------------------------------------
|
|
76
75
|
*/
|
|
77
76
|
/** Nested type implementation. */
|
|
78
|
-
type
|
|
79
|
-
/** Value of a nested property of a given dot-path. */
|
|
80
|
-
type ExactValueInDotPath<TObject, TPath extends DotPaths<TObject> | ''> = NestedType<TObject, TPath>;
|
|
77
|
+
type ValueInPath<TObject, TPath> = TPath extends keyof TObject ? TObject[TPath] : TPath extends '' ? TObject : 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;
|
|
81
78
|
/**
|
|
82
79
|
* --------------------------------------------
|
|
83
80
|
* RETURNED VALUE OF A NESTED PROPERTY PROVIDING A DOT PATH
|
|
84
81
|
* --------------------------------------------
|
|
85
82
|
*/
|
|
86
83
|
/** Returned nested type implementation. */
|
|
87
|
-
type
|
|
88
|
-
/** Value of a RETURNED nested property of a given dot-path (so when accessing arrays can be undefined). */
|
|
89
|
-
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;
|
|
90
85
|
/**
|
|
91
86
|
* --------------------------------------------
|
|
92
87
|
* UPDATE OBJECT WITH DOT PATH IMPLEMENTATION
|
|
93
88
|
* --------------------------------------------
|
|
94
89
|
*/
|
|
95
90
|
/** Value of a dot-path update object, can be the value or a function. */
|
|
96
|
-
type
|
|
91
|
+
type UpdateValue<TObject, TPath> = ValueInPath<TObject, TPath> | ((fieldValue: ValueInPath<TObject, TPath>) => ValueInPath<TObject, TPath>);
|
|
97
92
|
/** Dot-path update object, used to give updates to the updateImmutably function. */
|
|
98
|
-
type
|
|
99
|
-
[TPath in
|
|
93
|
+
type UpdateObject<TObject, TPaths extends PropertyKey = DotPaths<TObject>> = {
|
|
94
|
+
[TPath in TPaths]?: ValueInPath<TObject, TPath> | ((fieldValue: ValueInPath<TObject, TPath>) => ValueInPath<TObject, TPath>);
|
|
100
95
|
};
|
|
101
96
|
/**
|
|
102
97
|
* --------------------------------------------
|
|
@@ -139,7 +134,10 @@ type ExtractTypeFromDotPathUpdateObject<T extends Record<string, any>> = T exten
|
|
|
139
134
|
/** New expanded value after aplying updates including new properties */
|
|
140
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>;
|
|
141
136
|
|
|
142
|
-
type Select =
|
|
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
|
+
};
|
|
143
141
|
/**
|
|
144
142
|
* Returns the value from a given dot path of an object/array or undefined if doesn't exist.
|
|
145
143
|
* @param state State from which retrieve the value.
|
|
@@ -172,4 +170,4 @@ declare const isObjectLiteral: (valueToTest: any) => boolean;
|
|
|
172
170
|
declare const parseStringIndex: (v: string) => number | null;
|
|
173
171
|
declare const isStringIndex: (v: string) => boolean;
|
|
174
172
|
|
|
175
|
-
export { type
|
|
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
|
@@ -15,13 +15,12 @@ declare const remove: Remove;
|
|
|
15
15
|
/** Index literal type to improve DX at managing updates. */
|
|
16
16
|
declare const LITERAL_INDEX = "${number}";
|
|
17
17
|
type LiteralIndex = typeof LITERAL_INDEX;
|
|
18
|
-
type ObjectOrArray = Record<string | number | symbol, any>;
|
|
19
18
|
type OptionValues = 'error' | 'skip' | 'add';
|
|
20
19
|
type Options = {
|
|
21
20
|
onNewProps?: OptionValues;
|
|
22
21
|
onNewIndexes?: OptionValues;
|
|
23
22
|
};
|
|
24
|
-
type ImmutableUpdate = <TObject extends
|
|
23
|
+
type ImmutableUpdate = <TObject extends Record<PropertyKey, any>>(state: TObject, dotPathUpdateObject: UpdateObject<TObject>, options?: Options) => TObject;
|
|
25
24
|
/**
|
|
26
25
|
* Creates a new object applying immutable updates using dot-path syntax.
|
|
27
26
|
* Can add or skip new props or indexes depending on options.
|
|
@@ -32,7 +31,7 @@ type ImmutableUpdate = <TObject extends ObjectOrArray>(state: TObject, dotPathUp
|
|
|
32
31
|
* @returns New Updated Object.
|
|
33
32
|
*/
|
|
34
33
|
declare const update: ImmutableUpdate;
|
|
35
|
-
type ExtendableImmutableUpdate = <TObject extends
|
|
34
|
+
type ExtendableImmutableUpdate = <TObject extends Record<PropertyKey, any>, TUpdateObject extends UpdateObject<TObject>>(state: TObject, dotPathUpdateObject: TUpdateObject) => ExtendedUpdate<TObject, TUpdateObject>;
|
|
36
35
|
/**
|
|
37
36
|
* Creates a new object applying immutable updates using dot-path syntax.
|
|
38
37
|
* It will always add non-existent props or indexes if provided.
|
|
@@ -63,8 +62,8 @@ type IsTuple<T extends ReadonlyArray<any>> = number extends T['length'] ? false
|
|
|
63
62
|
type ArrayPaths<TInnerType, TAllowedTypes> = TInnerType extends TAllowedTypes ? TInnerType extends PrimitivesAndNativeObjects ? number | `${ArrayIndexes}` : number | `${ArrayIndexes}` | `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}` : `${ArrayIndexes}.${DotPaths<TInnerType, TAllowedTypes>}`;
|
|
64
63
|
/** Dot-paths of an object. */
|
|
65
64
|
type ObjectPaths<T, TAllowedTypes> = {
|
|
66
|
-
[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>}`;
|
|
67
|
-
}[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)];
|
|
68
67
|
/** Dot-paths of a tuple. */
|
|
69
68
|
type TuplePaths<T, TAllowedTypes> = ObjectPaths<Omit<T, keyof any[]>, TAllowedTypes>;
|
|
70
69
|
/** Literal union of all posible dot-paths which satisfy provided types as second argument (default: any). */
|
|
@@ -75,28 +74,24 @@ type DotPaths<T, TAllowedTypes = any> = T extends ReadonlyArray<infer U> ? IsTup
|
|
|
75
74
|
* --------------------------------------------
|
|
76
75
|
*/
|
|
77
76
|
/** Nested type implementation. */
|
|
78
|
-
type
|
|
79
|
-
/** Value of a nested property of a given dot-path. */
|
|
80
|
-
type ExactValueInDotPath<TObject, TPath extends DotPaths<TObject> | ''> = NestedType<TObject, TPath>;
|
|
77
|
+
type ValueInPath<TObject, TPath> = TPath extends keyof TObject ? TObject[TPath] : TPath extends '' ? TObject : 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;
|
|
81
78
|
/**
|
|
82
79
|
* --------------------------------------------
|
|
83
80
|
* RETURNED VALUE OF A NESTED PROPERTY PROVIDING A DOT PATH
|
|
84
81
|
* --------------------------------------------
|
|
85
82
|
*/
|
|
86
83
|
/** Returned nested type implementation. */
|
|
87
|
-
type
|
|
88
|
-
/** Value of a RETURNED nested property of a given dot-path (so when accessing arrays can be undefined). */
|
|
89
|
-
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;
|
|
90
85
|
/**
|
|
91
86
|
* --------------------------------------------
|
|
92
87
|
* UPDATE OBJECT WITH DOT PATH IMPLEMENTATION
|
|
93
88
|
* --------------------------------------------
|
|
94
89
|
*/
|
|
95
90
|
/** Value of a dot-path update object, can be the value or a function. */
|
|
96
|
-
type
|
|
91
|
+
type UpdateValue<TObject, TPath> = ValueInPath<TObject, TPath> | ((fieldValue: ValueInPath<TObject, TPath>) => ValueInPath<TObject, TPath>);
|
|
97
92
|
/** Dot-path update object, used to give updates to the updateImmutably function. */
|
|
98
|
-
type
|
|
99
|
-
[TPath in
|
|
93
|
+
type UpdateObject<TObject, TPaths extends PropertyKey = DotPaths<TObject>> = {
|
|
94
|
+
[TPath in TPaths]?: ValueInPath<TObject, TPath> | ((fieldValue: ValueInPath<TObject, TPath>) => ValueInPath<TObject, TPath>);
|
|
100
95
|
};
|
|
101
96
|
/**
|
|
102
97
|
* --------------------------------------------
|
|
@@ -139,7 +134,10 @@ type ExtractTypeFromDotPathUpdateObject<T extends Record<string, any>> = T exten
|
|
|
139
134
|
/** New expanded value after aplying updates including new properties */
|
|
140
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>;
|
|
141
136
|
|
|
142
|
-
type Select =
|
|
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
|
+
};
|
|
143
141
|
/**
|
|
144
142
|
* Returns the value from a given dot path of an object/array or undefined if doesn't exist.
|
|
145
143
|
* @param state State from which retrieve the value.
|
|
@@ -172,4 +170,4 @@ declare const isObjectLiteral: (valueToTest: any) => boolean;
|
|
|
172
170
|
declare const parseStringIndex: (v: string) => number | null;
|
|
173
171
|
declare const isStringIndex: (v: string) => boolean;
|
|
174
172
|
|
|
175
|
-
export { type
|
|
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 m=Object.defineProperty;var
|
|
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 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
|
|
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};
|