{"version":3,"sources":["jsdelivr-header.js","/npm/hypermerge@0.4.0/index.js"],"names":[],"mappings":"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","file":"/npm/hypermerge@0.4.0/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/hypermerge@0.4.0/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","const EventEmitter = require('events')\nconst Automerge = require('automerge')\nconst MultiCore = require('./MultiCore')\nconst discoverySwarm = require('discovery-swarm')\nconst swarmDefaults = require('datland-swarm-defaults')\n\n// The first block is used for metadata:\nconst START_BLOCK = 1\nconst METADATA = {\n  hypermerge: 1\n}\n\n/**\n * An Automerge document.\n * @typedef {object} Document\n */\n\n/**\n * Create and share Automerge documents using peer-to-peer networking.\n *\n * @param {Object} options\n * @param {string} options.path - path to directory used to store multiple\n *   hypercores\n * @param {number} [options.port=0] - port number to listen on\n */\n\nmodule.exports = class Hypermerge extends EventEmitter {\n  constructor ({path, port = 0, immutableApi = false, defaultMetadata}) {\n    super()\n\n    this.immutableApi = immutableApi\n    this.defaultMetadata = defaultMetadata || {}\n    this.port = port\n    this.isReady = false\n    this.feeds = {}\n    this.pDocs = {} // index of docs previously emitted by `document:updated`\n    this.docs = {}\n\n    this.readyIndex = {} // docId -> Boolean\n    this.groupIndex = {} // groupId -> [actorId]\n    this.docIndex = {} // docId -> [actorId]\n    this.metaIndex = {} // actorId -> metadata\n    this.requestedBlocks = {} // docId -> actorId -> blockIndex (exclusive)\n\n    this.core = new MultiCore(path)\n\n    this.core.ready(this._onMultiCoreReady())\n  }\n\n  /**\n   * Have any automerge documents been built?\n   *\n   * @param {filterCallback} [f] - a filter function\n   * @returns {boolean}\n   */\n  any (f = () => true) {\n    return Object.keys(this.docs).some(id => f(this.docs[id], id))\n  }\n\n  has (docId) {\n    return !!this.docs[docId]\n  }\n\n  find (docId) {\n    const doc = this.docs[docId]\n\n    if (!doc) throw new Error(`Cannot find document. open(docId) first. docId: ${docId}`)\n\n    return doc\n  }\n\n  set (doc) {\n    const docId = this.getId(doc)\n    this.docs[docId] = doc\n    return doc\n  }\n\n  /**\n   * Opens an existing document.\n   *\n   * @param {string} docId - docId of document to open\n   */\n  open (docId, metadata = null) {\n    this._ensureReady()\n\n    if (this.docs[docId]) return this.docs[docId]\n\n    // we haven't seen this doc before:\n    this.feed(docId)\n  }\n\n  /**\n   * Creates an automerge document backed by a new hypercore.\n   *\n   * @param {object} metadata - metadata to be associated with this document\n   */\n  create (metadata = {}) {\n    this._ensureReady()\n    return this._create(metadata)\n  }\n\n  _create (metadata, parentMetadata = {}) {\n    const feed = this.feed()\n    const actorId = feed.key.toString('hex')\n\n    // TODO this is a little wacky:\n    metadata = Object.assign(\n      {},\n      METADATA,\n      { groupId: actorId }, // default to self if parent doesn't have groupId\n      parentMetadata, // metadata of the parent feed to this feed (e.g. when opening, forking)\n      this.defaultMetadata, // user-specified default metadata\n      { docId: actorId }, // set the docId to this core's actorId by default\n      metadata // directly provided metadata should override everything else\n    )\n\n    this._appendMetadata(actorId, metadata)\n\n    const doc = this.set(this.empty(actorId))\n    this._shareDoc(doc)\n\n    return doc\n  }\n\n  change (doc, message = null, changeFn) {\n    return this.update(Automerge.change(doc, message, changeFn))\n  }\n\n  /**\n   * Finds any new changes for the submitted doc for the actor,\n   * and appends the changes to the actor's hypercore feed.\n   *\n   * @param {Object} doc - document to find changes for\n   */\n  update (doc) {\n    this._ensureReady()\n\n    const actorId = this.getActorId(doc)\n    const docId = this.actorToId(actorId)\n    const pDoc = this.find(docId)\n\n    const changes = Automerge.getChanges(pDoc, doc)\n      .filter(({actor}) => actor === actorId)\n\n    this._addToMaxRequested(docId, actorId, changes.length)\n\n    this._appendAll(actorId, changes)\n\n    this.pDocs[docId] = doc\n\n    return this.set(doc)\n  }\n\n  /**\n   * Creates a new actor hypercore feed and automerge document, with\n   * an empty change that depends on the document for another actor.\n   *\n   * @param {string} parentId - id of document to fork\n   */\n  fork (parentId) {\n    this._ensureReady()\n\n    const parent = this.find(parentId)\n    const doc = this._create({parentId}, this.metadata(parentId))\n\n    return this.change(\n      Automerge.merge(doc, parent),\n      `Forked from ${parentId}`,\n      () => {})\n  }\n\n  /**\n   * Takes all the changes from a document (sourceId) and adds them to\n   * another document (destId).\n   * @param {string} destId - docId to merge changes into\n   * @param {string} sourceId - docId to copy changes from\n   */\n  merge (destId, sourceId) {\n    this._ensureReady()\n\n    const dest = this.find(destId)\n    const source = this.find(sourceId)\n\n    return this.change(\n      Automerge.merge(dest, source),\n      `Merged with ${sourceId}`,\n      () => {})\n  }\n\n  /**\n   * Removes hypercore feed for an actor and automerge doc.\n   *\n   * Leaves the network swarm. Doesn't remove files from disk.\n   * @param {string} docId\n   */\n  delete (docId) {\n    const doc = this.find(docId)\n    this.core.archiver.remove(docId)\n    delete this.feeds[docId]\n    delete this.docs[docId]\n    delete this.pDocs[docId]\n    return doc\n  }\n\n  message (actorId, msg) {\n    this.feed(actorId).peers.forEach(peer => {\n      this._messagePeer(peer, msg)\n    })\n  }\n\n  length (actorId) {\n    return this._feed(actorId).length\n  }\n\n  /**\n   * Is the hypercore writable?\n   *\n   * @param {string} actorId - actor id\n   * @returns {boolean}\n   */\n  isWritable (actorId) {\n    return this._feed(actorId).writable\n  }\n\n  isOpened (actorId) {\n    return this._feed(actorId).opened\n  }\n\n  isMissingDeps (docId) {\n    const deps = Automerge.getMissingDeps(this.find(docId))\n    return !!Object.keys(deps).length\n  }\n\n  empty (actorId) {\n    return this.immutableApi\n      ? Automerge.initImmutable(actorId)\n      : Automerge.init(actorId)\n  }\n\n  metadatas (docId) {\n    const actorIds = this.docIndex[docId] || []\n    return actorIds.map(actorId => this.metadata(actorId))\n  }\n\n  metadata (actorId) {\n    return this.metaIndex[actorId]\n  }\n\n  isDocId (actorId) {\n    return this.actorToId(actorId) === actorId\n  }\n\n  getId (doc) {\n    return this.actorToId(this.getActorId(doc))\n  }\n\n  actorToId (actorId) {\n    const {docId} = this.metadata(actorId)\n    return docId\n  }\n\n  getActorId (doc) {\n    return doc._actorId\n  }\n\n  clock (doc) {\n    return doc._state.getIn(['opSet', 'clock'])\n  }\n\n  _feed (actorId = null) {\n    const key = actorId ? Buffer.from(actorId, 'hex') : null\n    return this.core.createFeed(key)\n  }\n\n  feed (actorId = null) {\n    this._ensureReady()\n\n    if (actorId && this.feeds[actorId]) return this.feeds[actorId]\n\n    return this._trackFeed(this._feed(actorId))\n  }\n\n  isDocReady (docId) {\n    return this.readyIndex[docId]\n  }\n\n  replicate (opts) {\n    return this.core.replicate(opts)\n  }\n\n  joinSwarm (opts = {}) {\n    this._ensureReady()\n\n    const {archiver} = this.core\n\n    const sw = this.swarm = discoverySwarm(swarmDefaults(Object.assign({\n      port: this.port,\n      hash: false,\n      encrypt: true,\n      stream: opts => this.replicate(opts)\n    }, opts)))\n\n    sw.join(archiver.changes.discoveryKey)\n\n    Object.values(this.feeds).forEach(feed => {\n      sw.join(feed.discoveryKey)\n    })\n\n    archiver.on('add', feed => {\n      sw.join(feed.discoveryKey)\n    })\n\n    archiver.on('remove', feed => {\n      sw.leave(feed.discoveryKey)\n    })\n\n    sw.listen(this.port)\n\n    sw.once('error', err => {\n      console.error('Swarm error:', err)\n      console.log('Swarm re-listening')\n      sw.listen()\n    })\n\n    return this\n  }\n\n  _appendMetadata (actorId, metadata) {\n    if (this.length(actorId) > 0) throw new Error(`Metadata can only be set if feed is empty.`)\n\n    this._setMetadata(actorId, metadata)\n\n    return this._append(actorId, metadata)\n  }\n\n  _append (actorId, change) {\n    return this._appendAll(actorId, [change])\n  }\n\n  _appendAll (actorId, changes) {\n    const blocks = changes.map(change => JSON.stringify(change))\n    return _promise(cb => {\n      this.feed(actorId).append(blocks, cb)\n    })\n  }\n\n  _trackFeed (feed) {\n    const actorId = feed.key.toString('hex')\n\n    this.feeds[actorId] = feed\n\n    feed.ready(this._onFeedReady(actorId, feed))\n\n    feed.on('peer-add', this._onPeerAdded(actorId))\n    feed.on('peer-remove', this._onPeerRemoved(actorId))\n\n    return feed\n  }\n\n  _onFeedReady (actorId, feed) {\n    return () => {\n      this._loadMetadata(actorId)\n      .then(() => {\n        const docId = this.actorToId(actorId)\n\n        this._createDocIfMissing(docId, actorId)\n\n        feed.on('download', this._onDownload(docId, actorId))\n\n        return this._loadAllBlocks(actorId)\n          .then(() => {\n            if (actorId !== docId) return\n\n            this.readyIndex[docId] = true\n            this._emitReady(docId)\n          })\n      })\n\n      /**\n       * Emitted when a hypercore feed is ready.\n       *\n       * @event feed:ready\n       * @param {object} feed - hypercore feed\n       */\n      this.emit('feed:ready', feed)\n    }\n  }\n\n  _createDocIfMissing (docId, actorId) {\n    if (this.docs[docId]) return\n\n    // TODO extra, empty hypercores are still being created\n\n    if (this.isWritable(actorId)) {\n      this.docs[docId] = this.empty(actorId)\n    }\n\n    const parentMetadata = this.metadata(actorId)\n\n    // TODO might need an empty commit to be included in other vector clocks:\n    return this._create({docId}, parentMetadata)\n  }\n\n  _initFeeds (actorIds) {\n    return Promise.all(\n      actorIds.map(actorId => {\n        // don't load metadata if the feed is empty:\n        if (this.length(actorId) === 0) {\n          console.log('skipping feed init', actorId)\n          return Promise.resolve(null)\n        }\n\n        return this._loadMetadata(actorId)\n        .then(({docId}) => {\n          if (this.isWritable(actorId)) {\n            this.docs[docId] = this.empty(actorId)\n          }\n        })\n        .then(() => actorId)\n      }))\n  }\n\n  _loadMetadata (actorId) {\n    if (this.metaIndex[actorId]) return Promise.resolve(this.metaIndex[actorId])\n\n    return _promise(cb => {\n      this._feed(actorId).get(0, cb)\n    })\n    .then(data => this._setMetadata(actorId, JSON.parse(data)))\n  }\n\n  _setMetadata (actorId, metadata) {\n    if (this.metaIndex[actorId]) return this.metaIndex[actorId]\n\n    this.metaIndex[actorId] = metadata\n    const {docId, groupId} = metadata\n\n    if (!this.groupIndex[groupId]) this.groupIndex[groupId] = []\n    this.groupIndex[groupId].push(actorId)\n\n    if (!this.docIndex[docId]) this.docIndex[docId] = []\n    this.docIndex[docId].push(actorId)\n\n    return metadata\n  }\n\n  _loadAllBlocks (actorId) {\n    return this._loadOwnBlocks(actorId)\n    .then(() => this._loadMissingBlocks(actorId))\n  }\n\n  _loadOwnBlocks (actorId) {\n    const docId = this.actorToId(actorId)\n\n    return this._loadBlocks(docId, actorId, this.length(actorId))\n  }\n\n  _loadMissingBlocks (actorId) {\n    const docId = this.actorToId(actorId)\n\n    if (docId !== actorId) return\n\n    const deps = Automerge.getMissingDeps(this.find(docId))\n\n    return Promise.all(Object.keys(deps).map(actor => {\n      const last = deps[actor] + 1 // last is exclusive\n\n      return this._loadBlocks(docId, actor, last)\n    }))\n  }\n\n  _loadBlocks (docId, actorId, last) {\n    const first = this._maxRequested(docId, actorId, last)\n\n    // Stop requesting if done:\n    if (first >= last) return Promise.resolve()\n\n    return this._getBlockRange(actorId, first, last)\n    .then(blocks => this._applyBlocks(docId, blocks))\n    .then(() => this._loadMissingBlocks(docId))\n  }\n\n  _getBlockRange (actorId, first, last) {\n    const length = Math.max(0, last - first)\n\n    return Promise.all(Array(length).fill().map((_, i) =>\n      this._getBlock(actorId, first + i)))\n  }\n\n  _getBlock (actorId, index) {\n    return _promise(cb => {\n      this.feed(actorId).get(index, cb)\n    })\n  }\n\n  _applyBlock (docId, block) {\n    return this._applyBlocks(docId, [block])\n  }\n\n  _applyBlocks (docId, blocks) {\n    return this._applyChanges(docId, blocks.map(block => JSON.parse(block)))\n  }\n\n  _applyChanges (docId, changes) {\n    return changes.length > 0\n      ? this._setRemote(Automerge.applyChanges(this.find(docId), changes))\n      : this.find(docId)\n  }\n\n  // tracks which blocks have been requested for a given doc,\n  // so we know not to request them again\n  _maxRequested (docId, actorId, max) {\n    if (!this.requestedBlocks[docId]) this.requestedBlocks[docId] = {}\n\n    const current = this.requestedBlocks[docId][actorId] || START_BLOCK\n    this.requestedBlocks[docId][actorId] = Math.max(max, current)\n    return current\n  }\n\n  _addToMaxRequested (docId, actorId, x) {\n    if (!this.requestedBlocks[docId]) this.requestedBlocks[docId] = {}\n    this.requestedBlocks[docId][actorId] = (this.requestedBlocks[docId][actorId] || START_BLOCK) + x\n  }\n\n  _setRemote (doc) {\n    const docId = this.getId(doc)\n\n    this.set(doc)\n\n    if (this.readyIndex[docId] && !this.isMissingDeps(docId)) {\n      const pDoc = this.pDocs[docId]\n\n      this.pDocs[docId] = doc\n\n      /**\n       * Emitted when an updated document has been downloaded.\n       *\n       * @event document:updated\n       * @param {string} docId - the hex id representing this document\n       * @param {Document} document - automerge document\n       * @param {Document} prevDocument - previous version of the document\n       */\n      this.emit('document:updated', docId, doc, pDoc)\n    }\n  }\n\n  _shareDoc (doc) {\n    const {groupId} = this.metadata(this.getActorId(doc))\n    const keys = this.groupIndex[groupId]\n    this.message(groupId, {type: 'FEEDS_SHARED', keys})\n  }\n\n  _relatedKeys (actorId) {\n    const {groupId} = this.metadata(actorId)\n    return this.groupIndex[groupId]\n  }\n\n  _messagePeer (peer, msg) {\n    const data = Buffer.from(JSON.stringify(msg))\n    peer.stream.extension('hypermerge', data)\n  }\n\n  _onMultiCoreReady () {\n    return () => {\n      const actorIds =\n        Object.values(this.core.archiver.feeds)\n        .map(feed => feed.key.toString('hex'))\n\n      this._initFeeds(actorIds)\n      .then(() => {\n        this.isReady = true\n        actorIds.forEach(actorId => this.feed(actorId))\n        this.emit('ready', this)\n      })\n    }\n  }\n\n  _onDownload (docId, actorId) {\n    return (index, data) => {\n      this._applyBlock(docId, data)\n      this._loadMissingBlocks(docId)\n    }\n  }\n\n  _onPeerAdded (actorId) {\n    return peer => {\n      peer.stream.on('extension', this._onExtension(actorId, peer))\n\n      this._loadMetadata(actorId)\n      .then(() => {\n        if (!this.isDocId(actorId)) return\n\n        const keys = this._relatedKeys(actorId)\n        this._messagePeer(peer, {type: 'FEEDS_SHARED', keys})\n\n        this.emit('peer:joined', actorId, peer)\n      })\n    }\n  }\n\n  _onPeerRemoved (actorId) {\n    return peer => {\n      this._loadMetadata(actorId)\n      .then(() => {\n        if (!this.isDocId(actorId)) return\n\n        this.emit('peer:left', actorId, peer)\n      })\n    }\n  }\n\n  _onExtension (actorId, peer) {\n    return (name, data) => {\n      switch (name) {\n        case 'hypermerge':\n          return this._onMessage(actorId, peer, data)\n        default:\n          this.emit('peer:extension', actorId, name, data, peer)\n      }\n    }\n  }\n\n  _onMessage (actorId, peer, data) {\n    const msg = JSON.parse(data)\n\n    switch (msg.type) {\n      case 'FEEDS_SHARED':\n        return msg.keys.map(actorId => this.feed(actorId))\n      default:\n        this.emit('peer:message', actorId, peer, msg)\n    }\n  }\n\n  _onConnection (docId, actorId) {\n    return (conn, info) => {\n      console.log('_onConnection', conn, info)\n    }\n  }\n\n  _onListening () {\n    return (...args) => {\n      // console.log('_onListening', ...args)\n    }\n  }\n\n  _emitReady (docId) {\n    const doc = this.find(docId)\n    this.pDocs[docId] = doc\n\n    /**\n     * Emitted when a document has been fully loaded.\n     *\n     * @event document:ready\n     * @param {string} docId - the hex id representing this document\n     * @param {Document} document - automerge document\n     */\n    this.emit('document:ready', docId, doc)\n  }\n\n  _ensureReady () {\n    if (!this.isReady) throw new Error('Hypermerge is not ready yet. Use .once(\"ready\") first.')\n  }\n}\n\nfunction _promise (f) {\n  return new Promise((resolve, reject) => {\n    f((err, x) => {\n      err ? reject(err) : resolve(x)\n    })\n  })\n}\n"]}