or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-object-path

Access deep object properties using a path

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/object-path@0.11.x

To install, run

npx @tessl/cli install tessl/npm-object-path@0.11.0

index.mddocs/

Object Path

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.

Package Information

  • Package Name: object-path
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install object-path

Core Imports

const objectPath = require("object-path");

For ES modules:

import objectPath from "object-path";

Browser global:

// Available as window.objectPath

Basic Usage

const objectPath = require("object-path");

const obj = {
  a: {
    b: "value",
    c: ["item1", "item2"],
    "special.key": "data"
  }
};

// Get deep property
objectPath.get(obj, "a.b");  // returns "value"
objectPath.get(obj, ["a", "special.key"]);  // returns "data"

// Set deep property
objectPath.set(obj, "a.d", "new value");
objectPath.set(obj, "a.e.0", "array item");  // creates intermediate objects/arrays

// Check existence
objectPath.has(obj, "a.b");  // returns true
objectPath.has(obj, "a.missing");  // returns false

// Delete property
objectPath.del(obj, "a.b");  // removes the property

Architecture

Object Path is built around several key concepts:

  • Path Resolution: Supports string paths with dot notation, array paths, and numeric indices
  • Type Safety: Handles different data types appropriately (objects, arrays, primitives)
  • Security: Protection against prototype pollution attacks in inherited properties mode
  • Instance Creation: Factory pattern for creating configured instances with different behaviors
  • Bound Instances: Object-bound instances for cleaner repeated operations on the same object

Capabilities

Core Property Access

Access and manipulate deep object properties using various path formats.

/**
 * Gets a deep property value using a path
 * @param {object} obj - The object to traverse
 * @param {string|array|number} path - The path to the property
 * @param {any} defaultValue - Value to return if path doesn't exist
 * @returns {any} The value at the path or defaultValue
 */
objectPath.get(obj, path, defaultValue);

/**
 * Sets a deep property value, creating intermediate objects/arrays as needed
 * @param {object} obj - The object to modify
 * @param {string|array|number} path - The path to set
 * @param {any} value - The value to set
 * @param {boolean} doNotReplace - If true, won't replace existing values
 * @returns {any} The previous value at the path
 */
objectPath.set(obj, path, value, doNotReplace);

/**
 * Tests whether a deep property exists
 * @param {object} obj - The object to test
 * @param {string|array|number} path - The path to test
 * @returns {boolean} True if property exists
 */
objectPath.has(obj, path);

/**
 * Deletes a deep property (splices arrays, deletes object properties)
 * @param {object} obj - The object to modify
 * @param {string|array|number} path - The path to delete
 * @returns {object} The modified object
 */
objectPath.del(obj, path);

Usage Examples:

const obj = { a: { b: { c: "value" } } };

// Different path formats
objectPath.get(obj, "a.b.c");          // "value"
objectPath.get(obj, ["a", "b", "c"]);  // "value"
objectPath.get(obj, ["a.b", "c"]);     // undefined (literal key "a.b")

// Default values
objectPath.get(obj, "missing.path", "default");  // "default"

// Setting with path creation
objectPath.set(obj, "x.y.z", "new");  // Creates nested structure
objectPath.set(obj, "arr.0", "first"); // Creates array at obj.arr

// Conditional setting (doNotReplace = true)
objectPath.set(obj, "a.b.c", "new", true);    // Won't replace existing "value"
objectPath.set(obj, "x.y.z", "new", true);    // Will set since path doesn't exist

Array Manipulation

Specialized methods for working with arrays at specific paths.

/**
 * Pushes values to an array at the given path, creating the array if needed
 * @param {object} obj - The object to modify
 * @param {string|array|number} path - The path to the array
 * @param {...any} values - Values to push
 */
objectPath.push(obj, path, ...values);

/**
 * Inserts a value into an array at a specific index
 * @param {object} obj - The object to modify
 * @param {string|array|number} path - The path to the array
 * @param {any} value - The value to insert
 * @param {number} at - The index to insert at (defaults to 0)
 */
objectPath.insert(obj, path, value, at);

Usage Examples:

const obj = { items: ["a", "b"] };

// Push multiple values
objectPath.push(obj, "items", "c", "d");  // obj.items = ["a", "b", "c", "d"]

// Create array and push
objectPath.push(obj, "newArray", "first");  // obj.newArray = ["first"]

// Insert at specific position
objectPath.insert(obj, "items", "inserted", 1);  // obj.items = ["a", "inserted", "b", "c", "d"]

Utility Operations

Advanced operations for data manipulation and retrieval.

/**
 * Empties a property while maintaining object/array references
 * @param {object} obj - The object to modify
 * @param {string|array|number} path - The path to empty
 * @returns {any} The previous value
 */
objectPath.empty(obj, path);

