1
1
import * as util from 'node:util' ;
2
2
import * as uuid from 'uuid' ;
3
- import type { ActionLessMessage , IoHelper } from './io-helper' ;
3
+ import type { ActionLessMessage , ActionLessRequest , IoHelper } from './io-helper' ;
4
4
import type * as make from './message-maker' ;
5
5
import type { Duration } from '../../../payloads/types' ;
6
6
import { formatTime } from '../../../util' ;
7
- import type { IoMessageLevel } from '../io-message' ;
7
+ import type { IActionAwareIoHost } from '../io-host' ;
8
+ import type { IoDefaultMessages } from './io-default-messages' ;
8
9
9
10
export interface SpanEnd {
10
11
readonly duration : number ;
@@ -57,7 +58,15 @@ interface ElapsedTime {
57
58
/**
58
59
* A message span that can be ended and read times from
59
60
*/
60
- export interface IMessageSpan < E extends SpanEnd > {
61
+ export interface IMessageSpan < E extends SpanEnd > extends IActionAwareIoHost {
62
+ /**
63
+ * An IoHelper wrapped around the span.
64
+ */
65
+ readonly asHelper : IoHelper ;
66
+ /**
67
+ * An IoDefaultMessages wrapped around the span.
68
+ */
69
+ readonly defaults : IoDefaultMessages ;
61
70
/**
62
71
* Get the time elapsed since the start
63
72
*/
@@ -67,14 +76,6 @@ export interface IMessageSpan<E extends SpanEnd> {
67
76
* For more complex intermediate messages, get the `elapsedTime` and use `notify`
68
77
*/
69
78
timing ( maker : make . IoMessageMaker < Duration > , message ?: string ) : Promise < ElapsedTime > ;
70
- /**
71
- * Sends an arbitrary intermediate message as part of the span
72
- */
73
- notify ( message : ActionLessMessage < unknown > ) : Promise < void > ;
74
- /**
75
- * Sends an arbitrary intermediate default message as part of the span
76
- */
77
- notifyDefault ( level : IoMessageLevel , message : string ) : Promise < void > ;
78
79
/**
79
80
* End the span with a payload
80
81
*/
@@ -99,10 +100,12 @@ export interface IMessageSpan<E extends SpanEnd> {
99
100
export class SpanMaker < S extends object , E extends SpanEnd > {
100
101
private readonly definition : SpanDefinition < S , E > ;
101
102
private readonly ioHelper : IoHelper ;
103
+ private makeHelper : ( ioHost : IActionAwareIoHost ) => IoHelper ;
102
104
103
- public constructor ( ioHelper : IoHelper , definition : SpanDefinition < S , E > ) {
105
+ public constructor ( ioHelper : IoHelper , definition : SpanDefinition < S , E > , makeHelper : ( ioHost : IActionAwareIoHost ) => IoHelper ) {
104
106
this . definition = definition ;
105
107
this . ioHelper = ioHelper ;
108
+ this . makeHelper = makeHelper ;
106
109
}
107
110
108
111
/**
@@ -112,68 +115,77 @@ export class SpanMaker<S extends object, E extends SpanEnd> {
112
115
public async begin ( payload : VoidWhenEmpty < S > ) : Promise < IMessageSpan < E > > ;
113
116
public async begin ( message : string , payload : S ) : Promise < IMessageSpan < E > > ;
114
117
public async begin ( a : any , b ?: S ) : Promise < IMessageSpan < E > > {
115
- const spanId = uuid . v4 ( ) ;
116
- const startTime = new Date ( ) . getTime ( ) ;
117
-
118
- const notify = ( msg : ActionLessMessage < unknown > ) : Promise < void > => {
119
- return this . ioHelper . notify ( withSpanId ( spanId , msg ) ) ;
120
- } ;
121
-
118
+ const span = new MessageSpan ( this . ioHelper , this . definition , this . makeHelper ) ;
122
119
const startInput = parseArgs < S > ( a , b ) ;
123
120
const startMsg = startInput . message ?? `Starting ${ this . definition . name } ...` ;
124
121
const startPayload = startInput . payload ;
122
+ await span . notify ( this . definition . start . msg ( startMsg , startPayload ) ) ;
125
123
126
- await notify ( this . definition . start . msg (
127
- startMsg ,
128
- startPayload ,
129
- ) ) ;
130
-
131
- const timingMsgTemplate = '\n✨ %s time: %ds\n' ;
132
- const time = ( ) => {
133
- const elapsedTime = new Date ( ) . getTime ( ) - startTime ;
134
- return {
135
- asMs : elapsedTime ,
136
- asSec : formatTime ( elapsedTime ) ,
137
- } ;
138
- } ;
124
+ return span ;
125
+ }
126
+ }
127
+
128
+ class MessageSpan < S extends object , E extends SpanEnd > implements IMessageSpan < E > {
129
+ public readonly asHelper : IoHelper ;
130
+
131
+ private readonly definition : SpanDefinition < S , E > ;
132
+ private readonly ioHelper : IoHelper ;
133
+ private readonly spanId : string ;
134
+ private readonly startTime : number ;
135
+ private readonly timingMsgTemplate : string ;
136
+
137
+ public constructor ( ioHelper : IoHelper , definition : SpanDefinition < S , E > , makeHelper : ( ioHost : IActionAwareIoHost ) => IoHelper ) {
138
+ this . definition = definition ;
139
+ this . ioHelper = ioHelper ;
140
+ this . spanId = uuid . v4 ( ) ;
141
+ this . startTime = new Date ( ) . getTime ( ) ;
142
+ this . timingMsgTemplate = '\n✨ %s time: %ds\n' ;
143
+ this . asHelper = makeHelper ( this ) ;
144
+ }
145
+
146
+ public get defaults ( ) : IoDefaultMessages {
147
+ return this . asHelper . defaults ;
148
+ }
149
+
150
+ public async elapsedTime ( ) : Promise < ElapsedTime > {
151
+ return this . time ( ) ;
152
+ }
153
+ public async timing ( maker : make . IoMessageMaker < Duration > , message ?: string ) : Promise < ElapsedTime > {
154
+ const duration = this . time ( ) ;
155
+ const timingMsg = message ? message : util . format ( this . timingMsgTemplate , this . definition . name , duration . asSec ) ;
156
+ await this . notify ( maker . msg ( timingMsg , {
157
+ duration : duration . asMs ,
158
+ } ) ) ;
159
+ return duration ;
160
+ }
161
+ public async notify ( msg : ActionLessMessage < unknown > ) : Promise < void > {
162
+ return this . ioHelper . notify ( withSpanId ( this . spanId , msg ) ) ;
163
+ }
164
+ public async end ( x : any , y ?: ForceEmpty < Optional < E , keyof SpanEnd > > ) : Promise < ElapsedTime > {
165
+ const duration = this . time ( ) ;
166
+
167
+ const endInput = parseArgs < ForceEmpty < Optional < E , keyof SpanEnd > > > ( x , y ) ;
168
+ const endMsg = endInput . message ?? util . format ( this . timingMsgTemplate , this . definition . name , duration . asSec ) ;
169
+ const endPayload = endInput . payload ;
170
+
171
+ await this . notify ( this . definition . end . msg (
172
+ endMsg , {
173
+ duration : duration . asMs ,
174
+ ...endPayload ,
175
+ } as E ) ) ;
176
+
177
+ return duration ;
178
+ }
179
+
180
+ public async requestResponse < T > ( msg : ActionLessRequest < unknown , T > ) : Promise < T > {
181
+ return this . ioHelper . requestResponse ( withSpanId ( this . spanId , msg ) ) ;
182
+ }
139
183
184
+ private time ( ) {
185
+ const elapsedTime = new Date ( ) . getTime ( ) - this . startTime ;
140
186
return {
141
- elapsedTime : async ( ) : Promise < ElapsedTime > => {
142
- return time ( ) ;
143
- } ,
144
-
145
- notify : async ( msg : ActionLessMessage < unknown > ) : Promise < void > => {
146
- await notify ( msg ) ;
147
- } ,
148
-
149
- notifyDefault : async ( level : IoMessageLevel , msg : string ) : Promise < void > => {
150
- await notify ( this . ioHelper . defaults . msg ( level , msg ) ) ;
151
- } ,
152
-
153
- timing : async ( maker : make . IoMessageMaker < Duration > , message ?: string ) : Promise < ElapsedTime > => {
154
- const duration = time ( ) ;
155
- const timingMsg = message ? message : util . format ( timingMsgTemplate , this . definition . name , duration . asSec ) ;
156
- await notify ( maker . msg ( timingMsg , {
157
- duration : duration . asMs ,
158
- } ) ) ;
159
- return duration ;
160
- } ,
161
-
162
- end : async ( x : any , y ?: ForceEmpty < Optional < E , keyof SpanEnd > > ) : Promise < ElapsedTime > => {
163
- const duration = time ( ) ;
164
-
165
- const endInput = parseArgs < ForceEmpty < Optional < E , keyof SpanEnd > > > ( x , y ) ;
166
- const endMsg = endInput . message ?? util . format ( timingMsgTemplate , this . definition . name , duration . asSec ) ;
167
- const endPayload = endInput . payload ;
168
-
169
- await notify ( this . definition . end . msg (
170
- endMsg , {
171
- duration : duration . asMs ,
172
- ...endPayload ,
173
- } as E ) ) ;
174
-
175
- return duration ;
176
- } ,
187
+ asMs : elapsedTime ,
188
+ asSec : formatTime ( elapsedTime ) ,
177
189
} ;
178
190
}
179
191
}
@@ -194,7 +206,7 @@ function parseArgs<S extends object>(first: any, second?: S): { message: string
194
206
} ;
195
207
}
196
208
197
- function withSpanId ( span : string , message : ActionLessMessage < unknown > ) : ActionLessMessage < unknown > {
209
+ function withSpanId < T extends object > ( span : string , message : T ) : T & { span : string } {
198
210
return {
199
211
...message ,
200
212
span,
0 commit comments