Skip to content

Commit 40e417a

Browse files
committed
fix: improve error handling
1 parent fa62bc1 commit 40e417a

File tree

3 files changed

+61
-41
lines changed

3 files changed

+61
-41
lines changed

messages/lightning.dev.component.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ Unable to find components
2828

2929
Unable to determine component name
3030

31+
# error.component-metadata
32+
33+
Failed to parse component metadata at: %s
34+
35+
# error.component-not-found
36+
37+
Unable to find component with name: %s
38+
3139
# examples
3240

3341
- Select a component and launch the component preview:

src/commands/lightning/dev/component.ts

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,44 +32,57 @@ export default class LightningDevComponent extends SfCommand<void> {
3232
};
3333

3434
public async run(): Promise<void> {
35-
const project = await SfProject.resolve();
3635
const { flags } = await this.parse(LightningDevComponent);
36+
const project = await SfProject.resolve();
3737

38-
let name = flags.name;
39-
if (!name) {
40-
const dirs = await ComponentUtils.getComponentPaths(project);
41-
if (!dirs) {
42-
throw new Error(messages.getMessage('error.directory'));
43-
}
38+
const namespacePaths = await ComponentUtils.getNamespacePaths(project);
39+
const componentPaths = await ComponentUtils.getAllComponentPaths(namespacePaths);
40+
if (!componentPaths) {
41+
throw new Error(messages.getMessage('error.directory'));
42+
}
4443

45-
const components = (
46-
await Promise.all(
47-
dirs.map(async (dir) => {
48-
const xml = await ComponentUtils.getComponentMetadata(dir);
49-
if (!xml) {
50-
return undefined;
51-
}
44+
const components = (
45+
await Promise.all(
46+
componentPaths.map(async (componentPath) => {
47+
let xml;
5248

53-
const componentName = path.basename(dir);
54-
const label = ComponentUtils.componentNameToTitleCase(componentName);
49+
try {
50+
xml = await ComponentUtils.getComponentMetadata(componentPath);
51+
} catch (err) {
52+
this.warn(messages.getMessage('error.component-metadata', [componentPath]));
53+
}
5554

56-
return {
57-
name: componentName,
58-
label: xml.LightningComponentBundle.masterLabel ?? label,
59-
description: xml.LightningComponentBundle.description ?? '',
60-
};
61-
})
62-
)
63-
).filter((component) => !!component);
55+
// components must have meta xml to be previewed
56+
if (!xml) {
57+
return undefined;
58+
}
6459

60+
const componentName = path.basename(componentPath);
61+
const label = ComponentUtils.componentNameToTitleCase(componentName);
62+
63+
return {
64+
name: componentName,
65+
label: xml.LightningComponentBundle.masterLabel ?? label,
66+
description: xml.LightningComponentBundle.description ?? '',
67+
};
68+
})
69+
)
70+
).filter((component) => !!component);
71+
72+
let name = flags.name;
73+
if (name) {
74+
// validate that the component exists before launching the server
75+
if (!components.find((component) => name === component.name)) {
76+
throw new Error(messages.getMessage('error.component-not-found', [name]));
77+
}
78+
} else {
79+
// prompt the user for a name if one was not provided
6580
name = await PromptUtils.promptUserToSelectComponent(components);
6681
if (!name) {
6782
throw new Error(messages.getMessage('error.component'));
6883
}
6984
}
7085

71-
this.log('Starting application on port 3000...');
72-
7386
const port = parseInt(process.env.PORT ?? '3000', 10);
7487

7588
await cmpDev({

src/shared/componentUtils.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
*/
77
import path from 'node:path';
88
import fs from 'node:fs';
9-
import { SfProject } from '@salesforce/core';
109
import { glob } from 'glob';
1110
import { parseStringPromise } from 'xml2js';
11+
import { SfProject } from '@salesforce/core';
1212

1313
export type LwcMetadata = {
1414
LightningComponentBundle: {
@@ -26,33 +26,32 @@ export class ComponentUtils {
2626
return componentName.replace(/([A-Z])/g, ' $1').replace(/^./, (str) => str.toUpperCase());
2727
}
2828

29-
public static async getComponentPaths(project: SfProject): Promise<string[]> {
29+
public static async getNamespacePaths(project: SfProject): Promise<string[]> {
3030
const packageDirs = project.getPackageDirectories();
31-
const namespacePaths = (
32-
await Promise.all(packageDirs.map((dir) => glob(`${dir.fullPath}/**/lwc`, { absolute: true })))
33-
).flat();
3431

35-
return (
36-
await Promise.all(
37-
namespacePaths.map(async (namespacePath): Promise<string[]> => {
38-
const children = await fs.promises.readdir(namespacePath, { withFileTypes: true });
32+
return (await Promise.all(packageDirs.map((dir) => glob(`${dir.fullPath}/**/lwc`, { absolute: true })))).flat();
33+
}
3934

40-
return children
41-
.filter((child) => child.isDirectory())
42-
.map((child) => path.join(child.parentPath, child.name));
43-
})
44-
)
35+
public static async getAllComponentPaths(namespacePaths: string[]): Promise<string[]> {
36+
return (
37+
await Promise.all(namespacePaths.map((namespacePath) => ComponentUtils.getComponentPaths(namespacePath)))
4538
).flat();
4639
}
4740

41+
public static async getComponentPaths(namespacePath: string): Promise<string[]> {
42+
const children = await fs.promises.readdir(namespacePath, { withFileTypes: true });
43+
44+
return children.filter((child) => child.isDirectory()).map((child) => path.join(child.parentPath, child.name));
45+
}
46+
4847
public static async getComponentMetadata(dirname: string): Promise<LwcMetadata | undefined> {
4948
const componentName = path.basename(dirname);
5049
const metaXmlPath = path.join(dirname, `${componentName}.js-meta.xml`);
5150
if (!fs.existsSync(metaXmlPath)) {
5251
return undefined;
5352
}
5453

55-
const xmlContent = fs.readFileSync(metaXmlPath, 'utf8');
54+
const xmlContent = await fs.promises.readFile(metaXmlPath, 'utf8');
5655
const parsedData = (await parseStringPromise(xmlContent)) as LwcMetadata;
5756
if (!this.isLwcMetadata(parsedData)) {
5857
return undefined;

0 commit comments

Comments
 (0)