@ocpp-debugkit/toolkit 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +14 -0
  3. package/README.md +35 -0
  4. package/dist/cli/commands/inspect.d.ts +8 -0
  5. package/dist/cli/commands/inspect.d.ts.map +1 -0
  6. package/dist/cli/commands/inspect.js +63 -0
  7. package/dist/cli/commands/inspect.js.map +1 -0
  8. package/dist/cli/commands/report.d.ts +9 -0
  9. package/dist/cli/commands/report.d.ts.map +1 -0
  10. package/dist/cli/commands/report.js +54 -0
  11. package/dist/cli/commands/report.js.map +1 -0
  12. package/dist/cli/commands/scenario.d.ts +10 -0
  13. package/dist/cli/commands/scenario.d.ts.map +1 -0
  14. package/dist/cli/commands/scenario.js +104 -0
  15. package/dist/cli/commands/scenario.js.map +1 -0
  16. package/dist/cli/index.d.ts +7 -0
  17. package/dist/cli/index.d.ts.map +1 -0
  18. package/dist/cli/index.js +47 -0
  19. package/dist/cli/index.js.map +1 -0
  20. package/dist/cli/utils.d.ts +13 -0
  21. package/dist/cli/utils.d.ts.map +1 -0
  22. package/dist/cli/utils.js +43 -0
  23. package/dist/cli/utils.js.map +1 -0
  24. package/dist/core/__fixtures__/connector-fault.d.ts +116 -0
  25. package/dist/core/__fixtures__/connector-fault.d.ts.map +1 -0
  26. package/dist/core/__fixtures__/connector-fault.js +231 -0
  27. package/dist/core/__fixtures__/connector-fault.js.map +1 -0
  28. package/dist/core/__fixtures__/failed-auth.d.ts +64 -0
  29. package/dist/core/__fixtures__/failed-auth.d.ts.map +1 -0
  30. package/dist/core/__fixtures__/failed-auth.js +173 -0
  31. package/dist/core/__fixtures__/failed-auth.js.map +1 -0
  32. package/dist/core/__fixtures__/normal-session.d.ts +108 -0
  33. package/dist/core/__fixtures__/normal-session.d.ts.map +1 -0
  34. package/dist/core/__fixtures__/normal-session.js +261 -0
  35. package/dist/core/__fixtures__/normal-session.js.map +1 -0
  36. package/dist/core/detection.d.ts +23 -0
  37. package/dist/core/detection.d.ts.map +1 -0
  38. package/dist/core/detection.js +226 -0
  39. package/dist/core/detection.js.map +1 -0
  40. package/dist/core/fixtures/index.d.ts +298 -0
  41. package/dist/core/fixtures/index.d.ts.map +1 -0
  42. package/dist/core/fixtures/index.js +19 -0
  43. package/dist/core/fixtures/index.js.map +1 -0
  44. package/dist/core/index.d.ts +14 -0
  45. package/dist/core/index.d.ts.map +1 -0
  46. package/dist/core/index.js +22 -0
  47. package/dist/core/index.js.map +1 -0
  48. package/dist/core/normalizer.d.ts +83 -0
  49. package/dist/core/normalizer.d.ts.map +1 -0
  50. package/dist/core/normalizer.js +289 -0
  51. package/dist/core/normalizer.js.map +1 -0
  52. package/dist/core/parser.d.ts +53 -0
  53. package/dist/core/parser.d.ts.map +1 -0
  54. package/dist/core/parser.js +282 -0
  55. package/dist/core/parser.js.map +1 -0
  56. package/dist/core/schemas.d.ts +68 -0
  57. package/dist/core/schemas.d.ts.map +1 -0
  58. package/dist/core/schemas.js +81 -0
  59. package/dist/core/schemas.js.map +1 -0
  60. package/dist/core/summarizer.d.ts +25 -0
  61. package/dist/core/summarizer.d.ts.map +1 -0
  62. package/dist/core/summarizer.js +47 -0
  63. package/dist/core/summarizer.js.map +1 -0
  64. package/dist/core/timeline.d.ts +26 -0
  65. package/dist/core/timeline.d.ts.map +1 -0
  66. package/dist/core/timeline.js +318 -0
  67. package/dist/core/timeline.js.map +1 -0
  68. package/dist/core/types.d.ts +160 -0
  69. package/dist/core/types.d.ts.map +1 -0
  70. package/dist/core/types.js +9 -0
  71. package/dist/core/types.js.map +1 -0
  72. package/dist/core/validator.d.ts +33 -0
  73. package/dist/core/validator.d.ts.map +1 -0
  74. package/dist/core/validator.js +122 -0
  75. package/dist/core/validator.js.map +1 -0
  76. package/dist/index.d.ts +24 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/index.js +26 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/react/components.d.ts +50 -0
  81. package/dist/react/components.d.ts.map +1 -0
  82. package/dist/react/components.js +49 -0
  83. package/dist/react/components.js.map +1 -0
  84. package/dist/react/index.d.ts +11 -0
  85. package/dist/react/index.d.ts.map +1 -0
  86. package/dist/react/index.js +10 -0
  87. package/dist/react/index.js.map +1 -0
  88. package/dist/react/types.d.ts +33 -0
  89. package/dist/react/types.d.ts.map +1 -0
  90. package/dist/react/types.js +5 -0
  91. package/dist/react/types.js.map +1 -0
  92. package/dist/replay/engine.d.ts +55 -0
  93. package/dist/replay/engine.d.ts.map +1 -0
  94. package/dist/replay/engine.js +86 -0
  95. package/dist/replay/engine.js.map +1 -0
  96. package/dist/replay/index.d.ts +11 -0
  97. package/dist/replay/index.d.ts.map +1 -0
  98. package/dist/replay/index.js +11 -0
  99. package/dist/replay/index.js.map +1 -0
  100. package/dist/reporter/index.d.ts +6 -0
  101. package/dist/reporter/index.d.ts.map +1 -0
  102. package/dist/reporter/index.js +5 -0
  103. package/dist/reporter/index.js.map +1 -0
  104. package/dist/reporter/markdown.d.ts +20 -0
  105. package/dist/reporter/markdown.d.ts.map +1 -0
  106. package/dist/reporter/markdown.js +181 -0
  107. package/dist/reporter/markdown.js.map +1 -0
  108. package/dist/reporter/types.d.ts +34 -0
  109. package/dist/reporter/types.d.ts.map +1 -0
  110. package/dist/reporter/types.js +9 -0
  111. package/dist/reporter/types.js.map +1 -0
  112. package/dist/scenarios/__scenarios__/station-offline.d.ts +94 -0
  113. package/dist/scenarios/__scenarios__/station-offline.d.ts.map +1 -0
  114. package/dist/scenarios/__scenarios__/station-offline.js +168 -0
  115. package/dist/scenarios/__scenarios__/station-offline.js.map +1 -0
  116. package/dist/scenarios/__scenarios__/unexpected-stop-reason.d.ts +112 -0
  117. package/dist/scenarios/__scenarios__/unexpected-stop-reason.d.ts.map +1 -0
  118. package/dist/scenarios/__scenarios__/unexpected-stop-reason.js +216 -0
  119. package/dist/scenarios/__scenarios__/unexpected-stop-reason.js.map +1 -0
  120. package/dist/scenarios/index.d.ts +21 -0
  121. package/dist/scenarios/index.d.ts.map +1 -0
  122. package/dist/scenarios/index.js +61 -0
  123. package/dist/scenarios/index.js.map +1 -0
  124. package/package.json +110 -0
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Zod schemas for OCPP DebugKit trace input validation.
3
+ *
4
+ * These schemas validate untrusted input at the boundary (ADR-0007).
5
+ * They prevent prototype pollution and ensure structural correctness
6
+ * before any processing occurs.
7
+ *
8
+ * @see docs/trace-format-spec.md
9
+ * @see ADR-0002 (input trace formats)
10
+ * @see ADR-0003 (canonical event model)
11
+ * @see ADR-0007 (malformed trace handling)
12
+ */
13
+ import { z } from 'zod';
14
+ export declare const directionSchema: z.ZodEnum<{
15
+ CS_TO_CSMS: "CS_TO_CSMS";
16
+ CSMS_TO_CS: "CSMS_TO_CS";
17
+ UNKNOWN: "UNKNOWN";
18
+ }>;
19
+ export declare const messageTypeSchema: z.ZodEnum<{
20
+ Call: "Call";
21
+ CallResult: "CallResult";
22
+ CallError: "CallError";
23
+ }>;
24
+ /**
25
+ * Raw OCPP 1.6 JSON message array.
26
+ * - Call (2): [2, UniqueId, Action, Payload]
27
+ * - CallResult (3): [3, UniqueId, Payload]
28
+ * - CallError (4): [4, UniqueId, ErrorCode, ErrorDescription, ErrorDetails]
29
+ *
30
+ * We validate the first two elements strictly (MessageTypeId + UniqueId)
31
+ * and accept arbitrary payload data.
32
+ */
33
+ export declare const rawOcppMessageSchema: z.ZodTuple<[z.ZodNumber, z.ZodString], z.ZodUnknown>;
34
+ export declare const traceEventInputSchema: z.ZodObject<{
35
+ timestamp: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
36
+ direction: z.ZodOptional<z.ZodEnum<{
37
+ CS_TO_CSMS: "CS_TO_CSMS";
38
+ CSMS_TO_CS: "CSMS_TO_CS";
39
+ UNKNOWN: "UNKNOWN";
40
+ }>>;
41
+ message: z.ZodTuple<[z.ZodNumber, z.ZodString], z.ZodUnknown>;
42
+ }, z.core.$strip>;
43
+ export declare const traceMetadataSchema: z.ZodObject<{
44
+ stationId: z.ZodOptional<z.ZodString>;
45
+ ocppVersion: z.ZodOptional<z.ZodString>;
46
+ source: z.ZodOptional<z.ZodString>;
47
+ description: z.ZodOptional<z.ZodString>;
48
+ }, z.core.$strip>;
49
+ export declare const traceSchema: z.ZodObject<{
50
+ traceId: z.ZodOptional<z.ZodString>;
51
+ metadata: z.ZodOptional<z.ZodObject<{
52
+ stationId: z.ZodOptional<z.ZodString>;
53
+ ocppVersion: z.ZodOptional<z.ZodString>;
54
+ source: z.ZodOptional<z.ZodString>;
55
+ description: z.ZodOptional<z.ZodString>;
56
+ }, z.core.$strip>>;
57
+ events: z.ZodArray<z.ZodObject<{
58
+ timestamp: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
59
+ direction: z.ZodOptional<z.ZodEnum<{
60
+ CS_TO_CSMS: "CS_TO_CSMS";
61
+ CSMS_TO_CS: "CSMS_TO_CS";
62
+ UNKNOWN: "UNKNOWN";
63
+ }>>;
64
+ message: z.ZodTuple<[z.ZodNumber, z.ZodString], z.ZodUnknown>;
65
+ }, z.core.$strip>>;
66
+ }, z.core.$strip>;
67
+ export declare const bareArraySchema: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodString], z.ZodUnknown>>;
68
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/core/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,eAAe;;;;EAAkD,CAAC;AAE/E,eAAO,MAAM,iBAAiB;;;;EAA8C,CAAC;AAE7E;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,sDAwB7B,CAAC;AAML,eAAO,MAAM,qBAAqB;;;;;;;;iBAIhC,CAAC;AAMH,eAAO,MAAM,mBAAmB;;;;;iBAK9B,CAAC;AAMH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;iBAItB,CAAC;AAMH,eAAO,MAAM,eAAe,kEAAuC,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Zod schemas for OCPP DebugKit trace input validation.
3
+ *
4
+ * These schemas validate untrusted input at the boundary (ADR-0007).
5
+ * They prevent prototype pollution and ensure structural correctness
6
+ * before any processing occurs.
7
+ *
8
+ * @see docs/trace-format-spec.md
9
+ * @see ADR-0002 (input trace formats)
10
+ * @see ADR-0003 (canonical event model)
11
+ * @see ADR-0007 (malformed trace handling)
12
+ */
13
+ import { z } from 'zod';
14
+ // ---------------------------------------------------------------------------
15
+ // Primitives
16
+ // ---------------------------------------------------------------------------
17
+ export const directionSchema = z.enum(['CS_TO_CSMS', 'CSMS_TO_CS', 'UNKNOWN']);
18
+ export const messageTypeSchema = z.enum(['Call', 'CallResult', 'CallError']);
19
+ /**
20
+ * Raw OCPP 1.6 JSON message array.
21
+ * - Call (2): [2, UniqueId, Action, Payload]
22
+ * - CallResult (3): [3, UniqueId, Payload]
23
+ * - CallError (4): [4, UniqueId, ErrorCode, ErrorDescription, ErrorDetails]
24
+ *
25
+ * We validate the first two elements strictly (MessageTypeId + UniqueId)
26
+ * and accept arbitrary payload data.
27
+ */
28
+ export const rawOcppMessageSchema = z
29
+ .tuple([z.number(), z.string()])
30
+ .rest(z.unknown())
31
+ .refine((msg) => msg[0] === 2 || msg[0] === 3 || msg[0] === 4, {
32
+ message: 'MessageTypeId must be 2 (Call), 3 (CallResult), or 4 (CallError)',
33
+ })
34
+ .refine((msg) => (msg[0] === 2 ? msg.length >= 4 : true), {
35
+ message: 'Call message must have at least 4 elements: [2, UniqueId, Action, Payload]',
36
+ })
37
+ .refine((msg) => (msg[0] === 3 ? msg.length >= 3 : true), {
38
+ message: 'CallResult message must have at least 3 elements: [3, UniqueId, Payload]',
39
+ })
40
+ .refine((msg) => (msg[0] === 4 ? msg.length >= 5 : true), {
41
+ message: 'CallError message must have at least 5 elements: [4, UniqueId, ErrorCode, ErrorDescription, ErrorDetails]',
42
+ })
43
+ .refine((msg) => (msg[0] === 2 ? typeof msg[2] === 'string' : true), {
44
+ message: 'Call message Action (index 2) must be a string',
45
+ })
46
+ .refine((msg) => (msg[0] === 4 ? typeof msg[2] === 'string' : true), {
47
+ message: 'CallError ErrorCode (index 2) must be a string',
48
+ })
49
+ .refine((msg) => (msg[0] === 4 ? typeof msg[3] === 'string' : true), {
50
+ message: 'CallError ErrorDescription (index 3) must be a string',
51
+ });
52
+ // ---------------------------------------------------------------------------
53
+ // Trace Event Input (ADR-0002, ADR-0003)
54
+ // ---------------------------------------------------------------------------
55
+ export const traceEventInputSchema = z.object({
56
+ timestamp: z.union([z.string(), z.number()]).nullable().optional(),
57
+ direction: directionSchema.optional(),
58
+ message: rawOcppMessageSchema,
59
+ });
60
+ // ---------------------------------------------------------------------------
61
+ // Trace Metadata (ADR-0002)
62
+ // ---------------------------------------------------------------------------
63
+ export const traceMetadataSchema = z.object({
64
+ stationId: z.string().optional(),
65
+ ocppVersion: z.string().optional(),
66
+ source: z.string().optional(),
67
+ description: z.string().optional(),
68
+ });
69
+ // ---------------------------------------------------------------------------
70
+ // JSON Object Trace Format (ADR-0002)
71
+ // ---------------------------------------------------------------------------
72
+ export const traceSchema = z.object({
73
+ traceId: z.string().optional(),
74
+ metadata: traceMetadataSchema.optional(),
75
+ events: z.array(traceEventInputSchema).min(1, { message: 'events array must not be empty' }),
76
+ });
77
+ // ---------------------------------------------------------------------------
78
+ // Bare Array Format (degenerate — array of raw OCPP messages)
79
+ // ---------------------------------------------------------------------------
80
+ export const bareArraySchema = z.array(rawOcppMessageSchema).min(1);
81
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/core/schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Session summarizer — produces overview statistics for a charging session.
3
+ *
4
+ * @see ADR-0003
5
+ */
6
+ import type { Session, SessionSummary } from './types.js';
7
+ /**
8
+ * Summarize a charging session with overview statistics.
9
+ *
10
+ * @param session - The session to summarize
11
+ * @param failureCount - Number of failures detected in this session
12
+ * @returns Summary statistics
13
+ */
14
+ export declare function summarizeSession(session: Session, failureCount?: number): SessionSummary;
15
+ /**
16
+ * Summarize all sessions in a trace.
17
+ *
18
+ * @param sessions - All sessions in the trace
19
+ * @param failures - All detected failures
20
+ * @returns Array of session summaries
21
+ */
22
+ export declare function summarizeSessions(sessions: Session[], failures: {
23
+ eventIds: string[];
24
+ }[]): SessionSummary[];
25
+ //# sourceMappingURL=summarizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarizer.d.ts","sourceRoot":"","sources":["../../src/core/summarizer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,SAAI,GAAG,cAAc,CAqBnF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,OAAO,EAAE,EACnB,QAAQ,EAAE;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,GACjC,cAAc,EAAE,CAUlB"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Session summarizer — produces overview statistics for a charging session.
3
+ *
4
+ * @see ADR-0003
5
+ */
6
+ /**
7
+ * Summarize a charging session with overview statistics.
8
+ *
9
+ * @param session - The session to summarize
10
+ * @param failureCount - Number of failures detected in this session
11
+ * @returns Summary statistics
12
+ */
13
+ export function summarizeSession(session, failureCount = 0) {
14
+ const actionSequence = session.events
15
+ .filter((e) => e.messageType === 'Call' && e.action !== null)
16
+ .map((e) => e.action);
17
+ const durationMs = session.startTime !== null && session.endTime !== null
18
+ ? session.endTime - session.startTime
19
+ : null;
20
+ return {
21
+ sessionId: session.sessionId,
22
+ stationId: session.stationId,
23
+ connectorId: session.connectorId,
24
+ transactionId: session.transactionId,
25
+ status: session.status,
26
+ eventCount: session.events.length,
27
+ durationMs,
28
+ failureCount,
29
+ actionSequence,
30
+ };
31
+ }
32
+ /**
33
+ * Summarize all sessions in a trace.
34
+ *
35
+ * @param sessions - All sessions in the trace
36
+ * @param failures - All detected failures
37
+ * @returns Array of session summaries
38
+ */
39
+ export function summarizeSessions(sessions, failures) {
40
+ return sessions.map((session) => {
41
+ // Count failures that belong to this session
42
+ const sessionEventIds = new Set(session.events.map((e) => e.id));
43
+ const failureCount = failures.filter((f) => f.eventIds.some((id) => sessionEventIds.has(id))).length;
44
+ return summarizeSession(session, failureCount);
45
+ });
46
+ }
47
+ //# sourceMappingURL=summarizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../../src/core/summarizer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB,EAAE,YAAY,GAAG,CAAC;IACjE,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM;SAClC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC;SAC5D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAgB,CAAC,CAAC;IAElC,MAAM,UAAU,GACd,OAAO,CAAC,SAAS,KAAK,IAAI,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI;QACpD,CAAC,CAAC,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,SAAS;QACrC,CAAC,CAAC,IAAI,CAAC;IAEX,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM;QACjC,UAAU;QACV,YAAY;QACZ,cAAc;KACf,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAmB,EACnB,QAAkC;IAElC,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,6CAA6C;QAC7C,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACjE,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACzC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CACjD,CAAC,MAAM,CAAC;QAET,OAAO,gBAAgB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Session timeline builder — correlates events into logical charging sessions.
3
+ *
4
+ * Session correlation strategy (ADR-0006):
5
+ * 1. Primary: transactionId (from StartTransaction response / StopTransaction)
6
+ * 2. Secondary: connectorId + stationId grouping
7
+ * 3. Events without a transaction are grouped by stationId + connectorId
8
+ *
9
+ * @see ADR-0006
10
+ */
11
+ import type { Event, Session } from './types.js';
12
+ /**
13
+ * Build session timelines from normalized events.
14
+ *
15
+ * Correlates events into logical charging sessions by:
16
+ * 1. Matching StartTransaction responses to find transactionIds
17
+ * 2. Grouping StopTransaction and MeterValues events by transactionId
18
+ * 3. Grouping StatusNotification events by connectorId + stationId
19
+ * 4. Events without a transaction are assigned to a "no-session" group
20
+ *
21
+ * Sessions are ordered by their first event's timestamp.
22
+ *
23
+ * @see ADR-0006
24
+ */
25
+ export declare function buildSessionTimeline(events: Event[]): Session[];
26
+ //# sourceMappingURL=timeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../../src/core/timeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AA4FjD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAgN/D"}
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Session timeline builder — correlates events into logical charging sessions.
3
+ *
4
+ * Session correlation strategy (ADR-0006):
5
+ * 1. Primary: transactionId (from StartTransaction response / StopTransaction)
6
+ * 2. Secondary: connectorId + stationId grouping
7
+ * 3. Events without a transaction are grouped by stationId + connectorId
8
+ *
9
+ * @see ADR-0006
10
+ */
11
+ // ---------------------------------------------------------------------------
12
+ // Helpers
13
+ // ---------------------------------------------------------------------------
14
+ /**
15
+ * Extract transactionId from an event's payload.
16
+ * - StartTransaction response (CallResult): { transactionId, idTagInfo }
17
+ * - StopTransaction request (Call): { transactionId, ... }
18
+ * - MeterValues request (Call): { transactionId, ... }
19
+ */
20
+ function extractTransactionId(event) {
21
+ if (event.messageType === 'Call') {
22
+ if (event.action === 'StartTransaction') {
23
+ // StartTransaction request doesn't have transactionId — the response does.
24
+ return null;
25
+ }
26
+ if (event.action === 'StopTransaction' || event.action === 'MeterValues') {
27
+ const payload = event.payload;
28
+ if (typeof payload?.transactionId === 'number') {
29
+ return payload.transactionId;
30
+ }
31
+ }
32
+ }
33
+ if (event.messageType === 'CallResult') {
34
+ const payload = event.payload;
35
+ if (typeof payload?.transactionId === 'number') {
36
+ return payload.transactionId;
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+ /**
42
+ * Extract connectorId from an event's payload.
43
+ * Present in StatusNotification, StartTransaction, MeterValues.
44
+ */
45
+ function extractConnectorId(event) {
46
+ if (event.messageType !== 'Call' || event.payload === null) {
47
+ return null;
48
+ }
49
+ const payload = event.payload;
50
+ if (typeof payload?.connectorId === 'number') {
51
+ return payload.connectorId;
52
+ }
53
+ return null;
54
+ }
55
+ /**
56
+ * Extract stationId from BootNotification payload.
57
+ */
58
+ function extractStationId(events) {
59
+ for (const event of events) {
60
+ if (event.messageType === 'Call' && event.action === 'BootNotification') {
61
+ const payload = event.payload;
62
+ if (typeof payload?.chargePointSerialNumber === 'string') {
63
+ return payload.chargePointSerialNumber;
64
+ }
65
+ }
66
+ }
67
+ return 'unknown';
68
+ }
69
+ /**
70
+ * Determine if an event indicates a connector fault status.
71
+ */
72
+ function isFaultedStatus(event) {
73
+ if (event.messageType !== 'Call' || event.action !== 'StatusNotification') {
74
+ return false;
75
+ }
76
+ const payload = event.payload;
77
+ return payload?.status === 'Faulted';
78
+ }
79
+ /**
80
+ * Determine if an event indicates the connector is unavailable/offline.
81
+ */
82
+ function isUnavailableStatus(event) {
83
+ if (event.messageType !== 'Call' || event.action !== 'StatusNotification') {
84
+ return false;
85
+ }
86
+ const payload = event.payload;
87
+ return payload?.status === 'Unavailable' || payload?.status === 'Offline';
88
+ }
89
+ // ---------------------------------------------------------------------------
90
+ // buildSessionTimeline()
91
+ // ---------------------------------------------------------------------------
92
+ /**
93
+ * Build session timelines from normalized events.
94
+ *
95
+ * Correlates events into logical charging sessions by:
96
+ * 1. Matching StartTransaction responses to find transactionIds
97
+ * 2. Grouping StopTransaction and MeterValues events by transactionId
98
+ * 3. Grouping StatusNotification events by connectorId + stationId
99
+ * 4. Events without a transaction are assigned to a "no-session" group
100
+ *
101
+ * Sessions are ordered by their first event's timestamp.
102
+ *
103
+ * @see ADR-0006
104
+ */
105
+ export function buildSessionTimeline(events) {
106
+ if (events.length === 0) {
107
+ return [];
108
+ }
109
+ const stationId = extractStationId(events);
110
+ // Step 1: Build a map of messageId → transactionId from StartTransaction responses.
111
+ // The StartTransaction Call (msg-005) gets a response (CallResult) with transactionId.
112
+ // We match by messageId.
113
+ const messageIdToTransactionId = new Map();
114
+ for (const event of events) {
115
+ if (event.messageType === 'CallResult') {
116
+ const txId = extractTransactionId(event);
117
+ if (txId !== null) {
118
+ messageIdToTransactionId.set(event.messageId, txId);
119
+ }
120
+ }
121
+ }
122
+ // Step 2: Build a map of messageId → transactionId for StopTransaction/MeterValues Calls.
123
+ // These Calls contain the transactionId in their payload directly.
124
+ const callMessageIdToTransactionId = new Map();
125
+ for (const event of events) {
126
+ if (event.messageType === 'Call') {
127
+ const txId = extractTransactionId(event);
128
+ if (txId !== null) {
129
+ callMessageIdToTransactionId.set(event.messageId, txId);
130
+ }
131
+ }
132
+ }
133
+ // Step 3: Group events into sessions.
134
+ // A session is identified by a transactionId.
135
+ // Events are assigned to a session if:
136
+ // - They contain that transactionId in their payload (StopTransaction, MeterValues)
137
+ // - They are a StartTransaction Call/CallResult with a matched messageId
138
+ // - They are StatusNotification events for the same connectorId around the same time
139
+ // First, find all StartTransaction Call messages and their corresponding response transactionIds
140
+ const startTxCalls = [];
141
+ for (const event of events) {
142
+ if (event.messageType === 'Call' && event.action === 'StartTransaction') {
143
+ const txId = messageIdToTransactionId.get(event.messageId) ?? null;
144
+ const responseEvent = events.find((e) => e.messageId === event.messageId && e.messageType === 'CallResult') ??
145
+ null;
146
+ startTxCalls.push({ callEvent: event, responseEvent, transactionId: txId });
147
+ }
148
+ }
149
+ // If no transactions found, return a single session with all events
150
+ if (startTxCalls.length === 0) {
151
+ return [createSession('session-0', stationId, events)];
152
+ }
153
+ // Build a map of messageId → transactionId for ALL Call messages that have
154
+ // a transactionId (StopTransaction, MeterValues). Their CallResult responses
155
+ // inherit this transactionId.
156
+ const callMessageIdToTxId = new Map();
157
+ for (const event of events) {
158
+ if (event.messageType === 'Call') {
159
+ const txId = extractTransactionId(event);
160
+ if (txId !== null) {
161
+ callMessageIdToTxId.set(event.messageId, txId);
162
+ }
163
+ // StartTransaction Call — get txId from the response
164
+ if (event.action === 'StartTransaction') {
165
+ const respTxId = messageIdToTransactionId.get(event.messageId);
166
+ if (respTxId !== undefined) {
167
+ callMessageIdToTxId.set(event.messageId, respTxId);
168
+ }
169
+ }
170
+ }
171
+ }
172
+ // Group events by transactionId
173
+ const sessionEventsMap = new Map();
174
+ for (const event of events) {
175
+ let txId = null;
176
+ if (event.messageType === 'Call') {
177
+ // Call: check if this messageId has a known transactionId
178
+ txId = callMessageIdToTxId.get(event.messageId) ?? null;
179
+ if (txId === null) {
180
+ // Try extracting from payload directly
181
+ txId = extractTransactionId(event);
182
+ }
183
+ }
184
+ else if (event.messageType === 'CallResult') {
185
+ // CallResult: check if the matching Call has a transactionId
186
+ txId = callMessageIdToTxId.get(event.messageId) ?? null;
187
+ // Also check if transactionId is directly in the response payload
188
+ if (txId === null) {
189
+ txId = extractTransactionId(event);
190
+ }
191
+ }
192
+ if (txId !== null) {
193
+ const group = sessionEventsMap.get(txId) ?? [];
194
+ group.push(event);
195
+ sessionEventsMap.set(txId, group);
196
+ }
197
+ else {
198
+ // Events without a transaction — assign to null group (will be distributed)
199
+ const group = sessionEventsMap.get(null) ?? [];
200
+ group.push(event);
201
+ sessionEventsMap.set(null, group);
202
+ }
203
+ }
204
+ // Distribute null-group events to sessions by connectorId and time proximity
205
+ const nullEvents = sessionEventsMap.get(null) ?? [];
206
+ sessionEventsMap.delete(null);
207
+ const usedNullEventIds = new Set();
208
+ // Build sessions
209
+ const sessions = [];
210
+ let sessionIndex = 0;
211
+ for (const [txId, txEvents] of sessionEventsMap) {
212
+ // Find connectorId from the StartTransaction Call
213
+ const startTxCall = txEvents.find((e) => e.messageType === 'Call' && e.action === 'StartTransaction');
214
+ const connectorId = startTxCall ? extractConnectorId(startTxCall) : null;
215
+ // Include null-group events that belong to this session's connector
216
+ // and time range, or that are responses to Calls already in the session.
217
+ const txMessageIds = new Set(txEvents.map((e) => e.messageId));
218
+ const sessionStart = txEvents[0]?.timestamp ?? null;
219
+ const sessionEnd = txEvents[txEvents.length - 1]?.timestamp ?? null;
220
+ const relatedNullEvents = nullEvents.filter((e) => {
221
+ // Skip already-used events
222
+ if (usedNullEventIds.has(e.id))
223
+ return false;
224
+ // Include CallResult/CallError that match a Call already in the session
225
+ if (e.messageType !== 'Call' && txMessageIds.has(e.messageId)) {
226
+ return true;
227
+ }
228
+ const eventConnectorId = extractConnectorId(e);
229
+ // Include events with matching connectorId within time range
230
+ if (eventConnectorId !== null && connectorId !== null && eventConnectorId === connectorId) {
231
+ if (sessionStart !== null && sessionEnd !== null && e.timestamp !== null) {
232
+ return e.timestamp >= sessionStart && e.timestamp <= sessionEnd + 60000; // 1 min grace
233
+ }
234
+ return true; // No timestamps — include
235
+ }
236
+ // Include BootNotification events at the start
237
+ if (e.action === 'BootNotification' || e.action === 'Heartbeat') {
238
+ // Only include if this is the first session
239
+ return sessionIndex === 0;
240
+ }
241
+ // Include events without connectorId (like Authorize) within time range
242
+ // (extending before session start to include pre-session events like Authorize)
243
+ if (eventConnectorId === null &&
244
+ e.messageType === 'Call' &&
245
+ e.action !== 'BootNotification' &&
246
+ e.action !== 'Heartbeat') {
247
+ if (sessionStart !== null && sessionEnd !== null && e.timestamp !== null) {
248
+ // Include if within 5 minutes before session start through 1 min after end
249
+ return e.timestamp >= sessionStart - 300000 && e.timestamp <= sessionEnd + 60000;
250
+ }
251
+ }
252
+ return false;
253
+ });
254
+ // Mark these null events as used so they aren't included in other sessions
255
+ for (const e of relatedNullEvents) {
256
+ usedNullEventIds.add(e.id);
257
+ }
258
+ const allEvents = [...txEvents, ...relatedNullEvents].sort((a, b) => {
259
+ // Sort by original event order (ID is sequential)
260
+ return a.id.localeCompare(b.id);
261
+ });
262
+ sessions.push(createSession(`session-${sessionIndex}`, stationId, allEvents, connectorId, txId));
263
+ sessionIndex++;
264
+ }
265
+ // Sort sessions by start time
266
+ sessions.sort((a, b) => {
267
+ if (a.startTime === null)
268
+ return 1;
269
+ if (b.startTime === null)
270
+ return -1;
271
+ return a.startTime - b.startTime;
272
+ });
273
+ // Renumber sessions
274
+ sessions.forEach((s, i) => {
275
+ s.sessionId = `session-${i}`;
276
+ });
277
+ return sessions;
278
+ }
279
+ // ---------------------------------------------------------------------------
280
+ // createSession helper
281
+ // ---------------------------------------------------------------------------
282
+ function createSession(sessionId, stationId, events, connectorId = null, transactionId = null) {
283
+ const timestamps = events.map((e) => e.timestamp).filter((t) => t !== null);
284
+ const startTime = timestamps.length > 0 ? Math.min(...timestamps) : null;
285
+ const endTime = timestamps.length > 0 ? Math.max(...timestamps) : null;
286
+ // Determine session status
287
+ let status = 'active';
288
+ const hasStop = events.some((e) => e.messageType === 'Call' && e.action === 'StopTransaction');
289
+ const hasFaulted = events.some(isFaultedStatus);
290
+ const hasUnavailable = events.some(isUnavailableStatus);
291
+ if (hasStop) {
292
+ status = 'completed';
293
+ }
294
+ else if (hasFaulted || hasUnavailable) {
295
+ status = 'aborted';
296
+ }
297
+ // If we didn't get a transactionId from parameter, try to extract it
298
+ if (transactionId === null) {
299
+ for (const event of events) {
300
+ const txId = extractTransactionId(event);
301
+ if (txId !== null) {
302
+ transactionId = txId;
303
+ break;
304
+ }
305
+ }
306
+ }
307
+ return {
308
+ sessionId,
309
+ stationId,
310
+ connectorId,
311
+ transactionId,
312
+ startTime,
313
+ endTime,
314
+ events,
315
+ status,
316
+ };
317
+ }
318
+ //# sourceMappingURL=timeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/core/timeline.ts"],"names":[],"mappings":"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"}