@uipath/packager-tool-bpmn 1.201.0 → 1.202.0-preview.136

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.
@@ -6,9 +6,11 @@ import { type IFileSystem, type IToolLogger, ProjectTool, ToolResult } from "@ui
6
6
  export declare class BpmnTool extends ProjectTool {
7
7
  private readonly _temporaryStorage;
8
8
  private readonly _validateService;
9
+ private readonly _packValidateService;
9
10
  constructor(fileSystem: IFileSystem, logger: IToolLogger);
10
11
  restoreAsync(_options: IProjectRestoreOptions, _cancellationToken?: AbortSignal): Promise<ToolResult>;
11
12
  validateAsync(options: IProjectValidateOptions, _cancellationToken?: AbortSignal): Promise<ToolResult>;
13
+ private runValidation;
12
14
  buildAsync(options: IProjectBuildOptions, _cancellationToken?: AbortSignal): Promise<ToolResult>;
13
15
  packAsync(options: IProjectPackOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
14
16
  dispose(): Promise<void>;
package/dist/index.js CHANGED
@@ -17,19 +17,19 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
17
  // ../../maestro-sdk/dist/bpmn-packaging/index.js
18
18
  var exports_bpmn_packaging = {};
19
19
  __export(exports_bpmn_packaging, {
20
- required: () => required,
21
- parseOptionalJson: () => parseOptionalJson,
22
- parseJson: () => parseJson,
23
- parseBpmnProcesses: () => parseBpmnProcesses,
24
- isJsonObject: () => isJsonObject,
25
- formatBpmnPackageFile: () => formatBpmnPackageFile,
26
- extensionValues: () => extensionValues,
27
- entryPointDisplayName: () => entryPointDisplayName,
28
- deriveBpmnEntryPoints: () => deriveBpmnEntryPoints,
29
- childNodes: () => childNodes,
30
- buildConnectionResources: () => buildConnectionResources,
20
+ BPMN_PACKAGE_FILES: () => BPMN_PACKAGE_FILES,
31
21
  buildBpmnPackageMetadata: () => buildBpmnPackageMetadata,
32
- BPMN_PACKAGE_FILES: () => BPMN_PACKAGE_FILES
22
+ buildConnectionResources: () => buildConnectionResources,
23
+ childNodes: () => childNodes,
24
+ deriveBpmnEntryPoints: () => deriveBpmnEntryPoints,
25
+ entryPointDisplayName: () => entryPointDisplayName,
26
+ extensionValues: () => extensionValues,
27
+ formatBpmnPackageFile: () => formatBpmnPackageFile,
28
+ isJsonObject: () => isJsonObject,
29
+ parseBpmnProcesses: () => parseBpmnProcesses,
30
+ parseJson: () => parseJson,
31
+ parseOptionalJson: () => parseOptionalJson,
32
+ required: () => required
33
33
  });
34
34
  function isGuid2(value) {
35
35
  return GUID_REGEX2.test(value);
@@ -57,26 +57,34 @@ function buildConnectionResources(processes, existingResources) {
57
57
  const connectionBindings = childNodes(extensionValues(process).find((node) => node.$type === "uipath:bindings")).filter((node) => node.$type === "uipath:binding" && node.resource === "Connection" && node.propertyAttribute === "ConnectionId").map(toConnectionBinding);
58
58
  const bindingById = new Map(connectionBindings.map((binding) => [binding.id, binding]));
59
59
  for (const element of allFlowElements(process)) {
60
- const activity = extensionValues(element).find((node) => node.$type === "uipath:activity");
61
- const type = childNodes(activity).find((node) => node.$type === "uipath:type");
62
- if (type?.value !== "Intsvc.ActivityExecution") {
60
+ const payload = extensionValues(element).find((node) => node.$type === "uipath:activity" || node.$type === "uipath:event");
61
+ const extensionType = childNodes(payload).find((node) => node.$type === "uipath:type")?.value;
62
+ if (extensionType === undefined || !CONNECTION_CONNECTOR_TYPES.has(extensionType)) {
63
63
  continue;
64
64
  }
65
- const context = childNodes(activity).find((node) => node.$type === "uipath:context");
66
- const values = new Map(childNodes(context).filter((node) => node.$type === "uipath:input" && node.name).map((node) => [
65
+ const context = childNodes(payload).find((node) => node.$type === "uipath:context");
66
+ const values = new Map([...childNodes(context), ...childNodes(payload)].filter((node) => node.$type === "uipath:input" && node.name).map((node) => [
67
67
  node.name,
68
68
  node.value ?? node.$body
69
69
  ]));
70
- if (!isIntsvcActivityExecutionV12(values.get("activityConfigurationVersion"), workflowActivityConfigurationVersion)) {
70
+ if (extensionType === "Intsvc.ActivityExecution" && !isIntsvcActivityExecutionV12(values.get("activityConfigurationVersion"), workflowActivityConfigurationVersion)) {
71
71
  continue;
72
72
  }
73
- const activityId = required(element.id, "Integration Service activity id");
73
+ const connectionRef = [
74
+ values.get("connection"),
75
+ values.get("connectionId")
76
+ ].find((value) => value?.trim());
77
+ if (connectionRef === undefined && extensionType !== "Intsvc.ActivityExecution") {
78
+ continue;
79
+ }
80
+ const nodeLabel = extensionType === "Intsvc.EventTrigger" ? "Trigger" : extensionType === "Intsvc.WaitForEvent" ? "Wait" : "Activity";
81
+ const activityId = required(element.id, `Integration Service ${nodeLabel.toLowerCase()} id`);
74
82
  const activityDisplayName = element.name?.trim() || activityId;
75
- const connector = required(values.get("connectorKey"), `Activity "${activityDisplayName}" connectorKey`);
76
- const bindingId = bindingReference(values.get("connection"), activityDisplayName);
83
+ const connector = required(values.get("connectorKey"), `${nodeLabel} "${activityDisplayName}" connectorKey`);
84
+ const bindingId = bindingReference(connectionRef, activityDisplayName, nodeLabel);
77
85
  const binding = bindingById.get(bindingId);
78
86
  if (!binding) {
79
- throw new Error(`Activity "${activityDisplayName}" references missing Connection binding "${bindingId}".`);
87
+ throw new Error(`${nodeLabel} "${activityDisplayName}" references missing Connection binding "${bindingId}".`);
80
88
  }
81
89
  const current = connectionResource({
82
90
  activityId,
@@ -87,7 +95,7 @@ function buildConnectionResources(processes, existingResources) {
87
95
  const prior = generated.get(binding.resourceKey);
88
96
  if (prior) {
89
97
  if (prior.metadata.Connector !== connector || prior.value.ConnectionId.defaultValue !== binding.connectionId) {
90
- throw new Error(`Connection resource "${binding.resourceKey}" is used by Integration Service activities with different connectors or connections.`);
98
+ throw new Error(`Connection resource "${binding.resourceKey}" is used by Integration Service nodes with different connectors or connections.`);
91
99
  }
92
100
  continue;
93
101
  }
@@ -146,10 +154,10 @@ function allFlowElements(element) {
146
154
  }
147
155
  return result;
148
156
  }
149
- function bindingReference(value, activity) {
157
+ function bindingReference(value, nodeName, nodeLabel) {
150
158
  const match = /^=bindings\.([A-Za-z_][\w.-]*)$/.exec(value ?? "");
151
159
  if (!match) {
152
- throw new Error(`Activity "${activity}" connection must reference a root binding as "=bindings.<id>".`);
160
+ throw new Error(`${nodeLabel} "${nodeName}" connection must reference a root binding as "=bindings.<id>".`);
153
161
  }
154
162
  return match[1];
155
163
  }
@@ -1451,7 +1459,7 @@ function parseJson(raw, label) {
1451
1459
  }
1452
1460
  return value;
1453
1461
  }
1454
- var GUID_REGEX2, bpmn_spec_default2, BPMN_SPEC2, STATIC_UIPATH_EXTENSION_TAG_NAMES2, SUPPORTED_UIPATH_EXTENSION_TAG_NAMES2, SUPPORTED_UIPATH_EXTENSION_TAGS2, KNOWN_UIPATH_TAGS2, ACTIVITY_CONFIGURATION_V12 = "v1", nativeToString, nativeHasOwnProperty, BUILTINS, TYPE_CONVERTERS, fromCharCode, hasOwnProperty, ENTITY_PATTERN, ENTITY_MAPPING, NON_WHITESPACE_OUTSIDE_ROOT_NODE = "non-whitespace outside of root node", DEFAULT_NS_MAP, SERIALIZE_PROPERTY = "property", XML_PREAMBLE = `<?xml version="1.0" encoding="UTF-8"?>
1462
+ var GUID_REGEX2, bpmn_spec_default2, BPMN_SPEC2, STATIC_UIPATH_EXTENSION_TAG_NAMES2, SUPPORTED_UIPATH_EXTENSION_TAG_NAMES2, SUPPORTED_UIPATH_EXTENSION_TAGS2, KNOWN_UIPATH_TAGS2, CALL_ACTIVITY_TYPES2, CALL_ACTIVITY_PAYLOAD_TAGS2, ACTIVITY_CONFIGURATION_V12 = "v1", FREE_TEXT_ELEMENTS2, CONNECTION_CONNECTOR_TYPES, nativeToString, nativeHasOwnProperty, BUILTINS, TYPE_CONVERTERS, fromCharCode, hasOwnProperty, ENTITY_PATTERN, ENTITY_MAPPING, NON_WHITESPACE_OUTSIDE_ROOT_NODE = "non-whitespace outside of root node", DEFAULT_NS_MAP, SERIALIZE_PROPERTY = "property", XML_PREAMBLE = `<?xml version="1.0" encoding="UTF-8"?>
1455
1463
  `, ESCAPE_ATTR_CHARS, ESCAPE_CHARS, ESCAPE_ATTR_MAP, ESCAPE_MAP, name$5 = "BPMN20", uri$5 = "http://www.omg.org/spec/BPMN/20100524/MODEL", prefix$5 = "bpmn", associations$5, types$5, enumerations$3, xml$1, BpmnPackage, name$4 = "BPMNDI", uri$4 = "http://www.omg.org/spec/BPMN/20100524/DI", prefix$4 = "bpmndi", types$4, enumerations$2, associations$4, BpmnDiPackage, name$3 = "DC", uri$3 = "http://www.omg.org/spec/DD/20100524/DC", prefix$3 = "dc", types$3, associations$3, DcPackage, name$2 = "DI", uri$2 = "http://www.omg.org/spec/DD/20100524/DI", prefix$2 = "di", types$2, associations$2, xml, DiPackage, name$1 = "bpmn.io colors for BPMN", uri$1 = "http://bpmn.io/schema/bpmn/biocolor/1.0", prefix$1 = "bioc", types$1, enumerations$1, associations$1, BiocPackage, name = "BPMN in Color", uri = "http://www.omg.org/spec/BPMN/non-normative/color/1.0", prefix = "color", types, enumerations, associations, BpmnInColorPackage, packages, BPMN_PACKAGE_FILES, SCHEMA_ANNOTATIONS;
1456
1464
  var init_bpmn_packaging = __esm(() => {
1457
1465
  GUID_REGEX2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -2237,6 +2245,15 @@ var init_bpmn_packaging = __esm(() => {
2237
2245
  <bpmn:extensionElements>
2238
2246
  <uipath:event version="v1">
2239
2247
  <uipath:type value="Intsvc.WaitForEvent" version="v1" />
2248
+ <uipath:context>
2249
+ <uipath:input name="connectorKey" type="string" value="{connectorKey}" />
2250
+ <uipath:input name="connectionId" type="string" value="=bindings.{connectionBindingId}" />
2251
+ <uipath:input name="folderId" type="string" value="{folderId}" />
2252
+ <uipath:input name="folderPath" type="string" value="{folderPath}" />
2253
+ <uipath:input name="folderKey" type="string" value="{folderKey}" />
2254
+ <uipath:input name="operation" type="string" value="{operation}" />
2255
+ <uipath:input name="objectName" type="string" value="{objectName}" />
2256
+ </uipath:context>
2240
2257
  <uipath:output name="result" type="custom" source="." var="{varId}" />
2241
2258
  </uipath:event>
2242
2259
  </bpmn:extensionElements>
@@ -2257,7 +2274,12 @@ var init_bpmn_packaging = __esm(() => {
2257
2274
  isPrimaryKey: false,
2258
2275
  binding: true,
2259
2276
  defaultValue: null,
2260
- description: "Connection ID for the IS connector (bindable)"
2277
+ description: "Connection ID for the IS connector (bindable)",
2278
+ bindingInfo: {
2279
+ resource: "Connection",
2280
+ resourceKeyPattern: "${resourceKey}",
2281
+ propertyAttribute: "ConnectionId"
2282
+ }
2261
2283
  },
2262
2284
  {
2263
2285
  name: "connectorKey",
@@ -2375,6 +2397,15 @@ var init_bpmn_packaging = __esm(() => {
2375
2397
  <bpmn:extensionElements>
2376
2398
  <uipath:event version="v1">
2377
2399
  <uipath:type value="Intsvc.EventTrigger" version="v1" />
2400
+ <uipath:context>
2401
+ <uipath:input name="connectorKey" type="string" value="{connectorKey}" />
2402
+ <uipath:input name="connectionId" type="string" value="=bindings.{connectionBindingId}" />
2403
+ <uipath:input name="folderId" type="string" value="{folderId}" />
2404
+ <uipath:input name="folderPath" type="string" value="{folderPath}" />
2405
+ <uipath:input name="folderKey" type="string" value="{folderKey}" />
2406
+ <uipath:input name="operation" type="string" value="{operation}" />
2407
+ <uipath:input name="objectName" type="string" value="{objectName}" />
2408
+ </uipath:context>
2378
2409
  <uipath:output name="result" type="custom" source="." var="{varId}" />
2379
2410
  </uipath:event>
2380
2411
  </bpmn:extensionElements>
@@ -2396,7 +2427,12 @@ var init_bpmn_packaging = __esm(() => {
2396
2427
  isPrimaryKey: false,
2397
2428
  binding: true,
2398
2429
  defaultValue: null,
2399
- description: "Connection ID for the IS connector (bindable)"
2430
+ description: "Connection ID for the IS connector (bindable)",
2431
+ bindingInfo: {
2432
+ resource: "Connection",
2433
+ resourceKeyPattern: "${resourceKey}",
2434
+ propertyAttribute: "ConnectionId"
2435
+ }
2400
2436
  },
2401
2437
  {
2402
2438
  name: "connectorKey",
@@ -4455,6 +4491,14 @@ var init_bpmn_packaging = __esm(() => {
4455
4491
  ].sort());
4456
4492
  SUPPORTED_UIPATH_EXTENSION_TAGS2 = Object.freeze(SUPPORTED_UIPATH_EXTENSION_TAG_NAMES2.map((tag) => `uipath:${tag}`));
4457
4493
  KNOWN_UIPATH_TAGS2 = new Set(SUPPORTED_UIPATH_EXTENSION_TAGS2);
4494
+ CALL_ACTIVITY_TYPES2 = Object.entries(BPMN_SPEC2.extensionTypes).filter(([, contract]) => contract.bpmnElement === "bpmn:CallActivity").map(([type]) => type).sort((a, b) => a.localeCompare(b));
4495
+ CALL_ACTIVITY_PAYLOAD_TAGS2 = new Set(Object.values(BPMN_SPEC2.extensionTypes).filter((contract) => contract.bpmnElement === "bpmn:CallActivity").map((contract) => contract.extensionTag).filter((tag) => typeof tag === "string"));
4496
+ FREE_TEXT_ELEMENTS2 = new Set(["documentation", "text"]);
4497
+ CONNECTION_CONNECTOR_TYPES = new Set([
4498
+ "Intsvc.ActivityExecution",
4499
+ "Intsvc.EventTrigger",
4500
+ "Intsvc.WaitForEvent"
4501
+ ]);
4458
4502
  nativeToString = Object.prototype.toString;
4459
4503
  nativeHasOwnProperty = Object.prototype.hasOwnProperty;
4460
4504
  Base.prototype.get = function(name) {
@@ -9304,6 +9348,14 @@ import {
9304
9348
 
9305
9349
  // ../../maestro-sdk/dist/bpmn-validation/project-validator.js
9306
9350
  var {createRequire} = (() => ({}));
9351
+ var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
9352
+ function isGuid(value) {
9353
+ return GUID_REGEX.test(value);
9354
+ }
9355
+ var GUID_REGEX;
9356
+ var init_guid = __esm2(() => {
9357
+ GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
9358
+ });
9307
9359
  var bpmn_spec_default = {
9308
9360
  version: "1.0.0",
9309
9361
  source: "PO.Frontend registry generator (2026-04-14) + CLI notes",
@@ -10086,6 +10138,15 @@ var bpmn_spec_default = {
10086
10138
  <bpmn:extensionElements>
10087
10139
  <uipath:event version="v1">
10088
10140
  <uipath:type value="Intsvc.WaitForEvent" version="v1" />
10141
+ <uipath:context>
10142
+ <uipath:input name="connectorKey" type="string" value="{connectorKey}" />
10143
+ <uipath:input name="connectionId" type="string" value="=bindings.{connectionBindingId}" />
10144
+ <uipath:input name="folderId" type="string" value="{folderId}" />
10145
+ <uipath:input name="folderPath" type="string" value="{folderPath}" />
10146
+ <uipath:input name="folderKey" type="string" value="{folderKey}" />
10147
+ <uipath:input name="operation" type="string" value="{operation}" />
10148
+ <uipath:input name="objectName" type="string" value="{objectName}" />
10149
+ </uipath:context>
10089
10150
  <uipath:output name="result" type="custom" source="." var="{varId}" />
10090
10151
  </uipath:event>
10091
10152
  </bpmn:extensionElements>
@@ -10106,7 +10167,12 @@ var bpmn_spec_default = {
10106
10167
  isPrimaryKey: false,
10107
10168
  binding: true,
10108
10169
  defaultValue: null,
10109
- description: "Connection ID for the IS connector (bindable)"
10170
+ description: "Connection ID for the IS connector (bindable)",
10171
+ bindingInfo: {
10172
+ resource: "Connection",
10173
+ resourceKeyPattern: "${resourceKey}",
10174
+ propertyAttribute: "ConnectionId"
10175
+ }
10110
10176
  },
10111
10177
  {
10112
10178
  name: "connectorKey",
@@ -10224,6 +10290,15 @@ var bpmn_spec_default = {
10224
10290
  <bpmn:extensionElements>
10225
10291
  <uipath:event version="v1">
10226
10292
  <uipath:type value="Intsvc.EventTrigger" version="v1" />
10293
+ <uipath:context>
10294
+ <uipath:input name="connectorKey" type="string" value="{connectorKey}" />
10295
+ <uipath:input name="connectionId" type="string" value="=bindings.{connectionBindingId}" />
10296
+ <uipath:input name="folderId" type="string" value="{folderId}" />
10297
+ <uipath:input name="folderPath" type="string" value="{folderPath}" />
10298
+ <uipath:input name="folderKey" type="string" value="{folderKey}" />
10299
+ <uipath:input name="operation" type="string" value="{operation}" />
10300
+ <uipath:input name="objectName" type="string" value="{objectName}" />
10301
+ </uipath:context>
10227
10302
  <uipath:output name="result" type="custom" source="." var="{varId}" />
10228
10303
  </uipath:event>
10229
10304
  </bpmn:extensionElements>
@@ -10245,7 +10320,12 @@ var bpmn_spec_default = {
10245
10320
  isPrimaryKey: false,
10246
10321
  binding: true,
10247
10322
  defaultValue: null,
10248
- description: "Connection ID for the IS connector (bindable)"
10323
+ description: "Connection ID for the IS connector (bindable)",
10324
+ bindingInfo: {
10325
+ resource: "Connection",
10326
+ resourceKeyPattern: "${resourceKey}",
10327
+ propertyAttribute: "ConnectionId"
10328
+ }
10249
10329
  },
10250
10330
  {
10251
10331
  name: "connectorKey",
@@ -12303,11 +12383,10 @@ var SUPPORTED_UIPATH_EXTENSION_TAG_NAMES = Object.freeze([
12303
12383
  ])
12304
12384
  ].sort());
12305
12385
  var SUPPORTED_UIPATH_EXTENSION_TAGS = Object.freeze(SUPPORTED_UIPATH_EXTENSION_TAG_NAMES.map((tag) => `uipath:${tag}`));
12306
- var GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
12307
- function isGuid(value) {
12308
- return GUID_REGEX.test(value);
12309
- }
12386
+ init_guid();
12310
12387
  var KNOWN_UIPATH_TAGS = new Set(SUPPORTED_UIPATH_EXTENSION_TAGS);
12388
+ var CALL_ACTIVITY_TYPES = Object.entries(BPMN_SPEC.extensionTypes).filter(([, contract]) => contract.bpmnElement === "bpmn:CallActivity").map(([type]) => type).sort((a, b) => a.localeCompare(b));
12389
+ var CALL_ACTIVITY_PAYLOAD_TAGS = new Set(Object.values(BPMN_SPEC.extensionTypes).filter((contract) => contract.bpmnElement === "bpmn:CallActivity").map((contract) => contract.extensionTag).filter((tag) => typeof tag === "string"));
12311
12390
  var SEMANTIC_VALIDATION_ERROR = "BPMN_VALIDATION_ERROR";
12312
12391
  var BPMN_MODEL_NAMESPACE = "http://www.omg.org/spec/BPMN/20100524/MODEL";
12313
12392
  var ACTIVITY_CONFIGURATION_VERSION = "activityConfigurationVersion";
@@ -12420,6 +12499,84 @@ class BpmnValidateService {
12420
12499
  const availableBindings = new Map(bindings);
12421
12500
  collectInlineBindings(definitions, availableBindings);
12422
12501
  this.validateUiPathTags(file, definitions, availableBindings, diagnostics);
12502
+ this.validateUnassignedVariables(file, definitions, diagnostics);
12503
+ this.validateCallActivityReferences(file, definitions, diagnostics);
12504
+ }
12505
+ validateUnassignedVariables(file, definitions, diagnostics) {
12506
+ for (const process of findChildren(definitions, (node) => hasLocalName(node, "process"))) {
12507
+ this.reportUnassignedVariables(file, process, diagnostics);
12508
+ }
12509
+ }
12510
+ reportUnassignedVariables(file, process, diagnostics) {
12511
+ const startEventIds = new Set(findChildren(process, (node) => hasLocalName(node, "startEvent")).filter(isManualStartEvent).map((node) => node.attributes.id).filter((id) => Boolean(id)));
12512
+ const declaredById = new Map;
12513
+ for (const block of findDescendants(process, (node) => hasLocalName(node, "variables"))) {
12514
+ for (const decl of block.children) {
12515
+ const declKind = getLocalName(decl.name);
12516
+ if (declKind !== "input" && declKind !== "inputoutput" && declKind !== "output") {
12517
+ continue;
12518
+ }
12519
+ const id = decl.attributes.id;
12520
+ if (!id) {
12521
+ continue;
12522
+ }
12523
+ const elementId = decl.attributes.elementId?.trim() ?? "";
12524
+ const callerCanSupply = declKind === "input" && !!decl.attributes.name?.trim() && startEventIds.has(elementId);
12525
+ declaredById.set(id, {
12526
+ hasValueSource: !!decl.attributes.default?.trim() || callerCanSupply,
12527
+ declKind,
12528
+ element: describeElement(decl)
12529
+ });
12530
+ }
12531
+ }
12532
+ if (declaredById.size === 0) {
12533
+ return;
12534
+ }
12535
+ const assigned = new Set;
12536
+ for (const output of findDescendants(process, (node) => hasLocalName(node, "output"))) {
12537
+ const target = output.attributes.var;
12538
+ const isDeclaration = output.parent !== undefined && hasLocalName(output.parent, "variables");
12539
+ if (target && !isDeclaration) {
12540
+ assigned.add(target);
12541
+ }
12542
+ }
12543
+ for (const id of collectVariableReads(process)) {
12544
+ const declared = declaredById.get(id);
12545
+ if (!declared || declared.hasValueSource || assigned.has(id)) {
12546
+ continue;
12547
+ }
12548
+ diagnostics.push({
12549
+ file,
12550
+ element: declared.element,
12551
+ message: `Variable "vars.${id}" is read but never assigned; it will be empty at run time.`,
12552
+ instruction: declared.declKind === "input" ? "Give the variable a default, assign it through a uipath:output mapping, or bind it to an entry-point start event by giving it both a name and an elementId." : "Give the variable a default, or assign it through a uipath:output mapping before it is read.",
12553
+ severity: "warning"
12554
+ });
12555
+ }
12556
+ }
12557
+ validateCallActivityReferences(file, definitions, diagnostics) {
12558
+ for (const callActivity of findDescendants(definitions, (node) => hasLocalName(node, "callActivity"))) {
12559
+ const hasUiPathPayload = findDescendants(callActivity, (node) => CALL_ACTIVITY_PAYLOAD_TAGS.has(node.name)).length > 0;
12560
+ const calledElement = callActivity.attributes.calledElement?.trim() ?? "";
12561
+ if (!hasUiPathPayload) {
12562
+ diagnostics.push({
12563
+ file,
12564
+ element: describeElement(callActivity),
12565
+ message: "Call activity has no uipath:activity payload, so it invokes nothing at run time.",
12566
+ instruction: `Add a payload naming one of the call-activity types (${CALL_ACTIVITY_TYPES.join(", ")}), with a process resource binding.`
12567
+ });
12568
+ continue;
12569
+ }
12570
+ if (calledElement) {
12571
+ diagnostics.push({
12572
+ file,
12573
+ element: describeElement(callActivity),
12574
+ message: `Call activity attribute calledElement="${calledElement}" is ignored; the invoked process comes from the uipath:activity payload and its process binding.`,
12575
+ instruction: "Remove calledElement, or ensure the uipath:activity payload names the process you intend to invoke.",
12576
+ severity: "warning"
12577
+ });
12578
+ }
12579
+ }
12423
12580
  }
12424
12581
  validateRootEntryPointIds(file, process, diagnostics) {
12425
12582
  const rootStartEvents = findChildren(process, (node) => hasLocalName(node, "startEvent"));
@@ -12522,12 +12679,13 @@ class BpmnValidateService {
12522
12679
  }
12523
12680
  const contract = BPMN_SPEC.extensionTypes[extensionType];
12524
12681
  if (!contract) {
12682
+ const severity = this.options.unsupportedExtensionTypeSeverity ?? "warning";
12525
12683
  diagnostics.push({
12526
12684
  file,
12527
12685
  element: describeElement(typeNode ?? payload),
12528
12686
  message: `Unsupported UiPath extension type "${extensionType}".`,
12529
- instruction: "Use an extension type present in the UiPath BPMN contract, or update the contract before packaging this project.",
12530
- severity: "warning"
12687
+ instruction: severity === "error" ? `"${extensionType}" is not in this CLI's BPMN contract, so Orchestrator will reject the package at deploy (Error 1654). Use a supported extension type, remove the node, or upgrade the CLI to a version whose contract includes it.` : "Use an extension type present in the UiPath BPMN contract, or update the contract before packaging this project.",
12688
+ severity
12531
12689
  });
12532
12690
  return;
12533
12691
  }
@@ -12540,6 +12698,9 @@ class BpmnValidateService {
12540
12698
  if (contract.extensionType === "Orchestrator.StartAgentJob") {
12541
12699
  this.validateStartAgentJobBindings(file, payload, owner, bindings, diagnostics);
12542
12700
  }
12701
+ if (contract.extensionType === "Intsvc.EventTrigger" || contract.extensionType === "Intsvc.WaitForEvent") {
12702
+ this.validateTriggerConnectionBinding(file, payload, owner, bindings, contract.extensionType === "Intsvc.WaitForEvent" ? "wait" : "trigger", diagnostics);
12703
+ }
12543
12704
  this.validateInputs(file, payload, owner, contract, diagnostics);
12544
12705
  this.validateOutput(file, payload, owner, contract, diagnostics);
12545
12706
  this.validateBindingReferences(file, payload, bindings, diagnostics);
@@ -12613,23 +12774,44 @@ class BpmnValidateService {
12613
12774
  }
12614
12775
  }
12615
12776
  validateActivityExecutionV1Bindings(file, payload, owner, bindings, diagnostics) {
12616
- const contextByName = new Map(getContextInputs(payload).map((input) => [
12617
- input.attributes.name,
12618
- input
12619
- ]));
12620
- const bindingFields = [
12777
+ const resourceKeys = this.validateConnectionBindings(file, payload, owner, bindings, diagnostics, "activity", [
12778
+ {
12779
+ contextName: "connection",
12780
+ propertyAttribute: "ConnectionId"
12781
+ },
12782
+ { contextName: "folderKey", propertyAttribute: "folderKey" }
12783
+ ]);
12784
+ const connectionResourceKey = resourceKeys.get("connection");
12785
+ const folderResourceKey = resourceKeys.get("folderKey");
12786
+ if (connectionResourceKey && folderResourceKey && connectionResourceKey !== folderResourceKey) {
12787
+ diagnostics.push({
12788
+ file,
12789
+ element: describeElement(owner),
12790
+ message: "Integration Service activity connection and folder bindings refer to different connection resources.",
12791
+ instruction: "Set the same resourceKey on both root bindings."
12792
+ });
12793
+ }
12794
+ }
12795
+ validateTriggerConnectionBinding(file, payload, owner, bindings, nodeLabel, diagnostics) {
12796
+ this.validateConnectionBindings(file, payload, owner, bindings, diagnostics, nodeLabel, [
12621
12797
  {
12622
12798
  contextName: "connection",
12623
12799
  propertyAttribute: "ConnectionId"
12624
12800
  },
12625
12801
  {
12626
- contextName: "folderKey",
12627
- propertyAttribute: "folderKey"
12802
+ contextName: "connectionId",
12803
+ propertyAttribute: "ConnectionId"
12628
12804
  }
12629
- ];
12805
+ ]);
12806
+ }
12807
+ validateConnectionBindings(file, payload, owner, bindings, diagnostics, nodeLabel, bindingFields) {
12808
+ const inputByName = new Map(getConnectorInputs(payload).map((input) => [
12809
+ input.attributes.name,
12810
+ input
12811
+ ]));
12630
12812
  const resourceKeys = new Map;
12631
12813
  for (const field of bindingFields) {
12632
- const contextInput = contextByName.get(field.contextName);
12814
+ const contextInput = inputByName.get(field.contextName);
12633
12815
  if (!contextInput) {
12634
12816
  continue;
12635
12817
  }
@@ -12641,7 +12823,7 @@ class BpmnValidateService {
12641
12823
  diagnostics.push({
12642
12824
  file,
12643
12825
  element: describeElement(owner),
12644
- message: `Integration Service activity context input "${field.contextName}" must reference a root binding.`,
12826
+ message: `Integration Service ${nodeLabel} context input "${field.contextName}" must reference a root binding.`,
12645
12827
  instruction: `Set ${field.contextName} to =bindings.<bindingId> and declare that binding with resource="Connection" and propertyAttribute="${field.propertyAttribute}".`
12646
12828
  });
12647
12829
  continue;
@@ -12656,7 +12838,7 @@ class BpmnValidateService {
12656
12838
  diagnostics.push({
12657
12839
  file,
12658
12840
  element: describeElement(owner),
12659
- message: `Integration Service activity ${field.contextName} binding "${bindingId}" must use resource="Connection" and propertyAttribute="${field.propertyAttribute}".`,
12841
+ message: `Integration Service ${nodeLabel} ${field.contextName} binding "${bindingId}" must use resource="Connection" and propertyAttribute="${field.propertyAttribute}".`,
12660
12842
  instruction: `Set resource="Connection" and propertyAttribute="${field.propertyAttribute}" on that binding.`
12661
12843
  });
12662
12844
  }
@@ -12665,23 +12847,14 @@ class BpmnValidateService {
12665
12847
  diagnostics.push({
12666
12848
  file,
12667
12849
  element: describeElement(owner),
12668
- message: `Integration Service activity ${field.contextName} binding "${bindingId}" is missing resourceKey.`,
12850
+ message: `Integration Service ${nodeLabel} ${field.contextName} binding "${bindingId}" is missing resourceKey.`,
12669
12851
  instruction: "Set resourceKey on that root binding."
12670
12852
  });
12671
12853
  } else if (!hasInvalidBindingShape) {
12672
12854
  resourceKeys.set(field.contextName, resourceKey);
12673
12855
  }
12674
12856
  }
12675
- const connectionResourceKey = resourceKeys.get("connection");
12676
- const folderResourceKey = resourceKeys.get("folderKey");
12677
- if (connectionResourceKey && folderResourceKey && connectionResourceKey !== folderResourceKey) {
12678
- diagnostics.push({
12679
- file,
12680
- element: describeElement(owner),
12681
- message: "Integration Service activity connection and folder bindings refer to different connection resources.",
12682
- instruction: "Set the same resourceKey on both root bindings."
12683
- });
12684
- }
12857
+ return resourceKeys;
12685
12858
  }
12686
12859
  validateInputs(file, payload, owner, contract, diagnostics) {
12687
12860
  const directInputs = childElements(payload, "uipath:input");
@@ -13102,6 +13275,38 @@ function findFirst(node, predicate) {
13102
13275
  }
13103
13276
  return;
13104
13277
  }
13278
+ function isManualStartEvent(startEvent) {
13279
+ const hasEventDefinition = startEvent.children.some((child) => getLocalName(child.name).endsWith("eventdefinition"));
13280
+ const hasUiPathEvent = findDescendants(startEvent, (node) => hasLocalName(node, "event")).length > 0;
13281
+ return !hasEventDefinition && !hasUiPathEvent;
13282
+ }
13283
+ var VARIABLE_READ = /vars(?:\.([A-Za-z_$][\w$]*)|\[\s*["']([^"']+)["']\s*\])/g;
13284
+ var FREE_TEXT_ELEMENTS = new Set(["documentation", "text"]);
13285
+ function collectVariableReads(node, into = new Set) {
13286
+ for (const value of Object.values(node.attributes)) {
13287
+ if (!value.trimStart().startsWith("=")) {
13288
+ continue;
13289
+ }
13290
+ for (const match of value.matchAll(VARIABLE_READ)) {
13291
+ const id = match[1] ?? match[2];
13292
+ if (id) {
13293
+ into.add(id);
13294
+ }
13295
+ }
13296
+ }
13297
+ if (node.text && !FREE_TEXT_ELEMENTS.has(getLocalName(node.name))) {
13298
+ for (const match of node.text.matchAll(VARIABLE_READ)) {
13299
+ const id = match[1] ?? match[2];
13300
+ if (id) {
13301
+ into.add(id);
13302
+ }
13303
+ }
13304
+ }
13305
+ for (const child of node.children) {
13306
+ collectVariableReads(child, into);
13307
+ }
13308
+ return into;
13309
+ }
13105
13310
  function hasLocalName(node, localName) {
13106
13311
  return getLocalName(node.name) === localName.toLowerCase();
13107
13312
  }
@@ -13134,6 +13339,12 @@ function findBpmnOwner(payload) {
13134
13339
  function getContextInputs(payload) {
13135
13340
  return childElements(payload, "uipath:context").flatMap((context) => childElements(context, "uipath:input"));
13136
13341
  }
13342
+ function getConnectorInputs(payload) {
13343
+ return [
13344
+ ...getContextInputs(payload),
13345
+ ...childElements(payload, "uipath:input")
13346
+ ];
13347
+ }
13137
13348
  function isIntsvcActivityExecutionV1(nodeVersion, workflowVersion) {
13138
13349
  const version = nodeVersion ?? workflowVersion;
13139
13350
  return version === undefined || version === ACTIVITY_CONFIGURATION_V1;
@@ -13354,18 +13565,24 @@ function createBpmnValidationFileSystem(fileSystem) {
13354
13565
  class BpmnTool extends ProjectTool {
13355
13566
  _temporaryStorage;
13356
13567
  _validateService;
13568
+ _packValidateService;
13357
13569
  constructor(fileSystem, logger) {
13358
13570
  super(fileSystem, logger);
13359
13571
  this._temporaryStorage = new TemporaryStorageService(fileSystem);
13360
- this._validateService = new BpmnValidateService(createBpmnValidationFileSystem(fileSystem));
13572
+ const validationFileSystem = createBpmnValidationFileSystem(fileSystem);
13573
+ this._validateService = new BpmnValidateService(validationFileSystem);
13574
+ this._packValidateService = new BpmnValidateService(validationFileSystem, { unsupportedExtensionTypeSeverity: "error" });
13361
13575
  }
13362
13576
  async restoreAsync(_options, _cancellationToken) {
13363
13577
  this.logger.info("Restore operation is not required for ProcessOrchestration projects");
13364
13578
  return ToolResult.success();
13365
13579
  }
13366
13580
  async validateAsync(options, _cancellationToken) {
13581
+ return this.runValidation(this._validateService, options.projectPath);
13582
+ }
13583
+ async runValidation(service, projectPath) {
13367
13584
  this.logger.info("Validating ProcessOrchestration BPMN project...");
13368
- const result = await this._validateService.validateProject(options.projectPath);
13585
+ const result = await service.validateProject(projectPath);
13369
13586
  if (!result.isValid) {
13370
13587
  if (result.message) {
13371
13588
  this.logger.error(result.message);
@@ -13384,16 +13601,7 @@ class BpmnTool extends ProjectTool {
13384
13601
  const contentFolder = Path.join(localBuildFolder, NugetConstants.ContentFolderName);
13385
13602
  try {
13386
13603
  if (!options.skipValidate) {
13387
- const validationResult = await this.validateAsync({
13388
- projectPath: options.projectPath,
13389
- excludeConfiguredSources: options.excludeConfiguredSources,
13390
- skipAnalyze: options.skipAnalyze,
13391
- skipValidate: options.skipValidate,
13392
- detailedLogPath: options.detailedLogPath,
13393
- policyFilePath: options.policyFilePath,
13394
- logLevel: options.logLevel,
13395
- nuGetSourcesConfigPath: options.nuGetSourcesConfigPath
13396
- });
13604
+ const validationResult = await this.runValidation(this._packValidateService, options.projectPath);
13397
13605
  if (!validationResult.isSuccess) {
13398
13606
  return validationResult;
13399
13607
  }
@@ -13515,11 +13723,18 @@ class BpmnTool extends ProjectTool {
13515
13723
  const existing = await this.readExistingArtifacts(contentFolder, parseOptionalJson2);
13516
13724
  const existingBindings = existing["bindings_v2.json"];
13517
13725
  const existingResources = Array.isArray(existingBindings?.resources) ? existingBindings.resources.filter(isJsonObject2) : [];
13726
+ let resources;
13727
+ try {
13728
+ resources = buildConnectionResources2(processes, existingResources);
13729
+ } catch (error3) {
13730
+ const message = error3 instanceof Error ? error3.message : String(error3);
13731
+ return `${bpmnFile} has an Integration Service connection binding that cannot be resolved — ${message}`;
13732
+ }
13518
13733
  const metadata = buildBpmnPackageMetadata2({
13519
13734
  bpmnFile,
13520
13735
  entryPoints,
13521
13736
  projectId: options.projectStorageId ?? crypto.randomUUID(),
13522
- resources: buildConnectionResources2(processes, existingResources),
13737
+ resources,
13523
13738
  existing
13524
13739
  });
13525
13740
  for (const name2 of [
@@ -13630,4 +13845,4 @@ export {
13630
13845
  BpmnToolFactory
13631
13846
  };
13632
13847
 
13633
- //# debugId=3BC19C27ABE50E1864756E2164756E21
13848
+ //# debugId=63A8A4C6F0F0836164756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/packager-tool-bpmn",
3
- "version": "1.201.0",
3
+ "version": "1.202.0-preview.136",
4
4
  "description": "UiPath ProcessOrchestration (BPMN) tool implementation",
5
5
  "type": "module",
6
6
  "exports": {
@@ -25,10 +25,10 @@
25
25
  "author": "",
26
26
  "license": "ISC",
27
27
  "peerDependencies": {
28
- "@uipath/solutionpackager-tool-core": "1.201.0"
28
+ "@uipath/solutionpackager-tool-core": "1.202.0"
29
29
  },
30
30
  "dependencies": {
31
- "@uipath/maestro-sdk": "1.201.0"
31
+ "@uipath/maestro-sdk": "1.202.0"
32
32
  },
33
- "gitHead": "7933378ad5276ac369900293a1447474dcec6826"
33
+ "gitHead": "f6270de2c7c04f4c43b2f5187b0c3d3c314c2610"
34
34
  }
package/src/bpmn-tool.ts CHANGED
@@ -51,13 +51,23 @@ function createBpmnValidationFileSystem(
51
51
  */
52
52
  export class BpmnTool extends ProjectTool {
53
53
  private readonly _temporaryStorage: TemporaryStorageService;
54
+ // Standalone `validate` keeps an extension type absent from the contract a
55
+ // warning, so authoring against a type newer than the CLI's bundled contract
56
+ // is not blocked.
54
57
  private readonly _validateService: BpmnValidateService;
58
+ // Packaging must fail fast on such a type rather than ship a package
59
+ // Orchestrator rejects at deploy (Error 1654), so the build path validates
60
+ // with error severity.
61
+ private readonly _packValidateService: BpmnValidateService;
55
62
 
56
63
  constructor(fileSystem: IFileSystem, logger: IToolLogger) {
57
64
  super(fileSystem, logger);
58
65
  this._temporaryStorage = new TemporaryStorageService(fileSystem);
59
- this._validateService = new BpmnValidateService(
60
- createBpmnValidationFileSystem(fileSystem),
66
+ const validationFileSystem = createBpmnValidationFileSystem(fileSystem);
67
+ this._validateService = new BpmnValidateService(validationFileSystem);
68
+ this._packValidateService = new BpmnValidateService(
69
+ validationFileSystem,
70
+ { unsupportedExtensionTypeSeverity: "error" },
61
71
  );
62
72
  }
63
73
 
@@ -74,11 +84,16 @@ export class BpmnTool extends ProjectTool {
74
84
  override async validateAsync(
75
85
  options: IProjectValidateOptions,
76
86
  _cancellationToken?: AbortSignal,
87
+ ): Promise<ToolResult> {
88
+ return this.runValidation(this._validateService, options.projectPath);
89
+ }
90
+
91
+ private async runValidation(
92
+ service: BpmnValidateService,
93
+ projectPath: string,
77
94
  ): Promise<ToolResult> {
78
95
  this.logger.info("Validating ProcessOrchestration BPMN project...");
79
- const result = await this._validateService.validateProject(
80
- options.projectPath,
81
- );
96
+ const result = await service.validateProject(projectPath);
82
97
  if (!result.isValid) {
83
98
  if (result.message) {
84
99
  this.logger.error(result.message);
@@ -111,16 +126,13 @@ export class BpmnTool extends ProjectTool {
111
126
 
112
127
  try {
113
128
  if (!options.skipValidate) {
114
- const validationResult = await this.validateAsync({
115
- projectPath: options.projectPath,
116
- excludeConfiguredSources: options.excludeConfiguredSources,
117
- skipAnalyze: options.skipAnalyze,
118
- skipValidate: options.skipValidate,
119
- detailedLogPath: options.detailedLogPath,
120
- policyFilePath: options.policyFilePath,
121
- logLevel: options.logLevel,
122
- nuGetSourcesConfigPath: options.nuGetSourcesConfigPath,
123
- });
129
+ // Error severity here: the build/pack path fails fast on an
130
+ // extension type absent from the contract, unlike standalone
131
+ // `validate`.
132
+ const validationResult = await this.runValidation(
133
+ this._packValidateService,
134
+ options.projectPath,
135
+ );
124
136
  if (!validationResult.isSuccess) {
125
137
  return validationResult;
126
138
  }
@@ -348,9 +360,8 @@ export class BpmnTool extends ProjectTool {
348
360
  // Deferred, not a top-level import: the derivation carries bpmn-moddle,
349
361
  // and a static import lands it in a chunk that `maestro-tool`'s eager
350
362
  // startup graph also touches — it is only needed when a BPMN project is
351
- // actually built. Same reason `bpmn-validate-service.ts:470` defers
352
- // `@uipath/maestro-sdk/bpmn-validation/canvas` and `refresh.ts` defers
353
- // `BpmnRefreshService`.
363
+ // actually built. The BPMN validate service and refresh command defer
364
+ // their own heavy code for the same reason.
354
365
  const {
355
366
  buildBpmnPackageMetadata,
356
367
  buildConnectionResources,
@@ -381,6 +392,19 @@ export class BpmnTool extends ProjectTool {
381
392
  ? existingBindings.resources.filter(isJsonObject)
382
393
  : [];
383
394
 
395
+ // buildConnectionResources throws when an Integration Service node's
396
+ // connection binding cannot be resolved (missing, literal, or malformed).
397
+ // Turn that into a specific reason here so `uip solution pack` reports
398
+ // the real cause instead of buildAsync's generic InternalError.
399
+ let resources: ReturnType<typeof buildConnectionResources>;
400
+ try {
401
+ resources = buildConnectionResources(processes, existingResources);
402
+ } catch (error) {
403
+ const message =
404
+ error instanceof Error ? error.message : String(error);
405
+ return `${bpmnFile} has an Integration Service connection binding that cannot be resolved — ${message}`;
406
+ }
407
+
384
408
  const metadata = buildBpmnPackageMetadata({
385
409
  bpmnFile,
386
410
  entryPoints,
@@ -388,7 +412,7 @@ export class BpmnTool extends ProjectTool {
388
412
  // so this id is inert: operate.json stays owned by
389
413
  // `ensureContentOperateFile`, which backfills the stable project id.
390
414
  projectId: options.projectStorageId ?? crypto.randomUUID(),
391
- resources: buildConnectionResources(processes, existingResources),
415
+ resources,
392
416
  existing,
393
417
  });
394
418