@lwrjs/core 0.9.0-alpha.1 → 0.9.0-alpha.10

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.
Files changed (78) hide show
  1. package/build/cjs/context/{hooks.cjs → configurations.cjs} +33 -9
  2. package/build/cjs/context/provider.cjs +82 -0
  3. package/build/cjs/context/server.cjs +75 -0
  4. package/build/cjs/context/services.cjs +8 -1
  5. package/build/cjs/index.cjs +39 -139
  6. package/build/cjs/middleware/asset-middleware.cjs +56 -0
  7. package/build/cjs/middleware/bundle-middleware.cjs +114 -0
  8. package/build/cjs/{middlewares → middleware}/hmr-middleware.cjs +4 -4
  9. package/build/cjs/{middlewares → middleware}/locale-middleware.cjs +2 -2
  10. package/build/cjs/middleware/mapping-middleware.cjs +61 -0
  11. package/build/cjs/middleware/module-middleware.cjs +88 -0
  12. package/build/cjs/middleware/redirects/unsigned-module-redirect.cjs +21 -0
  13. package/build/cjs/middleware/resource-middleware.cjs +64 -0
  14. package/build/cjs/middleware/utils/error-handling.cjs +56 -0
  15. package/build/cjs/middleware/utils/identity.cjs +93 -0
  16. package/build/cjs/middleware/utils/metadata.cjs +49 -0
  17. package/build/cjs/{middlewares/utils.cjs → middleware/utils/request.cjs} +17 -16
  18. package/build/cjs/middleware/view-middleware.cjs +154 -0
  19. package/build/cjs/middleware.cjs +43 -0
  20. package/build/cjs/tools/server-build.cjs +182 -0
  21. package/build/cjs/tools/static-generation.cjs +34 -24
  22. package/build/es/context/configurations.d.ts +9 -0
  23. package/build/es/context/configurations.js +53 -0
  24. package/build/es/context/provider.d.ts +3 -0
  25. package/build/es/context/provider.js +38 -0
  26. package/build/es/context/server.d.ts +3 -0
  27. package/build/es/context/server.js +48 -0
  28. package/build/es/context/services.d.ts +2 -7
  29. package/build/es/context/services.js +11 -1
  30. package/build/es/index.d.ts +3 -2
  31. package/build/es/index.js +45 -130
  32. package/build/es/middleware/asset-middleware.d.ts +3 -0
  33. package/build/es/middleware/asset-middleware.js +26 -0
  34. package/build/es/middleware/bundle-middleware.d.ts +3 -0
  35. package/build/es/middleware/bundle-middleware.js +87 -0
  36. package/build/es/middleware/hmr-middleware.d.ts +5 -0
  37. package/build/es/{middlewares → middleware}/hmr-middleware.js +2 -2
  38. package/build/es/middleware/locale-middleware.d.ts +3 -0
  39. package/build/es/{middlewares → middleware}/locale-middleware.js +2 -1
  40. package/build/es/middleware/mapping-middleware.d.ts +3 -0
  41. package/build/es/middleware/mapping-middleware.js +34 -0
  42. package/build/es/middleware/module-middleware.d.ts +3 -0
  43. package/build/es/middleware/module-middleware.js +62 -0
  44. package/build/es/middleware/redirects/unsigned-module-redirect.d.ts +5 -0
  45. package/build/es/middleware/redirects/unsigned-module-redirect.js +10 -0
  46. package/build/es/middleware/resource-middleware.d.ts +3 -0
  47. package/build/es/middleware/resource-middleware.js +37 -0
  48. package/build/es/middleware/utils/error-handling.d.ts +3 -0
  49. package/build/es/middleware/utils/error-handling.js +32 -0
  50. package/build/es/middleware/utils/identity.d.ts +6 -0
  51. package/build/es/middleware/utils/identity.js +64 -0
  52. package/build/es/middleware/utils/metadata.d.ts +3 -0
  53. package/build/es/middleware/utils/metadata.js +28 -0
  54. package/build/es/middleware/utils/request.d.ts +15 -0
  55. package/build/es/{middlewares/utils.js → middleware/utils/request.js} +15 -23
  56. package/build/es/middleware/view-middleware.d.ts +3 -0
  57. package/build/es/middleware/view-middleware.js +139 -0
  58. package/build/es/middleware.d.ts +9 -0
  59. package/build/es/middleware.js +13 -0
  60. package/build/es/tools/server-build.d.ts +14 -0
  61. package/build/es/tools/server-build.js +182 -0
  62. package/build/es/tools/static-generation.js +50 -34
  63. package/build/es/tools/types.d.ts +1 -0
  64. package/package.json +34 -30
  65. package/build/cjs/middlewares/api-middleware.cjs +0 -359
  66. package/build/cjs/middlewares/base-middleware.cjs +0 -15
  67. package/build/cjs/middlewares/ui-middleware.cjs +0 -183
  68. package/build/es/context/hooks.d.ts +0 -9
  69. package/build/es/context/hooks.js +0 -36
  70. package/build/es/middlewares/api-middleware.d.ts +0 -3
  71. package/build/es/middlewares/api-middleware.js +0 -410
  72. package/build/es/middlewares/base-middleware.d.ts +0 -3
  73. package/build/es/middlewares/base-middleware.js +0 -4
  74. package/build/es/middlewares/hmr-middleware.d.ts +0 -5
  75. package/build/es/middlewares/locale-middleware.d.ts +0 -3
  76. package/build/es/middlewares/ui-middleware.d.ts +0 -3
  77. package/build/es/middlewares/ui-middleware.js +0 -186
  78. package/build/es/middlewares/utils.d.ts +0 -22