/**
 * Sets a value only if the path doesn't already exist
 * @param {object} obj - The object to modify
 * @param {string|array|number} path - The path to ensure
 * @param {any} value - The default value to set
 * @returns {any} The existing or newly set value
 */
objectPath.ensureExists(obj, path, value);

/**
 * Returns the first non-undefined value from multiple paths
 * @param {object} obj - The object to search
 * @param {array} paths - Array of paths to try
 * @param {any} defaultValue - Value to return if all paths are undefined
 * @returns {any} The first defined value or defaultValue
 */
objectPath.coalesce(obj, paths, defaultValue);

Usage Examples:

const obj = {
  data: { count: 5, items: ["a", "b"], active: true },
  text: "hello"
};

// Empty different types while preserving references
objectPath.empty(obj, "text");           // obj.text = ""
objectPath.empty(obj, "data.count");     // obj.data.count = 0
objectPath.empty(obj, "data.active");    // obj.data.active = false
objectPath.empty(obj, "data.items");     // obj.data.items = [] (same array reference)

// Ensure existence
objectPath.ensureExists(obj, "config.timeout", 5000);  // Sets only if missing
const existing = objectPath.ensureExists(obj, "text", "default");  // Returns ""

// Coalesce - find first existing value
const value = objectPath.coalesce(obj, [
  "user.preferences.theme",
  "defaults.theme",
  "config.theme"
], "light");  // Returns "light" if none exist

Instance Creation and Configuration

Create configured instances for different behaviors and security requirements.

/**
 * Creates a new object-path instance with custom options
 * @param {object} options - Configuration options
 * @param {boolean} options.includeInheritedProps - Whether to access inherited properties
 * @returns {object} New object-path instance with all methods
 */
objectPath.create(options);

/**
 * Pre-configured instance that accesses inherited properties
 * @type {object}
 */
objectPath.withInheritedProps;

/**
 * Creates a bound instance with all methods pre-bound to the given object
 * @param {object} obj - The object to bind to
 * @returns {object} Bound instance with get, set, del, has, push, insert, empty, ensureExists, coalesce methods
 */
objectPath(obj);

Usage Examples:

// Create instance with inherited properties support
const inheritedPath = objectPath.create({ includeInheritedProps: true });

// Use pre-configured inherited instance
const proto = { inherited: { value: "from prototype" } };
const obj = Object.create(proto);
objectPath.withInheritedProps.get(obj, "inherited.value");  // "from prototype"

// Create bound instance for cleaner repeated operations
const model = objectPath({
  user: { name: "Alice", preferences: { theme: "dark" } }
});

model.get("user.name");                    // "Alice"
model.set("user.age", 25);                 // Sets obj.user.age = 25
model.has("user.preferences.theme");       // true
model.del("user.preferences");             // Deletes the preferences object

Security Considerations

Object Path includes built-in protection against prototype pollution attacks.

// Default mode - only accesses own properties (secure)
const obj = Object.create({ inherited: "value" });
objectPath.get(obj, "inherited");  // undefined (safe)

// Inherited props mode - includes security checks
const inheritedPath = objectPath.withInheritedProps;
// These will throw errors for security:
// inheritedPath.set(obj, "__proto__.polluted", true);     // Error
// inheritedPath.set(obj, "constructor.prototype.polluted", true);  // Error

Path Format Support

Object Path supports multiple path formats for maximum flexibility:

// String paths with dot notation
"property.nested.deep"
"array.0.property"
"unicode.ключ.property"

// Array paths (handles keys with dots)
["property", "nested", "deep"]
["array", 0, "property"]
["key.with.dots", "nested"]

// Numeric paths (converted to single-element array)
0  // equivalent to [0]
1  // equivalent to [1]

Types

// Path types
type Path = string | (string | number)[] | number;

// Instance interface (returned by objectPath.create())
interface ObjectPath {
  get(obj: object, path: Path, defaultValue?: any): any;
  set(obj: object, path: Path, value: any, doNotReplace?: boolean): any;
  has(obj: object, path: Path): boolean;
  del(obj: object, path: Path): object;
  push(obj: object, path: Path, ...values: any[]): void;
  insert(obj: object, path: Path, value: any, at?: number): void;
  empty(obj: object, path: Path): any;
  ensureExists(obj: object, path: Path, value: any): any;
  coalesce(obj: object, paths: Path[], defaultValue?: any): any;
}

// Bound instance interface (returned by objectPath(obj))
interface BoundObjectPath {
  get(path: Path, defaultValue?: any): any;
  set(path: Path, value: any, doNotReplace?: boolean): any;
  has(path: Path): boolean;
  del(path: Path): object;
  push(path: Path, ...values: any[]): void;
  insert(path: Path, value: any, at?: number): void;
  empty(path: Path): any;
  ensureExists(path: Path, value: any): any;
  coalesce(paths: Path[], defaultValue?: any): any;
}

// Configuration options
interface ObjectPathOptions {
  includeInheritedProps?: boolean;
}