Serverless framework TypeError: e is not a function - serverless-framework

I'm using serverless-framework to schedule tasks in AWS.
My application structure is
|- src
|- tasks
|- analytics.task.js
|- tasks.js
|- serverless.yml
The contents of analytics.task.js
module.exports.run = (event, context, callback) => {
console.log('Getting data...');
console.log('success');
};
Removed all other codes from the run method for testing purpose.
content of tasks.js
const analyticsTask = require('./src/tasks/analytics.task');
module.exports.analytics = analyticsTask.run();
and content of serverless.yml
functions:
analyticsDataProcess:
handler: tasks.analytics
description: 'Send analytics data to the backend server'
events:
- schedule:
name: analytics-data-process-task
description: 'Send analytics data every minute'
rate: rate(1 minute)
enabled: true
But when running the task, it is giving an error
{
"errorMessage": "e is not a function",
"errorType": "TypeError",
"stackTrace": [
"TypeError: e is not a function",
" at /home/user/code/user/qcg-app/serverless_sdk/index.js:9:88073",
" at resolve (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/lib/plugins/aws/invokeLocal/index.js:692:30)",
" at Promise._execute (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/debuggability.js:411:9)",
" at Promise._resolveFromExecutor (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:518:18)",
" at new Promise (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:103:10)",
" at AwsInvokeLocal.invokeLocalNodeJs (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/lib/plugins/aws/invokeLocal/index.js:645:12)",
" at AwsInvokeLocal.invokeLocal (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/lib/plugins/aws/invokeLocal/index.js:155:19)",
" at AwsInvokeLocal.tryCatcher (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/util.js:16:23)",
" at Promise._settlePromiseFromHandler (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:547:31)",
" at Promise._settlePromise (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:604:18)",
" at Promise._settlePromiseCtx (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:641:10)",
" at _drainQueueStep (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:97:12)",
" at _drainQueue (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:86:9)",
" at Async._drainQueues (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:102:5)",
" at Immediate.Async.drainQueues [as _onImmediate] (/home/user/.nvm/versions/node/v10.15.3/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:15:14)",
" at runCallback (timers.js:705:18)",
" at tryOnImmediate (timers.js:676:5)",
" at processImmediate (timers.js:658:5)",
" at process.topLevelDomainCallback (domain.js:120:23)"
]
}

Okay there seems to be a few things going on here.
First, it's expected that your handler returns a function that can be called by lambda. In this case, you're calling the handler instead of returning the function to be called by lambda.
To solve this problem, remove the parenthesis after run in task.js
const analyticsTask = require('./src/tasks/analytics.task');
module.exports.analytics = analyticsTask.run;
There's another issue - lambda handlers need to be asynchronous functions. So you'll need to add async in front of the function exported as run in analytics.task.js. Now you can remove the callback argument.
The alternative would be to omit async, but actually call the callback. Since we tend to prefer newer node syntax, let's remove the callback arg in favor of async.
module.exports.run = async (event, context) => {
console.log('Getting data...');
console.log('success');
};

Aurelia W mentioned it in a comment but I wanted to post it since it was the answer for me. Make sure your function name matches what is in serverless.yml.
It's too bad the error isn't more descriptive.

Related

Why can't browser.getRequest get data?

I use wdio intercept service to test the network interface,This is his official document. I used it completely according to his instructions, but I didn't get the expected results
this is my test.js
it("test a", async () => {
browser.url("https://www.amazon.in/")
let input = await $("#twotabsearchtextbox")
input.setValue("mobile")
await browser.pause(3000)
await browser.expectRequest("GET", "/api/2017/suggestions", "200")
let searchSuggestions = await browser.getRequest(
"GET",
"https://completion.amazon.in/api/2017/suggestions"
)
console.log("Response Headers", searchSuggestions)
expect(searchSuggestions).to.have.length.above(0)
})
when I run it, I got:
expected [] to have a length above +0 but got +0
This is my repo for test: https://github.com/Ruobei/wdioTest.git
I checked a lot of materials, but I didn't find the reason, nor did I find any other calling methods。If anyone knows how to solve it, it will be appreciated。
You need to call the setup function in order to assess request called. Please add browser.setupInterceptor() after the browser.url() command.
More details can be found here: https://webdriver.io/docs/wdio-intercept-service/#api
Try with 4.2.2 version:
npm install wdio-intercept-service#4.2.2

