@salesforce/packaging 4.4.0 → 4.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.
@@ -106,6 +106,44 @@ export type PackageVersionListResult = {
106
106
  HasMetadataRemoved?: boolean;
107
107
  Language?: string;
108
108
  };
109
+ export type PackagePushRequestListQueryOptions = {
110
+ packageId: string;
111
+ scheduledLastDays?: number;
112
+ status?: 'Created' | 'Cancelled' | 'Pending' | 'In Progress' | 'Failed' | 'Succeeded';
113
+ isMigration?: boolean;
114
+ };
115
+ export type PackagePushRequestListResult = {
116
+ Id: string;
117
+ PackageVersionId: string;
118
+ PackageVersion: {
119
+ Name: string;
120
+ MajorVersion: string;
121
+ MinorVersion: string;
122
+ };
123
+ Status: string;
124
+ ScheduledStartTime: string;
125
+ StartTime: string;
126
+ EndTime: string;
127
+ OrgsScheduled: number;
128
+ OrgsUpgradeSucceeded: number;
129
+ OrgsUpgradeFailed: number;
130
+ };
131
+ export type PackagePushScheduleQueryOptions = {
132
+ packageVersionId: string;
133
+ scheduledStartTime?: string;
134
+ orgList: string;
135
+ };
136
+ export type PackagePushScheduleResult = {
137
+ PushRequestId: string;
138
+ ScheduledStartTime: string | undefined;
139
+ Status: string;
140
+ };
141
+ export type PackagePushRequestReportQueryOptions = {
142
+ packagePushRequestId: string;
143
+ };
144
+ export type PackagePushRequestAbortQueryOptions = {
145
+ packagePushRequestId: string;
146
+ };
109
147
  export type PackageInstallCreateRequest = Partial<Pick<PackageInstallRequest, 'ApexCompileType' | 'EnableRss' | 'NameConflictResolution' | 'PackageInstallSource' | 'Password' | 'SecurityType' | 'SkipHandlers' | 'UpgradeType'>> & Pick<PackagingSObjects.PackageInstallRequest, 'SubscriberPackageVersionKey'>;
