UNPKG

@salesforce/packaging

Version:

Packaging library for the Salesforce packaging platform

117 lines 6.69 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PackageProfileApi = void 0; /* * Copyright (c) 2022, 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_os_1 = __importDefault(require("node:os")); const node_fs_1 = __importDefault(require("node:fs")); const globby_1 = __importDefault(require("globby")); const core_1 = require("@salesforce/core"); const kit_1 = require("@salesforce/kit"); const profileRewriter_1 = require("./profileRewriter"); core_1.Messages.importMessagesDirectory(__dirname); const profileApiMessages = core_1.Messages.loadMessages('@salesforce/packaging', 'profile_api'); /* * This class provides functions used to re-write .profiles in the project package directories when creating a package2 version. * All profiles found in the project package directories are extracted out and then re-written to only include metadata in the * profile that is relevant to the source in the package directory being packaged. */ class PackageProfileApi extends kit_1.AsyncCreatable { project; includeUserLicenses = false; constructor(options) { super(options); this.project = options.project; this.includeUserLicenses = options.includeUserLicenses ?? false; } // eslint-disable-next-line class-methods-use-this,@typescript-eslint/no-empty-function async init() { } /** * For any profile present in the project package directories, this function generates a subset of data that only * contains references to items in the manifest. * * return a list of profile file locations that need to be removed from the package because they are empty * * @param destPath location of new profiles * @param manifestTypes: array of objects { name: string, members: string[] } that represent package xml types * @param excludedDirectories Directories to not include profiles from */ generateProfiles(destPath, manifestTypes, excludedDirectories = []) { const logger = core_1.Logger.childFromRoot('PackageProfileApi'); return (this.getProfilesWithNamesAndPaths(excludedDirectories) .map(({ profilePath, name: profileName }) => { const originalProfile = (0, profileRewriter_1.profileStringToProfile)(node_fs_1.default.readFileSync(profilePath, 'utf-8')); const adjustedProfile = (0, profileRewriter_1.profileRewriter)(originalProfile, (0, profileRewriter_1.manifestTypesToMap)(manifestTypes), this.includeUserLicenses); return { profileName, profilePath, hasContent: Object.keys(adjustedProfile).length, adjustedProfile, removedSettings: getRemovedSettings(originalProfile, adjustedProfile), xmlFileLocation: getXmlFileLocation(destPath, profilePath), }; }) // side effect: modify profiles in place .filter(({ hasContent, profileName, removedSettings, profilePath, xmlFileLocation, adjustedProfile }) => { if (!hasContent) { logger.warn(`Profile ${profileName} has no content after filtering. It will still be part of the package but you can remove it if it's not needed.`); return true; } else { logger.info(profileApiMessages.getMessage('addProfileToPackage', [profileName, profilePath])); removedSettings.forEach((setting) => { logger.info(profileApiMessages.getMessage('removeProfileSetting', [setting, profileName])); }); node_fs_1.default.writeFileSync(xmlFileLocation, (0, profileRewriter_1.profileObjectToString)(adjustedProfile), 'utf-8'); } }) .map(({ xmlFileLocation }) => xmlFileLocation.replace(/(.*)(\.profile)/, '$1'))); } /** * Filter out all profiles in the manifest and if any profiles exist in the project package directories, add them to the manifest. * * @param typesArr array of objects { name[], members[] } that represent package types JSON. * @param excludedDirectories Direcotires not to generate profiles for */ filterAndGenerateProfilesForManifest(typesArr, excludedDirectories = []) { const profilePathsWithNames = this.getProfilesWithNamesAndPaths(excludedDirectories); // Filter all profiles, and add back the ones we found names for return typesArr .filter((kvp) => kvp.name !== 'Profile') .concat([{ name: 'Profile', members: profilePathsWithNames.map((i) => i.name) }]); } // Look for profiles in all package directories findAllProfiles(excludedDirectories = []) { const ignore = excludedDirectories.map((dir) => `**/${dir.split(node_path_1.default.sep).join(node_path_1.default.posix.sep)}/**`); const patterns = this.project .getUniquePackageDirectories() .map((pDir) => pDir.fullPath) .map((fullDir) => node_os_1.default.type() === 'Windows_NT' ? node_path_1.default.posix.join(...fullDir.split(node_path_1.default.sep), '**', '*.profile-meta.xml') : node_path_1.default.join(fullDir, '**', '*.profile-meta.xml')); return globby_1.default.sync(patterns, { ignore }); } getProfilesWithNamesAndPaths(excludedDirectories) { return this.findAllProfiles(excludedDirectories) .map((profilePath) => ({ profilePath, name: profilePathToName(profilePath) })) .filter(isProfilePathWithName); } } exports.PackageProfileApi = PackageProfileApi; const isProfilePathWithName = (profilePathWithName) => typeof profilePathWithName.name === 'string'; const profilePathToName = (profilePath) => profilePath.match(/([^/]+)\.profile-meta.xml/)?.[1]; const getXmlFileLocation = (destPath, profilePath) => node_path_1.default.join(destPath, node_path_1.default.basename(profilePath).replace(/(.*)(-meta.xml)/, '$1')); const getRemovedSettings = (originalProfile, adjustedProfile) => { const originalProfileSettings = Object.keys(originalProfile); const adjustedProfileSettings = new Set(Object.keys(adjustedProfile)); return originalProfileSettings.filter((setting) => !adjustedProfileSettings.has(setting)); }; //# sourceMappingURL=packageProfileApi.js.map