Skip to main content

API Reference

Complete reference for @powerduck/conf-patch v0.3.4. Every exported symbol is documented with its exact signature and defaults.

There are two entry points:

  • @powerduck/conf-patch — everything below (core + file layer + OpenAPI validation + utilities).
  • @powerduck/conf-patch/core — only the browser-safe subset: patchContent, setContentValue, deleteContentValue, PatchContentOptions, the assertion helpers, and the types ConfigFormat, JsonPatchOp, JsonPathSegment.

Core layer (browser-safe)

patchContent

Applies an array of RFC 6902 patch operations to a configuration string. Pure function — no filesystem access.

function patchContent(
content: string,
ops: JsonPatchOp[],
format: ConfigFormat,
options?: PatchContentOptions,
): string;
ParameterTypeDescription
contentstringThe raw configuration content. Must be a valid format.
opsJsonPatchOp[]Operations to apply in order. An empty array returns content unchanged.
formatConfigFormat"json" | "jsonc" | "yaml".
options.strictbooleanWhen true (default), a failed operation throws. When false, it is skipped with a console.warn.

Returns: the patched configuration content (string).

Throws: TypeError if content is not a string or ops is invalid; an error describing the failing operation when strict is true.

import { patchContent } from "@powerduck/conf-patch/core";

patchContent(
'{"name": "app"}',
[{ op: "add", path: ["version"], value: "1.0.0" }],
"json",
);
// => '{\n "name": "app",\n "version": "1.0.0"\n}'

setContentValue

Sets or creates a single value. Internally calls patchContent with one add operation. add replaces an existing object property or inserts at an array index (RFC 6902).

function setContentValue(
content: string,
path: readonly (string | number)[],
value: unknown,
format: ConfigFormat,
): string;
ParameterTypeDescription
contentstringThe raw configuration content.
pathreadonly (string | number)[]Segment path, e.g. ["server", "port"]. Must be non-empty.
valueunknownThe value to write.
formatConfigFormatThe configuration format.

Returns: the updated content (string).

setContentValue("name: app\n", ["server", "port"], 8080, "yaml");

deleteContentValue

Removes a key or array element. Internally calls patchContent with one remove operation. The path must exist.

function deleteContentValue(
content: string,
path: readonly (string | number)[],
format: ConfigFormat,
): string;
deleteContentValue(
'{"name": "app", "legacy": true}',
["legacy"],
"json",
);

PatchContentOptions

interface PatchContentOptions {
/** When true, failed operations throw. When false, they are skipped with a warning. Default: true */
strict?: boolean;
}

File layer (Node.js / Electron only)

readConfigFile

Reads UTF-8 text from a local file path or file:// URL.

function readConfigFile(filePath: string): Promise<string>;
ParameterTypeDescription
filePathstringAbsolute path, relative path, or file:// URL. Must be non-empty.

Returns: the raw UTF-8 content (Promise<string>).

Throws: an error wrapping the underlying filesystem failure if the file cannot be read.


writeConfigFile

Writes content to a file using an atomic write (temp file + rename) and, by default, an exclusive file lock. Parent directories are created before locking.

function writeConfigFile(
filePath: string,
content: string,
options?: WriteConfigOptions,
): Promise<void>;
ParameterTypeDescription
filePathstringPath to the configuration file.
contentstringThe content to write. Must be a string.
optionsWriteConfigOptionsSee below.

Throws: TypeError on bad input; wraps filesystem failures on write.

WriteConfigOptions

OptionTypeDefaultDescription
lockbooleantrueEnable file locking during the write.
lockTimeoutMsnumberwithFileLock default (10s)Max time (ms) to wait to acquire the lock.
lockRetryDelayMsnumberwithFileLock default (25ms)Initial retry delay (ms) before exponential backoff.
lockStaleThresholdMsnumberwithFileLock defaultLock age (ms) after which recovery is allowed.
allowStaleRecoverybooleanfalseWhether stale locks may be automatically reclaimed.
import { writeConfigFile } from "@powerduck/conf-patch";

