@uipath/solution-tool 1.204.0-preview.255 → 1.205.0-preview.256
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.
- package/README.md +3 -3
- package/dist/THIRD-PARTY-NOTICES.md +2 -2
- package/dist/archive-extract-x35t9ktj.js +120 -0
- package/dist/cleanup-command-service-n4e7vxnw.js +149 -0
- package/dist/deploy-delete-service-cag0q8yx.js +25 -0
- package/dist/deploy-run-service-f0h8wb9w.js +25 -0
- package/dist/{deploy-status-service-6svq7c6w.js → deploy-status-service-yh6xn6e0.js} +41 -33
- package/dist/deploy.js +23 -17
- package/dist/{deployment-search-v2qtz23x.js → deployment-search-mnywd9nc.js} +16 -10
- package/dist/{embedded-file-reader-rf2g1kfj.js → embedded-file-reader-z4becc02.js} +2 -2
- package/dist/{feed-resolver-xz3akamf.js → feed-resolver-fve33dxq.js} +10 -9
- package/dist/feed-scope-failure-jmg4t1r1.js +19 -0
- package/dist/{feed-session-sxga31vn.js → feed-session-7xqphdrg.js} +3 -3
- package/dist/governance-options-4vxz7ekn.js +32 -0
- package/dist/index-g8c8nf1c.js +667 -0
- package/dist/index-prm27bvm.js +138 -0
- package/dist/index.js +27 -29
- package/dist/init.js +11 -10
- package/dist/{list-tjetkspc.js → list-50mepbed.js} +10 -8
- package/dist/models/pack-command-types.d.ts +15 -0
- package/dist/node-7jm7ksqa.js +86 -0
- package/dist/pack-command-service-dewf5vsq.js +35 -0
- package/dist/pack-project-xwd1rbaa.js +97 -0
- package/dist/pack.js +24 -14
- package/dist/package-id-1wr3cy9c.js +13 -0
- package/dist/packager-tool-09swr9cp.js +171 -0
- package/dist/{packager-tool-a9jx8gf4.js → packager-tool-2vmsh5pt.js} +196 -1519
- package/dist/{packager-tool-px1j9kre.js → packager-tool-3bwnkjdq.js} +2 -2
- package/dist/{packager-tool-gb35b4qs.js → packager-tool-43ahv5mn.js} +192 -96
- package/dist/{packager-tool-9ha2z8h5.js → packager-tool-47by487p.js} +6 -4
- package/dist/packager-tool-47wzvqw0.js +86 -0
- package/dist/{packager-tool-zns6n8zp.js → packager-tool-5ddtwzva.js} +1 -1
- package/dist/packager-tool-5edvzz80.js +543 -0
- package/dist/{packager-tool-jq9zw82w.js → packager-tool-5n6jsn41.js} +104 -14
- package/dist/packager-tool-60af1hw2.js +26 -0
- package/dist/{packager-tool-f5gq77m5.js → packager-tool-61pwb567.js} +2 -2
- package/dist/{packager-tool-yrz4mwfn.js → packager-tool-6kz1pv9f.js} +1373 -486
- package/dist/packager-tool-6ybywxxn.js +1809 -0
- package/dist/packager-tool-8ptbmmmp.js +2132 -0
- package/dist/{packager-tool-7gr2nphb.js → packager-tool-97rcgwvv.js} +224 -6
- package/dist/{packager-tool-83m6ns0r.js → packager-tool-9t26kde1.js} +3556 -1646
- package/dist/packager-tool-act5r386.js +239 -0
- package/dist/packager-tool-amhyxzz6.js +125 -0
- package/dist/packager-tool-b03rva43.js +188 -0
- package/dist/{packager-tool-e2rtr49j.js → packager-tool-b2nhscfk.js} +15 -31
- package/dist/{packager-tool-tv9c1e80.js → packager-tool-d6rrfd46.js} +149 -53
- package/dist/packager-tool-frr2xmkr.js +445 -0
- package/dist/{packager-tool-v8bkkqdb.js → packager-tool-gmwva4yv.js} +5 -5
- package/dist/packager-tool-gs3f3tf7.js +103 -0
- package/dist/packager-tool-jg692f13.js +517 -0
- package/dist/packager-tool-jmpb786m.js +109 -0
- package/dist/{packager-tool-5sex4a1h.js → packager-tool-kds8ytzw.js} +74 -23
- package/dist/packager-tool-kkfb5kgn.js +182 -0
- package/dist/packager-tool-kvcxg0zv.js +1510 -0
- package/dist/packager-tool-n3jfjn5r.js +42 -0
- package/dist/{packager-tool-fjsn5h8s.js → packager-tool-n5d5dx5j.js} +2196 -3455
- package/dist/{packager-tool-yfpcvdpm.js → packager-tool-nsya65z1.js} +357 -1370
- package/dist/{packager-tool-fv7xyzg2.js → packager-tool-pbmqk39a.js} +126 -128
- package/dist/{packager-tool-bqre28m1.js → packager-tool-qw47eyw7.js} +1 -1
- package/dist/{packager-tool-9qgmwy21.js → packager-tool-rc3hwn4b.js} +25 -4
- package/dist/packager-tool-resolver-994z3jkj.js +23 -0
- package/dist/{packager-tool-tgw5x6vx.js → packager-tool-rvt68c1t.js} +17 -8
- package/dist/{packager-tool-gab9y5ct.js → packager-tool-t8gh825q.js} +37 -13
- package/dist/{packager-tool-kswwd3hp.js → packager-tool-tx834spe.js} +2376 -4077
- package/dist/{packager-tool-zf3929se.js → packager-tool-v1f5e8t9.js} +11 -1
- package/dist/{packager-tool-ssq2kzqm.js → packager-tool-w77d72a7.js} +13 -11
- package/dist/{packager-tool-1rzssy0x.js → packager-tool-wy4fx250.js} +19 -18
- package/dist/packager-tool-wz34ma3s.js +1333 -0
- package/dist/packager-tool-zq16e1xv.js +68 -0
- package/dist/packager-tool.js +2 -2
- package/dist/prepare-solution-resources-m1djfj62.js +29 -0
- package/dist/project-command-utils-t6pmpvq3.js +90 -0
- package/dist/project-contributions-79ndycrx.js +32 -0
- package/dist/publish.js +13 -12
- package/dist/resource-mutations-c3krjqze.js +36 -0
- package/dist/resource-version-lookup-0e3e2j58.js +99 -0
- package/dist/resource.js +10 -9
- package/dist/restore-command-service-5v0b9363.js +155 -0
- package/dist/run-service-tg6b67wp.js +428 -0
- package/dist/services/deploy-activate-service.d.ts +10 -5
- package/dist/services/deploy-delete-service.d.ts +8 -4
- package/dist/services/deploy-run-service.d.ts +34 -1
- package/dist/services/deploy-uninstall-service.d.ts +21 -3
- package/dist/services/deploy-upgrade-service.d.ts +35 -1
- package/dist/services/deployment-feed-locator.d.ts +15 -4
- package/dist/services/deployment-search-client.d.ts +5 -53
- package/dist/services/deployment-search.d.ts +58 -3
- package/dist/services/deployment-state.d.ts +84 -24
- package/dist/services/deployment-validation.d.ts +5 -0
- package/dist/services/emit-runtime-dependencies.d.ts +2 -1
- package/dist/services/feed-resolver.d.ts +6 -4
- package/dist/services/feed-selection.d.ts +47 -0
- package/dist/services/http-status.d.ts +2 -7
- package/dist/services/pack-command-service.d.ts +9 -0
- package/dist/services/pack-project-selection.d.ts +51 -0
- package/dist/services/pack-project.d.ts +26 -0
- package/dist/services/pack-service.d.ts +7 -3
- package/dist/services/package-search-client.d.ts +7 -0
- package/dist/services/packager-tool-resolver.d.ts +7 -1
- package/dist/services/packages-list-service.d.ts +1 -1
- package/dist/services/permanent-deletion-consent.d.ts +110 -0
- package/dist/services/pipeline-deploy-poll.d.ts +7 -0
- package/dist/services/prepare-solution-resources.d.ts +12 -2
- package/dist/services/project-contributions.d.ts +5 -4
- package/dist/services/search-failure.d.ts +9 -13
- package/dist/services/solution-packager-helpers.d.ts +5 -2
- package/dist/services/solution-path.d.ts +1 -1
- package/dist/services/uninstall-consent.d.ts +82 -0
- package/dist/ship-telemetry-myes7ak5.js +21 -0
- package/dist/solution-auth-aead70sw.js +11 -0
- package/dist/templates/AGENTS.md +125 -12
- package/dist/tool.js +27 -29
- package/dist/utils/deployment-errors.d.ts +9 -1
- package/package.json +2 -2
- package/dist/deploy-delete-service-w3e8x1kq.js +0 -22
- package/dist/feed-scope-failure-0j5byccb.js +0 -18
- package/dist/packager-tool-f2e9rzxk.js +0 -104
- package/dist/packager-tool-resolver-6zwhec62.js +0 -20
- package/dist/packager-tool-zdfn32bc.js +0 -4465
- package/dist/prepare-solution-resources-jpb5as2s.js +0 -25
- package/dist/project-contributions-6wpff2hm.js +0 -30
- package/dist/services/legacy-deployment-search-v3.d.ts +0 -23
|
@@ -1,135 +1,65 @@
|
|
|
1
|
+
import {
|
|
2
|
+
inspectSolutionPackageProjectTypes,
|
|
3
|
+
trackSolutionShipSucceeded
|
|
4
|
+
} from "./packager-tool-amhyxzz6.js";
|
|
1
5
|
import {
|
|
2
6
|
getStudioWebAuthWithOrganizationId,
|
|
3
7
|
useStudioWebAuth
|
|
4
|
-
} from "./packager-tool-
|
|
8
|
+
} from "./packager-tool-gmwva4yv.js";
|
|
5
9
|
import {
|
|
6
10
|
resolveFeedScopeOrFailureAsync
|
|
7
|
-
} from "./packager-tool-
|
|
11
|
+
} from "./packager-tool-47by487p.js";
|
|
8
12
|
import {
|
|
9
13
|
activateDeploymentAsync,
|
|
10
|
-
deployRunAsync,
|
|
11
|
-
extractDeploymentErrors,
|
|
12
|
-
formatDeploymentErrorsAsText,
|
|
13
14
|
listDeploymentsAsync,
|
|
14
15
|
listPackagesAsync,
|
|
15
16
|
uninstallDeploymentAsync,
|
|
16
17
|
upgradeDeploymentAsync
|
|
17
|
-
} from "./packager-tool-
|
|
18
|
+
} from "./packager-tool-kvcxg0zv.js";
|
|
19
|
+
import {
|
|
20
|
+
extractDeploymentErrors,
|
|
21
|
+
formatDeploymentErrorsAsText
|
|
22
|
+
} from "./packager-tool-act5r386.js";
|
|
18
23
|
import {
|
|
19
24
|
SolutionInitError,
|
|
20
25
|
solutionInitAsync
|
|
21
|
-
} from "./packager-tool-
|
|
26
|
+
} from "./packager-tool-3bwnkjdq.js";
|
|
22
27
|
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
SOLUTION_PATH_INSTRUCTIONS,
|
|
26
|
-
SolutionPackOptions,
|
|
27
|
-
applyAuthConnection,
|
|
28
|
-
checkSolutionPathAsync,
|
|
29
|
-
createSolutionPackager,
|
|
30
|
-
packSolutionAsync,
|
|
31
|
-
readSolutionFileAsUint8Array,
|
|
32
|
-
resolveSdkLogLevel,
|
|
33
|
-
validateGovernanceOptions
|
|
34
|
-
} from "./packager-tool-fjsn5h8s.js";
|
|
35
|
-
import {
|
|
36
|
-
prepareSolutionResources
|
|
37
|
-
} from "./packager-tool-gab9y5ct.js";
|
|
38
|
-
import {
|
|
39
|
-
ensurePackagerTools,
|
|
40
|
-
isUnpackableProjectTypeError,
|
|
41
|
-
toolVerbForProjectType
|
|
42
|
-
} from "./packager-tool-e2rtr49j.js";
|
|
28
|
+
validatePackProjectOptions
|
|
29
|
+
} from "./packager-tool-gs3f3tf7.js";
|
|
43
30
|
import {
|
|
44
31
|
publishSolutionAsync
|
|
45
|
-
} from "./packager-tool-
|
|
46
|
-
import {
|
|
47
|
-
Configuration,
|
|
48
|
-
PipelinesApi
|
|
49
|
-
} from "./packager-tool-7gr2nphb.js";
|
|
32
|
+
} from "./packager-tool-w77d72a7.js";
|
|
50
33
|
import {
|
|
51
34
|
feedScopeInitOverride,
|
|
52
35
|
listSelectablePublishLocations
|
|
53
|
-
} from "./packager-tool-
|
|
54
|
-
import {
|
|
55
|
-
DeploymentActivationStatus,
|
|
56
|
-
DeploymentOperationStatus,
|
|
57
|
-
StudioWebIncompatibleProjectError,
|
|
58
|
-
UipignoreExcludesProjectError,
|
|
59
|
-
buildSolutionUploadFailureOutput,
|
|
60
|
-
bundleSolution,
|
|
61
|
-
getProjectDebugStatus,
|
|
62
|
-
importSolution,
|
|
63
|
-
isDebugProvisioningSucceeded,
|
|
64
|
-
isDebugProvisioningTerminal,
|
|
65
|
-
isSolutionUploadHttpError,
|
|
66
|
-
overwriteSolution,
|
|
67
|
-
solutionExistsOnStudioWeb
|
|
68
|
-
} from "./packager-tool-83m6ns0r.js";
|
|
36
|
+
} from "./packager-tool-rvt68c1t.js";
|
|
69
37
|
import {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
createProjectInSolutionBuilder,
|
|
74
|
-
createResourceBuilderServices,
|
|
75
|
-
createResourceKindMetadataResolver,
|
|
76
|
-
exportResourceDefinitionAsync,
|
|
77
|
-
findCatalogEntityAsync,
|
|
78
|
-
findMatchingLocalResource,
|
|
79
|
-
findProjectFile,
|
|
80
|
-
findResourceByKeyInRcs,
|
|
81
|
-
formatResourceSubtypes,
|
|
82
|
-
getRemoteResourceClients,
|
|
83
|
-
hasAnyTemplateRow,
|
|
84
|
-
hasBareTemplateRow,
|
|
85
|
-
isMissingProjectTypeError,
|
|
86
|
-
isProjectManifestError,
|
|
87
|
-
normalizeFolderPath,
|
|
88
|
-
normalizeResourceFileCasing,
|
|
89
|
-
readProjectFile,
|
|
90
|
-
readSolutionFile,
|
|
91
|
-
readSpecProperty,
|
|
92
|
-
resolveResourceKindMetadata,
|
|
93
|
-
resolveSolutionFilePath,
|
|
94
|
-
resourceRefreshAsync,
|
|
95
|
-
resourceRemoteSyncAsync,
|
|
96
|
-
restoreSolutionFile,
|
|
97
|
-
sameResourceSubtype,
|
|
98
|
-
saveCasingNormalized,
|
|
99
|
-
searchRcsResources,
|
|
100
|
-
syncResourcesFromBindings,
|
|
101
|
-
toResourceReference,
|
|
102
|
-
validateResourceName,
|
|
103
|
-
writeSolutionFile
|
|
104
|
-
} from "./packager-tool-yrz4mwfn.js";
|
|
38
|
+
Configuration,
|
|
39
|
+
PipelinesApi
|
|
40
|
+
} from "./packager-tool-97rcgwvv.js";
|
|
105
41
|
import {
|
|
106
|
-
|
|
107
|
-
|
|
42
|
+
DeploymentActivationStatus,
|
|
43
|
+
DeploymentOperationStatus
|
|
44
|
+
} from "./packager-tool-9t26kde1.js";
|
|
108
45
|
import {
|
|
109
46
|
getSolutionAuthContext
|
|
110
|
-
} from "./packager-tool-
|
|
47
|
+
} from "./packager-tool-61pwb567.js";
|
|
111
48
|
import {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
updateUipxSolutionId
|
|
115
|
-
} from "./packager-tool-f2e9rzxk.js";
|
|
49
|
+
getLoginStatusAsync
|
|
50
|
+
} from "./packager-tool-43ahv5mn.js";
|
|
116
51
|
import {
|
|
117
|
-
CommandDimensions,
|
|
118
52
|
DEFAULT_PAGE_SIZE,
|
|
119
53
|
Option,
|
|
120
54
|
OutputFormatter,
|
|
121
55
|
Pagination,
|
|
122
56
|
PollOutcome,
|
|
123
57
|
RESULTS,
|
|
124
|
-
|
|
58
|
+
addDeprecatedOptionAlias,
|
|
125
59
|
carriedErrorCode,
|
|
126
|
-
carriedInstructions,
|
|
127
60
|
carriedRetry,
|
|
128
|
-
catchError,
|
|
129
61
|
createHiddenDeprecatedTenantOption,
|
|
130
|
-
|
|
131
|
-
extractErrorMessage,
|
|
132
|
-
isGuid,
|
|
62
|
+
httpStatusOf,
|
|
133
63
|
isPreviewBuild,
|
|
134
64
|
logger,
|
|
135
65
|
mapPackageMetadataOptions,
|
|
@@ -146,18 +76,18 @@ import {
|
|
|
146
76
|
unsupportedSolutionProjectType,
|
|
147
77
|
warnDeprecatedOptionAlias,
|
|
148
78
|
withCompleter
|
|
149
|
-
} from "./packager-tool-
|
|
79
|
+
} from "./packager-tool-tx834spe.js";
|
|
150
80
|
import {
|
|
151
|
-
|
|
152
|
-
|
|
81
|
+
CommandDimensions,
|
|
82
|
+
ShipDimensions,
|
|
83
|
+
carriedInstructions,
|
|
84
|
+
catchError,
|
|
85
|
+
extractErrorDetails,
|
|
86
|
+
extractErrorMessage
|
|
87
|
+
} from "./packager-tool-6ybywxxn.js";
|
|
153
88
|
import {
|
|
154
89
|
getFileSystem
|
|
155
|
-
} from "./packager-tool-
|
|
156
|
-
import {
|
|
157
|
-
strFromU8,
|
|
158
|
-
unzip,
|
|
159
|
-
unzipSync
|
|
160
|
-
} from "./packager-tool-dfrk01gn.js";
|
|
90
|
+
} from "./packager-tool-v1f5e8t9.js";
|
|
161
91
|
import {
|
|
162
92
|
__require
|
|
163
93
|
} from "./packager-tool-1de529jm.js";
|
|
@@ -166,7 +96,7 @@ var package_default = {
|
|
|
166
96
|
name: "@uipath/solution-tool",
|
|
167
97
|
author: "UiPath",
|
|
168
98
|
license: "SEE LICENSE IN LICENSE.txt",
|
|
169
|
-
version: "1.
|
|
99
|
+
version: "1.205.0-preview.256",
|
|
170
100
|
description: "Create, pack, publish, and deploy UiPath Automation Solutions.",
|
|
171
101
|
repository: {
|
|
172
102
|
type: "git",
|
|
@@ -229,7 +159,8 @@ var package_default = {
|
|
|
229
159
|
"@uipath/packager-tool-connector": "workspace:*",
|
|
230
160
|
"@uipath/pipelines-sdk": "workspace:*",
|
|
231
161
|
"@uipath/project-executor": "workspace:*",
|
|
232
|
-
"@uipath/
|
|
162
|
+
"@uipath/project-packager": "workspace:*",
|
|
163
|
+
"@uipath/resource-builder-sdk": "2025.11.0-alpha6584-4367",
|
|
233
164
|
"@uipath/resource-builder-tool": "2025.11.0-alpha6004-4107",
|
|
234
165
|
"@uipath/solution-packager": "workspace:*",
|
|
235
166
|
"@uipath/solution-sdk": "workspace:*",
|
|
@@ -241,113 +172,6 @@ var package_default = {
|
|
|
241
172
|
}
|
|
242
173
|
};
|
|
243
174
|
|
|
244
|
-
// src/services/cleanup-command-service.ts
|
|
245
|
-
class CleanupCommandService {
|
|
246
|
-
packager = null;
|
|
247
|
-
fs;
|
|
248
|
-
constructor() {
|
|
249
|
-
this.fs = getFileSystem();
|
|
250
|
-
}
|
|
251
|
-
async execute(solutionPath, options, context) {
|
|
252
|
-
const check = await checkSolutionPathAsync(this.fs, solutionPath);
|
|
253
|
-
if (!check.ok) {
|
|
254
|
-
this.reportFailureAndExit(context, check.message, SOLUTION_PATH_INSTRUCTIONS, check.statError, check.errorCode);
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
const { absoluteSolutionPath } = check;
|
|
258
|
-
logger.info(options.dryRun ? `
|
|
259
|
-
Detecting unused items (dry-run)...
|
|
260
|
-
` : `
|
|
261
|
-
Removing unused items...
|
|
262
|
-
`);
|
|
263
|
-
logger.info("Details:");
|
|
264
|
-
logger.info(` Solution: ${absoluteSolutionPath}`);
|
|
265
|
-
logger.info("");
|
|
266
|
-
const [error, result] = await catchError(this.executeAsync(solutionPath, options));
|
|
267
|
-
if (error) {
|
|
268
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
269
|
-
this.reportFailureAndExit(context, msg, carriedInstructions(error) ?? "Check that the solution can be loaded, the required packager tools are available, and the current login has access to the tenant.", error);
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
if (result.errorCode !== "SUCCESS" /* Success */) {
|
|
273
|
-
this.reportFailureAndExit(context, `Error code: ${result.errorCode} : ${result.message}`, result.instructions ?? result.message ?? "");
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
const changedFilesByProject = result.details?.changedFilesByProject ?? {};
|
|
277
|
-
const cleanupByProject = result.details?.cleanupByProject ?? {};
|
|
278
|
-
OutputFormatter.success({
|
|
279
|
-
Result: RESULTS.Success,
|
|
280
|
-
Code: "SolutionCleanup",
|
|
281
|
-
Data: {
|
|
282
|
-
DryRun: Boolean(options.dryRun),
|
|
283
|
-
ChangedFilesByProject: changedFilesByProject,
|
|
284
|
-
CleanupByProject: cleanupByProject
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
reportFailureAndExit(context, message, instructions, error, errorCode) {
|
|
289
|
-
OutputFormatter.error({
|
|
290
|
-
Result: RESULTS.Failure,
|
|
291
|
-
Message: message,
|
|
292
|
-
Instructions: instructions,
|
|
293
|
-
ErrorCode: errorCode
|
|
294
|
-
});
|
|
295
|
-
if (error instanceof Error && error.stack) {
|
|
296
|
-
logger.error("Stack trace:");
|
|
297
|
-
logger.error(error.stack);
|
|
298
|
-
}
|
|
299
|
-
context.exit(1);
|
|
300
|
-
}
|
|
301
|
-
async executeAsync(solutionPath, options) {
|
|
302
|
-
if (options.loginValidity !== undefined && Number.isNaN(options.loginValidity)) {
|
|
303
|
-
return new ToolResult("INTERNAL_ERROR" /* InternalError */, `Invalid --login-validity value: ${options.loginValidity}`, []);
|
|
304
|
-
}
|
|
305
|
-
const check = await checkSolutionPathAsync(this.fs, solutionPath);
|
|
306
|
-
if (!check.ok) {
|
|
307
|
-
return new ToolResult("INTERNAL_ERROR" /* InternalError */, check.message, []);
|
|
308
|
-
}
|
|
309
|
-
const { absoluteSolutionPath, isUisFile } = check;
|
|
310
|
-
if (isUisFile && !options.dryRun) {
|
|
311
|
-
return new ToolResult("INTERNAL_ERROR" /* InternalError */, `In-place cleanup of a .uis file is not supported: changes would be written to a temporary extraction and then discarded, leaving '${absoluteSolutionPath}' unchanged. Re-run with --dry-run to only detect unused items, or point at an unpacked solution directory to modify it in place.`, []);
|
|
312
|
-
}
|
|
313
|
-
const [error, result] = await catchError(async () => {
|
|
314
|
-
const packager = await this.ensurePackagerAsync();
|
|
315
|
-
let inputPath;
|
|
316
|
-
if (isUisFile) {
|
|
317
|
-
const uint8Array = await readSolutionFileAsUint8Array(this.fs, absoluteSolutionPath);
|
|
318
|
-
inputPath = await packager.setupAsync(uint8Array);
|
|
319
|
-
} else {
|
|
320
|
-
inputPath = await packager.setupAsync(absoluteSolutionPath);
|
|
321
|
-
}
|
|
322
|
-
await ensurePackagerTools(inputPath, this.fs);
|
|
323
|
-
const cleanupOptions = await this.createCleanupOptions(inputPath, options);
|
|
324
|
-
return packager.cleanupSolutionAsync(cleanupOptions);
|
|
325
|
-
});
|
|
326
|
-
if (error) {
|
|
327
|
-
return new ToolResult("INTERNAL_ERROR" /* InternalError */, error instanceof Error ? error.message : String(error), [], carriedInstructions(error));
|
|
328
|
-
}
|
|
329
|
-
return result;
|
|
330
|
-
}
|
|
331
|
-
async ensurePackagerAsync() {
|
|
332
|
-
this.packager ??= await createSolutionPackager();
|
|
333
|
-
return this.packager;
|
|
334
|
-
}
|
|
335
|
-
async createCleanupOptions(inputPath, options) {
|
|
336
|
-
const cleanupOptions = new SolutionPackOptions;
|
|
337
|
-
cleanupOptions.inputPath = inputPath;
|
|
338
|
-
cleanupOptions.cleanupOptions = {
|
|
339
|
-
dryRun: options.dryRun ?? false,
|
|
340
|
-
skipImports: options.skipImports ?? false
|
|
341
|
-
};
|
|
342
|
-
cleanupOptions.logLevel = resolveSdkLogLevel();
|
|
343
|
-
cleanupOptions.nuGetSourcesConfigPath = options.nugetSourcesConfigPath;
|
|
344
|
-
cleanupOptions.excludeConfiguredSources = options.excludeConfiguredSources ?? false;
|
|
345
|
-
cleanupOptions.feedFolder = options.feedFolder;
|
|
346
|
-
await applyAuthConnection(cleanupOptions, options.loginValidity);
|
|
347
|
-
return cleanupOptions;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
175
|
// src/commands/cleanup.ts
|
|
352
176
|
var SOLUTION_CLEANUP_EXAMPLES = [
|
|
353
177
|
{
|
|
@@ -388,7 +212,8 @@ var SOLUTION_CLEANUP_EXAMPLES = [
|
|
|
388
212
|
}
|
|
389
213
|
];
|
|
390
214
|
var registerCleanupCommand = (program) => {
|
|
391
|
-
program.command("cleanup").description("Remove unused items from every project in a UiPath solution. Accepts a solution directory (containing .uipx) or a .uis file. For a directory the project sources are modified in place. Pass --dry-run to only detect unused items.").argument("<
|
|
215
|
+
program.command("cleanup").description("Remove unused items from every project in a UiPath solution. Accepts a solution directory (containing .uipx) or a .uis file. For a directory the project sources are modified in place. Pass --dry-run to only detect unused items.").argument("<solution-path>", "Path to a solution directory (containing .uipx) or a .uis file").option("--dry-run", "Detect unused items but do not modify any project files.").option("--skip-imports", "Do not clean up now-unused references to removed items in the project's files.").option("--nuget-sources-config-path <path>", "Path to NuGet sources configuration file").option("--exclude-configured-sources", "Resolve project dependencies only from the tenant feeds and any --nuget-sources-config-path. Drops the built-in UiPath and nuget.org feeds, so a dependency that is not on those feeds fails to restore.").option("--feed-folder <name>", "Resolve project dependencies from this Orchestrator folder's library feed instead of every tenant feed. Accepts a folder name or fully qualified path.").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", (value) => Number.parseInt(value, 10), 10).examples(SOLUTION_CLEANUP_EXAMPLES).trackedAction(processContext, async (solutionPath, options) => {
|
|
216
|
+
const { CleanupCommandService } = await import("./cleanup-command-service-n4e7vxnw.js");
|
|
392
217
|
const service = new CleanupCommandService;
|
|
393
218
|
const cleanupOptions = {
|
|
394
219
|
dryRun: options.dryRun,
|
|
@@ -492,9 +317,11 @@ var SOLUTION_DEPLOY_ACTIVATE_EXAMPLES = [
|
|
|
492
317
|
}
|
|
493
318
|
];
|
|
494
319
|
var registerDeployActivateCommand = (program) => {
|
|
495
|
-
program.command("activate").description("Activate a deployed solution that was deployed without auto-activation. Activation provisions all solution components.").argument("<deployment-name>", "Name of the deployment to activate. Use 'solution deploy list' to find deployment names.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--timeout <seconds>", "Timeout in seconds for activation polling (default: 360)", (v) => parseInt(v, 10), 360).option("--poll-interval <ms>", "Milliseconds between activation status polls (default: 5000)", (v) => parseInt(v, 10), 5000).option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).examples(SOLUTION_DEPLOY_ACTIVATE_EXAMPLES).trackedAction(processContext, async (deploymentName, options) => {
|
|
320
|
+
program.command("activate").description("Activate a deployed solution that was deployed without auto-activation. Activation provisions all solution components.").argument("<deployment-name>", "Name of the deployment to activate. Use 'solution deploy list' to find deployment names.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--timeout <seconds>", "Timeout in seconds for activation polling (default: 360)", (v) => parseInt(v, 10), 360).option("--poll-interval <ms>", "Milliseconds between activation status polls (default: 5000)", (v) => parseInt(v, 10), 5000).option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).addOption(new Option("--feed <name-or-key>", "The feed the deployment lives in (name or folder key, from 'solution feeds list'). Only that feed is searched; without it the tenant feed, your Personal Workspace and the folder feeds are tried in turn. Needs a user session for a feed other than the tenant's. Mutually exclusive with --personal-workspace.").conflicts("personalWorkspace")).option("--personal-workspace", "The deployment lives in your Personal Workspace feed: only that feed is searched. Needs a user session.").examples(SOLUTION_DEPLOY_ACTIVATE_EXAMPLES).trackedAction(processContext, async (deploymentName, options) => {
|
|
496
321
|
const result = await activateDeploymentAsync(deploymentName, {
|
|
497
322
|
tenant: options.tenant,
|
|
323
|
+
personalWorkspace: options.personalWorkspace,
|
|
324
|
+
feed: options.feed,
|
|
498
325
|
timeout: options.timeout,
|
|
499
326
|
pollInterval: options.pollInterval,
|
|
500
327
|
loginValidity: options.loginValidity,
|
|
@@ -1049,13 +876,15 @@ var SOLUTION_DEPLOY_DELETE_EXAMPLES = [
|
|
|
1049
876
|
}
|
|
1050
877
|
];
|
|
1051
878
|
var registerDeployDeleteCommand = (program) => {
|
|
1052
|
-
program.command("delete").description("Delete a deployment from the tenant. Use this for a deployment that 'deploy uninstall' cannot remove: one left inactive after an uninstall, one superseded by a newer version, or one left behind by a failed install — Orchestrator refuses to uninstall those with error 4007. The command reads the deployment first, and refuses when its own action list offers actions but not Delete, naming the state and the actions that are available. A record that lists no actions at all says nothing, so there the request goes to the server and the server decides.").argument("<deployment-name>", "Name of the deployment to delete. Use 'solution deploy list' to find deployment names.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).option("-y, --yes", "Confirm this irreversible operation (required; the CLI never prompts)").examples(SOLUTION_DEPLOY_DELETE_EXAMPLES).trackedAction(processContext, async (deploymentName, options) => {
|
|
879
|
+
program.command("delete").description("Delete a deployment from the tenant. Use this for a deployment that 'deploy uninstall' cannot remove: one left inactive after an uninstall, one superseded by a newer version, or one left behind by a failed install — Orchestrator refuses to uninstall those with error 4007. The command reads the deployment first, and refuses when its own action list offers actions but not Delete, naming the state and the actions that are available. A record that lists no actions at all says nothing, so there the request goes to the server and the server decides.").argument("<deployment-name>", "Name of the deployment to delete. Use 'solution deploy list' to find deployment names.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).option("-y, --yes", "Confirm this irreversible operation (required; the CLI never prompts)").addOption(new Option("--feed <name-or-key>", "The feed the deployment lives in (name or folder key, from 'solution feeds list'). Only that feed is searched; without it the tenant feed, your Personal Workspace and the folder feeds are tried in turn. Needs a user session for a feed other than the tenant's. Mutually exclusive with --personal-workspace.").conflicts("personalWorkspace")).option("--personal-workspace", "The deployment lives in your Personal Workspace feed: only that feed is searched. Needs a user session.").examples(SOLUTION_DEPLOY_DELETE_EXAMPLES).trackedAction(processContext, async (deploymentName, options) => {
|
|
1053
880
|
if (!requireConfirmation(options, `delete deployment '${deploymentName}'`)) {
|
|
1054
881
|
return;
|
|
1055
882
|
}
|
|
1056
|
-
const { deleteDeploymentAsync } = await import("./deploy-delete-service-
|
|
883
|
+
const { deleteDeploymentAsync } = await import("./deploy-delete-service-cag0q8yx.js");
|
|
1057
884
|
const result = await deleteDeploymentAsync(deploymentName, {
|
|
1058
885
|
tenant: options.tenant,
|
|
886
|
+
personalWorkspace: options.personalWorkspace,
|
|
887
|
+
feed: options.feed,
|
|
1059
888
|
loginValidity: options.loginValidity
|
|
1060
889
|
});
|
|
1061
890
|
if (!result.ok) {
|
|
@@ -1388,12 +1217,13 @@ var SOLUTION_DEPLOY_RUN_FEED_EXAMPLE = {
|
|
|
1388
1217
|
}
|
|
1389
1218
|
};
|
|
1390
1219
|
var registerDeployRunCommand = (program) => {
|
|
1391
|
-
const command = program.command("run").description("Deploy a solution package to Orchestrator. Creates a folder, provisions resources, and (by default) activates the solution. The deployment is keyed on --name: a name that does not exist yet gets a NEW deployment in a NEW folder (the normal case), while re-using an existing deployment's name updates that deployment in place — use 'deploy upgrade' when that is what you want. If the package is already deployed the command stops and points you at the upgrade path; pass --yes with a different --name to deploy a second, separate copy anyway. Pass --skip-activate to leave the deployment in 'Inactive (Ready to activate)' state and activate later with 'deploy activate'. A deployment whose resources need 'Setup activation' in Orchestrator is installed but not activated: the command reports Result: Success with ActivationStatus: NeedsSetupToActivate, the resources and the steps left — do not deploy it again. To customize resource settings before deploying, use 'config get' to fetch the default config, 'config set' / 'config link' to edit it, then pass it here with --config-file.").requiredOption("-n, --name <deployment-name>", "Name for the deployment").addOption(withCompleter(new Option("--package-name <name>", "Solution package name to deploy. Use 'solution packages list' to find available names.").makeOptionMandatory(), packageNameCompleter)).addOption(withCompleter(new Option("--package-version <version>", "Solution package version to deploy. Use 'solution packages list' to find available versions.").makeOptionMandatory(), packageVersionCompleter)).requiredOption("--folder-name <name>", "Name for the new Orchestrator folder created for this deployment (created under --parent-folder-path if specified)").addOption(new Option("--parent-folder-path <path>", "Parent folder path (e.g., 'Shared'). Solution folder is created under this.").conflicts("parentFolderKey")).option("--parent-folder-key <key>", "Parent folder key (GUID). Alternative to --parent-folder-path.").addOption(new Option("--personal-workspace", "Deploy into the current user's Personal Workspace. Resolves the workspace name from Orchestrator automatically; needs a user session (an external app has no workspace, and the server ignores the feed header on client-credentials requests). Mutually exclusive with --parent-folder-path and --parent-folder-key.").conflicts(["parentFolderPath", "parentFolderKey"])).option("--config-file <path>", "JSON or YAML configuration file. Generate with: uip solution deploy config get <name> -d config.json, then customize with 'config set' or 'config link'.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--timeout <seconds>", "Timeout in seconds applied per polling phase — deploy and (when not skipped) activate (default: 360 each)", (v) => parseInt(v, 10), 360).option("--poll-interval <ms>", "Milliseconds between status polls during the deploy and activate phases (default: 5000)", (v) => parseInt(v, 10), 5000).option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).addOption(new Option("--wait", "Deprecated and ignored: every deploy now waits for the install to finish (bounded by --timeout).").hideHelp()).option("--skip-activate", "Skip auto-activation; leave the deployment in 'Inactive (Ready to activate)' state. Activate later with 'uip solution deploy activate <name>'.").option("-y, --yes", "Deploy even when this package already has a deployment. Without it, deploy run looks the package up and stops if it is already deployed. That check is best-effort, not a guarantee: a lookup failure only warns, and under an application (client-credentials) login it never stops the deploy — an existing deployment is reported as a warning, or the check is skipped on servers without the Pipelines deployment search. --yes only skips that check: the install is keyed on --name, so re-using an existing deployment's name updates that deployment in place rather than creating a second copy — pass a different --name for a separate deployment.");
|
|
1220
|
+
const command = program.command("run").description("Deploy a solution package to Orchestrator. Creates a folder, provisions resources, and (by default) activates the solution. The deployment is keyed on --name: a name that does not exist yet gets a NEW deployment in a NEW folder (the normal case), while re-using an existing deployment's name updates that deployment in place — use 'deploy upgrade' when that is what you want. If the package is already deployed the command stops and points you at the upgrade path; pass --yes with a different --name to deploy a second, separate copy anyway. Pass --skip-activate to leave the deployment in 'Inactive (Ready to activate)' state and activate later with 'deploy activate'. A deployment whose resources need 'Setup activation' in Orchestrator is installed but not activated: the command reports Result: Success with ActivationStatus: NeedsSetupToActivate, the resources and the steps left — do not deploy it again. To customize resource settings before deploying, use 'config get' to fetch the default config, 'config set' / 'config link' to edit it, then pass it here with --config-file. When the deploy replaces an installed resource with a link (a config-file link to an existing resource), the server deletes the installed copy and its data, and asks for confirmation first: the command stops and lists those resources unless --acknowledge-permanent-deletion is passed.").requiredOption("-n, --name <deployment-name>", "Name for the deployment").addOption(withCompleter(new Option("--package-name <name>", "Solution package name to deploy. Use 'solution packages list' to find available names.").makeOptionMandatory(), packageNameCompleter)).addOption(withCompleter(new Option("--package-version <version>", "Solution package version to deploy. Use 'solution packages list' to find available versions.").makeOptionMandatory(), packageVersionCompleter)).requiredOption("--folder-name <name>", "Name for the new Orchestrator folder created for this deployment (created under --parent-folder-path if specified)").addOption(new Option("--parent-folder-path <path>", "Parent folder path (e.g., 'Shared'). Solution folder is created under this.").conflicts("parentFolderKey")).option("--parent-folder-key <key>", "Parent folder key (GUID). Alternative to --parent-folder-path.").addOption(new Option("--personal-workspace", "Deploy into the current user's Personal Workspace. Resolves the workspace name from Orchestrator automatically; needs a user session (an external app has no workspace, and the server ignores the feed header on client-credentials requests). Mutually exclusive with --parent-folder-path and --parent-folder-key.").conflicts(["parentFolderPath", "parentFolderKey"])).option("--config-file <path>", "JSON or YAML configuration file. Generate with: uip solution deploy config get <name> -d config.json, then customize with 'config set' or 'config link'.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--timeout <seconds>", "Timeout in seconds applied per polling phase — deploy and (when not skipped) activate (default: 360 each)", (v) => parseInt(v, 10), 360).option("--poll-interval <ms>", "Milliseconds between status polls during the deploy and activate phases (default: 5000)", (v) => parseInt(v, 10), 5000).option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).addOption(new Option("--wait", "Deprecated and ignored: every deploy now waits for the install to finish (bounded by --timeout).").hideHelp()).option("--skip-activate", "Skip auto-activation; leave the deployment in 'Inactive (Ready to activate)' state. Activate later with 'uip solution deploy activate <name>'.").option("-y, --yes", "Deploy even when this package already has a deployment. Without it, deploy run looks the package up and stops if it is already deployed. That check is best-effort, not a guarantee: a lookup failure only warns, and under an application (client-credentials) login it never stops the deploy — an existing deployment is reported as a warning, or the check is skipped on servers without the Pipelines deployment search. --yes only skips that check: the install is keyed on --name, so re-using an existing deployment's name updates that deployment in place rather than creating a second copy — pass a different --name for a separate deployment.").option("--acknowledge-permanent-deletion", "Confirm that installed resources this deployment replaces with a link are permanently deleted, along with their data. Without it the deploy stops at the server's confirmation request and lists those resources; nothing is installed. With it each listed resource is acknowledged and the same install runs once more, within the same --timeout. Independent of --yes.");
|
|
1392
1221
|
command.addOption(new Option("--feed <name-or-key>", "Deploy a package from a specific feed (name or folder key, from 'solution feeds list') instead of the tenant feed. Needs a user session: the server ignores the feed header on client-credentials requests, so an external app is refused rather than deploying to the tenant feed by accident. Mutually exclusive with --personal-workspace.").conflicts("personalWorkspace"));
|
|
1393
1222
|
command.examples([
|
|
1394
1223
|
...SOLUTION_DEPLOY_RUN_EXAMPLES,
|
|
1395
1224
|
SOLUTION_DEPLOY_RUN_FEED_EXAMPLE
|
|
1396
1225
|
]).trackedAction(processContext, async (options) => {
|
|
1226
|
+
const { deployRunAsync } = await import("./deploy-run-service-f0h8wb9w.js");
|
|
1397
1227
|
const result = await deployRunAsync({
|
|
1398
1228
|
tenant: options.tenant,
|
|
1399
1229
|
deploymentName: options.name,
|
|
@@ -1410,6 +1240,7 @@ var registerDeployRunCommand = (program) => {
|
|
|
1410
1240
|
loginValidity: options.loginValidity,
|
|
1411
1241
|
skipActivate: options.skipActivate,
|
|
1412
1242
|
yes: options.yes,
|
|
1243
|
+
acknowledgePermanentDeletion: options.acknowledgePermanentDeletion,
|
|
1413
1244
|
signal: processContext.pollSignal
|
|
1414
1245
|
});
|
|
1415
1246
|
if (!result.ok) {
|
|
@@ -1418,7 +1249,24 @@ var registerDeployRunCommand = (program) => {
|
|
|
1418
1249
|
Message: result.message,
|
|
1419
1250
|
Instructions: result.instructions,
|
|
1420
1251
|
ErrorCode: result.errorCode,
|
|
1421
|
-
Retry: result.retry
|
|
1252
|
+
Retry: result.retry,
|
|
1253
|
+
...result.permanentDeletionResources ? {
|
|
1254
|
+
Data: {
|
|
1255
|
+
PipelineDeploymentId: result.pipelineDeploymentId,
|
|
1256
|
+
DeploymentKey: result.deploymentKey,
|
|
1257
|
+
PermanentDeletionResources: result.permanentDeletionResources.map((resource) => ({
|
|
1258
|
+
Key: resource.key,
|
|
1259
|
+
Kind: resource.kind ?? null,
|
|
1260
|
+
Name: resource.name
|
|
1261
|
+
}))
|
|
1262
|
+
}
|
|
1263
|
+
} : {},
|
|
1264
|
+
...result.permanentlyDeletedResources ? {
|
|
1265
|
+
Data: {
|
|
1266
|
+
PipelineDeploymentId: result.pipelineDeploymentId,
|
|
1267
|
+
PermanentlyDeletedResources: result.permanentlyDeletedResources
|
|
1268
|
+
}
|
|
1269
|
+
} : {}
|
|
1422
1270
|
});
|
|
1423
1271
|
processContext.exit(result.exitCode);
|
|
1424
1272
|
return;
|
|
@@ -1441,10 +1289,12 @@ var registerDeployRunCommand = (program) => {
|
|
|
1441
1289
|
Kind: resource.kind,
|
|
1442
1290
|
Name: resource.name,
|
|
1443
1291
|
Type: resource.type ?? null,
|
|
1444
|
-
Reason: resource.reason ?? null
|
|
1292
|
+
Reason: resource.reason ?? null,
|
|
1293
|
+
FolderPaths: resource.folderPaths ?? null
|
|
1445
1294
|
}))
|
|
1446
1295
|
} : {},
|
|
1447
1296
|
...result.nextSteps ? { NextSteps: result.nextSteps } : {},
|
|
1297
|
+
PermanentlyDeletedResources: result.permanentlyDeletedResources,
|
|
1448
1298
|
DeploymentName: result.deploymentName,
|
|
1449
1299
|
PackageName: result.packageName,
|
|
1450
1300
|
PackageVersion: result.packageVersion
|
|
@@ -1581,8 +1431,8 @@ var registerDeployStatusCommand = (program) => {
|
|
|
1581
1431
|
processContext.exit(1);
|
|
1582
1432
|
return;
|
|
1583
1433
|
}
|
|
1584
|
-
const { feedScopeInitOverride: feedScopeInitOverride2 } = await import("./feed-resolver-
|
|
1585
|
-
const { FeedReadRefusedError, feedReadRefusalForApplication } = await import("./feed-session-
|
|
1434
|
+
const { feedScopeInitOverride: feedScopeInitOverride2 } = await import("./feed-resolver-fve33dxq.js");
|
|
1435
|
+
const { FeedReadRefusedError, feedReadRefusalForApplication } = await import("./feed-session-7xqphdrg.js");
|
|
1586
1436
|
const refuseFeed = (action) => {
|
|
1587
1437
|
const refusal = feedReadRefusalForApplication(auth, action);
|
|
1588
1438
|
if (!refusal) {
|
|
@@ -1601,14 +1451,14 @@ var registerDeployStatusCommand = (program) => {
|
|
|
1601
1451
|
if (options.personalWorkspace === true && refuseFeed("Reading a Personal Workspace deployment")) {
|
|
1602
1452
|
return;
|
|
1603
1453
|
}
|
|
1604
|
-
const { resolveFeedScopeOrFailureAsync: resolveFeedScopeOrFailureAsync2 } = await import("./feed-scope-failure-
|
|
1454
|
+
const { resolveFeedScopeOrFailureAsync: resolveFeedScopeOrFailureAsync2 } = await import("./feed-scope-failure-jmg4t1r1.js");
|
|
1605
1455
|
const [scopeFailure, feedScope] = await resolveFeedScopeOrFailureAsync2(options, auth);
|
|
1606
1456
|
if (scopeFailure) {
|
|
1607
1457
|
OutputFormatter.error(scopeFailure);
|
|
1608
1458
|
processContext.exit(1);
|
|
1609
1459
|
return;
|
|
1610
1460
|
}
|
|
1611
|
-
const { describeDeploymentAsync, looksLikeDeploymentKey } = await import("./deploy-status-service-
|
|
1461
|
+
const { describeDeploymentAsync, looksLikeDeploymentKey } = await import("./deploy-status-service-yh6xn6e0.js");
|
|
1612
1462
|
if (feedScope.kind !== "tenant" && !looksLikeDeploymentKey(deployment) && refuseFeed(`Reading a deployment in the feed '${feedScope.name ?? feedScope.folderKey}'`)) {
|
|
1613
1463
|
return;
|
|
1614
1464
|
}
|
|
@@ -1649,7 +1499,7 @@ var registerDeployStatusCommand = (program) => {
|
|
|
1649
1499
|
const api = new PipelinesApi(configuration);
|
|
1650
1500
|
const [statusError, result] = await catchError(api.pipelinesGetPipelineDeploymentStatus({ pipelineDeploymentId: deployment }, feedSelected ? feedScopeInitOverride2(feedScope) : undefined));
|
|
1651
1501
|
if (statusError) {
|
|
1652
|
-
const { isPipelineDeploymentNotFoundError } = await import("./deployment-search-
|
|
1502
|
+
const { isPipelineDeploymentNotFoundError } = await import("./deployment-search-mnywd9nc.js");
|
|
1653
1503
|
if (await isPipelineDeploymentNotFoundError(statusError)) {
|
|
1654
1504
|
const [stateError, state] = await catchError(describe());
|
|
1655
1505
|
if (stateError instanceof FeedReadRefusedError) {
|
|
@@ -1741,7 +1591,8 @@ function deploymentStateData(state) {
|
|
|
1741
1591
|
Kind: resource.kind,
|
|
1742
1592
|
Name: resource.name,
|
|
1743
1593
|
Type: resource.type ?? null,
|
|
1744
|
-
Reason: resource.reason ?? null
|
|
1594
|
+
Reason: resource.reason ?? null,
|
|
1595
|
+
FolderPaths: resource.folderPaths ?? null
|
|
1745
1596
|
}))
|
|
1746
1597
|
} : {},
|
|
1747
1598
|
...state.nextSteps ? { NextSteps: state.nextSteps } : {}
|
|
@@ -1764,15 +1615,18 @@ var SOLUTION_DEPLOY_UNINSTALL_EXAMPLES = [
|
|
|
1764
1615
|
}
|
|
1765
1616
|
];
|
|
1766
1617
|
var registerDeployUninstallCommand = (program) => {
|
|
1767
|
-
program.command("uninstall").description("Uninstall a deployed solution. Removes all provisioned resources and the solution folder.").argument("<deployment-name>", "Name of the deployment to uninstall. Use 'solution deploy list' to find deployment names.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--timeout <seconds>", "Timeout in seconds for uninstall polling (default: 360)", (v) => parseInt(v, 10), 360).option("--poll-interval <ms>", "Milliseconds between uninstall status polls (default: 5000)", (v) => parseInt(v, 10), 5000).option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).option("-y, --yes", "Confirm this irreversible operation (required; the CLI never prompts)").examples(SOLUTION_DEPLOY_UNINSTALL_EXAMPLES).trackedAction(processContext, async (deploymentName, options) => {
|
|
1618
|
+
program.command("uninstall").description("Uninstall a deployed solution. Removes all provisioned resources and the solution folder.").argument("<deployment-name>", "Name of the deployment to uninstall. Use 'solution deploy list' to find deployment names.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--timeout <seconds>", "Timeout in seconds for uninstall polling (default: 360)", (v) => parseInt(v, 10), 360).option("--poll-interval <ms>", "Milliseconds between uninstall status polls (default: 5000)", (v) => parseInt(v, 10), 5000).option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).option("-y, --yes", "Confirm this irreversible operation (required; the CLI never prompts)").option("--force", "Force the uninstall past the two refusals Orchestrator lets you override: uncompleted jobs, and the permanent deletion of installed resources that were replaced by links. Also confirms the operation, so --yes is not needed in addition. Flag only; the CLI never prompts.").addOption(new Option("--feed <name-or-key>", "The feed the deployment lives in (name or folder key, from 'solution feeds list'). Only that feed is searched; without it the tenant feed, your Personal Workspace and the folder feeds are tried in turn. Needs a user session for a feed other than the tenant's. Mutually exclusive with --personal-workspace.").conflicts("personalWorkspace")).option("--personal-workspace", "The deployment lives in your Personal Workspace feed: only that feed is searched. Needs a user session.").examples(SOLUTION_DEPLOY_UNINSTALL_EXAMPLES).trackedAction(processContext, async (deploymentName, options) => {
|
|
1768
1619
|
if (!requireConfirmation(options, `uninstall deployment '${deploymentName}'`)) {
|
|
1769
1620
|
return;
|
|
1770
1621
|
}
|
|
1771
1622
|
const result = await uninstallDeploymentAsync(deploymentName, {
|
|
1772
1623
|
tenant: options.tenant,
|
|
1624
|
+
personalWorkspace: options.personalWorkspace,
|
|
1625
|
+
feed: options.feed,
|
|
1773
1626
|
timeout: options.timeout,
|
|
1774
1627
|
pollInterval: options.pollInterval,
|
|
1775
1628
|
loginValidity: options.loginValidity,
|
|
1629
|
+
force: options.force,
|
|
1776
1630
|
signal: processContext.pollSignal
|
|
1777
1631
|
});
|
|
1778
1632
|
if (!result.ok) {
|
|
@@ -1781,7 +1635,8 @@ var registerDeployUninstallCommand = (program) => {
|
|
|
1781
1635
|
Message: result.message,
|
|
1782
1636
|
Instructions: result.instructions,
|
|
1783
1637
|
ErrorCode: result.errorCode,
|
|
1784
|
-
Retry: result.retry
|
|
1638
|
+
Retry: result.retry,
|
|
1639
|
+
...result.data ? { Data: result.data } : {}
|
|
1785
1640
|
});
|
|
1786
1641
|
processContext.exit(result.exitCode);
|
|
1787
1642
|
return;
|
|
@@ -1943,7 +1798,7 @@ var SOLUTION_DEPLOY_UPGRADE_EXAMPLES = [
|
|
|
1943
1798
|
}
|
|
1944
1799
|
];
|
|
1945
1800
|
var registerDeployUpgradeCommand = (program) => {
|
|
1946
|
-
program.command("upgrade").description("Upgrade an existing deployment to another published version of its package in place — the CLI equivalent of the Orchestrator UI 'Upgrade' button. Use this when 'deploy run' is blocked because a deployment already exists. The deployment's existing configuration is preserved, so values already set on it (for example a credential asset's secret) are not reset to the package defaults. The package is validated against the target before anything is installed; a validation failure reports the errors and leaves the deployment on its current version. Address the deployment either by key (positional) or by --name with --package-name. Every call this command makes is an external-app (client-credentials) capable Pipelines endpoint, so both forms work from a CI/CD pipeline (on a server that predates the Pipelines deployment lookup, the key form falls back to the Solutions API for a user session); a deployment in a Personal Workspace or folder feed needs a user session, because the server ignores the feed header on client-credentials requests. Waits for the upgrade to finish unless --no-wait is passed; track a running upgrade with 'deploy status <pipeline-deployment-id>'.").argument("[deployment-key]", "Key of the deployment to upgrade, as 'solution deploy list' reports it (Key), or a stored InstallDeploymentKey. Resolved through the Pipelines deployment lookup: the deployment's name, package, current version and feed come from the server, so --package-name and --personal-workspace are not needed. On a server without that lookup, a user session reads the key through the Solutions API instead, where a Personal Workspace deployment needs --personal-workspace. Use either this or --name with --package-name.").option("-n, --name <deployment-name>", "Name of the deployment to upgrade, as reported by 'solution deploy list'. Goes with --package-name. The name is checked to exist first, because the install route would create a new deployment for a name it cannot find; this form never does.").option("--package-name <name>", "The deployment's package, for the --name form. Required there: it identifies the package version to install, and nothing name-keyed in Pipelines reports it.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--version <version>", "Target package version (default: the newest published). Any published version of the same package is accepted, including an older one.").option("--personal-workspace", "With --name: upgrade a deployment in your Personal Workspace feed instead of the tenant. With a key the feed is read from the deployment itself and this flag is not needed, except on a server without the Pipelines deployment lookup, where a key is read on the tenant feed unless you pass it.").option("--discard-draft", "When the deployment has a pending draft (an earlier attempt that never completed, usually one rejected by validation), discard it first and upgrade the live version. Without it such a deployment is refused, because the server would re-run the draft, with the configuration it was rejected for, in place of this upgrade. With --name the draft is found through a user session only; under an external app, pass the deployment key.").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).option("--no-wait", "Return as soon as the upgrade is accepted instead of waiting for it to finish.").option("--timeout <seconds>", "Seconds to wait for the upgrade to finish (default: 300)", (v) => parseInt(v, 10), 300).option("--poll-interval <ms>", "Milliseconds between status polls (default: 5000)", (v) => parseInt(v, 10), 5000).examples(SOLUTION_DEPLOY_UPGRADE_EXAMPLES).trackedAction(processContext, async (deploymentKey, options) => {
|
|
1801
|
+
program.command("upgrade").description("Upgrade an existing deployment to another published version of its package in place — the CLI equivalent of the Orchestrator UI 'Upgrade' button. Use this when 'deploy run' is blocked because a deployment already exists. The deployment's existing configuration is preserved, so values already set on it (for example a credential asset's secret) are not reset to the package defaults. The package is validated against the target before anything is installed; a validation failure reports the errors and leaves the deployment on its current version. Address the deployment either by key (positional) or by --name with --package-name. Every call this command makes is an external-app (client-credentials) capable Pipelines endpoint, so both forms work from a CI/CD pipeline (on a server that predates the Pipelines deployment lookup, the key form falls back to the Solutions API for a user session); a deployment in a Personal Workspace or folder feed needs a user session, because the server ignores the feed header on client-credentials requests. Waits for the upgrade to finish unless --no-wait is passed; track a running upgrade with 'deploy status <pipeline-deployment-id>'. When the new version replaces an installed resource with a link, the server deletes the installed copy and its data, and asks for confirmation first: the command stops and lists those resources unless --acknowledge-permanent-deletion is passed.").argument("[deployment-key]", "Key of the deployment to upgrade, as 'solution deploy list' reports it (Key), or a stored InstallDeploymentKey. Resolved through the Pipelines deployment lookup: the deployment's name, package, current version and feed come from the server, so --package-name and --personal-workspace are not needed. On a server without that lookup, a user session reads the key through the Solutions API instead, where a Personal Workspace deployment needs --personal-workspace. Use either this or --name with --package-name.").option("-n, --name <deployment-name>", "Name of the deployment to upgrade, as reported by 'solution deploy list'. Goes with --package-name. The name is checked to exist first, because the install route would create a new deployment for a name it cannot find; this form never does.").option("--package-name <name>", "The deployment's package, for the --name form. Required there: it identifies the package version to install, and nothing name-keyed in Pipelines reports it.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--version <version>", "Target package version (default: the newest published). Any published version of the same package is accepted, including an older one.").option("--personal-workspace", "With --name: upgrade a deployment in your Personal Workspace feed instead of the tenant. With a key the feed is read from the deployment itself and this flag is not needed, except on a server without the Pipelines deployment lookup, where a key is read on the tenant feed unless you pass it.").option("--discard-draft", "When the deployment has a pending draft (an earlier attempt that never completed, usually one rejected by validation), discard it first and upgrade the live version. Without it such a deployment is refused, because the server would re-run the draft, with the configuration it was rejected for, in place of this upgrade. With --name the draft is found through a user session only; under an external app, pass the deployment key.").option("--acknowledge-permanent-deletion", "Confirm that installed resources the new version replaces with a link are permanently deleted, along with their data. Without it the upgrade stops at the server's confirmation request and lists those resources; nothing is installed. With it each listed resource is acknowledged and the same upgrade runs once more, within the same --timeout. Also re-runs a pending draft of the same version that awaits this confirmation instead of refusing it. Has no effect with --no-wait, which never sees the run end: such a draft is then refused as without the flag.").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).option("--no-wait", "Return as soon as the upgrade is accepted instead of waiting for it to finish.").option("--timeout <seconds>", "Seconds to wait for the upgrade to finish (default: 300)", (v) => parseInt(v, 10), 300).option("--poll-interval <ms>", "Milliseconds between status polls (default: 5000)", (v) => parseInt(v, 10), 5000).examples(SOLUTION_DEPLOY_UPGRADE_EXAMPLES).trackedAction(processContext, async (deploymentKey, options) => {
|
|
1947
1802
|
const result = await upgradeDeploymentAsync({
|
|
1948
1803
|
deploymentKey,
|
|
1949
1804
|
deploymentName: options.name,
|
|
@@ -1952,6 +1807,7 @@ var registerDeployUpgradeCommand = (program) => {
|
|
|
1952
1807
|
version: options.version,
|
|
1953
1808
|
personalWorkspace: options.personalWorkspace,
|
|
1954
1809
|
discardDraft: options.discardDraft,
|
|
1810
|
+
acknowledgePermanentDeletion: options.acknowledgePermanentDeletion,
|
|
1955
1811
|
loginValidity: options.loginValidity,
|
|
1956
1812
|
noWait: options.wait === false,
|
|
1957
1813
|
timeout: options.timeout,
|
|
@@ -1964,7 +1820,18 @@ var registerDeployUpgradeCommand = (program) => {
|
|
|
1964
1820
|
Message: result.message,
|
|
1965
1821
|
Instructions: result.instructions,
|
|
1966
1822
|
ErrorCode: result.errorCode,
|
|
1967
|
-
Retry: result.retry
|
|
1823
|
+
Retry: result.retry,
|
|
1824
|
+
...result.permanentDeletionResources ? {
|
|
1825
|
+
Data: {
|
|
1826
|
+
PipelineDeploymentId: result.pipelineDeploymentId,
|
|
1827
|
+
DeploymentKey: result.deploymentKey,
|
|
1828
|
+
PermanentDeletionResources: result.permanentDeletionResources.map((resource) => ({
|
|
1829
|
+
Key: resource.key,
|
|
1830
|
+
Kind: resource.kind ?? null,
|
|
1831
|
+
Name: resource.name
|
|
1832
|
+
}))
|
|
1833
|
+
}
|
|
1834
|
+
} : {}
|
|
1968
1835
|
});
|
|
1969
1836
|
processContext.exit(result.exitCode);
|
|
1970
1837
|
return;
|
|
@@ -1983,7 +1850,8 @@ var registerDeployUpgradeCommand = (program) => {
|
|
|
1983
1850
|
Kind: resource.kind,
|
|
1984
1851
|
Name: resource.name,
|
|
1985
1852
|
Type: resource.type ?? null,
|
|
1986
|
-
Reason: resource.reason ?? null
|
|
1853
|
+
Reason: resource.reason ?? null,
|
|
1854
|
+
FolderPaths: resource.folderPaths ?? null
|
|
1987
1855
|
}))
|
|
1988
1856
|
} : {},
|
|
1989
1857
|
...result.nextSteps ? { NextSteps: result.nextSteps } : {},
|
|
@@ -1993,7 +1861,8 @@ var registerDeployUpgradeCommand = (program) => {
|
|
|
1993
1861
|
PipelineDeploymentId: result.pipelineDeploymentId,
|
|
1994
1862
|
DeploymentKey: result.deploymentKey,
|
|
1995
1863
|
InstallDeploymentKey: result.installDeploymentKey,
|
|
1996
|
-
DiscardedDraftKey: result.discardedDraftKey
|
|
1864
|
+
DiscardedDraftKey: result.discardedDraftKey,
|
|
1865
|
+
PermanentlyDeletedResources: result.permanentlyDeletedResources
|
|
1997
1866
|
}
|
|
1998
1867
|
});
|
|
1999
1868
|
});
|
|
@@ -2060,104 +1929,6 @@ async function writeMissingBriefingFilesAsync(solutionDir) {
|
|
|
2060
1929
|
return written;
|
|
2061
1930
|
}
|
|
2062
1931
|
|
|
2063
|
-
// ../common/src/zip.ts
|
|
2064
|
-
function resolveZipEntryPath(fs, root, entryName) {
|
|
2065
|
-
if (entryName.includes("\x00")) {
|
|
2066
|
-
throw new Error(`Invalid zip entry path: ${entryName}`);
|
|
2067
|
-
}
|
|
2068
|
-
const normalizedEntry = entryName.replace(/\\/g, "/");
|
|
2069
|
-
if (normalizedEntry.startsWith("/")) {
|
|
2070
|
-
throw new Error(`Unsafe absolute zip entry path: ${entryName}`);
|
|
2071
|
-
}
|
|
2072
|
-
const target = fs.path.resolve(root, normalizedEntry);
|
|
2073
|
-
if (!isUnder(fs, root, target)) {
|
|
2074
|
-
throw new Error(`Unsafe zip entry path: ${entryName}`);
|
|
2075
|
-
}
|
|
2076
|
-
return target;
|
|
2077
|
-
}
|
|
2078
|
-
function isUnder(fs, root, path) {
|
|
2079
|
-
const relative = fs.path.relative(root, path);
|
|
2080
|
-
return relative === "" || !relative.startsWith("..") && !fs.path.isAbsolute(relative);
|
|
2081
|
-
}
|
|
2082
|
-
async function assertNoEscapeThroughSymlink(fs, lexicalRoot, realRoot, path, entryName) {
|
|
2083
|
-
const resolved = await fs.realpath(path);
|
|
2084
|
-
if (isUnder(fs, realRoot, resolved) || isUnder(fs, lexicalRoot, resolved)) {
|
|
2085
|
-
return;
|
|
2086
|
-
}
|
|
2087
|
-
throw new Error(`Unsafe zip entry path (escapes via a symlink at the destination): ${entryName}`);
|
|
2088
|
-
}
|
|
2089
|
-
async function mkdirUnderRoot(fs, lexicalRoot, realRoot, dir, entryName) {
|
|
2090
|
-
const relative = fs.path.relative(lexicalRoot, dir);
|
|
2091
|
-
if (relative === "") {
|
|
2092
|
-
return;
|
|
2093
|
-
}
|
|
2094
|
-
let current = lexicalRoot;
|
|
2095
|
-
for (const segment of relative.split(/[\\/]/)) {
|
|
2096
|
-
if (segment === "") {
|
|
2097
|
-
continue;
|
|
2098
|
-
}
|
|
2099
|
-
current = fs.path.join(current, segment);
|
|
2100
|
-
await fs.mkdir(current);
|
|
2101
|
-
await assertNoEscapeThroughSymlink(fs, lexicalRoot, realRoot, current, entryName);
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
async function extractZipDataToDir(fs, zipData, destinationDir) {
|
|
2105
|
-
await fs.mkdir(destinationDir);
|
|
2106
|
-
const lexicalRoot = fs.path.resolve(destinationDir);
|
|
2107
|
-
const realRoot = await fs.realpath(lexicalRoot);
|
|
2108
|
-
const entries = unzipSync(zipData);
|
|
2109
|
-
for (const [entryName, content] of Object.entries(entries)) {
|
|
2110
|
-
const target = resolveZipEntryPath(fs, lexicalRoot, entryName);
|
|
2111
|
-
if (entryName.endsWith("/")) {
|
|
2112
|
-
await mkdirUnderRoot(fs, lexicalRoot, realRoot, target, entryName);
|
|
2113
|
-
continue;
|
|
2114
|
-
}
|
|
2115
|
-
await mkdirUnderRoot(fs, lexicalRoot, realRoot, fs.path.dirname(target), entryName);
|
|
2116
|
-
await assertNoEscapeThroughSymlink(fs, lexicalRoot, realRoot, target, entryName);
|
|
2117
|
-
await fs.writeFile(target, content);
|
|
2118
|
-
}
|
|
2119
|
-
}
|
|
2120
|
-
async function extractArchive(archivePath, destinationDir) {
|
|
2121
|
-
const fs = getFileSystem();
|
|
2122
|
-
const data = await fs.readFile(archivePath);
|
|
2123
|
-
if (data === null) {
|
|
2124
|
-
throw new Error(`Archive not found: ${archivePath}`);
|
|
2125
|
-
}
|
|
2126
|
-
await extractZipDataToDir(fs, data, destinationDir);
|
|
2127
|
-
}
|
|
2128
|
-
|
|
2129
|
-
// src/services/archive-extract.ts
|
|
2130
|
-
var SOLUTION_STORAGE_ENTRY = "SolutionStorage.json";
|
|
2131
|
-
function isRootUipxEntry(name) {
|
|
2132
|
-
return !name.includes("/") && name.endsWith(".uipx");
|
|
2133
|
-
}
|
|
2134
|
-
function readSolutionIdField(bytes) {
|
|
2135
|
-
if (!bytes) {
|
|
2136
|
-
return;
|
|
2137
|
-
}
|
|
2138
|
-
const [parseError, parsed] = catchError(() => JSON.parse(strFromU8(bytes)));
|
|
2139
|
-
if (parseError || !parsed) {
|
|
2140
|
-
return;
|
|
2141
|
-
}
|
|
2142
|
-
const id = parsed.SolutionId;
|
|
2143
|
-
return typeof id === "string" && isGuid(id) ? id : undefined;
|
|
2144
|
-
}
|
|
2145
|
-
function readBundledSolutionId(archive) {
|
|
2146
|
-
const [unzipError, entries] = catchError(() => unzipSync(archive, {
|
|
2147
|
-
filter: (file) => file.name === SOLUTION_STORAGE_ENTRY || isRootUipxEntry(file.name)
|
|
2148
|
-
}));
|
|
2149
|
-
if (unzipError || !entries) {
|
|
2150
|
-
logger.debug(`Could not inspect the solution archive for its SolutionId: ${unzipError?.message ?? "no entries"}`);
|
|
2151
|
-
return;
|
|
2152
|
-
}
|
|
2153
|
-
const rootUipxName = Object.keys(entries).find(isRootUipxEntry);
|
|
2154
|
-
const solutionId = readSolutionIdField(entries[SOLUTION_STORAGE_ENTRY]) ?? readSolutionIdField(rootUipxName ? entries[rootUipxName] : undefined);
|
|
2155
|
-
if (!solutionId) {
|
|
2156
|
-
logger.debug("No SolutionId found in the solution archive.");
|
|
2157
|
-
}
|
|
2158
|
-
return solutionId;
|
|
2159
|
-
}
|
|
2160
|
-
|
|
2161
1932
|
// src/commands/download.ts
|
|
2162
1933
|
var SOLUTION_DOWNLOAD_EXAMPLES = [
|
|
2163
1934
|
{
|
|
@@ -2217,6 +1988,7 @@ async function downloadSolution(solutionId, options, command) {
|
|
|
2217
1988
|
const extractedTo = options.extract ? fs.path.join(outputDir, filename.replace(/\.uis$/, "")) : undefined;
|
|
2218
1989
|
let briefingFiles = [];
|
|
2219
1990
|
if (extractedTo) {
|
|
1991
|
+
const { extractArchive } = await import("./archive-extract-x35t9ktj.js");
|
|
2220
1992
|
await extractArchive(outputPath, extractedTo);
|
|
2221
1993
|
logger.info(`Extracted to ${extractedTo}`);
|
|
2222
1994
|
briefingFiles = await writeBriefingFiles(extractedTo);
|
|
@@ -2337,7 +2109,7 @@ var SOLUTION_NEW_EXAMPLES = [
|
|
|
2337
2109
|
}
|
|
2338
2110
|
];
|
|
2339
2111
|
var registerNewCommand = (program) => {
|
|
2340
|
-
program.command("init").description("Initialize a new empty UiPath solution. Creates a directory named after the solution containing a .uipx manifest file with an empty Projects array, plus AGENTS.md and CLAUDE.md briefing files that orient AI coding agents to the solution. Use 'solution projects add' to add projects afterward.").argument("<
|
|
2112
|
+
program.command("init").description("Initialize a new empty UiPath solution. Creates a directory named after the solution containing a .uipx manifest file with an empty Projects array, plus AGENTS.md and CLAUDE.md briefing files that orient AI coding agents to the solution. Use 'solution projects add' to add projects afterward.").argument("<solution-name>", "Solution name or path. Creates a directory with this name containing a .uipx manifest file.").examples(SOLUTION_NEW_EXAMPLES).trackedAction(processContext, async (solutionName) => {
|
|
2341
2113
|
const [briefingError, briefingContent] = await catchError(renderBriefingTemplateAsync());
|
|
2342
2114
|
if (briefingError) {
|
|
2343
2115
|
OutputFormatter.error({
|
|
@@ -2413,6 +2185,17 @@ var SOLUTION_PACK_EXAMPLES = [
|
|
|
2413
2185
|
}
|
|
2414
2186
|
}
|
|
2415
2187
|
},
|
|
2188
|
+
{
|
|
2189
|
+
Description: "Pack one project of the solution into its own .nupkg instead of the solution .zip, as a stand-alone project packs: no solution resources go into it. --project takes the project's Id from the .uipx or its path relative to the solution; --package-id overrides the id a whole-solution pack would give it.",
|
|
2190
|
+
Command: "uip solution pack ./my-solution ./dist --project MyProcess --package-id Acme.MyProcess --version 1.2.0",
|
|
2191
|
+
Output: {
|
|
2192
|
+
Code: "SolutionPack",
|
|
2193
|
+
Data: {
|
|
2194
|
+
Package: "Acme.MyProcess@1.2.0",
|
|
2195
|
+
Packages: "/home/me/dist/Acme.MyProcess.1.2.0.nupkg"
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
},
|
|
2416
2199
|
{
|
|
2417
2200
|
Description: "Pack without running the workflow analyzer on the RPA projects. Compilation and validation still run — only the analyzer rules are skipped.",
|
|
2418
2201
|
Command: "uip solution pack ./my-solution ./dist --version 1.2.0 --skip-analyze",
|
|
@@ -2429,7 +2212,7 @@ var SOLUTION_PACK_EXAMPLES = [
|
|
|
2429
2212
|
Output: PACKED_1_2_0_OUTPUT
|
|
2430
2213
|
},
|
|
2431
2214
|
{
|
|
2432
|
-
Description: "Analyze the RPA projects against the governance policy published in AutomationOps for the signed-in tenant. The value is the product whose policy is downloaded — pass StudioWeb for the default one.",
|
|
2215
|
+
Description: "Analyze the RPA projects against the governance policy published in AutomationOps for the signed-in tenant. The value is the product whose policy is downloaded — pass StudioWeb for the default one. Signed in as an external application, the policy is not downloaded yet.",
|
|
2433
2216
|
Command: "uip solution pack ./my-solution ./dist --version 1.2.0 --governance-product Development",
|
|
2434
2217
|
Output: PACKED_1_2_0_OUTPUT
|
|
2435
2218
|
}
|
|
@@ -2439,13 +2222,29 @@ function parseIgnoredRules(value, previous = []) {
|
|
|
2439
2222
|
return [...new Set([...previous, ...rules])];
|
|
2440
2223
|
}
|
|
2441
2224
|
var registerPackCommand = (program) => {
|
|
2442
|
-
const command = program.command("pack").description("Pack a UiPath solution into a deployable .zip package. Accepts a solution directory (containing .uipx) or a .uis file. Output is used with 'solution publish' to upload to UiPath. Pass --dry-run to check that the solution packs without producing a package.").argument("<
|
|
2225
|
+
const command = program.command("pack").description("Pack a UiPath solution into a deployable .zip package. Accepts a solution directory (containing .uipx) or a .uis file. Output is used with 'solution publish' to upload to UiPath. Pass --project to pack one project into its own .nupkg instead. Pass --dry-run to check that the solution packs without producing a package.").argument("<solution-path>", "Path to a solution directory (containing .uipx) or a .uis file").argument("[output-path]", "Output directory where the packed solution will be saved. Required unless --dry-run is set.").option("-n, --name <name>", "Package name (default: solution folder name or .uis file name)").option("-v, --version <version>", "Package version (default: 1.0.0)", "1.0.0").addOption(new Option("--solution-type <type>", "What kind of solution this is. Omitted by default, which means a standard solution.").choices(["standard", "vertical"]).hideHelp()).option("--project <id-or-path>", "Pack only this project of the solution into its own .nupkg, instead of the solution .zip. It packs as a stand-alone project: no solution resources go into it. Takes the project's Id from the .uipx, or its path relative to the solution folder; a .uis file is not supported.").option("--package-id <id>", "Package id for the project packed with --project, instead of the id a whole-solution pack gives it (<solution>.<type>.<project folder>). Requires --project.").option("--nuget-sources-config-path <path>", "Path to NuGet sources configuration file").option("--exclude-configured-sources", "Resolve project dependencies only from the tenant feeds and any --nuget-sources-config-path. Drops the built-in UiPath and nuget.org feeds, so a dependency that is not on those feeds fails to restore.").option("--feed-folder <name>", "Resolve project dependencies from this Orchestrator folder's library feed instead of every tenant feed. Accepts a folder name or fully qualified path.").option("--signing-certificate-path <path>", "Path to .pfx certificate file used to sign each packed project .nupkg").option("--signing-certificate-password <password>", "Certificate password. Use env.ENV_NAME to read from an environment variable.").option("--signing-timestamp-server <url>", "Timestamp server URL").option("--skip-analyze", "Skip the workflow analyzer for every RPA project in the solution. Compilation and validation still run.").option("--ignored-rules <rules>", "Analyzer rule IDs whose findings are ignored for every RPA project, e.g. ST-USG-034,ST-MRD-002. Comma-separated; repeat the flag to add more. The rules still run, but their findings are not reported and do not fail the pack. Applies on top of --governance-file-path or the shipped rules; when the signed-in tenant publishes an AutomationOps policy, the list is not applied and a warning says so.", parseIgnoredRules).option("--governance-file-path <path>", "Analyze every RPA project against this local governance policy file, instead of the analyzer rules shipped with the WorkflowCompiler. When you are signed in as a user the tenant is asked first — about StudioWeb unless --governance-product names another product — and when the tenant publishes a policy of its own, that policy is used instead and this file is ignored with a warning.").option("--governance-product <product>", "Analyze every RPA project against the governance policy published in AutomationOps for the signed-in tenant. The value is the product whose policy is downloaded, e.g. StudioWeb, Development, Business. Signed in as an external application, the policy is not downloaded yet (AutomationOps does not accept external-application tokens): the pack uses --governance-file-path if given, otherwise the rules shipped with the WorkflowCompiler.").addOption(new Option("--automation-ops-profile <profile>").hideHelp());
|
|
2443
2226
|
registerPackageMetadataOptions(command).option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).option("--dry-run", "Run the full pack pipeline against a temporary directory and discard the output. Catches pack-time failures; does not inspect the produced package contents.").examples(SOLUTION_PACK_EXAMPLES).trackedAction(processContext, async (solutionPath, outputPath, options) => {
|
|
2227
|
+
const {
|
|
2228
|
+
GOVERNANCE_OPTION_INSTRUCTIONS,
|
|
2229
|
+
validateGovernanceOptions
|
|
2230
|
+
} = await import("./governance-options-4vxz7ekn.js");
|
|
2231
|
+
const { PackCommandService } = await import("./pack-command-service-dewf5vsq.js");
|
|
2444
2232
|
if (!options.dryRun && outputPath === undefined) {
|
|
2445
2233
|
OutputFormatter.error({
|
|
2446
2234
|
Result: RESULTS.Failure,
|
|
2447
|
-
Message: "Missing required argument:
|
|
2448
|
-
Instructions: "Run `uip solution pack <
|
|
2235
|
+
Message: "Missing required argument: output-path. Provide an output directory, or pass --dry-run to validate without packing.",
|
|
2236
|
+
Instructions: "Run `uip solution pack <solution-path> <output-path>` to produce a package, or `uip solution pack <solution-path> --dry-run` to validate only."
|
|
2237
|
+
});
|
|
2238
|
+
processContext.exit(1);
|
|
2239
|
+
return;
|
|
2240
|
+
}
|
|
2241
|
+
const projectError = validatePackProjectOptions(options);
|
|
2242
|
+
if (projectError) {
|
|
2243
|
+
OutputFormatter.error({
|
|
2244
|
+
Result: RESULTS.Failure,
|
|
2245
|
+
ErrorCode: "invalid_argument",
|
|
2246
|
+
Message: projectError,
|
|
2247
|
+
Instructions: "Pass --project <id-or-path> to pack one project, and --package-id <id> (not --name) only together with it: `uip solution pack <solution-path> <output-path> --project <id-or-path> [--package-id <id>]`."
|
|
2449
2248
|
});
|
|
2450
2249
|
processContext.exit(1);
|
|
2451
2250
|
return;
|
|
@@ -2485,6 +2284,8 @@ var registerPackCommand = (program) => {
|
|
|
2485
2284
|
const packOptions = {
|
|
2486
2285
|
output: outputPath,
|
|
2487
2286
|
name: options.name,
|
|
2287
|
+
project: options.project,
|
|
2288
|
+
packageId: options.packageId,
|
|
2488
2289
|
version: options.version,
|
|
2489
2290
|
solutionType: options.solutionType,
|
|
2490
2291
|
loginValidity: options.loginValidity,
|
|
@@ -2840,40 +2641,6 @@ var registerPackagesCommand = (program) => {
|
|
|
2840
2641
|
|
|
2841
2642
|
// src/commands/project-add.ts
|
|
2842
2643
|
import { randomUUID } from "node:crypto";
|
|
2843
|
-
|
|
2844
|
-
// src/commands/project-command-utils.ts
|
|
2845
|
-
function rejectUnsupportedProjectType(projectType, failureMessage) {
|
|
2846
|
-
const reason = unsupportedSolutionProjectType(projectType);
|
|
2847
|
-
if (!reason) {
|
|
2848
|
-
return false;
|
|
2849
|
-
}
|
|
2850
|
-
OutputFormatter.error({
|
|
2851
|
-
Result: RESULTS.Failure,
|
|
2852
|
-
Message: failureMessage,
|
|
2853
|
-
Instructions: reason
|
|
2854
|
-
});
|
|
2855
|
-
processContext.exit(1);
|
|
2856
|
-
return true;
|
|
2857
|
-
}
|
|
2858
|
-
function projectManifestInstructions(fileName, readProjectError, verb) {
|
|
2859
|
-
if (fileName !== "uipath.json" || !isMissingProjectTypeError(readProjectError)) {
|
|
2860
|
-
return readProjectError.message;
|
|
2861
|
-
}
|
|
2862
|
-
return `${readProjectError.message} If this is a coded app, scaffold it with 'uip codedapp init <project-path>' — that writes the project.uiproj this command registers — then run 'uip solution projects ${verb} <project-path>' again.`;
|
|
2863
|
-
}
|
|
2864
|
-
function resourcesPendingForProjectType(projectType) {
|
|
2865
|
-
return !hasBareTemplateRow(projectType) && hasAnyTemplateRow(projectType);
|
|
2866
|
-
}
|
|
2867
|
-
function hostGeneratesResources(projectType) {
|
|
2868
|
-
return hasBareTemplateRow(projectType);
|
|
2869
|
-
}
|
|
2870
|
-
function resourcesPendingWarning(projectType) {
|
|
2871
|
-
const verb = toolVerbForProjectType(projectType);
|
|
2872
|
-
const needs = verb ? `that needs the '${verb}' tool installed ('uip tools install ${verb}')` : "that needs the tool that owns this project type installed";
|
|
2873
|
-
return `No solution resources were generated for this project yet. Run 'uip solution resources refresh' to create them — ${needs}. 'uip solution pack' and 'uip solution upload' do it too.`;
|
|
2874
|
-
}
|
|
2875
|
-
|
|
2876
|
-
// src/commands/project-add.ts
|
|
2877
2644
|
var PROJECT_ADD_EXAMPLES = [
|
|
2878
2645
|
{
|
|
2879
2646
|
Description: "Register an existing project subfolder in a solution",
|
|
@@ -2890,6 +2657,7 @@ var PROJECT_ADD_EXAMPLES = [
|
|
|
2890
2657
|
}
|
|
2891
2658
|
];
|
|
2892
2659
|
async function hasProjectInSolution(fs, solutionDir, projectDir, projects) {
|
|
2660
|
+
const { toPortableRelativePath } = await import("./index-g8c8nf1c.js");
|
|
2893
2661
|
const projectDirReal = await canonicalizePath(fs, projectDir);
|
|
2894
2662
|
for (const project of projects ?? []) {
|
|
2895
2663
|
const candidateDir = fs.path.resolve(solutionDir, fs.path.dirname(toPortableRelativePath(project.ProjectRelativePath)));
|
|
@@ -2905,9 +2673,29 @@ async function canonicalizePath(fs, path) {
|
|
|
2905
2673
|
return error || !realPath ? path : realPath;
|
|
2906
2674
|
}
|
|
2907
2675
|
var registerProjectAddCommand = (project) => {
|
|
2908
|
-
project.command("add").description("Register an existing project subfolder in the .uipx solution manifest. The project folder must already reside inside the solution directory. Use 'projects import' instead to copy an external project into the solution.").argument("<project-path>", "Path to the project folder (must contain project.uiproj, project.json, or uipath.json)").argument("[
|
|
2676
|
+
project.command("add").description("Register an existing project subfolder in the .uipx solution manifest. The project folder must already reside inside the solution directory. Use 'projects import' instead to copy an external project into the solution.").argument("<project-path>", "Path to the project folder (must contain project.uiproj, project.json, or uipath.json), or to that manifest file itself").argument("[solution-file]", "Path to the .uipx solution file (defaults to the nearest .uipx file found by searching up from the project path)").examples(PROJECT_ADD_EXAMPLES).trackedAction(processContext, async (projectPath, solutionFile) => {
|
|
2677
|
+
const {
|
|
2678
|
+
createProjectInSolutionBuilder,
|
|
2679
|
+
findProjectFile,
|
|
2680
|
+
isProjectManifestError,
|
|
2681
|
+
readProjectFile,
|
|
2682
|
+
readSolutionFile,
|
|
2683
|
+
resolveSolutionFilePath,
|
|
2684
|
+
restoreSolutionFile,
|
|
2685
|
+
syncResourcesFromBindings,
|
|
2686
|
+
writeSolutionFile
|
|
2687
|
+
} = await import("./index-prm27bvm.js");
|
|
2688
|
+
const { toPortableRelativePath } = await import("./index-g8c8nf1c.js");
|
|
2689
|
+
const {
|
|
2690
|
+
hostGeneratesResources,
|
|
2691
|
+
projectManifestInstructions,
|
|
2692
|
+
rejectUnsupportedProjectType,
|
|
2693
|
+
resolveProjectManifestDirectory,
|
|
2694
|
+
resourcesPendingForProjectType,
|
|
2695
|
+
resourcesPendingWarning
|
|
2696
|
+
} = await import("./project-command-utils-t6pmpvq3.js");
|
|
2909
2697
|
const fs = getFileSystem();
|
|
2910
|
-
const resolvedProjectPath = fs.path.resolve(fs.env.cwd(), projectPath);
|
|
2698
|
+
const resolvedProjectPath = await resolveProjectManifestDirectory(fs, fs.path.resolve(fs.env.cwd(), projectPath));
|
|
2911
2699
|
const isResolvedProjectPathValid = await fs.exists(resolvedProjectPath);
|
|
2912
2700
|
if (!isResolvedProjectPathValid) {
|
|
2913
2701
|
OutputFormatter.error({
|
|
@@ -3048,7 +2836,7 @@ import { randomUUID as randomUUID2 } from "node:crypto";
|
|
|
3048
2836
|
var PROJECT_IMPORT_EXAMPLES = [
|
|
3049
2837
|
{
|
|
3050
2838
|
Description: "Copy an external project folder into a solution",
|
|
3051
|
-
Command: "uip solution projects import ./external-project --
|
|
2839
|
+
Command: "uip solution projects import ./external-project --solution-file ./my-solution/my-solution.uipx",
|
|
3052
2840
|
Output: {
|
|
3053
2841
|
Code: "ProjectImport",
|
|
3054
2842
|
Data: {
|
|
@@ -3061,7 +2849,25 @@ var PROJECT_IMPORT_EXAMPLES = [
|
|
|
3061
2849
|
}
|
|
3062
2850
|
];
|
|
3063
2851
|
var registerProjectImportCommand = (project) => {
|
|
3064
|
-
project.command("import").description("Copy an external project folder into the solution directory and register it in the .uipx manifest. Unlike 'projects add' which references an existing subfolder, import copies the source files into the solution tree.").argument("<source>", "Path to the project folder to import (must contain project.uiproj, project.json, or uipath.json)").option("--
|
|
2852
|
+
const command = project.command("import").description("Copy an external project folder into the solution directory and register it in the .uipx manifest. Unlike 'projects add' which references an existing subfolder, import copies the source files into the solution tree.").argument("<source>", "Path to the project folder to import (must contain project.uiproj, project.json, or uipath.json)").option("--solution-file <path>", "Path to the .uipx solution file (defaults to the nearest .uipx file found by searching up from the current directory)").examples(PROJECT_IMPORT_EXAMPLES).trackedAction(processContext, async (sourcePath, options) => {
|
|
2853
|
+
const {
|
|
2854
|
+
createProjectInSolutionBuilder,
|
|
2855
|
+
findProjectFile,
|
|
2856
|
+
isProjectManifestError,
|
|
2857
|
+
readProjectFile,
|
|
2858
|
+
readSolutionFile,
|
|
2859
|
+
resolveSolutionFilePath,
|
|
2860
|
+
syncResourcesFromBindings,
|
|
2861
|
+
writeSolutionFile
|
|
2862
|
+
} = await import("./index-prm27bvm.js");
|
|
2863
|
+
const { toPortableRelativePath } = await import("./index-g8c8nf1c.js");
|
|
2864
|
+
const {
|
|
2865
|
+
hostGeneratesResources,
|
|
2866
|
+
projectManifestInstructions,
|
|
2867
|
+
rejectUnsupportedProjectType,
|
|
2868
|
+
resourcesPendingForProjectType,
|
|
2869
|
+
resourcesPendingWarning
|
|
2870
|
+
} = await import("./project-command-utils-t6pmpvq3.js");
|
|
3065
2871
|
const { solutionFile } = options;
|
|
3066
2872
|
const fs = getFileSystem();
|
|
3067
2873
|
const cwd = fs.env.cwd();
|
|
@@ -3229,6 +3035,7 @@ var registerProjectImportCommand = (project) => {
|
|
|
3229
3035
|
}
|
|
3230
3036
|
});
|
|
3231
3037
|
});
|
|
3038
|
+
addDeprecatedOptionAlias(command, "--solutionFile <path>", "--solution-file");
|
|
3232
3039
|
};
|
|
3233
3040
|
|
|
3234
3041
|
// src/commands/project-list.ts
|
|
@@ -3246,6 +3053,13 @@ function fallbackProjectName(fs, solutionDir, projectRelativePath) {
|
|
|
3246
3053
|
const projectDir = fs.path.dirname(projectRelativePath);
|
|
3247
3054
|
return projectDir && projectDir !== "." ? fs.path.basename(projectDir) : fs.path.basename(solutionDir);
|
|
3248
3055
|
}
|
|
3056
|
+
async function createPackageIdReaderAsync(fs, solutionDir, solutionName) {
|
|
3057
|
+
const { readMemberPackageIdAsync } = await import("./package-id-1wr3cy9c.js");
|
|
3058
|
+
return async (project) => {
|
|
3059
|
+
const [error, packageId] = await catchError(readMemberPackageIdAsync(fs, project, solutionDir, solutionName));
|
|
3060
|
+
return error ? undefined : packageId ?? undefined;
|
|
3061
|
+
};
|
|
3062
|
+
}
|
|
3249
3063
|
var PROJECT_LIST_EXAMPLES = [
|
|
3250
3064
|
{
|
|
3251
3065
|
Description: "List the local projects registered in the .uipx solution manifest (run from inside the solution dir, or pass --solution-folder)",
|
|
@@ -3258,14 +3072,16 @@ var PROJECT_LIST_EXAMPLES = [
|
|
|
3258
3072
|
Type: "Process",
|
|
3259
3073
|
Id: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
|
|
3260
3074
|
ProjectRelativePath: "MyProject/project.uiproj",
|
|
3261
|
-
ProjectFilePath: "/workspace/my-solution/MyProject/project.uiproj"
|
|
3075
|
+
ProjectFilePath: "/workspace/my-solution/MyProject/project.uiproj",
|
|
3076
|
+
PackageId: "my-solution.Rpa.MyProject"
|
|
3262
3077
|
}
|
|
3263
3078
|
]
|
|
3264
3079
|
}
|
|
3265
3080
|
}
|
|
3266
3081
|
];
|
|
3267
3082
|
var registerProjectListCommand = (project) => {
|
|
3268
|
-
project.command("list").description("List the projects registered in the local .uipx solution manifest. " + "Reads only on-disk metadata — does not call any backend.").option("--solution-folder <path>", "Path to the solution root folder (defaults to current directory)").examples(PROJECT_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
|
|
3083
|
+
project.command("list").description("List the projects registered in the local .uipx solution manifest, each with the package id a solution pack gives it. " + "Reads only on-disk metadata — does not call any backend.").option("--solution-folder <path>", "Path to the solution root folder (defaults to current directory)").examples(PROJECT_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
|
|
3084
|
+
const { readSolutionFile, resolveSolutionFilePath } = await import("./index-prm27bvm.js");
|
|
3269
3085
|
const fs = getFileSystem();
|
|
3270
3086
|
const solutionPath = options.solutionFolder ?? ".";
|
|
3271
3087
|
const resolvedPath = fs.path.resolve(fs.env.cwd(), solutionPath);
|
|
@@ -3300,6 +3116,7 @@ var registerProjectListCommand = (project) => {
|
|
|
3300
3116
|
return;
|
|
3301
3117
|
}
|
|
3302
3118
|
const solutionDir = fs.path.dirname(resolvedSolutionFile);
|
|
3119
|
+
const readPackageIdAsync = await createPackageIdReaderAsync(fs, solutionDir, fs.path.basename(resolvedSolutionFile).replace(/\.uipx$/i, ""));
|
|
3303
3120
|
const projects = parsedSolution.solution.Projects ?? [];
|
|
3304
3121
|
const data = await Promise.all(projects.map(async (p) => {
|
|
3305
3122
|
const projectFilePath = fs.path.resolve(solutionDir, p.ProjectRelativePath);
|
|
@@ -3309,7 +3126,12 @@ var registerProjectListCommand = (project) => {
|
|
|
3309
3126
|
Type: p.Type,
|
|
3310
3127
|
Id: p.Id,
|
|
3311
3128
|
ProjectRelativePath: p.ProjectRelativePath,
|
|
3312
|
-
ProjectFilePath: projectFilePath
|
|
3129
|
+
ProjectFilePath: projectFilePath,
|
|
3130
|
+
PackageId: await readPackageIdAsync({
|
|
3131
|
+
Id: p.Id,
|
|
3132
|
+
Type: p.Type,
|
|
3133
|
+
ProjectRelativePath: p.ProjectRelativePath
|
|
3134
|
+
})
|
|
3313
3135
|
};
|
|
3314
3136
|
}));
|
|
3315
3137
|
OutputFormatter.success({
|
|
@@ -3492,10 +3314,20 @@ var PROJECT_REMOVE_EXAMPLES = [
|
|
|
3492
3314
|
}
|
|
3493
3315
|
];
|
|
3494
3316
|
var registerProjectRemoveCommand = (project) => {
|
|
3495
|
-
project.command("remove").description("Unregister a project from the .uipx solution manifest and remove its entry from the solution builder. Does not delete the project files from disk. Doesn't remove the last project in a solution.").argument("<project-path>", "Path to the project folder to remove").argument("[
|
|
3317
|
+
project.command("remove").description("Unregister a project from the .uipx solution manifest and remove its entry from the solution builder. Does not delete the project files from disk. Doesn't remove the last project in a solution.").argument("<project-path>", "Path to the project folder to remove, or to its project manifest file (the form the .uipx records)").argument("[solution-file]", "Path to the .uipx solution file (defaults to the nearest .uipx file found by searching up from the project path)").examples(PROJECT_REMOVE_EXAMPLES).trackedAction(processContext, async (projectPath, solutionFile) => {
|
|
3318
|
+
const {
|
|
3319
|
+
createResourceBuilderServices,
|
|
3320
|
+
readSolutionFile,
|
|
3321
|
+
resolveSolutionFilePath,
|
|
3322
|
+
restoreSolutionFile,
|
|
3323
|
+
writeSolutionFile
|
|
3324
|
+
} = await import("./index-prm27bvm.js");
|
|
3325
|
+
const { toPortableRelativePath } = await import("./index-g8c8nf1c.js");
|
|
3326
|
+
const { resolveSolutionSearchStart } = await import("./project-command-utils-t6pmpvq3.js");
|
|
3496
3327
|
const fs = getFileSystem();
|
|
3497
3328
|
const resolvedProjectPath = fs.path.resolve(fs.env.cwd(), projectPath);
|
|
3498
|
-
const
|
|
3329
|
+
const searchStart = solutionFile ? resolvedProjectPath : await resolveSolutionSearchStart(fs, resolvedProjectPath);
|
|
3330
|
+
const [solutionFileError, resolvedSolutionFile] = await resolveSolutionFilePath(solutionFile, searchStart);
|
|
3499
3331
|
if (solutionFileError) {
|
|
3500
3332
|
OutputFormatter.error({
|
|
3501
3333
|
Result: RESULTS.Failure,
|
|
@@ -3529,7 +3361,11 @@ var registerProjectRemoveCommand = (project) => {
|
|
|
3529
3361
|
return;
|
|
3530
3362
|
}
|
|
3531
3363
|
const { solution, rawContent: originalSolutionContent } = parsedSolution;
|
|
3532
|
-
const
|
|
3364
|
+
const requestedPath = toPortableRelativePath(relativePath);
|
|
3365
|
+
const projectIndex = (solution.Projects ?? []).findIndex((p) => {
|
|
3366
|
+
const recorded = toPortableRelativePath(p.ProjectRelativePath);
|
|
3367
|
+
return recorded === requestedPath || fs.path.dirname(recorded) === requestedPath;
|
|
3368
|
+
});
|
|
3533
3369
|
if (projectIndex === -1) {
|
|
3534
3370
|
OutputFormatter.error({
|
|
3535
3371
|
Result: RESULTS.Failure,
|
|
@@ -3786,113 +3622,6 @@ var registerProjectCommand = (program) => {
|
|
|
3786
3622
|
wireProjectSubcommands(project);
|
|
3787
3623
|
};
|
|
3788
3624
|
|
|
3789
|
-
// src/services/ship-telemetry.ts
|
|
3790
|
-
var PROJECT_TYPE_MAP = {
|
|
3791
|
-
Agent: "low_code_agent",
|
|
3792
|
-
Api: "api_workflow",
|
|
3793
|
-
AppV2: "coded_app",
|
|
3794
|
-
CaseManagement: "case",
|
|
3795
|
-
Flow: "flow",
|
|
3796
|
-
Process: "rpa",
|
|
3797
|
-
ProcessOrchestration: "bpmn",
|
|
3798
|
-
WebApp: "coded_app",
|
|
3799
|
-
processOrchestration: "bpmn"
|
|
3800
|
-
};
|
|
3801
|
-
function isRecord(value) {
|
|
3802
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3803
|
-
}
|
|
3804
|
-
function normalizeShipProjectType(projectType) {
|
|
3805
|
-
return PROJECT_TYPE_MAP[projectType] ?? projectType.trim().toLowerCase();
|
|
3806
|
-
}
|
|
3807
|
-
function summarizeShipProjectTypes(projectTypes) {
|
|
3808
|
-
const normalized = [
|
|
3809
|
-
...new Set(projectTypes.map((projectType) => projectType.trim()).filter(Boolean).map(normalizeShipProjectType))
|
|
3810
|
-
];
|
|
3811
|
-
if (normalized.length === 0) {
|
|
3812
|
-
return { projectType: "unknown" };
|
|
3813
|
-
}
|
|
3814
|
-
if (normalized.length === 1) {
|
|
3815
|
-
return { projectType: normalized[0] };
|
|
3816
|
-
}
|
|
3817
|
-
const sortedProjectTypes = [...normalized];
|
|
3818
|
-
sortedProjectTypes.sort((left, right) => left.localeCompare(right));
|
|
3819
|
-
return {
|
|
3820
|
-
projectType: "mixed",
|
|
3821
|
-
projectTypes: sortedProjectTypes.join(",")
|
|
3822
|
-
};
|
|
3823
|
-
}
|
|
3824
|
-
function readProjectTypesFromUipx(content) {
|
|
3825
|
-
const parsed = JSON.parse(content);
|
|
3826
|
-
if (!isRecord(parsed) || !Array.isArray(parsed.Projects)) {
|
|
3827
|
-
return [];
|
|
3828
|
-
}
|
|
3829
|
-
return parsed.Projects.map((project) => {
|
|
3830
|
-
if (!isRecord(project)) {
|
|
3831
|
-
return;
|
|
3832
|
-
}
|
|
3833
|
-
return typeof project.Type === "string" ? project.Type : undefined;
|
|
3834
|
-
}).filter((projectType) => projectType !== undefined);
|
|
3835
|
-
}
|
|
3836
|
-
var MAX_INSPECTABLE_PACKAGE_BYTES = 256 * 1024 * 1024;
|
|
3837
|
-
function isProjectManifestEntry(name) {
|
|
3838
|
-
return name.endsWith(".uipx");
|
|
3839
|
-
}
|
|
3840
|
-
function unzipProjectManifests(archive) {
|
|
3841
|
-
return new Promise((resolve, reject) => {
|
|
3842
|
-
unzip(archive, { filter: (file) => isProjectManifestEntry(file.name) }, (error, entries) => {
|
|
3843
|
-
if (error) {
|
|
3844
|
-
reject(error);
|
|
3845
|
-
return;
|
|
3846
|
-
}
|
|
3847
|
-
resolve(entries);
|
|
3848
|
-
});
|
|
3849
|
-
});
|
|
3850
|
-
}
|
|
3851
|
-
async function inspectSolutionPackageProjectTypes(packagePath) {
|
|
3852
|
-
const fs = getFileSystem();
|
|
3853
|
-
const [statError, stats] = await catchError(fs.stat(packagePath));
|
|
3854
|
-
if (statError || !stats) {
|
|
3855
|
-
logger.debug(`[Cli.ShipSucceeded] Could not stat solution package for project type telemetry: ${statError?.message ?? "no stats"}`);
|
|
3856
|
-
return { projectType: "unknown" };
|
|
3857
|
-
}
|
|
3858
|
-
if (stats.size > MAX_INSPECTABLE_PACKAGE_BYTES) {
|
|
3859
|
-
logger.debug(`[Cli.ShipSucceeded] Solution package is ${stats.size} bytes, over the ${MAX_INSPECTABLE_PACKAGE_BYTES}-byte inspection cap; skipping project type telemetry.`);
|
|
3860
|
-
return { projectType: "unknown" };
|
|
3861
|
-
}
|
|
3862
|
-
const [readError, archive] = await catchError(fs.readFile(packagePath));
|
|
3863
|
-
if (readError || !archive) {
|
|
3864
|
-
logger.debug(`[Cli.ShipSucceeded] Could not read solution package for project type telemetry: ${readError?.message ?? "empty archive"}`);
|
|
3865
|
-
return { projectType: "unknown" };
|
|
3866
|
-
}
|
|
3867
|
-
const [unzipError, entries] = await catchError(unzipProjectManifests(new Uint8Array(archive)));
|
|
3868
|
-
if (unzipError || !entries) {
|
|
3869
|
-
logger.debug(`[Cli.ShipSucceeded] Could not inspect solution package zip: ${unzipError?.message ?? "no entries"}`);
|
|
3870
|
-
return { projectType: "unknown" };
|
|
3871
|
-
}
|
|
3872
|
-
const decoder = new TextDecoder;
|
|
3873
|
-
const projectTypes = [];
|
|
3874
|
-
for (const [entryName, entryBytes] of Object.entries(entries)) {
|
|
3875
|
-
if (!isProjectManifestEntry(entryName)) {
|
|
3876
|
-
continue;
|
|
3877
|
-
}
|
|
3878
|
-
const [parseError, parsedTypes] = await catchError(Promise.resolve().then(() => readProjectTypesFromUipx(decoder.decode(entryBytes))));
|
|
3879
|
-
if (parseError) {
|
|
3880
|
-
logger.debug(`[Cli.ShipSucceeded] Could not parse ${entryName} for project type telemetry: ${parseError.message}`);
|
|
3881
|
-
continue;
|
|
3882
|
-
}
|
|
3883
|
-
projectTypes.push(...parsedTypes);
|
|
3884
|
-
}
|
|
3885
|
-
return summarizeShipProjectTypes(projectTypes);
|
|
3886
|
-
}
|
|
3887
|
-
function trackSolutionShipSucceeded(payload) {
|
|
3888
|
-
const { projectTypeSummary, ...rest } = payload;
|
|
3889
|
-
return trackShipSucceeded({
|
|
3890
|
-
...rest,
|
|
3891
|
-
[ShipDimensions.ProjectType]: projectTypeSummary.projectType,
|
|
3892
|
-
[ShipDimensions.ProjectTypes]: projectTypeSummary.projectTypes
|
|
3893
|
-
});
|
|
3894
|
-
}
|
|
3895
|
-
|
|
3896
3625
|
// src/commands/publish.ts
|
|
3897
3626
|
var PUBLISHED_STATUS = "Package is published to Orchestrator but not yet deployed";
|
|
3898
3627
|
var NEXT_STEPS_MESSAGE = "Package is published to Orchestrator but not yet deployed. " + "Deploy/activate it into an Orchestrator folder before it appears in the " + "processes list or can be started as a job.";
|
|
@@ -3987,7 +3716,7 @@ var EXIT_CODES_BY_REASON = {
|
|
|
3987
3716
|
poll_timeout: 2
|
|
3988
3717
|
};
|
|
3989
3718
|
var registerPublishCommand = (program) => {
|
|
3990
|
-
const command = program.command("publish").description("Publish a solution package (.zip) to the UiPath solution feed. The .zip must be produced by 'solution pack'. By default the package lands in the tenant feed; use --personal-workspace to target the current user's Personal Workspace feed. After publishing, use 'solution deploy run' to deploy it.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).argument("<
|
|
3719
|
+
const command = program.command("publish").description("Publish a solution package (.zip) to the UiPath solution feed. The .zip must be produced by 'solution pack'. By default the package lands in the tenant feed; use --personal-workspace to target the current user's Personal Workspace feed. After publishing, use 'solution deploy run' to deploy it.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).argument("<package-path>", "Path to a .zip package file produced by 'solution pack'.").option("--personal-workspace", "Upload the package into the current user's Personal Workspace feed instead of the tenant feed. Resolves the workspace folder key from Orchestrator automatically.").option("--package-name <name>", "Publish under this package name instead of the one the .zip was packed with. Rewrites the archive's solutionMetadata.json in memory (with a fresh package version key); the file on disk is left untouched. The bundled project packages keep their own names and versions.").option("--package-version <version>", "Publish under this package version instead of the one the .zip was packed with. Use it to clear a 'version already exists' rejection when you have the packed .zip but not the solution source. Same in-memory rewrite as --package-name.").option("--wait", "Wait until the published package is Ready or Active").option("--timeout <seconds>", "Timeout in seconds for package state polling (default: 360)", (v) => parseInt(v, 10), 360).option("--poll-interval <ms>", "Milliseconds between package state polls (default: 5000)", (v) => parseInt(v, 10), 5000).option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10);
|
|
3991
3720
|
command.addOption(new Option("--feed <name-or-key>", "Publish into a feed by its name or folder key (from 'solution feeds list') instead of the tenant feed. Mutually exclusive with --personal-workspace.").conflicts("personalWorkspace"));
|
|
3992
3721
|
command.examples([...SOLUTION_PUBLISH_EXAMPLES, SOLUTION_PUBLISH_FEED_EXAMPLE]).trackedAction(processContext, async (packagePath, options) => {
|
|
3993
3722
|
const result = await publishSolutionAsync(packagePath, {
|
|
@@ -4050,6 +3779,7 @@ var registerPublishCommand = (program) => {
|
|
|
4050
3779
|
});
|
|
4051
3780
|
});
|
|
4052
3781
|
};
|
|
3782
|
+
|
|
4053
3783
|
// src/commands/resource-add.ts
|
|
4054
3784
|
var RESOURCE_ADD_EXAMPLES = [
|
|
4055
3785
|
{
|
|
@@ -4089,7 +3819,14 @@ var RESOURCE_ADD_EXAMPLES = [
|
|
|
4089
3819
|
];
|
|
4090
3820
|
var registerResourceAddCommand = (resource) => {
|
|
4091
3821
|
resource.command("add").description("Add a resource to the solution. Use --source local to create a virtual stub, " + "or --source remote to import an existing Orchestrator resource. Idempotent: " + "if a resource with the same (kind, name, folder) already exists, it is returned unchanged.").option("--source <source>", "Resource source: local (virtual stub) or remote (import from Orchestrator)").option("--kind <kind>", "Resource kind (e.g. Queue, Asset, Bucket, Process, Connection, App, Index, Trigger, Entity, ChoiceSet). Case-insensitive, matched against SDK metadata.").option("--name <name>", "Resource name").option("--type <type>", "Resource subtype, case-insensitive (e.g. Text/Integer/Bool/Credential/Secret or stringAsset/credentialAsset for Asset, connector type for Connection). Rejected when the kind does not declare it or has no subtypes (Queue); with --source remote it must match the resource's type and narrows same-name matches.").option("--folder-path <path>", "Orchestrator folder path for remote lookup. Required to disambiguate when more than one remote match exists. Not valid with --source local.").option("--cloud-key <guid>", "Skip remote search and import this exact resource key. Only valid with --source remote.").option("--solution-folder <path>", "Path to the solution root folder (defaults to current directory)").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).examples(RESOURCE_ADD_EXAMPLES).trackedAction(processContext, async (options) => {
|
|
4092
|
-
const
|
|
3822
|
+
const {
|
|
3823
|
+
assertSolutionManifest,
|
|
3824
|
+
createResourceBuilderServices,
|
|
3825
|
+
normalizeResourceFileCasing,
|
|
3826
|
+
saveCasingNormalized
|
|
3827
|
+
} = await import("./index-prm27bvm.js");
|
|
3828
|
+
const { getSolutionAuthContext: getSolutionAuthContext2 } = await import("./solution-auth-aead70sw.js");
|
|
3829
|
+
const validation = await validateOptions(options);
|
|
4093
3830
|
if (!validation.ok) {
|
|
4094
3831
|
OutputFormatter.error({
|
|
4095
3832
|
Result: RESULTS.Failure,
|
|
@@ -4122,7 +3859,7 @@ var registerResourceAddCommand = (resource) => {
|
|
|
4122
3859
|
return;
|
|
4123
3860
|
}
|
|
4124
3861
|
if (source === "remote") {
|
|
4125
|
-
const [authError] = await catchError(
|
|
3862
|
+
const [authError] = await catchError(getSolutionAuthContext2({
|
|
4126
3863
|
loginValidity: options.loginValidity
|
|
4127
3864
|
}));
|
|
4128
3865
|
if (authError) {
|
|
@@ -4217,7 +3954,8 @@ function canonicalizeKind(kind) {
|
|
|
4217
3954
|
return trimmed.charAt(0).toLowerCase() + trimmed.slice(1);
|
|
4218
3955
|
}
|
|
4219
3956
|
var GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4220
|
-
function validateOptions(options) {
|
|
3957
|
+
async function validateOptions(options) {
|
|
3958
|
+
const { validateResourceName } = await import("./index-prm27bvm.js");
|
|
4221
3959
|
if (!options.source) {
|
|
4222
3960
|
return {
|
|
4223
3961
|
ok: false,
|
|
@@ -4291,6 +4029,7 @@ function validateOptions(options) {
|
|
|
4291
4029
|
async function resolveTypeInput(services, kind, type) {
|
|
4292
4030
|
if (type === undefined)
|
|
4293
4031
|
return { ok: true, type };
|
|
4032
|
+
const { formatResourceSubtypes, resolveResourceKindMetadata } = await import("./resource-mutations-c3krjqze.js");
|
|
4294
4033
|
const metadata = await resolveResourceKindMetadata(services, kind, type);
|
|
4295
4034
|
if (metadata?.typeMatched) {
|
|
4296
4035
|
return { ok: true, type: metadata.type ?? type };
|
|
@@ -4320,6 +4059,13 @@ function formatCandidates(matches) {
|
|
|
4320
4059
|
`);
|
|
4321
4060
|
}
|
|
4322
4061
|
async function runAdd(builder, services, rawInput) {
|
|
4062
|
+
const { findMatchingLocalResource } = await import("./index-prm27bvm.js");
|
|
4063
|
+
const {
|
|
4064
|
+
createLocalResource,
|
|
4065
|
+
findResourceByKeyInRcs,
|
|
4066
|
+
sameResourceSubtype,
|
|
4067
|
+
searchRcsResources
|
|
4068
|
+
} = await import("./resource-mutations-c3krjqze.js");
|
|
4323
4069
|
const typeResolution = await resolveTypeInput(services, rawInput.kind, rawInput.type);
|
|
4324
4070
|
if (!typeResolution.ok)
|
|
4325
4071
|
return typeResolution.outcome;
|
|
@@ -4381,7 +4127,7 @@ async function runAdd(builder, services, rawInput) {
|
|
|
4381
4127
|
instructions: searchError.message
|
|
4382
4128
|
};
|
|
4383
4129
|
}
|
|
4384
|
-
const inFolder = filterMatchesByFolder(matches, input.folderPath);
|
|
4130
|
+
const inFolder = await filterMatchesByFolder(matches, input.folderPath);
|
|
4385
4131
|
if (inFolder.length === 0) {
|
|
4386
4132
|
return {
|
|
4387
4133
|
kind: "error",
|
|
@@ -4478,7 +4224,8 @@ ${formatCandidates(filtered)}`
|
|
|
4478
4224
|
data: toResourceAddData(imported, refreshed.folders, "remote", statusToOutputStatus(response.status))
|
|
4479
4225
|
};
|
|
4480
4226
|
}
|
|
4481
|
-
function filterMatchesByFolder(matches, folderPath) {
|
|
4227
|
+
async function filterMatchesByFolder(matches, folderPath) {
|
|
4228
|
+
const { normalizeFolderPath } = await import("./index-prm27bvm.js");
|
|
4482
4229
|
const normalized = normalizeFolderPath(folderPath);
|
|
4483
4230
|
if (!normalized)
|
|
4484
4231
|
return matches;
|
|
@@ -4506,8 +4253,31 @@ function toResourceAddData(resource, folders, source, status) {
|
|
|
4506
4253
|
};
|
|
4507
4254
|
}
|
|
4508
4255
|
|
|
4509
|
-
// src/commands/resource-
|
|
4256
|
+
// src/commands/resource-command-utils.ts
|
|
4510
4257
|
var RESOURCE_KEY_REGEX = /^[A-Za-z0-9._:-]{1,256}$/;
|
|
4258
|
+
function validateResourceKeyArgument(resourceKey) {
|
|
4259
|
+
if (!resourceKey || resourceKey.trim().length === 0) {
|
|
4260
|
+
OutputFormatter.error({
|
|
4261
|
+
Result: RESULTS.Failure,
|
|
4262
|
+
Message: "Missing required argument <resource-key>",
|
|
4263
|
+
Instructions: "Pass the solution resource key as a positional argument. Use 'uip solution resources list' to discover keys."
|
|
4264
|
+
});
|
|
4265
|
+
processContext.exit(1);
|
|
4266
|
+
return false;
|
|
4267
|
+
}
|
|
4268
|
+
if (!RESOURCE_KEY_REGEX.test(resourceKey)) {
|
|
4269
|
+
OutputFormatter.error({
|
|
4270
|
+
Result: RESULTS.Failure,
|
|
4271
|
+
Message: "<resource-key> contains unsupported characters",
|
|
4272
|
+
Instructions: "Resource keys use letters, digits, and '. _ - :' only. Use 'uip solution resources list' to find a valid key."
|
|
4273
|
+
});
|
|
4274
|
+
processContext.exit(1);
|
|
4275
|
+
return false;
|
|
4276
|
+
}
|
|
4277
|
+
return true;
|
|
4278
|
+
}
|
|
4279
|
+
|
|
4280
|
+
// src/commands/resource-edit.ts
|
|
4511
4281
|
var REMOTE_FAILURE_MESSAGE = {
|
|
4512
4282
|
solution_not_found: "Failed to edit resource",
|
|
4513
4283
|
not_a_solution: "Failed to edit resource",
|
|
@@ -4600,24 +4370,15 @@ var RESOURCE_EDIT_EXAMPLES = [
|
|
|
4600
4370
|
];
|
|
4601
4371
|
var registerResourceEditCommand = (resource) => {
|
|
4602
4372
|
resource.command("edit").description("Edit a resource's spec properties by key. Pass --patch with a JSON object " + "of property → value; the JSON is merged into the existing spec. Properties " + "the SDK metadata marks as reference/read-only/unknown are silently ignored. " + "Use 'uip solution resources get <key>' to inspect the current spec; the " + "get↔edit shapes match, so a round-trip is straightforward. " + "Pass --source remote instead of --patch to take the values from the cloud " + "definition the resource was imported from — the only way to pick up a change " + "made in Orchestrator or Data Fabric after the import, since 'resources refresh' " + "never overwrites an imported resource.").argument("<resource-key>", "Solution resource key (a GUID, or a compound key such as MyFunction.api.MyFunction.1:1.0.0)").option("--patch <json>", `JSON object of spec property → value (e.g. '{"retentionPeriod":14}'). Pass '-' to read the JSON from stdin.`).option("--source <source>", "Where the new values come from: 'local' (default, use --patch) or 'remote' (the cloud definition this resource was imported from)", "local").option("--force", "With --source remote, write the cloud definition over the local one. Without it the command only reports what would change and writes nothing.").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10). Only used by --source remote.", "10").option("--solution-folder <path>", "Path to the solution root folder (defaults to current directory)").examples(RESOURCE_EDIT_EXAMPLES).trackedAction(processContext, async (resourceKey, options) => {
|
|
4603
|
-
if (!resourceKey
|
|
4604
|
-
OutputFormatter.error({
|
|
4605
|
-
Result: RESULTS.Failure,
|
|
4606
|
-
Message: "Missing required argument <resource-key>",
|
|
4607
|
-
Instructions: "Pass the solution resource key as a positional argument. Use 'uip solution resources list' to discover keys."
|
|
4608
|
-
});
|
|
4609
|
-
processContext.exit(1);
|
|
4610
|
-
return;
|
|
4611
|
-
}
|
|
4612
|
-
if (!RESOURCE_KEY_REGEX.test(resourceKey)) {
|
|
4613
|
-
OutputFormatter.error({
|
|
4614
|
-
Result: RESULTS.Failure,
|
|
4615
|
-
Message: "<resource-key> contains unsupported characters",
|
|
4616
|
-
Instructions: "Resource keys use letters, digits, and '. _ - :' only. Use 'uip solution resources list' to find a valid key."
|
|
4617
|
-
});
|
|
4618
|
-
processContext.exit(1);
|
|
4373
|
+
if (!validateResourceKeyArgument(resourceKey)) {
|
|
4619
4374
|
return;
|
|
4620
4375
|
}
|
|
4376
|
+
const {
|
|
4377
|
+
assertSolutionManifest,
|
|
4378
|
+
createResourceBuilderServices,
|
|
4379
|
+
normalizeResourceFileCasing,
|
|
4380
|
+
saveCasingNormalized
|
|
4381
|
+
} = await import("./index-prm27bvm.js");
|
|
4621
4382
|
const source = (options.source ?? "local").toLowerCase();
|
|
4622
4383
|
if (source !== "local" && source !== "remote") {
|
|
4623
4384
|
OutputFormatter.error({
|
|
@@ -4753,6 +4514,7 @@ var registerResourceEditCommand = (resource) => {
|
|
|
4753
4514
|
});
|
|
4754
4515
|
};
|
|
4755
4516
|
async function handleRemoteSourceAsync(resourceKey, options) {
|
|
4517
|
+
const { resourceRemoteSyncAsync } = await import("./index-prm27bvm.js");
|
|
4756
4518
|
const result = await resourceRemoteSyncAsync(options.solutionFolder ?? ".", resourceKey, {
|
|
4757
4519
|
force: options.force === true,
|
|
4758
4520
|
loginValidity: options.loginValidity ? parseInt(options.loginValidity, 10) : undefined
|
|
@@ -4833,7 +4595,6 @@ async function readStdin() {
|
|
|
4833
4595
|
}
|
|
4834
4596
|
|
|
4835
4597
|
// src/commands/resource-get.ts
|
|
4836
|
-
var NOT_FOUND_PATTERN2 = /not\s+found/i;
|
|
4837
4598
|
var RESOURCE_GET_EXAMPLES = [
|
|
4838
4599
|
{
|
|
4839
4600
|
Description: "Get the configuration for a single solution resource (run from inside the solution dir, or pass --solution-folder)",
|
|
@@ -4891,6 +4652,11 @@ var RESOURCE_GET_EXAMPLES = [
|
|
|
4891
4652
|
];
|
|
4892
4653
|
var registerResourceGetCommand = (resource) => {
|
|
4893
4654
|
resource.command("get").description("Get the configuration of a solution resource by key. Returns the resource spec, locks, and metadata as the SDK exposes them. " + "Use --include-dependencies to also retrieve configurations for every dependency the resource references.").argument("<resource-key>", "Solution resource key (GUID, or composite key like 'TestRPA.process.TestRPA:1.0.0' for packages)").option("--solution-folder <path>", "Path to the solution root folder (defaults to current directory)").option("--include-dependencies", "Also return configurations for the resource's dependencies").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", "10").examples(RESOURCE_GET_EXAMPLES).trackedAction(processContext, async (resourceKey, options) => {
|
|
4655
|
+
const {
|
|
4656
|
+
createResourceBuilderServices,
|
|
4657
|
+
readResourceConfigurationsAsync
|
|
4658
|
+
} = await import("./index-prm27bvm.js");
|
|
4659
|
+
const { getSolutionAuthContext: getSolutionAuthContext2 } = await import("./solution-auth-aead70sw.js");
|
|
4894
4660
|
const solutionPath = options.solutionFolder ?? ".";
|
|
4895
4661
|
if (!resourceKey || resourceKey.trim() === "") {
|
|
4896
4662
|
OutputFormatter.error({
|
|
@@ -4914,7 +4680,7 @@ var registerResourceGetCommand = (resource) => {
|
|
|
4914
4680
|
return;
|
|
4915
4681
|
}
|
|
4916
4682
|
const loginValidityMinutes = options.loginValidity ? parseInt(options.loginValidity, 10) : undefined;
|
|
4917
|
-
const [authError] = await catchError(
|
|
4683
|
+
const [authError] = await catchError(getSolutionAuthContext2({
|
|
4918
4684
|
loginValidity: loginValidityMinutes
|
|
4919
4685
|
}));
|
|
4920
4686
|
if (authError) {
|
|
@@ -4946,87 +4712,32 @@ var registerResourceGetCommand = (resource) => {
|
|
|
4946
4712
|
processContext.exit(1);
|
|
4947
4713
|
return;
|
|
4948
4714
|
}
|
|
4949
|
-
const
|
|
4950
|
-
|
|
4951
|
-
if (
|
|
4952
|
-
const resource2 = await refreshArtefactSpecAsync(builder, data, includeDeps);
|
|
4953
|
-
if (!includeDeps) {
|
|
4954
|
-
await attachLiveSpecOnMismatchAsync(services, resource2, data);
|
|
4955
|
-
}
|
|
4956
|
-
await builder.disposeAsync();
|
|
4957
|
-
OutputFormatter.success({
|
|
4958
|
-
Result: RESULTS.Success,
|
|
4959
|
-
Code: includeDeps ? "ResourceConfigurations" : "ResourceConfiguration",
|
|
4960
|
-
Data: data
|
|
4961
|
-
});
|
|
4962
|
-
return;
|
|
4963
|
-
}
|
|
4964
|
-
if (NOT_FOUND_PATTERN2.test(fetchError.message)) {
|
|
4965
|
-
const [remoteError, remoteData] = await catchError(getRemoteConfiguration(services, resourceKey, includeDeps));
|
|
4966
|
-
await builder.disposeAsync();
|
|
4967
|
-
if (!remoteError) {
|
|
4968
|
-
OutputFormatter.success({
|
|
4969
|
-
Result: RESULTS.Success,
|
|
4970
|
-
Code: includeDeps ? "ResourceConfigurations" : "ResourceConfiguration",
|
|
4971
|
-
Data: remoteData
|
|
4972
|
-
});
|
|
4973
|
-
return;
|
|
4974
|
-
}
|
|
4715
|
+
const [fetchError, data] = await catchError(options.includeDependencies === true ? readResourceConfigurationsAsync(services, builder, resourceKey) : readWithLiveSpecAsync(services, builder, resourceKey));
|
|
4716
|
+
await builder.disposeAsync();
|
|
4717
|
+
if (fetchError) {
|
|
4975
4718
|
OutputFormatter.error({
|
|
4976
4719
|
Result: RESULTS.Failure,
|
|
4977
4720
|
Message: "Failed to get resource configuration",
|
|
4978
|
-
Instructions: await extractErrorMessage(
|
|
4721
|
+
Instructions: await extractErrorMessage(fetchError)
|
|
4979
4722
|
});
|
|
4980
4723
|
processContext.exit(1);
|
|
4981
4724
|
return;
|
|
4982
4725
|
}
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
Instructions: await extractErrorMessage(fetchError)
|
|
4726
|
+
OutputFormatter.success({
|
|
4727
|
+
Result: RESULTS.Success,
|
|
4728
|
+
Code: options.includeDependencies === true ? "ResourceConfigurations" : "ResourceConfiguration",
|
|
4729
|
+
Data: data
|
|
4988
4730
|
});
|
|
4989
|
-
processContext.exit(1);
|
|
4990
4731
|
});
|
|
4991
4732
|
};
|
|
4992
|
-
async function
|
|
4993
|
-
const
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
const { importer } = getRemoteResourceClients(services);
|
|
4998
|
-
const payload = await importer.exportResourceAsync(reference);
|
|
4999
|
-
const definitions = payload.resourceDefinitions ?? [];
|
|
5000
|
-
const primary = definitions.find((d) => d.key === resourceKey) ?? definitions[0];
|
|
5001
|
-
if (!primary) {
|
|
5002
|
-
throw new Error(`FPS export for '${resourceKey}' returned no resource definitions`);
|
|
5003
|
-
}
|
|
5004
|
-
if (!includeDependencies) {
|
|
5005
|
-
return mapDefinitionToConfiguration(primary);
|
|
5006
|
-
}
|
|
5007
|
-
const all = {
|
|
5008
|
-
resources: definitions.map((d) => ({
|
|
5009
|
-
...mapDefinitionToConfiguration(d),
|
|
5010
|
-
name: d.name ?? "",
|
|
5011
|
-
kind: d.kind ?? "",
|
|
5012
|
-
dependencies: (d.dependencies ?? []).map((dep) => ({
|
|
5013
|
-
kind: dep.kind ?? "",
|
|
5014
|
-
name: dep.name ?? ""
|
|
5015
|
-
}))
|
|
5016
|
-
}))
|
|
5017
|
-
};
|
|
5018
|
-
return all;
|
|
5019
|
-
}
|
|
5020
|
-
function mapDefinitionToConfiguration(def) {
|
|
5021
|
-
return {
|
|
5022
|
-
key: def.key ?? "",
|
|
5023
|
-
spec: def.spec ?? {},
|
|
5024
|
-
locks: def.locks ?? [],
|
|
5025
|
-
apiVersion: def.apiVersion,
|
|
5026
|
-
isOverridable: def.isOverridable
|
|
5027
|
-
};
|
|
4733
|
+
async function readWithLiveSpecAsync(services, builder, resourceKey) {
|
|
4734
|
+
const { readResourceConfigurationAsync } = await import("./index-prm27bvm.js");
|
|
4735
|
+
const { configuration, resource } = await readResourceConfigurationAsync(services, builder, resourceKey);
|
|
4736
|
+
await attachLiveSpecOnMismatchAsync(services, resource, configuration);
|
|
4737
|
+
return configuration;
|
|
5028
4738
|
}
|
|
5029
4739
|
async function attachLiveSpecOnMismatchAsync(services, resource, config) {
|
|
4740
|
+
const { getRemoteResourceClients } = await import("./index-prm27bvm.js");
|
|
5030
4741
|
const overwriteData = config.resourceOverwrite;
|
|
5031
4742
|
const overwrite = overwriteData?.resourceOverwrite?.overwrite;
|
|
5032
4743
|
if (overwriteData?.matchingOverwriteConfiguration !== false || !overwrite || !resource) {
|
|
@@ -5039,104 +4750,6 @@ async function attachLiveSpecOnMismatchAsync(services, resource, config) {
|
|
|
5039
4750
|
}
|
|
5040
4751
|
config.liveSpec = exported.spec;
|
|
5041
4752
|
}
|
|
5042
|
-
async function refreshArtefactSpecAsync(builder, data, includeDeps) {
|
|
5043
|
-
const [loadError, solution] = await catchError(builder.context.loadAsync());
|
|
5044
|
-
if (loadError || !solution) {
|
|
5045
|
-
return;
|
|
5046
|
-
}
|
|
5047
|
-
let requestedResource;
|
|
5048
|
-
const configs = includeDeps ? data.resources ?? [] : [data];
|
|
5049
|
-
for (const config of configs) {
|
|
5050
|
-
if (!config?.key) {
|
|
5051
|
-
continue;
|
|
5052
|
-
}
|
|
5053
|
-
const resource = solution.resources.find((r) => r.key === config.key);
|
|
5054
|
-
if (!includeDeps) {
|
|
5055
|
-
requestedResource = resource;
|
|
5056
|
-
}
|
|
5057
|
-
if (!resource?.projectKey) {
|
|
5058
|
-
continue;
|
|
5059
|
-
}
|
|
5060
|
-
config.spec = await applyEntryPointEnhancementAsync(builder.context, resource, config.spec ?? {});
|
|
5061
|
-
}
|
|
5062
|
-
return requestedResource;
|
|
5063
|
-
}
|
|
5064
|
-
async function findRemoteReferenceByKey(services, resourceKey) {
|
|
5065
|
-
const entity = await findCatalogEntityAsync(getRemoteResourceClients(services).catalog, {}, (item) => item.entityKey === resourceKey);
|
|
5066
|
-
return entity ? toResourceReference(entity) : null;
|
|
5067
|
-
}
|
|
5068
|
-
|
|
5069
|
-
// src/services/resource-version-lookup.ts
|
|
5070
|
-
var VERSION_PROPERTY = "version";
|
|
5071
|
-
var LOOKUP_CONCURRENCY = 5;
|
|
5072
|
-
async function resolveResourceVersionsAsync(services, builder, targets) {
|
|
5073
|
-
const versions = new Map;
|
|
5074
|
-
if (targets.length === 0) {
|
|
5075
|
-
return versions;
|
|
5076
|
-
}
|
|
5077
|
-
const resolveKind = await createResourceKindMetadataResolver(services);
|
|
5078
|
-
const versioned = [];
|
|
5079
|
-
for (const target of targets) {
|
|
5080
|
-
const metadata = await resolveKind(target.kind, target.type);
|
|
5081
|
-
if (metadata?.specProperties.has(VERSION_PROPERTY)) {
|
|
5082
|
-
versioned.push(target);
|
|
5083
|
-
}
|
|
5084
|
-
}
|
|
5085
|
-
if (versioned.length === 0) {
|
|
5086
|
-
return versions;
|
|
5087
|
-
}
|
|
5088
|
-
const { importer } = getRemoteResourceClients(services);
|
|
5089
|
-
for (let i = 0;i < versioned.length; i += LOOKUP_CONCURRENCY) {
|
|
5090
|
-
const batch = versioned.slice(i, i + LOOKUP_CONCURRENCY);
|
|
5091
|
-
const resolved = await Promise.all(batch.map((target) => target.source === "Local" ? readLocalVersionAsync(builder, target) : readRemoteVersionAsync(importer, target)));
|
|
5092
|
-
for (const [id, version] of resolved) {
|
|
5093
|
-
if (version !== undefined) {
|
|
5094
|
-
versions.set(id, version);
|
|
5095
|
-
}
|
|
5096
|
-
}
|
|
5097
|
-
}
|
|
5098
|
-
return versions;
|
|
5099
|
-
}
|
|
5100
|
-
async function readLocalVersionAsync(builder, target) {
|
|
5101
|
-
const [error, configuration] = await catchError(builder.getConfigurationAsync(target.key));
|
|
5102
|
-
if (error || !configuration) {
|
|
5103
|
-
warnLookupFailed(target, error);
|
|
5104
|
-
return [target.id, undefined];
|
|
5105
|
-
}
|
|
5106
|
-
return [target.id, readVersion(configuration.spec)];
|
|
5107
|
-
}
|
|
5108
|
-
async function readRemoteVersionAsync(importer, target) {
|
|
5109
|
-
const reference = {
|
|
5110
|
-
kind: target.kind,
|
|
5111
|
-
type: target.type,
|
|
5112
|
-
key: target.key,
|
|
5113
|
-
name: target.name,
|
|
5114
|
-
folder: target.folderFullyQualifiedName ? {
|
|
5115
|
-
fullyQualifiedName: target.folderFullyQualifiedName,
|
|
5116
|
-
folderKey: target.folderKey
|
|
5117
|
-
} : undefined
|
|
5118
|
-
};
|
|
5119
|
-
const [error, primary] = await catchError(exportResourceDefinitionAsync(importer, reference));
|
|
5120
|
-
if (error) {
|
|
5121
|
-
warnLookupFailed(target, error);
|
|
5122
|
-
return [target.id, undefined];
|
|
5123
|
-
}
|
|
5124
|
-
if (!primary) {
|
|
5125
|
-
logger.warn(`Export for ${target.kind} '${target.name ?? target.key}' returned no definition for that key; version omitted.`);
|
|
5126
|
-
return [target.id, undefined];
|
|
5127
|
-
}
|
|
5128
|
-
return [target.id, readVersion(primary.spec)];
|
|
5129
|
-
}
|
|
5130
|
-
function readVersion(spec) {
|
|
5131
|
-
const value = readSpecProperty(spec, VERSION_PROPERTY);
|
|
5132
|
-
if (value === undefined || value === null || value === "") {
|
|
5133
|
-
return;
|
|
5134
|
-
}
|
|
5135
|
-
return typeof value === "string" ? value : String(value);
|
|
5136
|
-
}
|
|
5137
|
-
function warnLookupFailed(target, error) {
|
|
5138
|
-
logger.warn(`Failed to read the version of ${target.kind} '${target.name ?? target.key}': ${error?.message ?? "no configuration returned"}`);
|
|
5139
|
-
}
|
|
5140
4753
|
|
|
5141
4754
|
// src/commands/resource-list.ts
|
|
5142
4755
|
var RESOURCE_LIST_EXAMPLES = [
|
|
@@ -5177,6 +4790,8 @@ var RESOURCE_LIST_EXAMPLES = [
|
|
|
5177
4790
|
];
|
|
5178
4791
|
var registerResourceListCommand = (resource) => {
|
|
5179
4792
|
resource.command("list").description("List resources in the solution and/or available in Orchestrator. " + "Shows local solution resources, remote Orchestrator resources, or both.").option("--solution-folder <path>", "Path to the solution root folder (defaults to current directory)").option("--kind <kind>", "Filter by resource kind (e.g. Queue, Asset, Bucket, Process, Connection, App, Index, Trigger, Entity, ChoiceSet). Any kind RCS indexes is accepted.").option("--search <term>", "Filter resources by name").option("--source <source>", "Resource source: all, local, or remote (default: all)", "all").option("--include-version", "Also report each resource's version, for the kinds that carry one (app, appVersion, package, process). " + "Remote rows report the version live in the folder, local rows the version the solution pins. " + "Costs one extra call per resource, so it is off by default.").option("-l, --limit <number>", "Number of resources to return", parseLimit, DEFAULT_PAGE_SIZE).option("--offset <number>", "Only 0 is accepted: the resource catalog pages by cursor. Use --next-page instead", parseOffset).option("--next-page <cursor>", "Cursor from a previous response's Pagination.NextPage").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).examples(RESOURCE_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
|
|
4793
|
+
const { createResourceBuilderServices } = await import("./index-prm27bvm.js");
|
|
4794
|
+
const { getSolutionAuthContext: getSolutionAuthContext2 } = await import("./solution-auth-aead70sw.js");
|
|
5180
4795
|
const solutionPath = options.solutionFolder ?? ".";
|
|
5181
4796
|
const fs = getFileSystem();
|
|
5182
4797
|
const resolvedPath = fs.path.resolve(fs.env.cwd(), solutionPath);
|
|
@@ -5205,7 +4820,7 @@ var registerResourceListCommand = (resource) => {
|
|
|
5205
4820
|
return;
|
|
5206
4821
|
}
|
|
5207
4822
|
const normalizedKind = options.kind;
|
|
5208
|
-
const [authError] = await catchError(
|
|
4823
|
+
const [authError] = await catchError(getSolutionAuthContext2({
|
|
5209
4824
|
loginValidity: options.loginValidity
|
|
5210
4825
|
}));
|
|
5211
4826
|
if (authError) {
|
|
@@ -5353,6 +4968,7 @@ function versionLookupId(entry) {
|
|
|
5353
4968
|
return `${entry.Source}|${entry.Key}|${entry.Folder ?? ""}`;
|
|
5354
4969
|
}
|
|
5355
4970
|
async function annotateVersions(services, builder, entries) {
|
|
4971
|
+
const { resolveResourceVersionsAsync } = await import("./resource-version-lookup-0e3e2j58.js");
|
|
5356
4972
|
const targets = new Map;
|
|
5357
4973
|
for (const entry of entries) {
|
|
5358
4974
|
if (entry.Key === "") {
|
|
@@ -5384,6 +5000,7 @@ async function annotateVersions(services, builder, entries) {
|
|
|
5384
5000
|
}
|
|
5385
5001
|
}
|
|
5386
5002
|
async function allRemotePage(services, search, pageCursor) {
|
|
5003
|
+
const { getRemoteResourceClients } = await import("./index-prm27bvm.js");
|
|
5387
5004
|
const rcs = getRemoteResourceClients(services).catalog;
|
|
5388
5005
|
const result = await rcs.searchFolderEntities({
|
|
5389
5006
|
name: search,
|
|
@@ -5450,9 +5067,10 @@ var RESOURCE_REFRESH_EXAMPLES = [
|
|
|
5450
5067
|
Imported: 1,
|
|
5451
5068
|
Skipped: 5,
|
|
5452
5069
|
Pruned: 0,
|
|
5070
|
+
ProjectResourcesCreated: 2,
|
|
5453
5071
|
ReconciledSpecs: 1,
|
|
5454
5072
|
Warnings: [],
|
|
5455
|
-
Status: "Synced 3 resources (5 already in solution). Refresh never overwrites an imported resource — to pull a changed cloud definition, run 'uip solution resources edit <resource-key> --source remote'."
|
|
5073
|
+
Status: "Synced 3 resources (5 already in solution, 2 project resources generated). Refresh never overwrites an imported resource — to pull a changed cloud definition, run 'uip solution resources edit <resource-key> --source remote'."
|
|
5456
5074
|
}
|
|
5457
5075
|
}
|
|
5458
5076
|
}
|
|
@@ -5465,31 +5083,39 @@ var FAILURE_MESSAGE = {
|
|
|
5465
5083
|
};
|
|
5466
5084
|
var registerResourceRefreshSubcommand = (resource) => {
|
|
5467
5085
|
resource.command("refresh").description("Re-scan all projects in the solution and sync each project's authored files into the solution resource JSONs. " + "Bindings: creates new resources for `bindings_v2.json` entries not yet in the solution, imports from Orchestrator when a matching resource exists, and removes duplicate copies of the solution's own projects that earlier runs imported from a deployed folder. " + "Project contributions: each project's owning tool reports what its authored files add to the solution resources, and refresh persists it onto the matching resource. " + "Run this after editing a project's bindings or any file the project's tool contributes from, to update the solution resource inventory. " + "Refresh is import-only for cloud resources: it never overwrites an imported resource, so local edits survive; a project's own artefact resources are rewritten from the project's files on every run. " + "To pull a cloud definition that changed after the import, use 'uip solution resources edit <resource-key> --source remote'.").option("--solution-folder <path>", "Path to the solution root folder (defaults to current directory)").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", "10").examples(RESOURCE_REFRESH_EXAMPLES).trackedAction(processContext, async (options) => {
|
|
5086
|
+
const { resourceRefreshAsync } = await import("./index-prm27bvm.js");
|
|
5468
5087
|
const loginValidityMinutes = options.loginValidity ? parseInt(options.loginValidity, 10) : undefined;
|
|
5469
5088
|
const solutionFolder = options.solutionFolder ?? ".";
|
|
5470
5089
|
const fs = getFileSystem();
|
|
5471
5090
|
let contributions;
|
|
5472
5091
|
const [
|
|
5473
|
-
{ ensurePackagerTools
|
|
5474
|
-
{ projectSubTypesFrom },
|
|
5092
|
+
{ ensurePackagerTools },
|
|
5093
|
+
{ projectBindingsFrom, projectSubTypesFrom },
|
|
5475
5094
|
{
|
|
5476
5095
|
applyProjectContributions,
|
|
5477
5096
|
collectProjectContributions,
|
|
5478
5097
|
contributionErrorMessages
|
|
5479
5098
|
}
|
|
5480
5099
|
] = await Promise.all([
|
|
5481
|
-
import("./packager-tool-resolver-
|
|
5482
|
-
import("./prepare-solution-resources-
|
|
5483
|
-
import("./project-contributions-
|
|
5100
|
+
import("./packager-tool-resolver-994z3jkj.js"),
|
|
5101
|
+
import("./prepare-solution-resources-m1djfj62.js"),
|
|
5102
|
+
import("./project-contributions-79ndycrx.js")
|
|
5484
5103
|
]);
|
|
5485
5104
|
const resolveProjectSubTypesAsync = async () => {
|
|
5486
|
-
await
|
|
5105
|
+
await ensurePackagerTools(solutionFolder, fs);
|
|
5487
5106
|
contributions = await collectProjectContributions(solutionFolder, fs);
|
|
5488
5107
|
return projectSubTypesFrom(contributions);
|
|
5489
5108
|
};
|
|
5109
|
+
const resolveProjectBindingsAsync = async () => {
|
|
5110
|
+
if (!contributions) {
|
|
5111
|
+
throw new Error("the project tools could not be loaded");
|
|
5112
|
+
}
|
|
5113
|
+
return projectBindingsFrom(contributions);
|
|
5114
|
+
};
|
|
5490
5115
|
const result = await resourceRefreshAsync(solutionFolder, {
|
|
5491
5116
|
loginValidity: loginValidityMinutes,
|
|
5492
|
-
resolveProjectSubTypesAsync
|
|
5117
|
+
resolveProjectSubTypesAsync,
|
|
5118
|
+
resolveProjectBindingsAsync
|
|
5493
5119
|
});
|
|
5494
5120
|
if (!result.ok) {
|
|
5495
5121
|
OutputFormatter.error({
|
|
@@ -5501,6 +5127,7 @@ var registerResourceRefreshSubcommand = (resource) => {
|
|
|
5501
5127
|
return;
|
|
5502
5128
|
}
|
|
5503
5129
|
const prunedNote = result.pruned > 0 ? `, ${result.pruned} duplicates removed` : "";
|
|
5130
|
+
const projectNote = result.projectResourcesCreated > 0 ? `, ${result.projectResourcesCreated} project resources generated` : "";
|
|
5504
5131
|
const skippedNote = result.skipped > 0 ? " Refresh never overwrites an imported resource — to pull a changed cloud definition, run 'uip solution resources edit <resource-key> --source remote'." : "";
|
|
5505
5132
|
let applied = { updated: 0, warnings: [] };
|
|
5506
5133
|
if (contributions) {
|
|
@@ -5529,16 +5156,16 @@ var registerResourceRefreshSubcommand = (resource) => {
|
|
|
5529
5156
|
Imported: result.imported,
|
|
5530
5157
|
Skipped: result.skipped,
|
|
5531
5158
|
Pruned: result.pruned,
|
|
5159
|
+
ProjectResourcesCreated: result.projectResourcesCreated,
|
|
5532
5160
|
ReconciledSpecs: applied.updated,
|
|
5533
5161
|
Warnings: warnings,
|
|
5534
|
-
Status: `Synced ${result.created + result.imported} resources (${result.skipped} already in solution${prunedNote}).${skippedNote}`
|
|
5162
|
+
Status: `Synced ${result.created + result.imported} resources (${result.skipped} already in solution${prunedNote}${projectNote}).${skippedNote}`
|
|
5535
5163
|
}
|
|
5536
5164
|
});
|
|
5537
5165
|
});
|
|
5538
5166
|
};
|
|
5539
5167
|
|
|
5540
5168
|
// src/commands/resource-remove.ts
|
|
5541
|
-
var RESOURCE_KEY_REGEX2 = /^[A-Za-z0-9._:-]{1,256}$/;
|
|
5542
5169
|
var RESOURCE_REMOVE_EXAMPLES = [
|
|
5543
5170
|
{
|
|
5544
5171
|
Description: "Remove a resource by its solution key",
|
|
@@ -5556,24 +5183,15 @@ var RESOURCE_REMOVE_EXAMPLES = [
|
|
|
5556
5183
|
];
|
|
5557
5184
|
var registerResourceRemoveCommand = (resource) => {
|
|
5558
5185
|
resource.command("remove").description("Remove a resource from the solution by its key. Use 'uip solution resources list' " + "or 'uip solution resources get' to discover the key first. " + "Purely local — no auth required, doesn't touch any bindings_v2.json.").argument("<resource-key>", "Solution resource key (a GUID, or a compound key such as MyFunction.api.MyFunction.1:1.0.0)").option("--solution-folder <path>", "Path to the solution root folder (defaults to current directory)").examples(RESOURCE_REMOVE_EXAMPLES).trackedAction(processContext, async (resourceKey, options) => {
|
|
5559
|
-
if (!resourceKey
|
|
5560
|
-
OutputFormatter.error({
|
|
5561
|
-
Result: RESULTS.Failure,
|
|
5562
|
-
Message: "Missing required argument <resource-key>",
|
|
5563
|
-
Instructions: "Pass the solution resource key as a positional argument. Use 'uip solution resources list' to discover keys."
|
|
5564
|
-
});
|
|
5565
|
-
processContext.exit(1);
|
|
5566
|
-
return;
|
|
5567
|
-
}
|
|
5568
|
-
if (!RESOURCE_KEY_REGEX2.test(resourceKey)) {
|
|
5569
|
-
OutputFormatter.error({
|
|
5570
|
-
Result: RESULTS.Failure,
|
|
5571
|
-
Message: "<resource-key> contains unsupported characters",
|
|
5572
|
-
Instructions: "Resource keys use letters, digits, and '. _ - :' only. Use 'uip solution resources list' to find a valid key."
|
|
5573
|
-
});
|
|
5574
|
-
processContext.exit(1);
|
|
5186
|
+
if (!validateResourceKeyArgument(resourceKey)) {
|
|
5575
5187
|
return;
|
|
5576
5188
|
}
|
|
5189
|
+
const {
|
|
5190
|
+
assertSolutionManifest,
|
|
5191
|
+
createResourceBuilderServices,
|
|
5192
|
+
normalizeResourceFileCasing,
|
|
5193
|
+
saveCasingNormalized
|
|
5194
|
+
} = await import("./index-prm27bvm.js");
|
|
5577
5195
|
const fs = getFileSystem();
|
|
5578
5196
|
const resolvedPath = fs.path.resolve(fs.env.cwd(), options.solutionFolder ?? ".");
|
|
5579
5197
|
if (!await fs.exists(resolvedPath)) {
|
|
@@ -5680,118 +5298,6 @@ var registerResourceCommand = (program) => {
|
|
|
5680
5298
|
registerResourceEditCommand(resources);
|
|
5681
5299
|
};
|
|
5682
5300
|
|
|
5683
|
-
// src/services/restore-command-service.ts
|
|
5684
|
-
class RestoreCommandService {
|
|
5685
|
-
packager = null;
|
|
5686
|
-
fs;
|
|
5687
|
-
constructor() {
|
|
5688
|
-
this.fs = getFileSystem();
|
|
5689
|
-
}
|
|
5690
|
-
async execute(solutionPath, options, context) {
|
|
5691
|
-
const check = await checkSolutionPathAsync(this.fs, solutionPath);
|
|
5692
|
-
if (!check.ok) {
|
|
5693
|
-
OutputFormatter.error({
|
|
5694
|
-
Result: RESULTS.Failure,
|
|
5695
|
-
Message: check.message,
|
|
5696
|
-
Instructions: SOLUTION_PATH_INSTRUCTIONS,
|
|
5697
|
-
ErrorCode: check.errorCode
|
|
5698
|
-
});
|
|
5699
|
-
if (check.statError?.stack) {
|
|
5700
|
-
logger.error("Stack trace:");
|
|
5701
|
-
logger.error(check.statError.stack);
|
|
5702
|
-
}
|
|
5703
|
-
context.exit(1);
|
|
5704
|
-
return;
|
|
5705
|
-
}
|
|
5706
|
-
const { absoluteSolutionPath, isUisFile } = check;
|
|
5707
|
-
const solutionName = isUisFile ? this.fs.path.basename(solutionPath, ".uis") : this.fs.path.basename(solutionPath);
|
|
5708
|
-
logger.info(`
|
|
5709
|
-
Restoring solution dependencies...
|
|
5710
|
-
`);
|
|
5711
|
-
logger.info("Details:");
|
|
5712
|
-
logger.info(` Solution: ${absoluteSolutionPath}`);
|
|
5713
|
-
logger.info("");
|
|
5714
|
-
const [error, result] = await catchError(this.executeAsync(solutionPath, options));
|
|
5715
|
-
if (error) {
|
|
5716
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
5717
|
-
OutputFormatter.error({
|
|
5718
|
-
Result: RESULTS.Failure,
|
|
5719
|
-
...isUnpackableProjectTypeError(error) ? { ErrorCode: "invalid_argument" } : {},
|
|
5720
|
-
Message: msg,
|
|
5721
|
-
Instructions: carriedInstructions(error) ?? "Check that you are logged in (`uip auth login`) and that the solution path is accessible, then rerun: uip solution restore <solutionPath>"
|
|
5722
|
-
});
|
|
5723
|
-
if (error instanceof Error && error.stack && !isUnpackableProjectTypeError(error)) {
|
|
5724
|
-
logger.error("Stack trace:");
|
|
5725
|
-
logger.error(error.stack);
|
|
5726
|
-
}
|
|
5727
|
-
context.exit(1);
|
|
5728
|
-
return;
|
|
5729
|
-
}
|
|
5730
|
-
if (result.errorCode !== "SUCCESS" /* Success */) {
|
|
5731
|
-
OutputFormatter.error({
|
|
5732
|
-
Result: RESULTS.Failure,
|
|
5733
|
-
Message: `Error code: ${result.errorCode} : ${result.message}`,
|
|
5734
|
-
Instructions: "Resolve the reported dependency issue, ensure you are logged in with `uip auth login`, then rerun: uip solution restore <solutionPath>"
|
|
5735
|
-
});
|
|
5736
|
-
context.exit(1);
|
|
5737
|
-
return;
|
|
5738
|
-
}
|
|
5739
|
-
OutputFormatter.success({
|
|
5740
|
-
Result: RESULTS.Success,
|
|
5741
|
-
Code: "SolutionRestore",
|
|
5742
|
-
Data: {
|
|
5743
|
-
Solution: solutionName,
|
|
5744
|
-
Status: "Restored"
|
|
5745
|
-
}
|
|
5746
|
-
});
|
|
5747
|
-
}
|
|
5748
|
-
async executeAsync(solutionPath, options) {
|
|
5749
|
-
const check = await checkSolutionPathAsync(this.fs, solutionPath);
|
|
5750
|
-
if (!check.ok) {
|
|
5751
|
-
if (check.statError) {
|
|
5752
|
-
throw check.statError;
|
|
5753
|
-
}
|
|
5754
|
-
return new ToolResult("INTERNAL_ERROR" /* InternalError */, check.message, []);
|
|
5755
|
-
}
|
|
5756
|
-
const { absoluteSolutionPath, isUisFile } = check;
|
|
5757
|
-
const solutionName = isUisFile ? this.fs.path.basename(solutionPath, ".uis") : this.fs.path.basename(solutionPath);
|
|
5758
|
-
const packager = await this.ensurePackagerAsync();
|
|
5759
|
-
let inputPath;
|
|
5760
|
-
if (isUisFile) {
|
|
5761
|
-
const uint8Array = await readSolutionFileAsUint8Array(this.fs, absoluteSolutionPath);
|
|
5762
|
-
inputPath = await packager.setupAsync(uint8Array);
|
|
5763
|
-
} else {
|
|
5764
|
-
inputPath = await packager.setupAsync(absoluteSolutionPath);
|
|
5765
|
-
}
|
|
5766
|
-
await ensurePackagerTools(inputPath, this.fs);
|
|
5767
|
-
const restoreOptions = await this.createRestoreOptions(inputPath, solutionName, options);
|
|
5768
|
-
return packager.restoreSolutionAsync(restoreOptions);
|
|
5769
|
-
}
|
|
5770
|
-
async ensurePackagerAsync() {
|
|
5771
|
-
if (!this.packager) {
|
|
5772
|
-
this.packager = await createSolutionPackager();
|
|
5773
|
-
}
|
|
5774
|
-
return this.packager;
|
|
5775
|
-
}
|
|
5776
|
-
async createRestoreOptions(inputPath, solutionName, options) {
|
|
5777
|
-
const restoreOptions = new SolutionPackOptions;
|
|
5778
|
-
restoreOptions.inputPath = inputPath;
|
|
5779
|
-
restoreOptions.configuration = "Release" /* Release */;
|
|
5780
|
-
restoreOptions.excludeConfiguredSources = options.excludeConfiguredSources ?? false;
|
|
5781
|
-
restoreOptions.package = {
|
|
5782
|
-
id: solutionName,
|
|
5783
|
-
version: "1.0.0",
|
|
5784
|
-
author: "",
|
|
5785
|
-
description: ""
|
|
5786
|
-
};
|
|
5787
|
-
restoreOptions.logLevel = resolveSdkLogLevel();
|
|
5788
|
-
restoreOptions.nuGetSourcesConfigPath = options.nugetSourcesConfigPath;
|
|
5789
|
-
restoreOptions.feedFolder = options.feedFolder;
|
|
5790
|
-
await applyAuthConnection(restoreOptions, options.loginValidity);
|
|
5791
|
-
return restoreOptions;
|
|
5792
|
-
}
|
|
5793
|
-
}
|
|
5794
|
-
|
|
5795
5301
|
// src/commands/restore.ts
|
|
5796
5302
|
var SOLUTION_RESTORE_EXAMPLES = [
|
|
5797
5303
|
{
|
|
@@ -5807,7 +5313,8 @@ var SOLUTION_RESTORE_EXAMPLES = [
|
|
|
5807
5313
|
}
|
|
5808
5314
|
];
|
|
5809
5315
|
var registerRestoreCommand = (program) => {
|
|
5810
|
-
program.command("restore").description("Restore NuGet dependencies for every project in a UiPath solution using the authenticated session. Accepts a solution directory (containing .uipx) or a .uis file. Resolves dependencies in place and does not produce a package — run it before 'uip solution pack'.").argument("<
|
|
5316
|
+
program.command("restore").description("Restore NuGet dependencies for every project in a UiPath solution using the authenticated session. Accepts a solution directory (containing .uipx) or a .uis file. Resolves dependencies in place and does not produce a package — run it before 'uip solution pack'.").argument("<solution-path>", "Path to a solution directory (containing .uipx) or a .uis file").option("--nuget-sources-config-path <path>", "Path to NuGet sources configuration file").option("--exclude-configured-sources", "Resolve project dependencies only from the tenant feeds and any --nuget-sources-config-path. Drops the built-in UiPath and nuget.org feeds, so a dependency that is not on those feeds fails to restore.").option("--feed-folder <name>", "Resolve project dependencies from this Orchestrator folder's library feed instead of every tenant feed. Accepts a folder name or fully qualified path.").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).examples(SOLUTION_RESTORE_EXAMPLES).trackedAction(processContext, async (solutionPath, options) => {
|
|
5317
|
+
const { RestoreCommandService } = await import("./restore-command-service-5v0b9363.js");
|
|
5811
5318
|
const service = new RestoreCommandService;
|
|
5812
5319
|
await service.execute(solutionPath, {
|
|
5813
5320
|
loginValidity: options.loginValidity,
|
|
@@ -5817,541 +5324,6 @@ var registerRestoreCommand = (program) => {
|
|
|
5817
5324
|
}, processContext);
|
|
5818
5325
|
});
|
|
5819
5326
|
};
|
|
5820
|
-
// ../executor/project-executor/src/models/run-status.ts
|
|
5821
|
-
var TERMINAL_RUN_STATUSES = [
|
|
5822
|
-
"Succeeded" /* Succeeded */,
|
|
5823
|
-
"Faulted" /* Faulted */,
|
|
5824
|
-
"Cancelled" /* Cancelled */
|
|
5825
|
-
];
|
|
5826
|
-
function isTerminalRunStatus(status) {
|
|
5827
|
-
return TERMINAL_RUN_STATUSES.includes(status);
|
|
5828
|
-
}
|
|
5829
|
-
|
|
5830
|
-
// ../executor/project-executor/src/models/run-result.ts
|
|
5831
|
-
class RunResult {
|
|
5832
|
-
status;
|
|
5833
|
-
errorCode;
|
|
5834
|
-
rawStatus;
|
|
5835
|
-
message;
|
|
5836
|
-
jobKey;
|
|
5837
|
-
instanceId;
|
|
5838
|
-
runId;
|
|
5839
|
-
traceId;
|
|
5840
|
-
steps;
|
|
5841
|
-
output;
|
|
5842
|
-
url;
|
|
5843
|
-
details;
|
|
5844
|
-
constructor(status, errorCode = "None" /* None */, message) {
|
|
5845
|
-
this.status = status;
|
|
5846
|
-
this.errorCode = errorCode;
|
|
5847
|
-
this.message = message;
|
|
5848
|
-
}
|
|
5849
|
-
get isSuccess() {
|
|
5850
|
-
return this.status === "Succeeded" /* Succeeded */ && this.errorCode === "None" /* None */;
|
|
5851
|
-
}
|
|
5852
|
-
get isTerminal() {
|
|
5853
|
-
return isTerminalRunStatus(this.status);
|
|
5854
|
-
}
|
|
5855
|
-
static succeeded(init = {}) {
|
|
5856
|
-
return Object.assign(new RunResult("Succeeded" /* Succeeded */, "None" /* None */), init);
|
|
5857
|
-
}
|
|
5858
|
-
static failed(errorCode, message, init = {}) {
|
|
5859
|
-
return Object.assign(new RunResult("Faulted" /* Faulted */, errorCode, message), init);
|
|
5860
|
-
}
|
|
5861
|
-
}
|
|
5862
|
-
// ../executor/project-executor/src/services/executor-tool-import.ts
|
|
5863
|
-
async function importExecutorToolModule(specifier) {
|
|
5864
|
-
try {
|
|
5865
|
-
return { module: await import(specifier) };
|
|
5866
|
-
} catch (error) {
|
|
5867
|
-
return {
|
|
5868
|
-
error: error instanceof Error ? error : new Error(String(error))
|
|
5869
|
-
};
|
|
5870
|
-
}
|
|
5871
|
-
}
|
|
5872
|
-
|
|
5873
|
-
// ../executor/project-executor/src/services/executor-tool-module.ts
|
|
5874
|
-
var EXECUTOR_FACTORY_EXPORT = "createExecutorFactory";
|
|
5875
|
-
function isExecutorFactoryModule(module) {
|
|
5876
|
-
return typeof module === "object" && module !== null && typeof module[EXECUTOR_FACTORY_EXPORT] === "function";
|
|
5877
|
-
}
|
|
5878
|
-
|
|
5879
|
-
// ../executor/project-executor/src/services/executors-factory-repository.ts
|
|
5880
|
-
class ExecutorsFactoryRepository {
|
|
5881
|
-
factoryMap = new Map;
|
|
5882
|
-
onConflict;
|
|
5883
|
-
constructor(onConflict) {
|
|
5884
|
-
this.onConflict = onConflict ?? ((message) => console.warn(message));
|
|
5885
|
-
}
|
|
5886
|
-
registerProjectExecutorFactory(factory) {
|
|
5887
|
-
for (const projectType of factory.supportedTypes) {
|
|
5888
|
-
const existing = this.factoryMap.get(projectType);
|
|
5889
|
-
if (existing) {
|
|
5890
|
-
if (existing.constructor?.name !== factory.constructor?.name) {
|
|
5891
|
-
this.onConflict(`Executor factory conflict for project type '${projectType}': ` + `'${existing.constructor?.name}' already registered, ` + `ignoring '${factory.constructor?.name}'.`);
|
|
5892
|
-
}
|
|
5893
|
-
continue;
|
|
5894
|
-
}
|
|
5895
|
-
this.factoryMap.set(projectType, factory);
|
|
5896
|
-
}
|
|
5897
|
-
}
|
|
5898
|
-
canHandleProject(projectType) {
|
|
5899
|
-
return this.factoryMap.has(projectType);
|
|
5900
|
-
}
|
|
5901
|
-
getProjectExecutorFactory(projectType) {
|
|
5902
|
-
const factory = this.factoryMap.get(projectType);
|
|
5903
|
-
if (!factory) {
|
|
5904
|
-
throw new Error(`Cannot run project type '${projectType}': no runner is installed for it. ` + `Project types that can be run: ${this.registeredTypes.join(", ") || "none"}.`);
|
|
5905
|
-
}
|
|
5906
|
-
return factory;
|
|
5907
|
-
}
|
|
5908
|
-
get registeredTypes() {
|
|
5909
|
-
return [...this.factoryMap.keys()];
|
|
5910
|
-
}
|
|
5911
|
-
reset() {
|
|
5912
|
-
this.factoryMap.clear();
|
|
5913
|
-
}
|
|
5914
|
-
}
|
|
5915
|
-
var REGISTRY_KEY = Symbol.for("@uipath/project-executor/executorsFactoryRepository");
|
|
5916
|
-
var _global = globalThis;
|
|
5917
|
-
if (!_global[REGISTRY_KEY]) {
|
|
5918
|
-
_global[REGISTRY_KEY] = new ExecutorsFactoryRepository;
|
|
5919
|
-
}
|
|
5920
|
-
var executorsFactoryRepository = _global[REGISTRY_KEY];
|
|
5921
|
-
|
|
5922
|
-
// ../executor/project-executor/src/services/executor-factory-provider.ts
|
|
5923
|
-
var PROVIDER_KEY = Symbol.for("@uipath/project-executor/executorFactoryProvider");
|
|
5924
|
-
var _global2 = globalThis;
|
|
5925
|
-
function registerExecutorFactoryFromModule(module, source) {
|
|
5926
|
-
if (!isExecutorFactoryModule(module)) {
|
|
5927
|
-
throw new Error(`${source} does not export ${EXECUTOR_FACTORY_EXPORT}().`);
|
|
5928
|
-
}
|
|
5929
|
-
const factory = module.createExecutorFactory();
|
|
5930
|
-
executorsFactoryRepository.registerProjectExecutorFactory(factory);
|
|
5931
|
-
return factory;
|
|
5932
|
-
}
|
|
5933
|
-
async function ensureExecutorFactory(verb, packageName) {
|
|
5934
|
-
const provider = _global2[PROVIDER_KEY];
|
|
5935
|
-
if (provider) {
|
|
5936
|
-
await provider(verb);
|
|
5937
|
-
return;
|
|
5938
|
-
}
|
|
5939
|
-
if (!packageName) {
|
|
5940
|
-
throw new Error(`Running this project type needs the executor factory for '${verb}', and no package provides it.`);
|
|
5941
|
-
}
|
|
5942
|
-
const specifier = `${packageName}/executor-tool`;
|
|
5943
|
-
const { module, error } = await importExecutorToolModule(specifier);
|
|
5944
|
-
if (error) {
|
|
5945
|
-
throw new Error(`Running this project type needs '${packageName}'. Install it.`, { cause: error });
|
|
5946
|
-
}
|
|
5947
|
-
registerExecutorFactoryFromModule(module, specifier);
|
|
5948
|
-
}
|
|
5949
|
-
// ../executor/project-executor/src/services/executor-logger.ts
|
|
5950
|
-
var noopExecutorLogger = {
|
|
5951
|
-
info: () => {},
|
|
5952
|
-
warn: () => {},
|
|
5953
|
-
error: () => {}
|
|
5954
|
-
};
|
|
5955
|
-
// ../executor/project-executor/src/services/project-runner.ts
|
|
5956
|
-
class ProjectRunner {
|
|
5957
|
-
fileSystem;
|
|
5958
|
-
logger;
|
|
5959
|
-
registry;
|
|
5960
|
-
constructor(deps) {
|
|
5961
|
-
this.fileSystem = deps.fileSystem;
|
|
5962
|
-
this.logger = deps.logger ?? noopExecutorLogger;
|
|
5963
|
-
this.registry = deps.registry ?? executorsFactoryRepository;
|
|
5964
|
-
}
|
|
5965
|
-
canRun(projectType) {
|
|
5966
|
-
return this.registry.canHandleProject(projectType);
|
|
5967
|
-
}
|
|
5968
|
-
get runnableTypes() {
|
|
5969
|
-
return this.registry.registeredTypes;
|
|
5970
|
-
}
|
|
5971
|
-
async runAsync(options, cancellationToken) {
|
|
5972
|
-
const { projectType, name } = options.project;
|
|
5973
|
-
if (!this.canRun(projectType)) {
|
|
5974
|
-
const known = this.runnableTypes.join(", ") || "none";
|
|
5975
|
-
return RunResult.failed("UnsupportedProjectType" /* UnsupportedProjectType */, `Cannot run project '${name}' (project type '${projectType}'): ` + `no runner is installed for it. Project types that can be run: ${known}.`);
|
|
5976
|
-
}
|
|
5977
|
-
let executor;
|
|
5978
|
-
try {
|
|
5979
|
-
const factory = this.registry.getProjectExecutorFactory(projectType);
|
|
5980
|
-
executor = await factory.createAsync(this.logger, this.fileSystem);
|
|
5981
|
-
this.logger.info(`Running ${name} (${projectType}) on ${options.target}.`);
|
|
5982
|
-
return await executor.runAsync(options, cancellationToken);
|
|
5983
|
-
} catch (error) {
|
|
5984
|
-
return RunResult.failed("Unknown" /* Unknown */, messageOf(error));
|
|
5985
|
-
} finally {
|
|
5986
|
-
try {
|
|
5987
|
-
await executor?.dispose();
|
|
5988
|
-
} catch (error) {
|
|
5989
|
-
this.logger.warn(`Failed to dispose the ${projectType} executor: ${messageOf(error)}`);
|
|
5990
|
-
}
|
|
5991
|
-
}
|
|
5992
|
-
}
|
|
5993
|
-
}
|
|
5994
|
-
function messageOf(error) {
|
|
5995
|
-
return error instanceof Error ? error.message : String(error);
|
|
5996
|
-
}
|
|
5997
|
-
// src/services/executor-tool-resolver.ts
|
|
5998
|
-
var PROJECT_TYPE_TO_TOOL = new Map([
|
|
5999
|
-
["Process", "rpa"],
|
|
6000
|
-
["Tests", "rpa"],
|
|
6001
|
-
["WebApp", "rpa"],
|
|
6002
|
-
["Agent", "agent"],
|
|
6003
|
-
["Api", "api-workflow"]
|
|
6004
|
-
]);
|
|
6005
|
-
var TOOL_TO_PACKAGE = new Map([
|
|
6006
|
-
["rpa", "@uipath/rpa-tool"],
|
|
6007
|
-
["agent", "@uipath/agent-tool"],
|
|
6008
|
-
["api-workflow", "@uipath/api-workflow-tool"]
|
|
6009
|
-
]);
|
|
6010
|
-
function hasExecutorToolFor(projectType) {
|
|
6011
|
-
return PROJECT_TYPE_TO_TOOL.has(projectType);
|
|
6012
|
-
}
|
|
6013
|
-
async function ensureExecutorTools(projectTypes) {
|
|
6014
|
-
const neededTools = new Set;
|
|
6015
|
-
for (const type of projectTypes) {
|
|
6016
|
-
if (executorsFactoryRepository.canHandleProject(type))
|
|
6017
|
-
continue;
|
|
6018
|
-
const toolVerb = PROJECT_TYPE_TO_TOOL.get(type);
|
|
6019
|
-
if (toolVerb) {
|
|
6020
|
-
neededTools.add(toolVerb);
|
|
6021
|
-
} else {
|
|
6022
|
-
logger.warn(`No installable tool runs project type '${type}'. Run may fail.`);
|
|
6023
|
-
}
|
|
6024
|
-
}
|
|
6025
|
-
for (const toolVerb of neededTools) {
|
|
6026
|
-
logger.info(`Loading executor factory for '${toolVerb}' to run project types...`);
|
|
6027
|
-
await ensureExecutorFactory(toolVerb, TOOL_TO_PACKAGE.get(toolVerb));
|
|
6028
|
-
}
|
|
6029
|
-
}
|
|
6030
|
-
function projectDirOf(fs, declaredPath) {
|
|
6031
|
-
const dir = fs.path.dirname(declaredPath);
|
|
6032
|
-
return dir && dir !== "." ? dir : "";
|
|
6033
|
-
}
|
|
6034
|
-
async function readSolutionProjects(solutionDir, fs) {
|
|
6035
|
-
const entries = await fs.readdir(solutionDir);
|
|
6036
|
-
const uipxFile = entries.find((f) => f.endsWith(".uipx"));
|
|
6037
|
-
if (!uipxFile) {
|
|
6038
|
-
throw new Error(`No .uipx solution file found in '${solutionDir}'. ` + `Pass a solution directory or run 'uip solution init' first.`);
|
|
6039
|
-
}
|
|
6040
|
-
const content = await fs.readFile(fs.path.join(solutionDir, uipxFile));
|
|
6041
|
-
if (!content) {
|
|
6042
|
-
throw new Error(`Solution file '${uipxFile}' is empty.`);
|
|
6043
|
-
}
|
|
6044
|
-
const json = typeof content === "string" ? content : new TextDecoder().decode(content);
|
|
6045
|
-
const [parseError, solution] = catchError(() => JSON.parse(json));
|
|
6046
|
-
if (parseError) {
|
|
6047
|
-
throw new Error(`Failed to parse ${uipxFile}: ${parseError.message}`);
|
|
6048
|
-
}
|
|
6049
|
-
return (solution.Projects ?? []).map((p) => {
|
|
6050
|
-
const relativePath = projectDirOf(fs, p.ProjectRelativePath ?? "");
|
|
6051
|
-
return {
|
|
6052
|
-
name: p.Name || fs.path.basename(relativePath || solutionDir) || "",
|
|
6053
|
-
projectType: p.Type ?? "",
|
|
6054
|
-
relativePath
|
|
6055
|
-
};
|
|
6056
|
-
});
|
|
6057
|
-
}
|
|
6058
|
-
|
|
6059
|
-
// src/services/provision-debug-service.ts
|
|
6060
|
-
function nextDebugVersion() {
|
|
6061
|
-
return `1.0.${Math.floor(Date.now() / 1000)}`;
|
|
6062
|
-
}
|
|
6063
|
-
async function defaultGetSolutionBuilder(solutionDir) {
|
|
6064
|
-
const services = await createResourceBuilderServices();
|
|
6065
|
-
return services.getSolutionBuilder(solutionDir, true);
|
|
6066
|
-
}
|
|
6067
|
-
async function provisionSolutionForDebugAsync(options, deps = {}) {
|
|
6068
|
-
const listLocations = deps.listLocations ?? listSelectablePublishLocations;
|
|
6069
|
-
const pack = deps.pack ?? packSolutionAsync;
|
|
6070
|
-
const publish = deps.publish ?? publishSolutionAsync;
|
|
6071
|
-
const getBuilder = deps.getSolutionBuilder ?? defaultGetSolutionBuilder;
|
|
6072
|
-
const newSessionId = deps.newSessionId ?? (() => crypto.randomUUID());
|
|
6073
|
-
const authOptions = {
|
|
6074
|
-
tenant: options.tenant,
|
|
6075
|
-
loginValidity: options.loginValidity
|
|
6076
|
-
};
|
|
6077
|
-
const getDebugStatus = deps.getDebugStatus ?? (async (solutionKey2, debugSessionId) => {
|
|
6078
|
-
const auth = await getSolutionAuthContext(authOptions);
|
|
6079
|
-
return getProjectDebugStatus({ basePath: auth.basePath, accessToken: auth.accessToken }, solutionKey2, debugSessionId);
|
|
6080
|
-
});
|
|
6081
|
-
logger.info("Resolving the personal workspace to deploy into...");
|
|
6082
|
-
const [locationsError, locations] = await catchError(listLocations(authOptions));
|
|
6083
|
-
if (locationsError) {
|
|
6084
|
-
return fail(`Could not resolve a personal workspace to deploy into: ${locationsError.message}`);
|
|
6085
|
-
}
|
|
6086
|
-
const personal = locations.find((l) => l.isMyPersonalWorkspace);
|
|
6087
|
-
if (!personal) {
|
|
6088
|
-
return fail("This account has no personal workspace, so there is nowhere to deploy the solution for a debug run. " + "Ask an administrator to enable a personal workspace, or run with --no-provision-resources — " + "the run then starts without a deployment, and cross-project calls will not resolve.");
|
|
6089
|
-
}
|
|
6090
|
-
const version = options.version ?? nextDebugVersion();
|
|
6091
|
-
const fs = getFileSystem();
|
|
6092
|
-
const outputPath = fs.path.join(fs.env.tmpdir(), "uip-solution-run", newSessionId());
|
|
6093
|
-
const uploaded = await packAndUploadAsync({
|
|
6094
|
-
options,
|
|
6095
|
-
authOptions,
|
|
6096
|
-
pack,
|
|
6097
|
-
publish,
|
|
6098
|
-
version,
|
|
6099
|
-
outputPath
|
|
6100
|
-
});
|
|
6101
|
-
if (!uploaded.ok) {
|
|
6102
|
-
return fail(uploaded.message);
|
|
6103
|
-
}
|
|
6104
|
-
const packageVersionKey = uploaded.packageVersionKey;
|
|
6105
|
-
logger.info("Provisioning the solution's resources for the run...");
|
|
6106
|
-
const [builderError, builder] = await catchError(getBuilder(options.solutionDir));
|
|
6107
|
-
if (builderError) {
|
|
6108
|
-
return fail(`Could not read the solution: ${builderError.message}`);
|
|
6109
|
-
}
|
|
6110
|
-
const sessionId = newSessionId();
|
|
6111
|
-
const [debugError, debug] = await catchError(builder.debugProjectAsync(personal.key, options.solutionName, sessionId, packageVersionKey, true));
|
|
6112
|
-
let solutionKey;
|
|
6113
|
-
if (!debugError && debug.complete === false) {
|
|
6114
|
-
const [, definition] = await catchError(builder.context.loadAsync());
|
|
6115
|
-
solutionKey = definition?.key;
|
|
6116
|
-
}
|
|
6117
|
-
await builder.disposeAsync().catch(() => {});
|
|
6118
|
-
if (debugError) {
|
|
6119
|
-
return fail(`Provisioning the solution failed: ${debugError.message}`);
|
|
6120
|
-
}
|
|
6121
|
-
if (debug.complete === false) {
|
|
6122
|
-
if (!solutionKey) {
|
|
6123
|
-
return fail("The cloud is still provisioning the solution, but its key could not be read back from the .uipx, so the provisioning cannot be waited on. Retry the run.");
|
|
6124
|
-
}
|
|
6125
|
-
return waitForProvisioningAsync({
|
|
6126
|
-
solutionKey,
|
|
6127
|
-
sessionId,
|
|
6128
|
-
packageVersionKey,
|
|
6129
|
-
options,
|
|
6130
|
-
getDebugStatus
|
|
6131
|
-
});
|
|
6132
|
-
}
|
|
6133
|
-
const folderPath = debug.folderFullyQualifiedName;
|
|
6134
|
-
logger.info(folderPath ? `Solution provisioned into ${folderPath}.` : "Solution provisioned.");
|
|
6135
|
-
return {
|
|
6136
|
-
ok: true,
|
|
6137
|
-
folderPath,
|
|
6138
|
-
packageVersionKey
|
|
6139
|
-
};
|
|
6140
|
-
}
|
|
6141
|
-
function fail(message) {
|
|
6142
|
-
return { ok: false, message };
|
|
6143
|
-
}
|
|
6144
|
-
async function packAndUploadAsync(args) {
|
|
6145
|
-
const { options, authOptions, version } = args;
|
|
6146
|
-
logger.info("Packing the solution...");
|
|
6147
|
-
const [packError, packed] = await catchError(args.pack(options.solutionDir, {
|
|
6148
|
-
output: args.outputPath,
|
|
6149
|
-
name: options.solutionName,
|
|
6150
|
-
version,
|
|
6151
|
-
loginValidity: options.loginValidity
|
|
6152
|
-
}));
|
|
6153
|
-
if (packError) {
|
|
6154
|
-
return {
|
|
6155
|
-
ok: false,
|
|
6156
|
-
message: `Packing the solution failed: ${packError.message}`
|
|
6157
|
-
};
|
|
6158
|
-
}
|
|
6159
|
-
if (!packed.ok) {
|
|
6160
|
-
return {
|
|
6161
|
-
ok: false,
|
|
6162
|
-
message: `Packing the solution failed: ${packed.message}`
|
|
6163
|
-
};
|
|
6164
|
-
}
|
|
6165
|
-
const packagePath = packed.packages?.[0];
|
|
6166
|
-
if (!packagePath) {
|
|
6167
|
-
return {
|
|
6168
|
-
ok: false,
|
|
6169
|
-
message: "Packing the solution produced no package."
|
|
6170
|
-
};
|
|
6171
|
-
}
|
|
6172
|
-
logger.info("Uploading the solution to the personal workspace...");
|
|
6173
|
-
const [publishError, published] = await catchError(args.publish(packagePath, {
|
|
6174
|
-
...authOptions,
|
|
6175
|
-
personalWorkspace: true,
|
|
6176
|
-
packageVersion: version
|
|
6177
|
-
}));
|
|
6178
|
-
if (publishError) {
|
|
6179
|
-
return {
|
|
6180
|
-
ok: false,
|
|
6181
|
-
message: `Uploading the solution failed: ${publishError.message}`
|
|
6182
|
-
};
|
|
6183
|
-
}
|
|
6184
|
-
if (!published.ok) {
|
|
6185
|
-
return {
|
|
6186
|
-
ok: false,
|
|
6187
|
-
message: `Uploading the solution failed: ${published.message}`
|
|
6188
|
-
};
|
|
6189
|
-
}
|
|
6190
|
-
if (!published.packageVersionKey) {
|
|
6191
|
-
return {
|
|
6192
|
-
ok: false,
|
|
6193
|
-
message: "The solution was uploaded but the feed did not report a package version, so it cannot be provisioned. Retry the run."
|
|
6194
|
-
};
|
|
6195
|
-
}
|
|
6196
|
-
return { ok: true, packageVersionKey: published.packageVersionKey };
|
|
6197
|
-
}
|
|
6198
|
-
async function waitForProvisioningAsync(args) {
|
|
6199
|
-
const { solutionKey, sessionId, packageVersionKey, options } = args;
|
|
6200
|
-
const timeoutMs = options.provisioningTimeoutMs ?? 360000;
|
|
6201
|
-
logger.info("Waiting for the cloud to finish provisioning...");
|
|
6202
|
-
const poll = await pollUntil({
|
|
6203
|
-
fn: () => args.getDebugStatus(solutionKey, sessionId),
|
|
6204
|
-
until: (info2) => isDebugProvisioningTerminal(info2.status),
|
|
6205
|
-
getStatus: (info2) => info2.status ?? "pending",
|
|
6206
|
-
label: `solution provisioning (session ${sessionId})`,
|
|
6207
|
-
logPrefix: "provision",
|
|
6208
|
-
timeoutMs,
|
|
6209
|
-
intervalMs: options.provisioningPollIntervalMs ?? 5000,
|
|
6210
|
-
maxConsecutiveErrors: 5,
|
|
6211
|
-
signal: processContext.pollSignal
|
|
6212
|
-
});
|
|
6213
|
-
if (poll.outcome !== PollOutcome.Completed || !poll.data) {
|
|
6214
|
-
return fail(describeIncompleteWait(poll, timeoutMs));
|
|
6215
|
-
}
|
|
6216
|
-
const info = poll.data;
|
|
6217
|
-
if (!isDebugProvisioningSucceeded(info.status)) {
|
|
6218
|
-
const details = (info.errors ?? []).map((error) => error.resource ? `${error.resource.kind ?? "resource"} '${error.resource.name ?? error.resource.key ?? ""}': ${error.message}` : error.message).join(`
|
|
6219
|
-
`);
|
|
6220
|
-
return fail(`Provisioning the solution failed (${info.status}).` + (details ? `
|
|
6221
|
-
${details}` : ""));
|
|
6222
|
-
}
|
|
6223
|
-
logger.info("Solution provisioned.");
|
|
6224
|
-
return { ok: true, packageVersionKey };
|
|
6225
|
-
}
|
|
6226
|
-
function describeIncompleteWait(poll, timeoutMs) {
|
|
6227
|
-
const lastStatus = poll.data?.status ?? "unknown";
|
|
6228
|
-
if (poll.outcome === PollOutcome.Interrupted) {
|
|
6229
|
-
return `The wait for the solution's provisioning was cancelled (last status: ${lastStatus}). ` + "The cloud may still finish it.";
|
|
6230
|
-
}
|
|
6231
|
-
if (poll.outcome === PollOutcome.Failed || poll.outcome === PollOutcome.Aborted) {
|
|
6232
|
-
return `Checking the solution's provisioning status failed: ${poll.error?.message ?? "too many consecutive errors"} ` + `(last status: ${lastStatus}). The provisioning itself may still be running or have finished — ` + "retry the run to check.";
|
|
6233
|
-
}
|
|
6234
|
-
return `The solution was uploaded, but the cloud did not finish provisioning it within ${Math.round(timeoutMs / 1000)}s ` + `(last status: ${lastStatus}). ` + "Running again will not help: each run uploads a new version and provisions that one too. " + "To run a project that calls another project, deploy the solution once " + "('uip solution pack' → 'publish' → 'deploy run') and then run with " + "--no-provision-resources --folder-path <deployed folder>.";
|
|
6235
|
-
}
|
|
6236
|
-
|
|
6237
|
-
// src/services/run-service.ts
|
|
6238
|
-
async function runSolutionAsync(options, deps, cancellationToken) {
|
|
6239
|
-
const { fileSystem } = deps;
|
|
6240
|
-
const solutionDir = fileSystem.path.resolve(options.solutionPath);
|
|
6241
|
-
const [readError, projects] = await catchError(readSolutionProjects(solutionDir, fileSystem));
|
|
6242
|
-
if (readError) {
|
|
6243
|
-
return RunResult.failed("InvalidInput" /* InvalidInput */, readError.message);
|
|
6244
|
-
}
|
|
6245
|
-
const runnable = projects.filter((p) => hasExecutorToolFor(p.projectType));
|
|
6246
|
-
if (runnable.length === 0) {
|
|
6247
|
-
const seen = projects.map((p) => `${p.name} (${p.projectType})`).join(", ") || "none";
|
|
6248
|
-
return RunResult.failed("UnsupportedProjectType" /* UnsupportedProjectType */, `No project in this solution can be run. Projects: ${seen}.`);
|
|
6249
|
-
}
|
|
6250
|
-
const [selectionError, selected] = selectProject(runnable, options.projectName);
|
|
6251
|
-
if (selectionError) {
|
|
6252
|
-
return RunResult.failed("InvalidInput" /* InvalidInput */, selectionError);
|
|
6253
|
-
}
|
|
6254
|
-
const provision = deps.provisionForDebug ?? provisionSolutionForDebugAsync;
|
|
6255
|
-
const shouldProvision = options.provisionResources ?? projects.length > 1;
|
|
6256
|
-
const [executorOutcome, provisionOutcome] = await Promise.allSettled([
|
|
6257
|
-
ensureExecutorTools([selected.projectType]),
|
|
6258
|
-
shouldProvision ? provision({
|
|
6259
|
-
solutionDir,
|
|
6260
|
-
solutionName: fileSystem.path.basename(solutionDir),
|
|
6261
|
-
tenant: options.tenant,
|
|
6262
|
-
loginValidity: options.loginValidity
|
|
6263
|
-
}) : Promise.resolve(undefined)
|
|
6264
|
-
]);
|
|
6265
|
-
if (executorOutcome.status === "rejected") {
|
|
6266
|
-
return RunResult.failed("PrepareFailed" /* PrepareFailed */, `Could not load the runner for project type '${selected.projectType}': ${describeError(executorOutcome.reason)}`);
|
|
6267
|
-
}
|
|
6268
|
-
if (provisionOutcome.status === "rejected") {
|
|
6269
|
-
return RunResult.failed("PrepareFailed" /* PrepareFailed */, `Could not deploy the solution before the run: ${describeError(provisionOutcome.reason)}`);
|
|
6270
|
-
}
|
|
6271
|
-
let folderPath = options.folderPath;
|
|
6272
|
-
const provisioned = provisionOutcome.value;
|
|
6273
|
-
if (provisioned) {
|
|
6274
|
-
if (!provisioned.ok) {
|
|
6275
|
-
return RunResult.failed("PrepareFailed" /* PrepareFailed */, provisioned.message ?? "Could not deploy the solution before the run.");
|
|
6276
|
-
}
|
|
6277
|
-
folderPath = provisioned.folderPath;
|
|
6278
|
-
}
|
|
6279
|
-
const projectPath = fileSystem.path.resolve(solutionDir, selected.relativePath);
|
|
6280
|
-
logger.debug(`Running '${selected.name}' (${selected.projectType}) from ${projectPath}` + `${options.entryPoint ? ` with entry point ${options.entryPoint}` : " with its default entry point"}`);
|
|
6281
|
-
const connection = await resolveConnection(folderPath, options, deps);
|
|
6282
|
-
const runner = new ProjectRunner({
|
|
6283
|
-
fileSystem,
|
|
6284
|
-
logger: deps.logger
|
|
6285
|
-
});
|
|
6286
|
-
return runner.runAsync({
|
|
6287
|
-
project: {
|
|
6288
|
-
name: selected.name,
|
|
6289
|
-
projectType: selected.projectType,
|
|
6290
|
-
projectPath
|
|
6291
|
-
},
|
|
6292
|
-
entryPoint: options.entryPoint,
|
|
6293
|
-
inputArguments: options.inputArguments,
|
|
6294
|
-
target: "Local" /* Local */,
|
|
6295
|
-
connection,
|
|
6296
|
-
siblingProjects: projects.filter((p) => p !== selected).map((p) => ({
|
|
6297
|
-
name: p.name,
|
|
6298
|
-
projectType: p.projectType,
|
|
6299
|
-
projectPath: fileSystem.path.resolve(solutionDir, p.relativePath)
|
|
6300
|
-
})),
|
|
6301
|
-
timeoutMs: options.timeoutMs
|
|
6302
|
-
}, cancellationToken);
|
|
6303
|
-
}
|
|
6304
|
-
async function resolveConnection(folderPath, options, deps) {
|
|
6305
|
-
const getLoginStatus = deps.getLoginStatus ?? getLoginStatusAsync;
|
|
6306
|
-
const [loginError, status] = await catchError(getLoginStatus({
|
|
6307
|
-
ensureTokenValidityMinutes: options.loginValidity
|
|
6308
|
-
}));
|
|
6309
|
-
if (loginError || status.loginStatus !== "Logged in") {
|
|
6310
|
-
logger.debug(`No signed-in session for the run: ${loginError?.message ?? status.loginStatus}. ` + "A project type that needs one will say so.");
|
|
6311
|
-
return {
|
|
6312
|
-
folderPath,
|
|
6313
|
-
baseUrl: "",
|
|
6314
|
-
accessToken: "",
|
|
6315
|
-
organizationId: "",
|
|
6316
|
-
organizationName: ""
|
|
6317
|
-
};
|
|
6318
|
-
}
|
|
6319
|
-
return {
|
|
6320
|
-
folderPath,
|
|
6321
|
-
baseUrl: status.baseUrl ?? "",
|
|
6322
|
-
accessToken: status.accessToken ?? "",
|
|
6323
|
-
organizationId: status.organizationId ?? "",
|
|
6324
|
-
organizationName: status.organizationName ?? "",
|
|
6325
|
-
tenantId: status.tenantId,
|
|
6326
|
-
tenantName: status.tenantName
|
|
6327
|
-
};
|
|
6328
|
-
}
|
|
6329
|
-
function describeError(reason) {
|
|
6330
|
-
const message = reason instanceof Error ? reason.message : String(reason);
|
|
6331
|
-
const instructions = carriedInstructions(reason);
|
|
6332
|
-
return instructions ? `${message} ${instructions}` : message;
|
|
6333
|
-
}
|
|
6334
|
-
function selectProject(runnable, requested) {
|
|
6335
|
-
if (requested) {
|
|
6336
|
-
const match = runnable.find((p) => p.name === requested);
|
|
6337
|
-
if (!match) {
|
|
6338
|
-
const names = runnable.map((p) => p.name).join(", ");
|
|
6339
|
-
return [
|
|
6340
|
-
`Project '${requested}' is not a runnable project in this solution. Runnable projects: ${names}.`,
|
|
6341
|
-
runnable[0]
|
|
6342
|
-
];
|
|
6343
|
-
}
|
|
6344
|
-
return [undefined, match];
|
|
6345
|
-
}
|
|
6346
|
-
if (runnable.length > 1) {
|
|
6347
|
-
const names = runnable.map((p) => p.name).join(", ");
|
|
6348
|
-
return [
|
|
6349
|
-
`This solution has more than one runnable project, so one has to be named with --project-name. Runnable projects: ${names}.`,
|
|
6350
|
-
runnable[0]
|
|
6351
|
-
];
|
|
6352
|
-
}
|
|
6353
|
-
return [undefined, runnable[0]];
|
|
6354
|
-
}
|
|
6355
5327
|
|
|
6356
5328
|
// src/commands/run.ts
|
|
6357
5329
|
var ERROR_CODE_BY_RUN_ERROR = {
|
|
@@ -6366,7 +5338,7 @@ var NEVER_STARTED = new Set([
|
|
|
6366
5338
|
"Unauthorized" /* Unauthorized */
|
|
6367
5339
|
]);
|
|
6368
5340
|
var registerRunCommand = (program) => {
|
|
6369
|
-
program.command("run", { hidden: true }).description("Run a project from a UiPath solution. Currently supports RPA projects, agents and API Workflows.").argument("<
|
|
5341
|
+
program.command("run", { hidden: true }).description("Run a project from a UiPath solution. Currently supports RPA projects, agents and API Workflows.").argument("<solution-path>", "Path to a solution directory (containing .uipx)").option("--project-name <name>", "Name of the project to run. Required only when the solution has more than one runnable project.").option("--entry-point <path>", "Entry point to execute (for RPA, a workflow such as Main.xaml). Defaults to the project's own entry point.").option("--input-arguments <json>", `Input arguments for the entry point, as a JSON object string (e.g. '{"name": "World"}').`).option("--folder-path <path>", "Orchestrator folder the run reports itself under, when the runtime needs one. Ignored when the solution is deployed, which uses the folder it deploys into.").option("--provision-resources", "Pack and deploy the solution into your personal workspace before running, even when the solution holds a single project. Done automatically for a solution with more than one project.").option("--no-provision-resources", "Run without deploying the solution first. Cross-project calls will not resolve.").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10).", Number.parseInt, 10).trackedAction(processContext, async (solutionPath, options) => {
|
|
6370
5342
|
const [inputError, inputArguments] = parseInputArguments(options.inputArguments);
|
|
6371
5343
|
if (inputError) {
|
|
6372
5344
|
OutputFormatter.error({
|
|
@@ -6378,6 +5350,7 @@ var registerRunCommand = (program) => {
|
|
|
6378
5350
|
processContext.exit(1);
|
|
6379
5351
|
return;
|
|
6380
5352
|
}
|
|
5353
|
+
const { runSolutionAsync } = await import("./run-service-tg6b67wp.js");
|
|
6381
5354
|
const result = await runSolutionAsync({
|
|
6382
5355
|
solutionPath,
|
|
6383
5356
|
projectName: options.projectName,
|
|
@@ -6493,7 +5466,26 @@ var SOLUTION_UPLOAD_EXAMPLES = [
|
|
|
6493
5466
|
}
|
|
6494
5467
|
];
|
|
6495
5468
|
var registerUploadCommand = (program) => {
|
|
6496
|
-
program.command("upload").description("Upload a solution to UiPath Studio Web for browser-based editing. Accepts a solution directory, .uipx file, or .uis file. If Studio Web has no solution with the bundled SolutionId, the solution is imported as new and the local .uipx is updated with the assigned id; otherwise it is overwritten in place, with the replaced contents recorded first as a restorable version (skip with --no-snapshot). The output field Data.Action says which happened: 'Imported' or 'Overwritten'.").argument("<
|
|
5469
|
+
program.command("upload").description("Upload a solution to UiPath Studio Web for browser-based editing. Accepts a solution directory, .uipx file, or .uis file. If Studio Web has no solution with the bundled SolutionId, the solution is imported as new and the local .uipx is updated with the assigned id; otherwise it is overwritten in place, with the replaced contents recorded first as a restorable version (skip with --no-snapshot). The output field Data.Action says which happened: 'Imported' or 'Overwritten'.").argument("<solution-path>", "Path to a solution directory (containing .uipx), a .uipx file, or a .uis file.").option("--force", "Skip the existence check and overwrite the Studio Web solution named by the bundled SolutionId directly. Not normally needed — an upload overwrites an existing cloud solution on its own. Fails if that solution does not exist. No effect when no SolutionId is bundled (a .uis archive without one): the upload imports as new.").option("--no-snapshot", "Do not record a restorable pre-overwrite version of the cloud solution before replacing its contents. Changes made in Studio Web since the last upload are lost; local files are unaffected. No effect when the upload imports a new solution.").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).examples(SOLUTION_UPLOAD_EXAMPLES).trackedAction(processContext, async (solutionPath, options) => {
|
|
5470
|
+
const {
|
|
5471
|
+
buildSolutionUploadFailureOutput,
|
|
5472
|
+
bundleSolution,
|
|
5473
|
+
importSolution,
|
|
5474
|
+
isSolutionUploadHttpError,
|
|
5475
|
+
overwriteSolution,
|
|
5476
|
+
resolveSolutionDir,
|
|
5477
|
+
StudioWebIncompatibleProjectError,
|
|
5478
|
+
solutionExistsOnStudioWeb,
|
|
5479
|
+
UipignoreExcludesProjectError
|
|
5480
|
+
} = await import("./index-g8c8nf1c.js");
|
|
5481
|
+
const { readBundledSolutionId } = await import("./archive-extract-x35t9ktj.js");
|
|
5482
|
+
const { isUnpackableProjectTypeError } = await import("./packager-tool-resolver-994z3jkj.js");
|
|
5483
|
+
const { prepareSolutionResources } = await import("./prepare-solution-resources-m1djfj62.js");
|
|
5484
|
+
const {
|
|
5485
|
+
inspectSolutionPackageProjectTypes: inspectSolutionPackageProjectTypes2,
|
|
5486
|
+
summarizeShipProjectTypes,
|
|
5487
|
+
trackSolutionShipSucceeded: trackSolutionShipSucceeded2
|
|
5488
|
+
} = await import("./ship-telemetry-myes7ak5.js");
|
|
6497
5489
|
const fs = getFileSystem();
|
|
6498
5490
|
const [loginError, loginStatus] = await catchError(getLoginStatusAsync({
|
|
6499
5491
|
ensureTokenValidityMinutes: options.loginValidity
|
|
@@ -6551,10 +5543,12 @@ var registerUploadCommand = (program) => {
|
|
|
6551
5543
|
if (prepareError) {
|
|
6552
5544
|
const errorCode = carriedErrorCode(prepareError) ?? (isUnpackableProjectTypeError(prepareError) ? "invalid_argument" : undefined);
|
|
6553
5545
|
const contributionCode = prepareError.contributionCode;
|
|
5546
|
+
const retry = carriedRetry(prepareError);
|
|
6554
5547
|
OutputFormatter.error({
|
|
6555
5548
|
Result: RESULTS.Failure,
|
|
6556
5549
|
Message: prepareError.message,
|
|
6557
5550
|
...errorCode ? { ErrorCode: errorCode } : {},
|
|
5551
|
+
...retry ? { Retry: retry } : {},
|
|
6558
5552
|
...typeof contributionCode === "string" ? { Context: { errorCode: contributionCode } } : {},
|
|
6559
5553
|
Instructions: carriedInstructions(prepareError) ?? "Fix the reported problem in the project's files, then re-run the upload."
|
|
6560
5554
|
});
|
|
@@ -6686,8 +5680,8 @@ var registerUploadCommand = (program) => {
|
|
|
6686
5680
|
Response: result
|
|
6687
5681
|
}
|
|
6688
5682
|
});
|
|
6689
|
-
const projectTypeSummary = bundledProjectTypes.length > 0 ? summarizeShipProjectTypes(bundledProjectTypes) : await
|
|
6690
|
-
|
|
5683
|
+
const projectTypeSummary = bundledProjectTypes.length > 0 ? summarizeShipProjectTypes(bundledProjectTypes) : await inspectSolutionPackageProjectTypes2(uisPath);
|
|
5684
|
+
trackSolutionShipSucceeded2({
|
|
6691
5685
|
[ShipDimensions.ShipKind]: "upload",
|
|
6692
5686
|
[ShipDimensions.Target]: "studio_web",
|
|
6693
5687
|
[CommandDimensions.CommandName]: "uip solution upload",
|
|
@@ -6710,19 +5704,12 @@ async function updateLocalSolutionId(fs, result, solutionId, uipxPath) {
|
|
|
6710
5704
|
const shouldUpdateUipx = uipxPath !== undefined && returnedSolutionId !== undefined && returnedSolutionId !== solutionId;
|
|
6711
5705
|
const rewroteLocalSolutionId = shouldUpdateUipx && solutionId !== undefined;
|
|
6712
5706
|
if (shouldUpdateUipx && returnedSolutionId && uipxPath) {
|
|
5707
|
+
const { updateUipxSolutionId } = await import("./index-g8c8nf1c.js");
|
|
6713
5708
|
await updateUipxSolutionId(fs, uipxPath, returnedSolutionId);
|
|
6714
5709
|
logger.info(solutionId ? `Studio Web assigned SolutionId ${returnedSolutionId} — the local .uipx now points at it (was ${solutionId}).` : `Studio Web assigned SolutionId ${returnedSolutionId} — the local .uipx now points at it.`);
|
|
6715
5710
|
}
|
|
6716
5711
|
return { returnedSolutionId, rewroteLocalSolutionId };
|
|
6717
5712
|
}
|
|
6718
|
-
function httpStatusOf(error) {
|
|
6719
|
-
if (error instanceof Error && "status" in error) {
|
|
6720
|
-
const status = error.status;
|
|
6721
|
-
if (typeof status === "number")
|
|
6722
|
-
return status;
|
|
6723
|
-
}
|
|
6724
|
-
return;
|
|
6725
|
-
}
|
|
6726
5713
|
function isSolutionNotFoundError(error) {
|
|
6727
5714
|
return httpStatusOf(error) === 404;
|
|
6728
5715
|
}
|
|
@@ -6749,7 +5736,7 @@ async function buildProbeFailureOutput(probeError, solutionId, identity) {
|
|
|
6749
5736
|
}
|
|
6750
5737
|
function probeAuthInstructions(solutionId, identity) {
|
|
6751
5738
|
const actor = identity?.type === "Application" ? `This session acts as external application ${identity.clientId ?? "(client id unknown)"}: it needs a Studio Web grant that can read a solution.` : identity?.type === "User" ? "This session acts as a user: check that your account has Studio Web access in this tenant." : "Check that this session may read a solution in Studio Web — an external application needs a StudioWebS2S grant, a user needs Studio Web access in the tenant.";
|
|
6752
|
-
return `Studio Web refused the read, and the session is authenticated, so
|
|
5739
|
+
return `Studio Web refused the read, and the session is authenticated, so re-running 'uip login' mints the same token and fails the same way. ${actor} Also confirm solution ${solutionId} lives in the organization and tenant this session logged into. Nothing was uploaded.`;
|
|
6753
5740
|
}
|
|
6754
5741
|
function outputError(message) {
|
|
6755
5742
|
OutputFormatter.error({
|
|
@@ -6782,7 +5769,7 @@ var registerCommands = async (program) => {
|
|
|
6782
5769
|
registerResourceCommand(program);
|
|
6783
5770
|
registerDeleteCommand(program);
|
|
6784
5771
|
if (isPreviewBuild()) {
|
|
6785
|
-
const { registerListCommand } = await import("./list-
|
|
5772
|
+
const { registerListCommand } = await import("./list-50mepbed.js");
|
|
6786
5773
|
registerListCommand(program);
|
|
6787
5774
|
}
|
|
6788
5775
|
registerFeedsCommand(program);
|
|
@@ -6790,4 +5777,4 @@ var registerCommands = async (program) => {
|
|
|
6790
5777
|
|
|
6791
5778
|
export { metadata, registerCommands };
|
|
6792
5779
|
|
|
6793
|
-
//# debugId=
|
|
5780
|
+
//# debugId=4DC15BD6E15D8F5C64756E2164756E21
|