@firebreak/vitals 1.0.2 → 1.1.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/README.md +115 -46
- package/dist/checks/databricks.cjs +57 -0
- package/dist/checks/databricks.d.cts +23 -0
- package/dist/checks/databricks.d.ts +23 -0
- package/dist/checks/databricks.mjs +30 -0
- package/dist/checks/http.cjs +63 -0
- package/dist/checks/http.d.cts +17 -0
- package/dist/checks/http.d.ts +17 -0
- package/dist/checks/http.mjs +36 -0
- package/dist/checks/postgres.cjs +4 -11
- package/dist/checks/postgres.d.cts +1 -1
- package/dist/checks/postgres.d.ts +1 -1
- package/dist/checks/postgres.mjs +4 -13
- package/dist/checks/redis.cjs +4 -11
- package/dist/checks/redis.d.cts +1 -1
- package/dist/checks/redis.d.ts +1 -1
- package/dist/checks/redis.mjs +4 -13
- package/dist/{core-9-MXAO0I.d.cts → core-BJ2Z0rRi.d.cts} +13 -3
- package/dist/{core-9-MXAO0I.d.ts → core-BJ2Z0rRi.d.ts} +13 -3
- package/dist/handler-Bccbso4b.d.cts +25 -0
- package/dist/handler-D0nYVQvu.d.ts +25 -0
- package/dist/index.cjs +24 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +23 -0
- package/dist/integrations/express.cjs +28 -14
- package/dist/integrations/express.d.cts +3 -6
- package/dist/integrations/express.d.ts +3 -6
- package/dist/integrations/express.mjs +28 -14
- package/dist/integrations/next.cjs +121 -0
- package/dist/integrations/next.d.cts +24 -0
- package/dist/integrations/next.d.ts +24 -0
- package/dist/integrations/next.mjs +94 -0
- package/package.json +32 -2
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// src/auth.ts
|
|
2
|
+
import { createHash, timingSafeEqual } from "crypto";
|
|
3
|
+
function verifyToken(provided, expected) {
|
|
4
|
+
if (!provided || !expected) return false;
|
|
5
|
+
const providedHash = createHash("sha256").update(provided).digest();
|
|
6
|
+
const expectedHash = createHash("sha256").update(expected).digest();
|
|
7
|
+
return timingSafeEqual(providedHash, expectedHash);
|
|
8
|
+
}
|
|
9
|
+
function extractToken(options) {
|
|
10
|
+
const { queryParams, authorizationHeader, queryParamName = "token" } = options;
|
|
11
|
+
if (queryParams) {
|
|
12
|
+
const value = queryParams[queryParamName];
|
|
13
|
+
const str = Array.isArray(value) ? value[0] : value;
|
|
14
|
+
if (str) return str;
|
|
15
|
+
}
|
|
16
|
+
if (authorizationHeader?.startsWith("Bearer ")) {
|
|
17
|
+
const token = authorizationHeader.slice("Bearer ".length);
|
|
18
|
+
if (token) return token;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/types.ts
|
|
24
|
+
var Status = {
|
|
25
|
+
HEALTHY: 2,
|
|
26
|
+
DEGRADED: 1,
|
|
27
|
+
OUTAGE: 0
|
|
28
|
+
};
|
|
29
|
+
function statusToLabel(status) {
|
|
30
|
+
const labels = {
|
|
31
|
+
[Status.HEALTHY]: "healthy",
|
|
32
|
+
[Status.DEGRADED]: "degraded",
|
|
33
|
+
[Status.OUTAGE]: "outage"
|
|
34
|
+
};
|
|
35
|
+
return labels[status];
|
|
36
|
+
}
|
|
37
|
+
function toJson(response) {
|
|
38
|
+
return {
|
|
39
|
+
status: statusToLabel(response.status),
|
|
40
|
+
timestamp: response.timestamp,
|
|
41
|
+
checks: Object.fromEntries(
|
|
42
|
+
Object.entries(response.checks).map(([name, result]) => [
|
|
43
|
+
name,
|
|
44
|
+
{ status: statusToLabel(result.status), latencyMs: result.latencyMs, message: result.message }
|
|
45
|
+
])
|
|
46
|
+
)
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function httpStatusCode(status) {
|
|
50
|
+
return status === Status.HEALTHY ? 200 : 503;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/handler.ts
|
|
54
|
+
function createHealthcheckHandler(options) {
|
|
55
|
+
const { registry, token = null, queryParamName = "token" } = options;
|
|
56
|
+
return async (req) => {
|
|
57
|
+
if (token !== null) {
|
|
58
|
+
const provided = extractToken({
|
|
59
|
+
queryParams: req.queryParams,
|
|
60
|
+
authorizationHeader: req.authorizationHeader,
|
|
61
|
+
queryParamName
|
|
62
|
+
});
|
|
63
|
+
if (provided === null || !verifyToken(provided, token)) {
|
|
64
|
+
return { status: 403, body: { error: "Forbidden" } };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const response = await registry.run();
|
|
68
|
+
return {
|
|
69
|
+
status: httpStatusCode(response.status),
|
|
70
|
+
body: toJson(response)
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/integrations/next.ts
|
|
76
|
+
function createNextHandler(options) {
|
|
77
|
+
const handle = createHealthcheckHandler(options);
|
|
78
|
+
return async (request) => {
|
|
79
|
+
try {
|
|
80
|
+
const url = new URL(request.url);
|
|
81
|
+
const queryParams = Object.fromEntries(url.searchParams);
|
|
82
|
+
const result = await handle({
|
|
83
|
+
queryParams,
|
|
84
|
+
authorizationHeader: request.headers.get("authorization")
|
|
85
|
+
});
|
|
86
|
+
return Response.json(result.body, { status: result.status });
|
|
87
|
+
} catch {
|
|
88
|
+
return Response.json({ error: "Internal Server Error" }, { status: 500 });
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
export {
|
|
93
|
+
createNextHandler
|
|
94
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firebreak/vitals",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Deep healthcheck endpoints following the HEALTHCHECK_SPEC format",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -24,6 +24,26 @@
|
|
|
24
24
|
"default": "./dist/checks/postgres.cjs"
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
|
+
"./checks/http": {
|
|
28
|
+
"import": {
|
|
29
|
+
"types": "./dist/checks/http.d.ts",
|
|
30
|
+
"default": "./dist/checks/http.mjs"
|
|
31
|
+
},
|
|
32
|
+
"require": {
|
|
33
|
+
"types": "./dist/checks/http.d.cts",
|
|
34
|
+
"default": "./dist/checks/http.cjs"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"./checks/databricks": {
|
|
38
|
+
"import": {
|
|
39
|
+
"types": "./dist/checks/databricks.d.ts",
|
|
40
|
+
"default": "./dist/checks/databricks.mjs"
|
|
41
|
+
},
|
|
42
|
+
"require": {
|
|
43
|
+
"types": "./dist/checks/databricks.d.cts",
|
|
44
|
+
"default": "./dist/checks/databricks.cjs"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
27
47
|
"./checks/redis": {
|
|
28
48
|
"import": {
|
|
29
49
|
"types": "./dist/checks/redis.d.ts",
|
|
@@ -43,6 +63,16 @@
|
|
|
43
63
|
"types": "./dist/integrations/express.d.cts",
|
|
44
64
|
"default": "./dist/integrations/express.cjs"
|
|
45
65
|
}
|
|
66
|
+
},
|
|
67
|
+
"./next": {
|
|
68
|
+
"import": {
|
|
69
|
+
"types": "./dist/integrations/next.d.ts",
|
|
70
|
+
"default": "./dist/integrations/next.mjs"
|
|
71
|
+
},
|
|
72
|
+
"require": {
|
|
73
|
+
"types": "./dist/integrations/next.d.cts",
|
|
74
|
+
"default": "./dist/integrations/next.cjs"
|
|
75
|
+
}
|
|
46
76
|
}
|
|
47
77
|
},
|
|
48
78
|
"main": "./dist/index.cjs",
|
|
@@ -89,5 +119,5 @@
|
|
|
89
119
|
"engines": {
|
|
90
120
|
"node": ">=20.0.0"
|
|
91
121
|
},
|
|
92
|
-
"license": "
|
|
122
|
+
"license": "MIT"
|
|
93
123
|
}
|