@salesforce/core 8.17.0 → 8.18.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.
@@ -259,6 +259,8 @@ export declare class AuthInfo extends AsyncOptionalCreatable<AuthInfo.Options> {
259
259
  getFields(decrypt?: boolean): Readonly<AuthFields>;
260
260
  /**
261
261
  * Get the org front door (used for web based oauth flows)
262
+ *
263
+ * @deprecated Will be removed in the next major version. Use the `Org.getFrontDoorUrl()` method instead.
262
264
  */
263
265
  getOrgFrontDoorUrl(): string;
264
266
  /**
@@ -545,6 +545,8 @@ class AuthInfo extends kit_1.AsyncOptionalCreatable {
545
545
  }
546
546
  /**
547
547
  * Get the org front door (used for web based oauth flows)
548
+ *
549
+ * @deprecated Will be removed in the next major version. Use the `Org.getFrontDoorUrl()` method instead.
548
550
  */
549
551
  getOrgFrontDoorUrl() {
550
552
  const authFields = this.getFields(true);
package/lib/org/org.d.ts CHANGED
@@ -152,6 +152,39 @@ export declare class Org extends AsyncOptionalCreatable<Org.Options> {
152
152
  * @ignore
153
153
  */
154
154
  constructor(options?: Org.Options);
155
+ /**
156
+ * Generate a URL to a metadata UI builder/setup section in an org.
157
+ *
158
+ * Bot: open in Agentforce Builder
159
+ * ApexPage: opens page
160
+ * Flow: open in Flow Builder
161
+ * FlexiPage: open in Lightning App Builder
162
+ * CustomObject: open in Object Manager
163
+ * ApexClass: open in Setup -> Apex Classes UI
164
+ *
165
+ * if you pass any other metadata type you'll get a path to Lightning App Builder
166
+ *
167
+ * @example
168
+ * // use SDR resolver:
169
+ * import { MetadataResolver } from '@salesforce/source-deploy-retrieve';
170
+ *
171
+ * const metadataResolver = new MetadataResolver();
172
+ * const components = metadataResolver.getComponentsFromPath(filePath);
173
+ * const typeName = components[0]?.type?.name;
174
+ *
175
+ * const metadataBuilderUrl = await org.getMetadataUIURL(typeName, filePath);
176
+ *
177
+ * @typeName Bot | ApexPage | Flow | FlexiPage | CustomObject | ApexClass
178
+ * @file Absolute file path to the metadata file
179
+ */
180
+ getMetadataUIURL(typeName: string, file: string): Promise<string>;
181
+ /**
182
+ * Get a Frontdoor URL
183
+ *
184
+ * This uses the UI Bridge API to generate a single-use Frontdoor URL:
185
+ * https://help.salesforce.com/s/articleView?id=xcloud.frontdoor_singleaccess.htm&type=5
186
+ */
187
+ getFrontDoorUrl(redirectUri?: string): Promise<string>;
155
188
  /**
156
189
  * create a sandbox from a production org
157
190
  * 'this' needs to be a production org with sandbox licenses available
package/lib/org/org.js CHANGED
@@ -29,10 +29,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
29
29
  __setModuleDefault(result, mod);
30
30
  return result;
31
31
  };
32
+ var __importDefault = (this && this.__importDefault) || function (mod) {
33
+ return (mod && mod.__esModule) ? mod : { "default": mod };
34
+ };
32
35
  Object.defineProperty(exports, "__esModule", { value: true });
33
36
  exports.Org = exports.SandboxEvents = exports.OrgTypes = void 0;
34
37
  exports.sandboxIsResumable = sandboxIsResumable;
35
- const node_path_1 = require("node:path");
38
+ const node_path_1 = __importDefault(require("node:path"));
36
39
  const fs = __importStar(require("node:fs"));
37
40
  const kit_1 = require("@salesforce/kit");
38
41
  const ts_types_1 = require("@salesforce/ts-types");
@@ -53,7 +56,7 @@ const authInfo_1 = require("./authInfo");
53
56
  const scratchOrgCreate_1 = require("./scratchOrgCreate");
54
57
  const orgConfigProperties_1 = require("./orgConfigProperties");
55
58
  ;
56
- const messages = new messages_1.Messages('@salesforce/core', 'org', new Map([["notADevHub", "The provided dev hub username %s is not a valid dev hub."], ["noUsernameFound", "No username found."], ["noDevHubFound", "Unable to associate this scratch org with a DevHub."], ["deleteOrgHubError", "The Dev Hub org cannot be deleted."], ["insufficientAccessToDelete", "You do not have the appropriate permissions to delete a scratch org. Please contact your Salesforce admin."], ["scratchOrgNotFound", "Attempting to delete an expired or deleted org"], ["sandboxDeleteFailed", "The sandbox org deletion failed with a result of %s."], ["sandboxNotFound", "We can't find a SandboxProcess for the sandbox %s."], ["sandboxInfoCreateFailed", "The sandbox org creation failed with a result of %s."], ["sandboxInfoRefreshFailed", "The sandbox org refresh failed with a result of %s."], ["missingAuthUsername", "The sandbox %s does not have an authorized username."], ["orgPollingTimeout", "Sandbox status is %s; timed out waiting for completion."], ["NotFoundOnDevHub", "The scratch org does not belong to the dev hub username %s."], ["AuthInfoOrgIdUndefined", "AuthInfo orgId is undefined."], ["sandboxCreateNotComplete", "The sandbox creation has not completed."], ["SandboxProcessNotFoundBySandboxName", "We can't find a SandboxProcess with the SandboxName %s."], ["MultiSandboxProcessNotFoundBySandboxName", "We found more than one SandboxProcess with the SandboxName %s."], ["sandboxNotResumable", "The sandbox %s cannot resume with status of %s."]]));
59
+ const messages = new messages_1.Messages('@salesforce/core', 'org', new Map([["notADevHub", "The provided dev hub username %s is not a valid dev hub."], ["noUsernameFound", "No username found."], ["noDevHubFound", "Unable to associate this scratch org with a DevHub."], ["deleteOrgHubError", "The Dev Hub org cannot be deleted."], ["insufficientAccessToDelete", "You do not have the appropriate permissions to delete a scratch org. Please contact your Salesforce admin."], ["scratchOrgNotFound", "Attempting to delete an expired or deleted org"], ["sandboxDeleteFailed", "The sandbox org deletion failed with a result of %s."], ["sandboxNotFound", "We can't find a SandboxProcess for the sandbox %s."], ["sandboxInfoCreateFailed", "The sandbox org creation failed with a result of %s."], ["sandboxInfoRefreshFailed", "The sandbox org refresh failed with a result of %s."], ["missingAuthUsername", "The sandbox %s does not have an authorized username."], ["orgPollingTimeout", "Sandbox status is %s; timed out waiting for completion."], ["NotFoundOnDevHub", "The scratch org does not belong to the dev hub username %s."], ["AuthInfoOrgIdUndefined", "AuthInfo orgId is undefined."], ["sandboxCreateNotComplete", "The sandbox creation has not completed."], ["SandboxProcessNotFoundBySandboxName", "We can't find a SandboxProcess with the SandboxName %s."], ["MultiSandboxProcessNotFoundBySandboxName", "We found more than one SandboxProcess with the SandboxName %s."], ["sandboxNotResumable", "The sandbox %s cannot resume with status of %s."], ["FrontdoorURLError", "Failed to generate a frontdoor URL."], ["FlowIdNotFound", "ID not found for Flow %s."], ["CustomObjectIdNotFound", "ID not found for custom object %s."], ["ApexClassIdNotFound", "ID not found for Apex class %s."]]));
57
60
  var OrgTypes;
58
61
  (function (OrgTypes) {
59
62
  OrgTypes["Scratch"] = "scratch";
@@ -146,6 +149,111 @@ class Org extends kit_1.AsyncOptionalCreatable {
146
149
  super(options);
147
150
  this.options = options ?? {};
148
151
  }
152
+ /**
153
+ * Generate a URL to a metadata UI builder/setup section in an org.
154
+ *
155
+ * Bot: open in Agentforce Builder
156
+ * ApexPage: opens page
157
+ * Flow: open in Flow Builder
158
+ * FlexiPage: open in Lightning App Builder
159
+ * CustomObject: open in Object Manager
160
+ * ApexClass: open in Setup -> Apex Classes UI
161
+ *
162
+ * if you pass any other metadata type you'll get a path to Lightning App Builder
163
+ *
164
+ * @example
165
+ * // use SDR resolver:
166
+ * import { MetadataResolver } from '@salesforce/source-deploy-retrieve';
167
+ *
168
+ * const metadataResolver = new MetadataResolver();
169
+ * const components = metadataResolver.getComponentsFromPath(filePath);
170
+ * const typeName = components[0]?.type?.name;
171
+ *
172
+ * const metadataBuilderUrl = await org.getMetadataUIURL(typeName, filePath);
173
+ *
174
+ * @typeName Bot | ApexPage | Flow | FlexiPage | CustomObject | ApexClass
175
+ * @file Absolute file path to the metadata file
176
+ */
177
+ async getMetadataUIURL(typeName, file) {
178
+ const botFileNameToId = async (conn, filePath) => (await conn.singleRecordQuery(`SELECT id FROM BotDefinition WHERE DeveloperName='${node_path_1.default.basename(filePath, '.bot-meta.xml')}'`)).Id;
179
+ /** query flexipage via toolingAPI to get its ID (starts with 0M0) */
180
+ const flexiPageFilenameToId = async (conn, filePath) => (await conn.singleRecordQuery(`SELECT id FROM flexipage WHERE DeveloperName='${node_path_1.default.basename(filePath, '.flexipage-meta.xml')}'`, { tooling: true })).Id;
181
+ /** query the rest API to turn a flow's filepath into a FlowId (starts with 301) */
182
+ const flowFileNameToId = async (conn, filePath) => {
183
+ try {
184
+ const flow = await conn.singleRecordQuery(`SELECT DurableId FROM FlowVersionView WHERE FlowDefinitionView.ApiName = '${node_path_1.default.basename(filePath, '.flow-meta.xml')}' ORDER BY VersionNumber DESC LIMIT 1`);
185
+ return flow.DurableId;
186
+ }
187
+ catch (error) {
188
+ throw messages.createError('FlowIdNotFound', [filePath]);
189
+ }
190
+ };
191
+ const customObjectFileNameToId = async (conn, filePath) => {
192
+ try {
193
+ const customObject = await conn.singleRecordQuery(`SELECT Id FROM CustomObject WHERE DeveloperName = '${node_path_1.default.basename(filePath.replace(/__c/g, ''), '.object-meta.xml')}'`, {
194
+ tooling: true,
195
+ });
196
+ return customObject.Id;
197
+ }
198
+ catch (error) {
199
+ throw messages.createError('CustomObjectIdNotFound', [filePath]);
200
+ }
201
+ };
202
+ const apexClassFileNameToId = async (conn, filePath) => {
203
+ try {
204
+ const apexClass = await conn.singleRecordQuery(`SELECT Id FROM ApexClass WHERE Name = '${node_path_1.default.basename(filePath, '.cls')}'`, {
205
+ tooling: true,
206
+ });
207
+ return apexClass.Id;
208
+ }
209
+ catch (error) {
210
+ throw messages.createError('ApexClassIdNotFound', [filePath]);
211
+ }
212
+ };
213
+ let redirectUri = '';
214
+ switch (typeName) {
215
+ case 'ApexClass':
216
+ redirectUri = `lightning/setup/ApexClasses/page?address=%2F${await apexClassFileNameToId(this.connection, file)}`;
217
+ break;
218
+ case 'CustomObject':
219
+ redirectUri = `lightning/setup/ObjectManager/${await customObjectFileNameToId(this.connection, file)}/Details/view`;
220
+ break;
221
+ case 'Bot':
222
+ redirectUri = `/AiCopilot/copilotStudio.app#/copilot/builder?copilotId=${await botFileNameToId(this.connection, file)}`;
223
+ break;
224
+ case 'ApexPage':
225
+ redirectUri = `/apex/${node_path_1.default.basename(file).replace('.page-meta.xml', '').replace('.page', '')}`;
226
+ break;
227
+ case 'Flow':
228
+ redirectUri = `/builder_platform_interaction/flowBuilder.app?flowId=${await flowFileNameToId(this.connection, file)}`;
229
+ break;
230
+ case 'FlexiPage':
231
+ redirectUri = `/visualEditor/appBuilder.app?pageId=${await flexiPageFilenameToId(this.connection, file)}`;
232
+ break;
233
+ default:
234
+ redirectUri = '/lightning/setup/FlexiPageList/home';
235
+ break;
236
+ }
237
+ return this.getFrontDoorUrl(redirectUri);
238
+ }
239
+ /**
240
+ * Get a Frontdoor URL
241
+ *
242
+ * This uses the UI Bridge API to generate a single-use Frontdoor URL:
243
+ * https://help.salesforce.com/s/articleView?id=xcloud.frontdoor_singleaccess.htm&type=5
244
+ */
245
+ async getFrontDoorUrl(redirectUri) {
246
+ // the `singleaccess` endpoint returns 403 when using an expired token and jsforce only triggers a token refresh on 401 so we check if it's valid first
247
+ await this.refreshAuth();
248
+ const singleAccessUrl = new URL('/services/oauth2/singleaccess', this.connection.instanceUrl);
249
+ if (redirectUri) {
250
+ singleAccessUrl.searchParams.append('redirect_uri', redirectUri);
251
+ }
252
+ const response = await this.connection.requestGet(singleAccessUrl.toString());
253
+ if (response.frontdoor_uri)
254
+ return response.frontdoor_uri;
255
+ throw new sfError_1.SfError(messages.getMessage('FrontdoorURLError')).setData(response);
256
+ }
149
257
  /**
150
258
  * create a sandbox from a production org
151
259
  * 'this' needs to be a production org with sandbox licenses available
@@ -925,7 +1033,7 @@ class Org extends kit_1.AsyncOptionalCreatable {
925
1033
  }
926
1034
  async getLocalDataDir(orgDataPath) {
927
1035
  const rootFolder = await config_1.Config.resolveRootFolder(false);
928
- return (0, node_path_1.join)(rootFolder, global_1.Global.SFDX_STATE_FOLDER, orgDataPath ? orgDataPath : 'orgs');
1036
+ return node_path_1.default.join(rootFolder, global_1.Global.SFDX_STATE_FOLDER, orgDataPath ? orgDataPath : 'orgs');
929
1037
  }
930
1038
  /**
931
1039
  * Gets the sandboxProcessObject and then polls for it to complete.
@@ -1351,7 +1459,7 @@ class Org extends kit_1.AsyncOptionalCreatable {
1351
1459
  async removeSourceTrackingFiles() {
1352
1460
  try {
1353
1461
  const rootFolder = await config_1.Config.resolveRootFolder(false);
1354
- await fs.promises.rm((0, node_path_1.join)(rootFolder, global_1.Global.SF_STATE_FOLDER, 'orgs', this.getOrgId()), {
1462
+ await fs.promises.rm(node_path_1.default.join(rootFolder, global_1.Global.SF_STATE_FOLDER, 'orgs', this.getOrgId()), {
1355
1463
  recursive: true,
1356
1464
  force: true,
1357
1465
  });
package/messages/org.md CHANGED
@@ -69,3 +69,19 @@ We found more than one SandboxProcess with the SandboxName %s.
69
69
  # sandboxNotResumable
70
70
 
71
71
  The sandbox %s cannot resume with status of %s.
72
+
73
+ # FrontdoorURLError
74
+
75
+ Failed to generate a frontdoor URL.
76
+
77
+ # FlowIdNotFound
78
+
79
+ ID not found for Flow %s.
80
+
81
+ # CustomObjectIdNotFound
82
+
83
+ ID not found for custom object %s.
84
+
85
+ # ApexClassIdNotFound
86
+
87
+ ID not found for Apex class %s.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/core",
3
- "version": "8.17.0",
3
+ "version": "8.18.0",
4
4
  "description": "Core libraries to interact with SFDX projects, orgs, and APIs.",
5
5
  "main": "lib/index",
6
6
  "types": "lib/index.d.ts",
@@ -53,7 +53,7 @@
53
53
  "messageTransformer/messageTransformer.ts"
54
54
  ],
55
55
  "dependencies": {
56
- "@jsforce/jsforce-node": "^3.8.2",
56
+ "@jsforce/jsforce-node": "^3.9.1",
57
57
  "@salesforce/kit": "^3.2.2",
58
58
  "@salesforce/schemas": "^1.9.0",
59
59
  "@salesforce/ts-types": "^2.0.10",