I'm making a basic restaurant ordering web app for fun/learning purposes using node/express for my backend and react as my frontend. I've based my app on a mix of various YT tutorials including the ones Dave Gray to structure my project.
Currently I'm at the stage where I'm trying to implement notifications using SocketIO (the idea that the server will push notifications down to the clients to notify them of certain events such as an order being made).
My current progress is here: https://github.com/kevin-rph-lee/noodlebox/tree/socket-notifications
The issue I'm having is I'm trying to figure out the best way to pass my SocketIO object down to one of my controllers (specifically the orders controller).
My current structure is:
server.js --> orders.js (route) --> ordersController.js (controller)
Currently in my main server.js file I have initialized the io object for SocketIO (as seen below)
require('dotenv').config();
const WebSocketServer = require("ws").Server
var http = require("http")
const express = require('express');
const path = require('path');
const PORT = process.env.PORT || 3001;
const app = express();
const morgan = require('morgan');
const cors = require('cors');
const corsOptions = require('./config/corsOptions');
const credentials = require('./middleware/credentials');
const cookieParser = require('cookie-parser');
// Creating a new socketio server
const server = require('http').createServer(app);
const io = require('socket.io')(server);
//Numbers of users connected. Initially 0
let clientsConnected = 0
io.on('connection', function(socket){
//Client connecting, incrementing client counter
clientsConnected++
console.log('Client connected. Total clients connected ' + clientsConnected)
//When a message is recieved from a client, echo it to all other clients connected
socket.on("message from client", (arg) => {
console.log('reieved')
console.log(arg)
// socket.broadcast.emit('message to client', arg)
// socket.to(1).emit('message to client', 'enjoy the game')
io.in(1).emit('message to client', 'enjoy the game')
});
socket.on("join", (userID) => {
socket.join(userID)
console.log('Rooms:')
console.log(socket.rooms)
});
socket.on("leave", (userID) => {
socket.leave(userID)
console.log('Rooms:')
console.log(socket.rooms)
});
//Deincrement the counter when the client disconnects
socket.on("disconnect", (reason) => {
clientsConnected--
console.log('Client connected. Total clients connected ' + clientsConnected)
});
})
// PG database client/connection setup
const { Pool } = require('pg');
const dbParams = require('./lib/db.js');
const db = new Pool(dbParams);
db.connect();
// Load the logger first so all (static) HTTP requests are logged to STDOUT
// 'dev' = Concise output colored by response status for development use.
// The :status token will be colored red for server error codes, yellow for client error codes, cyan for redirection codes, and uncolored for all other codes.
app.use(morgan('dev'));
app.use(credentials);
app.use(cors(corsOptions));
app.use(express.json()); // => allows us to access the req.body
//middleware for cookies
app.use(cookieParser());
if (process.env.NODE_ENV === 'production') {
//server static content
//npm run build
app.use(express.static(path.join(__dirname, 'client/build')));
}
console.log(__dirname);
console.log(path.join(__dirname, 'client/build'));
// Separated Routes for each Resource
const usersRoutes = require('./routes/users');
const refreshRoutes = require('./routes/refresh');
const menuItemsRoutes = require('./routes/menuItems');
const ordersRoutes = require('./routes/orders');
// Resource routes
app.use('/users', usersRoutes());
app.use('/refresh', refreshRoutes());
app.use('/menuItems', menuItemsRoutes());
app.use('/orders', ordersRoutes());
// All other GET requests not handled before will return our React app
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '/client/build/index.html'));
});
server.listen(PORT);
I am now trying to figure out how to pass the io object down to my orders route, and then from the route to the controller.
Within server.js, to pass io down to the route it was thinking it would be something like...
app.use('/orders', ordersRoutes(io));
But within the order route itself I get stuck
order.js
const express = require('express');
const router = express.Router();
const ordersController = require('../controllers/ordersController')
const verifyJWT = require('../middleware/verifyJWT')
const verifyRoles = require('../middleware/verifyRoles');
module.exports = () => {
//Get order
router.route('/')
.get(verifyJWT, verifyRoles('user', 'admin'),ordersController.getOrders)
//Create order
router.route('/')
.post(verifyJWT, verifyRoles('user', 'admin'), ordersController.createOrder)
return router;
};
To receive the io object from server.js I'm thinking I would need to modify the module.exports line so it would look like:
module.exports = (io) = {
but at that point I'm stuck on how I can pass it down one more layer from the route file to the controller file. The idea is I want the io functionality (e.g broadcasting a SocketIO message) to be available to me within the controllers file. In particular I want the ability to broadcast a message when a certain axios request is made from a connected client (e.g broadcast a SocketIO message when an axios POST request is made to create an order).
I was hoping someone could help me out with a potential way to move forward, or let me know if I'm going down the completely wrong path.
Thank you