@ocpp-debugkit/toolkit 0.2.0 → 0.2.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.
Files changed (70) hide show
  1. package/dist/cli/commands/report.d.ts.map +1 -1
  2. package/dist/cli/commands/report.js +6 -3
  3. package/dist/cli/commands/report.js.map +1 -1
  4. package/dist/cli/commands/scenario.d.ts +11 -3
  5. package/dist/cli/commands/scenario.d.ts.map +1 -1
  6. package/dist/cli/commands/scenario.js +41 -4
  7. package/dist/cli/commands/scenario.js.map +1 -1
  8. package/dist/cli/index.js +14 -5
  9. package/dist/cli/index.js.map +1 -1
  10. package/dist/core/__fixtures__/connector-fault.d.ts +6 -0
  11. package/dist/core/__fixtures__/connector-fault.d.ts.map +1 -1
  12. package/dist/core/__fixtures__/connector-fault.js +11 -1
  13. package/dist/core/__fixtures__/connector-fault.js.map +1 -1
  14. package/dist/core/__fixtures__/normal-session.d.ts +6 -0
  15. package/dist/core/__fixtures__/normal-session.d.ts.map +1 -1
  16. package/dist/core/__fixtures__/normal-session.js +10 -0
  17. package/dist/core/__fixtures__/normal-session.js.map +1 -1
  18. package/dist/core/detection.d.ts +13 -3
  19. package/dist/core/detection.d.ts.map +1 -1
  20. package/dist/core/detection.js +338 -6
  21. package/dist/core/detection.js.map +1 -1
  22. package/dist/core/fixtures/index.d.ts +12 -0
  23. package/dist/core/fixtures/index.d.ts.map +1 -1
  24. package/dist/core/types.d.ts +2 -2
  25. package/dist/core/types.d.ts.map +1 -1
  26. package/dist/react/components.d.ts +9 -45
  27. package/dist/react/components.d.ts.map +1 -1
  28. package/dist/react/components.js +120 -38
  29. package/dist/react/components.js.map +1 -1
  30. package/dist/reporter/html.d.ts +25 -0
  31. package/dist/reporter/html.d.ts.map +1 -0
  32. package/dist/reporter/html.js +396 -0
  33. package/dist/reporter/html.js.map +1 -0
  34. package/dist/reporter/index.d.ts +1 -0
  35. package/dist/reporter/index.d.ts.map +1 -1
  36. package/dist/reporter/index.js +1 -0
  37. package/dist/reporter/index.js.map +1 -1
  38. package/dist/scenarios/__scenarios__/diagnostics-failure.d.ts +58 -0
  39. package/dist/scenarios/__scenarios__/diagnostics-failure.d.ts.map +1 -0
  40. package/dist/scenarios/__scenarios__/diagnostics-failure.js +91 -0
  41. package/dist/scenarios/__scenarios__/diagnostics-failure.js.map +1 -0
  42. package/dist/scenarios/__scenarios__/invalid-stop-reason.d.ts +118 -0
  43. package/dist/scenarios/__scenarios__/invalid-stop-reason.d.ts.map +1 -0
  44. package/dist/scenarios/__scenarios__/invalid-stop-reason.js +226 -0
  45. package/dist/scenarios/__scenarios__/invalid-stop-reason.js.map +1 -0
  46. package/dist/scenarios/__scenarios__/meter-value-gap.d.ts +103 -0
  47. package/dist/scenarios/__scenarios__/meter-value-gap.d.ts.map +1 -0
  48. package/dist/scenarios/__scenarios__/meter-value-gap.js +196 -0
  49. package/dist/scenarios/__scenarios__/meter-value-gap.js.map +1 -0
  50. package/dist/scenarios/__scenarios__/station-offline.d.ts +6 -0
  51. package/dist/scenarios/__scenarios__/station-offline.d.ts.map +1 -1
  52. package/dist/scenarios/__scenarios__/station-offline.js +10 -0
  53. package/dist/scenarios/__scenarios__/station-offline.js.map +1 -1
  54. package/dist/scenarios/__scenarios__/status-transition-violation.d.ts +52 -0
  55. package/dist/scenarios/__scenarios__/status-transition-violation.d.ts.map +1 -0
  56. package/dist/scenarios/__scenarios__/status-transition-violation.js +112 -0
  57. package/dist/scenarios/__scenarios__/status-transition-violation.js.map +1 -0
  58. package/dist/scenarios/__scenarios__/unexpected-start.d.ts +80 -0
  59. package/dist/scenarios/__scenarios__/unexpected-start.d.ts.map +1 -0
  60. package/dist/scenarios/__scenarios__/unexpected-start.js +124 -0
  61. package/dist/scenarios/__scenarios__/unexpected-start.js.map +1 -0
  62. package/dist/scenarios/__scenarios__/unexpected-stop-reason.d.ts +6 -0
  63. package/dist/scenarios/__scenarios__/unexpected-stop-reason.d.ts.map +1 -1
  64. package/dist/scenarios/__scenarios__/unexpected-stop-reason.js +10 -0
  65. package/dist/scenarios/__scenarios__/unexpected-stop-reason.js.map +1 -1
  66. package/dist/scenarios/index.d.ts +8 -3
  67. package/dist/scenarios/index.d.ts.map +1 -1
  68. package/dist/scenarios/index.js +24 -4
  69. package/dist/scenarios/index.js.map +1 -1
  70. package/package.json +1 -1
