UNPKG

json-crdt-server

Version:

JSON CRDT server and syncing local-first browser client

74 lines (73 loc) 3.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.upd = void 0; const schema_1 = require("../schema"); const upd = ({ t, services }) => (r) => { const Request = t.Object(t.prop('id', schema_1.BlockIdRef).options({ title: 'Document ID', description: 'The ID of the document to apply the patch to.', }), t.prop('batch', schema_1.BlockBatchPartialRef).options({ title: 'Batch', description: 'The batch of changes to apply to the document.', }), t.propOpt('create', t.bool).options({ title: 'Create, if not Exists', description: 'If true, creates a new document if it does not exist.', }), t.propOpt('seq', schema_1.BlockCurRef).options({ title: 'Sequence Number', description: 'The last client known sequence number. The server will return history starting from this sequence number.', }), t.propOpt('clientId', t.Number({ format: 'u32' })).options({ title: 'Client ID', description: 'Browser (client) ID, a unique ID of a specific browser instance. If not provided, the server will use it when propagating changes, so that subscriptions can filter out updates of own client. If set to 0, the server will not use it.', })); const Response = t.Object(t.prop('batch', schema_1.BlockBatchPartialReturnRef).options({ title: 'Committed Batch Parts', description: 'Parts of committed batch which were generated on the server.', }), t.propOpt('pull', t.Object(t.prop('batches', t.Array(schema_1.BlockBatchRef)).options({ title: 'Batches', description: 'The list of batches that happened after the given sequence number.', }), t.propOpt('snapshot', schema_1.BlockSnapshotRef).options({ title: 'Snapshot', description: 'The snapshot of the block, to which the batches can be applied to get the current state of the block.', })))); const Func = t.Function(Request, Response).options({ title: 'Edit Block', intro: 'Applies patches to an existing block.', description: 'Applies patches to an existing document and returns the latest concurrent changes.', }); return r.prop('block.upd', Func, async ({ id, batch, create, seq, clientId = 0 }) => { const blocks = services.blocks; const res = await blocks.edit(id, batch, !!create, clientId); const response = { batch: { seq: res.batch.seq, ts: res.batch.ts, }, }; let pull; if (typeof seq === 'number') { const diff = res.batch.seq - seq; if (diff <= 1) { pull = { batches: [] }; } else { const needsSnapshot = diff > 100; let min, max, limit; if (needsSnapshot) { min = res.batch.seq - 100; max = res.batch.seq - 1; limit = max - min + 1; } else { min = seq + 1; max = res.batch.seq - 1; limit = max - min + 1; } pull = (await blocks.scan(id, needsSnapshot, min, limit)); } } if (pull) response.pull = pull; return response; }); }; exports.upd = upd;