@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.
- package/CHANGELOG.md +16 -0
- package/lib/constants.d.ts +21 -0
- package/lib/constants.js +40 -0
- package/lib/interfaces/packagingInterfacesAndType.d.ts +85 -4
- package/lib/interfaces/packagingSObjects.d.ts +2 -1
- package/lib/interfaces/packagingSObjects.js +0 -6
- package/lib/package/index.d.ts +4 -1
- package/lib/package/index.js +7 -2
- package/lib/package/packageConvert.d.ts +11 -0
- package/lib/package/packageConvert.js +84 -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/packageProfileApi.d.ts +59 -0
- package/lib/package/packageProfileApi.js +278 -0
- package/lib/package/packageVersion.d.ts +25 -0
- package/lib/package/packageVersion.js +73 -0
- package/lib/package/packageVersionCreate.d.ts +68 -0
- package/lib/package/packageVersionCreate.js +758 -0
- package/lib/package/packageVersionCreateRequest.d.ts +4 -0
- package/lib/package/packageVersionCreateRequest.js +85 -0
- package/lib/package/packageVersionList.d.ts +4 -24
- package/lib/package/packageVersionList.js +4 -5
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/lib/utils/packageUtils.d.ts +15 -14
- package/lib/utils/packageUtils.js +77 -39
- package/lib/utils/srcDevUtils.d.ts +12 -0
- package/lib/utils/srcDevUtils.js +66 -0
- package/lib/utils/versionNumber.d.ts +1 -0
- package/lib/utils/versionNumber.js +10 -5
- package/messages/messages.md +49 -0
- package/package.json +11 -16
- package/lib/package/packageVersion2GP.d.ts +0 -17
- package/lib/package/packageVersion2GP.js +0 -46
- package/lib/package/packageVersionCreateRequestApi.d.ts +0 -17
- package/lib/package/packageVersionCreateRequestApi.js +0 -92
|
@@ -0,0 +1,758 @@
|
|
|
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.PackageVersionCreate = void 0;
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const os = require("os");
|
|
12
|
+
const fs = require("fs");
|
|
13
|
+
const core_1 = require("@salesforce/core");
|
|
14
|
+
const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
|
|
15
|
+
const testSetup_1 = require("@salesforce/core/lib/testSetup");
|
|
16
|
+
const scratchOrgSettingsGenerator_1 = require("@salesforce/core/lib/org/scratchOrgSettingsGenerator");
|
|
17
|
+
const xml2js = require("xml2js");
|
|
18
|
+
const kit_1 = require("@salesforce/kit");
|
|
19
|
+
const pkgUtils = require("../utils/packageUtils");
|
|
20
|
+
const constants_1 = require("../constants");
|
|
21
|
+
const utils_1 = require("../utils");
|
|
22
|
+
const versionNumber_1 = require("../utils/versionNumber");
|
|
23
|
+
const packageProfileApi_1 = require("./packageProfileApi");
|
|
24
|
+
const packageVersionCreateRequest_1 = require("./packageVersionCreateRequest");
|
|
25
|
+
core_1.Messages.importMessagesDirectory(__dirname);
|
|
26
|
+
const messages = core_1.Messages.loadMessages('@salesforce/packaging', 'messages');
|
|
27
|
+
const logger = core_1.Logger.childFromRoot('packageVersionCreate');
|
|
28
|
+
const DESCRIPTOR_FILE = 'package2-descriptor.json';
|
|
29
|
+
const POLL_INTERVAL_WITHOUT_VALIDATION_SECONDS = 5;
|
|
30
|
+
class PackageVersionCreate {
|
|
31
|
+
constructor(options) {
|
|
32
|
+
this.options = options;
|
|
33
|
+
this.connection = this.options.connection;
|
|
34
|
+
this.project = this.options.project;
|
|
35
|
+
}
|
|
36
|
+
createPackageVersion() {
|
|
37
|
+
return this.packageVersionCreate(this.options).catch((err) => {
|
|
38
|
+
// TODO: until package2 is GA, wrap perm-based errors w/ 'contact sfdc' action (REMOVE once package2 is GA'd)
|
|
39
|
+
err = pkgUtils.massageErrorMessage(err);
|
|
40
|
+
throw pkgUtils.applyErrorAction(err);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async listRequest(createdlastdays, status) {
|
|
44
|
+
return (0, packageVersionCreateRequest_1.list)({ createdlastdays, status, connection: this.connection });
|
|
45
|
+
}
|
|
46
|
+
async listRequestById(id, connection) {
|
|
47
|
+
return (0, packageVersionCreateRequest_1.byId)(id, connection);
|
|
48
|
+
}
|
|
49
|
+
// convert source to mdapi format and copy to tmp dir packaging up
|
|
50
|
+
async generateMDFolderForArtifact(options) {
|
|
51
|
+
var _a;
|
|
52
|
+
const sourcepath = (_a = options.sourcePaths) !== null && _a !== void 0 ? _a : [options.sourceDir];
|
|
53
|
+
const componentSet = await source_deploy_retrieve_1.ComponentSetBuilder.build({
|
|
54
|
+
sourceapiversion: this.project.getSfProjectJson().get('sourceApiVersion'),
|
|
55
|
+
sourcepath,
|
|
56
|
+
});
|
|
57
|
+
const packageName = options.packageName;
|
|
58
|
+
const outputDirectory = path.resolve(options.deploydir);
|
|
59
|
+
const converter = new source_deploy_retrieve_1.MetadataConverter();
|
|
60
|
+
const convertResult = await converter.convert(componentSet, 'metadata', {
|
|
61
|
+
type: 'directory',
|
|
62
|
+
outputDirectory,
|
|
63
|
+
packageName,
|
|
64
|
+
genUniqueDir: false,
|
|
65
|
+
});
|
|
66
|
+
if (packageName) {
|
|
67
|
+
// SDR will build an output path like /output/directory/packageName/package.xml
|
|
68
|
+
// this was breaking from toolbelt, so to revert it we copy the directory up a level and delete the original
|
|
69
|
+
(0, utils_1.copyDir)(convertResult.packagePath, outputDirectory);
|
|
70
|
+
try {
|
|
71
|
+
fs.rmSync(convertResult.packagePath, { recursive: true });
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
// rmdirSync is being deprecated and emits a warning
|
|
75
|
+
// but rmSync is introduced in node 14 so fall back to rmdirSync
|
|
76
|
+
fs.rmdirSync(convertResult.packagePath, { recursive: true });
|
|
77
|
+
}
|
|
78
|
+
convertResult.packagePath = outputDirectory;
|
|
79
|
+
return convertResult;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
validateDependencyValues(dependency) {
|
|
83
|
+
// If valid 04t package, just return it to be used straight away.
|
|
84
|
+
if (dependency.subscriberPackageVersionId) {
|
|
85
|
+
pkgUtils.validateId(pkgUtils.BY_LABEL.SUBSCRIBER_PACKAGE_VERSION_ID, dependency.subscriberPackageVersionId);
|
|
86
|
+
return Promise.resolve();
|
|
87
|
+
}
|
|
88
|
+
if (dependency.packageId && dependency.package) {
|
|
89
|
+
throw messages.createError('errorPackageAndPackageIdCollision', []);
|
|
90
|
+
}
|
|
91
|
+
const packageIdFromAlias = pkgUtils.getPackageIdFromAlias(dependency.packageId || dependency.package, this.project);
|
|
92
|
+
// If valid 04t package, just return it to be used straight away.
|
|
93
|
+
if (pkgUtils.validateIdNoThrow(pkgUtils.BY_LABEL.SUBSCRIBER_PACKAGE_VERSION_ID, packageIdFromAlias)) {
|
|
94
|
+
dependency.subscriberPackageVersionId = packageIdFromAlias;
|
|
95
|
+
return Promise.resolve();
|
|
96
|
+
}
|
|
97
|
+
if (!packageIdFromAlias || !dependency.versionNumber) {
|
|
98
|
+
throw messages.createError('errorDependencyPair', [JSON.stringify(dependency)]);
|
|
99
|
+
}
|
|
100
|
+
// Just override dependency.packageId value to the resolved alias.
|
|
101
|
+
dependency.packageId = packageIdFromAlias;
|
|
102
|
+
pkgUtils.validateId(pkgUtils.BY_LABEL.PACKAGE_ID, dependency.packageId);
|
|
103
|
+
pkgUtils.validateVersionNumber(dependency.versionNumber, versionNumber_1.BuildNumberToken.LATEST_BUILD_NUMBER_TOKEN, versionNumber_1.BuildNumberToken.RELEASED_BUILD_NUMBER_TOKEN);
|
|
104
|
+
// Validate that the Package2 id exists on the server
|
|
105
|
+
const query = `SELECT Id FROM Package2 WHERE Id = '${dependency.packageId}'`;
|
|
106
|
+
return this.connection.tooling.query(query).then((pkgQueryResult) => {
|
|
107
|
+
const subRecords = pkgQueryResult.records;
|
|
108
|
+
if (!subRecords || subRecords.length !== 1) {
|
|
109
|
+
throw messages.createError('errorNoIdInHub', [dependency.packageId]);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* A dependency in the workspace config file may be specified using either a subscriber package version id (04t)
|
|
115
|
+
* or a package Id (0Ho) + a version number. Additionally, a build number may be the actual build number, or a
|
|
116
|
+
* keyword: LATEST or RELEASED (meaning the latest or released build number for a given major.minor.patch).
|
|
117
|
+
*
|
|
118
|
+
* This method resolves a package Id + version number to a subscriber package version id (04t)
|
|
119
|
+
* and adds it as a SubscriberPackageVersionId parameter in the dependency object.
|
|
120
|
+
*/
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
+
async retrieveSubscriberPackageVersionId(dependency, branchFromFlagOrDef) {
|
|
123
|
+
await this.validateDependencyValues(dependency);
|
|
124
|
+
if (dependency.subscriberPackageVersionId) {
|
|
125
|
+
delete dependency.package;
|
|
126
|
+
// if a 04t id is specified just use it.
|
|
127
|
+
return dependency;
|
|
128
|
+
}
|
|
129
|
+
const versionNumber = versionNumber_1.VersionNumber.from(dependency.versionNumber);
|
|
130
|
+
const buildNumber = versionNumber.build;
|
|
131
|
+
// use the dependency.branch if present otherwise use the branch of the version being created
|
|
132
|
+
const branch = dependency.branch || dependency.branch === '' ? dependency.branch : branchFromFlagOrDef;
|
|
133
|
+
const branchString = !branch || branch === '' ? 'null' : `'${branch}'`;
|
|
134
|
+
// resolve a build number keyword to an actual number, if needed
|
|
135
|
+
const resolvedBuildNumber = await this.resolveBuildNumber(versionNumber, dependency.packageId, branch);
|
|
136
|
+
// now that we have a full build number, query for the associated 04t.
|
|
137
|
+
// because the build number may not be unique across versions, add in conditionals for
|
|
138
|
+
// the branch or the RELEASED token (if used)
|
|
139
|
+
const branchOrReleasedCondition = buildNumber === versionNumber_1.BuildNumberToken.RELEASED_BUILD_NUMBER_TOKEN
|
|
140
|
+
? 'AND IsReleased = true'
|
|
141
|
+
: `AND Branch = ${branchString}`;
|
|
142
|
+
const query = `SELECT SubscriberPackageVersionId FROM Package2Version WHERE Package2Id = '${dependency.packageId}' AND MajorVersion = ${versionNumber[0]} AND MinorVersion = ${versionNumber[1]} AND PatchVersion = ${versionNumber[2]} AND BuildNumber = ${resolvedBuildNumber} ${branchOrReleasedCondition}`;
|
|
143
|
+
const pkgVerQueryResult = await this.connection.tooling.query(query);
|
|
144
|
+
const subRecords = pkgVerQueryResult.records;
|
|
145
|
+
if (!subRecords || subRecords.length !== 1) {
|
|
146
|
+
throw messages.createError('versionNumberNotFoundInDevHub', [
|
|
147
|
+
dependency.packageId,
|
|
148
|
+
branchString,
|
|
149
|
+
versionNumber.toString(),
|
|
150
|
+
resolvedBuildNumber,
|
|
151
|
+
]);
|
|
152
|
+
}
|
|
153
|
+
dependency.subscriberPackageVersionId = pkgVerQueryResult.records[0].SubscriberPackageVersionId;
|
|
154
|
+
// warn user of the resolved build number when LATEST and RELEASED keywords are used
|
|
155
|
+
if (versionNumber.isbuildKeyword()) {
|
|
156
|
+
versionNumber.build = resolvedBuildNumber;
|
|
157
|
+
if (buildNumber === versionNumber_1.BuildNumberToken.LATEST_BUILD_NUMBER_TOKEN) {
|
|
158
|
+
logger.info(messages.getMessage('buildNumberResolvedForLatest', [
|
|
159
|
+
dependency.package,
|
|
160
|
+
versionNumber.toString(),
|
|
161
|
+
branchString,
|
|
162
|
+
dependency.subscriberPackageVersionId,
|
|
163
|
+
]));
|
|
164
|
+
}
|
|
165
|
+
else if (buildNumber === versionNumber_1.BuildNumberToken.RELEASED_BUILD_NUMBER_TOKEN) {
|
|
166
|
+
logger.info(messages.getMessage('buildNumberResolvedForReleased', [
|
|
167
|
+
dependency.package,
|
|
168
|
+
versionNumber.toString(),
|
|
169
|
+
dependency.subscriberPackageVersionId,
|
|
170
|
+
]));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
delete dependency.packageId;
|
|
174
|
+
delete dependency.package;
|
|
175
|
+
delete dependency.versionNumber;
|
|
176
|
+
delete dependency.branch;
|
|
177
|
+
return dependency;
|
|
178
|
+
}
|
|
179
|
+
async resolveBuildNumber(versionNumber, packageId, branch) {
|
|
180
|
+
if (!versionNumber.isbuildKeyword()) {
|
|
181
|
+
// The build number is already specified so just return it using the tooling query result obj structure
|
|
182
|
+
return versionNumber.build;
|
|
183
|
+
}
|
|
184
|
+
// query for the LATEST or RELEASED build number (excluding deleted versions)
|
|
185
|
+
let branchCondition = '';
|
|
186
|
+
let releasedCondition = '';
|
|
187
|
+
if (versionNumber[3] === versionNumber_1.BuildNumberToken.LATEST_BUILD_NUMBER_TOKEN) {
|
|
188
|
+
// respect the branch when querying for LATEST
|
|
189
|
+
const branchString = !branch || branch === '' ? 'null' : `'${branch}'`;
|
|
190
|
+
branchCondition = `AND Branch = ${branchString}`;
|
|
191
|
+
}
|
|
192
|
+
else if (versionNumber[3] === versionNumber_1.BuildNumberToken.RELEASED_BUILD_NUMBER_TOKEN) {
|
|
193
|
+
releasedCondition = 'AND IsReleased = true';
|
|
194
|
+
}
|
|
195
|
+
const query = `SELECT MAX(BuildNumber) FROM Package2Version WHERE Package2Id = '${packageId}' AND IsDeprecated != true AND MajorVersion = ${versionNumber.major} AND MinorVersion = ${versionNumber.minor} AND PatchVersion = ${versionNumber.patch} ${branchCondition} ${releasedCondition}`;
|
|
196
|
+
const results = await this.connection.tooling.query(query);
|
|
197
|
+
const records = results.records;
|
|
198
|
+
if (!records || records.length === 0 || records[0].expr0 == null) {
|
|
199
|
+
if (versionNumber.build === versionNumber_1.BuildNumberToken.RELEASED_BUILD_NUMBER_TOKEN) {
|
|
200
|
+
throw messages.createError('noReleaseVersionFound', [packageId, versionNumber.toString()]);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
throw messages.createError('noReleaseVersionFoundForBranch', [packageId, branch, versionNumber.toString()]);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return `${results.records[0].expr0}`;
|
|
207
|
+
}
|
|
208
|
+
async createRequestObject(packageId, options, preserveFiles, packageVersTmpRoot, packageVersBlobZipFile) {
|
|
209
|
+
const zipFileBase64 = fs.readFileSync(packageVersBlobZipFile).toString('base64');
|
|
210
|
+
const requestObject = {
|
|
211
|
+
Package2Id: packageId,
|
|
212
|
+
VersionInfo: zipFileBase64,
|
|
213
|
+
Tag: options.tag,
|
|
214
|
+
Branch: options.branch,
|
|
215
|
+
InstallKey: options.installationkey,
|
|
216
|
+
Instance: options.buildinstance,
|
|
217
|
+
SourceOrg: options.sourceorg,
|
|
218
|
+
CalculateCodeCoverage: options.codecoverage || false,
|
|
219
|
+
SkipValidation: options.skipvalidation || false,
|
|
220
|
+
};
|
|
221
|
+
if (preserveFiles) {
|
|
222
|
+
logger.info(messages.getMessage('tempFileLocation', [packageVersTmpRoot]));
|
|
223
|
+
return requestObject;
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
return fs.promises.rm(packageVersTmpRoot, { recursive: true, force: true }).then(() => requestObject);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
getPackageDescriptorJsonFromPackageId(packageId, options) {
|
|
230
|
+
const artDir = options.path;
|
|
231
|
+
const packageDescriptorJson = this.project.getPackageDirectories().find((packageDir) => {
|
|
232
|
+
const packageDirPackageId = pkgUtils.getPackageIdFromAlias(packageDir.package, this.project);
|
|
233
|
+
return !!packageDirPackageId && packageDirPackageId === packageId ? packageDir : null;
|
|
234
|
+
});
|
|
235
|
+
if (!packageDescriptorJson) {
|
|
236
|
+
throw messages.createError('packagingDirNotFoundInConfigFile', [constants_1.consts.WORKSPACE_CONFIG_FILENAME, artDir]);
|
|
237
|
+
}
|
|
238
|
+
return packageDescriptorJson;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Convert the list of command line options to a JSON object that can be used to create an Package2VersionCreateRequest entity.
|
|
242
|
+
*
|
|
243
|
+
* @param options
|
|
244
|
+
* @param packageId
|
|
245
|
+
* @param versionNumberString
|
|
246
|
+
* @returns {{Package2Id: (*|p|boolean), Package2VersionMetadata: *, Tag: *, Branch: number}}
|
|
247
|
+
* @private
|
|
248
|
+
*/
|
|
249
|
+
async createPackageVersionCreateRequestFromOptions(options, packageId, versionNumberString) {
|
|
250
|
+
const artDir = options.path;
|
|
251
|
+
const preserveFiles = !!(options.preserve || process.env.SFDX_PACKAGE2_VERSION_CREATE_PRESERVE);
|
|
252
|
+
const uniqueHash = (0, testSetup_1.uniqid)({ template: `${packageId}-%s` });
|
|
253
|
+
const packageVersTmpRoot = path.join(os.tmpdir(), `${uniqueHash}`);
|
|
254
|
+
const packageVersMetadataFolder = path.join(packageVersTmpRoot, 'md-files');
|
|
255
|
+
const unpackagedMetadataFolder = path.join(packageVersTmpRoot, 'unpackaged-md-files');
|
|
256
|
+
const packageVersProfileFolder = path.join(packageVersMetadataFolder, 'profiles');
|
|
257
|
+
const packageVersBlobDirectory = path.join(packageVersTmpRoot, 'package-version-info');
|
|
258
|
+
const metadataZipFile = path.join(packageVersBlobDirectory, 'package.zip');
|
|
259
|
+
const unpackagedMetadataZipFile = path.join(packageVersBlobDirectory, 'unpackaged-metadata-package.zip');
|
|
260
|
+
const settingsZipFile = path.join(packageVersBlobDirectory, 'settings.zip');
|
|
261
|
+
const packageVersBlobZipFile = path.join(packageVersTmpRoot, 'package-version-info.zip');
|
|
262
|
+
const sourceBaseDir = path.join(this.project.getPath(), artDir);
|
|
263
|
+
const mdOptions = {
|
|
264
|
+
deploydir: packageVersMetadataFolder,
|
|
265
|
+
sourceDir: sourceBaseDir,
|
|
266
|
+
};
|
|
267
|
+
// Stores any additional client side info that might be needed later on in the process
|
|
268
|
+
const clientSideInfo = new Map();
|
|
269
|
+
await fs.promises.mkdir(packageVersBlobDirectory, { recursive: true });
|
|
270
|
+
const settingsGenerator = new scratchOrgSettingsGenerator_1.default({ asDirectory: true });
|
|
271
|
+
// Copy all of the metadata from the workspace to a tmp folder
|
|
272
|
+
await this.generateMDFolderForArtifact(mdOptions);
|
|
273
|
+
const packageDescriptorJson = this.getPackageDescriptorJsonFromPackageId(packageId, options);
|
|
274
|
+
if (packageDescriptorJson.package) {
|
|
275
|
+
delete packageDescriptorJson.package;
|
|
276
|
+
packageDescriptorJson.id = packageId;
|
|
277
|
+
}
|
|
278
|
+
const definitionFile = options.definitionfile ? options.definitionfile : packageDescriptorJson.definitionFile;
|
|
279
|
+
if (definitionFile) {
|
|
280
|
+
// package2-descriptor.json sent to the server should contain only the features, snapshot & orgPreferences
|
|
281
|
+
// defined in the definition file.
|
|
282
|
+
delete packageDescriptorJson.features;
|
|
283
|
+
delete packageDescriptorJson.orgPreferences;
|
|
284
|
+
delete packageDescriptorJson.definitionFile;
|
|
285
|
+
delete packageDescriptorJson.snapshot;
|
|
286
|
+
const definitionFilePayload = await fs.promises.readFile(definitionFile, 'utf8');
|
|
287
|
+
const definitionFileJson = JSON.parse(definitionFilePayload);
|
|
288
|
+
const pkgProperties = [
|
|
289
|
+
'country',
|
|
290
|
+
'edition',
|
|
291
|
+
'language',
|
|
292
|
+
'features',
|
|
293
|
+
'orgPreferences',
|
|
294
|
+
'snapshot',
|
|
295
|
+
'release',
|
|
296
|
+
'sourceOrg',
|
|
297
|
+
];
|
|
298
|
+
// Load any settings from the definition
|
|
299
|
+
await settingsGenerator.extract(definitionFileJson);
|
|
300
|
+
if (settingsGenerator.hasSettings() && definitionFileJson.orgPreferences) {
|
|
301
|
+
// this is not allowed, exit with an error
|
|
302
|
+
return Promise.reject(messages.createError('signupDuplicateSettingsSpecified'));
|
|
303
|
+
}
|
|
304
|
+
pkgProperties.forEach((prop) => {
|
|
305
|
+
const propValue = definitionFileJson[prop];
|
|
306
|
+
if (propValue) {
|
|
307
|
+
packageDescriptorJson[prop] = propValue;
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
const hasUnpackagedMetadata = await this.resolveUnpackagedMetadata(packageDescriptorJson, unpackagedMetadataFolder, clientSideInfo, options.codecoverage);
|
|
312
|
+
this.resolveApexTestPermissions(packageDescriptorJson, options);
|
|
313
|
+
// All dependencies for the packaging dir should be resolved to an 04t id to be passed to the server.
|
|
314
|
+
// (see _retrieveSubscriberPackageVersionId for details)
|
|
315
|
+
const dependencies = packageDescriptorJson.dependencies;
|
|
316
|
+
// branch can be set via flag or descriptor; flag takes precedence
|
|
317
|
+
options.branch = options.branch ? options.branch : packageDescriptorJson.branch;
|
|
318
|
+
const resultValues = await Promise.all(!dependencies
|
|
319
|
+
? []
|
|
320
|
+
: dependencies.map((dependency) => this.retrieveSubscriberPackageVersionId(dependency, options.branch)));
|
|
321
|
+
const ancestorId = await pkgUtils.getAncestorId(packageDescriptorJson, this.connection, this.project, versionNumberString, options.skipancestorcheck);
|
|
322
|
+
// If dependencies exist, the resultValues array will contain the dependencies populated with a resolved
|
|
323
|
+
// subscriber pkg version id.
|
|
324
|
+
if (resultValues.length > 0) {
|
|
325
|
+
packageDescriptorJson.dependencies = resultValues;
|
|
326
|
+
}
|
|
327
|
+
this.cleanPackageDescriptorJson(packageDescriptorJson);
|
|
328
|
+
this.setPackageDescriptorJsonValues(packageDescriptorJson, options);
|
|
329
|
+
await fs.promises.mkdir(packageVersTmpRoot, { recursive: true });
|
|
330
|
+
await fs.promises.mkdir(packageVersBlobDirectory, { recursive: true });
|
|
331
|
+
if (Reflect.has(packageDescriptorJson, 'ancestorVersion')) {
|
|
332
|
+
delete packageDescriptorJson.ancestorVersion;
|
|
333
|
+
}
|
|
334
|
+
packageDescriptorJson.ancestorId = ancestorId;
|
|
335
|
+
await fs.promises.writeFile(path.join(packageVersBlobDirectory, DESCRIPTOR_FILE),
|
|
336
|
+
// TODO: need to make sure packageDescriptorJson contains the right values for the descriptor
|
|
337
|
+
JSON.stringify(packageDescriptorJson), 'utf-8');
|
|
338
|
+
// As part of the source convert process, the package.xml has been written into the tmp metadata directory.
|
|
339
|
+
// The package.xml may need to be manipulated due to processing profiles in the workspace or additional
|
|
340
|
+
// metadata exclusions. If necessary, read the existing package.xml and then re-write it.
|
|
341
|
+
const currentPackageXml = await fs.promises.readFile(path.join(packageVersMetadataFolder, 'package.xml'), 'utf8');
|
|
342
|
+
// convert to json
|
|
343
|
+
const packageJson = await xml2js.parseStringPromise(currentPackageXml);
|
|
344
|
+
fs.mkdirSync(packageVersMetadataFolder, { recursive: true });
|
|
345
|
+
fs.mkdirSync(packageVersProfileFolder, { recursive: true });
|
|
346
|
+
// Apply any necessary exclusions to typesArr.
|
|
347
|
+
let typesArr = packageJson.Package.types;
|
|
348
|
+
this.apiVersionFromPackageXml = packageJson.Package.version;
|
|
349
|
+
// if we're using unpackaged metadata, don't package the profiles located there
|
|
350
|
+
if (hasUnpackagedMetadata) {
|
|
351
|
+
typesArr = options.profileApi.filterAndGenerateProfilesForManifest(typesArr, [
|
|
352
|
+
clientSideInfo.get('UnpackagedMetadataPath'),
|
|
353
|
+
]);
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
typesArr = options.profileApi.filterAndGenerateProfilesForManifest(typesArr);
|
|
357
|
+
}
|
|
358
|
+
// Next generate profiles and retrieve any profiles that were excluded because they had no matching nodes.
|
|
359
|
+
const excludedProfiles = options.profileApi.generateProfiles(packageVersProfileFolder, {
|
|
360
|
+
Package: { types: typesArr },
|
|
361
|
+
}, [clientSideInfo.get('UnpackagedMetadataPath')]);
|
|
362
|
+
if (excludedProfiles.length > 0) {
|
|
363
|
+
const profileIdx = typesArr.findIndex((e) => e.name[0] === 'Profile');
|
|
364
|
+
typesArr[profileIdx].members = typesArr[profileIdx].members.filter((e) => excludedProfiles.indexOf(e) === -1);
|
|
365
|
+
}
|
|
366
|
+
packageJson.Package.types = typesArr;
|
|
367
|
+
// Re-write the package.xml in case profiles have been added or removed
|
|
368
|
+
const xmlBuilder = new xml2js.Builder({
|
|
369
|
+
xmldec: { version: '1.0', encoding: 'UTF-8' },
|
|
370
|
+
});
|
|
371
|
+
const xml = xmlBuilder.buildObject(packageJson);
|
|
372
|
+
// Log information about the profiles being packaged up
|
|
373
|
+
const profiles = options.profileApi.getProfileInformation();
|
|
374
|
+
profiles.forEach((profile) => {
|
|
375
|
+
if (logger.shouldLog(core_1.LoggerLevel.DEBUG)) {
|
|
376
|
+
logger.debug(profile.logDebug());
|
|
377
|
+
}
|
|
378
|
+
else if (logger.shouldLog(core_1.LoggerLevel.INFO)) {
|
|
379
|
+
logger.info(profile.logInfo());
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
// TODO: confirm that param xml is writeable
|
|
383
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
384
|
+
await fs.promises.writeFile(path.join(packageVersMetadataFolder, 'package.xml'), xml, 'utf-8');
|
|
385
|
+
// Zip the packageVersMetadataFolder folder and put the zip in {packageVersBlobDirectory}/package.zip
|
|
386
|
+
await (0, utils_1.zipDir)(packageVersMetadataFolder, metadataZipFile);
|
|
387
|
+
if (hasUnpackagedMetadata) {
|
|
388
|
+
// Zip the unpackagedMetadataFolder folder and put the zip in {packageVersBlobDirectory}/{unpackagedMetadataZipFile}
|
|
389
|
+
await (0, utils_1.zipDir)(unpackagedMetadataFolder, unpackagedMetadataZipFile);
|
|
390
|
+
}
|
|
391
|
+
// Zip up the expanded settings (if present)
|
|
392
|
+
if (settingsGenerator.hasSettings()) {
|
|
393
|
+
await settingsGenerator.createDeploy();
|
|
394
|
+
await settingsGenerator.createDeployPackageContents(this.apiVersionFromPackageXml);
|
|
395
|
+
await (0, utils_1.zipDir)(`${settingsGenerator.getDestinationPath()}${path.sep}${settingsGenerator.getShapeDirName()}`, settingsZipFile);
|
|
396
|
+
}
|
|
397
|
+
// Zip the Version Info and package.zip files into another zip
|
|
398
|
+
await (0, utils_1.zipDir)(packageVersBlobDirectory, packageVersBlobZipFile);
|
|
399
|
+
return this.createRequestObject(packageId, options, preserveFiles, packageVersTmpRoot, packageVersBlobZipFile);
|
|
400
|
+
}
|
|
401
|
+
resolveApexTestPermissions(packageDescriptorJson, options) {
|
|
402
|
+
// Process permissionSet and permissionSetLicenses that should be enabled when running Apex tests
|
|
403
|
+
// This only applies if code coverage is enabled
|
|
404
|
+
if (options.codecoverage) {
|
|
405
|
+
// Assuming no permission sets are named 0, 0n, null, undefined, false, NaN, and the empty string
|
|
406
|
+
if (packageDescriptorJson.apexTestAccess && packageDescriptorJson.apexTestAccess.permissionSets) {
|
|
407
|
+
let permSets = packageDescriptorJson.apexTestAccess.permissionSets;
|
|
408
|
+
if (!Array.isArray(permSets)) {
|
|
409
|
+
permSets = permSets.split(',');
|
|
410
|
+
}
|
|
411
|
+
packageDescriptorJson.permissionSetNames = permSets.map((s) => s.trim());
|
|
412
|
+
}
|
|
413
|
+
if (packageDescriptorJson.apexTestAccess && packageDescriptorJson.apexTestAccess.permissionSetLicenses) {
|
|
414
|
+
let permissionSetLicenses = packageDescriptorJson.apexTestAccess.permissionSetLicenses;
|
|
415
|
+
if (!Array.isArray(permissionSetLicenses)) {
|
|
416
|
+
permissionSetLicenses = permissionSetLicenses.split(',');
|
|
417
|
+
}
|
|
418
|
+
packageDescriptorJson.permissionSetLicenseDeveloperNames = permissionSetLicenses.map((s) => s.trim());
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
delete packageDescriptorJson.apexTestAccess;
|
|
422
|
+
}
|
|
423
|
+
async resolveUnpackagedMetadata(packageDescriptorJson, unpackagedMetadataFolder, clientSideInfo, codeCoverage) {
|
|
424
|
+
let hasUnpackagedMetadata = false;
|
|
425
|
+
// Add the Unpackaged Metadata, if any, to the output directory, only when code coverage is specified
|
|
426
|
+
if (codeCoverage && packageDescriptorJson.unpackagedMetadata && packageDescriptorJson.unpackagedMetadata.path) {
|
|
427
|
+
hasUnpackagedMetadata = true;
|
|
428
|
+
const unpackagedPath = path.join(process.cwd(), packageDescriptorJson.unpackagedMetadata.path);
|
|
429
|
+
try {
|
|
430
|
+
fs.statSync(unpackagedPath);
|
|
431
|
+
}
|
|
432
|
+
catch (err) {
|
|
433
|
+
throw messages.createError('unpackagedMDDirectoryDoesNotExist', [
|
|
434
|
+
packageDescriptorJson.unpackagedMetadata.path,
|
|
435
|
+
]);
|
|
436
|
+
}
|
|
437
|
+
fs.mkdirSync(unpackagedMetadataFolder, { recursive: true });
|
|
438
|
+
await this.generateMDFolderForArtifact({
|
|
439
|
+
deploydir: unpackagedMetadataFolder,
|
|
440
|
+
sourceDir: unpackagedPath,
|
|
441
|
+
});
|
|
442
|
+
// Set which package is the "unpackaged" package
|
|
443
|
+
clientSideInfo.set('UnpackagedMetadataPath', packageDescriptorJson.unpackagedMetadata.path);
|
|
444
|
+
}
|
|
445
|
+
return hasUnpackagedMetadata;
|
|
446
|
+
}
|
|
447
|
+
getPackagePropertyFromPackage(packageDirs, options) {
|
|
448
|
+
let foundByPackage = packageDirs.some((x) => x['package'] === options.package);
|
|
449
|
+
let foundById = packageDirs.some((x) => x['id'] === options.package);
|
|
450
|
+
if (foundByPackage && foundById) {
|
|
451
|
+
throw messages.createError('errorPackageAndIdCollision', []);
|
|
452
|
+
}
|
|
453
|
+
// didn't find anything? let's see if we can reverse look up
|
|
454
|
+
if (!foundByPackage && !foundById) {
|
|
455
|
+
// is it an alias?
|
|
456
|
+
const pkgId = pkgUtils.getPackageIdFromAlias(options.package, this.project);
|
|
457
|
+
if (pkgId === options.package) {
|
|
458
|
+
// not an alias, or not a valid one, try to reverse lookup an alias in case this is an id
|
|
459
|
+
const aliases = pkgUtils.getPackageAliasesFromId(options.package, this.project);
|
|
460
|
+
// if we found an alias, try to look that up in the config.
|
|
461
|
+
foundByPackage = aliases.some((alias) => packageDirs.find((x) => x['package'] === alias));
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
// it is an alias; try to lookup it's id in the config
|
|
465
|
+
foundByPackage = packageDirs.some((x) => x['package'] === pkgId);
|
|
466
|
+
foundById = packageDirs.some((x) => x['id'] === pkgId);
|
|
467
|
+
if (!foundByPackage && !foundById) {
|
|
468
|
+
// check if any configs use a different alias to that same id
|
|
469
|
+
const aliases = pkgUtils.getPackageAliasesFromId(pkgId, this.project);
|
|
470
|
+
foundByPackage = aliases.some((alias) => {
|
|
471
|
+
const pd = packageDirs.find((x) => x['package'] === alias);
|
|
472
|
+
if (pd) {
|
|
473
|
+
// if so, set this.options.package.flags.package to be this alias instead of the alternate
|
|
474
|
+
options.package = alias;
|
|
475
|
+
}
|
|
476
|
+
return pd;
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
// if we still didn't find anything, throw the error
|
|
481
|
+
if (!foundByPackage && !foundById) {
|
|
482
|
+
throw messages.createError('errorMissingPackage', [pkgId]);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return foundByPackage ? 'package' : 'id';
|
|
486
|
+
}
|
|
487
|
+
getPackageValuePropertyFromDirectory(directoryFlag, options) {
|
|
488
|
+
const packageValue = this.getConfigPackageDirectoriesValue(this.project.getPackageDirectories(), 'package', 'path', options.path, directoryFlag, options);
|
|
489
|
+
const packageIdValue = this.getConfigPackageDirectoriesValue(this.project.getPackageDirectories(), 'id', 'path', options.path, directoryFlag, options);
|
|
490
|
+
let packagePropVal;
|
|
491
|
+
if (!packageValue && !packageIdValue) {
|
|
492
|
+
throw messages.createError('errorMissingPackage', []);
|
|
493
|
+
}
|
|
494
|
+
else if (packageValue && packageIdValue) {
|
|
495
|
+
throw messages.createError('errorPackageAndIdCollision', []);
|
|
496
|
+
}
|
|
497
|
+
else if (packageValue) {
|
|
498
|
+
packagePropVal = {
|
|
499
|
+
packageProperty: 'package',
|
|
500
|
+
packageValue,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
packagePropVal = {
|
|
505
|
+
packageProperty: 'id',
|
|
506
|
+
packageValue: packageIdValue,
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
return packagePropVal;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Returns the property value that corresponds to the propertyToLookup. This value found for a particular
|
|
513
|
+
* package directory element that matches the knownProperty and knownValue. In other words, we locate a package
|
|
514
|
+
* directory element whose knownProperty matches the knownValue, then we grab the value for the propertyToLookup
|
|
515
|
+
* and return it.
|
|
516
|
+
*
|
|
517
|
+
* @param packageDirs The list of all the package directories from the sfdx-project.json
|
|
518
|
+
* @param propertyToLookup The property ID whose value we want to find
|
|
519
|
+
* @param knownProperty The JSON property in the packageDirectories that is already known
|
|
520
|
+
* @param knownValue The value that corresponds to the knownProperty in the packageDirectories JSON
|
|
521
|
+
* @param knownFlag The flag details e.g. short/long name, etc. Only used for the error message
|
|
522
|
+
* @param options
|
|
523
|
+
*/
|
|
524
|
+
getConfigPackageDirectoriesValue(packageDirs, propertyToLookup, knownProperty, knownValue, knownFlag, options
|
|
525
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
526
|
+
) {
|
|
527
|
+
let value;
|
|
528
|
+
let packageDir = packageDirs.find((x) => x[knownProperty] === knownValue);
|
|
529
|
+
if (!packageDir && knownFlag === 'path' && knownValue.endsWith(path.sep)) {
|
|
530
|
+
// if this is the directory flag, try removing the trailing slash added by CLI auto-complete
|
|
531
|
+
const dirWithoutTrailingSlash = knownValue.slice(0, -1);
|
|
532
|
+
packageDir = packageDirs.find((x) => x[knownProperty] === dirWithoutTrailingSlash);
|
|
533
|
+
if (packageDir) {
|
|
534
|
+
// TODO: how to deal with this side effect?
|
|
535
|
+
options.path = dirWithoutTrailingSlash;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
// didn't find it with the package property, try a reverse lookup with alias and id
|
|
539
|
+
if (!packageDir && knownProperty === 'package') {
|
|
540
|
+
const pkgId = pkgUtils.getPackageIdFromAlias(knownValue, this.project);
|
|
541
|
+
if (pkgId !== knownValue) {
|
|
542
|
+
packageDir = packageDirs.find((x) => x[knownProperty] === pkgId);
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
const aliases = pkgUtils.getPackageAliasesFromId(knownValue, this.project);
|
|
546
|
+
aliases.some((alias) => {
|
|
547
|
+
packageDir = packageDirs.find((x) => x[knownProperty] === alias);
|
|
548
|
+
return packageDir;
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
if (packageDir) {
|
|
553
|
+
value = packageDir[propertyToLookup];
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
throw messages.createError('errorNoMatchingPackageDirectory', [`--${knownFlag}`, knownValue, knownProperty]);
|
|
557
|
+
}
|
|
558
|
+
return value;
|
|
559
|
+
}
|
|
560
|
+
async packageVersionCreate(options) {
|
|
561
|
+
var _a, _b;
|
|
562
|
+
let pollInterval = kit_1.Duration.seconds(pkgUtils.POLL_INTERVAL_SECONDS);
|
|
563
|
+
let maxRetries = 0;
|
|
564
|
+
if (((_a = options.wait) === null || _a === void 0 ? void 0 : _a.milliseconds) > 0) {
|
|
565
|
+
if (options.skipvalidation === true) {
|
|
566
|
+
pollInterval = kit_1.Duration.seconds(POLL_INTERVAL_WITHOUT_VALIDATION_SECONDS);
|
|
567
|
+
}
|
|
568
|
+
maxRetries = (60 / pollInterval.seconds) * options.wait.seconds;
|
|
569
|
+
}
|
|
570
|
+
// For the first rollout of validating sfdx-project.json data against schema, make it optional and defaulted
|
|
571
|
+
// to false. Validation only occurs if the hidden -j (--validateschema) flag has been specified.
|
|
572
|
+
if (options.validateschema) {
|
|
573
|
+
await this.project.getSfProjectJson().schemaValidate();
|
|
574
|
+
}
|
|
575
|
+
// Check for empty packageDirectories
|
|
576
|
+
if (((_b = this.project.getPackageDirectories()) === null || _b === void 0 ? void 0 : _b.length) === 0) {
|
|
577
|
+
throw messages.createError('errorEmptyPackageDirs');
|
|
578
|
+
}
|
|
579
|
+
const canonicalPackageProperty = this.resolveCanonicalPackageProperty(options);
|
|
580
|
+
const resolvedPackageId = pkgUtils.getPackageIdFromAlias(options.package, this.project);
|
|
581
|
+
// At this point, the packageIdFromAlias should have been resolved to an Id. Now, we
|
|
582
|
+
// need to validate that the Id is correct.
|
|
583
|
+
pkgUtils.validateId(pkgUtils.BY_LABEL.PACKAGE_ID, resolvedPackageId);
|
|
584
|
+
await this.validateFlagsForPackageType(resolvedPackageId, options);
|
|
585
|
+
const versionNumberString = await this.validateVersionNumber(canonicalPackageProperty, resolvedPackageId, options);
|
|
586
|
+
try {
|
|
587
|
+
fs.statSync(path.join(process.cwd(), options.path));
|
|
588
|
+
}
|
|
589
|
+
catch (err) {
|
|
590
|
+
throw messages.createError('directoryDoesNotExist', [options.path]);
|
|
591
|
+
}
|
|
592
|
+
options.profileApi = await this.resolveUserLicenses(canonicalPackageProperty, options);
|
|
593
|
+
[pollInterval, maxRetries] = await this.resolveOrgDependentPollingTime(resolvedPackageId, options, pollInterval, maxRetries);
|
|
594
|
+
const request = await this.createPackageVersionCreateRequestFromOptions(options, resolvedPackageId, versionNumberString);
|
|
595
|
+
const createResult = await this.connection.tooling.create('Package2VersionCreateRequest', request);
|
|
596
|
+
if (!createResult.success) {
|
|
597
|
+
const errStr = createResult.errors && createResult.errors.length ? createResult.errors.join(', ') : createResult.errors;
|
|
598
|
+
throw messages.createError('failedToCreatePVCRequest', [
|
|
599
|
+
createResult.id ? ` [${createResult.id}]` : '',
|
|
600
|
+
errStr.toString(),
|
|
601
|
+
]);
|
|
602
|
+
}
|
|
603
|
+
let result;
|
|
604
|
+
if (options.wait && options.wait.milliseconds > 0) {
|
|
605
|
+
pollInterval = pollInterval !== null && pollInterval !== void 0 ? pollInterval : kit_1.Duration.seconds(options.wait.seconds / maxRetries);
|
|
606
|
+
if (pollInterval) {
|
|
607
|
+
result = await pkgUtils.pollForStatusWithInterval(createResult.id, maxRetries, resolvedPackageId, options.branch, this.project, this.connection, pollInterval);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
result = (await this.listRequestById(createResult.id, this.connection))[0];
|
|
612
|
+
}
|
|
613
|
+
return result;
|
|
614
|
+
}
|
|
615
|
+
resolveCanonicalPackageProperty(options) {
|
|
616
|
+
let canonicalPackageProperty;
|
|
617
|
+
if (!options.package) {
|
|
618
|
+
const packageValProp = this.getPackageValuePropertyFromDirectory(options.path, options);
|
|
619
|
+
options.package = packageValProp.packageValue;
|
|
620
|
+
canonicalPackageProperty = packageValProp.packageProperty;
|
|
621
|
+
}
|
|
622
|
+
else if (!options.path) {
|
|
623
|
+
canonicalPackageProperty = this.getPackagePropertyFromPackage(this.project.getPackageDirectories(), options);
|
|
624
|
+
options.path = this.getConfigPackageDirectoriesValue(this.project.getPackageDirectories(), 'path', canonicalPackageProperty, options.package, 'package', options);
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
canonicalPackageProperty = this.getPackagePropertyFromPackage(this.project.getPackageDirectories(), options);
|
|
628
|
+
this.getConfigPackageDirectoriesValue(this.project.getPackageDirectories(), canonicalPackageProperty, 'path', options.path, 'path', options);
|
|
629
|
+
const expectedPackageId = this.getConfigPackageDirectoriesValue(this.project.getPackageDirectories(), canonicalPackageProperty, 'path', options.path, 'path', options);
|
|
630
|
+
// This will throw an error if the package id flag value doesn't match
|
|
631
|
+
// any of the :id values in the package dirs.
|
|
632
|
+
this.getConfigPackageDirectoriesValue(this.project.getPackageDirectories(), 'path', canonicalPackageProperty, options.package, 'package', options);
|
|
633
|
+
// This will throw an error if the package id flag value doesn't match
|
|
634
|
+
// the correct corresponding directory with that packageId.
|
|
635
|
+
if (options.package !== expectedPackageId) {
|
|
636
|
+
throw messages.createError('errorDirectoryIdMismatch', ['--path', options.path, '--package', options.package]);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
return canonicalPackageProperty;
|
|
640
|
+
}
|
|
641
|
+
// TODO: should be in pkg utils
|
|
642
|
+
async validateVersionNumber(canonicalPackageProperty, resolvedPackageId, options) {
|
|
643
|
+
// validate the versionNumber flag value if specified, otherwise the descriptor value
|
|
644
|
+
const versionNumberString = options.versionnumber
|
|
645
|
+
? options.versionnumber
|
|
646
|
+
: this.getConfigPackageDirectoriesValue(this.project.getPackageDirectories(), 'versionNumber', canonicalPackageProperty, options.package, 'package', options);
|
|
647
|
+
pkgUtils.validateVersionNumber(versionNumberString, versionNumber_1.BuildNumberToken.NEXT_BUILD_NUMBER_TOKEN, null);
|
|
648
|
+
await pkgUtils.validatePatchVersion(this.connection, versionNumberString, resolvedPackageId);
|
|
649
|
+
return versionNumberString;
|
|
650
|
+
}
|
|
651
|
+
async resolveUserLicenses(canonicalPackageProperty, options) {
|
|
652
|
+
// Check for an includeProfileUserLiceneses flag in the packageDirectory
|
|
653
|
+
const includeProfileUserLicenses = this.getConfigPackageDirectoriesValue(this.project.getPackageDirectories(), 'includeProfileUserLicenses', canonicalPackageProperty, options.package, 'package', options);
|
|
654
|
+
if (includeProfileUserLicenses !== undefined &&
|
|
655
|
+
includeProfileUserLicenses !== true &&
|
|
656
|
+
includeProfileUserLicenses !== false) {
|
|
657
|
+
throw messages.createError('errorProfileUserLicensesInvalidValue', [includeProfileUserLicenses]);
|
|
658
|
+
}
|
|
659
|
+
const shouldGenerateProfileInformation = logger.shouldLog(core_1.LoggerLevel.INFO) || logger.shouldLog(core_1.LoggerLevel.DEBUG);
|
|
660
|
+
return packageProfileApi_1.PackageProfileApi.create({
|
|
661
|
+
project: this.project,
|
|
662
|
+
includeUserLicenses: includeProfileUserLicenses,
|
|
663
|
+
generateProfileInformation: shouldGenerateProfileInformation,
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
async resolveOrgDependentPollingTime(resolvedPackageId, options, pollInterval, maxRetries) {
|
|
667
|
+
let pi = pollInterval;
|
|
668
|
+
let mr = maxRetries;
|
|
669
|
+
// If we are polling check to see if the package is Org-Dependent, if so, update the poll time
|
|
670
|
+
if (options.wait) {
|
|
671
|
+
const query = `SELECT IsOrgDependent FROM Package2 WHERE Id = '${resolvedPackageId}'`;
|
|
672
|
+
try {
|
|
673
|
+
const pkgQueryResult = await this.connection.singleRecordQuery(query, {
|
|
674
|
+
tooling: true,
|
|
675
|
+
});
|
|
676
|
+
if (pkgQueryResult.IsOrgDependent) {
|
|
677
|
+
pi = kit_1.Duration.seconds(POLL_INTERVAL_WITHOUT_VALIDATION_SECONDS);
|
|
678
|
+
mr = (60 / pollInterval.seconds) * options.wait.seconds;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
catch {
|
|
682
|
+
// do nothing
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return [pi, mr];
|
|
686
|
+
}
|
|
687
|
+
async validateFlagsForPackageType(packageId, options) {
|
|
688
|
+
const packageType = await pkgUtils.getPackageType(packageId, this.connection);
|
|
689
|
+
if (packageType === 'Unlocked') {
|
|
690
|
+
if (options.postinstallscript || options.uninstallscript) {
|
|
691
|
+
// migrate coreMessages to messages
|
|
692
|
+
throw messages.createError('version_create.errorScriptsNotApplicableToUnlockedPackage');
|
|
693
|
+
}
|
|
694
|
+
// Don't allow ancestor in unlocked packages
|
|
695
|
+
const packageDescriptorJson = this.getPackageDescriptorJsonFromPackageId(packageId, options);
|
|
696
|
+
const ancestorId = packageDescriptorJson.ancestorId;
|
|
697
|
+
const ancestorVersion = packageDescriptorJson.ancestorVersion;
|
|
698
|
+
if (ancestorId || ancestorVersion) {
|
|
699
|
+
throw messages.createError('version_create.errorAncestorNotApplicableToUnlockedPackage');
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Cleans invalid attribute(s) from the packageDescriptorJSON
|
|
705
|
+
*/
|
|
706
|
+
cleanPackageDescriptorJson(packageDescriptorJson) {
|
|
707
|
+
delete packageDescriptorJson.default; // for client-side use only, not needed
|
|
708
|
+
delete packageDescriptorJson.includeProfileUserLicenses; // for client-side use only, not needed
|
|
709
|
+
delete packageDescriptorJson.unpackagedMetadata; // for client-side use only, not needed
|
|
710
|
+
delete packageDescriptorJson.branch; // for client-side use only, not needed
|
|
711
|
+
delete packageDescriptorJson.fullPath; // for client-side use only, not needed
|
|
712
|
+
delete packageDescriptorJson.name; // for client-side use only, not needed
|
|
713
|
+
return packageDescriptorJson;
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Sets default or override values for packageDescriptorJSON attribs
|
|
717
|
+
*/
|
|
718
|
+
setPackageDescriptorJsonValues(packageDescriptorJson, options) {
|
|
719
|
+
if (options.versionname) {
|
|
720
|
+
packageDescriptorJson.versionName = options.versionname;
|
|
721
|
+
}
|
|
722
|
+
if (options.versiondescription) {
|
|
723
|
+
packageDescriptorJson.versionDescription = options.versiondescription;
|
|
724
|
+
}
|
|
725
|
+
if (options.versionnumber) {
|
|
726
|
+
packageDescriptorJson.versionNumber = options.versionnumber;
|
|
727
|
+
}
|
|
728
|
+
// default versionName to versionNumber if unset, stripping .NEXT if present
|
|
729
|
+
if (!packageDescriptorJson.versionName) {
|
|
730
|
+
const versionNumber = packageDescriptorJson.versionNumber;
|
|
731
|
+
packageDescriptorJson.versionName =
|
|
732
|
+
versionNumber.split(pkgUtils.VERSION_NUMBER_SEP)[3] === versionNumber_1.BuildNumberToken.NEXT_BUILD_NUMBER_TOKEN
|
|
733
|
+
? versionNumber.substring(0, versionNumber.indexOf(pkgUtils.VERSION_NUMBER_SEP + versionNumber_1.BuildNumberToken.NEXT_BUILD_NUMBER_TOKEN))
|
|
734
|
+
: versionNumber;
|
|
735
|
+
logger.warn(options, messages.getMessage('defaultVersionName', [packageDescriptorJson.versionName]));
|
|
736
|
+
}
|
|
737
|
+
if (options.releasenotesurl) {
|
|
738
|
+
packageDescriptorJson.releaseNotesUrl = options.releasenotesurl;
|
|
739
|
+
}
|
|
740
|
+
if (packageDescriptorJson.releaseNotesUrl && !pkgUtils.validUrl(packageDescriptorJson.releaseNotesUrl)) {
|
|
741
|
+
throw messages.createError('malformedUrl', ['releaseNotesUrl', packageDescriptorJson.releaseNotesUrl]);
|
|
742
|
+
}
|
|
743
|
+
if (options.postinstallurl) {
|
|
744
|
+
packageDescriptorJson.postInstallUrl = options.postinstallurl;
|
|
745
|
+
}
|
|
746
|
+
if (packageDescriptorJson.postInstallUrl && !pkgUtils.validUrl(packageDescriptorJson.postInstallUrl)) {
|
|
747
|
+
throw messages.createError('malformedUrl', ['postInstallUrl', packageDescriptorJson.postInstallUrl]);
|
|
748
|
+
}
|
|
749
|
+
if (options.postinstallscript) {
|
|
750
|
+
packageDescriptorJson.postInstallScript = options.postinstallscript;
|
|
751
|
+
}
|
|
752
|
+
if (options.uninstallscript) {
|
|
753
|
+
packageDescriptorJson.uninstallScript = options.uninstallscript;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
exports.PackageVersionCreate = PackageVersionCreate;
|
|
758
|
+
//# sourceMappingURL=packageVersionCreate.js.map
|