@luckystack/server 0.7.6 → 0.8.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/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.8.0] - 2026-07-27
11
+
12
+ ### Added
13
+
14
+ - 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.
15
+
10
16
  ## [0.7.6] - 2026-07-23
11
17
 
12
18
  ### Fixed
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 tryCatchSync2, resolveEnvKey as resolveEnvKey5, dispatchHook as dispatchHook8 } from "@luckystack/core";
12
+ import { registerBindAddress, registerBoundAddress, writeBootUuid, startBootUuidHeartbeat, getLogger as getLogger13, getProjectConfig as getProjectConfig15, tryCatch as tryCatch10, tryCatchSync as tryCatchSync3, resolveEnvKey as resolveEnvKey5, 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
@@ -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
- const apiData = typeof params === "object" ? { ...params } : {};
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] = tryCatchSync(() => {
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] = tryCatchSync(() => decodeURIComponent(routePathRaw ?? "/"));
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");
@@ -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 = tryCatchSync2(() => getProjectConfig15().oauthCallbackBase)[1] ?? "";
2402
- const callbackPort = tryCatchSync2(() => {
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] ?? "";