@bpmnkit/connectors 0.1.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/LICENSE +21 -0
- package/README.md +145 -0
- package/dist/apply.d.ts +67 -0
- package/dist/apply.js +243 -0
- package/dist/catalog.d.ts +76 -0
- package/dist/catalog.js +195 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +5 -0
- package/dist/node/discover.d.ts +90 -0
- package/dist/node/discover.js +176 -0
- package/dist/node/index.d.ts +12 -0
- package/dist/node/index.js +11 -0
- package/dist/template-types.d.ts +143 -0
- package/dist/template-types.js +6 -0
- package/dist/templates/generated.d.ts +3 -0
- package/dist/templates/generated.js +57865 -0
- package/dist/validate.d.ts +65 -0
- package/dist/validate.js +238 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 urbanisierung
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<a href="https://bpmnkit.com"><img src="https://bpmnkit.com/favicon.svg" width="72" height="72" alt="BPMN Kit logo"></a>
|
|
3
|
+
<h1>@bpmnkit/connectors</h1>
|
|
4
|
+
<p>Camunda 8 out-of-the-box connector catalog and deterministic element-template application for @bpmnkit/core</p>
|
|
5
|
+
|
|
6
|
+
[](https://www.npmjs.com/package/@bpmnkit/connectors)
|
|
7
|
+
[](https://github.com/bpmnkit/monorepo/blob/main/LICENSE)
|
|
8
|
+
[](https://github.com/bpmnkit/monorepo)
|
|
9
|
+
[](https://github.com/bpmnkit/monorepo)
|
|
10
|
+
[](https://github.com/bpmnkit/monorepo)
|
|
11
|
+
|
|
12
|
+
[Website](https://bpmnkit.com) · [Documentation](https://bpmnkit.com/docs) · [GitHub](https://github.com/bpmnkit/monorepo) · [Changelog](https://github.com/bpmnkit/monorepo/blob/main/packages/connectors/CHANGELOG.md)
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
18
|
+
|
|
19
|
+
`@bpmnkit/connectors` bundles the 116+ Camunda 8 out-of-the-box connector element templates (Slack, SendGrid, HTTP, Kafka, AWS, the agentic-AI family, and more) and applies them to `@bpmnkit/core` builder options deterministically — every binding kind (`zeebe:input`, `zeebe:output`, `zeebe:taskHeader`, `zeebe:taskDefinition`, `zeebe:property`, `zeebe:adHoc`), dropdown-gated conditions, required-field validation, and FEEL parse-checking on FEEL-tagged values.
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **Full connector catalog** — search and inspect all bundled Camunda 8 OOTB templates
|
|
24
|
+
- **Complete binding resolution** — including `zeebe:property` and `zeebe:output`, which naive appliers drop
|
|
25
|
+
- **Required-field and FEEL validation** — problems are reported, never silently swallowed
|
|
26
|
+
- **Works with any template** — bundled catalog or a custom/generated `ElementTemplate`
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
npm install @bpmnkit/connectors
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { Bpmn } from "@bpmnkit/core"
|
|
38
|
+
import { applyConnectorTemplate, searchConnectors } from "@bpmnkit/connectors"
|
|
39
|
+
|
|
40
|
+
const [slack] = searchConnectors("slack")
|
|
41
|
+
const result = applyConnectorTemplate(slack.id, {
|
|
42
|
+
method: "chat.postMessage",
|
|
43
|
+
token: "{{secrets.SLACK_OAUTH_TOKEN}}",
|
|
44
|
+
"data.channel": "#ops",
|
|
45
|
+
"data.text": "=\"Order \" + orderId + \" failed validation\"",
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
if (result.problems.length > 0) throw new Error(result.problems[0].message)
|
|
49
|
+
|
|
50
|
+
const defs = Bpmn.createProcess("proc")
|
|
51
|
+
.startEvent("s")
|
|
52
|
+
.serviceTask("notify", result.serviceTask!)
|
|
53
|
+
.endEvent("e")
|
|
54
|
+
.build()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Your project's own templates
|
|
58
|
+
|
|
59
|
+
Drop element templates in `.camunda/element-templates/` and they join the bundled catalogue —
|
|
60
|
+
no project configuration, no registration step. A template nearer the diagram wins over one at
|
|
61
|
+
the project root, which wins over the bundled version of the same id.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { registerElementTemplates } from "@bpmnkit/connectors"
|
|
65
|
+
import { discoverElementTemplates } from "@bpmnkit/connectors/node"
|
|
66
|
+
|
|
67
|
+
const { templates, problems } = await discoverElementTemplates({
|
|
68
|
+
from: "processes/orders/order.bpmn",
|
|
69
|
+
root: process.cwd(),
|
|
70
|
+
})
|
|
71
|
+
registerElementTemplates(templates)
|
|
72
|
+
// `problems` names every template that was rejected, and why — nothing is dropped silently.
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The filesystem half lives behind `@bpmnkit/connectors/node`, so the main entry stays
|
|
76
|
+
importable in a browser: a studio or a viewer takes templates from its host instead.
|
|
77
|
+
|
|
78
|
+
Validate them in CI with `casen connector validate`.
|
|
79
|
+
|
|
80
|
+
## API Reference
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
function listConnectors(): ConnectorSummary[]
|
|
84
|
+
function searchConnectors(query: string): ConnectorSummary[]
|
|
85
|
+
function getTemplate(id: string): ElementTemplate | undefined
|
|
86
|
+
function registerElementTemplates(templates: readonly ElementTemplate[]): void
|
|
87
|
+
function clearRegisteredTemplates(): void
|
|
88
|
+
|
|
89
|
+
function validateElementTemplate(value: unknown): TemplateValidation
|
|
90
|
+
function readTemplateDocument(value: unknown): TemplateDocumentResult
|
|
91
|
+
|
|
92
|
+
function applyConnectorTemplate(templateId: string, values?: Record<string, string>): ApplyResult
|
|
93
|
+
function applyElementTemplate(template: ElementTemplate, values?: Record<string, string>): ApplyResult
|
|
94
|
+
|
|
95
|
+
// @bpmnkit/connectors/node
|
|
96
|
+
function discoverElementTemplates(options: DiscoverOptions): Promise<DiscoveryResult>
|
|
97
|
+
function collectElementTemplates(options: { root: string; configFolder?: string }): Promise<DiscoveryResult>
|
|
98
|
+
|
|
99
|
+
interface ApplyResult {
|
|
100
|
+
serviceTask?: ServiceTaskOptions
|
|
101
|
+
adHocSubProcess?: Partial<AdHocSubProcessOptions>
|
|
102
|
+
startEvent?: Partial<StartEventOptions>
|
|
103
|
+
boundaryEvent?: Partial<BoundaryEventOptions>
|
|
104
|
+
intermediateEvent?: Partial<IntermediateCatchEventOptions>
|
|
105
|
+
problems: ApplyProblem[]
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Related Packages
|
|
112
|
+
|
|
113
|
+
| Package | Description |
|
|
114
|
+
|---------|-------------|
|
|
115
|
+
| [`@bpmnkit/core`](https://www.npmjs.com/package/@bpmnkit/core) | BPMN/DMN/Form parser, builder, layout engine |
|
|
116
|
+
| [`@bpmnkit/canvas`](https://www.npmjs.com/package/@bpmnkit/canvas) | Zero-dependency SVG BPMN viewer |
|
|
117
|
+
| [`@bpmnkit/editor`](https://www.npmjs.com/package/@bpmnkit/editor) | Full-featured interactive BPMN editor |
|
|
118
|
+
| [`@bpmnkit/engine`](https://www.npmjs.com/package/@bpmnkit/engine) | Lightweight BPMN process execution engine |
|
|
119
|
+
| [`@bpmnkit/feel`](https://www.npmjs.com/package/@bpmnkit/feel) | FEEL expression language parser & evaluator |
|
|
120
|
+
| [`@bpmnkit/plugins`](https://www.npmjs.com/package/@bpmnkit/plugins) | 22 composable canvas plugins |
|
|
121
|
+
| [`@bpmnkit/api`](https://www.npmjs.com/package/@bpmnkit/api) | Camunda 8 REST API TypeScript client |
|
|
122
|
+
| [`@bpmnkit/ascii`](https://www.npmjs.com/package/@bpmnkit/ascii) | Render BPMN diagrams as Unicode ASCII art |
|
|
123
|
+
| [`@bpmnkit/docspack`](https://www.npmjs.com/package/@bpmnkit/docspack) | BPMN Kit docs as an offline docspack package for AI agents |
|
|
124
|
+
| [`@bpmnkit/ui`](https://www.npmjs.com/package/@bpmnkit/ui) | Shared design tokens and UI components |
|
|
125
|
+
| [`@bpmnkit/profiles`](https://www.npmjs.com/package/@bpmnkit/profiles) | Shared auth, profile storage, and client factories for CLI & proxy |
|
|
126
|
+
| [`@bpmnkit/operate`](https://www.npmjs.com/package/@bpmnkit/operate) | Monitoring & operations frontend for Camunda clusters |
|
|
127
|
+
| [`@bpmnkit/connector-gen`](https://www.npmjs.com/package/@bpmnkit/connector-gen) | Generate connector templates from OpenAPI specs |
|
|
128
|
+
| [`@bpmnkit/cli`](https://www.npmjs.com/package/@bpmnkit/cli) | Camunda 8 command-line interface (casen) |
|
|
129
|
+
| [`@bpmnkit/proxy`](https://www.npmjs.com/package/@bpmnkit/proxy) | Local AI bridge and Camunda API proxy server |
|
|
130
|
+
| [`@bpmnkit/patterns`](https://www.npmjs.com/package/@bpmnkit/patterns) | Domain process patterns for BPMNKit AIKit |
|
|
131
|
+
| [`@bpmnkit/reebe-wasm`](https://www.npmjs.com/package/@bpmnkit/reebe-wasm) | WebAssembly BPMN engine for browser simulation |
|
|
132
|
+
| [`@bpmnkit/worker-client`](https://www.npmjs.com/package/@bpmnkit/worker-client) | Thin Zeebe REST client for standalone workers |
|
|
133
|
+
| [`@bpmnkit/cli-sdk`](https://www.npmjs.com/package/@bpmnkit/cli-sdk) | Plugin authoring SDK for the casen CLI |
|
|
134
|
+
| [`@bpmnkit/create-casen-plugin`](https://www.npmjs.com/package/@bpmnkit/create-casen-plugin) | Scaffold a new casen CLI plugin in seconds |
|
|
135
|
+
| [`@bpmnkit/casen-report`](https://www.npmjs.com/package/@bpmnkit/casen-report) | HTML reports from Camunda 8 incident and SLA data |
|
|
136
|
+
| [`@bpmnkit/casen-worker-http`](https://www.npmjs.com/package/@bpmnkit/casen-worker-http) | Example HTTP worker plugin — completes jobs with live JSONPlaceholder API data |
|
|
137
|
+
| [`@bpmnkit/casen-worker-ai`](https://www.npmjs.com/package/@bpmnkit/casen-worker-ai) | AI task worker — classify, summarize, extract, and decide using Claude |
|
|
138
|
+
|
|
139
|
+
## License
|
|
140
|
+
|
|
141
|
+
[MIT](https://github.com/bpmnkit/monorepo/blob/main/LICENSE) © BPMN Kit — made by [u11g](https://u11g.com)
|
|
142
|
+
|
|
143
|
+
<div align="center">
|
|
144
|
+
<a href="https://bpmnkit.com"><img src="https://bpmnkit.com/favicon.svg" width="32" height="32" alt="BPMN Kit"></a>
|
|
145
|
+
</div>
|
package/dist/apply.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { AdHocSubProcessOptions, BoundaryEventOptions, IntermediateCatchEventOptions, ServiceTaskOptions, StartEventOptions } from "@bpmnkit/core";
|
|
2
|
+
import type { ElementTemplate } from "./template-types.js";
|
|
3
|
+
export interface ApplyProblem {
|
|
4
|
+
/** The property key this problem is about, if any. */
|
|
5
|
+
key?: string;
|
|
6
|
+
message: string;
|
|
7
|
+
/**
|
|
8
|
+
* What kind of problem this is — distinguishes a genuinely unmet required
|
|
9
|
+
* field ("missing-required") from an unrecognized values key
|
|
10
|
+
* ("unknown-key"), a FEEL syntax error ("invalid-feel"), or a template
|
|
11
|
+
* with no resolvable task type ("no-task-type"). Callers that specifically
|
|
12
|
+
* want "what's still required" (e.g. the deploy-lint connector check)
|
|
13
|
+
* must filter on `kind === "missing-required"` — an unknown key is not
|
|
14
|
+
* evidence that some other field is missing.
|
|
15
|
+
*/
|
|
16
|
+
kind?: "missing-required" | "unknown-key" | "invalid-feel" | "no-task-type";
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The result of applying a connector template — exactly one of `serviceTask`,
|
|
20
|
+
* `adHocSubProcess`, `startEvent`, `boundaryEvent`, or `intermediateEvent` is
|
|
21
|
+
* set, matching the template's direction. `problems` is always present and
|
|
22
|
+
* must be checked: a non-empty array means the template could not be fully
|
|
23
|
+
* applied (missing required value, unknown value key, or a FEEL parse error).
|
|
24
|
+
*/
|
|
25
|
+
export interface ApplyResult {
|
|
26
|
+
serviceTask?: ServiceTaskOptions;
|
|
27
|
+
adHocSubProcess?: Partial<AdHocSubProcessOptions>;
|
|
28
|
+
startEvent?: Partial<StartEventOptions>;
|
|
29
|
+
boundaryEvent?: Partial<BoundaryEventOptions>;
|
|
30
|
+
intermediateEvent?: Partial<IntermediateCatchEventOptions>;
|
|
31
|
+
problems: ApplyProblem[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The binding types `applyBinding` below writes.
|
|
35
|
+
*
|
|
36
|
+
* Declared beside the switch so the two are edited together: anything the
|
|
37
|
+
* switch gains belongs here, and `validateElementTemplate` warns about every
|
|
38
|
+
* binding that is valid but absent from this set — otherwise a template using
|
|
39
|
+
* one would apply silently and do nothing.
|
|
40
|
+
*/
|
|
41
|
+
export declare const APPLIED_BINDING_TYPES: ReadonlySet<string>;
|
|
42
|
+
/**
|
|
43
|
+
* Applies a Camunda 8 out-of-the-box connector element template deterministically.
|
|
44
|
+
*
|
|
45
|
+
* Unlike a naive apply that only handles `zeebe:input`, this resolves every
|
|
46
|
+
* binding kind (`zeebe:input`, `zeebe:output`, `zeebe:taskHeader`,
|
|
47
|
+
* `zeebe:taskDefinition(:type)`, `zeebe:property`, `zeebe:adHoc`), respects
|
|
48
|
+
* dropdown-gated `condition`s, validates required fields, and parse-validates
|
|
49
|
+
* any value that looks like a FEEL expression (leading "=").
|
|
50
|
+
*
|
|
51
|
+
* `values` keys match `ConnectorSummary.requiredInputs[].key` /
|
|
52
|
+
* `optionalInputs[].key` from `listConnectors()`/`searchConnectors()`.
|
|
53
|
+
*
|
|
54
|
+
* Operates on any {@link ElementTemplate} object — not just the bundled OOTB
|
|
55
|
+
* catalog — so custom/generated templates (e.g. from `@bpmnkit/connector-gen`)
|
|
56
|
+
* work the same way. Use {@link applyConnectorTemplate} to apply by bundled
|
|
57
|
+
* template id instead.
|
|
58
|
+
*/
|
|
59
|
+
export declare function applyElementTemplate(template: ElementTemplate, values?: Record<string, string>): ApplyResult;
|
|
60
|
+
/**
|
|
61
|
+
* Applies a bundled Camunda 8 out-of-the-box connector element template by
|
|
62
|
+
* id — see {@link applyElementTemplate} for the full binding-resolution
|
|
63
|
+
* behavior. Returns a single `problems` entry if `templateId` isn't in the
|
|
64
|
+
* bundled catalog (use `applyElementTemplate` directly for custom templates).
|
|
65
|
+
*/
|
|
66
|
+
export declare function applyConnectorTemplate(templateId: string, values?: Record<string, string>): ApplyResult;
|
|
67
|
+
//# sourceMappingURL=apply.d.ts.map
|
package/dist/apply.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { parseExpression } from "@bpmnkit/feel";
|
|
2
|
+
import { getTemplate, propertyKey } from "./catalog.js";
|
|
3
|
+
function evalCondition(cond, values) {
|
|
4
|
+
if ("allMatch" in cond) {
|
|
5
|
+
return cond.allMatch.every((c) => evalCondition(c, values));
|
|
6
|
+
}
|
|
7
|
+
if ("equals" in cond)
|
|
8
|
+
return values[cond.property] === cond.equals;
|
|
9
|
+
if ("oneOf" in cond)
|
|
10
|
+
return cond.oneOf.includes(values[cond.property] ?? "");
|
|
11
|
+
if ("isActive" in cond)
|
|
12
|
+
return Boolean(values[cond.property]) === cond.isActive;
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
function defaultValueOf(prop) {
|
|
16
|
+
if (prop.value === undefined)
|
|
17
|
+
return undefined;
|
|
18
|
+
return String(prop.value);
|
|
19
|
+
}
|
|
20
|
+
/** Resolves every property to its effective string value: user override, else template default. */
|
|
21
|
+
function resolveValues(template, values) {
|
|
22
|
+
const resolved = {};
|
|
23
|
+
for (const prop of template.properties) {
|
|
24
|
+
const key = propertyKey(prop);
|
|
25
|
+
if (!key)
|
|
26
|
+
continue;
|
|
27
|
+
const value = values[key] ?? defaultValueOf(prop);
|
|
28
|
+
if (value !== undefined)
|
|
29
|
+
resolved[key] = value;
|
|
30
|
+
}
|
|
31
|
+
return resolved;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The binding types `applyBinding` below writes.
|
|
35
|
+
*
|
|
36
|
+
* Declared beside the switch so the two are edited together: anything the
|
|
37
|
+
* switch gains belongs here, and `validateElementTemplate` warns about every
|
|
38
|
+
* binding that is valid but absent from this set — otherwise a template using
|
|
39
|
+
* one would apply silently and do nothing.
|
|
40
|
+
*/
|
|
41
|
+
export const APPLIED_BINDING_TYPES = new Set([
|
|
42
|
+
"zeebe:input",
|
|
43
|
+
"zeebe:output",
|
|
44
|
+
"zeebe:taskHeader",
|
|
45
|
+
"zeebe:taskDefinition",
|
|
46
|
+
"zeebe:taskDefinition:type",
|
|
47
|
+
"zeebe:property",
|
|
48
|
+
"zeebe:adHoc",
|
|
49
|
+
"property",
|
|
50
|
+
]);
|
|
51
|
+
function applyBinding(binding, value, accum) {
|
|
52
|
+
switch (binding.type) {
|
|
53
|
+
case "zeebe:input":
|
|
54
|
+
accum.inputs.push({ source: value, target: binding.name });
|
|
55
|
+
return;
|
|
56
|
+
case "zeebe:output":
|
|
57
|
+
// `binding.source` is the template's fixed FEEL read expression (e.g. "=response");
|
|
58
|
+
// `value` is the user-chosen process-variable name to write it to.
|
|
59
|
+
accum.outputs.push({ source: binding.source, target: value });
|
|
60
|
+
return;
|
|
61
|
+
case "zeebe:taskHeader":
|
|
62
|
+
accum.taskHeaders[binding.key] = value;
|
|
63
|
+
return;
|
|
64
|
+
case "zeebe:taskDefinition":
|
|
65
|
+
if (binding.property === "type")
|
|
66
|
+
accum.taskType = value;
|
|
67
|
+
else
|
|
68
|
+
accum.retries = value;
|
|
69
|
+
return;
|
|
70
|
+
case "zeebe:taskDefinition:type":
|
|
71
|
+
accum.taskType = value;
|
|
72
|
+
return;
|
|
73
|
+
case "zeebe:property":
|
|
74
|
+
accum.zeebeProperties.push({ name: binding.name, value });
|
|
75
|
+
return;
|
|
76
|
+
case "zeebe:adHoc":
|
|
77
|
+
accum.adHoc[binding.property] = value;
|
|
78
|
+
return;
|
|
79
|
+
case "property":
|
|
80
|
+
// "name" binds to the element's display name — handled by the caller, not here.
|
|
81
|
+
return;
|
|
82
|
+
default:
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function directionOf(template) {
|
|
87
|
+
return template.elementType?.value ?? template.appliesTo[0] ?? "";
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Applies a Camunda 8 out-of-the-box connector element template deterministically.
|
|
91
|
+
*
|
|
92
|
+
* Unlike a naive apply that only handles `zeebe:input`, this resolves every
|
|
93
|
+
* binding kind (`zeebe:input`, `zeebe:output`, `zeebe:taskHeader`,
|
|
94
|
+
* `zeebe:taskDefinition(:type)`, `zeebe:property`, `zeebe:adHoc`), respects
|
|
95
|
+
* dropdown-gated `condition`s, validates required fields, and parse-validates
|
|
96
|
+
* any value that looks like a FEEL expression (leading "=").
|
|
97
|
+
*
|
|
98
|
+
* `values` keys match `ConnectorSummary.requiredInputs[].key` /
|
|
99
|
+
* `optionalInputs[].key` from `listConnectors()`/`searchConnectors()`.
|
|
100
|
+
*
|
|
101
|
+
* Operates on any {@link ElementTemplate} object — not just the bundled OOTB
|
|
102
|
+
* catalog — so custom/generated templates (e.g. from `@bpmnkit/connector-gen`)
|
|
103
|
+
* work the same way. Use {@link applyConnectorTemplate} to apply by bundled
|
|
104
|
+
* template id instead.
|
|
105
|
+
*/
|
|
106
|
+
export function applyElementTemplate(template, values = {}) {
|
|
107
|
+
const resolved = resolveValues(template, values);
|
|
108
|
+
const problems = [];
|
|
109
|
+
const knownKeys = new Set(template.properties.map(propertyKey).filter(Boolean));
|
|
110
|
+
for (const key of Object.keys(values)) {
|
|
111
|
+
if (key !== "name" && !knownKeys.has(key)) {
|
|
112
|
+
problems.push({
|
|
113
|
+
key,
|
|
114
|
+
kind: "unknown-key",
|
|
115
|
+
message: `Unknown value key "${key}" for template "${template.id}"`,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const accum = {
|
|
120
|
+
inputs: [],
|
|
121
|
+
outputs: [],
|
|
122
|
+
taskHeaders: {},
|
|
123
|
+
zeebeProperties: [],
|
|
124
|
+
adHoc: {},
|
|
125
|
+
};
|
|
126
|
+
for (const prop of template.properties) {
|
|
127
|
+
const key = propertyKey(prop);
|
|
128
|
+
if (prop.condition && !evalCondition(prop.condition, resolved))
|
|
129
|
+
continue;
|
|
130
|
+
const value = resolved[key];
|
|
131
|
+
if (value === undefined || value === "") {
|
|
132
|
+
if (prop.type !== "Hidden" && prop.constraints?.notEmpty) {
|
|
133
|
+
problems.push({
|
|
134
|
+
key,
|
|
135
|
+
kind: "missing-required",
|
|
136
|
+
message: `Missing required value for "${prop.label ?? key}" (${key})`,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if ((prop.feel === "required" || prop.feel === "optional") && value.startsWith("=")) {
|
|
142
|
+
const { errors } = parseExpression(value.slice(1));
|
|
143
|
+
for (const err of errors) {
|
|
144
|
+
problems.push({
|
|
145
|
+
key,
|
|
146
|
+
kind: "invalid-feel",
|
|
147
|
+
message: `Invalid FEEL expression for "${key}": ${err.message}`,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
applyBinding(prop.binding, value, accum);
|
|
152
|
+
}
|
|
153
|
+
const modelerTemplate = template.id;
|
|
154
|
+
const modelerTemplateVersion = template.version !== undefined ? String(template.version) : undefined;
|
|
155
|
+
const modelerTemplateIcon = template.icon?.contents;
|
|
156
|
+
const name = values.name ?? template.name;
|
|
157
|
+
const direction = directionOf(template);
|
|
158
|
+
if (direction === "bpmn:AdHocSubProcess") {
|
|
159
|
+
return {
|
|
160
|
+
adHocSubProcess: {
|
|
161
|
+
name,
|
|
162
|
+
taskDefinition: accum.taskType
|
|
163
|
+
? { type: accum.taskType, retries: accum.retries }
|
|
164
|
+
: undefined,
|
|
165
|
+
ioMapping: accum.inputs.length || accum.outputs.length
|
|
166
|
+
? { inputs: accum.inputs, outputs: accum.outputs }
|
|
167
|
+
: undefined,
|
|
168
|
+
taskHeaders: Object.keys(accum.taskHeaders).length > 0 ? accum.taskHeaders : undefined,
|
|
169
|
+
zeebeProperties: accum.zeebeProperties.length > 0 ? accum.zeebeProperties : undefined,
|
|
170
|
+
outputCollection: accum.adHoc.outputCollection,
|
|
171
|
+
outputElement: accum.adHoc.outputElement,
|
|
172
|
+
activeElementsCollection: accum.adHoc.activeElementsCollection,
|
|
173
|
+
modelerTemplate,
|
|
174
|
+
modelerTemplateVersion,
|
|
175
|
+
modelerTemplateIcon,
|
|
176
|
+
},
|
|
177
|
+
problems,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
if (direction === "bpmn:StartEvent" ||
|
|
181
|
+
direction === "bpmn:BoundaryEvent" ||
|
|
182
|
+
direction === "bpmn:IntermediateCatchEvent" ||
|
|
183
|
+
direction === "bpmn:ReceiveTask") {
|
|
184
|
+
if (accum.inputs.length > 0 ||
|
|
185
|
+
accum.outputs.length > 0 ||
|
|
186
|
+
Object.keys(accum.taskHeaders).length > 0) {
|
|
187
|
+
problems.push({
|
|
188
|
+
message: "Template uses zeebe:input/output/taskHeader bindings on an event-attached element; " +
|
|
189
|
+
"applyConnectorTemplate() only maps zeebe:property for start/boundary/intermediate events. " +
|
|
190
|
+
"Apply the remaining bindings manually.",
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
const partial = {
|
|
194
|
+
name,
|
|
195
|
+
zeebeProperties: accum.zeebeProperties.length > 0 ? accum.zeebeProperties : undefined,
|
|
196
|
+
modelerTemplate,
|
|
197
|
+
modelerTemplateVersion,
|
|
198
|
+
modelerTemplateIcon,
|
|
199
|
+
};
|
|
200
|
+
if (direction === "bpmn:StartEvent")
|
|
201
|
+
return { startEvent: partial, problems };
|
|
202
|
+
if (direction === "bpmn:BoundaryEvent")
|
|
203
|
+
return { boundaryEvent: partial, problems };
|
|
204
|
+
return { intermediateEvent: partial, problems };
|
|
205
|
+
}
|
|
206
|
+
// Default: outbound service task (bpmn:ServiceTask, bpmn:SendTask, bpmn:EndEvent, bpmn:Task, ...)
|
|
207
|
+
if (!accum.taskType) {
|
|
208
|
+
problems.push({
|
|
209
|
+
kind: "no-task-type",
|
|
210
|
+
message: `Template "${template.id}" produced no zeebe:taskDefinition type`,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
serviceTask: {
|
|
215
|
+
name,
|
|
216
|
+
taskType: accum.taskType ?? "",
|
|
217
|
+
retries: accum.retries,
|
|
218
|
+
ioMapping: accum.inputs.length || accum.outputs.length
|
|
219
|
+
? { inputs: accum.inputs, outputs: accum.outputs }
|
|
220
|
+
: undefined,
|
|
221
|
+
taskHeaders: Object.keys(accum.taskHeaders).length > 0 ? accum.taskHeaders : undefined,
|
|
222
|
+
zeebeProperties: accum.zeebeProperties.length > 0 ? accum.zeebeProperties : undefined,
|
|
223
|
+
modelerTemplate,
|
|
224
|
+
modelerTemplateVersion,
|
|
225
|
+
modelerTemplateIcon,
|
|
226
|
+
},
|
|
227
|
+
problems,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Applies a bundled Camunda 8 out-of-the-box connector element template by
|
|
232
|
+
* id — see {@link applyElementTemplate} for the full binding-resolution
|
|
233
|
+
* behavior. Returns a single `problems` entry if `templateId` isn't in the
|
|
234
|
+
* bundled catalog (use `applyElementTemplate` directly for custom templates).
|
|
235
|
+
*/
|
|
236
|
+
export function applyConnectorTemplate(templateId, values = {}) {
|
|
237
|
+
const template = getTemplate(templateId);
|
|
238
|
+
if (!template) {
|
|
239
|
+
return { problems: [{ message: `Unknown connector template "${templateId}"` }] };
|
|
240
|
+
}
|
|
241
|
+
return applyElementTemplate(template, values);
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=apply.js.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { ElementTemplate, TemplateCondition, TemplateProperty } from "./template-types.js";
|
|
2
|
+
/** Where in the process a connector template attaches. */
|
|
3
|
+
export type ConnectorDirection = "outbound" | "inbound-start" | "inbound-intermediate" | "inbound-boundary"
|
|
4
|
+
/** The AI Agent Sub-process connector — an ad-hoc sub-process, not a single task. */
|
|
5
|
+
| "agentic";
|
|
6
|
+
/** One user-configurable (non-Hidden) property on a connector template. */
|
|
7
|
+
export interface ConnectorInputSpec {
|
|
8
|
+
/** Lookup key — matches the keys `applyConnectorTemplate()` expects in its `values` argument. */
|
|
9
|
+
key: string;
|
|
10
|
+
label: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
/** True for fields whose label/key suggest a credential (API key, token, password, secret). */
|
|
13
|
+
isSecret: boolean;
|
|
14
|
+
/** True if the field's value is interpreted as FEEL (a leading "=" makes it an expression). */
|
|
15
|
+
isFeel: boolean;
|
|
16
|
+
default?: string | number | boolean;
|
|
17
|
+
choices?: Array<{
|
|
18
|
+
name: string;
|
|
19
|
+
value: string;
|
|
20
|
+
}>;
|
|
21
|
+
/** This field only applies (and is only required) when this condition holds against other values. */
|
|
22
|
+
condition?: TemplateCondition;
|
|
23
|
+
}
|
|
24
|
+
/** A connector template reduced to what a skill or LLM needs to select and configure it. */
|
|
25
|
+
export interface ConnectorSummary {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
/** Zeebe job type this template sets, e.g. "io.camunda:slack:1". Absent for some inbound templates. */
|
|
30
|
+
taskType?: string;
|
|
31
|
+
appliesTo: string[];
|
|
32
|
+
direction: ConnectorDirection;
|
|
33
|
+
keywords: string[];
|
|
34
|
+
requiredInputs: ConnectorInputSpec[];
|
|
35
|
+
optionalInputs: ConnectorInputSpec[];
|
|
36
|
+
}
|
|
37
|
+
/** Same key-derivation logic used at apply time — kept in sync with `apply.ts`. */
|
|
38
|
+
export declare function propertyKey(prop: TemplateProperty): string;
|
|
39
|
+
/**
|
|
40
|
+
* What a template will do, without applying it.
|
|
41
|
+
*
|
|
42
|
+
* The catalogue computes this for every listing already; it is exported because
|
|
43
|
+
* anything offering a template to a person needs to be able to say what it
|
|
44
|
+
* binds and what it will ask for — a picker that applies on the first click is
|
|
45
|
+
* asking someone to choose blind.
|
|
46
|
+
*
|
|
47
|
+
* @param template - The template to describe.
|
|
48
|
+
*/
|
|
49
|
+
export declare function summarizeTemplate(template: ElementTemplate): ConnectorSummary;
|
|
50
|
+
/**
|
|
51
|
+
* Adds templates to the catalogue, replacing any bundled template with the same
|
|
52
|
+
* id.
|
|
53
|
+
*
|
|
54
|
+
* The workspace wins deliberately: a project that ships its own version of a
|
|
55
|
+
* connector means it, and the bundle is the fallback. Registering the same id
|
|
56
|
+
* twice keeps the later one, so a nearer directory can override a further one.
|
|
57
|
+
*
|
|
58
|
+
* @param templates - Validated templates. Nothing is checked here; run
|
|
59
|
+
* `validateElementTemplate` (or `readTemplateDocument`) at the boundary where
|
|
60
|
+
* the JSON was read, so a bad file is reported against its own path.
|
|
61
|
+
*/
|
|
62
|
+
export declare function registerElementTemplates(templates: readonly ElementTemplate[]): void;
|
|
63
|
+
/** Drops every registered template, leaving only the bundled catalogue. */
|
|
64
|
+
export declare function clearRegisteredTemplates(): void;
|
|
65
|
+
/** Every connector template — bundled and registered — as a compact summary. */
|
|
66
|
+
export declare function listConnectors(): ConnectorSummary[];
|
|
67
|
+
/** The full element template for a given template id, registered or bundled. */
|
|
68
|
+
export declare function getTemplate(id: string): ElementTemplate | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Keyword-scored search over the bundled connector catalog — mirrors
|
|
71
|
+
* `@bpmnkit/patterns`' `findPattern()` matching style. Matches against the
|
|
72
|
+
* template name are weighted highest, then keyword-list matches, then a
|
|
73
|
+
* general substring match; ties prefer outbound connectors.
|
|
74
|
+
*/
|
|
75
|
+
export declare function searchConnectors(query: string): ConnectorSummary[];
|
|
76
|
+
//# sourceMappingURL=catalog.d.ts.map
|