UNPKG

@sanity/document-store

Version:

Sanity / gradient document store

156 lines (119 loc) 6.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createObservableBufferedDocument = exports.snapshotEventFrom = void 0; var _mutator = require("@sanity/mutator"); var _rxjs = require("rxjs"); var _operators = require("rxjs/operators"); function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } var snapshotEventFrom = snapshot => ({ type: 'snapshot', document: snapshot }); // This is an observable interface for BufferedDocument in an attempt // to make it easier to work with the api provided by it exports.snapshotEventFrom = snapshotEventFrom; var createObservableBufferedDocument = (serverEvents$, doCommit) => { // Incoming local actions (e.g. a request to mutate, a request to commit pending changes, etc.) var actions$ = new _rxjs.Subject(); // Stream of events that has happened with documents (e.g. a mutation that has been applied, a rebase). // These are "after the fact" events and also includes the next document state. var updates$ = new _rxjs.Subject(); // Stream of commit requests. Must be handled by a commit handler var commits$ = new _rxjs.Subject(); var createInitialBufferedDocument = snapshot => { var bufferedDocument = new _mutator.BufferedDocument(snapshot); bufferedDocument.onMutation = (_ref) => { var mutation = _ref.mutation, remote = _ref.remote; updates$.next({ type: 'mutation', document: bufferedDocument.LOCAL, mutations: mutation.mutations, origin: remote ? 'remote' : 'local' }); }; bufferedDocument.onRebase = edge => { updates$.next({ type: 'rebase', document: edge }); }; bufferedDocument.commitHandler = opts => { var _opts$mutation$params = opts.mutation.params, resultRev = _opts$mutation$params.resultRev, mutation = _objectWithoutProperties(_opts$mutation$params, ["resultRev"]); commits$.next({ onSuccess: opts.success, onError: opts.failure, payload: mutation }); }; return bufferedDocument; }; var bufferedDocument$ = serverEvents$.pipe((0, _operators.scan)((bufferedDocument, serverEvent) => { if (serverEvent.type === 'snapshot') { if (bufferedDocument) { // we received a new snapshot and already got an old one. When we receive a snapshot again // it is usually because the connection has been down. Attempt to save pending changes (if any) bufferedDocument.commit(); } return createInitialBufferedDocument(serverEvent.document || null); } if (!bufferedDocument) { // eslint-disable-next-line no-console console.warn('Ignoring event of type "%s" since buffered document has not yet been set up with snapshot', serverEvent.type); return bufferedDocument; } if (serverEvent.type === 'mutation') { bufferedDocument.arrive(new _mutator.Mutation(serverEvent)); } else if (serverEvent.type !== 'reconnect') { // eslint-disable-next-line no-console console.warn('Received unexpected server event of type "%s"', serverEvent.type); } return bufferedDocument; }, null), (0, _operators.publishReplay)(1), (0, _operators.refCount)()); // this is where the side effects mandated by local actions actually happens var actionHandler$ = actions$.pipe((0, _operators.withLatestFrom)(bufferedDocument$), (0, _operators.map)((_ref2) => { var _ref3 = _slicedToArray(_ref2, 2), action = _ref3[0], bufferedDocument = _ref3[1]; if (action.type === 'mutation') { bufferedDocument.add(new _mutator.Mutation({ mutations: action.mutations })); } if (action.type === 'commit') { bufferedDocument.commit(); } return null; }), (0, _operators.filter)(Boolean), (0, _operators.share)()); var emitAction = action => actions$.next(action); var addMutations = mutations => emitAction({ type: 'mutation', mutations }); var addMutation = mutation => addMutations([mutation]); var commit = () => (0, _rxjs.defer)(() => { emitAction({ type: 'commit' }); return (0, _rxjs.of)(null); }); var snapshot$ = bufferedDocument$.pipe((0, _operators.distinctUntilChanged)((bufDoc, prevBufDoc) => bufDoc.LOCAL === prevBufDoc.LOCAL), (0, _operators.map)(buf => snapshotEventFrom(buf.LOCAL))); var commitResults$ = commits$.pipe((0, _operators.concatMap)(commitReq => doCommit(commitReq.payload).pipe((0, _operators.tap)({ next: commitReq.onSuccess, error: commitReq.onError }))), (0, _operators.mapTo)({ type: 'committed' })); return { updates$: (0, _rxjs.merge)(snapshot$, actionHandler$, updates$, commitResults$), addMutation, addMutations, commit }; }; exports.createObservableBufferedDocument = createObservableBufferedDocument;