@uipath/maestro-builder-sdk 6.70.9 → 6.71.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-index.md +8 -8
- package/dist/api-members.md +37 -35
- package/dist/check.js +11 -11
- package/dist/core/event-subscription.d.ts +113 -0
- package/dist/core/event-subscription.js +356 -0
- package/dist/core/nodes/registry.d.ts +3 -1
- package/dist/core/nodes/registry.js +22 -3
- package/dist/core/refusals.d.ts +3 -0
- package/dist/core/refusals.js +3 -0
- package/dist/decompile.js +0 -7
- package/dist/flow-node-type.d.ts +25 -0
- package/dist/nodes/connector/flow/event-wait.d.ts +33 -0
- package/dist/nodes/connector/flow/event-wait.js +162 -0
- package/dist/nodes/connector/flow/family.d.ts +1 -1
- package/dist/nodes/connector/flow/family.js +3 -2
- package/dist/nodes/process/flow/check.js +16 -2
- package/dist/nodes/process/flow/node-type.js +19 -10
- package/dist/nodes/process/flow/refusals.js +1 -1
- package/dist/nodes/process/flow/spec.d.ts +28 -2
- package/dist/serialize.js +20 -391
- package/package.json +2 -2
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { missingBindingLabels } from '../../../core/binding-messages.js';
|
|
2
|
+
import { prepareCommand } from '../../../core/cli-spelling.js';
|
|
3
|
+
import { commentText } from '../../../core/comment-text.js';
|
|
4
|
+
import { eventFilterFromTreeLeaf } from '../../../core/event-filters.js';
|
|
5
|
+
import { eventDetail, eventTarget, libraryRequiredForEvent, refuseUnverifiedByoa, resolveEvent } from '../../../core/event-subscription.js';
|
|
6
|
+
import { Expr } from '../../../core/expr.js';
|
|
7
|
+
import { tsLiteral, tsObject, tsOptions } from '../../../core/ts-literal.js';
|
|
8
|
+
const EVENT_PREFIX = 'uipath.connector.event.';
|
|
9
|
+
/** `<connector>.<event>` after the prefix, split on the last dot; undefined for a name with no event. */
|
|
10
|
+
export function splitEvent(typeName) {
|
|
11
|
+
if (!typeName.startsWith(EVENT_PREFIX))
|
|
12
|
+
return undefined;
|
|
13
|
+
const rest = typeName.slice(EVENT_PREFIX.length);
|
|
14
|
+
const dot = rest.lastIndexOf('.');
|
|
15
|
+
if (dot <= 0)
|
|
16
|
+
return undefined;
|
|
17
|
+
return { connector: rest.slice(0, dot), event: rest.slice(dot + 1) };
|
|
18
|
+
}
|
|
19
|
+
function serializeEventWait(spec, ctx) {
|
|
20
|
+
const sub = spec.subscription;
|
|
21
|
+
const site = `waitForEvent "${ctx.step}"`;
|
|
22
|
+
if (!ctx.library)
|
|
23
|
+
throw libraryRequiredForEvent(ctx.events, sub, ctx.nodeId, site, site);
|
|
24
|
+
const rc = resolveEvent(ctx.library, 'event', sub, site);
|
|
25
|
+
refuseUnverifiedByoa(ctx.events, site, sub);
|
|
26
|
+
const detail = eventDetail(rc, sub, ctx.nodeId, ctx.events, site);
|
|
27
|
+
// The platform reaches the connection through the flow's `bindings[]`, as for
|
|
28
|
+
// a connector operation (board G-19). `eventDetail` refused a node without
|
|
29
|
+
// both labels, so both resolve here.
|
|
30
|
+
const target = eventTarget(sub);
|
|
31
|
+
const connectionId = ctx.resolveBinding(sub.connection, 'connection', site, target);
|
|
32
|
+
const folderKey = ctx.resolveBinding(sub.folder, 'folder', site, target);
|
|
33
|
+
ctx.bindConnection({
|
|
34
|
+
model: rc.v1def?.model,
|
|
35
|
+
connectorKey: rc.connectorKey, connectionId: connectionId,
|
|
36
|
+
...(folderKey !== undefined ? { folderKey } : {}),
|
|
37
|
+
});
|
|
38
|
+
// The node is the event the author named (`rc.nodeType`); a definition naming
|
|
39
|
+
// another is written under that name, so the node and its definitions[] entry agree.
|
|
40
|
+
const v1def = rc.v1def;
|
|
41
|
+
const def = v1def.nodeType === rc.nodeType ? v1def : { ...v1def, nodeType: rc.nodeType };
|
|
42
|
+
return {
|
|
43
|
+
definition: { source: 'snapshot', nodeType: def.nodeType, version: def.version, manifest: def },
|
|
44
|
+
inputs: { detail },
|
|
45
|
+
// A wait continues on `output`, as every connector node does.
|
|
46
|
+
port: 'output',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** A `where` value as decompile reads it: an expression back to an `Expr`, wire text as text, any other JSON as is. */
|
|
50
|
+
function liftValue(v, ctx) {
|
|
51
|
+
const raw = Array.isArray(v) ? undefined : ctx.sourceText(v);
|
|
52
|
+
if (raw === undefined)
|
|
53
|
+
return v;
|
|
54
|
+
return raw.startsWith('=js:') ? new Expr(raw.slice(4)) : raw;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The subscription back from the node: the `where` scope from
|
|
58
|
+
* `detail.eventParameters`, which carries it verbatim, and the filters from the
|
|
59
|
+
* filter tree inside `detail.configuration`. Both are also encoded into the
|
|
60
|
+
* generated `filterExpression`, but reading the structured copies avoids parsing
|
|
61
|
+
* a string compile generated.
|
|
62
|
+
*/
|
|
63
|
+
function liftEventWait(node, ctx) {
|
|
64
|
+
const n = node;
|
|
65
|
+
const split = splitEvent(n.type);
|
|
66
|
+
if (!split)
|
|
67
|
+
return undefined;
|
|
68
|
+
const detail = (n.inputs?.detail ?? undefined);
|
|
69
|
+
const where = Object.entries((detail?.eventParameters ?? {}))
|
|
70
|
+
.filter(([, v]) => v !== undefined && v !== null && String(v) !== '')
|
|
71
|
+
.map(([k, v]) => [k, liftValue(v, ctx)]);
|
|
72
|
+
// The filter tree lives inside the `=jsonString:` configuration blob, and so
|
|
73
|
+
// does the one fact that says whether `detail.objectName` was the AUTHOR's
|
|
74
|
+
// choice: a GENERIC event (`activityType: GenericTrigger`) carries the object
|
|
75
|
+
// the author named, a curated one carries its built-in object.
|
|
76
|
+
let filters = [];
|
|
77
|
+
let generic = false;
|
|
78
|
+
const config = detail?.configuration;
|
|
79
|
+
if (typeof config === 'string' && config.startsWith('=jsonString:')) {
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(config.slice('=jsonString:'.length));
|
|
82
|
+
generic = parsed?.essentialConfiguration?.instanceParameters?.activityType === 'GenericTrigger';
|
|
83
|
+
const rows = (parsed?.essentialConfiguration?.filter?.filters ?? []);
|
|
84
|
+
filters = rows
|
|
85
|
+
.map((f) => eventFilterFromTreeLeaf(f))
|
|
86
|
+
.filter((f) => f !== undefined);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// A hand-edited blob is not ours to guess at — the scope and identity
|
|
90
|
+
// still recover, and the filters simply do not come back.
|
|
91
|
+
filters = [];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const object = generic && typeof detail?.objectName === 'string' && detail.objectName !== ''
|
|
95
|
+
? detail.objectName
|
|
96
|
+
: undefined;
|
|
97
|
+
const connection = typeof detail?.connectionId === 'string' ? detail.connectionId : undefined;
|
|
98
|
+
const folder = typeof detail?.connectionFolderKey === 'string' ? detail.connectionFolderKey : undefined;
|
|
99
|
+
// A connection the file never picked (`connectionId: null`): the source cannot
|
|
100
|
+
// invent labels for it, and compile and check refuse a node without both
|
|
101
|
+
// (BINDING_MISSING, flow-builder-sdk#890), so the source says so at the node
|
|
102
|
+
// and the run warns once.
|
|
103
|
+
const missing = missingBindingLabels({ connection, folder });
|
|
104
|
+
if (missing.length > 0) {
|
|
105
|
+
ctx.warn(`node ${tsLiteral(n.id)} (${n.type}) has no ${missing.join(' or ')} in the .flow (an unbound draft). `
|
|
106
|
+
+ `The source leaves ${missing.length > 1 ? 'them' : 'it'} out, and compile and check refuse it (BINDING_MISSING) `
|
|
107
|
+
+ `until it names both labels: run \`${prepareCommand(split.connector, split.event)}\`, then pass `
|
|
108
|
+
+ `\`connection\` and \`folder\`.`);
|
|
109
|
+
}
|
|
110
|
+
return { kind: 'waitEvent', ...split, where, object, filters, connection, folder, missing };
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* `waitForEvent({ … })`, the stringly form: the subscription as one object. The
|
|
114
|
+
* unbound marker sits inside the call, after the object, where the lift has
|
|
115
|
+
* always put it.
|
|
116
|
+
*/
|
|
117
|
+
function printEventWait(l, ctx) {
|
|
118
|
+
const value = (v) => (v instanceof Expr ? ctx.value(v) : ctx.json(v));
|
|
119
|
+
const filters = l.filters.map((f) => tsOptions([
|
|
120
|
+
['field', tsLiteral(f.field)],
|
|
121
|
+
[f.operator, typeof f.value === 'string' ? tsLiteral(f.value) : JSON.stringify(f.value)],
|
|
122
|
+
]));
|
|
123
|
+
const subscription = tsOptions([
|
|
124
|
+
['connector', tsLiteral(l.connector)],
|
|
125
|
+
['event', tsLiteral(l.event)],
|
|
126
|
+
['where', l.where.length ? tsObject(l.where.map(([k, v]) => [k, value(v)])) : undefined],
|
|
127
|
+
['object', l.object !== undefined ? tsLiteral(l.object) : undefined],
|
|
128
|
+
['filters', filters.length ? `[${filters.join(', ')}]` : undefined],
|
|
129
|
+
['connection', l.connection !== undefined ? tsLiteral(l.connection) : undefined],
|
|
130
|
+
['folder', l.folder !== undefined ? tsLiteral(l.folder) : undefined],
|
|
131
|
+
]);
|
|
132
|
+
const marker = l.missing.length > 0
|
|
133
|
+
? ` /* TODO: bind ${commentText(l.missing.join(' and '))}; check refuses this node until it has both labels (BINDING_MISSING) */`
|
|
134
|
+
: '';
|
|
135
|
+
return { factory: 'waitForEvent', positional: [subscription + marker] };
|
|
136
|
+
}
|
|
137
|
+
const eventWait10 = {
|
|
138
|
+
kind: 'waitEvent', typeName: `${EVENT_PREFIX}*`, version: '1.0.0', factory: 'waitForEvent',
|
|
139
|
+
definition: 'per-tenant',
|
|
140
|
+
// An event wait resumes or it does not: it has no error port to route.
|
|
141
|
+
errorPort: false,
|
|
142
|
+
serialize: (spec, ctx) => serializeEventWait(spec, ctx),
|
|
143
|
+
deserialize: (node, ctx) => liftEventWait(node, ctx),
|
|
144
|
+
print: (spec, ctx) => printEventWait(spec, ctx),
|
|
145
|
+
check: (spec, ctx) => ctx.eventSubscription(spec.subscription, `waitForEvent "${ctx.step}"`),
|
|
146
|
+
namedNode: (spec) => {
|
|
147
|
+
const sub = spec.subscription;
|
|
148
|
+
return {
|
|
149
|
+
typeName: `${EVENT_PREFIX}${sub?.connector}.${sub?.event}`,
|
|
150
|
+
...(typeof sub?.version === 'string' ? { version: sub.version } : {}),
|
|
151
|
+
};
|
|
152
|
+
},
|
|
153
|
+
expressions: () => [],
|
|
154
|
+
output: () => ({ kind: 'opaque' }),
|
|
155
|
+
};
|
|
156
|
+
export const eventWaitNodeType = {
|
|
157
|
+
kind: 'waitEvent', typeName: `${EVENT_PREFIX}*`, typeNamePrefix: EVENT_PREFIX, factory: 'waitForEvent',
|
|
158
|
+
typeNameMatches: (typeName) => splitEvent(typeName) !== undefined,
|
|
159
|
+
versionedByDefinition: true,
|
|
160
|
+
defaultVersion: eventWait10.version,
|
|
161
|
+
versions: { [eventWait10.version]: eventWait10 },
|
|
162
|
+
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/** The connector node family, as flow-node-registry.ts lists it: an Integration Service connector operation. */
|
|
1
|
+
/** The connector node family, as flow-node-registry.ts lists it: an Integration Service connector operation, and a mid-flow event wait. */
|
|
2
2
|
import type { FlowNodeFamily } from '../../../flow-node-type.js';
|
|
3
3
|
export declare const connectorFlowFamily: FlowNodeFamily;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { eventWaitNodeType } from './event-wait.js';
|
|
1
2
|
import { connectorNodeType } from './node-type.js';
|
|
2
3
|
export const connectorFlowFamily = {
|
|
3
4
|
id: 'connector',
|
|
4
5
|
title: 'Integration Service connector',
|
|
5
|
-
types: [connectorNodeType],
|
|
6
|
-
// Its rules' codes are the pipeline's, shared with
|
|
6
|
+
types: [connectorNodeType, eventWaitNodeType],
|
|
7
|
+
// Its rules' codes are the pipeline's, shared with the triggers (ctx.connector, ctx.eventSubscription).
|
|
7
8
|
diagnostics: {},
|
|
8
9
|
};
|
|
@@ -33,6 +33,9 @@ export const PROCESS_DIAGNOSTICS = {
|
|
|
33
33
|
AGENTIC_RESERVED_INPUT: { severity: 'error', summary: 'an agentic process step with the reserved fireAndForget input' },
|
|
34
34
|
APIWF_EMPTY_RETURNS: { severity: 'warning', summary: 'an API workflow step with returns: {}' },
|
|
35
35
|
APIWF_KEY_NOT_KEY: { severity: 'error', summary: 'an API workflow step whose key is not a GUID' },
|
|
36
|
+
APIWF_LOCAL_HAS_FOLDER: { severity: 'error', summary: 'an API workflow step in-solution, with a folderPath' },
|
|
37
|
+
APIWF_LOCAL_NO_PROJECT_ID: { severity: 'error', summary: 'an API workflow step in-solution, with no projectId' },
|
|
38
|
+
APIWF_LOCAL_PROJECT_ID_NOT_GUID: { severity: 'error', summary: 'an API workflow step in-solution, with a projectId that is not a GUID' },
|
|
36
39
|
APIWF_NAME_IS_PATH: { severity: 'error', summary: 'an API workflow step whose name looks like a folder path' },
|
|
37
40
|
APIWF_NO_FOLDER: { severity: 'error', summary: 'an API workflow step with no folderPath' },
|
|
38
41
|
APIWF_NO_KEY: { severity: 'error', summary: 'an API workflow step with no key' },
|
|
@@ -157,10 +160,21 @@ export function checkApiWorkflow(inputs, ctx) {
|
|
|
157
160
|
at('APIWF_NO_NAME', `API workflow step "${step}" has no \`name\`. The runtime starts the job by name + folder, not by the `
|
|
158
161
|
+ `key in the node type, so without it the workflow cannot be resolved and the run fails before dispatch.`, `name: 'NameToAgeFixed'`);
|
|
159
162
|
}
|
|
160
|
-
|
|
163
|
+
const inSolution = inputs?.location === 'in-solution';
|
|
164
|
+
if (!inSolution && blank(inputs?.folderPath)) {
|
|
161
165
|
at('APIWF_NO_FOLDER', `API workflow step "${step}" has no \`folderPath\`. The runtime starts the job by name + folder, so the `
|
|
162
|
-
+ `Orchestrator folder holding the workflow is required
|
|
166
|
+
+ `Orchestrator folder holding the workflow is required. For an API workflow in the SAME solution, set `
|
|
167
|
+
+ `\`location: 'in-solution'\` and its \`projectId\` instead.`, `folderPath: 'Shared'`);
|
|
168
|
+
}
|
|
169
|
+
if (inSolution && blank(inputs?.projectId)) {
|
|
170
|
+
at('APIWF_LOCAL_NO_PROJECT_ID', `In-solution API workflow step "${step}" has no \`projectId\`. Read \`resource.projectKey\` from `
|
|
171
|
+
+ `\`resources/solution_folder/process/api/<project>.json\`.`, `projectId: '<resource.projectKey>'`);
|
|
172
|
+
}
|
|
173
|
+
else if (inSolution && !GUID_RE.test(String(inputs.projectId).trim())) {
|
|
174
|
+
at('APIWF_LOCAL_PROJECT_ID_NOT_GUID', `In-solution API workflow step "${step}" has projectId ${JSON.stringify(inputs.projectId)}, which is not `
|
|
175
|
+
+ `the sibling project's GUID. Read \`resource.projectKey\` from the generated resource file.`, `projectId: '<resource.projectKey>'`);
|
|
163
176
|
}
|
|
177
|
+
// A folderPath beside in-solution is the serializer's APIWF_LOCAL_HAS_FOLDER (refusals.ts).
|
|
164
178
|
const name = typeof inputs?.name === 'string' ? inputs.name.trim() : '';
|
|
165
179
|
if (name.includes('/')) {
|
|
166
180
|
at('APIWF_NAME_IS_PATH', `API workflow step "${step}"'s \`name\` is ${JSON.stringify(inputs.name)}, which is a folder path. `
|
|
@@ -176,7 +176,8 @@ const API_WORKFLOW_PREFIX = 'uipath.core.api-workflow.';
|
|
|
176
176
|
* one the platform's own definition writes.
|
|
177
177
|
*/
|
|
178
178
|
function apiWorkflowDef(spec) {
|
|
179
|
-
const
|
|
179
|
+
const loc = processResourceLocation(spec);
|
|
180
|
+
const { resourceKey } = loc;
|
|
180
181
|
const properties = {};
|
|
181
182
|
for (const [k, v] of Object.entries(spec.inputs)) {
|
|
182
183
|
properties[k] = { type: typeof v === 'number' ? 'number' : typeof v === 'boolean' ? 'boolean' : 'string' };
|
|
@@ -186,8 +187,8 @@ function apiWorkflowDef(spec) {
|
|
|
186
187
|
version: '1.0.0',
|
|
187
188
|
category: 'api-workflow',
|
|
188
189
|
runtimeConstraints: { exclude: ['api-function'] },
|
|
189
|
-
description:
|
|
190
|
-
tags:
|
|
190
|
+
description: loc.description,
|
|
191
|
+
tags: loc.tags,
|
|
191
192
|
sortOrder: resourceNodeSortOrder('api-workflow'),
|
|
192
193
|
supportsErrorHandling: true,
|
|
193
194
|
display: { label: spec.name, icon: 'api' },
|
|
@@ -195,11 +196,12 @@ function apiWorkflowDef(spec) {
|
|
|
195
196
|
{ position: 'left', handles: [{ id: 'input', type: 'target', handleType: 'input' }] },
|
|
196
197
|
{ position: 'right', handles: [{ id: 'output', type: 'source', handleType: 'output' }] },
|
|
197
198
|
],
|
|
199
|
+
...loc.definitionExtras,
|
|
198
200
|
model: {
|
|
199
201
|
type: 'bpmn:ServiceTask',
|
|
200
202
|
serviceType: 'Orchestrator.ExecuteApiWorkflowAsync',
|
|
201
203
|
version: 'v2',
|
|
202
|
-
section: 'Published',
|
|
204
|
+
...(loc.inSolution ? {} : { section: 'Published' }),
|
|
203
205
|
bindings: {
|
|
204
206
|
resource: 'process',
|
|
205
207
|
resourceSubType: 'Api',
|
|
@@ -207,9 +209,10 @@ function apiWorkflowDef(spec) {
|
|
|
207
209
|
orchestratorType: 'api',
|
|
208
210
|
values: [
|
|
209
211
|
{ name: 'name', propertyAttribute: 'name', default: spec.name },
|
|
210
|
-
{ name: 'folderPath', propertyAttribute: 'folderPath', default:
|
|
212
|
+
{ name: 'folderPath', propertyAttribute: 'folderPath', default: loc.folderPath },
|
|
211
213
|
],
|
|
212
214
|
},
|
|
215
|
+
...loc.modelExtras,
|
|
213
216
|
context: [
|
|
214
217
|
{ name: 'name', type: 'string', value: '<bindings.name>' },
|
|
215
218
|
{ name: 'folderPath', type: 'string', value: '<bindings.folderPath>' },
|
|
@@ -611,7 +614,10 @@ export function processDefinition(spec) {
|
|
|
611
614
|
inputs: s.inputs ?? {}, returns: s.returns,
|
|
612
615
|
});
|
|
613
616
|
case 'apiWorkflow':
|
|
614
|
-
return apiWorkflowDef({
|
|
617
|
+
return apiWorkflowDef({
|
|
618
|
+
key: s.key, name: s.name, folderPath: s.folderPath, location: s.location, projectId: s.projectId,
|
|
619
|
+
inputs: s.inputs ?? {}, returns: s.returns,
|
|
620
|
+
});
|
|
615
621
|
case 'agenticProcess':
|
|
616
622
|
return agenticProcessDef({
|
|
617
623
|
key: s.key, name: s.name, folderPath: s.folderPath, location: s.location, projectId: s.projectId,
|
|
@@ -723,11 +729,14 @@ function liftProcess(node, ctx, prefix, kind, form) {
|
|
|
723
729
|
const name = binding('name');
|
|
724
730
|
const folderPath = binding('folderPath');
|
|
725
731
|
// A sibling project of the same solution (#951): the model names its project
|
|
726
|
-
// instead of a folder. `isInSolution` is flow-core's marker
|
|
727
|
-
// `
|
|
728
|
-
//
|
|
732
|
+
// instead of a folder. `isInSolution` is flow-core's marker; files that carry
|
|
733
|
+
// `projectName` but neither it nor `projectId` still carry the `in-solution`
|
|
734
|
+
// tag and an empty folder. Read back as `location: 'in-solution'` so the
|
|
735
|
+
// recompile takes the in-solution path instead of a published one with an
|
|
736
|
+
// empty folder (#1396). A tag beside a real folder is not enough.
|
|
729
737
|
const projectId = typeof def?.model?.projectId === 'string' ? def.model.projectId : undefined;
|
|
730
|
-
const inSolution = def?.model?.isInSolution === true || projectId !== undefined
|
|
738
|
+
const inSolution = def?.model?.isInSolution === true || projectId !== undefined
|
|
739
|
+
|| (Array.isArray(def?.tags) && def.tags.includes('in-solution') && !folderPath);
|
|
731
740
|
const inputs = { ...(n.inputs ?? {}) };
|
|
732
741
|
// The design-time fire-and-forget switch is an OPTION on agenticProcess(),
|
|
733
742
|
// not a process argument — serialize adds it to `inputs` after rendering the
|
|
@@ -25,7 +25,7 @@ const KINDS = {
|
|
|
25
25
|
noKeySuggestion: `key: '486edc26-0658-4ac1-92c9-1ef953927151'`,
|
|
26
26
|
},
|
|
27
27
|
apiWorkflow: {
|
|
28
|
-
noKeyCode: 'APIWF_NO_KEY', label: 'API workflow', oldField: 'workflow',
|
|
28
|
+
noKeyCode: 'APIWF_NO_KEY', localCode: 'APIWF_LOCAL_HAS_FOLDER', label: 'API workflow', oldField: 'workflow', localLabel: 'API workflow step',
|
|
29
29
|
noKey: (step) => `API workflow step "${step}" has no \`key\`. That is the published workflow's key (a GUID), and `
|
|
30
30
|
+ `it becomes part of the node's type — without it there is no workflow to invoke. Find it with `
|
|
31
31
|
+ `\`uip or processes list --all-folders\` (an API workflow's ProcessKey reads "<name>.api.<name>").`,
|
|
@@ -74,12 +74,38 @@ export interface ApiWorkflowInputs {
|
|
|
74
74
|
* `uip or processes list --all-folders --process-type Api` (an API workflow's
|
|
75
75
|
* `ProcessKey` reads `<name>.api.<name>`; the GUID you want is the row's `Key`)
|
|
76
76
|
* or `uip maestro flow registry search`.
|
|
77
|
+
*
|
|
78
|
+
* For an in-solution sibling it is `resource.key` from
|
|
79
|
+
* `resources/solution_folder/process/api/<project>.json`, the suffix of the
|
|
80
|
+
* node type `uip maestro flow registry list --local` shows.
|
|
77
81
|
*/
|
|
78
82
|
key: string;
|
|
79
83
|
/** The workflow's name in Orchestrator — e.g. `'NameToAgeFixed'`. */
|
|
80
84
|
name: string;
|
|
81
|
-
/**
|
|
82
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Where the workflow lives. `'published'` (the default) is a workflow
|
|
87
|
+
* deployed to `folderPath`. `'in-solution'` is a sibling API workflow project
|
|
88
|
+
* of the same solution: it needs `projectId` and no `folderPath`, and `key` is
|
|
89
|
+
* that sibling's `resource.key`.
|
|
90
|
+
*/
|
|
91
|
+
location?: ProcessLocation;
|
|
92
|
+
/**
|
|
93
|
+
* The Orchestrator folder holding it — e.g. `'Shared'`. Required for a
|
|
94
|
+
* published workflow; omit it for an in-solution sibling.
|
|
95
|
+
*
|
|
96
|
+
* @enforcedBy APIWF_NO_FOLDER A published API workflow needs its folder.
|
|
97
|
+
* @enforcedBy APIWF_LOCAL_HAS_FOLDER An in-solution API workflow has no folder.
|
|
98
|
+
*/
|
|
99
|
+
folderPath?: string;
|
|
100
|
+
/**
|
|
101
|
+
* The sibling API workflow project's `resource.projectKey`, read from
|
|
102
|
+
* `resources/solution_folder/process/api/<project>.json`. Required only when
|
|
103
|
+
* `location` is `'in-solution'`.
|
|
104
|
+
*
|
|
105
|
+
* @enforcedBy APIWF_LOCAL_NO_PROJECT_ID An in-solution API workflow needs its project id.
|
|
106
|
+
* @enforcedBy APIWF_LOCAL_PROJECT_ID_NOT_GUID The project id is the sibling's GUID, not its name.
|
|
107
|
+
*/
|
|
108
|
+
projectId?: string;
|
|
83
109
|
/**
|
|
84
110
|
* The WORKFLOW's own input arguments, by its own argument names (e.g.
|
|
85
111
|
* `{ name: 'tomasz' }`). Not a fixed schema — every workflow declares its own.
|