mockingpug
Concepts

Reconciliation & Storage

How mockingpug decides what to (re)generate, and where data lives

Store adapters

mockingpug ships two StoreAdapter implementations:

  • MemoryStoreAdapter: a plain in-process Map. Nothing survives a process restart or (in the browser) a page reload. This is the right choice for mockingpug/react in a SPA, since there's no filesystem to write to anyway.
  • FileStoreAdapter: one JSON file per entity under .mockingpug/db/<entity>.json ({ meta, records }). This is the default for the CLI and mockingpug/next, so mutations made while testing (POST/PUT/DELETE) and the dataset itself survive between next dev restarts.

Configured via mock.config.js's persist.adapter: 'memory' | 'file'; see Reference → mock.config.js.

persist.strategy

  • 'always' (default): every generate() call reconciles: it compares each entity's current schema against what was previously generated, and only touches what actually changed.
  • 'fresh': wipes the store first; every run is a full regeneration from scratch.

How reconciliation decides what changed

Each entity's stored metadata includes a fingerprint, a stable hash of its data block (field names + generator types, independent of key order). Before regenerating anything, mockingpug compares the old fingerprint's per-field hashes against the current schema and produces a plan covering exactly these cases, only doing the work each one requires:

ChangeWhat happens
New entity (no prior fingerprint)Full generation of amount records.
Unchanged schema, unchanged amountSkipped entirely: not even re-read/re-hashed beyond the cheap fingerprint comparison. Reported as skipped in the CLI's generate output.
amount increasedExisting records untouched; new records appended, continuing number.increment counters past the current max (not restarting at 1).
amount decreasedGenerated (_seed: true) records are trimmed from the end first; only if that's not enough does trimming touch manually-created records.
Field addedOnly the new field is generated and added to every existing record; other fields are untouched.
Field removedThe key is deleted from every existing record; nothing else regenerated.
Field's generator type changedOnly that field is regenerated on every existing record it applies to (same seed, so still deterministic per record) — except records covered by a fixture, whose fixed fields are reapplied afterward regardless.
fixtures added, removed, or editedReapplied positionally onto records 0..fixtures.length - 1 after every other step.
Any combination of the above at onceApplied in this order: shrink → remove fields → change/add fields → grow → reapply fixtures.
Schema deleted entirely (entity still in the store)Reported as an orphan: data left behind with no corresponding schema. Not deleted automatically; see mpug prune in the CLI guide.

The practical effect: editing one field in a 10,000-record entity regenerates that one field on 10,000 records. It does not throw away and regenerate the other 9 fields, and it does not touch any other entity.

Manual mutations survive reconciliation

Records created via POST while testing (not part of the original amount) are tracked as manual (_seed: false internally; this and _index are stripped from every API response, never visible to your app). When amount shrinks, generated records are trimmed first specifically so manual test data isn't silently deleted by a schema change elsewhere. This is only trim protection, though: a manually-created record's fields are still regenerated like any other record's if their generator type changes later.

If you need specific field values to stay fixed no matter what else changes in the schema, that's a stronger guarantee than "survives trimming", declare them as fixtures instead.

Safe merging

PUT/PATCH bodies are merged into a stored record via a merge function that explicitly drops __proto__/constructor/prototype keys at every level of nesting, rather than a bare {...target, ...body} spread (which does not protect against prototype pollution). See Security for the full threat model.

On this page