@neo4j/graphql
Version:
A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations
185 lines • 8.65 kB
JavaScript
;
/*
* 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.DisconnectFactory = void 0;
const utils_1 = require("../../../../utils/utils");
const MutationOperationField_1 = require("../../ast/input-fields/MutationOperationField");
const ParamInputField_1 = require("../../ast/input-fields/ParamInputField");
const DisconnectOperation_1 = require("../../ast/operations/DisconnectOperation");
const CompositeDisconnectOperation_1 = require("../../ast/operations/composite/CompositeDisconnectOperation");
const CompositeDisconnectPartial_1 = require("../../ast/operations/composite/CompositeDisconnectPartial");
const RelationshipSelectionPattern_1 = require("../../ast/selection/SelectionPattern/RelationshipSelectionPattern");
const is_concrete_entity_1 = require("../../utils/is-concrete-entity");
const is_interface_entity_1 = require("../../utils/is-interface-entity");
const is_union_entity_1 = require("../../utils/is-union-entity");
const raise_attribute_ambiguity_1 = require("../../utils/raise-attribute-ambiguity");
class DisconnectFactory {
constructor(queryASTFactory) {
this.queryASTFactory = queryASTFactory;
}
createDisconnectOperation(entity, relationship, input, context, callbackBucket) {
const disconnectOP = new DisconnectOperation_1.DisconnectOperation({
target: entity,
selectionPattern: new RelationshipSelectionPattern_1.RelationshipSelectionPattern({
relationship,
targetOverride: entity,
}),
relationship,
});
this.hydrateDisconnectOperation({
target: entity,
relationship,
input,
disconnect: disconnectOP,
context,
callbackBucket,
});
return disconnectOP;
}
createCompositeDisconnectOperation(entity, relationship, input, context, callbackBucket) {
const partials = [];
for (const concreteEntity of entity.concreteEntities) {
const partial = this.createCompositeDisconnectPartial(concreteEntity, relationship, input, context, callbackBucket);
partials.push(partial);
}
return new CompositeDisconnectOperation_1.CompositeDisconnectOperation({
partials,
target: entity,
});
}
createCompositeDisconnectPartial(entity, relationship, input, context, callbackBucket) {
const disconnectOp = new CompositeDisconnectPartial_1.CompositeDisconnectPartial({
target: entity,
selectionPattern: new RelationshipSelectionPattern_1.RelationshipSelectionPattern({
relationship,
targetOverride: entity,
}),
relationship,
});
this.hydrateDisconnectOperation({
target: entity,
relationship,
input,
disconnect: disconnectOp,
context,
callbackBucket,
});
return disconnectOp;
}
hydrateDisconnectOperation({ target, relationship, input, disconnect, context, callbackBucket, }) {
this.addEntityAuthorization({
entity: target,
context,
operation: disconnect,
});
if ((0, is_concrete_entity_1.isConcreteEntity)(relationship.source)) {
this.addSourceEntityAuthorization({
entity: relationship.source,
context,
operation: disconnect,
});
}
(0, utils_1.asArray)(input).forEach((inputItem) => {
const { whereArg, disconnectArg } = this.parseDisconnectArgs(inputItem);
const nodeFilters = [];
const edgeFilters = [];
if (whereArg.node) {
if ((0, is_concrete_entity_1.isConcreteEntity)(relationship.target) || (0, is_union_entity_1.isUnionEntity)(relationship.target)) {
nodeFilters.push(...this.queryASTFactory.filterFactory.createNodeFilters(target, whereArg.node));
}
else if ((0, is_interface_entity_1.isInterfaceEntity)(relationship.target)) {
nodeFilters.push(...this.queryASTFactory.filterFactory.createInterfaceNodeFilters({
entity: relationship.target,
targetEntity: target,
whereFields: whereArg.node,
relationship,
}));
}
}
if (whereArg.edge) {
edgeFilters.push(...this.queryASTFactory.filterFactory.createEdgeFilters(relationship, whereArg.edge));
}
disconnect.addFilters(...nodeFilters, ...edgeFilters);
(0, utils_1.asArray)(disconnectArg).forEach((nestedDisconnectInputFields) => {
Object.entries(nestedDisconnectInputFields).forEach(([key, value]) => {
const nestedRelationship = target.relationships.get(key);
if (!nestedRelationship) {
throw new Error("Expected relationship on connect operation. Please contact support");
}
const nestedEntity = nestedRelationship.target;
(0, utils_1.asArray)(value).forEach((nestedDisconnectInputItem) => {
const nestedDisconnectOperation = this.queryASTFactory.operationsFactory.createDisconnectOperation(nestedEntity, nestedRelationship, nestedDisconnectInputItem, context, callbackBucket);
const mutationOperationField = new MutationOperationField_1.MutationOperationField(nestedDisconnectOperation, key);
disconnect.addField(mutationOperationField, "node");
});
});
});
const targetInputEdge = this.getInputEdge(inputItem, relationship);
/* Create the attributes for the edge */
(0, raise_attribute_ambiguity_1.raiseAttributeAmbiguity)(Object.keys(targetInputEdge), relationship);
for (const key of Object.keys(targetInputEdge)) {
const attribute = relationship.attributes.get(key);
if (attribute) {
const attachedTo = "relationship";
const paramInputField = new ParamInputField_1.ParamInputField({
attachedTo,
attribute,
inputValue: targetInputEdge[key],
});
disconnect.addField(paramInputField, attachedTo);
}
}
});
}
addEntityAuthorization({ entity, context, operation, }) {
const authFilters = this.queryASTFactory.authorizationFactory.getAuthFilters({
entity,
operations: ["DELETE_RELATIONSHIP"],
context,
afterValidation: true,
});
operation.addAuthFilters(...authFilters);
}
addSourceEntityAuthorization({ entity, context, operation, }) {
const authFilters = this.queryASTFactory.authorizationFactory.getAuthFilters({
entity,
operations: ["DELETE_RELATIONSHIP"],
context,
afterValidation: true,
});
operation.addSourceAuthFilters(...authFilters);
}
getInputEdge(inputItem, relationship) {
const edge = inputItem.edge ?? {};
// Deals with composite relationships
if (relationship.propertiesTypeName && edge[relationship.propertiesTypeName]) {
return edge[relationship.propertiesTypeName];
}
return edge;
}
parseDisconnectArgs(args) {
const rawWhere = args.where ?? {};
const whereArg = { node: rawWhere.node, edge: rawWhere.edge };
const disconnectArg = args.disconnect ?? {};
return { whereArg, disconnectArg };
}
}
exports.DisconnectFactory = DisconnectFactory;
//# sourceMappingURL=DisconnectFactory.js.map