@aikirun/workflow 0.10.0 → 0.10.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 +5 -5
- package/dist/index.js +73 -35
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { WorkflowName, WorkflowVersionId } from '@aikirun/types/workflow';
|
|
2
2
|
import { Client, Logger, ApiClient } from '@aikirun/types/client';
|
|
3
3
|
import { INTERNAL } from '@aikirun/types/symbols';
|
|
4
|
-
import { Schema } from '@aikirun/types/validator';
|
|
5
4
|
import { WorkflowRun, TerminalWorkflowRunStatus, WorkflowRunState, WorkflowRunId, WorkflowOptions } from '@aikirun/types/workflow-run';
|
|
5
|
+
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
6
6
|
import { DurationObject, Duration } from '@aikirun/types/duration';
|
|
7
7
|
import { SleepResult } from '@aikirun/types/sleep';
|
|
8
8
|
import { EventSendOptions, EventWaitOptions, EventWaitState } from '@aikirun/types/event';
|
|
@@ -138,11 +138,11 @@ type WorkflowRunWaitResult<Status extends TerminalWorkflowRunStatus, Output, Tim
|
|
|
138
138
|
declare function event(): EventDefinition<void>;
|
|
139
139
|
declare function event<Data extends Serializable>(params?: EventParams<Data>): EventDefinition<Data>;
|
|
140
140
|
interface EventParams<Data> {
|
|
141
|
-
schema?:
|
|
141
|
+
schema?: StandardSchemaV1<Data>;
|
|
142
142
|
}
|
|
143
143
|
interface EventDefinition<Data> {
|
|
144
144
|
_type: Data;
|
|
145
|
-
schema?:
|
|
145
|
+
schema?: StandardSchemaV1<Data>;
|
|
146
146
|
}
|
|
147
147
|
type EventsDefinition = Record<string, EventDefinition<unknown>>;
|
|
148
148
|
type EventData<TEventDefinition> = TEventDefinition extends EventDefinition<infer Data> ? Data : never;
|
|
@@ -244,8 +244,8 @@ interface WorkflowVersionParams<Input, Output, AppContext, TEventsDefinition ext
|
|
|
244
244
|
events?: TEventsDefinition;
|
|
245
245
|
opts?: WorkflowOptions;
|
|
246
246
|
schema?: RequireAtLeastOneProp<{
|
|
247
|
-
input?:
|
|
248
|
-
output?:
|
|
247
|
+
input?: StandardSchemaV1<Input>;
|
|
248
|
+
output?: StandardSchemaV1<Output>;
|
|
249
249
|
}>;
|
|
250
250
|
}
|
|
251
251
|
interface WorkflowVersion<Input, Output, AppContext, TEventsDefinition extends EventsDefinition = EventsDefinition> {
|
package/dist/index.js
CHANGED
|
@@ -289,6 +289,7 @@ function getRetryParams(attempts, strategy) {
|
|
|
289
289
|
|
|
290
290
|
// run/event.ts
|
|
291
291
|
import { INTERNAL } from "@aikirun/types/symbols";
|
|
292
|
+
import { SchemaValidationError } from "@aikirun/types/validator";
|
|
292
293
|
import {
|
|
293
294
|
WorkflowRunConflictError,
|
|
294
295
|
WorkflowRunFailedError,
|
|
@@ -325,17 +326,24 @@ function createEventWaiter(handle, eventName, schema, logger) {
|
|
|
325
326
|
logger.debug("Timed out waiting for event");
|
|
326
327
|
return { timeout: true };
|
|
327
328
|
}
|
|
328
|
-
let data;
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
329
|
+
let data = event2.data;
|
|
330
|
+
if (schema) {
|
|
331
|
+
const schemaValidation = schema["~standard"].validate(event2.data);
|
|
332
|
+
const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
|
|
333
|
+
if (!schemaValidationResult.issues) {
|
|
334
|
+
data = schemaValidationResult.value;
|
|
335
|
+
} else {
|
|
336
|
+
logger.error("Invalid event data", { "aiki.issues": schemaValidationResult.issues });
|
|
337
|
+
await handle[INTERNAL].transitionState({
|
|
338
|
+
status: "failed",
|
|
339
|
+
cause: "self",
|
|
340
|
+
error: {
|
|
341
|
+
name: "SchemaValidationError",
|
|
342
|
+
message: JSON.stringify(schemaValidationResult.issues)
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
throw new WorkflowRunFailedError(handle.run.id, handle.run.attempts);
|
|
346
|
+
}
|
|
339
347
|
}
|
|
340
348
|
logger.debug("Event received");
|
|
341
349
|
return { timeout: false, data };
|
|
@@ -382,9 +390,16 @@ function createEventSender(api, workflowRunId, eventName, schema, logger, onSend
|
|
|
382
390
|
send: (...args) => createEventSender(api, workflowRunId, eventName, schema, logger, onSend, optsBuilder.build()).send(...args)
|
|
383
391
|
});
|
|
384
392
|
async function send(...args) {
|
|
385
|
-
const
|
|
393
|
+
const dataRaw = isNonEmptyArray(args) ? args[0] : void 0;
|
|
394
|
+
let data = dataRaw;
|
|
386
395
|
if (schema) {
|
|
387
|
-
schema.
|
|
396
|
+
const schemaValidation = schema["~standard"].validate(dataRaw);
|
|
397
|
+
const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
|
|
398
|
+
if (schemaValidationResult.issues) {
|
|
399
|
+
logger.error("Invalid event data", { "aiki.issues": schemaValidationResult.issues });
|
|
400
|
+
throw new SchemaValidationError("Invalid event data", schemaValidationResult.issues);
|
|
401
|
+
}
|
|
402
|
+
data = schemaValidationResult.value;
|
|
388
403
|
}
|
|
389
404
|
const { run } = await api.workflowRun.sendEventV1({
|
|
390
405
|
id: workflowRunId,
|
|
@@ -426,26 +441,33 @@ function createEventMulticaster(workflowName, workflowVersionId, eventName, sche
|
|
|
426
441
|
)
|
|
427
442
|
});
|
|
428
443
|
async function send(client, runId, ...args) {
|
|
429
|
-
const
|
|
444
|
+
const dataRaw = isNonEmptyArray(args) ? args[0] : void 0;
|
|
445
|
+
let data = dataRaw;
|
|
430
446
|
if (schema) {
|
|
431
|
-
schema.
|
|
447
|
+
const schemaValidation = schema["~standard"].validate(dataRaw);
|
|
448
|
+
const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
|
|
449
|
+
if (schemaValidationResult.issues) {
|
|
450
|
+
client.logger.error("Invalid event data", {
|
|
451
|
+
"aiki.workflowName": workflowName,
|
|
452
|
+
"aiki.workflowVersionId": workflowVersionId,
|
|
453
|
+
"aiki.eventName": eventName,
|
|
454
|
+
"aiki.issues": schemaValidationResult.issues
|
|
455
|
+
});
|
|
456
|
+
throw new SchemaValidationError("Invalid event data", schemaValidationResult.issues);
|
|
457
|
+
}
|
|
458
|
+
data = schemaValidationResult.value;
|
|
432
459
|
}
|
|
433
460
|
const runIds = Array.isArray(runId) ? runId : [runId];
|
|
434
461
|
if (!isNonEmptyArray(runIds)) {
|
|
435
462
|
return;
|
|
436
463
|
}
|
|
437
|
-
const logger = client.logger.child({
|
|
438
|
-
"aiki.workflowName": workflowName,
|
|
439
|
-
"aiki.workflowVersionId": workflowVersionId,
|
|
440
|
-
"aiki.eventName": eventName
|
|
441
|
-
});
|
|
442
464
|
await client.api.workflowRun.multicastEventV1({
|
|
443
465
|
ids: runIds,
|
|
444
466
|
eventName,
|
|
445
467
|
data,
|
|
446
468
|
options
|
|
447
469
|
});
|
|
448
|
-
logger.info("Multicasted event to workflows", {
|
|
470
|
+
client.logger.info("Multicasted event to workflows", {
|
|
449
471
|
"aiki.workflowName": workflowName,
|
|
450
472
|
"aiki.workflowVersionId": workflowVersionId,
|
|
451
473
|
"aiki.workflowRunIds": runIds,
|
|
@@ -721,6 +743,7 @@ function getWorkflowRunPath(name, versionId, referenceId) {
|
|
|
721
743
|
// workflow-version.ts
|
|
722
744
|
import { INTERNAL as INTERNAL5 } from "@aikirun/types/symbols";
|
|
723
745
|
import { TaskFailedError } from "@aikirun/types/task";
|
|
746
|
+
import { SchemaValidationError as SchemaValidationError2 } from "@aikirun/types/validator";
|
|
724
747
|
import {
|
|
725
748
|
WorkflowRunConflictError as WorkflowRunConflictError5,
|
|
726
749
|
WorkflowRunFailedError as WorkflowRunFailedError2,
|
|
@@ -854,7 +877,17 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
854
877
|
}
|
|
855
878
|
async start(client, ...args) {
|
|
856
879
|
const inputRaw = isNonEmptyArray(args) ? args[0] : void 0;
|
|
857
|
-
|
|
880
|
+
let input = inputRaw;
|
|
881
|
+
const schema = this.params.schema?.input;
|
|
882
|
+
if (schema) {
|
|
883
|
+
const schemaValidation = schema["~standard"].validate(inputRaw);
|
|
884
|
+
const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
|
|
885
|
+
if (schemaValidationResult.issues) {
|
|
886
|
+
client.logger.error("Invalid workflow data", { "aiki.issues": schemaValidationResult.issues });
|
|
887
|
+
throw new SchemaValidationError2("Invalid workflow data", schemaValidationResult.issues);
|
|
888
|
+
}
|
|
889
|
+
input = schemaValidationResult.value;
|
|
890
|
+
}
|
|
858
891
|
const { run } = await client.api.workflowRun.createV1({
|
|
859
892
|
name: this.name,
|
|
860
893
|
versionId: this.versionId,
|
|
@@ -873,7 +906,7 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
873
906
|
parentRunHandle[INTERNAL5].assertExecutionAllowed();
|
|
874
907
|
const { client } = parentRunHandle[INTERNAL5];
|
|
875
908
|
const inputRaw = isNonEmptyArray(args) ? args[0] : void 0;
|
|
876
|
-
const input = await this.parse(parentRunHandle, this.params.schema?.input, inputRaw);
|
|
909
|
+
const input = await this.parse(parentRunHandle, this.params.schema?.input, inputRaw, parentRun.logger);
|
|
877
910
|
const inputHash = await hashInput(input);
|
|
878
911
|
const reference = this.params.opts?.reference;
|
|
879
912
|
const path = getWorkflowRunPath(this.name, this.versionId, reference?.id ?? inputHash);
|
|
@@ -888,7 +921,7 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
888
921
|
);
|
|
889
922
|
const { run: existingRun } = await client.api.workflowRun.getByIdV1({ id: existingRunInfo.id });
|
|
890
923
|
if (existingRun.state.status === "completed") {
|
|
891
|
-
await this.parse(parentRunHandle, this.params.schema?.output, existingRun.state.output);
|
|
924
|
+
await this.parse(parentRunHandle, this.params.schema?.output, existingRun.state.output, parentRun.logger);
|
|
892
925
|
}
|
|
893
926
|
const logger2 = parentRun.logger.child({
|
|
894
927
|
"aiki.childWorkflowName": existingRun.name,
|
|
@@ -975,7 +1008,7 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
975
1008
|
while (true) {
|
|
976
1009
|
try {
|
|
977
1010
|
const outputRaw = await this.params.handler(run, input, context);
|
|
978
|
-
const output = await this.parse(handle, this.params.schema?.output, outputRaw);
|
|
1011
|
+
const output = await this.parse(handle, this.params.schema?.output, outputRaw, run.logger);
|
|
979
1012
|
return output;
|
|
980
1013
|
} catch (error) {
|
|
981
1014
|
if (error instanceof WorkflowRunSuspendedError4 || error instanceof WorkflowRunFailedError2 || error instanceof WorkflowRunConflictError5) {
|
|
@@ -1024,20 +1057,25 @@ var WorkflowVersionImpl = class _WorkflowVersionImpl {
|
|
|
1024
1057
|
throw error;
|
|
1025
1058
|
}
|
|
1026
1059
|
}
|
|
1027
|
-
async parse(handle, schema, data) {
|
|
1060
|
+
async parse(handle, schema, data, logger) {
|
|
1028
1061
|
if (!schema) {
|
|
1029
1062
|
return data;
|
|
1030
1063
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
status: "failed",
|
|
1036
|
-
cause: "self",
|
|
1037
|
-
error: createSerializableError(error)
|
|
1038
|
-
});
|
|
1039
|
-
throw new WorkflowRunFailedError2(handle.run.id, handle.run.attempts);
|
|
1064
|
+
const schemaValidation = schema["~standard"].validate(data);
|
|
1065
|
+
const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
|
|
1066
|
+
if (!schemaValidationResult.issues) {
|
|
1067
|
+
return schemaValidationResult.value;
|
|
1040
1068
|
}
|
|
1069
|
+
logger.error("Invalid workflow data", { "aiki.issues": schemaValidationResult.issues });
|
|
1070
|
+
await handle[INTERNAL5].transitionState({
|
|
1071
|
+
status: "failed",
|
|
1072
|
+
cause: "self",
|
|
1073
|
+
error: {
|
|
1074
|
+
name: "SchemaValidationError",
|
|
1075
|
+
message: JSON.stringify(schemaValidationResult.issues)
|
|
1076
|
+
}
|
|
1077
|
+
});
|
|
1078
|
+
throw new WorkflowRunFailedError2(handle.run.id, handle.run.attempts);
|
|
1041
1079
|
}
|
|
1042
1080
|
createFailedState(error) {
|
|
1043
1081
|
if (error instanceof TaskFailedError) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aikirun/workflow",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Workflow SDK for Aiki - define durable workflows with tasks, sleeps, waits, and event handling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"build": "tsup"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@aikirun/types": "0.10.
|
|
21
|
+
"@aikirun/types": "0.10.1",
|
|
22
|
+
"@standard-schema/spec": "^1.1.0"
|
|
22
23
|
},
|
|
23
24
|
"publishConfig": {
|
|
24
25
|
"access": "public"
|