@uipath/maestro-builder-sdk 6.70.7 → 6.70.8

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.
@@ -5,7 +5,7 @@
5
5
  * from the inner loop as from compile. Before this, `check` printed `0 error(s)`
6
6
  * for a source `compile` then refused (teams-decision, 2026-09-01, turn 22 → 23).
7
7
  */
8
- import { prepareCommand } from './cli-spelling.js';
8
+ import { placeholder, prepareCommand } from './cli-spelling.js';
9
9
  import { CompileRefusal } from './compile-refusal.js';
10
10
  /** A tenant resource key — an Integration Service connection id or an Orchestrator folder key — is a GUID. */
11
11
  export const GUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -96,7 +96,7 @@ export function bindingLabelRefusal(bindings, name, attribute, where, target) {
96
96
  return undefined;
97
97
  }
98
98
  function prepareFor(target) {
99
- return prepareCommand(target?.key ?? '<connector-key>', target?.action ?? '<action>');
99
+ return prepareCommand(target?.key ?? placeholder('<connector-key>'), target?.action ?? placeholder('<action>'));
100
100
  }
101
101
  /**
102
102
  * Why compile refuses `name`, and how to bind it.
@@ -143,7 +143,7 @@ export function connectionConnectorConflictMessage(connection, users) {
143
143
  return `connection "${connection}" is used by steps of different connectors (${who}). An Integration Service `
144
144
  + `connection belongs to exactly one connector, so at most one of these steps can run on it, and the solution `
145
145
  + `resource would be declared as whichever came first. Give each connector its own connection label in `
146
- + `bindings.json (\`${prepareCommand('<connector-key>', '<action>')}\` binds one per connector). A managed `
146
+ + `bindings.json (\`${prepareCommand(placeholder('<connector-key>'), placeholder('<action>'))}\` binds one per connector). A managed `
147
147
  + `\`http({ managed: true, … })\` step on another connector's connection must name that connector in `
148
148
  + `\`targetConnector\`.`;
149
149
  }
package/dist/core/byoa.js CHANGED
@@ -88,11 +88,11 @@ export function byoaUnverified(where, sub, facts, ledger, bindings) {
88
88
  if (byoaRecordFor(ledger, byoaLedgerKey(sub.connector, sub.event), id))
89
89
  return undefined;
90
90
  const named = label === id ? `connection ${id}` : `connection \`${label}\` (${id})`;
91
- const object = sub.object ? ` --object ${sub.object}` : '';
91
+ const object = sub.object ? ['--object', sub.object] : [];
92
92
  return `${where}: \`${sub.connector}\` \`${sub.event}\` requires a BYOA (bring-your-own-app) connection — `
93
93
  + `one created with your own OAuth app — and ${named} was never checked against that requirement. `
94
94
  + `A standard connection deploys and the trigger never fires. Prepare the event on this connection, `
95
95
  + `which refuses a standard connection and records a BYOA one:\n`
96
- + ` ${prepareCommand(sub.connector, sub.event)}${object} --connection-id ${id}\n`
96
+ + ` ${prepareCommand(sub.connector, sub.event, ...object, '--connection-id', id)}\n`
97
97
  + `BYOA connections (rows for \`${sub.connector}\`): uip is connections list --byoa --all-folders`;
98
98
  }
@@ -23,12 +23,33 @@ export interface CliSpellingEnv {
23
23
  * @returns `uip maestro` when the caller said so, else `npx flow-sdk`.
24
24
  */
25
25
  export declare function cliSpelling(env?: CliSpellingEnv): string;
