@@ -3,6 +3,7 @@ import { dbSymbols, IDbOptions } from '../db';
33import { IJsonOptions , jsonSymbols } from '../json' ;
44import { modelSymbols } from '../model' ;
55import { privateSymbols } from '../private' ;
6+ import { SapiModelMixin } from '../sapi-model-mixin' ;
67import { formatToJsonSymbols , ToJsonHandler } from '../to-json' ;
78import { debug } from './index' ;
89
@@ -62,42 +63,43 @@ function isInclusiveProjection(projection: IProjection) {
6263 if ( projection ) {
6364 const keys = Object . keys ( projection ) ;
6465 for ( const key of keys ) {
65- if ( projection [ key ] === true || projection [ key ] > 0 ) {
66+ if ( ! Array . isArray ( projection [ key ] ) && typeof projection [ key ] === 'object' ) {
67+ continue ;
68+ } else if ( projection [ key ] === true || projection [ key ] > 0 ) {
6669 return true ;
6770 }
6871 }
6972 return false ;
7073 }
71-
7274 return true ;
7375}
7476
7577function keyMapper ( key , value , options : IJsonOptions , optionsStar : IJsonOptions ) {
7678 return options . field || optionsStar . field || key ;
7779}
7880
79- function mapModelToJson ( ctx : IContext , source , projection : IProjection ) {
81+ function mapModelToJson ( ctx : IContext , model : InstanceType < ReturnType < typeof SapiModelMixin > > , projection : IProjection ) {
8082
8183 let jsonObj = { } ;
8284
83- if ( ! source ) {
84- return source ;
85+ if ( ! model ) {
86+ return model ;
8587 }
8688
87- const dbOptionsByPropertyName : Map < string , IDbOptions > = Reflect . getMetadata ( dbSymbols . dbByPropertyName , source ) ;
89+ const dbOptionsByPropertyName : Map < string , IDbOptions > = Reflect . getMetadata ( dbSymbols . dbByPropertyName , model ) ;
8890
8991 const privateFields : Map < string , boolean > = Reflect
90- . getMetadata ( privateSymbols . sakuraApiPrivatePropertyToFieldNames , source ) || new Map < string , boolean > ( ) ;
92+ . getMetadata ( privateSymbols . sakuraApiPrivatePropertyToFieldNames , model ) || new Map < string , boolean > ( ) ;
9193
9294 const inclusiveProjection = isInclusiveProjection ( projection ) ;
9395
9496 // iterate over each property
95- const keys = Object . keys ( source ) ;
97+ const keys = Object . keys ( model ) ;
9698 for ( const key of keys ) {
9799
98100 const dbOptions = ( dbOptionsByPropertyName ) ? dbOptionsByPropertyName . get ( key ) || { } : { } ;
99- const jsonOptions = getJsonOptions ( source , key , ctx ) ;
100- const jsonOptionsStar = getJsonOptions ( source , key , '*' ) ;
101+ const jsonOptions = getJsonOptions ( model , key , ctx ) ;
102+ const jsonOptionsStar = getJsonOptions ( model , key , '*' ) ;
101103
102104 if ( ( ctx . context !== jsonOptions . context ) && ( jsonOptionsStar . context !== '*' ) ) {
103105 continue ;
@@ -118,73 +120,73 @@ function mapModelToJson(ctx: IContext, source, projection: IProjection) {
118120 continue ;
119121 }
120122
121- const model = dbOptions . model || jsonOptions . model || jsonOptionsStar . model || null ;
122- const newKey = keyMapper ( key , source [ key ] , jsonOptions , jsonOptionsStar ) ;
123+ const subModel = dbOptions . model || jsonOptions . model || jsonOptionsStar . model || null ;
124+ const newKey = keyMapper ( key , model [ key ] , jsonOptions , jsonOptionsStar ) ;
123125
124126 if ( skipProjection ( inclusiveProjection , projection , newKey ) ) {
125127 continue ;
126128 }
127129
128130 let value ;
129- if ( model || shouldRecurse ( source [ key ] ) ) {
131+ if ( subModel || shouldRecurse ( model [ key ] ) ) {
130132
131133 const subProjection = ( projection )
132134 ? ( typeof projection [ newKey ] === 'object' ) ? projection [ newKey ] as IProjection : undefined
133135 : undefined ;
134136
135- if ( Array . isArray ( source [ key ] ) ) {
137+ if ( Array . isArray ( model [ key ] ) ) {
136138
137139 const values = [ ] ;
138- for ( const src of source [ key ] ) {
140+ for ( const src of model [ key ] ) {
139141 values . push ( mapModelToJson ( ctx , src , subProjection ) ) ;
140142 }
141143 value = values ;
142144
143145 } else if ( newKey !== undefined ) {
144146
145- value = mapModelToJson ( ctx , source [ key ] , subProjection ) ;
147+ value = mapModelToJson ( ctx , model [ key ] , subProjection ) ;
146148
147149 }
148150
149151 } else if ( newKey !== undefined ) {
150152
151- value = source [ key ] ;
153+ value = model [ key ] ;
152154
153155 }
154156
155157 // check for @json ({toJson})
156158 if ( jsonOptions . toJson ) {
157- value = jsonOptions . toJson . call ( source , value , key , ctx ) ;
159+ value = jsonOptions . toJson . call ( model , value , key , ctx ) ;
158160 }
159161 if ( jsonOptionsStar . toJson ) {
160- value = jsonOptionsStar . toJson . call ( source , value , key , ctx ) ;
162+ value = jsonOptionsStar . toJson . call ( model , value , key , ctx ) ;
161163 }
162164
163165 // check for @json ({encrypt})
164166 if ( jsonOptions . encrypt ) {
165167 value = ( jsonOptions . encryptor )
166- ? jsonOptions . encryptor . call ( source , value , key , jsonOptions . key , ctx )
167- : encrypt ( value , jsonOptions . key || source [ modelSymbols . cipherKey ] ) ;
168+ ? jsonOptions . encryptor . call ( model , value , key , jsonOptions . key , ctx )
169+ : encrypt ( value , jsonOptions . key || model [ modelSymbols . cipherKey ] ) ;
168170 }
169171 if ( jsonOptionsStar . encrypt ) {
170172 value = ( jsonOptionsStar . encryptor )
171- ? jsonOptionsStar . encryptor . call ( source , value , key , jsonOptions . key , ctx )
172- : encrypt ( value , jsonOptionsStar . key || source [ modelSymbols . cipherKey ] ) ;
173+ ? jsonOptionsStar . encryptor . call ( model , value , key , jsonOptions . key , ctx )
174+ : encrypt ( value , jsonOptionsStar . key || model [ modelSymbols . cipherKey ] ) ;
173175 }
174176
175177 jsonObj [ newKey ] = value ;
176178
177179 }
178180
179181 // @ToJson
180- const formatToJson = Reflect . getMetadata ( formatToJsonSymbols . functionMap , source ) ;
182+ const formatToJson = Reflect . getMetadata ( formatToJsonSymbols . functionMap , model ) ;
181183 if ( formatToJson ) {
182184 const formatters : ToJsonHandler [ ] = [
183185 ...formatToJson . get ( ctx . context ) || [ ] ,
184186 ...formatToJson . get ( '*' ) || [ ]
185187 ] ;
186188 for ( const formatter of formatters ) {
187- jsonObj = formatter . call ( source , jsonObj , source , ctx ) ;
189+ jsonObj = formatter . call ( model , jsonObj , model , ctx ) ;
188190 }
189191 }
190192
@@ -196,6 +198,11 @@ function skipProjection(isInclusive: boolean, projection: IProjection, newKey: s
196198 return false ;
197199 }
198200
201+ // is projection of sub-document
202+ if ( ! Array . isArray ( projection [ newKey ] ) && typeof projection [ newKey ] === 'object' ) {
203+ return false ;
204+ }
205+
199206 return ( isInclusive )
200207 ? projection [ newKey ] == null || projection [ newKey ] === false || projection [ newKey ] < 1
201208 : projection [ newKey ] === false || projection [ newKey ] < 1 ;
0 commit comments