@salesforce/core 3.7.4 → 3.7.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 +219 -0
- package/README.md +4 -4
- package/lib/config/config.d.ts +5 -5
- package/lib/config/config.js +5 -5
- package/lib/config/configAggregator.d.ts +2 -2
- package/lib/config/configAggregator.js +2 -2
- package/lib/config/configFile.d.ts +2 -2
- package/lib/config/configFile.js +7 -7
- package/lib/config/configStore.js +7 -6
- package/lib/config/envVars.d.ts +20 -5
- package/lib/config/envVars.js +70 -5
- package/lib/crypto/keyChainImpl.js +2 -3
- package/lib/deviceOauthService.js +2 -2
- package/lib/exported.d.ts +6 -4
- package/lib/exported.js +13 -6
- package/lib/globalInfo/accessors/aliasAccessor.js +2 -2
- package/lib/lifecycleEvents.js +1 -1
- package/lib/logger.d.ts +3 -3
- package/lib/logger.js +9 -10
- package/lib/messages.d.ts +2 -2
- package/lib/messages.js +4 -4
- package/lib/org/authInfo.d.ts +1 -1
- package/lib/org/authInfo.js +6 -7
- package/lib/org/authRemover.d.ts +2 -2
- package/lib/org/authRemover.js +2 -2
- package/lib/org/connection.d.ts +7 -2
- package/lib/org/connection.js +17 -4
- package/lib/org/org.d.ts +16 -6
- package/lib/org/org.js +52 -49
- package/lib/org/permissionSetAssignment.js +2 -2
- package/lib/org/scratchOrgCreate.d.ts +43 -0
- package/lib/org/scratchOrgCreate.js +142 -0
- package/lib/org/scratchOrgErrorCodes.d.ts +4 -0
- package/lib/org/scratchOrgErrorCodes.js +62 -0
- package/lib/org/scratchOrgFeatureDeprecation.d.ts +26 -0
- package/lib/org/scratchOrgFeatureDeprecation.js +110 -0
- package/lib/org/scratchOrgInfoApi.d.ts +94 -0
- package/lib/org/scratchOrgInfoApi.js +350 -0
- package/lib/org/scratchOrgInfoGenerator.d.ts +63 -0
- package/lib/org/scratchOrgInfoGenerator.js +223 -0
- package/lib/org/scratchOrgSettingsGenerator.d.ts +56 -0
- package/lib/org/scratchOrgSettingsGenerator.js +210 -0
- package/lib/org/user.js +8 -7
- package/lib/schema/printer.js +2 -2
- package/lib/schema/validator.d.ts +4 -4
- package/lib/schema/validator.js +9 -9
- package/lib/{sfdxError.d.ts → sfError.d.ts} +14 -9
- package/lib/{sfdxError.js → sfError.js} +20 -14
- package/lib/{sfdxProject.d.ts → sfProject.d.ts} +37 -27
- package/lib/{sfdxProject.js → sfProject.js} +75 -63
- package/lib/status/pollingClient.d.ts +2 -2
- package/lib/status/pollingClient.js +10 -4
- package/lib/status/streamingClient.d.ts +1 -1
- package/lib/status/streamingClient.js +6 -6
- package/lib/testSetup.d.ts +4 -4
- package/lib/testSetup.js +8 -8
- package/lib/util/fs.js +7 -7
- package/lib/util/internal.d.ts +2 -2
- package/lib/util/internal.js +2 -2
- package/lib/util/jsonXmlTools.d.ts +14 -0
- package/lib/util/jsonXmlTools.js +41 -0
- package/lib/util/mapKeys.d.ts +14 -0
- package/lib/util/mapKeys.js +48 -0
- package/lib/util/sfdcUrl.d.ts +2 -2
- package/lib/util/sfdcUrl.js +2 -2
- package/lib/util/zipWriter.d.ts +14 -0
- package/lib/util/zipWriter.js +68 -0
- package/lib/webOAuthServer.js +11 -11
- package/messages/envVars.md +53 -13
- package/messages/org.md +4 -0
- package/messages/scratchOrgCreate.md +27 -0
- package/messages/scratchOrgErrorCodes.md +99 -0
- package/messages/scratchOrgFeatureDeprecation.md +11 -0
- package/messages/scratchOrgInfoApi.md +11 -0
- package/messages/scratchOrgInfoGenerator.md +19 -0
- package/messages/user.md +4 -0
- package/package.json +5 -1
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getScratchOrgInfoPayload = exports.generateScratchOrgInfo = exports.getAncestorIds = void 0;
|
|
4
|
+
/*
|
|
5
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
6
|
+
* All rights reserved.
|
|
7
|
+
* Licensed under the BSD 3-Clause license.
|
|
8
|
+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
9
|
+
*/
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
const kit_1 = require("@salesforce/kit");
|
|
12
|
+
const ts_types_1 = require("@salesforce/ts-types");
|
|
13
|
+
const sfdc_1 = require("../util/sfdc");
|
|
14
|
+
const sfProject_1 = require("../sfProject");
|
|
15
|
+
const webOAuthServer_1 = require("../webOAuthServer");
|
|
16
|
+
const messages_1 = require("../messages");
|
|
17
|
+
const sfError_1 = require("../sfError");
|
|
18
|
+
const scratchOrgFeatureDeprecation_1 = require("./scratchOrgFeatureDeprecation");
|
|
19
|
+
const defaultConnectedAppInfo = {
|
|
20
|
+
clientId: 'PlatformCLI',
|
|
21
|
+
legacyClientId: 'SalesforceDevelopmentExperience',
|
|
22
|
+
legacyClientSecret: '1384510088588713504',
|
|
23
|
+
};
|
|
24
|
+
messages_1.Messages.importMessagesDirectory(__dirname);
|
|
25
|
+
const messages = messages_1.Messages.loadMessages('@salesforce/core', 'scratchOrgInfoGenerator');
|
|
26
|
+
const SNAPSHOT_UNSUPPORTED_OPTIONS = [
|
|
27
|
+
'features',
|
|
28
|
+
'orgPreferences',
|
|
29
|
+
'edition',
|
|
30
|
+
'sourceOrg',
|
|
31
|
+
'settingsPath',
|
|
32
|
+
'releaseVersion',
|
|
33
|
+
'language',
|
|
34
|
+
];
|
|
35
|
+
// A validator function to ensure any options parameters entered by the user adhere
|
|
36
|
+
// to a allowlist of valid option settings. Because org:create allows options to be
|
|
37
|
+
// input either key=value pairs or within the definition file, this validator is
|
|
38
|
+
// executed within the ctor and also after parsing/normalization of the definition file.
|
|
39
|
+
const optionsValidator = (key, scratchOrgInfoPayload) => {
|
|
40
|
+
if (key.toLowerCase() === 'durationdays') {
|
|
41
|
+
throw new sfError_1.SfError('unrecognizedScratchOrgOption', 'durationDays');
|
|
42
|
+
}
|
|
43
|
+
if (key.toLowerCase() === 'snapshot') {
|
|
44
|
+
const foundInvalidFields = SNAPSHOT_UNSUPPORTED_OPTIONS.filter((invalidField) => invalidField in scratchOrgInfoPayload);
|
|
45
|
+
if (foundInvalidFields.length > 0) {
|
|
46
|
+
throw new sfError_1.SfError(messages.getMessage('unsupportedSnapshotOrgCreateOptions', [foundInvalidFields.join(', ')]), 'orgSnapshot');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Generates the package2AncestorIds scratch org property
|
|
52
|
+
*
|
|
53
|
+
* @param scratchOrgInfo - the scratchOrgInfo passed in by the user
|
|
54
|
+
* @param projectJson - sfProjectJson
|
|
55
|
+
* @param hubOrg - the hub org, in case we need to do queries
|
|
56
|
+
*/
|
|
57
|
+
const getAncestorIds = async (scratchOrgInfo, projectJson, hubOrg) => {
|
|
58
|
+
if (Reflect.has(scratchOrgInfo, 'package2AncestorIds')) {
|
|
59
|
+
throw new sfError_1.SfError(messages.getMessage('Package2AncestorsIdsKeyNotSupportedError'), 'DeprecationError');
|
|
60
|
+
}
|
|
61
|
+
const packagesWithAncestors = (await projectJson.getPackageDirectories())
|
|
62
|
+
// check that the package has any ancestor types (id or version)
|
|
63
|
+
.filter((packageDir) => packageDir.ancestorId || packageDir.ancestorVersion);
|
|
64
|
+
if (packagesWithAncestors.length === 0) {
|
|
65
|
+
return '';
|
|
66
|
+
}
|
|
67
|
+
const ancestorIds = await Promise.all(packagesWithAncestors.map(async (packageDir) => {
|
|
68
|
+
var _a, _b, _c;
|
|
69
|
+
// ancestorID can be 05i, or 04t, alias; OR "ancestorVersion": "4.6.0.1"
|
|
70
|
+
// according to docs, 05i is not ok: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev2gp_config_file.htm
|
|
71
|
+
if (packageDir.ancestorVersion) {
|
|
72
|
+
if (!/^[0-9]+.[0-9]+.[0-9]+(.[0-9]+)?$/.test(packageDir.ancestorVersion)) {
|
|
73
|
+
throw messages.createError('InvalidAncestorVersionFormatError', [packageDir.ancestorVersion]);
|
|
74
|
+
}
|
|
75
|
+
// package can be an ID, but not according to docs
|
|
76
|
+
const packageAliases = projectJson.get('packageAliases');
|
|
77
|
+
const packageId = (_a = packageAliases[(0, ts_types_1.ensureString)(packageDir.package)]) !== null && _a !== void 0 ? _a : packageDir.package;
|
|
78
|
+
const [major, minor, patch] = packageDir.ancestorVersion.split('.');
|
|
79
|
+
let releasedAncestor;
|
|
80
|
+
try {
|
|
81
|
+
releasedAncestor = await hubOrg
|
|
82
|
+
.getConnection()
|
|
83
|
+
.singleRecordQuery(`SELECT Id, IsReleased FROM Package2Version WHERE Package2Id = '${packageId}' AND MajorVersion = ${major} AND MinorVersion = ${minor} AND PatchVersion = ${patch} and IsReleased = true`, { tooling: true });
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
throw new sfError_1.SfError(messages.getMessage('NoMatchingAncestorError', [packageDir.ancestorVersion, packageDir.package]), 'NoMatchingAncestorError', [messages.getMessage('AncestorNotReleasedError', [packageDir.ancestorVersion])]);
|
|
87
|
+
}
|
|
88
|
+
if (packageDir.ancestorId && packageDir.ancestorId !== releasedAncestor.Id) {
|
|
89
|
+
throw messages.createError('AncestorIdVersionMismatchError', [
|
|
90
|
+
packageDir.ancestorVersion,
|
|
91
|
+
packageDir.ancestorId,
|
|
92
|
+
]);
|
|
93
|
+
}
|
|
94
|
+
return releasedAncestor.Id;
|
|
95
|
+
}
|
|
96
|
+
if ((_b = packageDir === null || packageDir === void 0 ? void 0 : packageDir.ancestorId) === null || _b === void 0 ? void 0 : _b.startsWith('05i')) {
|
|
97
|
+
// if it's already a 05i return it, otherwise query for it
|
|
98
|
+
return packageDir.ancestorId;
|
|
99
|
+
}
|
|
100
|
+
if ((_c = packageDir === null || packageDir === void 0 ? void 0 : packageDir.ancestorId) === null || _c === void 0 ? void 0 : _c.startsWith('04t')) {
|
|
101
|
+
// query for the Id
|
|
102
|
+
return (await hubOrg
|
|
103
|
+
.getConnection()
|
|
104
|
+
.singleRecordQuery(`SELECT Id FROM Package2Version WHERE SubscriberPackageVersionId = '${packageDir.ancestorId}'`, { tooling: true })).Id;
|
|
105
|
+
}
|
|
106
|
+
// ancestorID can be an alias get it from projectJson
|
|
107
|
+
const packageAliases = projectJson.get('packageAliases');
|
|
108
|
+
if (packageDir.ancestorId && (packageAliases === null || packageAliases === void 0 ? void 0 : packageAliases[packageDir.ancestorId])) {
|
|
109
|
+
return packageAliases[packageDir.ancestorId];
|
|
110
|
+
}
|
|
111
|
+
throw new sfError_1.SfError(`Invalid ancestorId ${packageDir.ancestorId}`, 'InvalidAncestorId');
|
|
112
|
+
}));
|
|
113
|
+
return Array.from(new Set(ancestorIds)).join(';');
|
|
114
|
+
};
|
|
115
|
+
exports.getAncestorIds = getAncestorIds;
|
|
116
|
+
/**
|
|
117
|
+
* Takes in a scratchOrgInfo and fills in the missing fields
|
|
118
|
+
*
|
|
119
|
+
* @param hubOrg the environment hub org
|
|
120
|
+
* @param scratchOrgInfoPayload - the scratchOrgInfo passed in by the user
|
|
121
|
+
* @param nonamespace create the scratch org with no namespace
|
|
122
|
+
* @param ignoreAncestorIds true if the sfdx-project.json ancestorId keys should be ignored
|
|
123
|
+
*/
|
|
124
|
+
const generateScratchOrgInfo = async ({ hubOrg, scratchOrgInfoPayload, nonamespace, ignoreAncestorIds, }) => {
|
|
125
|
+
var _a, _b;
|
|
126
|
+
let sfProject;
|
|
127
|
+
try {
|
|
128
|
+
sfProject = await sfProject_1.SfProjectJson.create({});
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
// project is not required
|
|
132
|
+
}
|
|
133
|
+
scratchOrgInfoPayload.orgName = (_a = scratchOrgInfoPayload.orgName) !== null && _a !== void 0 ? _a : 'Company';
|
|
134
|
+
scratchOrgInfoPayload.package2AncestorIds =
|
|
135
|
+
!ignoreAncestorIds && (sfProject === null || sfProject === void 0 ? void 0 : sfProject.hasPackages())
|
|
136
|
+
? await (0, exports.getAncestorIds)(scratchOrgInfoPayload, sfProject, hubOrg)
|
|
137
|
+
: '';
|
|
138
|
+
// Use the Hub org's client ID value, if one wasn't provided to us, or the default
|
|
139
|
+
if (!scratchOrgInfoPayload.connectedAppConsumerKey) {
|
|
140
|
+
scratchOrgInfoPayload.connectedAppConsumerKey =
|
|
141
|
+
(_b = hubOrg.getConnection().getAuthInfoFields().clientId) !== null && _b !== void 0 ? _b : defaultConnectedAppInfo.clientId;
|
|
142
|
+
}
|
|
143
|
+
if (!nonamespace && (sfProject === null || sfProject === void 0 ? void 0 : sfProject.get('namespace'))) {
|
|
144
|
+
scratchOrgInfoPayload.namespace = sfProject.get('namespace');
|
|
145
|
+
}
|
|
146
|
+
// we already have the info, and want to get rid of configApi, so this doesn't use that
|
|
147
|
+
scratchOrgInfoPayload.connectedAppCallbackUrl = `http://localhost:${await webOAuthServer_1.WebOAuthServer.determineOauthPort()}/OauthRedirect`;
|
|
148
|
+
return scratchOrgInfoPayload;
|
|
149
|
+
};
|
|
150
|
+
exports.generateScratchOrgInfo = generateScratchOrgInfo;
|
|
151
|
+
/**
|
|
152
|
+
* Returns a valid signup json
|
|
153
|
+
*
|
|
154
|
+
* definitionjson org definition in JSON format
|
|
155
|
+
* definitionfile path to an org definition file
|
|
156
|
+
* connectedAppConsumerKey The connected app consumer key. May be null for JWT OAuth flow.
|
|
157
|
+
* durationdays duration of the scratch org (in days) (default:1, min:1, max:30)
|
|
158
|
+
* nonamespace create the scratch org with no namespace
|
|
159
|
+
* noancestors do not include second-generation package ancestors in the scratch org
|
|
160
|
+
* orgConfig overrides definitionjson
|
|
161
|
+
*
|
|
162
|
+
* @returns scratchOrgInfoPayload: ScratchOrgInfoPayload;
|
|
163
|
+
ignoreAncestorIds: boolean;
|
|
164
|
+
warnings: string[];
|
|
165
|
+
*/
|
|
166
|
+
const getScratchOrgInfoPayload = async (options) => {
|
|
167
|
+
var _a;
|
|
168
|
+
let warnings = [];
|
|
169
|
+
// orgConfig input overrides definitionjson (-j option; hidden/deprecated)
|
|
170
|
+
const definitionJson = options.definitionjson ? JSON.parse(options.definitionjson) : {};
|
|
171
|
+
const orgConfigInput = { ...definitionJson, ...((_a = options.orgConfig) !== null && _a !== void 0 ? _a : {}) };
|
|
172
|
+
let scratchOrgInfoPayload = orgConfigInput;
|
|
173
|
+
// the -f option
|
|
174
|
+
if (options.definitionfile) {
|
|
175
|
+
try {
|
|
176
|
+
const fileData = await fs_1.promises.readFile(options.definitionfile, 'utf8');
|
|
177
|
+
const defFileContents = (0, kit_1.parseJson)(fileData);
|
|
178
|
+
// definitionjson and orgConfig override file input
|
|
179
|
+
scratchOrgInfoPayload = { ...defFileContents, ...orgConfigInput };
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
const error = err;
|
|
183
|
+
if (error.name === 'JsonParseError') {
|
|
184
|
+
throw new sfError_1.SfError(`An error occurred parsing ${options.definitionfile}`);
|
|
185
|
+
}
|
|
186
|
+
throw sfError_1.SfError.wrap(error);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// scratchOrgInfoPayload must be heads down camelcase.
|
|
190
|
+
const upperCaseKey = sfdc_1.sfdc.findUpperCaseKeys(scratchOrgInfoPayload);
|
|
191
|
+
if (upperCaseKey) {
|
|
192
|
+
throw new sfError_1.SfError('InvalidJsonCasing', upperCaseKey);
|
|
193
|
+
}
|
|
194
|
+
// Now run the fully resolved user input against the validator
|
|
195
|
+
Object.keys(scratchOrgInfoPayload).forEach((key) => {
|
|
196
|
+
optionsValidator(key, scratchOrgInfoPayload);
|
|
197
|
+
});
|
|
198
|
+
if (options.connectedAppConsumerKey) {
|
|
199
|
+
scratchOrgInfoPayload.connectedAppConsumerKey = options.connectedAppConsumerKey;
|
|
200
|
+
}
|
|
201
|
+
scratchOrgInfoPayload.durationDays = options.durationDays;
|
|
202
|
+
// Throw warnings for deprecated scratch org features.
|
|
203
|
+
const scratchOrgFeatureDeprecation = new scratchOrgFeatureDeprecation_1.ScratchOrgFeatureDeprecation();
|
|
204
|
+
// convert various supported array and string formats to a semi-colon-delimited string
|
|
205
|
+
if (scratchOrgInfoPayload.features) {
|
|
206
|
+
if (typeof scratchOrgInfoPayload.features === 'string') {
|
|
207
|
+
scratchOrgInfoPayload.features = scratchOrgInfoPayload.features.split(/[;,]/);
|
|
208
|
+
}
|
|
209
|
+
warnings = scratchOrgFeatureDeprecation.getFeatureWarnings(scratchOrgInfoPayload.features);
|
|
210
|
+
scratchOrgInfoPayload.features = scratchOrgInfoPayload.features.map((feature) => feature.trim());
|
|
211
|
+
scratchOrgInfoPayload.features = scratchOrgFeatureDeprecation
|
|
212
|
+
.filterDeprecatedFeatures(scratchOrgInfoPayload.features)
|
|
213
|
+
.join(';');
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
scratchOrgInfoPayload,
|
|
217
|
+
// Ignore ancestor ids only when 'nonamespace' or 'noancestors' options are specified
|
|
218
|
+
ignoreAncestorIds: options.nonamespace || options.noancestors || false,
|
|
219
|
+
warnings,
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
exports.getScratchOrgInfoPayload = getScratchOrgInfoPayload;
|
|
223
|
+
//# sourceMappingURL=scratchOrgInfoGenerator.js.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { JsonMap } from '@salesforce/ts-types';
|
|
2
|
+
import { ScratchOrgInfo } from './scratchOrgInfoApi';
|
|
3
|
+
import { Org } from './org';
|
|
4
|
+
export declare enum RequestStatus {
|
|
5
|
+
Pending = "Pending",
|
|
6
|
+
InProgress = "InProgress",
|
|
7
|
+
Succeeded = "Succeeded",
|
|
8
|
+
SucceededPartial = "SucceededPartial",
|
|
9
|
+
Failed = "Failed",
|
|
10
|
+
Canceling = "Canceling",
|
|
11
|
+
Canceled = "Canceled"
|
|
12
|
+
}
|
|
13
|
+
export interface ObjectSetting extends JsonMap {
|
|
14
|
+
sharingModel?: string;
|
|
15
|
+
defaultRecordType?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface BusinessProcessFileContent extends JsonMap {
|
|
18
|
+
fullName: string;
|
|
19
|
+
isActive: boolean;
|
|
20
|
+
values: [
|
|
21
|
+
{
|
|
22
|
+
fullName: string;
|
|
23
|
+
default?: boolean;
|
|
24
|
+
}
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Helper class for dealing with the settings that are defined in a scratch definition file. This class knows how to extract the
|
|
29
|
+
* settings from the definition, how to expand them into a MD directory and how to generate a package.xml.
|
|
30
|
+
*/
|
|
31
|
+
export default class SettingsGenerator {
|
|
32
|
+
private settingData?;
|
|
33
|
+
private objectSettingsData?;
|
|
34
|
+
private logger;
|
|
35
|
+
private writer;
|
|
36
|
+
private shapeDirName;
|
|
37
|
+
constructor();
|
|
38
|
+
/** extract the settings from the scratch def file, if they are present. */
|
|
39
|
+
extract(scratchDef: ScratchOrgInfo): Promise<void>;
|
|
40
|
+
/** True if we are currently tracking setting or object setting data. */
|
|
41
|
+
hasSettings(): boolean;
|
|
42
|
+
/** Create temporary deploy directory used to upload the scratch org shape.
|
|
43
|
+
* This will create the dir, all of the .setting files and minimal object files needed for objectSettings
|
|
44
|
+
*/
|
|
45
|
+
createDeploy(): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Deploys the settings to the org.
|
|
48
|
+
*/
|
|
49
|
+
deploySettingsViaFolder(scratchOrg: Org, apiVersion: string): Promise<void>;
|
|
50
|
+
private writeObjectSettingsIfNeeded;
|
|
51
|
+
private writeSettingsIfNeeded;
|
|
52
|
+
private createPackageXml;
|
|
53
|
+
private createObjectFileContent;
|
|
54
|
+
private createRecordTypeFileContent;
|
|
55
|
+
private createBusinessProcessFileContent;
|
|
56
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2021, 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.RequestStatus = void 0;
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const kit_1 = require("@salesforce/kit");
|
|
12
|
+
const ts_types_1 = require("@salesforce/ts-types");
|
|
13
|
+
const js2xmlparser = require("js2xmlparser");
|
|
14
|
+
const logger_1 = require("../logger");
|
|
15
|
+
const sfError_1 = require("../sfError");
|
|
16
|
+
const jsonXmlTools_1 = require("../util/jsonXmlTools");
|
|
17
|
+
const zipWriter_1 = require("../util/zipWriter");
|
|
18
|
+
const pollingClient_1 = require("../status/pollingClient");
|
|
19
|
+
var RequestStatus;
|
|
20
|
+
(function (RequestStatus) {
|
|
21
|
+
RequestStatus["Pending"] = "Pending";
|
|
22
|
+
RequestStatus["InProgress"] = "InProgress";
|
|
23
|
+
RequestStatus["Succeeded"] = "Succeeded";
|
|
24
|
+
RequestStatus["SucceededPartial"] = "SucceededPartial";
|
|
25
|
+
RequestStatus["Failed"] = "Failed";
|
|
26
|
+
RequestStatus["Canceling"] = "Canceling";
|
|
27
|
+
RequestStatus["Canceled"] = "Canceled";
|
|
28
|
+
})(RequestStatus = exports.RequestStatus || (exports.RequestStatus = {}));
|
|
29
|
+
const breakPolling = ['Succeeded', 'SucceededPartial', 'Failed', 'Canceled'];
|
|
30
|
+
/**
|
|
31
|
+
* Helper class for dealing with the settings that are defined in a scratch definition file. This class knows how to extract the
|
|
32
|
+
* settings from the definition, how to expand them into a MD directory and how to generate a package.xml.
|
|
33
|
+
*/
|
|
34
|
+
class SettingsGenerator {
|
|
35
|
+
constructor() {
|
|
36
|
+
this.shapeDirName = `shape_${Date.now()}`;
|
|
37
|
+
this.logger = logger_1.Logger.childFromRoot('SettingsGenerator');
|
|
38
|
+
// If SFDX_MDAPI_TEMP_DIR is set, copy settings to that dir for people to inspect.
|
|
39
|
+
const mdapiTmpDir = kit_1.env.getString('SFDX_MDAPI_TEMP_DIR');
|
|
40
|
+
this.writer = new zipWriter_1.ZipWriter(mdapiTmpDir);
|
|
41
|
+
}
|
|
42
|
+
/** extract the settings from the scratch def file, if they are present. */
|
|
43
|
+
async extract(scratchDef) {
|
|
44
|
+
this.logger.debug('extracting settings from scratch definition file');
|
|
45
|
+
this.settingData = scratchDef.settings;
|
|
46
|
+
this.objectSettingsData = scratchDef.objectSettings;
|
|
47
|
+
this.logger.debug('settings are', this.settingData);
|
|
48
|
+
}
|
|
49
|
+
/** True if we are currently tracking setting or object setting data. */
|
|
50
|
+
hasSettings() {
|
|
51
|
+
return !(0, kit_1.isEmpty)(this.settingData) || !(0, kit_1.isEmpty)(this.objectSettingsData);
|
|
52
|
+
}
|
|
53
|
+
/** Create temporary deploy directory used to upload the scratch org shape.
|
|
54
|
+
* This will create the dir, all of the .setting files and minimal object files needed for objectSettings
|
|
55
|
+
*/
|
|
56
|
+
async createDeploy() {
|
|
57
|
+
const settingsDir = path.join(this.shapeDirName, 'settings');
|
|
58
|
+
const objectsDir = path.join(this.shapeDirName, 'objects');
|
|
59
|
+
await Promise.all([this.writeSettingsIfNeeded(settingsDir), this.writeObjectSettingsIfNeeded(objectsDir)]);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Deploys the settings to the org.
|
|
63
|
+
*/
|
|
64
|
+
async deploySettingsViaFolder(scratchOrg, apiVersion) {
|
|
65
|
+
const username = scratchOrg.getUsername();
|
|
66
|
+
const logger = await logger_1.Logger.child('deploySettingsViaFolder');
|
|
67
|
+
this.createPackageXml(apiVersion);
|
|
68
|
+
await this.writer.finalize();
|
|
69
|
+
const connection = scratchOrg.getConnection();
|
|
70
|
+
logger.debug(`deploying to apiVersion: ${apiVersion}`);
|
|
71
|
+
connection.setApiVersion(apiVersion);
|
|
72
|
+
const { id } = await connection.deploy(this.writer.buffer, {});
|
|
73
|
+
logger.debug(`deploying settings id ${id}`);
|
|
74
|
+
let result = await connection.metadata.checkDeployStatus(id);
|
|
75
|
+
const pollingOptions = {
|
|
76
|
+
async poll() {
|
|
77
|
+
try {
|
|
78
|
+
result = await connection.metadata.checkDeployStatus(id, true);
|
|
79
|
+
logger.debug(`Deploy id: ${id} status: ${result.status}`);
|
|
80
|
+
if (breakPolling.includes(result.status)) {
|
|
81
|
+
return {
|
|
82
|
+
completed: true,
|
|
83
|
+
payload: result.status,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
completed: false,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
logger.debug(`An error occurred trying to check deploy id: ${id}`);
|
|
92
|
+
logger.debug(`Error: ${error.message}`);
|
|
93
|
+
logger.debug('Re-trying deploy check again....');
|
|
94
|
+
return {
|
|
95
|
+
completed: false,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
timeout: kit_1.Duration.minutes(10),
|
|
100
|
+
frequency: kit_1.Duration.seconds(1),
|
|
101
|
+
timeoutErrorName: 'DeployingSettingsTimeoutError',
|
|
102
|
+
};
|
|
103
|
+
const client = await pollingClient_1.PollingClient.create(pollingOptions);
|
|
104
|
+
const status = await client.subscribe();
|
|
105
|
+
if (status !== RequestStatus.Succeeded) {
|
|
106
|
+
const componentFailures = (0, ts_types_1.ensureObject)(result.details).componentFailures;
|
|
107
|
+
const failures = (Array.isArray(componentFailures) ? componentFailures : [componentFailures])
|
|
108
|
+
.map((failure) => failure.problem)
|
|
109
|
+
.join('\n');
|
|
110
|
+
const error = new sfError_1.SfError(`A scratch org was created with username ${username}, but the settings failed to deploy due to: \n${failures}`, 'ProblemDeployingSettings');
|
|
111
|
+
error.setData(result);
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async writeObjectSettingsIfNeeded(objectsDir) {
|
|
116
|
+
if (!this.objectSettingsData || !Object.keys(this.objectSettingsData).length) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
for (const objectName of Object.keys(this.objectSettingsData)) {
|
|
120
|
+
const value = this.objectSettingsData[objectName];
|
|
121
|
+
// writes the object file in source format
|
|
122
|
+
const objectDir = path.join(objectsDir, (0, kit_1.upperFirst)(objectName));
|
|
123
|
+
const customObjectDir = path.join(objectDir, `${(0, kit_1.upperFirst)(objectName)}.object`);
|
|
124
|
+
const customObjectXml = (0, jsonXmlTools_1.JsonAsXml)({
|
|
125
|
+
json: this.createObjectFileContent(value),
|
|
126
|
+
type: 'RecordType',
|
|
127
|
+
});
|
|
128
|
+
this.writer.addToZip(customObjectXml, customObjectDir);
|
|
129
|
+
if (value.defaultRecordType) {
|
|
130
|
+
const recordTypesDir = path.join(objectDir, 'recordTypes', `${(0, kit_1.upperFirst)(value.defaultRecordType)}.recordType`);
|
|
131
|
+
const recordTypesFileContent = this.createRecordTypeFileContent(objectName, value);
|
|
132
|
+
const recordTypesXml = (0, jsonXmlTools_1.JsonAsXml)({
|
|
133
|
+
json: recordTypesFileContent,
|
|
134
|
+
type: 'RecordType',
|
|
135
|
+
});
|
|
136
|
+
this.writer.addToZip(recordTypesXml, recordTypesDir);
|
|
137
|
+
// for things that required a businessProcess
|
|
138
|
+
if (recordTypesFileContent.businessProcess) {
|
|
139
|
+
const businessProcessesDir = path.join(objectDir, 'businessProcesses', `${recordTypesFileContent.businessProcess}.businessProcess`);
|
|
140
|
+
const businessProcessesXml = (0, jsonXmlTools_1.JsonAsXml)({
|
|
141
|
+
json: this.createBusinessProcessFileContent(objectName, recordTypesFileContent.businessProcess),
|
|
142
|
+
type: 'BusinessProcess',
|
|
143
|
+
});
|
|
144
|
+
this.writer.addToZip(businessProcessesXml, businessProcessesDir);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async writeSettingsIfNeeded(settingsDir) {
|
|
150
|
+
if (this.settingData) {
|
|
151
|
+
for (const item of Object.keys(this.settingData)) {
|
|
152
|
+
const value = (0, ts_types_1.getObject)(this.settingData, item);
|
|
153
|
+
const typeName = (0, kit_1.upperFirst)(item);
|
|
154
|
+
const fname = typeName.replace('Settings', '');
|
|
155
|
+
const fileContent = js2xmlparser.parse(typeName, value);
|
|
156
|
+
this.writer.addToZip(fileContent, path.join(settingsDir, fname + '.settings'));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
createPackageXml(apiVersion) {
|
|
161
|
+
const pkg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
162
|
+
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
163
|
+
<types>
|
|
164
|
+
<members>*</members>
|
|
165
|
+
<name>Settings</name>
|
|
166
|
+
</types>
|
|
167
|
+
<types>
|
|
168
|
+
<members>*</members>
|
|
169
|
+
<name>CustomObject</name>
|
|
170
|
+
</types>
|
|
171
|
+
<version>${apiVersion}</version>
|
|
172
|
+
</Package>`;
|
|
173
|
+
this.writer.addToZip(pkg, path.join(this.shapeDirName, 'package.xml'));
|
|
174
|
+
}
|
|
175
|
+
createObjectFileContent(json) {
|
|
176
|
+
const output = {};
|
|
177
|
+
if (json.sharingModel) {
|
|
178
|
+
output.sharingModel = (0, kit_1.upperFirst)(json.sharingModel);
|
|
179
|
+
}
|
|
180
|
+
return output;
|
|
181
|
+
}
|
|
182
|
+
createRecordTypeFileContent(objectName, setting) {
|
|
183
|
+
const defaultRecordType = (0, kit_1.upperFirst)(setting.defaultRecordType);
|
|
184
|
+
const output = {
|
|
185
|
+
fullName: defaultRecordType,
|
|
186
|
+
label: defaultRecordType,
|
|
187
|
+
active: true,
|
|
188
|
+
};
|
|
189
|
+
// all the edge cases
|
|
190
|
+
if (['Case', 'Lead', 'Opportunity', 'Solution'].includes((0, kit_1.upperFirst)(objectName))) {
|
|
191
|
+
return { ...output, businessProcess: `${defaultRecordType}Process` };
|
|
192
|
+
}
|
|
193
|
+
return output;
|
|
194
|
+
}
|
|
195
|
+
createBusinessProcessFileContent(objectName, businessProcessName) {
|
|
196
|
+
const objectToBusinessProcessPicklist = {
|
|
197
|
+
Opportunity: { fullName: 'Prospecting' },
|
|
198
|
+
Case: { fullName: 'New', default: true },
|
|
199
|
+
Lead: { fullName: 'New - Not Contacted', default: true },
|
|
200
|
+
Solution: { fullName: 'Draft', default: true },
|
|
201
|
+
};
|
|
202
|
+
return {
|
|
203
|
+
fullName: businessProcessName,
|
|
204
|
+
isActive: true,
|
|
205
|
+
values: [objectToBusinessProcessPicklist[(0, kit_1.upperFirst)(objectName)]],
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.default = SettingsGenerator;
|
|
210
|
+
//# sourceMappingURL=scratchOrgSettingsGenerator.js.map
|
package/lib/org/user.js
CHANGED
|
@@ -11,12 +11,12 @@ const os_1 = require("os");
|
|
|
11
11
|
const kit_1 = require("@salesforce/kit");
|
|
12
12
|
const ts_types_1 = require("@salesforce/ts-types");
|
|
13
13
|
const http_api_1 = require("jsforce/lib/http-api");
|
|
14
|
-
const connection_1 = require("../org/connection");
|
|
15
14
|
const logger_1 = require("../logger");
|
|
16
15
|
const messages_1 = require("../messages");
|
|
17
16
|
const secureBuffer_1 = require("../crypto/secureBuffer");
|
|
18
|
-
const
|
|
17
|
+
const sfError_1 = require("../sfError");
|
|
19
18
|
const sfdc_1 = require("../util/sfdc");
|
|
19
|
+
const connection_1 = require("./connection");
|
|
20
20
|
const permissionSetAssignment_1 = require("./permissionSetAssignment");
|
|
21
21
|
const authInfo_1 = require("./authInfo");
|
|
22
22
|
const rand = (len) => Math.floor(Math.random() * len.length);
|
|
@@ -185,11 +185,11 @@ class User extends kit_1.AsyncCreatable {
|
|
|
185
185
|
static generatePasswordUtf8(passwordCondition = { length: 13, complexity: 5 }) {
|
|
186
186
|
if (!PASSWORD_COMPLEXITY[passwordCondition.complexity]) {
|
|
187
187
|
const msg = messages.getMessage('complexityOutOfBound');
|
|
188
|
-
throw new
|
|
188
|
+
throw new sfError_1.SfError(msg, 'complexityOutOfBound');
|
|
189
189
|
}
|
|
190
190
|
if (passwordCondition.length < 8 || passwordCondition.length > 1000) {
|
|
191
191
|
const msg = messages.getMessage('lengthOutOfBound');
|
|
192
|
-
throw new
|
|
192
|
+
throw new sfError_1.SfError(msg, 'lengthOutOfBound');
|
|
193
193
|
}
|
|
194
194
|
let password = [];
|
|
195
195
|
['SYMBOLS', 'NUMBERS', 'UPPER', 'LOWER'].forEach((charSet) => {
|
|
@@ -228,7 +228,6 @@ class User extends kit_1.AsyncCreatable {
|
|
|
228
228
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
229
229
|
password.value(async (buffer) => {
|
|
230
230
|
try {
|
|
231
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
232
231
|
// @ts-ignore TODO: expose `soap` on Connection however appropriate
|
|
233
232
|
const soap = userConnection.soap;
|
|
234
233
|
await soap.setPassword((0, ts_types_1.ensureString)(info.getFields().userId), buffer.toString('utf8'));
|
|
@@ -294,6 +293,7 @@ class User extends kit_1.AsyncCreatable {
|
|
|
294
293
|
* ```
|
|
295
294
|
*/
|
|
296
295
|
async createUser(fields) {
|
|
296
|
+
var _a;
|
|
297
297
|
// Create a user and get a refresh token
|
|
298
298
|
const refreshTokenSecret = await this.createUserInternal(fields);
|
|
299
299
|
// Create the initial auth info
|
|
@@ -301,7 +301,8 @@ class User extends kit_1.AsyncCreatable {
|
|
|
301
301
|
const adminUserAuthFields = authInfo.getFields(true);
|
|
302
302
|
// Setup oauth options for the new user
|
|
303
303
|
const oauthOptions = {
|
|
304
|
-
|
|
304
|
+
// Communities users require the instance for auth
|
|
305
|
+
loginUrl: (_a = adminUserAuthFields.instanceUrl) !== null && _a !== void 0 ? _a : adminUserAuthFields.loginUrl,
|
|
305
306
|
refreshToken: refreshTokenSecret.buffer.value((buffer) => buffer.toString('utf8')),
|
|
306
307
|
clientId: adminUserAuthFields.clientId,
|
|
307
308
|
clientSecret: adminUserAuthFields.clientSecret,
|
|
@@ -406,7 +407,7 @@ class User extends kit_1.AsyncCreatable {
|
|
|
406
407
|
}
|
|
407
408
|
}
|
|
408
409
|
this.logger.debug(message);
|
|
409
|
-
throw new
|
|
410
|
+
throw new sfError_1.SfError(message, 'UserCreateHttpError');
|
|
410
411
|
}
|
|
411
412
|
fields.id = (0, ts_types_1.ensureString)(responseBody.id);
|
|
412
413
|
await this.updateRequiredUserFields(fields);
|
package/lib/schema/printer.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.SchemaPrinter = exports.SchemaPropertyRenderer = void 0;
|
|
10
10
|
const ts_types_1 = require("@salesforce/ts-types");
|
|
11
|
-
const
|
|
11
|
+
const sfError_1 = require("../sfError");
|
|
12
12
|
/**
|
|
13
13
|
* Renders schema properties. By default, this is simply an identity transform. Subclasses may provide more
|
|
14
14
|
* interesting decorations of each values, such as ANSI coloring.
|
|
@@ -78,7 +78,7 @@ class SchemaPrinter {
|
|
|
78
78
|
// No need to add to messages, since this should never happen. In fact,
|
|
79
79
|
// this will cause a test failure if there is a command that uses a schema
|
|
80
80
|
// with no properties defined.
|
|
81
|
-
throw new
|
|
81
|
+
throw new sfError_1.SfError('There is no purpose to print a schema with no properties or items');
|
|
82
82
|
}
|
|
83
83
|
const startLevel = 0;
|
|
84
84
|
const add = this.addFn(startLevel);
|
|
@@ -27,8 +27,8 @@ export declare class SchemaValidator {
|
|
|
27
27
|
* Performs validation of JSON data against the schema located at the `schemaPath` value provided
|
|
28
28
|
* at instantiation.
|
|
29
29
|
*
|
|
30
|
-
* **Throws** *{@link
|
|
31
|
-
* **Throws** *{@link
|
|
30
|
+
* **Throws** *{@link SfError}{ name: 'ValidationSchemaFieldError' }* If there are known validations errors.
|
|
31
|
+
* **Throws** *{@link SfError}{ name: 'ValidationSchemaUnknownError' }* If there are unknown validations errors.
|
|
32
32
|
*
|
|
33
33
|
* @param json A JSON value to validate against this instance's target schema.
|
|
34
34
|
* @returns The validated JSON data.
|
|
@@ -38,8 +38,8 @@ export declare class SchemaValidator {
|
|
|
38
38
|
* Performs validation of JSON data against the schema located at the `schemaPath` value provided
|
|
39
39
|
* at instantiation.
|
|
40
40
|
*
|
|
41
|
-
* **Throws** *{@link
|
|
42
|
-
* **Throws** *{@link
|
|
41
|
+
* **Throws** *{@link SfError}{ name: 'ValidationSchemaFieldError' }* If there are known validations errors.
|
|
42
|
+
* **Throws** *{@link SfError}{ name: 'ValidationSchemaUnknownError' }* If there are unknown validations errors.
|
|
43
43
|
*
|
|
44
44
|
* @param json A JSON value to validate against this instance's target schema.
|
|
45
45
|
* @returns The validated JSON data.
|
package/lib/schema/validator.js
CHANGED
|
@@ -11,7 +11,7 @@ const path = require("path");
|
|
|
11
11
|
const kit_1 = require("@salesforce/kit");
|
|
12
12
|
const ts_types_1 = require("@salesforce/ts-types");
|
|
13
13
|
const validator = require("jsen");
|
|
14
|
-
const
|
|
14
|
+
const sfError_1 = require("../sfError");
|
|
15
15
|
const fs_1 = require("../util/fs");
|
|
16
16
|
/**
|
|
17
17
|
* Loads a JSON schema and performs validations against JSON objects.
|
|
@@ -52,8 +52,8 @@ class SchemaValidator {
|
|
|
52
52
|
* Performs validation of JSON data against the schema located at the `schemaPath` value provided
|
|
53
53
|
* at instantiation.
|
|
54
54
|
*
|
|
55
|
-
* **Throws** *{@link
|
|
56
|
-
* **Throws** *{@link
|
|
55
|
+
* **Throws** *{@link SfError}{ name: 'ValidationSchemaFieldError' }* If there are known validations errors.
|
|
56
|
+
* **Throws** *{@link SfError}{ name: 'ValidationSchemaUnknownError' }* If there are unknown validations errors.
|
|
57
57
|
*
|
|
58
58
|
* @param json A JSON value to validate against this instance's target schema.
|
|
59
59
|
* @returns The validated JSON data.
|
|
@@ -66,8 +66,8 @@ class SchemaValidator {
|
|
|
66
66
|
* Performs validation of JSON data against the schema located at the `schemaPath` value provided
|
|
67
67
|
* at instantiation.
|
|
68
68
|
*
|
|
69
|
-
* **Throws** *{@link
|
|
70
|
-
* **Throws** *{@link
|
|
69
|
+
* **Throws** *{@link SfError}{ name: 'ValidationSchemaFieldError' }* If there are known validations errors.
|
|
70
|
+
* **Throws** *{@link SfError}{ name: 'ValidationSchemaUnknownError' }* If there are unknown validations errors.
|
|
71
71
|
*
|
|
72
72
|
* @param json A JSON value to validate against this instance's target schema.
|
|
73
73
|
* @returns The validated JSON data.
|
|
@@ -85,10 +85,10 @@ class SchemaValidator {
|
|
|
85
85
|
if (!validate(json)) {
|
|
86
86
|
if (validate.errors) {
|
|
87
87
|
const errors = this.getErrorsText(validate.errors, schema);
|
|
88
|
-
throw new
|
|
88
|
+
throw new sfError_1.SfError(`Validation errors:\n${errors}`, 'ValidationSchemaFieldError');
|
|
89
89
|
}
|
|
90
90
|
else {
|
|
91
|
-
throw new
|
|
91
|
+
throw new sfError_1.SfError('Unknown schema validation error', 'ValidationSchemaUnknownError');
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
return validate.build(json);
|
|
@@ -112,7 +112,7 @@ class SchemaValidator {
|
|
|
112
112
|
externalSchemas[externalSchema.id] = externalSchema;
|
|
113
113
|
}
|
|
114
114
|
else {
|
|
115
|
-
throw new
|
|
115
|
+
throw new sfError_1.SfError(`Unexpected external schema id type: ${typeof externalSchema.id}`, 'ValidationSchemaTypeError');
|
|
116
116
|
}
|
|
117
117
|
});
|
|
118
118
|
return externalSchemas;
|
|
@@ -129,7 +129,7 @@ class SchemaValidator {
|
|
|
129
129
|
}
|
|
130
130
|
catch (err) {
|
|
131
131
|
if (err.code === 'ENOENT') {
|
|
132
|
-
throw new
|
|
132
|
+
throw new sfError_1.SfError(`Schema not found: ${schemaPath}`, 'ValidationSchemaNotFound');
|
|
133
133
|
}
|
|
134
134
|
throw err;
|
|
135
135
|
}
|