Skip to content

Commit

Permalink
Remove @types node dev dependency from botframework-streaming (#1795)
Browse files Browse the repository at this point in the history
* replaced new Server with createNodeServer(); created test INodeSocket2 for type hint

* removed new Func unit test

* consolidated server-creation into 1 utils module; added unit tests

* removed await from Promise.all, as it was originally

* Update libraries/botframework-streaming/tests/NamedPipe.test.js

Co-Authored-By: Christopher Anderson <chrande@microsoft.com>

* replaced references to @types/node classes with bf-streaming interfaces, minus for the static methods on Buffer and nodeWebSocket.create()

* added more signatures to INodeSocket to remove Socket type dependency from WebSocketTransport

* cleaned up comment

* changed INodeSocket.connect() to return any, as the nested types on signature made it unsuitable to be a Socket (we are not creating interfaces for the multiple layers of node types

* changed Buffer to INodeBuffer type hint

* added type guards to ensure we're getting an INodeServer back from createNodeServer

* added unit test

* added duck typing checks for server methods

* Added methods to INodeSocket to remove dependency on node stream.Duplex type

* put server-creation in trycatch block, as we don't know if node 'net' module might change their Server ctor overloads

* removed space from top of imports in tests

* added false path to checks (whoops, forgot them)

* moved imort below comment

Co-authored-by: Christopher Anderson <chrande@microsoft.com>
Co-authored-by: Steven Ickman <stevenic@microsoft.com>
  • Loading branch information
3 people authored Mar 4, 2020
1 parent 8a7456e commit cc6d78e
Show file tree
Hide file tree
Showing 19 changed files with 397 additions and 46 deletions.
7 changes: 4 additions & 3 deletions libraries/botframework-streaming/src/contentStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
import { SubscribableStream } from './subscribableStream';
import { PayloadAssembler } from './assemblers';
import { INodeBuffer } from './interfaces/INodeBuffer';

export class ContentStream {
public id: string;
Expand Down Expand Up @@ -57,22 +58,22 @@ export class ContentStream {

private async readAll(): Promise<Record<string, any>> {
// do a read-all
let allData: Buffer[] = [];
let allData: INodeBuffer[] = [];
let count = 0;
let stream = this.getStream();

// populate the array with any existing buffers
while (count < stream.length) {
let chunk = stream.read(stream.length);
allData.push(chunk);
count += (chunk as Buffer).length;
count += (chunk as INodeBuffer).length;
}

if (count < this.length) {
let readToEnd = new Promise<boolean>((resolve): void => {
let callback = (cs: ContentStream) => (chunk: any): void => {
allData.push(chunk);
count += (chunk as Buffer).length;
count += (chunk as INodeBuffer).length;
if (count === cs.length) {
resolve(true);
}
Expand Down
31 changes: 31 additions & 0 deletions libraries/botframework-streaming/src/interfaces/IEventEmitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @module botframework-streaming
*/
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/

/**
* Represents a EventEmitter from the `net` module in Node.js.
*
* This interface supports the framework and is not intended to be called directly for your code.
*/
export interface IEventEmitter {
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
off(event: string | symbol, listener: (...args: any[]) => void): this;
removeAllListeners(event?: string | symbol): this;
setMaxListeners(n: number): this;
getMaxListeners(): number;
listeners(event: string | symbol): Function[];
rawListeners(event: string | symbol): Function[];
emit(event: string | symbol, ...args: any[]): boolean;
listenerCount(type: string | symbol): number;
// Added in Node 6...
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
eventNames(): Array<string | symbol>;
}
74 changes: 72 additions & 2 deletions libraries/botframework-streaming/src/interfaces/INodeBuffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,79 @@
* Licensed under the MIT License.
*/

export type ValidBuffer = string | Uint8Array | INodeBuffer;

export type BufferEncoding = "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex";

/**
* Represents a Buffer from the `buffer` module in Node.js.
* Represents a Buffer from the `net` module in Node.js.
*
* This interface supports the framework and is not intended to be called directly for your code.
*/
export interface INodeBuffer { }
export interface INodeBuffer extends Uint8Array {
constructor: any;
write(string: string, offset?: number, length?: number, encoding?: string): number;
toString(encoding?: string, start?: number, end?: number): string;
toJSON(): { type: 'Buffer', data: any[] };
equals(otherBuffer: Uint8Array): boolean;
compare(otherBuffer: Uint8Array, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;
copy(targetBuffer: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
slice(start?: number, end?: number): this;

writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;

readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
readUInt8(offset: number, noAssert?: boolean): number;

readUInt16LE(offset: number, noAssert?: boolean): number;
readUInt16BE(offset: number, noAssert?: boolean): number;
readUInt32LE(offset: number, noAssert?: boolean): number;
readUInt32BE(offset: number, noAssert?: boolean): number;

readInt8(offset: number, noAssert?: boolean): number;
readInt16LE(offset: number, noAssert?: boolean): number;
readInt16BE(offset: number, noAssert?: boolean): number;
readInt32LE(offset: number, noAssert?: boolean): number;
readInt32BE(offset: number, noAssert?: boolean): number;

readFloatLE(offset: number, noAssert?: boolean): number;
readFloatBE(offset: number, noAssert?: boolean): number;
readDoubleLE(offset: number, noAssert?: boolean): number;
readDoubleBE(offset: number, noAssert?: boolean): number;

swap16(): this;
swap32(): this;
swap64(): this;

writeUInt8(value: number, offset: number, noAssert?: boolean): number;
writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;
writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;
writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;
writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;

writeInt8(value: number, offset: number, noAssert?: boolean): number;
writeInt16LE(value: number, offset: number, noAssert?: boolean): number;
writeInt16BE(value: number, offset: number, noAssert?: boolean): number;
writeInt32LE(value: number, offset: number, noAssert?: boolean): number;
writeInt32BE(value: number, offset: number, noAssert?: boolean): number;

writeFloatLE(value: number, offset: number, noAssert?: boolean): number;
writeFloatBE(value: number, offset: number, noAssert?: boolean): number;

writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;
writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;

fill(value: any, offset?: number, end?: number): this;
indexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: string): number;
lastIndexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: string): number;
entries(): IterableIterator<[number, number]>;
includes(value: string | number | this, byteOffset?: number, encoding?: string): boolean;
keys(): IterableIterator<number>;
values(): IterableIterator<number>;
}
21 changes: 21 additions & 0 deletions libraries/botframework-streaming/src/interfaces/INodeServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @module botframework-streaming
*/
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/

import { IEventEmitter } from '.';

/**
* Represents a Server from the `net` module in Node.js.
*
* This interface supports the framework and is not intended to be called directly for your code.
*/
export interface INodeServer extends IEventEmitter {
constructor: this;
close(callback?: (err?: Error) => void): this;
listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this;
listen(path: string, listeningListener?: () => void): this;
}
140 changes: 139 additions & 1 deletion libraries/botframework-streaming/src/interfaces/INodeSocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,151 @@
* Licensed under the MIT License.
*/

import { INodeBuffer, ValidBuffer } from './INodeBuffer';
import { IEventEmitter } from './IEventEmitter';

/**
* Represents a Socket from the `net` module in Node.js.
*
* This interface supports the framework and is not intended to be called directly for your code.
*/
export interface INodeSocket {
connecting: boolean;
destroyed: boolean;
writable: boolean;
write(str: string, cb?: Function): boolean;
readable: boolean;
readonly bytesRead: number;
readonly bufferSize: number;
readonly bytesWritten: number;
readonly localAddress: string;
readonly localPort: number;
readonly writableHighWaterMark: number;
readonly writableLength: number;
readonly readableHighWaterMark: number;
readonly readableLength: number;

address(): AddressInfo | string;

connect(options: any, connectionListener?: () => void): any;
connect(port: number, host: string, connectionListener?: () => void): any;
connect(port: number, connectionListener?: () => void): any;
connect(path: string, connectionListener?: () => void): any;

cork(): void;
uncork(): void;

end(cb?: () => void): void;
end(chunk: any, cb?: () => void): void;
end(chunk: any, encoding?: string, cb?: () => void): void;

_destroy(error: Error | null, callback: (error: Error | null) => void): void;
destroy(error?: Error): void;

pause(): this;
resume(): this;
isPaused(): boolean;
unpipe(destination?: any): this;
unshift(chunk: any): void;
wrap(oldStream: any): this;
push(chunk: any, encoding?: string): boolean;

pipe<T extends WritableStream>(destination: T, options?: { end?: boolean; }): T;

addListener(event: "close", listener: () => void): this;
addListener(event: "data", listener: (chunk: any) => void): this;
addListener(event: "end", listener: () => void): this;
addListener(event: "readable", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;

emit(event: "close"): boolean;
emit(event: "data", chunk: any): boolean;
emit(event: "end"): boolean;
emit(event: "readable"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: string | symbol, ...args: any[]): boolean;

eventNames(): Array<string | symbol>;
_final(callback: (error?: Error | null) => void): void;
listeners(event: string | symbol): Function[];
listenerCount(type: string | symbol): number;

off(event: string | symbol, listener: (...args: any[]) => void): this;

on(event: string, listener: (...args: any[]) => void): this;
on(event: "close", listener: (had_error: boolean) => void): this;
on(event: "connect", listener: () => void): this;
on(event: "data", listener: (data: INodeBuffer) => void): this;
on(event: "end", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;

once(event: "close", listener: () => void): this;
once(event: "data", listener: (chunk: any) => void): this;
once(event: "end", listener: () => void): this;
once(event: "readable", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;

prependListener(event: "close", listener: () => void): this;
prependListener(event: "data", listener: (chunk: any) => void): this;
prependListener(event: "end", listener: () => void): this;
prependListener(event: "readable", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;

prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "data", listener: (chunk: any) => void): this;
prependOnceListener(event: "end", listener: () => void): this;
prependOnceListener(event: "readable", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;

rawListeners(event: string | symbol): Function[];

removeAllListeners(event?: string | symbol): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;

[Symbol.asyncIterator](): AsyncIterableIterator<any>;

_read(size: number): void;
read(size?: number): any;

setDefaultEncoding(encoding: string): this;
setEncoding(encoding: string): this;
setMaxListeners(n: number): this;
getMaxListeners(): number;
setTimeout(timeout: number, callback?: () => void): this;
setKeepAlive(enable?: boolean, initialDelay?: number): this;
setNoDelay(noDelay?: boolean): this;

_write(chunk: any, encoding: string, callback: (error?: Error | null) => void): void;
_writev?(chunks: Array<{ chunk: any, encoding: string }>, callback: (error?: Error | null) => void): void;

write(buffer: ValidBuffer, cb?: (err?: Error) => void): boolean;
write(str: string, encoding?: string, cb?: Function): boolean;
write(buffer: ValidBuffer): boolean;
write(str: string, cb?: Function): boolean;
write(str: string, encoding?: string, fd?: string): boolean;
write(data: any, encoding?: string, callback?: Function): void;
write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean;
write(chunk: any, encoding?: string, cb?: (error: Error | null | undefined) => void): boolean;

ref(): any;
unref(): any;
}

interface AddressInfo {
address: string;
family: string;
port: number;
}

interface WritableStream extends IEventEmitter {
writable: boolean;
write(buffer: Buffer | string, cb?: Function): boolean;
write(str: string, encoding?: string, cb?: Function): boolean;
end(cb?: Function): void;
end(buffer: Buffer, cb?: Function): void;
end(str: string, cb?: Function): void;
end(str: string, encoding?: string, cb?: Function): void;
}
5 changes: 4 additions & 1 deletion libraries/botframework-streaming/src/interfaces/ISocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
* The interface implemented by any compatible socket transport, typically used
* with the WebSocket server or client.
*/

import { INodeBuffer } from "./INodeBuffer";

export interface ISocket {
isConnected: boolean;
write(buffer: Buffer);
write(buffer: INodeBuffer);
connect(serverAddress: string): Promise<void>;
close();
setOnMessageHandler(handler: (x: any) => void);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
* Licensed under the MIT License.
*/
import { ITransport } from './ITransport';
import { INodeBuffer } from './INodeBuffer';

/**
* Definition of a streaming transport that can receive requests.
*/
export interface ITransportReceiver extends ITransport {
receive(count: number): Promise<Buffer>;
receive(count: number): Promise<INodeBuffer>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
* Licensed under the MIT License.
*/
import { ITransport } from './ITransport';
import { INodeBuffer } from './INodeBuffer';

/**
* Definition of a streaming transport that can send requests.
*/
export interface ITransportSender extends ITransport {
send(buffer: Buffer): number;
send(buffer: INodeBuffer): number;
}
2 changes: 2 additions & 0 deletions libraries/botframework-streaming/src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

export * from './IBrowserFileReader';
export * from './IBrowserWebSocket';
export * from './IEventEmitter';
export * from './INodeBuffer';
export * from './INodeIncomingMessage';
export * from './INodeServer';
export * from './INodeSocket';
export * from './IReceiveRequest';
export * from './IReceiveResponse';
Expand Down
Loading

0 comments on commit cc6d78e

Please sign in to comment.