@@ -6,6 +6,7 @@ import type { Server } from '../sdam/server';
66import type { ClientSession } from '../sessions' ;
77import type { Callback } from '../utils' ;
88import { CommandOperation , CommandOperationOptions } from './command' ;
9+ import { CreateIndexOperation } from './indexes' ;
910import { Aspect , defineAspects } from './operation' ;
1011
1112const ILLEGAL_COMMAND_FIELDS = new Set ( [
@@ -75,6 +76,8 @@ export interface CreateCollectionOptions extends CommandOperationOptions {
7576 timeseries ?: TimeSeriesCollectionOptions ;
7677 /** The number of seconds after which a document in a timeseries collection expires. */
7778 expireAfterSeconds ?: number ;
79+ /** @experimental */
80+ encryptedFields ?: Document ;
7881}
7982
8083/** @internal */
@@ -96,31 +99,79 @@ export class CreateCollectionOperation extends CommandOperation<Collection> {
9699 session : ClientSession | undefined ,
97100 callback : Callback < Collection >
98101 ) : void {
99- const db = this . db ;
100- const name = this . name ;
101- const options = this . options ;
102+ ( async ( ) => {
103+ const db = this . db ;
104+ const name = this . name ;
105+ const options = this . options ;
102106
103- const done : Callback = err => {
104- if ( err ) {
105- return callback ( err ) ;
107+ const encryptedFields : Document | undefined =
108+ options . encryptedFields ??
109+ db . s . client . options . autoEncryption ?. encryptedFieldsMap ?. [ `${ db . databaseName } .${ name } ` ] ;
110+
111+ if ( encryptedFields ) {
112+ // Create auxilliary collections for FLE2 support.
113+ const escCollection = encryptedFields . escCollection ?? `enxcol_.${ name } .esc` ;
114+ const eccCollection = encryptedFields . eccCollection ?? `enxcol_.${ name } .ecc` ;
115+ const ecocCollection = encryptedFields . ecocCollection ?? `enxcol_.${ name } .ecoc` ;
116+
117+ for ( const collectionName of [ escCollection , eccCollection , ecocCollection ] ) {
118+ const createOp = new CreateCollectionOperation ( db , collectionName ) ;
119+ await createOp . executeWithoutEncryptedFieldsCheck ( server , session ) ;
120+ }
121+
122+ if ( ! options . encryptedFields ) {
123+ this . options = { ...this . options , encryptedFields } ;
124+ }
125+ }
126+
127+ const coll = await this . executeWithoutEncryptedFieldsCheck ( server , session ) ;
128+
129+ if ( encryptedFields ) {
130+ // Create the required index for FLE2 support.
131+ const createIndexOp = new CreateIndexOperation ( db , name , { __safeContent__ : 1 } , { } ) ;
132+ await new Promise < void > ( ( resolve , reject ) => {
133+ createIndexOp . execute ( server , session , err => ( err ? reject ( err ) : resolve ( ) ) ) ;
134+ } ) ;
106135 }
107136
108- callback ( undefined , new Collection ( db , name , options ) ) ;
109- } ;
110-
111- const cmd : Document = { create : name } ;
112- for ( const n in options ) {
113- if (
114- ( options as any ) [ n ] != null &&
115- typeof ( options as any ) [ n ] !== 'function' &&
116- ! ILLEGAL_COMMAND_FIELDS . has ( n )
117- ) {
118- cmd [ n ] = ( options as any ) [ n ] ;
137+ return coll ;
138+ } ) ( ) . then (
139+ coll => callback ( undefined , coll ) ,
140+ err => callback ( err )
141+ ) ;
142+ }
143+
144+ private executeWithoutEncryptedFieldsCheck (
145+ server : Server ,
146+ session : ClientSession | undefined
147+ ) : Promise < Collection > {
148+ return new Promise < Collection > ( ( resolve , reject ) => {
149+ const db = this . db ;
150+ const name = this . name ;
151+ const options = this . options ;
152+
153+ const done : Callback = err => {
154+ if ( err ) {
155+ return reject ( err ) ;
156+ }
157+
158+ resolve ( new Collection ( db , name , options ) ) ;
159+ } ;
160+
161+ const cmd : Document = { create : name } ;
162+ for ( const n in options ) {
163+ if (
164+ ( options as any ) [ n ] != null &&
165+ typeof ( options as any ) [ n ] !== 'function' &&
166+ ! ILLEGAL_COMMAND_FIELDS . has ( n )
167+ ) {
168+ cmd [ n ] = ( options as any ) [ n ] ;
169+ }
119170 }
120- }
121171
122- // otherwise just execute the command
123- super . executeCommand ( server , session , cmd , done ) ;
172+ // otherwise just execute the command
173+ super . executeCommand ( server , session , cmd , done ) ;
174+ } ) ;
124175 }
125176}
126177
0 commit comments