Add type definitions for stompit.

This commit is contained in:
Daniel Rose 2018-09-20 13:19:33 +02:00
parent 14d0a6329a
commit baa6e57716
16 changed files with 891 additions and 0 deletions

21
types/stompit/index.d.ts vendored Normal file
View File

@ -0,0 +1,21 @@
// Type definitions for stompit 0.26
// Project: https://github.com/gdaws/node-stomp
// Definitions by: Daniel Rose <https://github.com/DanielRose>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/// <reference types="node" />
import { Writable, Readable, Duplex, WritableOptions } from "stream";
import { EventEmitter } from "events";
export import IncomingFrameStream = require("./lib/IncomingFrameStream");
export import OutgoingFrameStream = require("./lib/OutgoingFrameStream");
export import Client = require("./lib/Client");
export import connect = require("./lib/connect");
export import ConnectFailover = require("./lib/ConnectFailover");
export import Channel = require("./lib/Channel");
export import ChannelFactory = require("./lib/ChannelFactory");
export import ChannelPool = require("./lib/ChannelPool");

42
types/stompit/lib/Channel.d.ts vendored Normal file
View File

@ -0,0 +1,42 @@
import { EventEmitter } from "events";
import { Readable } from "stream";
import { Message, Ack, MessageCallback, SendOptions } from "./Client";
import ConnectFailover = require("./ConnectFailover");
import Transaction = require("./client/Transaction");
declare class Channel extends EventEmitter {
constructor(connectFailover: ConnectFailover, options?: Channel.ChannelOptions);
send(headers: any, body: Channel.Body, callback?: (err: Error | null) => void): this;
subscribe(headers: any, onMessageCallback: (err: Error | null, message: Message, channelSubscription: Channel.ChannelSubscription) => void): Channel.ChannelSubscription;
setImplicitSubscription(id: number, ack?: Ack, msgListener?: MessageCallback): Channel.ChannelSubscription;
ack(message: Message, headers?: any, sendOptions?: SendOptions, callback?: (error?: Error | null) => void): void;
nack(message: Message, headers?: any, sendOptions?: SendOptions, callback?: (error?: Error | null) => void): void;
begin(headers?: any): Transaction;
close(error: Error): void;
isEmpty(): boolean;
lock(): void;
unlock(): void;
}
export = Channel;
declare namespace Channel {
interface ChannelOptions {
alwaysConnected?: boolean;
recoverAfterApplicationError?: boolean;
}
type Body = string | Buffer | (() => Readable);
interface ChannelSubscription {
cancel(): void;
unsubscribe(): void;
}
}

8
types/stompit/lib/ChannelFactory.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
import ChannelPool = require("./ChannelPool");
import ConnectFailover = require("./ConnectFailover");
declare class ChannelFactory extends ChannelPool {
constructor(connectFailover: ConnectFailover);
}
export = ChannelFactory;

24
types/stompit/lib/ChannelPool.d.ts vendored Normal file
View File

@ -0,0 +1,24 @@
import { ChannelOptions } from "./Channel";
import Channel = require("./Channel");
import ConnectFailover = require("./ConnectFailover");
declare class ChannelPool {
constructor(connectFailover: ConnectFailover, options?: ChannelPool.ChannelPoolOptions);
channel(callback: (err: Error | null, channel: Channel) => void): void;
close(): void;
}
export = ChannelPool;
declare namespace ChannelPool {
interface ChannelPoolOptions {
minChannels?: number;
minFreeChannels?: number;
maxChannels?: number;
freeExcessTimeout?: number;
requestChannelTimeout?: number;
channelOptions?: ChannelOptions;
}
}

50
types/stompit/lib/Client.d.ts vendored Normal file
View File

