@smithers-orchestrator/server 0.16.9 → 0.18.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/package.json +18 -11
- package/src/EventFrame.ts +1 -0
- package/src/GatewayOptions.ts +19 -0
- package/src/GatewayRegisterOptions.ts +8 -0
- package/src/GatewayTokenGrant.ts +4 -0
- package/src/GatewayUiConfig.ts +20 -0
- package/src/ResponseFrame.ts +5 -0
- package/src/ServerOptions.ts +12 -0
- package/src/gateway.js +801 -103
- package/src/gatewayRoutes/getNodeDiff.js +2 -4
- package/src/gatewayUi/createGatewayUiApp.js +47 -0
- package/src/index.d.ts +271 -47
- package/src/index.js +9 -2
- package/src/serve.js +1 -2
package/src/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createServer
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
@@ -20,6 +20,7 @@ import { errorToJson } from "@smithers-orchestrator/errors/errorToJson";
|
|
|
20
20
|
import { SmithersError } from "@smithers-orchestrator/errors/SmithersError";
|
|
21
21
|
import { assertMaxBytes, assertMaxJsonDepth } from "@smithers-orchestrator/db/input-bounds";
|
|
22
22
|
import { prometheusContentType, renderPrometheusMetrics, } from "@smithers-orchestrator/observability";
|
|
23
|
+
/** @typedef {import("node:http").ServerResponse} ServerResponse */
|
|
23
24
|
/** @typedef {import("./ServerOptions.js").ServerOptions} ServerOptions */
|
|
24
25
|
|
|
25
26
|
// Re-export the full public surface so the tsup-bundled `src/index.d.ts`
|
|
@@ -44,6 +45,8 @@ const DEFAULT_MAX_BODY_BYTES = 1_048_576;
|
|
|
44
45
|
const DEFAULT_MAX_BODY_JSON_DEPTH = 32;
|
|
45
46
|
const DEFAULT_SSE_HEARTBEAT_MS = 10_000;
|
|
46
47
|
const COMPLETED_RUN_RETENTION_MS = 60_000;
|
|
48
|
+
const DEFAULT_HEADERS_TIMEOUT = 30_000;
|
|
49
|
+
const DEFAULT_REQUEST_TIMEOUT = 60_000;
|
|
47
50
|
class HttpError extends Error {
|
|
48
51
|
status;
|
|
49
52
|
code;
|
|
@@ -355,7 +358,7 @@ function assertAuth(req, authToken) {
|
|
|
355
358
|
req.headers["Authorization"] ??
|
|
356
359
|
req.headers["x-smithers-key"];
|
|
357
360
|
const value = Array.isArray(header) ? header[0] : header;
|
|
358
|
-
const token = value?.
|
|
361
|
+
const token = value?.slice(0, 7).toLowerCase() === "bearer " ? value.slice(7) : value;
|
|
359
362
|
if (!token || token !== authToken) {
|
|
360
363
|
throw new HttpError(401, "UNAUTHORIZED", "Missing or invalid authorization token");
|
|
361
364
|
}
|
|
@@ -645,6 +648,8 @@ function startServerInternal(opts = {}) {
|
|
|
645
648
|
const maxBodyBytes = opts.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
|
|
646
649
|
const rootDir = opts.rootDir ? resolve(opts.rootDir) : undefined;
|
|
647
650
|
const allowNetwork = Boolean(opts.allowNetwork);
|
|
651
|
+
const headersTimeout = opts.headersTimeout ?? DEFAULT_HEADERS_TIMEOUT;
|
|
652
|
+
const requestTimeout = opts.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;
|
|
648
653
|
if (serverDb) {
|
|
649
654
|
ensureSmithersTables(serverDb);
|
|
650
655
|
}
|
|
@@ -1206,6 +1211,8 @@ function startServerInternal(opts = {}) {
|
|
|
1206
1211
|
await recordHttpRequestMetricsSafely(requestMethod, requestPathname, res.statusCode || 500, performance.now() - requestStart);
|
|
1207
1212
|
}
|
|
1208
1213
|
});
|
|
1214
|
+
server.headersTimeout = headersTimeout;
|
|
1215
|
+
server.requestTimeout = requestTimeout;
|
|
1209
1216
|
server.on("close", () => {
|
|
1210
1217
|
logInfo("stopping smithers server", {
|
|
1211
1218
|
activeRuns: runs.size,
|
package/src/serve.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
2
|
import { streamSSE } from "hono/streaming";
|
|
3
3
|
import { Effect, Metric } from "effect";
|
|
4
|
-
import { SmithersDb } from "@smithers-orchestrator/db/adapter";
|
|
5
4
|
import { approveNode, denyNode } from "@smithers-orchestrator/engine/approvals";
|
|
6
5
|
import { isRunHeartbeatFresh } from "@smithers-orchestrator/engine";
|
|
7
6
|
import { nowMs } from "@smithers-orchestrator/scheduler/nowMs";
|
|
@@ -119,7 +118,7 @@ export function createServeApp(opts) {
|
|
|
119
118
|
return next();
|
|
120
119
|
const authHeader = c.req.header("authorization");
|
|
121
120
|
if (authHeader) {
|
|
122
|
-
const token = authHeader.
|
|
121
|
+
const token = authHeader.slice(0, 7).toLowerCase() === "bearer "
|
|
123
122
|
? authHeader.slice(7)
|
|
124
123
|
: authHeader;
|
|
125
124
|
if (token === authToken)
|