@push.rocks/smartmongo 2.1.0 → 3.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +1 -1
- package/dist_ts/index.js +3 -3
- package/dist_ts/tsmdb/engine/AggregationEngine.js +189 -0
- package/dist_ts/tsmdb/engine/IndexEngine.js +376 -0
- package/dist_ts/tsmdb/engine/QueryEngine.js +271 -0
- package/dist_ts/{congodb → tsmdb}/engine/TransactionEngine.d.ts +1 -1
- package/dist_ts/tsmdb/engine/TransactionEngine.js +287 -0
- package/dist_ts/tsmdb/engine/UpdateEngine.js +461 -0
- package/dist_ts/{congodb/errors/CongoErrors.d.ts → tsmdb/errors/TsmdbErrors.d.ts} +16 -16
- package/dist_ts/tsmdb/errors/TsmdbErrors.js +155 -0
- package/dist_ts/{congodb → tsmdb}/index.d.ts +4 -4
- package/dist_ts/tsmdb/index.js +26 -0
- package/dist_ts/{congodb → tsmdb}/server/CommandRouter.d.ts +4 -4
- package/dist_ts/tsmdb/server/CommandRouter.js +132 -0
- package/dist_ts/{congodb/server/CongoServer.d.ts → tsmdb/server/TsmdbServer.d.ts} +6 -6
- package/dist_ts/tsmdb/server/TsmdbServer.js +227 -0
- package/dist_ts/{congodb → tsmdb}/server/WireProtocol.d.ts +1 -1
- package/dist_ts/tsmdb/server/WireProtocol.js +298 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/AdminHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/AdminHandler.js +568 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/AggregateHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/AggregateHandler.js +277 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/DeleteHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/DeleteHandler.js +83 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/FindHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/FindHandler.js +261 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/HelloHandler.d.ts +1 -1
- package/dist_ts/{congodb → tsmdb}/server/handlers/HelloHandler.js +2 -2
- package/dist_ts/{congodb → tsmdb}/server/handlers/IndexHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/IndexHandler.js +183 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/InsertHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/InsertHandler.js +76 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/UpdateHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/UpdateHandler.js +270 -0
- package/dist_ts/tsmdb/server/handlers/index.js +10 -0
- package/dist_ts/{congodb → tsmdb}/server/index.d.ts +2 -2
- package/dist_ts/tsmdb/server/index.js +7 -0
- package/dist_ts/{congodb → tsmdb}/storage/FileStorageAdapter.d.ts +2 -2
- package/dist_ts/tsmdb/storage/FileStorageAdapter.js +396 -0
- package/dist_ts/{congodb → tsmdb}/storage/IStorageAdapter.d.ts +2 -2
- package/dist_ts/{congodb → tsmdb}/storage/IStorageAdapter.js +1 -1
- package/dist_ts/{congodb → tsmdb}/storage/MemoryStorageAdapter.d.ts +2 -2
- package/dist_ts/tsmdb/storage/MemoryStorageAdapter.js +367 -0
- package/dist_ts/{congodb → tsmdb}/storage/OpLog.d.ts +1 -1
- package/dist_ts/tsmdb/storage/OpLog.js +221 -0
- package/dist_ts/tsmdb/tsmdb.plugins.js +14 -0
- package/dist_ts/{congodb → tsmdb}/types/interfaces.d.ts +3 -3
- package/dist_ts/{congodb → tsmdb}/types/interfaces.js +1 -1
- package/package.json +1 -1
- package/readme.hints.md +7 -12
- package/readme.md +398 -44
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +2 -2
- package/ts/{congodb → tsmdb}/engine/AggregationEngine.ts +1 -1
- package/ts/{congodb → tsmdb}/engine/IndexEngine.ts +7 -7
- package/ts/{congodb → tsmdb}/engine/QueryEngine.ts +1 -1
- package/ts/{congodb → tsmdb}/engine/TransactionEngine.ts +12 -12
- package/ts/{congodb → tsmdb}/engine/UpdateEngine.ts +1 -1
- package/ts/{congodb/errors/CongoErrors.ts → tsmdb/errors/TsmdbErrors.ts} +34 -34
- package/ts/{congodb → tsmdb}/index.ts +7 -7
- package/ts/{congodb → tsmdb}/server/CommandRouter.ts +5 -5
- package/ts/{congodb/server/CongoServer.ts → tsmdb/server/TsmdbServer.ts} +8 -8
- package/ts/{congodb → tsmdb}/server/WireProtocol.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/AdminHandler.ts +6 -6
- package/ts/{congodb → tsmdb}/server/handlers/AggregateHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/DeleteHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/FindHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/HelloHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/IndexHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/InsertHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/UpdateHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/index.ts +2 -2
- package/ts/{congodb → tsmdb}/storage/FileStorageAdapter.ts +2 -2
- package/ts/{congodb → tsmdb}/storage/IStorageAdapter.ts +2 -2
- package/ts/{congodb → tsmdb}/storage/MemoryStorageAdapter.ts +2 -2
- package/ts/{congodb → tsmdb}/storage/OpLog.ts +1 -1
- package/ts/{congodb → tsmdb}/types/interfaces.ts +3 -3
- package/dist_ts/congodb/congodb.plugins.js +0 -14
- package/dist_ts/congodb/engine/AggregationEngine.js +0 -189
- package/dist_ts/congodb/engine/IndexEngine.js +0 -376
- package/dist_ts/congodb/engine/QueryEngine.js +0 -271
- package/dist_ts/congodb/engine/TransactionEngine.js +0 -287
- package/dist_ts/congodb/engine/UpdateEngine.js +0 -461
- package/dist_ts/congodb/errors/CongoErrors.js +0 -155
- package/dist_ts/congodb/index.js +0 -26
- package/dist_ts/congodb/server/CommandRouter.js +0 -132
- package/dist_ts/congodb/server/CongoServer.js +0 -227
- package/dist_ts/congodb/server/WireProtocol.js +0 -298
- package/dist_ts/congodb/server/handlers/AdminHandler.js +0 -568
- package/dist_ts/congodb/server/handlers/AggregateHandler.js +0 -277
- package/dist_ts/congodb/server/handlers/DeleteHandler.js +0 -83
- package/dist_ts/congodb/server/handlers/FindHandler.js +0 -261
- package/dist_ts/congodb/server/handlers/IndexHandler.js +0 -183
- package/dist_ts/congodb/server/handlers/InsertHandler.js +0 -76
- package/dist_ts/congodb/server/handlers/UpdateHandler.js +0 -270
- package/dist_ts/congodb/server/handlers/index.js +0 -10
- package/dist_ts/congodb/server/index.js +0 -7
- package/dist_ts/congodb/storage/FileStorageAdapter.js +0 -396
- package/dist_ts/congodb/storage/MemoryStorageAdapter.js +0 -367
- package/dist_ts/congodb/storage/OpLog.js +0 -221
- /package/dist_ts/{congodb → tsmdb}/engine/AggregationEngine.d.ts +0 -0
- /package/dist_ts/{congodb → tsmdb}/engine/IndexEngine.d.ts +0 -0
- /package/dist_ts/{congodb → tsmdb}/engine/QueryEngine.d.ts +0 -0
- /package/dist_ts/{congodb → tsmdb}/engine/UpdateEngine.d.ts +0 -0
- /package/dist_ts/{congodb → tsmdb}/server/handlers/index.d.ts +0 -0
- /package/dist_ts/{congodb/congodb.plugins.d.ts → tsmdb/tsmdb.plugins.d.ts} +0 -0
- /package/ts/{congodb → tsmdb}/server/handlers/index.ts +0 -0
- /package/ts/{congodb/congodb.plugins.ts → tsmdb/tsmdb.plugins.ts} +0 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import * as plugins from '../../tsmdb.plugins.js';
|
|
2
|
+
import { AggregationEngine } from '../../engine/AggregationEngine.js';
|
|
3
|
+
/**
|
|
4
|
+
* AggregateHandler - Handles aggregate command
|
|
5
|
+
*/
|
|
6
|
+
export class AggregateHandler {
|
|
7
|
+
cursors;
|
|
8
|
+
nextCursorId;
|
|
9
|
+
constructor(cursors, nextCursorId) {
|
|
10
|
+
this.cursors = cursors;
|
|
11
|
+
this.nextCursorId = nextCursorId;
|
|
12
|
+
}
|
|
13
|
+
async handle(context) {
|
|
14
|
+
const { storage, database, command } = context;
|
|
15
|
+
const collection = command.aggregate;
|
|
16
|
+
const pipeline = command.pipeline || [];
|
|
17
|
+
const cursor = command.cursor || {};
|
|
18
|
+
const batchSize = cursor.batchSize || 101;
|
|
19
|
+
// Validate
|
|
20
|
+
if (typeof collection !== 'string' && collection !== 1) {
|
|
21
|
+
return {
|
|
22
|
+
ok: 0,
|
|
23
|
+
errmsg: 'aggregate command requires a collection name or 1',
|
|
24
|
+
code: 2,
|
|
25
|
+
codeName: 'BadValue',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (!Array.isArray(pipeline)) {
|
|
29
|
+
return {
|
|
30
|
+
ok: 0,
|
|
31
|
+
errmsg: 'pipeline must be an array',
|
|
32
|
+
code: 2,
|
|
33
|
+
codeName: 'BadValue',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
// Get source documents
|
|
38
|
+
let documents = [];
|
|
39
|
+
if (collection === 1 || collection === '1') {
|
|
40
|
+
// Database-level aggregation (e.g., $listLocalSessions)
|
|
41
|
+
documents = [];
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// Collection-level aggregation
|
|
45
|
+
const exists = await storage.collectionExists(database, collection);
|
|
46
|
+
if (exists) {
|
|
47
|
+
documents = await storage.findAll(database, collection);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Handle $lookup and $graphLookup stages that reference other collections
|
|
51
|
+
const processedPipeline = await this.preprocessPipeline(storage, database, pipeline, documents);
|
|
52
|
+
// Run aggregation
|
|
53
|
+
let results;
|
|
54
|
+
// Check for special stages that we handle manually
|
|
55
|
+
if (this.hasSpecialStages(pipeline)) {
|
|
56
|
+
results = await this.executeWithSpecialStages(storage, database, documents, pipeline);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
results = AggregationEngine.aggregate(documents, processedPipeline);
|
|
60
|
+
}
|
|
61
|
+
// Handle $out and $merge stages
|
|
62
|
+
const lastStage = pipeline[pipeline.length - 1];
|
|
63
|
+
if (lastStage && lastStage.$out) {
|
|
64
|
+
await this.handleOut(storage, database, results, lastStage.$out);
|
|
65
|
+
return { ok: 1, cursor: { id: plugins.bson.Long.fromNumber(0), ns: `${database}.${collection}`, firstBatch: [] } };
|
|
66
|
+
}
|
|
67
|
+
if (lastStage && lastStage.$merge) {
|
|
68
|
+
await this.handleMerge(storage, database, results, lastStage.$merge);
|
|
69
|
+
return { ok: 1, cursor: { id: plugins.bson.Long.fromNumber(0), ns: `${database}.${collection}`, firstBatch: [] } };
|
|
70
|
+
}
|
|
71
|
+
// Build cursor response
|
|
72
|
+
const effectiveBatchSize = Math.min(batchSize, results.length);
|
|
73
|
+
const firstBatch = results.slice(0, effectiveBatchSize);
|
|
74
|
+
const remaining = results.slice(effectiveBatchSize);
|
|
75
|
+
let cursorId = BigInt(0);
|
|
76
|
+
if (remaining.length > 0) {
|
|
77
|
+
cursorId = this.nextCursorId();
|
|
78
|
+
this.cursors.set(cursorId, {
|
|
79
|
+
id: cursorId,
|
|
80
|
+
database,
|
|
81
|
+
collection: typeof collection === 'string' ? collection : '$cmd.aggregate',
|
|
82
|
+
documents: remaining,
|
|
83
|
+
position: 0,
|
|
84
|
+
batchSize,
|
|
85
|
+
createdAt: new Date(),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
ok: 1,
|
|
90
|
+
cursor: {
|
|
91
|
+
id: plugins.bson.Long.fromBigInt(cursorId),
|
|
92
|
+
ns: `${database}.${typeof collection === 'string' ? collection : '$cmd.aggregate'}`,
|
|
93
|
+
firstBatch,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return {
|
|
99
|
+
ok: 0,
|
|
100
|
+
errmsg: error.message || 'Aggregation failed',
|
|
101
|
+
code: 1,
|
|
102
|
+
codeName: 'InternalError',
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Preprocess pipeline to handle cross-collection lookups
|
|
108
|
+
*/
|
|
109
|
+
async preprocessPipeline(storage, database, pipeline, documents) {
|
|
110
|
+
// For now, return the pipeline as-is
|
|
111
|
+
// Cross-collection lookups are handled in executeWithSpecialStages
|
|
112
|
+
return pipeline;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Check if pipeline has stages that need special handling
|
|
116
|
+
*/
|
|
117
|
+
hasSpecialStages(pipeline) {
|
|
118
|
+
return pipeline.some(stage => stage.$lookup ||
|
|
119
|
+
stage.$graphLookup ||
|
|
120
|
+
stage.$unionWith);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Execute pipeline with special stage handling
|
|
124
|
+
*/
|
|
125
|
+
async executeWithSpecialStages(storage, database, documents, pipeline) {
|
|
126
|
+
let results = [...documents];
|
|
127
|
+
for (const stage of pipeline) {
|
|
128
|
+
if (stage.$lookup) {
|
|
129
|
+
const lookupSpec = stage.$lookup;
|
|
130
|
+
const fromCollection = lookupSpec.from;
|
|
131
|
+
// Get foreign collection documents
|
|
132
|
+
const foreignExists = await storage.collectionExists(database, fromCollection);
|
|
133
|
+
const foreignDocs = foreignExists
|
|
134
|
+
? await storage.findAll(database, fromCollection)
|
|
135
|
+
: [];
|
|
136
|
+
results = AggregationEngine.executeLookup(results, lookupSpec, foreignDocs);
|
|
137
|
+
}
|
|
138
|
+
else if (stage.$graphLookup) {
|
|
139
|
+
const graphLookupSpec = stage.$graphLookup;
|
|
140
|
+
const fromCollection = graphLookupSpec.from;
|
|
141
|
+
const foreignExists = await storage.collectionExists(database, fromCollection);
|
|
142
|
+
const foreignDocs = foreignExists
|
|
143
|
+
? await storage.findAll(database, fromCollection)
|
|
144
|
+
: [];
|
|
145
|
+
results = AggregationEngine.executeGraphLookup(results, graphLookupSpec, foreignDocs);
|
|
146
|
+
}
|
|
147
|
+
else if (stage.$unionWith) {
|
|
148
|
+
let unionSpec = stage.$unionWith;
|
|
149
|
+
let unionColl;
|
|
150
|
+
let unionPipeline;
|
|
151
|
+
if (typeof unionSpec === 'string') {
|
|
152
|
+
unionColl = unionSpec;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
unionColl = unionSpec.coll;
|
|
156
|
+
unionPipeline = unionSpec.pipeline;
|
|
157
|
+
}
|
|
158
|
+
const unionExists = await storage.collectionExists(database, unionColl);
|
|
159
|
+
const unionDocs = unionExists
|
|
160
|
+
? await storage.findAll(database, unionColl)
|
|
161
|
+
: [];
|
|
162
|
+
results = AggregationEngine.executeUnionWith(results, unionDocs, unionPipeline);
|
|
163
|
+
}
|
|
164
|
+
else if (stage.$facet) {
|
|
165
|
+
// Execute each facet pipeline separately
|
|
166
|
+
const facetResults = {};
|
|
167
|
+
for (const [facetName, facetPipeline] of Object.entries(stage.$facet)) {
|
|
168
|
+
const facetDocs = await this.executeWithSpecialStages(storage, database, results, facetPipeline);
|
|
169
|
+
facetResults[facetName] = facetDocs;
|
|
170
|
+
}
|
|
171
|
+
results = [facetResults];
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// Regular stage - pass to mingo
|
|
175
|
+
results = AggregationEngine.aggregate(results, [stage]);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return results;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Handle $out stage - write results to a collection
|
|
182
|
+
*/
|
|
183
|
+
async handleOut(storage, database, results, outSpec) {
|
|
184
|
+
let targetDb = database;
|
|
185
|
+
let targetColl;
|
|
186
|
+
if (typeof outSpec === 'string') {
|
|
187
|
+
targetColl = outSpec;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
targetDb = outSpec.db || database;
|
|
191
|
+
targetColl = outSpec.coll;
|
|
192
|
+
}
|
|
193
|
+
// Drop existing collection
|
|
194
|
+
await storage.dropCollection(targetDb, targetColl);
|
|
195
|
+
// Create new collection and insert results
|
|
196
|
+
await storage.createCollection(targetDb, targetColl);
|
|
197
|
+
for (const doc of results) {
|
|
198
|
+
if (!doc._id) {
|
|
199
|
+
doc._id = new plugins.bson.ObjectId();
|
|
200
|
+
}
|
|
201
|
+
await storage.insertOne(targetDb, targetColl, doc);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Handle $merge stage - merge results into a collection
|
|
206
|
+
*/
|
|
207
|
+
async handleMerge(storage, database, results, mergeSpec) {
|
|
208
|
+
let targetDb = database;
|
|
209
|
+
let targetColl;
|
|
210
|
+
if (typeof mergeSpec === 'string') {
|
|
211
|
+
targetColl = mergeSpec;
|
|
212
|
+
}
|
|
213
|
+
else if (typeof mergeSpec.into === 'string') {
|
|
214
|
+
targetColl = mergeSpec.into;
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
targetDb = mergeSpec.into.db || database;
|
|
218
|
+
targetColl = mergeSpec.into.coll;
|
|
219
|
+
}
|
|
220
|
+
const on = mergeSpec.on || '_id';
|
|
221
|
+
const whenMatched = mergeSpec.whenMatched || 'merge';
|
|
222
|
+
const whenNotMatched = mergeSpec.whenNotMatched || 'insert';
|
|
223
|
+
// Ensure target collection exists
|
|
224
|
+
await storage.createCollection(targetDb, targetColl);
|
|
225
|
+
for (const doc of results) {
|
|
226
|
+
// Find matching document
|
|
227
|
+
const existingDocs = await storage.findAll(targetDb, targetColl);
|
|
228
|
+
const onFields = Array.isArray(on) ? on : [on];
|
|
229
|
+
let matchingDoc = null;
|
|
230
|
+
for (const existing of existingDocs) {
|
|
231
|
+
let matches = true;
|
|
232
|
+
for (const field of onFields) {
|
|
233
|
+
if (JSON.stringify(existing[field]) !== JSON.stringify(doc[field])) {
|
|
234
|
+
matches = false;
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (matches) {
|
|
239
|
+
matchingDoc = existing;
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (matchingDoc) {
|
|
244
|
+
// Handle whenMatched
|
|
245
|
+
if (whenMatched === 'replace') {
|
|
246
|
+
await storage.updateById(targetDb, targetColl, matchingDoc._id, doc);
|
|
247
|
+
}
|
|
248
|
+
else if (whenMatched === 'keepExisting') {
|
|
249
|
+
// Do nothing
|
|
250
|
+
}
|
|
251
|
+
else if (whenMatched === 'merge') {
|
|
252
|
+
const merged = { ...matchingDoc, ...doc };
|
|
253
|
+
await storage.updateById(targetDb, targetColl, matchingDoc._id, merged);
|
|
254
|
+
}
|
|
255
|
+
else if (whenMatched === 'fail') {
|
|
256
|
+
throw new Error('Document matched but whenMatched is fail');
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
// Handle whenNotMatched
|
|
261
|
+
if (whenNotMatched === 'insert') {
|
|
262
|
+
if (!doc._id) {
|
|
263
|
+
doc._id = new plugins.bson.ObjectId();
|
|
264
|
+
}
|
|
265
|
+
await storage.insertOne(targetDb, targetColl, doc);
|
|
266
|
+
}
|
|
267
|
+
else if (whenNotMatched === 'discard') {
|
|
268
|
+
// Do nothing
|
|
269
|
+
}
|
|
270
|
+
else if (whenNotMatched === 'fail') {
|
|
271
|
+
throw new Error('Document not matched but whenNotMatched is fail');
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWdncmVnYXRlSGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3RzbWRiL3NlcnZlci9oYW5kbGVycy9BZ2dyZWdhdGVIYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFFbEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFFdEU7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBQ25CLE9BQU8sQ0FBNEI7SUFDbkMsWUFBWSxDQUFlO0lBRW5DLFlBQ0UsT0FBa0MsRUFDbEMsWUFBMEI7UUFFMUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7SUFDbkMsQ0FBQztJQUVELEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBd0I7UUFDbkMsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDO1FBRS9DLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7UUFDckMsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUM7UUFDeEMsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7UUFDcEMsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLFNBQVMsSUFBSSxHQUFHLENBQUM7UUFFMUMsV0FBVztRQUNYLElBQUksT0FBTyxVQUFVLEtBQUssUUFBUSxJQUFJLFVBQVUsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN2RCxPQUFPO2dCQUNMLEVBQUUsRUFBRSxDQUFDO2dCQUNMLE1BQU0sRUFBRSxtREFBbUQ7Z0JBQzNELElBQUksRUFBRSxDQUFDO2dCQUNQLFFBQVEsRUFBRSxVQUFVO2FBQ3JCLENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxD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
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import * as plugins from '../../tsmdb.plugins.js';
|
|
2
|
+
import { QueryEngine } from '../../engine/QueryEngine.js';
|
|
3
|
+
/**
|
|
4
|
+
* DeleteHandler - Handles delete commands
|
|
5
|
+
*/
|
|
6
|
+
export class DeleteHandler {
|
|
7
|
+
async handle(context) {
|
|
8
|
+
const { storage, database, command, documentSequences } = context;
|
|
9
|
+
const collection = command.delete;
|
|
10
|
+
if (typeof collection !== 'string') {
|
|
11
|
+
return {
|
|
12
|
+
ok: 0,
|
|
13
|
+
errmsg: 'delete command requires a collection name',
|
|
14
|
+
code: 2,
|
|
15
|
+
codeName: 'BadValue',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
// Get deletes from command or document sequences
|
|
19
|
+
let deletes = command.deletes || [];
|
|
20
|
+
// Check for OP_MSG document sequences
|
|
21
|
+
if (documentSequences && documentSequences.has('deletes')) {
|
|
22
|
+
deletes = documentSequences.get('deletes');
|
|
23
|
+
}
|
|
24
|
+
if (!Array.isArray(deletes) || deletes.length === 0) {
|
|
25
|
+
return {
|
|
26
|
+
ok: 0,
|
|
27
|
+
errmsg: 'delete command requires deletes array',
|
|
28
|
+
code: 2,
|
|
29
|
+
codeName: 'BadValue',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const ordered = command.ordered !== false;
|
|
33
|
+
const writeErrors = [];
|
|
34
|
+
let totalDeleted = 0;
|
|
35
|
+
// Check if collection exists
|
|
36
|
+
const exists = await storage.collectionExists(database, collection);
|
|
37
|
+
if (!exists) {
|
|
38
|
+
// Collection doesn't exist, return success with 0 deleted
|
|
39
|
+
return { ok: 1, n: 0 };
|
|
40
|
+
}
|
|
41
|
+
for (let i = 0; i < deletes.length; i++) {
|
|
42
|
+
const deleteSpec = deletes[i];
|
|
43
|
+
const filter = deleteSpec.q || deleteSpec.filter || {};
|
|
44
|
+
const limit = deleteSpec.limit;
|
|
45
|
+
// limit: 0 means delete all matching, limit: 1 means delete one
|
|
46
|
+
const deleteAll = limit === 0;
|
|
47
|
+
try {
|
|
48
|
+
// Get all documents
|
|
49
|
+
const documents = await storage.findAll(database, collection);
|
|
50
|
+
// Apply filter
|
|
51
|
+
const matchingDocs = QueryEngine.filter(documents, filter);
|
|
52
|
+
if (matchingDocs.length === 0) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
// Determine which documents to delete
|
|
56
|
+
const docsToDelete = deleteAll ? matchingDocs : matchingDocs.slice(0, 1);
|
|
57
|
+
// Delete the documents
|
|
58
|
+
const idsToDelete = docsToDelete.map(doc => doc._id);
|
|
59
|
+
const deleted = await storage.deleteByIds(database, collection, idsToDelete);
|
|
60
|
+
totalDeleted += deleted;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
writeErrors.push({
|
|
64
|
+
index: i,
|
|
65
|
+
code: error.code || 1,
|
|
66
|
+
errmsg: error.message || 'Delete failed',
|
|
67
|
+
});
|
|
68
|
+
if (ordered) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const response = {
|
|
74
|
+
ok: 1,
|
|
75
|
+
n: totalDeleted,
|
|
76
|
+
};
|
|
77
|
+
if (writeErrors.length > 0) {
|
|
78
|
+
response.writeErrors = writeErrors;
|
|
79
|
+
}
|
|
80
|
+
return response;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVsZXRlSGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3RzbWRiL3NlcnZlci9oYW5kbGVycy9EZWxldGVIYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFFbEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRTFEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUFDeEIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUF3QjtRQUNuQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFFbEUsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztRQUNsQyxJQUFJLE9BQU8sVUFBVSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ25DLE9BQU87Z0JBQ0wsRUFBRSxFQUFFLENBQUM7Z0JBQ0wsTUFBTSxFQUFFLDJDQUEyQztnQkFDbkQsSUFBSSxFQUFFLENBQUM7Z0JBQ1AsUUFBUSxFQUFFLFVBQVU7YUFDckIsQ0FBQztRQUNKLENBQUM7UUFFRCxpREFBaUQ7UUFDakQsSUFBSSxPQUFPLEdBQTRCLE9BQU8sQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDO1FBRTdELHNDQUFzQztRQUN0QyxJQUFJLGlCQUFpQixJQUFJLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQzFELE9BQU8sR0FBRyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFFLENBQUM7UUFDOUMsQ0FBQztRQUVELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDcEQsT0FBTztnQkFDTCxFQUFFLEVBQUUsQ0FBQztnQkFDTCxNQUFNLEVB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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as plugins from '../../
|
|
1
|
+
import * as plugins from '../../tsmdb.plugins.js';
|
|
2
2
|
import type { ICommandHandler, IHandlerContext, ICursorState } from '../CommandRouter.js';
|
|
3
3
|
/**
|
|
4
4
|
* FindHandler - Handles find, getMore, killCursors, count, distinct commands
|