@uipath/maestro-builder-sdk 6.39.0 → 6.40.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.
@@ -112,6 +112,8 @@ export type BpmnNode = {
112
112
  * BPMN's default, interrupting, and writes no attribute.
113
113
  */
114
114
  interrupting?: boolean;
115
+ /** A start event's own `uipath:entryPointId`; `false` writes none. */
116
+ entryPointId?: string | false;
115
117
  } | {
116
118
  kind: 'boundaryEvent';
117
119
  id: string;
@@ -175,6 +177,8 @@ export type BpmnNode = {
175
177
  name?: string;
176
178
  /** The registry extension type, e.g. `'Intsvc.UnifiedHttpRequest'`. */
177
179
  type: string;
180
+ /** When emitted as a `bpmn:startEvent`: its `uipath:entryPointId`; `false` writes none. */
181
+ entryPointId?: string | false;
178
182
  /** `uipath:context` values, by field name. */
179
183
  context: Record<string, unknown>;
180
184
  /** The payload, shaped by the type's `inputPattern`. */
@@ -203,6 +207,8 @@ export type BpmnNode = {
203
207
  kind: 'connectorEvent';
204
208
  id: string;
205
209
  name?: string;
210
+ /** A trigger's `uipath:entryPointId`; `false` writes none. */
211
+ entryPointId?: string | false;
206
212
  /**
207
213
  * `trigger` STARTS the process (`Intsvc.EventTrigger`, a `bpmn:startEvent`
208
214
  * carrying a message event definition); `event` pauses one mid-flow
@@ -539,8 +545,15 @@ export interface ProcessMetadata {
539
545
  * The root start event's package entry-point id (`uipath:entryPointId`). A GUID —
540
546
  * the one `bpmn init` assigned, or `crypto.randomUUID()`; `validate` refuses any
541
547
  * other value and `check` reports `ENTRYPOINT_ID_NOT_GUID`.
548
+ *
549
+ * Optional since every start event gets a stable derived id when none is set
550
+ * (`entry-point-id.ts`): the canvas writes one on every start, and
551
+ * `uip maestro bpmn refresh` requires one on every root manual start. `false`
552
+ * writes none on the root start — what `decompile` emits for an import that
553
+ * carried none, so the round trip stays faithful. A start event other than the
554
+ * first root one takes its id on the event itself (`StartOpts.entryPointId`).
542
555
  */
543
- entryPointId?: string;
556
+ entryPointId?: string | false;
544
557
  /** Free-form document tags (`uipath:tags` / `uipath:tag`). */
545
558
  tags?: string[];
546
559
  /** Case-management marker (`uipath:caseManagement`) — `version` plus its body value. */
@@ -685,6 +698,15 @@ export interface StartOpts {
685
698
  * {@link ScopeBuilder.eventSubProcess} sets this from its own `interrupting` option.
686
699
  */
687
700
  interrupting?: boolean;
701
+ /**
702
+ * This start event's `uipath:entryPointId`. Unset, a root start derives a stable id
703
+ * from the process and event ids — which therefore changes if either is renamed, so
704
+ * pin the old id here when renaming in a deployed process; `false` writes none (what
705
+ * `decompile` emits for an imported start that carried none). The first root start
706
+ * may also take it from `.metadata({ entryPointId })`. A start inside a sub-process
707
+ * derives nothing (the canvas strips ids there) and writes only a value set here.
708
+ */
709
+ entryPointId?: string | false;
688
710
  }
689
711
  /**
690
712
  * Options for `.endEvent()`. `terminate`, `error`, or `message` picks the event
@@ -1497,6 +1519,11 @@ export interface ConnectorEventOpts extends ActivityOpts {
1497
1519
  outputs?: Record<string, string>;
1498
1520
  /** `=`-expression that skips the node when truthy. */
1499
1521
  skipCondition?: string;
1522
+ /**
1523
+ * `.eventTrigger()` only: the start event's `uipath:entryPointId`. Unset, a stable
1524
+ * id is derived; `false` writes none. Ignored by `.waitForEvent()`.
1525
+ */
1526
+ entryPointId?: string | false;
1500
1527
  }
1501
1528
  /** Options for `.externalAgent()` / `.externalWorkflow()`. */
1502
1529
  export interface ExternalTaskOpts extends ActivityOpts {
@@ -1607,6 +1634,12 @@ export interface ActivityNodeOpts extends ActivityOpts {
1607
1634
  * writing `.activity()` by hand wants the defaults.
1608
1635
  */
1609
1636
  contextVerbatim?: boolean;
1637
+ /**
1638
+ * When the registry type is emitted as a `bpmn:startEvent` (a trigger such as
1639
+ * `Intsvc.EventTrigger`): its `uipath:entryPointId`. Unset, a stable id is derived;
1640
+ * `false` writes none, as `decompile` emits for an imported start that carried none.
1641
+ */
1642
+ entryPointId?: string | false;
1610
1643
  }
1611
1644
  /**
1612
1645
  * The BPMN task elements that are legal with NO `uipath:*` payload.
@@ -1892,6 +1925,8 @@ export interface EventSubProcessOpts {
1892
1925
  startName?: string;
1893
1926
  /** A payload on the start event, spelled out by hand — see {@link ExtensionPayload}. Exclusive with `errorVar`. */
1894
1927
  startPayload?: ExtensionPayload;
1928
+ /** The nested start event's `uipath:entryPointId`, written only when set: the canvas strips ids inside a sub-process, so none is derived. */
1929
+ startEntryPointId?: string | false;
1895
1930
  /** `uipath:tags` on the sub-process — see {@link ActivityOpts.tags}. */
1896
1931
  tags?: Record<string, string>;
1897
1932
  /** A `uipath:mapping` on the sub-process itself — see {@link SubProcessOpts.payload}. */
@@ -2690,9 +2725,10 @@ declare abstract class ScopeBuilder {
2690
2725
  * therefore proves the graph runs and the artifact validates — nothing about the
2691
2726
  * message actually arriving. See Phase 5 in `docs/BPMN_COVERAGE_DESIGN.md`.
2692
2727
  *
2693
- * The throw side (`Maestro.SendMessageEvent`) is deliberately NOT authored: its
2694
- * required `Reference` payload field cannot be expressed in a way the platform
2695
- * validator accepts. See `unsatisfiableRequiredInputs`.
2728
+ * The throw side (`Maestro.SendMessageEvent`) has no builder method yet; author it
2729
+ * as `.activity('send', 'Maestro.SendMessageEvent', { context: { name, inputSchema },
2730
+ * inputs: { Reference } })` — it validates on uip 1.205 (Phase 6 in
2731
+ * `docs/BPMN_COVERAGE_DESIGN.md`).
2696
2732
  *
2697
2733
  * @example
2698
2734
  * **Wait for another process to signal a shipment**
@@ -344,6 +344,15 @@ class ScopeBuilder {
344
344
  * @returns This builder, so calls chain.
345
345
  */
346
346
  pushActivity(node, body) {
347
+ // An `outputVar` names the variable the type's own output row lands in; a type
348
+ // with no output row (the fire-and-forget Async starts) would accept it and emit
349
+ // nothing, so the author reads a variable nothing ever writes.
350
+ if (node.kind === 'typed' && node.outputVar !== undefined && !node.outputRows && !registryType(node.type, node.spec).output) {
351
+ throw new Error(`"${node.id}" (${node.type}) publishes no output row, so outputVar "${node.outputVar}" would bind nothing. ` +
352
+ (node.type.endsWith('Async')
353
+ ? 'The Async start returns before the job does: drop outputVar, or use the waiting form (async: false) to read the response.'
354
+ : 'Drop outputVar, or spell the rows with outputRows.'));
355
+ }
347
356
  this.place(node);
348
357
  if (body)
349
358
  body(new ActivityBuilder(this, node.id));
@@ -697,6 +706,7 @@ class ScopeBuilder {
697
706
  return this.push({
698
707
  kind: 'startEvent',
699
708
  id,
709
+ entryPointId: opts.entryPointId,
700
710
  name: opts.name,
701
711
  payload: opts.payload,
702
712
  interrupting: opts.interrupting === false ? false : undefined,
@@ -1619,9 +1629,10 @@ class ScopeBuilder {
1619
1629
  * therefore proves the graph runs and the artifact validates — nothing about the
1620
1630
  * message actually arriving. See Phase 5 in `docs/BPMN_COVERAGE_DESIGN.md`.
1621
1631
  *
1622
- * The throw side (`Maestro.SendMessageEvent`) is deliberately NOT authored: its
1623
- * required `Reference` payload field cannot be expressed in a way the platform
1624
- * validator accepts. See `unsatisfiableRequiredInputs`.
1632
+ * The throw side (`Maestro.SendMessageEvent`) has no builder method yet; author it
1633
+ * as `.activity('send', 'Maestro.SendMessageEvent', { context: { name, inputSchema },
1634
+ * inputs: { Reference } })` — it validates on uip 1.205 (Phase 6 in
1635
+ * `docs/BPMN_COVERAGE_DESIGN.md`).
1625
1636
  *
1626
1637
  * @example
1627
1638
  * **Wait for another process to signal a shipment**
@@ -1754,6 +1765,7 @@ class ScopeBuilder {
1754
1765
  return this.push({
1755
1766
  kind: 'connectorEvent',
1756
1767
  id,
1768
+ entryPointId: opts.entryPointId,
1757
1769
  name: opts.name,
1758
1770
  subscribe: 'trigger',
1759
1771
  key: connector,
@@ -1907,6 +1919,7 @@ class ScopeBuilder {
1907
1919
  outputRows: opts.outputRows,
1908
1920
  skipCondition: opts.skipCondition,
1909
1921
  contextVerbatim: opts.contextVerbatim,
1922
+ entryPointId: opts.entryPointId,
1910
1923
  tags: opts.tags,
1911
1924
  retry: opts.retry,
1912
1925
  errorMapping: opts.errorMapping,
@@ -2036,6 +2049,7 @@ class ScopeBuilder {
2036
2049
  sb._begin({
2037
2050
  kind: 'startEvent',
2038
2051
  id: startId,
2052
+ entryPointId: opts.startEntryPointId,
2039
2053
  name: opts.startName,
2040
2054
  event,
2041
2055
  payload: opts.startPayload ?? (capture !== undefined ? errorCapturePayload(capture, 'startEvent') : undefined),
@@ -3,7 +3,7 @@ import { allNodes, folderCompanionKeys, implicitNodeVars, processId } from './se
3
3
  import { KNOWN_METHOD_SET } from './known-methods.js';
4
4
  import { EQUALS_EXPR_DIALECT, checkConnectorContract, checkConnectorLookups, checkConnectorSchema, checkBindingLabels, } from '../core/connector-checks.js';
5
5
  import { checkEventResolution, checkEventSubscription, eventParamsFor, } from '../core/event-checks.js';
6
- import { bindingRequiredFields, missingRequiredContext, missingRequiredInputs, REGISTRY_GAPS, registryType, unsatisfiableRequiredInputs, } from './typed-node.js';
6
+ import { bindingRequiredFields, CASE_RUNTIME_INTERNAL_TYPES, missingRequiredContext, missingRequiredInputs, REGISTRY_GAPS, registryType, } from './typed-node.js';
7
7
  import { ownEntry } from '../core/own-entry.js';
8
8
  /**
9
9
  * The job-start family — the types whose engine handler switches addressing on the
@@ -310,15 +310,25 @@ const GUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
310
310
  * main one agent spent its whole turn budget there. Reported here, at the first rung.
311
311
  */
312
312
  function checkEntryPointId(built, diags) {
313
+ const report = (where, id, at) => {
314
+ diags.push({
315
+ level: 'error',
316
+ code: 'ENTRYPOINT_ID_NOT_GUID',
317
+ message: `${where} "${id}" is not a GUID; \`uip maestro bpmn validate\` refuses it. Use the id \`bpmn init\` ` +
318
+ `assigned (decompile the stub it wrote to carry it), a fresh one from \`crypto.randomUUID()\`, or leave it ` +
319
+ `unset and the SDK derives a stable one.`,
320
+ ...(at !== undefined ? { where: at } : {}),
321
+ });
322
+ };
313
323
  const id = built.metadata?.entryPointId;
314
- if (id === undefined || GUID.test(id))
315
- return;
316
- diags.push({
317
- level: 'error',
318
- code: 'ENTRYPOINT_ID_NOT_GUID',
319
- message: `metadata.entryPointId "${id}" is not a GUID; \`uip maestro bpmn validate\` refuses it. Use the id \`bpmn init\` ` +
320
- `assigned (decompile the stub it wrote to carry it), or a fresh one from \`crypto.randomUUID()\`.`,
321
- });
324
+ if (typeof id === 'string' && !GUID.test(id))
325
+ report('metadata.entryPointId', id);
326
+ for (const n of allNodes(built.nodes)) {
327
+ if (n.kind !== 'startEvent' && n.kind !== 'connectorEvent' && n.kind !== 'typed')
328
+ continue;
329
+ if (typeof n.entryPointId === 'string' && !GUID.test(n.entryPointId))
330
+ report(`"${n.id}" entryPointId`, n.entryPointId, n.id);
331
+ }
322
332
  }
323
333
  /**
324
334
  * A `folderKey` binding must be keyed by its CONNECTION, not by the folder.
@@ -1417,20 +1427,20 @@ inEventSubProcess = false) {
1417
1427
  where: n.id,
1418
1428
  });
1419
1429
  }
1420
- // A type whose required payload fields cannot be expressed at all. Warning,
1421
- // not error: the node is as correct as the registry allows, so refusing it
1422
- // would block work the platform, not the author, has to fix. Saying nothing
1423
- // is worse — the artifact validates here and is rejected by the CLI.
1424
- const unsatisfiable = unsatisfiableRequiredInputs(n.type, n.spec);
1425
- if (unsatisfiable.length) {
1430
+ // A type the case-management runtime writes for itself. Warning, not error:
1431
+ // the platform validates it, and nobody designs a process around it. The one
1432
+ // legitimate authored form is a preserved import, which `decompile` writes as
1433
+ // `contextVerbatim: true` — that node is left alone, so a brownfield edit that
1434
+ // keeps the platform's nodes as they were is not told off on every check.
1435
+ if (CASE_RUNTIME_INTERNAL_TYPES.has(n.type) && n.contextVerbatim !== true) {
1426
1436
  diags.push({
1427
1437
  level: 'warning',
1428
- code: 'REQUIRED_INPUT_UNSATISFIABLE',
1429
- message: `"${n.id}" (${n.type}) declares required input(s) ${unsatisfiable.map((f) => `"${f}"`).join(', ')}, ` +
1430
- `but its "${registryType(n.type, n.spec).inputPattern}" pattern merges every input into one row, so the ` +
1431
- `platform's required-field rule cannot see them. \`uip maestro bpmn validate\` will report ` +
1432
- `EMPTY_REQUIRED_FIELD whatever this node carries — a platform defect, not an authoring error. ` +
1433
- `See docs/BPMN_COVERAGE_DESIGN.md D13.`,
1438
+ code: 'TYPE_RUNTIME_INTERNAL',
1439
+ message: `"${n.id}" (${n.type}) is a node the case-management runtime writes for itself when it materializes a ` +
1440
+ `case plan (scheduler state only the platform produces); the canvas offers it nowhere, and a process is not ` +
1441
+ `designed around one — author the case in the Case SDK instead. To preserve an imported one as it was, keep ` +
1442
+ `the form \`decompile\` writes (\`contextVerbatim: true\`), which this check leaves alone. ` +
1443
+ `See its row in typescript/sdk/bpmn-coverage.json.`,
1434
1444
  where: n.id,
1435
1445
  });
1436
1446
  }
@@ -61,6 +61,7 @@ import { BPMN_SCHEMA_VERSIONS } from './format-profile.js';
61
61
  import { preserveSchemaVersion } from '../schema-version.js';
62
62
  import { commentText } from '../core/comment-text.js';
63
63
  import { tsLiteral, tsText } from '../core/ts-literal.js';
64
+ import { defaultEntryPointId } from './entry-point-id.js';
64
65
  const require = createRequire(import.meta.url);
65
66
  const uipathDescriptor = require('./uipath-moddle.v1.json');
66
67
  /**
@@ -717,6 +718,47 @@ function emitOutputRows(payload) {
717
718
  return `[${rendered.join(', ')}]`;
718
719
  }
719
720
  // ─── Element emitters ─────────────────────────────────────────────────────────
721
+ /**
722
+ * The process being decompiled, for the entry-point spelling below: the builder id
723
+ * the derived default is seeded from, the root start events, and the one root start
724
+ * whose id `.metadata({ entryPointId })` spells — the only root start, when there is
725
+ * exactly one. With several, every root start spells its own on the event, because
726
+ * `serialize` hands `.metadata()`'s id to the first root start in CHAIN order and the
727
+ * chain is emitted manual-first, which need not be document order.
728
+ */
729
+ let runEntryPoints = {
730
+ builderProcessId: '',
731
+ rootStartIds: new Set(),
732
+ };
733
+ /**
734
+ * How an imported start event's `uipath:entryPointId` is spelled on the event's own
735
+ * call, or `undefined` for none. A root start: the value as text when the file
736
+ * carries one the SDK would not derive; nothing when it equals the derived default
737
+ * (compile writes it back unprompted); `false` when the file carries none, so the
738
+ * recompile adds nothing. The lone root start is `.metadata()`'s and gets nothing
739
+ * here. A nested start derives nothing on compile, so it is spelled only when the
740
+ * file carries a value.
741
+ */
742
+ function entryPointOption(el) {
743
+ if (localName(el.$type) !== 'startEvent' || el.id === runEntryPoints.metadataStartId)
744
+ return undefined;
745
+ const legacy = runEntryPoints.processLevel;
746
+ const value = entryPointValueOf(el) ?? (legacy !== undefined && legacy.startId === el.id ? legacy.value : undefined);
747
+ if (!runEntryPoints.rootStartIds.has(el.id))
748
+ return value === undefined ? undefined : tsText(value);
749
+ return entryPointText(el.id, value);
750
+ }
751
+ /** The `uipath:entryPointId` value a start event carries, if any. */
752
+ function entryPointValueOf(el) {
753
+ const row = (el.extensionElements?.values ?? []).find((x) => x.$type === 'uipath:EntryPointId');
754
+ return row?.value !== undefined ? String(row.value) : undefined;
755
+ }
756
+ /** `entryPointOption`'s spelling for a ROOT start event id and the value it carries. */
757
+ function entryPointText(startId, value) {
758
+ if (value === undefined)
759
+ return 'false';
760
+ return value === defaultEntryPointId(runEntryPoints.builderProcessId, startId) ? undefined : tsText(value);
761
+ }
720
762
  /**
721
763
  * A registry-typed node.
722
764
  *
@@ -776,6 +818,7 @@ function emitTypedNode(chain, el, payload, type) {
776
818
  ['outputs', verbatimRows === undefined ? record(extras) : undefined],
777
819
  ['skipCondition', payload.skipCondition !== undefined ? tsText(payload.skipCondition) : undefined],
778
820
  ['contextVerbatim', Object.keys(ctx).length ? 'true' : undefined],
821
+ ['entryPointId', entryPointOption(el)],
779
822
  ['tags', tagsOf(el)],
780
823
  ['retry', emitRetry(retryOf(el))],
781
824
  ['errorMapping', emitErrorMapping(errorMappingOf(el))],
@@ -1489,6 +1532,7 @@ function renderEventSubProcess(plan, sp, depth, indent) {
1489
1532
  ],
1490
1533
  ['startId', start.id !== `${sp.id}_start` ? tsText(start.id) : undefined],
1491
1534
  ['startName', start.name !== undefined ? tsText(start.name) : undefined],
1535
+ ['startEntryPointId', entryPointOption(start)],
1492
1536
  ['startPayload', payload && type && capture === undefined ? opts([['type', tsText(type)], ['outputRows', emitOutputRows(payload) ?? '[]']]) : undefined],
1493
1537
  ['tags', tagsOf(sp)],
1494
1538
  ['payload', spPayload && spType ? opts([['type', tsText(spType)], ['outputRows', emitOutputRows(spPayload) ?? '[]']]) : undefined],
@@ -1665,6 +1709,7 @@ function emitTriggerStartEvent(chain, el, payload, type) {
1665
1709
  ['name', el.name !== undefined ? tsText(el.name) : undefined],
1666
1710
  ...eventOptions(el),
1667
1711
  ['trigger', trigger],
1712
+ ['entryPointId', entryPointOption(el)],
1668
1713
  ])})`);
1669
1714
  }
1670
1715
  /**
@@ -1748,6 +1793,7 @@ function emitEvent(chain, el, kind, payload, type) {
1748
1793
  // Only a start event can be non-interrupting, and only the exception is
1749
1794
  // spelled — the builder's default is BPMN's.
1750
1795
  ['interrupting', kind === 'startEvent' && el.isInterrupting === false ? 'false' : undefined],
1796
+ ['entryPointId', entryPointOption(el)],
1751
1797
  ['payload', eventPayload],
1752
1798
  ]))})`);
1753
1799
  }
@@ -2086,6 +2132,26 @@ export async function decompile(xml, options = {}) {
2086
2132
  const migration = findExt('uipath:MigrationVersion');
2087
2133
  const rootStart = (process.flowElements ?? []).find((x) => x.$type === 'bpmn:StartEvent');
2088
2134
  const entryPoint = (rootStart?.extensionElements?.values ?? []).find((x) => x.$type === 'uipath:EntryPointId') ?? findExt('uipath:EntryPointId');
2135
+ const rootStarts = (process.flowElements ?? []).filter((x) => x.$type === 'bpmn:StartEvent');
2136
+ // `bpmn(process.id)` is what the source will say, so it is the seed on both sides.
2137
+ const builderId = String(process.id ?? '');
2138
+ const processLevelEntryPoint = findExt('uipath:EntryPointId');
2139
+ runEntryPoints = {
2140
+ builderProcessId: builderId,
2141
+ rootStartIds: new Set(rootStarts.map((x) => x.id)),
2142
+ metadataStartId: rootStarts.length === 1 ? rootStart?.id : undefined,
2143
+ ...(rootStarts.length > 1 && rootStart !== undefined && processLevelEntryPoint?.value !== undefined
2144
+ && !(rootStart.extensionElements?.values ?? []).some((x) => x.$type === 'uipath:EntryPointId')
2145
+ ? { processLevel: { startId: rootStart.id, value: String(processLevelEntryPoint.value) } }
2146
+ : {}),
2147
+ };
2148
+ // A lone root start's id is `.metadata()`'s: the file's own value when the SDK would
2149
+ // not derive it, `false` when the file carries none (so the recompile adds none), and
2150
+ // nothing when it equals the derived default. With several root starts each spells
2151
+ // its own on the event (see `runEntryPoints`).
2152
+ const rootEntryPointText = rootStarts.length === 1 && rootStart !== undefined
2153
+ ? entryPointText(rootStart.id, entryPoint?.value !== undefined ? String(entryPoint.value) : undefined)
2154
+ : undefined;
2089
2155
  const tagsExt = findExt('uipath:Tags');
2090
2156
  const caseMgmt = findExt('uipath:CaseManagement');
2091
2157
  const tagValues = (tagsExt?.tags ?? []).map((t) => t.value).filter((v) => typeof v === 'string');
@@ -2103,13 +2169,13 @@ export async function decompile(xml, options = {}) {
2103
2169
  const schema = preserveSchemaVersion(BPMN_SCHEMA_VERSIONS, migration?.version);
2104
2170
  if (schema.call)
2105
2171
  chain.add(schema.call);
2106
- if (entryPoint !== undefined ||
2172
+ if (rootEntryPointText !== undefined ||
2107
2173
  tagValues.length > 0 ||
2108
2174
  caseMgmt !== undefined ||
2109
2175
  nonExecutable) {
2110
2176
  chain.add(`.metadata(${opts([
2111
2177
  ['executable', nonExecutable ? 'false' : undefined],
2112
- ['entryPointId', entryPoint?.value !== undefined ? tsText(entryPoint.value) : undefined],
2178
+ ['entryPointId', rootEntryPointText],
2113
2179
  ['tags', tagValues.length > 0 ? `[${tagValues.map((t) => tsText(t)).join(', ')}]` : undefined],
2114
2180
  [
2115
2181
  'caseManagement',
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The default `uipath:entryPointId` for one start event.
3
+ *
4
+ * @param builderProcessId - The id `bpmn(id)` was called with — not the `bpmn:process` id
5
+ * on the wire, which `processId()` folds every non-identifier name to `Process_1`, so
6
+ * two such processes would share every start's id.
7
+ * @param startEventId - The start event's element id.
8
+ */
9
+ export declare function defaultEntryPointId(builderProcessId: string, startEventId: string): string;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The entry-point id a start event carries when nobody chose one.
3
+ *
4
+ * The canvas writes `uipath:entryPointId` on every root start event, and the CLI's
5
+ * packaging (`uip maestro bpmn refresh`, UiPath/cli `bpmn-packaging/entry-points.ts`)
6
+ * requires exactly one, a GUID, on every root manual start — "read from the BPMN,
7
+ * never minted, so the derived entry-points.json is stable across runs".
8
+ *
9
+ * A root start with no id of its own gets this one: the first 128 bits of SHA-256
10
+ * over the builder's process id and the start event id, in GUID shape — the derivation
11
+ * the Case compiler uses for an entry point's `uniqueId`. It is the same on every
12
+ * compile and machine, differs between processes and between starts, and is
13
+ * reproducible by `decompile`, which omits an id equal to it.
14
+ *
15
+ * It is derived from two names, so it CHANGES when either is renamed. The entry point's
16
+ * `uniqueId` is what Orchestrator rebinds a release by on upgrade
17
+ * (`ReleasesManager.cs`, `UniqueId`): rename `bpmn('Invoice')` or its start in a
18
+ * process that is already deployed, and on the next upgrade Orchestrator finds no
19
+ * entry point with the old `uniqueId` and silently rebinds the release to the main
20
+ * entry point. Pin the old id on the start (`.startEvent(id, { entryPointId })` or
21
+ * `.metadata({ entryPointId })`) when renaming either; `decompile` of the deployed
22
+ * file carries it.
23
+ */
24
+ import { sha256Uuid } from '../core/stable-id.js';
25
+ /**
26
+ * The default `uipath:entryPointId` for one start event.
27
+ *
28
+ * @param builderProcessId - The id `bpmn(id)` was called with — not the `bpmn:process` id
29
+ * on the wire, which `processId()` folds every non-identifier name to `Process_1`, so
30
+ * two such processes would share every start's id.
31
+ * @param startEventId - The start event's element id.
32
+ */
33
+ export function defaultEntryPointId(builderProcessId, startEventId) {
34
+ return sha256Uuid(`uipath:entryPointId/${builderProcessId}/${startEventId}`);
35
+ }
@@ -159,7 +159,11 @@ export function shapeExtensionType(spec) {
159
159
  output,
160
160
  eventDefinition: eventDefinitionOf(spec.XmlTemplate),
161
161
  requiresDiscovery: Boolean(spec.RequiresDiscovery),
162
+ isDynamic: Boolean(spec.IsDynamic),
162
163
  bindingPattern: spec.BindingPattern ?? 'none',
164
+ placements: Object.fromEntries(Object.entries((spec.Placements ?? {}))
165
+ .sort(([a], [b]) => a.localeCompare(b))
166
+ .map(([name, p]) => [name, { element: p?.Type ?? null, eventDefinition: p?.EventDefinition?.Type ?? null }])),
163
167
  };
164
168
  }
165
169
  /** `registry get <type>`, shaped, or `undefined` when the registry has no such type. */