Skip to content

feat: update component command to return proper json result @W-19036340 #459

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,21 +201,22 @@ EXAMPLES
$ sf lightning dev app --target-org myOrg --device-type ios --device-id "iPhone 15 Pro Max"
```

_See code: [src/commands/lightning/dev/app.ts](https://github.com/salesforcecli/plugin-lightning-dev/blob/4.4.0/src/commands/lightning/dev/app.ts)_
_See code: [src/commands/lightning/dev/app.ts](https://github.com/salesforcecli/plugin-lightning-dev/blob/4.4.1-alpha.0/src/commands/lightning/dev/app.ts)_

## `sf lightning dev component`

[Beta] Preview LWC components in isolation.

```
USAGE
$ sf lightning dev component -o <value> [--json] [--flags-dir <value>] [-n <value>] [-c]
$ sf lightning dev component -o <value> [--json] [--flags-dir <value>] [-n <value>] [--api-version <value>] [-c]

FLAGS
-c, --client-select Launch component preview without selecting a component
-n, --name=<value> Name of a component to preview.
-o, --target-org=<value> (required) Username or alias of the target org. Not required if the `target-org`
configuration variable is already set.
-c, --client-select Launch component preview without selecting a component
-n, --name=<value> Name of a component to preview.
-o, --target-org=<value> (required) Username or alias of the target org. Not required if the `target-org`
configuration variable is already set.
--api-version=<value> Override the api version used for api requests made by this command

GLOBAL FLAGS
--flags-dir=<value> Import flag values from a directory.
Expand Down Expand Up @@ -248,7 +249,7 @@ EXAMPLES
$ sf lightning dev component --name myComponent
```

_See code: [src/commands/lightning/dev/component.ts](https://github.com/salesforcecli/plugin-lightning-dev/blob/4.4.0/src/commands/lightning/dev/component.ts)_
_See code: [src/commands/lightning/dev/component.ts](https://github.com/salesforcecli/plugin-lightning-dev/blob/4.4.1-alpha.0/src/commands/lightning/dev/component.ts)_

## `sf lightning dev site`

Expand Down Expand Up @@ -304,6 +305,6 @@ EXAMPLES
$ sf lightning dev site --name "Partner Central" --target-org myOrg --get-latest
```

