@wordpress/sync
Version:
130 lines (119 loc) • 4.46 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createSyncProvider = void 0;
var Y = _interopRequireWildcard(require("yjs"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/**
* External dependencies
*/
// @ts-ignore
/** @typedef {import('./types').ObjectType} ObjectType */
/** @typedef {import('./types').ObjectID} ObjectID */
/** @typedef {import('./types').ObjectConfig} ObjectConfig */
/** @typedef {import('./types').CRDTDoc} CRDTDoc */
/** @typedef {import('./types').ConnectDoc} ConnectDoc */
/** @typedef {import('./types').SyncProvider} SyncProvider */
/**
* Create a sync provider.
*
* @param {ConnectDoc} connectLocal Connect the document to a local database.
* @param {ConnectDoc} connectRemote Connect the document to a remote sync connection.
* @return {SyncProvider} Sync provider.
*/
const createSyncProvider = (connectLocal, connectRemote) => {
/**
* @type {Record<string,ObjectConfig>}
*/
const config = {};
/**
* @type {Record<string,Record<string,()=>void>>}
*/
const listeners = {};
/**
* @type {Record<string,Record<string,CRDTDoc>>}
*/
const docs = {};
/**
* Registers an object type.
*
* @param {ObjectType} objectType Object type to register.
* @param {ObjectConfig} objectConfig Object config.
*/
function register(objectType, objectConfig) {
config[objectType] = objectConfig;
}
/**
* Fetch data from local database or remote source.
*
* @param {ObjectType} objectType Object type to load.
* @param {ObjectID} objectId Object ID to load.
* @param {Function} handleChanges Callback to call when data changes.
*/
async function bootstrap(objectType, objectId, handleChanges) {
const doc = new Y.Doc();
docs[objectType] = docs[objectType] || {};
docs[objectType][objectId] = doc;
const updateHandler = () => {
const data = config[objectType].fromCRDTDoc(doc);
handleChanges(data);
};
doc.on('update', updateHandler);
// connect to locally saved database.
const destroyLocalConnection = await connectLocal(objectId, objectType, doc);
// Once the database syncing is done, start the remote syncing
if (connectRemote) {
await connectRemote(objectId, objectType, doc);
}
const loadRemotely = config[objectType].fetch;
if (loadRemotely) {
loadRemotely(objectId).then(data => {
doc.transact(() => {
config[objectType].applyChangesToDoc(doc, data);
});
});
}
listeners[objectType] = listeners[objectType] || {};
listeners[objectType][objectId] = () => {
destroyLocalConnection();
doc.off('update', updateHandler);
};
}
/**
* Fetch data from local database or remote source.
*
* @param {ObjectType} objectType Object type to load.
* @param {ObjectID} objectId Object ID to load.
* @param {any} data Updates to make.
*/
async function update(objectType, objectId, data) {
const doc = docs[objectType][objectId];
if (!doc) {
throw 'Error doc ' + objectType + ' ' + objectId + ' not found';
}
doc.transact(() => {
config[objectType].applyChangesToDoc(doc, data);
});
}
/**
* Stop updating a document and discard it.
*
* @param {ObjectType} objectType Object type to load.
* @param {ObjectID} objectId Object ID to load.
*/
async function discard(objectType, objectId) {
if (listeners?.[objectType]?.[objectId]) {
listeners[objectType][objectId]();
}
}
return {
register,
bootstrap,
update,
discard
};
};
exports.createSyncProvider = createSyncProvider;
//# sourceMappingURL=provider.js.map