@uipath/maestro-builder-sdk 6.21.1 → 6.21.2

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.
@@ -7,11 +7,14 @@
7
7
  *
8
8
  * Runs the fast static check first; if it passes, serializes to a V30
9
9
  * caseplan.json. The authoritative deploy gate is `uip maestro case validate`.
10
- * Output defaults to `caseplan.json` (the platform's canonical file name).
10
+ * Output defaults to the plan file the project in the working directory ships
11
+ * (`caseplan.case` for a project `uip maestro case init` scaffolded), else
12
+ * `caseplan.json`. An `-o` that names a different plan file than the project
13
+ * ships is refused (CASE_OUTPUT_NOT_SHIPPED).
11
14
  */
12
15
  import { reportDiagnostics, reportResult, thrownDiagnostic } from '../cli-result.js';
13
16
  import { writeJsonFile } from '../core/json-file.js';
14
- import { readFileSync, existsSync } from 'node:fs';
17
+ import { readFileSync, existsSync, readdirSync } from 'node:fs';
15
18
  import { join, dirname, basename, resolve } from 'node:path';
16
19
  import { resolveCaseFile, loadBuiltCase } from './load.js';
17
20
  import { serialize } from './serialize.js';
@@ -28,7 +31,7 @@ import { sha256Uuid } from '../core/stable-id.js';
28
31
  import { isRecord } from '../core/node-envelope.js';
29
32
  export async function run(argv) {
30
33
  if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
31
- console.error('usage: compile <case.ts | BaseName> [-o caseplan.json]');
34
+ console.error('usage: compile <case.ts | BaseName> [-o <project>/caseplan.case]');
32
35
  return 2;
33
36
  }
34
37
  const flags = new Set(['-o', '--library', '--bindings', '--connectors-local']);
@@ -61,6 +64,14 @@ export async function run(argv) {
61
64
  console.error(`compile: ${errors.length} error(s); not emitting.`);
62
65
  return 1;
63
66
  }
67
+ const out = flagValue(argv, '-o') ?? shippedCasePlanName('.') ?? 'caseplan.json';
68
+ const shadow = shadowedOutputDiagnostic(out);
69
+ if (shadow) {
70
+ console.error(` ✗ [${shadow.code}] ${shadow.message}`);
71
+ reportDiagnostics([...diags, shadow]);
72
+ console.error('compile: 1 error(s); not emitting.');
73
+ return 1;
74
+ }
64
75
  let caseplan;
65
76
  try {
66
77
  caseplan = serialize(built, { library, bindings });
@@ -69,7 +80,6 @@ export async function run(argv) {
69
80
  reportDiagnostics([...diags, thrownDiagnostic(error)]);
70
81
  throw error;
71
82
  }
72
- const out = flagValue(argv, '-o') ?? 'caseplan.json';
73
83
  writeJsonFile(out, caseplan);
74
84
  const stages = caseplan.nodes.filter((n) => String(n.type).endsWith('Stage')).length;
75
85
  const triggers = syncEntryPoints(caseplan, out);
@@ -80,6 +90,70 @@ export async function run(argv) {
80
90
  reportResult({ path: resolve(out), stages, ...(triggers >= 0 ? { triggers } : {}), ...(resources >= 0 ? { resources } : {}) });
81
91
  return 0;
82
92
  }
93
+ /**
94
+ * The file names a Case project's plan can have, in the order the packager
95
+ * (`@uipath/packager-tool-case` `CasePlanFileNames`) picks the first one present.
96
+ * `uip maestro case init` scaffolds `caseplan.case` since uipath-cli#5004.
97
+ */
98
+ const CASE_PLAN_FILE_NAMES = ['caseplan.case', 'caseplan.json', 'case.stage.json', 'default.stage.json'];
99
+ /**
100
+ * The plan file the project in `dir` ships, or undefined when `dir` is not a
101
+ * Case project. Decided as the packager decides: the first plan file present in
102
+ * packager order. The packager regenerates `package-descriptor.json` from that
103
+ * file (Studio Web renames the plan without updating the descriptor), so the
104
+ * descriptor is only a fallback when no plan file exists yet.
105
+ */
106
+ function shippedCasePlanName(dir) {
107
+ // Exact directory entries, as the packager matches them: `existsSync` ignores
108
+ // case on macOS and Windows, so `CasePlan.case` would pass for `caseplan.case`.
109
+ let entries;
110
+ try {
111
+ entries = new Set(readdirSync(dir));
112
+ }
113
+ catch {
114
+ entries = new Set();
115
+ }
116
+ return CASE_PLAN_FILE_NAMES.find((name) => entries.has(name)) ?? describedCaseFileName(dir);
117
+ }
118
+ /**
119
+ * Refuse to write a plan file the package will not ship: pack, debug and deploy
120
+ * would read the other plan. Non-plan names (`<Name>.caseplan.json`) are not
121
+ * checked.
122
+ */
123
+ function shadowedOutputDiagnostic(outPath) {
124
+ const name = basename(outPath);
125
+ // Case-insensitive: on macOS and Windows `-o CasePlan.json` writes over caseplan.json.
126
+ if (!CASE_PLAN_FILE_NAMES.includes(name.toLowerCase()))
127
+ return undefined;
128
+ const dir = dirname(outPath);
129
+ const shipped = shippedCasePlanName(dir);
130
+ if (!shipped || shipped === name)
131
+ return undefined;
132
+ const target = join(dir, shipped);
133
+ return {
134
+ level: 'error',
135
+ code: 'CASE_OUTPUT_NOT_SHIPPED',
136
+ message: `the project ships ${target}, not ${outPath}; writing ${name} beside it leaves the shipped plan unchanged, ` +
137
+ `so pack, debug and deploy would use the old ${shipped}.`,
138
+ suggestion: `compile with -o ${target}`,
139
+ };
140
+ }
141
+ /** The case file `package-descriptor.json` in `dir` ships, if it names one. */
142
+ function describedCaseFileName(dir) {
143
+ const descriptorPath = join(dir, 'package-descriptor.json');
144
+ if (!existsSync(descriptorPath))
145
+ return undefined;
146
+ try {
147
+ const files = JSON.parse(readFileSync(descriptorPath, 'utf8'))?.files;
148
+ if (files && typeof files === 'object') {
149
+ // The descriptor keys the pair by logical name; the case file is the one
150
+ // whose BPMN sibling it also ships.
151
+ return Object.keys(files).find((k) => `${k}.bpmn` in files);
152
+ }
153
+ }
154
+ catch { /* a malformed descriptor is not worth failing a compile over */ }
155
+ return undefined;
156
+ }
83
157
  /**
84
158
  * The name of the case file THE PACKAGE SHIPS, which is what an entry point's
85
159
  * `filePath` has to name — not the name this compile happened to write.
@@ -92,30 +166,12 @@ export async function run(argv) {
92
166
  * task that took that path never left `Pending (0/0 elements completed)`: the
93
167
  * debug instance was created and no element ever started.
94
168
  *
95
- * `package-descriptor.json` is the project's own declaration of what it ships
96
- * and `uip maestro case init` writes it beside `entry-points.json`, so it is the
97
- * authority whenever it is there.
169
+ * The packaged pair is decided by `shippedCasePlanName` (the plan file on disk,
170
+ * in packager order, else the descriptor); only when neither exists does the
171
+ * output's own name stand.
98
172
  */
99
173
  function packagedCaseFileName(dir, outPath) {
100
- const descriptorPath = join(dir, 'package-descriptor.json');
101
- if (existsSync(descriptorPath)) {
102
- try {
103
- const files = JSON.parse(readFileSync(descriptorPath, 'utf8'))?.files;
104
- if (files && typeof files === 'object') {
105
- // The descriptor keys the pair by logical name; the case file is the one
106
- // whose BPMN sibling it also ships.
107
- const named = Object.keys(files).find((k) => `${k}.bpmn` in files);
108
- if (named)
109
- return named;
110
- }
111
- }
112
- catch { /* a malformed descriptor is not worth failing a compile over */ }
113
- }
114
- // No descriptor (a project scaffolded some other way): a sibling `caseplan.json`
115
- // still says what the project ships, and only the output name is in doubt.
116
- if (existsSync(join(dir, 'caseplan.json')))
117
- return 'caseplan.json';
118
- return basename(outPath);
174
+ return shippedCasePlanName(dir) ?? basename(outPath);
119
175
  }
120
176
  /**
121
177
  * Keep the sibling `entry-points.json` in step with the caseplan's trigger nodes:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.21.1",
3
+ "version": "6.21.2",
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",
@@ -92,5 +92,5 @@
92
92
  "@types/node": "^22.7.0",
93
93
  "esbuild": "^0.28.1"
94
94
  },
95
- "gitref": "fb7b702cde7f69674dfc8ed9e4eb171472e8d8e7"
95
+ "gitref": "1e310a7eebe0932dacee8f36729f54ce6ccc73f4"
96
96
  }