@uipath/maestro-builder-sdk 6.69.0 → 6.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,22 +5,24 @@
5
5
  * Usage:
6
6
  * node --experimental-strip-types compile-cli.js <case.ts | BaseName> [-o out.json]
7
7
  *
8
- * Runs the fast static check first; if it passes, serializes to a V32
9
- * caseplan.json. The authoritative deploy gate is `uip maestro case validate`.
8
+ * Only serializes, to a V32 caseplan.json (docs/CHECK_COMPILE_CONTRACT_DESIGN.md
9
+ * D1, phase 8). It does not run `check()`'s lint rules: run `case check` first
10
+ * for those. It stops only when it cannot write a correct plan, a refusal the
11
+ * serializer throws, printed in `check`'s `✗ [CODE]` shape (and `case check`
12
+ * reports the same refusal, from the same code). The authoritative deploy gate
13
+ * is `uip maestro case validate`.
10
14
  * Output defaults to the plan file the project in the working directory ships
11
15
  * (`caseplan.case` for a project `uip maestro case init` scaffolded), else
12
16
  * `caseplan.json`. An `-o` that names a different plan file than the project
13
17
  * ships is refused (CASE_OUTPUT_NOT_SHIPPED), and so is a plan file written into
14
18
  * a solution directory above its Case project (CASE_OUTPUT_OUTSIDE_PROJECT).
15
19
  */
16
- import { reportDiagnostics, reportResult, thrownDiagnostic } from '../cli-result.js';
20
+ import { diagnosticLine, reportDiagnostics, reportResult, thrownDiagnostic } from '../cli-result.js';
17
21
  import { writeJsonFile } from '../core/json-file.js';
18
22
  import { readFileSync, existsSync, readdirSync } from 'node:fs';
19
23
  import { join, dirname, basename, resolve } from 'node:path';
20
24
  import { resolveCaseFile, loadBuiltCase } from './load.js';
21
25
  import { serialize } from './serialize.js';
22
- import { check } from './check.js';
23
- import { caseCheckOpts } from './cli-library.js';
24
26
  import { entryPointIO } from './entry-points.js';
25
27
  import { Bindings } from '../core/bindings.js';
26
28
  import { offlineBindingLabel } from './ids.js';
@@ -32,6 +34,7 @@ import { CASE_FORMAT_PROFILE } from './format-profile.js';
32
34
  import { deriveCaseBindingsV2 } from './bindings-v2.js';
33
35
  import { BINDINGS_V2_DOCUMENT_VERSION } from '../core/bindings-v2-resource.js';
34
36
  import { sha256Uuid } from '../core/stable-id.js';
