Loopback-next: Exposing GraphQL APIs tutorial doesn't work

Created on 14 Nov 2018  路  21Comments  路  Source: strongloop/loopback-next

Description / Steps to reproduce / Feature proposal

Follow the steps in Exposing GraphQL APIs

Current Behavior

$ npm i --save oasgraph express express-graphql
npm WARN [email protected] requires a peer of graphql@^0.12.0 || ^0.13.0 || ^14.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.9.6 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@>=0.8.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] No license field.

+ [email protected]
+ [email protected]
+ [email protected]
added 32 packages from 28 contributors, removed 6 packages, updated 3 packages and audited 3563 packages in 5.37s
found 1 low severity vulnerability
  run `npm audit fix` to fix them, or `npm audit` for details
$ npx oasgraph http://localhost:3000/openapi.json
npx: installed 156 in 5.754s
command not found: oasgraph

Expected Behavior

Server launched and listening for input on port 3001.

Most helpful comment

Hi,
Upgraded to node 10.14.2 with npm 6.4.1.
Re-did tutorial and found that I did not install https://github.com/strongloop/oasgraph as not clear to click and install libraries from GitHub on first read.
1) I had to change node_modules/.bin/oasgraph http://localhost:3000/openapi.json to oasgraph http://localhost:3000/openapi.json

1) I think typo in Try out GraphQL...
it says

query{
   todos {
     id
     title
     desc
   }
 }
I had to change to
query{
  todos2
   {
     id,
     title,
     desc
   }
 }

All other examples worked.
Thanks,
John

All 21 comments

@rubys I think you need to install oasgraph-cli now as the CLI has been refactored into its own module.

npm i --save oasgraph-cli express express-graphql

@dhmlau Please fix the docs.

