@salesforce/packaging 0.0.4 → 0.0.7

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/lib/constants.d.ts +21 -0
  3. package/lib/constants.js +40 -0
  4. package/lib/interfaces/packagingInterfacesAndType.d.ts +85 -4
  5. package/lib/interfaces/packagingSObjects.d.ts +2 -1
  6. package/lib/interfaces/packagingSObjects.js +0 -6
  7. package/lib/package/index.d.ts +4 -1
  8. package/lib/package/index.js +7 -2
  9. package/lib/package/packageConvert.d.ts +11 -0
  10. package/lib/package/packageConvert.js +84 -0
  11. package/lib/package/packageCreate.d.ts +26 -0
  12. package/lib/package/packageCreate.js +115 -0
  13. package/lib/package/packageDelete.d.ts +3 -0
  14. package/lib/package/packageDelete.js +26 -0
  15. package/lib/package/packageProfileApi.d.ts +59 -0
  16. package/lib/package/packageProfileApi.js +278 -0
  17. package/lib/package/packageVersion.d.ts +25 -0
  18. package/lib/package/packageVersion.js +73 -0
  19. package/lib/package/packageVersionCreate.d.ts +68 -0
  20. package/lib/package/packageVersionCreate.js +758 -0
  21. package/lib/package/packageVersionCreateRequest.d.ts +4 -0
  22. package/lib/package/packageVersionCreateRequest.js +85 -0
  23. package/lib/package/packageVersionList.d.ts +4 -24
  24. package/lib/package/packageVersionList.js +4 -5
  25. package/lib/utils/index.d.ts +1 -0
  26. package/lib/utils/index.js +1 -0
  27. package/lib/utils/packageUtils.d.ts +15 -14
  28. package/lib/utils/packageUtils.js +77 -39
  29. package/lib/utils/srcDevUtils.d.ts +12 -0
  30. package/lib/utils/srcDevUtils.js +66 -0
  31. package/lib/utils/versionNumber.d.ts +1 -0
  32. package/lib/utils/versionNumber.js +10 -5
  33. package/messages/messages.md +49 -0
  34. package/package.json +11 -16
  35. package/lib/package/packageVersion2GP.d.ts +0 -17
  36. package/lib/package/packageVersion2GP.js +0 -46
  37. package/lib/package/packageVersionCreateRequestApi.d.ts +0 -17
  38. package/lib/package/packageVersionCreateRequestApi.js +0 -92
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2022, salesforce.com, inc.
4
+ * All rights reserved.
5
+ * Licensed under the BSD 3-Clause license.
6
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.PackageProfileApi = void 0;
10
+ const path = require("path");
11
+ const fs = require("fs");
12
+ const glob = require("glob");
13
+ const xmldom_sfdx_encoding_1 = require("xmldom-sfdx-encoding");
14
+ const core_1 = require("@salesforce/core");
15
+ const kit_1 = require("@salesforce/kit");
16
+ core_1.Messages.importMessagesDirectory(__dirname);
17
+ // TODO: need to transfer these messages
18
+ const profileApiMessages = core_1.Messages.loadMessages('@salesforce/packaging', 'messages');
19
+ /*
20
+ * This class provides functions used to re-write .profiles in the workspace when creating a package2 version.
21
+ * All profiles found in the workspaces are extracted out and then re-written to only include metadata in the profile
22
+ * that is relevant to the source in the package directory being packaged.
23
+ */
24
+ class PackageProfileApi extends kit_1.AsyncCreatable {
25
+ constructor(options) {
26
+ super(options);
27
+ this.options = options;
28
+ this.profiles = [];
29
+ this.generateProfileInformation = false;
30
+ }
31
+ async init() {
32
+ this.project = this.options.project;
33
+ this.includeUserLicenses = this.options.includeUserLicenses;
34
+ this.generateProfileInformation = this.options.generateProfileInformation;
35
+ this.config = await core_1.ConfigAggregator.create();
36
+ this.apiVersion = this.config.getPropertyValue('apiVersion');
37
+ // nodeEntities is used to determine which elements in the profile are relevant to the source being packaged.
38
+ // name refers to the entity type name in source that the element pertains to. As an example, a profile may
39
+ // have an entry like the example below, which should only be added to the packaged profile if the related
40
+ // CustomObject is in the source being packaged:
41
+ // <objectPermissions>
42
+ // <allowCreate>true</allowCreate>
43
+ // ...
44
+ // <object>MyCustomObject__c</object>
45
+ // ...
46
+ // </objectPermissions>
47
+ //
48
+ // For this example: nodeEntities.parentElement = objectPermissions and nodeEntities.childElement = object
49
+ this.nodeEntities = {
50
+ name: [
51
+ 'CustomObject',
52
+ 'CustomField',
53
+ 'Layout',
54
+ 'CustomTab',
55
+ 'CustomApplication',
56
+ 'ApexClass',
57
+ 'CustomPermission',
58
+ 'ApexPage',
59
+ 'ExternalDataSource',
60
+ 'RecordType',
61
+ ],
62
+ parentElement: [
63
+ 'objectPermissions',
64
+ 'fieldPermissions',
65
+ 'layoutAssignments',
66
+ 'tabVisibilities',
67
+ 'applicationVisibilities',
68
+ 'classAccesses',
69
+ 'customPermissions',
70
+ 'pageAccesses',
71
+ 'externalDataSourceAccesses',
72
+ 'recordTypeVisibilities',
73
+ ],
74
+ childElement: [
75
+ 'object',
76
+ 'field',
77
+ 'layout',
78
+ 'tab',
79
+ 'application',
80
+ 'apexClass',
81
+ 'name',
82
+ 'apexPage',
83
+ 'externalDataSource',
84
+ 'recordType',
85
+ ],
86
+ };
87
+ // There are some profile settings that are allowed to be packaged that may not necessarily map to a specific metadata
88
+ // object. We should still handle these accordingly, but a little differently than the above mentioned types.
89
+ this.otherProfileSettings = {
90
+ name: ['CustomSettings', 'CustomMetadataTypeAccess'],
91
+ parentElement: ['customSettingAccesses', 'customMetadataTypeAccesses'],
92
+ childElement: ['name', 'name'],
93
+ };
94
+ }
95
+ /**
96
+ * For any profile present in the workspace, this function generates a subset of data that only contains references
97
+ * to items in the manifest.
98
+ *
99
+ * @param destPath location of new profiles
100
+ * @param manifest
101
+ * @param excludedDirectories Directories to not include profiles from
102
+ */
103
+ generateProfiles(destPath, manifest, excludedDirectories = []) {
104
+ const excludedProfiles = [];
105
+ const profilePaths = this.findAllProfiles(excludedDirectories);
106
+ if (!profilePaths) {
107
+ return excludedProfiles;
108
+ }
109
+ profilePaths.forEach((profilePath) => {
110
+ // profile metadata can present in any directory in the package structure
111
+ const profileName = profilePath.match(/([^/]+)\.profile-meta.xml/)[1];
112
+ const profileDom = new xmldom_sfdx_encoding_1.DOMParser().parseFromString(fs.readFileSync(profilePath, 'utf-8'));
113
+ const newDom = new xmldom_sfdx_encoding_1.DOMParser().parseFromString('<?xml version="1.0" encoding="UTF-8"?><Profile xmlns="http://soap.sforce.com/2006/04/metadata"></Profile>');
114
+ const profileNode = newDom.getElementsByTagName('Profile')[0];
115
+ let hasNodes = false;
116
+ // We need to keep track of all the members for when we package up the "OtherProfileSettings"
117
+ let allMembers = [];
118
+ manifest.Package.types.forEach((element) => {
119
+ const name = element['name'];
120
+ const members = element['members'];
121
+ allMembers = allMembers.concat(members);
122
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
123
+ const idx = this.nodeEntities.name.indexOf(name[0]);
124
+ if (idx > -1) {
125
+ hasNodes =
126
+ this.copyNodes(profileDom, this.nodeEntities.parentElement[idx], this.nodeEntities.childElement[idx], members, profileNode, profileName) || hasNodes;
127
+ }
128
+ });
129
+ // Go through each of the other profile settings we might want to include. We pass in "all" the members since these
130
+ // will reference anything that could be packaged. The "copyNodes" function will only include the type if it
131
+ // exists in the profile itself
132
+ this.otherProfileSettings.name.forEach((element) => {
133
+ const idx = this.otherProfileSettings.name.indexOf(element);
134
+ if (idx > -1) {
135
+ hasNodes =
136
+ this.copyNodes(profileDom, this.otherProfileSettings.parentElement[idx], this.otherProfileSettings.childElement[idx], allMembers, profileNode, profileName) || hasNodes;
137
+ }
138
+ });
139
+ // add userLicenses to the profile
140
+ if (this.includeUserLicenses === true) {
141
+ const userLicenses = profileDom.getElementsByTagName('userLicense');
142
+ if (userLicenses) {
143
+ hasNodes = true;
144
+ for (const userLicense of userLicenses) {
145
+ profileNode.appendChild(userLicense.cloneNode(true));
146
+ }
147
+ }
148
+ }
149
+ const xmlSrcFile = path.basename(profilePath);
150
+ const xmlFile = xmlSrcFile.replace(/(.*)(-meta.xml)/, '$1');
151
+ const destFilePath = path.join(destPath, xmlFile);
152
+ if (hasNodes) {
153
+ const serializer = new xmldom_sfdx_encoding_1.XMLSerializer();
154
+ serializer.serializeToString(newDom);
155
+ fs.writeFileSync(destFilePath, serializer.serializeToString(newDom), 'utf-8');
156
+ }
157
+ else {
158
+ // remove from manifest
159
+ // eslint-disable-next-line @typescript-eslint/no-shadow
160
+ const profileName = xmlFile.replace(/(.*)(\.profile)/, '$1');
161
+ excludedProfiles.push(profileName);
162
+ if (this.generateProfileInformation) {
163
+ const profile = this.profiles.find(({ ProfileName }) => ProfileName === profileName);
164
+ if (profile) {
165
+ profile.setIsPackaged(false);
166
+ }
167
+ }
168
+ try {
169
+ fs.unlinkSync(destFilePath);
170
+ }
171
+ catch (err) {
172
+ // It is normal for the file to not exist if the profile is in the worskpace but not in the directory being packaged.
173
+ if (err.code !== 'ENOENT') {
174
+ throw err;
175
+ }
176
+ }
177
+ }
178
+ });
179
+ return excludedProfiles;
180
+ }
181
+ /**
182
+ * Filter out all profiles in the manifest and if any profiles exists in the workspace, add them to the manifest.
183
+ *
184
+ * @param typesArr array of objects { name[], members[] } that represent package types JSON.
185
+ * @param excludedDirectories Direcotires not to generate profiles for
186
+ */
187
+ filterAndGenerateProfilesForManifest(typesArr, excludedDirectories = []) {
188
+ const profilePaths = this.findAllProfiles(excludedDirectories);
189
+ // Filter all profiles
190
+ typesArr = typesArr.filter((kvp) => kvp.name[0] !== 'Profile');
191
+ if (profilePaths) {
192
+ const members = [];
193
+ profilePaths.forEach((profilePath) => {
194
+ // profile metadata can present in any directory in the package structure
195
+ const profileName = profilePath.match(/([^/]+)\.profile-meta.xml/)[1];
196
+ members.push(profileName);
197
+ if (this.generateProfileInformation) {
198
+ this.profiles.push(new ProfileInformation(profileName, profilePath, true, []));
199
+ }
200
+ });
201
+ if (members.length > 0) {
202
+ typesArr.push({ name: ['Profile'], members });
203
+ }
204
+ }
205
+ return typesArr;
206
+ }
207
+ getProfileInformation() {
208
+ return this.profiles;
209
+ }
210
+ copyNodes(originalDom, parentElement, childElement, members, appendToNode, profileName) {
211
+ let nodesAdded = false;
212
+ const nodes = originalDom.getElementsByTagName(parentElement);
213
+ if (!nodes) {
214
+ return nodesAdded;
215
+ }
216
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
217
+ for (let i = 0; i < nodes.length; i++) {
218
+ const name = nodes[i].getElementsByTagName(childElement)[0].childNodes[0].nodeValue;
219
+ if (members.indexOf(name) >= 0) {
220
+ // appendChild will take the passed in node (newNode) and find the parent if it exists and then remove
221
+ // the newNode from the parent. This causes issues with the way this is copying the nodes, so pass in a clone instead.
222
+ const currentNode = nodes[i].cloneNode(true);
223
+ appendToNode.appendChild(currentNode);
224
+ nodesAdded = true;
225
+ }
226
+ else {
227
+ // Tell the user which profile setting has been removed from the package
228
+ if (this.generateProfileInformation) {
229
+ const profile = this.profiles.find(({ ProfileName }) => ProfileName === profileName);
230
+ if (profile) {
231
+ profile.appendRemovedSetting(name);
232
+ }
233
+ }
234
+ }
235
+ }
236
+ return nodesAdded;
237
+ }
238
+ findAllProfiles(excludedDirectories = []) {
239
+ return glob.sync(path.join(this.project.getPath(), '**', '*.profile-meta.xml'), {
240
+ ignore: excludedDirectories.map((dir) => `**/${dir}/**`),
241
+ });
242
+ }
243
+ }
244
+ exports.PackageProfileApi = PackageProfileApi;
245
+ class ProfileInformation {
246
+ constructor(ProfileName, ProfilePath, IsPackaged, settingsRemoved) {
247
+ this.ProfileName = ProfileName;
248
+ this.ProfilePath = ProfilePath;
249
+ this.IsPackaged = IsPackaged;
250
+ this.settingsRemoved = settingsRemoved;
251
+ }
252
+ setIsPackaged(IsPackaged) {
253
+ this.IsPackaged = IsPackaged;
254
+ }
255
+ appendRemovedSetting(setting) {
256
+ this.settingsRemoved.push(setting);
257
+ }
258
+ logDebug() {
259
+ let info = profileApiMessages.getMessage('profile_api.addProfileToPackage', [this.ProfileName, this.ProfilePath]);
260
+ this.settingsRemoved.forEach((setting) => {
261
+ info += '\n\t' + profileApiMessages.getMessage('profile_api.removeProfileSetting', [setting, this.ProfileName]);
262
+ });
263
+ if (!this.IsPackaged) {
264
+ info += '\n\t' + profileApiMessages.getMessage('profile_api.removeProfile', [this.ProfileName]);
265
+ }
266
+ info += '\n';
267
+ return info;
268
+ }
269
+ logInfo() {
270
+ if (this.IsPackaged) {
271
+ return profileApiMessages.getMessage('profile_api.addProfileToPackage', [this.ProfileName, this.ProfilePath]);
272
+ }
273
+ else {
274
+ return profileApiMessages.getMessage('profile_api.profileNotIncluded', [this.ProfileName]);
275
+ }
276
+ }
277
+ }
278
+ //# sourceMappingURL=packageProfileApi.js.map
@@ -0,0 +1,25 @@
1
+ import { PackageVersionCreateRequestResult, PackageSaveResult, PackageVersionCreateOptions, PackageVersionOptions } from '../interfaces';
2
+ export declare class PackageVersion {
3
+ private options;
4
+ private readonly project;
5
+ private readonly connection;
6
+ constructor(options: PackageVersionOptions);
7
+ /**
8
+ * Creates a new package version.
9
+ *
10
+ * @param options
11
+ */
12
+ create(options: PackageVersionCreateOptions): Promise<Partial<PackageVersionCreateRequestResult>>;
13
+ /**
14
+ * Deletes a package version.
15
+ *
16
+ * @param idOrAlias
17
+ * @param undelete
18
+ */
19
+ delete(idOrAlias: string, undelete?: boolean): Promise<PackageSaveResult>;
20
+ convert(): Promise<void>;
21
+ install(): Promise<void>;
22
+ list(): Promise<void>;
23
+ uninstall(): Promise<void>;
24
+ update(): Promise<void>;
25
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2020, salesforce.com, inc.
4
+ * All rights reserved.
5
+ * Licensed under the BSD 3-Clause license.
6
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.PackageVersion = void 0;
10
+ const core_1 = require("@salesforce/core");
11
+ const pkgUtils = require("../utils/packageUtils");
12
+ const utils_1 = require("../utils");
13
+ const packageVersionCreate_1 = require("./packageVersionCreate");
14
+ core_1.Messages.importMessagesDirectory(__dirname);
15
+ // const messages = Messages.loadMessages('@salesforce/packaging', 'messages');
16
+ // const logger = Logger.childFromRoot('packageVersionCreate');
17
+ class PackageVersion {
18
+ constructor(options) {
19
+ this.options = options;
20
+ this.connection = this.options.connection;
21
+ this.project = this.options.project;
22
+ }
23
+ /**
24
+ * Creates a new package version.
25
+ *
26
+ * @param options
27
+ */
28
+ async create(options) {
29
+ const pvc = new packageVersionCreate_1.PackageVersionCreate({ ...options, ...this.options });
30
+ return pvc.createPackageVersion();
31
+ }
32
+ /**
33
+ * Deletes a package version.
34
+ *
35
+ * @param idOrAlias
36
+ * @param undelete
37
+ */
38
+ async delete(idOrAlias, undelete = false) {
39
+ const packageVersionId = pkgUtils.getPackageIdFromAlias(idOrAlias, this.project);
40
+ // ID can be an 04t or 05i
41
+ pkgUtils.validateId([pkgUtils.BY_LABEL.SUBSCRIBER_PACKAGE_VERSION_ID, pkgUtils.BY_LABEL.PACKAGE_VERSION_ID], packageVersionId);
42
+ // lookup the 05i ID, if needed
43
+ const packageId = await pkgUtils.getPackageVersionId(packageVersionId, this.connection);
44
+ // setup the request
45
+ const request = {
46
+ Id: packageId,
47
+ IsDeprecated: !undelete,
48
+ };
49
+ const updateResult = await this.connection.tooling.update('Package2Version', request);
50
+ if (!updateResult.success) {
51
+ throw (0, utils_1.combineSaveErrors)('Package2', 'update', updateResult.errors);
52
+ }
53
+ updateResult.id = await pkgUtils.getSubscriberPackageVersionId(packageVersionId, this.connection);
54
+ return updateResult;
55
+ }
56
+ convert() {
57
+ return Promise.resolve(undefined);
58
+ }
59
+ install() {
60
+ return Promise.resolve(undefined);
61
+ }
62
+ list() {
63
+ return Promise.resolve(undefined);
64
+ }
65
+ uninstall() {
66
+ return Promise.resolve(undefined);
67
+ }
68
+ update() {
69
+ return Promise.resolve(undefined);
70
+ }
71
+ }
72
+ exports.PackageVersion = PackageVersion;
73
+ //# sourceMappingURL=packageVersion.js.map
@@ -0,0 +1,68 @@
1
+ import { Connection } from '@salesforce/core';
2
+ import { PackageVersionCreateRequestResult, PackageVersionCreateOptions } from '../interfaces';
3
+ export declare class PackageVersionCreate {
4
+ private options;
5
+ private apiVersionFromPackageXml;
6
+ private readonly project;
7
+ private readonly connection;
8
+ constructor(options: PackageVersionCreateOptions);
9
+ createPackageVersion(): Promise<Partial<PackageVersionCreateRequestResult>>;
10
+ listRequest(createdlastdays?: number, status?: string): Promise<PackageVersionCreateRequestResult[]>;
11
+ listRequestById(id: string, connection: Connection): Promise<PackageVersionCreateRequestResult[]>;
12
+ private generateMDFolderForArtifact;
13
+ private validateDependencyValues;
14
+ /**
15
+ * A dependency in the workspace config file may be specified using either a subscriber package version id (04t)
16
+ * or a package Id (0Ho) + a version number. Additionally, a build number may be the actual build number, or a
17
+ * keyword: LATEST or RELEASED (meaning the latest or released build number for a given major.minor.patch).
18
+ *
19
+ * This method resolves a package Id + version number to a subscriber package version id (04t)
20
+ * and adds it as a SubscriberPackageVersionId parameter in the dependency object.
21
+ */
22
+ private retrieveSubscriberPackageVersionId;
23
+ private resolveBuildNumber;
24
+ private createRequestObject;
25
+ private getPackageDescriptorJsonFromPackageId;
26
+ /**
27
+ * Convert the list of command line options to a JSON object that can be used to create an Package2VersionCreateRequest entity.
28
+ *
29
+ * @param options
30
+ * @param packageId
31
+ * @param versionNumberString
32
+ * @returns {{Package2Id: (*|p|boolean), Package2VersionMetadata: *, Tag: *, Branch: number}}
33
+ * @private
34
+ */
35
+ private createPackageVersionCreateRequestFromOptions;
36
+ private resolveApexTestPermissions;
37
+ private resolveUnpackagedMetadata;
38
+ private getPackagePropertyFromPackage;
39
+ private getPackageValuePropertyFromDirectory;
40
+ /**
41
+ * Returns the property value that corresponds to the propertyToLookup. This value found for a particular
42
+ * package directory element that matches the knownProperty and knownValue. In other words, we locate a package
43
+ * directory element whose knownProperty matches the knownValue, then we grab the value for the propertyToLookup
44
+ * and return it.
45
+ *
46
+ * @param packageDirs The list of all the package directories from the sfdx-project.json
47
+ * @param propertyToLookup The property ID whose value we want to find
48
+ * @param knownProperty The JSON property in the packageDirectories that is already known
49
+ * @param knownValue The value that corresponds to the knownProperty in the packageDirectories JSON
50
+ * @param knownFlag The flag details e.g. short/long name, etc. Only used for the error message
51
+ * @param options
52
+ */
53
+ private getConfigPackageDirectoriesValue;
54
+ private packageVersionCreate;
55
+ private resolveCanonicalPackageProperty;
56
+ private validateVersionNumber;
57
+ private resolveUserLicenses;
58
+ private resolveOrgDependentPollingTime;
59
+ private validateFlagsForPackageType;
60
+ /**
61
+ * Cleans invalid attribute(s) from the packageDescriptorJSON
62
+ */
63
+ private cleanPackageDescriptorJson;
64
+ /**
65
+ * Sets default or override values for packageDescriptorJSON attribs
66
+ */
67
+ private setPackageDescriptorJsonValues;
68
+ }