Deprecate whatwg-streams in favor for DOM types (#38785)

TypeScript 3.2 shipped with built-in type definitions for streams,
so this types package is no longer needed.
This commit is contained in:
Mattias Buelens 2019-10-03 23:26:56 +02:00 committed by Ryan Cavanaugh
parent 1dc4eaa79e
commit 20f812d176
5 changed files with 6 additions and 756 deletions

View File

@ -3906,6 +3906,12 @@
"sourceRepoURL": "https://github.com/neutrinojs/webpack-chain",
"asOfVersion": "5.2.0"
},
{
"libraryName": "typescript",
"typingsPackageName": "whatwg-streams",
"sourceRepoURL": "https://streams.spec.whatwg.org",
"asOfVersion": "3.2.1"
},
{
"libraryName": "winston",
"typingsPackageName": "winston",

View File

@ -1,167 +0,0 @@
// Type definitions for Streams API
// Project: https://github.com/whatwg/streams
// Definitions by: Kagami Sascha Rosylight <https://github.com/saschanaz>
// Konstantin Simon Maria Möllers <https://github.com/ksm2>
// Mattias Buelens <https://github.com/MattiasBuelens>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
export interface ReadableStreamSource<R = ArrayBufferView> {
start?(controller: ReadableStreamDefaultController<R>): void | Promise<any>;
pull?(controller: ReadableStreamDefaultController<R>): void | Promise<any>;
cancel?(reason: any): void | Promise<any>;
}
export interface ReadableByteStreamSource {
start?(controller: ReadableByteStreamController): void | Promise<any>;
pull?(controller: ReadableByteStreamController): void | Promise<any>;
cancel?(reason: any): void | Promise<any>;
type: "bytes";
autoAllocateChunkSize?: number;
}
export interface QueuingStrategy<T = ArrayBufferView> {
size?(chunk: T): number;
highWaterMark?: number;
}
export interface PipeOptions {
preventClose?: boolean;
preventAbort?: boolean;
preventCancel?: boolean;
}
export interface WritableReadablePair<T extends WritableStream<any>, U extends ReadableStream<any>> {
writable: T;
readable: U;
}
export interface ReadResult<T> {
done: boolean;
value: T;
}
declare class ReadableStream<R = ArrayBufferView> {
constructor(underlyingSource?: ReadableStreamSource<R>, strategy?: QueuingStrategy<R>);
constructor(underlyingSource?: ReadableByteStreamSource, strategy?: QueuingStrategy<R>);
readonly locked: boolean;
cancel(reason: any): Promise<void>;
getReader(): ReadableStreamDefaultReader<R>;
getReader({ mode }: { mode: "byob" }): ReadableStreamBYOBReader<R>;
pipeThrough<T extends ReadableStream<any>>({ writable, readable }: WritableReadablePair<WritableStream<R>, T>, options?: PipeOptions): T;
pipeTo(dest: WritableStream<R>, options?: PipeOptions): Promise<void>;
tee(): [ReadableStream<R>, ReadableStream<R>];
}
declare class ReadableStreamDefaultReader<R = ArrayBufferView> {
constructor(stream: ReadableStream<R>);
readonly closed: Promise<void>;
cancel(reason: any): Promise<void>;
read(): Promise<ReadResult<R>>;
releaseLock(): void;
}
declare class ReadableStreamBYOBReader<R = ArrayBufferView> {
constructor(stream: ReadableStream<R>);
readonly closed: Promise<void>;
cancel(reason: any): Promise<void>;
read<T extends ArrayBufferView>(view: T): Promise<ReadResult<T>>;
releaseLock(): void;
}
declare class ReadableStreamDefaultController<R = ArrayBufferView> {
readonly desiredSize: number | null;
close(): void;
enqueue(chunk: R): void;
error(e: any): void;
}
declare class ReadableByteStreamController {
readonly byobRequest: ReadableStreamBYOBRequest | undefined;
readonly desiredSize: number | null;
close(): void;
enqueue(chunk: ArrayBufferView): void;
error(e: any): void;
}
declare class ReadableStreamBYOBRequest {
readonly view: Uint8Array;
respond(bytesWritten: number): void;
respondWithNewView(view: ArrayBufferView): void;
}
interface WritableStreamSink<W = ArrayBufferView> {
start?(controller: WritableStreamDefaultController<W>): void | Promise<any>;
write?(chunk: W, controller?: WritableStreamDefaultController<W>): void | Promise<any>;
close?(controller: WritableStreamDefaultController<W>): void | Promise<any>;
abort?(reason: any): void | Promise<any>;
}
declare class WritableStream<W = ArrayBufferView> {
constructor(underlyingSink?: WritableStreamSink<W>, strategy?: QueuingStrategy<W>);
readonly locked: boolean;
abort(reason: any): Promise<void>;
getWriter(): WritableStreamDefaultWriter<W>;
}
declare class WritableStreamDefaultWriter<W = ArrayBufferView> {
constructor(stream: WritableStream<W>);
readonly closed: Promise<void>;
readonly desiredSize: number | null;
readonly ready: Promise<void>;
abort(reason: any): Promise<void>;
close(): Promise<void>;
releaseLock(): void;
write(chunk: W): Promise<void>;
}
declare class WritableStreamDefaultController<W = ArrayBufferView> {
error(e: any): void;
}
declare class ByteLengthQueuingStrategy<T = ArrayBufferView> {
constructor({ highWaterMark }: { highWaterMark: number });
size(chunk: T): number | undefined;
}
declare class CountQueuingStrategy {
constructor({ highWaterMark }: { highWaterMark: number });
size(): 1;
}
export interface TransformStreamTransformer<R, W> {
start?(controller: TransformStreamDefaultController<R>): void | Promise<any>;
transform?(chunk: W, controller: TransformStreamDefaultController<R>): void | Promise<any>;
flush?(controller: TransformStreamDefaultController<R>): void | Promise<any>;
}
declare class TransformStream<R, W> implements WritableReadablePair<WritableStream<W>, ReadableStream<R>> {
constructor(transformer?: TransformStreamTransformer<R, W>, writableStrategy?: QueuingStrategy<W>, readableStrategy?: QueuingStrategy<R>);
readonly readable: ReadableStream<R>;
readonly writable: WritableStream<W>;
}
declare class TransformStreamDefaultController<R> {
enqueue(chunk: R): void;
error(reason: any): void;
terminate(): void;
readonly desiredSize: number | null;
}

View File

@ -1,24 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6",
"dom"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"whatwg-streams-tests.ts"
]
}

