From 3142f6db59efa9a3ba5c395ee7b12202e0c64692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Mendoza=20P=C3=A9rez?= Date: Thu, 22 Jul 2021 22:32:08 +0200 Subject: [PATCH] update to spec main branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Antonio Mendoza PĂ©rez --- README.md | 8 +- examples/browser/index.html | 1 + package-lock.json | 6 + package.json | 2 +- ...lder.ts => defaultconditiondef-builder.ts} | 23 +- src/lib/builders/index.ts | 8 +- ...meout-builder.ts => subflowref-builder.ts} | 18 +- ...{repeat-builder.ts => timeouts-builder.ts} | 18 +- ...er.ts => workflow-exec-timeout-builder.ts} | 23 +- src/lib/definitions/README.md | 2 - src/lib/definitions/action.ts | 32 +- src/lib/definitions/branch.ts | 28 +- src/lib/definitions/callbackstate.ts | 61 +- src/lib/definitions/databasedswitch.ts | 49 +- .../{defaultdef.ts => defaultconditiondef.ts} | 24 +- src/lib/definitions/delaystate.ts | 46 +- src/lib/definitions/end.ts | 8 +- src/lib/definitions/enddatacondition.ts | 8 +- src/lib/definitions/enddeventcondition.ts | 16 +- src/lib/definitions/error.ts | 16 +- src/lib/definitions/eventbasedswitch.ts | 54 +- src/lib/definitions/eventdatafilter.ts | 4 +- src/lib/definitions/eventdef.ts | 15 +- src/lib/definitions/eventref.ts | 4 + src/lib/definitions/events.ts | 18 - src/lib/definitions/eventstate.ts | 55 +- src/lib/definitions/foreachstate.ts | 52 +- src/lib/definitions/function.ts | 8 +- src/lib/definitions/functionref.ts | 7 + src/lib/definitions/injectstate.ts | 42 +- src/lib/definitions/onevents.ts | 13 +- src/lib/definitions/operationstate.ts | 56 +- src/lib/definitions/parallelstate.ts | 66 +- src/lib/definitions/produceeventdef.ts | 4 + src/lib/definitions/repeat.ts | 61 -- src/lib/definitions/schedule.ts | 4 +- src/lib/definitions/specification.ts | 12 +- src/lib/definitions/startdef.ts | 4 +- src/lib/definitions/subflowref.ts | 51 + src/lib/definitions/subflowstate.ts | 123 --- src/lib/definitions/timeouts.ts | 41 + src/lib/definitions/transition.ts | 6 +- .../definitions/transitiondatacondition.ts | 8 +- .../definitions/transitioneventcondition.ts | 16 +- src/lib/definitions/types.ts | 38 +- src/lib/definitions/utils.ts | 265 +++-- src/lib/definitions/workflow.ts | 87 +- ...{exectimeout.ts => workflowExecTimeout.ts} | 18 +- src/lib/schema/__merged.json | 905 ++++++++++-------- src/lib/schema/common.json | 2 +- src/lib/schema/events.json | 7 +- src/lib/schema/functions.json | 7 +- src/lib/schema/retries.json | 2 +- src/lib/schema/secrets.json | 26 + src/lib/schema/timeouts.json | 96 ++ src/lib/schema/types/workflow.ts | 558 ++++++----- src/lib/schema/validation/validators-paths.ts | 93 +- src/lib/schema/workflow.json | 529 +++++----- src/lib/validation/validators-paths.ts | 143 +-- src/lib/validators.ts | 12 +- tests/examples/applicantrequest.json | 111 ++- tests/examples/applicantrequest.spec.ts | 12 +- tests/examples/booklending.json | 261 +++-- tests/examples/booklending.spec.ts | 1 + tests/examples/carauctionbids.json | 91 +- tests/examples/carauctionbids.spec.ts | 3 +- tests/examples/checkcarvitals.json | 115 ++- tests/examples/checkcarvitals.spec.ts | 40 +- tests/examples/jobmonitoring.json | 273 +++--- tests/examples/jobmonitoring.spec.ts | 12 +- tests/examples/parallel.json | 53 +- tests/examples/parallel.spec.ts | 15 +- tests/examples/provisionorder.json | 159 +-- tests/examples/provisionorder.spec.ts | 22 +- tests/examples/sendcloudevent.json | 11 +- tests/examples/sendcloudevent.spec.ts | 1 + tests/examples/solvemathproblems.json | 9 +- tests/examples/solvemathproblems.spec.ts | 1 + tests/lib/builders/eventstate-builder.spec.ts | 13 - .../subflowref.spec.ts} | 16 +- tests/lib/definitions/util.spec.ts | 71 ++ .../workflow-converter-hello-world.json | 1 + .../workflow-converter-hello-world.yaml | 1 + .../workflow-converter-hello-world.yml | 1 + tests/lib/definitions/workflow.spec.ts | 42 +- tests/lib/workflow-validator.spec.ts | 2 + tools/consts.ts | 3 +- 87 files changed, 2993 insertions(+), 2256 deletions(-) rename src/lib/builders/{subflowstate-builder.ts => defaultconditiondef-builder.ts} (59%) rename src/lib/builders/{exectimeout-builder.ts => subflowref-builder.ts} (63%) rename src/lib/builders/{repeat-builder.ts => timeouts-builder.ts} (65%) rename src/lib/builders/{defaultdef-builder.ts => workflow-exec-timeout-builder.ts} (59%) delete mode 100644 src/lib/definitions/README.md rename src/lib/definitions/{defaultdef.ts => defaultconditiondef.ts} (72%) delete mode 100644 src/lib/definitions/events.ts delete mode 100644 src/lib/definitions/repeat.ts create mode 100644 src/lib/definitions/subflowref.ts delete mode 100644 src/lib/definitions/subflowstate.ts create mode 100644 src/lib/definitions/timeouts.ts rename src/lib/definitions/{exectimeout.ts => workflowExecTimeout.ts} (70%) create mode 100644 src/lib/schema/secrets.json create mode 100644 src/lib/schema/timeouts.json rename tests/lib/{builders/subflow-builder.spec.ts => definitions/subflowref.spec.ts} (68%) create mode 100644 tests/lib/definitions/util.spec.ts diff --git a/README.md b/README.md index 5e07f7b..d1a5a6a 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ import { workflowBuilder, injectstateBuilder, Specification } from '@severlesswo const workflow: Specification.Workflow = workflowBuilder() .id("helloworld") + .specVersion("0.7") .version("1.0") .name("Hello World Workflow") .description("Inject Hello World") @@ -70,6 +71,7 @@ import { Specification, Workflow } from '@severlessworkflow/sdk-typescript'; const source = `id: helloworld version: '1.0' +specVerion: '0.7' name: Hello World Workflow description: Inject Hello World start: Hello State @@ -94,6 +96,7 @@ import { workflowBuilder, injectstateBuilder, Specification } from '@severlesswo const workflow: Specification.Workflow = workflowBuilder() .id("helloworld") .version("1.0") + .specVersion("0.7") .name("Hello World Workflow") .description("Inject Hello World") .start("Hello State") @@ -153,9 +156,10 @@ const workflow: Specification.Workflow = { } as Specification.Injectstate ] }; + const workflowValidator: WorkflowValidator = new WorkflowValidator(workflow); -if (!workflowValidator.validate()) { - workflowValidator.errors.forEach(error => console.error(error.message)); +if (!workflowValidator.isValid) { + workflowValidator.errors.forEach(error => console.error((error as ValidationError).message)); } ``` diff --git a/examples/browser/index.html b/examples/browser/index.html index 6000a1d..3aea110 100644 --- a/examples/browser/index.html +++ b/examples/browser/index.html @@ -19,6 +19,7 @@ const workflow = workflowBuilder() .id("helloworld") .version("1.0") + .specVersion("0.7") .name("Hello World Workflow") .description("Inject Hello World") .start("Hello State") diff --git a/package-lock.json b/package-lock.json index d5df753..f45ad78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2225,6 +2225,9 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, + "dependencies": { + "graceful-fs": "^4.1.6" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -3163,6 +3166,9 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.47.0.tgz", "integrity": "sha512-rqBjgq9hQfW0vRmz+0S062ORRNJXvwRpzxhFXORvar/maZqY6za3rgQ/p1Glg+j1hnc1GtYyQCPiAei95uTElg==", "dev": true, + "dependencies": { + "fsevents": "~2.3.1" + }, "bin": { "rollup": "dist/bin/rollup" }, diff --git a/package.json b/package.json index 4e3e0b1..ca56a35 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@severlessworkflow/sdk-typescript", "version": "2.0.0", - "schemaVersion": "0.6", + "schemaVersion": "0.7", "description": "Typescript SDK for Serverless Workflow Specification", "main": "umd/index.umd.min.js", "browser": "umd/index.umd.min.js", diff --git a/src/lib/builders/subflowstate-builder.ts b/src/lib/builders/defaultconditiondef-builder.ts similarity index 59% rename from src/lib/builders/subflowstate-builder.ts rename to src/lib/builders/defaultconditiondef-builder.ts index a08e6ba..81a1a84 100644 --- a/src/lib/builders/subflowstate-builder.ts +++ b/src/lib/builders/defaultconditiondef-builder.ts @@ -17,28 +17,27 @@ import { Builder, builder } from '../builder'; import { Specification } from '../definitions'; import { validate } from '../utils'; -import { setEndValueIfNoTransition } from '../definitions/utils'; /** * The internal function used by the builder proxy to validate and return its underlying object - * @param {Specification.Subflowstate} data The underlying object - * @returns {Specification.Subflowstate} The validated underlying object + * @param {Specification.Defaultconditiondef} data The underlying object + * @returns {Specification.Defaultconditiondef} The validated underlying object */ -function subflowstateBuildingFn(data: Specification.Subflowstate): () => Specification.Subflowstate { +function defaultconditiondefBuildingFn( + data: Specification.Defaultconditiondef +): () => Specification.Defaultconditiondef { return () => { - const model = new Specification.Subflowstate(data); + const model = new Specification.Defaultconditiondef(data); - setEndValueIfNoTransition(model); - - validate('Subflowstate', model); + validate('Defaultconditiondef', model); return model; }; } /** - * A factory to create a builder proxy for the type `Specification.Subflowstate` - * @returns {Specification.Subflowstate} A builder for `Specification.Subflowstate` + * A factory to create a builder proxy for the type `Specification.Defaultconditiondef` + * @returns {Specification.Defaultconditiondef} A builder for `Specification.Defaultconditiondef` */ -export function subflowstateBuilder(): Builder { - return builder(subflowstateBuildingFn); +export function defaultconditiondefBuilder(): Builder { + return builder(defaultconditiondefBuildingFn); } diff --git a/src/lib/builders/index.ts b/src/lib/builders/index.ts index 2f6025b..600d8d0 100644 --- a/src/lib/builders/index.ts +++ b/src/lib/builders/index.ts @@ -22,7 +22,7 @@ export * from './callbackstate-builder'; export * from './correlation-def-builder'; export * from './crondef-builder'; export * from './databasedswitch-builder'; -export * from './defaultdef-builder'; +export * from './defaultconditiondef-builder'; export * from './delaystate-builder'; export * from './end-builder'; export * from './enddatacondition-builder'; @@ -33,7 +33,6 @@ export * from './eventdatafilter-builder'; export * from './eventdef-builder'; export * from './eventref-builder'; export * from './eventstate-builder'; -export * from './exectimeout-builder'; export * from './foreachstate-builder'; export * from './function-builder'; export * from './functionref-builder'; @@ -43,12 +42,13 @@ export * from './onevents-builder'; export * from './operationstate-builder'; export * from './parallelstate-builder'; export * from './produceeventdef-builder'; -export * from './repeat-builder'; export * from './retrydef-builder'; export * from './schedule-builder'; export * from './startdef-builder'; export * from './statedatafilter-builder'; -export * from './subflowstate-builder'; +export * from './subflowref-builder'; +export * from './timeouts-builder'; export * from './transition-builder'; export * from './transitiondatacondition-builder'; export * from './transitioneventcondition-builder'; +export * from './workflow-exec-timeout-builder'; diff --git a/src/lib/builders/exectimeout-builder.ts b/src/lib/builders/subflowref-builder.ts similarity index 63% rename from src/lib/builders/exectimeout-builder.ts rename to src/lib/builders/subflowref-builder.ts index 9e2ade8..d2cffce 100644 --- a/src/lib/builders/exectimeout-builder.ts +++ b/src/lib/builders/subflowref-builder.ts @@ -20,22 +20,22 @@ import { validate } from '../utils'; /** * The internal function used by the builder proxy to validate and return its underlying object - * @param {Specification.Exectimeout} data The underlying object - * @returns {Specification.Exectimeout} The validated underlying object + * @param {Specification.Subflowref} data The underlying object + * @returns {Specification.Subflowref} The validated underlying object */ -function exectimeoutBuildingFn(data: Specification.Exectimeout): () => Specification.Exectimeout { +function subflowrefBuildingFn(data: Specification.Subflowref): () => Specification.Subflowref { return () => { - const model = new Specification.Exectimeout(data); + const model = new Specification.Subflowref(data); - validate('Exectimeout', model); + validate('Subflowref', model); return model; }; } /** - * A factory to create a builder proxy for the type `Specification.Exectimeout` - * @returns {Specification.Exectimeout} A builder for `Specification.Exectimeout` + * A factory to create a builder proxy for the type `Specification.Subflowref` + * @returns {Specification.Subflowref} A builder for `Specification.Subflowref` */ -export function exectimeoutBuilder(): Builder { - return builder(exectimeoutBuildingFn); +export function subflowrefBuilder(): Builder { + return builder(subflowrefBuildingFn); } diff --git a/src/lib/builders/repeat-builder.ts b/src/lib/builders/timeouts-builder.ts similarity index 65% rename from src/lib/builders/repeat-builder.ts rename to src/lib/builders/timeouts-builder.ts index 512f1a8..e124235 100644 --- a/src/lib/builders/repeat-builder.ts +++ b/src/lib/builders/timeouts-builder.ts @@ -20,22 +20,22 @@ import { validate } from '../utils'; /** * The internal function used by the builder proxy to validate and return its underlying object - * @param {Specification.Repeat} data The underlying object - * @returns {Specification.Repeat} The validated underlying object + * @param {Specification.Timeouts} data The underlying object + * @returns {Specification.Timeouts} The validated underlying object */ -function repeatBuildingFn(data: Specification.Repeat): () => Specification.Repeat { +function timeoutsBuildingFn(data: Specification.Timeouts): () => Specification.Timeouts { return () => { - const model = new Specification.Repeat(data); + const model = new Specification.Timeouts(data); - validate('Repeat', model); + validate('Timeouts', model); return model; }; } /** - * A factory to create a builder proxy for the type `Specification.Repeat` - * @returns {Specification.Repeat} A builder for `Specification.Repeat` + * A factory to create a builder proxy for the type `Specification.Timeouts` + * @returns {Specification.Timeouts} A builder for `Specification.Timeouts` */ -export function repeatBuilder(): Builder { - return builder(repeatBuildingFn); +export function timeoutsBuilder(): Builder { + return builder(timeoutsBuildingFn); } diff --git a/src/lib/builders/defaultdef-builder.ts b/src/lib/builders/workflow-exec-timeout-builder.ts similarity index 59% rename from src/lib/builders/defaultdef-builder.ts rename to src/lib/builders/workflow-exec-timeout-builder.ts index 18e5418..9e7d613 100644 --- a/src/lib/builders/defaultdef-builder.ts +++ b/src/lib/builders/workflow-exec-timeout-builder.ts @@ -17,28 +17,27 @@ import { Builder, builder } from '../builder'; import { Specification } from '../definitions'; import { validate } from '../utils'; -import { setEndValueIfNoTransition } from '../definitions/utils'; /** * The internal function used by the builder proxy to validate and return its underlying object - * @param {Specification.Defaultdef} data The underlying object - * @returns {Specification.Defaultdef} The validated underlying object + * @param {Specification.WorkflowExecTimeout} data The underlying object + * @returns {Specification.WorkflowExecTimeout} The validated underlying object */ -function defaultdefBuildingFn(data: Specification.Defaultdef): () => Specification.Defaultdef { +function workflowExecTimeoutBuildingFn( + data: Specification.WorkflowExecTimeout +): () => Specification.WorkflowExecTimeout { return () => { - const model = new Specification.Defaultdef(data); + const model = new Specification.WorkflowExecTimeout(data); - setEndValueIfNoTransition(model); - - validate('Defaultdef', model); + validate('WorkflowExecTimeout', model); return model; }; } /** - * A factory to create a builder proxy for the type `Specification.Defaultdef` - * @returns {Specification.Defaultdef} A builder for `Specification.Defaultdef` + * A factory to create a builder proxy for the type `Specification.WorkflowExecTimeout` + * @returns {Specification.WorkflowExecTimeout} A builder for `Specification.WorkflowExecTimeout` */ -export function defaultdefBuilder(): Builder { - return builder(defaultdefBuildingFn); +export function workflowExecTimeoutBuilder(): Builder { + return builder(workflowExecTimeoutBuildingFn); } diff --git a/src/lib/definitions/README.md b/src/lib/definitions/README.md deleted file mode 100644 index 7d5a864..0000000 --- a/src/lib/definitions/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Auto generated notice -This directory and its content has been generated automatically. Do not modify its content, it WILL be lost. \ No newline at end of file diff --git a/src/lib/definitions/action.ts b/src/lib/definitions/action.ts index 2dd751d..a3c1c9f 100644 --- a/src/lib/definitions/action.ts +++ b/src/lib/definitions/action.ts @@ -16,26 +16,42 @@ import { Actiondatafilter } from './actiondatafilter'; import { Eventref } from './eventref'; import { Functionref } from './functionref'; -import { overwriteActionDataFilterValue, overwriteEventRefValue, overwriteFunctionRefValue } from './utils'; +import { + normalizeSubFlowRefIfObject, + overwriteActionDataFilter, + overwriteEventRef, + overwriteFunctionRefIfObject, + overwriteSubFlowRefIfObject, +} from './utils'; +import { Subflowref } from './subflowref'; export class Action { constructor(model: any) { Object.assign(this, model); - overwriteFunctionRefValue(this); - overwriteEventRefValue(this); - overwriteActionDataFilterValue(this); + overwriteFunctionRefIfObject(this); + overwriteEventRef(this); + overwriteSubFlowRefIfObject(this); + overwriteActionDataFilter(this); } /** * Unique action definition name */ name?: string; - functionRef: string | Functionref; + functionRef?: string | Functionref; eventRef?: /* Event References */ Eventref; + subFlowRef?: string | Subflowref; + actionDataFilter?: Actiondatafilter; + /** - * Time period to wait for function execution to complete + * Normalize the value of each property by recursively deleting properties whose value is equal to its default value. Does not modify the object state. + * @returns {Specification.Action} without deleted properties. */ - timeout?: string; - actionDataFilter?: Actiondatafilter; + normalize = (): Action => { + const clone = new Action(this); + normalizeSubFlowRefIfObject(clone); + + return clone; + }; } diff --git a/src/lib/definitions/branch.ts b/src/lib/definitions/branch.ts index 55ba4ce..5948ea1 100644 --- a/src/lib/definitions/branch.ts +++ b/src/lib/definitions/branch.ts @@ -13,26 +13,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { Action } from './action'; -import { overwriteActionsValue } from './utils'; +import { normalizeActions, overwriteActions, overwritePropertyAsPlainType } from './utils'; +import { ActionExecTimeout, BranchExecTimeout } from './types'; export class Branch /* Branch Definition */ { constructor(model: any) { Object.assign(this, model); - - overwriteActionsValue(this); + overwriteActions(this); + overwritePropertyAsPlainType('timeouts', this); } /** * Branch name */ name: string; + /** + * State specific timeouts + */ + timeouts?: { + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + branchExecTimeout?: /* Single branch execution timeout duration (ISO 8601 duration format) */ BranchExecTimeout; + }; /** * Actions to be executed in this branch */ - actions?: Action[]; + actions: Action[]; + /** - * Unique Id of a workflow to be executed in this branch + * Normalize the value of each property by recursively deleting properties whose value is equal to its default value. Does not modify the object state. + * @returns {Specification.Action} without deleted properties. */ - workflowId: string; + normalize = (): Branch => { + const clone = new Branch(this); + normalizeActions(clone); + + return clone; + }; } diff --git a/src/lib/definitions/callbackstate.ts b/src/lib/definitions/callbackstate.ts index 2ada080..644e435 100644 --- a/src/lib/definitions/callbackstate.ts +++ b/src/lib/definitions/callbackstate.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Specification } from '.'; import { Action } from './action'; import { End } from './end'; @@ -23,32 +22,36 @@ import { Metadata } from './metadata'; import { Statedatafilter } from './statedatafilter'; import { Transition } from './transition'; import { - normalizeEndProperty, - normalizeOnErrorsProperty, - normalizeTransitionProperty, - normalizeUsedForCompensationProperty, - overwriteActionValue, - overwriteEndValueIfObject, - overwriteEventDataFilterValue, - overwriteMetadataValue, - overwriteOnErrorsValue, - overwriteStateDataFilterValue, - overwriteTransitionValueIfObject, + normalizeAction, + normalizeEndIfObject, + normalizeOnErrors, + normalizeTransitionIfObject, + normalizeUsedForCompensation, + overwriteAction, + overwriteEndIfObject, + overwriteEventDataFilter, + overwriteMetadata, + overwriteOnErrors, + overwritePropertyAsPlainType, + overwriteStateDataFilter, + overwriteTransitionIfObject, setEndValueIfNoTransition, } from './utils'; +import { ActionExecTimeout, EventTimeout, StateExecTimeout } from './types'; export class Callbackstate { constructor(model: any) { - const defaultModel = { type: 'callback' } as Specification.Callbackstate; + const defaultModel = { type: 'callback', usedForCompensation: false }; Object.assign(this, defaultModel, model); - overwriteActionValue(this); - overwriteEndValueIfObject(this); - overwriteEventDataFilterValue(this); - overwriteMetadataValue(this); - overwriteOnErrorsValue(this); - overwriteStateDataFilterValue(this); - overwriteTransitionValueIfObject(this); + overwriteAction(this); + overwritePropertyAsPlainType('timeouts', this); + overwriteEventDataFilter(this); + overwriteStateDataFilter(this); + overwriteOnErrors(this); + overwriteTransitionIfObject(this); + overwriteEndIfObject(this); + overwriteMetadata(this); } /** @@ -72,9 +75,13 @@ export class Callbackstate { */ eventRef?: string; /** - * Time period to wait for incoming events (ISO 8601 format) + * State specific timeouts */ - timeout?: string; + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + eventTimeout?: /* Timeout duration to wait for consuming defined events (ISO 8601 duration format) */ EventTimeout; + }; /** * Event data filter */ @@ -112,11 +119,11 @@ export class Callbackstate { normalize = (): Callbackstate => { const clone = new Callbackstate(this); - normalizeUsedForCompensationProperty(clone); - normalizeEndProperty(clone); - normalizeTransitionProperty(clone); - normalizeOnErrorsProperty(clone); - + normalizeAction(clone); + normalizeOnErrors(clone); + normalizeTransitionIfObject(clone); + normalizeEndIfObject(clone); + normalizeUsedForCompensation(clone); setEndValueIfNoTransition(clone); return clone; diff --git a/src/lib/definitions/databasedswitch.ts b/src/lib/definitions/databasedswitch.ts index 98bb253..01d748e 100644 --- a/src/lib/definitions/databasedswitch.ts +++ b/src/lib/definitions/databasedswitch.ts @@ -13,32 +13,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Defaultdef } from './defaultdef'; + +import { Defaultconditiondef } from './defaultconditiondef'; import { Error } from './error'; import { Metadata } from './metadata'; import { Statedatafilter } from './statedatafilter'; import { - normalizeDataConditionsProperty, - normalizeOnErrorsProperty, - normalizeUsedForCompensationProperty, - overwriteDataConditionsValue, - overwriteDefaultValue, - overwriteMetadataValue, - overwriteOnErrorsValue, - overwriteStateDataFilterValue, + normalizeDataConditions, + normalizeDefaultCondition, + normalizeOnErrors, + normalizeUsedForCompensation, + overwriteDataConditions, + overwriteDefaultCondition, + overwriteMetadata, + overwriteOnErrors, + overwriteStateDataFilter, + overwritePropertyAsPlainType, } from './utils'; -import { Datacondition } from './types'; +import { Datacondition, StateExecTimeout } from './types'; export class Databasedswitch { constructor(model: any) { const defaultModel = { type: 'switch', usedForCompensation: false }; Object.assign(this, defaultModel, model); - overwriteMetadataValue(this); - overwriteOnErrorsValue(this); - overwriteDataConditionsValue(this); - overwriteDefaultValue(this); - overwriteStateDataFilterValue(this); + overwriteStateDataFilter(this); + overwritePropertyAsPlainType('timeouts', this); + overwriteDataConditions(this); + overwriteOnErrors(this); + overwriteDefaultCondition(this); + overwriteMetadata(this); } /** @@ -57,6 +61,12 @@ export class Databasedswitch { * State data filter */ stateDataFilter?: Statedatafilter; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + }; /** * Defines conditions evaluated against state data */ @@ -68,7 +78,7 @@ export class Databasedswitch { /** * Default transition of the workflow if there is no matching data conditions. Can include a transition or end definition */ - default?: /* Default definition. Can be either a transition or end definition */ Defaultdef; + defaultCondition?: /* DefaultCondition definition. Can be either a transition or end definition */ Defaultconditiondef; /** * Unique Name of a workflow state which is responsible for compensation of this state */ @@ -86,9 +96,10 @@ export class Databasedswitch { normalize = (): Databasedswitch => { const clone = new Databasedswitch(this); - normalizeUsedForCompensationProperty(clone); - normalizeOnErrorsProperty(clone); - normalizeDataConditionsProperty(clone); + normalizeDataConditions(clone); + normalizeOnErrors(clone); + normalizeDefaultCondition(clone); + normalizeUsedForCompensation(clone); return clone; }; diff --git a/src/lib/definitions/defaultdef.ts b/src/lib/definitions/defaultconditiondef.ts similarity index 72% rename from src/lib/definitions/defaultdef.ts rename to src/lib/definitions/defaultconditiondef.ts index e64866b..dafac30 100644 --- a/src/lib/definitions/defaultdef.ts +++ b/src/lib/definitions/defaultconditiondef.ts @@ -13,22 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { End } from './end'; import { Transition } from './transition'; import { - normalizeEndProperty, - normalizeTransitionProperty, - overwriteEndValueIfObject, - overwriteTransitionValueIfObject, + normalizeEndIfObject, + normalizeTransitionIfObject, + overwriteEndIfObject, + overwriteTransitionIfObject, setEndValueIfNoTransition, } from './utils'; - -export class Defaultdef /* Default definition. Can be either a transition or end definition */ { +export class Defaultconditiondef /* DefaultCondition definition. Can be either a transition or end definition */ { constructor(model: any) { Object.assign(this, model); - overwriteTransitionValueIfObject(this); - overwriteEndValueIfObject(this); + overwriteTransitionIfObject(this); + overwriteEndIfObject(this); } transition: string | Transition; @@ -38,11 +38,11 @@ export class Defaultdef /* Default definition. Can be either a transition or end * Normalize the value of each property by recursively deleting properties whose value is equal to its default value. Does not modify the object state. * @returns {Specification.Defaultdef} without deleted properties. */ - normalize = (): Defaultdef => { - const clone = new Defaultdef(this); + normalize = (): Defaultconditiondef => { + const clone = new Defaultconditiondef(this); - normalizeEndProperty(clone); - normalizeTransitionProperty(clone); + normalizeEndIfObject(clone); + normalizeTransitionIfObject(clone); setEndValueIfNoTransition(clone); return clone; diff --git a/src/lib/definitions/delaystate.ts b/src/lib/definitions/delaystate.ts index 6b655dd..476466f 100644 --- a/src/lib/definitions/delaystate.ts +++ b/src/lib/definitions/delaystate.ts @@ -13,23 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { End } from './end'; import { Error } from './error'; import { Metadata } from './metadata'; import { Statedatafilter } from './statedatafilter'; import { Transition } from './transition'; import { - normalizeEndProperty, - normalizeOnErrorsProperty, - normalizeTransitionProperty, - normalizeUsedForCompensationProperty, - overwriteEndValueIfObject, - overwriteMetadataValue, - overwriteOnErrorsValue, - overwriteStateDataFilterValue, - overwriteTransitionValueIfObject, + normalizeEndIfObject, + normalizeOnErrors, + normalizeTransitionIfObject, + normalizeUsedForCompensation, + overwriteEndIfObject, + overwriteMetadata, + overwriteOnErrors, + overwriteStateDataFilter, + overwritePropertyAsPlainType, + overwriteTransitionIfObject, setEndValueIfNoTransition, } from './utils'; +import { StateExecTimeout } from './types'; export class Delaystate { constructor(model: any) { @@ -39,11 +42,12 @@ export class Delaystate { }; Object.assign(this, defaultModel, model); - overwriteMetadataValue(this); - overwriteOnErrorsValue(this); - overwriteEndValueIfObject(this); - overwriteTransitionValueIfObject(this); - overwriteStateDataFilterValue(this); + overwriteEndIfObject(this); + overwriteStateDataFilter(this); + overwritePropertyAsPlainType('timeouts', this); + overwriteOnErrors(this); + overwriteTransitionIfObject(this); + overwriteMetadata(this); } /** @@ -70,6 +74,12 @@ export class Delaystate { * Amount of time (ISO 8601 format) to delay */ timeDelay?: string; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + }; /** * States error handling and retries definitions */ @@ -95,10 +105,10 @@ export class Delaystate { normalize = (): Delaystate => { const clone = new Delaystate(this); - normalizeUsedForCompensationProperty(clone); - normalizeEndProperty(clone); - normalizeOnErrorsProperty(clone); - normalizeTransitionProperty(clone); + normalizeEndIfObject(clone); + normalizeOnErrors(clone); + normalizeTransitionIfObject(clone); + normalizeUsedForCompensation(clone); setEndValueIfNoTransition(clone); return clone; }; diff --git a/src/lib/definitions/end.ts b/src/lib/definitions/end.ts index 33d8270..5e6b9c7 100644 --- a/src/lib/definitions/end.ts +++ b/src/lib/definitions/end.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { Produceeventdef } from './produceeventdef'; -import { normalizeCompensateProperty, normalizeTerminateProperty, overwriteProduceEventsValue } from './utils'; +import { normalizeCompensate, normalizeTerminate, overwriteProduceEvents } from './utils'; export class End { constructor(model: any) { @@ -24,7 +24,7 @@ export class End { }; Object.assign(this, defaultModel, model); - overwriteProduceEventsValue(this); + overwriteProduceEvents(this); } /** @@ -47,8 +47,8 @@ export class End { normalize = (): End => { const clone = new End(this); - normalizeCompensateProperty(clone); - normalizeTerminateProperty(clone); + normalizeCompensate(clone); + normalizeTerminate(clone); return clone; }; diff --git a/src/lib/definitions/enddatacondition.ts b/src/lib/definitions/enddatacondition.ts index 6d5d8e4..3cadfdb 100644 --- a/src/lib/definitions/enddatacondition.ts +++ b/src/lib/definitions/enddatacondition.ts @@ -15,14 +15,14 @@ */ import { End } from './end'; import { Metadata } from './metadata'; -import { normalizeEndProperty, overwriteEndValueIfObject, overwriteMetadataValue } from './utils'; +import { normalizeEndIfObject, overwriteEndIfObject, overwriteMetadata } from './utils'; export class Enddatacondition { constructor(model: any) { Object.assign(this, model); - overwriteMetadataValue(this); - overwriteEndValueIfObject(this); + overwriteEndIfObject(this); + overwriteMetadata(this); } /** @@ -46,7 +46,7 @@ export class Enddatacondition { normalize = (): Enddatacondition => { const clone = new Enddatacondition(this); - normalizeEndProperty(clone); + normalizeEndIfObject(clone); return clone; }; diff --git a/src/lib/definitions/enddeventcondition.ts b/src/lib/definitions/enddeventcondition.ts index d29dafd..65858cd 100644 --- a/src/lib/definitions/enddeventcondition.ts +++ b/src/lib/definitions/enddeventcondition.ts @@ -16,21 +16,15 @@ import { End } from './end'; import { Eventdatafilter } from './eventdatafilter'; import { Metadata } from './metadata'; -import { - normalizeEndProperty, - overwriteEndValueIfObject, - overwriteEventDataFilterValue, - overwriteMetadataValue, -} from './utils'; +import { normalizeEndIfObject, overwriteEndIfObject, overwriteEventDataFilter, overwriteMetadata } from './utils'; export class Enddeventcondition { constructor(model: any) { Object.assign(this, model); - overwriteMetadataValue(this); - overwriteEndValueIfObject(this); - - overwriteEventDataFilterValue(this); + overwriteEndIfObject(this); + overwriteEventDataFilter(this); + overwriteMetadata(this); } /** @@ -58,7 +52,7 @@ export class Enddeventcondition { normalize = (): Enddeventcondition => { const clone = new Enddeventcondition(this); - normalizeEndProperty(clone); + normalizeEndIfObject(clone); return clone; }; diff --git a/src/lib/definitions/error.ts b/src/lib/definitions/error.ts index 844edf5..b90486c 100644 --- a/src/lib/definitions/error.ts +++ b/src/lib/definitions/error.ts @@ -16,10 +16,10 @@ import { End } from './end'; import { Transition } from './transition'; import { - normalizeEndProperty, - normalizeTransitionProperty, - overwriteEndValueIfObject, - overwriteTransitionValueIfObject, + normalizeEndIfObject, + normalizeTransitionIfObject, + overwriteEndIfObject, + overwriteTransitionIfObject, setEndValueIfNoTransition, } from './utils'; @@ -27,8 +27,8 @@ export class Error { constructor(model: any) { Object.assign(this, model); - overwriteTransitionValueIfObject(this); - overwriteEndValueIfObject(this); + overwriteTransitionIfObject(this); + overwriteEndIfObject(this); } /** @@ -53,8 +53,8 @@ export class Error { normalize = (): Error => { const clone = new Error(this); - normalizeEndProperty(clone); - normalizeTransitionProperty(clone); + normalizeEndIfObject(clone); + normalizeTransitionIfObject(clone); setEndValueIfNoTransition(clone); diff --git a/src/lib/definitions/eventbasedswitch.ts b/src/lib/definitions/eventbasedswitch.ts index 83186f2..7e451ad 100644 --- a/src/lib/definitions/eventbasedswitch.ts +++ b/src/lib/definitions/eventbasedswitch.ts @@ -13,21 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Defaultdef } from './defaultdef'; + +import { Defaultconditiondef } from './defaultconditiondef'; import { Error } from './error'; import { Metadata } from './metadata'; import { Statedatafilter } from './statedatafilter'; import { - normalizeEventConditionsProperty, - normalizeOnErrorsProperty, - normalizeUsedForCompensationProperty, - overwriteDefaultValue, - overwriteEventConditionsValue, - overwriteMetadataValue, - overwriteOnErrorsValue, - overwriteStateDataFilterValue, + normalizeDefaultCondition, + normalizeEventConditions, + normalizeOnErrors, + normalizeUsedForCompensation, + overwriteDefaultCondition, + overwriteEventConditions, + overwriteMetadata, + overwriteOnErrors, + overwriteStateDataFilter, + overwritePropertyAsPlainType, } from './utils'; -import { Eventcondition } from './types'; +import { Eventcondition, EventTimeout, StateExecTimeout } from './types'; export class Eventbasedswitch { constructor(model: any) { @@ -37,11 +40,12 @@ export class Eventbasedswitch { }; Object.assign(this, defaultModel, model); - overwriteMetadataValue(this); - overwriteOnErrorsValue(this); - overwriteEventConditionsValue(this); - overwriteDefaultValue(this); - overwriteStateDataFilterValue(this); + overwriteStateDataFilter(this); + overwritePropertyAsPlainType('timeouts', this); + overwriteEventConditions(this); + overwriteOnErrors(this); + overwriteDefaultCondition(this); + overwriteMetadata(this); } /** @@ -60,6 +64,13 @@ export class Eventbasedswitch { * State data filter */ stateDataFilter?: Statedatafilter; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + eventTimeout?: /* Timeout duration to wait for consuming defined events (ISO 8601 duration format) */ EventTimeout; + }; /** * Defines conditions evaluated against events */ @@ -68,14 +79,10 @@ export class Eventbasedswitch { * States error handling and retries definitions */ onErrors?: Error[]; - /** - * If eventConditions is used, defines the time period to wait for events (ISO 8601 format) - */ - eventTimeout?: string; /** * Default transition of the workflow if there is no matching data conditions. Can include a transition or end definition */ - default?: /* Default definition. Can be either a transition or end definition */ Defaultdef; + defaultCondition?: /* DefaultCondition definition. Can be either a transition or end definition */ Defaultconditiondef; /** * Unique Name of a workflow state which is responsible for compensation of this state */ @@ -93,9 +100,10 @@ export class Eventbasedswitch { normalize = (): Eventbasedswitch => { const clone = new Eventbasedswitch(this); - normalizeUsedForCompensationProperty(clone); - normalizeOnErrorsProperty(clone); - normalizeEventConditionsProperty(clone); + normalizeEventConditions(clone); + normalizeOnErrors(clone); + normalizeDefaultCondition(clone); + normalizeUsedForCompensation(clone); return clone; }; diff --git a/src/lib/definitions/eventdatafilter.ts b/src/lib/definitions/eventdatafilter.ts index 9786dd7..0c34636 100644 --- a/src/lib/definitions/eventdatafilter.ts +++ b/src/lib/definitions/eventdatafilter.ts @@ -20,11 +20,11 @@ export class Eventdatafilter { } /** - * Workflow expression that filters of the event data (payload) + * Workflow expression that filters the received event/payload (default: '${ . }') */ data?: string; /** - * Workflow expression that selects a state data element to which the event payload should be added/merged into. If not specified, denotes, the top-level state data element. + * Workflow expression that selects a state data element to which the filtered event should be added/merged into. If not specified, denotes, the top-level state data element. */ toStateData?: string; } diff --git a/src/lib/definitions/eventdef.ts b/src/lib/definitions/eventdef.ts index c82d279..c5aade0 100644 --- a/src/lib/definitions/eventdef.ts +++ b/src/lib/definitions/eventdef.ts @@ -14,18 +14,19 @@ * limitations under the License. */ import { Metadata } from './metadata'; -import { normalizeKindProperty, overwriteCorrelationValue, overwriteMetadataValue } from './utils'; +import { normalizeDataOnly, normalizeKind, overwriteCorrelation, overwriteMetadata } from './utils'; import { CorrelationDefs } from './types'; export class Eventdef { constructor(model: any) { const defaultModel = { kind: 'consumed', + dataOnly: true, }; Object.assign(this, defaultModel, model); - overwriteMetadataValue(this); - overwriteCorrelationValue(this); + overwriteCorrelation(this); + overwriteMetadata(this); } /** @@ -48,6 +49,11 @@ export class Eventdef { * CloudEvent correlation definitions */ correlation?: CorrelationDefs; + + /** + * If `true`, only the Event payload is accessible to consuming Workflow states. If `false`, both event payload and context attributes should be accessible + */ + dataOnly?: boolean; /** * Metadata information */ @@ -60,7 +66,8 @@ export class Eventdef { normalize = (): Eventdef => { const clone = new Eventdef(this); - normalizeKindProperty(clone); + normalizeKind(clone); + normalizeDataOnly(clone); return clone; }; diff --git a/src/lib/definitions/eventref.ts b/src/lib/definitions/eventref.ts index d96204b..2d7133d 100644 --- a/src/lib/definitions/eventref.ts +++ b/src/lib/definitions/eventref.ts @@ -14,9 +14,13 @@ * limitations under the License. */ +import { overwritePropertyAsPlainType } from './utils'; + export class Eventref { constructor(model: any) { Object.assign(this, model); + overwritePropertyAsPlainType('data', this); + overwritePropertyAsPlainType('contextAttributes', this); } /** diff --git a/src/lib/definitions/events.ts b/src/lib/definitions/events.ts deleted file mode 100644 index 30c8d2b..0000000 --- a/src/lib/definitions/events.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2021-Present The Serverless Workflow Specification Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Eventdef } from './eventdef'; - -export type Events = string /* uri */ | [Eventdef, ...Eventdef[]]; diff --git a/src/lib/definitions/eventstate.ts b/src/lib/definitions/eventstate.ts index 6c7fd4a..efad8fd 100644 --- a/src/lib/definitions/eventstate.ts +++ b/src/lib/definitions/eventstate.ts @@ -20,31 +20,34 @@ import { Onevents } from './onevents'; import { Statedatafilter } from './statedatafilter'; import { Transition } from './transition'; import { + normalizeEndIfObject, + normalizeExclusive, + normalizeOnErrors, + normalizeOnEvents, + normalizeTransitionIfObject, + overwriteEndIfObject, + overwriteMetadata, + overwriteOnErrors, + overwriteOnEvents, + overwriteStateDataFilter, + overwritePropertyAsPlainType, + overwriteTransitionIfObject, setEndValueIfNoTransition, - overwriteEndValueIfObject, - overwriteMetadataValue, - overwriteOnErrorsValue, - overwriteOnEventsValue, - overwriteStateDataFilterValue, - overwriteTransitionValueIfObject, - normalizeEndProperty, - normalizeTransitionProperty, - normalizeOnEventsProperty, - normalizeOnErrorsProperty, - normalizeExclusiveProperty, } from './utils'; +import { ActionExecTimeout, EventTimeout, StateExecTimeout } from './types'; export class Eventstate /* This state is used to wait for events from event sources, then consumes them and invoke one or more actions to run in sequence or parallel */ { constructor(model: any) { const defaultModel = { type: 'event', exclusive: true }; Object.assign(this, defaultModel, model); - overwriteOnEventsValue(this); - overwriteStateDataFilterValue(this); - overwriteOnErrorsValue(this); - overwriteTransitionValueIfObject(this); - overwriteEndValueIfObject(this); - overwriteMetadataValue(this); + overwriteOnEvents(this); + overwritePropertyAsPlainType('timeouts', this); + overwriteStateDataFilter(this); + overwriteOnErrors(this); + overwriteTransitionIfObject(this); + overwriteEndIfObject(this); + overwriteMetadata(this); } /** @@ -68,9 +71,13 @@ export class Eventstate /* This state is used to wait for events from event sour */ onEvents: Onevents[]; /** - * Time period to wait for incoming events (ISO 8601 format) + * State specific timeouts */ - timeout?: string; + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + eventTimeout?: /* Timeout duration to wait for consuming defined events (ISO 8601 duration format) */ EventTimeout; + }; stateDataFilter?: Statedatafilter; /** * States error handling and retries definitions @@ -91,11 +98,11 @@ export class Eventstate /* This state is used to wait for events from event sour normalize = (): Eventstate => { const clone = new Eventstate(this); - normalizeExclusiveProperty(clone); - normalizeOnEventsProperty(clone); - normalizeOnErrorsProperty(clone); - normalizeEndProperty(clone); - normalizeTransitionProperty(clone); + normalizeExclusive(clone); + normalizeOnEvents(clone); + normalizeOnErrors(clone); + normalizeTransitionIfObject(clone); + normalizeEndIfObject(clone); setEndValueIfNoTransition(clone); return clone; diff --git a/src/lib/definitions/foreachstate.ts b/src/lib/definitions/foreachstate.ts index 261c466..3201ad2 100644 --- a/src/lib/definitions/foreachstate.ts +++ b/src/lib/definitions/foreachstate.ts @@ -20,30 +20,34 @@ import { Metadata } from './metadata'; import { Statedatafilter } from './statedatafilter'; import { Transition } from './transition'; import { - normalizeEndProperty, - normalizeOnErrorsProperty, - normalizeTransitionProperty, - normalizeUsedForCompensationProperty, - overwriteActionsValue, - overwriteEndValueIfObject, - overwriteMetadataValue, - overwriteOnErrorsValue, - overwriteStateDataFilterValue, - overwriteTransitionValueIfObject, + normalizeActions, + normalizeEndIfObject, + normalizeOnErrors, + normalizeTransitionIfObject, + normalizeUsedForCompensation, + overwriteActions, + overwriteEndIfObject, + overwriteMetadata, + overwriteOnErrors, + overwriteStateDataFilter, + overwritePropertyAsPlainType, + overwriteTransitionIfObject, setEndValueIfNoTransition, } from './utils'; +import { ActionExecTimeout, StateExecTimeout } from './types'; export class Foreachstate { constructor(model: any) { const defaultModel = { type: 'foreach', usedForCompensation: false }; Object.assign(this, defaultModel, model); - overwriteEndValueIfObject(this); - overwriteActionsValue(this); - overwriteStateDataFilterValue(this); - overwriteOnErrorsValue(this); - overwriteTransitionValueIfObject(this); - overwriteMetadataValue(this); + overwriteEndIfObject(this); + overwriteActions(this); + overwritePropertyAsPlainType('timeouts', this); + overwriteStateDataFilter(this); + overwriteOnErrors(this); + overwriteTransitionIfObject(this); + overwriteMetadata(this); } /** @@ -83,9 +87,12 @@ export class Foreachstate { */ actions?: Action[]; /** - * Unique Id of a workflow to be executed for each of the elements of inputCollection + * State specific timeouts */ - workflowId?: string; + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + }; /** * State data filter */ @@ -115,10 +122,11 @@ export class Foreachstate { normalize = (): Foreachstate => { const clone = new Foreachstate(this); - normalizeUsedForCompensationProperty(clone); - normalizeOnErrorsProperty(clone); - normalizeEndProperty(clone); - normalizeTransitionProperty(clone); + normalizeEndIfObject(clone); + normalizeActions(clone); + normalizeOnErrors(clone); + normalizeTransitionIfObject(clone); + normalizeUsedForCompensation(clone); setEndValueIfNoTransition(clone); return clone; diff --git a/src/lib/definitions/function.ts b/src/lib/definitions/function.ts index df845da..b1ef75d 100644 --- a/src/lib/definitions/function.ts +++ b/src/lib/definitions/function.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { normalizeTypeRestProperty } from './utils'; +import { normalizeType } from './utils'; export class Function { constructor(model: any) { @@ -27,11 +27,11 @@ export class Function { */ name: string; /** - * If type is `rest`, #. If type is `rpc`, ##. If type is `expression`, defines the workflow expression. + * If type is `rest`, #. If type is `rpc`, ##. If type is `graphql`, ##. If type is `expression`, defines the workflow expression. */ operation: string; /** - * Defines the function type. Is either `rest`, `rpc` or `expression`. Default is `rest` + * Defines the function type. Is either `rest`, `rpc`, `graphql` or `expression`. Default is `rest` */ type?: 'rest' | 'rpc' | 'expression'; @@ -43,7 +43,7 @@ export class Function { normalize = (): Function => { const clone = new Function(this); - normalizeTypeRestProperty(clone); + normalizeType(clone); return clone; }; diff --git a/src/lib/definitions/functionref.ts b/src/lib/definitions/functionref.ts index f432ac7..3053000 100644 --- a/src/lib/definitions/functionref.ts +++ b/src/lib/definitions/functionref.ts @@ -14,9 +14,12 @@ * limitations under the License. */ +import { overwritePropertyAsPlainType } from './utils'; + export class Functionref { constructor(model: any) { Object.assign(this, model); + overwritePropertyAsPlainType('arguments', this); } /** @@ -29,4 +32,8 @@ export class Functionref { arguments?: { [key: string]: any; }; + /** + * Only used if function type is 'graphql'. A string containing a valid GraphQL selection set + */ + selectionSet?: string; } diff --git a/src/lib/definitions/injectstate.ts b/src/lib/definitions/injectstate.ts index 8031b56..63b2c24 100644 --- a/src/lib/definitions/injectstate.ts +++ b/src/lib/definitions/injectstate.ts @@ -13,30 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { End } from './end'; import { Metadata } from './metadata'; import { Statedatafilter } from './statedatafilter'; import { Transition } from './transition'; import { - normalizeEndProperty, - normalizeTransitionProperty, - normalizeUsedForCompensationProperty, - overwriteEndValueIfObject, - overwriteMetadataValue, - overwriteStateDataFilterValue, - overwriteTransitionValueIfObject, + normalizeEndIfObject, + normalizeTransitionIfObject, + normalizeUsedForCompensation, + overwriteEndIfObject, + overwriteMetadata, + overwritePropertyAsPlainType, + overwriteStateDataFilter, + overwriteTransitionIfObject, setEndValueIfNoTransition, } from './utils'; +import { StateExecTimeout } from './types'; export class Injectstate { constructor(model: any) { const defaultModel = { type: 'inject', usedForCompensation: false }; Object.assign(this, defaultModel, model); - overwriteEndValueIfObject(this); - overwriteStateDataFilterValue(this); - overwriteTransitionValueIfObject(this); - overwriteMetadataValue(this); + overwriteEndIfObject(this); + overwritePropertyAsPlainType('data', this); + overwritePropertyAsPlainType('timeouts', this); + overwriteStateDataFilter(this); + overwriteTransitionIfObject(this); + overwriteMetadata(this); } /** @@ -61,12 +66,18 @@ export class Injectstate { data?: { [key: string]: any; }; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + }; /** * State data filter */ stateDataFilter?: Statedatafilter; /** - * Next transition of the workflow after subflow has completed + * Next transition of the workflow after injection has completed */ transition?: string | Transition; /** @@ -86,10 +97,9 @@ export class Injectstate { normalize = (): Injectstate => { const clone = new Injectstate(this); - normalizeUsedForCompensationProperty(clone); - normalizeEndProperty(clone); - normalizeTransitionProperty(clone); - + normalizeEndIfObject(clone); + normalizeTransitionIfObject(clone); + normalizeUsedForCompensation(clone); setEndValueIfNoTransition(clone); return clone; diff --git a/src/lib/definitions/onevents.ts b/src/lib/definitions/onevents.ts index 2905733..737c370 100644 --- a/src/lib/definitions/onevents.ts +++ b/src/lib/definitions/onevents.ts @@ -15,15 +15,15 @@ */ import { Action } from './action'; import { Eventdatafilter } from './eventdatafilter'; -import { normalizeActionModeParallelProperty, overwriteActionsValue, overwriteEventDataFilterValue } from './utils'; +import { normalizeActionMode, normalizeActions, overwriteActions, overwriteEventDataFilter } from './utils'; export class Onevents { constructor(model: any) { - const defaultModel = { actionMode: 'parallel' }; + const defaultModel = { actionMode: 'sequential' }; Object.assign(this, defaultModel, model); - overwriteEventDataFilterValue(this); - overwriteActionsValue(this); + overwriteActions(this); + overwriteEventDataFilter(this); } /** @@ -31,7 +31,7 @@ export class Onevents { */ eventRefs: [string, ...string[]]; /** - * Specifies how actions are to be performed (in sequence of parallel) + * Specifies how actions are to be performed (in sequence or in parallel) */ actionMode?: 'sequential' | 'parallel'; /** @@ -50,7 +50,8 @@ export class Onevents { normalize = (): Onevents => { const clone = new Onevents(this); - normalizeActionModeParallelProperty(clone); + normalizeActionMode(clone); + normalizeActions(clone); return clone; }; diff --git a/src/lib/definitions/operationstate.ts b/src/lib/definitions/operationstate.ts index d157bfb..cf84a98 100644 --- a/src/lib/definitions/operationstate.ts +++ b/src/lib/definitions/operationstate.ts @@ -20,19 +20,22 @@ import { Metadata } from './metadata'; import { Statedatafilter } from './statedatafilter'; import { Transition } from './transition'; import { - normalizeActionModeSequentialProperty, - normalizeEndProperty, - normalizeOnErrorsProperty, - normalizeTransitionProperty, - normalizeUsedForCompensationProperty, - overwriteActionsValue, - overwriteEndValueIfObject, - overwriteMetadataValue, - overwriteOnErrorsValue, - overwriteStateDataFilterValue, - overwriteTransitionValueIfObject, + normalizeActionMode, + normalizeActions, + normalizeEndIfObject, + normalizeOnErrors, + normalizeTransitionIfObject, + normalizeUsedForCompensation, + overwriteActions, + overwriteEndIfObject, + overwriteMetadata, + overwriteOnErrors, + overwriteStateDataFilter, + overwritePropertyAsPlainType, + overwriteTransitionIfObject, setEndValueIfNoTransition, } from './utils'; +import { ActionExecTimeout, StateExecTimeout } from './types'; export class Operationstate { constructor(model: any) { @@ -43,12 +46,13 @@ export class Operationstate { }; Object.assign(this, defaultModel, model); - overwriteEndValueIfObject(this); - overwriteActionsValue(this); - overwriteStateDataFilterValue(this); - overwriteOnErrorsValue(this); - overwriteTransitionValueIfObject(this); - overwriteMetadataValue(this); + overwriteEndIfObject(this); + overwriteStateDataFilter(this); + overwriteActions(this); + overwritePropertyAsPlainType('timeouts', this); + overwriteOnErrors(this); + overwriteTransitionIfObject(this); + overwriteMetadata(this); } /** @@ -79,6 +83,13 @@ export class Operationstate { * Actions to be performed */ actions?: Action[]; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + }; /** * States error handling and retries definitions */ @@ -104,11 +115,12 @@ export class Operationstate { normalize = (): Operationstate => { const clone = new Operationstate(this); - normalizeActionModeSequentialProperty(clone); - normalizeUsedForCompensationProperty(clone); - normalizeEndProperty(clone); - normalizeTransitionProperty(clone); - normalizeOnErrorsProperty(clone); + normalizeEndIfObject(clone); + normalizeActionMode(clone); + normalizeActions(clone); + normalizeOnErrors(clone); + normalizeTransitionIfObject(clone); + normalizeUsedForCompensation(clone); setEndValueIfNoTransition(clone); return clone; diff --git a/src/lib/definitions/parallelstate.ts b/src/lib/definitions/parallelstate.ts index 658922b..e835831 100644 --- a/src/lib/definitions/parallelstate.ts +++ b/src/lib/definitions/parallelstate.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { Branch } from './branch'; import { End } from './end'; import { Error } from './error'; @@ -20,35 +21,39 @@ import { Metadata } from './metadata'; import { Statedatafilter } from './statedatafilter'; import { Transition } from './transition'; import { - normalizeCompletionTypeProperty, - normalizeEndProperty, - normalizeOnErrorsProperty, - normalizeTransitionProperty, - normalizeUsedForCompensationProperty, - overwriteBranchesValue, - overwriteEndValueIfObject, - overwriteMetadataValue, - overwriteOnErrorsValue, - overwriteStateDataFilterValue, - overwriteTransitionValueIfObject, + normalizeBranches, + normalizeCompletionType, + normalizeEndIfObject, + normalizeOnErrors, + normalizeTransitionIfObject, + normalizeUsedForCompensation, + overwriteBranches, + overwriteEndIfObject, + overwriteMetadata, + overwriteOnErrors, + overwriteStateDataFilter, + overwritePropertyAsPlainType, + overwriteTransitionIfObject, setEndValueIfNoTransition, } from './utils'; +import { BranchExecTimeout, StateExecTimeout } from './types'; export class Parallelstate { constructor(model: any) { const defaultModel = { type: 'parallel', - completionType: 'and', + completionType: 'allOf', usedForCompensation: false, }; Object.assign(this, defaultModel, model); - overwriteEndValueIfObject(this); - overwriteStateDataFilterValue(this); - overwriteBranchesValue(this); - overwriteOnErrorsValue(this); - overwriteTransitionValueIfObject(this); - overwriteMetadataValue(this); + overwriteEndIfObject(this); + overwriteStateDataFilter(this); + overwritePropertyAsPlainType('timeouts', this); + overwriteBranches(this); + overwriteOnErrors(this); + overwriteTransitionIfObject(this); + overwriteMetadata(this); } /** @@ -71,6 +76,13 @@ export class Parallelstate { * State data filter */ stateDataFilter?: Statedatafilter; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + branchExecTimeout?: /* Single branch execution timeout duration (ISO 8601 duration format) */ BranchExecTimeout; + }; /** * Branch Definitions */ @@ -78,11 +90,11 @@ export class Parallelstate { /** * Option types on how to complete branch execution. */ - completionType?: 'and' | 'xor' | 'n_of_m'; + completionType?: 'allOf' | 'atLeast'; /** - * Used when completionType is set to 'n_of_m' to specify the 'N' value + * Used when completionType is set to 'atLeast' to specify the minimum number of branches that must complete before the state will transition. */ - n?: number | string; + numCompleted?: number | string; /** * States error handling and retries definitions */ @@ -108,12 +120,12 @@ export class Parallelstate { normalize = (): Parallelstate => { const clone = new Parallelstate(this); - normalizeCompletionTypeProperty(clone); - normalizeOnErrorsProperty(clone); - normalizeUsedForCompensationProperty(clone); - normalizeEndProperty(clone); - normalizeTransitionProperty(clone); - + normalizeEndIfObject(clone); + normalizeBranches(clone); + normalizeCompletionType(clone); + normalizeOnErrors(clone); + normalizeTransitionIfObject(clone); + normalizeUsedForCompensation(clone); setEndValueIfNoTransition(clone); return clone; diff --git a/src/lib/definitions/produceeventdef.ts b/src/lib/definitions/produceeventdef.ts index fe6cc54..ff7db27 100644 --- a/src/lib/definitions/produceeventdef.ts +++ b/src/lib/definitions/produceeventdef.ts @@ -14,9 +14,13 @@ * limitations under the License. */ +import { overwritePropertyAsPlainType } from './utils'; + export class Produceeventdef { constructor(model: any) { Object.assign(this, model); + overwritePropertyAsPlainType('data', this); + overwritePropertyAsPlainType('contextAttributes', this); } /** diff --git a/src/lib/definitions/repeat.ts b/src/lib/definitions/repeat.ts deleted file mode 100644 index a5a7036..0000000 --- a/src/lib/definitions/repeat.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2021-Present The Serverless Workflow Specification Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { normalizeCheckBeforeProperty, normalizeContinueOnErrorProperty } from './utils'; - -export class Repeat { - constructor(model: any) { - const defaultModel = { - continueOnError: false, - checkBefore: false, - }; - Object.assign(this, defaultModel, model); - } - - /** - * Expression evaluated against SubFlow state data. SubFlow will repeat execution as long as this expression is true or until the max property count is reached - */ - expression?: string; - /** - * If true, the expression is evaluated before each repeat execution, if false the expression is evaluated after each repeat execution - */ - checkBefore?: boolean; - /** - * Sets the maximum amount of repeat executions - */ - max?: number; - /** - * If true, repeats executions in a case unhandled errors propagate from the sub-workflow to this state - */ - continueOnError?: boolean; - /** - * List referencing defined consumed workflow events. SubFlow will repeat execution until one of the defined events is consumed, or until the max property count is reached - */ - stopOnEvents?: [string, ...string[]]; - - /** - * Normalize the value of each property by recursively deleting properties whose value is equal to its default value. Does not modify the object state. - * @returns {Specification.Repeat} without deleted properties. - */ - normalize = (): Repeat => { - const clone = new Repeat(this); - - normalizeContinueOnErrorProperty(clone); - normalizeCheckBeforeProperty(clone); - - return clone; - }; -} diff --git a/src/lib/definitions/schedule.ts b/src/lib/definitions/schedule.ts index efb5a9f..38f07df 100644 --- a/src/lib/definitions/schedule.ts +++ b/src/lib/definitions/schedule.ts @@ -14,13 +14,13 @@ * limitations under the License. */ import { Crondef } from './crondef'; -import { overwriteCronValueIfObject } from './utils'; +import { overwriteCronIfObject } from './utils'; export class Schedule { constructor(model: any) { Object.assign(this, model); - overwriteCronValueIfObject(this); + overwriteCronIfObject(this); } /** diff --git a/src/lib/definitions/specification.ts b/src/lib/definitions/specification.ts index 4dd1eed..5050b12 100644 --- a/src/lib/definitions/specification.ts +++ b/src/lib/definitions/specification.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './workflow'; + export * from './action'; export * from './actiondatafilter'; export * from './branch'; @@ -21,7 +21,7 @@ export * from './callbackstate'; export * from './correlationDef'; export * from './crondef'; export * from './databasedswitch'; -export * from './defaultdef'; +export * from './defaultconditiondef'; export * from './delaystate'; export * from './end'; export * from './enddatacondition'; @@ -31,9 +31,7 @@ export * from './eventbasedswitch'; export * from './eventdatafilter'; export * from './eventdef'; export * from './eventref'; -export * from './events'; export * from './eventstate'; -export * from './exectimeout'; export * from './foreachstate'; export * from './function'; export * from './functionref'; @@ -43,13 +41,15 @@ export * from './onevents'; export * from './operationstate'; export * from './parallelstate'; export * from './produceeventdef'; -export * from './repeat'; export * from './retrydef'; export * from './schedule'; export * from './startdef'; export * from './statedatafilter'; -export * from './subflowstate'; +export * from './subflowref'; +export * from './timeouts'; export * from './transition'; export * from './transitiondatacondition'; export * from './transitioneventcondition'; +export * from './workflow'; +export * from './workflowExecTimeout'; export * from './types'; diff --git a/src/lib/definitions/startdef.ts b/src/lib/definitions/startdef.ts index c4a25a1..2778107 100644 --- a/src/lib/definitions/startdef.ts +++ b/src/lib/definitions/startdef.ts @@ -14,13 +14,13 @@ * limitations under the License. */ import { Schedule } from './schedule'; -import { overwriteScheduleValueIfObject } from './utils'; +import { overwriteScheduleIfObject } from './utils'; export class Startdef { constructor(model: any) { Object.assign(this, model); - overwriteScheduleValueIfObject(this); + overwriteScheduleIfObject(this); } /** diff --git a/src/lib/definitions/subflowref.ts b/src/lib/definitions/subflowref.ts new file mode 100644 index 0000000..52e0bcd --- /dev/null +++ b/src/lib/definitions/subflowref.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2021-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Specification } from './index'; +import { normalizeWaitForCompletion } from './utils'; + +export class Subflowref { + constructor(model: any) { + const defaultModel = { waitForCompletion: true } as Specification.Subflowref; + + Object.assign(this, defaultModel, model); + } + + /** + * Workflow execution must wait for sub-workflow to finish before continuing + */ + waitForCompletion?: boolean; + /** + * Unique id of the sub-workflow to be invoked + */ + workflowId: string; + /** + * Version of the sub-workflow to be invoked + */ + version?: string; + + /** + * Normalize the value of each property by recursively deleting properties whose value is equal to its default value. Does not modify the object state. + * @returns {Specification.Subflowref} without deleted properties. + */ + normalize = (): Subflowref => { + const clone = new Subflowref(this); + + normalizeWaitForCompletion(clone); + + return clone; + }; +} diff --git a/src/lib/definitions/subflowstate.ts b/src/lib/definitions/subflowstate.ts deleted file mode 100644 index 43f9e0a..0000000 --- a/src/lib/definitions/subflowstate.ts +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2021-Present The Serverless Workflow Specification Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { End } from './end'; -import { Error } from './error'; -import { Metadata } from './metadata'; -import { Repeat } from './repeat'; -import { Statedatafilter } from './statedatafilter'; -import { Transition } from './transition'; -import { - normalizeEndProperty, - normalizeRepeatProperty, - normalizeTransitionProperty, - normalizeUsedForCompensationProperty, - overwriteEndValueIfObject, - overwriteMetadataValue, - overwriteOnErrorsValue, - overwriteRepeatValue, - overwriteStateDataFilterValue, - overwriteTransitionValueIfObject, - setEndValueIfNoTransition, -} from './utils'; - -export class Subflowstate { - constructor(model: any) { - const defaultModel = { - type: 'subflow', - usedForCompensation: false, - waitForCompletion: false, - }; - Object.assign(this, defaultModel, model); - - overwriteEndValueIfObject(this); - overwriteRepeatValue(this); - overwriteStateDataFilterValue(this); - overwriteOnErrorsValue(this); - overwriteTransitionValueIfObject(this); - overwriteMetadataValue(this); - } - - /** - * Unique state id - */ - id?: string; - /** - * State name - */ - name?: string; - /** - * State type - */ - type?: 'subflow'; - /** - * State end definition - */ - end?: boolean | End; - /** - * Workflow execution must wait for sub-workflow to finish before continuing - */ - waitForCompletion?: boolean; - /** - * Sub-workflow unique id - */ - workflowId?: string; - /** - * SubFlow state repeat exec definition - */ - repeat?: Repeat; - /** - * State data filter - */ - stateDataFilter?: Statedatafilter; - /** - * States error handling and retries definitions - */ - onErrors?: Error[]; - /** - * Next transition of the workflow after SubFlow has completed execution - */ - transition?: string | Transition; - /** - * Unique Name of a workflow state which is responsible for compensation of this state - */ - compensatedBy?: string; - /** - * If true, this state is used to compensate another state. Default is false - */ - usedForCompensation?: boolean; - metadata?: /* Metadata information */ Metadata; - - /** - * Normalize the value of each property by recursively deleting properties whose value is equal to its default value. Does not modify the object state. - * @returns {Specification.Subflowstate} without deleted properties. - */ - normalize = (): Subflowstate => { - const clone = new Subflowstate(this); - - normalizeUsedForCompensationProperty(clone); - - if (!clone.waitForCompletion) { - delete clone.waitForCompletion; - } - - normalizeEndProperty(clone); - normalizeTransitionProperty(clone); - normalizeRepeatProperty(clone); - setEndValueIfNoTransition(clone); - - return clone; - }; -} diff --git a/src/lib/definitions/timeouts.ts b/src/lib/definitions/timeouts.ts new file mode 100644 index 0000000..5f0eb0a --- /dev/null +++ b/src/lib/definitions/timeouts.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2021-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { WorkflowExecTimeout } from './workflowExecTimeout'; +import { ActionExecTimeout, BranchExecTimeout, EventTimeout, StateExecTimeout } from './types'; +import { normalizeWorkflowExecTimeout, overwriteWorkflowExecTimeout } from './utils'; + +export class Timeouts { + constructor(model: any) { + Object.assign(this, model); + overwriteWorkflowExecTimeout(this); + } + + workflowExecTimeout?: WorkflowExecTimeout; + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + branchExecTimeout?: /* Single branch execution timeout duration (ISO 8601 duration format) */ BranchExecTimeout; + eventTimeout?: /* Timeout duration to wait for consuming defined events (ISO 8601 duration format) */ EventTimeout; + + /** + * Normalize the value of each property by recursively deleting properties whose value is equal to its default value. Does not modify the object state. + * @returns {Specification.Exectimeout} without deleted properties. + */ + normalize = (): Timeouts => { + const clone = new Timeouts(this); + normalizeWorkflowExecTimeout(clone); + return clone; + }; +} diff --git a/src/lib/definitions/transition.ts b/src/lib/definitions/transition.ts index 2b98d52..f9c6851 100644 --- a/src/lib/definitions/transition.ts +++ b/src/lib/definitions/transition.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { Produceeventdef } from './produceeventdef'; -import { normalizeCompensateProperty, overwriteProduceEventsValue } from './utils'; +import { normalizeCompensate, overwriteProduceEvents } from './utils'; export class Transition { constructor(model: any) { @@ -23,7 +23,7 @@ export class Transition { }; Object.assign(this, defaultModel, model); - overwriteProduceEventsValue(this); + overwriteProduceEvents(this); } /** @@ -46,7 +46,7 @@ export class Transition { normalize = (): Transition => { const clone = new Transition(this); - normalizeCompensateProperty(clone); + normalizeCompensate(clone); return clone; }; diff --git a/src/lib/definitions/transitiondatacondition.ts b/src/lib/definitions/transitiondatacondition.ts index 9400568..c004edb 100644 --- a/src/lib/definitions/transitiondatacondition.ts +++ b/src/lib/definitions/transitiondatacondition.ts @@ -15,14 +15,14 @@ */ import { Metadata } from './metadata'; import { Transition } from './transition'; -import { normalizeTransitionProperty, overwriteMetadataValue, overwriteTransitionValueIfObject } from './utils'; +import { normalizeTransitionIfObject, overwriteMetadata, overwriteTransitionIfObject } from './utils'; export class Transitiondatacondition { constructor(model: any) { Object.assign(this, model); - overwriteTransitionValueIfObject(this); - overwriteMetadataValue(this); + overwriteTransitionIfObject(this); + overwriteMetadata(this); } /** @@ -46,7 +46,7 @@ export class Transitiondatacondition { normalize = (): Transitiondatacondition => { const clone = new Transitiondatacondition(this); - normalizeTransitionProperty(clone); + normalizeTransitionIfObject(clone); return clone; }; diff --git a/src/lib/definitions/transitioneventcondition.ts b/src/lib/definitions/transitioneventcondition.ts index acd73c1..299ec4e 100644 --- a/src/lib/definitions/transitioneventcondition.ts +++ b/src/lib/definitions/transitioneventcondition.ts @@ -17,19 +17,19 @@ import { Eventdatafilter } from './eventdatafilter'; import { Metadata } from './metadata'; import { Transition } from './transition'; import { - normalizeTransitionProperty, - overwriteEventDataFilterValue, - overwriteMetadataValue, - overwriteTransitionValueIfObject, + normalizeTransitionIfObject, + overwriteEventDataFilter, + overwriteMetadata, + overwriteTransitionIfObject, } from './utils'; export class Transitioneventcondition { constructor(model: any) { Object.assign(this, model); - overwriteTransitionValueIfObject(this); - overwriteEventDataFilterValue(this); - overwriteMetadataValue(this); + overwriteTransitionIfObject(this); + overwriteEventDataFilter(this); + overwriteMetadata(this); } /** @@ -57,7 +57,7 @@ export class Transitioneventcondition { normalize = (): Transitioneventcondition => { const clone = new Transitioneventcondition(this); - normalizeTransitionProperty(clone); + normalizeTransitionIfObject(clone); return clone; }; diff --git a/src/lib/definitions/types.ts b/src/lib/definitions/types.ts index cbcd460..1faf9c0 100644 --- a/src/lib/definitions/types.ts +++ b/src/lib/definitions/types.ts @@ -26,10 +26,10 @@ import { Delaystate } from './delaystate'; import { Eventstate } from './eventstate'; import { Operationstate } from './operationstate'; import { Parallelstate } from './parallelstate'; -import { Subflowstate } from './subflowstate'; import { Injectstate } from './injectstate'; import { Foreachstate } from './foreachstate'; import { Callbackstate } from './callbackstate'; +import { Eventdef } from './eventdef'; export type CorrelationDefs = [ /* CloudEvent correlation definition */ CorrelationDef, @@ -41,13 +41,9 @@ export type Datacondition /* Switch state data based condition */ = | /* Switch state data based condition */ Enddatacondition; export type Retries = string /* uri */ | [Retrydef, ...Retrydef[]]; -export type Functions = - | string /* uri */ - | [ - // eslint-disable-next-line @typescript-eslint/ban-types - Function, - ...Function[] - ]; + +export type Functions = string /* uri */ | [Function, ...Function[]]; + export type Switchstate /* Permits transitions to other states based on data conditions */ = | Databasedswitch | /* Permits transitions to other states based on events */ Eventbasedswitch; @@ -55,6 +51,7 @@ export type Switchstate /* Permits transitions to other states based on data con export type Eventcondition /* Switch state data event condition */ = | Transitioneventcondition | /* Switch state data event condition */ Enddeventcondition; + export type States = [ ( | /* Causes the workflow execution to delay for a specified duration */ Delaystate @@ -62,7 +59,6 @@ export type States = [ | /* Defines actions be performed. Does not wait for incoming events */ Operationstate | /* Consists of a number of states that are executed in parallel */ Parallelstate | Switchstate - | /* Defines a sub-workflow to be executed */ Subflowstate | /* Inject static data into state data. Does not perform any actions */ Injectstate | /* Execute a set of defined actions or workflows for each element of a data array */ Foreachstate | /* This state performs an action, then waits for the callback event that denotes completion of the action */ Callbackstate @@ -73,9 +69,31 @@ export type States = [ | /* Defines actions be performed. Does not wait for incoming events */ Operationstate | /* Consists of a number of states that are executed in parallel */ Parallelstate | Switchstate - | /* Defines a sub-workflow to be executed */ Subflowstate | /* Inject static data into state data. Does not perform any actions */ Injectstate | /* Execute a set of defined actions or workflows for each element of a data array */ Foreachstate | /* This state performs an action, then waits for the callback event that denotes completion of the action */ Callbackstate )[] ]; + +/** + * Single branch execution timeout duration (ISO 8601 duration format) + */ +export type BranchExecTimeout = string; + +/** + * Single actions definition execution timeout duration (ISO 8601 duration format) + */ +export type ActionExecTimeout = string; +/** + * State execution timeout duration (ISO 8601 duration format) + */ +export type StateExecTimeout = string; + +/** + * Timeout duration to wait for consuming defined events (ISO 8601 duration format) + */ +export type EventTimeout = string; + +export type Secrets = string /* uri */ | [string, ...string[]]; + +export type Events = string /* uri */ | [Eventdef, ...Eventdef[]]; diff --git a/src/lib/definitions/utils.ts b/src/lib/definitions/utils.ts index 792313e..72d9c23 100644 --- a/src/lib/definitions/utils.ts +++ b/src/lib/definitions/utils.ts @@ -20,25 +20,27 @@ import { isObject } from '../utils'; * Modify the provided object, set the value to 'schedule' property as an instance of Specification.Schedule class, if the provided value is an object * @param object to set/overwrite the property */ -export function overwriteScheduleValueIfObject(object: { schedule: string | Specification.Schedule }): void { +export function overwriteScheduleIfObject(object: { schedule: string | Specification.Schedule }): void { if (isObject(object.schedule)) { object.schedule = new Specification.Schedule(object.schedule); } } /** - * Modify the provided object, set the value to 'repeat' property as an instance of Specification.Repeat class + * Modify the provided object, set the value to 'start' property as an instance of Specification.Startdef class, if the provided value is an object * @param object to set/overwrite the property */ -export function overwriteRepeatValue(object: { repeat?: Specification.Repeat }): void { - object.repeat = object.repeat && new Specification.Repeat(object.repeat); +export function overwriteStartIfObject(object: { start: string | Specification.Startdef }): void { + if (isObject(object.start)) { + object.start = new Specification.Startdef(object.start); + } } /** * Modify the provided object, set the value to 'end' property as an instance of Specification.End class, if the provided value is an object * @param object to set/overwrite the property */ -export function overwriteEndValueIfObject(object: { end?: boolean | Specification.End }): void { +export function overwriteEndIfObject(object: { end?: boolean | Specification.End }): void { if (isObject(object.end)) { object.end = new Specification.End(object.end); } @@ -48,7 +50,7 @@ export function overwriteEndValueIfObject(object: { end?: boolean | Specificatio * Modify the provided object, set the value to 'cron' property as an instance of Specification.Crondef class, if the provided value is an object * @param object to set/overwrite the property */ -export function overwriteCronValueIfObject(object: { cron?: string | Specification.Crondef }): void { +export function overwriteCronIfObject(object: { cron?: string | Specification.Crondef }): void { if (isObject(object.cron)) { object.cron = new Specification.Crondef(object.cron); } @@ -58,18 +60,18 @@ export function overwriteCronValueIfObject(object: { cron?: string | Specificati * Modify the provided object, set the value to 'transition' property as an instance of Specification.Transition class, if the provided value is an object * @param object to set/overwrite the property */ -export function overwriteTransitionValueIfObject(object: { transition?: string | Specification.Transition }): void { +export function overwriteTransitionIfObject(object: { transition?: string | Specification.Transition }): void { if (isObject(object.transition)) { object.transition = new Specification.Transition(object.transition); } } /** - * Modify the provided object, set the value to 'default' property as an instance of Specification.Defaultdef class + * Modify the provided object, set the value to 'defaultCondition' property as an instance of Specification.Defaultconditiondef class * @param object to set/overwrite the property */ -export function overwriteDefaultValue(object: { default?: Specification.Defaultdef }): void { - object.default = object.default && new Specification.Defaultdef(object.default); +export function overwriteDefaultCondition(object: { defaultCondition?: Specification.Defaultconditiondef }): void { + object.defaultCondition = object.defaultCondition && new Specification.Defaultconditiondef(object.defaultCondition); } /** @@ -77,7 +79,7 @@ export function overwriteDefaultValue(object: { default?: Specification.Defaultd * Throws an error if provided value is neither a Transitioneventcondition nor a Enddeventcondition * @param object to set/overwrite the property */ -export function overwriteEventConditionsValue(object: { eventConditions: Specification.Eventcondition[] }): void { +export function overwriteEventConditions(object: { eventConditions: Specification.Eventcondition[] }): void { if (Array.isArray(object.eventConditions)) { object.eventConditions = object.eventConditions.map((eventCondition: any) => { if (eventCondition.transition) { @@ -100,7 +102,7 @@ export function overwriteEventConditionsValue(object: { eventConditions: Specifi * Throws an error if provided value is neither a Transitiondatacondition nor a Enddatacondition * @param object to set/overwrite the property */ -export function overwriteDataConditionsValue(object: { dataConditions: Specification.Datacondition[] }): void { +export function overwriteDataConditions(object: { dataConditions: Specification.Datacondition[] }): void { if (Array.isArray(object.dataConditions)) { object.dataConditions = object.dataConditions.map((dataCondition: any) => { if (dataCondition.transition) { @@ -122,7 +124,7 @@ export function overwriteDataConditionsValue(object: { dataConditions: Specifica * Modify the provided object, set the value to 'actions' property as an instance of Specification.Action[] class * @param object to set/overwrite the property */ -export function overwriteActionsValue(object: { actions?: Specification.Action[] }): void { +export function overwriteActions(object: { actions?: Specification.Action[] }): void { if (Array.isArray(object.actions)) { object.actions = object.actions.map((v) => new Specification.Action(v)); } @@ -132,7 +134,7 @@ export function overwriteActionsValue(object: { actions?: Specification.Action[] * Modify the provided object, set the value to 'onEvents' property as an instance of Specification.Onevents[] class * @param object to set/overwrite the property */ -export function overwriteOnEventsValue(object: { onEvents: Specification.Onevents[] }): void { +export function overwriteOnEvents(object: { onEvents: Specification.Onevents[] }): void { object.onEvents = object.onEvents.map((event) => new Specification.Onevents(event)); } @@ -140,7 +142,7 @@ export function overwriteOnEventsValue(object: { onEvents: Specification.Onevent * Modify the provided object, set the value to 'stateDataFilter' property as an instance of Specification.Statedatafilter class * @param object to set/overwrite the property */ -export function overwriteStateDataFilterValue(object: { stateDataFilter?: Specification.Statedatafilter }): void { +export function overwriteStateDataFilter(object: { stateDataFilter?: Specification.Statedatafilter }): void { object.stateDataFilter = object.stateDataFilter && new Specification.Statedatafilter(object.stateDataFilter); } @@ -148,23 +150,15 @@ export function overwriteStateDataFilterValue(object: { stateDataFilter?: Specif * Modify the provided object, set the value to 'metadata' property as an instance of Specification.Metadata class * @param object to set/overwrite the property */ -export function overwriteMetadataValue(object: { metadata?: Specification.Metadata }): void { +export function overwriteMetadata(object: { metadata?: Specification.Metadata }): void { object.metadata = object.metadata && new Specification.Metadata(object.metadata); } -/** - * Modify the provided object, set the value to 'execTimeout' property as an instance of Specification.Exectimeout class - * @param object to set/overwrite the property - */ -export function overwriteExecTimeoutValue(object: { execTimeout?: Specification.Exectimeout }): void { - object.execTimeout = object.execTimeout && new Specification.Exectimeout(object.execTimeout); -} - /** * Modify the provided object, set the value to 'retries' property as an instance of Specification.Retries class * @param object to set/overwrite the property */ -export function overwriteRetriesValue(object: { retries?: Specification.Retries }) { +export function overwriteRetries(object: { retries?: Specification.Retries }) { if (Array.isArray(object.retries)) { object.retries = (object.retries as Specification.Retrydef[]).map( (f) => new Specification.Retrydef(f) @@ -176,7 +170,7 @@ export function overwriteRetriesValue(object: { retries?: Specification.Retries * Modify the provided object, set the value to 'events' property as an instance of Specification.Events class * @param object to set/overwrite the property */ -export function overwriteEventsValue(object: { events?: Specification.Events }) { +export function overwriteEvents(object: { events?: Specification.Events }) { if (Array.isArray(object.events)) { object.events = (object.events as Specification.Eventdef[]).map( (f) => new Specification.Eventdef(f) @@ -188,7 +182,7 @@ export function overwriteEventsValue(object: { events?: Specification.Events }) * Modify the provided object, set the value to 'functions' property as an instance of Specification.Functions class * @param object to set/overwrite the property */ -export function overwriteFunctionsValue(object: { functions?: Specification.Functions }) { +export function overwriteFunctions(object: { functions?: Specification.Functions }) { if (Array.isArray(object.functions)) { object.functions = (object.functions as Specification.Function[]).map( (f) => new Specification.Function(f) @@ -201,15 +195,21 @@ export function overwriteFunctionsValue(object: { functions?: Specification.Func * Throws an error if the value of the property type is not handler * @param object to set/overwrite the property */ -export function overwriteStatesValue(object: { states: Specification.States }) { +// + +export function overwriteStates(object: { states: Specification.States }) { object.states = object.states && ((object.states as Specification.States).map((v) => { switch (v.type) { - case 'inject': - return new Specification.Injectstate(v); - case 'subflow': - return new Specification.Subflowstate(v); + case 'delay': + return new Specification.Delaystate(v); + case 'event': + return new Specification.Eventstate(v); + case 'operation': + return new Specification.Operationstate(v); + case 'parallel': + return new Specification.Parallelstate(v); case 'switch': const switchState: any = v; if (switchState.dataConditions) { @@ -219,16 +219,10 @@ export function overwriteStatesValue(object: { states: Specification.States }) { return new Specification.Eventbasedswitch(v); } throw new Error(`Unexpected switch type; \n state value= ${JSON.stringify(v, null, 4)}`); - case 'operation': - return new Specification.Operationstate(v); - case 'event': - return new Specification.Eventstate(v); - case 'parallel': - return new Specification.Parallelstate(v); + case 'inject': + return new Specification.Injectstate(v); case 'foreach': return new Specification.Foreachstate(v); - case 'delay': - return new Specification.Delaystate(v); case 'callback': return new Specification.Callbackstate(v); default: @@ -241,7 +235,7 @@ export function overwriteStatesValue(object: { states: Specification.States }) { * Modify the provided object, set the value to 'correlation' property as an instance of Specification.CorrelationDefs class * @param object to set/overwrite the property */ -export function overwriteCorrelationValue(object: { correlation?: Specification.CorrelationDefs }): void { +export function overwriteCorrelation(object: { correlation?: Specification.CorrelationDefs }): void { if (Array.isArray(object.correlation)) { object.correlation = object.correlation.map( (correlation) => new Specification.CorrelationDef(correlation) @@ -253,15 +247,26 @@ export function overwriteCorrelationValue(object: { correlation?: Specification. * Modify the provided object, set the value to 'action' property as an instance of Specification.Action class * @param object to set/overwrite the property */ -export function overwriteActionValue(object: { action?: Specification.Action }): void { +export function overwriteAction(object: { action?: Specification.Action }): void { object.action = object.action && new Specification.Action(object.action); } +/** + * Modify the provided object, set the value to 'workflowExecTimeout' property as an instance of Specification.WorkflowExecTimeout class + * @param object to set/overwrite the property + */ +export function overwriteWorkflowExecTimeout(object: { + workflowExecTimeout?: Specification.WorkflowExecTimeout; +}): void { + object.workflowExecTimeout = + object.workflowExecTimeout && new Specification.WorkflowExecTimeout(object.workflowExecTimeout); +} + /** * Modify the provided object, set the value to 'eventDataFilter' property as an instance of Specification.Eventdatafilter class * @param object to set/overwrite the property */ -export function overwriteEventDataFilterValue(object: { eventDataFilter?: Specification.Eventdatafilter }): void { +export function overwriteEventDataFilter(object: { eventDataFilter?: Specification.Eventdatafilter }): void { object.eventDataFilter = object.eventDataFilter && new Specification.Eventdatafilter(object.eventDataFilter); } @@ -269,7 +274,7 @@ export function overwriteEventDataFilterValue(object: { eventDataFilter?: Specif * Modify the provided object, set the value to 'onErrors' property as an instance of Specification.Error[] class * @param object to set/overwrite the property */ -export function overwriteOnErrorsValue(object: { onErrors?: Specification.Error[] }): void { +export function overwriteOnErrors(object: { onErrors?: Specification.Error[] }): void { if (Array.isArray(object.onErrors)) { object.onErrors = object.onErrors.map((error) => new Specification.Error(error)); } @@ -279,7 +284,7 @@ export function overwriteOnErrorsValue(object: { onErrors?: Specification.Error[ * Modify the provided object, set the value to 'branches' property as an instance of Specification.Branch[] class * @param object to set/overwrite the property */ -export function overwriteBranchesValue(object: { branches?: Specification.Branch[] }): void { +export function overwriteBranches(object: { branches?: Specification.Branch[] }): void { if (Array.isArray(object.branches)) { object.branches = object.branches.map((v) => new Specification.Branch(v)); } @@ -289,27 +294,37 @@ export function overwriteBranchesValue(object: { branches?: Specification.Branch * Modify the provided object, set the value to 'produceEvents' property as an instance of Specification.Produceeventdef[] class * @param object to set/overwrite the property */ -export function overwriteProduceEventsValue(object: { produceEvents?: Specification.Produceeventdef[] }): void { +export function overwriteProduceEvents(object: { produceEvents?: Specification.Produceeventdef[] }): void { if (Array.isArray(object.produceEvents)) { object.produceEvents = object.produceEvents.map((produceEvent) => new Specification.Produceeventdef(produceEvent)); } } /** - * Modify the provided object, set the value to 'functionRef' property as an instance of Specification.Functionref class + * Modify the provided object, set the value to 'functionRef' property as an instance of Specification.Functionref class, if the provided value is an object * @param object to set/overwrite the property */ -export function overwriteFunctionRefValue(object: { functionRef: string | Specification.Functionref }): void { +export function overwriteFunctionRefIfObject(object: { functionRef?: string | Specification.Functionref }): void { if (isObject(object.functionRef)) { object.functionRef = new Specification.Functionref(object.functionRef); } } +/** + * Modify the provided object, set the value to 'subFlowRef' property as an instance of Specification.Subflowref class, if the provided value is an object + * @param object to set/overwrite the property + */ +export function overwriteSubFlowRefIfObject(object: { subFlowRef?: string | Specification.Subflowref }): void { + if (isObject(object.subFlowRef)) { + object.subFlowRef = new Specification.Subflowref(object.subFlowRef); + } +} + /** * Modify the provided object, set the value to 'eventRef' property as an instance of Specification.Eventref class * @param object to set/overwrite the property */ -export function overwriteEventRefValue(object: { eventRef?: Specification.Eventref }): void { +export function overwriteEventRef(object: { eventRef?: Specification.Eventref }): void { object.eventRef = object.eventRef && new Specification.Eventref(object.eventRef); } @@ -317,7 +332,7 @@ export function overwriteEventRefValue(object: { eventRef?: Specification.Eventr * Modify the provided object, set the value to 'actionDataFilter' property as an instance of Specification.Actiondatafilter class * @param object to set/overwrite the property */ -export function overwriteActionDataFilterValue(object: { actionDataFilter?: Specification.Actiondatafilter }): void { +export function overwriteActionDataFilter(object: { actionDataFilter?: Specification.Actiondatafilter }): void { object.actionDataFilter = object.actionDataFilter && new Specification.Actiondatafilter(object.actionDataFilter); } @@ -338,74 +353,94 @@ export function setEndValueIfNoTransition(object: { * Modify the provided object by normalizing the 'end' property. * @param object to be modified */ -export function normalizeEndProperty(object: { end?: boolean | Specification.End }) { +export function normalizeEndIfObject(object: { end?: boolean | Specification.End }) { if (isObject(object.end)) { object.end = (object.end as Specification.End).normalize(); } } + /** - * Modify the provided object by normalizing the 'actionMode' property, where the default value is 'parallel'. - * @param object to be modified + * Modify the provided object, deep cloning the value of the provided property + * @param property to be cloned + * @param object to set/overwrite the property */ -export function normalizeActionModeParallelProperty(object: { actionMode?: string }) { - if (object.actionMode === 'parallel') { - delete object.actionMode; +export function overwritePropertyAsPlainType(property: string, object: any): void { + if (isObject(object[property])) { + Object.assign(object, { [property]: JSON.parse(JSON.stringify(object[property])) }); } } /** - * Modify the provided object by normalizing the 'actionMode' property, where the default value is 'sequential'. - * @param object to be modified + * Modify the provided object, set the value to 'timeouts' property as an instance of Specification.Timeouts class + * @param object to set/overwrite the property */ -export function normalizeActionModeSequentialProperty(object: { actionMode?: string }) { - if (object.actionMode === 'sequential') { - delete object.actionMode; +export function overwriteTimeoutsIfObject(object: { timeouts?: string | Specification.Timeouts }): void { + if (isObject(object.timeouts)) { + object.timeouts = object.timeouts && new Specification.Timeouts(object.timeouts); } } /** - * Modify the provided object by normalizing the 'completionType' property, where the default value is 'and'. + * Modify the provided object by normalizing the 'end' property. * @param object to be modified */ -export function normalizeCompletionTypeProperty(object: { completionType?: string }) { - if (object.completionType === 'and') { - delete object.completionType; +export function normalizeSubFlowRefIfObject(object: { subFlowRef?: string | Specification.Subflowref }) { + if (isObject(object.subFlowRef)) { + object.subFlowRef = (object.subFlowRef as Specification.Subflowref).normalize(); } } /** - * Modify the provided object by normalizing the 'continueOnError' property, where the default value is 'false'. + * Modify the provided object by normalizing the 'defaultCondition' property. + * @param object to be modified + */ +export function normalizeDefaultCondition(object: { defaultCondition?: Specification.Defaultconditiondef }) { + object.defaultCondition = object.defaultCondition && object.defaultCondition.normalize(); +} + +/** + * Modify the provided object by normalizing the 'workflowExecTimeout' property. * @param object to be modified */ -export function normalizeContinueOnErrorProperty(object: { continueOnError?: boolean }) { - if (!object.continueOnError) { - delete object.continueOnError; +export function normalizeWorkflowExecTimeout(object: { workflowExecTimeout?: Specification.WorkflowExecTimeout }) { + object.workflowExecTimeout = object.workflowExecTimeout && object.workflowExecTimeout.normalize(); +} + +/** + * Modify the provided object by normalizing the 'waitForCompletion' property, where the default value is 'true'. + * @param object to be modified + */ +export function normalizeWaitForCompletion(object: { waitForCompletion?: boolean }) { + if (object.waitForCompletion) { + delete object.waitForCompletion; } } /** - * Modify the provided object by normalizing the 'checkBefore' property, where the default value is 'false'. + * Modify the provided object by normalizing the 'actionMode' property, where the default value is 'sequential'. * @param object to be modified */ -export function normalizeCheckBeforeProperty(object: { checkBefore?: boolean }) { - if (!object.checkBefore) { - delete object.checkBefore; +export function normalizeActionMode(object: { actionMode?: string }) { + if (object.actionMode === 'sequential') { + delete object.actionMode; } } /** - * Modify the provided object by normalizing the 'repeat' property. + * Modify the provided object by normalizing the 'completionType' property, where the default value is 'allOf'. * @param object to be modified */ -export function normalizeRepeatProperty(object: { repeat?: Specification.Repeat }) { - object.repeat = object.repeat && object.repeat.normalize(); +export function normalizeCompletionType(object: { completionType?: string }) { + if (object.completionType === 'allOf') { + delete object.completionType; + } } /** * Modify the provided object by normalizing the 'usedForCompensation' property, where the default value is 'false'. * @param object to be modified */ -export function normalizeUsedForCompensationProperty(object: { usedForCompensation?: boolean }) { +export function normalizeUsedForCompensation(object: { usedForCompensation?: boolean }) { if (!object.usedForCompensation) { delete object.usedForCompensation; } @@ -415,7 +450,7 @@ export function normalizeUsedForCompensationProperty(object: { usedForCompensati * Modify the provided object by normalizing the 'onEvents' property. * @param object to be modified */ -export function normalizeOnEventsProperty(object: { onEvents: Specification.Onevents[] }) { +export function normalizeOnEvents(object: { onEvents: Specification.Onevents[] }) { object.onEvents = object.onEvents && object.onEvents.map((onEvent) => onEvent.normalize()); } @@ -423,17 +458,45 @@ export function normalizeOnEventsProperty(object: { onEvents: Specification.Onev * Modify the provided object by normalizing the 'onErrors' property. * @param object to be modified */ -export function normalizeOnErrorsProperty(object: { onErrors?: Specification.Error[] }): void { +export function normalizeOnErrors(object: { onErrors?: Specification.Error[] }): void { if (Array.isArray(object.onErrors)) { object.onErrors = object.onErrors.map((error) => error.normalize()); } } +/** + * Modify the provided object by normalizing the 'branches' property. + * @param object to be modified + */ +export function normalizeBranches(object: { branches?: Specification.Branch[] }): void { + if (Array.isArray(object.branches)) { + object.branches = object.branches.map((branch) => branch.normalize()); + } +} + +/** + * Modify the provided object by normalizing the 'actions' property. + * @param object to be modified + */ +export function normalizeActions(object: { actions?: Specification.Action[] }): void { + if (Array.isArray(object.actions)) { + object.actions = object.actions.map((action) => action.normalize()); + } +} + +/** + * Modify the provided object by normalizing the 'action' property. + * @param object to be modified + */ +export function normalizeAction(object: { action?: Specification.Action }): void { + object.action = object.action && object.action.normalize(); +} + /** * Modify the provided object by normalizing the 'dataConditions' property. * @param object to be modified */ -export function normalizeDataConditionsProperty(object: { dataConditions?: Specification.Datacondition[] }): void { +export function normalizeDataConditions(object: { dataConditions?: Specification.Datacondition[] }): void { if (Array.isArray(object.dataConditions)) { object.dataConditions = object.dataConditions.map((dc) => dc.normalize()); } @@ -443,7 +506,7 @@ export function normalizeDataConditionsProperty(object: { dataConditions?: Speci * Modify the provided object by normalizing the 'eventConditions' property. * @param object to be modified */ -export function normalizeEventConditionsProperty(object: { eventConditions?: Specification.Eventcondition[] }): void { +export function normalizeEventConditions(object: { eventConditions?: Specification.Eventcondition[] }): void { if (Array.isArray(object.eventConditions)) { object.eventConditions = object.eventConditions.map((event) => event.normalize()); } @@ -453,7 +516,7 @@ export function normalizeEventConditionsProperty(object: { eventConditions?: Spe * Modify the provided object by normalizing the 'transition' property if property type is Specification.Transition. * @param object to be modified */ -export function normalizeTransitionProperty(object: { transition?: string | Specification.Transition }) { +export function normalizeTransitionIfObject(object: { transition?: string | Specification.Transition }) { if (isObject(object.transition)) { object.transition = (object.transition as Specification.Transition).normalize(); } @@ -463,7 +526,7 @@ export function normalizeTransitionProperty(object: { transition?: string | Spec * Modify the provided object by normalizing the 'compensate' property, where the default value is 'false'. * @param object to be modified */ -export function normalizeCompensateProperty(object: { compensate?: boolean }) { +export function normalizeCompensate(object: { compensate?: boolean }) { if (!object.compensate) { delete object.compensate; } @@ -473,7 +536,7 @@ export function normalizeCompensateProperty(object: { compensate?: boolean }) { * Modify the provided object by normalizing the 'terminate' property, where the default value is 'false'. * @param object to be modified */ -export function normalizeTerminateProperty(object: { terminate?: boolean }) { +export function normalizeTerminate(object: { terminate?: boolean }) { if (!object.terminate) { delete object.terminate; } @@ -483,7 +546,7 @@ export function normalizeTerminateProperty(object: { terminate?: boolean }) { * Modify the provided object by normalizing the 'exclusive' property, where the default value is 'true'. * @param object to be modified */ -export function normalizeExclusiveProperty(object: { exclusive?: boolean }) { +export function normalizeExclusive(object: { exclusive?: boolean }) { if (object.exclusive) { delete object.exclusive; } @@ -493,7 +556,7 @@ export function normalizeExclusiveProperty(object: { exclusive?: boolean }) { * Modify the provided object by normalizing the 'keepActive' property, where the default value is 'true'. * @param object to be modified */ -export function normalizeKeepActiveProperty(object: { keepActive?: boolean }) { +export function normalizeKeepActive(object: { keepActive?: boolean }) { if (object.keepActive) { delete object.keepActive; } @@ -503,18 +566,18 @@ export function normalizeKeepActiveProperty(object: { keepActive?: boolean }) { * Modify the provided object by normalizing the 'expressionLang' property, where the default value is 'jq'. * @param object to be modified */ -export function normalizeExpressionLangProperty(object: { expressionLang?: string }) { +export function normalizeExpressionLang(object: { expressionLang?: string }) { if (object.expressionLang === 'jq') { delete object.expressionLang; } } /** - * Modify the provided object by normalizing the 'interrupt' property, where the default value is 'false'. + * Modify the provided object by normalizing the 'interrupt' property, where the default value is 'true'. * @param object to be modified */ -export function normalizeInterruptProperty(object: { interrupt?: boolean }) { - if (!object.interrupt) { +export function normalizeInterrupt(object: { interrupt?: boolean }) { + if (object.interrupt) { delete object.interrupt; } } @@ -523,7 +586,7 @@ export function normalizeInterruptProperty(object: { interrupt?: boolean }) { * Modify the provided object by normalizing the 'type' property, where the default value is 'rest'. * @param object to be modified */ -export function normalizeTypeRestProperty(object: { type?: string }) { +export function normalizeType(object: { type?: string }) { if (object.type === 'rest') { delete object.type; } @@ -533,12 +596,22 @@ export function normalizeTypeRestProperty(object: { type?: string }) { * Modify the provided object by normalizing the 'kind' property, where the default value is 'consumed'. * @param object to be modified */ -export function normalizeKindProperty(object: { kind?: string }) { +export function normalizeKind(object: { kind?: string }) { if (object.kind === 'consumed') { delete object.kind; } } +/** + * Modify the provided object by normalizing the 'dataOnly' property, where the default value is 'true'. + * @param object to be modified + */ +export function normalizeDataOnly(object: { dataOnly?: boolean }) { + if (object.dataOnly) { + delete object.dataOnly; + } +} + /** * Modify the provided object by normalizing the 'states' property. * @param object to be modified @@ -574,9 +647,11 @@ export function normalizeEvents(object: { events?: Specification.Events }) { } /** - * Modify the provided object by normalizing the 'execTimeout' property. + * Modify the provided object by normalizing the 'timeouts' property. * @param object to be modified */ -export function normalizeExecTimeout(object: { execTimeout?: Specification.Exectimeout }) { - object.execTimeout = object.execTimeout && object.execTimeout.normalize(); +export function normalizeTimeoutsIfObject(object: { timeouts?: string /* uri */ | Specification.Timeouts }) { + if (isObject(object.timeouts)) { + object.timeouts = object.timeouts && object.timeouts.normalize(); + } } diff --git a/src/lib/definitions/workflow.ts b/src/lib/definitions/workflow.ts index 3378a81..1b26992 100644 --- a/src/lib/definitions/workflow.ts +++ b/src/lib/definitions/workflow.ts @@ -17,25 +17,26 @@ import { Specification } from '.'; import * as yaml from 'js-yaml'; import { validate } from '../utils'; -import { Events } from './events'; -import { Exectimeout } from './exectimeout'; import { Metadata } from './metadata'; import { Startdef } from './startdef'; -import { Functions, Retries, States } from './types'; +import { Events, Functions, Retries, Secrets, States } from './types'; import { normalizeEvents, - normalizeExecTimeout, - normalizeExpressionLangProperty, + normalizeExpressionLang, normalizeFunctions, - normalizeKeepActiveProperty, + normalizeKeepActive, normalizeStates, - overwriteEventsValue, - overwriteExecTimeoutValue, - overwriteFunctionsValue, - overwriteMetadataValue, - overwriteRetriesValue, - overwriteStatesValue, + normalizeTimeoutsIfObject, + overwriteEvents, + overwriteFunctions, + overwriteMetadata, + overwritePropertyAsPlainType, + overwriteRetries, + overwriteStartIfObject, + overwriteStates, + overwriteTimeoutsIfObject, } from './utils'; +import { Timeouts } from './timeouts'; export class Workflow { constructor(model: any) { @@ -46,18 +47,25 @@ export class Workflow { Object.assign(this, defaultModel, model); - overwriteFunctionsValue(this); - overwriteStatesValue(this); - overwriteEventsValue(this); - overwriteRetriesValue(this); - overwriteExecTimeoutValue(this); - overwriteMetadataValue(this); + overwritePropertyAsPlainType('dataInputSchema', this); + overwritePropertyAsPlainType('constants', this); + overwriteStartIfObject(this); + overwriteTimeoutsIfObject(this); + overwriteMetadata(this); + overwriteEvents(this); + overwriteFunctions(this); + overwriteRetries(this); + overwriteStates(this); } /** * Workflow unique identifier */ id: string; + /** + * Domain-specific workflow identifier + */ + key?: string; /** * Workflow name */ @@ -69,19 +77,41 @@ export class Workflow { /** * Workflow version */ - version: string; + version?: string; + /** + * List of helpful terms describing the workflows intended purpose, subject areas, or other important qualities + */ + annotations?: [string, ...string[]]; + dataInputSchema?: + | string + | { + /** + * URI of the JSON Schema used to validate the workflow data input + */ + schema: string; + /** + * Determines if workflow execution should continue if there are validation errors + */ + failOnValidationErrors: boolean; + }; + secrets?: Secrets; + constants?: + | string /* uri */ + | { + [key: string]: any; + }; start: string | Startdef; /** * Serverless Workflow schema version */ - schemaVersion?: string; + specVersion: string; /** * Identifies the expression language used for workflow expressions. Default is 'jq' */ expressionLang?: string; - execTimeout?: Exectimeout; + timeouts?: string /* uri */ | Timeouts; /** - * If 'true', workflow instances is not terminated when there are no active execution paths. Instance can be terminated via 'terminate end definition' or reaching defined 'execTimeout' + * If 'true', workflow instances is not terminated when there are no active execution paths. Instance can be terminated via 'terminate end definition' or reaching defined 'workflowExecTimeout' */ keepActive?: boolean; metadata?: /* Metadata information */ Metadata; @@ -92,23 +122,20 @@ export class Workflow { * State definitions */ states: States; - /** * Normalize the value of each property by recursively deleting properties whose value is equal to its default value. Does not modify the object state. * @returns {Specification.Workflow} without deleted properties. */ normalize = (): Workflow => { const clone = new Workflow(this); - normalizeKeepActiveProperty(clone); - - normalizeExpressionLangProperty(clone); - - normalizeStates(clone); - normalizeFunctions(clone); + normalizeExpressionLang(clone); + normalizeTimeoutsIfObject(clone); + normalizeKeepActive(clone); normalizeEvents(clone); + normalizeFunctions(clone); + normalizeStates(clone); - normalizeExecTimeout(clone); return clone; }; diff --git a/src/lib/definitions/exectimeout.ts b/src/lib/definitions/workflowExecTimeout.ts similarity index 70% rename from src/lib/definitions/exectimeout.ts rename to src/lib/definitions/workflowExecTimeout.ts index ff6a2fc..a0b0483 100644 --- a/src/lib/definitions/exectimeout.ts +++ b/src/lib/definitions/workflowExecTimeout.ts @@ -14,15 +14,16 @@ * limitations under the License. */ -import { normalizeInterruptProperty } from './utils'; +import { normalizeInterrupt } from './utils'; -export class Exectimeout { +export class WorkflowExecTimeout { constructor(model: any) { - Object.assign(this, model); + const defaultModel = { interrupt: true }; + Object.assign(this, defaultModel, model); } /** - * Timeout duration (ISO 8601 duration format) + * Workflow execution timeout duration (ISO 8601 duration format). If not specified should be 'unlimited' */ duration: string; /** @@ -36,12 +37,13 @@ export class Exectimeout { /** * Normalize the value of each property by recursively deleting properties whose value is equal to its default value. Does not modify the object state. - * @returns {Specification.Exectimeout} without deleted properties. + * @returns {Specification.WorkflowExecTimeout} without deleted properties. */ - normalize = (): Exectimeout => { - const clone = new Exectimeout(this); - normalizeInterruptProperty(clone); + normalize = (): WorkflowExecTimeout => { + const clone = new WorkflowExecTimeout(this); + + normalizeInterrupt(clone); return clone; }; diff --git a/src/lib/schema/__merged.json b/src/lib/schema/__merged.json index 03caead..031315d 100644 --- a/src/lib/schema/__merged.json +++ b/src/lib/schema/__merged.json @@ -1,5 +1,5 @@ { - "$id": "https://serverlessworkflow.io/schemas/0.6/workflow.json", + "$id": "https://serverlessworkflow.io/schemas/0.7/workflow.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Serverless Workflow specification - workflow schema", "type": "object", @@ -9,6 +9,11 @@ "description": "Workflow unique identifier", "minLength": 1 }, + "key": { + "type": "string", + "description": "Domain-specific workflow identifier", + "minLength": 1 + }, "name": { "type": "string", "description": "Workflow name", @@ -23,10 +28,65 @@ "description": "Workflow version", "minLength": 1 }, + "annotations": { + "type": "array", + "description": "List of helpful terms describing the workflows intended purpose, subject areas, or other important qualities", + "minItems": 1, + "items": { + "type": "string" + }, + "additionalItems": false + }, + "dataInputSchema": { + "oneOf": [ + { + "type": "string", + "description": "URI of the JSON Schema used to validate the workflow data input", + "minLength": 1 + }, + { + "type": "object", + "description": "Workflow data input schema definition", + "properties": { + "schema": { + "type": "string", + "description": "URI of the JSON Schema used to validate the workflow data input", + "minLength": 1 + }, + "failOnValidationErrors": { + "type": "boolean", + "default": true, + "description": "Determines if workflow execution should continue if there are validation errors" + } + }, + "additionalProperties": false, + "required": [ + "schema", + "failOnValidationErrors" + ] + } + ] + }, + "secrets": { + "$ref": "#/definitions/secrets" + }, + "constants": { + "oneOf": [ + { + "type": "string", + "format": "uri", + "description": "URI to a resource containing constants data (json or yaml)" + }, + { + "type": "object", + "description": "Workflow constants data (object type)" + } + ] + }, "start": { "$ref": "#/definitions/startdef" }, - "schemaVersion": { + "specVersion": { "type": "string", "description": "Serverless Workflow schema version", "minLength": 1 @@ -37,13 +97,13 @@ "default": "jq", "minLength": 1 }, - "execTimeout": { - "$ref": "#/definitions/exectimeout" + "timeouts": { + "$ref": "#/definitions/timeouts" }, "keepActive": { "type": "boolean", "default": false, - "description": "If 'true', workflow instances is not terminated when there are no active execution paths. Instance can be terminated via 'terminate end definition' or reaching defined 'execTimeout'" + "description": "If 'true', workflow instances is not terminated when there are no active execution paths. Instance can be terminated via 'terminate end definition' or reaching defined 'workflowExecTimeout'" }, "metadata": { "$ref": "#/definitions/metadata" @@ -82,10 +142,6 @@ "title": "Switch State", "$ref": "#/definitions/switchstate" }, - { - "title": "SubFlow State", - "$ref": "#/definitions/subflowstate" - }, { "title": "Inject State", "$ref": "#/definitions/injectstate" @@ -104,12 +160,25 @@ "minItems": 1 } }, - "required": [ - "id", - "name", - "version", - "start", - "states" + "oneOf": [ + { + "required": [ + "id", + "specVersion", + "name", + "start", + "states" + ] + }, + { + "required": [ + "key", + "specVersion", + "name", + "start", + "states" + ] + } ], "definitions": { "crondef": { @@ -139,30 +208,6 @@ } ] }, - "exectimeout": { - "type": "object", - "properties": { - "duration": { - "type": "string", - "description": "Timeout duration (ISO 8601 duration format)", - "minLength": 1 - }, - "interrupt": { - "type": "boolean", - "description": "If `false`, workflow instance is allowed to finish current execution. If `true`, current workflow execution is abrupted.", - "default": false - }, - "runBefore": { - "type": "string", - "description": "Name of a workflow state to be executed before workflow instance is terminated", - "minLength": 1 - } - }, - "additionalProperties": false, - "required": [ - "duration" - ] - }, "transition": { "oneOf": [ { @@ -262,7 +307,7 @@ "sequential", "parallel" ], - "description": "Specifies how actions are to be performed (in sequence of parallel)", + "description": "Specifies how actions are to be performed (in sequence or in parallel)", "default": "sequential" }, "actions": { @@ -299,9 +344,9 @@ "description": "References a 'trigger' and 'result' reusable event definitions", "$ref": "#/definitions/eventref" }, - "timeout": { - "type": "string", - "description": "Time period to wait for function execution to complete" + "subFlowRef": { + "description": "References a sub-workflow to invoke", + "$ref": "#/definitions/subflowref" }, "actionDataFilter": { "description": "Action data filter", @@ -319,6 +364,11 @@ "required": [ "eventRef" ] + }, + { + "required": [ + "subFlowRef" + ] } ] }, @@ -340,6 +390,10 @@ "arguments": { "type": "object", "description": "Function arguments/inputs" + }, + "selectionSet": { + "type": "string", + "description": "Only used if function type is 'graphql'. A string containing a valid GraphQL selection set" } }, "additionalProperties": false, @@ -382,6 +436,38 @@ "resultEventRef" ] }, + "subflowref": { + "oneOf": [ + { + "type": "string", + "description": "Unique id of the sub-workflow to be invoked", + "minLength": 1 + }, + { + "type": "object", + "description": "Specifies a sub-workflow to be invoked", + "properties": { + "waitForCompletion": { + "type": "boolean", + "default": true, + "description": "Workflow execution must wait for sub-workflow to finish before continuing" + }, + "workflowId": { + "type": "string", + "description": "Unique id of the sub-workflow to be invoked" + }, + "version": { + "type": "string", + "description": "Version of the sub-workflow to be invoked", + "minLength": 1 + } + }, + "required": [ + "workflowId" + ] + } + ] + }, "branch": { "type": "object", "description": "Branch Definition", @@ -390,6 +476,19 @@ "type": "string", "description": "Branch name" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "actionExecTimeout": { + "$ref": "#/definitions/actionExecTimeout" + }, + "branchExecTimeout": { + "$ref": "#/definitions/branchExecTimeout" + } + }, + "required": [] + }, "actions": { "type": "array", "description": "Actions to be executed in this branch", @@ -398,26 +497,12 @@ "$ref": "#/definitions/action" }, "additionalItems": false - }, - "workflowId": { - "type": "string", - "description": "Unique Id of a workflow to be executed in this branch" } }, "additionalProperties": false, - "oneOf": [ - { - "required": [ - "name", - "workflowId" - ] - }, - { - "required": [ - "name", - "actions" - ] - } + "required": [ + "name", + "actions" ] }, "delaystate": { @@ -450,6 +535,16 @@ "type": "string", "description": "Amount of time (ISO 8601 format) to delay" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + } + }, + "required": [] + }, "onErrors": { "type": "array", "description": "States error handling and retries definitions", @@ -548,9 +643,21 @@ }, "additionalItems": false }, - "timeout": { - "type": "string", - "description": "Time period to wait for incoming events (ISO 8601 format)" + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + }, + "actionExecTimeout": { + "$ref": "#/definitions/actionExecTimeout" + }, + "eventTimeout": { + "$ref": "#/definitions/eventTimeout" + } + }, + "required": [] }, "stateDataFilter": { "description": "State data filter", @@ -645,6 +752,19 @@ "$ref": "#/definitions/action" } }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + }, + "actionExecTimeout": { + "$ref": "#/definitions/actionExecTimeout" + } + }, + "required": [] + }, "onErrors": { "type": "array", "description": "States error handling and retries definitions", @@ -707,6 +827,14 @@ "actions", "transition" ] + }, + { + "required": [ + "name", + "type", + "actions", + "end" + ] } ] } @@ -737,6 +865,19 @@ "description": "State data filter", "$ref": "#/definitions/statedatafilter" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + }, + "branchExecTimeout": { + "$ref": "#/definitions/branchExecTimeout" + } + }, + "required": [] + }, "branches": { "type": "array", "description": "Branch Definitions", @@ -749,21 +890,20 @@ "completionType": { "type": "string", "enum": [ - "and", - "xor", - "n_of_m" + "allOf", + "atLeast" ], "description": "Option types on how to complete branch execution.", - "default": "and" + "default": "allOf" }, - "n": { + "numCompleted": { "type": [ "number", "string" ], "minimum": 0, "minLength": 0, - "description": "Used when completionType is set to 'n_of_m' to specify the 'N' value" + "description": "Used when completionType is set to 'atLeast' to specify the minimum number of branches that must complete before the state will transition." }, "onErrors": { "type": "array", @@ -863,6 +1003,19 @@ "description": "State data filter", "$ref": "#/definitions/statedatafilter" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + }, + "eventTimeout": { + "$ref": "#/definitions/eventTimeout" + } + }, + "required": [] + }, "eventConditions": { "type": "array", "description": "Defines conditions evaluated against events", @@ -881,13 +1034,9 @@ }, "additionalItems": false }, - "eventTimeout": { - "type": "string", - "description": "If eventConditions is used, defines the time period to wait for events (ISO 8601 format)" - }, - "default": { + "defaultCondition": { "description": "Default transition of the workflow if there is no matching data conditions. Can include a transition or end definition", - "$ref": "#/definitions/defaultdef" + "$ref": "#/definitions/defaultconditiondef" }, "compensatedBy": { "type": "string", @@ -932,6 +1081,16 @@ "description": "State data filter", "$ref": "#/definitions/statedatafilter" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + } + }, + "required": [] + }, "dataConditions": { "type": "array", "description": "Defines conditions evaluated against state data", @@ -950,9 +1109,9 @@ }, "additionalItems": false }, - "default": { + "defaultCondition": { "description": "Default transition of the workflow if there is no matching data conditions. Can include a transition or end definition", - "$ref": "#/definitions/defaultdef" + "$ref": "#/definitions/defaultconditiondef" }, "compensatedBy": { "type": "string", @@ -975,9 +1134,9 @@ "dataConditions" ] }, - "defaultdef": { + "defaultconditiondef": { "type": "object", - "description": "Default definition. Can be either a transition or end definition", + "description": "DefaultCondition definition. Can be either a transition or end definition", "properties": { "transition": { "$ref": "#/definitions/transition" @@ -1132,9 +1291,9 @@ "end" ] }, - "subflowstate": { + "injectstate": { "type": "object", - "description": "Defines a sub-workflow to be executed", + "description": "Inject static data into state data. Does not perform any actions", "properties": { "id": { "type": "string", @@ -1147,41 +1306,33 @@ }, "type": { "type": "string", - "const": "subflow", + "const": "inject", "description": "State type" }, "end": { "$ref": "#/definitions/end", "description": "State end definition" }, - "waitForCompletion": { - "type": "boolean", - "default": false, - "description": "Workflow execution must wait for sub-workflow to finish before continuing" - }, - "workflowId": { - "type": "string", - "description": "Sub-workflow unique id" + "data": { + "type": "object", + "description": "JSON object which can be set as states data input and can be manipulated via filters" }, - "repeat": { - "$ref": "#/definitions/repeat", - "description": "SubFlow state repeat exec definition" + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + } + }, + "required": [] }, "stateDataFilter": { "description": "State data filter", "$ref": "#/definitions/statedatafilter" }, - "onErrors": { - "type": "array", - "description": "States error handling and retries definitions", - "items": { - "type": "object", - "$ref": "#/definitions/error" - }, - "additionalItems": false - }, "transition": { - "description": "Next transition of the workflow after SubFlow has completed execution", + "description": "Next transition of the workflow after injection has completed", "$ref": "#/definitions/transition" }, "compensatedBy": { @@ -1204,13 +1355,16 @@ "usedForCompensation": { "const": true } - } + }, + "required": [ + "usedForCompensation" + ] }, "then": { "required": [ "name", "type", - "workflowId" + "data" ] }, "else": { @@ -1219,7 +1373,7 @@ "required": [ "name", "type", - "workflowId", + "data", "end" ] }, @@ -1227,20 +1381,20 @@ "required": [ "name", "type", - "workflowId", + "data", "transition" ] } ] } }, - "injectstate": { + "foreachstate": { "type": "object", - "description": "Inject static data into state data. Does not perform any actions", + "description": "Execute a set of defined actions or workflows for each element of a data array", "properties": { "id": { "type": "string", - "description": "Unique state id", + "description": "Unique State id", "minLength": 1 }, "name": { @@ -1249,149 +1403,71 @@ }, "type": { "type": "string", - "const": "inject", + "const": "foreach", "description": "State type" }, "end": { "$ref": "#/definitions/end", "description": "State end definition" }, - "data": { + "inputCollection": { + "type": "string", + "description": "Workflow expression selecting an array element of the states data" + }, + "outputCollection": { + "type": "string", + "description": "Workflow expression specifying an array element of the states data to add the results of each iteration" + }, + "iterationParam": { + "type": "string", + "description": "Name of the iteration parameter that can be referenced in actions/workflow. For each parallel iteration, this param should contain an unique element of the inputCollection array" + }, + "max": { + "type": [ + "number", + "string" + ], + "minimum": 0, + "minLength": 0, + "description": "Specifies how upper bound on how many iterations may run in parallel" + }, + "actions": { + "type": "array", + "description": "Actions to be executed for each of the elements of inputCollection", + "items": { + "type": "object", + "$ref": "#/definitions/action" + }, + "additionalItems": false + }, + "timeouts": { "type": "object", - "description": "JSON object which can be set as states data input and can be manipulated via filters" + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + }, + "actionExecTimeout": { + "$ref": "#/definitions/actionExecTimeout" + } + }, + "required": [] }, "stateDataFilter": { "description": "State data filter", "$ref": "#/definitions/statedatafilter" }, + "onErrors": { + "type": "array", + "description": "States error handling and retries definitions", + "items": { + "type": "object", + "$ref": "#/definitions/error" + }, + "additionalItems": false + }, "transition": { - "description": "Next transition of the workflow after subflow has completed", - "$ref": "#/definitions/transition" - }, - "compensatedBy": { - "type": "string", - "minLength": 1, - "description": "Unique Name of a workflow state which is responsible for compensation of this state" - }, - "usedForCompensation": { - "type": "boolean", - "default": false, - "description": "If true, this state is used to compensate another state. Default is false" - }, - "metadata": { - "$ref": "#/definitions/metadata" - } - }, - "additionalProperties": false, - "if": { - "properties": { - "usedForCompensation": { - "const": true - } - }, - "required": [ - "usedForCompensation" - ] - }, - "then": { - "required": [ - "name", - "type", - "data" - ] - }, - "else": { - "oneOf": [ - { - "required": [ - "name", - "type", - "data", - "end" - ] - }, - { - "required": [ - "name", - "type", - "data", - "transition" - ] - } - ] - } - }, - "foreachstate": { - "type": "object", - "description": "Execute a set of defined actions or workflows for each element of a data array", - "properties": { - "id": { - "type": "string", - "description": "Unique State id", - "minLength": 1 - }, - "name": { - "type": "string", - "description": "State name" - }, - "type": { - "type": "string", - "const": "foreach", - "description": "State type" - }, - "end": { - "$ref": "#/definitions/end", - "description": "State end definition" - }, - "inputCollection": { - "type": "string", - "description": "Workflow expression selecting an array element of the states data" - }, - "outputCollection": { - "type": "string", - "description": "Workflow expression specifying an array element of the states data to add the results of each iteration" - }, - "iterationParam": { - "type": "string", - "description": "Name of the iteration parameter that can be referenced in actions/workflow. For each parallel iteration, this param should contain an unique element of the inputCollection array" - }, - "max": { - "type": [ - "number", - "string" - ], - "minimum": 0, - "minLength": 0, - "description": "Specifies how upper bound on how many iterations may run in parallel" - }, - "actions": { - "type": "array", - "description": "Actions to be executed for each of the elements of inputCollection", - "items": { - "type": "object", - "$ref": "#/definitions/action" - }, - "additionalItems": false - }, - "workflowId": { - "type": "string", - "description": "Unique Id of a workflow to be executed for each of the elements of inputCollection" - }, - "stateDataFilter": { - "description": "State data filter", - "$ref": "#/definitions/statedatafilter" - }, - "onErrors": { - "type": "array", - "description": "States error handling and retries definitions", - "items": { - "type": "object", - "$ref": "#/definitions/error" - }, - "additionalItems": false - }, - "transition": { - "description": "Next transition of the workflow after state has completed", + "description": "Next transition of the workflow after state has completed", "$ref": "#/definitions/transition" }, "compensatedBy": { @@ -1425,31 +1501,11 @@ "type", "inputCollection", "iterationParam", - "workflowId" + "actions" ] }, "else": { "oneOf": [ - { - "required": [ - "name", - "type", - "inputCollection", - "iterationParam", - "workflowId", - "end" - ] - }, - { - "required": [ - "name", - "type", - "inputCollection", - "iterationParam", - "workflowId", - "transition" - ] - }, { "required": [ "name", @@ -1499,9 +1555,21 @@ "type": "string", "description": "References an unique callback event name in the defined workflow events" }, - "timeout": { - "type": "string", - "description": "Time period to wait for incoming events (ISO 8601 format)" + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + }, + "actionExecTimeout": { + "$ref": "#/definitions/actionExecTimeout" + }, + "eventTimeout": { + "$ref": "#/definitions/eventTimeout" + } + }, + "required": [] }, "eventDataFilter": { "description": "Event data filter", @@ -1558,8 +1626,7 @@ "name", "type", "action", - "eventRef", - "timeout" + "eventRef" ] }, "else": { @@ -1570,7 +1637,6 @@ "type", "action", "eventRef", - "timeout", "end" ] }, @@ -1580,7 +1646,6 @@ "type", "action", "eventRef", - "timeout", "transition" ] } @@ -1740,11 +1805,11 @@ "properties": { "data": { "type": "string", - "description": "Workflow expression that filters of the event data (payload)" + "description": "Workflow expression that filters the received event/payload (default: '${ . }')" }, "toStateData": { "type": "string", - "description": " Workflow expression that selects a state data element to which the event payload should be added/merged into. If not specified, denotes, the top-level state data element." + "description": " Workflow expression that selects a state data element to which the filtered event should be added/merged into. If not specified, denotes, the top-level state data element." } }, "additionalProperties": false, @@ -1769,97 +1834,59 @@ "additionalProperties": false, "required": [] }, - "repeat": { - "type": "object", - "properties": { - "expression": { + "workflowExecTimeout": { + "oneOf": [ + { "type": "string", - "description": "Expression evaluated against SubFlow state data. SubFlow will repeat execution as long as this expression is true or until the max property count is reached", + "description": "Workflow execution timeout duration (ISO 8601 duration format). If not specified should be 'unlimited'", "minLength": 1 }, - "checkBefore": { - "type": "boolean", - "description": "If true, the expression is evaluated before each repeat execution, if false the expression is evaluated after each repeat execution", - "default": true - }, - "max": { - "type": "integer", - "description": "Sets the maximum amount of repeat executions", - "minimum": 0 - }, - "continueOnError": { - "type": "boolean", - "description": "If true, repeats executions in a case unhandled errors propagate from the sub-workflow to this state", - "default": false - }, - "stopOnEvents": { - "type": "array", - "description": "List referencing defined consumed workflow events. SubFlow will repeat execution until one of the defined events is consumed, or until the max property count is reached", - "minItems": 1, - "items": { - "type": "string" + { + "type": "object", + "properties": { + "duration": { + "type": "string", + "description": "Workflow execution timeout duration (ISO 8601 duration format). If not specified should be 'unlimited'", + "minLength": 1 + }, + "interrupt": { + "type": "boolean", + "description": "If `false`, workflow instance is allowed to finish current execution. If `true`, current workflow execution is abrupted.", + "default": true + }, + "runBefore": { + "type": "string", + "description": "Name of a workflow state to be executed before workflow instance is terminated", + "minLength": 1 + } }, - "additionalItems": false - } - }, - "additionalProperties": false, - "required": [] - }, - "retrydef": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Unique retry strategy name", - "minLength": 1 - }, - "delay": { - "type": "string", - "description": "Time delay between retry attempts (ISO 8601 duration format)" - }, - "maxDelay": { - "type": "string", - "description": "Maximum time delay between retry attempts (ISO 8601 duration format)" - }, - "increment": { - "type": "string", - "description": "Static value by which the delay increases during each attempt (ISO 8601 time format)" - }, - "multiplier": { - "type": [ - "number", - "string" - ], - "minimum": 0, - "minLength": 1, - "multipleOf": 0.01, - "description": "Numeric value, if specified the delay between retries is multiplied by this value." - }, - "maxAttempts": { - "type": [ - "number", - "string" - ], - "minimum": 1, - "minLength": 0, - "description": "Maximum number of retry attempts." - }, - "jitter": { - "type": [ - "number", - "string" - ], - "minimum": 0, - "maximum": 1, - "description": "If float type, maximum amount of random time added or subtracted from the delay between each retry relative to total delay (between 0 and 1). If string type, absolute maximum amount of random time added or subtracted from the delay between each retry (ISO 8601 duration format)" + "additionalProperties": false, + "required": [ + "duration" + ] } - }, - "additionalProperties": false, - "required": [ - "name", - "maxAttempts" ] }, + "stateExecTimeout": { + "type": "string", + "description": "State execution timeout duration (ISO 8601 duration format)", + "minLength": 1 + }, + "actionExecTimeout": { + "type": "string", + "description": "Single actions definition execution timeout duration (ISO 8601 duration format)", + "minLength": 1 + }, + "branchExecTimeout": { + "type": "string", + "description": "Single branch execution timeout duration (ISO 8601 duration format)", + "minLength": 1 + }, + "eventTimeout": { + "type": "string", + "description": "Timeout duration to wait for consuming defined events (ISO 8601 duration format)", + "minLength": 1 + }, "metadata": { "type": "object", "description": "Metadata information", @@ -1867,36 +1894,6 @@ "type": "string" } }, - "function": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Unique function name", - "minLength": 1 - }, - "operation": { - "type": "string", - "description": "If type is `rest`, #. If type is `rpc`, ##. If type is `expression`, defines the workflow expression.", - "minLength": 1 - }, - "type": { - "type": "string", - "description": "Defines the function type. Is either `rest`, `rpc` or `expression`. Default is `rest`", - "enum": [ - "rest", - "rpc", - "expression" - ], - "default": "rest" - } - }, - "additionalProperties": false, - "required": [ - "name", - "operation" - ] - }, "eventdef": { "type": "object", "properties": { @@ -1932,6 +1929,11 @@ }, "additionalItems": false }, + "dataOnly": { + "type": "boolean", + "default": true, + "description": "If `true`, only the Event payload is accessible to consuming Workflow states. If `false`, both event payload and context attributes should be accessible " + }, "metadata": { "$ref": "#/definitions/metadata", "description": "Metadata information" @@ -1979,6 +1981,141 @@ "contextAttributeName" ] }, + "function": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Unique function name", + "minLength": 1 + }, + "operation": { + "type": "string", + "description": "If type is `rest`, #. If type is `rpc`, ##. If type is `graphql`, ##. If type is `expression`, defines the workflow expression.", + "minLength": 1 + }, + "type": { + "type": "string", + "description": "Defines the function type. Is either `rest`, `rpc`, `graphql` or `expression`. Default is `rest`", + "enum": [ + "rest", + "rpc", + "graphql", + "expression" + ], + "default": "rest" + } + }, + "additionalProperties": false, + "required": [ + "name", + "operation" + ] + }, + "retrydef": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Unique retry strategy name", + "minLength": 1 + }, + "delay": { + "type": "string", + "description": "Time delay between retry attempts (ISO 8601 duration format)" + }, + "maxDelay": { + "type": "string", + "description": "Maximum time delay between retry attempts (ISO 8601 duration format)" + }, + "increment": { + "type": "string", + "description": "Static value by which the delay increases during each attempt (ISO 8601 time format)" + }, + "multiplier": { + "type": [ + "number", + "string" + ], + "minimum": 0, + "minLength": 1, + "multipleOf": 0.01, + "description": "Numeric value, if specified the delay between retries is multiplied by this value." + }, + "maxAttempts": { + "type": [ + "number", + "string" + ], + "minimum": 1, + "minLength": 0, + "description": "Maximum number of retry attempts." + }, + "jitter": { + "type": [ + "number", + "string" + ], + "minimum": 0, + "maximum": 1, + "description": "If float type, maximum amount of random time added or subtracted from the delay between each retry relative to total delay (between 0 and 1). If string type, absolute maximum amount of random time added or subtracted from the delay between each retry (ISO 8601 duration format)" + } + }, + "additionalProperties": false, + "required": [ + "name", + "maxAttempts" + ] + }, + "secrets": { + "oneOf": [ + { + "type": "string", + "format": "uri", + "description": "URI to a resource containing secrets definitions (json or yaml)" + }, + { + "type": "array", + "description": "Workflow Secrets definitions", + "items": { + "type": "string" + }, + "minItems": 1 + } + ] + }, + "timeouts": { + "oneOf": [ + { + "type": "string", + "format": "uri", + "description": "URI to a resource containing timeouts definitions (json or yaml)" + }, + { + "type": "object", + "description": "Workflow default timeouts", + "properties": { + "workflowExecTimeout": { + "$ref": "#/definitions/workflowExecTimeout" + }, + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + }, + "actionExecTimeout": { + "$ref": "#/definitions/actionExecTimeout" + }, + "branchExecTimeout": { + "$ref": "#/definitions/branchExecTimeout" + }, + "eventTimeout": { + "$ref": "#/definitions/eventTimeout" + } + }, + "additionalProperties": false, + "required": [] + } + ] + }, "events": { "oneOf": [ { diff --git a/src/lib/schema/common.json b/src/lib/schema/common.json index 3d2e4d3..60224c5 100644 --- a/src/lib/schema/common.json +++ b/src/lib/schema/common.json @@ -1,5 +1,5 @@ { - "$id": "https://serverlessworkflow.io/schemas/0.6/common.json", + "$id": "https://serverlessworkflow.io/schemas/0.7/common.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Serverless Workflow specification - common schema", "type": "object", diff --git a/src/lib/schema/events.json b/src/lib/schema/events.json index 7ba488c..c5c72ae 100644 --- a/src/lib/schema/events.json +++ b/src/lib/schema/events.json @@ -1,5 +1,5 @@ { - "$id": "https://serverlessworkflow.io/schemas/0.6/events.json", + "$id": "https://serverlessworkflow.io/schemas/0.7/events.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Serverless Workflow specification - events schema", "type": "object", @@ -61,6 +61,11 @@ }, "additionalItems": false }, + "dataOnly": { + "type": "boolean", + "default": true, + "description": "If `true`, only the Event payload is accessible to consuming Workflow states. If `false`, both event payload and context attributes should be accessible " + }, "metadata": { "$ref": "common.json#/definitions/metadata", "description": "Metadata information" diff --git a/src/lib/schema/functions.json b/src/lib/schema/functions.json index 6b30cd0..f5abc79 100644 --- a/src/lib/schema/functions.json +++ b/src/lib/schema/functions.json @@ -1,5 +1,5 @@ { - "$id": "https://serverlessworkflow.io/schemas/0.6/functions.json", + "$id": "https://serverlessworkflow.io/schemas/0.7/functions.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Serverless Workflow specification - functions schema", "type": "object", @@ -36,15 +36,16 @@ }, "operation": { "type": "string", - "description": "If type is `rest`, #. If type is `rpc`, ##. If type is `expression`, defines the workflow expression.", + "description": "If type is `rest`, #. If type is `rpc`, ##. If type is `graphql`, ##. If type is `expression`, defines the workflow expression.", "minLength": 1 }, "type": { "type": "string", - "description": "Defines the function type. Is either `rest`, `rpc` or `expression`. Default is `rest`", + "description": "Defines the function type. Is either `rest`, `rpc`, `graphql` or `expression`. Default is `rest`", "enum": [ "rest", "rpc", + "graphql", "expression" ], "default": "rest" diff --git a/src/lib/schema/retries.json b/src/lib/schema/retries.json index 8264dd8..23df5e3 100644 --- a/src/lib/schema/retries.json +++ b/src/lib/schema/retries.json @@ -1,5 +1,5 @@ { - "$id": "https://serverlessworkflow.io/schemas/0.6/retries.json", + "$id": "https://serverlessworkflow.io/schemas/0.7/retries.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Serverless Workflow specification - retries schema", "type": "object", diff --git a/src/lib/schema/secrets.json b/src/lib/schema/secrets.json new file mode 100644 index 0000000..427d68e --- /dev/null +++ b/src/lib/schema/secrets.json @@ -0,0 +1,26 @@ +{ + "$id": "https://serverlessworkflow.io/schemas/0.7/secrets.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Serverless Workflow specification - secrets schema", + "type": "object", + "secrets": { + "oneOf": [ + { + "type": "string", + "format": "uri", + "description": "URI to a resource containing secrets definitions (json or yaml)" + }, + { + "type": "array", + "description": "Workflow Secrets definitions", + "items": { + "type": "string" + }, + "minItems": 1 + } + ] + }, + "required": [ + "secrets" + ] +} \ No newline at end of file diff --git a/src/lib/schema/timeouts.json b/src/lib/schema/timeouts.json new file mode 100644 index 0000000..a829dab --- /dev/null +++ b/src/lib/schema/timeouts.json @@ -0,0 +1,96 @@ +{ + "$id": "https://serverlessworkflow.io/schemas/0.7/timeouts.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Serverless Workflow specification - functions schema", + "type": "object", + "timeouts": { + "oneOf": [ + { + "type": "string", + "format": "uri", + "description": "URI to a resource containing timeouts definitions (json or yaml)" + }, + { + "type": "object", + "description": "Workflow default timeouts", + "properties": { + "workflowExecTimeout": { + "$ref": "#/definitions/workflowExecTimeout" + }, + "stateExecTimeout": { + "$ref": "#/definitions/stateExecTimeout" + }, + "actionExecTimeout": { + "$ref": "#/definitions/actionExecTimeout" + }, + "branchExecTimeout": { + "$ref": "#/definitions/branchExecTimeout" + }, + "eventTimeout": { + "$ref": "#/definitions/eventTimeout" + } + }, + "additionalProperties": false, + "required": [] + } + ] + }, + "required": [ + "timeouts" + ], + "definitions": { + "workflowExecTimeout": { + "oneOf": [ + { + "type": "string", + "description": "Workflow execution timeout duration (ISO 8601 duration format). If not specified should be 'unlimited'", + "minLength": 1 + }, + { + "type": "object", + "properties": { + "duration": { + "type": "string", + "description": "Workflow execution timeout duration (ISO 8601 duration format). If not specified should be 'unlimited'", + "minLength": 1 + }, + "interrupt": { + "type": "boolean", + "description": "If `false`, workflow instance is allowed to finish current execution. If `true`, current workflow execution is abrupted.", + "default": true + }, + "runBefore": { + "type": "string", + "description": "Name of a workflow state to be executed before workflow instance is terminated", + "minLength": 1 + } + }, + "additionalProperties": false, + "required": [ + "duration" + ] + } + ] + }, + "stateExecTimeout": { + "type": "string", + "description": "State execution timeout duration (ISO 8601 duration format)", + "minLength": 1 + }, + "actionExecTimeout": { + "type": "string", + "description": "Single actions definition execution timeout duration (ISO 8601 duration format)", + "minLength": 1 + }, + "branchExecTimeout": { + "type": "string", + "description": "Single branch execution timeout duration (ISO 8601 duration format)", + "minLength": 1 + }, + "eventTimeout": { + "type": "string", + "description": "Timeout duration to wait for consuming defined events (ISO 8601 duration format)", + "minLength": 1 + } + } +} \ No newline at end of file diff --git a/src/lib/schema/types/workflow.ts b/src/lib/schema/types/workflow.ts index 0892833..13f7305 100644 --- a/src/lib/schema/types/workflow.ts +++ b/src/lib/schema/types/workflow.ts @@ -17,69 +17,181 @@ /** * Serverless Workflow specification - workflow schema */ -export interface Workflow { - /** - * Workflow unique identifier - */ - id: string; - /** - * Workflow name - */ - name: string; - /** - * Workflow description - */ - description?: string; - /** - * Workflow version - */ - version: string; - start: Startdef; - /** - * Serverless Workflow schema version - */ - schemaVersion?: string; - /** - * Identifies the expression language used for workflow expressions. Default is 'jq' - */ - expressionLang?: string; - execTimeout?: Exectimeout; - /** - * If 'true', workflow instances is not terminated when there are no active execution paths. Instance can be terminated via 'terminate end definition' or reaching defined 'execTimeout' - */ - keepActive?: boolean; - metadata?: /* Metadata information */ Metadata; - events?: Events; - functions?: Functions; - retries?: Retries; - /** - * State definitions - */ - states: [ - ( - | /* Causes the workflow execution to delay for a specified duration */ Delaystate - | /* This state is used to wait for events from event sources, then consumes them and invoke one or more actions to run in sequence or parallel */ Eventstate - | /* Defines actions be performed. Does not wait for incoming events */ Operationstate - | /* Consists of a number of states that are executed in parallel */ Parallelstate - | Switchstate - | /* Defines a sub-workflow to be executed */ Subflowstate - | /* Inject static data into state data. Does not perform any actions */ Injectstate - | /* Execute a set of defined actions or workflows for each element of a data array */ Foreachstate - | /* This state performs an action, then waits for the callback event that denotes completion of the action */ Callbackstate - ), - ...( - | /* Causes the workflow execution to delay for a specified duration */ Delaystate - | /* This state is used to wait for events from event sources, then consumes them and invoke one or more actions to run in sequence or parallel */ Eventstate - | /* Defines actions be performed. Does not wait for incoming events */ Operationstate - | /* Consists of a number of states that are executed in parallel */ Parallelstate - | Switchstate - | /* Defines a sub-workflow to be executed */ Subflowstate - | /* Inject static data into state data. Does not perform any actions */ Injectstate - | /* Execute a set of defined actions or workflows for each element of a data array */ Foreachstate - | /* This state performs an action, then waits for the callback event that denotes completion of the action */ Callbackstate - )[] - ]; -} +export type Workflow /* Serverless Workflow specification - workflow schema */ = + | { + /** + * Workflow unique identifier + */ + id: string; + /** + * Domain-specific workflow identifier + */ + key?: string; + /** + * Workflow name + */ + name: string; + /** + * Workflow description + */ + description?: string; + /** + * Workflow version + */ + version?: string; + /** + * List of helpful terms describing the workflows intended purpose, subject areas, or other important qualities + */ + annotations?: [string, ...string[]]; + dataInputSchema?: + | string + | { + /** + * URI of the JSON Schema used to validate the workflow data input + */ + schema: string; + /** + * Determines if workflow execution should continue if there are validation errors + */ + failOnValidationErrors: boolean; + }; + secrets?: Secrets; + constants?: + | string /* uri */ + | { + [key: string]: any; + }; + start: Startdef; + /** + * Serverless Workflow schema version + */ + specVersion: string; + /** + * Identifies the expression language used for workflow expressions. Default is 'jq' + */ + expressionLang?: string; + timeouts?: Timeouts; + /** + * If 'true', workflow instances is not terminated when there are no active execution paths. Instance can be terminated via 'terminate end definition' or reaching defined 'workflowExecTimeout' + */ + keepActive?: boolean; + metadata?: /* Metadata information */ Metadata; + events?: Events; + functions?: Functions; + retries?: Retries; + /** + * State definitions + */ + states: [ + ( + | /* Causes the workflow execution to delay for a specified duration */ Delaystate + | /* This state is used to wait for events from event sources, then consumes them and invoke one or more actions to run in sequence or parallel */ Eventstate + | /* Defines actions be performed. Does not wait for incoming events */ Operationstate + | /* Consists of a number of states that are executed in parallel */ Parallelstate + | Switchstate + | /* Inject static data into state data. Does not perform any actions */ Injectstate + | /* Execute a set of defined actions or workflows for each element of a data array */ Foreachstate + | /* This state performs an action, then waits for the callback event that denotes completion of the action */ Callbackstate + ), + ...( + | /* Causes the workflow execution to delay for a specified duration */ Delaystate + | /* This state is used to wait for events from event sources, then consumes them and invoke one or more actions to run in sequence or parallel */ Eventstate + | /* Defines actions be performed. Does not wait for incoming events */ Operationstate + | /* Consists of a number of states that are executed in parallel */ Parallelstate + | Switchstate + | /* Inject static data into state data. Does not perform any actions */ Injectstate + | /* Execute a set of defined actions or workflows for each element of a data array */ Foreachstate + | /* This state performs an action, then waits for the callback event that denotes completion of the action */ Callbackstate + )[] + ]; + } + | { + /** + * Workflow unique identifier + */ + id?: string; + /** + * Domain-specific workflow identifier + */ + key: string; + /** + * Workflow name + */ + name: string; + /** + * Workflow description + */ + description?: string; + /** + * Workflow version + */ + version?: string; + /** + * List of helpful terms describing the workflows intended purpose, subject areas, or other important qualities + */ + annotations?: [string, ...string[]]; + dataInputSchema?: + | string + | { + /** + * URI of the JSON Schema used to validate the workflow data input + */ + schema: string; + /** + * Determines if workflow execution should continue if there are validation errors + */ + failOnValidationErrors: boolean; + }; + secrets?: Secrets; + constants?: + | string /* uri */ + | { + [key: string]: any; + }; + start: Startdef; + /** + * Serverless Workflow schema version + */ + specVersion: string; + /** + * Identifies the expression language used for workflow expressions. Default is 'jq' + */ + expressionLang?: string; + timeouts?: Timeouts; + /** + * If 'true', workflow instances is not terminated when there are no active execution paths. Instance can be terminated via 'terminate end definition' or reaching defined 'workflowExecTimeout' + */ + keepActive?: boolean; + metadata?: /* Metadata information */ Metadata; + events?: Events; + functions?: Functions; + retries?: Retries; + /** + * State definitions + */ + states: [ + ( + | /* Causes the workflow execution to delay for a specified duration */ Delaystate + | /* This state is used to wait for events from event sources, then consumes them and invoke one or more actions to run in sequence or parallel */ Eventstate + | /* Defines actions be performed. Does not wait for incoming events */ Operationstate + | /* Consists of a number of states that are executed in parallel */ Parallelstate + | Switchstate + | /* Inject static data into state data. Does not perform any actions */ Injectstate + | /* Execute a set of defined actions or workflows for each element of a data array */ Foreachstate + | /* This state performs an action, then waits for the callback event that denotes completion of the action */ Callbackstate + ), + ...( + | /* Causes the workflow execution to delay for a specified duration */ Delaystate + | /* This state is used to wait for events from event sources, then consumes them and invoke one or more actions to run in sequence or parallel */ Eventstate + | /* Defines actions be performed. Does not wait for incoming events */ Operationstate + | /* Consists of a number of states that are executed in parallel */ Parallelstate + | Switchstate + | /* Inject static data into state data. Does not perform any actions */ Injectstate + | /* Execute a set of defined actions or workflows for each element of a data array */ Foreachstate + | /* This state performs an action, then waits for the callback event that denotes completion of the action */ Callbackstate + )[] + ]; + }; export type Action = | { /** @@ -88,10 +200,7 @@ export type Action = name?: string; functionRef: Functionref; eventRef?: /* Event References */ Eventref; - /** - * Time period to wait for function execution to complete - */ - timeout?: string; + subFlowRef?: Subflowref; actionDataFilter?: Actiondatafilter; } | { @@ -101,12 +210,23 @@ export type Action = name?: string; functionRef?: Functionref; eventRef: /* Event References */ Eventref; + subFlowRef?: Subflowref; + actionDataFilter?: Actiondatafilter; + } + | { /** - * Time period to wait for function execution to complete + * Unique action definition name */ - timeout?: string; + name?: string; + functionRef?: Functionref; + eventRef?: /* Event References */ Eventref; + subFlowRef: Subflowref; actionDataFilter?: Actiondatafilter; }; +/** + * Single actions definition execution timeout duration (ISO 8601 duration format) + */ +export type ActionExecTimeout = string; export interface Actiondatafilter { /** * Workflow expression that selects state data that the state action can use @@ -124,35 +244,27 @@ export interface Actiondatafilter { /** * Branch Definition */ -export type Branch /* Branch Definition */ = - | { - /** - * Branch name - */ - name: string; - /** - * Actions to be executed in this branch - */ - actions?: Action[]; - /** - * Unique Id of a workflow to be executed in this branch - */ - workflowId: string; - } - | { - /** - * Branch name - */ - name: string; - /** - * Actions to be executed in this branch - */ - actions: Action[]; - /** - * Unique Id of a workflow to be executed in this branch - */ - workflowId?: string; - }; +export interface Branch { + /** + * Branch name + */ + name: string; + /** + * State specific timeouts + */ + timeouts?: { + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + branchExecTimeout?: /* Single branch execution timeout duration (ISO 8601 duration format) */ BranchExecTimeout; + }; + /** + * Actions to be executed in this branch + */ + actions: Action[]; +} +/** + * Single branch execution timeout duration (ISO 8601 duration format) + */ +export type BranchExecTimeout = string; /** * This state performs an action, then waits for the callback event that denotes completion of the action */ @@ -178,9 +290,13 @@ export interface Callbackstate { */ eventRef?: string; /** - * Time period to wait for incoming events (ISO 8601 format) + * State specific timeouts */ - timeout?: string; + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + eventTimeout?: /* Timeout duration to wait for consuming defined events (ISO 8601 duration format) */ EventTimeout; + }; /** * Event data filter */ @@ -256,6 +372,12 @@ export interface Databasedswitch { * State data filter */ stateDataFilter?: Statedatafilter; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + }; /** * Defines conditions evaluated against state data */ @@ -267,7 +389,7 @@ export interface Databasedswitch { /** * Default transition of the workflow if there is no matching data conditions. Can include a transition or end definition */ - default?: /* Default definition. Can be either a transition or end definition */ Defaultdef; + defaultCondition?: /* DefaultCondition definition. Can be either a transition or end definition */ Defaultconditiondef; /** * Unique Name of a workflow state which is responsible for compensation of this state */ @@ -282,9 +404,9 @@ export type Datacondition /* Switch state data based condition */ = | Transitiondatacondition | /* Switch state data based condition */ Enddatacondition; /** - * Default definition. Can be either a transition or end definition + * DefaultCondition definition. Can be either a transition or end definition */ -export type Defaultdef /* Default definition. Can be either a transition or end definition */ = +export type Defaultconditiondef /* DefaultCondition definition. Can be either a transition or end definition */ = | { transition: Transition; end?: End; @@ -321,6 +443,12 @@ export interface Delaystate { * Amount of time (ISO 8601 format) to delay */ timeDelay?: string; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + }; /** * States error handling and retries definitions */ @@ -428,6 +556,10 @@ export type Error = transition?: Transition; end: End; }; +/** + * Timeout duration to wait for consuming defined events (ISO 8601 duration format) + */ +export type EventTimeout = string; /** * Permits transitions to other states based on events */ @@ -448,6 +580,13 @@ export interface Eventbasedswitch { * State data filter */ stateDataFilter?: Statedatafilter; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + eventTimeout?: /* Timeout duration to wait for consuming defined events (ISO 8601 duration format) */ EventTimeout; + }; /** * Defines conditions evaluated against events */ @@ -456,14 +595,10 @@ export interface Eventbasedswitch { * States error handling and retries definitions */ onErrors?: Error[]; - /** - * If eventConditions is used, defines the time period to wait for events (ISO 8601 format) - */ - eventTimeout?: string; /** * Default transition of the workflow if there is no matching data conditions. Can include a transition or end definition */ - default?: /* Default definition. Can be either a transition or end definition */ Defaultdef; + defaultCondition?: /* DefaultCondition definition. Can be either a transition or end definition */ Defaultconditiondef; /** * Unique Name of a workflow state which is responsible for compensation of this state */ @@ -479,11 +614,11 @@ export type Eventcondition /* Switch state data event condition */ = | /* Switch state data event condition */ Enddeventcondition; export interface Eventdatafilter { /** - * Workflow expression that filters of the event data (payload) + * Workflow expression that filters the received event/payload (default: '${ . }') */ data?: string; /** - * Workflow expression that selects a state data element to which the event payload should be added/merged into. If not specified, denotes, the top-level state data element. + * Workflow expression that selects a state data element to which the filtered event should be added/merged into. If not specified, denotes, the top-level state data element. */ toStateData?: string; } @@ -511,6 +646,10 @@ export interface Eventdef { /* CloudEvent correlation definition */ CorrelationDef, .../* CloudEvent correlation definition */ CorrelationDef[] ]; + /** + * If `true`, only the Event payload is accessible to consuming Workflow states. If `false`, both event payload and context attributes should be accessible + */ + dataOnly?: boolean; /** * Metadata information */ @@ -571,9 +710,13 @@ export type Eventstate = */ onEvents: Onevents[]; /** - * Time period to wait for incoming events (ISO 8601 format) + * State specific timeouts */ - timeout?: string; + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + eventTimeout?: /* Timeout duration to wait for consuming defined events (ISO 8601 duration format) */ EventTimeout; + }; stateDataFilter?: Statedatafilter; /** * States error handling and retries definitions @@ -609,9 +752,13 @@ export type Eventstate = */ onEvents: Onevents[]; /** - * Time period to wait for incoming events (ISO 8601 format) + * State specific timeouts */ - timeout?: string; + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + eventTimeout?: /* Timeout duration to wait for consuming defined events (ISO 8601 duration format) */ EventTimeout; + }; stateDataFilter?: Statedatafilter; /** * States error handling and retries definitions @@ -625,20 +772,6 @@ export type Eventstate = compensatedBy?: string; metadata?: /* Metadata information */ Metadata; }; -export interface Exectimeout { - /** - * Timeout duration (ISO 8601 duration format) - */ - duration: string; - /** - * If `false`, workflow instance is allowed to finish current execution. If `true`, current workflow execution is abrupted. - */ - interrupt?: boolean; - /** - * Name of a workflow state to be executed before workflow instance is terminated - */ - runBefore?: string; -} /** * Execute a set of defined actions or workflows for each element of a data array */ @@ -680,9 +813,12 @@ export interface Foreachstate { */ actions?: Action[]; /** - * Unique Id of a workflow to be executed for each of the elements of inputCollection + * State specific timeouts */ - workflowId?: string; + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + }; /** * State data filter */ @@ -711,13 +847,13 @@ export interface Function { */ name: string; /** - * If type is `rest`, #. If type is `rpc`, ##. If type is `expression`, defines the workflow expression. + * If type is `rest`, #. If type is `rpc`, ##. If type is `graphql`, ##. If type is `expression`, defines the workflow expression. */ operation: string; /** - * Defines the function type. Is either `rest`, `rpc` or `expression`. Default is `rest` + * Defines the function type. Is either `rest`, `rpc`, `graphql` or `expression`. Default is `rest` */ - type?: 'rest' | 'rpc' | 'expression'; + type?: 'rest' | 'rpc' | 'graphql' | 'expression'; } export type Functionref = | string @@ -732,6 +868,10 @@ export type Functionref = arguments?: { [key: string]: any; }; + /** + * Only used if function type is 'graphql'. A string containing a valid GraphQL selection set + */ + selectionSet?: string; }; export type Functions = string /* uri */ | [Function, ...Function[]]; /** @@ -760,12 +900,18 @@ export interface Injectstate { data?: { [key: string]: any; }; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + }; /** * State data filter */ stateDataFilter?: Statedatafilter; /** - * Next transition of the workflow after subflow has completed + * Next transition of the workflow after injection has completed */ transition?: Transition; /** @@ -790,7 +936,7 @@ export interface Onevents { */ eventRefs: [string, ...string[]]; /** - * Specifies how actions are to be performed (in sequence of parallel) + * Specifies how actions are to be performed (in sequence or in parallel) */ actionMode?: 'sequential' | 'parallel'; /** @@ -834,6 +980,13 @@ export interface Operationstate { * Actions to be performed */ actions?: Action[]; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + }; /** * States error handling and retries definitions */ @@ -876,6 +1029,13 @@ export interface Parallelstate { * State data filter */ stateDataFilter?: Statedatafilter; + /** + * State specific timeouts + */ + timeouts?: { + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + branchExecTimeout?: /* Single branch execution timeout duration (ISO 8601 duration format) */ BranchExecTimeout; + }; /** * Branch Definitions */ @@ -883,11 +1043,11 @@ export interface Parallelstate { /** * Option types on how to complete branch execution. */ - completionType?: 'and' | 'xor' | 'n_of_m'; + completionType?: 'allOf' | 'atLeast'; /** - * Used when completionType is set to 'n_of_m' to specify the 'N' value + * Used when completionType is set to 'atLeast' to specify the minimum number of branches that must complete before the state will transition. */ - n?: number | string; + numCompleted?: number | string; /** * States error handling and retries definitions */ @@ -929,28 +1089,6 @@ export interface Produceeventdef { [name: string]: string; }; } -export interface Repeat { - /** - * Expression evaluated against SubFlow state data. SubFlow will repeat execution as long as this expression is true or until the max property count is reached - */ - expression?: string; - /** - * If true, the expression is evaluated before each repeat execution, if false the expression is evaluated after each repeat execution - */ - checkBefore?: boolean; - /** - * Sets the maximum amount of repeat executions - */ - max?: number; - /** - * If true, repeats executions in a case unhandled errors propagate from the sub-workflow to this state - */ - continueOnError?: boolean; - /** - * List referencing defined consumed workflow events. SubFlow will repeat execution until one of the defined events is consumed, or until the max property count is reached - */ - stopOnEvents?: [string, ...string[]]; -} export type Retries = string /* uri */ | [Retrydef, ...Retrydef[]]; export interface Retrydef { /** @@ -1008,6 +1146,7 @@ export type Schedule = timezone?: string; } ); +export type Secrets = string /* uri */ | [string, ...string[]]; export type Startdef = | string | { @@ -1020,6 +1159,10 @@ export type Startdef = */ schedule: Schedule; }; +/** + * State execution timeout duration (ISO 8601 duration format) + */ +export type StateExecTimeout = string; export interface Statedatafilter { /** * Workflow expression to filter the state data input @@ -1030,63 +1173,34 @@ export interface Statedatafilter { */ output?: string; } -/** - * Defines a sub-workflow to be executed - */ -export interface Subflowstate { - /** - * Unique state id - */ - id?: string; - /** - * State name - */ - name?: string; - /** - * State type - */ - type?: 'subflow'; - /** - * State end definition - */ - end?: End; - /** - * Workflow execution must wait for sub-workflow to finish before continuing - */ - waitForCompletion?: boolean; - /** - * Sub-workflow unique id - */ - workflowId?: string; - /** - * SubFlow state repeat exec definition - */ - repeat?: Repeat; - /** - * State data filter - */ - stateDataFilter?: Statedatafilter; - /** - * States error handling and retries definitions - */ - onErrors?: Error[]; - /** - * Next transition of the workflow after SubFlow has completed execution - */ - transition?: Transition; - /** - * Unique Name of a workflow state which is responsible for compensation of this state - */ - compensatedBy?: string; - /** - * If true, this state is used to compensate another state. Default is false - */ - usedForCompensation?: boolean; - metadata?: /* Metadata information */ Metadata; -} +export type Subflowref = + | string + | { + /** + * Workflow execution must wait for sub-workflow to finish before continuing + */ + waitForCompletion?: boolean; + /** + * Unique id of the sub-workflow to be invoked + */ + workflowId: string; + /** + * Version of the sub-workflow to be invoked + */ + version?: string; + }; export type Switchstate /* Permits transitions to other states based on data conditions */ = | Databasedswitch | /* Permits transitions to other states based on events */ Eventbasedswitch; +export type Timeouts = + | string /* uri */ + | { + workflowExecTimeout?: WorkflowExecTimeout; + stateExecTimeout?: /* State execution timeout duration (ISO 8601 duration format) */ StateExecTimeout; + actionExecTimeout?: /* Single actions definition execution timeout duration (ISO 8601 duration format) */ ActionExecTimeout; + branchExecTimeout?: /* Single branch execution timeout duration (ISO 8601 duration format) */ BranchExecTimeout; + eventTimeout?: /* Timeout duration to wait for consuming defined events (ISO 8601 duration format) */ EventTimeout; + }; export type Transition = | string | { @@ -1143,3 +1257,19 @@ export interface Transitioneventcondition { eventDataFilter?: Eventdatafilter; metadata?: /* Metadata information */ Metadata; } +export type WorkflowExecTimeout = + | string + | { + /** + * Workflow execution timeout duration (ISO 8601 duration format). If not specified should be 'unlimited' + */ + duration: string; + /** + * If `false`, workflow instance is allowed to finish current execution. If `true`, current workflow execution is abrupted. + */ + interrupt?: boolean; + /** + * Name of a workflow state to be executed before workflow instance is terminated + */ + runBefore?: string; + }; diff --git a/src/lib/schema/validation/validators-paths.ts b/src/lib/schema/validation/validators-paths.ts index 00669c4..1115e51 100644 --- a/src/lib/schema/validation/validators-paths.ts +++ b/src/lib/schema/validation/validators-paths.ts @@ -18,54 +18,59 @@ * A map of type names and their corresponding schema */ export const validatorsPaths: [string, string][] = [ - ['Workflow', 'https://serverlessworkflow.io/schemas/0.6/workflow.json'], - ['Crondef', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/crondef'], - ['Exectimeout', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/exectimeout'], - ['Transition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/transition'], - ['Error', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/error'], - ['Onevents', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/onevents'], - ['Action', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/action'], - ['Functionref', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/functionref'], - ['Eventref', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/eventref'], - ['Branch', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/branch'], - ['Delaystate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/delaystate'], - ['Eventstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/eventstate'], - ['Operationstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/operationstate'], - ['Parallelstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/parallelstate'], - ['Switchstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/switchstate'], - ['Eventbasedswitch', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/eventbasedswitch'], - ['Databasedswitch', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/databasedswitch'], - ['Defaultdef', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/defaultdef'], - ['Eventcondition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/eventcondition'], + ['Workflow', 'https://serverlessworkflow.io/schemas/0.7/workflow.json'], + ['Crondef', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/crondef'], + ['Transition', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/transition'], + ['Error', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/error'], + ['Onevents', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/onevents'], + ['Action', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/action'], + ['Functionref', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/functionref'], + ['Eventref', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/eventref'], + ['Subflowref', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/subflowref'], + ['Branch', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/branch'], + ['Delaystate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/delaystate'], + ['Eventstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/eventstate'], + ['Operationstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/operationstate'], + ['Parallelstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/parallelstate'], + ['Switchstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/switchstate'], + ['Eventbasedswitch', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/eventbasedswitch'], + ['Databasedswitch', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/databasedswitch'], + ['Defaultconditiondef', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/defaultconditiondef'], + ['Eventcondition', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/eventcondition'], [ 'Transitioneventcondition', - 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/transitioneventcondition', + 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/transitioneventcondition', ], - ['Enddeventcondition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/enddeventcondition'], - ['Datacondition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/datacondition'], + ['Enddeventcondition', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/enddeventcondition'], + ['Datacondition', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/datacondition'], [ 'Transitiondatacondition', - 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/transitiondatacondition', + 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/transitiondatacondition', ], - ['Enddatacondition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/enddatacondition'], - ['Subflowstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/subflowstate'], - ['Injectstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/injectstate'], - ['Foreachstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/foreachstate'], - ['Callbackstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/callbackstate'], - ['Startdef', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/startdef'], - ['Schedule', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/schedule'], - ['End', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/end'], - ['Produceeventdef', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/produceeventdef'], - ['Statedatafilter', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/statedatafilter'], - ['Eventdatafilter', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/eventdatafilter'], - ['Actiondatafilter', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/actiondatafilter'], - ['Repeat', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/repeat'], - ['Metadata', 'https://serverlessworkflow.io/schemas/0.6/common.json#/definitions/metadata'], - ['Function', 'https://serverlessworkflow.io/schemas/0.6/functions.json#/definitions/function'], - ['Retrydef', 'https://serverlessworkflow.io/schemas/0.6/retries.json#/definitions/retrydef'], - ['Eventdef', 'https://serverlessworkflow.io/schemas/0.6/events.json#/definitions/eventdef'], - ['CorrelationDef', 'https://serverlessworkflow.io/schemas/0.6/events.json#/definitions/correlationDef'], - ['Events', 'https://serverlessworkflow.io/schemas/0.6/events.json#/events'], - ['Functions', 'https://serverlessworkflow.io/schemas/0.6/functions.json#/functions'], - ['Retries', 'https://serverlessworkflow.io/schemas/0.6/retries.json#/retries'], + ['Enddatacondition', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/enddatacondition'], + ['Injectstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/injectstate'], + ['Foreachstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/foreachstate'], + ['Callbackstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/callbackstate'], + ['Startdef', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/startdef'], + ['Schedule', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/schedule'], + ['End', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/end'], + ['Produceeventdef', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/produceeventdef'], + ['Statedatafilter', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/statedatafilter'], + ['Eventdatafilter', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/eventdatafilter'], + ['Actiondatafilter', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/actiondatafilter'], + ['WorkflowExecTimeout', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/definitions/workflowExecTimeout'], + ['StateExecTimeout', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/definitions/stateExecTimeout'], + ['ActionExecTimeout', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/definitions/actionExecTimeout'], + ['BranchExecTimeout', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/definitions/branchExecTimeout'], + ['EventTimeout', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/definitions/eventTimeout'], + ['Function', 'https://serverlessworkflow.io/schemas/0.7/functions.json#/definitions/function'], + ['Metadata', 'https://serverlessworkflow.io/schemas/0.7/common.json#/definitions/metadata'], + ['Eventdef', 'https://serverlessworkflow.io/schemas/0.7/events.json#/definitions/eventdef'], + ['CorrelationDef', 'https://serverlessworkflow.io/schemas/0.7/events.json#/definitions/correlationDef'], + ['Retrydef', 'https://serverlessworkflow.io/schemas/0.7/retries.json#/definitions/retrydef'], + ['Secrets', 'https://serverlessworkflow.io/schemas/0.7/secrets.json#/secrets'], + ['Timeouts', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/timeouts'], + ['Events', 'https://serverlessworkflow.io/schemas/0.7/events.json#/events'], + ['Functions', 'https://serverlessworkflow.io/schemas/0.7/functions.json#/functions'], + ['Retries', 'https://serverlessworkflow.io/schemas/0.7/retries.json#/retries'], ]; diff --git a/src/lib/schema/workflow.json b/src/lib/schema/workflow.json index d2196b1..a92f06e 100644 --- a/src/lib/schema/workflow.json +++ b/src/lib/schema/workflow.json @@ -1,5 +1,5 @@ { - "$id": "https://serverlessworkflow.io/schemas/0.6/workflow.json", + "$id": "https://serverlessworkflow.io/schemas/0.7/workflow.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Serverless Workflow specification - workflow schema", "type": "object", @@ -9,6 +9,11 @@ "description": "Workflow unique identifier", "minLength": 1 }, + "key": { + "type": "string", + "description": "Domain-specific workflow identifier", + "minLength": 1 + }, "name": { "type": "string", "description": "Workflow name", @@ -23,10 +28,65 @@ "description": "Workflow version", "minLength": 1 }, + "annotations": { + "type": "array", + "description": "List of helpful terms describing the workflows intended purpose, subject areas, or other important qualities", + "minItems": 1, + "items": { + "type": "string" + }, + "additionalItems": false + }, + "dataInputSchema": { + "oneOf": [ + { + "type": "string", + "description": "URI of the JSON Schema used to validate the workflow data input", + "minLength": 1 + }, + { + "type": "object", + "description": "Workflow data input schema definition", + "properties": { + "schema": { + "type": "string", + "description": "URI of the JSON Schema used to validate the workflow data input", + "minLength": 1 + }, + "failOnValidationErrors": { + "type": "boolean", + "default": true, + "description": "Determines if workflow execution should continue if there are validation errors" + } + }, + "additionalProperties": false, + "required": [ + "schema", + "failOnValidationErrors" + ] + } + ] + }, + "secrets": { + "$ref": "secrets.json#/secrets" + }, + "constants": { + "oneOf": [ + { + "type": "string", + "format": "uri", + "description": "URI to a resource containing constants data (json or yaml)" + }, + { + "type": "object", + "description": "Workflow constants data (object type)" + } + ] + }, "start": { "$ref": "#/definitions/startdef" }, - "schemaVersion": { + "specVersion": { "type": "string", "description": "Serverless Workflow schema version", "minLength": 1 @@ -37,13 +97,13 @@ "default": "jq", "minLength": 1 }, - "execTimeout": { - "$ref": "#/definitions/exectimeout" + "timeouts": { + "$ref": "timeouts.json#/timeouts" }, "keepActive": { "type": "boolean", "default": false, - "description": "If 'true', workflow instances is not terminated when there are no active execution paths. Instance can be terminated via 'terminate end definition' or reaching defined 'execTimeout'" + "description": "If 'true', workflow instances is not terminated when there are no active execution paths. Instance can be terminated via 'terminate end definition' or reaching defined 'workflowExecTimeout'" }, "metadata": { "$ref": "common.json#/definitions/metadata" @@ -82,10 +142,6 @@ "title": "Switch State", "$ref": "#/definitions/switchstate" }, - { - "title": "SubFlow State", - "$ref": "#/definitions/subflowstate" - }, { "title": "Inject State", "$ref": "#/definitions/injectstate" @@ -104,12 +160,25 @@ "minItems": 1 } }, - "required": [ - "id", - "name", - "version", - "start", - "states" + "oneOf": [ + { + "required": [ + "id", + "specVersion", + "name", + "start", + "states" + ] + }, + { + "required": [ + "key", + "specVersion", + "name", + "start", + "states" + ] + } ], "definitions": { "crondef": { @@ -139,30 +208,6 @@ } ] }, - "exectimeout": { - "type": "object", - "properties": { - "duration": { - "type": "string", - "description": "Timeout duration (ISO 8601 duration format)", - "minLength": 1 - }, - "interrupt": { - "type": "boolean", - "description": "If `false`, workflow instance is allowed to finish current execution. If `true`, current workflow execution is abrupted.", - "default": false - }, - "runBefore": { - "type": "string", - "description": "Name of a workflow state to be executed before workflow instance is terminated", - "minLength": 1 - } - }, - "additionalProperties": false, - "required": [ - "duration" - ] - }, "transition": { "oneOf": [ { @@ -262,7 +307,7 @@ "sequential", "parallel" ], - "description": "Specifies how actions are to be performed (in sequence of parallel)", + "description": "Specifies how actions are to be performed (in sequence or in parallel)", "default": "sequential" }, "actions": { @@ -299,9 +344,9 @@ "description": "References a 'trigger' and 'result' reusable event definitions", "$ref": "#/definitions/eventref" }, - "timeout": { - "type": "string", - "description": "Time period to wait for function execution to complete" + "subFlowRef": { + "description": "References a sub-workflow to invoke", + "$ref": "#/definitions/subflowref" }, "actionDataFilter": { "description": "Action data filter", @@ -319,6 +364,11 @@ "required": [ "eventRef" ] + }, + { + "required": [ + "subFlowRef" + ] } ] }, @@ -340,6 +390,10 @@ "arguments": { "type": "object", "description": "Function arguments/inputs" + }, + "selectionSet": { + "type": "string", + "description": "Only used if function type is 'graphql'. A string containing a valid GraphQL selection set" } }, "additionalProperties": false, @@ -382,6 +436,38 @@ "resultEventRef" ] }, + "subflowref": { + "oneOf": [ + { + "type": "string", + "description": "Unique id of the sub-workflow to be invoked", + "minLength": 1 + }, + { + "type": "object", + "description": "Specifies a sub-workflow to be invoked", + "properties": { + "waitForCompletion": { + "type": "boolean", + "default": true, + "description": "Workflow execution must wait for sub-workflow to finish before continuing" + }, + "workflowId": { + "type": "string", + "description": "Unique id of the sub-workflow to be invoked" + }, + "version": { + "type": "string", + "description": "Version of the sub-workflow to be invoked", + "minLength": 1 + } + }, + "required": [ + "workflowId" + ] + } + ] + }, "branch": { "type": "object", "description": "Branch Definition", @@ -390,6 +476,19 @@ "type": "string", "description": "Branch name" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "actionExecTimeout": { + "$ref": "timeouts.json#/definitions/actionExecTimeout" + }, + "branchExecTimeout": { + "$ref": "timeouts.json#/definitions/branchExecTimeout" + } + }, + "required": [] + }, "actions": { "type": "array", "description": "Actions to be executed in this branch", @@ -398,26 +497,12 @@ "$ref": "#/definitions/action" }, "additionalItems": false - }, - "workflowId": { - "type": "string", - "description": "Unique Id of a workflow to be executed in this branch" } }, "additionalProperties": false, - "oneOf": [ - { - "required": [ - "name", - "workflowId" - ] - }, - { - "required": [ - "name", - "actions" - ] - } + "required": [ + "name", + "actions" ] }, "delaystate": { @@ -450,6 +535,16 @@ "type": "string", "description": "Amount of time (ISO 8601 format) to delay" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "timeouts.json#/definitions/stateExecTimeout" + } + }, + "required": [] + }, "onErrors": { "type": "array", "description": "States error handling and retries definitions", @@ -548,9 +643,21 @@ }, "additionalItems": false }, - "timeout": { - "type": "string", - "description": "Time period to wait for incoming events (ISO 8601 format)" + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "timeouts.json#/definitions/stateExecTimeout" + }, + "actionExecTimeout": { + "$ref": "timeouts.json#/definitions/actionExecTimeout" + }, + "eventTimeout": { + "$ref": "timeouts.json#/definitions/eventTimeout" + } + }, + "required": [] }, "stateDataFilter": { "description": "State data filter", @@ -645,6 +752,19 @@ "$ref": "#/definitions/action" } }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "timeouts.json#/definitions/stateExecTimeout" + }, + "actionExecTimeout": { + "$ref": "timeouts.json#/definitions/actionExecTimeout" + } + }, + "required": [] + }, "onErrors": { "type": "array", "description": "States error handling and retries definitions", @@ -697,7 +817,7 @@ "name", "type", "actions", - "end" + "transition" ] }, { @@ -705,7 +825,7 @@ "name", "type", "actions", - "transition" + "end" ] } ] @@ -737,6 +857,19 @@ "description": "State data filter", "$ref": "#/definitions/statedatafilter" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "timeouts.json#/definitions/stateExecTimeout" + }, + "branchExecTimeout": { + "$ref": "timeouts.json#/definitions/branchExecTimeout" + } + }, + "required": [] + }, "branches": { "type": "array", "description": "Branch Definitions", @@ -749,21 +882,20 @@ "completionType": { "type": "string", "enum": [ - "and", - "xor", - "n_of_m" + "allOf", + "atLeast" ], "description": "Option types on how to complete branch execution.", - "default": "and" + "default": "allOf" }, - "n": { + "numCompleted": { "type": [ "number", "string" ], "minimum": 0, "minLength": 0, - "description": "Used when completionType is set to 'n_of_m' to specify the 'N' value" + "description": "Used when completionType is set to 'atLeast' to specify the minimum number of branches that must complete before the state will transition." }, "onErrors": { "type": "array", @@ -863,6 +995,19 @@ "description": "State data filter", "$ref": "#/definitions/statedatafilter" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "timeouts.json#/definitions/stateExecTimeout" + }, + "eventTimeout": { + "$ref": "timeouts.json#/definitions/eventTimeout" + } + }, + "required": [] + }, "eventConditions": { "type": "array", "description": "Defines conditions evaluated against events", @@ -881,13 +1026,9 @@ }, "additionalItems": false }, - "eventTimeout": { - "type": "string", - "description": "If eventConditions is used, defines the time period to wait for events (ISO 8601 format)" - }, - "default": { + "defaultCondition": { "description": "Default transition of the workflow if there is no matching data conditions. Can include a transition or end definition", - "$ref": "#/definitions/defaultdef" + "$ref": "#/definitions/defaultconditiondef" }, "compensatedBy": { "type": "string", @@ -932,6 +1073,16 @@ "description": "State data filter", "$ref": "#/definitions/statedatafilter" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "timeouts.json#/definitions/stateExecTimeout" + } + }, + "required": [] + }, "dataConditions": { "type": "array", "description": "Defines conditions evaluated against state data", @@ -950,9 +1101,9 @@ }, "additionalItems": false }, - "default": { + "defaultCondition": { "description": "Default transition of the workflow if there is no matching data conditions. Can include a transition or end definition", - "$ref": "#/definitions/defaultdef" + "$ref": "#/definitions/defaultconditiondef" }, "compensatedBy": { "type": "string", @@ -975,9 +1126,9 @@ "dataConditions" ] }, - "defaultdef": { + "defaultconditiondef": { "type": "object", - "description": "Default definition. Can be either a transition or end definition", + "description": "DefaultCondition definition. Can be either a transition or end definition", "properties": { "transition": { "$ref": "#/definitions/transition" @@ -1132,108 +1283,6 @@ "end" ] }, - "subflowstate": { - "type": "object", - "description": "Defines a sub-workflow to be executed", - "properties": { - "id": { - "type": "string", - "description": "Unique state id", - "minLength": 1 - }, - "name": { - "type": "string", - "description": "State name" - }, - "type": { - "type": "string", - "const": "subflow", - "description": "State type" - }, - "end": { - "$ref": "#/definitions/end", - "description": "State end definition" - }, - "waitForCompletion": { - "type": "boolean", - "default": false, - "description": "Workflow execution must wait for sub-workflow to finish before continuing" - }, - "workflowId": { - "type": "string", - "description": "Sub-workflow unique id" - }, - "repeat": { - "$ref": "#/definitions/repeat", - "description": "SubFlow state repeat exec definition" - }, - "stateDataFilter": { - "description": "State data filter", - "$ref": "#/definitions/statedatafilter" - }, - "onErrors": { - "type": "array", - "description": "States error handling and retries definitions", - "items": { - "type": "object", - "$ref": "#/definitions/error" - }, - "additionalItems": false - }, - "transition": { - "description": "Next transition of the workflow after SubFlow has completed execution", - "$ref": "#/definitions/transition" - }, - "compensatedBy": { - "type": "string", - "minLength": 1, - "description": "Unique Name of a workflow state which is responsible for compensation of this state" - }, - "usedForCompensation": { - "type": "boolean", - "default": false, - "description": "If true, this state is used to compensate another state. Default is false" - }, - "metadata": { - "$ref": "common.json#/definitions/metadata" - } - }, - "additionalProperties": false, - "if": { - "properties": { - "usedForCompensation": { - "const": true - } - } - }, - "then": { - "required": [ - "name", - "type", - "workflowId" - ] - }, - "else": { - "oneOf": [ - { - "required": [ - "name", - "type", - "workflowId", - "end" - ] - }, - { - "required": [ - "name", - "type", - "workflowId", - "transition" - ] - } - ] - } - }, "injectstate": { "type": "object", "description": "Inject static data into state data. Does not perform any actions", @@ -1260,12 +1309,22 @@ "type": "object", "description": "JSON object which can be set as states data input and can be manipulated via filters" }, + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "timeouts.json#/definitions/stateExecTimeout" + } + }, + "required": [] + }, "stateDataFilter": { "description": "State data filter", "$ref": "#/definitions/statedatafilter" }, "transition": { - "description": "Next transition of the workflow after subflow has completed", + "description": "Next transition of the workflow after injection has completed", "$ref": "#/definitions/transition" }, "compensatedBy": { @@ -1373,9 +1432,18 @@ }, "additionalItems": false }, - "workflowId": { - "type": "string", - "description": "Unique Id of a workflow to be executed for each of the elements of inputCollection" + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "timeouts.json#/definitions/stateExecTimeout" + }, + "actionExecTimeout": { + "$ref": "timeouts.json#/definitions/actionExecTimeout" + } + }, + "required": [] }, "stateDataFilter": { "description": "State data filter", @@ -1425,31 +1493,11 @@ "type", "inputCollection", "iterationParam", - "workflowId" + "actions" ] }, "else": { "oneOf": [ - { - "required": [ - "name", - "type", - "inputCollection", - "iterationParam", - "workflowId", - "end" - ] - }, - { - "required": [ - "name", - "type", - "inputCollection", - "iterationParam", - "workflowId", - "transition" - ] - }, { "required": [ "name", @@ -1499,9 +1547,21 @@ "type": "string", "description": "References an unique callback event name in the defined workflow events" }, - "timeout": { - "type": "string", - "description": "Time period to wait for incoming events (ISO 8601 format)" + "timeouts": { + "type": "object", + "description": "State specific timeouts", + "properties": { + "stateExecTimeout": { + "$ref": "timeouts.json#/definitions/stateExecTimeout" + }, + "actionExecTimeout": { + "$ref": "timeouts.json#/definitions/actionExecTimeout" + }, + "eventTimeout": { + "$ref": "timeouts.json#/definitions/eventTimeout" + } + }, + "required": [] }, "eventDataFilter": { "description": "Event data filter", @@ -1558,8 +1618,7 @@ "name", "type", "action", - "eventRef", - "timeout" + "eventRef" ] }, "else": { @@ -1570,7 +1629,6 @@ "type", "action", "eventRef", - "timeout", "end" ] }, @@ -1580,7 +1638,6 @@ "type", "action", "eventRef", - "timeout", "transition" ] } @@ -1740,11 +1797,11 @@ "properties": { "data": { "type": "string", - "description": "Workflow expression that filters of the event data (payload)" + "description": "Workflow expression that filters the received event/payload (default: '${ . }')" }, "toStateData": { "type": "string", - "description": " Workflow expression that selects a state data element to which the event payload should be added/merged into. If not specified, denotes, the top-level state data element." + "description": " Workflow expression that selects a state data element to which the filtered event should be added/merged into. If not specified, denotes, the top-level state data element." } }, "additionalProperties": false, @@ -1768,42 +1825,6 @@ }, "additionalProperties": false, "required": [] - }, - "repeat": { - "type": "object", - "properties": { - "expression": { - "type": "string", - "description": "Expression evaluated against SubFlow state data. SubFlow will repeat execution as long as this expression is true or until the max property count is reached", - "minLength": 1 - }, - "checkBefore": { - "type": "boolean", - "description": "If true, the expression is evaluated before each repeat execution, if false the expression is evaluated after each repeat execution", - "default": true - }, - "max": { - "type": "integer", - "description": "Sets the maximum amount of repeat executions", - "minimum": 0 - }, - "continueOnError": { - "type": "boolean", - "description": "If true, repeats executions in a case unhandled errors propagate from the sub-workflow to this state", - "default": false - }, - "stopOnEvents": { - "type": "array", - "description": "List referencing defined consumed workflow events. SubFlow will repeat execution until one of the defined events is consumed, or until the max property count is reached", - "minItems": 1, - "items": { - "type": "string" - }, - "additionalItems": false - } - }, - "additionalProperties": false, - "required": [] } } -} \ No newline at end of file +} diff --git a/src/lib/validation/validators-paths.ts b/src/lib/validation/validators-paths.ts index 947c736..7876beb 100644 --- a/src/lib/validation/validators-paths.ts +++ b/src/lib/validation/validators-paths.ts @@ -1,66 +1,77 @@ -/* -* Copyright 2021-Present The Serverless Workflow Specification Authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* oUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -*/ - -/** -* A map of type names and their corresponding schema -*/ -export const validatorsPaths: [string, string][] = [ - ['Workflow', 'https://serverlessworkflow.io/schemas/0.6/workflow.json'], - ['Crondef', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/crondef'], - ['Exectimeout', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/exectimeout'], - ['Transition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/transition'], - ['Error', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/error'], - ['Onevents', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/onevents'], - ['Action', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/action'], - ['Functionref', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/functionref'], - ['Eventref', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/eventref'], - ['Branch', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/branch'], - ['Delaystate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/delaystate'], - ['Eventstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/eventstate'], - ['Operationstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/operationstate'], - ['Parallelstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/parallelstate'], - ['Switchstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/switchstate'], - ['Eventbasedswitch', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/eventbasedswitch'], - ['Databasedswitch', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/databasedswitch'], - ['Defaultdef', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/defaultdef'], - ['Eventcondition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/eventcondition'], - ['Transitioneventcondition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/transitioneventcondition'], - ['Enddeventcondition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/enddeventcondition'], - ['Datacondition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/datacondition'], - ['Transitiondatacondition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/transitiondatacondition'], - ['Enddatacondition', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/enddatacondition'], - ['Subflowstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/subflowstate'], - ['Injectstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/injectstate'], - ['Foreachstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/foreachstate'], - ['Callbackstate', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/callbackstate'], - ['Startdef', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/startdef'], - ['Schedule', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/schedule'], - ['End', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/end'], - ['Produceeventdef', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/produceeventdef'], - ['Statedatafilter', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/statedatafilter'], - ['Eventdatafilter', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/eventdatafilter'], - ['Actiondatafilter', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/actiondatafilter'], - ['Repeat', 'https://serverlessworkflow.io/schemas/0.6/workflow.json#/definitions/repeat'], - ['Eventdef', 'https://serverlessworkflow.io/schemas/0.6/events.json#/definitions/eventdef'], - ['CorrelationDef', 'https://serverlessworkflow.io/schemas/0.6/events.json#/definitions/correlationDef'], - ['Metadata', 'https://serverlessworkflow.io/schemas/0.6/common.json#/definitions/metadata'], - ['Function', 'https://serverlessworkflow.io/schemas/0.6/functions.json#/definitions/function'], - ['Retrydef', 'https://serverlessworkflow.io/schemas/0.6/retries.json#/definitions/retrydef'], - ['Events', 'https://serverlessworkflow.io/schemas/0.6/events.json#/events'], - ['Functions', 'https://serverlessworkflow.io/schemas/0.6/functions.json#/functions'], - ['Retries', 'https://serverlessworkflow.io/schemas/0.6/retries.json#/retries'], -] \ No newline at end of file +/* +* Copyright 2021-Present The Serverless Workflow Specification Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* oUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ + +/** +* A map of type names and their corresponding schema +*/ +export const validatorsPaths: [string, string][] = [ + ['Workflow', 'https://serverlessworkflow.io/schemas/0.7/workflow.json'], + ['Crondef', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/crondef'], + ['Transition', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/transition'], + ['Error', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/error'], + ['Onevents', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/onevents'], + ['Action', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/action'], + ['Functionref', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/functionref'], + ['Eventref', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/eventref'], + ['Subflowref', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/subflowref'], + ['Branch', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/branch'], + ['Delaystate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/delaystate'], + ['Eventstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/eventstate'], + ['Operationstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/operationstate'], + ['Parallelstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/parallelstate'], + ['Switchstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/switchstate'], + ['Eventbasedswitch', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/eventbasedswitch'], + ['Databasedswitch', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/databasedswitch'], + ['Defaultconditiondef', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/defaultconditiondef'], + ['Eventcondition', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/eventcondition'], + [ + 'Transitioneventcondition', + 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/transitioneventcondition', + ], + ['Enddeventcondition', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/enddeventcondition'], + ['Datacondition', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/datacondition'], + [ + 'Transitiondatacondition', + 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/transitiondatacondition', + ], + ['Enddatacondition', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/enddatacondition'], + ['Injectstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/injectstate'], + ['Foreachstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/foreachstate'], + ['Callbackstate', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/callbackstate'], + ['Startdef', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/startdef'], + ['Schedule', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/schedule'], + ['End', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/end'], + ['Produceeventdef', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/produceeventdef'], + ['Statedatafilter', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/statedatafilter'], + ['Eventdatafilter', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/eventdatafilter'], + ['Actiondatafilter', 'https://serverlessworkflow.io/schemas/0.7/workflow.json#/definitions/actiondatafilter'], + ['WorkflowExecTimeout', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/definitions/workflowExecTimeout'], + ['StateExecTimeout', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/definitions/stateExecTimeout'], + ['ActionExecTimeout', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/definitions/actionExecTimeout'], + ['BranchExecTimeout', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/definitions/branchExecTimeout'], + ['EventTimeout', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/definitions/eventTimeout'], + ['Eventdef', 'https://serverlessworkflow.io/schemas/0.7/events.json#/definitions/eventdef'], + ['CorrelationDef', 'https://serverlessworkflow.io/schemas/0.7/events.json#/definitions/correlationDef'], + ['Function', 'https://serverlessworkflow.io/schemas/0.7/functions.json#/definitions/function'], + ['Retrydef', 'https://serverlessworkflow.io/schemas/0.7/retries.json#/definitions/retrydef'], + ['Metadata', 'https://serverlessworkflow.io/schemas/0.7/common.json#/definitions/metadata'], + ['Secrets', 'https://serverlessworkflow.io/schemas/0.7/secrets.json#/secrets'], + ['Timeouts', 'https://serverlessworkflow.io/schemas/0.7/timeouts.json#/timeouts'], + ['Events', 'https://serverlessworkflow.io/schemas/0.7/events.json#/events'], + ['Functions', 'https://serverlessworkflow.io/schemas/0.7/functions.json#/functions'], + ['Retries', 'https://serverlessworkflow.io/schemas/0.7/retries.json#/retries'], +] diff --git a/src/lib/validators.ts b/src/lib/validators.ts index dd5ffcd..5a7d03b 100644 --- a/src/lib/validators.ts +++ b/src/lib/validators.ts @@ -19,10 +19,20 @@ import commonSchema from './schema/common.json'; import eventsChema from './schema/events.json'; import functionsSchema from './schema/functions.json'; import retriesSchema from './schema/retries.json'; +import secretsSchema from './schema/secrets.json'; +import timeoutsSchema from './schema/timeouts.json'; import workflowSchema from './schema/workflow.json'; import { validatorsPaths } from './validation/validators-paths'; -const schemas: any[] = [commonSchema, eventsChema, functionsSchema, retriesSchema, workflowSchema]; +const schemas: any[] = [ + commonSchema, + eventsChema, + functionsSchema, + retriesSchema, + secretsSchema, + timeoutsSchema, + workflowSchema, +]; const strict: boolean = false; const ajv = new Ajv({ schemas, strict }); ajv.addFormat('uri', (uri: string): boolean => true); diff --git a/tests/examples/applicantrequest.json b/tests/examples/applicantrequest.json index 062719a..9125e10 100644 --- a/tests/examples/applicantrequest.json +++ b/tests/examples/applicantrequest.json @@ -1,53 +1,58 @@ -{ - "id": "applicantrequest", - "version": "1.0", - "name": "Applicant Request Decision Workflow", - "description": "Determine if applicant request is valid", - "start": "CheckApplication", - "functions": [ - { - "name": "sendRejectionEmailFunction", - "operation": "http://myapis.org/applicationapi.json#emailRejection" - } - ], - "states": [ - { - "type": "switch", - "name": "CheckApplication", - "dataConditions": [ - { - "condition": "${ .applicants | .age >= 18 }", - "transition": "StartApplication" - }, - { - "condition": "${ .applicants | .age < 18 }", - "transition": "RejectApplication" - } - ], - "default": { - "transition": "RejectApplication" - } - }, - { - "type": "subflow", - "name": "StartApplication", - "workflowId": "startApplicationWorkflowId", - "end": true - }, - { - "type": "operation", - "name": "RejectApplication", - "actions": [ - { - "functionRef": { - "refName": "sendRejectionEmailFunction", - "arguments": { - "applicant": "${ .applicant }" - } - } - } - ], - "end": true - } - ] -} +{ + "id": "applicantrequest", + "version": "1.0", + "specVersion": "0.7", + "name": "Applicant Request Decision Workflow", + "description": "Determine if applicant request is valid", + "start": "CheckApplication", + "functions": [ + { + "name": "sendRejectionEmailFunction", + "operation": "http://myapis.org/applicationapi.json#emailRejection" + } + ], + "states":[ + { + "type":"switch", + "name":"CheckApplication", + "dataConditions": [ + { + "condition": "${ .applicants | .age >= 18 }", + "transition": "StartApplication" + }, + { + "condition": "${ .applicants | .age < 18 }", + "transition": "RejectApplication" + } + ], + "defaultCondition": { + "transition": "RejectApplication" + } + }, + { + "type": "operation", + "name": "StartApplication", + "actions": [ + { + "subFlowRef": "startApplicationWorkflowId" + } + ], + "end": true + }, + { + "type":"operation", + "name":"RejectApplication", + "actions":[ + { + "functionRef": { + "refName": "sendRejectionEmailFunction", + "arguments": { + "applicant": "${ .applicant }" + } + } + } + ], + "end": true + } + ] +} diff --git a/tests/examples/applicantrequest.spec.ts b/tests/examples/applicantrequest.spec.ts index acfad8e..106fed6 100644 --- a/tests/examples/applicantrequest.spec.ts +++ b/tests/examples/applicantrequest.spec.ts @@ -18,13 +18,12 @@ import * as fs from 'fs'; import { actionBuilder, databasedswitchBuilder, - defaultdefBuilder, functionBuilder, functionrefBuilder, operationstateBuilder, - subflowstateBuilder, transitiondataconditionBuilder, workflowBuilder, + defaultconditiondefBuilder, } from '../../src'; describe('applicationrequest workflow example', () => { @@ -32,6 +31,7 @@ describe('applicationrequest workflow example', () => { const workflow = workflowBuilder() .id('applicantrequest') .version('1.0') + .specVersion('0.7') .name('Applicant Request Decision Workflow') .description('Determine if applicant request is valid') .start('CheckApplication') @@ -54,9 +54,13 @@ describe('applicationrequest workflow example', () => { .transition('RejectApplication') .build(), ]) - .default(defaultdefBuilder().transition('RejectApplication').build()) + .defaultCondition(defaultconditiondefBuilder().transition('RejectApplication').build()) + .build(), + operationstateBuilder() + .name('StartApplication') + .actionMode('sequential') + .actions([actionBuilder().subFlowRef('startApplicationWorkflowId').build()]) .build(), - subflowstateBuilder().name('StartApplication').workflowId('startApplicationWorkflowId').build(), operationstateBuilder() .name('RejectApplication') .actionMode('sequential') diff --git a/tests/examples/booklending.json b/tests/examples/booklending.json index 004a8f5..34bf9c5 100644 --- a/tests/examples/booklending.json +++ b/tests/examples/booklending.json @@ -1,131 +1,130 @@ -{ - "id": "booklending", - "name": "Book Lending Workflow", - "version": "1.0", - "start": "Book Lending Request", - "states": [ - { - "type": "event", - "name": "Book Lending Request", - "onEvents": [ - { - "eventRefs": [ - "Book Lending Request Event" - ] - } - ], - "transition": "Get Book Status" - }, - { - "type": "operation", - "name": "Get Book Status", - "actions": [ - { - "functionRef": { - "refName": "Get status for book", - "arguments": { - "bookid": "${ .book.id }" - } - } - } - ], - "transition": "Book Status Decision" - }, - { - "type": "switch", - "name": "Book Status Decision", - "dataConditions": [ - { - "name": "Book is on loan", - "condition": "${ .book.status == \"onloan\" }", - "transition": "Report Status To Lender" - }, - { - "name": "Check is available", - "condition": "${ .book.status == \"available\" }", - "transition": "Check Out Book" - } - ] - }, - { - "type": "operation", - "name": "Report Status To Lender", - "actions": [ - { - "functionRef": { - "refName": "Send status to lender", - "arguments": { - "bookid": "${ .book.id }", - "message": "Book ${ .book.title } is already on loan" - } - } - } - ], - "transition": "Wait for Lender response" - }, - { - "type": "switch", - "name": "Wait for Lender response", - "eventConditions": [ - { - "name": "Hold Book", - "eventRef": "Hold Book Event", - "transition": "Request Hold" - }, - { - "name": "Decline Book Hold", - "eventRef": "Decline Hold Event", - "transition": "Cancel Request" - } - ] - }, - { - "type": "operation", - "name": "Request Hold", - "actions": [ - { - "functionRef": { - "refName": "Request hold for lender", - "arguments": { - "bookid": "${ .book.id }", - "lender": "${ .lender }" - } - } - } - ], - "transition": "Wait two weeks" - }, - { - "type": "delay", - "name": "Wait two weeks", - "timeDelay": "PT2W", - "transition": "Get Book Status" - }, - { - "type": "operation", - "name": "Check Out Book", - "actions": [ - { - "functionRef": { - "refName": "Check out book with id", - "arguments": { - "bookid": "${ .book.id }" - } - } - }, - { - "functionRef": { - "refName": "Notify Lender for checkout", - "arguments": { - "bookid": "${ .book.id }", - "lender": "${ .lender }" - } - } - } - ], - "end": true - } - ], - "functions": "file://books/lending/functions.json", - "events": "file://books/lending/events.json" -} +{ + "id": "booklending", + "name": "Book Lending Workflow", + "version": "1.0", + "specVersion": "0.7", + "start": "Book Lending Request", + "states": [ + { + "type": "event", + "name": "Book Lending Request", + "onEvents": [ + { + "eventRefs": ["Book Lending Request Event"] + } + ], + "transition": "Get Book Status" + }, + { + "type": "operation", + "name": "Get Book Status", + "actions": [ + { + "functionRef": { + "refName": "Get status for book", + "arguments": { + "bookid": "${ .book.id }" + } + } + } + ], + "transition": "Book Status Decision" + }, + { + "type": "switch", + "name": "Book Status Decision", + "dataConditions": [ + { + "name": "Book is on loan", + "condition": "${ .book.status == \"onloan\" }", + "transition": "Report Status To Lender" + }, + { + "name": "Check is available", + "condition": "${ .book.status == \"available\" }", + "transition": "Check Out Book" + } + ] + }, + { + "type": "operation", + "name": "Report Status To Lender", + "actions": [ + { + "functionRef": { + "refName": "Send status to lender", + "arguments": { + "bookid": "${ .book.id }", + "message": "Book ${ .book.title } is already on loan" + } + } + } + ], + "transition": "Wait for Lender response" + }, + { + "type": "switch", + "name": "Wait for Lender response", + "eventConditions": [ + { + "name": "Hold Book", + "eventRef": "Hold Book Event", + "transition": "Request Hold" + }, + { + "name": "Decline Book Hold", + "eventRef": "Decline Hold Event", + "transition": "Cancel Request" + } + ] + }, + { + "type": "operation", + "name": "Request Hold", + "actions": [ + { + "functionRef": { + "refName": "Request hold for lender", + "arguments": { + "bookid": "${ .book.id }", + "lender": "${ .lender }" + } + } + } + ], + "transition": "Wait two weeks" + }, + { + "type": "delay", + "name": "Wait two weeks", + "timeDelay": "PT2W", + "transition": "Get Book Status" + }, + { + "type": "operation", + "name": "Check Out Book", + "actions": [ + { + "functionRef": { + "refName": "Check out book with id", + "arguments": { + "bookid": "${ .book.id }" + } + } + }, + { + "functionRef": { + "refName": "Notify Lender for checkout", + "arguments": { + "bookid": "${ .book.id }", + "lender": "${ .lender }" + } + } + } + ], + "end": true + } + ], + "functions": "file://books/lending/functions.json", + "events": "file://books/lending/events.json" +} diff --git a/tests/examples/booklending.spec.ts b/tests/examples/booklending.spec.ts index c765ddc..0c25f46 100644 --- a/tests/examples/booklending.spec.ts +++ b/tests/examples/booklending.spec.ts @@ -35,6 +35,7 @@ describe('booklending workflow example', () => { .id('booklending') .name('Book Lending Workflow') .version('1.0') + .specVersion('0.7') .start('Book Lending Request') .states([ eventstateBuilder() diff --git a/tests/examples/carauctionbids.json b/tests/examples/carauctionbids.json index e7e64ea..66a435c 100644 --- a/tests/examples/carauctionbids.json +++ b/tests/examples/carauctionbids.json @@ -1,47 +1,44 @@ -{ - "id": "handleCarAuctionBid", - "version": "1.0", - "name": "Car Auction Bidding Workflow", - "description": "Store a single bid whole the car auction is active", - "start": { - "stateName": "StoreCarAuctionBid", - "schedule": "2020-03-20T09:00:00Z/2020-03-20T15:00:00Z" - }, - "functions": [ - { - "name": "StoreBidFunction", - "operation": "http://myapis.org/carauctionapi.json#storeBid" - } - ], - "events": [ - { - "name": "CarBidEvent", - "type": "carBidMadeType", - "source": "carBidEventSource" - } - ], - "states": [ - { - "type": "event", - "name": "StoreCarAuctionBid", - "onEvents": [ - { - "eventRefs": [ - "CarBidEvent" - ], - "actions": [ - { - "functionRef": { - "refName": "StoreBidFunction", - "arguments": { - "bid": "${ .bid }" - } - } - } - ] - } - ], - "end": true - } - ] -} +{ + "id": "handleCarAuctionBid", + "version": "1.0", + "specVersion": "0.7", + "name": "Car Auction Bidding Workflow", + "description": "Store a single bid whole the car auction is active", + "start": { + "stateName": "StoreCarAuctionBid", + "schedule": "R/PT2H" + }, + "functions": [ + { + "name": "StoreBidFunction", + "operation": "http://myapis.org/carauctionapi.json#storeBid" + } + ], + "events": [ + { + "name": "CarBidEvent", + "type": "carBidMadeType", + "source": "carBidEventSource" + } + ], + "states": [ + { + "type": "event", + "name": "StoreCarAuctionBid", + "onEvents": [ + { + "eventRefs": ["CarBidEvent"], + "actions": [{ + "functionRef": { + "refName": "StoreBidFunction", + "arguments": { + "bid": "${ .bid }" + } + } + }] + } + ], + "end": true + } + ] +} diff --git a/tests/examples/carauctionbids.spec.ts b/tests/examples/carauctionbids.spec.ts index ea63dbd..4d28cee 100644 --- a/tests/examples/carauctionbids.spec.ts +++ b/tests/examples/carauctionbids.spec.ts @@ -29,11 +29,12 @@ describe('carauctionbids workflow example', () => { const workflow = workflowBuilder() .id('handleCarAuctionBid') .version('1.0') + .specVersion('0.7') .name('Car Auction Bidding Workflow') .description('Store a single bid whole the car auction is active') .start({ stateName: 'StoreCarAuctionBid', - schedule: '2020-03-20T09:00:00Z/2020-03-20T15:00:00Z', + schedule: 'R/PT2H', }) .functions([ functionBuilder().name('StoreBidFunction').operation('http://myapis.org/carauctionapi.json#storeBid').build(), diff --git a/tests/examples/checkcarvitals.json b/tests/examples/checkcarvitals.json index b560b14..e584359 100644 --- a/tests/examples/checkcarvitals.json +++ b/tests/examples/checkcarvitals.json @@ -1,43 +1,72 @@ -{ - "id": "checkcarvitals", - "version": "1.0", - "name": "Check Car Vitals Workflow", - "start": "WhenCarIsOn", - "states": [ - { - "type": "event", - "name": "WhenCarIsOn", - "onEvents": [ - { - "eventRefs": [ - "CarTurnedOnEvent" - ] - } - ], - "transition": "DoCarVitalsChecks" - }, - { - "type": "subflow", - "name": "DoCarVitalsChecks", - "workflowId": "vitalscheck", - "repeat": { - "stopOnEvents": [ - "CarTurnedOffEvent" - ] - }, - "end": true - } - ], - "events": [ - { - "name": "CarTurnedOnEvent", - "type": "car.events", - "source": "my/car/start" - }, - { - "name": "CarTurnedOffEvent", - "type": "car.events", - "source": "my/car/start" - } - ] -} +{ + "id": "checkcarvitals", + "name": "Check Car Vitals Workflow", + "version": "1.0", + "specVersion": "0.7", + "start": "WhenCarIsOn", + "states": [ + { + "type": "event", + "name": "WhenCarIsOn", + "onEvents": [ + { + "eventRefs": ["CarTurnedOnEvent"] + } + ], + "transition": "DoCarVitalsChecks" + }, + { + "type": "operation", + "name": "DoCarVitalsChecks", + "actions": [ + { + "subFlowRef": { + "waitForCompletion": false, + "workflowId": "vitalscheck" + } + } + ], + "transition": "WaitForCarStopped" + }, + { + "type": "event", + "name": "WaitForCarStopped", + "onEvents": [ + { + "eventRefs": ["CarTurnedOffEvent"], + "actions": [ + { + "eventRef": { + "triggerEventRef": "StopVitalsCheck", + "resultEventRef": "VitalsCheckingStopped" + } + } + ] + } + ], + "end": true + } + ], + "events": [ + { + "name": "CarTurnedOnEvent", + "type": "car.events", + "source": "my/car" + }, + { + "name": "CarTurnedOffEvent", + "type": "car.events", + "source": "my/car" + }, + { + "name": "StopVitalsCheck", + "type": "car.events", + "source": "my/car" + }, + { + "name": "VitalsCheckingStopped", + "type": "car.events", + "source": "my/car" + } + ] +} diff --git a/tests/examples/checkcarvitals.spec.ts b/tests/examples/checkcarvitals.spec.ts index 292bd25..5d66226 100644 --- a/tests/examples/checkcarvitals.spec.ts +++ b/tests/examples/checkcarvitals.spec.ts @@ -17,19 +17,22 @@ import * as fs from 'fs'; import { eventdefBuilder, + subflowrefBuilder, + actionBuilder, + operationstateBuilder, eventstateBuilder, oneventsBuilder, - repeatBuilder, - subflowstateBuilder, workflowBuilder, + eventrefBuilder, } from '../../src'; describe('checkcarvitals workflow example', () => { it('should generate Workflow object', function () { const workflow = workflowBuilder() .id('checkcarvitals') - .version('1.0') .name('Check Car Vitals Workflow') + .version('1.0') + .specVersion('0.7') .start('WhenCarIsOn') .states([ eventstateBuilder() @@ -37,15 +40,36 @@ describe('checkcarvitals workflow example', () => { .onEvents([oneventsBuilder().eventRefs(['CarTurnedOnEvent']).build()]) .transition('DoCarVitalsChecks') .build(), - subflowstateBuilder() + operationstateBuilder() .name('DoCarVitalsChecks') - .workflowId('vitalscheck') - .repeat(repeatBuilder().stopOnEvents(['CarTurnedOffEvent']).build()) + .actions([ + actionBuilder() + .subFlowRef(subflowrefBuilder().workflowId('vitalscheck').waitForCompletion(false).build()) + .build(), + ]) + .transition('WaitForCarStopped') + .build(), + eventstateBuilder() + .name('WaitForCarStopped') + .onEvents([ + oneventsBuilder() + .eventRefs(['CarTurnedOffEvent']) + .actions([ + actionBuilder() + .eventRef( + eventrefBuilder().triggerEventRef('StopVitalsCheck').resultEventRef('VitalsCheckingStopped').build() + ) + .build(), + ]) + .build(), + ]) .build(), ]) .events([ - eventdefBuilder().name('CarTurnedOnEvent').type('car.events').source('my/car/start').build(), - eventdefBuilder().name('CarTurnedOffEvent').type('car.events').source('my/car/start').build(), + eventdefBuilder().name('CarTurnedOnEvent').type('car.events').source('my/car').build(), + eventdefBuilder().name('CarTurnedOffEvent').type('car.events').source('my/car').build(), + eventdefBuilder().name('StopVitalsCheck').type('car.events').source('my/car').build(), + eventdefBuilder().name('VitalsCheckingStopped').type('car.events').source('my/car').build(), ]) .build(); diff --git a/tests/examples/jobmonitoring.json b/tests/examples/jobmonitoring.json index 3c37daa..0630a78 100644 --- a/tests/examples/jobmonitoring.json +++ b/tests/examples/jobmonitoring.json @@ -1,134 +1,139 @@ -{ - "id": "jobmonitoring", - "version": "1.0", - "name": "Job Monitoring", - "description": "Monitor finished execution of a submitted job", - "start": "SubmitJob", - "functions": [ - { - "name": "submitJob", - "operation": "http://myapis.org/monitorapi.json#doSubmit" - }, - { - "name": "checkJobStatus", - "operation": "http://myapis.org/monitorapi.json#checkStatus" - }, - { - "name": "reportJobSuceeded", - "operation": "http://myapis.org/monitorapi.json#reportSucceeded" - }, - { - "name": "reportJobFailed", - "operation": "http://myapis.org/monitorapi.json#reportFailure" - } - ], - "states": [ - { - "type": "operation", - "name": "SubmitJob", - "actions": [ - { - "functionRef": { - "refName": "submitJob", - "arguments": { - "name": "${ .job.name }" - } - }, - "actionDataFilter": { - "results": "${ .jobuid }" - } - } - ], - "onErrors": [ - { - "error": "*", - "transition": "SubmitError" - } - ], - "stateDataFilter": { - "output": "${ .jobuid }" - }, - "transition": "WaitForCompletion" - }, - { - "type": "subflow", - "name": "SubmitError", - "workflowId": "handleJobSubmissionErrorWorkflow", - "end": true - }, - { - "type": "delay", - "name": "WaitForCompletion", - "timeDelay": "PT5S", - "transition": "GetJobStatus" - }, - { - "type": "operation", - "name": "GetJobStatus", - "actions": [ - { - "functionRef": { - "refName": "checkJobStatus", - "arguments": { - "name": "${ .jobuid }" - } - }, - "actionDataFilter": { - "results": "${ .jobstatus }" - } - } - ], - "stateDataFilter": { - "output": "${ .jobstatus }" - }, - "transition": "DetermineCompletion" - }, - { - "type": "switch", - "name": "DetermineCompletion", - "dataConditions": [ - { - "condition": "${ .jobStatus == \"SUCCEEDED\" }", - "transition": "JobSucceeded" - }, - { - "condition": "${ .jobStatus == \"FAILED\" }", - "transition": "JobFailed" - } - ], - "default": { - "transition": "WaitForCompletion" - } - }, - { - "type": "operation", - "name": "JobSucceeded", - "actions": [ - { - "functionRef": { - "refName": "reportJobSuceeded", - "arguments": { - "name": "${ .jobuid }" - } - } - } - ], - "end": true - }, - { - "type": "operation", - "name": "JobFailed", - "actions": [ - { - "functionRef": { - "refName": "reportJobFailed", - "arguments": { - "name": "${ .jobuid }" - } - } - } - ], - "end": true - } - ] -} +{ + "id": "jobmonitoring", + "version": "1.0", + "specVersion": "0.7", + "name": "Job Monitoring", + "description": "Monitor finished execution of a submitted job", + "start": "SubmitJob", + "functions": [ + { + "name": "submitJob", + "operation": "http://myapis.org/monitorapi.json#doSubmit" + }, + { + "name": "checkJobStatus", + "operation": "http://myapis.org/monitorapi.json#checkStatus" + }, + { + "name": "reportJobSuceeded", + "operation": "http://myapis.org/monitorapi.json#reportSucceeded" + }, + { + "name": "reportJobFailed", + "operation": "http://myapis.org/monitorapi.json#reportFailure" + } + ], + "states":[ + { + "type":"operation", + "name":"SubmitJob", + "actions":[ + { + "functionRef": { + "refName": "submitJob", + "arguments": { + "name": "${ .job.name }" + } + }, + "actionDataFilter": { + "results": "${ .jobuid }" + } + } + ], + "onErrors": [ + { + "error": "*", + "transition": "SubmitError" + } + ], + "stateDataFilter": { + "output": "${ .jobuid }" + }, + "transition": "WaitForCompletion" + }, + { + "type": "operation", + "name": "SubmitError", + "actions": [ + { + "subFlowRef": "handleJobSubmissionErrorWorkflow" + } + ], + "end": true + }, + { + "type": "delay", + "name": "WaitForCompletion", + "timeDelay": "PT5S", + "transition": "GetJobStatus" + }, + { + "type":"operation", + "name":"GetJobStatus", + "actions":[ + { + "functionRef": { + "refName": "checkJobStatus", + "arguments": { + "name": "${ .jobuid }" + } + }, + "actionDataFilter": { + "results": "${ .jobstatus }" + } + } + ], + "stateDataFilter": { + "output": "${ .jobstatus }" + }, + "transition": "DetermineCompletion" + }, + { + "type":"switch", + "name":"DetermineCompletion", + "dataConditions": [ + { + "condition": "${ .jobStatus == \"SUCCEEDED\" }", + "transition": "JobSucceeded" + }, + { + "condition": "${ .jobStatus == \"FAILED\" }", + "transition": "JobFailed" + } + ], + "defaultCondition": { + "transition": "WaitForCompletion" + } + }, + { + "type":"operation", + "name":"JobSucceeded", + "actions":[ + { + "functionRef": { + "refName": "reportJobSuceeded", + "arguments": { + "name": "${ .jobuid }" + } + } + } + ], + "end": true + }, + { + "type":"operation", + "name":"JobFailed", + "actions":[ + { + "functionRef": { + "refName": "reportJobFailed", + "arguments": { + "name": "${ .jobuid }" + } + } + } + ], + "end": true + } + ] +} diff --git a/tests/examples/jobmonitoring.spec.ts b/tests/examples/jobmonitoring.spec.ts index 3af1994..b864764 100644 --- a/tests/examples/jobmonitoring.spec.ts +++ b/tests/examples/jobmonitoring.spec.ts @@ -19,16 +19,15 @@ import { actionBuilder, actiondatafilterBuilder, databasedswitchBuilder, - defaultdefBuilder, delaystateBuilder, errorBuilder, functionBuilder, functionrefBuilder, operationstateBuilder, statedatafilterBuilder, - subflowstateBuilder, transitiondataconditionBuilder, workflowBuilder, + defaultconditiondefBuilder, } from '../../src'; describe('jobmonitoring workflow example', () => { @@ -36,6 +35,7 @@ describe('jobmonitoring workflow example', () => { const workflow = workflowBuilder() .id('jobmonitoring') .version('1.0') + .specVersion('0.7') .name('Job Monitoring') .description('Monitor finished execution of a submitted job') .start('SubmitJob') @@ -69,7 +69,11 @@ describe('jobmonitoring workflow example', () => { .stateDataFilter(statedatafilterBuilder().output('${ .jobuid }').build()) .transition('WaitForCompletion') .build(), - subflowstateBuilder().name('SubmitError').workflowId('handleJobSubmissionErrorWorkflow').build(), + + operationstateBuilder() + .name('SubmitError') + .actions([actionBuilder().subFlowRef('handleJobSubmissionErrorWorkflow').build()]) + .build(), delaystateBuilder().name('WaitForCompletion').timeDelay('PT5S').transition('GetJobStatus').build(), operationstateBuilder() .name('GetJobStatus') @@ -99,7 +103,7 @@ describe('jobmonitoring workflow example', () => { .build(), transitiondataconditionBuilder().condition('${ .jobStatus == "FAILED" }').transition('JobFailed').build(), ]) - .default(defaultdefBuilder().transition('WaitForCompletion').build()) + .defaultCondition(defaultconditiondefBuilder().transition('WaitForCompletion').build()) .build(), operationstateBuilder() .name('JobSucceeded') diff --git a/tests/examples/parallel.json b/tests/examples/parallel.json index 003268a..8a7d80b 100644 --- a/tests/examples/parallel.json +++ b/tests/examples/parallel.json @@ -1,24 +1,29 @@ -{ - "id": "parallelexec", - "version": "1.0", - "name": "Parallel Execution Workflow", - "description": "Executes two branches in parallel", - "start": "ParallelExec", - "states": [ - { - "type": "parallel", - "name": "ParallelExec", - "branches": [ - { - "name": "ShortDelayBranch", - "workflowId": "shortdelayworkflowid" - }, - { - "name": "LongDelayBranch", - "workflowId": "longdelayworkflowid" - } - ], - "end": true - } - ] -} +{ + "id": "parallelexec", + "version": "1.0", + "specVersion": "0.7", + "name": "Parallel Execution Workflow", + "description": "Executes two branches in parallel", + "start": "ParallelExec", + "states":[ + { + "type": "parallel", + "name": "ParallelExec", + "branches": [ + { + "name": "ShortDelayBranch", + "actions": [{ + "subFlowRef": "shortdelayworkflowid" + }] + }, + { + "name": "LongDelayBranch", + "actions": [{ + "subFlowRef": "longdelayworkflowid" + }] + } + ], + "end": true + } + ] +} diff --git a/tests/examples/parallel.spec.ts b/tests/examples/parallel.spec.ts index 2ddd6b0..16ca4ad 100644 --- a/tests/examples/parallel.spec.ts +++ b/tests/examples/parallel.spec.ts @@ -15,23 +15,30 @@ * */ import * as fs from 'fs'; -import { branchBuilder, parallelstateBuilder, workflowBuilder } from '../../src'; +import { actionBuilder, branchBuilder, parallelstateBuilder, workflowBuilder } from '../../src'; describe('parallel workflow example', () => { it('should generate Workflow object', function () { const workflow = workflowBuilder() .id('parallelexec') .version('1.0') + .specVersion('0.7') .name('Parallel Execution Workflow') .description('Executes two branches in parallel') .start('ParallelExec') .states([ parallelstateBuilder() .name('ParallelExec') - .completionType('and') + .completionType('allOf') .branches([ - branchBuilder().name('ShortDelayBranch').workflowId('shortdelayworkflowid').build(), - branchBuilder().name('LongDelayBranch').workflowId('longdelayworkflowid').build(), + branchBuilder() + .name('ShortDelayBranch') + .actions([actionBuilder().subFlowRef('shortdelayworkflowid').build()]) + .build(), + branchBuilder() + .name('LongDelayBranch') + .actions([actionBuilder().subFlowRef('longdelayworkflowid').build()]) + .build(), ]) .build(), ]) diff --git a/tests/examples/provisionorder.json b/tests/examples/provisionorder.json index af49dd5..4bf4160 100644 --- a/tests/examples/provisionorder.json +++ b/tests/examples/provisionorder.json @@ -1,71 +1,88 @@ -{ - "id": "provisionorders", - "version": "1.0", - "name": "Provision Orders", - "description": "Provision Orders and handle errors thrown", - "start": "ProvisionOrder", - "functions": [ - { - "name": "provisionOrderFunction", - "operation": "http://myapis.org/provisioningapi.json#doProvision" - } - ], - "states": [ - { - "type": "operation", - "name": "ProvisionOrder", - "actions": [ - { - "functionRef": { - "refName": "provisionOrderFunction", - "arguments": { - "order": "${ .order }" - } - } - } - ], - "stateDataFilter": { - "output": "${ .exceptions }" - }, - "transition": "ApplyOrder", - "onErrors": [ - { - "error": "Missing order id", - "transition": "MissingId" - }, - { - "error": "Missing order item", - "transition": "MissingItem" - }, - { - "error": "Missing order quantity", - "transition": "MissingQuantity" - } - ] - }, - { - "type": "subflow", - "name": "MissingId", - "workflowId": "handleMissingIdExceptionWorkflow", - "end": true - }, - { - "type": "subflow", - "name": "MissingItem", - "workflowId": "handleMissingItemExceptionWorkflow", - "end": true - }, - { - "type": "subflow", - "name": "MissingQuantity", - "workflowId": "handleMissingQuantityExceptionWorkflow", - "end": true - }, - { - "type": "subflow", - "name": "ApplyOrder", - "workflowId": "applyOrderWorkflowId", - "end": true - } - ] -} +{ + "id": "provisionorders", + "version": "1.0", + "specVersion": "0.7", + "name": "Provision Orders", + "description": "Provision Orders and handle errors thrown", + "start": "ProvisionOrder", + "functions": [ + { + "name": "provisionOrderFunction", + "operation": "http://myapis.org/provisioningapi.json#doProvision" + } + ], + "states":[ + { + "type":"operation", + "name":"ProvisionOrder", + "actions":[ + { + "functionRef": { + "refName": "provisionOrderFunction", + "arguments": { + "order": "${ .order }" + } + } + } + ], + "stateDataFilter": { + "output": "${ .exceptions }" + }, + "transition": "ApplyOrder", + "onErrors": [ + { + "error": "Missing order id", + "transition": "MissingId" + }, + { + "error": "Missing order item", + "transition": "MissingItem" + }, + { + "error": "Missing order quantity", + "transition": "MissingQuantity" + } + ] + }, + { + "type": "operation", + "name": "MissingId", + "actions": [ + { + "subFlowRef": "handleMissingIdExceptionWorkflow" + } + ], + "end": true + }, + { + "type": "operation", + "name": "MissingItem", + "actions": [ + { + "subFlowRef": "handleMissingItemExceptionWorkflow" + } + ], + "end": true + }, + { + "type": "operation", + "name": "MissingQuantity", + "actions": [ + { + "subFlowRef": "handleMissingQuantityExceptionWorkflow" + } + ], + "end": true + }, + { + "type": "operation", + "name": "ApplyOrder", + "actions": [ + { + "subFlowRef": "applyOrderWorkflowId" + } + ], + "end": true + } + ] +} diff --git a/tests/examples/provisionorder.spec.ts b/tests/examples/provisionorder.spec.ts index b868adf..dcedd21 100644 --- a/tests/examples/provisionorder.spec.ts +++ b/tests/examples/provisionorder.spec.ts @@ -21,7 +21,6 @@ import { functionBuilder, operationstateBuilder, statedatafilterBuilder, - subflowstateBuilder, workflowBuilder, functionrefBuilder, } from '../../src'; @@ -31,6 +30,7 @@ describe('provisionorder workflow example', () => { const workflow = workflowBuilder() .id('provisionorders') .version('1.0') + .specVersion('0.7') .name('Provision Orders') .description('Provision Orders and handle errors thrown') .start('ProvisionOrder') @@ -64,10 +64,22 @@ describe('provisionorder workflow example', () => { errorBuilder().error('Missing order quantity').transition('MissingQuantity').build(), ]) .build(), - subflowstateBuilder().name('MissingId').workflowId('handleMissingIdExceptionWorkflow').build(), - subflowstateBuilder().name('MissingItem').workflowId('handleMissingItemExceptionWorkflow').build(), - subflowstateBuilder().name('MissingQuantity').workflowId('handleMissingQuantityExceptionWorkflow').build(), - subflowstateBuilder().name('ApplyOrder').workflowId('applyOrderWorkflowId').build(), + operationstateBuilder() + .name('MissingId') + .actions([actionBuilder().subFlowRef('handleMissingIdExceptionWorkflow').build()]) + .build(), + operationstateBuilder() + .name('MissingItem') + .actions([actionBuilder().subFlowRef('handleMissingItemExceptionWorkflow').build()]) + .build(), + operationstateBuilder() + .name('MissingQuantity') + .actions([actionBuilder().subFlowRef('handleMissingQuantityExceptionWorkflow').build()]) + .build(), + operationstateBuilder() + .name('ApplyOrder') + .actions([actionBuilder().subFlowRef('applyOrderWorkflowId').build()]) + .build(), ]) .build(); diff --git a/tests/examples/sendcloudevent.json b/tests/examples/sendcloudevent.json index 85fd2da..7ab9429 100644 --- a/tests/examples/sendcloudevent.json +++ b/tests/examples/sendcloudevent.json @@ -1,6 +1,7 @@ { "id": "sendcloudeventonprovision", "version": "1.0", + "specVersion": "0.7", "name": "Send CloudEvent on provision completion", "start": "ProvisionOrdersState", "events": [ @@ -34,12 +35,10 @@ } ], "end": { - "produceEvents": [ - { - "eventRef": "provisioningCompleteEvent", - "data": "${ .provisionedOrders }" - } - ] + "produceEvents": [{ + "eventRef": "provisioningCompleteEvent", + "data": "${ .provisionedOrders }" + }] } } ] diff --git a/tests/examples/sendcloudevent.spec.ts b/tests/examples/sendcloudevent.spec.ts index 23374dd..b747eee 100644 --- a/tests/examples/sendcloudevent.spec.ts +++ b/tests/examples/sendcloudevent.spec.ts @@ -30,6 +30,7 @@ describe('sendcloudevent workflow example', () => { const workflow = workflowBuilder() .id('sendcloudeventonprovision') .version('1.0') + .specVersion('0.7') .name('Send CloudEvent on provision completion') .start('ProvisionOrdersState') .events([ diff --git a/tests/examples/solvemathproblems.json b/tests/examples/solvemathproblems.json index 12b27da..2b56018 100644 --- a/tests/examples/solvemathproblems.json +++ b/tests/examples/solvemathproblems.json @@ -1,6 +1,7 @@ { "id": "solvemathproblems", "version": "1.0", + "specVersion": "0.7", "name": "Solve Math Problems Workflow", "description": "Solve math problems", "start": "Solve", @@ -10,14 +11,14 @@ "operation": "http://myapis.org/mapthapis.json#solveExpression" } ], - "states": [ + "states":[ { - "type": "foreach", - "name": "Solve", + "type":"foreach", + "name":"Solve", "inputCollection": "${ .expressions }", "iterationParam": "singleexpression", "outputCollection": "${ .results }", - "actions": [ + "actions":[ { "functionRef": { "refName": "solveMathExpressionFunction", diff --git a/tests/examples/solvemathproblems.spec.ts b/tests/examples/solvemathproblems.spec.ts index fa0db3b..42adab1 100644 --- a/tests/examples/solvemathproblems.spec.ts +++ b/tests/examples/solvemathproblems.spec.ts @@ -28,6 +28,7 @@ describe('solvemathproblems workflow example', () => { const workflow = workflowBuilder() .id('solvemathproblems') .version('1.0') + .specVersion('0.7') .name('Solve Math Problems Workflow') .description('Solve math problems') .start('Solve') diff --git a/tests/lib/builders/eventstate-builder.spec.ts b/tests/lib/builders/eventstate-builder.spec.ts index 6cf67c2..67079e6 100644 --- a/tests/lib/builders/eventstate-builder.spec.ts +++ b/tests/lib/builders/eventstate-builder.spec.ts @@ -40,18 +40,5 @@ describe('eventstateBuilder ', () => { transition: 'Get Book Status', }) ); - - // const deserializedObject = object.deserialize(serializedObject); - // expect(deserializedObject.exclusive).toBeTrue(); - - //Having serialize/ deserialize de following signature - - // deserialize(value: string): Eventstate { - - // } - // normalize(): string { - - // } - // }); }); diff --git a/tests/lib/builders/subflow-builder.spec.ts b/tests/lib/definitions/subflowref.spec.ts similarity index 68% rename from tests/lib/builders/subflow-builder.spec.ts rename to tests/lib/definitions/subflowref.spec.ts index 7597268..1c23dba 100644 --- a/tests/lib/builders/subflow-builder.spec.ts +++ b/tests/lib/definitions/subflowref.spec.ts @@ -14,22 +14,20 @@ * limitations under the License. * */ -import { subflowstateBuilder } from '../../../src/lib/builders/subflowstate-builder'; - -describe('subflowstateBuilder ', () => { - it('should build an object', () => { - const object = subflowstateBuilder().name('StartApplication').workflowId('startApplicationWorkflowId').build(); - expect(object.waitForCompletion).toBeFalse(); +import { Subflowref } from '../../../src/lib/definitions/subflowref'; +describe('Subflowref ', () => { + it('normalize should unset properties whose value is equal to its default value', () => { + const object = new Subflowref({ workflowId: 'startApplicationWorkflowId' }); + expect(object.waitForCompletion).toBeTrue(); const serializedObject = object.normalize(); + expect(JSON.stringify(serializedObject)).toBe( JSON.stringify({ - type: 'subflow', - name: 'StartApplication', workflowId: 'startApplicationWorkflowId', - end: true, }) ); + expect(serializedObject.waitForCompletion).toBeUndefined(); }); }); diff --git a/tests/lib/definitions/util.spec.ts b/tests/lib/definitions/util.spec.ts new file mode 100644 index 0000000..7a167b8 --- /dev/null +++ b/tests/lib/definitions/util.spec.ts @@ -0,0 +1,71 @@ +/* + * Copyright 2021-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { overwritePropertyAsPlainType } from '../../../src/lib/definitions/utils'; + +describe('Util ', () => { + describe('overwritePropertyAsPlainType ', () => { + class HasTimeouts { + timeouts?: { + key: string; + }; + } + + it('should create a copy of timeouts property', () => { + const source = { + timeouts: { + key: 'action', + }, + } as HasTimeouts; + + const target = {} as HasTimeouts; + Object.assign(target, source); + overwritePropertyAsPlainType('timeouts', target); + + expect(target.timeouts!.key).toBe('action'); + source.timeouts!.key = 'action2'; + expect(target.timeouts!.key).toBe('action'); + }); + + class HasData { + data?: + | string + | { + [key: string]: any; + }; + } + + it('should create a copy of data property', () => { + const source = { + data: { + key1: 'value1', + }, + } as HasData; + + const target = {} as HasData; + Object.assign(target, source); + overwritePropertyAsPlainType('data', target); + + // @ts-ignore + expect(target!.data['key1']).toBe('value1'); + // @ts-ignore + source!.data['key1'] = 'value2'; + // @ts-ignore + expect(target!.data['key1']).toBe('value1'); + }); + }); +}); diff --git a/tests/lib/definitions/workflow-converter-hello-world.json b/tests/lib/definitions/workflow-converter-hello-world.json index a313bf9..5d763af 100644 --- a/tests/lib/definitions/workflow-converter-hello-world.json +++ b/tests/lib/definitions/workflow-converter-hello-world.json @@ -1,6 +1,7 @@ { "id": "helloworld", "version": "1.0", + "specVersion": "0.7", "name": "Hello World Workflow", "description": "Inject Hello World", "start": "Hello State", diff --git a/tests/lib/definitions/workflow-converter-hello-world.yaml b/tests/lib/definitions/workflow-converter-hello-world.yaml index 4320ecb..854b4a4 100644 --- a/tests/lib/definitions/workflow-converter-hello-world.yaml +++ b/tests/lib/definitions/workflow-converter-hello-world.yaml @@ -1,5 +1,6 @@ id: helloworld version: '1.0' +specVersion": '0.7' name: Hello World Workflow description: Inject Hello World start: Hello State diff --git a/tests/lib/definitions/workflow-converter-hello-world.yml b/tests/lib/definitions/workflow-converter-hello-world.yml index 4320ecb..854b4a4 100644 --- a/tests/lib/definitions/workflow-converter-hello-world.yml +++ b/tests/lib/definitions/workflow-converter-hello-world.yml @@ -1,5 +1,6 @@ id: helloworld version: '1.0' +specVersion": '0.7' name: Hello World Workflow description: Inject Hello World start: Hello State diff --git a/tests/lib/definitions/workflow.spec.ts b/tests/lib/definitions/workflow.spec.ts index cef3c82..57cb800 100644 --- a/tests/lib/definitions/workflow.spec.ts +++ b/tests/lib/definitions/workflow.spec.ts @@ -73,7 +73,7 @@ describe('workflow ', () => { maxAttempts: 4, }, ], - execTimeout: { + timeouts: { duration: 'P30M5S', }, metadata: { @@ -84,8 +84,7 @@ describe('workflow ', () => { const model = new Workflow(data); expect(model.functions![0]!.constructor.name).toBe('Function'); - expect(model.execTimeout!.constructor.name).toBe('Exectimeout'); - expect(model.metadata!.constructor.name).toBe('Metadata'); + expect(model.timeouts!.constructor.name).toBe('Timeouts'); expect(model.metadata!.constructor.name).toBe('Metadata'); expect(model.events![0]!.constructor.name).toBe('Eventdef'); expect(model.retries![0]!.constructor.name).toBe('Retrydef'); @@ -96,6 +95,7 @@ describe('workflow ', () => { workflowBuilder() .id('helloworld') .version('1.0') + .specVersion('0.7') .name('Hello World Workflow') .description('Inject Hello World') .start('Hello State') @@ -114,6 +114,7 @@ describe('workflow ', () => { '{' + '"id":"helloworld",' + '"version":"1.0",' + + '"specVersion":"0.7",' + '"name":"Hello World Workflow",' + '"description":"Inject Hello World",' + '"start":"Hello State",' + @@ -136,6 +137,7 @@ describe('workflow ', () => { workflowBuilder() .id('helloworld') .version('1.0') + .specVersion('0.7') .name('Hello World Workflow') .description('Inject Hello World') .start('Hello State') @@ -153,6 +155,7 @@ describe('workflow ', () => { expect(yamlWorkflow).toBe( 'id: helloworld\n' + "version: '1.0'\n" + + "specVersion: '0.7'\n" + 'name: Hello World Workflow\n' + 'description: Inject Hello World\n' + 'start: Hello State\n' + @@ -165,36 +168,3 @@ describe('workflow ', () => { ); }); }); - -// describe('Workflow serialize / deserialize ', () => { -// it('should serialize whiout default values, / deserialize with default values', () => { -// const workflow = new Workflow({ -// id: 'helloworld', -// version: '1.0', -// name: 'Hello World Workflow', -// description: 'Inject Hello World', -// start: 'Hello State', -// keepActive: true, -// states: [ -// { -// type: 'inject', -// name: 'Hello State', -// data: { -// result: 'Hello World!', -// }, -// end: true, -// }, -// ], -// }); -// -// const serializedWF = workflow.normalize(); -// -// expect(JSON.parse(serializedWF).keepActive).toBeUndefined(); -// expect(JSON.parse(serializedWF).expressionLang).toBeUndefined(); -// -// const deserializedWF = Workflow.fromSource(serializedWF); -// -// expect(deserializedWF.keepActive).toBeTrue(); -// expect(deserializedWF.expressionLang).toBe('jq'); -// }); -// }); diff --git a/tests/lib/workflow-validator.spec.ts b/tests/lib/workflow-validator.spec.ts index 53fdd45..396897f 100644 --- a/tests/lib/workflow-validator.spec.ts +++ b/tests/lib/workflow-validator.spec.ts @@ -24,6 +24,7 @@ describe('workflow-validator', () => { id: 'helloworld', name: 'Hello World Workflow', version: '1.0', + specVersion: '0.7', description: 'Inject Hello World', start: 'Hello State', states: [], @@ -43,6 +44,7 @@ describe('workflow-validator', () => { const workflow = { id: 'helloworld', version: '1.0', + specVersion: '0.7', name: 'Hello World Workflow', description: 'Inject Hello World', start: 'Hello State', diff --git a/tools/consts.ts b/tools/consts.ts index eea188c..0b94bee 100644 --- a/tools/consts.ts +++ b/tools/consts.ts @@ -24,10 +24,9 @@ export const fileHeader = `/* * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, -* oUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. -* */ `;