json-crdt-repo
Version:
JSON CRDT server and syncing local-first browser client
91 lines (90 loc) • 3.67 kB
JavaScript
;
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;