@orion-js/mongodb 4.1.8 → 4.2.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/index.cjs +121 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -2
- package/dist/index.d.ts +31 -2
- package/dist/index.js +109 -23
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -250,6 +250,7 @@ var getMongoConnection = ({ name, uri }) => {
|
|
|
250
250
|
// src/types/index.ts
|
|
251
251
|
var MongoDB = __toESM(require("mongodb"), 1);
|
|
252
252
|
var import_schema = require("@orion-js/schema");
|
|
253
|
+
var import_helpers2 = require("@orion-js/helpers");
|
|
253
254
|
var BaseCollection = class {
|
|
254
255
|
name;
|
|
255
256
|
connectionName;
|
|
@@ -294,6 +295,12 @@ var BaseCollection = class {
|
|
|
294
295
|
*/
|
|
295
296
|
createIndexes;
|
|
296
297
|
createIndexesPromise;
|
|
298
|
+
/**
|
|
299
|
+
* Deletes indexes that exist in MongoDB but are not defined in the collection configuration.
|
|
300
|
+
* This helps clean up stale indexes that are no longer needed.
|
|
301
|
+
* Always preserves the _id_ index.
|
|
302
|
+
*/
|
|
303
|
+
deleteUnusedIndexes;
|
|
297
304
|
/**
|
|
298
305
|
* @deprecated Use startConnection() instead. This property is not guaranteed to be resolved if the connection is not started.
|
|
299
306
|
* When using async calls startConnection or connectionPromise is no longer needed. Orion will automatically start the connection if it is not already started.
|
|
@@ -310,7 +317,8 @@ function typedId(prefix) {
|
|
|
310
317
|
return {
|
|
311
318
|
...import_schema.fieldTypes.string,
|
|
312
319
|
name: `typedId:${prefix}`,
|
|
313
|
-
toSerializedType: async () => "string"
|
|
320
|
+
toSerializedType: async () => "string",
|
|
321
|
+
generateId: () => (0, import_helpers2.generateUUIDWithPrefix)(prefix)
|
|
314
322
|
};
|
|
315
323
|
}
|
|
316
324
|
|
|
@@ -947,13 +955,13 @@ var insertOne_default = (collection) => {
|
|
|
947
955
|
};
|
|
948
956
|
|
|
949
957
|
// src/createCollection/getMethods/insertMany.ts
|
|
950
|
-
var
|
|
958
|
+
var import_helpers3 = require("@orion-js/helpers");
|
|
951
959
|
var import_schema10 = require("@orion-js/schema");
|
|
952
960
|
var insertMany_default = (collection) => {
|
|
953
961
|
const insertMany = async (docs, options = {}) => {
|
|
954
962
|
await collection.connectionPromise;
|
|
955
963
|
for (let index = 0; index < docs.length; index++) {
|
|
956
|
-
let doc = (0,
|
|
964
|
+
let doc = (0, import_helpers3.clone)(docs[index]);
|
|
957
965
|
if (!doc || type(doc) !== "Object") {
|
|
958
966
|
throw new Error(`Item at index ${index} is not a document`);
|
|
959
967
|
}
|
|
@@ -1070,7 +1078,7 @@ function loadOne_default(collection) {
|
|
|
1070
1078
|
}
|
|
1071
1079
|
|
|
1072
1080
|
// src/createCollection/getMethods/dataLoader/loadData.ts
|
|
1073
|
-
var
|
|
1081
|
+
var import_helpers5 = require("@orion-js/helpers");
|
|
1074
1082
|
|
|
1075
1083
|
// src/createCollection/getMethods/dataLoader/dataLoad/getDataLoader.ts
|
|
1076
1084
|
var import_dataloader = __toESM(require("dataloader"), 1);
|
|
@@ -1092,10 +1100,10 @@ var getDataLoader = (params) => {
|
|
|
1092
1100
|
};
|
|
1093
1101
|
|
|
1094
1102
|
// src/createCollection/getMethods/dataLoader/dataLoad/index.ts
|
|
1095
|
-
var
|
|
1103
|
+
var import_helpers4 = require("@orion-js/helpers");
|
|
1096
1104
|
var dataLoad = async (options) => {
|
|
1097
1105
|
const dataLoader = getDataLoader({
|
|
1098
|
-
key: (0,
|
|
1106
|
+
key: (0, import_helpers4.hashObject)(options.loaderKey),
|
|
1099
1107
|
func: options.load,
|
|
1100
1108
|
timeout: options.timeout || 5
|
|
1101
1109
|
});
|
|
@@ -1124,10 +1132,10 @@ function loadData_default(collection) {
|
|
|
1124
1132
|
timeout: options.timeout,
|
|
1125
1133
|
load: async (values) => {
|
|
1126
1134
|
const query = {
|
|
1127
|
-
...(0,
|
|
1135
|
+
...(0, import_helpers5.clone)(options.match),
|
|
1128
1136
|
[options.key]: { $in: values }
|
|
1129
1137
|
};
|
|
1130
|
-
const cursor = collection.find(query);
|
|
1138
|
+
const cursor = collection.find(query, { readPreference: "secondaryPreferred" });
|
|
1131
1139
|
if (options.sort) {
|
|
1132
1140
|
cursor.sort(options.sort);
|
|
1133
1141
|
}
|
|
@@ -1138,7 +1146,7 @@ function loadData_default(collection) {
|
|
|
1138
1146
|
console.info(`Will execute data loading query now on ${collection.name}: `, query);
|
|
1139
1147
|
}
|
|
1140
1148
|
const items = await cursor.toArray();
|
|
1141
|
-
const itemsMap = (0,
|
|
1149
|
+
const itemsMap = (0, import_helpers5.createMapArray)(items, options.key);
|
|
1142
1150
|
return values.map((value) => {
|
|
1143
1151
|
return itemsMap[value] || [];
|
|
1144
1152
|
});
|
|
@@ -1150,7 +1158,7 @@ function loadData_default(collection) {
|
|
|
1150
1158
|
}
|
|
1151
1159
|
|
|
1152
1160
|
// src/createCollection/generateId.ts
|
|
1153
|
-
var
|
|
1161
|
+
var import_helpers6 = require("@orion-js/helpers");
|
|
1154
1162
|
var import_bson = require("bson");
|
|
1155
1163
|
var getIdGenerator = (options) => {
|
|
1156
1164
|
var _a, _b;
|
|
@@ -1158,23 +1166,21 @@ var getIdGenerator = (options) => {
|
|
|
1158
1166
|
const idField = options.schema._id.type;
|
|
1159
1167
|
if ((_b = idField.name) == null ? void 0 : _b.startsWith("typedId:")) {
|
|
1160
1168
|
return () => {
|
|
1161
|
-
|
|
1162
|
-
const random = (0, import_helpers5.generateUUID)();
|
|
1163
|
-
return `${prefix}-${random}`;
|
|
1169
|
+
return idField.generateId();
|
|
1164
1170
|
};
|
|
1165
1171
|
}
|
|
1166
1172
|
}
|
|
1167
1173
|
if (options.idPrefix || options.idGeneration === "uuid") {
|
|
1168
1174
|
return () => {
|
|
1169
1175
|
const prefix = options.idPrefix || "";
|
|
1170
|
-
const random = (0,
|
|
1176
|
+
const random = (0, import_helpers6.generateUUID)();
|
|
1171
1177
|
return `${prefix}${random}`;
|
|
1172
1178
|
};
|
|
1173
1179
|
}
|
|
1174
1180
|
if (options.idGeneration === "random") {
|
|
1175
1181
|
return () => {
|
|
1176
1182
|
const prefix = options.idPrefix || "";
|
|
1177
|
-
const random = (0,
|
|
1183
|
+
const random = (0, import_helpers6.generateId)();
|
|
1178
1184
|
return `${prefix}${random}`;
|
|
1179
1185
|
};
|
|
1180
1186
|
}
|
|
@@ -1187,12 +1193,82 @@ var generateId_default = getIdGenerator;
|
|
|
1187
1193
|
|
|
1188
1194
|
// src/createCollection/createIndexes.ts
|
|
1189
1195
|
var import_mongodb2 = require("mongodb");
|
|
1196
|
+
var import_logger3 = require("@orion-js/logger");
|
|
1197
|
+
|
|
1198
|
+
// src/createCollection/deleteUnusedIndexes.ts
|
|
1190
1199
|
var import_logger2 = require("@orion-js/logger");
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1200
|
+
|
|
1201
|
+
// src/createCollection/getIndexOptions.ts
|
|
1202
|
+
function getIndexOptions(indexDef) {
|
|
1203
|
+
const { keys: _keys, options: deprecatedOptions, ...flatOptions } = indexDef;
|
|
1204
|
+
if (deprecatedOptions) {
|
|
1205
|
+
return { ...deprecatedOptions, ...flatOptions };
|
|
1206
|
+
}
|
|
1207
|
+
return Object.keys(flatOptions).length > 0 ? flatOptions : void 0;
|
|
1195
1208
|
}
|
|
1209
|
+
function getIndexName(indexDef) {
|
|
1210
|
+
var _a;
|
|
1211
|
+
if (indexDef.name) {
|
|
1212
|
+
return indexDef.name;
|
|
1213
|
+
}
|
|
1214
|
+
return (_a = indexDef.options) == null ? void 0 : _a.name;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
// src/createCollection/deleteUnusedIndexes.ts
|
|
1218
|
+
function keysMatch(definitionKeys, currentIndexKey) {
|
|
1219
|
+
const defEntries = Object.entries(definitionKeys);
|
|
1220
|
+
const curEntries = Object.entries(currentIndexKey);
|
|
1221
|
+
if (defEntries.length !== curEntries.length) return false;
|
|
1222
|
+
for (let i = 0; i < defEntries.length; i++) {
|
|
1223
|
+
const [defKey, defValue] = defEntries[i];
|
|
1224
|
+
const [curKey, curValue] = curEntries[i];
|
|
1225
|
+
if (defKey !== curKey || defValue !== curValue) return false;
|
|
1226
|
+
}
|
|
1227
|
+
return true;
|
|
1228
|
+
}
|
|
1229
|
+
function isIndexDefined(definedIndexes, currentIndex) {
|
|
1230
|
+
return definedIndexes.some((defIndex) => {
|
|
1231
|
+
const customName = getIndexName(defIndex);
|
|
1232
|
+
if (customName && customName === currentIndex.name) return true;
|
|
1233
|
+
return keysMatch(defIndex.keys, currentIndex.key);
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
async function deleteUnusedIndexes(collection) {
|
|
1237
|
+
await collection.connectionPromise;
|
|
1238
|
+
const result = {
|
|
1239
|
+
deletedIndexes: [],
|
|
1240
|
+
collectionName: collection.name
|
|
1241
|
+
};
|
|
1242
|
+
let currentIndexes = [];
|
|
1243
|
+
try {
|
|
1244
|
+
currentIndexes = await collection.rawCollection.indexes();
|
|
1245
|
+
} catch (error) {
|
|
1246
|
+
if (error.codeName === "NamespaceNotFound") {
|
|
1247
|
+
return result;
|
|
1248
|
+
}
|
|
1249
|
+
throw error;
|
|
1250
|
+
}
|
|
1251
|
+
if (!collection.indexes || collection.indexes.length === 0) {
|
|
1252
|
+
return result;
|
|
1253
|
+
}
|
|
1254
|
+
const unusedIndexes = currentIndexes.filter(
|
|
1255
|
+
(index) => index.name !== "_id_" && !isIndexDefined(collection.indexes, index)
|
|
1256
|
+
);
|
|
1257
|
+
for (const index of unusedIndexes) {
|
|
1258
|
+
try {
|
|
1259
|
+
await collection.rawCollection.dropIndex(index.name);
|
|
1260
|
+
result.deletedIndexes.push(index.name);
|
|
1261
|
+
import_logger2.logger.info(`Deleted unused index "${index.name}" from collection "${collection.name}"`);
|
|
1262
|
+
} catch (error) {
|
|
1263
|
+
import_logger2.logger.error(`Failed to delete index "${index.name}" from collection "${collection.name}"`, {
|
|
1264
|
+
error
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
return result;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
// src/createCollection/createIndexes.ts
|
|
1196
1272
|
async function checkIndexes(collection) {
|
|
1197
1273
|
await collection.connectionPromise;
|
|
1198
1274
|
let currentIndexes = [];
|
|
@@ -1200,13 +1276,17 @@ async function checkIndexes(collection) {
|
|
|
1200
1276
|
currentIndexes = await collection.rawCollection.indexes();
|
|
1201
1277
|
} catch (error) {
|
|
1202
1278
|
if (error.codeName !== "NamespaceNotFound") throw error;
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
if (!collection.indexes || collection.indexes.length === 0) {
|
|
1282
|
+
return;
|
|
1203
1283
|
}
|
|
1204
|
-
const
|
|
1205
|
-
(index) => index.name !== "_id_" && !collection.indexes
|
|
1206
|
-
)
|
|
1207
|
-
if (
|
|
1208
|
-
|
|
1209
|
-
`${
|
|
1284
|
+
const unexpectedIndexes = currentIndexes.filter(
|
|
1285
|
+
(index) => index.name !== "_id_" && !isIndexDefined(collection.indexes, index)
|
|
1286
|
+
);
|
|
1287
|
+
if (unexpectedIndexes.length > 0) {
|
|
1288
|
+
import_logger3.logger.warn(
|
|
1289
|
+
`${unexpectedIndexes.length} unexpected indexes found in collection "${collection.name}": ${unexpectedIndexes.map((i) => i.name).join(", ")} | Delete the index or fix the collection definition`
|
|
1210
1290
|
);
|
|
1211
1291
|
}
|
|
1212
1292
|
}
|
|
@@ -1215,7 +1295,9 @@ async function loadIndexes(collection) {
|
|
|
1215
1295
|
if (!collection.indexes.length) return;
|
|
1216
1296
|
await collection.connectionPromise;
|
|
1217
1297
|
const results = Promise.all(
|
|
1218
|
-
collection.indexes.map(async (
|
|
1298
|
+
collection.indexes.map(async (indexDef) => {
|
|
1299
|
+
const { keys } = indexDef;
|
|
1300
|
+
const options = getIndexOptions(indexDef);
|
|
1219
1301
|
try {
|
|
1220
1302
|
return await collection.rawCollection.createIndex(keys, options);
|
|
1221
1303
|
} catch (error) {
|
|
@@ -1246,7 +1328,7 @@ async function loadIndexes(collection) {
|
|
|
1246
1328
|
}
|
|
1247
1329
|
|
|
1248
1330
|
// src/createCollection/getSchemaAndModel.ts
|
|
1249
|
-
var
|
|
1331
|
+
var import_helpers7 = require("@orion-js/helpers");
|
|
1250
1332
|
Symbol.metadata ?? (Symbol.metadata = Symbol("Symbol.metadata"));
|
|
1251
1333
|
function prepareShema(schema) {
|
|
1252
1334
|
if (!schema._id) {
|
|
@@ -1268,7 +1350,7 @@ function getSchema(options) {
|
|
|
1268
1350
|
}
|
|
1269
1351
|
if (options.schema.getModel) {
|
|
1270
1352
|
const model = options.schema.getModel();
|
|
1271
|
-
const schema = model ? (0,
|
|
1353
|
+
const schema = model ? (0, import_helpers7.clone)(model.getSchema()) : {};
|
|
1272
1354
|
return prepareShema(schema);
|
|
1273
1355
|
}
|
|
1274
1356
|
if (type(options.schema) === "Object") {
|
|
@@ -1277,7 +1359,7 @@ function getSchema(options) {
|
|
|
1277
1359
|
}
|
|
1278
1360
|
|
|
1279
1361
|
// src/createCollection/wrapMethods.ts
|
|
1280
|
-
var
|
|
1362
|
+
var import_logger4 = require("@orion-js/logger");
|
|
1281
1363
|
function wrapMethods(collection) {
|
|
1282
1364
|
const methodsWithPromises = [
|
|
1283
1365
|
"findOne",
|
|
@@ -1313,7 +1395,7 @@ function wrapMethods(collection) {
|
|
|
1313
1395
|
collection[methodName2] = (...args) => {
|
|
1314
1396
|
collection.startConnection();
|
|
1315
1397
|
if (!collection.rawCollection) {
|
|
1316
|
-
|
|
1398
|
+
import_logger4.logger.error("Method called before connection was initialized", {
|
|
1317
1399
|
collectionName: collection.name,
|
|
1318
1400
|
connectionName: collection.connectionName,
|
|
1319
1401
|
methodName: methodName2
|
|
@@ -1414,6 +1496,10 @@ function createCollection(options) {
|
|
|
1414
1496
|
return createIndexPromise;
|
|
1415
1497
|
};
|
|
1416
1498
|
mainCollection.createIndexes = createIndexes;
|
|
1499
|
+
mainCollection.deleteUnusedIndexes = async () => {
|
|
1500
|
+
await orionConnection.startConnection();
|
|
1501
|
+
return deleteUnusedIndexes(mainCollection);
|
|
1502
|
+
};
|
|
1417
1503
|
if (!process.env.DONT_CREATE_INDEXES_AUTOMATICALLY) {
|
|
1418
1504
|
createIndexes();
|
|
1419
1505
|
}
|
|
@@ -1449,7 +1535,7 @@ function MongoCollection(options) {
|
|
|
1449
1535
|
}
|
|
1450
1536
|
|
|
1451
1537
|
// src/encrypted/getOrCreateEncryptionKey.ts
|
|
1452
|
-
var
|
|
1538
|
+
var import_logger5 = require("@orion-js/logger");
|
|
1453
1539
|
var import_mongodb3 = require("mongodb");
|
|
1454
1540
|
async function getOrCreateEncryptionKey({
|
|
1455
1541
|
keyAltName,
|
|
@@ -1461,7 +1547,7 @@ async function getOrCreateEncryptionKey({
|
|
|
1461
1547
|
kmsProviders
|
|
1462
1548
|
}) {
|
|
1463
1549
|
const keyVaultNamespace = `${keyVaultDatabase}.${keyVaultCollection}`;
|
|
1464
|
-
|
|
1550
|
+
import_logger5.logger.info("Connecting to database to get or create the encryption key", {
|
|
1465
1551
|
keyVaultNamespace,
|
|
1466
1552
|
keyAltName
|
|
1467
1553
|
});
|
|
@@ -1479,14 +1565,14 @@ async function getOrCreateEncryptionKey({
|
|
|
1479
1565
|
});
|
|
1480
1566
|
const key = await clientEncryption.getKeyByAltName(keyAltName);
|
|
1481
1567
|
if (key) {
|
|
1482
|
-
|
|
1568
|
+
import_logger5.logger.info("Key found on the key vault", {
|
|
1483
1569
|
keyVaultNamespace,
|
|
1484
1570
|
keyAltName,
|
|
1485
1571
|
UUID: key._id
|
|
1486
1572
|
});
|
|
1487
1573
|
return { key: key._id, keyVaultNamespace };
|
|
1488
1574
|
}
|
|
1489
|
-
|
|
1575
|
+
import_logger5.logger.info("Key not found on the key vault, creating a new one", {
|
|
1490
1576
|
keyVaultNamespace,
|
|
1491
1577
|
keyAltName
|
|
1492
1578
|
});
|
|
@@ -1494,7 +1580,7 @@ async function getOrCreateEncryptionKey({
|
|
|
1494
1580
|
keyAltNames: [keyAltName],
|
|
1495
1581
|
...masterKey ? { masterKey } : {}
|
|
1496
1582
|
});
|
|
1497
|
-
|
|
1583
|
+
import_logger5.logger.info("New encryption key created", {
|
|
1498
1584
|
keyVaultNamespace,
|
|
1499
1585
|
keyAltName,
|
|
1500
1586
|
UUID: newKey
|