diff --git a/.prettierignore b/.prettierignore index ebf20c6..1f2e5e6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -6,3 +6,4 @@ build/ coverage/ pnpm-lock.yaml *.md +apps/web/next-env.d.ts diff --git a/AGENTS.md b/AGENTS.md index 83bd690..f642b79 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,12 +21,14 @@ infrastructure developers. ``` ocpp-debugkit/ ├── packages/ -│ ├── core/ # Data model, parser, normalizer, timeline, failure detection -│ ├── scenarios/ # Predefined trace scenarios for testing -│ ├── reporter/ # Report generators (Markdown, HTML) -│ ├── cli/ # Command-line interface -│ ├── replay/ # Replay engine (v0.2+) -│ └── react/ # Reusable React components (v0.2+) +│ └── toolkit/ # Single npm package @ocpp-debugkit/toolkit +│ └── src/ +│ ├── core/ # Data model, parser, normalizer, timeline, failure detection +│ ├── scenarios/ # Predefined trace scenarios for testing +│ ├── reporter/ # Report generators (Markdown, HTML) +│ ├── replay/ # Replay engine +│ ├── react/ # Reusable React components +│ └── cli/ # Command-line interface (bin: ocpp-debugkit) ├── apps/ │ └── web/ # Single Next.js app (landing, inspector, docs, blog) ├── turbo.json # Turborepo task pipeline @@ -52,16 +54,20 @@ pnpm changeset # Add a changeset for release ## Package Dependency Graph ``` - core ← everything depends on this - / | \ - scenarios | reporter | replay - \ | / | - cli | - | | - apps/web (single Next.js app) +@ocpp-debugkit/toolkit (single package, subpath exports) + src/ + core ← internal modules depend on this + scenarios ← depends on core (internal) + reporter ← depends on core (internal) + replay ← depends on core (internal) + react ← depends on core, scenarios, reporter, replay (internal) + cli ← depends on core, scenarios, reporter (internal; Node-only) + +apps/web (single Next.js app) + imports: @ocpp-debugkit/toolkit/core, /scenarios, /reporter, /react, /replay ``` -**Build order:** core → scenarios/reporter/replay → cli → app +**Build order:** toolkit (all internal modules in one tsc pass) → app ## Testing Conventions diff --git a/CURRENT_STATE.md b/CURRENT_STATE.md index c20c69f..898573a 100644 --- a/CURRENT_STATE.md +++ b/CURRENT_STATE.md @@ -4,13 +4,13 @@ ## Current Version -`0.1.0` — Inspector MVP (released) +`0.2.0` — Packaging Consolidation + Scenario Evaluator & Replay (in progress) ## Active Milestone -**v0.1.0 — Inspector MVP (complete)** +**v0.2.0 — Packaging Consolidation + Scenario Evaluator & Replay (in progress)** -All v0.1.0 issues complete. Packages published to npm. Web app deployed. +Phase 0: Packaging consolidation — creating `@ocpp-debugkit/toolkit` single package with subpath exports. ## What's Done @@ -156,11 +156,23 @@ All v0.1.0 issues complete. Packages published to npm. Web app deployed. - ✅ `/docs` index with navigation sidebar - ✅ `/docs/quickstart`, `/docs/glossary`, `/docs/architecture`, `/docs/trace-format`, `/docs/cli`, `/docs/scenarios` +### Packaging Consolidation (v0.2.0 Phase 0 — in progress) + +- 🔄 `packages/toolkit/` — single `@ocpp-debugkit/toolkit` package created +- 🔄 Core, scenarios, reporter, CLI code moved into `src/core/`, `src/scenarios/`, `src/reporter/`, `src/cli/` +- 🔄 `src/replay/` and `src/react/` stub modules added +- 🔄 Subpath exports configured (`/core`, `/scenarios`, `/reporter`, `/replay`, `/react`, `/cli`, `/fixtures`) +- 🔄 CLI binary `ocpp-debugkit` via `package.json#bin` +- 🔄 Old package directories removed +- 🔄 Web app updated to consume `@ocpp-debugkit/toolkit` +- 🔄 All 196 existing tests pass from new locations +- 🔄 Build, lint, typecheck, format all green + ## What's Next -1. **v0.2.0** — Scenario evaluator & replay (expanded failure rules, replay - engine, `@ocpp-debugkit/react`, CLI external scenario files, HTML report - format, app replay UI) +1. **v0.2.0 remaining** — External fixture test, migration docs, release workflow + simplification, expanded failure detection (7 new rules), 10 scenarios, replay + engine, React components, HTML reports, app replay UI 2. **v0.3.0** — Integrations & OSS credibility (trace diffing, CI mode, anonymize, integration examples) 3. **v1.0.0** — API stabilization, 20+ scenarios, docs overhaul, contributor @@ -174,10 +186,9 @@ All v0.1.0 issues complete. Packages published to npm. Web app deployed. | Package | Status | Version | |---------|--------|---------| -| `@ocpp-debugkit/core` | published | 0.1.1 | -| `@ocpp-debugkit/scenarios` | published | 0.1.1 | -| `@ocpp-debugkit/reporter` | published | 0.1.1 | -| `@ocpp-debugkit/cli` | published | 0.1.1 | -| `@ocpp-debugkit/replay` | not started | — | -| `@ocpp-debugkit/react` | not started | — | +| `@ocpp-debugkit/toolkit` | in progress | 0.2.0 | +| `@ocpp-debugkit/core` | published (deprecated after v0.2.0) | 0.1.1 | +| `@ocpp-debugkit/scenarios` | published (deprecated after v0.2.0) | 0.1.1 | +| `@ocpp-debugkit/reporter` | published (deprecated after v0.2.0) | 0.1.1 | +| `@ocpp-debugkit/cli` | published (deprecated after v0.2.0) | 0.1.1 | | `apps/web` | deployed | — | diff --git a/apps/web/package.json b/apps/web/package.json index a43c554..4981069 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -12,9 +12,7 @@ "test:e2e": "playwright test" }, "dependencies": { - "@ocpp-debugkit/core": "workspace:*", - "@ocpp-debugkit/reporter": "workspace:*", - "@ocpp-debugkit/scenarios": "workspace:*", + "@ocpp-debugkit/toolkit": "workspace:*", "next": "16.2.10", "react": "19.2.4", "react-dom": "19.2.4" diff --git a/apps/web/src/app/docs/cli/page.tsx b/apps/web/src/app/docs/cli/page.tsx index d5ac5f0..e630869 100644 --- a/apps/web/src/app/docs/cli/page.tsx +++ b/apps/web/src/app/docs/cli/page.tsx @@ -9,7 +9,7 @@ export default function CliReferencePage() {
-{`npm install -g @ocpp-debugkit/cli`}+{`npm install -g @ocpp-debugkit/toolkit`}
-{`npm install -g @ocpp-debugkit/cli`}+{`npm install -g @ocpp-debugkit/toolkit`}
For programmatic use in your own TypeScript/JavaScript project:
- {`import { parseTrace, buildSessionTimeline, detectFailures } from '@ocpp-debugkit/core';
+ {`import { parseTrace, buildSessionTimeline, detectFailures } from '@ocpp-debugkit/toolkit/core';
const result = parseTrace(traceString);
const sessions = buildSessionTimeline(result.events);
diff --git a/apps/web/src/app/inspector/page.tsx b/apps/web/src/app/inspector/page.tsx
index 41228b0..f3bbfd8 100644
--- a/apps/web/src/app/inspector/page.tsx
+++ b/apps/web/src/app/inspector/page.tsx
@@ -14,9 +14,9 @@ import {
type Scenario,
ParseError,
MAX_INPUT_SIZE_BYTES,
-} from '@ocpp-debugkit/core';
-import { generateMarkdownReport } from '@ocpp-debugkit/reporter';
-import { scenarios } from '@ocpp-debugkit/scenarios';
+} from '@ocpp-debugkit/toolkit/core';
+import { generateMarkdownReport } from '@ocpp-debugkit/toolkit/reporter';
+import { scenarios } from '@ocpp-debugkit/toolkit/scenarios';
// ---------------------------------------------------------------------------
// Types
diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx
index a17a80b..be1703a 100644
--- a/apps/web/src/app/page.tsx
+++ b/apps/web/src/app/page.tsx
@@ -73,13 +73,13 @@ export default function HomePage() {
Architecture
- A modular monorepo with independent packages. Use only what you need.
+ A single package with modular subpath exports. Use only what you need.
-
-
-
-
+
+
+
+
@@ -91,7 +91,7 @@ export default function HomePage() {
{`# Install the CLI
-npm install -g @ocpp-debugkit/cli
+npm install -g @ocpp-debugkit/toolkit
# Inspect a trace
ocpp-debugkit inspect trace.json
diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md
deleted file mode 100644
index 81de88f..0000000
--- a/packages/cli/CHANGELOG.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# @ocpp-debugkit/cli
-
-## 0.1.1
-
-### Patch Changes
-
-- 38618c7: Add package READMEs for npm discoverability.
-- Updated dependencies [38618c7]
- - @ocpp-debugkit/core@0.1.1
- - @ocpp-debugkit/scenarios@0.1.1
- - @ocpp-debugkit/reporter@0.1.1
-
-## 0.1.0
-
-### Minor Changes
-
-- a959fa4: Create CLI package with inspect, report, and scenario commands.
-
- - `ocpp-debugkit inspect ` — parse + analyze + output summary
- - `ocpp-debugkit report ` — generate Markdown report (stdout or --output)
- - `ocpp-debugkit scenario list` — list all 5 built-in scenarios
- - `ocpp-debugkit scenario run ` — run scenario through analysis engine,
- compare detected vs expected failures
- - Path safety: validated file paths, size limits
- - Input validation: safe parsing, non-sensitive error messages
- - 17 integration tests (execa-based)
- - Converted JSON fixtures to TS modules (fixes Node.js ESM JSON import issue)
-
-### Patch Changes
-
-- Updated dependencies [07bca8c]
-- Updated dependencies [9543d50]
-- Updated dependencies [f2cef5d]
-- Updated dependencies [805434f]
-- Updated dependencies [17c2aa0]
- - @ocpp-debugkit/core@0.1.0
- - @ocpp-debugkit/reporter@0.1.0
- - @ocpp-debugkit/scenarios@0.1.0
diff --git a/packages/cli/README.md b/packages/cli/README.md
deleted file mode 100644
index c0814e5..0000000
--- a/packages/cli/README.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# @ocpp-debugkit/cli
-
-> Command-line interface for OCPP DebugKit — inspect traces, generate reports, run scenarios.
-
-## Installation
-
-```bash
-npm install -g @ocpp-debugkit/cli
-```
-
-## Commands
-
-### inspect
-
-Parse and analyze an OCPP trace file:
-
-```bash
-ocpp-debugkit inspect trace.json
-```
-
-Outputs event count, sessions, detected failures, and parse warnings.
-
-### report
-
-Generate a Markdown report:
-
-```bash
-# To stdout
-ocpp-debugkit report trace.json
-
-# To a file
-ocpp-debugkit report trace.json --output report.md
-
-# Specify format
-ocpp-debugkit report trace.json --format markdown
-```
-
-### scenario list
-
-List all available built-in scenarios:
-
-```bash
-ocpp-debugkit scenario list
-```
-
-### scenario run
-
-Run a scenario through the analysis engine and compare detected vs expected failures:
-
-```bash
-ocpp-debugkit scenario run failed-auth
-```
-
-**Note:** `scenario run` runs static fixtures through the local analysis engine only. It is not active endpoint testing, WebSocket simulation, or live station/CSMS testing.
-
-## Accepted Trace Formats
-
-- **JSON Object** — `{ "metadata": {...}, "events": [...] }`
-- **JSONL** — one event per line
-- **Bare array** — `[[2, "id", "Action", {}], ...]`
-
-## Limits
-
-- Maximum input size: 10 MB
-- Maximum event count: 10,000
-
-## License
-
-Apache 2.0
diff --git a/packages/cli/package.json b/packages/cli/package.json
deleted file mode 100644
index e8cd431..0000000
--- a/packages/cli/package.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "name": "@ocpp-debugkit/cli",
- "version": "0.1.1",
- "description": "Command-line interface for OCPP DebugKit — inspect traces, generate reports, run scenarios.",
- "license": "Apache-2.0",
- "type": "module",
- "main": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "bin": {
- "ocpp-debugkit": "./dist/index.js"
- },
- "files": [
- "dist",
- "README.md",
- "NOTICE"
- ],
- "keywords": [
- "ocpp",
- "ocpp1.6",
- "ev-charging",
- "cli",
- "debugging",
- "trace-inspector"
- ],
- "repository": {
- "type": "git",
- "url": "https://github.com/ocpp-debugkit/ocpp-debugkit.git",
- "directory": "packages/cli"
- },
- "homepage": "https://github.com/ocpp-debugkit/ocpp-debugkit/tree/main/packages/cli",
- "bugs": {
- "url": "https://github.com/ocpp-debugkit/ocpp-debugkit/issues"
- },
- "scripts": {
- "build": "tsc -p tsconfig.json",
- "typecheck": "tsc --noEmit",
- "test": "vitest run",
- "clean": "rm -rf dist .turbo"
- },
- "dependencies": {
- "@ocpp-debugkit/core": "workspace:*",
- "@ocpp-debugkit/scenarios": "workspace:*",
- "@ocpp-debugkit/reporter": "workspace:*",
- "commander": "^13.0.0"
- },
- "devDependencies": {
- "typescript": "^5.7.0",
- "vitest": "^3.0.0",
- "execa": "^9.0.0"
- },
- "publishConfig": {
- "access": "public"
- }
-}
diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json
deleted file mode 100644
index dd1cdcb..0000000
--- a/packages/cli/tsconfig.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "outDir": "./dist",
- "rootDir": "./src"
- },
- "include": ["src"],
- "exclude": ["node_modules", "dist", "**/*.test.ts"]
-}
diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md
deleted file mode 100644
index bd233cb..0000000
--- a/packages/core/CHANGELOG.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# @ocpp-debugkit/core
-
-## 0.1.1
-
-### Patch Changes
-
-- 38618c7: Add package READMEs for npm discoverability.
-
-## 0.1.0
-
-### Minor Changes
-
-- 07bca8c: Finalize core package for npm publishing.
-
- - Add `sideEffects: false` for tree-shaking
- - Add `files` field to limit published content
- - Add `keywords`, `repository`, `homepage`, `bugs` fields for npm discoverability
- - Verify barrel export is complete (types, schemas, parser, normalizer, timeline, detection, summarizer, validator, fixtures)
-
-- 9543d50: Implement trace parser, event normalizer, and Zod schemas.
-
- - `parseTrace()` accepts JSON Object, JSONL, and bare array trace formats
- - `normalizeEvents()` classifies message types, infers directions (ADR-0004),
- and normalizes timestamps to epoch milliseconds (ADR-0005)
- - Zod schemas validate all untrusted input, preventing prototype pollution
- - Input size limit (10 MB) and event count limit (10,000) enforced
- - Malformed individual events are skipped with `ParseWarning` (ADR-0007)
- - Added `Failure`, `Scenario`, `SessionSummary`, `ValidationResult` types
- - 78 new unit tests (46 normalizer + 32 parser)
-
-- f2cef5d: Implement session timeline, failure detection, summarizer, and validator.
-
- - `buildSessionTimeline()` correlates events into sessions by transactionId (ADR-0006)
- - `detectFailures()` implements 3 detection rules: FAILED_AUTHORIZATION,
- CONNECTOR_FAULT, STATION_OFFLINE_DURING_SESSION
- - `summarizeSession()` / `summarizeSessions()` produce overview statistics
- - `validateMessage()` / `validateMessages()` check OCPP 1.6 JSON structural compliance
- - 40 new unit tests (10 timeline + 11 detection + 5 summarizer + 14 validator)
diff --git a/packages/core/README.md b/packages/core/README.md
deleted file mode 100644
index 69a55b2..0000000
--- a/packages/core/README.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# @ocpp-debugkit/core
-
-> Core data model, parser, normalizer, timeline, and failure detection for OCPP DebugKit.
-
-## Installation
-
-```bash
-npm install @ocpp-debugkit/core
-```
-
-## Usage
-
-### Parse a trace
-
-```typescript
-import { parseTrace } from '@ocpp-debugkit/core';
-
-const result = parseTrace(traceString);
-// result.events — normalized Event[]
-// result.warnings — ParseWarning[] for malformed entries
-```
-
-Accepts JSON Object, JSONL, and bare array formats.
-
-### Build session timeline
-
-```typescript
-import { buildSessionTimeline } from '@ocpp-debugkit/core';
-
-const sessions = buildSessionTimeline(result.events);
-```
-
-### Detect failures
-
-```typescript
-import { detectFailures } from '@ocpp-debugkit/core';
-
-const failures = detectFailures(result.events, sessions);
-// Three detection rules: FAILED_AUTHORIZATION, CONNECTOR_FAULT,
-// STATION_OFFLINE_DURING_SESSION
-```
-
-### Generate summaries
-
-```typescript
-import { summarizeSessions } from '@ocpp-debugkit/core';
-
-const summaries = summarizeSessions(sessions, failures);
-```
-
-### Validate messages
-
-```typescript
-import { validateMessage } from '@ocpp-debugkit/core';
-
-const result = validateMessage(event);
-// result.valid, result.errors
-```
-
-## Key Types
-
-- `Event` — canonical normalized OCPP message
-- `Session` — logical charging session
-- `Failure` — detected failure with severity and suggested steps
-- `Scenario` — predefined trace fixture with expected failures
-
-## License
-
-Apache 2.0
diff --git a/packages/core/package.json b/packages/core/package.json
deleted file mode 100644
index d35c9dd..0000000
--- a/packages/core/package.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
- "name": "@ocpp-debugkit/core",
- "version": "0.1.1",
- "description": "Core data model, parser, normalizer, timeline, and failure detection for OCPP DebugKit.",
- "license": "Apache-2.0",
- "type": "module",
- "sideEffects": false,
- "main": "./dist/index.js",
- "module": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "exports": {
- ".": {
- "types": "./dist/index.d.ts",
- "import": "./dist/index.js"
- },
- "./fixtures": {
- "types": "./dist/fixtures/index.d.ts",
- "import": "./dist/fixtures/index.js"
- }
- },
- "files": [
- "dist",
- "README.md",
- "NOTICE"
- ],
- "keywords": [
- "ocpp",
- "ocpp1.6",
- "ev-charging",
- "charge-point",
- "csms",
- "debugging",
- "trace-parser",
- "failure-detection"
- ],
- "repository": {
- "type": "git",
- "url": "https://github.com/ocpp-debugkit/ocpp-debugkit.git",
- "directory": "packages/core"
- },
- "homepage": "https://github.com/ocpp-debugkit/ocpp-debugkit/tree/main/packages/core",
- "bugs": {
- "url": "https://github.com/ocpp-debugkit/ocpp-debugkit/issues"
- },
- "scripts": {
- "build": "tsc -p tsconfig.json",
- "typecheck": "tsc --noEmit",
- "test": "vitest run",
- "clean": "rm -rf dist .turbo"
- },
- "dependencies": {
- "zod": "^4.4.3"
- },
- "devDependencies": {
- "typescript": "^5.7.0",
- "vitest": "^3.0.0"
- },
- "publishConfig": {
- "access": "public"
- }
-}
diff --git a/packages/reporter/CHANGELOG.md b/packages/reporter/CHANGELOG.md
deleted file mode 100644
index df6c77f..0000000
--- a/packages/reporter/CHANGELOG.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# @ocpp-debugkit/reporter
-
-## 0.1.1
-
-### Patch Changes
-
-- 38618c7: Add package READMEs for npm discoverability.
-- Updated dependencies [38618c7]
- - @ocpp-debugkit/core@0.1.1
-
-## 0.1.0
-
-### Minor Changes
-
-- 805434f: Create reporter package with Markdown report generator.
-
- - `generateMarkdownReport()` produces a structured Markdown report with:
- session overview, timeline summary, failures (with severity and suggested
- steps), suggested next steps, and raw event appendix
- - `AnalysisResult` input type representing the analysis pipeline output
- - 11 tests covering structure, failure inclusion, readability, metadata, severity
-
-### Patch Changes
-
-- Updated dependencies [07bca8c]
-- Updated dependencies [9543d50]
-- Updated dependencies [f2cef5d]
- - @ocpp-debugkit/core@0.1.0
diff --git a/packages/reporter/README.md b/packages/reporter/README.md
deleted file mode 100644
index 253a0e1..0000000
--- a/packages/reporter/README.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# @ocpp-debugkit/reporter
-
-> Report generators for OCPP DebugKit analysis results.
-
-## Installation
-
-```bash
-npm install @ocpp-debugkit/reporter
-```
-
-## Usage
-
-### Generate a Markdown report
-
-```typescript
-import { generateMarkdownReport } from '@ocpp-debugkit/reporter';
-import type { AnalysisResult } from '@ocpp-debugkit/reporter';
-
-const report = generateMarkdownReport({
- events,
- sessions,
- failures,
- summaries,
- warnings,
-});
-
-// report is a Markdown string with:
-// - Session overview table
-// - Timeline summary (action sequences)
-// - Failures (severity, description, suggested steps)
-// - Suggested next steps
-// - Raw event appendix
-```
-
-## Input Type
-
-```typescript
-interface AnalysisResult {
- events: Event[];
- sessions: Session[];
- failures: Failure[];
- summaries: SessionSummary[];
- warnings: ParseWarning[];
- metadata?: TraceMetadata;
-}
-```
-
-## License
-
-Apache 2.0
diff --git a/packages/reporter/package.json b/packages/reporter/package.json
deleted file mode 100644
index b94b5c7..0000000
--- a/packages/reporter/package.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "name": "@ocpp-debugkit/reporter",
- "version": "0.1.1",
- "description": "Report generators (Markdown, HTML) for OCPP DebugKit analysis results.",
- "license": "Apache-2.0",
- "type": "module",
- "sideEffects": false,
- "main": "./dist/index.js",
- "module": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "exports": {
- ".": {
- "types": "./dist/index.d.ts",
- "import": "./dist/index.js"
- }
- },
- "files": [
- "dist",
- "README.md",
- "NOTICE"
- ],
- "keywords": [
- "ocpp",
- "ocpp1.6",
- "ev-charging",
- "report",
- "markdown",
- "debugging"
- ],
- "repository": {
- "type": "git",
- "url": "https://github.com/ocpp-debugkit/ocpp-debugkit.git",
- "directory": "packages/reporter"
- },
- "homepage": "https://github.com/ocpp-debugkit/ocpp-debugkit/tree/main/packages/reporter",
- "bugs": {
- "url": "https://github.com/ocpp-debugkit/ocpp-debugkit/issues"
- },
- "scripts": {
- "build": "tsc -p tsconfig.json",
- "typecheck": "tsc --noEmit",
- "test": "vitest run",
- "clean": "rm -rf dist .turbo"
- },
- "dependencies": {
- "@ocpp-debugkit/core": "workspace:*"
- },
- "devDependencies": {
- "typescript": "^5.7.0",
- "vitest": "^3.0.0"
- },
- "publishConfig": {
- "access": "public"
- }
-}
diff --git a/packages/reporter/tsconfig.json b/packages/reporter/tsconfig.json
deleted file mode 100644
index dd1cdcb..0000000
--- a/packages/reporter/tsconfig.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "outDir": "./dist",
- "rootDir": "./src"
- },
- "include": ["src"],
- "exclude": ["node_modules", "dist", "**/*.test.ts"]
-}
diff --git a/packages/scenarios/CHANGELOG.md b/packages/scenarios/CHANGELOG.md
deleted file mode 100644
index d4a04a1..0000000
--- a/packages/scenarios/CHANGELOG.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# @ocpp-debugkit/scenarios
-
-## 0.1.1
-
-### Patch Changes
-
-- 38618c7: Add package READMEs for npm discoverability.
-- Updated dependencies [38618c7]
- - @ocpp-debugkit/core@0.1.1
-
-## 0.1.0
-
-### Minor Changes
-
-- 17c2aa0: Create scenarios package with 5 initial scenarios.
-
- - Scenario registry with `getScenario()` lookup
- - 5 scenarios: normal-session, failed-auth, connector-fault,
- station-offline, unexpected-stop-reason
- - Each scenario's expectedFailures aligns with v0.1 detection rules
- - 21 tests (registry, engine integration, synthetic data policy)
-
-### Patch Changes
-
-- Updated dependencies [07bca8c]
-- Updated dependencies [9543d50]
-- Updated dependencies [f2cef5d]
- - @ocpp-debugkit/core@0.1.0
diff --git a/packages/scenarios/README.md b/packages/scenarios/README.md
deleted file mode 100644
index e37b07f..0000000
--- a/packages/scenarios/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# @ocpp-debugkit/scenarios
-
-> Predefined OCPP trace scenarios for testing the DebugKit analysis engine.
-
-## Installation
-
-```bash
-npm install @ocpp-debugkit/scenarios
-```
-
-## Usage
-
-```typescript
-import { scenarios, getScenario } from '@ocpp-debugkit/scenarios';
-
-// List all scenario names
-scenarios.forEach(s => console.log(s.name, s.expectedFailures));
-
-// Get a specific scenario
-const scenario = getScenario('failed-auth');
-
-// Run through the analysis engine
-import { parseTrace, buildSessionTimeline, detectFailures } from '@ocpp-debugkit/core';
-
-const result = parseTrace(JSON.stringify(scenario.trace));
-const sessions = buildSessionTimeline(result.events);
-const failures = detectFailures(result.events, sessions);
-```
-
-## Available Scenarios
-
-| Name | Expected Failures |
-|------|-------------------|
-| `normal-session` | none |
-| `failed-auth` | `FAILED_AUTHORIZATION` |
-| `connector-fault` | `CONNECTOR_FAULT` |
-| `station-offline` | `STATION_OFFLINE_DURING_SESSION` |
-| `unexpected-stop-reason` | none (parser/timeline-only fixture) |
-
-All scenario data is fully synthetic — no real station identifiers or personal data.
-
-## License
-
-Apache 2.0
diff --git a/packages/scenarios/package.json b/packages/scenarios/package.json
deleted file mode 100644
index c24ae2a..0000000
--- a/packages/scenarios/package.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "name": "@ocpp-debugkit/scenarios",
- "version": "0.1.1",
- "description": "Predefined OCPP trace scenarios for testing the DebugKit analysis engine.",
- "license": "Apache-2.0",
- "type": "module",
- "sideEffects": false,
- "main": "./dist/index.js",
- "module": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "exports": {
- ".": {
- "types": "./dist/index.d.ts",
- "import": "./dist/index.js"
- }
- },
- "files": [
- "dist",
- "README.md",
- "NOTICE"
- ],
- "keywords": [
- "ocpp",
- "ocpp1.6",
- "ev-charging",
- "scenarios",
- "test-fixtures",
- "trace"
- ],
- "repository": {
- "type": "git",
- "url": "https://github.com/ocpp-debugkit/ocpp-debugkit.git",
- "directory": "packages/scenarios"
- },
- "homepage": "https://github.com/ocpp-debugkit/ocpp-debugkit/tree/main/packages/scenarios",
- "bugs": {
- "url": "https://github.com/ocpp-debugkit/ocpp-debugkit/issues"
- },
- "scripts": {
- "build": "tsc -p tsconfig.json",
- "typecheck": "tsc --noEmit",
- "test": "vitest run",
- "clean": "rm -rf dist .turbo"
- },
- "dependencies": {
- "@ocpp-debugkit/core": "workspace:*"
- },
- "devDependencies": {
- "typescript": "^5.7.0",
- "vitest": "^3.0.0"
- },
- "publishConfig": {
- "access": "public"
- }
-}
diff --git a/packages/scenarios/tsconfig.json b/packages/scenarios/tsconfig.json
deleted file mode 100644
index dd1cdcb..0000000
--- a/packages/scenarios/tsconfig.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "outDir": "./dist",
- "rootDir": "./src"
- },
- "include": ["src"],
- "exclude": ["node_modules", "dist", "**/*.test.ts"]
-}
diff --git a/packages/toolkit/NOTICE b/packages/toolkit/NOTICE
new file mode 100644
index 0000000..36936e8
--- /dev/null
+++ b/packages/toolkit/NOTICE
@@ -0,0 +1,14 @@
+OCPP DebugKit
+Copyright 2026 OCPP DebugKit Contributors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/packages/toolkit/README.md b/packages/toolkit/README.md
new file mode 100644
index 0000000..65d8c73
--- /dev/null
+++ b/packages/toolkit/README.md
@@ -0,0 +1,35 @@
+# @ocpp-debugkit/toolkit
+
+Open-source DevTools for debugging OCPP charging sessions.
+
+## Installation
+
+```bash
+npm install @ocpp-debugkit/toolkit
+```
+
+## Usage
+
+### Modular imports (recommended)
+
+```ts
+import { parseTrace, detectFailures, buildSessionTimeline } from '@ocpp-debugkit/toolkit/core';
+import { builtInScenarios, getScenario } from '@ocpp-debugkit/toolkit/scenarios';
+import { generateMarkdownReport } from '@ocpp-debugkit/toolkit/reporter';
+import { ReplayEngine } from '@ocpp-debugkit/toolkit/replay';
+import { SessionTimeline } from '@ocpp-debugkit/toolkit/react';
+```
+
+### CLI
+
+```bash
+npm install -g @ocpp-debugkit/toolkit
+ocpp-debugkit inspect trace.json
+ocpp-debugkit report trace.json
+ocpp-debugkit scenario list
+ocpp-debugkit scenario run normal-session
+```
+
+## License
+
+Apache 2.0
diff --git a/packages/toolkit/package.json b/packages/toolkit/package.json
new file mode 100644
index 0000000..39c5e8a
--- /dev/null
+++ b/packages/toolkit/package.json
@@ -0,0 +1,110 @@
+{
+ "name": "@ocpp-debugkit/toolkit",
+ "version": "0.2.0",
+ "description": "Open-source DevTools for debugging OCPP charging sessions — parser, normalizer, timeline, failure detection, scenarios, replay, reports, CLI, and React components.",
+ "license": "Apache-2.0",
+ "type": "module",
+ "sideEffects": false,
+ "main": "./dist/index.js",
+ "module": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "bin": {
+ "ocpp-debugkit": "./dist/cli/index.js"
+ },
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js"
+ },
+ "./core": {
+ "types": "./dist/core/index.d.ts",
+ "import": "./dist/core/index.js"
+ },
+ "./scenarios": {
+ "types": "./dist/scenarios/index.d.ts",
+ "import": "./dist/scenarios/index.js"
+ },
+ "./reporter": {
+ "types": "./dist/reporter/index.d.ts",
+ "import": "./dist/reporter/index.js"
+ },
+ "./replay": {
+ "types": "./dist/replay/index.d.ts",
+ "import": "./dist/replay/index.js"
+ },
+ "./react": {
+ "types": "./dist/react/index.d.ts",
+ "import": "./dist/react/index.js"
+ },
+ "./cli": {
+ "types": "./dist/cli/index.d.ts",
+ "import": "./dist/cli/index.js"
+ },
+ "./fixtures": {
+ "types": "./dist/core/fixtures/index.d.ts",
+ "import": "./dist/core/fixtures/index.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "files": [
+ "dist",
+ "README.md",
+ "NOTICE"
+ ],
+ "keywords": [
+ "ocpp",
+ "ocpp1.6",
+ "ev-charging",
+ "charge-point",
+ "csms",
+ "debugging",
+ "trace-parser",
+ "failure-detection",
+ "replay",
+ "scenario",
+ "report",
+ "cli"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/ocpp-debugkit/ocpp-debugkit.git",
+ "directory": "packages/toolkit"
+ },
+ "homepage": "https://github.com/ocpp-debugkit/ocpp-debugkit/tree/main/packages/toolkit",
+ "bugs": {
+ "url": "https://github.com/ocpp-debugkit/ocpp-debugkit/issues"
+ },
+ "scripts": {
+ "build": "tsc -p tsconfig.json",
+ "typecheck": "tsc --noEmit",
+ "test": "vitest run",
+ "clean": "rm -rf dist .turbo"
+ },
+ "dependencies": {
+ "zod": "^4.4.3",
+ "commander": "^13.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ },
+ "devDependencies": {
+ "@types/node": "^22.0.0",
+ "@types/react": "^19",
+ "@types/react-dom": "^19",
+ "execa": "^9.0.0",
+ "typescript": "^5.7.0",
+ "vitest": "^3.0.0"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/cli/src/cli.test.ts b/packages/toolkit/src/cli/cli.test.ts
similarity index 98%
rename from packages/cli/src/cli.test.ts
rename to packages/toolkit/src/cli/cli.test.ts
index 12d36c9..083a4f2 100644
--- a/packages/cli/src/cli.test.ts
+++ b/packages/toolkit/src/cli/cli.test.ts
@@ -3,9 +3,9 @@ import { execa } from 'execa';
import { writeFileSync, mkdtempSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
-import { fixtures } from '@ocpp-debugkit/core';
+import { fixtures } from '../core/index.js';
-const CLI_PATH = join(process.cwd(), 'packages/cli/dist/index.js');
+const CLI_PATH = join(process.cwd(), 'packages/toolkit/dist/cli/index.js');
// Helper: run the CLI with given args
async function runCli(
diff --git a/packages/cli/src/commands/inspect.ts b/packages/toolkit/src/cli/commands/inspect.ts
similarity index 98%
rename from packages/cli/src/commands/inspect.ts
rename to packages/toolkit/src/cli/commands/inspect.ts
index 6e60907..6f8e9bc 100644
--- a/packages/cli/src/commands/inspect.ts
+++ b/packages/toolkit/src/cli/commands/inspect.ts
@@ -8,7 +8,7 @@ import {
detectFailures,
summarizeSessions,
ParseError,
-} from '@ocpp-debugkit/core';
+} from '../../core/index.js';
import { CliError, readTraceFile } from '../utils.js';
export interface InspectOptions {
diff --git a/packages/cli/src/commands/report.ts b/packages/toolkit/src/cli/commands/report.ts
similarity index 95%
rename from packages/cli/src/commands/report.ts
rename to packages/toolkit/src/cli/commands/report.ts
index 8bd2990..f5c4128 100644
--- a/packages/cli/src/commands/report.ts
+++ b/packages/toolkit/src/cli/commands/report.ts
@@ -9,8 +9,8 @@ import {
summarizeSessions,
ParseError,
type Trace,
-} from '@ocpp-debugkit/core';
-import { generateMarkdownReport } from '@ocpp-debugkit/reporter';
+} from '../../core/index.js';
+import { generateMarkdownReport } from '../../reporter/index.js';
import { CliError, readTraceFile } from '../utils.js';
export interface ReportOptions {
diff --git a/packages/cli/src/commands/scenario.ts b/packages/toolkit/src/cli/commands/scenario.ts
similarity index 97%
rename from packages/cli/src/commands/scenario.ts
rename to packages/toolkit/src/cli/commands/scenario.ts
index 3f2a660..7de9cd1 100644
--- a/packages/cli/src/commands/scenario.ts
+++ b/packages/toolkit/src/cli/commands/scenario.ts
@@ -6,8 +6,8 @@
* live station/CSMS testing, or the v0.2 scenario evaluator.
*/
-import { parseTrace, buildSessionTimeline, detectFailures, ParseError } from '@ocpp-debugkit/core';
-import { scenarioNames, getScenario } from '@ocpp-debugkit/scenarios';
+import { parseTrace, buildSessionTimeline, detectFailures, ParseError } from '../../core/index.js';
+import { scenarioNames, getScenario } from '../../scenarios/index.js';
import { CliError } from '../utils.js';
export function scenarioListCommand(): void {
diff --git a/packages/cli/src/index.ts b/packages/toolkit/src/cli/index.ts
similarity index 100%
rename from packages/cli/src/index.ts
rename to packages/toolkit/src/cli/index.ts
diff --git a/packages/cli/src/utils.ts b/packages/toolkit/src/cli/utils.ts
similarity index 95%
rename from packages/cli/src/utils.ts
rename to packages/toolkit/src/cli/utils.ts
index 284f518..bc83920 100644
--- a/packages/cli/src/utils.ts
+++ b/packages/toolkit/src/cli/utils.ts
@@ -4,7 +4,7 @@
import { readFileSync, statSync } from 'node:fs';
import { resolve } from 'node:path';
-import { MAX_INPUT_SIZE_BYTES } from '@ocpp-debugkit/core';
+import { MAX_INPUT_SIZE_BYTES } from '../core/index.js';
/** Maximum file size for trace input (10 MB). */
const MAX_FILE_SIZE = MAX_INPUT_SIZE_BYTES;
diff --git a/packages/core/src/__fixtures__/connector-fault.ts b/packages/toolkit/src/core/__fixtures__/connector-fault.ts
similarity index 100%
rename from packages/core/src/__fixtures__/connector-fault.ts
rename to packages/toolkit/src/core/__fixtures__/connector-fault.ts
diff --git a/packages/core/src/__fixtures__/failed-auth.ts b/packages/toolkit/src/core/__fixtures__/failed-auth.ts
similarity index 100%
rename from packages/core/src/__fixtures__/failed-auth.ts
rename to packages/toolkit/src/core/__fixtures__/failed-auth.ts
diff --git a/packages/core/src/__fixtures__/normal-session.ts b/packages/toolkit/src/core/__fixtures__/normal-session.ts
similarity index 100%
rename from packages/core/src/__fixtures__/normal-session.ts
rename to packages/toolkit/src/core/__fixtures__/normal-session.ts
diff --git a/packages/core/src/detection.test.ts b/packages/toolkit/src/core/detection.test.ts
similarity index 100%
rename from packages/core/src/detection.test.ts
rename to packages/toolkit/src/core/detection.test.ts
diff --git a/packages/core/src/detection.ts b/packages/toolkit/src/core/detection.ts
similarity index 100%
rename from packages/core/src/detection.ts
rename to packages/toolkit/src/core/detection.ts
diff --git a/packages/core/src/fixtures.test.ts b/packages/toolkit/src/core/fixtures.test.ts
similarity index 100%
rename from packages/core/src/fixtures.test.ts
rename to packages/toolkit/src/core/fixtures.test.ts
diff --git a/packages/core/src/fixtures/index.ts b/packages/toolkit/src/core/fixtures/index.ts
similarity index 100%
rename from packages/core/src/fixtures/index.ts
rename to packages/toolkit/src/core/fixtures/index.ts
diff --git a/packages/core/src/index.ts b/packages/toolkit/src/core/index.ts
similarity index 100%
rename from packages/core/src/index.ts
rename to packages/toolkit/src/core/index.ts
diff --git a/packages/core/src/normalizer.test.ts b/packages/toolkit/src/core/normalizer.test.ts
similarity index 100%
rename from packages/core/src/normalizer.test.ts
rename to packages/toolkit/src/core/normalizer.test.ts
diff --git a/packages/core/src/normalizer.ts b/packages/toolkit/src/core/normalizer.ts
similarity index 100%
rename from packages/core/src/normalizer.ts
rename to packages/toolkit/src/core/normalizer.ts
diff --git a/packages/core/src/parser.test.ts b/packages/toolkit/src/core/parser.test.ts
similarity index 100%
rename from packages/core/src/parser.test.ts
rename to packages/toolkit/src/core/parser.test.ts
diff --git a/packages/core/src/parser.ts b/packages/toolkit/src/core/parser.ts
similarity index 100%
rename from packages/core/src/parser.ts
rename to packages/toolkit/src/core/parser.ts
diff --git a/packages/core/src/schemas.ts b/packages/toolkit/src/core/schemas.ts
similarity index 100%
rename from packages/core/src/schemas.ts
rename to packages/toolkit/src/core/schemas.ts
diff --git a/packages/core/src/summarizer.test.ts b/packages/toolkit/src/core/summarizer.test.ts
similarity index 100%
rename from packages/core/src/summarizer.test.ts
rename to packages/toolkit/src/core/summarizer.test.ts
diff --git a/packages/core/src/summarizer.ts b/packages/toolkit/src/core/summarizer.ts
similarity index 100%
rename from packages/core/src/summarizer.ts
rename to packages/toolkit/src/core/summarizer.ts
diff --git a/packages/core/src/timeline.test.ts b/packages/toolkit/src/core/timeline.test.ts
similarity index 100%
rename from packages/core/src/timeline.test.ts
rename to packages/toolkit/src/core/timeline.test.ts
diff --git a/packages/core/src/timeline.ts b/packages/toolkit/src/core/timeline.ts
similarity index 100%
rename from packages/core/src/timeline.ts
rename to packages/toolkit/src/core/timeline.ts
diff --git a/packages/core/src/types.ts b/packages/toolkit/src/core/types.ts
similarity index 100%
rename from packages/core/src/types.ts
rename to packages/toolkit/src/core/types.ts
diff --git a/packages/core/src/validator.test.ts b/packages/toolkit/src/core/validator.test.ts
similarity index 100%
rename from packages/core/src/validator.test.ts
rename to packages/toolkit/src/core/validator.test.ts
diff --git a/packages/core/src/validator.ts b/packages/toolkit/src/core/validator.ts
similarity index 100%
rename from packages/core/src/validator.ts
rename to packages/toolkit/src/core/validator.ts
diff --git a/packages/toolkit/src/index.ts b/packages/toolkit/src/index.ts
new file mode 100644
index 0000000..b7ded7f
--- /dev/null
+++ b/packages/toolkit/src/index.ts
@@ -0,0 +1,74 @@
+/**
+ * @ocpp-debugkit/toolkit — Open-source DevTools for debugging OCPP charging sessions.
+ *
+ * @module @ocpp-debugkit/toolkit
+ *
+ * The root barrel re-exports the most commonly used functions from the
+ * core module. For full modular consumption, use subpath exports:
+ *
+ * import { parseTrace } from '@ocpp-debugkit/toolkit/core';
+ * import { builtInScenarios } from '@ocpp-debugkit/toolkit/scenarios';
+ * import { generateMarkdownReport } from '@ocpp-debugkit/toolkit/reporter';
+ * import { ReplayEngine } from '@ocpp-debugkit/toolkit/replay';
+ * import { SessionTimeline } from '@ocpp-debugkit/toolkit/react';
+ */
+
+// Re-export the most commonly used core functions for convenience
+export {
+ parseTrace,
+ ParseError,
+ MAX_INPUT_SIZE_BYTES,
+ MAX_EVENT_COUNT,
+ type TraceFormat,
+} from './core/index.js';
+
+export {
+ normalizeEvents,
+ normalizeTimestamp,
+ inferDirection,
+ reverseDirection,
+ classifyMessageType,
+ extractAction,
+ extractPayload,
+ extractErrorCode,
+ extractErrorDescription,
+} from './core/index.js';
+
+export { buildSessionTimeline } from './core/index.js';
+export { detectFailures } from './core/index.js';
+export { summarizeSession, summarizeSessions } from './core/index.js';
+export { validateMessage, validateMessages } from './core/index.js';
+
+// Re-export core types and schemas
+export type {
+ Trace,
+ Event,
+ Session,
+ Failure,
+ Scenario,
+ SessionSummary,
+ ValidationResult,
+ RawOcppMessage,
+ Direction,
+ MessageType,
+ FailureSeverity,
+ FailureCode,
+ TraceEventInput,
+ TraceMetadata,
+ ParseWarning,
+ ParseResult,
+} from './core/index.js';
+
+// Re-export schemas
+export {
+ directionSchema,
+ messageTypeSchema,
+ rawOcppMessageSchema,
+ traceEventInputSchema,
+ traceMetadataSchema,
+ traceSchema,
+ bareArraySchema,
+} from './core/index.js';
+
+// Re-export fixtures
+export { fixtures, fixtureNames } from './core/index.js';
diff --git a/packages/toolkit/src/react/components.ts b/packages/toolkit/src/react/components.ts
new file mode 100644
index 0000000..c304aea
--- /dev/null
+++ b/packages/toolkit/src/react/components.ts
@@ -0,0 +1,72 @@
+/**
+ * React component stubs for @ocpp-debugkit/toolkit/react.
+ *
+ * v0.2.0: These are stub implementations — presentational components
+ * that will be fully extracted from the Inspector in Phase 4.
+ * They are functional but minimal, using no external CSS framework.
+ */
+
+import type {
+ SessionTimelineProps,
+ MessageInspectorProps,
+ FailureSummaryProps,
+ ReportViewerProps,
+ ReplayControlsProps,
+} from './types.js';
+
+export function SessionTimeline({ events, selectedEventId, onSelectEvent }: SessionTimelineProps) {
+ return {
+ type: 'SessionTimeline',
+ props: { events, selectedEventId, onSelectEvent },
+ } as const;
+}
+
+export function MessageInspector({ event }: MessageInspectorProps) {
+ return {
+ type: 'MessageInspector',
+ props: { event },
+ } as const;
+}
+
+export function FailureSummary({ failures }: FailureSummaryProps) {
+ return {
+ type: 'FailureSummary',
+ props: { failures },
+ } as const;
+}
+
+export function ReportViewer({ html }: ReportViewerProps) {
+ return {
+ type: 'ReportViewer',
+ props: { html },
+ } as const;
+}
+
+export function ReplayControls({
+ isPlaying,
+ currentIndex,
+ totalEvents,
+ onPlay,
+ onPause,
+ onStep,
+ onStepBack,
+ onJump,
+ speed,
+ onSpeedChange,
+}: ReplayControlsProps) {
+ return {
+ type: 'ReplayControls',
+ props: {
+ isPlaying,
+ currentIndex,
+ totalEvents,
+ onPlay,
+ onPause,
+ onStep,
+ onStepBack,
+ onJump,
+ speed,
+ onSpeedChange,
+ },
+ } as const;
+}
diff --git a/packages/toolkit/src/react/index.ts b/packages/toolkit/src/react/index.ts
new file mode 100644
index 0000000..f508653
--- /dev/null
+++ b/packages/toolkit/src/react/index.ts
@@ -0,0 +1,23 @@
+/**
+ * Reusable React components for OCPP DebugKit.
+ *
+ * @module @ocpp-debugkit/toolkit/react
+ *
+ * These components are presentational — they accept data as props and
+ * render UI. They are SSR-safe (no window/document access at module level).
+ */
+
+export type {
+ SessionTimelineProps,
+ MessageInspectorProps,
+ FailureSummaryProps,
+ ReportViewerProps,
+ ReplayControlsProps,
+} from './types.js';
+export {
+ SessionTimeline,
+ MessageInspector,
+ FailureSummary,
+ ReportViewer,
+ ReplayControls,
+} from './components.js';
diff --git a/packages/toolkit/src/react/types.ts b/packages/toolkit/src/react/types.ts
new file mode 100644
index 0000000..a6c6712
--- /dev/null
+++ b/packages/toolkit/src/react/types.ts
@@ -0,0 +1,40 @@
+/**
+ * Prop types for the React components in @ocpp-debugkit/toolkit/react.
+ */
+
+import type { Event, Failure, SessionSummary } from '../core/index.js';
+
+export interface SessionTimelineProps {
+ events: Event[];
+ selectedEventId?: string | null;
+ onSelectEvent?: (eventId: string) => void;
+}
+
+export interface MessageInspectorProps {
+ event: Event | null;
+}
+
+export interface FailureSummaryProps {
+ failures: Failure[];
+}
+
+export interface ReportViewerProps {
+ /** The HTML report string (from generateHtmlReport). */
+ html: string;
+}
+
+export interface ReplayControlsProps {
+ isPlaying: boolean;
+ currentIndex: number;
+ totalEvents: number;
+ onPlay: () => void;
+ onPause: () => void;
+ onStep: () => void;
+ onStepBack: () => void;
+ onJump: (index: number) => void;
+ speed?: number;
+ onSpeedChange?: (speed: number) => void;
+}
+
+// Summary type re-export for consumers
+export type { SessionSummary };
diff --git a/packages/toolkit/src/replay/engine.ts b/packages/toolkit/src/replay/engine.ts
new file mode 100644
index 0000000..b38ecb7
--- /dev/null
+++ b/packages/toolkit/src/replay/engine.ts
@@ -0,0 +1,125 @@
+/**
+ * Replay engine — replays OCPP trace events in timestamp order.
+ *
+ * @module @ocpp-debugkit/toolkit/replay
+ */
+
+import type { Event, Failure } from '../core/index.js';
+
+// ---------------------------------------------------------------------------
+// Types
+// ---------------------------------------------------------------------------
+
+export interface ReplayEvent {
+ /** The normalized event. */
+ event: Event;
+ /** Failures detected at this event's position. */
+ failures: Failure[];
+ /** Zero-based index in the original event array. */
+ index: number;
+}
+
+export interface ReplayState {
+ /** Events replayed so far. */
+ played: ReplayEvent[];
+ /** Events remaining. */
+ remaining: Event[];
+ /** Whether the replay is complete. */
+ complete: boolean;
+}
+
+export interface ReplayOptions {
+ /** Playback speed multiplier (1 = real-time, 2 = 2x, etc.). Default: 1. */
+ speed?: number;
+ /** Start from this event index. Default: 0. */
+ startIndex?: number;
+}
+
+// ---------------------------------------------------------------------------
+// ReplayEngine
+// ---------------------------------------------------------------------------
+
+/**
+ * Deterministic replay engine for OCPP traces.
+ *
+ * The engine is pure — it does not use timers or I/O. The consumer
+ * calls `step()`, `stepBack()`, or `jumpTo()` to advance the replay.
+ */
+export class ReplayEngine {
+ private readonly events: Event[];
+ private readonly failures: Failure[];
+ private currentIndex: number;
+
+ constructor(events: Event[], failures: Failure[] = [], options?: ReplayOptions) {
+ this.events = [...events];
+ this.failures = [...failures];
+ this.currentIndex = options?.startIndex ?? 0;
+ }
+
+ /** Total number of events. */
+ get totalEvents(): number {
+ return this.events.length;
+ }
+
+ /** Current event index (0-based). Returns -1 if no events. */
+ get current(): number {
+ return this.events.length === 0 ? -1 : this.currentIndex;
+ }
+
+ /** Step forward one event. Returns the replay event, or null if complete. */
+ step(): ReplayEvent | null {
+ if (this.currentIndex >= this.events.length) {
+ return null;
+ }
+ const event = this.events[this.currentIndex];
+ if (!event) {
+ return null;
+ }
+ const index = this.currentIndex;
+ const failures = this.failures.filter((f) => f.eventIds.includes(event.id));
+ this.currentIndex++;
+ return { event, failures, index };
+ }
+
+ /** Step backward one event. Returns the replay event, or null if at start. */
+ stepBack(): ReplayEvent | null {
+ if (this.currentIndex <= 1) {
+ return null;
+ }
+ this.currentIndex -= 2;
+ return this.step();
+ }
+
+ /** Jump to a specific event index. Returns the replay event, or null if out of range. */
+ jumpTo(index: number): ReplayEvent | null {
+ if (index < 0 || index >= this.events.length) {
+ return null;
+ }
+ this.currentIndex = index;
+ return this.step();
+ }
+
+ /** Get the current replay state snapshot. */
+ getState(): ReplayState {
+ const played = [];
+ for (let i = 0; i < this.currentIndex && i < this.events.length; i++) {
+ const event = this.events[i];
+ if (!event) continue;
+ played.push({
+ event,
+ failures: this.failures.filter((f) => f.eventIds.includes(event.id)),
+ index: i,
+ });
+ }
+ return {
+ played,
+ remaining: this.events.slice(this.currentIndex),
+ complete: this.currentIndex >= this.events.length,
+ };
+ }
+
+ /** Reset the replay to the beginning. */
+ reset(): void {
+ this.currentIndex = 0;
+ }
+}
diff --git a/packages/toolkit/src/replay/index.ts b/packages/toolkit/src/replay/index.ts
new file mode 100644
index 0000000..fe68902
--- /dev/null
+++ b/packages/toolkit/src/replay/index.ts
@@ -0,0 +1,11 @@
+/**
+ * Replay engine module — v0.2.0.
+ *
+ * The replay engine takes a parsed trace and replays events in timestamp order,
+ * emitting state transitions and failures. It is pure — no timers, no I/O.
+ * The consumer (app or CLI) drives the clock.
+ *
+ * @module @ocpp-debugkit/toolkit/replay
+ */
+
+export { ReplayEngine, type ReplayEvent, type ReplayState, type ReplayOptions } from './engine.js';
diff --git a/packages/reporter/src/index.ts b/packages/toolkit/src/reporter/index.ts
similarity index 100%
rename from packages/reporter/src/index.ts
rename to packages/toolkit/src/reporter/index.ts
diff --git a/packages/reporter/src/markdown.test.ts b/packages/toolkit/src/reporter/markdown.test.ts
similarity index 99%
rename from packages/reporter/src/markdown.test.ts
rename to packages/toolkit/src/reporter/markdown.test.ts
index ead7c26..c21fb5b 100644
--- a/packages/reporter/src/markdown.test.ts
+++ b/packages/toolkit/src/reporter/markdown.test.ts
@@ -1,7 +1,7 @@
import { describe, it, expect } from 'vitest';
import { generateMarkdownReport } from './markdown.js';
import type { AnalysisResult } from './types.js';
-import type { Event, Failure, Session, SessionSummary, RawOcppMessage } from '@ocpp-debugkit/core';
+import type { Event, Failure, Session, SessionSummary, RawOcppMessage } from '../core/index.js';
// Helpers
function makeEvent(
diff --git a/packages/reporter/src/markdown.ts b/packages/toolkit/src/reporter/markdown.ts
similarity index 99%
rename from packages/reporter/src/markdown.ts
rename to packages/toolkit/src/reporter/markdown.ts
index 0b36085..98c3024 100644
--- a/packages/reporter/src/markdown.ts
+++ b/packages/toolkit/src/reporter/markdown.ts
@@ -11,7 +11,7 @@
*/
import type { AnalysisResult } from './types.js';
-import type { Event } from '@ocpp-debugkit/core';
+import type { Event } from '../core/index.js';
// ---------------------------------------------------------------------------
// Helpers
diff --git a/packages/reporter/src/types.ts b/packages/toolkit/src/reporter/types.ts
similarity index 91%
rename from packages/reporter/src/types.ts
rename to packages/toolkit/src/reporter/types.ts
index 924f28c..771f4e2 100644
--- a/packages/reporter/src/types.ts
+++ b/packages/toolkit/src/reporter/types.ts
@@ -6,7 +6,7 @@
* detectFailures pipeline.
*/
-import type { Event, Failure, Session, SessionSummary } from '@ocpp-debugkit/core';
+import type { Event, Failure, Session, SessionSummary } from '../core/index.js';
/** Analysis result passed to report generators. */
export interface AnalysisResult {
diff --git a/packages/scenarios/src/__scenarios__/station-offline.ts b/packages/toolkit/src/scenarios/__scenarios__/station-offline.ts
similarity index 100%
rename from packages/scenarios/src/__scenarios__/station-offline.ts
rename to packages/toolkit/src/scenarios/__scenarios__/station-offline.ts
diff --git a/packages/scenarios/src/__scenarios__/unexpected-stop-reason.ts b/packages/toolkit/src/scenarios/__scenarios__/unexpected-stop-reason.ts
similarity index 100%
rename from packages/scenarios/src/__scenarios__/unexpected-stop-reason.ts
rename to packages/toolkit/src/scenarios/__scenarios__/unexpected-stop-reason.ts
diff --git a/packages/scenarios/src/index.test.ts b/packages/toolkit/src/scenarios/index.test.ts
similarity index 99%
rename from packages/scenarios/src/index.test.ts
rename to packages/toolkit/src/scenarios/index.test.ts
index 64cd0bb..bb77404 100644
--- a/packages/scenarios/src/index.test.ts
+++ b/packages/toolkit/src/scenarios/index.test.ts
@@ -9,7 +9,7 @@ import {
stationOfflineScenario,
unexpectedStopReasonScenario,
} from './index.js';
-import { parseTrace, buildSessionTimeline, detectFailures } from '@ocpp-debugkit/core';
+import { parseTrace, buildSessionTimeline, detectFailures } from '../core/index.js';
// ---------------------------------------------------------------------------
// Registry tests
diff --git a/packages/scenarios/src/index.ts b/packages/toolkit/src/scenarios/index.ts
similarity index 96%
rename from packages/scenarios/src/index.ts
rename to packages/toolkit/src/scenarios/index.ts
index fa3ba21..7bc1524 100644
--- a/packages/scenarios/src/index.ts
+++ b/packages/toolkit/src/scenarios/index.ts
@@ -5,8 +5,8 @@
* transaction IDs, idTag values, or personal data.
*/
-import type { Scenario, Trace } from '@ocpp-debugkit/core';
-import { fixtures } from '@ocpp-debugkit/core';
+import type { Scenario, Trace } from '../core/index.js';
+import { fixtures } from '../core/index.js';
import stationOffline from './__scenarios__/station-offline.js';
import unexpectedStopReason from './__scenarios__/unexpected-stop-reason.js';
diff --git a/packages/core/tsconfig.json b/packages/toolkit/tsconfig.json
similarity index 78%
rename from packages/core/tsconfig.json
rename to packages/toolkit/tsconfig.json
index dd1cdcb..060f8e5 100644
--- a/packages/core/tsconfig.json
+++ b/packages/toolkit/tsconfig.json
@@ -2,7 +2,8 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist",
- "rootDir": "./src"
+ "rootDir": "./src",
+ "jsx": "react-jsx"
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index cdb97e4..91ad8f9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -38,15 +38,9 @@ importers:
apps/web:
dependencies:
- '@ocpp-debugkit/core':
+ '@ocpp-debugkit/toolkit':
specifier: workspace:*
- version: link:../../packages/core
- '@ocpp-debugkit/reporter':
- specifier: workspace:*
- version: link:../../packages/reporter
- '@ocpp-debugkit/scenarios':
- specifier: workspace:*
- version: link:../../packages/scenarios
+ version: link:../../packages/toolkit
next:
specifier: 16.2.10
version: 16.2.10(@babel/core@7.29.7)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -85,63 +79,33 @@ importers:
specifier: ^5
version: 5.9.3
- packages/cli:
+ packages/toolkit:
dependencies:
- '@ocpp-debugkit/core':
- specifier: workspace:*
- version: link:../core
- '@ocpp-debugkit/reporter':
- specifier: workspace:*
- version: link:../reporter
- '@ocpp-debugkit/scenarios':
- specifier: workspace:*
- version: link:../scenarios
commander:
specifier: ^13.0.0
version: 13.1.0
- devDependencies:
- execa:
- specifier: ^9.0.0
- version: 9.6.1
- typescript:
- specifier: ^5.7.0
- version: 5.9.3
- vitest:
- specifier: ^3.0.0
- version: 3.2.7(@types/node@22.20.0)(jiti@2.7.0)(lightningcss@1.32.0)
-
- packages/core:
- dependencies:
+ react:
+ specifier: ^18.0.0 || ^19.0.0
+ version: 19.2.4
+ react-dom:
+ specifier: ^18.0.0 || ^19.0.0
+ version: 19.2.4(react@19.2.4)
zod:
specifier: ^4.4.3
version: 4.4.3
devDependencies:
- typescript:
- specifier: ^5.7.0
- version: 5.9.3
- vitest:
- specifier: ^3.0.0
- version: 3.2.7(@types/node@22.20.0)(jiti@2.7.0)(lightningcss@1.32.0)
-
- packages/reporter:
- dependencies:
- '@ocpp-debugkit/core':
- specifier: workspace:*
- version: link:../core
- devDependencies:
- typescript:
- specifier: ^5.7.0
- version: 5.9.3
- vitest:
- specifier: ^3.0.0
- version: 3.2.7(@types/node@22.20.0)(jiti@2.7.0)(lightningcss@1.32.0)
-
- packages/scenarios:
- dependencies:
- '@ocpp-debugkit/core':
- specifier: workspace:*
- version: link:../core
- devDependencies:
+ '@types/node':
+ specifier: ^22.0.0
+ version: 22.20.0
+ '@types/react':
+ specifier: ^19
+ version: 19.2.17
+ '@types/react-dom':
+ specifier: ^19
+ version: 19.2.3(@types/react@19.2.17)
+ execa:
+ specifier: ^9.0.0
+ version: 9.6.1
typescript:
specifier: ^5.7.0
version: 5.9.3
@@ -4364,8 +4328,8 @@ snapshots:
'@next/eslint-plugin-next': 16.2.10
eslint: 9.39.4(jiti@2.7.0)
eslint-import-resolver-node: 0.3.10
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0))
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0))
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4(jiti@2.7.0))
eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@2.7.0))
eslint-plugin-react-hooks: 7.1.1(eslint@9.39.4(jiti@2.7.0))
@@ -4387,7 +4351,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0)):
+ eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.3
@@ -4398,22 +4362,22 @@ snapshots:
tinyglobby: 0.2.17
unrs-resolver: 1.12.2
optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0))
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.14.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)):
+ eslint-module-utils@2.14.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)
eslint: 9.39.4(jiti@2.7.0)
eslint-import-resolver-node: 0.3.10
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0))
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0))
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -4424,7 +4388,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.39.4(jiti@2.7.0)
eslint-import-resolver-node: 0.3.10
- eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0))
+ eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.63.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0))
hasown: 2.0.4
is-core-module: 2.16.2
is-glob: 4.0.3