gqlify icon indicating copy to clipboard operation
gqlify copied to clipboard

TypeError: Cannot set property 'PageInfo' of undefined

Open yeuem1vannam opened this issue 6 years ago • 5 comments

Describe the bug Cannot start the server because of RelayPlugin

To Reproduce

  1. 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
  1. Create demo.graphql and index.js file follow the quick start guide
  2. Start the server by running node index.js
  3. 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

yeuem1vannam avatar Apr 02 '19 05:04 yeuem1vannam

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

yeuem1vannam avatar Apr 02 '19 05:04 yeuem1vannam

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]

aapav01 avatar Apr 03 '19 05:04 aapav01

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?

alexandrethsilva avatar Apr 10 '19 12:04 alexandrethsilva

npm i [email protected]

helped me

nezaidu avatar Apr 26 '19 15:04 nezaidu

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.

jthegedus avatar Jun 12 '19 23:06 jthegedus