@uipath/solution-packager 0.0.30 → 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.
Files changed (28) hide show
  1. package/dist/index.js +231 -112
  2. package/dist/node.js +227 -54
  3. package/dist/src/browser-solution-packager-factory.d.ts +0 -1
  4. package/dist/src/i18n/locales/en.d.ts +3 -0
  5. package/dist/src/models/solution-pack-options.d.ts +4 -6
  6. package/dist/src/node-solution-packager-factory.d.ts +0 -1
  7. package/dist/src/services/options-builder.d.ts +7 -5
  8. package/dist/src/services/solution-loader.d.ts +1 -1
  9. package/dist/src/services/solution-pack-service.d.ts +7 -0
  10. package/dist/src/services/solution-packager.d.ts +25 -13
  11. package/dist/src/services/solution-restore-service.d.ts +23 -0
  12. package/dist/src/services/solution-validate-options-validator.d.ts +7 -0
  13. package/dist/src/services/solution-validate-service.d.ts +15 -0
  14. package/dist/src/services/tool-result-helpers.d.ts +10 -0
  15. package/dist/src/telemetry-names.d.ts +2 -0
  16. package/dist/tests/{solution-packager-e2e.test.d.ts → solution-packager.e2e.test.d.ts} +1 -0
  17. package/dist/tests/solution-packager.spec.d.ts +1 -0
  18. package/dist/tests/solution-validate-options-validator.spec.d.ts +1 -0
  19. package/dist/tests/solution-validate-service.spec.d.ts +1 -0
  20. package/dist/tests/zip-temp-storage.integration.test.d.ts +1 -0
  21. package/package.json +24 -39
  22. /package/dist/tests/{browser.test.d.ts → browser.spec.d.ts} +0 -0
  23. /package/dist/tests/{common.test.d.ts → common.spec.d.ts} +0 -0
  24. /package/dist/tests/{node.test.d.ts → node.spec.d.ts} +0 -0
  25. /package/dist/tests/{solution-pack-service.test.d.ts → options-builder.spec.d.ts} +0 -0
  26. /package/dist/tests/{solution-loader.test.d.ts → solution-loader.spec.d.ts} +0 -0
  27. /package/dist/tests/{solution-packager.test.d.ts → solution-pack-service.spec.d.ts} +0 -0
  28. /package/dist/tests/{zip-temp-storage-integration.test.d.ts → solution-restore-service.spec.d.ts} +0 -0
package/dist/node.js CHANGED
@@ -8,6 +8,9 @@ var de_default = {
8
8
  pathRequired: "Solution directory path is required",
9
9
  fileNotFound: "Solution file not found: {path}",
10
10
  invalidSolution: "Invalid solution file: {path}",
11
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
12
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
13
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
11
14
  noSolutionFile: "No .uipx solution file found in directory: {path}",
12
15
  invalidStorageFile: "Invalid {fileName} file"
13
16
  }
@@ -30,6 +33,9 @@ var en = {
30
33
  pathRequired: "Solution directory path is required",
31
34
  fileNotFound: "Solution file not found: {path}",
32
35
  invalidSolution: "Invalid solution file: {path}",
36
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
37
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
38
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
33
39
  noSolutionFile: "No .uipx solution file found in directory: {path}",
34
40
  invalidStorageFile: "Invalid {fileName} file"
35
41
  }
@@ -51,6 +57,9 @@ var es_default = {
51
57
  pathRequired: "Solution directory path is required",
52
58
  fileNotFound: "Solution file not found: {path}",
53
59
  invalidSolution: "Invalid solution file: {path}",
60
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
61
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
62
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
54
63
  noSolutionFile: "No .uipx solution file found in directory: {path}",
55
64
  invalidStorageFile: "Invalid {fileName} file"
56
65
  }
@@ -72,6 +81,9 @@ var es_MX_default = {
72
81
  pathRequired: "Solution directory path is required",
73
82
  fileNotFound: "Solution file not found: {path}",
74
83
  invalidSolution: "Invalid solution file: {path}",
84
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
85
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
86
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
75
87
  noSolutionFile: "No .uipx solution file found in directory: {path}",
76
88
  invalidStorageFile: "Invalid {fileName} file"
77
89
  }
@@ -93,6 +105,9 @@ var fr_default = {
93
105
  pathRequired: "Solution directory path is required",
94
106
  fileNotFound: "Solution file not found: {path}",
95
107
  invalidSolution: "Invalid solution file: {path}",
108
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
109
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
110
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
96
111
  noSolutionFile: "No .uipx solution file found in directory: {path}",
97
112
  invalidStorageFile: "Invalid {fileName} file"
98
113
  }
