dangcuuson / graphql-schema-typescript Goto Github PK
View Code? Open in Web Editor NEWGenerate TypeScript from GraphQL's schema type definitions
Generate TypeScript from GraphQL's schema type definitions
Hi,
I am trying out the push the types in resolvers to the limit with new options :-).
In my use case TParent is usually needed to retype to the model types (as often some additional fields that are not exposed via graphql are being used), but that still looks very good as it can be nicely defined per graphql type, like this :
type Study {
_id: ObjectId!
ready: Bool!
studyDescription: StudyDescription!
referringPhysicians: [ReferringPhysician]!
}
const studyResolvers: GQLStudyTypeResolver<MStudy> = {
referringPhysicians(study, {}, ctx) {
return loadReferringPhysicianByIds(ctx, study.referringPhysicianIds);
},
studyDescription(study, {}, ctx) {
if (!study.studyDescriptionId) {
return null;
}
return loadStudyDescriptionById(ctx, study.studyDescriptionId);
},
};
But thinking about following improvement that I believe could make the result type significantly more useful, don't know how difficult be to add that in.
In this example smartTResult type requires that resolver which is returning GQLStudy would have return all fields (_id, read, studyDescription and referringPhysicians), but in fact since Study type has own resolvers for referringPhysicians
and studyDescription
ideally it should not require these fields (make them optional) when resolving Study type and require only _id
and ready
.
That would require to not just look at what type is being returned, but also look into the resolvers if there are some field resolvers.
What do you think, does it make sense?
Getting this error GraphQLError: Syntax Error GraphQL request (1:1) Unexpected
Hi! I'm trying to convert Gitlab graphql schema using this CLI.
Here is the output:
npx graphql-schema-typescript generate-ts .
Message: null
Error: Error: Unknown type "ID".
[](url)
Unknown type "ID".
There can be only one type named "Date".
There can be only one type named "User".
Field "User.email" can only be defined once.
Field "User.username" can only be defined once.
Could you please have a look at this file and to tell what's wrong with it? OR may be there is an error in the parser.
Firstly, thanks for this tool. It's been really great to have my resolvers strongly typed with minimal effort. I've recently been trying out a new modular pattern which has led me to a problem.
When I use extend
to break up my type definitions I don't see the extended values in the type.
Prior to splitting the modules out I have a TypeScript type that accurately describes the resolvers for Query.
type Dog {
imageUrl: String!
}
type Query {
dogs(limit: Int): [Dog!]
}
export interface GQLQueryTypeResolver<TParent = undefined> {
dogs?: QueryToDogsResolver<TParent>;
}
But as I want to add more to the schema I look to add something like:
type Cat {
imageUrl: String!
}
type Query {
cats(breed: String!, limit: Int): [Cat!]
}
Which of-course isn't valid, as I've now defined Query twice.
To keep the code nice and clean I give the Query a base definition, and use extend
in the seperate modules:
type Query {
_empty: String
}
extend type Query {...
However, now the Query definition shows only _empty
and not the extended values:
export interface GQLQueryTypeResolver<TParent = undefined> {
_empty?: QueryTo_emptyResolver<TParent>;
}
Ideally I want to see something like below. Is this possible? If not is there a reason the extended types shouldn't be concatenated together?
If it's not currently possible, and it's not a terrible idea would you be open to a PR?
export interface GQLQueryTypeResolver<TParent = undefined> {
_empty?: QueryTo_emptyResolver<TParent>;
cats?: QueryToCatsResolver<TParent>;
dogs?: QueryToDogsResolver<TParent>;
}
When trying to generate typescript code from an invalid graphql file:
$ graphql-schema-typescript generate-ts generate-ts src/chema.graphql
Message: null
Error: { GraphQLError: Syntax Error: Cannot parse the unexpected character "/".
at syntaxError (/Users/ldiqual/Siteline/siteline/node_modules/graphql/error/syntaxError.js:15:10)
at readToken (/Users/ldiqual/Siteline/siteline/node_modules/graphql/language/lexer.js:270:38)
at Object.lookahead (/Users/ldiqual/Siteline/siteline/node_modules/graphql/language/lexer.js:54:43)
at Object.advanceLexer [as advance] (/Users/ldiqual/Siteline/siteline/node_modules/graphql/language/lexer.js:44:33)
at Parser.expectToken (/Users/ldiqual/Siteline/siteline/node_modules/graphql/language/parser.js:1398:19)
at Parser.many (/Users/ldiqual/Siteline/siteline/node_modules/graphql/language/parser.js:1514:10)
at Parser.parseDocument (/Users/ldiqual/Siteline/siteline/node_modules/graphql/language/parser.js:111:25)
at parse (/Users/ldiqual/Siteline/siteline/node_modules/graphql/language/parser.js:36:17)
at Object.buildSchema (/Users/ldiqual/Siteline/siteline/node_modules/graphql/utilities/buildASTSchema.js:462:43)
at Object.<anonymous> (/Users/ldiqual/Siteline/siteline/node_modules/graphql-schema-typescript/lib/index.js:98:42)
message: 'Syntax Error: Cannot parse the unexpected character "/".',
locations: [ { line: 1, column: 1 } ] }
What happens is that https://github.com/dangcuuson/graphql-schema-typescript/blob/master/src/index.ts#L53 parses the schema file from a path, and it throws because there's a syntax error, but then the error is silenced and the code tries to parse the actual path string, which results in the error above.
Right now its only support input as GraphQLSchema or path of schema but in some cases like where we using graphql-import
then in this case it throws an error. It should be nice to have an option to pass schema as string.
For example :
const { generateTypeScriptTypes } = require("graphql-schema-typescript"); generateTypeScriptTypes("type Query{ hello: string }", path);
I'm using TypeORM and in my entities, I got properties which are defined as property?: string | null
so its type is string | null | undefined
. This creates conflicts with the types I get from the generated types of nullable properties from my graphql schema.
Maybe we can add an option to define nullable properties to property?: string | null
instead of the normal property?: string
.
I love this tool! ๐ It was exactly what I looked for. Thanks so much!
It would be cool though with an option (or even as a default) to have a timestamp added to the top of the generated types .ts
file, in order to quickly diff the version at a glance.
Something like:
import { GraphQLResolveInfo } from 'graphql';
/**
* This file is auto-generated by graphql-schema-typescript
* Please note that any changes in this file may be overwritten
*
* Generated at 2018-07-20T23:01:01
*/
/* tslint:disable */
/*******************************
*
* TYPE DEFS
*
*******************************/
Let me know if I can provide a PR for this.
I'm following the graphql-schema-typescript generate-ts --help
. It says
graphql-schema-typescript generate-ts <folderPath>
But CLI doesn't take the folderName argument.
$ npx graphql-schema-typescript generate-ts graphql
Message: null
Error: GraphQLError: Syntax Error: Unexpected Name "gql"
I tried ./graphql
or full-path, but nothing changes.
yarn audit
shows a low vulnerability in a dependency: https://www.npmjs.com/advisories/1500
path: graphql-schema-typescript > yargs > yargs-parser
From https://graphql.org/graphql-js/:
// Run the GraphQL query '{ hello }' and print out the response
graphql(schema, '{ hello }', root).then((response) => {
console.log(response);
});
In src/utils/:
await graphql({ schema: schema, source: introspectionQuery });
I recently heard about graphql-code-generator through @c0m1t
https://github.com/dotansimha/graphql-code-generator
https://graphql-code-generator.com/
What is the difference between this package (graphql-schema-typescript) and that (graphql-code-generator)?
Any idea how I could use the generated types of schema to generate types for query results?
Something akin to what https://github.com/apollographql/apollo-tooling does but to do it dynamically. I would be willing to work on this if you could point in me the right direction.
This tool looks incredibly helpful, however I'm running into a blocker thats stopping me being able to use unfortunately.
My Schema is distributed using Apollo's Managed Federation, which essentially means the schema may or may not have some types explicitly defined. For example I may have a schema like:
extend type User @key(fields: "id") {
id: ID! @external
}
type Product {
id: ID!
name: String!
created_by: User!
}
In this case, User
is stubbed out and resolved by a different service, and when attempting to generate types, I get the following
Error: Unknown type "User".
Cannot extend type "Mutation" because it is not defined.
Cannot extend type "Query" because it is not defined.
Cannot extend type "User" because it is not defined.
I think a resolution to this would be to essentially not require a "base" definition of a type (User
in this case). Though of course this would affect non-federated schema's, so making it a config option would be needed.
The other issue that arises is the directives used (key
& external
in this example), as these aren't defined either by each service.
Apollo's schema for directives is the following:
scalar _Any
scalar _FieldSet
# a union of all types that use the @key directive
union _Entity
type _Service {
sdl: String
}
extend type Query {
_entities(representations: [_Any!]!): [_Entity]!
_service: _Service!
}
directive @external on FIELD_DEFINITION
directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
directive @key(fields: _FieldSet!) on OBJECT | INTERFACE
# this is an optional directive discussed below
directive @extends on OBJECT | INTERFACE
Currently I am just prepending this to my schema at the time of generation, but it would be nice if the federation config option prepended this itself perhaps
https://github.com/liyikun/vscode-graphql-schema-typescript
Simple Generate a typescript interface based on your graphql type
Thank you for the project!
In terms of keeping this package up to date, Are you open to sharing NPM and repo to more maintainers to make it easier to catch up graphql releases and maintain? What do you think? Are you open to making an organization?
If so I'm interested (and maybe others). I am currently publishing to an a forked organizational package in the mean time.
Please look into supporting more recent versions of graphql
. For example, it wouldn't work with version 14.0.0
and above in the path, and I spent a couple hours diagnosing this and #45. Thanks.
First of all, thank you for this awesome library! It has been so much easier to get up and running with TypeScript and GraphQL.
I have in a situation, where I need to resolve a union type property in my schema:
type UnitEvent {
id: String!
details: UnitEventDetails
}
union UnitEventDetails = DamageReportEvent | CanErrorEvent
type DamageReportEvent {
damageReportId: String
}
type CanErrorEvent {
canErrorId: String
}
In my 'UnitEventResolver` I have the following:
const unitEventResolver: GQLUnitEventTypeResolver<IUnitEventApiResponse> = {
id: parent => {
return parent.eventId;
},
details: parent => {
return parent;
}
};
export default unitEventResolver;
Then in my UnitEventDetailsResolver
I have:
const unitEventDetailsResolver: GQLUnitEventDetailsTypeResolver = (
parent: IUnitEventApiResponse
) => {
switch (parent.type) {
case 1:
return "DamageReportEvent";
case 7:
return "CanErrorEvent";
}
};
export default unitEventDetailsResolver;
And finally in my CanErrorEventResolver
:
const canErrorEventResolver: GQLCanErrorEventTypeResolver<
IUnitEventApiResponse
> = {
canErrorId: parent => {
return parent.data.canErrorId;
}
};
export default canErrorEventResolver;
However, I am getting this message:
"message": "Abstract type UnitEventDetails must resolve to an Object type at runtime for field UnitEvent.details with value { [REDACTED], type: 7, [REDACTED] }, received "undefined". Either the UnitEventDetails type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function."
I am also getting this in the console:
Type "UnitEventDetails" is missing a "__resolveType" resolver. Pass false into "resolverValidationOptions.requireResolversForResolveType" to disable this warning.
I have tried messing around with the types, but unable to make it work?
Can you point me in a direction to solve this?
Thanks!
Hi, this is great project, exactly what I was looking for!
As you say in readme, resolver result is any at this moment and can be explicitly defined in resolvers. I am wondering what was the reason to leave results as any? Are you considering to have option that would also type the results of resolvers?
Using a const enum
gives you the possibility to set
"compilerOptions": {
"preserveConstEnums": true
}
in the tsconfig.json
which will inline used enum values. Otherwise you'll get a runtime error because the enum is not available.
I'm trying to generate my types with yarn graphql-schema-typescript generate-ts graphql
and getting this error:
Message: null
Error: GraphQLError [Object]: Syntax Error: Unexpected Name "graphql".
at syntaxError (/Users/sam/vytal/partner_app/node_modules/graphql/error/syntaxError.js:15:10)
at Parser.unexpected (/Users/sam/vytal/partner_app/node_modules/graphql/language/parser.js:1482:41)
at Parser.parseDefinition (/Users/sam/vytal/partner_app/node_modules/graphql/language/parser.js:155:16)
at Parser.many (/Users/sam/vytal/partner_app/node_modules/graphql/language/parser.js:1537:26)
at Parser.parseDocument (/Users/sam/vytal/partner_app/node_modules/graphql/language/parser.js:109:25)
at parse (/Users/sam/vytal/partner_app/node_modules/graphql/language/parser.js:36:17)
at Object.buildSchema (/Users/sam/vytal/partner_app/node_modules/graphql/utilities/buildASTSchema.js:116:36)
at Object.<anonymous> (/Users/sam/vytal/partner_app/node_modules/graphql-schema-typescript/lib/index.js:94:42)
at step (/Users/sam/vytal/partner_app/node_modules/graphql-schema-typescript/lib/index.js:40:23)
at Object.throw (/Users/sam/vytal/partner_app/node_modules/graphql-schema-typescript/lib/index.js:21:53) {
locations: [ { line: 1, column: 1 } ]
}
My gql config is located in graphql/graphql.config
My project is using graphql: 15.3.0
, node: 14.12.0
I have a very similar setup in another project that uses graphql: 14.7.0
, and there everything works fine. When I use 14.7.0
in this project, ts type generation also works fine. So there must be some breaking changes in 14->15 that graphql-schema-typescript is not handling yet.
Any idea how to fix this without reverting my entire project back to graphql 14?
GraphQL enum naming convention specifies using ALL_CAPS_WITH_UNDERSCORES (https://graphql.github.io/graphql-spec/draft/#sec-Enum-Value) while Typescript convention is to use PascalCase (https://basarat.gitbooks.io/typescript/docs/styleguide/styleguide.html).
It would be nice with an option to force PascalCase for enum values.
When I set asyncResult
option to true
, the return type of the resolvers are set to TResult | Promise<TResult>
as indicated in the docs, but when I use Ctrl + Space
to see suggestions in my resolver returns, it does not give me field suggestions for the TResult. However, when I change all of the resolver return types from TResult | Promise<TResult>
to Promise<TResult>
, I am already able to see field suggestions. Can we add an option to set resolver return types to Promise<TResult>
only? Will it produce undesired side effects?
I'm not sure if it's because of my typescript configuration or not, and I'm still new in Typescript.
I'm using VS Code as my editor.
When running graphql-schema-typescript generate-ts ./src/datamodel/testSchema.graphql --output ./src/datamodel/testSchema.d.ts
from my package.json script:
"generate:schema": "graphql-schema-typescript generate-ts ./src/datamodel/testSchema.graphql --output ./src/datamodel/testSchema.d.ts"
I get the following error:
$ graphql-schema-typescript generate-ts ./src/datamodel/testSchema.graphql --output ./src/datamodel/testSchema.d.ts
Message: null
Error: GraphQLError: Syntax Error: Cannot parse the unexpected character ".".
at syntaxError (/root/ziina/monorepo/graphqlserver/node_modules/graphql/error/syntaxError.js:15:10)
at readToken (/root/ziina/monorepo/graphqlserver/node_modules/graphql/language/lexer.js:270:38)
at Object.lookahead (/root/ziina/monorepo/graphqlserver/node_modules/graphql/language/lexer.js:54:43)
at Object.advanceLexer [as advance] (/root/ziina/monorepo/graphqlserver/node_modules/graphql/language/lexer.js:44:33)
at Parser.expectToken (/root/ziina/monorepo/graphqlserver/node_modules/graphql/language/parser.js:1399:19)
at Parser.many (/root/ziina/monorepo/graphqlserver/node_modules/graphql/language/parser.js:1514:10)
at Parser.parseDocument (/root/ziina/monorepo/graphqlserver/node_modules/graphql/language/parser.js:111:25)
at parse (/root/ziina/monorepo/graphqlserver/node_modules/graphql/language/parser.js:36:17)
at Object.buildSchema (/root/ziina/monorepo/graphqlserver/node_modules/graphql/utilities/buildASTSchema.js:462:43)
at Object.<anonymous> (/root/ziina/monorepo/graphqlserver/node_modules/graphql-schema-typescript/lib/index.js:94:42) {
message: 'Syntax Error: Cannot parse the unexpected character ".".',
locations: [ { line: 1, column: 1 } ]
}
error Command failed with exit code 1.
I've tried with escaping double quotes, single quotes, etc.
I've also tried to use the testSchema.graphql
from the __tests__
to no avail.
Seems like a parse issue with the directory paths?
As title, graphql@15
was in devDependencies
but graphql@14
in peerDependencies
, it makes npm install fails with ERESOLVE unable to resolve dependency tree
error.
How is this library supposed to behave when there are no in possibleTypes, e.g. on an interface that extends nothing?
File detail.graphql
schema {
query: Query
}
type Query {
getDetail: Detail
}
interface Detail {
name: String!
value: Float
}
File output.d.ts
// lots of lines omitted...
export interface DetailTypeResolver<TParent = any> {
(parent: TParent, context: any, info: GraphQLResolveInfo): | Promise<>; // <--- notice empty return type and no Promise return type
}
Debugger after evaluating const introspectResult = await getIntrospectResult();
here shows no possibleTypes (empty array):
My question is what is the intended output or if this is a bug, what is the expected output?
Hi, first thanks for your work! It's really useful.
I was developing a class implementing the QueryResolvers interface, but one of the things I wanted was to make sure that all resolvers are implemented, to make sure that if some mutation/query is added, the corresponding resolver is there. Does it makes sense?
class MyResolvers implements QueryResolvers.Resolvers {
//no error because the resolvers are optional
}
export namespace QueryResolvers {
export interface Resolvers {
getSomething?: getSomethingResolver;
}
}
Hopefully it makes sense and it's easy to implement :)
Thanks again!
./node_modules/.bin/graphql-schema-typescript generate-ts --help
env: node\r: No such file or directory
node is installed ofc. Issue with line endings?
Hi,
I have defined a Schema with union. However the resolved is throwing the following run time error:
I have attached the schema.js and index.js text. Please help me in rectifying the resolver of the union type.
import { buildSchema } from 'graphql';
const schema = buildSchema(`
union AgendaItem = StudyGroup | Workout
type StudyGroup {
name: String!
}
type Workout {
subject: String
}
type Query {
agenda: [AgendaItem!]
}
import express from 'express';
import graphqlHTTP from 'express-graphql';
import schema from './schema';
const app = express();
app.get('/', (req,res) => {
res.send('Graph QL is amazing!');
});
// Custom Functions
function responseToQuery(obj){
return [
{"name": "Rudra"},
{"name": "Ram"}
]
}
const root = { agenda: (obj) => responseToQuery(obj) };
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(9090, () => console.log('Running server on port localhost:9090/graphql'));
"errors": [
{
"message": "Abstract type AgendaItem must resolve to an Object type at runtime for field Query.agenda with value { name: "Rudra" }, received "undefined". Either the AgendaItem type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.",
Hi,
I using grahpQL Modules and all my schema.graphql are separeted in modules.
My problem is:
I have one type in one module, after this, i declare this type again injecting other property.
But when i generat the interfase only the last type is considered.
Example
In Doctor Module:
type Doctor {
id: ID!
name: String!
birth: String
}
In Specialty Module:
type Doctor {
specialties: [Specialty]
}
Bu when i generate interfaces:
export interface GQLDoctor {
specialties?: Array<GQLSpecialty | null>;
}
I use this function to merge schemas:
const genSchema = async () => {
const schemas: GraphQLSchema[] = [];
const folders = readdirSync(join(__dirname, "../modules")).filter(f => !f.includes("."));
folders.forEach(folder => {
const typeDefs = importSchema(join(__dirname, ../modules/${folder}/schema.graphql`));
schemas.push(makeExecutableSchema({ typeDefs }));
});
await generateTypeScriptTypes(
mergeSchemas({ schemas }),
join(__dirname, "../types/schemas.d.ts")
);
};
Hello, seems that library is incompatible with graphql-js 6
node node_modules/.bin/graphql-schema-typescript generate-ts schema.graphql --output app/javascript/graphqlSchema.ts
Message: null
Error: Error: Expected undefined to be a GraphQL schema.
at assertSchema (.../node_modules/graphql/type/schema.js:35:11)
at validateSchema (.../node_modules/graphql/type/validate.js:34:28)
at graphqlImpl (.../node_modules/graphql/graphql.js:52:64)
at .../node_modules/graphql/graphql.js:21:43
at new Promise (<anonymous>)
at Object.graphql (.../node_modules/graphql/graphql.js:21:10)
at .../node_modules/graphql-schema-typescript/lib/utils.js:58:52
at step (.../node_modules/graphql-schema-typescript/lib/utils.js:33:23)
at Object.next (.../wasteapp/node_modules/graphql-schema-typescript/lib/utils.js:14:53)
at .../node_modules/graphql-schema-typescript/lib/utils.js:8:71
GraphQL allows enum with allow values in resolvers
https://www.apollographql.com/docs/apollo-server/schema/schema/#internal-values-advanced
but this is generating always the enum's literal string value, is there anyway can support given values?
https://blog.logrocket.com/what-you-need-to-know-about-graphql-enums/
to make GraphQL
enum AuthType {
GOOGLE = 'google-auth',
GITHUB = 'github-auth',
OUTLOOK = 'outlook-auth',
}
to generate TypeScript
export const enum AuthType {
GOOGLE = 'google-auth',
GITHUB = 'github-auth',
OUTLOOK = 'outlook-auth',
}
This package requires [email protected]
, lodash
, and typescript
as dependencies to be used. Please move them out of devDependencies
.
When generating d.ts file with --namespace option, a declare
modifier is required.
declare namespace user {
// ....
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.