How to create api routes with Fastify and Nuxt? - javascript

Fastify changed a lot since the last time I played with it. Also, I read that we should use Nuxt serverMiddleware to add api routes but I couldn't find any example on how to proceed.
Below there is my index file to start Fastify. I tried adding a route in it before nuxt with this line:
fastify.register(require('./routesIndex'), { prefix: '/api' })
routesIndex.js as per the new fastify documentation:
async function routes(fastify, options) {
fastify.register(require('./fetchRemote'))
fastify.register(require('./domains'))
}
module.exports = routes
To be thorough, the domains.js file:
async function routes(fastify, options) {
const database = fastify.mongo.db('db')
const collection = database.collection('test')
fastify.get('/domains/list', async (request, reply) => {
return { hello: 'world' }
})
fastify.get('/domains/:id', async (request, reply) => {
const result = await collection.findOne({ id: request.params.id })
if (result.value === null) {
throw new Error('Invalid value')
}
return result.value
})
}
module.exports = routes
server/index.js:
const { Nuxt, Builder } = require('nuxt')
const fastify = require('fastify')({
logger: true
})
fastify.register(require('./db'), {
url: 'mongodb://localhost:27017'
})
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
config.dev = !(process.env.NODE_ENV === 'production')
async function start() {
// Instantiate nuxt.js
const nuxt = new Nuxt(config)
const {
host = process.env.HOST || '127.0.0.1',
port = process.env.PORT || 3000
} = nuxt.options.server
// Build only in dev mode
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
} else {
await nuxt.ready()
}
fastify.use(nuxt.render)
fastify.listen(port, host, (err, address) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
}
start()
The /api route is not found in the browser. But then I read I should use serverMiddleware inside nuxt.config.js:
serverMiddleware: [
{ path: '/api', handler: '~/server/routesIndex.js' },
],
Doing so results in an error from fastify.register:
(node:10441) UnhandledPromiseRejectionWarning: TypeError: fastify.register is not a function
at routes (/media/srv/testingNuxt/server/routesIndex.js:4:13)
at call (/media/srv/testingNuxt/node_modules/connect/index.js:239:7)
at next (/media/srv/testingNuxt/node_modules/connect/index.js:183:5)
at next (/media/srv/testingNuxt/node_modules/connect/index.js:161:14)
at WebpackBundler.middleware (/media/srv/testingNuxt/node_modules/#nuxt/webpack/dist/webpack.js:5430:5)
(node:10441) 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(). (rejection id: 1)
(node:10441) [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.
How can I add api routes using Fastify and Nuxt?
I want to avoid creating a second server on port 3001 just for the api.

Related

Node UnhandledPromiseRejectionWarning when saving to MongoDb

New to node- I'm trying to save some of my tweets from Twitter API into mongo using Twit package.
I've connected to mongodb on port 27017 using mongoose, and this piece of code I've written seems to save the tweets to my db, however I seem to be getting this warning back everytime I save a document:
(node:9991) 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: 8)
Here is my code:
const Tweet = require('./app/models/tweet.model.js');
const dbConfig = require('./config/database.config.js');
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect(dbConfig.url, {
useNewUrlParser: true
}).then(() => {
console.log("Successfully connected to the database");
}).catch(err => {
console.log('Could not connect to the database. Exiting now...', err);
process.exit();
});
var Twit = require("twit");
var config = require("./config/twitter.config");
var T = new Twit(config);
var params = {
screen_name: "decade3uk",
count: 2
};
T.get("statuses/user_timeline", params, gotData);
function gotData(err, data, response) {
var tweets = data;
for(var i=0;i<tweets.length;i++){
const tweet = new Tweet({
created_at:tweets[i].created_at,
id_str:tweets[i].id_str,
text:tweets[i].text
});
tweet.save()
.then(entry => {
response.send(entry);
}).catch(err => {
response.status(500).send({
message: err.message || "Some error occurred while creating the Tweet."
});
});
}
}
What is best practice to get rid of this error?
Why don't you try to find where is that exception coming from and what exactly it is. You can find that by adding the following code to your server file, just to make sure you get what's causing the exception.
process.on('unhandledRejection', (reason, promise) => {
console.log("Reason: ",reason,"promise: ",promise);
})

node/pg/PSQL: Create Tables using Promises

I am writing a simple Node/Express/React/Postgres application and I'm using the pg package to interface with my Postgres Server.
I require three tables, table1, table2, and table3. table2 has a foreign key in table1 and table3 has a foreign key in table 2, so the order that I need to create the tables in is: table1 then table2 then table3.
I am attempting to use promises to enforce this order in my asynchronous table creation calls. I've generally followed Brian Carlson's suggested Project Structure, but clearly I'm doing something wrong.
Here are the simplified, relevant files from my project:
db.js:
const { Pool } = require('pg');
// Create pool connection to database
const pool = new Pool({
user: XXXX,
host: XXXX,
database: XXXX,
password: XXXX,
port: XXXX
});
// Pool emitters
pool.on('connect', () => {
console.log('Connected a client to the database');
});
pool.on('remove', () => {
console.log('Disconnected a client from the database');
});
pool.on('error', (err, client) => {
console.error('Unexpected error on idle client', err);
process.exit(-1);
});
// This structure taken from Brian Carlson's pg API Documentation
// https://node-postgres.com/guides/project-structure
module.exports = {
query: (text, params) => {
console.log('Making a query!');
return pool.query(text, params);
}
};
table_scripts.js:
const db = require('../db');
const Database_Scripts = {
create_table_1: () => {
const create_table_1_query = {
text: `CREATE TABLE IF NOT EXISTS
public.table_1
(
id smallserial,
name text NOT NULL,
PRIMARY KEY (id)
);`
};
return db.query(create_table_1_query);
},
create_table_2: () => {
const create_table_2_query = {
text: `CREATE TABLE IF NOT EXISTS
public.table_2
(
id smallserial,
table_1_id integer NOT NULL REFERENCES public.table_1(id),
name text NOT NULL,
PRIMARY KEY (id)
);`
};
return db.query(create_table_2_query);
},
create_projects_table: () => {
const create_table_3_query = {
text: `
CREATE TABLE IF NOT EXISTS
public.table_3
(
id smallserial,
table_3_id integer NOT NULL REFERENCES public.table_2(id),
name text NOT NULL,
PRIMARY KEY (id)
);`
};
return db.query(create_table_3_query);
}
};
module.exports = Database_Scripts;
create_tables.js:
const Table_Scripts = require('./table_scripts');
Table_Scripts.create_table_1()
.then(Table_Scripts.create_table_2())
.then(Table_Scripts.create_table_3())
.catch(error => console.log(error.stack));
package.json:
{
"name": "app",
"version": "0.0.0",
"scripts": {
"start": "nodemon ./bin/www",
"create_tables": "node ./database/scripts/create_tables.js"
}
}
When I run my create_tables script (npm run-script create_tables), I get the following (sanitized) errors:
Connected a client to the database
Connected a client to the database
Connected a client to the database
Disconnected a client from the database
(node:13444) UnhandledPromiseRejectionWarning: error: relation "public.table_1" does not exist
(node:13444) 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(). (rejection id: 1)
(node:13444) [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.
Disconnected a client from the database
(node:13444) UnhandledPromiseRejectionWarning: error: relation "public.table_2" does not exist
(node:13444) 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(). (rejection id: 2)
Disconnected a client from the database
I've been able to get this script to work converting the functions to async functions, however, I'd really like to understand what I'm doing wrong here.
Your problem seems to be that you're concurrently creating the tables despite explicitly needing to do the opposite.
According to the documentation, pool.query() returns a promise if not provided a callback function as a third argument. You need to wait for each of your db.query() promises to be resolved. Thus it'll wait for the first table to be created, then create the second one and finally the third one.
I would recommend using the async/await syntax
async function createTables () {
try {
const create_table_1_query = {
text: `yourQuery1`
};
// awaits for the first table to be created
await db.query(create_table_1_query);
const create_table_2_query = {
text: `yourQuery2`
};
// awaits for the second table to be created
await db.query(create_table_2_query);
const create_table_3_query = {
text: `yourQuery3`
};
// awaits for the third table to be created
await db.query(create_table_3_query);
} catch (e) {
console.error(e.stack);
}
}
module.exports.createTables = createTables;
You can then call await createTables();

Properly handled Promise Rejections

Considering the following code:
db.js
// Connecting to catalogstore (mongodb)
const mydb = async () => {
try {
await mongoose.connect(process.env.db);
console.log("Connected to Database!");
}
catch (err) {
throw new Error("Database connection error:", err);
}
};
export { db }
app.js
import { db } from './db';
db().then(async() => {
try {
let server = app.listen(process.env.port,
process.env.host, function() {
let host = server.address().address;
let port = server.address().port;
console.log('App started');
});
} catch (err) {
console.log(err);
}
});
Basically I'd like to start an Express server only after establishing the db connection.
It actually works fine, however I get this warning:
(node:29892) UnhandledPromiseRejectionWarning: Error: Database connection error:
at catalogstore (/Users/notaris/Workspace/Google/gcp-devops/apps/catalogservice/src/db.js:44:11)
at processTicksAndRejections (internal/process/task_queues.js:89:5)
(node:29892) 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(). (rejection id: 1)
(node:29892) [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.
How can I properly handle that?
The error is thrown by the db async function.
The correct way to handle this Error (using an async function/arrow) is:
import { db } from './db';
const main = async () => {
try {
await db();
let server = app.listen(process.env.port,
process.env.host, function() {
let host = server.address().address;
let port = server.address().port;
console.log('App started');
});
} catch (err) {
console.log(err);
}
});
main();
Modify app.js like follow
import { db } from './db';
db()
.then(/* normal logic */)
.catch(/* error logic */)
Just catch it ^^
In debugger i see that you should catch the error in the promise like this :
//app.js
import { db } from './db';
db().then(async() => {
try {
let server = app.listen(process.env.port,
process.env.host, function() {
let host = server.address().address;
let port = server.address().port;
console.log('App started');
});
} catch (err) {
console.log(err);
}
}).catch(error=>{
console.log('error'+error);
});
And you can check this link for more details.

nodejs crash only when I send multiple request

node js thunder when I send multiple requests to the server at the same time, but not when I send one by one. And nodejs says.
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
(node:4) 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(). (rejection id: 6)
That error in common when you send two responses to the client but in my code only sent one
This is my code
const User = require('../../../modelos/users');
async function getAllValuationsByUserName(req, res, next) {
let isOwner = false;
const userId = req.params.id;
const pagination = {
skip: Number(req.query.skip),
limit: Number(req.query.limit)
}
if (userId === res.locals.userid) {
isOwner = true;
}
try {
const user = await User.findOne(
{ userName: new RegExp('^' + userId + '$', "i") },
{
'userPhoto.valuations': {
$slice: [pagination.skip, pagination.limit]
}
})
const valuations = user.userPhoto.valuations
const total = user.userPhoto.valuations.length
return res.status(200).send({
erro: false,
isOwner,
valuations,
total
})
} catch (err) {
console.log(err)
return res.status(400).send({
error: true,
inf: err
});
}
}
module.exports = getAllValuationsByUserName

Promise and Resolve not working

const { GraphQLServer } = require('graphql-yoga');
const mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/test1");
const Todo = mongoose.model('Todo',{
text: String,
complete: Boolean
});
const typeDefs = `
type Query {
hello(name: String): String!
}
type Todo{
id: ID!
text: String!
complete: Boolean!
}
type Mutation{
createTodo(text:String!): Todo
}
`
const resolvers = {
Query: {
hello: (_, { name }) => `Hello ${name || 'World'}`,
},
Mutation:{
createTodo: async (_,{ text }) => {
const todo = new Todo({text, complete: false});
await todo.save();
return todo;
}
}
};
const server = new GraphQLServer({ typeDefs, resolvers })
mongoose.connection.once("open", function() {
server.start(() => console.log('Server is running on localhost:4000'))
});
Hello I'm new to node js and mongoDB. I'm trying to start my server but it's not starting. Every time it shows a error like this:
(node:17896) 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(). (rejection id: 1)
(node:17896) [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.
Every time this is showing some promise error.Can anyone please help me to debug this program. I m a beginner. I don't know much of it. But as per my understanding, I have written correct code only.
Probably your save function throws an arrow which you don't handle it!
you can solve this issue with one of these ways:
GraphQL handles promise by itself, so this would give you same result:
createTodo: (_,{ text }) => {
const todo = new Todo({text, complete: false});
return todo.save();
}
using try catch would give you better error handling:
createTodo: async (_,{ text }) => {
const todo = new Todo({text, complete: false});
try {
await todo.save();
return todo;
} catch(err) {
\\ do something with error
console.error('error=>', err);
return null;
}
}

Categories