@salesforce/packaging 0.0.3 → 0.0.6
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/CHANGELOG.md +12 -0
- package/lib/constants.d.ts +21 -0
- package/lib/constants.js +40 -0
- package/lib/interfaces/packagingInterfacesAndType.d.ts +111 -0
- package/lib/interfaces/packagingSObjects.d.ts +2 -1
- package/lib/interfaces/packagingSObjects.js +0 -6
- package/lib/package/index.d.ts +4 -0
- package/lib/package/index.js +8 -0
- package/lib/package/packageConvert.d.ts +11 -0
- package/lib/package/packageConvert.js +78 -0
- package/lib/package/packageCreate.d.ts +26 -0
- package/lib/package/packageCreate.js +115 -0
- package/lib/package/packageDelete.d.ts +3 -0
- package/lib/package/packageDelete.js +26 -0
- package/lib/package/packageVersion.d.ts +8 -0
- package/lib/package/packageVersion.js +27 -0
- package/lib/package/packageVersionCreate.d.ts +70 -0
- package/lib/package/packageVersionCreate.js +781 -0
- package/lib/package/packageVersionCreateRequest.d.ts +4 -0
- package/lib/package/packageVersionCreateRequest.js +85 -0
- package/lib/package/packageVersionList.d.ts +9 -0
- package/lib/package/packageVersionList.js +91 -0
- package/lib/package/profileApi.d.ts +55 -0
- package/lib/package/profileApi.js +275 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/lib/utils/packageUtils.d.ts +7 -6
- package/lib/utils/packageUtils.js +51 -13
- package/lib/utils/srcDevUtils.d.ts +12 -0
- package/lib/utils/srcDevUtils.js +62 -0
- package/lib/utils/versionNumber.d.ts +1 -0
- package/lib/utils/versionNumber.js +5 -0
- package/messages/messages.md +17 -0
- package/package.json +10 -5
- package/lib/package/packageVersionCreateRequestApi.d.ts +0 -17
- package/lib/package/packageVersionCreateRequestApi.js +0 -92
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Connection } from '@salesforce/core';
|
|
2
|
+
import { Package2VersionCreateRequestResult, PackageVersionCreateRequestQueryOptions } from '../interfaces';
|
|
3
|
+
export declare function list(options?: PackageVersionCreateRequestQueryOptions): Promise<Package2VersionCreateRequestResult[]>;
|
|
4
|
+
export declare function byId(package2VersionCreateRequestId: any, connection: Connection): Promise<Package2VersionCreateRequestResult[]>;
|
|
@@ -0,0 +1,85 @@
|
|
|
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.byId = exports.list = void 0;
|
|
10
|
+
const util = require("util");
|
|
11
|
+
const core_1 = require("@salesforce/core");
|
|
12
|
+
const packageUtils = require("../utils/packageUtils");
|
|
13
|
+
core_1.Messages.importMessagesDirectory(__dirname);
|
|
14
|
+
const messages = core_1.Messages.loadMessages('@salesforce/packaging', 'messages');
|
|
15
|
+
const STATUS_ERROR = 'Error';
|
|
16
|
+
const QUERY = 'SELECT Id, Status, Package2Id, Package2VersionId, Package2Version.SubscriberPackageVersionId, Tag, Branch, ' +
|
|
17
|
+
'CreatedDate, Package2Version.HasMetadataRemoved, CreatedById ' +
|
|
18
|
+
'FROM Package2VersionCreateRequest ' +
|
|
19
|
+
'%s' + // WHERE, if applicable
|
|
20
|
+
'ORDER BY CreatedDate';
|
|
21
|
+
const ERROR_QUERY = "SELECT Message FROM Package2VersionCreateRequestError WHERE ParentRequest.Id = '%s'";
|
|
22
|
+
const STATUSES = ['Queued', 'InProgress', 'Success', 'Error'];
|
|
23
|
+
async function list(options = {}) {
|
|
24
|
+
const whereClause = _constructWhere();
|
|
25
|
+
return _query(util.format(QUERY, whereClause), options.connection);
|
|
26
|
+
}
|
|
27
|
+
exports.list = list;
|
|
28
|
+
async function byId(package2VersionCreateRequestId, connection) {
|
|
29
|
+
const results = await _query(util.format(QUERY, `WHERE Id = '${package2VersionCreateRequestId}' `), connection);
|
|
30
|
+
if (results && results.length === 1 && results[0].Status === STATUS_ERROR) {
|
|
31
|
+
results[0].Error = await _queryErrors(package2VersionCreateRequestId, connection);
|
|
32
|
+
}
|
|
33
|
+
return results;
|
|
34
|
+
}
|
|
35
|
+
exports.byId = byId;
|
|
36
|
+
async function _query(query, connection) {
|
|
37
|
+
const queryResult = await connection.tooling.query(query);
|
|
38
|
+
return (queryResult.records ? queryResult.records : []).map((record) => ({
|
|
39
|
+
Id: record.Id,
|
|
40
|
+
Status: record.Status,
|
|
41
|
+
Package2Id: record.Package2Id,
|
|
42
|
+
Package2VersionId: record.Package2VersionId,
|
|
43
|
+
SubscriberPackageVersionId: record.Package2Version != null ? record.Package2Version.SubscriberPackageVersionId : null,
|
|
44
|
+
Tag: record.Tag,
|
|
45
|
+
Branch: record.Branch,
|
|
46
|
+
Error: [],
|
|
47
|
+
CreatedDate: packageUtils.formatDate(new Date(record.CreatedDate)),
|
|
48
|
+
HasMetadataRemoved: record.Package2Version != null ? record.Package2Version.HasMetadataRemoved : null,
|
|
49
|
+
CreatedBy: record.CreatedById,
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
async function _queryErrors(package2VersionCreateRequestId, connection) {
|
|
53
|
+
const errorResults = [];
|
|
54
|
+
const queryResult = connection.tooling.query(util.format(ERROR_QUERY, package2VersionCreateRequestId));
|
|
55
|
+
if (queryResult.records) {
|
|
56
|
+
queryResult.records.forEach((record) => {
|
|
57
|
+
errorResults.push(record.Message);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return errorResults;
|
|
61
|
+
}
|
|
62
|
+
function _constructWhere(options) {
|
|
63
|
+
const where = [];
|
|
64
|
+
// filter on created date, days ago: 0 for today, etc
|
|
65
|
+
if (!util.isNullOrUndefined(this.options.createdlastdays)) {
|
|
66
|
+
if (options.createdlastdays < 0) {
|
|
67
|
+
throw new Error(messages.getMessage('invalidDaysNumber', ['createdlastdays', options.createdlastdays]));
|
|
68
|
+
}
|
|
69
|
+
where.push(`CreatedDate = LAST_N_DAYS:${this.options.createdlastdays}`);
|
|
70
|
+
}
|
|
71
|
+
// filter on errors
|
|
72
|
+
if (options.status) {
|
|
73
|
+
const foundStatus = STATUSES.find((status) => status.toLowerCase() === this.options.status.toLowerCase());
|
|
74
|
+
if (!foundStatus) {
|
|
75
|
+
const args = [options.status];
|
|
76
|
+
STATUSES.forEach((status) => {
|
|
77
|
+
args.push(status);
|
|
78
|
+
});
|
|
79
|
+
throw new Error(messages.getMessage('invalidStatus', args));
|
|
80
|
+
}
|
|
81
|
+
where.push(`Status = '${foundStatus}'`);
|
|
82
|
+
}
|
|
83
|
+
return where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=packageVersionCreateRequest.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SfProject } from '@salesforce/core';
|
|
2
|
+
import { QueryResult } from 'jsforce';
|
|
3
|
+
import { PackageVersionListResult, PackageVersionQueryOptions } from '../interfaces';
|
|
4
|
+
export declare const DEFAULT_ORDER_BY_FIELDS = "Package2Id, Branch, MajorVersion, MinorVersion, PatchVersion, BuildNumber";
|
|
5
|
+
export declare function listPackageVersions(options: PackageVersionQueryOptions): Promise<QueryResult<PackageVersionListResult>>;
|
|
6
|
+
export declare function _constructQuery(options: PackageVersionQueryOptions): string;
|
|
7
|
+
export declare function _assembleQueryParts(select: string, where: string[], orderBy?: string): string;
|
|
8
|
+
export declare function _constructWhere(idsOrAliases: string[], createdLastDays: number, lastModLastDays: number, project: SfProject): string[];
|
|
9
|
+
export declare function _getLastDays(paramName: string, lastDays: number): number;
|
|
@@ -0,0 +1,91 @@
|
|
|
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._getLastDays = exports._constructWhere = exports._assembleQueryParts = exports._constructQuery = exports.listPackageVersions = exports.DEFAULT_ORDER_BY_FIELDS = void 0;
|
|
10
|
+
const core_1 = require("@salesforce/core");
|
|
11
|
+
const ts_types_1 = require("@salesforce/ts-types");
|
|
12
|
+
const utils_1 = require("../utils");
|
|
13
|
+
core_1.Messages.importMessagesDirectory(__dirname);
|
|
14
|
+
const messages = core_1.Messages.loadMessages('@salesforce/packaging', 'messages');
|
|
15
|
+
// Stripping CodeCoverage, HasPassedCodeCoverageCheck as they are causing a perf issue in 47.0+ W-6997762
|
|
16
|
+
const DEFAULT_SELECT = 'SELECT Id, Package2Id, SubscriberPackageVersionId, Name, Package2.Name, Package2.NamespacePrefix, ' +
|
|
17
|
+
'Description, Tag, Branch, MajorVersion, MinorVersion, PatchVersion, BuildNumber, IsReleased, ' +
|
|
18
|
+
'CreatedDate, LastModifiedDate, IsPasswordProtected, AncestorId, ValidationSkipped, CreatedById ' +
|
|
19
|
+
'FROM Package2Version';
|
|
20
|
+
const VERBOSE_SELECT = 'SELECT Id, Package2Id, SubscriberPackageVersionId, Name, Package2.Name, Package2.NamespacePrefix, ' +
|
|
21
|
+
'Description, Tag, Branch, MajorVersion, MinorVersion, PatchVersion, BuildNumber, IsReleased, ' +
|
|
22
|
+
'CreatedDate, LastModifiedDate, IsPasswordProtected, CodeCoverage, HasPassedCodeCoverageCheck, AncestorId, ValidationSkipped, ' +
|
|
23
|
+
'ConvertedFromVersionId, Package2.IsOrgDependent, ReleaseVersion, BuildDurationInSeconds, HasMetadataRemoved, CreatedById ' +
|
|
24
|
+
'FROM Package2Version';
|
|
25
|
+
exports.DEFAULT_ORDER_BY_FIELDS = 'Package2Id, Branch, MajorVersion, MinorVersion, PatchVersion, BuildNumber';
|
|
26
|
+
const logger = core_1.Logger.childFromRoot('packageVersionList');
|
|
27
|
+
async function listPackageVersions(options) {
|
|
28
|
+
return options.connection.tooling.query(_constructQuery(options));
|
|
29
|
+
}
|
|
30
|
+
exports.listPackageVersions = listPackageVersions;
|
|
31
|
+
function _constructQuery(options) {
|
|
32
|
+
// construct custom WHERE clause, if applicable
|
|
33
|
+
const where = _constructWhere(options.packages, options.createdLastDays, options.modifiedLastDays, options.project);
|
|
34
|
+
if (options.isReleased) {
|
|
35
|
+
where.push('IsReleased = true');
|
|
36
|
+
}
|
|
37
|
+
return _assembleQueryParts(options.verbose === true ? VERBOSE_SELECT : DEFAULT_SELECT, where, options.orderBy);
|
|
38
|
+
}
|
|
39
|
+
exports._constructQuery = _constructQuery;
|
|
40
|
+
function _assembleQueryParts(select, where, orderBy = exports.DEFAULT_ORDER_BY_FIELDS) {
|
|
41
|
+
// construct ORDER BY clause
|
|
42
|
+
// TODO: validate given fields
|
|
43
|
+
const orderByPart = `ORDER BY ${orderBy ? orderBy : exports.DEFAULT_ORDER_BY_FIELDS}`;
|
|
44
|
+
const wherePart = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
|
|
45
|
+
const query = `${select} ${wherePart} ${orderByPart}`;
|
|
46
|
+
logger.debug(query);
|
|
47
|
+
return query;
|
|
48
|
+
}
|
|
49
|
+
exports._assembleQueryParts = _assembleQueryParts;
|
|
50
|
+
// construct custom WHERE clause parts
|
|
51
|
+
function _constructWhere(idsOrAliases, createdLastDays, lastModLastDays, project) {
|
|
52
|
+
const where = [];
|
|
53
|
+
// filter on given package ids
|
|
54
|
+
if ((idsOrAliases === null || idsOrAliases === void 0 ? void 0 : idsOrAliases.length) > 0) {
|
|
55
|
+
// remove dups
|
|
56
|
+
const aliasesOrIds = [...new Set(idsOrAliases)];
|
|
57
|
+
// resolve any aliases
|
|
58
|
+
const packageIds = aliasesOrIds.map((idOrAlias) => (0, utils_1.getPackageIdFromAlias)(idOrAlias, project));
|
|
59
|
+
// validate ids
|
|
60
|
+
packageIds.forEach((packageId) => {
|
|
61
|
+
(0, utils_1.validateId)(utils_1.BY_LABEL.PACKAGE_ID, packageId);
|
|
62
|
+
});
|
|
63
|
+
// stash where part
|
|
64
|
+
where.push(`Package2Id IN ('${packageIds.join("','")}')`);
|
|
65
|
+
}
|
|
66
|
+
// filter on created date, days ago: 0 for today, etc
|
|
67
|
+
if ((0, ts_types_1.isNumber)(createdLastDays)) {
|
|
68
|
+
createdLastDays = _getLastDays('createdlastdays', createdLastDays);
|
|
69
|
+
where.push(`CreatedDate = LAST_N_DAYS:${createdLastDays}`);
|
|
70
|
+
}
|
|
71
|
+
// filter on last mod date, days ago: 0 for today, etc
|
|
72
|
+
if ((0, ts_types_1.isNumber)(lastModLastDays)) {
|
|
73
|
+
lastModLastDays = _getLastDays('modifiedlastdays', lastModLastDays);
|
|
74
|
+
where.push(`LastModifiedDate = LAST_N_DAYS:${lastModLastDays}`);
|
|
75
|
+
}
|
|
76
|
+
// exclude deleted
|
|
77
|
+
where.push('IsDeprecated = false');
|
|
78
|
+
return where;
|
|
79
|
+
}
|
|
80
|
+
exports._constructWhere = _constructWhere;
|
|
81
|
+
function _getLastDays(paramName, lastDays) {
|
|
82
|
+
if (isNaN(lastDays)) {
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
if (lastDays < 0) {
|
|
86
|
+
throw messages.createError('invalidDaysNumber', [paramName, `${lastDays}`]);
|
|
87
|
+
}
|
|
88
|
+
return lastDays;
|
|
89
|
+
}
|
|
90
|
+
exports._getLastDays = _getLastDays;
|
|
91
|
+
//# sourceMappingURL=packageVersionList.js.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ConfigAggregator, SfProject } from '@salesforce/core';
|
|
2
|
+
export declare class ProfileApi {
|
|
3
|
+
project: SfProject;
|
|
4
|
+
includeUserLicenses: boolean;
|
|
5
|
+
generateProfileInformation: boolean;
|
|
6
|
+
readonly profiles: ProfileInformation[];
|
|
7
|
+
apiVersion: string;
|
|
8
|
+
nodeEntities: {
|
|
9
|
+
name: string[];
|
|
10
|
+
childElement: string[];
|
|
11
|
+
parentElement: string[];
|
|
12
|
+
};
|
|
13
|
+
otherProfileSettings: {
|
|
14
|
+
name: string[];
|
|
15
|
+
childElement: string[];
|
|
16
|
+
parentElement: string[];
|
|
17
|
+
};
|
|
18
|
+
config: ConfigAggregator;
|
|
19
|
+
constructor(project: SfProject, includeUserLicenses: boolean, generateProfileInformation?: boolean);
|
|
20
|
+
/**
|
|
21
|
+
* For any profile present in the workspace, this function generates a subset of data that only contains references
|
|
22
|
+
* to items in the manifest.
|
|
23
|
+
*
|
|
24
|
+
* @param destPath location of new profiles
|
|
25
|
+
* @param manifest
|
|
26
|
+
* @param excludedDirectories Directories to not include profiles from
|
|
27
|
+
*/
|
|
28
|
+
generateProfiles(destPath: string, manifest: {
|
|
29
|
+
Package: {
|
|
30
|
+
types: string[];
|
|
31
|
+
};
|
|
32
|
+
}, excludedDirectories?: string[]): any[];
|
|
33
|
+
/**
|
|
34
|
+
* Filter out all profiles in the manifest and if any profiles exists in the workspace, add them to the manifest.
|
|
35
|
+
*
|
|
36
|
+
* @param typesArr array of objects { name[], members[] } that represent package types JSON.
|
|
37
|
+
* @param excludedDirectories Direcotires not to generate profiles for
|
|
38
|
+
*/
|
|
39
|
+
filterAndGenerateProfilesForManifest(typesArr: any, excludedDirectories?: string[]): any;
|
|
40
|
+
getProfileInformation(): ProfileInformation[];
|
|
41
|
+
private copyNodes;
|
|
42
|
+
private findAllProfiles;
|
|
43
|
+
}
|
|
44
|
+
declare class ProfileInformation {
|
|
45
|
+
ProfileName: string;
|
|
46
|
+
ProfilePath: string;
|
|
47
|
+
IsPackaged: boolean;
|
|
48
|
+
settingsRemoved: string[];
|
|
49
|
+
constructor(ProfileName: string, ProfilePath: string, IsPackaged: boolean, settingsRemoved: string[]);
|
|
50
|
+
setIsPackaged(IsPackaged: boolean): void;
|
|
51
|
+
appendRemovedSetting(setting: string): void;
|
|
52
|
+
logDebug(): string;
|
|
53
|
+
logInfo(): string;
|
|
54
|
+
}
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,275 @@
|
|
|
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.ProfileApi = 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
|
+
// Local
|
|
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 ProfileApi {
|
|
25
|
+
constructor(project, includeUserLicenses, generateProfileInformation = false) {
|
|
26
|
+
this.project = project;
|
|
27
|
+
this.includeUserLicenses = includeUserLicenses;
|
|
28
|
+
this.generateProfileInformation = generateProfileInformation;
|
|
29
|
+
this.profiles = [];
|
|
30
|
+
(async () => {
|
|
31
|
+
this.config = await core_1.ConfigAggregator.create();
|
|
32
|
+
})();
|
|
33
|
+
this.apiVersion = this.config.getPropertyValue('apiVersion');
|
|
34
|
+
// nodeEntities is used to determine which elements in the profile are relevant to the source being packaged.
|
|
35
|
+
// name refers to the entity type name in source that the element pertains to. As an example, a profile may
|
|
36
|
+
// have an entry like the example below, which should only be added to the packaged profile if the related
|
|
37
|
+
// CustomObject is in the source being packaged:
|
|
38
|
+
// <objectPermissions>
|
|
39
|
+
// <allowCreate>true</allowCreate>
|
|
40
|
+
// ...
|
|
41
|
+
// <object>MyCustomObject__c</object>
|
|
42
|
+
// ...
|
|
43
|
+
// </objectPermissions>
|
|
44
|
+
//
|
|
45
|
+
// For this example: nodeEntities.parentElement = objectPermissions and nodeEntities.childElement = object
|
|
46
|
+
this.nodeEntities = {
|
|
47
|
+
name: [
|
|
48
|
+
'CustomObject',
|
|
49
|
+
'CustomField',
|
|
50
|
+
'Layout',
|
|
51
|
+
'CustomTab',
|
|
52
|
+
'CustomApplication',
|
|
53
|
+
'ApexClass',
|
|
54
|
+
'CustomPermission',
|
|
55
|
+
'ApexPage',
|
|
56
|
+
'ExternalDataSource',
|
|
57
|
+
'RecordType',
|
|
58
|
+
],
|
|
59
|
+
parentElement: [
|
|
60
|
+
'objectPermissions',
|
|
61
|
+
'fieldPermissions',
|
|
62
|
+
'layoutAssignments',
|
|
63
|
+
'tabVisibilities',
|
|
64
|
+
'applicationVisibilities',
|
|
65
|
+
'classAccesses',
|
|
66
|
+
'customPermissions',
|
|
67
|
+
'pageAccesses',
|
|
68
|
+
'externalDataSourceAccesses',
|
|
69
|
+
'recordTypeVisibilities',
|
|
70
|
+
],
|
|
71
|
+
childElement: [
|
|
72
|
+
'object',
|
|
73
|
+
'field',
|
|
74
|
+
'layout',
|
|
75
|
+
'tab',
|
|
76
|
+
'application',
|
|
77
|
+
'apexClass',
|
|
78
|
+
'name',
|
|
79
|
+
'apexPage',
|
|
80
|
+
'externalDataSource',
|
|
81
|
+
'recordType',
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
// There are some profile settings that are allowed to be packaged that may not necessarily map to a specific metadata
|
|
85
|
+
// object. We should still handle these accordingly, but a little differently than the above mentioned types.
|
|
86
|
+
this.otherProfileSettings = {
|
|
87
|
+
name: ['CustomSettings', 'CustomMetadataTypeAccess'],
|
|
88
|
+
parentElement: ['customSettingAccesses', 'customMetadataTypeAccesses'],
|
|
89
|
+
childElement: ['name', 'name'],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* For any profile present in the workspace, this function generates a subset of data that only contains references
|
|
94
|
+
* to items in the manifest.
|
|
95
|
+
*
|
|
96
|
+
* @param destPath location of new profiles
|
|
97
|
+
* @param manifest
|
|
98
|
+
* @param excludedDirectories Directories to not include profiles from
|
|
99
|
+
*/
|
|
100
|
+
generateProfiles(destPath, manifest, excludedDirectories = []) {
|
|
101
|
+
const excludedProfiles = [];
|
|
102
|
+
const profilePaths = this.findAllProfiles(excludedDirectories);
|
|
103
|
+
if (!profilePaths) {
|
|
104
|
+
return excludedProfiles;
|
|
105
|
+
}
|
|
106
|
+
profilePaths.forEach((profilePath) => {
|
|
107
|
+
// profile metadata can present in any directory in the package structure
|
|
108
|
+
const profileName = profilePath.match(/([^/]+)\.profile-meta.xml/)[1];
|
|
109
|
+
const profileDom = new xmldom_sfdx_encoding_1.DOMParser().parseFromString(fs.readFileSync(profilePath, 'utf-8'));
|
|
110
|
+
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>');
|
|
111
|
+
const profileNode = newDom.getElementsByTagName('Profile')[0];
|
|
112
|
+
let hasNodes = false;
|
|
113
|
+
// We need to keep track of all the members for when we package up the "OtherProfileSettings"
|
|
114
|
+
let allMembers = [];
|
|
115
|
+
manifest.Package.types.forEach((element) => {
|
|
116
|
+
const name = element['name'];
|
|
117
|
+
const members = element['members'];
|
|
118
|
+
allMembers = allMembers.concat(members);
|
|
119
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
120
|
+
const idx = this.nodeEntities.name.indexOf(name[0]);
|
|
121
|
+
if (idx > -1) {
|
|
122
|
+
hasNodes =
|
|
123
|
+
this.copyNodes(profileDom, this.nodeEntities.parentElement[idx], this.nodeEntities.childElement[idx], members, profileNode, profileName) || hasNodes;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
// Go through each of the other profile settings we might want to include. We pass in "all" the members since these
|
|
127
|
+
// will reference anything that could be packaged. The "copyNodes" function will only include the type if it
|
|
128
|
+
// exists in the profile itself
|
|
129
|
+
this.otherProfileSettings.name.forEach((element) => {
|
|
130
|
+
const idx = this.otherProfileSettings.name.indexOf(element);
|
|
131
|
+
if (idx > -1) {
|
|
132
|
+
hasNodes =
|
|
133
|
+
this.copyNodes(profileDom, this.otherProfileSettings.parentElement[idx], this.otherProfileSettings.childElement[idx], allMembers, profileNode, profileName) || hasNodes;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
// add userLicenses to the profile
|
|
137
|
+
if (this.includeUserLicenses === true) {
|
|
138
|
+
const userLicenses = profileDom.getElementsByTagName('userLicense');
|
|
139
|
+
if (userLicenses) {
|
|
140
|
+
hasNodes = true;
|
|
141
|
+
for (const userLicense of userLicenses) {
|
|
142
|
+
profileNode.appendChild(userLicense.cloneNode(true));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const xmlSrcFile = path.basename(profilePath);
|
|
147
|
+
const xmlFile = xmlSrcFile.replace(/(.*)(-meta.xml)/, '$1');
|
|
148
|
+
const destFilePath = path.join(destPath, xmlFile);
|
|
149
|
+
if (hasNodes) {
|
|
150
|
+
const serializer = new xmldom_sfdx_encoding_1.XMLSerializer();
|
|
151
|
+
serializer.serializeToString(newDom);
|
|
152
|
+
fs.writeFileSync(destFilePath, serializer.serializeToString(newDom), 'utf-8');
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// remove from manifest
|
|
156
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
157
|
+
const profileName = xmlFile.replace(/(.*)(\.profile)/, '$1');
|
|
158
|
+
excludedProfiles.push(profileName);
|
|
159
|
+
if (this.generateProfileInformation) {
|
|
160
|
+
const profile = this.profiles.find(({ ProfileName }) => ProfileName === profileName);
|
|
161
|
+
if (profile) {
|
|
162
|
+
profile.setIsPackaged(false);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
fs.unlinkSync(destFilePath);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
// It is normal for the file to not exist if the profile is in the worskpace but not in the directory being packaged.
|
|
170
|
+
if (err.code !== 'ENOENT') {
|
|
171
|
+
throw err;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
return excludedProfiles;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Filter out all profiles in the manifest and if any profiles exists in the workspace, add them to the manifest.
|
|
180
|
+
*
|
|
181
|
+
* @param typesArr array of objects { name[], members[] } that represent package types JSON.
|
|
182
|
+
* @param excludedDirectories Direcotires not to generate profiles for
|
|
183
|
+
*/
|
|
184
|
+
filterAndGenerateProfilesForManifest(typesArr, excludedDirectories = []) {
|
|
185
|
+
const profilePaths = this.findAllProfiles(excludedDirectories);
|
|
186
|
+
// Filter all profiles
|
|
187
|
+
typesArr = typesArr.filter((kvp) => kvp.name[0] !== 'Profile');
|
|
188
|
+
if (profilePaths) {
|
|
189
|
+
const members = [];
|
|
190
|
+
profilePaths.forEach((profilePath) => {
|
|
191
|
+
// profile metadata can present in any directory in the package structure
|
|
192
|
+
const profileName = profilePath.match(/([^/]+)\.profile-meta.xml/)[1];
|
|
193
|
+
members.push(profileName);
|
|
194
|
+
if (this.generateProfileInformation) {
|
|
195
|
+
this.profiles.push(new ProfileInformation(profileName, profilePath, true, []));
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
if (members.length > 0) {
|
|
199
|
+
typesArr.push({ name: ['Profile'], members });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return typesArr;
|
|
203
|
+
}
|
|
204
|
+
getProfileInformation() {
|
|
205
|
+
return this.profiles;
|
|
206
|
+
}
|
|
207
|
+
copyNodes(originalDom, parentElement, childElement, members, appendToNode, profileName) {
|
|
208
|
+
let nodesAdded = false;
|
|
209
|
+
const nodes = originalDom.getElementsByTagName(parentElement);
|
|
210
|
+
if (!nodes) {
|
|
211
|
+
return nodesAdded;
|
|
212
|
+
}
|
|
213
|
+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
214
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
215
|
+
const name = nodes[i].getElementsByTagName(childElement)[0].childNodes[0].nodeValue;
|
|
216
|
+
if (members.indexOf(name) >= 0) {
|
|
217
|
+
// appendChild will take the passed in node (newNode) and find the parent if it exists and then remove
|
|
218
|
+
// the newNode from the parent. This causes issues with the way this is copying the nodes, so pass in a clone instead.
|
|
219
|
+
const currentNode = nodes[i].cloneNode(true);
|
|
220
|
+
appendToNode.appendChild(currentNode);
|
|
221
|
+
nodesAdded = true;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
// Tell the user which profile setting has been removed from the package
|
|
225
|
+
if (this.generateProfileInformation) {
|
|
226
|
+
const profile = this.profiles.find(({ ProfileName }) => ProfileName === profileName);
|
|
227
|
+
if (profile) {
|
|
228
|
+
profile.appendRemovedSetting(name);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return nodesAdded;
|
|
234
|
+
}
|
|
235
|
+
findAllProfiles(excludedDirectories = []) {
|
|
236
|
+
return glob.sync(path.join(this.project.getPath(), '**', '*.profile-meta.xml'), {
|
|
237
|
+
ignore: excludedDirectories.map((dir) => `**/${dir}/**`),
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
exports.ProfileApi = ProfileApi;
|
|
242
|
+
class ProfileInformation {
|
|
243
|
+
constructor(ProfileName, ProfilePath, IsPackaged, settingsRemoved) {
|
|
244
|
+
this.ProfileName = ProfileName;
|
|
245
|
+
this.ProfilePath = ProfilePath;
|
|
246
|
+
this.IsPackaged = IsPackaged;
|
|
247
|
+
this.settingsRemoved = settingsRemoved;
|
|
248
|
+
}
|
|
249
|
+
setIsPackaged(IsPackaged) {
|
|
250
|
+
this.IsPackaged = IsPackaged;
|
|
251
|
+
}
|
|
252
|
+
appendRemovedSetting(setting) {
|
|
253
|
+
this.settingsRemoved.push(setting);
|
|
254
|
+
}
|
|
255
|
+
logDebug() {
|
|
256
|
+
let info = profileApiMessages.getMessage('profile_api.addProfileToPackage', [this.ProfileName, this.ProfilePath]);
|
|
257
|
+
this.settingsRemoved.forEach((setting) => {
|
|
258
|
+
info += '\n\t' + profileApiMessages.getMessage('profile_api.removeProfileSetting', [setting, this.ProfileName]);
|
|
259
|
+
});
|
|
260
|
+
if (!this.IsPackaged) {
|
|
261
|
+
info += '\n\t' + profileApiMessages.getMessage('profile_api.removeProfile', [this.ProfileName]);
|
|
262
|
+
}
|
|
263
|
+
info += '\n';
|
|
264
|
+
return info;
|
|
265
|
+
}
|
|
266
|
+
logInfo() {
|
|
267
|
+
if (this.IsPackaged) {
|
|
268
|
+
return profileApiMessages.getMessage('profile_api.addProfileToPackage', [this.ProfileName, this.ProfilePath]);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
return profileApiMessages.getMessage('profile_api.profileNotIncluded', [this.ProfileName]);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=profileApi.js.map
|
package/lib/utils/index.d.ts
CHANGED
package/lib/utils/index.js
CHANGED
|
@@ -21,4 +21,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
21
21
|
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
22
22
|
*/
|
|
23
23
|
__exportStar(require("./packageUtils"), exports);
|
|
24
|
+
__exportStar(require("./srcDevUtils"), exports);
|
|
24
25
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Connection, NamedPackageDir, PackageDir, SfProject } from '@salesforce/core';
|
|
1
|
+
import { Connection, NamedPackageDir, PackageDir, SfError, SfProject } from '@salesforce/core';
|
|
2
2
|
import { Duration } from '@salesforce/kit';
|
|
3
3
|
import { Many } from '@salesforce/ts-types';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { SaveError } from 'jsforce';
|
|
5
|
+
import { PackagingSObjects, Package2VersionCreateRequestResult, PackageVersionCreateOptions } from '../interfaces';
|
|
6
6
|
export declare const VERSION_NUMBER_SEP = ".";
|
|
7
7
|
export declare type IdRegistryValue = {
|
|
8
8
|
prefix: string;
|
|
@@ -123,7 +123,7 @@ export declare function getAncestorIdHighestRelease(connection: Connection, pack
|
|
|
123
123
|
export declare function concatVersion(major: string | number, minor: string | number, patch: string | number, build: string | number): string;
|
|
124
124
|
export declare function getPackage2VersionNumber(package2VersionObj: PackagingSObjects.Package2Version): string;
|
|
125
125
|
export declare function getConfigPackageDirectories(project: SfProject): PackageDir[];
|
|
126
|
-
export declare function getConfigPackageDirectory(packageDirs: NamedPackageDir[], lookupProperty: string, lookupValue: unknown): NamedPackageDir | undefined;
|
|
126
|
+
export declare function getConfigPackageDirectory(packageDirs: NamedPackageDir[] | PackageDir[], lookupProperty: string, lookupValue: unknown): NamedPackageDir | PackageDir | undefined;
|
|
127
127
|
/**
|
|
128
128
|
* Given a packageAlias, attempt to return the associated id from the config
|
|
129
129
|
*
|
|
@@ -146,7 +146,8 @@ export declare function convertCamelCaseStringToSentence(stringIn: string): stri
|
|
|
146
146
|
*/
|
|
147
147
|
export declare function getPackageAliasesFromId(packageId: string, project: SfProject): string[];
|
|
148
148
|
export declare function findOrCreatePackage2(seedPackage: string, connection: Connection): Promise<string>;
|
|
149
|
-
export declare function
|
|
150
|
-
export declare function pollForStatusWithInterval(context: any, id: string, retries: number, packageId: string, branch: string, withProject: SfProject, connection: Connection, interval: Duration): Promise<Package2VersionCreateRequestResult>;
|
|
149
|
+
export declare function pollForStatusWithInterval(id: string, retries: number, packageId: string, branch: string, withProject: SfProject, connection: Connection, interval: Duration): Promise<Package2VersionCreateRequestResult>;
|
|
151
150
|
export declare function getSoqlWhereClauseMaxLength(): number;
|
|
152
151
|
export declare function formatDate(date: Date): string;
|
|
152
|
+
export declare function combineSaveErrors(sObject: string, crudOperation: string, errors: SaveError[]): SfError;
|
|
153
|
+
export declare function resolveCanonicalPackageProperty(options: PackageVersionCreateOptions): "id" | "package";
|