@@ -1,49 +1,131 @@
1
- /**
2
- * React component stubs for @ocpp-debugkit/toolkit/react.
3
- *
4
- * v0.2.0: These are stub implementations — presentational components
5
- * that will be fully extracted from the Inspector in Phase 4.
6
- * They are functional but minimal, using no external CSS framework.
7
- */
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const SEVERITY_COLORS = {
3
+ critical: '#dc2626',
4
+ warning: '#f59e0b',
5
+ info: '#3b82f6',
6
+ };
7
+ const styles = {
8
+ container: {
9
+ fontFamily: 'system-ui, -apple-system, sans-serif',
10
+ color: '#1f2937',
11
+ },
12
+ list: {
13
+ listStyle: 'none',
14
+ padding: 0,
15
+ margin: 0,
16
+ },
17
+ listItem: {
18
+ padding: '8px 12px',
19
+ borderBottom: '1px solid #e5e7eb',
20
+ cursor: 'pointer',
21
+ fontSize: '13px',
22
+ },
23
+ selectedItem: {
24
+ backgroundColor: '#dbeafe',
25
+ },
26
+ badge: {
27
+ display: 'inline-block',
28
+ padding: '2px 8px',
29
+ borderRadius: '4px',
30
+ fontSize: '11px',
31
+ fontWeight: 600,
32
+ color: '#fff',
33
+ marginRight: '6px',
34
+ },
35
+ code: {
36
+ fontFamily: 'monospace',
37
+ fontSize: '12px',
38
+ backgroundColor: '#f3f4f6',
39
+ padding: '2px 4px',
40
+ borderRadius: '3px',
41
+ },
42
+ section: {
43
+ marginBottom: '16px',
44
+ },
45
+ heading: {
46
+ fontSize: '14px',
47
+ fontWeight: 600,
48
+ marginBottom: '8px',
49
+ color: '#374151',
50
+ },
51
+ empty: {
52
+ color: '#9ca3af',
53
+ fontStyle: 'italic',
54
+ padding: '12px',
55
+ },
56
+ button: {
57
+ padding: '4px 12px',
58
+ border: '1px solid #d1d5db',
59
+ borderRadius: '4px',
60
+ background: '#fff',
61
+ cursor: 'pointer',
62
+ fontSize: '13px',
63
+ marginRight: '4px',
64
+ },
65
+ buttonActive: {
66
+ background: '#3b82f6',
67
+ color: '#fff',
68
+ borderColor: '#3b82f6',
69
+ },
70
+ rangeInput: {
71
+ width: '100%',
72
+ margin: '8px 0',
73
+ },
74
+ };
75
+ function formatTimestamp(ts) {
76
+ if (ts === null)
77
+ return '—';
78
+ return new Date(ts).toISOString().slice(11, 19);
79
+ }
8
80
  export function SessionTimeline({ events, selectedEventId, onSelectEvent }) {
9
- return {
10
- type: 'SessionTimeline',
11
- props: { events, selectedEventId, onSelectEvent },
12
- };
81
+ if (events.length === 0) {
82
+ return _jsx("div", { style: styles.empty, children: "No events in trace" });
83
+ }
84
+ return (_jsxs("div", { style: styles.container, children: [_jsxs("div", { style: styles.heading, children: ["Timeline (", events.length, " events)"] }), _jsx("ul", { style: styles.list, children: events.map((event, i) => (_jsxs("li", { onClick: () => onSelectEvent?.(event.id), style: {
85
+ ...styles.listItem,
86
+ ...(selectedEventId === event.id ? styles.selectedItem : {}),
87
+ }, children: [_jsx("span", { style: { color: '#9ca3af', marginRight: '8px' }, children: i }), _jsx("span", { style: { color: '#6b7280', marginRight: '8px' }, children: formatTimestamp(event.timestamp) }), _jsx("span", { style: styles.code, children: event.messageType }), event.action && (_jsx("span", { style: { marginLeft: '6px', fontWeight: 500 }, children: event.action })), _jsx("span", { style: { marginLeft: '8px', color: '#9ca3af' }, children: event.direction })] }, event.id))) })] }));
13
88
  }
