@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.
Files changed (100) hide show
  1. package/dist/credentials/credentials.d.ts +6 -0
  2. package/dist/credentials/credentials.js +87 -0
  3. package/dist/credentials/encrypted_yaml_provider.d.ts +2 -0
  4. package/dist/credentials/encrypted_yaml_provider.js +77 -0
  5. package/dist/credentials/encryption.d.ts +3 -0
  6. package/dist/credentials/encryption.js +6 -0
  7. package/dist/credentials/errors.d.ts +13 -0
  8. package/dist/credentials/errors.js +39 -0
  9. package/dist/credentials/index.d.ts +6 -0
  10. package/dist/credentials/index.js +5 -0
  11. package/dist/credentials/init.d.ts +1 -0
  12. package/dist/credentials/init.js +7 -0
  13. package/dist/credentials/paths.d.ts +7 -0
  14. package/dist/credentials/paths.js +14 -0
  15. package/dist/credentials/provider_registry.d.ts +3 -0
  16. package/dist/credentials/provider_registry.js +6 -0
  17. package/dist/credentials/types.d.ts +12 -0
  18. package/dist/credentials/types.js +1 -0
  19. package/package.json +25 -14
  20. package/src/async_storage.d.ts +4 -0
  21. package/src/consts.js +0 -2
  22. package/src/helpers/object.d.ts +2 -0
  23. package/src/hooks/index.d.ts +0 -8
  24. package/src/hooks/index.js +0 -3
  25. package/src/logger/index.d.ts +4 -0
  26. package/src/worker/index.js +3 -1
  27. package/bin/healthcheck.spec.js +0 -90
  28. package/src/bus.spec.js +0 -196
  29. package/src/errors.spec.js +0 -19
  30. package/src/helpers/activity_options.spec.js +0 -55
  31. package/src/helpers/component.spec.js +0 -54
  32. package/src/helpers/error_serializer.spec.js +0 -479
  33. package/src/helpers/errors.spec.js +0 -189
  34. package/src/helpers/fetch.spec.js +0 -292
  35. package/src/helpers/function.spec.js +0 -24
  36. package/src/helpers/object.spec.js +0 -425
  37. package/src/helpers/promise.spec.js +0 -62
  38. package/src/helpers/redact.spec.js +0 -66
  39. package/src/helpers/string.spec.js +0 -99
  40. package/src/helpers/temporal_context.spec.ts +0 -83
  41. package/src/helpers/trace_info.spec.js +0 -45
  42. package/src/helpers/workflow_context.spec.js +0 -46
  43. package/src/hooks/index.spec.js +0 -265
  44. package/src/hooks/pending_hooks.spec.js +0 -62
  45. package/src/interface/evaluator.spec.js +0 -685
  46. package/src/interface/logger.spec.js +0 -172
  47. package/src/interface/step.spec.js +0 -128
  48. package/src/interface/validations/index.spec.js +0 -197
  49. package/src/interface/validations/schemas.spec.js +0 -229
  50. package/src/interface/webhook.spec.js +0 -170
  51. package/src/interface/workflow.spec.js +0 -710
  52. package/src/interface/workflow_utils.spec.js +0 -271
  53. package/src/interface/zod_integration.spec.js +0 -646
  54. package/src/internal_activities/index.spec.js +0 -186
  55. package/src/logger/development.spec.js +0 -87
  56. package/src/logger/index.spec.js +0 -27
  57. package/src/logger/production.spec.js +0 -71
  58. package/src/sdk/helpers/component_metadata.spec.js +0 -30
  59. package/src/sdk/helpers/objects.spec.js +0 -16
  60. package/src/sdk/helpers/path.spec.js +0 -102
  61. package/src/sdk/runtime/context.spec.js +0 -37
  62. package/src/sdk/runtime/events.spec.js +0 -40
  63. package/src/temporal/client.spec.js +0 -124
  64. package/src/tracing/processors/local/index.spec.js +0 -204
  65. package/src/tracing/processors/s3/configs.spec.js +0 -64
  66. package/src/tracing/processors/s3/index.spec.js +0 -185
  67. package/src/tracing/processors/s3/redis_client.spec.js +0 -179
  68. package/src/tracing/processors/s3/s3_client.spec.js +0 -68
  69. package/src/tracing/tools/build_trace_tree.spec.js +0 -216
  70. package/src/tracing/trace_engine.spec.js +0 -299
  71. package/src/worker/bundle.spec.js +0 -53
  72. package/src/worker/bundler_options.spec.js +0 -62
  73. package/src/worker/catalog_workflow/catalog_publisher.spec.js +0 -317
  74. package/src/worker/catalog_workflow/index.spec.js +0 -222
  75. package/src/worker/configs.spec.js +0 -213
  76. package/src/worker/configs_tuner_schema.spec.js +0 -127
  77. package/src/worker/connection_monitor.spec.js +0 -328
  78. package/src/worker/global_functions.spec.js +0 -55
  79. package/src/worker/index.spec.js +0 -526
  80. package/src/worker/interceptors/activity.spec.js +0 -369
  81. package/src/worker/interceptors/headers.spec.js +0 -73
  82. package/src/worker/interceptors/workflow.spec.js +0 -357
  83. package/src/worker/interruption.spec.js +0 -177
  84. package/src/worker/loader/activities.spec.js +0 -212
  85. package/src/worker/loader/hooks.spec.js +0 -64
  86. package/src/worker/loader/matchers.spec.js +0 -140
  87. package/src/worker/loader/tools.spec.js +0 -595
  88. package/src/worker/loader/workflows.spec.js +0 -287
  89. package/src/worker/log_hooks.spec.js +0 -303
  90. package/src/worker/shutdown.spec.js +0 -197
  91. package/src/worker/sinks.spec.js +0 -220
  92. package/src/worker/telemetry.spec.js +0 -80
  93. package/src/worker/temporal_logger.spec.js +0 -90
  94. package/src/worker/webpack_loaders/tools.spec.js +0 -314
  95. package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.spec.js +0 -134
  96. package/src/worker/webpack_loaders/workflow_rewriter/index.spec.js +0 -154
  97. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_activity_calls.spec.js +0 -165
  98. package/src/worker/webpack_loaders/workflow_validator/index.spec.js +0 -202
  99. package/src/worker/webpack_loaders/workflow_validator/npm_workflow_export_resolve.spec.js +0 -374
  100. package/src/worker/worker_runner.spec.js +0 -220
