Modular components extracted from attack_timearcs.js.
src/
├── config/
│ └── constants.js # Margins, colors, defaults
├── utils/
│ └── helpers.js # Pure utility functions
├── mappings/
│ └── decoders.js # IP/attack/color decoding
├── data/
│ ├── aggregation.js # Link computation, components
│ └── csvParser.js # Stream CSV parsing
├── rendering/
│ └── arcPath.js # SVG arc path generation
├── ui/
│ └── legend.js # Legend building/interaction
└── index.js # Re-exports all modules
- Purpose: Global configuration constants
- Exports:
MARGIN,DEFAULT_WIDTH,DEFAULT_HEIGHT,INNER_HEIGHT,PROTOCOL_COLORS,DEFAULT_COLOR,NEUTRAL_GREY,LENS_DEFAULTS,FISHEYE_DEFAULTS - Dependencies: None (pure constants)
- Purpose: Pure utility functions with no side effects
- Exports:
toNumber(v)- Safe number conversionsanitizeId(s)- SVG ID sanitizationcanonicalizeName(s)- Attack name normalizationshowTooltip(tooltip, evt, html)- Display tooltiphideTooltip(tooltip)- Hide tooltipsetStatus(statusEl, msg)- Update status message
- Dependencies: None (pure functions)
- Purpose: IP address and attack type decoding/mapping
- Exports:
decodeIp(value, idToAddr)- Decode IP ID to dotted quaddecodeAttack(value, idToName)- Decode attack ID to namedecodeAttackGroup(groupVal, fallbackVal, groupIdToName, attackIdToName)- Decode attack grouplookupAttackColor(name, rawColorMap, canonicalColorMap)- Get color for attacklookupAttackGroupColor(name, rawColorMap, canonicalColorMap)- Get color for attack group
- Dependencies:
canonicalizeNamefrom utils/helpers.js
- Purpose: Data aggregation and network graph computation
- Exports:
buildRelationships(data)- Build pairwise IP relationshipscomputeConnectivityFromRelationships(relationships, threshold, allIps)- Compute connectivity metricscomputeLinks(data)- Aggregate links per (src, dst, minute)findConnectedComponents(nodes, links)- Find network components using DFS
- Dependencies: None (pure data processing)
- Purpose: Stream-based CSV file parsing
- Exports:
parseCSVLine(line, delimiter)- Parse single CSV line with quote handlingparseCSVStream(file, onRow, options)- Stream-parse entire CSV file
- Dependencies: None (pure parsing)
- Features:
- Memory-efficient streaming
- Handles CR/LF/CRLF line endings
- Respects quoted fields with embedded commas
- Handles escaped quotes
- Purpose: SVG path generation for network arcs
- Exports:
linkArc(d)- Generate curved arc path between nodesgradientIdForLink(d, sanitizeId)- Generate unique gradient ID for link
- Dependencies: None (pure rendering functions)
- Purpose: Interactive legend UI component
- Exports:
buildLegend(container, items, colorFn, visibleAttacks, callbacks)- Build legend with interactionsupdateLegendVisualState(container, visibleAttacks)- Update legend visual stateisolateAttack(attackName, visibleAttacks, container)- Isolate/show-all attack toggle
- Dependencies: None (pure UI functions)
- Features:
- Click to toggle visibility
- Double-click to isolate
- Hover effects
- Visual state management
import { computeLinks, findConnectedComponents } from './src/data/aggregation.js';
import { linkArc } from './src/rendering/arcPath.js';
import { buildLegend } from './src/ui/legend.js';import {
computeLinks,
linkArc,
buildLegend,
parseCSVStream,
decodeIp
} from './src/index.js';- Separation of Concerns: Each module has a single, well-defined responsibility
- Pure Functions: Most functions are pure (no side effects) for easier testing
- Minimal Dependencies: Modules have minimal cross-dependencies
- Reusability: Functions designed to be reusable in other contexts
- Type Safety: JSDoc comments provide type information
Each module can be tested independently:
// Example: Test CSV parser
import { parseCSVLine } from './src/data/csvParser.js';
const line = 'name,value,"quoted,field"';
const fields = parseCSVLine(line);
console.assert(fields.length === 3);
console.assert(fields[2] === 'quoted,field');The refactoring maintains backward compatibility:
- Original
attack_timearcs.jsimports from modules - All functionality preserved
- No API changes for end users
- Future modules can be added incrementally
Possible next steps:
- Add TypeScript definitions (.d.ts files)
- Create unit tests for each module
- Bundle modules for production (Webpack/Rollup)
- Extract more visualization logic (force layout, timeline)
- Create shared types module
