0
# Object Path
1
2
Object Path is a JavaScript utility library for accessing and manipulating deep object properties using string paths or arrays. It provides safe traversal of nested object structures with comprehensive functionality for getting, setting, deleting, and testing existence of deeply nested properties.
3
4
## Package Information
5
6
- **Package Name**: object-path
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install object-path`
10
11
## Core Imports
12
13
```javascript
14
const objectPath = require("object-path");
15
```
16
17
For ES modules:
18
19
```javascript
20
import objectPath from "object-path";
21
```
22
23
Browser global:
24
25
```javascript
26
// Available as window.objectPath
27
```
28
29
## Basic Usage
30
31
```javascript
32
const objectPath = require("object-path");
33
34
const obj = {
35
a: {
36
b: "value",
37
c: ["item1", "item2"],
38
"special.key": "data"
39
}
40
};
41
42
// Get deep property
43
objectPath.get(obj, "a.b"); // returns "value"
44
objectPath.get(obj, ["a", "special.key"]); // returns "data"
45
46
// Set deep property
47
objectPath.set(obj, "a.d", "new value");
48
objectPath.set(obj, "a.e.0", "array item"); // creates intermediate objects/arrays
49
50
// Check existence
51
objectPath.has(obj, "a.b"); // returns true
52
objectPath.has(obj, "a.missing"); // returns false
53
54
// Delete property
55
objectPath.del(obj, "a.b"); // removes the property
56
```
57
58
## Architecture
59
60
Object Path is built around several key concepts:
61
62
- **Path Resolution**: Supports string paths with dot notation, array paths, and numeric indices
63
- **Type Safety**: Handles different data types appropriately (objects, arrays, primitives)
64
- **Security**: Protection against prototype pollution attacks in inherited properties mode
65
- **Instance Creation**: Factory pattern for creating configured instances with different behaviors
66
- **Bound Instances**: Object-bound instances for cleaner repeated operations on the same object
67
68
## Capabilities
69
70
### Core Property Access
71
72
Access and manipulate deep object properties using various path formats.
73
74
```javascript { .api }
75
/**
76
* Gets a deep property value using a path
77
* @param {object} obj - The object to traverse
78
* @param {string|array|number} path - The path to the property
79
* @param {any} defaultValue - Value to return if path doesn't exist
80
* @returns {any} The value at the path or defaultValue
81
*/
82
objectPath.get(obj, path, defaultValue);
83
84
/**
85
* Sets a deep property value, creating intermediate objects/arrays as needed
86
* @param {object} obj - The object to modify
87
* @param {string|array|number} path - The path to set
88
* @param {any} value - The value to set
89
* @param {boolean} doNotReplace - If true, won't replace existing values
90
* @returns {any} The previous value at the path
91
*/
92
objectPath.set(obj, path, value, doNotReplace);
93
94
/**
95
* Tests whether a deep property exists
96
* @param {object} obj - The object to test
97
* @param {string|array|number} path - The path to test
98
* @returns {boolean} True if property exists
99
*/
100
objectPath.has(obj, path);
101
102
/**
103
* Deletes a deep property (splices arrays, deletes object properties)
104
* @param {object} obj - The object to modify
105
* @param {string|array|number} path - The path to delete
106
* @returns {object} The modified object
107
*/
108
objectPath.del(obj, path);
109
```
110
111
**Usage Examples:**
112
113
```javascript
114
const obj = { a: { b: { c: "value" } } };
115
116
// Different path formats
117
objectPath.get(obj, "a.b.c"); // "value"
118
objectPath.get(obj, ["a", "b", "c"]); // "value"
119
objectPath.get(obj, ["a.b", "c"]); // undefined (literal key "a.b")
120
121
// Default values
122
objectPath.get(obj, "missing.path", "default"); // "default"
123
124
// Setting with path creation
125
objectPath.set(obj, "x.y.z", "new"); // Creates nested structure
126
objectPath.set(obj, "arr.0", "first"); // Creates array at obj.arr
127
128
// Conditional setting (doNotReplace = true)
129
objectPath.set(obj, "a.b.c", "new", true); // Won't replace existing "value"
130
objectPath.set(obj, "x.y.z", "new", true); // Will set since path doesn't exist
131
```
132
133
### Array Manipulation
134
135
Specialized methods for working with arrays at specific paths.
136
137
```javascript { .api }
138
/**
139
* Pushes values to an array at the given path, creating the array if needed
140
* @param {object} obj - The object to modify
141
* @param {string|array|number} path - The path to the array
142
* @param {...any} values - Values to push
143
*/
144
objectPath.push(obj, path, ...values);
145
146
/**
147
* Inserts a value into an array at a specific index
148
* @param {object} obj - The object to modify
149
* @param {string|array|number} path - The path to the array
150
* @param {any} value - The value to insert
151
* @param {number} at - The index to insert at (defaults to 0)
152
*/
153
objectPath.insert(obj, path, value, at);
154
```
155
156
**Usage Examples:**
157
158
```javascript
159
const obj = { items: ["a", "b"] };
160
161
// Push multiple values
162
objectPath.push(obj, "items", "c", "d"); // obj.items = ["a", "b", "c", "d"]
163
164
// Create array and push
165
objectPath.push(obj, "newArray", "first"); // obj.newArray = ["first"]
166
167
// Insert at specific position
168
objectPath.insert(obj, "items", "inserted", 1); // obj.items = ["a", "inserted", "b", "c", "d"]
169
```
170
171
### Utility Operations
172
173
Advanced operations for data manipulation and retrieval.
174
175
```javascript { .api }
176
/**
177
* Empties a property while maintaining object/array references
178
* @param {object} obj - The object to modify
179
* @param {string|array|number} path - The path to empty
180
* @returns {any} The previous value
181
*/
182
objectPath.empty(obj, path);
183
184
/**
185
* Sets a value only if the path doesn't already exist
186
* @param {object} obj - The object to modify
187
* @param {string|array|number} path - The path to ensure
188
* @param {any} value - The default value to set
189
* @returns {any} The existing or newly set value
190
*/
191
objectPath.ensureExists(obj, path, value);
192
193
/**
194
* Returns the first non-undefined value from multiple paths
195
* @param {object} obj - The object to search
196
* @param {array} paths - Array of paths to try
197
* @param {any} defaultValue - Value to return if all paths are undefined
198
* @returns {any} The first defined value or defaultValue
199
*/
200
objectPath.coalesce(obj, paths, defaultValue);
201
```
202
203
**Usage Examples:**
204
205
```javascript
206
const obj = {
207
data: { count: 5, items: ["a", "b"], active: true },
208
text: "hello"
209
};
210
211
// Empty different types while preserving references
212
objectPath.empty(obj, "text"); // obj.text = ""
213
objectPath.empty(obj, "data.count"); // obj.data.count = 0
214
objectPath.empty(obj, "data.active"); // obj.data.active = false
215
objectPath.empty(obj, "data.items"); // obj.data.items = [] (same array reference)
216
217
// Ensure existence
218
objectPath.ensureExists(obj, "config.timeout", 5000); // Sets only if missing
219
const existing = objectPath.ensureExists(obj, "text", "default"); // Returns ""
220
221
// Coalesce - find first existing value
222
const value = objectPath.coalesce(obj, [
223
"user.preferences.theme",
224
"defaults.theme",
225
"config.theme"
226
], "light"); // Returns "light" if none exist
227
```
228
229
### Instance Creation and Configuration
230
231
Create configured instances for different behaviors and security requirements.
232
233
```javascript { .api }
234
/**
235
* Creates a new object-path instance with custom options
236
* @param {object} options - Configuration options
237
* @param {boolean} options.includeInheritedProps - Whether to access inherited properties
238
* @returns {object} New object-path instance with all methods
239
*/
240
objectPath.create(options);
241
242
/**
243
* Pre-configured instance that accesses inherited properties
244
* @type {object}
245
*/
246
objectPath.withInheritedProps;
247
248
/**
249
* Creates a bound instance with all methods pre-bound to the given object
250
* @param {object} obj - The object to bind to
251
* @returns {object} Bound instance with get, set, del, has, push, insert, empty, ensureExists, coalesce methods
252
*/
253
objectPath(obj);
254
```
255
256
**Usage Examples:**
257
258
```javascript
259
// Create instance with inherited properties support
260
const inheritedPath = objectPath.create({ includeInheritedProps: true });
261
262
// Use pre-configured inherited instance
263
const proto = { inherited: { value: "from prototype" } };
264
const obj = Object.create(proto);
265
objectPath.withInheritedProps.get(obj, "inherited.value"); // "from prototype"
266
267
// Create bound instance for cleaner repeated operations
268
const model = objectPath({
269
user: { name: "Alice", preferences: { theme: "dark" } }
270
});
271
272
model.get("user.name"); // "Alice"
273
model.set("user.age", 25); // Sets obj.user.age = 25
274
model.has("user.preferences.theme"); // true
275
model.del("user.preferences"); // Deletes the preferences object
276
```
277
278
### Security Considerations
279
280
Object Path includes built-in protection against prototype pollution attacks.
281
282
```javascript
283
// Default mode - only accesses own properties (secure)
284
const obj = Object.create({ inherited: "value" });
285
objectPath.get(obj, "inherited"); // undefined (safe)
286
287
// Inherited props mode - includes security checks
288
const inheritedPath = objectPath.withInheritedProps;
289
// These will throw errors for security:
290
// inheritedPath.set(obj, "__proto__.polluted", true); // Error
291
// inheritedPath.set(obj, "constructor.prototype.polluted", true); // Error
292
```
293
294
## Path Format Support
295
296
Object Path supports multiple path formats for maximum flexibility:
297
298
```javascript { .api }
299
// String paths with dot notation
300
"property.nested.deep"
301
"array.0.property"
302
"unicode.ключ.property"
303
304
// Array paths (handles keys with dots)
305
["property", "nested", "deep"]
306
["array", 0, "property"]
307
["key.with.dots", "nested"]
308
309
// Numeric paths (converted to single-element array)
310
0 // equivalent to [0]
311
1 // equivalent to [1]
312
```
313
314
## Types
315
316
```javascript { .api }
317
// Path types
318
type Path = string | (string | number)[] | number;
319
320
// Instance interface (returned by objectPath.create())
321
interface ObjectPath {
322
get(obj: object, path: Path, defaultValue?: any): any;
323
set(obj: object, path: Path, value: any, doNotReplace?: boolean): any;
324
has(obj: object, path: Path): boolean;
325
del(obj: object, path: Path): object;
326
push(obj: object, path: Path, ...values: any[]): void;
327
insert(obj: object, path: Path, value: any, at?: number): void;
328
empty(obj: object, path: Path): any;
329
ensureExists(obj: object, path: Path, value: any): any;
330
coalesce(obj: object, paths: Path[], defaultValue?: any): any;
331
}
332
333
// Bound instance interface (returned by objectPath(obj))
334
interface BoundObjectPath {
335
get(path: Path, defaultValue?: any): any;
336
set(path: Path, value: any, doNotReplace?: boolean): any;
337
has(path: Path): boolean;
338
del(path: Path): object;
339
push(path: Path, ...values: any[]): void;
340
insert(path: Path, value: any, at?: number): void;
341
empty(path: Path): any;
342
ensureExists(path: Path, value: any): any;
343
coalesce(paths: Path[], defaultValue?: any): any;
344
}
345
346
// Configuration options
347
interface ObjectPathOptions {
348
includeInheritedProps?: boolean;
349
}
350
```