Skip to content
Warlock.js v4.7.0

Safely overwrite a JSON config

Every project ends up with a config file that something else is watching — a dev server, a linter, your own hot-reload. You need to flip a field without ever letting a truncated, half-written JSON file be observed.

The facade’s mergeJson reads, patches, and writes in one call. Pass { atomic: true } so the write goes through a temp file and an atomic rename.

src/set-feature.ts
import { fs } from "@warlock.js/fs";
await fs.files.mergeJson(
"config.json",
{ features: { "dark-mode": true }, updatedAt: new Date().toISOString() },
{ atomic: true },
);

Any watcher sees the old config or the new one, never a half-written one. A crash between read and write leaves the file untouched.

mergeJson spreads a partial over the top level. When you need to compute the new value from the old one — bump a counter, push into an array — reach for editJson:

src/bump-build.ts
import { fs } from "@warlock.js/fs";
await fs.files.editJson("config.json", (cfg) => ({
...cfg,
builds: cfg.builds + 1,
}), { atomic: true });

atomic makes the write safe to observe. It does not lock the read-modify-write pair — two callers can both read the same starting state and one write silently wins. @warlock.js/fs has no file locking by design.

If lost updates matter, serialize the whole operation:

  • In-process — an async-aware mutex around the mergeJson call.
  • Cross-process@warlock.js/cache’s cache.lock(key, ttl, fn), backed by Redis or Postgres.