@ -0,0 +1,50 @@
import { WritableOptions, Writable, Readable, Duplex } from "stream";
import { IncomingFrame } from "./IncomingFrameStream";
import { SocketOptions } from "./Socket";
import IncomingFrameStream = require("./IncomingFrameStream");
import Socket = require("./Socket");
import Subscription = require("./client/Subscription");
import Transaction = require("./client/Transaction");
declare class Client extends Socket {
constructor(transportSocket: Duplex, options?: SocketOptions);
send(headers?: any, options?: Client.SendOptions): Writable;
sendFrame(command: string, headers?: any, options?: Client.SendOptions): Writable;
sendString(headers?: any, body?: any, options?: Client.SendOptions, callback?: (error?: Error | null) => void): void;
connect(headers?: any, callback?: (err: Error | null, client: Client) => void): void;
disconnect(callback?: (error: Error | null, client: Client) => void): void;
subscribe(headers?: any, messageListener?: Client.MessageCallback): Subscription;
setImplicitSubscription(id: number, ack?: Client.Ack, messageListener?: Client.MessageCallback): Subscription;
getSubscription(id: number): Subscription;
begin(headers?: any): Transaction;
ack(message: Client.Message, headers?: any, sendOptions?: Client.SendOptions, callback?: (error?: Error | null) => void): void;
nack(message: Client.Message, headers?: any, sendOptions?: Client.SendOptions, callback?: (error?: Error | null) => void): void;
readEmptyBody(frame: IncomingFrameStream, callback?: (client: Client) => void): void;
getOptions(): SocketOptions;
}
export = Client;
declare namespace Client {
interface Message extends IncomingFrame {
ack(): void;
nack(): void;
}
type MessageCallback = (err: Error | null, message: Message) => void;
interface SendOptions extends WritableOptions {
onReceipt(): void;
onError(err: Error): void;
}
type Ack = "auto" | "client" | "client-individual";
}

66
types/stompit/lib/ConnectFailover.d.ts vendored Normal file
View File

@ -0,0 +1,66 @@
import { EventEmitter } from "events";
import { ConnectOptions } from "./connect";
import { AddressInfo } from "./connect-failover/getAddressInfo";
import Client = require("./Client");
declare class ConnectFailover extends EventEmitter {
constructor(servers?: ConnectOptions[] | string, options?: ConnectFailover.ConnectFailoverOptions);
addServer(config: ConnectOptions | string): void;
getReconnectDelay(reconnects: number): number;
connect(callback: (error: Error | null, client: Client, reconnect: () => void, server: ConnectFailover.Server) => void): {
abort: () => void;
};
on(event: "error", listener: (err: ConnectFailover.ConnectError, server: ConnectFailover.ConnectState) => void): this;
on(event: "connect" | "connecting", listener: (server: ConnectFailover.ConnectState) => void): this;
}
export = ConnectFailover;
declare namespace ConnectFailover {
interface ConnectFailoverOptions {
// Milliseconds delay of the first reconnect
initialReconnectDelay?: number;
// Maximum milliseconds delay of any reconnect
maxReconnectDelay?: number;
// Exponential increase of the reconnect delay
useExponentialBackOff?: boolean;
// The exponent used in the exponential backoff attempts
reconnectDelayExponent?: number;
// Maximum number of reconnects
maxReconnects?: number;
// Randomly choose a server to use for reconnect
randomize?: boolean;
// Override the connect function
connectFunction?: (options: ConnectOptions, connectionListener?: (err: Error | null, client: Client) => void) => Client;
}
interface Server {
connectOptions: ConnectOptions;
remoteAddress: AddressInfo;
blacklist(error?: Error): void;
isBlacklisted(): boolean;
getBlacklistError(): Error;
}
// Internal class, which is not exported
interface ConnectState {
serverProperties: Server;
failedConnects: number;
}
interface ConnectError extends Error {
connectArgs: ConnectOptions;
}
}

View File

@ -0,0 +1,17 @@
import { Transform, Readable, TransformOptions } from "stream";
declare class IncomingFrameStream extends Transform {
constructor(opts?: TransformOptions);
setVersion(versionId: string): boolean;
}
export = IncomingFrameStream;
declare namespace IncomingFrameStream {
// Internal class, which is not exported
interface IncomingFrame extends Readable {
readEmptyBody(callback?: (isEmpty: boolean) => void): void;
readString(encoding: string, callback?: (err: Error | null, buffer?: string) => void): void;
}
}

View File

@ -0,0 +1,16 @@
import { Duplex, Writable, WritableOptions } from "stream";
declare class OutgoingFrameStream {
constructor(destination: Duplex);
setVersion(versionId: string): boolean;
frame(command: string, headers?: any, streamOptions?: WritableOptions): Writable;
heartbeat(): void;
finish(): void;
hasFinished(): boolean;
}
export = OutgoingFrameStream;

55
types/stompit/lib/Socket.d.ts vendored Normal file
View File

