how to deploy vuejs/nodejs app in firebase hosting? - node.js

My project structure
client part contains vue app and server part contains nodejs. In client side handling api service which is created from server. Created api services inside client folder to get response from server.
here is my structure of client-> services->api.js.
here is client -> services -> api.js code:
import axios from 'axios'
export default() => {
return axios.create({
baseURL: `https://dev-cloudthrifty-com.firebaseapp.com`
// https://dev-cloudthrifty-com.firebaseapp.com/
// http://localhost:8081
})
}
client -> vue.config.js configuration file.
const path = require('path')
module.exports = {
devServer: {
compress: true,
disableHostCheck: true,
},
outputDir: path.resolve(__dirname, '../server/dist'), // build all the assets inside server/dist folder
pluginOptions: {
'style-resources-loader': {
preProcessor: 'scss',
patterns: [path.resolve(__dirname, './src/styles/global.scss')]
}
},
chainWebpack: config => {
if (config.plugins.has('optimize-css')) {
config.plugins.delete('optimize-css')
}
}
}
Here is my firebase configuration: firebase.json
{
"hosting": {
"public": "./server/dist",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
},
{ "source": "**", "function": "app"}
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"headers": [ {
"source": "**/*.#(eot|otf|ttf|ttc|woff|font.css)",
"headers": [ {
"key": "Access-Control-Allow-Origin",
"value": "*"
} ]
}, {
"source": "**/*.#(jpg|jpeg|gif|png)",
"headers": [ {
"key": "Cache-Control",
"value": "max-age=7200"
} ]
}, {
"source": "404.html",
"headers": [ {
"key": "Cache-Control",
"value": "max-age=300"
} ]
} ],
"cleanUrls": true
}
}
Server-> app.js where i'm creating api for front-end
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const morgan = require('morgan')
const firebase = require('firebase');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const axios = require('axios');
const credentials = new Buffer('testing:testing123').toString('base64')
const app = express()
app.use(morgan('combined'))
app.use(bodyParser.json())
app.use(cors())
var Post = require("./models/post");
const firebaseConfig = {
apiKey: "AIzaSyDHDKttdke4WArImpRu1pIU",
authDomain: "dev-cxxxxxy-com.firebaseapp.com",
databaseURL: "https://dev-cxxxx-com.firebaseio.com",
projectId: "dev-clxxxx-com",
storageBucket: "dev-cxxxx-com.appspot.com",
messagingSenderId: "830534343916",
appId: "1:83916:web:e0fd232ebb1"
};
const firebaseApp = admin.initializeApp(firebaseConfig);
var db = firebaseApp.firestore();
app.get('/gcp-scheduler', (req, res) => {
res.send(
[{
title: "Hello World!",
description: "Hi there! How are you?"
}]
)
})
// serve dist folder
if (process.env.NODE_ENV === 'production') {
// Static folder
app.use(express.static(__dirname + '/dist'));
// Handle SPA
app.get('**', (req, res) => res.sendFile(__dirname + '/dist/index.html'));
}
// Add new post
app.post('/list-server', (req, res) => {
var token = req.body.token;
var ccExp = req.body.ccExp;
var cardNumber = req.body.cardNumber;
var currentUserUUID = req.body.currentUserUUID;
var amount = req.body.amount;
console.log(token);
console.log(ccExp);
(async() => {
const paymentRequest = await getAuthTokenForThePayment({
account: cardNumber,
merchid: '496160873888',
amount: amount, // Smallest currency unit. e.g. 100 cents to charge $1.00
expiry: ccExp,
currency: 'USD'
});
const charge = await makeCharge({
merchid: paymentRequest.data.merchid,
retref: paymentRequest.data.retref
});
console.log(charge);
console.log(charge.data.respstat)
if (charge.data.respstat == 'A'){
var data = db.collection('transactionTable').doc(charge.data.retref);
var setAlan = data.set({
'respstat': charge.data.respstat,
'retref': charge.data.retref,
'account': charge.data.account,
'token': charge.data.token,
'batchid': charge.data.batchid,
'amount': charge.data.amount,
'resptext': charge.data.resptext,
'respcode': charge.data.respcode,
'commcard': charge.data.commcard,
'setlstat': charge.data.setlstat,
});
res.send(charge.data.respstat);
} else if(charge.data.respstat == 'B'){
console.log("Declined");
res.send(charge.data.respstat);
}else if(charge.data.respstat == 'C'){
console.log("Retry");
res.send(charge.data.respstat);
}
})();
})
const getAuthTokenForThePayment = async (data) => {
try {
const config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${credentials}`
}
};
const URL = 'https://fts.cardconnect.com:6443/cardconnect/rest/auth';
return await axios.put(URL, data, config);
} catch (error) {
throw (error);
}
}
const makeCharge = async (data) => {
try {
const config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${credentials}`
}
};
const URL = 'https://fts.cardconnect.com:6443/cardconnect/rest/capture';
return await axios.put(URL, data, config);
} catch (error) {
throw (error);
}
}
// app.listen(process.env.PORT || 8081)
exports.app = functions.https.onRequest(app);
My issue when i click on checkout button in cart view, it should send current user card details with token to the server(app.js) through post api. After receiving card details from front-end, it should call cardconnect charge api functionality which i have implemented in app.js. In browser console current user card details received successfully but while clicking checkout charge api are not called it shows some other which is unrelated to api.
But everything works in localhost. client side localhost url: http://localhost:8080 and server side localhost url: http://localhost8081.
my firebase hosting url: https://dev-xxxx.firebaseapp.com
here is my console output screenshot:
Dont where i am making mistakes in firebase vuejs/nodejs hosting, rewrites path.
it show error in postservice.js file
import Api from '#/services/Api'
export default {
fetchPosts () {
return Api().get('gcp-scheduler')
},
addPost (params) {
return Api().post('list-server', params)
}
}
Any help much appreciated pls..

