@salesforce/packaging 1.5.6 → 1.6.0

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.
@@ -3,6 +3,7 @@ import { Connection, NamedPackageDir, SfProject } from '@salesforce/core';
3
3
  import { SaveResult } from 'jsforce';
4
4
  import { Attributes } from 'graphology-types';
5
5
  import { Optional } from '@salesforce/ts-types';
6
+ import { ConvertResult } from '@salesforce/source-deploy-retrieve';
6
7
  import { PackageProfileApi } from '../package/packageProfileApi';
7
8
  import { PackageAncestryNode } from '../package/packageAncestry';
8
9
  import { PackagingSObjects } from './packagingSObjects';
@@ -170,6 +171,11 @@ export type PackageVersionCreateRequestOptions = {
170
171
  branch?: string;
171
172
  skipancestorcheck?: boolean;
172
173
  };
174
+ export type PackageVersionMetadataDownloadOptions = {
175
+ subscriberPackageVersionId: string;
176
+ destinationFolder?: string;
177
+ };
178
+ export type PackageVersionMetadataDownloadResult = ConvertResult;
173
179
  export type PackageInstallOptions = {
174
180
  /**
175
181
  * The frequency to poll the org for package publish status. If providing a number
@@ -297,5 +297,6 @@ export declare namespace PackagingSObjects {
297
297
  PatchVersion: number;
298
298
  BuildNumber: number;
299
299
  IsDeprecated: boolean;
300
+ MetadataZip?: string;
300
301
  };
301
302
  }
@@ -1,5 +1,5 @@
1
1
  import { Connection, SfProject } from '@salesforce/core';
2
- import { ConvertPackageOptions, PackageCreateOptions, PackageOptions, PackageSaveResult, PackageType, PackageUpdateOptions, PackageVersionCreateRequestResult, PackageVersionListOptions, PackageVersionListResult, PackagingSObjects } from '../interfaces';
2
+ import { ConvertPackageOptions, PackageCreateOptions, PackageOptions, PackageSaveResult, PackageType, PackageUpdateOptions, PackageVersionCreateRequestResult, PackageVersionListOptions, PackageVersionListResult, PackagingSObjects, PackageVersionMetadataDownloadOptions, PackageVersionMetadataDownloadResult } from '../interfaces';
3
3
  import { PackageAncestry } from './packageAncestry';
4
4
  export declare const Package2Fields: string[];
5
5
  /**
@@ -69,6 +69,15 @@ export declare class Package {
69
69
  * @param project
70
70
  */
71
71
  static convert(pkgId: string, connection: Connection, options: ConvertPackageOptions, project?: SfProject): Promise<PackageVersionCreateRequestResult>;
72
+ /**
73
+ * Download the metadata files for a previously published package version, convert them to source format, and put them into a new project folder within the sfdx project.
74
+ *
75
+ * @param project
76
+ * @param options {@link PackageVersionMetadataDownloadOptions}
77
+ * @param connection
78
+ * @returns
79
+ */
80
+ static downloadPackageVersionMetadata(project: SfProject, options: PackageVersionMetadataDownloadOptions, connection: Connection): Promise<PackageVersionMetadataDownloadResult>;
72
81
  private static getPackage2Fields;
73
82
  /**
74
83
  * Returns the package ID of the package.
@@ -7,7 +7,10 @@ exports.Package = exports.Package2Fields = void 0;
7
7
  * Licensed under the BSD 3-Clause license.
8
8
  * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
9
9
  */
10
+ const path = require("path");
11
+ const fs = require("fs");
10
12
  const core_1 = require("@salesforce/core");
13
+ const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
11
14
  const packageUtils_1 = require("../utils/packageUtils");
12
15
  const packageCreate_1 = require("./packageCreate");
13
16
  const packageConvert_1 = require("./packageConvert");
@@ -150,6 +153,53 @@ class Package {
150
153
  static async convert(pkgId, connection, options, project) {
151
154
  return (0, packageConvert_1.convertPackage)(pkgId, connection, options, project);
152
155
  }
156
+ /**
157
+ * Download the metadata files for a previously published package version, convert them to source format, and put them into a new project folder within the sfdx project.
158
+ *
159
+ * @param project
160
+ * @param options {@link PackageVersionMetadataDownloadOptions}
161
+ * @param connection
162
+ * @returns
163
+ */
164
+ static async downloadPackageVersionMetadata(project, options, connection) {
165
+ // Validate the destination path is suitable to extract package version metadata (must be new or empty)
166
+ const destinationFolder = options.destinationFolder ?? 'force-app';
167
+ if (path.isAbsolute(destinationFolder)) {
168
+ throw messages.createError('sourcesDownloadDirectoryMustBeRelative');
169
+ }
170
+ const destinationPath = path.join(project.getPath(), destinationFolder);
171
+ if (!fs.existsSync(destinationPath)) {
172
+ fs.mkdirSync(destinationPath, { recursive: true });
173
+ }
174
+ if (!(0, packageUtils_1.isPackageDirectoryEffectivelyEmpty)(destinationPath)) {
175
+ throw messages.createError('sourcesDownloadDirectoryNotEmpty');
176
+ }
177
+ // Get the MetadataZip URL from the MetadataPackageVersion record
178
+ const { subscriberPackageVersionId } = options;
179
+ const versionInfo = (await connection.tooling
180
+ .sobject('MetadataPackageVersion')
181
+ .retrieve(subscriberPackageVersionId));
182
+ if (!versionInfo.MetadataZip) {
183
+ throw messages.createError('unableToAccessMetadataZip');
184
+ }
185
+ const responseBase64 = await connection.tooling.request(versionInfo.MetadataZip, {
186
+ encoding: 'base64',
187
+ });
188
+ const buffer = Buffer.from(responseBase64, 'base64');
189
+ const converter = new source_deploy_retrieve_1.MetadataConverter();
190
+ const tree = await source_deploy_retrieve_1.ZipTreeContainer.create(buffer);
191
+ const zipComponents = source_deploy_retrieve_1.ComponentSet.fromSource({
192
+ fsPaths: ['.'],
193
+ tree,
194
+ })
195
+ .getSourceComponents()
196
+ .toArray();
197
+ return converter.convert(zipComponents, 'source', {
198
+ type: 'directory',
199
+ outputDirectory: destinationPath,
200
+ genUniqueDir: false,
201
+ });
202
+ }
153
203
  static getPackage2Fields(connection) {
154
204
  const apiVersion = connection.getApiVersion();
155
205
  return exports.Package2Fields.filter((field) => (apiVersion >= '59.0' ? true : field !== 'AppAnalyticsEnabled'));
@@ -475,7 +475,15 @@ class PackageVersionCreate {
475
475
  throw error;
476
476
  }
477
477
  const request = await this.createPackageVersionCreateRequestFromOptions();
478
- const createResult = await this.connection.tooling.create('Package2VersionCreateRequest', request);
478
+ const options = {
479
+ multipartFileFields: {
480
+ VersionInfo: {
481
+ contentType: 'application/zip',
482
+ filename: 'package-version-info.zip',
483
+ },
484
+ },
485
+ };
486
+ const createResult = await this.connection.tooling.create('Package2VersionCreateRequest', request, options);
479
487
  if (!createResult.success) {
480
488
  const errStr = createResult.errors?.join(', ') ?? createResult.errors;
481
489
  const id = createResult.id ?? '';
@@ -98,3 +98,13 @@ export declare function zipDir(dir: string, zipfile: string): Promise<void>;
98
98
  export declare function copyDir(src: string, dest: string): void;
99
99
  export declare function copyDescriptorProperties(packageDescriptorJson: PackageDescriptorJson, definitionFileJson: ScratchOrgInfo): PackageDescriptorJson;
100
100
  export declare function replaceIfEmpty<T>(value: T, replacement: T): T;
101
+ /**
102
+ * Brand new SFDX projects contain a force-app directory tree contiaining empty folders
103
+ * and a few .eslint.json files. We still want to consider such a directory tree
104
+ * as 'empty' for the sake of operations like downloading package version metadata.
105
+ *
106
+ * @param directory The absolute path to a directory
107
+ * @returns true if the directory contains nothing except empty directories or
108
+ * directories containing only an .eslint.json file.
109
+ */
110
+ export declare function isPackageDirectoryEffectivelyEmpty(directory: string): boolean;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replaceIfEmpty = exports.copyDescriptorProperties = exports.copyDir = exports.zipDir = exports.numberToDuration = exports.combineSaveErrors = exports.generatePackageAliasEntry = exports.getPackageVersionNumber = exports.getPackageVersionStrings = exports.getContainerOptions = exports.escapeInstallationKey = exports.getPackageVersionId = exports.massageErrorMessage = exports.applyErrorAction = exports.validateIdNoThrow = exports.validateId = exports.uniqid = exports.BY_LABEL = exports.DEFAULT_PACKAGE_DIR = exports.POLL_INTERVAL_SECONDS = exports.INSTALL_URL_BASE = exports.VERSION_NUMBER_SEP = void 0;
3
+ exports.isPackageDirectoryEffectivelyEmpty = exports.replaceIfEmpty = exports.copyDescriptorProperties = exports.copyDir = exports.zipDir = exports.numberToDuration = exports.combineSaveErrors = exports.generatePackageAliasEntry = exports.getPackageVersionNumber = exports.getPackageVersionStrings = exports.getContainerOptions = exports.escapeInstallationKey = exports.getPackageVersionId = exports.massageErrorMessage = exports.applyErrorAction = exports.validateIdNoThrow = exports.validateId = exports.uniqid = exports.BY_LABEL = exports.DEFAULT_PACKAGE_DIR = exports.POLL_INTERVAL_SECONDS = exports.INSTALL_URL_BASE = exports.VERSION_NUMBER_SEP = void 0;
4
4
  /*
5
5
  * Copyright (c) 2022, salesforce.com, inc.
6
6
  * All rights reserved.
@@ -407,4 +407,23 @@ function replaceIfEmpty(value, replacement) {
407
407
  return !(0, kit_1.isEmpty)(value) ? value : replacement;
408
408
  }
409
409
  exports.replaceIfEmpty = replaceIfEmpty;
410
+ /**
411
+ * Brand new SFDX projects contain a force-app directory tree contiaining empty folders
412
+ * and a few .eslint.json files. We still want to consider such a directory tree
413
+ * as 'empty' for the sake of operations like downloading package version metadata.
414
+ *
415
+ * @param directory The absolute path to a directory
416
+ * @returns true if the directory contains nothing except empty directories or
417
+ * directories containing only an .eslint.json file.
418
+ */
419
+ function isPackageDirectoryEffectivelyEmpty(directory) {
420
+ if (!fs.lstatSync(directory).isDirectory()) {
421
+ return false;
422
+ }
423
+ const entries = fs.readdirSync(directory, { withFileTypes: true });
424
+ return entries.every((entry) => entry.isDirectory()
425
+ ? isPackageDirectoryEffectivelyEmpty((0, path_1.join)(directory, entry.name))
426
+ : entry.name === '.eslint.json');
427
+ }
428
+ exports.isPackageDirectoryEffectivelyEmpty = isPackageDirectoryEffectivelyEmpty;
410
429
  //# sourceMappingURL=packageUtils.js.map
@@ -25,3 +25,21 @@ A package with id %s was not found.
25
25
  # appAnalyticsEnabledApiPriorTo59Error
26
26
 
27
27
  Enabling App Analytics is only possible with API version 59.0 or higher.
28
+
29
+ # sourcesDownloadDirectoryNotEmpty
30
+
31
+ Can’t retrieve package version metadata. The specified directory isn’t empty. Empty the directory, or create a new one and try again.
32
+
33
+ # sourcesDownloadDirectoryMustBeRelative
34
+
35
+ Can’t retrieve package version metadata. The specified directory must be relative to your Salesforce DX project directory, and not an absolute path.
36
+
37
+ # unableToAccessMetadataZip
38
+
39
+ Can’t retrieve package version metadata. Ensure that you’re using API version 59.0 or higher, and that you have the user permissions needed to access fields on the MetadataPackageVersion object.
40
+
41
+ # errorDownloadingMetadataZip
42
+
43
+ Can’t retrieve package version metadata.
44
+
45
+ An error occurred downloading the metadata: %s
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/packaging",
3
- "version": "1.5.6",
3
+ "version": "1.6.0",
4
4
  "description": "Packaging library for the Salesforce packaging platform",
5
5
  "main": "lib/exported",
6
6
  "types": "lib/exported.d.ts",
@@ -42,7 +42,7 @@
42
42
  "@salesforce/core": "^3.36.1",
43
43
  "@salesforce/kit": "^1.9.2",
44
44
  "@salesforce/schemas": "^1.5.1",
45
- "@salesforce/source-deploy-retrieve": "^8.0.7",
45
+ "@salesforce/source-deploy-retrieve": "^8.5.1",
46
46
  "@salesforce/ts-types": "^1.7.3",
47
47
  "@xmldom/xmldom": "^0.8.7",
48
48
  "debug": "^4.3.4",
@@ -51,14 +51,14 @@
51
51
  "graphology-traversal": "^0.3.1",
52
52
  "graphology-types": "^0.24.7",
53
53
  "js2xmlparser": "^4.0.2",
54
- "jsforce": "2.0.0-beta.23",
54
+ "jsforce": "^2.0.0-beta.23",
55
55
  "jszip": "^3.10.1",
56
56
  "mkdirp": "1.0.4",
57
57
  "ts-retry-promise": "^0.7.0",
58
58
  "xml2js": "^0.5.0"
59
59
  },
60
60
  "devDependencies": {
61
- "@salesforce/cli-plugins-testkit": "^3.3.6",
61
+ "@salesforce/cli-plugins-testkit": "^3.4.0",
62
62
  "@salesforce/dev-config": "^3.1.0",
63
63
  "@salesforce/dev-scripts": "^4.3.1",
64
64
  "@salesforce/prettier-config": "^0.0.2",
@@ -67,8 +67,8 @@
67
67
  "@types/globby": "^9.1.0",
68
68
  "@types/jszip": "^3.4.1",
69
69
  "@types/xml2js": "^0.4.11",
70
- "@typescript-eslint/eslint-plugin": "^5.59.2",
71
- "@typescript-eslint/parser": "^5.59.5",
70
+ "@typescript-eslint/eslint-plugin": "^5.59.6",
71
+ "@typescript-eslint/parser": "^5.59.6",
72
72
  "chai": "^4.3.7",
73
73
  "commitizen": "^4.2.6",
74
74
  "eslint": "^8.40.0",