@lwrjs/core 0.7.0-alpha.0 → 0.7.0-alpha.11

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.
@@ -55,6 +55,7 @@ var DEFAULT_DATA_DIR = "$rootDir/src/data";
55
55
  var DEFAULT_MODULE_PROVIDERS = [
56
56
  "@lwrjs/app-service/moduleProvider",
57
57
  "@lwrjs/lwc-ssr/moduleProvider",
58
+ "@lwrjs/router/module-provider",
58
59
  "@lwrjs/lwc-module-provider",
59
60
  "@lwrjs/npm-module-provider"
60
61
  ];
@@ -294,12 +295,17 @@ function normalizeConfig(config) {
294
295
  lwc: normalizeLwcConfig(mergeLWCConfigs(lwrJsonConfig, config)),
295
296
  bundleConfig: mergeBundleConfig(lwrJsonConfig, config),
296
297
  locker: mergeLockerConfig(lwrJsonConfig, config),
298
+ staticSiteGenerator: {
299
+ ...DEFAULT_GENERATOR_CONFIG,
300
+ ...lwrJsonConfig?.staticSiteGenerator,
301
+ ...config?.staticSiteGenerator
302
+ },
297
303
  rootDir
298
304
  };
299
305
  const assets = normalizeAssetsDir(mergedLwrGlobalConfig.assets, rootDir);
300
306
  const contentDir = (0, import_shared_utils.normalizeDirectory)(mergedLwrGlobalConfig.contentDir, rootDir);
301
307
  const layoutsDir = (0, import_shared_utils.normalizeDirectory)(mergedLwrGlobalConfig.layoutsDir, rootDir);
302
- const amdLoader = (0, import_shared_utils.getExperimentalFeatures)().ENABLE_FINGERPRINTS ? DEFAULT_AMD_LOADER : DEFAULT_AMD_LOADER_LEGACY;
308
+ const amdLoader = (0, import_shared_utils.getFeatureFlags)().LEGACY_LOADER ? DEFAULT_AMD_LOADER_LEGACY : DEFAULT_AMD_LOADER;
303
309
  return {
304
310
  ...mergedLwrGlobalConfig,
305
311
  assets,
@@ -75,7 +75,7 @@ async function initContext(app, server, rawLwrConfig) {
75
75
  lwrVersion,
76
76
  debug: false,
77
77
  serverMode,
78
- experimental_features: (0, import_shared_utils.getExperimentalFeatures)()
78
+ featureFlags: (0, import_shared_utils.getFeatureFlags)()
79
79
  };
80
80
  const hookProviders = await getServices(rawLwrConfig.hooks, void 0, rawLwrConfig);
81
81
  const {lwrConfig, dataConfig, runtimeConfig} = await (0, import_hooks.runConfigurationsHook)(hookProviders, rawLwrConfig, rawDataConfig, rawRuntimeEnvConfig);
@@ -259,7 +259,7 @@ async function generateStaticSite(config) {
259
259
  await new import_static_generation.default().buildStaticApplication(lwrApp.getConfig(), dispatcher);
260
260
  }
261
261
  function overrideConfigAsSrc(lwrApp) {
262
- if ((0, import_shared_utils.getExperimentalFeatures)().ENABLE_FINGERPRINTS) {
262
+ if (!(0, import_shared_utils.getFeatureFlags)().LEGACY_LOADER) {
263
263
  const normalizedConfig = lwrApp.getConfig();
264
264
  const routes = normalizedConfig.routes || [];
265
265
  for (const route of routes) {
@@ -102,7 +102,7 @@ function apiMiddleware(app, context) {
102
102
  res.type("application/javascript").send(bundleDef.code);
103
103
  } catch (e) {
104
104
  console.log(e);
105
- const error = (0, import_utils.createReturnStatus)(`bundle for "${moduleId?.specifier || req.params?.specifier}"`, e);
105
+ const error = (0, import_diagnostics.createReturnStatus)(`bundle for "${moduleId?.specifier || req.params?.specifier}"`, e);
106
106
  res.status(error.status).send(error.message);
107
107
  }
108
108
  });
@@ -138,7 +138,7 @@ function apiMiddleware(app, context) {
138
138
  }
139
139
  } catch (e) {
140
140
  console.log(e);
141
- const error = (0, import_utils.createReturnStatus)(`bundle for "${moduleId?.specifier || req.params?.specifier}"`, e);
141
+ const error = (0, import_diagnostics.createReturnStatus)(`bundle for "${moduleId?.specifier || req.params?.specifier}"`, e);
142
142
  res.status(error.status).send(error.message);
143
143
  }
144
144
  });
@@ -169,7 +169,7 @@ function apiMiddleware(app, context) {
169
169
  res.type("application/json").send(bundleDef.map);
170
170
  } catch (e) {
171
171
  console.log(e);
172
- const error = (0, import_utils.createReturnStatus)(`bundle sourcemap for "${moduleId?.specifier || req.params?.specifier}"`, e);
172
+ const error = (0, import_diagnostics.createReturnStatus)(`bundle sourcemap for "${moduleId?.specifier || req.params?.specifier}"`, e);
173
173
  res.status(error.status).send(error.message);
174
174
  }
175
175
  });
@@ -211,7 +211,7 @@ function apiMiddleware(app, context) {
211
211
  }
212
212
  } catch (e) {
213
213
  console.log(e);
214
- const error = (0, import_utils.createReturnStatus)(`module "${moduleId?.specifier || req.params?.specifier}"`, e);
214
+ const error = (0, import_diagnostics.createReturnStatus)(`module "${moduleId?.specifier || req.params?.specifier}"`, e);
215
215
  res.status(error.status).send(error.message);
216
216
  }
217
217
  });
@@ -247,14 +247,18 @@ function apiMiddleware(app, context) {
247
247
  }
248
248
  } catch (e) {
249
249
  console.log(e);
250
- const error = (0, import_utils.createReturnStatus)(`module "${moduleId?.specifier || req.params?.specifier}"`, e);
250
+ const error = (0, import_diagnostics.createReturnStatus)(`module "${moduleId?.specifier || req.params?.specifier}"`, e);
251
251
  res.status(error.status).send(error.message);
252
252
  }
253
253
  });
254
254
  app.get([
255
+ `/:apiVersion/mapping/:format/:compat/l/:locale/e/:environment/bi/:bundleSpecifier/mp/:specifiers`,
255
256
  `/:apiVersion/mapping/:format/:compat/l/:locale/e/:environment/mp/:specifiers`,
257
+ `/:apiVersion/mapping/:format/:compat/l/:locale/bi/:bundleSpecifier/mp/:specifiers`,
258
+ `/:apiVersion/mapping/:format/:compat/e/:environment/bi/:bundleSpecifier/mp/:specifiers`,
256
259
  `/:apiVersion/mapping/:format/:compat/l/:locale/mp/:specifiers`,
257
260
  `/:apiVersion/mapping/:format/:compat/e/:environment/mp/:specifiers`,
261
+ `/:apiVersion/mapping/:format/:compat/bi/:bundleSpecifier/mp/:specifiers`,
258
262
  `/:apiVersion/mapping/:format/:compat/mp/:specifiers`
259
263
  ], async (req, res) => {
260
264
  const requestContext = req.getRuntimeContext(defaultRuntimeEnvironment);
@@ -272,7 +276,7 @@ function apiMiddleware(app, context) {
272
276
  res.status(200).type("application/json").send(importMetadata);
273
277
  } catch (e) {
274
278
  console.log(e);
275
- const error = (0, import_utils.createReturnStatus)(`mappings for "${JSON.stringify(moduleIds || req.params?.specifiers)}"`, e);
279
+ const error = (0, import_diagnostics.createReturnStatus)(`mappings for "${JSON.stringify(moduleIds || req.params?.specifiers)}"`, e);
276
280
  res.status(error.status).send(error.message);
277
281
  }
278
282
  });
