import Hyperdrive from 'hyperdrive'
import b4a from 'b4a'
class WikiStore {
constructor (store, opts = {}) {
this._store = store // Corestore instance (shared)
this._key = opts.key || null
this._drive = null
this._ready = false
}
async ready () {
if (this._ready) return
this._drive = this._key
? new Hyperdrive(this._store, this._key)
: new Hyperdrive(this._store)
await this._drive.ready()
this._ready = true
}
get key () {
return this._drive?.key || null
}
get discoveryKey () {
return this._drive?.discoveryKey || null
}
_pagePath (slug) {
return `/wiki/${slug}.md`
}
_metaPath (slug) {
return `/wiki/${slug}.meta.json`
}
async put (slug, content, meta = {}) {
await this.ready()
const now = Date.now()
const existing = await this.getMeta(slug)
const metadata = {
title: meta.title || existing?.title || slug,
author: meta.author || existing?.author || '',
created: existing?.created || now,
updated: now,
tags: meta.tags || existing?.tags || [],
version: (existing?.version || 0) + 1
}
await this._drive.put(this._pagePath(slug), b4a.from(content))
await this._drive.put(this._metaPath(slug), b4a.from(JSON.stringify(metadata)))
return metadata
}
async get (slug) {
await this.ready()
const buf = await this._drive.get(this._pagePath(slug))
if (!buf) return null
const meta = await this.getMeta(slug)
return {
slug,
content: b4a.toString(buf),
...meta
}
}
async getMeta (slug) {
await this.ready()
const buf = await this._drive.get(this._metaPath(slug))
if (!buf) return null
try {
return JSON.parse(b4a.toString(buf))
} catch {
return null
}
}
async del (slug) {
await this.ready()
await this._drive.del(this._pagePath(slug))
await this._drive.del(this._metaPath(slug))
}
async exists (slug) {
await this.ready()
const entry = await this._drive.entry(this._pagePath(slug))
return entry !== null
}
async list () {
await this.ready()
const pages = []
for await (const entry of this._drive.list('/wiki/')) {
const name = entry.key
if (name.endsWith('.md')) {
const slug = name.replace('/wiki/', '').replace('.md', '')
const meta = await this.getMeta(slug)
pages.push({
slug,
title: meta?.title || slug,
updated: meta?.updated || 0,
version: meta?.version || 1
})
}
}
pages.sort((a, b) => b.updated - a.updated)
return pages
}
async close () {
if (this._drive) await this._drive.close()
this._ready = false
}
}
export { WikiStore }