Skip to content

Commit

Permalink
feat: allow projection as an extension
Browse files Browse the repository at this point in the history
* Allow projection extension
* Rename context to info
  • Loading branch information
stefanprobst authored and nodkz committed Mar 28, 2019
1 parent c7a04c5 commit 9dcbb0c
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 19 deletions.
24 changes: 24 additions & 0 deletions src/utils/__tests__/projection-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ const Level1TC = schemaComposer.createObjectTC({
field1a: { field2a: true },
},
},
withProjectionExtension: {
type: 'Int',
extensions: {
projection: {
field1b: true,
field1a: { field2a: true },
},
},
},
},
});
const resolve = jest.fn(() => ({}));
Expand Down Expand Up @@ -155,6 +164,21 @@ describe('projection', () => {
});
});

it('extend by projection extension', async () => {
const info = await getResolveInfo(`
query {
field0 {
withProjectionExtension
}
}
`);
expect(getProjectionFromAST(info)).toEqual({
withProjectionExtension: {},
field1b: true,
field1a: { field2a: true },
});
});

describe('extendByFieldProjection()', () => {
it('first level', () => {
const type: GraphQLObjectType = (schema.getType('Level1'): any);
Expand Down
4 changes: 2 additions & 2 deletions src/utils/projection.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ export type ProjectionType = {
};

export function getProjectionFromAST(
context: GraphQLResolveInfo,
info: GraphQLResolveInfo,
fieldNode?: FieldNode | InlineFragmentNode | FragmentDefinitionNode,
): ProjectionType;

export function getFlatProjectionFromAST(
context: GraphQLResolveInfo,
info: GraphQLResolveInfo,
fieldNodes?: FieldNode | InlineFragmentNode | FragmentDefinitionNode,
): { [key: string]: boolean };

Expand Down
34 changes: 17 additions & 17 deletions src/utils/projection.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,23 @@ export type ProjectionType = { [fieldName: string]: any };
export type ProjectionNode = { [fieldName: string]: any };

export function getProjectionFromAST(
context: GraphQLResolveInfo,
info: GraphQLResolveInfo,
fieldNode?: FieldNode | InlineFragmentNode | FragmentDefinitionNode
): ProjectionType {
if (!context) {
if (!info) {
return {};
}

const queryProjection = getProjectionFromASTquery(context, fieldNode);
const queryExtProjection = extendByFieldProjection(context.returnType, queryProjection);
const queryProjection = getProjectionFromASTquery(info, fieldNode);
const queryExtProjection = extendByFieldProjection(info.returnType, queryProjection);
return queryExtProjection;
}

export function getProjectionFromASTquery(
context: GraphQLResolveInfo,
info: GraphQLResolveInfo,
fieldNode?: FieldNode | InlineFragmentNode | FragmentDefinitionNode
): ProjectionType {
if (!context) {
if (!info) {
return {};
}

Expand All @@ -51,9 +51,9 @@ export function getProjectionFromASTquery(
if (fieldNode.selectionSet) {
selections = fieldNode.selectionSet.selections;
}
} else if (Array.isArray(context.fieldNodes)) {
} else if (Array.isArray(info.fieldNodes)) {
// get all selectionSets
selections = context.fieldNodes.reduce((result, source) => {
selections = info.fieldNodes.reduce((result, source) => {
if (source.selectionSet) {
result.push(...source.selectionSet.selections);
}
Expand All @@ -67,19 +67,16 @@ export function getProjectionFromASTquery(
case FIELD: {
const { value } = ast.name;
if (res[value]) {
res[value] = deepmerge(res[value], getProjectionFromASTquery(context, ast) || true);
res[value] = deepmerge(res[value], getProjectionFromASTquery(info, ast) || true);
} else {
res[value] = getProjectionFromASTquery(context, ast) || true;
res[value] = getProjectionFromASTquery(info, ast) || true;
}
return res;
}
case INLINE_FRAGMENT:
return deepmerge(res, getProjectionFromASTquery(context, ast));
return deepmerge(res, getProjectionFromASTquery(info, ast));
case FRAGMENT_SPREAD:
return deepmerge(
res,
getProjectionFromASTquery(context, context.fragments[ast.name.value])
);
return deepmerge(res, getProjectionFromASTquery(info, info.fragments[ast.name.value]));
default:
throw new Error('Unsuported query selection');
}
Expand All @@ -91,10 +88,10 @@ export function getProjectionFromASTquery(
}

export function getFlatProjectionFromAST(
context: GraphQLResolveInfo,
info: GraphQLResolveInfo,
fieldNodes?: FieldNode | InlineFragmentNode | FragmentDefinitionNode
) {
const projection = getProjectionFromAST(context, fieldNodes) || {};
const projection = getProjectionFromAST(info, fieldNodes) || {};
const flatProjection = {};
Object.keys(projection).forEach(key => {
flatProjection[key] = !!projection[key];
Expand Down Expand Up @@ -124,6 +121,9 @@ export function extendByFieldProjection(
if (!field) return;

if (field.projection) proj = deepmerge(proj, field.projection);
if (field.extensions && field.extensions.projection) {
proj = deepmerge(proj, field.extensions.projection);
}
proj[key] = extendByFieldProjection((field.type: any), proj[key]);
});

Expand Down

0 comments on commit 9dcbb0c

Please sign in to comment.