26
+ declare const PLACEHOLDER_TEXT: unique symbol;
27
+ /** A `<name>` placeholder the SDK itself writes into a printed command; printed bare. */
28
+ export interface Placeholder {
29
+ readonly [PLACEHOLDER_TEXT]: string;
30
+ }
31
+ /**
32
+ * Mark `<name>` as a placeholder for {@link prepareCommand}. Only a marked
33
+ * placeholder is printed bare: a plain string shaped like `<x>` can come from a
34
+ * `.flow`, and bare it is a shell redirection.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * prepareCommand(key, event, '--connection-id', placeholder('<id>'));
39
+ * ```
40
+ */
41
+ export declare function placeholder(name: string): Placeholder;
26
42
  /**
27
43
  * A `registry prepare` command line, spelled for whoever is driving.
28
44
  *
29
- * @param connectorKey - The connector key, or omitted for the bare command.
30
- * @param action - The operation, printed as `--action <action>`.
31
- * @param rest - Further arguments, e.g. `--object`, `<name>`.
45
+ * The key, action and object often come from a `.flow` file, so every argument
46
+ * goes through {@link shellArg}; only a {@link placeholder} is kept as is. A value
47
+ * {@link shellArg} cannot quote prints as its placeholder, and the line ends
48
+ * with the value once, JSON-escaped: `… --object <object> (where <object> is "a';x")`.
49
+ *
50
+ * @param connectorKey - The connector key, or omitted (or empty) for the bare command.
51
+ * @param action - The operation, printed as `--action <action>`; omitted when empty.
52
+ * @param rest - Further arguments, e.g. `--object`, `Lead`; an empty one prints as `''`.
32
53
  * @returns The full command, no trailing newline.
33
54
  *
34
55
  * @example
@@ -36,9 +57,25 @@ export declare function cliSpelling(env?: CliSpellingEnv): string;
36
57
  * prepareCommand('uipath-salesforce-slack', 'send-message-to-user');
37
58
  * // -> "npx flow-sdk registry prepare uipath-salesforce-slack --action send-message-to-user"
38
59
  * // -> "uip maestro registry prepare …" when FLOW_SDK_INVOKED_AS="uip maestro"
60
+ * prepareCommand('uipath-x', 'created', '--object', 'My Object');
61
+ * // -> "npx flow-sdk registry prepare uipath-x --action created --object 'My Object'"
62
+ * ```
63
+ */
64
+ export declare function prepareCommand(connectorKey?: string | Placeholder, action?: string | Placeholder, ...rest: (string | Placeholder)[]): string;
65
+ /**
66
+ * One argument of a printed command, safe to paste into a POSIX shell or PowerShell.
67
+ *
68
+ * @param arg - The argument; `''` is returned for the empty string.
69
+ * @returns The argument as is, single-quoted, or `undefined` when no quoting is safe in both shells.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * shellArg('Lead'); // -> "Lead"
74
+ * shellArg('Lead;curl x|sh'); // -> "'Lead;curl x|sh'"
75
+ * shellArg("a';echo X;#"); // -> undefined
39
76
  * ```
40
77
  */
41
- export declare function prepareCommand(connectorKey?: string, action?: string, ...rest: string[]): string;
78
+ export declare function shellArg(arg: string): string | undefined;
42
79
  /**
43
80
  * The argument of one `--resolve <field>:<by>=<value>`, single-quoted when the
44
81
  * shell would otherwise mangle it.
@@ -58,3 +95,4 @@ export declare function resolveFlagArg(field: string, by: string, value: string)
58
95
  * moved to `uip`. Name it here once.
59
96
  */
60
97
  export declare const PULL_COMMAND = "uip maestro registry pull";
98
+ export {};
@@ -44,12 +44,39 @@ export function cliSpelling(env = ambientEnv()) {
44
44
  const hint = (env.FLOW_SDK_INVOKED_AS ?? '').trim();
45
45
  return SPELLING.test(hint) ? hint : DEFAULT_CLI_SPELLING;
46
46
  }
