@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 +148 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +1 -0
- package/dist/mongodb.d.mts +21 -0
- package/dist/mongodb.mjs +1 -0
- package/dist/mongoose.d.mts +19 -0
- package/dist/mongoose.mjs +1 -0
- package/dist/shared-B-1hAtzF.mjs +1 -0
- package/dist/shared-C_B8UrQ_.d.mts +13 -0
- package/package.json +54 -0
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
|
+
```
|
package/dist/index.d.mts
ADDED
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 };
|
package/dist/mongodb.mjs
ADDED
|
@@ -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
|
+
}
|