14
89
  export function MessageInspector({ event }) {
15
- return {
16
- type: 'MessageInspector',
17
- props: { event },
18
- };
90
+ if (!event) {
91
+ return _jsx("div", { style: styles.empty, children: "Select an event to inspect" });
92
+ }
93
+ return (_jsxs("div", { style: styles.container, children: [_jsx("div", { style: styles.heading, children: "Message Inspector" }), _jsxs("div", { style: styles.section, children: [_jsx("strong", { children: "ID:" }), " ", _jsx("span", { style: styles.code, children: event.id })] }), _jsxs("div", { style: styles.section, children: [_jsx("strong", { children: "Message ID:" }), " ", _jsx("span", { style: styles.code, children: event.messageId })] }), _jsxs("div", { style: styles.section, children: [_jsx("strong", { children: "Type:" }), " ", event.messageType] }), _jsxs("div", { style: styles.section, children: [_jsx("strong", { children: "Action:" }), " ", event.action ?? '—'] }), _jsxs("div", { style: styles.section, children: [_jsx("strong", { children: "Direction:" }), " ", event.direction] }), _jsxs("div", { style: styles.section, children: [_jsx("strong", { children: "Timestamp:" }), " ", formatTimestamp(event.timestamp)] }), _jsxs("div", { style: styles.section, children: [_jsx("strong", { children: "Payload:" }), _jsx("pre", { style: {
94
+ ...styles.code,
95
+ padding: '8px',
96
+ overflowX: 'auto',
97
+ whiteSpace: 'pre-wrap',
98
+ }, children: JSON.stringify(event.payload, null, 2) })] }), _jsxs("div", { style: styles.section, children: [_jsx("strong", { children: "Raw:" }), _jsx("pre", { style: {
99
+ ...styles.code,
100
+ padding: '8px',
101
+ overflowX: 'auto',
102
+ whiteSpace: 'pre-wrap',
103
+ }, children: JSON.stringify(event.rawMessage, null, 2) })] })] }));
19
104
  }
20
105
  export function FailureSummary({ failures }) {
21
- return {
22
- type: 'FailureSummary',
23
- props: { failures },
24
- };
106
+ if (failures.length === 0) {
107
+ return (_jsxs("div", { style: styles.container, children: [_jsx("div", { style: styles.heading, children: "Failures" }), _jsx("div", { style: styles.empty, children: "No failures detected" })] }));
108
+ }
109
+ return (_jsxs("div", { style: styles.container, children: [_jsxs("div", { style: styles.heading, children: ["Failures (", failures.length, ")"] }), _jsx("ul", { style: styles.list, children: failures.map((failure, i) => (_jsxs("li", { style: { ...styles.listItem, cursor: 'default' }, children: [_jsx("span", { style: {
110
+ ...styles.badge,
111
+ backgroundColor: SEVERITY_COLORS[failure.severity] ?? '#6b7280',
112
+ }, children: failure.severity.toUpperCase() }), _jsx("strong", { children: failure.code }), _jsx("div", { style: { marginTop: '4px', fontSize: '12px', color: '#6b7280' }, children: failure.description }), failure.suggestedSteps.length > 0 && (_jsxs("div", { style: { marginTop: '4px', fontSize: '12px' }, children: [_jsx("strong", { children: "Suggested steps:" }), _jsx("ul", { style: { margin: '4px 0 0 20px', padding: 0 }, children: failure.suggestedSteps.map((step, j) => (_jsx("li", { children: step }, j))) })] }))] }, `${failure.code}-${i}`))) })] }));
25
113
  }