@@ -114,6 +129,9 @@ var ja_default = {
114
129
  pathRequired: "Solution directory path is required",
115
130
  fileNotFound: "Solution file not found: {path}",
116
131
  invalidSolution: "Invalid solution file: {path}",
132
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
133
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
134
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
117
135
  noSolutionFile: "No .uipx solution file found in directory: {path}",
118
136
  invalidStorageFile: "Invalid {fileName} file"
119
137
  }
@@ -135,6 +153,9 @@ var ko_default = {
135
153
  pathRequired: "Solution directory path is required",
136
154
  fileNotFound: "Solution file not found: {path}",
137
155
  invalidSolution: "Invalid solution file: {path}",
156
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
157
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
158
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
138
159
  noSolutionFile: "No .uipx solution file found in directory: {path}",
139
160
  invalidStorageFile: "Invalid {fileName} file"
140
161
  }
@@ -156,6 +177,9 @@ var pt_default = {
156
177
  pathRequired: "Solution directory path is required",
157
178
  fileNotFound: "Solution file not found: {path}",
158
179
  invalidSolution: "Invalid solution file: {path}",
180
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
181
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
182
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
159
183
  noSolutionFile: "No .uipx solution file found in directory: {path}",
160
184
  invalidStorageFile: "Invalid {fileName} file"
161
185
  }
@@ -177,6 +201,9 @@ var pt_BR_default = {
177
201
  pathRequired: "Solution directory path is required",
178
202
  fileNotFound: "Solution file not found: {path}",
179
203
  invalidSolution: "Invalid solution file: {path}",
204
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
205
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
206
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
180
207
  noSolutionFile: "No .uipx solution file found in directory: {path}",
181
208
  invalidStorageFile: "Invalid {fileName} file"
182
209
  }
@@ -198,6 +225,9 @@ var ro_default = {
198
225
  pathRequired: "Solution directory path is required",
199
226
  fileNotFound: "Solution file not found: {path}",
200
227
  invalidSolution: "Invalid solution file: {path}",
228
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
229
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
230
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
201
231
  noSolutionFile: "No .uipx solution file found in directory: {path}",
202
232
  invalidStorageFile: "Invalid {fileName} file"
203
233
  }
@@ -219,6 +249,9 @@ var ru_default = {
219
249
  pathRequired: "Solution directory path is required",
220
250
  fileNotFound: "Solution file not found: {path}",
221
251
  invalidSolution: "Invalid solution file: {path}",
252
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
253
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
254
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
222
255
  noSolutionFile: "No .uipx solution file found in directory: {path}",
223
256
  invalidStorageFile: "Invalid {fileName} file"
224
257
  }
@@ -240,6 +273,9 @@ var tr_default = {
240
273
  pathRequired: "Solution directory path is required",
241
274
  fileNotFound: "Solution file not found: {path}",
242
275
  invalidSolution: "Invalid solution file: {path}",
276
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
277
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
278
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
243
279
  noSolutionFile: "No .uipx solution file found in directory: {path}",
244
280
  invalidStorageFile: "Invalid {fileName} file"
245
281
  }
@@ -261,6 +297,9 @@ var zh_CN_default = {
261
297
  pathRequired: "Solution directory path is required",
262
298
  fileNotFound: "Solution file not found: {path}",
263
299
  invalidSolution: "Invalid solution file: {path}",
300
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
301
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
302
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
264
303
  noSolutionFile: "No .uipx solution file found in directory: {path}",
265
304
  invalidStorageFile: "Invalid {fileName} file"
266
305
  }
@@ -282,6 +321,9 @@ var zh_TW_default = {
282
321
  pathRequired: "Solution directory path is required",
283
322
  fileNotFound: "Solution file not found: {path}",
284
323
  invalidSolution: "Invalid solution file: {path}",
324
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
325
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
326
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
285
327
  noSolutionFile: "No .uipx solution file found in directory: {path}",
286
328
  invalidStorageFile: "Invalid {fileName} file"
287
329
  }
@@ -303,6 +345,9 @@ var zu_default = {
303
345
  pathRequired: "Solution directory path is required",
304
346
  fileNotFound: "Solution file not found: {path}",
305
347
  invalidSolution: "Invalid solution file: {path}",
348
+ projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.",
349
+ projectMissingProjectRelativePath: `Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`,
350
+ projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.",
306
351
  noSolutionFile: "No .uipx solution file found in directory: {path}",
307
352
  invalidStorageFile: "Invalid {fileName} file"
308
353
  }
@@ -344,11 +389,11 @@ import {
344
389
  } from "@uipath/solutionpackager-tool-core";
345
390
 
