TypeError: Cannot set property 'PageInfo' of undefined
Describe the bug Cannot start the server because of RelayPlugin
To Reproduce
- Create a fresh new app as the quick start
mkdir gqlify-demo
cd gqlify-demo
yarn init -y
yarn add @gqlify/server graphql apollo-server
- Create
demo.graphqlandindex.jsfile follow the quick start guide - Start the server by running
node index.js - Error occurred
Starting Gqlify...
- Gqlify Models
- Model User (generated from 'User')
Field: id `ID!`
Field: username `String!`
Field: email `String`
Field: books `[Book!]!` @relation(name: UserAndBookOnbooks)
- Model Book (generated from 'Book')
Field: id `ID!`
Field: name `String!`
Field: author `User!` @relation(name: UserAndBookOnbooks)
- Relations
Relation UserAndBookOnbooks
* Type: Bidirectional One-to-Many
* Relationship: 1-* on `User`-`Book`
/workspace/gqlify-demo/node_modules/@gqlify/server/lib/rootNode.js:247
this.defBuilder._typeDefinitionsMap[name] = typeDefNode;
^
TypeError: Cannot set property 'PageInfo' of undefined
at RootNode.buildObjectType (/workspace/gqlify-demo/node_modules/@gqlify/server/lib/rootNode.js:247:51)
at RootNode.addObjectType (/workspace/gqlify-demo/node_modules/@gqlify/server/lib/rootNode.js:93:23)
at RelayPlugin.init (/workspace/gqlify-demo/node_modules/@gqlify/server/lib/plugins/relay.js:58:14)
at /workspace/gqlify-demo/node_modules/@gqlify/server/lib/generator.js:22:24
at Array.forEach (<anonymous>)
at Generator.generate (/workspace/gqlify-demo/node_modules/@gqlify/server/lib/generator.js:17:22)
at Gqlify.createServerConfig (/workspace/gqlify-demo/node_modules/@gqlify/server/lib/gqlify.js:107:34)
at Gqlify.createApolloConfig (/workspace/gqlify-demo/node_modules/@gqlify/server/lib/gqlify.js:116:33)
at Object.<anonymous> (/workspace/gqlify-demo/index.js:33:40)
at Module._compile (module.js:653:30)
Expected behavior Server start normally
Screenshots
- package.json
{
"name": "gqlify-demo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"@gqlify/server": "^3.2.1",
"apollo-server": "^2.4.8",
"graphql": "^14.2.1"
}
}
Desktop (please complete the following information):
- OS: [e.g. iOS] Docker image
node:8 - Browser [e.g. chrome, safari]
- Version [e.g. 22] latest
Additional context
It seems related to the version of graphql library.
After remove the graphql and downgrade the @gqlify/server to v1.1.7, the application can start successfully.
However, I cannot make it works for any version higher than 1.1.7
I got the same issue
Use the Stable version v3.0.0 which was released 10 days ago it works fine
other versions are not stable...
and im using [email protected]
Unfortunately I can't yet provide any meaningful solutions as I'm still trying to get my head around how GQLify works under the hood in an attempt to find fixes for other issues, but I hope this may point someone with more knowledge of the intent and purpose of the library internals in the right direction.
There has been an update on ASTDefinitionBuilder since [email protected] and some internal fields have been removed.
IMHO using graphql-js internals (as well as any other dependencies') should be probably reconsidered as it makes such issues impossible to avoid.
i.e. this:
export class ASTDefinitionBuilder {
_typeDefinitionsMap: TypeDefinitionsMap;
_options: ?BuildSchemaOptions;
_resolveType: TypeResolver;
_cache: ObjMap<GraphQLNamedType>;
constructor(
typeDefinitionsMap: TypeDefinitionsMap,
options: ?BuildSchemaOptions,
resolveType: TypeResolver,
) {
this._typeDefinitionsMap = typeDefinitionsMap;
this._options = options;
this._resolveType = resolveType;
// Initialize to the GraphQL built in scalars and introspection types.
this._cache = keyMap(
specifiedScalarTypes.concat(introspectionTypes),
type => type.name,
);
}
...
buildType(node: NamedTypeNode | TypeDefinitionNode): GraphQLNamedType {
const typeName = node.name.value;
if (!this._cache[typeName]) {
if (node.kind === Kind.NAMED_TYPE) {
const defNode = this._typeDefinitionsMap[typeName];
this._cache[typeName] = defNode
? this._makeSchemaDef(defNode)
: this._resolveType(node.name.value);
} else {
this._cache[typeName] = this._makeSchemaDef(node);
}
}
return this._cache[typeName];
}
became this:
export class ASTDefinitionBuilder {
_options: ?BuildSchemaOptions;
_resolveType: TypeResolver;
constructor(options: ?BuildSchemaOptions, resolveType: TypeResolver) {
this._options = options;
this._resolveType = resolveType;
}
...
buildType(astNode: TypeDefinitionNode): GraphQLNamedType {
const name = astNode.name.value;
if (stdTypeMap[name]) {
return stdTypeMap[name];
}
switch (astNode.kind) {
case Kind.OBJECT_TYPE_DEFINITION:
return this._makeTypeDef(astNode);
case Kind.INTERFACE_TYPE_DEFINITION:
return this._makeInterfaceDef(astNode);
case Kind.ENUM_TYPE_DEFINITION:
return this._makeEnumDef(astNode);
case Kind.UNION_TYPE_DEFINITION:
return this._makeUnionDef(astNode);
case Kind.SCALAR_TYPE_DEFINITION:
return this._makeScalarDef(astNode);
case Kind.INPUT_OBJECT_TYPE_DEFINITION:
return this._makeInputObjectDef(astNode);
}
// Not reachable. All possible type definition nodes have been considered.
/* istanbul ignore next */
throw new Error(
`Unexpected type definition node: "${inspect((astNode: empty))}".`,
);
}
...
My guess while having a first look is that this technique was being used to add the schema Types to this internal _typeDefinitionsMap of allowed definitions to be validated, but [email protected] uses a hard-coded list, coming from this file, so... no dice.
export const specifiedScalarTypes: $ReadOnlyArray<*> = [
GraphQLString,
GraphQLInt,
GraphQLFloat,
GraphQLBoolean,
GraphQLID,
];
This is the method that checks against it:
const stdTypeMap = keyMap(
specifiedScalarTypes.concat(introspectionTypes),
type => type.name,
);
@wwwy3y3 Does any of what I'm saying here make sense to you?
Can confirm [email protected] does not work with @gqlify/[email protected] (both lastest at the time of writing). As @nezaidu said, installing [email protected] seems to resolve the issue at this time.