UNPKG

@deep-foundation/deeplinks

Version:

[![npm](https://img.shields.io/npm/v/@deep-foundation/deeplinks.svg)](https://www.npmjs.com/package/@deep-foundation/deeplinks) [![Gitpod](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/deep-fo

818 lines 37.8 kB
import _remove from 'lodash/remove.js'; import _isEqual from 'lodash/isEqual.js'; import _mean from 'lodash/mean.js'; import _sum from 'lodash/sum.js'; import _min from 'lodash/min.js'; import _max from 'lodash/max.js'; import EventEmitter from 'events'; import React, { createContext, useContext, useEffect, useMemo, useRef, useState } from 'react'; import Debug from 'debug'; import { minilinksQuery, minilinksQueryIs } from './minilinks-query.js'; import { useDebounceCallback } from '@react-hook/debounce'; import { Observable } from '@apollo/client/index.js'; import get from 'get-value'; import { _ids, random, useDebouncedInput } from './client.js'; import { Traveler } from './traveler.js'; const debug = Debug('deeplinks:minilinks'); const log = debug.extend('log'); const error = debug.extend('error'); ; const nativeLinkKeys = ['id', 'type_id', 'from_id', 'to_id', 'value', 'type', 'typed', 'from', 'out', 'outByType', 'to', 'in', 'inByType', '_applies', '_namespaces', 'ml']; export function toPlain(link) { return { id: link._id || link.id, type_id: link._type_id || link.type_id, from_id: link._from_id || link.from_id, to_id: link._to_id || link.to_id, value: link.value || undefined, }; } export class MinilinksLink { get type_id() { var _a; return (((_a = this.ml) === null || _a === void 0 ? void 0 : _a.virtualInverted[this._type_id]) || this._type_id); } get from_id() { var _a; return (((_a = this.ml) === null || _a === void 0 ? void 0 : _a.virtualInverted[this._from_id]) || this._from_id); } get to_id() { var _a; return (((_a = this.ml) === null || _a === void 0 ? void 0 : _a.virtualInverted[this._to_id]) || this._to_id); } set type_id(id) { this._type_id = id; } set from_id(id) { this._from_id = id; } set to_id(id) { this._to_id = id; } get typed() { var _a, _b; return this.ml._traveled(((_b = (_a = this.ml) === null || _a === void 0 ? void 0 : _a.byType) === null || _b === void 0 ? void 0 : _b[this.id]) || []); } get type() { var _a, _b; return this.ml._traveled((_b = (_a = this.ml) === null || _a === void 0 ? void 0 : _a.byId) === null || _b === void 0 ? void 0 : _b[this.type_id]); } get in() { var _a, _b; return this.ml._traveled(((_b = (_a = this.ml) === null || _a === void 0 ? void 0 : _a.byTo) === null || _b === void 0 ? void 0 : _b[this.id]) || []); } get inByType() { var _a, _b, _c, _d, _e; const hash = {}; for (let i = 0; i < (((_c = (_b = (_a = this.ml) === null || _a === void 0 ? void 0 : _a.byTo) === null || _b === void 0 ? void 0 : _b[this.id]) === null || _c === void 0 ? void 0 : _c.length) || 0); i++) { const element = (_e = (_d = this.ml) === null || _d === void 0 ? void 0 : _d.byTo) === null || _e === void 0 ? void 0 : _e[this.id][i]; hash[element.type_id] = hash[element.type_id] || this.ml._traveled([]); hash[element.type_id].push(element); } return hash; } get out() { var _a, _b; return this.ml._traveled((_b = (_a = this.ml) === null || _a === void 0 ? void 0 : _a.byFrom) === null || _b === void 0 ? void 0 : _b[this.id]); } get outByType() { var _a, _b, _c, _d, _e, _f; const hash = {}; for (let i = 0; i < (((_c = (_b = (_a = this.ml) === null || _a === void 0 ? void 0 : _a.byFrom) === null || _b === void 0 ? void 0 : _b[this.id]) === null || _c === void 0 ? void 0 : _c.length) || 0); i++) { const element = (_f = (_e = (_d = this.ml) === null || _d === void 0 ? void 0 : _d.byFrom) === null || _e === void 0 ? void 0 : _e[this.id]) === null || _f === void 0 ? void 0 : _f[i]; hash[element.type_id] = hash[element.type_id] || this.ml._traveled([]); hash[element.type_id].push(element); } return hash; } get from() { var _a, _b; return (_b = (_a = this.ml) === null || _a === void 0 ? void 0 : _a.byId) === null || _b === void 0 ? void 0 : _b[this.from_id]; } get to() { var _a, _b; return (_b = (_a = this.ml) === null || _a === void 0 ? void 0 : _a.byId) === null || _b === void 0 ? void 0 : _b[this.to_id]; } get displayId() { return this._id || this.id; } get value() { return (this === null || this === void 0 ? void 0 : this.string) || (this === null || this === void 0 ? void 0 : this.number) || (this === null || this === void 0 ? void 0 : this.object); } get name() { var _a; return (_a = this.ml) === null || _a === void 0 ? void 0 : _a.name(this.id); } get symbol() { var _a; return (_a = this.ml) === null || _a === void 0 ? void 0 : _a.symbol(this.id); } travel(query) { var _a, _b; return ((_a = this === null || this === void 0 ? void 0 : this.ml) === null || _a === void 0 ? void 0 : _a.deep) ? new Traveler((_b = this.ml) === null || _b === void 0 ? void 0 : _b.deep, [this], query ? [{ query }] : [], 'local') : undefined; } toString() { return `${this.symbol} ${this.id} ${this.name}`; } valueOf() { var _a; return (_a = this === null || this === void 0 ? void 0 : this.value) === null || _a === void 0 ? void 0 : _a.value; } constructor(link) { var _a, _b, _c; this._applies = []; this._namespaces = []; this.ml = link.ml; this.id = link.id; this._id = link._id; this._type_id = link.type_id; this._from_id = link.from_id; this._to_id = link.to_id; this._applies = link._applies; if (link.value) { if (typeof ((_a = link === null || link === void 0 ? void 0 : link.value) === null || _a === void 0 ? void 0 : _a.value) === 'string' && !this.string) this.string = link.value; if (typeof ((_b = link === null || link === void 0 ? void 0 : link.value) === null || _b === void 0 ? void 0 : _b.value) === 'number' && !this.number) this.number = link.value; if (typeof ((_c = link === null || link === void 0 ? void 0 : link.value) === null || _c === void 0 ? void 0 : _c.value) === 'object' && !this.object) this.object = link.value; } const keys = Object.keys(link); for (const key of keys) { if (!nativeLinkKeys.includes(key)) this[key] = link[key]; } } toPlain() { return toPlain(this); } is(query) { return minilinksQueryIs(query, this); } } export const MinilinksGeneratorOptionsDefault = { id: 'id', type_id: 'type_id', type: 'type', typed: 'typed', from_id: 'from_id', from: 'from', out: 'out', to_id: 'to_id', to: 'to', in: 'in', inByType: 'inByType', outByType: 'outByType', equal: (ol, nl) => { const _ol = toPlain(ol); const _nl = toPlain(nl); return _ol.type_id == _nl.type_id && _ol.from_id == _nl.from_id && _ol.to_id == _nl.to_id && _isEqual(_ol.value, _nl.value); }, Link: MinilinksLink, }; export function Minilinks(options) { return function minilinks(linksArray = [], memory = {}) { const mc = new MinilinkCollection(options, memory); mc.add(linksArray); return mc; }; } export class MinilinkCollection { query(query, options) { this.emitter.emit('select.before', { minilinks: this, query, options }); const result = minilinksQuery(query, this); if ((options === null || options === void 0 ? void 0 : options.aggregate) === 'count') return result === null || result === void 0 ? void 0 : result.length; if ((options === null || options === void 0 ? void 0 : options.aggregate) === 'avg') return _mean(result === null || result === void 0 ? void 0 : result.map(l => { var _a; return (_a = l === null || l === void 0 ? void 0 : l.value) === null || _a === void 0 ? void 0 : _a.value; })); if ((options === null || options === void 0 ? void 0 : options.aggregate) === 'sum') return _sum(result === null || result === void 0 ? void 0 : result.map(l => { var _a; return (_a = l === null || l === void 0 ? void 0 : l.value) === null || _a === void 0 ? void 0 : _a.value; })); if ((options === null || options === void 0 ? void 0 : options.aggregate) === 'min') return _min(result === null || result === void 0 ? void 0 : result.map(l => { var _a; return (_a = l === null || l === void 0 ? void 0 : l.value) === null || _a === void 0 ? void 0 : _a.value; })); if ((options === null || options === void 0 ? void 0 : options.aggregate) === 'max') return _max(result === null || result === void 0 ? void 0 : result.map(l => { var _a; return (_a = l === null || l === void 0 ? void 0 : l.value) === null || _a === void 0 ? void 0 : _a.value; })); this._traveled(result); this.emitter.emit('select', { minilinks: this, query, options, localData: result, }); return result; } select(query, options) { return this.query(query, options); } id(start, ...path) { const paths = [start, ...(path[path.length - 1] === true ? path.slice(0, -1) : path)]; const [link] = this.query({ id: { _id: paths } }); const result = link === null || link === void 0 ? void 0 : link.id; if (!result && path[path.length - 1] !== true) { const precached = get(_ids, paths.join('.')); if (precached) return precached; throw new Error(`Id not found by ${JSON.stringify([start, ...path])}`); } else { return result; } } ; name(input) { var _a, _b, _c, _d; const id = typeof (input) === 'number' || typeof (input) === 'string' ? input : input === null || input === void 0 ? void 0 : input.id; if (!id) return null; const it = this.byId[id]; if ((it === null || it === void 0 ? void 0 : it.type_id) === _ids['@deep-foundation/core']['Package']) return (_a = it === null || it === void 0 ? void 0 : it.value) === null || _a === void 0 ? void 0 : _a.value; return ((_d = (_c = (_b = it === null || it === void 0 ? void 0 : it.inByType[_ids['@deep-foundation/core']['Contain']]) === null || _b === void 0 ? void 0 : _b.find((c) => { var _a; return !!((_a = c === null || c === void 0 ? void 0 : c.value) === null || _a === void 0 ? void 0 : _a.value); })) === null || _c === void 0 ? void 0 : _c.value) === null || _d === void 0 ? void 0 : _d.value) || id; } symbol(input) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; const id = typeof (input) === 'number' || typeof (input) === 'string' ? input : input === null || input === void 0 ? void 0 : input.id; if (!id) return null; return ((_e = (_d = (_c = (_b = (_a = this.byId[id]) === null || _a === void 0 ? void 0 : _a.inByType) === null || _b === void 0 ? void 0 : _b[_ids['@deep-foundation/core']['Symbol']]) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.value) === null || _e === void 0 ? void 0 : _e.value) || ((_l = (_k = (_j = (_h = (_g = (_f = this.byId[id]) === null || _f === void 0 ? void 0 : _f.type) === null || _g === void 0 ? void 0 : _g.inByType) === null || _h === void 0 ? void 0 : _h[_ids['@deep-foundation/core']['Symbol']]) === null || _j === void 0 ? void 0 : _j[0]) === null || _k === void 0 ? void 0 : _k.value) === null || _l === void 0 ? void 0 : _l.value) || '📍'; } subscribe(query, options) { const ml = this; this.emitter.emit('subscribe.before', { minilinks: this, query, options, }); return new Observable((observer) => { let prev = ml.query(query, options); let t; observer.next(prev); let listener = (oldL, newL) => { clearTimeout(t); t = setTimeout(() => { const data = ml.query(query, options); if (!_isEqual(prev, data)) { prev = data; this.emitter.emit('subscribe', { minilinks: this, query, options, localData: data, }); observer.next(data); } }, 300); }; ml.emitter.on('added', listener); ml.emitter.on('updated', listener); ml.emitter.on('removed', listener); return () => { ml.emitter.removeListener('added', listener); ml.emitter.removeListener('updated', listener); ml.emitter.removeListener('removed', listener); }; }); } add(linksArray, applyName = '') { log('add', linksArray, this); const { byId, byFrom, byTo, byType, links, options } = this; const anomalies = []; const errors = []; const newLinks = this._traveled([]); for (let l = 0; l < linksArray.length; l++) { if (!!byId[linksArray[l][options.id]]) errors.push(new Error(`${linksArray[l][options.id]} can't add because already exists in collection`)); if (byId[linksArray[l][options.id]]) { if (options.handler) options.handler(byId[linksArray[l][options.id]], this); } else { const isVirtual = linksArray[l].id < 0; if (isVirtual && !this.virtual.hasOwnProperty(linksArray[l].id)) { this.virtual[linksArray[l].id] = undefined; } const link = new this.options.Link(Object.assign({ ml: this, _applies: [applyName], _namespaces: [], _id: isVirtual ? undefined : linksArray[l].id }, linksArray[l])); byId[link[options.id]] = link; if (link[options.from_id]) { if (byFrom[link[options.from_id]]) byFrom[link[options.from_id]].push(link); else byFrom[link[options.from_id]] = this._traveled([link]); } if (link[options.to_id]) { if (byTo[link[options.to_id]]) byTo[link[options.to_id]].push(link); else byTo[link[options.to_id]] = this._traveled([link]); } if (link[options.type_id]) { if (byType[link[options.type_id]]) byType[link[options.type_id]].push(link); else byType[link[options.type_id]] = this._traveled([link]); } links.push(link); newLinks.push(link); } } for (let l = 0; l < newLinks.length; l++) { const link = newLinks[l]; const type = byId[link[options.type_id]]; const from = byId[link[options.from_id]]; const to = byId[link[options.to_id]]; if (type) { } else if (link[options.type_id]) anomalies.push(new Error(`${link[options.id]} link.type_id ${link[options.type_id]} not found`)); if (from) { } else if (link[options.from_id]) anomalies.push(new Error(`${link[options.id]} link.from_id ${link[options.from_id]} not found`)); if (to) { } else if (link[options.to_id]) anomalies.push(new Error(`${link[options.id]} link.to_id ${link[options.to_id]} not found`)); if (options.handler) options.handler(link, this); } for (let l = 0; l < newLinks.length; l++) { const link = newLinks[l]; if (!this._updating) { this.emitter.emit('added', undefined, link, applyName); this.emitter.emit(`link.${link.id}`, undefined, link, applyName); } } return { anomalies, errors, }; } remove(idsArray, applyName) { log('remove', idsArray, this); const { byId, byFrom, byTo, byType, types, links, options } = this; const anomalies = []; const errors = []; const oldLinksArray = this._traveled([]); const oldLinksObject = {}; for (let l = 0; l < idsArray.length; l++) { const id = idsArray[l]; const link = byId[id]; log('remove old l:', l, 'id:', id, 'link:', link); if (link) { oldLinksArray.push(link); oldLinksObject[id] = link; } } for (let l = 0; l < idsArray.length; l++) { const id = idsArray[l]; const link = oldLinksArray[l]; if (!link) errors.push(new Error(`${id} can't delete because not exists in collection`)); _remove((byFrom === null || byFrom === void 0 ? void 0 : byFrom[link === null || link === void 0 ? void 0 : link[options.from_id]]) || [], (r) => r.id === id); _remove((byTo === null || byTo === void 0 ? void 0 : byTo[link === null || link === void 0 ? void 0 : link[options.to_id]]) || [], (r) => r.id === id); _remove((byType === null || byType === void 0 ? void 0 : byType[link === null || link === void 0 ? void 0 : link[options.type_id]]) || [], (r) => r.id === id); byId === null || byId === void 0 ? true : delete byId[id]; } _remove(links, l => idsArray.includes(l[options.id])); for (let l = 0; l < oldLinksArray.length; l++) { const link = oldLinksArray[l]; log('emit removed link', link, '_updating', this._updating); if (!this._updating) { this.emitter.emit('removed', link, undefined, applyName); this.emitter.emit(`link.${link.id}`, link, undefined, applyName); } } return { anomalies, errors, }; } _toPlainLinksArray(linkOrLinks, applyOptions, plainLinksArray, returnLinksPathsById) { var _a; const links = Array.isArray(linkOrLinks) ? linkOrLinks : [linkOrLinks]; plainLinksArray.push(...links.filter(l => l.__typename === 'links').map(l => (Object.assign(Object.assign({}, l), { id: l.id, type_id: l.type_id, from_id: l.from_id, to_id: l.to_id, value: l.value })))); for (let l in links) { for (let r in ((applyOptions === null || applyOptions === void 0 ? void 0 : applyOptions.return) || {})) { this._toPlainLinksArray(links[l][r] || [], (_a = applyOptions === null || applyOptions === void 0 ? void 0 : applyOptions.return) === null || _a === void 0 ? void 0 : _a[r], plainLinksArray, returnLinksPathsById); } } } apply(_input, applyName = '', applyOptions) { var _a, _b, _c, _d; const result = []; const input = Array.isArray(_input) ? _input : Array.isArray(_input === null || _input === void 0 ? void 0 : _input.data) ? _input === null || _input === void 0 ? void 0 : _input.data : []; const returning = (_input === null || _input === void 0 ? void 0 : _input.return) || {}; const _applyOptions = Object.assign({ return: returning }, applyOptions); const deep = _input === null || _input === void 0 ? void 0 : _input.deep; const namespace = deep === null || deep === void 0 ? void 0 : deep.namespace; log('apply', input, this); const { byId, byFrom, byTo, byType, types, links, options } = this; const toAdd = []; const toUpdate = []; const beforeUpdate = {}; const toRemove = []; const _byId = {}; const linksArray = []; const returnLinksPathsById = {}; for (let l = 0; l < input.length; l++) { const link = input[l]; this._toPlainLinksArray(link, _applyOptions, linksArray, returnLinksPathsById); } const virtualizedLinks = {}; for (let l = 0; l < linksArray.length; l++) { let link = linksArray[l]; if (!virtualizedLinks[link.id] && !link.from_id && !link.to_id) { const virtualId = this.virtualInverted[link.id]; const compatable = []; if (virtualId) compatable.push(virtualId); if (!compatable.length && virtualizedLinks[link.type_id]) { compatable.push((_a = this.byType[virtualizedLinks[link.type_id].id]) === null || _a === void 0 ? void 0 : _a.find(l => !l._id)); } if (!compatable.length) compatable.push((_b = this.byType[link.type_id]) === null || _b === void 0 ? void 0 : _b.find(l => !l._id)); if (compatable[0]) { virtualizedLinks[link.id] = compatable[0]; } } } let needRepeatIdentification = true; while (needRepeatIdentification) { let hasIdentifiedVirtualizedPerCycle = false; for (let l = 0; l < linksArray.length; l++) { let link = linksArray[l]; if (!virtualizedLinks[link.id]) { if (link.from_id && link.to_id) { const virtual = this.virtualInverted[link.id]; const compatable = []; if (virtualizedLinks[link.to_id]) { compatable.push((_c = this.byTo[virtualizedLinks[link.to_id].id]) === null || _c === void 0 ? void 0 : _c.find(l => { var _a, _b; return l.from_id === ((_a = virtualizedLinks[link.from_id]) === null || _a === void 0 ? void 0 : _a.id) || l.from_id === link.from_id && l.type_id === ((_b = virtualizedLinks[link.type_id]) === null || _b === void 0 ? void 0 : _b.id) || l.type_id === link.type_id && !l._id; })); } if (!compatable.length) compatable.push((_d = this.byTo[link.to_id]) === null || _d === void 0 ? void 0 : _d.find(l => { var _a, _b; return l.from_id === ((_a = virtualizedLinks[link.from_id]) === null || _a === void 0 ? void 0 : _a.id) || l.from_id === link.from_id && l.type_id === ((_b = virtualizedLinks[link.type_id]) === null || _b === void 0 ? void 0 : _b.id) || l.type_id === link.type_id && !l._id; })); if (compatable[0]) { virtualizedLinks[link.id] = compatable[0]; hasIdentifiedVirtualizedPerCycle = true; } } } } if (!hasIdentifiedVirtualizedPerCycle) needRepeatIdentification = false; } for (let l = 0; l < linksArray.length; l++) { let link = linksArray[l]; let old = byId[link.id]; const virtual = virtualizedLinks[link.id] || (this.virtualInverted[link.id] ? this.byId[this.virtualInverted[link.id]] : undefined); if (virtual && !old) { old = virtual; if (!virtual._id) { this.virtual[virtual.id] = link.id; this.virtualInverted[link.id] = virtual.id; virtual._id = link.id; link = Object.assign(Object.assign({}, link), { _id: link.id, id: virtual.id }); } } if (!old && !virtual) { link._applies = [applyName]; if (namespace) link._namespaces = [namespace]; this.emitter.emit('apply', old, link, applyName); this.emitter.emit('+apply', old, link, applyName); toAdd.push(link); } else { if (!~old._applies.indexOf(applyName)) { link._applies = old._applies = [...old._applies, applyName]; this.emitter.emit('apply', old, link, applyName); this.emitter.emit('+apply', old, link, applyName); } else { link._applies = old._applies; } if (!options.equal(old, link)) { toUpdate.push(link); beforeUpdate[link.id] = old; } if (namespace) { if (!~old._namespaces.indexOf(namespace)) { link._namespaces = old._namespaces = [...old._namespaces, namespace]; } else { link._namespaces = old._namespaces; } } } _byId[link.id] = link; } for (let l = 0; l < links.length; l++) { const link = links[l]; if (!_byId[link._id]) { const index = link._applies.indexOf(applyName); const isVirtualAndNeedToDelete = link._applies.length == 2 && link._applies.includes(''); if (!!~index) { if (link._applies.length === 1 || isVirtualAndNeedToDelete) { toRemove.push(link); } else { link._applies.splice(index, 1); this.emitter.emit('apply', link, link, applyName); this.emitter.emit('-apply', link, link, applyName); } } } } const r1 = this.remove(toRemove.map(l => l[options.id]), applyName); const a1 = this.add(toAdd); this._updating = true; const r2 = this.remove(toUpdate.map(l => l[options.id]), applyName); const a2 = this.add(toUpdate); for (let i = 0; i < toUpdate.length; i++) { const l = toUpdate[i]; this.emitter.emit('updated', beforeUpdate[l.id], byId[l.id], applyName); this.emitter.emit(`link.${l.id}`, beforeUpdate[l.id], byId[l.id], applyName); } this._updating = false; return { errors: [...r1.errors, ...a1.errors, ...r2.errors, ...a2.errors], anomalies: [...r1.anomalies, ...a1.anomalies, ...r2.anomalies, ...a2.anomalies], data: this._traveled(input.map(i => this.byId[i === null || i === void 0 ? void 0 : i.id])), plainLinks: linksArray, }; } update(linksArray, applyName) { log('update', linksArray, this); const { byId, byFrom, byTo, byType, types, links, options } = this; const toUpdate = []; const beforeUpdate = {}; const _byId = {}; for (let l = 0; l < linksArray.length; l++) { let link = linksArray[l]; let old = byId[link.id]; const virtualIds = Object.keys(this.virtual); let virtual; for (let i = 0; i < virtualIds.length; i++) { const v = this.byId[virtualIds[i]]; if ((!link.type_id || link.type_id == v._type_id) && (!link.from_id || link.from_id == v._from_id) && (!link.to_id || link.to_id == v._to_id) && (!link.value || _isEqual(link.value, v.value))) { virtual = v; break; } } if (virtual) { if (old) throw new Error(`somehow we have oldLink.id ${old.id} and virtualLink.id ${virtual.id} virtualLink._id = ${virtual._id}`); old = virtual; virtual._id = link.id; link = Object.assign(Object.assign({}, link), { _id: link.id, id: virtual.id }); } if (old) { if (!options.equal(old, link)) { toUpdate.push(link); beforeUpdate[link.id] = old; } } _byId[link.id] = link; } this._updating = true; const r2 = this.remove(toUpdate.map(l => l[options.id]), applyName); const a2 = this.add(toUpdate, applyName); for (let i = 0; i < toUpdate.length; i++) { const l = toUpdate[i]; this.emitter.emit('updated', beforeUpdate[l.id], byId[l.id], applyName); this.emitter.emit(`link.${l.id}`, beforeUpdate[l.id], byId[l.id], applyName); } this._updating = false; return { errors: [...r2.errors, ...a2.errors], anomalies: [...r2.anomalies, ...a2.anomalies] }; } constructor(options, memory) { this.useMinilinksQuery = useMinilinksQuery; this.useMinilinksFilter = useMinilinksFilter; this.useMinilinksApply = useMinilinksApply; this.useMinilinksSubscription = useMinilinksSubscription; this.useMinilinksId = useMinilinksId; this.useMinilinksHandle = useMinilinksHandle; this.toPlain = toPlain; this.virtual = {}; this.virtualInverted = {}; this.virtualCounter = -1; this.types = {}; this.byId = {}; this.byFrom = {}; this.byTo = {}; this.byType = {}; this.links = this._traveled([]); this._updating = false; const _options = options || MinilinksGeneratorOptionsDefault; this.types = this.byType = (memory === null || memory === void 0 ? void 0 : memory.types) || {}; this.byId = (memory === null || memory === void 0 ? void 0 : memory.byId) || {}; this.byFrom = (memory === null || memory === void 0 ? void 0 : memory.byFrom) || {}; this.byTo = (memory === null || memory === void 0 ? void 0 : memory.byTo) || {}; this.links = (memory === null || memory === void 0 ? void 0 : memory.links) || []; this.options = _options; this.emitter = new EventEmitter(); } _traveled(array) { if (!array) return array; array.travel = (query) => this.deep ? new Traveler(this.deep, array, query ? [{ query }] : [], 'local') : undefined; return array; } } export const minilinks = Minilinks(MinilinksGeneratorOptionsDefault); export function useMinilinksConstruct(options) { const mlRef = useRef(useMemo(() => { return new MinilinkCollection(options); }, [])); const ml = mlRef.current; return { ml, ref: mlRef }; } export function useMinilinksFilter(ml, filter, results, interval) { const [state, setState] = useState(); const action = useDebounceCallback((l, ml, ol, nl) => { setState(results(l, ml, ol, nl)); }, 500, true); const refs = useRef({}); useEffect(() => { if (refs.current.addedListener) ml.emitter.removeListener('added', refs.current.addedListener); if (refs.current.updatedListener) ml.emitter.removeListener('updated', refs.current.updatedListener); if (refs.current.removedListener) ml.emitter.removeListener('removed', refs.current.removedListener); if (refs.current.applyListener) ml.emitter.removeListener('apply', refs.current.applyListener); refs.current.addedListener = (ol, nl) => { if (filter(nl, ol, nl)) { action(nl, ml, ol, nl); } }; ml.emitter.on('added', refs.current.addedListener); refs.current.updatedListener = (ol, nl) => { if (filter(nl, ol, nl)) { action(nl, ml, ol, nl); } }; ml.emitter.on('updated', refs.current.updatedListener); refs.current.removedListener = (ol, nl) => { if (filter(ol, ol, nl)) { action(ol, ml, ol, nl); } }; ml.emitter.on('removed', refs.current.removedListener); refs.current.applyListener = (ol, nl) => { if (filter(nl, ol, nl)) { action(nl, ml, ol, nl); } }; let timeout; if (interval) timeout = setTimeout(() => { action(undefined, ml); }, interval); ml.emitter.on('apply', refs.current.applyListener); return () => { clearTimeout(timeout); ml.emitter.removeListener('added', refs.current.addedListener); ml.emitter.removeListener('updated', refs.current.updatedListener); ml.emitter.removeListener('removed', refs.current.removedListener); ml.emitter.removeListener('apply', refs.current.applyListener); }; }, [ml]); useEffect(() => { setState(results(undefined, ml, undefined, undefined)); }, [ml, filter, results]); return state; } ; export function useMinilinksHandle(ml, handler) { useEffect(() => { const addedListener = (ol, nl) => { handler('added', ol, nl); }; ml.emitter.on('added', addedListener); const updatedListener = (ol, nl) => { handler('updated', ol, nl); }; ml.emitter.on('updated', updatedListener); const removedListener = (ol, nl) => { handler('removed', ol, nl); }; ml.emitter.on('removed', removedListener); const applyListener = (ol, nl) => { handler('apply', ol, nl); }; ml.emitter.on('apply', applyListener); return () => { ml.emitter.removeListener('added', addedListener); ml.emitter.removeListener('updated', updatedListener); ml.emitter.removeListener('removed', removedListener); ml.emitter.removeListener('apply', applyListener); }; }, []); } ; const defaultMinilinksApplyResult = { errors: [], anomalies: [], data: [], plainLinks: [] }; export function useMinilinksApply(ml, name, data) { const [strictName] = useState(name); useEffect(() => { return () => { if (ml) ml.apply(Array.isArray(data) ? [] : Object.assign(Object.assign({}, data), { data: [] }), strictName); }; }, []); const results = useMemo(() => { if (ml) return ml.apply(data, strictName); return defaultMinilinksApplyResult; }, [data]); return results; } export function useMinilinksQuery(ml, query, options) { const miniName = useMemo(() => random(), []); useMemo(() => { ml.emitter.emit('useQuery.mount', { minilinks: ml, query, options }); }, []); const { _q, _o } = useDebouncedInput(query, options, options === null || options === void 0 ? void 0 : options.debounce); const results = useMemo(() => ml.query(_q, _o), [ml, _q]); useMemo(() => { ml.emitter.emit('useQuery', { minilinks: ml, query: _q, options: _o, localData: results, }); return () => { ml.emitter.emit('useQuery.unmount', { minilinks: ml, query: _q, options: _o, localData: results, }); }; }, [results]); return results; } ; export function useMinilinksSubscription(ml, query, options) { const miniName = useMemo(() => random(), []); const { _q, _o } = useDebouncedInput(query, options, options === null || options === void 0 ? void 0 : options.debounce); useMemo(() => { ml.emitter.emit('useSubscription.mount', { minilinks: ml, query: _q, options: _o }); }, []); const [d, setD] = useState(); const sRef = useRef(); const qPrevRef = useRef(_q); const q = useMemo(() => _isEqual(_q, qPrevRef.current) ? qPrevRef.current : _q, [_q]); qPrevRef.current = q; useEffect(() => { setD(ml.query(q)); if (sRef.current) sRef.current.unsubscribe(); const obs = ml.subscribe(q, _o); const sub = sRef.current = obs.subscribe({ next: (links) => { setD(links); }, error: (error) => { throw new Error(error); }, }); return () => { sub.unsubscribe(); }; }, [q]); let results = d || (ml ? ml.query(q) : []); useMemo(() => { ml.emitter.emit('useSubscription', { minilinks: ml, query: _q, options: _o, localData: results, }); return () => { ml.emitter.emit('useSubscription.unmount', { minilinks: ml, query: _q, options: _o, localData: results, }); }; }, [results]); return results; } ; export function useMinilinksId(ml, start, ...path) { var _a; const result = useMinilinksQuery(ml, { id: { _id: [start, ...path] } }); return (_a = result === null || result === void 0 ? void 0 : result[0]) === null || _a === void 0 ? void 0 : _a.id; } export function useMinilinksGenerator(minilinks) { const ref = useRef(minilinks); ref.current = useMemo(() => { if (ref.current) return ref.current; return new MinilinkCollection(); }, []); return ref.current; } export const MinilinksContext = createContext(undefined); export function MinilinksProvider({ minilinks: initialMinilinks, children, }) { const minilinks = useMinilinksGenerator(initialMinilinks); return (React.createElement(MinilinksContext.Provider, { value: minilinks }, children)); } export function useMinilinks() { return useContext(MinilinksContext); } //# sourceMappingURL=minilinks.js.map