View File

@ -1,80 +0,0 @@
{
"extends": "dtslint/dt.json",
"rules": {
"adjacent-overload-signatures": false,
"array-type": false,
"arrow-return-shorthand": false,
"ban-types": false,
"callable-types": false,
"comment-format": false,
"dt-header": false,
"npm-naming": false,
"eofline": false,
"export-just-namespace": false,
"import-spacing": false,
"interface-name": false,
"interface-over-type-literal": false,
"jsdoc-format": false,
"max-line-length": false,
"member-access": false,
"new-parens": false,
"no-any-union": false,
"no-boolean-literal-compare": false,
"no-conditional-assignment": false,
"no-consecutive-blank-lines": false,
"no-construct": false,
"no-declare-current-package": false,
"no-duplicate-imports": false,
"no-duplicate-variable": false,
"no-empty-interface": false,
"no-for-in-array": false,
"no-inferrable-types": false,
"no-internal-module": false,
"no-irregular-whitespace": false,
"no-mergeable-namespace": false,
"no-misused-new": false,
"no-namespace": false,
"no-object-literal-type-assertion": false,
"no-padding": false,
"no-redundant-jsdoc": false,
"no-redundant-jsdoc-2": false,
"no-redundant-undefined": false,
"no-reference-import": false,
"no-relative-import-in-test": false,
"no-self-import": false,
"no-single-declare-module": false,
"no-string-throw": false,
"no-unnecessary-callback-wrapper": false,
"no-unnecessary-class": false,
"no-unnecessary-generics": false,
"no-unnecessary-qualifier": false,
"no-unnecessary-type-assertion": false,
"no-useless-files": false,
"no-var-keyword": false,
"no-var-requires": false,
"no-void-expression": false,
"no-trailing-whitespace": false,
"object-literal-key-quotes": false,
"object-literal-shorthand": false,
"one-line": false,
"one-variable-per-declaration": false,
"only-arrow-functions": false,
"prefer-conditional-expression": false,
"prefer-const": false,
"prefer-declare-function": false,
"prefer-for-of": false,
"prefer-method-signature": false,
"prefer-template": false,
"radix": false,
"semicolon": false,
"space-before-function-paren": false,
"space-within-parens": false,
"strict-export-declare-modifiers": false,
"trim-file": false,
"triple-equals": false,
"typedef-whitespace": false,
"unified-signatures": false,
"void-return": false,
"whitespace": false
}
}

