@uipath/packager-tool-flow 1.195.0 → 1.196.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.
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Replace the BPMN `exporterVersion="development"` placeholder produced by
3
+ * `@uipath/flow-converter` with a real version string.
4
+ *
5
+ * Why: Studio Web treats `exporterVersion="development"` as dev-build content
6
+ * and locks the file read-only ("cannot save"). Published CLI bundles must
7
+ * emit a real version so Studio Web accepts the uploaded BPMN for editing.
8
+ */
9
+ export declare const replaceExporterVersion: (bpmnXml: string, version: string) => string;
package/dist/flow-io.d.ts CHANGED
@@ -2,7 +2,22 @@ import { type IFileSystem } from "@uipath/filesystem";
2
2
  import { type Workflow } from "@uipath/flow-schema";
3
3
  export type FlowIoLogger = {
4
4
  warn: (message: string) => void;
5
+ debug?: (message: string) => void;
5
6
  };
7
+ /**
8
+ * Migrate a freshly-parsed raw workflow document to the current schema
9
+ * version, in memory. `inMemoryWorkflowToFileFormat` refuses to serialize a
10
+ * workflow whose `version` predates the current one (the flow-schema
11
+ * migration contract), so every read that can reach a serialize path —
12
+ * debug, format, pack, node/edge edits — must migrate first, the same way
13
+ * the canvas migrates on open. The source file is never touched; the
14
+ * migrated version is persisted only when a caller explicitly writes back.
15
+ *
16
+ * Fail-soft: a missing/current `version`, an unknown version with no
17
+ * migration chain, or a failing chain step all return the document
18
+ * unchanged — the serializer guard remains the backstop, exactly as before.
19
+ */
20
+ export declare function migrateRawWorkflow(raw: unknown, logger?: FlowIoLogger): unknown;
6
21
  export interface ReadFlowWorkflowOptions {
7
22
  /** Filesystem to read from. Defaults to `getFileSystem()`. */
8
23
  fs?: IFileSystem;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { type FlowIoLogger, readFlowWorkflow } from "./flow-io.js";
1
+ export { replaceExporterVersion } from "./exporter-version.js";
2
+ export { type FlowIoLogger, migrateRawWorkflow, readFlowWorkflow, } from "./flow-io.js";
2
3
  export { FlowTool } from "./flow-tool.js";
3
4
  export { FlowToolFactory } from "./flow-tool-factory.js";
4
5
  export { setPublishIntentOnInlineAgents } from "./inline-agent-utils.js";
package/dist/index.js CHANGED
@@ -27,6 +27,74 @@ import {
27
27
  ToolErrorCodes,
28
28
  ToolResult
29
29
  } from "@uipath/solutionpackager-tool-core";
30
+ // package.json
31
+ var package_default = {
32
+ name: "@uipath/packager-tool-flow",
33
+ version: "1.196.0",
34
+ description: "UiPath Flow tool implementation",
35
+ type: "module",
36
+ exports: {
37
+ ".": {
38
+ source: "./src/index.ts",
39
+ default: "./dist/index.js"
40
+ }
41
+ },
42
+ repository: {
43
+ type: "git",
44
+ url: "https://github.com/UiPath/cli.git",
45
+ directory: "packages/packager/packager-tool-flow"
46
+ },
47
+ publishConfig: {
48
+ registry: "https://npm.pkg.github.com/"
49
+ },
50
+ types: "./dist/index.d.ts",
51
+ scripts: {
52
+ build: "bun build ./src/index.ts --outdir dist --format esm --target browser --external @uipath/filesystem --external @uipath/solutionpackager-tool-core --external @uipath/tool-agent --external @uipath/flow-core --external @uipath/flow-converter --external @uipath/flow-migrations --external @uipath/flow-schema && tsc --emitDeclarationOnly --outDir dist",
53
+ dev: "bun build ./src/index.ts --outdir dist --format esm --target browser --external @uipath/filesystem --external @uipath/solutionpackager-tool-core --external @uipath/tool-agent --external @uipath/flow-core --external @uipath/flow-converter --external @uipath/flow-migrations --external @uipath/flow-schema --watch",
54
+ test: "vitest run",
55
+ "test:browser": "vitest run --config=vitest.browser.config.ts",
56
+ "test:coverage": "vitest run --coverage",
57
+ "test:browser:coverage": "vitest run --config=vitest.browser.config.ts --coverage",
58
+ "test:all": "bun run test && bun run test:browser",
59
+ "test:all:coverage": "bun run test:coverage && bun run test:browser:coverage",
60
+ prepack: "bun run build",
61
+ "publish:dry": "bun publish --dry-run",
62
+ "publish:gh": "bun publish",
63
+ "version:patch": "bun version patch --no-git-tag-version",
64
+ "version:minor": "bun version minor --no-git-tag-version",
65
+ "version:major": "bun version major --no-git-tag-version",
66
+ lint: "biome check ."
67
+ },
68
+ files: [
69
+ "dist",
70
+ "!dist/**/*.map",
71
+ "src"
72
+ ],
73
+ author: "",
74
+ license: "ISC",
75
+ peerDependencies: {
76
+ "@uipath/filesystem": "workspace:*",
77
+ "@uipath/flow-converter": "^0.1.312",
78
+ "@uipath/flow-core": "^0.2.415",
79
+ "@uipath/flow-migrations": "^0.1.214",
80
+ "@uipath/flow-schema": "^0.2.534",
81
+ "@uipath/solutionpackager-tool-core": "workspace:*",
82
+ "@uipath/tool-agent": "^1.2.6"
83
+ },
84
+ devDependencies: {
85
+ "@types/node": "^25.5.2",
86
+ "@uipath/filesystem": "workspace:*",
87
+ "@uipath/flow-core": "^0.2.415",
88
+ "@uipath/solutionpackager-tool-core": "workspace:*",
89
+ "@uipath/tool-agent": "^1.2.6",
90
+ "@vitest/browser": "^4.1.6",
91
+ "@vitest/browser-playwright": "^4.1.6",
92
+ "@vitest/coverage-v8": "^4.1.6",
93
+ playwright: "^1.57.0",
94
+ typescript: "^6.0.2",
95
+ vitest: "^4.1.6"
96
+ }
97
+ };
30
98
 
31
99
  // src/agents.ts
32
100
  import { Path as Path2 } from "@uipath/solutionpackager-tool-core";
@@ -197,13 +265,40 @@ function ensureProcessBindings(workflow, logger) {
197
265
  return bindingsCreated;
198
266
  }
199
267
 
268
+ // src/exporter-version.ts
269
+ var replaceExporterVersion = (bpmnXml, version) => bpmnXml.replace(/exporterVersion="development"/g, () => `exporterVersion="${version}"`);
270
+
200
271
  // src/flow-io.ts
201
272
  import { getFileSystem } from "@uipath/filesystem";
273
+ import {
274
+ currentVersion,
275
+ migrateWorkflow,
276
+ migrations
277
+ } from "@uipath/flow-migrations";
202
278
  import { resolveAndConvertWorkflow } from "@uipath/flow-schema";
279
+ function migrateRawWorkflow(raw, logger) {
280
+ const doc = raw;
281
+ if (!doc?.version || doc.version === currentVersion) {
282
+ return raw;
283
+ }
284
+ try {
285
+ const result = migrateWorkflow(migrations, doc, currentVersion);
286
+ if (!result.migrated) {
287
+ const detail = result.error ? `: [${result.error.step}] ${result.error.message}` : "";
288
+ logger?.warn(`migrateRawWorkflow: migration ${result.fromVersion} -> ${result.toVersion} did not apply${detail}`);
289
+ return raw;
290
+ }
291
+ logger?.debug?.(`migrateRawWorkflow: migrated workflow ${result.fromVersion} -> ${result.toVersion}`);
292
+ return result.workflow;
293
+ } catch (err) {
294
+ logger?.warn(`migrateRawWorkflow: failed to migrate v${String(doc.version)} workflow: ${err instanceof Error ? err.message : String(err)}`);
295
+ return raw;
296
+ }
297
+ }
203
298
  async function readFlowWorkflow(filePath, options = {}) {
204
299
  const fs = options.fs ?? getFileSystem();
205
300
  const logger = options.logger;
206
- const raw = JSON.parse(await readUtf8(fs, filePath));
301
+ const raw = migrateRawWorkflow(JSON.parse(await readUtf8(fs, filePath)), logger);
207
302
  const resolver = async (refPath, baseUri) => {
208
303
  const resolvedPath = fs.path.resolve(fs.path.dirname(baseUri), refPath);
209
304
  const refContent = await readUtf8OrNull(fs, resolvedPath);
@@ -368,7 +463,8 @@ class FlowTool extends ProjectTool {
368
463
  const fileFormat = inMemoryWorkflowToFileFormat(workflow);
369
464
  setPublishIntentOnInlineAgents(fileFormat);
370
465
  const resolvedFlowJson = JSON.stringify(fileFormat);
371
- const { bpmn } = await convertFlowToBpmn(resolvedFlowJson);
466
+ const { bpmn: rawBpmn } = await convertFlowToBpmn(resolvedFlowJson);
467
+ const bpmn = replaceExporterVersion(rawBpmn, package_default.version);
372
468
  await this.fileSystem.writeFile(bpmnPath, bpmn);
373
469
  const packagingNodes = (workflow.nodes ?? []).map((node) => ({
374
470
  id: node.id,
@@ -564,7 +660,9 @@ class FlowToolFactory {
564
660
  toolsFactoryRepository.registerProjectToolFactory(new FlowToolFactory);
565
661
  export {
566
662
  setPublishIntentOnInlineAgents,
663
+ replaceExporterVersion,
567
664
  readFlowWorkflow,
665
+ migrateRawWorkflow,
568
666
  FlowToolFactory,
569
667
  FlowTool
570
668
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/packager-tool-flow",
3
- "version": "1.195.0",
3
+ "version": "1.196.0",
4
4
  "description": "UiPath Flow tool implementation",
5
5
  "type": "module",
6
6
  "exports": {
@@ -26,12 +26,13 @@
26
26
  "author": "",
27
27
  "license": "ISC",
28
28
  "peerDependencies": {
29
- "@uipath/filesystem": "1.195.0",
30
- "@uipath/flow-converter": "^0.1.273",
31
- "@uipath/flow-core": "^0.2.376",
32
- "@uipath/flow-schema": "^0.2.495",
33
- "@uipath/solutionpackager-tool-core": "1.195.0",
34
- "@uipath/tool-agent": "^1.2.4"
29
+ "@uipath/filesystem": "1.196.0",
30
+ "@uipath/flow-converter": "^0.1.312",
31
+ "@uipath/flow-core": "^0.2.415",
32
+ "@uipath/flow-migrations": "^0.1.214",
33
+ "@uipath/flow-schema": "^0.2.534",
34
+ "@uipath/solutionpackager-tool-core": "1.196.0",
35
+ "@uipath/tool-agent": "^1.2.6"
35
36
  },
36
- "gitHead": "eecf5713cd579b15783c770d1923e44e730271ea"
37
+ "gitHead": "94d71f9c52214980a1f0ae62b3f5372095788553"
37
38
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Replace the BPMN `exporterVersion="development"` placeholder produced by
3
+ * `@uipath/flow-converter` with a real version string.
4
+ *
5
+ * Why: Studio Web treats `exporterVersion="development"` as dev-build content
6
+ * and locks the file read-only ("cannot save"). Published CLI bundles must
7
+ * emit a real version so Studio Web accepts the uploaded BPMN for editing.
8
+ */
9
+ export const replaceExporterVersion = (
10
+ bpmnXml: string,
11
+ version: string,
12
+ ): string =>
13
+ // Use a replacer function so any `$` sequences in `version` (e.g. `$&`,
14
+ // `$1`) are not interpreted by String.prototype.replace.
15
+ bpmnXml.replace(
16
+ /exporterVersion="development"/g,
17
+ () => `exporterVersion="${version}"`,
18
+ );
package/src/flow-io.ts CHANGED
@@ -1,10 +1,63 @@
1
1
  import { getFileSystem, type IFileSystem } from "@uipath/filesystem";
2
+ import {
3
+ currentVersion,
4
+ type MigrationWorkflow,
5
+ migrateWorkflow,
6
+ migrations,
7
+ } from "@uipath/flow-migrations";
2
8
  import { resolveAndConvertWorkflow, type Workflow } from "@uipath/flow-schema";
3
9
 
4
10
  export type FlowIoLogger = {
5
11
  warn: (message: string) => void;
12
+ debug?: (message: string) => void;
6
13
  };
7
14
 
15
+ /**
16
+ * Migrate a freshly-parsed raw workflow document to the current schema
17
+ * version, in memory. `inMemoryWorkflowToFileFormat` refuses to serialize a
18
+ * workflow whose `version` predates the current one (the flow-schema
19
+ * migration contract), so every read that can reach a serialize path —
20
+ * debug, format, pack, node/edge edits — must migrate first, the same way
21
+ * the canvas migrates on open. The source file is never touched; the
22
+ * migrated version is persisted only when a caller explicitly writes back.
23
+ *
24
+ * Fail-soft: a missing/current `version`, an unknown version with no
25
+ * migration chain, or a failing chain step all return the document
26
+ * unchanged — the serializer guard remains the backstop, exactly as before.
27
+ */
28
+ export function migrateRawWorkflow(
29
+ raw: unknown,
30
+ logger?: FlowIoLogger,
31
+ ): unknown {
32
+ const doc = raw as MigrationWorkflow | null;
33
+ if (!doc?.version || doc.version === currentVersion) {
34
+ return raw;
35
+ }
36
+ try {
37
+ const result = migrateWorkflow(migrations, doc, currentVersion);
38
+ if (!result.migrated) {
39
+ const detail = result.error
40
+ ? `: [${result.error.step}] ${result.error.message}`
41
+ : "";
42
+ logger?.warn(
43
+ `migrateRawWorkflow: migration ${result.fromVersion} -> ${result.toVersion} did not apply${detail}`,
44
+ );
45
+ return raw;
46
+ }
47
+ logger?.debug?.(
48
+ `migrateRawWorkflow: migrated workflow ${result.fromVersion} -> ${result.toVersion}`,
49
+ );
50
+ return result.workflow;
51
+ } catch (err) {
52
+ logger?.warn(
53
+ `migrateRawWorkflow: failed to migrate v${String(doc.version)} workflow: ${
54
+ err instanceof Error ? err.message : String(err)
55
+ }`,
56
+ );
57
+ return raw;
58
+ }
59
+ }
60
+
8
61
  export interface ReadFlowWorkflowOptions {
9
62
  /** Filesystem to read from. Defaults to `getFileSystem()`. */
10
63
  fs?: IFileSystem;
@@ -33,7 +86,10 @@ export async function readFlowWorkflow(
33
86
  ): Promise<Workflow> {
34
87
  const fs = options.fs ?? getFileSystem();
35
88
  const logger = options.logger;
36
- const raw = JSON.parse(await readUtf8(fs, filePath));
89
+ const raw = migrateRawWorkflow(
90
+ JSON.parse(await readUtf8(fs, filePath)),
91
+ logger,
92
+ );
37
93
 
38
94
  const resolver = async (refPath: string, baseUri: string) => {
39
95
  const resolvedPath = fs.path.resolve(fs.path.dirname(baseUri), refPath);
package/src/flow-tool.ts CHANGED
@@ -33,8 +33,10 @@ import {
33
33
  ToolErrorCodes,
34
34
  ToolResult,
35
35
  } from "@uipath/solutionpackager-tool-core";
36
+ import pkg from "../package.json" with { type: "json" };
36
37
  import { processAgents } from "./agents.js";
37
38
  import { ensureProcessBindings } from "./ensure-process-bindings.js";
39
+ import { replaceExporterVersion } from "./exporter-version.js";
38
40
  import { readFlowWorkflow } from "./flow-io.js";
39
41
  import { setPublishIntentOnInlineAgents } from "./inline-agent-utils.js";
40
42
 
@@ -262,7 +264,8 @@ export class FlowTool extends ProjectTool {
262
264
  const fileFormat = inMemoryWorkflowToFileFormat(workflow);
263
265
  setPublishIntentOnInlineAgents(fileFormat);
264
266
  const resolvedFlowJson = JSON.stringify(fileFormat);
265
- const { bpmn } = await convertFlowToBpmn(resolvedFlowJson);
267
+ const { bpmn: rawBpmn } = await convertFlowToBpmn(resolvedFlowJson);
268
+ const bpmn = replaceExporterVersion(rawBpmn, pkg.version);
266
269
  await this.fileSystem.writeFile(bpmnPath, bpmn);
267
270
 
268
271
  // Map file-format nodes to flat PackagingNode shape so
package/src/index.ts CHANGED
@@ -2,7 +2,12 @@
2
2
  import { toolsFactoryRepository } from "@uipath/solutionpackager-tool-core";
3
3
  import { FlowToolFactory } from "./flow-tool-factory.js";
4
4
 
5
- export { type FlowIoLogger, readFlowWorkflow } from "./flow-io.js";
5
+ export { replaceExporterVersion } from "./exporter-version.js";
6
+ export {
7
+ type FlowIoLogger,
8
+ migrateRawWorkflow,
9
+ readFlowWorkflow,
10
+ } from "./flow-io.js";
6
11
  export { FlowTool } from "./flow-tool.js";
7
12
  export { FlowToolFactory } from "./flow-tool-factory.js";
8
13
  export { setPublishIntentOnInlineAgents } from "./inline-agent-utils.js";