47
+ /** A `<name>` placeholder a caller prints for the reader to fill in, e.g. `<id>`, `<action>`. */
48
+ const PLACEHOLDER = /^<[a-z][a-z0-9-]*>$/;
49
+ const PLACEHOLDER_TEXT = Symbol('placeholder');
50
+ /**
51
+ * Mark `<name>` as a placeholder for {@link prepareCommand}. Only a marked
52
+ * placeholder is printed bare: a plain string shaped like `<x>` can come from a
53
+ * `.flow`, and bare it is a shell redirection.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * prepareCommand(key, event, '--connection-id', placeholder('<id>'));
58
+ * ```
59
+ */
60
+ export function placeholder(name) {
61
+ if (!PLACEHOLDER.test(name))
62
+ throw new Error(`internal SDK error: ${JSON.stringify(name)} is not a <name> placeholder`);
63
+ return { [PLACEHOLDER_TEXT]: name };
64
+ }
65
+ /** The placeholder printed in place of the value after `flag`: `<object>` after `--object`, else `<arg>`. */
66
+ function placeholderAfter(flag) {
67
+ return flag !== undefined && /^--[a-z][a-z0-9-]*$/.test(flag) ? `<${flag.slice(2)}>` : '<arg>';
68
+ }
47
69
  /**
48
70
  * A `registry prepare` command line, spelled for whoever is driving.
49
71
  *
50
- * @param connectorKey - The connector key, or omitted for the bare command.
51
- * @param action - The operation, printed as `--action <action>`.
52
- * @param rest - Further arguments, e.g. `--object`, `<name>`.
72
+ * The key, action and object often come from a `.flow` file, so every argument
73
+ * goes through {@link shellArg}; only a {@link placeholder} is kept as is. A value
74
+ * {@link shellArg} cannot quote prints as its placeholder, and the line ends
75
+ * with the value once, JSON-escaped: `… --object <object> (where <object> is "a';x")`.
76
+ *
77
+ * @param connectorKey - The connector key, or omitted (or empty) for the bare command.
78
+ * @param action - The operation, printed as `--action <action>`; omitted when empty.
79
+ * @param rest - Further arguments, e.g. `--object`, `Lead`; an empty one prints as `''`.
53
80
  * @returns The full command, no trailing newline.
54
81
  *
55
82
  * @example
@@ -57,22 +84,64 @@ export function cliSpelling(env = ambientEnv()) {
57
84
  * prepareCommand('uipath-salesforce-slack', 'send-message-to-user');
58
85
  * // -> "npx flow-sdk registry prepare uipath-salesforce-slack --action send-message-to-user"
59
86
  * // -> "uip maestro registry prepare …" when FLOW_SDK_INVOKED_AS="uip maestro"
87
+ * prepareCommand('uipath-x', 'created', '--object', 'My Object');
88
+ * // -> "npx flow-sdk registry prepare uipath-x --action created --object 'My Object'"
60
89
  * ```
61
90
  */
