@lwrjs/tools 0.9.0-alpha.14
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/LICENSE +10 -0
- package/build/es/index.d.ts +2 -0
- package/build/es/index.js +2 -0
- package/build/es/plugins/build-server-plugin.d.ts +18 -0
- package/build/es/plugins/build-server-plugin.js +132 -0
- package/build/es/plugins/generate-entry-plugin.d.ts +11 -0
- package/build/es/plugins/generate-entry-plugin.js +45 -0
- package/build/es/server-build.d.ts +13 -0
- package/build/es/server-build.js +76 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
MIT LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020, Salesforce.com, Inc.
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
7
|
+
|
|
8
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
9
|
+
|
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Plugin } from 'esbuild';
|
|
2
|
+
import type { LwrGlobalConfig } from '@lwrjs/types';
|
|
3
|
+
/**
|
|
4
|
+
* Creates an esbuild plugin that generates a server build module
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* The generated server build module contains:
|
|
8
|
+
* - normalized lwr global config(without normalized directories and after config hooks are applied)
|
|
9
|
+
* - runtime environment(after config hooks are applied)
|
|
10
|
+
* - global data(after config hooks are applied)
|
|
11
|
+
* - lwr services(ie. module providers) with static imports
|
|
12
|
+
* - route handlers with static imports
|
|
13
|
+
*
|
|
14
|
+
* @param config - programmatic global config
|
|
15
|
+
* @returns esbuild plugin
|
|
16
|
+
*/
|
|
17
|
+
export default function buildLwrServer(config?: LwrGlobalConfig): Plugin;
|
|
18
|
+
//# sourceMappingURL=build-server-plugin.d.ts.map
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { loadConfig } from '@lwrjs/config';
|
|
3
|
+
import { normalizeDirectory } from '@lwrjs/shared-utils';
|
|
4
|
+
const services = [
|
|
5
|
+
'moduleProviders',
|
|
6
|
+
'assetProviders',
|
|
7
|
+
'assetTransformers',
|
|
8
|
+
'viewProviders',
|
|
9
|
+
'viewTransformers',
|
|
10
|
+
'resourceProviders',
|
|
11
|
+
];
|
|
12
|
+
function processServices(kind, entries, rootDir) {
|
|
13
|
+
const output = {
|
|
14
|
+
imports: [],
|
|
15
|
+
entries: [],
|
|
16
|
+
};
|
|
17
|
+
for (const [index, [entry, config]] of entries.entries()) {
|
|
18
|
+
const name = kind + index;
|
|
19
|
+
output.imports.push(`import ${name} from '${normalizeDirectory(entry, rootDir)}';`);
|
|
20
|
+
output.entries.push([name, config]);
|
|
21
|
+
}
|
|
22
|
+
return output;
|
|
23
|
+
}
|
|
24
|
+
function processRoutes(routes, rootDir) {
|
|
25
|
+
const output = {
|
|
26
|
+
imports: [],
|
|
27
|
+
routes: [],
|
|
28
|
+
};
|
|
29
|
+
const handlers = {};
|
|
30
|
+
for (const route of routes) {
|
|
31
|
+
if (!route.routeHandler) {
|
|
32
|
+
output.routes.push(route);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const handler = route.routeHandler;
|
|
36
|
+
if (!handlers[handler]) {
|
|
37
|
+
const name = `routeHandler${Object.keys(handlers).length}`;
|
|
38
|
+
handlers[handler] = name;
|
|
39
|
+
output.imports.push(`import ${name} from '${normalizeDirectory(handler, rootDir)}';`);
|
|
40
|
+
}
|
|
41
|
+
output.routes.push({
|
|
42
|
+
...route,
|
|
43
|
+
routeHandler: handlers[handler],
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return output;
|
|
47
|
+
}
|
|
48
|
+
function printServices(config) {
|
|
49
|
+
return `{${Object.entries(config)
|
|
50
|
+
.map(([key, value]) => {
|
|
51
|
+
const entries = value;
|
|
52
|
+
return `${key}: [${entries.map(([ctor, config = {}]) => `[${ctor}, ${JSON.stringify(config)}]`)}]`;
|
|
53
|
+
})
|
|
54
|
+
.join(',')}}`;
|
|
55
|
+
}
|
|
56
|
+
function printRoutes(routes) {
|
|
57
|
+
return `[${routes
|
|
58
|
+
.map((route) => {
|
|
59
|
+
return `{${Object.entries(route)
|
|
60
|
+
.map(([key, value]) => {
|
|
61
|
+
if (key !== 'routeHandler') {
|
|
62
|
+
return `${key}: ${JSON.stringify(value)}`;
|
|
63
|
+
}
|
|
64
|
+
return `${key}: ${value}`;
|
|
65
|
+
})
|
|
66
|
+
.join(',')}}`;
|
|
67
|
+
})
|
|
68
|
+
.join(',')}]`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Creates an esbuild plugin that generates a server build module
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* The generated server build module contains:
|
|
75
|
+
* - normalized lwr global config(without normalized directories and after config hooks are applied)
|
|
76
|
+
* - runtime environment(after config hooks are applied)
|
|
77
|
+
* - global data(after config hooks are applied)
|
|
78
|
+
* - lwr services(ie. module providers) with static imports
|
|
79
|
+
* - route handlers with static imports
|
|
80
|
+
*
|
|
81
|
+
* @param config - programmatic global config
|
|
82
|
+
* @returns esbuild plugin
|
|
83
|
+
*/
|
|
84
|
+
export default function buildLwrServer(config) {
|
|
85
|
+
return {
|
|
86
|
+
name: 'lwr-server-build',
|
|
87
|
+
setup(build) {
|
|
88
|
+
// This file is generated during the build, so it is mapped to a custom namespace
|
|
89
|
+
// to prevent looking for it on the file system.
|
|
90
|
+
build.onResolve({ filter: /.*\/lwr.build.js$/ }, (args) => ({
|
|
91
|
+
path: args.path,
|
|
92
|
+
namespace: 'lwr-server-build',
|
|
93
|
+
}));
|
|
94
|
+
build.onLoad({ filter: /.*/, namespace: 'lwr-server-build' }, async (args) => {
|
|
95
|
+
const { appConfig, runtimeEnvironment, globalData } = await loadConfig(config, {
|
|
96
|
+
skipDirNormalization: true,
|
|
97
|
+
});
|
|
98
|
+
const remoteAppConfig = {
|
|
99
|
+
...appConfig,
|
|
100
|
+
ignoreLwrConfigFile: true,
|
|
101
|
+
rootDir: undefined,
|
|
102
|
+
port: undefined,
|
|
103
|
+
};
|
|
104
|
+
const serviceImports = [];
|
|
105
|
+
const serviceConfig = {};
|
|
106
|
+
for (const service of services) {
|
|
107
|
+
const entries = processServices(service, appConfig[service], appConfig.rootDir);
|
|
108
|
+
serviceImports.push(...entries.imports);
|
|
109
|
+
serviceConfig[service] = entries.entries;
|
|
110
|
+
}
|
|
111
|
+
const routesConfig = processRoutes(appConfig.routes, appConfig.rootDir);
|
|
112
|
+
const errorRoutesConfig = processRoutes(appConfig.errorRoutes, appConfig.rootDir);
|
|
113
|
+
return {
|
|
114
|
+
contents: [
|
|
115
|
+
...serviceImports,
|
|
116
|
+
...routesConfig.imports,
|
|
117
|
+
...errorRoutesConfig.imports,
|
|
118
|
+
`export const appConfig = ${JSON.stringify(remoteAppConfig)};`,
|
|
119
|
+
`export const runtimeEnvironment = ${JSON.stringify(runtimeEnvironment)};`,
|
|
120
|
+
`export const globalData = ${JSON.stringify(globalData)};`,
|
|
121
|
+
`export const services = ${printServices(serviceConfig)};`,
|
|
122
|
+
`export const routes = ${printRoutes(routesConfig.routes)};`,
|
|
123
|
+
`export const errorRoutes = ${printRoutes(errorRoutesConfig.routes)};`,
|
|
124
|
+
].join('\n'),
|
|
125
|
+
loader: 'ts',
|
|
126
|
+
resolveDir: path.dirname(args.path),
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=build-server-plugin.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Plugin } from 'esbuild';
|
|
2
|
+
/**
|
|
3
|
+
* Creates an esbuild plugin that generates the application entry point
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* The generated entry point includes a reference to a generated server build module.
|
|
7
|
+
*
|
|
8
|
+
* @returns esbuild plugin
|
|
9
|
+
*/
|
|
10
|
+
export default function generateLwrEntry(): Plugin;
|
|
11
|
+
//# sourceMappingURL=generate-entry-plugin.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Creates an esbuild plugin that generates the application entry point
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* The generated entry point includes a reference to a generated server build module.
|
|
7
|
+
*
|
|
8
|
+
* @returns esbuild plugin
|
|
9
|
+
*/
|
|
10
|
+
export default function generateLwrEntry() {
|
|
11
|
+
return {
|
|
12
|
+
name: 'lwr-entry',
|
|
13
|
+
setup(build) {
|
|
14
|
+
// This file is generated during the build, so it is mapped to a custom namespace
|
|
15
|
+
// to prevent looking for it on the file system.
|
|
16
|
+
build.onResolve({ filter: /.*\/lwr.entry.js$/ }, ({ kind, path }) => {
|
|
17
|
+
if (kind === 'entry-point') {
|
|
18
|
+
return {
|
|
19
|
+
path,
|
|
20
|
+
namespace: 'lwr-entry',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
build.onLoad({ filter: /.*/, namespace: 'lwr-entry' }, (args) => ({
|
|
25
|
+
contents: [
|
|
26
|
+
`/* This module is generated */`,
|
|
27
|
+
`import { createHandler } from '@lwrjs/lambda';`,
|
|
28
|
+
// Importing the server build module at this point enables support for ESM bundling.
|
|
29
|
+
// If the server build module was imported in `createHandler`, it would need to be exposed
|
|
30
|
+
// as CJS.
|
|
31
|
+
`import * as build from './lwr.build.js';`,
|
|
32
|
+
// The server build module MUST NOT require asynchronous initialization to support running on MRT
|
|
33
|
+
// Once MRT supports ESM, top-level await could be used at this point to perform some asynchronous
|
|
34
|
+
// initialization.
|
|
35
|
+
`const handler = createHandler(build);`,
|
|
36
|
+
// MRT expects the handler to be a named export: `get`
|
|
37
|
+
`export { handler as get };`,
|
|
38
|
+
].join('\n'),
|
|
39
|
+
loader: 'ts',
|
|
40
|
+
resolveDir: path.dirname(args.path),
|
|
41
|
+
}));
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=generate-entry-plugin.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LwrGlobalConfig } from '@lwrjs/types';
|
|
2
|
+
export interface BuildOptions {
|
|
3
|
+
outputDir?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Resolve configurations, generate a server build module, and bundle
|
|
7
|
+
* the LWR server. The bundled server will be written to the file system.
|
|
8
|
+
*
|
|
9
|
+
* @param {LwrGlobalConfig} configArg - programmatic LWR global config
|
|
10
|
+
* @param {BuildOptions} options - server build options
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildServer(configArg?: LwrGlobalConfig, options?: BuildOptions): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=server-build.d.ts.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import esbuild from 'esbuild';
|
|
4
|
+
import { performance } from 'perf_hooks';
|
|
5
|
+
import { getFeatureFlags, logger } from '@lwrjs/shared-utils';
|
|
6
|
+
import { LWR_VERSION } from '@lwrjs/config';
|
|
7
|
+
import generateLwrEntry from './plugins/generate-entry-plugin.js';
|
|
8
|
+
import buildLwrServer from './plugins/build-server-plugin.js';
|
|
9
|
+
async function build(outputDir, config) {
|
|
10
|
+
// building specifically for MRT/Lambda
|
|
11
|
+
await esbuild.build({
|
|
12
|
+
entryPoints: ['./lwr.entry.js'],
|
|
13
|
+
bundle: true,
|
|
14
|
+
sourcemap: true,
|
|
15
|
+
format: 'cjs',
|
|
16
|
+
platform: 'node',
|
|
17
|
+
logLevel: 'silent',
|
|
18
|
+
// Alow us to roll up additional require() dependencies
|
|
19
|
+
mainFields: ['module', 'main'],
|
|
20
|
+
external: [
|
|
21
|
+
// node native dependencies
|
|
22
|
+
'node:*',
|
|
23
|
+
// fsevents used by chokidar used by nunjucks
|
|
24
|
+
'fsevents',
|
|
25
|
+
// Used for express compression. Should be an optional dependency ans should be omitted at runtime
|
|
26
|
+
'iltorb',
|
|
27
|
+
'shrink-ray-current',
|
|
28
|
+
// Work in progress to isolate
|
|
29
|
+
'esbuild*',
|
|
30
|
+
// Used in the NPM module provider. Once Static Module Bundler is done we should be able to remove this
|
|
31
|
+
'esinstall',
|
|
32
|
+
// Rollup resolves plugins in node_modules at runtime. More investigation needed.
|
|
33
|
+
'rollup',
|
|
34
|
+
'rollup-plugin-*',
|
|
35
|
+
// We can remove this once we have the module bundler working
|
|
36
|
+
'@lwrjs/loader',
|
|
37
|
+
],
|
|
38
|
+
banner: {
|
|
39
|
+
js: createEnvVarHeader(),
|
|
40
|
+
},
|
|
41
|
+
plugins: [generateLwrEntry(), buildLwrServer(config)],
|
|
42
|
+
// MRT expects an entry point named `ssr.js`
|
|
43
|
+
outfile: path.join(outputDir, 'ssr.js'),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Resolve configurations, generate a server build module, and bundle
|
|
48
|
+
* the LWR server. The bundled server will be written to the file system.
|
|
49
|
+
*
|
|
50
|
+
* @param {LwrGlobalConfig} configArg - programmatic LWR global config
|
|
51
|
+
* @param {BuildOptions} options - server build options
|
|
52
|
+
*/
|
|
53
|
+
export async function buildServer(configArg, options) {
|
|
54
|
+
const startTime = performance.now();
|
|
55
|
+
const outputDir = path.join(configArg?.rootDir || process.cwd(), options?.outputDir || '/build');
|
|
56
|
+
await fs.ensureDir(outputDir);
|
|
57
|
+
await build(outputDir, configArg);
|
|
58
|
+
const endTime = performance.now();
|
|
59
|
+
const timeDiff = endTime - startTime;
|
|
60
|
+
logger.info(`[Server Build] successfully built the server in ${Math.round(timeDiff)} ms`);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build in important environment variables set during build
|
|
64
|
+
*/
|
|
65
|
+
function createEnvVarHeader() {
|
|
66
|
+
// Setup global environment variables
|
|
67
|
+
const currentFeatureFlags = getFeatureFlags();
|
|
68
|
+
let initFatureFlagsString = '';
|
|
69
|
+
for (const [key, val] of Object.entries(currentFeatureFlags)) {
|
|
70
|
+
if (val) {
|
|
71
|
+
initFatureFlagsString += `process.env.${key} = 'true'`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return `globalThis.LWR_VERSION='${LWR_VERSION}';${initFatureFlagsString}`;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=server-build.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lwrjs/tools",
|
|
3
|
+
"license": "MIT",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"version": "0.9.0-alpha.14",
|
|
8
|
+
"homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/salesforce/lwr.git",
|
|
12
|
+
"directory": "packages/@lwrjs/tools"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/salesforce/lwr/issues"
|
|
16
|
+
},
|
|
17
|
+
"type": "module",
|
|
18
|
+
"types": "build/es/index.d.ts",
|
|
19
|
+
"module": "build/es/index.js",
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc -b"
|
|
22
|
+
},
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"import": "./build/es/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"build/**/*.js",
|
|
30
|
+
"build/**/*.cjs",
|
|
31
|
+
"build/**/*.d.ts",
|
|
32
|
+
"package.cjs"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@lwrjs/core": "0.9.0-alpha.14",
|
|
36
|
+
"esbuild": "^0.17.4"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@lwrjs/types": "0.9.0-alpha.14"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"lwc": "2.x"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=14.15.4 <19"
|
|
46
|
+
},
|
|
47
|
+
"gitHead": "64e0ba617151429da6e09f1a9686628f64183d25"
|
|
48
|
+
}
|