346
391
  class SolutionPackOptions extends PackagerParameters {
347
- downloadUrl;
348
392
  destinationPath;
349
- projectsToBuild;
393
+ projectDesignIds;
350
394
  validateOptions = {
351
395
  skipAnalyze: false,
396
+ skipValidate: false,
352
397
  governanceFileType: RulesConfigFileType.Default
353
398
  };
354
399
  package;
@@ -360,6 +405,7 @@ class SolutionPackOptions extends PackagerParameters {
360
405
  // src/node-solution-packager-factory.ts
361
406
  import {
362
407
  BaseNodePackagerFactory,
408
+ DotnetDiscoveryService,
363
409
  NodePackageSignService,
364
410
  ToolLogger as ToolLogger2
365
411
  } from "@uipath/project-packager/node";
@@ -376,15 +422,15 @@ import {
376
422
  Path as Path4,
377
423
  TargetFramework,
378
424
  TemporaryStorageService,
379
- ToolErrorCodes as ToolErrorCodes2,
380
- ToolResult as ToolResult2,
425
+ ToolErrorCodes as ToolErrorCodes3,
426
+ ToolResult as ToolResult3,
381
427
  toolsFactoryRepository,
428
+ translate as translate3,
382
429
  ZipService
383
430
  } from "@uipath/solutionpackager-tool-core";
384
431
 
385
432
  // src/services/options-builder.ts
386
433
  import {
387
- BuildConfiguration as BuildConfiguration2,
388
434
  Path,
389
435
  translate
390
436
  } from "@uipath/solutionpackager-tool-core";
@@ -404,7 +450,6 @@ class OptionsBuilder {
404
450
  throw new Error(translate.t("solutionpackager.optionsBuilder.errors.outputPathRequired"));
405
451
  }
406
452
  await this.createOutputFilesDirectoryAsync(parameters.outputPath);
407
- const projectsToBuild = this.getProjectIdsToBuild(parameters, solution);
408
453
  if (!parameters.package.id || parameters.package.id.trim() === "") {
409
454
  parameters.package.id = solution.Name;
410
455
  }
@@ -415,7 +460,7 @@ class OptionsBuilder {
415
460
  configuration: parameters.configuration,
416
461
  package: parameters.package,
417
462
  publishId: parameters.publishInfo?.id,
418
- projectsToBuild
463
+ projectsToBuild: solution.Projects.map((p) => p.Id)
419
464
  };
420
465
  }
421
466
  async createOutputFilesDirectoryAsync(outputPath) {
@@ -423,9 +468,7 @@ class OptionsBuilder {
423
468
  await this.fileSystem.mkdir(filesDir);
424
469
  }
425
470
  async buildProjectPackOptions(solutionOptions, project) {
426
- const solutionFolderPath = solutionOptions.inputPath;
427
- const projectRelativePath = Path.dirname(project.ProjectRelativePath);
428
- const projectPath = Path.join(solutionFolderPath, projectRelativePath);
471
+ const projectPath = this.resolveProjectPath(solutionOptions, project);
429
472
  const solutionName = solutionOptions.package.id || undefined;
430
473
  const packageInfo = {
431
474
  ...solutionOptions.package,
@@ -442,7 +485,7 @@ class OptionsBuilder {
442
485
  nuGetSourcesConfigPath: solutionOptions.nuGetSourcesConfigPath,
443
486
  logLevel: solutionOptions.logLevel,
444
487
  skipAnalyze: solutionOptions.validateOptions.skipAnalyze,
445
- skipValidate: false,
488
+ skipValidate: solutionOptions.validateOptions.skipValidate,
446
489
  projectStorageId: project.StorageId,
447
490
  detailedLogPath: solutionOptions.detailedLogPath,
448
491
  policyFilePath: solutionOptions.validateOptions.governanceFilePath,
@@ -456,26 +499,29 @@ class OptionsBuilder {
456
499
  splitPackages: solutionOptions.packOptions?.splitPackages ?? false
457
500
  };
458
501
  }
502
+ buildProjectValidateOptions(solutionOptions, project) {
503
+ return {
504
+ projectPath: this.resolveProjectPath(solutionOptions, project),
505
+ excludeConfiguredSources: solutionOptions.excludeConfiguredSources ?? false,
506
+ nuGetSourcesConfigPath: solutionOptions.nuGetSourcesConfigPath,
507
+ logLevel: solutionOptions.logLevel,
508
+ skipAnalyze: solutionOptions.validateOptions.skipAnalyze,
509
+ skipValidate: solutionOptions.validateOptions.skipValidate,
510
+ defaultSeverity: solutionOptions.validateOptions.defaultSeverity,
511
+ detailedLogPath: solutionOptions.detailedLogPath,
512
+ policyFilePath: solutionOptions.validateOptions.governanceFilePath,
513
+ policyFileType: solutionOptions.validateOptions.governanceFileType
514
+ };
515
+ }
516
+ resolveProjectPath(solutionOptions, project) {
517
+ return Path.join(solutionOptions.inputPath, Path.dirname(project.ProjectRelativePath));
518
+ }
459
519
  async buildProjectOutputPath(solutionOutputPath, project) {
460
520
  const filesDir = Path.join(solutionOutputPath, OptionsBuilder.FILES_DIRECTORY_NAME);
461
521
  const projectOutputPath = Path.join(filesDir, project.Id);
462
522
  await this.fileSystem.mkdir(projectOutputPath);
463
523
  return projectOutputPath;
464
524
  }
465
- getProjectIdsToBuild(parameters, solution) {
466
- const solutionProjectIds = solution.Projects.map((p) => p.Id);
467
- if (parameters.projectsToBuild === null || parameters.projectsToBuild === undefined || parameters.projectsToBuild.length === 0) {
468
- return parameters.configuration === BuildConfiguration2.Release ? solutionProjectIds : [];
469
- }
470
- const invalidProjectIds = parameters.projectsToBuild.filter((id) => !solutionProjectIds.includes(id));
471
- if (invalidProjectIds.length > 0) {
472
- console.warn(translate.t("solutionpackager.optionsBuilder.errors.invalidProjectIds", {
473
- ids: invalidProjectIds.join(",")
474
- }));
475
- return solutionProjectIds.filter((id) => parameters.projectsToBuild?.includes(id));
476
- }
477
- return parameters.projectsToBuild;
478
- }
479
525
  }
480
526
 
481
527
  // src/services/package-id-reader.ts
@@ -491,7 +537,8 @@ class PackageIdReader {
491
537
  agent: "agent",
492
538
  api: "api",
493
539
  webapp: "webApp",
494
- process: "process"
540
+ process: "process",
541
+ flow: "flow"
495
542
  };
496
543
  static projectTypeMap = {
497
544
  process: "Rpa",
@@ -501,7 +548,8 @@ class PackageIdReader {
501
548
  processorchestration: "Agentic",
502
549
  casemanagement: "Case",
503
550
  api: "Api",
504
- agent: "Agent"
551
+ agent: "Agent",
552
+ flow: "Flow"
505
553
  };
506
554
  constructor(fileSystem, packService) {
507
555
  this.fileSystem = fileSystem;
@@ -639,7 +687,7 @@ import { Path as Path3, translate as translate2 } from "@uipath/solutionpackager
639
687
 
640
688
  class SolutionLoader {
641
689
  fileSystem;
642
- static SolutionStorageFileName = ".storage";
690
+ static SolutionStorageFileName = "SolutionStorage.json";
643
691
  constructor(fileSystem) {
644
692
  this.fileSystem = fileSystem;
645
693
  }
@@ -655,12 +703,8 @@ class SolutionLoader {
655
703
  }));
656
704
  }
657
705
  const json = typeof fileContent === "string" ? fileContent : new TextDecoder("utf-8").decode(fileContent);
658
- const solution = JSON.parse(json);
659
- if (!solution?.Projects) {
660
- throw new Error(translate2.t("solutionpackager.solutionLoader.errors.invalidSolution", {
661
- path: solutionFilePath
662
- }));
663
- }
706
+ const parsed = JSON.parse(json);
707
+ const solution = validateSolutionFile(parsed, solutionFilePath);
664
708
  const loadedSolution = {
665
709
  ...solution,
666
710
  Name: GetSolutionName(),
@@ -712,6 +756,38 @@ class SolutionLoader {
712
756
  }
713
757
  }
714
758
  }
759
+ function validateSolutionFile(parsed, solutionFilePath) {
760
+ if (!isRecord(parsed)) {
761
+ throw new Error(translate2.t("solutionpackager.solutionLoader.errors.invalidSolution", {
762
+ path: solutionFilePath
763
+ }));
764
+ }
765
+ if (!Array.isArray(parsed.Projects)) {
766
+ throw new Error(translate2.t("solutionpackager.solutionLoader.errors.invalidSolution", {
767
+ path: solutionFilePath
768
+ }));
769
+ }
770
+ for (const [index, project] of parsed.Projects.entries()) {
771
+ if (!isRecord(project)) {
772
+ throw new Error(translate2.t("solutionpackager.solutionLoader.errors.projectMustBeObject", {
773
+ path: solutionFilePath,
774
+ index
775
+ }));
776
+ }
777
+ if (typeof project.ProjectRelativePath !== "string" || !project.ProjectRelativePath.trim()) {
778
+ const pathHint = typeof project.Path === "string" ? translate2.t("solutionpackager.solutionLoader.errors.projectRelativePathPathHint") : "";
779
+ throw new Error(translate2.t("solutionpackager.solutionLoader.errors.projectMissingProjectRelativePath", {
780
+ path: solutionFilePath,
781
+ index,
782
+ pathHint
783
+ }));
784
+ }
785
+ }
786
+ return parsed;
787
+ }
788
+ function isRecord(value) {
789
+ return typeof value === "object" && value !== null && !Array.isArray(value);
790
+ }
715
791
 
716
792
  // src/services/solution-pack-options-validator.ts
717
793
  import {
@@ -806,6 +882,7 @@ class SolutionPackService {
806
882
  return await this.telemetry.trackDependencyOperation("SolutionPackager.Solution.Compress" /* SolutionCompress */, "compress", async () => {
807
883
  const packageName = parameters.package.id || "solution";
808
884
  const version = parameters.package.version || "1.0.0";
885
+ await this.writePackageMetadataAsync(parameters, outputPath);
809
886
  const archiveFileName = `${packageName}_${version}.zip`;
810
887
  const archivePath = `${parameters.destinationPath}/${archiveFileName}`;
811
888
  const zipData = await this.zipService.compressAsync(outputPath);
@@ -813,6 +890,68 @@ class SolutionPackService {
813
890
  return archivePath;
814
891
  });
815
892
  }
893
+ async writePackageMetadataAsync(parameters, outputPath) {
894
+ const pkg = parameters.package;
895
+ const metadata = {
896
+ name: pkg.id || "solution",
897
+ version: pkg.version || "1.0.0"
898
+ };
899
+ const optional = {
900
+ releaseNotes: pkg.releaseNotes,
901
+ projectUrl: pkg.projectUrl,
902
+ repositoryType: pkg.repositoryType,
903
+ repositoryUrl: pkg.repositoryUrl,
904
+ repositoryBranch: pkg.repositoryBranch,
905
+ repositoryCommit: pkg.repositoryCommit
906
+ };
907
+ for (const [key, value] of Object.entries(optional)) {
908
+ if (value !== undefined && value !== "") {
909
+ metadata[key] = value;
910
+ }
911
+ }
912
+ const metadataPath = `${outputPath}/package.metadata.json`;
913
+ await this.fileSystem.writeFile(metadataPath, `${JSON.stringify(metadata, null, 2)}
914
+ `);
915
+ }
916
+ }
917
+
918
+ // src/services/solution-validate-options-validator.ts
919
+ import {
920
+ PackagerParametersValidator as PackagerParametersValidator2
921
+ } from "@uipath/project-packager";
922
+
923
+ class SolutionValidateOptionsValidator extends PackagerParametersValidator2 {
924
+ async validateAsync(options, _cancellationToken) {
925
+ return await this.validateGovernanceOptions(options.validateOptions);
926
+ }
927
+ }
928
+
929
+ // src/services/solution-validate-service.ts
930
+ import {
931
+ ToolErrorCodes as ToolErrorCodes2,
932
+ ToolResult as ToolResult2
933
+ } from "@uipath/solutionpackager-tool-core";
934
+ class SolutionValidateService {
935
+ optionsBuilder;
936
+ projectExecutor;
937
+ telemetry;
938
+ constructor(optionsBuilder, projectExecutor, telemetry) {
939
+ this.optionsBuilder = optionsBuilder;
940
+ this.projectExecutor = projectExecutor;
941
+ this.telemetry = telemetry;
942
+ }
943
+ async validateAsync(parameters, solution, context, cancellationToken) {
944
+ return await this.telemetry.trackDependencyOperation("SolutionPackager.Solution.Validate" /* SolutionValidate */, "validate", async () => {
945
+ const projectResults = await Promise.all(solution.Projects.map((project) => {
946
+ if (project.ProjectPath == null) {
947
+ return Promise.resolve(ToolResult2.error(ToolErrorCodes2.InternalError, `Project '${project.Id}' has no ProjectPath; the solution loader must populate it before validation.`));
948
+ }
949
+ return this.projectExecutor.validateAsync(this.optionsBuilder.buildProjectValidateOptions(parameters, project), project, context, cancellationToken);
950
+ }));
951
+ const failed = projectResults.find((r) => !r.isSuccess);
952
+ return failed ?? ToolResult2.success();
953
+ }, { solutionId: solution.SolutionId });
954
+ }
816
955
  }
817
956
 
818
957
  // src/services/solution-packager.ts
@@ -829,7 +968,9 @@ class SolutionPackager {
829
968
  projectExecutor;
830
969
  solutionLoader;
831
970
  solutionPackService;
832
- optionsValidator;
971
+ solutionValidateService;
972
+ packOptionsValidator;
973
+ validateOptionsValidator;
833
974
  governancePolicyService;
834
975
  constructor(fileSystem, telemetryService, packageSignService) {
835
976
  this.fileSystem = fileSystem;
@@ -839,7 +980,8 @@ class SolutionPackager {
839
980
  this.temporaryStorage = new TemporaryStorageService(this.fileSystem);
840
981
  this.zipService = new ZipService(this.fileSystem);
841
982
  this.logger = new ToolLogger("SolutionPackager", "PackSolution");
842
- this.optionsValidator = new SolutionPackOptionsValidator(this.logger, this.fileSystem);
983
+ this.packOptionsValidator = new SolutionPackOptionsValidator(this.logger, this.fileSystem);
984
+ this.validateOptionsValidator = new SolutionValidateOptionsValidator(this.logger, this.fileSystem);
843
985
  const packService = new PackService;
844
986
  const packageIdReader = new PackageIdReader(this.fileSystem, packService);
845
987
  this.optionsBuilder = new OptionsBuilder(packageIdReader, packService, this.fileSystem);
@@ -848,19 +990,7 @@ class SolutionPackager {
848
990
  this.solutionLoader = new SolutionLoader(this.fileSystem);
849
991
  this.governancePolicyService = new GovernancePolicyService(this.fileSystem, this.temporaryStorage);
850
992
  this.solutionPackService = new SolutionPackService(this.optionsBuilder, this.toolsFactory, this.projectExecutor, this.zipService, this.fileSystem, this.telemetryService);
851
- }
852
- async canPackSolutionAsync(solutionPath) {
853
- const solution = await this.solutionLoader.loadSolution(solutionPath);
854
- for (const project of solution.Projects) {
855
- if (!project.ProjectPath) {
856
- return false;
857
- }
858
- const canHandle = this.repository.canHandleProject(project.Type);
859
- if (!canHandle) {
860
- return false;
861
- }
862
- }
863
- return true;
993
+ this.solutionValidateService = new SolutionValidateService(this.optionsBuilder, this.projectExecutor, this.telemetryService);
864
994
  }
865
995
  async setupAsync(input, operationId) {
866
996
  this.telemetryService.setOperationId(operationId);
@@ -897,14 +1027,15 @@ class SolutionPackager {
897
1027
  return await this.telemetryService.trackRequest("SolutionPackager.PackSolution" /* SolutionPackagerPackSolution */, async () => {
898
1028
  try {
899
1029
  await this.governancePolicyService.resolveGovernancePolicyAsync(options.validateOptions, options.connection, cancellationToken);
900
- let result = await this.optionsValidator.validateAsync(options, cancellationToken);
1030
+ let result = await this.packOptionsValidator.validateAsync(options, cancellationToken);
901
1031
  if (!result.isSuccess) {
902
1032
  return result;
903
1033
  }
904
1034
  if (!options.outputPath) {
905
1035
  options.outputPath = await this.temporaryStorage.getTempSubfolderPathAsync("output");
906
1036
  }
907
- const solution = await this.solutionLoader.loadSolution(options.inputPath);
1037
+ const loadedSolution = await this.solutionLoader.loadSolution(options.inputPath);
1038
+ const solution = this.filterSolutionProjects(loadedSolution, options.projectDesignIds);
908
1039
  const context = this.createOperationContext(options, solution);
909
1040
  result = await this.solutionPackService.packAsync(options, solution, context, cancellationToken);
910
1041
  if (result.isSuccess) {
@@ -916,16 +1047,57 @@ class SolutionPackager {
916
1047
  } catch (error) {
917
1048
  const errorMessage = error instanceof Error ? error.message : String(error);
918
1049
  this.logger.error(`Processing error: ${errorMessage}`);
919
- return ToolResult2.error(ToolErrorCodes2.InternalError, `Solution pack failed: ${errorMessage}`);
1050
+ return ToolResult3.error(ToolErrorCodes3.InternalError, `Solution pack failed: ${errorMessage}`);
1051
+ } finally {
1052
+ await this.temporaryStorage.cleanup();
1053
+ }
1054
+ });
1055
+ }
1056
+ async validateSolutionAsync(options, cancellationToken) {
1057
+ return await this.telemetryService.trackRequest("SolutionPackager.ValidateSolution" /* SolutionPackagerValidateSolution */, async () => {
1058
+ try {
1059
+ await this.governancePolicyService.resolveGovernancePolicyAsync(options.validateOptions, options.connection, cancellationToken);
1060
+ const validationResult = await this.validateOptionsValidator.validateAsync(options, cancellationToken);
1061
+ if (!validationResult.isSuccess) {
1062
+ return validationResult;
1063
+ }
1064
+ const loadedSolution = await this.solutionLoader.loadSolution(options.inputPath);
1065
+ const solution = this.filterSolutionProjects(loadedSolution, options.projectDesignIds);
1066
+ const context = this.createOperationContext(options, solution);
1067
+ const result = await this.solutionValidateService.validateAsync(options, solution, context, cancellationToken);
1068
+ if (result.isSuccess) {
1069
+ this.logger.info("Solution validate completed successfully.");
1070
+ } else {
1071
+ this.logger.error(`Solution validate failed with error code ${result.errorCode}: ${result.message}`);
1072
+ }
1073
+ return result;
1074
+ } catch (error) {
1075
+ const errorMessage = error instanceof Error ? error.message : String(error);
1076
+ this.logger.error(`Processing error: ${errorMessage}`);
1077
+ return ToolResult3.error(ToolErrorCodes3.InternalError, `Solution validate failed: ${errorMessage}`);
920
1078
  } finally {
921
1079
  await this.temporaryStorage.cleanup();
922
1080
  }
923
1081
  });
924
1082
  }
1083
+ filterSolutionProjects(solution, projectDesignIds) {
1084
+ if (!projectDesignIds?.length)
1085
+ return solution;
1086
+ const solutionProjectIds = new Set(solution.Projects.map((p) => p.Id));
1087
+ const unknownIds = projectDesignIds.filter((id) => !solutionProjectIds.has(id));
1088
+ if (unknownIds.length > 0) {
1089
+ this.logger.warn(translate3.t("solutionpackager.optionsBuilder.errors.invalidProjectIds", { ids: unknownIds.join(",") }));
1090
+ }
1091
+ const requested = new Set(projectDesignIds);
1092
+ return {
1093
+ ...solution,
1094
+ Projects: solution.Projects.filter((p) => requested.has(p.Id))
1095
+ };
1096
+ }
925
1097
  createOperationContext(options, solution) {
926
1098
  return {
927
1099
  id: crypto.randomUUID(),
928
- solution,
1100
+ projects: solution.Projects,
929
1101
  downloadUrl: options.downloadUrl,
930
1102
  configuration: options.configuration,
931
1103
  targetFramework: options.targetFramework ?? TargetFramework.Portable,
@@ -963,7 +1135,8 @@ class NodeSolutionPackagerFactory extends BaseNodePackagerFactory {
963
1135
  logger.info("Creating SolutionPackager instance...");
964
1136
  const fileSystem = this.getOrCreateFileSystem(config);
965
1137
  const telemetryService = this.getOrCreateTelemetryService(config);
966
- const packageSignService = new NodePackageSignService(logger);
1138
+ this.dotnetDiscovery = new DotnetDiscoveryService;
1139
+ const packageSignService = new NodePackageSignService(this.dotnetDiscovery, logger);
967
1140
  const solutionPackager = new SolutionPackager(fileSystem, telemetryService, packageSignService);
968
1141
  this.checkDotnetAvailability(logger);
969
1142
  logger.info("SolutionPackager created successfully.");
@@ -4,7 +4,6 @@ import { type ISolutionPackager } from "./services/solution-packager.js";
4
4
  * Creates a SolutionPackager instance configured for browser usage.
5
5
  *
6
6
  * This is a convenience function that creates a BrowserSolutionPackagerFactory and calls createAsync.
7
- * For more control, use the BrowserSolutionPackagerFactory class directly.
8
7
  *
9
8
  * @param options - Configuration options for the SolutionPackager
10
9
  * @returns Promise<ISolutionPackager> - A fully configured SolutionPackager instance ready for use in the browser.
@@ -9,6 +9,9 @@ export declare const en: {
9
9
  readonly pathRequired: "Solution directory path is required";
10
10
  readonly fileNotFound: "Solution file not found: {path}";
11
11
  readonly invalidSolution: "Invalid solution file: {path}";
12
+ readonly projectMustBeObject: "Invalid solution file: {path}. Projects[{index}] must be an object.";
13
+ readonly projectMissingProjectRelativePath: "Invalid solution file: {path}. Projects[{index}] is missing ProjectRelativePath.{pathHint} Use 'uip solution project add' to add projects, or set ProjectRelativePath to the project file path, for example \"Foo/project.uiproj\".";
14
+ readonly projectRelativePathPathHint: " Found Path, but .uipx uses ProjectRelativePath.";
12
15
  readonly noSolutionFile: "No .uipx solution file found in directory: {path}";
13
16
  readonly invalidStorageFile: "Invalid {fileName} file";
14
17
  };
@@ -5,18 +5,16 @@ import { BuildConfiguration, type NugetPackageInfo } from "@uipath/solutionpacka
5
5
  * Solution-specific parameters extending base packager parameters
6
6
  */
7
7
  export declare class SolutionPackOptions extends PackagerParameters {
8
- /**
9
- * URL to download the solution snapshot for remote packing
10
- */
11
- downloadUrl?: string;
12
8
  /**
13
9
  * Path to the folder where the packed output will be stored.
14
10
  */
15
11
  destinationPath: string;
16
12
  /**
17
- * Array of project names/paths to build
13
+ * Subset of solution project design IDs (the `Id` field of each
14
+ * `UiPathProject` in the solution model) to process. Empty or undefined
15
+ * means "all projects". Unknown IDs are logged and silently dropped.
18
16
  */
19
- projectsToBuild?: string[];
17
+ projectDesignIds?: string[];
20
18
  /**
21
19
  * Validate options
22
20
  */
@@ -4,7 +4,6 @@ import { type ISolutionPackager } from "./services/solution-packager.js";
4
4
  * Creates a SolutionPackager instance configured for Node.js usage.
5
5
  *
6
6
  * This is a convenience function that creates a NodeSolutionPackagerFactory and calls createAsync.
7
- * For more control, use the NodeSolutionPackagerFactory class directly.
8
7
  *
9
8
  * @param options - Configuration options for the SolutionPackager
10
9
  * @returns Promise<ISolutionPackager> - A fully configured SolutionPackager instance ready for use in Node.js.
@@ -1,5 +1,5 @@
1
1
  import type { IPackService, UiPathProject } from "@uipath/project-packager";
2
- import { type IFileSystem, type IProjectPackOptions, type ISolutionPackOptions } from "@uipath/solutionpackager-tool-core";
2
+ import { type IFileSystem, type IProjectPackOptions, type IProjectValidateOptions, type ISolutionPackOptions } from "@uipath/solutionpackager-tool-core";
3
3
  import type { LoadedUiPathSolution } from "../models/loaded-uipath-solution.js";
4
4
  import type { SolutionPackOptions } from "../models/solution-pack-options.js";
5
5
  import type { IPackageIdReader } from "./package-id-reader.js";
@@ -15,6 +15,10 @@ export interface IOptionsBuilder {
15
15
  * Build project pack options from solution parameters, for a specific project
16
16
  */
17
17
  buildProjectPackOptions(options: SolutionPackOptions, project: UiPathProject): Promise<IProjectPackOptions>;
18
+ /**
19
+ * Build project validate options from solution parameters, for a specific project
20
+ */
21
+ buildProjectValidateOptions(options: SolutionPackOptions, project: UiPathProject): IProjectValidateOptions;
18
22
  }
19
23
  export declare class OptionsBuilder implements IOptionsBuilder {
20
24
  private readonly packageIdReader;
@@ -28,6 +32,8 @@ export declare class OptionsBuilder implements IOptionsBuilder {
28
32
  * Build project pack options from solution parameters for a specific project
29
33
  */
30
34
  buildProjectPackOptions(solutionOptions: SolutionPackOptions, project: UiPathProject): Promise<IProjectPackOptions>;
35
+ buildProjectValidateOptions(solutionOptions: SolutionPackOptions, project: UiPathProject): IProjectValidateOptions;
36
+ private resolveProjectPath;
31
37
  /**
32
38
  * Build the output path for a project
33
39
  * Path structure: {solutionOutputFolder}/files/{projectId}
@@ -35,8 +41,4 @@ export declare class OptionsBuilder implements IOptionsBuilder {
35
41
  * @returns The output path for the project
36
42
  */
37
43
  private buildProjectOutputPath;
38
- /**
39
- * Get the list of project IDs to build based on parameters and solution
40
- */
41
- private getProjectIdsToBuild;
42
44
  }
@@ -11,7 +11,7 @@ export interface ISolutionLoader {
11
11
  }
12
12
  export declare class SolutionLoader implements ISolutionLoader {
13
13
  private readonly fileSystem;
14
- static readonly SolutionStorageFileName = ".storage";
14
+ static readonly SolutionStorageFileName = "SolutionStorage.json";
15
15
  constructor(fileSystem: IFileSystem);
16
16
  loadSolution(solutionPath: string): Promise<LoadedUiPathSolution>;
17
17
  private getSolutionFilePathAsync;
@@ -57,4 +57,11 @@ export declare class SolutionPackService implements ISolutionPackService {
57
57
  * @returns Path to the created archive file
58
58
  */
59
59
  private compressSolutionAsync;
60
+ /**
61
+ * Write a `package.metadata.json` file into the solution output folder
62
+ * (it lands at the root of the produced .zip). Only fields the caller
63
+ * actually supplied are emitted, so a metadata-free pack still gets a
64
+ * minimal file carrying the package name and version.
65
+ */
66
+ private writePackageMetadataAsync;
60
67
  }