From 4e1468076bbd23cdd9156b039de1d03bbc68942c Mon Sep 17 00:00:00 2001 From: angrykoala Date: Fri, 24 Jan 2025 11:03:04 +0000 Subject: [PATCH 1/5] add new flag: addCypherVersion --- .changeset/soft-socks-count.md | 23 +++ packages/graphql/package.json | 2 +- .../src/translate/translate-aggregate.ts | 5 +- .../graphql/src/translate/translate-create.ts | 3 +- .../graphql/src/translate/translate-delete.ts | 5 +- .../graphql/src/translate/translate-read.ts | 5 +- .../translate/translate-resolve-reference.ts | 11 +- .../translate/translate-top-level-cypher.ts | 5 +- .../graphql/src/translate/translate-update.ts | 3 +- .../graphql/src/translate/unwind-create.ts | 3 +- packages/graphql/src/types/index.ts | 1 + .../graphql/src/utils/get-cypher-version.ts | 25 +++ .../tests/tck/features/cypher-version.test.ts | 183 ++++++++++++++++++ yarn.lock | 10 +- 14 files changed, 267 insertions(+), 17 deletions(-) create mode 100644 .changeset/soft-socks-count.md create mode 100644 packages/graphql/src/utils/get-cypher-version.ts create mode 100644 packages/graphql/tests/tck/features/cypher-version.test.ts diff --git a/.changeset/soft-socks-count.md b/.changeset/soft-socks-count.md new file mode 100644 index 0000000000..0c88714e76 --- /dev/null +++ b/.changeset/soft-socks-count.md @@ -0,0 +1,23 @@ +--- +"@neo4j/graphql": patch +--- + +Add feature flag "addCypherVersion": + +```js +neoSchema = new Neo4jGraphQL({ + typeDefs, + features: { + addCypherVersion: true, + }, +}); +``` + +This prepends all Cypher queries with a `CYPHER [version]` statement: + +```cypher +CYPHER 5 +MATCH (this:Movie) +WHERE this.title = $param0 +RETURN this { .title } AS this +``` diff --git a/packages/graphql/package.json b/packages/graphql/package.json index f616c1e26f..0e5a72c75d 100644 --- a/packages/graphql/package.json +++ b/packages/graphql/package.json @@ -79,7 +79,7 @@ "@graphql-tools/resolvers-composition": "^7.0.0", "@graphql-tools/schema": "^10.0.0", "@graphql-tools/utils": "10.6.1", - "@neo4j/cypher-builder": "2.2.1", + "@neo4j/cypher-builder": "2.3.0", "camelcase": "^6.3.0", "debug": "^4.3.4", "dot-prop": "^6.0.1", diff --git a/packages/graphql/src/translate/translate-aggregate.ts b/packages/graphql/src/translate/translate-aggregate.ts index 9bd41b6c95..0ad802453c 100644 --- a/packages/graphql/src/translate/translate-aggregate.ts +++ b/packages/graphql/src/translate/translate-aggregate.ts @@ -22,6 +22,7 @@ import Debug from "debug"; import { DEBUG_TRANSLATE } from "../constants"; import type { EntityAdapter } from "../schema-model/entity/EntityAdapter"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; +import { getCypherVersion } from "../utils/get-cypher-version"; import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; const debug = Debug(DEBUG_TRANSLATE); @@ -43,5 +44,7 @@ export function translateAggregate({ const queryAST = queryASTFactory.createQueryAST({ resolveTree, entityAdapter, context }); debug(queryAST.print()); const clause = queryAST.buildNew(context); - return clause.build(); + return clause.build({ + cypherVersion: getCypherVersion(context), + }); } diff --git a/packages/graphql/src/translate/translate-create.ts b/packages/graphql/src/translate/translate-create.ts index 062e12e408..26f81e2b8b 100644 --- a/packages/graphql/src/translate/translate-create.ts +++ b/packages/graphql/src/translate/translate-create.ts @@ -24,6 +24,7 @@ import { CallbackBucket } from "../classes/CallbackBucket"; import { DEBUG_TRANSLATE } from "../constants"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; import { compileCypherIfExists } from "../utils/compile-cypher"; +import { getCypherVersion } from "../utils/get-cypher-version"; import { asArray, filterTruthy } from "../utils/utils"; import createCreateAndParams from "./create-create-and-params"; import { QueryASTContext, QueryASTEnv } from "./queryAST/ast/QueryASTContext"; @@ -152,7 +153,7 @@ export default async function translateCreate({ ]; }); - const createQueryCypher = createQuery.build({ prefix: "create_" }); + const createQueryCypher = createQuery.build({ prefix: "create_", cypherVersion: getCypherVersion(context) }); const { cypher, params: resolvedCallbacks } = await callbackBucket.resolveCallbacksAndFilterCypher({ cypher: createQueryCypher.cypher, }); diff --git a/packages/graphql/src/translate/translate-delete.ts b/packages/graphql/src/translate/translate-delete.ts index bfaccafe65..3b28285e65 100644 --- a/packages/graphql/src/translate/translate-delete.ts +++ b/packages/graphql/src/translate/translate-delete.ts @@ -25,6 +25,7 @@ import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-tran import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; import type { ResolveTree } from "graphql-parse-resolve-info"; +import { getCypherVersion } from "../utils/get-cypher-version"; const debug = Debug(DEBUG_TRANSLATE); @@ -52,7 +53,9 @@ function translateUsingQueryAST({ }); debug(operationsTree.print()); const clause = operationsTree.build(context, varName); - return clause.build(); + return clause.build({ + cypherVersion: getCypherVersion(context), + }); } export function translateDelete({ context, diff --git a/packages/graphql/src/translate/translate-read.ts b/packages/graphql/src/translate/translate-read.ts index a6d25c827a..e2ffab3352 100644 --- a/packages/graphql/src/translate/translate-read.ts +++ b/packages/graphql/src/translate/translate-read.ts @@ -22,6 +22,7 @@ import Debug from "debug"; import { DEBUG_TRANSLATE } from "../constants"; import type { EntityAdapter } from "../schema-model/entity/EntityAdapter"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; +import { getCypherVersion } from "../utils/get-cypher-version"; import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; const debug = Debug(DEBUG_TRANSLATE); @@ -45,5 +46,7 @@ export function translateRead({ }); debug(operationsTree.print()); const clause = operationsTree.build(context, varName); - return clause.build(); + return clause.build({ + cypherVersion: getCypherVersion(context), + }); } diff --git a/packages/graphql/src/translate/translate-resolve-reference.ts b/packages/graphql/src/translate/translate-resolve-reference.ts index 1fc547d3d9..849d0673cd 100644 --- a/packages/graphql/src/translate/translate-resolve-reference.ts +++ b/packages/graphql/src/translate/translate-resolve-reference.ts @@ -18,11 +18,12 @@ */ import type Cypher from "@neo4j/cypher-builder"; -import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; import Debug from "debug"; -import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; -import type { EntityAdapter } from "../schema-model/entity/EntityAdapter"; import { DEBUG_TRANSLATE } from "../constants"; +import type { EntityAdapter } from "../schema-model/entity/EntityAdapter"; +import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; +import { getCypherVersion } from "../utils/get-cypher-version"; +import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; const debug = Debug(DEBUG_TRANSLATE); @@ -46,5 +47,7 @@ export function translateResolveReference({ }); debug(operationsTree.print()); const clause = operationsTree.build(context, "this"); - return clause.build(); + return clause.build({ + cypherVersion: getCypherVersion(context), + }); } diff --git a/packages/graphql/src/translate/translate-top-level-cypher.ts b/packages/graphql/src/translate/translate-top-level-cypher.ts index 419c742c98..ce0b0ae3a8 100644 --- a/packages/graphql/src/translate/translate-top-level-cypher.ts +++ b/packages/graphql/src/translate/translate-top-level-cypher.ts @@ -24,6 +24,7 @@ import type { AuthenticationOperation } from "../schema-model/annotation/Authent import { getEntityAdapter } from "../schema-model/utils/get-entity-adapter"; import type { CypherField } from "../types"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; +import { getCypherVersion } from "../utils/get-cypher-version"; import { applyAuthentication } from "./authorization/utils/apply-authentication"; import { QueryASTContext, QueryASTEnv } from "./queryAST/ast/QueryASTContext"; import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; @@ -84,5 +85,7 @@ export function translateTopLevelCypher({ const projectionStatements = queryASTResult.clauses.length ? Cypher.utils.concat(...queryASTResult.clauses) : new Cypher.Return(new Cypher.Literal("Query cannot conclude with CALL")); - return projectionStatements.build(); + return projectionStatements.build({ + cypherVersion: getCypherVersion(context), + }); } diff --git a/packages/graphql/src/translate/translate-update.ts b/packages/graphql/src/translate/translate-update.ts index 546e6ef9ae..ecea1d4f0b 100644 --- a/packages/graphql/src/translate/translate-update.ts +++ b/packages/graphql/src/translate/translate-update.ts @@ -25,6 +25,7 @@ import { DEBUG_TRANSLATE } from "../constants"; import type { GraphQLWhereArg, RelationField } from "../types"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; import { compileCypher } from "../utils/compile-cypher"; +import { getCypherVersion } from "../utils/get-cypher-version"; import createConnectAndParams from "./create-connect-and-params"; import { createConnectOrCreateAndParams } from "./create-connect-or-create-and-params"; import createCreateAndParams from "./create-create-and-params"; @@ -485,7 +486,7 @@ export default async function translateUpdate({ ]; }); - const cypherResult = updateQuery.build({ prefix: "update_" }); + const cypherResult = updateQuery.build({ prefix: "update_", cypherVersion: getCypherVersion(context) }); const { cypher, params: resolvedCallbacks } = await callbackBucket.resolveCallbacksAndFilterCypher({ cypher: cypherResult.cypher, }); diff --git a/packages/graphql/src/translate/unwind-create.ts b/packages/graphql/src/translate/unwind-create.ts index a940cb9833..4825309544 100644 --- a/packages/graphql/src/translate/unwind-create.ts +++ b/packages/graphql/src/translate/unwind-create.ts @@ -21,6 +21,7 @@ import Debug from "debug"; import { DEBUG_TRANSLATE } from "../constants"; import type { EntityAdapter } from "../schema-model/entity/EntityAdapter"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; +import { getCypherVersion } from "../utils/get-cypher-version"; import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; const debug = Debug(DEBUG_TRANSLATE); @@ -44,5 +45,5 @@ export default function unwindCreate({ const clauses = queryAST.build(context); - return clauses.build({ prefix: "create_" }); + return clauses.build({ prefix: "create_", cypherVersion: getCypherVersion(context) }); } diff --git a/packages/graphql/src/types/index.ts b/packages/graphql/src/types/index.ts index 795c7e5b5c..71f0a755ea 100644 --- a/packages/graphql/src/types/index.ts +++ b/packages/graphql/src/types/index.ts @@ -443,6 +443,7 @@ export type Neo4jFeaturesSettings = { populatedBy?: Neo4jPopulatedBySettings; authorization?: Neo4jAuthorizationSettings; subscriptions?: boolean | Neo4jGraphQLSubscriptionsCDCEngine; + addCypherVersion?: boolean; /** If set to `true`, removes `@neo4j/graphql` fields that are marked as deprecated to reduce schema size. * * NOTE: this will not remove user defined deprecated fields diff --git a/packages/graphql/src/utils/get-cypher-version.ts b/packages/graphql/src/utils/get-cypher-version.ts new file mode 100644 index 0000000000..9d5d8d06a1 --- /dev/null +++ b/packages/graphql/src/utils/get-cypher-version.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +import type { Neo4jFeaturesSettings } from "../types"; + +/** Returns the Cypher version to pass to Cypher builder, if any, based on context */ +export function getCypherVersion({ features }: { features: Neo4jFeaturesSettings }): "5" | undefined { + return features.addCypherVersion ? "5" : undefined; +} diff --git a/packages/graphql/tests/tck/features/cypher-version.test.ts b/packages/graphql/tests/tck/features/cypher-version.test.ts new file mode 100644 index 0000000000..432275a1a4 --- /dev/null +++ b/packages/graphql/tests/tck/features/cypher-version.test.ts @@ -0,0 +1,183 @@ +/* + * 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. + */ + +import { Neo4jGraphQL } from "../../../src"; +import { formatCypher, translateQuery } from "../utils/tck-test-utils"; + +describe("Cypher version", () => { + let typeDefs: string; + let neoSchema: Neo4jGraphQL; + + beforeAll(() => { + typeDefs = /* GraphQL */ ` + type Actor @node { + name: String! + } + + type Movie @node { + id: ID + title: String + } + `; + + neoSchema = new Neo4jGraphQL({ + typeDefs, + features: { + addCypherVersion: true, + }, + }); + }); + + test("Read query", async () => { + const query = /* GraphQL */ ` + { + movies(where: { title_EQ: "River Runs Through It, A" }) { + title + } + } + `; + + const result = await translateQuery(neoSchema, query); + + // NOTE: Order of these subqueries have been reversed after refactor + expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` + "CYPHER 5 + MATCH (this:Movie) + WHERE this.title = $param0 + RETURN this { .title } AS this" + `); + }); + + test("Read connection", async () => { + const query = /* GraphQL */ ` + query ActorsConnection { + actorsConnection { + totalCount + } + } + `; + + const result = await translateQuery(neoSchema, query); + + // NOTE: Order of these subqueries have been reversed after refactor + expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` + "CYPHER 5 + MATCH (this0:Actor) + WITH collect({ node: this0 }) AS edges + WITH edges, size(edges) AS totalCount + CALL { + WITH edges + UNWIND edges AS edge + WITH edge.node AS this0 + RETURN collect({ node: { __id: id(this0), __resolveType: \\"Actor\\" } }) AS var1 + } + RETURN { edges: var1, totalCount: totalCount } AS this" + `); + }); + + test("Aggregate", async () => { + const query = /* GraphQL */ ` + { + moviesAggregate { + count + } + } + `; + + const result = await translateQuery(neoSchema, query); + + // NOTE: Order of these subqueries have been reversed after refactor + expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` + "CYPHER 5 + CALL { + MATCH (this:Movie) + RETURN count(this) AS var0 + } + RETURN { count: var0 }" + `); + }); + + test("Create", async () => { + const query = /* GraphQL */ ` + mutation { + createMovies(input: [{ title: "dsa" }]) { + movies { + title + } + } + } + `; + + const result = await translateQuery(neoSchema, query); + + // NOTE: Order of these subqueries have been reversed after refactor + expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` + "CYPHER 5 + UNWIND $create_param0 AS create_var0 + CALL { + WITH create_var0 + CREATE (create_this1:Movie) + SET + create_this1.title = create_var0.title + RETURN create_this1 + } + RETURN collect(create_this1 { .title }) AS data" + `); + }); + test("Update", async () => { + const query = /* GraphQL */ ` + mutation { + updateMovies(update: { title_SET: "Potato" }) { + movies { + title + } + } + } + `; + + const result = await translateQuery(neoSchema, query); + + // NOTE: Order of these subqueries have been reversed after refactor + expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` + "CYPHER 5 + MATCH (this:Movie) + SET this.title = $this_update_title_SET + RETURN collect(DISTINCT this { .title }) AS data" + `); + }); + + test("Delete", async () => { + const query = /* GraphQL */ ` + mutation { + deleteActors { + nodesDeleted + } + } + `; + + const result = await translateQuery(neoSchema, query); + + // NOTE: Order of these subqueries have been reversed after refactor + expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` + "CYPHER 5 + MATCH (this:Actor) + DETACH DELETE this" + `); + }); +}); diff --git a/yarn.lock b/yarn.lock index ff538b0070..3f52a540fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2082,10 +2082,10 @@ __metadata: languageName: node linkType: hard -"@neo4j/cypher-builder@npm:2.2.1": - version: 2.2.1 - resolution: "@neo4j/cypher-builder@npm:2.2.1" - checksum: 10c0/5d3af9a6b9bc7db5dc36ca7cfe6e0ec2d104a65538afca20aa47245cfb87681275e26d99e802f9ac80f2597b3535133c3be97cd3b5db35ba1495e6ef4f230dfb +"@neo4j/cypher-builder@npm:2.3.0": + version: 2.3.0 + resolution: "@neo4j/cypher-builder@npm:2.3.0" + checksum: 10c0/bd7d98b8c3a84e9562ff88b9f2ad10a9258aabc2204dba247d4aa83944bce6f5100a3e14199a688dea62de2313910b90e03da7a9b1a423d0a279b022e5909fc3 languageName: node linkType: hard @@ -2106,7 +2106,7 @@ __metadata: "@graphql-tools/resolvers-composition": "npm:^7.0.0" "@graphql-tools/schema": "npm:^10.0.0" "@graphql-tools/utils": "npm:10.6.1" - "@neo4j/cypher-builder": "npm:2.2.1" + "@neo4j/cypher-builder": "npm:2.3.0" "@types/deep-equal": "npm:1.0.4" "@types/is-uuid": "npm:1.0.2" "@types/jest": "npm:29.5.14" From d8eaecb955aeeb41713244ee8efa2915363e9c13 Mon Sep 17 00:00:00 2001 From: angrykoala Date: Mon, 27 Jan 2025 15:21:32 +0000 Subject: [PATCH 2/5] Move version to cypherQueryOptions --- .changeset/soft-socks-count.md | 11 +- packages/graphql/src/classes/Executor.ts | 27 ++- .../src/translate/translate-aggregate.ts | 5 +- .../graphql/src/translate/translate-create.ts | 3 +- .../graphql/src/translate/translate-delete.ts | 5 +- .../graphql/src/translate/translate-read.ts | 5 +- .../translate/translate-resolve-reference.ts | 5 +- .../translate/translate-top-level-cypher.ts | 5 +- .../graphql/src/translate/translate-update.ts | 3 +- .../graphql/src/translate/unwind-create.ts | 3 +- packages/graphql/src/types/index.ts | 2 +- .../graphql/src/utils/get-cypher-version.ts | 25 --- .../config-options/query-options.int.test.ts | 32 +++ .../tests/tck/features/cypher-version.test.ts | 183 ------------------ 14 files changed, 67 insertions(+), 247 deletions(-) delete mode 100644 packages/graphql/src/utils/get-cypher-version.ts delete mode 100644 packages/graphql/tests/tck/features/cypher-version.test.ts diff --git a/.changeset/soft-socks-count.md b/.changeset/soft-socks-count.md index 0c88714e76..4f90025dc6 100644 --- a/.changeset/soft-socks-count.md +++ b/.changeset/soft-socks-count.md @@ -2,15 +2,14 @@ "@neo4j/graphql": patch --- -Add feature flag "addCypherVersion": +Add `version` to `cypherQueryOptions` in context to add a Cypher version with `CYPHER` before each query: ```js -neoSchema = new Neo4jGraphQL({ - typeDefs, - features: { - addCypherVersion: true, +{ + cypherQueryOptions: { + version: "5", }, -}); +} ``` This prepends all Cypher queries with a `CYPHER [version]` statement: diff --git a/packages/graphql/src/classes/Executor.ts b/packages/graphql/src/classes/Executor.ts index d970ccbd85..15584a1773 100644 --- a/packages/graphql/src/classes/Executor.ts +++ b/packages/graphql/src/classes/Executor.ts @@ -107,7 +107,6 @@ export class Executor { }: ExecutorConstructorParam) { this.executionContext = executionContext; this.cypherQueryOptions = cypherQueryOptions; - this.cypherQueryOptions = cypherQueryOptions; this.sessionConfig = sessionConfig; this.cypherParams = cypherParams; this.transactionMetadata = transactionMetadata; @@ -174,12 +173,28 @@ export class Executor { } private generateQuery(query: string): string { - if (this.cypherQueryOptions && Object.keys(this.cypherQueryOptions).length) { - const cypherQueryOptions = `CYPHER ${Object.entries(this.cypherQueryOptions) - .map(([key, value]) => `${key}=${value}`) - .join(" ")}`; + if (this.cypherQueryOptions) { + let cypherVersion = ""; + // Cypher version should be rendered as a separate statement + if (this.cypherQueryOptions.version) { + cypherVersion = `CYPHER ${this.cypherQueryOptions.version}\n`; + } + + let cypherQueryOptions = ""; + const cypherQueryOptionsToAddToStatement = Object.entries(this.cypherQueryOptions).filter( + ([key, _value]) => { + return key !== "version"; + } + ); + if (cypherQueryOptionsToAddToStatement.length) { + cypherQueryOptions = `CYPHER ${cypherQueryOptionsToAddToStatement + .map(([key, value]) => { + return `${key}=${value}`; + }) + .join(" ")}\n`; + } - return `${cypherQueryOptions}\n${query}`; + return `${cypherVersion}${cypherQueryOptions}${query}`; } return query; diff --git a/packages/graphql/src/translate/translate-aggregate.ts b/packages/graphql/src/translate/translate-aggregate.ts index 0ad802453c..9bd41b6c95 100644 --- a/packages/graphql/src/translate/translate-aggregate.ts +++ b/packages/graphql/src/translate/translate-aggregate.ts @@ -22,7 +22,6 @@ import Debug from "debug"; import { DEBUG_TRANSLATE } from "../constants"; import type { EntityAdapter } from "../schema-model/entity/EntityAdapter"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; -import { getCypherVersion } from "../utils/get-cypher-version"; import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; const debug = Debug(DEBUG_TRANSLATE); @@ -44,7 +43,5 @@ export function translateAggregate({ const queryAST = queryASTFactory.createQueryAST({ resolveTree, entityAdapter, context }); debug(queryAST.print()); const clause = queryAST.buildNew(context); - return clause.build({ - cypherVersion: getCypherVersion(context), - }); + return clause.build(); } diff --git a/packages/graphql/src/translate/translate-create.ts b/packages/graphql/src/translate/translate-create.ts index 26f81e2b8b..062e12e408 100644 --- a/packages/graphql/src/translate/translate-create.ts +++ b/packages/graphql/src/translate/translate-create.ts @@ -24,7 +24,6 @@ import { CallbackBucket } from "../classes/CallbackBucket"; import { DEBUG_TRANSLATE } from "../constants"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; import { compileCypherIfExists } from "../utils/compile-cypher"; -import { getCypherVersion } from "../utils/get-cypher-version"; import { asArray, filterTruthy } from "../utils/utils"; import createCreateAndParams from "./create-create-and-params"; import { QueryASTContext, QueryASTEnv } from "./queryAST/ast/QueryASTContext"; @@ -153,7 +152,7 @@ export default async function translateCreate({ ]; }); - const createQueryCypher = createQuery.build({ prefix: "create_", cypherVersion: getCypherVersion(context) }); + const createQueryCypher = createQuery.build({ prefix: "create_" }); const { cypher, params: resolvedCallbacks } = await callbackBucket.resolveCallbacksAndFilterCypher({ cypher: createQueryCypher.cypher, }); diff --git a/packages/graphql/src/translate/translate-delete.ts b/packages/graphql/src/translate/translate-delete.ts index 3b28285e65..bfaccafe65 100644 --- a/packages/graphql/src/translate/translate-delete.ts +++ b/packages/graphql/src/translate/translate-delete.ts @@ -25,7 +25,6 @@ import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-tran import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; import type { ResolveTree } from "graphql-parse-resolve-info"; -import { getCypherVersion } from "../utils/get-cypher-version"; const debug = Debug(DEBUG_TRANSLATE); @@ -53,9 +52,7 @@ function translateUsingQueryAST({ }); debug(operationsTree.print()); const clause = operationsTree.build(context, varName); - return clause.build({ - cypherVersion: getCypherVersion(context), - }); + return clause.build(); } export function translateDelete({ context, diff --git a/packages/graphql/src/translate/translate-read.ts b/packages/graphql/src/translate/translate-read.ts index e2ffab3352..a6d25c827a 100644 --- a/packages/graphql/src/translate/translate-read.ts +++ b/packages/graphql/src/translate/translate-read.ts @@ -22,7 +22,6 @@ import Debug from "debug"; import { DEBUG_TRANSLATE } from "../constants"; import type { EntityAdapter } from "../schema-model/entity/EntityAdapter"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; -import { getCypherVersion } from "../utils/get-cypher-version"; import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; const debug = Debug(DEBUG_TRANSLATE); @@ -46,7 +45,5 @@ export function translateRead({ }); debug(operationsTree.print()); const clause = operationsTree.build(context, varName); - return clause.build({ - cypherVersion: getCypherVersion(context), - }); + return clause.build(); } diff --git a/packages/graphql/src/translate/translate-resolve-reference.ts b/packages/graphql/src/translate/translate-resolve-reference.ts index 849d0673cd..b3658b5c19 100644 --- a/packages/graphql/src/translate/translate-resolve-reference.ts +++ b/packages/graphql/src/translate/translate-resolve-reference.ts @@ -22,7 +22,6 @@ import Debug from "debug"; import { DEBUG_TRANSLATE } from "../constants"; import type { EntityAdapter } from "../schema-model/entity/EntityAdapter"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; -import { getCypherVersion } from "../utils/get-cypher-version"; import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; const debug = Debug(DEBUG_TRANSLATE); @@ -47,7 +46,5 @@ export function translateResolveReference({ }); debug(operationsTree.print()); const clause = operationsTree.build(context, "this"); - return clause.build({ - cypherVersion: getCypherVersion(context), - }); + return clause.build(); } diff --git a/packages/graphql/src/translate/translate-top-level-cypher.ts b/packages/graphql/src/translate/translate-top-level-cypher.ts index ce0b0ae3a8..419c742c98 100644 --- a/packages/graphql/src/translate/translate-top-level-cypher.ts +++ b/packages/graphql/src/translate/translate-top-level-cypher.ts @@ -24,7 +24,6 @@ import type { AuthenticationOperation } from "../schema-model/annotation/Authent import { getEntityAdapter } from "../schema-model/utils/get-entity-adapter"; import type { CypherField } from "../types"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; -import { getCypherVersion } from "../utils/get-cypher-version"; import { applyAuthentication } from "./authorization/utils/apply-authentication"; import { QueryASTContext, QueryASTEnv } from "./queryAST/ast/QueryASTContext"; import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; @@ -85,7 +84,5 @@ export function translateTopLevelCypher({ const projectionStatements = queryASTResult.clauses.length ? Cypher.utils.concat(...queryASTResult.clauses) : new Cypher.Return(new Cypher.Literal("Query cannot conclude with CALL")); - return projectionStatements.build({ - cypherVersion: getCypherVersion(context), - }); + return projectionStatements.build(); } diff --git a/packages/graphql/src/translate/translate-update.ts b/packages/graphql/src/translate/translate-update.ts index ecea1d4f0b..546e6ef9ae 100644 --- a/packages/graphql/src/translate/translate-update.ts +++ b/packages/graphql/src/translate/translate-update.ts @@ -25,7 +25,6 @@ import { DEBUG_TRANSLATE } from "../constants"; import type { GraphQLWhereArg, RelationField } from "../types"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; import { compileCypher } from "../utils/compile-cypher"; -import { getCypherVersion } from "../utils/get-cypher-version"; import createConnectAndParams from "./create-connect-and-params"; import { createConnectOrCreateAndParams } from "./create-connect-or-create-and-params"; import createCreateAndParams from "./create-create-and-params"; @@ -486,7 +485,7 @@ export default async function translateUpdate({ ]; }); - const cypherResult = updateQuery.build({ prefix: "update_", cypherVersion: getCypherVersion(context) }); + const cypherResult = updateQuery.build({ prefix: "update_" }); const { cypher, params: resolvedCallbacks } = await callbackBucket.resolveCallbacksAndFilterCypher({ cypher: cypherResult.cypher, }); diff --git a/packages/graphql/src/translate/unwind-create.ts b/packages/graphql/src/translate/unwind-create.ts index 4825309544..a940cb9833 100644 --- a/packages/graphql/src/translate/unwind-create.ts +++ b/packages/graphql/src/translate/unwind-create.ts @@ -21,7 +21,6 @@ import Debug from "debug"; import { DEBUG_TRANSLATE } from "../constants"; import type { EntityAdapter } from "../schema-model/entity/EntityAdapter"; import type { Neo4jGraphQLTranslationContext } from "../types/neo4j-graphql-translation-context"; -import { getCypherVersion } from "../utils/get-cypher-version"; import { QueryASTFactory } from "./queryAST/factory/QueryASTFactory"; const debug = Debug(DEBUG_TRANSLATE); @@ -45,5 +44,5 @@ export default function unwindCreate({ const clauses = queryAST.build(context); - return clauses.build({ prefix: "create_", cypherVersion: getCypherVersion(context) }); + return clauses.build({ prefix: "create_" }); } diff --git a/packages/graphql/src/types/index.ts b/packages/graphql/src/types/index.ts index 71f0a755ea..e3a36bf77b 100644 --- a/packages/graphql/src/types/index.ts +++ b/packages/graphql/src/types/index.ts @@ -276,6 +276,7 @@ export interface CypherQueryOptions { operatorEngine?: "default" | "interpreted" | "compiled"; interpretedPipesFallback?: "default" | "disabled" | "whitelisted_plans_only" | "all"; replan?: "default" | "force" | "skip"; + version?: "5"; } /** Input field for graphql-compose */ @@ -443,7 +444,6 @@ export type Neo4jFeaturesSettings = { populatedBy?: Neo4jPopulatedBySettings; authorization?: Neo4jAuthorizationSettings; subscriptions?: boolean | Neo4jGraphQLSubscriptionsCDCEngine; - addCypherVersion?: boolean; /** If set to `true`, removes `@neo4j/graphql` fields that are marked as deprecated to reduce schema size. * * NOTE: this will not remove user defined deprecated fields diff --git a/packages/graphql/src/utils/get-cypher-version.ts b/packages/graphql/src/utils/get-cypher-version.ts deleted file mode 100644 index 9d5d8d06a1..0000000000 --- a/packages/graphql/src/utils/get-cypher-version.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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. - */ - -import type { Neo4jFeaturesSettings } from "../types"; - -/** Returns the Cypher version to pass to Cypher builder, if any, based on context */ -export function getCypherVersion({ features }: { features: Neo4jFeaturesSettings }): "5" | undefined { - return features.addCypherVersion ? "5" : undefined; -} diff --git a/packages/graphql/tests/integration/config-options/query-options.int.test.ts b/packages/graphql/tests/integration/config-options/query-options.int.test.ts index cac91a87fb..7f37a78a0d 100644 --- a/packages/graphql/tests/integration/config-options/query-options.int.test.ts +++ b/packages/graphql/tests/integration/config-options/query-options.int.test.ts @@ -87,4 +87,36 @@ describe("query options", () => { expect(result?.data?.[Movie.plural]).toEqual([{ id }, { id }, { id }]); }); + + test("queries should work with version set to Cypher version", async () => { + const id = generate({ + charset: "alphabetic", + }); + + const query = ` + query($id: ID){ + ${Movie.plural}(where: {id_EQ: $id}){ + id + } + } + `; + + await neoSchema.checkNeo4jCompat(); + + await testHelper.executeCypher( + ` + CREATE (:${Movie} {id: $id}), (:${Movie} {id: $id}), (:${Movie} {id: $id}) + `, + { id } + ); + + const result = await testHelper.executeGraphQL(query, { + variableValues: { id }, + contextValue: { cypherQueryOptions: { runtime: "interpreted", version: "5" } }, + }); + + expect(result.errors).toBeFalsy(); + + expect(result?.data?.[Movie.plural]).toEqual([{ id }, { id }, { id }]); + }); }); diff --git a/packages/graphql/tests/tck/features/cypher-version.test.ts b/packages/graphql/tests/tck/features/cypher-version.test.ts deleted file mode 100644 index 432275a1a4..0000000000 --- a/packages/graphql/tests/tck/features/cypher-version.test.ts +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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. - */ - -import { Neo4jGraphQL } from "../../../src"; -import { formatCypher, translateQuery } from "../utils/tck-test-utils"; - -describe("Cypher version", () => { - let typeDefs: string; - let neoSchema: Neo4jGraphQL; - - beforeAll(() => { - typeDefs = /* GraphQL */ ` - type Actor @node { - name: String! - } - - type Movie @node { - id: ID - title: String - } - `; - - neoSchema = new Neo4jGraphQL({ - typeDefs, - features: { - addCypherVersion: true, - }, - }); - }); - - test("Read query", async () => { - const query = /* GraphQL */ ` - { - movies(where: { title_EQ: "River Runs Through It, A" }) { - title - } - } - `; - - const result = await translateQuery(neoSchema, query); - - // NOTE: Order of these subqueries have been reversed after refactor - expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` - "CYPHER 5 - MATCH (this:Movie) - WHERE this.title = $param0 - RETURN this { .title } AS this" - `); - }); - - test("Read connection", async () => { - const query = /* GraphQL */ ` - query ActorsConnection { - actorsConnection { - totalCount - } - } - `; - - const result = await translateQuery(neoSchema, query); - - // NOTE: Order of these subqueries have been reversed after refactor - expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` - "CYPHER 5 - MATCH (this0:Actor) - WITH collect({ node: this0 }) AS edges - WITH edges, size(edges) AS totalCount - CALL { - WITH edges - UNWIND edges AS edge - WITH edge.node AS this0 - RETURN collect({ node: { __id: id(this0), __resolveType: \\"Actor\\" } }) AS var1 - } - RETURN { edges: var1, totalCount: totalCount } AS this" - `); - }); - - test("Aggregate", async () => { - const query = /* GraphQL */ ` - { - moviesAggregate { - count - } - } - `; - - const result = await translateQuery(neoSchema, query); - - // NOTE: Order of these subqueries have been reversed after refactor - expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` - "CYPHER 5 - CALL { - MATCH (this:Movie) - RETURN count(this) AS var0 - } - RETURN { count: var0 }" - `); - }); - - test("Create", async () => { - const query = /* GraphQL */ ` - mutation { - createMovies(input: [{ title: "dsa" }]) { - movies { - title - } - } - } - `; - - const result = await translateQuery(neoSchema, query); - - // NOTE: Order of these subqueries have been reversed after refactor - expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` - "CYPHER 5 - UNWIND $create_param0 AS create_var0 - CALL { - WITH create_var0 - CREATE (create_this1:Movie) - SET - create_this1.title = create_var0.title - RETURN create_this1 - } - RETURN collect(create_this1 { .title }) AS data" - `); - }); - test("Update", async () => { - const query = /* GraphQL */ ` - mutation { - updateMovies(update: { title_SET: "Potato" }) { - movies { - title - } - } - } - `; - - const result = await translateQuery(neoSchema, query); - - // NOTE: Order of these subqueries have been reversed after refactor - expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` - "CYPHER 5 - MATCH (this:Movie) - SET this.title = $this_update_title_SET - RETURN collect(DISTINCT this { .title }) AS data" - `); - }); - - test("Delete", async () => { - const query = /* GraphQL */ ` - mutation { - deleteActors { - nodesDeleted - } - } - `; - - const result = await translateQuery(neoSchema, query); - - // NOTE: Order of these subqueries have been reversed after refactor - expect(formatCypher(result.cypher)).toMatchInlineSnapshot(` - "CYPHER 5 - MATCH (this:Actor) - DETACH DELETE this" - `); - }); -}); From ce773e85a4f43f4e36508b053caf5d1b466b1b9b Mon Sep 17 00:00:00 2001 From: angrykoala Date: Mon, 27 Jan 2025 15:39:08 +0000 Subject: [PATCH 3/5] minor code cleanup in cypherQueryOptions --- packages/graphql/src/classes/Executor.ts | 47 ++++++++++++------------ 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/packages/graphql/src/classes/Executor.ts b/packages/graphql/src/classes/Executor.ts index 15584a1773..633e7fae11 100644 --- a/packages/graphql/src/classes/Executor.ts +++ b/packages/graphql/src/classes/Executor.ts @@ -172,32 +172,33 @@ export class Executor { return error; } - private generateQuery(query: string): string { - if (this.cypherQueryOptions) { - let cypherVersion = ""; - // Cypher version should be rendered as a separate statement - if (this.cypherQueryOptions.version) { - cypherVersion = `CYPHER ${this.cypherQueryOptions.version}\n`; - } + private addCypherOptionsToQuery(query: string): string { + const cypherVersion = this.getCypherVersionStatement(); - let cypherQueryOptions = ""; - const cypherQueryOptionsToAddToStatement = Object.entries(this.cypherQueryOptions).filter( - ([key, _value]) => { - return key !== "version"; - } - ); - if (cypherQueryOptionsToAddToStatement.length) { - cypherQueryOptions = `CYPHER ${cypherQueryOptionsToAddToStatement - .map(([key, value]) => { - return `${key}=${value}`; - }) - .join(" ")}\n`; - } + const cypherQueryOptions = this.getCypherQueryOptionsStatement(); + + return `${cypherVersion}${cypherQueryOptions}${query}`; + } - return `${cypherVersion}${cypherQueryOptions}${query}`; + private getCypherVersionStatement(): string { + if (this.cypherQueryOptions?.version) { + return `CYPHER ${this.cypherQueryOptions.version}\n`; } + return ""; + } - return query; + private getCypherQueryOptionsStatement(): string { + const cypherQueryOptions = Object.entries(this.cypherQueryOptions ?? []).filter(([key, _value]) => { + return key !== "version"; + }); + if (cypherQueryOptions.length) { + return `CYPHER ${cypherQueryOptions + .map(([key, value]) => { + return `${key}=${value}`; + }) + .join(" ")}\n`; + } + return ""; } private getTransactionConfig(info?: GraphQLResolveInfo): TransactionConfig { @@ -291,7 +292,7 @@ export class Executor { parameters: Record, transaction: Transaction | ManagedTransaction ): Result { - const queryToRun = this.generateQuery(query); + const queryToRun = this.addCypherOptionsToQuery(query); debugCypherAndParams(debug, queryToRun, parameters); From 48fda924ad620efadfe915c5fdbd7e08ce3ac9e8 Mon Sep 17 00:00:00 2001 From: angrykoala Date: Tue, 28 Jan 2025 10:41:52 +0000 Subject: [PATCH 4/5] Change addCypherVersion option to addCypherVersionPrefix as a boolean --- .changeset/soft-socks-count.md | 2 +- packages/graphql/src/classes/Executor.ts | 10 +++++++--- packages/graphql/src/types/index.ts | 2 +- .../config-options/query-options.int.test.ts | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.changeset/soft-socks-count.md b/.changeset/soft-socks-count.md index 4f90025dc6..2e69ca159d 100644 --- a/.changeset/soft-socks-count.md +++ b/.changeset/soft-socks-count.md @@ -7,7 +7,7 @@ Add `version` to `cypherQueryOptions` in context to add a Cypher version with `C ```js { cypherQueryOptions: { - version: "5", + addCypherVersionPrefix: true, }, } ``` diff --git a/packages/graphql/src/classes/Executor.ts b/packages/graphql/src/classes/Executor.ts index 633e7fae11..294e5ed9a1 100644 --- a/packages/graphql/src/classes/Executor.ts +++ b/packages/graphql/src/classes/Executor.ts @@ -40,6 +40,7 @@ import { } from "../constants"; import { debugCypherAndParams } from "../debug/debug-cypher-and-params"; import type { CypherQueryOptions } from "../types"; +import { isInArray } from "../utils/is-in-array"; import { Neo4jGraphQLAuthenticationError, Neo4jGraphQLConstraintValidationError, @@ -49,6 +50,8 @@ import { const debug = Debug(DEBUG_EXECUTE); +const SUPPORTED_CYPHER_VERSION = "5"; + interface DriverLike { session(config); } @@ -181,15 +184,16 @@ export class Executor { } private getCypherVersionStatement(): string { - if (this.cypherQueryOptions?.version) { - return `CYPHER ${this.cypherQueryOptions.version}\n`; + if (this.cypherQueryOptions?.addCypherVersionPrefix) { + return `CYPHER ${SUPPORTED_CYPHER_VERSION}\n`; } return ""; } private getCypherQueryOptionsStatement(): string { + const ignoredCypherQueryOptions: Array = ["addCypherVersionPrefix"]; const cypherQueryOptions = Object.entries(this.cypherQueryOptions ?? []).filter(([key, _value]) => { - return key !== "version"; + return !isInArray(ignoredCypherQueryOptions, key); }); if (cypherQueryOptions.length) { return `CYPHER ${cypherQueryOptions diff --git a/packages/graphql/src/types/index.ts b/packages/graphql/src/types/index.ts index e3a36bf77b..8117a4f63a 100644 --- a/packages/graphql/src/types/index.ts +++ b/packages/graphql/src/types/index.ts @@ -276,7 +276,7 @@ export interface CypherQueryOptions { operatorEngine?: "default" | "interpreted" | "compiled"; interpretedPipesFallback?: "default" | "disabled" | "whitelisted_plans_only" | "all"; replan?: "default" | "force" | "skip"; - version?: "5"; + addCypherVersionPrefix?: boolean; } /** Input field for graphql-compose */ diff --git a/packages/graphql/tests/integration/config-options/query-options.int.test.ts b/packages/graphql/tests/integration/config-options/query-options.int.test.ts index 7f37a78a0d..db510244c9 100644 --- a/packages/graphql/tests/integration/config-options/query-options.int.test.ts +++ b/packages/graphql/tests/integration/config-options/query-options.int.test.ts @@ -112,7 +112,7 @@ describe("query options", () => { const result = await testHelper.executeGraphQL(query, { variableValues: { id }, - contextValue: { cypherQueryOptions: { runtime: "interpreted", version: "5" } }, + contextValue: { cypherQueryOptions: { runtime: "interpreted", addCypherVersionPrefix: true } }, }); expect(result.errors).toBeFalsy(); From c1f163bf2a7d237bf9664e6cc59b23ff79435b79 Mon Sep 17 00:00:00 2001 From: angrykoala Date: Tue, 28 Jan 2025 15:29:44 +0000 Subject: [PATCH 5/5] Rename addCypherVersionPrefix to addVersionPrefix --- .changeset/soft-socks-count.md | 2 +- packages/graphql/src/classes/Executor.ts | 4 ++-- packages/graphql/src/types/index.ts | 2 +- .../integration/config-options/query-options.int.test.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.changeset/soft-socks-count.md b/.changeset/soft-socks-count.md index 2e69ca159d..cada9436ec 100644 --- a/.changeset/soft-socks-count.md +++ b/.changeset/soft-socks-count.md @@ -7,7 +7,7 @@ Add `version` to `cypherQueryOptions` in context to add a Cypher version with `C ```js { cypherQueryOptions: { - addCypherVersionPrefix: true, + addVersionPrefix: true, }, } ``` diff --git a/packages/graphql/src/classes/Executor.ts b/packages/graphql/src/classes/Executor.ts index 294e5ed9a1..13f51728b4 100644 --- a/packages/graphql/src/classes/Executor.ts +++ b/packages/graphql/src/classes/Executor.ts @@ -184,14 +184,14 @@ export class Executor { } private getCypherVersionStatement(): string { - if (this.cypherQueryOptions?.addCypherVersionPrefix) { + if (this.cypherQueryOptions?.addVersionPrefix) { return `CYPHER ${SUPPORTED_CYPHER_VERSION}\n`; } return ""; } private getCypherQueryOptionsStatement(): string { - const ignoredCypherQueryOptions: Array = ["addCypherVersionPrefix"]; + const ignoredCypherQueryOptions: Array = ["addVersionPrefix"]; const cypherQueryOptions = Object.entries(this.cypherQueryOptions ?? []).filter(([key, _value]) => { return !isInArray(ignoredCypherQueryOptions, key); }); diff --git a/packages/graphql/src/types/index.ts b/packages/graphql/src/types/index.ts index 8117a4f63a..c492c11b99 100644 --- a/packages/graphql/src/types/index.ts +++ b/packages/graphql/src/types/index.ts @@ -276,7 +276,7 @@ export interface CypherQueryOptions { operatorEngine?: "default" | "interpreted" | "compiled"; interpretedPipesFallback?: "default" | "disabled" | "whitelisted_plans_only" | "all"; replan?: "default" | "force" | "skip"; - addCypherVersionPrefix?: boolean; + addVersionPrefix?: boolean; } /** Input field for graphql-compose */ diff --git a/packages/graphql/tests/integration/config-options/query-options.int.test.ts b/packages/graphql/tests/integration/config-options/query-options.int.test.ts index db510244c9..3db6adb016 100644 --- a/packages/graphql/tests/integration/config-options/query-options.int.test.ts +++ b/packages/graphql/tests/integration/config-options/query-options.int.test.ts @@ -112,7 +112,7 @@ describe("query options", () => { const result = await testHelper.executeGraphQL(query, { variableValues: { id }, - contextValue: { cypherQueryOptions: { runtime: "interpreted", addCypherVersionPrefix: true } }, + contextValue: { cypherQueryOptions: { runtime: "interpreted", addVersionPrefix: true } }, }); expect(result.errors).toBeFalsy();