lwr 0.11.0-alpha.8 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,14 +27,16 @@ __export(exports, {
27
27
  createBuildCommand: () => createBuildCommand
28
28
  });
29
29
  var import_commander = __toModule(require("commander"));
30
- var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
30
+ var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
31
31
  var import_fs_extra = __toModule(require("fs-extra"));
32
32
  var import_path = __toModule(require("path"));
33
33
  var import_utils = __toModule(require("../utils.cjs"));
34
34
  var import_config = __toModule(require("@lwrjs/config"));
35
+ var import_tools = __toModule(require("@lwrjs/tools"));
36
+ var RUNTIME_CONFIG_SRC_DIR = "config";
35
37
  function createBuildCommand() {
36
38
  return new import_commander.Command("build").description("Build an LWR application").addOption((0, import_utils.getTargetOption)()).addOption((0, import_utils.getModeOption)().choices(["prod", "prod-compat"])).option("-o, --output <directory>", `[string] output directory`).option("--clean", `[boolean] delete the output directory`, false).option("-r, --routes <routes...>", `routes`).option("-m, --modules <modules...>", `modules`).option("-l, --locales <locales...>", `locales`).option("--minify", "[boolean] minifies build output", false).action(async (options, cmd) => {
37
- import_shared_utils.logger.info("[build] Building lwr application");
39
+ import_diagnostics.logger.info("[build] Building lwr application");
38
40
  const {rootDir, config, output, mode, clean, target, minify, routes, modules, locales} = cmd.optsWithGlobals();
39
41
  const outputDir = output ? output : (0, import_utils.getDefaultBuildDirectory)(rootDir, config, target);
40
42
  const aConfig = (0, import_config.loadConfig)({rootDir, lwrConfigFile: config});
@@ -43,47 +45,55 @@ function createBuildCommand() {
43
45
  ssrFunctionNodeVersion = getSuggestedNodeVersion();
44
46
  }
45
47
  if (clean) {
46
- import_shared_utils.logger.info(`[build] Clearing output directory: ${outputDir}`);
48
+ import_diagnostics.logger.info(`[build] Clearing output directory: ${outputDir}`);
47
49
  import_fs_extra.default.rmSync(outputDir, {recursive: true, force: true});
48
50
  } else {
49
51
  if (import_fs_extra.default.existsSync(`${outputDir}`)) {
50
- import_shared_utils.logger.warn(`[build] Output directory already exists. Previously generated files will not be deleted. If you did not intend to do this, re-run with --clean true`);
52
+ import_diagnostics.logger.warn(`[build] Output directory already exists. Previously generated files will not be deleted. If you did not intend to do this, re-run with --clean true`);
51
53
  }
52
54
  }
53
55
  const generatedSitePath = target === "mrt" ? import_path.default.join(outputDir, "site") : outputDir;
54
56
  const {generateStaticSite} = await Promise.resolve().then(() => __toModule(require("@lwrjs/core")));
57
+ const theLocales = locales ? locales.map((l) => {
58
+ return {id: l};
59
+ }) : aConfig.appConfig.i18n?.locales || [];
60
+ const i18n = {
61
+ ...aConfig.appConfig.i18n,
62
+ locales: theLocales
63
+ };
55
64
  try {
56
- const _additionalRoutes = routes || aConfig.appConfig.staticSiteGenerator._additionalRoutePaths || [];
65
+ const _additionalRoutePaths = routes || aConfig.appConfig.staticSiteGenerator._additionalRoutePaths || [];
57
66
  const _additionalModules = modules || aConfig.appConfig.staticSiteGenerator._additionalModules || [];
58
- const theLocales = locales || aConfig.appConfig.staticSiteGenerator.locales || [];
59
67
  if (target === "mrt") {
60
68
  _additionalModules.push("@lwc/engine-server");
61
69
  }
62
70
  const staticSiteGenerator = {
63
71
  outputDir: generatedSitePath,
64
72
  skipCleanOutputDir: true,
65
- _additionalRoutes,
66
- _additionalModules,
67
- locales: theLocales
73
+ _additionalRoutePaths,
74
+ _additionalModules
68
75
  };
69
76
  await generateStaticSite({
70
77
  serverMode: mode,
71
- staticSiteGenerator
78
+ staticSiteGenerator,
79
+ i18n
72
80
  });
81
+ stageProxyConfig(rootDir, outputDir);
73
82
  } catch (error) {
74
- import_shared_utils.logger.error(error);
83
+ import_diagnostics.logger.error(error);
75
84
  }
76
85
  if (target === "mrt") {
86
+ (0, import_tools.dedupeBundles)(generatedSitePath, i18n);
77
87
  const config2 = aConfig.appConfig;
78
88
  const rootDir2 = config2.rootDir;
79
89
  try {
80
90
  process.env.SSR_STATIC_BUNDLES = "true";
81
- import_shared_utils.logger.info("[build] Generating ssr.js");
91
+ import_diagnostics.logger.info("[build] Generating ssr.js");
82
92
  const {buildServer} = await Promise.resolve().then(() => __toModule(require("@lwrjs/tools")));
83
93
  const castMinify = minify == "false" ? false : !!minify;
84
94
  await buildServer({rootDir: rootDir2, serverMode: mode, staticSiteGenerator: {outputDir: "site"}}, {outputDir, minify: castMinify});
85
95
  } catch (error) {
86
- import_shared_utils.logger.error(error);
96
+ import_diagnostics.logger.error(error);
87
97
  }
88
98
  const dirsInConfig = [];
89
99
  try {
@@ -93,7 +103,7 @@ function createBuildCommand() {
93
103
  name: packageJson.name ? packageJson.name : "lwr-app",
94
104
  version: packageJson.version ? packageJson.version : "1.0.0"
95
105
  }, null, 4));
96
- import_shared_utils.logger.info("[build] copying source files");
106
+ import_diagnostics.logger.info("[build] copying source files");
97
107
  const contentDir = config2.contentDir;
98
108
  if (import_fs_extra.default.existsSync(contentDir)) {
99
109
  const relPath = contentDir.substring(rootDir2.length);
@@ -116,15 +126,15 @@ function createBuildCommand() {
116
126
  import_fs_extra.default.copySync(globalDataDir, globalDataOutputDir);
117
127
  }
118
128
  } catch (e) {
119
- import_shared_utils.logger.error(e);
129
+ import_diagnostics.logger.error(e);
120
130
  }
121
- import_shared_utils.logger.info("[build] generating default.json");
131
+ import_diagnostics.logger.info("[build] generating default.json");
122
132
  try {
123
- const configFile = import_path.default.join(rootDir2, "config", "default.json");
124
- const outputConfigFile = import_path.default.join(outputDir, "config", "default.json");
125
- import_fs_extra.default.ensureDirSync(import_path.default.join(outputDir, "config"));
133
+ const configFile = import_path.default.join(rootDir2, RUNTIME_CONFIG_SRC_DIR, "default.json");
134
+ const outputConfigFile = import_path.default.join(outputDir, RUNTIME_CONFIG_SRC_DIR, "default.json");
135
+ import_fs_extra.default.ensureDirSync(import_path.default.join(outputDir, RUNTIME_CONFIG_SRC_DIR));
126
136
  if (import_fs_extra.default.existsSync(configFile)) {
127
- import_shared_utils.logger.warn("[build] You have a config file already defined, using that rather than generating one.");
137
+ import_diagnostics.logger.warn("[build] You have a config file already defined, using that rather than generating one.");
128
138
  import_fs_extra.default.copyFileSync(configFile, outputConfigFile);
129
139
  } else {
130
140
  const defaultConfigContent = {
@@ -147,9 +157,9 @@ function createBuildCommand() {
147
157
  import_fs_extra.default.writeFileSync(outputConfigFile, JSON.stringify(defaultConfigContent, null, 4));
148
158
  }
149
159
  } catch (e) {
150
- import_shared_utils.logger.error(e);
160
+ import_diagnostics.logger.error(e);
151
161
  }
152
- import_shared_utils.logger.info("[build] complete");
162
+ import_diagnostics.logger.info("[build] complete");
153
163
  }
154
164
  });
155
165
  }
@@ -158,8 +168,21 @@ function getSuggestedNodeVersion() {
158
168
  const nodeVersion = process.version;
159
169
  const majorVersion = parseInt(nodeVersion.slice(1).split(".")[0]);
160
170
  if (!MRT_VERSIONS.includes(majorVersion)) {
161
- import_shared_utils.logger.error(`Node Version ${nodeVersion} is not one of LWR Lambda's supported versions ${MRT_VERSIONS.join(", ")}`);
171
+ import_diagnostics.logger.error(`Node Version ${nodeVersion} is not one of LWR Lambda's supported versions ${MRT_VERSIONS.join(", ")}`);
162
172
  process.exit(1);
163
173
  }
164
174
  return `${majorVersion}.x`;
165
175
  }
176
+ function stageProxyConfig(rootDir, outputDir) {
177
+ try {
178
+ const configFile = import_path.default.join(rootDir, RUNTIME_CONFIG_SRC_DIR, "_proxy");
179
+ const outputConfigFile = import_path.default.join(outputDir, RUNTIME_CONFIG_SRC_DIR, "_proxy");
180
+ if (import_fs_extra.default.existsSync(configFile)) {
181
+ import_diagnostics.logger.info("[build] staging proxy configuration");
182
+ import_fs_extra.default.ensureDirSync(import_path.default.join(outputDir, RUNTIME_CONFIG_SRC_DIR));
183
+ import_fs_extra.default.copyFileSync(configFile, outputConfigFile);
184
+ }
185
+ } catch (e) {
186
+ import_diagnostics.logger.error(e);
187
+ }
188
+ }
@@ -28,22 +28,45 @@ __export(exports, {
28
28
  });
29
29
  var import_commander = __toModule(require("commander"));
30
30
  var import_chalk = __toModule(require("chalk"));
31
- var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
31
+ var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
32
32
  var import_utils = __toModule(require("../utils.cjs"));
33
+ var import_dev_proxy_server = __toModule(require("@lwrjs/dev-proxy-server"));
33
34
  function createDevCommand() {
34
35
  return new import_commander.Command("dev").description("Starts an LWR server (defaults to dev mode)").addOption((0, import_utils.getPortOption)()).addOption((0, import_utils.getModeOption)().default("dev")).option("-o, --open", `[boolean] open browser on startup`, false).action(async (options, cmd) => {
35
36
  const {createServer} = await Promise.resolve().then(() => __toModule(require("@lwrjs/core")));
36
37
  const {port, mode, rootDir, config, open} = cmd.optsWithGlobals();
38
+ let runtimePort = port;
39
+ const proxyPort = port === void 0 ? import_dev_proxy_server.DEFAULT_PROXY_PORT : port;
37
40
  try {
38
- const server = createServer({port, serverMode: mode, rootDir, lwrConfigFile: config});
39
- await server.listen(async ({serverMode, port: port2}) => {
40
- console.log(import_chalk.default.green(`Running LWR at: http://localhost:${port2} | mode: ${serverMode}`));
41
- if (open) {
42
- await (0, import_utils.launch)(port2);
43
- }
41
+ const proxyConfig = (0, import_dev_proxy_server.findProxyConfiguration)(rootDir);
42
+ if (proxyConfig) {
43
+ runtimePort = proxyPort + 1;
44
+ const proxyServer = (0, import_dev_proxy_server.createProxyServer)({
45
+ port: proxyPort,
46
+ defaultHost: `http://localhost:${runtimePort}`,
47
+ ...proxyConfig
48
+ });
49
+ await proxyServer.listen(({port: proxyPort2}) => {
50
+ console.log(import_chalk.default.blue(`Running LWR Proxy at: http://localhost:${proxyPort2}`));
51
+ });
52
+ }
53
+ const server = createServer({
54
+ port: runtimePort,
55
+ serverMode: mode,
56
+ rootDir,
57
+ lwrConfigFile: config
44
58
  });
59
+ await server.listen(async ({serverMode, port: appPort}) => {
60
+ runtimePort = appPort;
61
+ console.log(import_chalk.default.green(`Running LWR at: http://localhost:${appPort} | mode: ${serverMode}`));
62
+ });
63
+ const sitePort = proxyConfig !== void 0 ? proxyPort : runtimePort;
64
+ console.log(import_chalk.default.magenta(`Application site is available at: http://localhost:${sitePort}`));
65
+ if (open) {
66
+ await (0, import_utils.launch)(sitePort);
67
+ }
45
68
  } catch (error) {
46
- import_shared_utils.logger.error(error);
69
+ import_diagnostics.logger.error(error);
47
70
  process.exit(1);
48
71
  }
49
72
  });
@@ -32,23 +32,41 @@ var import_commander = __toModule(require("commander"));
32
32
  var import_chalk = __toModule(require("chalk"));
33
33
  var import_express = __toModule(require("express"));
34
34
  var import_fs_extra = __toModule(require("fs-extra"));
35
- var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
35
+ var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
36
36
  var import_utils = __toModule(require("../utils.cjs"));
37
+ var import_dev_proxy_server = __toModule(require("@lwrjs/dev-proxy-server"));
37
38
  function createPreviewCommand() {
38
39
  return new import_commander.Command("preview").aliases(["start"]).description("Preview your built server on the specified target environment").addOption((0, import_utils.getPortOption)()).addOption((0, import_utils.getModeOption)()).addOption((0, import_utils.getTargetOption)()).option("-b, --buildDir <string>", "[string] The prebuilt directory for your site").option("-o, --open", `[boolean] open browser on startup`, false).action(async (options, cmd) => {
39
40
  try {
40
41
  const {rootDir, config, port, target, mode, buildDir, open} = cmd.optsWithGlobals();
41
42
  const serverMode = mode;
43
+ let runtimePort = port;
44
+ const proxyPort = port === void 0 ? import_dev_proxy_server.DEFAULT_PROXY_PORT : port;
42
45
  if (buildDir && !import_fs_extra.default.existsSync(buildDir)) {
43
46
  throw new Error(`specified build directory '${buildDir}' does not exist`);
44
47
  }
45
48
  const dir = buildDir ? buildDir : (0, import_utils.getDefaultBuildDirectory)(rootDir, config, target);
49
+ const proxyConfig = (0, import_dev_proxy_server.findProxyConfiguration)(rootDir, buildDir);
50
+ if (proxyConfig) {
51
+ runtimePort = proxyPort + 1;
52
+ const proxyServer = (0, import_dev_proxy_server.createProxyServer)({
53
+ port: proxyPort,
54
+ defaultHost: `http://localhost:${runtimePort}`,
55
+ ...proxyConfig
56
+ });
57
+ await proxyServer.listen(({port: proxyPort2}) => {
58
+ console.log(import_chalk.default.blue(`Running LWR Proxy at: http://localhost:${proxyPort2}`));
59
+ });
60
+ }
46
61
  if (target === "mrt") {
47
62
  const ssrJs = import_path.default.join(dir, "ssr.js");
48
63
  if (import_fs_extra.default.existsSync(ssrJs)) {
49
- (0, import_child_process.execSync)(`node ${ssrJs}`, {
64
+ (0, import_child_process.spawn)("node", [`${ssrJs}`], {
65
+ cwd: process.cwd(),
50
66
  env: {
51
- ...process.env
67
+ ...process.env,
68
+ PORT: runtimePort,
69
+ NODE_ENV: "test"
52
70
  },
53
71
  stdio: "inherit"
54
72
  });
@@ -57,21 +75,29 @@ function createPreviewCommand() {
57
75
  }
58
76
  } else {
59
77
  const {createServer} = await Promise.resolve().then(() => __toModule(require("@lwrjs/core")));
60
- const server = createServer({port, serverMode, rootDir, lwrConfigFile: config});
78
+ const server = createServer({
79
+ port: runtimePort,
80
+ serverMode,
81
+ rootDir,
82
+ lwrConfigFile: config
83
+ });
61
84
  const internalServer = server.getInternalServer();
62
85
  if (import_fs_extra.default.existsSync(dir)) {
63
- import_shared_utils.logger.info("Using prebuilt content from directory: " + dir);
86
+ import_diagnostics.logger.info("Using prebuilt content from directory: " + dir);
64
87
  internalServer.use(import_express.default.static(dir));
65
88
  }
66
- await server.listen(async ({serverMode: serverMode2, port: port2}) => {
67
- console.log(import_chalk.default.green(`Running LWR at: http://localhost:${port2} | mode: ${serverMode2}`));
68
- if (open) {
69
- await (0, import_utils.launch)(port2);
70
- }
89
+ await server.listen(async ({serverMode: serverMode2, port: appPort}) => {
90
+ runtimePort = appPort;
91
+ console.log(import_chalk.default.green(`Running LWR at: http://localhost:${appPort} | mode: ${serverMode2}`));
71
92
  });
72
93
  }
94
+ const sitePort = proxyConfig !== void 0 ? proxyPort : runtimePort;
95
+ console.log(import_chalk.default.magenta(`Application site is available at: http://localhost:${sitePort}`));
96
+ if (open && target !== "mrt") {
97
+ await (0, import_utils.launch)(sitePort);
98
+ }
73
99
  } catch (error) {
74
- import_shared_utils.logger.error(error);
100
+ import_diagnostics.logger.error(error);
75
101
  process.exit(1);
76
102
  }
77
103
  });
@@ -1,9 +1,11 @@
1
1
  import { Command } from 'commander';
2
- import { logger } from '@lwrjs/shared-utils';
2
+ import { logger } from '@lwrjs/diagnostics';
3
3
  import fs from 'fs-extra';
4
4
  import path from 'path';
5
5
  import { getDefaultBuildDirectory, getModeOption, getTargetOption } from '../utils.js';
6
6
  import { loadConfig } from '@lwrjs/config';
7
+ import { dedupeBundles } from '@lwrjs/tools';
8
+ const RUNTIME_CONFIG_SRC_DIR = 'config';
7
9
  export function createBuildCommand() {
8
10
  return new Command('build')
9
11
  .description('Build an LWR application')
@@ -36,11 +38,19 @@ export function createBuildCommand() {
36
38
  }
37
39
  const generatedSitePath = target === 'mrt' ? path.join(outputDir, 'site') : outputDir;
38
40
  const { generateStaticSite } = await import('@lwrjs/core');
41
+ const theLocales = locales
42
+ ? locales.map((l) => {
43
+ return { id: l };
44
+ })
45
+ : aConfig.appConfig.i18n?.locales || [];
46
+ const i18n = {
47
+ ...aConfig.appConfig.i18n,
48
+ locales: theLocales,
49
+ };
39
50
  try {
40
51
  // Use existing staticSiteGenerator config as defaults for now until we finish spikes on new design
41
- const _additionalRoutes = routes || aConfig.appConfig.staticSiteGenerator._additionalRoutePaths || [];
52
+ const _additionalRoutePaths = routes || aConfig.appConfig.staticSiteGenerator._additionalRoutePaths || [];
42
53
  const _additionalModules = modules || aConfig.appConfig.staticSiteGenerator._additionalModules || [];
43
- const theLocales = locales || aConfig.appConfig.staticSiteGenerator.locales || [];
44
54
  if (target === 'mrt') {
45
55
  // Pre-generate the LWC SSR package for MRT
46
56
  _additionalModules.push('@lwc/engine-server');
@@ -48,20 +58,24 @@ export function createBuildCommand() {
48
58
  const staticSiteGenerator = {
49
59
  outputDir: generatedSitePath,
50
60
  skipCleanOutputDir: true,
51
- _additionalRoutes,
61
+ _additionalRoutePaths,
52
62
  _additionalModules,
53
- locales: theLocales,
54
63
  };
55
64
  await generateStaticSite({
56
65
  serverMode: mode,
57
66
  staticSiteGenerator,
67
+ i18n,
58
68
  });
69
+ // Stage runtime configuration
70
+ stageProxyConfig(rootDir, outputDir);
59
71
  }
60
72
  catch (error) {
61
73
  logger.error(error);
62
74
  }
63
75
  // If target === MRT - we will always deploy to "app" dir
64
76
  if (target === 'mrt') {
77
+ // De-duplicate localized bundles
78
+ dedupeBundles(generatedSitePath, i18n);
65
79
  const config = aConfig.appConfig;
66
80
  const rootDir = config.rootDir;
67
81
  try {
@@ -125,9 +139,9 @@ export function createBuildCommand() {
125
139
  logger.info('[build] generating default.json');
126
140
  try {
127
141
  // TODO we could add some kind of merging later, but I think its too complex and not really worth it
128
- const configFile = path.join(rootDir, 'config', 'default.json');
129
- const outputConfigFile = path.join(outputDir, 'config', 'default.json');
130
- fs.ensureDirSync(path.join(outputDir, 'config'));
142
+ const configFile = path.join(rootDir, RUNTIME_CONFIG_SRC_DIR, 'default.json');
143
+ const outputConfigFile = path.join(outputDir, RUNTIME_CONFIG_SRC_DIR, 'default.json');
144
+ fs.ensureDirSync(path.join(outputDir, RUNTIME_CONFIG_SRC_DIR));
131
145
  if (fs.existsSync(configFile)) {
132
146
  // If they have defined their own config, use that, but display a warning
133
147
  logger.warn('[build] You have a config file already defined, using that rather than generating one.');
@@ -184,4 +198,19 @@ function getSuggestedNodeVersion() {
184
198
  }
185
199
  return `${majorVersion}.x`;
186
200
  }
201
+ function stageProxyConfig(rootDir, outputDir) {
202
+ // stage config/_proxy configuration
203
+ try {
204
+ const configFile = path.join(rootDir, RUNTIME_CONFIG_SRC_DIR, '_proxy');
205
+ const outputConfigFile = path.join(outputDir, RUNTIME_CONFIG_SRC_DIR, '_proxy');
206
+ if (fs.existsSync(configFile)) {
207
+ logger.info('[build] staging proxy configuration');
208
+ fs.ensureDirSync(path.join(outputDir, RUNTIME_CONFIG_SRC_DIR));
209
+ fs.copyFileSync(configFile, outputConfigFile);
210
+ }
211
+ }
212
+ catch (e) {
213
+ logger.error(e);
214
+ }
215
+ }
187
216
  //# sourceMappingURL=build.js.map
@@ -1,7 +1,8 @@
1
1
  import { Command } from 'commander';
2
2
  import chalk from 'chalk';
3
- import { logger } from '@lwrjs/shared-utils';
3
+ import { logger } from '@lwrjs/diagnostics';
4
4
  import { getModeOption, getPortOption, launch } from '../utils.js';
5
+ import { DEFAULT_PROXY_PORT, createProxyServer, findProxyConfiguration } from '@lwrjs/dev-proxy-server';
5
6
  export function createDevCommand() {
6
7
  return new Command('dev')
7
8
  .description('Starts an LWR server (defaults to dev mode)')
@@ -11,14 +12,39 @@ export function createDevCommand() {
11
12
  .action(async (options, cmd) => {
12
13
  const { createServer } = await import('@lwrjs/core');
13
14
  const { port, mode, rootDir, config, open } = cmd.optsWithGlobals();
15
+ // runtimePort can be undefined on invocation. The actual value is resolved via createServer()
16
+ let runtimePort = port;
17
+ const proxyPort = port === undefined ? DEFAULT_PROXY_PORT : port;
14
18
  try {
15
- const server = createServer({ port, serverMode: mode, rootDir, lwrConfigFile: config });
16
- await server.listen(async ({ serverMode, port }) => {
17
- console.log(chalk.green(`Running LWR at: http://localhost:${port} | mode: ${serverMode}`));
18
- if (open) {
19
- await launch(port);
20
- }
19
+ const proxyConfig = findProxyConfiguration(rootDir);
20
+ if (proxyConfig) {
21
+ runtimePort = proxyPort + 1;
22
+ // start an express proxy
23
+ const proxyServer = createProxyServer({
24
+ port: proxyPort,
25
+ // TODO: expose this as a configurable property.
26
+ defaultHost: `http://localhost:${runtimePort}`,
27
+ ...proxyConfig,
28
+ });
29
+ await proxyServer.listen(({ port: proxyPort }) => {
30
+ console.log(chalk.blue(`Running LWR Proxy at: http://localhost:${proxyPort}`));
31
+ });
32
+ }
33
+ const server = createServer({
34
+ port: runtimePort,
35
+ serverMode: mode,
36
+ rootDir,
37
+ lwrConfigFile: config,
21
38
  });
39
+ await server.listen(async ({ serverMode, port: appPort }) => {
40
+ runtimePort = appPort;
41
+ console.log(chalk.green(`Running LWR at: http://localhost:${appPort} | mode: ${serverMode}`));
42
+ });
43
+ const sitePort = proxyConfig !== undefined ? proxyPort : runtimePort;
44
+ console.log(chalk.magenta(`Application site is available at: http://localhost:${sitePort}`));
45
+ if (open) {
46
+ await launch(sitePort);
47
+ }
22
48
  }
23
49
  catch (error) {
24
50
  logger.error(error);
@@ -1,11 +1,12 @@
1
1
  import path from 'path';
2
- import { execSync } from 'child_process';
2
+ import { spawn } from 'child_process';
3
3
  import { Command } from 'commander';
4
4
  import chalk from 'chalk';
5
5
  import express from 'express';
6
6
  import fs from 'fs-extra';
7
- import { logger } from '@lwrjs/shared-utils';
7
+ import { logger } from '@lwrjs/diagnostics';
8
8
  import { getDefaultBuildDirectory, getModeOption, getPortOption, getTargetOption, launch } from '../utils.js';
9
+ import { createProxyServer, findProxyConfiguration, DEFAULT_PROXY_PORT } from '@lwrjs/dev-proxy-server';
9
10
  export function createPreviewCommand() {
10
11
  return new Command('preview')
11
12
  .aliases(['start'])
@@ -19,23 +20,44 @@ export function createPreviewCommand() {
19
20
  try {
20
21
  const { rootDir, config, port, target, mode, buildDir, open } = cmd.optsWithGlobals();
21
22
  const serverMode = mode;
23
+ // runtimePort can be undefined on invocation. The actual value is resolved via createServer()
24
+ let runtimePort = port;
25
+ const proxyPort = port === undefined ? DEFAULT_PROXY_PORT : port;
22
26
  // if you specified a buildDir in CLI and it doesn't exist, throw an error
23
27
  if (buildDir && !fs.existsSync(buildDir)) {
24
28
  throw new Error(`specified build directory '${buildDir}' does not exist`);
25
29
  }
26
30
  // Get the proper build directory
27
31
  const dir = buildDir ? buildDir : getDefaultBuildDirectory(rootDir, config, target);
28
- // The `open` option is not used when target === mrt because `pwa-kit` launches the browser.
29
- // The following env var will prevent `pwa-kit` from opening the browser, but we should work with
30
- // them on a better api to control this:
31
- // `process.env.NODE_ENV = 'test';`
32
+ const proxyConfig = findProxyConfiguration(rootDir, buildDir);
33
+ if (proxyConfig) {
34
+ runtimePort = proxyPort + 1;
35
+ // start an express proxy
36
+ const proxyServer = createProxyServer({
37
+ port: proxyPort,
38
+ // TODO: expose this as a configurable property.
39
+ defaultHost: `http://localhost:${runtimePort}`,
40
+ ...proxyConfig,
41
+ });
42
+ await proxyServer.listen(({ port: proxyPort }) => {
43
+ console.log(chalk.blue(`Running LWR Proxy at: http://localhost:${proxyPort}`));
44
+ });
45
+ }
32
46
  if (target === 'mrt') {
33
47
  const ssrJs = path.join(dir, 'ssr.js');
34
48
  // If ssr.js exists, run it
35
49
  if (fs.existsSync(ssrJs)) {
36
- execSync(`node ${ssrJs}`, {
50
+ // TODO: Add IPC to notify when server is started.
51
+ spawn('node', [`${ssrJs}`], {
52
+ cwd: process.cwd(),
37
53
  env: {
38
54
  ...process.env,
55
+ PORT: runtimePort,
56
+ // The `open` option is not used when target === mrt because `pwa-kit` launches the browser.
57
+ // The following env var will prevent `pwa-kit` from opening the browser, but we should work with
58
+ // them on a better api to control this:
59
+ // `process.env.NODE_ENV = 'test';`
60
+ NODE_ENV: 'test',
39
61
  },
40
62
  stdio: 'inherit',
41
63
  });
@@ -48,7 +70,12 @@ export function createPreviewCommand() {
48
70
  else {
49
71
  // Not mrt, just launch LWR server
50
72
  const { createServer } = await import('@lwrjs/core');
51
- const server = createServer({ port, serverMode, rootDir, lwrConfigFile: config });
73
+ const server = createServer({
74
+ port: runtimePort,
75
+ serverMode,
76
+ rootDir,
77
+ lwrConfigFile: config,
78
+ });
52
79
  const internalServer = server.getInternalServer();
53
80
  // TODO we could just run a static server vs running LWR services here
54
81
  if (fs.existsSync(dir)) {
@@ -56,13 +83,18 @@ export function createPreviewCommand() {
56
83
  logger.info('Using prebuilt content from directory: ' + dir);
57
84
  internalServer.use(express.static(dir));
58
85
  }
59
- await server.listen(async ({ serverMode, port }) => {
60
- console.log(chalk.green(`Running LWR at: http://localhost:${port} | mode: ${serverMode}`));
61
- if (open) {
62
- await launch(port);
63
- }
86
+ await server.listen(async ({ serverMode, port: appPort }) => {
87
+ runtimePort = appPort;
88
+ console.log(chalk.green(`Running LWR at: http://localhost:${appPort} | mode: ${serverMode}`));
64
89
  });
65
90
  }
91
+ const sitePort = proxyConfig !== undefined ? proxyPort : runtimePort;
92
+ console.log(chalk.magenta(`Application site is available at: http://localhost:${sitePort}`));
93
+ // TODO: Standardize support for the --open option for all server configurations.
94
+ // This opens to quickly for target=mrt configuration.
95
+ if (open && target !== 'mrt') {
96
+ await launch(sitePort);
97
+ }
66
98
  }
67
99
  catch (error) {
68
100
  logger.error(error);
package/package.json CHANGED
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "type": "module",
20
20
  "types": "build/es/index.d.ts",
21
- "version": "0.11.0-alpha.8",
21
+ "version": "0.11.0",
22
22
  "module": "build/es/index.js",
23
23
  "main": "build/cjs/index.cjs",
24
24
  "files": [
@@ -41,21 +41,22 @@
41
41
  }
42
42
  },
43
43
  "dependencies": {
44
- "@lwrjs/config": "0.11.0-alpha.8",
45
- "@lwrjs/core": "0.11.0-alpha.8",
46
- "@lwrjs/diagnostics": "0.11.0-alpha.8",
47
- "@lwrjs/shared-utils": "0.11.0-alpha.8",
48
- "@lwrjs/tools": "0.11.0-alpha.8",
44
+ "@lwrjs/config": "0.11.0",
45
+ "@lwrjs/core": "0.11.0",
46
+ "@lwrjs/dev-proxy-server": "0.11.0",
47
+ "@lwrjs/diagnostics": "0.11.0",
48
+ "@lwrjs/shared-utils": "0.11.0",
49
+ "@lwrjs/tools": "0.11.0",
49
50
  "chalk": "^4.1.0",
50
51
  "commander": "^10.0.0",
51
52
  "fs-extra": "^11.1.1"
52
53
  },
53
54
  "devDependencies": {
54
55
  "@commander-js/extra-typings": "^10.0.2",
55
- "@lwrjs/types": "0.11.0-alpha.8"
56
+ "@lwrjs/types": "0.11.0"
56
57
  },
57
58
  "engines": {
58
59
  "node": ">=16.0.0"
59
60
  },
60
- "gitHead": "bba3cfa996e84ee702f287e7e7b6361b807434db"
61
+ "gitHead": "fbc883ea90a12672ce6f1adc2201144fda8762bd"
61
62
  }