@ -0,0 +1,55 @@
import { EventEmitter } from "events";
import { Duplex, WritableOptions, Writable } from "stream";
import OutgoingFrameStream = require("./OutgoingFrameStream");
declare class Socket extends EventEmitter {
constructor(transportSocket: Duplex, options: Socket.SocketOptions);
destroy(exception: Error): void;
hasFinishedOutput(): boolean;
setVersion(version: string): void;
getTransportSocket(): Duplex;
setCommandHandler(command: string, handler: Socket.commandHandler): void;
setCommandHandlers(handlers: Socket.CommandHandlers): void;
setUnknownCommandHandler(handler: () => void): void;
sendFrame(command: string, headers?: any, streamOptions?: WritableOptions): Writable;
getHeartbeat(): Socket.Heartbeat;
setHeartbeat(heartbeat: Socket.Heartbeat): void;
createTransportError(message?: string | Error): Socket.SocketError;
createProtocolError(message?: string | Error): Socket.SocketError;
createApplicationError(message?: string | Error): Socket.SocketError;
}
export = Socket;
declare namespace Socket {
type Heartbeat = number[];
type commandHandler = (frame: Writable) => void;
interface CommandHandlers {
[command: string]: (frame: Writable, callback: commandHandler) => void;
}
interface SocketOptions {
commandHandlers?: CommandHandlers;
unknownCommand?: () => void;
outgoingFrameStream?: OutgoingFrameStream;
heartbeat?: Heartbeat;
heartbeatDelayMargin?: number;
heartbeatOutputMargin?: number;
resetDisconnect?: boolean;
}
interface SocketError extends Error {
isTransportError: () => boolean;
isProtocolError: () => boolean;
isApplicationError: () => boolean;
}
}

View File

@ -0,0 +1,14 @@
import { Ack, MessageCallback } from "../Client";
import { Readable, Writable } from "stream";
import Client = require("../Client");
declare class Subscription {
constructor(id: number, ack: Ack, onMessageCallback: MessageCallback, client: Client);
getId(): number;
processMessageFrame(error: Error | null, frame: Writable): void;
unsubscribe(headers?: any): void;
}
export = Subscription;

View File

@ -0,0 +1,15 @@
import { Writable } from "stream";
import { SendOptions } from "../Client";
import Client = require("../Client");
declare class Transaction {
constructor(id: number, client: Client);
send(headers?: any, options?: SendOptions): Writable;
commit(options?: SendOptions): void;
abort(options?: SendOptions): void;
}
export = Transaction;

View File

@ -0,0 +1,17 @@
import { ConnectOptions } from "../connect";
declare function getAddressInfo(args: ConnectOptions): getAddressInfo.AddressInfo;
export = getAddressInfo;
declare namespace getAddressInfo {
interface AddressInfo {
connectArgs: ConnectOptions;
transport: string;
transportPath: string;
path?: string;
host?: string;
port?: number;
pseudoUri: string;
}
}

40
types/stompit/lib/connect.d.ts vendored Normal file
View File

@ -0,0 +1,40 @@
import { Socket, TcpNetConnectOpts, IpcNetConnectOpts } from "net";
import { ConnectionOptions as TlsConnectionOptions } from "tls";
import Client = require("./Client");
import { SocketOptions } from "./Socket";
declare function connect(optionsOrPath: connect.ConnectOptions | string, connectionListener?: (err: Error | null, client: Client) => void): Client;
declare function connect(port: number, host?: string, connectionListener?: (err: Error | null, client: Client) => void): Client;
export = connect;
declare namespace connect {
interface ConnectHeaders {
"accept-version"?: string;
"heart-beat"?: string;
host?: string;
login?: string;
passcode?: string;
}
interface BaseConnectOptions extends SocketOptions {
connectHeaders?: ConnectHeaders;
ssl?: boolean;
connect?: (options: ConnectOptions, connectionListener?: () => void) => Socket;
}
interface NetTcpConnectOptions extends BaseConnectOptions, TcpNetConnectOpts {
ssl?: false;
}
interface NetIpcConnectOptions extends BaseConnectOptions, IpcNetConnectOpts {
ssl?: false;
}
interface SslConnectOptions extends BaseConnectOptions, TlsConnectionOptions {
ssl: true;
}
type ConnectOptions = NetTcpConnectOptions | NetIpcConnectOptions | SslConnectOptions;
}

View File

