Giter VIP home page Giter VIP logo

graphql-schema-utilities's Introduction

graphql-schema-utilities

A CLI tool to merge schema files, and validate operations against a GraphQL Schema.

Installation

npm install -g graphql-schema-utilities

Usage

Using the CLI tool

>> graphql-schema-utilities

The tool will first merge schema files and then validate the merged schema, throwing errors if the schema isn't valid and exit with exit code 1. If Schema is valid it will check each operation in the file glob by parsing the operation and validating it against the schema. If errors are found, they will be displayed by file name and exit with exit code 1.

Merging schema files

You can merge your schema files across different modules and directories. In this example, you have three different set of files in three different directories:

~/moduleMain/schemas/Root.graphql:
type Query;

~/module1/schemas/Book.graphql:
extend type Query {
  bookById(id: ID!): Book
}
    
type Book {
  id: ID!
  authorId: ID!
}
 
~/module2/schemas/User.graphql:
extend type Query {
  userById(id: ID!): User
}
    
type User {
  id: ID!
  name: String!
}

Running the CLI utility generates the merged schema file, Merged_schema.graphQL:


type Query {
   userById(id: ID!): User
   bookById(id: ID!): Book
 }
 
 type User {
   id: ID!
   name: String!
 }
 
 type Book {
   id: ID!
   authorId: ID!
 }

The CLI options:

Options:
  -V, --version               output the version number.
  -o, --output [pattern]      The file path where the merged schema will be outputted to.
  -s, --schema [pattern]      Use a glob path that would define all of your schema files to merge them into a valid schema. (default: "").
  -r, --rules [pattern]       The file path for your custom rules to validate your operations, and your merged schema. To learn abot how to write your custom rules: check the README.md file  (default: "").
  -p, --operations [pattern]  Use a glob that that contains your graphql operation files to test against the merged schema file. (default: "").
  -d, --includeDirectives     By default will NOT merge the directives, unless you added this flag.
  -h, --help                  output usage information.

How to merge the schema files:

>> graphql-schema-utilities -s "{./First_Directory/**/*.graphql,./Second_Directory/users/**/
*.graphql}"

That will merge all the schema files in both directories. Note that we are passing the directories as Glob.

How to validate your operations against your merged schema:

>> graphql-schema-utilities -s "{./First_Directory/**/*.graphql,./Second_Directory/users/**/
*.graphql}" -p "./path_to_directory/operations/*.graphql"

Note that the "./path_to_directory/operations/*.graphql" operations path is also using Glob.

How to add your custom validation rules:

These tools will use the validation rules as defined in graphql-js validation rules. But you can create your own validation rule. Here is an example for custom validation rule against your operation which validates that your operation name must be prefixed with Hawaii_ .

### file name: custom_rule.ts

import { GraphQLError } from 'graphql';

export function doesNotStartWithHawaii(operationName: string): string {
  return `"${operationName}" operation does not start with Hawaii_.`;
}

/**
 * Valid only if it starts with Hawaii_.
 * A GraphQL document is only valid if all defined operations starts with Hawaii_.
 */
export function OperationNameStartsWithHawaii(
  context: any,
): any {
  const knownOperationNames = Object.create(null);  
  return {
    OperationDefinition(node) {
      const operationName = node.name;
      if (operationName) {
        if (!operationName.value.startsWith('Hawaii_')) {
          
          context.reportError(
            new GraphQLError(
              doesNotStartWithHawaii(operationName.value)
            ),
          );
        } else {
          knownOperationNames[operationName.value] = operationName;
        }
      }
      return false;
    },
    FragmentDefinition: () => false,
  };
}

Then run the CLI with the rules option:

>> graphql-schema-utilities -s "{./First_Directory/**/*.graphql,./Second_Directory/users/**/
*.graphql}" -p "./path_to_directory/operations/*.graphql" -r "path/to/custom_rule.js"

Note:

1- We are referencing the .js file not the .ts.

2- The path here is NOT Glob, You can use either relative or absolute path.

To learn more about how to write your own custom validation rules against graphql schema or operation files: Validate method in graphql-js.

Merge and Validate programmatically

This tool can be used as a library for a JS app as well. you can call the mergeSchemas async using Promise.

const tools = require('graphql-schema-utilities');

const glob = "{./First_Directory/**/*.graphql,./Second_Directory/users/**/
  *.graphql}"
