bazis 0.133.0 → 0.135.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/access/contracts/References.ts +2 -0
- package/core/agent/AgentToolExecutor.ts +5 -0
- package/core/agent/Tool.contract.ts +2 -2
- package/core/agent/metadata.ts +11 -0
- package/core/infra/connectors/codex/CodexAppServerClient.ts +1 -1
- package/core/scripts/di-generate.ts +8 -0
- package/core/tools/StandardTools.module.ts +14 -0
- package/core/tools/generated/deps.ts +10 -0
- package/core/tools/index.ts +8 -0
- package/core/tools/orm/OrmEntity.references.ts +75 -0
- package/core/tools/orm/ormEntityTools.ts +423 -0
- package/core/workflow/contracts/WorkflowError.ts +2 -1
- package/core/workflow/contracts/WorkflowPartitions.ts +29 -0
- package/core/workflow/contracts/WorkflowProcessUsage.ts +8 -0
- package/core/workflow/definitions_module/WorkflowDefinitions.module.ts +9 -2
- package/core/workflow/definitions_module/access/Definitions.permissions.ts +4 -2
- package/core/workflow/definitions_module/access/ProcessPartition.lookup.ts +27 -0
- package/core/workflow/definitions_module/code/CodeProcessPublisher.ts +13 -1
- package/core/workflow/definitions_module/code/inspectProcesses.ts +15 -4
- package/core/workflow/definitions_module/events/Definitions.events.ts +1 -1
- package/core/workflow/definitions_module/http/Processes.controller.ts +19 -4
- package/core/workflow/definitions_module/services/IWorkflowDefinitions.service.ts +31 -0
- package/core/workflow/definitions_module/services/WorkflowDefinitions.service.ts +80 -6
- package/core/workflow/generated/deps.ts +13 -4
- package/core/workflow/index.ts +5 -0
- package/core/workflow/internal/WorkflowReferences.ts +69 -0
- package/core/workflow/runtime_module/WorkflowRuntime.module.ts +5 -0
- package/core/workflow/runtime_module/access/Runtime.permissions.ts +1 -1
- package/core/workflow/runtime_module/background/WorkflowRetention.ts +15 -11
- package/core/workflow/runtime_module/events/Runtime.events.ts +7 -0
- package/core/workflow/runtime_module/http/Instances.controller.ts +7 -2
- package/core/workflow/runtime_module/internal/ChildCalls.ts +1 -0
- package/core/workflow/runtime_module/internal/EventDelivery.ts +234 -0
- package/core/workflow/runtime_module/internal/RunLimits.ts +16 -5
- package/core/workflow/runtime_module/internal/RuntimeProcessUsage.ts +13 -0
- package/core/workflow/runtime_module/internal/Schedules.ts +97 -30
- package/core/workflow/runtime_module/internal/ToolStep.ts +16 -2
- package/core/workflow/runtime_module/internal/WorkflowEngine.ts +48 -9
- package/core/workflow/runtime_module/internal/WorkflowJobs.ts +7 -0
- package/core/workflow/runtime_module/model/WfJob.model.ts +7 -6
- package/core/workflow/runtime_module/services/IWorkflowRuntime.service.ts +34 -1
- package/core/workflow/runtime_module/services/WorkflowRuntime.service.ts +40 -41
- package/core/workflow/tasks_module/events/TaskEvents.ts +17 -1
- package/core/workflow/tasks_module/services/IWorkflowTasks.service.ts +2 -0
- package/core/workflow/tasks_module/services/WorkflowTasks.service.ts +2 -1
- package/library/workflow/cron.ts +103 -24
- package/library/workflow/index.ts +3 -2
- package/library/workflow/nodeKinds.ts +64 -9
- package/library/workflow/paths.ts +2 -2
- package/library/workflow/references.ts +106 -0
- package/library/workflow/validateProcess.ts +13 -0
- package/package.json +2 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { WorkflowPortContext } from "./WorkflowExtensions";
|
|
2
|
+
|
|
3
|
+
/** A partition a process is connected to. */
|
|
4
|
+
export interface ProcessPartition {
|
|
5
|
+
/** `null`: the process runs without a partition. */
|
|
6
|
+
readonly partition: string | null;
|
|
7
|
+
/** An IANA time zone for the schedules of this partition; a time zone on the node goes first. */
|
|
8
|
+
readonly timezone?: string;
|
|
9
|
+
/** A process that is switched off here takes no events and no scheduled starts. */
|
|
10
|
+
readonly enabled: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Where a process works (WORKFLOW-002 §6): tenants, spaces, organizations. An
|
|
15
|
+
* event starts a process only in a partition listed here, a schedule with
|
|
16
|
+
* `partitions: "all"` runs in every enabled one, and a process connected to a
|
|
17
|
+
* partition cannot be deleted. The application registers its implementation in
|
|
18
|
+
* any module.
|
|
19
|
+
*/
|
|
20
|
+
export abstract class WorkflowPartitions {
|
|
21
|
+
abstract of(processKey: string, context: WorkflowPortContext): readonly ProcessPartition[] | Promise<readonly ProcessPartition[]>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** By default a process has one place to work: no partition. */
|
|
25
|
+
export class DefaultWorkflowPartitions extends WorkflowPartitions {
|
|
26
|
+
of(): readonly ProcessPartition[] {
|
|
27
|
+
return [{ partition: null, enabled: true }];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the catalog asks before it deletes a process. Runtime answers: the catalog
|
|
3
|
+
* knows nothing of instances, and without Runtime there are none.
|
|
4
|
+
*/
|
|
5
|
+
export abstract class WorkflowProcessUsage {
|
|
6
|
+
/** How many `pending`, `running` and `failed` instances the process has. */
|
|
7
|
+
abstract liveInstances(processKey: string): Promise<number>;
|
|
8
|
+
}
|
|
@@ -3,13 +3,16 @@ import { HOSTED_SERVICE, Module, scoped, singleton } from "../../di";
|
|
|
3
3
|
import { SystemWorkflowClock, WorkflowClock } from "../contracts/WorkflowClock";
|
|
4
4
|
import { workflowConfig } from "../contracts/Workflow.config";
|
|
5
5
|
import { DefaultWorkflowExtensions, WorkflowExtensions } from "../contracts/WorkflowExtensions";
|
|
6
|
+
import { DefaultWorkflowPartitions, WorkflowPartitions } from "../contracts/WorkflowPartitions";
|
|
6
7
|
import { WorkflowEvents } from "../internal/WorkflowEvents";
|
|
7
8
|
import { WorkflowLanguages } from "../internal/WorkflowLanguages";
|
|
9
|
+
import { WorkflowReferences } from "../internal/WorkflowReferences";
|
|
8
10
|
import { WorkflowTools } from "../internal/WorkflowTools";
|
|
9
11
|
import { definitionsPermissions } from "./access/Definitions.permissions";
|
|
10
12
|
import { FolderReferences } from "./access/Folder.references";
|
|
11
13
|
import { ProcessReferences } from "./access/Process.references";
|
|
12
14
|
import { ProcessFolderLookup } from "./access/ProcessFolder.lookup";
|
|
15
|
+
import { ProcessPartitionLookup } from "./access/ProcessPartition.lookup";
|
|
13
16
|
import { CatalogImport } from "./code/CatalogImport";
|
|
14
17
|
import { CodeProcessCatalog } from "./code/CodeProcessCatalog";
|
|
15
18
|
import { CodeProcessPublisher } from "./code/CodeProcessPublisher";
|
|
@@ -23,7 +26,8 @@ import { WorkflowDefinitions } from "./services/WorkflowDefinitions.service";
|
|
|
23
26
|
/**
|
|
24
27
|
* The process catalog: drafts and published versions, and the processes
|
|
25
28
|
* declared in code ([passport](MODULE.md)). The application checks its own
|
|
26
|
-
* `extensions` by registering its `WorkflowExtensions
|
|
29
|
+
* `extensions` by registering its `WorkflowExtensions` and says where processes
|
|
30
|
+
* work by registering its `WorkflowPartitions`.
|
|
27
31
|
*/
|
|
28
32
|
@Module({
|
|
29
33
|
imports: [AccessModule],
|
|
@@ -37,15 +41,18 @@ import { WorkflowDefinitions } from "./services/WorkflowDefinitions.service";
|
|
|
37
41
|
singleton(CodeProcessCatalog),
|
|
38
42
|
singleton(WorkflowLanguages),
|
|
39
43
|
singleton(WorkflowExtensions, DefaultWorkflowExtensions),
|
|
44
|
+
singleton(WorkflowPartitions, DefaultWorkflowPartitions),
|
|
40
45
|
scoped(WorkflowEvents),
|
|
46
|
+
scoped(WorkflowReferences),
|
|
41
47
|
scoped(CatalogImport),
|
|
42
48
|
scoped(IWorkflowDefinitions, WorkflowDefinitions),
|
|
43
49
|
scoped(ProcessReferences),
|
|
44
50
|
scoped(FolderReferences),
|
|
45
51
|
scoped(ProcessFolderLookup),
|
|
52
|
+
scoped(ProcessPartitionLookup),
|
|
46
53
|
singleton(HOSTED_SERVICE, CodeProcessPublisher),
|
|
47
54
|
],
|
|
48
55
|
controllers: [ProcessesController],
|
|
49
|
-
exports: [IWorkflowDefinitions, WorkflowTools, WorkflowClock, WorkflowEvents, WorkflowLanguages, WorkflowExtensions, ProcessFolderLookup],
|
|
56
|
+
exports: [IWorkflowDefinitions, WorkflowReferences, WorkflowTools, WorkflowClock, WorkflowEvents, WorkflowLanguages, WorkflowExtensions, WorkflowPartitions, ProcessFolderLookup],
|
|
50
57
|
})
|
|
51
58
|
export class WorkflowDefinitionsModule {}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { definePermissions } from "../../../access";
|
|
2
|
+
import { ProcessPartitionLookup } from "./ProcessPartition.lookup";
|
|
2
3
|
|
|
3
4
|
const process = { ref: "workflow.process", column: "key" };
|
|
4
5
|
const folder = { ref: "workflow.folder", column: "folder" };
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* The rights of the process catalog (WORKFLOW-002 §6.2). A process is one per
|
|
8
|
-
* application
|
|
9
|
-
*
|
|
9
|
+
* application: only reading it has partitions, those `WorkflowPartitions`
|
|
10
|
+
* connects it to.
|
|
10
11
|
*/
|
|
11
12
|
export const definitionsPermissions = definePermissions({
|
|
12
13
|
"workflow.processes.read": {
|
|
13
14
|
title: { en: "See processes", ru: "Видеть процессы" },
|
|
15
|
+
scope: { lookup: ProcessPartitionLookup },
|
|
14
16
|
on: { process, folder },
|
|
15
17
|
},
|
|
16
18
|
"workflow.processes.manage": {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AttributeLookup, type AccessValue, type LookupColumn } from "../../../access";
|
|
2
|
+
import type { ServiceProvider } from "../../../di";
|
|
3
|
+
import { WorkflowPartitions } from "../../contracts/WorkflowPartitions";
|
|
4
|
+
import type { WorkflowLanguages } from "../../internal/WorkflowLanguages";
|
|
5
|
+
import type { DefinitionsDbContext } from "../model/Definitions.dbContext";
|
|
6
|
+
|
|
7
|
+
/** The partitions of a process are not a column: partition → the keys of the processes connected to it (WORKFLOW-002 §6.2). */
|
|
8
|
+
export class ProcessPartitionLookup extends AttributeLookup {
|
|
9
|
+
constructor(
|
|
10
|
+
private readonly db: DefinitionsDbContext,
|
|
11
|
+
private readonly languages: WorkflowLanguages,
|
|
12
|
+
private readonly services: ServiceProvider,
|
|
13
|
+
) {
|
|
14
|
+
super();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async toColumn(values: readonly AccessValue[]): Promise<LookupColumn> {
|
|
18
|
+
const port = this.services.resolve(WorkflowPartitions);
|
|
19
|
+
const rows = await this.db.processes.asNoTracking().select((p) => ({ key: p.key })).toList();
|
|
20
|
+
const keys: string[] = [];
|
|
21
|
+
for (const { key } of rows) {
|
|
22
|
+
const partitions = await port.of(key, { partition: null, language: this.languages.default, actor: null });
|
|
23
|
+
if (partitions.some((item) => item.enabled && values.includes(item.partition))) keys.push(key);
|
|
24
|
+
}
|
|
25
|
+
return { column: "key", in: keys };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { markConfigurationError, type ServiceProvider } from "../../../di";
|
|
2
2
|
import type { HostedService } from "../../../di/extensions/hosted-service";
|
|
3
3
|
import { LOGGER } from "../../../kernel";
|
|
4
|
+
import { WorkflowReferences } from "../../internal/WorkflowReferences";
|
|
4
5
|
import { WorkflowTools } from "../../internal/WorkflowTools";
|
|
5
6
|
import { IWorkflowDefinitions } from "../services/IWorkflowDefinitions.service";
|
|
6
7
|
import { CatalogImport } from "./CatalogImport";
|
|
@@ -12,7 +13,9 @@ import { definitionProblems, WorkflowSetupError } from "./codeProcesses";
|
|
|
12
13
|
* (WORKFLOW-002 §9), then publishes the processes of `@Module({ processes })`
|
|
13
14
|
* (WORKFLOW-001 §14). A document with an unknown Tool or process, or an `extensions`
|
|
14
15
|
* namespace nobody checks, stops the start with every finding of every process; the same
|
|
15
|
-
* document again gives no new version.
|
|
16
|
+
* document again gives no new version. So does a reference kind no module owns, in a Tool
|
|
17
|
+
* or a document. A value that does not exist only warns: it may be data that is yet to come,
|
|
18
|
+
* and the step then fails with `ref_not_found`.
|
|
16
19
|
*/
|
|
17
20
|
export class CodeProcessPublisher implements HostedService {
|
|
18
21
|
readonly diagnosticName = "workflow:processes";
|
|
@@ -25,6 +28,11 @@ export class CodeProcessPublisher implements HostedService {
|
|
|
25
28
|
try {
|
|
26
29
|
const imported = await scope.resolve(CatalogImport).run();
|
|
27
30
|
if (imported > 0) logger?.info("workflow catalog brought over from the old store", { processes: imported });
|
|
31
|
+
const references = scope.resolve(WorkflowReferences);
|
|
32
|
+
const unowned = references.unownedToolKinds();
|
|
33
|
+
if (unowned.length > 0) {
|
|
34
|
+
throw markConfigurationError(new WorkflowSetupError(`Tools refer to kinds no module owns:\n${unowned.map(({ tool, kind }) => ` - ${tool}: ${kind}${kind.startsWith("orm.") ? " (import StandardToolsModule from bazis/core/tools)" : " (declare it in @Module({ references }))"}`).join("\n")}`));
|
|
35
|
+
}
|
|
28
36
|
const entries = this.services.resolve(CodeProcessCatalog).list();
|
|
29
37
|
if (entries.length === 0) return;
|
|
30
38
|
const tools = this.services.resolve(WorkflowTools);
|
|
@@ -35,6 +43,10 @@ export class CodeProcessPublisher implements HostedService {
|
|
|
35
43
|
const found = [...definitionProblems(process, (name) => tools.has(name))];
|
|
36
44
|
for (const issue of await definitions.validate(process.document, { processes })) {
|
|
37
45
|
if (issue.severity === "error" && (issue.code === "extension_unknown" || issue.code === "extension_invalid" || issue.code === "unknown_process")) found.push(`${issue.message} (${issue.code})`);
|
|
46
|
+
else if (issue.code === "broken_ref") {
|
|
47
|
+
if (issue.message.startsWith("no module owns")) found.push(`${issue.message} (${issue.code})`);
|
|
48
|
+
else logger?.warn("workflow process refers to what does not exist", { process: process.key, node: issue.node, message: issue.message });
|
|
49
|
+
}
|
|
38
50
|
}
|
|
39
51
|
if (found.length > 0) problems.push(`${module}: process "${process.key}":\n${found.map((line) => ` - ${line}`).join("\n")}`);
|
|
40
52
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { expandModuleMetadata, type BazisModuleRef } from "../../../di";
|
|
2
|
-
import { toolMetadataOf } from "../../../agent";
|
|
3
|
-
import { validateProcess } from "../../../../library/workflow";
|
|
2
|
+
import { describeTool, toolMetadataOf } from "../../../agent";
|
|
3
|
+
import { documentReferences, schemaReferenceKinds, validateProcess } from "../../../../library/workflow";
|
|
4
4
|
import { WORKFLOW_CALLER } from "../../internal/WorkflowTools";
|
|
5
5
|
import { WorkflowDefinitionsModule } from "../WorkflowDefinitions.module";
|
|
6
6
|
import { definitionProblems, type OwnedCodeProcess } from "./codeProcesses";
|
|
@@ -28,16 +28,23 @@ export function inspectProcesses(root: BazisModuleRef): ProcessInspection {
|
|
|
28
28
|
const found: OwnedCodeProcess[] = [];
|
|
29
29
|
const errors: string[] = [];
|
|
30
30
|
const tools = new Set<string>();
|
|
31
|
+
const schemas = new Map<string, unknown>();
|
|
32
|
+
const kinds = new Set<string>();
|
|
31
33
|
const visited = new Set<BazisModuleRef>();
|
|
32
34
|
const visit = (moduleRef: BazisModuleRef): void => {
|
|
33
35
|
if (visited.has(moduleRef)) return;
|
|
34
36
|
visited.add(moduleRef);
|
|
35
37
|
const module = typeof moduleRef === "function" ? moduleRef.name || "<anonymous module>" : "<module>";
|
|
36
|
-
const fields = moduleRef as { readonly processes?: unknown; readonly tools?: unknown };
|
|
38
|
+
const fields = moduleRef as { readonly processes?: unknown; readonly tools?: unknown; readonly references?: unknown };
|
|
39
|
+
if (typeof fields.references === "object" && fields.references !== null) for (const kind of Object.keys(fields.references)) kinds.add(kind);
|
|
37
40
|
if (Array.isArray(fields.tools)) {
|
|
38
41
|
for (const target of fields.tools) {
|
|
39
42
|
const metadata = typeof target === "function" ? toolMetadataOf(target as new () => object) : undefined;
|
|
40
|
-
if (metadata?.callers.includes(WORKFLOW_CALLER))
|
|
43
|
+
if (metadata?.callers.includes(WORKFLOW_CALLER)) {
|
|
44
|
+
tools.add(metadata.name);
|
|
45
|
+
const input = describeTool({ target: target as new () => object, metadata }).input;
|
|
46
|
+
if (input?.kind === "json-schema") schemas.set(metadata.name, input.schema);
|
|
47
|
+
}
|
|
41
48
|
}
|
|
42
49
|
}
|
|
43
50
|
if (fields.processes !== undefined) {
|
|
@@ -54,6 +61,10 @@ export function inspectProcesses(root: BazisModuleRef): ProcessInspection {
|
|
|
54
61
|
if (found.length > 0 && !visited.has(WorkflowDefinitionsModule)) {
|
|
55
62
|
errors.push(`${found[0]!.module} declares processes, but the application does not import WorkflowModule (bazis/core/workflow).`);
|
|
56
63
|
}
|
|
64
|
+
// The values live in the database: `check` knows only whether someone owns their kind.
|
|
65
|
+
for (const [tool, schema] of schemas) {
|
|
66
|
+
for (const kind of schemaReferenceKinds(schema)) if (!kinds.has(kind)) errors.push(`Tool ${tool} refers to the kind ${kind}, and no module owns it.`);
|
|
67
|
+
}
|
|
57
68
|
const owners = new Map<string, string>();
|
|
58
69
|
for (const { process, module } of found) {
|
|
59
70
|
const other = owners.get(process.key);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createEventToken } from "../../../kernel";
|
|
2
2
|
import type { WorkflowActor, WorkflowRequest } from "../../contracts/types";
|
|
3
3
|
|
|
4
|
-
export type ProcessChange = "created" | "updated" | "draftSaved" | "published" | "archived" | "restored";
|
|
4
|
+
export type ProcessChange = "created" | "updated" | "draftSaved" | "published" | "archived" | "restored" | "deleted";
|
|
5
5
|
|
|
6
6
|
/** A process of the catalog changed, for the application's audit. Published after the commit. */
|
|
7
7
|
export interface WorkflowProcessChanged {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { contextOnlyController } from "../../../http/Routing/contextOnlyControllers";
|
|
2
2
|
import { can, type AccessObject } from "../../../access";
|
|
3
3
|
import type { LocalizedText } from "../../../../library/workflow";
|
|
4
|
-
import { Authorize, Controller, Created, Get, Patch, Post, Put, type HttpContext } from "../../../http";
|
|
4
|
+
import { Authorize, Controller, Created, Delete, Get, Patch, Post, Put, type HttpContext } from "../../../http";
|
|
5
5
|
import { buildListDocument } from "../../../../library/jsonapi";
|
|
6
6
|
import { body, callerOf, defaultLanguage, filterOf, listQuery, optionalInteger, optionalString, optionalText, pagingOfList, param, requiredString, withTitleText } from "../../internal/http";
|
|
7
7
|
import { WorkflowError } from "../../contracts/WorkflowError";
|
|
@@ -52,10 +52,20 @@ export class ProcessesController {
|
|
|
52
52
|
@Authorize(can("workflow.processes.read"))
|
|
53
53
|
async get(ctx: HttpContext) {
|
|
54
54
|
const key = param(ctx, "key");
|
|
55
|
-
const { language } = await callerOf(ctx, "workflow.processes.read", await this.
|
|
55
|
+
const { language } = await callerOf(ctx, "workflow.processes.read", await this.readObjectOf(key));
|
|
56
56
|
return withTitleText(await this.definitions.get(key), language, defaultLanguage(ctx));
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/** An archived process without unfinished instances and partitions (WORKFLOW-002 §4.3). */
|
|
60
|
+
@Delete("processes/:key")
|
|
61
|
+
@Authorize(can("workflow.processes.manage"))
|
|
62
|
+
async remove(ctx: HttpContext) {
|
|
63
|
+
const key = param(ctx, "key");
|
|
64
|
+
const { actor, request } = await callerOf(ctx, "workflow.processes.manage", await this.objectOf(key));
|
|
65
|
+
await this.definitions.remove(key, actor, { request });
|
|
66
|
+
ctx.res.status(204);
|
|
67
|
+
}
|
|
68
|
+
|
|
59
69
|
@Patch("processes/:key")
|
|
60
70
|
@Authorize(can("workflow.processes.manage"))
|
|
61
71
|
async update(ctx: HttpContext) {
|
|
@@ -102,7 +112,7 @@ export class ProcessesController {
|
|
|
102
112
|
@Authorize(can("workflow.processes.read"))
|
|
103
113
|
async versions(ctx: HttpContext) {
|
|
104
114
|
const key = param(ctx, "key");
|
|
105
|
-
await callerOf(ctx, "workflow.processes.read", await this.
|
|
115
|
+
await callerOf(ctx, "workflow.processes.read", await this.readObjectOf(key));
|
|
106
116
|
return { data: await this.definitions.versions(key) };
|
|
107
117
|
}
|
|
108
118
|
|
|
@@ -110,7 +120,7 @@ export class ProcessesController {
|
|
|
110
120
|
@Authorize(can("workflow.processes.read"))
|
|
111
121
|
async version(ctx: HttpContext) {
|
|
112
122
|
const key = param(ctx, "key");
|
|
113
|
-
await callerOf(ctx, "workflow.processes.read", await this.
|
|
123
|
+
await callerOf(ctx, "workflow.processes.read", await this.readObjectOf(key));
|
|
114
124
|
const version = optionalInteger(param(ctx, "version"), "version");
|
|
115
125
|
if (version === undefined) throw new WorkflowError("invalid_input", "version must be an integer");
|
|
116
126
|
return await this.definitions.version(key, version);
|
|
@@ -144,6 +154,11 @@ export class ProcessesController {
|
|
|
144
154
|
return { process: key, folder: await this.definitions.folderOf(key) };
|
|
145
155
|
}
|
|
146
156
|
|
|
157
|
+
/** Reading a process is allowed by the partitions it works in. */
|
|
158
|
+
private async readObjectOf(key: string): Promise<AccessObject> {
|
|
159
|
+
return { ...await this.objectOf(key), scope: await this.definitions.partitionsOf(key) };
|
|
160
|
+
}
|
|
161
|
+
|
|
147
162
|
private localized(items: readonly ProcessSummary[], language: string, ctx: HttpContext) {
|
|
148
163
|
return items.map((item) => withTitleText(item, language, defaultLanguage(ctx)));
|
|
149
164
|
}
|
|
@@ -92,6 +92,24 @@ export interface SavedDraft {
|
|
|
92
92
|
readonly draftUpdatedAt: Date;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
export interface ProcessReferenceQuery {
|
|
96
|
+
readonly kind: string;
|
|
97
|
+
readonly id: string;
|
|
98
|
+
/** The area of the value: the table of a field. Without it any area goes. */
|
|
99
|
+
readonly within?: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** A process that refers to a value, and where. */
|
|
103
|
+
export interface ProcessReference {
|
|
104
|
+
readonly processKey: string;
|
|
105
|
+
readonly version: number;
|
|
106
|
+
readonly node?: string;
|
|
107
|
+
readonly variable?: string;
|
|
108
|
+
readonly within?: string;
|
|
109
|
+
/** Where in the input of the step: `/values/status`. */
|
|
110
|
+
readonly path: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
95
113
|
/**
|
|
96
114
|
* The process catalog: drafts and immutable published versions
|
|
97
115
|
* (WORKFLOW-001 §3). Errors are {@link WorkflowError}: `not_found`, `conflict`,
|
|
@@ -102,6 +120,8 @@ export abstract class IWorkflowDefinitions {
|
|
|
102
120
|
abstract get(key: string): Promise<ProcessDetails>;
|
|
103
121
|
/** The folder of a process, for a check of rights; `null` also for a process that does not exist. */
|
|
104
122
|
abstract folderOf(key: string): Promise<string | null>;
|
|
123
|
+
/** The partitions a process works in, for a check of rights. */
|
|
124
|
+
abstract partitionsOf(key: string): Promise<readonly (string | null)[]>;
|
|
105
125
|
/** Every finding of a document, with the application's `extensions` checks; nothing is stored. */
|
|
106
126
|
abstract validate(document: unknown, options?: ValidateOptions): Promise<readonly ProcessIssue[]>;
|
|
107
127
|
/** What a designer builds its forms from: node kinds, functions, paths and Tools. */
|
|
@@ -109,6 +129,12 @@ export abstract class IWorkflowDefinitions {
|
|
|
109
129
|
abstract create(process: CreateProcess, actor: WorkflowActor, options?: WorkflowAuditOptions): Promise<ProcessDetails>;
|
|
110
130
|
/** A process declared in code takes only `archived`; other fields give `conflict`. */
|
|
111
131
|
abstract update(key: string, changes: UpdateProcess, actor: WorkflowActor, options?: WorkflowAuditOptions): Promise<ProcessDetails>;
|
|
132
|
+
/**
|
|
133
|
+
* Deletes an archived process with its versions: `wrong_status` when it is not
|
|
134
|
+
* archived, `conflict` when it is declared in code, `in_use` when it has unfinished
|
|
135
|
+
* instances or partitions. Finished instances and their history stay.
|
|
136
|
+
*/
|
|
137
|
+
abstract remove(key: string, actor: WorkflowActor, options?: WorkflowAuditOptions): Promise<void>;
|
|
112
138
|
/** Stores the draft even with errors; `conflict` for a process declared in code and when `expected` is out of date. */
|
|
113
139
|
abstract saveDraft(key: string, document: unknown, actor: WorkflowActor, options?: SaveDraftOptions): Promise<SavedDraft>;
|
|
114
140
|
/**
|
|
@@ -124,6 +150,11 @@ export abstract class IWorkflowDefinitions {
|
|
|
124
150
|
abstract published(): Promise<readonly VersionDetails[]>;
|
|
125
151
|
/** A version by id, for the engine; `undefined` if there is none. */
|
|
126
152
|
abstract versionById(id: string): Promise<VersionDetails | undefined>;
|
|
153
|
+
/**
|
|
154
|
+
* Who refers to a value (WORKFLOW-002 §6.3), by the latest published versions: the
|
|
155
|
+
* application forbids or warns before it removes a field or a table.
|
|
156
|
+
*/
|
|
157
|
+
abstract referencing(reference: ProcessReferenceQuery): Promise<readonly ProcessReference[]>;
|
|
127
158
|
/** Processes with a retention period: what the retention service deletes. */
|
|
128
159
|
abstract retentionPolicies(): Promise<readonly { readonly key: string; readonly retentionDays: number }[]>;
|
|
129
160
|
/** The Tools a service task may call, with their input and output schemas. */
|
|
@@ -2,15 +2,18 @@ import { grantsToWhere } from "../../../access";
|
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { paginate, UniqueViolationError } from "../../../orm";
|
|
4
4
|
import type { AgentToolContract } from "../../../agent";
|
|
5
|
-
import { allTexts, checkLocalizedText, emptyProcess, hasErrors, processPalette, validateProcess, type LocalizedText, type ProcessDocument, type ProcessIssue, type ProcessPalette } from "../../../../library/workflow";
|
|
5
|
+
import { allTexts, checkLocalizedText, emptyProcess, hasErrors, processPalette, validateProcess, type DocumentReference, type LocalizedText, type ProcessDocument, type ProcessIssue, type ProcessPalette } from "../../../../library/workflow";
|
|
6
6
|
import type { ServiceProvider } from "../../../di";
|
|
7
7
|
import { isUuid, pageQueryOf, type WorkflowActor, type WorkflowAuditOptions, type WorkflowPage } from "../../contracts/types";
|
|
8
8
|
import type { WorkflowClock } from "../../contracts/WorkflowClock";
|
|
9
9
|
import { WorkflowError } from "../../contracts/WorkflowError";
|
|
10
10
|
import { WorkflowExtensions, type ExtensionTarget, type WorkflowPortContext } from "../../contracts/WorkflowExtensions";
|
|
11
|
+
import { WorkflowPartitions } from "../../contracts/WorkflowPartitions";
|
|
12
|
+
import { WorkflowProcessUsage } from "../../contracts/WorkflowProcessUsage";
|
|
11
13
|
import { canonicalJson } from "../../internal/canonicalJson";
|
|
12
14
|
import type { WorkflowEvents } from "../../internal/WorkflowEvents";
|
|
13
15
|
import type { WorkflowLanguages } from "../../internal/WorkflowLanguages";
|
|
16
|
+
import type { WorkflowReferences } from "../../internal/WorkflowReferences";
|
|
14
17
|
import type { WorkflowTools } from "../../internal/WorkflowTools";
|
|
15
18
|
import type { CodeProcessCatalog } from "../code/CodeProcessCatalog";
|
|
16
19
|
import type { OwnedCodeProcess } from "../code/codeProcesses";
|
|
@@ -23,6 +26,8 @@ import {
|
|
|
23
26
|
type CreateProcess,
|
|
24
27
|
type ProcessDetails,
|
|
25
28
|
type ProcessListQuery,
|
|
29
|
+
type ProcessReference,
|
|
30
|
+
type ProcessReferenceQuery,
|
|
26
31
|
type ProcessSummary,
|
|
27
32
|
type SavedDraft,
|
|
28
33
|
type SaveDraftOptions,
|
|
@@ -46,6 +51,7 @@ export class WorkflowDefinitions extends IWorkflowDefinitions {
|
|
|
46
51
|
private readonly clock: WorkflowClock,
|
|
47
52
|
private readonly events: WorkflowEvents,
|
|
48
53
|
private readonly languages: WorkflowLanguages,
|
|
54
|
+
private readonly references: WorkflowReferences,
|
|
49
55
|
/** The scope: the port is asked here, so that the application's own registration replaces the default. */
|
|
50
56
|
private readonly services: ServiceProvider,
|
|
51
57
|
) {
|
|
@@ -83,13 +89,22 @@ export class WorkflowDefinitions extends IWorkflowDefinitions {
|
|
|
83
89
|
return row?.folder ?? null;
|
|
84
90
|
}
|
|
85
91
|
|
|
92
|
+
async partitionsOf(key: string): Promise<readonly (string | null)[]> {
|
|
93
|
+
const partitions = await this.partitions(key, null);
|
|
94
|
+
return partitions.filter((item) => item.enabled).map((item) => item.partition);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private async partitions(key: string, actor: WorkflowActor | null) {
|
|
98
|
+
return await this.services.resolve(WorkflowPartitions).of(key, { partition: null, language: this.languages.default, actor });
|
|
99
|
+
}
|
|
100
|
+
|
|
86
101
|
async validate(document: unknown, options: ValidateOptions = {}): Promise<readonly ProcessIssue[]> {
|
|
87
102
|
const port = this.services.resolve(WorkflowExtensions);
|
|
88
103
|
const namespaces = new Set(port.namespaces());
|
|
89
104
|
const published = await this.db.processes.asNoTracking().where((p) => p.archivedAt.isNull().and(p.latestVersion.isNotNull())).select((p) => ({ key: p.key })).toList();
|
|
90
105
|
const processes = new Set([...published.map((row) => row.key), ...options.processes ?? []]);
|
|
91
106
|
const issues = validateProcess(document, { tools: (name) => this.workflowTools.has(name), processes: (key) => processes.has(key), extensions: (namespace) => namespaces.has(namespace) });
|
|
92
|
-
if (
|
|
107
|
+
if (issues.some((issue) => issue.code === "too_large" || issue.code === "schema")) return issues;
|
|
93
108
|
const context: WorkflowPortContext = { partition: null, language: options.language ?? this.languages.default, actor: options.actor ?? null };
|
|
94
109
|
const found: ProcessIssue[] = [...issues];
|
|
95
110
|
const { extensions, variables, nodes } = document as ProcessDocument;
|
|
@@ -100,9 +115,52 @@ export class WorkflowDefinitions extends IWorkflowDefinitions {
|
|
|
100
115
|
for (const message of await port.check(namespace, value, target, context)) found.push({ severity: "error", code: "extension_invalid", message: `${namespace}: ${message}`, ...target });
|
|
101
116
|
}
|
|
102
117
|
};
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
118
|
+
if (namespaces.size > 0) {
|
|
119
|
+
await checkAll(extensions, {});
|
|
120
|
+
if (Array.isArray(variables)) for (const variable of variables) await checkAll(variable?.extensions, { variable: variable?.name });
|
|
121
|
+
for (const [node, raw] of Object.entries(nodes)) await checkAll(raw?.extensions, { node });
|
|
122
|
+
}
|
|
123
|
+
found.push(...await this.brokenReferences(document as ProcessDocument, context.language));
|
|
124
|
+
return found;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** The literal references no owner knows. The processes a document calls are told above as `unknown_process`. */
|
|
128
|
+
private async brokenReferences(document: ProcessDocument, language: string): Promise<ProcessIssue[]> {
|
|
129
|
+
let references: DocumentReference[];
|
|
130
|
+
try {
|
|
131
|
+
references = this.references.of(document);
|
|
132
|
+
} catch {
|
|
133
|
+
// A document that is not whole yet: its shape has been told above.
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
const missing = await this.references.missing(references.filter((reference) => reference.kind !== "workflow.process"), { scope: null, language });
|
|
137
|
+
return missing.map((reference) => ({
|
|
138
|
+
severity: "error" as const,
|
|
139
|
+
code: "broken_ref" as const,
|
|
140
|
+
message: this.references.owned(reference.kind)
|
|
141
|
+
? `${reference.kind} ${JSON.stringify(reference.id)}${reference.within === undefined ? "" : ` in ${reference.within}`} does not exist`
|
|
142
|
+
: `no module owns the reference kind ${reference.kind}`,
|
|
143
|
+
...(reference.node === undefined ? {} : { node: reference.node }),
|
|
144
|
+
...(reference.variable === undefined ? {} : { variable: reference.variable }),
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async referencing(reference: ProcessReferenceQuery): Promise<readonly ProcessReference[]> {
|
|
149
|
+
const found: ProcessReference[] = [];
|
|
150
|
+
for (const version of await this.published()) {
|
|
151
|
+
for (const item of this.references.of(version.document)) {
|
|
152
|
+
if (item.kind !== reference.kind || item.id !== reference.id) continue;
|
|
153
|
+
if (reference.within !== undefined && item.within !== reference.within) continue;
|
|
154
|
+
found.push({
|
|
155
|
+
processKey: version.key,
|
|
156
|
+
version: version.version,
|
|
157
|
+
path: item.path,
|
|
158
|
+
...(item.node === undefined ? {} : { node: item.node }),
|
|
159
|
+
...(item.variable === undefined ? {} : { variable: item.variable }),
|
|
160
|
+
...(item.within === undefined ? {} : { within: item.within }),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
106
164
|
return found;
|
|
107
165
|
}
|
|
108
166
|
|
|
@@ -153,6 +211,19 @@ export class WorkflowDefinitions extends IWorkflowDefinitions {
|
|
|
153
211
|
return this.detailsOf(row);
|
|
154
212
|
}
|
|
155
213
|
|
|
214
|
+
async remove(key: string, actor: WorkflowActor, options: WorkflowAuditOptions = {}): Promise<void> {
|
|
215
|
+
const row = await this.process(key, false);
|
|
216
|
+
this.assertNotCode(key);
|
|
217
|
+
if (row.archivedAt === null) throw new WorkflowError("wrong_status", `Process ${key} is not archived`);
|
|
218
|
+
// An archived process starts nothing more, so what is counted here cannot grow.
|
|
219
|
+
const connected = (await this.partitions(key, actor)).filter((item) => item.partition !== null).map((item) => item.partition);
|
|
220
|
+
if (connected.length > 0) throw new WorkflowError("in_use", `Process ${key} is connected to partitions: ${connected.join(", ")}`);
|
|
221
|
+
const live = await this.services.tryResolve(WorkflowProcessUsage)?.liveInstances(key) ?? 0;
|
|
222
|
+
if (live > 0) throw new WorkflowError("in_use", `Process ${key} has ${live} unfinished instances`);
|
|
223
|
+
await this.db.processes.asNoTracking().where((p) => p.key.eq(key)).executeDelete();
|
|
224
|
+
await this.changed("deleted", key, actor, options);
|
|
225
|
+
}
|
|
226
|
+
|
|
156
227
|
async saveDraft(key: string, document: unknown, actor: WorkflowActor, options: SaveDraftOptions = {}): Promise<SavedDraft> {
|
|
157
228
|
const issues = await this.validate(document, { actor, ...(options.language === undefined ? {} : { language: options.language }) });
|
|
158
229
|
if (issues.some((issue) => issue.code === "too_large")) throw new WorkflowError("invalid_document", "The document is too large", issues);
|
|
@@ -175,12 +246,15 @@ export class WorkflowDefinitions extends IWorkflowDefinitions {
|
|
|
175
246
|
}
|
|
176
247
|
|
|
177
248
|
async publish(key: string, actor: WorkflowActor, options: WorkflowAuditOptions & Pick<ValidateOptions, "language"> = {}): Promise<VersionDetails> {
|
|
249
|
+
// Before the transaction: the owners of references and the ports read their own contexts.
|
|
250
|
+
const draft = await this.process(key, false);
|
|
251
|
+
const issues = await this.validate(draft.draft, { actor, processes: [key], ...(options.language === undefined ? {} : { language: options.language }) });
|
|
178
252
|
return await this.db.transactionScope(async (transaction) => {
|
|
179
253
|
const row = await this.db.processes.where((p) => p.key.eq(key)).forUpdate().firstOrDefault();
|
|
180
254
|
if (!row) throw notFound(key);
|
|
181
255
|
this.assertNotCode(key);
|
|
182
256
|
if (row.archivedAt !== null) throw new WorkflowError("archived", `Process ${key} is archived`);
|
|
183
|
-
|
|
257
|
+
if (canonicalJson(row.draft) !== canonicalJson(draft.draft)) throw new WorkflowError("conflict", `The draft of ${key} was saved while it was being published`);
|
|
184
258
|
if (hasErrors(issues)) throw new WorkflowError("invalid_document", `Process ${key} has errors and cannot be published`, issues);
|
|
185
259
|
const { version, created } = await this.publishDraft(row, actor);
|
|
186
260
|
if (created) transaction.afterCommit(() => this.changed("published", key, actor, options, version.version));
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
// Do not edit manually.
|
|
3
3
|
import { registerFrameworkClassDeps } from "../../di/module/autoDeps";
|
|
4
4
|
import { DbContextOptions } from "../../../library/orm/DbContextOptions";
|
|
5
|
+
import { IAccessCatalog } from "../../access/catalog/IAccessCatalog.service";
|
|
5
6
|
import { ServiceProvider } from "../../di/ServiceProvider";
|
|
6
7
|
import { EventBus } from "../../kernel/events/EventBus";
|
|
7
8
|
import { WorkflowClock } from "../contracts/WorkflowClock";
|
|
8
9
|
import { FolderReferences } from "../definitions_module/access/Folder.references";
|
|
9
10
|
import { ProcessReferences } from "../definitions_module/access/Process.references";
|
|
10
11
|
import { ProcessFolderLookup } from "../definitions_module/access/ProcessFolder.lookup";
|
|
12
|
+
import { ProcessPartitionLookup } from "../definitions_module/access/ProcessPartition.lookup";
|
|
11
13
|
import { CatalogImport } from "../definitions_module/code/CatalogImport";
|
|
12
14
|
import { CodeProcessCatalog } from "../definitions_module/code/CodeProcessCatalog";
|
|
13
15
|
import { CodeProcessPublisher } from "../definitions_module/code/CodeProcessPublisher";
|
|
@@ -17,14 +19,17 @@ import { IWorkflowDefinitions } from "../definitions_module/services/IWorkflowDe
|
|
|
17
19
|
import { WorkflowDefinitions } from "../definitions_module/services/WorkflowDefinitions.service";
|
|
18
20
|
import { WorkflowEvents } from "../internal/WorkflowEvents";
|
|
19
21
|
import { WorkflowLanguages } from "../internal/WorkflowLanguages";
|
|
22
|
+
import { WorkflowReferences } from "../internal/WorkflowReferences";
|
|
20
23
|
import { WorkflowTools } from "../internal/WorkflowTools";
|
|
21
24
|
import { WorkflowRetention } from "../runtime_module/background/WorkflowRetention";
|
|
22
25
|
import { WorkflowWorker } from "../runtime_module/background/WorkflowWorker";
|
|
23
26
|
import { EventsController } from "../runtime_module/http/Events.controller";
|
|
24
27
|
import { InstancesController } from "../runtime_module/http/Instances.controller";
|
|
25
28
|
import { ChildCalls } from "../runtime_module/internal/ChildCalls";
|
|
29
|
+
import { EventDelivery } from "../runtime_module/internal/EventDelivery";
|
|
26
30
|
import { GraphCache } from "../runtime_module/internal/GraphCache";
|
|
27
31
|
import { RunLimits } from "../runtime_module/internal/RunLimits";
|
|
32
|
+
import { RuntimeProcessUsage } from "../runtime_module/internal/RuntimeProcessUsage";
|
|
28
33
|
import { Schedules } from "../runtime_module/internal/Schedules";
|
|
29
34
|
import { TimerStep } from "../runtime_module/internal/TimerStep";
|
|
30
35
|
import { ToolStep } from "../runtime_module/internal/ToolStep";
|
|
@@ -44,26 +49,30 @@ registerFrameworkClassDeps([
|
|
|
44
49
|
[CodeProcessCatalog, [ServiceProvider]],
|
|
45
50
|
[CodeProcessPublisher, [ServiceProvider]],
|
|
46
51
|
[DefinitionsDbContext, [DbContextOptions]],
|
|
52
|
+
[EventDelivery, [RuntimeDbContext, WorkflowEngine, IWorkflowDefinitions, WorkflowLanguages, ServiceProvider]],
|
|
47
53
|
[EventsController, [IWorkflowRuntime]],
|
|
48
54
|
[FolderReferences, [DefinitionsDbContext]],
|
|
49
55
|
[InstancesController, [IWorkflowRuntime, IWorkflowDefinitions]],
|
|
50
56
|
[ProcessesController, [IWorkflowDefinitions]],
|
|
51
57
|
[ProcessFolderLookup, [DefinitionsDbContext]],
|
|
58
|
+
[ProcessPartitionLookup, [DefinitionsDbContext, WorkflowLanguages, ServiceProvider]],
|
|
52
59
|
[ProcessReferences, [DefinitionsDbContext]],
|
|
53
60
|
[RunLimits, [RuntimeDbContext, WorkflowEngine, IWorkflowDefinitions]],
|
|
54
61
|
[RuntimeDbContext, [DbContextOptions]],
|
|
55
|
-
[
|
|
62
|
+
[RuntimeProcessUsage, [RuntimeDbContext]],
|
|
63
|
+
[Schedules, [RuntimeDbContext, WorkflowEngine, IWorkflowDefinitions, WorkflowLanguages, ServiceProvider]],
|
|
56
64
|
[TaskEvents, [TasksDbContext]],
|
|
57
65
|
[TasksController, [IWorkflowTasks]],
|
|
58
66
|
[TasksDbContext, [DbContextOptions]],
|
|
59
67
|
[TimerStep, [RuntimeDbContext, WorkflowEngine]],
|
|
60
|
-
[ToolStep, [RuntimeDbContext, WorkflowEngine, WorkflowTools]],
|
|
61
|
-
[WorkflowDefinitions, [DefinitionsDbContext, WorkflowTools, CodeProcessCatalog, WorkflowClock, WorkflowEvents, WorkflowLanguages, ServiceProvider]],
|
|
68
|
+
[ToolStep, [RuntimeDbContext, WorkflowEngine, WorkflowTools, WorkflowReferences, WorkflowLanguages]],
|
|
69
|
+
[WorkflowDefinitions, [DefinitionsDbContext, WorkflowTools, CodeProcessCatalog, WorkflowClock, WorkflowEvents, WorkflowLanguages, WorkflowReferences, ServiceProvider]],
|
|
62
70
|
[WorkflowEngine, [RuntimeDbContext, IWorkflowDefinitions, GraphCache, WorkflowEvents, WorkflowClock]],
|
|
63
71
|
[WorkflowEvents, [EventBus, ServiceProvider, "optional:Logger"]],
|
|
64
72
|
[WorkflowLanguages, ["Config:workflow"]],
|
|
73
|
+
[WorkflowReferences, [IAccessCatalog, WorkflowTools, ServiceProvider]],
|
|
65
74
|
[WorkflowRetention, [ServiceProvider, "Config:workflow"]],
|
|
66
|
-
[WorkflowRuntime, [RuntimeDbContext, WorkflowEngine, IWorkflowDefinitions, ServiceProvider, WorkflowLanguages]],
|
|
75
|
+
[WorkflowRuntime, [RuntimeDbContext, WorkflowEngine, EventDelivery, IWorkflowDefinitions, ServiceProvider, WorkflowLanguages]],
|
|
67
76
|
[WorkflowTasks, [TasksDbContext, IWorkflowRuntime, WorkflowClock, WorkflowEvents]],
|
|
68
77
|
[WorkflowTools, [ServiceProvider]],
|
|
69
78
|
[WorkflowWorker, [ServiceProvider, "Config:workflow"]],
|
package/core/workflow/index.ts
CHANGED
|
@@ -33,6 +33,7 @@ export {
|
|
|
33
33
|
export {
|
|
34
34
|
IWorkflowRuntime,
|
|
35
35
|
type CancelInstance,
|
|
36
|
+
type EmitCause,
|
|
36
37
|
type EmitOptions,
|
|
37
38
|
type EmitResult,
|
|
38
39
|
type HistoryEntry,
|
|
@@ -41,6 +42,9 @@ export {
|
|
|
41
42
|
type InstanceSummary,
|
|
42
43
|
type RetryInstance,
|
|
43
44
|
type StartInstance,
|
|
45
|
+
type StartMany,
|
|
46
|
+
type StartManyItem,
|
|
47
|
+
type StartManyResult,
|
|
44
48
|
type TokenDetails,
|
|
45
49
|
} from "./runtime_module/services/IWorkflowRuntime.service";
|
|
46
50
|
export {
|
|
@@ -65,6 +69,7 @@ export type { InstanceStatus, StartedVia } from "./runtime_module/model/WfInstan
|
|
|
65
69
|
export type { TokenStatus } from "./runtime_module/model/WfToken.model";
|
|
66
70
|
export { WorkflowInputValidator, DefaultWorkflowInputValidator, type WorkflowInputContext } from "./contracts/WorkflowInputValidator";
|
|
67
71
|
export { WorkflowExtensions, DefaultWorkflowExtensions, type ExtensionTarget, type WorkflowPortContext } from "./contracts/WorkflowExtensions";
|
|
72
|
+
export { WorkflowPartitions, DefaultWorkflowPartitions, type ProcessPartition } from "./contracts/WorkflowPartitions";
|
|
68
73
|
export { WorkflowError, type WorkflowErrorCode } from "./contracts/WorkflowError";
|
|
69
74
|
export type { WorkflowActor, WorkflowAuditOptions, WorkflowPage, WorkflowPaging, WorkflowRequest, WorkflowToolMetadata } from "./contracts/types";
|
|
70
75
|
|