import { S3Client , S3Metadata } from '../s3' ; import { S3DB } from '../db' ; import { SaveBehavior } from './behaviors/SaveBehavior' ; import { HeadBehavior } from './behaviors/HeadBehavior' ; import { ExistsBehavior } from './behaviors/ExistsBehavior' ; import { LoadBehavior } from './behaviors/LoadBehavior' ; import { DeleteBehavior } from './behaviors/DeleteBehavior' ; import { FindBehavior } from './behaviors/FindBehavior' ; import { ReferenceList } from './ReferenceList' ; import { CollectionConfiguration } from './CollectionConfiguration' ; import { Logger , LogLevelString } from '@mu-ts/logger' ; import { CollectionRegistry } from './CollectionRegistry' ; /**
 * Provides the logical interfaces of a collection and translates it into the
 * appropriate S3 calls.
 *
 * Usage: const myCollection: Collection<SomeType> = new Collection(SomeType);
 *
 * The 'SomeType' definition needs to have [prop: string]: any; on it to avoid
 * a TypeScript collission issue when it interprets the 'two types'.
 */ export class Collection < Of > { private logger : Logger ; private configuration : CollectionConfiguration ; private idPrefix : string | undefined ; private saveBheavior : SaveBehavior < Of > ; private existsBehavior : ExistsBehavior < Of > ; private loadBehavior : LoadBehavior < Of > ; private deleteBehavior : DeleteBehavior < Of > ; private findBehavior : FindBehavior < Of > ; private headBehavior : HeadBehavior < Of > ; constructor ( type , idPrefix ? ) { const name = typeof type === 'string' ? type : `${ ( type as any ) . name }` ; this . logger = S3DB . getRootLogger ( ) . child ( `Collection[${ name }]` ) ; this . logger . info ( { ofType : typeof type , type } , 'Type of argument provided.' ) ; if ( ! name || name === '' ) throw Error ( 'No type was provided.' ) ; const resolvedConfiguration = CollectionRegistry . instance ( ) . resolve ( `${ name . toLowerCase ( ) }` ) ; this . configuration = { ... new CollectionConfiguration ( ) , ... resolvedConfiguration , ... { type } } ; if ( ! this . configuration . name ) throw Error ( `The configuration has no name defined, which is used to determine the bucket name.` ) ; this . idPrefix = idPrefix ; const fullBucketName = S3DB . getCollectionFQN ( this . configuration . name ) ; this . logger . trace ( { fullBucketName } , 'init()' , 'fullBucketName' ) ; const s3Client = new S3Client ( ) ; this . headBehavior = new HeadBehavior ( this . configuration , s3Client , fullBucketName , this . idPrefix ) ; this . existsBehavior = new ExistsBehavior ( this . configuration , s3Client , fullBucketName , this . idPrefix ) ; this . loadBehavior = new LoadBehavior ( this . configuration , s3Client , fullBucketName , this . idPrefix ) ; this . saveBheavior = new SaveBehavior ( this . configuration , s3Client , fullBucketName , this . idPrefix ) ; this . deleteBehavior = new DeleteBehavior ( this . configuration , s3Client , fullBucketName , this . idPrefix ) ; this . findBehavior = new FindBehavior ( this . configuration , s3Client , fullBucketName , this . idPrefix ) ; this . logger . trace ( { configuration : this . configuration } , 'init()' , 'configuration' ) ; } param level deprecated mu-ts public setLogLevel ( level ) { this . logger . setLevel ( level ) ; } param prefix param type public subCollection < OfThis > ( prefix , newType ) { return new Collection < OfThis > ( newType , `${ this . idPrefix }${ prefix }` ) ; } public async head ( id ) { return this . headBehavior . head ( id ) ; } public async exists ( id ) { return this . existsBehavior . exists ( id ) ; } public async load ( id ) { return this . loadBehavior . load ( id ) ; } public async save ( toSave ) { return this . saveBheavior . save ( toSave ) ; } public async delete ( id ) { return this . deleteBehavior . delete ( id ) ; } public async find ( prefix , pageSize ? , continuationToken ? ) { return this . findBehavior . find ( prefix , pageSize , continuationToken ) ; } }