@output.ai/core 0.0.7 → 0.0.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.
Files changed (30) hide show
  1. package/package.json +7 -3
  2. package/src/configs.js +1 -1
  3. package/src/consts.js +3 -3
  4. package/src/index.d.ts +302 -30
  5. package/src/index.js +3 -2
  6. package/src/interface/metadata.js +3 -3
  7. package/src/interface/step.js +3 -3
  8. package/src/interface/webhook.js +13 -14
  9. package/src/interface/workflow.js +22 -42
  10. package/src/internal_activities/index.js +16 -5
  11. package/src/worker/catalog_workflow/catalog.js +105 -0
  12. package/src/worker/catalog_workflow/index.js +21 -0
  13. package/src/worker/catalog_workflow/index.spec.js +139 -0
  14. package/src/worker/catalog_workflow/workflow.js +13 -0
  15. package/src/worker/index.js +37 -5
  16. package/src/worker/internal_utils.js +54 -0
  17. package/src/worker/internal_utils.spec.js +134 -0
  18. package/src/worker/loader.js +30 -44
  19. package/src/worker/loader.spec.js +68 -0
  20. package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.js +117 -0
  21. package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.spec.js +77 -0
  22. package/src/worker/webpack_loaders/workflow_rewriter/consts.js +3 -0
  23. package/src/worker/webpack_loaders/workflow_rewriter/index.mjs +56 -0
  24. package/src/worker/webpack_loaders/workflow_rewriter/index.spec.js +129 -0
  25. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.js +64 -0
  26. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.spec.js +33 -0
  27. package/src/worker/webpack_loaders/workflow_rewriter/tools.js +225 -0
  28. package/src/worker/webpack_loaders/workflow_rewriter/tools.spec.js +144 -0
  29. package/src/errors.d.ts +0 -3
  30. package/src/worker/temp/__workflows_entrypoint.js +0 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@output.ai/core",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "The core module of the output framework",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -20,13 +20,17 @@
20
20
  "url": "git+https://github.com/growthxai/flow-sdk"
21
21
  },
22
22
  "dependencies": {
23
+ "@babel/generator": "7.26.5",
24
+ "@babel/parser": "7.26.7",
25
+ "@babel/traverse": "7.25.9",
26
+ "@babel/types": "7.26.7",
23
27
  "@temporalio/worker": "1.13.0",
24
- "@temporalio/workflow": "1.13.0",
25
- "undici": "7.15.0"
28
+ "@temporalio/workflow": "1.13.0"
26
29
  },
27
30
  "imports": {
28
31
  "#consts": "./src/consts.js",
29
32
  "#configs": "./src/configs.js",
33
+ "#errors": "./src/errors.js",
30
34
  "#internal_activities": "./src/internal_activities/index.js"
31
35
  }
32
36
  }
package/src/configs.js CHANGED
@@ -5,7 +5,7 @@ export const worker = {
5
5
  maxActivities: 100,
6
6
  maxWorkflows: 100,
7
7
  namespace: process.env.TEMPORAL_NAMESPACE ?? 'default',
8
- taskQueue: process.env.TEMPORAL_TASK_QUEUE ?? 'main'
8
+ taskQueue: process.env.TEMPORAL_TASK_QUEUE
9
9
  };
10
10
 
