@objectql/driver-mongo 3.0.1 → 4.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.
package/MIGRATION.md ADDED
@@ -0,0 +1,213 @@
1
+ # MongoDB Driver Migration Guide (Phase 4)
2
+
3
+ ## Overview
4
+
5
+ The MongoDB driver has been migrated to support the standard `DriverInterface` from `@objectstack/spec` while maintaining full backward compatibility with the existing `Driver` interface from `@objectql/types`.
6
+
7
+ ## What Changed
8
+
9
+ ### 1. Driver Metadata
10
+
11
+ The driver now exposes metadata for ObjectStack compatibility:
12
+
13
+ ```typescript
14
+ const driver = new MongoDriver(config);
15
+ console.log(driver.name); // 'MongoDriver'
16
+ console.log(driver.version); // '3.0.1'
17
+ console.log(driver.supports); // { transactions: true, joins: false, ... }
18
+ ```
19
+
20
+ ### 2. Lifecycle Methods
21
+
22
+ New optional lifecycle methods for DriverInterface compatibility:
23
+
24
+ ```typescript
25
+ // Connect (ensures connection is established)
26
+ await driver.connect();
27
+
28
+ // Check connection health
29
+ const healthy = await driver.checkHealth(); // true/false
30
+
31
+ // Disconnect (existing method)
32
+ await driver.disconnect();
33
+ ```
34
+
35
+ ### 3. QueryAST Format Support
36
+
37
+ The driver now supports the new QueryAST format from `@objectstack/spec`:
38
+
39
+ #### Legacy UnifiedQuery Format (Still Supported)
40
+ ```typescript
41
+ const query = {
42
+ fields: ['name', 'age'],
43
+ filters: [['age', '>', 18]],
44
+ sort: [['name', 'asc']],
45
+ limit: 10,
46
+ skip: 0
47
+ };
48
+ ```
49
+
50
+ #### New QueryAST Format (Now Supported)
51
+ ```typescript
52
+ const query = {
53
+ object: 'users',
54
+ fields: ['name', 'age'],
55
+ filters: [['age', '>', 18]],
56
+ sort: [{ field: 'name', order: 'asc' }],
57
+ top: 10, // Instead of 'limit'
58
+ skip: 0
59
+ };
60
+ ```
61
+
62
+ ### Key Differences
63
+
64
+ | Aspect | Legacy Format | QueryAST Format |
65
+ |--------|--------------|-----------------|
66
+ | Limit | `limit: 10` | `top: 10` |
67
+ | Sort | `[['field', 'dir']]` | `[{field, order}]` |
68
+
69
+ ## Migration Strategy
70
+
71
+ The driver uses a **normalization layer** that automatically converts QueryAST format to the internal format:
72
+
73
+ ```typescript
74
+ private normalizeQuery(query: any): any {
75
+ // Converts 'top' → 'limit'
76
+ // Handles both sort formats
77
+ }
78
+ ```
79
+
80
+ This means:
81
+ - ✅ Existing code continues to work without changes
82
+ - ✅ New code can use QueryAST format
83
+ - ✅ Both formats work interchangeably
84
+ - ✅ No breaking changes
85
+
86
+ ## Usage Examples
87
+
88
+ ### Using Legacy Format (Unchanged)
89
+ ```typescript
90
+ import { MongoDriver } from '@objectql/driver-mongo';
91
+
92
+ const driver = new MongoDriver({
93
+ url: 'mongodb://localhost:27017',
94
+ dbName: 'mydb'
95
+ });
96
+
97
+ // Works as before
98
+ const results = await driver.find('users', {
99
+ filters: [['active', '=', true]],
100
+ sort: [['created_at', 'desc']],
101
+ limit: 20
102
+ });
103
+ ```
104
+
105
+ ### Using QueryAST Format (New)
106
+ ```typescript
107
+ import { MongoDriver } from '@objectql/driver-mongo';
108
+
109
+ const driver = new MongoDriver({
110
+ url: 'mongodb://localhost:27017',
111
+ dbName: 'mydb'
112
+ });
113
+
114
+ // New format
115
+ const results = await driver.find('users', {
116
+ filters: [['active', '=', true]],
117
+ sort: [{ field: 'created_at', order: 'desc' }],
118
+ top: 20
119
+ });
120
+ ```
121
+
122
+ ### Using with ObjectStack Kernel
123
+ ```typescript
124
+ import { ObjectQL } from '@objectql/core';
125
+ import { MongoDriver } from '@objectql/driver-mongo';
126
+
127
+ const app = new ObjectQL({
128
+ datasources: {
129
+ default: new MongoDriver({
130
+ url: 'mongodb://localhost:27017',
131
+ dbName: 'mydb'
132
+ })
133
+ }
134
+ });
135
+
136
+ await app.init();
137
+
138
+ // The kernel will use QueryAST format internally
139
+ const ctx = app.createContext({ userId: 'user123' });
140
+ const repo = ctx.object('users');
141
+ const users = await repo.find({ filters: [['active', '=', true]] });
142
+ ```
143
+
144
+ ## Testing
145
+
146
+ Comprehensive tests have been added in `test/queryast.test.ts`:
147
+
148
+ ```bash
149
+ npm test -- queryast.test.ts
150
+ ```
151
+
152
+ Test coverage includes:
153
+ - Driver metadata exposure
154
+ - Lifecycle methods (connect, checkHealth, disconnect)
155
+ - QueryAST format with `top` parameter
156
+ - Object-based sort notation
157
+ - Backward compatibility with legacy format
158
+ - Mixed format support
159
+ - Field mapping (id/_id conversion)
160
+
161
+ ## Implementation Details
162
+
163
+ ### Files Changed
164
+ - `package.json`: Added `@objectstack/spec@^0.2.0` dependency
165
+ - `src/index.ts`:
166
+ - Added driver metadata properties
167
+ - Added `normalizeQuery()` method (~45 lines)
168
+ - Added `connect()` and `checkHealth()` methods (~25 lines)
169
+ - Updated `find()` to use normalization
170
+ - Refactored internal `connect()` to `internalConnect()`
171
+ - `test/queryast.test.ts`: New comprehensive test suite (240+ lines)
172
+
173
+ ### Lines of Code
174
+ - **Added**: ~310 lines (including tests and docs)
175
+ - **Modified**: ~15 lines (method signatures and refactoring)
176
+ - **Deleted**: 0 lines
177
+
178
+ ## Driver Capabilities
179
+
180
+ The MongoDB driver supports:
181
+ - **Transactions**: ✅ Yes
182
+ - **Joins**: ❌ No (MongoDB is document-oriented)
183
+ - **Full-Text Search**: ✅ Yes (MongoDB text search)
184
+ - **JSON Fields**: ✅ Yes (native BSON support)
185
+ - **Array Fields**: ✅ Yes (native array support)
186
+
187
+ ## ID Field Mapping
188
+
189
+ The driver maintains smart ID mapping:
190
+ - API uses `id` field
191
+ - MongoDB uses `_id` field
192
+ - Automatic bidirectional conversion
193
+ - Both `id` and `_id` can be used in queries for backward compatibility
194
+
195
+ ## Next Steps
196
+
197
+ With MongoDB driver migration complete, the pattern is established for migrating other drivers:
198
+
199
+ 1. ✅ SQL Driver (completed)
200
+ 2. ✅ MongoDB Driver (completed)
201
+ 3. 🔜 Memory Driver (recommended next - used for testing)
202
+ 4. 🔜 Other drivers (bulk migration)
203
+
204
+ ## Backward Compatibility Guarantee
205
+
206
+ **100% backward compatible** - all existing code using the MongoDB driver will continue to work without any changes. The QueryAST support is additive, not replacing.
207
+
208
+ ## References
209
+
210
+ - [ObjectStack Spec Package](https://www.npmjs.com/package/@objectstack/spec)
211
+ - [SQL Driver Migration Guide](../sql/MIGRATION.md)
212
+ - [Runtime Integration Docs](../../foundation/core/RUNTIME_INTEGRATION.md)
213
+ - [Driver Interface Documentation](../../foundation/types/src/driver.ts)
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  MongoDB driver for ObjectQL. Supports basic CRUD, filtering, and aggregation pipelines on MongoDB.
4
4
 
5
+ **Now with ObjectStack QueryAST support!** This driver implements both the legacy `Driver` interface and the new `DriverInterface` from `@objectstack/spec` for seamless integration with the ObjectStack ecosystem.
6
+
5
7
  ## Installation
6
8
 
7
9
  ```bash
@@ -24,3 +26,59 @@ const objectql = new ObjectQL({
24
26
  }
25
27
  });
26
28
  ```
29
+
30
+ ## Features
31
+
32
+ - ✅ **100% Backward Compatible** - All existing code continues to work
33
+ - ✅ **QueryAST Support** - Supports the new `@objectstack/spec` query format
34
+ - ✅ **Smart ID Mapping** - Automatic conversion between `id` (API) and `_id` (MongoDB)
35
+ - ✅ **Full-Text Search** - MongoDB text search capabilities
36
+ - ✅ **Array & JSON Fields** - Native BSON support for complex data types
37
+ - ✅ **Aggregation Pipelines** - Native MongoDB aggregation support
38
+
39
+ ## Driver Metadata
40
+
41
+ ```typescript
42
+ console.log(driver.name); // 'MongoDriver'
43
+ console.log(driver.version); // '3.0.1'
44
+ console.log(driver.supports);
45
+ // {
46
+ // transactions: true,
47
+ // joins: false,
48
+ // fullTextSearch: true,
49
+ // jsonFields: true,
50
+ // arrayFields: true
51
+ // }
52
+ ```
53
+
54
+ ## QueryAST Format
55
+
56
+ The driver now supports both legacy and QueryAST formats:
57
+
58
+ ### Legacy Format
59
+ ```typescript
60
+ const results = await driver.find('users', {
61
+ filters: [['age', '>', 18]],
62
+ sort: [['name', 'asc']],
63
+ limit: 10,
64
+ skip: 0
65
+ });
66
+ ```
67
+
68
+ ### QueryAST Format
69
+ ```typescript
70
+ const results = await driver.find('users', {
71
+ filters: [['age', '>', 18]],
72
+ sort: [{ field: 'name', order: 'asc' }],
73
+ top: 10, // Instead of 'limit'
74
+ skip: 0
75
+ });
76
+ ```
77
+
78
+ ## Migration Guide
79
+
80
+ See [MIGRATION.md](./MIGRATION.md) for detailed information about the ObjectStack migration and QueryAST format support.
81
+
82
+ ## License
83
+
84
+ MIT
package/dist/index.d.ts CHANGED
@@ -1,5 +1,56 @@
1
+ /**
2
+ * ObjectQL
3
+ * Copyright (c) 2026-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
1
8
  import { Driver } from '@objectql/types';
2
- export declare class MongoDriver implements Driver {
9
+ import { DriverInterface, QueryAST } from '@objectstack/spec';
10
+ /**
11
+ * Command interface for executeCommand method
12
+ */
13
+ export interface Command {
14
+ type: 'create' | 'update' | 'delete' | 'bulkCreate' | 'bulkUpdate' | 'bulkDelete';
15
+ object: string;
16
+ data?: any;
17
+ id?: string | number;
18
+ ids?: Array<string | number>;
19
+ records?: any[];
20
+ updates?: Array<{
21
+ id: string | number;
22
+ data: any;
23
+ }>;
24
+ options?: any;
25
+ }
26
+ /**
27
+ * Command result interface
28
+ */
29
+ export interface CommandResult {
30
+ success: boolean;
31
+ data?: any;
32
+ affected: number;
33
+ error?: string;
34
+ }
35
+ /**
36
+ * MongoDB Driver for ObjectQL
37
+ *
38
+ * Implements both the legacy Driver interface from @objectql/types and
39
+ * the standard DriverInterface from @objectstack/spec for compatibility
40
+ * with the new kernel-based plugin system.
41
+ *
42
+ * The driver internally converts QueryAST format to MongoDB query format.
43
+ */
44
+ export declare class MongoDriver implements Driver, DriverInterface {
45
+ readonly name = "MongoDriver";
46
+ readonly version = "3.0.1";
47
+ readonly supports: {
48
+ transactions: boolean;
49
+ joins: boolean;
50
+ fullTextSearch: boolean;
51
+ jsonFields: boolean;
52
+ arrayFields: boolean;
53
+ };
3
54
  private client;
4
55
  private db?;
5
56
  private config;
@@ -8,7 +59,19 @@ export declare class MongoDriver implements Driver {
8
59
  url: string;
9
60
  dbName?: string;
10
61
  });
11
- private connect;
62
+ /**
63
+ * Internal connect method used in constructor
64
+ */
65
+ private internalConnect;
66
+ /**
67
+ * Connect to the database (for DriverInterface compatibility)
68
+ * This method ensures the connection is established.
69
+ */
70
+ connect(): Promise<void>;
71
+ /**
72
+ * Check database connection health
73
+ */
74
+ checkHealth(): Promise<boolean>;
12
75
  private getCollection;
13
76
  private normalizeId;
14
77
  /**
@@ -33,6 +96,15 @@ export declare class MongoDriver implements Driver {
33
96
  * Build a single MongoDB condition from field, operator, and value.
34
97
  */
35
98
  private buildSingleCondition;
99
+ /**
100
+ * Normalizes query format to support both legacy UnifiedQuery and QueryAST formats.
101
+ * This ensures backward compatibility while supporting the new @objectstack/spec interface.
102
+ *
103
+ * QueryAST format uses 'top' for limit, while UnifiedQuery uses 'limit'.
104
+ * QueryAST sort is array of {field, order}, while UnifiedQuery is array of [field, order].
105
+ * QueryAST uses 'aggregations', while legacy uses 'aggregate'.
106
+ */
107
+ private normalizeQuery;
36
108
  find(objectName: string, query: any, options?: any): Promise<any[]>;
37
109
  findOne(objectName: string, id: string | number, query?: any, options?: any): Promise<any>;
38
110
  create(objectName: string, data: any, options?: any): Promise<any>;
@@ -44,4 +116,44 @@ export declare class MongoDriver implements Driver {
44
116
  deleteMany(objectName: string, filters: any, options?: any): Promise<any>;
45
117
  aggregate(objectName: string, pipeline: any[], options?: any): Promise<any[]>;
46
118
  disconnect(): Promise<void>;
119
+ /**
120
+ * Execute a query using QueryAST (DriverInterface v4.0 method)
121
+ *
122
+ * This is the new standard method for query execution using the
123
+ * ObjectStack QueryAST format.
124
+ *
125
+ * @param ast - The QueryAST representing the query
126
+ * @param options - Optional execution options
127
+ * @returns Query results with value and count
128
+ */
129
+ executeQuery(ast: QueryAST, options?: any): Promise<{
130
+ value: any[];
131
+ count?: number;
132
+ }>;
133
+ /**
134
+ * Execute a command (DriverInterface v4.0 method)
135
+ *
136
+ * This method handles all mutation operations (create, update, delete)
137
+ * using a unified command interface.
138
+ *
139
+ * @param command - The command to execute
140
+ * @param options - Optional execution options
141
+ * @returns Command execution result
142
+ */
143
+ executeCommand(command: Command, options?: any): Promise<CommandResult>;
144
+ /**
145
+ * Convert FilterNode (QueryAST format) to legacy filter array format
146
+ * This allows reuse of existing filter logic while supporting new QueryAST
147
+ *
148
+ * @private
149
+ */
150
+ private convertFilterNodeToLegacy;
151
+ /**
152
+ * Execute command (alternative signature for compatibility)
153
+ *
154
+ * @param command - Command string or object
155
+ * @param parameters - Command parameters
156
+ * @param options - Execution options
157
+ */
158
+ execute(command: any, parameters?: any[], options?: any): Promise<any>;
47
159
  }