UNPKG

@wordpress/sync

Version:
130 lines (119 loc) 4.46 kB
"use strict"; 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