Giter VIP home page Giter VIP logo

gql-generator's Introduction

gql-generator

Generate queries from graphql schema, used for writing api test.

Example

# Sample schema
type Query {
  user(id: Int!): User!
}

type User {
  id: Int!
  username: String!
  email: String!
  createdAt: String!
}
# Sample query generated
query user($id: Int!) {
  user(id: $id){
    id
    username
    email
    createdAt
  }
}

Usage

# Install
npm install gql-generator -g

# see the usage
gqlg --help

# Generate sample queries from schema file
gqlg --schemaFilePath ./example/sampleTypeDef.graphql --destDirPath ./example/output --depthLimit 5

Now the queries generated from the sampleTypeDef.graphql can be found in the destDir: ./example/output.

This tool generate 3 folders holding the queries: mutations, queries and subscriptions. And also index.js files to export the queries in each folder.

You can require the queries like this:

// require all the queries
const queries = require('./example/output');
// require mutations only
const mutations = require('./example/output/mutations');

// sample content
console.log(queries.mutations.signup);
console.log(mutations.signup);
/*
mutation signup($username: String!, email: String!, password: String!){
  signup(username: $username, email: $email, password: $password){
    token
    user {
      id
      username
      email
      createdAt
    }
  }
}
*/

The tool will automatically exclude any @deprecated schema fields (see more on schema directives here). To change this behavior to include deprecated fields you can use the includeDeprecatedFields flag when running the tool, e.g. gqlg --includeDeprecatedFields.

Programmatic Access

Alternatively, you can run gql-generator directly from your scripts:

const gqlg = require('gql-generator')

gqlg({ schemaFilePath: './example/sampleTypeDef.graphql', destDirPath: './example/output', depthLimit: 5 })

Usage example

Say you have a graphql schema like this:

type Mutation {
  signup(
    email: String!
    username: String!
    password: String!
  ): UserToken!
}

type UserToken {
  token: String!
  user: User!
}

type User {
  id: Int!
  username: String!
  email: String!
  createdAt: String!
}

Before this tool, you write graphql api test like this:

const { GraphQLClient } = require('graphql-request');
require('should');

const host = 'http://localhost:8080/graphql';