110
148
  export type Package1Display = {
111
149
  MetadataPackageVersionId: string;
@@ -250,6 +288,7 @@ export type ConvertPackageOptions = {
250
288
  buildInstance?: string;
251
289
  frequency?: Duration;
252
290
  seedMetadata?: string;
291
+ patchversion?: string;
253
292
  };
254
293
  export type PackageVersionCreateOptions = {
255
294
  connection: Connection;
@@ -390,3 +429,33 @@ export declare const Package1VersionEvents: {
390
429
  };
391
430
  };
392
431
  export type PackageXml = Pick<Package, 'types' | 'version'>;
432
+ export type PackagePushRequestReportResult = {
433
+ PackageVersion: {
434
+ MetadataPackage: {
435
+ Name: string;
436
+ NamespacePrefix: string;
437
+ };
438
+ MetadataPackageId: string;
439
+ Name: string;
440
+ MajorVersion: string;
441
+ MinorVersion: string;
442
+ };
443
+ Id: string;
444
+ PackageVersionId: string;
445
+ Status: string;
446
+ ScheduledStartTime: string | null;
447
+ StartTime: string | null;
448
+ EndTime: string | null;
449
+ DurationSeconds: number | null;
450
+ };
451
+ export type PackagePushRequestJobCountByStatusResult = {
452
+ expr0: number;
453
+ };
454
+ export type PackagePushRequestReportJobFailuresResult = {
455
+ ErrorMessage: string;
456
+ ErrorDetails: string;
457
+ ErrorTitle: string;
458
+ ErrorSeverity: string;
459
+ ErrorType: string;
460
+ PackagePushJobId: string;
461
+ };
@@ -1,4 +1,5 @@
1
1
  export * from './package';
2
2
  export * from './packageVersion';
3
3
  export * from './subscriberPackageVersion';
4
+ export * from './packagePushUpgrade';
4
5
  export { VersionNumber } from './versionNumber';
@@ -24,6 +24,7 @@ exports.VersionNumber = void 0;
24
24
  __exportStar(require("./package"), exports);
25
25
  __exportStar(require("./packageVersion"), exports);
26
26
  __exportStar(require("./subscriberPackageVersion"), exports);
27
+ __exportStar(require("./packagePushUpgrade"), exports);
27
28
  var versionNumber_1 = require("./versionNumber");
28
29
  Object.defineProperty(exports, "VersionNumber", { enumerable: true, get: function () { return versionNumber_1.VersionNumber; } });
29
30
  //# sourceMappingURL=index.js.map
@@ -15,4 +15,5 @@ export declare function createPackageVersionCreateRequest(context: {
15
15
  definitionfile?: string;
16
16
  buildinstance?: string;
17
17
  seedmetadata?: string;
18
+ patchversion?: string;
18
19
  }, packageId: string, apiVersion: string): Promise<PackagingSObjects.Package2VersionCreateRequest>;
@@ -111,6 +111,7 @@ async function convertPackage(pkg, connection, options, project) {
111
111
  definitionfile: options.definitionfile,
112
112
  buildinstance: options.buildInstance,
113
113
  seedmetadata: options.seedMetadata,
114
+ patchversion: options.patchversion,
114
115
  }, packageId,
115
116
  // TODO: createPackageVersionCreateRequest requires apiVersion exist.
116
117
  // UT fail if we validate that it exists (there might not even be a project)
@@ -151,6 +152,7 @@ async function createPackageVersionCreateRequest(context, packageId, apiVersion)
151
152
  const packageVersBlobZipFile = node_path_1.default.join(packageVersTmpRoot, 'package-version-info.zip');
152
153
  let packageDescriptorJson = {
153
154
  id: packageId,
155
+ versionNumber: context.patchversion,
154
156
  };
155
157
  const settingsGenerator = new core_1.ScratchOrgSettingsGenerator({ asDirectory: true });
156
158
  const definitionFile = context.definitionfile;
@@ -0,0 +1,19 @@
1
+ import { Connection, SfProject } from '@salesforce/core';
2
+ import { PackagePushRequestListQueryOptions, PackagePushRequestListResult, PackagePushScheduleResult, PackagePushRequestReportQueryOptions, PackagePushRequestReportResult, PackagePushRequestReportJobFailuresResult, PackagePushRequestAbortQueryOptions } from '../interfaces';
3
+ export type PackagePushRequestListOptions = {
4
+ connection: Connection;
5
+ packageId: string;
6
+ project?: SfProject;
7
+ };
8
+ export declare class PackagePushUpgrade {
9
+ constructor();
10
+ static list(connection: Connection, options?: PackagePushRequestListQueryOptions): Promise<PackagePushRequestListResult[]>;
11
+ static report(connection: Connection, options: PackagePushRequestReportQueryOptions): Promise<PackagePushRequestReportResult[]>;
12
+ static getFailedJobs(connection: Connection, options: PackagePushRequestReportQueryOptions): Promise<number>;
13
+ static getSucceededJobs(connection: Connection, options: PackagePushRequestReportQueryOptions): Promise<number>;
14
+ static getTotalJobs(connection: Connection, options: PackagePushRequestReportQueryOptions): Promise<number>;
15
+ static getJobFailureReasons(connection: Connection, options: PackagePushRequestReportQueryOptions): Promise<PackagePushRequestReportJobFailuresResult[]>;
16
+ static schedule(connection: Connection, packageVersionId: string, scheduleTime: string | undefined, orgList: string[], isMigration?: boolean): Promise<PackagePushScheduleResult>;
17
+ static abort(connection: Connection, options: PackagePushRequestAbortQueryOptions): Promise<boolean>;
18
+ private static writeJobErrorsToFile;
19
+ }
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PackagePushUpgrade = void 0;
7
+ /*
8
+ * Copyright (c) 2024, salesforce.com, inc.
9
+ * All rights reserved.
10
+ * Licensed under the BSD 3-Clause license.
11
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
12
+ */
13
+ const promises_1 = __importDefault(require("node:fs/promises"));
14
+ const node_path_1 = __importDefault(require("node:path"));
15
+ const node_util_1 = __importDefault(require("node:util"));
16
+ const core_1 = require("@salesforce/core");
17
+ const packageUtils_1 = require("../utils/packageUtils");
18
+ class PackagePushUpgrade {
19
+ constructor() { }
20
+ static async list(connection, options) {
21
+ try {
22
+ const whereClause = constructWhereList(options);
23
+ return await queryList(node_util_1.default.format(getListQuery(), whereClause), connection);
24
+ }
25
+ catch (err) {
26
+ if (err instanceof Error) {
27
+ throw (0, packageUtils_1.applyErrorAction)((0, packageUtils_1.massageErrorMessage)(err));
28
+ }
29
+ throw err;
30
+ }
31
+ }
32
+ static async report(connection, options) {
33
+ try {
34
+ const whereClause = constructWhereReport(options);
35
+ return (await queryReport(node_util_1.default.format(getReportQuery(), whereClause), connection)).records;
36
+ }
37
+ catch (err) {
38
+ if (err instanceof Error) {
39
+ throw (0, packageUtils_1.applyErrorAction)((0, packageUtils_1.massageErrorMessage)(err));
40
+ }
41
+ throw err;
42
+ }
43
+ }
44
+ static async getFailedJobs(connection, options) {
45
+ try {
46
+ const whereClause = constructWhereJobCountByStatus(options, 'Failed');
47
+ return (await queryJobCountByStatus(node_util_1.default.format(getJobCountByStatusQuery(), whereClause), connection)).records[0]
48
+ ?.expr0;
49
+ }
50
+ catch (err) {
51
+ if (err instanceof Error) {
52
+ throw (0, packageUtils_1.applyErrorAction)((0, packageUtils_1.massageErrorMessage)(err));
53
+ }
54
+ throw err;
55
+ }
56
+ }
57
+ static async getSucceededJobs(connection, options) {
58
+ try {
59
+ const whereClause = constructWhereJobCountByStatus(options, 'Succeeded');
60
+ return (await queryJobCountByStatus(node_util_1.default.format(getJobCountByStatusQuery(), whereClause), connection)).records[0]
61
+ ?.expr0;
62
+ }
63
+ catch (err) {
64
+ if (err instanceof Error) {
65
+ throw (0, packageUtils_1.applyErrorAction)((0, packageUtils_1.massageErrorMessage)(err));
66
+ }
67
+ throw err;
68
+ }
69
+ }
70
+ static async getTotalJobs(connection, options) {
71
+ try {
72
+ const whereClause = constructWhereJobCountByStatus(options);
73
+ return (await queryJobCountByStatus(node_util_1.default.format(getJobCountByStatusQuery(), whereClause), connection)).records[0]
74
+ ?.expr0;
75
+ }
76
+ catch (err) {
77
+ if (err instanceof Error) {
78
+ throw (0, packageUtils_1.applyErrorAction)((0, packageUtils_1.massageErrorMessage)(err));
79
+ }
80
+ throw err;
81
+ }
82
+ }
83
+ static async getJobFailureReasons(connection, options) {
84
+ try {
85
+ const whereClause = constructWhereJobFailureReasons(options);
86
+ return (await queryJobFailureReasons(node_util_1.default.format(getJobFailureReasonsQuery(), whereClause), connection)).records;
87
+ }
88
+ catch (err) {
89
+ if (err instanceof Error) {
90
+ throw (0, packageUtils_1.applyErrorAction)((0, packageUtils_1.massageErrorMessage)(err));
91
+ }
92
+ throw err;
93
+ }
94
+ }
95
+ static async schedule(connection, packageVersionId, scheduleTime, orgList, isMigration = false) {
96
+ let job;
97
+ try {
98
+ const packagePushRequestBody = {
99
+ PackageVersionId: packageVersionId,
100
+ };
101
+ if (scheduleTime) {
102
+ packagePushRequestBody.ScheduledStartTime = scheduleTime;
103
+ }
104
+ if (isMigration) {
105
+ packagePushRequestBody.IsMigration = true;
106
+ }
107
+ const pushRequestResult = await connection.request({
108
+ method: 'POST',
109
+ url: `/services/data/v${connection.getApiVersion()}/sobjects/packagepushrequest/`,
110
+ body: JSON.stringify(packagePushRequestBody),
111
+ });
112
+ const pushJobs = orgList.map((orgId) => ({
113
+ PackagePushRequestId: pushRequestResult.id,
114
+ SubscriberOrganizationKey: orgId,
115
+ }));
116
+ // Create PackagePushJob for each org using Bulk API v2
117
+ job = connection.bulk2.createJob({ operation: 'insert', object: 'PackagePushJob' });
118
+ await job.open();
119
+ await job.uploadData(pushJobs);
120
+ await job.close();
121
+ await job.poll(1000, 600_000);
122
+ // If there are any errors for a job, write all specific job errors to an output file
123
+ const jobErrors = await job.getFailedResults();
124
+ if (jobErrors.length > 0) {
125
+ const filePath = await this.writeJobErrorsToFile(pushRequestResult?.id, jobErrors);
126
+ throw new core_1.SfError(`Push upgrade failed, job errors have been written to file: ${filePath}`);
127
+ }
128
+ await connection.request({
129
+ method: 'PATCH',
130
+ url: `/services/data/v${connection.getApiVersion()}/sobjects/packagepushrequest/` + pushRequestResult?.id,
131
+ body: JSON.stringify({ Status: 'Pending' }),
132
+ });
133
+ return {
134
+ PushRequestId: pushRequestResult.id,
135
+ ScheduledStartTime: scheduleTime,
136
+ Status: 'Pending',
137
+ };
138
+ }
139
+ catch (err) {
140
+ if (job && err.name !== 'JobPollingTimeoutError') {
141
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
142
+ job.delete().catch((ignored) => ignored);
143
+ }
144
+ throw (0, packageUtils_1.applyErrorAction)((0, packageUtils_1.massageErrorMessage)(err));
145
+ }
146
+ }
147
+ static async abort(connection, options) {
148
+ try {
149
+ // Fetch the current status of the PackagePushRequest
150
+ const abortQuery = node_util_1.default.format(getPushRequestStatusQuery(), getPushRequestStatusWhereClause(options));
151
+ const queryResult = await queryReport(abortQuery, connection);
152
+ if (!queryResult.records || queryResult.records.length === 0) {
153
+ throw new Error('Can’t abort package push upgrade request. The specified push upgrade ID isn’t valid. Check the ID (starts with 0DV) and retry the command.');
154
+ }
155
+ const pushRequest = queryResult.records[0];
156
+ // Validate the current status
157
+ if (!['Created', 'Pending'].includes(pushRequest.Status)) {
158
+ throw new Error(`Can’t abort package push upgrade request with status '${pushRequest.Status}'. Only push upgrade requests with a status of 'Created' or 'Pending' can be cancelled.`);
159
+ }
160
+ // Abort the push request by setting its status to "Canceled"
161
+ await connection.request({
162
+ method: 'PATCH',
163
+ url: `/services/data/v${connection.getApiVersion()}/sobjects/packagepushrequest/` + options.packagePushRequestId,
164
+ body: JSON.stringify({ Status: 'Canceled' }),
165
+ });
166
+ // Return the updated PackagePushRequest details
167
+ return true;
168
+ }
169
+ catch (err) {
170
+ if (err instanceof Error) {
171
+ throw (0, packageUtils_1.applyErrorAction)((0, packageUtils_1.massageErrorMessage)(err));
172
+ }
173
+ return false;
174
+ }
175
+ }
176
+ static async writeJobErrorsToFile(pushRequestId, jobErrors) {
177
+ const outputDir = node_path_1.default.join(process.cwd(), 'job_errors');
178
+ const outputFile = node_path_1.default.join(outputDir, `push_request_${pushRequestId}_errors.log`);
179
+ try {
180
+ await promises_1.default.mkdir(outputDir, { recursive: true });
181
+ const errorContent = jobErrors
182
+ .map((job, index) => `Job ${index + 1} Error:${JSON.stringify(job?.sf__Error, null, 2)}`)
183
+ .join('\n');
184
+ await promises_1.default.writeFile(outputFile, errorContent, 'utf-8');
185
+ return outputFile;
186
+ }
187
+ catch (error) {
188
+ throw new core_1.SfError('Error when saving job errors to file. ' + error.message);
189
+ }
190
+ }
191
+ }
192
+ exports.PackagePushUpgrade = PackagePushUpgrade;
193
+ async function queryList(query, connection) {
194
+ const queryResult = await connection.autoFetchQuery(query, {});
195
+ return queryResult.records;
196
+ }
197
+ function constructWhereList(options) {
198
+ const where = [];
199
+ if (options?.packageId) {
200
+ where.push(`PackageVersion.MetadataPackageId = '${options.packageId}'`);
201
+ }
202
+ if (options?.status) {
203
+ where.push(`Status = '${options.status}'`);
204
+ }
205
+ if (options?.scheduledLastDays) {
206
+ const daysAgo = new Date();
207
+ daysAgo.setDate(daysAgo.getDate() - options.scheduledLastDays);
208
+ where.push(`ScheduledStartTime >= ${daysAgo.toISOString()}`);
209
+ }
210
+ if (options?.isMigration) {
211
+ where.push(`IsMigration = ${options.isMigration}`);
212
+ }
213
+ return where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
214
+ }
215
+ function getListQuery() {
216
+ // WHERE, if applicable
217
+ return ('SELECT Id, PackageVersionId, PackageVersion.Name, PackageVersion.MajorVersion, PackageVersion.MinorVersion, Status, ScheduledStartTime, StartTime, EndTime, IsMigration FROM PackagePushRequest ' +
218
+ '%s');
219
+ }
220
+ async function queryReport(query, connection) {
221
+ return connection.autoFetchQuery(query, {});
222
+ }
223
+ async function queryJobCountByStatus(query, connection) {
224
+ return connection.autoFetchQuery(query, {});
225
+ }
226
+ function constructWhereReport(options) {
227
+ const where = [];
228
+ where.push(`Id = '${options.packagePushRequestId}'`);
229
+ return `WHERE ${where.join(' AND ')}`;
230
+ }
231
+ function getReportQuery() {
232
+ const QUERY = 'SELECT PackageVersion.MetadataPackage.Name, PackageVersion.MajorVersion, PackageVersion.MinorVersion, PackageVersion.MetadataPackage.NamespacePrefix, PackageVersion.MetadataPackageId, PackageVersionId, PackageVersion.Name, Id, Status, ScheduledStartTime, StartTime, EndTime, DurationSeconds FROM PackagePushRequest ' +
233
+ '%s'; // WHERE, if applicable
234
+ return QUERY;
235
+ }
236
+ function constructWhereJobCountByStatus(options, status) {
237
+ const where = [];
238
+ where.push(`PackagePushRequestId = '${options.packagePushRequestId}'`);
239
+ if (status) {
240
+ where.push(`Status = '${status}'`);
241
+ }
242
+ return `WHERE ${where.join(' AND ')}`;
243
+ }
244
+ function getJobCountByStatusQuery() {
245
+ const QUERY = 'SELECT Count(Id) FROM PackagePushJob ' + '%s '; // WHERE, if applicable
246
+ return QUERY;
247
+ }
248
+ function constructWhereJobFailureReasons(options) {
249
+ const where = [];
250
+ where.push(`PackagePushJob.PackagePushRequestId = '${options.packagePushRequestId}'`);
251
+ return `WHERE ${where.join(' AND ')}`;
252
+ }
253
+ function getJobFailureReasonsQuery() {
254
+ const QUERY = 'SELECT ErrorMessage, ErrorDetails, ErrorTitle, ErrorSeverity, ErrorType from PackagePushError ' + '%s '; // WHERE, if applicable
255
+ return QUERY;
256
+ }
257
+ async function queryJobFailureReasons(query, connection) {
258
+ return connection.autoFetchQuery(query, {});
259
+ }
260
+ function getPushRequestStatusWhereClause(options) {
261
+ const where = [];
262
+ where.push(`Id = '${options.packagePushRequestId}'`);
263
+ return `WHERE ${where.join(' AND ')}`;
264
+ }
265
+ function getPushRequestStatusQuery() {
266
+ const QUERY = 'SELECT Id, Status FROM PackagePushRequest ' + '%s';
267
+ return QUERY;
268
+ }
269
+ //# sourceMappingURL=packagePushUpgrade.js.map
@@ -46,6 +46,10 @@ You cannot use 'settings' and 'orgPreferences' in your scratch definition file,
46
46
 
47
47
  There was an error while reading or parsing the provided scratch definition file: %s
48
48
 
49
+ # invalidPatchVersionSpecified
50
+
51
+ Requested patch version number %s to convert is invalid
52
+
49
53
  # seedMDDirectoryDoesNotExist
50
54
 
51
55
  Seed metadata directory %s was specified but does not exist.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/packaging",
3
- "version": "4.4.0",
3
+ "version": "4.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
  ],
43
43
  "dependencies": {
44
44
  "@jsforce/jsforce-node": "^3.6.5",
45
- "@salesforce/core": "^8.8.5",
45
+ "@salesforce/core": "^8.11.1",
46
46
  "@salesforce/kit": "^3.2.3",
47
47
  "@salesforce/schemas": "^1.9.0",
48
48
  "@salesforce/source-deploy-retrieve": "^12.16.9",