@push.rocks/smartmongo 2.2.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 +25 -25
- 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,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for all TsmDB errors
|
|
3
|
+
* Mirrors MongoDB driver error hierarchy
|
|
4
|
+
*/
|
|
5
|
+
export class TsmdbError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
codeName;
|
|
8
|
+
constructor(message, code, codeName) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'TsmdbError';
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.codeName = codeName;
|
|
13
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Error thrown during connection issues
|
|
18
|
+
*/
|
|
19
|
+
export class TsmdbConnectionError extends TsmdbError {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = 'TsmdbConnectionError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Error thrown when an operation times out
|
|
27
|
+
*/
|
|
28
|
+
export class TsmdbTimeoutError extends TsmdbError {
|
|
29
|
+
constructor(message) {
|
|
30
|
+
super(message, 50, 'MaxTimeMSExpired');
|
|
31
|
+
this.name = 'TsmdbTimeoutError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Error thrown during write operations
|
|
36
|
+
*/
|
|
37
|
+
export class TsmdbWriteError extends TsmdbError {
|
|
38
|
+
writeErrors;
|
|
39
|
+
result;
|
|
40
|
+
constructor(message, code, writeErrors) {
|
|
41
|
+
super(message, code);
|
|
42
|
+
this.name = 'TsmdbWriteError';
|
|
43
|
+
this.writeErrors = writeErrors;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Error thrown for duplicate key violations
|
|
48
|
+
*/
|
|
49
|
+
export class TsmdbDuplicateKeyError extends TsmdbWriteError {
|
|
50
|
+
keyPattern;
|
|
51
|
+
keyValue;
|
|
52
|
+
constructor(message, keyPattern, keyValue) {
|
|
53
|
+
super(message, 11000);
|
|
54
|
+
this.name = 'TsmdbDuplicateKeyError';
|
|
55
|
+
this.codeName = 'DuplicateKey';
|
|
56
|
+
this.keyPattern = keyPattern;
|
|
57
|
+
this.keyValue = keyValue;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Error thrown for bulk write failures
|
|
62
|
+
*/
|
|
63
|
+
export class TsmdbBulkWriteError extends TsmdbError {
|
|
64
|
+
writeErrors;
|
|
65
|
+
result;
|
|
66
|
+
constructor(message, writeErrors, result) {
|
|
67
|
+
super(message, 65);
|
|
68
|
+
this.name = 'TsmdbBulkWriteError';
|
|
69
|
+
this.writeErrors = writeErrors;
|
|
70
|
+
this.result = result;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Error thrown during transaction operations
|
|
75
|
+
*/
|
|
76
|
+
export class TsmdbTransactionError extends TsmdbError {
|
|
77
|
+
constructor(message, code) {
|
|
78
|
+
super(message, code);
|
|
79
|
+
this.name = 'TsmdbTransactionError';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Error thrown when a transaction is aborted due to conflict
|
|
84
|
+
*/
|
|
85
|
+
export class TsmdbWriteConflictError extends TsmdbTransactionError {
|
|
86
|
+
constructor(message = 'Write conflict during transaction') {
|
|
87
|
+
super(message, 112);
|
|
88
|
+
this.name = 'TsmdbWriteConflictError';
|
|
89
|
+
this.codeName = 'WriteConflict';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Error thrown for invalid arguments
|
|
94
|
+
*/
|
|
95
|
+
export class TsmdbArgumentError extends TsmdbError {
|
|
96
|
+
constructor(message) {
|
|
97
|
+
super(message);
|
|
98
|
+
this.name = 'TsmdbArgumentError';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Error thrown when an operation is not supported
|
|
103
|
+
*/
|
|
104
|
+
export class TsmdbNotSupportedError extends TsmdbError {
|
|
105
|
+
constructor(message) {
|
|
106
|
+
super(message, 115);
|
|
107
|
+
this.name = 'TsmdbNotSupportedError';
|
|
108
|
+
this.codeName = 'CommandNotSupported';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Error thrown when cursor is exhausted or closed
|
|
113
|
+
*/
|
|
114
|
+
export class TsmdbCursorError extends TsmdbError {
|
|
115
|
+
constructor(message) {
|
|
116
|
+
super(message);
|
|
117
|
+
this.name = 'TsmdbCursorError';
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Error thrown when a namespace (database.collection) is invalid
|
|
122
|
+
*/
|
|
123
|
+
export class TsmdbNamespaceError extends TsmdbError {
|
|
124
|
+
constructor(message) {
|
|
125
|
+
super(message, 73);
|
|
126
|
+
this.name = 'TsmdbNamespaceError';
|
|
127
|
+
this.codeName = 'InvalidNamespace';
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Error thrown when an index operation fails
|
|
132
|
+
*/
|
|
133
|
+
export class TsmdbIndexError extends TsmdbError {
|
|
134
|
+
constructor(message, code) {
|
|
135
|
+
super(message, code || 86);
|
|
136
|
+
this.name = 'TsmdbIndexError';
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Convert any error to a TsmdbError
|
|
141
|
+
*/
|
|
142
|
+
export function toTsmdbError(error) {
|
|
143
|
+
if (error instanceof TsmdbError) {
|
|
144
|
+
return error;
|
|
145
|
+
}
|
|
146
|
+
const tsmdbError = new TsmdbError(error.message || String(error));
|
|
147
|
+
if (error.code) {
|
|
148
|
+
tsmdbError.code = error.code;
|
|
149
|
+
}
|
|
150
|
+
if (error.codeName) {
|
|
151
|
+
tsmdbError.codeName = error.codeName;
|
|
152
|
+
}
|
|
153
|
+
return tsmdbError;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHNtZGJFcnJvcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90c21kYi9lcnJvcnMvVHNtZGJFcnJvcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFVBQVcsU0FBUSxLQUFLO0lBQzVCLElBQUksQ0FBVTtJQUNkLFFBQVEsQ0FBVTtJQUV6QixZQUFZLE9BQWUsRUFBRSxJQUFhLEVBQUUsUUFBaUI7UUFDM0QsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxZQUFZLENBQUM7UUFDekIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNwRCxDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxvQkFBcUIsU0FBUSxVQUFVO0lBQ2xELFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLHNCQUFzQixDQUFDO0lBQ3JDLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGlCQUFrQixTQUFRLFVBQVU7SUFDL0MsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLGtCQUFrQixDQUFDLENBQUM7UUFDdkMsSUFBSSxDQUFDLElBQUksR0FBRyxtQkFBbUIsQ0FBQztJQUNsQyxDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFnQixTQUFRLFVBQVU7SUFDdEMsV0FBVyxDQUFpQjtJQUM1QixNQUFNLENBQU87SUFFcEIsWUFBWSxPQUFlLEVBQUUsSUFBYSxFQUFFLFdBQTJCO1FBQ3JFLEtBQUssQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDckIsSUFBSSxDQUFDLElBQUksR0FBRyxpQkFBaUIsQ0FBQztRQUM5QixJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztJQUNqQyxDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxzQkFBdUIsU0FBUSxlQUFlO0lBQ2xELFVBQVUsQ0FBcUI7SUFDL0IsUUFBUSxDQUF1QjtJQUV0QyxZQUFZLE9BQWUsRUFBRSxVQUE4QixFQUFFLFFBQThCO1FBQ3pGLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdEIsSUFBSSxDQUFDLElBQUksR0FBRyx3QkFBd0IsQ0FBQztRQUNyQyxJQUFJLENBQUMsUUFBUSxHQUFHLGNBQWMsQ0FBQztRQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztJQUMzQixDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxtQkFBb0IsU0FBUSxVQUFVO0lBQzFDLFdBQVcsQ0FBZ0I7SUFDM0IsTUFBTSxDQUFNO0lBRW5CLFlBQVksT0FBZSxFQUFFLFdBQTBCLEVBQUUsTUFBVztRQUNsRSxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ25CLElBQUksQ0FBQyxJQUFJLEdBQUcscUJBQXFCLENBQUM7UUFDbEMsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFDL0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFDdkIsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8scUJBQXNCLFNBQVEsVUFBVTtJQUNuRCxZQUFZLE9BQWUsRUFBRSxJQUFhO1FBQ3hDLEtBQUssQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDckIsSUFBSSxDQUFDLElBQUksR0FBRyx1QkFBdUIsQ0FBQztJQUN0QyxDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyx1QkFBd0IsU0FBUSxxQkFBcUI7SUFDaEUsWUFBWSxVQUFrQixtQ0FBbUM7UUFDL0QsS0FBSyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNwQixJQUFJLENBQUMsSUFBSSxHQUFHLHlCQUF5QixDQUFDO1FBQ3RDLElBQUksQ0FBQyxRQUFRLEdBQUcsZUFBZSxDQUFDO0lBQ2xDLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGtCQUFtQixTQUFRLFVBQVU7SUFDaEQsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsb0JBQW9CLENBQUM7SUFDbkMsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sc0JBQXVCLFNBQVEsVUFBVTtJQUNwRCxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNwQixJQUFJLENBQUMsSUFBSSxHQUFHLHdCQUF3QixDQUFDO1FBQ3JDLElBQUksQ0FBQyxRQUFRLEdBQUcscUJBQXFCLENBQUM7SUFDeEMsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWlCLFNBQVEsVUFBVTtJQUM5QyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxrQkFBa0IsQ0FBQztJQUNqQyxDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxtQkFBb0IsU0FBUSxVQUFVO0lBQ2pELFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ25CLElBQUksQ0FBQyxJQUFJLEdBQUcscUJBQXFCLENBQUM7UUFDbEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxrQkFBa0IsQ0FBQztJQUNyQyxDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFnQixTQUFRLFVBQVU7SUFDN0MsWUFBWSxPQUFlLEVBQUUsSUFBYTtRQUN4QyxLQUFLLENBQUMsT0FBTyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQztRQUMzQixJQUFJLENBQUMsSUFBSSxHQUFHLGlCQUFpQixDQUFDO0lBQ2hDLENBQUM7Q0FDRjtBQVlEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FBQyxLQUFVO0lBQ3JDLElBQUksS0FBSyxZQUFZLFVBQVUsRUFBRSxDQUFDO1FBQ2hDLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUNELE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxDQUFDLEtBQUssQ0FBQyxPQUFPLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDbEUsSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZixVQUFVLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUM7SUFDL0IsQ0FBQztJQUNELElBQUksS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ25CLFVBQVUsQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQztJQUN2QyxDQUFDO0lBQ0QsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQyJ9
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as plugins from './
|
|
1
|
+
import * as plugins from './tsmdb.plugins.js';
|
|
2
2
|
export { plugins };
|
|
3
3
|
export { ObjectId, Binary, Timestamp, Long, Decimal128, UUID } from 'bson';
|
|
4
4
|
export * from './types/interfaces.js';
|
|
5
|
-
export * from './errors/
|
|
5
|
+
export * from './errors/TsmdbErrors.js';
|
|
6
6
|
export type { IStorageAdapter } from './storage/IStorageAdapter.js';
|
|
7
7
|
export { MemoryStorageAdapter } from './storage/MemoryStorageAdapter.js';
|
|
8
8
|
export { FileStorageAdapter } from './storage/FileStorageAdapter.js';
|
|
@@ -12,8 +12,8 @@ export { UpdateEngine } from './engine/UpdateEngine.js';
|
|
|
12
12
|
export { AggregationEngine } from './engine/AggregationEngine.js';
|
|
13
13
|
export { IndexEngine } from './engine/IndexEngine.js';
|
|
14
14
|
export { TransactionEngine } from './engine/TransactionEngine.js';
|
|
15
|
-
export {
|
|
16
|
-
export type {
|
|
15
|
+
export { TsmdbServer } from './server/TsmdbServer.js';
|
|
16
|
+
export type { ITsmdbServerOptions } from './server/TsmdbServer.js';
|
|
17
17
|
export { WireProtocol } from './server/WireProtocol.js';
|
|
18
18
|
export { CommandRouter } from './server/CommandRouter.js';
|
|
19
19
|
export type { ICommandHandler, IHandlerContext, ICursorState } from './server/CommandRouter.js';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// TsmDB - MongoDB Wire Protocol compatible in-memory database server
|
|
2
|
+
// Use the official MongoDB driver to connect to TsmdbServer
|
|
3
|
+
// Re-export plugins for external use
|
|
4
|
+
import * as plugins from './tsmdb.plugins.js';
|
|
5
|
+
export { plugins };
|
|
6
|
+
// Export BSON types for convenience
|
|
7
|
+
export { ObjectId, Binary, Timestamp, Long, Decimal128, UUID } from 'bson';
|
|
8
|
+
// Export all types
|
|
9
|
+
export * from './types/interfaces.js';
|
|
10
|
+
// Export errors
|
|
11
|
+
export * from './errors/TsmdbErrors.js';
|
|
12
|
+
export { MemoryStorageAdapter } from './storage/MemoryStorageAdapter.js';
|
|
13
|
+
export { FileStorageAdapter } from './storage/FileStorageAdapter.js';
|
|
14
|
+
export { OpLog } from './storage/OpLog.js';
|
|
15
|
+
// Export engines
|
|
16
|
+
export { QueryEngine } from './engine/QueryEngine.js';
|
|
17
|
+
export { UpdateEngine } from './engine/UpdateEngine.js';
|
|
18
|
+
export { AggregationEngine } from './engine/AggregationEngine.js';
|
|
19
|
+
export { IndexEngine } from './engine/IndexEngine.js';
|
|
20
|
+
export { TransactionEngine } from './engine/TransactionEngine.js';
|
|
21
|
+
// Export server (the main entry point for using TsmDB)
|
|
22
|
+
export { TsmdbServer } from './server/TsmdbServer.js';
|
|
23
|
+
// Export wire protocol utilities (for advanced usage)
|
|
24
|
+
export { WireProtocol } from './server/WireProtocol.js';
|
|
25
|
+
export { CommandRouter } from './server/CommandRouter.js';
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy90c21kYi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxRUFBcUU7QUFDckUsNERBQTREO0FBRTVELHFDQUFxQztBQUNyQyxPQUFPLEtBQUssT0FBTyxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztBQUVuQixvQ0FBb0M7QUFDcEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRTNFLG1CQUFtQjtBQUNuQixjQUFjLHVCQUF1QixDQUFDO0FBRXRDLGdCQUFnQjtBQUNoQixjQUFjLHlCQUF5QixDQUFDO0FBSXhDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUUzQyxpQkFBaUI7QUFDakIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDdEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFbEUsdURBQXVEO0FBQ3ZELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUd0RCxzREFBc0Q7QUFDdEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQyJ9
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import * as plugins from '../
|
|
1
|
+
import * as plugins from '../tsmdb.plugins.js';
|
|
2
2
|
import type { IStorageAdapter } from '../storage/IStorageAdapter.js';
|
|
3
3
|
import type { IParsedCommand } from './WireProtocol.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { TsmdbServer } from './TsmdbServer.js';
|
|
5
5
|
/**
|
|
6
6
|
* Handler context passed to command handlers
|
|
7
7
|
*/
|
|
8
8
|
export interface IHandlerContext {
|
|
9
9
|
storage: IStorageAdapter;
|
|
10
|
-
server:
|
|
10
|
+
server: TsmdbServer;
|
|
11
11
|
database: string;
|
|
12
12
|
command: plugins.bson.Document;
|
|
13
13
|
documentSequences?: Map<string, plugins.bson.Document[]>;
|
|
@@ -27,7 +27,7 @@ export declare class CommandRouter {
|
|
|
27
27
|
private handlers;
|
|
28
28
|
private cursors;
|
|
29
29
|
private cursorIdCounter;
|
|
30
|
-
constructor(storage: IStorageAdapter, server:
|
|
30
|
+
constructor(storage: IStorageAdapter, server: TsmdbServer);
|
|
31
31
|
/**
|
|
32
32
|
* Register all command handlers
|
|
33
33
|
*/
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as plugins from '../tsmdb.plugins.js';
|
|
2
|
+
// Import handlers
|
|
3
|
+
import { HelloHandler } from './handlers/HelloHandler.js';
|
|
4
|
+
import { InsertHandler } from './handlers/InsertHandler.js';
|
|
5
|
+
import { FindHandler } from './handlers/FindHandler.js';
|
|
6
|
+
import { UpdateHandler } from './handlers/UpdateHandler.js';
|
|
7
|
+
import { DeleteHandler } from './handlers/DeleteHandler.js';
|
|
8
|
+
import { AggregateHandler } from './handlers/AggregateHandler.js';
|
|
9
|
+
import { IndexHandler } from './handlers/IndexHandler.js';
|
|
10
|
+
import { AdminHandler } from './handlers/AdminHandler.js';
|
|
11
|
+
/**
|
|
12
|
+
* CommandRouter - Routes incoming commands to appropriate handlers
|
|
13
|
+
*/
|
|
14
|
+
export class CommandRouter {
|
|
15
|
+
storage;
|
|
16
|
+
server;
|
|
17
|
+
handlers = new Map();
|
|
18
|
+
// Cursor state for getMore operations
|
|
19
|
+
cursors = new Map();
|
|
20
|
+
cursorIdCounter = BigInt(1);
|
|
21
|
+
constructor(storage, server) {
|
|
22
|
+
this.storage = storage;
|
|
23
|
+
this.server = server;
|
|
24
|
+
this.registerHandlers();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Register all command handlers
|
|
28
|
+
*/
|
|
29
|
+
registerHandlers() {
|
|
30
|
+
// Create handler instances with shared state
|
|
31
|
+
const helloHandler = new HelloHandler();
|
|
32
|
+
const findHandler = new FindHandler(this.cursors, () => this.cursorIdCounter++);
|
|
33
|
+
const insertHandler = new InsertHandler();
|
|
34
|
+
const updateHandler = new UpdateHandler();
|
|
35
|
+
const deleteHandler = new DeleteHandler();
|
|
36
|
+
const aggregateHandler = new AggregateHandler(this.cursors, () => this.cursorIdCounter++);
|
|
37
|
+
const indexHandler = new IndexHandler();
|
|
38
|
+
const adminHandler = new AdminHandler();
|
|
39
|
+
// Handshake commands
|
|
40
|
+
this.handlers.set('hello', helloHandler);
|
|
41
|
+
this.handlers.set('ismaster', helloHandler);
|
|
42
|
+
this.handlers.set('isMaster', helloHandler);
|
|
43
|
+
// CRUD commands
|
|
44
|
+
this.handlers.set('find', findHandler);
|
|
45
|
+
this.handlers.set('insert', insertHandler);
|
|
46
|
+
this.handlers.set('update', updateHandler);
|
|
47
|
+
this.handlers.set('delete', deleteHandler);
|
|
48
|
+
this.handlers.set('findAndModify', updateHandler);
|
|
49
|
+
this.handlers.set('getMore', findHandler);
|
|
50
|
+
this.handlers.set('killCursors', findHandler);
|
|
51
|
+
// Aggregation
|
|
52
|
+
this.handlers.set('aggregate', aggregateHandler);
|
|
53
|
+
this.handlers.set('count', findHandler);
|
|
54
|
+
this.handlers.set('distinct', findHandler);
|
|
55
|
+
// Index operations
|
|
56
|
+
this.handlers.set('createIndexes', indexHandler);
|
|
57
|
+
this.handlers.set('dropIndexes', indexHandler);
|
|
58
|
+
this.handlers.set('listIndexes', indexHandler);
|
|
59
|
+
// Admin/Database operations
|
|
60
|
+
this.handlers.set('ping', adminHandler);
|
|
61
|
+
this.handlers.set('listDatabases', adminHandler);
|
|
62
|
+
this.handlers.set('listCollections', adminHandler);
|
|
63
|
+
this.handlers.set('drop', adminHandler);
|
|
64
|
+
this.handlers.set('dropDatabase', adminHandler);
|
|
65
|
+
this.handlers.set('create', adminHandler);
|
|
66
|
+
this.handlers.set('serverStatus', adminHandler);
|
|
67
|
+
this.handlers.set('buildInfo', adminHandler);
|
|
68
|
+
this.handlers.set('whatsmyuri', adminHandler);
|
|
69
|
+
this.handlers.set('getLog', adminHandler);
|
|
70
|
+
this.handlers.set('hostInfo', adminHandler);
|
|
71
|
+
this.handlers.set('replSetGetStatus', adminHandler);
|
|
72
|
+
this.handlers.set('isMaster', helloHandler);
|
|
73
|
+
this.handlers.set('saslStart', adminHandler);
|
|
74
|
+
this.handlers.set('saslContinue', adminHandler);
|
|
75
|
+
this.handlers.set('endSessions', adminHandler);
|
|
76
|
+
this.handlers.set('abortTransaction', adminHandler);
|
|
77
|
+
this.handlers.set('commitTransaction', adminHandler);
|
|
78
|
+
this.handlers.set('collStats', adminHandler);
|
|
79
|
+
this.handlers.set('dbStats', adminHandler);
|
|
80
|
+
this.handlers.set('connectionStatus', adminHandler);
|
|
81
|
+
this.handlers.set('currentOp', adminHandler);
|
|
82
|
+
this.handlers.set('collMod', adminHandler);
|
|
83
|
+
this.handlers.set('renameCollection', adminHandler);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Route a command to its handler
|
|
87
|
+
*/
|
|
88
|
+
async route(parsedCommand) {
|
|
89
|
+
const { commandName, command, database, documentSequences } = parsedCommand;
|
|
90
|
+
// Create handler context
|
|
91
|
+
const context = {
|
|
92
|
+
storage: this.storage,
|
|
93
|
+
server: this.server,
|
|
94
|
+
database,
|
|
95
|
+
command,
|
|
96
|
+
documentSequences,
|
|
97
|
+
};
|
|
98
|
+
// Find handler
|
|
99
|
+
const handler = this.handlers.get(commandName);
|
|
100
|
+
if (!handler) {
|
|
101
|
+
// Unknown command
|
|
102
|
+
return {
|
|
103
|
+
ok: 0,
|
|
104
|
+
errmsg: `no such command: '${commandName}'`,
|
|
105
|
+
code: 59,
|
|
106
|
+
codeName: 'CommandNotFound',
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
return await handler.handle(context);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
// Handle known error types
|
|
114
|
+
if (error.code) {
|
|
115
|
+
return {
|
|
116
|
+
ok: 0,
|
|
117
|
+
errmsg: error.message,
|
|
118
|
+
code: error.code,
|
|
119
|
+
codeName: error.codeName || 'UnknownError',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
// Generic error
|
|
123
|
+
return {
|
|
124
|
+
ok: 0,
|
|
125
|
+
errmsg: error.message || 'Internal error',
|
|
126
|
+
code: 1,
|
|
127
|
+
codeName: 'InternalError',
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tbWFuZFJvdXRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL3RzbWRiL3NlcnZlci9Db21tYW5kUm91dGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFLL0Msa0JBQWtCO0FBQ2xCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDNUQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDbEUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzFELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQW9CMUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sYUFBYTtJQUNoQixPQUFPLENBQWtCO0lBQ3pCLE1BQU0sQ0FBYztJQUNwQixRQUFRLEdBQWlDLElBQUksR0FBRyxFQUFFLENBQUM7SUFFM0Qsc0NBQXNDO0lBQzlCLE9BQU8sR0FBOEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUMvQyxlQUFlLEdBQVcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRTVDLFlBQVksT0FBd0IsRUFBRSxNQUFtQjtRQUN2RCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRUQ7O09BRUc7SUFDSyxnQkFBZ0I7UUFDdEIsNkNB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
|
|
@@ -2,7 +2,7 @@ import type { IStorageAdapter } from '../storage/IStorageAdapter.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Server configuration options
|
|
4
4
|
*/
|
|
5
|
-
export interface
|
|
5
|
+
export interface ITsmdbServerOptions {
|
|
6
6
|
/** Port to listen on (default: 27017) */
|
|
7
7
|
port?: number;
|
|
8
8
|
/** Host to bind to (default: 127.0.0.1) */
|
|
@@ -17,24 +17,24 @@ export interface ICongoServerOptions {
|
|
|
17
17
|
persistIntervalMs?: number;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* TsmdbServer - MongoDB Wire Protocol compatible server
|
|
21
21
|
*
|
|
22
22
|
* This server implements the MongoDB wire protocol (OP_MSG) to allow
|
|
23
23
|
* official MongoDB drivers to connect and perform operations.
|
|
24
24
|
*
|
|
25
25
|
* @example
|
|
26
26
|
* ```typescript
|
|
27
|
-
* import {
|
|
27
|
+
* import { TsmdbServer } from '@push.rocks/smartmongo/tsmdb';
|
|
28
28
|
* import { MongoClient } from 'mongodb';
|
|
29
29
|
*
|
|
30
|
-
* const server = new
|
|
30
|
+
* const server = new TsmdbServer({ port: 27017 });
|
|
31
31
|
* await server.start();
|
|
32
32
|
*
|
|
33
33
|
* const client = new MongoClient('mongodb://127.0.0.1:27017');
|
|
34
34
|
* await client.connect();
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
|
-
export declare class
|
|
37
|
+
export declare class TsmdbServer {
|
|
38
38
|
private options;
|
|
39
39
|
private server;
|
|
40
40
|
private storage;
|
|
@@ -43,7 +43,7 @@ export declare class CongoServer {
|
|
|
43
43
|
private connectionIdCounter;
|
|
44
44
|
private isRunning;
|
|
45
45
|
private startTime;
|
|
46
|
-
constructor(options?:
|
|
46
|
+
constructor(options?: ITsmdbServerOptions);
|
|
47
47
|
/**
|
|
48
48
|
* Get the storage adapter (for testing/debugging)
|
|
49
49
|
*/
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import * as net from 'net';
|
|
2
|
+
import * as plugins from '../tsmdb.plugins.js';
|
|
3
|
+
import { WireProtocol, OP_QUERY } from './WireProtocol.js';
|
|
4
|
+
import { CommandRouter } from './CommandRouter.js';
|
|
5
|
+
import { MemoryStorageAdapter } from '../storage/MemoryStorageAdapter.js';
|
|
6
|
+
import { FileStorageAdapter } from '../storage/FileStorageAdapter.js';
|
|
7
|
+
/**
|
|
8
|
+
* TsmdbServer - MongoDB Wire Protocol compatible server
|
|
9
|
+
*
|
|
10
|
+
* This server implements the MongoDB wire protocol (OP_MSG) to allow
|
|
11
|
+
* official MongoDB drivers to connect and perform operations.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { TsmdbServer } from '@push.rocks/smartmongo/tsmdb';
|
|
16
|
+
* import { MongoClient } from 'mongodb';
|
|
17
|
+
*
|
|
18
|
+
* const server = new TsmdbServer({ port: 27017 });
|
|
19
|
+
* await server.start();
|
|
20
|
+
*
|
|
21
|
+
* const client = new MongoClient('mongodb://127.0.0.1:27017');
|
|
22
|
+
* await client.connect();
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export class TsmdbServer {
|
|
26
|
+
options;
|
|
27
|
+
server = null;
|
|
28
|
+
storage;
|
|
29
|
+
commandRouter;
|
|
30
|
+
connections = new Map();
|
|
31
|
+
connectionIdCounter = 0;
|
|
32
|
+
isRunning = false;
|
|
33
|
+
startTime = new Date();
|
|
34
|
+
constructor(options = {}) {
|
|
35
|
+
this.options = {
|
|
36
|
+
port: options.port ?? 27017,
|
|
37
|
+
host: options.host ?? '127.0.0.1',
|
|
38
|
+
storage: options.storage ?? 'memory',
|
|
39
|
+
storagePath: options.storagePath ?? './data',
|
|
40
|
+
persistPath: options.persistPath ?? '',
|
|
41
|
+
persistIntervalMs: options.persistIntervalMs ?? 60000,
|
|
42
|
+
};
|
|
43
|
+
// Create storage adapter
|
|
44
|
+
if (this.options.storage === 'file') {
|
|
45
|
+
this.storage = new FileStorageAdapter(this.options.storagePath);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this.storage = new MemoryStorageAdapter({
|
|
49
|
+
persistPath: this.options.persistPath || undefined,
|
|
50
|
+
persistIntervalMs: this.options.persistPath ? this.options.persistIntervalMs : undefined,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// Create command router
|
|
54
|
+
this.commandRouter = new CommandRouter(this.storage, this);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get the storage adapter (for testing/debugging)
|
|
58
|
+
*/
|
|
59
|
+
getStorage() {
|
|
60
|
+
return this.storage;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get server uptime in seconds
|
|
64
|
+
*/
|
|
65
|
+
getUptime() {
|
|
66
|
+
return Math.floor((Date.now() - this.startTime.getTime()) / 1000);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get current connection count
|
|
70
|
+
*/
|
|
71
|
+
getConnectionCount() {
|
|
72
|
+
return this.connections.size;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Start the server
|
|
76
|
+
*/
|
|
77
|
+
async start() {
|
|
78
|
+
if (this.isRunning) {
|
|
79
|
+
throw new Error('Server is already running');
|
|
80
|
+
}
|
|
81
|
+
// Initialize storage
|
|
82
|
+
await this.storage.initialize();
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
this.server = net.createServer((socket) => {
|
|
85
|
+
this.handleConnection(socket);
|
|
86
|
+
});
|
|
87
|
+
this.server.on('error', (err) => {
|
|
88
|
+
if (!this.isRunning) {
|
|
89
|
+
reject(err);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
console.error('Server error:', err);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
this.server.listen(this.options.port, this.options.host, () => {
|
|
96
|
+
this.isRunning = true;
|
|
97
|
+
this.startTime = new Date();
|
|
98
|
+
resolve();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Stop the server
|
|
104
|
+
*/
|
|
105
|
+
async stop() {
|
|
106
|
+
if (!this.isRunning || !this.server) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// Close all connections
|
|
110
|
+
for (const conn of this.connections.values()) {
|
|
111
|
+
conn.socket.destroy();
|
|
112
|
+
}
|
|
113
|
+
this.connections.clear();
|
|
114
|
+
// Close storage
|
|
115
|
+
await this.storage.close();
|
|
116
|
+
return new Promise((resolve) => {
|
|
117
|
+
this.server.close(() => {
|
|
118
|
+
this.isRunning = false;
|
|
119
|
+
this.server = null;
|
|
120
|
+
resolve();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Handle a new client connection
|
|
126
|
+
*/
|
|
127
|
+
handleConnection(socket) {
|
|
128
|
+
const connectionId = ++this.connectionIdCounter;
|
|
129
|
+
const state = {
|
|
130
|
+
id: connectionId,
|
|
131
|
+
socket,
|
|
132
|
+
buffer: Buffer.alloc(0),
|
|
133
|
+
authenticated: true, // No auth required for now
|
|
134
|
+
database: 'test',
|
|
135
|
+
};
|
|
136
|
+
this.connections.set(connectionId, state);
|
|
137
|
+
socket.on('data', (data) => {
|
|
138
|
+
this.handleData(state, Buffer.isBuffer(data) ? data : Buffer.from(data));
|
|
139
|
+
});
|
|
140
|
+
socket.on('close', () => {
|
|
141
|
+
this.connections.delete(connectionId);
|
|
142
|
+
});
|
|
143
|
+
socket.on('error', (err) => {
|
|
144
|
+
// Connection errors are expected when clients disconnect
|
|
145
|
+
this.connections.delete(connectionId);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Handle incoming data from a client
|
|
150
|
+
*/
|
|
151
|
+
handleData(state, data) {
|
|
152
|
+
// Append new data to buffer
|
|
153
|
+
state.buffer = Buffer.concat([state.buffer, data]);
|
|
154
|
+
// Process messages from buffer
|
|
155
|
+
this.processMessages(state);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Process complete messages from the buffer
|
|
159
|
+
*/
|
|
160
|
+
async processMessages(state) {
|
|
161
|
+
while (state.buffer.length >= 16) {
|
|
162
|
+
try {
|
|
163
|
+
const result = WireProtocol.parseMessage(state.buffer);
|
|
164
|
+
if (!result) {
|
|
165
|
+
// Not enough data for a complete message
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
const { command, bytesConsumed } = result;
|
|
169
|
+
// Remove processed bytes from buffer
|
|
170
|
+
state.buffer = state.buffer.subarray(bytesConsumed);
|
|
171
|
+
// Process the command
|
|
172
|
+
const response = await this.commandRouter.route(command);
|
|
173
|
+
// Encode and send response
|
|
174
|
+
let responseBuffer;
|
|
175
|
+
if (command.opCode === OP_QUERY) {
|
|
176
|
+
// Legacy OP_QUERY gets OP_REPLY response
|
|
177
|
+
responseBuffer = WireProtocol.encodeOpReplyResponse(command.requestID, [response]);
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
// OP_MSG gets OP_MSG response
|
|
181
|
+
responseBuffer = WireProtocol.encodeOpMsgResponse(command.requestID, response);
|
|
182
|
+
}
|
|
183
|
+
if (!state.socket.destroyed) {
|
|
184
|
+
state.socket.write(responseBuffer);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
// Send error response
|
|
189
|
+
const errorResponse = WireProtocol.encodeErrorResponse(0, // We don't have the requestID at this point
|
|
190
|
+
1, error.message || 'Internal error');
|
|
191
|
+
if (!state.socket.destroyed) {
|
|
192
|
+
state.socket.write(errorResponse);
|
|
193
|
+
}
|
|
194
|
+
// Clear buffer on parse errors to avoid infinite loops
|
|
195
|
+
if (error.message?.includes('opCode') || error.message?.includes('section')) {
|
|
196
|
+
state.buffer = Buffer.alloc(0);
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get the connection URI for this server
|
|
204
|
+
*/
|
|
205
|
+
getConnectionUri() {
|
|
206
|
+
return `mongodb://${this.options.host}:${this.options.port}`;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Check if the server is running
|
|
210
|
+
*/
|
|
211
|
+
get running() {
|
|
212
|
+
return this.isRunning;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get the port the server is listening on
|
|
216
|
+
*/
|
|
217
|
+
get port() {
|
|
218
|
+
return this.options.port;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Get the host the server is bound to
|
|
222
|
+
*/
|
|
223
|
+
get host() {
|
|
224
|
+
return this.options.host;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHNtZGJTZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90c21kYi9zZXJ2ZXIvVHNtZGJTZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEdBQUcsTUFBTSxLQUFLLENBQUM7QUFDM0IsT0FBTyxLQUFLLE9BQU8sTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzNELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNuRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUMxRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQWdDdEU7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsTUFBTSxPQUFPLFdBQVc7SUFDZCxPQUFPLENBQWdDO0lBQ3ZDLE1BQU0sR0FBc0IsSUFBSSxDQUFDO0lBQ2pDLE9BQU8sQ0FBa0I7SUFDekIsYUFBYSxDQUFnQjtJQUM3QixXQUFXLEdBQWtDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDdkQsbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0lBQ3hCLFNBQVMsR0FBRyxLQUFLLENBQUM7SUFDbEIsU0FBUyxHQUFTLElBQUksSUFBSSxFQUFFLENBQUM7SUFFckMsWUFBWSxVQUErQixFQUFFO1FBQzNDLElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksSUFBSSxLQUFLO1lBQzNCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxJQUFJLFdBQVc7WUFDakMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPLElBQUksUUFBUTtZQUNwQyxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVcsSUFBSSxRQUFRO1lBQzVDLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVyxJQUFJLEVBQUU7WUFDdEMs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
|