|
5 | 5 | * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause |
6 | 6 | */ |
7 | 7 |
|
8 | | -import path from 'node:path'; |
9 | 8 | import { |
10 | 9 | Flags, |
11 | 10 | loglevel, |
12 | 11 | orgApiVersionFlagWithDeprecations, |
13 | 12 | requiredOrgFlagWithDeprecations, |
14 | 13 | } from '@salesforce/sf-plugins-core'; |
15 | | -import { Connection, Messages } from '@salesforce/core'; |
| 14 | +import { Messages, Org } from '@salesforce/core'; |
16 | 15 | import { MetadataResolver } from '@salesforce/source-deploy-retrieve'; |
17 | | -import { env } from '@salesforce/kit'; |
18 | 16 | import { buildFrontdoorUrl } from '../../shared/orgOpenUtils.js'; |
19 | 17 | import { OrgOpenCommandBase } from '../../shared/orgOpenCommandBase.js'; |
20 | 18 | import { type OrgOpenOutput } from '../../shared/orgTypes.js'; |
21 | 19 |
|
22 | 20 | Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); |
23 | 21 | const messages = Messages.loadMessages('@salesforce/plugin-org', 'open'); |
24 | | -const sharedMessages = Messages.loadMessages('@salesforce/plugin-org', 'messages'); |
25 | 22 |
|
26 | 23 | export class OrgOpenCommand extends OrgOpenCommandBase<OrgOpenOutput> { |
27 | 24 | public static readonly summary = messages.getMessage('summary'); |
@@ -68,75 +65,39 @@ export class OrgOpenCommand extends OrgOpenCommandBase<OrgOpenOutput> { |
68 | 65 | }; |
69 | 66 |
|
70 | 67 | public async run(): Promise<OrgOpenOutput> { |
71 | | - this.warn(sharedMessages.getMessage('BehaviorChangeWarning')); |
72 | 68 | const { flags } = await this.parse(OrgOpenCommand); |
73 | 69 | this.org = flags['target-org']; |
74 | 70 | this.connection = this.org.getConnection(flags['api-version']); |
75 | 71 |
|
76 | | - const singleUseEnvVar: boolean = env.getBoolean('SF_SINGLE_USE_ORG_OPEN_URL'); |
77 | | - const singleUseMode = singleUseEnvVar ? singleUseEnvVar : !(flags['url-only'] || this.jsonEnabled()); |
78 | 72 | const [frontDoorUrl, retUrl] = await Promise.all([ |
79 | | - buildFrontdoorUrl(this.org, this.connection, singleUseMode), |
80 | | - flags['source-file'] ? generateFileUrl(flags['source-file'], this.connection) : flags.path, |
| 73 | + buildFrontdoorUrl(this.org), |
| 74 | + flags['source-file'] ? generateFileUrl(flags['source-file'], this.org) : flags.path, |
81 | 75 | ]); |
82 | 76 |
|
83 | 77 | return this.openOrgUI(flags, frontDoorUrl, retUrl); |
84 | 78 | } |
85 | 79 | } |
86 | 80 |
|
87 | | -const generateFileUrl = async (file: string, conn: Connection): Promise<string> => { |
| 81 | +const generateFileUrl = async (file: string, org: Org): Promise<string> => { |
88 | 82 | try { |
89 | 83 | const metadataResolver = new MetadataResolver(); |
90 | 84 | const components = metadataResolver.getComponentsFromPath(file); |
91 | 85 | const typeName = components[0]?.type?.name; |
92 | 86 |
|
93 | | - switch (typeName) { |
94 | | - case 'Bot': |
95 | | - return `AiCopilot/copilotStudio.app#/copilot/builder?copilotId=${await botFileNameToId(conn, file)}`; |
96 | | - case 'ApexPage': |
97 | | - return `/apex/${path.basename(file).replace('.page-meta.xml', '').replace('.page', '')}`; |
98 | | - case 'Flow': |
99 | | - return `/builder_platform_interaction/flowBuilder.app?flowId=${await flowFileNameToId(conn, file)}`; |
100 | | - case 'FlexiPage': |
101 | | - return `/visualEditor/appBuilder.app?pageId=${await flexiPageFilenameToId(conn, file)}`; |
102 | | - default: |
103 | | - return 'lightning/setup/FlexiPageList/home'; |
| 87 | + if (!typeName) { |
| 88 | + throw new Error(`Unable to determine metadata type for file: ${file}`); |
104 | 89 | } |
| 90 | + |
| 91 | + return await org.getMetadataUIURL(typeName, file); |
105 | 92 | } catch (error) { |
106 | | - if (error instanceof Error && error.name === 'FlowIdNotFoundError') { |
| 93 | + if ( |
| 94 | + error instanceof Error && |
| 95 | + (error.message.includes('FlowIdNotFound') || |
| 96 | + error.message.includes('CustomObjectIdNotFound') || |
| 97 | + error.message.includes('ApexClassIdNotFound')) |
| 98 | + ) { |
107 | 99 | throw error; |
108 | 100 | } |
109 | | - return 'lightning/setup/FlexiPageList/home'; |
110 | | - } |
111 | | -}; |
112 | | - |
113 | | -const botFileNameToId = async (conn: Connection, filePath: string): Promise<string> => |
114 | | - ( |
115 | | - await conn.singleRecordQuery<{ Id: string }>( |
116 | | - `SELECT id FROM BotDefinition WHERE DeveloperName='${path.basename(filePath, '.bot-meta.xml')}'` |
117 | | - ) |
118 | | - ).Id; |
119 | | - |
120 | | -/** query flexipage via toolingPAI to get its ID (starts with 0M0) */ |
121 | | -const flexiPageFilenameToId = async (conn: Connection, filePath: string): Promise<string> => |
122 | | - ( |
123 | | - await conn.singleRecordQuery<{ Id: string }>( |
124 | | - `SELECT id FROM flexipage WHERE DeveloperName='${path.basename(filePath, '.flexipage-meta.xml')}'`, |
125 | | - { tooling: true } |
126 | | - ) |
127 | | - ).Id; |
128 | | - |
129 | | -/** query the rest API to turn a flow's filepath into a FlowId (starts with 301) */ |
130 | | -const flowFileNameToId = async (conn: Connection, filePath: string): Promise<string> => { |
131 | | - try { |
132 | | - const flow = await conn.singleRecordQuery<{ DurableId: string }>( |
133 | | - `SELECT DurableId FROM FlowVersionView WHERE FlowDefinitionView.ApiName = '${path.basename( |
134 | | - filePath, |
135 | | - '.flow-meta.xml' |
136 | | - )}' ORDER BY VersionNumber DESC LIMIT 1` |
137 | | - ); |
138 | | - return flow.DurableId; |
139 | | - } catch (error) { |
140 | | - throw messages.createError('FlowIdNotFound', [filePath]); |
| 101 | + return ''; |
141 | 102 | } |
142 | 103 | }; |
0 commit comments