From 7b42d8ac8d848e92b98c3fab07e17ee664a480c6 Mon Sep 17 00:00:00 2001 From: Mihael Konjevic Date: Sat, 10 Feb 2024 18:52:48 +0100 Subject: [PATCH] feat: utility types for workflow, workItem, task and explicit condition types from workflow builder --- package-lock.json | 201 +++++++++++--------------- package.json | 4 +- src/Service.ts | 32 ++--- src/builder/CompositeTaskBuilder.ts | 63 +++++---- src/builder/WorkflowBuilder.ts | 209 +++++++++++++++++++++------- src/elements/Workflow.ts | 4 +- src/index.ts | 20 +++ src/types.ts | 28 ++-- 8 files changed, 335 insertions(+), 226 deletions(-) diff --git a/package-lock.json b/package-lock.json index 77c057c..011ff26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,8 +27,8 @@ "@trivago/prettier-plugin-sort-imports": "^4.1.1", "@types/node": "^18.16.3", "@types/prompts": "^2.4.4", - "@typescript-eslint/eslint-plugin": "^5.61.0", - "@typescript-eslint/parser": "^5.61.0", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "c8": "^8.0.0", "cspell": "^6.31.1", "eslint": "^8.44.0", @@ -3248,32 +3248,33 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -3282,25 +3283,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -3309,16 +3311,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -3326,25 +3328,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -3353,12 +3355,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -3366,21 +3368,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -3413,42 +3416,41 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -6046,19 +6048,6 @@ "eslint": ">=5.0.0" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", @@ -6321,15 +6310,6 @@ "node": ">=4.0" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -9231,12 +9211,6 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -15331,6 +15305,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ts-api-utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -15370,27 +15356,6 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/tsx": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", diff --git a/package.json b/package.json index 7d405bc..591f4a5 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,8 @@ "@trivago/prettier-plugin-sort-imports": "^4.1.1", "@types/node": "^18.16.3", "@types/prompts": "^2.4.4", - "@typescript-eslint/eslint-plugin": "^5.61.0", - "@typescript-eslint/parser": "^5.61.0", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "c8": "^8.0.0", "cspell": "^6.31.1", "eslint": "^8.44.0", diff --git a/src/Service.ts b/src/Service.ts index 1ca41d9..e6556d3 100644 --- a/src/Service.ts +++ b/src/Service.ts @@ -24,6 +24,7 @@ import { } from './errors.js'; import * as StateImpl from './state/StateImpl.js'; import { + ElementTypes, ExecutionContext, ExecutionContextQueueItem, GetSym, @@ -37,7 +38,6 @@ import { WorkItemId, WorkItemInstance, WorkItemPayloadSym, - WorkflowAndWorkItemTypes, WorkflowContextSym, WorkflowId, WorkflowInstance, @@ -50,7 +50,7 @@ function pathAsArray(path: string | string[] | readonly string[]) { export class Service< WorkflowMetadata, - WWAIT extends WorkflowAndWorkItemTypes = WorkflowAndWorkItemTypes, + ET extends ElementTypes = ElementTypes, R = never, E = never > { @@ -64,7 +64,9 @@ export class Service< private stateChangeLogger: StateChangeLogger ) {} - onStateChange(fn: OnStateChangeFn) { + onStateChange( + fn: OnStateChangeFn + ) { const changeLog = this.stateChangeLogger.drain(); this.onStateChangeListener = fn; if (changeLog.length) { @@ -579,7 +581,7 @@ export class Service< return Effect.gen(function* ($) { return (yield* $( self.state.getState() - )) as StorePersistableState; + )) as StorePersistableState; }); } @@ -1083,14 +1085,8 @@ function makeStateChangeLogger(): StateChangeLogger { type WorkflowR = T extends Workflow ? R : never; type WorkflowE = T extends Workflow ? E : never; type WorkflowContext = T extends Workflow ? C : never; -type WorkflowWorkflowAndWorkItemTypes = T extends Workflow< - any, - any, - any, - any, - infer WWAIT -> - ? WWAIT +type WorkflowElementTypes = T extends Workflow + ? ET : never; type IsOptional = T extends never @@ -1124,7 +1120,7 @@ export function initialize< const interpreter = new Service< WorkflowMetadata, - WorkflowWorkflowAndWorkItemTypes, + WorkflowElementTypes, R, E >(id, workflow, state, queue, stateChangeLogger); @@ -1137,10 +1133,14 @@ export function resume< W extends Workflow, R extends WorkflowR = WorkflowR, E extends WorkflowE = WorkflowE, - WWAIT extends WorkflowWorkflowAndWorkItemTypes = WorkflowWorkflowAndWorkItemTypes + ET extends WorkflowElementTypes = WorkflowElementTypes >( workflow: W, - resumableState: StorePersistableState + resumableState: StorePersistableState< + ET['workflow'], + ET['workItem'], + ET['task'] + > ) { return Effect.gen(function* ($) { const queue = yield* $(Queue.unbounded()); @@ -1164,7 +1164,7 @@ export function resume< return yield* $(Effect.fail(new InvalidResumableState({}))); } - const interpreter = new Service, WWAIT, R, E>( + const interpreter = new Service, ET, R, E>( rootWorkflow.id, workflow, state, diff --git a/src/builder/CompositeTaskBuilder.ts b/src/builder/CompositeTaskBuilder.ts index db989bc..c101f58 100644 --- a/src/builder/CompositeTaskBuilder.ts +++ b/src/builder/CompositeTaskBuilder.ts @@ -12,10 +12,13 @@ import { import { CompositeTaskActivities, CompositeTaskOnStartPayload, + ConditionInstance, + ElementTypes, JoinType, ShouldCompositeTaskCompleteFn, ShouldCompositeTaskFailFn, SplitType, + TaskInstance, TaskOnCancelPayload, TaskOnCompletePayload, TaskOnDisablePayload, @@ -23,7 +26,6 @@ import { TaskOnFailPayload, TaskOnStartSym, WorkItemInstance, - WorkflowAndWorkItemTypes, WorkflowInstance, activeWorkflowInstanceStates, } from '../types.js'; @@ -32,9 +34,9 @@ import { AnyWorkflowBuilderWithCorrectParentContext, WorkflowBuilderC, WorkflowBuilderE, + WorkflowBuilderElementTypes, WorkflowBuilderMetadata, WorkflowBuilderR, - WorkflowBuilderWorkflowAndWorkItemTypes, } from './WorkflowBuilder.js'; export type CompositeTaskBuilderContext = T extends CompositeTaskBuilder< @@ -158,21 +160,20 @@ interface CompositeTaskActivityMetadata { return: R; } -export type CompositeTaskWorkflowAndWorkItemTypes = - T extends CompositeTaskBuilder< - any, - any, - any, - any, - any, - any, - any, - infer WWAIT, - any, - any - > - ? WWAIT - : never; +export type CompositeTaskElementTypes = T extends CompositeTaskBuilder< + any, + any, + any, + any, + any, + any, + any, + infer ET, + any, + any +> + ? ET + : never; export class CompositeTaskBuilder< C, @@ -182,9 +183,11 @@ export class CompositeTaskBuilder< ST extends SplitType | undefined, CTM = object, WM = never, - WWAIT extends WorkflowAndWorkItemTypes = { + ET extends ElementTypes = { workflow: WorkflowInstance; workItem: WorkItemInstance; + condition: ConditionInstance; + task: TaskInstance; }, R = never, E = never @@ -217,14 +220,14 @@ export class CompositeTaskBuilder< withJoinType( joinType: T - ): CompositeTaskBuilder { + ): CompositeTaskBuilder { this.joinType = joinType; return this; } withSplitType( splitType: T - ): CompositeTaskBuilder { + ): CompositeTaskBuilder { this.splitType = splitType; return this; } @@ -250,7 +253,7 @@ export class CompositeTaskBuilder< ST, CTM, WM, - WWAIT, + ET, R | Effect.Effect.Context>, E | Effect.Effect.Error> > { @@ -270,7 +273,7 @@ export class CompositeTaskBuilder< ST, CTM, WM, - WWAIT, + ET, R | Effect.Effect.Context>, E | Effect.Effect.Error> > { @@ -305,7 +308,7 @@ export class CompositeTaskBuilder< } >, WM, - WWAIT, + ET, R | Effect.Effect.Context>, E | Effect.Effect.Error> > { @@ -327,7 +330,7 @@ export class CompositeTaskBuilder< ST, CTM, WM, - WWAIT, + ET, R | Effect.Effect.Context>, E | Effect.Effect.Error> > { @@ -347,7 +350,7 @@ export class CompositeTaskBuilder< ST, CTM, WM, - WWAIT, + ET, R | Effect.Effect.Context>, E | Effect.Effect.Error> > { @@ -367,7 +370,7 @@ export class CompositeTaskBuilder< ST, CTM, WM, - WWAIT, + ET, R | Effect.Effect.Context>, E | Effect.Effect.Error> > { @@ -385,7 +388,7 @@ export class CompositeTaskBuilder< ST, CTM, WM, - WWAIT, + ET, R | Effect.Effect.Context>, E | Effect.Effect.Error> > { @@ -403,7 +406,7 @@ export class CompositeTaskBuilder< ST, CTM, WM, - WWAIT, + ET, R | Effect.Effect.Context>, E | Effect.Effect.Error> > { @@ -458,7 +461,7 @@ export interface InitialCompositeTaskFnReturnType { undefined, object, WorkflowBuilderMetadata, - WorkflowBuilderWorkflowAndWorkItemTypes, + WorkflowBuilderElementTypes, WorkflowBuilderR, WorkflowBuilderE >; @@ -477,7 +480,7 @@ export function compositeTask() { undefined, object, WorkflowBuilderMetadata, - WorkflowBuilderWorkflowAndWorkItemTypes, + WorkflowBuilderElementTypes, WorkflowBuilderR, WorkflowBuilderE >(workflow).initialize(); diff --git a/src/builder/WorkflowBuilder.ts b/src/builder/WorkflowBuilder.ts index c1c0006..7f7d793 100644 --- a/src/builder/WorkflowBuilder.ts +++ b/src/builder/WorkflowBuilder.ts @@ -8,13 +8,17 @@ import { StartConditionDoesNotExist, } from '../errors.js'; import { + ConditionName, ConditionNode, + ElementTypes, NotExtends, + TaskInstanceState, + TaskName, WorkItemInstance, WorkflowActivities, - WorkflowAndWorkItemTypes, WorkflowBuilderDefinition, WorkflowContextSym, + WorkflowId, WorkflowInstance, WorkflowOnCancelPayload, WorkflowOnCompletePayload, @@ -170,24 +174,41 @@ export type WorkflowBuilderMetadata = T extends WorkflowBuilder< ? M : never; -export type WorkflowBuilderWorkflowAndWorkItemTypes = - T extends WorkflowBuilder< - any, - any, - any, - any, - any, - any, - any, - any, - any, - any, - any, - infer WAWIT, - any - > - ? WAWIT - : never; +export type WorkflowBuilderElementTypes = T extends WorkflowBuilder< + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + infer WAWIT, + any +> + ? WAWIT + : never; + +export type WorkflowBuilderTaskName = T extends WorkflowBuilder< + any, + any, + any, + any, + infer TN, + any, + any, + any, + any, + any, + any, + any, + any +> + ? TN + : never; interface WorkflowActivityMetadata { input: I; @@ -207,9 +228,11 @@ export class WorkflowBuilder< WBConnectedTasks = never, WBConnectedConditions = never, WBMetadata = { [WorkflowContextSym]: WBContext }, - WBWorkflowAndWorkItemTypes extends WorkflowAndWorkItemTypes = { + WBElementTypes extends ElementTypes = { workflow: WorkflowInstance; workItem: never; + condition: never; + task: never; }, WBParentContext = never > { @@ -254,7 +277,7 @@ export class WorkflowBuilder< WBConnectedTasks, WBConnectedConditions, WBMetadata, - WBWorkflowAndWorkItemTypes, + WBElementTypes, PC > { return this; @@ -287,7 +310,7 @@ export class WorkflowBuilder< >; } >, - WBWorkflowAndWorkItemTypes, + WBElementTypes, WBParentContext > { this.activities.onStart = f; @@ -320,7 +343,7 @@ export class WorkflowBuilder< >; } >, - WBWorkflowAndWorkItemTypes, + WBElementTypes, WBParentContext > { this.activities.onComplete = f; @@ -354,7 +377,7 @@ export class WorkflowBuilder< >; } >, - WBWorkflowAndWorkItemTypes, + WBElementTypes, WBParentContext > { this.activities.onFail = f; @@ -388,7 +411,7 @@ export class WorkflowBuilder< >; } >, - WBWorkflowAndWorkItemTypes, + WBElementTypes, WBParentContext > { this.activities.onCancel = f; @@ -409,7 +432,19 @@ export class WorkflowBuilder< WBConnectedTasks, WBConnectedConditions, WBMetadata, - WBWorkflowAndWorkItemTypes, + { + workflow: WBElementTypes['workflow']; + workItem: WBElementTypes['workItem']; + condition: + | WBElementTypes['condition'] + | { + name: CN & ConditionName; + workflowName: WName; + workflowId: WorkflowId; + marking: number; + }; + task: WBElementTypes['task']; + }, WBParentContext > { return this.addConditionUnsafe(conditionName); @@ -429,7 +464,19 @@ export class WorkflowBuilder< WBConnectedTasks, WBConnectedConditions, WBMetadata, - WBWorkflowAndWorkItemTypes, + { + workflow: WBElementTypes['workflow']; + workItem: WBElementTypes['workItem']; + condition: + | WBElementTypes['condition'] + | { + name: CN & ConditionName; + workflowName: WName; + workflowId: WorkflowId; + marking: number; + }; + task: WBElementTypes['task']; + }, WBParentContext > { this.definition.startCondition = conditionName; @@ -450,7 +497,19 @@ export class WorkflowBuilder< WBConnectedTasks, WBConnectedConditions, WBMetadata, - WBWorkflowAndWorkItemTypes, + { + workflow: WBElementTypes['workflow']; + workItem: WBElementTypes['workItem']; + condition: + | WBElementTypes['condition'] + | { + name: CN & ConditionName; + workflowName: WName; + workflowId: WorkflowId; + marking: number; + }; + task: WBElementTypes['task']; + }, WBParentContext > { this.definition.endCondition = conditionName; @@ -483,10 +542,20 @@ export class WorkflowBuilder< } >, { - workflow: WBWorkflowAndWorkItemTypes['workflow']; + workflow: WBElementTypes['workflow']; workItem: - | WBWorkflowAndWorkItemTypes['workItem'] + | WBElementTypes['workItem'] | WorkItemInstance, WName, TN>; + condition: WBElementTypes['condition']; + task: + | WBElementTypes['task'] + | { + name: TN & TaskName; + workflowName: WName; + workflowId: WorkflowId; + generation: number; + state: TaskInstanceState; + }; }, WBParentContext >; @@ -520,10 +589,20 @@ export class WorkflowBuilder< } >, { - workflow: WBWorkflowAndWorkItemTypes['workflow']; + workflow: WBElementTypes['workflow']; workItem: - | WBWorkflowAndWorkItemTypes['workItem'] + | WBElementTypes['workItem'] | WorkItemInstance>, WName, TN>; + condition: WBElementTypes['condition']; + task: + | WBElementTypes['task'] + | { + name: TN & TaskName; + workflowName: WName; + workflowId: WorkflowId; + generation: number; + state: TaskInstanceState; + }; }, WBParentContext >; @@ -546,10 +625,20 @@ export class WorkflowBuilder< } >, { - workflow: WBWorkflowAndWorkItemTypes['workflow']; + workflow: WBElementTypes['workflow']; workItem: - | WBWorkflowAndWorkItemTypes['workItem'] + | WBElementTypes['workItem'] | WorkItemInstance; + condition: WBElementTypes['condition']; + task: + | WBElementTypes['task'] + | { + name: TN & TaskName; + workflowName: WName; + workflowId: WorkflowId; + generation: number; + state: TaskInstanceState; + }; }, WBParentContext >; @@ -597,11 +686,24 @@ export class WorkflowBuilder< }, { workflow: - | WBWorkflowAndWorkItemTypes['workflow'] - | CTB.CompositeTaskWorkflowAndWorkItemTypes['workflow']; + | WBElementTypes['workflow'] + | CTB.CompositeTaskElementTypes['workflow']; workItem: - | WBWorkflowAndWorkItemTypes['workItem'] - | CTB.CompositeTaskWorkflowAndWorkItemTypes['workItem']; + | WBElementTypes['workItem'] + | CTB.CompositeTaskElementTypes['workItem']; + condition: + | WBElementTypes['condition'] + | CTB.CompositeTaskElementTypes['condition']; + task: + | WBElementTypes['task'] + | { + name: TN & TaskName; + workflowName: WName; + workflowId: WorkflowId; + generation: number; + state: TaskInstanceState; + } + | CTB.CompositeTaskElementTypes['task']; }, WBParentContext >; @@ -634,11 +736,24 @@ export class WorkflowBuilder< }, { workflow: - | WBWorkflowAndWorkItemTypes['workflow'] - | CTB.CompositeTaskWorkflowAndWorkItemTypes>['workflow']; + | WBElementTypes['workflow'] + | CTB.CompositeTaskElementTypes>['workflow']; workItem: - | WBWorkflowAndWorkItemTypes['workItem'] - | CTB.CompositeTaskWorkflowAndWorkItemTypes>['workItem']; + | WBElementTypes['workItem'] + | CTB.CompositeTaskElementTypes>['workItem']; + condition: + | WBElementTypes['condition'] + | CTB.CompositeTaskElementTypes>['condition']; + task: + | WBElementTypes['task'] + | { + name: TN & TaskName; + workflowName: WName; + workflowId: WorkflowId; + generation: number; + state: TaskInstanceState; + } + | CTB.CompositeTaskElementTypes>['task']; }, WBParentContext >; @@ -678,7 +793,7 @@ export class WorkflowBuilder< WBConnectedTasks, WBConnectedConditions, WBMetadata, - WBWorkflowAndWorkItemTypes, + WBElementTypes, WBParentContext > { this.definition.cancellationRegions[taskName] = toCancel; @@ -702,7 +817,7 @@ export class WorkflowBuilder< WBConnectedTasks, WBConnectedConditions | CN, WBMetadata, - WBWorkflowAndWorkItemTypes, + WBElementTypes, WBParentContext > { this.definition.flows.conditions[conditionName] = builder( @@ -737,7 +852,7 @@ export class WorkflowBuilder< WBConnectedTasks | TN, WBConnectedConditions, WBMetadata, - WBWorkflowAndWorkItemTypes, + WBElementTypes, WBParentContext >; @@ -758,7 +873,7 @@ export class WorkflowBuilder< WBConnectedTasks | TN, WBConnectedConditions, WBMetadata, - WBWorkflowAndWorkItemTypes, + WBElementTypes, WBParentContext >; @@ -799,7 +914,7 @@ export class WorkflowBuilder< E, WBContext, WBMetadata, - WBWorkflowAndWorkItemTypes + WBElementTypes >(name, activities as unknown as WorkflowActivities); for (const [taskName, taskBuilder] of Object.entries(definition.tasks)) { diff --git a/src/elements/Workflow.ts b/src/elements/Workflow.ts index b48402c..67f223a 100644 --- a/src/elements/Workflow.ts +++ b/src/elements/Workflow.ts @@ -19,10 +19,10 @@ import { } from '../errors.js'; import { ConditionName, + ElementTypes, ExecutionContext, TaskName, WorkflowActivities, - WorkflowAndWorkItemTypes, WorkflowId, WorkflowInstanceParent, finalWorkflowInstanceStates, @@ -46,7 +46,7 @@ export class Workflow< _E = never, Context = unknown, _WorkflowMetadata = object, - _WorkflowAndWorkItemInstances = WorkflowAndWorkItemTypes + _WorkflowAndWorkItemInstances = ElementTypes > { readonly tasks: Record = {}; readonly conditions: Record = {}; diff --git a/src/index.ts b/src/index.ts index c6a1a58..d03f273 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,26 @@ +import { Get, Simplify } from 'type-fest'; + +import type { WorkflowBuilderElementTypes } from './builder/WorkflowBuilder.js'; + export * as Builder from './builder.js'; export * as Service from './Service.js'; export * as TaskBuilder from './builder/TaskBuilder.js'; export * from './types.js'; export * from './errors.js'; + +export type WorkflowBuilderWorkflow = Simplify< + Get, 'workflow'> +>; + +export type WorkflowBuilderWorkItem = Simplify< + Get, 'workItem'> +>; + +export type WorkflowBuilderExplicitCondition = Simplify< + Get, 'condition'> +>; + +export type WorkflowBuilderTask = Simplify< + Get, 'task'> +>; diff --git a/src/types.ts b/src/types.ts index cfc25d6..7029afa 100644 --- a/src/types.ts +++ b/src/types.ts @@ -487,10 +487,11 @@ interface WorkflowState { export type Store = Record; export interface StorePersistableState< W extends WorkflowInstance = WorkflowInstance, - WI extends WorkItemInstance = WorkItemInstance + WI extends WorkItemInstance = WorkItemInstance, + T extends TaskInstance = TaskInstance > { workflows: W[]; - tasks: TaskInstance[]; + tasks: T[]; conditions: ConditionInstance[]; workItems: WI[]; } @@ -579,13 +580,14 @@ export type ShouldCompositeTaskFailFn< export type StateChange< W extends WorkflowInstance = WorkflowInstance, - WI extends WorkItemInstance = WorkItemInstance + WI extends WorkItemInstance = WorkItemInstance, + T extends TaskInstance = TaskInstance > = | { type: 'WORKFLOW_INITIALIZED'; workflow: W } | { type: 'WORKFLOW_STATE_UPDATED'; workflow: W } | { type: 'WORKFLOW_CONTEXT_UPDATED'; workflow: W } - | { type: 'TASK_INITIALIZED'; task: TaskInstance } - | { type: 'TASK_STATE_UPDATED'; task: TaskInstance } + | { type: 'TASK_INITIALIZED'; task: T } + | { type: 'TASK_STATE_UPDATED'; task: T } | { type: 'CONDITION_MARKING_UPDATED'; condition: ConditionInstance } | { type: 'CONDITION_INITIALIZED'; condition: ConditionInstance } | { type: 'WORK_ITEM_INITIALIZED'; workItem: WI } @@ -594,10 +596,11 @@ export type StateChange< export interface StateChangeItem< W extends WorkflowInstance = WorkflowInstance, - WI extends WorkItemInstance = WorkItemInstance + WI extends WorkItemInstance = WorkItemInstance, + T extends TaskInstance = TaskInstance > { - change: StateChange; - getState: () => StorePersistableState; + change: StateChange; + getState: () => StorePersistableState; } export interface StateChangeLogger { log: (item: StateChangeItem) => void; @@ -606,12 +609,15 @@ export interface StateChangeLogger { export type OnStateChangeFn< W extends WorkflowInstance = WorkflowInstance, - WI extends WorkItemInstance = WorkItemInstance -> = (changes: StateChangeItem[]) => Effect.Effect; + WI extends WorkItemInstance = WorkItemInstance, + T extends TaskInstance = TaskInstance +> = (changes: StateChangeItem[]) => Effect.Effect; -export interface WorkflowAndWorkItemTypes { +export interface ElementTypes { workflow: WorkflowInstance; workItem: WorkItemInstance; + task: TaskInstance; + condition: ConditionInstance; } export interface DefaultWorkflowActivityPayload {