How can I access Vuex Store from Node.js? - javascript

I have to access a state from server. I want to change the twitterName with a mutation after figure out from this. I set a getter but when I try to import store to js file it sends error. How can I import a state?
server/index.js
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const path = require('path')
const app = express()
app.use(bodyParser.json())
app.use(cors())
const tweets = require('./routes/api/tweets')
const twitterName = require('./routes/api/name')
app.use('/api/tweets', tweets)
app.use('/name/', twitterName)
if (process.env.NODE_ENV === 'production') {
app.use(express.static(__dirname + '/public/'))
app.get(/.*/, (req, res) => res.sendFile(__dirname + '/public/index.html'))
}
const port = process.env.PORT || 8081
app.listen(port, () => console.log(`Server started on port ${port}`))
server/name.js
const express = require('express')
const router = express.Router()
router.get('/:twitterName', (req, res) => {
const name = req.params.twitterName
res.status(200).send(name)
})
module.exports = router
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
twitterName: 'name1234'
},
getters: {
twitterName: (state) => state.twitterName
}
actions: {
updateId({ commit }, id) {
commit('setId', id)
},
async getTweetData({ state }) {
const res = await axios.get('http://localhost:8081/name/' + state.twitterName)
// do what you want with the data
}
},
})

You can’t use the store from the client in your express server from the simple reason that all the data used in client side of your application, including vuex store is saved in the browser, and you don’t have access to it in the server. This is not the correct way to achieve your goal.
If you want to use data from the client you need to send it to your server, so you could use it there. So if you need the twitterName specifically you can do something like this:
router.get('/tweets/:twitterName', (req, res) => {
// const name = 'name123'
const name = req.params.twitterName
T.get(
'search/tweets',
{ from: name, count: 5 },
function (err, data, response) {
if (err) {
return res.status(400).json('Oops! Something went wrong.')
}
data.twitterName = '<new-name>'
res.status(200).send(data)
}
)
})
And from the vuejs store:
actions: {
async getTweetData({ state, commit }) {
const res = await axios.get('<your-server-ip>/' + state.twitterName)
commit('setTwitterName', res.data.twitterName)
}
},
mutations: {
setTwitterName(state, newTwitterName) {
state.twitterName = newTwitterName
}
}

Related

Mocking a function within an express request for a Jest Unit test

I have a simple express application and i want to fully be able to mock it, here's what i've got so far
userRoute.js
const express = require("express")
const router = express.Router()
const db = require('./db')
router.get("/users/", async (req, res) => {
res.json({
status: 200,
data: await db.getUsers(),
})
})
module.exports = router
My issue is i am trying to mock the db.getUsers function but not sure how
here is my test code:
const router = require("./userRoute.js")
const app = new express()
app.use("/", router)
describe("Users Route", () => {
test("getUsers Happy Path", async () => {
jest.spyOn(db, "getUsers").mockImplementation(() => {
return {
id:12345
name: "Jason"
age: "34"
}
})
const res = await app.get("/users/")
console.log(res)
})
})
this doesn't work for me, if i run the function regularly in a standard function it works but since its an api endpoint in a route it doesn't work for whatever reason, any help would be fantastic
Maybe you want to try to mock the db before require the useRouter.js
Also, you need to run the server (and close it after all tests) and make a real request to your server.
const express = require('express');
const axios = require('axios');
const PORT = 5565;
const userMock = {
id: 1,
name: 'John Doe',
email: 'email#email.com',
}
const dbSpy = jest.spyOn(require('./db.js'), 'getUsers').mockImplementation(() => userMock);
const router = require('./index.js');
const app = express();
app.use('/', router);
const server = app.listen(PORT, () => 'Example app listening on port 3000!');
describe('Users Route', () => {
afterAll(() => server.close());
test('getUsers Happy Path', async () => {
const response = await axios.get(`http://localhost:${PORT}/users/`);
expect(dbSpy).toHaveBeenCalledTimes(1);
expect(response.status).toBe(200);
expect(response.data.data).toEqual(userMock);
});
})

Express, request body is {} in middleware, but has content in controller