View File

@ -1,485 +0,0 @@
/// <reference types="node" />
import {
ReadableStream, ReadableStreamSource, WritableStream,
ReadableStreamDefaultController, WritableStreamSink, WritableStreamDefaultController, ReadableByteStreamController,
TransformStream, TransformStreamDefaultController, TransformStreamTransformer
} from "whatwg-streams";
// Examples taken from https://streams.spec.whatwg.org/#creating-examples
// 8.1. A readable stream with an underlying push source (no backpressure support)
function makeReadableWebSocketStream(url: string, protocols: string | string[]) {
const ws = new WebSocket(url, protocols);
ws.binaryType = "arraybuffer";
return new ReadableStream({
start(controller) {
ws.onmessage = event => controller.enqueue(event.data);
ws.onclose = () => controller.close();
ws.onerror = () => controller.error(new Error("The WebSocket errored!"));
},
cancel() {
ws.close();
}
});
}
{
const writableStream = new WritableStream();
const webSocketStream = makeReadableWebSocketStream("wss://example.com:443/", "protocol");
webSocketStream.pipeTo(writableStream)
.then(() => console.log("All data successfully written!"))
.catch(e => console.error("Something went wrong!", e));
}
// 8.2. A readable stream with an underlying push source and backpressure support
function makeReadableBackpressureSocketStream(host: string, port: number) {
const socket = createBackpressureSocket(host, port);
return new ReadableStream({
start(controller) {
socket.ondata = (event: any) => {
controller.enqueue(event.data);
if (controller.desiredSize! <= 0) {
// The internal queue is full, so propagate
// the backpressure signal to the underlying source.
socket.readStop();
}
};
socket.onend = () => controller.close();
socket.onerror = () => controller.error(new Error("The socket errored!"));
},
pull() {
// This is called if the internal queue has been emptied, but the
// streams consumer still wants more data. In that case, restart
// the flow of data if we have previously paused it.
socket.readStart();
},
cancel() {
socket.close();
}
});
function createBackpressureSocket(host: string, port: number): any { };
}
// 8.3. A readable byte stream with an underlying push source (no backpressure support)
const DEFAULT_CHUNK_SIZE = 65536;
function makeUDPSocketStream(host: string, port: number) {
const socket = createUDPSocket(host, port);
return new ReadableStream({
type: "bytes",
start(controller: ReadableByteStreamController) {
readRepeatedly().catch(e => controller.error(e));
function readRepeatedly(): Promise<void> {
return socket.select2().then(() => {
// Since the socket can become readable even when theres
// no pending BYOB requests, we need to handle both cases.
let bytesRead: number;
if (controller.byobRequest) {
const v = controller.byobRequest.view;
bytesRead = socket.readInto(v.buffer, v.byteOffset, v.byteLength);
controller.byobRequest.respond(bytesRead);
} else {
const buffer = new ArrayBuffer(DEFAULT_CHUNK_SIZE);
bytesRead = socket.readInto(buffer, 0, DEFAULT_CHUNK_SIZE);
controller.enqueue(new Uint8Array(buffer, 0, bytesRead));
}
if (bytesRead === 0) {
controller.close();
return;
}
return readRepeatedly();
});
}
},
cancel() {
socket.close();
}
});
function createUDPSocket(host: string, port: number): any { };
}
// 8.4. A readable stream with an underlying pull source
//const fs = require("pr/fs"); // https://github.com/jden/pr
interface fs {
open(path: string | Buffer, flags: string | number): Promise<number>;
read(fd: number, buffer: Buffer, offset: number, length: number, position: number): Promise<number>;
write(fd: number, buffer: Buffer | string, offset: number, length: number): Promise<number>;
close(fd: number): Promise<void>;
}
let fs: fs;
const CHUNK_SIZE = 1024;
function makeReadableFileStream(filename: string) {
let fd: number;
let position = 0;
return new ReadableStream({
start() {
return fs.open(filename, "r").then(result => {
fd = result;
});
},
pull(controller) {
const buffer = new ArrayBuffer(CHUNK_SIZE);
return fs.read(fd, buffer as any, 0, CHUNK_SIZE, position).then(bytesRead => {
if (bytesRead === 0) {
return fs.close(fd).then(() => controller.close());
} else {
position += bytesRead;
controller.enqueue(new Uint8Array(buffer, 0, bytesRead));
}
});
},
cancel() {
return fs.close(fd);
}
});
}
// 8.5. A readable byte stream with an underlying pull source
//const fs = require("pr/fs"); // https://github.com/jden/pr
//const DEFAULT_CHUNK_SIZE = 1024;
function makeReadableByteFileStream(filename: string) {
let fd: number;
let position = 0;
return new ReadableStream({
type: "bytes",
start() {
return fs.open(filename, "r").then(result => {
fd = result;
});
},
pull(controller: ReadableByteStreamController) {
// Even when the consumer is using the default reader, the auto-allocation
// feature allocates a buffer and passes it to us via byobRequest.
const v = controller.byobRequest!.view;
return fs.read(fd, v.buffer as any, v.byteOffset, v.byteLength, position).then(bytesRead => {
if (bytesRead === 0) {
return fs.close(fd).then(() => controller.close());
} else {
position += bytesRead;
controller.byobRequest!.respond(bytesRead);
}
});
},
cancel() {
return fs.close(fd);
},
autoAllocateChunkSize: DEFAULT_CHUNK_SIZE
});
}
// 8.6. A writable stream with no backpressure or success signals
function makeWritableWebSocketStream(url: string, protocols: string | string[]) {
const ws = new WebSocket(url, protocols);
return new WritableStream({
start(controller) {
ws.onerror = () => controller.error(new Error("The WebSocket errored!"));
return new Promise<void>(resolve => ws.onopen = () => resolve());
},
write(chunk) {
ws.send(chunk);
// Return immediately, since the web socket gives us no easy way to tell
// when the write completes.
},
close() {
return new Promise<void>((resolve, reject) => {
ws.onclose = () => resolve();
ws.close();
});
}
});
}
{
const readableStream = new ReadableStream();
const webSocketStream = makeWritableWebSocketStream("wss://example.com:443/", "protocol");
readableStream.pipeTo(webSocketStream)
.then(() => console.log("All data successfully written!"))
.catch(e => console.error("Something went wrong!", e));
}
// 8.7. A writable stream with backpressure and success signals
//const fs = require("pr/fs"); // https://github.com/jden/pr
function makeWritableFileStream(filename: string) {
let fd: number;
return new WritableStream<string>({
start() {
return fs.open(filename, "w").then(result => {
fd = result;
});
},
write(chunk) {
return fs.write(fd, chunk, 0, chunk.length);
},
close() {
return fs.close(fd);
}
});
}
{
const fileStream = makeWritableFileStream("/example/path/on/fs.txt");
const writer = fileStream.getWriter();
writer.write("To stream, or not to stream\n");
writer.write("That is the question\n");
writer.close()
.then(() => console.log("chunks written and stream closed successfully!"))
.catch(e => console.error(e));
}
// 8.8. A { readable, writable } stream pair wrapping the same underlying resource
function streamifyWebSocket(url: string, protocol: string) {
const ws = new WebSocket(url, protocol);
ws.binaryType = "arraybuffer";
return {
readable: new ReadableStream(new WebSocketSource(ws)),
writable: new WritableStream<string>(new WebSocketSink(ws))
};
}
class WebSocketSource implements ReadableStreamSource {
private readonly _ws: WebSocket;
constructor(ws: WebSocket) {
this._ws = ws;
}
start(controller: ReadableStreamDefaultController) {
this._ws.onmessage = event => controller.enqueue(event.data);
this._ws.onclose = () => controller.close();
this._ws.addEventListener("error", () => {
controller.error(new Error("The WebSocket errored!"));
});
}
cancel() {
this._ws.close();
}
}
class WebSocketSink implements WritableStreamSink {
private readonly _ws: WebSocket;
constructor(ws: WebSocket) {
this._ws = ws;
}
start(controller: WritableStreamDefaultController) {
this._ws.addEventListener("error", () => {
controller.error(new Error("The WebSocket errored!"));
});
return new Promise<void>(resolve => this._ws.onopen = () => resolve());
}
write(chunk: any) {
this._ws.send(chunk);
}
close() {
return new Promise<void>((resolve, reject) => {
this._ws.onclose = () => resolve();
this._ws.close();
});
}
}
{
const streamyWS = streamifyWebSocket("wss://example.com:443/", "protocol");
const writer = streamyWS.writable.getWriter();
const reader = streamyWS.readable.getReader();
writer.write("Hello");
writer.write("web socket!");
reader.read().then(({ value, done }) => {
console.log("The web socket says: ", value);
});
}
// 8.9. A transform stream that replaces template tags
type Dictionary<T> = { [key: string]: T }
declare function fetch(input?: Request | string): Promise<Response>;
declare interface FetchEvent {
readonly request: Request;
respondWith(promise: Promise<Response>): void;
}
declare class Request {
readonly url: string;
}
declare class Response {
constructor(body?: ReadableStream);
readonly body: ReadableStream;
}
declare class TextDecoderStream extends TransformStream<string, ArrayBufferView> {
}
declare class TextEncoderStream extends TransformStream<Uint8Array, string> {
}
class LipFuzzTransformer implements TransformStreamTransformer<string, string> {
substitutions: Dictionary<string>;
partialChunk: string;
lastIndex: number | undefined;
constructor(substitutions: Dictionary<string>) {
this.substitutions = substitutions;
this.partialChunk = "";
this.lastIndex = undefined;
}
transform(chunk: string, controller: TransformStreamDefaultController<string>) {
chunk = this.partialChunk + chunk;
this.partialChunk = "";
// lastIndex is the index of the first character after the last substitution.
this.lastIndex = 0;
chunk = chunk.replace(/\{\{([a-zA-Z0-9_-]+)\}\}/g, this.replaceTag.bind(this));
// Regular expression for an incomplete template at the end of a string.
const partialAtEndRegexp = /\{(\{([a-zA-Z0-9_-]+(\})?)?)?$/g;
// Avoid looking at any characters that have already been substituted.
partialAtEndRegexp.lastIndex = this.lastIndex;
this.lastIndex = undefined;
const match = partialAtEndRegexp.exec(chunk);
if (match) {
this.partialChunk = chunk.substring(match.index);
chunk = chunk.substring(0, match.index);
}
controller.enqueue(chunk);
}
flush(controller: TransformStreamDefaultController<string>) {
if (this.partialChunk.length > 0) {
controller.enqueue(this.partialChunk);
}
}
replaceTag(match: string, p1: string, offset: number) {
let replacement = this.substitutions[p1];
if (replacement === undefined) {
replacement = "";
}
this.lastIndex = offset + replacement.length;
return replacement;
}
}
{
const userName = "";
const displayName = "";
const icon = "";
const date = "";
const fetchEvent = {} as FetchEvent;
const data = { userName, displayName, icon, date };
const ts = new TransformStream(new LipFuzzTransformer(data));
fetchEvent.respondWith(
fetch(fetchEvent.request.url).then(response => {
const transformedBody = response.body
// Decode the binary-encoded response to string
.pipeThrough(new TextDecoderStream())
// Apply the LipFuzzTransformer
.pipeThrough(ts)
// Encode the transformed string
.pipeThrough(new TextEncoderStream());
return new Response(transformedBody);
})
);
}
// 8.10. A transform stream created from a sync mapper function
function mapperTransformStream<R, W>(mapperFunction: (chunk: W) => R) {
return new TransformStream<R, W>({
transform(chunk, controller) {
controller.enqueue(mapperFunction(chunk));
}
});
}
{
const ts = mapperTransformStream((chunk: string) => chunk.toUpperCase());
const writer = ts.writable.getWriter();
const reader = ts.readable.getReader();
writer.write("No need to shout");
// Logs "NO NEED TO SHOUT":
reader.read().then(({ value }) => console.log(value));
}
{
const ts = mapperTransformStream((chunk: string) => JSON.parse(chunk));
const writer = ts.writable.getWriter();
const reader = ts.readable.getReader();
writer.write("[1, ");
// Logs a SyntaxError, twice:
reader.read().catch(e => console.error(e));
writer.write("{}").catch(e => console.error(e));
}