I'm currently learning AWS Lambda, and I'm trying to deploy a Lambda function whose inputs would be stored in a DynamoDB table(if that makes sense?), we were already given a source code to use and a separate code to test it.
I've checked both codes, refactored them, and started testing but somehow my results still return "failed" results. My code source is this:
const randomBytes = require('crypto').randomBytes;
const AWS = require('aws-sdk');
const ddb = new AWS.DynamoDB.DocumentClient();
const fleet = [
{
Name: 'Bucephalus',
Color: 'Golden',
Gender: 'Male',
},
{
Name: 'Shadowfax',
Color: 'White',
Gender: 'Male',
},
{
Name: 'Rocinante',
Color: 'Yellow',
Gender: 'Female',
},
];
exports.handler = (event, context, callback) => {
if (!event.requestContext.authorizer) {
errorResponse('Authorization not configured', context.awsRequestId, callback);
return;
}
const rideId = toUrlString(randomBytes(16));
console.log('Received event (', rideId, '): ', event);
// Because we're using a Cognito User Pools authorizer, all of the claims
// included in the authentication token are provided in the request context.
// This includes the username as well as other attributes.
const username = event.requestContext.authorizer.claims['cognito:username'];
// The body field of the event in a proxy integration is a raw string.
// In order to extract meaningful values, we need to first parse this string
// into an object. A more robust implementation might inspect the Content-Type
// header first and use a different parsing strategy based on that value.
const requestBody = JSON.parse(event.body);
const pickupLocation = requestBody.PickupLocation;
const unicorn = findUnicorn(pickupLocation);
recordRide(rideId, username, unicorn).then(() => {
// You can use the callback function to provide a return value from your Node.js
// Lambda functions. The first parameter is used for failed invocations. The
// second parameter specifies the result data of the invocation.
// Because this Lambda function is called by an API Gateway proxy integration
// the result object must use the following structure.
callback(null, {
statusCode: 201,
body: JSON.stringify({
RideId: rideId,
Unicorn: unicorn,
UnicornName: unicorn.Name,
Eta: '30 seconds',
Rider: username,
}),
headers: {
'Access-Control-Allow-Origin': '*',
},
});
}).catch((err) => {
console.error(err);
// If there is an error during processing, catch it and return
// from the Lambda function successfully. Specify a 500 HTTP status
// code and provide an error message in the body. This will provide a
// more meaningful error response to the end client.
errorResponse(err.message, context.awsRequestId, callback);
});
};
function findUnicorn(pickupLocation) {
console.log('Finding unicorn for ', pickupLocation.Latitude, ', ', pickupLocation.Longitude);
return fleet[Math.floor(Math.random() * fleet.length)];
}
function recordRide(rideId, username, unicorn) {
return ddb.put({
TableName: 'AWSIES-jeremie.agravante',
Item: {
RideId: rideId,
User: username,
Unicorn: unicorn,
UnicornName: unicorn.Name,
RequestTime: new Date().toISOString(),
},
}).promise();
}
function toUrlString(buffer) {
return buffer.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
function errorResponse(errorMessage, awsRequestId, callback) {
callback(null, {
statusCode: 500,
body: JSON.stringify({
Error: errorMessage,
Reference: awsRequestId,
}),
headers: {
'Access-Control-Allow-Origin': '*',
}
});
}
And the test code is this:
{
"path": "/ride",
"httpMethod ": "POST",
"headers": {
"Accept": "*/*",
"Authorization": "eyJraWQiOiJLTzRVMWZs",
"content-type": "application/json; charset=UTF 8"
},
"queryStringParameters ":"null",
"pathParameters ":"null",
"requestContext ": {
"authorizer": {
"claims": {
"cognito:username ": "the_username"
}
}
},
"body": "{\"PickupLocation \":
{\"Latitude\":47.6174755835663,\"Longitude\":-122.28837066650185}}"
}
The error that it throws me is this:
Test Event Name:testRequestEvent
Response
{
"errorType": "Runtime.UserCodeSyntaxError",
"errorMessage": "SyntaxError: Unexpected end of input",
"trace": [
"Runtime.UserCodeSyntaxError: SyntaxError: Unexpected end of input",
" at _loadUserApp (/var/runtime/UserFunction.js:98:13)",
" at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
" at Object.<anonymous> (/var/runtime/index.js:43:30)",
" at Module._compile (internal/modules/cjs/loader.js:1072:14)",
" at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)",
" at Module.load (internal/modules/cjs/loader.js:937:32)",
" at Function.Module._load (internal/modules/cjs/loader.js:778:12)",
" at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)",
" at internal/main/run_main_module.js:17:47"
]
}
Function Logs
START RequestId: 2f5c85af-632f-4fa2-8a32-46547e84fe64 Version: $LATEST
2021-11-18T01:39:55.279Z undefined ERROR Uncaught Exception
{"errorType":"Runtime.UserCodeSyntaxError","errorMessage":"SyntaxError: Unexpected end of
input","stack":["Runtime.UserCodeSyntaxError: SyntaxError: Unexpected end of input"," at
_loadUserApp (/var/runtime/UserFunction.js:98:13)"," at Object.module.exports.load
(/var/runtime/UserFunction.js:140:17)"," at Object.<anonymous>
(/var/runtime/index.js:43:30)"," at Module._compile
(internal/modules/cjs/loader.js:1072:14)"," at Object.Module._extensions..js
(internal/modules/cjs/loader.js:1101:10)"," at Module.load
(internal/modules/cjs/loader.js:937:32)"," at Function.Module._load
(internal/modules/cjs/loader.js:778:12)"," at Function.executeUserEntryPoint [as runMain]
(internal/modules/run_main.js:76:12)"," at internal/main/run_main_module.js:17:47"]}
2021-11-18T01:39:56.826Z undefined ERROR Uncaught Exception
{"errorType":"Runtime.UserCodeSyntaxError","errorMessage":"SyntaxError: Unexpected end of input","stack":["Runtime.UserCodeSyntaxError: SyntaxError: Unexpected end of input"," at _loadUserApp (/var/runtime/UserFunction.js:98:13)"," at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)"," at Object.<anonymous> (/var/runtime/index.js:43:30)"," at Module._compile (internal/modules/cjs/loader.js:1072:14)"," at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)"," at Module.load (internal/modules/cjs/loader.js:937:32)"," at Function.Module._load (internal/modules/cjs/loader.js:778:12)"," at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)"," at internal/main/run_main_module.js:17:47"]}
END RequestId: 2f5c85af-632f-4fa2-8a32-46547e84fe64
REPORT RequestId: 2f5c85af-632f-4fa2-8a32-46547e84fe64 Duration: 1714.81 ms Billed
Duration: 1715 ms Memory Size: 128 MB Max Memory Used: 12 MB
Unknown application error occurred
Runtime.UserCodeSyntaxError
Request ID
2f5c85af-632f-4fa2-8a32-46547e84fe64
I'm sorry if this is really long, but I could really use a hand in this one. I keep looking for syntax errors even found some bugs that my instructors have purposely snuck in to test us, but I guess my beginner skills are not enough at the moment. Thanks to anyone who could help.
Related
We've created a Custom Botbuilder Adapter to connect to the Vonage API called botbuilder-adapter-vonage-js. To test the Adapter's basic functionality, with a basic bot reply, we send an SMS to the Vonage number and should get an SMS reply back "Hello Back", but instead receive the error below:
[onTurnError] unhandled error: TypeError: bot.reply is not a function
Not sure how to actually debug the Custom Adapter to find where it is broken.
Would be great to find someone familiar with either the Botkit Core library and Botkit Platform Adapters could help with this. I've attached the Express Server (webhook-server.js) below.
// webhook-server.js
require('dotenv').config();
const express = require('express');
const app = express();
const port = 3000;
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const SendMessagesAPI = require('./Vonage-SEND-messages-api');
const VonageAdapter = require('botbuilder-adapter-vonage-js');
const Botkit = require('botkit');
const {
BotFrameworkAdapter,
InspectionMiddleware,
MemoryStorage,
InspectionState,
UserState,
ConversationState,
} = require('botbuilder');
const { MicrosoftAppCredentials } = require('botframework-connector');
// This bot's main dialog.
const { IntersectionBot } = require('./bot');
const { Message } = require('#vonage/server-sdk');
const creds = {
apiKey: process.env.VONAGE_API_KEY,
apiSecret: process.env.VONAGE_API_SECRET,
applicationId: process.env.VONAGE_APPLICATION_ID,
privateKey: process.env.VONAGE_APPLICATION_PRIVATE_KEY_PATH,
};
const config = {
to_number: process.env.TO_NUMBER,
from_number: process.env.FROM_NUMBER,
// enable_incomplete: true
};
// Create Adapter
const adapter = new VonageAdapter(creds, config);
// Create the Storage provider and the various types of BotState.
const memoryStorage = new MemoryStorage();
const inspectionState = new InspectionState(memoryStorage);
const userState = new UserState(memoryStorage);
const conversationState = new ConversationState(memoryStorage);
// Create and add the InspectionMiddleware to the adapter.
adapter.use(
new InspectionMiddleware(
inspectionState,
userState,
conversationState,
new MicrosoftAppCredentials(
process.env.MicrosoftAppId,
process.env.MicrosoftAppPassword
)
)
);
app.post('/webhooks/dlr', (req, res) => {
res.status(200).end();
});
// Catch-all for errors.
adapter.onTurnError = async (, error) => {
// This check writes out errors to console log .vs. app insights.
// NOTE: In production environment, you should consider logging this to Azure
// application insights. See https://aka.ms/bottelemetry for telemetry
// configuration instructions.
console.error(`\n [onTurnError] unhandled error: ${error}`);
// Send a trace activity, which will be displayed in Bot Framework Emulator
await .sendTraceActivity(
'OnTurnError Trace',
`${error}`,
'https://www.botframework.com/schemas/error',
'TurnError'
);
// Send a message to the user
await .sendActivity('The bot encountered an error or bug.');
await .sendActivity(
'To continue to run this bot, please fix the bot source code.'
);
// Clear out state
await conversationState.clear();
};
// Create the main dialog.
const bot = new IntersectionBot(conversationState, userState);
// Listen for incoming requests.
app.post('/webhooks/inbound', (req, res) => {
console.log('/webhooks/inbound req.body', req.body);
adapter.processActivity(req, res, async () => {
console.log(context);
// [onTurnError] unhandled error: TypeError: Cannot read property 'from' of undefined
// await bot.run();
// [onTurnError] unhandled error: TypeError: .reply is not a function
// await .reply('I heard a message!');
// [onTurnError] unhandled error: TypeError: bot.reply is not a function
await bot.reply('Hello Back!');
});
res.status(200).end();
});
app.post('/webhooks/status', (req, res) => {
res.status(200).end();
});
app.listen(port, () => {
console.log(`🌏 Server running at http://localhost:${port}`);
});
Response
🌏 Server running at http://localhost:3000
/webhooks/inbound req.body {
message_uuid: 'e93a3007-f7a5-436a-8ba7-c46d64343d80',
to: { type: 'sms', number: '12018994297' },
from: { type: 'sms', number: '15754947000' },
timestamp: '2021-08-27T21:14:51.228Z',
usage: { price: '0.0057', currency: 'EUR' },
message: {
content: { type: 'text', text: 'Hello' },
sms: { num_messages: '1' }
},
direction: 'inbound'
}
TurnContext {
_respondedRef: { responded: false },
_turnState: TurnContextStateCollection(2) [Map] {
'httpStatus' => 200,
Symbol(state) => { state: [Object], hash: '{}' }
},
_onSendActivities: [],
_onUpdateActivity: [],
_onDeleteActivity: [],
_turn: 'turn',
_locale: 'locale',
bufferedReplyActivities: [],
_adapter: VonageAdapter {
middleware: MiddlewareSet { middleware: [Array] },
BotIdentityKey: Symbol(BotIdentity),
OAuthScopeKey: Symbol(OAuthScope),
name: 'Vonage Adapter',
middlewares: null,
botkit_worker: [class VonageBotWorker extends BotWorker],
credentials: {
apiKey: '4f2ff535',
apiSecret: 'jtYzPbh3MXr8M1Hr',
applicationId: '978500cf-7ea8-4d7b-ac54-2b42f67b28a2',
privateKey: './private.key'
},
options: {},
to_number: '15754947000',
from_number: '12018994297',
enable_incomplete: undefined,
turnError: [AsyncFunction (anonymous)]
},
_activity: {
id: 'e93a3007-f7a5-436a-8ba7-c46d64343d80',
timestamp: 2021-08-27T21:14:39.573Z,
channelId: 'vonage-sms',
conversation: { id: '15754947000' },
from: { id: '15754947000' },
recipient: { id: '12018994297' },
text: 'Hello',
channelData: {
message_uuid: 'e93a3007-f7a5-436a-8ba7-c46d64343d80',
to: [Object],
from: [Object],
timestamp: '2021-08-27T21:14:51.228Z',
usage: [Object],
message: [Object],
direction: 'inbound'
},
type: 'message'
}
}
[onTurnError] unhandled error: TypeError: bot.reply is not a function
Botkit version:
Messaging Platform: Vonage
Node version: v14.16.1
Os: MAC
It looks like your custom adapter is built using both Botkit and BotFramework similar to other Botkit adapters. However, your bot's implementation aligns more with a bot built only for BotFramework yet you are trying to call the reply() method that belongs to a Botkit bot.
For example, in Botkit's 'botbuilder-adapter-twilio-sms' adapter, you are presented with two ways to utilize the adapter. In the first, under Botkit Basics, an adapter is created which is then consumed by Botkit to form the controller. This then allows you to access the reply() method callable from a Botkit bot.
In the second, under BotBuilder Basics, an adapter is created which is then utilized within the Express server's /api/messages endpoint. Inbound messages are passed to the adapter's processActivity() method where the bot then responds using the sendActivity() method, callable from within a BotFramework adapter's context.
Narrowing down which implementation you intend to use I believe will alleviate the error you are receiving.
I've tried to set up an API gateway and IAM permission but I keep getting an error message when I test my lambda function.
"errorType": "Runtime.UserCodeSyntaxError",
"errorMessage": "SyntaxError: Cannot use import statement outside a module",
"trace":
"Runtime.UserCodeSyntaxError: SyntaxError: Cannot use import statement outside a module",
" at _loadUserApp (/var/runtime/UserFunction.js:98:13)",
" at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
" at Object.<anonymous> (/var/runtime/index.js:43:30)",
" at Module._compile (internal/modules/cjs/loader.js:1138:30)",
" at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)",
" at Module.load (internal/modules/cjs/loader.js:986:32)",
" at Function.Module._load (internal/modules/cjs/loader.js:879:14)",
" at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)",
" at internal/main/run_main_module.js:17:47"
My lambda function:
import * as AWS from 'aws-sdk';
AWS.config.update({
accessKeyId: 'key',
secretAccessKey: 'key',
region: 'us-east-1'
});
const documentClient: AWS.DynamoDB.DocumentClient = new AWS.DynamoDB.DocumentClient();
interface IEvent {
email: string;
firstName: string;
lastName: string;
}
exports.handler = async (event: IEvent): Promise<void> => {
if (!event.email) {
throw new Error('Candidate email is required.');
}
if (!event.firstName) {
throw new Error('Candidate first name is required.');
}
if (!event.lastName) {
throw new Error('Candidate last name is required.');
}
await documentClient.put({
TableName: 'honeypot-interview-contacts',
Item: event
}).promise();
};
You've got the error right there, actually: SyntaxError: Cannot use import statement outside a module. Try switching to require? And it looks like you're running TypeScript? I don't think the default Node runtime has built in support for TS, you might want to run the code through the TS compiler first, that should also handle the import error.
I'm implementing graphql login mutation to authenticate user login credential. Mutation verifies the password with bcrypt then sends a cookie to the client, which will render user profile based on whether the cookie is a buyer or owner user).
GraphQL Login Mutation Code:
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
loginUser: {
type: UserType,
args: {
email: { type: GraphQLString },
password: { type: GraphQLString }
},
resolve: function (parent, args, { req, res }) {
User.findOne({ email: args.email }, (err, user) => {
if (user) {
bcrypt.compare(args.password, user.password).then(isMatch => {
if (isMatch) {
if (!user.owner) {
res.cookie('cookie', "buyer", { maxAge: 900000, httpOnly: false, path: '/' });
} else {
res.cookie('cookie', "owner", { maxAge: 900000, httpOnly: false, path: '/' });
}
return res.status(200).json('Successful login');
} else {
console.log('Incorrect password');
}
});
}
});
}
}
}
});
Server.js:
app.use("/graphql",
(req, res) => {
return graphqlHTTP({
schema,
graphiql: true,
context: { req, res },
})(req, res);
});
Error message:
(node:10630) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
[0] at ServerResponse.setHeader (_http_outgoing.js:470:11)
[0] at ServerResponse.header (/Users/xxx/xxx/server/node_modules/express/lib/response.js:771:10)
[0] at ServerResponse.append (/Users/xxx/xxx/server/node_modules/express/lib/response.js:732:15)
[0] at ServerResponse.res.cookie (/Users/xxx/xxx/server/node_modules/express/lib/response.js:857:8)
[0] at bcrypt.compare.then.isMatch (/Users/xxx/xxx/server/schema/schema.js:89:41)
I've done some research on this error, but can't seem to find a relevant answer. The issue seems to lie within response body being executing more than once, thus "cannot set headers after they are sent to the client". Since I'm sending both res.cookie() and res.status(200), how could I fix this problem?
express-graphql already sets the status and sends a response for you -- there's no need to call either res.status or res.json inside your resolver.
GraphQL always returns a status of 200, unless the requested query was invalid, in which case it returns a status of 400. If errors occur while executing the request, they will be included the response (in an errors array separate from the returned data) but the status will still be 200. This is all by design -- see additional discussion here.
Instead of calling res.json, your resolver should return a value of the appropriate type (in this particular case UserType), or a Promise that will resolve to this value.
Additionally, you shouldn't utilize callbacks inside resolvers since they are not compatible with Promises. If the bcrypt library you're using supports using Promises, use the appropriate API. If it doesn't, switch to a library that does (like bcryptjs) or wrap your callback inside a Promise. Ditto for whatever ORM you're using.
In the end, your resolver should look something like this:
resolve: function (parent, args, { req, res }) {
const user = await User.findOne({ email: args.email })
if (user) {
const isMatch = await bcrypt.compare(args.password, user.password)
if (isMatch) {
const cookieValue = user.owner ? 'owner' : 'buyer'
res.cookie('cookie', cookieValue, { maxAge: 900000, httpOnly: false, path: '/' })
return user
}
}
// If you want an error returned in the response, just throw it
throw new Error('Invalid credentials')
}
I came across protractor-image-comparison and wanted to test it out.
I made a limited test based on the example of the website, and I get the error
Failed: Cannot read property 'saveFullPageScreen' of undefined.
The browser.imageComparison is not defined.
It's strange I get this error following the example. There is limited support for protractor so I ask it here.
----------------- test.spec.ts --------------
import { browser, } from 'protractor';
import { Urls, DashboardPage } from '../utils';
fdescribe('protractor-image-comparison desktop', () => {
beforeEach(async () => {
await Urls.gotoDashboard();
await DashboardPage.getVPoints();
// await DashboardPage.removeDebugInfo();
});
it('should save some screenshots', async() => {
// Save a full page screens
await .saveFullPageScreen('fullPage', { /* some options*/ });
});
it('should compare successful with a baseline', async() => {
// Check a full page screens
expect(await browser.imageComparison.checkFullPageScreen('fullPage', { /* some options*/ })).toEqual(0);
});
});
-------------- part of jasmine.ts ---------------
plugins: [
{
// The module name
package: 'protractor-image-comparison',
// Some options, see the docs for more
options: {
baselineFolder: join(process.cwd(), './baseline/'),
formatImageName: `{tag}-{logName}-{width}x{height}`,
screenshotPath: join(process.cwd(), '.tmp/'),
savePerInstance: true,
autoSaveBaseline: true,
blockOutToolBar: true,
clearRuntimeFolder: true,
// ... more options
},
},
],
Failures:
1) protractor-image-comparison desktop should save some screenshots
Message:
Failed: Cannot read property 'saveFullPageScreen' of undefined
Stack:
TypeError: Cannot read property 'saveFullPageScreen' of undefined
at Object.<anonymous> (c:\projects\vital10-frontend\e2e\jasmine\image_compair\test.spec.ts:119:83)
at step (c:\projects\vital10-frontend\e2e\jasmine\image_compair\test.spec.ts:75:27)
at Object.next (c:\projects\vital10-frontend\e2e\jasmine\image_compair\test.spec.ts:24:53)
at c:\projects\vital10-frontend\e2e\jasmine\image_compair\test.spec.ts:17:71
at new Promise (<anonymous>)
at __awaiter (c:\projects\vital10-frontend\e2e\jasmine\image_compair\test.spec.ts:3:12)
at UserContext.<anonymous> (c:\projects\vital10-frontend\e2e\jasmine\image_compair\test.spec.ts:110:16)
at c:\projects\vital10-frontend\node_modules\jasminewd2\index.js:112:25
at new ManagedPromise (c:\projects\vital10-frontend\node_modules\selenium-webdriver\lib\promise.js:1077:7)
at ControlFlow.promise (c:\projects\vital10-frontend\node_modules\selenium-webdriver\lib\promise.js:2505:12)
From: Task: Run it("should save some screenshots") in control flow
at UserContext.<anonymous> (c:\projects\vital10-frontend\node_modules\jasminewd2\index.js:94:19)
at c:\projects\vital10-frontend\node_modules\jasminewd2\index.js:64:48
at ControlFlow.emit (c:\projects\vital10-frontend\node_modules\selenium-webdriver\lib\events.js:62:21)
at ControlFlow.shutdown_ (c:\projects\vital10-frontend\node_modules\selenium-webdriver\lib\promise.js:2674:10)
at c:\projects\vital10-frontend\node_modules\selenium-webdriver\lib\promise.js:2599:53
From asynchronous test:
Error
at Suite.<anonymous> (c:\projects\vital10-frontend\e2e\jasmine\image_compair\test.spec.ts:109:5)
at Object.<anonymous> (c:\projects\vital10-frontend\e2e\jasmine\image_compair\test.spec.ts:93:1)
at Module._compile (internal/modules/cjs/loader.js:868:30)
at Module.m._compile (c:\projects\vital10-frontend\node_modules\ts-node\src\index.ts:392:23)
at Module.m._compile (c:\projects\vital10-frontend\node_modules\ts-node\src\index.ts:392:23)
at Module._extensions..js (internal/modules/cjs/loader.js:879:10)
According to the docs you are missing browser.imageComparison before .saveFullPageScreen
I follow this doc https://www.apollographql.com/docs/apollo-server/requests.html#postRequests and try to send a POST request to apollo server.
test code:
it('should get author correctly', () => {
const body = {
query: `
query {
getAuthor($id: Int!) {
name
}
}
`,
// operationName: 'query author',
variables: {
id: 1
}
};
return rp.post(body).then(res => {
expect(res.data.getAuthor.name).to.equal('lin');
});
});
rp.js:
const requestPromise = require('request-promise');
const { PORT } = require('./config');
const GRAPHQL_ENDPOINT = `http://localhost:${PORT}/graphql`;
function rp(options) {
function post(body) {
return requestPromise(GRAPHQL_ENDPOINT, {
method: 'POST',
body,
json: true,
headers: {
'Content-Type': 'application/json'
}
});
}
return {
post
};
}
module.exports = rp;
When I run npm test command, got an error:
graphql test suites
Go to http://localhost:3000/graphiql to run queries!
✓ t0
1) should get author correctly
1 passing (79ms)
1 failing
1) graphql test suites
should get author correctly:
StatusCodeError: 400 - {"errors":[{"message":"Syntax Error: Expected Name, found $","locations":[{"line":3,"column":21}]}]}
at new StatusCodeError (node_modules/request-promise-core/lib/errors.js:32:15)
at Request.plumbing.callback (node_modules/request-promise-core/lib/plumbing.js:104:33)
at Request.RP$callback [as _callback] (node_modules/request-promise-core/lib/plumbing.js:46:31)
at Request.self.callback (node_modules/request/request.js:186:22)
at Request.<anonymous> (node_modules/request/request.js:1163:10)
at IncomingMessage.<anonymous> (node_modules/request/request.js:1085:12)
at endReadableNT (_stream_readable.js:1106:12)
at process._tickCallback (internal/process/next_tick.js:178:19)
The format of your query is not valid. There's actually two things wrong. One, variables are defined at the very top of the operation (next to the query or mutation keyword). And, two, if you define a variable, you have to use it. So your query should look more like this:
query($id: Int!) {
getAuthor(id: $id) {
name
}
}