@ -0,0 +1,470 @@
// Adapted from README
import stompit = require("stompit");
import fs = require("fs");
import path = require("path");
import { NetTcpConnectOptions } from "stompit/lib/connect";
{
const connectOptions = {
host: "localhost",
port: 61613,
connectHeaders: {
host: "/",
login: "username",
passcode: "password",
"heart-beat": "5000,5000"
}
};
stompit.connect(
connectOptions,
(error, client) => {
if (error) {
console.log("connect error " + error.message);
return;
}
const sendHeaders = {
destination: "/queue/test",
"content-type": "text/plain"
};
const frame = client.send(sendHeaders);
frame.write("hello");
frame.end();
const subscribeHeaders = {
destination: "/queue/test",
ack: "client-individual"
};
client.subscribe(subscribeHeaders, (error, message) => {
if (error) {
console.log("subscribe error " + error.message);
return;
}
message.readString("utf-8", (error, body) => {
if (error) {
console.log("read message error " + error.message);
return;
}
console.log("received message: " + body);
client.ack(message);
client.disconnect();
});
});
}
);
}
// Adapted from examples folder
// channel/consume_once.js
{
// Configure connection management
const servers = [
{
host: "localhost",
port: 61613,
connectHeaders: {
host: "localhost",
login: "admin",
passcode: "password",
"heart-beat": "100,100"
}
}
];
const reconnectOptions = {
maxReconnects: 1
};
const connections = new stompit.ConnectFailover(servers, reconnectOptions);
// Log connection events
connections.on("connecting", connector => {
const address = connector.serverProperties.remoteAddress.transportPath;
console.log("Connecting to " + address);
});
connections.on("error", error => {
const connectArgs = error.connectArgs as NetTcpConnectOptions;
const address = `${connectArgs.host}:${connectArgs.port}`;
console.log(`Connection error to ${address}: ${error.message}`);
});
// Create channel, subscribe to a queue, and consume one message
const channelFactory = new stompit.ChannelFactory(connections);
channelFactory.channel((error, channel) => {
if (error) {
console.log("channel factory error: " + error.message);
return;
}
const headers = {
destination: "/queue/test",
ack: "client-individual"
};
channel.subscribe(headers, (error, message, subscription) => {
if (error) {
console.log("subscribe error: " + error.message);
return;
}
message.readString("utf8", (error, string) => {
if (error) {
console.log("read message error: " + error.message);
return;
}
console.log("receive message: " + string);
channel.ack(message);
// We only want to consume one message so we unsubscribe now
subscription.unsubscribe();
});
});
});
}
// channel/send.js
{
// Configure connection management
const servers = [
{
host: "localhost",
port: 61613,
connectHeaders: {
host: "localhost",
login: "admin",
passcode: "password"
}
}
];
const reconnectOptions = {
maxReconnects: 1
};
const connections = new stompit.ConnectFailover(servers, reconnectOptions);
// Log connection events
connections.on("connecting", connector => {
const address = connector.serverProperties.remoteAddress.transportPath;
console.log("Connecting to " + address);
});
connections.on("error", error => {
const connectArgs = error.connectArgs as NetTcpConnectOptions;
const address = `${connectArgs.host}:${connectArgs.port}`;
console.log(`Connection error to ${address}: ${error.message}`);
});
// Create channel and send message
const channelFactory = new stompit.ChannelFactory(connections);
channelFactory.channel((error, channel) => {
if (error) {
console.log("channel factory error: " + error.message);
return;
}
const headers = {
destination: "/queue/test",
"content-type": "text/plain",
"content-length": 5
};
const body = "hello";
channel.send(headers, body, error => {
if (error) {
console.log("send error: " + error.message);
return;
}
console.log("sent message");
});
});
}
// client/consume_once.js
{
const connectParams = {
host: "localhost",
port: 61613,
connectHeaders: {
host: "localhost",
login: "admin",
passcode: "password"
}
};
stompit.connect(
connectParams,
(error, client) => {
if (error) {
console.log("Unable to connect: " + error.message);
return;
}
const subscribeParams = {
destination: "/queue/test",
ack: "client-individual"
};
let consuming = false;
client.subscribe(subscribeParams, (error, message) => {
// Don't consume more than one message
if (consuming) {
return;
}
consuming = true;
const read = () => {
let chunk: any;
// tslint:disable-next-line:no-conditional-assignment
while (null !== (chunk = message.read())) {
process.stdout.write(chunk);
}
};
message.on("readable", read);
message.on("end", () => {
client.ack(message);
client.disconnect();
});
});
}
);
}
// client/send_file.js
{
const connectParams = {
host: "localhost",
port: 61613,
connectHeaders: {
host: "localhost",
login: "admin",
passcode: "password"
}
};
stompit.connect(
connectParams,
(error, client) => {
if (error) {
console.log("Unable to connect: " + error.message);
return;
}
const filename = path.dirname(module.filename) + "/data/input1.jpg";
const fileStat = fs.statSync(filename);
const contentLength = fileStat.size;
const sendParams = {
destination: "/queue/test",
"content-type": "image/jpeg",
"content-length": contentLength
};
const frame = client.send(sendParams);
const file = fs.createReadStream(filename);
file.pipe(frame);
client.disconnect(error => {
if (error) {
console.log("Error while disconnecting: " + error.message);
return;
}
console.log("Sent file");
});
}
);
}
// client/send.js
{
const connectParams = {
host: "localhost",
port: 61613,
connectHeaders: {
host: "localhost",
login: "admin",
passcode: "password"
}
};
stompit.connect(
connectParams,
(error, client) => {
if (error) {
console.log("Unable to connect: " + error.message);
return;
}
const sendParams = {
destination: "/queue/test",
"content-type": "application/json"
};
const frame = client.send(sendParams);
frame.end(
JSON.stringify({
anything: "anything",
example: true
})
);
client.disconnect(error => {
if (error) {
console.log("Error while disconnecting: " + error.message);
return;
}
console.log("Sent message");
});
}
);
}
// client/transaction.js
{
const connectParams = {
host: "localhost",
port: 61613,
connectHeaders: {
host: "localhost",
login: "admin",
passcode: "password"
}
};
stompit.connect(
connectParams,
(error, client) => {
if (error) {
console.log("Unable to connect: " + error.message);
return;
}
const transaction = client.begin();
transaction.send({ destination: "/queue/test" }).end("first");
transaction.send({ destination: "/queue/test" }).end("second");
transaction.commit(); // or call transaction.abort()
client.disconnect(error => {
if (error) {
console.log("Error while disconnecting: " + error.message);
return;
}
console.log("Sent messages");
});
}
);
}
// pubsub.js
{
const connectionManager = new stompit.ConnectFailover([
{
host: "localhost",
port: 61613,
resetDisconnect: false,
connectHeaders: {
"accept-version": "1.0",
host: "localhost",
login: "admin",
passcode: "password",
"heart-beat": "1000,1000"
}
}
]);
connectionManager.on("error", error => {
const connectArgs = error.connectArgs as NetTcpConnectOptions;
const address = `${connectArgs.host}:${connectArgs.port}`;
console.log(`Could not connect to ${address}: ${error.message}`);
});
connectionManager.on("connecting", connector => {
console.log("Connecting to " + connector.serverProperties.remoteAddress.transportPath);
});
const channelPool = new stompit.ChannelPool(connectionManager);
channelPool.channel((error, channel) => {
if (error) {
console.log("send-channel error: " + error.message);
return;
}
const sendHeaders = {
destination: "/queue/a"
};
channel.send(sendHeaders, "hello", error => {
if (error) {
console.log("send error " + error.message);
return;
}
console.log("message sent");
});
});
channelPool.channel((error, channel) => {
if (error) {
console.log("subscribe-channel error: " + error.message);
return;
}
const subscribeHeaders = {
destination: "/queue/a"
};
channel.subscribe(subscribeHeaders, (error, message, subscription) => {
if (error) {
console.log("subscribe error: " + error.message);
return;
}
message.readString("utf8", (error, body) => {
if (error) {
console.log("read message error " + error.message);
return;
}
console.log("received message: " + body);
subscription.unsubscribe();
});
});
});
}

View File

@ -0,0 +1,35 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"lib/client/Subscription.d.ts",
"lib/client/Transaction.d.ts",
"lib/connect-failover/getAddressInfo.d.ts",
"lib/Channel.d.ts",
"lib/ChannelFactory.d.ts",
"lib/ChannelPool.d.ts",
"lib/Client.d.ts",
"lib/connect.d.ts",
"lib/ConnectFailover.d.ts",
"lib/IncomingFrameStream.d.ts",
"lib/OutgoingFrameStream.d.ts",
"lib/Socket.d.ts",
"stompit-tests.ts"
]
}

View File

@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }