@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.
- package/build/cjs/context/{hooks.cjs → configurations.cjs} +33 -9
- package/build/cjs/context/provider.cjs +82 -0
- package/build/cjs/context/server.cjs +75 -0
- package/build/cjs/context/services.cjs +8 -1
- package/build/cjs/index.cjs +39 -139
- package/build/cjs/middleware/asset-middleware.cjs +56 -0
- package/build/cjs/middleware/bundle-middleware.cjs +114 -0
- package/build/cjs/{middlewares → middleware}/hmr-middleware.cjs +4 -4
- package/build/cjs/{middlewares → middleware}/locale-middleware.cjs +2 -2
- package/build/cjs/middleware/mapping-middleware.cjs +61 -0
- package/build/cjs/middleware/module-middleware.cjs +88 -0
- package/build/cjs/middleware/redirects/unsigned-module-redirect.cjs +21 -0
- package/build/cjs/middleware/resource-middleware.cjs +64 -0
- package/build/cjs/middleware/utils/error-handling.cjs +56 -0
- package/build/cjs/middleware/utils/identity.cjs +93 -0
- package/build/cjs/middleware/utils/metadata.cjs +49 -0
- package/build/cjs/{middlewares/utils.cjs → middleware/utils/request.cjs} +17 -16
- package/build/cjs/middleware/view-middleware.cjs +154 -0
- package/build/cjs/middleware.cjs +43 -0
- package/build/cjs/tools/server-build.cjs +182 -0
- package/build/cjs/tools/static-generation.cjs +34 -24
- package/build/es/context/configurations.d.ts +9 -0
- package/build/es/context/configurations.js +53 -0
- package/build/es/context/provider.d.ts +3 -0
- package/build/es/context/provider.js +38 -0
- package/build/es/context/server.d.ts +3 -0
- package/build/es/context/server.js +48 -0
- package/build/es/context/services.d.ts +2 -7
- package/build/es/context/services.js +11 -1
- package/build/es/index.d.ts +3 -2
- package/build/es/index.js +45 -130
- package/build/es/middleware/asset-middleware.d.ts +3 -0
- package/build/es/middleware/asset-middleware.js +26 -0
- package/build/es/middleware/bundle-middleware.d.ts +3 -0
- package/build/es/middleware/bundle-middleware.js +87 -0
- package/build/es/middleware/hmr-middleware.d.ts +5 -0
- package/build/es/{middlewares → middleware}/hmr-middleware.js +2 -2
- package/build/es/middleware/locale-middleware.d.ts +3 -0
- package/build/es/{middlewares → middleware}/locale-middleware.js +2 -1
- package/build/es/middleware/mapping-middleware.d.ts +3 -0
- package/build/es/middleware/mapping-middleware.js +34 -0
- package/build/es/middleware/module-middleware.d.ts +3 -0
- package/build/es/middleware/module-middleware.js +62 -0
- package/build/es/middleware/redirects/unsigned-module-redirect.d.ts +5 -0
- package/build/es/middleware/redirects/unsigned-module-redirect.js +10 -0
- package/build/es/middleware/resource-middleware.d.ts +3 -0
- package/build/es/middleware/resource-middleware.js +37 -0
- package/build/es/middleware/utils/error-handling.d.ts +3 -0
- package/build/es/middleware/utils/error-handling.js +32 -0
- package/build/es/middleware/utils/identity.d.ts +6 -0
- package/build/es/middleware/utils/identity.js +64 -0
- package/build/es/middleware/utils/metadata.d.ts +3 -0
- package/build/es/middleware/utils/metadata.js +28 -0
- package/build/es/middleware/utils/request.d.ts +15 -0
- package/build/es/{middlewares/utils.js → middleware/utils/request.js} +15 -23
- package/build/es/middleware/view-middleware.d.ts +3 -0
- package/build/es/middleware/view-middleware.js +139 -0
- package/build/es/middleware.d.ts +9 -0
- package/build/es/middleware.js +13 -0
- package/build/es/tools/server-build.d.ts +14 -0
- package/build/es/tools/server-build.js +182 -0
- package/build/es/tools/static-generation.js +50 -34
- package/build/es/tools/types.d.ts +1 -0
- package/package.json +34 -30
- package/build/cjs/middlewares/api-middleware.cjs +0 -359
- package/build/cjs/middlewares/base-middleware.cjs +0 -15
- package/build/cjs/middlewares/ui-middleware.cjs +0 -183
- package/build/es/context/hooks.d.ts +0 -9
- package/build/es/context/hooks.js +0 -36
- package/build/es/middlewares/api-middleware.d.ts +0 -3
- package/build/es/middlewares/api-middleware.js +0 -410
- package/build/es/middlewares/base-middleware.d.ts +0 -3
- package/build/es/middlewares/base-middleware.js +0 -4
- package/build/es/middlewares/hmr-middleware.d.ts +0 -5
- package/build/es/middlewares/locale-middleware.d.ts +0 -3
- package/build/es/middlewares/ui-middleware.d.ts +0 -3
- package/build/es/middlewares/ui-middleware.js +0 -186
- 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 =
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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=
|
|
42
|
+
//# sourceMappingURL=request.js.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
|