@uipath/packager-tool-webapp 1.202.0-preview.140 → 1.202.0-preview.142
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/package.json +4 -8
- package/src/constants.ts +0 -81
- package/src/index.ts +0 -9
- package/src/models/webapp-manifest.ts +0 -46
- package/src/strategies/coded-app-strategy.ts +0 -475
- package/src/strategies/js-apps-strategy.ts +0 -378
- package/src/strategies/variant-strategy-factory.ts +0 -38
- package/src/strategies/variant-strategy.ts +0 -67
- package/src/utils/fs-helpers.ts +0 -58
- package/src/utils/manifest-loader.ts +0 -63
- package/src/webapp-tool-factory.ts +0 -23
- package/src/webapp-tool.ts +0 -269
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
IFileSystem,
|
|
3
|
-
OperateFileModel,
|
|
4
|
-
PackageDescriptorFileModel,
|
|
5
|
-
} from "@uipath/solutionpackager-tool-core";
|
|
6
|
-
import {
|
|
7
|
-
NugetConstants,
|
|
8
|
-
NugetPackager,
|
|
9
|
-
Path,
|
|
10
|
-
ProjectTypes,
|
|
11
|
-
TargetFramework,
|
|
12
|
-
} from "@uipath/solutionpackager-tool-core";
|
|
13
|
-
import {
|
|
14
|
-
APP_FOLDER_NAME,
|
|
15
|
-
CONTENT_APP_FOLDER_NAME,
|
|
16
|
-
DEFAULT_ENTRY_POINT_TYPE,
|
|
17
|
-
ERROR_MESSAGES,
|
|
18
|
-
TARGET_JS_RUNTIME,
|
|
19
|
-
} from "../constants.js";
|
|
20
|
-
import type { WebAppManifest } from "../models/webapp-manifest.js";
|
|
21
|
-
import { WEBAPP_MANIFEST_FILE_NAME } from "../models/webapp-manifest.js";
|
|
22
|
-
import { copyDirectoryAsync } from "../utils/fs-helpers.js";
|
|
23
|
-
import { ensureWebAppProjectId } from "../utils/manifest-loader.js";
|
|
24
|
-
import type { PackageArgs, VariantStrategy } from "./variant-strategy.js";
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* JS apps strategy for the JS variant.
|
|
28
|
-
* Packages a pre-built `.app` folder whose contents are placed under `content/app`
|
|
29
|
-
* in the resulting .nupkg.
|
|
30
|
-
*/
|
|
31
|
-
export class JsAppsStrategy implements VariantStrategy {
|
|
32
|
-
constructor(private readonly fileSystem: IFileSystem) {}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Variant-specific validation: warn if the `.app` folder is missing or not a directory.
|
|
36
|
-
* Bundle path from the manifest is intentionally ignored for this variant.
|
|
37
|
-
*/
|
|
38
|
-
async validateAsync(args: {
|
|
39
|
-
fileSystem: IFileSystem;
|
|
40
|
-
projectPath: string;
|
|
41
|
-
manifest: WebAppManifest;
|
|
42
|
-
logger?: {
|
|
43
|
-
info: (message: string) => void;
|
|
44
|
-
error: (message: string) => void;
|
|
45
|
-
progress: (message: string) => void;
|
|
46
|
-
warn?: (message: string) => void;
|
|
47
|
-
};
|
|
48
|
-
}): Promise<void> {
|
|
49
|
-
const { projectPath, logger } = args;
|
|
50
|
-
const appFolder = Path.join(projectPath, APP_FOLDER_NAME);
|
|
51
|
-
|
|
52
|
-
const exists = await this.fileSystem.exists(appFolder);
|
|
53
|
-
if (!exists) {
|
|
54
|
-
const message = ERROR_MESSAGES.APP_FOLDER_NOT_FOUND(appFolder);
|
|
55
|
-
if (logger?.warn) {
|
|
56
|
-
logger.warn(message);
|
|
57
|
-
} else {
|
|
58
|
-
logger?.info(`Warning: ${message}`);
|
|
59
|
-
}
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const stat = await this.fileSystem.stat(appFolder);
|
|
64
|
-
if (!stat?.isDirectory()) {
|
|
65
|
-
const message = ERROR_MESSAGES.APP_FOLDER_NOT_DIRECTORY(appFolder);
|
|
66
|
-
if (logger?.warn) {
|
|
67
|
-
logger.warn(message);
|
|
68
|
-
} else {
|
|
69
|
-
logger?.info(`Warning: ${message}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async packageAsync(args: PackageArgs): Promise<string> {
|
|
75
|
-
const { projectPath, manifest, outputPath, packageInfo, logger } = args;
|
|
76
|
-
|
|
77
|
-
logger?.info(
|
|
78
|
-
`Packaging JS variant: ${packageInfo.id}@${packageInfo.version}`,
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
const appFolder = Path.join(projectPath, APP_FOLDER_NAME);
|
|
82
|
-
|
|
83
|
-
logger?.progress("Validating .app folder...");
|
|
84
|
-
const appFolderExists = await this.fileSystem.exists(appFolder);
|
|
85
|
-
if (!appFolderExists) {
|
|
86
|
-
throw new Error(ERROR_MESSAGES.APP_FOLDER_NOT_FOUND(appFolder));
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const appFolderStat = await this.fileSystem.stat(appFolder);
|
|
90
|
-
if (!appFolderStat?.isDirectory()) {
|
|
91
|
-
throw new Error(ERROR_MESSAGES.APP_FOLDER_NOT_DIRECTORY(appFolder));
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Bundle directory structure: <output>/bundle/content/app
|
|
95
|
-
const localBuildFolder = Path.join(
|
|
96
|
-
outputPath,
|
|
97
|
-
NugetConstants.OutputFolderName,
|
|
98
|
-
);
|
|
99
|
-
const contentFolder = Path.join(
|
|
100
|
-
localBuildFolder,
|
|
101
|
-
NugetConstants.ContentFolderName,
|
|
102
|
-
);
|
|
103
|
-
const contentAppFolder = Path.join(
|
|
104
|
-
contentFolder,
|
|
105
|
-
CONTENT_APP_FOLDER_NAME,
|
|
106
|
-
);
|
|
107
|
-
await this.fileSystem.mkdir(contentFolder);
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
// Copy contents of .app into content/app
|
|
111
|
-
logger?.progress("Copying .app folder into content/app...");
|
|
112
|
-
await copyDirectoryAsync(
|
|
113
|
-
this.fileSystem,
|
|
114
|
-
appFolder,
|
|
115
|
-
contentAppFolder,
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
logger?.progress("Preparing metadata files...");
|
|
119
|
-
await this.prepareMetadataFiles(
|
|
120
|
-
contentFolder,
|
|
121
|
-
contentAppFolder,
|
|
122
|
-
packageInfo,
|
|
123
|
-
manifest,
|
|
124
|
-
projectPath,
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
logger?.progress("Creating NuGet package...");
|
|
128
|
-
const nupkgFileName = `${packageInfo.id}.${packageInfo.version}.nupkg`;
|
|
129
|
-
const nupkgPath = Path.join(outputPath, nupkgFileName);
|
|
130
|
-
|
|
131
|
-
const packager = new NugetPackager(this.fileSystem);
|
|
132
|
-
const result = await packager.packAsync(
|
|
133
|
-
localBuildFolder,
|
|
134
|
-
packageInfo,
|
|
135
|
-
nupkgPath,
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
logger?.info(`Package created successfully: ${result.outputPath}`);
|
|
139
|
-
return result.outputPath;
|
|
140
|
-
} finally {
|
|
141
|
-
try {
|
|
142
|
-
await this.fileSystem.rm(localBuildFolder);
|
|
143
|
-
} catch (cleanupError) {
|
|
144
|
-
logger?.error(
|
|
145
|
-
`Failed to cleanup build folder: ${
|
|
146
|
-
cleanupError instanceof Error
|
|
147
|
-
? cleanupError.message
|
|
148
|
-
: String(cleanupError)
|
|
149
|
-
}`,
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Prepare metadata files (operate.json, package-descriptor.json, bindings.json, bindings_v2.json, entry-points.json)
|
|
157
|
-
*/
|
|
158
|
-
private async prepareMetadataFiles(
|
|
159
|
-
contentFolder: string,
|
|
160
|
-
_contentAppFolder: string,
|
|
161
|
-
_packageInfo: {
|
|
162
|
-
id: string;
|
|
163
|
-
version: string;
|
|
164
|
-
author?: string;
|
|
165
|
-
description?: string;
|
|
166
|
-
},
|
|
167
|
-
_manifest: WebAppManifest,
|
|
168
|
-
projectPath: string,
|
|
169
|
-
): Promise<void> {
|
|
170
|
-
const mainFile = "index.html";
|
|
171
|
-
|
|
172
|
-
// Path referenced from within the package content folder
|
|
173
|
-
const mainRelativeToContent = `${CONTENT_APP_FOLDER_NAME}/${mainFile}`;
|
|
174
|
-
|
|
175
|
-
// operate.json in content folder
|
|
176
|
-
const operatePath = Path.join(
|
|
177
|
-
contentFolder,
|
|
178
|
-
NugetConstants.OperateFileName,
|
|
179
|
-
);
|
|
180
|
-
const operateModel: OperateFileModel & { targetRuntime: string } = {
|
|
181
|
-
projectId: await ensureWebAppProjectId(
|
|
182
|
-
this.fileSystem,
|
|
183
|
-
projectPath,
|
|
184
|
-
),
|
|
185
|
-
main: mainRelativeToContent,
|
|
186
|
-
contentType: ProjectTypes.WebApp,
|
|
187
|
-
targetFramework: TargetFramework.Portable,
|
|
188
|
-
targetRuntime: TARGET_JS_RUNTIME,
|
|
189
|
-
runtimeOptions: {
|
|
190
|
-
requiresUserInteraction: false,
|
|
191
|
-
isAttended: false,
|
|
192
|
-
},
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
const operateJson = JSON.stringify(operateModel, null, 2);
|
|
196
|
-
await this.fileSystem.writeFile(operatePath, operateJson);
|
|
197
|
-
|
|
198
|
-
// Copy webAppManifest.json from project root into content (as-is)
|
|
199
|
-
const manifestSourcePath = Path.join(
|
|
200
|
-
projectPath,
|
|
201
|
-
WEBAPP_MANIFEST_FILE_NAME,
|
|
202
|
-
);
|
|
203
|
-
const manifestDestPath = Path.join(
|
|
204
|
-
contentFolder,
|
|
205
|
-
WEBAPP_MANIFEST_FILE_NAME,
|
|
206
|
-
);
|
|
207
|
-
const manifestExists = await this.fileSystem.exists(manifestSourcePath);
|
|
208
|
-
if (manifestExists) {
|
|
209
|
-
const manifestContent =
|
|
210
|
-
await this.fileSystem.readFile(manifestSourcePath);
|
|
211
|
-
if (manifestContent) {
|
|
212
|
-
await this.fileSystem.writeFile(
|
|
213
|
-
manifestDestPath,
|
|
214
|
-
manifestContent,
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Copy uipath.json from project root into content (if it exists)
|
|
220
|
-
const uipathJsonSourcePath = Path.join(projectPath, "uipath.json");
|
|
221
|
-
const uipathJsonDestPath = Path.join(contentFolder, "uipath.json");
|
|
222
|
-
const uipathJsonExists =
|
|
223
|
-
await this.fileSystem.exists(uipathJsonSourcePath);
|
|
224
|
-
if (uipathJsonExists) {
|
|
225
|
-
const uipathJsonContent =
|
|
226
|
-
await this.fileSystem.readFile(uipathJsonSourcePath);
|
|
227
|
-
if (uipathJsonContent) {
|
|
228
|
-
await this.fileSystem.writeFile(
|
|
229
|
-
uipathJsonDestPath,
|
|
230
|
-
uipathJsonContent,
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Create or copy bindings.json (version 1.0)
|
|
236
|
-
const bindingsPath = Path.join(contentFolder, "bindings.json");
|
|
237
|
-
const bindingsExists = await this.fileSystem.exists(bindingsPath);
|
|
238
|
-
if (!bindingsExists) {
|
|
239
|
-
const bindingsJson = JSON.stringify(
|
|
240
|
-
{ version: "1.0", resources: [] },
|
|
241
|
-
null,
|
|
242
|
-
2,
|
|
243
|
-
);
|
|
244
|
-
await this.fileSystem.writeFile(bindingsPath, bindingsJson);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Create or copy bindings_v2.json (version 2.0)
|
|
248
|
-
const bindingsV2Path = Path.join(contentFolder, "bindings_v2.json");
|
|
249
|
-
const bindingsV2Exists = await this.fileSystem.exists(bindingsV2Path);
|
|
250
|
-
if (!bindingsV2Exists) {
|
|
251
|
-
const bindingsV2Json = JSON.stringify(
|
|
252
|
-
{ version: "2.0", resources: [] },
|
|
253
|
-
null,
|
|
254
|
-
2,
|
|
255
|
-
);
|
|
256
|
-
await this.fileSystem.writeFile(bindingsV2Path, bindingsV2Json);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Create or copy entry-points.json
|
|
260
|
-
const entryPointsPath = Path.join(contentFolder, "entry-points.json");
|
|
261
|
-
const projectEntryPointsPath = Path.join(
|
|
262
|
-
projectPath,
|
|
263
|
-
"entry-points.json",
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
let entryPointsContent: string;
|
|
267
|
-
const projectEntryPointsExists = await this.fileSystem.exists(
|
|
268
|
-
projectEntryPointsPath,
|
|
269
|
-
);
|
|
270
|
-
if (projectEntryPointsExists) {
|
|
271
|
-
const entryPointsData = await this.fileSystem.readFile(
|
|
272
|
-
projectEntryPointsPath,
|
|
273
|
-
);
|
|
274
|
-
if (entryPointsData) {
|
|
275
|
-
entryPointsContent = new TextDecoder().decode(entryPointsData);
|
|
276
|
-
} else {
|
|
277
|
-
entryPointsContent = this.createDefaultEntryPoints(
|
|
278
|
-
mainRelativeToContent,
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
} else {
|
|
282
|
-
entryPointsContent = this.createDefaultEntryPoints(
|
|
283
|
-
mainRelativeToContent,
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
await this.fileSystem.writeFile(entryPointsPath, entryPointsContent);
|
|
288
|
-
|
|
289
|
-
// Create package-descriptor.json in content folder
|
|
290
|
-
const packageDescriptorPath = Path.join(
|
|
291
|
-
contentFolder,
|
|
292
|
-
NugetConstants.PackageDescriptorFileName,
|
|
293
|
-
);
|
|
294
|
-
const packageDescriptor: PackageDescriptorFileModel = {
|
|
295
|
-
files: {
|
|
296
|
-
[NugetConstants.OperateFileName]: Path.join(
|
|
297
|
-
NugetConstants.ContentFolderName,
|
|
298
|
-
NugetConstants.OperateFileName,
|
|
299
|
-
),
|
|
300
|
-
"entry-points.json": Path.join(
|
|
301
|
-
NugetConstants.ContentFolderName,
|
|
302
|
-
"entry-points.json",
|
|
303
|
-
),
|
|
304
|
-
"bindings.json": Path.join(
|
|
305
|
-
NugetConstants.ContentFolderName,
|
|
306
|
-
"bindings_v2.json",
|
|
307
|
-
),
|
|
308
|
-
},
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
const packageDescriptorJson = JSON.stringify(
|
|
312
|
-
packageDescriptor,
|
|
313
|
-
null,
|
|
314
|
-
2,
|
|
315
|
-
);
|
|
316
|
-
await this.fileSystem.writeFile(
|
|
317
|
-
packageDescriptorPath,
|
|
318
|
-
packageDescriptorJson,
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Create default entry-points.json structure
|
|
324
|
-
*/
|
|
325
|
-
private createDefaultEntryPoints(mainFilePath: string): string {
|
|
326
|
-
const uniqueId = this.generateUniqueId();
|
|
327
|
-
|
|
328
|
-
const entryPoints = {
|
|
329
|
-
$schema: "https://cloud.uipath.com/draft/2024-12/entry-point",
|
|
330
|
-
$id: "entry-points-doc-001",
|
|
331
|
-
entryPoints: [
|
|
332
|
-
{
|
|
333
|
-
filePath: mainFilePath,
|
|
334
|
-
uniqueId: uniqueId,
|
|
335
|
-
type: DEFAULT_ENTRY_POINT_TYPE,
|
|
336
|
-
input: {
|
|
337
|
-
amount: { type: "integer" },
|
|
338
|
-
id: { type: "string" },
|
|
339
|
-
},
|
|
340
|
-
output: {
|
|
341
|
-
status: { type: "string" },
|
|
342
|
-
},
|
|
343
|
-
},
|
|
344
|
-
],
|
|
345
|
-
};
|
|
346
|
-
|
|
347
|
-
return JSON.stringify(entryPoints, null, 2);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Generate a cryptographically secure unique ID (UUID v4-like format)
|
|
352
|
-
*/
|
|
353
|
-
private generateUniqueId(): string {
|
|
354
|
-
const randomBytes = new Uint8Array(16);
|
|
355
|
-
|
|
356
|
-
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
357
|
-
crypto.getRandomValues(randomBytes);
|
|
358
|
-
} else {
|
|
359
|
-
throw new Error("crypto.getRandomValues is not available");
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Set version (4) and variant bits according to UUID v4 spec
|
|
363
|
-
randomBytes[6] = (randomBytes[6] & 0x0f) | 0x40;
|
|
364
|
-
randomBytes[8] = (randomBytes[8] & 0x3f) | 0x80;
|
|
365
|
-
|
|
366
|
-
const hex = Array.from(randomBytes)
|
|
367
|
-
.map((b) => b.toString(16).padStart(2, "0"))
|
|
368
|
-
.join("");
|
|
369
|
-
|
|
370
|
-
return [
|
|
371
|
-
hex.substring(0, 8),
|
|
372
|
-
hex.substring(8, 12),
|
|
373
|
-
hex.substring(12, 16),
|
|
374
|
-
hex.substring(16, 20),
|
|
375
|
-
hex.substring(20, 32),
|
|
376
|
-
].join("-");
|
|
377
|
-
}
|
|
378
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { IFileSystem } from "@uipath/solutionpackager-tool-core";
|
|
2
|
-
import type { WebAppManifest } from "../models/webapp-manifest.js";
|
|
3
|
-
import { WebAppVariantType } from "../models/webapp-manifest.js";
|
|
4
|
-
import { CodedAppStrategy } from "./coded-app-strategy.js";
|
|
5
|
-
import { JsAppsStrategy } from "./js-apps-strategy.js";
|
|
6
|
-
import type { VariantStrategy } from "./variant-strategy.js";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Factory for creating variant-specific packaging strategies
|
|
10
|
-
*/
|
|
11
|
-
export class VariantStrategyFactory {
|
|
12
|
-
/**
|
|
13
|
-
* Create a strategy instance based on manifest type
|
|
14
|
-
* @param manifest - WebApp manifest
|
|
15
|
-
* @param fileSystem - File system instance
|
|
16
|
-
* @returns Strategy instance
|
|
17
|
-
* @throws Error if variant is not supported
|
|
18
|
-
*/
|
|
19
|
-
static createStrategy(
|
|
20
|
-
manifest: WebAppManifest,
|
|
21
|
-
fileSystem: IFileSystem,
|
|
22
|
-
): VariantStrategy {
|
|
23
|
-
const variant = manifest.type;
|
|
24
|
-
|
|
25
|
-
switch (variant) {
|
|
26
|
-
case WebAppVariantType.Coded:
|
|
27
|
-
return new CodedAppStrategy(fileSystem);
|
|
28
|
-
|
|
29
|
-
case WebAppVariantType.JS:
|
|
30
|
-
return new JsAppsStrategy(fileSystem);
|
|
31
|
-
|
|
32
|
-
default:
|
|
33
|
-
throw new Error(
|
|
34
|
-
`Unknown WebApp variant: ${manifest.type}. Supported variants: ${Object.values(WebAppVariantType).join(", ")}`,
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
IFileSystem,
|
|
3
|
-
NugetPackageInfo,
|
|
4
|
-
} from "@uipath/solutionpackager-tool-core";
|
|
5
|
-
import type { WebAppManifest } from "../models/webapp-manifest.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Arguments for packaging operation
|
|
9
|
-
*/
|
|
10
|
-
export interface PackageArgs {
|
|
11
|
-
/**
|
|
12
|
-
* File system instance
|
|
13
|
-
*/
|
|
14
|
-
fileSystem: IFileSystem;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Project root path
|
|
18
|
-
*/
|
|
19
|
-
projectPath: string;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Parsed webApp manifest
|
|
23
|
-
*/
|
|
24
|
-
manifest: WebAppManifest;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Output directory path
|
|
28
|
-
*/
|
|
29
|
-
outputPath: string;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* NuGet package information
|
|
33
|
-
*/
|
|
34
|
-
packageInfo: NugetPackageInfo;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Logger instance (optional, for strategy-specific logging)
|
|
38
|
-
*/
|
|
39
|
-
logger?: {
|
|
40
|
-
info: (message: string) => void;
|
|
41
|
-
error: (message: string) => void;
|
|
42
|
-
progress: (message: string) => void;
|
|
43
|
-
warn?: (message: string) => void;
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Strategy interface for different WebApp variant packaging
|
|
49
|
-
*/
|
|
50
|
-
export interface VariantStrategy {
|
|
51
|
-
/**
|
|
52
|
-
* Package the WebApp according to variant-specific logic
|
|
53
|
-
* @param args - Packaging arguments
|
|
54
|
-
* @returns Path to the created .nupkg file
|
|
55
|
-
*/
|
|
56
|
-
packageAsync(args: PackageArgs): Promise<string>;
|
|
57
|
-
/**
|
|
58
|
-
* Optional variant-specific validation step invoked during tool validation.
|
|
59
|
-
* Implementations may warn or throw on invalid configuration.
|
|
60
|
-
*/
|
|
61
|
-
validateAsync?(args: {
|
|
62
|
-
fileSystem: PackageArgs["fileSystem"];
|
|
63
|
-
projectPath: string;
|
|
64
|
-
manifest: PackageArgs["manifest"];
|
|
65
|
-
logger?: PackageArgs["logger"];
|
|
66
|
-
}): Promise<void>;
|
|
67
|
-
}
|
package/src/utils/fs-helpers.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type { IFileSystem } from "@uipath/solutionpackager-tool-core";
|
|
2
|
-
import { Path } from "@uipath/solutionpackager-tool-core";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Copy directory recursively from source to destination
|
|
6
|
-
*/
|
|
7
|
-
export async function copyDirectoryAsync(
|
|
8
|
-
fileSystem: IFileSystem,
|
|
9
|
-
sourcePath: string,
|
|
10
|
-
destinationPath: string,
|
|
11
|
-
): Promise<void> {
|
|
12
|
-
await fileSystem.mkdir(destinationPath);
|
|
13
|
-
|
|
14
|
-
const entries = await fileSystem.readdir(sourcePath);
|
|
15
|
-
|
|
16
|
-
for (const entry of entries) {
|
|
17
|
-
const sourceEntry = Path.join(sourcePath, entry);
|
|
18
|
-
const destEntry = Path.join(destinationPath, entry);
|
|
19
|
-
|
|
20
|
-
const stat = await fileSystem.stat(sourceEntry);
|
|
21
|
-
if (stat?.isDirectory()) {
|
|
22
|
-
await copyDirectoryAsync(fileSystem, sourceEntry, destEntry);
|
|
23
|
-
} else if (stat?.isFile()) {
|
|
24
|
-
const content = await fileSystem.readFile(sourceEntry);
|
|
25
|
-
if (content) {
|
|
26
|
-
await fileSystem.writeFile(destEntry, content);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Find .nupkg file in a directory
|
|
34
|
-
*/
|
|
35
|
-
export async function findNupkgInFolder(
|
|
36
|
-
fileSystem: IFileSystem,
|
|
37
|
-
directoryPath: string,
|
|
38
|
-
): Promise<string | null> {
|
|
39
|
-
const entries = await fileSystem.readdir(directoryPath);
|
|
40
|
-
|
|
41
|
-
for (const entry of entries) {
|
|
42
|
-
const entryPath = Path.join(directoryPath, entry);
|
|
43
|
-
const stat = await fileSystem.stat(entryPath);
|
|
44
|
-
|
|
45
|
-
if (stat?.isFile() && entry.endsWith(".nupkg")) {
|
|
46
|
-
return entryPath;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (stat?.isDirectory()) {
|
|
50
|
-
const found = await findNupkgInFolder(fileSystem, entryPath);
|
|
51
|
-
if (found) {
|
|
52
|
-
return found;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import type { IFileSystem } from "@uipath/solutionpackager-tool-core";
|
|
2
|
-
import { Path } from "@uipath/solutionpackager-tool-core";
|
|
3
|
-
import type { WebAppManifest } from "../models/webapp-manifest.js";
|
|
4
|
-
import { WEBAPP_MANIFEST_FILE_NAME } from "../models/webapp-manifest.js";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Load and parse webAppManifest.json from project path
|
|
8
|
-
*/
|
|
9
|
-
export async function loadWebAppManifest(
|
|
10
|
-
fileSystem: IFileSystem,
|
|
11
|
-
projectPath: string,
|
|
12
|
-
): Promise<WebAppManifest | null> {
|
|
13
|
-
const manifestPath = Path.join(projectPath, WEBAPP_MANIFEST_FILE_NAME);
|
|
14
|
-
|
|
15
|
-
const exists = await fileSystem.exists(manifestPath);
|
|
16
|
-
if (!exists) {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const content = await fileSystem.readFile(manifestPath);
|
|
21
|
-
if (!content) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
const text = new TextDecoder().decode(content);
|
|
27
|
-
const manifest: WebAppManifest = JSON.parse(text);
|
|
28
|
-
return manifest;
|
|
29
|
-
} catch (error) {
|
|
30
|
-
throw new Error(
|
|
31
|
-
`Failed to parse ${WEBAPP_MANIFEST_FILE_NAME}: ${error instanceof Error ? error.message : String(error)}`,
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Resolve a stable projectId for a webapp, persisting it to
|
|
38
|
-
* webAppManifest.json so re-packs are stable.
|
|
39
|
-
*/
|
|
40
|
-
export async function ensureWebAppProjectId(
|
|
41
|
-
fileSystem: IFileSystem,
|
|
42
|
-
projectPath: string,
|
|
43
|
-
): Promise<string> {
|
|
44
|
-
const manifest = await loadWebAppManifest(fileSystem, projectPath);
|
|
45
|
-
if (
|
|
46
|
-
manifest &&
|
|
47
|
-
typeof manifest.projectId === "string" &&
|
|
48
|
-
manifest.projectId.length > 0
|
|
49
|
-
) {
|
|
50
|
-
return manifest.projectId;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const id = crypto.randomUUID();
|
|
54
|
-
if (manifest) {
|
|
55
|
-
const updated: WebAppManifest = { ...manifest, projectId: id };
|
|
56
|
-
const manifestPath = Path.join(projectPath, WEBAPP_MANIFEST_FILE_NAME);
|
|
57
|
-
await fileSystem.writeFile(
|
|
58
|
-
manifestPath,
|
|
59
|
-
`${JSON.stringify(updated, null, 2)}\n`,
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
return id;
|
|
63
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type IFileSystem,
|
|
3
|
-
type IProjectToolFactory,
|
|
4
|
-
type IToolLogger,
|
|
5
|
-
type ProjectTool,
|
|
6
|
-
type ProjectType,
|
|
7
|
-
ProjectTypes,
|
|
8
|
-
} from "@uipath/solutionpackager-tool-core";
|
|
9
|
-
import { WebAppTool } from "./webapp-tool.js";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Factory for creating WebApp project tools
|
|
13
|
-
*/
|
|
14
|
-
export class WebAppToolFactory implements IProjectToolFactory {
|
|
15
|
-
readonly supportedTypes: readonly ProjectType[] = [ProjectTypes.AppV2];
|
|
16
|
-
|
|
17
|
-
async createAsync(
|
|
18
|
-
logger: IToolLogger,
|
|
19
|
-
fileSystem: IFileSystem,
|
|
20
|
-
): Promise<ProjectTool> {
|
|
21
|
-
return new WebAppTool(fileSystem, logger);
|
|
22
|
-
}
|
|
23
|
-
}
|