26
114
  export function ReportViewer({ html }) {
27
- return {
28
- type: 'ReportViewer',
29
- props: { html },
30
- };
115
+ return (_jsxs("div", { style: styles.container, children: [_jsx("div", { style: styles.heading, children: "Report" }), _jsx("iframe", { srcDoc: html, style: {
116
+ width: '100%',
117
+ height: '500px',
118
+ border: '1px solid #e5e7eb',
119
+ borderRadius: '4px',
120
+ }, title: "OCPP DebugKit Report", sandbox: "allow-same-origin" })] }));
31
121
  }
32
122
  export function ReplayControls({ isPlaying, currentIndex, totalEvents, onPlay, onPause, onStep, onStepBack, onJump, speed, onSpeedChange, }) {
33
- return {
34
- type: 'ReplayControls',
35
- props: {
36
- isPlaying,
37
- currentIndex,
38
- totalEvents,
39
- onPlay,
40
- onPause,
41
- onStep,
42
- onStepBack,
43
- onJump,
44
- speed,
45
- onSpeedChange,
46
- },
47
- };
123
+ return (_jsxs("div", { style: styles.container, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '4px' }, children: [_jsx("button", { onClick: onStepBack, disabled: currentIndex <= 0, style: {
124
+ ...styles.button,
125
+ opacity: currentIndex <= 0 ? 0.5 : 1,
126
+ }, children: "\u2190 Step Back" }), isPlaying ? (_jsx("button", { onClick: onPause, style: { ...styles.button, ...styles.buttonActive }, children: "\u23F8 Pause" })) : (_jsx("button", { onClick: onPlay, style: { ...styles.button, ...styles.buttonActive }, children: "\u25B6 Play" })), _jsx("button", { onClick: onStep, disabled: currentIndex >= totalEvents - 1, style: {
127
+ ...styles.button,
128
+ opacity: currentIndex >= totalEvents - 1 ? 0.5 : 1,
129
+ }, children: "Step Forward \u2192" }), _jsxs("span", { style: { marginLeft: '12px', fontSize: '13px', color: '#6b7280' }, children: [currentIndex + 1, " / ", totalEvents] }), onSpeedChange && (_jsxs("span", { style: { marginLeft: '12px', fontSize: '13px' }, children: [_jsx("label", { htmlFor: "replay-speed", children: "Speed: " }), _jsxs("select", { id: "replay-speed", value: speed ?? 1, onChange: (e) => onSpeedChange(Number(e.currentTarget.value)), style: styles.button, children: [_jsx("option", { value: 0.5, children: "0.5x" }), _jsx("option", { value: 1, children: "1x" }), _jsx("option", { value: 2, children: "2x" }), _jsx("option", { value: 5, children: "5x" })] })] }))] }), _jsx("input", { type: "range", min: 0, max: Math.max(0, totalEvents - 1), value: currentIndex, onChange: (e) => onJump(Number(e.currentTarget.value)), style: styles.rangeInput })] }));
48
130
  }
49
131
  //# sourceMappingURL=components.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/react/components.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,MAAM,UAAU,eAAe,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,EAAwB;IAC9F,OAAO;QACL,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE;KACzC,CAAC;AACb,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAE,KAAK,EAAyB;IAC/D,OAAO;QACL,IAAI,EAAE,kBAAkB;QACxB,KAAK,EAAE,EAAE,KAAK,EAAE;KACR,CAAC;AACb,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAE,QAAQ,EAAuB;IAC9D,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,KAAK,EAAE,EAAE,QAAQ,EAAE;KACX,CAAC;AACb,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAE,IAAI,EAAqB;IACtD,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,KAAK,EAAE,EAAE,IAAI,EAAE;KACP,CAAC;AACb,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAC7B,SAAS,EACT,YAAY,EACZ,WAAW,EACX,MAAM,EACN,OAAO,EACP,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,aAAa,GACO;IACpB,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,KAAK,EAAE;YACL,SAAS;YACT,YAAY;YACZ,WAAW;YACX,MAAM;YACN,OAAO;YACP,MAAM;YACN,UAAU;YACV,MAAM;YACN,KAAK;YACL,aAAa;SACd;KACO,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/react/components.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * HTML report generator — produces a self-contained, human-readable HTML
