48 lines
2.2 KiB
TypeScript
48 lines
2.2 KiB
TypeScript
|
|
/**
|
||
|
|
* @module utils/jsonSafeIndexMetadata
|
||
|
|
* @description The metadata-index crossing's JSON-safety law, as a leaf
|
||
|
|
* function both the coordinator and the transaction operations share.
|
||
|
|
*
|
||
|
|
* The seam's metadata is JSON-safe BY CONTRACT (a native provider serializes
|
||
|
|
* it; u64 ints as Number corrupt above 2^53) — but `resolveVerbEndpointInts`
|
||
|
|
* MIRRORS the resolved endpoint ints onto the verb object itself as BigInt
|
||
|
|
* (`verb.sourceInt`/`targetInt`), so a verb object reused as index metadata
|
||
|
|
* carries BigInts into JSON.stringify, which throws, aborting the whole
|
||
|
|
* transaction. Endpoint ints ride their OWN op params on the graph legs — the
|
||
|
|
* metadata crossing drops every BigInt-valued top-level key instead of
|
||
|
|
* guessing at a lossy numeric encoding.
|
||
|
|
*
|
||
|
|
* WHY THIS IS A LEAF MODULE, ENFORCED AT THE CROSSING: sanitizing only at
|
||
|
|
* operation-construction time is not enough. `transact()`'s delete legs pass
|
||
|
|
* the SAME verb object to both the graph-retraction op (whose endpoint-int
|
||
|
|
* thunk deliberately resolves at EXECUTE time, for same-batch forward refs)
|
||
|
|
* and the metadata-retraction op. At plan time the verb is still clean, so a
|
||
|
|
* plan-time sanitize returns the same reference — then the graph op executes
|
||
|
|
* first, mirrors the BigInt ints onto the shared object, and the metadata op
|
||
|
|
* crosses the seam with them (found by the first fleet adoption of the native
|
||
|
|
* pair: every transact-wrapped edge delete aborted). The crossing itself is
|
||
|
|
* the only place ordering cannot bypass.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* A JSON-safe view of a record bound for the metadata-index crossing.
|
||
|
|
*
|
||
|
|
* @param metadata - The candidate index-metadata record.
|
||
|
|
* @returns The same object when already JSON-safe, else a shallow copy
|
||
|
|
* without the BigInt-valued keys.
|
||
|
|
*/
|
||
|
|
export function jsonSafeIndexMetadata(metadata: unknown): unknown {
|
||
|
|
if (metadata === null || typeof metadata !== 'object') return metadata
|
||
|
|
const rec = metadata as Record<string, unknown>
|
||
|
|
let hasBigint = false
|
||
|
|
for (const k in rec) {
|
||
|
|
if (typeof rec[k] === 'bigint') { hasBigint = true; break }
|
||
|
|
}
|
||
|
|
if (!hasBigint) return metadata
|
||
|
|
const out: Record<string, unknown> = {}
|
||
|
|
for (const k in rec) {
|
||
|
|
if (typeof rec[k] !== 'bigint') out[k] = rec[k]
|
||
|
|
}
|
||
|
|
return out
|
||
|
|
}
|