cjoudrey / graphql-schema-linter

Validate GraphQL schema definitions against a set of rules
MIT License
694 stars 62 forks source link

Error when piping async output to --stdin #211

Closed arminrosu closed 4 years ago

arminrosu commented 4 years ago

Hello,

Thanks for a very useful package. I stumbled upon a weird error when piping a schema from an async node script. I suspect the issue originates with getSchemaFromFileDescriptor.

I have no prior experience with stdin, but, outside of keeping your code synchronous, is there a reason you didn't use stdin.on('data') and stdin.on('end') events to build the schema string?

To Reproduce

  1. test.js:
setTimeout(() => {
  console.log(`
type Starship {
  id: ID!
  name: String!
}

type Query {
  starship: Starship
}
  `)
}, 1000)
  1. Run node test.js | graphql-schema-linter --stdin
  2. Error:
The --stdin option was specified, but not schema was provided via stdin.
No valid schema input.

Expected behaviour

Expected it to validate the schema.

Additional context

I'm using graphql-import@beta to import multiple types from a schema generated by openapi-to-graphql. I am redeclaring some types from there, so I cannot run the linter against them, as duplicate definition errors will show up.

I think it's also a better method than requiring graphql-schema-linter to support all schema extensions (i.e. #147, #155)

graphql-import@beta became async and now my pipe to graphql-schema-linter --stdin fails.

cjoudrey commented 4 years ago

Hey @arminrosu,

Thanks for opening this issue.

I have no prior experience with stdin, but, outside of keeping your code synchronous, is there a reason you didn't use stdin.on('data') and stdin.on('end') events to build the schema string?

To be honest, I don't have any prior experience with stdin in JS. The reasoning was definitely to keep the code synchronous, but really, it doesn't necessarily have to be if we can leverage await. I didn't realize using fs.readSync on process.stdin could break in certain cases.

I'd be happy to accept a pull request that fixes this.

Thanks for the feedback!

arminrosu commented 4 years ago

@cjoudrey sure, I can have a go at it.

If I understood the code well, rules also use configuration.getSchema(). So that method needs to remain sync, so as to not break 3rd party rules.

Then I would suggest to initialize Configuration with a schema string, instead of stdinfd and schemaPaths. That would mean extracting getSchemaFromFile, getSchemaFromFileDescriptor and getSchemaSegmentsFromFiles into their own async module.

What do you think?

cjoudrey commented 4 years ago

Hey @arminrosu,

I hadn't even considered the fact that configuration.getSchema() might be used by rules, but you're absolutely right.

I don't have a lot of opinions on the implementation. What you're describing sounds good to me. 😄

dnerdy commented 4 years ago

I've run into this issue as well. It sounds like @arminrosu has a good plan. Please let me know if you need additional assistance. I'm going to put some simple retry logic in place locally until the long term solution is ready.

dnerdy commented 4 years ago

We've seen an uptick in this issue recently, so I've gone ahead and created a PR.

cjoudrey commented 4 years ago

Should be fixed in v0.2.6. Thanks again @dnerdy.