flugrekorder 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +289 -0
- package/dist/flugrekorder.d.mts +84 -0
- package/dist/flugrekorder.d.ts +84 -0
- package/dist/flugrekorder.global.js +282 -0
- package/dist/flugrekorder.global.js.map +1 -0
- package/dist/flugrekorder.js +290 -0
- package/dist/flugrekorder.js.map +1 -0
- package/dist/flugrekorder.mjs +260 -0
- package/dist/flugrekorder.mjs.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../source/flugrekorder.ts"],"sourcesContent":["import type { Writable } from 'node:stream';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Any value that can be wrapped in a Proxy — objects and functions. */\n// biome-ignore lint/complexity/noBannedTypes: Function is intentional — Proxiable must accept any callable\nexport type Proxiable = object | Function;\n\n/** Reflect traps that operate on a property — carry a parent ID and key in their origin. */\nexport type PropertyTrap =\n\t| 'get'\n\t| 'set'\n\t| 'defineProperty'\n\t| 'getOwnPropertyDescriptor';\n\n/** Reflect traps that invoke a callable — carry a source ID in their origin. */\nexport type CallTrap = 'apply' | 'construct';\n\n/** Describes how a proxy was created — which trap fired, on which parent, and under which key or source. Null for root proxies. */\nexport type Origin =\n\t| { trap: PropertyTrap; parent: string; key: string | symbol }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** Origin with symbol keys coerced to strings — safe to include in a Rekording. */\ntype SerializedOrigin =\n\t| { trap: PropertyTrap; parent: string; key: string }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** A JSON-safe representation of any value. Proxiable values are replaced with `{ $proxy: id }` tags. */\nexport type Serialized =\n\t| string\n\t| number\n\t| boolean\n\t| bigint\n\t| null\n\t| undefined\n\t| { readonly $proxy: string }\n\t| Array<Serialized>\n\t| { [key: string]: Serialized };\n\n/** A single recorded interaction — one Reflect trap firing on one proxy. */\nexport type Rekording = {\n\tid: string;\n\ttrap: string;\n\torigin: SerializedOrigin;\n\targs: Array<Serialized>;\n\tresult: Serialized;\n};\n\n/** Resolved runtime configuration — derived from CreateOptions and passed through the proxy factory. */\ntype Config = {\n\twrite: (r: Rekording) => void;\n\trecursive: boolean;\n\tonly: Set<string> | null;\n};\n\n/** A function that conditionally wraps a value in a proxy. */\ntype Wrapper = (v: unknown) => unknown;\n\n/** Pre/post hooks for a Reflect trap — transform args before dispatch and/or wrap the result. */\ntype Spec = {\n\tpre?: (\n\t\targs: Array<unknown>,\n\t\twrap: Wrapper,\n\t\tknown: Wrapper,\n\t) => Array<unknown>;\n\tpost?: (result: unknown, args: Array<unknown>, wrap: Wrapper) => unknown;\n};\n\n// ─── Graph ────────────────────────────────────────────────────────────────────\n\n/** A node in the proxy graph — links a proxy to its original target, its origin, and its ID. */\ntype GraphNode = {\n\treadonly id: string;\n\treadonly proxy: Proxiable;\n\treadonly target: Proxiable;\n\treadonly origin: Origin;\n};\n\n/**\n * Session-scoped proxy registry.\n * Each `create()` call produces its own Graph so proxied trees are\n * independent and GC-eligible once no longer referenced.\n */\nclass Graph {\n\t#byId = new Map<string, GraphNode>();\n\t#byProxy = new WeakMap<Proxiable, GraphNode>();\n\t#byTarget = new WeakMap<Proxiable, GraphNode>();\n\t#generator: () => string;\n\n\tconstructor(id: number | (() => string)) {\n\t\tlet counter = typeof id === 'number' ? id : 0;\n\n\t\tthis.#generator = typeof id === 'function' ? id : () => `#${++counter}`;\n\t}\n\n\tnextId(): string {\n\t\treturn this.#generator();\n\t}\n\n\tgetByProxy(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byProxy.get(v);\n\t}\n\tgetByTarget(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byTarget.get(v);\n\t}\n\tgetById(id: string): GraphNode | undefined {\n\t\treturn this.#byId.get(id);\n\t}\n\n\tregister(\n\t\tproxy: Proxiable,\n\t\ttarget: Proxiable,\n\t\torigin: Origin,\n\t\tid: string,\n\t): GraphNode {\n\t\tconst node: GraphNode = { id, proxy, target, origin };\n\n\t\tthis.#byId.set(id, node);\n\t\tthis.#byProxy.set(proxy, node);\n\t\tthis.#byTarget.set(target, node);\n\n\t\treturn node;\n\t}\n}\n\n// Module-level weak index: proxy → owning graph.\n// WeakMap — does not prevent GC of either the proxy or the graph.\nconst graphOf = new WeakMap<Proxiable, Graph>();\n\n// All known proxies across all graphs — guards against double-wrapping.\n// WeakSet — does not prevent GC.\nconst allProxies = new WeakSet<Proxiable>();\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\n/** Returns true for any value that can meaningfully be wrapped in a Proxy. */\nfunction isProxiable(value: unknown): value is Proxiable {\n\treturn (\n\t\tvalue !== null &&\n\t\t(typeof value === 'object' || typeof value === 'function')\n\t);\n}\n\n/** Maps a typeof pattern to a serialization handler. */\ntype Mapping = {\n\tmatch: RegExp;\n\tmap: (v: unknown, graph: Graph, seen: Set<unknown>) => Serialized;\n};\n\n/** Serializes an object or function value — tags known proxies by ID, inlines arrays and plain objects. */\nfunction serializeProxiable(\n\tv: unknown,\n\tgraph: Graph,\n\tseen: Set<unknown>,\n): Serialized {\n\t// Check for a known proxy BEFORE Array.isArray: iterating a proxied\n\t// array via its proxy triggers get traps which call serialize again,\n\t// causing infinite recursion. A proxy is always tagged by ID.\n\tconst node =\n\t\tgraph.getByProxy(<Proxiable>v) ?? graph.getByTarget(<Proxiable>v);\n\n\tif (node !== undefined) return { $proxy: node.id };\n\t// Plain (unproxied) arrays are safe to iterate directly.\n\tif (Array.isArray(v))\n\t\treturn (<Array<unknown>>v).map((item) => serialize(item, graph, seen));\n\t// Plain (unproxied) objects: serialize by value with a circular-reference guard.\n\tif (seen.has(v)) return { $proxy: '?' };\n\n\tseen.add(v);\n\n\tconst result = Object.fromEntries(\n\t\tObject.entries(<object>v).map(([k, val]) => [\n\t\t\tk,\n\t\t\tserialize(val, graph, seen),\n\t\t]),\n\t);\n\n\tseen.delete(v);\n\n\treturn result;\n}\n\n/** Ordered serialization handlers — first match wins; unmatched values fall through to String(). */\nconst mappings: Array<Mapping> = [\n\t{ match: /number|boolean|bigint/, map: (v) => <Serialized>v },\n\t{ match: /object|function/, map: serializeProxiable },\n];\n\n/** Converts any value to a JSON-safe Serialized form, tagging graph members by ID. */\nfunction serialize(\n\tv: unknown,\n\tgraph: Graph,\n\tseen = new Set<unknown>(),\n): Serialized {\n\tif (v === null || v === undefined) return v;\n\n\tconst { map = String } =\n\t\tmappings.find(({ match }) => match.test(typeof v)) ?? {};\n\n\treturn map(v, graph, seen);\n}\n\n/** Converts an Origin to its serialized form — coerces symbol keys to strings. */\nfunction serializeOrigin(o: Origin): SerializedOrigin {\n\tif (!o) return null;\n\tif ('key' in o)\n\t\treturn { trap: o.trap, parent: o.parent, key: String(o.key) };\n\n\treturn o;\n}\n\n// ─── Specs ────────────────────────────────────────────────────────────────────\n\n/** Per-trap hooks that transform arguments and results to maintain proxy transparency. */\nconst specs: Partial<Record<string, Spec>> = {\n\tget: {\n\t\tpost: (result, [, key], wrap) =>\n\t\t\tkey === 'prototype' ? result : wrap(result),\n\t},\n\tset: {\n\t\tpre: ([target, key, value, receiver], wrap) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\twrap(value),\n\t\t\treceiver,\n\t\t],\n\t},\n\tapply: {\n\t\t// thisArg is wrapped normally (it's always a graph node).\n\t\t// Call arguments are wrapped with known — only existing graph nodes\n\t\t// get proxied; plain data passes through and is inlined by serialize().\n\t\tpre: ([target, thisArg, callArgs], wrap, known) => [\n\t\t\ttarget,\n\t\t\twrap(thisArg),\n\t\t\t(<Array<unknown>>callArgs).map(known),\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tconstruct: {\n\t\tpre: ([target, callArgs, newTarget], wrap) => [\n\t\t\ttarget,\n\t\t\t(<Array<unknown>>callArgs).map(wrap),\n\t\t\tnewTarget,\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tdefineProperty: {\n\t\tpre: (args, wrap) => {\n\t\t\tconst [target, key, descriptor] = <\n\t\t\t\t[unknown, unknown, PropertyDescriptor]\n\t\t\t>args;\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (descriptor.value != null) patch.value = wrap(descriptor.value);\n\t\t\tif (typeof descriptor.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(descriptor.get);\n\t\t\tif (typeof descriptor.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(descriptor.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? [target, key, { ...descriptor, ...patch }]\n\t\t\t\t: args;\n\t\t},\n\t},\n\tgetOwnPropertyDescriptor: {\n\t\tpost: (result, _args, wrap) => {\n\t\t\tconst desc = <PropertyDescriptor | undefined>result;\n\n\t\t\tif (!desc) return result;\n\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (desc.value != null) patch.value = wrap(desc.value);\n\t\t\tif (typeof desc.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(desc.get);\n\t\t\tif (typeof desc.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(desc.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? { ...desc, ...patch }\n\t\t\t\t: result;\n\t\t},\n\t},\n};\n\n// ─── Core proxy factory ───────────────────────────────────────────────────────\n\n/**\n * Creates a recording proxy for `target` within `graph`.\n * Reuses existing proxies for stability, handles Promises specially,\n * and registers every new proxy in both the graph and the module-level index.\n */\nfunction makeProxy<T extends Proxiable>(\n\ttarget: T,\n\tgraph: Graph,\n\tconfig: Config,\n\torigin: Origin,\n): T {\n\t// Already a proxy (in any graph) — return unchanged, preventing double-wrapping.\n\tif (allProxies.has(<Proxiable>target)) return target;\n\n\t// Already have a proxy for this original — reuse it (stability guarantee).\n\tconst existing = graph.getByTarget(<Proxiable>target);\n\n\tif (existing) return <T>existing.proxy;\n\n\t// Promises cannot be proxied directly: native methods like .then() check for\n\t// the [[PromiseState]] internal slot and throw if `this` is a Proxy. Instead,\n\t// return a new Promise that resolves to a proxy of the settled value.\n\tif (target instanceof Promise) {\n\t\tconst chained = <T>(\n\t\t\t(<unknown>(\n\t\t\t\ttarget.then((value) =>\n\t\t\t\t\tisProxiable(value)\n\t\t\t\t\t\t? makeProxy(<Proxiable>value, graph, config, origin)\n\t\t\t\t\t\t: value,\n\t\t\t\t)\n\t\t\t))\n\t\t);\n\t\t// Register with a placeholder node so stability lookups work.\n\t\tconst id = graph.nextId();\n\n\t\tgraph.register(<Proxiable>chained, <Proxiable>target, origin, id);\n\t\tgraphOf.set(<Proxiable>chained, graph);\n\n\t\treturn chained;\n\t}\n\n\tconst proxyId = graph.nextId();\n\n\tlet pxy!: T;\n\n\tconst traps = (<Array<keyof typeof Reflect>>(\n\t\tObject.getOwnPropertyNames(Reflect)\n\t)).filter((trap) => config.only === null || config.only.has(trap));\n\n\tconst handler: ProxyHandler<Proxiable> = Object.fromEntries(\n\t\ttraps.map((trap) => [\n\t\t\ttrap,\n\t\t\t(...rawArgs: Array<unknown>) => {\n\t\t\t\tconst selfId = (<GraphNode>graph.getByProxy(pxy)).id;\n\n\t\t\t\tconst childOrigin: Origin =\n\t\t\t\t\t/get|set|defineProperty|getOwnPropertyDescriptor/.test(trap)\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\ttrap: <PropertyTrap>trap,\n\t\t\t\t\t\t\t\tparent: selfId,\n\t\t\t\t\t\t\t\tkey: <string | symbol>rawArgs[1],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: /apply|construct/.test(trap)\n\t\t\t\t\t\t\t? { trap: <CallTrap>trap, source: selfId }\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\tconst wrap: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v) || allProxies.has(<Proxiable>v))\n\t\t\t\t\t\treturn v;\n\t\t\t\t\tif (!config.recursive) return v;\n\n\t\t\t\t\treturn makeProxy(<Proxiable>v, graph, config, childOrigin);\n\t\t\t\t};\n\n\t\t\t\t// Only wraps values already in the graph — new plain data passes through.\n\t\t\t\tconst known: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v)) return v;\n\t\t\t\t\tif (allProxies.has(<Proxiable>v)) return v;\n\n\t\t\t\t\tconst existing = graph.getByTarget(<Proxiable>v);\n\n\t\t\t\t\tif (existing) return existing.proxy;\n\n\t\t\t\t\treturn v;\n\t\t\t\t};\n\n\t\t\t\tconst spec = specs[trap] ?? {};\n\t\t\t\tconst args = spec.pre\n\t\t\t\t\t? spec.pre(rawArgs, wrap, known)\n\t\t\t\t\t: rawArgs;\n\t\t\t\t// biome-ignore lint/complexity/noBannedTypes: dynamic Reflect dispatch requires Function cast\n\t\t\t\tconst result = (<Function>Reflect[trap])(...args);\n\t\t\t\tconst output = spec.post\n\t\t\t\t\t? spec.post(result, args, wrap)\n\t\t\t\t\t: result;\n\n\t\t\t\tconfig.write({\n\t\t\t\t\tid: graph.nextId(),\n\t\t\t\t\ttrap,\n\t\t\t\t\torigin: serializeOrigin(childOrigin),\n\t\t\t\t\targs: args.map((arg) => serialize(arg, graph)),\n\t\t\t\t\tresult: serialize(output, graph),\n\t\t\t\t});\n\n\t\t\t\treturn output;\n\t\t\t},\n\t\t]),\n\t);\n\n\tpxy = <T>(<unknown>new Proxy(<Proxiable>target, handler));\n\n\tgraph.register(<Proxiable>pxy, <Proxiable>target, origin, proxyId);\n\tgraphOf.set(<Proxiable>pxy, graph);\n\tallProxies.add(<Proxiable>pxy);\n\n\treturn pxy;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\ntype CreateOptions = {\n\tid?: number | (() => string);\n\trecursive?: boolean;\n\tonly?: string[];\n} & (\n\t| { stream: Writable; callback?: never }\n\t| { callback: (record: Rekording) => void; stream?: never }\n);\n\n/**\n * Wraps `target` in a transparent recording proxy.\n * Every Reflect trap that fires emits a `Rekording` to `callback` or `stream`.\n */\nexport function create<T extends Proxiable>(\n\ttarget: T,\n\toptions: CreateOptions,\n): T {\n\tconst { stream, callback } = options;\n\tconst write: (r: Rekording) => void = stream\n\t\t? (r) => stream.write(`${JSON.stringify(r)}\\n`)\n\t\t: // biome-ignore lint/style/noNonNullAssertion: CreateOptions guarantees stream or callback is set — TypeScript cannot express this mutual exclusion\n\t\t\tcallback!;\n\tconst recursive = options.recursive !== false;\n\tconst only = options.only ? new Set(options.only) : null;\n\tconst graph = new Graph(options.id ?? 0);\n\n\treturn makeProxy(target, graph, { write, recursive, only }, null);\n}\n\n/** Returns `true` if `value` is a proxy created by this module. */\nexport function isFlugrekorder(value: unknown): value is Proxiable {\n\treturn isProxiable(value) && allProxies.has(<Proxiable>value);\n}\n\n/** Returns the original unwrapped target of a proxy, or `null` for non-proxies. */\nexport function getTarget(pxy: Proxiable): Proxiable | null {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.target ?? null;\n}\n\n/**\n * Looks up a proxy by its recorded ID within the same graph as `pxy`.\n * Use this to resolve `{ $proxy: id }` references in recorded args and results back to live proxies.\n */\nexport function getProxyById(\n\tid: string,\n\tpxy: Proxiable,\n): Proxiable | undefined {\n\treturn graphOf.get(pxy)?.getById(id)?.proxy;\n}\n\n/** Returns the `Origin` of a proxy — how and from where it was created. Returns `null` for root proxies and non-proxies. */\nexport function getOrigin(pxy: Proxiable): Origin {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.origin ?? null;\n}\n\n/**\n * Walks the origin chain from the root proxy down to `pxy`.\n * Returns an ordered array of `{ proxy, origin }` pairs, root first.\n * Returns an empty array for non-proxies.\n */\nexport function getAncestors(\n\tpxy: Proxiable,\n): Array<{ proxy: Proxiable; origin: Origin }> {\n\tconst graph = graphOf.get(pxy);\n\n\tif (!graph) return [];\n\n\tconst result: Array<{ proxy: Proxiable; origin: Origin }> = [];\n\tlet node = graph.getByProxy(pxy);\n\n\twhile (node) {\n\t\tresult.unshift({ proxy: node.proxy, origin: node.origin });\n\t\tif (!node.origin) break;\n\n\t\tconst parentId =\n\t\t\t'parent' in node.origin ? node.origin.parent : node.origin.source;\n\n\t\tnode = graph.getById(parentId);\n\t}\n\n\treturn result;\n}\n\n/**\n * Returns a human-readable dotted path string for a proxy.\n * Function and constructor calls are annotated with `()`.\n * Returns an empty string for the root proxy and for non-proxies.\n */\nexport function getPath(pxy: Proxiable): string {\n\tconst ancestors = getAncestors(pxy);\n\tconst parts: Array<string> = [];\n\n\tfor (const { origin: o } of ancestors) {\n\t\tif (!o) continue;\n\t\tif ('key' in o) {\n\t\t\tparts.push(String(o.key));\n\t\t} else {\n\t\t\tif (parts.length > 0) {\n\t\t\t\tparts[parts.length - 1] += '()';\n\t\t\t} else {\n\t\t\t\tparts.push('()');\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join('.');\n}\n"],"mappings":"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","names":["existing"]}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
8
|
+
|
|
9
|
+
// source/flugrekorder.ts
|
|
10
|
+
var _byId, _byProxy, _byTarget, _generator;
|
|
11
|
+
var Graph = class {
|
|
12
|
+
constructor(id) {
|
|
13
|
+
__privateAdd(this, _byId, /* @__PURE__ */ new Map());
|
|
14
|
+
__privateAdd(this, _byProxy, /* @__PURE__ */ new WeakMap());
|
|
15
|
+
__privateAdd(this, _byTarget, /* @__PURE__ */ new WeakMap());
|
|
16
|
+
__privateAdd(this, _generator);
|
|
17
|
+
let counter = typeof id === "number" ? id : 0;
|
|
18
|
+
__privateSet(this, _generator, typeof id === "function" ? id : () => `#${++counter}`);
|
|
19
|
+
}
|
|
20
|
+
nextId() {
|
|
21
|
+
return __privateGet(this, _generator).call(this);
|
|
22
|
+
}
|
|
23
|
+
getByProxy(v) {
|
|
24
|
+
return __privateGet(this, _byProxy).get(v);
|
|
25
|
+
}
|
|
26
|
+
getByTarget(v) {
|
|
27
|
+
return __privateGet(this, _byTarget).get(v);
|
|
28
|
+
}
|
|
29
|
+
getById(id) {
|
|
30
|
+
return __privateGet(this, _byId).get(id);
|
|
31
|
+
}
|
|
32
|
+
register(proxy, target, origin, id) {
|
|
33
|
+
const node = { id, proxy, target, origin };
|
|
34
|
+
__privateGet(this, _byId).set(id, node);
|
|
35
|
+
__privateGet(this, _byProxy).set(proxy, node);
|
|
36
|
+
__privateGet(this, _byTarget).set(target, node);
|
|
37
|
+
return node;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
_byId = new WeakMap();
|
|
41
|
+
_byProxy = new WeakMap();
|
|
42
|
+
_byTarget = new WeakMap();
|
|
43
|
+
_generator = new WeakMap();
|
|
44
|
+
var graphOf = /* @__PURE__ */ new WeakMap();
|
|
45
|
+
var allProxies = /* @__PURE__ */ new WeakSet();
|
|
46
|
+
function isProxiable(value) {
|
|
47
|
+
return value !== null && (typeof value === "object" || typeof value === "function");
|
|
48
|
+
}
|
|
49
|
+
function serializeProxiable(v, graph, seen) {
|
|
50
|
+
const node = graph.getByProxy(v) ?? graph.getByTarget(v);
|
|
51
|
+
if (node !== void 0) return { $proxy: node.id };
|
|
52
|
+
if (Array.isArray(v))
|
|
53
|
+
return v.map((item) => serialize(item, graph, seen));
|
|
54
|
+
if (seen.has(v)) return { $proxy: "?" };
|
|
55
|
+
seen.add(v);
|
|
56
|
+
const result = Object.fromEntries(
|
|
57
|
+
Object.entries(v).map(([k, val]) => [
|
|
58
|
+
k,
|
|
59
|
+
serialize(val, graph, seen)
|
|
60
|
+
])
|
|
61
|
+
);
|
|
62
|
+
seen.delete(v);
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
var mappings = [
|
|
66
|
+
{ match: /number|boolean|bigint/, map: (v) => v },
|
|
67
|
+
{ match: /object|function/, map: serializeProxiable }
|
|
68
|
+
];
|
|
69
|
+
function serialize(v, graph, seen = /* @__PURE__ */ new Set()) {
|
|
70
|
+
if (v === null || v === void 0) return v;
|
|
71
|
+
const { map = String } = mappings.find(({ match }) => match.test(typeof v)) ?? {};
|
|
72
|
+
return map(v, graph, seen);
|
|
73
|
+
}
|
|
74
|
+
function serializeOrigin(o) {
|
|
75
|
+
if (!o) return null;
|
|
76
|
+
if ("key" in o)
|
|
77
|
+
return { trap: o.trap, parent: o.parent, key: String(o.key) };
|
|
78
|
+
return o;
|
|
79
|
+
}
|
|
80
|
+
var specs = {
|
|
81
|
+
get: {
|
|
82
|
+
post: (result, [, key], wrap) => key === "prototype" ? result : wrap(result)
|
|
83
|
+
},
|
|
84
|
+
set: {
|
|
85
|
+
pre: ([target, key, value, receiver], wrap) => [
|
|
86
|
+
target,
|
|
87
|
+
key,
|
|
88
|
+
wrap(value),
|
|
89
|
+
receiver
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
apply: {
|
|
93
|
+
// thisArg is wrapped normally (it's always a graph node).
|
|
94
|
+
// Call arguments are wrapped with known — only existing graph nodes
|
|
95
|
+
// get proxied; plain data passes through and is inlined by serialize().
|
|
96
|
+
pre: ([target, thisArg, callArgs], wrap, known) => [
|
|
97
|
+
target,
|
|
98
|
+
wrap(thisArg),
|
|
99
|
+
callArgs.map(known)
|
|
100
|
+
],
|
|
101
|
+
post: (result, _args, wrap) => wrap(result)
|
|
102
|
+
},
|
|
103
|
+
construct: {
|
|
104
|
+
pre: ([target, callArgs, newTarget], wrap) => [
|
|
105
|
+
target,
|
|
106
|
+
callArgs.map(wrap),
|
|
107
|
+
newTarget
|
|
108
|
+
],
|
|
109
|
+
post: (result, _args, wrap) => wrap(result)
|
|
110
|
+
},
|
|
111
|
+
defineProperty: {
|
|
112
|
+
pre: (args, wrap) => {
|
|
113
|
+
const [target, key, descriptor] = args;
|
|
114
|
+
const patch = {};
|
|
115
|
+
if (descriptor.value != null) patch.value = wrap(descriptor.value);
|
|
116
|
+
if (typeof descriptor.get === "function")
|
|
117
|
+
patch.get = wrap(descriptor.get);
|
|
118
|
+
if (typeof descriptor.set === "function")
|
|
119
|
+
patch.set = wrap(descriptor.set);
|
|
120
|
+
return Object.keys(patch).length > 0 ? [target, key, { ...descriptor, ...patch }] : args;
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
getOwnPropertyDescriptor: {
|
|
124
|
+
post: (result, _args, wrap) => {
|
|
125
|
+
const desc = result;
|
|
126
|
+
if (!desc) return result;
|
|
127
|
+
const patch = {};
|
|
128
|
+
if (desc.value != null) patch.value = wrap(desc.value);
|
|
129
|
+
if (typeof desc.get === "function")
|
|
130
|
+
patch.get = wrap(desc.get);
|
|
131
|
+
if (typeof desc.set === "function")
|
|
132
|
+
patch.set = wrap(desc.set);
|
|
133
|
+
return Object.keys(patch).length > 0 ? { ...desc, ...patch } : result;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
function makeProxy(target, graph, config, origin) {
|
|
138
|
+
if (allProxies.has(target)) return target;
|
|
139
|
+
const existing = graph.getByTarget(target);
|
|
140
|
+
if (existing) return existing.proxy;
|
|
141
|
+
if (target instanceof Promise) {
|
|
142
|
+
const chained = target.then(
|
|
143
|
+
(value) => isProxiable(value) ? makeProxy(value, graph, config, origin) : value
|
|
144
|
+
);
|
|
145
|
+
const id = graph.nextId();
|
|
146
|
+
graph.register(chained, target, origin, id);
|
|
147
|
+
graphOf.set(chained, graph);
|
|
148
|
+
return chained;
|
|
149
|
+
}
|
|
150
|
+
const proxyId = graph.nextId();
|
|
151
|
+
let pxy;
|
|
152
|
+
const traps = Object.getOwnPropertyNames(Reflect).filter((trap) => config.only === null || config.only.has(trap));
|
|
153
|
+
const handler = Object.fromEntries(
|
|
154
|
+
traps.map((trap) => [
|
|
155
|
+
trap,
|
|
156
|
+
(...rawArgs) => {
|
|
157
|
+
const selfId = graph.getByProxy(pxy).id;
|
|
158
|
+
const childOrigin = /get|set|defineProperty|getOwnPropertyDescriptor/.test(trap) ? {
|
|
159
|
+
trap,
|
|
160
|
+
parent: selfId,
|
|
161
|
+
key: rawArgs[1]
|
|
162
|
+
} : /apply|construct/.test(trap) ? { trap, source: selfId } : null;
|
|
163
|
+
const wrap = (v) => {
|
|
164
|
+
if (!isProxiable(v) || allProxies.has(v))
|
|
165
|
+
return v;
|
|
166
|
+
if (!config.recursive) return v;
|
|
167
|
+
return makeProxy(v, graph, config, childOrigin);
|
|
168
|
+
};
|
|
169
|
+
const known = (v) => {
|
|
170
|
+
if (!isProxiable(v)) return v;
|
|
171
|
+
if (allProxies.has(v)) return v;
|
|
172
|
+
const existing2 = graph.getByTarget(v);
|
|
173
|
+
if (existing2) return existing2.proxy;
|
|
174
|
+
return v;
|
|
175
|
+
};
|
|
176
|
+
const spec = specs[trap] ?? {};
|
|
177
|
+
const args = spec.pre ? spec.pre(rawArgs, wrap, known) : rawArgs;
|
|
178
|
+
const result = Reflect[trap](...args);
|
|
179
|
+
const output = spec.post ? spec.post(result, args, wrap) : result;
|
|
180
|
+
config.write({
|
|
181
|
+
id: graph.nextId(),
|
|
182
|
+
trap,
|
|
183
|
+
origin: serializeOrigin(childOrigin),
|
|
184
|
+
args: args.map((arg) => serialize(arg, graph)),
|
|
185
|
+
result: serialize(output, graph)
|
|
186
|
+
});
|
|
187
|
+
return output;
|
|
188
|
+
}
|
|
189
|
+
])
|
|
190
|
+
);
|
|
191
|
+
pxy = new Proxy(target, handler);
|
|
192
|
+
graph.register(pxy, target, origin, proxyId);
|
|
193
|
+
graphOf.set(pxy, graph);
|
|
194
|
+
allProxies.add(pxy);
|
|
195
|
+
return pxy;
|
|
196
|
+
}
|
|
197
|
+
function create(target, options) {
|
|
198
|
+
const { stream, callback } = options;
|
|
199
|
+
const write = stream ? (r) => stream.write(`${JSON.stringify(r)}
|
|
200
|
+
`) : (
|
|
201
|
+
// biome-ignore lint/style/noNonNullAssertion: CreateOptions guarantees stream or callback is set — TypeScript cannot express this mutual exclusion
|
|
202
|
+
callback
|
|
203
|
+
);
|
|
204
|
+
const recursive = options.recursive !== false;
|
|
205
|
+
const only = options.only ? new Set(options.only) : null;
|
|
206
|
+
const graph = new Graph(options.id ?? 0);
|
|
207
|
+
return makeProxy(target, graph, { write, recursive, only }, null);
|
|
208
|
+
}
|
|
209
|
+
function isFlugrekorder(value) {
|
|
210
|
+
return isProxiable(value) && allProxies.has(value);
|
|
211
|
+
}
|
|
212
|
+
function getTarget(pxy) {
|
|
213
|
+
return graphOf.get(pxy)?.getByProxy(pxy)?.target ?? null;
|
|
214
|
+
}
|
|
215
|
+
function getProxyById(id, pxy) {
|
|
216
|
+
return graphOf.get(pxy)?.getById(id)?.proxy;
|
|
217
|
+
}
|
|
218
|
+
function getOrigin(pxy) {
|
|
219
|
+
return graphOf.get(pxy)?.getByProxy(pxy)?.origin ?? null;
|
|
220
|
+
}
|
|
221
|
+
function getAncestors(pxy) {
|
|
222
|
+
const graph = graphOf.get(pxy);
|
|
223
|
+
if (!graph) return [];
|
|
224
|
+
const result = [];
|
|
225
|
+
let node = graph.getByProxy(pxy);
|
|
226
|
+
while (node) {
|
|
227
|
+
result.unshift({ proxy: node.proxy, origin: node.origin });
|
|
228
|
+
if (!node.origin) break;
|
|
229
|
+
const parentId = "parent" in node.origin ? node.origin.parent : node.origin.source;
|
|
230
|
+
node = graph.getById(parentId);
|
|
231
|
+
}
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
function getPath(pxy) {
|
|
235
|
+
const ancestors = getAncestors(pxy);
|
|
236
|
+
const parts = [];
|
|
237
|
+
for (const { origin: o } of ancestors) {
|
|
238
|
+
if (!o) continue;
|
|
239
|
+
if ("key" in o) {
|
|
240
|
+
parts.push(String(o.key));
|
|
241
|
+
} else {
|
|
242
|
+
if (parts.length > 0) {
|
|
243
|
+
parts[parts.length - 1] += "()";
|
|
244
|
+
} else {
|
|
245
|
+
parts.push("()");
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return parts.join(".");
|
|
250
|
+
}
|
|
251
|
+
export {
|
|
252
|
+
create,
|
|
253
|
+
getAncestors,
|
|
254
|
+
getOrigin,
|
|
255
|
+
getPath,
|
|
256
|
+
getProxyById,
|
|
257
|
+
getTarget,
|
|
258
|
+
isFlugrekorder
|
|
259
|
+
};
|
|
260
|
+
//# sourceMappingURL=flugrekorder.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../source/flugrekorder.ts"],"sourcesContent":["import type { Writable } from 'node:stream';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Any value that can be wrapped in a Proxy — objects and functions. */\n// biome-ignore lint/complexity/noBannedTypes: Function is intentional — Proxiable must accept any callable\nexport type Proxiable = object | Function;\n\n/** Reflect traps that operate on a property — carry a parent ID and key in their origin. */\nexport type PropertyTrap =\n\t| 'get'\n\t| 'set'\n\t| 'defineProperty'\n\t| 'getOwnPropertyDescriptor';\n\n/** Reflect traps that invoke a callable — carry a source ID in their origin. */\nexport type CallTrap = 'apply' | 'construct';\n\n/** Describes how a proxy was created — which trap fired, on which parent, and under which key or source. Null for root proxies. */\nexport type Origin =\n\t| { trap: PropertyTrap; parent: string; key: string | symbol }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** Origin with symbol keys coerced to strings — safe to include in a Rekording. */\ntype SerializedOrigin =\n\t| { trap: PropertyTrap; parent: string; key: string }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** A JSON-safe representation of any value. Proxiable values are replaced with `{ $proxy: id }` tags. */\nexport type Serialized =\n\t| string\n\t| number\n\t| boolean\n\t| bigint\n\t| null\n\t| undefined\n\t| { readonly $proxy: string }\n\t| Array<Serialized>\n\t| { [key: string]: Serialized };\n\n/** A single recorded interaction — one Reflect trap firing on one proxy. */\nexport type Rekording = {\n\tid: string;\n\ttrap: string;\n\torigin: SerializedOrigin;\n\targs: Array<Serialized>;\n\tresult: Serialized;\n};\n\n/** Resolved runtime configuration — derived from CreateOptions and passed through the proxy factory. */\ntype Config = {\n\twrite: (r: Rekording) => void;\n\trecursive: boolean;\n\tonly: Set<string> | null;\n};\n\n/** A function that conditionally wraps a value in a proxy. */\ntype Wrapper = (v: unknown) => unknown;\n\n/** Pre/post hooks for a Reflect trap — transform args before dispatch and/or wrap the result. */\ntype Spec = {\n\tpre?: (\n\t\targs: Array<unknown>,\n\t\twrap: Wrapper,\n\t\tknown: Wrapper,\n\t) => Array<unknown>;\n\tpost?: (result: unknown, args: Array<unknown>, wrap: Wrapper) => unknown;\n};\n\n// ─── Graph ────────────────────────────────────────────────────────────────────\n\n/** A node in the proxy graph — links a proxy to its original target, its origin, and its ID. */\ntype GraphNode = {\n\treadonly id: string;\n\treadonly proxy: Proxiable;\n\treadonly target: Proxiable;\n\treadonly origin: Origin;\n};\n\n/**\n * Session-scoped proxy registry.\n * Each `create()` call produces its own Graph so proxied trees are\n * independent and GC-eligible once no longer referenced.\n */\nclass Graph {\n\t#byId = new Map<string, GraphNode>();\n\t#byProxy = new WeakMap<Proxiable, GraphNode>();\n\t#byTarget = new WeakMap<Proxiable, GraphNode>();\n\t#generator: () => string;\n\n\tconstructor(id: number | (() => string)) {\n\t\tlet counter = typeof id === 'number' ? id : 0;\n\n\t\tthis.#generator = typeof id === 'function' ? id : () => `#${++counter}`;\n\t}\n\n\tnextId(): string {\n\t\treturn this.#generator();\n\t}\n\n\tgetByProxy(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byProxy.get(v);\n\t}\n\tgetByTarget(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byTarget.get(v);\n\t}\n\tgetById(id: string): GraphNode | undefined {\n\t\treturn this.#byId.get(id);\n\t}\n\n\tregister(\n\t\tproxy: Proxiable,\n\t\ttarget: Proxiable,\n\t\torigin: Origin,\n\t\tid: string,\n\t): GraphNode {\n\t\tconst node: GraphNode = { id, proxy, target, origin };\n\n\t\tthis.#byId.set(id, node);\n\t\tthis.#byProxy.set(proxy, node);\n\t\tthis.#byTarget.set(target, node);\n\n\t\treturn node;\n\t}\n}\n\n// Module-level weak index: proxy → owning graph.\n// WeakMap — does not prevent GC of either the proxy or the graph.\nconst graphOf = new WeakMap<Proxiable, Graph>();\n\n// All known proxies across all graphs — guards against double-wrapping.\n// WeakSet — does not prevent GC.\nconst allProxies = new WeakSet<Proxiable>();\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\n/** Returns true for any value that can meaningfully be wrapped in a Proxy. */\nfunction isProxiable(value: unknown): value is Proxiable {\n\treturn (\n\t\tvalue !== null &&\n\t\t(typeof value === 'object' || typeof value === 'function')\n\t);\n}\n\n/** Maps a typeof pattern to a serialization handler. */\ntype Mapping = {\n\tmatch: RegExp;\n\tmap: (v: unknown, graph: Graph, seen: Set<unknown>) => Serialized;\n};\n\n/** Serializes an object or function value — tags known proxies by ID, inlines arrays and plain objects. */\nfunction serializeProxiable(\n\tv: unknown,\n\tgraph: Graph,\n\tseen: Set<unknown>,\n): Serialized {\n\t// Check for a known proxy BEFORE Array.isArray: iterating a proxied\n\t// array via its proxy triggers get traps which call serialize again,\n\t// causing infinite recursion. A proxy is always tagged by ID.\n\tconst node =\n\t\tgraph.getByProxy(<Proxiable>v) ?? graph.getByTarget(<Proxiable>v);\n\n\tif (node !== undefined) return { $proxy: node.id };\n\t// Plain (unproxied) arrays are safe to iterate directly.\n\tif (Array.isArray(v))\n\t\treturn (<Array<unknown>>v).map((item) => serialize(item, graph, seen));\n\t// Plain (unproxied) objects: serialize by value with a circular-reference guard.\n\tif (seen.has(v)) return { $proxy: '?' };\n\n\tseen.add(v);\n\n\tconst result = Object.fromEntries(\n\t\tObject.entries(<object>v).map(([k, val]) => [\n\t\t\tk,\n\t\t\tserialize(val, graph, seen),\n\t\t]),\n\t);\n\n\tseen.delete(v);\n\n\treturn result;\n}\n\n/** Ordered serialization handlers — first match wins; unmatched values fall through to String(). */\nconst mappings: Array<Mapping> = [\n\t{ match: /number|boolean|bigint/, map: (v) => <Serialized>v },\n\t{ match: /object|function/, map: serializeProxiable },\n];\n\n/** Converts any value to a JSON-safe Serialized form, tagging graph members by ID. */\nfunction serialize(\n\tv: unknown,\n\tgraph: Graph,\n\tseen = new Set<unknown>(),\n): Serialized {\n\tif (v === null || v === undefined) return v;\n\n\tconst { map = String } =\n\t\tmappings.find(({ match }) => match.test(typeof v)) ?? {};\n\n\treturn map(v, graph, seen);\n}\n\n/** Converts an Origin to its serialized form — coerces symbol keys to strings. */\nfunction serializeOrigin(o: Origin): SerializedOrigin {\n\tif (!o) return null;\n\tif ('key' in o)\n\t\treturn { trap: o.trap, parent: o.parent, key: String(o.key) };\n\n\treturn o;\n}\n\n// ─── Specs ────────────────────────────────────────────────────────────────────\n\n/** Per-trap hooks that transform arguments and results to maintain proxy transparency. */\nconst specs: Partial<Record<string, Spec>> = {\n\tget: {\n\t\tpost: (result, [, key], wrap) =>\n\t\t\tkey === 'prototype' ? result : wrap(result),\n\t},\n\tset: {\n\t\tpre: ([target, key, value, receiver], wrap) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\twrap(value),\n\t\t\treceiver,\n\t\t],\n\t},\n\tapply: {\n\t\t// thisArg is wrapped normally (it's always a graph node).\n\t\t// Call arguments are wrapped with known — only existing graph nodes\n\t\t// get proxied; plain data passes through and is inlined by serialize().\n\t\tpre: ([target, thisArg, callArgs], wrap, known) => [\n\t\t\ttarget,\n\t\t\twrap(thisArg),\n\t\t\t(<Array<unknown>>callArgs).map(known),\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tconstruct: {\n\t\tpre: ([target, callArgs, newTarget], wrap) => [\n\t\t\ttarget,\n\t\t\t(<Array<unknown>>callArgs).map(wrap),\n\t\t\tnewTarget,\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tdefineProperty: {\n\t\tpre: (args, wrap) => {\n\t\t\tconst [target, key, descriptor] = <\n\t\t\t\t[unknown, unknown, PropertyDescriptor]\n\t\t\t>args;\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (descriptor.value != null) patch.value = wrap(descriptor.value);\n\t\t\tif (typeof descriptor.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(descriptor.get);\n\t\t\tif (typeof descriptor.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(descriptor.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? [target, key, { ...descriptor, ...patch }]\n\t\t\t\t: args;\n\t\t},\n\t},\n\tgetOwnPropertyDescriptor: {\n\t\tpost: (result, _args, wrap) => {\n\t\t\tconst desc = <PropertyDescriptor | undefined>result;\n\n\t\t\tif (!desc) return result;\n\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (desc.value != null) patch.value = wrap(desc.value);\n\t\t\tif (typeof desc.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(desc.get);\n\t\t\tif (typeof desc.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(desc.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? { ...desc, ...patch }\n\t\t\t\t: result;\n\t\t},\n\t},\n};\n\n// ─── Core proxy factory ───────────────────────────────────────────────────────\n\n/**\n * Creates a recording proxy for `target` within `graph`.\n * Reuses existing proxies for stability, handles Promises specially,\n * and registers every new proxy in both the graph and the module-level index.\n */\nfunction makeProxy<T extends Proxiable>(\n\ttarget: T,\n\tgraph: Graph,\n\tconfig: Config,\n\torigin: Origin,\n): T {\n\t// Already a proxy (in any graph) — return unchanged, preventing double-wrapping.\n\tif (allProxies.has(<Proxiable>target)) return target;\n\n\t// Already have a proxy for this original — reuse it (stability guarantee).\n\tconst existing = graph.getByTarget(<Proxiable>target);\n\n\tif (existing) return <T>existing.proxy;\n\n\t// Promises cannot be proxied directly: native methods like .then() check for\n\t// the [[PromiseState]] internal slot and throw if `this` is a Proxy. Instead,\n\t// return a new Promise that resolves to a proxy of the settled value.\n\tif (target instanceof Promise) {\n\t\tconst chained = <T>(\n\t\t\t(<unknown>(\n\t\t\t\ttarget.then((value) =>\n\t\t\t\t\tisProxiable(value)\n\t\t\t\t\t\t? makeProxy(<Proxiable>value, graph, config, origin)\n\t\t\t\t\t\t: value,\n\t\t\t\t)\n\t\t\t))\n\t\t);\n\t\t// Register with a placeholder node so stability lookups work.\n\t\tconst id = graph.nextId();\n\n\t\tgraph.register(<Proxiable>chained, <Proxiable>target, origin, id);\n\t\tgraphOf.set(<Proxiable>chained, graph);\n\n\t\treturn chained;\n\t}\n\n\tconst proxyId = graph.nextId();\n\n\tlet pxy!: T;\n\n\tconst traps = (<Array<keyof typeof Reflect>>(\n\t\tObject.getOwnPropertyNames(Reflect)\n\t)).filter((trap) => config.only === null || config.only.has(trap));\n\n\tconst handler: ProxyHandler<Proxiable> = Object.fromEntries(\n\t\ttraps.map((trap) => [\n\t\t\ttrap,\n\t\t\t(...rawArgs: Array<unknown>) => {\n\t\t\t\tconst selfId = (<GraphNode>graph.getByProxy(pxy)).id;\n\n\t\t\t\tconst childOrigin: Origin =\n\t\t\t\t\t/get|set|defineProperty|getOwnPropertyDescriptor/.test(trap)\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\ttrap: <PropertyTrap>trap,\n\t\t\t\t\t\t\t\tparent: selfId,\n\t\t\t\t\t\t\t\tkey: <string | symbol>rawArgs[1],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: /apply|construct/.test(trap)\n\t\t\t\t\t\t\t? { trap: <CallTrap>trap, source: selfId }\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\tconst wrap: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v) || allProxies.has(<Proxiable>v))\n\t\t\t\t\t\treturn v;\n\t\t\t\t\tif (!config.recursive) return v;\n\n\t\t\t\t\treturn makeProxy(<Proxiable>v, graph, config, childOrigin);\n\t\t\t\t};\n\n\t\t\t\t// Only wraps values already in the graph — new plain data passes through.\n\t\t\t\tconst known: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v)) return v;\n\t\t\t\t\tif (allProxies.has(<Proxiable>v)) return v;\n\n\t\t\t\t\tconst existing = graph.getByTarget(<Proxiable>v);\n\n\t\t\t\t\tif (existing) return existing.proxy;\n\n\t\t\t\t\treturn v;\n\t\t\t\t};\n\n\t\t\t\tconst spec = specs[trap] ?? {};\n\t\t\t\tconst args = spec.pre\n\t\t\t\t\t? spec.pre(rawArgs, wrap, known)\n\t\t\t\t\t: rawArgs;\n\t\t\t\t// biome-ignore lint/complexity/noBannedTypes: dynamic Reflect dispatch requires Function cast\n\t\t\t\tconst result = (<Function>Reflect[trap])(...args);\n\t\t\t\tconst output = spec.post\n\t\t\t\t\t? spec.post(result, args, wrap)\n\t\t\t\t\t: result;\n\n\t\t\t\tconfig.write({\n\t\t\t\t\tid: graph.nextId(),\n\t\t\t\t\ttrap,\n\t\t\t\t\torigin: serializeOrigin(childOrigin),\n\t\t\t\t\targs: args.map((arg) => serialize(arg, graph)),\n\t\t\t\t\tresult: serialize(output, graph),\n\t\t\t\t});\n\n\t\t\t\treturn output;\n\t\t\t},\n\t\t]),\n\t);\n\n\tpxy = <T>(<unknown>new Proxy(<Proxiable>target, handler));\n\n\tgraph.register(<Proxiable>pxy, <Proxiable>target, origin, proxyId);\n\tgraphOf.set(<Proxiable>pxy, graph);\n\tallProxies.add(<Proxiable>pxy);\n\n\treturn pxy;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\ntype CreateOptions = {\n\tid?: number | (() => string);\n\trecursive?: boolean;\n\tonly?: string[];\n} & (\n\t| { stream: Writable; callback?: never }\n\t| { callback: (record: Rekording) => void; stream?: never }\n);\n\n/**\n * Wraps `target` in a transparent recording proxy.\n * Every Reflect trap that fires emits a `Rekording` to `callback` or `stream`.\n */\nexport function create<T extends Proxiable>(\n\ttarget: T,\n\toptions: CreateOptions,\n): T {\n\tconst { stream, callback } = options;\n\tconst write: (r: Rekording) => void = stream\n\t\t? (r) => stream.write(`${JSON.stringify(r)}\\n`)\n\t\t: // biome-ignore lint/style/noNonNullAssertion: CreateOptions guarantees stream or callback is set — TypeScript cannot express this mutual exclusion\n\t\t\tcallback!;\n\tconst recursive = options.recursive !== false;\n\tconst only = options.only ? new Set(options.only) : null;\n\tconst graph = new Graph(options.id ?? 0);\n\n\treturn makeProxy(target, graph, { write, recursive, only }, null);\n}\n\n/** Returns `true` if `value` is a proxy created by this module. */\nexport function isFlugrekorder(value: unknown): value is Proxiable {\n\treturn isProxiable(value) && allProxies.has(<Proxiable>value);\n}\n\n/** Returns the original unwrapped target of a proxy, or `null` for non-proxies. */\nexport function getTarget(pxy: Proxiable): Proxiable | null {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.target ?? null;\n}\n\n/**\n * Looks up a proxy by its recorded ID within the same graph as `pxy`.\n * Use this to resolve `{ $proxy: id }` references in recorded args and results back to live proxies.\n */\nexport function getProxyById(\n\tid: string,\n\tpxy: Proxiable,\n): Proxiable | undefined {\n\treturn graphOf.get(pxy)?.getById(id)?.proxy;\n}\n\n/** Returns the `Origin` of a proxy — how and from where it was created. Returns `null` for root proxies and non-proxies. */\nexport function getOrigin(pxy: Proxiable): Origin {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.origin ?? null;\n}\n\n/**\n * Walks the origin chain from the root proxy down to `pxy`.\n * Returns an ordered array of `{ proxy, origin }` pairs, root first.\n * Returns an empty array for non-proxies.\n */\nexport function getAncestors(\n\tpxy: Proxiable,\n): Array<{ proxy: Proxiable; origin: Origin }> {\n\tconst graph = graphOf.get(pxy);\n\n\tif (!graph) return [];\n\n\tconst result: Array<{ proxy: Proxiable; origin: Origin }> = [];\n\tlet node = graph.getByProxy(pxy);\n\n\twhile (node) {\n\t\tresult.unshift({ proxy: node.proxy, origin: node.origin });\n\t\tif (!node.origin) break;\n\n\t\tconst parentId =\n\t\t\t'parent' in node.origin ? node.origin.parent : node.origin.source;\n\n\t\tnode = graph.getById(parentId);\n\t}\n\n\treturn result;\n}\n\n/**\n * Returns a human-readable dotted path string for a proxy.\n * Function and constructor calls are annotated with `()`.\n * Returns an empty string for the root proxy and for non-proxies.\n */\nexport function getPath(pxy: Proxiable): string {\n\tconst ancestors = getAncestors(pxy);\n\tconst parts: Array<string> = [];\n\n\tfor (const { origin: o } of ancestors) {\n\t\tif (!o) continue;\n\t\tif ('key' in o) {\n\t\t\tparts.push(String(o.key));\n\t\t} else {\n\t\t\tif (parts.length > 0) {\n\t\t\t\tparts[parts.length - 1] += '()';\n\t\t\t} else {\n\t\t\t\tparts.push('()');\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join('.');\n}\n"],"mappings":"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","names":["existing"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "flugrekorder",
|
|
3
|
+
"version": "1.0.0-beta.1",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/rspieker/flugrekorder.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/rspieker/flugrekorder/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/rspieker/flugrekorder#readme",
|
|
15
|
+
"main": "dist/flugrekorder.js",
|
|
16
|
+
"module": "dist/flugrekorder.mjs",
|
|
17
|
+
"types": "dist/flugrekorder.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/flugrekorder.d.ts",
|
|
21
|
+
"import": "./dist/flugrekorder.mjs",
|
|
22
|
+
"require": "./dist/flugrekorder.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsup",
|
|
32
|
+
"lint": "biome lint source",
|
|
33
|
+
"format": "biome format source",
|
|
34
|
+
"check": "biome check source",
|
|
35
|
+
"check:write": "biome check --write source",
|
|
36
|
+
"release": "release-it --ci",
|
|
37
|
+
"release:beta": "release-it --preRelease=beta --ci",
|
|
38
|
+
"prepublishOnly": "npm run build",
|
|
39
|
+
"test": "run-script-os",
|
|
40
|
+
"test:nix": "ts-node --project tsconfig.test.json node_modules/tape/bin/tape 'source/**/*.spec.ts' | tap-arc",
|
|
41
|
+
"test:win32": "ts-node --project tsconfig.test.json node_modules/tape/bin/tape source/**/*.spec.ts | tap-arc",
|
|
42
|
+
"test:coverage": "run-script-os",
|
|
43
|
+
"test:coverage:nix": "TS_NODE_PROJECT=tsconfig.test.json nyc --reporter=html --require ts-node/register tape 'source/**/*.spec.ts' | tap-arc",
|
|
44
|
+
"test:coverage:win32": "TS_NODE_PROJECT=tsconfig.test.json nyc --require ts-node/register tape source/**/*.spec.ts | tap-arc",
|
|
45
|
+
"test:pretty": "run-script-os",
|
|
46
|
+
"test:pretty:nix": "TS_NODE_PROJECT=tsconfig.test.json nyc --require ts-node/register tape 'source/**/*.spec.ts' | tap-arc",
|
|
47
|
+
"test:pretty:win32": "TS_NODE_PROJECT=tsconfig.test.json nyc --require ts-node/register tape source/**/*.spec.ts | tap-arc",
|
|
48
|
+
"prepare": "husky || true"
|
|
49
|
+
},
|
|
50
|
+
"keywords": [
|
|
51
|
+
"proxy",
|
|
52
|
+
"recorder",
|
|
53
|
+
"reflect",
|
|
54
|
+
"trap",
|
|
55
|
+
"observer",
|
|
56
|
+
"flight recorder",
|
|
57
|
+
"logger"
|
|
58
|
+
],
|
|
59
|
+
"author": "Rogier Spieker <rogier+npm@konfirm.eu>",
|
|
60
|
+
"license": "MIT",
|
|
61
|
+
"description": "A tireless, impartial, punctilious, incurious spectator. It witnesses every interaction. It takes note. It understands nothing. Remarkably, this is a feature.",
|
|
62
|
+
"sideEffects": false,
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": ">=22"
|
|
65
|
+
},
|
|
66
|
+
"nyc": {
|
|
67
|
+
"exclude": [
|
|
68
|
+
"source/**/*.spec.ts"
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@biomejs/biome": "^2.4.15",
|
|
73
|
+
"@commitlint/config-conventional": "^20.5.3",
|
|
74
|
+
"@release-it/conventional-changelog": "^11.0.0",
|
|
75
|
+
"@types/node": "^25.8.0",
|
|
76
|
+
"@types/tape": "^5.8.1",
|
|
77
|
+
"commitlint": "^20.5.3",
|
|
78
|
+
"husky": "^9.1.7",
|
|
79
|
+
"nyc": "^18.0.0",
|
|
80
|
+
"release-it": "^20.0.1",
|
|
81
|
+
"run-script-os": "^1.1.6",
|
|
82
|
+
"tap-arc": "^1.3.2",
|
|
83
|
+
"tape": "^5.9.0",
|
|
84
|
+
"template-literal-each": "^3.0.1",
|
|
85
|
+
"ts-node": "^10.9.2",
|
|
86
|
+
"tsup": "^8.5.1",
|
|
87
|
+
"typescript": "^6.0.3"
|
|
88
|
+
}
|
|
89
|
+
}
|