@@ -16,7 +16,8 @@ class Entity {
1616 constructor ( data , id , ancestors , namespace , key ) {
1717 this . className = 'Entity' ;
1818 this . schema = this . constructor . schema ;
19- this . excludeFromIndexes = [ ] ;
19+ this . excludeFromIndexes = { } ;
20+
2021 /**
2122 * Object to store custom data for the entity.
2223 * In some cases we might want to add custom data onto the entity
@@ -36,8 +37,8 @@ class Entity {
3637
3738 this . setId ( ) ;
3839
39- // create entityData from data passed
40- this . entityData = buildEntityData ( this , data || { } ) ;
40+ // create entityData from data provided
41+ this . ____buildEntityData ( data || { } ) ;
4142
4243 /**
4344 * Create virtual properties (getters and setters for entityData object)
@@ -333,6 +334,88 @@ class Entity {
333334
334335 return entityData ;
335336 }
337+
338+ ____buildEntityData ( data ) {
339+ const { schema } = this ;
340+ const isJoiSchema = schema . isJoi ;
341+
342+ // If Joi schema, get its default values
343+ if ( isJoiSchema ) {
344+ const { error, value } = schema . validateJoi ( data ) ;
345+
346+ if ( ! error ) {
347+ this . entityData = { ...value } ;
348+ }
349+ }
350+
351+ this . entityData = { ...this . entityData , ...data } ;
352+
353+ let isArray ;
354+ let isObject ;
355+
356+ Object . entries ( schema . paths ) . forEach ( ( [ key , prop ] ) => {
357+ const hasValue = { } . hasOwnProperty . call ( this . entityData , key ) ;
358+ const isOptional = { } . hasOwnProperty . call ( prop , 'optional' ) && prop . optional !== false ;
359+ const isRequired = { } . hasOwnProperty . call ( prop , 'required' ) && prop . required === true ;
360+
361+ // Set Default Values
362+ if ( ! isJoiSchema && ! hasValue && ! isOptional ) {
363+ let value = null ;
364+
365+ if ( { } . hasOwnProperty . call ( prop , 'default' ) ) {
366+ if ( typeof prop . default === 'function' ) {
367+ value = prop . default ( ) ;
368+ } else {
369+ value = prop . default ;
370+ }
371+ }
372+
373+ if ( ( { } ) . hasOwnProperty . call ( defaultValues . __map__ , value ) ) {
374+ /**
375+ * If default value is in the gstore.defaultValue hashTable
376+ * then execute the handler for that shortcut
377+ */
378+ value = defaultValues . __handler__ ( value ) ;
379+ } else if ( value === null && { } . hasOwnProperty . call ( prop , 'values' ) && ! isRequired ) {
380+ // Default to first value of the allowed values if **not** required
381+ [ value ] = prop . values ;
382+ }
383+
384+ this . entityData [ key ] = value ;
385+ }
386+
387+ // Set excludeFromIndexes
388+ // ----------------------
389+ isArray = prop . type === Array || ( prop . joi && prop . joi . _type === 'array' ) ;
390+ isObject = prop . type === Object || ( prop . joi && prop . joi . _type === 'object' ) ;
391+
392+ if ( prop . excludeFromIndexes === true ) {
393+ if ( isArray ) {
394+ // We exclude both the array values + all the child properties of object items
395+ this . excludeFromIndexes [ key ] = [ `${ key } []` , `${ key } [].*` ] ;
396+ } else if ( isObject ) {
397+ // We exclude the emmbeded entity + all its properties
398+ this . excludeFromIndexes [ key ] = [ key , `${ key } .*` ] ;
399+ } else {
400+ this . excludeFromIndexes [ key ] = [ key ] ;
401+ }
402+ } else if ( prop . excludeFromIndexes !== false ) {
403+ const excludedArray = arrify ( prop . excludeFromIndexes ) ;
404+ if ( isArray ) {
405+ // The format to exclude a property from an embedded entity inside
406+ // an array is: "myArrayProp[].embeddedKey"
407+ this . excludeFromIndexes [ key ] = excludedArray . map ( propExcluded => `${ key } [].${ propExcluded } ` ) ;
408+ } else if ( isObject ) {
409+ // The format to exclude a property from an embedded entity
410+ // is: "myEmbeddedEntity.key"
411+ this . excludeFromIndexes [ key ] = excludedArray . map ( propExcluded => `${ key } .${ propExcluded } ` ) ;
412+ }
413+ }
414+ } ) ;
415+
416+ // add Symbol Key to the entityData
417+ this . entityData [ this . gstore . ds . KEY ] = this . entityKey ;
418+ }
336419}
337420
338421// Private
@@ -367,90 +450,6 @@ function createKey(self, id, ancestors, namespace) {
367450 return namespace ? self . gstore . ds . key ( { namespace, path } ) : self . gstore . ds . key ( path ) ;
368451}
369452
370- function buildEntityData ( self , data ) {
371- const { schema } = self ;
372- const isJoiSchema = schema . isJoi ;
373-
374- let entityData ;
375-
376- // If Joi schema, get its default values
377- if ( isJoiSchema ) {
378- const { error, value } = schema . validateJoi ( data ) ;
379-
380- if ( ! error ) {
381- entityData = { ...value } ;
382- }
383- }
384-
385- entityData = { ...entityData , ...data } ;
386-
387- let isTypeArray ;
388-
389- Object . keys ( schema . paths ) . forEach ( k => {
390- const prop = schema . paths [ k ] ;
391- const hasValue = { } . hasOwnProperty . call ( entityData , k ) ;
392- const isOptional = { } . hasOwnProperty . call ( prop , 'optional' ) && prop . optional !== false ;
393- const isRequired = { } . hasOwnProperty . call ( prop , 'required' ) && prop . required === true ;
394-
395- // Set Default Values
396- if ( ! isJoiSchema && ! hasValue && ! isOptional ) {
397- let value = null ;
398-
399- if ( { } . hasOwnProperty . call ( prop , 'default' ) ) {
400- if ( typeof prop . default === 'function' ) {
401- value = prop . default ( ) ;
402- } else {
403- value = prop . default ;
404- }
405- }
406-
407- if ( ( { } ) . hasOwnProperty . call ( defaultValues . __map__ , value ) ) {
408- /**
409- * If default value is in the gstore.defaultValue hashTable
410- * then execute the handler for that shortcut
411- */
412- value = defaultValues . __handler__ ( value ) ;
413- } else if ( value === null && { } . hasOwnProperty . call ( prop , 'values' ) && ! isRequired ) {
414- // Default to first value of the allowed values if **not** required
415- [ value ] = prop . values ;
416- }
417-
418- entityData [ k ] = value ;
419- }
420-
421- // Set excludeFromIndexes
422- // ----------------------
423- isTypeArray = prop . type === 'array' || ( prop . joi && prop . joi . _type === 'array' ) ;
424-
425- if ( prop . excludeFromIndexes === true && ! isTypeArray ) {
426- self . excludeFromIndexes . push ( k ) ;
427- } else if ( ! is . boolean ( prop . excludeFromIndexes ) ) {
428- // For embedded entities we can set which properties are excluded from indexes
429- // by passing a string|array of properties
430-
431- let formatted ;
432- const exFromIndexes = arrify ( prop . excludeFromIndexes ) ;
433-
434- if ( prop . type === 'array' ) {
435- // The format to exclude a property from an embedded entity inside
436- // an array is: "myArrayProp[].embeddedKey"
437- formatted = exFromIndexes . map ( excluded => `${ k } [].${ excluded } ` ) ;
438- } else {
439- // The format to exclude a property from an embedded entity
440- // is: "myEmbeddedEntity.key"
441- formatted = exFromIndexes . map ( excluded => `${ k } .${ excluded } ` ) ;
442- }
443-
444- self . excludeFromIndexes = [ ...self . excludeFromIndexes , ...formatted ] ;
445- }
446- } ) ;
447-
448- // add Symbol Key to the entityData
449- entityData [ self . gstore . ds . KEY ] = self . entityKey ;
450-
451- return entityData ;
452- }
453-
454453function registerHooksFromSchema ( self ) {
455454 const callQueue = self . schema . callQueue . entity ;
456455
0 commit comments