@orion-js/mongodb 4.0.18 → 4.0.20

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.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as MongoDB from 'mongodb';
2
- import { MongoClient, Db, EnhancedOmit } from 'mongodb';
2
+ import { MongoClient, Db, MongoClientOptions, EnhancedOmit, KMSProviders, AWSEncryptionKeyOptions, UUID } from 'mongodb';
3
3
  export { MongoDB };
4
4
  import { SchemaInAnyOrionForm, Schema, StrictInferSchemaType, TypedSchemaOnSchema, InferSchemaType, FieldType } from '@orion-js/schema';
5
5
 
@@ -8,14 +8,51 @@ interface OrionMongoClient {
8
8
  db: Db;
9
9
  uri: string;
10
10
  dbName: string;
11
+ /**
12
+ * @deprecated Use startConnection() instead. This property is not guaranteed to be resolved if the connection is not started.
13
+ * When using async calls startConnection or connectionPromise is no longer needed. Orion will automatically start the connection if it is not already started.
14
+ * Kept for backwards compatibility. startConnection does not re-start the connection if it is already started, so it is safe to use.
15
+ */
11
16
  connectionPromise: Promise<MongoClient>;
12
17
  connectionName: string;
18
+ encrypted: {
19
+ client: MongoClient;
20
+ db: Db;
21
+ };
22
+ /**
23
+ * Starts the connection if it is not already started.
24
+ * If the connection is already started, it resolves immediately.
25
+ */
13
26
  startConnection: () => Promise<MongoClient>;
27
+ closeConnection: () => Promise<void>;
14
28
  }