@@ -1,369 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import { ApplicationFailure, CompleteAsyncError } from '@temporalio/common';
3
- import { ActivitySpecialOutput, BusEventType, METADATA_ACCESS_SYMBOL } from '#consts';
4
- import { TransparentFatalError } from '#errors';
5
-
6
- const heartbeatMock = vi.hoisted( () => vi.fn() );
7
- const runWithContextMock = vi.hoisted( () => vi.fn().mockImplementation( async fn => fn() ) );
8
- const activityInfoMock = vi.hoisted( () => ( {
9
- workflowExecution: { workflowId: 'wf-1', runId: 'run-1' },
10
- activityId: 'act-1',
11
- attempt: 1,
12
- activityType: 'myWorkflow#myStep',
13
- workflowType: 'myWorkflow'
14
- } ) );
15
- const traceInfoMock = vi.hoisted( () => ( {
16
- workflowId: 'wf-1',
17
- runId: 'run-1',
18
- workflowType: 'myWorkflow',
19
- startTime: 1710000000000
20
- } ) );
21
- const workflowDetailsMock = vi.hoisted( () => ( {
22
- workflowId: 'wf-1',
23
- runId: 'run-1',
24
- workflowType: 'myWorkflow',
25
- firstExecutionRunId: 'run-1',
26
- startTime: 1710000000000,
27
- runStartTime: 1710000000000,
28
- attempt: 1
29
- } ) );
30
-
31
- vi.mock( '@temporalio/activity', async importOriginal => {
32
- const actual = await importOriginal();
33
- return {
34
- ...actual,
35
- activityInfo: () => activityInfoMock,
36
- Context: {
37
- current: () => ( {
38
- info: activityInfoMock,
39
- heartbeat: heartbeatMock
40
- } )
41
- }
42
- };
43
- } );
44
-
45
- vi.mock( '#async_storage', () => ( {
46
- Storage: {
47
- runWithContext: runWithContextMock
48
- }
49
- } ) );
50
-
51
- const addEventStartMock = vi.fn();
52
- const addEventEndMock = vi.fn();
53
- const addEventErrorMock = vi.fn();
54
- vi.mock( '#tracing', () => ( {
55
- addEventStart: addEventStartMock,
56
- addEventEnd: addEventEndMock,
57
- addEventError: addEventErrorMock
58
- } ) );
59
-
60
- vi.mock( './headers.js', () => ( {
61
- headersToObject: () => ( { traceInfo: traceInfoMock, workflowDetails: workflowDetailsMock } )
62
- } ) );
63
-
64
- const mainEventBusEmitMock = vi.fn();
65
- vi.mock( '#bus', () => ( { mainEventBus: { emit: mainEventBusEmitMock } } ) );
66
-
67
- vi.mock( '../configs.js', () => ( {
68
- get activityHeartbeatEnabled() {
69
- return process.env.OUTPUT_ACTIVITY_HEARTBEAT_ENABLED !== 'false';
70
- },
71
- get activityHeartbeatIntervalMs() {
72
- return parseInt( process.env.OUTPUT_ACTIVITY_HEARTBEAT_INTERVAL_MS || '120000', 10 );
73
- }
74
- } ) );
75
-
76
- const makeActivities = () => ( {
77
- 'myWorkflow#myStep': { [METADATA_ACCESS_SYMBOL]: { type: 'step' } }
78
- } );
79
-
80
- const makeWorkflows = () => [ { name: 'myWorkflow', path: '/workflows/myWorkflow.js' } ];
81
-
82
- const makeInput = () => ( {
83
- args: [ { someInput: 'data' } ],
84
- headers: {}
85
- } );
86
-
87
- describe( 'ActivityExecutionInterceptor', () => {
88
- beforeEach( () => {
89
- vi.clearAllMocks();
90
- activityInfoMock.workflowType = 'myWorkflow';
91
- activityInfoMock.workflowExecution.runId = 'run-1';
92
- activityInfoMock.attempt = 1;
93
- delete activityInfoMock.retryPolicy;
94
- vi.useFakeTimers();
95
- // Default: heartbeat enabled with 50ms interval for fast tests
96
- vi.stubEnv( 'OUTPUT_ACTIVITY_HEARTBEAT_ENABLED', 'true' );
97
- vi.stubEnv( 'OUTPUT_ACTIVITY_HEARTBEAT_INTERVAL_MS', '50' );
98
- } );
99
-
100
- afterEach( () => {
101
- vi.useRealTimers();
102
- vi.unstubAllEnvs();
103
- } );
104
-
105
- it( 'records trace start and end events on successful execution', async () => {
106
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
107
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
108
- const next = vi.fn().mockResolvedValue( { result: 'ok' } );
109
-
110
- await expect( interceptor.execute( makeInput(), next ) ).resolves.toEqual( { result: 'ok' } );
111
- expect( mainEventBusEmitMock ).toHaveBeenCalledWith(
112
- BusEventType.ACTIVITY_START,
113
- { activityInfo: activityInfoMock, workflowDetails: workflowDetailsMock, outputActivityKind: 'step' }
114
- );
115
- expect( mainEventBusEmitMock ).toHaveBeenCalledWith(
116
- BusEventType.ACTIVITY_END,
117
- { activityInfo: activityInfoMock, workflowDetails: workflowDetailsMock, outputActivityKind: 'step' }
118
- );
119
- expect( addEventStartMock ).toHaveBeenCalledWith( {
120
- id: 'run-1:act-1:1',
121
- name: 'myWorkflow#myStep',
122
- kind: 'step',
123
- parentId: 'run-1',
124
- details: { someInput: 'data' },
125
- traceInfo: traceInfoMock
126
- } );
127
- expect( addEventEndMock ).toHaveBeenCalledWith( { id: 'run-1:act-1:1', details: { result: 'ok' }, traceInfo: traceInfoMock } );
128
- expect( addEventErrorMock ).not.toHaveBeenCalled();
129
- expect( runWithContextMock ).toHaveBeenCalledWith(
130
- expect.any( Function ),
131
- expect.objectContaining( {
132
- parentId: 'run-1:act-1:1',
133
- activityInfo: activityInfoMock,
134
- workflowDetails: workflowDetailsMock,
135
- outputActivityKind: 'step',
136
- workflowFilename: '/workflows/myWorkflow.js',
137
- traceInfo: traceInfoMock
138
- } )
139
- );
140
- } );
141
-
142
- it( 'scopes trace ids by attempt so retries do not reuse the same id', async () => {
143
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
144
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
145
- activityInfoMock.attempt = 3;
146
- const next = vi.fn().mockResolvedValue( { result: 'ok' } );
147
-
148
- await expect( interceptor.execute( makeInput(), next ) ).resolves.toEqual( { result: 'ok' } );
149
- expect( addEventStartMock ).toHaveBeenCalledWith( expect.objectContaining( { id: 'run-1:act-1:3', parentId: 'run-1' } ) );
150
- expect( addEventEndMock ).toHaveBeenCalledWith( expect.objectContaining( { id: 'run-1:act-1:3' } ) );
151
- expect( runWithContextMock ).toHaveBeenCalledWith(
152
- expect.any( Function ),
153
- expect.objectContaining( { parentId: 'run-1:act-1:3' } )
154
- );
155
- } );
156
-
157
- it( 'scopes trace ids by run so a child workflow reusing an activityId gets a distinct id', async () => {
158
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
159
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
160
- const next = vi.fn().mockResolvedValue( { result: 'ok' } );
161
-
162
- // Temporal numbers activityIds per run, so a parent and its child both reach the same 'act-1' on attempt 1.
163
- await interceptor.execute( makeInput(), next );
164
- activityInfoMock.workflowExecution.runId = 'run-2';
165
- await interceptor.execute( makeInput(), next );
166
-
167
- expect( addEventStartMock.mock.calls.map( ( [ { id, parentId } ] ) => ( { id, parentId } ) ) ).toEqual( [
168
- { id: 'run-1:act-1:1', parentId: 'run-1' },
169
- { id: 'run-2:act-1:1', parentId: 'run-2' }
170
- ] );
171
- } );
172
-
173
- it( 'wraps native errors with serialized details', async () => {
174
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
175
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
176
- const error = new Error( 'step failed' );
177
- error.code = 'ESTEP';
178
- const next = vi.fn().mockRejectedValue( error );
179
-
180
- const thrown = await interceptor.execute( makeInput(), next ).catch( e => e );
181
-
182
- expect( thrown ).toBeInstanceOf( ApplicationFailure );
183
- expect( thrown ).toMatchObject( {
184
- message: 'step failed',
185
- type: 'Error',
186
- details: [ {
187
- error: {
188
- name: 'Error',
189
- message: 'step failed',
190
- code: 'ESTEP'
191
- }
192
- } ],
193
- cause: error,
194
- nonRetryable: false
195
- } );
196
- expect( mainEventBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_ERROR, {
197
- activityInfo: activityInfoMock,
198
- workflowDetails: workflowDetailsMock,
199
- outputActivityKind: 'step',
200
- error
201
- } );
202
- expect( addEventErrorMock ).toHaveBeenCalledOnce();
203
- expect( addEventEndMock ).not.toHaveBeenCalled();
204
- } );
205
-
206
- it( 'marks inherited configured error types as non-retryable', async () => {
207
- class ValidationError extends Error {}
208
- class SpecificValidationError extends ValidationError {}
209
- activityInfoMock.retryPolicy = { nonRetryableErrorTypes: [ 'ValidationError' ] };
210
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
211
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
212
- const error = new SpecificValidationError( 'invalid input' );
213
- const next = vi.fn().mockRejectedValue( error );
214
-
215
- const thrown = await interceptor.execute( makeInput(), next ).catch( e => e );
216
-
217
- expect( thrown ).toMatchObject( {
218
- type: 'SpecificValidationError',
219
- nonRetryable: true,
220
- cause: error
221
- } );
222
- } );
223
-
224
- it( 'uses a transparent error cause while remaining non-retryable without retry policy metadata', async () => {
225
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
226
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
227
- const cause = new TypeError( 'provider rejected request' );
228
- cause.code = 'EAUTH';
229
- const error = new TransparentFatalError( cause );
230
- const next = vi.fn().mockRejectedValue( error );
231
-
232
- const thrown = await interceptor.execute( makeInput(), next ).catch( e => e );
233
-
234
- expect( thrown ).toMatchObject( {
235
- message: 'provider rejected request',
236
- type: 'TypeError',
237
- nonRetryable: true,
238
- cause,
239
- details: [ {
240
- error: {
241
- name: 'TypeError',
242
- message: 'provider rejected request',
243
- code: 'EAUTH'
244
- }
245
- } ]
246
- } );
247
- expect( addEventErrorMock ).toHaveBeenCalledWith( { id: 'run-1:act-1:1', details: cause, traceInfo: traceInfoMock } );
248
- expect( mainEventBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_ERROR, {
249
- activityInfo: activityInfoMock,
250
- workflowDetails: workflowDetailsMock,
251
- outputActivityKind: 'step',
252
- error: cause
253
- } );
254
- } );
255
-
256
- it( 'rethrows existing Temporal failures unchanged', async () => {
257
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
258
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
259
- const error = ApplicationFailure.nonRetryable( 'domain failed', 'DomainFailure', { reason: 'invalid' } );
260
- const next = vi.fn().mockRejectedValue( error );
261
-
262
- await expect( interceptor.execute( makeInput(), next ) ).rejects.toBe( error );
263
- expect( addEventErrorMock ).toHaveBeenCalledWith( { id: 'run-1:act-1:1', details: error, traceInfo: traceInfoMock } );
264
- expect( mainEventBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_ERROR, {
265
- activityInfo: activityInfoMock,
266
- workflowDetails: workflowDetailsMock,
267
- outputActivityKind: 'step',
268
- error
269
- } );
270
- } );
271
-
272
- it( 'records async completion handoff as a trace end only', async () => {
273
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
274
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
275
- const error = new CompleteAsyncError();
276
- const next = vi.fn().mockRejectedValue( error );
277
-
278
- await expect( interceptor.execute( makeInput(), next ) ).rejects.toBe( error );
279
- expect( mainEventBusEmitMock ).toHaveBeenCalledWith( BusEventType.ACTIVITY_START, expect.any( Object ) );
280
- expect( mainEventBusEmitMock ).toHaveBeenCalledTimes( 1 );
281
- expect( addEventEndMock ).toHaveBeenCalledWith( {
282
- id: 'run-1:act-1:1',
283
- details: ActivitySpecialOutput.ASYNC_HANDOFF,
284
- traceInfo: traceInfoMock
285
- } );
286
- expect( addEventErrorMock ).not.toHaveBeenCalled();
287
- } );
288
-
289
- it( 'sends periodic heartbeats and stops after successful execution', async () => {
290
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
291
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
292
-
293
- const deferred = { resolve: null };
294
- const next = vi.fn().mockImplementation( () => new Promise( r => {
295
- deferred.resolve = r;
296
- } ) );
297
-
298
- const promise = interceptor.execute( makeInput(), next );
299
-
300
- expect( heartbeatMock ).not.toHaveBeenCalled();
301
-
302
- vi.advanceTimersByTime( 50 );
303
- expect( heartbeatMock ).toHaveBeenCalledTimes( 1 );
304
-
305
- vi.advanceTimersByTime( 50 );
306
- expect( heartbeatMock ).toHaveBeenCalledTimes( 2 );
307
-
308
- vi.advanceTimersByTime( 50 );
309
- expect( heartbeatMock ).toHaveBeenCalledTimes( 3 );
310
-
311
- deferred.resolve( { result: 'done' } );
312
- await promise;
313
-
314
- heartbeatMock.mockClear();
315
- vi.advanceTimersByTime( 500 );
316
- expect( heartbeatMock ).not.toHaveBeenCalled();
317
- } );
318
-
319
- it( 'clears heartbeat interval after activity fails', async () => {
320
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
321
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
322
- const next = vi.fn().mockRejectedValue( new Error( 'boom' ) );
323
-
324
- const promise = interceptor.execute( makeInput(), next );
325
- vi.advanceTimersByTime( 0 );
326
- await expect( promise ).rejects.toBeInstanceOf( ApplicationFailure );
327
-
328
- heartbeatMock.mockClear();
329
- vi.advanceTimersByTime( 500 );
330
- expect( heartbeatMock ).not.toHaveBeenCalled();
331
- } );
332
-
333
- it( 'resolves workflow alias in workflowsMap', async () => {
334
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
335
- const workflows = [ { name: 'myWorkflow', path: '/workflows/myWorkflow.js', aliases: [ 'myWorkflowOld' ] } ];
336
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows } );
337
-
338
- activityInfoMock.workflowType = 'myWorkflowOld';
339
- const next = vi.fn().mockResolvedValue( { result: 'ok' } );
340
-
341
- const promise = interceptor.execute( makeInput(), next );
342
- vi.advanceTimersByTime( 0 );
343
- await promise;
344
-
345
- expect( runWithContextMock ).toHaveBeenCalledWith(
346
- expect.any( Function ),
347
- expect.objectContaining( { workflowFilename: '/workflows/myWorkflow.js' } )
348
- );
349
- } );
350
-
351
- it( 'does not heartbeat when OUTPUT_ACTIVITY_HEARTBEAT_ENABLED is false', async () => {
352
- vi.stubEnv( 'OUTPUT_ACTIVITY_HEARTBEAT_ENABLED', 'false' );
353
- const { ActivityExecutionInterceptor } = await import( './activity.js' );
354
- const interceptor = new ActivityExecutionInterceptor( { activities: makeActivities(), workflows: makeWorkflows() } );
355
-
356
- const deferred = { resolve: null };
357
- const next = vi.fn().mockImplementation( () => new Promise( r => {
358
- deferred.resolve = r;
359
- } ) );
360
-
361
- const promise = interceptor.execute( makeInput(), next );
362
-
363
- vi.advanceTimersByTime( 200 );
364
- expect( heartbeatMock ).not.toHaveBeenCalled();
365
-
366
- deferred.resolve( { result: 'done' } );
367
- await promise;
368
- } );
369
- } );
@@ -1,73 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
-
3
- const toPayloadMock = vi.hoisted( () => vi.fn( value => ( { encoded: value } ) ) );
4
- const fromPayloadMock = vi.hoisted( () => vi.fn( payload => payload.encoded ) );
5
-
6
- vi.mock( '@temporalio/common', () => ( {
7
- defaultPayloadConverter: {
8
- toPayload: toPayloadMock,
9
- fromPayload: fromPayloadMock
10
- }
11
- } ) );
12
-
13
- describe( 'headers utils', () => {
14
- beforeEach( () => {
15
- vi.clearAllMocks();
16
- } );
17
-
18
- describe( 'memoToHeaders', () => {
19
- it( 'converts memo entries into Temporal payload headers', async () => {
20
- const { memoToHeaders } = await import( './headers.js' );
21
- const memo = {
22
- traceInfo: { runId: 'run-1' },
23
- workflowDetails: { workflowId: 'workflow-1' }
24
- };
25
-
26
- const headers = memoToHeaders( memo );
27
-
28
- expect( headers ).toEqual( {
29
- traceInfo: { encoded: memo.traceInfo },
30
- workflowDetails: { encoded: memo.workflowDetails }
31
- } );
32
- expect( toPayloadMock ).toHaveBeenCalledTimes( 2 );
33
- expect( toPayloadMock ).toHaveBeenCalledWith( memo.traceInfo );
34
- expect( toPayloadMock ).toHaveBeenCalledWith( memo.workflowDetails );
35
- } );
36
-
37
- it( 'returns an empty object for nullish memo', async () => {
38
- const { memoToHeaders } = await import( './headers.js' );
39
-
40
- expect( memoToHeaders() ).toEqual( {} );
41
- expect( memoToHeaders( null ) ).toEqual( {} );
42
- expect( toPayloadMock ).not.toHaveBeenCalled();
43
- } );
44
- } );
45
-
46
- describe( 'headersToObject', () => {
47
- it( 'converts Temporal payload headers into plain object values', async () => {
48
- const { headersToObject } = await import( './headers.js' );
49
- const headers = {
50
- traceInfo: { encoded: { runId: 'run-1' } },
51
- workflowDetails: { encoded: { workflowId: 'workflow-1' } }
52
- };
53
-
54
- const object = headersToObject( headers );
55
-
56
- expect( object ).toEqual( {
57
- traceInfo: headers.traceInfo.encoded,
58
- workflowDetails: headers.workflowDetails.encoded
59
- } );
60
- expect( fromPayloadMock ).toHaveBeenCalledTimes( 2 );
61
- expect( fromPayloadMock ).toHaveBeenCalledWith( headers.traceInfo );
62
- expect( fromPayloadMock ).toHaveBeenCalledWith( headers.workflowDetails );
63
- } );
64
-
65
- it( 'returns an empty object for nullish headers', async () => {
66
- const { headersToObject } = await import( './headers.js' );
67
-
68
- expect( headersToObject() ).toEqual( {} );
69
- expect( headersToObject( null ) ).toEqual( {} );
70
- expect( fromPayloadMock ).not.toHaveBeenCalled();
71
- } );
72
- } );
73
- } );