strapi-plugin-io
Version:
A plugin for Strapi CMS that provides the ability for Socket IO integration
90 lines (73 loc) • 2.38 kB
JavaScript
const { Server } = require('socket.io');
const { handshake } = require('../middleware');
const { getService } = require('../utils/getService');
const { pluginId } = require('../utils/pluginId');
const { API_TOKEN_TYPE } = require('../utils/constants');
class SocketIO {
constructor(options) {
this._socket = new Server(strapi.server.httpServer, options);
const { hooks } = strapi.config.get(`plugin.${pluginId}`);
hooks.init?.({ strapi, $io: this });
this._socket.use(handshake);
}
// eslint-disable-next-line no-unused-vars
async emit({ event, schema, data: rawData }) {
const sanitizeService = getService({ name: 'sanitize' });
const strategyService = getService({ name: 'strategy' });
const transformService = getService({ name: 'transform' });
// account for unsaved single content type being null
if (!rawData) {
return;
}
const eventName = `${schema.singularName}:${event}`;
for (const strategyType in strategyService) {
if (Object.hasOwnProperty.call(strategyService, strategyType)) {
const strategy = strategyService[strategyType];
const rooms = await strategy.getRooms();
for (const room of rooms) {
const permissions = room.permissions.map(({ action }) => ({ action }));
const ability = await strapi.contentAPI.permissions.engine.generateAbility(permissions);
if (room.type === API_TOKEN_TYPE.FULL_ACCESS || ability.can(schema.uid + '.' + event)) {
// sanitize
const sanitizedData = await sanitizeService.output({
data: rawData,
schema,
options: {
auth: {
name: strategy.name,
ability,
strategy: {
verify: strategy.verify,
},
credentials: strategy.credentials?.(room),
},
},
});
const roomName = strategy.getRoomName(room);
// transform
const data = transformService.response({ data: sanitizedData, schema });
// emit
this._socket.to(roomName.replace(' ', '-')).emit(eventName, { ...data });
}
}
}
}
}
async raw({ event, data, rooms }) {
let emitter = this._socket;
// send to all specified rooms
if (rooms && rooms.length) {
rooms.forEach((r) => {
emitter = emitter.to(r);
});
}
emitter.emit(event, { data });
}
get server() {
return this._socket;
}
}
module.exports = {
SocketIO,
};
;