@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createTask, Schema } from '../index'
|
|
2
2
|
|
|
3
3
|
describe('Task safeRun tests', () => {
|
|
4
|
-
it('returns [
|
|
4
|
+
it('returns [result, null, record] on successful execution', async () => {
|
|
5
5
|
// Create a simple schema
|
|
6
6
|
const schema = new Schema({
|
|
7
7
|
value: Schema.number()
|
|
@@ -25,16 +25,23 @@ describe('Task safeRun tests', () => {
|
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
// Call safeRun with valid input
|
|
28
|
-
const [
|
|
28
|
+
const [result, error, record] = await successTask.safeRun({ value: 5 })
|
|
29
29
|
|
|
30
30
|
// Verify success case
|
|
31
31
|
expect(error).toBeNull()
|
|
32
32
|
expect(result).toEqual({ result: 10, success: true })
|
|
33
|
-
expect(
|
|
34
|
-
expect(
|
|
33
|
+
expect(record).not.toBeNull()
|
|
34
|
+
expect(record).toHaveProperty('boundaries.fetchData')
|
|
35
|
+
expect(record.boundaries.fetchData).toHaveLength(1)
|
|
36
|
+
|
|
37
|
+
// useful to check types on record
|
|
38
|
+
const data = record.boundaries.fetchData[0]
|
|
39
|
+
expect(data.input).toEqual([5])
|
|
40
|
+
expect(data.output).toEqual(10)
|
|
41
|
+
expect(data.error).toBeUndefined()
|
|
35
42
|
})
|
|
36
43
|
|
|
37
|
-
it('returns [
|
|
44
|
+
it('returns [null, error, record] on failed execution', async () => {
|
|
38
45
|
// Create a simple schema
|
|
39
46
|
const schema = new Schema({
|
|
40
47
|
value: Schema.number()
|
|
@@ -61,17 +68,26 @@ describe('Task safeRun tests', () => {
|
|
|
61
68
|
)
|
|
62
69
|
|
|
63
70
|
// Call safeRun with problematic input that will cause an error
|
|
64
|
-
const [
|
|
71
|
+
const [result, error, record] = await errorTask.safeRun({ value: -5 })
|
|
65
72
|
|
|
66
73
|
// Verify error case
|
|
67
|
-
expect(error).
|
|
68
|
-
expect(error
|
|
74
|
+
expect(error).not.toBeNull()
|
|
75
|
+
expect(error instanceof Error).toBe(true)
|
|
76
|
+
if (error instanceof Error) {
|
|
77
|
+
expect(error.message).toContain('Value cannot be negative')
|
|
78
|
+
}
|
|
69
79
|
expect(result).toBeNull()
|
|
70
|
-
expect(
|
|
71
|
-
expect(
|
|
80
|
+
expect(record).not.toBeNull()
|
|
81
|
+
expect(record).toHaveProperty('boundaries.fetchData')
|
|
82
|
+
expect(record.boundaries.fetchData).toHaveLength(1)
|
|
83
|
+
|
|
84
|
+
const data = record.boundaries.fetchData[0]
|
|
85
|
+
expect(data.input).toEqual([-5])
|
|
86
|
+
expect(data.error).toContain('Value cannot be negative')
|
|
87
|
+
expect(data.output).toBeUndefined()
|
|
72
88
|
})
|
|
73
89
|
|
|
74
|
-
it('returns [
|
|
90
|
+
it('returns [null, error, record] on schema validation failure', async () => {
|
|
75
91
|
// Create a schema that requires a positive number
|
|
76
92
|
const schema = new Schema({
|
|
77
93
|
value: Schema.number().min(1, 'Value must be positive')
|
|
@@ -95,13 +111,21 @@ describe('Task safeRun tests', () => {
|
|
|
95
111
|
)
|
|
96
112
|
|
|
97
113
|
// Call safeRun with invalid input that will fail schema validation
|
|
98
|
-
const [
|
|
114
|
+
const [result, error, record] = await validationTask.safeRun({ value: 0 })
|
|
99
115
|
|
|
100
116
|
// Verify validation error case
|
|
101
117
|
expect(error).toBeInstanceOf(Error)
|
|
102
|
-
expect(error
|
|
118
|
+
expect(error instanceof Error).toBe(true)
|
|
119
|
+
if (error instanceof Error) {
|
|
120
|
+
expect(error.message).toContain('Value must be positive')
|
|
121
|
+
}
|
|
103
122
|
expect(result).toBeNull()
|
|
104
|
-
expect(
|
|
123
|
+
expect(record).not.toBeNull()
|
|
124
|
+
expect(record.input).toEqual({ value: 0 })
|
|
125
|
+
expect(record.error).toContain('Value must be positive')
|
|
126
|
+
expect(record.boundaries).toEqual({
|
|
127
|
+
fetchData: []
|
|
128
|
+
})
|
|
105
129
|
})
|
|
106
130
|
|
|
107
131
|
it('properly calls the listener with safeRun and run', async () => {
|
|
@@ -145,7 +169,10 @@ describe('Task safeRun tests', () => {
|
|
|
145
169
|
1,
|
|
146
170
|
expect.objectContaining({
|
|
147
171
|
input: { value: 10 },
|
|
148
|
-
output: 20
|
|
172
|
+
output: 20,
|
|
173
|
+
boundaries: {
|
|
174
|
+
fetchData: expect.any(Array)
|
|
175
|
+
}
|
|
149
176
|
})
|
|
150
177
|
)
|
|
151
178
|
|
|
@@ -154,7 +181,10 @@ describe('Task safeRun tests', () => {
|
|
|
154
181
|
2,
|
|
155
182
|
expect.objectContaining({
|
|
156
183
|
input: { value: 20 },
|
|
157
|
-
output: 40
|
|
184
|
+
output: 40,
|
|
185
|
+
boundaries: {
|
|
186
|
+
fetchData: expect.any(Array)
|
|
187
|
+
}
|
|
158
188
|
})
|
|
159
189
|
)
|
|
160
190
|
})
|
|
@@ -187,7 +217,7 @@ describe('Task safeRun tests', () => {
|
|
|
187
217
|
)
|
|
188
218
|
|
|
189
219
|
// Call safeRun
|
|
190
|
-
const [
|
|
220
|
+
const [result, error, record] = await multiBoundaryTask.safeRun({ values: [1, 2, 3] })
|
|
191
221
|
|
|
192
222
|
// Verify success
|
|
193
223
|
expect(error).toBeNull()
|
|
@@ -196,19 +226,16 @@ describe('Task safeRun tests', () => {
|
|
|
196
226
|
total: 12
|
|
197
227
|
})
|
|
198
228
|
|
|
199
|
-
// Verify
|
|
200
|
-
expect(
|
|
201
|
-
expect(
|
|
202
|
-
expect(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
expect(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
expect(boundaryLogs.sumValues).toHaveLength(1)
|
|
211
|
-
// @ts-expect-error - we know the boundaryLogs is not null here
|
|
212
|
-
expect(boundaryLogs.sumValues[0].input).toEqual([[2, 4, 6]])
|
|
229
|
+
// Verify record structure
|
|
230
|
+
expect(record).not.toBeNull()
|
|
231
|
+
expect(record).toHaveProperty('boundaries.doubleValue')
|
|
232
|
+
expect(record).toHaveProperty('boundaries.sumValues')
|
|
233
|
+
|
|
234
|
+
expect(record.boundaries.doubleValue).toHaveLength(3)
|
|
235
|
+
expect(record.boundaries.sumValues).toHaveLength(1)
|
|
236
|
+
expect(record.boundaries.doubleValue[0]).toEqual({ input: [1], output: 2 })
|
|
237
|
+
expect(record.boundaries.doubleValue[1]).toEqual({ input: [2], output: 4 })
|
|
238
|
+
expect(record.boundaries.doubleValue[2]).toEqual({ input: [3], output: 6 })
|
|
239
|
+
expect(record.boundaries.sumValues[0]).toEqual({ input: [[2, 4, 6]], output: 12 })
|
|
213
240
|
})
|
|
214
241
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createTask, Schema, TaskRecord } from '../index'
|
|
1
|
+
import { createTask, Schema, TaskRecord, BoundaryTapeData } from '../index'
|
|
2
2
|
|
|
3
3
|
// Need to add proxy cache mode to the boundaries
|
|
4
4
|
describe('Boundaries tasks tests', () => {
|
|
@@ -316,7 +316,7 @@ describe('Boundaries tasks tests', () => {
|
|
|
316
316
|
return value * externalData
|
|
317
317
|
},
|
|
318
318
|
{
|
|
319
|
-
boundariesData: boundariesData3,
|
|
319
|
+
boundariesData: boundariesData3 as BoundaryTapeData,
|
|
320
320
|
mode: 'proxy-pass'
|
|
321
321
|
}
|
|
322
322
|
)
|
package/src/utils/boundary.ts
CHANGED
|
@@ -14,17 +14,39 @@ export type Mode = 'proxy' | 'proxy-pass' | 'proxy-catch' | 'replay'
|
|
|
14
14
|
export type BoundaryFunction<TReturn = any> = (...args: any[]) => Promise<TReturn>
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Success record for a boundary function call
|
|
18
18
|
* @template TInput - The type of input data
|
|
19
19
|
* @template TOutput - The type of output data
|
|
20
20
|
*/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
error?: string
|
|
21
|
+
export type BoundarySuccessRecord<TInput = unknown[], TOutput = unknown> = {
|
|
22
|
+
input: TInput;
|
|
23
|
+
output: TOutput;
|
|
24
|
+
error?: undefined;
|
|
26
25
|
}
|
|
27
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Error record for a boundary function call
|
|
29
|
+
* @template TInput - The type of input data
|
|
30
|
+
*/
|
|
31
|
+
export type BoundaryErrorRecord<TInput = unknown[]> = {
|
|
32
|
+
input: TInput;
|
|
33
|
+
output?: undefined;
|
|
34
|
+
error: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Represents a record of a boundary function call - either success or error
|
|
39
|
+
* @template TInput - The type of input data
|
|
40
|
+
* @template TOutput - The type of output data
|
|
41
|
+
*/
|
|
42
|
+
export type BoundaryRecord<TInput = unknown[], TOutput = unknown> =
|
|
43
|
+
BoundarySuccessRecord<TInput, TOutput> | BoundaryErrorRecord<TInput>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Represents the tape data for all boundaries
|
|
47
|
+
*/
|
|
48
|
+
export type BoundaryTapeData = Record<string, Array<BoundaryRecord>>;
|
|
49
|
+
|
|
28
50
|
/**
|
|
29
51
|
* Represents a wrapped boundary function with additional methods
|
|
30
52
|
*/
|
|
@@ -79,10 +101,6 @@ export const createBoundary = <Func extends BaseBoundary>(fn: Func): WrappedBoun
|
|
|
79
101
|
return result
|
|
80
102
|
}
|
|
81
103
|
|
|
82
|
-
const record: RecordType = {
|
|
83
|
-
input: args
|
|
84
|
-
}
|
|
85
|
-
|
|
86
104
|
if (mode === 'proxy-pass') {
|
|
87
105
|
const record = findRecord(args, cacheTape)
|
|
88
106
|
|
|
@@ -101,7 +119,8 @@ export const createBoundary = <Func extends BaseBoundary>(fn: Func): WrappedBoun
|
|
|
101
119
|
throw new Error('No tape value for this inputs')
|
|
102
120
|
}
|
|
103
121
|
|
|
104
|
-
if
|
|
122
|
+
// Check if this is an error record by checking if error property exists
|
|
123
|
+
if (record.error !== undefined) {
|
|
105
124
|
throw new Error(record.error)
|
|
106
125
|
}
|
|
107
126
|
|
|
@@ -124,18 +143,26 @@ export const createBoundary = <Func extends BaseBoundary>(fn: Func): WrappedBoun
|
|
|
124
143
|
return prevRecord.output as unknown as ReturnType<Func>
|
|
125
144
|
})()
|
|
126
145
|
} else {
|
|
127
|
-
|
|
146
|
+
// Create an error record
|
|
147
|
+
const errorRecord: BoundaryErrorRecord<FuncInput> = {
|
|
148
|
+
input: args,
|
|
149
|
+
error: error.message
|
|
150
|
+
}
|
|
128
151
|
|
|
129
|
-
if (hasRun) { runLog.push(
|
|
130
|
-
cacheTape.push(
|
|
152
|
+
if (hasRun) { runLog.push(errorRecord) }
|
|
153
|
+
cacheTape.push(errorRecord)
|
|
131
154
|
|
|
132
155
|
throw error
|
|
133
156
|
}
|
|
134
157
|
} else {
|
|
135
|
-
|
|
158
|
+
// Create a success record
|
|
159
|
+
const successRecord: BoundarySuccessRecord<FuncInput, FuncOutput> = {
|
|
160
|
+
input: args,
|
|
161
|
+
output: result as FuncOutput
|
|
162
|
+
}
|
|
136
163
|
|
|
137
|
-
if (hasRun) { runLog.push(
|
|
138
|
-
cacheTape.push(
|
|
164
|
+
if (hasRun) { runLog.push(successRecord) }
|
|
165
|
+
cacheTape.push(successRecord)
|
|
139
166
|
|
|
140
167
|
return result as ReturnType<Func>
|
|
141
168
|
}
|