@@ -0,0 +1,64 @@
1
+ import { explodeSpecifier, explodeSpecifiers, LATEST_SIGNATURE } from '@lwrjs/shared-utils';
2
+ import { createSingleDiagnosticError, descriptions, LwrUnresolvableError } from '@lwrjs/diagnostics';
3
+ function validateSpecifier(specifer) {
4
+ return specifer.indexOf('../') < 0;
5
+ }
6
+ export function getModuleIdentity(req, importer) {
7
+ const { specifier, signature } = req.params;
8
+ if (validateSpecifier(specifier) === false) {
9
+ throw createSingleDiagnosticError({
10
+ description: descriptions.UNRESOLVABLE.INVALID_SPECIFIER(specifier),
11
+ }, LwrUnresolvableError);
12
+ }
13
+ const moduleId = explodeSpecifier(specifier);
14
+ return {
15
+ moduleId: {
16
+ ...moduleId,
17
+ importer,
18
+ },
19
+ signature,
20
+ };
21
+ }
22
+ export function getMappingIdentity(req) {
23
+ const { specifiers } = req.params;
24
+ const moduleIds = explodeSpecifiers(specifiers).map((obj) => ({
25
+ ...obj,
26
+ importer: req.query.importer,
27
+ }));
28
+ return {
29
+ moduleIds,
30
+ };
31
+ }
32
+ export function getResourceIdentity(req) {
33
+ const { specifier, signature = LATEST_SIGNATURE } = req.params;
34
+ if (validateSpecifier(specifier) === false) {
35
+ throw createSingleDiagnosticError({
36
+ description: descriptions.UNRESOLVABLE.INVALID_SPECIFIER(specifier),
37
+ }, LwrUnresolvableError);
38
+ }
39
+ const resourceId = explodeSpecifier(specifier);
40
+ return {
41
+ resourceId,
42
+ signature,
43
+ };
44
+ }
45
+ export function getAssetIdentity(req) {
46
+ const { signature, immutable, assetType: type } = req.params;
47
+ const specifier = signature && type ? '/' + req.params[0] : req.originalUrl.split('?')[0];
48
+ if (immutable) {
49
+ // WIP: ?
50
+ }
51
+ if (validateSpecifier(specifier) === false) {
52
+ throw createSingleDiagnosticError({
53
+ description: descriptions.UNRESOLVABLE.INVALID_SPECIFIER(specifier),
54
+ }, LwrUnresolvableError);
55
+ }
56
+ return {
57
+ assetId: {
58
+ specifier,
59
+ type,
60
+ },
61
+ signature: signature || LATEST_SIGNATURE,
62
+ };
63
+ }
64
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1,3 @@
1
+ import { BundleDefinition, ModuleRegistry, RuntimeEnvironment, RuntimeParams } from '@lwrjs/types';
2
+ export declare function normalizeResolvedUris(bundleDefinition: BundleDefinition, runtimeEnvironment: RuntimeEnvironment, runtimeParams: RuntimeParams, moduleRegistry: ModuleRegistry): Promise<string[]>;
3
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1,28 @@
1
+ import { getVersionedModuleId } from '@lwrjs/shared-utils';
2
+ export async function normalizeResolvedUris(bundleDefinition, runtimeEnvironment, runtimeParams, moduleRegistry) {
3
+ const resolvedUris = [];
4
+ // TODO might be able to remove this in the future but not sure how to properly send
5
+ // back bundleRecord imports with absolute uris (lwc is the main one)
6
+ if (bundleDefinition.bundleRecord.imports) {
7
+ for (const theImport of bundleDefinition.bundleRecord.imports) {
8
+ const childSpecifier = theImport.specifier;
9
+ // eslint-disable-next-line no-await-in-loop
10
+ const id = await getVersionedModuleId(childSpecifier, moduleRegistry);
11
+ // eslint-disable-next-line no-await-in-loop
12
+ const uri = await moduleRegistry.resolveModuleUri(id, runtimeEnvironment, runtimeParams);
13
+ resolvedUris.push(uri);
14
+ }
15
+ }
16
+ if (bundleDefinition.bundleRecord.dynamicImports) {
17
+ for (const theImport of bundleDefinition.bundleRecord.dynamicImports) {
18
+ const childSpecifier = theImport.specifier;
19
+ // eslint-disable-next-line no-await-in-loop
20
+ const id = await getVersionedModuleId(childSpecifier, moduleRegistry);
21
+ // eslint-disable-next-line no-await-in-loop
22
+ const uri = await moduleRegistry.resolveModuleUri(id, runtimeEnvironment, runtimeParams);
23
+ resolvedUris.push(uri);
24
+ }
25
+ }
26
+ return resolvedUris;
27
+ }
28
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" />
2
+ import type { MiddlewareRequest, ModuleRegistry } from '@lwrjs/types';
3
+ import http from 'http';
4
+ import qs from 'qs';
5
+ interface Params {
6
+ [key: string]: string;
7
+ }
8
+ export declare function getRequestProperties(pattern: string, req: http.IncomingMessage): {
9
+ url: string;
10
+ params: Params;
11
+ query: qs.ParsedQs;
12
+ } | undefined;
13
+ export declare function getRequestImporter(req: MiddlewareRequest, moduleRegistry: ModuleRegistry): Promise<string>;
14
+ export {};
15
+ //# sourceMappingURL=request.d.ts.map
@@ -1,5 +1,12 @@
1
- import { pathToRegexp } from 'path-to-regexp';
2
1
  import qs from 'qs';
