Add a live edit mode
continuous-integration/drone/push Build is passing Details

pull/5/head
Clément FRÉVILLE 11 months ago
parent b58317ae88
commit ef726bc789

@ -1,6 +1,6 @@
{
"typescript": {
"quoteStyle": "preferSingle"
"quoteStyle": "preferDouble"
},
"includes": ["src/**/*.{ts,tsx,js,jsx,cjs,mjs,json}"],
"excludes": [

@ -12,8 +12,11 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@codemirror/collab": "^6.1.1",
"@codemirror/state": "^6.4.1",
"@fastify/cors": "^9.0.0",
"@fastify/type-provider-typebox": "^4.0.0",
"@fastify/websocket": "^10.0.1",
"@sinclair/typebox": "^0.32.9",
"fastify": "^4.27.0",
"nanoid": "^5.0.4",

@ -1,14 +1,14 @@
import cors from "@fastify/cors";
import websocket, { WebSocket } from '@fastify/websocket';
import { Type, TypeBoxTypeProvider } from "@fastify/type-provider-typebox";
import Fastify, { FastifyReply, FastifyRequest } from "fastify";
import Fastify, { FastifyReply } from "fastify";
import { nanoid } from "nanoid";
import { allocateBuffer, IMAGES } from "runner";
import { allocateBuffer, getRunner } from "runner";
import { Pull, Push } from "zeromq";
import { ChangeSet, Text } from "@codemirror/state";
import { Update, rebaseUpdates } from "@codemirror/collab";
import * as db from "./database";
console.log(IMAGES.logo);
const sender = new Push();
await sender.bind(`tcp://127.0.0.1:5557`);
const receiver = new Pull();
@ -17,14 +17,85 @@ await receiver.bind(`tcp://127.0.0.1:5558`);
const clients: Record<string, FastifyReply> = {};
const generateId = () => nanoid(32);
let updates: Update[] = [];
let doc = Text.of(['']);
const liveClients: WebSocket[] = [];
function send(socket: WebSocket, requestId: number, payload: unknown) {
const response = {
_request: requestId,
payload
};
socket.send(JSON.stringify(response));
}
const fastify = Fastify({
logger: true,
}).withTypeProvider<TypeBoxTypeProvider>();
await fastify.register(cors, {
origin: process.env.ALLOW_ORIGIN || "*",
origin: process.env.ALLOW_ORIGIN || '*',
});
fastify.register(websocket);
fastify.get("/live", { websocket: true }, (socket, req) => {
liveClients.push(socket);
socket.on("message", message => {
const data = JSON.parse(message.toString());
const requestId = data._request;
if (data.type === "pullUpdates") {
send(socket, requestId, updates.slice(data.version))
} else if (data.type === "pushUpdates") {
let received = data.updates.map((json: any) => ({
clientID: json.clientID,
changes: ChangeSet.fromJSON(json.changes)
}))
if (data.version != updates.length) {
received = rebaseUpdates(received, updates.slice(data.version))
}
for (let update of received) {
updates.push(update)
doc = update.changes.apply(doc)
}
send(socket, requestId, received.map((update: any) => ({
clientID: update.clientID,
changes: update.changes.toJSON()
})));
} else if (data.type == "getDocument") {
send(socket, requestId, {version: updates.length, doc: doc.toString()})
}
})
})
/* Database */
fastify.post("/run", {
schema: {
body: Type.Object({
code: Type.String(),
language: Type.String(),
}),
},
}, (req, reply) => {
const { code, language } = req.body;
const runner = getRunner(language);
if (runner === null) {
return reply.status(422).send({ error: "Invalid language" });
}
const jobId = generateId();
const buffer = allocateBuffer(jobId, code, runner);
reply.raw.writeHead(200, {
"Content-Type": "text/event-stream",
Connection: "keep-alive",
"Cache-Control": "no-cache",
"Access-Control-Allow-Origin": process.env.ALLOW_ORIGIN || "*",
});
reply.raw.on("close", () => {
delete clients[jobId];
});
sender.send(buffer).then(() => {
reply.raw.write("event: connected\n");
reply.raw.write(`data: ${jobId}\n`);
reply.raw.write("id: 0\n\n");
});
clients[jobId] = reply;
});
/* Création du répertoire de la base de données s'il n'existe pas */
db.createDbDirectory();

Loading…
Cancel
Save