Here is my server.js:
import express from "express";
import mongoose from "mongoose";
import productRouter from "./routers/productRouter.js";
import dotenv from "dotenv";
dotenv.config();
const app = express();
app.use(express.json());
let prof = process.env.PROF;
mongoose.connect(
`${prof}`
);
// Add headers before the routes are defined
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader("Access-Control-Allow-Origin", "*");
// Request methods you wish to allow
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, OPTIONS, PUT, PATCH, DELETE"
);
res.header("Access-Control-Allow-Headers", "Content-Type");
// Request headers you wish to allow
// res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader("Access-Control-Allow-Credentials", true);
// Pass to next layer of middleware
next();
});
/*
app.get("/api/products", (req, res) => {
res.send(data);
});*/
app.use("/api/products", productRouter);
app.get("/", (req, res) => {
res.send("Server is ready");
});
const port = process.env.PORT || 5000;
app.listen(port);
Going inside productRouter.js ...
import express from "express";
import mongoose from "mongoose";
import data from "../data.js";
import Product from "../models/productModel.js";
import { payment } from "./paymentController.js";
const productRouter = express.Router();
productRouter.use("/pay", async (req, res, next) => {
// dont store cart in db, store it in local storage. On checkout get Id of all items in cart. Then find their prices from the db and charge correctly.
console.log("middleware ran");
console.log(req.body);
const productIdsAndAmounts = req.body.basketItems.items.map((item) => {
return { id: item.id, amount: item.amount };
});
// this works faster (apparently)
/*
const objIds = productIds.map((id) => mongoose.Types.ObjectId(id));
const orderedItems = await Product.find({
_id: { $in: objIds },
});
*/
// this sends more query requests to db
const orderedItems = await Promise.all(
productIdsAndAmounts.map((productId) => {
return Product.findById(productId.id);
})
);
let i = -1;
let productIdsPricesAmounts = [];
orderedItems.forEach((item) => {
i = i + 1;
productIdsPricesAmounts.push({
id: item.id,
price: item.price,
amount: productIdsAndAmounts[i].amount,
});
});
console.log(productIdsPricesAmounts);
const prices = productIdsPricesAmounts.map((item) => {
return item.price * item.amount;
});
const reducer = (prevValue, currValue) => prevValue + currValue;
const totalTotalPrice = prices.reduce(reducer);
console.log(totalTotalPrice);
req.totalPrice = totalTotalPrice;
//console.log(orderedItems);
//console.log(productIdsAndAmounts);
// console.log(req.body.user); // adres
next();
});
productRouter.get("/", async (req, res) => {
const products = await Product.find({});
res.send(products);
});
productRouter.post("/pay", payment);
export default productRouter;
Now to the paymentController.js:
export const paymentController = async (req, res, next) => {
console.log(req.body.basketItems)
/* returns contents of the body like expected, i can do whatever i want with it*/
}
The behaviour, i can get is:
Client sends request to "api/products/pay", i have access to req.body in paymentController.
The behaviour, i want is:
Client sends request to "api/products/pay", the request first goes through a middleware where i do some calculations on it, then i forward the new variable to my paymentController. The problem is req.body is {} in middleware productRouter.use(), but available in paymentController
What am I doing wrong ? I'm new to express and i don't exactly know what I'm doing yes. I want to have access to req.body inside productRouter. I'm guessing i set up the middleware wrong or something like that. But I can't see what i did wrong.
Can You Use
Router For Example :
user.ts
import express from "express";
let UserRoute = express.Router()
UserRoute.get('/',function (req,res) {
res.json('Hello World')
})
export { UserRoute }
App.ts
import express from "express";
import cors from "cors";
import { UserRoute } from "./routes/v1/user"
const http = require('http');
const app = express();
const server = http.createServer(app);
const PORT : string|number = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
app.use('/',UserRoute)
//Run Server And Listen To Port
server.listen(PORT,()=>{
console.log("Server UP")
})
Guess this is your main route where you want to add middleware function right
Create a middle were function with name "abc" export from there as name "abc"
Now, here in main route you can use that function as a middleware
productRouter.post("/pay",abc, payment);
here abc is your middleware function

