@uipath/maestro-builder-sdk 6.25.0 → 6.25.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.
@@ -10,7 +10,8 @@
10
10
  * Output defaults to the plan file the project in the working directory ships
11
11
  * (`caseplan.case` for a project `uip maestro case init` scaffolded), else
12
12
  * `caseplan.json`. An `-o` that names a different plan file than the project
13
- * ships is refused (CASE_OUTPUT_NOT_SHIPPED).
13
+ * ships is refused (CASE_OUTPUT_NOT_SHIPPED), and so is a plan file written into
14
+ * a solution directory above its Case project (CASE_OUTPUT_OUTSIDE_PROJECT).
14
15
  */
15
16
  import { reportDiagnostics, reportResult, thrownDiagnostic } from '../cli-result.js';
16
17
  import { writeJsonFile } from '../core/json-file.js';
@@ -67,7 +68,7 @@ export async function run(argv) {
67
68
  const out = flagValue(argv, '-o') ?? shippedCasePlanName('.') ?? 'caseplan.json';
68
69
  const shadow = shadowedOutputDiagnostic(out);
69
70
  if (shadow) {
70
- console.error(` ✗ [${shadow.code}] ${shadow.message}`);
71
+ console.error(` ✗ [${shadow.code}] ${shadow.message} Fix: ${shadow.suggestion}.`);
71
72
  reportDiagnostics([...diags, shadow]);
72
73
  console.error('compile: 1 error(s); not emitting.');
73
74
  return 1;
@@ -96,6 +97,9 @@ export async function run(argv) {
96
97
  * `uip maestro case init` scaffolds `caseplan.case` since uipath-cli#5004.
97
98
  */
98
99
  const CASE_PLAN_FILE_NAMES = ['caseplan.case', 'caseplan.json', 'case.stage.json', 'default.stage.json'];
100
+ /** The file that makes a directory a project, and the `ProjectType` a Case project declares in it. */
101
+ const PROJECT_FILE = 'project.uiproj';
102
+ const CASE_PROJECT_TYPE = 'CaseManagement';
99
103
  /**
100
104
  * The plan file the project in `dir` ships, or undefined when `dir` is not a
101
105
  * Case project. Decided as the packager decides: the first plan file present in
@@ -126,6 +130,11 @@ function shadowedOutputDiagnostic(outPath) {
126
130
  if (!CASE_PLAN_FILE_NAMES.includes(name.toLowerCase()))
127
131
  return undefined;
128
132
  const dir = dirname(outPath);
133
+ // First: a plan file already in a solution directory would otherwise make it
134
+ // look like a project that ships that file.
135
+ const outside = outsideProjectDiagnostic(outPath);
136
+ if (outside)
137
+ return outside;
129
138
  const shipped = shippedCasePlanName(dir);
130
139
  if (!shipped || shipped === name)
131
140
  return undefined;
@@ -138,6 +147,53 @@ function shadowedOutputDiagnostic(outPath) {
138
147
  suggestion: `compile with -o ${target}`,
139
148
  };
140
149
  }
150
+ /**
151
+ * A plan file in a non-project dir that holds Case projects (a solution dir) is
152
+ * packed by none. A directory that is itself a project, or holds no Case
153
+ * project, is not checked.
154
+ */
155
+ function outsideProjectDiagnostic(outPath) {
156
+ const dir = dirname(outPath);
157
+ if (existsSync(join(dir, PROJECT_FILE)))
158
+ return undefined;
159
+ const projects = childCaseProjects(dir);
160
+ if (projects.length === 0)
161
+ return undefined;
162
+ const targets = projects.map((p) => join(dir, p, shippedCasePlanName(join(dir, p)) ?? CASE_PLAN_FILE_NAMES[0]));
163
+ return {
164
+ level: 'error',
165
+ code: 'CASE_OUTPUT_OUTSIDE_PROJECT',
166
+ message: `${outPath} is in a solution directory, not a Case project; no project packs it. ` +
167
+ `The Case project${projects.length > 1 ? 's here are' : ' here is'} ${projects.map((p) => join(dir, p)).join(', ')}.`,
168
+ suggestion: projects.length === 1 ? `compile with -o ${targets[0]}` : `compile with -o one of: ${targets.join(', ')}`,
169
+ };
170
+ }
171
+ /**
172
+ * Subdirectories of `dir` (or links to one) whose `project.uiproj` declares a
173
+ * CaseManagement project.
174
+ */
175
+ function childCaseProjects(dir) {
176
+ let entries;
177
+ try {
178
+ entries = readdirSync(dir, { withFileTypes: true });
179
+ }
180
+ catch {
181
+ return [];
182
+ }
183
+ return entries
184
+ // A link counts: the read below fails for a link to a file.
185
+ .filter((e) => e.isDirectory() || e.isSymbolicLink())
186
+ .map((e) => e.name)
187
+ .filter((name) => {
188
+ try {
189
+ return JSON.parse(readFileSync(join(dir, name, PROJECT_FILE), 'utf8'))?.ProjectType === CASE_PROJECT_TYPE;
190
+ }
191
+ catch {
192
+ return false;
193
+ }
194
+ })
195
+ .sort();
196
+ }
141
197
  /** The case file `package-descriptor.json` in `dir` ships, if it names one. */
142
198
  function describedCaseFileName(dir) {
143
199
  const descriptorPath = join(dir, 'package-descriptor.json');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.25.0",
3
+ "version": "6.25.1",
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": "119258f247ce3ff7e3b3b3faf21ab2e2b13eca5a"
95
+ "gitref": "384f76113bc43067b5ec5ea700534e9611e664ff"
96
96
  }