Skip to content

BACKLOG-22337: Implement new GraphQLDirectiveProvider for validation #396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@
import java.util.stream.Collectors;

@Component(service = GraphQLProvider.class, immediate = true)
public class DXGraphQLProvider implements GraphQLTypesProvider, GraphQLQueryProvider, GraphQLMutationProvider, GraphQLSubscriptionProvider, GraphQLCodeRegistryProvider, DXGraphQLExtensionsProvider {
public class DXGraphQLProvider implements
GraphQLTypesProvider, GraphQLQueryProvider, GraphQLMutationProvider, GraphQLDirectiveProvider,
GraphQLSubscriptionProvider, GraphQLCodeRegistryProvider, DXGraphQLExtensionsProvider
{
private static Logger logger = LoggerFactory.getLogger(DXGraphQLProvider.class);

private static DXGraphQLProvider instance;
Expand Down Expand Up @@ -304,6 +307,11 @@ public Collection<GraphQLType> getTypes() {
return types;
}

@Override
public Collection<GraphQLDirective> getDirectives() {
return sdlSchemaService.getDirectives();
}

@Override
public Collection<GraphQLFieldDefinition> getQueries() {
List<GraphQLFieldDefinition> defs = new ArrayList<>(queryType.getFieldDefinitions());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@
import java.net.URL;
import java.text.MessageFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static graphql.Scalars.GraphQLBoolean;
import static graphql.Scalars.GraphQLString;
import static org.jahia.modules.graphql.provider.dxm.sdl.SDLConstants.*;

@Component(service = SDLSchemaService.class, immediate = true)
public class SDLSchemaService {
Expand Down Expand Up @@ -198,17 +200,16 @@ public List<GraphQLFieldDefinition> getSDLQueries() {

List<GraphQLFieldDefinition> fieldDefinitions = graphQLSchema.getQueryType().getFieldDefinitions();
for (GraphQLFieldDefinition fieldDefinition : fieldDefinitions) {
GraphQLObjectType objectType = fieldDefinition.getType() instanceof GraphQLList ?
(GraphQLObjectType) ((GraphQLList) fieldDefinition.getType()).getWrappedType() : (GraphQLObjectType) fieldDefinition.getType();

GraphQLAppliedDirective directive = objectType.getAppliedDirective(SDLConstants.MAPPING_DIRECTIVE);
GraphQLDirectiveContainer directiveContainer = fieldDefinition.getType() instanceof GraphQLList ?
(GraphQLDirectiveContainer) ((GraphQLList) fieldDefinition.getType()).getWrappedType() :
(GraphQLDirectiveContainer) fieldDefinition.getType();

GraphQLAppliedDirective directive = directiveContainer.getAppliedDirective(SDLConstants.MAPPING_DIRECTIVE);
if (directive == null) {
continue;
}

String nodeType = directive.getArgument(SDLConstants.MAPPING_DIRECTIVE_NODE).getValue().toString();

//Handle connections
if (fieldDefinition.getName().contains(SDLConstants.CONNECTION_QUERY_SUFFIX)) {
String queryFieldName = fieldDefinition.getName().replace(SDLConstants.CONNECTION_QUERY_SUFFIX, "");
Expand Down Expand Up @@ -256,6 +257,21 @@ public List<GraphQLType> getSDLTypes() {
return types;
}

public Set<GraphQLDirective> getDirectives() {
Set<GraphQLDirective> result = new HashSet<>();
if (graphQLSchema == null) {
generateSchema();
}

if (graphQLSchema != null) {
List<GraphQLDirective> directives = graphQLSchema.getDirectives();
if (directives != null) {
result.addAll(directives);
}
}
return result;
}

public GraphQLSchema getGraphQLSchema() {
return graphQLSchema;
}
Expand Down Expand Up @@ -334,27 +350,27 @@ private void applyDefaultFetcher(final List<GraphQLFieldDefinition> defs, final

private TypeDefinitionRegistry prepareTypeRegistryDefinition() {
TypeDefinitionRegistry typeDefinitionRegistry = new TypeDefinitionRegistry();
typeDefinitionRegistry.add(new ObjectTypeDefinition("Query"));
Function<GraphQLScalarType, TypeName> newType = scalar -> new TypeName(scalar.getName());

typeDefinitionRegistry.add(ObjectTypeDefinition.newObjectTypeDefinition().name("Query")
.fieldDefinition(new FieldDefinition("_empty", newType.apply(GraphQLBoolean)))
.build());
typeDefinitionRegistry.add(new ScalarTypeDefinition("Date"));
typeDefinitionRegistry.add(DirectiveDefinition.newDirectiveDefinition()
.name(SDLConstants.MAPPING_DIRECTIVE)
.directiveLocations(Arrays.asList(
DirectiveLocation.newDirectiveLocation().name("OBJECT").build(),
DirectiveLocation.newDirectiveLocation().name("FIELD_DEFINITION").build()))
new DirectiveLocation("OBJECT"),
new DirectiveLocation("FIELD_DEFINITION") ))
.inputValueDefinitions(Arrays.asList(
InputValueDefinition.newInputValueDefinition().name(SDLConstants.MAPPING_DIRECTIVE_NODE).type(TypeName.newTypeName(GraphQLString.getName()).build()).build(),
InputValueDefinition.newInputValueDefinition().name(SDLConstants.MAPPING_DIRECTIVE_PROPERTY).type(TypeName.newTypeName(GraphQLString.getName()).build()).build(),
InputValueDefinition.newInputValueDefinition().name(SDLConstants.MAPPING_DIRECTIVE_IGNORE_DEFAULT_QUERIES).type(TypeName.newTypeName(GraphQLBoolean.getName()).build()).build()))
new InputValueDefinition(MAPPING_DIRECTIVE_NODE, newType.apply(GraphQLString)),
new InputValueDefinition(MAPPING_DIRECTIVE_PROPERTY, newType.apply(GraphQLString)),
new InputValueDefinition(MAPPING_DIRECTIVE_IGNORE_DEFAULT_QUERIES, newType.apply(GraphQLBoolean)) ))
.build());

typeDefinitionRegistry.add(DirectiveDefinition.newDirectiveDefinition()
.name(SDLConstants.FETCHER_DIRECTIVE)
.directiveLocations(Arrays.asList(
DirectiveLocation.newDirectiveLocation().name("FIELD_DEFINITION").build()))
.inputValueDefinitions(Arrays.asList(
InputValueDefinition.newInputValueDefinition().name(SDLConstants.FETCHER_DIRECTIVE_NAME).type(TypeName.newTypeName(GraphQLString.getName()).build()).build()))
.name(FETCHER_DIRECTIVE)
.directiveLocation(new DirectiveLocation("FIELD_DEFINITION"))
.inputValueDefinition(new InputValueDefinition(FETCHER_DIRECTIVE_NAME, newType.apply(GraphQLString)))
.build());

return typeDefinitionRegistry;
}

Expand All @@ -365,7 +381,7 @@ private void handleCustomConnectionTypes(TypeDefinitionRegistry typeDefinitionRe
ObjectTypeExtensionDefinition query = typeDefinitionRegistry.objectTypeExtensions().get("Query").get(queryIndex);
List<FieldDefinition> fields = query.getFieldDefinitions();

//Collect connection fields i. e. ones that map to <TypeName>Connection
//Collect connection fields i.e. ones that map to <TypeName>Connection
for (FieldDefinition f : fields) {
if (f.getName().endsWith(SDLConstants.CONNECTION_QUERY_SUFFIX) && f.getType() instanceof TypeName) {
String connectionName = ((TypeName) f.getType()).getName();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
directive @mapping(node : String, property: String, ignoreDefaultQueries: Boolean) on FIELD_DEFINITION

"""This is news"""
type NewsSDL @mapping(node:"jnt:news", ignoreDefaultQueries: true) {
"""This is title"""
Expand Down Expand Up @@ -28,4 +26,4 @@ extend type Query {
myNewsByDate: [NewsSDL]
"""This is myImagesByHeight"""
myImagesByHeight: [Images]
}
}
33 changes: 33 additions & 0 deletions tests/cypress/e2e/sdl/sdlExtensions.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
getCoreSdlExtensions,
getExampleSdlExtensions
} from '../../fixtures/sdl/sdlExtensions';

describe('SDL extensions', () => {
it('should have SDL extensions defined in dxm-provider module', () => {
cy.apollo({query: getCoreSdlExtensions}).then((response) => {
const {category, imageAsset} = response?.data || {};
expect(category?.fields?.map(f => f.name)).to.deep.eq(
['metadata', 'description', 'title']
);
expect(imageAsset?.fields?.map(f => f.name)).to.deep.eq(
['metadata', 'type', 'size', 'height', 'width']
);
});
});

it('should have SDL extensions defined in extension-examples module', () => {
cy.apollo({query: getExampleSdlExtensions}).then((response) => {
const {newsSdl, images, queries} = response?.data || {};
expect(newsSdl?.fields?.map(f => f.name)).to.deep.eq(
['title', 'description', 'checked', 'date']
);
expect(images?.fields?.map(f => f.name)).to.deep.eq(
['height']
);
['newsByChecked', 'myNewsByDate', 'myImagesByHeight'].forEach(queryField => {
expect(queries?.fields?.find(f => f.name === queryField)).to.exist;
});
});
});
});
26 changes: 26 additions & 0 deletions tests/cypress/fixtures/sdl/sdlExtensions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import gql from 'graphql-tag';

export const getCoreSdlExtensions = gql`
query coreSdlExtensions {
category: __type(name: "Category") {
fields {name}
},
imageAsset: __type(name: "ImageAsset") {
fields {name}
}
}
`;

export const getExampleSdlExtensions = gql`
query exampleSdlExtensions {
newsSdl: __type(name:"NewsSDL") {
fields {name}
}
images: __type(name:"Images") {
fields {name}
}
queries: __type(name: "Query") {
fields {name}
}
}
`;