@luckystack/server 0.7.6 → 0.8.1
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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +37 -19
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.1] - 2026-07-27
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Production route maps, dev-tool startup, cookie security, bootstrap checks and port auto-increment now follow `NODE_ENV`; named topology environments remain available for health and routing identity.
|
|
15
|
+
|
|
16
|
+
## [0.8.0] - 2026-07-27
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Routed GET API calls can carry a lossless typed payload through the reserved `__luckystack_data` query value while public key-per-query callers remain compatible.
|
|
21
|
+
|
|
10
22
|
## [0.7.6] - 2026-07-23
|
|
11
23
|
|
|
12
24
|
### Fixed
|
package/dist/index.d.ts
CHANGED
|
@@ -110,7 +110,7 @@ interface CreateLuckyStackServerOptions {
|
|
|
110
110
|
customRoutes?: CustomRouteHandler;
|
|
111
111
|
/**
|
|
112
112
|
* Enable dev-mode tooling (devkit hot reload, REPL, console init).
|
|
113
|
-
* Defaults to `
|
|
113
|
+
* Defaults to `resolveRuntimeMode() !== 'production'` (NODE_ENV-based).
|
|
114
114
|
*/
|
|
115
115
|
enableDevTools?: boolean;
|
|
116
116
|
/**
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
|
|
10
10
|
// src/createServer.ts
|
|
11
11
|
import http from "http";
|
|
12
|
-
import { registerBindAddress, registerBoundAddress, writeBootUuid, startBootUuidHeartbeat, getLogger as getLogger13, getProjectConfig as getProjectConfig15, tryCatch as tryCatch10, tryCatchSync as
|
|
12
|
+
import { registerBindAddress, registerBoundAddress, writeBootUuid, startBootUuidHeartbeat, getLogger as getLogger13, getProjectConfig as getProjectConfig15, tryCatch as tryCatch10, tryCatchSync as tryCatchSync3, resolveRuntimeMode, dispatchHook as dispatchHook8 } from "@luckystack/core";
|
|
13
13
|
|
|
14
14
|
// src/httpHandler.ts
|
|
15
15
|
import { randomUUID } from "crypto";
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
normalizeOrigin,
|
|
25
25
|
readSession as readSession3,
|
|
26
26
|
tryCatch as tryCatch7,
|
|
27
|
-
tryCatchSync
|
|
27
|
+
tryCatchSync as tryCatchSync2
|
|
28
28
|
} from "@luckystack/core";
|
|
29
29
|
|
|
30
30
|
// src/logSanitize.ts
|
|
@@ -475,11 +475,11 @@ import {
|
|
|
475
475
|
} from "@luckystack/core";
|
|
476
476
|
|
|
477
477
|
// src/httpRoutes/sessionCookie.ts
|
|
478
|
-
import {
|
|
478
|
+
import { isProductionRuntime } from "@luckystack/core";
|
|
479
479
|
var resolveCookieSecure = (sessionCookieSecure, secureEnv) => {
|
|
480
480
|
if (sessionCookieSecure !== void 0) return sessionCookieSecure;
|
|
481
481
|
if (secureEnv === "true") return true;
|
|
482
|
-
return
|
|
482
|
+
return isProductionRuntime();
|
|
483
483
|
};
|
|
484
484
|
|
|
485
485
|
// src/httpRoutes/authApiRoute.ts
|
|
@@ -921,7 +921,8 @@ import {
|
|
|
921
921
|
dispatchHook as dispatchHook3,
|
|
922
922
|
extractTokenFromRequest,
|
|
923
923
|
getLogger as getLogger4,
|
|
924
|
-
tryCatch as tryCatch4
|
|
924
|
+
tryCatch as tryCatch4,
|
|
925
|
+
tryCatchSync
|
|
925
926
|
} from "@luckystack/core";
|
|
926
927
|
import { handleHttpApiRequest } from "@luckystack/api";
|
|
927
928
|
|
|
@@ -1038,8 +1039,25 @@ var handleApiRoute = async ({
|
|
|
1038
1039
|
res.end(JSON.stringify(response));
|
|
1039
1040
|
return true;
|
|
1040
1041
|
}
|
|
1041
|
-
|
|
1042
|
+
let apiData = typeof params === "object" ? { ...params } : {};
|
|
1042
1043
|
delete apiData.stream;
|
|
1044
|
+
const routedData = apiData.__luckystack_data;
|
|
1045
|
+
if (typeof routedData === "string") {
|
|
1046
|
+
const [parseError, parsed] = tryCatchSync(() => JSON.parse(routedData));
|
|
1047
|
+
if (parseError || parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1048
|
+
const response = {
|
|
1049
|
+
status: "error",
|
|
1050
|
+
httpStatus: 400,
|
|
1051
|
+
message: "api.invalidRequestFormat",
|
|
1052
|
+
errorCode: "api.invalidRequestFormat"
|
|
1053
|
+
};
|
|
1054
|
+
res.setHeader("Content-Type", "application/json");
|
|
1055
|
+
res.writeHead(400);
|
|
1056
|
+
res.end(JSON.stringify(response));
|
|
1057
|
+
return true;
|
|
1058
|
+
}
|
|
1059
|
+
apiData = { ...parsed };
|
|
1060
|
+
}
|
|
1043
1061
|
const requesterIp = resolveRequesterIp(req);
|
|
1044
1062
|
const result = await handleHttpApiRequest({
|
|
1045
1063
|
name: apiName,
|
|
@@ -1390,7 +1408,7 @@ var setSecurityHeaders = (req, res, origin) => {
|
|
|
1390
1408
|
res.setHeader("X-Content-Type-Options", securityHeaders.contentTypeOptions);
|
|
1391
1409
|
const builder = getSecurityHeadersBuilder();
|
|
1392
1410
|
if (builder) {
|
|
1393
|
-
const [error] =
|
|
1411
|
+
const [error] = tryCatchSync2(() => {
|
|
1394
1412
|
const custom = builder(req);
|
|
1395
1413
|
if (custom) {
|
|
1396
1414
|
for (const [name, value] of Object.entries(custom)) {
|
|
@@ -1509,7 +1527,7 @@ var handleHttpRequestInner = async (req, res, options) => {
|
|
|
1509
1527
|
);
|
|
1510
1528
|
const url = req.url ?? "/";
|
|
1511
1529
|
const [routePathRaw, queryStringRaw] = url.split("?");
|
|
1512
|
-
const [decodeError, decodedPath] =
|
|
1530
|
+
const [decodeError, decodedPath] = tryCatchSync2(() => decodeURIComponent(routePathRaw ?? "/"));
|
|
1513
1531
|
if (decodeError || decodedPath === null) {
|
|
1514
1532
|
res.statusCode = 400;
|
|
1515
1533
|
res.setHeader("Content-Type", "text/plain");
|
|
@@ -2002,7 +2020,7 @@ import {
|
|
|
2002
2020
|
isLocalizedNormalizerRegistered,
|
|
2003
2021
|
isProjectConfigRegistered,
|
|
2004
2022
|
isRuntimeMapsProviderRegistered,
|
|
2005
|
-
|
|
2023
|
+
isProductionRuntime as isProductionRuntime2
|
|
2006
2024
|
} from "@luckystack/core";
|
|
2007
2025
|
var verifyBootstrap = async (requirements = {}) => {
|
|
2008
2026
|
const missing = [];
|
|
@@ -2041,7 +2059,7 @@ var verifyBootstrap = async (requirements = {}) => {
|
|
|
2041
2059
|
}
|
|
2042
2060
|
}
|
|
2043
2061
|
if (!isRuntimeMapsProviderRegistered()) {
|
|
2044
|
-
if (
|
|
2062
|
+
if (isProductionRuntime2()) {
|
|
2045
2063
|
missing.push(
|
|
2046
2064
|
"RuntimeMapsProvider \u2014 call `registerRuntimeMapsProvider({...})` from `server/prod/runtimeMaps.ts`. Without it, every api/sync request returns notFound."
|
|
2047
2065
|
);
|
|
@@ -2052,7 +2070,7 @@ var verifyBootstrap = async (requirements = {}) => {
|
|
|
2052
2070
|
}
|
|
2053
2071
|
}
|
|
2054
2072
|
if (!isLocalizedNormalizerRegistered()) {
|
|
2055
|
-
if (
|
|
2073
|
+
if (isProductionRuntime2()) {
|
|
2056
2074
|
missing.push(
|
|
2057
2075
|
"LocalizedNormalizer \u2014 call `registerLocalizedNormalizer({...})` from your bootstrap. Without it, error response messages will be the raw errorCode (no i18n)."
|
|
2058
2076
|
);
|
|
@@ -2095,7 +2113,7 @@ var verifyBootstrap = async (requirements = {}) => {
|
|
|
2095
2113
|
import {
|
|
2096
2114
|
getLogger as getLogger10,
|
|
2097
2115
|
registerRuntimeMapsProvider,
|
|
2098
|
-
|
|
2116
|
+
isProductionRuntime as isProductionRuntime3
|
|
2099
2117
|
} from "@luckystack/core";
|
|
2100
2118
|
var emptyRuntimeMaps = {
|
|
2101
2119
|
apisObject: {},
|
|
@@ -2145,7 +2163,7 @@ var mergeInto = (target, source, kind, fromPreset, keyOrigin) => {
|
|
|
2145
2163
|
target[key] = source[key];
|
|
2146
2164
|
}
|
|
2147
2165
|
};
|
|
2148
|
-
var isProduction = () =>
|
|
2166
|
+
var isProduction = () => isProductionRuntime3();
|
|
2149
2167
|
var createProdRuntimeMapsProvider = (options) => {
|
|
2150
2168
|
let prodMapsPromise = null;
|
|
2151
2169
|
let devkitModulePromise = null;
|
|
@@ -2353,9 +2371,9 @@ var initDevTools = async () => {
|
|
|
2353
2371
|
};
|
|
2354
2372
|
var listenLuckyStackServer = (httpServer, ip, port, callback) => new Promise((resolve, reject) => {
|
|
2355
2373
|
const startPort = normalizeServerPort(port);
|
|
2356
|
-
const
|
|
2357
|
-
const production =
|
|
2358
|
-
const test =
|
|
2374
|
+
const runtimeMode = resolveRuntimeMode();
|
|
2375
|
+
const production = runtimeMode === "production";
|
|
2376
|
+
const test = runtimeMode === "test";
|
|
2359
2377
|
const autoIncrementEnv = (process.env.SERVER_PORT_AUTO_INCREMENT ?? "").toLowerCase();
|
|
2360
2378
|
let autoIncrement;
|
|
2361
2379
|
if (["0", "false"].includes(autoIncrementEnv)) autoIncrement = false;
|
|
@@ -2398,8 +2416,8 @@ var listenLuckyStackServer = (httpServer, ip, port, callback) => new Promise((re
|
|
|
2398
2416
|
process.once("exit", clearDevServerInfo);
|
|
2399
2417
|
}
|
|
2400
2418
|
if (attemptPort !== startPort && !production) {
|
|
2401
|
-
const configuredCallbackBase =
|
|
2402
|
-
const callbackPort =
|
|
2419
|
+
const configuredCallbackBase = tryCatchSync3(() => getProjectConfig15().oauthCallbackBase)[1] ?? "";
|
|
2420
|
+
const callbackPort = tryCatchSync3(() => {
|
|
2403
2421
|
const callbackUrl = new URL(configuredCallbackBase);
|
|
2404
2422
|
return callbackUrl.port || (callbackUrl.protocol === "https:" ? "443" : "80");
|
|
2405
2423
|
})[1] ?? "";
|
|
@@ -2438,7 +2456,7 @@ var createLuckyStackServer = async (options = {}) => {
|
|
|
2438
2456
|
envPort: process.env.SERVER_PORT
|
|
2439
2457
|
});
|
|
2440
2458
|
const ip = options.ip ?? process.env.SERVER_IP ?? "127.0.0.1";
|
|
2441
|
-
const enableDevTools = options.enableDevTools ??
|
|
2459
|
+
const enableDevTools = options.enableDevTools ?? resolveRuntimeMode() !== "production";
|
|
2442
2460
|
registerBindAddress({ ip, port });
|
|
2443
2461
|
if (enableDevTools) {
|
|
2444
2462
|
await initDevTools();
|