@@ -303,7 +307,7 @@ function apiMiddleware(app, context) {
303
307
  res.setMetadata({resource});
304
308
  } catch (e) {
305
309
  console.log(e);
306
- const error = (0, import_utils.createReturnStatus)(`resource "${resourceId?.specifier || req.params?.specifier}"`, e);
310
+ const error = (0, import_diagnostics.createReturnStatus)(`resource "${resourceId?.specifier || req.params?.specifier}"`, e);
307
311
  res.status(error.status).send(error.message);
308
312
  }
309
313
  });
@@ -326,7 +330,7 @@ function apiMiddleware(app, context) {
326
330
  res.stream(assetObj.stream());
327
331
  } catch (e) {
328
332
  console.log(e);
329
- const error = (0, import_utils.createReturnStatus)(`asset at "${specifier}"`, e);
333
+ const error = (0, import_diagnostics.createReturnStatus)(`asset at "${specifier}"`, e);
330
334
  res.status(error.status).send(error.message);
331
335
  }
332
336
  });
@@ -348,7 +352,7 @@ function apiMiddleware(app, context) {
348
352
  res.stream(assetObj.stream());
349
353
  } catch (e) {
350
354
  console.log(e);
351
- const error = (0, import_utils.createReturnStatus)(`asset at "${specifier}"`, e);
355
+ const error = (0, import_diagnostics.createReturnStatus)(`asset at "${specifier}"`, e);
352
356
  res.status(error.status).send(error.message);
353
357
  }
354
358
  });
@@ -42,6 +42,7 @@ function uiMiddleware(app, context) {
42
42
  res.status(400).send({error: "Accept header and json query parameter are incompatible"});
43
43
  return;
44
44
  }
45
+ req.params.bundleSpecifier = defaultRuntimeEnvironment.bundle ? "0" : void 0;
45
46
  const {runtimeEnvironment, runtimeParams} = req.getRuntimeContext(defaultRuntimeEnvironment);
46
47
  const targetEnvironment = runtimeParams.environment;
47
48
  if (!(0, import_utils.isSupportedEnvironment)(environmentConfig, targetEnvironment)) {
@@ -89,6 +90,7 @@ function uiMiddleware(app, context) {
89
90
  }
90
91
  }
