feat(search): Phase 627 search hub depth (v0.8.590)
Extend search hub/panel live regions with active channel context and mesh notes; tighten search-errors reaction bleed exclusion; refresh composer search hints for hub and panel; platform guild.search.cache/mesh spans include activeChannelId; agentctl and phase627 smoke bundle.
This commit is contained in:
@@ -1,28 +1,119 @@
|
|||||||
# pearcord-db
|
# pearcord-db
|
||||||
|
|
||||||
HyperDB schema build and local Rocks/JSON database adapter.
|
Local persistence for Pearcord: HyperDB (RocksDB) when the schema is built, with automatic fallback to a JSON file store.
|
||||||
|
|
||||||
Part of **[Pearcord](https://git.ssh.surf/pearcord)** — 100% peer-to-peer community chat on [Pear](https://pear.holepunch.to). No central servers.
|
## Mission
|
||||||
|
|
||||||
|
Offer one `LocalDatabase` class that serializes all reads/writes, picks the best engine at runtime, and exposes a minimal `insert` / `get` / `find` / `delete` API aligned with `@pearcord/*` collections from `pearcord-shared`.
|
||||||
|
|
||||||
|
## When to use / not
|
||||||
|
|
||||||
|
**Use when:**
|
||||||
|
|
||||||
|
- Any module needs durable guild, user, message, or invite rows on disk.
|
||||||
|
- You want engine-agnostic storage (`hyperdb` vs `json`) without branching in callers.
|
||||||
|
|
||||||
|
**Do not use when:**
|
||||||
|
|
||||||
|
- You only need in-memory structures or P2P gossip without local materialization.
|
||||||
|
- You need Autobase multi-writer replication — planned in `pearcord-sync` (not wired yet).
|
||||||
|
|
||||||
|
## Public API
|
||||||
|
|
||||||
|
| Export | Role |
|
||||||
|
|--------|------|
|
||||||
|
| `LocalDatabase` | Main facade (`storagePath` → `db/` directory) |
|
||||||
|
| `LocalDatabase#ready()` | Opens HyperDB or `JsonStore` backend |
|
||||||
|
| `LocalDatabase#insert(collection, record)` | Upsert by collection primary key |
|
||||||
|
| `LocalDatabase#get(collection, query)` | Single-row lookup |
|
||||||
|
| `LocalDatabase#find(collection, query, opts?)` | Query; supports `{ limit }`; normalizes async iterators |
|
||||||
|
| `LocalDatabase#delete(collection, query)` | Remove matching row |
|
||||||
|
| `LocalDatabase#close()` | Close backend |
|
||||||
|
| `LocalDatabase#getEngine()` | `'hyperdb'` or `'json'` |
|
||||||
|
| `hasHyperDB` | `true` if `hyperdb` + generated `spec/hyperdb` loaded |
|
||||||
|
| `jsonStoreHasUsers(storagePath)` | Migration probe: legacy JSON has users |
|
||||||
|
| `JsonStore` | Subpath export `pearcord-db/store-json` — standalone JSON backend |
|
||||||
|
|
||||||
|
`LocalDatabase` uses an internal promise chain (`_serialize`) so concurrent mutations do not interleave.
|
||||||
|
|
||||||
|
## P2P surface
|
||||||
|
|
||||||
|
None. This module is local-only. Peers replicate via gossip into the same collections on other devices; `pearcord-guild` writes inbound RPC payloads through platform handlers that call `db.insert`.
|
||||||
|
|
||||||
|
## Storage
|
||||||
|
|
||||||
|
| Engine | Path | When |
|
||||||
|
|--------|------|------|
|
||||||
|
| HyperDB | `{storagePath}/` (RocksDB files) | `hyperdb` installed and `spec/hyperdb/index.js` exists after `npm run build:schema` |
|
||||||
|
| JSON | `{storagePath}/pearcord-db.json` | Fallback if HyperDB unavailable, or HyperDB empty while JSON already has users |
|
||||||
|
|
||||||
|
Platform default path: `{PEARCORD_STORAGE or ~/.config/pearcord}/db`.
|
||||||
|
|
||||||
|
DM metadata uses a separate `JsonStore` at `{storagePath}/dm-meta` (platform-only).
|
||||||
|
|
||||||
|
## Platform integration
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const { LocalDatabase } = require('pearcord-db')
|
||||||
|
// PearcordPlatform constructor:
|
||||||
|
this.dbPath = path.join(this.storagePath, 'db')
|
||||||
|
this.db = new LocalDatabase(this.dbPath)
|
||||||
|
```
|
||||||
|
|
||||||
|
Shared by `pearcord-identity`, `pearcord-guild`, `pearcord-message`, `pearcord-invite`, and direct platform queries (`listGuilds`, search, audit). Platform checks `this.db.getEngine()` for HyperDB-optimized message scans.
|
||||||
|
|
||||||
|
## UI / IPC
|
||||||
|
|
||||||
|
No direct UI dependency. All IPC flows go through `pearcord-platform`, which owns the single `LocalDatabase` instance per session.
|
||||||
|
|
||||||
|
## Related docs
|
||||||
|
|
||||||
|
- [HYPERDB.md](../../docs/HYPERDB.md) — schema build, collections, v9 `replyToId`
|
||||||
|
- [MODULES.md](../../docs/MODULES.md) — dependency graph
|
||||||
|
- [ARCHITECTURE.md](../../docs/ARCHITECTURE.md) — storage layout
|
||||||
|
- [GETTING_STARTED.md](../../docs/GETTING_STARTED.md) — `PEARCORD_STORAGE`
|
||||||
|
- [AUTOMATED_TESTING.md](../../docs/AUTOMATED_TESTING.md) — schema smoke targets
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
From `apps/pearcord`:
|
||||||
|
|
||||||
|
- `npm run test:hyperdb` — `smoke-hyperdb.cjs`
|
||||||
|
- `npm run test:schema-v9` — `smoke-schema-v9.cjs`
|
||||||
|
|
||||||
|
Both use `LocalDatabase` and `hasHyperDB` from this package.
|
||||||
|
|
||||||
|
## Code example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const path = require('bare-path')
|
||||||
|
const { LocalDatabase } = require('pearcord-db')
|
||||||
|
const { COLLECTIONS, id, now } = require('pearcord-shared')
|
||||||
|
|
||||||
|
const db = new LocalDatabase(path.join('/tmp/pearcord-demo', 'db'))
|
||||||
|
await db.ready()
|
||||||
|
console.log('engine:', db.getEngine())
|
||||||
|
|
||||||
|
await db.insert(COLLECTIONS.USERS, {
|
||||||
|
id: id(),
|
||||||
|
username: 'alice',
|
||||||
|
createdAt: now()
|
||||||
|
})
|
||||||
|
|
||||||
|
const users = await db.find(COLLECTIONS.USERS, {})
|
||||||
|
await db.close()
|
||||||
|
```
|
||||||
|
|
||||||
|
Build HyperDB schema:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd modules/pearcord-db && npm install && npm run build:schema
|
||||||
|
```
|
||||||
|
|
||||||
## Repository
|
## Repository
|
||||||
|
|
||||||
|
Part of **[Pearcord](https://git.ssh.surf/pearcord)**.
|
||||||
|
|
||||||
- **Org:** [`pearcord`](https://git.ssh.surf/pearcord)
|
- **Org:** [`pearcord`](https://git.ssh.surf/pearcord)
|
||||||
- **Clone:** `git clone https://git.ssh.surf/pearcord/pearcord-db.git`
|
- **Clone:** `git clone https://git.ssh.surf/pearcord/pearcord-db.git`
|
||||||
|
- **Install:** `npm install git+https://git.ssh.surf/pearcord/pearcord-db.git#main`
|
||||||
## Install (npm)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install git+https://git.ssh.surf/pearcord/pearcord-db.git#main
|
|
||||||
```
|
|
||||||
|
|
||||||
## Stack
|
|
||||||
|
|
||||||
Hyperswarm · HyperDB · Protomux · Pear / Bare
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
See [`pearcord/pearcord-docs`](https://git.ssh.surf/pearcord/pearcord-docs) for architecture, roadmap, and IPC reference.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Pearcord modules are developed for the Pearcord platform. See the org README for contribution guidelines.
|
|
||||||
|
|||||||
@@ -201,7 +201,8 @@ ns.register({
|
|||||||
fields: [
|
fields: [
|
||||||
{ name: 'guildId', type: 'string', required: true },
|
{ name: 'guildId', type: 'string', required: true },
|
||||||
{ name: 'channelId', type: 'string', required: true },
|
{ name: 'channelId', type: 'string', required: true },
|
||||||
{ name: 'slowmodeSeconds', type: 'uint', required: true }
|
{ name: 'slowmodeSeconds', type: 'uint', required: true },
|
||||||
|
{ name: 'description', type: 'string' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user