@web-ts-toolkit/express-runtime 0.26.0 → 0.27.0
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 +2 -0
- package/chunk-SOW7OLVN.mjs +221 -0
- package/cli-api.d.mts +237 -0
- package/cli-api.d.ts +237 -0
- package/cli-api.js +1084 -0
- package/cli-api.mjs +839 -0
- package/cli.js +158 -52
- package/index.mjs +7 -213
- package/package.json +7 -1
package/cli.js
CHANGED
|
@@ -6,6 +6,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
9
16
|
var __copyProps = (to, from, except, desc) => {
|
|
10
17
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
18
|
for (let key of __getOwnPropNames(from))
|
|
@@ -23,22 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
30
|
mod
|
|
24
31
|
));
|
|
25
32
|
|
|
26
|
-
// src/cli-utils.ts
|
|
27
|
-
var import_node_url = require("url");
|
|
28
|
-
var import_node_path = require("path");
|
|
29
|
-
var import_node_fs = require("fs");
|
|
30
|
-
var import_node_module = require("module");
|
|
31
|
-
var import_node_child_process = require("child_process");
|
|
32
|
-
|
|
33
33
|
// src/index.ts
|
|
34
|
-
var import_node_http = __toESM(require("http"));
|
|
35
|
-
var import_express = __toESM(require("express"));
|
|
36
|
-
var import_serverless_http = __toESM(require("serverless-http"));
|
|
37
|
-
var defaultLogger = {
|
|
38
|
-
log: (...args) => console.log(...args),
|
|
39
|
-
error: (...args) => console.error(...args),
|
|
40
|
-
debug: (...args) => console.debug(...args)
|
|
41
|
-
};
|
|
42
34
|
function applySettings(app, options) {
|
|
43
35
|
if (options.disablePoweredBy !== false) {
|
|
44
36
|
app.disable("x-powered-by");
|
|
@@ -83,8 +75,6 @@ function createExpressApp(options = {}) {
|
|
|
83
75
|
}
|
|
84
76
|
return app;
|
|
85
77
|
}
|
|
86
|
-
var DEFAULT_SIGNALS = ["SIGINT", "SIGTERM"];
|
|
87
|
-
var DEFAULT_SHUTDOWN_TIMEOUT = 5e3;
|
|
88
78
|
function normalizePort(val) {
|
|
89
79
|
if (val === void 0 || val === "") {
|
|
90
80
|
const envPort = process.env.PORT;
|
|
@@ -194,10 +184,24 @@ function startLocalServer(app, options = {}) {
|
|
|
194
184
|
shutdown
|
|
195
185
|
};
|
|
196
186
|
}
|
|
187
|
+
var import_node_http, import_express, import_serverless_http, defaultLogger, DEFAULT_SIGNALS, DEFAULT_SHUTDOWN_TIMEOUT;
|
|
188
|
+
var init_src = __esm({
|
|
189
|
+
"src/index.ts"() {
|
|
190
|
+
"use strict";
|
|
191
|
+
import_node_http = __toESM(require("http"));
|
|
192
|
+
import_express = __toESM(require("express"));
|
|
193
|
+
import_serverless_http = __toESM(require("serverless-http"));
|
|
194
|
+
defaultLogger = {
|
|
195
|
+
log: (...args) => console.log(...args),
|
|
196
|
+
error: (...args) => console.error(...args),
|
|
197
|
+
debug: (...args) => console.debug(...args)
|
|
198
|
+
};
|
|
199
|
+
DEFAULT_SIGNALS = ["SIGINT", "SIGTERM"];
|
|
200
|
+
DEFAULT_SHUTDOWN_TIMEOUT = 5e3;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
197
203
|
|
|
198
204
|
// src/cli-utils.ts
|
|
199
|
-
var import_meta = {};
|
|
200
|
-
var CLI_VERSION = "0.0.0-PLACEHOLDER";
|
|
201
205
|
function readValue(argv, index, name) {
|
|
202
206
|
const value = argv[index + 1];
|
|
203
207
|
if (value === void 0 || value.startsWith("--")) {
|
|
@@ -307,8 +311,6 @@ function isHelp(arg) {
|
|
|
307
311
|
function isSubcommand(arg) {
|
|
308
312
|
return arg === "dev" || arg === "build" || arg === "start" || arg === "build-serverless" || arg === "start-serverless";
|
|
309
313
|
}
|
|
310
|
-
var DEFAULT_WATCH_EXTENSIONS = ["ts", "js", "mjs", "cjs", "json"];
|
|
311
|
-
var DEFAULT_WATCH_DELAY = 500;
|
|
312
314
|
function parseRepeatable(argv, index, arg, list) {
|
|
313
315
|
const value = readValue(argv, index, arg);
|
|
314
316
|
for (const part of value.split(",")) {
|
|
@@ -681,9 +683,6 @@ function loadEnvFiles(paths) {
|
|
|
681
683
|
}
|
|
682
684
|
}
|
|
683
685
|
}
|
|
684
|
-
var moduleRequire = (0, import_node_module.createRequire)(
|
|
685
|
-
typeof import_meta !== "undefined" && import_meta.url || (0, import_node_path.resolve)(process.cwd(), "x").replace(/x$/, "")
|
|
686
|
-
);
|
|
687
686
|
async function preloadModules(modules) {
|
|
688
687
|
for (const mod of modules) {
|
|
689
688
|
moduleRequire(mod);
|
|
@@ -763,8 +762,6 @@ function runWithWatch(args) {
|
|
|
763
762
|
process.on("SIGTERM", shutdown);
|
|
764
763
|
spawnChild();
|
|
765
764
|
}
|
|
766
|
-
var TEMP_BUILD_ENTRY_FILENAME = ".express-runtime-build-entry.ts";
|
|
767
|
-
var TEMP_SERVERLESS_ENTRY_FILENAME = ".express-runtime-build-serverless-entry.ts";
|
|
768
765
|
function generateServerlessEntry(appPath, initPath) {
|
|
769
766
|
const absAppPath = (0, import_node_path.resolve)(process.cwd(), appPath);
|
|
770
767
|
const absInitPath = initPath ? (0, import_node_path.resolve)(process.cwd(), initPath) : void 0;
|
|
@@ -796,11 +793,11 @@ function generateRuntimeEntry(appPath, initPath) {
|
|
|
796
793
|
}
|
|
797
794
|
return lines.join("\n") + "\n";
|
|
798
795
|
}
|
|
799
|
-
async function
|
|
796
|
+
async function buildBundleFromEntryContent(args) {
|
|
800
797
|
const tsupModule = await import("tsup");
|
|
801
798
|
const { build } = tsupModule;
|
|
802
|
-
const tempEntryPath = (0, import_node_path.resolve)(process.cwd(), tempEntryFilename);
|
|
803
|
-
(0, import_node_fs.writeFileSync)(tempEntryPath, entryContent, "utf8");
|
|
799
|
+
const tempEntryPath = (0, import_node_path.resolve)(process.cwd(), args.tempEntryFilename);
|
|
800
|
+
(0, import_node_fs.writeFileSync)(tempEntryPath, args.entryContent, "utf8");
|
|
804
801
|
try {
|
|
805
802
|
await build({
|
|
806
803
|
config: false,
|
|
@@ -819,10 +816,18 @@ async function buildBundle(args, tempEntryFilename, entryContent) {
|
|
|
819
816
|
}
|
|
820
817
|
}
|
|
821
818
|
async function buildRuntime(args) {
|
|
822
|
-
await
|
|
819
|
+
const { runBuildEntryCommand: runBuildEntryCommand2 } = await Promise.resolve().then(() => (init_cli_api(), cli_api_exports));
|
|
820
|
+
await runBuildEntryCommand2(args, {
|
|
821
|
+
generateEntry: generateRuntimeEntry,
|
|
822
|
+
tempEntryFilename: TEMP_BUILD_ENTRY_FILENAME
|
|
823
|
+
});
|
|
823
824
|
}
|
|
824
825
|
async function buildServerless(args) {
|
|
825
|
-
await
|
|
826
|
+
const { runBuildEntryCommand: runBuildEntryCommand2 } = await Promise.resolve().then(() => (init_cli_api(), cli_api_exports));
|
|
827
|
+
await runBuildEntryCommand2(args, {
|
|
828
|
+
generateEntry: generateServerlessEntry,
|
|
829
|
+
tempEntryFilename: TEMP_SERVERLESS_ENTRY_FILENAME
|
|
830
|
+
});
|
|
826
831
|
}
|
|
827
832
|
function collectBody(req) {
|
|
828
833
|
return new Promise((resolve, reject) => {
|
|
@@ -913,36 +918,120 @@ async function loadHandler(handlerPath) {
|
|
|
913
918
|
}
|
|
914
919
|
return exported;
|
|
915
920
|
}
|
|
921
|
+
var import_node_url, import_node_path, import_node_fs, import_node_module, import_node_child_process, import_meta, CLI_VERSION, DEFAULT_WATCH_EXTENSIONS, DEFAULT_WATCH_DELAY, moduleRequire, TEMP_BUILD_ENTRY_FILENAME, TEMP_SERVERLESS_ENTRY_FILENAME;
|
|
922
|
+
var init_cli_utils = __esm({
|
|
923
|
+
"src/cli-utils.ts"() {
|
|
924
|
+
"use strict";
|
|
925
|
+
import_node_url = require("url");
|
|
926
|
+
import_node_path = require("path");
|
|
927
|
+
import_node_fs = require("fs");
|
|
928
|
+
import_node_module = require("module");
|
|
929
|
+
import_node_child_process = require("child_process");
|
|
930
|
+
init_src();
|
|
931
|
+
import_meta = {};
|
|
932
|
+
CLI_VERSION = "0.0.0-PLACEHOLDER";
|
|
933
|
+
DEFAULT_WATCH_EXTENSIONS = ["ts", "js", "mjs", "cjs", "json"];
|
|
934
|
+
DEFAULT_WATCH_DELAY = 500;
|
|
935
|
+
moduleRequire = (0, import_node_module.createRequire)(
|
|
936
|
+
typeof import_meta !== "undefined" && import_meta.url || (0, import_node_path.resolve)(process.cwd(), "x").replace(/x$/, "")
|
|
937
|
+
);
|
|
938
|
+
TEMP_BUILD_ENTRY_FILENAME = ".express-runtime-build-entry.ts";
|
|
939
|
+
TEMP_SERVERLESS_ENTRY_FILENAME = ".express-runtime-build-serverless-entry.ts";
|
|
940
|
+
}
|
|
941
|
+
});
|
|
916
942
|
|
|
917
|
-
// src/cli.ts
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
943
|
+
// src/cli-api.ts
|
|
944
|
+
var cli_api_exports = {};
|
|
945
|
+
__export(cli_api_exports, {
|
|
946
|
+
CLI_VERSION: () => CLI_VERSION,
|
|
947
|
+
applyServerlessResult: () => applyServerlessResult,
|
|
948
|
+
buildBundleFromEntryContent: () => buildBundleFromEntryContent,
|
|
949
|
+
buildChildArgs: () => buildChildArgs,
|
|
950
|
+
buildRuntime: () => buildRuntime,
|
|
951
|
+
buildServerless: () => buildServerless,
|
|
952
|
+
createServerlessAdapterApp: () => createServerlessAdapterApp,
|
|
953
|
+
extractExport: () => extractExport,
|
|
954
|
+
generateRuntimeEntry: () => generateRuntimeEntry,
|
|
955
|
+
generateServerlessEntry: () => generateServerlessEntry,
|
|
956
|
+
isExpressApp: () => isExpressApp,
|
|
957
|
+
loadApp: () => loadApp,
|
|
958
|
+
loadBuiltApp: () => loadBuiltApp,
|
|
959
|
+
loadEnvFiles: () => loadEnvFiles,
|
|
960
|
+
loadHandler: () => loadHandler,
|
|
961
|
+
parseArgs: () => parseArgs,
|
|
962
|
+
parseEnvFile: () => parseEnvFile,
|
|
963
|
+
preloadModules: () => preloadModules,
|
|
964
|
+
printHelp: () => printHelp,
|
|
965
|
+
readValue: () => readValue,
|
|
966
|
+
resolveExport: () => resolveExport,
|
|
967
|
+
runBuildEntryCommand: () => runBuildEntryCommand,
|
|
968
|
+
runCliCommand: () => runCliCommand,
|
|
969
|
+
runDevCommand: () => runDevCommand,
|
|
970
|
+
runExpressDevCommand: () => runExpressDevCommand,
|
|
971
|
+
runWithWatch: () => runWithWatch,
|
|
972
|
+
toServerlessEvent: () => toServerlessEvent
|
|
973
|
+
});
|
|
974
|
+
async function runDevCommand(args, runner) {
|
|
975
|
+
if (args.watch.length > 0) {
|
|
976
|
+
(runner.watch ?? runWithWatch)(args);
|
|
921
977
|
return;
|
|
922
978
|
}
|
|
979
|
+
if (args.env.length > 0) {
|
|
980
|
+
loadEnvFiles(args.env);
|
|
981
|
+
}
|
|
982
|
+
await preloadModules(args.require);
|
|
983
|
+
const loaded = await runner.load(args.appPath);
|
|
984
|
+
runner.start(loaded, { ...args.options, exitAfterShutdown: true });
|
|
985
|
+
}
|
|
986
|
+
async function runExpressDevCommand(args) {
|
|
987
|
+
await runDevCommand(args, {
|
|
988
|
+
load: loadApp,
|
|
989
|
+
start: (app, options) => {
|
|
990
|
+
startLocalServer(app, options);
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
async function runBuildEntryCommand(args, options) {
|
|
995
|
+
if (options.allowInit === false && args.initPath) {
|
|
996
|
+
throw new Error(options.initErrorMessage ?? "This build command manages init automatically. Remove --init.");
|
|
997
|
+
}
|
|
998
|
+
await buildBundleFromEntryContent({
|
|
999
|
+
entryContent: options.generateEntry(args.appPath, args.initPath),
|
|
1000
|
+
tempEntryFilename: options.tempEntryFilename,
|
|
1001
|
+
outDir: args.outDir,
|
|
1002
|
+
outName: args.outName,
|
|
1003
|
+
format: args.format,
|
|
1004
|
+
target: args.target,
|
|
1005
|
+
external: args.external,
|
|
1006
|
+
clean: args.clean
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
async function runCliCommand(parsedArgs) {
|
|
923
1010
|
if (parsedArgs.subcommand === "dev") {
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
if (dev.env.length > 0) {
|
|
930
|
-
loadEnvFiles(dev.env);
|
|
931
|
-
}
|
|
932
|
-
await preloadModules(dev.require);
|
|
933
|
-
const app = await loadApp(dev.appPath);
|
|
934
|
-
startLocalServer(app, { ...dev.options, exitAfterShutdown: true });
|
|
935
|
-
} else if (parsedArgs.subcommand === "start") {
|
|
1011
|
+
await runExpressDevCommand(parsedArgs.dev);
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
if (parsedArgs.subcommand === "start") {
|
|
936
1015
|
const { start } = parsedArgs;
|
|
937
1016
|
if (start.env.length > 0) {
|
|
938
1017
|
loadEnvFiles(start.env);
|
|
939
1018
|
}
|
|
940
1019
|
await preloadModules(start.require);
|
|
941
1020
|
const { app, init } = await loadBuiltApp(start.appPath);
|
|
942
|
-
startLocalServer(app, {
|
|
943
|
-
|
|
1021
|
+
startLocalServer(app, {
|
|
1022
|
+
...start.options,
|
|
1023
|
+
init: init ? async () => {
|
|
1024
|
+
await init();
|
|
1025
|
+
} : void 0,
|
|
1026
|
+
exitAfterShutdown: true
|
|
1027
|
+
});
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
if (parsedArgs.subcommand === "build") {
|
|
944
1031
|
await buildRuntime(parsedArgs.build);
|
|
945
|
-
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
if (parsedArgs.subcommand === "start-serverless") {
|
|
946
1035
|
const { startServerless } = parsedArgs;
|
|
947
1036
|
if (startServerless.env.length > 0) {
|
|
948
1037
|
loadEnvFiles(startServerless.env);
|
|
@@ -951,9 +1040,26 @@ async function main() {
|
|
|
951
1040
|
const handler = await loadHandler(startServerless.handlerPath);
|
|
952
1041
|
const app = createServerlessAdapterApp(handler);
|
|
953
1042
|
startLocalServer(app, { ...startServerless.options, exitAfterShutdown: true });
|
|
954
|
-
|
|
955
|
-
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
await buildServerless(parsedArgs.buildServerless);
|
|
1046
|
+
}
|
|
1047
|
+
var init_cli_api = __esm({
|
|
1048
|
+
"src/cli-api.ts"() {
|
|
1049
|
+
"use strict";
|
|
1050
|
+
init_src();
|
|
1051
|
+
init_cli_utils();
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
|
|
1055
|
+
// src/cli.ts
|
|
1056
|
+
init_cli_api();
|
|
1057
|
+
async function main() {
|
|
1058
|
+
const parsedArgs = parseArgs(process.argv.slice(2));
|
|
1059
|
+
if (!parsedArgs) {
|
|
1060
|
+
return;
|
|
956
1061
|
}
|
|
1062
|
+
await runCliCommand(parsedArgs);
|
|
957
1063
|
}
|
|
958
1064
|
main().catch((error) => {
|
|
959
1065
|
const message = error instanceof Error ? error.message : String(error);
|
package/index.mjs
CHANGED
|
@@ -1,216 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
debug: (...args) => console.debug(...args)
|
|
9
|
-
};
|
|
10
|
-
function applySettings(app, options) {
|
|
11
|
-
if (options.disablePoweredBy !== false) {
|
|
12
|
-
app.disable("x-powered-by");
|
|
13
|
-
}
|
|
14
|
-
app.set("etag", options.etag ?? false);
|
|
15
|
-
app.set("trust proxy", options.trustProxy ?? false);
|
|
16
|
-
}
|
|
17
|
-
function applyMiddlewareList(app, list) {
|
|
18
|
-
if (list) {
|
|
19
|
-
for (const mw of list) {
|
|
20
|
-
app.use(mw);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
function applyRouters(app, options) {
|
|
25
|
-
const mounts = [];
|
|
26
|
-
if (options.router) mounts.push(options.router);
|
|
27
|
-
if (options.routers) mounts.push(...options.routers);
|
|
28
|
-
for (const mount of mounts) {
|
|
29
|
-
const path = typeof mount.path === "function" ? mount.path() : mount.path;
|
|
30
|
-
app.use(path, mount.handler);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function createExpressApp(options = {}) {
|
|
34
|
-
const app = express();
|
|
35
|
-
applySettings(app, options);
|
|
36
|
-
applyMiddlewareList(app, options.preMiddleware);
|
|
37
|
-
if (options.json !== false) {
|
|
38
|
-
app.use(express.json(options.json ?? { limit: "1mb" }));
|
|
39
|
-
}
|
|
40
|
-
if (options.urlencoded !== false) {
|
|
41
|
-
app.use(express.urlencoded(options.urlencoded ?? { extended: false, limit: "1mb" }));
|
|
42
|
-
}
|
|
43
|
-
applyMiddlewareList(app, options.middleware);
|
|
44
|
-
applyRouters(app, options);
|
|
45
|
-
applyMiddlewareList(app, options.postMiddleware);
|
|
46
|
-
if (options.finalize) {
|
|
47
|
-
options.finalize(app);
|
|
48
|
-
}
|
|
49
|
-
if (options.errorHandler) {
|
|
50
|
-
app.use(options.errorHandler);
|
|
51
|
-
}
|
|
52
|
-
return app;
|
|
53
|
-
}
|
|
54
|
-
function defaultRequestHook(req, maxBodyBytes = 1024 * 1024, logger = defaultLogger) {
|
|
55
|
-
if (!req.body || !Buffer.isBuffer(req.body)) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
if (req.body.length > maxBodyBytes) {
|
|
59
|
-
logger.debug?.(" Skipping oversized serverless body for content-type parsing");
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
try {
|
|
63
|
-
const bodyStr = req.body.toString("utf8");
|
|
64
|
-
const contentType = (req.headers?.["content-type"] ?? "").toLowerCase();
|
|
65
|
-
if (contentType.startsWith("application/json")) {
|
|
66
|
-
req.body = JSON.parse(bodyStr);
|
|
67
|
-
} else {
|
|
68
|
-
req.body = bodyStr;
|
|
69
|
-
}
|
|
70
|
-
} catch (error) {
|
|
71
|
-
logger.error("Failed to parse serverless request body:", error);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
function createServerlessHandler(app, options = {}) {
|
|
75
|
-
const logger = options.logger ?? defaultLogger;
|
|
76
|
-
const maxBodyBytes = options.maxBodyBytes ?? 1024 * 1024;
|
|
77
|
-
const requestHook = options.request ?? ((req) => defaultRequestHook(req, maxBodyBytes, logger));
|
|
78
|
-
const baseOptions = {
|
|
79
|
-
...options.serverlessOptions ?? {},
|
|
80
|
-
request: requestHook
|
|
81
|
-
};
|
|
82
|
-
if (options.response) {
|
|
83
|
-
baseOptions.response = options.response;
|
|
84
|
-
}
|
|
85
|
-
const apiHandler = serverless(app, baseOptions);
|
|
86
|
-
let initialized = null;
|
|
87
|
-
const ensureInit = () => {
|
|
88
|
-
if (!initialized) {
|
|
89
|
-
logger.debug?.("Serverless cold start: running init");
|
|
90
|
-
initialized = options.init ? options.init() : Promise.resolve();
|
|
91
|
-
}
|
|
92
|
-
return initialized;
|
|
93
|
-
};
|
|
94
|
-
const handler = async (event, context) => {
|
|
95
|
-
await ensureInit();
|
|
96
|
-
return apiHandler(event, context);
|
|
97
|
-
};
|
|
98
|
-
handler.reset = () => {
|
|
99
|
-
initialized = null;
|
|
100
|
-
};
|
|
101
|
-
return handler;
|
|
102
|
-
}
|
|
103
|
-
var DEFAULT_SIGNALS = ["SIGINT", "SIGTERM"];
|
|
104
|
-
var DEFAULT_SHUTDOWN_TIMEOUT = 5e3;
|
|
105
|
-
function normalizePort(val) {
|
|
106
|
-
if (val === void 0 || val === "") {
|
|
107
|
-
const envPort = process.env.PORT;
|
|
108
|
-
if (envPort === void 0 || envPort === "") {
|
|
109
|
-
return 8080;
|
|
110
|
-
}
|
|
111
|
-
val = envPort;
|
|
112
|
-
}
|
|
113
|
-
if (typeof val === "string") {
|
|
114
|
-
const parsed = Number(val);
|
|
115
|
-
if (Number.isNaN(parsed)) {
|
|
116
|
-
return val;
|
|
117
|
-
}
|
|
118
|
-
val = parsed;
|
|
119
|
-
}
|
|
120
|
-
if (!Number.isFinite(val) || val < 0 || val > 65535) {
|
|
121
|
-
throw new Error(`Invalid port: ${String(val)}`);
|
|
122
|
-
}
|
|
123
|
-
return val;
|
|
124
|
-
}
|
|
125
|
-
function defaultOnError(error, port, logger) {
|
|
126
|
-
if (error.syscall !== "listen") {
|
|
127
|
-
throw error;
|
|
128
|
-
}
|
|
129
|
-
const bind = typeof port === "string" ? `Pipe ${port}` : `Port ${port}`;
|
|
130
|
-
if (error.code === "EACCES") {
|
|
131
|
-
logger.error(`${bind} requires elevated privileges`);
|
|
132
|
-
process.exit(1);
|
|
133
|
-
} else if (error.code === "EADDRINUSE") {
|
|
134
|
-
logger.error(`${bind} is already in use`);
|
|
135
|
-
process.exit(1);
|
|
136
|
-
} else {
|
|
137
|
-
throw error;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
function startLocalServer(app, options = {}) {
|
|
141
|
-
const logger = options.logger ?? defaultLogger;
|
|
142
|
-
const port = normalizePort(options.port);
|
|
143
|
-
const host = options.host ?? process.env.HOST ?? "0.0.0.0";
|
|
144
|
-
const shutdownTimeout = options.shutdownTimeout ?? DEFAULT_SHUTDOWN_TIMEOUT;
|
|
145
|
-
const server = http.createServer(app);
|
|
146
|
-
app.set("port", port);
|
|
147
|
-
const onError = (error) => {
|
|
148
|
-
if (options.onError) {
|
|
149
|
-
options.onError(error);
|
|
150
|
-
} else {
|
|
151
|
-
defaultOnError(error, port, logger);
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
const onListening = () => {
|
|
155
|
-
const addr = server.address();
|
|
156
|
-
const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr?.port}`;
|
|
157
|
-
logger.log(`Server running at http://${host}:${port}/ (${bind})`);
|
|
158
|
-
options.onListening?.();
|
|
159
|
-
};
|
|
160
|
-
server.on("error", onError);
|
|
161
|
-
server.on("listening", onListening);
|
|
162
|
-
const shutdown = async () => {
|
|
163
|
-
logger.log("Shutting down...");
|
|
164
|
-
try {
|
|
165
|
-
if (options.onShutdown) {
|
|
166
|
-
await options.onShutdown();
|
|
167
|
-
}
|
|
168
|
-
} catch (err) {
|
|
169
|
-
logger.error("onShutdown hook failed:", err);
|
|
170
|
-
}
|
|
171
|
-
await new Promise((resolve) => {
|
|
172
|
-
const timer = setTimeout(() => {
|
|
173
|
-
server.closeAllConnections?.();
|
|
174
|
-
resolve();
|
|
175
|
-
}, shutdownTimeout);
|
|
176
|
-
server.close((err) => {
|
|
177
|
-
clearTimeout(timer);
|
|
178
|
-
if (err) {
|
|
179
|
-
logger.error("Server close error:", err);
|
|
180
|
-
}
|
|
181
|
-
resolve();
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
if (options.exitAfterShutdown) {
|
|
185
|
-
process.exit(0);
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
if (options.signals !== false) {
|
|
189
|
-
const list = options.signals === void 0 || options.signals === true ? DEFAULT_SIGNALS : options.signals;
|
|
190
|
-
for (const sig of list) {
|
|
191
|
-
process.once(sig, () => void shutdown());
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
const start = async () => {
|
|
195
|
-
try {
|
|
196
|
-
if (options.init) {
|
|
197
|
-
await options.init();
|
|
198
|
-
}
|
|
199
|
-
if (typeof port === "number") {
|
|
200
|
-
server.listen(port, host);
|
|
201
|
-
} else {
|
|
202
|
-
server.listen(port);
|
|
203
|
-
}
|
|
204
|
-
} catch (err) {
|
|
205
|
-
server.emit("error", err);
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
void start();
|
|
209
|
-
return {
|
|
210
|
-
server,
|
|
211
|
-
shutdown
|
|
212
|
-
};
|
|
213
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
createExpressApp,
|
|
3
|
+
createServerlessHandler,
|
|
4
|
+
defaultRequestHook,
|
|
5
|
+
normalizePort,
|
|
6
|
+
startLocalServer
|
|
7
|
+
} from "./chunk-SOW7OLVN.mjs";
|
|
214
8
|
export {
|
|
215
9
|
createExpressApp,
|
|
216
10
|
createServerlessHandler,
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@web-ts-toolkit/express-runtime",
|
|
3
3
|
"description": "Express app factory plus serverless handler and local dev server helpers",
|
|
4
4
|
"homepage": "https://web-ts-toolkit.pages.dev/docs/packages/express-runtime",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.27.0",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"keywords": [
|
|
8
8
|
"express",
|
|
@@ -24,6 +24,12 @@
|
|
|
24
24
|
"import": "./index.mjs",
|
|
25
25
|
"require": "./index.js",
|
|
26
26
|
"default": "./index.js"
|
|
27
|
+
},
|
|
28
|
+
"./cli": {
|
|
29
|
+
"types": "./cli-api.d.ts",
|
|
30
|
+
"import": "./cli-api.mjs",
|
|
31
|
+
"require": "./cli-api.js",
|
|
32
|
+
"default": "./cli-api.js"
|
|
27
33
|
}
|
|
28
34
|
},
|
|
29
35
|
"engines": {
|