chore(cli): remove NUL edge-key separator + refresh stale macro comments

Address Codex P2 nits: (1) the macro edge map packed (lib, consumer) into a
string with a literal NUL separator, which made localGraph.ts read as a binary
file to grep/rg — replace with a nested lib->consumer Map (no separator); (2)
comments claiming macro nodes/edges are 'deployed graph only' contradicted this
PR's local derivation — describe the code as it is.
This commit is contained in:
Ruben Fiszel
2026-07-05 22:38:34 +00:00
parent 32d70bd5f4
commit d294e948a5
2 changed files with 23 additions and 17 deletions
+20 -15
View File
@@ -59,8 +59,9 @@ export type GraphRunnable = {
// schema-contract warnings; only present when set (default `warn` is absent),
// mirroring the deployed graph node.
materialize_on_schema_change?: string;
// `// macros` library: the macros it defines (deployed graph only — the wasm
// asset parser does not emit them). Non-empty ⇒ definition-only node.
// `// macros` library: the macros it defines. Derived locally by
// `buildMacroEdges` (the wasm asset parser emits neither the marker nor the
// registry). Non-empty ⇒ definition-only node.
macros?: { name: string; params?: string; is_table?: boolean }[];
};
export type GraphEdge = {
@@ -95,7 +96,7 @@ export type AssetGraph = {
edges: GraphEdge[];
triggers: GraphTrigger[];
// ƒ edges from a `// macros` library to the scripts calling its macros
// (deployed graph only).
// (present on both the deployed graph and the locally-derived one).
macro_edges?: {
lib_path: string;
consumer_path: string;
@@ -697,14 +698,19 @@ function buildMacroEdges(
// (`all` is this folder's scripts).
const pipelinePaths = new Set(runnables.map((r) => r.path));
type EdgeAgg = { names: Set<string>; viaUse: boolean };
const edgeMap = new Map<string, EdgeAgg>();
const edgeKey = (lib: string, consumer: string) => `${lib}${consumer}`;
// lib_path → consumer_path → aggregate. Nested (not a packed single-string key)
// so no separator can ever collide with a path.
const edgeMap = new Map<string, Map<string, EdgeAgg>>();
const aggFor = (lib: string, consumer: string): EdgeAgg => {
const key = edgeKey(lib, consumer);
let agg = edgeMap.get(key);
let byConsumer = edgeMap.get(lib);
if (!byConsumer) {
byConsumer = new Map();
edgeMap.set(lib, byConsumer);
}
let agg = byConsumer.get(consumer);
if (!agg) {
agg = { names: new Set(), viaUse: false };
edgeMap.set(key, agg);
byConsumer.set(consumer, agg);
}
return agg;
};
@@ -734,17 +740,16 @@ function buildMacroEdges(
}
const edges = [...edgeMap.entries()]
.map(([key, agg]) => {
const [lib_path, consumer_path] = key.split("");
// `via_use` is always present (the deployed `MacroEdge` serializes it
// unconditionally) so `--json` matches byte-for-byte.
return {
.flatMap(([lib_path, byConsumer]) =>
[...byConsumer.entries()].map(([consumer_path, agg]) => ({
lib_path,
consumer_path,
macro_names: [...agg.names].sort(),
// `via_use` is always present (the deployed `MacroEdge` serializes it
// unconditionally) so `--json` matches byte-for-byte.
via_use: agg.viaUse,
};
})
})),
)
.sort((a, b) =>
a.lib_path.localeCompare(b.lib_path) ||
a.consumer_path.localeCompare(b.consumer_path),
+3 -2
View File
@@ -304,8 +304,9 @@ async function renderGraph(
}
// `// macros` libraries: badge the node with the macros it defines and list
// its consumers as ƒ edges. Deployed graphs only — the local wasm parse does
// not emit `macros`/`macro_edges`, so local mode renders them as plain nodes.
// its consumers as ƒ edges. Populated on both the deployed graph and the local
// graph (localGraph.ts derives `macros`/`macro_edges` from the working tree,
// since the wasm asset parser emits neither).
const macrosByLib = new Map(
graph.runnables
.filter((r) => (r.macros?.length ?? 0) > 0)