@outputai/core 0.14.0 → 0.14.1-next.2947341.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/credentials/credentials.d.ts +6 -0
- package/dist/credentials/credentials.js +87 -0
- package/dist/credentials/encrypted_yaml_provider.d.ts +2 -0
- package/dist/credentials/encrypted_yaml_provider.js +77 -0
- package/dist/credentials/encryption.d.ts +3 -0
- package/dist/credentials/encryption.js +6 -0
- package/dist/credentials/errors.d.ts +13 -0
- package/dist/credentials/errors.js +39 -0
- package/dist/credentials/index.d.ts +6 -0
- package/dist/credentials/index.js +5 -0
- package/dist/credentials/init.d.ts +1 -0
- package/dist/credentials/init.js +7 -0
- package/dist/credentials/paths.d.ts +7 -0
- package/dist/credentials/paths.js +14 -0
- package/dist/credentials/provider_registry.d.ts +3 -0
- package/dist/credentials/provider_registry.js +6 -0
- package/dist/credentials/types.d.ts +12 -0
- package/dist/credentials/types.js +1 -0
- package/package.json +25 -14
- package/src/async_storage.d.ts +4 -0
- package/src/consts.js +0 -2
- package/src/helpers/object.d.ts +2 -0
- package/src/hooks/index.d.ts +0 -8
- package/src/hooks/index.js +0 -3
- package/src/logger/index.d.ts +4 -0
- package/src/worker/index.js +3 -1
- package/bin/healthcheck.spec.js +0 -90
- package/src/bus.spec.js +0 -196
- package/src/errors.spec.js +0 -19
- package/src/helpers/activity_options.spec.js +0 -55
- package/src/helpers/component.spec.js +0 -54
- package/src/helpers/error_serializer.spec.js +0 -479
- package/src/helpers/errors.spec.js +0 -189
- package/src/helpers/fetch.spec.js +0 -292
- package/src/helpers/function.spec.js +0 -24
- package/src/helpers/object.spec.js +0 -425
- package/src/helpers/promise.spec.js +0 -62
- package/src/helpers/redact.spec.js +0 -66
- package/src/helpers/string.spec.js +0 -99
- package/src/helpers/temporal_context.spec.ts +0 -83
- package/src/helpers/trace_info.spec.js +0 -45
- package/src/helpers/workflow_context.spec.js +0 -46
- package/src/hooks/index.spec.js +0 -265
- package/src/hooks/pending_hooks.spec.js +0 -62
- package/src/interface/evaluator.spec.js +0 -685
- package/src/interface/logger.spec.js +0 -172
- package/src/interface/step.spec.js +0 -128
- package/src/interface/validations/index.spec.js +0 -197
- package/src/interface/validations/schemas.spec.js +0 -229
- package/src/interface/webhook.spec.js +0 -170
- package/src/interface/workflow.spec.js +0 -710
- package/src/interface/workflow_utils.spec.js +0 -271
- package/src/interface/zod_integration.spec.js +0 -646
- package/src/internal_activities/index.spec.js +0 -186
- package/src/logger/development.spec.js +0 -87
- package/src/logger/index.spec.js +0 -27
- package/src/logger/production.spec.js +0 -71
- package/src/sdk/helpers/component_metadata.spec.js +0 -30
- package/src/sdk/helpers/objects.spec.js +0 -16
- package/src/sdk/helpers/path.spec.js +0 -102
- package/src/sdk/runtime/context.spec.js +0 -37
- package/src/sdk/runtime/events.spec.js +0 -40
- package/src/temporal/client.spec.js +0 -124
- package/src/tracing/processors/local/index.spec.js +0 -204
- package/src/tracing/processors/s3/configs.spec.js +0 -64
- package/src/tracing/processors/s3/index.spec.js +0 -185
- package/src/tracing/processors/s3/redis_client.spec.js +0 -179
- package/src/tracing/processors/s3/s3_client.spec.js +0 -68
- package/src/tracing/tools/build_trace_tree.spec.js +0 -216
- package/src/tracing/trace_engine.spec.js +0 -299
- package/src/worker/bundle.spec.js +0 -53
- package/src/worker/bundler_options.spec.js +0 -62
- package/src/worker/catalog_workflow/catalog_publisher.spec.js +0 -317
- package/src/worker/catalog_workflow/index.spec.js +0 -222
- package/src/worker/configs.spec.js +0 -213
- package/src/worker/configs_tuner_schema.spec.js +0 -127
- package/src/worker/connection_monitor.spec.js +0 -328
- package/src/worker/global_functions.spec.js +0 -55
- package/src/worker/index.spec.js +0 -526
- package/src/worker/interceptors/activity.spec.js +0 -369
- package/src/worker/interceptors/headers.spec.js +0 -73
- package/src/worker/interceptors/workflow.spec.js +0 -357
- package/src/worker/interruption.spec.js +0 -177
- package/src/worker/loader/activities.spec.js +0 -212
- package/src/worker/loader/hooks.spec.js +0 -64
- package/src/worker/loader/matchers.spec.js +0 -140
- package/src/worker/loader/tools.spec.js +0 -595
- package/src/worker/loader/workflows.spec.js +0 -287
- package/src/worker/log_hooks.spec.js +0 -303
- package/src/worker/shutdown.spec.js +0 -197
- package/src/worker/sinks.spec.js +0 -220
- package/src/worker/telemetry.spec.js +0 -80
- package/src/worker/temporal_logger.spec.js +0 -90
- package/src/worker/webpack_loaders/tools.spec.js +0 -314
- package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.spec.js +0 -134
- package/src/worker/webpack_loaders/workflow_rewriter/index.spec.js +0 -154
- package/src/worker/webpack_loaders/workflow_rewriter/rewrite_activity_calls.spec.js +0 -165
- package/src/worker/webpack_loaders/workflow_validator/index.spec.js +0 -202
- package/src/worker/webpack_loaders/workflow_validator/npm_workflow_export_resolve.spec.js +0 -374
- package/src/worker/worker_runner.spec.js +0 -220
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import type { WorkflowInfo } from '@temporalio/workflow';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { createWorkflowDetails } from './temporal_context.js';
|
|
4
|
-
|
|
5
|
-
/*
|
|
6
|
-
This spec is TypeScript on purpose.
|
|
7
|
-
createWorkflowDetails() accepts a small projection of Temporal's WorkflowInfo,
|
|
8
|
-
so the fixture below uses Pick<WorkflowInfo, ...> to catch Temporal type drift
|
|
9
|
-
without exposing or maintaining the full native object in hook payloads.
|
|
10
|
-
*/
|
|
11
|
-
type WorkflowDetailsSource = Pick<
|
|
12
|
-
WorkflowInfo,
|
|
13
|
-
'attempt' |
|
|
14
|
-
'continuedFromExecutionRunId' |
|
|
15
|
-
'firstExecutionRunId' |
|
|
16
|
-
'parent' |
|
|
17
|
-
'root' |
|
|
18
|
-
'runId' |
|
|
19
|
-
'runStartTime' |
|
|
20
|
-
'startTime' |
|
|
21
|
-
'workflowId' |
|
|
22
|
-
'workflowType'
|
|
23
|
-
>;
|
|
24
|
-
|
|
25
|
-
describe( 'createWorkflowDetails', () => {
|
|
26
|
-
it( 'creates hook-safe workflow details from Temporal workflow info', () => {
|
|
27
|
-
const parent = { workflowId: 'parent-wf', runId: 'parent-run', namespace: 'default' };
|
|
28
|
-
const root = { workflowId: 'root-wf', runId: 'root-run' };
|
|
29
|
-
const workflowInfo = {
|
|
30
|
-
attempt: 2,
|
|
31
|
-
continuedFromExecutionRunId: 'previous-run',
|
|
32
|
-
firstExecutionRunId: 'first-run',
|
|
33
|
-
parent,
|
|
34
|
-
root,
|
|
35
|
-
runId: 'current-run',
|
|
36
|
-
runStartTime: new Date( '2026-06-02T09:30:00.000Z' ),
|
|
37
|
-
startTime: new Date( '2026-06-02T09:00:00.000Z' ),
|
|
38
|
-
workflowId: 'workflow-id',
|
|
39
|
-
workflowType: 'prompt'
|
|
40
|
-
} satisfies WorkflowDetailsSource;
|
|
41
|
-
|
|
42
|
-
expect( createWorkflowDetails( workflowInfo ) ).toEqual( {
|
|
43
|
-
attempt: 2,
|
|
44
|
-
continuedFromExecutionRunId: 'previous-run',
|
|
45
|
-
firstExecutionRunId: 'first-run',
|
|
46
|
-
parent,
|
|
47
|
-
root,
|
|
48
|
-
runId: 'current-run',
|
|
49
|
-
runStartTime: Date.parse( '2026-06-02T09:30:00.000Z' ),
|
|
50
|
-
startTime: Date.parse( '2026-06-02T09:00:00.000Z' ),
|
|
51
|
-
workflowId: 'workflow-id',
|
|
52
|
-
workflowType: 'prompt'
|
|
53
|
-
} );
|
|
54
|
-
} );
|
|
55
|
-
|
|
56
|
-
it( 'preserves absent optional workflow relationships as undefined', () => {
|
|
57
|
-
const workflowInfo = {
|
|
58
|
-
attempt: 1,
|
|
59
|
-
continuedFromExecutionRunId: undefined,
|
|
60
|
-
firstExecutionRunId: 'first-run',
|
|
61
|
-
parent: undefined,
|
|
62
|
-
root: undefined,
|
|
63
|
-
runId: 'current-run',
|
|
64
|
-
runStartTime: new Date( '2026-06-02T09:30:00.000Z' ),
|
|
65
|
-
startTime: new Date( '2026-06-02T09:00:00.000Z' ),
|
|
66
|
-
workflowId: 'workflow-id',
|
|
67
|
-
workflowType: 'prompt'
|
|
68
|
-
} satisfies WorkflowDetailsSource;
|
|
69
|
-
|
|
70
|
-
expect( createWorkflowDetails( workflowInfo ) ).toEqual( {
|
|
71
|
-
attempt: 1,
|
|
72
|
-
continuedFromExecutionRunId: undefined,
|
|
73
|
-
firstExecutionRunId: 'first-run',
|
|
74
|
-
parent: undefined,
|
|
75
|
-
root: undefined,
|
|
76
|
-
runId: 'current-run',
|
|
77
|
-
runStartTime: Date.parse( '2026-06-02T09:30:00.000Z' ),
|
|
78
|
-
startTime: Date.parse( '2026-06-02T09:00:00.000Z' ),
|
|
79
|
-
workflowId: 'workflow-id',
|
|
80
|
-
workflowType: 'prompt'
|
|
81
|
-
} );
|
|
82
|
-
} );
|
|
83
|
-
} );
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { TraceInfo } from './trace_info.js';
|
|
3
|
-
|
|
4
|
-
const inWorkflowContextMock = vi.hoisted( () => vi.fn() );
|
|
5
|
-
const workflowInfoMock = vi.hoisted( () => vi.fn() );
|
|
6
|
-
|
|
7
|
-
vi.mock( '@temporalio/workflow', () => ( {
|
|
8
|
-
inWorkflowContext: inWorkflowContextMock,
|
|
9
|
-
workflowInfo: workflowInfoMock
|
|
10
|
-
} ) );
|
|
11
|
-
|
|
12
|
-
describe( 'TraceInfo', () => {
|
|
13
|
-
beforeEach( () => {
|
|
14
|
-
vi.clearAllMocks();
|
|
15
|
-
} );
|
|
16
|
-
|
|
17
|
-
it( 'builds trace info from Temporal workflow info in workflow context', () => {
|
|
18
|
-
inWorkflowContextMock.mockReturnValue( true );
|
|
19
|
-
workflowInfoMock.mockReturnValue( {
|
|
20
|
-
workflowId: 'workflow-id',
|
|
21
|
-
workflowType: 'workflow-type',
|
|
22
|
-
runId: 'run-id',
|
|
23
|
-
startTime: new Date( '2026-06-02T09:00:00.000Z' )
|
|
24
|
-
} );
|
|
25
|
-
|
|
26
|
-
expect( TraceInfo.build() ).toEqual( {
|
|
27
|
-
workflowId: 'workflow-id',
|
|
28
|
-
workflowType: 'workflow-type',
|
|
29
|
-
runId: 'run-id',
|
|
30
|
-
startTime: Date.parse( '2026-06-02T09:00:00.000Z' )
|
|
31
|
-
} );
|
|
32
|
-
} );
|
|
33
|
-
|
|
34
|
-
it( 'builds trace info without Temporal fields outside workflow context', () => {
|
|
35
|
-
inWorkflowContextMock.mockReturnValue( false );
|
|
36
|
-
|
|
37
|
-
expect( TraceInfo.build() ).toEqual( {
|
|
38
|
-
workflowId: undefined,
|
|
39
|
-
workflowType: undefined,
|
|
40
|
-
runId: undefined,
|
|
41
|
-
startTime: undefined
|
|
42
|
-
} );
|
|
43
|
-
expect( workflowInfoMock ).not.toHaveBeenCalled();
|
|
44
|
-
} );
|
|
45
|
-
} );
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { WorkflowContext } from './workflow_context.js';
|
|
3
|
-
|
|
4
|
-
const inWorkflowContextMock = vi.hoisted( () => vi.fn() );
|
|
5
|
-
const workflowInfoMock = vi.hoisted( () => vi.fn() );
|
|
6
|
-
const continueAsNewMock = vi.hoisted( () => vi.fn() );
|
|
7
|
-
|
|
8
|
-
vi.mock( '@temporalio/workflow', () => ( {
|
|
9
|
-
continueAsNew: continueAsNewMock,
|
|
10
|
-
inWorkflowContext: inWorkflowContextMock,
|
|
11
|
-
workflowInfo: workflowInfoMock
|
|
12
|
-
} ) );
|
|
13
|
-
|
|
14
|
-
describe( 'WorkflowContext', () => {
|
|
15
|
-
beforeEach( () => {
|
|
16
|
-
vi.clearAllMocks();
|
|
17
|
-
} );
|
|
18
|
-
|
|
19
|
-
it( 'builds a test context outside Temporal workflow context', async () => {
|
|
20
|
-
inWorkflowContextMock.mockReturnValue( false );
|
|
21
|
-
|
|
22
|
-
const context = WorkflowContext.build();
|
|
23
|
-
|
|
24
|
-
expect( context.info ).toEqual( { workflowId: 'test-workflow', runId: 'test-run' } );
|
|
25
|
-
expect( context.control.isContinueAsNewSuggested() ).toBe( false );
|
|
26
|
-
await expect( context.control.continueAsNew() ).resolves.toBeUndefined();
|
|
27
|
-
expect( workflowInfoMock ).not.toHaveBeenCalled();
|
|
28
|
-
expect( continueAsNewMock ).not.toHaveBeenCalled();
|
|
29
|
-
} );
|
|
30
|
-
|
|
31
|
-
it( 'builds a workflow context from Temporal workflow info', () => {
|
|
32
|
-
inWorkflowContextMock.mockReturnValue( true );
|
|
33
|
-
workflowInfoMock.mockReturnValue( {
|
|
34
|
-
workflowId: 'workflow-id',
|
|
35
|
-
runId: 'run-id',
|
|
36
|
-
continueAsNewSuggested: true
|
|
37
|
-
} );
|
|
38
|
-
|
|
39
|
-
const context = WorkflowContext.build();
|
|
40
|
-
|
|
41
|
-
expect( context.info ).toEqual( { workflowId: 'workflow-id', runId: 'run-id' } );
|
|
42
|
-
expect( context.control.continueAsNew ).toBe( continueAsNewMock );
|
|
43
|
-
expect( context.control.isContinueAsNewSuggested() ).toBe( true );
|
|
44
|
-
expect( workflowInfoMock ).toHaveBeenCalledTimes( 2 );
|
|
45
|
-
} );
|
|
46
|
-
} );
|
package/src/hooks/index.spec.js
DELETED
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { BusEventType } from '#consts';
|
|
3
|
-
|
|
4
|
-
const logErrorMock = vi.hoisted( () => vi.fn() );
|
|
5
|
-
const createChildLoggerMock = vi.hoisted( () =>
|
|
6
|
-
vi.fn( () => ( { error: logErrorMock } ) )
|
|
7
|
-
);
|
|
8
|
-
const serializeErrorMock = vi.hoisted( () => vi.fn( error => ( {
|
|
9
|
-
name: error.name,
|
|
10
|
-
message: error.message,
|
|
11
|
-
stack: error.stack
|
|
12
|
-
} ) ) );
|
|
13
|
-
|
|
14
|
-
const mainOnHandlers = vi.hoisted( () => ( {} ) );
|
|
15
|
-
const stepOnHandlers = vi.hoisted( () => ( {} ) );
|
|
16
|
-
const mainEventBusMock = vi.hoisted( () => ( {
|
|
17
|
-
on: vi.fn( ( eventType, handler ) => {
|
|
18
|
-
mainOnHandlers[eventType] = handler;
|
|
19
|
-
} )
|
|
20
|
-
} ) );
|
|
21
|
-
const stepEventBusMock = vi.hoisted( () => ( {
|
|
22
|
-
emit: vi.fn( () => true ),
|
|
23
|
-
on: vi.fn( ( eventType, handler ) => {
|
|
24
|
-
stepOnHandlers[eventType] = handler;
|
|
25
|
-
} )
|
|
26
|
-
} ) );
|
|
27
|
-
|
|
28
|
-
vi.mock( '#logger', () => ( { createChildLogger: createChildLoggerMock } ) );
|
|
29
|
-
vi.mock( '#helpers/error_serializer', () => ( { serializeError: serializeErrorMock } ) );
|
|
30
|
-
vi.mock( '#bus', () => ( {
|
|
31
|
-
mainEventBus: mainEventBusMock,
|
|
32
|
-
stepEventBus: stepEventBusMock
|
|
33
|
-
} ) );
|
|
34
|
-
|
|
35
|
-
import {
|
|
36
|
-
emit,
|
|
37
|
-
on,
|
|
38
|
-
onActivityEnd,
|
|
39
|
-
onActivityError,
|
|
40
|
-
onActivityStart,
|
|
41
|
-
onBeforeWorkerStart,
|
|
42
|
-
onError,
|
|
43
|
-
onWorkflowEnd,
|
|
44
|
-
onWorkflowError,
|
|
45
|
-
onWorkflowStart
|
|
46
|
-
} from './index.js';
|
|
47
|
-
import { pendingHooks } from './pending_hooks.js';
|
|
48
|
-
|
|
49
|
-
const workflowDetails = {
|
|
50
|
-
workflowId: 'wf-1',
|
|
51
|
-
runId: 'run-1',
|
|
52
|
-
workflowType: 'myWorkflow',
|
|
53
|
-
firstExecutionRunId: 'run-1',
|
|
54
|
-
startTime: 1710000000000,
|
|
55
|
-
runStartTime: 1710000000000,
|
|
56
|
-
attempt: 1
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const activityInfo = {
|
|
60
|
-
activityId: 'act-1',
|
|
61
|
-
activityType: 'wf#step',
|
|
62
|
-
workflowExecution: { workflowId: 'wf-1', runId: 'run-1' },
|
|
63
|
-
workflowType: 'myWorkflow'
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const eventDate = 1710000001234;
|
|
67
|
-
|
|
68
|
-
describe( 'hooks/index', () => {
|
|
69
|
-
beforeEach( () => {
|
|
70
|
-
vi.clearAllMocks();
|
|
71
|
-
pendingHooks.clear();
|
|
72
|
-
Object.keys( mainOnHandlers ).forEach( k => {
|
|
73
|
-
delete mainOnHandlers[k];
|
|
74
|
-
} );
|
|
75
|
-
Object.keys( stepOnHandlers ).forEach( k => {
|
|
76
|
-
delete stepOnHandlers[k];
|
|
77
|
-
} );
|
|
78
|
-
} );
|
|
79
|
-
|
|
80
|
-
describe( 'onError', () => {
|
|
81
|
-
it( 'registers activity, workflow, and runtime error listeners', () => {
|
|
82
|
-
const handler = vi.fn().mockResolvedValue( undefined );
|
|
83
|
-
onError( handler );
|
|
84
|
-
|
|
85
|
-
expect( mainEventBusMock.on ).toHaveBeenCalledWith( BusEventType.ACTIVITY_ERROR, expect.any( Function ) );
|
|
86
|
-
expect( mainEventBusMock.on ).toHaveBeenCalledWith( BusEventType.WORKFLOW_ERROR, expect.any( Function ) );
|
|
87
|
-
expect( mainEventBusMock.on ).toHaveBeenCalledWith( BusEventType.RUNTIME_ERROR, expect.any( Function ) );
|
|
88
|
-
} );
|
|
89
|
-
|
|
90
|
-
it( 'invokes handler with activity-shaped payload, forwarding bus fields', async () => {
|
|
91
|
-
const handler = vi.fn().mockResolvedValue( undefined );
|
|
92
|
-
onError( handler );
|
|
93
|
-
|
|
94
|
-
const err = new Error( 'act-fail' );
|
|
95
|
-
await mainOnHandlers[BusEventType.ACTIVITY_ERROR]( {
|
|
96
|
-
eventId: 'evt-act-1',
|
|
97
|
-
eventDate,
|
|
98
|
-
activityInfo,
|
|
99
|
-
workflowDetails,
|
|
100
|
-
outputActivityKind: 'step',
|
|
101
|
-
error: err,
|
|
102
|
-
extra: 'passthrough'
|
|
103
|
-
} );
|
|
104
|
-
|
|
105
|
-
expect( handler ).toHaveBeenCalledWith( {
|
|
106
|
-
eventId: 'evt-act-1',
|
|
107
|
-
eventDate,
|
|
108
|
-
source: 'activity',
|
|
109
|
-
activityInfo,
|
|
110
|
-
workflowDetails,
|
|
111
|
-
outputActivityKind: 'step',
|
|
112
|
-
error: err,
|
|
113
|
-
extra: 'passthrough'
|
|
114
|
-
} );
|
|
115
|
-
} );
|
|
116
|
-
|
|
117
|
-
it( 'invokes handler with workflow-shaped payload, forwarding bus fields', async () => {
|
|
118
|
-
const handler = vi.fn().mockResolvedValue( undefined );
|
|
119
|
-
onError( handler );
|
|
120
|
-
|
|
121
|
-
const err = new Error( 'wf-fail' );
|
|
122
|
-
await mainOnHandlers[BusEventType.WORKFLOW_ERROR]( {
|
|
123
|
-
eventId: 'evt-wf-1',
|
|
124
|
-
eventDate,
|
|
125
|
-
workflowDetails,
|
|
126
|
-
error: err,
|
|
127
|
-
extra: 'passthrough'
|
|
128
|
-
} );
|
|
129
|
-
|
|
130
|
-
expect( handler ).toHaveBeenCalledWith( {
|
|
131
|
-
eventId: 'evt-wf-1',
|
|
132
|
-
eventDate,
|
|
133
|
-
source: 'workflow',
|
|
134
|
-
workflowDetails,
|
|
135
|
-
error: err,
|
|
136
|
-
extra: 'passthrough'
|
|
137
|
-
} );
|
|
138
|
-
} );
|
|
139
|
-
|
|
140
|
-
it( 'logs and does not rethrow when handler rejects', async () => {
|
|
141
|
-
const handler = vi.fn().mockRejectedValue( new Error( 'boom' ) );
|
|
142
|
-
onError( handler );
|
|
143
|
-
|
|
144
|
-
const error = new Error( 'rt' );
|
|
145
|
-
await mainOnHandlers[BusEventType.RUNTIME_ERROR]( { eventId: 'evt-rt-1', eventDate, error } );
|
|
146
|
-
|
|
147
|
-
expect( handler ).toHaveBeenCalledWith( { eventId: 'evt-rt-1', eventDate, source: 'runtime', error } );
|
|
148
|
-
expect( logErrorMock ).toHaveBeenCalledWith( 'onError hook error', {
|
|
149
|
-
error: {
|
|
150
|
-
name: 'Error',
|
|
151
|
-
message: 'boom',
|
|
152
|
-
stack: expect.any( String )
|
|
153
|
-
}
|
|
154
|
-
} );
|
|
155
|
-
expect( serializeErrorMock ).toHaveBeenCalledWith( expect.objectContaining( { message: 'boom' } ) );
|
|
156
|
-
} );
|
|
157
|
-
} );
|
|
158
|
-
|
|
159
|
-
describe( 'onBeforeWorkerStart', () => {
|
|
160
|
-
it( 'registers and invokes handler with undefined payload', async () => {
|
|
161
|
-
const handler = vi.fn().mockResolvedValue( undefined );
|
|
162
|
-
onBeforeWorkerStart( handler );
|
|
163
|
-
|
|
164
|
-
expect( mainEventBusMock.on ).toHaveBeenCalledWith( BusEventType.WORKER_BEFORE_START, expect.any( Function ) );
|
|
165
|
-
await mainOnHandlers[BusEventType.WORKER_BEFORE_START]();
|
|
166
|
-
|
|
167
|
-
expect( handler ).toHaveBeenCalledWith( undefined );
|
|
168
|
-
} );
|
|
169
|
-
} );
|
|
170
|
-
|
|
171
|
-
it( 'tracks a hook callback until it settles', async () => {
|
|
172
|
-
const deferred = { resolve: null };
|
|
173
|
-
const handlerPromise = new Promise( resolve => {
|
|
174
|
-
deferred.resolve = resolve;
|
|
175
|
-
} );
|
|
176
|
-
const handler = vi.fn( () => handlerPromise );
|
|
177
|
-
onActivityEnd( handler );
|
|
178
|
-
|
|
179
|
-
const callbackPromise = mainOnHandlers[BusEventType.ACTIVITY_END]( { activityInfo } );
|
|
180
|
-
|
|
181
|
-
expect( pendingHooks.size ).toBe( 1 );
|
|
182
|
-
|
|
183
|
-
deferred.resolve();
|
|
184
|
-
await callbackPromise;
|
|
185
|
-
expect( pendingHooks.size ).toBe( 0 );
|
|
186
|
-
} );
|
|
187
|
-
|
|
188
|
-
describe( 'workflow lifecycle hooks', () => {
|
|
189
|
-
const cases = [
|
|
190
|
-
[ 'onWorkflowStart', onWorkflowStart, BusEventType.WORKFLOW_START, {} ],
|
|
191
|
-
[ 'onWorkflowEnd', onWorkflowEnd, BusEventType.WORKFLOW_END, {} ],
|
|
192
|
-
[ 'onWorkflowError', onWorkflowError, BusEventType.WORKFLOW_ERROR, { error: new Error( 'workflow failed' ) } ]
|
|
193
|
-
];
|
|
194
|
-
|
|
195
|
-
it.each( cases )( '%s forwards bus fields', async ( _name, registerHook, eventType, extraFields ) => {
|
|
196
|
-
const handler = vi.fn().mockResolvedValue( undefined );
|
|
197
|
-
const payload = {
|
|
198
|
-
eventId: 'evt-workflow-1',
|
|
199
|
-
eventDate,
|
|
200
|
-
workflowDetails,
|
|
201
|
-
extra: 'passthrough',
|
|
202
|
-
...extraFields
|
|
203
|
-
};
|
|
204
|
-
registerHook( handler );
|
|
205
|
-
|
|
206
|
-
expect( mainEventBusMock.on ).toHaveBeenCalledWith( eventType, expect.any( Function ) );
|
|
207
|
-
await mainOnHandlers[eventType]( payload );
|
|
208
|
-
|
|
209
|
-
expect( handler ).toHaveBeenCalledWith( payload );
|
|
210
|
-
} );
|
|
211
|
-
} );
|
|
212
|
-
|
|
213
|
-
describe( 'activity lifecycle hooks', () => {
|
|
214
|
-
const cases = [
|
|
215
|
-
[ 'onActivityStart', onActivityStart, BusEventType.ACTIVITY_START, undefined ],
|
|
216
|
-
[ 'onActivityEnd', onActivityEnd, BusEventType.ACTIVITY_END ],
|
|
217
|
-
[ 'onActivityError', onActivityError, BusEventType.ACTIVITY_ERROR, { error: new Error( 'activity failed' ) } ]
|
|
218
|
-
];
|
|
219
|
-
|
|
220
|
-
it.each( cases )( '%s forwards internal activity bus fields', async ( _name, registerHook, eventType, extraFields = {} ) => {
|
|
221
|
-
const handler = vi.fn().mockResolvedValue( undefined );
|
|
222
|
-
const payload = {
|
|
223
|
-
eventId: 'evt-activity-1',
|
|
224
|
-
eventDate,
|
|
225
|
-
activityInfo,
|
|
226
|
-
workflowDetails,
|
|
227
|
-
outputActivityKind: 'internal_step',
|
|
228
|
-
extra: 'passthrough',
|
|
229
|
-
...extraFields
|
|
230
|
-
};
|
|
231
|
-
registerHook( handler );
|
|
232
|
-
|
|
233
|
-
expect( mainEventBusMock.on ).toHaveBeenCalledWith( eventType, expect.any( Function ) );
|
|
234
|
-
await mainOnHandlers[eventType]( payload );
|
|
235
|
-
|
|
236
|
-
expect( handler ).toHaveBeenCalledWith( payload );
|
|
237
|
-
} );
|
|
238
|
-
} );
|
|
239
|
-
|
|
240
|
-
describe( 'on', () => {
|
|
241
|
-
it( 'subscribes to SDK and user event channels and forwards payloads', async () => {
|
|
242
|
-
const handler = vi.fn().mockResolvedValue( undefined );
|
|
243
|
-
on( 'myEvent', handler );
|
|
244
|
-
|
|
245
|
-
expect( stepEventBusMock.on ).toHaveBeenCalledWith( 'sdk:myEvent', expect.any( Function ) );
|
|
246
|
-
expect( stepEventBusMock.on ).toHaveBeenCalledWith( 'usr:myEvent', expect.any( Function ) );
|
|
247
|
-
await stepOnHandlers['sdk:myEvent']( { payload: { source: 'sdk' } } );
|
|
248
|
-
await stepOnHandlers['usr:myEvent']( { payload: { source: 'user' } } );
|
|
249
|
-
|
|
250
|
-
expect( handler ).toHaveBeenNthCalledWith( 1, { payload: { source: 'sdk' } } );
|
|
251
|
-
expect( handler ).toHaveBeenNthCalledWith( 2, { payload: { source: 'user' } } );
|
|
252
|
-
} );
|
|
253
|
-
} );
|
|
254
|
-
|
|
255
|
-
describe( 'emit', () => {
|
|
256
|
-
it( 'emits payloads on the user event channel', () => {
|
|
257
|
-
const payload = { foo: 1 };
|
|
258
|
-
|
|
259
|
-
const emitted = emit( 'myEvent', payload );
|
|
260
|
-
|
|
261
|
-
expect( stepEventBusMock.emit ).toHaveBeenCalledWith( 'usr:myEvent', payload );
|
|
262
|
-
expect( emitted ).toBe( true );
|
|
263
|
-
} );
|
|
264
|
-
} );
|
|
265
|
-
} );
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
|
|
3
|
-
const logMock = vi.hoisted( () => ( { warn: vi.fn() } ) );
|
|
4
|
-
|
|
5
|
-
vi.mock( '#logger', () => ( { createChildLogger: () => logMock } ) );
|
|
6
|
-
|
|
7
|
-
import { flushPendingHooks, pendingHooks } from './pending_hooks.js';
|
|
8
|
-
|
|
9
|
-
describe( 'pending hooks', () => {
|
|
10
|
-
beforeEach( () => {
|
|
11
|
-
pendingHooks.clear();
|
|
12
|
-
vi.clearAllMocks();
|
|
13
|
-
} );
|
|
14
|
-
|
|
15
|
-
afterEach( () => {
|
|
16
|
-
pendingHooks.clear();
|
|
17
|
-
vi.useRealTimers();
|
|
18
|
-
} );
|
|
19
|
-
|
|
20
|
-
it( 'waits for pending hooks to settle', async () => {
|
|
21
|
-
const deferred = { resolve: null };
|
|
22
|
-
const hookPromise = new Promise( resolve => {
|
|
23
|
-
deferred.resolve = resolve;
|
|
24
|
-
} );
|
|
25
|
-
pendingHooks.add( hookPromise );
|
|
26
|
-
|
|
27
|
-
const flushPromise = flushPendingHooks( 5000 );
|
|
28
|
-
const state = { flushed: false };
|
|
29
|
-
flushPromise.then( () => {
|
|
30
|
-
state.flushed = true;
|
|
31
|
-
} );
|
|
32
|
-
|
|
33
|
-
await Promise.resolve();
|
|
34
|
-
expect( state.flushed ).toBe( false );
|
|
35
|
-
|
|
36
|
-
deferred.resolve();
|
|
37
|
-
await flushPromise;
|
|
38
|
-
expect( state.flushed ).toBe( true );
|
|
39
|
-
} );
|
|
40
|
-
|
|
41
|
-
it( 'stops waiting after the timeout', async () => {
|
|
42
|
-
vi.useFakeTimers();
|
|
43
|
-
pendingHooks.add( new Promise( () => {} ) );
|
|
44
|
-
|
|
45
|
-
const flushPromise = flushPendingHooks( 5000 );
|
|
46
|
-
await vi.advanceTimersByTimeAsync( 5000 );
|
|
47
|
-
|
|
48
|
-
await expect( flushPromise ).resolves.toBeUndefined();
|
|
49
|
-
} );
|
|
50
|
-
|
|
51
|
-
it( 'logs the number of hooks that exceeded the timeout', async () => {
|
|
52
|
-
vi.useFakeTimers();
|
|
53
|
-
pendingHooks.add( new Promise( () => {} ) );
|
|
54
|
-
pendingHooks.add( new Promise( () => {} ) );
|
|
55
|
-
|
|
56
|
-
const flushPromise = flushPendingHooks( 5000 );
|
|
57
|
-
await vi.advanceTimersByTimeAsync( 5000 );
|
|
58
|
-
await flushPromise;
|
|
59
|
-
|
|
60
|
-
expect( logMock.warn ).toHaveBeenCalledWith( expect.any( String ), { count: 2 } );
|
|
61
|
-
} );
|
|
62
|
-
} );
|