91
92
  async function sendConfigurationResponse(req, res, defaultStatus = 200) {
93
+ req.params.bundleSpecifier = defaultRuntimeEnvironment.bundle ? "0" : void 0;
92
94
  const {runtimeEnvironment, runtimeParams} = req.getRuntimeContext(defaultRuntimeEnvironment);
93
95
  const {appId, encodedViewPath} = req.params;
94
96
  const route = routes.find((route2) => route2.id === appId);
@@ -24,31 +24,11 @@ var __toModule = (module2) => {
24
24
  // packages/@lwrjs/core/src/middlewares/utils.ts
25
25
  __markAsModule(exports);
26
26
  __export(exports, {
27
- createReturnStatus: () => createReturnStatus,
28
27
  getRequestProperties: () => getRequestProperties,
29
28
  isSupportedEnvironment: () => isSupportedEnvironment
30
29
  });
31
- var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
32
30
  var import_path_to_regexp = __toModule(require("path-to-regexp"));
33
31
  var import_qs = __toModule(require("qs"));
34
- var import_dompurify = __toModule(require("dompurify"));
35
- var import_jsdom = __toModule(require("jsdom"));
36
- var window = new import_jsdom.JSDOM("").window;
37
- var DOMPurify = (0, import_dompurify.default)(window);
38
- function createReturnStatus(name, error) {
39
- let returnStatus = {status: 501, message: ""};
40
- if ((0, import_diagnostics.isNodeError)(error) && error.code === "NO_LWC_MODULE_FOUND") {
41
- returnStatus = {status: 404, message: import_diagnostics.descriptions.UNRESOLVABLE.LWC_MODULE(name).message};
42
- } else if (error instanceof import_diagnostics.LwrUnresolvableError && error.diagnostics[0].description.category === "lwrUnresolvable/invalid") {
43
- returnStatus = {status: 400, message: error.message};
44
- } else if (error instanceof import_diagnostics.LwrUnresolvableError) {
45
- returnStatus = {status: 404, message: error.message};
46
- } else {
47
- returnStatus = {status: 500, message: import_diagnostics.descriptions.UNRESOLVABLE.SERVER_ERROR(name).message};
48
- }
49
- returnStatus.message = DOMPurify.sanitize(returnStatus.message);
50
- return returnStatus;
51
- }
52
32
  function getRequestProperties(pattern, req) {
53
33
  const {url = "/"} = req;
54
34
  const [pathname, search] = url.split("?");
@@ -29,11 +29,20 @@ __export(exports, {
29
29
  var import_static_generation = __toModule(require("./static-generation.cjs"));
30
30
  var import_dir = __toModule(require("./utils/dir.cjs"));
31
31
  var import_network_dispatcher = __toModule(require("./utils/network-dispatcher.cjs"));
32
+ var import_env_config = __toModule(require("../env-config.cjs"));
32
33
  async function warmupServer(config, internalRequestKey) {
33
34
  console.log("[Server Warmup] starting");
34
- const {routes, staticSiteGenerator, port} = config;
35
+ const {routes, staticSiteGenerator, port, apiVersion, basePath, lwrVersion, serverMode} = config;
35
36
  staticSiteGenerator.outputDir = import_dir.skipDirCreation;
36
37
  const urlRewriteMap = new Map();
37
- await new import_static_generation.default().generateRoutes(staticSiteGenerator, routes, new import_network_dispatcher.default(port, internalRequestKey), staticSiteGenerator.outputDir, urlRewriteMap);
38
+ const runtimeEnvironment = {
39
+ ...(0, import_env_config.explodeMode)(serverMode),
40
+ apiVersion,
41
+ basePath,
42
+ lwrVersion,
43
+ debug: false,
44
+ serverMode
45
+ };
46
+ await new import_static_generation.default().generateRoutes(runtimeEnvironment, staticSiteGenerator, routes, new import_network_dispatcher.default(port, internalRequestKey), staticSiteGenerator.outputDir, urlRewriteMap);
38
47
  console.log("[Server Warmup] complete");
39
48
  }
@@ -33,6 +33,7 @@ var import_path = __toModule(require("path"));
33
33
  var import_fs_extra = __toModule(require("fs-extra"));
34
34
  var import_stream = __toModule(require("./utils/stream.cjs"));
35
35
  var import_dir = __toModule(require("./utils/dir.cjs"));
36
+ var import_env_config = __toModule(require("../env-config.cjs"));
36
37
  var SiteGenerator = class {
37
38
  async buildStaticApplication(config, dispatcher) {
38
39
  const startTime = import_perf_hooks.performance.now();
@@ -45,29 +46,45 @@ var SiteGenerator = class {
45
46
  console.log(`[INFO] Clear Output Location: ${outputDir}`);
46
47
  import_fs_extra.default.rmSync(outputDir, {recursive: true, force: true});
47
48
  const urlRewriteMap = new Map();
48
- await this.generateRoutes(staticSiteGenerator, routes, dispatcher, outputDir, urlRewriteMap);
49
+ const {apiVersion, basePath, lwrVersion, serverMode} = config;
50
+ const runtimeEnvironment = {
51
+ ...(0, import_env_config.explodeMode)(serverMode),
52
+ apiVersion,
53
+ basePath,
54
+ lwrVersion,
55
+ debug: false,
56
+ serverMode
57
+ };
58
+ await this.generateRoutes(runtimeEnvironment, staticSiteGenerator, routes, dispatcher, outputDir, urlRewriteMap);
49
59
  this.writeNetlifyRedirectConfig(outputDir, urlRewriteMap);
50
60
  this.copyAssets(assets, outputDir);
51
61
  const endTime = import_perf_hooks.performance.now();
52
62
  const timeDiff = (endTime - startTime) / 1e3;
53
63
  console.log(`[Static Generation] complete in ${Math.round(timeDiff)} seconds`);
54
64
  }
55
- async generateRoutes(staticSiteGenerator, routes, dispatcher, outputDir, urlRewriteMap = new Map()) {
65
+ async generateRoutes(runtimeEnvironment, staticSiteGenerator, routes, dispatcher, outputDir, urlRewriteMap = new Map()) {
56
66
  if (!staticSiteGenerator.locales) {
57
67
  staticSiteGenerator.locales = ["en-US"];
58
68
  }
59
69
  const generateUrl = this.createGenerateURLFunction(dispatcher);
60
70
  for (const locale of staticSiteGenerator.locales) {
61
71
  for (const route of routes) {
62
- const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap);
72
+ const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap, runtimeEnvironment);
63
73
  await generateUrl(route.path, siteConfig);
64
74
  }
65
75
  if (staticSiteGenerator._additionalRoutePaths) {
66
76
  for (const uri of staticSiteGenerator._additionalRoutePaths) {
67
- const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap);
77
+ const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap, runtimeEnvironment);
68
78
  await generateUrl(uri, siteConfig);
69
79
  }
70
80
  }
81
+ const {_additionalModules} = staticSiteGenerator;
82
+ if (_additionalModules) {
83
+ for (const specifier of _additionalModules) {
84
+ const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap, runtimeEnvironment);
85
+ await this.dispatchJSResourceRecursive(specifier, dispatcher, siteConfig, true);
86
+ }
87
+ }
71
88
  }
72
89
  }
73
90
  createGenerateURLFunction(dispatcher) {
@@ -88,7 +105,14 @@ var SiteGenerator = class {
88
105
  console.error("Skipped url with variable path segment: " + url);
89
106
  return;
90
107
  }
91
- const context = await dispatcher.dispatchUrl(url, "GET", siteConfig.locale);
108
+ let context;
109
+ context = await dispatcher.dispatchUrl(url, "GET", siteConfig.locale);
110
+ if (context?.fs?.headers?.Location) {
111
+ const redirectUrl = context?.fs?.headers?.Location;
112
+ url = redirectUrl;
113
+ const redirectContext = await dispatcher.dispatchUrl(url, "GET", siteConfig.locale);
114
+ context = redirectContext;
115
+ }
92
116
  const {resourceType} = resourceOpts;
93
117
  if (resourceType === "route") {
94
118
  await this.handleHtmlResource(url, context, siteConfig, dispatcher);
@@ -139,11 +163,12 @@ var SiteGenerator = class {
139
163
  const statusCode = context.response?.status;
140
164
  if (statusCode === 200) {
141
165
  const newImportMetadata = context.fs?.body;
166
+ let filteredImportMetadata;
142
167
  if (!importMetatdata) {
143
- console.warn("[WARN] Import metadata collector was never initialized");
144
- return;
168
+ filteredImportMetadata = newImportMetadata;
169
+ } else {
170
+ filteredImportMetadata = importMetatdata.addAdditionalMetadata(newImportMetadata);
145
171
  }
146
- const filteredImportMetadata = importMetatdata.addAdditionalMetadata(newImportMetadata);
147
172
  const dispatchRequests = [];
148
173
  for (const uri of Object.keys(filteredImportMetadata.imports)) {
149
174
  dispatchRequests.push(this.dispatchResourceRecursive(uri, dispatcher, {resourceType: "js"}, siteConfig));
@@ -173,7 +198,6 @@ var SiteGenerator = class {
173
198
  }
174
199
  }
175
200
  async handleViewDefinition(viewDefinition, siteConfig, dispatcher) {
176
- siteConfig.endpoints = viewDefinition.viewRecord.endpoints;
177
201
  if (viewDefinition.viewRecord.importMetadata) {
178
202
  siteConfig.importMetadata = new ViewImportMetadataImpl(viewDefinition.viewRecord.importMetadata);
179
203
  }
@@ -224,11 +248,11 @@ var SiteGenerator = class {
224
248
  }
225
249
  await Promise.all(dispatchRequests);
226
250
  }
227
- async dispatchJSResourceRecursive(jsUri, dispatcher, siteConfig) {
251
+ async dispatchJSResourceRecursive(jsUri, dispatcher, siteConfig, isAdditionalModulesRequest) {
228
252
  if (jsUri.startsWith("/")) {
229
253
  await this.dispatchResourceRecursive(jsUri, dispatcher, {resourceType: "js"}, siteConfig);
230
254
  } else {
231
- const supportsFingerprints = siteConfig.experimentalFeatures?.ENABLE_FINGERPRINTS;
255
+ const supportsFingerprints = !siteConfig.featureFlags?.LEGACY_LOADER;
232
256
  if (supportsFingerprints) {
233
257
  const mappingEndpoint = siteConfig.endpoints?.uris?.mapping;
234
258
  if (mappingEndpoint) {
@@ -237,6 +261,9 @@ var SiteGenerator = class {
237
261
  } else {
238
262
  console.warn('[WARN] Unable to fetch mapping for bare specifier or variable dynamic import: "' + jsUri + '"');
239
263
  }
264
+ } else if (isAdditionalModulesRequest) {
265
+ const uri = `${siteConfig.endpoints?.uris.legacyDefault}${encodeURIComponent(jsUri)}`;
266
+ await this.dispatchResourceRecursive(uri, dispatcher, {resourceType: "js"}, siteConfig);
240
267
  }
241
268
  }
242
269
  }
@@ -279,31 +306,38 @@ var SiteGenerator = class {
279
306
  throw new Error("Could not find assets to copy at path: " + assetSrcDir);
280
307
  }
281
308
  } catch (e) {
282
- console.error("Error occurred processing asset config: " + asset);
309
+ console.error("Error occurred processing asset config: " + JSON.stringify(asset));
283
310
  console.error(e);
284
311
  }
285
312
  }
286
313
  }
287
- createSiteConfig(outputDir, locale, urlRewriteMap) {
288
- const experimentalFeatures = this.filterExperimentalFeatures();
314
+ createSiteConfig(outputDir, locale, urlRewriteMap, runtimeEnvironment) {
315
+ const featureFlags = this.filterFeatureFlags();
316
+ const endpoints = {
317
+ uris: {
318
+ legacyDefault: (0, import_shared_utils.getModuleUriPrefix)(runtimeEnvironment, {locale}),
319
+ mapping: (0, import_shared_utils.getMappingUriPrefix)(runtimeEnvironment, {locale})
320
+ }
321
+ };
289
322
  return {
290
323
  outputDir,
291
324
  viewPaths: new Set(),
292
325
  visitedUrls: new Set(),
293
326
  locale,
294
327
  urlRewriteMap,
295
- ...experimentalFeatures
328
+ endpoints,
329
+ ...featureFlags
296
330
  };
297
331
  }
298
- filterExperimentalFeatures() {
299
- if ((0, import_shared_utils.getExperimentalFeatures)().ENABLE_FINGERPRINTS) {
300
- return {experimentalFeatures: {ENABLE_FINGERPRINTS: true}};
332
+ filterFeatureFlags() {
333
+ if ((0, import_shared_utils.getFeatureFlags)().LEGACY_LOADER) {
334
+ return {featureFlags: {LEGACY_LOADER: true}};
301
335
  } else {
302
336
  return void 0;
303
337
  }
304
338
  }
305
339
  addAdditionalImportMetadataToViewConfig(siteConfig) {
306
- const supportsFingerprints = siteConfig.experimentalFeatures?.ENABLE_FINGERPRINTS;
340
+ const supportsFingerprints = !siteConfig.featureFlags?.LEGACY_LOADER;
307
341
  const additionalImportMetadata = siteConfig?.importMetadata?.getAdditionalImportMetadata();
308
342
  if (supportsFingerprints && siteConfig.viewConfigPath && additionalImportMetadata?.imports && Object.keys(additionalImportMetadata.imports).length > 0) {
309
343
  const imports = additionalImportMetadata.imports ? JSON.stringify(additionalImportMetadata.imports) : "{}";
@@ -26,6 +26,7 @@ __markAsModule(exports);
26
26
  __export(exports, {
27
27
  ASSET_DIR_ATTRIBUTE_KEYS: () => ASSET_DIR_ATTRIBUTE_KEYS,
28
28
  ASSET_FILE_ATTRIBUTE_KEYS: () => ASSET_FILE_ATTRIBUTE_KEYS,
29
+ BASE_PATH_REGEX: () => BASE_PATH_REGEX,
29
30
  BOOTSTRAP_ATTRIBUTE_KEYS: () => BOOTSTRAP_ATTRIBUTE_KEYS,
30
31
  ERROR_ROUTE_ATTRIBUTE_KEYS: () => ERROR_ROUTE_ATTRIBUTE_KEYS,
31
32
  LOCKER_ATTRIBUTE_KEYS: () => LOCKER_ATTRIBUTE_KEYS,
@@ -111,6 +112,7 @@ var SPECIFIER_REGEX = /^@?[\w-]+(\/[\w-]+)*$/;
111
112
  function isNotEmptyString(node) {
112
113
  return node.type === "string" && node.value.length > 0;
113
114
  }
115
+ var BASE_PATH_REGEX = /^(\/[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$/g;
114
116
  var ValidationContext = class {
115
117
  constructor(sourceText) {
116
118
  this.diagnostics = [];
@@ -224,6 +226,24 @@ var ValidationContext = class {
224
226
  });
225
227
  }
226
228
  }
229
+ assertIsBasePath(node, property) {
230
+ if (!node) {
231
+ return;
232
+ }
233
+ if (node.type !== "string") {
234
+ this.diagnostics.push({
235
+ description: import_diagnostics.descriptions.CONFIG_PARSER.INCORRECT_NODE_TYPE(property, "string", node.type),
236
+ location: this.getLocationFromNode(node)
237
+ });
238
+ } else if (node.value === "") {
239
+ return;
240
+ } else if (node.value.match(BASE_PATH_REGEX) === null) {
241
+ this.diagnostics.push({
242
+ description: import_diagnostics.descriptions.CONFIG_PARSER.INVALID_BASEPATH(property, node.value),
243
+ location: this.getLocationFromNode(node)
244
+ });
245
+ }
246
+ }
227
247
  assertNotEmptyString(node, property) {
228
248
  if (!node) {
229
249
  return;
@@ -168,6 +168,7 @@ function validateRoot(node, validationContext, preMerge) {
168
168
  validationContext.assertArrayOfServices((0, import_jsonc_parser.findNodeAtLocation)(node, ["assetProviders"]), "assetProviders");
169
169
  validationContext.assertNotEmptyArray((0, import_jsonc_parser.findNodeAtLocation)(node, ["lwc", "modules"]), "lwc.modules");
170
170
  validationContext.assertIsEnvironment((0, import_jsonc_parser.findNodeAtLocation)(node, ["environment"]), "environment");
171
+ validationContext.assertIsBasePath((0, import_jsonc_parser.findNodeAtLocation)(node, ["basePath"]), "basePath");
171
172
  }
172
173
  function validateLwrAppConfig(jsonSourceText, phase) {
173
174
  const errors = [];
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { createRequire } from 'module';
4
- import { ASSETS_CACHE_DIR, readFile, normalizeDirectory, normalizeResourcePath, DEFAULT_LWR_BOOTSTRAP_CONFIG, DEFAULT_LWR_LOCKER_CONFIG, DEFAULT_LOCKER_TRUSTED_CMP, normalizeInterchangeableModuleConfig, getExperimentalFeatures, } from '@lwrjs/shared-utils';
4
+ import { ASSETS_CACHE_DIR, readFile, normalizeDirectory, normalizeResourcePath, DEFAULT_LWR_BOOTSTRAP_CONFIG, DEFAULT_LWR_LOCKER_CONFIG, DEFAULT_LOCKER_TRUSTED_CMP, normalizeInterchangeableModuleConfig, getFeatureFlags, } from '@lwrjs/shared-utils';
5
5
  import { rootPath, version } from '@lwrjs/core/package';
6
6
  import { validateLwrAppConfig } from './validation/app-config.js';
7
7
  import { LwrConfigValidationError } from '@lwrjs/diagnostics';
@@ -28,6 +28,7 @@ const DEFAULT_DATA_DIR = '$rootDir/src/data';
28
28
  const DEFAULT_MODULE_PROVIDERS = [
29
29
  '@lwrjs/app-service/moduleProvider',
30
30
  '@lwrjs/lwc-ssr/moduleProvider',
31
+ '@lwrjs/router/module-provider',
31
32
  '@lwrjs/lwc-module-provider',
32
33
  '@lwrjs/npm-module-provider',
33
34
  ];
@@ -305,15 +306,18 @@ export function normalizeConfig(config) {
305
306
  lwc: normalizeLwcConfig(mergeLWCConfigs(lwrJsonConfig, config)),
306
307
  bundleConfig: mergeBundleConfig(lwrJsonConfig, config),
307
308
  locker: mergeLockerConfig(lwrJsonConfig, config),
309
+ staticSiteGenerator: {
310
+ ...DEFAULT_GENERATOR_CONFIG,
311
+ ...lwrJsonConfig?.staticSiteGenerator,
312
+ ...config?.staticSiteGenerator,
313
+ },
308
314
  rootDir,
309
315
  };
310
316
  // Normalize entries (eg: parse full file paths, etc)
311
317
  const assets = normalizeAssetsDir(mergedLwrGlobalConfig.assets, rootDir);
312
318
  const contentDir = normalizeDirectory(mergedLwrGlobalConfig.contentDir, rootDir);
313
319
  const layoutsDir = normalizeDirectory(mergedLwrGlobalConfig.layoutsDir, rootDir);
314
- const amdLoader = getExperimentalFeatures().ENABLE_FINGERPRINTS
315
- ? DEFAULT_AMD_LOADER
316
- : DEFAULT_AMD_LOADER_LEGACY;
320
+ const amdLoader = getFeatureFlags().LEGACY_LOADER ? DEFAULT_AMD_LOADER_LEGACY : DEFAULT_AMD_LOADER;
317
321
  return {
318
322
  ...mergedLwrGlobalConfig,
319
323
  assets,
package/build/es/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { deepFreeze, getExperimentalFeatures, DEFAULT_LWR_BOOTSTRAP_CONFIG } from '@lwrjs/shared-utils';
1
+ import { deepFreeze, getFeatureFlags, DEFAULT_LWR_BOOTSTRAP_CONFIG } from '@lwrjs/shared-utils';
2
2
  import { LwrCompiler } from '@lwrjs/compiler';
3
3
  import { LwrModuleBundler } from '@lwrjs/module-bundler';
4
4
  import { LwrModuleRegistry } from '@lwrjs/module-registry';
@@ -50,7 +50,7 @@ async function initContext(app, server, rawLwrConfig) {
50
50
  lwrVersion,
51
51
  debug: false,
52
52
  serverMode,
53
- experimental_features: getExperimentalFeatures(),
53
+ featureFlags: getFeatureFlags(),
54
54
  };
55
55
  const hookProviders = await getServices(rawLwrConfig.hooks, undefined, rawLwrConfig);
56
56
  const { lwrConfig, dataConfig, runtimeConfig } = await runConfigurationsHook(hookProviders, rawLwrConfig, rawDataConfig, rawRuntimeEnvConfig);
@@ -233,7 +233,7 @@ export async function generateStaticSite(config) {
233
233
  * Create normalized config for static generation forcing the app config to come as src
234
234
  */
235
235
  function overrideConfigAsSrc(lwrApp) {
236
- if (getExperimentalFeatures().ENABLE_FINGERPRINTS) {
236
+ if (!getFeatureFlags().LEGACY_LOADER) {
237
237
  const normalizedConfig = lwrApp.getConfig();
238
238
  const routes = normalizedConfig.routes || [];
239
239
  for (const route of routes) {
@@ -1,6 +1,6 @@
1
- import { LwrUnresolvableError, createSingleDiagnosticError as createDiagnostic, descriptions, } from '@lwrjs/diagnostics';
1
+ import { createReturnStatus, LwrUnresolvableError, createSingleDiagnosticError as createDiagnostic, descriptions, } from '@lwrjs/diagnostics';
2
2
  import { LATEST_SIGNATURE, explodeSpecifier, getImportMetadataMappings, serializeModuleToJson, getModuleIdentity, getResourceIdentity, getAssetIdentity, getMappingIdentity, getVersionedModuleId, } from '@lwrjs/shared-utils';
3
- import { createReturnStatus, isSupportedEnvironment } from './utils.js';
3
+ import { isSupportedEnvironment } from './utils.js';
4
4
  export default function apiMiddleware(app, context) {
5
5
  const { appConfig: { environment: environmentConfig }, moduleRegistry, moduleBundler, resourceRegistry, runtimeEnvironment: defaultRuntimeEnvironment, } = context;
6
6
  const errors = descriptions.UNRESOLVABLE;
@@ -276,15 +276,19 @@ export default function apiMiddleware(app, context) {
276
276
  }
277
277
  });
278
278
  // Mapping Services
279
- // /{apiversion}/mapping/{format}/{compat}/l/{language}/mp/{specifiers}
279
+ // /{apiversion}/mapping/{format}/{compat}(/l/{language})?(/e/{environment})?(/bi/{bundleStrategyId})?/mp/{specifiers}
280
280
  app.get([
281
- // Full URL
281
+ // Full URL (3 optional segments)
282
+ `/:apiVersion/mapping/:format/:compat/l/:locale/e/:environment/bi/:bundleSpecifier/mp/:specifiers`,
283
+ // With 2 optional segments: l & e, l & bi, e & bi
282
284
  `/:apiVersion/mapping/:format/:compat/l/:locale/e/:environment/mp/:specifiers`,
283
- // Without Environment
285
+ `/:apiVersion/mapping/:format/:compat/l/:locale/bi/:bundleSpecifier/mp/:specifiers`,
286
+ `/:apiVersion/mapping/:format/:compat/e/:environment/bi/:bundleSpecifier/mp/:specifiers`,
287
+ // With 1 optional segment
284
288
  `/:apiVersion/mapping/:format/:compat/l/:locale/mp/:specifiers`,
285
- // Without Locale
286
289
  `/:apiVersion/mapping/:format/:compat/e/:environment/mp/:specifiers`,
287
- // Without Optional Segments
290
+ `/:apiVersion/mapping/:format/:compat/bi/:bundleSpecifier/mp/:specifiers`,
291
+ // With 0 optional segments
288
292
  `/:apiVersion/mapping/:format/:compat/mp/:specifiers`,
289
293
  ], async (req, res) => {
290
294
  const requestContext = req.getRuntimeContext(defaultRuntimeEnvironment);
@@ -14,6 +14,8 @@ export default function uiMiddleware(app, context) {
14
14
  res.status(400).send({ error: 'Accept header and json query parameter are incompatible' });
15
15
  return;
16
16
  }
17
+ // UI URIs do not contain bundle IDs, so always use the environment default
18
+ req.params.bundleSpecifier = defaultRuntimeEnvironment.bundle ? '0' : undefined;
17
19
  const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(defaultRuntimeEnvironment);
18
20
  const targetEnvironment = runtimeParams.environment;
19
21
  if (!isSupportedEnvironment(environmentConfig, targetEnvironment)) {
@@ -67,6 +69,8 @@ export default function uiMiddleware(app, context) {
67
69
  }
68
70
  }
69
71
  async function sendConfigurationResponse(req, res, defaultStatus = 200) {
72
+ // UI URIs do not contain bundle IDs, so always use the environment default
73
+ req.params.bundleSpecifier = defaultRuntimeEnvironment.bundle ? '0' : undefined;
70
74
  const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(defaultRuntimeEnvironment);
71
75
  const { appId, encodedViewPath } = req.params;
72
76
  // Match the route id
@@ -2,16 +2,6 @@
2
2
  import http from 'http';
3
3
  import { EnvironmentConfig } from '@lwrjs/types';
4
4
  import qs from 'qs';
5
- /**
6
- * Create a status object Express can return when there is an error
7
- *
8
- * @param name - string name of the problem module/resource
9
- * @param error - an Error/Diagnostic object; thrown from try/catch
10
- */
11
- export declare function createReturnStatus(name: string, error: unknown): {
12
- status: number;
13
- message: string;
14
- };
15
5
  interface Params {
16
6
  [key: string]: string;
17
7
  }
@@ -1,34 +1,5 @@
1
- import { LwrUnresolvableError, descriptions, isNodeError } from '@lwrjs/diagnostics';
2
1
  import { pathToRegexp } from 'path-to-regexp';
3
2
  import qs from 'qs';
4
- import createDOMPurify from 'dompurify';
5
- import { JSDOM } from 'jsdom';
6
- const window = new JSDOM('').window;
7
- const DOMPurify = createDOMPurify(window);
8
- /**
9
- * Create a status object Express can return when there is an error
10
- *
11
- * @param name - string name of the problem module/resource
12
- * @param error - an Error/Diagnostic object; thrown from try/catch
13
- */
14
- export function createReturnStatus(name, error) {
15
- let returnStatus = { status: 501, message: '' };
16
- if (isNodeError(error) && error.code === 'NO_LWC_MODULE_FOUND') {
17
- returnStatus = { status: 404, message: descriptions.UNRESOLVABLE.LWC_MODULE(name).message };
18
- }
19
- else if (error instanceof LwrUnresolvableError &&
20
- error.diagnostics[0].description.category === 'lwrUnresolvable/invalid') {
21
- returnStatus = { status: 400, message: error.message };
22
- }
23
- else if (error instanceof LwrUnresolvableError) {
24
- returnStatus = { status: 404, message: error.message };
25
- }
26
- else {
27
- returnStatus = { status: 500, message: descriptions.UNRESOLVABLE.SERVER_ERROR(name).message };
28
- }
29
- returnStatus.message = DOMPurify.sanitize(returnStatus.message);
30
- return returnStatus;
31
- }
32
3
  // Adapted from https://github.com/expressjs/express/blob/master/lib/router/layer.js
33
4
  export function getRequestProperties(pattern, req) {
34
5
  const { url = '/' } = req;
@@ -1,13 +1,22 @@
1
1
  import SiteGenerator from './static-generation.js';
2
2
  import { skipDirCreation } from './utils/dir.js';
3
3
  import NetworkDispatcher from './utils/network-dispatcher.js';
4
+ import { explodeMode } from '../env-config.js';
4
5
  export async function warmupServer(config, internalRequestKey) {
5
6
  console.log('[Server Warmup] starting');
6
- const { routes, staticSiteGenerator, port } = config;
7
+ const { routes, staticSiteGenerator, port, apiVersion, basePath, lwrVersion, serverMode } = config;
7
8
  staticSiteGenerator.outputDir = skipDirCreation;
8
9
  const urlRewriteMap = new Map();
10
+ const runtimeEnvironment = {
11
+ ...explodeMode(serverMode),
12
+ apiVersion,
13
+ basePath,
14
+ lwrVersion,
15
+ debug: false,
16
+ serverMode,
17
+ };
9
18
  // For each locale, generate all the modules
10
- await new SiteGenerator().generateRoutes(staticSiteGenerator, routes, new NetworkDispatcher(port, internalRequestKey), staticSiteGenerator.outputDir, urlRewriteMap);
19
+ await new SiteGenerator().generateRoutes(runtimeEnvironment, staticSiteGenerator, routes, new NetworkDispatcher(port, internalRequestKey), staticSiteGenerator.outputDir, urlRewriteMap);
11
20
  console.log('[Server Warmup] complete');
12
21
  }
13
22
  //# sourceMappingURL=server-warmup.js.map
@@ -1,4 +1,4 @@
1
- import { ImportMetadata, LwrDispatcher, StaticSiteGenerator, LwrRoute, NormalizedLwrGlobalConfig } from '@lwrjs/types';
1
+ import { ImportMetadata, LwrDispatcher, StaticSiteGenerator, LwrRoute, NormalizedLwrGlobalConfig, RuntimeEnvironment } from '@lwrjs/types';
2
2
  import { ResourceContextOpts, SiteConfig, ViewImportMetadata } from './types.js';
3
3
  export default class SiteGenerator {
4
4
  /**
@@ -13,7 +13,7 @@ export default class SiteGenerator {
13
13
  /**
14
14
  * Crawl all view routes for a site
15
15
  */
16
- generateRoutes(staticSiteGenerator: StaticSiteGenerator, routes: LwrRoute[], dispatcher: LwrDispatcher, outputDir: string, urlRewriteMap?: Map<string, string>): Promise<void>;
16
+ generateRoutes(runtimeEnvironment: RuntimeEnvironment, staticSiteGenerator: StaticSiteGenerator, routes: LwrRoute[], dispatcher: LwrDispatcher, outputDir: string, urlRewriteMap?: Map<string, string>): Promise<void>;
17
17
  /**
18
18
  * Creates a function to dispatch the root requests for a given view url
19
19
  */
@@ -91,7 +91,7 @@ export default class SiteGenerator {
91
91
  * Create a new site config for the current view
92
92
  */
93
93
  private createSiteConfig;
94
- private filterExperimentalFeatures;
94
+ private filterFeatureFlags;
95
95
  /**
96
96
  * Add any additional import metadata collected during static site generation to the Client Bootstrap Config for this view.
97
97
  */
@@ -1,9 +1,10 @@
1
1
  import { performance } from 'perf_hooks';
2
- import { getSpecifier, getExperimentalFeatures, hashContent } from '@lwrjs/shared-utils';
2
+ import { getSpecifier, getFeatureFlags, hashContent, getModuleUriPrefix, getMappingUriPrefix, } from '@lwrjs/shared-utils';
3
3
  import { join, dirname, extname } from 'path';
4
4
  import fs from 'fs-extra';
5
5
  import { writeResponse } from './utils/stream.js';
6
6
  import { createDir, createResourceDir } from './utils/dir.js';
7
+ import { explodeMode } from '../env-config.js';
7
8
  export default class SiteGenerator {
8
9
  /**
9
10
  * Build a static site in the configured directory
@@ -24,8 +25,17 @@ export default class SiteGenerator {
24
25
  console.log(`[INFO] Clear Output Location: ${outputDir}`);
25
26
  fs.rmSync(outputDir, { recursive: true, force: true });
26
27
  const urlRewriteMap = new Map();
28
+ const { apiVersion, basePath, lwrVersion, serverMode } = config;
29
+ const runtimeEnvironment = {
30
+ ...explodeMode(serverMode),
31
+ apiVersion,
32
+ basePath,
33
+ lwrVersion,
34
+ debug: false,
35
+ serverMode,
36
+ };
27
37
  // For each locale, generate all the modules
28
- await this.generateRoutes(staticSiteGenerator, routes, dispatcher, outputDir, urlRewriteMap);
38
+ await this.generateRoutes(runtimeEnvironment, staticSiteGenerator, routes, dispatcher, outputDir, urlRewriteMap);
29
39
  // Write redirect files
30
40
  this.writeNetlifyRedirectConfig(outputDir, urlRewriteMap);
31
41
  // Copy over assets
@@ -37,7 +47,7 @@ export default class SiteGenerator {
37
47
  /**
38
48
  * Crawl all view routes for a site
39
49
  */
40
- async generateRoutes(staticSiteGenerator, routes, dispatcher, outputDir, urlRewriteMap = new Map()) {
50
+ async generateRoutes(runtimeEnvironment, staticSiteGenerator, routes, dispatcher, outputDir, urlRewriteMap = new Map()) {
41
51
  if (!staticSiteGenerator.locales) {
42
52
  staticSiteGenerator.locales = ['en-US'];
43
53
  }
@@ -46,18 +56,27 @@ export default class SiteGenerator {
46
56
  for (const locale of staticSiteGenerator.locales) {
47
57
  // Generate all the routes
48
58
  for (const route of routes) {
49
- const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap);
59
+ const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap, runtimeEnvironment);
50
60
  // eslint-disable-next-line no-await-in-loop
51
61
  await generateUrl(route.path, siteConfig);
52
62
  }
53
63
  // Generate any additional urls
54
64
  if (staticSiteGenerator._additionalRoutePaths) {
55
65
  for (const uri of staticSiteGenerator._additionalRoutePaths) {
56
- const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap);
66
+ const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap, runtimeEnvironment);
57
67
  // eslint-disable-next-line no-await-in-loop
58
68
  await generateUrl(uri, siteConfig);
59
69
  }
60
70
  }
71
+ // Handle _additionalModules specifiers
72
+ const { _additionalModules } = staticSiteGenerator;
73
+ if (_additionalModules) {
74
+ for (const specifier of _additionalModules) {
75
+ const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap, runtimeEnvironment);
76
+ // eslint-disable-next-line no-await-in-loop
77
+ await this.dispatchJSResourceRecursive(specifier, dispatcher, siteConfig, true);
78
+ }
79
+ }
61
80
  }
62
81
  }
63
82
  /**
@@ -94,7 +113,15 @@ export default class SiteGenerator {
94
113
  return;
95
114
  }
96
115
  // Generate resource
97
- const context = await dispatcher.dispatchUrl(url, 'GET', siteConfig.locale);
116
+ let context;
117
+ context = await dispatcher.dispatchUrl(url, 'GET', siteConfig.locale);
118
+ // Handle 302 redirect if applicable
119
+ if (context?.fs?.headers?.Location) {
120
+ const redirectUrl = context?.fs?.headers?.Location;
121
+ url = redirectUrl;
122
+ const redirectContext = await dispatcher.dispatchUrl(url, 'GET', siteConfig.locale);
123
+ context = redirectContext;
124
+ }
98
125
  const { resourceType } = resourceOpts;
99
126
  // -- Routes (root resources) -------
100
127
  if (resourceType === 'route') {
@@ -192,12 +219,16 @@ export default class SiteGenerator {
192
219
  if (statusCode === 200) {
193
220
  // Read JSON
194
221
  const newImportMetadata = context.fs?.body;
222
+ let filteredImportMetadata;
195
223
  if (!importMetatdata) {
196
- console.warn('[WARN] Import metadata collector was never initialized');
197
- return;
224
+ filteredImportMetadata = newImportMetadata;
225
+ }
226
+ else {
227
+ // need to handle importMetadata when generating from a view
228
+ filteredImportMetadata = importMetatdata.addAdditionalMetadata(newImportMetadata);
198
229
  }
199
230
  // Filter out and import metadata already included with the view
200
- const filteredImportMetadata = importMetatdata.addAdditionalMetadata(newImportMetadata);
231
+ // const filteredImportMetadata = importMetatdata.addAdditionalMetadata(newImportMetadata);
201
232
  // Build up a list of dispatch requests to kick off in parallel
202
233
  const dispatchRequests = [];
203
234
  // Iterate through the import mappings and return request uris
@@ -254,8 +285,6 @@ export default class SiteGenerator {
254
285
  * @param dispatcher - Network dispatcher
255
286
  */
256
287
  async handleViewDefinition(viewDefinition, siteConfig, dispatcher) {
257
- // Save mapping endpoint for future
258
- siteConfig.endpoints = viewDefinition.viewRecord.endpoints;
259
288
  // Save existing import metadata
260
289
  if (viewDefinition.viewRecord.importMetadata) {
261
290
  // Initialize import metadata collector
@@ -320,12 +349,12 @@ export default class SiteGenerator {
320
349
  // -- Dispatch dependencies
321
350
  await Promise.all(dispatchRequests);
322
351
  }
323
- async dispatchJSResourceRecursive(jsUri, dispatcher, siteConfig) {
352
+ async dispatchJSResourceRecursive(jsUri, dispatcher, siteConfig, isAdditionalModulesRequest) {
324
353
  if (jsUri.startsWith('/')) {
325
354
  await this.dispatchResourceRecursive(jsUri, dispatcher, { resourceType: 'js' }, siteConfig);
326
355
  }
327
356
  else {
328
- const supportsFingerprints = siteConfig.experimentalFeatures?.ENABLE_FINGERPRINTS;
357
+ const supportsFingerprints = !siteConfig.featureFlags?.LEGACY_LOADER;
329
358
  if (supportsFingerprints) {
330
359
  // Download mapping
331
360
  const mappingEndpoint = siteConfig.endpoints?.uris?.mapping;
@@ -339,6 +368,14 @@ export default class SiteGenerator {
339
368
  '"');
340
369
  }
341
370
  }
371
+ // TODO: this code path was still being hit prior to _additionalModules
372
+ // flag for bare dynamic imports metadata. This flag keeps the behavior as
373
+ // before until we can figure out what to do with those requests.
374
+ else if (isAdditionalModulesRequest) {
375
+ // fallback to globalThis.LWR.imports.default
376
+ const uri = `${siteConfig.endpoints?.uris.legacyDefault}${encodeURIComponent(jsUri)}`;
377
+ await this.dispatchResourceRecursive(uri, dispatcher, { resourceType: 'js' }, siteConfig);
378
+ }
342
379
  }
343
380
  }
344
381
  /**
@@ -408,7 +445,7 @@ export default class SiteGenerator {
408
445
  }
409
446
  }
410
447
  catch (e) {
411
- console.error('Error occurred processing asset config: ' + asset);
448
+ console.error('Error occurred processing asset config: ' + JSON.stringify(asset));
412
449
  console.error(e);
413
450
  }
414
451
  }
@@ -416,21 +453,29 @@ export default class SiteGenerator {
416
453
  /**
417
454
  * Create a new site config for the current view
418
455
  */
419
- createSiteConfig(outputDir, locale, urlRewriteMap) {
420
- const experimentalFeatures = this.filterExperimentalFeatures();
456
+ createSiteConfig(outputDir, locale, urlRewriteMap, runtimeEnvironment) {
457
+ const featureFlags = this.filterFeatureFlags();
458
+ const endpoints = {
459
+ uris: {
460
+ // legacy globalThis.LWR.importMappings.default
461
+ legacyDefault: getModuleUriPrefix(runtimeEnvironment, { locale }),
462
+ mapping: getMappingUriPrefix(runtimeEnvironment, { locale }),
463
+ },
464
+ };
421
465
  return {
422
466
  outputDir,
423
467
  viewPaths: new Set(),
424
468
  visitedUrls: new Set(),
425
469
  locale,
426
470
  urlRewriteMap,
427
- // Only include ENABLE_FINGERPRINTS if true
428
- ...experimentalFeatures,
471
+ endpoints,
472
+ // Only include LEGACY_LOADER if true
473
+ ...featureFlags,
429
474
  };
430
475
  }
431
- filterExperimentalFeatures() {
432
- if (getExperimentalFeatures().ENABLE_FINGERPRINTS) {
433
- return { experimentalFeatures: { ENABLE_FINGERPRINTS: true } };
476
+ filterFeatureFlags() {
477
+ if (getFeatureFlags().LEGACY_LOADER) {
478
+ return { featureFlags: { LEGACY_LOADER: true } };
434
479
  }
435
480
  else {
436
481
  return undefined;
@@ -440,7 +485,7 @@ export default class SiteGenerator {
440
485
  * Add any additional import metadata collected during static site generation to the Client Bootstrap Config for this view.
441
486
  */
442
487
  addAdditionalImportMetadataToViewConfig(siteConfig) {
443
- const supportsFingerprints = siteConfig.experimentalFeatures?.ENABLE_FINGERPRINTS;
488
+ const supportsFingerprints = !siteConfig.featureFlags?.LEGACY_LOADER;
444
489
  const additionalImportMetadata = siteConfig?.importMetadata?.getAdditionalImportMetadata();
445
490
  if (supportsFingerprints &&
446
491
  siteConfig.viewConfigPath &&
@@ -1,4 +1,4 @@
1
- import { Endpoints, ExperimentalFeatures, ImportMetadata } from '@lwrjs/types';
1
+ import { Endpoints, FeatureFlags, ImportMetadata } from '@lwrjs/types';
2
2
  import { RenderedAssetReference } from '@lwrjs/types';
3
3
  export interface BaseResourceContextOpts {
4
4
  resourceType: 'route' | 'asset' | 'js' | 'resource' | 'mapping';
@@ -41,6 +41,7 @@ export interface SiteConfig {
41
41
  endpoints?: Endpoints;
42
42
  importMetadata?: ViewImportMetadata;
43
43
  viewConfigPath?: string;
44
- experimentalFeatures?: ExperimentalFeatures;
44
+ featureFlags?: FeatureFlags;
45
+ legacyDefaultMappingEndpoint?: string;
45
46
  }
46
47
  //# sourceMappingURL=types.d.ts.map
@@ -22,6 +22,7 @@ export declare const LOCKER_ATTRIBUTE_KEYS: ["enabled", "trustedComponents", "cl
22
22
  export declare const ROUTE_ATTRIBUTE_KEYS: ["bootstrap", "contentTemplate", "id", "cache", "layoutTemplate", "method", "path", "rootComponent", "routeHandler", "properties"];
23
23
  export declare const ERROR_ROUTE_ATTRIBUTE_KEYS: ["bootstrap", "contentTemplate", "id", "layoutTemplate", "rootComponent", "routeHandler", "status", "properties", "cache"];
24
24
  export declare const BOOTSTRAP_ATTRIBUTE_KEYS: ["autoBoot", "syntheticShadow", "workers", "services", "configAsSrc", "experimentalSSR"];
25
+ export declare const BASE_PATH_REGEX: RegExp;
25
26
  export declare class ValidationContext {
26
27
  diagnostics: Diagnostic[];
27
28
  sourceText: string;
@@ -38,6 +39,7 @@ export declare class ValidationContext {
38
39
  assertIsMethod(node: Node | undefined, property: string): void;
39
40
  assertIsStatus(node: Node | undefined, property: string): void;
40
41
  assertIsEnvironment(node: Node | undefined, property: string): void;
42
+ assertIsBasePath(node: Node | undefined, property: string): void;
41
43
  assertNotEmptyString(node: Node | undefined, property: string): void;
42
44
  assertNotEmptyArray(node: Node | undefined, property: string): void;
43
45
  assertHasOneOrMore(node: Node, property: string, childProps: string[]): void;
@@ -78,6 +78,7 @@ const SPECIFIER_REGEX = /^@?[\w-]+(\/[\w-]+)*$/;
78
78
  function isNotEmptyString(node) {
79
79
  return node.type === 'string' && node.value.length > 0;
80
80
  }
81
+ export const BASE_PATH_REGEX = /^(\/[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$/g;
81
82
  export class ValidationContext {
82
83
  constructor(sourceText) {
83
84
  this.diagnostics = [];
@@ -191,6 +192,26 @@ export class ValidationContext {
191
192
  });
192
193
  }
193
194
  }
195
+ assertIsBasePath(node, property) {
196
+ if (!node) {
197
+ return;
198
+ }
199
+ if (node.type !== 'string') {
200
+ this.diagnostics.push({
201
+ description: descriptions.CONFIG_PARSER.INCORRECT_NODE_TYPE(property, 'string', node.type),
202
+ location: this.getLocationFromNode(node),
203
+ });
204
+ }
205
+ else if (node.value === '') {
206
+ return;
207
+ }
208
+ else if (node.value.match(BASE_PATH_REGEX) === null) {
209
+ this.diagnostics.push({
210
+ description: descriptions.CONFIG_PARSER.INVALID_BASEPATH(property, node.value),
211
+ location: this.getLocationFromNode(node),
212
+ });
213
+ }
214
+ }
194
215
  assertNotEmptyString(node, property) {
195
216
  if (!node) {
196
217
  return;
@@ -180,6 +180,7 @@ function validateLocker(node, validationContext) {
180
180
  * - resourceProviders: array of services
181
181
  * - assetProviders: array of services
182
182
  * - lwc.modules: array
183
+ * - basePath: valid subdomain part
183
184
  * Notes:
184
185
  * - ignore `bundleConfig` because it is not yet RFCed
185
186
  * - specifier strings are validated for type and shape only, NOT if they are resolvable
@@ -216,6 +217,7 @@ function validateRoot(node, validationContext, preMerge) {
216
217
  validationContext.assertArrayOfServices(findNode(node, ['assetProviders']), 'assetProviders');
217
218
  validationContext.assertNotEmptyArray(findNode(node, ['lwc', 'modules']), 'lwc.modules');
218
219
  validationContext.assertIsEnvironment(findNode(node, ['environment']), 'environment');
220
+ validationContext.assertIsBasePath(findNode(node, ['basePath']), 'basePath');
219
221
  }
220
222
  export function validateLwrAppConfig(jsonSourceText, phase) {
221
223
  const errors = [];
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.7.0-alpha.0",
7
+ "version": "0.7.0-alpha.11",
8
8
  "homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
9
9
  "repository": {
10
10
  "type": "git",
@@ -33,32 +33,31 @@
33
33
  "package.cjs"
34
34
  ],
35
35
  "dependencies": {
36
- "@lwrjs/app-service": "0.7.0-alpha.0",
37
- "@lwrjs/asset-registry": "0.7.0-alpha.0",
38
- "@lwrjs/asset-transformer": "0.7.0-alpha.0",
39
- "@lwrjs/base-template-engine": "0.7.0-alpha.0",
40
- "@lwrjs/base-view-provider": "0.7.0-alpha.0",
41
- "@lwrjs/base-view-transformer": "0.7.0-alpha.0",
42
- "@lwrjs/client-modules": "0.7.0-alpha.0",
43
- "@lwrjs/compiler": "0.7.0-alpha.0",
44
- "@lwrjs/diagnostics": "0.7.0-alpha.0",
45
- "@lwrjs/fs-asset-provider": "0.7.0-alpha.0",
46
- "@lwrjs/html-view-provider": "0.7.0-alpha.0",
47
- "@lwrjs/loader": "0.7.0-alpha.0",
48
- "@lwrjs/lwc-module-provider": "0.7.0-alpha.0",
49
- "@lwrjs/lwc-ssr": "0.7.0-alpha.0",
50
- "@lwrjs/markdown-view-provider": "0.7.0-alpha.0",
51
- "@lwrjs/module-bundler": "0.7.0-alpha.0",
52
- "@lwrjs/module-registry": "0.7.0-alpha.0",
53
- "@lwrjs/npm-module-provider": "0.7.0-alpha.0",
54
- "@lwrjs/nunjucks-view-provider": "0.7.0-alpha.0",
55
- "@lwrjs/o11y": "0.7.0-alpha.0",
56
- "@lwrjs/resource-registry": "0.7.0-alpha.0",
57
- "@lwrjs/router": "0.7.0-alpha.0",
58
- "@lwrjs/server": "0.7.0-alpha.0",
59
- "@lwrjs/shared-utils": "0.7.0-alpha.0",
60
- "@lwrjs/view-registry": "0.7.0-alpha.0",
61
- "dompurify": "^2.3.0",
36
+ "@lwrjs/app-service": "0.7.0-alpha.11",
37
+ "@lwrjs/asset-registry": "0.7.0-alpha.11",
38
+ "@lwrjs/asset-transformer": "0.7.0-alpha.11",
39
+ "@lwrjs/base-template-engine": "0.7.0-alpha.11",
40
+ "@lwrjs/base-view-provider": "0.7.0-alpha.11",
41
+ "@lwrjs/base-view-transformer": "0.7.0-alpha.11",
42
+ "@lwrjs/client-modules": "0.7.0-alpha.11",
43
+ "@lwrjs/compiler": "0.7.0-alpha.11",
44
+ "@lwrjs/diagnostics": "0.7.0-alpha.11",
45
+ "@lwrjs/fs-asset-provider": "0.7.0-alpha.11",
46
+ "@lwrjs/html-view-provider": "0.7.0-alpha.11",
47
+ "@lwrjs/loader": "0.7.0-alpha.11",
48
+ "@lwrjs/lwc-module-provider": "0.7.0-alpha.11",
49
+ "@lwrjs/lwc-ssr": "0.7.0-alpha.11",
50
+ "@lwrjs/markdown-view-provider": "0.7.0-alpha.11",
51
+ "@lwrjs/module-bundler": "0.7.0-alpha.11",
52
+ "@lwrjs/module-registry": "0.7.0-alpha.11",
53
+ "@lwrjs/npm-module-provider": "0.7.0-alpha.11",
54
+ "@lwrjs/nunjucks-view-provider": "0.7.0-alpha.11",
55
+ "@lwrjs/o11y": "0.7.0-alpha.11",
56
+ "@lwrjs/resource-registry": "0.7.0-alpha.11",
57
+ "@lwrjs/router": "0.7.0-alpha.11",
58
+ "@lwrjs/server": "0.7.0-alpha.11",
59
+ "@lwrjs/shared-utils": "0.7.0-alpha.11",
60
+ "@lwrjs/view-registry": "0.7.0-alpha.11",
62
61
  "fs-extra": "^10.0.0",
63
62
  "jsdom": "^16.7.0",
64
63
  "jsonc-parser": "^3.0.0",
@@ -67,7 +66,7 @@
67
66
  "qs": "^6.9.4"
68
67
  },
69
68
  "devDependencies": {
70
- "@lwrjs/types": "0.7.0-alpha.0"
69
+ "@lwrjs/types": "0.7.0-alpha.11"
71
70
  },
72
71
  "peerDependencies": {
73
72
  "lwc": ">= 1.x <= 2.x"
@@ -75,5 +74,5 @@
75
74
  "engines": {
76
75
  "node": ">=14.15.4 <17"
77
76
  },
78
- "gitHead": "4ed70d0bb9fd53feb629468b558b882adade0967"
77
+ "gitHead": "0b272d15905ec7b949974e8c5ba668a98eaa7e2d"
79
78
  }
@@ -6,5 +6,8 @@
6
6
  "watchFiles": true,
7
7
  "defaultLocale": "en_US",
8
8
  "hmrEnabled": false,
9
- "immutableAssets": false
9
+ "immutableAssets": false,
10
+ "env": {
11
+ "NODE_ENV": "development"
12
+ }
10
13
  }
@@ -6,5 +6,8 @@
6
6
  "watchFiles": true,
7
7
  "defaultLocale": "en_US",
8
8
  "hmrEnabled": true,
9
- "immutableAssets": false
9
+ "immutableAssets": false,
10
+ "env": {
11
+ "NODE_ENV": "development"
12
+ }
10
13
  }
@@ -6,5 +6,8 @@
6
6
  "watchFiles": false,
7
7
  "defaultLocale": "en_US",
8
8
  "hmrEnabled": false,
9
- "immutableAssets": true
9
+ "immutableAssets": true,
10
+ "env": {
11
+ "NODE_ENV": "production"
12
+ }
10
13
  }
@@ -6,5 +6,8 @@
6
6
  "watchFiles": false,
7
7
  "defaultLocale": "en_US",
8
8
  "hmrEnabled": false,
9
- "immutableAssets": true
9
+ "immutableAssets": true,
10
+ "env": {
11
+ "NODE_ENV": "production"
12
+ }
10
13
  }