Neo4j-graphql-js: Feature request: A 'cypher' template literal tag for @cypher statements

Created on 2 May 2020  路  3Comments  路  Source: neo4j-graphql/neo4j-graphql-js

This issue requests support for a cypher template literal tag for use in writing the Cypher statement argument of @cypher directive fields. Using a cypher tag would result in support for Cypher syntax highlighting in any editor using an extension that provides highlighting support for it, such as the Cypher Query Langauge Tools for Neo4j extension for Visual Studio Code.

This would result in a smoother experience when reading and writing Cypher within a GraphQL schema using @cypher fields, especially for multi-line Cypher statements. A GraphQL block string is currently used to support a multi-line String type directive argument. This results in an absense of syntax highlighting support within such arguments. In the Federation example for the inventory service, the @cypher statement for the shippingEstimate field on the Product entity would normally be as follows:

Situation

shippingEstimate: Int
  @requires(fields: "weight price")
  @cypher(statement: """
    CALL apoc.when($price > 900,
      // free for expensive items
      'RETURN 0 AS value',
      // estimate is based on weight
      'RETURN $weight * 0.5 AS value',
      {
        price: $price,
        weight: $weight
      })
    YIELD value
    RETURN value.value
  """)

An implementation for a cypher tag template for the statement argument of a @cypher directive might look like:

Implementation

export const cypher = (statement, ...substitutions) => {
  // Get the array of string literals
  const literals = statement.raw;
  // Add each substitution inbetween all
  const composed = substitutions.reduce((composed, substitution, index) => {
    // Add the string literal
    composed.push(literals[index]);
    // Add the substitution proceeding it
    composed.push(substitution);
    return composed;
  }, []);
  // Add the last literal
  composed.push(literals[literals.length - 1]);
  // Return the Cypher statement string as a GraphQL block string
  // for the `@cypher` directive statement argument
  return `statement: """${composed.join('')}"""`;
};

Example

With the Cypher statement argument being provided as the result of the above cypher tag implementation, we could write the shippingEstimate's @cypher statement within another string literal with the tag, used as an embedded expression within the string literal containing the GraphQL schema SDL (which is the case when using a gql tag). The Cypher would then be appropriately highlighted in an editor with Cypher language support for the tag.

shippingEstimate: Int
  @requires(fields: "weight price")
  @cypher(${cypher`
    CALL apoc.when($price > 900,
      // free for expensive items
      'RETURN 0 AS value',
      // estimate is based on weight
      'RETURN $weight * 0.5 AS value',
      {
        price: $price,
        weight: $weight
      })
    YIELD value
    RETURN value.value
  `})

Using the Cypher Query Langauge Tools for Neo4j extension for Visual Studio Code:

image

Additional possibilities

  • Statements as variables

    The Cypher statement of a @cypher directive using a cypher tag could also be elevated to a
    variable, which could be imported.

    matchUsers.js
import { cypher } from 'neo4j-graphql-js';

export MATCH_USERS = cypher`
  MATCH (users: User)
  RETURN users
`;
typeDefs.js
import { MATCH_USERS } from 'matchUsers.js';

const typeDefs = gql`
  type Query {
    Users: [User] @cypher(${
      MATCH_USERS
    })
  }
  type User {
    id: ID!
    name: String
  }
`;
  • Validation and analysis

    A Cypher statement using a cypher tag could be processed using additional behaviours added
    to its implementation, such as validation and analysis.

Most helpful comment

It's been implemented in the referenced PR :)

All 3 comments

@michaeldgraham Why did you close this? Sounds useful to me.

It's been implemented in the referenced PR :)

Yay!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

purplemana picture purplemana  路  3Comments

NathanPimlott picture NathanPimlott  路  4Comments

benjamin-rood picture benjamin-rood  路  5Comments

robmurtagh picture robmurtagh  路  3Comments

emregency picture emregency  路  5Comments