@springfield/ham-radio-utils 3.2.6 → 4.0.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.
@@ -6,20 +6,6 @@ import type { ILogLayer } from 'loglayer';
6
6
  * This module provides a specialized logger for capturing command-level information
7
7
  * that can be easily parsed and displayed in a UI. It captures details about
8
8
  * commands, data sent, data expected, and data received in a structured format.
9
- *
10
- * Purpose:
11
- * - Captures command-level information for UI display
12
- * - Provides structured JSON logging for easy parsing
13
- * - Tracks command execution details including timing
14
- * - Supports protocol debugging in UI environments
15
- * - Maintains separation from debug logging
16
- *
17
- * Design Rationale:
18
- * - Single log entry per command provides clean UI display
19
- * - JSON structure enables easy parsing and filtering
20
- * - Command-level granularity is appropriate for UI debugging
21
- * - Structured data supports rich UI representations
22
- * - Separate from debug logging avoids UI noise
23
9
  */
24
10
 
25
11
  interface ProtocolContext {
@@ -31,30 +17,9 @@ interface ProtocolContext {
31
17
  */
32
18
  export type UIProtocolStep = Record<string, unknown>;
33
19
 
34
- /**
35
- * Type guards for protocol step properties
36
- */
37
20
  const hasDescription = (obj: unknown): obj is { description: string } =>
38
21
  typeof obj === 'object' && obj !== null && 'description' in obj && typeof (obj as Record<string, unknown>).description === 'string';
39
22
 
40
- const hasReceive = (obj: unknown): obj is { receive: unknown } => typeof obj === 'object' && obj !== null && 'receive' in obj;
41
-
42
- const hasEndChunk = (obj: unknown): obj is { endChunk: { receive: unknown } } =>
43
- typeof obj === 'object' &&
44
- obj !== null &&
45
- 'endChunk' in obj &&
46
- typeof (obj as Record<string, unknown>).endChunk === 'object' &&
47
- (obj as Record<string, unknown>).endChunk !== null &&
48
- 'receive' in ((obj as Record<string, unknown>).endChunk as Record<string, unknown>);
49
-
50
- const hasStartChunk = (obj: unknown): obj is { startChunk: { receive: unknown } } =>
51
- typeof obj === 'object' &&
52
- obj !== null &&
53
- 'startChunk' in obj &&
54
- typeof (obj as Record<string, unknown>).startChunk === 'object' &&
55
- (obj as Record<string, unknown>).startChunk !== null &&
56
- 'receive' in ((obj as Record<string, unknown>).startChunk as Record<string, unknown>);
57
-
58
23
  /**
59
24
  * UI Logger for capturing command-level information for UI display
60
25
  */
@@ -98,15 +63,11 @@ export class UILogger {
98
63
  const commandType = this.getCommandType(step);
99
64
  const description = this.getStepDescription(step);
100
65
 
101
- // Extract sent and received data from context
102
66
  const dataSent = context.variables && context.variables.get('lastSentData');
103
67
  const dataReceived = context.variables && context.variables.get('lastReceivedData');
104
68
  const dataExpected = this.getExpectedData(step);
69
+ const dataChunks = commandType === 'read' && context.variables && context.variables.get('lastReadSegmentChunks');
105
70
 
106
- // For readSegment, also extract chunk logs if present
107
- const dataChunks = commandType === 'readSegment' && context.variables && context.variables.get('lastReadSegmentChunks');
108
-
109
- // Convert dataSent and dataReceived to byte array format if they exist
110
71
  // eslint-disable-next-line unicorn/prefer-spread
111
72
  const dataSentArray = dataSent && Array.from(dataSent as Uint8Array);
112
73
  // eslint-disable-next-line unicorn/prefer-spread
@@ -141,11 +102,9 @@ export class UILogger {
141
102
  const commandType = this.getCommandType(step);
142
103
  const description = this.getStepDescription(step);
143
104
 
144
- // Extract sent data from context
145
105
  const dataSent = context.variables && context.variables.get('lastSentData');
146
106
  const dataExpected = this.getExpectedData(step);
147
107
 
148
- // Convert dataSent to byte array format if it exists
149
108
  // eslint-disable-next-line unicorn/prefer-spread
150
109
  const dataSentArray = dataSent && Array.from(dataSent as Uint8Array);
151
110
 
@@ -168,63 +127,38 @@ export class UILogger {
168
127
  }
169
128
 
170
129
  private getCommandType(step: UIProtocolStep): string {
171
- if ('sendReceive' in step) {
172
- return 'sendReceive';
130
+ if ('read' in step) {
131
+ return 'read';
173
132
  }
174
- if ('send' in step) {
175
- return 'send';
133
+ if ('write' in step) {
134
+ return 'write';
176
135
  }
177
- if ('receive' in step) {
178
- return 'receive';
179
- }
180
- if ('readSegment' in step) {
181
- return 'readSegment';
182
- }
183
- if ('writeSegment' in step) {
184
- return 'writeSegment';
185
- }
186
- if ('setVariable' in step) {
187
- return 'setVariable';
136
+ if ('send' in step || 'expect' in step) {
137
+ return 'exchange';
188
138
  }
189
139
  return 'unknown';
190
140
  }
191
141
 
192
142
  private getStepDescription(step: UIProtocolStep): string {
193
- if ('sendReceive' in step && hasDescription(step.sendReceive)) {
194
- return step.sendReceive.description;
195
- }
196
- if ('send' in step && hasDescription(step.send)) {
197
- return step.send.description;
198
- }
199
- if ('receive' in step && hasDescription(step.receive)) {
200
- return step.receive.description;
201
- }
202
- if ('readSegment' in step && hasDescription(step.readSegment)) {
203
- return step.readSegment.description;
204
- }
205
- if ('writeSegment' in step && hasDescription(step.writeSegment)) {
206
- return step.writeSegment.description;
143
+ if (hasDescription(step)) {
144
+ return step.description;
207
145
  }
208
146
  return 'No description';
209
147
  }
210
148
 
211
149
  private getExpectedData(step: UIProtocolStep): unknown {
212
- if ('sendReceive' in step && hasReceive(step.sendReceive)) {
213
- return step.sendReceive.receive;
150
+ if ('read' in step && typeof step.read === 'object' && step.read !== null && 'expect' in step.read) {
151
+ const read = step.read as { expect: unknown; ack?: { expect?: unknown } };
152
+ return {
153
+ expect: read.expect,
154
+ ack: read.ack?.expect,
155
+ };
214
156
  }
215
- if ('receive' in step) {
216
- return step.receive;
157
+ if ('write' in step && typeof step.write === 'object' && step.write !== null && 'expect' in step.write) {
158
+ return (step.write as { expect: unknown }).expect;
217
159
  }
218
- if ('readSegment' in step) {
219
- // For readSegment, return both start and end chunk receive patterns
220
- const { readSegment } = step;
221
- if (hasEndChunk(readSegment) && hasStartChunk(readSegment)) {
222
- return {
223
- endChunk: readSegment.endChunk.receive,
224
- startChunk: readSegment.startChunk.receive,
225
- type: 'readSegment',
226
- };
227
- }
160
+ if ('expect' in step) {
161
+ return step.expect;
228
162
  }
229
163
  return {};
230
164
  }