@salesforce/packaging
Version:
Packaging library for the Salesforce packaging platform
171 lines • 8.49 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.retrievePackageVersionMetadata = retrievePackageVersionMetadata;
/*
* Copyright (c) 2023, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
const node_path_1 = __importDefault(require("node:path"));
const node_fs_1 = __importDefault(require("node:fs"));
const core_1 = require("@salesforce/core");
const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
const kit_1 = require("@salesforce/kit");
const packageUtils_1 = require("../utils/packageUtils");
const packageCreate_1 = require("./packageCreate");
const package_1 = require("./package");
const packageVersion_1 = require("./packageVersion");
core_1.Messages.importMessagesDirectory(__dirname);
const messages = core_1.Messages.loadMessages('@salesforce/packaging', 'package');
/**
* Download the metadata files for a previously published package version, convert them to source format, and put them into a new project folder within the sfdx project.
*
* @param project
* @param options {@link PackageVersionMetadataDownloadOptions}
* @param connection
* @returns
*/
async function retrievePackageVersionMetadata(project, options, connection) {
// Validate the destination path is suitable to extract package version metadata (must be new or empty)
const destinationFolder = options.destinationFolder ?? 'force-app';
if (node_path_1.default.isAbsolute(destinationFolder)) {
throw messages.createError('sourcesDownloadDirectoryMustBeRelative');
}
const destinationPath = node_path_1.default.join(project.getPath(), destinationFolder);
if (!node_fs_1.default.existsSync(destinationPath)) {
node_fs_1.default.mkdirSync(destinationPath, { recursive: true });
}
if (!(0, packageUtils_1.isPackageDirectoryEffectivelyEmpty)(destinationPath)) {
throw messages.createError('sourcesDownloadDirectoryNotEmpty');
}
// Get the DeveloperUsePkgZip URL from the Package2Version record
const subscriberPackageVersionId = project.getPackageIdFromAlias(options.subscriberPackageVersionId) ?? options.subscriberPackageVersionId;
// Query Package2Version to get the record by SubscriberPackageVersionId
const queryOptions = {
whereClause: `WHERE SubscriberPackageVersionId = '${subscriberPackageVersionId}'`,
};
let versionInfo;
try {
[versionInfo] = await packageVersion_1.PackageVersion.queryPackage2Version(connection, queryOptions);
}
catch (e) {
const msg = e instanceof Error ? e.message : String(e);
if (msg.includes("No such column 'DeveloperUsePkgZip' on entity 'Package2Version'")) {
throw messages.createError('developerUsePkgZipFieldUnavailable');
}
if (msg.includes("sObject type 'Package2Version' is not supported.")) {
throw messages.createError('packagingNotEnabledOnOrg');
}
throw e;
}
if (!versionInfo?.DeveloperUsePkgZip) {
throw messages.createError('developerUsePkgZipFieldUnavailable');
}
const responseBase64 = await connection.tooling.request(versionInfo.DeveloperUsePkgZip, {
encoding: 'base64',
});
const buffer = Buffer.from(responseBase64, 'base64');
let tree;
try {
tree = await source_deploy_retrieve_1.ZipTreeContainer.create(buffer);
}
catch (e) {
if (e instanceof Error && e.message.includes('data length = 0')) {
throw messages.createError('downloadDeveloperPackageZipHasNoData');
}
throw e;
}
let dependencies = [];
// 2GP packages declare their dependencies in dependency-ids.json within the outer zip.
if (tree.exists('dependency-ids.json')) {
const f = await tree.readFile('dependency-ids.json');
const idsObj = JSON.parse(f.toString());
if (idsObj?.ids) {
dependencies = idsObj.ids;
}
}
// 2GP packages have the package.zip wrapped in an outer zip.
if (tree.exists('package.zip')) {
tree = await source_deploy_retrieve_1.ZipTreeContainer.create(await tree.readFile('package.zip'));
}
const zipComponents = source_deploy_retrieve_1.ComponentSet.fromSource({
fsPaths: ['.'],
tree,
})
.getSourceComponents()
.toArray();
const result = await new source_deploy_retrieve_1.MetadataConverter().convert(zipComponents, 'source', {
type: 'directory',
outputDirectory: destinationPath,
genUniqueDir: false,
});
await attemptToUpdateProjectJson(project, connection, versionInfo.Package2Id, subscriberPackageVersionId, dependencies, destinationFolder);
return result;
}
/**
* Attempt to update the sfdx-project.json file to add information about the retrieved sources. If this fails for some reason we
* print out an error message and return so the user will still see a list of retrieved metadata.
*
*/
async function attemptToUpdateProjectJson(project, connection, packageId, subscriberPackageVersionId, dependencyIds, destinationFolder) {
const logger = core_1.Logger.childFromRoot('packageVersionRetrieve');
if (kit_1.env.getBoolean('SF_PROJECT_AUTOUPDATE_DISABLE_FOR_PACKAGE_VERSION_RETRIEVE')) {
logger.info('Skipping sfdx-project.json updates because SF_PROJECT_AUTOUPDATE_DISABLE_FOR_PACKAGE_VERSION_RETRIEVE is set');
return;
}
try {
const queryOptions = {
whereClause: `WHERE SubscriberPackageVersionId = '${subscriberPackageVersionId}'`,
};
const [version] = await packageVersion_1.PackageVersion.queryPackage2Version(connection, queryOptions);
if (version) {
const pkg = new package_1.Package({
packageAliasOrId: version.Package2Id,
project,
connection,
});
const pkgData = await pkg.getPackageData();
if (pkgData) {
const dirEntry = (0, packageCreate_1.createPackageDirEntry)(project, {
name: pkgData.Name,
description: pkgData.Description,
path: destinationFolder,
noNamespace: pkgData.NamespacePrefix != null,
orgDependent: pkgData.IsOrgDependent,
packageType: pkgData.ContainerOptions,
errorNotificationUsername: pkgData.PackageErrorUsername,
});
const namedDir = {
...dirEntry,
versionNumber: '<set version number>',
versionName: '<set version name>',
ancestorVersion: '<set ancestor version>',
dependencies: dependencyIds.map((dep) => ({ package: dep })),
};
project.getSfProjectJson().addPackageDirectory(namedDir);
const packageVersionVersionString = `${version.MajorVersion}.${version.MinorVersion}.${version.PatchVersion}-${version.BuildNumber}`;
const [alias, writtenId] = await (0, packageUtils_1.generatePackageAliasEntry)(connection, project, subscriberPackageVersionId, packageVersionVersionString, 'main', pkg.getId());
project.getSfProjectJson().addPackageAlias(alias, writtenId);
if (pkgData.ContainerOptions === 'Managed' && !project.getSfProjectJson().get('namespace')) {
project.getSfProjectJson().set('namespace', pkgData.NamespacePrefix);
}
await project.getSfProjectJson().write();
}
else {
logger.warn(`Failed to update sfdx-project.json. Could not find package for ${version.Package2Id}. This should never happen.`);
}
}
else {
logger.info(`Could not find Package2Version record for ${subscriberPackageVersionId}. No updates to sfdx-project.json will be made.`);
}
}
catch (e) {
const msg = e instanceof Error ? e.message : e;
logger.error(`Encountered error trying to update sfdx-project.json after retrieving package version metadata: ${msg}`);
}
}
//# sourceMappingURL=packageVersionRetrieve.js.map