62
91
  export function prepareCommand(connectorKey, action, ...rest) {
63
- return [cliSpelling(), 'registry', 'prepare', connectorKey, ...(action ? ['--action', action] : []), ...rest]
64
- .filter(Boolean)
65
- .join(' ');
92
+ const held = [];
93
+ const arg = (value, stand) => {
94
+ if (typeof value !== 'string')
95
+ return value[PLACEHOLDER_TEXT];
96
+ const quoted = shellArg(value);
97
+ if (quoted !== undefined)
98
+ return quoted;
99
+ held.push(`${stand} is ${JSON.stringify(value)}`);
100
+ return stand;
101
+ };
102
+ const words = [cliSpelling(), 'registry', 'prepare'];
103
+ if (connectorKey)
104
+ words.push(arg(connectorKey, '<connector-key>'));
105
+ if (action)
106
+ words.push('--action', arg(action, '<action>'));
107
+ rest.forEach((value, i) => {
108
+ const prev = rest[i - 1];
109
+ words.push(arg(value, placeholderAfter(typeof prev === 'string' ? prev : undefined)));
110
+ });
111
+ const line = words.join(' ');
112
+ return held.length ? `${line} (where ${held.join(', ')})` : line;
113
+ }
114
+ /** Characters a POSIX shell or PowerShell reads specially in an unquoted argument (globs, whitespace, quotes incl. “ ” „, `$`, operators). */
115
+ const SHELL_UNSAFE = /[\s'"`$\\[\]*?;&|(){}!#~<>\u201C-\u201E]/;
116
+ /**
117
+ * Characters no single quoting keeps literal in both a POSIX shell and
118
+ * PowerShell: POSIX writes `'` as `'\''`, which PowerShell reads as a break-out;
119
+ * PowerShell also ends `'…'` at U+2018–U+201B; a control character can end the
120
+ * line. Every other character is literal inside `'…'` in both.
121
+ */
122
+ const UNQUOTABLE = /['\u2018-\u201B\p{Cc}]/u;
123
+ /** `arg` in POSIX shell single quotes, each embedded `'` written as `'\''`. */
124
+ function singleQuote(arg) {
125
+ return `'${arg.replaceAll("'", `'\\''`)}'`;
66
126
  }
67
127
  /**
68
- * Characters that make a `--resolve` argument unsafe to paste unquoted. `[*]`
69
- * is a shell glob (every multiselect wire name, `users[*]`), whitespace splits
70
- * a real name (`Coder Evals`) into two arguments, and quotes, `$`, backslash
71
- * and the control operators change what the shell hands over. The `<value>`
72
- * placeholder a template prints is stripped before the test, so a template
73
- * with nothing else unsafe keeps its bytes.
128
+ * One argument of a printed command, safe to paste into a POSIX shell or PowerShell.
129
+ *
130
+ * @param arg - The argument; `''` is returned for the empty string.
131
+ * @returns The argument as is, single-quoted, or `undefined` when no quoting is safe in both shells.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * shellArg('Lead'); // -> "Lead"
136
+ * shellArg('Lead;curl x|sh'); // -> "'Lead;curl x|sh'"
137
+ * shellArg("a';echo X;#"); // -> undefined
138
+ * ```
74
139
  */
75
- const SHELL_UNSAFE = /[\s'"`$\\[\]*?;&|(){}!#~<>]/;
140
+ export function shellArg(arg) {
141
+ if (UNQUOTABLE.test(arg))
142
+ return undefined;
143
+ return arg === '' || SHELL_UNSAFE.test(arg) ? `'${arg}'` : arg;
144
+ }
76
145
  /**
77
146
  * The argument of one `--resolve <field>:<by>=<value>`, single-quoted when the
78
147
  * shell would otherwise mangle it.
@@ -86,7 +155,7 @@ export function resolveFlagArg(field, by, value) {
86
155
  const arg = `${field}:${by}=${value}`;
87
156
  if (!SHELL_UNSAFE.test(arg.replaceAll('<value>', '')))
88
157
  return arg;
89
- return `'${arg.replaceAll("'", `'\\''`)}'`;
158
+ return singleQuote(arg);
90
159
  }
91
160
  /**
92
161
  * The command a message tells a person or agent to run when the cache is
@@ -121,7 +121,7 @@ compileRefusals = true) {
121
121
  warn('OBJECT_UNPREPARED', `${where}: object \`${object}\` has no prepared schema for `
122
122
  + `\`${sub.connector}\` \`${sub.event}\`, and this connector's objects come from `
123
123
  + `the connection, so the library cannot carry one. Materialize it:\n`
124
- + ` ${prepareCommand(connectorKey, eventName)} --object ${object}\n`
124
+ + ` ${prepareCommand(connectorKey, eventName, '--object', object)}\n`
125
125
  + `Until then its event parameters and filterable fields are unknown and `
126
126
  + `nothing here can check them.`);
127
127
  }
@@ -171,8 +171,7 @@ compileRefusals = true) {
171
171
  + `connector discovers CUSTOM FIELDS per connection, so the baked list is a `
172
172
  + `subset by design and this name may be a real field of yours. Prepare the `
173
173
  + `event against your connection to check it for real:\n`
174
- + ` ${prepareCommand(connectorKey, eventName)}`
175
- + `${object ? ` --object ${object}` : ''}\n`
174
+ + ` ${prepareCommand(connectorKey, eventName, ...(object ? ['--object', object] : []))}\n`
176
175
  + `Baked fields: ${names.slice(0, 12).join(', ')}${names.length > 12 ? ', …' : ''}.`);
177
176
  return;
178
177
  }
package/dist/decompile.js CHANGED
@@ -45,7 +45,7 @@ import { outputBackingGlobal, outputBackingName } from './flow-output-backing.js
45
45
  import { mapJsCode } from './core/js-code-spans.js';
46
46
  import { VARS_READ_RE } from './core/vars-read.js';
47
47
  import { missingBindingLabels } from './core/binding-messages.js';
48
- import { prepareCommand } from './core/cli-spelling.js';
48
+ import { placeholder, prepareCommand } from './core/cli-spelling.js';
49
49
  import { OUTCOME_HANDLE_NODE_TYPES } from './core/hitl-routing.js';
50
50
  import { contributionPort, forwardFanOut } from './core/definition-handles.js';
51
51
  import { STICKY_NOTE_TYPE } from './core/definitionless-node-types.js';
@@ -982,7 +982,7 @@ function unboundMarker(node, labels, key, action) {
982
982
  + `The source leaves ${missing.length > 1 ? 'them' : 'it'} out${isCanvasDraft(node)
983
983
  ? ' and marks the step `{ draft: true }`: compile writes it as a draft, and check refuses it'
984
984
  : ', and compile and check refuse it'} (BINDING_MISSING) until it names both labels: `
985
- + `run \`${prepareCommand(key, action ?? '<action>')}\`, then pass `
985
+ + `run \`${prepareCommand(key, action ?? placeholder('<action>'))}\`, then pass `
986
986
  + `\`connection\` and \`folder\`.`);
987
987
  return ` /* TODO: bind ${commentText(names)}; check refuses this node until it has both labels (BINDING_MISSING) */`;
988
988
  }
@@ -18,7 +18,7 @@
18
18
  * event's per-object variants are skipped because they share their template's
19
19
  * node type and so would emit the same const twice.
20
20
  */
21
- import { prepareCommand } from "../../core/cli-spelling.js";
21
+ import { placeholder, prepareCommand } from "../../core/cli-spelling.js";
22
22
  import { commentText, docComment } from "../../core/comment-text.js";
23
23
  import { PACKAGE_NAME } from "../../package-name.js";
24
24
  import { pyJsonString, pyJsonStringify } from "../codecs/pyjson.js";
@@ -207,7 +207,7 @@ export function emitEvent(entry, inFields, inputTree, outputTree, name, inputTyp
207
207
  lines.push(" * Requires a BYOA (bring-your-own-app) connection — on a standard one the");
208
208
  lines.push(" * trigger deploys and never fires. Bind it with");
209
209
  // Spelled for whoever ran the generator, like every `check` remedy.
210
- lines.push(` * \`${commentText(prepareCommand(pyStr(connectorKey), eventId, "--connection-id", "<id>"))}\`,`);
210
+ lines.push(` * \`${commentText(prepareCommand(pyStr(connectorKey), eventId, "--connection-id", placeholder("<id>")))}\`,`);
211
211
  lines.push(" * which refuses a standard connection and records the check `compile` requires;");
212
212
  lines.push(" * `uip is connections list --byoa --all-folders` lists the BYOA connections.");
213
213
  }
@@ -5,7 +5,7 @@
5
5
  * event page is unchanged. The facts are the sidecar's, which the library build
6
6
  * stamps from the event's `triggers objects` row (#848).
7
7
  */
8
- import { prepareCommand } from "../../../../core/cli-spelling.js";
8
+ import { placeholder, prepareCommand } from "../../../../core/cli-spelling.js";
9
9
  import { isEventNodeType } from "../../../model/library.js";
10
10
  import { dictOf, getStr } from "../pyvalue.js";
11
11
  export function eventFactsLines(j, v1def) {
@@ -29,7 +29,7 @@ export function eventFactsLines(j, v1def) {
29
29
  "connection that was never checked (`EVENT_BYOA_UNVERIFIED`).");
30
30
  out.push("");
31
31
  out.push("```bash");
32
- out.push(prepareCommand(key, event, "--connection-id", "<id>"));
32
+ out.push(prepareCommand(key, event, "--connection-id", placeholder("<id>")));
33
33
  out.push("uip is connections list --byoa --all-folders # the BYOA connections");
34
34
  out.push("```");
35
35
  out.push("");
package/dist/serialize.js CHANGED
@@ -57,7 +57,7 @@ import { planFlowGlobals, planSharedInputs, sharedInputRoots } from './flow-vari
57
57
  import { outputBackingGlobal, planOutputBacking } from './flow-output-backing.js';
58
58
  import { mapJsCode } from './core/js-code-spans.js';
59
59
  import { contributionPort } from './core/definition-handles.js';
60
- import { prepareCommand } from './core/cli-spelling.js';
60
+ import { placeholder, prepareCommand } from './core/cli-spelling.js';
61
61
  import { processResourceBindings } from './core/process-resource.js';
62
62
  import { types } from './core/expr.js';
63
63
  import { SUBFLOW_START_LABEL } from './core/subflow-start.js';
@@ -612,7 +612,7 @@ function resolveBinding(opts, name, attribute, where, target) {
612
612
  const fault = STUB_GUID_RE.test(value)
613
613
  ? `"401 Invalid Organization or User secret, or invalid Element token provided" — no such connection exists`
614
614
  : `"'Connection' has an invalid GUID value: '${value}'"`;
615
- const remedy = `Bind the real one: \`${prepareCommand('<connector-key>', '<action>')}\` finds the connection `
615
+ const remedy = `Bind the real one: \`${prepareCommand(placeholder('<connector-key>'), placeholder('<action>'))}\` finds the connection `
616
616
  + `and writes both entries into bindings.json (several candidates: pass \`--connection-id <id>\` from the list it `
617
617
  + `prints); by hand, read Id and FolderKey from \`uip is connections list --all-folders --output json\`.`;
618
618
  const message = resolved === undefined
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.70.7",
3
+ "version": "6.70.8",
4
4
  "description": "Build UiPath Flow, Case, and BPMN artifacts by writing TypeScript.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://docs.uipath.com/maestro",
@@ -100,5 +100,5 @@
100
100
  "@types/node": "^22.7.0",
101
101
  "esbuild": "^0.28.1"
102
102
  },
103
- "gitref": "31471f814e8ca706a02e96e3dbceb39641584de6"
103
+ "gitref": "17641bf2850dc69f377b91277d0e6dfc756b1280"
104
104
  }