94 lines
2.8 KiB
TypeScript
94 lines
2.8 KiB
TypeScript
import { App } from '@kevisual/router';
|
||
import { useConfig } from '@kevisual/use-config';
|
||
import { dynamicImport } from './lib/dynamic-import.ts';
|
||
import { redisPublisher, redisSubscriber, redis } from './modules/redis.ts';
|
||
import { minioClient } from './modules/minio.ts';
|
||
import { sequelize } from './modules/sequelize.ts';
|
||
import { useContextKey, useContext } from '@kevisual/use-config/context';
|
||
useConfig();
|
||
export const emit = (channel: string, message?: any) => {
|
||
redisPublisher.publish(channel, JSON.stringify(message));
|
||
};
|
||
export { redis, minioClient, sequelize };
|
||
|
||
const init = () => {
|
||
console.log('init app', global.context);
|
||
return new App<{ import: any; emit: typeof emit; sequelize: typeof sequelize }>({
|
||
serverOptions: {
|
||
cors: {
|
||
origin: '*',
|
||
},
|
||
},
|
||
io: true,
|
||
routerContext: {
|
||
import: dynamicImport,
|
||
emit,
|
||
sequelize,
|
||
},
|
||
});
|
||
};
|
||
export const app = useContextKey('app', init);
|
||
// @ts-ignore
|
||
// app.name = 'main-app';
|
||
// console.log('app context', global.context);
|
||
const clients = [];
|
||
// 订阅频道 pageEdit, container 单个页面预览 container 整个页面预览
|
||
type ClientData = {
|
||
cid?: string; // container id
|
||
pid?: string[]; // page id
|
||
cids?: string[]; // container id
|
||
type: 'page' | 'container' | 'flow';
|
||
};
|
||
type MessageData = {
|
||
source: 'container';
|
||
data: any;
|
||
operation?: 'edit';
|
||
};
|
||
redisSubscriber.subscribe('pageEdit', () => {
|
||
console.log('Subscribed to Redis data-updates channel');
|
||
});
|
||
redisSubscriber.on('message', (channel, message) => {
|
||
if (channel !== 'pageEdit') return;
|
||
const m = JSON.parse(message) as MessageData;
|
||
clients.forEach((client) => {
|
||
const data = client.data as any;
|
||
const { cid, cids = [], pid } = data || {};
|
||
const wrapper = (data: any) => {
|
||
const res = {
|
||
type: 'pageEdit',
|
||
source: 'container',
|
||
data,
|
||
pid,
|
||
};
|
||
return JSON.stringify(res);
|
||
};
|
||
const { source, data: mData } = m; // 拆包
|
||
if (source === 'container') {
|
||
if (cid === mData?.id) {
|
||
client.ws.send(wrapper(mData));
|
||
} else if (cids.includes(mData?.id)) {
|
||
client.ws.send(wrapper(mData));
|
||
}
|
||
}
|
||
// 其他操作 暂时 不处理
|
||
// TODO
|
||
});
|
||
});
|
||
app.io.addListener('subscribe', async ({ data, end, ws }) => {
|
||
const { type } = data || {};
|
||
if (type === 'pageEdit') {
|
||
clients.push({ ws, data: data.data }); // 拆包,里面包含的type信息,去掉
|
||
end({ code: 200, data: 'subscribe success' });
|
||
} else if (type === 'unsubscribe') {
|
||
const index = clients.findIndex((client) => client.ws === ws);
|
||
clients.splice(index, 1);
|
||
end({ code: 200, data: 'unsubscribe success' });
|
||
} else {
|
||
end({ code: 404, data: 'subscribe fail' });
|
||
}
|
||
ws.on('close', () => {
|
||
const index = clients.findIndex((client) => client.ws === ws);
|
||
clients.splice(index, 1);
|
||
});
|
||
});
|