@@ -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,17 @@ 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+ await MetaUtils . ensureFirstPartyCookiesNotRequired ( targetOrg . getConnection ( undefined ) ) ;
83+ } catch ( error ) {
84+ this . log ( 'Error autoenabling local dev' , error ) ;
85+ }
86+ }
6687
6788 const { ldpServerId, ldpServerToken } = await PreviewUtils . initializePreviewConnection ( targetOrg ) ;
6889
@@ -71,44 +92,56 @@ export default class LightningDevComponent extends SfCommand<void> {
7192 logger . debug ( `Next available ports are http=${ serverPorts . httpPort } , https=${ serverPorts . httpsPort } ` ) ;
7293
7394 logger . debug ( 'Determining Local Dev Server url' ) ;
74- const ldpServerUrl = PreviewUtils . generateWebSocketUrlForLocalDevServer ( Platform . desktop , serverPorts , logger ) ;
95+ let ldpServerUrl ;
96+
97+ // In Code Builder, we cannot go to localhost - we need to use a proxy URI to get to the ldpServer
98+ if ( process . env . SF_CONTAINER_MODE && process . env . VSCODE_PROXY_URI ) {
99+ logger . debug ( 'In Code Builder Mode - using proxy URI' ) ;
100+ ldpServerUrl = process . env . VSCODE_PROXY_URI . replace ( 'https://' , 'ws://' ) . replace (
101+ '{{port}}' ,
102+ `${ serverPorts . httpPort } `
103+ ) ;
104+ } else {
105+ // Default behavior
106+ ldpServerUrl = PreviewUtils . generateWebSocketUrlForLocalDevServer ( Platform . desktop , serverPorts , logger ) ;
107+ }
75108 logger . debug ( `Local Dev Server url is ${ ldpServerUrl } ` ) ;
76109
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- }
110+ if ( ! clientSelect ) {
111+ const namespacePaths = await ComponentUtils . getNamespacePaths ( project ) ;
112+ const componentPaths = await ComponentUtils . getAllComponentPaths ( namespacePaths ) ;
113+ if ( ! componentPaths ) {
114+ throw new Error ( messages . getMessage ( 'error.directory' ) ) ;
115+ }
82116
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 ) ;
117+ const components = (
118+ await Promise . all (
119+ componentPaths . map ( async ( componentPath ) => {
120+ let xml ;
121+
122+ try {
123+ xml = await ComponentUtils . getComponentMetadata ( componentPath ) ;
124+ } catch ( err ) {
125+ this . warn ( messages . getMessage ( 'error.component-metadata' , [ componentPath ] ) ) ;
126+ }
127+
128+ // components must have meta xml to be previewed
129+ if ( ! xml ) {
130+ return undefined ;
131+ }
132+
133+ const name = path . basename ( componentPath ) ;
134+ const label = ComponentUtils . componentNameToTitleCase ( name ) ;
135+
136+ return {
137+ name,
138+ label : xml . LightningComponentBundle . masterLabel ?? label ,
139+ description : xml . LightningComponentBundle . description ?? '' ,
140+ } ;
141+ } )
142+ )
143+ ) . filter ( ( component ) => ! ! component ) ;
110144
111- if ( ! clientSelect ) {
112145 if ( componentName ) {
113146 // validate that the component exists before launching the server
114147 const match = components . find (
@@ -138,7 +171,28 @@ export default class LightningDevComponent extends SfCommand<void> {
138171 targetOrgArg
139172 ) ;
140173
141- // Open the browser and navigate to the right page
142- await this . config . runCommand ( 'org:open' , launchArguments ) ;
174+ // Construct and log the full URL that will be opened
175+ const connection = targetOrg . getConnection ( apiVersion ) ;
176+
177+ // strip trailing slashes
178+ const instanceUrl = connection . instanceUrl . replace ( / \/ $ / , '' ) ;
179+
180+ const previewUrl = PreviewUtils . generateComponentPreviewUrl ( instanceUrl , ldpServerUrl , ldpServerId , componentName ) ;
181+
182+ // Prepare the result for JSON output
183+ const result : ComponentPreviewResult = {
184+ instanceUrl,
185+ ldpServerUrl,
186+ ldpServerId,
187+ componentName : componentName ?? '' ,
188+ previewUrl,
189+ } ;
190+
191+ // Open the browser and navigate to the right page (unless OPEN_BROWSER is set to true)
192+ if ( process . env . OPEN_BROWSER !== 'false' ) {
193+ await this . config . runCommand ( 'org:open' , launchArguments ) ;
194+ }
195+
196+ return result ;
143197 }
144198}
0 commit comments