15
- interface OrionMongoConnectionsMap {
16
- [key: string]: OrionMongoClient;
29
+ declare class OrionMongoDatabaseWrapper implements OrionMongoClient {
30
+ uri: string;
31
+ dbName: string;
32
+ connectionName: string;
33
+ connectionPromise: Promise<MongoClient>;
34
+ private mongoOptions;
35
+ private connectionEvent;
36
+ private state;
37
+ client: MongoClient;
38
+ db: Db;
39
+ configured: boolean;
40
+ readonly encrypted: {
41
+ client: MongoClient;
42
+ db: Db;
43
+ };
44
+ readonly configTimeout: NodeJS.Timeout;
45
+ constructor(connectionName: string);
46
+ config(mongoURL: string, mongoOptions: MongoClientOptions): void;
47
+ awaitConnection(): Promise<this>;
48
+ connectWithRetry(client: MongoClient): any;
49
+ startConnection(): Promise<MongoClient>;
50
+ closeConnection(): Promise<void>;
17
51
  }
18
- declare const connections: OrionMongoConnectionsMap;
52
+ declare function configureConnection(connectionName: string, mongoOptions: MongoClientOptions): Promise<OrionMongoDatabaseWrapper>;
53
+ declare const connections: {
54
+ [key: string]: OrionMongoDatabaseWrapper;
55
+ };
19
56
 
20
57
  declare const allConnectionPromises: any[];
21
58
  interface MongoConnectOptions {
@@ -141,16 +178,19 @@ type CreateCollectionOptionsWithTypedSchema<T extends TypedSchemaOnSchema & {
141
178
  }> = {
142
179
  schema: T;
143
180
  } & Omit<CreateCollectionOptions<InferSchemaType<T>>, 'schema'>;
144
- declare class Collection<ModelClass extends ModelClassBase = ModelClassBase> {
181
+ declare class BaseCollection<ModelClass extends ModelClassBase = ModelClassBase> {
145
182
  name: string;
146
183
  connectionName?: string;
147
184
  schema?: Schema;
148
- indexes: Array<CollectionIndex>;
149
185
  generateId: () => ModelClass['_id'];
150
186
  getSchema: () => Schema;
151
187
  db: MongoDB.Db;
152
188
  client: OrionMongoClient;
189
+ /**
190
+ * @deprecated Use getRawCollection() instead. This property is not guaranteed to be defined if the connection has not been started.
191
+ */
153
192
  rawCollection: MongoDB.Collection<ModelClass>;
193
+ getRawCollection: () => Promise<MongoDB.Collection<ModelClass>>;
154
194
  findOne: FindOne<ModelClass>;
155
195
  find: Find<ModelClass>;
156
196
  insertOne: InsertOne<ModelClass>;
@@ -182,9 +222,18 @@ declare class Collection<ModelClass extends ModelClassBase = ModelClassBase> {
182
222
  */
183
223
  createIndexes: () => Promise<string[]>;
184
224
  createIndexesPromise: Promise<string[]>;
225
+ /**
226
+ * @deprecated Use startConnection() instead. This property is not guaranteed to be resolved if the connection is not started.
227
+ * When using async calls startConnection or connectionPromise is no longer needed. Orion will automatically start the connection if it is not already started.
228
+ * Kept for backwards compatibility. startConnection does not re-start the connection if it is already started, so it is safe to use.
229
+ */
185
230
  connectionPromise: Promise<MongoDB.MongoClient>;
186
231
  startConnection: () => Promise<MongoDB.MongoClient>;
187
232
  }
233
+ declare class Collection<ModelClass extends ModelClassBase = ModelClassBase> extends BaseCollection<ModelClass> {
234
+ indexes: Array<CollectionIndex>;
235
+ encrypted?: BaseCollection<ModelClass>;
236
+ }
188
237
  type DistinctDocumentId<DistinctId extends string> = string & {
189
238
  __TYPE__: `DistinctDocumentId<${DistinctId}>`;
190
239
  };
@@ -219,4 +268,21 @@ declare function createCollection<T extends TypedSchemaOnSchema & {
219
268
  }>(options: CreateCollectionOptionsWithTypedSchema<T>): Collection<InferSchemaType<T>>;
220
269
  declare function createCollection<T extends ModelClassBase>(options: CreateCollectionOptions<T>): Collection<T>;
221
270
 
222
- export { Collection, type CollectionIndex, type CountDocuments, type CreateCollectionOptions, type CreateCollectionOptionsWithSchemaType, type CreateCollectionOptionsWithTypedSchema, DataLoader, type DeleteMany, type DeleteOne, type DistinctDocumentId, type DocumentWithId, type EstimatedDocumentCount, type Find, type FindCursor, type FindOne, type FindOneAndUpdate, type FindOneAndUpdateUpdateOptions, type InferIdType, type InferSchemaTypeWithId, type InitItem, type InsertAndFind, type InsertMany, type InsertOne, type InsertOptions, type ModelClassBase, type ModelToMongoSelector, MongoCollection, type MongoFilter, type MongoSelector, type OptionalId, Repository, type SchemaWithRequiredId, type TypedId, type UpdateAndFind, type UpdateItem, type UpdateMany, type UpdateOne, type UpdateOptions, type Upsert, allConnectionPromises, connections, createCollection, createIndexesPromises, getMongoConnection, typedId };
271
+ declare function getOrCreateEncryptionKey({ keyAltName, kmsProvider, masterKey, connectionName, keyVaultDatabase, keyVaultCollection, kmsProviders, }: {
272
+ keyAltName: string;
273
+ kmsProvider: keyof KMSProviders;
274
+ masterKey?: AWSEncryptionKeyOptions;
275
+ connectionName?: string;
276
+ keyVaultDatabase?: string;
277
+ keyVaultCollection?: string;
278
+ kmsProviders: KMSProviders;
279
+ }): Promise<{
280
+ key: UUID;
281
+ keyVaultNamespace: string;
282
+ }>;
283
+ declare const ENCRYPTION_ALGORITHMS: {
284
+ DETERMINISTIC: string;
285
+ RANDOM: string;
286
+ };
287
+
288
+ export { BaseCollection, Collection, type CollectionIndex, type CountDocuments, type CreateCollectionOptions, type CreateCollectionOptionsWithSchemaType, type CreateCollectionOptionsWithTypedSchema, DataLoader, type DeleteMany, type DeleteOne, type DistinctDocumentId, type DocumentWithId, ENCRYPTION_ALGORITHMS, type EstimatedDocumentCount, type Find, type FindCursor, type FindOne, type FindOneAndUpdate, type FindOneAndUpdateUpdateOptions, type InferIdType, type InferSchemaTypeWithId, type InitItem, type InsertAndFind, type InsertMany, type InsertOne, type InsertOptions, type ModelClassBase, type ModelToMongoSelector, MongoCollection, type MongoFilter, type MongoSelector, type OptionalId, Repository, type SchemaWithRequiredId, type TypedId, type UpdateAndFind, type UpdateItem, type UpdateMany, type UpdateOne, type UpdateOptions, type Upsert, allConnectionPromises, configureConnection, connections, createCollection, createIndexesPromises, getMongoConnection, getOrCreateEncryptionKey, typedId };
package/dist/index.js CHANGED
@@ -1,7 +1,5 @@
1
1
  // src/connect/connections.ts
2
- var connections = {};
3
-
4
- // src/connect/getMongoConnection.ts
2
+ import { EventEmitter } from "events";
5
3
  import { MongoClient } from "mongodb";
6
4
 
7
5
  // src/connect/getDBName.ts
@@ -24,10 +22,14 @@ function getDBName(url) {
24
22
  return dbName;
25
23
  }
26
24
 
25
+ // src/connect/connections.ts
26
+ import { nextTick } from "process";
27
+ import { logger } from "@orion-js/logger";
28
+ import { sleep } from "@orion-js/helpers";
29
+
27
30
  // src/connect/getMongoURLFromEnv.ts
28
31
  import { internalGetEnv } from "@orion-js/env";
29
32
  var getMongoURLFromEnv = (connectionName) => {
30
- var _a;
31
33
  if (connectionName === "main") {
32
34
  if (!internalGetEnv("mongo_url", "MONGO_URL")) {
33
35
  throw new Error("MONGO_URL is required");
@@ -36,7 +38,7 @@ var getMongoURLFromEnv = (connectionName) => {
36
38
  }
37
39
  const envName = `mongo_url_${connectionName.toLowerCase()}`;
38
40
  const processEnvName = `MONGO_URL_${connectionName.toUpperCase()}`;
39
- const uri = ((_a = connections[connectionName]) == null ? void 0 : _a.uri) ?? internalGetEnv(envName, processEnvName);
41
+ const uri = internalGetEnv(envName, processEnvName);
40
42
  if (!uri) {
41
43
  throw new Error(
42
44
  `To use the connection "${connectionName}" you must initialize it first calling getMongoConnection({name: "${connectionName}", uri: "MONGOURI"}) or setting the environment variable ${processEnvName}.`
@@ -44,56 +46,156 @@ var getMongoURLFromEnv = (connectionName) => {
44
46
  }
45
47
  return uri;
46
48
  };
49
+ var requiresExplicitSetup = (connectionName) => {
50
+ if (connectionName === "main") {
51
+ const value2 = internalGetEnv("mongo_explicit_setup", "MONGO_EXPLICIT_SETUP");
52
+ return typeof value2 === "boolean" ? value2 : value2 === "true";
53
+ }
54
+ const envName = `mongo_explicit_setup_${connectionName.toLowerCase()}`;
55
+ const processEnvName = `MONGO_EXPLICIT_SETUP_${connectionName.toUpperCase()}`;
56
+ const value = internalGetEnv(envName, processEnvName);
57
+ return typeof value === "boolean" ? value : value === "true";
58
+ };
47
59
 
48
- // src/connect/getMongoConnection.ts
49
- import { logger } from "@orion-js/logger";
50
- import { sleep } from "@orion-js/helpers";
51
- var allConnectionPromises = [];
52
- async function connect(client) {
53
- try {
54
- const result = await client.connect();
55
- return result;
56
- } catch (error) {
57
- logger.error(`Error connecting to mongo: ${error.message}. Will retry in 5s`, error);
58
- await sleep(5e3);
59
- return connect(client);
60
+ // src/connect/connections.ts
61
+ var connectionWrappers = {};
62
+ var OrionMongoDatabaseWrapper = class {
63
+ uri;
64
+ dbName;
65
+ connectionName;
66
+ connectionPromise;
67
+ mongoOptions;
68
+ connectionEvent = new EventEmitter();
69
+ state = "disconnected";
70
+ client;
71
+ db;
72
+ configured = false;
73
+ encrypted = { client: null, db: null };
74
+ configTimeout;
75
+ constructor(connectionName) {
76
+ this.connectionName = connectionName;
77
+ logger.info("New connection requested", {
78
+ connectionName
79
+ });
80
+ this.connectionEvent.setMaxListeners(Number.POSITIVE_INFINITY);
81
+ this.connectionPromise = new Promise((resolve, reject) => {
82
+ if (this.state === "connected") {
83
+ resolve(this.client);
84
+ }
85
+ this.connectionEvent.once("connected", resolve);
86
+ this.connectionEvent.once("error", reject);
87
+ });
88
+ this.configTimeout = setTimeout(() => {
89
+ logger.error(
90
+ "Connection was required but never configured, call configureConnection() or unset the env variable MONGO_EXPLICIT_SETUP",
91
+ {
92
+ connectionName
93
+ }
94
+ );
95
+ this.connectionEvent.emit("error", new Error("Connection was required but never configured"));
96
+ }, 30 * 1e3);
97
+ }
98
+ config(mongoURL, mongoOptions) {
99
+ var _a;
100
+ this.uri = mongoURL;
101
+ this.mongoOptions = mongoOptions;
102
+ this.configured = true;
103
+ if ((_a = this.mongoOptions) == null ? void 0 : _a.autoEncryption) {
104
+ this.encrypted.client = new MongoClient(mongoURL, {
105
+ retryReads: true,
106
+ ...this.mongoOptions
107
+ });
108
+ this.encrypted.db = this.encrypted.client.db(getDBName(this.uri));
109
+ }
110
+ this.client = new MongoClient(mongoURL, {
111
+ retryReads: true,
112
+ ...this.mongoOptions,
113
+ autoEncryption: null
114
+ });
115
+ this.db = this.client.db(getDBName(this.uri));
116
+ clearTimeout(this.configTimeout);
117
+ }
118
+ async awaitConnection() {
119
+ if (this.state === "connected") return this;
120
+ if (this.state === "connecting" || !this.configured) {
121
+ await this.connectionPromise;
122
+ return this;
123
+ }
124
+ this.state = "connecting";
125
+ const censoredURI = this.uri.replace(/\/\/.*:.*@/, "//");
126
+ logger.info("Connecting to mongo", {
127
+ uri: censoredURI,
128
+ connectionName: this.connectionName
129
+ });
130
+ if (this.encrypted.client) {
131
+ await this.connectWithRetry(this.encrypted.client);
132
+ logger.info("Successfully connected to encrypted mongo", {
133
+ uri: censoredURI,
134
+ connectionName: this.connectionName
135
+ });
136
+ }
137
+ await this.connectWithRetry(this.client);
138
+ this.state = "connected";
139
+ this.connectionEvent.emit("connected", this.client);
140
+ logger.info("Successfully connected to mongo", {
141
+ uri: censoredURI,
142
+ connectionName: this.connectionName
143
+ });
144
+ nextTick(() => {
145
+ this.connectionEvent.removeAllListeners();
146
+ this.connectionEvent = null;
147
+ });
148
+ return this;
149
+ }
150
+ async connectWithRetry(client) {
151
+ try {
152
+ return await client.connect();
153
+ } catch (error) {
154
+ logger.error("Error connecting to mongo. Will retry in 5s", {
155
+ error,
156
+ connectionName: this.connectionName
157
+ });
158
+ await sleep(5e3);
159
+ return this.connectWithRetry(client);
160
+ }
161
+ }
162
+ async startConnection() {
163
+ return this.awaitConnection().then(() => this.client);
60
164
  }
165
+ async closeConnection() {
166
+ var _a, _b, _c;
167
+ if (this.state === "disconnected" || this.state === "disconnecting") return;
168
+ this.state = "disconnecting";
169
+ await ((_a = this.client) == null ? void 0 : _a.close());
170
+ await ((_c = (_b = this.encrypted) == null ? void 0 : _b.client) == null ? void 0 : _c.close());
171
+ this.state = "disconnected";
172
+ }
173
+ };
174
+ function configureConnection(connectionName, mongoOptions) {
175
+ connectionWrappers[connectionName] = connectionWrappers[connectionName] || new OrionMongoDatabaseWrapper(connectionName);
176
+ const connectionWrapper = connectionWrappers[connectionName];
177
+ if (connectionWrapper.configured) {
178
+ throw new Error("Connection already configured");
179
+ }
180
+ connectionWrapper.config(getMongoURLFromEnv(connectionName), mongoOptions);
181
+ return connectionWrapper.awaitConnection();
61
182
  }
183
+ function getExistingConnection(connectionName) {
184
+ connectionWrappers[connectionName] = connectionWrappers[connectionName] || new OrionMongoDatabaseWrapper(connectionName);
185
+ return connectionWrappers[connectionName];
186
+ }
187
+ var connections = connectionWrappers;
188
+
189
+ // src/connect/getMongoConnection.ts
190
+ var allConnectionPromises = [];
62
191
  var getMongoConnection = ({ name, uri }) => {
63
192
  uri = uri || getMongoURLFromEnv(name);
64
- if (connections[name]) return connections[name];
65
- const client = new MongoClient(uri, {
66
- retryReads: true
67
- });
68
- let resolveConnected;
69
- const connectionPromise = new Promise((resolve) => {
70
- resolveConnected = resolve;
71
- });
72
- let internalConnectionPromise;
73
- const startConnection = async () => {
74
- if (internalConnectionPromise) {
75
- return await internalConnectionPromise;
76
- }
77
- internalConnectionPromise = connect(client);
78
- allConnectionPromises.push(internalConnectionPromise);
79
- internalConnectionPromise.then((client2) => {
80
- resolveConnected(client2);
81
- });
82
- return await internalConnectionPromise;
83
- };
84
- const dbName = getDBName(uri);
85
- const db = client.db(dbName);
86
- const mongoClient = {
87
- uri,
88
- client,
89
- connectionPromise,
90
- startConnection,
91
- dbName,
92
- db,
93
- connectionName: name
94
- };
95
- connections[name] = mongoClient;
96
- return mongoClient;
193
+ const connection = getExistingConnection(name);
194
+ if (!connection.configured && !requiresExplicitSetup(name)) {
195
+ connection.config(uri, {});
196
+ }
197
+ allConnectionPromises.push(connection.connectionPromise);
198
+ return connection;
97
199
  };
98
200
 
99
201
  // src/types/index.ts
@@ -101,16 +203,19 @@ import * as MongoDB from "mongodb";
101
203
  import {
102
204
  fieldTypes
103
205
  } from "@orion-js/schema";
104
- var Collection = class {
206
+ var BaseCollection = class {
105
207
  name;
106
208
  connectionName;
107
209
  schema;
108
- indexes;
109
210
  generateId;
110
211
  getSchema;
111
212
  db;
112
213
  client;
214
+ /**
215
+ * @deprecated Use getRawCollection() instead. This property is not guaranteed to be defined if the connection has not been started.
216
+ */
113
217
  rawCollection;
218
+ getRawCollection;
114
219
  findOne;
115
220
  find;
116
221
  insertOne;
@@ -142,9 +247,18 @@ var Collection = class {
142
247
  */
143
248
  createIndexes;
144
249
  createIndexesPromise;
250
+ /**
251
+ * @deprecated Use startConnection() instead. This property is not guaranteed to be resolved if the connection is not started.
252
+ * When using async calls startConnection or connectionPromise is no longer needed. Orion will automatically start the connection if it is not already started.
253
+ * Kept for backwards compatibility. startConnection does not re-start the connection if it is already started, so it is safe to use.
254
+ */
145
255
  connectionPromise;
146
256
  startConnection;
147
257
  };
258
+ var Collection = class extends BaseCollection {
259
+ indexes;
260
+ encrypted;
261
+ };
148
262
  function typedId(prefix) {
149
263
  return {
150
264
  ...fieldTypes.string,
@@ -1115,6 +1229,7 @@ function getSchema(options) {
1115
1229
  }
1116
1230
 
1117
1231
  // src/createCollection/wrapMethods.ts
1232
+ import { logger as logger2 } from "@orion-js/logger";
1118
1233
  function wrapMethods(collection) {
1119
1234
  const methodsWithPromises = [
1120
1235
  "findOne",
@@ -1149,6 +1264,14 @@ function wrapMethods(collection) {
1149
1264
  if (typeof collection[methodName2] === "function") {
1150
1265
  collection[methodName2] = (...args) => {
1151
1266
  collection.startConnection();
1267
+ if (!collection.rawCollection) {
1268
+ logger2.error("Method called before connection was initialized", {
1269
+ collectionName: collection.name,
1270
+ connectionName: collection.connectionName,
1271
+ methodName: methodName2
1272
+ });
1273
+ throw new Error("Method called before connection was initialized");
1274
+ }
1152
1275
  return originalMethods[methodName2](...args);
1153
1276
  };
1154
1277
  }
@@ -1164,56 +1287,91 @@ function createCollection(options) {
1164
1287
  if (!orionConnection) {
1165
1288
  throw new Error(`The connection to MongoDB "${connectionName}" was not found`);
1166
1289
  }
1167
- const db = orionConnection.db;
1168
- const rawCollection = db.collection(options.name);
1169
1290
  const schema = getSchema(options);
1170
- const collection = {
1291
+ let resolveCollectionPromise;
1292
+ const collectionPromise = new Promise((resolve) => {
1293
+ resolveCollectionPromise = resolve;
1294
+ });
1295
+ const baseCollection = {
1171
1296
  name: options.name,
1172
1297
  connectionName,
1173
1298
  schema,
1174
1299
  indexes: options.indexes || [],
1175
- db,
1176
1300
  client: orionConnection,
1177
- connectionPromise: orionConnection.connectionPromise,
1178
- startConnection: orionConnection.startConnection,
1179
- rawCollection,
1301
+ connectionPromise: collectionPromise,
1302
+ startConnection: () => orionConnection.startConnection(),
1180
1303
  generateId: generateId_default(options),
1304
+ getRawCollection: async () => {
1305
+ await orionConnection.startConnection();
1306
+ return orionConnection.db.collection(options.name);
1307
+ },
1181
1308
  getSchema: () => schema
1182
1309
  };
1183
- collection.findOne = findOne_default(collection);
1184
- collection.find = find_default(collection);
1185
- collection.findOneAndUpdate = findOneAndUpdate_default(collection);
1186
- collection.insertOne = insertOne_default(collection);
1187
- collection.insertMany = insertMany_default(collection);
1188
- collection.insertAndFind = insertAndFind_default(collection);
1189
- collection.updateOne = updateOne_default(collection);
1190
- collection.updateMany = updateMany_default(collection);
1191
- collection.deleteMany = deleteMany_default(collection);
1192
- collection.deleteOne = deleteOne_default(collection);
1193
- collection.upsert = upsert_default(collection);
1194
- collection.estimatedDocumentCount = estimatedDocumentCount_default(collection);
1195
- collection.countDocuments = countDocuments_default(collection);
1196
- collection.updateAndFind = updateAndFind_default(collection);
1197
- collection.updateItem = updateItem_default(collection);
1198
- collection.aggregate = (pipeline, options2) => collection.rawCollection.aggregate(pipeline, options2);
1199
- collection.watch = (pipeline, options2) => collection.rawCollection.watch(pipeline, options2);
1200
- collection.loadData = loadData_default(collection);
1201
- collection.loadById = loadById_default(collection);
1202
- collection.loadOne = loadOne_default(collection);
1203
- collection.loadMany = loadMany_default(collection);
1310
+ const encryptedCollection = {
1311
+ ...baseCollection,
1312
+ getRawCollection: async () => {
1313
+ await orionConnection.startConnection();
1314
+ return orionConnection.encrypted.db.collection(options.name);
1315
+ }
1316
+ };
1317
+ const mainCollection = {
1318
+ ...baseCollection,
1319
+ encrypted: encryptedCollection
1320
+ };
1321
+ const defineCollectionProperties = () => {
1322
+ if (orionConnection.db) {
1323
+ mainCollection.db = orionConnection.db;
1324
+ mainCollection.rawCollection = orionConnection.db.collection(options.name);
1325
+ }
1326
+ if (orionConnection.encrypted.db) {
1327
+ encryptedCollection.db = orionConnection.encrypted.db;
1328
+ encryptedCollection.rawCollection = orionConnection.encrypted.db.collection(options.name);
1329
+ }
1330
+ };
1331
+ defineCollectionProperties();
1332
+ orionConnection.connectionPromise.then(() => {
1333
+ defineCollectionProperties();
1334
+ resolveCollectionPromise(orionConnection.client);
1335
+ });
1336
+ const collections = [mainCollection, encryptedCollection];
1337
+ for (const collection of collections) {
1338
+ collection.findOne = findOne_default(collection);
1339
+ collection.find = find_default(collection);
1340
+ collection.findOneAndUpdate = findOneAndUpdate_default(collection);
1341
+ collection.insertOne = insertOne_default(collection);
1342
+ collection.insertMany = insertMany_default(collection);
1343
+ collection.insertAndFind = insertAndFind_default(collection);
1344
+ collection.updateOne = updateOne_default(collection);
1345
+ collection.updateMany = updateMany_default(collection);
1346
+ collection.deleteMany = deleteMany_default(collection);
1347
+ collection.deleteOne = deleteOne_default(collection);
1348
+ collection.upsert = upsert_default(collection);
1349
+ collection.estimatedDocumentCount = estimatedDocumentCount_default(collection);
1350
+ collection.countDocuments = countDocuments_default(collection);
1351
+ collection.updateAndFind = updateAndFind_default(collection);
1352
+ collection.updateItem = updateItem_default(collection);
1353
+ collection.aggregate = (pipeline, options2) => collection.rawCollection.aggregate(pipeline, options2);
1354
+ collection.watch = (pipeline, options2) => collection.rawCollection.watch(pipeline, options2);
1355
+ collection.loadData = loadData_default(collection);
1356
+ collection.loadById = loadById_default(collection);
1357
+ collection.loadOne = loadOne_default(collection);
1358
+ collection.loadMany = loadMany_default(collection);
1359
+ collection.createIndexes = async () => [];
1360
+ }
1204
1361
  const createIndexes = async () => {
1205
- await orionConnection.connectionPromise;
1206
- const createIndexPromise = loadIndexes(collection);
1362
+ await orionConnection.startConnection();
1363
+ const createIndexPromise = loadIndexes(mainCollection);
1207
1364
  createIndexesPromises.push(createIndexPromise);
1208
- collection.createIndexesPromise = createIndexPromise;
1365
+ mainCollection.createIndexesPromise = createIndexPromise;
1209
1366
  return createIndexPromise;
1210
1367
  };
1211
- collection.createIndexes = createIndexes;
1368
+ mainCollection.createIndexes = createIndexes;
1212
1369
  if (!process.env.DONT_CREATE_INDEXES_AUTOMATICALLY) {
1213
1370
  createIndexes();
1214
1371
  }
1215
- wrapMethods(collection);
1216
- return collection;
1372
+ wrapMethods(mainCollection);
1373
+ wrapMethods(encryptedCollection);
1374
+ return mainCollection;
1217
1375
  }
1218
1376
 
1219
1377
  // src/service/index.ts
@@ -1241,16 +1399,78 @@ function MongoCollection(options) {
1241
1399
  });
1242
1400
  };
1243
1401
  }
1402
+
1403
+ // src/encrypted/getOrCreateEncryptionKey.ts
1404
+ import { logger as logger3 } from "@orion-js/logger";
1405
+ import { ClientEncryption, MongoClient as MongoClient2 } from "mongodb";
1406
+ async function getOrCreateEncryptionKey({
1407
+ keyAltName,
1408
+ kmsProvider,
1409
+ masterKey,
1410
+ connectionName = "main",
1411
+ keyVaultDatabase = "encryption",
1412
+ keyVaultCollection = "__keyVault",
1413
+ kmsProviders
1414
+ }) {
1415
+ const keyVaultNamespace = `${keyVaultDatabase}.${keyVaultCollection}`;
1416
+ logger3.info("Connecting to database to get or create the encryption key", {
1417
+ keyVaultNamespace,
1418
+ keyAltName
1419
+ });
1420
+ const client = new MongoClient2(getMongoURLFromEnv(connectionName));
1421
+ await client.connect();
1422
+ const db = client.db(keyVaultDatabase);
1423
+ const collection = db.collection(keyVaultCollection);
1424
+ await collection.createIndex(
1425
+ { keyAltName: 1 },
1426
+ { unique: true, partialFilterExpression: { keyAltName: { $exists: true } } }
1427
+ );
1428
+ const clientEncryption = new ClientEncryption(client, {
1429
+ keyVaultNamespace,
1430
+ kmsProviders
1431
+ });
1432
+ const key = await clientEncryption.getKeyByAltName(keyAltName);
1433
+ if (key) {
1434
+ logger3.info("Key found on the key vault", {
1435
+ keyVaultNamespace,
1436
+ keyAltName,
1437
+ UUID: key._id
1438
+ });
1439
+ return { key: key._id, keyVaultNamespace };
1440
+ }
1441
+ logger3.info("Key not found on the key vault, creating a new one", {
1442
+ keyVaultNamespace,
1443
+ keyAltName
1444
+ });
1445
+ const newKey = await clientEncryption.createDataKey(kmsProvider, {
1446
+ keyAltNames: [keyAltName],
1447
+ ...masterKey ? { masterKey } : {}
1448
+ });
1449
+ logger3.info("New encryption key created", {
1450
+ keyVaultNamespace,
1451
+ keyAltName,
1452
+ UUID: newKey
1453
+ });
1454
+ return { key: newKey, keyVaultNamespace };
1455
+ }
1456
+ var ENCRYPTION_ALGORITHMS = {
1457
+ DETERMINISTIC: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
1458
+ RANDOM: "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
1459
+ };
1244
1460
  export {
1461
+ BaseCollection,
1245
1462
  Collection,
1463
+ ENCRYPTION_ALGORITHMS,
1246
1464
  MongoCollection,
1247
1465
  MongoDB,
1248
1466
  Repository,
1249
1467
  allConnectionPromises,
1468
+ configureConnection,
1250
1469
  connections,
1251
1470
  createCollection,
1252
1471
  createIndexesPromises,
1253
1472
  getMongoConnection,
1473
+ getOrCreateEncryptionKey,
1254
1474
  typedId
1255
1475
  };
1256
1476
  //# sourceMappingURL=index.js.map