@rebasepro/server-mongodb 0.0.1-canary.4d4fb3e
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/LICENSE +6 -0
- package/dist/index.es.js +875 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +878 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/server-mongodb/src/connection.d.ts +35 -0
- package/dist/server-mongodb/src/connection.d.ts.map +1 -0
- package/dist/server-mongodb/src/db/MongoConditionBuilder.d.ts +64 -0
- package/dist/server-mongodb/src/db/MongoConditionBuilder.d.ts.map +1 -0
- package/dist/server-mongodb/src/db/MongoEntityService.d.ts +98 -0
- package/dist/server-mongodb/src/db/MongoEntityService.d.ts.map +1 -0
- package/dist/server-mongodb/src/factory.d.ts +139 -0
- package/dist/server-mongodb/src/factory.d.ts.map +1 -0
- package/dist/server-mongodb/src/index.d.ts +17 -0
- package/dist/server-mongodb/src/index.d.ts.map +1 -0
- package/dist/server-mongodb/src/services/MongoDriver.d.ts +81 -0
- package/dist/server-mongodb/src/services/MongoDriver.d.ts.map +1 -0
- package/dist/server-mongodb/src/services/MongoRealtimeService.d.ts +65 -0
- package/dist/server-mongodb/src/services/MongoRealtimeService.d.ts.map +1 -0
- package/dist/server-mongodb/src/useMongoDriver.d.ts +18 -0
- package/dist/server-mongodb/src/useMongoDriver.d.ts.map +1 -0
- package/dist/server-mongodb/src/utils.d.ts +10 -0
- package/dist/server-mongodb/src/utils.d.ts.map +1 -0
- package/dist/types/src/controllers/analytics_controller.d.ts +8 -0
- package/dist/types/src/controllers/analytics_controller.d.ts.map +1 -0
- package/dist/types/src/controllers/auth.d.ts +118 -0
- package/dist/types/src/controllers/auth.d.ts.map +1 -0
- package/dist/types/src/controllers/client.d.ts +59 -0
- package/dist/types/src/controllers/client.d.ts.map +1 -0
- package/dist/types/src/controllers/collection_registry.d.ts +45 -0
- package/dist/types/src/controllers/collection_registry.d.ts.map +1 -0
- package/dist/types/src/controllers/customization_controller.d.ts +55 -0
- package/dist/types/src/controllers/customization_controller.d.ts.map +1 -0
- package/dist/types/src/controllers/data.d.ts +142 -0
- package/dist/types/src/controllers/data.d.ts.map +1 -0
- package/dist/types/src/controllers/data_driver.d.ts +169 -0
- package/dist/types/src/controllers/data_driver.d.ts.map +1 -0
- package/dist/types/src/controllers/database_admin.d.ts +12 -0
- package/dist/types/src/controllers/database_admin.d.ts.map +1 -0
- package/dist/types/src/controllers/dialogs_controller.d.ts +37 -0
- package/dist/types/src/controllers/dialogs_controller.d.ts.map +1 -0
- package/dist/types/src/controllers/effective_role.d.ts +5 -0
- package/dist/types/src/controllers/effective_role.d.ts.map +1 -0
- package/dist/types/src/controllers/index.d.ts +18 -0
- package/dist/types/src/controllers/index.d.ts.map +1 -0
- package/dist/types/src/controllers/local_config_persistence.d.ts +21 -0
- package/dist/types/src/controllers/local_config_persistence.d.ts.map +1 -0
- package/dist/types/src/controllers/navigation.d.ts +214 -0
- package/dist/types/src/controllers/navigation.d.ts.map +1 -0
- package/dist/types/src/controllers/registry.d.ts +52 -0
- package/dist/types/src/controllers/registry.d.ts.map +1 -0
- package/dist/types/src/controllers/side_dialogs_controller.d.ts +68 -0
- package/dist/types/src/controllers/side_dialogs_controller.d.ts.map +1 -0
- package/dist/types/src/controllers/side_entity_controller.d.ts +90 -0
- package/dist/types/src/controllers/side_entity_controller.d.ts.map +1 -0
- package/dist/types/src/controllers/snackbar.d.ts +25 -0
- package/dist/types/src/controllers/snackbar.d.ts.map +1 -0
- package/dist/types/src/controllers/storage.d.ts +174 -0
- package/dist/types/src/controllers/storage.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +5 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/rebase_context.d.ts +102 -0
- package/dist/types/src/rebase_context.d.ts.map +1 -0
- package/dist/types/src/types/backend.d.ts +534 -0
- package/dist/types/src/types/backend.d.ts.map +1 -0
- package/dist/types/src/types/builders.d.ts +15 -0
- package/dist/types/src/types/builders.d.ts.map +1 -0
- package/dist/types/src/types/chips.d.ts +6 -0
- package/dist/types/src/types/chips.d.ts.map +1 -0
- package/dist/types/src/types/collections.d.ts +813 -0
- package/dist/types/src/types/collections.d.ts.map +1 -0
- package/dist/types/src/types/data_source.d.ts +65 -0
- package/dist/types/src/types/data_source.d.ts.map +1 -0
- package/dist/types/src/types/entities.d.ts +146 -0
- package/dist/types/src/types/entities.d.ts.map +1 -0
- package/dist/types/src/types/entity_actions.d.ts +99 -0
- package/dist/types/src/types/entity_actions.d.ts.map +1 -0
- package/dist/types/src/types/entity_callbacks.d.ts +174 -0
- package/dist/types/src/types/entity_callbacks.d.ts.map +1 -0
- package/dist/types/src/types/entity_link_builder.d.ts +8 -0
- package/dist/types/src/types/entity_link_builder.d.ts.map +1 -0
- package/dist/types/src/types/entity_overrides.d.ts +10 -0
- package/dist/types/src/types/entity_overrides.d.ts.map +1 -0
- package/dist/types/src/types/entity_views.d.ts +62 -0
- package/dist/types/src/types/entity_views.d.ts.map +1 -0
- package/dist/types/src/types/export_import.d.ts +22 -0
- package/dist/types/src/types/export_import.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +23 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/src/types/locales.d.ts +5 -0
- package/dist/types/src/types/locales.d.ts.map +1 -0
- package/dist/types/src/types/modify_collections.d.ts +6 -0
- package/dist/types/src/types/modify_collections.d.ts.map +1 -0
- package/dist/types/src/types/plugins.d.ts +226 -0
- package/dist/types/src/types/plugins.d.ts.map +1 -0
- package/dist/types/src/types/properties.d.ts +1092 -0
- package/dist/types/src/types/properties.d.ts.map +1 -0
- package/dist/types/src/types/property_config.d.ts +71 -0
- package/dist/types/src/types/property_config.d.ts.map +1 -0
- package/dist/types/src/types/relations.d.ts +337 -0
- package/dist/types/src/types/relations.d.ts.map +1 -0
- package/dist/types/src/types/slots.d.ts +229 -0
- package/dist/types/src/types/slots.d.ts.map +1 -0
- package/dist/types/src/types/translations.d.ts +827 -0
- package/dist/types/src/types/translations.d.ts.map +1 -0
- package/dist/types/src/types/user_management_delegate.d.ts +121 -0
- package/dist/types/src/types/user_management_delegate.d.ts.map +1 -0
- package/dist/types/src/types/websockets.d.ts +79 -0
- package/dist/types/src/types/websockets.d.ts.map +1 -0
- package/dist/types/src/users/index.d.ts +3 -0
- package/dist/types/src/users/index.d.ts.map +1 -0
- package/dist/types/src/users/roles.d.ts +23 -0
- package/dist/types/src/users/roles.d.ts.map +1 -0
- package/dist/types/src/users/user.d.ts +47 -0
- package/dist/types/src/users/user.d.ts.map +1 -0
- package/package.json +81 -0
- package/src/connection.ts +60 -0
- package/src/db/MongoConditionBuilder.ts +181 -0
- package/src/db/MongoEntityService.ts +350 -0
- package/src/factory.ts +274 -0
- package/src/index.ts +24 -0
- package/src/services/MongoDriver.ts +267 -0
- package/src/services/MongoRealtimeService.ts +295 -0
- package/src/useMongoDriver.ts +516 -0
- package/src/utils.ts +28 -0
|
@@ -0,0 +1,878 @@
|
|
|
1
|
+
(function(global, factory) {
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("mongodb")) : typeof define === "function" && define.amd ? define(["exports", "mongodb"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["Rebase MongoDB"] = {}, global.mongodb));
|
|
3
|
+
})(this, function(exports2, mongodb) {
|
|
4
|
+
"use strict";
|
|
5
|
+
class MongoDBConnection {
|
|
6
|
+
constructor(db, client) {
|
|
7
|
+
this.db = db;
|
|
8
|
+
this.client = client;
|
|
9
|
+
}
|
|
10
|
+
type = "mongodb";
|
|
11
|
+
get isConnected() {
|
|
12
|
+
try {
|
|
13
|
+
const clientInternal = this.client;
|
|
14
|
+
return clientInternal.topology?.isConnected?.() ?? false;
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async close() {
|
|
20
|
+
await this.client.close();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function createMongoDBConnection(connectionString, databaseName) {
|
|
24
|
+
const client = new mongodb.MongoClient(connectionString);
|
|
25
|
+
await client.connect();
|
|
26
|
+
const db = client.db(databaseName);
|
|
27
|
+
return new MongoDBConnection(db, client);
|
|
28
|
+
}
|
|
29
|
+
const REBASE_TO_MONGO_OP = {
|
|
30
|
+
"<": "$lt",
|
|
31
|
+
"<=": "$lte",
|
|
32
|
+
"==": "$eq",
|
|
33
|
+
"!=": "$ne",
|
|
34
|
+
">=": "$gte",
|
|
35
|
+
">": "$gt",
|
|
36
|
+
"array-contains": "$elemMatch",
|
|
37
|
+
"array-contains-any": "$in",
|
|
38
|
+
"in": "$in",
|
|
39
|
+
"not-in": "$nin"
|
|
40
|
+
};
|
|
41
|
+
class MongoConditionBuilder {
|
|
42
|
+
/**
|
|
43
|
+
* Build MongoDB filter conditions from Rebase FilterValues
|
|
44
|
+
*
|
|
45
|
+
* @param filter - Rebase filter values
|
|
46
|
+
* @returns Array of MongoDB filter objects
|
|
47
|
+
*/
|
|
48
|
+
static buildFilterConditions(filter) {
|
|
49
|
+
if (!filter) return [];
|
|
50
|
+
const conditions = [];
|
|
51
|
+
for (const [field, filterParam] of Object.entries(filter)) {
|
|
52
|
+
if (!filterParam) continue;
|
|
53
|
+
const [op, value] = filterParam;
|
|
54
|
+
const mongoOp = REBASE_TO_MONGO_OP[op];
|
|
55
|
+
if (!mongoOp) {
|
|
56
|
+
console.warn(`Unsupported filter operator: ${op}`);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (op === "array-contains") {
|
|
60
|
+
conditions.push({
|
|
61
|
+
[field]: { $elemMatch: { $eq: value } }
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
conditions.push({
|
|
65
|
+
[field]: { [mongoOp]: value }
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return conditions;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Build search conditions for text search
|
|
73
|
+
*
|
|
74
|
+
* @param searchString - Text to search for
|
|
75
|
+
* @param properties - Properties to search in
|
|
76
|
+
* @returns Array of MongoDB filter objects for text search
|
|
77
|
+
*/
|
|
78
|
+
static buildSearchConditions(searchString, properties) {
|
|
79
|
+
if (!searchString) return [];
|
|
80
|
+
const orConditions = [];
|
|
81
|
+
const searchRegex = new RegExp(searchString, "i");
|
|
82
|
+
for (const [key, prop] of Object.entries(properties)) {
|
|
83
|
+
if (prop?.dataType === "string" || typeof prop === "string") {
|
|
84
|
+
orConditions.push({
|
|
85
|
+
[key]: { $regex: searchRegex }
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (orConditions.length === 0) {
|
|
90
|
+
return [{ $text: { $search: searchString } }];
|
|
91
|
+
}
|
|
92
|
+
return orConditions;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Combine multiple conditions with AND operator
|
|
96
|
+
*
|
|
97
|
+
* @param conditions - Array of filter conditions
|
|
98
|
+
* @returns Combined filter or undefined if empty
|
|
99
|
+
*/
|
|
100
|
+
static combineConditionsWithAnd(conditions) {
|
|
101
|
+
if (conditions.length === 0) return void 0;
|
|
102
|
+
if (conditions.length === 1) return conditions[0];
|
|
103
|
+
return { $and: conditions };
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Combine multiple conditions with OR operator
|
|
107
|
+
*
|
|
108
|
+
* @param conditions - Array of filter conditions
|
|
109
|
+
* @returns Combined filter or undefined if empty
|
|
110
|
+
*/
|
|
111
|
+
static combineConditionsWithOr(conditions) {
|
|
112
|
+
if (conditions.length === 0) return void 0;
|
|
113
|
+
if (conditions.length === 1) return conditions[0];
|
|
114
|
+
return { $or: conditions };
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Build a complete MongoDB query from Rebase options
|
|
118
|
+
*
|
|
119
|
+
* @param options - Rebase fetch options
|
|
120
|
+
* @returns MongoDB filter object
|
|
121
|
+
*/
|
|
122
|
+
static buildQuery(options) {
|
|
123
|
+
const conditions = [];
|
|
124
|
+
if (options.filter) {
|
|
125
|
+
const filterConditions = this.buildFilterConditions(options.filter);
|
|
126
|
+
conditions.push(...filterConditions);
|
|
127
|
+
}
|
|
128
|
+
if (options.searchString && options.properties) {
|
|
129
|
+
const searchConditions = this.buildSearchConditions(
|
|
130
|
+
options.searchString,
|
|
131
|
+
options.properties
|
|
132
|
+
);
|
|
133
|
+
if (searchConditions.length > 0) {
|
|
134
|
+
const searchFilter = this.combineConditionsWithOr(searchConditions);
|
|
135
|
+
if (searchFilter) {
|
|
136
|
+
conditions.push(searchFilter);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return this.combineConditionsWithAnd(conditions) ?? {};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Build MongoDB sort options from Rebase options
|
|
144
|
+
*
|
|
145
|
+
* @param orderBy - Field to order by
|
|
146
|
+
* @param order - Sort direction
|
|
147
|
+
* @returns MongoDB sort object
|
|
148
|
+
*/
|
|
149
|
+
static buildSort(orderBy, order) {
|
|
150
|
+
if (!orderBy) return void 0;
|
|
151
|
+
return { [orderBy]: order === "desc" ? -1 : 1 };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
class MongoEntityService {
|
|
155
|
+
constructor(db) {
|
|
156
|
+
this.db = db;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get a MongoDB collection by its path
|
|
160
|
+
*/
|
|
161
|
+
getCollection(collectionPath) {
|
|
162
|
+
const collectionName = collectionPath.replace(/\//g, "_");
|
|
163
|
+
return this.db.collection(collectionName);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Convert a string ID to ObjectId if it's a valid ObjectId string
|
|
167
|
+
*/
|
|
168
|
+
toObjectId(id) {
|
|
169
|
+
if (typeof id === "string" && mongodb.ObjectId.isValid(id) && id.length === 24) {
|
|
170
|
+
return new mongodb.ObjectId(id);
|
|
171
|
+
}
|
|
172
|
+
return id;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Convert a MongoDB document to a Rebase Entity
|
|
176
|
+
*/
|
|
177
|
+
documentToEntity(doc, path) {
|
|
178
|
+
const { _id, ...values } = doc;
|
|
179
|
+
return {
|
|
180
|
+
id: _id.toString(),
|
|
181
|
+
path,
|
|
182
|
+
values: this.convertFromMongoValues(values)
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Convert values from MongoDB format to Rebase format
|
|
187
|
+
*/
|
|
188
|
+
convertFromMongoValues(values) {
|
|
189
|
+
const result = {};
|
|
190
|
+
for (const [key, value] of Object.entries(values)) {
|
|
191
|
+
result[key] = this.convertFromMongoValue(value);
|
|
192
|
+
}
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Convert a single value from MongoDB format
|
|
197
|
+
*/
|
|
198
|
+
convertFromMongoValue(value) {
|
|
199
|
+
if (value === null || value === void 0) return value;
|
|
200
|
+
if (value instanceof mongodb.ObjectId) {
|
|
201
|
+
return value.toString();
|
|
202
|
+
}
|
|
203
|
+
if (value instanceof Date) {
|
|
204
|
+
return value;
|
|
205
|
+
}
|
|
206
|
+
if (Array.isArray(value)) {
|
|
207
|
+
return value.map((v) => this.convertFromMongoValue(v));
|
|
208
|
+
}
|
|
209
|
+
if (typeof value === "object" && "path" in value && "id" in value) {
|
|
210
|
+
return {
|
|
211
|
+
path: value.path,
|
|
212
|
+
id: value.id instanceof mongodb.ObjectId ? value.id.toString() : value.id
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
if (typeof value === "object") {
|
|
216
|
+
return this.convertFromMongoValues(value);
|
|
217
|
+
}
|
|
218
|
+
return value;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Convert values to MongoDB format for storage
|
|
222
|
+
*/
|
|
223
|
+
convertToMongoValues(values) {
|
|
224
|
+
const result = {};
|
|
225
|
+
for (const [key, value] of Object.entries(values)) {
|
|
226
|
+
result[key] = this.convertToMongoValue(value);
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Convert a single value to MongoDB format
|
|
232
|
+
*/
|
|
233
|
+
convertToMongoValue(value) {
|
|
234
|
+
if (value === null || value === void 0) return value;
|
|
235
|
+
if (typeof value === "object" && value.isEntityReference?.()) {
|
|
236
|
+
return {
|
|
237
|
+
id: mongodb.ObjectId.isValid(value.id) ? new mongodb.ObjectId(value.id) : value.id,
|
|
238
|
+
path: value.path
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
if (value instanceof Date) {
|
|
242
|
+
return value;
|
|
243
|
+
}
|
|
244
|
+
if (Array.isArray(value)) {
|
|
245
|
+
return value.map((v) => this.convertToMongoValue(v));
|
|
246
|
+
}
|
|
247
|
+
if (typeof value === "object") {
|
|
248
|
+
return this.convertToMongoValues(value);
|
|
249
|
+
}
|
|
250
|
+
return value;
|
|
251
|
+
}
|
|
252
|
+
// =============================================================
|
|
253
|
+
// EntityRepository Implementation
|
|
254
|
+
// =============================================================
|
|
255
|
+
/**
|
|
256
|
+
* Fetch a single entity by ID
|
|
257
|
+
*/
|
|
258
|
+
async fetchEntity(collectionPath, entityId, _databaseId) {
|
|
259
|
+
const collection = this.getCollection(collectionPath);
|
|
260
|
+
const id = this.toObjectId(entityId);
|
|
261
|
+
const doc = await collection.findOne({ _id: id });
|
|
262
|
+
if (!doc) return void 0;
|
|
263
|
+
return this.documentToEntity(doc, collectionPath);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Fetch a collection of entities with optional filtering, ordering, and pagination
|
|
267
|
+
*/
|
|
268
|
+
async fetchCollection(collectionPath, options = {}) {
|
|
269
|
+
const collection = this.getCollection(collectionPath);
|
|
270
|
+
const query = MongoConditionBuilder.buildQuery({
|
|
271
|
+
filter: options.filter,
|
|
272
|
+
searchString: options.searchString,
|
|
273
|
+
properties: options.collection?.properties ?? {}
|
|
274
|
+
});
|
|
275
|
+
const findOptions = {};
|
|
276
|
+
const sort = MongoConditionBuilder.buildSort(options.orderBy, options.order);
|
|
277
|
+
if (sort) {
|
|
278
|
+
findOptions.sort = sort;
|
|
279
|
+
}
|
|
280
|
+
if (options.limit) {
|
|
281
|
+
findOptions.limit = options.limit;
|
|
282
|
+
}
|
|
283
|
+
if (options.startAfter !== void 0) {
|
|
284
|
+
findOptions.skip = Number(options.startAfter);
|
|
285
|
+
}
|
|
286
|
+
const docs = await collection.find(query, findOptions).toArray();
|
|
287
|
+
return docs.map((doc) => this.documentToEntity(doc, collectionPath));
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Search entities by text
|
|
291
|
+
*/
|
|
292
|
+
async searchEntities(collectionPath, searchString, options = {}) {
|
|
293
|
+
return this.fetchCollection(collectionPath, {
|
|
294
|
+
...options,
|
|
295
|
+
searchString
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Count entities in a collection
|
|
300
|
+
*/
|
|
301
|
+
async countEntities(collectionPath, options = {}) {
|
|
302
|
+
const collection = this.getCollection(collectionPath);
|
|
303
|
+
const query = options.filter ? MongoConditionBuilder.buildQuery({ filter: options.filter }) : {};
|
|
304
|
+
return collection.countDocuments(query);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Save an entity (create or update)
|
|
308
|
+
*/
|
|
309
|
+
async saveEntity(collectionPath, values, entityId, _databaseId) {
|
|
310
|
+
const collection = this.getCollection(collectionPath);
|
|
311
|
+
const mongoValues = this.convertToMongoValues(values);
|
|
312
|
+
if (entityId) {
|
|
313
|
+
const id = this.toObjectId(entityId);
|
|
314
|
+
await collection.updateOne(
|
|
315
|
+
{ _id: id },
|
|
316
|
+
{ $set: mongoValues },
|
|
317
|
+
{ upsert: true }
|
|
318
|
+
);
|
|
319
|
+
return {
|
|
320
|
+
id: entityId.toString(),
|
|
321
|
+
path: collectionPath,
|
|
322
|
+
values
|
|
323
|
+
};
|
|
324
|
+
} else {
|
|
325
|
+
const newId = new mongodb.ObjectId();
|
|
326
|
+
await collection.insertOne({
|
|
327
|
+
_id: newId,
|
|
328
|
+
...mongoValues
|
|
329
|
+
});
|
|
330
|
+
return {
|
|
331
|
+
id: newId.toString(),
|
|
332
|
+
path: collectionPath,
|
|
333
|
+
values
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Delete an entity by ID
|
|
339
|
+
*/
|
|
340
|
+
async deleteEntity(collectionPath, entityId, _databaseId) {
|
|
341
|
+
const collection = this.getCollection(collectionPath);
|
|
342
|
+
const id = this.toObjectId(entityId);
|
|
343
|
+
const result = await collection.deleteOne({ _id: id });
|
|
344
|
+
if (result.deletedCount === 0) {
|
|
345
|
+
console.warn(`Entity ${entityId} not found in collection ${collectionPath}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Check if a field value is unique in a collection
|
|
350
|
+
*/
|
|
351
|
+
async checkUniqueField(collectionPath, fieldName, value, excludeEntityId, _databaseId) {
|
|
352
|
+
const collection = this.getCollection(collectionPath);
|
|
353
|
+
const query = { [fieldName]: value };
|
|
354
|
+
if (excludeEntityId) {
|
|
355
|
+
const id = this.toObjectId(excludeEntityId);
|
|
356
|
+
query._id = { $ne: id };
|
|
357
|
+
}
|
|
358
|
+
const count = await collection.countDocuments(query);
|
|
359
|
+
return count === 0;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Generate a new entity ID
|
|
363
|
+
*/
|
|
364
|
+
generateEntityId() {
|
|
365
|
+
return new mongodb.ObjectId().toString();
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
class MongoRealtimeService {
|
|
369
|
+
constructor(db) {
|
|
370
|
+
this.db = db;
|
|
371
|
+
this.entityService = new MongoEntityService(db);
|
|
372
|
+
}
|
|
373
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
374
|
+
entityService;
|
|
375
|
+
/**
|
|
376
|
+
* Get the collection name from a path
|
|
377
|
+
*/
|
|
378
|
+
getCollectionName(path) {
|
|
379
|
+
return path.replace(/\//g, "_");
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Subscribe to collection changes
|
|
383
|
+
*/
|
|
384
|
+
subscribeToCollection(subscriptionId, config, callback) {
|
|
385
|
+
this.unsubscribe(subscriptionId);
|
|
386
|
+
const collectionName = this.getCollectionName(config.path);
|
|
387
|
+
const collection = this.db.collection(collectionName);
|
|
388
|
+
const pipeline = [];
|
|
389
|
+
pipeline.push({
|
|
390
|
+
$match: {
|
|
391
|
+
operationType: { $in: ["insert", "update", "replace", "delete"] }
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
try {
|
|
395
|
+
const changeStream = collection.watch(pipeline, {
|
|
396
|
+
fullDocument: "updateLookup"
|
|
397
|
+
});
|
|
398
|
+
const subscription = {
|
|
399
|
+
type: "collection",
|
|
400
|
+
config,
|
|
401
|
+
changeStream,
|
|
402
|
+
callback
|
|
403
|
+
};
|
|
404
|
+
this.subscriptions.set(subscriptionId, subscription);
|
|
405
|
+
this.fetchAndNotifyCollection(subscriptionId, config, callback);
|
|
406
|
+
changeStream.on("change", async (change) => {
|
|
407
|
+
await this.fetchAndNotifyCollection(subscriptionId, config, callback);
|
|
408
|
+
});
|
|
409
|
+
changeStream.on("error", (error) => {
|
|
410
|
+
console.error(`Change stream error for subscription ${subscriptionId}:`, error);
|
|
411
|
+
});
|
|
412
|
+
} catch (error) {
|
|
413
|
+
console.warn("Change streams not available, falling back to polling:", error);
|
|
414
|
+
const subscription = {
|
|
415
|
+
type: "collection",
|
|
416
|
+
config,
|
|
417
|
+
callback
|
|
418
|
+
};
|
|
419
|
+
this.subscriptions.set(subscriptionId, subscription);
|
|
420
|
+
this.fetchAndNotifyCollection(subscriptionId, config, callback);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Fetch collection and notify callback
|
|
425
|
+
*/
|
|
426
|
+
async fetchAndNotifyCollection(subscriptionId, config, callback) {
|
|
427
|
+
try {
|
|
428
|
+
const entities = await this.entityService.fetchCollection(config.path, {
|
|
429
|
+
filter: config.filter,
|
|
430
|
+
orderBy: config.orderBy,
|
|
431
|
+
order: config.order,
|
|
432
|
+
limit: config.limit,
|
|
433
|
+
startAfter: config.startAfter,
|
|
434
|
+
searchString: config.searchString
|
|
435
|
+
});
|
|
436
|
+
if (callback) {
|
|
437
|
+
callback(entities);
|
|
438
|
+
}
|
|
439
|
+
} catch (error) {
|
|
440
|
+
console.error(`Error fetching collection for subscription ${subscriptionId}:`, error);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Subscribe to single entity changes
|
|
445
|
+
*/
|
|
446
|
+
subscribeToEntity(subscriptionId, config, callback) {
|
|
447
|
+
this.unsubscribe(subscriptionId);
|
|
448
|
+
const collectionName = this.getCollectionName(config.path);
|
|
449
|
+
const collection = this.db.collection(collectionName);
|
|
450
|
+
const entityId = typeof config.entityId === "string" && mongodb.ObjectId.isValid(config.entityId) ? new mongodb.ObjectId(config.entityId) : config.entityId;
|
|
451
|
+
const pipeline = [
|
|
452
|
+
{
|
|
453
|
+
$match: {
|
|
454
|
+
"documentKey._id": entityId,
|
|
455
|
+
operationType: { $in: ["insert", "update", "replace", "delete"] }
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
];
|
|
459
|
+
try {
|
|
460
|
+
const changeStream = collection.watch(pipeline, {
|
|
461
|
+
fullDocument: "updateLookup"
|
|
462
|
+
});
|
|
463
|
+
const subscription = {
|
|
464
|
+
type: "entity",
|
|
465
|
+
config,
|
|
466
|
+
changeStream,
|
|
467
|
+
callback
|
|
468
|
+
};
|
|
469
|
+
this.subscriptions.set(subscriptionId, subscription);
|
|
470
|
+
this.fetchAndNotifyEntity(subscriptionId, config, callback);
|
|
471
|
+
changeStream.on("change", async (change) => {
|
|
472
|
+
if (change.operationType === "delete") {
|
|
473
|
+
if (callback) {
|
|
474
|
+
callback(null);
|
|
475
|
+
}
|
|
476
|
+
} else {
|
|
477
|
+
await this.fetchAndNotifyEntity(subscriptionId, config, callback);
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
changeStream.on("error", (error) => {
|
|
481
|
+
console.error(`Change stream error for subscription ${subscriptionId}:`, error);
|
|
482
|
+
});
|
|
483
|
+
} catch (error) {
|
|
484
|
+
console.warn("Change streams not available, falling back to polling:", error);
|
|
485
|
+
const subscription = {
|
|
486
|
+
type: "entity",
|
|
487
|
+
config,
|
|
488
|
+
callback
|
|
489
|
+
};
|
|
490
|
+
this.subscriptions.set(subscriptionId, subscription);
|
|
491
|
+
this.fetchAndNotifyEntity(subscriptionId, config, callback);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Fetch entity and notify callback
|
|
496
|
+
*/
|
|
497
|
+
async fetchAndNotifyEntity(subscriptionId, config, callback) {
|
|
498
|
+
try {
|
|
499
|
+
const entity = await this.entityService.fetchEntity(config.path, config.entityId);
|
|
500
|
+
if (callback) {
|
|
501
|
+
callback(entity || null);
|
|
502
|
+
}
|
|
503
|
+
} catch (error) {
|
|
504
|
+
console.error(`Error fetching entity for subscription ${subscriptionId}:`, error);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Unsubscribe from a subscription
|
|
509
|
+
*/
|
|
510
|
+
unsubscribe(subscriptionId) {
|
|
511
|
+
const subscription = this.subscriptions.get(subscriptionId);
|
|
512
|
+
if (subscription) {
|
|
513
|
+
if (subscription.changeStream) {
|
|
514
|
+
subscription.changeStream.close().catch(console.error);
|
|
515
|
+
}
|
|
516
|
+
this.subscriptions.delete(subscriptionId);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Notify all relevant subscribers of an entity update
|
|
521
|
+
* This is called after save/delete operations to push updates
|
|
522
|
+
*/
|
|
523
|
+
async notifyEntityUpdate(path, entityId, entity, _databaseId) {
|
|
524
|
+
for (const [subscriptionId, subscription] of this.subscriptions) {
|
|
525
|
+
if (subscription.type === "entity") {
|
|
526
|
+
const config = subscription.config;
|
|
527
|
+
if (config.path === path && config.entityId.toString() === entityId) {
|
|
528
|
+
if (subscription.callback) {
|
|
529
|
+
subscription.callback(entity);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
} else if (subscription.type === "collection") {
|
|
533
|
+
const config = subscription.config;
|
|
534
|
+
if (config.path === path) {
|
|
535
|
+
await this.fetchAndNotifyCollection(subscriptionId, config, subscription.callback);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Get all active subscriptions (for debugging)
|
|
542
|
+
*/
|
|
543
|
+
getSubscriptions() {
|
|
544
|
+
return this.subscriptions;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Close all subscriptions
|
|
548
|
+
*/
|
|
549
|
+
async closeAll() {
|
|
550
|
+
for (const [subscriptionId] of this.subscriptions) {
|
|
551
|
+
this.unsubscribe(subscriptionId);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
class MongoDriver {
|
|
556
|
+
constructor(db, realtimeService) {
|
|
557
|
+
this.db = db;
|
|
558
|
+
this.entityService = new MongoEntityService(db);
|
|
559
|
+
this.realtimeService = realtimeService ?? new MongoRealtimeService(db);
|
|
560
|
+
}
|
|
561
|
+
key = "mongodb";
|
|
562
|
+
initialised = true;
|
|
563
|
+
entityService;
|
|
564
|
+
realtimeService;
|
|
565
|
+
/**
|
|
566
|
+
* Get the current timestamp
|
|
567
|
+
*/
|
|
568
|
+
currentTime() {
|
|
569
|
+
return /* @__PURE__ */ new Date();
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Fetch a collection of entities
|
|
573
|
+
*/
|
|
574
|
+
async fetchCollection({
|
|
575
|
+
path,
|
|
576
|
+
collection,
|
|
577
|
+
filter,
|
|
578
|
+
limit,
|
|
579
|
+
startAfter,
|
|
580
|
+
orderBy,
|
|
581
|
+
searchString,
|
|
582
|
+
order
|
|
583
|
+
}) {
|
|
584
|
+
return this.entityService.fetchCollection(path, {
|
|
585
|
+
filter,
|
|
586
|
+
limit,
|
|
587
|
+
startAfter,
|
|
588
|
+
orderBy,
|
|
589
|
+
order,
|
|
590
|
+
searchString,
|
|
591
|
+
collection
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Listen to collection changes
|
|
596
|
+
*/
|
|
597
|
+
listenCollection({
|
|
598
|
+
path,
|
|
599
|
+
collection,
|
|
600
|
+
filter,
|
|
601
|
+
limit,
|
|
602
|
+
startAfter,
|
|
603
|
+
orderBy,
|
|
604
|
+
searchString,
|
|
605
|
+
order,
|
|
606
|
+
onUpdate,
|
|
607
|
+
onError
|
|
608
|
+
}) {
|
|
609
|
+
const subscriptionId = this.generateSubscriptionId();
|
|
610
|
+
const callback = (entities) => {
|
|
611
|
+
try {
|
|
612
|
+
onUpdate(entities);
|
|
613
|
+
} catch (error) {
|
|
614
|
+
console.error("Error in collection update callback:", error);
|
|
615
|
+
if (onError) {
|
|
616
|
+
onError(error instanceof Error ? error : new Error(String(error)));
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
this.realtimeService.subscribeToCollection(
|
|
621
|
+
subscriptionId,
|
|
622
|
+
{
|
|
623
|
+
clientId: "driver",
|
|
624
|
+
path,
|
|
625
|
+
filter,
|
|
626
|
+
orderBy,
|
|
627
|
+
order,
|
|
628
|
+
limit,
|
|
629
|
+
startAfter,
|
|
630
|
+
searchString
|
|
631
|
+
},
|
|
632
|
+
callback
|
|
633
|
+
);
|
|
634
|
+
return () => {
|
|
635
|
+
this.realtimeService.unsubscribe(subscriptionId);
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Fetch a single entity
|
|
640
|
+
*/
|
|
641
|
+
async fetchEntity({
|
|
642
|
+
path,
|
|
643
|
+
entityId,
|
|
644
|
+
databaseId,
|
|
645
|
+
collection
|
|
646
|
+
}) {
|
|
647
|
+
return this.entityService.fetchEntity(path, entityId, databaseId);
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Listen to entity changes
|
|
651
|
+
*/
|
|
652
|
+
listenEntity({
|
|
653
|
+
path,
|
|
654
|
+
entityId,
|
|
655
|
+
collection,
|
|
656
|
+
onUpdate,
|
|
657
|
+
onError
|
|
658
|
+
}) {
|
|
659
|
+
const subscriptionId = this.generateSubscriptionId();
|
|
660
|
+
const callback = (entity) => {
|
|
661
|
+
try {
|
|
662
|
+
onUpdate(entity);
|
|
663
|
+
} catch (error) {
|
|
664
|
+
console.error("Error in entity update callback:", error);
|
|
665
|
+
if (onError) {
|
|
666
|
+
onError(error instanceof Error ? error : new Error(String(error)));
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
this.realtimeService.subscribeToEntity(
|
|
671
|
+
subscriptionId,
|
|
672
|
+
{
|
|
673
|
+
clientId: "driver",
|
|
674
|
+
path,
|
|
675
|
+
entityId
|
|
676
|
+
},
|
|
677
|
+
callback
|
|
678
|
+
);
|
|
679
|
+
return () => {
|
|
680
|
+
this.realtimeService.unsubscribe(subscriptionId);
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Save an entity (create or update)
|
|
685
|
+
*/
|
|
686
|
+
async saveEntity({
|
|
687
|
+
path,
|
|
688
|
+
entityId,
|
|
689
|
+
values,
|
|
690
|
+
collection,
|
|
691
|
+
status
|
|
692
|
+
}) {
|
|
693
|
+
const entity = await this.entityService.saveEntity(path, values, entityId);
|
|
694
|
+
await this.realtimeService.notifyEntityUpdate(path, String(entity.id), entity);
|
|
695
|
+
return entity;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Delete an entity
|
|
699
|
+
*/
|
|
700
|
+
async deleteEntity({
|
|
701
|
+
entity,
|
|
702
|
+
collection
|
|
703
|
+
}) {
|
|
704
|
+
await this.entityService.deleteEntity(entity.path, entity.id);
|
|
705
|
+
await this.realtimeService.notifyEntityUpdate(entity.path, String(entity.id), null);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Check if a field value is unique
|
|
709
|
+
*/
|
|
710
|
+
async checkUniqueField(path, name, value, entityId, collection) {
|
|
711
|
+
return this.entityService.checkUniqueField(path, name, value, entityId);
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Generate a new entity ID
|
|
715
|
+
*/
|
|
716
|
+
generateEntityId(path, collection) {
|
|
717
|
+
return this.entityService.generateEntityId();
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Count entities in a collection
|
|
721
|
+
*/
|
|
722
|
+
async countEntities({
|
|
723
|
+
path,
|
|
724
|
+
collection,
|
|
725
|
+
filter
|
|
726
|
+
}) {
|
|
727
|
+
return this.entityService.countEntities(path, { filter });
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Generate a unique subscription ID
|
|
731
|
+
*/
|
|
732
|
+
generateSubscriptionId() {
|
|
733
|
+
return `mongo_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Check if the delegate is ready
|
|
737
|
+
*/
|
|
738
|
+
isReady() {
|
|
739
|
+
return this.initialised;
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Get the underlying entity service for direct access
|
|
743
|
+
*/
|
|
744
|
+
getEntityService() {
|
|
745
|
+
return this.entityService;
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Get the underlying realtime service for direct access
|
|
749
|
+
*/
|
|
750
|
+
getRealtimeService() {
|
|
751
|
+
return this.realtimeService;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
class MongoCollectionRegistry {
|
|
755
|
+
collections = /* @__PURE__ */ new Map();
|
|
756
|
+
/**
|
|
757
|
+
* Register a collection
|
|
758
|
+
*/
|
|
759
|
+
register(collection) {
|
|
760
|
+
this.collections.set(collection.name, collection);
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Get a collection by its path
|
|
764
|
+
*/
|
|
765
|
+
getCollectionByPath(path) {
|
|
766
|
+
return this.collections.get(path);
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Get all registered collections
|
|
770
|
+
*/
|
|
771
|
+
getCollections() {
|
|
772
|
+
return Array.from(this.collections.values());
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
function createMongoBackend(config) {
|
|
776
|
+
const { connection: db, client, collections } = config;
|
|
777
|
+
const collectionRegistry = new MongoCollectionRegistry();
|
|
778
|
+
if (collections) {
|
|
779
|
+
collections.forEach((collection) => collectionRegistry.register(collection));
|
|
780
|
+
}
|
|
781
|
+
const entityService = new MongoEntityService(db);
|
|
782
|
+
const realtimeService = new MongoRealtimeService(db);
|
|
783
|
+
const driver = new MongoDriver(db, realtimeService);
|
|
784
|
+
const mongoConnection = new MongoDBConnection(db, client);
|
|
785
|
+
const admin = {
|
|
786
|
+
async executeAggregate(pipeline) {
|
|
787
|
+
const firstStage = pipeline[0];
|
|
788
|
+
const collName = firstStage?.$from ?? "__admin__";
|
|
789
|
+
const cursor = db.collection(collName).aggregate(pipeline);
|
|
790
|
+
return await cursor.toArray();
|
|
791
|
+
},
|
|
792
|
+
async fetchCollectionStats(collectionName) {
|
|
793
|
+
const stats = await db.command({ collStats: collectionName });
|
|
794
|
+
return { count: stats.count, sizeBytes: stats.size };
|
|
795
|
+
},
|
|
796
|
+
async fetchUnmappedTables(mappedPaths) {
|
|
797
|
+
const allCollections = await db.listCollections().toArray();
|
|
798
|
+
const names = allCollections.map((c) => c.name).filter((n) => !n.startsWith("system."));
|
|
799
|
+
if (!mappedPaths || mappedPaths.length === 0) return names;
|
|
800
|
+
const mappedSet = new Set(mappedPaths.map((p) => p.toLowerCase()));
|
|
801
|
+
return names.filter((n) => !mappedSet.has(n.toLowerCase()));
|
|
802
|
+
},
|
|
803
|
+
async fetchTableMetadata(collectionName) {
|
|
804
|
+
const sample = await db.collection(collectionName).findOne();
|
|
805
|
+
if (!sample) return { columns: [], foreignKeys: [], junctions: [], policies: [] };
|
|
806
|
+
const columns = Object.entries(sample).map(([key, value]) => ({
|
|
807
|
+
column_name: key,
|
|
808
|
+
data_type: typeof value,
|
|
809
|
+
udt_name: typeof value,
|
|
810
|
+
is_nullable: "YES",
|
|
811
|
+
column_default: null,
|
|
812
|
+
character_maximum_length: null
|
|
813
|
+
}));
|
|
814
|
+
return { columns, foreignKeys: [], junctions: [], policies: [] };
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
return {
|
|
818
|
+
// Abstract interface implementations
|
|
819
|
+
connection: mongoConnection,
|
|
820
|
+
entityRepository: entityService,
|
|
821
|
+
realtimeProvider: realtimeService,
|
|
822
|
+
collectionRegistry,
|
|
823
|
+
admin,
|
|
824
|
+
// Lifecycle
|
|
825
|
+
async initialize() {
|
|
826
|
+
},
|
|
827
|
+
async healthCheck() {
|
|
828
|
+
const start = Date.now();
|
|
829
|
+
try {
|
|
830
|
+
await db.command({ ping: 1 });
|
|
831
|
+
return { healthy: true, latencyMs: Date.now() - start };
|
|
832
|
+
} catch {
|
|
833
|
+
return { healthy: false, latencyMs: Date.now() - start };
|
|
834
|
+
}
|
|
835
|
+
},
|
|
836
|
+
async destroy() {
|
|
837
|
+
await client.close();
|
|
838
|
+
},
|
|
839
|
+
// MongoDB-specific accessors
|
|
840
|
+
db,
|
|
841
|
+
client,
|
|
842
|
+
driver,
|
|
843
|
+
entityService,
|
|
844
|
+
realtimeService
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
function createMongoDelegate(db, realtimeService) {
|
|
848
|
+
const realtime = realtimeService ?? new MongoRealtimeService(db);
|
|
849
|
+
return new MongoDriver(db, realtime);
|
|
850
|
+
}
|
|
851
|
+
function createMongoRealtimeService(db) {
|
|
852
|
+
return new MongoRealtimeService(db);
|
|
853
|
+
}
|
|
854
|
+
function createMongoEntityRepository(db) {
|
|
855
|
+
return new MongoEntityService(db);
|
|
856
|
+
}
|
|
857
|
+
function isMongoBackendConfig(config) {
|
|
858
|
+
return config.type === "mongodb" && typeof config.connection !== "undefined" && typeof config.client !== "undefined";
|
|
859
|
+
}
|
|
860
|
+
function isMongoDriverConfig(obj) {
|
|
861
|
+
return typeof obj === "object" && obj !== null && "type" in obj && obj.type === "mongodb" && "connection" in obj && "client" in obj;
|
|
862
|
+
}
|
|
863
|
+
exports2.MongoCollectionRegistry = MongoCollectionRegistry;
|
|
864
|
+
exports2.MongoConditionBuilder = MongoConditionBuilder;
|
|
865
|
+
exports2.MongoDBConnection = MongoDBConnection;
|
|
866
|
+
exports2.MongoDriver = MongoDriver;
|
|
867
|
+
exports2.MongoEntityService = MongoEntityService;
|
|
868
|
+
exports2.MongoRealtimeService = MongoRealtimeService;
|
|
869
|
+
exports2.createMongoBackend = createMongoBackend;
|
|
870
|
+
exports2.createMongoDBConnection = createMongoDBConnection;
|
|
871
|
+
exports2.createMongoDelegate = createMongoDelegate;
|
|
872
|
+
exports2.createMongoEntityRepository = createMongoEntityRepository;
|
|
873
|
+
exports2.createMongoRealtimeService = createMongoRealtimeService;
|
|
874
|
+
exports2.isMongoBackendConfig = isMongoBackendConfig;
|
|
875
|
+
exports2.isMongoDriverConfig = isMongoDriverConfig;
|
|
876
|
+
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
877
|
+
});
|
|
878
|
+
//# sourceMappingURL=index.umd.js.map
|