@openstatus/health-postgres 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 ADDED
@@ -0,0 +1,80 @@
1
+ # @openstatus/health-postgres
2
+
3
+ [PostgreSQL](https://www.postgresql.org/) probe for
4
+ [`@openstatus/health`](https://jsr.io/@openstatus/health). Runs `select 1`
5
+ through the client you already have — a [`pg`](https://node-postgres.com/)
6
+ pool or client, a [postgres.js](https://github.com/porsager/postgres) `sql`
7
+ instance, `@neondatabase/serverless` or `@vercel/postgres` — and fails the
8
+ check when the round trip does.
9
+
10
+ ```sh
11
+ deno add jsr:@openstatus/health jsr:@openstatus/health-postgres
12
+ npm install @openstatus/health @openstatus/health-postgres
13
+ ```
14
+
15
+ ```ts
16
+ import { Pool } from "pg";
17
+ import { createHealthHandler } from "@openstatus/health";
18
+ import { postgresProbe } from "@openstatus/health-postgres";
19
+
20
+ const pool = new Pool({ connectionString: env.DATABASE_URL });
21
+
22
+ Deno.serve(
23
+ createHealthHandler({ probes: [postgresProbe({ client: pool })] }),
24
+ );
25
+ ```
26
+
27
+ The probe picks the first method the client exposes:
28
+
29
+ | Client | Call |
30
+ | ------ | ---- |
31
+ | `pg` `Pool` / `Client`, `@vercel/postgres` `sql`, Neon `Pool` / `Client` / `neon()` | `client.query("select 1")` |
32
+ | postgres.js `sql` | `sql.unsafe("select 1")` |
33
+
34
+ Pass a pool rather than a single connection where you can: a pool checks a
35
+ connection out per probe and hands it back, so the health endpoint never
36
+ holds one open and never collides with request traffic on a shared client.
37
+
38
+ A timed-out check is reported `timeout` and the round moves on; the driver
39
+ query is not cancelled, because none of the supported clients expose a
40
+ portable abort (`pg` and `@vercel/postgres` take query text only, and
41
+ postgres.js cancels through the pending query's `.cancel()` rather than a
42
+ signal). With a pool, the connection returns to it once the query settles.
43
+
44
+ ```ts
45
+ postgresProbe({
46
+ client: pool,
47
+ // optional overrides from the Probe contract
48
+ name: "primary",
49
+ critical: false,
50
+ timeoutMs: 2000,
51
+ skip: () => env.DATABASE_URL == null,
52
+ });
53
+ ```
54
+
55
+ Critical by default: a Postgres that does not answer usually means requests
56
+ cannot be served, so the report turns `unhealthy` and the instance is taken
57
+ out of rotation. Set `critical: false` for a replica or reporting database.
58
+
59
+ The client is typed structurally as `{ query(text) }` or `{ unsafe(text) }`,
60
+ so `pg` and `postgres` are optional peer dependencies for their types only
61
+ and the probe adds no runtime import of either. The factory throws
62
+ `ProbeConfigError` at construction when the client has neither method.
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,33 @@
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 postgresDefaultName = "database";
7
+ /** A probe that runs `select 1`; critical by default. Throws `ProbeConfigError` without `query()` or `unsafe()`. */
8
+ function postgresProbe(options) {
9
+ const client = options.client;
10
+ let run;
11
+ if (typeof client?.query === "function") run = () => client.query("select 1");
12
+ else if (typeof client?.unsafe === "function") run = () => client.unsafe("select 1");
13
+ else throw new __openstatus_health.ProbeConfigError("postgresProbe", "client", `must expose query() or unsafe(), got ${describe(client)}`);
14
+ return {
15
+ name: options.name ?? postgresDefaultName,
16
+ critical: options.critical ?? true,
17
+ timeoutMs: options.timeoutMs,
18
+ skip: options.skip,
19
+ run: async () => {
20
+ await run();
21
+ }
22
+ };
23
+ }
24
+ function describe(client) {
25
+ if (client == null) return String(client);
26
+ if (typeof client !== "object" && typeof client !== "function") return typeof client;
27
+ const keys = Object.keys(client);
28
+ return keys.length === 0 ? `${typeof client === "function" ? "a function" : "an object"} with no keys` : `an object with keys ${keys.slice(0, 8).join(", ")}`;
29
+ }
30
+
31
+ //#endregion
32
+ exports.postgresDefaultName = postgresDefaultName;
33
+ exports.postgresProbe = postgresProbe;
package/dist/mod.d.cts ADDED
@@ -0,0 +1,24 @@
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 postgresDefaultName = "database";
7
+ /** The subset of a Postgres client the probe uses; one of the two methods must exist. */
8
+ interface PostgresLikeClient {
9
+ /** `pg` pools and clients, `@vercel/postgres`, Neon's `Pool` and `sql.query()`. */
10
+ query?(text: string): PromiseLike<ProbeResult>;
11
+ /** postgres.js's `sql.unsafe()`. */
12
+ unsafe?(query: string): PromiseLike<ProbeResult>;
13
+ }
14
+ /** Options for `postgresProbe()`. */
15
+ interface PostgresProbeOptions extends ProbeOverrides {
16
+ /** A Postgres pool, client or postgres.js `sql` instance. */
17
+ readonly client: PostgresLikeClient;
18
+ }
19
+ /** A probe that runs `select 1`; critical by default. Throws `ProbeConfigError` without `query()` or `unsafe()`. */
20
+ declare function postgresProbe(options: PostgresProbeOptions): Probe;
21
+ //# sourceMappingURL=mod.d.ts.map
22
+ //#endregion
23
+ export { PostgresLikeClient, PostgresProbeOptions, postgresDefaultName, postgresProbe };
24
+ //# sourceMappingURL=mod.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.cts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;;AA2C8D,cAjBjD,mBAAA,GAiBiD,UAAA;AAAK;UAdlD,kBAAA;;wBAEO,YAAY;;0BAEV,YAAY;;;UAIrB,oBAAA,SAA6B;;mBAE3B;;;iBAIH,aAAA,UAAuB,uBAAuB"}
package/dist/mod.d.ts ADDED
@@ -0,0 +1,24 @@
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 postgresDefaultName = "database";
7
+ /** The subset of a Postgres client the probe uses; one of the two methods must exist. */
8
+ interface PostgresLikeClient {
9
+ /** `pg` pools and clients, `@vercel/postgres`, Neon's `Pool` and `sql.query()`. */
10
+ query?(text: string): PromiseLike<ProbeResult>;
11
+ /** postgres.js's `sql.unsafe()`. */
12
+ unsafe?(query: string): PromiseLike<ProbeResult>;
13
+ }
14
+ /** Options for `postgresProbe()`. */
15
+ interface PostgresProbeOptions extends ProbeOverrides {
16
+ /** A Postgres pool, client or postgres.js `sql` instance. */
17
+ readonly client: PostgresLikeClient;
18
+ }
19
+ /** A probe that runs `select 1`; critical by default. Throws `ProbeConfigError` without `query()` or `unsafe()`. */
20
+ declare function postgresProbe(options: PostgresProbeOptions): Probe;
21
+ //# sourceMappingURL=mod.d.ts.map
22
+ //#endregion
23
+ export { PostgresLikeClient, PostgresProbeOptions, postgresDefaultName, postgresProbe };
24
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;;AA2C8D,cAjBjD,mBAAA,GAiBiD,UAAA;AAAK;UAdlD,kBAAA;;wBAEO,YAAY;;0BAEV,YAAY;;;UAIrB,oBAAA,SAA6B;;mBAE3B;;;iBAIH,aAAA,UAAuB,uBAAuB"}
package/dist/mod.js ADDED
@@ -0,0 +1,32 @@
1
+ import { ProbeConfigError } from "@openstatus/health";
2
+
3
+ //#region src/mod.ts
4
+ /** Probe name when `name` is unset. */
5
+ const postgresDefaultName = "database";
6
+ /** A probe that runs `select 1`; critical by default. Throws `ProbeConfigError` without `query()` or `unsafe()`. */
7
+ function postgresProbe(options) {
8
+ const client = options.client;
9
+ let run;
10
+ if (typeof client?.query === "function") run = () => client.query("select 1");
11
+ else if (typeof client?.unsafe === "function") run = () => client.unsafe("select 1");
12
+ else throw new ProbeConfigError("postgresProbe", "client", `must expose query() or unsafe(), got ${describe(client)}`);
13
+ return {
14
+ name: options.name ?? postgresDefaultName,
15
+ critical: options.critical ?? true,
16
+ timeoutMs: options.timeoutMs,
17
+ skip: options.skip,
18
+ run: async () => {
19
+ await run();
20
+ }
21
+ };
22
+ }
23
+ function describe(client) {
24
+ if (client == null) return String(client);
25
+ if (typeof client !== "object" && typeof client !== "function") return typeof client;
26
+ const keys = Object.keys(client);
27
+ return keys.length === 0 ? `${typeof client === "function" ? "a function" : "an object"} with no keys` : `an object with keys ${keys.slice(0, 8).join(", ")}`;
28
+ }
29
+
30
+ //#endregion
31
+ export { postgresDefaultName, postgresProbe };
32
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.js","names":["options: PostgresProbeOptions","run: () => PromiseLike<ProbeResult>","client: PostgresLikeClient"],"sources":["../src/mod.ts"],"sourcesContent":["/**\n * Postgres probe for `@openstatus/health`: runs `select 1` through `pg`,\n * postgres.js, `@neondatabase/serverless`, `@vercel/postgres` or any client\n * with a `query()` or `unsafe()` method.\n *\n * ```ts\n * import { Pool } from \"pg\";\n * import { postgresProbe } from \"@openstatus/health-postgres\";\n *\n * const probe = postgresProbe({ client: new Pool({ connectionString }) });\n * ```\n *\n * A timed-out check is reported `timeout` without cancelling the in-flight\n * driver query: none of the supported clients accept an `AbortSignal`.\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 postgresDefaultName = \"database\";\n\n/** The subset of a Postgres client the probe uses; one of the two methods must exist. */\nexport interface PostgresLikeClient {\n /** `pg` pools and clients, `@vercel/postgres`, Neon's `Pool` and `sql.query()`. */\n query?(text: string): PromiseLike<ProbeResult>;\n /** postgres.js's `sql.unsafe()`. */\n unsafe?(query: string): PromiseLike<ProbeResult>;\n}\n\n/** Options for `postgresProbe()`. */\nexport interface PostgresProbeOptions extends ProbeOverrides {\n /** A Postgres pool, client or postgres.js `sql` instance. */\n readonly client: PostgresLikeClient;\n}\n\n/** A probe that runs `select 1`; critical by default. Throws `ProbeConfigError` without `query()` or `unsafe()`. */\nexport function postgresProbe(options: PostgresProbeOptions): Probe {\n const client = options.client;\n let run: () => PromiseLike<ProbeResult>;\n if (typeof client?.query === \"function\") {\n run = () => client.query!(\"select 1\");\n } else if (typeof client?.unsafe === \"function\") {\n run = () => client.unsafe!(\"select 1\");\n } else {\n throw new ProbeConfigError(\n \"postgresProbe\",\n \"client\",\n `must expose query() or unsafe(), got ${describe(client)}`,\n );\n }\n return {\n name: options.name ?? postgresDefaultName,\n critical: options.critical ?? true,\n timeoutMs: options.timeoutMs,\n skip: options.skip,\n // The signal is ignored: no supported driver takes an AbortSignal, so a\n // timed-out query keeps running. See the README.\n run: async () => {\n await run();\n },\n };\n}\n\nfunction describe(client: PostgresLikeClient): string {\n if (client == null) return String(client);\n if (typeof client !== \"object\" && typeof client !== \"function\") {\n return typeof client;\n }\n const keys = Object.keys(client);\n return keys.length === 0\n ? `${\n typeof client === \"function\" ? \"a function\" : \"an object\"\n } with no keys`\n : `an object with keys ${keys.slice(0, 8).join(\", \")}`;\n}\n"],"mappings":";;;;AA0BA,MAAa,sBAAsB;;AAiBnC,SAAgB,cAAcA,SAAsC;CAClE,MAAM,SAAS,QAAQ;CACvB,IAAIC;AACJ,YAAW,QAAQ,UAAU,WAC3B,OAAM,MAAM,OAAO,MAAO,WAAW;iBACrB,QAAQ,WAAW,WACnC,OAAM,MAAM,OAAO,OAAQ,WAAW;KAEtC,OAAM,IAAI,iBACR,iBACA,WACC,uCAAuC,SAAS,OAAO,CAAC;AAG7D,QAAO;EACL,MAAM,QAAQ,QAAQ;EACtB,UAAU,QAAQ,YAAY;EAC9B,WAAW,QAAQ;EACnB,MAAM,QAAQ;EAGd,KAAK,YAAY;AACf,SAAM,KAAK;EACZ;CACF;AACF;AAED,SAAS,SAASC,QAAoC;AACpD,KAAI,UAAU,KAAM,QAAO,OAAO,OAAO;AACzC,YAAW,WAAW,mBAAmB,WAAW,WAClD,eAAc;CAEhB,MAAM,OAAO,OAAO,KAAK,OAAO;AAChC,QAAO,KAAK,WAAW,KAClB,SACM,WAAW,aAAa,eAAe,YAC/C,kBACE,sBAAsB,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC;AACxD"}
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@openstatus/health-postgres",
3
+ "version": "0.1.4-dev.0",
4
+ "description": "Postgres probe for @openstatus/health",
5
+ "keywords": [
6
+ "openstatus",
7
+ "health",
8
+ "healthcheck",
9
+ "postgres",
10
+ "postgresql",
11
+ "pg",
12
+ "database"
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/postgres/"
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
+ "pg": ">=8.0.0",
53
+ "postgres": ">=3.0.0"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "pg": {
57
+ "optional": true
58
+ },
59
+ "postgres": {
60
+ "optional": true
61
+ }
62
+ },
63
+ "devDependencies": {
64
+ "pg": "^8.16.0",
65
+ "@types/pg": "^8.15.0",
66
+ "postgres": "^3.4.0",
67
+ "tsdown": "^0.12.7",
68
+ "typescript": "^5.8.3"
69
+ },
70
+ "scripts": {
71
+ "build": "tsdown",
72
+ "prepack": "tsdown",
73
+ "test": "node --experimental-transform-types --test"
74
+ }
75
+ }