Skip to content

Commit

Permalink
Promise is working with translate filter
Browse files Browse the repository at this point in the history
  • Loading branch information
noam-honig committed Jul 18, 2021
1 parent 2ee2b56 commit 374cb31
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 32 deletions.
5 changes: 3 additions & 2 deletions projects/core/src/filter/filter-interfaces.ts
@@ -1,4 +1,5 @@
import { FieldMetadata } from "../column-interfaces";
import { Context } from "../context";
import { ComparisonFilterFactory, EntityMetadata, EntityWhere, FilterFactories, FilterFactory, getEntityRef, getEntitySettings, SortSegments, ContainsFilterFactory } from "../remult3";


Expand Down Expand Up @@ -64,7 +65,7 @@ export class filterHelper implements FilterFactory<any>, ComparisonFilterFactory
constructor(public metadata: FieldMetadata) {

}

processVal(val: any) {
let ei = getEntitySettings(this.metadata.valueType, false);
if (ei) {
Expand Down Expand Up @@ -331,7 +332,7 @@ export function packToRawWhere(w: Filter) {
}

export class CustomFilterBuilder<entityType, customFilterObject> {
constructor(public readonly translateFilter: (entityType: FilterFactories<entityType>, customFilter: customFilterObject) => Filter) {
constructor(public readonly translateFilter: (entityType: FilterFactories<entityType>, customFilter: customFilterObject, context: Context) => Filter | Promise<Filter>) {

}
build(custom: customFilterObject): Filter {
Expand Down
79 changes: 56 additions & 23 deletions projects/core/src/remult3/RepositoryImplementation.ts
Expand Up @@ -239,7 +239,7 @@ export class RepositoryImplementation<entityType> implements Repository<entityTy
if (!options.orderBy) {
options.orderBy = this._info.entityInfo.defaultOrderBy;
}
opt.where = this.translateWhereToFilter(options.where);
opt.where = await this.translateWhereToFilter(options.where);
opt.orderBy = Sort.translateOrderByToSort(this.metadata, options.orderBy);

opt.limit = options.limit;
Expand Down Expand Up @@ -271,7 +271,7 @@ export class RepositoryImplementation<entityType> implements Repository<entityTy
}

async count(where?: EntityWhere<entityType>): Promise<number> {
return this.edp.count(this.translateWhereToFilter(where));
return this.edp.count(await this.translateWhereToFilter(where));
}
private cache = new Map<string, cacheEntityInfo<entityType>>();
findFirst(options?: EntityWhere<entityType> | FindFirstOptions<entityType>): Promise<entityType> {
Expand Down Expand Up @@ -362,65 +362,98 @@ export class RepositoryImplementation<entityType> implements Repository<entityTy



private translateWhereToFilter(where: EntityWhere<entityType>): Filter {
private async translateWhereToFilter(where: EntityWhere<entityType>): Promise<Filter> {
if (this.metadata.options.fixedFilter)
where = [where, this.metadata.options.fixedFilter];
let filterFactories = Filter.createFilterFactories(this.metadata)
let r = Filter.translateWhereToFilter(filterFactories, where);
if (r && !this.dataProvider.supportsCustomFilter) {
let f = r;
r = new Filter(add => {
f.__applyToConsumer(new customTranslator(add, custom => {
return this.metadata.options.customFilterTranslator.translateFilter(filterFactories, custom);
}))
let f = new customTranslator(async custom => {
return await this.metadata.options.customFilterTranslator.translateFilter(filterFactories, custom, this.context);
});
r.__applyToConsumer(f);

await f.resolve();
r = new Filter(x => f.applyTo(x));

}
return r;
}

}
class customTranslator implements FilterConsumer {
constructor(private orig: FilterConsumer, private translateCustom: (custom: any) => Filter) { }
applyTo(x: FilterConsumer): void {
this.commands.forEach(y => y(x));
}
constructor(private translateCustom: (custom: any) => Promise<Filter>) { }

commands: ((x: FilterConsumer) => void)[] = [];
promises: Promise<void>[] = [];
or(orElements: Filter[]) {
this.orig.or(orElements.map(o => new Filter(add => o.__applyToConsumer(new customTranslator(add, this.translateCustom)))));
let newOrElements: Filter[];
this.promises.push(Promise.all(orElements.map(async element => {
let c = new customTranslator(this.translateCustom);
element.__applyToConsumer(c);
await c.resolve();
return new Filter(x => c.applyTo(x));
})).then(x => {
newOrElements = x;
}));
this.commands.push(x => x.or(newOrElements));
}
isEqualTo(col: FieldMetadata<any>, val: any): void {
this.orig.isEqualTo(col, val);
this.commands.push(x => x.isEqualTo(col, val));
}
isDifferentFrom(col: FieldMetadata<any>, val: any): void {
this.orig.isDifferentFrom(col, val);
this.commands.push(x => x.isDifferentFrom(col, val));
}
isNull(col: FieldMetadata<any>): void {
this.orig.isNull(col);
this.commands.push(x => x.isNull(col));
}
isNotNull(col: FieldMetadata<any>): void {
this.orig.isNotNull(col);
this.commands.push(x => x.isNotNull(col));
}
isGreaterOrEqualTo(col: FieldMetadata<any>, val: any): void {
this.orig.isGreaterOrEqualTo(col, val);
this.commands.push(x => x.isGreaterOrEqualTo(col, val));
}
isGreaterThan(col: FieldMetadata<any>, val: any): void {
this.orig.isGreaterThan(col, val);
this.commands.push(x => x.isGreaterThan(col, val));
}
isLessOrEqualTo(col: FieldMetadata<any>, val: any): void {
this.orig.isLessOrEqualTo(col, val);
this.commands.push(x => x.isLessOrEqualTo(col, val));
}
isLessThan(col: FieldMetadata<any>, val: any): void {
this.orig.isLessThan(col, val);
this.commands.push(x => x.isLessThan(col, val));
}
containsCaseInsensitive(col: FieldMetadata<any>, val: any): void {
this.orig.containsCaseInsensitive(col, val);
this.commands.push(x => x.containsCaseInsensitive(col, val));
}
startsWith(col: FieldMetadata<any>, val: any): void {
this.orig.startsWith(col, val);
this.commands.push(x => x.startsWith(col, val));
}
isIn(col: FieldMetadata<any>, val: any[]): void {
this.orig.isIn(col, val);
this.commands.push(x => x.isIn(col, val));
}
custom(customItem: any): void {
this.translateCustom(customItem)?.__applyToConsumer(this);
this.promises.push(
(async () => {
let r = await this.translateCustom(customItem);
if (r)
r.__applyToConsumer(this);
})()
)

}
databaseCustom(custom: any) {
this.commands.push(x => x.databaseCustom(custom));
}
async resolve() {
while (this.promises.length > 0) {
let p = this.promises;
this.promises = [];
await Promise.all(p);
}
}
databaseCustom(custom: any) { this.orig.databaseCustom(custom) };

}

Expand Down
21 changes: 14 additions & 7 deletions projects/core/src/tests/test-where-api.spec.ts
Expand Up @@ -63,7 +63,7 @@ describe("custom filter", () => {
for (let id = 0; id < 5; id++) {
await c.create({ id }).save();
}
expect(await (c.count(e => SqlDatabase.customFilter(x => x.sql = c.metadata.fields.id.dbName + ' in (' + x.addParameterAndReturnSqlToken(1) + "," + x.addParameterAndReturnSqlToken(3, c.metadata.fields.id) + ")"))))
expect(await (c.count(e => SqlDatabase.customFilter(x => x.sql = e.id.metadata.dbName + ' in (' + x.addParameterAndReturnSqlToken(1) + "," + x.addParameterAndReturnSqlToken(3, c.metadata.fields.id) + ")"))))
.toBe(2);
expect(await (c.count(e => entityForCustomFilter.filter.build({ dbOneOrThree: true })))).toBe(2);
});
Expand All @@ -77,6 +77,14 @@ describe("custom filter", () => {
expect(await (c.count(e => ArrayEntityDataProvider.customFilter(x => x.id == 1 || x.id == 3))))
.toBe(2);
expect(await (c.count(e => entityForCustomFilter.filter.build({ dbOneOrThree: true })))).toBe(2);

});
itAsync("test or and promise in translate", async () => {
let c = new ServerContext(new InMemoryDataProvider()).for(entityForCustomFilter);
for (let id = 0; id < 5; id++) {
await c.create({ id }).save();
}
expect(await (c.count(e => e.id.isEqualTo(4).or(entityForCustomFilter.filter.build({ dbOneOrThree: true }))))).toBe(3);
});
itAsync("test sent in api", async () => {
let ok = new Done();
Expand All @@ -92,7 +100,7 @@ describe("custom filter", () => {
put: undefined
});
let c = new ServerContext(z);
c.for(entityForCustomFilter).count(e => entityForCustomFilter.filter.build({ oneAndThree: true }));
await c.for(entityForCustomFilter).count(e => entityForCustomFilter.filter.build({ oneAndThree: true }));
ok.test();
});
itAsync("test that api reads custom correctly", async () => {
Expand Down Expand Up @@ -154,13 +162,12 @@ class entityForCustomFilter extends EntityBase {
static filter = new CustomFilterBuilder<entityForCustomFilter, {
oneAndThree?: boolean,
dbOneOrThree?: boolean
}>((e, c) => {
}>(async (e, c) => {
if (c.oneAndThree)
return e.id.isIn([1, 3]);
if (c.dbOneOrThree) {
e.id.isEqualTo
let idcolName = 'id';
return SqlDatabase.customFilter(x => x.sql = idcolName + ' in (' + x.addParameterAndReturnSqlToken(1) + "," + x.addParameterAndReturnSqlToken(3) + ")").and(

return SqlDatabase.customFilter(x => x.sql = e.id.metadata.dbName + ' in (' + x.addParameterAndReturnSqlToken(1) + "," + x.addParameterAndReturnSqlToken(3) + ")").and(
ArrayEntityDataProvider.customFilter(x => x.id == 1 || x.id == 3)
)
}
Expand All @@ -176,7 +183,7 @@ export interface customFilterTranslator<customerFilterType> extends filterFuncti
let x: customFilterTranslator<{ oneOrThree: true }>;


function CustomFilterBuilderBuilder<entityType, customFilterObject =any>(translateFilter: (entityType: FilterFactories<entityType>, customFilter: customFilterObject) => Filter): customFilterTranslator<customFilterObject> {
function CustomFilterBuilderBuilder<entityType, customFilterObject = any>(translateFilter: (entityType: FilterFactories<entityType>, customFilter: customFilterObject) => Filter): customFilterTranslator<customFilterObject> {
return undefined;
}

0 comments on commit 374cb31

Please sign in to comment.