Skip to content

Commit 8b993f1

Browse files
Mustafa MansourMkMan
Mustafa Mansour
authored andcommitted
feat(wrap): allow making the new field type Nullable
1 parent 1bc4ba9 commit 8b993f1

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

packages/wrap/src/transforms/WrapFields.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ interface WrapFieldsTransformationContext {
3434
paths: Record<string, { pathToField: Array<string>; alias: string }>;
3535
}
3636

37+
interface WrapFieldsConfig {
38+
isNullable?: boolean;
39+
}
40+
3741
export default class WrapFields<TContext extends Record<string, any>>
3842
implements Transform<WrapFieldsTransformationContext, TContext>
3943
{
@@ -43,19 +47,22 @@ export default class WrapFields<TContext extends Record<string, any>>
4347
private readonly numWraps: number;
4448
private readonly fieldNames: Array<string> | undefined;
4549
private readonly transformer: MapFields<TContext>;
50+
private readonly config: WrapFieldsConfig;
4651

4752
constructor(
4853
outerTypeName: string,
4954
wrappingFieldNames: Array<string>,
5055
wrappingTypeNames: Array<string>,
5156
fieldNames?: Array<string>,
5257
prefix = 'gqtld',
58+
config: WrapFieldsConfig = { isNullable: false },
5359
) {
5460
this.outerTypeName = outerTypeName;
5561
this.wrappingFieldNames = wrappingFieldNames;
5662
this.wrappingTypeNames = wrappingTypeNames;
5763
this.numWraps = wrappingFieldNames.length;
5864
this.fieldNames = fieldNames;
65+
this.config = config;
5966

6067
const remainingWrappingFieldNames = this.wrappingFieldNames.slice();
6168
const outerMostWrappingFieldName = remainingWrappingFieldNames.shift();
@@ -167,9 +174,11 @@ export default class WrapFields<TContext extends Record<string, any>>
167174
resolve = defaultMergedResolver;
168175
}
169176

170-
const wrappingType = new GraphQLNonNull(
171-
newSchema.getType(wrappingTypeName) as GraphQLObjectType,
172-
);
177+
const baseType = newSchema.getType(wrappingTypeName) as GraphQLObjectType;
178+
const wrappingType = this.config.isNullable
179+
? baseType
180+
: new GraphQLNonNull(baseType);
181+
173182
const newFieldConfig: GraphQLFieldConfig<any, any> =
174183
wrappingOperation === 'subscription'
175184
? {

packages/wrap/tests/transformWrapFields.test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { makeExecutableSchema } from '@graphql-tools/schema';
22
import { WrapFields, wrapSchema } from '@graphql-tools/wrap';
3-
import { graphql, GraphQLObjectType } from 'graphql';
3+
import { graphql, GraphQLObjectType, isNullableType } from 'graphql';
44
import { describe, expect, test } from 'vitest';
55

66
describe('WrapFields', () => {
@@ -44,7 +44,9 @@ describe('WrapFields', () => {
4444
test('schema is transformed with new type and field', async () => {
4545
const userType = schema.getType('User') as GraphQLObjectType;
4646
const addressType = schema.getType('Address') as GraphQLObjectType;
47+
const addressField = userType.getFields()['address'];
4748

49+
expect(isNullableType(addressField?.type)).toBe(false);
4850
expect(userType.getFields()['address']).toBeDefined();
4951
expect(Object.keys(addressType.getFields()).sort()).toEqual([
5052
'city',
@@ -53,6 +55,27 @@ describe('WrapFields', () => {
5355
]);
5456
});
5557

58+
test('new field is nullable if specified', async () => {
59+
const schema = wrapSchema({
60+
schema: subschema,
61+
transforms: [
62+
new WrapFields(
63+
'User',
64+
['address'],
65+
['Address'],
66+
['street', 'city', 'zipcode'],
67+
undefined,
68+
{ isNullable: true },
69+
),
70+
],
71+
});
72+
73+
const userType = schema.getType('User') as GraphQLObjectType;
74+
const addressField = userType.getFields()['address'];
75+
76+
expect(isNullableType(addressField?.type)).toBe(true);
77+
});
78+
5679
test('select fields are wrapped and queryable', async () => {
5780
const result = await graphql({
5881
schema,

0 commit comments

Comments
 (0)