@salesforce/core 4.0.0-v3.0 → 4.0.1

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.
Files changed (160) hide show
  1. package/LICENSE.txt +1 -1
  2. package/README.md +93 -44
  3. package/lib/config/aliasesConfig.d.ts +12 -0
  4. package/lib/config/aliasesConfig.js +28 -0
  5. package/lib/config/authInfoConfig.d.ts +19 -0
  6. package/lib/config/authInfoConfig.js +35 -0
  7. package/lib/config/config.d.ts +181 -48
  8. package/lib/config/config.js +382 -159
  9. package/lib/config/configAggregator.d.ts +59 -42
  10. package/lib/config/configAggregator.js +135 -82
  11. package/lib/config/configFile.d.ts +2 -2
  12. package/lib/config/configFile.js +40 -31
  13. package/lib/config/configGroup.d.ts +9 -9
  14. package/lib/config/configGroup.js +13 -11
  15. package/lib/config/configStore.d.ts +9 -9
  16. package/lib/config/configStore.js +29 -26
  17. package/lib/config/envVars.d.ts +102 -0
  18. package/lib/config/envVars.js +457 -0
  19. package/lib/config/orgUsersConfig.d.ts +8 -0
  20. package/lib/config/orgUsersConfig.js +12 -0
  21. package/lib/config/sandboxOrgConfig.d.ts +8 -0
  22. package/lib/config/sandboxOrgConfig.js +12 -0
  23. package/lib/config/sandboxProcessCache.d.ts +16 -0
  24. package/lib/config/sandboxProcessCache.js +38 -0
  25. package/lib/config/tokensConfig.d.ts +10 -0
  26. package/lib/config/tokensConfig.js +29 -0
  27. package/lib/config/ttlConfig.d.ts +34 -0
  28. package/lib/config/ttlConfig.js +50 -0
  29. package/lib/crypto/crypto.js +29 -16
  30. package/lib/crypto/keyChain.js +4 -4
  31. package/lib/crypto/keyChainImpl.d.ts +5 -3
  32. package/lib/crypto/keyChainImpl.js +65 -66
  33. package/lib/crypto/secureBuffer.d.ts +1 -1
  34. package/lib/crypto/secureBuffer.js +1 -1
  35. package/lib/deviceOauthService.d.ts +5 -5
  36. package/lib/deviceOauthService.js +37 -33
  37. package/lib/exported.d.ts +22 -15
  38. package/lib/exported.js +49 -25
  39. package/lib/global.d.ts +17 -3
  40. package/lib/global.js +46 -13
  41. package/lib/lifecycleEvents.d.ts +39 -2
  42. package/lib/lifecycleEvents.js +77 -3
  43. package/lib/logger.d.ts +21 -11
  44. package/lib/logger.js +121 -105
  45. package/lib/messages.d.ts +53 -36
  46. package/lib/messages.js +89 -97
  47. package/lib/org/authInfo.d.ts +84 -72
  48. package/lib/org/authInfo.js +326 -320
  49. package/lib/org/authRemover.d.ts +16 -23
  50. package/lib/org/authRemover.js +62 -60
  51. package/lib/org/connection.d.ts +33 -59
  52. package/lib/org/connection.js +129 -190
  53. package/lib/org/index.js +6 -2
  54. package/lib/org/org.d.ts +263 -38
  55. package/lib/org/org.js +734 -149
  56. package/lib/org/orgConfigProperties.d.ts +69 -0
  57. package/lib/org/orgConfigProperties.js +121 -0
  58. package/lib/org/permissionSetAssignment.js +6 -15
  59. package/lib/org/scratchOrgCache.d.ts +20 -0
  60. package/lib/org/scratchOrgCache.js +33 -0
  61. package/lib/org/scratchOrgCreate.d.ts +54 -0
  62. package/lib/org/scratchOrgCreate.js +214 -0
  63. package/lib/org/scratchOrgErrorCodes.d.ts +10 -0
  64. package/lib/org/scratchOrgErrorCodes.js +79 -0
  65. package/lib/org/scratchOrgFeatureDeprecation.d.ts +26 -0
  66. package/lib/org/scratchOrgFeatureDeprecation.js +105 -0
  67. package/lib/org/scratchOrgInfoApi.d.ts +68 -0
  68. package/lib/org/scratchOrgInfoApi.js +416 -0
  69. package/lib/org/scratchOrgInfoGenerator.d.ts +64 -0
  70. package/lib/org/scratchOrgInfoGenerator.js +237 -0
  71. package/lib/org/scratchOrgLifecycleEvents.d.ts +10 -0
  72. package/lib/org/scratchOrgLifecycleEvents.js +41 -0
  73. package/lib/org/scratchOrgSettingsGenerator.d.ts +79 -0
  74. package/lib/org/scratchOrgSettingsGenerator.js +277 -0
  75. package/lib/org/scratchOrgTypes.d.ts +43 -0
  76. package/lib/{status/client.js → org/scratchOrgTypes.js} +1 -1
  77. package/lib/org/user.d.ts +7 -2
  78. package/lib/org/user.js +78 -54
  79. package/lib/schema/printer.d.ts +6 -0
  80. package/lib/schema/printer.js +49 -46
  81. package/lib/schema/validator.d.ts +12 -10
  82. package/lib/schema/validator.js +56 -76
  83. package/lib/{sfdxError.d.ts → sfError.d.ts} +12 -15
  84. package/lib/{sfdxError.js → sfError.js} +42 -24
  85. package/lib/{sfdxProject.d.ts → sfProject.d.ts} +75 -35
  86. package/lib/sfProject.js +651 -0
  87. package/lib/stateAggregator/accessors/aliasAccessor.d.ts +98 -0
  88. package/lib/stateAggregator/accessors/aliasAccessor.js +146 -0
  89. package/lib/stateAggregator/accessors/orgAccessor.d.ts +101 -0
  90. package/lib/stateAggregator/accessors/orgAccessor.js +240 -0
  91. package/lib/stateAggregator/accessors/sandboxAccessor.d.ts +8 -0
  92. package/lib/stateAggregator/accessors/sandboxAccessor.js +28 -0
  93. package/lib/stateAggregator/accessors/tokenAccessor.d.ts +63 -0
  94. package/lib/stateAggregator/accessors/tokenAccessor.js +80 -0
  95. package/lib/stateAggregator/index.d.ts +4 -0
  96. package/lib/stateAggregator/index.js +27 -0
  97. package/lib/stateAggregator/stateAggregator.d.ts +25 -0
  98. package/lib/stateAggregator/stateAggregator.js +46 -0
  99. package/lib/status/myDomainResolver.d.ts +1 -1
  100. package/lib/status/myDomainResolver.js +10 -10
  101. package/lib/status/pollingClient.d.ts +2 -6
  102. package/lib/status/pollingClient.js +38 -64
  103. package/lib/status/streamingClient.d.ts +5 -80
  104. package/lib/status/streamingClient.js +74 -94
  105. package/lib/status/types.d.ts +89 -0
  106. package/lib/status/types.js +18 -0
  107. package/lib/testSetup.d.ts +212 -79
  108. package/lib/testSetup.js +478 -182
  109. package/lib/util/cache.d.ts +11 -0
  110. package/lib/util/cache.js +70 -0
  111. package/lib/util/checkLightningDomain.d.ts +1 -0
  112. package/lib/util/checkLightningDomain.js +29 -0
  113. package/lib/util/directoryWriter.d.ts +12 -0
  114. package/lib/util/directoryWriter.js +54 -0
  115. package/lib/util/getJwtAudienceUrl.d.ts +4 -0
  116. package/lib/util/getJwtAudienceUrl.js +19 -0
  117. package/lib/util/internal.d.ts +28 -2
  118. package/lib/util/internal.js +65 -8
  119. package/lib/util/jsonXmlTools.d.ts +14 -0
  120. package/lib/util/jsonXmlTools.js +39 -0
  121. package/lib/util/mapKeys.d.ts +14 -0
  122. package/lib/util/mapKeys.js +52 -0
  123. package/lib/util/sfdc.d.ts +51 -63
  124. package/lib/util/sfdc.js +75 -127
  125. package/lib/util/sfdcUrl.d.ts +64 -0
  126. package/lib/util/sfdcUrl.js +197 -0
  127. package/lib/util/structuredWriter.d.ts +9 -0
  128. package/lib/util/structuredWriter.js +3 -0
  129. package/lib/util/zipWriter.d.ts +16 -0
  130. package/lib/util/zipWriter.js +68 -0
  131. package/lib/webOAuthServer.d.ts +20 -7
  132. package/lib/webOAuthServer.js +107 -60
  133. package/messageTransformer/messageTransformer.ts +93 -0
  134. package/messages/auth.md +11 -3
  135. package/messages/config.md +94 -6
  136. package/messages/connection.md +8 -0
  137. package/messages/core.json +3 -3
  138. package/messages/core.md +11 -1
  139. package/messages/envVars.md +313 -0
  140. package/messages/org.md +64 -0
  141. package/messages/scratchOrgCreate.md +23 -0
  142. package/messages/scratchOrgErrorCodes.md +115 -0
  143. package/messages/scratchOrgFeatureDeprecation.md +11 -0
  144. package/messages/scratchOrgInfoApi.md +20 -0
  145. package/messages/scratchOrgInfoGenerator.md +27 -0
  146. package/messages/user.md +12 -0
  147. package/package.json +138 -66
  148. package/CHANGELOG.md +0 -699
  149. package/lib/config/aliases.d.ts +0 -56
  150. package/lib/config/aliases.js +0 -96
  151. package/lib/config/globalInfoConfig.d.ts +0 -74
  152. package/lib/config/globalInfoConfig.js +0 -144
  153. package/lib/config/keychainConfig.d.ts +0 -19
  154. package/lib/config/keychainConfig.js +0 -43
  155. package/lib/config/sfdxDataHandler.d.ts +0 -36
  156. package/lib/config/sfdxDataHandler.js +0 -165
  157. package/lib/sfdxProject.js +0 -546
  158. package/lib/status/client.d.ts +0 -15
  159. package/lib/util/fs.d.ts +0 -198
  160. package/lib/util/fs.js +0 -374
