[Flexible-schema] Add findOne and fix findMany pagination + soft-delete for graphql-query-runner (#6978)
This commit is contained in:
+11
-3
@@ -26,15 +26,19 @@ export class GraphqlQueryFilterConditionParser {
|
||||
}
|
||||
|
||||
const result: FindOptionsWhere<ObjectLiteral> = {};
|
||||
let orCondition: FindOptionsWhere<ObjectLiteral>[] | null = null;
|
||||
|
||||
for (const [key, value] of Object.entries(conditions)) {
|
||||
switch (key) {
|
||||
case 'and':
|
||||
return this.parseAndCondition(value, isNegated);
|
||||
Object.assign(result, this.parseAndCondition(value, isNegated));
|
||||
break;
|
||||
case 'or':
|
||||
return this.parseOrCondition(value, isNegated);
|
||||
orCondition = this.parseOrCondition(value, isNegated);
|
||||
break;
|
||||
case 'not':
|
||||
return this.parse(value, !isNegated);
|
||||
Object.assign(result, this.parse(value, !isNegated));
|
||||
break;
|
||||
default:
|
||||
Object.assign(
|
||||
result,
|
||||
@@ -43,6 +47,10 @@ export class GraphqlQueryFilterConditionParser {
|
||||
}
|
||||
}
|
||||
|
||||
if (orCondition) {
|
||||
return orCondition.map((condition) => ({ ...result, ...condition }));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -28,7 +28,15 @@ export class GraphqlQueryFilterOperatorParser {
|
||||
lt: (value: any) => LessThan(value),
|
||||
lte: (value: any) => LessThanOrEqual(value),
|
||||
in: (value: any) => In(value),
|
||||
is: (value: any) => (value === 'NULL' ? IsNull() : value),
|
||||
is: (value: any) => {
|
||||
if (value === 'NULL') {
|
||||
return IsNull();
|
||||
} else if (value === 'NOT_NULL') {
|
||||
return Not(IsNull());
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
like: (value: string) => Like(`%${value}%`),
|
||||
ilike: (value: string) => ILike(`%${value}%`),
|
||||
startsWith: (value: string) => ILike(`${value}%`),
|
||||
|
||||
+31
-8
@@ -23,7 +23,10 @@ export class GraphqlQueryOrderFieldParser {
|
||||
this.fieldMetadataMap = fieldMetadataMap;
|
||||
}
|
||||
|
||||
parse(orderBy: RecordOrderBy): Record<string, FindOptionsOrderValue> {
|
||||
parse(
|
||||
orderBy: RecordOrderBy,
|
||||
isForwardPagination = true,
|
||||
): Record<string, FindOptionsOrderValue> {
|
||||
return orderBy.reduce(
|
||||
(acc, item) => {
|
||||
Object.entries(item).forEach(([key, value]) => {
|
||||
@@ -40,11 +43,15 @@ export class GraphqlQueryOrderFieldParser {
|
||||
const compositeOrder = this.parseCompositeFieldForOrder(
|
||||
fieldMetadata,
|
||||
value,
|
||||
isForwardPagination,
|
||||
);
|
||||
|
||||
Object.assign(acc, compositeOrder);
|
||||
} else {
|
||||
acc[key] = this.convertOrderByToFindOptionsOrder(value);
|
||||
acc[key] = this.convertOrderByToFindOptionsOrder(
|
||||
value,
|
||||
isForwardPagination,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -57,6 +64,7 @@ export class GraphqlQueryOrderFieldParser {
|
||||
private parseCompositeFieldForOrder(
|
||||
fieldMetadata: FieldMetadataInterface,
|
||||
value: any,
|
||||
isForwardPagination = true,
|
||||
): Record<string, FindOptionsOrderValue> {
|
||||
const compositeType = compositeTypeDefinitions.get(
|
||||
fieldMetadata.type as CompositeFieldMetadataType,
|
||||
@@ -87,8 +95,10 @@ export class GraphqlQueryOrderFieldParser {
|
||||
`Sub field order by value must be of type OrderByDirection, but got: ${subFieldValue}`,
|
||||
);
|
||||
}
|
||||
acc[fullFieldName] =
|
||||
this.convertOrderByToFindOptionsOrder(subFieldValue);
|
||||
acc[fullFieldName] = this.convertOrderByToFindOptionsOrder(
|
||||
subFieldValue,
|
||||
isForwardPagination,
|
||||
);
|
||||
|
||||
return acc;
|
||||
},
|
||||
@@ -98,16 +108,29 @@ export class GraphqlQueryOrderFieldParser {
|
||||
|
||||
private convertOrderByToFindOptionsOrder(
|
||||
direction: OrderByDirection,
|
||||
isForwardPagination = true,
|
||||
): FindOptionsOrderValue {
|
||||
switch (direction) {
|
||||
case OrderByDirection.AscNullsFirst:
|
||||
return { direction: 'ASC', nulls: 'FIRST' };
|
||||
return {
|
||||
direction: isForwardPagination ? 'ASC' : 'DESC',
|
||||
nulls: 'FIRST',
|
||||
};
|
||||
case OrderByDirection.AscNullsLast:
|
||||
return { direction: 'ASC', nulls: 'LAST' };
|
||||
return {
|
||||
direction: isForwardPagination ? 'ASC' : 'DESC',
|
||||
nulls: 'LAST',
|
||||
};
|
||||
case OrderByDirection.DescNullsFirst:
|
||||
return { direction: 'DESC', nulls: 'FIRST' };
|
||||
return {
|
||||
direction: isForwardPagination ? 'DESC' : 'ASC',
|
||||
nulls: 'FIRST',
|
||||
};
|
||||
case OrderByDirection.DescNullsLast:
|
||||
return { direction: 'DESC', nulls: 'LAST' };
|
||||
return {
|
||||
direction: isForwardPagination ? 'DESC' : 'ASC',
|
||||
nulls: 'LAST',
|
||||
};
|
||||
default:
|
||||
throw new GraphqlQueryRunnerException(
|
||||
`Invalid direction: ${direction}`,
|
||||
|
||||
+39
-3
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
FindOptionsOrderValue,
|
||||
FindOptionsWhere,
|
||||
IsNull,
|
||||
ObjectLiteral,
|
||||
} from 'typeorm';
|
||||
|
||||
@@ -32,20 +33,55 @@ export class GraphqlQueryParser {
|
||||
|
||||
parseFilter(
|
||||
recordFilter: RecordFilter,
|
||||
shouldAddDefaultSoftDeleteCondition = false,
|
||||
): FindOptionsWhere<ObjectLiteral> | FindOptionsWhere<ObjectLiteral>[] {
|
||||
const graphqlQueryFilterParser = new GraphqlQueryFilterParser(
|
||||
this.fieldMetadataMap,
|
||||
);
|
||||
|
||||
return graphqlQueryFilterParser.parse(recordFilter);
|
||||
const parsedFilter = graphqlQueryFilterParser.parse(recordFilter);
|
||||
|
||||
if (
|
||||
!shouldAddDefaultSoftDeleteCondition ||
|
||||
!('deletedAt' in this.fieldMetadataMap)
|
||||
) {
|
||||
return parsedFilter;
|
||||
}
|
||||
|
||||
return this.addDefaultSoftDeleteCondition(parsedFilter);
|
||||
}
|
||||
|
||||
parseOrder(orderBy: RecordOrderBy): Record<string, FindOptionsOrderValue> {
|
||||
private addDefaultSoftDeleteCondition(
|
||||
filter: FindOptionsWhere<ObjectLiteral> | FindOptionsWhere<ObjectLiteral>[],
|
||||
): FindOptionsWhere<ObjectLiteral> | FindOptionsWhere<ObjectLiteral>[] {
|
||||
if (Array.isArray(filter)) {
|
||||
return filter.map((condition) =>
|
||||
this.addSoftDeleteToCondition(condition),
|
||||
);
|
||||
}
|
||||
|
||||
return this.addSoftDeleteToCondition(filter);
|
||||
}
|
||||
|
||||
private addSoftDeleteToCondition(
|
||||
condition: FindOptionsWhere<ObjectLiteral>,
|
||||
): FindOptionsWhere<ObjectLiteral> {
|
||||
if (!('deletedAt' in condition)) {
|
||||
return { ...condition, deletedAt: IsNull() };
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
parseOrder(
|
||||
orderBy: RecordOrderBy,
|
||||
isForwardPagination = true,
|
||||
): Record<string, FindOptionsOrderValue> {
|
||||
const graphqlQueryOrderParser = new GraphqlQueryOrderParser(
|
||||
this.fieldMetadataMap,
|
||||
);
|
||||
|
||||
return graphqlQueryOrderParser.parse(orderBy);
|
||||
return graphqlQueryOrderParser.parse(orderBy, isForwardPagination);
|
||||
}
|
||||
|
||||
parseSelectedFields(
|
||||
|
||||
Reference in New Issue
Block a user