UNPKG

json-crdt-repo

Version:

JSON CRDT server and syncing local-first browser client

91 lines (90 loc) 3.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EditSessionFactory = void 0; const json_crdt_1 = require("json-joy/lib/json-crdt"); const EditSession_1 = require("./EditSession"); const timeout_1 = require("thingies/lib/timeout"); class EditSessionFactory { constructor(opts) { this.opts = opts; } /** * Creates a new editing session synchronously (immediately). If the block * with a given ID already exists, it asynchronously synchronizes the local * and remote state. */ make(opts) { const { id, schema, pull = true } = opts; const factoryOpts = this.opts; const model = json_crdt_1.Model.create(void 0, factoryOpts.sid); const session = new EditSession_1.EditSession(factoryOpts.repo, id, model, undefined, opts.session); if (schema) { const sessionModel = session.model; sessionModel.setSchema(schema); sessionModel.api.flush(); } let sync; if (pull && !session.log.patches.size()) { sync = session .sync() .then(() => { }) .catch(() => { }); } session.log.end.api.autoFlush(); return { session, sync }; } /** * Load block from the local repo. Creates a new editing session * asynchronously from an existing local block. * * It is also possible to block on remote state check in case the block does * not exist locally, or to pull the latest state from the remote. */ async load(opts) { const id = opts.id; const repo = this.opts.repo; try { const { model, cursor } = await repo.get({ id }); const session = new EditSession_1.EditSession(repo, id, model, cursor, opts.session); session.log.end.api.autoFlush(); return session; } catch (error) { if (error instanceof Error && error.message === 'NOT_FOUND') { const remote = opts.remote; if (remote) { const timeoutMs = remote.timeout; try { const { model, cursor } = await (typeof timeoutMs === 'number' ? (0, timeout_1.timeout)(timeoutMs, repo.pull(id)) : repo.pull(id)); if (remote.throwIf === 'exists') throw new Error('EXISTS'); const session = new EditSession_1.EditSession(repo, id, model, cursor, opts.session); session.log.end.api.autoFlush(); return session; } catch (error) { if (!!error && typeof error === 'object' && error.message === 'TIMEOUT') { if (!opts.make) throw error; } else if (!!error && typeof error === 'object' && (error.message === 'NOT_FOUND' || error.code === 'NOT_FOUND')) { if (remote.throwIf === 'missing') throw error; } else throw error; } } if (opts.make) return this.make({ session: opts.session, ...opts.make, id }).session; } throw error; } } } exports.EditSessionFactory = EditSessionFactory;