mapra 0.1.0
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 +144 -0
- package/dist/analyzer/blast-radius.d.ts +27 -0
- package/dist/analyzer/blast-radius.d.ts.map +1 -0
- package/dist/analyzer/blast-radius.js +58 -0
- package/dist/analyzer/blast-radius.js.map +1 -0
- package/dist/analyzer/churn.d.ts +26 -0
- package/dist/analyzer/churn.d.ts.map +1 -0
- package/dist/analyzer/churn.js +96 -0
- package/dist/analyzer/churn.js.map +1 -0
- package/dist/analyzer/co-change.d.ts +60 -0
- package/dist/analyzer/co-change.d.ts.map +1 -0
- package/dist/analyzer/co-change.js +153 -0
- package/dist/analyzer/co-change.js.map +1 -0
- package/dist/analyzer/conventions.d.ts +22 -0
- package/dist/analyzer/conventions.d.ts.map +1 -0
- package/dist/analyzer/conventions.js +81 -0
- package/dist/analyzer/conventions.js.map +1 -0
- package/dist/analyzer/git-hash.d.ts +11 -0
- package/dist/analyzer/git-hash.d.ts.map +1 -0
- package/dist/analyzer/git-hash.js +25 -0
- package/dist/analyzer/git-hash.js.map +1 -0
- package/dist/analyzer/graph-utils.d.ts +46 -0
- package/dist/analyzer/graph-utils.d.ts.map +1 -0
- package/dist/analyzer/graph-utils.js +145 -0
- package/dist/analyzer/graph-utils.js.map +1 -0
- package/dist/analyzer/index.d.ts +34 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +63 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/cli/hooks.d.ts +24 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +126 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/index.d.ts +18 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +818 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/plan-parser.d.ts +20 -0
- package/dist/cli/plan-parser.d.ts.map +1 -0
- package/dist/cli/plan-parser.js +104 -0
- package/dist/cli/plan-parser.js.map +1 -0
- package/dist/cli/shim.d.ts +3 -0
- package/dist/cli/shim.d.ts.map +1 -0
- package/dist/cli/shim.js +33 -0
- package/dist/cli/shim.js.map +1 -0
- package/dist/cli/templates.d.ts +28 -0
- package/dist/cli/templates.d.ts.map +1 -0
- package/dist/cli/templates.js +91 -0
- package/dist/cli/templates.js.map +1 -0
- package/dist/encoder/encode.d.ts +17 -0
- package/dist/encoder/encode.d.ts.map +1 -0
- package/dist/encoder/encode.js +270 -0
- package/dist/encoder/encode.js.map +1 -0
- package/dist/encoder/layer-infrastructure.d.ts +17 -0
- package/dist/encoder/layer-infrastructure.d.ts.map +1 -0
- package/dist/encoder/layer-infrastructure.js +232 -0
- package/dist/encoder/layer-infrastructure.js.map +1 -0
- package/dist/encoder/layer-labels.d.ts +18 -0
- package/dist/encoder/layer-labels.d.ts.map +1 -0
- package/dist/encoder/layer-labels.js +172 -0
- package/dist/encoder/layer-labels.js.map +1 -0
- package/dist/encoder/layer-terrain.d.ts +18 -0
- package/dist/encoder/layer-terrain.d.ts.map +1 -0
- package/dist/encoder/layer-terrain.js +135 -0
- package/dist/encoder/layer-terrain.js.map +1 -0
- package/dist/encoder/layout.d.ts +53 -0
- package/dist/encoder/layout.d.ts.map +1 -0
- package/dist/encoder/layout.js +178 -0
- package/dist/encoder/layout.js.map +1 -0
- package/dist/encoder/parse-strand-header.d.ts +29 -0
- package/dist/encoder/parse-strand-header.d.ts.map +1 -0
- package/dist/encoder/parse-strand-header.js +59 -0
- package/dist/encoder/parse-strand-header.js.map +1 -0
- package/dist/encoder/spatial-text-encode.d.ts +22 -0
- package/dist/encoder/spatial-text-encode.d.ts.map +1 -0
- package/dist/encoder/spatial-text-encode.js +199 -0
- package/dist/encoder/spatial-text-encode.js.map +1 -0
- package/dist/encoder/strand-format-encode-v1.d.ts +16 -0
- package/dist/encoder/strand-format-encode-v1.d.ts.map +1 -0
- package/dist/encoder/strand-format-encode-v1.js +296 -0
- package/dist/encoder/strand-format-encode-v1.js.map +1 -0
- package/dist/encoder/strand-format-encode.d.ts +21 -0
- package/dist/encoder/strand-format-encode.d.ts.map +1 -0
- package/dist/encoder/strand-format-encode.js +562 -0
- package/dist/encoder/strand-format-encode.js.map +1 -0
- package/dist/encoder/text-encode.d.ts +13 -0
- package/dist/encoder/text-encode.d.ts.map +1 -0
- package/dist/encoder/text-encode.js +123 -0
- package/dist/encoder/text-encode.js.map +1 -0
- package/dist/query/blast-radius.d.ts +14 -0
- package/dist/query/blast-radius.d.ts.map +1 -0
- package/dist/query/blast-radius.js +81 -0
- package/dist/query/blast-radius.js.map +1 -0
- package/dist/query/cache.d.ts +29 -0
- package/dist/query/cache.d.ts.map +1 -0
- package/dist/query/cache.js +138 -0
- package/dist/query/cache.js.map +1 -0
- package/dist/query/index.d.ts +2 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +46 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/resolve.d.ts +7 -0
- package/dist/query/resolve.d.ts.map +1 -0
- package/dist/query/resolve.js +24 -0
- package/dist/query/resolve.js.map +1 -0
- package/dist/query/risk-profile.d.ts +30 -0
- package/dist/query/risk-profile.d.ts.map +1 -0
- package/dist/query/risk-profile.js +94 -0
- package/dist/query/risk-profile.js.map +1 -0
- package/dist/query/test-map.d.ts +13 -0
- package/dist/query/test-map.d.ts.map +1 -0
- package/dist/query/test-map.js +43 -0
- package/dist/query/test-map.js.map +1 -0
- package/dist/scanner/index.d.ts +51 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +480 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/workspace.d.ts +11 -0
- package/dist/scanner/workspace.d.ts.map +1 -0
- package/dist/scanner/workspace.js +243 -0
- package/dist/scanner/workspace.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 3 — Labels (Precise Detail)
|
|
3
|
+
*
|
|
4
|
+
* Encodes: File names, function signatures, HTTP methods, model names.
|
|
5
|
+
* - Each node labeled with file name and key exports
|
|
6
|
+
* - API routes with HTTP methods (GET, POST, etc.)
|
|
7
|
+
* - Prisma models with field counts
|
|
8
|
+
* - Test coverage indicators
|
|
9
|
+
* - High-resolution, text-focused, minimal visual noise
|
|
10
|
+
*
|
|
11
|
+
* What the LLM learns: The precise details that Layer 1 and 2 can't show.
|
|
12
|
+
* File paths, function names, exact counts.
|
|
13
|
+
*/
|
|
14
|
+
import { computeLayout, escapeXml, TYPE_COLORS, } from "./layout.js";
|
|
15
|
+
export function encodeLabelsSVG(graph) {
|
|
16
|
+
const layout = computeLayout(graph);
|
|
17
|
+
return renderLabels(layout, graph);
|
|
18
|
+
}
|
|
19
|
+
export function encodeLabelsSVGFromLayout(layout, graph) {
|
|
20
|
+
return renderLabels(layout, graph);
|
|
21
|
+
}
|
|
22
|
+
function renderLabels(layout, graph) {
|
|
23
|
+
const { width, height, modules } = layout;
|
|
24
|
+
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}">
|
|
25
|
+
<style>
|
|
26
|
+
text { font-family: monospace; }
|
|
27
|
+
.layer-title { font-size: 14px; font-weight: bold; fill: #111; }
|
|
28
|
+
.layer-subtitle { font-size: 10px; fill: #666; }
|
|
29
|
+
.module-header { font-size: 11px; font-weight: bold; fill: #111; }
|
|
30
|
+
.module-stats { font-size: 8px; fill: #888; }
|
|
31
|
+
.file-label { font-size: 7px; fill: #333; }
|
|
32
|
+
.export-label { font-size: 6px; fill: #666; }
|
|
33
|
+
.method-badge { font-size: 6px; font-weight: bold; }
|
|
34
|
+
.type-indicator { font-size: 6px; fill: #999; }
|
|
35
|
+
</style>
|
|
36
|
+
<rect width="100%" height="100%" fill="#F8F9FA"/>
|
|
37
|
+
`;
|
|
38
|
+
// Title
|
|
39
|
+
svg += `<text x="60" y="30" class="layer-title">L3: Labels — ${escapeXml(graph.projectName)}</text>\n`;
|
|
40
|
+
svg += `<text x="60" y="45" class="layer-subtitle">${graph.totalFiles} files · ${graph.totalLines.toLocaleString()} lines · ${graph.modules.length} modules</text>\n`;
|
|
41
|
+
// Compute test coverage map for indicators
|
|
42
|
+
const testedFiles = new Set();
|
|
43
|
+
for (const edge of graph.edges) {
|
|
44
|
+
if (edge.type === "tests") {
|
|
45
|
+
testedFiles.add(edge.to);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Draw each module with detailed labels
|
|
49
|
+
for (const mod of modules) {
|
|
50
|
+
svg += drawModuleLabels(mod, testedFiles);
|
|
51
|
+
}
|
|
52
|
+
// Legend — type abbreviations
|
|
53
|
+
svg += drawLabelsLegend(width - 180, 10);
|
|
54
|
+
svg += `</svg>`;
|
|
55
|
+
return svg;
|
|
56
|
+
}
|
|
57
|
+
function drawModuleLabels(mod, testedFiles) {
|
|
58
|
+
let svg = "";
|
|
59
|
+
// Module boundary — light dashed outline
|
|
60
|
+
svg += `<rect x="${mod.x}" y="${mod.y}" width="${mod.width}" height="${mod.height}" rx="8" fill="white" stroke="#DEE2E6" stroke-width="1" opacity="0.5"/>\n`;
|
|
61
|
+
// Module header with stats
|
|
62
|
+
svg += `<text x="${mod.x + 8}" y="${mod.y + 14}" class="module-header">${escapeXml(mod.name)}/</text>\n`;
|
|
63
|
+
svg += `<text x="${mod.x + 8}" y="${mod.y + 24}" class="module-stats">${mod.nodes.length} files · ${mod.totalLines} lines</text>\n`;
|
|
64
|
+
// Label each node
|
|
65
|
+
for (const node of mod.nodes) {
|
|
66
|
+
svg += drawNodeLabel(node, testedFiles);
|
|
67
|
+
}
|
|
68
|
+
return svg;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Draw a label at each node position with:
|
|
72
|
+
* - Tiny type-colored dot (for spatial reference)
|
|
73
|
+
* - File name (without extension)
|
|
74
|
+
* - Key exports or metadata (HTTP methods, models)
|
|
75
|
+
* - Test coverage indicator
|
|
76
|
+
*/
|
|
77
|
+
function drawNodeLabel(node, testedFiles) {
|
|
78
|
+
let svg = "";
|
|
79
|
+
// Tiny dot for spatial reference (matches node position from other layers)
|
|
80
|
+
svg += `<circle cx="${node.x.toFixed(1)}" cy="${node.y.toFixed(1)}" r="2" fill="${node.color}" opacity="0.5"/>\n`;
|
|
81
|
+
const shortName = node.name.replace(/\.(ts|tsx|js|jsx|prisma)$/, "");
|
|
82
|
+
const isTested = testedFiles.has(node.id);
|
|
83
|
+
// Build label parts
|
|
84
|
+
const parts = [];
|
|
85
|
+
// Type prefix
|
|
86
|
+
const typePrefix = getTypePrefix(node.type);
|
|
87
|
+
// For API routes: show HTTP methods
|
|
88
|
+
if (node.type === "api-route") {
|
|
89
|
+
const methods = node.framework?.metadata?.methods ?? [];
|
|
90
|
+
const routePath = node.framework?.metadata?.routePath ?? "";
|
|
91
|
+
parts.push(`${methods.join(",")} ${routePath}`);
|
|
92
|
+
}
|
|
93
|
+
else if (node.type === "route") {
|
|
94
|
+
const routePath = node.framework?.metadata?.routePath ?? "";
|
|
95
|
+
const isClient = node.framework?.metadata?.isClientComponent;
|
|
96
|
+
parts.push(routePath || shortName);
|
|
97
|
+
if (isClient)
|
|
98
|
+
parts.push("[client]");
|
|
99
|
+
}
|
|
100
|
+
else if (node.type === "schema") {
|
|
101
|
+
const models = node.framework?.metadata?.models ?? [];
|
|
102
|
+
if (models.length > 0) {
|
|
103
|
+
parts.push(`${models.length} models: ${models.slice(0, 4).join(", ")}`);
|
|
104
|
+
if (models.length > 4)
|
|
105
|
+
parts.push(`+${models.length - 4}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
parts.push(shortName);
|
|
110
|
+
}
|
|
111
|
+
// Main label
|
|
112
|
+
const mainLabel = `${typePrefix} ${parts.join(" ")}`;
|
|
113
|
+
const labelColor = node.type === "api-route" ? "#E63946" : "#333";
|
|
114
|
+
svg += `<text x="${(node.x + 5).toFixed(1)}" y="${(node.y + 1).toFixed(1)}" class="file-label" fill="${labelColor}">${escapeXml(mainLabel)}</text>\n`;
|
|
115
|
+
// Key exports (for non-routes, show top 3 exports)
|
|
116
|
+
if (node.type !== "api-route" &&
|
|
117
|
+
node.type !== "route" &&
|
|
118
|
+
node.exports.length > 0) {
|
|
119
|
+
const exportList = node.exports.slice(0, 3).join(", ");
|
|
120
|
+
const suffix = node.exports.length > 3 ? ` +${node.exports.length - 3}` : "";
|
|
121
|
+
svg += `<text x="${(node.x + 5).toFixed(1)}" y="${(node.y + 8).toFixed(1)}" class="export-label">→ ${escapeXml(exportList + suffix)}</text>\n`;
|
|
122
|
+
}
|
|
123
|
+
// Lines count + test indicator
|
|
124
|
+
const meta = `${node.lines}L`;
|
|
125
|
+
const testMark = isTested ? " ✓" : "";
|
|
126
|
+
svg += `<text x="${(node.x + 5).toFixed(1)}" y="${(node.y + (node.exports.length > 0 ? 15 : 8)).toFixed(1)}" class="type-indicator">${meta}${testMark}</text>\n`;
|
|
127
|
+
return svg;
|
|
128
|
+
}
|
|
129
|
+
function getTypePrefix(type) {
|
|
130
|
+
switch (type) {
|
|
131
|
+
case "api-route":
|
|
132
|
+
return "◆";
|
|
133
|
+
case "route":
|
|
134
|
+
return "▪";
|
|
135
|
+
case "component":
|
|
136
|
+
return "●";
|
|
137
|
+
case "layout":
|
|
138
|
+
return "◻";
|
|
139
|
+
case "middleware":
|
|
140
|
+
return "◈";
|
|
141
|
+
case "schema":
|
|
142
|
+
return "⬡";
|
|
143
|
+
case "test":
|
|
144
|
+
return "▲";
|
|
145
|
+
case "config":
|
|
146
|
+
return "⚙";
|
|
147
|
+
default:
|
|
148
|
+
return "○";
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function drawLabelsLegend(x, y) {
|
|
152
|
+
let svg = `<g transform="translate(${x},${y})">\n`;
|
|
153
|
+
svg += `<rect x="0" y="0" width="170" height="130" rx="4" fill="white" stroke="#DEE2E6" stroke-width="1" opacity="0.9"/>\n`;
|
|
154
|
+
svg += `<text x="8" y="14" font-family="monospace" font-size="9" font-weight="bold" fill="#333">Node Types</text>\n`;
|
|
155
|
+
const items = [
|
|
156
|
+
{ prefix: "◆", label: "API Route", color: TYPE_COLORS["api-route"] },
|
|
157
|
+
{ prefix: "▪", label: "Page/Route", color: TYPE_COLORS.route },
|
|
158
|
+
{ prefix: "●", label: "Component", color: TYPE_COLORS.component },
|
|
159
|
+
{ prefix: "⬡", label: "Schema", color: TYPE_COLORS.schema },
|
|
160
|
+
{ prefix: "○", label: "Utility", color: TYPE_COLORS.utility },
|
|
161
|
+
{ prefix: "▲", label: "Test", color: TYPE_COLORS.test },
|
|
162
|
+
];
|
|
163
|
+
items.forEach((item, i) => {
|
|
164
|
+
const iy = 28 + i * 14;
|
|
165
|
+
svg += `<text x="8" y="${iy}" font-family="monospace" font-size="8" fill="${item.color}">${item.prefix}</text>\n`;
|
|
166
|
+
svg += `<text x="20" y="${iy}" font-family="monospace" font-size="8" fill="#555">${item.label}</text>\n`;
|
|
167
|
+
});
|
|
168
|
+
svg += `<text x="8" y="118" font-family="monospace" font-size="7" fill="#888">✓ = has test coverage</text>\n`;
|
|
169
|
+
svg += `</g>\n`;
|
|
170
|
+
return svg;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=layer-labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer-labels.js","sourceRoot":"","sources":["../../src/encoder/layer-labels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 1 — Terrain (Complexity Topography)
|
|
3
|
+
*
|
|
4
|
+
* Encodes: Module boundaries and complexity as contour lines.
|
|
5
|
+
* - Dense contour lines = complex areas (many files, high coupling)
|
|
6
|
+
* - Sparse contour lines = simple modules
|
|
7
|
+
* - Color gradient green (simple) → yellow → red (complex)
|
|
8
|
+
* - Module boundaries as labeled regions
|
|
9
|
+
* - NO file-level text labels — pure visual signal
|
|
10
|
+
*
|
|
11
|
+
* What the LLM learns: Where the "mountains" are. Which areas are
|
|
12
|
+
* flat/simple vs steep/complex. At a glance.
|
|
13
|
+
*/
|
|
14
|
+
import type { StrandGraph } from "../scanner/index.js";
|
|
15
|
+
import { type CanvasLayout } from "./layout.js";
|
|
16
|
+
export declare function encodeTerrainSVG(graph: StrandGraph): string;
|
|
17
|
+
export declare function encodeTerrainSVGFromLayout(layout: CanvasLayout, graph: StrandGraph): string;
|
|
18
|
+
//# sourceMappingURL=layer-terrain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer-terrain.d.ts","sourceRoot":"","sources":["../../src/encoder/layer-terrain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAIL,KAAK,YAAY,EAGlB,MAAM,aAAa,CAAC;AA+BrB,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAG3D;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,WAAW,GACjB,MAAM,CAER"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 1 — Terrain (Complexity Topography)
|
|
3
|
+
*
|
|
4
|
+
* Encodes: Module boundaries and complexity as contour lines.
|
|
5
|
+
* - Dense contour lines = complex areas (many files, high coupling)
|
|
6
|
+
* - Sparse contour lines = simple modules
|
|
7
|
+
* - Color gradient green (simple) → yellow → red (complex)
|
|
8
|
+
* - Module boundaries as labeled regions
|
|
9
|
+
* - NO file-level text labels — pure visual signal
|
|
10
|
+
*
|
|
11
|
+
* What the LLM learns: Where the "mountains" are. Which areas are
|
|
12
|
+
* flat/simple vs steep/complex. At a glance.
|
|
13
|
+
*/
|
|
14
|
+
import { computeLayout, escapeXml, lerpColor, } from "./layout.js";
|
|
15
|
+
// Complexity color ramp: green → yellow → orange → red
|
|
16
|
+
const COMPLEXITY_COLORS = [
|
|
17
|
+
"#2D6A4F",
|
|
18
|
+
"#52B788",
|
|
19
|
+
"#B5E48C",
|
|
20
|
+
"#FED766",
|
|
21
|
+
"#F4845F",
|
|
22
|
+
"#E63946",
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* Get a color from the complexity ramp (t: 0-1)
|
|
26
|
+
* 0 = deep green (simple), 1 = hot red (complex)
|
|
27
|
+
*/
|
|
28
|
+
function complexityColor(t) {
|
|
29
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
30
|
+
const segmentCount = COMPLEXITY_COLORS.length - 1;
|
|
31
|
+
const segment = Math.min(Math.floor(clamped * segmentCount), segmentCount - 1);
|
|
32
|
+
const localT = clamped * segmentCount - segment;
|
|
33
|
+
return lerpColor(COMPLEXITY_COLORS[segment], COMPLEXITY_COLORS[segment + 1], localT);
|
|
34
|
+
}
|
|
35
|
+
export function encodeTerrainSVG(graph) {
|
|
36
|
+
const layout = computeLayout(graph);
|
|
37
|
+
return renderTerrain(layout, graph);
|
|
38
|
+
}
|
|
39
|
+
export function encodeTerrainSVGFromLayout(layout, graph) {
|
|
40
|
+
return renderTerrain(layout, graph);
|
|
41
|
+
}
|
|
42
|
+
function renderTerrain(layout, graph) {
|
|
43
|
+
const { width, height, modules } = layout;
|
|
44
|
+
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}">
|
|
45
|
+
<style>
|
|
46
|
+
text { font-family: monospace; }
|
|
47
|
+
.layer-title { font-size: 14px; font-weight: bold; fill: #111; }
|
|
48
|
+
.layer-subtitle { font-size: 10px; fill: #666; }
|
|
49
|
+
.module-label { font-size: 11px; font-weight: bold; fill: #333; opacity: 0.8; }
|
|
50
|
+
</style>
|
|
51
|
+
<rect width="100%" height="100%" fill="#F8F9FA"/>
|
|
52
|
+
`;
|
|
53
|
+
// Title
|
|
54
|
+
svg += `<text x="60" y="30" class="layer-title">L1: Terrain — ${escapeXml(graph.projectName)}</text>\n`;
|
|
55
|
+
svg += `<text x="60" y="45" class="layer-subtitle">Complexity topography · Dense contours = complex areas</text>\n`;
|
|
56
|
+
// Draw modules as elevation regions with contour lines
|
|
57
|
+
for (const mod of modules) {
|
|
58
|
+
svg += drawModuleTerrain(mod, graph);
|
|
59
|
+
}
|
|
60
|
+
// Draw complexity heat dots at each node position (NO labels)
|
|
61
|
+
for (const node of layout.allNodes) {
|
|
62
|
+
svg += drawComplexityDot(node);
|
|
63
|
+
}
|
|
64
|
+
// Legend — complexity ramp
|
|
65
|
+
svg += drawTerrainLegend(width - 180, 10);
|
|
66
|
+
svg += `</svg>`;
|
|
67
|
+
return svg;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Draw a module as an elevation region with contour lines.
|
|
71
|
+
* More complex modules get denser contour lines and warmer colors.
|
|
72
|
+
*/
|
|
73
|
+
function drawModuleTerrain(mod, graph) {
|
|
74
|
+
let svg = "";
|
|
75
|
+
// Module background — colored by average complexity
|
|
76
|
+
const bgColor = complexityColor(mod.avgComplexity * 0.5); // muted base color
|
|
77
|
+
svg += `<rect x="${mod.x}" y="${mod.y}" width="${mod.width}" height="${mod.height}" rx="8" fill="${bgColor}" opacity="0.15" stroke="${bgColor}" stroke-width="1.5" stroke-opacity="0.4"/>\n`;
|
|
78
|
+
// Contour lines — number of rings based on complexity and node count
|
|
79
|
+
// More nodes + higher complexity = more contour rings (max 6)
|
|
80
|
+
const contourCount = Math.min(Math.max(1, Math.round(mod.avgComplexity * 5 + mod.nodes.length / 8)), 6);
|
|
81
|
+
const cx = mod.x + mod.width / 2;
|
|
82
|
+
const cy = mod.y + mod.height / 2 + 5;
|
|
83
|
+
const maxRx = (mod.width / 2) * 0.85;
|
|
84
|
+
const maxRy = (mod.height / 2) * 0.85;
|
|
85
|
+
for (let i = contourCount; i >= 1; i--) {
|
|
86
|
+
const t = i / contourCount;
|
|
87
|
+
const rx = maxRx * t;
|
|
88
|
+
const ry = maxRy * t;
|
|
89
|
+
const ringColor = complexityColor(mod.avgComplexity * t);
|
|
90
|
+
const opacity = 0.1 + (1 - t) * 0.2; // inner rings more visible
|
|
91
|
+
svg += `<ellipse cx="${cx}" cy="${cy}" rx="${rx}" ry="${ry}" fill="none" stroke="${ringColor}" stroke-width="1" opacity="${opacity.toFixed(2)}"/>\n`;
|
|
92
|
+
}
|
|
93
|
+
// Inner fill — a small filled ellipse at the center showing "peak" elevation
|
|
94
|
+
const peakRx = maxRx * 0.15;
|
|
95
|
+
const peakRy = maxRy * 0.15;
|
|
96
|
+
const peakColor = complexityColor(mod.avgComplexity);
|
|
97
|
+
svg += `<ellipse cx="${cx}" cy="${cy}" rx="${peakRx}" ry="${peakRy}" fill="${peakColor}" opacity="0.3"/>\n`;
|
|
98
|
+
// Module label — positioned at top-left of module
|
|
99
|
+
svg += `<text x="${mod.x + 8}" y="${mod.y + 16}" class="module-label">${escapeXml(mod.name)}</text>\n`;
|
|
100
|
+
return svg;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Draw a dot at each node's position, sized and colored by complexity.
|
|
104
|
+
* No labels — this is pure visual signal.
|
|
105
|
+
*/
|
|
106
|
+
function drawComplexityDot(node) {
|
|
107
|
+
const color = complexityColor(node.complexity);
|
|
108
|
+
const r = 2 + node.complexity * 6; // 2px min, 8px max
|
|
109
|
+
return `<circle cx="${node.x.toFixed(1)}" cy="${node.y.toFixed(1)}" r="${r.toFixed(1)}" fill="${color}" opacity="0.7"/>\n`;
|
|
110
|
+
}
|
|
111
|
+
function drawTerrainLegend(x, y) {
|
|
112
|
+
let svg = `<g transform="translate(${x},${y})">\n`;
|
|
113
|
+
svg += `<rect x="0" y="0" width="170" height="90" rx="4" fill="white" stroke="#DEE2E6" stroke-width="1" opacity="0.9"/>\n`;
|
|
114
|
+
svg += `<text x="8" y="14" font-family="monospace" font-size="9" font-weight="bold" fill="#333">Complexity</text>\n`;
|
|
115
|
+
// Gradient bar
|
|
116
|
+
const barY = 22;
|
|
117
|
+
const barWidth = 154;
|
|
118
|
+
const barHeight = 12;
|
|
119
|
+
const steps = 20;
|
|
120
|
+
for (let i = 0; i < steps; i++) {
|
|
121
|
+
const t = i / (steps - 1);
|
|
122
|
+
const color = complexityColor(t);
|
|
123
|
+
const segWidth = barWidth / steps;
|
|
124
|
+
svg += `<rect x="${8 + i * segWidth}" y="${barY}" width="${segWidth + 0.5}" height="${barHeight}" fill="${color}"/>\n`;
|
|
125
|
+
}
|
|
126
|
+
svg += `<text x="8" y="${barY + barHeight + 12}" font-family="monospace" font-size="7" fill="#666">Simple</text>\n`;
|
|
127
|
+
svg += `<text x="${barWidth - 24}" y="${barY + barHeight + 12}" font-family="monospace" font-size="7" fill="#666">Complex</text>\n`;
|
|
128
|
+
// Contour explanation
|
|
129
|
+
svg += `<text x="8" y="62" font-family="monospace" font-size="7" fill="#666">Dense contours = high complexity</text>\n`;
|
|
130
|
+
svg += `<text x="8" y="72" font-family="monospace" font-size="7" fill="#666">Sparse contours = low complexity</text>\n`;
|
|
131
|
+
svg += `<text x="8" y="82" font-family="monospace" font-size="7" fill="#666">Dot size = file complexity</text>\n`;
|
|
132
|
+
svg += `</g>\n`;
|
|
133
|
+
return svg;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=layer-terrain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer-terrain.js","sourceRoot":"","sources":["../../src/encoder/layer-terrain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Layout Engine — deterministic positioning for all visual layers
|
|
3
|
+
*
|
|
4
|
+
* All topographic layers (terrain, infrastructure, labels) share the same
|
|
5
|
+
* canvas size and node positions so the LLM can mentally overlay them.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from encode.ts to ensure consistency across layers.
|
|
8
|
+
*/
|
|
9
|
+
import type { StrandGraph, StrandNode } from "../scanner/index.js";
|
|
10
|
+
export interface Point {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
}
|
|
14
|
+
export interface LayoutNode extends StrandNode {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
radius: number;
|
|
18
|
+
color: string;
|
|
19
|
+
moduleId: string;
|
|
20
|
+
}
|
|
21
|
+
export interface LayoutModule {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
nodes: LayoutNode[];
|
|
29
|
+
/** Average complexity of nodes in this module (0-1) */
|
|
30
|
+
avgComplexity: number;
|
|
31
|
+
/** Total lines in this module */
|
|
32
|
+
totalLines: number;
|
|
33
|
+
}
|
|
34
|
+
export interface CanvasLayout {
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
modules: LayoutModule[];
|
|
38
|
+
nodes: Map<string, LayoutNode>;
|
|
39
|
+
/** All nodes as a flat array for iteration */
|
|
40
|
+
allNodes: LayoutNode[];
|
|
41
|
+
}
|
|
42
|
+
export declare const TYPE_COLORS: Record<string, string>;
|
|
43
|
+
/**
|
|
44
|
+
* Compute the full layout for a StrandGraph.
|
|
45
|
+
* Returns canvas dimensions, module positions, and node positions.
|
|
46
|
+
* All layers MUST use this to ensure spatial consistency.
|
|
47
|
+
*/
|
|
48
|
+
export declare function computeLayout(graph: StrandGraph): CanvasLayout;
|
|
49
|
+
/** XML-safe string escaping */
|
|
50
|
+
export declare function escapeXml(str: string): string;
|
|
51
|
+
/** Interpolate between two hex colors based on t (0-1) */
|
|
52
|
+
export declare function lerpColor(color1: string, color2: string, t: number): string;
|
|
53
|
+
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/encoder/layout.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EAEX,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,UAAW,SAAQ,UAAU;IAC5C,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,uDAAuD;IACvD,aAAa,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/B,8CAA8C;IAC9C,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAGD,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAW9C,CAAC;AAOF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CAyB9D;AAkID,+BAA+B;AAC/B,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM7C;AAED,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAO3E"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Layout Engine — deterministic positioning for all visual layers
|
|
3
|
+
*
|
|
4
|
+
* All topographic layers (terrain, infrastructure, labels) share the same
|
|
5
|
+
* canvas size and node positions so the LLM can mentally overlay them.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from encode.ts to ensure consistency across layers.
|
|
8
|
+
*/
|
|
9
|
+
// Color palette — same as encode.ts for consistency
|
|
10
|
+
export const TYPE_COLORS = {
|
|
11
|
+
route: "#FF6B35",
|
|
12
|
+
"api-route": "#E63946",
|
|
13
|
+
component: "#457B9D",
|
|
14
|
+
layout: "#A8DADC",
|
|
15
|
+
middleware: "#F4A261",
|
|
16
|
+
schema: "#2A9D8F",
|
|
17
|
+
test: "#6C757D",
|
|
18
|
+
config: "#ADB5BD",
|
|
19
|
+
utility: "#264653",
|
|
20
|
+
module: "#E9ECEF",
|
|
21
|
+
};
|
|
22
|
+
const PADDING = 60;
|
|
23
|
+
const MODULE_PADDING = 30;
|
|
24
|
+
const MIN_NODE_RADIUS = 4;
|
|
25
|
+
const MAX_NODE_RADIUS = 18;
|
|
26
|
+
/**
|
|
27
|
+
* Compute the full layout for a StrandGraph.
|
|
28
|
+
* Returns canvas dimensions, module positions, and node positions.
|
|
29
|
+
* All layers MUST use this to ensure spatial consistency.
|
|
30
|
+
*/
|
|
31
|
+
export function computeLayout(graph) {
|
|
32
|
+
// Step 1: Layout modules in a grid
|
|
33
|
+
const layoutModules = layoutModulesInGrid(graph);
|
|
34
|
+
// Step 2: Position nodes within their modules
|
|
35
|
+
const nodeMap = positionNodesInModules(graph.nodes, layoutModules, graph.modules);
|
|
36
|
+
// Step 3: Calculate canvas size
|
|
37
|
+
const allNodes = layoutModules.flatMap((m) => m.nodes);
|
|
38
|
+
const maxX = Math.max(...layoutModules.map((m) => m.x + m.width)) + PADDING;
|
|
39
|
+
const maxY = Math.max(...layoutModules.map((m) => m.y + m.height)) + PADDING;
|
|
40
|
+
const canvasWidth = Math.max(maxX, 800);
|
|
41
|
+
const canvasHeight = Math.max(maxY, 600);
|
|
42
|
+
return {
|
|
43
|
+
width: canvasWidth,
|
|
44
|
+
height: canvasHeight,
|
|
45
|
+
modules: layoutModules,
|
|
46
|
+
nodes: nodeMap,
|
|
47
|
+
allNodes,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function layoutModulesInGrid(graph) {
|
|
51
|
+
const modules = graph.modules
|
|
52
|
+
.filter((m) => m.nodeCount > 0)
|
|
53
|
+
.sort((a, b) => b.totalLines - a.totalLines);
|
|
54
|
+
const cols = Math.ceil(Math.sqrt(modules.length));
|
|
55
|
+
const layoutModules = [];
|
|
56
|
+
let currentX = PADDING;
|
|
57
|
+
let currentY = 60; // below title area
|
|
58
|
+
let rowHeight = 0;
|
|
59
|
+
let col = 0;
|
|
60
|
+
for (const mod of modules) {
|
|
61
|
+
const nodesPerRow = Math.ceil(Math.sqrt(mod.nodeCount));
|
|
62
|
+
const estimatedWidth = Math.max(nodesPerRow * 30 + MODULE_PADDING * 2, 120);
|
|
63
|
+
const estimatedHeight = Math.max(Math.ceil(mod.nodeCount / nodesPerRow) * 30 + MODULE_PADDING * 2 + 20, 80);
|
|
64
|
+
if (col >= cols && currentX + estimatedWidth > 1200) {
|
|
65
|
+
currentX = PADDING;
|
|
66
|
+
currentY += rowHeight + 20;
|
|
67
|
+
rowHeight = 0;
|
|
68
|
+
col = 0;
|
|
69
|
+
}
|
|
70
|
+
layoutModules.push({
|
|
71
|
+
id: mod.id,
|
|
72
|
+
name: mod.name,
|
|
73
|
+
x: currentX,
|
|
74
|
+
y: currentY,
|
|
75
|
+
width: estimatedWidth,
|
|
76
|
+
height: estimatedHeight,
|
|
77
|
+
nodes: [],
|
|
78
|
+
avgComplexity: 0,
|
|
79
|
+
totalLines: mod.totalLines,
|
|
80
|
+
});
|
|
81
|
+
currentX += estimatedWidth + 15;
|
|
82
|
+
rowHeight = Math.max(rowHeight, estimatedHeight);
|
|
83
|
+
col++;
|
|
84
|
+
}
|
|
85
|
+
return layoutModules;
|
|
86
|
+
}
|
|
87
|
+
function positionNodesInModules(nodes, layoutModules, modules) {
|
|
88
|
+
const nodeMap = new Map();
|
|
89
|
+
const moduleMap = new Map(layoutModules.map((m) => [m.id, m]));
|
|
90
|
+
// Assign nodes to modules
|
|
91
|
+
for (const node of nodes) {
|
|
92
|
+
const parts = node.path.split("/");
|
|
93
|
+
const moduleKey = parts.length > 2 ? parts.slice(0, 2).join("/") : (parts[0] ?? "");
|
|
94
|
+
const layoutMod = moduleMap.get(moduleKey);
|
|
95
|
+
if (!layoutMod)
|
|
96
|
+
continue;
|
|
97
|
+
const radius = MIN_NODE_RADIUS +
|
|
98
|
+
(MAX_NODE_RADIUS - MIN_NODE_RADIUS) * Math.min(node.complexity, 1);
|
|
99
|
+
const layoutNode = {
|
|
100
|
+
...node,
|
|
101
|
+
x: 0,
|
|
102
|
+
y: 0,
|
|
103
|
+
radius,
|
|
104
|
+
color: TYPE_COLORS[node.type] ?? TYPE_COLORS.utility,
|
|
105
|
+
moduleId: layoutMod.id,
|
|
106
|
+
};
|
|
107
|
+
layoutMod.nodes.push(layoutNode);
|
|
108
|
+
nodeMap.set(node.id, layoutNode);
|
|
109
|
+
}
|
|
110
|
+
// Position nodes within each module using spiral layout
|
|
111
|
+
for (const mod of layoutModules) {
|
|
112
|
+
const centerX = mod.x + mod.width / 2;
|
|
113
|
+
const centerY = mod.y + mod.height / 2 + 10;
|
|
114
|
+
if (mod.nodes.length === 1) {
|
|
115
|
+
mod.nodes[0].x = centerX;
|
|
116
|
+
mod.nodes[0].y = centerY;
|
|
117
|
+
}
|
|
118
|
+
else if (mod.nodes.length > 1) {
|
|
119
|
+
// Sort: entry points first, then by complexity
|
|
120
|
+
mod.nodes.sort((a, b) => {
|
|
121
|
+
const aEntry = modules
|
|
122
|
+
.find((m) => m.id === mod.id)
|
|
123
|
+
?.entryPoints.includes(a.id)
|
|
124
|
+
? -1
|
|
125
|
+
: 0;
|
|
126
|
+
const bEntry = modules
|
|
127
|
+
.find((m) => m.id === mod.id)
|
|
128
|
+
?.entryPoints.includes(b.id)
|
|
129
|
+
? -1
|
|
130
|
+
: 0;
|
|
131
|
+
if (aEntry !== bEntry)
|
|
132
|
+
return aEntry - bEntry;
|
|
133
|
+
return b.complexity - a.complexity;
|
|
134
|
+
});
|
|
135
|
+
// Spiral layout — golden angle for even distribution
|
|
136
|
+
const angleStep = (2 * Math.PI) / Math.max(mod.nodes.length, 1);
|
|
137
|
+
const maxR = Math.min(mod.width, mod.height) / 2 - 25;
|
|
138
|
+
for (let i = 0; i < mod.nodes.length; i++) {
|
|
139
|
+
const angle = i * angleStep * 1.618;
|
|
140
|
+
const r = (maxR * Math.sqrt(i + 1)) / Math.sqrt(mod.nodes.length);
|
|
141
|
+
mod.nodes[i].x = centerX + r * Math.cos(angle);
|
|
142
|
+
mod.nodes[i].y = centerY + r * Math.sin(angle);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Calculate average complexity for this module
|
|
146
|
+
if (mod.nodes.length > 0) {
|
|
147
|
+
mod.avgComplexity =
|
|
148
|
+
mod.nodes.reduce((sum, n) => sum + n.complexity, 0) / mod.nodes.length;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return nodeMap;
|
|
152
|
+
}
|
|
153
|
+
/** XML-safe string escaping */
|
|
154
|
+
export function escapeXml(str) {
|
|
155
|
+
return str
|
|
156
|
+
.replace(/&/g, "&")
|
|
157
|
+
.replace(/</g, "<")
|
|
158
|
+
.replace(/>/g, ">")
|
|
159
|
+
.replace(/"/g, """);
|
|
160
|
+
}
|
|
161
|
+
/** Interpolate between two hex colors based on t (0-1) */
|
|
162
|
+
export function lerpColor(color1, color2, t) {
|
|
163
|
+
const c1 = hexToRgb(color1);
|
|
164
|
+
const c2 = hexToRgb(color2);
|
|
165
|
+
const r = Math.round(c1.r + (c2.r - c1.r) * t);
|
|
166
|
+
const g = Math.round(c1.g + (c2.g - c1.g) * t);
|
|
167
|
+
const b = Math.round(c1.b + (c2.b - c1.b) * t);
|
|
168
|
+
return `rgb(${r},${g},${b})`;
|
|
169
|
+
}
|
|
170
|
+
function hexToRgb(hex) {
|
|
171
|
+
const clean = hex.replace("#", "");
|
|
172
|
+
return {
|
|
173
|
+
r: parseInt(clean.substring(0, 2), 16),
|
|
174
|
+
g: parseInt(clean.substring(2, 4), 16),
|
|
175
|
+
b: parseInt(clean.substring(4, 6), 16),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/encoder/layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .mapra Header Parser — extracts metadata from the MAPRA header line.
|
|
3
|
+
*
|
|
4
|
+
* Parses headers like:
|
|
5
|
+
* MAPRA v3 | project | Typescript | 76 files | 12,629 lines | generated 2026-03-07T05:21:49 | git:f9e429a
|
|
6
|
+
* MAPRA v3 | project | Typescript | 76 files | 12,629 lines | generated 2026-03-07T05:21:49
|
|
7
|
+
*/
|
|
8
|
+
export interface StrandHeaderInfo {
|
|
9
|
+
/** Format version string, e.g. "v3" */
|
|
10
|
+
version: string;
|
|
11
|
+
/** Project name */
|
|
12
|
+
projectName: string;
|
|
13
|
+
/** Framework/language, e.g. "Typescript" */
|
|
14
|
+
framework: string;
|
|
15
|
+
/** Total file count */
|
|
16
|
+
fileCount: number;
|
|
17
|
+
/** Total line count */
|
|
18
|
+
lineCount: number;
|
|
19
|
+
/** Generation timestamp (ISO-8601 without timezone, e.g. "2026-03-07T05:21:49") */
|
|
20
|
+
timestamp: string;
|
|
21
|
+
/** Short git hash at generation time, or null if not present (legacy format) */
|
|
22
|
+
gitHash: string | null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Parse a .mapra file's header line and extract structured metadata.
|
|
26
|
+
* Returns null if the content doesn't contain a valid MAPRA header.
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseStrandHeader(content: string): StrandHeaderInfo | null;
|
|
29
|
+
//# sourceMappingURL=parse-strand-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-strand-header.d.ts","sourceRoot":"","sources":["../../src/encoder/parse-strand-header.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAmD1E"}
|