await writeConfigFile("config.json", '{"name": "app"}');

patchConfigFile

The primary file-layer transaction: read the file inside a lock, apply patchContent, and write back atomically only if the content changed. Format is auto-detected from the extension when options.format is omitted.

function patchConfigFile(
filePath: string,
ops: JsonPatchOp[],
options?: PatchConfigOptions,
): Promise<void>;
ParameterTypeDescription
filePathstringPath to the configuration file. Must be non-empty.
opsJsonPatchOp[]Operations to apply. An empty array returns without reading or writing.
optionsPatchConfigOptionsSee below.

Throws: TypeError if filePath is empty, lock options are invalid, or the format cannot be detected (and no format is given); the operation error when strict is true.

PatchConfigOptions

OptionTypeDefaultDescription
formatConfigFormatauto-detectedExplicit format. Overrides extension detection.
strictbooleantrueFailed operations throw.
lockbooleantrueEnable file locking.
lockTimeoutMsnumber10sNon-negative. Max wait for the lock.
lockRetryDelayMsnumber25msPositive. Initial retry delay.
lockStaleThresholdMsnumberderivedPositive. Lock age for stale recovery.
allowStaleRecoverybooleanfalseAuto-reclaim stale locks.
await patchConfigFile("config.json", [
{ op: "replace", path: ["server", "host"], value: "0.0.0.0" },
{ op: "add", path: ["server", "ssl"], value: true },
{ op: "remove", path: ["legacySection"] },
]);

setConfigValue

Adds or replaces a nested value in a file. Delegates to patchConfigFile with a single add operation.

function setConfigValue(
filePath: string,
path: readonly (string | number)[],
value: unknown,
options?: PatchConfigOptions,
): Promise<void>;
await setConfigValue("config.yaml", ["database", "port"], 5432);

deleteConfigValue

Removes an existing nested value from a file. Delegates to patchConfigFile with a single remove operation.

function deleteConfigValue(
filePath: string,
path: readonly (string | number)[],
options?: PatchConfigOptions,
): Promise<void>;
await deleteConfigValue("config.json", ["features", "betaPreview"]);

withFileLock

Runs an async callback under a process-local queue and an exclusive lock file (<file>.confedit.lock). Locks use ownership tokens; a stale lock is recovered only when allowStaleRecovery is true and the lock exceeds staleThresholdMs. PID checks are intentionally avoided (PIDs can be reused).

function withFileLock<T>(
filePath: string,
callback: () => Promise<T>,
options?: FileLockOptions,
): Promise<T>;
ParameterTypeDescription
filePathstringThe file to lock.
callback() => Promise<T>Work to run while holding the lock.
optionsFileLockOptionsSee below.

Returns: whatever callback returns (Promise<T>). The lock is always released in a finally block, even if the callback throws.

FileLockOptions

OptionTypeDefaultDescription
timeoutMsnumber10000Max time (ms) to wait for the lock. Must be non-negative.
retryDelayMsnumber25Initial retry delay (ms). Must be positive. Backoff grows by 1.5x, capped at 1000ms.
staleThresholdMsnumbermax(timeoutMs * 2, 60000)Lock age (ms) after which recovery is allowed. Must be positive.
allowStaleRecoverybooleanfalseAuto-reclaim stale locks. Disabled by default for Electron's single main process to avoid preempting live transactions.
import { withFileLock } from "@powerduck/conf-patch";

await withFileLock("state.json", async () => {
// ... read, modify, write ...
}, { timeoutMs: 5000 });

releaseAllLocalLocks

Unlinks every lock file owned by the current process. Designed for Electron's app.whenReady quit path (e.g. app.on("will-quit", ...)). Failures per lock are swallowed.

function releaseAllLocalLocks(): Promise<void>;

OpenAPI validation

validateOpenAPISpec

Validates raw OpenAPI/Swagger content (JSON or YAML). Input is treated as content by default; file-path interpretation only happens when inputKind: "file". Validation is delegated to @powerduck/openapi-parser; this function adds secure input handling.

