@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.
@@ -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
- }
@@ -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
- }