@salesforce/packaging 0.0.20 → 0.0.21

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