@uipath/packager-tool-webapp 1.0.4 → 1.196.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +14 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +224 -13
- package/dist/strategies/js-apps-strategy.d.ts +40 -0
- package/package.json +11 -27
- package/src/constants.ts +21 -0
- package/src/index.ts +5 -0
- package/src/strategies/coded-app-strategy.ts +28 -4
- package/src/strategies/js-apps-strategy.ts +374 -0
- package/src/strategies/variant-strategy-factory.ts +2 -3
package/dist/constants.d.ts
CHANGED
|
@@ -9,10 +9,22 @@ export declare const PROJECT_JSON_FILE = "project.json";
|
|
|
9
9
|
* Default bundle path if not specified in manifest
|
|
10
10
|
*/
|
|
11
11
|
export declare const DEFAULT_BUNDLE_PATH = "source/dist";
|
|
12
|
+
/**
|
|
13
|
+
* Pre-built app folder for the JS variant (source)
|
|
14
|
+
*/
|
|
15
|
+
export declare const APP_FOLDER_NAME = ".app";
|
|
16
|
+
/**
|
|
17
|
+
* Destination folder inside the NuGet content folder for the JS variant
|
|
18
|
+
*/
|
|
19
|
+
export declare const CONTENT_APP_FOLDER_NAME = "app";
|
|
12
20
|
/**
|
|
13
21
|
* Target runtime for operate.json
|
|
14
22
|
*/
|
|
15
23
|
export declare const TARGET_RUNTIME = "Coded";
|
|
24
|
+
/**
|
|
25
|
+
* Target runtime for operate.json
|
|
26
|
+
*/
|
|
27
|
+
export declare const TARGET_JS_RUNTIME = "JS";
|
|
16
28
|
/**
|
|
17
29
|
* Default entry point type
|
|
18
30
|
*/
|
|
@@ -26,6 +38,8 @@ export declare const ERROR_MESSAGES: {
|
|
|
26
38
|
readonly MANIFEST_LOAD_FAILED: (file: string) => string;
|
|
27
39
|
readonly BUNDLE_NOT_FOUND: (path: string) => string;
|
|
28
40
|
readonly BUNDLE_NOT_DIRECTORY: (path: string) => string;
|
|
41
|
+
readonly APP_FOLDER_NOT_FOUND: (path: string) => string;
|
|
42
|
+
readonly APP_FOLDER_NOT_DIRECTORY: (path: string) => string;
|
|
29
43
|
readonly BUILD_NOT_SUPPORTED: "Build execution (isCompiled=false) is not yet supported. Please build the project manually and set isCompiled=true.";
|
|
30
44
|
readonly VALIDATION_FAILED: (context: string) => string;
|
|
31
45
|
readonly PACKING_FAILED: (context: string) => string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
export type { WebAppManifest } from "./models/webapp-manifest.js";
|
|
2
|
+
export { WEBAPP_MANIFEST_FILE_NAME, WebAppVariantType, } from "./models/webapp-manifest.js";
|
|
1
3
|
export { WebAppTool } from "./webapp-tool.js";
|
|
2
4
|
export { WebAppToolFactory } from "./webapp-tool-factory.js";
|
package/dist/index.js
CHANGED
|
@@ -3,12 +3,12 @@ import { toolsFactoryRepository } from "@uipath/solutionpackager-tool-core";
|
|
|
3
3
|
|
|
4
4
|
// src/webapp-tool-factory.ts
|
|
5
5
|
import {
|
|
6
|
-
ProjectTypes as
|
|
6
|
+
ProjectTypes as ProjectTypes3
|
|
7
7
|
} from "@uipath/solutionpackager-tool-core";
|
|
8
8
|
|
|
9
9
|
// src/webapp-tool.ts
|
|
10
10
|
import {
|
|
11
|
-
Path as
|
|
11
|
+
Path as Path5,
|
|
12
12
|
ProjectTool,
|
|
13
13
|
TemporaryStorageService,
|
|
14
14
|
ToolErrorCodes,
|
|
@@ -18,7 +18,10 @@ import {
|
|
|
18
18
|
// src/constants.ts
|
|
19
19
|
var PROJECT_JSON_FILE = "project.json";
|
|
20
20
|
var DEFAULT_BUNDLE_PATH = "source/dist";
|
|
21
|
+
var APP_FOLDER_NAME = ".app";
|
|
22
|
+
var CONTENT_APP_FOLDER_NAME = "app";
|
|
21
23
|
var TARGET_RUNTIME = "Coded";
|
|
24
|
+
var TARGET_JS_RUNTIME = "JS";
|
|
22
25
|
var DEFAULT_ENTRY_POINT_TYPE = "api";
|
|
23
26
|
var ERROR_MESSAGES = {
|
|
24
27
|
MANIFEST_NOT_FOUND: (file) => `WebApp manifest not found: ${file}. This file is required for WebApp projects.`,
|
|
@@ -26,6 +29,8 @@ var ERROR_MESSAGES = {
|
|
|
26
29
|
MANIFEST_LOAD_FAILED: (file) => `Failed to load or parse ${file}`,
|
|
27
30
|
BUNDLE_NOT_FOUND: (path) => `Compiled bundle not found at ${path}. Ensure the project is built before packing.`,
|
|
28
31
|
BUNDLE_NOT_DIRECTORY: (path) => `Bundle path ${path} exists but is not a directory.`,
|
|
32
|
+
APP_FOLDER_NOT_FOUND: (path) => `.app folder not found at ${path}. Ensure the project contains a .app folder.`,
|
|
33
|
+
APP_FOLDER_NOT_DIRECTORY: (path) => `.app path ${path} exists but is not a directory.`,
|
|
29
34
|
BUILD_NOT_SUPPORTED: "Build execution (isCompiled=false) is not yet supported. Please build the project manually and set isCompiled=true.",
|
|
30
35
|
VALIDATION_FAILED: (context) => `Validation failed: ${context}`,
|
|
31
36
|
PACKING_FAILED: (context) => `An error occurred while packing WebApp project: ${context}`,
|
|
@@ -201,14 +206,29 @@ class CodedAppStrategy {
|
|
|
201
206
|
await this.fileSystem.writeFile(bindingsPath, bindingsJson);
|
|
202
207
|
}
|
|
203
208
|
const bindingsV2Path = Path2.join(contentFolder, "bindings_v2.json");
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
209
|
+
const bindingsCandidatePaths = [
|
|
210
|
+
Path2.join(projectPath, "source", "bindings.json"),
|
|
211
|
+
Path2.join(projectPath, "bindings.json"),
|
|
212
|
+
Path2.join(projectPath, "bindings_v2.json")
|
|
213
|
+
];
|
|
214
|
+
let bindingsV2Json = null;
|
|
215
|
+
for (const candidate of bindingsCandidatePaths) {
|
|
216
|
+
if (await this.fileSystem.exists(candidate)) {
|
|
217
|
+
bindingsV2Json = await this.fileSystem.readFile(candidate, "utf-8");
|
|
218
|
+
if (bindingsV2Json)
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (!bindingsV2Json && await this.fileSystem.exists(bindingsV2Path)) {
|
|
223
|
+
bindingsV2Json = await this.fileSystem.readFile(bindingsV2Path, "utf-8");
|
|
224
|
+
}
|
|
225
|
+
if (!bindingsV2Json) {
|
|
226
|
+
bindingsV2Json = JSON.stringify({
|
|
207
227
|
version: "2.0",
|
|
208
228
|
resources: []
|
|
209
229
|
}, null, 2);
|
|
210
|
-
await this.fileSystem.writeFile(bindingsV2Path, bindingsV2Json);
|
|
211
230
|
}
|
|
231
|
+
await this.fileSystem.writeFile(bindingsV2Path, bindingsV2Json);
|
|
212
232
|
const entryPointsPath = Path2.join(contentFolder, "entry-points.json");
|
|
213
233
|
const projectEntryPointsPath = Path2.join(projectPath, "entry-points.json");
|
|
214
234
|
let entryPointsContent;
|
|
@@ -226,6 +246,7 @@ class CodedAppStrategy {
|
|
|
226
246
|
await this.fileSystem.writeFile(entryPointsPath, entryPointsContent);
|
|
227
247
|
const packageDescriptorPath = Path2.join(contentFolder, NugetConstants.PackageDescriptorFileName);
|
|
228
248
|
const packageDescriptor = {
|
|
249
|
+
$schema: "https://cloud.uipath.com/draft/2024-12/package-descriptor",
|
|
229
250
|
files: {
|
|
230
251
|
[NugetConstants.OperateFileName]: Path2.join(NugetConstants.ContentFolderName, NugetConstants.OperateFileName),
|
|
231
252
|
"entry-points.json": Path2.join(NugetConstants.ContentFolderName, "entry-points.json"),
|
|
@@ -277,6 +298,194 @@ class CodedAppStrategy {
|
|
|
277
298
|
}
|
|
278
299
|
}
|
|
279
300
|
|
|
301
|
+
// src/strategies/js-apps-strategy.ts
|
|
302
|
+
import {
|
|
303
|
+
NugetConstants as NugetConstants2,
|
|
304
|
+
NugetPackager as NugetPackager2,
|
|
305
|
+
Path as Path3,
|
|
306
|
+
ProjectTypes as ProjectTypes2,
|
|
307
|
+
TargetFramework as TargetFramework2
|
|
308
|
+
} from "@uipath/solutionpackager-tool-core";
|
|
309
|
+
class JsAppsStrategy {
|
|
310
|
+
fileSystem;
|
|
311
|
+
constructor(fileSystem) {
|
|
312
|
+
this.fileSystem = fileSystem;
|
|
313
|
+
}
|
|
314
|
+
async validateAsync(args) {
|
|
315
|
+
const { projectPath, logger } = args;
|
|
316
|
+
const appFolder = Path3.join(projectPath, APP_FOLDER_NAME);
|
|
317
|
+
const exists = await this.fileSystem.exists(appFolder);
|
|
318
|
+
if (!exists) {
|
|
319
|
+
const message = ERROR_MESSAGES.APP_FOLDER_NOT_FOUND(appFolder);
|
|
320
|
+
if (logger?.warn) {
|
|
321
|
+
logger.warn(message);
|
|
322
|
+
} else {
|
|
323
|
+
logger?.info(`Warning: ${message}`);
|
|
324
|
+
}
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const stat = await this.fileSystem.stat(appFolder);
|
|
328
|
+
if (!stat?.isDirectory()) {
|
|
329
|
+
const message = ERROR_MESSAGES.APP_FOLDER_NOT_DIRECTORY(appFolder);
|
|
330
|
+
if (logger?.warn) {
|
|
331
|
+
logger.warn(message);
|
|
332
|
+
} else {
|
|
333
|
+
logger?.info(`Warning: ${message}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
async packageAsync(args) {
|
|
338
|
+
const { projectPath, manifest, outputPath, packageInfo, logger } = args;
|
|
339
|
+
logger?.info(`Packaging JS variant: ${packageInfo.id}@${packageInfo.version}`);
|
|
340
|
+
const appFolder = Path3.join(projectPath, APP_FOLDER_NAME);
|
|
341
|
+
logger?.progress("Validating .app folder...");
|
|
342
|
+
const appFolderExists = await this.fileSystem.exists(appFolder);
|
|
343
|
+
if (!appFolderExists) {
|
|
344
|
+
throw new Error(ERROR_MESSAGES.APP_FOLDER_NOT_FOUND(appFolder));
|
|
345
|
+
}
|
|
346
|
+
const appFolderStat = await this.fileSystem.stat(appFolder);
|
|
347
|
+
if (!appFolderStat?.isDirectory()) {
|
|
348
|
+
throw new Error(ERROR_MESSAGES.APP_FOLDER_NOT_DIRECTORY(appFolder));
|
|
349
|
+
}
|
|
350
|
+
const localBuildFolder = Path3.join(outputPath, NugetConstants2.OutputFolderName);
|
|
351
|
+
const contentFolder = Path3.join(localBuildFolder, NugetConstants2.ContentFolderName);
|
|
352
|
+
const contentAppFolder = Path3.join(contentFolder, CONTENT_APP_FOLDER_NAME);
|
|
353
|
+
await this.fileSystem.mkdir(contentFolder);
|
|
354
|
+
try {
|
|
355
|
+
logger?.progress("Copying .app folder into content/app...");
|
|
356
|
+
await copyDirectoryAsync(this.fileSystem, appFolder, contentAppFolder);
|
|
357
|
+
logger?.progress("Preparing metadata files...");
|
|
358
|
+
await this.prepareMetadataFiles(contentFolder, contentAppFolder, packageInfo, manifest, projectPath);
|
|
359
|
+
logger?.progress("Creating NuGet package...");
|
|
360
|
+
const nupkgFileName = `${packageInfo.id}.${packageInfo.version}.nupkg`;
|
|
361
|
+
const nupkgPath = Path3.join(outputPath, nupkgFileName);
|
|
362
|
+
const packager = new NugetPackager2(this.fileSystem);
|
|
363
|
+
const result = await packager.packAsync(localBuildFolder, packageInfo, nupkgPath);
|
|
364
|
+
logger?.info(`Package created successfully: ${result.outputPath}`);
|
|
365
|
+
return result.outputPath;
|
|
366
|
+
} finally {
|
|
367
|
+
try {
|
|
368
|
+
await this.fileSystem.rm(localBuildFolder);
|
|
369
|
+
} catch (cleanupError) {
|
|
370
|
+
logger?.error(`Failed to cleanup build folder: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
async prepareMetadataFiles(contentFolder, contentAppFolder, packageInfo, _manifest, projectPath) {
|
|
375
|
+
const mainFile = "index.html";
|
|
376
|
+
const mainRelativeToContent = `${CONTENT_APP_FOLDER_NAME}/${mainFile}`;
|
|
377
|
+
const operatePath = Path3.join(contentFolder, NugetConstants2.OperateFileName);
|
|
378
|
+
const operateModel = {
|
|
379
|
+
projectId: packageInfo.id,
|
|
380
|
+
main: mainRelativeToContent,
|
|
381
|
+
contentType: ProjectTypes2.WebApp,
|
|
382
|
+
targetFramework: TargetFramework2.Portable,
|
|
383
|
+
targetRuntime: TARGET_JS_RUNTIME,
|
|
384
|
+
runtimeOptions: {
|
|
385
|
+
requiresUserInteraction: false,
|
|
386
|
+
isAttended: false
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
const operateJson = JSON.stringify(operateModel, null, 2);
|
|
390
|
+
await this.fileSystem.writeFile(operatePath, operateJson);
|
|
391
|
+
const manifestSourcePath = Path3.join(projectPath, WEBAPP_MANIFEST_FILE_NAME);
|
|
392
|
+
const manifestDestPath = Path3.join(contentFolder, WEBAPP_MANIFEST_FILE_NAME);
|
|
393
|
+
const manifestExists = await this.fileSystem.exists(manifestSourcePath);
|
|
394
|
+
if (manifestExists) {
|
|
395
|
+
const manifestContent = await this.fileSystem.readFile(manifestSourcePath);
|
|
396
|
+
if (manifestContent) {
|
|
397
|
+
await this.fileSystem.writeFile(manifestDestPath, manifestContent);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
const uipathJsonSourcePath = Path3.join(projectPath, "uipath.json");
|
|
401
|
+
const uipathJsonDestPath = Path3.join(contentFolder, "uipath.json");
|
|
402
|
+
const uipathJsonExists = await this.fileSystem.exists(uipathJsonSourcePath);
|
|
403
|
+
if (uipathJsonExists) {
|
|
404
|
+
const uipathJsonContent = await this.fileSystem.readFile(uipathJsonSourcePath);
|
|
405
|
+
if (uipathJsonContent) {
|
|
406
|
+
await this.fileSystem.writeFile(uipathJsonDestPath, uipathJsonContent);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
const bindingsPath = Path3.join(contentFolder, "bindings.json");
|
|
410
|
+
const bindingsExists = await this.fileSystem.exists(bindingsPath);
|
|
411
|
+
if (!bindingsExists) {
|
|
412
|
+
const bindingsJson = JSON.stringify({ version: "1.0", resources: [] }, null, 2);
|
|
413
|
+
await this.fileSystem.writeFile(bindingsPath, bindingsJson);
|
|
414
|
+
}
|
|
415
|
+
const bindingsV2Path = Path3.join(contentFolder, "bindings_v2.json");
|
|
416
|
+
const bindingsV2Exists = await this.fileSystem.exists(bindingsV2Path);
|
|
417
|
+
if (!bindingsV2Exists) {
|
|
418
|
+
const bindingsV2Json = JSON.stringify({ version: "2.0", resources: [] }, null, 2);
|
|
419
|
+
await this.fileSystem.writeFile(bindingsV2Path, bindingsV2Json);
|
|
420
|
+
}
|
|
421
|
+
const entryPointsPath = Path3.join(contentFolder, "entry-points.json");
|
|
422
|
+
const projectEntryPointsPath = Path3.join(projectPath, "entry-points.json");
|
|
423
|
+
let entryPointsContent;
|
|
424
|
+
const projectEntryPointsExists = await this.fileSystem.exists(projectEntryPointsPath);
|
|
425
|
+
if (projectEntryPointsExists) {
|
|
426
|
+
const entryPointsData = await this.fileSystem.readFile(projectEntryPointsPath);
|
|
427
|
+
if (entryPointsData) {
|
|
428
|
+
entryPointsContent = new TextDecoder().decode(entryPointsData);
|
|
429
|
+
} else {
|
|
430
|
+
entryPointsContent = this.createDefaultEntryPoints(mainRelativeToContent);
|
|
431
|
+
}
|
|
432
|
+
} else {
|
|
433
|
+
entryPointsContent = this.createDefaultEntryPoints(mainRelativeToContent);
|
|
434
|
+
}
|
|
435
|
+
await this.fileSystem.writeFile(entryPointsPath, entryPointsContent);
|
|
436
|
+
const packageDescriptorPath = Path3.join(contentFolder, NugetConstants2.PackageDescriptorFileName);
|
|
437
|
+
const packageDescriptor = {
|
|
438
|
+
files: {
|
|
439
|
+
[NugetConstants2.OperateFileName]: Path3.join(NugetConstants2.ContentFolderName, NugetConstants2.OperateFileName),
|
|
440
|
+
"entry-points.json": Path3.join(NugetConstants2.ContentFolderName, "entry-points.json"),
|
|
441
|
+
"bindings.json": Path3.join(NugetConstants2.ContentFolderName, "bindings_v2.json")
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
const packageDescriptorJson = JSON.stringify(packageDescriptor, null, 2);
|
|
445
|
+
await this.fileSystem.writeFile(packageDescriptorPath, packageDescriptorJson);
|
|
446
|
+
}
|
|
447
|
+
createDefaultEntryPoints(mainFilePath) {
|
|
448
|
+
const uniqueId = this.generateUniqueId();
|
|
449
|
+
const entryPoints = {
|
|
450
|
+
$schema: "https://cloud.uipath.com/draft/2024-12/entry-point",
|
|
451
|
+
$id: "entry-points-doc-001",
|
|
452
|
+
entryPoints: [
|
|
453
|
+
{
|
|
454
|
+
filePath: mainFilePath,
|
|
455
|
+
uniqueId,
|
|
456
|
+
type: DEFAULT_ENTRY_POINT_TYPE,
|
|
457
|
+
input: {
|
|
458
|
+
amount: { type: "integer" },
|
|
459
|
+
id: { type: "string" }
|
|
460
|
+
},
|
|
461
|
+
output: {
|
|
462
|
+
status: { type: "string" }
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
]
|
|
466
|
+
};
|
|
467
|
+
return JSON.stringify(entryPoints, null, 2);
|
|
468
|
+
}
|
|
469
|
+
generateUniqueId() {
|
|
470
|
+
const randomBytes = new Uint8Array(16);
|
|
471
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
472
|
+
crypto.getRandomValues(randomBytes);
|
|
473
|
+
} else {
|
|
474
|
+
throw new Error("crypto.getRandomValues is not available");
|
|
475
|
+
}
|
|
476
|
+
randomBytes[6] = randomBytes[6] & 15 | 64;
|
|
477
|
+
randomBytes[8] = randomBytes[8] & 63 | 128;
|
|
478
|
+
const hex = Array.from(randomBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
479
|
+
return [
|
|
480
|
+
hex.substring(0, 8),
|
|
481
|
+
hex.substring(8, 12),
|
|
482
|
+
hex.substring(12, 16),
|
|
483
|
+
hex.substring(16, 20),
|
|
484
|
+
hex.substring(20, 32)
|
|
485
|
+
].join("-");
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
280
489
|
// src/strategies/variant-strategy-factory.ts
|
|
281
490
|
class VariantStrategyFactory {
|
|
282
491
|
static createStrategy(manifest, fileSystem) {
|
|
@@ -285,7 +494,7 @@ class VariantStrategyFactory {
|
|
|
285
494
|
case "Coded" /* Coded */:
|
|
286
495
|
return new CodedAppStrategy(fileSystem);
|
|
287
496
|
case "JS" /* JS */:
|
|
288
|
-
|
|
497
|
+
return new JsAppsStrategy(fileSystem);
|
|
289
498
|
default:
|
|
290
499
|
throw new Error(`Unknown WebApp variant: ${manifest.type}. Supported variants: ${Object.values(WebAppVariantType).join(", ")}`);
|
|
291
500
|
}
|
|
@@ -293,9 +502,9 @@ class VariantStrategyFactory {
|
|
|
293
502
|
}
|
|
294
503
|
|
|
295
504
|
// src/utils/manifest-loader.ts
|
|
296
|
-
import { Path as
|
|
505
|
+
import { Path as Path4 } from "@uipath/solutionpackager-tool-core";
|
|
297
506
|
async function loadWebAppManifest(fileSystem, projectPath) {
|
|
298
|
-
const manifestPath =
|
|
507
|
+
const manifestPath = Path4.join(projectPath, WEBAPP_MANIFEST_FILE_NAME);
|
|
299
508
|
const exists = await fileSystem.exists(manifestPath);
|
|
300
509
|
if (!exists) {
|
|
301
510
|
return null;
|
|
@@ -411,12 +620,12 @@ class WebAppTool extends ProjectTool {
|
|
|
411
620
|
} catch {}
|
|
412
621
|
}
|
|
413
622
|
async getManifestAndStrategy(projectPath) {
|
|
414
|
-
const manifestPath =
|
|
623
|
+
const manifestPath = Path5.join(projectPath, WEBAPP_MANIFEST_FILE_NAME);
|
|
415
624
|
const manifestExists = await this.fileSystem.exists(manifestPath);
|
|
416
625
|
if (!manifestExists) {
|
|
417
626
|
throw new Error(ERROR_MESSAGES.MANIFEST_NOT_FOUND(WEBAPP_MANIFEST_FILE_NAME));
|
|
418
627
|
}
|
|
419
|
-
const projectJsonPath =
|
|
628
|
+
const projectJsonPath = Path5.join(projectPath, PROJECT_JSON_FILE);
|
|
420
629
|
if (await this.fileSystem.exists(projectJsonPath)) {
|
|
421
630
|
throw new Error(ERROR_MESSAGES.PROJECT_JSON_FOUND);
|
|
422
631
|
}
|
|
@@ -452,7 +661,7 @@ class WebAppTool extends ProjectTool {
|
|
|
452
661
|
|
|
453
662
|
// src/webapp-tool-factory.ts
|
|
454
663
|
class WebAppToolFactory {
|
|
455
|
-
supportedTypes = [
|
|
664
|
+
supportedTypes = [ProjectTypes3.AppV2];
|
|
456
665
|
async createAsync(logger, fileSystem) {
|
|
457
666
|
return new WebAppTool(fileSystem, logger);
|
|
458
667
|
}
|
|
@@ -461,6 +670,8 @@ class WebAppToolFactory {
|
|
|
461
670
|
// src/index.ts
|
|
462
671
|
toolsFactoryRepository.registerProjectToolFactory(new WebAppToolFactory);
|
|
463
672
|
export {
|
|
673
|
+
WebAppVariantType,
|
|
464
674
|
WebAppToolFactory,
|
|
465
|
-
WebAppTool
|
|
675
|
+
WebAppTool,
|
|
676
|
+
WEBAPP_MANIFEST_FILE_NAME
|
|
466
677
|
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { IFileSystem } from "@uipath/solutionpackager-tool-core";
|
|
2
|
+
import type { WebAppManifest } from "../models/webapp-manifest.js";
|
|
3
|
+
import type { PackageArgs, VariantStrategy } from "./variant-strategy.js";
|
|
4
|
+
/**
|
|
5
|
+
* JS apps strategy for the JS variant.
|
|
6
|
+
* Packages a pre-built `.app` folder whose contents are placed under `content/app`
|
|
7
|
+
* in the resulting .nupkg.
|
|
8
|
+
*/
|
|
9
|
+
export declare class JsAppsStrategy implements VariantStrategy {
|
|
10
|
+
private readonly fileSystem;
|
|
11
|
+
constructor(fileSystem: IFileSystem);
|
|
12
|
+
/**
|
|
13
|
+
* Variant-specific validation: warn if the `.app` folder is missing or not a directory.
|
|
14
|
+
* Bundle path from the manifest is intentionally ignored for this variant.
|
|
15
|
+
*/
|
|
16
|
+
validateAsync(args: {
|
|
17
|
+
fileSystem: IFileSystem;
|
|
18
|
+
projectPath: string;
|
|
19
|
+
manifest: WebAppManifest;
|
|
20
|
+
logger?: {
|
|
21
|
+
info: (message: string) => void;
|
|
22
|
+
error: (message: string) => void;
|
|
23
|
+
progress: (message: string) => void;
|
|
24
|
+
warn?: (message: string) => void;
|
|
25
|
+
};
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
packageAsync(args: PackageArgs): Promise<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Prepare metadata files (operate.json, package-descriptor.json, bindings.json, bindings_v2.json, entry-points.json)
|
|
30
|
+
*/
|
|
31
|
+
private prepareMetadataFiles;
|
|
32
|
+
/**
|
|
33
|
+
* Create default entry-points.json structure
|
|
34
|
+
*/
|
|
35
|
+
private createDefaultEntryPoints;
|
|
36
|
+
/**
|
|
37
|
+
* Generate a cryptographically secure unique ID (UUID v4-like format)
|
|
38
|
+
*/
|
|
39
|
+
private generateUniqueId;
|
|
40
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/packager-tool-webapp",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.196.0",
|
|
4
4
|
"description": "UiPath WebApp tool implementation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -18,23 +18,6 @@
|
|
|
18
18
|
"registry": "https://registry.npmjs.org/"
|
|
19
19
|
},
|
|
20
20
|
"types": "./dist/index.d.ts",
|
|
21
|
-
"scripts": {
|
|
22
|
-
"build": "bun build ./src/index.ts --outdir dist --format esm --target browser --external @uipath/solutionpackager-tool-core && tsc --emitDeclarationOnly --outDir dist",
|
|
23
|
-
"dev": "bun build ./src/index.ts --outdir dist --format esm --target browser --external @uipath/solutionpackager-tool-core --watch",
|
|
24
|
-
"test": "vitest run",
|
|
25
|
-
"test:browser": "vitest run --config=vitest.browser.config.ts",
|
|
26
|
-
"test:coverage": "vitest run --coverage",
|
|
27
|
-
"test:browser:coverage": "vitest run --config=vitest.browser.config.ts --coverage",
|
|
28
|
-
"test:all": "bun run test && bun run test:browser",
|
|
29
|
-
"test:all:coverage": "bun run test:coverage && bun run test:browser:coverage",
|
|
30
|
-
"prepack": "bun run build",
|
|
31
|
-
"publish:dry": "bun publish --dry-run",
|
|
32
|
-
"publish:gh": "bun publish",
|
|
33
|
-
"version:patch": "bun version patch --no-git-tag-version",
|
|
34
|
-
"version:minor": "bun version minor --no-git-tag-version",
|
|
35
|
-
"version:major": "bun version major --no-git-tag-version",
|
|
36
|
-
"lint": "biome check ."
|
|
37
|
-
},
|
|
38
21
|
"files": [
|
|
39
22
|
"dist",
|
|
40
23
|
"!dist/**/*.map",
|
|
@@ -43,16 +26,17 @@
|
|
|
43
26
|
"author": "",
|
|
44
27
|
"license": "ISC",
|
|
45
28
|
"peerDependencies": {
|
|
46
|
-
"@uipath/solutionpackager-tool-core": "
|
|
29
|
+
"@uipath/solutionpackager-tool-core": "1.196.0"
|
|
47
30
|
},
|
|
48
31
|
"devDependencies": {
|
|
49
|
-
"@types/node": "^25.5.
|
|
50
|
-
"@uipath/solutionpackager-tool-core": "
|
|
51
|
-
"@vitest/browser": "^4.
|
|
52
|
-
"@vitest/browser-playwright": "^4.
|
|
53
|
-
"@vitest/coverage-v8": "^4.
|
|
32
|
+
"@types/node": "^25.5.2",
|
|
33
|
+
"@uipath/solutionpackager-tool-core": "1.196.0",
|
|
34
|
+
"@vitest/browser": "^4.1.6",
|
|
35
|
+
"@vitest/browser-playwright": "^4.1.6",
|
|
36
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
54
37
|
"playwright": "^1.57.0",
|
|
55
|
-
"typescript": "^
|
|
56
|
-
"vitest": "^4.
|
|
57
|
-
}
|
|
38
|
+
"typescript": "^6.0.2",
|
|
39
|
+
"vitest": "^4.1.6"
|
|
40
|
+
},
|
|
41
|
+
"gitHead": "bed2b46f1ec33a47a7dcae2e6d4b7ab99bd06981"
|
|
58
42
|
}
|
package/src/constants.ts
CHANGED
|
@@ -12,11 +12,26 @@ export const PROJECT_JSON_FILE = "project.json";
|
|
|
12
12
|
*/
|
|
13
13
|
export const DEFAULT_BUNDLE_PATH = "source/dist";
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Pre-built app folder for the JS variant (source)
|
|
17
|
+
*/
|
|
18
|
+
export const APP_FOLDER_NAME = ".app";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Destination folder inside the NuGet content folder for the JS variant
|
|
22
|
+
*/
|
|
23
|
+
export const CONTENT_APP_FOLDER_NAME = "app";
|
|
24
|
+
|
|
15
25
|
/**
|
|
16
26
|
* Target runtime for operate.json
|
|
17
27
|
*/
|
|
18
28
|
export const TARGET_RUNTIME = "Coded";
|
|
19
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Target runtime for operate.json
|
|
32
|
+
*/
|
|
33
|
+
export const TARGET_JS_RUNTIME = "JS";
|
|
34
|
+
|
|
20
35
|
/**
|
|
21
36
|
* Default entry point type
|
|
22
37
|
*/
|
|
@@ -41,6 +56,12 @@ export const ERROR_MESSAGES = {
|
|
|
41
56
|
BUNDLE_NOT_DIRECTORY: (path: string): string =>
|
|
42
57
|
`Bundle path ${path} exists but is not a directory.`,
|
|
43
58
|
|
|
59
|
+
APP_FOLDER_NOT_FOUND: (path: string): string =>
|
|
60
|
+
`.app folder not found at ${path}. Ensure the project contains a .app folder.`,
|
|
61
|
+
|
|
62
|
+
APP_FOLDER_NOT_DIRECTORY: (path: string): string =>
|
|
63
|
+
`.app path ${path} exists but is not a directory.`,
|
|
64
|
+
|
|
44
65
|
BUILD_NOT_SUPPORTED:
|
|
45
66
|
"Build execution (isCompiled=false) is not yet supported. Please build the project manually and set isCompiled=true.",
|
|
46
67
|
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { toolsFactoryRepository } from "@uipath/solutionpackager-tool-core";
|
|
2
2
|
import { WebAppToolFactory } from "./webapp-tool-factory.js";
|
|
3
3
|
|
|
4
|
+
export type { WebAppManifest } from "./models/webapp-manifest.js";
|
|
5
|
+
export {
|
|
6
|
+
WEBAPP_MANIFEST_FILE_NAME,
|
|
7
|
+
WebAppVariantType,
|
|
8
|
+
} from "./models/webapp-manifest.js";
|
|
4
9
|
export { WebAppTool } from "./webapp-tool.js";
|
|
5
10
|
export { WebAppToolFactory } from "./webapp-tool-factory.js";
|
|
6
11
|
|
|
@@ -279,10 +279,32 @@ export class CodedAppStrategy implements VariantStrategy {
|
|
|
279
279
|
|
|
280
280
|
// Create or copy bindings_v2.json (version 2.0)
|
|
281
281
|
const bindingsV2Path = Path.join(contentFolder, "bindings_v2.json");
|
|
282
|
-
const
|
|
282
|
+
const bindingsCandidatePaths = [
|
|
283
|
+
Path.join(projectPath, "source", "bindings.json"),
|
|
284
|
+
Path.join(projectPath, "bindings.json"),
|
|
285
|
+
Path.join(projectPath, "bindings_v2.json"),
|
|
286
|
+
];
|
|
287
|
+
|
|
288
|
+
let bindingsV2Json: string | null = null;
|
|
289
|
+
for (const candidate of bindingsCandidatePaths) {
|
|
290
|
+
if (await this.fileSystem.exists(candidate)) {
|
|
291
|
+
bindingsV2Json = await this.fileSystem.readFile(
|
|
292
|
+
candidate,
|
|
293
|
+
"utf-8",
|
|
294
|
+
);
|
|
295
|
+
if (bindingsV2Json) break;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (!bindingsV2Json && (await this.fileSystem.exists(bindingsV2Path))) {
|
|
300
|
+
bindingsV2Json = await this.fileSystem.readFile(
|
|
301
|
+
bindingsV2Path,
|
|
302
|
+
"utf-8",
|
|
303
|
+
);
|
|
304
|
+
}
|
|
283
305
|
|
|
284
|
-
if (!
|
|
285
|
-
|
|
306
|
+
if (!bindingsV2Json) {
|
|
307
|
+
bindingsV2Json = JSON.stringify(
|
|
286
308
|
{
|
|
287
309
|
version: "2.0",
|
|
288
310
|
resources: [],
|
|
@@ -290,8 +312,8 @@ export class CodedAppStrategy implements VariantStrategy {
|
|
|
290
312
|
null,
|
|
291
313
|
2,
|
|
292
314
|
);
|
|
293
|
-
await this.fileSystem.writeFile(bindingsV2Path, bindingsV2Json);
|
|
294
315
|
}
|
|
316
|
+
await this.fileSystem.writeFile(bindingsV2Path, bindingsV2Json);
|
|
295
317
|
|
|
296
318
|
// Create or copy entry-points.json
|
|
297
319
|
const entryPointsPath = Path.join(contentFolder, "entry-points.json");
|
|
@@ -326,6 +348,8 @@ export class CodedAppStrategy implements VariantStrategy {
|
|
|
326
348
|
NugetConstants.PackageDescriptorFileName,
|
|
327
349
|
);
|
|
328
350
|
const packageDescriptor: PackageDescriptorFileModel = {
|
|
351
|
+
$schema:
|
|
352
|
+
"https://cloud.uipath.com/draft/2024-12/package-descriptor",
|
|
329
353
|
files: {
|
|
330
354
|
[NugetConstants.OperateFileName]: Path.join(
|
|
331
355
|
NugetConstants.ContentFolderName,
|
|
@@ -0,0 +1,374 @@
|
|
|
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 type { PackageArgs, VariantStrategy } from "./variant-strategy.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* JS apps strategy for the JS variant.
|
|
27
|
+
* Packages a pre-built `.app` folder whose contents are placed under `content/app`
|
|
28
|
+
* in the resulting .nupkg.
|
|
29
|
+
*/
|
|
30
|
+
export class JsAppsStrategy implements VariantStrategy {
|
|
31
|
+
constructor(private readonly fileSystem: IFileSystem) {}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Variant-specific validation: warn if the `.app` folder is missing or not a directory.
|
|
35
|
+
* Bundle path from the manifest is intentionally ignored for this variant.
|
|
36
|
+
*/
|
|
37
|
+
async validateAsync(args: {
|
|
38
|
+
fileSystem: IFileSystem;
|
|
39
|
+
projectPath: string;
|
|
40
|
+
manifest: WebAppManifest;
|
|
41
|
+
logger?: {
|
|
42
|
+
info: (message: string) => void;
|
|
43
|
+
error: (message: string) => void;
|
|
44
|
+
progress: (message: string) => void;
|
|
45
|
+
warn?: (message: string) => void;
|
|
46
|
+
};
|
|
47
|
+
}): Promise<void> {
|
|
48
|
+
const { projectPath, logger } = args;
|
|
49
|
+
const appFolder = Path.join(projectPath, APP_FOLDER_NAME);
|
|
50
|
+
|
|
51
|
+
const exists = await this.fileSystem.exists(appFolder);
|
|
52
|
+
if (!exists) {
|
|
53
|
+
const message = ERROR_MESSAGES.APP_FOLDER_NOT_FOUND(appFolder);
|
|
54
|
+
if (logger?.warn) {
|
|
55
|
+
logger.warn(message);
|
|
56
|
+
} else {
|
|
57
|
+
logger?.info(`Warning: ${message}`);
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const stat = await this.fileSystem.stat(appFolder);
|
|
63
|
+
if (!stat?.isDirectory()) {
|
|
64
|
+
const message = ERROR_MESSAGES.APP_FOLDER_NOT_DIRECTORY(appFolder);
|
|
65
|
+
if (logger?.warn) {
|
|
66
|
+
logger.warn(message);
|
|
67
|
+
} else {
|
|
68
|
+
logger?.info(`Warning: ${message}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async packageAsync(args: PackageArgs): Promise<string> {
|
|
74
|
+
const { projectPath, manifest, outputPath, packageInfo, logger } = args;
|
|
75
|
+
|
|
76
|
+
logger?.info(
|
|
77
|
+
`Packaging JS variant: ${packageInfo.id}@${packageInfo.version}`,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const appFolder = Path.join(projectPath, APP_FOLDER_NAME);
|
|
81
|
+
|
|
82
|
+
logger?.progress("Validating .app folder...");
|
|
83
|
+
const appFolderExists = await this.fileSystem.exists(appFolder);
|
|
84
|
+
if (!appFolderExists) {
|
|
85
|
+
throw new Error(ERROR_MESSAGES.APP_FOLDER_NOT_FOUND(appFolder));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const appFolderStat = await this.fileSystem.stat(appFolder);
|
|
89
|
+
if (!appFolderStat?.isDirectory()) {
|
|
90
|
+
throw new Error(ERROR_MESSAGES.APP_FOLDER_NOT_DIRECTORY(appFolder));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Bundle directory structure: <output>/bundle/content/app
|
|
94
|
+
const localBuildFolder = Path.join(
|
|
95
|
+
outputPath,
|
|
96
|
+
NugetConstants.OutputFolderName,
|
|
97
|
+
);
|
|
98
|
+
const contentFolder = Path.join(
|
|
99
|
+
localBuildFolder,
|
|
100
|
+
NugetConstants.ContentFolderName,
|
|
101
|
+
);
|
|
102
|
+
const contentAppFolder = Path.join(
|
|
103
|
+
contentFolder,
|
|
104
|
+
CONTENT_APP_FOLDER_NAME,
|
|
105
|
+
);
|
|
106
|
+
await this.fileSystem.mkdir(contentFolder);
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
// Copy contents of .app into content/app
|
|
110
|
+
logger?.progress("Copying .app folder into content/app...");
|
|
111
|
+
await copyDirectoryAsync(
|
|
112
|
+
this.fileSystem,
|
|
113
|
+
appFolder,
|
|
114
|
+
contentAppFolder,
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
logger?.progress("Preparing metadata files...");
|
|
118
|
+
await this.prepareMetadataFiles(
|
|
119
|
+
contentFolder,
|
|
120
|
+
contentAppFolder,
|
|
121
|
+
packageInfo,
|
|
122
|
+
manifest,
|
|
123
|
+
projectPath,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
logger?.progress("Creating NuGet package...");
|
|
127
|
+
const nupkgFileName = `${packageInfo.id}.${packageInfo.version}.nupkg`;
|
|
128
|
+
const nupkgPath = Path.join(outputPath, nupkgFileName);
|
|
129
|
+
|
|
130
|
+
const packager = new NugetPackager(this.fileSystem);
|
|
131
|
+
const result = await packager.packAsync(
|
|
132
|
+
localBuildFolder,
|
|
133
|
+
packageInfo,
|
|
134
|
+
nupkgPath,
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
logger?.info(`Package created successfully: ${result.outputPath}`);
|
|
138
|
+
return result.outputPath;
|
|
139
|
+
} finally {
|
|
140
|
+
try {
|
|
141
|
+
await this.fileSystem.rm(localBuildFolder);
|
|
142
|
+
} catch (cleanupError) {
|
|
143
|
+
logger?.error(
|
|
144
|
+
`Failed to cleanup build folder: ${
|
|
145
|
+
cleanupError instanceof Error
|
|
146
|
+
? cleanupError.message
|
|
147
|
+
: String(cleanupError)
|
|
148
|
+
}`,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Prepare metadata files (operate.json, package-descriptor.json, bindings.json, bindings_v2.json, entry-points.json)
|
|
156
|
+
*/
|
|
157
|
+
private async prepareMetadataFiles(
|
|
158
|
+
contentFolder: string,
|
|
159
|
+
contentAppFolder: string,
|
|
160
|
+
packageInfo: {
|
|
161
|
+
id: string;
|
|
162
|
+
version: string;
|
|
163
|
+
author?: string;
|
|
164
|
+
description?: string;
|
|
165
|
+
},
|
|
166
|
+
_manifest: WebAppManifest,
|
|
167
|
+
projectPath: string,
|
|
168
|
+
): Promise<void> {
|
|
169
|
+
const mainFile = "index.html";
|
|
170
|
+
|
|
171
|
+
// Path referenced from within the package content folder
|
|
172
|
+
const mainRelativeToContent = `${CONTENT_APP_FOLDER_NAME}/${mainFile}`;
|
|
173
|
+
|
|
174
|
+
// operate.json in content folder
|
|
175
|
+
const operatePath = Path.join(
|
|
176
|
+
contentFolder,
|
|
177
|
+
NugetConstants.OperateFileName,
|
|
178
|
+
);
|
|
179
|
+
const operateModel: OperateFileModel & { targetRuntime: string } = {
|
|
180
|
+
projectId: packageInfo.id,
|
|
181
|
+
main: mainRelativeToContent,
|
|
182
|
+
contentType: ProjectTypes.WebApp,
|
|
183
|
+
targetFramework: TargetFramework.Portable,
|
|
184
|
+
targetRuntime: TARGET_JS_RUNTIME,
|
|
185
|
+
runtimeOptions: {
|
|
186
|
+
requiresUserInteraction: false,
|
|
187
|
+
isAttended: false,
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const operateJson = JSON.stringify(operateModel, null, 2);
|
|
192
|
+
await this.fileSystem.writeFile(operatePath, operateJson);
|
|
193
|
+
|
|
194
|
+
// Copy webAppManifest.json from project root into content (as-is)
|
|
195
|
+
const manifestSourcePath = Path.join(
|
|
196
|
+
projectPath,
|
|
197
|
+
WEBAPP_MANIFEST_FILE_NAME,
|
|
198
|
+
);
|
|
199
|
+
const manifestDestPath = Path.join(
|
|
200
|
+
contentFolder,
|
|
201
|
+
WEBAPP_MANIFEST_FILE_NAME,
|
|
202
|
+
);
|
|
203
|
+
const manifestExists = await this.fileSystem.exists(manifestSourcePath);
|
|
204
|
+
if (manifestExists) {
|
|
205
|
+
const manifestContent =
|
|
206
|
+
await this.fileSystem.readFile(manifestSourcePath);
|
|
207
|
+
if (manifestContent) {
|
|
208
|
+
await this.fileSystem.writeFile(
|
|
209
|
+
manifestDestPath,
|
|
210
|
+
manifestContent,
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Copy uipath.json from project root into content (if it exists)
|
|
216
|
+
const uipathJsonSourcePath = Path.join(projectPath, "uipath.json");
|
|
217
|
+
const uipathJsonDestPath = Path.join(contentFolder, "uipath.json");
|
|
218
|
+
const uipathJsonExists =
|
|
219
|
+
await this.fileSystem.exists(uipathJsonSourcePath);
|
|
220
|
+
if (uipathJsonExists) {
|
|
221
|
+
const uipathJsonContent =
|
|
222
|
+
await this.fileSystem.readFile(uipathJsonSourcePath);
|
|
223
|
+
if (uipathJsonContent) {
|
|
224
|
+
await this.fileSystem.writeFile(
|
|
225
|
+
uipathJsonDestPath,
|
|
226
|
+
uipathJsonContent,
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Create or copy bindings.json (version 1.0)
|
|
232
|
+
const bindingsPath = Path.join(contentFolder, "bindings.json");
|
|
233
|
+
const bindingsExists = await this.fileSystem.exists(bindingsPath);
|
|
234
|
+
if (!bindingsExists) {
|
|
235
|
+
const bindingsJson = JSON.stringify(
|
|
236
|
+
{ version: "1.0", resources: [] },
|
|
237
|
+
null,
|
|
238
|
+
2,
|
|
239
|
+
);
|
|
240
|
+
await this.fileSystem.writeFile(bindingsPath, bindingsJson);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Create or copy bindings_v2.json (version 2.0)
|
|
244
|
+
const bindingsV2Path = Path.join(contentFolder, "bindings_v2.json");
|
|
245
|
+
const bindingsV2Exists = await this.fileSystem.exists(bindingsV2Path);
|
|
246
|
+
if (!bindingsV2Exists) {
|
|
247
|
+
const bindingsV2Json = JSON.stringify(
|
|
248
|
+
{ version: "2.0", resources: [] },
|
|
249
|
+
null,
|
|
250
|
+
2,
|
|
251
|
+
);
|
|
252
|
+
await this.fileSystem.writeFile(bindingsV2Path, bindingsV2Json);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Create or copy entry-points.json
|
|
256
|
+
const entryPointsPath = Path.join(contentFolder, "entry-points.json");
|
|
257
|
+
const projectEntryPointsPath = Path.join(
|
|
258
|
+
projectPath,
|
|
259
|
+
"entry-points.json",
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
let entryPointsContent: string;
|
|
263
|
+
const projectEntryPointsExists = await this.fileSystem.exists(
|
|
264
|
+
projectEntryPointsPath,
|
|
265
|
+
);
|
|
266
|
+
if (projectEntryPointsExists) {
|
|
267
|
+
const entryPointsData = await this.fileSystem.readFile(
|
|
268
|
+
projectEntryPointsPath,
|
|
269
|
+
);
|
|
270
|
+
if (entryPointsData) {
|
|
271
|
+
entryPointsContent = new TextDecoder().decode(entryPointsData);
|
|
272
|
+
} else {
|
|
273
|
+
entryPointsContent = this.createDefaultEntryPoints(
|
|
274
|
+
mainRelativeToContent,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
} else {
|
|
278
|
+
entryPointsContent = this.createDefaultEntryPoints(
|
|
279
|
+
mainRelativeToContent,
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
await this.fileSystem.writeFile(entryPointsPath, entryPointsContent);
|
|
284
|
+
|
|
285
|
+
// Create package-descriptor.json in content folder
|
|
286
|
+
const packageDescriptorPath = Path.join(
|
|
287
|
+
contentFolder,
|
|
288
|
+
NugetConstants.PackageDescriptorFileName,
|
|
289
|
+
);
|
|
290
|
+
const packageDescriptor: PackageDescriptorFileModel = {
|
|
291
|
+
files: {
|
|
292
|
+
[NugetConstants.OperateFileName]: Path.join(
|
|
293
|
+
NugetConstants.ContentFolderName,
|
|
294
|
+
NugetConstants.OperateFileName,
|
|
295
|
+
),
|
|
296
|
+
"entry-points.json": Path.join(
|
|
297
|
+
NugetConstants.ContentFolderName,
|
|
298
|
+
"entry-points.json",
|
|
299
|
+
),
|
|
300
|
+
"bindings.json": Path.join(
|
|
301
|
+
NugetConstants.ContentFolderName,
|
|
302
|
+
"bindings_v2.json",
|
|
303
|
+
),
|
|
304
|
+
},
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const packageDescriptorJson = JSON.stringify(
|
|
308
|
+
packageDescriptor,
|
|
309
|
+
null,
|
|
310
|
+
2,
|
|
311
|
+
);
|
|
312
|
+
await this.fileSystem.writeFile(
|
|
313
|
+
packageDescriptorPath,
|
|
314
|
+
packageDescriptorJson,
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Create default entry-points.json structure
|
|
320
|
+
*/
|
|
321
|
+
private createDefaultEntryPoints(mainFilePath: string): string {
|
|
322
|
+
const uniqueId = this.generateUniqueId();
|
|
323
|
+
|
|
324
|
+
const entryPoints = {
|
|
325
|
+
$schema: "https://cloud.uipath.com/draft/2024-12/entry-point",
|
|
326
|
+
$id: "entry-points-doc-001",
|
|
327
|
+
entryPoints: [
|
|
328
|
+
{
|
|
329
|
+
filePath: mainFilePath,
|
|
330
|
+
uniqueId: uniqueId,
|
|
331
|
+
type: DEFAULT_ENTRY_POINT_TYPE,
|
|
332
|
+
input: {
|
|
333
|
+
amount: { type: "integer" },
|
|
334
|
+
id: { type: "string" },
|
|
335
|
+
},
|
|
336
|
+
output: {
|
|
337
|
+
status: { type: "string" },
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
],
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
return JSON.stringify(entryPoints, null, 2);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Generate a cryptographically secure unique ID (UUID v4-like format)
|
|
348
|
+
*/
|
|
349
|
+
private generateUniqueId(): string {
|
|
350
|
+
const randomBytes = new Uint8Array(16);
|
|
351
|
+
|
|
352
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
353
|
+
crypto.getRandomValues(randomBytes);
|
|
354
|
+
} else {
|
|
355
|
+
throw new Error("crypto.getRandomValues is not available");
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Set version (4) and variant bits according to UUID v4 spec
|
|
359
|
+
randomBytes[6] = (randomBytes[6] & 0x0f) | 0x40;
|
|
360
|
+
randomBytes[8] = (randomBytes[8] & 0x3f) | 0x80;
|
|
361
|
+
|
|
362
|
+
const hex = Array.from(randomBytes)
|
|
363
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
364
|
+
.join("");
|
|
365
|
+
|
|
366
|
+
return [
|
|
367
|
+
hex.substring(0, 8),
|
|
368
|
+
hex.substring(8, 12),
|
|
369
|
+
hex.substring(12, 16),
|
|
370
|
+
hex.substring(16, 20),
|
|
371
|
+
hex.substring(20, 32),
|
|
372
|
+
].join("-");
|
|
373
|
+
}
|
|
374
|
+
}
|
|
@@ -2,6 +2,7 @@ import type { IFileSystem } from "@uipath/solutionpackager-tool-core";
|
|
|
2
2
|
import type { WebAppManifest } from "../models/webapp-manifest.js";
|
|
3
3
|
import { WebAppVariantType } from "../models/webapp-manifest.js";
|
|
4
4
|
import { CodedAppStrategy } from "./coded-app-strategy.js";
|
|
5
|
+
import { JsAppsStrategy } from "./js-apps-strategy.js";
|
|
5
6
|
import type { VariantStrategy } from "./variant-strategy.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -26,9 +27,7 @@ export class VariantStrategyFactory {
|
|
|
26
27
|
return new CodedAppStrategy(fileSystem);
|
|
27
28
|
|
|
28
29
|
case WebAppVariantType.JS:
|
|
29
|
-
|
|
30
|
-
"JS variant is not yet implemented. Only Coded is supported in v1.",
|
|
31
|
-
);
|
|
30
|
+
return new JsAppsStrategy(fileSystem);
|
|
32
31
|
|
|
33
32
|
default:
|
|
34
33
|
throw new Error(
|