11
11
  export const api = {
package/src/consts.js CHANGED
@@ -1,3 +1,3 @@
1
- export const nameSymbol = Symbol( '__name' );
2
- export const sendWebhookPostName = '__internal#sendWebhookPost';
3
- export const workflowsIndexFileName = '__workflows_entrypoint.js';
1
+ export const SEND_WEBHOOK_ACTIVITY_NAME = '__internal#sendWebhookPost';
2
+ export const METADATA_ACCESS_SYMBOL = Symbol( '__metadata' );
3
+ export const WORKFLOWS_INDEX_FILENAME = '__workflows_entrypoint.js';
package/src/index.d.ts CHANGED
@@ -1,38 +1,310 @@
1
- export interface StepDefinition<TInput = unknown, TOutput = unknown> {
1
+ // JSON Schema TypeScript type mapping (subset sufficient for IntelliSense)
2
+ type Simplify<T> = { [K in keyof T]: T[K] };
3
+ type EnumValues = readonly ( string | number | boolean | null )[];
4
+
5
+ type JSONSchema = {
6
+ type?: 'string' | 'number' | 'integer' | 'boolean' | 'null' | 'object' | 'array';
7
+ enum?: EnumValues;
8
+ const?: string | number | boolean | null;
9
+ anyOf?: readonly JSONSchema[];
10
+ oneOf?: readonly JSONSchema[];
11
+ allOf?: readonly JSONSchema[];
12
+ // object
13
+ properties?: { [key: string]: JSONSchema };
14
+ required?: readonly string[];
15
+ additionalProperties?: boolean | JSONSchema;
16
+ // array
17
+ items?: JSONSchema | readonly JSONSchema[];
18
+ // ignore $ref & others for typing purposes
19
+ $ref?: string;
20
+ } & Record<string, unknown>;
21
+
22
+ type UnionToIntersection<U> = ( U extends unknown ? ( k: U ) => void : never ) extends ( k: infer I ) => void ? I : never;
23
+
24
+ type FromEnum<S> = S extends { enum: infer E extends EnumValues } ? E[number] : never;
25
+ type FromConst<S> = S extends { const: infer C } ? C : never;
26
+
27
+ type FromPrimitive<S> =
28
+ S extends { type: 'string' } ? string :
29
+ S extends { type: 'number' | 'integer' } ? number :
30
+ S extends { type: 'boolean' } ? boolean :
31
+ S extends { type: 'null' } ? null :
32
+ never;
33
+
34
+ type ObjectProps<S extends JSONSchema> = S extends { properties: infer P extends Record<string, JSONSchema> }
35
+ ? { [K in keyof P]: FromSchema<P[K]> }
36
+ : Record<never, never>;
37
+
38
+ type ObjectRequiredKeys<S extends JSONSchema> = S extends { required: readonly ( infer R )[] }
39
+ ? Extract<R & string, keyof ObjectProps<S>>
40
+ : never;
41
+
42
+ type ObjectFrom<S extends JSONSchema> = Simplify<
43
+ Pick<ObjectProps<S>, ObjectRequiredKeys<S>> &
44
+ Partial<Omit<ObjectProps<S>, ObjectRequiredKeys<S>>>
45
+ >;
46
+
47
+ type ArrayFrom<S extends JSONSchema> = S extends { items: infer I }
48
+ ? I extends readonly unknown[]
49
+ ? FromSchema<I[number]>[]
50
+ : FromSchema<I>[]
51
+ : unknown[];
52
+
53
+ export type FromSchema<S extends JSONSchema> =
54
+ // combinators first
55
+ S extends { anyOf: infer A extends readonly JSONSchema[] } ? FromSchema<A[number]> :
56
+ S extends { oneOf: infer A extends readonly JSONSchema[] } ? FromSchema<A[number]> :
57
+ S extends { allOf: infer A extends readonly JSONSchema[] } ? UnionToIntersection<FromSchema<A[number]>> :
58
+ // enum/const
59
+ FromEnum<S> extends never ? ( FromConst<S> extends never ? (
60
+ // object (explicit or by presence of properties)
61
+ S extends { type: 'object' } | { properties: Record<string, JSONSchema> } ? ObjectFrom<S> :
62
+ // array
63
+ S extends { type: 'array' } ? ArrayFrom<S> :
64
+ // primitives
65
+ FromPrimitive<S> extends never ? unknown : FromPrimitive<S>
66
+ ) : FromConst<S> ) : FromEnum<S>;
67
+
68
+ export type OutputFrom<O extends JSONSchema> = FromSchema<O>;
69
+
70
+ // Utility to strip readonly from inferred types
71
+ /** Recursively removes readonly modifiers from object and array types. */
72
+ type DeepMutable<T> =
73
+ T extends readonly ( infer U )[] ? DeepMutable<U>[] :
74
+ T extends object ? { -readonly [K in keyof T]: DeepMutable<T[K]> } :
75
+ T;
76
+
77
+ /*
78
+ * There is 4 overrides of the "step" function"
79
+ * - with fn receiving input and returning output;
80
+ * - with fn receiving input and returning void;
81
+ * - with fn receiving void and returning outout;
82
+ * - with fn receiving void and returning void;
83
+ */
84
+
85
+ /**
86
+ * @callback StepFn
87
+ * @param {any} input - The input, defined by the inputSchema
88
+ * @returns {any} The output defined by the outputSchema
89
+ */
90
+
91
+ /**
92
+ * Creates logical unit of work, called "step", which will be invoked from workflows.
93
+ *
94
+ * @param {object} options - Step options
95
+ * @param {string} options.name - Human-readable step name (only letters, numbers and "_")
96
+ * @param {string} [options.description] - Description of the step
97
+ * @param {JSONSchema} options.inputSchema - JSON Schema for the fn input, will infer a TS type
98
+ * @param {JSONSchema} options.outputSchema - JSON Schema for the fn output, will infer a TS type
99
+ * @param {StepFn} options.fn - The function logic
100
+ * @returns {StepFn} The options.fn function
101
+ */
102
+ export async function step<
103
+ const InputSchema extends JSONSchema,
104
+ const OutputSchema extends JSONSchema
105
+ >( options: {
106
+ name: string;
107
+ description?: string;
108
+ inputSchema: InputSchema;
109
+ outputSchema: OutputSchema;
110
+ fn: ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<DeepMutable<FromSchema<OutputSchema>>>;
111
+ } ): ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<DeepMutable<FromSchema<OutputSchema>>>;
112
+
113
+ /**
114
+ * @callback InputOnlyStepFn
115
+ * @param {any} input - The input, defined by the inputSchema
116
+ */
117
+
118
+ /**
119
+ * Creates logical unit of work, called "step", which will be invoked from workflows.
120
+ *
121
+ * @param {object} options - Step options
122
+ * @param {string} options.name - Human-readable step name (only letters, numbers and "_")
123
+ * @param {string} [options.description] - Description of the step
124
+ * @param {JSONSchema} options.inputSchema - JSON Schema for the fn input, will infer a TS type
125
+ * @param {InputOnlyStepFn} options.fn - The function logic
126
+ * @returns {InputOnlyStepFn} The options.fn function
127
+ */
128
+ export async function step<
129
+ const InputSchema extends JSONSchema
130
+ >( options: {
131
+ name: string;
132
+ description?: string;
133
+ inputSchema: InputSchema;
134
+ fn: ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<void>;
135
+ } ): ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<void>;
136
+
137
+ /**
138
+ * @callback OutputOnlyStepFn
139
+ * @returns {any} The output defined by the outputSchema
140
+ */
141
+
142
+ /**
143
+ * Creates logical unit of work, called "step", which will be invoked from workflows.
144
+ *
145
+ * @param {object} options - Step options
146
+ * @param {string} options.name - Human-readable step name (only letters, numbers and "_")
147
+ * @param {string} [options.description] - Description of the step
148
+ * @param {JSONSchema} options.outputSchema - JSON Schema for the fn output, will infer a TS type
149
+ * @param {OutputOnlyStepFn} options.fn - The function logic
150
+ * @returns {OutputOnlyStepFn} The options.fn function
151
+ */
152
+ export async function step<
153
+ const OutputSchema extends JSONSchema
154
+ >( options: {
2
155
  name: string;
3
156
  description?: string;
4
- fn: ( input: TInput ) => Promise<TOutput>;
5
- }
6
-
7
- export interface WorkflowContext {
8
- steps: {
9
- [stepName: string]: ( input?: unknown ) => Promise<unknown>;
10
- };
11
- workflowId: string | null;
12
- tools: {
13
- webhook: ( options: {
14
- name: string;
15
- description?: string;
16
- url: string;
17
- payload: object;
18
- } ) => Promise<unknown>;
19
- };
20
- }
21
-
22
- export interface WorkflowDefinition<TInput = unknown, TOutput = unknown> {
157
+ outputSchema: OutputSchema;
158
+ fn: () => Promise<DeepMutable<FromSchema<OutputSchema>>>;
159
+ } ): () => Promise<DeepMutable<FromSchema<OutputSchema>>>;
160
+
161
+ /**
162
+ * @callback VoidStepFn
163
+ */
164
+
165
+ /**
166
+ * Creates logical unit of work, called "step", which will be invoked from workflows.
167
+ *
168
+ * @param {object} options - Step options
169
+ * @param {string} options.name - Human-readable step name (only letters, numbers and "_")
170
+ * @param {string} [options.description] - Description of the step
171
+ * @param {VoidStepFn} options.fn - The function logic
172
+ * @returns {VoidStepFn} The options.fn function
173
+ */
174
+ export async function step( options: {
23
175
  name: string;
24
176
  description?: string;
25
- fn: ( input: TInput, context: WorkflowContext ) => Promise<TOutput>;
26
- }
177
+ fn: () => Promise<void>;
178
+ } ): () => Promise<void>;
179
+
180
+ /*
181
+ * There is 4 overrides of the "workflow" function"
182
+ * - with fn receiving input and returning output;
183
+ * - with fn receiving input and returning void;
184
+ * - with fn receiving void and returning outout;
185
+ * - with fn receiving void and returning void;
186
+ */
187
+
188
+ /**
189
+ * @callback WorkflowFn
190
+ * @param {any} input - The input, defined by the inputSchema
191
+ * @returns {any} The output defined by the outputSchema
192
+ */
193
+
194
+ /**
195
+ * Creates a workflow orchestrator which can invoke steps.
196
+ *
197
+ * @param {object} options - Workflow options
198
+ * @param {string} options.name - Unique workflow name
199
+ * @param {string} [options.description] - Description of the workflow
200
+ * @param {JSONSchema} [options.inputSchema] - JSON Schema for workflow input
201
+ * @param {JSONSchema} [options.outputSchema] - JSON Schema for workflow output
202
+ * @param {WorkflowFn} options.fn - Workflow logic
203
+ * @returns {WorkflowFn} Callable workflow function
204
+ */
205
+ export function workflow<
206
+ const InputSchema extends JSONSchema,
207
+ const OutputSchema extends JSONSchema
208
+ >( options : {
209
+ name: string,
210
+ description?: string,
211
+ inputSchema: InputSchema,
212
+ outputSchema: OutputSchema,
213
+ fn: ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<DeepMutable<FromSchema<OutputSchema>>>
214
+ } ): ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<DeepMutable<FromSchema<OutputSchema>>>;
215
+
216
+ /**
217
+ * @callback InputOnlyWorkflowFn
218
+ * @param {any} input - The input, defined by the inputSchema
219
+ */
220
+
221
+ /**
222
+ * Creates a workflow orchestrator which can invoke steps.
223
+ *
224
+ * @param {object} options - Workflow options
225
+ * @param {string} options.name - Unique workflow name
226
+ * @param {string} [options.description] - Description of the workflow
227
+ * @param {JSONSchema} [options.inputSchema] - JSON Schema for workflow input
228
+ * @param {InputOnlyWorkflowFn} options.fn - Workflow logic
229
+ * @returns {InputOnlyWorkflowFn} Callable workflow function
230
+ */
231
+ export function workflow<
232
+ const InputSchema extends JSONSchema
233
+ >( options : {
234
+ name: string,
235
+ description?: string,
236
+ inputSchema: InputSchema,
237
+ fn: ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<void>
238
+ } ): ( input: DeepMutable<FromSchema<InputSchema>> ) => Promise<void>;
239
+
240
+ /**
241
+ * @callback OutputOnlyWorkflowFn
242
+ * @returns {any} The output defined by the outputSchema
243
+ */
244
+
245
+ /**
246
+ * Creates a workflow orchestrator which can invoke steps.
247
+ *
248
+ * @param {object} options - Workflow options
249
+ * @param {string} options.name - Unique workflow name
250
+ * @param {string} [options.description] - Description of the workflow
251
+ * @param {JSONSchema} [options.outputSchema] - JSON Schema for workflow output
252
+ * @param {OutputOnlyWorkflowFn} options.fn - Workflow logic
253
+ * @returns {OutputOnlyWorkflowFn} Callable workflow function
254
+ */
255
+ export function workflow<
256
+ const OutputSchema extends JSONSchema
257
+ >( options : {
258
+ name: string,
259
+ description?: string,
260
+ outputSchema: OutputSchema,
261
+ fn: () => Promise<DeepMutable<FromSchema<OutputSchema>>>
262
+ } ): () => Promise<DeepMutable<FromSchema<OutputSchema>>>;
263
+
264
+ /**
265
+ * @callback VoidWorkflowFn
266
+ * @param {any} input - The input, defined by the inputSchema
267
+ * @returns {any} The output defined by the outputSchema
268
+ */
27
269
 
28
- export function step<TInput = unknown, TOutput = unknown>(
29
- definition: StepDefinition<TInput, TOutput>
30
- ): ( input: TInput ) => Promise<TOutput>;
270
+ /**
271
+ * Creates a workflow orchestrator which can invoke steps.
272
+ *
273
+ * @param {object} options - Workflow options
274
+ * @param {string} options.name - Unique workflow name
275
+ * @param {string} [options.description] - Description of the workflow
276
+ * @param {VoidWorkflowFn} options.fn - Workflow logic
277
+ * @returns {VoidWorkflowFn} Callable workflow function
278
+ */
279
+ export function workflow( options : {
280
+ name: string,
281
+ description?: string,
282
+ fn: () => Promise<void>
283
+ } ): () => Promise<void>;
31
284
 
32
- export function workflow<TInput = unknown, TOutput = unknown>(
33
- definition: WorkflowDefinition<TInput, TOutput>
34
- ): ( input: TInput ) => Promise<TOutput>;
285
+ /**
286
+ * Create a webhook call that pauses the workflow until resumed via signal.
287
+ *
288
+ * Sends a request via an activity; the workflow will await a corresponding
289
+ * resume signal to continue and return the response payload.
290
+ *
291
+ * @param {object} options - Webhook request options
292
+ * @param {string} options.url - Webhook request url (POST)
293
+ * @param {object} [options.payload] - Webhook request payload
294
+ * @returns {Promise<object>} Resolves with the response payload when resumed
295
+ */
296
+ export function createWebhook( options: { url: string; payload?: object } ): Promise<object>;
35
297
 
36
- export function startWorkflow<TOutput = unknown>( name: string, options?: { input?: TInput } ): Promise<TOutput>;
298
+ /**
299
+ * Error indicating a non-recoverable failure.
300
+ *
301
+ * Use for failures that should not be retried by the workflow runtime.
302
+ */
303
+ export class FatalError extends Error {}
37
304
 
38
- export { FatalError, ValidationError } from './errors.js';
305
+ /**
306
+ * Error indicating invalid input or schema validation issues.
307
+ *
308
+ * Use for problems detected during input validation or contract checks.
309
+ */
310
+ export class ValidationError extends Error {}
package/src/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { step } from './interface/step.js';
2
- import { startWorkflow, workflow } from './interface/workflow.js';
2
+ import { workflow } from './interface/workflow.js';
3
+ import { createWebhook } from './interface/webhook.js';
3
4
  import { FatalError, ValidationError } from './errors.js';
4
5
 
5
- export { step, startWorkflow, workflow, FatalError, ValidationError };
6
+ export { step, workflow, createWebhook, FatalError, ValidationError };
@@ -1,4 +1,4 @@
1
- import { nameSymbol } from '#consts';
1
+ import { METADATA_ACCESS_SYMBOL } from '#consts';
2
2
 
3
- export const setName = ( target, name ) =>
4
- Object.defineProperty( target, nameSymbol, { value: name, writable: false, enumerable: false, configurable: false } );
3
+ export const setMetadata = ( target, values ) =>
4
+ Object.defineProperty( target, METADATA_ACCESS_SYMBOL, { value: values, writable: false, enumerable: false, configurable: false } );
@@ -1,6 +1,6 @@
1
- import { setName } from './metadata.js';
1
+ import { setMetadata } from './metadata.js';
2
2
 
3
- export function step( { name, description: _description, fn } ) {
4
- setName( fn, name );
3
+ export function step( { name, description, inputSchema, outputSchema, fn } ) {
4
+ setMetadata( fn, { name, description, inputSchema, outputSchema } );
5
5
  return fn;
6
6
  };
@@ -1,18 +1,17 @@
1
- import { defineSignal, setHandler } from '@temporalio/workflow';
1
+ // THIS RUNS IN THE TEMPORAL'S SANDBOX ENVIRONMENT
2
+ import { defineSignal, setHandler, proxyActivities, workflowInfo } from '@temporalio/workflow';
3
+ import { SEND_WEBHOOK_ACTIVITY_NAME } from '#consts';
2
4
 
3
- export function createWebhook( workflowId, requestDispatcher ) {
4
- return async function webhook( { name: _name, description: _description, url, payload } ) {
5
- const { error } = await requestDispatcher( { url, workflowId, payload } );
6
- if ( error ) {
7
- throw new Error( 'Webhook call failed' );
8
- }
5
+ export async function createWebhook( { url, payload } ) {
6
+ const workflowId = workflowInfo();
9
7
 
10
- const resumeSignal = defineSignal( 'resume' );
8
+ await proxyActivities( temporalActivityConfigs )[SEND_WEBHOOK_ACTIVITY_NAME]( { url, workflowId, payload } );
11
9
 
12
- return new Promise( resolve => {
13
- setHandler( resumeSignal, responsePayload => {
14
- resolve( responsePayload );
15
- } );
16
- } );
17
- };
10
+ const resumeSignal = defineSignal( 'resume' );
11
+
12
+ return new Promise( resolve =>
13
+ setHandler( resumeSignal, responsePayload => {
14
+ resolve( responsePayload );
15
+ } )
16
+ );
18
17
  };
@@ -1,9 +1,7 @@
1
1
  // THIS RUNS IN THE TEMPORAL'S SANDBOX ENVIRONMENT
2
- import { proxyActivities, IllegalStateError, executeChild, workflowInfo } from '@temporalio/workflow';
2
+ import { proxyActivities, inWorkflowContext, executeChild, workflowInfo } from '@temporalio/workflow';
3
3
  import { getInvocationDir } from './utils.js';
4
- import { createWebhook } from './webhook.js';
5
- import { setName } from './metadata.js';
6
- import { sendWebhookPostName } from '#consts';
4
+ import { setMetadata } from './metadata.js';
7
5
  import { FatalError, ValidationError } from '../errors.js';
8
6
 
9
7
  const temporalActivityConfigs = {
@@ -17,53 +15,35 @@ const temporalActivityConfigs = {
17
15
  }
18
16
  };
19
17
 
20
- export function workflow( { name, description: _description, fn } ) {
18
+ export function workflow( { name, description, inputSchema, outputSchema, fn } ) {
21
19
  const workflowPath = getInvocationDir();
22
20
 
23
- // This wraps the actually function call so before being invoked it creates the activity proxies and export the context
21
+ const steps = proxyActivities( temporalActivityConfigs );
22
+
24
23
  const wrapper = async input => {
25
- try {
26
- const { workflowId } = workflowInfo();
24
+ // this returns a plain function, for example, in unit tests
25
+ if ( !inWorkflowContext() ) { return fn( input ); }
27
26
 
28
- // enrich context information needed for tracking
29
- Object.assign( workflowInfo().memo, { workflowPath } );
27
+ Object.assign( workflowInfo().memo, { workflowPath } );
30
28
 
31
- const proxies = proxyActivities( temporalActivityConfigs );
32
- const context = {
33
- steps: new Proxy( {}, {
34
- get( _target, name ) {
35
- return proxies[`${workflowPath}#${name}`];
36
- }
37
- } ),
38
- tools: {
39
- webhook: createWebhook( workflowId, proxies[sendWebhookPostName] )
40
- }
41
- };
29
+ // call the function with custom context
30
+ return fn.call( {
31
+ invokeStep: async ( stepName, input ) => steps[`${workflowPath}#${stepName}`]( input ),
42
32
 
43
- return fn( input, context );
33
+ startWorkflow: async ( name, input ) => {
34
+ const { memo, workflowId, workflowType } = workflowInfo();
44
35
 
45
- } catch ( error ) {
46
- // IllegalStateError is thrown when temporal is not running and one try to access workflowInfo()
47
- if ( error instanceof IllegalStateError ) {
48
- return fn( input, { steps: null, workflowId: null } );
49
- }
36
+ // Checks if current memo has rootWorkflowId, which means current execution is already a child
37
+ // Then it sets the memory for the child execution passing along who's the original workflow is and its type
38
+ const workflowMemory = memo.rootWorkflowId ?
39
+ { parentWorkflowId: workflowId, rootWorkflowType: memo.rootWorkflowType, rootWorkflowId: memo.rootWorkflowId } :
40
+ { parentWorkflowId: workflowId, rootWorkflowId: workflowId, rootWorkflowType: workflowType };
50
41
 
51
- throw error;
52
- }
42
+ return executeChild( name, { args: input ? [ input ] : [], memo: workflowMemory } );
43
+ }
44
+ }, input );
53
45
  };
54
46
 
55
- setName( wrapper, name );
47
+ setMetadata( wrapper, { name, description, inputSchema, outputSchema } );
56
48
  return wrapper;
57
49
  };
58
-
59
- export async function startWorkflow( name, { input } = {} ) {
60
- const { memo, workflowId, workflowType } = workflowInfo();
61
-
62
- // Checks if current memo has rootWorkflowId, which means current execution is already a child
63
- // Then it sets the memory for the child execution passing along who's the original workflow is and its type
64
- const workflowMemory = memo.rootWorkflowId ?
65
- { parentWorkflowId: workflowId, rootWorkflowType: memo.rootWorkflowType, rootWorkflowId: memo.rootWorkflowId } :
66
- { parentWorkflowId: workflowId, rootWorkflowId: workflowId, rootWorkflowType: workflowType };
67
-
68
- return executeChild( name, { args: input ? [ input ] : [], memo: workflowMemory } );
69
- }
@@ -1,17 +1,28 @@
1
- import { fetch } from 'undici';
2
1
  import { api as apiConfig } from '#configs';
2
+ import { FatalError } from '#errors';
3
3
 
4
- export async function sendWebhookPost( { url, workflowId, payload } ) {
5
- const res = await fetch( url, {
4
+ export const sendWebhookPost = async ( { url, workflowId, payload } ) => {
5
+ const request = fetch( url, {
6
6
  method: 'POST',
7
7
  headers: {
8
8
  'Content-Type': 'application/json',
9
9
  Authentication: `Basic ${apiConfig.authKey}`
10
10
  },
11
- body: JSON.stringify( { workflowId, payload } )
11
+ body: JSON.stringify( { workflowId, payload } ),
12
+ signal: AbortSignal.timeout( 5000 )
12
13
  } );
13
14
 
15
+ const res = await ( async () => {
16
+ try {
17
+ return await request;
18
+ } catch {
19
+ throw new FatalError( 'Webhook fail: timeout' );
20
+ }
21
+ } )();
22
+
14
23
  console.log( '[Core.SendWebhookPost]', res.status, res.statusText );
15
24
 
16
- return { error: !res.ok };
25
+ if ( !res.ok ) {
26
+ throw new FatalError( `Webhook fail: ${res.status}` );
27
+ }
17
28
  };
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Represents the collection of metadata from workflows and activities that a worker has.
3
+ */
4
+ export class Catalog {
5
+ /**
6
+ * All workflows in the catalog
7
+ * @type {Array<CatalogWorkflow>}
8
+ */
9
+ workflows;
10
+
11
+ constructor() {
12
+ this.workflows = [];
13
+ };
14
+
15
+ /**
16
+ * Add a workflow entry to the catalog.
17
+ *
18
+ * @param {CatalogWorkflow} workflow - Workflow to add.
19
+ * @returns {Catalog} This catalog instance (for chaining).
20
+ */
21
+ addWorkflow( workflow ) {
22
+ this.workflows.push( workflow );
23
+ return this;
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Base type for catalog entries (workflows, activities).
29
+ *
30
+ * Encapsulates common descriptive fields and JSON schemas.
31
+ */
32
+ class CatalogEntry {
33
+ /**
34
+ * Name of the entry. Only letters, numbers and _ allowed.
35
+ * @type {string}
36
+ */
37
+ name;
38
+ /**
39
+ * Optional description.
40
+ * @type {string|undefined}
41
+ */
42
+ description;
43
+ /**
44
+ * JSON schema describing the expected input.
45
+ * @type {object}
46
+ */
47
+ inputSchema;
48
+ /**
49
+ * JSON schema describing the produced output.
50
+ * @type {object}
51
+ */
52
+ outputSchema;
53
+ /**
54
+ * Absolute path of the entity in the file system.
55
+ * @type {string}
56
+ */
57
+ path;
58
+
59
+ /**
60
+ * @param {Object} params - Entry parameters.
61
+ * @param {string} params.name - Name of the entry.
62
+ * @param {string} [params.description] - Optional description.
63
+ * @param {object} [params.inputSchema] - JSON schema describing the expected input.
64
+ * @param {object} [params.outputSchema] - JSON schema describing the produced output.
65
+ * @param {string} params.path - Absolute path of the entity in the file system.
66
+ */
67
+ constructor( { name, description, inputSchema, outputSchema, path } ) {
68
+ this.name = name;
69
+ this.description = description;
70
+ this.inputSchema = inputSchema;
71
+ this.outputSchema = outputSchema;
72
+ this.path = path;
73
+ };
74
+ }
75
+
76
+ /**
77
+ * Describes a single workflow within the catalog.
78
+ *
79
+ * @class
80
+ * @extends CatalogEntry
81
+ */
82
+ export class CatalogWorkflow extends CatalogEntry {
83
+ /**
84
+ * Each activity of this workflow.
85
+ * @type {Array<CatalogActivity>}
86
+ */
87
+ activities;
88
+
89
+ /**
90
+ * @inheritdoc
91
+ * @param {Array<CatalogActivity>} params.activities - Activities referenced by this workflow.
92
+ */
93
+ constructor( { activities, ...args } ) {
94
+ super( args );
95
+ this.activities = activities;
96
+ };
97
+ };
98
+
99
+ /**
100
+ * Describes a single activity within a workflow.
101
+ *
102
+ * @class
103
+ * @extends CatalogEntry
104
+ */
105
+ export class CatalogActivity extends CatalogEntry {}