A library for finding all occurrences of a property in OpenAPI/YAML/JSON files, with full $ref resolution support.
import { find, findWithCallback } from "openapi-field-finder";
// Returns all matches as a record
const results = await find("x-custom-extension", ["./openapi.yaml"]);
// Or use a callback for each match
await findWithCallback("x-custom-extension", ["./openapi.yaml"], (path, content, parent) => {
console.log(`Found at ${path}:`, content);
});Searches for all occurrences of a property in YAML/JSON files, following $ref references.
Parameters:
propertyToFind- The property key to search forfilePathsToSearch- Array of file paths to search
Returns: A record where keys are dot-notation paths and values are the property values.
Type Parameter:
T- Optional type for the property values (defaults tounknown)
findWithCallback<T>(propertyToFind: string, filePathsToSearch: string[], callback: FindCallback<T>): Promise<void>
Searches for all occurrences of a property and invokes a callback for each match.
Parameters:
propertyToFind- The property key to search forfilePathsToSearch- Array of file paths to searchcallback- Function called for each match:(path: string, content: T, parent: Record<string, unknown>) => void | Promise<void>path- Dot-notation path to the property (e.g.,paths./users.get.x-custom)content- The value of the found propertyparent- The object containing the found property
Returns:
Promise<void> - Resolves when all files have been searched and all callbacks have completed.
Type Parameter:
T- Optional type for the property values (defaults tounknown)
Given an OpenAPI file api.yaml:
openapi: 3.0.0
paths:
/users:
x-controller: UsersController
get:
x-operation-id: listUsers
summary: List all users
post:
x-operation-id: createUser
summary: Create a userimport { find } from "openapi-field-finder";
const results = await find("x-operation-id", ["./api.yaml"]);
// Results:
// {
// "paths./users.get.x-operation-id": "listUsers",
// "paths./users.post.x-operation-id": "createUser"
// }interface DeprecationInfo {
reason: string;
since: string;
replacement?: string;
}
const results = await find<DeprecationInfo>("x-deprecated", ["./api.yaml"]);
// TypeScript knows results values are DeprecationInfo
console.log(results["paths./users.x-deprecated"].reason);The callback API is useful when you want to process matches as they're found, or when you need access to the parent object:
import { findWithCallback } from "openapi-field-finder";
// Process each match individually
await findWithCallback("x-deprecated", ["./api.yaml"], (path, content, parent) => {
console.log(`Found deprecated property at: ${path}`);
console.log(`Reason: ${content.reason}`);
console.log(`Parent object keys: ${Object.keys(parent).join(", ")}`);
});
// Async callbacks are supported
await findWithCallback("x-custom", ["./api.yaml"], async (path, content) => {
await saveToDatabase(path, content);
});
// With TypeScript generics
interface CustomExtension {
enabled: boolean;
config: Record<string, unknown>;
}
await findWithCallback<CustomExtension>("x-custom", ["./api.yaml"], (path, content) => {
// TypeScript knows content is CustomExtension
if (content.enabled) {
console.log(`Feature enabled at ${path}`);
}
});The library automatically follows $ref references:
paths:
/users:
$ref: "#/components/pathItems/Users"
components:
pathItems:
Users:
x-custom:
message: "Found via ref"const results = await find("x-custom", ["./api.yaml"]);
// Results:
// {
// "paths./users.x-custom": { message: "Found via ref" },
// "components.pathItems.Users.x-custom": { message: "Found via ref" }
// }External file references are resolved relative to the current file:
# api.yaml
paths:
/users:
$ref: "./paths/users.yaml"# paths/users.yaml
x-custom:
message: "From external file"
get:
summary: Get usersconst results = await find("x-custom", ["./api.yaml"]);
// Results:
// {
// "paths./users.x-custom": { message: "From external file" }
// }const results = await find("x-deprecated", [
"./api-v1.yaml",
"./api-v2.yaml",
"./common.yaml",
]);Array indices are included in the path:
paths:
/users:
get:
parameters:
- name: limit
x-validation:
max: 100
- name: offset
x-validation:
min: 0const results = await find("x-validation", ["./api.yaml"]);
// Results:
// {
// "paths./users.get.parameters.0.x-validation": { max: 100 },
// "paths./users.get.parameters.1.x-validation": { min: 0 }
// }- Parses YAML (
.yaml,.yml) and JSON (.json) files - Follows local
$refreferences (#/components/...) - Follows external file
$refreferences (./other-file.yaml#/path) - Handles JSON Pointer escape sequences (
~0for~,~1for/) - Prevents infinite loops from circular references
- Caches external files to avoid re-parsing
- Returns dot-notation paths for easy identification of property locations
Result keys use dot-notation to represent the location of each found property:
| Path | Meaning |
|---|---|
paths./users.get.x-foo |
Property at paths["/users"]["get"]["x-foo"] |
components.schemas.User.x-bar |
Property at components["schemas"]["User"]["x-bar"] |
paths./users.get.parameters.0.x-baz |
First parameter's x-baz property |
npm installnpm run buildThis compiles TypeScript to ./dist/index.js.
npm run testTo run tests in watch mode:
npm run test:watch