OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb / hyper-social / hyper-wiki / lib / wiki.js

96 lines · javascript ref:
import Corestore from 'corestore'
import Hyperswarm from 'hyperswarm'
import { WikiStore } from './wiki-store.js'
import { SearchIndex } from './search.js'

class Wiki {
  constructor (storage, opts = {}) {
    this._storage = storage
    this._key = opts.key || null
    this._store = null
    this._wiki = null
    this._search = null
    this._swarm = null
    this._ready = false
    this._replicate = opts.replicate ?? false
  }

  async ready () {
    if (this._ready) return

    // Single shared Corestore for all components
    this._store = new Corestore(this._storage)

    this._wiki = new WikiStore(this._store, { key: this._key })
    await this._wiki.ready()

    this._search = new SearchIndex(this._store)
    await this._search.ready()

    if (this._replicate) {
      this._swarm = new Hyperswarm()
      this._swarm.on('connection', (conn) => {
        this._store.replicate(conn)
      })
      const topic = this._wiki.discoveryKey
      if (topic) {
        this._swarm.join(topic, { server: true, client: true })
      }
    }

    this._ready = true
  }

  get key () {
    return this._wiki?.key || null
  }

  async create (slug, content, meta = {}) {
    await this.ready()
    const result = await this._wiki.put(slug, content, meta)
    await this._search.index(slug, content, { ...meta, ...result })
    return result
  }

  async read (slug) {
    await this.ready()
    return this._wiki.get(slug)
  }

  async update (slug, content, meta = {}) {
    return this.create(slug, content, meta)
  }

  async remove (slug) {
    await this.ready()
    await this._wiki.del(slug)
    await this._search.remove(slug)
  }

  async exists (slug) {
    await this.ready()
    return this._wiki.exists(slug)
  }

  async list () {
    await this.ready()
    return this._wiki.list()
  }

  async search (query, limit = 20) {
    await this.ready()
    return this._search.search(query, limit)
  }

  async close () {
    if (this._swarm) {
      await this._swarm.destroy()
    }
    await this._wiki.close()
    if (this._store) await this._store.close()
    this._ready = false
  }
}

export { Wiki }