tools.mergeGQLSchemas(glob).then((schema) => {
  console.log('schema files were merged, and the valid schema is: ', schema)
})
  .catch((error) => {
    console.error(error)
  })

Validate operations using promises:

tools.mergeGQLSchemas('./schema/*.graphql').then((schema) => {
  tools.validateOperations('./queries/*.graphql', schema).then((results) => {
    console.log(results)
  })
})

Note: you must use quotes around each file glob or the utility will not work properly.

Development

Install dependencies with

npm install

Build

npm run build

Run test in watch mode

npm run test:watch

Contributing

Please help make this tool better. For more information take a look at CONTRIBUTING.md

License

Apache 2.0

Notes

This package was created based on a fork from graphql-validator that was developed by credit-karma.

graphql-schema-utilities's People

Contributors

dependabot[bot] avatar hsehweil avatar jamesiri avatar mattdhart avatar mridulag2899 avatar pandajiexiao avatar shenoyirvine avatar thillm-amazon avatar utsavmur avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql-schema-utilities's Issues

Empty type Query as mentioned in example not possible

Not possible to have an empty Root.graphql file with type Query as mentioned in example

https://aws.amazon.com/blogs/mobile/merging-graphql-schema-files-and-more-with-the-cli/

this is the error:

Loading schema from src/graphql/**/*.graphql
>> Error(1): Syntax Error: Expected Name, found } check the file:
file:///Users/**********/src/graphql/Root.graphql

Location of errors:  [ [ { line: 2, column: 1 } ] ]
>> Total numbers of errors found: 1.
Could not merge Schema files!

also in the blogpost this command is not complete:

