diff --git a/types/neffos.js/index.d.ts b/types/neffos.js/index.d.ts new file mode 100644 index 0000000000..d025da82bf --- /dev/null +++ b/types/neffos.js/index.d.ts @@ -0,0 +1,161 @@ +// Type definitions for neffos.js 0.1 +// Project: https://github.com/kataras/neffos.js +// Definitions by: Gerasimos (Makis) Maropoulos +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.1 + +/* The WSData is just a string type alias. */ +export type WSData = string; +/* The OnNamespaceConnect is the event name that it's fired on before namespace connect. */ +export const OnNamespaceConnect = "_OnNamespaceConnect"; +/* The OnNamespaceConnected is the event name that it's fired on after namespace connect. */ +export const OnNamespaceConnected = "_OnNamespaceConnected"; +/* The OnNamespaceDisconnect is the event name that it's fired on namespace disconnected. */ +export const OnNamespaceDisconnect = "_OnNamespaceDisconnect"; +/* The OnRoomJoin is the event name that it's fired on before room join. */ +export const OnRoomJoin = "_OnRoomJoin"; +/* The OnRoomJoined is the event name that it's fired on after room join. */ +export const OnRoomJoined = "_OnRoomJoined"; +/* The OnRoomLeave is the event name that it's fired on before room leave. */ +export const OnRoomLeave = "_OnRoomLeave"; +/* The OnRoomLeft is the event name that it's fired on after room leave. */ +export const OnRoomLeft = "_OnRoomLeft"; +/* The OnAnyEvent is the event name that it's fired, if no incoming event was registered, it's a "wilcard". */ +export const OnAnyEvent = "_OnAnyEvent"; +/* The OnNativeMessage is the event name, which if registered on empty "" namespace it accepts native messages(Message.Body and Message.IsNative is filled only). */ +export const OnNativeMessage = "_OnNativeMessage"; +/* The isSystemEvent reports whether the "event" is a system event, (connect, connected, disconnect, room join, room joined, room leave, room left). */ +export function isSystemEvent(event: string): boolean; +/* The Message is the structure which describes the icoming data (and if `Conn.Write` is manually used to write). */ +export class Message { + /* The Namespace that this message sent to. */ + Namespace: string; + /* The Room that this message sent to. */ + Room: string; + /* The Event that this message sent to. */ + Event: string; + /* The actual body of the incoming data. */ + Body: WSData; + /* The Err contains any message's error if defined and not empty. + server-side and client-side can return an error instead of a message from inside event callbacks. */ + Err: string; + /* The IsForced if true then it means that this is not an incoming action but a force action. + For example when websocket connection lost from remote the OnNamespaceDisconnect `Message.IsForced` will be true */ + IsForced: boolean; + /* The IsLocal reprots whether an event is sent by the client-side itself, i.e when `connect` call on `OnNamespaceConnect` event the `Message.IsLocal` will be true, + server-side can force-connect a client to connect to a namespace as well in this case the `IsLocal` will be false. */ + IsLocal: boolean; + /* The IsNative reports whether the Message is websocket native messages, only Body is filled. */ + IsNative: boolean; +} +/* The Room describes a connected connection to a room, + emits messages with the `Message.Room` filled to the specific room + and `Message.Namespace` to the underline `NSConn`'s namespace. */ +export class Room { + nsConn: NSConn; + name: string; + constructor(ns: NSConn, roomName: string); + /* The emit method sends a message to the server with its `Message.Room` filled to this specific room + and `Message.Namespace` to the underline `NSConn`'s namespace. */ + emit(event: string, body: WSData): boolean; + /* The leave method sends a room leave signal to the server and if succeed it fires the `OnRoomLeave` and `OnRoomLeft` events. */ + leave(): Promise; +} +/* The NSConn describes a connected connection to a specific namespace, + it emits with the `Message.Namespace` filled and it can join to multiple rooms. + A single Conn can be connected to one or more namespaces, + each connected namespace is described by this class. */ +export class NSConn { + /* The conn property refers to the main `Conn` constructed by the `dial` function. */ + conn: Conn; + namespace: string; + events: Events; + /* The rooms property its the map of the connected namespace's joined rooms. */ + rooms: Map; + constructor(conn: Conn, namespace: string, events: Events); + /* The emit method sends a message to the server with its `Message.Namespace` filled to this specific namespace. */ + emit(event: string, body: WSData): boolean; + /* See `Conn.ask`. */ + ask(event: string, body: WSData): Promise; + /* The joinRoom method can be used to join to a specific room, rooms are dynamic. + Returns a `Room` or an error. */ + joinRoom(roomName: string): Promise; + /* The room method returns a joined `Room`. */ + room(roomName: string): Room; + /* The leaveAll method sends a leave room signal to all rooms and fires the `OnRoomLeave` and `OnRoomLeft` (if no error caused) events. */ + leaveAll(): Promise; + /* The disconnect method sends a disconnect signal to the server and fires the `OnNamespaceDisconnect` event. */ + disconnect(): Promise; +} + +export type MessageHandlerFunc = (c: NSConn, msg: Message) => Error; + +export interface Events { + [key: string]: MessageHandlerFunc; +} +export interface Namespaces { + [key: string]: Events; +} + +/* The dial function returns a neffos client, a new `Conn` instance. + First parameter is the endpoint, i.e ws://localhost:8080/echo, + the second parameter should be the Namespaces structure. + Example Code: + var conn = await neffos.dial("ws://localhost:8080/echo", { + default: { // "default" namespace. + _OnNamespaceConnected: function (ns, msg) { + console.log("connected to namespace: " + msg.Namespace); + }, + _OnNamespaceDisconnect: function (ns, msg) { + console.log("disconnected from namespace: " + msg.Namespace); + }, + _OnRoomJoined: function (ns, msg) { + console.log("joined to room: " + msg.Room); + }, + _OnRoomLeft: function (ns, msg) { + console.log("left from room: " + msg.Room); + }, + chat: function (ns, msg) { // "chat" event. + let prefix = "Server says: "; + if (msg.Room !== "") { + prefix = msg.Room + " >> "; + } + console.log(prefix + msg.Body); + } + } + }); + + var nsConn = await conn.connect("default"); + nsConn.emit("chat", "Hello from client side!"); + See https://github.com/kataras/neffos.js/tree/master/_examples for more. +*/ +export function dial(endpoint: string, connHandler: Namespaces, protocols?: string[]): Promise; + +export const ErrInvalidPayload: Error; +export const ErrBadNamespace: Error; +export const ErrBadRoom: Error; +export const ErrClosed: Error; +export const ErrWrite: Error; + +/* The Conn class contains the websocket connection and the neffos communication functionality. + Its `connect` will return an `NSCOnn` instance, each connection can connect to one or more namespaces. + Each `NSConn` can join to multiple rooms. */ +export class Conn { + /* ID is the generated connection ID from the server-side, all connected namespaces(`NSConn` instances) + that belong to that connection have the same ID. It is available immediately after the `dial`. */ + ID: string; + constructor(conn: any, connHandler: Namespaces, protocols?: string[]); + /* The connect method returns a new connected to the specific "namespace" `NSConn` instance or an error. */ + connect(namespace: string): Promise; + /* The namespace method returns an already connected `NSConn`. */ + namespace(namespace: string): NSConn; + /* The ask method writes a message to the server and blocks until a response or an error. */ + ask(msg: Message): Promise; + /* The isClosed method reports whether this connection is closed. */ + isClosed(): boolean; + /* The write method writes a message to the server and reports whether the connection is still available. */ + write(msg: Message): boolean; + /* The close method will force-disconnect from all connected namespaces and force-leave from all joined rooms + and finally will terminate the underline websocket connection. After this method call the `Conn` is not usable anymore, a new `dial` call is required. */ + close(): void; +} diff --git a/types/neffos.js/neffos.js-tests.ts b/types/neffos.js/neffos.js-tests.ts new file mode 100644 index 0000000000..13bb0d9547 --- /dev/null +++ b/types/neffos.js/neffos.js-tests.ts @@ -0,0 +1,61 @@ +import neffos = require("neffos.js"); + +const wsURL = "ws://localhost:8080/echo"; +const noOpErr = new Error("no op"); + +async function asumeExample() { + try { + const conn = await neffos.dial(wsURL, { + default: { // "default" namespace. + _OnNamespaceConnected: (ns: neffos.NSConn, msg: neffos.Message): Error => { + return noOpErr; + }, + _OnNamespaceDisconnect: (ns: neffos.NSConn, msg: neffos.Message): Error => { + return noOpErr; + }, + _OnRoomJoined: (ns: neffos.NSConn, msg: neffos.Message): Error => { + return noOpErr; + }, + _OnRoomLeft: (ns: neffos.NSConn, msg: neffos.Message): Error => { + return noOpErr; + }, + chat: (ns: neffos.NSConn, msg: neffos.Message): Error => { // "chat" event. + let prefix = "Server says: "; + + if (msg.Room !== "") { + prefix = msg.Room + " >> "; + } + + return noOpErr; + }, + } + }); + + const nsConn = await conn.connect("default"); + nsConn.emit("chat", "Hello from client side!"); + + const msg = new neffos.Message(); + msg.Namespace = "default"; + msg.Event = "chat"; + msg.Body = "Hello from client (again) using the conn's write method!"; + conn.write(msg); + nsConn.conn.write(msg); + + const reply = await nsConn.ask("question", "what's my name"); + if (reply.Err !== "") { + throw new Error("error from reply: " + reply.Err); + } + + const room = await nsConn.joinRoom("room1"); + room.emit("chat", "I joined."); + room.leave(); + + room.nsConn.leaveAll(); + + room.nsConn.room("undefined").leave(); + + nsConn.disconnect().then(() => { }); + } catch (err) { } +} + +asumeExample(); diff --git a/types/neffos.js/tsconfig.json b/types/neffos.js/tsconfig.json new file mode 100644 index 0000000000..6dec26175b --- /dev/null +++ b/types/neffos.js/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "target": "es6", + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes":true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "neffos.js-tests.ts" + ] +} diff --git a/types/neffos.js/tslint.json b/types/neffos.js/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/neffos.js/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }