@semics-tech/mongolite 1.0.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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +179 -0
  3. package/dist/adapters/browser.d.ts +97 -0
  4. package/dist/adapters/browser.js +103 -0
  5. package/dist/adapters/browser.js.map +1 -0
  6. package/dist/adapters/cloudflare.d.ts +106 -0
  7. package/dist/adapters/cloudflare.js +94 -0
  8. package/dist/adapters/cloudflare.js.map +1 -0
  9. package/dist/bin/mongolite-debug.d.ts +2 -0
  10. package/dist/bin/mongolite-debug.js +115 -0
  11. package/dist/bin/mongolite-debug.js.map +1 -0
  12. package/dist/changeStream.d.ts +114 -0
  13. package/dist/changeStream.js +338 -0
  14. package/dist/changeStream.js.map +1 -0
  15. package/dist/cloudflare.d.ts +39 -0
  16. package/dist/cloudflare.js +39 -0
  17. package/dist/cloudflare.js.map +1 -0
  18. package/dist/collection.d.ts +274 -0
  19. package/dist/collection.js +1706 -0
  20. package/dist/collection.js.map +1 -0
  21. package/dist/cursors/findCursor.d.ts +101 -0
  22. package/dist/cursors/findCursor.js +757 -0
  23. package/dist/cursors/findCursor.js.map +1 -0
  24. package/dist/db.d.ts +116 -0
  25. package/dist/db.js +254 -0
  26. package/dist/db.js.map +1 -0
  27. package/dist/debugger/query-debugger.d.ts +22 -0
  28. package/dist/debugger/query-debugger.js +258 -0
  29. package/dist/debugger/query-debugger.js.map +1 -0
  30. package/dist/index.d.ts +30 -0
  31. package/dist/index.js +40 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/mongo-client.d.ts +56 -0
  34. package/dist/mongo-client.js +55 -0
  35. package/dist/mongo-client.js.map +1 -0
  36. package/dist/types.d.ts +318 -0
  37. package/dist/types.js +2 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/utils/indexing.d.ts +4 -0
  40. package/dist/utils/indexing.js +43 -0
  41. package/dist/utils/indexing.js.map +1 -0
  42. package/dist/utils/projection.d.ts +16 -0
  43. package/dist/utils/projection.js +98 -0
  44. package/dist/utils/projection.js.map +1 -0
  45. package/dist/utils/queryOperators.d.ts +16 -0
  46. package/dist/utils/queryOperators.js +138 -0
  47. package/dist/utils/queryOperators.js.map +1 -0
  48. package/package.json +92 -0
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Represents a document with an optional _id field.
3
+ */
4
+ export interface DocumentWithId {
5
+ _id?: string;
6
+ [key: string]: unknown;
7
+ }
8
+ /**
9
+ * Result of insertOne operation.
10
+ */
11
+ export interface InsertOneResult {
12
+ acknowledged: boolean;
13
+ insertedId: string;
14
+ }
15
+ /**
16
+ * Result of insertMany operation.
17
+ */
18
+ export interface InsertManyResult {
19
+ acknowledged: boolean;
20
+ insertedCount: number;
21
+ insertedIds: Record<number, string>;
22
+ }
23
+ /**
24
+ * Result of updateOne operation.
25
+ */
26
+ export interface UpdateResult {
27
+ acknowledged: boolean;
28
+ matchedCount: number;
29
+ modifiedCount: number;
30
+ upsertedId: string | null;
31
+ }
32
+ /**
33
+ * Result of findOneAndUpdate/findOneAndReplace/findOneAndDelete operations.
34
+ */
35
+ export interface ModifyResult<T> {
36
+ value: T | null;
37
+ ok: 1;
38
+ }
39
+ /**
40
+ * Result of deleteOne/deleteMany operations.
41
+ */
42
+ export interface DeleteResult {
43
+ acknowledged: boolean;
44
+ deletedCount: number;
45
+ }
46
+ /**
47
+ * Options for findOneAndUpdate operations.
48
+ */
49
+ export interface FindOneAndUpdateOptions<TSchema = DocumentWithId> {
50
+ /** Whether to return the document before ('before') or after ('after') the update. Default is 'before'. */
51
+ returnDocument?: 'before' | 'after';
52
+ /** If true, insert a new document when no match is found. */
53
+ upsert?: boolean;
54
+ /** Field projection to apply. */
55
+ projection?: Projection<TSchema>;
56
+ }
57
+ /**
58
+ * Options for findOneAndDelete operations.
59
+ */
60
+ export interface FindOneAndDeleteOptions<TSchema = DocumentWithId> {
61
+ /** Field projection to apply. */
62
+ projection?: Projection<TSchema>;
63
+ }
64
+ /**
65
+ * Options for findOneAndReplace operations.
66
+ */
67
+ export interface FindOneAndReplaceOptions<TSchema = DocumentWithId> {
68
+ /** Whether to return the document before ('before') or after ('after') the replacement. Default is 'before'. */
69
+ returnDocument?: 'before' | 'after';
70
+ /** If true, insert a new document when no match is found. */
71
+ upsert?: boolean;
72
+ /** Field projection to apply. */
73
+ projection?: Projection<TSchema>;
74
+ }
75
+ /**
76
+ * Options for replaceOne operations.
77
+ */
78
+ export interface ReplaceOptions {
79
+ /** If true, insert a new document when no match is found. */
80
+ upsert?: boolean;
81
+ }
82
+ /**
83
+ * Options for aggregate operations.
84
+ */
85
+ export type AggregationPipeline = Record<string, unknown>[];
86
+ /**
87
+ * Operators for filtering documents.
88
+ * T is the type of the field being queried.
89
+ */
90
+ export interface QueryOperators<T> {
91
+ $eq?: T;
92
+ $ne?: T;
93
+ $gt?: T;
94
+ $gte?: T;
95
+ $lt?: T;
96
+ $lte?: T;
97
+ $in?: T[];
98
+ $nin?: T[];
99
+ $all?: T extends unknown[] ? T : never;
100
+ $exists?: boolean;
101
+ $not?: QueryOperators<T>;
102
+ /** Regular expression pattern match. Can be a string pattern or RegExp object. */
103
+ $regex?: string | RegExp;
104
+ /** Regex options (flags). Used alongside $regex. E.g. 'i' for case-insensitive. */
105
+ $options?: string;
106
+ /** Matches arrays with the specified number of elements. */
107
+ $size?: number;
108
+ /** Selects documents where the value of the field is an instance of the specified BSON type. */
109
+ $type?: number | string | (number | string)[];
110
+ /** Matches documents where a field value divided by a divisor has a specified remainder. */
111
+ $mod?: [number, number];
112
+ }
113
+ /**
114
+ * Logical filter operators.
115
+ */
116
+ export interface LogicalOperators<T> {
117
+ $and?: Filter<T>[];
118
+ $or?: Filter<T>[];
119
+ $nor?: Filter<T>[];
120
+ }
121
+ /**
122
+ * Text search operator for full-text search.
123
+ */
124
+ export interface TextSearchOperator {
125
+ $search: string;
126
+ }
127
+ /**
128
+ * Filter type for querying documents.
129
+ * T is the document type.
130
+ */
131
+ export type Filter<T> = {
132
+ [P in keyof T]?: T[P] | QueryOperators<T[P]>;
133
+ } & {
134
+ [key: string]: unknown;
135
+ } & Partial<LogicalOperators<T>> & {
136
+ $text?: TextSearchOperator;
137
+ };
138
+ /**
139
+ * Operators for updating documents.
140
+ * T is the document type.
141
+ */
142
+ export interface UpdateOperators<T> {
143
+ $set?: {
144
+ [P in keyof T]?: T[P];
145
+ } & {
146
+ [key: string]: unknown;
147
+ };
148
+ $unset?: {
149
+ [P in keyof T]?: '';
150
+ } & {
151
+ [key: string]: '';
152
+ };
153
+ $inc?: {
154
+ [P in keyof T]?: number;
155
+ } & {
156
+ [key: string]: number;
157
+ };
158
+ $push?: {
159
+ [P in keyof T]?: unknown | {
160
+ $each: unknown[];
161
+ };
162
+ } & {
163
+ [key: string]: unknown | {
164
+ $each: unknown[];
165
+ };
166
+ };
167
+ $pull?: {
168
+ [P in keyof T]?: unknown;
169
+ } & {
170
+ [key: string]: unknown;
171
+ };
172
+ /** Adds a value to an array field only if the value is not already present. */
173
+ $addToSet?: {
174
+ [P in keyof T]?: unknown | {
175
+ $each: unknown[];
176
+ };
177
+ } & {
178
+ [key: string]: unknown | {
179
+ $each: unknown[];
180
+ };
181
+ };
182
+ /** Removes the first or last element from an array. Use 1 for last, -1 for first. */
183
+ $pop?: {
184
+ [P in keyof T]?: 1 | -1;
185
+ } & {
186
+ [key: string]: 1 | -1;
187
+ };
188
+ /** Multiplies the current value of a field by a number. */
189
+ $mul?: {
190
+ [P in keyof T]?: number;
191
+ } & {
192
+ [key: string]: number;
193
+ };
194
+ /** Updates the field value to the minimum of the current value and the specified value. */
195
+ $min?: {
196
+ [P in keyof T]?: T[P];
197
+ } & {
198
+ [key: string]: unknown;
199
+ };
200
+ /** Updates the field value to the maximum of the current value and the specified value. */
201
+ $max?: {
202
+ [P in keyof T]?: T[P];
203
+ } & {
204
+ [key: string]: unknown;
205
+ };
206
+ /** Sets the value of a field to the current date. */
207
+ $currentDate?: {
208
+ [P in keyof T]?: true | {
209
+ $type: 'date' | 'timestamp';
210
+ };
211
+ } & {
212
+ [key: string]: true | {
213
+ $type: 'date' | 'timestamp';
214
+ };
215
+ };
216
+ }
217
+ /**
218
+ * UpdateFilter type for updating documents.
219
+ */
220
+ export type UpdateFilter<T> = Partial<UpdateOperators<T>>;
221
+ /**
222
+ * SortCriteria type for sorting documents.
223
+ */
224
+ export type SortCriteria<T> = {
225
+ [P in keyof T]?: 1 | -1;
226
+ } & {
227
+ [key: string]: 1 | -1;
228
+ };
229
+ /**
230
+ * Projection type for selecting fields.
231
+ */
232
+ export type Projection<T> = {
233
+ [P in keyof T]?: 0 | 1 | boolean;
234
+ } & {
235
+ [key: string]: 0 | 1 | boolean;
236
+ };
237
+ /** * Represents a row in the SQLite database.
238
+ * The data field is a JSON string representing the document.
239
+ */
240
+ export interface SQLiteRow {
241
+ _id: string;
242
+ data: string;
243
+ }
244
+ /**
245
+ * Index specification type.
246
+ * Specifies fields to index and their sort order (1 for ascending, -1 for descending).
247
+ */
248
+ export type IndexSpecification = {
249
+ [key: string]: 1 | -1 | string;
250
+ };
251
+ /**
252
+ * Options for createIndex.
253
+ */
254
+ export interface CreateIndexOptions {
255
+ /**
256
+ * Unique index flag. If true, the index will enforce uniqueness of the indexed field.
257
+ */
258
+ unique?: boolean;
259
+ /**
260
+ * Name of the index. If not specified, a name will be generated.
261
+ */
262
+ name?: string;
263
+ /**
264
+ * If true, create the index in the background and don't block other operations.
265
+ * In SQLite this might not make a significant difference.
266
+ */
267
+ background?: boolean;
268
+ /**
269
+ * If true, MongoDB will ignore any duplicate values when creating a unique index.
270
+ * Not directly applicable to SQLite, but retained for API compatibility.
271
+ */
272
+ sparse?: boolean;
273
+ }
274
+ /**
275
+ * Result of createIndex operation.
276
+ */
277
+ export interface CreateIndexResult {
278
+ /**
279
+ * Indicates whether the index creation operation was acknowledged.
280
+ */
281
+ acknowledged: boolean;
282
+ /**
283
+ * The name of the created index.
284
+ */
285
+ name: string;
286
+ }
287
+ /**
288
+ * Result of dropIndex operation.
289
+ */
290
+ export interface DropIndexResult {
291
+ /**
292
+ * Indicates whether the index deletion operation was acknowledged.
293
+ */
294
+ acknowledged: boolean;
295
+ /**
296
+ * The name of the dropped index.
297
+ */
298
+ name: string;
299
+ }
300
+ /**
301
+ * Result of a listIndexes operation.
302
+ */
303
+ export interface IndexInfo {
304
+ /**
305
+ * Name of the index.
306
+ */
307
+ name: string;
308
+ /**
309
+ * The fields this index is defined on.
310
+ */
311
+ key: {
312
+ [key: string]: number;
313
+ };
314
+ /**
315
+ * Whether this index enforces uniqueness.
316
+ */
317
+ unique?: boolean;
318
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export declare function extractRawIndexColumns(sql: any): {
2
+ column: string;
3
+ direction: string | null;
4
+ }[];
@@ -0,0 +1,43 @@
1
+ export function extractRawIndexColumns(sql) {
2
+ const match = sql.match(/\(([\s\S]+)\)/); // allow multiline matching
3
+ if (!match)
4
+ return [];
5
+ const colsPart = match[1];
6
+ // Split on commas not inside parentheses
7
+ const columns = [];
8
+ let current = '';
9
+ let parens = 0;
10
+ for (let i = 0; i < colsPart.length; i++) {
11
+ const char = colsPart[i];
12
+ if (char === '(')
13
+ parens++;
14
+ if (char === ')')
15
+ parens--;
16
+ if (char === ',' && parens === 0) {
17
+ columns.push(current.trim());
18
+ current = '';
19
+ }
20
+ else {
21
+ current += char;
22
+ }
23
+ }
24
+ if (current.trim())
25
+ columns.push(current.trim());
26
+ return columns.map((col) => {
27
+ // Extract direction (ASC or DESC)
28
+ const directionMatch = col.match(/\s+(ASC|DESC)\s*$/i);
29
+ const direction = directionMatch ? directionMatch[1].toUpperCase() : null;
30
+ // Remove direction from column string
31
+ const colWithoutDirection = directionMatch
32
+ ? col.slice(0, directionMatch.index).trim()
33
+ : col.trim();
34
+ // Check for json_extract and pull out path
35
+ const jsonMatch = colWithoutDirection.match(/json_extract\s*\(\s*[^,]+,\s*'([^']+)'\s*\)/i);
36
+ let column = jsonMatch
37
+ ? jsonMatch[1] // the JSON path like '$.age'
38
+ : colWithoutDirection; // fallback to raw column like testCol
39
+ column = column.replace('$.', ''); // Remove leading $ if present
40
+ return { column, direction };
41
+ });
42
+ }
43
+ //# sourceMappingURL=indexing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexing.js","sourceRoot":"","sources":["../../src/utils/indexing.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,sBAAsB,CAAC,GAAG;IACxC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,2BAA2B;IACrE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IAEtB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAE1B,yCAAyC;IACzC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,IAAI,KAAK,GAAG;YAAE,MAAM,EAAE,CAAC;QAC3B,IAAI,IAAI,KAAK,GAAG;YAAE,MAAM,EAAE,CAAC;QAC3B,IAAI,IAAI,KAAK,GAAG,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7B,OAAO,GAAG,EAAE,CAAC;QACf,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,IAAI,CAAC;QAClB,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAEjD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACzB,kCAAkC;QAClC,MAAM,cAAc,GAAG,GAAG,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAE1E,sCAAsC;QACtC,MAAM,mBAAmB,GAAG,cAAc;YACxC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE;YAC3C,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAEf,2CAA2C;QAC3C,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC5F,IAAI,MAAM,GAAG,SAAS;YACpB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,6BAA6B;YAC5C,CAAC,CAAC,mBAAmB,CAAC,CAAC,sCAAsC;QAE/D,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,8BAA8B;QACjE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { DocumentWithId, Projection } from '../types.js';
2
+ export type ProjectionMode = 'include' | 'exclude';
3
+ /**
4
+ * Determines whether a projection is an inclusion or exclusion projection, matching MongoDB's
5
+ * rule: any explicit non-`_id` inclusion (1/true) puts it in inclusion mode; otherwise any
6
+ * explicit non-`_id` exclusion (0/false) puts it in exclusion mode; with only `_id` specified
7
+ * (or nothing), `_id: 0`/`false` means exclusion, everything else defaults to inclusion.
8
+ */
9
+ export declare function resolveProjectionMode<T>(projection: Projection<T>): ProjectionMode;
10
+ /**
11
+ * Applies a MongoDB-style projection to a single document, matching real MongoDB find()
12
+ * projection semantics: an empty/missing projection means no restriction, inclusion mode
13
+ * copies only listed fields (plus `_id` unless explicitly excluded), and exclusion mode copies
14
+ * everything except the listed fields. Supports dot-notation nested paths in both modes.
15
+ */
16
+ export declare function applyProjectionToDocument<T extends DocumentWithId>(doc: T, projection: Projection<T> | null | undefined): T;
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Determines whether a projection is an inclusion or exclusion projection, matching MongoDB's
3
+ * rule: any explicit non-`_id` inclusion (1/true) puts it in inclusion mode; otherwise any
4
+ * explicit non-`_id` exclusion (0/false) puts it in exclusion mode; with only `_id` specified
5
+ * (or nothing), `_id: 0`/`false` means exclusion, everything else defaults to inclusion.
6
+ */
7
+ export function resolveProjectionMode(projection) {
8
+ let hasExplicitInclusion = false;
9
+ let hasExplicitExclusion = false;
10
+ for (const key of Object.keys(projection)) {
11
+ if (key === '_id')
12
+ continue;
13
+ const value = projection[key];
14
+ if (value === 1 || value === true) {
15
+ hasExplicitInclusion = true;
16
+ break;
17
+ }
18
+ if (value === 0 || value === false) {
19
+ hasExplicitExclusion = true;
20
+ }
21
+ }
22
+ if (hasExplicitInclusion)
23
+ return 'include';
24
+ if (hasExplicitExclusion)
25
+ return 'exclude';
26
+ return projection._id === 0 || projection._id === false ? 'exclude' : 'include';
27
+ }
28
+ /**
29
+ * Applies a MongoDB-style projection to a single document, matching real MongoDB find()
30
+ * projection semantics: an empty/missing projection means no restriction, inclusion mode
31
+ * copies only listed fields (plus `_id` unless explicitly excluded), and exclusion mode copies
32
+ * everything except the listed fields. Supports dot-notation nested paths in both modes.
33
+ */
34
+ export function applyProjectionToDocument(doc, projection) {
35
+ if (!projection || Object.keys(projection).length === 0)
36
+ return doc;
37
+ const mode = resolveProjectionMode(projection);
38
+ const projectedDoc = {};
39
+ if (mode === 'include') {
40
+ for (const key in projection) {
41
+ const value = projection[key];
42
+ if (value !== 1 && value !== true)
43
+ continue;
44
+ if (key.includes('.')) {
45
+ const path = key.split('.');
46
+ let current = doc;
47
+ let target = projectedDoc;
48
+ for (let i = 0; i < path.length - 1; i++) {
49
+ const segment = path[i];
50
+ if (current[segment] === undefined || current[segment] === null)
51
+ break;
52
+ if (target[segment] === undefined) {
53
+ target[segment] = {};
54
+ }
55
+ current = current[segment];
56
+ target = target[segment];
57
+ }
58
+ const lastSegment = path[path.length - 1];
59
+ if (current && current[lastSegment] !== undefined) {
60
+ target[lastSegment] = current[lastSegment];
61
+ }
62
+ }
63
+ else if (key in doc) {
64
+ projectedDoc[key] = doc[key];
65
+ }
66
+ }
67
+ if (projection._id !== 0 && projection._id !== false && '_id' in doc) {
68
+ projectedDoc._id = doc._id;
69
+ }
70
+ }
71
+ else {
72
+ Object.assign(projectedDoc, doc);
73
+ for (const key in projection) {
74
+ const value = projection[key];
75
+ if (value !== 0 && value !== false)
76
+ continue;
77
+ if (key.includes('.')) {
78
+ const path = key.split('.');
79
+ let current = projectedDoc;
80
+ for (let i = 0; i < path.length - 1; i++) {
81
+ const segment = path[i];
82
+ if (current[segment] === undefined)
83
+ break;
84
+ current = current[segment];
85
+ }
86
+ const lastSegment = path[path.length - 1];
87
+ if (current && current[lastSegment] !== undefined) {
88
+ delete current[lastSegment];
89
+ }
90
+ }
91
+ else {
92
+ delete projectedDoc[key];
93
+ }
94
+ }
95
+ }
96
+ return projectedDoc;
97
+ }
98
+ //# sourceMappingURL=projection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection.js","sourceRoot":"","sources":["../../src/utils/projection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Shared query-operator registry used by in-memory ($match) filtering. Kept in sync with the
3
+ * operator set `buildComparisonCondition` (src/cursors/findCursor.ts) supports for SQL-generated
4
+ * find() filtering, so the two engines can't silently drift apart on what an operator means —
5
+ * see tests/operator-coverage.test.ts, which runs the same filter through both engines.
6
+ */
7
+ export declare const SUPPORTED_QUERY_OPERATORS: readonly ["$eq", "$ne", "$gt", "$gte", "$lt", "$lte", "$in", "$nin", "$all", "$exists", "$not", "$regex", "$size", "$type", "$mod"];
8
+ /**
9
+ * Evaluates a single query operator against a document's field value. Used for in-memory
10
+ * filtering (e.g. aggregation `$match`) — the SQL-generating side (`buildComparisonCondition`)
11
+ * emits SQL fragments instead of booleans and stays separate, but should support the same
12
+ * operator set.
13
+ */
14
+ export declare function evaluateOperator(op: string, docValue: unknown, opValue: unknown, regexOptions?: unknown): boolean;
15
+ /** Evaluates every operator in `ops` against `docValue`, ANDing the results together. */
16
+ export declare function evaluateOperators(docValue: unknown, ops: Record<string, unknown>): boolean;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Shared query-operator registry used by in-memory ($match) filtering. Kept in sync with the
3
+ * operator set `buildComparisonCondition` (src/cursors/findCursor.ts) supports for SQL-generated
4
+ * find() filtering, so the two engines can't silently drift apart on what an operator means —
5
+ * see tests/operator-coverage.test.ts, which runs the same filter through both engines.
6
+ */
7
+ export const SUPPORTED_QUERY_OPERATORS = [
8
+ '$eq',
9
+ '$ne',
10
+ '$gt',
11
+ '$gte',
12
+ '$lt',
13
+ '$lte',
14
+ '$in',
15
+ '$nin',
16
+ '$all',
17
+ '$exists',
18
+ '$not',
19
+ '$regex',
20
+ '$size',
21
+ '$type',
22
+ '$mod',
23
+ ];
24
+ function matchesBsonType(value, bsonType) {
25
+ switch (bsonType) {
26
+ case 1:
27
+ case 'double':
28
+ case 'number':
29
+ return typeof value === 'number';
30
+ case 2:
31
+ case 'string':
32
+ return typeof value === 'string';
33
+ case 3:
34
+ case 'object':
35
+ return (typeof value === 'object' &&
36
+ value !== null &&
37
+ !Array.isArray(value) &&
38
+ !(value instanceof Date));
39
+ case 4:
40
+ case 'array':
41
+ return Array.isArray(value);
42
+ case 8:
43
+ case 'bool':
44
+ case 'boolean':
45
+ return typeof value === 'boolean';
46
+ case 9:
47
+ case 'date':
48
+ return value instanceof Date;
49
+ case 10:
50
+ case 'null':
51
+ return value === null;
52
+ case 16:
53
+ case 'int':
54
+ case 18:
55
+ case 'long':
56
+ return typeof value === 'number' && Number.isInteger(value);
57
+ default:
58
+ return false;
59
+ }
60
+ }
61
+ /**
62
+ * Evaluates a single query operator against a document's field value. Used for in-memory
63
+ * filtering (e.g. aggregation `$match`) — the SQL-generating side (`buildComparisonCondition`)
64
+ * emits SQL fragments instead of booleans and stays separate, but should support the same
65
+ * operator set.
66
+ */
67
+ export function evaluateOperator(op, docValue, opValue, regexOptions) {
68
+ switch (op) {
69
+ case '$eq':
70
+ return JSON.stringify(docValue) === JSON.stringify(opValue);
71
+ case '$ne':
72
+ return JSON.stringify(docValue) !== JSON.stringify(opValue);
73
+ case '$gt':
74
+ return docValue > opValue;
75
+ case '$gte':
76
+ return docValue >= opValue;
77
+ case '$lt':
78
+ return docValue < opValue;
79
+ case '$lte':
80
+ return docValue <= opValue;
81
+ case '$in':
82
+ if (!Array.isArray(opValue))
83
+ return false;
84
+ if (Array.isArray(docValue)) {
85
+ return docValue.some((el) => opValue.some((v) => JSON.stringify(el) === JSON.stringify(v)));
86
+ }
87
+ return opValue.some((v) => JSON.stringify(v) === JSON.stringify(docValue));
88
+ case '$nin':
89
+ if (!Array.isArray(opValue))
90
+ return false;
91
+ if (Array.isArray(docValue)) {
92
+ return !docValue.some((el) => opValue.some((v) => JSON.stringify(el) === JSON.stringify(v)));
93
+ }
94
+ return !opValue.some((v) => JSON.stringify(v) === JSON.stringify(docValue));
95
+ case '$all':
96
+ if (!Array.isArray(opValue) || !Array.isArray(docValue))
97
+ return false;
98
+ return opValue.every((item) => docValue.some((el) => JSON.stringify(el) === JSON.stringify(item)));
99
+ case '$exists':
100
+ return opValue ? docValue !== undefined : docValue === undefined;
101
+ case '$not':
102
+ return !evaluateOperators(docValue, opValue);
103
+ case '$regex': {
104
+ const pattern = opValue instanceof RegExp
105
+ ? opValue
106
+ : new RegExp(opValue, typeof regexOptions === 'string' ? regexOptions : undefined);
107
+ return pattern.test(String(docValue));
108
+ }
109
+ case '$size':
110
+ return Array.isArray(docValue) && docValue.length === opValue;
111
+ case '$type': {
112
+ const types = Array.isArray(opValue) ? opValue : [opValue];
113
+ return types.some((t) => matchesBsonType(docValue, t));
114
+ }
115
+ case '$mod': {
116
+ if (!Array.isArray(opValue) || opValue.length !== 2 || typeof docValue !== 'number')
117
+ return false;
118
+ const [divisor, remainder] = opValue;
119
+ return Math.trunc(docValue) % divisor === remainder;
120
+ }
121
+ case '$options':
122
+ return true; // consumed alongside $regex, not an independent predicate
123
+ default:
124
+ return false; // unsupported operator — conservative: never matches, rather than silently no-op
125
+ }
126
+ }
127
+ /** Evaluates every operator in `ops` against `docValue`, ANDing the results together. */
128
+ export function evaluateOperators(docValue, ops) {
129
+ const regexOptions = ops['$options'];
130
+ for (const [op, opValue] of Object.entries(ops)) {
131
+ if (op === '$options')
132
+ continue;
133
+ if (!evaluateOperator(op, docValue, opValue, regexOptions))
134
+ return false;
135
+ }
136
+ return true;
137
+ }
138
+ //# sourceMappingURL=queryOperators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryOperators.js","sourceRoot":"","sources":["../../src/utils/queryOperators.ts"],"names":[],"mappings":"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"}