import facadeFieldFactories from "./entryFields" ; import { createFieldDescriptor , getEntryPropertyValueType , setEntryPropertyValueType } from "./tools" ; import Entry from "../core/Entry" ; import Group from "../core/Group" ; import { EntryFacade , EntryFacadeField , EntryID , EntryPropertyType , EntryType , EntryPropertyValueType , GroupID , VaultFacade } from "../types" ; export interface CreateEntryFacadeOptions { type ? : EntryType ; } const { FacadeType : FacadeTypeAttribute } = Entry . Attributes ; param entry param fields returns private function addExtraFieldsNonDestructive ( entry , fields ) { const exists = ( propName , fieldType ) => fields . find ( item => item . propertyType === fieldType && item . property === propName ) ; const properties = entry . getProperty ( ) ; const attributes = entry . getAttribute ( ) ; return [ ... fields , ... Object . keys ( properties ) . filter ( name => ! exists ( name , EntryPropertyType . Property ) ) . map ( name => createFieldDescriptor ( entry , "" , EntryPropertyType . Property , name , { removeable : true } ) ) , ... Object . keys ( attributes ) . filter ( name => ! exists ( name , EntryPropertyType . Attribute ) ) . map ( name => createFieldDescriptor ( entry , "" , EntryPropertyType . Attribute , name ) ) ] ; } param entry param descriptor private function applyFieldDescriptor ( entry , descriptor ) { setEntryValue ( entry , descriptor . propertyType , descriptor . property , descriptor . value , descriptor . valueType ) ; } param entry param facade memberof export function consumeEntryFacade ( entry , facade ) { const facadeType = getEntryFacadeType ( entry ) ; if ( facade && facade . type ) { const properties = entry . getProperty ( ) ; const attributes = entry . getAttribute ( ) ; if ( facade . type !== facadeType ) { throw new Error ( `Failed consuming entry data: Expected type "${ facadeType }" but received "${ facade . type }"` ) ; } ( facade . fields || [ ] ) . forEach ( field => applyFieldDescriptor ( entry , field ) ) ; Object . keys ( properties ) . forEach ( propKey => { const correspondingField = facade . fields . find ( ( { propertyType , property } ) => propertyType === "property" && property === propKey ) ; if ( typeof correspondingField === "undefined" ) { entry . deleteProperty ( propKey ) ; } } ) ; Object . keys ( attributes ) . forEach ( attrKey => { const correspondingField = facade . fields . find ( ( { propertyType , property } ) => propertyType === "attribute" && property === attrKey ) ; if ( typeof correspondingField === "undefined" ) { entry . deleteAttribute ( attrKey ) ; } } ) ; return ; } throw new Error ( "Failed consuming entry data: Invalid item passed as a facade" ) ; } param entry param options returns memberof export function createEntryFacade ( entry ? , options = { } ) { if ( entry && entry instanceof Entry !== true ) { throw new Error ( "Failed creating entry facade: Provided item is not an Entry" ) ; } const { type } = options ; const facadeType = type || getEntryFacadeType ( entry ) ; const createFields = facadeFieldFactories [ facadeType ] ; if ( ! createFields ) { throw new Error ( `Failed creating entry facade: No factory found for type "${ facadeType }"` ) ; } const fields = entry ? addExtraFieldsNonDestructive ( entry , createFields ( entry ) ) : createFields ( entry ) ; if ( ! fields . find ( field => field . propertyType === EntryPropertyType . Attribute && field . property === FacadeTypeAttribute ) ) { const entryTypeField = createFieldDescriptor ( entry , "" , EntryPropertyType . Attribute , FacadeTypeAttribute ) ; entryTypeField . value = facadeType ; fields . push ( entryTypeField ) ; } return { id : entry ? entry . id : null , type : facadeType , fields , parentID : entry ? entry . getGroup ( ) . id : null , _history : [ ] , _changes : entry ? entry . getChanges ( ) : [ ] } ; } param group param facade returns memberof export function createEntryFromFacade ( group , facade ) { const entry = group . createEntry ( ) ; const baseFacadeType = getEntryFacadeType ( entry ) ; const facadeType = facade . type || baseFacadeType ; const preparedFacade = { ... facade , parentID : group . id , type : baseFacadeType , id : null } ; consumeEntryFacade ( entry , preparedFacade ) ; if ( facadeType !== baseFacadeType ) { entry . setAttribute ( Entry . Attributes . FacadeType , facadeType ) ; } return entry ; } param facadeFields memberof export function fieldsToProperties ( facadeFields ) { return facadeFields . reduce ( ( output , field ) => { if ( field . propertyType !== "property" ) return output ; output [ field . property ] = field . value ; return output ; } , { } ) ; } export function getEntryFacadePath ( entryID , facade ) { const entry = facade . entries . find ( entry => entry . id === entryID ) ; if ( ! entry ) { throw new Error ( `No entry facade found for ID: ${ entryID }` ) ; } let targetGroupID = null ; const path = [ ] ; do { targetGroupID = targetGroupID ? facade . groups . find ( g => g . id === targetGroupID ) . parentID : entry . parentID ; if ( targetGroupID && targetGroupID != "0" ) { path . unshift ( targetGroupID ) ; } } while ( targetGroupID && targetGroupID != "0" ) ; return path ; } param entry returns private function getEntryFacadeType ( entry ? ) { if ( ! entry ) { return EntryType . Login ; } return entry . getType ( ) ; } param facade param propertyName param valueType export function setEntryFacadePropertyValueType ( facade , propertyName , valueType ) { const matchingPropertyField = facade . fields . find ( field => field . property === propertyName && field . propertyType === EntryPropertyType . Property ) ; const matchingAttributeField = facade . fields . find ( field => field . property === `${ Entry . Attributes . FieldTypePrefix }${ propertyName }` && field . propertyType === EntryPropertyType . Attribute ) ; if ( matchingPropertyField ) { matchingPropertyField . valueType = valueType ; } if ( matchingAttributeField ) { matchingAttributeField . value = valueType ; } } param entry param propertyType param property param value param valueType throws private function setEntryValue ( entry , propertyType , property , value , valueType ? ) { switch ( propertyType ) { case "property" : if ( entry . getProperty ( property ) !== value ) { entry . setProperty ( property , value ) ; } break ; case "attribute" : if ( entry . getAttribute ( property ) !== value ) { entry . setAttribute ( property , value ) ; } break ; default : throw new Error ( `Cannot set value: Unknown property type: ${ propertyType }` ) ; } if ( valueType && getEntryPropertyValueType ( entry , property ) !== valueType ) { setEntryPropertyValueType ( entry , property , valueType ) ; } }