@@ -0,0 +1,237 @@
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 sfProject_1 = require("../sfProject");
14
+ const webOAuthServer_1 = require("../webOAuthServer");
15
+ const messages_1 = require("../messages");
16
+ const sfError_1 = require("../sfError");
17
+ const scratchOrgFeatureDeprecation_1 = require("./scratchOrgFeatureDeprecation");
18
+ const authInfo_1 = require("./authInfo");
19
+ const messages = new messages_1.Messages('@salesforce/core', 'scratchOrgInfoGenerator', new Map([["Package2AncestorsIdsKeyNotSupportedError", "The package2AncestorIds key is no longer supported in a scratch org definition. Ancestors defined in sfdx-project.json will be included in the scratch org.\","], ["InvalidAncestorVersionFormatError", "The ancestor versionNumber must be in the format major.minor.patch but the value found is %s\","], ["NoMatchingAncestorError", "The ancestor for ancestorVersion %s can't be found. Package ID %s.\","], ["NoMatchingAncestorIdError", "The ancestor for ancestorId [%s] can't be found. Package ID %s.\""], ["AncestorNotReleasedError", "The ancestor package version [%s] specified in the sfdx-project.json file may exist hasn\u2019t been promoted and released. Release the ancestor package version before specifying it as the ancestor in a new package or patch version.\","], ["AncestorIdVersionMismatchError", "The ancestorVersion in sfdx-project.json is not the version expected for the ancestorId you supplied. ancestorVersion %s. ancestorID %s.\""], ["unsupportedSnapshotOrgCreateOptions", "Org snapshots don\u2019t support one or more options you specified: %s"]]));
20
+ const SNAPSHOT_UNSUPPORTED_OPTIONS = [
21
+ 'features',
22
+ 'orgPreferences',
23
+ 'edition',
24
+ 'sourceOrg',
25
+ 'settingsPath',
26
+ 'releaseVersion',
27
+ 'language',
28
+ ];
29
+ // A validator function to ensure any options parameters entered by the user adhere
30
+ // to a allowlist of valid option settings. Because org:create allows options to be
31
+ // input either key=value pairs or within the definition file, this validator is
32
+ // executed within the ctor and also after parsing/normalization of the definition file.
33
+ const optionsValidator = (key, scratchOrgInfoPayload) => {
34
+ if (key.toLowerCase() === 'durationdays') {
35
+ throw new sfError_1.SfError('unrecognizedScratchOrgOption', 'durationDays');
36
+ }
37
+ if (key.toLowerCase() === 'snapshot') {
38
+ const foundInvalidFields = SNAPSHOT_UNSUPPORTED_OPTIONS.filter((invalidField) => invalidField in scratchOrgInfoPayload);
39
+ if (foundInvalidFields.length > 0) {
40
+ throw new sfError_1.SfError(messages.getMessage('unsupportedSnapshotOrgCreateOptions', [foundInvalidFields.join(', ')]), 'orgSnapshot');
41
+ }
42
+ }
43
+ };
44
+ /**
45
+ * Generates the package2AncestorIds scratch org property
46
+ *
47
+ * @param scratchOrgInfo - the scratchOrgInfo passed in by the user
48
+ * @param projectJson - sfProjectJson
49
+ * @param hubOrg - the hub org, in case we need to do queries
50
+ */
51
+ const getAncestorIds = async (scratchOrgInfo, projectJson, hubOrg) => {
52
+ if (Reflect.has(scratchOrgInfo, 'package2AncestorIds')) {
53
+ throw new sfError_1.SfError(messages.getMessage('Package2AncestorsIdsKeyNotSupportedError'), 'DeprecationError');
54
+ }
55
+ const packagesWithAncestors = (await projectJson.getPackageDirectories())
56
+ // check that the package has any ancestor types (id or version)
57
+ .filter((packageDir) => packageDir.ancestorId ?? packageDir.ancestorVersion);
58
+ if (packagesWithAncestors.length === 0) {
59
+ return '';
60
+ }
61
+ const ancestorIds = await Promise.all(packagesWithAncestors.map(async (packageDir) => {
62
+ // ancestorID can be 05i, or 04t, alias; OR "ancestorVersion": "4.6.0.1"
63
+ // 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
64
+ // package can be an ID, but not according to docs
65
+ const packageAliases = projectJson.get('packageAliases');
66
+ const packageId = packageAliases[(0, ts_types_1.ensureString)(packageDir.package)] ?? packageDir.package;
67
+ // Handle HIGHEST and NONE in ancestor(Version|Id).
68
+ // Precedence chain: NONE -> HIGHEST -> ancestorVersion & ancestoryId
69
+ if (packageDir.ancestorVersion === 'NONE' || packageDir.ancestorId === 'NONE') {
70
+ return '';
71
+ }
72
+ else if (packageDir.ancestorVersion === 'HIGHEST' || packageDir.ancestorId === 'HIGHEST') {
73
+ const query = 'SELECT Id FROM Package2Version ' +
74
+ `WHERE Package2Id = '${packageId}' AND IsReleased = True AND IsDeprecated = False AND PatchVersion = 0 ` +
75
+ 'ORDER BY MajorVersion Desc, MinorVersion Desc, PatchVersion Desc, BuildNumber Desc LIMIT 1';
76
+ try {
77
+ return (await hubOrg.getConnection().singleRecordQuery(query, { tooling: true })).Id;
78
+ }
79
+ catch (err) {
80
+ if (packageDir.ancestorVersion === 'HIGHEST') {
81
+ throw new sfError_1.SfError(messages.getMessage('NoMatchingAncestorError', [packageDir.ancestorVersion, packageDir.package]), 'NoMatchingAncestorError', [messages.getMessage('AncestorNotReleasedError', [packageDir.ancestorVersion])]);
82
+ }
83
+ else {
84
+ throw new sfError_1.SfError(messages.getMessage('NoMatchingAncestorIdError', [packageDir.ancestorId, packageDir.package]), 'NoMatchingAncestorIdError', [messages.getMessage('AncestorNotReleasedError', [packageDir.ancestorId])]);
85
+ }
86
+ }
87
+ }
88
+ if (packageDir.ancestorVersion) {
89
+ if (!/^[0-9]+.[0-9]+.[0-9]+(.[0-9]+)?$/.test(packageDir.ancestorVersion)) {
90
+ throw messages.createError('InvalidAncestorVersionFormatError', [packageDir.ancestorVersion]);
91
+ }
92
+ const [major, minor, patch] = packageDir.ancestorVersion.split('.');
93
+ let releasedAncestor;
94
+ try {
95
+ releasedAncestor = await hubOrg
96
+ .getConnection()
97
+ .singleRecordQuery(`SELECT Id, IsReleased FROM Package2Version WHERE Package2Id = '${packageId}' AND MajorVersion = ${major} AND MinorVersion = ${minor} AND PatchVersion = ${patch} and IsReleased = true`, { tooling: true });
98
+ }
99
+ catch (err) {
100
+ throw new sfError_1.SfError(messages.getMessage('NoMatchingAncestorError', [packageDir.ancestorVersion, packageDir.package]), 'NoMatchingAncestorError', [messages.getMessage('AncestorNotReleasedError', [packageDir.ancestorVersion])]);
101
+ }
102
+ if (packageDir.ancestorId && packageDir.ancestorId !== releasedAncestor.Id) {
103
+ throw messages.createError('AncestorIdVersionMismatchError', [
104
+ packageDir.ancestorVersion,
105
+ packageDir.ancestorId,
106
+ ]);
107
+ }
108
+ return releasedAncestor.Id;
109
+ }
110
+ if (packageDir?.ancestorId?.startsWith('05i')) {
111
+ // if it's already a 05i return it, otherwise query for it
112
+ return packageDir.ancestorId;
113
+ }
114
+ if (packageDir?.ancestorId?.startsWith('04t')) {
115
+ // query for the Id
116
+ return (await hubOrg
117
+ .getConnection()
118
+ .singleRecordQuery(`SELECT Id FROM Package2Version WHERE SubscriberPackageVersionId = '${packageDir.ancestorId}'`, { tooling: true })).Id;
119
+ }
120
+ // ancestorID can be an alias; get it from projectJson
121
+ if (packageDir.ancestorId && packageAliases?.[packageDir.ancestorId]) {
122
+ return packageAliases[packageDir.ancestorId];
123
+ }
124
+ throw new sfError_1.SfError(`Invalid ancestorId ${packageDir.ancestorId}`, 'InvalidAncestorId');
125
+ }));
126
+ // strip out '' due to NONE
127
+ return Array.from(new Set(ancestorIds.filter((id) => id !== ''))).join(';');
128
+ };
129
+ exports.getAncestorIds = getAncestorIds;
130
+ /**
131
+ * Takes in a scratchOrgInfo and fills in the missing fields
132
+ *
133
+ * @param hubOrg the environment hub org
134
+ * @param scratchOrgInfoPayload - the scratchOrgInfo passed in by the user
135
+ * @param nonamespace create the scratch org with no namespace
136
+ * @param ignoreAncestorIds true if the sfdx-project.json ancestorId keys should be ignored
137
+ */
138
+ const generateScratchOrgInfo = async ({ hubOrg, scratchOrgInfoPayload, nonamespace, ignoreAncestorIds, }) => {
139
+ let sfProject;
140
+ try {
141
+ sfProject = await sfProject_1.SfProjectJson.create({});
142
+ }
143
+ catch (e) {
144
+ // project is not required
145
+ }
146
+ scratchOrgInfoPayload.orgName = scratchOrgInfoPayload.orgName ?? 'Company';
147
+ scratchOrgInfoPayload.package2AncestorIds =
148
+ !ignoreAncestorIds && sfProject?.hasPackages()
149
+ ? await (0, exports.getAncestorIds)(scratchOrgInfoPayload, sfProject, hubOrg)
150
+ : '';
151
+ // Use the Hub org's client ID value, if one wasn't provided to us, or the default
152
+ if (!scratchOrgInfoPayload.connectedAppConsumerKey) {
153
+ scratchOrgInfoPayload.connectedAppConsumerKey =
154
+ hubOrg.getConnection().getAuthInfoFields().clientId ?? authInfo_1.DEFAULT_CONNECTED_APP_INFO.clientId;
155
+ }
156
+ if (!nonamespace && sfProject?.get('namespace')) {
157
+ scratchOrgInfoPayload.namespace = sfProject.get('namespace');
158
+ }
159
+ // we already have the info, and want to get rid of configApi, so this doesn't use that
160
+ scratchOrgInfoPayload.connectedAppCallbackUrl = `http://localhost:${await webOAuthServer_1.WebOAuthServer.determineOauthPort()}/OauthRedirect`;
161
+ return scratchOrgInfoPayload;
162
+ };
163
+ exports.generateScratchOrgInfo = generateScratchOrgInfo;
164
+ /**
165
+ * Returns a valid signup json
166
+ *
167
+ * definitionjson org definition in JSON format
168
+ * definitionfile path to an org definition file
169
+ * connectedAppConsumerKey The connected app consumer key. May be null for JWT OAuth flow.
170
+ * durationdays duration of the scratch org (in days) (default:1, min:1, max:30)
171
+ * nonamespace create the scratch org with no namespace
172
+ * noancestors do not include second-generation package ancestors in the scratch org
173
+ * orgConfig overrides definitionjson
174
+ *
175
+ * @returns scratchOrgInfoPayload: ScratchOrgInfoPayload;
176
+ ignoreAncestorIds: boolean;
177
+ warnings: string[];
178
+ */
179
+ const getScratchOrgInfoPayload = async (options) => {
180
+ let warnings = [];
181
+ // orgConfig input overrides definitionjson (-j option; hidden/deprecated) overrides definitionfile (-f option)
182
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
183
+ const scratchOrgInfoPayload = {
184
+ ...(options.definitionfile ? await parseDefinitionFile(options.definitionfile) : {}),
185
+ ...(options.definitionjson ? JSON.parse(options.definitionjson) : {}),
186
+ ...(options.orgConfig ?? {}),
187
+ };
188
+ // scratchOrgInfoPayload must be heads down camelcase.
189
+ Object.keys(scratchOrgInfoPayload).forEach((key) => {
190
+ if (key[0].toUpperCase() === key[0]) {
191
+ throw new sfError_1.SfError('InvalidJsonCasing', key);
192
+ }
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
+ const parseDefinitionFile = async (definitionFile) => {
224
+ try {
225
+ const fileData = await fs_1.promises.readFile(definitionFile, 'utf8');
226
+ const defFileContents = (0, kit_1.parseJson)(fileData);
227
+ return defFileContents;
228
+ }
229
+ catch (err) {
230
+ const error = err;
231
+ if (error.name === 'JsonParseError') {
232
+ throw new sfError_1.SfError(`An error occurred parsing ${definitionFile}`);
233
+ }
234
+ throw sfError_1.SfError.wrap(error);
235
+ }
236
+ };
237
+ //# sourceMappingURL=scratchOrgInfoGenerator.js.map
@@ -0,0 +1,10 @@
1
+ import { AuthFields } from './authInfo';
2
+ import { ScratchOrgInfo } from './scratchOrgTypes';
3
+ export declare const scratchOrgLifecycleEventName = "scratchOrgLifecycleEvent";
4
+ export declare const scratchOrgLifecycleStages: readonly ["prepare request", "send request", "wait for org", "available", "authenticate", "deploy settings", "done"];
5
+ export interface ScratchOrgLifecycleEvent {
6
+ stage: typeof scratchOrgLifecycleStages[number];
7
+ scratchOrgInfo?: ScratchOrgInfo;
8
+ }
9
+ export declare const emit: (event: ScratchOrgLifecycleEvent) => Promise<void>;
10
+ export declare const emitPostOrgCreate: (authFields: AuthFields) => Promise<void>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emitPostOrgCreate = exports.emit = exports.scratchOrgLifecycleStages = exports.scratchOrgLifecycleEventName = void 0;
4
+ /*
5
+ * Copyright (c) 2020, 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 lifecycleEvents_1 = require("../lifecycleEvents");
11
+ const emitter = lifecycleEvents_1.Lifecycle.getInstance();
12
+ exports.scratchOrgLifecycleEventName = 'scratchOrgLifecycleEvent';
13
+ exports.scratchOrgLifecycleStages = [
14
+ 'prepare request',
15
+ 'send request',
16
+ 'wait for org',
17
+ 'available',
18
+ 'authenticate',
19
+ 'deploy settings',
20
+ 'done',
21
+ ];
22
+ const emit = async (event) => emitter.emit(exports.scratchOrgLifecycleEventName, event);
23
+ exports.emit = emit;
24
+ const postOrgCreateHookFields = [
25
+ 'accessToken',
26
+ 'clientId',
27
+ 'created',
28
+ 'createdOrgInstance',
29
+ 'devHubUsername',
30
+ 'expirationDate',
31
+ 'instanceUrl',
32
+ 'loginUrl',
33
+ 'orgId',
34
+ 'username',
35
+ ];
36
+ const isHookField = (key) => postOrgCreateHookFields.includes(key);
37
+ const emitPostOrgCreate = async (authFields) => {
38
+ await emitter.emit('postorgcreate', Object.fromEntries(Object.entries(authFields).filter(([key]) => isHookField(key))));
39
+ };
40
+ exports.emitPostOrgCreate = emitPostOrgCreate;
41
+ //# sourceMappingURL=scratchOrgLifecycleEvents.js.map
@@ -0,0 +1,79 @@
1
+ import { Duration } from '@salesforce/kit';
2
+ import { JsonMap } from '@salesforce/ts-types';
3
+ import { ScratchOrgInfo, ObjectSetting } from './scratchOrgTypes';
4
+ import { Org } from './org';
5
+ export declare enum RequestStatus {
6
+ Pending = "Pending",
7
+ InProgress = "InProgress",
8
+ Succeeded = "Succeeded",
9
+ SucceededPartial = "SucceededPartial",
10
+ Failed = "Failed",
11
+ Canceling = "Canceling",
12
+ Canceled = "Canceled"
13
+ }
14
+ export interface SettingType {
15
+ members: string[];
16
+ name: 'CustomObject' | 'RecordType' | 'BusinessProcess' | 'Settings';
17
+ }
18
+ export interface PackageFile {
19
+ '@': {
20
+ xmlns: string;
21
+ };
22
+ types: SettingType[];
23
+ version: string;
24
+ }
25
+ export declare const createObjectFileContent: ({ allRecordTypes, allBusinessProcesses, apiVersion, settingData, objectSettingsData, }: {
26
+ allRecordTypes?: string[] | undefined;
27
+ allBusinessProcesses?: string[] | undefined;
28
+ apiVersion: string;
29
+ settingData?: Record<string, unknown> | undefined;
30
+ objectSettingsData?: {
31
+ [objectName: string]: ObjectSetting;
32
+ } | undefined;
33
+ }) => PackageFile;
34
+ export declare const createRecordTypeAndBusinessProcessFileContent: (objectName: string, json: Record<string, unknown>, allRecordTypes: string[], allBusinessProcesses: string[]) => JsonMap;
35
+ /**
36
+ * Helper class for dealing with the settings that are defined in a scratch definition file. This class knows how to extract the
37
+ * settings from the definition, how to expand them into a MD directory and how to generate a package.xml.
38
+ */
39
+ export default class SettingsGenerator {
40
+ private settingData?;
41
+ private objectSettingsData?;
42
+ private logger;
43
+ private writer;
44
+ private allRecordTypes;
45
+ private allBusinessProcesses;
46
+ private readonly shapeDirName;
47
+ private readonly packageFilePath;
48
+ constructor(options?: {
49
+ mdApiTmpDir?: string;
50
+ shapeDirName?: string;
51
+ asDirectory?: boolean;
52
+ });
53
+ /** extract the settings from the scratch def file, if they are present. */
54
+ extract(scratchDef: ScratchOrgInfo): Promise<{
55
+ settings: Record<string, unknown> | undefined;
56
+ objectSettings: {
57
+ [objectName: string]: ObjectSetting;
58
+ } | undefined;
59
+ }>;
60
+ /** True if we are currently tracking setting or object setting data. */
61
+ hasSettings(): boolean;
62
+ /** Create temporary deploy directory used to upload the scratch org shape.
63
+ * This will create the dir, all of the .setting files and minimal object files needed for objectSettings
64
+ */
65
+ createDeploy(): Promise<void>;
66
+ /**
67
+ * Deploys the settings to the org.
68
+ */
69
+ deploySettingsViaFolder(scratchOrg: Org, apiVersion: string, timeout?: Duration): Promise<void>;
70
+ createDeployPackageContents(apiVersion: string): Promise<void>;
71
+ getShapeDirName(): string;
72
+ /**
73
+ * Returns the destination where the writer placed the settings content.
74
+ *
75
+ */
76
+ getDestinationPath(): string | undefined;
77
+ private writeObjectSettingsIfNeeded;
78
+ private writeSettingsIfNeeded;
79
+ }
@@ -0,0 +1,277 @@
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.createRecordTypeAndBusinessProcessFileContent = exports.createObjectFileContent = 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 pollingClient_1 = require("../status/pollingClient");
17
+ const zipWriter_1 = require("../util/zipWriter");
18
+ const directoryWriter_1 = require("../util/directoryWriter");
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
+ const createObjectFileContent = ({ allRecordTypes = [], allBusinessProcesses = [], apiVersion, settingData, objectSettingsData, }) => {
31
+ const output = {
32
+ '@': {
33
+ xmlns: 'http://soap.sforce.com/2006/04/metadata',
34
+ },
35
+ types: [],
36
+ };
37
+ if (settingData) {
38
+ const strings = Object.keys(settingData).map((item) => (0, kit_1.upperFirst)(item).replace('Settings', ''));
39
+ output.types.push({ members: strings, name: 'Settings' });
40
+ }
41
+ if (objectSettingsData) {
42
+ const strings = Object.keys(objectSettingsData).map((item) => (0, kit_1.upperFirst)(item));
43
+ output.types.push({ members: strings, name: 'CustomObject' });
44
+ if (allRecordTypes.length > 0) {
45
+ output.types.push({ members: allRecordTypes, name: 'RecordType' });
46
+ }
47
+ if (allBusinessProcesses.length > 0) {
48
+ output.types.push({ members: allBusinessProcesses, name: 'BusinessProcess' });
49
+ }
50
+ }
51
+ return { ...output, ...{ version: apiVersion } };
52
+ };
53
+ exports.createObjectFileContent = createObjectFileContent;
54
+ const calculateBusinessProcess = (objectName, defaultRecordType) => {
55
+ let businessProcessName = null;
56
+ let businessProcessPicklistVal = null;
57
+ // These four objects require any record type to specify a "business process"--
58
+ // a restricted set of items from a standard picklist on the object.
59
+ if (['Case', 'Lead', 'Opportunity', 'Solution'].includes(objectName)) {
60
+ businessProcessName = (0, kit_1.upperFirst)(defaultRecordType) + 'Process';
61
+ switch (objectName) {
62
+ case 'Case':
63
+ businessProcessPicklistVal = 'New';
64
+ break;
65
+ case 'Lead':
66
+ businessProcessPicklistVal = 'New - Not Contacted';
67
+ break;
68
+ case 'Opportunity':
69
+ businessProcessPicklistVal = 'Prospecting';
70
+ break;
71
+ case 'Solution':
72
+ businessProcessPicklistVal = 'Draft';
73
+ }
74
+ }
75
+ return [businessProcessName, businessProcessPicklistVal];
76
+ };
77
+ const createRecordTypeAndBusinessProcessFileContent = (objectName, json, allRecordTypes, allBusinessProcesses) => {
78
+ let output = {
79
+ '@': {
80
+ xmlns: 'http://soap.sforce.com/2006/04/metadata',
81
+ },
82
+ };
83
+ const name = (0, kit_1.upperFirst)(objectName);
84
+ const sharingModel = json.sharingModel;
85
+ if (sharingModel) {
86
+ output = {
87
+ ...output,
88
+ sharingModel: (0, kit_1.upperFirst)(sharingModel),
89
+ };
90
+ }
91
+ const defaultRecordType = json.defaultRecordType;
92
+ if (typeof defaultRecordType === 'string') {
93
+ // We need to keep track of these globally for when we generate the package XML.
94
+ allRecordTypes.push(`${name}.${(0, kit_1.upperFirst)(defaultRecordType)}`);
95
+ const [businessProcessName, businessProcessPicklistVal] = calculateBusinessProcess(name, defaultRecordType);
96
+ // Create the record type
97
+ const recordTypes = {
98
+ fullName: (0, kit_1.upperFirst)(defaultRecordType),
99
+ label: (0, kit_1.upperFirst)(defaultRecordType),
100
+ active: true,
101
+ };
102
+ output = {
103
+ ...output,
104
+ recordTypes: {
105
+ ...recordTypes,
106
+ },
107
+ };
108
+ if (businessProcessName) {
109
+ // We need to keep track of these globally for the package.xml
110
+ const values = {
111
+ fullName: businessProcessPicklistVal,
112
+ };
113
+ if (name !== 'Opportunity') {
114
+ values.default = true;
115
+ }
116
+ allBusinessProcesses.push(`${name}.${businessProcessName}`);
117
+ output = {
118
+ ...output,
119
+ recordTypes: {
120
+ ...recordTypes,
121
+ businessProcess: businessProcessName,
122
+ },
123
+ businessProcesses: {
124
+ fullName: businessProcessName,
125
+ isActive: true,
126
+ values,
127
+ },
128
+ };
129
+ }
130
+ }
131
+ return output;
132
+ };
133
+ exports.createRecordTypeAndBusinessProcessFileContent = createRecordTypeAndBusinessProcessFileContent;
134
+ /**
135
+ * Helper class for dealing with the settings that are defined in a scratch definition file. This class knows how to extract the
136
+ * settings from the definition, how to expand them into a MD directory and how to generate a package.xml.
137
+ */
138
+ class SettingsGenerator {
139
+ constructor(options) {
140
+ this.allRecordTypes = [];
141
+ this.allBusinessProcesses = [];
142
+ this.logger = logger_1.Logger.childFromRoot('SettingsGenerator');
143
+ // If SFDX_MDAPI_TEMP_DIR is set, copy settings to that dir for people to inspect.
144
+ const mdApiTmpDir = options?.mdApiTmpDir ?? kit_1.env.getString('SFDX_MDAPI_TEMP_DIR');
145
+ this.shapeDirName = options?.shapeDirName ?? `shape_${Date.now()}`;
146
+ this.packageFilePath = path.join(this.shapeDirName, 'package.xml');
147
+ let storePath;
148
+ if (!options?.asDirectory) {
149
+ storePath = mdApiTmpDir ? path.join(mdApiTmpDir, `${this.shapeDirName}.zip`) : undefined;
150
+ this.writer = new zipWriter_1.ZipWriter(storePath);
151
+ }
152
+ else {
153
+ storePath = mdApiTmpDir ? path.join(mdApiTmpDir, this.shapeDirName) : undefined;
154
+ this.writer = new directoryWriter_1.DirectoryWriter(storePath);
155
+ }
156
+ }
157
+ /** extract the settings from the scratch def file, if they are present. */
158
+ // eslint-disable-next-line @typescript-eslint/require-await
159
+ async extract(scratchDef) {
160
+ this.logger.debug('extracting settings from scratch definition file');
161
+ this.settingData = scratchDef.settings;
162
+ this.objectSettingsData = scratchDef.objectSettings;
163
+ this.logger.debug('settings are', this.settingData);
164
+ return { settings: this.settingData, objectSettings: this.objectSettingsData };
165
+ }
166
+ /** True if we are currently tracking setting or object setting data. */
167
+ hasSettings() {
168
+ return !(0, kit_1.isEmpty)(this.settingData) || !(0, kit_1.isEmpty)(this.objectSettingsData);
169
+ }
170
+ /** Create temporary deploy directory used to upload the scratch org shape.
171
+ * This will create the dir, all of the .setting files and minimal object files needed for objectSettings
172
+ */
173
+ async createDeploy() {
174
+ const settingsDir = path.join(this.shapeDirName, 'settings');
175
+ const objectsDir = path.join(this.shapeDirName, 'objects');
176
+ await Promise.all([
177
+ this.writeSettingsIfNeeded(settingsDir),
178
+ this.writeObjectSettingsIfNeeded(objectsDir, this.allRecordTypes, this.allBusinessProcesses),
179
+ ]);
180
+ }
181
+ /**
182
+ * Deploys the settings to the org.
183
+ */
184
+ async deploySettingsViaFolder(scratchOrg, apiVersion, timeout = kit_1.Duration.minutes(10)) {
185
+ const username = scratchOrg.getUsername();
186
+ const logger = await logger_1.Logger.child('deploySettingsViaFolder');
187
+ await this.createDeployPackageContents(apiVersion);
188
+ const connection = scratchOrg.getConnection();
189
+ logger.debug(`deploying to apiVersion: ${apiVersion}`);
190
+ connection.setApiVersion(apiVersion);
191
+ const { id } = await connection.deploy(this.writer.buffer, {});
192
+ logger.debug(`deploying settings id ${id}`);
193
+ let result = await connection.metadata.checkDeployStatus(id);
194
+ const pollingOptions = {
195
+ async poll() {
196
+ try {
197
+ result = await connection.metadata.checkDeployStatus(id, true);
198
+ logger.debug(`Deploy id: ${id} status: ${result.status}`);
199
+ if (breakPolling.includes(result.status)) {
200
+ return {
201
+ completed: true,
202
+ payload: result.status,
203
+ };
204
+ }
205
+ return {
206
+ completed: false,
207
+ };
208
+ }
209
+ catch (error) {
210
+ logger.debug(`An error occurred trying to check deploy id: ${id}`);
211
+ logger.debug(`Error: ${error.message}`);
212
+ logger.debug('Re-trying deploy check again....');
213
+ return {
214
+ completed: false,
215
+ };
216
+ }
217
+ },
218
+ timeout,
219
+ frequency: kit_1.Duration.seconds(1),
220
+ timeoutErrorName: 'DeployingSettingsTimeoutError',
221
+ };
222
+ const client = await pollingClient_1.PollingClient.create(pollingOptions);
223
+ const status = await client.subscribe();
224
+ if (status !== RequestStatus.Succeeded) {
225
+ const componentFailures = (0, ts_types_1.ensureObject)(result.details).componentFailures;
226
+ const failures = (Array.isArray(componentFailures) ? componentFailures : [componentFailures])
227
+ .map((failure) => failure.problem)
228
+ .join('\n');
229
+ 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');
230
+ error.setData(result);
231
+ throw error;
232
+ }
233
+ }
234
+ async createDeployPackageContents(apiVersion) {
235
+ const packageObjectProps = (0, exports.createObjectFileContent)({
236
+ allRecordTypes: this.allRecordTypes,
237
+ allBusinessProcesses: this.allBusinessProcesses,
238
+ apiVersion,
239
+ settingData: this.settingData,
240
+ objectSettingsData: this.objectSettingsData,
241
+ });
242
+ const xml = js2xmlparser.parse('Package', packageObjectProps);
243
+ await this.writer.addToStore(xml, this.packageFilePath);
244
+ await this.writer.finalize();
245
+ }
246
+ getShapeDirName() {
247
+ return this.shapeDirName;
248
+ }
249
+ /**
250
+ * Returns the destination where the writer placed the settings content.
251
+ *
252
+ */
253
+ getDestinationPath() {
254
+ return this.writer.getDestinationPath();
255
+ }
256
+ async writeObjectSettingsIfNeeded(objectsDir, allRecordTypes, allbusinessProcesses) {
257
+ if (this.objectSettingsData) {
258
+ await Promise.all(Object.entries(this.objectSettingsData).map(([item, value]) => {
259
+ const fileContent = (0, exports.createRecordTypeAndBusinessProcessFileContent)(item, value, allRecordTypes, allbusinessProcesses);
260
+ const xml = js2xmlparser.parse('CustomObject', fileContent);
261
+ return this.writer.addToStore(xml, path.join(objectsDir, (0, kit_1.upperFirst)(item) + '.object'));
262
+ }));
263
+ }
264
+ }
265
+ async writeSettingsIfNeeded(settingsDir) {
266
+ if (this.settingData) {
267
+ await Promise.all(Object.entries(this.settingData).map(([item, value]) => {
268
+ const typeName = (0, kit_1.upperFirst)(item);
269
+ const fname = typeName.replace('Settings', '');
270
+ const fileContent = js2xmlparser.parse(typeName, value);
271
+ return this.writer.addToStore(fileContent, path.join(settingsDir, fname + '.settings'));
272
+ }));
273
+ }
274
+ }
275
+ }
276
+ exports.default = SettingsGenerator;
277
+ //# sourceMappingURL=scratchOrgSettingsGenerator.js.map