@forgehive/record-tape 0.0.3 → 0.1.1

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