test('signup', async () => {
  const gql = new GraphQLClient(host);
  const query = `mutation signup($username: String!, email: String!, password: String!){
    signup(username: $username, email: $email, password: $password){
      token
      user {
        id
        username
        email
        createdAt
      }
    }
  }`;

  const data = await gql.request(query, {
    username: 'tim',
    email: '[email protected]',
    password: 'samplepass',
  });

  (typeof data.signup.token).should.equal('string');
);

As gqlg generated the queries for you, you don't need to write the query yourself, so your test will becomes:

const { GraphQLClient } = require('graphql-request');
require('should');
const mutations = require('./example/output/mutations');

const host = 'http://localhost:8080/graphql';

test('signup', async () => {
  const gql = new GraphQLClient(host);

  const data = await gql.request(mutations.signup, {
    username: 'tim',
    email: '[email protected]',
    password: 'samplepass',
  });

  (typeof data.signup.token).should.equal('string');
);

Notes

  • As this tool is used for tests, it expands all of the fields in a query. There might be recursive fields in the query, so gqlg ignores the types which have been added in the parent queries already by default. This can be disabled using the --includeCrossReferences argument.
  • Variable names are derived from argument names, so variables generated from multiple occurrences of the same argument name must be deduped. An index is appended to any duplicates e.g. region(language: $language1).

gql-generator's People

Contributors

aaronmoat avatar bonham000 avatar damau avatar dependabot[bot] avatar dr3 avatar galelq avatar justenau avatar mishasyrbu avatar robcrawford avatar rvanderlaan avatar samuelghill avatar svengau avatar timqian avatar tomfa avatar wooodhead avatar zvictor 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gql-generator's Issues

SyntaxError: Unexpected token ...

Unable to run

npm install gql-generator -g

Response

/usr/lib/node_modules/gql-generator/index.js:72
    const meta = { ...fieldData.meta };
                   ^^^

SyntaxError: Unexpected token ...
    at createScript (vm.js:56:10)
    at Object.runInThisContext (vm.js:97:10)
    at Module._compile (module.js:549:28)
    at Object.Module._extensions..js (module.js:586:10)
    at Module.load (module.js:494:32)
    at tryModuleLoad (module.js:453:12)
    at Function.Module._load (module.js:445:3)
    at Module.runMain (module.js:611:10)
    at run (bootstrap_node.js:387:7)

Support extend type

Hi,

We have modularized our graphql in to separate files so we extend the queries and mutations, eg.

extend type Query {
  someQuery: Boolean
}

Would it be possible to support this?

Cannot read property 'getFields' of undefined

Error Example:

gqlg --schemaFilePath ./schema.graphql --destDirPath ./gqlg-new --depthLimit 2
description: Mutation
/usr/local/lib/node_modules/gql-generator/index.js:177
    const field = gqlSchema.getType(description).getFields()[type];
                                                ^

TypeError: Cannot read property 'getFields' of undefined
    at /usr/local/lib/node_modules/gql-generator/index.js:177:49
    at Array.forEach (<anonymous>)
    at generateFile (/usr/local/lib/node_modules/gql-generator/index.js:176:20)
    at Object.<anonymous> (/usr/local/lib/node_modules/gql-generator/index.js:193:3)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Module.load (internal/modules/cjs/loader.js:643:32)
    at Function.Module._load (internal/modules/cjs/loader.js:556:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:839:10)
    at internal/main/run_main_module.js:17:11

If GQL Schema looks like this:

schema {
  query: RootQueryType
  mutation: RootMutationType
}

...
query: RootQueryType
  mutation: RootMutationType
}

type RootQueryType {
  asset(id: ID): Asset
  ...

* That's really popular example of schemas.

Then you will see error as shown above cause description filed in index.js get values from the hardcoded list: Query,Mutation,Subscription and doesn't check custom query names.

Fields cross-referencing type results in bug in output schema

Reproducible example:

type Query {
  testQuery(id: ID!): TestQuery
}

type TestQuery {
  foo: [Foo]
  bar: [Bar]
}

type Foo {
  bar: [Bar]
  surname: String
}

type Bar {
  foo: [Foo]
  name: String
}

Output:


query testQuery($id: ID!) {
  testQuery(id: $id) {
    foo {
      bar {
        foo {
          surname
        }
        name
      }
      surname
    }
    bar {
      name
    }
  }
}

Expected output with depthLimit = 3

query testQuery($id: ID!) {
  testQuery(id: $id) {
    foo {
      bar {
        foo {
          surname
        }
        name
      }
      surname
    }
   bar {
      foo {
        bar {
          name
        }
        surname
      }
      name
    }
  }
}

This is without passing in the depth limit flag, but there's the same issue with it anyways. Seems like it's stopping a bit too short as soon as it detects a circular reference, before it even starts expanding them.

Possibility to add exluded fields

Hey,

it would be great if it would be possible to exclude some fields. For example ID or date fields that make conflicts with snapshots.

Now I solve it with bash script:

find ./tests/ -name *.gql -type f -exec sed -i '' -e "s/  updatedAt//" {} \;
find ./tests/ -name *.gql -type f -exec sed -i '' -e "s/  createdAt//" {} \;

It goes to every gql file and remove createdAt and updatedAt fields. The space before those two is because we do not want to strip out the arguments with the same name.

Unexpected output on scheme based on unions

I'm generating queries based on this graphql scheme:

type Query {
  animals: [AnimalResult]!
}

union AnimalResult = Dog | Cat

type Dog {
  example: [Something!]!
}

type Cat {
  example: [Something!]!
}

type Something {
  id: ID!
}

I would expect that a animals.gql would be generated:

query animals{
    animals{
        ... on Dog {
            example{
                id
            }
        }
        ... on Cat {
            example{
                id
            }
        }
    }
}

But I obtain this:

query animals{
    animals{
        ... on Dog {
            example{
                id
            }
        }
        ... on Cat {

        }
    }
}

As you can see id field in Cat is not included.

Is this a bug? I would like to fix this, I think it could be something about this loop:
https://github.com/timqian/gql-generator/blob/master/index.js#L140

Need a way to add directive

Hello ,
I need a way to add directives to query like @ connection directive Example :

query Feed($type: FeedType!, $offset: Int, $limit: Int) {
feed(type: $type, offset: $offset, limit: $limit) @ connection(key: "feed", filter: ["type"]) {
id
# ...
}
}

Detect query/mutation/subscription roots from schema

I have schema that defines query,mutation and subscription root type names in schema file and does not use default names

schema {
  query: query_root
  mutation: mutation_root
  subscription: subscription_root
}
type mutation_root {...}

type query_root {...}

type subscription_root {...}

But they are not recognized by gql-generator, because it's regexes does not match those names.

Example from GraphQL spec https://spec.graphql.org/October2021/#example-e2969

Export typescript files

Could you provide a way to export the queries in typescript files ?
Like =>


import gql from 'graphql-tag';

export const ADD_TASK = gql`
mutation createTask($description: String!, $title: String!, $status: TaskStatus){
    createTask(description: $description, title: $title, status: $status){
      id
      title
      description
      version
      status
    }
  }
`;

Crash if input file is bigger than ~26kb

The tool is awesome, thank you for writing it.
Sadly if input schema.graphql (with all mutations and queries) is bigger than ~26kb there is a crash with output:

/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/lexer.js:302
  throw (0, _error.syntaxError)(source, pos, unexpectedCharacterMessage(code));
  ^
GraphQLError: Syntax Error: Cannot parse the unexpected character <EOF>.
    at syntaxError (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/error/syntaxError.js:24:10)
    at readToken (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/lexer.js:302:32)
    at Object.lookahead (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/lexer.js:61:43)
    at Object.advanceLexer [as advance] (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/lexer.js:52:33)
    at skip (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:1284:11)
    at many (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:1349:11)
    at parseEnumValuesDefinition (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:945:50)
    at parseEnumTypeDefinition (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:930:16)
    at parseTypeSystemDefinition (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:669:16)
    at parseDefinition (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:143:16)

Syntax Error: Unexpected character: U+FFFD.

Hello I am trying to generate query using this command

gqlg --schemaFilePath ./schema.graphql --destDirPath ./output --depthLimit 5

it is giving me this error

G:\usr\local\node_modules\gql-generator\node_modules\graphql\language\lexer.js:420
    throw (0, _syntaxError.syntaxError)(
    ^

GraphQLError: Syntax Error: Unexpected character: U+FFFD.
    at syntaxError (G:\usr\local\node_modules\gql-generator\node_modules\graphql\error\syntaxError.js:15:10)
    at readNextToken (G:\usr\local\node_modules\gql-generator\node_modules\graphql\language\lexer.js:420:40)
    at Lexer.lookahead (G:\usr\local\node_modules\gql-generator\node_modules\graphql\language\lexer.js:84:29)
    at Lexer.advance (G:\usr\local\node_modules\gql-generator\node_modules\graphql\language\lexer.js:67:38)
    at Parser.expectToken (G:\usr\local\node_modules\gql-generator\node_modules\graphql\language\parser.js:1408:19)
    at Parser.many (G:\usr\local\node_modules\gql-generator\node_modules\graphql\language\parser.js:1525:10)
    at Parser.parseDocument (G:\usr\local\node_modules\gql-generator\node_modules\graphql\language\parser.js:121:25)
    at parse (G:\usr\local\node_modules\gql-generator\node_modules\graphql\language\parser.js:32:17)
    at buildSchema (G:\usr\local\node_modules\gql-generator\node_modules\graphql\utilities\buildASTSchema.js:101:38)
    at Object.<anonymous> (G:\usr\local\node_modules\gql-generator\index.js:21:19) {
  path: undefined,
  locations: [ { line: 1, column: 1 } ],
  extensions: [Object: null prototype] {}
}
PS G:\gitLocal\nirmaan-web\nirmaan-frontend> 

here is my schema file

schema {
  query: query_root
  mutation: mutation_root
  subscription: subscription_root
}

"""whether this query should be cached (Hasura Cloud only)"""
directive @cached(
  """measured in seconds"""
  ttl: Int! = 60

  """refresh the cache entry"""
  refresh: Boolean! = false
) on QUERY

"""
Boolean expression to compare columns of type "Boolean". All fields are combined with logical 'AND'.
"""
input Boolean_comparison_exp {
  _eq: Boolean
  _gt: Boolean
  _gte: Boolean
  _in: [Boolean!]
  _is_null: Boolean
  _lt: Boolean
  _lte: Boolean
  _neq: Boolean
  _nin: [Boolean!]
}

"""
Boolean expression to compare columns of type "Int". All fields are combined with logical 'AND'.
"""
input Int_comparison_exp {
  _eq: Int
  _gt: Int
  _gte: Int
  _in: [Int!]
  _is_null: Boolean
  _lt: Int
  _lte: Int
  _neq: Int
  _nin: [Int!]
}

"""
Boolean expression to compare columns of type "String". All fields are combined with logical 'AND'.
"""
input String_comparison_exp {
  _eq: String
  _gt: String
  _gte: String

  """does the column match the given case-insensitive pattern"""
  _ilike: String
  _in: [String!]

  """
  does the column match the given POSIX regular expression, case insensitive
  """
  _iregex: String
  _is_null: Boolean

  """does the column match the given pattern"""
  _like: String
  _lt: String
  _lte: String
  _neq: String

  """does the column NOT match the given case-insensitive pattern"""
  _nilike: String
  _nin: [String!]

  """
  does the column NOT match the given POSIX regular expression, case insensitive
  """
  _niregex: String

  """does the column NOT match the given pattern"""
  _nlike: String

  """
  does the column NOT match the given POSIX regular expression, case sensitive
  """
  _nregex: String

  """does the column NOT match the given SQL regular expression"""
  _nsimilar: String

  """
  does the column match the given POSIX regular expression, case sensitive
  """
  _regex: String

  """does the column match the given SQL regular expression"""
  _similar: String
}

"""mutation root"""
type mutation_root {
  """
  delete data from the table: "temp_post"
  """
  delete_temp_post(
    """filter the rows which have to be deleted"""
    where: temp_post_bool_exp!
  ): temp_post_mutation_response

  """
  delete single row from the table: "temp_post"
  """
  delete_temp_post_by_pk(id: Int!): temp_post

  """
  delete data from the table: "user"
  """
  delete_user(
    """filter the rows which have to be deleted"""
    where: user_bool_exp!
  ): user_mutation_response

  """
  delete single row from the table: "user"
  """
  delete_user_by_pk(id: uuid!): user

  """
  insert data into the table: "temp_post"
  """
  insert_temp_post(
    """the rows to be inserted"""
    objects: [temp_post_insert_input!]!

    """upsert condition"""
    on_conflict: temp_post_on_conflict
  ): temp_post_mutation_response

  """
  insert a single row into the table: "temp_post"
  """
  insert_temp_post_one(
    """the row to be inserted"""
    object: temp_post_insert_input!

    """upsert condition"""
    on_conflict: temp_post_on_conflict
  ): temp_post

  """
  insert data into the table: "user"
  """
  insert_user(
    """the rows to be inserted"""
    objects: [user_insert_input!]!

    """upsert condition"""
    on_conflict: user_on_conflict
  ): user_mutation_response

  """
  insert a single row into the table: "user"
  """
  insert_user_one(
    """the row to be inserted"""
    object: user_insert_input!

    """upsert condition"""
    on_conflict: user_on_conflict
  ): user

  """
  update data of the table: "temp_post"
  """
  update_temp_post(
    """increments the numeric columns with given value of the filtered values"""
    _inc: temp_post_inc_input

    """sets the columns of the filtered rows to the given values"""
    _set: temp_post_set_input

    """filter the rows which have to be updated"""
    where: temp_post_bool_exp!
  ): temp_post_mutation_response

  """
  update single row of the table: "temp_post"
  """
  update_temp_post_by_pk(
    """increments the numeric columns with given value of the filtered values"""
    _inc: temp_post_inc_input

    """sets the columns of the filtered rows to the given values"""
    _set: temp_post_set_input
    pk_columns: temp_post_pk_columns_input!
  ): temp_post

  """
  update data of the table: "user"
  """
  update_user(
    """sets the columns of the filtered rows to the given values"""
    _set: user_set_input

    """filter the rows which have to be updated"""
    where: user_bool_exp!
  ): user_mutation_response

  """
  update single row of the table: "user"
  """
  update_user_by_pk(
    """sets the columns of the filtered rows to the given values"""
    _set: user_set_input
    pk_columns: user_pk_columns_input!
  ): user
}

"""column ordering options"""
enum order_by {
  """in ascending order, nulls last"""
  asc

  """in ascending order, nulls first"""
  asc_nulls_first

  """in ascending order, nulls last"""
  asc_nulls_last

  """in descending order, nulls first"""
  desc

  """in descending order, nulls first"""
  desc_nulls_first

  """in descending order, nulls last"""
  desc_nulls_last
}

type query_root {
  """
  fetch data from the table: "temp_post"
  """
  temp_post(
    """distinct select on columns"""
    distinct_on: [temp_post_select_column!]

    """limit the number of rows returned"""
    limit: Int

    """skip the first n rows. Use only with order_by"""
    offset: Int

    """sort the rows by one or more columns"""
    order_by: [temp_post_order_by!]

    """filter the rows returned"""
    where: temp_post_bool_exp
  ): [temp_post!]!

  """
  fetch aggregated fields from the table: "temp_post"
  """
  temp_post_aggregate(
    """distinct select on columns"""
    distinct_on: [temp_post_select_column!]

    """limit the number of rows returned"""
    limit: Int

    """skip the first n rows. Use only with order_by"""
    offset: Int

    """sort the rows by one or more columns"""
    order_by: [temp_post_order_by!]

    """filter the rows returned"""
    where: temp_post_bool_exp
  ): temp_post_aggregate!

  """fetch data from the table: "temp_post" using primary key columns"""
  temp_post_by_pk(id: Int!): temp_post

  """
  fetch data from the table: "user"
  """
  user(
    """distinct select on columns"""
    distinct_on: [user_select_column!]

    """limit the number of rows returned"""
    limit: Int

    """skip the first n rows. Use only with order_by"""
    offset: Int

    """sort the rows by one or more columns"""
    order_by: [user_order_by!]

    """filter the rows returned"""
    where: user_bool_exp
  ): [user!]!

  """
  fetch aggregated fields from the table: "user"
  """
  user_aggregate(
    """distinct select on columns"""
    distinct_on: [user_select_column!]

    """limit the number of rows returned"""
    limit: Int

    """skip the first n rows. Use only with order_by"""
    offset: Int

    """sort the rows by one or more columns"""
    order_by: [user_order_by!]

    """filter the rows returned"""
    where: user_bool_exp
  ): user_aggregate!

  """fetch data from the table: "user" using primary key columns"""
  user_by_pk(id: uuid!): user
}

type subscription_root {
  """
  fetch data from the table: "temp_post"
  """
  temp_post(
    """distinct select on columns"""
    distinct_on: [temp_post_select_column!]

    """limit the number of rows returned"""
    limit: Int

    """skip the first n rows. Use only with order_by"""
    offset: Int

    """sort the rows by one or more columns"""
    order_by: [temp_post_order_by!]

    """filter the rows returned"""
    where: temp_post_bool_exp
  ): [temp_post!]!

  """
  fetch aggregated fields from the table: "temp_post"
  """
  temp_post_aggregate(
    """distinct select on columns"""
    distinct_on: [temp_post_select_column!]

    """limit the number of rows returned"""
    limit: Int

    """skip the first n rows. Use only with order_by"""
    offset: Int

    """sort the rows by one or more columns"""
    order_by: [temp_post_order_by!]

    """filter the rows returned"""
    where: temp_post_bool_exp
  ): temp_post_aggregate!

  """fetch data from the table: "temp_post" using primary key columns"""
  temp_post_by_pk(id: Int!): temp_post

  """
  fetch data from the table: "user"
  """
  user(
    """distinct select on columns"""
    distinct_on: [user_select_column!]

    """limit the number of rows returned"""
    limit: Int

    """skip the first n rows. Use only with order_by"""
    offset: Int

    """sort the rows by one or more columns"""
    order_by: [user_order_by!]

    """filter the rows returned"""
    where: user_bool_exp
  ): [user!]!

  """
  fetch aggregated fields from the table: "user"
  """
  user_aggregate(
    """distinct select on columns"""
    distinct_on: [user_select_column!]

    """limit the number of rows returned"""
    limit: Int

    """skip the first n rows. Use only with order_by"""
    offset: Int

    """sort the rows by one or more columns"""
    order_by: [user_order_by!]

    """filter the rows returned"""
    where: user_bool_exp
  ): user_aggregate!

  """fetch data from the table: "user" using primary key columns"""
  user_by_pk(id: uuid!): user
}

"""
columns and relationships of "temp_post"
"""
type temp_post {
  content: String!
  id: Int!
}

"""
aggregated selection of "temp_post"
"""
type temp_post_aggregate {
  aggregate: temp_post_aggregate_fields
  nodes: [temp_post!]!
}

"""
aggregate fields of "temp_post"
"""
type temp_post_aggregate_fields {
  avg: temp_post_avg_fields
  count(columns: [temp_post_select_column!], distinct: Boolean): Int!
  max: temp_post_max_fields
  min: temp_post_min_fields
  stddev: temp_post_stddev_fields
  stddev_pop: temp_post_stddev_pop_fields
  stddev_samp: temp_post_stddev_samp_fields
  sum: temp_post_sum_fields
  var_pop: temp_post_var_pop_fields
  var_samp: temp_post_var_samp_fields
  variance: temp_post_variance_fields
}

"""aggregate avg on columns"""
type temp_post_avg_fields {
  id: Float
}

"""
Boolean expression to filter rows from the table "temp_post". All fields are combined with a logical 'AND'.
"""
input temp_post_bool_exp {
  _and: [temp_post_bool_exp!]
  _not: temp_post_bool_exp
  _or: [temp_post_bool_exp!]
  content: String_comparison_exp
  id: Int_comparison_exp
}

"""
unique or primary key constraints on table "temp_post"
"""
enum temp_post_constraint {
  """unique or primary key constraint"""
  temp_post_pkey
}

"""
input type for incrementing numeric columns in table "temp_post"
"""
input temp_post_inc_input {
  id: Int
}

"""
input type for inserting data into table "temp_post"
"""
input temp_post_insert_input {
  content: String
  id: Int
}

"""aggregate max on columns"""
type temp_post_max_fields {
  content: String
  id: Int
}

"""aggregate min on columns"""
type temp_post_min_fields {
  content: String
  id: Int
}

"""
response of any mutation on the table "temp_post"
"""
type temp_post_mutation_response {
  """number of rows affected by the mutation"""
  affected_rows: Int!

  """data from the rows affected by the mutation"""
  returning: [temp_post!]!
}

"""
on_conflict condition type for table "temp_post"
"""
input temp_post_on_conflict {
  constraint: temp_post_constraint!
  update_columns: [temp_post_update_column!]! = []
  where: temp_post_bool_exp
}

"""Ordering options when selecting data from "temp_post"."""
input temp_post_order_by {
  content: order_by
  id: order_by
}

"""primary key columns input for table: temp_post"""
input temp_post_pk_columns_input {
  id: Int!
}

"""
select columns of table "temp_post"
"""
enum temp_post_select_column {
  """column name"""
  content

  """column name"""
  id
}

"""
input type for updating data in table "temp_post"
"""
input temp_post_set_input {
  content: String
  id: Int
}

"""aggregate stddev on columns"""
type temp_post_stddev_fields {
  id: Float
}

"""aggregate stddev_pop on columns"""
type temp_post_stddev_pop_fields {
  id: Float
}

"""aggregate stddev_samp on columns"""
type temp_post_stddev_samp_fields {
  id: Float
}

"""aggregate sum on columns"""
type temp_post_sum_fields {
  id: Int
}

"""
update columns of table "temp_post"
"""
enum temp_post_update_column {
  """column name"""
  content

  """column name"""
  id
}

"""aggregate var_pop on columns"""
type temp_post_var_pop_fields {
  id: Float
}

"""aggregate var_samp on columns"""
type temp_post_var_samp_fields {
  id: Float
}

"""aggregate variance on columns"""
type temp_post_variance_fields {
  id: Float
}

"""
columns and relationships of "user"
"""
type user {
  active: Boolean!
  auth_provider_id: String!
  email: String!
  id: uuid!
  name: String
  role: String
}

"""
aggregated selection of "user"
"""
type user_aggregate {
  aggregate: user_aggregate_fields
  nodes: [user!]!
}

"""
aggregate fields of "user"
"""
type user_aggregate_fields {
  count(columns: [user_select_column!], distinct: Boolean): Int!
  max: user_max_fields
  min: user_min_fields
}

"""
Boolean expression to filter rows from the table "user". All fields are combined with a logical 'AND'.
"""
input user_bool_exp {
  _and: [user_bool_exp!]
  _not: user_bool_exp
  _or: [user_bool_exp!]
  active: Boolean_comparison_exp
  auth_provider_id: String_comparison_exp
  email: String_comparison_exp
  id: uuid_comparison_exp
  name: String_comparison_exp
  role: String_comparison_exp
}

"""
unique or primary key constraints on table "user"
"""
enum user_constraint {
  """unique or primary key constraint"""
  user_auth_provider_id_key

  """unique or primary key constraint"""
  user_email_key

  """unique or primary key constraint"""
  user_pkey
}

"""
input type for inserting data into table "user"
"""
input user_insert_input {
  active: Boolean
  auth_provider_id: String
  email: String
  id: uuid
  name: String
  role: String
}

"""aggregate max on columns"""
type user_max_fields {
  auth_provider_id: String
  email: String
  id: uuid
  name: String
  role: String
}

"""aggregate min on columns"""
type user_min_fields {
  auth_provider_id: String
  email: String
  id: uuid
  name: String
  role: String
}

"""
response of any mutation on the table "user"
"""
type user_mutation_response {
  """number of rows affected by the mutation"""
  affected_rows: Int!

  """data from the rows affected by the mutation"""
  returning: [user!]!
}

"""
on_conflict condition type for table "user"
"""
input user_on_conflict {
  constraint: user_constraint!
  update_columns: [user_update_column!]! = []
  where: user_bool_exp
}

"""Ordering options when selecting data from "user"."""
input user_order_by {
  active: order_by
  auth_provider_id: order_by
  email: order_by
  id: order_by
  name: order_by
  role: order_by
}

"""primary key columns input for table: user"""
input user_pk_columns_input {
  id: uuid!
}

"""
select columns of table "user"
"""
enum user_select_column {
  """column name"""
  active

  """column name"""
  auth_provider_id

  """column name"""
  email

  """column name"""
  id

  """column name"""
  name

  """column name"""
  role
}

"""
input type for updating data in table "user"
"""
input user_set_input {
  active: Boolean
  auth_provider_id: String
  email: String
  id: uuid
  name: String
  role: String
}

"""
update columns of table "user"
"""
enum user_update_column {
  """column name"""
  active

  """column name"""
  auth_provider_id

  """column name"""
  email

  """column name"""
  id

  """column name"""
  name

  """column name"""
  role
}

scalar uuid

"""
Boolean expression to compare columns of type "uuid". All fields are combined with logical 'AND'.
"""
input uuid_comparison_exp {
  _eq: uuid
  _gt: uuid
  _gte: uuid
  _in: [uuid!]
  _is_null: Boolean
  _lt: uuid
  _lte: uuid
  _neq: uuid
  _nin: [uuid!]
}



Confusing behaviour ignoring types

As this tool is used for tests, it expands all of the fields in a query. There might be recursive fields in the query, so gqlg ignores the types which have been added in the parent queries already.

The current behaviour only returns the first matched query in the depth first traversal behaviour not the shallowest in the tree. Is this what the above intends?

So if you have object nesting like the following

thing {
    thing {
        thing2 {
             thing3 {
                  thing4
              }
        }
    }
    thing3 {
       thing4
    }
}

Depending on the order of your fields it will return different queries. Some with the thing.thing3.thing4 and others with it nested inside thing.thing2.thing3.thing4.

Sorry I'm new to this stuff. My terminology sucks. Hope I'm making some sense.

Keep getting error when I try to use the tool

I keep getting this error as I am trying to use the tool:

gqlg --schemaFilePath ./schema.graphql --destDirPath ./gql/outputg --depthLimit 4
/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:212
throw this.unexpected(keywordToken);
^

GraphQLError: Syntax Error: Unexpected .
at syntaxError (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/error/syntaxError.js:15:10)
at Parser.unexpected (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:1458:41)
at Parser.parseDefinition (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:212:16)
at Parser.many (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:1511:26)
at Parser.parseDocument (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:122:25)
at parse (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/language/parser.js:32:17)
at buildSchema (/usr/local/lib/node_modules/gql-generator/node_modules/graphql/utilities/buildASTSchema.js:101:38)
at main (/usr/local/lib/node_modules/gql-generator/index.js:24:21)
at Object. (/usr/local/lib/node_modules/gql-generator/index.js:265:10)
at Module._compile (node:internal/modules/cjs/loader:1218:14) {
path: undefined,
locations: [ { line: 1, column: 1 } ],
extensions: [Object: null prototype] {}
}

Duplicate identifier

When generating types from gql-generator generated gql using graphql codegen, I get the following error.

"Duplicate identifier" graphql codegen

Infinite recursiveness

Gql-generator goes into infinite recursiveness once we add just 2 lines of code to the end of example/sampleTypeDef.graphql!
CC @RvanderLaan

Steps to reproduce:

  1. Copy the code below to example/sampleTypeDef.graphql:
type Query {
    user(id: Int!): User!
    members: [Member!] @deprecated(reason: "Test a deprecated query")
}

type Mutation {
    signup(
        email: String!
        username: String!
        password: String!
    ): UserToken!

    signin(
        email: String!
        password: String!
    ): String!

    setConfig(
        prefs: PrefsInput
    ): Config!

    sendMessage(
        message: String!
    ): String! @deprecated(reason: "Test a deprecated mutation")
}

input PrefsInput {
    language: String!
}

type Config {
    language: String!
    level(domain: String!): Int!
    lastSeen(domain: String!): Int!
    theme(domain: String!): Int!
}

type Subscription {
    UserUpdated(UserId: Int!): User
}

type UserToken {
    token: String!
    user: User!
}

type User {
    id: Int!
    username: String!
    email: String!
    createdAt: String!
    context: Context!
    details: UserDetails!
    address: String! @deprecated(reason: "Test a deprecated field")
}

union UserDetails = Guest | Member | Premium

type Guest {
    region(language: String): String!
}

type Member {
    address: String!
}

type Premium {
    location: String!
    card: Card!
}

type Card {
    number: String!
    type: [CardType!]!
    owner: User! # <------------------ ADDED ---------------------
}

type CardType {
    key: String!
}

type Context {
    user: User! # Circular ref
    domain: String!
    card: Card! # <------------------ ADDED ---------------------
}
  1. Run the tests or just node index.js --schemaFilePath ./example/sampleTypeDef.graphql --destDirPath ./example/output

Cannot use unicode emojies

Hei, unicode emojies in a GraphQL schema such as 🦄 makes the following error :

GraphQLError: Syntax Error: Cannot parse the unexpected character <EOF>.

# Sample schema 🦄
type Query {
  user(id: Int!): User!
}

type User {
  id: Int!
  username: String!
  email: String!
  createdAt: String!
}

Perhaps updating the graphql dependency to its latest version could fix the issue.

Error: Type "Long" not found in document.

Error: Type "Long" not found in document.
at ASTDefinitionBuilder._resolveType (C:\Users\sunbin\AppData\Roaming\npm\node_modules\gql-generator\node_modules\graphql\utilities\buildASTSchema.js:134:11)
at ASTDefinitionBuilder.buildType (C:\Users\sunbin\AppData\Roaming\npm\node_modules\gql-generator\node_modules\graphql\utilities\buildASTSchema.js:218:79)
at ASTDefinitionBuilder._buildWrappedType (C:\Users\sunbin\AppData\Roaming\npm\node_modules\gql-generator\node_modules\graphql\utilities\buildASTSchema.js:227:24)
at ASTDefinitionBuilder.buildField (C:\Users\sunbin\AppData\Roaming\npm\node_modules\gql-generator\node_modules\graphql\utilities\buildASTSchema.js:248:18)
at C:\Users\sunbin\AppData\Roaming\npm\node_modules\gql-generator\node_modules\graphql\utilities\buildASTSchema.js:302:21
at C:\Users\sunbin\AppData\Roaming\npm\node_modules\gql-generator\node_modules\graphql\jsutils\keyValMap.js:28:31
at Array.reduce ()
at keyValMap (C:\Users\sunbin\AppData\Roaming\npm\node_modules\gql-generator\node_modules\graphql\jsutils\keyValMap.js:27:15)
at ASTDefinitionBuilder._makeFieldDefMap (C:\Users\sunbin\AppData\Roaming\npm\node_modules\gql-generator\node_modules\graphql\utilities\buildASTSchema.js:299:49)
at fields (C:\Users\sunbin\AppData\Roaming\npm\node_modules\gql-generator\node_modules\graphql\utilities\buildASTSchema.js:284:23)

how to remove or disable unneeded generated fields

FIrst of all this plugin is wonderful and just what I was looking for. But question, if I have a query like this:

query findManyAgreements($cursor: AgreementsWhereUniqueInput, $distinct: [AgreementsScalarFieldEnum!], $orderBy: [AgreementsOrderByWithRelationAndSearchRelevanceInput!], $skip: Int, $take: Int, $where: AgreementsWhereInput){
    findManyAgreements(cursor: $cursor, distinct: $distinct, orderBy: $orderBy, skip: $skip, take: $take, where: $where){
        content
        created
        excerpt
        id
        image
        mediamanager
        name
        reference_id
        shop_id
        type
        updated
        user_id
    }
}

and wanted it to be generated as this instead:

query findManyAgreements{
    findManyAgreements{
        content
        created
        excerpt
        id
        image
        mediamanager
        name
        reference_id
        shop_id
        type
        updated
        user_id
    }
}

How would I do that, even if it means to adjust the code in the plugin, just need to know where to look. Thank you in advance.

Duplicate namespace for Queries and Mutations is unusable - Append Query/Mutation to schema names

In graphql you are able to create a query and a mutation with the same namespace. When gqlg code is run, these two will names will clash upon export.

Would it be possible to append the query & file names with Query, and the mutation & file names with Mutation

type Query {
  thingById(id: ID!): Thing!
}
type Mutation {
 thingById(input: Thing!): Thing!
}

Current Result:

// in queries/thingById.gql
query thingById($id: ID!){
    thingById(id: $id){
      ....
    }
}
// in mutations/thingById.gql
mutation thingById($input: Thing!){
    thingById(input: $input){
      ....
    }
}

Expected Result:

// in queries/thingByIdQuery.gql
query thingByIdQuery($id: ID!){
    thingById(id: $id){
      ....
    }
}
// in mutations/thingByIdMutation.gql
mutation thingByIdMutation($input: Thing!){
    thingById(input: $input){
      ....
    }
}

add an option to choose file extension

According the graphql-spec, .graphql is the official extension. It would be great if we could have an option to choose our extension, with default to .gql to maintain compatibility. If it sounds good for you, I can push a PR.

ps: Thanks for the good job on this really useful plugin.

Error: Cannot delete files/folders outside the current working directory. Can be overriden with the `force` option.

Can someone show me how to run the generator from another directory using the force option like the error says.

I have a package.json and created a .js file is attempting to run it like so:

"gql-generate": "node gql-generator.js" in my package.json

this is my file:

`const gqlg = require('gql-generator')

gqlg({ schemaFilePath: '../server/generated-schema.graphql', destDirPath: '/generated/'})`

Customise query depth limit

screen shot 2018-12-17 at 9 54 00 am

The current query Depth limit is 100, it will result to huge query file, It will be good if user can customise query depth.

Expected behavior:

gqlg --schemaFilePath ./example/sampleTypeDef.graphql --destDirPath ./example/output --depthLimit 2

Some suggestions and optimization✍️

  1. Sometimes our end-coder defined some types like Long, Float and Double
    when i use gql-generator to transform above types
    image

it's always throw error said Type "Long" not found in document.
image

Can you fix it? when appeared Long, Float and Double, it can autofix to Int type

  1. Cannot parse properly when comments appear in the file.
    image

I have to delete annotation in my *.graphqls

Can you fix it?

gqlgen doesn't the newish "repeatable" token on directives like graphql-java

What happened?
gqlgen failed at this line:
directive @key(fields: _FieldSet!) repeatable on OBJECT | INTERFACE
error I got: GraphQLError: Syntax Error: Expected "on", found Name "repeatable"

What did you expect?
It should support the new 'repeatable' token

Minimal graphql.schema and models to reproduce
directive @key(fields: _FieldSet!) repeatable on OBJECT | INTERFACE

BEWARE - this tool is dangerous. It will delete your files without the possibility of recovery

Wow, I never expected a GraphQL query generator to recursively delete a whole directory of files, but it did.

Steps to reproduce:

  1. Execute this command with a valid path to the schema: gqlg --schemaFilePath /path/to/schema --destDirPath .
  2. Get an error like this:
/Users/user/.nvm/versions/node/v14.20.1/lib/node_modules/gql-generator/index.js:210
      if (err.code !== 'EEXIST') throw err;
                                 ^

Error: ENOENT: no such file or directory, mkdir 'queries'
    at Object.mkdirSync (fs.js:1014:3)
    at generateFile (/Users/user/.nvm/versions/node/v14.20.1/lib/node_modules/gql-generator/index.js:208:10)
    at main (/Users/user/.nvm/versions/node/v14.20.1/lib/node_modules/gql-generator/index.js:252:5)
    at Object.<anonymous> (/Users/user/.nvm/versions/node/v14.20.1/lib/node_modules/gql-generator/index.js:283:3)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:12)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)
    at internal/main/run_main_module.js:17:47 {
  errno: -2,
  syscall: 'mkdir',
  code: 'ENOENT',
  path: 'queries'
}
  1. Execute ls -l and your current directory will be empty, including the schema that you gave as an input!

I would like an explanation for why this happened. Thankfully, most of my work is in git, but I did have to redo a couple hours worth of updates I had made. It seems the tool does not support using the current directory as the destination directory, which is perplexing to me as a user. Please fix this bug or at least include a very strong warning in the README.

This tool generates queries with empty parentheses

I have a query that takes no arguments, it should look like this:

query me {
  me {
    // fields
  }
}

however it looks like this after processing by this lib (making it impossible to use generated documents further in codegen.yml in graphql-codegen):

query me() {
  me{
    // fields
  }
}

How to generate __typename?

Currently, my mutation is generated as:

mutation login($login: LoginInput!){
    login(login: $login){
        ... on Authorised {
            _tag
            tokens{
                accessToken
                refreshToken
                accessExpiration
            }
        }
        ... on UnAuthorised {
            _tag
        }
    }
}

I want __typename to be generated as well, like:

mutation login($login: LoginInput!){
    login(login: $login){
        __typename                      <----- THIS SHOULD BE GENERATED AS WELL
        ... on Authorised {
            _tag
            tokens{
                accessToken
                refreshToken
                accessExpiration
            }
        }
        ... on UnAuthorised {
            _tag
        }
    }
}

How can I get this?

hidden bug : query & mutation results are different from schema

first of all thank you for your great work!

I used 'gqlg' since it was v1.0.5 and every think was ok.
A couple days ago I have updated 'gqlg' to v1.0.10 and here the problem became when generating result, I noticed that queries and mutations are different from schema. However , when I downgrade gqlg to v 1.0.5 it works back as expected.

do you prefer to provide you with schema for testing ?

error: unknown option `--depthLimit'

When running the script i'm getting this error

npx gqlg --schemaFilePath apollo/directus/schema.graphql --destDirPath apollo/directus/queries-mutations_subscriptions --depthLimit 2
error: unknown option `--depthLimit'

when I last used the extension 2 months prior things worked without issues, not sure what happened.

Faulty cross reference detection

Generator skips repeating models however those aren't cross references. With "--includeCrossReferences" parameter there is no issue.

Schema:

type OrderDTO {
  payment: PaymentDTO!
  tipPayment: PaymentDTO!
}

type PaymentDTO {
  id: Float!
  user: User!
}

type User {
  id: Int!
  fcmTokens: [FCMToken!]
  invoiceAddress: UserInvoiceAddressInput
}

type FCMToken {
  token: String!
  lastSeen: String!
}

type UserInvoiceAddressInput {
  customerName: String!
  country: String!
  city: String!
  streetAddress: String!
  postalCode: String!
  taxNumber: String
  email: String
}

type Query {
  getOrder(orderId: Int!): OrderDTO!
}

Generation result:

query getOrder($orderId: Int!){
    getOrder(orderId: $orderId){
        payment{
            id
            user{
                id
                fcmTokens{
                    token
                    lastSeen
                }
                invoiceAddress{
                    customerName
                    country
                    city
                    streetAddress
                    postalCode
                    taxNumber
                    email
                }
            }
        }
        tipPayment{
            id
            user{
                id
            }
        }
    }
}

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.