import { PersistentModel, SchemaModel, SortPredicate, ProducerSortPredicate, SortDirection, SortPredicatesGroup, } from '../types'; export class ModelSortPredicateCreator { private static sortPredicateGroupsMap = new WeakMap< SortPredicate, SortPredicatesGroup >(); private static createPredicateBuilder( modelDefinition: SchemaModel ) { const { name: modelName } = modelDefinition; const fieldNames = new Set(Object.keys(modelDefinition.fields)); let handler: ProxyHandler>; const predicate = new Proxy( {} as SortPredicate, (handler = { get(_target, propertyKey, receiver: SortPredicate) { const field = propertyKey as keyof T; if (!fieldNames.has(field)) { throw new Error( `Invalid field for model. field: ${field}, model: ${modelName}` ); } const result = (sortDirection: SortDirection) => { ModelSortPredicateCreator.sortPredicateGroupsMap .get(receiver) .push({ field, sortDirection }); return receiver; }; return result; }, }) ); ModelSortPredicateCreator.sortPredicateGroupsMap.set(predicate, []); return predicate; } static isValidPredicate( predicate: any ): predicate is SortPredicate { return ModelSortPredicateCreator.sortPredicateGroupsMap.has(predicate); } static getPredicates( predicate: SortPredicate, throwOnInvalid: boolean = true ): SortPredicatesGroup { if ( throwOnInvalid && !ModelSortPredicateCreator.isValidPredicate(predicate) ) { throw new Error('The predicate is not valid'); } return ModelSortPredicateCreator.sortPredicateGroupsMap.get(predicate); } // transforms cb-style predicate into Proxy static createFromExisting( modelDefinition: SchemaModel, existing: ProducerSortPredicate ) { if (!existing || !modelDefinition) { return undefined; } return existing( ModelSortPredicateCreator.createPredicateBuilder(modelDefinition) ); } }