diff --git a/packages/json/src/server/index.js b/packages/json/src/server/index.js index 5bf241a..ecf917f 100644 --- a/packages/json/src/server/index.js +++ b/packages/json/src/server/index.js @@ -1,7 +1,51 @@ +import fs from 'fs'; +import {join} from 'path'; +import {promisify} from 'util'; + import {decorateWithLatus} from '@latus/core'; +import {applyPatch} from 'fast-json-patch'; + +const readFile = promisify(fs.readFile); +const writeFile = promisify(fs.writeFile); export default { hooks: { + '@latus/core/starting': (latus) => { + latus.set('%patches', []); + const flushPatches = async () => { + const patches = latus.get('%patches'); + if (patches.length > 0) { + const patching = {}; + while (patches.length > 0) { + const {patch, project, uri} = patches.shift(); + const {decode, encode} = latus.get('%resource-controllers')(uri); + const path = join(process.cwd(), 'projects', project, uri); + if (!patching[path]) { + patching[path] = new Promise((resolve) => { + readFile(path).then((buffer) => { + resolve({ + decode, + json: encode(buffer, latus), + }); + }); + }); + } + // eslint-disable-next-line no-await-in-loop + const {json} = await patching[path]; + applyPatch(json, patch); + } + const entries = Object.entries(patching); + for (let i = 0; i < entries.length; i++) { + const [path, promise] = entries[i]; + // eslint-disable-next-line no-await-in-loop + const {decode, json} = await promise; + writeFile(path, decode(json, latus)); + } + } + setTimeout(flushPatches, 0); + }; + setTimeout(flushPatches, 0); + }, '@latus/socket/packets.decorate': decorateWithLatus( require.context('./packets/decorators', false, /\.js$/), ), diff --git a/packages/json/src/server/packets/decorators/action.js b/packages/json/src/server/packets/decorators/action.js index 641a9c0..3eaace4 100644 --- a/packages/json/src/server/packets/decorators/action.js +++ b/packages/json/src/server/packets/decorators/action.js @@ -1,27 +1,12 @@ -import fs from 'fs'; -import {join} from 'path'; -import {promisify} from 'util'; - -import {applyPatch} from 'fast-json-patch'; - import {patchJsonResource} from '../../../state/json'; -const readFile = promisify(fs.readFile); -const writeFile = promisify(fs.writeFile); - export default (Action, latus) => class ProjectAction extends Action { static async respond(packet, socket) { const {data: {type, payload}} = packet; switch (type) { case patchJsonResource.toString(): { - const {patch, project, uri} = payload; - const path = join(process.cwd(), 'projects', project, uri); - const buffer = await readFile(path); - const {decode, encode} = latus.get('%resource-controllers')(uri); - const json = encode(buffer, latus); - applyPatch(json, patch); - writeFile(path, decode(json, latus)); + latus.get('%patches').push(payload); break; } default: