@neo4j/graphql
Version:
A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations
249 lines • 12.9 kB
JavaScript
"use strict";
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRelationshipFields = createRelationshipFields;
const graphql_1 = require("graphql");
const graphql_compose_1 = require("graphql-compose");
const constants_1 = require("../../constants");
const ConcreteEntityAdapter_1 = require("../../schema-model/entity/model-adapters/ConcreteEntityAdapter");
const InterfaceEntityAdapter_1 = require("../../schema-model/entity/model-adapters/InterfaceEntityAdapter");
const UnionEntityAdapter_1 = require("../../schema-model/entity/model-adapters/UnionEntityAdapter");
const RelationshipAdapter_1 = require("../../schema-model/relationship/model-adapters/RelationshipAdapter");
const RelationshipDeclarationAdapter_1 = require("../../schema-model/relationship/model-adapters/RelationshipDeclarationAdapter");
const field_aggregation_composer_1 = require("../aggregations/field-aggregation-composer");
const augment_object_or_interface_1 = require("../generation/augment-object-or-interface");
const connect_input_1 = require("../generation/connect-input");
const create_input_1 = require("../generation/create-input");
const delete_input_1 = require("../generation/delete-input");
const disconnect_input_1 = require("../generation/disconnect-input");
const edge_wrapper_type_1 = require("../generation/edge-wrapper-type");
const object_type_1 = require("../generation/object-type");
const relation_input_1 = require("../generation/relation-input");
const sort_and_options_input_1 = require("../generation/sort-and-options-input");
const update_input_1 = require("../generation/update-input");
const where_input_1 = require("../generation/where-input");
const to_compose_1 = require("../to-compose");
function doForRelationshipDeclaration({ relationshipDeclarationAdapter, composer, }) {
// creates the type for the `edge` field that contains all possible implementations of a declared relationship
// an implementation being a relationship directive with different `properties` value
for (const relationshipAdapter of relationshipDeclarationAdapter.relationshipImplementations) {
if (!relationshipAdapter.propertiesTypeName) {
continue;
}
const propertiesType = composer
.getOrCreateUTC(relationshipDeclarationAdapter.operations.relationshipPropertiesFieldTypename)
.addType(relationshipAdapter.propertiesTypeName);
composer.getOrCreateOTC(relationshipDeclarationAdapter.operations.relationshipFieldTypename, (tc) => tc.addFields({
cursor: new graphql_1.GraphQLNonNull(graphql_1.GraphQLString),
node: `${relationshipDeclarationAdapter.target.name}!`,
properties: propertiesType.NonNull,
}));
(0, edge_wrapper_type_1.withEdgeWrapperType)({
edgeTypeName: relationshipDeclarationAdapter.operations.whereInputTypeName,
edgeFieldTypeName: relationshipAdapter.operations.whereInputTypeName,
edgeFieldAdapter: relationshipAdapter,
composer,
});
(0, edge_wrapper_type_1.withEdgeWrapperType)({
edgeTypeName: relationshipDeclarationAdapter.operations.sortInputTypeName,
edgeFieldTypeName: relationshipAdapter.operations.sortInputTypeName,
edgeFieldAdapter: relationshipAdapter,
composer,
});
if (relationshipAdapter.hasCreateInputFields) {
(0, edge_wrapper_type_1.withEdgeWrapperType)({
edgeTypeName: relationshipDeclarationAdapter.operations.createInputTypeName,
edgeFieldTypeName: relationshipAdapter.operations.edgeCreateInputTypeName,
edgeFieldAdapter: relationshipAdapter,
composer,
});
}
if (relationshipAdapter.hasUpdateInputFields) {
(0, edge_wrapper_type_1.withEdgeWrapperType)({
edgeTypeName: relationshipDeclarationAdapter.operations.edgeUpdateInputTypeName,
edgeFieldTypeName: relationshipAdapter.operations.edgeUpdateInputTypeName,
edgeFieldAdapter: relationshipAdapter,
composer,
});
}
if (relationshipAdapter.aggregationWhereFields) {
(0, edge_wrapper_type_1.withEdgeWrapperType)({
edgeTypeName: relationshipDeclarationAdapter.operations.edgeAggregationWhereInputTypeName,
edgeFieldTypeName: relationshipAdapter.operations.edgeAggregationWhereInputTypeName,
edgeFieldAdapter: relationshipAdapter,
composer,
});
}
}
}
function doForRelationshipPropertiesType({ composer, relationshipAdapter, userDefinedDirectivesForNode, userDefinedFieldDirectivesForNode, features, }) {
if (!relationshipAdapter.propertiesTypeName) {
return;
}
const userDefinedFieldDirectives = userDefinedFieldDirectivesForNode.get(relationshipAdapter.propertiesTypeName);
const userDefinedInterfaceDirectives = userDefinedDirectivesForNode.get(relationshipAdapter.name) || [];
(0, object_type_1.withObjectType)({
entityAdapter: relationshipAdapter,
userDefinedFieldDirectives,
userDefinedObjectDirectives: userDefinedInterfaceDirectives,
composer,
});
(0, sort_and_options_input_1.withSortInputType)({ relationshipAdapter, userDefinedFieldDirectives, composer });
(0, update_input_1.withUpdateInputType)({ entityAdapter: relationshipAdapter, userDefinedFieldDirectives, composer, features });
(0, where_input_1.withWhereInputType)({
entityAdapter: relationshipAdapter,
userDefinedFieldDirectives,
features,
composer,
});
(0, create_input_1.withCreateInputType)({ entityAdapter: relationshipAdapter, userDefinedFieldDirectives, composer });
}
function createRelationshipFields({ entityAdapter, schemaComposer,
// TODO: Ideally we come up with a solution where we don't have to pass the following into these kind of functions
composeNode, subgraph, userDefinedFieldDirectives, seenRelationshipPropertiesTypes, userDefinedDirectivesForNode, userDefinedFieldDirectivesForNode, features, complexityEstimatorHelper, }) {
const relationships = entityAdapter instanceof ConcreteEntityAdapter_1.ConcreteEntityAdapter
? entityAdapter.relationships
: entityAdapter.relationshipDeclarations;
if (!relationships.size) {
return;
}
relationships.forEach((relationshipAdapter) => {
if (!relationshipAdapter) {
return;
}
if (!relationshipAdapter.isList) {
throw new Error(`@relationship on non-list field [${relationshipAdapter.source.name}.${relationshipAdapter.name}] not supported`);
}
// TODO: find a way to merge these 2 into 1 RelationshipProperties generation function
if (relationshipAdapter instanceof RelationshipDeclarationAdapter_1.RelationshipDeclarationAdapter) {
doForRelationshipDeclaration({
relationshipDeclarationAdapter: relationshipAdapter,
composer: schemaComposer,
});
}
if (relationshipAdapter instanceof RelationshipAdapter_1.RelationshipAdapter) {
if (relationshipAdapter.propertiesTypeName) {
if (seenRelationshipPropertiesTypes.has(relationshipAdapter.propertiesTypeName)) {
// update description
const propertiesObjectType = schemaComposer.getOTC(relationshipAdapter.propertiesTypeName);
propertiesObjectType.setDescription((0, object_type_1.getRelationshipPropertiesTypeDescription)({ relationshipAdapter, propertiesObjectType }));
}
else {
doForRelationshipPropertiesType({
composer: schemaComposer,
relationshipAdapter,
userDefinedDirectivesForNode,
userDefinedFieldDirectivesForNode,
features,
});
seenRelationshipPropertiesTypes.add(relationshipAdapter.propertiesTypeName);
}
}
}
const relationshipTarget = relationshipAdapter.target;
const userDefinedDirectivesOnField = userDefinedFieldDirectives.get(relationshipAdapter.name);
const deprecatedDirectives = (0, to_compose_1.graphqlDirectivesToCompose)((userDefinedDirectivesOnField || []).filter((directive) => directive.name.value === constants_1.DEPRECATED));
const userDefinedDirectivesOnTargetFields = userDefinedFieldDirectivesForNode.get(relationshipAdapter.target.name);
const relationshipFieldsOpts = {
relationshipAdapter,
composer: schemaComposer,
composeNode,
userDefinedFieldDirectives,
deprecatedDirectives,
userDefinedDirectivesOnTargetFields,
features,
complexityEstimatorHelper,
};
if (relationshipTarget instanceof UnionEntityAdapter_1.UnionEntityAdapter) {
createRelationshipFieldsForTarget(relationshipFieldsOpts);
return;
}
if (composeNode instanceof graphql_compose_1.ObjectTypeComposer) {
// make a new fn augmentObjectTypeWithAggregationField
const fieldAggregationComposer = new field_aggregation_composer_1.FieldAggregationComposer(schemaComposer, subgraph);
fieldAggregationComposer.createAggregationTypeObject(relationshipAdapter, features);
}
if (relationshipTarget instanceof ConcreteEntityAdapter_1.ConcreteEntityAdapter) {
relationshipFieldsOpts.subgraph = subgraph;
}
createRelationshipFieldsForTarget(relationshipFieldsOpts);
});
}
function createRelationshipFieldsForTarget({ relationshipAdapter, composer, composeNode, userDefinedFieldDirectives, deprecatedDirectives, userDefinedDirectivesOnTargetFields, subgraph, // only for concrete targets
features, complexityEstimatorHelper, }) {
(0, where_input_1.withSourceWhereInputType)({
relationshipAdapter,
composer,
deprecatedDirectives,
userDefinedDirectivesOnTargetFields,
features,
});
if (relationshipAdapter.target instanceof InterfaceEntityAdapter_1.InterfaceEntityAdapter) {
(0, create_input_1.withFieldInputType)({ relationshipAdapter, composer, userDefinedFieldDirectives });
}
complexityEstimatorHelper.registerField(composeNode.getTypeName(), relationshipAdapter.name);
composeNode.addFields((0, augment_object_or_interface_1.augmentObjectOrInterfaceTypeWithRelationshipField)({
relationshipAdapter,
userDefinedFieldDirectives,
subgraph,
composer,
features,
}));
complexityEstimatorHelper.registerField(composeNode.getTypeName(), relationshipAdapter.operations.connectionFieldName);
composeNode.addFields((0, augment_object_or_interface_1.augmentObjectOrInterfaceTypeWithConnectionField)(relationshipAdapter, userDefinedFieldDirectives, composer, features));
(0, relation_input_1.withRelationInputType)({
relationshipAdapter,
composer,
deprecatedDirectives,
userDefinedFieldDirectives,
});
(0, create_input_1.augmentCreateInputTypeWithRelationshipsInput)({
relationshipAdapter,
composer,
deprecatedDirectives,
userDefinedFieldDirectives,
features,
});
(0, connect_input_1.augmentConnectInputTypeWithConnectFieldInput)({
relationshipAdapter,
composer,
deprecatedDirectives,
});
(0, delete_input_1.augmentDeleteInputTypeWithDeleteFieldInput)({
relationshipAdapter,
composer,
deprecatedDirectives,
features,
});
(0, disconnect_input_1.augmentDisconnectInputTypeWithDisconnectFieldInput)({
relationshipAdapter,
composer,
deprecatedDirectives,
features,
});
(0, update_input_1.augmentUpdateInputTypeWithUpdateFieldInput)({
relationshipAdapter,
composer,
deprecatedDirectives,
userDefinedFieldDirectives,
features,
});
}
//# sourceMappingURL=create-relationship-fields.js.map