@@ -22,12 +22,21 @@ import { ComponentUtils } from '../../../shared/componentUtils.js';
2222import { PromptUtils } from '../../../shared/promptUtils.js' ;
2323import { PreviewUtils } from '../../../shared/previewUtils.js' ;
2424import { startLWCServer } from '../../../lwc-dev-server/index.js' ;
25+ import { MetaUtils } from '../../../shared/metaUtils.js' ;
2526
2627Messages . importMessagesDirectoryFromMetaUrl ( import . meta. url ) ;
2728const messages = Messages . loadMessages ( '@salesforce/plugin-lightning-dev' , 'lightning.dev.component' ) ;
2829const sharedMessages = Messages . loadMessages ( '@salesforce/plugin-lightning-dev' , 'shared.utils' ) ;
2930
30- export default class LightningDevComponent extends SfCommand < void > {
31+ export type ComponentPreviewResult = {
32+ instanceUrl : string ;
33+ ldpServerUrl : string ;
34+ ldpServerId : string ;
35+ componentName : string ;
36+ previewUrl : string ;
37+ } ;
38+
39+ export default class LightningDevComponent extends SfCommand < ComponentPreviewResult > {
3140 public static readonly summary = messages . getMessage ( 'summary' ) ;
3241 public static readonly description = messages . getMessage ( 'description' ) ;
3342 public static readonly examples = messages . getMessages ( 'examples' ) ;
@@ -38,6 +47,7 @@ export default class LightningDevComponent extends SfCommand<void> {
3847 char : 'n' ,
3948 requiredOrDefaulted : false ,
4049 } ) ,
50+ 'api-version' : Flags . orgApiVersion ( ) ,
4151 'client-select' : Flags . boolean ( {
4252 summary : messages . getMessage ( 'flags.client-select.summary' ) ,
4353 char : 'c' ,
@@ -46,7 +56,7 @@ export default class LightningDevComponent extends SfCommand<void> {
4656 'target-org' : Flags . requiredOrg ( ) ,
4757 } ;
4858
49- public async run ( ) : Promise < void > {
59+ public async run ( ) : Promise < ComponentPreviewResult > {
5060 const { flags } = await this . parse ( LightningDevComponent ) ;
5161 const logger = await Logger . child ( this . ctor . name ) ;
5262 const project = await SfProject . resolve ( ) ;
@@ -63,6 +73,16 @@ export default class LightningDevComponent extends SfCommand<void> {
6373 let componentName = flags [ 'name' ] ;
6474 const clientSelect = flags [ 'client-select' ] ;
6575 const targetOrg = flags [ 'target-org' ] ;
76+ const apiVersion = flags [ 'api-version' ] ;
77+
78+ // Auto enable local dev
79+ if ( process . env . AUTO_ENABLE_LOCAL_DEV === 'true' ) {
80+ try {
81+ await MetaUtils . ensureLightningPreviewEnabled ( targetOrg . getConnection ( undefined ) ) ;
82+ } catch ( error ) {
83+ this . log ( 'Error autoenabling local dev' , error ) ;
84+ }
85+ }
6686
6787 const { ldpServerId, ldpServerToken } = await PreviewUtils . initializePreviewConnection ( targetOrg ) ;
6888
@@ -71,44 +91,56 @@ export default class LightningDevComponent extends SfCommand<void> {
7191 logger . debug ( `Next available ports are http=${ serverPorts . httpPort } , https=${ serverPorts . httpsPort } ` ) ;
7292
7393 logger . debug ( 'Determining Local Dev Server url' ) ;
74- const ldpServerUrl = PreviewUtils . generateWebSocketUrlForLocalDevServer ( Platform . desktop , serverPorts , logger ) ;
94+ let ldpServerUrl ;
95+
96+ // In Code Builder, we cannot go to localhost - we need to use a proxy URI to get to the ldpServer
97+ if ( process . env . SF_CONTAINER_MODE && process . env . VSCODE_PROXY_URI ) {
98+ logger . debug ( 'In Code Builder Mode - using proxy URI' ) ;
99+ ldpServerUrl = process . env . VSCODE_PROXY_URI . replace ( 'https://' , 'ws://' ) . replace (
100+ '{{port}}' ,
101+ `${ serverPorts . httpPort } `
102+ ) ;
103+ } else {
104+ // Default behavior
105+ ldpServerUrl = PreviewUtils . generateWebSocketUrlForLocalDevServer ( Platform . desktop , serverPorts , logger ) ;
106+ }
75107 logger . debug ( `Local Dev Server url is ${ ldpServerUrl } ` ) ;
76108
77- const namespacePaths = await ComponentUtils . getNamespacePaths ( project ) ;
78- const componentPaths = await ComponentUtils . getAllComponentPaths ( namespacePaths ) ;
79- if ( ! componentPaths ) {
80- throw new Error ( messages . getMessage ( 'error.directory' ) ) ;
81- }
109+ if ( ! clientSelect ) {
110+ const namespacePaths = await ComponentUtils . getNamespacePaths ( project ) ;
111+ const componentPaths = await ComponentUtils . getAllComponentPaths ( namespacePaths ) ;
112+ if ( ! componentPaths ) {
113+ throw new Error ( messages . getMessage ( 'error.directory' ) ) ;
114+ }
82115
83- const components = (
84- await Promise . all (
85- componentPaths . map ( async ( componentPath ) => {
86- let xml ;
87-
88- try {
89- xml = await ComponentUtils . getComponentMetadata ( componentPath ) ;
90- } catch ( err ) {
91- this . warn ( messages . getMessage ( 'error.component-metadata' , [ componentPath ] ) ) ;
92- }
93-
94- // components must have meta xml to be previewed
95- if ( ! xml ) {
96- return undefined ;
97- }
98-
99- const name = path . basename ( componentPath ) ;
100- const label = ComponentUtils . componentNameToTitleCase ( name ) ;
101-
102- return {
103- name,
104- label : xml . LightningComponentBundle . masterLabel ?? label ,
105- description : xml . LightningComponentBundle . description ?? '' ,
106- } ;
107- } )
108- )
109- ) . filter ( ( component ) => ! ! component ) ;
116+ const components = (
117+ await Promise . all (
118+ componentPaths . map ( async ( componentPath ) => {
119+ let xml ;
120+
121+ try {
122+ xml = await ComponentUtils . getComponentMetadata ( componentPath ) ;
123+ } catch ( err ) {
124+ this . warn ( messages . getMessage ( 'error.component-metadata' , [ componentPath ] ) ) ;
125+ }
126+
127+ // components must have meta xml to be previewed
128+ if ( ! xml ) {
129+ return undefined ;
130+ }
131+
132+ const name = path . basename ( componentPath ) ;
133+ const label = ComponentUtils . componentNameToTitleCase ( name ) ;
134+
135+ return {
136+ name,
137+ label : xml . LightningComponentBundle . masterLabel ?? label ,
138+ description : xml . LightningComponentBundle . description ?? '' ,
139+ } ;
140+ } )
141+ )
142+ ) . filter ( ( component ) => ! ! component ) ;
110143
111- if ( ! clientSelect ) {
112144 if ( componentName ) {
113145 // validate that the component exists before launching the server
114146 const match = components . find (
@@ -138,7 +170,34 @@ export default class LightningDevComponent extends SfCommand<void> {
138170 targetOrgArg
139171 ) ;
140172
141- // Open the browser and navigate to the right page
142- await this . config . runCommand ( 'org:open' , launchArguments ) ;
173+ // Construct and log the full URL that will be opened
174+ const connection = targetOrg . getConnection ( apiVersion ) ;
175+
176+ // strip trailing slashes
177+ const instanceUrl = connection . instanceUrl . replace ( / \/ $ / , '' ) ;
178+
179+ const previewUrl = PreviewUtils . generateComponentPreviewUrl (
180+ instanceUrl ,
181+ ldpServerUrl ,
182+ ldpServerId ,
183+ componentName ,
184+ false
185+ ) ;
186+
187+ // Prepare the result for JSON output
188+ const result : ComponentPreviewResult = {
189+ instanceUrl,
190+ ldpServerUrl,
191+ ldpServerId,
192+ componentName : componentName ?? '' ,
193+ previewUrl,
194+ } ;
195+
196+ // Open the browser and navigate to the right page (unless OPEN_BROWSER is set to true)
197+ if ( process . env . OPEN_BROWSER !== 'false' ) {
198+ await this . config . runCommand ( 'org:open' , launchArguments ) ;
199+ }
200+
201+ return result ;
143202 }
144203}
0 commit comments