I can't run the node.js server using keystone.js framework

I have source code using keystone.js, and I can't run it because of a Mongodb connection error.
This is the code creating Keystone.
const keystone = new Keystone({
name: process.env.PROJECT_NAME,
adapter: new Adapter({dbName}),
mongo: 'mongodb://127.0.0.1:27017/',
sessionStore: new MongoStore({ url: 'mongodb://localhost/' }),
cookieSecret: 'process.env.COOKIE_SECRET',
appVersion: {
version: '1.0.0',
addVersionToHttpHeaders: false,
access: false,
},
cookie: {
secure: false,
maxAge: 1000 * 60 * 60 * 24 * 30, // 30 days
sameSite: false
}
});
...
await keystone.connect()
Here are the error details:
(node:9928) UnhandledPromiseRejectionWarning: Error: No MongoDB connection URI specified.
at resolveAllKeys (E:\Node.JS\frostbets-master-2-20210809T155720Z-001\frostbets-master-2\keystone\node_modules\#keystonejs\utils\dist\utils.cjs.dev.js:51:19)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async Keystone.connect (E:\Node.JS\frostbets-master-2-20210809T155720Z-001\frostbets-master-2\keystone\node_modules\#keystonejs\keystone\lib\Keystone\index.js:450:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:9928) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:9928) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
------------------------------------------------------------------------------------------
You haven't specified but it looks like you're on Keystone 5 so I'm going with that assumption.
There are a number of issue in the code you've posted:
The main problem you have is you're passing dbName to init you Adapter but you should be passing the full mongoUri.
That's the source of the specific error you're getting.
Pretty sure dbName was an option at one point but not in the current release of KS5.
Again, not sure which version you're actually on but if you've updated some packages in an older project, that might be it.
I'm not sure what the mongo key being passed in the Keystone config but I don't think it's valid.
Any config for Mongo (for the main DB) should be passed to the adapter.
The syntax you're using to create your MongoStore instance has been deprecated for the current version of that package.
If it works for you leave it, but in the code below I've used the more recent MongoStore.create() syntax.
In your code you have mongodb://127.0.0.1:27017/ (under the mongo key, which I think is ignored) and mongodb://localhost/ for the sessionStore.
For most systems this will refer to the same DB though it's not clear if that's intentional in your case.
In my code I've put the sessions in a separate DB (my-app-sessions) but that's optional.
Your config uses the literal string 'process.env.COOKIE_SECRET' as the cookie secret, not the value in the COOKIE_SECRET environment var.
This is almost certainly not what you want.
To solve these problems, you probably want something close to this:
const { Keystone } = require('#keystonejs/keystone');
const { GraphQLApp } = require('#keystonejs/app-graphql');
const { AdminUIApp } = require('#keystonejs/app-admin-ui');
const MongoStore = require('connect-mongo');
const { MongooseAdapter: Adapter } = require('#keystonejs/adapter-mongoose');
const keystone = new Keystone({
name: process.env.PROJECT_NAME,
adapter: new Adapter({ mongoUri: 'mongodb://localhost/my-app' }),
sessionStore: MongoStore.create({ mongoUrl: 'mongodb://localhost/my-app-sessions' }),
cookieSecret: process.env.COOKIE_SECRET,
appVersion: {
version: '1.0.0',
addVersionToHttpHeaders: false,
access: false,
},
cookie: {
secure: false,
maxAge: 1000 * 60 * 60 * 24 * 30, // 30 days
sameSite: false
}
});
// ...
module.exports = {
keystone,
apps: [new GraphQLApp(), new AdminUIApp({ name: process.env.PROJECT_NAME, enableDefaultRoute: true })],
};
In this code I've left the standard exports at the bottom rather than calling keystone.connect() directly so I can run it with yarn keystone dev.
Tested with..
"dependencies": {
"#keystonejs/adapter-mongoose": "^11.2.2",
"#keystonejs/app-admin-ui": "^7.5.2",
"#keystonejs/app-graphql": "^6.3.2",
"#keystonejs/keystone": "^19.3.3",
"connect-mongo": "^4.4.1"
}

Reference Error with module exports event discord.js

I am very confused by this error. In my code I have /events/ and /commands/ this is in /events/ I made sure that everything else works but this I can't figure out. The code down below is meant to work as a server count for a website. Anybody know? Thank you.
const Discord = require('discord.js');
var db = require('mysql');
var con = db.createConnection({
host: "localhost",
user: "",
password: "",
database: ""
});
module.exports = (client, guildCreate) => {
//welcome embed
const welcomeEmbed = new Discord.MessageEmbed()
.setColor('#858884')
.setTitle('Hello!')
.setAuthor('DHL Bot', 'https://cdn.discordapp.com/app-icons/708717412391845988/967e1b05f7b8aeca1d6b4649dc5530c8.png')
.setDescription(`Hello I am DHL, I am devoloped by Den#0762. Please do !setup. For support you can join our support server https://discord.com/invite`)
.setTimestamp()
.setFooter('By: Den#0762', 'https://cdn.discordapp.com/avatars/407206318911258628/e972b589e0ea4c45064d39b0380d77fd.png')
guild.owner.send(welcomeEmbed)
//db for scount
con.connect(function(err) {
if (err) throw err;
var sql = "UPDATE scount SET servercount = servercount + 1";
con.query(sql, function (err, result) {
console.log(result.affectedRows + " new server");
});
});
}
(node:1949) UnhandledPromiseRejectionWarning: ReferenceError: guild is not defined
at module.exports (/root/dc/DHL/events/guildCreate.js:23:1)
at Client.emit (events.js:315:20)
at Object.module.exports [as GUILD_CREATE] (/root/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js:33:14)
at WebSocketManager.handlePacket (/root/node_modules/discord.js/src/client/websocket/WebSocketManager.js:386:31)
at WebSocketShard.onPacket (/root/node_modules/discord.js/src/client/websocket/WebSocketShard.js:436:22)
at WebSocketShard.onMessage (/root/node_modules/discord.js/src/client/websocket/WebSocketShard.js:293:10)
at WebSocket.onMessage (/root/node_modules/ws/lib/event-target.js:125:16)
at WebSocket.emit (events.js:315:20)
at Receiver.receiverOnMessage (/root/node_modules/ws/lib/websocket.js:797:20)
at Receiver.emit (events.js:315:20)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:1949) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:1949) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
You're referencing guild, but it isn't declared. Based on other code I've seen, I think you need something along these lines:
module.exports = (client, guildCreate) => {
//welcome embed
const welcomeEmbed = new Discord.MessageEmbed() [...]
client.on("guildCreate", guild => {
guild.owner.send(welcomeEmbed)
});
[...]

Scheduling localhost serverless cron: The model could not be resolved in registry

I'm hosting an ExpressJS/NodeJS API on AWS Lambda with Serverless framework. The API uses Knex.js and Bookshelf.js ORM.
I want to test scheduling a cron job locally. I'm using serverless-offline-scheduler to do this.
Question: My API runs fine if I call it from my client, but if I call a function via serverless scheduler, it complains that no models are in the registry. Why is this? I've already definitely included all necessary Models at the top of the OrderService.js file.
{
"errorMessage": "The model User could not be resolved from the registry plugin.",
"errorType": "Error",
"stackTrace": [
"Error: The model User could not be resolved from the registry plugin.",
" at new ModelNotResolved (/Users/danielturcotte/Sites/d2c/api_v4/node_modules/bookshelf/lib/plugins/registry.js:70:133)",
Serverless.yml:
functions:
app:
handler: handler.handler
events: ...
dequeue:
handler: ./services/OrderService.dequeue // Call dequeue function
events:
- schedule: rate(1 minute)
The handler calls root/services/OrderService.dequeue function, which contains
...
const dequeue = async function() {
await checkQueuedOrders();
};
module.exports = {
dequeue,
};
In my knexService.js file, I register Bookshelf models to the registry to remove circular dependencies:
const knexfile = require('./knexfile');
const config = require('./environment');
const environment = config.env.NODE_ENV || 'development';
const knex = require('knex')(knexfile[environment]);
knex.client.pool.numPendingCreates();
const bookshelf = require('bookshelf')(knex);
bookshelf.plugin('registry'); // Resolve circular dependencies with relations
bookshelf.plugin('visibility');
bookshelf.plugin('pagination');
module.exports.knex = knex;
module.exports.bookshelf = bookshelf;

Checkit with bookshelf, how to catch error and stop DB execution?

I'm trying to use checkit with bookshelf and after adding the checkit rules, intentionally violating them, my promise#catch block doesn't seem to be properly catching the errors. (I could also be totally misunderstanding the use of catch here)
var validationRules = new Checkit({
email: 'required',
password: 'required'
});
var User = bookshelf.Model.extend({
tableName: 'users',
initialize: function() {
this.on('saving', this.validateSave);
},
validateSave: function() {
validationRules.run(this.attributes);
}
});
User.forge({}).save().then(function(validated) {
console.log('this shouldnt trigger');
}).catch(function(err) { // this doesnt seem to be working the way I expect
console.log(e.message);
});
When I create the empty user object, I'm getting the following unhandled error stacktrace, and also seeing a DB query being built (which may be a separate question for the bookshelf project and what happens when you hook into the 'saving' event)
Possibly unhandled Checkit Errors - email: The email is required; password: The password is required
at checkit/checkit.js:105:23
at tryCatch1 (bluebird/js/main/util.js:45:21)
at Promise._callHandler (bluebird/js/main/promise.js:597:13)
at Promise._settlePromiseFromHandler (bluebird/js/main/promise.js:607:18)
at Promise._settlePromiseAt (checkit/node_modules/bluebird/js/main/promise.js:769:18)
at Promise._settlePromises (checkit/node_modules/bluebird/js/main/promise.js:884:14)
at Async._drainQueue (checkit/node_modules/bluebird/js/main/async.js:98:12)
at Async._drainQueues (checkit/node_modules/bluebird/js/main/async.js:103:10)
at Async.drainQueues (checkit/node_modules/bluebird/js/main/async.js:37:14)
at process._tickCallback (node.js:415:13)
{ __cid: '__cid1',
method: 'insert',
options: undefined,
bindings: [],
sql: 'insert into `users` () values ()' }
ER_NO_DEFAULT_FOR_FIELD: Field 'email' doesn't have a default value
I have 2 questions about this:
Since I have debug: true turned on in my knex config, the block between the stacktrace and the ER_NO_DEFAULT_FOR_FIELD seems to be prepared SQL statements. Given that I introduced Checkit to catch validation errors on the Model level, why is SQL still being executed?
Am I using the #catch block in the correct manner? And if so, why do I still get unhandled error stacktraces. (It looks as though the e.message resulting from the #catch function is actually coming from MySQL rather than from Checkit) If not, what is the correct way to handle errors more gracefully here?
My main sources of information so far have been the bookshelf.js docs(http://bookshelfjs.org/), and the Checkit repo (https://github.com/tgriesser/checkit)
Checkit returns promises, promises work with each-other using return values so by not having return after checkit.run you're not letting bookshelf know when the validation is complete.
Bluebird (the underlying promises) are letting you know you might have a rejection you're not aware of. In order to correct the code you need to change:
validationRules.run(this.attributes);
To:
return validationRules.run(this.attributes);
In your validateSave function so the promise can chain.