Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/onRelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
#ctc: true
sign: true
# At CLCO, the new patch branch's version will be released as 'prerelease'. After R2b, delete the logic below for 'latest' and update 'prerelease' candidate to 'latest'
tag: ${{ needs.getDistTag.outputs.tag || (needs.getMajorVersion.outputs.major == '3' && 'latest') || (needs.getMajorVersion.outputs.major == '4' && 'prerelease') ||'next' }}
tag: ${{ needs.getDistTag.outputs.tag || (needs.getMajorVersion.outputs.major == '4' && 'latest') || 'next' }}
githubTag: ${{ github.event.release.tag_name || inputs.tag }}

secrets: inherit
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/5.0.24/src/commands/lightning/dev/app.ts)_
_See code: [src/commands/lightning/dev/app.ts](https://github.com/salesforcecli/plugin-lightning-dev/blob/5.0.25-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/5.0.24/src/commands/lightning/dev/component.ts)_
_See code: [src/commands/lightning/dev/component.ts](https://github.com/salesforcecli/plugin-lightning-dev/blob/5.0.25-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/5.0.24/src/commands/lightning/dev/site.ts)_
_See code: [src/commands/lightning/dev/site.ts](https://github.com/salesforcecli/plugin-lightning-dev/blob/5.0.25-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"
}
]
6 changes: 1 addition & 5 deletions lwc.config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
{
"modules": [
{
"npm": "lightning-base-components"
}
]
"modules": []
}
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "@salesforce/plugin-lightning-dev",
"description": "Lightning development tools for LEX, Mobile, and Experience Sites",
"version": "5.0.24",
"version": "5.0.25-alpha.0",
"author": "Salesforce",
"bugs": "https://github.com/forcedotcom/cli/issues",
"dependencies": {
"@inquirer/prompts": "^5.3.8",
"@inquirer/select": "^2.4.7",
"@lwc/lwc-dev-server": "~13.2.18",
"@lwc/sfdc-lwc-compiler": "~13.2.7",
"@lwc/lwc-dev-server": "~13.2.19",
"@lwc/sfdc-lwc-compiler": "~13.2.19",
"@lwrjs/api": "0.18.3",
"@oclif/core": "^4.5.6",
"@salesforce/core": "^8.23.3",
Expand All @@ -17,7 +17,7 @@
"@salesforce/sf-plugins-core": "^11.2.4",
"axios": "^1.13.1",
"glob": "^10.4.5",
"lwc": "~8.23.0",
"lwc": "~8.24.0",
"node-fetch": "^3.3.2",
"open": "^10.2.0",
"xml2js": "^0.6.2"
Expand Down Expand Up @@ -265,7 +265,7 @@
"exports": "./lib/index.js",
"type": "module",
"volta": {
"node": "20.11.0",
"node": "20.12.0",
"yarn": "1.22.22"
}
}
135 changes: 97 additions & 38 deletions src/commands/lightning/dev/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,21 @@ import { ComponentUtils } from '../../../shared/componentUtils.js';
import { PromptUtils } from '../../../shared/promptUtils.js';
import { PreviewUtils } from '../../../shared/previewUtils.js';
import { startLWCServer } from '../../../lwc-dev-server/index.js';
import { MetaUtils } from '../../../shared/metaUtils.js';

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 @@ -38,6 +47,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 @@ -46,7 +56,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 @@ -63,6 +73,16 @@ 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'];

// Auto enable local dev
if (process.env.AUTO_ENABLE_LOCAL_DEV === 'true') {
try {
await MetaUtils.ensureLightningPreviewEnabled(targetOrg.getConnection(undefined));
} catch (error) {
this.log('Error autoenabling local dev', error);
}
}

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

Expand All @@ -71,44 +91,56 @@ export default class LightningDevComponent extends SfCommand<void> {
logger.debug(`Next available ports are http=${serverPorts.httpPort} , https=${serverPorts.httpsPort}`);

logger.debug('Determining Local Dev Server url');
const ldpServerUrl = PreviewUtils.generateWebSocketUrlForLocalDevServer(Platform.desktop, serverPorts, logger);
let ldpServerUrl;

// In Code Builder, we cannot go to localhost - we need to use a proxy URI to get to the ldpServer
if (process.env.SF_CONTAINER_MODE && process.env.VSCODE_PROXY_URI) {
logger.debug('In Code Builder Mode - using proxy URI');
ldpServerUrl = process.env.VSCODE_PROXY_URI.replace('https://', 'ws://').replace(
'{{port}}',
`${serverPorts.httpPort}`
);
} else {
// Default behavior
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 Down Expand Up @@ -138,7 +170,34 @@ 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);

// strip trailing slashes
const instanceUrl = connection.instanceUrl.replace(/\/$/, '');

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

// Prepare the result for JSON output
const result: ComponentPreviewResult = {
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;
}
}
Loading