@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 +213 -0
- package/README.md +58 -0
- package/dist/index.d.ts +114 -2
- package/dist/index.js +293 -12
- package/dist/index.js.map +1 -1
- package/jest.config.js +8 -0
- package/package.json +3 -2
- package/src/index.ts +342 -11
- package/test/index.test.ts +258 -1
- package/test/integration.test.ts +8 -0
- package/test/queryast.test.ts +322 -0
- package/tsconfig.tsbuildinfo +1 -1
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
|
-
|
|
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
|
-
|
|
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
|
}
|