function validateOpenAPISpec(
input: string,
options?: ValidateOpenApiOptions,
): Promise<AnyOpenAPIDocument>;
ParameterTypeDescription
inputstringRaw spec content, or a file path when inputKind: "file".
optionsValidateOpenApiOptionsSee below.

Returns: the validated document on success (Promise<AnyOpenAPIDocument>).

Throws: OpenApiValidationError on any failure.


validateOpenAPIFile

Convenience wrapper that calls validateOpenAPISpec with inputKind: "file" and baseFilePath set to the given path. Requires allowedRootDirectory.

function validateOpenAPIFile(
filePath: string,
options?: ValidateOpenApiOptions,
): Promise<AnyOpenAPIDocument>;
import { validateOpenAPIFile } from "@powerduck/conf-patch";

const doc = await validateOpenAPIFile("openapi.yaml", {
allowedRootDirectory: "./configs",
});

ValidateOpenApiOptions

OptionTypeDefaultDescription
inputKind"content" | "file""content"How to interpret input.
baseFilePathstringBase path for reference-resolution context.
allowedRootDirectorystringRoot directory for file input. Required when inputKind is "file".
timeoutMsnumber15000Operation deadline (ms).
maxInputBytesnumber5242880 (5 MB)Max raw input size in bytes.
maxDocumentNodesnumber100000Max nodes in the parsed document (DoS guard).
maxDocumentDepthnumber100Max nesting depth (DoS guard).
maxValidationErrorsnumber50Max errors included in the error message.
maxErrorMessageLengthnumber1000Max characters per validation error.
signalAbortSignalOptional cancellation signal.

OpenApiValidationError

Structured error thrown on validation failure. Safe to expose across an application boundary.

class OpenApiValidationError extends Error {
readonly code: string;
readonly cause?: unknown;
constructor(code: string, message: string, cause?: unknown);
}
PropertyTypeDescription
codestringMachine-readable error code (see table below).
messagestringHuman-readable detail.
causeunknownOptional underlying error.

Error codes

CodeMeaning
INVALID_OPTIONInvalid option value provided.
INPUT_TOO_LARGERaw content exceeds maxInputBytes.
INPUT_FILE_TOO_LARGEInput file exceeds the size limit.
FILE_INPUT_FORBIDDENFile input used without allowedRootDirectory.
PATH_OUTSIDE_ROOTFile path resolves outside allowedRootDirectory.
PARSE_ERRORFailed to parse JSON/YAML content.
INVALID_DOCUMENT_SHAPEDocument is not a JSON object.
UNSUPPORTED_VERSIONDocument does not declare a supported OpenAPI/Swagger version (only major 2 and 3 are accepted).
DOCUMENT_TOO_DEEPNesting depth exceeds maxDocumentDepth.
DOCUMENT_TOO_LARGENode count exceeds maxDocumentNodes.
SPEC_VALIDATION_FAILEDThe spec failed OpenAPI validation.
OPERATION_TIMEOUTOperation exceeded timeoutMs.
OPERATION_ABORTEDOperation was aborted via signal.
UNKNOWN_ERRORUnexpected error.

Utilities

detectFormat

Detects a ConfigFormat from a file path or file:// URL based on its extension.

function detectFormat(filePath: string): ConfigFormat;
ExtensionResult
.json"json"
.jsonc"jsonc"
.yaml, .yml"yaml"
anything elsethrows an error

normalizeFilePath

Converts a local path or file: URL into an absolute native path. Preserves valid whitespace and Unicode file names.

function normalizeFilePath(filePath: string): string;

A file: URL is decoded with fileURLToPath; an already-absolute path is returned as-is; a relative path is resolved against process.cwd().


Assertion helpers

These are re-exported for advanced use and by internal modules. They are rarely needed directly by application code.

assertNonEmptyString

function assertNonEmptyString(value: unknown, label: string): asserts value is string;

Throws TypeError unless value is a non-empty string.

assertPatchPath

