diff --git a/.gitignore b/.gitignore
index 7f78ea9..00e8ee6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,3 +50,18 @@ packages/tcp/bin
packages/udp/bin
packages/ws/bin
packages/webrtc/bin
+
+# publish-only files
+packages/kalm/LICENSE
+packages/ipc/LICENSE
+packages/tcp/LICENSE
+packages/udp/LICENSE
+packages/ws/LICENSE
+packages/webrtc/LICENSE
+
+packages/kalm/CHANGELOG.md
+packages/ipc/CHANGELOG.md
+packages/tcp/CHANGELOG.md
+packages/udp/CHANGELOG.md
+packages/ws/CHANGELOG.md
+packages/webrtc/CHANGELOG.md
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..7715330
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,127 @@
+# Changelog
+
+## [v3.3.0] - 2020-01-30
+
+commit: [af46059](https://github.com/kalm/kalm.js/commit/af4605958c567b5243887f911850a3c0eb6c6659)
+
+### Added
+- Adds webrtc package and examples
+- Adds the getChannels method on Client
+
+### Removed
+- Removed home implementation of EventEmitter in favor of Node's
+
+## [v3.2.3] - 2020-01-14
+
+commit: [c188225](https://github.com/kalm/kalm.js/commit/c18822532a49f2026eddf44cfbe3cfc1521110f8)
+
+### Added
+- Added pre-hook for lint on commit
+
+### Changed
+- Cleaned up Types management and typings file accessibility
+- Migrated test suite to Jest and centralized test tooling
+- Removed output rollup, and using only tsc with none modules
+- Fixed linting (was not targeting .ts files properly)
+- Fixed stats events (were previously unreachable, now exposed through client emitter as .*)
+- Fixed timeout behavior (only logged, now actually disconnects)
+
+## [v3.1.2] - 2019-07-01
+
+commit: [fac8047](https://github.com/kalm/kalm.js/commit/fac8047d4b7048d56803505103159e16d8f518a8)
+
+### Changed
+- Changed dev tooling from lerna to yarn workspaces
+- Changed dev tooling from tslint to eslint + @typescript-eslint
+- Housekeeping
+
+## [v3.0.0] - 2019-01-18
+
+commit: [a4c687d](https://github.com/kalm/kalm.js/commit/a4c687dd5786a70723d9d0964a9d189220d58418)
+
+### Added
+- New monorepo structure
+- Massive new changes to the interface
+
+### Changed
+- Serialization is now a toggle for json/binary
+- Re-written the entire codebase in Typescript
+
+### Removed
+- Transports are no longer bundled and must be installed separately and must be instantiated with options.
+ - [ipc](https://www.npmjs.com/package/@kalm/ipc)
+ - [tcp](https://www.npmjs.com/package/@kalm/tcp)
+ - [udp](https://www.npmjs.com/package/@kalm/udp)
+ - [ws](https://www.npmjs.com/package/@kalm/ws)
+- Profiles become routines and must be instantiated with options.
+- No more session stores
+- No more encryption
+
+## [v2.6.1] - 2018-01-27
+
+commit: [7393d17](https://github.com/kalm/kalm.js/commit/7393d17efb02088d7283ba83108fd7ab15e3d39e)
+
+### Added
+- Added package-lock.json file
+- Added server reference in the client object
+
+## [v2.5.0] - 2017-09-21
+
+commit: [2c687f6](https://github.com/kalm/kalm.js/commit/2c687f6074787af6b39c10abe19669fe20e7b02d)
+
+### Added
+- Added engines reqs
+
+### Changed
+- Some minor performance tuning
+
+## [v2.4.0] - 2017-09-01
+
+commit: [a7b8f95](https://github.com/kalm/kalm.js/commit/a7b8f950da56cbe35c538dc02e3dcc0e6d3a3db3)
+
+### Changed
+- Tuned performances
+- Added build targets for Node 8.x and 6.x
+- UDP client cache (tied with socketTimeout)
+- Bumped dependencies
+- Proper callback on disconnect
+
+### Removed
+- Dropped support for Node 4.x
+
+## [v2.3.0] - 2017-07-25
+
+commit: [f323bcd](https://github.com/kalm/kalm.js/commit/f323bcdc163faa40b0f8515fd4a8759e5180f516)
+
+### Added
+- Added realtime profile
+- Added JSDoc
+- Added parameter validation and error messages
+
+### Changed
+- Better performances (3x with default congestion)
+
+## [v2.2.0] - 2017-06-21
+
+commit: [b9f3bdd](https://github.com/kalm/kalm.js/commit/b9f3bdd50de8dae2b92a0866d234a0cb2e72f22b)
+
+### Added
+- Added support for node 8
+
+## [v2.1.0] - 2017-06-20
+
+commit: [129146f](https://github.com/kalm/kalm.js/commit/129146feeab14e94a540a4d9c54e05a4614fdb39)
+
+### Changed
+- Simplified and optimized queue system logic
+- Now allowing 0 to be passed as tick value in profiles
+- Added warning when non-serialized message are sent and serial config is `null`
+- Fixed hanging packets on maxBytes just reached
+
+## [v2.0.0] - 2017-03-02
+
+commit: [b5209ec](https://github.com/kalm/kalm.js/commit/b5209ec4d3ab86000b72b502d120f0a5b4da85af)
+
+### Added
+- Migrated the codebase from the [original repo](https://github.com/fed135/kalm)
+- Implemeted new interface
diff --git a/jest.config.js b/jest.config.js
deleted file mode 100644
index ebe914b..0000000
--- a/jest.config.js
+++ /dev/null
@@ -1,9 +0,0 @@
-module.exports = {
- preset: 'ts-jest',
- testEnvironment: 'node',
- globals: {
- 'ts-jest': {
- diagnostics: false,
- },
- },
-};
diff --git a/package.json b/package.json
index 3e39537..e32220d 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
"scripts": {
"lint": "eslint **/*.ts **/*.spec.ts",
"lint:fix": "yarn lint --fix",
- "test": "jest ./packages && jest ./tests/integration --forceExit",
+ "test": "yarn workspaces run test && jest ./tests/integration --forceExit",
"build": "yarn workspaces run build",
"clean": "yarn workspaces run clean",
"bench": "node ./scripts/benchmarks"
@@ -39,23 +39,29 @@
"pre-commit": "yarn lint"
}
},
+ "jest": {
+ "preset": "ts-jest",
+ "testEnvironment": "node",
+ "globals": {
+ "ts-jest": {
+ "diagnostics": false,
+ "isolatedModules": true
+ }
+ }
+ },
"devDependencies": {
- "@types/jest": "^24.0.17",
- "@types/node": "^13.1.0",
- "@typescript-eslint/eslint-plugin": "^2.14.0",
- "@typescript-eslint/parser": "^2.14.0",
+ "@types/jest": "^25.1.0",
+ "@types/node": "^13.9.0",
+ "@typescript-eslint/eslint-plugin": "^2.24.0",
+ "@typescript-eslint/parser": "^2.24.0",
"eslint": "^6.8.0",
- "eslint-config-airbnb-base": "^14.0.0",
- "eslint-plugin-import": "^2.19.0",
- "husky": "^3.1.0",
- "jest": "^24.9.0",
+ "eslint-config-airbnb-base": "^14.1.0",
+ "eslint-plugin-import": "^2.20.0",
+ "husky": "^4.2.0",
+ "jest": "^25.1.0",
"socket.io": "^2.3.0",
"socket.io-client": "^2.3.0",
- "ts-jest": "^24.2.0",
- "typescript": "^3.7.4"
- },
- "dependencies": {
- "webpack": "^4.41.5",
- "webpack-cli": "^3.3.10"
+ "ts-jest": "^25.2.0",
+ "typescript": "^3.8.0"
}
}
diff --git a/packages/ipc/README.md b/packages/ipc/README.md
index 3b36d4b..2877d21 100644
--- a/packages/ipc/README.md
+++ b/packages/ipc/README.md
@@ -1,4 +1,22 @@
-# Kalm IPC (Inter-process-communication) transport
+
+
+
+
+
+ Kalm
+
+
+ The Socket Optimizer
+
+
+
+
+[![Kalm](https://img.shields.io/npm/v/kalm.svg)](https://www.npmjs.com/package/@kalm/ipc)
+[![Build Status](https://github.com/kalm/kalm.js/workflows/master-status/badge.svg)](https://github.com/kalm/kalm.js/actions?query=workflow%3A+master-status)
+![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/kalm/kalm.js)
+[![Financial Contributors on Open Collective](https://opencollective.com/kalm/all/badge.svg?label=financial+contributors)](https://opencollective.com/kalm)
+[![Join the chat at https://gitter.im/KALM/home](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/KALM/?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
## Installing
@@ -8,8 +26,8 @@
```
{
- socketTimeout = 30000,
- path = '/tmp/app.socket-'
+ socketTimeout: 30000,
+ path: '/tmp/app.socket'
}
```
diff --git a/packages/ipc/package.json b/packages/ipc/package.json
index fc87114..380555c 100644
--- a/packages/ipc/package.json
+++ b/packages/ipc/package.json
@@ -5,7 +5,9 @@
"main": "bin/ipc.js",
"scripts": {
"build": "../../scripts/build.sh ipc",
- "clean": "../../scripts/cleanup.sh"
+ "clean": "../../scripts/cleanup.sh",
+ "test": "jest ./tests",
+ "prepublish": "cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md"
},
"funding": {
"type": "Open Collective",
@@ -16,23 +18,11 @@
"url": "git+https://github.com/kalm/kalm-js.git"
},
"keywords": [
- "multiplex",
+ "framework",
"network",
- "optimize",
+ "realtime",
"socket",
- "websocket",
- "client",
- "server",
- "service",
- "peer",
- "micro",
- "latency",
- "messaging",
- "queue",
"nagle",
- "buffer",
- "protocol",
- "web",
"ipc"
],
"files": ["bin", "types.d.ts"],
@@ -49,5 +39,15 @@
"browser": {
"net": false,
"fs": false
+ },
+ "jest": {
+ "preset": "ts-jest",
+ "testEnvironment": "node",
+ "globals": {
+ "ts-jest": {
+ "diagnostics": false,
+ "isolatedModules": true
+ }
+ }
}
}
diff --git a/packages/ipc/src/ipc.ts b/packages/ipc/src/ipc.ts
index d408963..1d1f6db 100644
--- a/packages/ipc/src/ipc.ts
+++ b/packages/ipc/src/ipc.ts
@@ -13,7 +13,7 @@ interface IPCSocket extends net.Socket {
}
}
-export function ipc({ socketTimeout = 30000, path = '/tmp/app.socket-' }: IPCConfig = {}): KalmTransport {
+function ipc({ socketTimeout = 30000, path = '/tmp/app.socket-' }: IPCConfig = {}): KalmTransport {
return function socket(params: ClientConfig, emitter: NodeJS.EventEmitter): Socket {
let listener: net.Server;
@@ -25,8 +25,8 @@ export function ipc({ socketTimeout = 30000, path = '/tmp/app.socket-' }: IPCCon
function remote(handle: IPCSocket): Remote {
return {
- host: handle._server._pipeName,
- port: handle._handle.fd,
+ host: handle && handle._server && handle._server._pipeName || null,
+ port: handle && handle._handle && handle._handle.fd || null,
};
}
diff --git a/packages/ipc/tests/unit/ipc.spec.ts b/packages/ipc/tests/unit/ipc.spec.ts
index 392b854..b543f77 100644
--- a/packages/ipc/tests/unit/ipc.spec.ts
+++ b/packages/ipc/tests/unit/ipc.spec.ts
@@ -1,5 +1,40 @@
+import { EventEmitter } from 'events';
import * as ipc from '../../src/ipc';
describe('IPC transport', () => {
- it('TODO', () => { expect(ipc).not.toBeUndefined(); });
+ it('basic setup', () => {
+ expect(typeof ipc.default).toBe('function');
+ const transport = ipc.default();
+ expect(typeof transport).toBe('function');
+ const socket = transport({}, new EventEmitter());
+
+ expect(socket).toHaveProperty('bind', expect.any(Function));
+ expect(socket).toHaveProperty('connect', expect.any(Function));
+ expect(socket).toHaveProperty('disconnect', expect.any(Function));
+ expect(socket).toHaveProperty('remote', expect.any(Function));
+ expect(socket).toHaveProperty('stop', expect.any(Function));
+ expect(socket).toHaveProperty('send', expect.any(Function));
+ });
+
+ describe('Given an empty handle reference and no configs', () => {
+ const transport = ipc.default();
+ const socket = transport({}, new EventEmitter());
+
+ describe('when fetching remote', () => {
+ it('should return null values', () => {
+ expect(socket.remote()).toEqual({ host: null, port: null });
+ });
+ });
+ });
+
+ describe('Given a handle reference and no configs', () => {
+ const transport = ipc.default();
+ const socket = transport({}, new EventEmitter());
+
+ describe('when fetching remote', () => {
+ it('should return handle\'s values', () => {
+ expect(socket.remote({ _server: { _pipeName: '/foo' }, _handle: { fd: 12345 } })).toEqual({ host: '/foo', port: 12345 });
+ });
+ });
+ });
});
diff --git a/packages/kalm/README.md b/packages/kalm/README.md
index 88d9191..6eb67ed 100644
--- a/packages/kalm/README.md
+++ b/packages/kalm/README.md
@@ -47,12 +47,20 @@ Install the transport layer ('tcp' for example)
const kalm = require('kalm');
const ws = require('@kalm/ws');
-const Server = kalm.listen({
+const server = kalm.listen({
port: 8800,
transport: ws(),
routine: kalm.routines.tick({ hz: 5 }), // Sends packets at a frequency of 5 Hz (200ms)
host: '0.0.0.0',
});
+
+server.on('connection', (client) => {
+ client.subscribe('my-channel', (body, frame) => {
+ // Handle messages here
+ });
+
+ server.broadcast('my-other-channel', 'some message');
+});
```
**Client**
@@ -61,12 +69,21 @@ const Server = kalm.listen({
const kalm = require('kalm');
const ws = require('@kalm/ws');
-const Client = kalm.connect({
+const client = kalm.connect({
host: '0.0.0.0',
port: 8800,
transport: ws(),
routine: kalm.routines.realtime(),
});
+
+client.on('connect', () => {
+ client.subscribe('my-other-channel', (body, frame) => {
+ // Handle messages here
+ });
+
+ client.write('my-channel', 'hello world');
+});
+
```
To see working implementations, check out our [examples](https://github.com/kalm/kalm.js/tree/master/examples) folder.
diff --git a/packages/kalm/package.json b/packages/kalm/package.json
index ad4432a..7088706 100644
--- a/packages/kalm/package.json
+++ b/packages/kalm/package.json
@@ -5,7 +5,9 @@
"main": "bin/kalm.js",
"scripts": {
"build": "../../scripts/build.sh kalm",
- "clean": "../../scripts/cleanup.sh"
+ "clean": "../../scripts/cleanup.sh",
+ "test": "jest ./tests",
+ "prepublish": "cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md"
},
"funding": {
"type": "Open Collective",
@@ -16,28 +18,17 @@
"url": "git+https://github.com/kalm/kalm-js.git"
},
"keywords": [
- "multiplex",
+ "framework",
"network",
- "optimize",
+ "realtime",
"socket",
- "websocket",
- "client",
- "server",
- "service",
- "peer",
- "micro",
- "latency",
- "messaging",
- "queue",
"nagle",
- "buffer",
- "protocol",
- "web",
"ipc",
"tcp",
"udp",
- "ws",
- "core"
+ "websocket",
+ "webrtc",
+ "peer"
],
"files": [
"bin",
@@ -53,7 +44,14 @@
"contributors": [
"frederic charette "
],
- "devDependencies": {
- "webpack-cli": "^3.3.10"
+ "jest": {
+ "preset": "ts-jest",
+ "testEnvironment": "node",
+ "globals": {
+ "ts-jest": {
+ "diagnostics": false,
+ "isolatedModules": true
+ }
+ }
}
}
diff --git a/packages/kalm/src/components/client.ts b/packages/kalm/src/components/client.ts
index e8ab5e5..37de64c 100644
--- a/packages/kalm/src/components/client.ts
+++ b/packages/kalm/src/components/client.ts
@@ -2,7 +2,7 @@
import { EventEmitter } from 'events';
import { log } from '../utils/logger';
-import { serialize, deserialize } from '../utils/parser';
+import { serializeLegacy, deserializeLegacy, indiceBuffer } from '../utils/parser';
/* Methods -------------------------------------------------------------------*/
@@ -11,17 +11,30 @@ export function Client(params: ClientConfig, emitter: NodeJS.EventEmitter, handl
const channels: ChannelList = {};
const socket: Socket = params.transport(params, emitter);
+ if (!socket.connect) {
+ throw new Error('Transport is not valid, it may not have been invoked, see: https://github.com/kalm/kalm.js#documentation');
+ }
+
function _createChannel(channel: string): Channel {
const channelEmitter: NodeJS.EventEmitter = new EventEmitter();
return {
+ name: channel,
emitter: channelEmitter,
queue: params.routine(channel, params, channelEmitter, emitter),
+ channelBuffer: Buffer.concat([indiceBuffer(channel.length), Buffer.from(channel)]),
};
}
function _wrap(event: RawFrame): void {
- const payload: number[] = serialize(event.frameId, event.channel, event.packets);
+ const payload: Buffer = params.framing === 'kalm'
+ ? serializeLegacy(event.frameId, channels[event.channel], event.packets)
+ : Buffer.from(JSON.stringify({
+ frameId: event.frameId,
+ channel: event.channel,
+ packets: event.packets.map(packet => packet.toString()),
+ }));
+
socket.send(handle, payload);
}
@@ -35,8 +48,16 @@ export function Client(params: ClientConfig, emitter: NodeJS.EventEmitter, handl
function _handlePackets(frame: RawFrame, packet: Buffer, index: number): Promise {
if (packet.length === 0) return;
- const decodedPacket = (params.json === true) ? JSON.parse(packet.toString()) : packet;
- if (channels[frame.channel]) {
+
+ let decodedPacket;
+
+ try {
+ decodedPacket = (params.json === true) ? JSON.parse(packet.toString()) : packet;
+ } catch (e) {
+ emitter.emit('error', `Error decoding packet: ${e}`);
+ }
+
+ if (decodedPacket && channels[frame.channel]) {
channels[frame.channel].emitter.emit(
'message',
decodedPacket,
@@ -68,9 +89,14 @@ export function Client(params: ClientConfig, emitter: NodeJS.EventEmitter, handl
}
function _handleRequest(payload: Buffer): void {
- const frame: RawFrame = deserialize(payload);
- emitter.emit('frame', frame);
- frame.packets.forEach((packet, i) => _handlePackets(frame, packet, i));
+ let frame: RawFrame;
+ try {
+ frame = params.framing === 'kalm' ? deserializeLegacy(payload) : JSON.parse(payload.toString());
+ } catch (e) {
+ emitter.emit(`Error decoding frame: ${e}`);
+ }
+ emitter.emit('frame', frame || payload.toString());
+ if (frame && frame.packets) frame.packets.forEach((packet, i) => _handlePackets(frame, Buffer.from(packet), i));
}
function _handleDisconnect() {
@@ -79,6 +105,9 @@ export function Client(params: ClientConfig, emitter: NodeJS.EventEmitter, handl
}
function write(channel: string, message: Serializable): void {
+ if (params.json !== true && !Buffer.isBuffer(message)) {
+ throw new Error(`Unable to serialize message: ${message}, expected type Buffer`);
+ }
return _resolveChannel(channel)
.queue.add(params.json === true ? Buffer.from(JSON.stringify(message)) : message as Buffer);
}
diff --git a/packages/kalm/src/components/provider.ts b/packages/kalm/src/components/provider.ts
index bcc9107..9df3683 100644
--- a/packages/kalm/src/components/provider.ts
+++ b/packages/kalm/src/components/provider.ts
@@ -10,6 +10,10 @@ export function Provider(params: ClientConfig, emitter: NodeJS.EventEmitter): Pr
const connections = [];
const socket: Socket = params.transport(params, emitter);
+ if (!socket.bind) {
+ throw new Error('Transport is not valid, it may not have been invoked, see: https://github.com/kalm/kalm.js#documentation');
+ }
+
function broadcast(channel: string, payload: Serializable): void {
connections.forEach(c => c.write(channel, payload));
}
diff --git a/packages/kalm/src/kalm.ts b/packages/kalm/src/kalm.ts
index 5af994f..d29c73a 100644
--- a/packages/kalm/src/kalm.ts
+++ b/packages/kalm/src/kalm.ts
@@ -10,12 +10,13 @@ import { tick } from './routines/tick';
/* Local variables -----------------------------------------------------------*/
-const defaults = {
+const defaults: ProviderConfig = {
host: '0.0.0.0',
json: true,
port: 3000,
routine: realtime(),
transport: null,
+ framing: 'kalm',
};
/* Methods -------------------------------------------------------------------*/
@@ -27,6 +28,20 @@ function validateOptions(options: ProviderConfig): void {
throw new Error(`Unable to create Kalm client, missing "transport" parameter.
You may need to install one. ex: @kalm/tcp`);
}
+
+ if (typeof options.transport !== 'function') {
+ throw new Error(`Transport is not a function (${options.transport}), see: https://github.com/kalm/kalm.js#documentation`);
+ }
+
+ if (options.routine) {
+ if (typeof options.transport !== 'function') {
+ throw new Error(`Routine is not a function (${options.routine}), see: https://github.com/kalm/kalm.js#documentation`);
+ }
+ const testChannel = options.routine('test', {}, {}, {});
+ if (!testChannel.add) {
+ throw new Error('Routine is not valid, it may not have been invoked, see: https://github.com/kalm/kalm.js#documentation');
+ }
+ }
}
export function listen(options: ProviderConfig): Provider {
diff --git a/packages/kalm/src/routines/dynamic.ts b/packages/kalm/src/routines/dynamic.ts
index 98d804b..66fd98d 100644
--- a/packages/kalm/src/routines/dynamic.ts
+++ b/packages/kalm/src/routines/dynamic.ts
@@ -1,6 +1,10 @@
/* Methods -------------------------------------------------------------------*/
-export function dynamic({ hz, maxPackets = Infinity }: { hz: number, maxPackets?: number }): KalmRoutine {
+export function dynamic({
+ hz,
+ maxPackets = Infinity,
+ maxBytes = 60000,
+}: { hz: number, maxPackets?: number, maxBytes?: number }): KalmRoutine {
if (hz <= 0 || hz > 1000) {
throw new Error(`Unable to set Hertz value of ${hz}. Must be between 0.1e13 and 1000`);
}
@@ -8,6 +12,7 @@ export function dynamic({ hz, maxPackets = Infinity }: { hz: number, maxPackets?
return function queue(channel: string, params: object, channelEmitter: NodeJS.EventEmitter, clientEmitter: NodeJS.EventEmitter): Queue {
let timer: NodeJS.Timer = null;
const packets: Buffer[] = [];
+ let totalBytes = 0;
let i: number = 0;
function _step(): void {
@@ -16,21 +21,38 @@ export function dynamic({ hz, maxPackets = Infinity }: { hz: number, maxPackets?
channelEmitter.emit('runQueue', { frameId: i++, channel, packets });
if (i > 255) i = 0;
packets.length = 0;
+ totalBytes = 0;
clientEmitter.emit(`${channel}.queueRun`, { frameId: i, packets: packets.length });
}
- function add(packet: Buffer): void {
+ function _add(packet: Buffer) {
+ packets.push(packet);
+ totalBytes += packet.length;
+ clientEmitter.emit(`${channel}.queueAdd`, { frameId: i, packet: packets.length });
+ }
+
+ function add(packet: Buffer) {
+ if (packet.length > maxBytes) {
+ throw new Error(`Cannot send packet of size ${packet.length} while maximum bytes per frame is ${maxBytes}`);
+ }
+
+ if (packet.length + totalBytes >= maxBytes) {
+ _step();
+ _add(packet);
+ return;
+ }
+
if (packets.length >= maxPackets - 1) {
- packets.push(packet);
+ _add(packet);
_step();
- clientEmitter.emit(`${channel}.queueAdd`, { frameId: i, packet: packets.length });
return;
}
+
if (timer === null) {
timer = setTimeout(_step, Math.round(1000 / hz));
}
- packets.push(packet);
- clientEmitter.emit(`${channel}.queueAdd`, { frameId: i, packet: packets.length });
+
+ _add(packet);
}
function size(): number { return packets.length; }
diff --git a/packages/kalm/src/utils/parser.ts b/packages/kalm/src/utils/parser.ts
index f180052..3c1577f 100644
--- a/packages/kalm/src/utils/parser.ts
+++ b/packages/kalm/src/utils/parser.ts
@@ -1,32 +1,46 @@
+/* Local variables -----------------------------------------------------------*/
+
+const singleIndiceCache = {};
+const doubleIndiceCache = {};
+
/* Methods -------------------------------------------------------------------*/
-function _uint16Size(value: number): number[] {
- return [value >>> 8, value & 0xff];
+export function indiceBuffer(num): Buffer {
+ if (singleIndiceCache[`${num}`]) return singleIndiceCache[`${num}`];
+ const buf = Buffer.allocUnsafe(1);
+ buf.writeUInt8(num, 0);
+ singleIndiceCache[`${num}`] = buf;
+ return buf;
+}
+
+export function doubleIndiceBuffer(num): Buffer {
+ if (doubleIndiceCache[`${num}`]) return doubleIndiceCache[`${num}`];
+ const buf = Buffer.allocUnsafe(2);
+ buf.writeUInt16BE(num, 0);
+ doubleIndiceCache[`${num}`] = buf;
+ return buf;
}
function _numericSize(bytes: Buffer, index: number): number {
return (bytes[index] << 8) | bytes[index + 1];
}
-export function serialize(frameId: number, channel: string, packets: Buffer[]): number[] {
- const channelLen: number = channel.length;
- const result: number[] = [frameId % 255, channelLen];
+export function serializeLegacy(frameId: number, channel: Channel, packets: Buffer[]): Buffer {
+ const serializedPackets = packets.reduce((acc, curr) => {
+ acc.push(doubleIndiceBuffer(curr.length));
+ acc.push(curr);
+ return acc;
+ }, []);
- for (let letter = 0; letter < channelLen; letter++) {
- result.push(channel.charCodeAt(letter));
- }
-
- result.push(..._uint16Size(packets.length));
-
- packets.forEach((packet: Buffer) => {
- if (!(packet instanceof Buffer)) throw new Error(`Cannot send packet ${packet}. Must be of type Buffer`);
- result.push(..._uint16Size(packet.length), ...packet);
- });
-
- return result;
+ return Buffer.concat([
+ indiceBuffer(frameId % 255),
+ channel.channelBuffer,
+ doubleIndiceBuffer(packets.length),
+ ...serializedPackets,
+ ]);
}
-export function deserialize(payload: Buffer): RawFrame {
+export function deserializeLegacy(payload: Buffer): RawFrame {
const channelLength = payload[1];
let caret = 4 + channelLength;
const totalPackets = _numericSize(payload, 2 + channelLength);
@@ -34,7 +48,7 @@ export function deserialize(payload: Buffer): RawFrame {
function _parseFramePacket(): Buffer[] {
const packets: Buffer[] = [];
for (let p = 0; p < totalPackets; p++) {
- if (caret >= payload.length) continue;
+ if (caret >= payload.length) break;
const packetLength = _numericSize(payload, caret);
packets.push(payload.slice(2 + caret, 2 + packetLength + caret));
caret = 2 + caret + packetLength;
diff --git a/packages/kalm/types.d.ts b/packages/kalm/types.d.ts
index 936af4a..59d8983 100644
--- a/packages/kalm/types.d.ts
+++ b/packages/kalm/types.d.ts
@@ -8,6 +8,7 @@ declare module 'kalm' {
host?: string
isServer?: boolean
provider?: any
+ framing?: 'kalm'
}
interface ProviderConfig {
@@ -17,6 +18,7 @@ declare module 'kalm' {
transport?: KalmTransport
port?: number
host?: string
+ framing?: 'kalm'
}
type Remote = {
@@ -134,7 +136,7 @@ declare module 'kalm' {
export const connect: (config: ClientConfig) => Client;
export const routines: {
tick: (config: { hz: number, seed?: number }) => KalmRoutine
- dynamic: (config: { hz: number, maxPackets?: number }) => KalmRoutine
+ dynamic: (config: { hz: number, maxPackets?: number, maxBytes?: number }) => KalmRoutine
realtime: () => KalmRoutine
};
}
diff --git a/packages/tcp/README.md b/packages/tcp/README.md
index bc51a34..269fb35 100644
--- a/packages/tcp/README.md
+++ b/packages/tcp/README.md
@@ -1,4 +1,21 @@
-# Kalm TCP transport
+
+
+
+
+
+ Kalm
+
+
+ The Socket Optimizer
+
+
+
+
+[![Kalm](https://img.shields.io/npm/v/kalm.svg)](https://www.npmjs.com/package/@kalm/tcp)
+[![Build Status](https://github.com/kalm/kalm.js/workflows/master-status/badge.svg)](https://github.com/kalm/kalm.js/actions?query=workflow%3A+master-status)
+![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/kalm/kalm.js)
+[![Financial Contributors on Open Collective](https://opencollective.com/kalm/all/badge.svg?label=financial+contributors)](https://opencollective.com/kalm)
+[![Join the chat at https://gitter.im/KALM/home](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/KALM/?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Installing
@@ -8,7 +25,7 @@
```
{
- socketTimeout = 30000
+ socketTimeout: 30000
}
```
diff --git a/packages/tcp/package.json b/packages/tcp/package.json
index b589416..3c4cb9c 100644
--- a/packages/tcp/package.json
+++ b/packages/tcp/package.json
@@ -5,7 +5,9 @@
"main": "bin/tcp.js",
"scripts": {
"build": "../../scripts/build.sh tcp",
- "clean": "../../scripts/cleanup.sh"
+ "clean": "../../scripts/cleanup.sh",
+ "test": "jest ./tests",
+ "prepublish": "cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md"
},
"funding": {
"type": "Open Collective",
@@ -16,23 +18,11 @@
"url": "git+https://github.com/kalm/kalm-js.git"
},
"keywords": [
- "multiplex",
+ "framework",
"network",
- "optimize",
+ "realtime",
"socket",
- "websocket",
- "client",
- "server",
- "service",
- "peer",
- "micro",
- "latency",
- "messaging",
- "queue",
"nagle",
- "buffer",
- "protocol",
- "web",
"tcp"
],
"files": ["bin", "types.d.ts"],
@@ -48,5 +38,15 @@
],
"browser": {
"net": false
+ },
+ "jest": {
+ "preset": "ts-jest",
+ "testEnvironment": "node",
+ "globals": {
+ "ts-jest": {
+ "diagnostics": false,
+ "isolatedModules": true
+ }
+ }
}
}
\ No newline at end of file
diff --git a/packages/tcp/src/tcp.ts b/packages/tcp/src/tcp.ts
index b39e1ad..549a75d 100644
--- a/packages/tcp/src/tcp.ts
+++ b/packages/tcp/src/tcp.ts
@@ -4,7 +4,7 @@ import net from 'net';
/* Methods -------------------------------------------------------------------*/
-export function tcp({ socketTimeout = 30000 }: TCPConfig = {}): KalmTransport {
+function tcp({ socketTimeout = 30000 }: TCPConfig = {}): KalmTransport {
return function socket(params: ClientConfig, emitter: NodeJS.EventEmitter): Socket {
let listener: net.Server;
@@ -16,8 +16,8 @@ export function tcp({ socketTimeout = 30000 }: TCPConfig = {}): KalmTransport {
function remote(handle: net.Socket): Remote {
return {
- host: handle.remoteAddress,
- port: handle.remotePort,
+ host: handle && handle.remoteAddress || null,
+ port: handle && handle.remotePort || null,
};
}
diff --git a/packages/tcp/tests/unit/tcp.spec.ts b/packages/tcp/tests/unit/tcp.spec.ts
index b024b76..d17e732 100644
--- a/packages/tcp/tests/unit/tcp.spec.ts
+++ b/packages/tcp/tests/unit/tcp.spec.ts
@@ -1,5 +1,40 @@
+import { EventEmitter } from 'events';
import * as tcp from '../../src/tcp';
describe('TCP transport', () => {
- it('TODO', () => { expect(tcp).not.toBeUndefined(); });
+ it('basic setup', () => {
+ expect(typeof tcp.default).toBe('function');
+ const transport = tcp.default();
+ expect(typeof transport).toBe('function');
+ const socket = transport({}, new EventEmitter());
+
+ expect(socket).toHaveProperty('bind', expect.any(Function));
+ expect(socket).toHaveProperty('connect', expect.any(Function));
+ expect(socket).toHaveProperty('disconnect', expect.any(Function));
+ expect(socket).toHaveProperty('remote', expect.any(Function));
+ expect(socket).toHaveProperty('stop', expect.any(Function));
+ expect(socket).toHaveProperty('send', expect.any(Function));
+ });
+
+ describe('Given an empty handle reference and no configs', () => {
+ const transport = tcp.default();
+ const socket = transport({}, new EventEmitter());
+
+ describe('when fetching remote', () => {
+ it('should return null values', () => {
+ expect(socket.remote()).toEqual({ host: null, port: null });
+ });
+ });
+ });
+
+ describe('Given a handle reference and no configs', () => {
+ const transport = tcp.default();
+ const socket = transport({}, new EventEmitter());
+
+ describe('when fetching remote', () => {
+ it('should return handle\'s values', () => {
+ expect(socket.remote({ remoteAddress: '127.0.0.1', remotePort: 3000 })).toEqual({ host: '127.0.0.1', port: 3000 });
+ });
+ });
+ });
});
diff --git a/packages/udp/README.md b/packages/udp/README.md
index 86e4baa..32155ed 100644
--- a/packages/udp/README.md
+++ b/packages/udp/README.md
@@ -1,4 +1,21 @@
-# Kalm UDP transport
+
+
+
+
+
+ Kalm
+
+
+ The Socket Optimizer
+
+
+
+
+[![Kalm](https://img.shields.io/npm/v/kalm.svg)](https://www.npmjs.com/package/@kalm/udp)
+[![Build Status](https://github.com/kalm/kalm.js/workflows/master-status/badge.svg)](https://github.com/kalm/kalm.js/actions?query=workflow%3A+master-status)
+![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/kalm/kalm.js)
+[![Financial Contributors on Open Collective](https://opencollective.com/kalm/all/badge.svg?label=financial+contributors)](https://opencollective.com/kalm)
+[![Join the chat at https://gitter.im/KALM/home](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/KALM/?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Installing
@@ -8,11 +25,11 @@
```
{
- type = 'udp4',
- localAddr = '0.0.0.0',
- reuseAddr = true,
- socketTimeout = 30000,
- connectTimeout = 1000,
+ type: 'udp4',
+ localAddr: '0.0.0.0',
+ reuseAddr: true,
+ socketTimeout: 30000,
+ connectTimeout: 1000,
}
```
diff --git a/packages/udp/package.json b/packages/udp/package.json
index 9c4b75f..6df222a 100644
--- a/packages/udp/package.json
+++ b/packages/udp/package.json
@@ -5,7 +5,9 @@
"main": "bin/udp.js",
"scripts": {
"build": "../../scripts/build.sh udp",
- "clean": "../../scripts/cleanup.sh"
+ "clean": "../../scripts/cleanup.sh",
+ "test": "jest ./tests",
+ "prepublish": "cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md"
},
"funding": {
"type": "Open Collective",
@@ -16,23 +18,11 @@
"url": "git+https://github.com/kalm/kalm-js.git"
},
"keywords": [
- "multiplex",
+ "framework",
"network",
- "optimize",
+ "realtime",
"socket",
- "websocket",
- "client",
- "server",
- "service",
- "peer",
- "micro",
- "latency",
- "messaging",
- "queue",
"nagle",
- "buffer",
- "protocol",
- "web",
"udp"
],
"files": ["bin", "types.d.ts"],
@@ -48,5 +38,15 @@
],
"browser": {
"dgram": false
+ },
+ "jest": {
+ "preset": "ts-jest",
+ "testEnvironment": "node",
+ "globals": {
+ "ts-jest": {
+ "diagnostics": false,
+ "isolatedModules": true
+ }
+ }
}
}
\ No newline at end of file
diff --git a/packages/udp/src/udp.ts b/packages/udp/src/udp.ts
index fa898df..3bd43b6 100644
--- a/packages/udp/src/udp.ts
+++ b/packages/udp/src/udp.ts
@@ -26,7 +26,7 @@ function udp({ type = 'udp4', localAddr = '0.0.0.0', reuseAddr = true, socketTim
}
function remote(handle: SocketHandle): Remote {
- return handle as Remote;
+ return handle || { host: null, port: null } as Remote;
}
function send(handle: UDPSocketHandle, payload: Buffer | number[]): void {
diff --git a/packages/udp/tests/unit/udp.spec.ts b/packages/udp/tests/unit/udp.spec.ts
index d43e569..8187a0f 100644
--- a/packages/udp/tests/unit/udp.spec.ts
+++ b/packages/udp/tests/unit/udp.spec.ts
@@ -1,5 +1,40 @@
+import { EventEmitter } from 'events';
import * as udp from '../../src/udp';
describe('UDP transport', () => {
- it('TODO', () => { expect(udp).not.toBeUndefined(); });
+ it('basic setup', () => {
+ expect(typeof udp.default).toBe('function');
+ const transport = udp.default();
+ expect(typeof transport).toBe('function');
+ const socket = transport({}, new EventEmitter());
+
+ expect(socket).toHaveProperty('bind', expect.any(Function));
+ expect(socket).toHaveProperty('connect', expect.any(Function));
+ expect(socket).toHaveProperty('disconnect', expect.any(Function));
+ expect(socket).toHaveProperty('remote', expect.any(Function));
+ expect(socket).toHaveProperty('stop', expect.any(Function));
+ expect(socket).toHaveProperty('send', expect.any(Function));
+ });
+
+ describe('Given an empty handle reference and no configs', () => {
+ const transport = udp.default();
+ const socket = transport({}, new EventEmitter());
+
+ describe('when fetching remote', () => {
+ it('should return null values', () => {
+ expect(socket.remote()).toEqual({ host: null, port: null });
+ });
+ });
+ });
+
+ describe('Given a handle reference and no configs', () => {
+ const transport = udp.default();
+ const socket = transport({}, new EventEmitter());
+
+ describe('when fetching remote', () => {
+ it('should return handle\'s values', () => {
+ expect(socket.remote({ host: '127.0.0.1', port: 3000 })).toEqual({ host: '127.0.0.1', port: 3000 });
+ });
+ });
+ });
});
diff --git a/packages/webrtc/README.md b/packages/webrtc/README.md
index 84631ab..6a799a2 100644
--- a/packages/webrtc/README.md
+++ b/packages/webrtc/README.md
@@ -1,4 +1,21 @@
-# Kalm Webrtc data channel transport
+
+
+
+
+
+ Kalm
+
+
+ The Socket Optimizer
+
+
+
+
+[![Kalm](https://img.shields.io/npm/v/kalm.svg)](https://www.npmjs.com/package/@kalm/webrtc)
+[![Build Status](https://github.com/kalm/kalm.js/workflows/master-status/badge.svg)](https://github.com/kalm/kalm.js/actions?query=workflow%3A+master-status)
+![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/kalm/kalm.js)
+[![Financial Contributors on Open Collective](https://opencollective.com/kalm/all/badge.svg?label=financial+contributors)](https://opencollective.com/kalm)
+[![Join the chat at https://gitter.im/KALM/home](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/KALM/?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Installing
diff --git a/packages/webrtc/package.json b/packages/webrtc/package.json
index 5910a0d..703ea13 100644
--- a/packages/webrtc/package.json
+++ b/packages/webrtc/package.json
@@ -5,7 +5,9 @@
"main": "bin/webrtc.js",
"scripts": {
"build": "../../scripts/build.sh webrtc",
- "clean": "../../scripts/cleanup.sh"
+ "clean": "../../scripts/cleanup.sh",
+ "test": "jest ./tests",
+ "prepublish": "cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md"
},
"funding": {
"type": "Open Collective",
@@ -16,24 +18,12 @@
"url": "git+https://github.com/kalm/kalm-js.git"
},
"keywords": [
- "multiplex",
+ "framework",
"network",
- "optimize",
+ "realtime",
"socket",
- "websocket",
- "client",
- "server",
- "service",
- "peer",
- "micro",
- "latency",
- "messaging",
- "queue",
"nagle",
- "buffer",
- "protocol",
- "web",
- "ws"
+ "webrtc"
],
"files": ["bin", "types.d.ts"],
"typings": "./types.d.ts",
@@ -48,6 +38,16 @@
],
"dependencies": {
"simple-peer": "^9.6.0"
+ },
+ "jest": {
+ "preset": "ts-jest",
+ "testEnvironment": "node",
+ "globals": {
+ "ts-jest": {
+ "diagnostics": false,
+ "isolatedModules": true
+ }
+ }
}
}
\ No newline at end of file
diff --git a/packages/webrtc/src/webrtc.ts b/packages/webrtc/src/webrtc.ts
index d66c636..d9468ff 100644
--- a/packages/webrtc/src/webrtc.ts
+++ b/packages/webrtc/src/webrtc.ts
@@ -2,7 +2,8 @@
import Peer from 'simple-peer';
-if (!Peer.WEBRTC_SUPPORT) throw new Error('Unsupported environement for WebRTC');
+const isNode = (typeof process !== 'undefined');
+if (!Peer.WEBRTC_SUPPORT && !(isNode && process.env.JEST_WORKER_ID)) throw new Error('Unsupported environement for WebRTC');
/* Methods -------------------------------------------------------------------*/
@@ -64,10 +65,7 @@ function webrtc(config: WebRTCConfig = {}): KalmTransport {
}
function remote(handle: any): Remote {
- return {
- host: handle,
- port: handle || 0,
- };
+ return handle || { host: null, port: null };
}
function disconnect(handle) {
diff --git a/packages/webrtc/tests/unit/webrtc.spec.ts b/packages/webrtc/tests/unit/webrtc.spec.ts
new file mode 100644
index 0000000..ec609e4
--- /dev/null
+++ b/packages/webrtc/tests/unit/webrtc.spec.ts
@@ -0,0 +1,41 @@
+import { EventEmitter } from 'events';
+import * as webrtc from '../../src/webrtc';
+
+describe('webrtc transport', () => {
+ it('basic setup', () => {
+ expect(typeof webrtc.default).toBe('function');
+ const transport = webrtc.default();
+ expect(typeof transport).toBe('function');
+ const socket = transport({}, new EventEmitter());
+
+ expect(socket).toHaveProperty('bind', expect.any(Function));
+ expect(socket).toHaveProperty('connect', expect.any(Function));
+ expect(socket).toHaveProperty('disconnect', expect.any(Function));
+ expect(socket).toHaveProperty('remote', expect.any(Function));
+ expect(socket).toHaveProperty('stop', expect.any(Function));
+ expect(socket).toHaveProperty('send', expect.any(Function));
+ expect(socket).toHaveProperty('negociate', expect.any(Function));
+ });
+
+ describe('Given an empty handle reference and no configs', () => {
+ const transport = webrtc.default();
+ const socket = transport({}, new EventEmitter());
+
+ describe('when fetching remote', () => {
+ it('should return null values', () => {
+ expect(socket.remote()).toEqual({ host: null, port: null });
+ });
+ });
+ });
+
+ describe('Given a handle reference and no configs', () => {
+ const transport = webrtc.default();
+ const socket = transport({}, new EventEmitter());
+
+ describe('when fetching remote', () => {
+ it('should return handle\'s values', () => {
+ expect(socket.remote({ host: '127.0.0.1', port: 3000 })).toEqual({ host: '127.0.0.1', port: 3000 });
+ });
+ });
+ });
+});
diff --git a/packages/ws/README.md b/packages/ws/README.md
index 613a038..fa86670 100644
--- a/packages/ws/README.md
+++ b/packages/ws/README.md
@@ -1,4 +1,21 @@
-# Kalm Websocket transport
+
+
+
+
+
+ Kalm
+
+
+ The Socket Optimizer
+
+
+
+
+[![Kalm](https://img.shields.io/npm/v/kalm.svg)](https://www.npmjs.com/package/@kalm/ws)
+[![Build Status](https://github.com/kalm/kalm.js/workflows/master-status/badge.svg)](https://github.com/kalm/kalm.js/actions?query=workflow%3A+master-status)
+![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/kalm/kalm.js)
+[![Financial Contributors on Open Collective](https://opencollective.com/kalm/all/badge.svg?label=financial+contributors)](https://opencollective.com/kalm)
+[![Join the chat at https://gitter.im/KALM/home](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/KALM/?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Installing
@@ -8,9 +25,9 @@
```
{
- cert = null,
- key = null,
- secure = false
+ cert: null,
+ key: null,
+ secure: false
}
```
diff --git a/packages/ws/package.json b/packages/ws/package.json
index 7d8fe87..5488c9e 100644
--- a/packages/ws/package.json
+++ b/packages/ws/package.json
@@ -5,7 +5,9 @@
"main": "bin/ws.js",
"scripts": {
"build": "../../scripts/build.sh ws",
- "clean": "../../scripts/cleanup.sh"
+ "clean": "../../scripts/cleanup.sh",
+ "test": "jest ./tests",
+ "prepublish": "cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md"
},
"funding": {
"type": "Open Collective",
@@ -16,24 +18,12 @@
"url": "git+https://github.com/kalm/kalm-js.git"
},
"keywords": [
- "multiplex",
+ "framework",
"network",
- "optimize",
+ "realtime",
"socket",
- "websocket",
- "client",
- "server",
- "service",
- "peer",
- "micro",
- "latency",
- "messaging",
- "queue",
"nagle",
- "buffer",
- "protocol",
- "web",
- "ws"
+ "websocket"
],
"files": ["bin", "types.d.ts"],
"typings": "./types.d.ts",
@@ -52,5 +42,15 @@
"browser": {
"http": false,
"https": false
+ },
+ "jest": {
+ "preset": "ts-jest",
+ "testEnvironment": "node",
+ "globals": {
+ "ts-jest": {
+ "diagnostics": false,
+ "isolatedModules": true
+ }
+ }
}
}
diff --git a/packages/ws/src/ws.ts b/packages/ws/src/ws.ts
index 8322360..39e8db1 100644
--- a/packages/ws/src/ws.ts
+++ b/packages/ws/src/ws.ts
@@ -48,13 +48,13 @@ function ws({ cert, key, secure }: WSConfig = {}): KalmTransport {
}
function remote(handle: WebSocket & { headers: any, connection: any }): Remote {
- const h = handle.headers;
+ const h = handle && handle.headers || {};
return {
host: (
(h && h['x-forwarded-for'] && h['x-forwarded-for'].split(',')[0])
- || (handle.connection && handle.connection.remoteAddress || '0.0.0.0')
+ || (handle && handle.connection && handle.connection.remoteAddress || null)
),
- port: handle.connection && handle.connection.remotePort || 0,
+ port: handle && handle.connection && handle.connection.remotePort || null,
};
}
diff --git a/packages/ws/tests/unit/ws.spec.ts b/packages/ws/tests/unit/ws.spec.ts
index 6923313..fdd70b4 100644
--- a/packages/ws/tests/unit/ws.spec.ts
+++ b/packages/ws/tests/unit/ws.spec.ts
@@ -1,5 +1,47 @@
+import { EventEmitter } from 'events';
import * as ws from '../../src/ws';
-describe('WS transport', () => {
- it('TODO', () => { expect(ws).not.toBeUndefined(); });
+describe('ws transport', () => {
+ it('basic setup', () => {
+ expect(typeof ws.default).toBe('function');
+ const transport = ws.default();
+ expect(typeof transport).toBe('function');
+ const socket = transport({}, new EventEmitter());
+
+ expect(socket).toHaveProperty('bind', expect.any(Function));
+ expect(socket).toHaveProperty('connect', expect.any(Function));
+ expect(socket).toHaveProperty('disconnect', expect.any(Function));
+ expect(socket).toHaveProperty('remote', expect.any(Function));
+ expect(socket).toHaveProperty('stop', expect.any(Function));
+ expect(socket).toHaveProperty('send', expect.any(Function));
+ });
+
+ describe('Given an empty handle reference and no configs', () => {
+ const transport = ws.default();
+ const socket = transport({}, new EventEmitter());
+
+ describe('when fetching remote', () => {
+ it('should return null values', () => {
+ expect(socket.remote()).toEqual({ host: null, port: null });
+ });
+ });
+ });
+
+ describe('Given a handle reference and no configs', () => {
+ const transport = ws.default();
+ const socket = transport({}, new EventEmitter());
+
+ describe('when fetching remote', () => {
+ it('should return handle\'s values from headers', () => {
+ expect(socket.remote({
+ headers: { 'x-forwarded-for': '127.0.0.1' },
+ connection: { remotePort: 3000 },
+ })).toEqual({ host: '127.0.0.1', port: 3000 });
+ });
+
+ it('should return handle\'s values from connection', () => {
+ expect(socket.remote({ connection: { remoteAddress: '127.0.0.1', remotePort: 3000 } })).toEqual({ host: '127.0.0.1', port: 3000 });
+ });
+ });
+ });
});
diff --git a/scripts/benchmarks/index.js b/scripts/benchmarks/index.js
index 033bdca..c10421a 100644
--- a/scripts/benchmarks/index.js
+++ b/scripts/benchmarks/index.js
@@ -98,6 +98,8 @@ adpts.forEach((i) => {
tests.push(_postResults);
+console.log(`Launching benchmarks for ${settings.testDuration/1000} second(s) -- MAKE SURE THAT YOU BUILD THE CODE FIRST --`)
+
tests.reduce(
(c, n) => c.then((resolve) => new Promise(n).then(resolve, _errorHandler), _errorHandler),
Promise.resolve(),
diff --git a/scripts/benchmarks/settings.js b/scripts/benchmarks/settings.js
index 9866ea7..c82cbbd 100644
--- a/scripts/benchmarks/settings.js
+++ b/scripts/benchmarks/settings.js
@@ -5,4 +5,5 @@ module.exports = {
testDuration: 1000 * 10,
testPayload: { foo: 'bar' },
testChannel: 'test',
+ framing: null,
};
diff --git a/scripts/benchmarks/transports/kalm.js b/scripts/benchmarks/transports/kalm.js
index 6b31008..48e6e2d 100644
--- a/scripts/benchmarks/transports/kalm.js
+++ b/scripts/benchmarks/transports/kalm.js
@@ -29,6 +29,7 @@ function setup(resolve) {
server = Kalm.listen({
port: settings.port,
json: true,
+ framing: settings.framing,
transport: transports[settings.transport](),
routine: Kalm.routines[settings.routine[0]](settings.routine[1]),
});
@@ -37,6 +38,10 @@ function setup(resolve) {
c.subscribe(settings.testChannel, (msg) => c.write(settings.testChannel, msg));
});
+ server.on('error', (e) => {
+ console.error('Server error:', e);
+ });
+
handbreak = false;
setTimeout(resolve, 0);
}
@@ -59,10 +64,15 @@ function step(resolve) {
client = Kalm.connect({
port: settings.port,
json: true,
+ framing: settings.framing,
transport: transports[settings.transport](),
routine: Kalm.routines.realtime(),
});
client.subscribe(settings.testChannel, () => count++);
+
+ client.on('error', (e) => {
+ console.error('Client error:', e);
+ });
}
client.write(settings.testChannel, settings.testPayload);
diff --git a/scripts/build.sh b/scripts/build.sh
index b99569d..4de4644 100755
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -3,7 +3,7 @@
echo "Building" $1
../../scripts/cleanup.sh
cp ../../tsconfig.json ./tsconfig.json
-../../node_modules/typescript/bin/tsc --outDir ./bin
+../../node_modules/typescript/bin/tsc --outDir ./bin >/dev/null
echo "Build completed, cleaning up"
rm -rf ./tsconfig.json
rm -rf ./dist
\ No newline at end of file
diff --git a/tests/integration/index.spec.ts b/tests/integration/index.spec.ts
index a8fc485..a88840d 100644
--- a/tests/integration/index.spec.ts
+++ b/tests/integration/index.spec.ts
@@ -41,8 +41,33 @@ describe('Integration tests', () => {
done();
});
});
+ server.on('error', e => {
+ throw new Error(e);
+ });
const client = connect({ transport: soc });
+ client.on('error', e => {
+ throw new Error(e);
+ });
+ client.write('test', payload);
+ });
+
+ it(`should handle foreign characters with ${transport}`, done => {
+ const payload = { foo: '한자' };
+ server.on('connection', c => {
+ c.subscribe('test', data => {
+ expect(data).toEqual(payload);
+ done();
+ });
+ });
+ server.on('error', e => {
+ throw new Error(e);
+ });
+
+ const client = connect({ transport: soc });
+ client.on('error', e => {
+ throw new Error(e);
+ });
client.write('test', payload);
});
@@ -58,8 +83,14 @@ describe('Integration tests', () => {
done();
});
});
+ server.on('error', e => {
+ throw new Error(e);
+ });
const client = connect({ transport: soc });
+ client.on('error', e => {
+ throw new Error(e);
+ });
client.write('test.large', largePayload);
});
@@ -74,8 +105,14 @@ describe('Integration tests', () => {
c.unsubscribe('test');
});
+ server.on('error', e => {
+ throw new Error(e);
+ });
const client = connect({ transport: soc });
+ client.on('error', e => {
+ throw new Error(e);
+ });
setTimeout(() => client.write('test', payload), 100);
setTimeout(() => done(), 200);
});
diff --git a/types.d.ts b/types.d.ts
index 10ba88f..5b77086 100644
--- a/types.d.ts
+++ b/types.d.ts
@@ -9,6 +9,7 @@ interface ClientConfig {
host?: string
isServer?: boolean
provider?: any
+ framing?: 'kalm'
}
interface ProviderConfig {
@@ -18,6 +19,7 @@ interface ProviderConfig {
transport?: KalmTransport
port?: number
host?: string
+ framing?: 'kalm'
}
type Remote = {
@@ -42,8 +44,10 @@ interface Client extends NodeJS.EventEmitter {
}
type Channel = {
+ name: string
queue: Queue
emitter: NodeJS.EventEmitter
+ channelBuffer: Buffer
}
type ChannelList = {
@@ -149,7 +153,7 @@ declare module 'kalm' {
export const connect: (config: ClientConfig) => Client;
export const routines: {
tick: (config: { hz: number, seed?: number }) => KalmRoutine
- dynamic: (config: { hz: number, maxPackets?: number }) => KalmRoutine
+ dynamic: (config: { hz: number, maxPackets?: number, maxBytes?: number }) => KalmRoutine
realtime: () => KalmRoutine
};
}