Skip to content

Commit

Permalink
Merge branch 'dev' into top-level-interface-connection
Browse files Browse the repository at this point in the history
  • Loading branch information
angrykoala authored Mar 5, 2024
2 parents c198de3 + bf11c81 commit 295bd4a
Show file tree
Hide file tree
Showing 42 changed files with 1,664 additions and 964 deletions.
5 changes: 5 additions & 0 deletions .changeset/violet-penguins-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@neo4j/graphql": patch
---

Fix user defined deprecated directives not propagated on all generated types
324 changes: 162 additions & 162 deletions .yarn/releases/yarn-4.1.0.cjs → .yarn/releases/yarn-4.1.1.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.1.0.cjs
yarnPath: .yarn/releases/yarn-4.1.1.cjs
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
},
"devDependencies": {
"@tsconfig/node16": "1.0.4",
"@typescript-eslint/eslint-plugin": "7.1.0",
"@typescript-eslint/parser": "7.1.0",
"@typescript-eslint/eslint-plugin": "7.1.1",
"@typescript-eslint/parser": "7.1.1",
"concurrently": "8.2.2",
"dotenv": "16.4.5",
"eslint": "8.57.0",
Expand All @@ -37,7 +37,7 @@
"eslint-plugin-import": "2.29.1",
"eslint-plugin-jest": "27.9.0",
"eslint-plugin-jsx-a11y": "6.8.0",
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react": "7.34.0",
"eslint-plugin-simple-import-sort": "12.0.0",
"graphql": "16.8.1",
"husky": "9.0.11",
Expand All @@ -49,7 +49,7 @@
"ts-jest": "29.1.2",
"typescript": "5.1.6"
},
"packageManager": "[email protected].0",
"packageManager": "[email protected].1",
"dependencies": {
"@changesets/changelog-github": "0.5.0",
"@changesets/cli": "2.27.1"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "apollo-federation-subgraph-compatibility",
"version": "1.0.0",
"packageManager": "[email protected].0",
"packageManager": "[email protected].1",
"scripts": {
"build": "webpack --config webpack.config.js",
"test:docker": "yarn build && fedtest docker --compose docker-compose.yml --schema schema.graphql",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,20 +226,25 @@ export function createRelationshipFields({
const deprecatedDirectives = graphqlDirectivesToCompose(
(userDefinedDirectivesOnField || []).filter((directive) => directive.name.value === DEPRECATED)
);
const userDefinedDirectivesOnTargetFields = userDefinedFieldDirectivesForNode.get(
relationshipAdapter.target.name
);

const relationshipFieldsOpts: {
relationshipAdapter: RelationshipAdapter | RelationshipDeclarationAdapter;
composer: SchemaComposer<any>;
composeNode: ObjectTypeComposer<any, any> | InterfaceTypeComposer<any, any>;
userDefinedFieldDirectives: Map<string, DirectiveNode[]>;
deprecatedDirectives: Directive[];
userDefinedDirectivesOnTargetFields: Map<string, DirectiveNode[]> | undefined;
subgraph?: Subgraph;
} = {
relationshipAdapter,
composer: schemaComposer,
composeNode,
userDefinedFieldDirectives,
deprecatedDirectives,
userDefinedDirectivesOnTargetFields,
};

if (relationshipTarget instanceof UnionEntityAdapter) {
Expand Down Expand Up @@ -285,16 +290,23 @@ function createRelationshipFieldsForTarget({
composeNode,
userDefinedFieldDirectives,
deprecatedDirectives,
userDefinedDirectivesOnTargetFields,
subgraph, // only for concrete targets
}: {
relationshipAdapter: RelationshipAdapter | RelationshipDeclarationAdapter;
composer: SchemaComposer;
composeNode: ObjectTypeComposer | InterfaceTypeComposer;
userDefinedFieldDirectives: Map<string, DirectiveNode[]>;
userDefinedDirectivesOnTargetFields: Map<string, DirectiveNode[]> | undefined;
deprecatedDirectives: Directive[];
subgraph?: Subgraph;
}) {
withSourceWhereInputType({ relationshipAdapter, composer, deprecatedDirectives });
withSourceWhereInputType({
relationshipAdapter,
composer,
deprecatedDirectives,
userDefinedDirectivesOnTargetFields,
});

if (relationshipAdapter.target instanceof InterfaceEntityAdapter) {
withFieldInputType({ relationshipAdapter, composer, userDefinedFieldDirectives });
Expand Down
69 changes: 55 additions & 14 deletions packages/graphql/src/schema/generation/aggregate-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import type {
ObjectTypeComposerFieldConfigMapDefinition,
SchemaComposer,
} from "graphql-compose";
import { AGGREGATION_COMPARISON_OPERATORS } from "../../constants";
import { AGGREGATION_COMPARISON_OPERATORS, DEPRECATED } from "../../constants";
import type { AttributeAdapter } from "../../schema-model/attribute/model-adapters/AttributeAdapter";
import { ConcreteEntityAdapter } from "../../schema-model/entity/model-adapters/ConcreteEntityAdapter";
import type { InterfaceEntityAdapter } from "../../schema-model/entity/model-adapters/InterfaceEntityAdapter";
Expand Down Expand Up @@ -84,10 +84,12 @@ export function withAggregateInputType({
relationshipAdapter,
entityAdapter, // TODO: this is relationshipAdapter.target but from the context above it is known to be ConcreteEntity and we don't know this yet!!!
composer,
userDefinedDirectivesOnTargetFields,
}: {
relationshipAdapter: RelationshipAdapter | RelationshipDeclarationAdapter;
entityAdapter: ConcreteEntityAdapter;
composer: SchemaComposer;
userDefinedDirectivesOnTargetFields: Map<string, DirectiveNode[]> | undefined;
}): InputTypeComposer {
const aggregateInputTypeName = relationshipAdapter.operations.aggregateInputTypeName;
if (composer.has(aggregateInputTypeName)) {
Expand All @@ -113,6 +115,7 @@ export function withAggregateInputType({
relationshipAdapter,
entityAdapter,
composer,
userDefinedDirectivesOnTargetFields,
});
if (nodeWhereInputType) {
aggregateSelection.addFields({ node: nodeWhereInputType });
Expand All @@ -121,6 +124,7 @@ export function withAggregateInputType({
relationshipAdapter,
entityAdapter: relationshipAdapter,
composer,
userDefinedDirectivesOnTargetFields,
});
if (edgeWhereInputType) {
aggregateSelection.addFields({ edge: edgeWhereInputType });
Expand All @@ -132,10 +136,12 @@ function withAggregationWhereInputType({
relationshipAdapter,
entityAdapter,
composer,
userDefinedDirectivesOnTargetFields,
}: {
relationshipAdapter: RelationshipAdapter | RelationshipDeclarationAdapter;
entityAdapter: ConcreteEntityAdapter | RelationshipAdapter | RelationshipDeclarationAdapter;
composer: SchemaComposer;
userDefinedDirectivesOnTargetFields: Map<string, DirectiveNode[]> | undefined;
}): InputTypeComposer | undefined {
const aggregationInputName =
entityAdapter instanceof ConcreteEntityAdapter
Expand All @@ -160,20 +166,31 @@ function withAggregationWhereInputType({
OR: aggregationInput.NonNull.List,
NOT: aggregationInput,
});
aggregationInput.addFields(makeAggregationFields(aggregationFields));
aggregationInput.addFields(makeAggregationFields(aggregationFields, userDefinedDirectivesOnTargetFields));
return aggregationInput;
}

function makeAggregationFields(attributes: AttributeAdapter[]): InputTypeComposerFieldConfigMapDefinition {
function makeAggregationFields(
attributes: AttributeAdapter[],
userDefinedDirectivesOnTargetFields: Map<string, DirectiveNode[]> | undefined
): InputTypeComposerFieldConfigMapDefinition {
const aggregationFields = attributes
.map((attribute) => getAggregationFieldsByType(attribute))
.map((attribute) =>
getAggregationFieldsByType(attribute, userDefinedDirectivesOnTargetFields?.get(attribute.name))
)
.reduce((acc, el) => ({ ...acc, ...el }), {});
return aggregationFields;
}

// TODO: refactor this by introducing specialized Adapters
function getAggregationFieldsByType(attribute: AttributeAdapter): InputTypeComposerFieldConfigMapDefinition {
function getAggregationFieldsByType(
attribute: AttributeAdapter,
directivesOnField: DirectiveNode[] | undefined
): InputTypeComposerFieldConfigMapDefinition {
const fields: InputTypeComposerFieldConfigMapDefinition = {};
const deprecatedDirectives = graphqlDirectivesToCompose(
(directivesOnField || []).filter((d) => d.name.value === DEPRECATED)
);
if (attribute.typeHelper.isID()) {
fields[`${attribute.name}_EQUAL`] = {
type: GraphQLID,
Expand All @@ -199,9 +216,18 @@ function getAggregationFieldsByType(attribute: AttributeAdapter): InputTypeCompo
type: GraphQLInt,
directives: [DEPRECATE_IMPLICIT_LENGTH_AGGREGATION_FILTERS],
};
fields[`${attribute.name}_AVERAGE_LENGTH_${operator}`] = GraphQLFloat;
fields[`${attribute.name}_LONGEST_LENGTH_${operator}`] = GraphQLInt;
fields[`${attribute.name}_SHORTEST_LENGTH_${operator}`] = GraphQLInt;
fields[`${attribute.name}_AVERAGE_LENGTH_${operator}`] = {
type: GraphQLFloat,
directives: deprecatedDirectives,
};
fields[`${attribute.name}_LONGEST_LENGTH_${operator}`] = {
type: GraphQLInt,
directives: deprecatedDirectives,
};
fields[`${attribute.name}_SHORTEST_LENGTH_${operator}`] = {
type: GraphQLInt,
directives: deprecatedDirectives,
};
}
return fields;
}
Expand All @@ -215,17 +241,26 @@ function getAggregationFieldsByType(attribute: AttributeAdapter): InputTypeCompo
type: attribute.getTypeName(),
directives: [DEPRECATE_INVALID_AGGREGATION_FILTERS],
};
fields[`${attribute.name}_MIN_${operator}`] = attribute.getTypeName();
fields[`${attribute.name}_MAX_${operator}`] = attribute.getTypeName();
fields[`${attribute.name}_MIN_${operator}`] = {
type: attribute.getTypeName(),
directives: deprecatedDirectives,
};
fields[`${attribute.name}_MAX_${operator}`] = {
type: attribute.getTypeName(),
directives: deprecatedDirectives,
};
if (attribute.getTypeName() !== "Duration") {
fields[`${attribute.name}_SUM_${operator}`] = attribute.getTypeName();
fields[`${attribute.name}_SUM_${operator}`] = {
type: attribute.getTypeName(),
directives: deprecatedDirectives,
};
}
const averageType = attribute.typeHelper.isBigInt()
? "BigInt"
: attribute.typeHelper.isDuration()
? "Duration"
: GraphQLFloat;
fields[`${attribute.name}_AVERAGE_${operator}`] = averageType;
fields[`${attribute.name}_AVERAGE_${operator}`] = { type: averageType, directives: deprecatedDirectives };
}
return fields;
}
Expand All @@ -234,8 +269,14 @@ function getAggregationFieldsByType(attribute: AttributeAdapter): InputTypeCompo
type: attribute.getTypeName(),
directives: [DEPRECATE_INVALID_AGGREGATION_FILTERS],
};
fields[`${attribute.name}_MIN_${operator}`] = attribute.getTypeName();
fields[`${attribute.name}_MAX_${operator}`] = attribute.getTypeName();
fields[`${attribute.name}_MIN_${operator}`] = {
type: attribute.getTypeName(),
directives: deprecatedDirectives,
};
fields[`${attribute.name}_MAX_${operator}`] = {
type: attribute.getTypeName(),
directives: deprecatedDirectives,
};
}
return fields;
}
3 changes: 3 additions & 0 deletions packages/graphql/src/schema/generation/where-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,12 @@ export function withSourceWhereInputType({
relationshipAdapter,
composer,
deprecatedDirectives,
userDefinedDirectivesOnTargetFields,
}: {
relationshipAdapter: RelationshipAdapter | RelationshipDeclarationAdapter;
composer: SchemaComposer;
deprecatedDirectives: Directive[];
userDefinedDirectivesOnTargetFields: Map<string, DirectiveNode[]> | undefined;
}): InputTypeComposer | undefined {
const relationshipTarget = relationshipAdapter.target;
const relationshipSource = relationshipAdapter.source;
Expand All @@ -183,6 +185,7 @@ export function withSourceWhereInputType({
relationshipAdapter,
entityAdapter: relationshipTarget,
composer: composer,
userDefinedDirectivesOnTargetFields,
});

if (relationshipAdapter.isFilterableByAggregate()) {
Expand Down
39 changes: 25 additions & 14 deletions packages/graphql/tests/integration/issues/1150.int.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { gql } from "graphql-tag";
import type { Driver } from "neo4j-driver";
import { Neo4jGraphQL } from "../../../src";
import { createBearerToken } from "../../utils/create-bearer-token";
import { UniqueType } from "../../utils/graphql-types";
import Neo4jHelper from "../neo4j";

describe("https://github.com/neo4j/graphql/issues/1150", () => {
Expand All @@ -31,45 +32,55 @@ describe("https://github.com/neo4j/graphql/issues/1150", () => {
let driver: Driver;
let neo4j: Neo4jHelper;

let Battery: UniqueType;
let CombustionEngine: UniqueType;
let Drive: UniqueType;
let DriveComposition: UniqueType;

beforeAll(async () => {
neo4j = new Neo4jHelper();
driver = await neo4j.getDriver();

Battery = new UniqueType("Battery");
CombustionEngine = new UniqueType("CombustionEngine");
Drive = new UniqueType("Drive");
DriveComposition = new UniqueType("DriveComposition");

const typeDefs = gql`
type JWTPayload @jwt {
roles: [String!]!
}
type Battery {
type ${Battery} {
id: ID! @unique
current: Boolean!
}
extend type Battery
extend type ${Battery}
@authorization(validate: [{ when: [BEFORE], where: { jwt: { roles_INCLUDES: "admin" } } }])
type CombustionEngine {
type ${CombustionEngine} {
id: ID! @unique
current: Boolean!
}
type Drive {
type ${Drive} {
id: ID! @unique
current: Boolean!
driveCompositions: [DriveComposition!]!
driveCompositions: [${DriveComposition}!]!
@relationship(type: "CONSISTS_OF", properties: "RelationProps", direction: OUT)
}
union DriveComponent = Battery | CombustionEngine
union DriveComponent = ${Battery} | ${CombustionEngine}
type DriveComposition {
type ${DriveComposition} {
id: ID! @unique
current: Boolean!
driveComponent: [DriveComponent!]!
@relationship(type: "HAS", properties: "RelationProps", direction: OUT)
}
type RelationProps @relationshipProperties {
type RelationProps @relationshipProperties {
current: Boolean!
}
`;
Expand All @@ -92,26 +103,26 @@ describe("https://github.com/neo4j/graphql/issues/1150", () => {
test("should handle union types with auth and connection-where", async () => {
const query = /* GraphQL */ `
query getDrivesWithFilteredUnionType {
drives(where: { current: true }) {
${Drive.plural}(where: { current: true }) {
current
driveCompositionsConnection(where: { edge: { current: true } }) {
edges {
node {
driveComponentConnection(
where: {
Battery: { edge: { current: true } }
CombustionEngine: { edge: { current: true } }
${Battery}: { edge: { current: true } }
${CombustionEngine}: { edge: { current: true } }
}
) {
edges {
properties {
current
}
node {
... on Battery {
... on ${Battery} {
id
}
... on CombustionEngine {
... on ${CombustionEngine} {
id
}
}
Expand All @@ -133,6 +144,6 @@ describe("https://github.com/neo4j/graphql/issues/1150", () => {

expect(res.errors).toBeUndefined();

expect(res.data).toEqual({ drives: [] });
expect(res.data).toEqual({ [Drive.plural]: [] });
});
});
Loading

0 comments on commit 295bd4a

Please sign in to comment.