@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.
Files changed (150) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1322 -2
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/connection.d.ts +93 -0
  6. package/dist/connection.d.ts.map +1 -0
  7. package/dist/connection.js +147 -0
  8. package/dist/connection.js.map +1 -0
  9. package/dist/index.d.ts +34 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +45 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/module.d.ts +26 -0
  14. package/dist/module.d.ts.map +1 -0
  15. package/dist/module.js +66 -0
  16. package/dist/module.js.map +1 -0
  17. package/dist/procedures/collections.create.d.ts +21 -0
  18. package/dist/procedures/collections.create.d.ts.map +1 -0
  19. package/dist/procedures/collections.create.js +46 -0
  20. package/dist/procedures/collections.create.js.map +1 -0
  21. package/dist/procedures/collections.drop.d.ts +20 -0
  22. package/dist/procedures/collections.drop.d.ts.map +1 -0
  23. package/dist/procedures/collections.drop.js +40 -0
  24. package/dist/procedures/collections.drop.js.map +1 -0
  25. package/dist/procedures/collections.list.d.ts +17 -0
  26. package/dist/procedures/collections.list.d.ts.map +1 -0
  27. package/dist/procedures/collections.list.js +34 -0
  28. package/dist/procedures/collections.list.js.map +1 -0
  29. package/dist/procedures/collections.stats.d.ts +16 -0
  30. package/dist/procedures/collections.stats.d.ts.map +1 -0
  31. package/dist/procedures/collections.stats.js +41 -0
  32. package/dist/procedures/collections.stats.js.map +1 -0
  33. package/dist/procedures/database.info.d.ts +16 -0
  34. package/dist/procedures/database.info.d.ts.map +1 -0
  35. package/dist/procedures/database.info.js +41 -0
  36. package/dist/procedures/database.info.js.map +1 -0
  37. package/dist/procedures/database.ping.d.ts +18 -0
  38. package/dist/procedures/database.ping.d.ts.map +1 -0
  39. package/dist/procedures/database.ping.js +34 -0
  40. package/dist/procedures/database.ping.js.map +1 -0
  41. package/dist/procedures/documents.aggregate.d.ts +20 -0
  42. package/dist/procedures/documents.aggregate.d.ts.map +1 -0
  43. package/dist/procedures/documents.aggregate.js +43 -0
  44. package/dist/procedures/documents.aggregate.js.map +1 -0
  45. package/dist/procedures/documents.count.d.ts +19 -0
  46. package/dist/procedures/documents.count.d.ts.map +1 -0
  47. package/dist/procedures/documents.count.js +32 -0
  48. package/dist/procedures/documents.count.js.map +1 -0
  49. package/dist/procedures/documents.delete.d.ts +18 -0
  50. package/dist/procedures/documents.delete.d.ts.map +1 -0
  51. package/dist/procedures/documents.delete.js +34 -0
  52. package/dist/procedures/documents.delete.js.map +1 -0
  53. package/dist/procedures/documents.find.d.ts +24 -0
  54. package/dist/procedures/documents.find.d.ts.map +1 -0
  55. package/dist/procedures/documents.find.js +106 -0
  56. package/dist/procedures/documents.find.js.map +1 -0
  57. package/dist/procedures/documents.get.d.ts +21 -0
  58. package/dist/procedures/documents.get.d.ts.map +1 -0
  59. package/dist/procedures/documents.get.js +57 -0
  60. package/dist/procedures/documents.get.js.map +1 -0
  61. package/dist/procedures/documents.insert.d.ts +22 -0
  62. package/dist/procedures/documents.insert.d.ts.map +1 -0
  63. package/dist/procedures/documents.insert.js +58 -0
  64. package/dist/procedures/documents.insert.js.map +1 -0
  65. package/dist/procedures/documents.update.d.ts +27 -0
  66. package/dist/procedures/documents.update.d.ts.map +1 -0
  67. package/dist/procedures/documents.update.js +64 -0
  68. package/dist/procedures/documents.update.js.map +1 -0
  69. package/dist/procedures/index.d.ts +21 -0
  70. package/dist/procedures/index.d.ts.map +1 -0
  71. package/dist/procedures/index.js +26 -0
  72. package/dist/procedures/index.js.map +1 -0
  73. package/dist/procedures/indexes.create.d.ts +21 -0
  74. package/dist/procedures/indexes.create.d.ts.map +1 -0
  75. package/dist/procedures/indexes.create.js +48 -0
  76. package/dist/procedures/indexes.create.js.map +1 -0
  77. package/dist/procedures/indexes.drop.d.ts +18 -0
  78. package/dist/procedures/indexes.drop.d.ts.map +1 -0
  79. package/dist/procedures/indexes.drop.js +33 -0
  80. package/dist/procedures/indexes.drop.js.map +1 -0
  81. package/dist/procedures/indexes.list.d.ts +18 -0
  82. package/dist/procedures/indexes.list.d.ts.map +1 -0
  83. package/dist/procedures/indexes.list.js +43 -0
  84. package/dist/procedures/indexes.list.js.map +1 -0
  85. package/dist/procedures/input-schemas.d.ts +45 -0
  86. package/dist/procedures/input-schemas.d.ts.map +1 -0
  87. package/dist/procedures/input-schemas.js +52 -0
  88. package/dist/procedures/input-schemas.js.map +1 -0
  89. package/dist/procedures/schema.d.ts +2 -0
  90. package/dist/procedures/schema.d.ts.map +1 -0
  91. package/dist/procedures/schema.js +2 -0
  92. package/dist/procedures/schema.js.map +1 -0
  93. package/dist/procedures/target.d.ts +44 -0
  94. package/dist/procedures/target.d.ts.map +1 -0
  95. package/dist/procedures/target.js +98 -0
  96. package/dist/procedures/target.js.map +1 -0
  97. package/dist/procedures.types.d.ts +129 -0
  98. package/dist/procedures.types.d.ts.map +1 -0
  99. package/dist/procedures.types.js +24 -0
  100. package/dist/procedures.types.js.map +1 -0
  101. package/dist/register.d.ts +7 -0
  102. package/dist/register.d.ts.map +1 -0
  103. package/dist/register.js +9 -0
  104. package/dist/register.js.map +1 -0
  105. package/dist/scope.d.ts +33 -0
  106. package/dist/scope.d.ts.map +1 -0
  107. package/dist/scope.js +52 -0
  108. package/dist/scope.js.map +1 -0
  109. package/dist/storage/index.d.ts +6 -0
  110. package/dist/storage/index.d.ts.map +1 -0
  111. package/dist/storage/index.js +5 -0
  112. package/dist/storage/index.js.map +1 -0
  113. package/dist/storage/mongo-storage.d.ts +50 -0
  114. package/dist/storage/mongo-storage.d.ts.map +1 -0
  115. package/dist/storage/mongo-storage.js +109 -0
  116. package/dist/storage/mongo-storage.js.map +1 -0
  117. package/dist/types.d.ts +239 -0
  118. package/dist/types.d.ts.map +1 -0
  119. package/dist/types.js +58 -0
  120. package/dist/types.js.map +1 -0
  121. package/package.json +84 -3
  122. package/src/connection.ts +198 -0
  123. package/src/index.ts +159 -0
  124. package/src/module.ts +71 -0
  125. package/src/procedures/collections.create.ts +72 -0
  126. package/src/procedures/collections.drop.ts +66 -0
  127. package/src/procedures/collections.list.ts +56 -0
  128. package/src/procedures/collections.stats.ts +60 -0
  129. package/src/procedures/database.info.ts +61 -0
  130. package/src/procedures/database.ping.ts +57 -0
  131. package/src/procedures/documents.aggregate.ts +72 -0
  132. package/src/procedures/documents.count.ts +55 -0
  133. package/src/procedures/documents.delete.ts +57 -0
  134. package/src/procedures/documents.find.ts +151 -0
  135. package/src/procedures/documents.get.ts +102 -0
  136. package/src/procedures/documents.insert.ts +86 -0
  137. package/src/procedures/documents.update.ts +96 -0
  138. package/src/procedures/index.ts +30 -0
  139. package/src/procedures/indexes.create.ts +74 -0
  140. package/src/procedures/indexes.drop.ts +56 -0
  141. package/src/procedures/indexes.list.ts +67 -0
  142. package/src/procedures/input-schemas.ts +63 -0
  143. package/src/procedures/schema.ts +1 -0
  144. package/src/procedures/target.ts +123 -0
  145. package/src/procedures.types.ts +162 -0
  146. package/src/register.ts +11 -0
  147. package/src/scope.ts +69 -0
  148. package/src/storage/index.ts +6 -0
  149. package/src/storage/mongo-storage.ts +151 -0
  150. 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 };