Related

Firebase Function Unable to find a valid endpoint for function app

I have a firebase functions folder which I am trying to connect to my frontend app to run calls to my backend server.
The function folder got set up and worked with the emulator, when I tried to use these function in the front end app however they didn't work. The following error showed: Error: Unable to find a valid endpoint for function app
This is what I added to the frontend firebaase.json file:
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
},
{
"source": "/bigben",
"function": "bigben",
"region": "us-central1"
},
{
"source": "/create-customer-portal-session",
"function": "app"
}
]
}
}
Then this is the index.js file in the functions folder:
const functions = require('firebase-functions');
const express = require('express');
const app = express();
const cors = require('cors')({origin: true});
app.use(cors);
exports.app = functions.https.onRequest(app);
exports.bigben = functions.https.onRequest((req, res) => {
const hours = (new Date().getHours() % 12) + 1 // London is UTC + 1hr;
res.status(200).send(`<!doctype html>
<head>
<title>Time</title>
</head>
<body>
${'BONG '.repeat(hours)}
</body>
</html>`);
});
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY)
const priceId = 'price_1LaJC1CKMdmWgnyspBbFet9v';
const storeItems = new Map([
[
1, { priceInCents: 10000, name: 'Item 1 Name'}
],
[
2, { priceInCents: 20000, name: 'Item 2 Name'}
],
])
app.post("/create-checkout-session", async (req, res) => {
const cust = req.body.customerId
const price = req.body.priceId
const quantity = req.body.students
const quantityA = Number(quantity)
try {
const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
mode: 'subscription',
allow_promotion_codes: true,
customer: cust,
line_items: [
{
price: price,
// For metered billing, do not pass quantity
quantity: quantityA,
},
],
success_url: `https://learning-platform.web.app/`,
cancel_url: `https://learning-platform.web.app/`,
})
res.redirect(session.url);
} catch (e) {
res.status(500).json({ error: e.message })
}
})
app.post('/create-customer-portal-session', async (req, res) => {
const cust = req.body.customerId
// Authenticate your user.
const session = await stripe.billingPortal.sessions.create({
customer: cust,
});
console.log(session.url)
res.redirect(session.url);
});
This is what is returned when I run the command: firebase deploy --only functions,hosting --debug

how to use local swagger.json, istead of giving api controllers

I am new to swagger. I am creating an express-nodejs-typescript, rest api project. I have configured swagger and it is working fine, please see my code below.
import swaggerUi from "swagger-ui-express";
import swaggerJsdoc from 'swagger-jsdoc'
const app = express()
const swaggerOptions: swaggerJsdoc.Options = {
definition: {
openapi: "3.0.0",
info: {
title: "REST API Docs",
version: '1.0',
},
components: {
securitySchemas: {
bearerAuth: {
type: "http",
scheme: "bearer",
bearerFormat: "JWT",
},
},
},
security: [
{
bearerAuth: [],
},
],
},
apis: ['src/apis/**/*.controller.ts', 'src/schemas/*.schema.ts'],
};
const swaggerDocs = swaggerJsdoc(swaggerOptions);
app.use(
"/docs",
swaggerUi.serve,
swaggerUi.setup(swaggerDocs, { explorer: true })
);
What i want is to use local swagger.json file, instead on giving apis array apis: ['src/apis/**/*.controller.ts', 'src/schemas/*.schema.ts'],
How can I do that, please help.
something like this should work:
const app = express();
const swaggerUi = require('swagger-ui-express');
try {
const swaggerDoc = require('./your/doc/swagger.json');
app.use('/doc', swaggerUi.serve, swaggerUi.setup(swaggerDoc));
} catch (error) {
console.error('Error loading Swagger json: ', error);
}
app.listen(3000, '0.0.0.0', () => {
console.log(`šŸš€ Server started: http://localhost:3000/doc`);
});

