momos 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,365 @@
1
+ class TypedCursor {
2
+ constructor(cursor) {
3
+ this.cursor = cursor;
4
+ }
5
+ /**
6
+ * Get the underlying MongoDB cursor
7
+ */
8
+ get raw() {
9
+ return this.cursor;
10
+ }
11
+ /**
12
+ * Returns all documents as an array
13
+ */
14
+ async toArray() {
15
+ return this.cursor.toArray();
16
+ }
17
+ /**
18
+ * Iterate over documents with a callback
19
+ */
20
+ async forEach(callback) {
21
+ for await (const doc of this.cursor) {
22
+ await callback(doc);
23
+ }
24
+ }
25
+ /**
26
+ * Map documents to a new type
27
+ */
28
+ map(transform) {
29
+ return new TypedCursor(this.cursor.map(transform));
30
+ }
31
+ /**
32
+ * Check if there are more documents
33
+ */
34
+ async hasNext() {
35
+ return this.cursor.hasNext();
36
+ }
37
+ /**
38
+ * Get the next document
39
+ */
40
+ async next() {
41
+ return this.cursor.next();
42
+ }
43
+ /**
44
+ * Close the cursor
45
+ */
46
+ async close() {
47
+ await this.cursor.close();
48
+ }
49
+ /**
50
+ * Make the cursor iterable
51
+ */
52
+ [Symbol.asyncIterator]() {
53
+ return this.cursor[Symbol.asyncIterator]();
54
+ }
55
+ }
56
+ class TypedFindCursor extends TypedCursor {
57
+ /**
58
+ * Map documents to a new type
59
+ */
60
+ map(transform) {
61
+ return new TypedFindCursor(this.cursor.map(transform));
62
+ }
63
+ /**
64
+ * Limit the number of documents returned
65
+ */
66
+ limit(count) {
67
+ this.cursor.limit(count);
68
+ return this;
69
+ }
70
+ /**
71
+ * Skip a number of documents
72
+ */
73
+ skip(count) {
74
+ this.cursor.skip(count);
75
+ return this;
76
+ }
77
+ /**
78
+ * Sort the documents
79
+ */
80
+ sort(sort) {
81
+ this.cursor.sort(sort);
82
+ return this;
83
+ }
84
+ /**
85
+ * Project specific fields
86
+ */
87
+ project(projection) {
88
+ this.cursor.project(projection);
89
+ return this;
90
+ }
91
+ /**
92
+ * Set batch size for cursor
93
+ */
94
+ batchSize(size) {
95
+ this.cursor.batchSize(size);
96
+ return this;
97
+ }
98
+ }
99
+ class TypedAggregationCursor extends TypedCursor {
100
+ /**
101
+ * Map documents to a new type
102
+ */
103
+ map(transform) {
104
+ return new TypedAggregationCursor(this.cursor.map(transform));
105
+ }
106
+ }
107
+
108
+ class ValidationError extends Error {
109
+ issues;
110
+ constructor(issues) {
111
+ const message = issues.map((i) => i.message).join(", ");
112
+ super(`Validation failed: ${message}`);
113
+ this.name = "ValidationError";
114
+ this.issues = issues;
115
+ }
116
+ }
117
+
118
+ async function validate(schema, data) {
119
+ const result = await schema["~standard"].validate(data);
120
+ if (result.issues) {
121
+ throw new ValidationError(result.issues);
122
+ }
123
+ return result.value;
124
+ }
125
+ async function validateMany(schema, data) {
126
+ return Promise.all(data.map((item) => validate(schema, item)));
127
+ }
128
+ async function isValid(schema, data) {
129
+ const result = await schema["~standard"].validate(data);
130
+ return !result.issues;
131
+ }
132
+
133
+ class TypedCollection {
134
+ collection;
135
+ schema;
136
+ shouldValidate;
137
+ constructor(collection, schema, options = {}) {
138
+ this.collection = collection;
139
+ this.schema = schema;
140
+ this.shouldValidate = options.validate !== false;
141
+ }
142
+ /**
143
+ * Get the underlying MongoDB collection
144
+ */
145
+ get raw() {
146
+ return this.collection;
147
+ }
148
+ /**
149
+ * Get the collection name
150
+ */
151
+ get collectionName() {
152
+ return this.collection.collectionName;
153
+ }
154
+ // ============================================
155
+ // INSERT OPERATIONS
156
+ // ============================================
157
+ /**
158
+ * Insert a single document
159
+ * Validates the document before insertion if validation is enabled
160
+ */
161
+ async insertOne(doc, options) {
162
+ const validated = this.shouldValidate ? await validate(this.schema, doc) : doc;
163
+ return this.collection.insertOne(validated, options);
164
+ }
165
+ /**
166
+ * Insert multiple documents
167
+ * Validates all documents before insertion if validation is enabled
168
+ */
169
+ async insertMany(docs, options) {
170
+ const validated = this.shouldValidate ? await validateMany(this.schema, docs) : docs;
171
+ return this.collection.insertMany(validated, options);
172
+ }
173
+ // ============================================
174
+ // FIND OPERATIONS
175
+ // ============================================
176
+ /**
177
+ * Find documents matching the filter
178
+ * Returns a typed cursor for further operations
179
+ */
180
+ find(filter = {}, options) {
181
+ const cursor = this.collection.find(filter, options);
182
+ return new TypedFindCursor(cursor);
183
+ }
184
+ /**
185
+ * Find a single document matching the filter
186
+ */
187
+ async findOne(filter = {}, options) {
188
+ const result = await this.collection.findOne(filter, options);
189
+ return result;
190
+ }
191
+ /**
192
+ * Find a document by its _id
193
+ */
194
+ async findById(id, options) {
195
+ return this.findOne({ _id: id }, options);
196
+ }
197
+ // ============================================
198
+ // UPDATE OPERATIONS
199
+ // ============================================
200
+ /**
201
+ * Update a single document
202
+ */
203
+ async updateOne(filter, update, options) {
204
+ return this.collection.updateOne(
205
+ filter,
206
+ update,
207
+ options
208
+ );
209
+ }
210
+ /**
211
+ * Update multiple documents
212
+ */
213
+ async updateMany(filter, update, options) {
214
+ return this.collection.updateMany(
215
+ filter,
216
+ update,
217
+ options
218
+ );
219
+ }
220
+ /**
221
+ * Replace a single document
222
+ * Validates the replacement document if validation is enabled
223
+ */
224
+ async replaceOne(filter, replacement, options) {
225
+ const validated = this.shouldValidate ? await validate(this.schema, replacement) : replacement;
226
+ return this.collection.replaceOne(
227
+ filter,
228
+ validated,
229
+ options
230
+ );
231
+ }
232
+ /**
233
+ * Find a document and update it atomically
234
+ */
235
+ async findOneAndUpdate(filter, update, options = {}) {
236
+ const result = await this.collection.findOneAndUpdate(
237
+ filter,
238
+ update,
239
+ options
240
+ );
241
+ return result;
242
+ }
243
+ /**
244
+ * Find a document and replace it atomically
245
+ * Validates the replacement document if validation is enabled
246
+ */
247
+ async findOneAndReplace(filter, replacement, options = {}) {
248
+ const validated = this.shouldValidate ? await validate(this.schema, replacement) : replacement;
249
+ const result = await this.collection.findOneAndReplace(
250
+ filter,
251
+ validated,
252
+ options
253
+ );
254
+ return result;
255
+ }
256
+ // ============================================
257
+ // DELETE OPERATIONS
258
+ // ============================================
259
+ /**
260
+ * Delete a single document
261
+ */
262
+ async deleteOne(filter, options) {
263
+ return this.collection.deleteOne(filter, options);
264
+ }
265
+ /**
266
+ * Delete multiple documents
267
+ */
268
+ async deleteMany(filter, options) {
269
+ return this.collection.deleteMany(filter, options);
270
+ }
271
+ /**
272
+ * Find a document and delete it atomically
273
+ */
274
+ async findOneAndDelete(filter, options = {}) {
275
+ const result = await this.collection.findOneAndDelete(
276
+ filter,
277
+ options
278
+ );
279
+ return result;
280
+ }
281
+ // ============================================
282
+ // COUNT OPERATIONS
283
+ // ============================================
284
+ /**
285
+ * Count documents matching the filter
286
+ */
287
+ async countDocuments(filter = {}, options) {
288
+ return this.collection.countDocuments(filter, options);
289
+ }
290
+ /**
291
+ * Get an estimated count of documents (faster, uses metadata)
292
+ */
293
+ async estimatedDocumentCount(options) {
294
+ return this.collection.estimatedDocumentCount(options);
295
+ }
296
+ // ============================================
297
+ // AGGREGATION
298
+ // ============================================
299
+ /**
300
+ * Run an aggregation pipeline
301
+ */
302
+ aggregate(pipeline, options) {
303
+ const cursor = this.collection.aggregate(pipeline, options);
304
+ return new TypedAggregationCursor(cursor);
305
+ }
306
+ // ============================================
307
+ // INDEX OPERATIONS
308
+ // ============================================
309
+ /**
310
+ * Create an index
311
+ */
312
+ async createIndex(indexSpec, options) {
313
+ return this.collection.createIndex(indexSpec, options);
314
+ }
315
+ /**
316
+ * Create multiple indexes
317
+ */
318
+ async createIndexes(indexSpecs, options) {
319
+ return this.collection.createIndexes(indexSpecs, options);
320
+ }
321
+ /**
322
+ * Drop an index
323
+ */
324
+ async dropIndex(indexName, options) {
325
+ await this.collection.dropIndex(indexName, options);
326
+ }
327
+ /**
328
+ * List all indexes
329
+ */
330
+ async indexes() {
331
+ return this.collection.indexes();
332
+ }
333
+ // ============================================
334
+ // UTILITY OPERATIONS
335
+ // ============================================
336
+ /**
337
+ * Get distinct values for a field
338
+ */
339
+ async distinct(field, filter = {}) {
340
+ const result = await this.collection.distinct(
341
+ field,
342
+ filter
343
+ );
344
+ return result;
345
+ }
346
+ /**
347
+ * Check if a document exists
348
+ */
349
+ async exists(filter) {
350
+ const count = await this.countDocuments(filter, { limit: 1 });
351
+ return count > 0;
352
+ }
353
+ /**
354
+ * Drop the collection
355
+ */
356
+ async drop() {
357
+ await this.collection.drop();
358
+ }
359
+ }
360
+ function defineCollection(db, name, schema, options = {}) {
361
+ const collection = db.collection(name);
362
+ return new TypedCollection(collection, schema, options);
363
+ }
364
+
365
+ export { TypedAggregationCursor, TypedCollection, TypedCursor, TypedFindCursor, ValidationError, defineCollection, isValid, validate, validateMany };
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "momos",
3
+ "description": "MongoDB ORM",
4
+ "version": "0.0.1",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "mongodb",
9
+ "orm"
10
+ ],
11
+ "main": "dist/index.cjs",
12
+ "module": "dist/index.js",
13
+ "types": "dist/index.d.ts",
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "exports": {
18
+ "import": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ },
22
+ "require": {
23
+ "types": "./dist/index.d.cts",
24
+ "default": "./dist/index.cjs"
25
+ }
26
+ },
27
+ "homepage": "https://honohub.dev/docs/momos",
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/rhinobase/momos.git"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/rhinobase/momos/issues"
37
+ },
38
+ "peerDependencies": {
39
+ "@standard-schema/spec": "^1.1.0",
40
+ "mongodb": "^7.0.0"
41
+ },
42
+ "devDependencies": {
43
+ "@biomejs/biome": "^2.3.10",
44
+ "husky": "^9.1.7",
45
+ "is-ci": "^4.1.0",
46
+ "nano-staged": "^0.9.0",
47
+ "pkgroll": "^2.21.4",
48
+ "typescript": "~5.9.3",
49
+ "vitest": "^4.0.16",
50
+ "zod": "^4.2.1"
51
+ },
52
+ "scripts": {
53
+ "build": "pkgroll --clean-dist",
54
+ "test": "vitest",
55
+ "format": "biome check --write ."
56
+ }
57
+ }