{"id":11922,"library":"reftools","title":"RefTools","description":"RefTools is a JavaScript utility library providing a comprehensive set of functions for working with JavaScript objects, particularly focusing on JSON References, JSON Pointers, and various cloning strategies. It offers deep, shallow, and circular-aware cloning, object flattening, and powerful recursion and visitation mechanisms for complex object structures. Currently at version 1.1.9, the library is actively maintained, as evidenced by its integration into the `oas-kit` monorepo, which includes projects like `swagger2openapi`. While `reftools` itself does not have a rapid, independent release cadence, its core features are crucial for OpenAPI/Swagger tooling, ensuring ongoing relevance and updates. Its key differentiators lie in its robust handling of JSON Pointers/References and advanced object traversal features with configurable callbacks, making it suitable for intricate data manipulation and schema processing tasks.","status":"active","version":"1.1.9","language":"javascript","source_language":"en","source_url":"https://github.com/Mermade/oas-kit","tags":["javascript","json-reference","json-pointer","object","objects","circular","reference","dereference","clone"],"install":[{"cmd":"npm install reftools","lang":"bash","label":"npm"},{"cmd":"yarn add reftools","lang":"bash","label":"yarn"},{"cmd":"pnpm add reftools","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The library primarily uses named exports. While CommonJS `require` might work in some environments, ESM `import` is the idiomatic and recommended approach for modern JavaScript projects.","wrong":"const { clone } = require('reftools')","symbol":"clone","correct":"import { clone } from 'reftools'"},{"note":"Functions like `dereference` are named exports. Attempting a default import will result in `undefined` or an error.","wrong":"import dereference from 'reftools'","symbol":"dereference","correct":"import { dereference } from 'reftools'"},{"note":"Accessing nested properties of the `require` result, instead of destructuring, is less concise and can be less performant in some module loaders. Named imports are preferred.","wrong":"const jptr = require('reftools').jptr","symbol":"jptr","correct":"import { jptr } from 'reftools'"},{"note":"Used for traversing object properties with a custom callback and state.","symbol":"recurse","correct":"import { recurse } from 'reftools'"},{"note":"Provides a powerful, callback-driven mechanism for deep object traversal, comparison, and modification.","symbol":"visit","correct":"import { visit } from 'reftools'"}],"quickstart":{"code":"import { clone, dereference, jptr, circularClone } from 'reftools';\n\nconst originalObject = {\n  a: 1,\n  b: { c: 2 },\n  d: { $ref: '#/b' }, // JSON Reference\n  e: [],\n};\noriginalObject.e.push(originalObject.b); // Introduce a circular reference\n\nconsole.log('Original Object:', JSON.stringify(originalObject, null, 2));\n\n// 1. Basic cloning\nconst clonedObject = clone(originalObject);\nconsole.log('\\nCloned Object (JSON.parse/stringify):', JSON.stringify(clonedObject, null, 2));\n// Note: JSON.parse/stringify cloning loses circular refs and some types\n\n// 2. Dereferencing JSON Pointers\nconst dereferencedObject = dereference(originalObject);\nconsole.log('\\nDereferenced Object (JSON Pointers resolved):', JSON.stringify(dereferencedObject, null, 2));\n\n// 3. Using JSON Pointer (jptr) to get and set values\nconst valueA = jptr(originalObject, '/a');\nconsole.log(`\\nValue at '/a': ${valueA}`);\n\njptr(originalObject, '/b/c', 99);\nconsole.log('Object after jptr set /b/c to 99:', JSON.stringify(originalObject, null, 2));\n\n// 4. Cloning with circular reference handling\nconst circularHandledClone = circularClone(originalObject);\nconsole.log('\\nCircular-aware cloned object (inspect for circularity - will be simplified):', circularHandledClone);","lang":"javascript","description":"Demonstrates basic cloning, JSON Reference dereferencing, JSON Pointer (jptr) usage for getting/setting values, and cloning an object with circular references."},"warnings":[{"fix":"Carefully select the appropriate cloning function based on your specific requirements for depth, prototype handling, and circular reference management. For circular structures, `circularClone` or `dereference` might be necessary.","message":"RefTools offers several cloning functions (`clone`, `shallowClone`, `deepClone`, `fastClone`, `circularClone`). Each has distinct behavior regarding prototype properties, deep vs. shallow copies, and handling of circular references. Using the wrong cloning method can lead to unexpected data loss (e.g., `clone` via `JSON.parse/stringify` drops circular references and certain data types) or performance issues.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always use `jpescape` for path segments before constructing a JSON Pointer if the segments might contain `~` or `/`. Ensure all JSON Pointers conform to RFC 6901 specifications.","message":"When working with JSON Pointers (`jptr`, `jpescape`, `jpunescape`), strict adherence to RFC 6901 syntax is required. Incorrectly formatted pointers (e.g., forgetting to escape `~` or `/` with `~0` and `~1` respectively) will result in incorrect paths being resolved or errors, particularly when dealing with property names containing these special characters.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Thoroughly test callbacks for `recurse` and `visit`. Ensure callbacks handle potential circularities, prevent infinite recursion, and correctly manage the state and mutation logic. Consider using `dereference` or `circularClone` beforehand if working with complex, potentially circular structures during traversal.","message":"The `recurse` and `visit` functions provide powerful object traversal but require careful implementation of callbacks. Improperly written callbacks, especially those that mutate the object structure without caution or fail to handle termination conditions, can lead to infinite loops or unexpected side effects during traversal, particularly with highly interconnected or circular data.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Verify that the JSON Pointer path is valid and all intermediate objects exist. Add defensive checks or ensure your data structure matches the expected path before calling `jptr` or `dereference`.","cause":"Attempting to access a property via `jptr` or `dereference` with a JSON Pointer that resolves to a non-existent path or an `undefined` intermediate object.","error":"TypeError: Cannot read properties of undefined (reading 'someProp')"},{"fix":"For circular references, ensure you use `circularClone` or the `dereference` function as intended. When writing custom `recurse` or `visit` callbacks, implement a visited-set mechanism to prevent re-processing already seen objects.","cause":"Using recursive functions like `dereference` or custom `recurse` callbacks on deeply nested or circularly referenced objects without proper handling for recursion depth or explicit circularity detection.","error":"RangeError: Maximum call stack size exceeded"}],"ecosystem":"npm"}