@jusbid/redis 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +60 -2
- package/package.json +1 -1
- package/redis-client.js +44 -0
- package/socket-manager.js +39 -0
- package/socketRedisClient.js +1 -1
package/index.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
const { createClient } = require('redis');
|
|
2
2
|
const { logger } = require('@jusbid/logger');
|
|
3
|
-
const {
|
|
3
|
+
const {
|
|
4
|
+
closeRedisClients,
|
|
4
5
|
initRedisClients,
|
|
5
6
|
getRedisClients,
|
|
6
7
|
publish,
|
|
7
8
|
subscribe
|
|
8
9
|
} = require('./socketRedisClient');
|
|
9
10
|
|
|
11
|
+
const { initSocketManager, getIO, emitEvent } = require("./socket-manager");
|
|
12
|
+
const { SOCKET_EVENTS } = require('./redis-client');
|
|
13
|
+
|
|
14
|
+
|
|
10
15
|
const redisOptions = {};
|
|
11
16
|
|
|
12
17
|
// Build Redis connection options dynamically
|
|
@@ -882,6 +887,56 @@ const deleteByPattern = async (pattern) => {
|
|
|
882
887
|
return keys.length;
|
|
883
888
|
}
|
|
884
889
|
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* Create Socket.IO server
|
|
893
|
+
*/
|
|
894
|
+
const createSocketServer = ({
|
|
895
|
+
httpServer,
|
|
896
|
+
cors = {
|
|
897
|
+
origin: process.env.CORS_ORIGIN,
|
|
898
|
+
methods: ["GET", "POST"],
|
|
899
|
+
},
|
|
900
|
+
path = "/socket.io",
|
|
901
|
+
verifyToken, // (token, socket) => Promise<payload> | payload
|
|
902
|
+
} = {}) => {
|
|
903
|
+
if (!httpServer) {
|
|
904
|
+
throw new Error("httpServer is required to create socket server");
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
const socketServer = new Server(httpServer, {
|
|
908
|
+
cors,
|
|
909
|
+
path,
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
// Token handshake middleware
|
|
913
|
+
socketServer.use(async (socket, next) => {
|
|
914
|
+
try {
|
|
915
|
+
const token =
|
|
916
|
+
socket.handshake.auth?.token ||
|
|
917
|
+
socket.handshake.headers?.authorization?.replace("Bearer ", "");
|
|
918
|
+
|
|
919
|
+
if (!token) {
|
|
920
|
+
return next(new Error("AUTH_TOKEN_MISSING"));
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
if (typeof verifyToken !== "function") {
|
|
924
|
+
throw new Error("verifyToken function is required to authenticate sockets");
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
const decoded = await verifyToken(token, socket);
|
|
928
|
+
socket.data.user = decoded; // attach identity for later use
|
|
929
|
+
|
|
930
|
+
next();
|
|
931
|
+
} catch (err) {
|
|
932
|
+
next(new Error("AUTH_TOKEN_INVALID"));
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
return socketServer;
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
|
|
885
940
|
module.exports = {
|
|
886
941
|
redisClient,
|
|
887
942
|
get,
|
|
@@ -911,6 +966,9 @@ module.exports = {
|
|
|
911
966
|
initRedisClients,
|
|
912
967
|
getRedisClients,
|
|
913
968
|
publish,
|
|
914
|
-
subscribe
|
|
969
|
+
subscribe,
|
|
915
970
|
|
|
971
|
+
initSocketManager, getIO, emitEvent,
|
|
972
|
+
createSocketServer,
|
|
973
|
+
SOCKET_EVENTS
|
|
916
974
|
};
|
package/package.json
CHANGED
package/redis-client.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// redis-client.js
|
|
2
|
+
const { createClient } = require("@jusbid/redis");
|
|
3
|
+
|
|
4
|
+
const createRedisClients = async ({ url = process.env.REDIS_URL } = {}) => {
|
|
5
|
+
const pubClient = createClient({ url });
|
|
6
|
+
const subClient = pubClient.duplicate();
|
|
7
|
+
|
|
8
|
+
pubClient.on("error", (err) => console.error("Redis Pub Client Error:", err));
|
|
9
|
+
subClient.on("error", (err) => console.error("Redis Sub Client Error:", err));
|
|
10
|
+
|
|
11
|
+
await Promise.all([pubClient.connect(), subClient.connect()]);
|
|
12
|
+
|
|
13
|
+
return { pubClient, subClient };
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Socket events
|
|
18
|
+
*/
|
|
19
|
+
const SOCKET_EVENTS = Object.freeze({
|
|
20
|
+
CONNECT: "connect",
|
|
21
|
+
DISCONNECT: "disconnect",
|
|
22
|
+
ERROR: "error",
|
|
23
|
+
|
|
24
|
+
BOOKING_CREATED: "booking.created",
|
|
25
|
+
BOOKING_UPDATED: "booking.updated",
|
|
26
|
+
BOOKING_CANCELLED: "booking.cancelled",
|
|
27
|
+
|
|
28
|
+
PROPERTY_CREATED: "property.created",
|
|
29
|
+
PROPERTY_UPDATED: "property.updated",
|
|
30
|
+
|
|
31
|
+
ROOM_CREATED: "room.created",
|
|
32
|
+
ROOM_UPDATED: "room.updated",
|
|
33
|
+
|
|
34
|
+
INVENTORY_UPDATED: "inventory.updated",
|
|
35
|
+
|
|
36
|
+
PAYMENT_SUCCESS: "payment.success",
|
|
37
|
+
PAYMENT_FAILED: "payment.failed",
|
|
38
|
+
|
|
39
|
+
NOTIFICATION: "notification",
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
module.exports = { createRedisClients, SOCKET_EVENTS };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
let ioInstance = null;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Initialize and store the io instance (call this ONCE, in index.js)
|
|
5
|
+
*/
|
|
6
|
+
const initSocketManager = (socketServerInstance) => {
|
|
7
|
+
if (!socketServerInstance) {
|
|
8
|
+
throw new Error("Socket server instance is required to initialize manager");
|
|
9
|
+
}
|
|
10
|
+
ioInstance = socketServerInstance;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get the stored io instance (call this from ANY other file)
|
|
15
|
+
*/
|
|
16
|
+
const getIO = () => {
|
|
17
|
+
if (!ioInstance) {
|
|
18
|
+
throw new Error("Socket.IO not initialized. Call initSocketManager first.");
|
|
19
|
+
}
|
|
20
|
+
return ioInstance;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Emit from anywhere, without needing direct io access
|
|
25
|
+
*/
|
|
26
|
+
const emitEvent = (event, data, room = null) => {
|
|
27
|
+
const io = getIO();
|
|
28
|
+
if (room) {
|
|
29
|
+
io.to(room).emit(event, data);
|
|
30
|
+
} else {
|
|
31
|
+
io.emit(event, data);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
initSocketManager,
|
|
37
|
+
getIO,
|
|
38
|
+
emitEvent,
|
|
39
|
+
};
|
package/socketRedisClient.js
CHANGED