@kree4js/kree4n
v1.0.11
Published
Kreex For Node.js
Readme
@kree4js/kree4n
Kree4X on NodeJS.
Seamless cross-browser, cross-language communication with mutual service calls.
The Node.js runtime for Kree4JS, bundling all transport providers (HTTP, HTTP/2, TCP, UDP, Socket.IO) and Node.js-specific Worker support.
Installation
npm install @kree4js/kree4nQuick Start
import { create } from '@kree4js/kree4n'
const node = create('my-node-name', 'My Node Description')
// Register a service, PlainObject or ClassInstance is enough
node.register('greeter', {
hello(name) {
return `Hello, ${name}!`
}
})
// Start listening
await node.listen('tcp://0.0.0.0:9000')Connect to a remote node
import { create } from '@kree4js/kree4n'
const node = create('client', 'Client Node')
node.attach('tcp://server-host:9000')
const greeter = node.service('greeter')
const result = await greeter.hello('World')Peer-to-peer service call
Kree4X has no strict client/server concept — nodes are symmetric peers. listen/attach only differ in connection direction; once connected, either side can register and call services.
import { create } from '@kree4js/kree4n'
// Node A: listen and register a service
const nodeA = create('node-a')
nodeA.register('math', { add(a, b) { return a + b } })
nodeA.listen('tcp://127.0.0.1:8500')
await nodeA.start()
// Node B: attach and call node A's service
const nodeB = create('node-b')
nodeB.attach('tcp://127.0.0.1:8500')
await nodeB.start()
const math = nodeB.service('math')
console.log(await math.add(1, 2)) // 3
// Peers are symmetric: node A can call node B's service too
nodeB.register('echo', { ping() { return 'pong' } })
const echo = nodeA.service('echo')
console.log(await echo.ping()) // pongCross-protocol indirect communication
Nodes using different transport protocols can still communicate indirectly: an intermediate proxy node relays service calls across protocols. Enable proxyMode on the proxy so it forwards discovery and requests across the mesh.
import { create, Transports } from '@kree4js/kree4n'
const { ServiceFindWaitPolicy } = Transports
// Node C: UDP backend service reachable only via the proxy
const nodeC = create('node-c')
nodeC.register('greet', { hello(name) { return `Hello, ${name}! (from node-c via UDP)` } })
nodeC.listen('udp://127.0.0.1:8510', { frameLimit: 1152, ack: true })
await nodeC.start()
// Proxy: relays between protocols - UDP toward node C, TCP toward node A
const proxy = create('proxy', undefined, { transport: { proxyMode: true } })
// UDP → node C
proxy.attach('udp://127.0.0.1:8510', { frameLimit: 1152, ack: true })
// TCP ← node A
proxy.listen('tcp://127.0.0.1:8511')
await proxy.start()
// Node A: TCP caller, indirectly calls the UDP node C via the proxy
const nodeA = create('node-a')
// TCP → proxy
nodeA.attach('tcp://127.0.0.1:8511')
await nodeA.start()
const greet = nodeA.service('greet')
greet.waitServiceFind(ServiceFindWaitPolicy.one(5000)) // wait for discovery via the proxy
console.log(await greet.hello('World')) // Hello, World! (from node-c via UDP)DSE (Distributed Service Events)
DSE turns an EventEmitter into a distributed service: remote nodes can subscribe to events published on the owning node.
Requires the @kree4js/dse package:
npm install @kree4js/dse @kree4js/commons-eventsimport { EventEmitter } from '@kree4js/commons-events'
import { PromiseUtils } from '@kree4js/commons-lang'
import { enableDse } from '@kree4js/dse'
import { create } from '@kree4js/kree4n'
// Callee: listen, then register an EventEmitter as a service
const callee = enableDse(create('callee'))
callee.listen('tcp://127.0.0.1:8520')
await callee.start()
const emitter = new EventEmitter()
callee.register('news', emitter)
// Caller: attach and subscribe to remote events via proxy
const caller = enableDse(create('caller'))
caller.attach('tcp://127.0.0.1:8520')
await caller.start()
// use "eventService" to create EventService stub.
const news = caller.eventService('news')
news.on('headline', (payload) => {
console.log('Caller received:', payload)
})
// Give the remote subscription a moment to register before publishing
await PromiseUtils.delay(100)
// Callee publishes; caller receives it across nodes
emitter.emit('headline', 'Hello from DSE!')WaitPolicy + SelectPolicy + ReducePolicy
Combine the three policies on a service cluster: wait for enough providers to be discovered, select which providers to call, then reduce their results.
import { create, SelectPolicy, ReducePolicy, Transports } from '@kree4js/kree4n'
const { ServiceFindWaitPolicy } = Transports
// 3 service nodes, each providing 'sensor' with a distinct value
for (let i = 1; i <= 3; i++) {
const node = create(`node-${i}`)
node.register('sensor', { read() { return i * 10 } })
node.listen(`tcp://127.0.0.1:${8530 + i}`)
await node.start()
}
const caller = create('caller')
for (let i = 1; i <= 3; i++) caller.attach(`tcp://127.0.0.1:${8530 + i}`)
await caller.start()
const sensor = caller.service('sensor')
// Wait: block until 3 providers are discovered (or timeout after 5s)
sensor.waitServiceFind(ServiceFindWaitPolicy.three(5000))
// Select: call all providers
sensor.select(new SelectPolicy.SelectAll())
// Reduce: sum the results (10 + 20 + 30)
sensor.reduce(new ReducePolicy.ReduceSumNumber())
const sum = await sensor.read()
console.log(sum) // 60Included Connection Providers
| Provider | Model | URL |
|----------|-------|-----|
| http-listen | Listen | http://…, https://… |
| http-attach | Attach | http://…, https://… |
| http2-listen | Listen | http2://…, https2://… |
| http2-attach | Attach | http2://…, https2://… |
| tcp-listen | Listen | tcp://… |
| tcp-attach | Attach | tcp://… |
| udp-listen | Listen | udp://… |
| udp-attach | Attach | udp://… |
| socketio-listen | Listen | io://… |
| socketio-attach | Attach | io://… |
| websocket-attach | Attach | ws://…, wss://… |
License
Apache-2.0