Cannot read property 'collection' of undefined MongoDB nodejs driver

i'm trying to pass the mongodb connection to all the other routes, so i created another file and imported mongoClient there and wrapped connect and getDb in functions so i can connect to the db first from server.js and then access the db from the other files, but idk why i'm getting Cannot read property 'collection' of undefined
server.js
const express = require('express')
const bodyParser = require('body-parser')
const mongodb = require('./mongodb/db.js')
const auth = require('./routes/auth.js')
require('dotenv').config()
const app = express();
app.use(bodyParser.json());
const PORT = process.env.PORT
app.get('/api', (req, res) => {
res.send('Welcome to the api')
})
app.use('/api/auth', auth);
mongodb.connect(() => {
app.listen(PORT, () => {
console.log(`app is listening at http://localhost:${PORT}`)
})
})
./mongodb/db.js
const MongoClient = require('mongodb').MongoClient;
const DB_URL = process.env.DB_URL
const DB_NAME = process.env.DB_NAME
const dbClient = new MongoClient(DB_URL, { useUnifiedTopology: true })
let db;
const connect = (callback) => {
dbClient.connect().then(client => {
db = client.db(DB_NAME)
console.log("connected to db")
}).catch(console.log)
callback()
}
const get = () => {
return db;
}
module.exports = {
connect,
get
};
./routes/auth.js
const express = require('express')
const router = express.Router();
const db = require('../mongodb/db.js');
const smth = db.get();
console.log(smth) //undefined;
const usersCollection = db.get().collection('users');
const authCollection = db.get().collection('auth')
router.post('/login', async (req, res) => {
...
})
router.post('/register', async (req, res) => {
...
})
module.exports = router
You call callback outside of the promise chain in the connect function of ./mongodb/db.js. It's possible that you are running into some async issues there, as the function can return before the promise chain resolves.

nuxtjs + express, why returns html?

I am trying to do something similar to the API, using nuxtjs + express.
in server/index.js file I create
app.get ('/ test', (req, res) => {
res.send ({method: 'GET'})
})
when contacting localhost:3000/test
HTML markup is returned, why is this happening?
When trying to make a request through POSTMAN, HTML is also returned
index.js
const express = require('express')
const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
const app = express()
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
config.dev = process.env.NODE_ENV !== 'production'
async function start() {
// Init Nuxt.js
const nuxt = new Nuxt(config)
const { host, port } = nuxt.options.server
await nuxt.ready()
// Build only in dev mode
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
}
app.get('/test', (req, res) => {
res.send({ method: 'GET' })
})
// Give nuxt middleware to express
app.use(nuxt.render)
// Listen the server
app.listen(port, host)
consola.ready({
message: `Server has been started on port: http://${host}:${port}`,
badge: true
})
}
start()

Vue api service showing error and not working at all

I am trying to call my vue api service via axios. However, it does not work at all and I am getting Network Error message on my browser console.
Could anyone advice what I did wrong? Below I have attached my code from by the client and server side.
error
api.js
const axios = require('axios')
export default () => {
return axios.create({
baseURL: 'http://localhost:1991'
})
}
api_metrics.js
import api from '#/services/api.js'
const url = api() + '/api/metrics/'
export default {
getIpAddress () {
console.log(url)
return api().get(url)
}
}
express_server.js
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const app = express()
// middleware
app.use(cors())
const metrics = require('./routes/api/metrics')
app.use('/api/metrics', metrics)
const port = process.env.PORT || 1991
app.listen(port, ()=>{
console.log(`server running on port ${port}`)
})
server_api.js
const express = require('express')
const router = express.Router()
router.get('/', (req,res)=>{
console.log('getIpAddress ')
res.send('"metrics"')
})
module.exports = router
home.vue
<template>
<p>Home</p>
</template>
<script>
export default {
data: () => ({
this.user_information = []
}),
async created () {
try {
this.user_information = await
apiService.getIpAddress()
console.log(this.user_information)
} catch (err) {
console.log(err.message)
}
}
}
</script>

Categories

Resources