Updates
Hyper-P2P Module Tests / unit-all (push) Failing after 1m4s
Hyper-P2P Module Tests / integration (push) Has been skipped

This commit is contained in:
Raven Scott
2026-05-20 18:50:27 -04:00
parent e1fb64e484
commit 6711365613
156 changed files with 24661 additions and 47 deletions
+2
View File
@@ -0,0 +1,2 @@
node_modules/
*-storage/
+6
View File
@@ -0,0 +1,6 @@
# Changelog
## [0.1.0] - 2026-05-20
### Added
- Initial v0.1.0 scaffold with Bare-compatible API, brittle tests, and docs.
+23
View File
@@ -0,0 +1,23 @@
# hyper-p2p-pattern-router
Bare/Pear P2P primitive — **pattern-router/v1**.
## Quick start
```js
const { HyperP2PPatternRouter } = require('hyper-p2p-pattern-router')
const mod = new HyperP2PPatternRouter()
// see examples/basic.js
await mod.close()
```
## Docs
- [docs/api.md](docs/api.md)
- [docs/architecture.md](docs/architecture.md)
## Test
```bash
npm test
```
+38
View File
@@ -0,0 +1,38 @@
# API: hyper-p2p-pattern-router
**Protocol:** `pattern-router/v1`
**Export:** `HyperP2PPatternRouter`
## Methods
- `addRoute`
- `route`
- `removeRoute`
## P2P and runtime options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `topic` | `string` \| `Buffer` | `null` | Hyperswarm discovery topic. Hex (64 chars) or string (hashed via `hypercore-crypto`). P2P is active when set. |
| `keyPair` | `KeyPair` | random | Ed25519 key pair (`hypercore-crypto.keyPair()`). |
### Runtime flags (test exit)
| Option | Modules | Default | Description |
|--------|---------|---------|-------------|
| `enableBackgroundTimers` | oracle, reputation | `false` | Enables periodic cleanup/decay/gossip timers. Keep `false` in unit tests so the process exits. |
| `enableGossip` | causal-consensus | `false` | Enables gossip interval + Protomux proposal fan-out when `topic` is also set. |
### Protomux
Wire format uses **Protomux v3** (`createChannel``addMessage``open`) via [`../_shared/p2p-bare.js`](../_shared/p2p-bare.js).
### Testing
```bash
npm install
npx brittle-bare test/test.js
```
Integration (2-node): [`../../real_tests/integration/`](../../real_tests/integration/) — see [DEVELOPMENT.md](../../DEVELOPMENT.md).
@@ -0,0 +1,10 @@
# Architecture: hyper-p2p-pattern-router
`pattern-router/v1` over Hyperswarm + Protomux when `topic` is set.
```mermaid
flowchart LR
App[Application] --> Mod[HyperP2PPatternRouter]
Mod --> P2P[Protomux pattern-router/v1]
P2P --> Swarm[Hyperswarm]
```
@@ -0,0 +1,11 @@
require('bare-process/global')
const { HyperP2PPatternRouter } = require('../index.js')
async function main () {
const r = new HyperP2PPatternRouter()
r.addRoute('ping.*', () => 'pong')
console.log(r.route({ route: 'ping.echo' }))
await r.close()
console.log('done')
}
main().catch(console.error)
+69
View File
@@ -0,0 +1,69 @@
require('bare-process/global')
const EventEmitter = require('bare-events')
const b4a = require('b4a')
const { initModuleSwarm } = require('../_shared/p2p-bare.js')
const PROTOCOL = 'pattern-router/v1'
function globToRegExp (pattern) {
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&')
const re = '^' + escaped.replace(/\*/g, '.*').replace(/\?/g, '.') + '$'
return new RegExp(re)
}
class HyperP2PPatternRouter extends EventEmitter {
constructor (opts = {}) {
super()
this.topic = opts.topic || null
this.keyPair = opts.keyPair || require('hypercore-crypto').keyPair()
this._routes = new Map()
this.swarm = null
this._peerMsgs = null
}
addRoute (pattern, handler) {
if (typeof handler !== 'function') throw new Error('handler must be a function')
this._routes.set(pattern, { pattern, re: globToRegExp(pattern), handler })
this.emit('route-added', { pattern })
return true
}
removeRoute (pattern) {
const ok = this._routes.delete(pattern)
if (ok) this.emit('route-removed', { pattern })
return ok
}
route (payload) {
const key = payload && (payload.route || payload.pattern || payload.type)
if (!key) return null
for (const { re, handler, pattern } of this._routes.values()) {
if (re.test(String(key))) {
const result = handler(payload)
this.emit('routed', { pattern, key })
return result
}
}
this.emit('unmatched', { key })
return null
}
async ready () {
if (this.swarm || !this.topic) return this
await initModuleSwarm(this, {
keyPair: this.keyPair,
topic: this.topic,
protocol: PROTOCOL,
onmessage: (data) => this.route(data)
})
return this
}
async close () {
if (this.swarm) await this.swarm.destroy().catch(() => {})
this.swarm = null
this.emit('closed')
}
}
module.exports = { HyperP2PPatternRouter, PROTOCOL }
File diff suppressed because it is too large Load Diff
+23
View File
@@ -0,0 +1,23 @@
{
"name": "hyper-p2p-pattern-router",
"version": "0.1.0",
"description": "Glob pattern message router for Bare/Pear P2P.",
"main": "index.js",
"type": "commonjs",
"license": "Apache-2.0",
"scripts": { "test": "brittle-bare test/test.js" },
"dependencies": {
"bare-events": "^2.8.0",
"bare-process": "^4.4.0",
"b4a": "^1.6.7",
"hypercore-crypto": "^3.0.0",
"protomux": "^3.0.0",
"compact-encoding": "^2.0.0"
},
"peerDependencies": { "hyperswarm": "^4.0.0", "bare": ">=1.0.0" },
"devDependencies": { "brittle": "^3.0.0" },
"imports": {
"process": { "bare": "bare-process", "default": "process" },
"events": { "bare": "bare-events", "default": "events" }
}
}
+19
View File
@@ -0,0 +1,19 @@
require('bare-process/global')
const test = require('brittle')
const { HyperP2PPatternRouter } = require('../index.js')
test('pattern-router: glob route', async (t) => {
const r = new HyperP2PPatternRouter()
r.addRoute('evt.*', (p) => p.route + '-ok')
t.is(r.route({ route: 'evt.foo' }), 'evt.foo-ok')
t.is(r.route({ route: 'other' }), null)
await r.close()
})
test('pattern-router: removeRoute', async (t) => {
const r = new HyperP2PPatternRouter()
r.addRoute('a', () => 1)
t.ok(r.removeRoute('a'))
t.not(r.route({ route: 'a' }))
await r.close()
})