@web-ts-toolkit/express-runtime 0.26.0 → 0.28.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 +241 -0
- package/cli-api.d.ts +241 -0
- package/cli-api.js +1111 -0
- package/cli-api.mjs +866 -0
- package/cli.js +187 -54
- 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("--")) {
|
|
@@ -228,12 +232,14 @@ Dev options:
|
|
|
228
232
|
--shutdown-timeout <ms> Max ms to wait for in-flight requests (default: 5000)
|
|
229
233
|
--require <module> Module(s) to preload before app load (repeatable)
|
|
230
234
|
--env <path> Env file(s) to load (repeatable; existing env vars are not overridden)
|
|
235
|
+
--tsconfig <path> Tsconfig used by config-aware consumers for TS path resolution
|
|
231
236
|
--watch <paths> Comma-separated paths to watch for restart (repeatable; dev only)
|
|
232
237
|
--ext <extensions> Comma-separated extensions to watch (default: ts,js,mjs,cjs,json)
|
|
233
238
|
--delay <ms> Debounce ms before restarting on change (default: 500)
|
|
234
239
|
|
|
235
240
|
Build options:
|
|
236
241
|
--init <path> Init hook module (default export, async function)
|
|
242
|
+
--tsconfig <path> Use a custom tsconfig for bundling
|
|
237
243
|
--out-dir <path> Output directory (default: dist)
|
|
238
244
|
--out-name <name> Output filename without extension (default: app)
|
|
239
245
|
--format <cjs|esm> Output format (default: cjs)
|
|
@@ -251,6 +257,7 @@ Start options:
|
|
|
251
257
|
|
|
252
258
|
Build-serverless options:
|
|
253
259
|
--init <path> Init hook module (default export, async function)
|
|
260
|
+
--tsconfig <path> Use a custom tsconfig for bundling
|
|
254
261
|
--out-dir <path> Output directory (default: dist)
|
|
255
262
|
--out-name <name> Output filename without extension (default: handler)
|
|
256
263
|
--format <cjs|esm> Output format (default: cjs)
|
|
@@ -307,8 +314,6 @@ function isHelp(arg) {
|
|
|
307
314
|
function isSubcommand(arg) {
|
|
308
315
|
return arg === "dev" || arg === "build" || arg === "start" || arg === "build-serverless" || arg === "start-serverless";
|
|
309
316
|
}
|
|
310
|
-
var DEFAULT_WATCH_EXTENSIONS = ["ts", "js", "mjs", "cjs", "json"];
|
|
311
|
-
var DEFAULT_WATCH_DELAY = 500;
|
|
312
317
|
function parseRepeatable(argv, index, arg, list) {
|
|
313
318
|
const value = readValue(argv, index, arg);
|
|
314
319
|
for (const part of value.split(",")) {
|
|
@@ -324,6 +329,7 @@ function parseDevArgs(argv) {
|
|
|
324
329
|
const watchPaths = [];
|
|
325
330
|
let watchExt;
|
|
326
331
|
let watchDelay;
|
|
332
|
+
let tsconfigPath;
|
|
327
333
|
let appPath;
|
|
328
334
|
for (let index = 0; index < argv.length; index += 1) {
|
|
329
335
|
const arg = argv[index];
|
|
@@ -390,6 +396,15 @@ function parseDevArgs(argv) {
|
|
|
390
396
|
}
|
|
391
397
|
continue;
|
|
392
398
|
}
|
|
399
|
+
if (arg === "--tsconfig") {
|
|
400
|
+
tsconfigPath = readValue(argv, index, arg);
|
|
401
|
+
index += 1;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
if (arg.startsWith("--tsconfig=")) {
|
|
405
|
+
tsconfigPath = arg.slice("--tsconfig=".length);
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
393
408
|
if (arg === "--watch") {
|
|
394
409
|
index = parseRepeatable(argv, index, arg, watchPaths);
|
|
395
410
|
continue;
|
|
@@ -439,6 +454,7 @@ function parseDevArgs(argv) {
|
|
|
439
454
|
return {
|
|
440
455
|
appPath,
|
|
441
456
|
options,
|
|
457
|
+
tsconfigPath,
|
|
442
458
|
require: requireModules,
|
|
443
459
|
env: envFiles,
|
|
444
460
|
watch: watchPaths,
|
|
@@ -448,8 +464,8 @@ function parseDevArgs(argv) {
|
|
|
448
464
|
}
|
|
449
465
|
function parseStartLikeArgs(argv, subcommandName) {
|
|
450
466
|
for (const arg of argv) {
|
|
451
|
-
if (arg === "--watch" || arg.startsWith("--watch=") || arg === "--ext" || arg.startsWith("--ext=") || arg === "--delay" || arg.startsWith("--delay=")) {
|
|
452
|
-
throw new Error(`--watch/--ext/--delay are not supported with the ${subcommandName} subcommand`);
|
|
467
|
+
if (arg === "--watch" || arg.startsWith("--watch=") || arg === "--tsconfig" || arg.startsWith("--tsconfig=") || arg === "--ext" || arg.startsWith("--ext=") || arg === "--delay" || arg.startsWith("--delay=")) {
|
|
468
|
+
throw new Error(`--watch/--tsconfig/--ext/--delay are not supported with the ${subcommandName} subcommand`);
|
|
453
469
|
}
|
|
454
470
|
}
|
|
455
471
|
return parseDevArgs(argv);
|
|
@@ -477,6 +493,7 @@ function parseBuildArgs(argv, outNameDefault) {
|
|
|
477
493
|
const external = [];
|
|
478
494
|
const result = {
|
|
479
495
|
initPath: void 0,
|
|
496
|
+
tsconfigPath: void 0,
|
|
480
497
|
outDir: "dist",
|
|
481
498
|
outName: outNameDefault,
|
|
482
499
|
format: "cjs",
|
|
@@ -501,6 +518,15 @@ function parseBuildArgs(argv, outNameDefault) {
|
|
|
501
518
|
result.initPath = arg.slice("--init=".length);
|
|
502
519
|
continue;
|
|
503
520
|
}
|
|
521
|
+
if (arg === "--tsconfig") {
|
|
522
|
+
result.tsconfigPath = readValue(argv, index, arg);
|
|
523
|
+
index += 1;
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
if (arg.startsWith("--tsconfig=")) {
|
|
527
|
+
result.tsconfigPath = arg.slice("--tsconfig=".length);
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
504
530
|
if (arg === "--out-dir") {
|
|
505
531
|
result.outDir = readValue(argv, index, arg);
|
|
506
532
|
index += 1;
|
|
@@ -681,9 +707,6 @@ function loadEnvFiles(paths) {
|
|
|
681
707
|
}
|
|
682
708
|
}
|
|
683
709
|
}
|
|
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
710
|
async function preloadModules(modules) {
|
|
688
711
|
for (const mod of modules) {
|
|
689
712
|
moduleRequire(mod);
|
|
@@ -696,6 +719,7 @@ function buildChildArgs(args) {
|
|
|
696
719
|
if (args.options.signals === false) result.push("--no-signals");
|
|
697
720
|
if (args.options.shutdownTimeout !== void 0)
|
|
698
721
|
result.push("--shutdown-timeout", String(args.options.shutdownTimeout));
|
|
722
|
+
if (args.tsconfigPath !== void 0) result.push("--tsconfig", args.tsconfigPath);
|
|
699
723
|
for (const r of args.require) result.push("--require", r);
|
|
700
724
|
for (const e of args.env) result.push("--env", e);
|
|
701
725
|
return result;
|
|
@@ -763,8 +787,6 @@ function runWithWatch(args) {
|
|
|
763
787
|
process.on("SIGTERM", shutdown);
|
|
764
788
|
spawnChild();
|
|
765
789
|
}
|
|
766
|
-
var TEMP_BUILD_ENTRY_FILENAME = ".express-runtime-build-entry.ts";
|
|
767
|
-
var TEMP_SERVERLESS_ENTRY_FILENAME = ".express-runtime-build-serverless-entry.ts";
|
|
768
790
|
function generateServerlessEntry(appPath, initPath) {
|
|
769
791
|
const absAppPath = (0, import_node_path.resolve)(process.cwd(), appPath);
|
|
770
792
|
const absInitPath = initPath ? (0, import_node_path.resolve)(process.cwd(), initPath) : void 0;
|
|
@@ -796,15 +818,16 @@ function generateRuntimeEntry(appPath, initPath) {
|
|
|
796
818
|
}
|
|
797
819
|
return lines.join("\n") + "\n";
|
|
798
820
|
}
|
|
799
|
-
async function
|
|
821
|
+
async function buildBundleFromEntryContent(args) {
|
|
800
822
|
const tsupModule = await import("tsup");
|
|
801
823
|
const { build } = tsupModule;
|
|
802
|
-
const tempEntryPath = (0, import_node_path.resolve)(process.cwd(), tempEntryFilename);
|
|
803
|
-
(0, import_node_fs.writeFileSync)(tempEntryPath, entryContent, "utf8");
|
|
824
|
+
const tempEntryPath = (0, import_node_path.resolve)(process.cwd(), args.tempEntryFilename);
|
|
825
|
+
(0, import_node_fs.writeFileSync)(tempEntryPath, args.entryContent, "utf8");
|
|
804
826
|
try {
|
|
805
827
|
await build({
|
|
806
828
|
config: false,
|
|
807
829
|
entry: { [args.outName]: tempEntryPath },
|
|
830
|
+
tsconfig: args.tsconfigPath,
|
|
808
831
|
format: [args.format],
|
|
809
832
|
target: args.target,
|
|
810
833
|
outDir: args.outDir,
|
|
@@ -819,10 +842,18 @@ async function buildBundle(args, tempEntryFilename, entryContent) {
|
|
|
819
842
|
}
|
|
820
843
|
}
|
|
821
844
|
async function buildRuntime(args) {
|
|
822
|
-
await
|
|
845
|
+
const { runBuildEntryCommand: runBuildEntryCommand2 } = await Promise.resolve().then(() => (init_cli_api(), cli_api_exports));
|
|
846
|
+
await runBuildEntryCommand2(args, {
|
|
847
|
+
generateEntry: generateRuntimeEntry,
|
|
848
|
+
tempEntryFilename: TEMP_BUILD_ENTRY_FILENAME
|
|
849
|
+
});
|
|
823
850
|
}
|
|
824
851
|
async function buildServerless(args) {
|
|
825
|
-
await
|
|
852
|
+
const { runBuildEntryCommand: runBuildEntryCommand2 } = await Promise.resolve().then(() => (init_cli_api(), cli_api_exports));
|
|
853
|
+
await runBuildEntryCommand2(args, {
|
|
854
|
+
generateEntry: generateServerlessEntry,
|
|
855
|
+
tempEntryFilename: TEMP_SERVERLESS_ENTRY_FILENAME
|
|
856
|
+
});
|
|
826
857
|
}
|
|
827
858
|
function collectBody(req) {
|
|
828
859
|
return new Promise((resolve, reject) => {
|
|
@@ -913,36 +944,121 @@ async function loadHandler(handlerPath) {
|
|
|
913
944
|
}
|
|
914
945
|
return exported;
|
|
915
946
|
}
|
|
947
|
+
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;
|
|
948
|
+
var init_cli_utils = __esm({
|
|
949
|
+
"src/cli-utils.ts"() {
|
|
950
|
+
"use strict";
|
|
951
|
+
import_node_url = require("url");
|
|
952
|
+
import_node_path = require("path");
|
|
953
|
+
import_node_fs = require("fs");
|
|
954
|
+
import_node_module = require("module");
|
|
955
|
+
import_node_child_process = require("child_process");
|
|
956
|
+
init_src();
|
|
957
|
+
import_meta = {};
|
|
958
|
+
CLI_VERSION = "0.0.0-PLACEHOLDER";
|
|
959
|
+
DEFAULT_WATCH_EXTENSIONS = ["ts", "js", "mjs", "cjs", "json"];
|
|
960
|
+
DEFAULT_WATCH_DELAY = 500;
|
|
961
|
+
moduleRequire = (0, import_node_module.createRequire)(
|
|
962
|
+
typeof import_meta !== "undefined" && import_meta.url || (0, import_node_path.resolve)(process.cwd(), "x").replace(/x$/, "")
|
|
963
|
+
);
|
|
964
|
+
TEMP_BUILD_ENTRY_FILENAME = ".express-runtime-build-entry.ts";
|
|
965
|
+
TEMP_SERVERLESS_ENTRY_FILENAME = ".express-runtime-build-serverless-entry.ts";
|
|
966
|
+
}
|
|
967
|
+
});
|
|
916
968
|
|
|
917
|
-
// src/cli.ts
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
969
|
+
// src/cli-api.ts
|
|
970
|
+
var cli_api_exports = {};
|
|
971
|
+
__export(cli_api_exports, {
|
|
972
|
+
CLI_VERSION: () => CLI_VERSION,
|
|
973
|
+
applyServerlessResult: () => applyServerlessResult,
|
|
974
|
+
buildBundleFromEntryContent: () => buildBundleFromEntryContent,
|
|
975
|
+
buildChildArgs: () => buildChildArgs,
|
|
976
|
+
buildRuntime: () => buildRuntime,
|
|
977
|
+
buildServerless: () => buildServerless,
|
|
978
|
+
createServerlessAdapterApp: () => createServerlessAdapterApp,
|
|
979
|
+
extractExport: () => extractExport,
|
|
980
|
+
generateRuntimeEntry: () => generateRuntimeEntry,
|
|
981
|
+
generateServerlessEntry: () => generateServerlessEntry,
|
|
982
|
+
isExpressApp: () => isExpressApp,
|
|
983
|
+
loadApp: () => loadApp,
|
|
984
|
+
loadBuiltApp: () => loadBuiltApp,
|
|
985
|
+
loadEnvFiles: () => loadEnvFiles,
|
|
986
|
+
loadHandler: () => loadHandler,
|
|
987
|
+
parseArgs: () => parseArgs,
|
|
988
|
+
parseEnvFile: () => parseEnvFile,
|
|
989
|
+
preloadModules: () => preloadModules,
|
|
990
|
+
printHelp: () => printHelp,
|
|
991
|
+
readValue: () => readValue,
|
|
992
|
+
resolveExport: () => resolveExport,
|
|
993
|
+
runBuildEntryCommand: () => runBuildEntryCommand,
|
|
994
|
+
runCliCommand: () => runCliCommand,
|
|
995
|
+
runDevCommand: () => runDevCommand,
|
|
996
|
+
runExpressDevCommand: () => runExpressDevCommand,
|
|
997
|
+
runWithWatch: () => runWithWatch,
|
|
998
|
+
toServerlessEvent: () => toServerlessEvent
|
|
999
|
+
});
|
|
1000
|
+
async function runDevCommand(args, runner) {
|
|
1001
|
+
if (args.watch.length > 0) {
|
|
1002
|
+
(runner.watch ?? runWithWatch)(args);
|
|
921
1003
|
return;
|
|
922
1004
|
}
|
|
1005
|
+
if (args.env.length > 0) {
|
|
1006
|
+
loadEnvFiles(args.env);
|
|
1007
|
+
}
|
|
1008
|
+
await preloadModules(args.require);
|
|
1009
|
+
const loaded = await runner.load(args.appPath);
|
|
1010
|
+
runner.start(loaded, { ...args.options, exitAfterShutdown: true });
|
|
1011
|
+
}
|
|
1012
|
+
async function runExpressDevCommand(args) {
|
|
1013
|
+
await runDevCommand(args, {
|
|
1014
|
+
load: loadApp,
|
|
1015
|
+
start: (app, options) => {
|
|
1016
|
+
startLocalServer(app, options);
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
async function runBuildEntryCommand(args, options) {
|
|
1021
|
+
if (options.allowInit === false && args.initPath) {
|
|
1022
|
+
throw new Error(options.initErrorMessage ?? "This build command manages init automatically. Remove --init.");
|
|
1023
|
+
}
|
|
1024
|
+
await buildBundleFromEntryContent({
|
|
1025
|
+
entryContent: options.generateEntry(args.appPath, args.initPath),
|
|
1026
|
+
tempEntryFilename: options.tempEntryFilename,
|
|
1027
|
+
tsconfigPath: args.tsconfigPath,
|
|
1028
|
+
outDir: args.outDir,
|
|
1029
|
+
outName: args.outName,
|
|
1030
|
+
format: args.format,
|
|
1031
|
+
target: args.target,
|
|
1032
|
+
external: args.external,
|
|
1033
|
+
clean: args.clean
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
async function runCliCommand(parsedArgs) {
|
|
923
1037
|
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") {
|
|
1038
|
+
await runExpressDevCommand(parsedArgs.dev);
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
if (parsedArgs.subcommand === "start") {
|
|
936
1042
|
const { start } = parsedArgs;
|
|
937
1043
|
if (start.env.length > 0) {
|
|
938
1044
|
loadEnvFiles(start.env);
|
|
939
1045
|
}
|
|
940
1046
|
await preloadModules(start.require);
|
|
941
1047
|
const { app, init } = await loadBuiltApp(start.appPath);
|
|
942
|
-
startLocalServer(app, {
|
|
943
|
-
|
|
1048
|
+
startLocalServer(app, {
|
|
1049
|
+
...start.options,
|
|
1050
|
+
init: init ? async () => {
|
|
1051
|
+
await init();
|
|
1052
|
+
} : void 0,
|
|
1053
|
+
exitAfterShutdown: true
|
|
1054
|
+
});
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
if (parsedArgs.subcommand === "build") {
|
|
944
1058
|
await buildRuntime(parsedArgs.build);
|
|
945
|
-
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
if (parsedArgs.subcommand === "start-serverless") {
|
|
946
1062
|
const { startServerless } = parsedArgs;
|
|
947
1063
|
if (startServerless.env.length > 0) {
|
|
948
1064
|
loadEnvFiles(startServerless.env);
|
|
@@ -951,9 +1067,26 @@ async function main() {
|
|
|
951
1067
|
const handler = await loadHandler(startServerless.handlerPath);
|
|
952
1068
|
const app = createServerlessAdapterApp(handler);
|
|
953
1069
|
startLocalServer(app, { ...startServerless.options, exitAfterShutdown: true });
|
|
954
|
-
|
|
955
|
-
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
await buildServerless(parsedArgs.buildServerless);
|
|
1073
|
+
}
|
|
1074
|
+
var init_cli_api = __esm({
|
|
1075
|
+
"src/cli-api.ts"() {
|
|
1076
|
+
"use strict";
|
|
1077
|
+
init_src();
|
|
1078
|
+
init_cli_utils();
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
// src/cli.ts
|
|
1083
|
+
init_cli_api();
|
|
1084
|
+
async function main() {
|
|
1085
|
+
const parsedArgs = parseArgs(process.argv.slice(2));
|
|
1086
|
+
if (!parsedArgs) {
|
|
1087
|
+
return;
|
|
956
1088
|
}
|
|
1089
|
+
await runCliCommand(parsedArgs);
|
|
957
1090
|
}
|
|
958
1091
|
main().catch((error) => {
|
|
959
1092
|
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.28.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": {
|