@forgehive/record-tape 0.0.2 → 0.1.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.
- package/dist/index.d.ts +22 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +102 -4
- package/dist/index.js.map +1 -1
- package/dist/tests/safe-run.test.d.ts +2 -0
- package/dist/tests/safe-run.test.d.ts.map +1 -0
- package/dist/tests/safe-run.test.js +282 -0
- package/dist/tests/safe-run.test.js.map +1 -0
- package/package.json +10 -3
- package/src/index.ts +128 -25
- package/src/tests/safe-run.test.ts +344 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,49 +1,53 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
-
|
|
2
|
+
import { type ExecutionRecord, type Boundaries } from '@forgehive/task';
|
|
3
|
+
export interface LogRecord<TInput = unknown, TOutput = unknown, B extends Boundaries = Boundaries> extends ExecutionRecord<TInput, TOutput, B> {
|
|
3
4
|
name: string;
|
|
4
5
|
type: 'success' | 'error';
|
|
5
|
-
input: TInput;
|
|
6
|
-
output?: TOutput;
|
|
7
|
-
error?: unknown;
|
|
8
|
-
boundaries: Record<string, unknown>;
|
|
9
6
|
}
|
|
10
|
-
interface SuccessLogItem<TInput = unknown
|
|
7
|
+
export interface SuccessLogItem<TInput = unknown, TOutput = unknown> {
|
|
11
8
|
input: TInput;
|
|
12
9
|
output: TOutput;
|
|
13
10
|
boundaries?: Record<string, unknown>;
|
|
14
11
|
}
|
|
15
|
-
interface ErrorLogItem<TInput = unknown
|
|
12
|
+
export interface ErrorLogItem<TInput = unknown> {
|
|
16
13
|
input: TInput;
|
|
17
14
|
error: unknown;
|
|
18
15
|
boundaries?: Record<string, unknown>;
|
|
19
16
|
}
|
|
20
|
-
export type LogItem<TInput = unknown
|
|
21
|
-
|
|
17
|
+
export type LogItem<TInput = unknown, TOutput = unknown> = SuccessLogItem<TInput, TOutput> | ErrorLogItem<TInput>;
|
|
18
|
+
export type TaskLogItem<TInput = unknown, TOutput = unknown> = LogItem<TInput, TOutput> | {
|
|
19
|
+
input: TInput;
|
|
20
|
+
output?: TOutput;
|
|
21
|
+
error?: unknown;
|
|
22
|
+
boundaries?: Record<string, unknown>;
|
|
23
|
+
};
|
|
24
|
+
interface Config<TInput = unknown, TOutput = unknown, B extends Boundaries = Boundaries> {
|
|
22
25
|
path?: fs.PathLike;
|
|
23
|
-
log?: LogRecord<TInput, TOutput>[];
|
|
26
|
+
log?: LogRecord<TInput, TOutput, B>[];
|
|
24
27
|
boundaries?: Record<string, unknown>;
|
|
25
28
|
}
|
|
26
29
|
export type Mode = 'record' | 'replay';
|
|
27
|
-
export declare class RecordTape<TInput = unknown
|
|
30
|
+
export declare class RecordTape<TInput = unknown, TOutput = unknown, B extends Boundaries = Boundaries> {
|
|
28
31
|
private _path;
|
|
29
32
|
private _mode;
|
|
30
33
|
private _boundaries;
|
|
31
34
|
private _log;
|
|
32
|
-
constructor(config?: Config<TInput, TOutput>);
|
|
33
|
-
getLog(): LogRecord<TInput, TOutput>[];
|
|
35
|
+
constructor(config?: Config<TInput, TOutput, B>);
|
|
36
|
+
getLog(): LogRecord<TInput, TOutput, B>[];
|
|
34
37
|
getMode(): Mode;
|
|
35
38
|
setMode(mode: Mode): void;
|
|
36
|
-
addLogItem(name: string, logItem:
|
|
37
|
-
|
|
39
|
+
addLogItem(name: string, logItem: any): void;
|
|
40
|
+
push(name: string, record: ExecutionRecord<TInput, any, B>): void;
|
|
41
|
+
addLogRecord(logRecord: LogRecord<TInput, TOutput, B>): void;
|
|
38
42
|
stringify(): string;
|
|
39
|
-
parse(content: string): LogRecord<TInput, TOutput>[];
|
|
43
|
+
parse(content: string): LogRecord<TInput, TOutput, B>[];
|
|
40
44
|
compileCache(): Record<string, unknown>;
|
|
41
45
|
recordFrom(name: string, task: {
|
|
42
46
|
_listener?: unknown;
|
|
43
47
|
setBoundariesData: (data: Record<string, unknown>) => void;
|
|
44
48
|
}): void;
|
|
45
|
-
load(): Promise<LogRecord<TInput, TOutput>[]>;
|
|
46
|
-
loadSync(): LogRecord<TInput, TOutput>[];
|
|
49
|
+
load(): Promise<LogRecord<TInput, TOutput, B>[]>;
|
|
50
|
+
loadSync(): LogRecord<TInput, TOutput, B>[];
|
|
47
51
|
save(): Promise<void>;
|
|
48
52
|
saveSync(): void;
|
|
49
53
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -34,18 +34,116 @@ class RecordTape {
|
|
|
34
34
|
if (this._mode === 'replay') {
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
+
// Format boundaries to ensure both error and output fields are set if needed
|
|
38
|
+
const formattedBoundaries = {};
|
|
39
|
+
if (logItem.boundaries) {
|
|
40
|
+
for (const key in logItem.boundaries) {
|
|
41
|
+
// Check if the source is from safe-run (if it has error field in entries)
|
|
42
|
+
const isSafeRun = logItem.boundaries[key].some((entry) => entry.error !== undefined);
|
|
43
|
+
formattedBoundaries[key] = logItem.boundaries[key].map((entry) => {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
// Only add error field if it's from safe-run
|
|
46
|
+
return isSafeRun ?
|
|
47
|
+
{
|
|
48
|
+
input: entry.input,
|
|
49
|
+
output: (_a = entry.output) !== null && _a !== void 0 ? _a : null,
|
|
50
|
+
error: (_b = entry.error) !== null && _b !== void 0 ? _b : null
|
|
51
|
+
} :
|
|
52
|
+
{
|
|
53
|
+
input: entry.input,
|
|
54
|
+
output: entry.output
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Handle LogItem interface
|
|
37
60
|
if (isSuccessLogItem(logItem)) {
|
|
38
|
-
const { input, output
|
|
39
|
-
this._log.push({
|
|
61
|
+
const { input, output } = logItem;
|
|
62
|
+
this._log.push({
|
|
63
|
+
name,
|
|
64
|
+
type: 'success',
|
|
65
|
+
input,
|
|
66
|
+
output,
|
|
67
|
+
boundaries: formattedBoundaries
|
|
68
|
+
});
|
|
40
69
|
}
|
|
41
70
|
else if (isErrorLogItem(logItem)) {
|
|
42
|
-
const { input, error
|
|
43
|
-
this._log.push({
|
|
71
|
+
const { input, error } = logItem;
|
|
72
|
+
this._log.push({
|
|
73
|
+
name,
|
|
74
|
+
type: 'error',
|
|
75
|
+
input,
|
|
76
|
+
error,
|
|
77
|
+
boundaries: formattedBoundaries
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// Handle TaskRecord interface
|
|
81
|
+
else if (logItem.output !== undefined) {
|
|
82
|
+
const { input, output } = logItem;
|
|
83
|
+
this._log.push({
|
|
84
|
+
name,
|
|
85
|
+
type: 'success',
|
|
86
|
+
input,
|
|
87
|
+
output,
|
|
88
|
+
boundaries: formattedBoundaries
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
else if (logItem.error !== undefined) {
|
|
92
|
+
const { input, error } = logItem;
|
|
93
|
+
this._log.push({
|
|
94
|
+
name,
|
|
95
|
+
type: 'error',
|
|
96
|
+
input,
|
|
97
|
+
error,
|
|
98
|
+
boundaries: formattedBoundaries
|
|
99
|
+
});
|
|
44
100
|
}
|
|
45
101
|
else {
|
|
46
102
|
throw new Error('invalid log item');
|
|
47
103
|
}
|
|
48
104
|
}
|
|
105
|
+
push(name, record) {
|
|
106
|
+
if (this._mode === 'replay') {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// For safeRun records, always include both error and output fields
|
|
110
|
+
const formattedBoundaries = {};
|
|
111
|
+
if (record.boundaries) {
|
|
112
|
+
for (const key in record.boundaries) {
|
|
113
|
+
formattedBoundaries[key] = record.boundaries[key].map((entry) => {
|
|
114
|
+
var _a, _b;
|
|
115
|
+
return {
|
|
116
|
+
input: entry.input,
|
|
117
|
+
output: (_a = entry.output) !== null && _a !== void 0 ? _a : null,
|
|
118
|
+
error: (_b = entry.error) !== null && _b !== void 0 ? _b : null
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (record.output !== undefined) {
|
|
124
|
+
const { input, output } = record;
|
|
125
|
+
this._log.push({
|
|
126
|
+
name,
|
|
127
|
+
type: 'success',
|
|
128
|
+
input,
|
|
129
|
+
output: output instanceof Promise ? null : output,
|
|
130
|
+
boundaries: formattedBoundaries
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
else if (record.error !== undefined) {
|
|
134
|
+
const { input, error } = record;
|
|
135
|
+
this._log.push({
|
|
136
|
+
name,
|
|
137
|
+
type: 'error',
|
|
138
|
+
input,
|
|
139
|
+
error,
|
|
140
|
+
boundaries: formattedBoundaries
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
throw new Error('invalid record type');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
49
147
|
addLogRecord(logRecord) {
|
|
50
148
|
this._log.push(logRecord);
|
|
51
149
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAmB;AACnB,gDAAuB;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-run.test.d.ts","sourceRoot":"","sources":["../../src/tests/safe-run.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const index_1 = require("../index");
|
|
4
|
+
const task_1 = require("@forgehive/task");
|
|
5
|
+
describe('RecordTape safeRun integration tests', () => {
|
|
6
|
+
it('should record log items directly from safeRun result', async () => {
|
|
7
|
+
// Create a schema
|
|
8
|
+
const schema = new task_1.Schema({
|
|
9
|
+
value: task_1.Schema.number()
|
|
10
|
+
});
|
|
11
|
+
// Define the boundaries
|
|
12
|
+
const boundaries = {
|
|
13
|
+
fetchData: async (value) => {
|
|
14
|
+
return value * 2;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
// Create the task
|
|
18
|
+
const task = (0, task_1.createTask)(schema, boundaries, async function ({ value }, { fetchData }) {
|
|
19
|
+
const result = await fetchData(value);
|
|
20
|
+
return { result, success: true };
|
|
21
|
+
});
|
|
22
|
+
// Create a record tape
|
|
23
|
+
const tape = new index_1.RecordTape();
|
|
24
|
+
// Run the task with safeRun and directly use the logItem
|
|
25
|
+
const [result, error, record] = await task.safeRun({ value: 5 });
|
|
26
|
+
tape.push('test-task', record);
|
|
27
|
+
// Verify the execution was successful
|
|
28
|
+
expect(error).toBeNull();
|
|
29
|
+
expect(result).toEqual({ result: 10, success: true });
|
|
30
|
+
// Get the recorded log from the tape
|
|
31
|
+
const recordedLog = tape.getLog();
|
|
32
|
+
// Verify the log was recorded correctly
|
|
33
|
+
expect(recordedLog).toHaveLength(1);
|
|
34
|
+
expect(recordedLog[0]).toEqual({
|
|
35
|
+
name: 'test-task',
|
|
36
|
+
type: 'success',
|
|
37
|
+
input: { value: 5 },
|
|
38
|
+
output: { result: 10, success: true },
|
|
39
|
+
boundaries: {
|
|
40
|
+
fetchData: [{
|
|
41
|
+
input: [5],
|
|
42
|
+
output: 10,
|
|
43
|
+
error: null
|
|
44
|
+
}]
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
it('should record log items from safeRun successfully', async () => {
|
|
49
|
+
// Create a schema
|
|
50
|
+
const schema = new task_1.Schema({
|
|
51
|
+
value: task_1.Schema.number()
|
|
52
|
+
});
|
|
53
|
+
// Define the boundaries
|
|
54
|
+
const boundaries = {
|
|
55
|
+
fetchData: async (value) => {
|
|
56
|
+
return value * 2;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
// Create the task
|
|
60
|
+
const task = (0, task_1.createTask)(schema, boundaries, async function ({ value }, { fetchData }) {
|
|
61
|
+
const result = await fetchData(value);
|
|
62
|
+
return { result, success: true };
|
|
63
|
+
});
|
|
64
|
+
// Create a record tape
|
|
65
|
+
const tape = new index_1.RecordTape();
|
|
66
|
+
// Add listener to record the log items
|
|
67
|
+
task.addListener((record) => {
|
|
68
|
+
// Manually ensure boundary records have error field for consistency with safeRun
|
|
69
|
+
if (record.boundaries && record.boundaries.fetchData && Array.isArray(record.boundaries.fetchData)) {
|
|
70
|
+
record.boundaries.fetchData = record.boundaries.fetchData.map((entry) => {
|
|
71
|
+
var _a, _b;
|
|
72
|
+
return (Object.assign(Object.assign({}, entry), { error: (_a = entry.error) !== null && _a !== void 0 ? _a : null, output: (_b = entry.output) !== null && _b !== void 0 ? _b : null }));
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
tape.addLogItem('test-task', record);
|
|
76
|
+
});
|
|
77
|
+
// Run the task with safeRun
|
|
78
|
+
const [result, error] = await task.safeRun({ value: 5 });
|
|
79
|
+
// Verify the execution was successful
|
|
80
|
+
expect(error).toBeNull();
|
|
81
|
+
expect(result).toEqual({ result: 10, success: true });
|
|
82
|
+
// Get the recorded log from the tape
|
|
83
|
+
const recordedLog = tape.getLog();
|
|
84
|
+
// Verify the log was recorded correctly
|
|
85
|
+
expect(recordedLog).toHaveLength(1);
|
|
86
|
+
expect(recordedLog[0]).toEqual({
|
|
87
|
+
name: 'test-task',
|
|
88
|
+
type: 'success',
|
|
89
|
+
input: { value: 5 },
|
|
90
|
+
output: { result: 10, success: true },
|
|
91
|
+
boundaries: {
|
|
92
|
+
fetchData: [{
|
|
93
|
+
input: [5],
|
|
94
|
+
output: 10,
|
|
95
|
+
error: null
|
|
96
|
+
}]
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
it('should record error log items from safeRun', async () => {
|
|
101
|
+
// Create a schema
|
|
102
|
+
const schema = new task_1.Schema({
|
|
103
|
+
value: task_1.Schema.number()
|
|
104
|
+
});
|
|
105
|
+
// Define the boundaries with a function that will throw an error
|
|
106
|
+
const boundaries = {
|
|
107
|
+
fetchData: async (value) => {
|
|
108
|
+
if (value < 0) {
|
|
109
|
+
throw new Error('Value cannot be negative');
|
|
110
|
+
}
|
|
111
|
+
return value * 2;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
// Create the task
|
|
115
|
+
const task = (0, task_1.createTask)(schema, boundaries, async function ({ value }, { fetchData }) {
|
|
116
|
+
const result = await fetchData(value);
|
|
117
|
+
return { result, success: true };
|
|
118
|
+
});
|
|
119
|
+
// Create a record tape
|
|
120
|
+
const tape = new index_1.RecordTape();
|
|
121
|
+
// Add listener to record the log items
|
|
122
|
+
task.addListener((record) => {
|
|
123
|
+
// Manually ensure boundary records have error field for consistency with safeRun
|
|
124
|
+
if (record.boundaries && record.boundaries.fetchData && Array.isArray(record.boundaries.fetchData)) {
|
|
125
|
+
record.boundaries.fetchData = record.boundaries.fetchData.map((entry) => {
|
|
126
|
+
var _a, _b;
|
|
127
|
+
return (Object.assign(Object.assign({}, entry), { error: (_a = entry.error) !== null && _a !== void 0 ? _a : null, output: (_b = entry.output) !== null && _b !== void 0 ? _b : null }));
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
tape.addLogItem('test-task', record);
|
|
131
|
+
});
|
|
132
|
+
// Run the task with safeRun with a value that will cause an error
|
|
133
|
+
const [result, error] = await task.safeRun({ value: -5 });
|
|
134
|
+
// Verify the execution failed as expected
|
|
135
|
+
expect(result).toBeNull();
|
|
136
|
+
expect(error).not.toBeNull();
|
|
137
|
+
expect(error === null || error === void 0 ? void 0 : error.message).toContain('Value cannot be negative');
|
|
138
|
+
// Get the recorded log from the tape
|
|
139
|
+
const recordedLog = tape.getLog();
|
|
140
|
+
// Verify the error log was recorded correctly
|
|
141
|
+
expect(recordedLog).toHaveLength(1);
|
|
142
|
+
expect(recordedLog[0]).toEqual({
|
|
143
|
+
name: 'test-task',
|
|
144
|
+
type: 'error',
|
|
145
|
+
input: { value: -5 },
|
|
146
|
+
error: 'Value cannot be negative',
|
|
147
|
+
boundaries: {
|
|
148
|
+
fetchData: [{
|
|
149
|
+
input: [-5],
|
|
150
|
+
output: null,
|
|
151
|
+
error: 'Value cannot be negative'
|
|
152
|
+
}]
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
it('should handle error records directly with push', async () => {
|
|
157
|
+
// Create a schema
|
|
158
|
+
const schema = new task_1.Schema({
|
|
159
|
+
value: task_1.Schema.number()
|
|
160
|
+
});
|
|
161
|
+
// Define the boundaries with a function that will throw an error
|
|
162
|
+
const boundaries = {
|
|
163
|
+
fetchData: async (value) => {
|
|
164
|
+
if (value < 0) {
|
|
165
|
+
throw new Error('Value cannot be negative');
|
|
166
|
+
}
|
|
167
|
+
return value * 2;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
// Create the task
|
|
171
|
+
const task = (0, task_1.createTask)(schema, boundaries, async function ({ value }, { fetchData }) {
|
|
172
|
+
const result = await fetchData(value);
|
|
173
|
+
return { result, success: true };
|
|
174
|
+
});
|
|
175
|
+
// Create a record tape
|
|
176
|
+
const tape = new index_1.RecordTape();
|
|
177
|
+
// Run the task with safeRun with a value that will cause an error
|
|
178
|
+
const [result, error, record] = await task.safeRun({ value: -5 });
|
|
179
|
+
// Push the error record directly
|
|
180
|
+
tape.push('test-error', record);
|
|
181
|
+
// Verify the execution failed as expected
|
|
182
|
+
expect(result).toBeNull();
|
|
183
|
+
expect(error).not.toBeNull();
|
|
184
|
+
expect(error instanceof Error).toBe(true);
|
|
185
|
+
if (error instanceof Error) {
|
|
186
|
+
expect(error.message).toContain('Value cannot be negative');
|
|
187
|
+
}
|
|
188
|
+
// Get the recorded log from the tape
|
|
189
|
+
const recordedLog = tape.getLog();
|
|
190
|
+
// Verify the error log was recorded correctly
|
|
191
|
+
expect(recordedLog).toHaveLength(1);
|
|
192
|
+
expect(recordedLog[0]).toEqual({
|
|
193
|
+
name: 'test-error',
|
|
194
|
+
type: 'error',
|
|
195
|
+
input: { value: -5 },
|
|
196
|
+
error: 'Value cannot be negative',
|
|
197
|
+
boundaries: {
|
|
198
|
+
fetchData: [{
|
|
199
|
+
input: [-5],
|
|
200
|
+
output: null,
|
|
201
|
+
error: 'Value cannot be negative'
|
|
202
|
+
}]
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
it('should handle custom execution records with push', async () => {
|
|
207
|
+
// Create a record tape
|
|
208
|
+
const tape = new index_1.RecordTape();
|
|
209
|
+
// Create a custom execution record
|
|
210
|
+
const customRecord = {
|
|
211
|
+
input: { value: 10 },
|
|
212
|
+
output: { result: 20 },
|
|
213
|
+
boundaries: {
|
|
214
|
+
fetchData: [
|
|
215
|
+
{
|
|
216
|
+
input: [10],
|
|
217
|
+
output: 20,
|
|
218
|
+
error: null
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
// Push the custom record
|
|
224
|
+
tape.push('custom-record', customRecord);
|
|
225
|
+
// Get the recorded log from the tape
|
|
226
|
+
const recordedLog = tape.getLog();
|
|
227
|
+
// Verify the log was recorded correctly
|
|
228
|
+
expect(recordedLog).toHaveLength(1);
|
|
229
|
+
expect(recordedLog[0]).toEqual({
|
|
230
|
+
name: 'custom-record',
|
|
231
|
+
type: 'success',
|
|
232
|
+
input: { value: 10 },
|
|
233
|
+
output: { result: 20 },
|
|
234
|
+
boundaries: {
|
|
235
|
+
fetchData: [{
|
|
236
|
+
input: [10],
|
|
237
|
+
output: 20,
|
|
238
|
+
error: null
|
|
239
|
+
}]
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
it('should handle execution records with Promise outputs correctly', async () => {
|
|
244
|
+
// Create a record tape
|
|
245
|
+
const tape = new index_1.RecordTape();
|
|
246
|
+
// Create a custom execution record with a Promise output
|
|
247
|
+
const promiseResult = Promise.resolve({ result: 30 });
|
|
248
|
+
const promiseRecord = {
|
|
249
|
+
input: { value: 15 },
|
|
250
|
+
output: promiseResult,
|
|
251
|
+
boundaries: {
|
|
252
|
+
fetchData: [
|
|
253
|
+
{
|
|
254
|
+
input: [15],
|
|
255
|
+
output: 30,
|
|
256
|
+
error: null
|
|
257
|
+
}
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
// Push the record with Promise output
|
|
262
|
+
tape.push('promise-record', promiseRecord);
|
|
263
|
+
// Get the recorded log from the tape
|
|
264
|
+
const recordedLog = tape.getLog();
|
|
265
|
+
// Verify the log was recorded correctly, with Promise output set to null
|
|
266
|
+
expect(recordedLog).toHaveLength(1);
|
|
267
|
+
expect(recordedLog[0]).toEqual({
|
|
268
|
+
name: 'promise-record',
|
|
269
|
+
type: 'success',
|
|
270
|
+
input: { value: 15 },
|
|
271
|
+
output: null, // Promise output should be set to null
|
|
272
|
+
boundaries: {
|
|
273
|
+
fetchData: [{
|
|
274
|
+
input: [15],
|
|
275
|
+
output: 30,
|
|
276
|
+
error: null
|
|
277
|
+
}]
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
//# sourceMappingURL=safe-run.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-run.test.js","sourceRoot":"","sources":["../../src/tests/safe-run.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgehive/record-tape",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@forgehive/schema": "^0.1.4",
|
|
11
|
+
"@forgehive/task": "^0.1.7"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
7
14
|
"devDependencies": {
|
|
8
15
|
"@types/jest": "^29.5.14",
|
|
9
16
|
"@types/node": "^20.11.24",
|
|
@@ -12,8 +19,8 @@
|
|
|
12
19
|
"typescript": "^5.3.3"
|
|
13
20
|
},
|
|
14
21
|
"dependencies": {
|
|
15
|
-
"@forgehive/schema": "
|
|
16
|
-
"@forgehive/task": "
|
|
22
|
+
"@forgehive/schema": "0.1.4",
|
|
23
|
+
"@forgehive/task": "0.1.7"
|
|
17
24
|
},
|
|
18
25
|
"scripts": {
|
|
19
26
|
"build": "tsc",
|
package/src/index.ts
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import fs from 'fs'
|
|
2
2
|
import path from 'path'
|
|
3
|
+
import { type ExecutionRecord, type Boundaries } from '@forgehive/task'
|
|
3
4
|
|
|
4
|
-
export interface LogRecord<TInput = unknown
|
|
5
|
+
export interface LogRecord<TInput = unknown, TOutput = unknown, B extends Boundaries = Boundaries> extends ExecutionRecord<TInput, TOutput, B> {
|
|
5
6
|
name: string
|
|
6
7
|
type: 'success' | 'error'
|
|
7
|
-
input: TInput
|
|
8
|
-
output?: TOutput
|
|
9
|
-
error?: unknown
|
|
10
|
-
boundaries: Record<string, unknown>
|
|
11
8
|
}
|
|
12
9
|
|
|
13
|
-
interface SuccessLogItem<TInput = unknown
|
|
10
|
+
export interface SuccessLogItem<TInput = unknown, TOutput = unknown> {
|
|
14
11
|
input: TInput
|
|
15
12
|
output: TOutput
|
|
16
13
|
boundaries?: Record<string, unknown>
|
|
17
14
|
}
|
|
18
15
|
|
|
19
|
-
interface ErrorLogItem<TInput = unknown
|
|
16
|
+
export interface ErrorLogItem<TInput = unknown> {
|
|
20
17
|
input: TInput
|
|
21
18
|
error: unknown
|
|
22
19
|
boundaries?: Record<string, unknown>
|
|
@@ -30,23 +27,31 @@ function isErrorLogItem<TInput>(log: SuccessLogItem<TInput> | ErrorLogItem<TInpu
|
|
|
30
27
|
return (log as ErrorLogItem<TInput>).error !== undefined
|
|
31
28
|
}
|
|
32
29
|
|
|
33
|
-
export type LogItem<TInput = unknown
|
|
30
|
+
export type LogItem<TInput = unknown, TOutput = unknown> = SuccessLogItem<TInput, TOutput> | ErrorLogItem<TInput>
|
|
31
|
+
|
|
32
|
+
// Additional type to handle TaskRecord compatibility
|
|
33
|
+
export type TaskLogItem<TInput = unknown, TOutput = unknown> = LogItem<TInput, TOutput> | {
|
|
34
|
+
input: TInput;
|
|
35
|
+
output?: TOutput;
|
|
36
|
+
error?: unknown;
|
|
37
|
+
boundaries?: Record<string, unknown>;
|
|
38
|
+
}
|
|
34
39
|
|
|
35
|
-
interface Config<TInput = unknown
|
|
40
|
+
interface Config<TInput = unknown, TOutput = unknown, B extends Boundaries = Boundaries> {
|
|
36
41
|
path?: fs.PathLike
|
|
37
|
-
log?: LogRecord<TInput, TOutput>[]
|
|
42
|
+
log?: LogRecord<TInput, TOutput, B>[]
|
|
38
43
|
boundaries?: Record<string, unknown>
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
export type Mode = 'record' | 'replay'
|
|
42
47
|
|
|
43
|
-
export class RecordTape<TInput = unknown
|
|
48
|
+
export class RecordTape<TInput = unknown, TOutput = unknown, B extends Boundaries = Boundaries> {
|
|
44
49
|
private _path: fs.PathLike | undefined
|
|
45
50
|
private _mode: Mode
|
|
46
51
|
private _boundaries: Record<string, unknown>
|
|
47
|
-
private _log: LogRecord<TInput, TOutput>[]
|
|
52
|
+
private _log: LogRecord<TInput, TOutput, B>[]
|
|
48
53
|
|
|
49
|
-
constructor(config: Config<TInput, TOutput> = {}) {
|
|
54
|
+
constructor(config: Config<TInput, TOutput, B> = {}) {
|
|
50
55
|
this._path = typeof config.path === 'string' ? `${config.path}.log` : undefined
|
|
51
56
|
this._log = config.log ?? []
|
|
52
57
|
this._boundaries = config.boundaries ?? {}
|
|
@@ -54,7 +59,7 @@ export class RecordTape<TInput = unknown[], TOutput = unknown> {
|
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
// Data functions
|
|
57
|
-
getLog(): LogRecord<TInput, TOutput>[] {
|
|
62
|
+
getLog(): LogRecord<TInput, TOutput, B>[] {
|
|
58
63
|
return this._log
|
|
59
64
|
}
|
|
60
65
|
|
|
@@ -66,23 +71,121 @@ export class RecordTape<TInput = unknown[], TOutput = unknown> {
|
|
|
66
71
|
this._mode = mode
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
addLogItem(name: string, logItem:
|
|
74
|
+
addLogItem(name: string, logItem: any): void {
|
|
70
75
|
if (this._mode === 'replay') {
|
|
71
76
|
return
|
|
72
77
|
}
|
|
73
78
|
|
|
79
|
+
// Format boundaries to ensure both error and output fields are set if needed
|
|
80
|
+
const formattedBoundaries: Record<string, any> = {}
|
|
81
|
+
if (logItem.boundaries) {
|
|
82
|
+
for (const key in logItem.boundaries) {
|
|
83
|
+
// Check if the source is from safe-run (if it has error field in entries)
|
|
84
|
+
const isSafeRun = logItem.boundaries[key].some((entry: any) => entry.error !== undefined)
|
|
85
|
+
|
|
86
|
+
formattedBoundaries[key] = logItem.boundaries[key].map((entry: any) => {
|
|
87
|
+
// Only add error field if it's from safe-run
|
|
88
|
+
return isSafeRun ?
|
|
89
|
+
{
|
|
90
|
+
input: entry.input,
|
|
91
|
+
output: entry.output ?? null,
|
|
92
|
+
error: entry.error ?? null
|
|
93
|
+
} :
|
|
94
|
+
{
|
|
95
|
+
input: entry.input,
|
|
96
|
+
output: entry.output
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Handle LogItem interface
|
|
74
103
|
if (isSuccessLogItem(logItem)) {
|
|
75
|
-
const { input, output
|
|
76
|
-
this._log.push({
|
|
104
|
+
const { input, output } = logItem
|
|
105
|
+
this._log.push({
|
|
106
|
+
name,
|
|
107
|
+
type: 'success',
|
|
108
|
+
input,
|
|
109
|
+
output,
|
|
110
|
+
boundaries: formattedBoundaries
|
|
111
|
+
} as LogRecord<TInput, TOutput, B>)
|
|
77
112
|
} else if (isErrorLogItem(logItem)) {
|
|
78
|
-
const { input, error
|
|
79
|
-
this._log.push({
|
|
113
|
+
const { input, error } = logItem
|
|
114
|
+
this._log.push({
|
|
115
|
+
name,
|
|
116
|
+
type: 'error',
|
|
117
|
+
input,
|
|
118
|
+
error,
|
|
119
|
+
boundaries: formattedBoundaries
|
|
120
|
+
} as LogRecord<TInput, TOutput, B>)
|
|
121
|
+
}
|
|
122
|
+
// Handle TaskRecord interface
|
|
123
|
+
else if (logItem.output !== undefined) {
|
|
124
|
+
const { input, output } = logItem
|
|
125
|
+
this._log.push({
|
|
126
|
+
name,
|
|
127
|
+
type: 'success',
|
|
128
|
+
input,
|
|
129
|
+
output,
|
|
130
|
+
boundaries: formattedBoundaries
|
|
131
|
+
} as LogRecord<TInput, TOutput, B>)
|
|
132
|
+
} else if (logItem.error !== undefined) {
|
|
133
|
+
const { input, error } = logItem
|
|
134
|
+
this._log.push({
|
|
135
|
+
name,
|
|
136
|
+
type: 'error',
|
|
137
|
+
input,
|
|
138
|
+
error,
|
|
139
|
+
boundaries: formattedBoundaries
|
|
140
|
+
} as LogRecord<TInput, TOutput, B>)
|
|
80
141
|
} else {
|
|
81
142
|
throw new Error('invalid log item')
|
|
82
143
|
}
|
|
83
144
|
}
|
|
84
145
|
|
|
85
|
-
|
|
146
|
+
push(name: string, record: ExecutionRecord<TInput, any, B>): void {
|
|
147
|
+
if (this._mode === 'replay') {
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// For safeRun records, always include both error and output fields
|
|
152
|
+
const formattedBoundaries: Record<string, any> = {}
|
|
153
|
+
if (record.boundaries) {
|
|
154
|
+
for (const key in record.boundaries) {
|
|
155
|
+
formattedBoundaries[key] = record.boundaries[key].map((entry: any) => {
|
|
156
|
+
return {
|
|
157
|
+
input: entry.input,
|
|
158
|
+
output: entry.output ?? null,
|
|
159
|
+
error: entry.error ?? null
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (record.output !== undefined) {
|
|
166
|
+
const { input, output } = record
|
|
167
|
+
this._log.push({
|
|
168
|
+
name,
|
|
169
|
+
type: 'success',
|
|
170
|
+
input,
|
|
171
|
+
output: output instanceof Promise ? null : output,
|
|
172
|
+
boundaries: formattedBoundaries
|
|
173
|
+
} as unknown as LogRecord<TInput, TOutput, B>)
|
|
174
|
+
} else if (record.error !== undefined) {
|
|
175
|
+
const { input, error } = record
|
|
176
|
+
this._log.push({
|
|
177
|
+
name,
|
|
178
|
+
type: 'error',
|
|
179
|
+
input,
|
|
180
|
+
error,
|
|
181
|
+
boundaries: formattedBoundaries
|
|
182
|
+
} as unknown as LogRecord<TInput, TOutput, B>)
|
|
183
|
+
} else {
|
|
184
|
+
throw new Error('invalid record type')
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
addLogRecord(logRecord: LogRecord<TInput, TOutput, B>): void {
|
|
86
189
|
this._log.push(logRecord)
|
|
87
190
|
}
|
|
88
191
|
|
|
@@ -95,12 +198,12 @@ export class RecordTape<TInput = unknown[], TOutput = unknown> {
|
|
|
95
198
|
return log
|
|
96
199
|
}
|
|
97
200
|
|
|
98
|
-
parse(content: string): LogRecord<TInput, TOutput>[] {
|
|
201
|
+
parse(content: string): LogRecord<TInput, TOutput, B>[] {
|
|
99
202
|
const items = content.split('\n')
|
|
100
|
-
const log: LogRecord<TInput, TOutput>[] = []
|
|
203
|
+
const log: LogRecord<TInput, TOutput, B>[] = []
|
|
101
204
|
for (const item of items) {
|
|
102
205
|
if (item !== '') {
|
|
103
|
-
const data = JSON.parse(item) as LogRecord<TInput, TOutput>
|
|
206
|
+
const data = JSON.parse(item) as LogRecord<TInput, TOutput, B>
|
|
104
207
|
log.push(data)
|
|
105
208
|
}
|
|
106
209
|
}
|
|
@@ -137,7 +240,7 @@ export class RecordTape<TInput = unknown[], TOutput = unknown> {
|
|
|
137
240
|
}
|
|
138
241
|
|
|
139
242
|
// Load save functions
|
|
140
|
-
async load(): Promise<LogRecord<TInput, TOutput>[]> {
|
|
243
|
+
async load(): Promise<LogRecord<TInput, TOutput, B>[]> {
|
|
141
244
|
if (typeof this._path === 'undefined') {
|
|
142
245
|
return []
|
|
143
246
|
}
|
|
@@ -167,7 +270,7 @@ export class RecordTape<TInput = unknown[], TOutput = unknown> {
|
|
|
167
270
|
return this._log
|
|
168
271
|
}
|
|
169
272
|
|
|
170
|
-
loadSync(): LogRecord<TInput, TOutput>[] {
|
|
273
|
+
loadSync(): LogRecord<TInput, TOutput, B>[] {
|
|
171
274
|
if (typeof this._path === 'undefined') { return [] }
|
|
172
275
|
|
|
173
276
|
const dirpath = path.dirname(this._path.toString())
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { RecordTape } from '../index'
|
|
2
|
+
import { createTask, Schema, type ExecutionRecord, type TaskRecord } from '@forgehive/task'
|
|
3
|
+
|
|
4
|
+
describe('RecordTape safeRun integration tests', () => {
|
|
5
|
+
it('should record log items directly from safeRun result', async () => {
|
|
6
|
+
// Create a schema
|
|
7
|
+
const schema = new Schema({
|
|
8
|
+
value: Schema.number()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
// Define the boundaries
|
|
12
|
+
const boundaries = {
|
|
13
|
+
fetchData: async (value: number): Promise<number> => {
|
|
14
|
+
return value * 2
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Create the task
|
|
19
|
+
const task = createTask(
|
|
20
|
+
schema,
|
|
21
|
+
boundaries,
|
|
22
|
+
async function ({ value }, { fetchData }) {
|
|
23
|
+
const result = await fetchData(value)
|
|
24
|
+
return { result, success: true }
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
// Create a record tape
|
|
29
|
+
const tape = new RecordTape<{ value: number }, { result: number; success: boolean }, typeof boundaries>()
|
|
30
|
+
|
|
31
|
+
// Run the task with safeRun and directly use the logItem
|
|
32
|
+
const [result, error, record] = await task.safeRun({ value: 5 })
|
|
33
|
+
tape.push('test-task', record)
|
|
34
|
+
|
|
35
|
+
// Verify the execution was successful
|
|
36
|
+
expect(error).toBeNull()
|
|
37
|
+
expect(result).toEqual({ result: 10, success: true })
|
|
38
|
+
|
|
39
|
+
// Get the recorded log from the tape
|
|
40
|
+
const recordedLog = tape.getLog()
|
|
41
|
+
|
|
42
|
+
// Verify the log was recorded correctly
|
|
43
|
+
expect(recordedLog).toHaveLength(1)
|
|
44
|
+
expect(recordedLog[0]).toEqual({
|
|
45
|
+
name: 'test-task',
|
|
46
|
+
type: 'success',
|
|
47
|
+
input: { value: 5 },
|
|
48
|
+
output: { result: 10, success: true },
|
|
49
|
+
boundaries: {
|
|
50
|
+
fetchData: [{
|
|
51
|
+
input: [5],
|
|
52
|
+
output: 10,
|
|
53
|
+
error: null
|
|
54
|
+
}]
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should record log items from safeRun successfully', async () => {
|
|
60
|
+
// Create a schema
|
|
61
|
+
const schema = new Schema({
|
|
62
|
+
value: Schema.number()
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
// Define the boundaries
|
|
66
|
+
const boundaries = {
|
|
67
|
+
fetchData: async (value: number): Promise<number> => {
|
|
68
|
+
return value * 2
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Create the task
|
|
73
|
+
const task = createTask(
|
|
74
|
+
schema,
|
|
75
|
+
boundaries,
|
|
76
|
+
async function ({ value }, { fetchData }) {
|
|
77
|
+
const result = await fetchData(value)
|
|
78
|
+
return { result, success: true }
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
// Create a record tape
|
|
83
|
+
const tape = new RecordTape<{ value: number }, { result: number; success: boolean }, typeof boundaries>()
|
|
84
|
+
|
|
85
|
+
// Add listener to record the log items
|
|
86
|
+
task.addListener((record: TaskRecord<{ value: number }, { result: number; success: boolean }>) => {
|
|
87
|
+
// Manually ensure boundary records have error field for consistency with safeRun
|
|
88
|
+
if (record.boundaries && record.boundaries.fetchData && Array.isArray(record.boundaries.fetchData)) {
|
|
89
|
+
record.boundaries.fetchData = record.boundaries.fetchData.map((entry: any) => ({
|
|
90
|
+
...entry,
|
|
91
|
+
error: entry.error ?? null,
|
|
92
|
+
output: entry.output ?? null
|
|
93
|
+
}))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
tape.addLogItem('test-task', record)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
// Run the task with safeRun
|
|
100
|
+
const [result, error] = await task.safeRun({ value: 5 })
|
|
101
|
+
|
|
102
|
+
// Verify the execution was successful
|
|
103
|
+
expect(error).toBeNull()
|
|
104
|
+
expect(result).toEqual({ result: 10, success: true })
|
|
105
|
+
|
|
106
|
+
// Get the recorded log from the tape
|
|
107
|
+
const recordedLog = tape.getLog()
|
|
108
|
+
|
|
109
|
+
// Verify the log was recorded correctly
|
|
110
|
+
expect(recordedLog).toHaveLength(1)
|
|
111
|
+
expect(recordedLog[0]).toEqual({
|
|
112
|
+
name: 'test-task',
|
|
113
|
+
type: 'success',
|
|
114
|
+
input: { value: 5 },
|
|
115
|
+
output: { result: 10, success: true },
|
|
116
|
+
boundaries: {
|
|
117
|
+
fetchData: [{
|
|
118
|
+
input: [5],
|
|
119
|
+
output: 10,
|
|
120
|
+
error: null
|
|
121
|
+
}]
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('should record error log items from safeRun', async () => {
|
|
127
|
+
// Create a schema
|
|
128
|
+
const schema = new Schema({
|
|
129
|
+
value: Schema.number()
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
// Define the boundaries with a function that will throw an error
|
|
133
|
+
const boundaries = {
|
|
134
|
+
fetchData: async (value: number): Promise<number> => {
|
|
135
|
+
if (value < 0) {
|
|
136
|
+
throw new Error('Value cannot be negative')
|
|
137
|
+
}
|
|
138
|
+
return value * 2
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Create the task
|
|
143
|
+
const task = createTask(
|
|
144
|
+
schema,
|
|
145
|
+
boundaries,
|
|
146
|
+
async function ({ value }, { fetchData }) {
|
|
147
|
+
const result = await fetchData(value)
|
|
148
|
+
return { result, success: true }
|
|
149
|
+
}
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
// Create a record tape
|
|
153
|
+
const tape = new RecordTape<{ value: number }, { result: number; success: boolean }, typeof boundaries>()
|
|
154
|
+
|
|
155
|
+
// Add listener to record the log items
|
|
156
|
+
task.addListener((record: TaskRecord<{ value: number }, { result: number; success: boolean }>) => {
|
|
157
|
+
// Manually ensure boundary records have error field for consistency with safeRun
|
|
158
|
+
if (record.boundaries && record.boundaries.fetchData && Array.isArray(record.boundaries.fetchData)) {
|
|
159
|
+
record.boundaries.fetchData = record.boundaries.fetchData.map((entry: any) => ({
|
|
160
|
+
...entry,
|
|
161
|
+
error: entry.error ?? null,
|
|
162
|
+
output: entry.output ?? null
|
|
163
|
+
}))
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
tape.addLogItem('test-task', record)
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
// Run the task with safeRun with a value that will cause an error
|
|
170
|
+
const [result, error] = await task.safeRun({ value: -5 })
|
|
171
|
+
|
|
172
|
+
// Verify the execution failed as expected
|
|
173
|
+
expect(result).toBeNull()
|
|
174
|
+
expect(error).not.toBeNull()
|
|
175
|
+
expect(error?.message).toContain('Value cannot be negative')
|
|
176
|
+
|
|
177
|
+
// Get the recorded log from the tape
|
|
178
|
+
const recordedLog = tape.getLog()
|
|
179
|
+
|
|
180
|
+
// Verify the error log was recorded correctly
|
|
181
|
+
expect(recordedLog).toHaveLength(1)
|
|
182
|
+
expect(recordedLog[0]).toEqual({
|
|
183
|
+
name: 'test-task',
|
|
184
|
+
type: 'error',
|
|
185
|
+
input: { value: -5 },
|
|
186
|
+
error: 'Value cannot be negative',
|
|
187
|
+
boundaries: {
|
|
188
|
+
fetchData: [{
|
|
189
|
+
input: [-5],
|
|
190
|
+
output: null,
|
|
191
|
+
error: 'Value cannot be negative'
|
|
192
|
+
}]
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
it('should handle error records directly with push', async () => {
|
|
198
|
+
// Create a schema
|
|
199
|
+
const schema = new Schema({
|
|
200
|
+
value: Schema.number()
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
// Define the boundaries with a function that will throw an error
|
|
204
|
+
const boundaries = {
|
|
205
|
+
fetchData: async (value: number): Promise<number> => {
|
|
206
|
+
if (value < 0) {
|
|
207
|
+
throw new Error('Value cannot be negative')
|
|
208
|
+
}
|
|
209
|
+
return value * 2
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Create the task
|
|
214
|
+
const task = createTask(
|
|
215
|
+
schema,
|
|
216
|
+
boundaries,
|
|
217
|
+
async function ({ value }, { fetchData }) {
|
|
218
|
+
const result = await fetchData(value)
|
|
219
|
+
return { result, success: true }
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
// Create a record tape
|
|
224
|
+
const tape = new RecordTape<{ value: number }, { result: number; success: boolean }, typeof boundaries>()
|
|
225
|
+
|
|
226
|
+
// Run the task with safeRun with a value that will cause an error
|
|
227
|
+
const [result, error, record] = await task.safeRun({ value: -5 })
|
|
228
|
+
|
|
229
|
+
// Push the error record directly
|
|
230
|
+
tape.push('test-error', record)
|
|
231
|
+
|
|
232
|
+
// Verify the execution failed as expected
|
|
233
|
+
expect(result).toBeNull()
|
|
234
|
+
expect(error).not.toBeNull()
|
|
235
|
+
expect(error instanceof Error).toBe(true)
|
|
236
|
+
if (error instanceof Error) {
|
|
237
|
+
expect(error.message).toContain('Value cannot be negative')
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Get the recorded log from the tape
|
|
241
|
+
const recordedLog = tape.getLog()
|
|
242
|
+
|
|
243
|
+
// Verify the error log was recorded correctly
|
|
244
|
+
expect(recordedLog).toHaveLength(1)
|
|
245
|
+
expect(recordedLog[0]).toEqual({
|
|
246
|
+
name: 'test-error',
|
|
247
|
+
type: 'error',
|
|
248
|
+
input: { value: -5 },
|
|
249
|
+
error: 'Value cannot be negative',
|
|
250
|
+
boundaries: {
|
|
251
|
+
fetchData: [{
|
|
252
|
+
input: [-5],
|
|
253
|
+
output: null,
|
|
254
|
+
error: 'Value cannot be negative'
|
|
255
|
+
}]
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
it('should handle custom execution records with push', async () => {
|
|
261
|
+
// Create a record tape
|
|
262
|
+
const tape = new RecordTape<{ value: number }, { result: number }, { fetchData: (n: number) => Promise<number> }>()
|
|
263
|
+
|
|
264
|
+
// Create a custom execution record
|
|
265
|
+
const customRecord: ExecutionRecord<{ value: number }, { result: number }, { fetchData: (n: number) => Promise<number> }> = {
|
|
266
|
+
input: { value: 10 },
|
|
267
|
+
output: { result: 20 },
|
|
268
|
+
boundaries: {
|
|
269
|
+
fetchData: [
|
|
270
|
+
{
|
|
271
|
+
input: [10],
|
|
272
|
+
output: 20,
|
|
273
|
+
error: null
|
|
274
|
+
}
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Push the custom record
|
|
280
|
+
tape.push('custom-record', customRecord)
|
|
281
|
+
|
|
282
|
+
// Get the recorded log from the tape
|
|
283
|
+
const recordedLog = tape.getLog()
|
|
284
|
+
|
|
285
|
+
// Verify the log was recorded correctly
|
|
286
|
+
expect(recordedLog).toHaveLength(1)
|
|
287
|
+
expect(recordedLog[0]).toEqual({
|
|
288
|
+
name: 'custom-record',
|
|
289
|
+
type: 'success',
|
|
290
|
+
input: { value: 10 },
|
|
291
|
+
output: { result: 20 },
|
|
292
|
+
boundaries: {
|
|
293
|
+
fetchData: [{
|
|
294
|
+
input: [10],
|
|
295
|
+
output: 20,
|
|
296
|
+
error: null
|
|
297
|
+
}]
|
|
298
|
+
}
|
|
299
|
+
})
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
it('should handle execution records with Promise outputs correctly', async () => {
|
|
303
|
+
// Create a record tape
|
|
304
|
+
const tape = new RecordTape<{ value: number }, { result: number }, { fetchData: (n: number) => Promise<number> }>()
|
|
305
|
+
|
|
306
|
+
// Create a custom execution record with a Promise output
|
|
307
|
+
const promiseResult = Promise.resolve({ result: 30 })
|
|
308
|
+
const promiseRecord: ExecutionRecord<{ value: number }, Promise<{ result: number }>, { fetchData: (n: number) => Promise<number> }> = {
|
|
309
|
+
input: { value: 15 },
|
|
310
|
+
output: promiseResult,
|
|
311
|
+
boundaries: {
|
|
312
|
+
fetchData: [
|
|
313
|
+
{
|
|
314
|
+
input: [15],
|
|
315
|
+
output: 30,
|
|
316
|
+
error: null
|
|
317
|
+
}
|
|
318
|
+
]
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Push the record with Promise output
|
|
323
|
+
tape.push('promise-record', promiseRecord)
|
|
324
|
+
|
|
325
|
+
// Get the recorded log from the tape
|
|
326
|
+
const recordedLog = tape.getLog()
|
|
327
|
+
|
|
328
|
+
// Verify the log was recorded correctly, with Promise output set to null
|
|
329
|
+
expect(recordedLog).toHaveLength(1)
|
|
330
|
+
expect(recordedLog[0]).toEqual({
|
|
331
|
+
name: 'promise-record',
|
|
332
|
+
type: 'success',
|
|
333
|
+
input: { value: 15 },
|
|
334
|
+
output: null, // Promise output should be set to null
|
|
335
|
+
boundaries: {
|
|
336
|
+
fetchData: [{
|
|
337
|
+
input: [15],
|
|
338
|
+
output: 30,
|
|
339
|
+
error: null
|
|
340
|
+
}]
|
|
341
|
+
}
|
|
342
|
+
})
|
|
343
|
+
})
|
|
344
|
+
})
|