@procedures/mongo 0.0.0-stage → 0.1.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/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +1322 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/connection.d.ts +93 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +147 -0
- package/dist/connection.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/module.d.ts +20 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +58 -0
- package/dist/module.js.map +1 -0
- package/dist/procedures/collections.create.d.ts +20 -0
- package/dist/procedures/collections.create.d.ts.map +1 -0
- package/dist/procedures/collections.create.js +43 -0
- package/dist/procedures/collections.create.js.map +1 -0
- package/dist/procedures/collections.drop.d.ts +19 -0
- package/dist/procedures/collections.drop.d.ts.map +1 -0
- package/dist/procedures/collections.drop.js +36 -0
- package/dist/procedures/collections.drop.js.map +1 -0
- package/dist/procedures/collections.list.d.ts +16 -0
- package/dist/procedures/collections.list.d.ts.map +1 -0
- package/dist/procedures/collections.list.js +31 -0
- package/dist/procedures/collections.list.js.map +1 -0
- package/dist/procedures/collections.stats.d.ts +15 -0
- package/dist/procedures/collections.stats.d.ts.map +1 -0
- package/dist/procedures/collections.stats.js +38 -0
- package/dist/procedures/collections.stats.js.map +1 -0
- package/dist/procedures/database.info.d.ts +15 -0
- package/dist/procedures/database.info.d.ts.map +1 -0
- package/dist/procedures/database.info.js +38 -0
- package/dist/procedures/database.info.js.map +1 -0
- package/dist/procedures/database.ping.d.ts +17 -0
- package/dist/procedures/database.ping.d.ts.map +1 -0
- package/dist/procedures/database.ping.js +31 -0
- package/dist/procedures/database.ping.js.map +1 -0
- package/dist/procedures/documents.aggregate.d.ts +19 -0
- package/dist/procedures/documents.aggregate.d.ts.map +1 -0
- package/dist/procedures/documents.aggregate.js +39 -0
- package/dist/procedures/documents.aggregate.js.map +1 -0
- package/dist/procedures/documents.count.d.ts +18 -0
- package/dist/procedures/documents.count.d.ts.map +1 -0
- package/dist/procedures/documents.count.js +29 -0
- package/dist/procedures/documents.count.js.map +1 -0
- package/dist/procedures/documents.delete.d.ts +17 -0
- package/dist/procedures/documents.delete.d.ts.map +1 -0
- package/dist/procedures/documents.delete.js +31 -0
- package/dist/procedures/documents.delete.js.map +1 -0
- package/dist/procedures/documents.find.d.ts +23 -0
- package/dist/procedures/documents.find.d.ts.map +1 -0
- package/dist/procedures/documents.find.js +103 -0
- package/dist/procedures/documents.find.js.map +1 -0
- package/dist/procedures/documents.get.d.ts +20 -0
- package/dist/procedures/documents.get.d.ts.map +1 -0
- package/dist/procedures/documents.get.js +54 -0
- package/dist/procedures/documents.get.js.map +1 -0
- package/dist/procedures/documents.insert.d.ts +21 -0
- package/dist/procedures/documents.insert.d.ts.map +1 -0
- package/dist/procedures/documents.insert.js +55 -0
- package/dist/procedures/documents.insert.js.map +1 -0
- package/dist/procedures/documents.update.d.ts +26 -0
- package/dist/procedures/documents.update.d.ts.map +1 -0
- package/dist/procedures/documents.update.js +61 -0
- package/dist/procedures/documents.update.js.map +1 -0
- package/dist/procedures/index.d.ts +21 -0
- package/dist/procedures/index.d.ts.map +1 -0
- package/dist/procedures/index.js +26 -0
- package/dist/procedures/index.js.map +1 -0
- package/dist/procedures/indexes.create.d.ts +20 -0
- package/dist/procedures/indexes.create.d.ts.map +1 -0
- package/dist/procedures/indexes.create.js +44 -0
- package/dist/procedures/indexes.create.js.map +1 -0
- package/dist/procedures/indexes.drop.d.ts +17 -0
- package/dist/procedures/indexes.drop.d.ts.map +1 -0
- package/dist/procedures/indexes.drop.js +30 -0
- package/dist/procedures/indexes.drop.js.map +1 -0
- package/dist/procedures/indexes.list.d.ts +17 -0
- package/dist/procedures/indexes.list.d.ts.map +1 -0
- package/dist/procedures/indexes.list.js +40 -0
- package/dist/procedures/indexes.list.js.map +1 -0
- package/dist/procedures/input-schemas.d.ts +45 -0
- package/dist/procedures/input-schemas.d.ts.map +1 -0
- package/dist/procedures/input-schemas.js +52 -0
- package/dist/procedures/input-schemas.js.map +1 -0
- package/dist/procedures/schema.d.ts +2 -0
- package/dist/procedures/schema.d.ts.map +1 -0
- package/dist/procedures/schema.js +2 -0
- package/dist/procedures/schema.js.map +1 -0
- package/dist/procedures/target.d.ts +44 -0
- package/dist/procedures/target.d.ts.map +1 -0
- package/dist/procedures/target.js +98 -0
- package/dist/procedures/target.js.map +1 -0
- package/dist/procedures.types.d.ts +129 -0
- package/dist/procedures.types.d.ts.map +1 -0
- package/dist/procedures.types.js +24 -0
- package/dist/procedures.types.js.map +1 -0
- package/dist/register.d.ts +8 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +14 -0
- package/dist/register.js.map +1 -0
- package/dist/scope.d.ts +33 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +52 -0
- package/dist/scope.js.map +1 -0
- package/dist/storage/index.d.ts +6 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/mongo-storage.d.ts +50 -0
- package/dist/storage/mongo-storage.d.ts.map +1 -0
- package/dist/storage/mongo-storage.js +109 -0
- package/dist/storage/mongo-storage.js.map +1 -0
- package/dist/types.d.ts +239 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +58 -0
- package/dist/types.js.map +1 -0
- package/package.json +85 -3
- package/src/connection.ts +198 -0
- package/src/index.ts +159 -0
- package/src/module.ts +62 -0
- package/src/procedures/collections.create.ts +69 -0
- package/src/procedures/collections.drop.ts +62 -0
- package/src/procedures/collections.list.ts +53 -0
- package/src/procedures/collections.stats.ts +57 -0
- package/src/procedures/database.info.ts +58 -0
- package/src/procedures/database.ping.ts +54 -0
- package/src/procedures/documents.aggregate.ts +68 -0
- package/src/procedures/documents.count.ts +52 -0
- package/src/procedures/documents.delete.ts +54 -0
- package/src/procedures/documents.find.ts +147 -0
- package/src/procedures/documents.get.ts +98 -0
- package/src/procedures/documents.insert.ts +83 -0
- package/src/procedures/documents.update.ts +93 -0
- package/src/procedures/index.ts +30 -0
- package/src/procedures/indexes.create.ts +70 -0
- package/src/procedures/indexes.drop.ts +53 -0
- package/src/procedures/indexes.list.ts +64 -0
- package/src/procedures/input-schemas.ts +63 -0
- package/src/procedures/schema.ts +1 -0
- package/src/procedures/target.ts +123 -0
- package/src/procedures.types.ts +162 -0
- package/src/register.ts +17 -0
- package/src/scope.ts +69 -0
- package/src/storage/index.ts +6 -0
- package/src/storage/mongo-storage.ts +151 -0
- package/src/types.ts +337 -0
package/README.md
CHANGED
|
@@ -1,3 +1,1323 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @procedures/mongo
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@procedures/mongo)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
[](https://nodejs.org/)
|
|
7
|
+
|
|
8
|
+
MongoDB client wrapper with client procedures for local or RPC access. Provides a comprehensive set of procedures for database operations, collection management, document CRUD, indexing, and aggregation pipeline support.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
`client-mongo` bridges MongoDB operations into the client procedure ecosystem, enabling both:
|
|
13
|
+
- **Local usage**: Direct MongoDB connection with native driver
|
|
14
|
+
- **RPC usage**: Remote procedure calls via `client.call()`
|
|
15
|
+
|
|
16
|
+
The package follows the client procedure pattern, auto-registering 16 procedures organized into 4 categories:
|
|
17
|
+
- **Database**: `ping`, `info`
|
|
18
|
+
- **Collections**: `list`, `create`, `drop`, `stats`
|
|
19
|
+
- **Documents**: `find`, `get`, `insert`, `update`, `delete`, `count`, `aggregate`
|
|
20
|
+
- **Indexes**: `list`, `create`, `drop`
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
|
|
24
|
+
```mermaid
|
|
25
|
+
graph TB
|
|
26
|
+
subgraph "Client Ecosystem"
|
|
27
|
+
Client["@procedures/client"]
|
|
28
|
+
Registry["Procedure Registry"]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
subgraph "client-mongo Package"
|
|
32
|
+
Register["register.ts<br/>(Auto-registers procedures)"]
|
|
33
|
+
Connection["connection.ts<br/>(Connection Management)"]
|
|
34
|
+
|
|
35
|
+
subgraph "Procedure Categories"
|
|
36
|
+
DB["Database Procedures<br/>ping, info"]
|
|
37
|
+
Collections["Collection Procedures<br/>list, create, drop, stats"]
|
|
38
|
+
Documents["Document Procedures<br/>find, get, insert, update, delete, count, aggregate"]
|
|
39
|
+
Indexes["Index Procedures<br/>list, create, drop"]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Types["types.ts<br/>(Type Definitions)"]
|
|
43
|
+
ProcTypes["procedures.types.ts<br/>(Typed Interface)"]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
subgraph "MongoDB Driver"
|
|
47
|
+
MongoDB["mongodb npm package"]
|
|
48
|
+
MongoClient["MongoClient"]
|
|
49
|
+
Db["Db Instance"]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
subgraph "External Systems"
|
|
53
|
+
MongoServer["MongoDB Server<br/>(local or remote)"]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
Register --> Client
|
|
57
|
+
Register --> Registry
|
|
58
|
+
|
|
59
|
+
DB --> Connection
|
|
60
|
+
Collections --> Connection
|
|
61
|
+
Documents --> Connection
|
|
62
|
+
Indexes --> Connection
|
|
63
|
+
|
|
64
|
+
Connection --> MongoClient
|
|
65
|
+
MongoClient --> Db
|
|
66
|
+
Db --> MongoServer
|
|
67
|
+
|
|
68
|
+
Types -.-> DB
|
|
69
|
+
Types -.-> Collections
|
|
70
|
+
Types -.-> Documents
|
|
71
|
+
Types -.-> Indexes
|
|
72
|
+
|
|
73
|
+
ProcTypes -.provides typing.-> Client
|
|
74
|
+
|
|
75
|
+
style Register fill:#e1f5ff
|
|
76
|
+
style Connection fill:#fff4e1
|
|
77
|
+
style Types fill:#f0f0f0
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Package Dependency Flow
|
|
81
|
+
|
|
82
|
+
```mermaid
|
|
83
|
+
graph LR
|
|
84
|
+
App["Your Application"]
|
|
85
|
+
ClientMongo["@procedures/mongo"]
|
|
86
|
+
Client["@procedures/client"]
|
|
87
|
+
MongoDB["mongodb"]
|
|
88
|
+
|
|
89
|
+
App --> ClientMongo
|
|
90
|
+
ClientMongo --> Client
|
|
91
|
+
ClientMongo --> MongoDB
|
|
92
|
+
|
|
93
|
+
App -.client.call.-> Client
|
|
94
|
+
Client -.executes.-> ClientMongo
|
|
95
|
+
ClientMongo -.queries.-> MongoDB
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Connection Management Flow
|
|
99
|
+
|
|
100
|
+
```mermaid
|
|
101
|
+
sequenceDiagram
|
|
102
|
+
participant App
|
|
103
|
+
participant Connection
|
|
104
|
+
participant MongoClient
|
|
105
|
+
participant MongoDB
|
|
106
|
+
|
|
107
|
+
App->>Connection: connect({ uri, database })
|
|
108
|
+
Connection->>MongoClient: new MongoClient(uri)
|
|
109
|
+
MongoClient->>MongoDB: Connect
|
|
110
|
+
MongoDB-->>MongoClient: Connected
|
|
111
|
+
Connection->>Connection: setDefaultConnection()
|
|
112
|
+
Connection-->>App: MongoConnection
|
|
113
|
+
|
|
114
|
+
App->>Connection: getDb()
|
|
115
|
+
Connection-->>App: Db instance
|
|
116
|
+
|
|
117
|
+
App->>Connection: disconnect()
|
|
118
|
+
Connection->>MongoClient: close()
|
|
119
|
+
MongoClient->>MongoDB: Disconnect
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Installation
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npm install @procedures/mongo
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Peer Dependencies
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"@procedures/client": "github:mark1russell7/client#main",
|
|
133
|
+
"mongodb": "^7.0.0"
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Configuration
|
|
138
|
+
|
|
139
|
+
### Environment Variables
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# MongoDB connection URI (optional, defaults to mongodb://localhost:27017)
|
|
143
|
+
MONGODB_URI=mongodb://localhost:27017
|
|
144
|
+
|
|
145
|
+
# Default database name (optional, defaults to "test")
|
|
146
|
+
MONGODB_DATABASE=myapp
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Programmatic Configuration
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { connect } from "@procedures/mongo";
|
|
153
|
+
|
|
154
|
+
// Using environment variables
|
|
155
|
+
await connect();
|
|
156
|
+
|
|
157
|
+
// With explicit options
|
|
158
|
+
await connect({
|
|
159
|
+
uri: "mongodb://localhost:27017",
|
|
160
|
+
database: "myapp",
|
|
161
|
+
clientOptions: {
|
|
162
|
+
// Any MongoDB client options
|
|
163
|
+
maxPoolSize: 10,
|
|
164
|
+
minPoolSize: 2,
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### The first call connects
|
|
170
|
+
|
|
171
|
+
A host does not have to call `connect()`. When there is no open connection, the first procedure call connects with the options of `configure()`, or with the environment variables. Concurrent first calls share one attempt.
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { configure } from "@procedures/mongo";
|
|
175
|
+
|
|
176
|
+
configure({ uri: "mongodb://localhost:27017", database: "myapp" });
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### The collection and the database of a call
|
|
180
|
+
|
|
181
|
+
Each procedure reads `collection` and `database` from its input. An MCP tool call can set them. The call metadata is the fallback, for the clients that set it.
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
await client.exec(["mongo", "documents", "count"], { collection: "users", query: { active: true } });
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## API Reference
|
|
188
|
+
|
|
189
|
+
### Connection Management
|
|
190
|
+
|
|
191
|
+
#### `connect(options?): Promise<MongoConnection>`
|
|
192
|
+
|
|
193
|
+
Create and connect to MongoDB. Sets the default connection used by all procedures.
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
interface MongoConnectionOptions {
|
|
197
|
+
uri?: string; // Default: MONGODB_URI or mongodb://localhost:27017
|
|
198
|
+
database?: string; // Default: MONGODB_DATABASE or "test"
|
|
199
|
+
clientOptions?: MongoClientOptions;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
interface MongoConnection {
|
|
203
|
+
getDb(): Db;
|
|
204
|
+
getClient(): MongoClient;
|
|
205
|
+
connect(): Promise<void>;
|
|
206
|
+
disconnect(): Promise<void>;
|
|
207
|
+
isConnected(): boolean;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Example:**
|
|
212
|
+
```typescript
|
|
213
|
+
const conn = await connect({
|
|
214
|
+
uri: "mongodb://localhost:27017",
|
|
215
|
+
database: "myapp"
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
#### `disconnect(): Promise<void>`
|
|
220
|
+
|
|
221
|
+
Disconnect the default connection.
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
await disconnect();
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### `getDb(): Db`
|
|
228
|
+
|
|
229
|
+
Get the database instance from the default connection.
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
const db = getDb();
|
|
233
|
+
const collection = db.collection("users");
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
#### `getClient(): MongoClient`
|
|
237
|
+
|
|
238
|
+
Get the MongoClient from the default connection.
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
const client = getClient();
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### `getDefaultConnection(): MongoConnection`
|
|
245
|
+
|
|
246
|
+
Get the default connection instance. Throws if not connected.
|
|
247
|
+
|
|
248
|
+
#### `setDefaultConnection(conn: MongoConnection): void`
|
|
249
|
+
|
|
250
|
+
Set the default connection (advanced usage).
|
|
251
|
+
|
|
252
|
+
#### `hasDefaultConnection(): boolean`
|
|
253
|
+
|
|
254
|
+
Check if a default connection exists.
|
|
255
|
+
|
|
256
|
+
### Registered Procedures
|
|
257
|
+
|
|
258
|
+
All procedures are automatically registered when the package is imported. They can be called via `client.call()` or used directly.
|
|
259
|
+
|
|
260
|
+
#### Database Procedures
|
|
261
|
+
|
|
262
|
+
##### `mongo.database.ping`
|
|
263
|
+
|
|
264
|
+
Test database connectivity and measure latency.
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
// Via RPC
|
|
268
|
+
const result = await client.exec(
|
|
269
|
+
["mongo", "database", "ping"],
|
|
270
|
+
{ timeout: 5000 }
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
// Direct import
|
|
274
|
+
import { pingProcedure } from "@procedures/mongo";
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Input:**
|
|
278
|
+
```typescript
|
|
279
|
+
interface PingInput {
|
|
280
|
+
timeout?: number; // Optional timeout in milliseconds
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Output:**
|
|
285
|
+
```typescript
|
|
286
|
+
interface PingOutput {
|
|
287
|
+
latencyMs: number; // Response time in milliseconds
|
|
288
|
+
ok: boolean; // Server status
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
##### `mongo.database.info`
|
|
293
|
+
|
|
294
|
+
Get database information and statistics.
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
const result = await client.exec(
|
|
298
|
+
["mongo", "database", "info"],
|
|
299
|
+
{ includeStats: true }
|
|
300
|
+
);
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Input:**
|
|
304
|
+
```typescript
|
|
305
|
+
interface InfoInput {
|
|
306
|
+
includeStats?: boolean;
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Output:**
|
|
311
|
+
```typescript
|
|
312
|
+
interface DatabaseInfo {
|
|
313
|
+
name: string; // Database name
|
|
314
|
+
collections: number; // Number of collections
|
|
315
|
+
views: number; // Number of views
|
|
316
|
+
sizeOnDisk: number; // Size on disk in bytes
|
|
317
|
+
empty: boolean; // Whether database is empty
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
#### Collection Procedures
|
|
322
|
+
|
|
323
|
+
##### `mongo.collections.list`
|
|
324
|
+
|
|
325
|
+
List all collections in the database.
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
const result = await client.exec(
|
|
329
|
+
["mongo", "collections", "list"],
|
|
330
|
+
{ filter: "user" }
|
|
331
|
+
);
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**Input:**
|
|
335
|
+
```typescript
|
|
336
|
+
interface ListCollectionsInput {
|
|
337
|
+
filter?: string; // Filter by name pattern
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
**Output:**
|
|
342
|
+
```typescript
|
|
343
|
+
interface ListCollectionsOutput {
|
|
344
|
+
collections: string[]; // Collection names
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
##### `mongo.collections.create`
|
|
349
|
+
|
|
350
|
+
Create a new collection.
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
const result = await client.exec(
|
|
354
|
+
["mongo", "collections", "create"],
|
|
355
|
+
{
|
|
356
|
+
name: "logs",
|
|
357
|
+
options: {
|
|
358
|
+
capped: true,
|
|
359
|
+
size: 10485760, // 10MB
|
|
360
|
+
max: 1000
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**Input:**
|
|
367
|
+
```typescript
|
|
368
|
+
interface CreateCollectionInput {
|
|
369
|
+
name: string;
|
|
370
|
+
options?: CollectionOptions;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
interface CollectionOptions {
|
|
374
|
+
capped?: boolean;
|
|
375
|
+
size?: number; // Max size in bytes (for capped)
|
|
376
|
+
max?: number; // Max documents (for capped)
|
|
377
|
+
validator?: Document; // JSON Schema validator
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**Output:**
|
|
382
|
+
```typescript
|
|
383
|
+
interface CreateCollectionOutput {
|
|
384
|
+
created: boolean;
|
|
385
|
+
name: string;
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
##### `mongo.collections.drop`
|
|
390
|
+
|
|
391
|
+
Drop a collection.
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
const result = await client.exec(
|
|
395
|
+
["mongo", "collections", "drop"],
|
|
396
|
+
{ name: "old_collection" }
|
|
397
|
+
);
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
**Input:**
|
|
401
|
+
```typescript
|
|
402
|
+
interface DropCollectionInput {
|
|
403
|
+
name: string;
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
**Output:**
|
|
408
|
+
```typescript
|
|
409
|
+
interface DropCollectionOutput {
|
|
410
|
+
dropped: boolean;
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
##### `mongo.collections.stats`
|
|
415
|
+
|
|
416
|
+
Get collection statistics.
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
const result = await client.exec(
|
|
420
|
+
["mongo", "collections", "stats"],
|
|
421
|
+
{},
|
|
422
|
+
{ metadata: { collection: "users" } }
|
|
423
|
+
);
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**Input:**
|
|
427
|
+
```typescript
|
|
428
|
+
interface StatsInput {
|
|
429
|
+
// Collection from metadata
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
**Output:**
|
|
434
|
+
```typescript
|
|
435
|
+
interface CollectionStats {
|
|
436
|
+
count: number; // Number of documents
|
|
437
|
+
size: number; // Size of documents in bytes
|
|
438
|
+
avgObjSize: number; // Average document size
|
|
439
|
+
storageSize: number; // Total storage size
|
|
440
|
+
nindexes: number; // Number of indexes
|
|
441
|
+
totalIndexSize: number; // Total index size
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
#### Document Procedures
|
|
446
|
+
|
|
447
|
+
##### `mongo.documents.find`
|
|
448
|
+
|
|
449
|
+
Find documents with pagination, filtering, sorting, and projection.
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
const result = await client.exec(
|
|
453
|
+
["mongo", "documents", "find"],
|
|
454
|
+
{
|
|
455
|
+
query: { status: "active", age: { $gte: 18 } },
|
|
456
|
+
projection: { name: 1, email: 1 },
|
|
457
|
+
sort: { createdAt: -1 },
|
|
458
|
+
page: 1,
|
|
459
|
+
limit: 20
|
|
460
|
+
},
|
|
461
|
+
{ metadata: { collection: "users" } }
|
|
462
|
+
);
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**Input:**
|
|
466
|
+
```typescript
|
|
467
|
+
interface FindInput {
|
|
468
|
+
query?: DocumentQuery; // MongoDB filter
|
|
469
|
+
projection?: Record<string, 0 | 1>; // Field projection
|
|
470
|
+
sort?: SortSpec; // Sort specification
|
|
471
|
+
page?: number; // Page number (1-indexed)
|
|
472
|
+
limit?: number; // Items per page (max 100)
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
type DocumentQuery = Filter<Document>;
|
|
476
|
+
type SortSpec = Record<string, 1 | -1>;
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
**Output:**
|
|
480
|
+
```typescript
|
|
481
|
+
interface FindOutput {
|
|
482
|
+
documents: MongoDocument[];
|
|
483
|
+
pagination: PaginationOutput;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
interface PaginationOutput {
|
|
487
|
+
page: number;
|
|
488
|
+
limit: number;
|
|
489
|
+
total: number;
|
|
490
|
+
totalPages: number;
|
|
491
|
+
hasNext: boolean;
|
|
492
|
+
hasPrev: boolean;
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
##### `mongo.documents.get`
|
|
497
|
+
|
|
498
|
+
Get a single document by ID.
|
|
499
|
+
|
|
500
|
+
```typescript
|
|
501
|
+
const result = await client.exec(
|
|
502
|
+
["mongo", "documents", "get"],
|
|
503
|
+
{ id: "507f1f77bcf86cd799439011" },
|
|
504
|
+
{ metadata: { collection: "users" } }
|
|
505
|
+
);
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
**Input:**
|
|
509
|
+
```typescript
|
|
510
|
+
interface GetInput {
|
|
511
|
+
id: string; // Document ID (converted to ObjectId)
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
**Output:**
|
|
516
|
+
```typescript
|
|
517
|
+
interface GetOutput {
|
|
518
|
+
document: MongoDocument | null;
|
|
519
|
+
}
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
##### `mongo.documents.insert`
|
|
523
|
+
|
|
524
|
+
Insert one or more documents.
|
|
525
|
+
|
|
526
|
+
```typescript
|
|
527
|
+
// Insert single document
|
|
528
|
+
const result = await client.exec(
|
|
529
|
+
["mongo", "documents", "insert"],
|
|
530
|
+
{
|
|
531
|
+
documents: {
|
|
532
|
+
name: "John Doe",
|
|
533
|
+
email: "john@example.com",
|
|
534
|
+
createdAt: new Date()
|
|
535
|
+
}
|
|
536
|
+
},
|
|
537
|
+
{ metadata: { collection: "users" } }
|
|
538
|
+
);
|
|
539
|
+
|
|
540
|
+
// Insert multiple documents
|
|
541
|
+
const result = await client.exec(
|
|
542
|
+
["mongo", "documents", "insert"],
|
|
543
|
+
{
|
|
544
|
+
documents: [
|
|
545
|
+
{ name: "Alice" },
|
|
546
|
+
{ name: "Bob" }
|
|
547
|
+
]
|
|
548
|
+
},
|
|
549
|
+
{ metadata: { collection: "users" } }
|
|
550
|
+
);
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
**Input:**
|
|
554
|
+
```typescript
|
|
555
|
+
interface InsertInput {
|
|
556
|
+
documents: MongoDocument | MongoDocument[];
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
**Output:**
|
|
561
|
+
```typescript
|
|
562
|
+
interface InsertOutput {
|
|
563
|
+
insertedCount: number;
|
|
564
|
+
insertedIds: string[];
|
|
565
|
+
}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
##### `mongo.documents.update`
|
|
569
|
+
|
|
570
|
+
Update one document by `id`, or the documents that match a `filter`.
|
|
571
|
+
|
|
572
|
+
A write needs exactly one of `id` or `filter`. An unknown field is an error: `query` is the field of `find` and `count`, not of `update`. An empty filter matches every document, so it needs `confirm: true`.
|
|
573
|
+
|
|
574
|
+
```typescript
|
|
575
|
+
// Update one document by ID
|
|
576
|
+
const result = await client.exec(
|
|
577
|
+
["mongo", "documents", "update"],
|
|
578
|
+
{
|
|
579
|
+
collection: "users",
|
|
580
|
+
id: "...",
|
|
581
|
+
update: { $set: { status: "inactive" } },
|
|
582
|
+
upsert: false
|
|
583
|
+
}
|
|
584
|
+
);
|
|
585
|
+
|
|
586
|
+
// Update multiple documents
|
|
587
|
+
const result = await client.exec(
|
|
588
|
+
["mongo", "documents", "update"],
|
|
589
|
+
{
|
|
590
|
+
collection: "users",
|
|
591
|
+
filter: { status: "pending" },
|
|
592
|
+
update: { $set: { status: "active" } },
|
|
593
|
+
multi: true
|
|
594
|
+
}
|
|
595
|
+
);
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
**Input:**
|
|
599
|
+
```typescript
|
|
600
|
+
interface UpdateInput {
|
|
601
|
+
collection?: string; // Or metadata.collection
|
|
602
|
+
database?: string; // Or metadata.database
|
|
603
|
+
id?: string; // Exactly one of id and filter
|
|
604
|
+
idType?: "auto" | "objectId" | "string";
|
|
605
|
+
filter?: DocumentQuery;
|
|
606
|
+
update: DocumentUpdate;
|
|
607
|
+
multi?: boolean; // Update all matching documents
|
|
608
|
+
upsert?: boolean; // Insert if not found
|
|
609
|
+
confirm?: boolean; // Required for an empty filter
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
type DocumentUpdate = UpdateFilter<Document>;
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
An upsert by `id` in the "auto" mode updates the document with that ID in either form. When no document matches, the new document gets the ObjectId form of the ID.
|
|
616
|
+
|
|
617
|
+
**Output:**
|
|
618
|
+
```typescript
|
|
619
|
+
interface UpdateOutput {
|
|
620
|
+
acknowledged: boolean;
|
|
621
|
+
matchedCount: number;
|
|
622
|
+
modifiedCount: number;
|
|
623
|
+
upsertedId: string | null;
|
|
624
|
+
upsertedCount: number;
|
|
625
|
+
}
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
##### `mongo.documents.delete`
|
|
629
|
+
|
|
630
|
+
Delete one document by `id`, or the documents that match a `filter`. The rules of `update` apply: exactly one target, no unknown fields, and `confirm: true` for an empty filter.
|
|
631
|
+
|
|
632
|
+
```typescript
|
|
633
|
+
// Delete one document by ID
|
|
634
|
+
const result = await client.exec(
|
|
635
|
+
["mongo", "documents", "delete"],
|
|
636
|
+
{ collection: "users", id: "..." }
|
|
637
|
+
);
|
|
638
|
+
|
|
639
|
+
// Delete multiple documents
|
|
640
|
+
const result = await client.exec(
|
|
641
|
+
["mongo", "documents", "delete"],
|
|
642
|
+
{
|
|
643
|
+
collection: "users",
|
|
644
|
+
filter: { status: "inactive" },
|
|
645
|
+
multi: true
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
**Input:**
|
|
651
|
+
```typescript
|
|
652
|
+
interface DeleteInput {
|
|
653
|
+
collection?: string; // Or metadata.collection
|
|
654
|
+
database?: string; // Or metadata.database
|
|
655
|
+
id?: string; // Exactly one of id and filter
|
|
656
|
+
idType?: "auto" | "objectId" | "string";
|
|
657
|
+
filter?: DocumentQuery;
|
|
658
|
+
multi?: boolean; // Delete all matching documents
|
|
659
|
+
confirm?: boolean; // Required for an empty filter
|
|
660
|
+
}
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
**Output:**
|
|
664
|
+
```typescript
|
|
665
|
+
interface DeleteOutput {
|
|
666
|
+
acknowledged: boolean;
|
|
667
|
+
deletedCount: number;
|
|
668
|
+
}
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
##### `mongo.documents.count`
|
|
672
|
+
|
|
673
|
+
Count documents matching a query.
|
|
674
|
+
|
|
675
|
+
```typescript
|
|
676
|
+
const result = await client.exec(
|
|
677
|
+
["mongo", "documents", "count"],
|
|
678
|
+
{ query: { status: "active" } },
|
|
679
|
+
{ metadata: { collection: "users" } }
|
|
680
|
+
);
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
**Input:**
|
|
684
|
+
```typescript
|
|
685
|
+
interface CountInput {
|
|
686
|
+
query?: DocumentQuery;
|
|
687
|
+
}
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
**Output:**
|
|
691
|
+
```typescript
|
|
692
|
+
interface CountOutput {
|
|
693
|
+
count: number;
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
##### `mongo.documents.aggregate`
|
|
698
|
+
|
|
699
|
+
Execute an aggregation pipeline.
|
|
700
|
+
|
|
701
|
+
```typescript
|
|
702
|
+
const result = await client.exec(
|
|
703
|
+
["mongo", "documents", "aggregate"],
|
|
704
|
+
{
|
|
705
|
+
pipeline: [
|
|
706
|
+
{ $match: { status: "active" } },
|
|
707
|
+
{ $group: { _id: "$country", count: { $sum: 1 } } },
|
|
708
|
+
{ $sort: { count: -1 } }
|
|
709
|
+
],
|
|
710
|
+
options: {
|
|
711
|
+
allowDiskUse: true,
|
|
712
|
+
maxTimeMS: 5000
|
|
713
|
+
}
|
|
714
|
+
},
|
|
715
|
+
{ metadata: { collection: "users" } }
|
|
716
|
+
);
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
**Input:**
|
|
720
|
+
```typescript
|
|
721
|
+
interface AggregateInput {
|
|
722
|
+
pipeline: AggregationStage[];
|
|
723
|
+
options?: AggregationOptions;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
type AggregationStage = Document;
|
|
727
|
+
|
|
728
|
+
interface AggregationOptions {
|
|
729
|
+
allowDiskUse?: boolean;
|
|
730
|
+
maxTimeMS?: number;
|
|
731
|
+
}
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
**Output:**
|
|
735
|
+
```typescript
|
|
736
|
+
interface AggregateOutput {
|
|
737
|
+
results: MongoDocument[];
|
|
738
|
+
}
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
#### Index Procedures
|
|
742
|
+
|
|
743
|
+
##### `mongo.indexes.list`
|
|
744
|
+
|
|
745
|
+
List all indexes on a collection.
|
|
746
|
+
|
|
747
|
+
```typescript
|
|
748
|
+
const result = await client.exec(
|
|
749
|
+
["mongo", "indexes", "list"],
|
|
750
|
+
{},
|
|
751
|
+
{ metadata: { collection: "users" } }
|
|
752
|
+
);
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
**Input:**
|
|
756
|
+
```typescript
|
|
757
|
+
interface ListIndexesInput {
|
|
758
|
+
// Collection from metadata
|
|
759
|
+
}
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
**Output:**
|
|
763
|
+
```typescript
|
|
764
|
+
interface ListIndexesOutput {
|
|
765
|
+
indexes: IndexInfo[];
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
interface IndexInfo {
|
|
769
|
+
name: string;
|
|
770
|
+
key: IndexSpec;
|
|
771
|
+
unique?: boolean;
|
|
772
|
+
sparse?: boolean;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
type IndexSpec = Record<string, 1 | -1 | "text" | "2dsphere">;
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
##### `mongo.indexes.create`
|
|
779
|
+
|
|
780
|
+
Create an index on a collection.
|
|
781
|
+
|
|
782
|
+
```typescript
|
|
783
|
+
// Simple index
|
|
784
|
+
const result = await client.exec(
|
|
785
|
+
["mongo", "indexes", "create"],
|
|
786
|
+
{
|
|
787
|
+
keys: { email: 1 },
|
|
788
|
+
options: { unique: true }
|
|
789
|
+
},
|
|
790
|
+
{ metadata: { collection: "users" } }
|
|
791
|
+
);
|
|
792
|
+
|
|
793
|
+
// Compound index
|
|
794
|
+
const result = await client.exec(
|
|
795
|
+
["mongo", "indexes", "create"],
|
|
796
|
+
{
|
|
797
|
+
keys: { status: 1, createdAt: -1 },
|
|
798
|
+
options: { name: "status_created_idx" }
|
|
799
|
+
},
|
|
800
|
+
{ metadata: { collection: "users" } }
|
|
801
|
+
);
|
|
802
|
+
|
|
803
|
+
// Text index
|
|
804
|
+
const result = await client.exec(
|
|
805
|
+
["mongo", "indexes", "create"],
|
|
806
|
+
{
|
|
807
|
+
keys: { title: "text", description: "text" }
|
|
808
|
+
},
|
|
809
|
+
{ metadata: { collection: "articles" } }
|
|
810
|
+
);
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
**Input:**
|
|
814
|
+
```typescript
|
|
815
|
+
interface CreateIndexInput {
|
|
816
|
+
keys: IndexSpec;
|
|
817
|
+
options?: IndexOptions;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
interface IndexOptions {
|
|
821
|
+
name?: string;
|
|
822
|
+
unique?: boolean;
|
|
823
|
+
sparse?: boolean;
|
|
824
|
+
background?: boolean;
|
|
825
|
+
expireAfterSeconds?: number; // TTL index
|
|
826
|
+
}
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
**Output:**
|
|
830
|
+
```typescript
|
|
831
|
+
interface CreateIndexOutput {
|
|
832
|
+
name: string; // Index name
|
|
833
|
+
}
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
##### `mongo.indexes.drop`
|
|
837
|
+
|
|
838
|
+
Drop an index from a collection.
|
|
839
|
+
|
|
840
|
+
```typescript
|
|
841
|
+
const result = await client.exec(
|
|
842
|
+
["mongo", "indexes", "drop"],
|
|
843
|
+
{ name: "email_1" },
|
|
844
|
+
{ metadata: { collection: "users" } }
|
|
845
|
+
);
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
**Input:**
|
|
849
|
+
```typescript
|
|
850
|
+
interface DropIndexInput {
|
|
851
|
+
name: string; // Index name to drop
|
|
852
|
+
}
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
**Output:**
|
|
856
|
+
```typescript
|
|
857
|
+
interface DropIndexOutput {
|
|
858
|
+
dropped: boolean;
|
|
859
|
+
}
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
### Type Definitions
|
|
863
|
+
|
|
864
|
+
#### Core Types
|
|
865
|
+
|
|
866
|
+
```typescript
|
|
867
|
+
// Documents
|
|
868
|
+
type DocumentId = string | ObjectId;
|
|
869
|
+
type BaseDocument = Document;
|
|
870
|
+
type MongoDocument = BaseDocument;
|
|
871
|
+
type DocumentQuery = Filter<Document>;
|
|
872
|
+
type DocumentUpdate = UpdateFilter<Document>;
|
|
873
|
+
|
|
874
|
+
// Metadata
|
|
875
|
+
interface BaseMeta extends Record<string, unknown> {
|
|
876
|
+
database?: string; // Override database name
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
interface CollectionMeta extends BaseMeta {
|
|
880
|
+
collection: string; // Collection name (required)
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// Pagination
|
|
884
|
+
interface PaginationInput {
|
|
885
|
+
page?: number; // Page number (1-indexed)
|
|
886
|
+
limit?: number; // Items per page
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
interface PaginationOutput {
|
|
890
|
+
page: number;
|
|
891
|
+
limit: number;
|
|
892
|
+
total: number;
|
|
893
|
+
totalPages: number;
|
|
894
|
+
hasNext: boolean;
|
|
895
|
+
hasPrev: boolean;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// Sorting
|
|
899
|
+
type SortOrder = 1 | -1;
|
|
900
|
+
type SortSpec = Record<string, SortOrder>;
|
|
901
|
+
|
|
902
|
+
// Indexes
|
|
903
|
+
type IndexSpec = Record<string, 1 | -1 | "text" | "2dsphere">;
|
|
904
|
+
|
|
905
|
+
interface IndexOptions {
|
|
906
|
+
name?: string;
|
|
907
|
+
unique?: boolean;
|
|
908
|
+
sparse?: boolean;
|
|
909
|
+
background?: boolean;
|
|
910
|
+
expireAfterSeconds?: number;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
interface IndexInfo {
|
|
914
|
+
name: string;
|
|
915
|
+
key: IndexSpec;
|
|
916
|
+
unique?: boolean;
|
|
917
|
+
sparse?: boolean;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// Collections
|
|
921
|
+
interface CollectionOptions {
|
|
922
|
+
capped?: boolean;
|
|
923
|
+
size?: number;
|
|
924
|
+
max?: number;
|
|
925
|
+
validator?: Document;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
interface CollectionStats {
|
|
929
|
+
count: number;
|
|
930
|
+
size: number;
|
|
931
|
+
avgObjSize: number;
|
|
932
|
+
storageSize: number;
|
|
933
|
+
nindexes: number;
|
|
934
|
+
totalIndexSize: number;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// Database
|
|
938
|
+
interface DatabaseInfo {
|
|
939
|
+
name: string;
|
|
940
|
+
collections: number;
|
|
941
|
+
views: number;
|
|
942
|
+
sizeOnDisk: number;
|
|
943
|
+
empty: boolean;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// Aggregation
|
|
947
|
+
type AggregationStage = Document;
|
|
948
|
+
|
|
949
|
+
interface AggregationOptions {
|
|
950
|
+
allowDiskUse?: boolean;
|
|
951
|
+
maxTimeMS?: number;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// Bulk Operations
|
|
955
|
+
interface BulkInsertOne {
|
|
956
|
+
insertOne: { document: Document };
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
interface BulkUpdateOne {
|
|
960
|
+
updateOne: {
|
|
961
|
+
filter: DocumentQuery;
|
|
962
|
+
update: DocumentUpdate;
|
|
963
|
+
upsert?: boolean;
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
interface BulkDeleteOne {
|
|
968
|
+
deleteOne: { filter: DocumentQuery };
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
type BulkOperation = BulkInsertOne | BulkUpdateOne | BulkDeleteOne;
|
|
972
|
+
|
|
973
|
+
interface BulkWriteResult {
|
|
974
|
+
acknowledged: boolean;
|
|
975
|
+
insertedCount: number;
|
|
976
|
+
matchedCount: number;
|
|
977
|
+
modifiedCount: number;
|
|
978
|
+
deletedCount: number;
|
|
979
|
+
upsertedCount: number;
|
|
980
|
+
}
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
#### Typed Procedures Interface
|
|
984
|
+
|
|
985
|
+
For compile-time autocomplete, use the `MongoProcedures` type:
|
|
986
|
+
|
|
987
|
+
```typescript
|
|
988
|
+
import type { MongoProcedures } from "@procedures/mongo";
|
|
989
|
+
import { createTypedCaller } from "@procedures/client";
|
|
990
|
+
|
|
991
|
+
const call = createTypedCaller<MongoProcedures>(client.call);
|
|
992
|
+
|
|
993
|
+
// Full autocomplete on path and input!
|
|
994
|
+
const result = await call(
|
|
995
|
+
["mongo", "documents", "find"],
|
|
996
|
+
{ query: { status: "active" } },
|
|
997
|
+
{ metadata: { collection: "users" } }
|
|
998
|
+
);
|
|
999
|
+
// result is typed as FindOutput
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
### Type Guards and Utilities
|
|
1003
|
+
|
|
1004
|
+
```typescript
|
|
1005
|
+
// Check if metadata has collection
|
|
1006
|
+
function hasCollection(metadata: Record<string, unknown>): metadata is CollectionMeta;
|
|
1007
|
+
|
|
1008
|
+
// Get collection metadata, throws if missing
|
|
1009
|
+
function requireCollection(metadata: Record<string, unknown>): CollectionMeta;
|
|
1010
|
+
|
|
1011
|
+
// Get base metadata (database override)
|
|
1012
|
+
function getBaseMeta(metadata: Record<string, unknown>): BaseMeta;
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
## Usage Examples
|
|
1016
|
+
|
|
1017
|
+
### Basic CRUD Operations
|
|
1018
|
+
|
|
1019
|
+
```typescript
|
|
1020
|
+
import { Client, LocalTransport, PROCEDURE_REGISTRY } from "@procedures/client";
|
|
1021
|
+
import { connect } from "@procedures/mongo";
|
|
1022
|
+
|
|
1023
|
+
// Connect to MongoDB
|
|
1024
|
+
await connect({
|
|
1025
|
+
uri: "mongodb://localhost:27017",
|
|
1026
|
+
database: "myapp"
|
|
1027
|
+
});
|
|
1028
|
+
|
|
1029
|
+
const client = new Client(new LocalTransport({ registry: PROCEDURE_REGISTRY }));
|
|
1030
|
+
|
|
1031
|
+
// Create a user
|
|
1032
|
+
const insertResult = await client.exec(
|
|
1033
|
+
["mongo", "documents", "insert"],
|
|
1034
|
+
{
|
|
1035
|
+
documents: {
|
|
1036
|
+
name: "Alice Johnson",
|
|
1037
|
+
email: "alice@example.com",
|
|
1038
|
+
age: 28,
|
|
1039
|
+
status: "active",
|
|
1040
|
+
createdAt: new Date()
|
|
1041
|
+
}
|
|
1042
|
+
},
|
|
1043
|
+
{ metadata: { collection: "users" } }
|
|
1044
|
+
);
|
|
1045
|
+
|
|
1046
|
+
// Find active users
|
|
1047
|
+
const findResult = await client.exec(
|
|
1048
|
+
["mongo", "documents", "find"],
|
|
1049
|
+
{
|
|
1050
|
+
query: { status: "active" },
|
|
1051
|
+
sort: { createdAt: -1 },
|
|
1052
|
+
limit: 10
|
|
1053
|
+
},
|
|
1054
|
+
{ metadata: { collection: "users" } }
|
|
1055
|
+
);
|
|
1056
|
+
|
|
1057
|
+
console.log(findResult.documents);
|
|
1058
|
+
console.log(findResult.pagination);
|
|
1059
|
+
|
|
1060
|
+
// Update a user
|
|
1061
|
+
await client.exec(
|
|
1062
|
+
["mongo", "documents", "update"],
|
|
1063
|
+
{
|
|
1064
|
+
filter: { email: "alice@example.com" },
|
|
1065
|
+
update: { $set: { status: "inactive" } }
|
|
1066
|
+
},
|
|
1067
|
+
{ metadata: { collection: "users" } }
|
|
1068
|
+
);
|
|
1069
|
+
|
|
1070
|
+
// Delete inactive users
|
|
1071
|
+
await client.exec(
|
|
1072
|
+
["mongo", "documents", "delete"],
|
|
1073
|
+
{
|
|
1074
|
+
filter: { status: "inactive" },
|
|
1075
|
+
multi: true
|
|
1076
|
+
},
|
|
1077
|
+
{ metadata: { collection: "users" } }
|
|
1078
|
+
);
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
### Aggregation Pipeline
|
|
1082
|
+
|
|
1083
|
+
```typescript
|
|
1084
|
+
// Group users by country and count
|
|
1085
|
+
const result = await client.exec(
|
|
1086
|
+
["mongo", "documents", "aggregate"],
|
|
1087
|
+
{
|
|
1088
|
+
pipeline: [
|
|
1089
|
+
{ $match: { status: "active" } },
|
|
1090
|
+
{ $group: {
|
|
1091
|
+
_id: "$country",
|
|
1092
|
+
count: { $sum: 1 },
|
|
1093
|
+
avgAge: { $avg: "$age" }
|
|
1094
|
+
}
|
|
1095
|
+
},
|
|
1096
|
+
{ $sort: { count: -1 } },
|
|
1097
|
+
{ $limit: 10 }
|
|
1098
|
+
]
|
|
1099
|
+
},
|
|
1100
|
+
{ metadata: { collection: "users" } }
|
|
1101
|
+
);
|
|
1102
|
+
|
|
1103
|
+
console.log(result.results);
|
|
1104
|
+
```
|
|
1105
|
+
|
|
1106
|
+
### Index Management
|
|
1107
|
+
|
|
1108
|
+
```typescript
|
|
1109
|
+
// Create unique email index
|
|
1110
|
+
await client.exec(
|
|
1111
|
+
["mongo", "indexes", "create"],
|
|
1112
|
+
{
|
|
1113
|
+
keys: { email: 1 },
|
|
1114
|
+
options: { unique: true, name: "email_unique_idx" }
|
|
1115
|
+
},
|
|
1116
|
+
{ metadata: { collection: "users" } }
|
|
1117
|
+
);
|
|
1118
|
+
|
|
1119
|
+
// Create compound index
|
|
1120
|
+
await client.exec(
|
|
1121
|
+
["mongo", "indexes", "create"],
|
|
1122
|
+
{
|
|
1123
|
+
keys: { status: 1, createdAt: -1 },
|
|
1124
|
+
options: { name: "status_created_idx" }
|
|
1125
|
+
},
|
|
1126
|
+
{ metadata: { collection: "users" } }
|
|
1127
|
+
);
|
|
1128
|
+
|
|
1129
|
+
// List all indexes
|
|
1130
|
+
const indexes = await client.exec(
|
|
1131
|
+
["mongo", "indexes", "list"],
|
|
1132
|
+
{},
|
|
1133
|
+
{ metadata: { collection: "users" } }
|
|
1134
|
+
);
|
|
1135
|
+
|
|
1136
|
+
console.log(indexes.indexes);
|
|
1137
|
+
|
|
1138
|
+
// Drop an index
|
|
1139
|
+
await client.exec(
|
|
1140
|
+
["mongo", "indexes", "drop"],
|
|
1141
|
+
{ name: "status_created_idx" },
|
|
1142
|
+
{ metadata: { collection: "users" } }
|
|
1143
|
+
);
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
### Collection Management
|
|
1147
|
+
|
|
1148
|
+
```typescript
|
|
1149
|
+
// Create capped collection for logs
|
|
1150
|
+
await client.exec(
|
|
1151
|
+
["mongo", "collections", "create"],
|
|
1152
|
+
{
|
|
1153
|
+
name: "logs",
|
|
1154
|
+
options: {
|
|
1155
|
+
capped: true,
|
|
1156
|
+
size: 10485760, // 10MB
|
|
1157
|
+
max: 1000
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
);
|
|
1161
|
+
|
|
1162
|
+
// List all collections
|
|
1163
|
+
const collections = await client.exec(
|
|
1164
|
+
["mongo", "collections", "list"],
|
|
1165
|
+
{ filter: "user" } // Filter collections containing "user"
|
|
1166
|
+
);
|
|
1167
|
+
|
|
1168
|
+
console.log(collections.collections);
|
|
1169
|
+
|
|
1170
|
+
// Get collection stats
|
|
1171
|
+
const stats = await client.exec(
|
|
1172
|
+
["mongo", "collections", "stats"],
|
|
1173
|
+
{},
|
|
1174
|
+
{ metadata: { collection: "users" } }
|
|
1175
|
+
);
|
|
1176
|
+
|
|
1177
|
+
console.log(stats);
|
|
1178
|
+
```
|
|
1179
|
+
|
|
1180
|
+
### Direct Usage (Without RPC)
|
|
1181
|
+
|
|
1182
|
+
```typescript
|
|
1183
|
+
import {
|
|
1184
|
+
connect,
|
|
1185
|
+
findProcedure,
|
|
1186
|
+
insertProcedure,
|
|
1187
|
+
requireCollection
|
|
1188
|
+
} from "@procedures/mongo";
|
|
1189
|
+
|
|
1190
|
+
await connect({ database: "myapp" });
|
|
1191
|
+
|
|
1192
|
+
// Use procedures directly
|
|
1193
|
+
const findResult = await findProcedure.handler(
|
|
1194
|
+
{ query: { status: "active" }, limit: 10 },
|
|
1195
|
+
{ metadata: { collection: "users" } }
|
|
1196
|
+
);
|
|
1197
|
+
|
|
1198
|
+
const insertResult = await insertProcedure.handler(
|
|
1199
|
+
{ documents: { name: "Bob", email: "bob@example.com" } },
|
|
1200
|
+
{ metadata: { collection: "users" } }
|
|
1201
|
+
);
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
### Multi-Database Support
|
|
1205
|
+
|
|
1206
|
+
```typescript
|
|
1207
|
+
// Default database
|
|
1208
|
+
await client.exec(
|
|
1209
|
+
["mongo", "documents", "find"],
|
|
1210
|
+
{ query: {} },
|
|
1211
|
+
{ metadata: { collection: "users" } }
|
|
1212
|
+
);
|
|
1213
|
+
|
|
1214
|
+
// Override database in metadata
|
|
1215
|
+
await client.exec(
|
|
1216
|
+
["mongo", "documents", "find"],
|
|
1217
|
+
{ query: {} },
|
|
1218
|
+
{ metadata: { database: "analytics", collection: "events" } }
|
|
1219
|
+
);
|
|
1220
|
+
```
|
|
1221
|
+
|
|
1222
|
+
## Integration with Ecosystem
|
|
1223
|
+
|
|
1224
|
+
### Bundle Packages
|
|
1225
|
+
|
|
1226
|
+
`client-mongo` can be included in bundle packages:
|
|
1227
|
+
|
|
1228
|
+
```typescript
|
|
1229
|
+
// In bundle-data/src/register.ts
|
|
1230
|
+
import "@procedures/mongo"; // registers its procedures
|
|
1231
|
+
import "@procedures/sqlite"; // registers its procedures
|
|
1232
|
+
import "@procedures/s3/register.js";
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
### Type-Safe Calling
|
|
1236
|
+
|
|
1237
|
+
```typescript
|
|
1238
|
+
import type { MongoProcedures } from "@procedures/mongo";
|
|
1239
|
+
|
|
1240
|
+
type AllProcedures = MongoProcedures & OtherProcedures;
|
|
1241
|
+
|
|
1242
|
+
const call = createTypedCaller<AllProcedures>(client.call);
|
|
1243
|
+
```
|
|
1244
|
+
|
|
1245
|
+
## Dependencies
|
|
1246
|
+
|
|
1247
|
+
### Runtime Dependencies
|
|
1248
|
+
|
|
1249
|
+
- **@procedures/client** - Core client procedure system
|
|
1250
|
+
- **mongodb** (^7.0.0) - Official MongoDB Node.js driver
|
|
1251
|
+
|
|
1252
|
+
### Development Dependencies
|
|
1253
|
+
|
|
1254
|
+
- **@mark1russell7/cue** - Configuration and type utilities
|
|
1255
|
+
- **typescript** (^5.9.3) - TypeScript compiler
|
|
1256
|
+
- **@types/node** (^22.0.0) - Node.js type definitions
|
|
1257
|
+
|
|
1258
|
+
## Package Structure
|
|
1259
|
+
|
|
1260
|
+
```
|
|
1261
|
+
client-mongo/
|
|
1262
|
+
├── src/
|
|
1263
|
+
│ ├── connection.ts # Connection management
|
|
1264
|
+
│ ├── types.ts # Core type definitions
|
|
1265
|
+
│ ├── procedures.types.ts # Typed procedures interface
|
|
1266
|
+
│ ├── register.ts # Auto-registration
|
|
1267
|
+
│ ├── index.ts # Main entry point
|
|
1268
|
+
│ ├── procedures/
|
|
1269
|
+
│ │ ├── schema.ts # Minimal schema helpers
|
|
1270
|
+
│ │ ├── index.ts # Procedure barrel export
|
|
1271
|
+
│ │ ├── database.ping.ts
|
|
1272
|
+
│ │ ├── database.info.ts
|
|
1273
|
+
│ │ ├── collections.list.ts
|
|
1274
|
+
│ │ ├── collections.create.ts
|
|
1275
|
+
│ │ ├── collections.drop.ts
|
|
1276
|
+
│ │ ├── collections.stats.ts
|
|
1277
|
+
│ │ ├── documents.find.ts
|
|
1278
|
+
│ │ ├── documents.get.ts
|
|
1279
|
+
│ │ ├── documents.insert.ts
|
|
1280
|
+
│ │ ├── documents.update.ts
|
|
1281
|
+
│ │ ├── documents.delete.ts
|
|
1282
|
+
│ │ ├── documents.count.ts
|
|
1283
|
+
│ │ ├── documents.aggregate.ts
|
|
1284
|
+
│ │ ├── indexes.list.ts
|
|
1285
|
+
│ │ ├── indexes.create.ts
|
|
1286
|
+
│ │ └── indexes.drop.ts
|
|
1287
|
+
├── dist/ # Compiled output
|
|
1288
|
+
├── package.json
|
|
1289
|
+
├── tsconfig.json
|
|
1290
|
+
└── README.md
|
|
1291
|
+
```
|
|
1292
|
+
|
|
1293
|
+
## Development
|
|
1294
|
+
|
|
1295
|
+
### Build
|
|
1296
|
+
|
|
1297
|
+
```bash
|
|
1298
|
+
npm run build
|
|
1299
|
+
```
|
|
1300
|
+
|
|
1301
|
+
### Type Check
|
|
1302
|
+
|
|
1303
|
+
```bash
|
|
1304
|
+
npm run typecheck
|
|
1305
|
+
```
|
|
1306
|
+
|
|
1307
|
+
### Clean
|
|
1308
|
+
|
|
1309
|
+
```bash
|
|
1310
|
+
npm run clean
|
|
1311
|
+
```
|
|
1312
|
+
|
|
1313
|
+
## License
|
|
1314
|
+
|
|
1315
|
+
MIT
|
|
1316
|
+
|
|
1317
|
+
## Author
|
|
1318
|
+
|
|
1319
|
+
Mark Russell <marktheprogrammer17@gmail.com>
|
|
1320
|
+
|
|
1321
|
+
## Repository
|
|
1322
|
+
|
|
1323
|
+
https://github.com/mark1russell7/client-mongo
|