How to resolve 'system:error:invalid-token' In Nexmo Vonage SDK changing to a new app in the same account

I am using "#vonage/server-sdk": "2.10.7-beta-2" package on server to create users in Vonage.
To create the user, I used this API
const Vonage = require('#vonage/server-sdk');
const v = new Vonage({
apiKey: config.voipConfig.key,
apiSecret: config.voipConfig.secret,
applicationId: config.voipConfig.appId,
privateKey: config.voipConfig.privateKeyPath
};
v.users.create({
"name": payload.username,
"display_name": payload.displayName
}, (error: any, result: any) => {
});
Everything was working fine. But when I created a new application in vonage account and used new configs, it started to throw the following error
{
description: 'You did not provide a valid token. Please provide a valid token.',
code: 'system:error:invalid-token'
}
I have checked the details multiple times and not sure what is wrong.
The new credentials are from completely new account.
Any help would be much appreciated.
Looks like you are using the Vonage Conversations API to create a user. In good practice, we usually use dotenv to store our .env variables. If you are using a public github repo, remember to add *.env to your .gitignore.
npm install dotenv
// .env
API_KEY=
API_SECRET=
APPLICATION_ID=
APPLICATION_PRIVATE_KEY_PATH=
TO_NUMBER=<YOUR CELL NUMBER>
VIRTUAL_NUMBER=<VONAGE VIRTUAL NUMBER>
NGROK_URL=https://<URL>.ngrok.io
For testing purposes. Can you make an outbound call with the snippet below? That'll test your credentials.
Make sure to store the private.key in same directory as .env and outbound-call.js
// outbound-call.js
require("dotenv").config();
const API_KEY = process.env.API_KEY;
const API_SECRET = process.env.API_SECRET;
const APPLICATION_ID = process.env.APPLICATION_ID;
const APPLICATION_PRIVATE_KEY_PATH = process.env.APPLICATION_PRIVATE_KEY_PATH;
const TO_NUMBER = process.env.TO_NUMBER;
const VIRTUAL_NUMBER = process.env.VIRTUAL_NUMBER;
if (!API_KEY || !API_SECRET) {
console.log("šŸ”„ API_KEY or API_SECRET missing");
process.exit(1);
}
if (!APPLICATION_ID || !APPLICATION_PRIVATE_KEY_PATH) {
console.log("šŸ”„ APPLICATION_ID or APPLICATION_PRIVATE_KEY_PATH missing");
process.exit(1);
}
if (!TO_NUMBER || !VIRTUAL_NUMBER) {
console.log("šŸ”„ TO_NUMBER or VIRTUAL_NUMBER missing");
process.exit(1);
}
const Vonage = require("#vonage/server-sdk");
const vonage = new Vonage({
apiKey: API_KEY,
apiSecret: API_SECRET,
applicationId: APPLICATION_ID,
privateKey: APPLICATION_PRIVATE_KEY_PATH,
});
vonage.calls.create({
to: [
{
type: "phone",
number: process.env.TO_NUMBER,
},
],
from: {
type: "phone",
number: process.env.VIRTUAL_NUMBER,
},
ncco: [
{
action: "talk",
text: "This is a text to speech call from Vonage",
},
],
});
To test the Conversations API, you will need to enable Voice for your Vonage Application and set the answer Webhook. I use NGROK as well, so it should look like this. https://<URL>.ngrok.io/webhooks/answer
When working with Conversations API, I usually do:
Create a Conversation
Create a User
Create a Member
and put that into the /webhooks/answer
//server.js
require('dotenv').config();
let express = require('express');
let cookieParser = require('cookie-parser');
let logger = require('morgan');
let app = express();
let port = 5001;
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static('public'));
const NGROK_URL = process.env.NGROK_URL;
const Vonage = require('#vonage/server-sdk');
const vonage = new Vonage({
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
applicationId: process.env.APPLICATION_ID,
privateKey: process.env.APPLICATION_PRIVATE_KEY_PATH
});
app.post('/webhooks/answer', async (req, res) => {
console.log('šŸšš answer', req.body);
let result = req.body;
const createCallConversationPromise = (ConvName, ConvDisplayName) => new Promise((resolve, reject) => {
vonage.conversations.create({
"name": ConvName,
"display_name": ConvDisplayName,
}, (error, result) => error ? reject(error) : resolve(result));
});
const createCallUserPromise = (Name, DisplayName) => new Promise((resolve, reject) => {
vonage.users.create({
name: Name,
display_name: DisplayName,
}, (error, result) => error ? reject(error) : resolve(result));
});
const createCallMemberPromise = (ConvId, UserId) => {
vonage.conversations.members.create(ConvId, {
"action": "join",
"user_id": UserId,
"channel": {
"type": "app"
}
}, (error, result) => {
if(error) {
console.log('\nšŸ”„ Error Creating Member', error);
}
else {
console.log('\nāœ… Created Member with ConvId', ConvId, 'and UserId',UserId)
console.log(result);
}
})
};
try {
let ConvName = result.from + result.to + result.conversation_uuid;
console.log('nāœ… ConvName', ConvName);
let ConvDisplayName = result.from + result.to + result.conversation_uuid;
const conversation = await createCallConversationPromise(ConvName, ConvDisplayName);
process.env.CONVERSATION_ID = conversation.id;
console.log('\nāœ… CONVERSATION_ID', process.env.CONVERSATION_ID);
let Name = result.from + result.conversation_uuid;
let DisplayName = result.from;
const callUser = await createCallUserPromise(Name, DisplayName);
console.log('\nāœ… UserId', callUser.id)
let ConvId = conversation.id;
let UserId = callUser.id;
const memberUser = await createCallMemberPromise(ConvId, UserId);
let ncco = [
{
action: "talk",
text: "<speak><lang xml:lang='en-GB'>Welcome to Vonage Development inbound call testing</lang></speak>",
voiceName: "Emma"
},
];
res.json(ncco);
} catch (error) {
console.log("šŸ”„ Error", error);
let ncco = [
{
"action": "talk",
"text": "<speak><lang xml:lang='en-GB'>Error on Process Answer</lang></speak>",
"voiceName": "Emma"
}
];
res.json(ncco);
}
});

