Skip to content

Commit 7d709ce

Browse files
authored
feat: local development multi-site support (#120)
1 parent 23cc45d commit 7d709ce

File tree

5 files changed

+655
-518
lines changed

5 files changed

+655
-518
lines changed

package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"author": "Salesforce",
66
"bugs": "https://github.com/forcedotcom/cli/issues",
77
"dependencies": {
8-
"@lwrjs/api": "0.13.3",
8+
"@lwrjs/api": "0.13.6",
99
"@lwc/lwc-dev-server": "^9.4.0",
1010
"@lwc/sfdc-lwc-compiler": "^9.4.0",
1111
"@oclif/core": "^4.0.17",
@@ -15,8 +15,8 @@
1515
"@salesforce/sf-plugins-core": "^11.2.4",
1616
"@inquirer/select": "^2.4.3",
1717
"chalk": "^5.3.0",
18-
"lwc": "7.2.0",
19-
"lwr": "0.13.3",
18+
"lwc": "7.2.1",
19+
"lwr": "0.13.6",
2020
"node-fetch": "^3.3.2",
2121
"tar": "^7.4.3"
2222
},
@@ -92,7 +92,6 @@
9292
"prepack": "sf-prepack",
9393
"prepare": "sf-install",
9494
"test": "wireit",
95-
"test:compile": "wireit",
9695
"test:nuts": "nyc mocha \"**/*.nut.ts\" --slow 4500 --timeout 600000 --parallel",
9796
"test:only": "wireit",
9897
"unlink-lwr": "yarn unlink @lwrjs/api @lwrjs/app-service @lwrjs/asset-registry @lwrjs/asset-transformer @lwrjs/auth-middleware @lwrjs/base-view-provider @lwrjs/base-view-transformer @lwrjs/client-modules @lwrjs/config @lwrjs/core @lwrjs/dev-proxy-server @lwrjs/diagnostics @lwrjs/esbuild @lwrjs/everywhere @lwrjs/fs-asset-provider @lwrjs/fs-watch @lwrjs/html-view-provider @lwrjs/instrumentation @lwrjs/label-module-provider @lwrjs/lambda @lwrjs/legacy-npm-module-provider @lwrjs/loader @lwrjs/lwc-module-provider @lwrjs/lwc-ssr @lwrjs/markdown-view-provider @lwrjs/module-bundler @lwrjs/module-registry @lwrjs/npm-module-provider @lwrjs/nunjucks-view-provider @lwrjs/o11y @lwrjs/resource-registry @lwrjs/router @lwrjs/security @lwrjs/server @lwrjs/shared-utils @lwrjs/static @lwrjs/tools @lwrjs/types @lwrjs/view-registry lwr",

schemas/lightning-dev-site.json

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/commands/lightning/dev/site.ts

Lines changed: 46 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
* Licensed under the BSD 3-Clause license.
55
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
7-
import fs from 'node:fs';
8-
import path from 'node:path';
7+
// import fs from 'node:fs';
8+
// import path from 'node:path';
99
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
10-
import { Messages, SfError } from '@salesforce/core';
11-
import { expDev, setupDev } from '@lwrjs/api';
10+
import { Messages } from '@salesforce/core';
11+
import { expDev } from '@lwrjs/api';
1212
import { PromptUtils } from '../../../shared/prompt.js';
13-
import { OrgUtils } from '../../../shared/orgUtils.js';
13+
// import { OrgUtils } from '../../../shared/orgUtils.js';
14+
import { ExperienceSite } from '../../../shared/experience/expSite.js';
1415

1516
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
1617
const messages = Messages.loadMessages('@salesforce/plugin-lightning-dev', 'lightning.dev.site');
@@ -19,7 +20,7 @@ export type LightningDevSiteResult = {
1920
path: string;
2021
};
2122

22-
export default class LightningDevSite extends SfCommand<LightningDevSiteResult> {
23+
export default class LightningDevSite extends SfCommand<void> {
2324
public static readonly summary = messages.getMessage('summary');
2425
public static readonly description = messages.getMessage('description');
2526
public static readonly examples = messages.getMessages('examples');
@@ -36,85 +37,54 @@ export default class LightningDevSite extends SfCommand<LightningDevSiteResult>
3637
'target-org': Flags.optionalOrg({ summary: messages.getMessage('flags.target-org.summary') }),
3738
};
3839

39-
public async run(): Promise<LightningDevSiteResult> {
40+
public async run(): Promise<void> {
4041
const { flags } = await this.parse(LightningDevSite);
41-
// Connect to Org
42-
const connection = flags['target-org'].getConnection();
4342

44-
// If we don't have a site to use, promp the user for one
45-
let siteName = flags.name;
46-
if (!siteName) {
47-
this.log('No site name was specified, pick one');
48-
// Query for the list of possible sites
49-
const siteList = await OrgUtils.retrieveSites(connection);
50-
siteName = await PromptUtils.promptUserToSelectSite(siteList);
51-
}
52-
this.log(`Setting up local development for: ${siteName}`);
43+
// TODO short circuit all this if user specifies a site name and it exists locally
5344

54-
siteName = siteName.trim().replace(' ', '_');
55-
const siteDir = path.join('__local_dev__', siteName);
56-
if (!fs.existsSync(path.join(siteDir, 'ssr.js'))) {
57-
// Ensure local dev dir is created
58-
fs.mkdirSync('__local_dev__');
59-
// 3. Check if the site has been published
60-
const result = await connection.query<{ Id: string; Name: string; LastModifiedDate: string }>(
61-
"SELECT Id, Name, LastModifiedDate FROM StaticResource WHERE Name LIKE 'MRT%" + siteName + "'"
62-
);
45+
try {
46+
// 1. Connect to Org
47+
const org = flags['target-org'];
48+
let siteName = flags.name;
6349

64-
let resourceName;
65-
// Pick the site you want if there is more than one
66-
if (result?.totalSize > 1) {
67-
const chooseFromList = result.records.map((record) => record.Name);
68-
resourceName = await PromptUtils.promptUserToSelectSite(chooseFromList);
69-
} else if (result?.totalSize === 1) {
70-
resourceName = result.records[0].Name;
71-
} else {
72-
throw new SfError(
73-
`Couldnt find your site: ${siteName}. Please navigate to the builder and publish your site with the Local Development preference enabled in your org.`
74-
);
50+
// 2. If we don't have a site to use, prompt the user for one
51+
if (!siteName) {
52+
this.log('No site was specified');
53+
// Allow user to pick a site
54+
const siteList = await ExperienceSite.getAllExpSites(org.getConnection());
55+
siteName = await PromptUtils.promptUserToSelectSite(siteList);
7556
}
7657

77-
// Download the static resource
78-
this.log('Downloading Site...');
79-
const staticresource = await connection.metadata.read('StaticResource', resourceName);
80-
const resourcePath = path.join('__local_dev__', `${resourceName}.gz`);
81-
if (staticresource?.content) {
82-
// Save the static resource
83-
const buffer = Buffer.from(staticresource.content, 'base64');
84-
this.log(`Writing file to path: ${resourcePath}`);
85-
fs.writeFileSync(resourcePath, buffer);
58+
// 3. Setup local dev directory structure: '.localdev/${site}'
59+
this.log(`Setting up Local Development for: ${siteName}`);
60+
const selectedSite = new ExperienceSite(org, siteName);
61+
let siteZip;
62+
if (!selectedSite.isSiteSetup()) {
63+
// TODO Verify the bundle has been published and download
64+
this.log('Downloading Site...');
65+
siteZip = await selectedSite.downloadSite();
8666
} else {
87-
throw new SfError(`Error occured downloading your site: ${siteName}`);
67+
// If we do have the site setup already, don't do anything / TODO prompt the user if they want to get latest?
68+
// Check if the site has been published
69+
// const result = await connection.query<{ Id: string; Name: string; LastModifiedDate: string }>(
70+
// "SELECT Id, Name, LastModifiedDate FROM StaticResource WHERE Name LIKE 'MRT%" + siteName + "'"
71+
// );
72+
// this.log('Setup already complete!');
8873
}
8974

90-
const domains = await OrgUtils.getDomains(connection);
91-
const domain = await PromptUtils.promptUserToSelectDomain(domains);
92-
const urlPrefix = await OrgUtils.getSitePathPrefix(connection, siteName);
93-
const fullProxyUrl = `https://${domain}${urlPrefix}`;
94-
95-
// Setup Local Dev
96-
await setupDev({ mrtBundle: resourcePath, mrtDir: siteDir, proxyUrl: fullProxyUrl, npmInstall: false });
97-
this.log('Setup Complete!');
98-
} else {
99-
// If we do have the site setup already, don't do anything / TODO prompt the user if they want to get latest?
75+
// 6. Start the dev server
76+
this.log('Starting local development server...');
77+
await expDev({
78+
open: false,
79+
port: 3000,
80+
logLevel: 'error',
81+
mode: 'dev',
82+
siteZip,
83+
siteDir: selectedSite.getSiteDirectory(),
84+
});
85+
} catch (e) {
86+
// this.error(e);
87+
this.log('Local Development setup failed', e);
10088
}
101-
102-
// 6. Start the dev server
103-
this.log('Starting local development server...');
104-
// TODO add additional args
105-
// eslint-disable-next-line unicorn/numeric-separators-style
106-
await expDev({
107-
open: false,
108-
port: 3000,
109-
timeout: 30000,
110-
sandbox: false,
111-
logLevel: 'error',
112-
mrtBundleRoot: siteDir,
113-
});
114-
// const name = flags.name ?? 'world';
115-
// this.log(`hello ${name} from /Users/nkruk/git/plugin-lightning-dev/src/commands/lightning/dev/site.ts`);
116-
return {
117-
path: '/Users/nkruk/git/plugin-lightning-dev/src/commands/lightning/dev/site.ts',
118-
};
11989
}
12090
}

0 commit comments

Comments
 (0)