UNPKG

@neo4j/graphql

Version:

A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations

175 lines 9.59 kB
"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. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const cypher_builder_1 = __importDefault(require("@neo4j/cypher-builder")); const case_where_1 = require("../utils/case-where"); const get_relationship_type_1 = require("../utils/get-relationship-type"); const check_authentication_1 = require("./authorization/check-authentication"); const create_authorization_before_and_params_1 = require("./authorization/compatibility/create-authorization-before-and-params"); const build_clause_1 = require("./utils/build-clause"); const get_relationship_direction_1 = require("./utils/get-relationship-direction"); const create_connection_where_and_params_1 = __importDefault(require("./where/create-connection-where-and-params")); function createDeleteAndParams({ deleteInput, varName, node, parentVar, chainStr, withVars, context, parameterPrefix, recursing, }) { (0, check_authentication_1.checkAuthentication)({ context, node, targetOperations: ["DELETE"] }); function reducer(res, [key, value]) { (0, check_authentication_1.checkAuthentication)({ context, node, targetOperations: ["DELETE"], field: key }); const relationField = node.relationFields.find((x) => key === x.fieldName); if (relationField) { const refNodes = []; const relationship = context.relationships.find((x) => x.properties === relationField.properties); if (relationField.union) { Object.keys(value).forEach((unionTypeName) => { refNodes.push(context.nodes.find((x) => x.name === unionTypeName)); }); } else if (relationField.interface) { relationField.interface.implementations?.forEach((implementationName) => { refNodes.push(context.nodes.find((x) => x.name === implementationName)); }); } else { refNodes.push(context.nodes.find((x) => x.name === relationField.typeMeta.name)); } const { inStr, outStr } = (0, get_relationship_direction_1.getRelationshipDirection)(relationField); refNodes.forEach((refNode) => { (0, check_authentication_1.checkAuthentication)({ context, node: refNode, targetOperations: ["DELETE"] }); const v = relationField.union ? value[refNode.name] : value; const deletes = relationField.typeMeta.array ? v : [v]; deletes.forEach((d, index) => { const innerStrs = []; const variableName = chainStr ? `${varName}${index}` : `${varName}_${key}${relationField.union || relationField.interface ? `_${refNode.name}` : ""}${index}`; const relationshipVariable = `${variableName}_relationship`; const fieldType = (0, get_relationship_type_1.getRelationshipType)(relationField, context.features); const relTypeStr = `[${relationshipVariable}:${fieldType}]`; const nodeToDelete = `${variableName}_to_delete`; const labels = refNode.getLabelString(context); innerStrs.push("WITH *"); innerStrs.push("CALL(*) {"); innerStrs.push(`OPTIONAL MATCH (${parentVar})${inStr}${relTypeStr}${outStr}(${variableName}${labels})`); const whereStrs = []; let aggregationWhere = false; if (d.where) { try { const { cypher: whereCypher, subquery: preComputedSubqueries, params: whereParams, } = (0, create_connection_where_and_params_1.default)({ nodeVariable: variableName, whereInput: d.where, node: refNode, context, relationshipVariable, relationship, parameterPrefix: `${parameterPrefix}${!recursing ? `.${key}` : ""}${relationField.union ? `.${refNode.name}` : ""}${relationField.typeMeta.array ? `[${index}]` : ""}.where`, }); if (whereCypher) { whereStrs.push(whereCypher); res.params = { ...res.params, ...whereParams }; if (preComputedSubqueries) { innerStrs.push(preComputedSubqueries); aggregationWhere = true; } } } catch (_err) { innerStrs.push(" \n}"); return; } } const authorizationAndParams = (0, create_authorization_before_and_params_1.createAuthorizationBeforeAndParams)({ context, nodes: [ { variable: variableName, node: refNode, }, ], operations: ["DELETE"], indexPrefix: "delete", }); if (authorizationAndParams) { const { cypher, params, subqueries } = authorizationAndParams; whereStrs.push(cypher); res.params = { ...res.params, ...params }; if (subqueries) { innerStrs.push(subqueries); innerStrs.push("WITH *"); } } if (whereStrs.length) { const predicate = `${whereStrs.join(" AND ")}`; if (aggregationWhere) { const columns = [ new cypher_builder_1.default.NamedVariable(relationshipVariable), new cypher_builder_1.default.NamedVariable(variableName), ]; const caseWhereClause = (0, case_where_1.caseWhere)(new cypher_builder_1.default.Raw(predicate), columns); const { cypher } = (0, build_clause_1.buildClause)(caseWhereClause, { context, prefix: "aggregateWhereFilter", }); innerStrs.push(cypher); } else { innerStrs.push(`WHERE ${predicate}`); } } if (d.delete) { const nestedDeleteInput = Object.entries(d.delete).reduce((d1, [k1, v1]) => ({ ...d1, [k1]: v1 }), {}); const importWithVars = [...withVars, variableName]; const deleteAndParams = createDeleteAndParams({ context, node: refNode, deleteInput: nestedDeleteInput, varName: variableName, withVars: importWithVars, parentVar: variableName, parameterPrefix: `${parameterPrefix}${!recursing ? `.${key}` : ""}${relationField.union ? `.${refNode.name}` : ""}${relationField.typeMeta.array ? `[${index}]` : ""}.delete`, recursing: false, }); innerStrs.push(deleteAndParams[0]); res.params = { ...res.params, ...deleteAndParams[1] }; } const statements = [ `WITH ${relationshipVariable}, collect(DISTINCT ${variableName}) AS ${nodeToDelete}`, `CALL(${nodeToDelete}) {`, `\tUNWIND ${nodeToDelete} AS x`, `\tDETACH DELETE x`, `}`, `}`, ]; innerStrs.push(...statements); res.strs.push(...innerStrs); }); }); return res; } return res; } const { strs, params } = Object.entries(deleteInput).reduce(reducer, { strs: [], params: {}, }); return [strs.join("\n"), params]; } exports.default = createDeleteAndParams; //# sourceMappingURL=create-delete-and-params.js.map