Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/telamon/piconet
Minimal and opinionated network stack
https://github.com/telamon/piconet
Last synced: 3 months ago
JSON representation
Minimal and opinionated network stack
- Host: GitHub
- URL: https://github.com/telamon/piconet
- Owner: telamon
- License: agpl-3.0
- Created: 2020-11-27T01:08:29.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2024-07-31T17:14:35.000Z (3 months ago)
- Last Synced: 2024-08-01T17:08:51.263Z (3 months ago)
- Language: JavaScript
- Size: 213 KB
- Stars: 6
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-starred - telamon/piconet - Minimal and opinionated network stack (others)
README
[`pure | π¦`](https://github.com/telamon/create-pure)
[`code style | standard`](https://standardjs.com/)
```ascii
____ _ _ _ _
| _ \(_) ___ ___ | \ | | ___| |_
| |_) | |/ __/ _ \| \| |/ _ \ __|
| __/| | (_| (_) | |\ | __/ |_
|_| |_|\___\___/|_| \_|\___|\__|
Minimal network stack
```This library is a redesign of network interactions.
It started as a separation layer between Application and Network,
solving the need to factor out Network when debugging
the application.Initial design specs:
- want a single solid error handler.
- want a single method to close/destroy/end the connection.
- want application to be transport/runtime/lock-in agnostic.
- want nodes using piconet over multiple protocols to form a bridge between networks.
- no more EventEmitters. Use Promises
- no network in tests and simulation.> Disclaimer: no responsibilities taken π¦Άπ«
## 3.x spec
**Receiver** `Array(2)`
The resolved return value of a Transmitter
contains the received message and next transmitter if so signaled by other end.
```js
rx[0] // message: Buffer
rx[1] // transmitter: Function?
```**Transmitter** `async function`
Functions `postMessage` and `replyTo` are considered transmitters.
They take exactly 2 arguments;```js
@param {Buffer} message
@param {Boolean} flag, default: false
```**Plug**
```
/* State: 4 getters */
plug.id // {string} `writable` optional wire label
plug.isActive // {boolean} true when other end is open and not closed.
plug.isClosed // {boolean} true after any end is closed.
plug.other // {Plug} reference to other end/* Actions: 3 methods */
plug.open(handler|plug) // {function} broadcast receiver
splices two wires together if passed a plug.plug.close(Error?) // Disconnect with optional error
// Transmit
plug.postMessage(data: Buffer, replyExpected: boolean) // => [message, replyTo]/* Events: 2 */
await plug.opened // {Promise} `readonly` resolves if/when both ends
are plugged in.
await plug.closed // {Promise} `readonly` resolves when any end is
closed.
```## Use
```bash
$ yarn add piconet
```## Examples
Anything that is pushed into one wire end; emerges at the other.
```js
import { picoWire } from 'piconet'
const [plugA, plugB] = picoWire({ id: 'OptionalLabel })plugA.onmessage = (data, replyTo) => console.log('A received:', data)
plugB.postMessage(Buffer.from('Hello A!'))// => A received: Hello A!
```When sending a message, you can `await` a reply:
```js
const [plugA, plugB] = picoWire({ id: 'OptionalLabel })plugA.onmessage = (data, replyTo) => {
console.log('A received:', data)
replyTo('Hey B!')
}// Second parameter flags 'replyExpected' as true
const [data, replyTo] = await plugB.postMessage(Buffer.from('Hello A!'), true)
console.log('B received:', data)// => A received: Hello A!
// => B received: Hey B!
```This can be used to hold an conversation:
```js
const [a, b] = picoWire()a.onmessage = ([data, replyTo]) => {
console.log('A received:', data)
replyTo('Hello Bob', true)
.then(([data, replyTo]) => {
console.log('A received:', data)
return replyTo('No AFAIK we are communicating over latched Promises', true)
})
.then(([data, replyTo]) => {
console.log('A received:', data)
return replyTo('Yes way! We can debug-step between nodes! :o', true)
})
.then(([data, replyTo]) => {
console.log('A received:', data)
return replyTo('Yup! :> a wire without network', true)
})
.then(([data, replyTo]) => {
console.log('A received:', data)
return replyTo('Do not worry, check the transport section', false)
})
}await b.postMessage('Hey Alice!', true)
.then(([data, replyTo]) => {
console.log('B received:', data)
return replyTo('Is this data transmitted over network?', true)
})
.then(([data, replyTo]) => {
console.log('B received:', data)
return replyTo('No way??', true)
})
.then(([data, replyTo]) => {
console.log('B received:', data)
return replyTo('Holy Mango! But then there is no actual network?', true)
})
.then(([data, replyTo]) => {
console.log('B received:', data)
return replyTo('That sounds a bit... illogical', true)
})
.then(([data, replyTo]) => console.log('B received:', data))
```Outputs:
```bash
A received: Hey Alice!
B received: Hello Bob
A received: Is this data transmitted over network?
B received: No AFAIK we are communicating over latched Promises
A received: No way??
B received: Yes way! We can debug-step between nodes! :o
A received: Holy Mango! But then there is no actual network?
B received: Yup! :> a wire without network
A received: That sounds a bit... illogical
B received: Do not worry, check the transport section
```## RPC
And to build an remote procedure call service```js
import { Hub } from 'piconet'const rpc = new Hub(async (plug, message, replyTo) => {
const command = message.toString()
switch (command) {
case 'hello':
await replyTo('Hi there')
breakcase 'time':
await replyTo(Date.now() + '')
breakcase 'get_price': {
const [subCommand, r] = replyTo('get price of?', true)
const table = {
'ice-cream': 3,
'beer': 2,
'freedom': Infinity
}
await r(table[subCommand])
}default:
await replyTo('InvalidCommand')
plug.close()
}
})rpc.createWire() // => Plug
```## Transports
When the App's tests pass,
it's time to switch protocols.Here's an example that acts as a bridge between
tcp, hyperswarm and Websocket.
###```js
import { createConnection } from 'node:net'
import {
picoWire,
hyperWire,
wsWire,
streamWire,
Hub
} from 'piconet'const repeater = new Hub() // default mode: dumb repeater
// Connect TCP localhost:5554
const stream = createConnection({ port: '5554' })
streamWire(repeater.createWire(), stream)// Websocket
wsWire(
repeater.createWire(),
new Websocket('wss://someplatform.tld')
)// hyperWire
TODO: haven't looked at hyperswarm-v3 yet;
hyperWire(repeater.createWire(), secretStream, key)// Transmit on all channels
const plug = repeater.createWire()
await plug.postMessage('Cross-protocol hello!')
```
---Developed by Decent Labs 2023 - AGPL - Discord: https://discord.gg/8RMRUPZ9RS