function assertPatchPath(
path: readonly (string | number)[],
label?: string, // default "path"
): void;

Throws unless path is a non-empty array whose segments are non-empty strings or safe non-negative integers.

assertPatchOperations

function assertPatchOperations(ops: JsonPatchOp[]): void;

Validates each operation: op must be "add" | "replace" | "remove", path must pass assertPatchPath, and add/replace must carry a value own-property.

assertConfigFormat

function assertConfigFormat(format: ConfigFormat): void;

Throws unless format is "json", "jsonc", or "yaml".

getErrorMessage

function getErrorMessage(error: unknown): string;

Returns error.message for Error instances, otherwise String(error).

createError

function createError(message: string, cause: unknown): Error;

Creates an Error and attaches a cause property (using Object.defineProperty, with a fallback for older runtimes).


Types

ConfigFormat

type ConfigFormat = "json" | "jsonc" | "yaml";

JsonPathSegment

type JsonPathSegment = string | number;

JsonPatchOp

interface JsonPatchOp {
op: "add" | "replace" | "remove";
path: JsonPathSegment[];
/** Required for "add" and "replace". */
value?: unknown;
}
caution

Only "add", "replace", and "remove" are supported. "move", "copy", and "test" are intentionally excluded.

PatchConfigOptions

interface PatchConfigOptions {
format?: ConfigFormat;
strict?: boolean;
lock?: boolean;
lockTimeoutMs?: number;
lockRetryDelayMs?: number;
lockStaleThresholdMs?: number;
/** Whether stale locks can be automatically reclaimed. Defaults to false. */
allowStaleRecovery?: boolean;
}

FileLockOptions

interface FileLockOptions {
/** Max time to wait for a lock. Defaults to 10 seconds. */
timeoutMs?: number;
/** Initial retry delay. Defaults to 25ms. */
retryDelayMs?: number;
/** Explicit lock age after which recovery is allowed. */
staleThresholdMs?: number;
/** Whether stale locks can be automatically reclaimed. Defaults to false. */
allowStaleRecovery?: boolean;
}

WriteConfigOptions

interface WriteConfigOptions {
lock?: boolean;
lockTimeoutMs?: number;
lockRetryDelayMs?: number;
lockStaleThresholdMs?: number;
allowStaleRecovery?: boolean;
}

PatchContentOptions

interface PatchContentOptions {
strict?: boolean;
}

OpenApiInputKind

type OpenApiInputKind = "content" | "file";

AnyOpenAPIDocument

A union of supported OpenAPI/Swagger document shapes returned by validation:

type AnyOpenAPIDocument =
| OpenAPIV2.Document // Swagger 2.0
| OpenAPIV3.Document // OpenAPI 3.0.x
| OpenAPIV3_1.Document // OpenAPI 3.1.x
| OpenAPIV3_2Document; // OpenAPI 3.2 (permissive structural type)

OpenAPIV3_2Document is a permissible structural type:

interface OpenAPIV3_2Document {
openapi: string;
info: Record<string, unknown>;
paths?: Record<string, unknown>;
[key: string]: unknown;
}

Export summary

SymbolMain entryCore subpathKind
patchContentfunction
setContentValuefunction
deleteContentValuefunction
PatchContentOptionstype
assertNonEmptyStringfunction
assertPatchPathfunction
assertPatchOperationsfunction
assertConfigFormatfunction
getErrorMessagefunction
createErrorfunction
ConfigFormattype
JsonPatchOptype
JsonPathSegmenttype
readConfigFilefunction
writeConfigFilefunction
WriteConfigOptionstype
patchConfigFilefunction
setConfigValuefunction
deleteConfigValuefunction
withFileLockfunction
releaseAllLocalLocksfunction
PatchConfigOptionstype
FileLockOptionstype
detectFormatfunction
normalizeFilePathfunction
validateOpenAPISpecfunction
validateOpenAPIFilefunction
OpenApiValidationErrorclass
ValidateOpenApiOptionstype
OpenApiInputKindtype
AnyOpenAPIDocumenttype