nuxtjs apollo-client does not set authorization header

I am trying to create a login functionality using nuxtjs with the nuxtjs apollo-module and nodejs in the backend using apollo-server. I would like to pass the token from the frontend (nuxtjs/apollo-client) to the backend (nodejs/apollo-server).
Signin Function (frontend)
async signin () {
const email = this.email
const password = this.password
try {
const res = await this.$apollo.mutate({
mutation: signIn,
variables: {
email,
password
}
}).then(({ data }) => data && data.signIn)
const token = res.token
await this.$apolloHelpers.onLogin(token)
this.$router.push('/feed')
} catch (err) {
// Error message
}
}
nuxtjs.config (frontend)
apollo: {
clientConfigs: {
default: {
httpEndpoint: 'http://localhost:8000/graphql',
wsEndpoint: 'ws://localhost:8000/graphql',
authenticationType: 'Bearer',
httpLinkOptions: {
credentials: 'include'
},
}
}
Cookie in Browser DevTools
Index File (backend)
const app = express()
const corsConfig = {
origin: 'http://127.0.0.1:3000',
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
credentials: true
}
app.use(cors(corsConfig))
app.use(morgan('dev'))
const getMe = async req => {
const token = req.headers.authorization // <========
console.log(token) // returns 'Bearer undefined'
if (token) {
try {
return await jwt.verify(token, process.env.SECRET)
} catch (e) {
// Error message
}
}
}
const server = new ApolloServer({
introspection: true,
playground: true,
typeDefs: schema,
resolvers,
context: async ({ req }) => {
if (req) {
const me = await getMe(req)
return {
models,
me,
secret: process.env.SECRET,
loaders: {
user: new DataLoader(keys =>
loaders.user.batchUsers(keys, models),
),
},
}
}
},
})
server.applyMiddleware({
app,
path: '/graphql',
cors: false
})
const httpServer = http.createServer(app)
server.installSubscriptionHandlers(httpServer)
const port = process.env.PORT || 8000
sequelize.sync({ force: true }).then(async () => {
createUsers(new Date())
httpServer.listen({ port }, () => {
console.log(`Apollo Server on http://localhost:${port}/graphql`)
})
})
The token is saved in a cookie called 'apollo-token'. However the Authoriation header in the format 'Bearer token' is not set. According to the apollo-client documentation this should be set automatically (https://github.com/nuxt-community/apollo-module#authenticationtype-string-optional-default-bearer).
What am I missing? I would be very thankful for any kind of help!

firebase.json rewrites issue for nodejs/vuejs firebase hosting?

i do not know exactly what problem i'm facing. here is my console out
I have client side and server side. In client side, developing front-end using vuejs. server side used node js/express.js for sending data to front end.
i have already deployed my project into firebase hosting. configured firebase json too.
Client side: client-> service->Api.js
import axios from 'axios'
export default() => {
return axios.create({
baseURL: `https://dev-cloudthrifty-com.firebaseapp.com`
// https://dev-cloudthrifty-com.firebaseapp.com/
// http://localhost:8081
})
}
Client side: vue.config.js
const path = require('path')
module.exports = {
devServer: {
compress: true,
disableHostCheck: true,
},
outputDir: path.resolve(__dirname, '../dist'), // build all the assets inside server/dist folder
pluginOptions: {
'style-resources-loader': {
preProcessor: 'scss',
patterns: [path.resolve(__dirname, './src/styles/global.scss')]
}
},
chainWebpack: config => {
if (config.plugins.has('optimize-css')) {
config.plugins.delete('optimize-css')
}
}
}
Firebase.json
{
"hosting": {
"public": "dist",
"rewrites": [
{ "source": "/", "function": "app"},
{ "source": "**", "destination": "/index.html"}
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"headers": [ {
"source": "**/*.#(eot|otf|ttf|ttc|woff|font.css)",
"headers": [ {
"key": "Access-Control-Allow-Origin",
"value": "*"
} ]
}, {
"source": "**/*.#(jpg|jpeg|gif|png)",
"headers": [ {
"key": "Cache-Control",
"value": "max-age=7200"
} ]
}, {
"source": "404.html",
"headers": [ {
"key": "Cache-Control",
"value": "max-age=300"
} ]
} ],
"cleanUrls": true
}
}
server side: app.js
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const morgan = require('morgan')
var firebase = require('firebase');
const functions = require('firebase-functions');
const axios = require('axios');
const credentials = new Buffer('testing:testing123').toString('base64')
const app = express()
app.use(morgan('combined'))
app.use(bodyParser.json())
app.use(cors())
var Post = require("./models/post");
const firebaseConfig = {
apiKey: "AIzaSyBDwqFKPt4D0eIspjsziweLI0nc49BRDrU",
authDomain: "cloudthrifty-demo.firebaseapp.com",
databaseURL: "https://cloudthrifty-demo.firebaseio.com",
projectId: "cloudthrifty-demo",
storageBucket: "cloudthrifty-demo.appspot.com",
messagingSenderId: "638814042535",
appId: "1:638814042535:web:221da9fcf361554b"
};
firebase.initializeApp(firebaseConfig);
var db = firebase.firestore();
app.get('/GCPScheduler', (req, res) => {
res.send(
[{
title: "Hello World!",
description: "Hi there! How are you?"
}]
)
})
// serve dist folder
if (process.env.NODE_ENV === 'production') {
// Static folder
app.use(express.static(__dirname + '/dist'));
// Handle SPA
app.get('*', (req, res) => res.sendFile(__dirname + '/dist/index.html'));
}
// Add new post
app.post('/list-server', (req, res) => {
var token = req.body.token;
var ccExp = req.body.ccExp;
var cardNumber = req.body.cardNumber;
var currentUserUUID = req.body.currentUserUUID;
var amount = req.body.amount;
console.log(token);
console.log(ccExp);
console.log(cardNumber);
console.log(currentUserUUID);
console.log(amount);
(async() => {
const paymentRequest = await getAuthTokenForThePayment({
account: cardNumber,
merchid: '496160873888',
amount: amount, // Smallest currency unit. e.g. 100 cents to charge $1.00
expiry: ccExp,
currency: 'USD'
});
const charge = await makeCharge({
merchid: paymentRequest.data.merchid,
retref: paymentRequest.data.retref
});
console.log(charge);
console.log(charge.data.respstat)
if (charge.data.respstat == 'A'){
var data = db.collection('transactionTable').doc(charge.data.retref);
var setAlan = data.set({
'respstat': charge.data.respstat,
'retref': charge.data.retref,
'account': charge.data.account,
'token': charge.data.token,
'batchid': charge.data.batchid,
'amount': charge.data.amount,
'resptext': charge.data.resptext,
'respcode': charge.data.respcode,
'commcard': charge.data.commcard,
'setlstat': charge.data.setlstat,
});
res.send(charge.data.respstat);
} else if(charge.data.respstat == 'B'){
console.log("Declined");
res.send(charge.data.respstat);
}else if(charge.data.respstat == 'C'){
console.log("Retry");
res.send(charge.data.respstat);
}
})();
})

Resources