@healthzkit/mongo 0.0.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 ADDED
@@ -0,0 +1,148 @@
1
+ # @healthzkit/mongo
2
+
3
+ MongoDB **healthzkit** `HealthAdapter` helpers for the official **[`mongodb`](https://www.mongodb.com/docs/drivers/node/current/)** driver and **[`mongoose`](https://mongoosejs.com/)**. Successful checks run an admin **`ping`** and return `ok` with `metadata.latencyMs` plus any fields from an optional `metadata` hook; failures return `fail` with the caught error.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @healthzkit/mongo healthzkit
9
+ # plus one of:
10
+ npm install mongodb
11
+ npm install mongoose
12
+ ```
13
+
14
+ `mongodb` and `mongoose` are optional peers—install the driver you use.
15
+
16
+ ## Package entrypoints
17
+
18
+ | Import | Exports |
19
+ | ---------------------------- | ---------------------------------------------- |
20
+ | `@healthzkit/mongo` | `mongodbAdapter`, `mongooseAdapter`, and types |
21
+ | `@healthzkit/mongo/mongodb` | `mongodbAdapter` only |
22
+ | `@healthzkit/mongo/mongoose` | `mongooseAdapter` only |
23
+
24
+ Use subpath imports when you want to avoid pulling both drivers into your bundle analysis path.
25
+
26
+ ## Shared options
27
+
28
+ Both factories accept `BaseMongoOptions`:
29
+
30
+ | Option | Description |
31
+ | ---------- | ------------------------------------------------------------------------------------------------- |
32
+ | `metadata` | Optional async `(client) => Record<string, unknown>` merged into check metadata with `latencyMs`. |
33
+
34
+ Pass either `connectionString` or an existing client/connection (not both).
35
+
36
+ ## `mongodbAdapter` (`mongodb`)
37
+
38
+ **Peer:** `mongodb` ≥ 6 or ≥ 7.
39
+
40
+ Each check runs `client.db("admin").command({ ping: 1 })` and records round-trip latency.
41
+
42
+ ### Connection string
43
+
44
+ The adapter lazily imports `mongodb`, creates a shared `MongoClient`, and connects once. Concurrent checks reuse the same client. Call **`close()`** on the adapter when you created it via `connectionString` to shut down the internal client (no-op for injected clients).
45
+
46
+ ```ts
47
+ import { createHealthKit } from "healthzkit";
48
+ import { mongodbAdapter } from "@healthzkit/mongo";
49
+
50
+ const adapter = mongodbAdapter({
51
+ connectionString: process.env.MONGODB_URI!,
52
+ mongoOptions: { serverSelectionTimeoutMS: 2000 },
53
+ });
54
+
55
+ const kit = createHealthKit({
56
+ checks: [
57
+ {
58
+ name: "mongodb",
59
+ type: ["readiness"],
60
+ adapter,
61
+ },
62
+ ],
63
+ });
64
+
65
+ // optional: on process shutdown when using connectionString
66
+ await adapter.close();
67
+ ```
68
+
69
+ ### Existing client
70
+
71
+ Pass **`client`** as an existing `MongoClient`. The adapter calls **`connect()`** once and reuses that client across checks. **`close()`** does not close an injected client.
72
+
73
+ ```ts
74
+ import { MongoClient } from "mongodb";
75
+ import { mongodbAdapter } from "@healthzkit/mongo/mongodb";
76
+
77
+ const client = new MongoClient(process.env.MONGODB_URI!);
78
+
79
+ const adapter = mongodbAdapter({
80
+ client,
81
+ metadata: async (c) => {
82
+ const hello = await c.db("admin").command({ hello: 1 });
83
+ return { setName: hello.setName };
84
+ },
85
+ });
86
+ ```
87
+
88
+ ## `mongooseAdapter` (`mongoose`)
89
+
90
+ **Peer:** `mongoose` ≥ 8 or ≥ 9.
91
+
92
+ Each check runs `db.admin().command({ ping: 1 })` on the resolved connection. Works with a **`Mongoose`** instance (`conn.connection.db`) or a mongoose **`Connection`** (`conn.db`).
93
+
94
+ ### Connection string
95
+
96
+ The adapter dynamically imports `mongoose`, calls **`mongoose.connect(connectionString, mongooseOptions)`** once, and reuses that instance.
97
+
98
+ ```ts
99
+ import { mongooseAdapter } from "@healthzkit/mongo/mongoose";
100
+
101
+ const adapter = mongooseAdapter({
102
+ connectionString: process.env.MONGODB_URI!,
103
+ mongooseOptions: { serverSelectionTimeoutMS: 2000 },
104
+ });
105
+ ```
106
+
107
+ ### Existing connection
108
+
109
+ Pass **`connection`** as your app's `mongoose` instance or a `Connection`. If **`readyState`** is not `1` (connected), the adapter awaits **`connection.asPromise()`** before pinging.
110
+
111
+ ```ts
112
+ import mongoose from "mongoose";
113
+ import { mongooseAdapter } from "@healthzkit/mongo";
114
+
115
+ await mongoose.connect(process.env.MONGODB_URI!);
116
+
117
+ const adapter = mongooseAdapter({
118
+ connection: mongoose,
119
+ metadata: async () => ({ driver: "mongoose" }),
120
+ });
121
+ ```
122
+
123
+ ## Check result
124
+
125
+ On success:
126
+
127
+ ```json
128
+ {
129
+ "status": "ok",
130
+ "metadata": { "latencyMs": 8 }
131
+ }
132
+ ```
133
+
134
+ On failure, `status` is `"fail"` and `error` is set (see [healthzkit](https://github.com/alasti-company/healthzkit) for how that rolls up into probe responses).
135
+
136
+ ## Scheduling
137
+
138
+ For busy clusters, pair these adapters with a **`schedule`** on the check so readiness reads cached results instead of pinging MongoDB on every probe. See the **Scheduling** section in the `healthzkit` README.
139
+
140
+ ## Development
141
+
142
+ From the monorepo root:
143
+
144
+ ```bash
145
+ vp install
146
+ vp test --filter @healthzkit/mongo
147
+ vp pack --filter @healthzkit/mongo
148
+ ```
@@ -0,0 +1,3 @@
1
+ import { MongoDbAdapterOptions, mongodbAdapter } from "./mongodb.mjs";
2
+ import { MongooseAdapterOptions, mongooseAdapter } from "./mongoose.mjs";
3
+ export { type MongoDbAdapterOptions, type MongooseAdapterOptions, mongodbAdapter, mongooseAdapter };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import{mongodbAdapter as e}from"./mongodb.mjs";import{mongooseAdapter as t}from"./mongoose.mjs";export{e as mongodbAdapter,t as mongooseAdapter};
@@ -0,0 +1,21 @@
1
+ import { n as HealthAdapter, t as BaseMongoOptions } from "./shared-C_B8UrQ_.mjs";
2
+ import { MongoClient, MongoClientOptions } from "mongodb";
3
+
4
+ //#region src/mongodb.d.ts
5
+ interface MongoDbAdapterOptionsWithClient extends BaseMongoOptions<MongoClient> {
6
+ client: MongoClient;
7
+ connectionString?: never;
8
+ mongoOptions?: never;
9
+ }
10
+ interface MongoDbAdapterOptionsWithConnectionString extends BaseMongoOptions<MongoClient> {
11
+ connectionString: string;
12
+ mongoOptions?: MongoClientOptions;
13
+ client?: never;
14
+ }
15
+ type MongoDbAdapterOptions = MongoDbAdapterOptionsWithClient | MongoDbAdapterOptionsWithConnectionString;
16
+ type MongoDbAdapter = HealthAdapter & {
17
+ close(): Promise<void>;
18
+ };
19
+ declare function mongodbAdapter(options: MongoDbAdapterOptions): MongoDbAdapter;
20
+ //#endregion
21
+ export { MongoDbAdapter, MongoDbAdapterOptions, MongoDbAdapterOptionsWithClient, MongoDbAdapterOptionsWithConnectionString, mongodbAdapter };
@@ -0,0 +1 @@
1
+ import{n as e,t}from"./shared-B-1hAtzF.mjs";function n(n){let r=null,i=null,a=null;async function o(e,t){return i??=(async()=>{let{MongoClient:n}=await import(`mongodb`),i=new n(e,t);return await i.connect(),r=i,i})().catch(e=>{throw i=null,r=null,e}),i}async function s(){if(`connectionString`in n&&n.connectionString)return o(n.connectionString,n.mongoOptions);if(`client`in n&&n.client)return a??=n.client.connect().then(()=>void 0).catch(e=>{throw a=null,e}),await a,n.client;throw Error(`mongoAdapter: provide a non-empty connectionString or a client`)}return{async check(){try{let t=await s(),r=Date.now();return await t.db(`admin`).command({ping:1}),e(Date.now()-r,n.metadata?await n.metadata(t):void 0)}catch(e){return t(e)}},async close(){r&&(await r.close(),r=null,i=null)}}}export{n as mongodbAdapter};
@@ -0,0 +1,19 @@
1
+ import { n as HealthAdapter, t as BaseMongoOptions } from "./shared-C_B8UrQ_.mjs";
2
+ import { ConnectOptions, Connection, Mongoose } from "mongoose";
3
+
4
+ //#region src/mongoose.d.ts
5
+ type MongooseConnection = Connection | Mongoose;
6
+ interface MongooseAdapterOptionsWithConnection extends BaseMongoOptions<MongooseConnection> {
7
+ connection: MongooseConnection;
8
+ connectionString?: never;
9
+ mongooseOptions?: never;
10
+ }
11
+ interface MongooseAdapterOptionsWithConnectionString extends BaseMongoOptions<MongooseConnection> {
12
+ connectionString: string;
13
+ mongooseOptions?: ConnectOptions;
14
+ connection?: never;
15
+ }
16
+ type MongooseAdapterOptions = MongooseAdapterOptionsWithConnection | MongooseAdapterOptionsWithConnectionString;
17
+ declare function mongooseAdapter(options: MongooseAdapterOptions): HealthAdapter;
18
+ //#endregion
19
+ export { MongooseAdapterOptions, MongooseAdapterOptionsWithConnection, MongooseAdapterOptionsWithConnectionString, mongooseAdapter };
@@ -0,0 +1 @@
1
+ import{n as e,t}from"./shared-B-1hAtzF.mjs";function n(n){let r=null;async function i(e,t){return r??=(async()=>{let{default:n}=await import(`mongoose`);return await n.connect(e,t),n})().catch(e=>{throw r=null,e}),r}async function a(){if(`connectionString`in n&&n.connectionString)return i(n.connectionString,n.mongooseOptions);let e=n.connection;if(!e)throw Error(`mongoose adapter requires connection or connectionString`);return`readyState`in e&&e.readyState!==1&&await e.asPromise(),e}return{async check(){try{let t=await a(),r=Date.now(),i=`db`in t?t.db:t.connection.db;if(!i)throw Error(`mongoose adapter: database unavailable`);return await i.admin().command({ping:1}),e(Date.now()-r,n.metadata?await n.metadata(t):void 0)}catch(e){return t(e)}}}}export{n as mongooseAdapter};
@@ -0,0 +1 @@
1
+ function e(e,t){return{status:`ok`,metadata:{...t,latencyMs:e}}}function t(e){return{status:`fail`,error:e instanceof Error?e:Error(String(e))}}export{e as n,t};
@@ -0,0 +1,13 @@
1
+ import { HealthAdapter } from "healthzkit";
2
+
3
+ //#region src/shared.d.ts
4
+ type MetadataFn<TClient> = (client: TClient) => Promise<Record<string, unknown>>;
5
+ interface BaseMongoOptions<TClient> {
6
+ /**
7
+ * Optional function to populate metadata in the check result.
8
+ * Receives the resolved client so you can run additional queries.
9
+ */
10
+ metadata?: MetadataFn<TClient>;
11
+ }
12
+ //#endregion
13
+ export { HealthAdapter as n, BaseMongoOptions as t };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@healthzkit/mongo",
3
+ "version": "0.0.1",
4
+ "license": "AGPL-3.0-only",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/alasti-company/healthzkit.dev",
8
+ "directory": "packages/mongo"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "type": "module",
14
+ "exports": {
15
+ ".": "./dist/index.mjs",
16
+ "./mongodb": "./dist/mongodb.mjs",
17
+ "./mongoose": "./dist/mongoose.mjs",
18
+ "./package.json": "./package.json"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "scripts": {
24
+ "build": "vp pack",
25
+ "dev": "vp pack --watch",
26
+ "test": "vp test",
27
+ "check": "vp check",
28
+ "prepublishOnly": "vp run build"
29
+ },
30
+ "devDependencies": {
31
+ "@types/mongodb": "^4.0.7",
32
+ "@types/mongoose": "^5.11.97",
33
+ "@types/node": "^25.6.2",
34
+ "@typescript/native-preview": "7.0.0-dev.20260509.2",
35
+ "bumpp": "^11.1.0",
36
+ "healthzkit": "workspace:*",
37
+ "mongodb": "^7.2.0",
38
+ "mongoose": "^9.6.2",
39
+ "typescript": "^6.0.3",
40
+ "vite-plus": "^0.1.20"
41
+ },
42
+ "peerDependencies": {
43
+ "mongodb": ">=6.0.0 || >=7.0.0",
44
+ "mongoose": ">= 8.0.0 || >=9.0.0"
45
+ },
46
+ "peerDependenciesMeta": {
47
+ "mongodb": {
48
+ "optional": true
49
+ },
50
+ "mongoose": {
51
+ "optional": true
52
+ }
53
+ }
54
+ }