@procedures/mongo 0.0.0-stage → 0.2.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 +26 -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 +26 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +66 -0
- package/dist/module.js.map +1 -0
- package/dist/procedures/collections.create.d.ts +21 -0
- package/dist/procedures/collections.create.d.ts.map +1 -0
- package/dist/procedures/collections.create.js +46 -0
- package/dist/procedures/collections.create.js.map +1 -0
- package/dist/procedures/collections.drop.d.ts +20 -0
- package/dist/procedures/collections.drop.d.ts.map +1 -0
- package/dist/procedures/collections.drop.js +40 -0
- package/dist/procedures/collections.drop.js.map +1 -0
- package/dist/procedures/collections.list.d.ts +17 -0
- package/dist/procedures/collections.list.d.ts.map +1 -0
- package/dist/procedures/collections.list.js +34 -0
- package/dist/procedures/collections.list.js.map +1 -0
- package/dist/procedures/collections.stats.d.ts +16 -0
- package/dist/procedures/collections.stats.d.ts.map +1 -0
- package/dist/procedures/collections.stats.js +41 -0
- package/dist/procedures/collections.stats.js.map +1 -0
- package/dist/procedures/database.info.d.ts +16 -0
- package/dist/procedures/database.info.d.ts.map +1 -0
- package/dist/procedures/database.info.js +41 -0
- package/dist/procedures/database.info.js.map +1 -0
- package/dist/procedures/database.ping.d.ts +18 -0
- package/dist/procedures/database.ping.d.ts.map +1 -0
- package/dist/procedures/database.ping.js +34 -0
- package/dist/procedures/database.ping.js.map +1 -0
- package/dist/procedures/documents.aggregate.d.ts +20 -0
- package/dist/procedures/documents.aggregate.d.ts.map +1 -0
- package/dist/procedures/documents.aggregate.js +43 -0
- package/dist/procedures/documents.aggregate.js.map +1 -0
- package/dist/procedures/documents.count.d.ts +19 -0
- package/dist/procedures/documents.count.d.ts.map +1 -0
- package/dist/procedures/documents.count.js +32 -0
- package/dist/procedures/documents.count.js.map +1 -0
- package/dist/procedures/documents.delete.d.ts +18 -0
- package/dist/procedures/documents.delete.d.ts.map +1 -0
- package/dist/procedures/documents.delete.js +34 -0
- package/dist/procedures/documents.delete.js.map +1 -0
- package/dist/procedures/documents.find.d.ts +24 -0
- package/dist/procedures/documents.find.d.ts.map +1 -0
- package/dist/procedures/documents.find.js +106 -0
- package/dist/procedures/documents.find.js.map +1 -0
- package/dist/procedures/documents.get.d.ts +21 -0
- package/dist/procedures/documents.get.d.ts.map +1 -0
- package/dist/procedures/documents.get.js +57 -0
- package/dist/procedures/documents.get.js.map +1 -0
- package/dist/procedures/documents.insert.d.ts +22 -0
- package/dist/procedures/documents.insert.d.ts.map +1 -0
- package/dist/procedures/documents.insert.js +58 -0
- package/dist/procedures/documents.insert.js.map +1 -0
- package/dist/procedures/documents.update.d.ts +27 -0
- package/dist/procedures/documents.update.d.ts.map +1 -0
- package/dist/procedures/documents.update.js +64 -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 +21 -0
- package/dist/procedures/indexes.create.d.ts.map +1 -0
- package/dist/procedures/indexes.create.js +48 -0
- package/dist/procedures/indexes.create.js.map +1 -0
- package/dist/procedures/indexes.drop.d.ts +18 -0
- package/dist/procedures/indexes.drop.d.ts.map +1 -0
- package/dist/procedures/indexes.drop.js +33 -0
- package/dist/procedures/indexes.drop.js.map +1 -0
- package/dist/procedures/indexes.list.d.ts +18 -0
- package/dist/procedures/indexes.list.d.ts.map +1 -0
- package/dist/procedures/indexes.list.js +43 -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 +7 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +9 -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 +84 -3
- package/src/connection.ts +198 -0
- package/src/index.ts +159 -0
- package/src/module.ts +71 -0
- package/src/procedures/collections.create.ts +72 -0
- package/src/procedures/collections.drop.ts +66 -0
- package/src/procedures/collections.list.ts +56 -0
- package/src/procedures/collections.stats.ts +60 -0
- package/src/procedures/database.info.ts +61 -0
- package/src/procedures/database.ping.ts +57 -0
- package/src/procedures/documents.aggregate.ts +72 -0
- package/src/procedures/documents.count.ts +55 -0
- package/src/procedures/documents.delete.ts +57 -0
- package/src/procedures/documents.find.ts +151 -0
- package/src/procedures/documents.get.ts +102 -0
- package/src/procedures/documents.insert.ts +86 -0
- package/src/procedures/documents.update.ts +96 -0
- package/src/procedures/index.ts +30 -0
- package/src/procedures/indexes.create.ts +74 -0
- package/src/procedures/indexes.drop.ts +56 -0
- package/src/procedures/indexes.list.ts +67 -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 +11 -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/src/index.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @procedures/mongo
|
|
3
|
+
*
|
|
4
|
+
* MongoDB client wrapper with client procedures for RPC access.
|
|
5
|
+
* Use locally with direct MongoDB connection or remotely via client.call().
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // Local usage: the first call connects (MONGODB_URI, or configure())
|
|
10
|
+
* import { configure } from "@procedures/mongo";
|
|
11
|
+
*
|
|
12
|
+
* configure({ uri: "mongodb://localhost:27017", database: "myapp" });
|
|
13
|
+
*
|
|
14
|
+
* // Via RPC client
|
|
15
|
+
* import { Client } from "client";
|
|
16
|
+
*
|
|
17
|
+
* const result = await client.call(
|
|
18
|
+
* ["mongo", "documents", "find"],
|
|
19
|
+
* { collection: "users", query: { status: "active" }, limit: 10 },
|
|
20
|
+
* );
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// =============================================================================
|
|
25
|
+
// Connection Management
|
|
26
|
+
// =============================================================================
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
connect,
|
|
30
|
+
configure,
|
|
31
|
+
ensureConnection,
|
|
32
|
+
disconnect,
|
|
33
|
+
getDb,
|
|
34
|
+
getClient,
|
|
35
|
+
getDefaultConnection,
|
|
36
|
+
setDefaultConnection,
|
|
37
|
+
hasDefaultConnection,
|
|
38
|
+
} from "./connection.js";
|
|
39
|
+
|
|
40
|
+
export type { MongoConnection, MongoConnectionOptions } from "./connection.js";
|
|
41
|
+
export type { ScopeInput } from "./scope.js";
|
|
42
|
+
|
|
43
|
+
// =============================================================================
|
|
44
|
+
// Types
|
|
45
|
+
// =============================================================================
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
// Type guards
|
|
49
|
+
hasCollection,
|
|
50
|
+
requireCollection,
|
|
51
|
+
getBaseMeta,
|
|
52
|
+
} from "./types.js";
|
|
53
|
+
|
|
54
|
+
// Typed procedures interface for autocomplete
|
|
55
|
+
export type {
|
|
56
|
+
MongoProcedures,
|
|
57
|
+
ProcedureInput,
|
|
58
|
+
ProcedureOutput,
|
|
59
|
+
// Individual procedure types
|
|
60
|
+
PingInput,
|
|
61
|
+
PingOutput,
|
|
62
|
+
InfoInput,
|
|
63
|
+
ListCollectionsInput,
|
|
64
|
+
ListCollectionsOutput,
|
|
65
|
+
CreateCollectionInput,
|
|
66
|
+
CreateCollectionOutput,
|
|
67
|
+
DropCollectionInput,
|
|
68
|
+
DropCollectionOutput,
|
|
69
|
+
StatsInput,
|
|
70
|
+
FindInput,
|
|
71
|
+
FindOutput,
|
|
72
|
+
GetInput,
|
|
73
|
+
GetOutput,
|
|
74
|
+
InsertInput,
|
|
75
|
+
InsertOutput,
|
|
76
|
+
UpdateInput,
|
|
77
|
+
UpdateOutput,
|
|
78
|
+
DeleteInput,
|
|
79
|
+
DeleteOutput,
|
|
80
|
+
CountInput,
|
|
81
|
+
CountOutput,
|
|
82
|
+
AggregateInput,
|
|
83
|
+
AggregateOutput,
|
|
84
|
+
ListIndexesInput,
|
|
85
|
+
ListIndexesOutput,
|
|
86
|
+
CreateIndexInput,
|
|
87
|
+
CreateIndexOutput,
|
|
88
|
+
DropIndexInput,
|
|
89
|
+
DropIndexOutput,
|
|
90
|
+
} from "./procedures.types.js";
|
|
91
|
+
|
|
92
|
+
export type {
|
|
93
|
+
// Common
|
|
94
|
+
PaginationInput,
|
|
95
|
+
PaginationOutput,
|
|
96
|
+
SortOrder,
|
|
97
|
+
SortSpec,
|
|
98
|
+
// Documents
|
|
99
|
+
DocumentId,
|
|
100
|
+
BaseDocument,
|
|
101
|
+
MongoDocument,
|
|
102
|
+
DocumentQuery,
|
|
103
|
+
DocumentUpdate,
|
|
104
|
+
// Metadata
|
|
105
|
+
BaseMeta,
|
|
106
|
+
CollectionMeta,
|
|
107
|
+
// Bulk operations
|
|
108
|
+
BulkInsertOne,
|
|
109
|
+
BulkUpdateOne,
|
|
110
|
+
BulkDeleteOne,
|
|
111
|
+
BulkOperation,
|
|
112
|
+
BulkWriteResult,
|
|
113
|
+
// Indexes
|
|
114
|
+
IndexSpec,
|
|
115
|
+
IndexOptions,
|
|
116
|
+
IndexInfo,
|
|
117
|
+
// Collections
|
|
118
|
+
CollectionOptions,
|
|
119
|
+
CollectionStats,
|
|
120
|
+
// Database
|
|
121
|
+
DatabaseInfo,
|
|
122
|
+
// Aggregation
|
|
123
|
+
AggregationStage,
|
|
124
|
+
AggregationOptions,
|
|
125
|
+
} from "./types.js";
|
|
126
|
+
|
|
127
|
+
// =============================================================================
|
|
128
|
+
// Storage (CollectionStorage implementation)
|
|
129
|
+
// =============================================================================
|
|
130
|
+
|
|
131
|
+
export { MongoStorage } from "./storage/index.js";
|
|
132
|
+
export type { MongoStorageOptions } from "./storage/index.js";
|
|
133
|
+
|
|
134
|
+
// =============================================================================
|
|
135
|
+
// Procedure Registration
|
|
136
|
+
// =============================================================================
|
|
137
|
+
|
|
138
|
+
export { registerMongoProcedures, procedures } from "./module.js";
|
|
139
|
+
|
|
140
|
+
// =============================================================================
|
|
141
|
+
// Individual Procedures (for direct import if needed)
|
|
142
|
+
// =============================================================================
|
|
143
|
+
|
|
144
|
+
export * from "./procedures/index.js";
|
|
145
|
+
|
|
146
|
+
// =============================================================================
|
|
147
|
+
// Re-export mongodb types users may need
|
|
148
|
+
// =============================================================================
|
|
149
|
+
|
|
150
|
+
export type {
|
|
151
|
+
Db,
|
|
152
|
+
Collection,
|
|
153
|
+
Document,
|
|
154
|
+
ObjectId,
|
|
155
|
+
Filter,
|
|
156
|
+
UpdateFilter,
|
|
157
|
+
FindOptions,
|
|
158
|
+
AggregateOptions,
|
|
159
|
+
} from "mongodb";
|
package/src/module.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module (no side effects): the procedures of this package as data, for `createRegistry()`.
|
|
3
|
+
*
|
|
4
|
+
* Procedure Registration
|
|
5
|
+
*
|
|
6
|
+
* Registers MongoDB procedures with the client system.
|
|
7
|
+
* This file is referenced by package.json's client.procedures field.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { type AnyProcedure, defineModule, type ProcedureModule, PROCEDURE_REGISTRY, registerModules, type ProcedureRegistry } from "@procedures/client";
|
|
11
|
+
|
|
12
|
+
// Import all procedures
|
|
13
|
+
import { pingProcedure } from "./procedures/database.ping.js";
|
|
14
|
+
import { infoProcedure } from "./procedures/database.info.js";
|
|
15
|
+
import { listProcedure } from "./procedures/collections.list.js";
|
|
16
|
+
import { createCollectionProcedure } from "./procedures/collections.create.js";
|
|
17
|
+
import { dropProcedure } from "./procedures/collections.drop.js";
|
|
18
|
+
import { statsProcedure } from "./procedures/collections.stats.js";
|
|
19
|
+
import { findProcedure } from "./procedures/documents.find.js";
|
|
20
|
+
import { getProcedure } from "./procedures/documents.get.js";
|
|
21
|
+
import { insertProcedure } from "./procedures/documents.insert.js";
|
|
22
|
+
import { updateProcedure } from "./procedures/documents.update.js";
|
|
23
|
+
import { deleteProcedure } from "./procedures/documents.delete.js";
|
|
24
|
+
import { countProcedure } from "./procedures/documents.count.js";
|
|
25
|
+
import { aggregateProcedure } from "./procedures/documents.aggregate.js";
|
|
26
|
+
import { listIndexesProcedure } from "./procedures/indexes.list.js";
|
|
27
|
+
import { createIndexProcedure } from "./procedures/indexes.create.js";
|
|
28
|
+
import { dropIndexProcedure } from "./procedures/indexes.drop.js";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* All MongoDB procedures
|
|
32
|
+
*/
|
|
33
|
+
export const procedures: readonly AnyProcedure[] = [
|
|
34
|
+
// Database
|
|
35
|
+
pingProcedure,
|
|
36
|
+
infoProcedure,
|
|
37
|
+
// Collections
|
|
38
|
+
listProcedure,
|
|
39
|
+
createCollectionProcedure,
|
|
40
|
+
dropProcedure,
|
|
41
|
+
statsProcedure,
|
|
42
|
+
// Documents
|
|
43
|
+
findProcedure,
|
|
44
|
+
getProcedure,
|
|
45
|
+
insertProcedure,
|
|
46
|
+
updateProcedure,
|
|
47
|
+
deleteProcedure,
|
|
48
|
+
countProcedure,
|
|
49
|
+
aggregateProcedure,
|
|
50
|
+
// Indexes
|
|
51
|
+
listIndexesProcedure,
|
|
52
|
+
createIndexProcedure,
|
|
53
|
+
dropIndexProcedure,
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The module of this package, for `createRegistry()`: its procedures as data. Importing this
|
|
58
|
+
* file registers nothing. (`register.ts` registers the same procedures in the global registry.)
|
|
59
|
+
*/
|
|
60
|
+
export const mongoModule: ProcedureModule = defineModule("@procedures/mongo", [...procedures]);
|
|
61
|
+
|
|
62
|
+
export default mongoModule;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* This function registers the procedures of @procedures/mongo, and of the modules that it requires, in
|
|
66
|
+
* a registry. The default is the global registry. Importing this file registers nothing: the
|
|
67
|
+
* `./register` entry starts this function (ARCHITECTURE-PROPOSALS-2026-10, P9).
|
|
68
|
+
*/
|
|
69
|
+
export function registerMongoProcedures(registry: ProcedureRegistry = PROCEDURE_REGISTRY): void {
|
|
70
|
+
registerModules(registry, [mongoModule]);
|
|
71
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Procedure: mongo.collections.create
|
|
3
|
+
* Create a new collection
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createProcedure, zodAdapter, type Effects, type Procedure, type ProcedureContext } from "@procedures/client";
|
|
7
|
+
import { databaseFor, type ScopeInput } from "../scope.js";
|
|
8
|
+
import { scopeFields, documentObject } from "./input-schemas.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import type { CreateCollectionOptions } from "mongodb";
|
|
11
|
+
import { type CollectionOptions } from "../types.js";
|
|
12
|
+
|
|
13
|
+
// Input/Output types
|
|
14
|
+
interface CreateInput extends ScopeInput {
|
|
15
|
+
name: string;
|
|
16
|
+
options?: CollectionOptions | undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface CreateOutput {
|
|
20
|
+
acknowledged: boolean;
|
|
21
|
+
collectionName: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Schemas
|
|
25
|
+
const createInputSchema = zodAdapter<CreateInput>(
|
|
26
|
+
z.object({
|
|
27
|
+
...scopeFields(),
|
|
28
|
+
name: z.string().min(1).describe("The name of the new collection"),
|
|
29
|
+
options: z
|
|
30
|
+
.looseObject({
|
|
31
|
+
capped: z.boolean().optional().describe("Make a capped collection"),
|
|
32
|
+
size: z.number().optional().describe("The maximum size in bytes (capped collections)"),
|
|
33
|
+
max: z.number().optional().describe("The maximum number of documents (capped collections)"),
|
|
34
|
+
validator: documentObject().optional().describe("A validator document (for example a $jsonSchema)"),
|
|
35
|
+
})
|
|
36
|
+
.optional()
|
|
37
|
+
.describe("The options of the collection"),
|
|
38
|
+
})
|
|
39
|
+
);
|
|
40
|
+
const createOutputSchema = zodAdapter<CreateOutput>(
|
|
41
|
+
z.looseObject({
|
|
42
|
+
acknowledged: z.boolean().describe("True when the server confirmed the write"),
|
|
43
|
+
collectionName: z.string().describe("The name of the new collection"),
|
|
44
|
+
})
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
export const createCollectionProcedure: Procedure<
|
|
48
|
+
CreateInput,
|
|
49
|
+
CreateOutput,
|
|
50
|
+
{ description: string; effects?: Effects }
|
|
51
|
+
> = createProcedure()
|
|
52
|
+
.path(["mongo", "collections", "create"])
|
|
53
|
+
.input(createInputSchema)
|
|
54
|
+
.output(createOutputSchema)
|
|
55
|
+
.meta({
|
|
56
|
+
description: "Create a new collection",
|
|
57
|
+
effects: { reads: ["mongo", "network"], writes: ["mongo", "network"], destructive: false },
|
|
58
|
+
})
|
|
59
|
+
.handler(async (input: CreateInput, ctx: ProcedureContext) => {
|
|
60
|
+
const db = await databaseFor(input, ctx);
|
|
61
|
+
|
|
62
|
+
// The schema leaves out an option that the input does not give: no option is undefined at run time
|
|
63
|
+
await db.createCollection(input.name, input.options as CreateCollectionOptions | undefined);
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
acknowledged: true,
|
|
67
|
+
collectionName: input.name,
|
|
68
|
+
};
|
|
69
|
+
})
|
|
70
|
+
.build();
|
|
71
|
+
|
|
72
|
+
export type { CreateInput, CreateOutput };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Procedure: mongo.collections.drop
|
|
3
|
+
* Drop (delete) a collection
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createProcedure, zodAdapter, type Effects, type Procedure, type ProcedureContext } from "@procedures/client";
|
|
7
|
+
import { collectionName, databaseFor, type ScopeInput } from "../scope.js";
|
|
8
|
+
import { scopeFields } from "./input-schemas.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
|
|
11
|
+
// Input/Output types
|
|
12
|
+
interface DropInput extends ScopeInput {
|
|
13
|
+
/** Confirmation required to prevent accidental drops */
|
|
14
|
+
confirm: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface DropOutput {
|
|
18
|
+
acknowledged: boolean;
|
|
19
|
+
dropped: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Schemas
|
|
23
|
+
const dropInputSchema = zodAdapter<DropInput>(
|
|
24
|
+
z.object({
|
|
25
|
+
...scopeFields(),
|
|
26
|
+
confirm: z.boolean().describe("Set to true to drop the collection and all of its documents"),
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
const dropOutputSchema = zodAdapter<DropOutput>(
|
|
30
|
+
z.looseObject({
|
|
31
|
+
acknowledged: z.boolean().describe("True when the server confirmed the write"),
|
|
32
|
+
dropped: z.boolean().describe("False when the collection did not exist"),
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
export const dropProcedure: Procedure<
|
|
37
|
+
DropInput,
|
|
38
|
+
DropOutput,
|
|
39
|
+
{ description: string; effects?: Effects }
|
|
40
|
+
> = createProcedure()
|
|
41
|
+
.path(["mongo", "collections", "drop"])
|
|
42
|
+
.input(dropInputSchema)
|
|
43
|
+
.output(dropOutputSchema)
|
|
44
|
+
.meta({
|
|
45
|
+
description: "Drop (delete) a collection",
|
|
46
|
+
// The drop of a missing collection is not an error: it gives dropped: false
|
|
47
|
+
effects: { reads: ["mongo", "network"], writes: ["mongo", "network"], idempotent: true },
|
|
48
|
+
})
|
|
49
|
+
.handler(async (input: DropInput, ctx: ProcedureContext) => {
|
|
50
|
+
const name = collectionName(input, ctx);
|
|
51
|
+
|
|
52
|
+
if (!input.confirm) {
|
|
53
|
+
throw new Error("confirm must be true to drop a collection");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const db = await databaseFor(input, ctx);
|
|
57
|
+
const dropped = await db.dropCollection(name);
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
acknowledged: true,
|
|
61
|
+
dropped,
|
|
62
|
+
};
|
|
63
|
+
})
|
|
64
|
+
.build();
|
|
65
|
+
|
|
66
|
+
export type { DropInput, DropOutput };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Procedure: mongo.collections.list
|
|
3
|
+
* List all collections in the database
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createProcedure, zodAdapter, type Effects, type Procedure, type ProcedureContext } from "@procedures/client";
|
|
7
|
+
import { databaseFor, type ScopeInput } from "../scope.js";
|
|
8
|
+
import { scopeFields } from "./input-schemas.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
|
|
11
|
+
// Input/Output types
|
|
12
|
+
/** The input: only the scope fields. */
|
|
13
|
+
type ListInput = ScopeInput;
|
|
14
|
+
|
|
15
|
+
interface ListOutput {
|
|
16
|
+
collections: string[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Schemas
|
|
20
|
+
const listInputSchema = zodAdapter<ListInput>(
|
|
21
|
+
z.object({ ...scopeFields() })
|
|
22
|
+
);
|
|
23
|
+
const listOutputSchema = zodAdapter<ListOutput>(
|
|
24
|
+
z.looseObject({
|
|
25
|
+
collections: z.array(z.string()).describe("The collection names of the database"),
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export const listProcedure: Procedure<
|
|
30
|
+
ListInput,
|
|
31
|
+
ListOutput,
|
|
32
|
+
{ description: string; effects?: Effects }
|
|
33
|
+
> = createProcedure()
|
|
34
|
+
.path(["mongo", "collections", "list"])
|
|
35
|
+
.input(listInputSchema)
|
|
36
|
+
.output(listOutputSchema)
|
|
37
|
+
.meta({
|
|
38
|
+
description: "List all collections in the database",
|
|
39
|
+
effects: { reads: ["mongo", "network"], writes: [] },
|
|
40
|
+
})
|
|
41
|
+
.handler(async (input: ListInput, ctx: ProcedureContext) => {
|
|
42
|
+
const db = await databaseFor(input, ctx);
|
|
43
|
+
|
|
44
|
+
const collections = await db.listCollections().toArray();
|
|
45
|
+
const collectionNames = collections
|
|
46
|
+
.filter((c) => c.type === "collection")
|
|
47
|
+
.map((c) => c.name)
|
|
48
|
+
.sort();
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
collections: collectionNames,
|
|
52
|
+
};
|
|
53
|
+
})
|
|
54
|
+
.build();
|
|
55
|
+
|
|
56
|
+
export type { ListInput, ListOutput };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Procedure: mongo.collections.stats
|
|
3
|
+
* Get collection statistics
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createProcedure, zodAdapter, type Effects, type Procedure, type ProcedureContext } from "@procedures/client";
|
|
7
|
+
import { collectionFor, type ScopeInput } from "../scope.js";
|
|
8
|
+
import { scopeFields } from "./input-schemas.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import type { CollectionStats } from "../types.js";
|
|
11
|
+
|
|
12
|
+
// Input/Output types
|
|
13
|
+
/** The input: only the scope fields. */
|
|
14
|
+
type StatsInput = ScopeInput;
|
|
15
|
+
|
|
16
|
+
// Schemas
|
|
17
|
+
const statsInputSchema = zodAdapter<StatsInput>(
|
|
18
|
+
z.object({ ...scopeFields() })
|
|
19
|
+
);
|
|
20
|
+
const statsOutputSchema = zodAdapter<CollectionStats>(
|
|
21
|
+
z.looseObject({
|
|
22
|
+
count: z.number().describe("The number of documents"),
|
|
23
|
+
size: z.number().describe("The size of the documents, in bytes"),
|
|
24
|
+
avgObjSize: z.number().describe("The average size of a document, in bytes"),
|
|
25
|
+
storageSize: z.number().describe("The storage size, in bytes"),
|
|
26
|
+
nindexes: z.number().describe("The number of indexes"),
|
|
27
|
+
totalIndexSize: z.number().describe("The size of the indexes, in bytes"),
|
|
28
|
+
})
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
export const statsProcedure: Procedure<
|
|
32
|
+
StatsInput,
|
|
33
|
+
CollectionStats,
|
|
34
|
+
{ description: string; effects?: Effects }
|
|
35
|
+
> = createProcedure()
|
|
36
|
+
.path(["mongo", "collections", "stats"])
|
|
37
|
+
.input(statsInputSchema)
|
|
38
|
+
.output(statsOutputSchema)
|
|
39
|
+
.meta({
|
|
40
|
+
description: "Get collection statistics",
|
|
41
|
+
effects: { reads: ["mongo", "network"], writes: [] },
|
|
42
|
+
})
|
|
43
|
+
.handler(async (input: StatsInput, ctx: ProcedureContext) => {
|
|
44
|
+
const { db, name } = await collectionFor(input, ctx);
|
|
45
|
+
// Use collStats command since stats() is deprecated
|
|
46
|
+
const stats = await db.command({ collStats: name });
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
count: (stats["count"] as number) ?? 0,
|
|
50
|
+
size: (stats["size"] as number) ?? 0,
|
|
51
|
+
avgObjSize: (stats["avgObjSize"] as number) ?? 0,
|
|
52
|
+
storageSize: (stats["storageSize"] as number) ?? 0,
|
|
53
|
+
nindexes: (stats["nindexes"] as number) ?? 0,
|
|
54
|
+
totalIndexSize: (stats["totalIndexSize"] as number) ?? 0,
|
|
55
|
+
};
|
|
56
|
+
})
|
|
57
|
+
.build();
|
|
58
|
+
|
|
59
|
+
export type { StatsInput };
|
|
60
|
+
export type StatsOutput = CollectionStats;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Procedure: mongo.database.info
|
|
3
|
+
* Get database information and statistics
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createProcedure, zodAdapter, type Effects, type Procedure, type ProcedureContext } from "@procedures/client";
|
|
7
|
+
import { databaseFor, type ScopeInput } from "../scope.js";
|
|
8
|
+
import { scopeFields } from "./input-schemas.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { type DatabaseInfo } from "../types.js";
|
|
11
|
+
|
|
12
|
+
// Input/Output types
|
|
13
|
+
/** The input: only the scope fields. */
|
|
14
|
+
type InfoInput = ScopeInput;
|
|
15
|
+
|
|
16
|
+
// Schemas
|
|
17
|
+
const infoInputSchema = zodAdapter<InfoInput>(
|
|
18
|
+
z.object({ ...scopeFields() })
|
|
19
|
+
);
|
|
20
|
+
const infoOutputSchema = zodAdapter<DatabaseInfo>(
|
|
21
|
+
z.looseObject({
|
|
22
|
+
name: z.string().describe("The database name"),
|
|
23
|
+
collections: z.number().describe("The number of collections (views not counted)"),
|
|
24
|
+
views: z.number().describe("The number of views"),
|
|
25
|
+
sizeOnDisk: z.number().describe("The data size, in bytes"),
|
|
26
|
+
empty: z.boolean().describe("True when the database has no collections"),
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export const infoProcedure: Procedure<
|
|
31
|
+
InfoInput,
|
|
32
|
+
DatabaseInfo,
|
|
33
|
+
{ description: string; effects?: Effects }
|
|
34
|
+
> = createProcedure()
|
|
35
|
+
.path(["mongo", "database", "info"])
|
|
36
|
+
.input(infoInputSchema)
|
|
37
|
+
.output(infoOutputSchema)
|
|
38
|
+
.meta({
|
|
39
|
+
description: "Get database information and statistics",
|
|
40
|
+
effects: { reads: ["mongo", "network"], writes: [] },
|
|
41
|
+
})
|
|
42
|
+
.handler(async (input: InfoInput, ctx: ProcedureContext) => {
|
|
43
|
+
const db = await databaseFor(input, ctx);
|
|
44
|
+
|
|
45
|
+
const stats = await db.stats();
|
|
46
|
+
const collections = await db.listCollections().toArray();
|
|
47
|
+
|
|
48
|
+
const views = collections.filter((c) => c.type === "view").length;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
name: db.databaseName,
|
|
52
|
+
collections: collections.length - views,
|
|
53
|
+
views,
|
|
54
|
+
sizeOnDisk: stats["dataSize"] ?? 0,
|
|
55
|
+
empty: collections.length === 0,
|
|
56
|
+
};
|
|
57
|
+
})
|
|
58
|
+
.build();
|
|
59
|
+
|
|
60
|
+
export type { InfoInput };
|
|
61
|
+
export type InfoOutput = DatabaseInfo;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Procedure: mongo.database.ping
|
|
3
|
+
* Health check and connectivity test
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createProcedure, zodAdapter, type Effects, type Procedure, type ProcedureContext } from "@procedures/client";
|
|
7
|
+
import { databaseFor, type ScopeInput } from "../scope.js";
|
|
8
|
+
import { scopeFields } from "./input-schemas.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
|
|
11
|
+
// Input/Output types
|
|
12
|
+
/** The input: only the scope fields. */
|
|
13
|
+
type PingInput = ScopeInput;
|
|
14
|
+
|
|
15
|
+
interface PingOutput {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
latencyMs: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Schemas
|
|
21
|
+
const pingInputSchema = zodAdapter<PingInput>(
|
|
22
|
+
z.object({ ...scopeFields() })
|
|
23
|
+
);
|
|
24
|
+
const pingOutputSchema = zodAdapter<PingOutput>(
|
|
25
|
+
z.looseObject({
|
|
26
|
+
ok: z.boolean().describe("True when the server answered"),
|
|
27
|
+
latencyMs: z.number().describe("The time of the ping, in milliseconds"),
|
|
28
|
+
})
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
export const pingProcedure: Procedure<
|
|
32
|
+
PingInput,
|
|
33
|
+
PingOutput,
|
|
34
|
+
{ description: string; effects?: Effects }
|
|
35
|
+
> = createProcedure()
|
|
36
|
+
.path(["mongo", "database", "ping"])
|
|
37
|
+
.input(pingInputSchema)
|
|
38
|
+
.output(pingOutputSchema)
|
|
39
|
+
.meta({
|
|
40
|
+
description: "Health check and connectivity test",
|
|
41
|
+
effects: { reads: ["mongo", "network"], writes: [] },
|
|
42
|
+
})
|
|
43
|
+
.handler(async (input: PingInput, ctx: ProcedureContext) => {
|
|
44
|
+
const db = await databaseFor(input, ctx);
|
|
45
|
+
|
|
46
|
+
const start = Date.now();
|
|
47
|
+
await db.command({ ping: 1 });
|
|
48
|
+
const latencyMs = Date.now() - start;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
ok: true,
|
|
52
|
+
latencyMs,
|
|
53
|
+
};
|
|
54
|
+
})
|
|
55
|
+
.build();
|
|
56
|
+
|
|
57
|
+
export type { PingInput, PingOutput };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Procedure: mongo.documents.aggregate
|
|
3
|
+
* Run an aggregation pipeline
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createProcedure, zodAdapter, type Effects, type Procedure, type ProcedureContext } from "@procedures/client";
|
|
7
|
+
import { collectionFor, type ScopeInput } from "../scope.js";
|
|
8
|
+
import { scopeFields, documentObject } from "./input-schemas.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import type { AggregateOptions } from "mongodb";
|
|
11
|
+
import {
|
|
12
|
+
type AggregationStage,
|
|
13
|
+
type AggregationOptions,
|
|
14
|
+
type MongoDocument,
|
|
15
|
+
} from "../types.js";
|
|
16
|
+
|
|
17
|
+
// Input/Output types
|
|
18
|
+
interface AggregateInput extends ScopeInput {
|
|
19
|
+
pipeline: AggregationStage[];
|
|
20
|
+
options?: AggregationOptions | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface AggregateOutput {
|
|
24
|
+
results: MongoDocument[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Schemas
|
|
28
|
+
const aggregateInputSchema = zodAdapter<AggregateInput>(
|
|
29
|
+
z.object({
|
|
30
|
+
...scopeFields(),
|
|
31
|
+
pipeline: z.array(documentObject()).describe("The aggregation stages, in order (for example [{ $match: {...} }, { $group: {...} }])"),
|
|
32
|
+
options: z
|
|
33
|
+
.looseObject({
|
|
34
|
+
allowDiskUse: z.boolean().optional().describe("Allow the use of disk for large stages"),
|
|
35
|
+
maxTimeMS: z.number().optional().describe("The longest run time in milliseconds"),
|
|
36
|
+
})
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("The options of the aggregation"),
|
|
39
|
+
})
|
|
40
|
+
);
|
|
41
|
+
const aggregateOutputSchema = zodAdapter<AggregateOutput>(
|
|
42
|
+
z.looseObject({
|
|
43
|
+
results: z.array(z.record(z.string(), z.unknown())).describe("The documents that the pipeline gave"),
|
|
44
|
+
})
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
export const aggregateProcedure: Procedure<
|
|
48
|
+
AggregateInput,
|
|
49
|
+
AggregateOutput,
|
|
50
|
+
{ description: string; effects?: Effects }
|
|
51
|
+
> = createProcedure()
|
|
52
|
+
.path(["mongo", "documents", "aggregate"])
|
|
53
|
+
.input(aggregateInputSchema)
|
|
54
|
+
.output(aggregateOutputSchema)
|
|
55
|
+
.meta({
|
|
56
|
+
description: "Run an aggregation pipeline",
|
|
57
|
+
// A $out or $merge stage of the pipeline writes to a collection, and $out replaces it
|
|
58
|
+
effects: { reads: ["mongo", "network"], writes: ["mongo", "network"] },
|
|
59
|
+
})
|
|
60
|
+
.handler(async (input: AggregateInput, ctx: ProcedureContext) => {
|
|
61
|
+
const { collection } = await collectionFor(input, ctx);
|
|
62
|
+
|
|
63
|
+
const results = await collection
|
|
64
|
+
// The schema leaves out an option that the input does not give
|
|
65
|
+
.aggregate(input.pipeline, input.options as AggregateOptions | undefined)
|
|
66
|
+
.toArray();
|
|
67
|
+
|
|
68
|
+
return { results };
|
|
69
|
+
})
|
|
70
|
+
.build();
|
|
71
|
+
|
|
72
|
+
export type { AggregateInput, AggregateOutput };
|