This commit is contained in:
Raven Scott
2026-05-20 23:36:32 -04:00
parent a020270cb1
commit be94546cd3
218 changed files with 9189 additions and 3078 deletions
@@ -1,33 +1,86 @@
# hyper-bare-bundle-bridge
Production module: Bundle bridge.
Register Bare bundle manifests by id and resolve them locally; gossip `bundle-register` on a Pear/Hyperswarm topic.
**Protocol:** `bare-bundle-bridge/v1`
**Category:** pear-platform · **Protocol:** `bare-bundle-bridge/v1` · **Exports:** `HyperBareBundleBridge`, `HyperP2PBareBundleBridge`, `PROTOCOL`
## When to use
Bundle manifest gossip.
Distributed catalog of bundle manifests before load/run on Bare.
## When not to use
Local bundles only.
Single static bundle path with no peer registry.
## Quick start
```js
const { HyperBareBundleBridge } = require('hyper-bare-bundle-bridge')
const m = new HyperBareBundleBridge()
await m.ready()
await m.close()
const bridge = new HyperBareBundleBridge({ topic: 'bundles' })
await bridge.ready()
bridge.registerBundle('app-v1', { entry: './index.js', files: ['index.js'] })
console.log(bridge.resolve('app-v1'))
await bridge.close()
```
## Docs
- [docs/api.md](docs/api.md)
- [docs/architecture.md](docs/architecture.md)
- [docs/api.md](docs/api.md) · [docs/architecture.md](docs/architecture.md)
## Test
```bash
npm install && npm test
npm test
```
## API
| Member | Description |
|--------|-------------|
| `new HyperBareBundleBridge(opts?)` | `topic`, `keyPair`. |
| `registerBundle(id, manifest)` | `manifest` must be object; gossips register. |
| `resolve(id)` | Entry or `null`; increments `resolved` stat on hit. |
| `listBundles()` | All `{ id, manifest, registeredAt }`. |
| `getStats()` | `{ registered, resolved, gossipIn, gossipOut, bundles, protocol }`. |
| `ready()` / `close()` | Swarm when `topic` set. |
**Events:** `registered`, `closed`. Remote register only if `id` not already local.
## Architecture
```
_bundles Map(id -> { id, manifest, registeredAt })
First local registration wins for id; remote fills gaps only
```
Alias export `HyperP2PBareBundleBridge` for registry naming consistency.
## Wire table
| `type` | Fields | Direction |
|--------|--------|-----------|
| `bundle-register` | `id`, `manifest` | Any → all |
## Errors
- Non-object `manifest` on `registerBundle`.
- Empty `id` on `registerBundle` / `resolve`.
## Composition
- Manifest schema is app-defined (entry, files, hashes).
- `hyper-bare-distributable-hint` supplies layout before register.
- `hyper-pear-update-gossip` can publish versioned manifest updates.
## Example
```js
const { HyperBareBundleBridge } = require('hyper-bare-bundle-bridge')
const bridge = new HyperBareBundleBridge({ topic: process.argv[2] })
await bridge.ready()
bridge.registerBundle('app-v1', { entry: './index.js', files: ['index.js'] })
console.log(bridge.resolve('app-v1'))
await bridge.close()
```
@@ -1,26 +1,102 @@
# API: hyper-bare-bundle-bridge
**Protocol:** `bare-bundle-bridge/v1` · **Export:** `HyperBareBundleBridge`
**Protocol:** `bare-bundle-bridge/v1` · **Export:** `HyperBareBundleBridge`, `HyperP2PBareBundleBridge`, `PROTOCOL`
## Overview
Registers Bare application bundle manifests by id and gossips registrations across a Hyperswarm topic. Peers merge remote `bundle-register` messages into a local map for offline resolution without a central registry.
## Constructor
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `topic` | `string` \| `Buffer` | `null` | Hyperswarm discovery topic; omit for local-only |
| `keyPair` | `KeyPair` | `hypercore-crypto.keyPair()` | Local peer identity for swarm |
## Methods
### `registerBundle(...)`
### `registerBundle(id, manifest)`
Domain API.
Stores `{ id, manifest, registeredAt }` and gossips registration.
### `resolve(...)`
- **Returns:** entry object
- **Throws:** `assertNonEmpty` on `id`; `manifest must be an object`
- **Gossip:** `{ type: 'bundle-register', id, manifest }`
Domain API.
### `resolve(id)`
### `listBundles(...)`
Looks up a bundle by id.
Domain API.
- **Returns:** entry or `null`
- **Throws:** `assertNonEmpty` on `id`
### `listBundles()`
### `getStats()` / `ready()` / `close()`
- **Returns:** array of all registered entries
Lifecycle helpers.
### `ready()`
Calls `initModuleSwarm` when `topic` is set and swarm not yet started. No-op if `topic` is null.
- **Returns:** `this`
### `close()`
Destroys swarm if present.
- **Emits:** `closed`
## Events
| Event | Payload |
|-------|---------|
| `registered` | `{ id, manifest, registeredAt }` |
| `closed` | — |
## getStats()
| Field | Meaning |
|-------|---------|
| `registered` | Local register count |
| `resolved` | Successful resolve calls |
| `gossipIn` / `gossipOut` | Mesh message counts |
| `bundles` | Current map size |
| `protocol` | `bare-bundle-bridge/v1` |
## Wire
| type | fields | direction | behavior |
|------|--------|-----------|----------|
| `bundle-register` | `id`, `manifest` | gossip | Insert if id not held locally |
## Errors
Empty `id` rejected via `assertNonEmpty` from [`../../_shared/lib/errors.js`](../../_shared/lib/errors.js). Invalid manifest type throws `manifest must be an object`.
See [`../../_shared/ERROR_CODES.md`](../../_shared/ERROR_CODES.md).
## P2P
Joins Hyperswarm when `topic` is set.
Gossip runs only after `ready()` with a non-null `topic`. Without `topic`, registrations are local-only and `_gossip` is a no-op.
## Testing
```bash
cd modules/pear-platform/hyper-bare-bundle-bridge && npm test
```
Covers local register/resolve and mesh merge when topic is configured.
## Composition
Use with `hyper-bare-distributable-hint` for layout hints and `hyper-pear-update-gossip` for versioned manifest updates on the same Pear mesh.
Pair with `hyper-p2p-peer-bootstrap-store` when bundle peers need bootstrap hints.
## Example
See [`examples/basic.js`](../examples/basic.js).
## See also
[`docs/architecture.md`](architecture.md), [`../../MODULE_CATEGORIES.md`](../../MODULE_CATEGORIES.md).
@@ -1,11 +1,33 @@
# Architecture: hyper-bare-bundle-bridge
**Protocol:** `bare-bundle-bridge/v1` · **Category:** pear-platform
```mermaid
flowchart LR
App --> Bridge[HyperBareBundleBridge]
Bridge --> Map[_bundles Map]
Bridge --> Gossip[p2p-bare]
Gossip --> Peers
```
## Wire messages
| type | fields | direction | behavior |
|------|--------|-----------|----------|
| `bundle-register` | id, manifest | gossip | Register |
| type | direction | fields | behavior |
|------|-----------|--------|----------|
| `bundle-register` | gossip | `id`, `manifest` | Insert entry if `id` not already in `_bundles` |
## State
## State model
In-memory structures; gossip via `initModuleSwarm` / `gossipSend` when P2P enabled.
- `_bundles`: `Map<id, { id, manifest, registeredAt }>`
- `_stats`: counters for register, resolve, gossip in/out
- `swarm` / `_peerMsgs`: set by `initModuleSwarm` when P2P enabled
## Sequence
1. `ready()` joins topic with protocol `bare-bundle-bridge/v1`
2. `registerBundle` writes locally and `gossipSend`s `bundle-register`
3. `_onGossip` merges unknown ids from peers
## Composition
`hyper-bare-distributable-hint`, `hyper-pear-update-gossip`, `hyper-p2p-peer-bootstrap-store`.