@forgehive/task 0.1.6 → 0.1.8
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.
- package/dist/index.d.ts +39 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +145 -77
- package/dist/index.js.map +1 -1
- package/dist/test/safe-replay-complex-boundary.test.d.ts +2 -0
- package/dist/test/safe-replay-complex-boundary.test.d.ts.map +1 -0
- package/dist/test/safe-replay-complex-boundary.test.js +314 -0
- package/dist/test/safe-replay-complex-boundary.test.js.map +1 -0
- package/dist/test/safe-replay.test.d.ts +2 -0
- package/dist/test/safe-replay.test.d.ts.map +1 -0
- package/dist/test/safe-replay.test.js +159 -0
- package/dist/test/safe-replay.test.js.map +1 -0
- package/dist/test/safe-run.test.js +55 -29
- package/dist/test/safe-run.test.js.map +1 -1
- package/dist/test/task-with-boundaries.test.js.map +1 -1
- package/dist/utils/boundary.d.ts +24 -5
- package/dist/utils/boundary.d.ts.map +1 -1
- package/dist/utils/boundary.js +16 -10
- package/dist/utils/boundary.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +258 -96
- package/src/test/safe-replay-complex-boundary.test.ts +385 -0
- package/src/test/safe-replay.test.ts +189 -0
- package/src/test/safe-run.test.ts +58 -31
- package/src/test/task-with-boundaries.test.ts +2 -2
- package/src/utils/boundary.ts +44 -17
package/src/index.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { Schema, type SchemaType, type InferSchema, type SchemaDescription } from '@forgehive/schema'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
createBoundary,
|
|
4
|
+
type Mode,
|
|
5
|
+
type Boundaries,
|
|
6
|
+
type WrappedBoundaries,
|
|
7
|
+
type WrappedBoundaryFunction,
|
|
8
|
+
type BoundaryRecord,
|
|
9
|
+
type BoundaryTapeData
|
|
10
|
+
} from './utils/boundary'
|
|
3
11
|
|
|
4
12
|
export interface Task {
|
|
5
13
|
id: string;
|
|
@@ -11,7 +19,17 @@ export interface Task {
|
|
|
11
19
|
export type BaseFunction = (...args: any[]) => any
|
|
12
20
|
|
|
13
21
|
// Re-export the boundary types for external use
|
|
14
|
-
export type {
|
|
22
|
+
export type {
|
|
23
|
+
BoundaryFunction,
|
|
24
|
+
WrappedBoundaryFunction,
|
|
25
|
+
Boundaries,
|
|
26
|
+
WrappedBoundaries,
|
|
27
|
+
Mode,
|
|
28
|
+
BoundarySuccessRecord,
|
|
29
|
+
BoundaryErrorRecord,
|
|
30
|
+
BoundaryRecord,
|
|
31
|
+
BoundaryTapeData
|
|
32
|
+
} from './utils/boundary'
|
|
15
33
|
|
|
16
34
|
// Re-export Schema for external use
|
|
17
35
|
export { Schema }
|
|
@@ -20,7 +38,14 @@ export interface TaskConfig<B extends Boundaries = Boundaries> {
|
|
|
20
38
|
schema?: Schema<Record<string, SchemaType>>
|
|
21
39
|
mode?: Mode
|
|
22
40
|
boundaries?: B
|
|
23
|
-
boundariesData?:
|
|
41
|
+
boundariesData?: BoundaryTapeData
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Interface for safeReplay configuration
|
|
45
|
+
export interface ReplayConfig<B extends Boundaries = Boundaries> {
|
|
46
|
+
boundaries: {
|
|
47
|
+
[K in keyof B]?: Mode
|
|
48
|
+
}
|
|
24
49
|
}
|
|
25
50
|
|
|
26
51
|
// ToDo: Add a type for the boundaries data
|
|
@@ -38,7 +63,33 @@ export interface TaskRecord<InputType = unknown, OutputType = unknown> {
|
|
|
38
63
|
boundaries?: Record<string, unknown>;
|
|
39
64
|
}
|
|
40
65
|
|
|
66
|
+
// Make BoundaryLog generic
|
|
67
|
+
export type BoundaryLog<I extends unknown[] = unknown[], O = unknown> = BoundaryRecord<I, O>;
|
|
68
|
+
|
|
69
|
+
// Mapped type for boundaries
|
|
70
|
+
export type BoundaryLogsFor<B extends Boundaries> = {
|
|
71
|
+
[K in keyof B]: B[K] extends (...args: infer I) => Promise<infer O>
|
|
72
|
+
? BoundaryLog<I, O>[]
|
|
73
|
+
: BoundaryLog[]
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Represents the execution record of a task, including input, output, error, and boundary data
|
|
78
|
+
*/
|
|
79
|
+
export interface ExecutionRecord<InputType = unknown, OutputType = unknown, B extends Boundaries = Boundaries> {
|
|
80
|
+
/** The input arguments passed to the task */
|
|
81
|
+
input: InputType
|
|
82
|
+
/** The output returned by the task (if successful) */
|
|
83
|
+
output?: OutputType | null
|
|
84
|
+
/** The error message if the task failed */
|
|
85
|
+
error?: string
|
|
86
|
+
/** Boundary execution data */
|
|
87
|
+
boundaries: BoundaryLogsFor<B>
|
|
88
|
+
}
|
|
89
|
+
|
|
41
90
|
export interface TaskInstanceType<Func extends BaseFunction = BaseFunction, B extends Boundaries = Boundaries> {
|
|
91
|
+
version: string
|
|
92
|
+
|
|
42
93
|
getMode: () => Mode
|
|
43
94
|
setMode: (mode: Mode) => void
|
|
44
95
|
setSchema: (base: Schema<Record<string, SchemaType>>) => void
|
|
@@ -59,7 +110,7 @@ export interface TaskInstanceType<Func extends BaseFunction = BaseFunction, B ex
|
|
|
59
110
|
// Boundary methods
|
|
60
111
|
asBoundary: () => (args: Parameters<Func>[0]) => Promise<ReturnType<Func>>
|
|
61
112
|
getBoundaries: () => WrappedBoundaries<B>
|
|
62
|
-
setBoundariesData: (boundariesData:
|
|
113
|
+
setBoundariesData: (boundariesData: BoundaryTapeData) => void
|
|
63
114
|
getBondariesData: () => Record<string, unknown>
|
|
64
115
|
|
|
65
116
|
// Mocking methods for testing
|
|
@@ -68,9 +119,18 @@ export interface TaskInstanceType<Func extends BaseFunction = BaseFunction, B ex
|
|
|
68
119
|
resetMocks: () => void
|
|
69
120
|
|
|
70
121
|
run: (argv?: Parameters<Func>[0]) => Promise<ReturnType<Func>>
|
|
71
|
-
safeRun: (argv?: Parameters<Func>[0]) => Promise<[
|
|
122
|
+
safeRun: (argv?: Parameters<Func>[0]) => Promise<[ReturnType<Func> | null, Error | null, ExecutionRecord<Parameters<Func>[0], ReturnType<Func>, B>]>
|
|
123
|
+
|
|
124
|
+
// Method for replaying task execution
|
|
125
|
+
safeReplay: (
|
|
126
|
+
executionLog: ExecutionRecord<Parameters<Func>[0], ReturnType<Func>, B>,
|
|
127
|
+
config: ReplayConfig<B>
|
|
128
|
+
) => Promise<[ReturnType<Func> | null, Error | null, ExecutionRecord<Parameters<Func>[0], ReturnType<Func>, B>]>
|
|
72
129
|
}
|
|
73
130
|
|
|
131
|
+
// Define a type for the accumulated boundary data
|
|
132
|
+
type BoundaryData = Array<{input: unknown[], output?: unknown}>
|
|
133
|
+
|
|
74
134
|
// Helper type to infer schema type
|
|
75
135
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
136
|
export type InferSchemaType<S> = S extends Schema<any> ? InferSchema<S> : Record<string, unknown>;
|
|
@@ -80,20 +140,19 @@ export type TaskFunction<S, B extends Boundaries> =
|
|
|
80
140
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
81
141
|
(argv: InferSchemaType<S>, boundaries: WrappedBoundaries<B>) => Promise<any>;
|
|
82
142
|
|
|
83
|
-
// Define a type for the accumulated boundary data
|
|
84
|
-
type BoundaryData = Array<{input: unknown[], output?: unknown}>
|
|
85
|
-
|
|
86
143
|
export const Task = class Task<
|
|
87
144
|
B extends Boundaries = Boundaries,
|
|
88
145
|
Func extends BaseFunction = BaseFunction
|
|
89
146
|
> implements TaskInstanceType<Func, B> {
|
|
147
|
+
public version: string = '0.1.7'
|
|
148
|
+
|
|
90
149
|
_fn: Func
|
|
91
150
|
_mode: Mode
|
|
92
151
|
_coolDown: number
|
|
93
152
|
_description?: string
|
|
94
153
|
|
|
95
154
|
_boundariesDefinition: B
|
|
96
|
-
_boundariesData:
|
|
155
|
+
_boundariesData: BoundaryTapeData | null
|
|
97
156
|
_accumulatedBoundariesData: Record<string, BoundaryData> = {}
|
|
98
157
|
|
|
99
158
|
// For storing mocks
|
|
@@ -218,7 +277,7 @@ export const Task = class Task<
|
|
|
218
277
|
})
|
|
219
278
|
}
|
|
220
279
|
|
|
221
|
-
setBoundariesData (boundariesData:
|
|
280
|
+
setBoundariesData (boundariesData: BoundaryTapeData): void {
|
|
222
281
|
this._boundariesData = boundariesData
|
|
223
282
|
|
|
224
283
|
// Update accumulated data as well
|
|
@@ -265,31 +324,36 @@ export const Task = class Task<
|
|
|
265
324
|
_createBounderies ({
|
|
266
325
|
definition,
|
|
267
326
|
baseData,
|
|
268
|
-
mode = 'proxy'
|
|
327
|
+
mode = 'proxy',
|
|
328
|
+
boundaryModes = {}
|
|
269
329
|
}: {
|
|
270
330
|
definition: B;
|
|
271
|
-
baseData:
|
|
331
|
+
baseData: BoundaryTapeData | null;
|
|
272
332
|
mode?: Mode;
|
|
333
|
+
boundaryModes?: Record<string, Mode | undefined>;
|
|
273
334
|
}): WrappedBoundaries<B> {
|
|
274
335
|
const boundariesFns: Record<string, WrappedBoundaryFunction> = {}
|
|
275
336
|
|
|
276
337
|
for (const name in definition) {
|
|
338
|
+
// Get the configured mode for this boundary or use default
|
|
339
|
+
const boundaryMode = boundaryModes[name] || mode
|
|
340
|
+
|
|
277
341
|
// Check if we have a mock for this boundary
|
|
278
342
|
if (this._boundaryMocks[name]) {
|
|
279
343
|
boundariesFns[name] = this._boundaryMocks[name]
|
|
280
344
|
continue
|
|
281
345
|
}
|
|
282
346
|
|
|
283
|
-
//
|
|
347
|
+
// Create the boundary
|
|
284
348
|
const boundary = createBoundary(definition[name])
|
|
285
349
|
|
|
286
350
|
if (baseData !== null && typeof baseData[name] !== 'undefined') {
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
290
|
-
boundary.setTape(tape as any)
|
|
351
|
+
const boundaryData = baseData[name] as Array<BoundaryRecord<Parameters<B[Extract<keyof B, string>]>, Awaited<ReturnType<B[Extract<keyof B, string>]>>>>
|
|
352
|
+
boundary.setTape(boundaryData)
|
|
291
353
|
}
|
|
292
|
-
|
|
354
|
+
|
|
355
|
+
// Set the mode after setting the tape
|
|
356
|
+
boundary.setMode(boundaryMode)
|
|
293
357
|
|
|
294
358
|
boundariesFns[name] = boundary
|
|
295
359
|
}
|
|
@@ -303,31 +367,15 @@ export const Task = class Task<
|
|
|
303
367
|
}
|
|
304
368
|
}
|
|
305
369
|
|
|
306
|
-
async safeRun (argv?: Parameters<Func>[0]): Promise<[
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const errorMessage = errorDetails
|
|
317
|
-
? `Invalid input on: ${errorDetails}`
|
|
318
|
-
: 'Invalid input'
|
|
319
|
-
|
|
320
|
-
// Emit the validation error
|
|
321
|
-
this.emit({
|
|
322
|
-
input: argv,
|
|
323
|
-
error: errorMessage
|
|
324
|
-
})
|
|
325
|
-
|
|
326
|
-
return [new Error(errorMessage), null, null]
|
|
327
|
-
}
|
|
328
|
-
} catch (error) {
|
|
329
|
-
return [error instanceof Error ? error : new Error(String(error)), null, null]
|
|
330
|
-
}
|
|
370
|
+
async safeRun (argv?: Parameters<Func>[0]): Promise<[
|
|
371
|
+
ReturnType<Func> | null,
|
|
372
|
+
Error | null,
|
|
373
|
+
ExecutionRecord<Parameters<Func>[0], ReturnType<Func>, B>
|
|
374
|
+
]> {
|
|
375
|
+
// Initialize log item
|
|
376
|
+
const logItem: ExecutionRecord<Parameters<Func>[0], ReturnType<Func>, B> = {
|
|
377
|
+
input: argv as Parameters<Func>[0],
|
|
378
|
+
boundaries: {} as BoundaryLogsFor<B>
|
|
331
379
|
}
|
|
332
380
|
|
|
333
381
|
// Create fresh boundaries for this execution
|
|
@@ -343,85 +391,199 @@ export const Task = class Task<
|
|
|
343
391
|
boundary.startRun()
|
|
344
392
|
}
|
|
345
393
|
|
|
394
|
+
// Handle schema validation
|
|
395
|
+
if (this._schema) {
|
|
396
|
+
const validation = this._schema.safeParse(argv)
|
|
397
|
+
if (!validation.success) {
|
|
398
|
+
const errorDetails = validation.error?.errors.map(err =>
|
|
399
|
+
`${err.path.join('.')}: ${err.message}`
|
|
400
|
+
).join(', ')
|
|
401
|
+
|
|
402
|
+
const errorMessage = errorDetails
|
|
403
|
+
? `Invalid input on: ${errorDetails}`
|
|
404
|
+
: 'Invalid input'
|
|
405
|
+
|
|
406
|
+
logItem.error = errorMessage
|
|
407
|
+
logItem.boundaries = {} as BoundaryLogsFor<B>
|
|
408
|
+
|
|
409
|
+
// Add boundary elements empty
|
|
410
|
+
for (const name in executionBoundaries) {
|
|
411
|
+
logItem.boundaries[name as keyof B] = [] as unknown as BoundaryLogsFor<B>[typeof name]
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
this.emit(logItem)
|
|
415
|
+
return [null, new Error(errorMessage), logItem]
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
let output: ReturnType<Func> | null = null
|
|
420
|
+
let error: Error | null = null
|
|
421
|
+
|
|
346
422
|
try {
|
|
347
423
|
// Execute the task function
|
|
348
|
-
|
|
424
|
+
output = await this._fn(
|
|
349
425
|
argv as Parameters<Func>[0],
|
|
350
426
|
executionBoundaries as unknown as Parameters<Func>[1]
|
|
351
427
|
)
|
|
352
428
|
|
|
353
|
-
|
|
354
|
-
|
|
429
|
+
logItem.output = output
|
|
430
|
+
} catch (caughtError) {
|
|
431
|
+
const errorMessage = caughtError instanceof Error ? caughtError.message : String(caughtError)
|
|
432
|
+
logItem.error = errorMessage
|
|
433
|
+
error = new Error(errorMessage)
|
|
434
|
+
}
|
|
355
435
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const runData = boundary.getRunData()
|
|
436
|
+
// Process boundary data after execution (both success and error cases)
|
|
437
|
+
const boundariesRunLog: BoundaryLogsFor<B> = {} as BoundaryLogsFor<B>
|
|
359
438
|
|
|
360
|
-
|
|
361
|
-
|
|
439
|
+
for (const name in executionBoundaries) {
|
|
440
|
+
const boundary = executionBoundaries[name]
|
|
441
|
+
const runData = boundary.getRunData()
|
|
362
442
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
443
|
+
// Add to the run log
|
|
444
|
+
boundariesRunLog[name as keyof B] = runData as unknown as BoundaryLogsFor<B>[typeof name]
|
|
445
|
+
|
|
446
|
+
// Accumulate in the task's total boundaries data
|
|
447
|
+
if (!this._accumulatedBoundariesData[name]) {
|
|
448
|
+
this._accumulatedBoundariesData[name] = []
|
|
449
|
+
}
|
|
367
450
|
|
|
368
|
-
|
|
369
|
-
|
|
451
|
+
// Get the current accumulated data for this boundary
|
|
452
|
+
const currentData = this._accumulatedBoundariesData[name]
|
|
370
453
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
}
|
|
454
|
+
// Add the new run data
|
|
455
|
+
if (Array.isArray(runData) && runData.length > 0) {
|
|
456
|
+
// Cast the run data to the correct type
|
|
457
|
+
this._accumulatedBoundariesData[name] = [...currentData, ...(runData as BoundaryData)]
|
|
376
458
|
}
|
|
459
|
+
}
|
|
377
460
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
input: argv,
|
|
381
|
-
output,
|
|
382
|
-
boundaries: boundariesRunLog
|
|
383
|
-
})
|
|
461
|
+
// Set boundaries in log item before emitting
|
|
462
|
+
logItem.boundaries = boundariesRunLog
|
|
384
463
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
// Process boundary data after error
|
|
388
|
-
const boundariesRunLog: Record<string, unknown> = {}
|
|
464
|
+
// Emit the log item
|
|
465
|
+
this.emit(logItem)
|
|
389
466
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
467
|
+
// Return the error, output and log item
|
|
468
|
+
return [output, error, logItem]
|
|
469
|
+
}
|
|
393
470
|
|
|
394
|
-
|
|
395
|
-
|
|
471
|
+
async safeReplay(
|
|
472
|
+
executionLog: ExecutionRecord<Parameters<Func>[0], ReturnType<Func>, B>,
|
|
473
|
+
config: ReplayConfig<B> = {
|
|
474
|
+
boundaries: {}
|
|
475
|
+
}
|
|
476
|
+
): Promise<[
|
|
477
|
+
ReturnType<Func> | null,
|
|
478
|
+
Error | null,
|
|
479
|
+
ExecutionRecord<Parameters<Func>[0], ReturnType<Func>, B>
|
|
480
|
+
]> {
|
|
481
|
+
// Extract the input from the execution log
|
|
482
|
+
const argv = executionLog.input
|
|
483
|
+
|
|
484
|
+
// Initialize log item for this replay
|
|
485
|
+
const logItem: ExecutionRecord<Parameters<Func>[0], ReturnType<Func>, B> = {
|
|
486
|
+
input: argv,
|
|
487
|
+
boundaries: {} as BoundaryLogsFor<B>
|
|
488
|
+
}
|
|
396
489
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
this._accumulatedBoundariesData[name] = []
|
|
400
|
-
}
|
|
490
|
+
// Create boundaries for this replay execution with custom modes based on config
|
|
491
|
+
const boundariesConfig: BoundaryTapeData = {}
|
|
401
492
|
|
|
402
|
-
|
|
403
|
-
|
|
493
|
+
// Setup boundary data for replay mode boundaries
|
|
494
|
+
for (const name in this._boundariesDefinition) {
|
|
495
|
+
// Check if this boundary is configured for replay mode
|
|
496
|
+
const mode = config.boundaries[name] || 'proxy'
|
|
404
497
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
this._accumulatedBoundariesData[name] = [...currentData, ...(runData as BoundaryData)]
|
|
409
|
-
}
|
|
498
|
+
if (mode === 'replay' && executionLog.boundaries[name]) {
|
|
499
|
+
// Add boundary data from the execution log for replay mode
|
|
500
|
+
boundariesConfig[name] = executionLog.boundaries[name]
|
|
410
501
|
}
|
|
502
|
+
}
|
|
411
503
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
504
|
+
// Create fresh boundaries for this execution
|
|
505
|
+
const executionBoundaries = this._createBounderies({
|
|
506
|
+
definition: this._boundariesDefinition,
|
|
507
|
+
baseData: boundariesConfig,
|
|
508
|
+
mode: 'proxy',
|
|
509
|
+
boundaryModes: config.boundaries
|
|
510
|
+
})
|
|
418
511
|
|
|
419
|
-
|
|
512
|
+
// Start run for each boundary
|
|
513
|
+
for (const name in executionBoundaries) {
|
|
514
|
+
const boundary = executionBoundaries[name]
|
|
515
|
+
boundary.startRun()
|
|
420
516
|
}
|
|
517
|
+
|
|
518
|
+
// Handle schema validation - reusing the input from the execution log
|
|
519
|
+
if (this._schema) {
|
|
520
|
+
const validation = this._schema.safeParse(argv)
|
|
521
|
+
if (!validation.success) {
|
|
522
|
+
const errorDetails = validation.error?.errors.map(err =>
|
|
523
|
+
`${err.path.join('.')}: ${err.message}`
|
|
524
|
+
).join(', ')
|
|
525
|
+
|
|
526
|
+
const errorMessage = errorDetails
|
|
527
|
+
? `Invalid input on: ${errorDetails}`
|
|
528
|
+
: 'Invalid input'
|
|
529
|
+
|
|
530
|
+
logItem.error = errorMessage
|
|
531
|
+
logItem.output = executionLog.output // Keep the original output
|
|
532
|
+
|
|
533
|
+
// Copy the boundary data from the execution log
|
|
534
|
+
logItem.boundaries = executionLog.boundaries
|
|
535
|
+
|
|
536
|
+
this.emit(logItem)
|
|
537
|
+
return [null, new Error(errorMessage), logItem]
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
let output: ReturnType<Func> | null = null
|
|
542
|
+
let error: Error | null = null
|
|
543
|
+
|
|
544
|
+
try {
|
|
545
|
+
// Execute the task function with replay boundaries
|
|
546
|
+
output = await this._fn(
|
|
547
|
+
argv,
|
|
548
|
+
executionBoundaries as unknown as Parameters<Func>[1]
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
logItem.output = output
|
|
552
|
+
} catch (caughtError) {
|
|
553
|
+
const errorMessage = caughtError instanceof Error ? caughtError.message : String(caughtError)
|
|
554
|
+
logItem.error = errorMessage
|
|
555
|
+
error = new Error(errorMessage)
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Process boundary data after execution
|
|
559
|
+
const boundariesRunLog: BoundaryLogsFor<B> = {} as BoundaryLogsFor<B>
|
|
560
|
+
|
|
561
|
+
for (const name in executionBoundaries) {
|
|
562
|
+
const boundary = executionBoundaries[name]
|
|
563
|
+
const runData = boundary.getRunData()
|
|
564
|
+
|
|
565
|
+
// For boundaries in replay mode, use the original log data instead
|
|
566
|
+
const mode = config.boundaries[name] || 'proxy'
|
|
567
|
+
if (mode === 'replay' && executionLog.boundaries[name]) {
|
|
568
|
+
boundariesRunLog[name as keyof B] = executionLog.boundaries[name as keyof B]
|
|
569
|
+
} else {
|
|
570
|
+
// For other modes, use the actual run data
|
|
571
|
+
boundariesRunLog[name as keyof B] = runData as unknown as BoundaryLogsFor<B>[typeof name]
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// Set boundaries in log item before emitting
|
|
576
|
+
logItem.boundaries = boundariesRunLog
|
|
577
|
+
|
|
578
|
+
// Emit the log item
|
|
579
|
+
this.emit(logItem)
|
|
580
|
+
|
|
581
|
+
// Return the output, error, and log item
|
|
582
|
+
return [output, error, logItem]
|
|
421
583
|
}
|
|
422
584
|
|
|
423
585
|
async run (argv?: Parameters<Func>[0]): Promise<ReturnType<Func>> {
|
|
424
|
-
const [
|
|
586
|
+
const [result, error] = await this.safeRun(argv)
|
|
425
587
|
|
|
426
588
|
if (error) {
|
|
427
589
|
throw error
|