Gql direct execution - Improvements (#18972)
#### Direct Execution __typename & null backfill ##### __typename filling The direct execution path now correctly derives __typename at every level of the GraphQL response: Connection types — CompanyConnection, CompanyEdge, Company, PageInfo GroupBy types — TaskGroupByConnection (was incorrectly producing TaskConnection) Composite fields — Links, FullName, Currency, etc. handled by a dedicated formatter (was inheriting the parent object's typename) Previously, __typename was derived from the object's universal identifier (a UUID), producing broken values like 20202020B3744779A56180086Cb2E17FConnection. ##### Null backfill Selected fields missing from the resolver result are backfilled with null, matching the standard Yoga schema behavior. ##### Integration test A new test runs the same findMany query (with __typename at all structural levels) through both paths — standard Yoga schema and direct execution — and asserts identical output via toStrictEqual.
This commit is contained in:
+6
@@ -1,9 +1,15 @@
|
||||
import { DataArgProcessorService } from 'src/engine/api/common/common-args-processors/data-arg-processor/data-arg-processor.service';
|
||||
import { FilterArgProcessorService } from 'src/engine/api/common/common-args-processors/filter-arg-processor/filter-arg-processor.service';
|
||||
import { GroupByArgProcessorService } from 'src/engine/api/common/common-args-processors/group-by-arg-processor/group-by-arg-processor.service';
|
||||
import { OrderByArgProcessorService } from 'src/engine/api/common/common-args-processors/order-by-arg-processor/order-by-arg-processor.service';
|
||||
import { OrderByWithGroupByArgProcessorService } from 'src/engine/api/common/common-args-processors/order-by-with-group-by-arg-processor/order-by-with-group-by-arg-processor.service';
|
||||
import { QueryRunnerArgsFactory } from 'src/engine/api/common/common-args-processors/query-runner-args.factory';
|
||||
|
||||
export const CommonArgsProcessors = [
|
||||
DataArgProcessorService,
|
||||
FilterArgProcessorService,
|
||||
GroupByArgProcessorService,
|
||||
OrderByArgProcessorService,
|
||||
OrderByWithGroupByArgProcessorService,
|
||||
QueryRunnerArgsFactory,
|
||||
]; // TODO: Refacto-common Remove QueryRunnerArgsFactory
|
||||
|
||||
+2
-1
@@ -1,9 +1,10 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
import { isNullEquivalentArrayFieldValue } from 'src/engine/api/common/common-args-processors/data-arg-processor/utils/is-null-equivalent-array-field-value.util';
|
||||
|
||||
export const transformArrayField = (
|
||||
value: string | string[] | null,
|
||||
): string[] | null => {
|
||||
if (typeof value === 'string') return [value];
|
||||
if (isString(value)) return [value];
|
||||
|
||||
return isNullEquivalentArrayFieldValue(value) ? null : value;
|
||||
};
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import {
|
||||
ObjectRecordGroupByForAtomicField,
|
||||
ObjectRecordGroupByForCompositeField,
|
||||
ObjectRecordGroupByForDateField,
|
||||
} from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
|
||||
|
||||
@Injectable()
|
||||
export class GroupByArgProcessorService {
|
||||
process({
|
||||
groupBy,
|
||||
}: {
|
||||
groupBy:
|
||||
| ObjectRecordGroupByForAtomicField
|
||||
| ObjectRecordGroupByForCompositeField
|
||||
| ObjectRecordGroupByForDateField
|
||||
| Array<
|
||||
| ObjectRecordGroupByForAtomicField
|
||||
| ObjectRecordGroupByForCompositeField
|
||||
| ObjectRecordGroupByForDateField
|
||||
>;
|
||||
}): Array<
|
||||
| ObjectRecordGroupByForAtomicField
|
||||
| ObjectRecordGroupByForCompositeField
|
||||
| ObjectRecordGroupByForDateField
|
||||
> {
|
||||
if (Array.isArray(groupBy)) {
|
||||
return groupBy;
|
||||
}
|
||||
|
||||
return [groupBy];
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ObjectRecordOrderBy } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
|
||||
import {
|
||||
ObjectRecordOrderByForCompositeField,
|
||||
ObjectRecordOrderByForScalarField,
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@Injectable()
|
||||
export class OrderByArgProcessorService {
|
||||
process({
|
||||
orderBy,
|
||||
}: {
|
||||
orderBy:
|
||||
| undefined
|
||||
| ObjectRecordOrderByForScalarField
|
||||
| ObjectRecordOrderByForCompositeField
|
||||
| ObjectRecordOrderBy;
|
||||
}): ObjectRecordOrderBy | undefined {
|
||||
if (Array.isArray(orderBy) || !isDefined(orderBy)) {
|
||||
return orderBy;
|
||||
}
|
||||
|
||||
return [orderBy];
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import {
|
||||
OrderByWithGroupBy,
|
||||
type AggregateOrderByWithGroupByField,
|
||||
type ObjectRecordOrderByForCompositeField,
|
||||
type ObjectRecordOrderByForRelationField,
|
||||
type ObjectRecordOrderByForScalarField,
|
||||
type ObjectRecordOrderByWithGroupByDateField,
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@Injectable()
|
||||
export class OrderByWithGroupByArgProcessorService {
|
||||
process({
|
||||
orderBy,
|
||||
}: {
|
||||
orderBy:
|
||||
| undefined
|
||||
| ObjectRecordOrderByForScalarField
|
||||
| ObjectRecordOrderByForCompositeField
|
||||
| ObjectRecordOrderByWithGroupByDateField
|
||||
| ObjectRecordOrderByForRelationField
|
||||
| AggregateOrderByWithGroupByField
|
||||
| OrderByWithGroupBy;
|
||||
}): OrderByWithGroupBy | undefined {
|
||||
if (Array.isArray(orderBy) || !isDefined(orderBy)) {
|
||||
return orderBy;
|
||||
}
|
||||
|
||||
return [orderBy];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user