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.
@@ -0,0 +1,573 @@
1
+ import * as mongodb from 'mongodb';
2
+ import { ObjectId, AbstractCursor, FindCursor, AggregationCursor, Document, Db, Collection, InsertOneOptions, InsertOneResult, BulkWriteOptions, InsertManyResult, FindOptions, UpdateOptions, UpdateResult, ReplaceOptions, FindOneAndUpdateOptions, FindOneAndReplaceOptions, DeleteOptions, DeleteResult, FindOneAndDeleteOptions, CountDocumentsOptions, EstimatedDocumentCountOptions, AggregateOptions, IndexSpecification, CreateIndexesOptions, IndexDescription, DropIndexesOptions } from 'mongodb';
3
+ import { StandardSchemaV1 } from '@standard-schema/spec';
4
+
5
+ /**
6
+ * Comparison operators for a field value
7
+ */
8
+ type ComparisonOperators<T> = {
9
+ /** Matches values equal to a specified value */
10
+ $eq?: T;
11
+ /** Matches values not equal to a specified value */
12
+ $ne?: T;
13
+ /** Matches values greater than a specified value */
14
+ $gt?: T;
15
+ /** Matches values greater than or equal to a specified value */
16
+ $gte?: T;
17
+ /** Matches values less than a specified value */
18
+ $lt?: T;
19
+ /** Matches values less than or equal to a specified value */
20
+ $lte?: T;
21
+ /** Matches any of the values specified in an array */
22
+ $in?: T[];
23
+ /** Matches none of the values specified in an array */
24
+ $nin?: T[];
25
+ };
26
+ /**
27
+ * Element operators
28
+ */
29
+ type ElementOperators = {
30
+ /** Matches documents that have the specified field */
31
+ $exists?: boolean;
32
+ /** Selects documents if a field is of the specified type */
33
+ $type?: string | number;
34
+ };
35
+ /**
36
+ * String-specific operators
37
+ */
38
+ type StringOperators = {
39
+ /** Matches documents where the field matches a regular expression */
40
+ $regex?: RegExp | string;
41
+ /** Regex options (i, m, x, s) */
42
+ $options?: string;
43
+ };
44
+ /**
45
+ * Array-specific operators
46
+ */
47
+ type ArrayOperators<T> = {
48
+ /** Matches arrays that contain all specified elements */
49
+ $all?: T extends Array<infer E> ? E[] : never;
50
+ /** Matches arrays with a specific number of elements */
51
+ $size?: T extends Array<unknown> ? number : never;
52
+ /** Matches documents that contain an array field with at least one element matching a query */
53
+ $elemMatch?: T extends Array<infer E> ? E extends object ? Filter<E> : ComparisonOperators<E> : never;
54
+ };
55
+ /**
56
+ * All operators that can be applied to a field
57
+ */
58
+ type FieldOperators<T> = ComparisonOperators<T> & ElementOperators & (T extends string ? StringOperators : object) & (T extends Array<unknown> ? ArrayOperators<T> : object);
59
+ /**
60
+ * Condition for a single field - either a direct value or operators
61
+ */
62
+ type FieldCondition<T> = T | FieldOperators<T>;
63
+ /**
64
+ * Filter for nested object paths using dot notation
65
+ * This provides basic support for nested field access
66
+ */
67
+ type NestedPaths<T, Depth extends number[] = []> = Depth["length"] extends 3 ? never : T extends object ? T extends ObjectId | Date | Array<unknown> ? never : {
68
+ [K in keyof T & string]: T[K] extends object ? `${K}` | `${K}.${NestedPaths<T[K], [...Depth, 1]> & string}` : `${K}`;
69
+ }[keyof T & string] : never;
70
+ /**
71
+ * Get the type at a nested path
72
+ */
73
+ type PathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? PathValue<T[K], Rest> : never : P extends keyof T ? T[P] : never;
74
+ /**
75
+ * Root filter type for querying documents
76
+ */
77
+ type Filter<Doc> = {
78
+ [K in keyof Doc]?: FieldCondition<Doc[K]>;
79
+ } & {
80
+ [K in NestedPaths<Doc>]?: FieldCondition<PathValue<Doc, K>>;
81
+ } & {
82
+ /** Logical AND - matches all conditions */
83
+ $and?: Filter<Doc>[];
84
+ /** Logical OR - matches any condition */
85
+ $or?: Filter<Doc>[];
86
+ /** Logical NOR - matches none of the conditions */
87
+ $nor?: Filter<Doc>[];
88
+ /** Logical NOT - inverts the condition */
89
+ $not?: Filter<Doc>;
90
+ /** Text search */
91
+ $text?: {
92
+ $search: string;
93
+ $language?: string;
94
+ $caseSensitive?: boolean;
95
+ $diacriticSensitive?: boolean;
96
+ };
97
+ /** JavaScript expression */
98
+ $where?: string | ((this: Doc) => boolean);
99
+ /** Comment for the query */
100
+ $comment?: string;
101
+ };
102
+ /**
103
+ * Empty filter type for matching all documents
104
+ */
105
+ type EmptyFilter = Record<string, never>;
106
+
107
+ /**
108
+ * Projection to include/exclude fields
109
+ */
110
+ type Projection<Doc> = {
111
+ [K in keyof Doc]?: 1 | 0 | true | false;
112
+ } & {
113
+ /** Always include _id unless explicitly excluded */
114
+ _id?: 1 | 0 | true | false;
115
+ };
116
+ /**
117
+ * Include projection - specifies which fields to include
118
+ */
119
+ type IncludeProjection<Doc> = {
120
+ [K in keyof Doc]?: 1 | true;
121
+ } & {
122
+ _id?: 0 | false;
123
+ };
124
+ /**
125
+ * Exclude projection - specifies which fields to exclude
126
+ */
127
+ type ExcludeProjection<Doc> = {
128
+ [K in keyof Doc]?: 0 | false;
129
+ };
130
+ /**
131
+ * Result type when projection is applied
132
+ * This is a simplified version - full implementation would need mapped types
133
+ */
134
+ type ProjectedDocument<Doc, P extends Projection<Doc>> = P extends {
135
+ _id: 0 | false;
136
+ } ? Omit<Pick<Doc, Extract<keyof P, keyof Doc>>, "_id"> : Pick<Doc, Extract<keyof P, keyof Doc> | "_id">;
137
+ /**
138
+ * Sort direction
139
+ */
140
+ type SortDirection = 1 | -1 | "asc" | "desc" | "ascending" | "descending";
141
+ /**
142
+ * Sort specification
143
+ */
144
+ type Sort<Doc> = {
145
+ [K in keyof Doc]?: SortDirection;
146
+ } & {
147
+ /** Natural order */
148
+ $natural?: SortDirection;
149
+ };
150
+
151
+ /**
152
+ * Helper type to get array element type
153
+ */
154
+ type ArrayElement<T> = T extends Array<infer E> ? E : never;
155
+ /**
156
+ * Helper to check if a type is an array
157
+ */
158
+ type IsArray<T> = T extends Array<unknown> ? true : false;
159
+ /**
160
+ * Helper to check if a type is a number
161
+ */
162
+ type IsNumber<T> = T extends number ? true : false;
163
+ /**
164
+ * $set operator - sets field values
165
+ */
166
+ type SetOperator<Doc> = {
167
+ $set?: Partial<Doc>;
168
+ };
169
+ /**
170
+ * $unset operator - removes fields
171
+ */
172
+ type UnsetOperator<Doc> = {
173
+ $unset?: {
174
+ [K in keyof Doc]?: 1 | "" | true;
175
+ };
176
+ };
177
+ /**
178
+ * $inc operator - increments numeric fields
179
+ */
180
+ type IncOperator<Doc> = {
181
+ $inc?: {
182
+ [K in keyof Doc as IsNumber<Doc[K]> extends true ? K : never]?: number;
183
+ };
184
+ };
185
+ /**
186
+ * $mul operator - multiplies numeric fields
187
+ */
188
+ type MulOperator<Doc> = {
189
+ $mul?: {
190
+ [K in keyof Doc as IsNumber<Doc[K]> extends true ? K : never]?: number;
191
+ };
192
+ };
193
+ /**
194
+ * $min operator - updates if new value is less than current
195
+ */
196
+ type MinOperator<Doc> = {
197
+ $min?: {
198
+ [K in keyof Doc]?: Doc[K];
199
+ };
200
+ };
201
+ /**
202
+ * $max operator - updates if new value is greater than current
203
+ */
204
+ type MaxOperator<Doc> = {
205
+ $max?: {
206
+ [K in keyof Doc]?: Doc[K];
207
+ };
208
+ };
209
+ /**
210
+ * $rename operator - renames fields
211
+ */
212
+ type RenameOperator<Doc> = {
213
+ $rename?: {
214
+ [K in keyof Doc]?: string;
215
+ };
216
+ };
217
+ /**
218
+ * $currentDate operator - sets field to current date
219
+ */
220
+ type CurrentDateOperator<Doc> = {
221
+ $currentDate?: {
222
+ [K in keyof Doc as Doc[K] extends Date ? K : never]?: true | {
223
+ $type: "date" | "timestamp";
224
+ };
225
+ };
226
+ };
227
+ /**
228
+ * $push operator - adds elements to arrays
229
+ */
230
+ type PushOperator<Doc> = {
231
+ $push?: {
232
+ [K in keyof Doc as IsArray<Doc[K]> extends true ? K : never]?: ArrayElement<Doc[K]> | {
233
+ $each: ArrayElement<Doc[K]>[];
234
+ $position?: number;
235
+ $slice?: number;
236
+ $sort?: 1 | -1 | Record<string, 1 | -1>;
237
+ };
238
+ };
239
+ };
240
+ /**
241
+ * $addToSet operator - adds elements to arrays only if they don't exist
242
+ */
243
+ type AddToSetOperator<Doc> = {
244
+ $addToSet?: {
245
+ [K in keyof Doc as IsArray<Doc[K]> extends true ? K : never]?: ArrayElement<Doc[K]> | {
246
+ $each: ArrayElement<Doc[K]>[];
247
+ };
248
+ };
249
+ };
250
+ /**
251
+ * $pop operator - removes first or last element from array
252
+ */
253
+ type PopOperator<Doc> = {
254
+ $pop?: {
255
+ [K in keyof Doc as IsArray<Doc[K]> extends true ? K : never]?: 1 | -1;
256
+ };
257
+ };
258
+ /**
259
+ * $pull operator - removes elements matching a condition
260
+ */
261
+ type PullOperator<Doc> = {
262
+ $pull?: {
263
+ [K in keyof Doc as IsArray<Doc[K]> extends true ? K : never]?: ArrayElement<Doc[K]> | Partial<ArrayElement<Doc[K]>>;
264
+ };
265
+ };
266
+ /**
267
+ * $pullAll operator - removes all matching values from array
268
+ */
269
+ type PullAllOperator<Doc> = {
270
+ $pullAll?: {
271
+ [K in keyof Doc as IsArray<Doc[K]> extends true ? K : never]?: ArrayElement<Doc[K]>[];
272
+ };
273
+ };
274
+ /**
275
+ * Combined update operators
276
+ */
277
+ type Update<Doc> = SetOperator<Doc> & UnsetOperator<Doc> & IncOperator<Doc> & MulOperator<Doc> & MinOperator<Doc> & MaxOperator<Doc> & RenameOperator<Doc> & CurrentDateOperator<Doc> & PushOperator<Doc> & AddToSetOperator<Doc> & PopOperator<Doc> & PullOperator<Doc> & PullAllOperator<Doc>;
278
+ /**
279
+ * Update with aggregation pipeline
280
+ */
281
+ type UpdatePipeline<Doc> = Update<Doc>[];
282
+
283
+ /**
284
+ * Base typed cursor wrapper with common operations
285
+ * Works with both FindCursor and AggregationCursor
286
+ */
287
+ declare class TypedCursor<Doc, RawCursor extends AbstractCursor<Doc>> {
288
+ protected readonly cursor: RawCursor;
289
+ constructor(cursor: RawCursor);
290
+ /**
291
+ * Get the underlying MongoDB cursor
292
+ */
293
+ get raw(): RawCursor;
294
+ /**
295
+ * Returns all documents as an array
296
+ */
297
+ toArray(): Promise<Doc[]>;
298
+ /**
299
+ * Iterate over documents with a callback
300
+ */
301
+ forEach(callback: (doc: Doc) => void | Promise<void>): Promise<void>;
302
+ /**
303
+ * Map documents to a new type
304
+ */
305
+ map<T>(transform: (doc: Doc) => T): TypedCursor<T, AbstractCursor<T>>;
306
+ /**
307
+ * Check if there are more documents
308
+ */
309
+ hasNext(): Promise<boolean>;
310
+ /**
311
+ * Get the next document
312
+ */
313
+ next(): Promise<Doc | null>;
314
+ /**
315
+ * Close the cursor
316
+ */
317
+ close(): Promise<void>;
318
+ /**
319
+ * Make the cursor iterable
320
+ */
321
+ [Symbol.asyncIterator](): AsyncIterator<Doc>;
322
+ }
323
+ /**
324
+ * Typed wrapper around MongoDB's FindCursor
325
+ * Extends base cursor with find-specific operations
326
+ */
327
+ declare class TypedFindCursor<Doc> extends TypedCursor<Doc, FindCursor<Doc>> {
328
+ /**
329
+ * Map documents to a new type
330
+ */
331
+ map<T>(transform: (doc: Doc) => T): TypedFindCursor<T>;
332
+ /**
333
+ * Limit the number of documents returned
334
+ */
335
+ limit(count: number): this;
336
+ /**
337
+ * Skip a number of documents
338
+ */
339
+ skip(count: number): this;
340
+ /**
341
+ * Sort the documents
342
+ */
343
+ sort(sort: Sort<Doc>): this;
344
+ /**
345
+ * Project specific fields
346
+ */
347
+ project<P extends Projection<Doc>>(projection: P): TypedFindCursor<Doc>;
348
+ /**
349
+ * Set batch size for cursor
350
+ */
351
+ batchSize(size: number): this;
352
+ }
353
+ /**
354
+ * Typed wrapper around MongoDB's AggregationCursor
355
+ * Uses the base TypedCursor functionality
356
+ */
357
+ declare class TypedAggregationCursor<Doc> extends TypedCursor<Doc, AggregationCursor<Doc>> {
358
+ /**
359
+ * Map documents to a new type
360
+ */
361
+ map<T>(transform: (doc: Doc) => T): TypedAggregationCursor<T>;
362
+ }
363
+
364
+ /**
365
+ * Check if a type has an _id property
366
+ */
367
+ type HasId<T> = "_id" extends keyof T ? true : false;
368
+ /**
369
+ * Document type that adds ObjectId _id only if not present in the schema
370
+ * - If schema defines _id, use the schema's type
371
+ * - If schema doesn't define _id, add _id: ObjectId
372
+ */
373
+ type DocumentWithId<T extends Document> = HasId<T> extends true ? T : T & {
374
+ _id: ObjectId;
375
+ };
376
+ /**
377
+ * Infer the input type from a Standard Schema (pre-validation)
378
+ * Used for insert/update operations where data is validated before storage
379
+ */
380
+ type InferSchemaInput<S extends StandardSchemaV1> = StandardSchemaV1.InferInput<S> & Document;
381
+ /**
382
+ * Infer the document type from a Standard Schema (post-validation)
383
+ * Automatically adds _id: ObjectId if not defined in the schema
384
+ * Used for query results and stored documents
385
+ */
386
+ type InferDocument<S extends StandardSchemaV1> = DocumentWithId<StandardSchemaV1.InferOutput<S> & Document>;
387
+ /**
388
+ * Optional _id for insert operations
389
+ * - If schema defines _id, it remains as defined (could be required or optional)
390
+ * - If schema doesn't define _id, adds optional _id that accepts ObjectId or string
391
+ */
392
+ type OptionalId<T extends Document> = HasId<T> extends true ? T : Omit<T, "_id"> & {
393
+ _id?: ObjectId | string;
394
+ };
395
+ /**
396
+ * Validation error thrown when schema validation fails
397
+ */
398
+ declare class ValidationError extends Error {
399
+ readonly issues: ReadonlyArray<StandardSchemaV1.Issue>;
400
+ constructor(issues: ReadonlyArray<StandardSchemaV1.Issue>);
401
+ }
402
+ /**
403
+ * Options for collection operations
404
+ */
405
+ interface CollectionOptions {
406
+ /**
407
+ * Whether to validate documents before insert/update operations
408
+ * @default true
409
+ */
410
+ validate?: boolean;
411
+ }
412
+
413
+ /**
414
+ * Type-safe MongoDB collection wrapper
415
+ * Validates documents before insert/update operations using Standard Schema
416
+ */
417
+ declare class TypedCollection<S extends StandardSchemaV1> {
418
+ private readonly collection;
419
+ private readonly schema;
420
+ private readonly shouldValidate;
421
+ constructor(collection: Collection<Document>, schema: S, options?: CollectionOptions);
422
+ /**
423
+ * Get the underlying MongoDB collection
424
+ */
425
+ get raw(): Collection<Document>;
426
+ /**
427
+ * Get the collection name
428
+ */
429
+ get collectionName(): string;
430
+ /**
431
+ * Insert a single document
432
+ * Validates the document before insertion if validation is enabled
433
+ */
434
+ insertOne(doc: OptionalId<InferSchemaInput<S>>, options?: InsertOneOptions): Promise<InsertOneResult>;
435
+ /**
436
+ * Insert multiple documents
437
+ * Validates all documents before insertion if validation is enabled
438
+ */
439
+ insertMany(docs: OptionalId<InferSchemaInput<S>>[], options?: BulkWriteOptions): Promise<InsertManyResult>;
440
+ /**
441
+ * Find documents matching the filter
442
+ * Returns a typed cursor for further operations
443
+ */
444
+ find(filter?: Filter<InferDocument<S>>, options?: FindOptions): TypedFindCursor<InferDocument<S>>;
445
+ /**
446
+ * Find a single document matching the filter
447
+ */
448
+ findOne(filter?: Filter<InferDocument<S>>, options?: FindOptions): Promise<InferDocument<S> | null>;
449
+ /**
450
+ * Find a document by its _id
451
+ */
452
+ findById(id: string | mongodb.ObjectId, options?: FindOptions): Promise<InferDocument<S> | null>;
453
+ /**
454
+ * Update a single document
455
+ */
456
+ updateOne(filter: Filter<InferDocument<S>>, update: Update<InferDocument<S>>, options?: UpdateOptions): Promise<UpdateResult>;
457
+ /**
458
+ * Update multiple documents
459
+ */
460
+ updateMany(filter: Filter<InferDocument<S>>, update: Update<InferDocument<S>>, options?: UpdateOptions): Promise<UpdateResult>;
461
+ /**
462
+ * Replace a single document
463
+ * Validates the replacement document if validation is enabled
464
+ */
465
+ replaceOne(filter: Filter<InferDocument<S>>, replacement: OptionalId<InferSchemaInput<S>>, options?: ReplaceOptions): Promise<UpdateResult>;
466
+ /**
467
+ * Find a document and update it atomically
468
+ */
469
+ findOneAndUpdate(filter: Filter<InferDocument<S>>, update: Update<InferDocument<S>>, options?: FindOneAndUpdateOptions): Promise<InferDocument<S> | null>;
470
+ /**
471
+ * Find a document and replace it atomically
472
+ * Validates the replacement document if validation is enabled
473
+ */
474
+ findOneAndReplace(filter: Filter<InferDocument<S>>, replacement: OptionalId<InferSchemaInput<S>>, options?: FindOneAndReplaceOptions): Promise<InferDocument<S> | null>;
475
+ /**
476
+ * Delete a single document
477
+ */
478
+ deleteOne(filter: Filter<InferDocument<S>>, options?: DeleteOptions): Promise<DeleteResult>;
479
+ /**
480
+ * Delete multiple documents
481
+ */
482
+ deleteMany(filter: Filter<InferDocument<S>>, options?: DeleteOptions): Promise<DeleteResult>;
483
+ /**
484
+ * Find a document and delete it atomically
485
+ */
486
+ findOneAndDelete(filter: Filter<InferDocument<S>>, options?: FindOneAndDeleteOptions): Promise<InferDocument<S> | null>;
487
+ /**
488
+ * Count documents matching the filter
489
+ */
490
+ countDocuments(filter?: Filter<InferDocument<S>>, options?: CountDocumentsOptions): Promise<number>;
491
+ /**
492
+ * Get an estimated count of documents (faster, uses metadata)
493
+ */
494
+ estimatedDocumentCount(options?: EstimatedDocumentCountOptions): Promise<number>;
495
+ /**
496
+ * Run an aggregation pipeline
497
+ */
498
+ aggregate<T extends Document = Document>(pipeline: Document[], options?: AggregateOptions): TypedAggregationCursor<T>;
499
+ /**
500
+ * Create an index
501
+ */
502
+ createIndex(indexSpec: IndexSpecification, options?: CreateIndexesOptions): Promise<string>;
503
+ /**
504
+ * Create multiple indexes
505
+ */
506
+ createIndexes(indexSpecs: IndexDescription[], options?: CreateIndexesOptions): Promise<string[]>;
507
+ /**
508
+ * Drop an index
509
+ */
510
+ dropIndex(indexName: string, options?: DropIndexesOptions): Promise<void>;
511
+ /**
512
+ * List all indexes
513
+ */
514
+ indexes(): Promise<Document[]>;
515
+ /**
516
+ * Get distinct values for a field
517
+ */
518
+ distinct<K extends keyof InferDocument<S>>(field: K, filter?: Filter<InferDocument<S>>): Promise<InferDocument<S>[K][]>;
519
+ /**
520
+ * Check if a document exists
521
+ */
522
+ exists(filter: Filter<InferDocument<S>>): Promise<boolean>;
523
+ /**
524
+ * Drop the collection
525
+ */
526
+ drop(): Promise<void>;
527
+ }
528
+ /**
529
+ * Create a typed collection from a database and schema
530
+ *
531
+ * @param db - MongoDB database instance
532
+ * @param name - Collection name
533
+ * @param schema - Standard Schema compatible validation schema (zod, valibot, arktype, etc.)
534
+ * @param options - Collection options
535
+ *
536
+ * @example
537
+ * ```typescript
538
+ * import { z } from 'zod';
539
+ * import { defineCollection } from 'momos';
540
+ *
541
+ * const userSchema = z.object({
542
+ * name: z.string(),
543
+ * email: z.string().email(),
544
+ * age: z.number().min(0),
545
+ * });
546
+ *
547
+ * const users = defineCollection(db, 'users', userSchema);
548
+ *
549
+ * // Type-safe insert
550
+ * await users.insertOne({ name: 'John', email: 'john@example.com', age: 30 });
551
+ *
552
+ * // Type-safe queries
553
+ * const adults = await users.find({ age: { $gte: 18 } }).toArray();
554
+ * ```
555
+ */
556
+ declare function defineCollection<S extends StandardSchemaV1>(db: Db, name: string, schema: S, options?: CollectionOptions): TypedCollection<S>;
557
+
558
+ /**
559
+ * Validate a value against a Standard Schema
560
+ * Works with any Standard Schema compatible library (zod, valibot, arktype, etc.)
561
+ */
562
+ declare function validate<S extends StandardSchemaV1>(schema: S, data: unknown): Promise<StandardSchemaV1.InferOutput<S>>;
563
+ /**
564
+ * Validate multiple values against a Standard Schema
565
+ */
566
+ declare function validateMany<S extends StandardSchemaV1>(schema: S, data: unknown[]): Promise<StandardSchemaV1.InferOutput<S>[]>;
567
+ /**
568
+ * Check if a value is valid according to a Standard Schema (non-throwing)
569
+ */
570
+ declare function isValid<S extends StandardSchemaV1>(schema: S, data: unknown): Promise<boolean>;
571
+
572
+ export { TypedAggregationCursor, TypedCollection, TypedCursor, TypedFindCursor, ValidationError, defineCollection, isValid, validate, validateMany };
573
+ export type { AddToSetOperator, ArrayOperators, CollectionOptions, ComparisonOperators, CurrentDateOperator, DocumentWithId, ElementOperators, EmptyFilter, ExcludeProjection, FieldCondition, FieldOperators, Filter, HasId, IncOperator, IncludeProjection, InferDocument, InferSchemaInput, MaxOperator, MinOperator, MulOperator, OptionalId, PopOperator, ProjectedDocument, Projection, PullAllOperator, PullOperator, PushOperator, RenameOperator, SetOperator, Sort, SortDirection, StringOperators, UnsetOperator, Update, UpdatePipeline };