The PR (https://github.com/strongloop/loopback-next/pull/2008) that fixes this issue has merged last night. Let me get it released.

The good news is that the oasgraph server launches. The bad news is that I can't get any of the queries to work.

input:

query {
  article(id:1) {
    title
  }
}

output:

{
  "errors": [
    {
      "message": "Invalid URI \"/articles/1\"",
      "locations": [
        {
          "line": 31,
          "column": 3
        }
      ],
      "path": [
        "article"
      ]
    }
  ],
  "data": {
    "article": null
  }
}

I'm also getting a number of warnings:

{
  "warnings": [
    {
      "type": "MissingResponseSchema",
      "message": "Operation 'PATCH /articles/{id}' has no (valid) response schema.",
      "mitigation": "Ignore operation"
    },
    {
      "type": "MissingResponseSchema",
      "message": "Operation 'DELETE /articles/{id}' has no (valid) response schema.",
      "mitigation": "Ignore operation"
    },
    {
      "type": "MissingResponseSchema",
      "message": "Operation 'PATCH /comments/{id}' has no (valid) response schema.",
      "mitigation": "Ignore operation"
    },
    {
      "type": "MissingResponseSchema",
      "message": "Operation 'DELETE /comments/{id}' has no (valid) response schema.",
      "mitigation": "Ignore operation"
    },
    {
      "type": "InvalidSchemaType",
      "message": "Request / response schema has no (valid) type: {\"type\":\"object\"}",
      "mitigation": "Fall back to type 'GraphQL String'"
    },
    {
      "type": "InvalidSchemaType",
      "message": "Request / response schema has no (valid) type: {\"type\":\"object\"}",
      "mitigation": "Fall back to type 'GraphQL String'"
    },
    {
      "type": "InvalidSchemaType",
      "message": "Request / response schema has no (valid) type: {\"type\":\"object\"}",
      "mitigation": "Fall back to type 'GraphQL String'"
    },
    {
      "type": "InvalidSchemaType",
      "message": "Request / response schema has no (valid) type: {\"type\":\"object\"}",
      "mitigation": "Fall back to type 'GraphQL String'"
    },
    {
      "type": "InvalidSchemaType",
      "message": "Request / response schema has no (valid) type: {\"type\":\"object\"}",
      "mitigation": "Fall back to type 'GraphQL String'"
    },
    {
      "type": "InvalidSchemaType",
      "message": "Request / response schema has no (valid) type: {\"type\":\"object\"}",
      "mitigation": "Fall back to type 'GraphQL String'"
    },
    {
      "type": "InvalidSchemaType",
      "message": "Request / response schema has no (valid) type: {\"type\":\"object\"}",
      "mitigation": "Fall back to type 'GraphQL String'"
    },
    {
      "type": "InvalidSchemaType",
      "message": "Request / response schema has no (valid) type: {\"type\":\"object\"}",
      "mitigation": "Fall back to type 'GraphQL String'"
    }
  ],
  "numOps": 16,
  "numOpsQuery": 8,
  "numOpsMutation": 8,
  "numQueriesCreated": 8,
  "numMutationsCreated": 4
}

The good news is that the oasgraph server launches. The bad news is that I can't get any of the queries to work.

input:

query {
  article(id:1) {
    title
  }
}

output:

{
  "errors": [
    {
      "message": "Invalid URI \"/articles/1\"",
      "locations": [
        {
          "line": 31,
          "column": 3
        }
      ],
      "path": [
        "article"
      ]
    }
  ],
  "data": {
    "article": null
  }
}

Open http://localhost:3000/openapi.json. Do you have servers url set like the following? I had issue from 'lb4 example todo-list' that server url was '/' but rebuilding the example from scratch returned the openapi spec set correctly.

"servers": [
    {
      "url": "http://localhost:3000"
    }
  ],

Alternatively you can save the openapi spec alter the url and launch graphql with altered openapi spec file directly.

@dougal83 That indeed is the problem:

  "servers": [
    {
      "url": "/"
    }
  ],

I'm reopening the issue as that prevents the tutorial from working as posted.

See https://loopback.io/doc/en/lb4/Server.html#customize-how-openapi-spec-is-served. Adding the following config should work.

setServersFromRequest: true,

@rubys Which version of @loopback/cli do you use?

The latest version should generate index.js as follows:

const application = require('./dist');

module.exports = application;

if (require.main === module) {
  // Run the application
  const config = {
    rest: {
      port: +process.env.PORT || 3000,
      host: process.env.HOST || 'localhost',
      openApiSpec: {
        // useful when used with OASGraph to locate your application
        setServersFromRequest: true,
      },
    },
  };
  application.main(config).catch(err => {
    console.error('Cannot start the application.', err);
    process.exit(1);
  });
}

With setServersFromRequest: true, the openapi.json should have servers friendly to oasgraph.

@rubys Which version of @loopback/cli do you use?

That was it. I was using loopback-cli 1.0.1. Upgrading to 1.1.1 fixes this.

Closing the issue again.

Thanks!

The example is still borked if you pull via 'lb4 example todo-list'.

If so, we need to fix existing samples to add such config.

Looks like the todo-list example does not take in the config as parameter. https://github.com/strongloop/loopback-next/blob/master/examples/todo-list/index.js#L22

It should be:

application.main(config).catch(err => {
    console.error('Cannot start the application.', err);
    process.exit(1);
  });

Let me verify and submit a PR.

Following tutoral and running into problem with Exposing GraphQL API,
Opsys: win10
node: 10.2.1
npm: 5.6.1
./node_modules/.bin/oasgraph http://localhost:3000/openapi.json
./node_modules/.bin/oasgraph : The term './node_modules/.bin/oasgraph' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a
path was included, verify that the path is correct and try again.
At line:1 char:1

  • ./node_modules/.bin/oasgraph http://localhost:3000/openapi.json
  • ~~~~~~~~

    • CategoryInfo : ObjectNotFound: (./node_modules/.bin/oasgraph:String) [], CommandNotFoundException

    • FullyQualifiedErrorId : CommandNotFoundException

http://localhost:3000/openapi.json

{
openapi: "3.0.0",
info: {
title: "LoopBack Application",
version: "1.0.0"
},
paths: {
/ping: {
get: {
x-controller-name: "PingController",
x-operation-name: "ping",
tags: [
"PingController"
],
responses: {
200: {
description: "Ping Response",
content: {
application/json: {
schema: {
type: "object",
properties: {
greeting: {
type: "string"
},
date: {
type: "string"
},
url: {
type: "string"
},
headers: {
type: "object",
properties: {
Content-Type: {
type: "string"
}
},
additionalProperties: true
}
}
}
}
}
}
}
}
},
/todos/count: {
get: {
x-controller-name: "TodoController",
x-operation-name: "count",
tags: [
"TodoController"
],
responses: {
200: {
description: "Todo model count",
content: {
application/json: {
schema: {
type: "object",
properties: {
count: {
type: "number"
}
}
}
}
}
}
},
parameters: [
{
name: "where",
in: "query",
style: "deepObject",
explode: true,
schema: {
type: "object"
}
}
]
}
},
/todos/{id}: {
put: {
x-controller-name: "TodoController",
x-operation-name: "replaceById",
tags: [
"TodoController"
],
responses: {
204: {
description: "Todo PUT success"
}
},
parameters: [
{
name: "id",
in: "path",
schema: {
type: "number"
},
required: true
}
],
requestBody: {
content: {
application/json: {
schema: {
$ref: "#/components/schemas/Todo"
}
}
},
x-parameter-index: 1
}
},
patch: {
x-controller-name: "TodoController",
x-operation-name: "updateById",
tags: [
"TodoController"
],
responses: {
204: {
description: "Todo PATCH success"
}
},
parameters: [
{
name: "id",
in: "path",
schema: {
type: "number"
},
required: true
}
],
requestBody: {
content: {
application/json: {
schema: {
$ref: "#/components/schemas/Todo"
}
}
},
x-parameter-index: 1
}
},
get: {
x-controller-name: "TodoController",
x-operation-name: "findById",
tags: [
"TodoController"
],
responses: {
200: {
description: "Todo model instance",
content: {
application/json: {
schema: {
$ref: "#/components/schemas/Todo"
}
}
}
}
},
parameters: [
{
name: "id",
in: "path",
schema: {
type: "number"
},
required: true
}
]
},
delete: {
x-controller-name: "TodoController",
x-operation-name: "deleteById",
tags: [
"TodoController"
],
responses: {
204: {
description: "Todo DELETE success"
}
},
parameters: [
{
name: "id",
in: "path",
schema: {
type: "number"
},
required: true
}
]
}
},
/todos: {
post: {
x-controller-name: "TodoController",
x-operation-name: "create",
tags: [
"TodoController"
],
responses: {
200: {
description: "Todo model instance",
content: {
application/json: {
schema: {
$ref: "#/components/schemas/Todo"
}
}
}
}
},
requestBody: {
content: {
application/json: {
schema: {
$ref: "#/components/schemas/Todo"
}
}
}
}
},
patch: {
x-controller-name: "TodoController",
x-operation-name: "updateAll",
tags: [
"TodoController"
],
responses: {
200: {
description: "Todo PATCH success count",
content: {
application/json: {
schema: {
type: "object",
properties: {
count: {
type: "number"
}
}
}
}
}
}
},
parameters: [
{
name: "where",
in: "query",
style: "deepObject",
explode: true,
schema: {
type: "object"
}
}
],
requestBody: {
content: {
application/json: {
schema: {
$ref: "#/components/schemas/Todo"
}
}
}
}
},
get: {
x-controller-name: "TodoController",
x-operation-name: "find",
tags: [
"TodoController"
],
responses: {
200: {
description: "Array of Todo model instances",
content: {
application/json: {
schema: {
type: "array",
items: {
$ref: "#/components/schemas/Todo"
}
}
}
}
}
},
parameters: [
{
name: "filter",
in: "query",
style: "deepObject",
explode: true,
schema: {
properties: {
where: {
type: "object"
},
fields: {
type: "object"
},
offset: {
type: "integer",
minimum: 0
},
limit: {
type: "integer",
minimum: 0
},
skip: {
type: "integer",
minimum: 0
},
order: {
type: "array",
items: {
type: "string"
}
}
},
type: "object"
}
}
]
}
}
},
servers: [
{
url: "http://localhost:3000"
}
],
components: {
schemas: {
Todo: {
title: "Todo",
properties: {
id: {
type: "number"
},
title: {
type: "string"
},
desc: {
type: "string"
},
isComplete: {
type: "boolean"
}
},
required: [
"title"
]
}
}
}
}

@johntom

./node_modules/.bin/oasgraph : The term './node_modules/.bin/oasgraph' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a

Assuming the example is sound, worked for me a while ago. Oasgraph relies on npx to run, perhaps that is not configured correctly? Open up powershell and run 'npx' if that is not recognized then you need to set up your environment. Possibly you do not have an environment path variable to npm?

e.g.: C:\Users\\AppData\Roaming\npm

Also recommend that you use the following to manage npm on windows(if you don't already!):
https://github.com/felixrieseberg/npm-windows-upgrade

Additional info:
https://www.npmjs.com/package/npx

Hi,
Upgraded to node 10.14.2 with npm 6.4.1.
Re-did tutorial and found that I did not install https://github.com/strongloop/oasgraph as not clear to click and install libraries from GitHub on first read.
1) I had to change node_modules/.bin/oasgraph http://localhost:3000/openapi.json to oasgraph http://localhost:3000/openapi.json

1) I think typo in Try out GraphQL...
it says

query{
   todos {
     id
     title
     desc
   }
 }
I had to change to
query{
  todos2
   {
     id,
     title,
     desc
   }
 }

All other examples worked.
Thanks,
John

@johntom thank you for the feedback. Would you like to contribute the necessary documentation improvements yourself? See https://loopback.io/doc/en/contrib/doc-contrib.html to get started.

@bajtos @johntom What is the reason for todos being changed to todos2?? Is this a bug? It doesn't make sense to me as to why the 2 needs to be appended to the route name.

@chadmg I have the same issue, did you figure it out ?

@chadmg I have the same issue, did you figure it out ?

@dudipsh I've just followed the tutorial and the result is as expected (ie. todos). I'd suggest ensuring that you are fully up to date. Works with following:

  • openapi-to-graphql-cli version: 1.6.2
  • @loopback/cli version: 1.25.1

If it helps, a working example here: https://github.com/dougal83/loopback4-example-graphql

Was this page helpful?
0 / 5 - 0 ratings