2
+ import { pathToRegexp } from 'path-to-regexp';
3
+ import { explodeSpecifier } from '@lwrjs/shared-utils';
4
+ function decodeParam(val) {
5
+ if (typeof val !== 'string' || val.length === 0) {
6
+ return val;
7
+ }
8
+ return decodeURIComponent(val);
9
+ }
3
10
  // Adapted from https://github.com/expressjs/express/blob/master/lib/router/layer.js
4
11
  export function getRequestProperties(pattern, req) {
5
12
  const { url = '/' } = req;
@@ -13,7 +20,7 @@ export function getRequestProperties(pattern, req) {
13
20
  for (let i = 1; i < matched.length; i++) {
14
21
  const key = keys[i - 1];
15
22
  const prop = key.name;
16
- const val = decode_param(matched[i]);
23
+ const val = decodeParam(matched[i]);
17
24
  if (val !== undefined || !Object.hasOwnProperty.call(params, prop)) {
18
25
  params[prop] = val;
19
26
  }
@@ -26,25 +33,10 @@ export function getRequestProperties(pattern, req) {
26
33
  }
27
34
  return;
28
35
  }
29
- /**
30
- * Check if the target environment is supported by the application
31
- *
32
- * @param environmentConfig - environment property from app config
33
- * @param targetEnvironment - environment value from module uri
34
- * @returns boolean
35
- */
36
- export function isSupportedEnvironment(environmentConfig, targetEnvironment) {
37
- if (!!targetEnvironment &&
38
- targetEnvironment !== environmentConfig?.default &&
39
- !environmentConfig?.supported?.includes(targetEnvironment)) {
40
- return false;
41
- }
42
- return true;
43
- }
44
- function decode_param(val) {
45
- if (typeof val !== 'string' || val.length === 0) {
46
- return val;
47
- }
48
- return decodeURIComponent(val);
36
+ export async function getRequestImporter(req, moduleRegistry) {
37
+ const importerSpecifier = req.query.importer;
38
+ const importerModuleId = explodeSpecifier(importerSpecifier);
39
+ const { entry } = await moduleRegistry.getModuleEntry(importerModuleId);
40
+ return entry;
49
41
  }
50
- //# sourceMappingURL=utils.js.map
42
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1,3 @@
1
+ import type { InternalAppServer, ServerContext, ServerTypes } from '@lwrjs/types';
2
+ export declare function viewMiddleware<T extends ServerTypes>(app: InternalAppServer<T>, context: ServerContext): void;
3
+ //# sourceMappingURL=view-middleware.d.ts.map
@@ -0,0 +1,139 @@
1
+ import { descriptions } from '@lwrjs/diagnostics';
2
+ import { getClientRoutes } from '@lwrjs/router';
3
+ import { decodeViewPath, extractRequestParams, getClientBootstrapConfigurationRoutes, shortestTtl, } from '@lwrjs/shared-utils';
4
+ import { handleErrors } from './utils/error-handling.js';
5
+ import { LwrViewHandler } from '@lwrjs/view-registry';
6
+ const CANONICAL_VIEW_ROUTES = [
7
+ `/:apiVersion/application/:format/l/:locale/ai/:appId`,
8
+ `/:apiVersion/application/:format/l/:locale/e/:environment/ai/:appId`,
9
+ `/:apiVersion/application/:format/ai/:appId`,
10
+ `/:apiVersion/application/:format/e/:environment/ai/:appId`,
11
+ ];
12
+ function createViewMiddleware(route, context, viewHandler) {
13
+ const { appConfig } = context;
14
+ const errorRoute = appConfig.errorRoutes.find((route) => route.status === 500);
15
+ return async (req, res) => {
16
+ if (!req.validateEnvironmentRequest(context.appConfig)) {
17
+ res.status(400);
18
+ res.send(descriptions.UNRESOLVABLE.INVALID_ENVIRONMENT(req.params.environment).message);
19
+ return;
20
+ }
21
+ if (!req.validateJsonRequest()) {
22
+ res.status(400);
23
+ res.send(descriptions.UNRESOLVABLE.INVALID_JSON().message);
24
+ return;
25
+ }
26
+ const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(context.runtimeEnvironment);
27
+ // set the default environment if an environment is configured in the app config
28
+ const { environment: environmentConfig } = context.appConfig;
29
+ if (!runtimeParams.environment && environmentConfig?.default) {
30
+ runtimeParams.environment = environmentConfig.default;
31
+ }
32
+ const viewRequest = {
33
+ url: req.originalUrl,
34
+ params: req.params,
35
+ query: req.query,
36
+ requestPath: req.path,
37
+ };
38
+ const resolve = req.isJsonRequest() ? viewHandler.getViewJson : viewHandler.getViewContent;
39
+ let viewResponse;
40
+ let resolvedRoute;
41
+ try {
42
+ viewResponse = await resolve.call(viewHandler, viewRequest, route, runtimeEnvironment, runtimeParams);
43
+ resolvedRoute = route;
44
+ }
45
+ catch (err) {
46
+ if (!errorRoute) {
47
+ throw err;
48
+ }
49
+ viewResponse = await resolve.call(viewHandler, viewRequest, errorRoute, runtimeEnvironment, runtimeParams);
50
+ resolvedRoute = errorRoute;
51
+ }
52
+ if (req.isSiteGeneration()) {
53
+ res.setSiteGenerationMetadata(viewResponse.metadata);
54
+ }
55
+ // view response will be html by default
56
+ res.type('text/html');
57
+ // the default content type can be overridden if specified by the view response
58
+ if (viewResponse.headers) {
59
+ res.set(viewResponse.headers);
60
+ }
61
+ // pick the shortest TTL between the view response and route object
62
+ const cacheTtl = shortestTtl(viewResponse.cache?.ttl, resolvedRoute.cache?.ttl);
63
+ if (cacheTtl) {
64
+ res.setHeader('cache-control', `public, max-age=${cacheTtl}`);
65
+ }
66
+ const status = resolvedRoute.status || viewResponse.status || 200;
67
+ res.status(status);
68
+ res.send(viewResponse.body);
69
+ };
70
+ }
71
+ function createConfigMiddleware(context, viewHandler) {
72
+ const { appConfig } = context;
73
+ const { routes } = appConfig;
74
+ return async (req, res) => {
75
+ const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(context.runtimeEnvironment);
76
+ const { appId, encodedViewPath } = req.params;
77
+ // match the app id to a route
78
+ const route = routes.find((route) => route.id === appId);
79
+ if (!route) {
80
+ res.status(404).send(descriptions.UNRESOLVABLE.APP_CONFIG(appId).message);
81
+ return;
82
+ }
83
+ // decode the resolved view path and extract any params.
84
+ const url = decodeViewPath(encodedViewPath);
85
+ const requestPath = route.path;
86
+ const params = extractRequestParams(requestPath, url, req.params);
87
+ const viewRequest = {
88
+ url,
89
+ params,
90
+ query: req.query,
91
+ requestPath,
92
+ };
93
+ const viewResponse = await viewHandler.getViewConfiguration(viewRequest, route, runtimeEnvironment, runtimeParams);
94
+ if (!viewResponse) {
95
+ res.status(404).send(descriptions.UNRESOLVABLE.VIEW_CONFIG(url).message);
96
+ return;
97
+ }
98
+ // Pick the shortest TTL between the view response and route object
99
+ const cacheTtl = shortestTtl(viewResponse.cache?.ttl, route.cache?.ttl);
100
+ if (cacheTtl) {
101
+ res.setHeader('cache-control', `public, max-age=${cacheTtl}`);
102
+ }
103
+ res.status(200);
104
+ res.type('application/javascript');
105
+ res.status(viewResponse.status || 200);
106
+ res.send(viewResponse.body);
107
+ };
108
+ }
109
+ function createNotFoundMiddleware(context, viewHandler) {
110
+ const { errorRoutes } = context.appConfig;
111
+ const errorRoute = errorRoutes.find((route) => route.status === 404);
112
+ if (errorRoute) {
113
+ return createViewMiddleware(errorRoute, context, viewHandler);
114
+ }
115
+ return (req, res) => {
116
+ res.status(404).send(descriptions.UNRESOLVABLE.VIEW(req.originalUrl).message);
117
+ };
118
+ }
119
+ export function viewMiddleware(app, context) {
120
+ const { appConfig, viewRegistry, moduleRegistry } = context;
121
+ const viewHandler = new LwrViewHandler({ viewRegistry, moduleRegistry }, appConfig);
122
+ // create and attach middleware for each route
123
+ for (const route of appConfig.routes) {
124
+ const paths = [route.path];
125
+ const subRoutes = route.subRoutes && getClientRoutes(route.subRoutes);
126
+ if (subRoutes) {
127
+ const prefix = route.path === '/' ? '' : route.path;
128
+ subRoutes.routes.forEach((subRoute) => subRoute.uri !== route.path && paths.push(`${prefix}${subRoute.uri}`));
129
+ }
130
+ paths.forEach((routePath) => paths.push(...CANONICAL_VIEW_ROUTES.map((viewRoute) => viewRoute + routePath)));
131
+ app.get(paths, handleErrors(createViewMiddleware(route, context, viewHandler)));
132
+ }
133
+ // create and attach middleware for bootstrap configurations
134
+ app.get(getClientBootstrapConfigurationRoutes(), handleErrors(createConfigMiddleware(context, viewHandler)));
135
+ // create and attach a greedy middleware to handle unsupported paths
136
+ // NOTE: a greedy `all` is used over `use` due to the way middleware is mounted in the server abstraction
137
+ app.get('/' + app.getRegexWildcard(), handleErrors(createNotFoundMiddleware(context, viewHandler)));
138
+ }
139
+ //# sourceMappingURL=view-middleware.js.map
@@ -0,0 +1,9 @@
1
+ export { localeMiddleware } from './middleware/locale-middleware.js';
2
+ export { hmrMiddleware } from './middleware/hmr-middleware.js';
3
+ export { moduleMiddleware } from './middleware/module-middleware.js';
4
+ export { bundleMiddleware } from './middleware/bundle-middleware.js';
5
+ export { mappingMiddleware } from './middleware/mapping-middleware.js';
6
+ export { assetMiddleware } from './middleware/asset-middleware.js';
7
+ export { viewMiddleware } from './middleware/view-middleware.js';
8
+ export { resourceMiddleware } from './middleware/resource-middleware.js';
9
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1,13 @@
1
+ // The middleware are exposed as a submodule to mitigate installing unnecessary dependency and minimize Lambda
2
+ // handler bundle size. For example, importing `@lwrjs/core` will pull in ALL `@lwrjs/server` dependencies
3
+ // which includes both `koa` and `express`. Importing `@lwrjs/core/middleware` will only pull in the
4
+ // middleware dependencies.
5
+ export { localeMiddleware } from './middleware/locale-middleware.js';
6
+ export { hmrMiddleware } from './middleware/hmr-middleware.js';
7
+ export { moduleMiddleware } from './middleware/module-middleware.js';
8
+ export { bundleMiddleware } from './middleware/bundle-middleware.js';
9
+ export { mappingMiddleware } from './middleware/mapping-middleware.js';
10
+ export { assetMiddleware } from './middleware/asset-middleware.js';
11
+ export { viewMiddleware } from './middleware/view-middleware.js';
12
+ export { resourceMiddleware } from './middleware/resource-middleware.js';
13
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1,14 @@
1
+ import { LwrGlobalConfig } from '@lwrjs/types';
2
+ export interface BuildOptions {
3
+ target?: string;
4
+ outputDir?: string;
5
+ }
6
+ /**
7
+ * Resolve application configurations, generate a server context module, and bundle
8
+ * the LWR server. The bundled server will be written to the filesystem.
9
+ *
10
+ * @param {LwrGlobalConfig} configArg - programmatic LWR application config
11
+ * @param {BuildOptions} options - server build configurations
12
+ */
13
+ export declare function buildServer(configArg?: LwrGlobalConfig, options?: BuildOptions): Promise<void>;
14
+ //# sourceMappingURL=server-build.d.ts.map
@@ -0,0 +1,182 @@
1
+ import path from 'path';
2
+ import fs from 'fs-extra';
3
+ import esbuild from 'esbuild';
4
+ import { normalizeConfig } from '@lwrjs/config';
5
+ import { resolveConfigurations } from '../context/configurations.js';
6
+ import { createProviderContext } from '../context/provider.js';
7
+ import { createServerContext } from '../context/server.js';
8
+ function getBuildMetadata(appConfig) {
9
+ const moduleProviders = processServiceEntries('moduleProvider', appConfig.moduleProviders);
10
+ const resourceProviders = processServiceEntries('resourceProvider', appConfig.resourceProviders);
11
+ const viewProviders = processServiceEntries('viewProvider', appConfig.viewProviders);
12
+ const viewTransformers = processServiceEntries('viewTransformer', appConfig.viewTransformers);
13
+ const assetProviders = processServiceEntries('assetProvider', appConfig.assetProviders);
14
+ const assetTransformers = processServiceEntries('assetTransformer', appConfig.assetTransformers);
15
+ const imports = [
16
+ ...moduleProviders.imports,
17
+ ...resourceProviders.imports,
18
+ ...viewProviders.imports,
19
+ ...viewTransformers.imports,
20
+ ...assetProviders.imports,
21
+ ...assetTransformers.imports,
22
+ ];
23
+ return {
24
+ imports,
25
+ moduleProviders: moduleProviders.services,
26
+ resourceProviders: resourceProviders.services,
27
+ viewProviders: viewProviders.services,
28
+ viewTransformers: viewTransformers.services,
29
+ assetProviders: assetProviders.services,
30
+ assetTransformers: assetTransformers.services,
31
+ };
32
+ }
33
+ function processServiceEntries(serviceType, entries) {
34
+ const imports = [];
35
+ const services = [];
36
+ for (const [index, [pkg, config]] of entries.entries()) {
37
+ const name = serviceType + index;
38
+ imports.push(`import ${name} from '${pkg}';`);
39
+ services.push(`[${name}, ${JSON.stringify(config)}]`);
40
+ }
41
+ return {
42
+ imports,
43
+ services,
44
+ };
45
+ }
46
+ function generateServices(providerContext) {
47
+ return ([ServiceCtor, serviceConfig = {}]) => new ServiceCtor(serviceConfig, providerContext);
48
+ }
49
+ function isRemote() {
50
+ return process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined;
51
+ }
52
+ function generateServerContextModule(appConfig, runtimeEnvironment, globalData, metadata) {
53
+ const { imports, moduleProviders, resourceProviders, viewProviders, viewTransformers, assetProviders, assetTransformers, } = metadata;
54
+ // config will be resolved programmatically and relative to the current machine
55
+ const config = {
56
+ ...appConfig,
57
+ rootDir: undefined,
58
+ ignoreLwrConfigFile: true,
59
+ };
60
+ return [
61
+ `/* This module is generated */`,
62
+ `import { LwrCompiler } from '@lwrjs/compiler';`,
63
+ `import { LwrModuleBundler } from '@lwrjs/module-bundler';`,
64
+ `import { LwrModuleRegistry } from '@lwrjs/module-registry';`,
65
+ `import { LwrResourceRegistry } from '@lwrjs/resource-registry';`,
66
+ `import { LwrAssetRegistry } from '@lwrjs/asset-registry';`,
67
+ `import { LwrViewRegistry } from '@lwrjs/view-registry';`,
68
+ `import { LwrApplicationObserver, deepFreeze } from '@lwrjs/shared-utils';`,
69
+ `import { normalizeConfig } from '@lwrjs/config';`,
70
+ // all of the static imports for the services
71
+ ...imports,
72
+ // reusing context resolution utils
73
+ createServerContext.toString(),
74
+ createProviderContext.toString(),
75
+ // helper function for generically initializing the services
76
+ generateServices.toString(),
77
+ // helper function to check if running on lambda
78
+ isRemote.toString(),
79
+ `const config = ${JSON.stringify(config, null, 4)}`,
80
+ `const runtimeEnvironment = ${JSON.stringify(runtimeEnvironment, null, 4)}`,
81
+ `const globalData = ${JSON.stringify(globalData, null, 4)}`,
82
+ // build artifacts are placed into a build dir on MRT
83
+ `isRemote() && process.chdir(__dirname);`,
84
+ `isRemote() && (config.rootDir = __dirname);`,
85
+ // cache dir must be in tmp dir to be able to write to the filesystem on lambda
86
+ `isRemote() && (config.cacheDir = '/tmp/__lwr_cache__');`,
87
+ // resolve all config config paths relative to the current machine
88
+ `const normalizedConfig = normalizeConfig(config);`,
89
+ `const serverContext = createServerContext(normalizedConfig, runtimeEnvironment, globalData);`,
90
+ `const providerContext = createProviderContext(serverContext);`,
91
+ `const generate = generateServices(providerContext);`,
92
+ `const moduleProviders = [${moduleProviders}].map(generate);`,
93
+ `const resourceProviders = [${resourceProviders}].map(generate);`,
94
+ `const viewProviders = [${viewProviders}].map(generate);`,
95
+ `const viewTransformers = [${viewTransformers}].map(generate);`,
96
+ `const assetProviders = [${assetProviders}].map(generate);`,
97
+ `const assetTransformers = [${assetTransformers}].map(generate);`,
98
+ `serverContext.moduleRegistry.addModuleProviders(moduleProviders);`,
99
+ `serverContext.resourceRegistry.addResourceProviders(resourceProviders);`,
100
+ `serverContext.viewRegistry.addViewProviders(viewProviders);`,
101
+ `serverContext.viewRegistry.addViewTransformers(viewTransformers);`,
102
+ `serverContext.assetRegistry.addAssetProviders(assetProviders);`,
103
+ `serverContext.assetRegistry.addAssetTransformers(assetTransformers);`,
104
+ `export default serverContext;`,
105
+ ].join('\n');
106
+ }
107
+ function generateServerSource(target) {
108
+ // `lambda` is the only supported build target for now
109
+ if (target !== 'lambda') {
110
+ // TODO: move to diagnostic error
111
+ throw `Unsupported server build target: ${target}`;
112
+ }
113
+ return [
114
+ `/* This module is generated */`,
115
+ `import { createHandler } from '@lwrjs/lambda';`,
116
+ // Importing the server context module at this point enables support for ESM bundling.
117
+ // If the server context module was imported in `createHandler`, it would need to be exposed
118
+ // as CJS.
119
+ `import build from './lwr.build.js';`,
120
+ // The server context module MUST NOT require asynchronous initialization to support running on MRT
121
+ // Once MRT supports ESM, top-level await could be used at this point to perform some asynchronous
122
+ // initialization.
123
+ `const handler = createHandler(build);`,
124
+ // MRT expects the handler to be a named export: `get`
125
+ `export { handler as get };`,
126
+ ].join('\n');
127
+ }
128
+ async function bundleServer(entryPoint, outputPath) {
129
+ await esbuild.build({
130
+ entryPoints: [entryPoint],
131
+ bundle: true,
132
+ sourcemap: true,
133
+ logLevel: 'silent',
134
+ external: [
135
+ // issues with native dependencies
136
+ 'node:*',
137
+ 'fsevents',
138
+ 'iltorb',
139
+ 'esbuild*',
140
+ 'esinstall',
141
+ 'jsonc-parser',
142
+ 'node-fetch',
143
+ 'rollup',
144
+ 'rollup-plugin-node-polyfills',
145
+ // issues resolving relative files after bundling
146
+ '@lwrjs/config',
147
+ '@lwrjs/loader',
148
+ ],
149
+ format: 'cjs',
150
+ platform: 'node',
151
+ outfile: outputPath,
152
+ });
153
+ }
154
+ /**
155
+ * Resolve application configurations, generate a server context module, and bundle
156
+ * the LWR server. The bundled server will be written to the filesystem.
157
+ *
158
+ * @param {LwrGlobalConfig} configArg - programmatic LWR application config
159
+ * @param {BuildOptions} options - server build configurations
160
+ */
161
+ export async function buildServer(configArg, options) {
162
+ // App config will be included in the generated server context module, but all of the config paths
163
+ // will not be normalized. The config paths will be normalized at runtime to enable running the
164
+ // application on a different machine.
165
+ const config = normalizeConfig(configArg, { skipDirNormalization: true, skipCacheDirCreation: true });
166
+ // Config hooks are applied during generation because they enable asynchronous modification of
167
+ // the LWR configurations. Since config hooks are run at build time, the config hooks MUST NOT be
168
+ // responsible for critical application initialization or have dependencies on normalized config paths.
169
+ const { appConfig, runtimeEnvironment, globalData } = await resolveConfigurations(config);
170
+ // All LWR services are processed and included in the generated server context module. This module will
171
+ // statically import the services and initialize all LWR server components(ie. providers and registries).
172
+ const metadata = getBuildMetadata(appConfig);
173
+ const serverContext = generateServerContextModule(appConfig, runtimeEnvironment, globalData, metadata);
174
+ const outputDir = path.join(appConfig.rootDir, options?.outputDir || '/build');
175
+ const serverSource = generateServerSource(options?.target || 'lambda');
176
+ // HACK: writing the server context module and server entry to a file for debugging
177
+ await fs.ensureDir(outputDir);
178
+ await fs.writeFile(path.join(outputDir, 'lwr.build.js'), serverContext);
179
+ await fs.writeFile(path.join(outputDir, 'entry.js'), serverSource);
180
+ await bundleServer(path.join(outputDir, 'entry.js'), path.join(outputDir, 'ssr.js'));
181
+ }
182
+ //# sourceMappingURL=server-build.js.map