> graphql-schema-utilities -s โ€œ{/module2/schemas/**/*.graphql,/module1/schemas/**/*.graphql,/moduleMain/schemas/**/*.graphql

AppSync supports multi interface implementation while this tool does not

AWS AppSync supports the following schema:

interface Entry {

}

interface Entry {

}

type User implements Entry, BaseRep @aws_cognito_user_pools {

}

However, this tool fails with the following error:

Error: Command failed: /Users/sav/app/node_modules/.bin/graphql-schema-utilities -d -s '/Users/sav/infrastructure/lib/projects/graphql/*.graphql' -o '/Users/sav/infrastructure/lib/projects/graphql/generated/schema.graphql'

>> Error(1): Syntax Error: Unexpected Name "BaseRep" check the file:
file:///Users/sav/infrastructure/lib/projects/graphql/user.graphql

Errors when using LIST of mutations in @aws_subscribe

Hi,
I am facing a "Could not merge Schema files!" error when trying to merge Subscriptions that contain the @aws_subscribe directive that expects a list of Strings as the "mutations" value.

The following directive has been defined in a file called "aws_appsync.graphql":
directive @aws_subscribe(mutations: [String!]!) on FIELD_DEFINITION

And Subscriptions defined in another as:

type Subscription {
    onCreate: Insight @aws_subscribe(mutations: ["createInsight"])
}

Behaviour:

  • When calling the command "graphql-schema-utilities" without the "includeDirectives" flag, the merge completes successfully, but obviously does not includes any directives
  • When calling the command with the "includeDirectives" flag, I receive the "Could not merge Schema files!" error
  • If the "mutations" value is changed to a String, and the "includeDirectives" flag is set, for example:
    onCreate: Insight @aws_subscribe(mutations: "createInsight")
    Then the merge completes successfully.

The issue is I have a onUpdate subscription that needs to be triggered based on multiple mutation events, so the "mutations" value needs to be a list.

Thanks.

make the tsconfig more strict

in addition to the set of rules below we need to add more ts rules:

"rules": {
"no-console": false,
"quotemark": [
true,
"single",
"avoid-escape"
],
"no-var-keyword": true,
"no-var-requires": false
}

@aws_subscribe directive is missing in merged schema

@aws_subscribe directive is missing in merged schema

extend type Subscription {
    onDriverPositionChange(input: OnDriverPositionChangeInput): DriverPosition @aws_subscribe(mutations: ["updateDriverPosition"])
}

input OnDriverPositionChangeInput {
    driverId: ID!
}

directive @aws_subscribe(mutations: [String!]!) on FIELD_DEFINITION

gets generated to

type Subscription {
    onDriverPositionChange(input: OnDriverPositionChangeInput): DriverPosition
}

input OnDeliveryRequestChangeInput {
    driverId: ID!
}

directive @aws_subscribe(mutations: [String!]!) on FIELD_DEFINITION

Allow --quiet / --silent option to the CLI

At the moment, even when using the -o option and writing the merged schema to a file, it still outputs the entire schema to stdout. This is very annoying when run in an npm script before a build or a cdk deploy.

It is also not an option to redirect to /dev/null because we also have to support Windows which uses NUL instead as an equivalent and it would also suppress any npm/npx error.

Currently using version: 1.1.3

Steps to reproduce:

  1. npm install graphql-schema-utilities
  2. npx graphql-schema-utilities -s "./schema/**/[!dist]*.graphql" -o "./schema/dist/schema.graphql" --includeDirectives

Result:
You get the entire schema output before the success message.

Expected:
That since we're using the -o option, there would be no output. Or at least a --quiet or --silent option to silence it.

Only Add Certain Directives

Hi there is a flag --includeDirectives to include all directives when building schema but is there a feature to only add certain directives?

I think it will be a very useful feature for schema that includes both custom directives and appsync recognized directives. Thanks

Programmatic access to mergeGQLSchemas is not exported.

In the README.md here, it states that it should be possible to do the following:

const tools = require('graphql-schema-utilities');
tools.mergeGQLSchemas([...])

However, mergeGQLSchemas() seems to only be exported from cli.ts, but isn't re-exported in index.ts, meaning that the above code doesn't seem like it will work (and doesn't, in my testing).

Is this an issue in index.ts, an issue in the docs, or am I missing something?

Warning about graphql version during installation

I get the following warning during yarn install of the monorepo project, where on of the workspaces uses graphql-schema-utilities:

warning "workspace-aggregator-... > ... > [email protected]" has incorrect peer dependency "graphql@^0.13.0 || ^14.0.0".

We use GraphQL v15, which is out for more than a year and is required by most of the modern tooling.

The warning is issued because the package requires GraphQL v13 or v14 in peer dependencies:

  "peerDependencies": {
    "graphql": "^0.13.0 || ^14.0.0"
  }

AppSync reject directive definition saying "Directive definitions are not supported."

in my schema I have subscription defined using @aws_subscribe

type Subscription {
  onCreateAlbum(owner: String!): Album @aws_subscribe(mutations: ["createAlbum"])
}

If I don't define following when I merge two schema file:
directive @aws_subscribe(mutations: [String!]!) on FIELD_DEFINITION
it will throw error saying "Error(1): Unknown directive "aws_subscribe""

If add the directive definition, when I upload to AppSync, it got rejected saying "Directive definitions are not supported."

How would I be able to merge the schema and use it for AppSync at the same time?

Multiple implements throws Syntax error

I have a type definition as:
type TopListBookEdge implements TopListEdge, Edge{...}

and merge throws an error ->
>> Error(1): Syntax Error: Unexpected Name "Edge" check the file:

Edge is defined in the schema file

Add an option to remove comments from the source files

I add quite many comments in the source files. After merging, unfortunately, AWS AppSync complains as it does not recognize comments. It would be great to have an option to automatically remove comments from the generated GraphQL schema.

Interfaces implementing other interfaces loose implements clause when --includeDirectives option set

The GraphQL spec supports interfaces implementing other interfaces:
graphql/graphql-spec#373

When using graphql-schema-utilities with the --includeDirectives flag set, the implements ... clause is removed from Interfaces in the merged schema.

Example

Input Schema

interface Node {
  id: ID!
}

interface FooNode implements Node {
  id: ID!
  foo: String
}

Output Schema from graphql-schema-utilities with the --includeDirectives flag set

interface Node {
  id: ID!
}

interface FooNode {
  id: ID!
  foo: String
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.