@uipath/packager-tool-webapp 1.204.0-preview.254 → 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/dist/action-schema/index.js +198 -85
- package/dist/constants.d.ts +13 -0
- package/dist/constants.js +1023 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +231 -118
- package/dist/models/webapp-manifest.d.ts +8 -0
- package/dist/strategies/coded-app-strategy.d.ts +35 -0
- package/dist/utils/bundle-path.d.ts +10 -0
- package/dist/webapp-tool-factory.d.ts +3 -2
- package/dist/webapp-tool.d.ts +7 -1
- package/package.json +5 -4
|
@@ -385,13 +385,57 @@ import {
|
|
|
385
385
|
|
|
386
386
|
// src/webapp-tool.ts
|
|
387
387
|
import {
|
|
388
|
-
Path as
|
|
388
|
+
Path as Path6,
|
|
389
389
|
ProjectTool as ProjectTool2,
|
|
390
390
|
TemporaryStorageService,
|
|
391
391
|
ToolErrorCodes,
|
|
392
392
|
ToolResult
|
|
393
393
|
} from "@uipath/solutionpackager-tool-core";
|
|
394
394
|
|
|
395
|
+
// src/utils/bundle-path.ts
|
|
396
|
+
import { Path } from "@uipath/solutionpackager-tool-core";
|
|
397
|
+
function normalizeBundlePath(path) {
|
|
398
|
+
return path.replace(/\\/g, "/");
|
|
399
|
+
}
|
|
400
|
+
function isBundleRelativePath(path) {
|
|
401
|
+
const normalized = normalizeBundlePath(path);
|
|
402
|
+
const segments = normalized.split("/");
|
|
403
|
+
return !normalized.startsWith("/") && !/^[a-zA-Z]:/.test(normalized) && !segments.includes("..") && segments.some((segment) => segment !== "" && segment !== ".");
|
|
404
|
+
}
|
|
405
|
+
async function isCanonicalBundleChild(fileSystem, projectPath, bundlePath) {
|
|
406
|
+
const project = normalizeBundlePath(await fileSystem.realpath(projectPath)).replace(/\/+$/, "") || "/";
|
|
407
|
+
let bundle = project;
|
|
408
|
+
for (const segment of normalizeBundlePath(bundlePath).split("/")) {
|
|
409
|
+
if (!segment || segment === ".")
|
|
410
|
+
continue;
|
|
411
|
+
bundle = normalizeBundlePath(await fileSystem.realpath(Path.join(bundle, segment))).replace(/\/+$/, "") || "/";
|
|
412
|
+
}
|
|
413
|
+
return bundle !== project && bundle.startsWith(project === "/" ? "/" : `${project}/`);
|
|
414
|
+
}
|
|
415
|
+
function isHtmlEntryPointPath(path) {
|
|
416
|
+
return typeof path === "string" && isBundleRelativePath(path) && /\.html?$/i.test(path);
|
|
417
|
+
}
|
|
418
|
+
async function resolveHtmlEntryPoint(fileSystem, folder, declaredPath) {
|
|
419
|
+
if (!isHtmlEntryPointPath(declaredPath))
|
|
420
|
+
return null;
|
|
421
|
+
const segments = normalizeBundlePath(declaredPath).split("/").filter((part) => part !== "" && part !== ".");
|
|
422
|
+
if (!(await fileSystem.stat(Path.join(folder, ...segments)))?.isFile())
|
|
423
|
+
return null;
|
|
424
|
+
const actual = [];
|
|
425
|
+
for (const segment of segments) {
|
|
426
|
+
const entries = await fileSystem.readdir(Path.join(folder, ...actual));
|
|
427
|
+
if (entries.includes(segment)) {
|
|
428
|
+
actual.push(segment);
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
const matches = entries.filter((entry) => entry.toLowerCase() === segment.toLowerCase());
|
|
432
|
+
if (matches.length !== 1)
|
|
433
|
+
return null;
|
|
434
|
+
actual.push(matches[0]);
|
|
435
|
+
}
|
|
436
|
+
return actual.join("/");
|
|
437
|
+
}
|
|
438
|
+
|
|
395
439
|
// src/constants.ts
|
|
396
440
|
var PROJECT_JSON_FILE = "project.json";
|
|
397
441
|
var DEFAULT_BUNDLE_PATH = "source/dist";
|
|
@@ -400,12 +444,23 @@ var CONTENT_APP_FOLDER_NAME = "app";
|
|
|
400
444
|
var TARGET_RUNTIME = "Coded";
|
|
401
445
|
var TARGET_JS_RUNTIME = "JS";
|
|
402
446
|
var DEFAULT_ENTRY_POINT_TYPE = "api";
|
|
447
|
+
var HTML_ENTRY_POINT_CANDIDATES = [
|
|
448
|
+
"index.html",
|
|
449
|
+
"main.html",
|
|
450
|
+
"app.html"
|
|
451
|
+
];
|
|
403
452
|
var ERROR_MESSAGES = {
|
|
404
453
|
MANIFEST_NOT_FOUND: (file) => `WebApp manifest not found: ${file}. This file is required for WebApp projects.`,
|
|
405
454
|
PROJECT_JSON_FOUND: "project.json found in WebApp project. The WebApp tool only supports Coded web apps without project.json.",
|
|
406
455
|
MANIFEST_LOAD_FAILED: (file) => `Failed to load or parse ${file}`,
|
|
407
456
|
BUNDLE_NOT_FOUND: (path) => `Compiled bundle not found at ${path}. Ensure the project is built before packing.`,
|
|
408
457
|
BUNDLE_NOT_DIRECTORY: (path) => `Bundle path ${path} exists but is not a directory.`,
|
|
458
|
+
BUNDLE_OUTSIDE_PROJECT: (path) => `Bundle path ${path} resolves to the project root or outside the project. Use a child build output folder inside the project.`,
|
|
459
|
+
BUNDLE_NO_ENTRY_POINT: (path) => `Bundle at ${path} has no HTML entry point (${HTML_ENTRY_POINT_CANDIDATES.join(", ")}). Build the app before packing, or point config.bundlePath in webAppManifest.json at its build output.`,
|
|
460
|
+
MAIN_FILE_INVALID_TYPE: "Invalid webAppManifest.json: config.mainFile must be a string naming an HTML file, or be omitted.",
|
|
461
|
+
MAIN_FILE_NOT_IN_BUNDLE: (path, mainFile) => `${WEBAPP_MANIFEST_FILE_NAME} asks for "${mainFile}" as the app's main file, but the bundle at ${path} does not hold it. Name an HTML file inside the bundle in config.mainFile, or remove it to use the first of ${HTML_ENTRY_POINT_CANDIDATES.join(", ")} the bundle holds.`,
|
|
462
|
+
MAIN_FILE_LOST: (path, mainFile) => `Bundle at ${path} held "${mainFile}" when the pack started, but the copy taken for the package has not. Something changed the folder mid-pack — usually a build or watch process. Stop it and pack again.`,
|
|
463
|
+
BUNDLE_ENTRY_POINT_LOST: (path) => `Bundle at ${path} had an HTML entry point (${HTML_ENTRY_POINT_CANDIDATES.join(", ")}) when the pack started, but the copy taken for the package has none. Something changed the folder mid-pack — usually a build or watch process. Stop it and pack again.`,
|
|
409
464
|
APP_FOLDER_NOT_FOUND: (path) => `.app folder not found at ${path}. Ensure the project contains a .app folder.`,
|
|
410
465
|
APP_FOLDER_NOT_DIRECTORY: (path) => `.app path ${path} exists but is not a directory.`,
|
|
411
466
|
BUILD_NOT_SUPPORTED: "Build execution (isCompiled=false) is not yet supported. Please build the project manually and set isCompiled=true.",
|
|
@@ -421,19 +476,19 @@ var ERROR_MESSAGES = {
|
|
|
421
476
|
import {
|
|
422
477
|
NugetConstants,
|
|
423
478
|
NugetPackager,
|
|
424
|
-
Path as
|
|
479
|
+
Path as Path4,
|
|
425
480
|
ProjectTypes,
|
|
426
481
|
TargetFramework
|
|
427
482
|
} from "@uipath/solutionpackager-tool-core";
|
|
428
483
|
|
|
429
484
|
// src/utils/fs-helpers.ts
|
|
430
|
-
import { Path } from "@uipath/solutionpackager-tool-core";
|
|
485
|
+
import { Path as Path2 } from "@uipath/solutionpackager-tool-core";
|
|
431
486
|
async function copyDirectoryAsync(fileSystem, sourcePath, destinationPath) {
|
|
432
487
|
await fileSystem.mkdir(destinationPath);
|
|
433
488
|
const entries = await fileSystem.readdir(sourcePath);
|
|
434
489
|
for (const entry of entries) {
|
|
435
|
-
const sourceEntry =
|
|
436
|
-
const destEntry =
|
|
490
|
+
const sourceEntry = Path2.join(sourcePath, entry);
|
|
491
|
+
const destEntry = Path2.join(destinationPath, entry);
|
|
437
492
|
const stat = await fileSystem.stat(sourceEntry);
|
|
438
493
|
if (stat?.isDirectory()) {
|
|
439
494
|
await copyDirectoryAsync(fileSystem, sourceEntry, destEntry);
|
|
@@ -447,9 +502,9 @@ async function copyDirectoryAsync(fileSystem, sourcePath, destinationPath) {
|
|
|
447
502
|
}
|
|
448
503
|
|
|
449
504
|
// src/utils/manifest-loader.ts
|
|
450
|
-
import { Path as
|
|
505
|
+
import { Path as Path3 } from "@uipath/solutionpackager-tool-core";
|
|
451
506
|
async function loadWebAppManifest2(fileSystem, projectPath) {
|
|
452
|
-
const manifestPath =
|
|
507
|
+
const manifestPath = Path3.join(projectPath, WEBAPP_MANIFEST_FILE_NAME);
|
|
453
508
|
const exists = await fileSystem.exists(manifestPath);
|
|
454
509
|
if (!exists) {
|
|
455
510
|
return null;
|
|
@@ -474,7 +529,7 @@ async function ensureWebAppProjectId(fileSystem, projectPath) {
|
|
|
474
529
|
const id = crypto.randomUUID();
|
|
475
530
|
if (manifest) {
|
|
476
531
|
const updated = { ...manifest, projectId: id };
|
|
477
|
-
const manifestPath =
|
|
532
|
+
const manifestPath = Path3.join(projectPath, WEBAPP_MANIFEST_FILE_NAME);
|
|
478
533
|
await fileSystem.writeFile(manifestPath, `${JSON.stringify(updated, null, 2)}
|
|
479
534
|
`);
|
|
480
535
|
}
|
|
@@ -496,10 +551,9 @@ class CodedAppStrategy {
|
|
|
496
551
|
}
|
|
497
552
|
const isCompiled = typed.config?.isCompiled ?? true;
|
|
498
553
|
if (isCompiled) {
|
|
499
|
-
const fullBundlePath =
|
|
500
|
-
const
|
|
501
|
-
if (
|
|
502
|
-
const message = ERROR_MESSAGES.BUNDLE_NOT_FOUND(fullBundlePath);
|
|
554
|
+
const fullBundlePath = Path4.join(projectPath, bundlePath);
|
|
555
|
+
const message = await this.describeBundleProblemAsync(fullBundlePath, typed.config?.mainFile);
|
|
556
|
+
if (message) {
|
|
503
557
|
const warnable = logger;
|
|
504
558
|
if (warnable?.warn) {
|
|
505
559
|
warnable.warn(message);
|
|
@@ -517,7 +571,11 @@ class CodedAppStrategy {
|
|
|
517
571
|
bundlePath = DEFAULT_BUNDLE_PATH;
|
|
518
572
|
}
|
|
519
573
|
const isCompiled = manifest.config?.isCompiled ?? true;
|
|
520
|
-
const
|
|
574
|
+
const declaredMainFile = manifest.config?.mainFile;
|
|
575
|
+
const fullBundlePath = Path4.join(projectPath, bundlePath);
|
|
576
|
+
if (isBundleRelativePath(bundlePath) && !await isCanonicalBundleChild(this.fileSystem, projectPath, bundlePath)) {
|
|
577
|
+
throw new Error(ERROR_MESSAGES.BUNDLE_OUTSIDE_PROJECT(bundlePath));
|
|
578
|
+
}
|
|
521
579
|
if (isCompiled) {
|
|
522
580
|
logger?.progress("Validating compiled bundle...");
|
|
523
581
|
const bundleExists = await this.fileSystem.exists(fullBundlePath);
|
|
@@ -528,21 +586,25 @@ class CodedAppStrategy {
|
|
|
528
586
|
if (!bundleStat?.isDirectory()) {
|
|
529
587
|
throw new Error(ERROR_MESSAGES.BUNDLE_NOT_DIRECTORY(fullBundlePath));
|
|
530
588
|
}
|
|
589
|
+
const problem = await this.describeBundleEntryProblemAsync(fullBundlePath, declaredMainFile);
|
|
590
|
+
if (problem) {
|
|
591
|
+
throw new Error(problem);
|
|
592
|
+
}
|
|
531
593
|
} else {
|
|
532
594
|
logger?.info("Build mode (isCompiled=false) is not yet implemented in v1.");
|
|
533
595
|
throw new Error(ERROR_MESSAGES.BUILD_NOT_SUPPORTED);
|
|
534
596
|
}
|
|
535
|
-
const localBuildFolder =
|
|
536
|
-
const contentFolder =
|
|
537
|
-
await this.fileSystem.mkdir(contentFolder);
|
|
597
|
+
const localBuildFolder = Path4.join(outputPath, `${NugetConstants.OutputFolderName}-${crypto.randomUUID()}`);
|
|
598
|
+
const contentFolder = Path4.join(localBuildFolder, NugetConstants.ContentFolderName);
|
|
538
599
|
try {
|
|
600
|
+
await this.fileSystem.mkdir(contentFolder);
|
|
539
601
|
logger?.progress("Copying bundle to content folder...");
|
|
540
602
|
await copyDirectoryAsync(this.fileSystem, fullBundlePath, contentFolder);
|
|
541
603
|
logger?.progress("Preparing metadata files...");
|
|
542
|
-
await this.prepareMetadataFiles(localBuildFolder, contentFolder, packageInfo, manifest, projectPath);
|
|
604
|
+
await this.prepareMetadataFiles(localBuildFolder, contentFolder, packageInfo, manifest, projectPath, fullBundlePath);
|
|
543
605
|
logger?.progress("Creating NuGet package...");
|
|
544
606
|
const nupkgFileName = `${packageInfo.id}.${packageInfo.version}.nupkg`;
|
|
545
|
-
const nupkgPath =
|
|
607
|
+
const nupkgPath = Path4.join(outputPath, nupkgFileName);
|
|
546
608
|
const packager = new NugetPackager(this.fileSystem);
|
|
547
609
|
const result = await packager.packAsync(localBuildFolder, packageInfo, nupkgPath);
|
|
548
610
|
logger?.info(`Package created successfully: ${result.outputPath}`);
|
|
@@ -555,21 +617,13 @@ class CodedAppStrategy {
|
|
|
555
617
|
}
|
|
556
618
|
}
|
|
557
619
|
}
|
|
558
|
-
async prepareMetadataFiles(_localBuildFolder, contentFolder, _packageInfo,
|
|
559
|
-
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
const possibleEntries = ["index.html", "main.html", "app.html"];
|
|
564
|
-
for (const entry of possibleEntries) {
|
|
565
|
-
const entryPath = Path3.join(contentFolder, entry);
|
|
566
|
-
if (await this.fileSystem.exists(entryPath)) {
|
|
567
|
-
mainFile = entry;
|
|
568
|
-
break;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
620
|
+
async prepareMetadataFiles(_localBuildFolder, contentFolder, _packageInfo, manifest, projectPath, sourceBundlePath) {
|
|
621
|
+
const declaredMainFile = manifest.config?.mainFile;
|
|
622
|
+
const mainFile = await this.resolveMainFileAsync(contentFolder, declaredMainFile);
|
|
623
|
+
if (!mainFile) {
|
|
624
|
+
throw new Error(declaredMainFile ? ERROR_MESSAGES.MAIN_FILE_LOST(sourceBundlePath, declaredMainFile) : ERROR_MESSAGES.BUNDLE_ENTRY_POINT_LOST(sourceBundlePath));
|
|
571
625
|
}
|
|
572
|
-
const operatePath =
|
|
626
|
+
const operatePath = Path4.join(contentFolder, NugetConstants.OperateFileName);
|
|
573
627
|
const operateModel = {
|
|
574
628
|
projectId: await ensureWebAppProjectId(this.fileSystem, projectPath),
|
|
575
629
|
main: mainFile,
|
|
@@ -583,17 +637,13 @@ class CodedAppStrategy {
|
|
|
583
637
|
};
|
|
584
638
|
const operateJson = JSON.stringify(operateModel, null, 2);
|
|
585
639
|
await this.fileSystem.writeFile(operatePath, operateJson);
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
const uipathJsonSourcePath = Path3.join(projectPath, "uipath.json");
|
|
596
|
-
const uipathJsonDestPath = Path3.join(contentFolder, "uipath.json");
|
|
640
|
+
await this.fileSystem.writeFile(Path4.join(contentFolder, WEBAPP_MANIFEST_FILE_NAME), JSON.stringify({
|
|
641
|
+
...manifest,
|
|
642
|
+
config: { ...manifest.config, mainFile },
|
|
643
|
+
projectId: operateModel.projectId
|
|
644
|
+
}, null, 2));
|
|
645
|
+
const uipathJsonSourcePath = Path4.join(projectPath, "uipath.json");
|
|
646
|
+
const uipathJsonDestPath = Path4.join(contentFolder, "uipath.json");
|
|
597
647
|
const uipathJsonExists = await this.fileSystem.exists(uipathJsonSourcePath);
|
|
598
648
|
if (uipathJsonExists) {
|
|
599
649
|
const uipathJsonContent = await this.fileSystem.readFile(uipathJsonSourcePath, "utf-8");
|
|
@@ -601,8 +651,8 @@ class CodedAppStrategy {
|
|
|
601
651
|
await this.fileSystem.writeFile(uipathJsonDestPath, uipathJsonContent);
|
|
602
652
|
}
|
|
603
653
|
}
|
|
604
|
-
const actionSchemaSourcePath =
|
|
605
|
-
const actionSchemaDestPath =
|
|
654
|
+
const actionSchemaSourcePath = Path4.join(projectPath, "action-schema.json");
|
|
655
|
+
const actionSchemaDestPath = Path4.join(contentFolder, "action-schema.json");
|
|
606
656
|
const actionSchemaExists = await this.fileSystem.exists(actionSchemaSourcePath);
|
|
607
657
|
if (actionSchemaExists) {
|
|
608
658
|
const actionSchemaContent = await this.fileSystem.readFile(actionSchemaSourcePath, "utf-8");
|
|
@@ -610,7 +660,7 @@ class CodedAppStrategy {
|
|
|
610
660
|
await this.fileSystem.writeFile(actionSchemaDestPath, actionSchemaContent);
|
|
611
661
|
}
|
|
612
662
|
}
|
|
613
|
-
const bindingsPath =
|
|
663
|
+
const bindingsPath = Path4.join(contentFolder, "bindings.json");
|
|
614
664
|
const bindingsExists = await this.fileSystem.exists(bindingsPath);
|
|
615
665
|
if (!bindingsExists) {
|
|
616
666
|
const bindingsJson = JSON.stringify({
|
|
@@ -619,12 +669,12 @@ class CodedAppStrategy {
|
|
|
619
669
|
}, null, 2);
|
|
620
670
|
await this.fileSystem.writeFile(bindingsPath, bindingsJson);
|
|
621
671
|
}
|
|
622
|
-
const bindingsV2Path =
|
|
672
|
+
const bindingsV2Path = Path4.join(contentFolder, "bindings_v2.json");
|
|
623
673
|
const bindingsCandidatePaths = [
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
674
|
+
Path4.join(projectPath, "source", "bindings_v2.json"),
|
|
675
|
+
Path4.join(projectPath, "source", "bindings.json"),
|
|
676
|
+
Path4.join(projectPath, "bindings.json"),
|
|
677
|
+
Path4.join(projectPath, "bindings_v2.json")
|
|
628
678
|
];
|
|
629
679
|
let bindingsV2Json = null;
|
|
630
680
|
for (const candidate of bindingsCandidatePaths) {
|
|
@@ -644,14 +694,14 @@ class CodedAppStrategy {
|
|
|
644
694
|
}, null, 2);
|
|
645
695
|
}
|
|
646
696
|
await this.fileSystem.writeFile(bindingsV2Path, bindingsV2Json);
|
|
647
|
-
const entryPointsPath =
|
|
648
|
-
const projectEntryPointsPath =
|
|
697
|
+
const entryPointsPath = Path4.join(contentFolder, "entry-points.json");
|
|
698
|
+
const projectEntryPointsPath = Path4.join(projectPath, "entry-points.json");
|
|
649
699
|
let entryPointsContent;
|
|
650
700
|
const projectEntryPointsExists = await this.fileSystem.exists(projectEntryPointsPath);
|
|
651
701
|
if (projectEntryPointsExists) {
|
|
652
702
|
const entryPointsData = await this.fileSystem.readFile(projectEntryPointsPath, "utf-8");
|
|
653
703
|
if (entryPointsData) {
|
|
654
|
-
entryPointsContent = entryPointsData;
|
|
704
|
+
entryPointsContent = this.alignEntryPoint(entryPointsData, mainFile);
|
|
655
705
|
} else {
|
|
656
706
|
entryPointsContent = this.createDefaultEntryPoints(mainFile);
|
|
657
707
|
}
|
|
@@ -659,18 +709,68 @@ class CodedAppStrategy {
|
|
|
659
709
|
entryPointsContent = this.createDefaultEntryPoints(mainFile);
|
|
660
710
|
}
|
|
661
711
|
await this.fileSystem.writeFile(entryPointsPath, entryPointsContent);
|
|
662
|
-
const packageDescriptorPath =
|
|
712
|
+
const packageDescriptorPath = Path4.join(contentFolder, NugetConstants.PackageDescriptorFileName);
|
|
663
713
|
const packageDescriptor = {
|
|
664
714
|
$schema: "https://cloud.uipath.com/draft/2024-12/package-descriptor",
|
|
665
715
|
files: {
|
|
666
|
-
[NugetConstants.OperateFileName]:
|
|
667
|
-
"entry-points.json":
|
|
668
|
-
"bindings.json":
|
|
716
|
+
[NugetConstants.OperateFileName]: Path4.join(NugetConstants.ContentFolderName, NugetConstants.OperateFileName),
|
|
717
|
+
"entry-points.json": Path4.join(NugetConstants.ContentFolderName, "entry-points.json"),
|
|
718
|
+
"bindings.json": Path4.join(NugetConstants.ContentFolderName, "bindings_v2.json")
|
|
669
719
|
}
|
|
670
720
|
};
|
|
671
721
|
const packageDescriptorJson = JSON.stringify(packageDescriptor, null, 2);
|
|
672
722
|
await this.fileSystem.writeFile(packageDescriptorPath, packageDescriptorJson);
|
|
673
723
|
}
|
|
724
|
+
async describeBundleProblemAsync(fullBundlePath, declaredMainFile) {
|
|
725
|
+
const bundleStat = await this.fileSystem.stat(fullBundlePath);
|
|
726
|
+
if (!bundleStat) {
|
|
727
|
+
return ERROR_MESSAGES.BUNDLE_NOT_FOUND(fullBundlePath);
|
|
728
|
+
}
|
|
729
|
+
if (!bundleStat.isDirectory()) {
|
|
730
|
+
return ERROR_MESSAGES.BUNDLE_NOT_DIRECTORY(fullBundlePath);
|
|
731
|
+
}
|
|
732
|
+
return this.describeBundleEntryProblemAsync(fullBundlePath, declaredMainFile);
|
|
733
|
+
}
|
|
734
|
+
async describeBundleEntryProblemAsync(fullBundlePath, declaredMainFile) {
|
|
735
|
+
if (declaredMainFile !== undefined && typeof declaredMainFile !== "string") {
|
|
736
|
+
return ERROR_MESSAGES.MAIN_FILE_INVALID_TYPE;
|
|
737
|
+
}
|
|
738
|
+
if (await this.resolveMainFileAsync(fullBundlePath, declaredMainFile)) {
|
|
739
|
+
return null;
|
|
740
|
+
}
|
|
741
|
+
return declaredMainFile !== undefined ? ERROR_MESSAGES.MAIN_FILE_NOT_IN_BUNDLE(fullBundlePath, declaredMainFile) : ERROR_MESSAGES.BUNDLE_NO_ENTRY_POINT(fullBundlePath);
|
|
742
|
+
}
|
|
743
|
+
async resolveMainFileAsync(folder, declaredMainFile) {
|
|
744
|
+
if (declaredMainFile === undefined) {
|
|
745
|
+
return this.findEntryPointAsync(folder);
|
|
746
|
+
}
|
|
747
|
+
return resolveHtmlEntryPoint(this.fileSystem, folder, declaredMainFile);
|
|
748
|
+
}
|
|
749
|
+
async findEntryPointAsync(folder) {
|
|
750
|
+
for (const candidate of HTML_ENTRY_POINT_CANDIDATES) {
|
|
751
|
+
const resolved = await resolveHtmlEntryPoint(this.fileSystem, folder, candidate);
|
|
752
|
+
if (resolved !== null)
|
|
753
|
+
return resolved;
|
|
754
|
+
}
|
|
755
|
+
return null;
|
|
756
|
+
}
|
|
757
|
+
alignEntryPoint(content, mainFile) {
|
|
758
|
+
const document = JSON.parse(content);
|
|
759
|
+
if (typeof document !== "object" || document === null || !("entryPoints" in document) || !Array.isArray(document.entryPoints)) {
|
|
760
|
+
throw new Error("Invalid entry-points.json: expected an entryPoints array.");
|
|
761
|
+
}
|
|
762
|
+
const primary = document.entryPoints[0];
|
|
763
|
+
if (typeof primary !== "object" || primary === null || Array.isArray(primary)) {
|
|
764
|
+
throw new Error("Invalid entry-points.json: expected a primary entry object.");
|
|
765
|
+
}
|
|
766
|
+
return JSON.stringify({
|
|
767
|
+
...document,
|
|
768
|
+
entryPoints: [
|
|
769
|
+
{ ...primary, filePath: mainFile },
|
|
770
|
+
...document.entryPoints.slice(1)
|
|
771
|
+
]
|
|
772
|
+
}, null, 2);
|
|
773
|
+
}
|
|
674
774
|
createDefaultEntryPoints(mainFile) {
|
|
675
775
|
const uniqueId = this.generateUniqueId();
|
|
676
776
|
const entryPoints = {
|
|
@@ -717,7 +817,7 @@ class CodedAppStrategy {
|
|
|
717
817
|
import {
|
|
718
818
|
NugetConstants as NugetConstants2,
|
|
719
819
|
NugetPackager as NugetPackager2,
|
|
720
|
-
Path as
|
|
820
|
+
Path as Path5,
|
|
721
821
|
ProjectTypes as ProjectTypes2,
|
|
722
822
|
TargetFramework as TargetFramework2
|
|
723
823
|
} from "@uipath/solutionpackager-tool-core";
|
|
@@ -728,7 +828,7 @@ class JsAppsStrategy {
|
|
|
728
828
|
}
|
|
729
829
|
async validateAsync(args) {
|
|
730
830
|
const { projectPath, logger } = args;
|
|
731
|
-
const appFolder =
|
|
831
|
+
const appFolder = Path5.join(projectPath, APP_FOLDER_NAME);
|
|
732
832
|
const exists = await this.fileSystem.exists(appFolder);
|
|
733
833
|
if (!exists) {
|
|
734
834
|
const message = ERROR_MESSAGES.APP_FOLDER_NOT_FOUND(appFolder);
|
|
@@ -752,7 +852,7 @@ class JsAppsStrategy {
|
|
|
752
852
|
async packageAsync(args) {
|
|
753
853
|
const { projectPath, manifest, outputPath, packageInfo, logger } = args;
|
|
754
854
|
logger?.info(`Packaging JS variant: ${packageInfo.id}@${packageInfo.version}`);
|
|
755
|
-
const appFolder =
|
|
855
|
+
const appFolder = Path5.join(projectPath, APP_FOLDER_NAME);
|
|
756
856
|
logger?.progress("Validating .app folder...");
|
|
757
857
|
const appFolderExists = await this.fileSystem.exists(appFolder);
|
|
758
858
|
if (!appFolderExists) {
|
|
@@ -762,9 +862,9 @@ class JsAppsStrategy {
|
|
|
762
862
|
if (!appFolderStat?.isDirectory()) {
|
|
763
863
|
throw new Error(ERROR_MESSAGES.APP_FOLDER_NOT_DIRECTORY(appFolder));
|
|
764
864
|
}
|
|
765
|
-
const localBuildFolder =
|
|
766
|
-
const contentFolder =
|
|
767
|
-
const contentAppFolder =
|
|
865
|
+
const localBuildFolder = Path5.join(outputPath, NugetConstants2.OutputFolderName);
|
|
866
|
+
const contentFolder = Path5.join(localBuildFolder, NugetConstants2.ContentFolderName);
|
|
867
|
+
const contentAppFolder = Path5.join(contentFolder, CONTENT_APP_FOLDER_NAME);
|
|
768
868
|
await this.fileSystem.mkdir(contentFolder);
|
|
769
869
|
try {
|
|
770
870
|
logger?.progress("Copying .app folder into content/app...");
|
|
@@ -773,7 +873,7 @@ class JsAppsStrategy {
|
|
|
773
873
|
await this.prepareMetadataFiles(contentFolder, contentAppFolder, packageInfo, manifest, projectPath);
|
|
774
874
|
logger?.progress("Creating NuGet package...");
|
|
775
875
|
const nupkgFileName = `${packageInfo.id}.${packageInfo.version}.nupkg`;
|
|
776
|
-
const nupkgPath =
|
|
876
|
+
const nupkgPath = Path5.join(outputPath, nupkgFileName);
|
|
777
877
|
const packager = new NugetPackager2(this.fileSystem);
|
|
778
878
|
const result = await packager.packAsync(localBuildFolder, packageInfo, nupkgPath);
|
|
779
879
|
logger?.info(`Package created successfully: ${result.outputPath}`);
|
|
@@ -789,7 +889,7 @@ class JsAppsStrategy {
|
|
|
789
889
|
async prepareMetadataFiles(contentFolder, _contentAppFolder, _packageInfo, _manifest, projectPath) {
|
|
790
890
|
const mainFile = "index.html";
|
|
791
891
|
const mainRelativeToContent = `${CONTENT_APP_FOLDER_NAME}/${mainFile}`;
|
|
792
|
-
const operatePath =
|
|
892
|
+
const operatePath = Path5.join(contentFolder, NugetConstants2.OperateFileName);
|
|
793
893
|
const operateModel = {
|
|
794
894
|
projectId: await ensureWebAppProjectId(this.fileSystem, projectPath),
|
|
795
895
|
main: mainRelativeToContent,
|
|
@@ -803,8 +903,8 @@ class JsAppsStrategy {
|
|
|
803
903
|
};
|
|
804
904
|
const operateJson = JSON.stringify(operateModel, null, 2);
|
|
805
905
|
await this.fileSystem.writeFile(operatePath, operateJson);
|
|
806
|
-
const manifestSourcePath =
|
|
807
|
-
const manifestDestPath =
|
|
906
|
+
const manifestSourcePath = Path5.join(projectPath, WEBAPP_MANIFEST_FILE_NAME);
|
|
907
|
+
const manifestDestPath = Path5.join(contentFolder, WEBAPP_MANIFEST_FILE_NAME);
|
|
808
908
|
const manifestExists = await this.fileSystem.exists(manifestSourcePath);
|
|
809
909
|
if (manifestExists) {
|
|
810
910
|
const manifestContent = await this.fileSystem.readFile(manifestSourcePath);
|
|
@@ -812,8 +912,8 @@ class JsAppsStrategy {
|
|
|
812
912
|
await this.fileSystem.writeFile(manifestDestPath, manifestContent);
|
|
813
913
|
}
|
|
814
914
|
}
|
|
815
|
-
const uipathJsonSourcePath =
|
|
816
|
-
const uipathJsonDestPath =
|
|
915
|
+
const uipathJsonSourcePath = Path5.join(projectPath, "uipath.json");
|
|
916
|
+
const uipathJsonDestPath = Path5.join(contentFolder, "uipath.json");
|
|
817
917
|
const uipathJsonExists = await this.fileSystem.exists(uipathJsonSourcePath);
|
|
818
918
|
if (uipathJsonExists) {
|
|
819
919
|
const uipathJsonContent = await this.fileSystem.readFile(uipathJsonSourcePath);
|
|
@@ -821,20 +921,20 @@ class JsAppsStrategy {
|
|
|
821
921
|
await this.fileSystem.writeFile(uipathJsonDestPath, uipathJsonContent);
|
|
822
922
|
}
|
|
823
923
|
}
|
|
824
|
-
const bindingsPath =
|
|
924
|
+
const bindingsPath = Path5.join(contentFolder, "bindings.json");
|
|
825
925
|
const bindingsExists = await this.fileSystem.exists(bindingsPath);
|
|
826
926
|
if (!bindingsExists) {
|
|
827
927
|
const bindingsJson = JSON.stringify({ version: "1.0", resources: [] }, null, 2);
|
|
828
928
|
await this.fileSystem.writeFile(bindingsPath, bindingsJson);
|
|
829
929
|
}
|
|
830
|
-
const bindingsV2Path =
|
|
930
|
+
const bindingsV2Path = Path5.join(contentFolder, "bindings_v2.json");
|
|
831
931
|
const bindingsV2Exists = await this.fileSystem.exists(bindingsV2Path);
|
|
832
932
|
if (!bindingsV2Exists) {
|
|
833
933
|
const bindingsV2Json = JSON.stringify({ version: "2.0", resources: [] }, null, 2);
|
|
834
934
|
await this.fileSystem.writeFile(bindingsV2Path, bindingsV2Json);
|
|
835
935
|
}
|
|
836
|
-
const entryPointsPath =
|
|
837
|
-
const projectEntryPointsPath =
|
|
936
|
+
const entryPointsPath = Path5.join(contentFolder, "entry-points.json");
|
|
937
|
+
const projectEntryPointsPath = Path5.join(projectPath, "entry-points.json");
|
|
838
938
|
let entryPointsContent;
|
|
839
939
|
const projectEntryPointsExists = await this.fileSystem.exists(projectEntryPointsPath);
|
|
840
940
|
if (projectEntryPointsExists) {
|
|
@@ -848,12 +948,12 @@ class JsAppsStrategy {
|
|
|
848
948
|
entryPointsContent = this.createDefaultEntryPoints(mainRelativeToContent);
|
|
849
949
|
}
|
|
850
950
|
await this.fileSystem.writeFile(entryPointsPath, entryPointsContent);
|
|
851
|
-
const packageDescriptorPath =
|
|
951
|
+
const packageDescriptorPath = Path5.join(contentFolder, NugetConstants2.PackageDescriptorFileName);
|
|
852
952
|
const packageDescriptor = {
|
|
853
953
|
files: {
|
|
854
|
-
[NugetConstants2.OperateFileName]:
|
|
855
|
-
"entry-points.json":
|
|
856
|
-
"bindings.json":
|
|
954
|
+
[NugetConstants2.OperateFileName]: Path5.join(NugetConstants2.ContentFolderName, NugetConstants2.OperateFileName),
|
|
955
|
+
"entry-points.json": Path5.join(NugetConstants2.ContentFolderName, "entry-points.json"),
|
|
956
|
+
"bindings.json": Path5.join(NugetConstants2.ContentFolderName, "bindings_v2.json")
|
|
857
957
|
}
|
|
858
958
|
};
|
|
859
959
|
const packageDescriptorJson = JSON.stringify(packageDescriptor, null, 2);
|
|
@@ -983,7 +1083,7 @@ class WebAppTool extends ProjectTool2 {
|
|
|
983
1083
|
let manifest;
|
|
984
1084
|
let strategy;
|
|
985
1085
|
try {
|
|
986
|
-
const prepared = await this.getManifestAndStrategy(options.projectPath);
|
|
1086
|
+
const prepared = await this.getManifestAndStrategy(options.projectPath, options.codedBundle);
|
|
987
1087
|
manifest = prepared.manifest;
|
|
988
1088
|
strategy = prepared.strategy;
|
|
989
1089
|
} catch (error) {
|
|
@@ -1013,20 +1113,33 @@ class WebAppTool extends ProjectTool2 {
|
|
|
1013
1113
|
await this._temporaryStorage.cleanup();
|
|
1014
1114
|
} catch {}
|
|
1015
1115
|
}
|
|
1016
|
-
async getManifestAndStrategy(projectPath) {
|
|
1017
|
-
const manifestPath =
|
|
1116
|
+
async getManifestAndStrategy(projectPath, codedBundle) {
|
|
1117
|
+
const manifestPath = Path6.join(projectPath, WEBAPP_MANIFEST_FILE_NAME);
|
|
1018
1118
|
const manifestExists = await this.fileSystem.exists(manifestPath);
|
|
1019
|
-
if (!manifestExists) {
|
|
1119
|
+
if (!manifestExists && !codedBundle) {
|
|
1020
1120
|
throw new Error(ERROR_MESSAGES.MANIFEST_NOT_FOUND(WEBAPP_MANIFEST_FILE_NAME));
|
|
1021
1121
|
}
|
|
1022
|
-
const projectJsonPath =
|
|
1122
|
+
const projectJsonPath = Path6.join(projectPath, PROJECT_JSON_FILE);
|
|
1023
1123
|
if (await this.fileSystem.exists(projectJsonPath)) {
|
|
1024
1124
|
throw new Error(ERROR_MESSAGES.PROJECT_JSON_FOUND);
|
|
1025
1125
|
}
|
|
1026
|
-
|
|
1126
|
+
let manifest = manifestExists ? await loadWebAppManifest2(this.fileSystem, projectPath) : {
|
|
1127
|
+
type: "Coded" /* Coded */,
|
|
1128
|
+
solutionResourceSubType: "Coded" /* Coded */,
|
|
1129
|
+
config: { isCompiled: true }
|
|
1130
|
+
};
|
|
1027
1131
|
if (!manifest) {
|
|
1028
1132
|
throw new Error(ERROR_MESSAGES.MANIFEST_LOAD_FAILED(WEBAPP_MANIFEST_FILE_NAME));
|
|
1029
1133
|
}
|
|
1134
|
+
if (codedBundle) {
|
|
1135
|
+
if (manifest.type !== "Coded" /* Coded */) {
|
|
1136
|
+
throw new Error("A coded bundle requires a Coded webAppManifest.json.");
|
|
1137
|
+
}
|
|
1138
|
+
manifest = {
|
|
1139
|
+
...manifest,
|
|
1140
|
+
config: { ...manifest.config, ...codedBundle }
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1030
1143
|
const strategy = VariantStrategyFactory.createStrategy(manifest, this.fileSystem);
|
|
1031
1144
|
return { manifest, strategy };
|
|
1032
1145
|
}
|
|
@@ -1086,4 +1199,4 @@ export {
|
|
|
1086
1199
|
validateActionSchema
|
|
1087
1200
|
};
|
|
1088
1201
|
|
|
1089
|
-
//# debugId=
|
|
1202
|
+
//# debugId=373EDDEBABAD6ECD64756E2164756E21
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { isBundleRelativePath, isCanonicalBundleChild, isHtmlEntryPointPath, normalizeBundlePath, resolveHtmlEntryPoint, } from "./utils/bundle-path.js";
|
|
1
2
|
/**
|
|
2
3
|
* Constants used throughout the WebApp tool implementation
|
|
3
4
|
*/
|
|
@@ -29,6 +30,12 @@ export declare const TARGET_JS_RUNTIME = "JS";
|
|
|
29
30
|
* Default entry point type
|
|
30
31
|
*/
|
|
31
32
|
export declare const DEFAULT_ENTRY_POINT_TYPE = "api";
|
|
33
|
+
/**
|
|
34
|
+
* HTML entry points a packed coded app may boot from, in the order
|
|
35
|
+
* `operate.json`'s `main` is resolved. A bundle with none of them produces an
|
|
36
|
+
* app that cannot start, so pack refuses it rather than shipping it.
|
|
37
|
+
*/
|
|
38
|
+
export declare const HTML_ENTRY_POINT_CANDIDATES: readonly ["index.html", "main.html", "app.html"];
|
|
32
39
|
/**
|
|
33
40
|
* Error messages
|
|
34
41
|
*/
|
|
@@ -38,6 +45,12 @@ export declare const ERROR_MESSAGES: {
|
|
|
38
45
|
readonly MANIFEST_LOAD_FAILED: (file: string) => string;
|
|
39
46
|
readonly BUNDLE_NOT_FOUND: (path: string) => string;
|
|
40
47
|
readonly BUNDLE_NOT_DIRECTORY: (path: string) => string;
|
|
48
|
+
readonly BUNDLE_OUTSIDE_PROJECT: (path: string) => string;
|
|
49
|
+
readonly BUNDLE_NO_ENTRY_POINT: (path: string) => string;
|
|
50
|
+
readonly MAIN_FILE_INVALID_TYPE: "Invalid webAppManifest.json: config.mainFile must be a string naming an HTML file, or be omitted.";
|
|
51
|
+
readonly MAIN_FILE_NOT_IN_BUNDLE: (path: string, mainFile: string) => string;
|
|
52
|
+
readonly MAIN_FILE_LOST: (path: string, mainFile: string) => string;
|
|
53
|
+
readonly BUNDLE_ENTRY_POINT_LOST: (path: string) => string;
|
|
41
54
|
readonly APP_FOLDER_NOT_FOUND: (path: string) => string;
|
|
42
55
|
readonly APP_FOLDER_NOT_DIRECTORY: (path: string) => string;
|
|
43
56
|
readonly BUILD_NOT_SUPPORTED: "Build execution (isCompiled=false) is not yet supported. Please build the project manually and set isCompiled=true.";
|