3
+ * document from an AnalysisResult.
4
+ *
5
+ * Sections:
6
+ * 1. Session overview (station ID, connector, duration, status)
7
+ * 2. Timeline summary (event count, action sequence)
8
+ * 3. Failures (severity, description, suggested steps)
9
+ * 4. Suggested next steps
10
+ * 5. Raw event appendix (compact)
11
+ *
12
+ * All user-supplied content (event payloads, descriptions, metadata) is
13
+ * HTML-escaped via {@link escapeHtml} to prevent injection / XSS.
14
+ */
15
+ import type { AnalysisResult } from './types.js';
16
+ /**
17
+ * Generate a self-contained HTML report from an analysis result.
18
+ *
19
+ * All user-supplied content is HTML-escaped to prevent injection / XSS.
20
+ *
21
+ * @param result - The analysis result to report on
22
+ * @returns A self-contained HTML string (inline CSS, no external dependencies)
23
+ */
24
+ export declare function generateHtmlReport(result: AnalysisResult): string;
25
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/reporter/html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAmYjD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAoBjE"}
@@ -0,0 +1,396 @@
1
+ /**
2
+ * HTML report generator — produces a self-contained, human-readable HTML
3
+ * document from an AnalysisResult.
4
+ *
5
+ * Sections:
6
+ * 1. Session overview (station ID, connector, duration, status)
7
+ * 2. Timeline summary (event count, action sequence)
8
+ * 3. Failures (severity, description, suggested steps)
9
+ * 4. Suggested next steps
10
+ * 5. Raw event appendix (compact)
11
+ *
12
+ * All user-supplied content (event payloads, descriptions, metadata) is
13
+ * HTML-escaped via {@link escapeHtml} to prevent injection / XSS.
14
+ */
15
+ // ---------------------------------------------------------------------------
16
+ // Helpers
17
+ // ---------------------------------------------------------------------------
18
+ /** Escape HTML special characters in a string to prevent XSS. */
19
+ function escapeHtml(value) {
20
+ const str = value === null || value === undefined ? '' : String(value);
21
+ return str
22
+ .replace(/&/g, '&amp;')
23
+ .replace(/</g, '&lt;')
24
+ .replace(/>/g, '&gt;')
25
+ .replace(/"/g, '&quot;')
26
+ .replace(/'/g, '&#39;');
27
+ }
28
+ /** Format a duration in milliseconds as a human-readable string. */
29
+ function formatDuration(ms) {
30
+ if (ms === null)
31
+ return 'Unknown';
32
+ if (ms < 1000)
33
+ return `${ms}ms`;
34
+ const seconds = Math.floor(ms / 1000);
35
+ if (seconds < 60)
36
+ return `${seconds}s`;
37
+ const minutes = Math.floor(seconds / 60);
38
+ const remainingSeconds = seconds % 60;
39
+ if (minutes < 60)
40
+ return `${minutes}m ${remainingSeconds}s`;
41
+ const hours = Math.floor(minutes / 60);
42
+ const remainingMinutes = minutes % 60;
43
+ return `${hours}h ${remainingMinutes}m`;
44
+ }
45
+ /** Format an epoch millisecond timestamp as ISO 8601. */
46
+ function formatTimestamp(ms) {
47
+ if (ms === null)
48
+ return 'Unknown';
49
+ return new Date(ms).toISOString();
50
+ }
51
+ /** Get severity badge class for a failure. */
52
+ function severityClass(severity) {
53
+ switch (severity) {
54
+ case 'critical':
55
+ return 'severity-critical';
56
+ case 'warning':
57
+ return 'severity-warning';
58
+ case 'info':
59
+ return 'severity-info';
60
+ default:
61
+ return 'severity-default';
62
+ }
63
+ }
64
+ /** Get severity emoji for a failure. */
65
+ function severityEmoji(severity) {
66
+ switch (severity) {
67
+ case 'critical':
68
+ return '🔴';
69
+ case 'warning':
70
+ return '🟡';
71
+ case 'info':
72
+ return '🔵';
73
+ default:
74
+ return '⚪';
75
+ }
76
+ }
77
+ // ---------------------------------------------------------------------------
78
+ // CSS theme (dark)
79
+ // ---------------------------------------------------------------------------
80
+ const CSS = `
81
+ :root {
82
+ color-scheme: dark;
83
+ }
84
+ body {
85
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
86
+ background: #0d1117;
87
+ color: #c9d1d9;
88
+ margin: 0;
89
+ padding: 2rem 1rem;
90
+ line-height: 1.6;
91
+ }
92
+ .container {
93
+ max-width: 960px;
94
+ margin: 0 auto;
95
+ }
96
+ h1 {
97
+ color: #f0f6fc;
98
+ border-bottom: 1px solid #30363d;
99
+ padding-bottom: 0.5rem;
100
+ }
101
+ h2 {
102
+ color: #58a6ff;
103
+ margin-top: 2.5rem;
104
+ border-bottom: 1px solid #21262d;
105
+ padding-bottom: 0.3rem;
106
+ }
107
+ h3 {
108
+ color: #d2a8ff;
109
+ margin-top: 1.5rem;
110
+ }
111
+ table {
112
+ border-collapse: collapse;
113
+ width: 100%;
114
+ margin: 1rem 0;
115
+ font-size: 0.875rem;
116
+ }
117
+ th, td {
118
+ border: 1px solid #30363d;
119
+ padding: 0.5rem 0.75rem;
120
+ text-align: left;
121
+ }
122
+ th {
123
+ background: #161b22;
124
+ color: #f0f6fc;
125
+ }
126
+ tr:nth-child(even) {
127
+ background: #161b22;
128
+ }
129
+ code {
130
+ background: #161b22;
131
+ padding: 0.15rem 0.4rem;
132
+ border-radius: 4px;
133
+ font-size: 0.85em;
134
+ }
135
+ .header-meta {
136
+ display: grid;
137
+ grid-template-columns: max-content 1fr;
138
+ gap: 0.25rem 1rem;
139
+ margin: 1rem 0;
140
+ }
141
+ .header-meta dt {
142
+ color: #8b949e;
143
+ font-weight: 600;
144
+ }
145
+ .stats {
146
+ display: flex;
147
+ gap: 1.5rem;
148
+ flex-wrap: wrap;
149
+ margin: 1rem 0;
150
+ }
151
+ .stat {
152
+ background: #161b22;
153
+ border: 1px solid #30363d;
154
+ border-radius: 6px;
155
+ padding: 0.75rem 1.25rem;
156
+ text-align: center;
157
+ }
158
+ .stat .stat-value {
159
+ font-size: 1.5rem;
160
+ font-weight: 700;
161
+ color: #f0f6fc;
162
+ }
163
+ .stat .stat-label {
164
+ color: #8b949e;
165
+ font-size: 0.8rem;
166
+ text-transform: uppercase;
167
+ letter-spacing: 0.05em;
168
+ }
169
+ .failure {
170
+ background: #161b22;
171
+ border: 1px solid #30363d;
172
+ border-radius: 6px;
173
+ padding: 1rem 1.25rem;
174
+ margin: 1rem 0;
175
+ }
176
+ .severity-badge {
177
+ display: inline-block;
178
+ padding: 0.15rem 0.5rem;
179
+ border-radius: 12px;
180
+ font-size: 0.75rem;
181
+ font-weight: 600;
182
+ text-transform: uppercase;
183
+ }
184
+ .severity-critical { background: #da3633; color: #fff; }
185
+ .severity-warning { background: #d29922; color: #1a1a1a; }
186
+ .severity-info { background: #1f6feb; color: #fff; }
187
+ .severity-default { background: #30363d; color: #c9d1d9; }
188
+ .ok-message {
189
+ color: #3fb950;
190
+ font-style: italic;
191
+ }
192
+ ol, ul { padding-left: 1.5rem; }
193
+ .event-id { color: #8b949e; font-family: monospace; }
194
+ footer {
195
+ color: #8b949e;
196
+ font-size: 0.8rem;
197
+ margin-top: 3rem;
198
+ padding-top: 1rem;
199
+ border-top: 1px solid #21262d;
200
+ }
201
+ `;
202
+ // ---------------------------------------------------------------------------
203
+ // Section generators
204
+ // ---------------------------------------------------------------------------
205
+ function generateHead() {
206
+ return `<head>
207
+ <meta charset="utf-8">
208
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
209
+ <title>OCPP DebugKit — Trace Analysis Report</title>
210
+ <style>${CSS}</style>
211
+ </head>`;
212
+ }
213
+ function generateHeader(result) {
214
+ const parts = ['<h1>OCPP DebugKit — Trace Analysis Report</h1>'];
215
+ // Metadata
216
+ if (result.metadata) {
217
+ const m = result.metadata;
218
+ const metaRows = [];
219
+ if (m.stationId) {
220
+ metaRows.push(`<dt>Station</dt><dd>${escapeHtml(m.stationId)}</dd>`);
221
+ }
222
+ if (m.ocppVersion) {
223
+ metaRows.push(`<dt>OCPP Version</dt><dd>${escapeHtml(m.ocppVersion)}</dd>`);
224
+ }
225
+ if (m.source) {
226
+ metaRows.push(`<dt>Source</dt><dd>${escapeHtml(m.source)}</dd>`);
227
+ }
228
+ if (m.description) {
229
+ metaRows.push(`<dt>Description</dt><dd>${escapeHtml(m.description)}</dd>`);
230
+ }
231
+ if (metaRows.length > 0) {
232
+ parts.push(`<dl class="header-meta">${metaRows.join('')}</dl>`);
233
+ }
234
+ }
235
+ // Stats
236
+ const stats = [
237
+ { label: 'Events', value: result.events.length },
238
+ { label: 'Sessions', value: result.sessions.length },
239
+ { label: 'Failures', value: result.failures.length },
240
+ { label: 'Warnings', value: result.warnings.length },
241
+ ];
242
+ const statHtml = stats
243
+ .map((s) => `<div class="stat"><div class="stat-value">${escapeHtml(s.value)}</div><div class="stat-label">${escapeHtml(s.label)}</div></div>`)
244
+ .join('');
245
+ parts.push(`<div class="stats">${statHtml}</div>`);
246
+ // Parse warnings
247
+ if (result.warnings.length > 0) {
248
+ const items = result.warnings.map((w) => `<li>${escapeHtml(w.message)}</li>`).join('');
249
+ parts.push(`<h2>Parse Warnings</h2><ul>${items}</ul>`);
250
+ }
251
+ return parts.join('\n');
252
+ }
253
+ function generateSessionOverview(result) {
254
+ if (result.sessions.length === 0) {
255
+ return '<h2>Session Overview</h2><p>No sessions detected.</p>';
256
+ }
257
+ const rows = result.sessions
258
+ .map((session) => {
259
+ const summary = result.summaries.find((s) => s.sessionId === session.sessionId);
260
+ const duration = summary?.durationMs ?? null;
261
+ return `<tr>
262
+ <td>${escapeHtml(session.sessionId)}</td>
263
+ <td>${escapeHtml(session.stationId)}</td>
264
+ <td>${escapeHtml(session.connectorId ?? '-')}</td>
265
+ <td>${escapeHtml(session.transactionId ?? '-')}</td>
266
+ <td>${escapeHtml(formatTimestamp(session.startTime))}</td>
267
+ <td>${escapeHtml(formatTimestamp(session.endTime))}</td>
268
+ <td>${escapeHtml(formatDuration(duration))}</td>
269
+ <td>${escapeHtml(session.status)}</td>
270
+ </tr>`;
271
+ })
272
+ .join('\n');
273
+ return `<h2>Session Overview</h2>
274
+ <table>
275
+ <thead><tr><th>Session</th><th>Station</th><th>Connector</th><th>Transaction</th><th>Start</th><th>End</th><th>Duration</th><th>Status</th></tr></thead>
276
+ <tbody>
277
+ ${rows}
278
+ </tbody>
279
+ </table>`;
280
+ }
281
+ function generateTimelineSummary(result) {
282
+ if (result.summaries.length === 0) {
283
+ return '<h2>Timeline Summary</h2><p>No sessions to summarize.</p>';
284
+ }
285
+ const blocks = result.summaries
286
+ .map((summary) => {
287
+ const actionSequence = escapeHtml(summary.actionSequence.join(' → ')) || 'None';
288
+ return `<h3>${escapeHtml(summary.sessionId)}</h3>
289
+ <ul>
290
+ <li><strong>Events:</strong> ${escapeHtml(summary.eventCount)}</li>
291
+ <li><strong>Duration:</strong> ${escapeHtml(formatDuration(summary.durationMs))}</li>
292
+ <li><strong>Failures:</strong> ${escapeHtml(summary.failureCount)}</li>
293
+ <li><strong>Action Sequence:</strong> ${actionSequence}</li>
294
+ </ul>`;
295
+ })
296
+ .join('\n');
297
+ return `<h2>Timeline Summary</h2>\n${blocks}`;
298
+ }
299
+ function generateFailures(result) {
300
+ if (result.failures.length === 0) {
301
+ return '<h2>Failures</h2><p class="ok-message">No failures detected. ✅</p>';
302
+ }
303
+ const blocks = result.failures
304
+ .map((failure) => {
305
+ const stepsItems = failure.suggestedSteps
306
+ .map((step) => `<li>${escapeHtml(step)}</li>`)
307
+ .join('\n');
308
+ const eventIds = failure.eventIds
309
+ .map((id) => `<span class="event-id">${escapeHtml(id)}</span>`)
310
+ .join(', ');
311
+ return `<div class="failure">
312
+ <h3>${escapeHtml(severityEmoji(failure.severity))} ${escapeHtml(failure.code)}</h3>
313
+ <p><span class="severity-badge ${severityClass(failure.severity)}">${escapeHtml(failure.severity)}</span></p>
314
+ <p><strong>Description:</strong> ${escapeHtml(failure.description)}</p>
315
+ <p><strong>Events:</strong> ${eventIds}</p>
316
+ <p><strong>Suggested Steps:</strong></p>
317
+ <ol>
318
+ ${stepsItems}
319
+ </ol>
320
+ </div>`;
321
+ })
322
+ .join('\n');
323
+ return `<h2>Failures</h2>\n${blocks}`;
324
+ }
325
+ function generateSuggestedSteps(result) {
326
+ if (result.failures.length === 0) {
327
+ return '<h2>Suggested Next Steps</h2><p class="ok-message">No issues detected. The trace appears to represent a normal charging session.</p>';
328
+ }
329
+ const allSteps = new Set();
330
+ for (const failure of result.failures) {
331
+ for (const step of failure.suggestedSteps) {
332
+ allSteps.add(step);
333
+ }
334
+ }
335
+ const items = Array.from(allSteps)
336
+ .map((step) => `<li>${escapeHtml(step)}</li>`)
337
+ .join('\n');
338
+ return `<h2>Suggested Next Steps</h2>\n<ol>\n${items}\n</ol>`;
339
+ }
340
+ function generateEventAppendix(result) {
341
+ if (result.events.length === 0) {
342
+ return '<h2>Event Appendix</h2><p>No events to display.</p>';
343
+ }
344
+ function formatEventCompact(event) {
345
+ const time = formatTimestamp(event.timestamp);
346
+ const action = event.action ?? '-';
347
+ return `<tr>
348
+ <td>${escapeHtml(event.id)}</td>
349
+ <td>${escapeHtml(time)}</td>
350
+ <td>${escapeHtml(event.direction)}</td>
351
+ <td>${escapeHtml(event.messageType)}</td>
352
+ <td>${escapeHtml(action)}</td>
353
+ <td><code>${escapeHtml(event.messageId)}</code></td>
354
+ </tr>`;
355
+ }
356
+ const rows = result.events.map(formatEventCompact).join('\n');
357
+ return `<h2>Event Appendix</h2>
358
+ <table>
359
+ <thead><tr><th>ID</th><th>Timestamp</th><th>Direction</th><th>Type</th><th>Action</th><th>MessageId</th></tr></thead>
360
+ <tbody>
361
+ ${rows}
362
+ </tbody>
363
+ </table>`;
364
+ }
365
+ // ---------------------------------------------------------------------------
366
+ // generateHtmlReport()
367
+ // ---------------------------------------------------------------------------
368
+ /**
369
+ * Generate a self-contained HTML report from an analysis result.
370
+ *
371
+ * All user-supplied content is HTML-escaped to prevent injection / XSS.
372
+ *
373
+ * @param result - The analysis result to report on
374
+ * @returns A self-contained HTML string (inline CSS, no external dependencies)
375
+ */
376
+ export function generateHtmlReport(result) {
377
+ const body = [
378
+ generateHeader(result),
379
+ generateSessionOverview(result),
380
+ generateTimelineSummary(result),
381
+ generateFailures(result),
382
+ generateSuggestedSteps(result),
383
+ generateEventAppendix(result),
384
+ ].join('\n');
385
+ return `<!DOCTYPE html>
386
+ <html lang="en">
387
+ ${generateHead()}
388
+ <body>
389
+ <div class="container">
390
+ ${body}
391
+ <footer>Generated by OCPP DebugKit</footer>
392
+ </div>
393
+ </body>
394
+ </html>`;
395
+ }
396
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/reporter/html.ts"],"names":[],"mappings":"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"}
@@ -3,4 +3,5 @@
3
3
  */
4
4
  export type { AnalysisResult } from './types.js';
5
5
  export { generateMarkdownReport } from './markdown.js';
6
+ export { generateHtmlReport } from './html.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reporter/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reporter/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC"}
@@ -2,4 +2,5 @@
2
2
  * Barrel export for the @ocpp-debugkit/reporter package.
3
3
  */
4
4
  export { generateMarkdownReport } from './markdown.js';
5
+ export { generateHtmlReport } from './html.js';
5
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reporter/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reporter/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC"}