n8n/scripts/mutation-health/ledger.mjs
n8n-cat-bot[bot] 53ade12c27
Some checks failed
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (22.22.3) (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (24.16.0) (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
Build: Benchmark Image / build (push) Has been cancelled
Util: Sync API Docs / sync-public-api (push) Has been cancelled
refactor: Add read-all ledger API to mutation-health pipeline (#32705)
Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-20 22:03:58 +00:00

51 lines
1.9 KiB
JavaScript

#!/usr/bin/env node
/**
* Read-all ledger access.
*
* One call returns every row in the live BigQuery ledger across every
* package — call sites no longer need to invoke per package. Per-package
* behaviour is preserved by passing `pkg`, which narrows the same
* single-pass read to one package without re-fetching.
*
* Accepted body shapes (matching the reader-webhook contract):
*
* '' → { rows: [] }
* '{"ledger":[]}' → { rows: [] }
* '{"ledger":[ {row}, ... ]}' → { rows: [ {row}, ... ] }
*
* The empty-body case mirrors the reader webhook's response for packages
* it has never scored — the picker must still synthesise `new` rows from
* the source tree in that situation.
*
* Malformed JSON or a missing `ledger` array throw, leaving the caller
* to decide whether to die or fall back.
*/
import { readFile } from 'node:fs/promises';
/**
* Pure parser. Used directly by tests and via the `readLedger` wrapper.
*/
export function parseLedgerBody(raw, { pkg } = {}) {
const trimmed = typeof raw === 'string' ? raw.trim() : '';
const payload = trimmed === '' ? { ledger: [] } : JSON.parse(trimmed);
if (!payload || !Array.isArray(payload.ledger)) {
throw new Error('Ledger payload missing `ledger` array.');
}
const all = payload.ledger;
if (pkg === undefined) return { rows: all };
return { rows: all.filter((r) => r && r.package === pkg) };
}
/**
* Read the ledger file and return all rows in one pass. With `pkg`, the
* same single read is narrowed to one package — existing per-package call
* sites stay structurally identical, the pipeline can later switch to a
* single fetch shared across packages without touching the call site.
*/
export async function readLedger({ path, pkg } = {}) {
if (!path) throw new TypeError('readLedger requires a `path`');
const raw = await readFile(path, 'utf8');
return parseLedgerBody(raw, { pkg });
}