_See code: [src/commands/lightning/dev/site.ts](https://github.com/salesforcecli/plugin-lightning-dev/blob/4.4.0/src/commands/lightning/dev/site.ts)_
_See code: [src/commands/lightning/dev/site.ts](https://github.com/salesforcecli/plugin-lightning-dev/blob/4.4.1-alpha.0/src/commands/lightning/dev/site.ts)_

<!-- commandsstop -->
4 changes: 2 additions & 2 deletions command-snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
"command": "lightning:dev:component",
"flagAliases": [],
"flagChars": ["c", "n", "o"],
"flags": ["client-select", "flags-dir", "json", "name", "target-org"],
"flags": ["api-version", "client-select", "flags-dir", "json", "name", "target-org"],
"plugin": "@salesforce/plugin-lightning-dev"
},
{
"alias": [],
"command": "lightning:dev:site",
"flagAliases": [],
"flagChars": ["l", "n", "o"],
"flags": ["flags-dir", "get-latest", "guest", "name", "target-org", "ssr"],
"flags": ["flags-dir", "get-latest", "guest", "name", "ssr", "target-org"],
"plugin": "@salesforce/plugin-lightning-dev"
}
]
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@salesforce/plugin-lightning-dev",
"description": "Lightning development tools for LEX, Mobile, and Experience Sites",
"version": "4.4.0",
"version": "4.4.1-alpha.0",
"author": "Salesforce",
"bugs": "https://github.com/forcedotcom/cli/issues",
"dependencies": {
Expand Down
112 changes: 74 additions & 38 deletions src/commands/lightning/dev/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@ Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-lightning-dev', 'lightning.dev.component');
const sharedMessages = Messages.loadMessages('@salesforce/plugin-lightning-dev', 'shared.utils');

export default class LightningDevComponent extends SfCommand<void> {
export type ComponentPreviewResult = {
instanceUrl: string;
ldpServerUrl: string;
ldpServerId: string;
componentName: string;
previewUrl: string;
};

export default class LightningDevComponent extends SfCommand<ComponentPreviewResult> {
public static readonly summary = messages.getMessage('summary');
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessages('examples');
Expand All @@ -29,6 +37,7 @@ export default class LightningDevComponent extends SfCommand<void> {
char: 'n',
requiredOrDefaulted: false,
}),
'api-version': Flags.orgApiVersion(),
'client-select': Flags.boolean({
summary: messages.getMessage('flags.client-select.summary'),
char: 'c',
Expand All @@ -37,7 +46,7 @@ export default class LightningDevComponent extends SfCommand<void> {
'target-org': Flags.requiredOrg(),
};

public async run(): Promise<void> {
public async run(): Promise<ComponentPreviewResult> {
const { flags } = await this.parse(LightningDevComponent);
const logger = await Logger.child(this.ctor.name);
const project = await SfProject.resolve();
Expand All @@ -54,6 +63,7 @@ export default class LightningDevComponent extends SfCommand<void> {
let componentName = flags['name'];
const clientSelect = flags['client-select'];
const targetOrg = flags['target-org'];
const apiVersion = flags['api-version'];

const { ldpServerId, ldpServerToken } = await PreviewUtils.initializePreviewConnection(targetOrg);

Expand All @@ -65,41 +75,41 @@ export default class LightningDevComponent extends SfCommand<void> {
const ldpServerUrl = PreviewUtils.generateWebSocketUrlForLocalDevServer(Platform.desktop, serverPorts, logger);
logger.debug(`Local Dev Server url is ${ldpServerUrl}`);

const namespacePaths = await ComponentUtils.getNamespacePaths(project);
const componentPaths = await ComponentUtils.getAllComponentPaths(namespacePaths);
if (!componentPaths) {
throw new Error(messages.getMessage('error.directory'));
}
if (!clientSelect) {
const namespacePaths = await ComponentUtils.getNamespacePaths(project);
const componentPaths = await ComponentUtils.getAllComponentPaths(namespacePaths);
if (!componentPaths) {
throw new Error(messages.getMessage('error.directory'));
}

const components = (
await Promise.all(
componentPaths.map(async (componentPath) => {
let xml;

try {
xml = await ComponentUtils.getComponentMetadata(componentPath);
} catch (err) {
this.warn(messages.getMessage('error.component-metadata', [componentPath]));
}

// components must have meta xml to be previewed
if (!xml) {
return undefined;
}

const name = path.basename(componentPath);
const label = ComponentUtils.componentNameToTitleCase(name);

return {
name,
label: xml.LightningComponentBundle.masterLabel ?? label,
description: xml.LightningComponentBundle.description ?? '',
};
})
)
).filter((component) => !!component);
const components = (
await Promise.all(
componentPaths.map(async (componentPath) => {
let xml;

try {
xml = await ComponentUtils.getComponentMetadata(componentPath);
} catch (err) {
this.warn(messages.getMessage('error.component-metadata', [componentPath]));
}

// components must have meta xml to be previewed
if (!xml) {
return undefined;
}

const name = path.basename(componentPath);
const label = ComponentUtils.componentNameToTitleCase(name);

return {
name,
label: xml.LightningComponentBundle.masterLabel ?? label,
description: xml.LightningComponentBundle.description ?? '',
};
})
)
).filter((component) => !!component);

if (!clientSelect) {
if (componentName) {
// validate that the component exists before launching the server
const match = components.find(
Expand All @@ -119,7 +129,9 @@ export default class LightningDevComponent extends SfCommand<void> {
}
}

await startLWCServer(logger, sfdxProjectRootPath, ldpServerToken, Platform.desktop, serverPorts);
if (process.env.LAUNCH_SERVER !== 'false') {
await startLWCServer(logger, sfdxProjectRootPath, ldpServerToken, Platform.desktop, serverPorts);
}

const targetOrgArg = PreviewUtils.getTargetOrgFromArguments(this.argv);
const launchArguments = PreviewUtils.generateComponentPreviewLaunchArguments(
Expand All @@ -129,7 +141,31 @@ export default class LightningDevComponent extends SfCommand<void> {
targetOrgArg
);

// Open the browser and navigate to the right page
await this.config.runCommand('org:open', launchArguments);
// Construct and log the full URL that will be opened
const connection = targetOrg.getConnection(apiVersion);

const previewUrl = PreviewUtils.generateComponentPreviewUrl(
connection.instanceUrl,
ldpServerUrl,
ldpServerId,
componentName,
false
);

// Prepare the result for JSON output
const result: ComponentPreviewResult = {
instanceUrl: connection.instanceUrl,
ldpServerUrl,
ldpServerId,
componentName: componentName ?? '',
previewUrl,
};

// Open the browser and navigate to the right page (unless OPEN_BROWSER is set to true)
if (process.env.OPEN_BROWSER !== 'false') {
await this.config.runCommand('org:open', launchArguments);
}

return result;
}
}
28 changes: 28 additions & 0 deletions src/shared/previewUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,34 @@ export class PreviewUtils {
return launchArguments;
}

/**
* Generates the full URL for a component preview.
*
* @param instanceUrl The URL of the Salesforce instance
* @param ldpServerUrl The URL for the local dev server
* @param ldpServerId Record ID for the identity token
* @param componentName The name of the component to preview
* @param encodePath Whether to encode the path
* @returns The full URL for the component preview
*/
public static generateComponentPreviewUrl(
instanceUrl: string,
ldpServerUrl: string,
ldpServerId: string,
componentName?: string,
encodePath = false
): string {
let url = `${instanceUrl}/lwr/application/e/devpreview/ai/${
encodePath ? encodeURIComponent('localdev%2Fpreview') : 'localdev%2Fpreview'
}?ldpServerUrl=${ldpServerUrl}&ldpServerId=${ldpServerId}`;
if (componentName) {
// TODO: support other namespaces
url += `&specifier=c/${componentName}`;
}

return url;
}

/**
* Generates the proper set of arguments to be used for launching a mobile app with custom launch arguments.
*
Expand Down