@openstatus/health-cloudflare-kv 0.1.4-dev.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 +80 -0
- package/dist/_virtual/rolldown_runtime.cjs +30 -0
- package/dist/mod.cjs +35 -0
- package/dist/mod.d.cts +26 -0
- package/dist/mod.d.cts.map +1 -0
- package/dist/mod.d.ts +26 -0
- package/dist/mod.d.ts.map +1 -0
- package/dist/mod.js +33 -0
- package/dist/mod.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# @openstatus/health-cloudflare-kv
|
|
2
|
+
|
|
3
|
+
[Cloudflare Workers KV](https://developers.cloudflare.com/kv/) probe for
|
|
4
|
+
[`@openstatus/health`](https://jsr.io/@openstatus/health). Reads one key
|
|
5
|
+
through a `KVNamespace` binding and fails the check when the read does — a
|
|
6
|
+
missing key is a healthy answer, only an error is not.
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
deno add jsr:@openstatus/health jsr:@openstatus/health-cloudflare-kv
|
|
10
|
+
npm install @openstatus/health @openstatus/health-cloudflare-kv
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createLazyHealthHandler } from "@openstatus/health";
|
|
15
|
+
import { kvProbe } from "@openstatus/health-cloudflare-kv";
|
|
16
|
+
|
|
17
|
+
interface Env {
|
|
18
|
+
CACHE: KVNamespace;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
fetch: createLazyHealthHandler<Request, Env>((env) => ({
|
|
23
|
+
path: "/health",
|
|
24
|
+
probes: [kvProbe({ namespace: env.CACHE })],
|
|
25
|
+
})),
|
|
26
|
+
};
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Bindings only exist inside `fetch(request, env)` in Workers, but the handler
|
|
30
|
+
must be built once or every request gets a fresh cache and the probe runs on
|
|
31
|
+
every poll. `createLazyHealthHandler` runs your callback on the first request
|
|
32
|
+
and reuses the handler it builds; with Hono, build the probe once inside a
|
|
33
|
+
route handler that receives `c.env` and memoise it the same way. The probe
|
|
34
|
+
calls `namespace.get("health")`; pass `key` to read a key your Worker
|
|
35
|
+
actually depends on. KV reads are served from the edge cache, so a
|
|
36
|
+
successful probe proves the binding and the nearest cache answer, not that
|
|
37
|
+
a write would reach the origin.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
kvProbe({
|
|
41
|
+
namespace: env.CACHE,
|
|
42
|
+
key: "config:v1",
|
|
43
|
+
// optional overrides from the Probe contract
|
|
44
|
+
name: "sessions",
|
|
45
|
+
critical: true,
|
|
46
|
+
timeoutMs: 1000,
|
|
47
|
+
skip: () => env.HEALTH_SKIP_KV === "true",
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The factory validates `namespace` when it is called, before `skip` is ever
|
|
52
|
+
consulted, so `skip` cannot stand in for a missing binding; leave the probe
|
|
53
|
+
out of `probes` instead when the Worker may run without KV.
|
|
54
|
+
|
|
55
|
+
Non-critical by default: KV is usually a cache or configuration store whose
|
|
56
|
+
outage degrades the report instead of taking the Worker out of rotation.
|
|
57
|
+
Set `critical: true` when requests cannot proceed without it.
|
|
58
|
+
|
|
59
|
+
The binding is typed structurally as `{ get(key) }`, so the package has no
|
|
60
|
+
dependency on `@cloudflare/workers-types` and works with the types
|
|
61
|
+
`wrangler types` generates. The factory throws `ProbeConfigError` at
|
|
62
|
+
construction when the binding has no `get()` or `key` is empty.
|
|
63
|
+
|
|
64
|
+
## About openstatus
|
|
65
|
+
|
|
66
|
+
[openstatus](https://www.openstatus.dev/) is the open-source uptime monitoring
|
|
67
|
+
and status page platform. This package is part of
|
|
68
|
+
[`@openstatus/health`](https://github.com/openstatusHQ/health), the `/health`
|
|
69
|
+
endpoints behind openstatus's own services, extracted so any JavaScript server
|
|
70
|
+
can expose one. Point an
|
|
71
|
+
[openstatus monitor](https://www.openstatus.dev/docs/reference/http-monitor)
|
|
72
|
+
at the endpoint and assert on `status` in the body to be alerted on
|
|
73
|
+
`degraded` before it becomes `unhealthy`.
|
|
74
|
+
|
|
75
|
+
Source: [github.com/openstatusHQ/health](https://github.com/openstatusHQ/health).
|
|
76
|
+
Issues and PRs welcome.
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
|
|
80
|
+
[MIT](https://github.com/openstatusHQ/health/blob/main/LICENSE)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
|
|
25
|
+
Object.defineProperty(exports, '__toESM', {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
get: function () {
|
|
28
|
+
return __toESM;
|
|
29
|
+
}
|
|
30
|
+
});
|
package/dist/mod.cjs
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const __openstatus_health = require_rolldown_runtime.__toESM(require("@openstatus/health"));
|
|
3
|
+
|
|
4
|
+
//#region src/mod.ts
|
|
5
|
+
/** Probe name when `name` is unset. */
|
|
6
|
+
const kvDefaultName = "kv";
|
|
7
|
+
/** Key read when `key` is unset. */
|
|
8
|
+
const kvDefaultKey = "health";
|
|
9
|
+
/** A probe that reads `key`; non-critical by default. Throws `ProbeConfigError` without `get()` or with an empty `key`. */
|
|
10
|
+
function kvProbe(options) {
|
|
11
|
+
const namespace = options.namespace;
|
|
12
|
+
if (typeof namespace?.get !== "function") throw new __openstatus_health.ProbeConfigError("kvProbe", "namespace", `must expose get(), got ${describe(namespace)}`);
|
|
13
|
+
const key = options.key === void 0 ? kvDefaultKey : options.key;
|
|
14
|
+
if (typeof key !== "string" || key.length === 0) throw new __openstatus_health.ProbeConfigError("kvProbe", "key", typeof key !== "string" ? `must be a string, got ${String(key)}` : "must not be empty");
|
|
15
|
+
return {
|
|
16
|
+
name: options.name ?? kvDefaultName,
|
|
17
|
+
critical: options.critical ?? false,
|
|
18
|
+
timeoutMs: options.timeoutMs,
|
|
19
|
+
skip: options.skip,
|
|
20
|
+
run: async () => {
|
|
21
|
+
await namespace.get(key);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function describe(namespace) {
|
|
26
|
+
if (namespace == null) return String(namespace);
|
|
27
|
+
if (typeof namespace !== "object") return typeof namespace;
|
|
28
|
+
const keys = Object.keys(namespace);
|
|
29
|
+
return keys.length === 0 ? "an object with no keys" : `an object with keys ${keys.slice(0, 8).join(", ")}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
exports.kvDefaultKey = kvDefaultKey;
|
|
34
|
+
exports.kvDefaultName = kvDefaultName;
|
|
35
|
+
exports.kvProbe = kvProbe;
|
package/dist/mod.d.cts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Probe, ProbeOverrides, ProbeResult } from "@openstatus/health";
|
|
2
|
+
|
|
3
|
+
//#region src/mod.d.ts
|
|
4
|
+
|
|
5
|
+
/** Probe name when `name` is unset. */
|
|
6
|
+
declare const kvDefaultName = "kv";
|
|
7
|
+
/** Key read when `key` is unset. */
|
|
8
|
+
declare const kvDefaultKey = "health";
|
|
9
|
+
/** The subset of a `KVNamespace` binding the probe uses. */
|
|
10
|
+
interface KVLikeNamespace {
|
|
11
|
+
/** Read one key; resolves with `null` when it does not exist. */
|
|
12
|
+
get(key: string): PromiseLike<ProbeResult>;
|
|
13
|
+
}
|
|
14
|
+
/** Options for `kvProbe()`. */
|
|
15
|
+
interface KVProbeOptions extends ProbeOverrides {
|
|
16
|
+
/** The `KVNamespace` binding from `env`. */
|
|
17
|
+
readonly namespace: KVLikeNamespace;
|
|
18
|
+
/** Key to read. Default `kvDefaultKey`; it does not need to exist. */
|
|
19
|
+
readonly key?: string;
|
|
20
|
+
}
|
|
21
|
+
/** A probe that reads `key`; non-critical by default. Throws `ProbeConfigError` without `get()` or with an empty `key`. */
|
|
22
|
+
declare function kvProbe(options: KVProbeOptions): Probe;
|
|
23
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
24
|
+
//#endregion
|
|
25
|
+
export { KVLikeNamespace, KVProbeOptions, kvDefaultKey, kvDefaultName, kvProbe };
|
|
26
|
+
//# sourceMappingURL=mod.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.cts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;;AA6CuD,cAnB1C,aAAA,GAmB0C,IAAA;;cAjB1C,YAAA;;UAGI,eAAA;;oBAEG,YAAY;;;UAIf,cAAA,SAAuB;;sBAElB;;;;;iBAMN,OAAA,UAAiB,iBAAiB"}
|
package/dist/mod.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Probe, ProbeOverrides, ProbeResult } from "@openstatus/health";
|
|
2
|
+
|
|
3
|
+
//#region src/mod.d.ts
|
|
4
|
+
|
|
5
|
+
/** Probe name when `name` is unset. */
|
|
6
|
+
declare const kvDefaultName = "kv";
|
|
7
|
+
/** Key read when `key` is unset. */
|
|
8
|
+
declare const kvDefaultKey = "health";
|
|
9
|
+
/** The subset of a `KVNamespace` binding the probe uses. */
|
|
10
|
+
interface KVLikeNamespace {
|
|
11
|
+
/** Read one key; resolves with `null` when it does not exist. */
|
|
12
|
+
get(key: string): PromiseLike<ProbeResult>;
|
|
13
|
+
}
|
|
14
|
+
/** Options for `kvProbe()`. */
|
|
15
|
+
interface KVProbeOptions extends ProbeOverrides {
|
|
16
|
+
/** The `KVNamespace` binding from `env`. */
|
|
17
|
+
readonly namespace: KVLikeNamespace;
|
|
18
|
+
/** Key to read. Default `kvDefaultKey`; it does not need to exist. */
|
|
19
|
+
readonly key?: string;
|
|
20
|
+
}
|
|
21
|
+
/** A probe that reads `key`; non-critical by default. Throws `ProbeConfigError` without `get()` or with an empty `key`. */
|
|
22
|
+
declare function kvProbe(options: KVProbeOptions): Probe;
|
|
23
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
24
|
+
//#endregion
|
|
25
|
+
export { KVLikeNamespace, KVProbeOptions, kvDefaultKey, kvDefaultName, kvProbe };
|
|
26
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;;AA6CuD,cAnB1C,aAAA,GAmB0C,IAAA;;cAjB1C,YAAA;;UAGI,eAAA;;oBAEG,YAAY;;;UAIf,cAAA,SAAuB;;sBAElB;;;;;iBAMN,OAAA,UAAiB,iBAAiB"}
|
package/dist/mod.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ProbeConfigError } from "@openstatus/health";
|
|
2
|
+
|
|
3
|
+
//#region src/mod.ts
|
|
4
|
+
/** Probe name when `name` is unset. */
|
|
5
|
+
const kvDefaultName = "kv";
|
|
6
|
+
/** Key read when `key` is unset. */
|
|
7
|
+
const kvDefaultKey = "health";
|
|
8
|
+
/** A probe that reads `key`; non-critical by default. Throws `ProbeConfigError` without `get()` or with an empty `key`. */
|
|
9
|
+
function kvProbe(options) {
|
|
10
|
+
const namespace = options.namespace;
|
|
11
|
+
if (typeof namespace?.get !== "function") throw new ProbeConfigError("kvProbe", "namespace", `must expose get(), got ${describe(namespace)}`);
|
|
12
|
+
const key = options.key === void 0 ? kvDefaultKey : options.key;
|
|
13
|
+
if (typeof key !== "string" || key.length === 0) throw new ProbeConfigError("kvProbe", "key", typeof key !== "string" ? `must be a string, got ${String(key)}` : "must not be empty");
|
|
14
|
+
return {
|
|
15
|
+
name: options.name ?? kvDefaultName,
|
|
16
|
+
critical: options.critical ?? false,
|
|
17
|
+
timeoutMs: options.timeoutMs,
|
|
18
|
+
skip: options.skip,
|
|
19
|
+
run: async () => {
|
|
20
|
+
await namespace.get(key);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function describe(namespace) {
|
|
25
|
+
if (namespace == null) return String(namespace);
|
|
26
|
+
if (typeof namespace !== "object") return typeof namespace;
|
|
27
|
+
const keys = Object.keys(namespace);
|
|
28
|
+
return keys.length === 0 ? "an object with no keys" : `an object with keys ${keys.slice(0, 8).join(", ")}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { kvDefaultKey, kvDefaultName, kvProbe };
|
|
33
|
+
//# sourceMappingURL=mod.js.map
|
package/dist/mod.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.js","names":["options: KVProbeOptions","namespace: KVLikeNamespace"],"sources":["../src/mod.ts"],"sourcesContent":["/**\n * Cloudflare Workers KV probe for `@openstatus/health`: reads one key\n * through a `KVNamespace` binding.\n *\n * ```ts\n * import { createLazyHealthHandler } from \"@openstatus/health\";\n * import { kvProbe } from \"@openstatus/health-cloudflare-kv\";\n *\n * export default {\n * fetch: createLazyHealthHandler<Request, Env>((env) => ({\n * probes: [kvProbe({ namespace: env.CACHE })],\n * })),\n * };\n * ```\n *\n * @module\n */\n\nimport {\n type Probe,\n ProbeConfigError,\n type ProbeOverrides,\n type ProbeResult,\n} from \"@openstatus/health\";\n\n/** Probe name when `name` is unset. */\nexport const kvDefaultName = \"kv\";\n/** Key read when `key` is unset. */\nexport const kvDefaultKey = \"health\";\n\n/** The subset of a `KVNamespace` binding the probe uses. */\nexport interface KVLikeNamespace {\n /** Read one key; resolves with `null` when it does not exist. */\n get(key: string): PromiseLike<ProbeResult>;\n}\n\n/** Options for `kvProbe()`. */\nexport interface KVProbeOptions extends ProbeOverrides {\n /** The `KVNamespace` binding from `env`. */\n readonly namespace: KVLikeNamespace;\n /** Key to read. Default `kvDefaultKey`; it does not need to exist. */\n readonly key?: string;\n}\n\n/** A probe that reads `key`; non-critical by default. Throws `ProbeConfigError` without `get()` or with an empty `key`. */\nexport function kvProbe(options: KVProbeOptions): Probe {\n const namespace = options.namespace;\n if (typeof namespace?.get !== \"function\") {\n throw new ProbeConfigError(\n \"kvProbe\",\n \"namespace\",\n `must expose get(), got ${describe(namespace)}`,\n );\n }\n const key = options.key === undefined ? kvDefaultKey : options.key;\n if (typeof key !== \"string\" || key.length === 0) {\n throw new ProbeConfigError(\n \"kvProbe\",\n \"key\",\n typeof key !== \"string\"\n ? `must be a string, got ${String(key)}`\n : \"must not be empty\",\n );\n }\n return {\n name: options.name ?? kvDefaultName,\n critical: options.critical ?? false,\n timeoutMs: options.timeoutMs,\n skip: options.skip,\n run: async () => {\n await namespace.get(key);\n },\n };\n}\n\nfunction describe(namespace: KVLikeNamespace): string {\n if (namespace == null) return String(namespace);\n if (typeof namespace !== \"object\") return typeof namespace;\n const keys = Object.keys(namespace);\n return keys.length === 0\n ? \"an object with no keys\"\n : `an object with keys ${keys.slice(0, 8).join(\", \")}`;\n}\n"],"mappings":";;;;AA0BA,MAAa,gBAAgB;;AAE7B,MAAa,eAAe;;AAiB5B,SAAgB,QAAQA,SAAgC;CACtD,MAAM,YAAY,QAAQ;AAC1B,YAAW,WAAW,QAAQ,WAC5B,OAAM,IAAI,iBACR,WACA,cACC,yBAAyB,SAAS,UAAU,CAAC;CAGlD,MAAM,MAAM,QAAQ,iBAAoB,eAAe,QAAQ;AAC/D,YAAW,QAAQ,YAAY,IAAI,WAAW,EAC5C,OAAM,IAAI,iBACR,WACA,cACO,QAAQ,YACV,wBAAwB,OAAO,IAAI,CAAC,IACrC;AAGR,QAAO;EACL,MAAM,QAAQ,QAAQ;EACtB,UAAU,QAAQ,YAAY;EAC9B,WAAW,QAAQ;EACnB,MAAM,QAAQ;EACd,KAAK,YAAY;AACf,SAAM,UAAU,IAAI,IAAI;EACzB;CACF;AACF;AAED,SAAS,SAASC,WAAoC;AACpD,KAAI,aAAa,KAAM,QAAO,OAAO,UAAU;AAC/C,YAAW,cAAc,SAAU,eAAc;CACjD,MAAM,OAAO,OAAO,KAAK,UAAU;AACnC,QAAO,KAAK,WAAW,IACnB,4BACC,sBAAsB,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC;AACxD"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openstatus/health-cloudflare-kv",
|
|
3
|
+
"version": "0.1.4-dev.0",
|
|
4
|
+
"description": "Cloudflare Workers KV probe for @openstatus/health",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"openstatus",
|
|
7
|
+
"health",
|
|
8
|
+
"healthcheck",
|
|
9
|
+
"cloudflare",
|
|
10
|
+
"kv",
|
|
11
|
+
"workers",
|
|
12
|
+
"cache"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "openstatus",
|
|
17
|
+
"url": "https://www.openstatus.dev/"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/openstatusHQ/health",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/openstatusHQ/health.git",
|
|
23
|
+
"directory": "packages/cloudflare-kv/"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/openstatusHQ/health/issues"
|
|
27
|
+
},
|
|
28
|
+
"type": "module",
|
|
29
|
+
"module": "./dist/mod.js",
|
|
30
|
+
"main": "./dist/mod.cjs",
|
|
31
|
+
"types": "./dist/mod.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": {
|
|
35
|
+
"import": "./dist/mod.d.ts",
|
|
36
|
+
"require": "./dist/mod.d.cts"
|
|
37
|
+
},
|
|
38
|
+
"import": "./dist/mod.js",
|
|
39
|
+
"require": "./dist/mod.cjs"
|
|
40
|
+
},
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
43
|
+
"sideEffects": false,
|
|
44
|
+
"files": [
|
|
45
|
+
"dist/"
|
|
46
|
+
],
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=22"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"@openstatus/health": "^0.1.4-dev.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"tsdown": "^0.12.7",
|
|
55
|
+
"typescript": "^5.8.3"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsdown",
|
|
59
|
+
"prepack": "tsdown",
|
|
60
|
+
"test": "node --experimental-transform-types --test"
|
|
61
|
+
}
|
|
62
|
+
}
|