37
+ import { CompileRefusal } from '../core/compile-refusal.js';
35
38
  export async function run(argv) {
36
39
  if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
37
40
  console.error('usage: compile <case.ts | BaseName> [-o <project>/caseplan.case]');
@@ -53,23 +56,13 @@ export async function run(argv) {
53
56
  // fine right after a pull on Flow failed here for no visible reason. The helper
54
57
  // also auto-detects the `connectors-local/` overlay `registry prepare` writes,
55
58
  // which is what the three copies of these lines used to each decide for itself.
56
- // Opened BEFORE the check pass, which reads the same library (#1014).
59
+ // `case check` opens it the same way (#1014).
57
60
  const library = openCliLibrary(argv);
58
61
  const { out, bindings } = caseCompileTarget(argv);
59
- const diags = check(built, caseCheckOpts(library, bindings));
60
- for (const d of diags)
61
- console.error(` ${d.level === 'error' ? '✗' : '⚠'} [${d.code}] ${d.message}`);
62
- // Reported before serialize, so every exit path carries what stderr printed.
63
- reportDiagnostics(diags);
64
- const errors = diags.filter((d) => d.level === 'error');
65
- if (errors.length) {
66
- console.error(`compile: ${errors.length} error(s); not emitting.`);
67
- return 1;
68
- }
69
62
  const shadow = shadowedOutputDiagnostic(out);
70
63
  if (shadow) {
71
64
  console.error(` ✗ [${shadow.code}] ${shadow.message} Fix: ${shadow.suggestion}.`);
72
- reportDiagnostics([...diags, shadow]);
65
+ reportDiagnostics([shadow]);
73
66
  console.error('compile: 1 error(s); not emitting.');
74
67
  return 1;
75
68
  }
@@ -78,9 +71,28 @@ export async function run(argv) {
78
71
  caseplan = serialize(built, { library, bindings });
79
72
  }
80
73
  catch (error) {
81
- reportDiagnostics([...diags, thrownDiagnostic(error)]);
82
- throw error;
74
+ if (!(error instanceof Error) || (!(error instanceof CompileRefusal) && error.message.startsWith('internal SDK error:'))) {
75
+ // A broken SDK invariant still ends the run through the caller (exit 1,
76
+ // `--json` `error`); the diagnostic is reported first.
77
+ reportDiagnostics([thrownDiagnostic(error)]);
78
+ throw error;
79
+ }
80
+ // The serializer cannot write a correct plan: a coded refusal, or a throw
81
+ // it has no refusal for (a `TypeError` on a malformed spec), which is
82
+ // COMPILE_FAILED, as `case check` reports it (`refusalOf`, serialize.ts).
83
+ const refused = error instanceof CompileRefusal
84
+ ? {
85
+ level: 'error', code: error.code, message: error.message,
86
+ ...(error.suggestion !== undefined ? { suggestion: error.suggestion } : {}),
87
+ }
88
+ : { level: 'error', code: 'COMPILE_FAILED', message: error.message };
89
+ console.error(` ${diagnosticLine(refused)}`);
90
+ reportDiagnostics([refused]);
91
+ console.error('compile: 1 error(s); not emitting.');
92
+ return 1;
83
93
  }
94
+ // Reported before the first write, so a write that throws still carries it.
95
+ reportDiagnostics([]);
84
96
  // Entry points first: each trigger carries its entry point's `uniqueId` as
85
97
  // `data.inputs.entryPointId`, so the plan is written after the ids are known.
86
98
  const triggers = syncEntryPoints(caseplan, out);
@@ -209,6 +209,7 @@ export declare const REFUSALS: {
209
209
  readonly DATAFABRIC_SYSTEM_COLUMN: "lint";
210
210
  readonly DEAD_END: "lint";
211
211
  readonly DECLARATION_SHAPE: "lowering";
212
+ readonly DECLARATION_TYPE_NOT_FLOW: "lowering";
212
213
  readonly DECLARATION_TYPE_UNKNOWN: "lowering";
213
214
  readonly DECOMPILE_NOT_A_NUMBER: "lowering";
214
215
  readonly DECOMPILE_VARIABLES_SHAPE: "lowering";
@@ -21,10 +21,10 @@
21
21
  * they get different codes, so one code never both stops compile and lets it
22
22
  * write.
23
23
  *
24
- * Since `compile` no longer runs `check` (#1497), a `lint` code is only right
24
+ * Since `compile` no longer runs `check` (Flow #1497, Case #1446), a `lint` code is only right
25
25
  * when the serializer still writes what the source says while the rule fires:
26
- * otherwise `compile` writes a wrong `.flow` without a word, and the code is
27
- * `lowering` (the serializer must refuse it). Every Flow `lint` code has a row
26
+ * otherwise `compile` writes a wrong `.flow` (or caseplan) without a word, and the code is
27
+ * `lowering` (the serializer must refuse it). Every Flow, Case and BPMN `lint` code has a row
28
28
  * in `tests/lint-lossless/` (#1518): a round-trip fixture, a fixture the
29
29
  * serializer refuses, or a written reason. The round trip shows the rule's
30
30
  * condition survives compile -> decompile -> compile and that compile is
@@ -261,6 +261,7 @@ export const REFUSALS = {
261
261
  DATAFABRIC_SYSTEM_COLUMN: 'lint',
262
262
  DEAD_END: 'lint',
263
263
  DECLARATION_SHAPE: 'lowering',
264
+ DECLARATION_TYPE_NOT_FLOW: 'lowering',
264
265
  DECLARATION_TYPE_UNKNOWN: 'lowering',
265
266
  DECOMPILE_NOT_A_NUMBER: 'lowering',
266
267
  DECOMPILE_VARIABLES_SHAPE: 'lowering',
package/dist/decompile.js CHANGED
@@ -39,6 +39,7 @@ import { tsKey as key, tsLiteral, tsNumber, tsObject as objLit, tsOptions as opt
39
39
  import { wireExprBody } from './core/wire-expr.js';
40
40
  import { hasExits } from './core/step-ports.js';
41
41
  import { readFlowGlobals } from './flow-variables.js';
42
+ import { FLOW_TYPE_NAMES, nonFlowTypeReplacement, runtimeEquivalentFlowType } from './flow-types.js';
42
43
  import { outputBackingGlobal, outputBackingName } from './flow-output-backing.js';
43
44
  import { mapJsCode } from './core/js-code-spans.js';
44
45
  import { VARS_READ_RE } from './core/vars-read.js';
@@ -1272,15 +1273,42 @@ function camel(id) {
1272
1273
  return head.charAt(0).toLowerCase() + head.slice(1) + rest.map((r) => r.charAt(0).toUpperCase() + r.slice(1)).join('');
1273
1274
  }
1274
1275
  // ─── Variables ────────────────────────────────────────────────────────────────
1275
- const TYPE_NAMES = new Set([
1276
- 'string', 'number', 'boolean', 'object', 'array', 'file', 'any',
1277
- 'integer', 'float', 'double', 'date', 'datetime',
1278
- ]);
1279
- /** `types.<name>` when the type is a known descriptor, else a defensive string literal. */
1280
- function typeExpr(type, imp) {
1281
- if (TYPE_NAMES.has(type))
1282
- return `${imp.use('types')}.${type}`;
1283
- return tsLiteral(type);
1276
+ const TYPE_NAMES = new Set(FLOW_TYPE_NAMES);
1277
+ /**
1278
+ * `types.<name>` for a global's type (#861).
1279
+ *
1280
+ * A Flow type prints as itself. Every other type warns once per variable (an
1281
+ * error when `bestEffort` is false), and then:
1282
+ * - `date` / `datetime` print as `types.string`, the type Flow packaging
1283
+ * already gives them, so an untouched global never blocks a brownfield
1284
+ * edit. The recompiled `.flow` says `"type":"string"`; the warning says so.
1285
+ * - `float`, `double` and `jsonSchema` print as written (`types.float`),
1286
+ * because a recompile would lose a format or a schema kind: the declaration
1287
+ * is a TypeScript error and `DECLARATION_TYPE_NOT_FLOW` at build until the
1288
+ * author picks the type the warning names.
1289
+ * - any other string prints as a string literal: `DECLARATION_TYPE_UNKNOWN`.
1290
+ */
1291
+ function typeExpr(g, imp) {
1292
+ if (TYPE_NAMES.has(g.type))
1293
+ return `${imp.use('types')}.${g.type}`;
1294
+ const replacement = nonFlowTypeReplacement(g.type);
1295
+ const equivalent = runtimeEquivalentFlowType(g.type);
1296
+ const head = `variable ${tsLiteral(g.id)} has type ${tsLiteral(g.type)}`;
1297
+ const message = equivalent !== undefined
1298
+ ? `${head}, a Case type Flow does not model. The source declares it types.${equivalent}, so a recompile `
1299
+ + `writes "type":"${equivalent}" in its place; nothing changes at run time, because flow pack already `
1300
+ + `writes a ${g.type} as a plain string.`
1301
+ : replacement !== undefined
1302
+ ? `${head}, a Case type Flow does not model (packaging and the Workbench do not know it). The source `
1303
+ + `keeps types.${g.type}, which the builder refuses (DECLARATION_TYPE_NOT_FLOW): declare it as ${replacement}.`
1304
+ : `${head}, which is not a Flow type. The source keeps it as a string, which the builder refuses `
1305
+ + `(DECLARATION_TYPE_UNKNOWN): declare one of ${FLOW_TYPE_NAMES.map((t) => `types.${t}`).join(', ')}.`;
1306
+ if (runStrict)
1307
+ throw new Error(`decompile: ${message}`);
1308
+ warnOnce(message);
1309
+ if (equivalent !== undefined)
1310
+ return `${imp.use('types')}.${equivalent}`;
1311
+ return replacement !== undefined ? `${imp.use('types')}.${g.type}` : tsLiteral(g.type);
1284
1312
  }
1285
1313
  /**
1286
1314
  * A global carrying metadata decompiles to the rich VarSpec spelling
@@ -1300,8 +1328,8 @@ function declExpr(g, withDefault, imp, shared) {
1300
1328
  if (shared !== undefined)
1301
1329
  meta.push(`shared: ${tsLiteral(shared)}`);
1302
1330
  if (meta.length === 0)
1303
- return typeExpr(g.type, imp);
1304
- return `{ type: ${typeExpr(g.type, imp)}, ${meta.join(', ')} }`;
1331
+ return typeExpr(g, imp);
1332
+ return `{ type: ${typeExpr(g, imp)}, ${meta.join(', ')} }`;
1305
1333
  }
1306
1334
  function sharedCopies(flow, triggers) {
1307
1335
  const globals = readFlowGlobals(flow.variables, runStrict);
@@ -38,7 +38,9 @@ export * from './core/lookups.js';
38
38
  export * from './core/node-classes.js';
39
39
  export * from './raw-node.js';
40
40
  import { Expr } from './core/expr.js';
41
- import type { ErrorEnvelopeField, TypeDesc } from './core/expr.js';
41
+ import type { ErrorEnvelopeField } from './core/expr.js';
42
+ import { type FlowTypeDesc } from './flow-types.js';
43
+ export type { FlowTypeDesc } from './flow-types.js';
42
44
  import type { ActionSpec, EventSubscription, TriggerOptions } from './core/actions.js';
43
45
  import type { FlowAction, FlowTrigger } from './core/node-classes.js';
44
46
  import type { TriggerDescriptor } from './core/connectors.js';
@@ -60,7 +62,7 @@ export type ChildFlow = BuiltFlow | {
60
62
  };
61
63
  export interface VarDecl {
62
64
  name: string;
63
- type: TypeDesc;
65
+ type: FlowTypeDesc;
64
66
  default?: unknown;
65
67
  /** Human-readable description, persisted on the variable. */
66
68
  description?: string;
@@ -80,7 +82,7 @@ export interface VarDecl {
80
82
  */
81
83
  export interface VarSpec {
82
84
  /** The variable's type, one of the `types.*` descriptors. */
83
- type: TypeDesc;
85
+ type: FlowTypeDesc;
84
86
  /** Human-readable description, persisted on the variable. */
85
87
  description?: string;
86
88
  /** Sub-type for complex types (e.g. an array's item type). */
@@ -1563,7 +1565,7 @@ declare class FlowBuilder extends StepList {
1563
1565
  * @returns This builder, so calls chain.
1564
1566
  */
1565
1567
  entryPoint(id: string, trigger: TriggerSpec | FlowTrigger, options?: Pick<NodeOptions, 'version' | 'label'> & {
1566
- inputs?: Record<string, TypeDesc | VarSpec>;
1568
+ inputs?: Record<string, FlowTypeDesc | VarSpec>;
1567
1569
  }, prefixFn?: (b: StepList) => void): this;
1568
1570
  /**
1569
1571
  * Rename the trigger node. The designer can rename it, so the SDK can too.
@@ -1732,7 +1734,7 @@ declare class FlowBuilder extends StepList {
1732
1734
  * @returns This builder, so calls chain.
1733
1735
  * @see input
1734
1736
  */
1735
- input(shape: Record<string, TypeDesc | VarSpec>): this;
1737
+ input(shape: Record<string, FlowTypeDesc | VarSpec>): this;
1736
1738
  /**
1737
1739
  * Declare the flow's outputs — what `.return(...)` binds values to.
1738
1740
  *
@@ -1768,7 +1770,7 @@ declare class FlowBuilder extends StepList {
1768
1770
  * @param shape - Output names to type descriptors, e.g. `{ total: types.number }`.
1769
1771
  * @returns This builder, so calls chain.
1770
1772
  */
1771
- output(shape: Record<string, TypeDesc | VarSpec>): this;
1773
+ output(shape: Record<string, FlowTypeDesc | VarSpec>): this;
1772
1774
  /**
1773
1775
  * Declare a flow-level variable. Read it with `v('<name>')`.
1774
1776
  *
@@ -1778,7 +1780,7 @@ declare class FlowBuilder extends StepList {
1778
1780
  * @returns This builder, so calls chain.
1779
1781
  * @see v
1780
1782
  */
1781
- var(name: string, type: TypeDesc | VarSpec, defaultValue?: unknown): this;
1783
+ var(name: string, type: FlowTypeDesc | VarSpec, defaultValue?: unknown): this;
1782
1784
  /**
1783
1785
  * Finish the flow and return the graph the compiler serializes.
1784
1786
  *
package/dist/flow-sdk.js CHANGED
@@ -42,7 +42,8 @@ export * from './core/connectors.js';
42
42
  export * from './core/lookups.js';
43
43
  export * from './core/node-classes.js';
44
44
  export * from './raw-node.js';
45
- import { err as errRef, toExpr, types } from './core/expr.js';
45
+ import { err as errRef, toExpr } from './core/expr.js';
46
+ import { FLOW_TYPE_NAMES, nonFlowTypeReplacement } from './flow-types.js';
46
47
  import { builtinActionSpec, builtinTriggerSpec, subscriptionFrom } from './core/actions.js';
47
48
  import { checkFlowExpressions, FlowBuildError } from './flow-expr-check.js';
48
49
  import { FLOW_SCHEMA_VERSIONS } from './format-profile.js';
@@ -50,7 +51,6 @@ import { schemaVersionRefusal } from './schema-version.js';
50
51
  import { indexCarriedDefinitions } from './core/carried-definitions.js';
51
52
  import { CompileRefusal } from './core/compile-refusal.js';
52
53
  export { FlowBuildError, checkFlowExpressions } from './flow-expr-check.js';
53
- const TYPE_NAMES = Object.values(types);
54
54
  /**
55
55
  * Reject a `.input()` / `.output()` argument that is not a `{ name: type }` map.
56
56
  *
@@ -79,7 +79,7 @@ function assertShape(method, shape) {
79
79
  return shape;
80
80
  }
81
81
  /**
82
- * Normalize a `TypeDesc | VarSpec` declaration value into VarDecl fields.
82
+ * Normalize a `FlowTypeDesc | VarSpec` declaration value into VarDecl fields.
83
83
  * Every direction takes a `default`: the format's `workflowVariableSchema` allows
84
84
  * `defaultValue` on `in`, `out` and `inout` alike, and the v1 CLI's
85
85
  * `variable add --direction out --default-value` writes one on an output.
@@ -111,12 +111,26 @@ function varDeclOf(method, name, value) {
111
111
  assertType(method, name, value);
112
112
  return { type: value };
113
113
  }
114
- /** A declared variable's type must be one of the seven `types.*` names. */
114
+ /**
115
+ * A declared variable's type must be a Flow type ({@link FlowTypeDesc}).
116
+ *
117
+ * TypeScript already refuses `types.date` here; this is the same rule for a
118
+ * caller TypeScript does not check (plain JS, a type built at run time).
119
+ * A Case-only member of `types` gets its own code, `DECLARATION_TYPE_NOT_FLOW`,
120
+ * naming the Flow type to use; anything else is `DECLARATION_TYPE_UNKNOWN`.
121
+ */
115
122
  function assertType(method, name, type) {
116
- if (typeof type === 'string' && TYPE_NAMES.includes(type))
123
+ if (typeof type === 'string' && FLOW_TYPE_NAMES.includes(type))
117
124
  return;
125
+ const flowTypes = FLOW_TYPE_NAMES.map((t) => `types.${t}`).join(', ');
126
+ const replacement = typeof type === 'string' ? nonFlowTypeReplacement(type) : undefined;
127
+ if (replacement !== undefined) {
128
+ throw new CompileRefusal('DECLARATION_TYPE_NOT_FLOW', `.${method}() declared ${JSON.stringify(name)} with types.${String(type)}, which is a Case type: `
129
+ + `Flow does not model it (packaging and the Workbench do not know it). Use ${replacement}. `
130
+ + `A Flow variable takes one of ${flowTypes}.`);
131
+ }
118
132
  throw new CompileRefusal('DECLARATION_TYPE_UNKNOWN', `.${method}() declared ${JSON.stringify(name)} with type ${JSON.stringify(type)}, which is not `
119
- + `a type. Use one of ${TYPE_NAMES.map((t) => `types.${t}`).join(', ')}.`);
133
+ + `a type. Use one of ${flowTypes}.`);
120
134
  }
121
135
  // ─── Triggers (what starts the flow) ────────────────────────────────────────
122
136
  //
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Which `types.*` descriptors a Flow variable may declare.
3
+ *
4
+ * `types` (`core/expr.ts`) is one vocabulary for every builder, but Flow models
5
+ * fewer types than Case does. Before this split, `flow().input({ d: types.date })`
6
+ * passed `check`, compiled, and carried `"type":"date"` into the `.flow`
7
+ * (UiPath/builder-sdk#861). This module is the Flow side of the split: the
8
+ * builder's `.input` / `.output` / `.var` take a {@link FlowTypeDesc}, and its
9
+ * run-time guard and the decompiler read {@link FLOW_TYPE_NAMES}.
10
+ */
11
+ import type { TypeDesc } from './core/expr.js';
12
+ /**
13
+ * Every `types.*` member, and whether Flow takes it. A `string` value is the
14
+ * Flow type to use instead, for the refusal message.
15
+ *
16
+ * Flow's own tools agree on the `true` set:
17
+ * - the Workbench variable picker offers `string number boolean object array file`;
18
+ * - `flow pack` (`@uipath/flow-schema` `mapTypeToJsonSchema`) and the canvas
19
+ * expression model (`mapTypeToTypeScript`) both map `integer` to an integer
20
+ * / number, and `uip maestro flow validate` accepts it (UiPath/cli#5616);
21
+ * - `any` is the SDK's own untyped declaration (typeless in an agent schema).
22
+ *
23
+ * The others are Case-only. Packaging turns `date` / `datetime` into a plain
24
+ * `string` with no format, the expression model types `float` / `double` /
25
+ * `jsonSchema` as `any`, and no Flow editor offers any of them.
26
+ *
27
+ * `satisfies Record<TypeDesc, …>` makes this exhaustive: adding a type to
28
+ * `types` without deciding whether Flow takes it is a compile error here.
29
+ */
30
+ declare const flowTypeSupport: {
31
+ readonly string: true;
32
+ readonly number: true;
33
+ readonly boolean: true;
34
+ readonly object: true;
35
+ readonly array: true;
36
+ readonly file: true;
37
+ readonly any: true;
38
+ readonly integer: true;
39
+ readonly float: "types.number";
40
+ readonly double: "types.number";
41
+ readonly date: "types.string";
42
+ readonly datetime: "types.string";
43
+ readonly jsonSchema: "types.object or types.array, with its shape in { schema }";
44
+ };
45
+ /**
46
+ * A `types.*` descriptor a Flow variable may declare: every member of `types`
47
+ * but the Case-only `float`, `double`, `date`, `datetime` and `jsonSchema`.
48
+ */
49
+ export type FlowTypeDesc = {
50
+ [K in TypeDesc]: (typeof flowTypeSupport)[K] extends true ? K : never;
51
+ }[TypeDesc];
52
+ /** The `types.*` names a Flow variable may declare, in `types` order. */
53
+ export declare const FLOW_TYPE_NAMES: readonly FlowTypeDesc[];
54
+ /**
55
+ * For a `types.*` name Flow does not take, what to declare instead
56
+ * (`'date'` → `'types.string'`). `undefined` for a Flow type, and for a name
57
+ * that is not in `types` at all.
58
+ */
59
+ export declare function nonFlowTypeReplacement(type: string): string | undefined;
60
+ /**
61
+ * The Flow type a Case-only type already IS once Flow packages it, for the
62
+ * ones where the two are the same at run time: `date` and `datetime`, which
63
+ * `flow pack` (`mapTypeToJsonSchema`) writes as a plain `string` with no
64
+ * format. Decompile prints this type for such a global, so a `.flow` that an
65
+ * older SDK or Studio Web wrote still round-trips; the recompile writes
66
+ * `"type":"string"`, which the decompile warning announces.
67
+ *
68
+ * `undefined` for every other type: `float` / `double` lose a format and
69
+ * `jsonSchema` a schema kind, so those keep the builder's hard stop.
70
+ */
71
+ export declare function runtimeEquivalentFlowType(type: string): FlowTypeDesc | undefined;
72
+ export {};
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Every `types.*` member, and whether Flow takes it. A `string` value is the
3
+ * Flow type to use instead, for the refusal message.
4
+ *
5
+ * Flow's own tools agree on the `true` set:
6
+ * - the Workbench variable picker offers `string number boolean object array file`;
7
+ * - `flow pack` (`@uipath/flow-schema` `mapTypeToJsonSchema`) and the canvas
8
+ * expression model (`mapTypeToTypeScript`) both map `integer` to an integer
9
+ * / number, and `uip maestro flow validate` accepts it (UiPath/cli#5616);
10
+ * - `any` is the SDK's own untyped declaration (typeless in an agent schema).
11
+ *
12
+ * The others are Case-only. Packaging turns `date` / `datetime` into a plain
13
+ * `string` with no format, the expression model types `float` / `double` /
14
+ * `jsonSchema` as `any`, and no Flow editor offers any of them.
15
+ *
16
+ * `satisfies Record<TypeDesc, …>` makes this exhaustive: adding a type to
17
+ * `types` without deciding whether Flow takes it is a compile error here.
18
+ */
19
+ const flowTypeSupport = {
20
+ string: true,
21
+ number: true,
22
+ boolean: true,
23
+ object: true,
24
+ array: true,
25
+ file: true,
26
+ any: true,
27
+ integer: true,
28
+ float: 'types.number',
29
+ double: 'types.number',
30
+ date: 'types.string',
31
+ datetime: 'types.string',
32
+ jsonSchema: 'types.object or types.array, with its shape in { schema }',
33
+ };
34
+ /** The `types.*` names a Flow variable may declare, in `types` order. */
35
+ export const FLOW_TYPE_NAMES = Object.entries(flowTypeSupport)
36
+ .filter(([, support]) => support === true)
37
+ .map(([name]) => name);
38
+ /**
39
+ * For a `types.*` name Flow does not take, what to declare instead
40
+ * (`'date'` → `'types.string'`). `undefined` for a Flow type, and for a name
41
+ * that is not in `types` at all.
42
+ */
43
+ export function nonFlowTypeReplacement(type) {
44
+ if (!Object.prototype.hasOwnProperty.call(flowTypeSupport, type))
45
+ return undefined;
46
+ const support = flowTypeSupport[type];
47
+ return support === true ? undefined : support;
48
+ }
49
+ /**
50
+ * The Flow type a Case-only type already IS once Flow packages it, for the
51
+ * ones where the two are the same at run time: `date` and `datetime`, which
52
+ * `flow pack` (`mapTypeToJsonSchema`) writes as a plain `string` with no
53
+ * format. Decompile prints this type for such a global, so a `.flow` that an
54
+ * older SDK or Studio Web wrote still round-trips; the recompile writes
55
+ * `"type":"string"`, which the decompile warning announces.
56
+ *
57
+ * `undefined` for every other type: `float` / `double` lose a format and
58
+ * `jsonSchema` a schema kind, so those keep the builder's hard stop.
59
+ */
60
+ export function runtimeEquivalentFlowType(type) {
61
+ return type === 'date' || type === 'datetime' ? 'string' : undefined;
62
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.69.0",
3
+ "version": "6.70.0",
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": "f1c4fc99c993d7cc8defcda32496be344f018a23"
103
+ "gitref": "990446f9254b96a4cb0cbfc1a3ec7f99deaabe5e"
104
104
  }