@nerest/nerest 0.0.5 → 0.0.7
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/README.md +33 -2
- package/build/excludes/empty-module +1 -0
- package/build/excludes/index.ts +20 -0
- package/build/index.ts +23 -0
- package/dist/build/excludes/index.d.ts +8 -0
- package/dist/build/excludes/index.js +23 -0
- package/dist/build/index.js +20 -0
- package/dist/server/development.js +4 -0
- package/dist/server/parts/runtime-hook.d.ts +2 -0
- package/dist/server/parts/runtime-hook.js +32 -0
- package/package.json +25 -18
- package/schemas/nerest-build.schema.d.ts +16 -0
- package/schemas/nerest-build.schema.json +22 -0
- package/server/development.ts +5 -0
- package/server/parts/runtime-hook.ts +35 -0
- package/server/production.ts +7 -0
package/README.md
CHANGED
|
@@ -61,11 +61,42 @@ Additional environment variables which can be setup for a runtime:
|
|
|
61
61
|
|
|
62
62
|
### JSON Configuration
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
You can configure the output of `nerest build` by placing an optional `nerest-build.json` configuration file in the root of the micro frontend. The full schema of this file is located in [schemas/nerest-build.schema.json](schemas/nerest-build.schema.json).
|
|
65
|
+
|
|
66
|
+
#### excludes: `string[]`
|
|
67
|
+
|
|
68
|
+
Excludes modules from the client build and replaces their imports with imports of an empty module instead. You can use this to exclude either JS or CSS modules from the final build.
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
"excludes": ["@scope/name"]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### externals: `Record<string, string>`
|
|
75
|
+
|
|
76
|
+
Excludes modules from the client build and maps them to globally available constants instead. You can use this to share common dependencies between different micro frontends by exposing them on the `window` object. For example:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
"externals": {
|
|
80
|
+
"react": "window.React",
|
|
81
|
+
"react-dom": "window['ReactDOM']"
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Here `react` and `react-dom` imports will be replaced with accessing the respective `window` constants.
|
|
65
86
|
|
|
66
87
|
### Runtime Hooks
|
|
67
88
|
|
|
68
|
-
|
|
89
|
+
If the module `nerest-runtime.ts` exists in the root of the micro frontend and exports a default function, this function will be executed when the server starts, and the fastify app instance will be passed to it as its only argument. Example of `nerest-runtime.ts`:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import type { FastifyInstance } from 'fastify';
|
|
93
|
+
|
|
94
|
+
export default function (app: FastifyInstance) {
|
|
95
|
+
console.log('Hello from nerest-runtime.ts');
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
This runtime hook can be used to adjust fastify settings, register additional plugins or add custom routes.
|
|
69
100
|
|
|
70
101
|
## Development
|
|
71
102
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/* Empty module to replace excluded imports with. */
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps list of imports into a list of rollup aliases that resolve
|
|
3
|
+
* into an empty module.
|
|
4
|
+
*/
|
|
5
|
+
export function excludes(list: string[] | undefined) {
|
|
6
|
+
return list?.map((exclude) => ({
|
|
7
|
+
// Excluding '@some/package' should exclude both '@some/package' and
|
|
8
|
+
// '@some/package/...` imports
|
|
9
|
+
find: new RegExp(`^${escapeRegExp(exclude)}($|\\/.*)`),
|
|
10
|
+
replacement: '@nerest/nerest/build/excludes/empty-module',
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Escapes string to use inside of a regular expression.
|
|
16
|
+
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
|
17
|
+
*/
|
|
18
|
+
function escapeRegExp(str: string) {
|
|
19
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
20
|
+
}
|
package/build/index.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
3
4
|
|
|
4
5
|
import vite from 'vite';
|
|
5
6
|
import type { InlineConfig } from 'vite';
|
|
7
|
+
import { viteExternalsPlugin } from 'vite-plugin-externals';
|
|
6
8
|
|
|
7
9
|
import { loadApps } from '../server/parts/apps';
|
|
10
|
+
import type { BuildConfiguration } from '../schemas/nerest-build.schema';
|
|
11
|
+
import { excludes } from './excludes';
|
|
8
12
|
|
|
9
13
|
export async function buildMicroFrontend() {
|
|
10
14
|
const root = process.cwd();
|
|
@@ -19,6 +23,8 @@ export async function buildMicroFrontend() {
|
|
|
19
23
|
);
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
const buildConfig = await readBuildConfig(root);
|
|
27
|
+
|
|
22
28
|
// Build client
|
|
23
29
|
// TODO: extract shared parts between build/index.ts and server/index.ts
|
|
24
30
|
// into a shared config
|
|
@@ -40,6 +46,14 @@ export async function buildMicroFrontend() {
|
|
|
40
46
|
},
|
|
41
47
|
},
|
|
42
48
|
},
|
|
49
|
+
resolve: {
|
|
50
|
+
// excludes - map buildConfig.excludes packages to an empty module
|
|
51
|
+
alias: excludes(buildConfig?.excludes),
|
|
52
|
+
},
|
|
53
|
+
plugins: [
|
|
54
|
+
// externals - map buildConfig.externals packages to a global variable on window
|
|
55
|
+
viteExternalsPlugin(buildConfig?.externals, { useWindow: false }),
|
|
56
|
+
],
|
|
43
57
|
};
|
|
44
58
|
|
|
45
59
|
console.log('Producing production client build...');
|
|
@@ -80,3 +94,12 @@ async function buildAppsManifest(root: string, staticPath: string) {
|
|
|
80
94
|
{ encoding: 'utf-8' }
|
|
81
95
|
);
|
|
82
96
|
}
|
|
97
|
+
|
|
98
|
+
// TODO: error handling
|
|
99
|
+
async function readBuildConfig(root: string) {
|
|
100
|
+
const configPath = path.join(root, 'nerest-build.json');
|
|
101
|
+
if (existsSync(configPath)) {
|
|
102
|
+
const content = await fs.readFile(configPath, { encoding: 'utf-8' });
|
|
103
|
+
return JSON.parse(content) as BuildConfiguration;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.excludes = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Maps list of imports into a list of rollup aliases that resolve
|
|
6
|
+
* into an empty module.
|
|
7
|
+
*/
|
|
8
|
+
function excludes(list) {
|
|
9
|
+
return list?.map((exclude) => ({
|
|
10
|
+
// Excluding '@some/package' should exclude both '@some/package' and
|
|
11
|
+
// '@some/package/...` imports
|
|
12
|
+
find: new RegExp(`^${escapeRegExp(exclude)}($|\\/.*)`),
|
|
13
|
+
replacement: '@nerest/nerest/build/excludes/empty-module',
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
exports.excludes = excludes;
|
|
17
|
+
/**
|
|
18
|
+
* Escapes string to use inside of a regular expression.
|
|
19
|
+
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
|
20
|
+
*/
|
|
21
|
+
function escapeRegExp(str) {
|
|
22
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
23
|
+
}
|
package/dist/build/index.js
CHANGED
|
@@ -6,8 +6,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.buildMicroFrontend = void 0;
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
|
+
const fs_1 = require("fs");
|
|
9
10
|
const vite_1 = __importDefault(require("vite"));
|
|
11
|
+
const vite_plugin_externals_1 = require("vite-plugin-externals");
|
|
10
12
|
const apps_1 = require("../server/parts/apps");
|
|
13
|
+
const excludes_1 = require("./excludes");
|
|
11
14
|
async function buildMicroFrontend() {
|
|
12
15
|
const root = process.cwd();
|
|
13
16
|
const staticPath = process.env.NEREST_STATIC_PATH;
|
|
@@ -17,6 +20,7 @@ async function buildMicroFrontend() {
|
|
|
17
20
|
if (!staticPath) {
|
|
18
21
|
throw new Error('NEREST_STATIC_PATH environment variable is not set but is required for the production build');
|
|
19
22
|
}
|
|
23
|
+
const buildConfig = await readBuildConfig(root);
|
|
20
24
|
// Build client
|
|
21
25
|
// TODO: extract shared parts between build/index.ts and server/index.ts
|
|
22
26
|
// into a shared config
|
|
@@ -38,6 +42,14 @@ async function buildMicroFrontend() {
|
|
|
38
42
|
},
|
|
39
43
|
},
|
|
40
44
|
},
|
|
45
|
+
resolve: {
|
|
46
|
+
// excludes - map buildConfig.excludes packages to an empty module
|
|
47
|
+
alias: (0, excludes_1.excludes)(buildConfig?.excludes),
|
|
48
|
+
},
|
|
49
|
+
plugins: [
|
|
50
|
+
// externals - map buildConfig.externals packages to a global variable on window
|
|
51
|
+
(0, vite_plugin_externals_1.viteExternalsPlugin)(buildConfig?.externals, { useWindow: false }),
|
|
52
|
+
],
|
|
41
53
|
};
|
|
42
54
|
console.log('Producing production client build...');
|
|
43
55
|
await vite_1.default.build(clientConfig);
|
|
@@ -70,3 +82,11 @@ async function buildAppsManifest(root, staticPath) {
|
|
|
70
82
|
const apps = await (0, apps_1.loadApps)(root, staticPath);
|
|
71
83
|
await promises_1.default.writeFile(path_1.default.join(root, 'build/nerest-manifest.json'), JSON.stringify(apps), { encoding: 'utf-8' });
|
|
72
84
|
}
|
|
85
|
+
// TODO: error handling
|
|
86
|
+
async function readBuildConfig(root) {
|
|
87
|
+
const configPath = path_1.default.join(root, 'nerest-build.json');
|
|
88
|
+
if ((0, fs_1.existsSync)(configPath)) {
|
|
89
|
+
const content = await promises_1.default.readFile(configPath, { encoding: 'utf-8' });
|
|
90
|
+
return JSON.parse(content);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -16,6 +16,8 @@ const preview_1 = require("./parts/preview");
|
|
|
16
16
|
const validator_1 = require("./parts/validator");
|
|
17
17
|
const swagger_1 = require("./parts/swagger");
|
|
18
18
|
const k8s_probes_1 = require("./parts/k8s-probes");
|
|
19
|
+
const runtime_hook_1 = require("./parts/runtime-hook");
|
|
20
|
+
// eslint-disable-next-line max-statements
|
|
19
21
|
async function runDevelopmentServer() {
|
|
20
22
|
const root = process.cwd();
|
|
21
23
|
// TODO: move build config into a separate file
|
|
@@ -136,6 +138,8 @@ async function runDevelopmentServer() {
|
|
|
136
138
|
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, content-type, Authorization');
|
|
137
139
|
},
|
|
138
140
|
});
|
|
141
|
+
// Execute runtime hook in nerest-runtime.ts if it exists
|
|
142
|
+
await (0, runtime_hook_1.runRuntimeHook)(app, () => viteSsr.ssrLoadModule('/nerest-runtime.ts'));
|
|
139
143
|
// TODO: remove hardcoded port
|
|
140
144
|
await app.listen({
|
|
141
145
|
host: '0.0.0.0',
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runRuntimeHook = void 0;
|
|
4
|
+
// Load the runtime hook module and run it if it exists, passing down our
|
|
5
|
+
// fastify instance. This hook can be used to modify fastify settings, add
|
|
6
|
+
// plugins or routes on an individual app level.
|
|
7
|
+
async function runRuntimeHook(app, loader) {
|
|
8
|
+
let module;
|
|
9
|
+
try {
|
|
10
|
+
module = (await loader());
|
|
11
|
+
}
|
|
12
|
+
catch { }
|
|
13
|
+
if (typeof module?.default === 'function') {
|
|
14
|
+
// If module exists and exports a default function, execute it and
|
|
15
|
+
// pass down the fastify instance
|
|
16
|
+
try {
|
|
17
|
+
await module.default(app);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
console.error('Failed to execute runtime hook', e);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else if (module) {
|
|
25
|
+
console.error("Runtime hook found, but doesn't export default function!");
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
console.log('Runtime hook not found, skipping...');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.runRuntimeHook = runRuntimeHook;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nerest/nerest",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "React micro frontend framework",
|
|
5
5
|
"homepage": "https://github.com/nerestjs/nerest#readme",
|
|
6
6
|
"repository": {
|
|
@@ -15,13 +15,15 @@
|
|
|
15
15
|
"/bin",
|
|
16
16
|
"/build",
|
|
17
17
|
"/client",
|
|
18
|
+
"/schemas",
|
|
18
19
|
"/server",
|
|
19
20
|
"/README.md"
|
|
20
21
|
],
|
|
21
22
|
"scripts": {
|
|
22
23
|
"build": "tsc -p tsconfig.json -d",
|
|
23
24
|
"lint": "eslint --ext .ts server bin",
|
|
24
|
-
"prepare": "simple-git-hooks"
|
|
25
|
+
"prepare": "simple-git-hooks",
|
|
26
|
+
"typegen": "json2ts -i 'schemas/**/*.json' -o schemas --bannerComment ''"
|
|
25
27
|
},
|
|
26
28
|
"simple-git-hooks": {
|
|
27
29
|
"pre-commit": "npx lint-staged"
|
|
@@ -40,6 +42,9 @@
|
|
|
40
42
|
},
|
|
41
43
|
"prettier": "@tinkoff/prettier-config",
|
|
42
44
|
"eslintConfig": {
|
|
45
|
+
"parserOptions": {
|
|
46
|
+
"project": true
|
|
47
|
+
},
|
|
43
48
|
"extends": [
|
|
44
49
|
"@tinkoff/eslint-config/lib",
|
|
45
50
|
"@tinkoff/eslint-config/jest",
|
|
@@ -47,31 +52,33 @@
|
|
|
47
52
|
]
|
|
48
53
|
},
|
|
49
54
|
"dependencies": {
|
|
50
|
-
"@fastify/static": "^6.
|
|
51
|
-
"@fastify/swagger": "^8.
|
|
52
|
-
"@fastify/swagger-ui": "^1.
|
|
55
|
+
"@fastify/static": "^6.12.0",
|
|
56
|
+
"@fastify/swagger": "^8.12.0",
|
|
57
|
+
"@fastify/swagger-ui": "^1.10.1",
|
|
53
58
|
"ajv": "^8.12.0",
|
|
54
59
|
"ajv-formats": "^2.1.1",
|
|
55
|
-
"dotenv": "^16.1
|
|
56
|
-
"fast-uri": "^2.
|
|
57
|
-
"fastify": "^4.
|
|
60
|
+
"dotenv": "^16.3.1",
|
|
61
|
+
"fast-uri": "^2.3.0",
|
|
62
|
+
"fastify": "^4.24.3",
|
|
58
63
|
"fastify-graceful-shutdown": "^3.5.1",
|
|
59
64
|
"nanoid": "^3.3.6",
|
|
60
|
-
"vite": "^4.
|
|
65
|
+
"vite": "^4.5.0",
|
|
66
|
+
"vite-plugin-externals": "^0.6.2"
|
|
61
67
|
},
|
|
62
68
|
"devDependencies": {
|
|
63
|
-
"@tinkoff/eslint-config": "^1.
|
|
64
|
-
"@tinkoff/eslint-config-react": "^1.
|
|
69
|
+
"@tinkoff/eslint-config": "^1.54.4",
|
|
70
|
+
"@tinkoff/eslint-config-react": "^1.54.4",
|
|
65
71
|
"@tinkoff/prettier-config": "^1.52.1",
|
|
66
|
-
"@types/react": "^18.2.
|
|
67
|
-
"@types/react-dom": "^18.2.
|
|
68
|
-
"jest": "^29.
|
|
69
|
-
"
|
|
72
|
+
"@types/react": "^18.2.33",
|
|
73
|
+
"@types/react-dom": "^18.2.14",
|
|
74
|
+
"jest": "^29.7.0",
|
|
75
|
+
"json-schema-to-typescript": "^13.1.1",
|
|
76
|
+
"lint-staged": "^15.0.2",
|
|
70
77
|
"react": "^18.2.0",
|
|
71
78
|
"react-dom": "^18.2.0",
|
|
72
|
-
"simple-git-hooks": "^2.
|
|
73
|
-
"sort-package-json": "^2.
|
|
74
|
-
"typescript": "^5.
|
|
79
|
+
"simple-git-hooks": "^2.9.0",
|
|
80
|
+
"sort-package-json": "^2.6.0",
|
|
81
|
+
"typescript": "^5.2.2"
|
|
75
82
|
},
|
|
76
83
|
"peerDependencies": {
|
|
77
84
|
"react": "^18.0.0",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build configuration placed as nerest-build.schema.json in the root of the application.
|
|
3
|
+
*/
|
|
4
|
+
export interface BuildConfiguration {
|
|
5
|
+
/**
|
|
6
|
+
* Excludes modules from the client build and replaces them with empty modules instead.
|
|
7
|
+
*/
|
|
8
|
+
excludes?: string[];
|
|
9
|
+
/**
|
|
10
|
+
* Excludes modules from the client build and maps them to globally available constants instead.
|
|
11
|
+
*/
|
|
12
|
+
externals?: {
|
|
13
|
+
[k: string]: string;
|
|
14
|
+
};
|
|
15
|
+
[k: string]: unknown;
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
+
"title": "Build Configuration",
|
|
4
|
+
"description": "Build configuration placed as nerest-build.schema.json in the root of the application.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"excludes": {
|
|
8
|
+
"description": "Excludes modules from the client build and replaces them with empty modules instead.",
|
|
9
|
+
"type": "array",
|
|
10
|
+
"items": {
|
|
11
|
+
"type": "string"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"externals": {
|
|
15
|
+
"description": "Excludes modules from the client build and maps them to globally available constants instead.",
|
|
16
|
+
"type": "object",
|
|
17
|
+
"additionalProperties": {
|
|
18
|
+
"type": "string"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
package/server/development.ts
CHANGED
|
@@ -17,7 +17,9 @@ import { renderPreviewPage } from './parts/preview';
|
|
|
17
17
|
import { validator } from './parts/validator';
|
|
18
18
|
import { setupSwagger } from './parts/swagger';
|
|
19
19
|
import { setupK8SProbes } from './parts/k8s-probes';
|
|
20
|
+
import { runRuntimeHook } from './parts/runtime-hook';
|
|
20
21
|
|
|
22
|
+
// eslint-disable-next-line max-statements
|
|
21
23
|
export async function runDevelopmentServer() {
|
|
22
24
|
const root = process.cwd();
|
|
23
25
|
|
|
@@ -171,6 +173,9 @@ export async function runDevelopmentServer() {
|
|
|
171
173
|
},
|
|
172
174
|
});
|
|
173
175
|
|
|
176
|
+
// Execute runtime hook in nerest-runtime.ts if it exists
|
|
177
|
+
await runRuntimeHook(app, () => viteSsr.ssrLoadModule('/nerest-runtime.ts'));
|
|
178
|
+
|
|
174
179
|
// TODO: remove hardcoded port
|
|
175
180
|
await app.listen({
|
|
176
181
|
host: '0.0.0.0',
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { FastifyInstance } from 'fastify';
|
|
2
|
+
|
|
3
|
+
type RuntimeHookModule = {
|
|
4
|
+
default: (app: FastifyInstance) => unknown;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// Load the runtime hook module and run it if it exists, passing down our
|
|
8
|
+
// fastify instance. This hook can be used to modify fastify settings, add
|
|
9
|
+
// plugins or routes on an individual app level.
|
|
10
|
+
export async function runRuntimeHook(
|
|
11
|
+
app: FastifyInstance,
|
|
12
|
+
loader: () => Promise<Record<string, any>>
|
|
13
|
+
) {
|
|
14
|
+
let module: RuntimeHookModule | undefined;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
module = (await loader()) as RuntimeHookModule;
|
|
18
|
+
} catch {}
|
|
19
|
+
|
|
20
|
+
if (typeof module?.default === 'function') {
|
|
21
|
+
// If module exists and exports a default function, execute it and
|
|
22
|
+
// pass down the fastify instance
|
|
23
|
+
try {
|
|
24
|
+
await module.default(app);
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error('Failed to execute runtime hook', e);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
} else if (module) {
|
|
30
|
+
console.error("Runtime hook found, but doesn't export default function!");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
} else {
|
|
33
|
+
console.log('Runtime hook not found, skipping...');
|
|
34
|
+
}
|
|
35
|
+
}
|
package/server/production.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { setupSwagger } from './parts/swagger';
|
|
|
12
12
|
import { validator } from './parts/validator';
|
|
13
13
|
import { renderPreviewPage } from './parts/preview';
|
|
14
14
|
import { setupK8SProbes } from './parts/k8s-probes';
|
|
15
|
+
import { runRuntimeHook } from './parts/runtime-hook';
|
|
15
16
|
|
|
16
17
|
// TODO: refactor to merge the similar parts between production and development server?
|
|
17
18
|
async function runProductionServer() {
|
|
@@ -103,6 +104,12 @@ async function runProductionServer() {
|
|
|
103
104
|
await setupK8SProbes(app);
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
// Execute runtime hook in nerest-runtime.ts if it exists
|
|
108
|
+
await runRuntimeHook(app, async () => {
|
|
109
|
+
const glob = import.meta.glob('/nerest-runtime.ts', { eager: true });
|
|
110
|
+
return glob['/nerest-runtime.ts'];
|
|
111
|
+
});
|
|
112
|
+
|
|
106
113
|
// TODO: remove hardcoded port
|
|
107
114
|
await app.listen({
|
|
108
115
|
host: '0.0.0.0',
|