BREAKING: reorganization (denoland/deno#5087)

* Prepend underscores to private modules
* Remove collectUint8Arrays() It would be a misuse of Deno.iter()'s result.
* Move _util/async.ts to async
* Move util/sha*.ts to hash
This commit is contained in:
Nayeem Rahman 2020-05-09 13:34:47 +01:00 committed by denobot
parent 45aafa4b27
commit 1eecc5c7d0
98 changed files with 302 additions and 361 deletions

View File

@ -19,28 +19,27 @@ Contributions are welcome!
These modules are tagged in accordance with Deno releases. So, for example, the
v0.3.0 tag is guaranteed to work with deno v0.3.0. You can link to v0.3.0 using
the URL `https://deno.land/std@v0.3.0/`
the URL `https://deno.land/std@v0.3.0/`. Not specifying a tag will link to the
master branch.
It's strongly recommended that you link to tagged releases rather than the
master branch. The project is still young and we expect disruptive renames in
the future.
It is strongly recommended that you link to tagged releases to avoid unintended
updates.
Don't link to / import any module whose path:
- Has a name or parent with an underscore prefix: `_foo.ts`, `_util/bar.ts`.
- Is that of a test module or test data: `test.ts`, `foo_test.ts`,
`testdata/bar.txt`.
No stability is guaranteed for these files.
## Documentation
Here are the dedicated documentations of modules:
To browse documentation for modules:
- [colors](fmt/colors.ts)
- [datetime](datetime/README.md)
- [encoding](encoding/README.md)
- [examples](examples/README.md)
- [flags](flags/README.md)
- [fs](fs/README.md)
- [http](http/README.md)
- [log](log/README.md)
- [node](node/README.md)
- [testing](testing/README.md)
- [uuid](uuid/README.md)
- [ws](ws/README.md)
- Go to https://deno.land/std/.
- Navigate to any module of interest.
- Click the "DOCUMENTATION" link.
## Contributing

26
async/deferred.ts Normal file
View File

@ -0,0 +1,26 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// TODO(ry) It'd be better to make Deferred a class that inherits from
// Promise, rather than an interface. This is possible in ES2016, however
// typescript produces broken code when targeting ES5 code.
// See https://github.com/Microsoft/TypeScript/issues/15202
// At the time of writing, the github issue is closed but the problem remains.
export interface Deferred<T> extends Promise<T> {
resolve: (value?: T | PromiseLike<T>) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
reject: (reason?: any) => void;
}
/** Creates a Promise with the `reject` and `resolve` functions
* placed as methods on the promise object itself. It allows you to do:
*
* const p = deferred<number>();
* // ...
* p.resolve(42);
*/
export function deferred<T>(): Deferred<T> {
let methods;
const promise = new Promise<T>((resolve, reject): void => {
methods = { resolve, reject };
});
return Object.assign(promise, methods) as Deferred<T>;
}

8
async/deferred_test.ts Normal file
View File

@ -0,0 +1,8 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { deferred } from "./deferred.ts";
Deno.test("[async] deferred", function (): Promise<void> {
const d = deferred<number>();
d.resolve(12);
return Promise.resolve();
});

9
async/delay.ts Normal file
View File

@ -0,0 +1,9 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
/* Resolves after the given number of milliseconds. */
export function delay(ms: number): Promise<void> {
return new Promise((res): number =>
setTimeout((): void => {
res();
}, ms)
);
}

4
async/mod.ts Normal file
View File

@ -0,0 +1,4 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
export * from "./deferred.ts";
export * from "./delay.ts";
export * from "./mux_async_iterator.ts";

View File

@ -0,0 +1,58 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { Deferred, deferred } from "./deferred.ts";
interface TaggedYieldedValue<T> {
iterator: AsyncIterableIterator<T>;
value: T;
}
/** The MuxAsyncIterator class multiplexes multiple async iterators into a
* single stream. It currently makes a few assumptions:
* - The iterators do not throw.
* - The final result (the value returned and not yielded from the iterator)
* does not matter; if there is any, it is discarded.
*/
export class MuxAsyncIterator<T> implements AsyncIterable<T> {
private iteratorCount = 0;
private yields: Array<TaggedYieldedValue<T>> = [];
private signal: Deferred<void> = deferred();
add(iterator: AsyncIterableIterator<T>): void {
++this.iteratorCount;
this.callIteratorNext(iterator);
}
private async callIteratorNext(
iterator: AsyncIterableIterator<T>
): Promise<void> {
const { value, done } = await iterator.next();
if (done) {
--this.iteratorCount;
} else {
this.yields.push({ iterator, value });
}
this.signal.resolve();
}
async *iterate(): AsyncIterableIterator<T> {
while (this.iteratorCount > 0) {
// Sleep until any of the wrapped iterators yields.
await this.signal;
// Note that while we're looping over `yields`, new items may be added.
for (let i = 0; i < this.yields.length; i++) {
const { iterator, value } = this.yields[i];
yield value;
this.callIteratorNext(iterator);
}
// Clear the `yields` list and reset the `signal` promise.
this.yields.length = 0;
this.signal = deferred();
}
}
[Symbol.asyncIterator](): AsyncIterableIterator<T> {
return this.iterate();
}
}

View File

@ -0,0 +1,28 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { assertEquals } from "../testing/asserts.ts";
import { MuxAsyncIterator } from "./mux_async_iterator.ts";
// eslint-disable-next-line require-await
async function* gen123(): AsyncIterableIterator<number> {
yield 1;
yield 2;
yield 3;
}
// eslint-disable-next-line require-await
async function* gen456(): AsyncIterableIterator<number> {
yield 4;
yield 5;
yield 6;
}
Deno.test("[async] MuxAsyncIterator", async function (): Promise<void> {
const mux = new MuxAsyncIterator<number>();
mux.add(gen123());
mux.add(gen456());
const results = new Set();
for await (const value of mux) {
results.add(value);
}
assertEquals(results.size, 6);
});

View File

@ -243,9 +243,7 @@ Serializes `object` as a YAML document.
### More example
See [`./yaml/example`](./yaml/example) folder and [js-yaml] repository.
[js-yaml]: https://github.com/nodeca/js-yaml
See https://github.com/nodeca/js-yaml.
## base32

View File

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { deepAssign } from "../util/deep_assign.ts";
import { deepAssign } from "../_util/deep_assign.ts";
import { assert } from "../testing/asserts.ts";
class KeyValuePair {

View File

@ -3,9 +3,9 @@
// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
export { ParseOptions, parse, parseAll } from "./yaml/parse.ts";
export { ParseOptions, parse, parseAll } from "./_yaml/parse.ts";
export {
DumpOptions as StringifyOptions,
stringify,
} from "./yaml/stringify.ts";
export * from "./yaml/schema/mod.ts";
} from "./_yaml/stringify.ts";
export { Schema, SchemaDefinition, TypeMap } from "./_yaml/schema/mod.ts";

View File

@ -1,4 +1,4 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import "./yaml/parse_test.ts";
import "./yaml/stringify_test.ts";
import "./_yaml/parse_test.ts";
import "./_yaml/stringify_test.ts";

View File

@ -3,7 +3,7 @@ import { assert, assertEquals } from "../../testing/asserts.ts";
import { TextProtoReader } from "../../textproto/mod.ts";
import { BufReader } from "../../io/bufio.ts";
import { connectWebSocket, WebSocket } from "../../ws/mod.ts";
import { delay } from "../../util/async.ts";
import { delay } from "../../async/delay.ts";
const { test } = Deno;

View File

@ -1,5 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
const { args } = Deno;
import { parse } from "./mod.ts";
import { parse } from "../flags/mod.ts";
console.dir(parse(args));
if (import.meta.main) {
console.dir(parse(args));
}

View File

@ -12,12 +12,12 @@ console.dir(parse(args));
```
```
$ deno run example.ts -a beep -b boop
$ deno run https://deno.land/std/examples/flags.ts -a beep -b boop
{ _: [], a: 'beep', b: 'boop' }
```
```
$ deno run example.ts -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
$ deno run https://deno.land/std/examples/flags.ts -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
{ _: [ 'foo', 'bar', 'baz' ],
x: 3,
y: 4,
@ -56,16 +56,13 @@ options can be:
the `--` and `parsedArgs['--']` with everything after the `--`. Here's an
example:
```ts
// $ deno run example.ts -- a arg1
const { args } = Deno;
import { parse } from "https://deno.land/std/flags/mod.ts";
// options['--'] is now set to false
console.dir(parse(args, { "--": false }));
// $ deno run example.ts -- a arg1
// output: { _: [ "example.ts", "a", "arg1" ] }
// options['--'] is now set to true
// output: { _: [ "a", "arg1" ] }
console.dir(parse(args, { "--": true }));
// $ deno run example.ts -- a arg1
// output: { _: [ "example.ts" ], --: [ "a", "arg1" ] }
// output: { _: [], --: [ "a", "arg1" ] }
```
- `options.unknown` - a function which is invoked with a command line parameter
not defined in the `options` configuration object. If the function returns

View File

@ -14,16 +14,13 @@ export interface ArgParsingOptions {
/** When `true`, populate the result `_` with everything before the `--` and
* the result `['--']` with everything after the `--`. Here's an example:
*
* // $ deno run example.ts -- a arg1
* const { args } = Deno;
* import { parse } from "https://deno.land/std/flags/mod.ts";
* // options['--'] is now set to false
* console.dir(parse(args, { "--": false }));
* // $ deno run example.ts -- a arg1
* // output: { _: [ "example.ts", "a", "arg1" ] }
* // options['--'] is now set to true
* // output: { _: [ "a", "arg1" ] }
* console.dir(parse(args, { "--": true }));
* // $ deno run example.ts -- a arg1
* // output: { _: [ "example.ts" ], --: [ "a", "arg1" ] }
* // output: { _: [], --: [ "a", "arg1" ] }
*
* Defaults to `false`.
*/

View File

@ -2,7 +2,7 @@
import { assertEquals } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { isSubdir, getFileInfoType, PathType } from "./utils.ts";
import { isSubdir, getFileInfoType, PathType } from "./_util.ts";
import { ensureFileSync } from "./ensure_file.ts";
import { ensureDirSync } from "./ensure_dir.ts";

View File

@ -1,7 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as path from "../path/mod.ts";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { isSubdir, getFileInfoType } from "./utils.ts";
import { isSubdir, getFileInfoType } from "./_util.ts";
import { assert } from "../testing/asserts.ts";
export interface CopyOptions {

View File

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { getFileInfoType } from "./utils.ts";
import { getFileInfoType } from "./_util.ts";
const { lstat, lstatSync, mkdir, mkdirSync } = Deno;
/**

View File

@ -1,7 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as path from "../path/mod.ts";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { getFileInfoType } from "./utils.ts";
import { getFileInfoType } from "./_util.ts";
const { lstat, lstatSync, writeFile, writeFileSync } = Deno;
/**

View File

@ -2,7 +2,7 @@
import * as path from "../path/mod.ts";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { exists, existsSync } from "./exists.ts";
import { getFileInfoType } from "./utils.ts";
import { getFileInfoType } from "./_util.ts";
/**
* Ensures that the hard link exists.

View File

@ -2,7 +2,7 @@
import * as path from "../path/mod.ts";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { exists, existsSync } from "./exists.ts";
import { getFileInfoType } from "./utils.ts";
import { getFileInfoType } from "./_util.ts";
/**
* Ensures that the link exists.

View File

@ -4,7 +4,6 @@ import {
globToRegExp,
isAbsolute,
isGlob,
isWindows,
joinGlobs,
normalize,
} from "../path/mod.ts";
@ -19,6 +18,8 @@ import { assert } from "../testing/asserts.ts";
const { cwd } = Deno;
type FileInfo = Deno.FileInfo;
const isWindows = Deno.build.os == "windows";
export interface ExpandGlobOptions extends GlobOptions {
root?: string;
exclude?: string[];

View File

@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { exists, existsSync } from "./exists.ts";
import { isSubdir } from "./utils.ts";
import { isSubdir } from "./_util.ts";
interface MoveOptions {
overwrite?: boolean;

View File

@ -7,18 +7,18 @@ import {
} from "../testing/asserts.ts";
import {
bodyReader,
chunkedBodyReader,
writeTrailers,
readTrailers,
parseHTTPVersion,
readRequest,
writeResponse,
} from "./io.ts";
} from "./_io.ts";
import { encode, decode } from "../encoding/utf8.ts";
import { BufReader, ReadLineResult } from "../io/bufio.ts";
import { chunkedBodyReader } from "./io.ts";
import { ServerRequest, Response } from "./server.ts";
import { StringReader } from "../io/readers.ts";
import { mockConn } from "./mock.ts";
import { mockConn } from "./_mock_conn.ts";
const { Buffer, test, readAll } = Deno;
test("bodyReader", async () => {

View File

@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { serve, ServerRequest } from "./server.ts";
import { delay } from "../util/async.ts";
import { delay } from "../async/delay.ts";
const addr = Deno.args[1] || "127.0.0.1:4501";
const server = serve(addr);

View File

@ -2,14 +2,14 @@
import { encode } from "../encoding/utf8.ts";
import { BufReader, BufWriter } from "../io/bufio.ts";
import { assert } from "../testing/asserts.ts";
import { deferred, Deferred, MuxAsyncIterator } from "../util/async.ts";
import { deferred, Deferred, MuxAsyncIterator } from "../async/mod.ts";
import {
bodyReader,
chunkedBodyReader,
emptyReader,
writeResponse,
readRequest,
} from "./io.ts";
} from "./_io.ts";
import Listener = Deno.Listener;
import Conn = Deno.Conn;
import Reader = Deno.Reader;

View File

@ -15,9 +15,9 @@ import {
} from "../testing/asserts.ts";
import { Response, ServerRequest, Server, serve } from "./server.ts";
import { BufReader, BufWriter } from "../io/bufio.ts";
import { delay } from "../util/async.ts";
import { delay } from "../async/delay.ts";
import { encode, decode } from "../encoding/utf8.ts";
import { mockConn } from "./mock.ts";
import { mockConn } from "./_mock_conn.ts";
const { Buffer, test } = Deno;

View File

@ -15,7 +15,7 @@ import {
readStringDelim,
readLines,
} from "./bufio.ts";
import * as iotest from "./iotest.ts";
import * as iotest from "./_iotest.ts";
import { charCode, copyBytes, stringsReader } from "./util.ts";
const encoder = new TextEncoder();

View File

@ -14,7 +14,7 @@ import { BufReader, BufWriter } from "../io/bufio.ts";
import { encoder } from "../encoding/utf8.ts";
import { assertStrictEq, assert } from "../testing/asserts.ts";
import { TextProtoReader } from "../textproto/mod.ts";
import { hasOwnProperty } from "../util/has_own_property.ts";
import { hasOwnProperty } from "../_util/has_own_property.ts";
/** FormFile object */
export interface FormFile {

View File

@ -36,7 +36,7 @@ const CHAR_FORWARD_SLASH = "/".charCodeAt(0);
const CHAR_BACKWARD_SLASH = "\\".charCodeAt(0);
const CHAR_COLON = ":".charCodeAt(0);
const isWindows = path.isWindows;
const isWindows = Deno.build.os == "windows";
const relativeResolveCache = Object.create(null);

View File

@ -48,7 +48,7 @@ export const CHAR_EQUAL = 61; /* = */
export const CHAR_0 = 48; /* 0 */
export const CHAR_9 = 57; /* 9 */
export const isWindows = build.os === "windows";
export const EOL = isWindows ? "\r\n" : "\n";
const isWindows = build.os == "windows";
export const SEP = isWindows ? "\\" : "/";
export const SEP_PATTERN = isWindows ? /[\\/]+/ : /\/+/;

View File

@ -4,7 +4,7 @@
const { test } = Deno;
import { assertEquals } from "../testing/asserts.ts";
import { GlobrexOptions, globrex } from "./globrex.ts";
import { GlobrexOptions, globrex } from "./_globrex.ts";
const isWin = Deno.build.os === "windows";
const t = { equal: assertEquals, is: assertEquals };

View File

@ -10,7 +10,7 @@ import {
CHAR_DOT,
CHAR_FORWARD_SLASH,
CHAR_BACKWARD_SLASH,
} from "./constants.ts";
} from "./_constants.ts";
export function assertPath(path: string): void {
if (typeof path !== "string") {

View File

@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { SEP } from "./constants.ts";
import { SEP } from "./separator.ts";
/** Determines the common path from a set of paths, using an optional separator,
* which defaults to the OS default separator.

View File

@ -1,5 +1,5 @@
import { SEP, SEP_PATTERN } from "./constants.ts";
import { globrex } from "./globrex.ts";
import { SEP, SEP_PATTERN } from "./separator.ts";
import { globrex } from "./_globrex.ts";
import { join, normalize } from "./mod.ts";
import { assert } from "../testing/asserts.ts";

View File

@ -4,7 +4,7 @@
import * as _win32 from "./win32.ts";
import * as _posix from "./posix.ts";
import { isWindows } from "./constants.ts";
const isWindows = Deno.build.os == "windows";
const path = isWindows ? _win32 : _posix;
@ -27,8 +27,7 @@ export const {
toNamespacedPath,
} = path;
export { common } from "./common.ts";
export { EOL, SEP, SEP_PATTERN, isWindows } from "./constants.ts";
export * from "./common.ts";
export { SEP, SEP_PATTERN } from "./separator.ts";
export * from "./interface.ts";
export * from "./glob.ts";
export * from "./globrex.ts";

View File

@ -3,14 +3,14 @@
const { cwd } = Deno;
import { FormatInputPathObject, ParsedPath } from "./interface.ts";
import { CHAR_DOT, CHAR_FORWARD_SLASH } from "./constants.ts";
import { CHAR_DOT, CHAR_FORWARD_SLASH } from "./_constants.ts";
import {
assertPath,
normalizeString,
isPosixPathSeparator,
_format,
} from "./utils.ts";
} from "./_util.ts";
export const sep = "/";
export const delimiter = ":";

4
path/separator.ts Normal file
View File

@ -0,0 +1,4 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
const isWindows = Deno.build.os == "windows";
export const SEP = isWindows ? "\\" : "/";
export const SEP_PATTERN = isWindows ? /[\\/]+/ : /\/+/;

View File

@ -8,7 +8,7 @@ import {
CHAR_BACKWARD_SLASH,
CHAR_COLON,
CHAR_QUESTION_MARK,
} from "./constants.ts";
} from "./_constants.ts";
import {
assertPath,
@ -16,7 +16,7 @@ import {
isWindowsDeviceRoot,
normalizeString,
_format,
} from "./utils.ts";
} from "./_util.ts";
import { assert } from "../testing/asserts.ts";
export const sep = "\\";

View File

@ -1,4 +1,4 @@
import { MuxAsyncIterator } from "../util/async.ts";
import { MuxAsyncIterator } from "../async/mux_async_iterator.ts";
export type Disposable = { dispose: () => void };

View File

@ -1,6 +1,6 @@
const { test } = Deno;
import { assertEquals, assertThrows } from "../testing/asserts.ts";
import { delay } from "../util/async.ts";
import { delay } from "../async/delay.ts";
import { signal, onSignal } from "./mod.ts";
test({

View File

@ -1,117 +0,0 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// TODO(ry) It'd be better to make Deferred a class that inherits from
// Promise, rather than an interface. This is possible in ES2016, however
// typescript produces broken code when targeting ES5 code.
// See https://github.com/Microsoft/TypeScript/issues/15202
// At the time of writing, the github issue is closed but the problem remains.
export interface Deferred<T> extends Promise<T> {
resolve: (value?: T | PromiseLike<T>) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
reject: (reason?: any) => void;
}
/** Creates a Promise with the `reject` and `resolve` functions
* placed as methods on the promise object itself. It allows you to do:
*
* const p = deferred<number>();
* // ...
* p.resolve(42);
*/
export function deferred<T>(): Deferred<T> {
let methods;
const promise = new Promise<T>((resolve, reject): void => {
methods = { resolve, reject };
});
return Object.assign(promise, methods) as Deferred<T>;
}
interface TaggedYieldedValue<T> {
iterator: AsyncIterableIterator<T>;
value: T;
}
/** The MuxAsyncIterator class multiplexes multiple async iterators into a
* single stream. It currently makes a few assumptions:
* - The iterators do not throw.
* - The final result (the value returned and not yielded from the iterator)
* does not matter; if there is any, it is discarded.
*/
export class MuxAsyncIterator<T> implements AsyncIterable<T> {
private iteratorCount = 0;
private yields: Array<TaggedYieldedValue<T>> = [];
private signal: Deferred<void> = deferred();
add(iterator: AsyncIterableIterator<T>): void {
++this.iteratorCount;
this.callIteratorNext(iterator);
}
private async callIteratorNext(
iterator: AsyncIterableIterator<T>
): Promise<void> {
const { value, done } = await iterator.next();
if (done) {
--this.iteratorCount;
} else {
this.yields.push({ iterator, value });
}
this.signal.resolve();
}
async *iterate(): AsyncIterableIterator<T> {
while (this.iteratorCount > 0) {
// Sleep until any of the wrapped iterators yields.
await this.signal;
// Note that while we're looping over `yields`, new items may be added.
for (let i = 0; i < this.yields.length; i++) {
const { iterator, value } = this.yields[i];
yield value;
this.callIteratorNext(iterator);
}
// Clear the `yields` list and reset the `signal` promise.
this.yields.length = 0;
this.signal = deferred();
}
}
[Symbol.asyncIterator](): AsyncIterableIterator<T> {
return this.iterate();
}
}
/** Collects all Uint8Arrays from an AsyncIterable and retuns a single
* Uint8Array with the concatenated contents of all the collected arrays.
*/
export async function collectUint8Arrays(
it: AsyncIterable<Uint8Array>
): Promise<Uint8Array> {
const chunks = [];
let length = 0;
for await (const chunk of it) {
chunks.push(chunk);
length += chunk.length;
}
if (chunks.length === 1) {
// No need to copy.
return chunks[0];
}
const collected = new Uint8Array(length);
let offset = 0;
for (const chunk of chunks) {
collected.set(chunk, offset);
offset += chunk.length;
}
return collected;
}
// Delays the given milliseconds and resolves.
export function delay(ms: number): Promise<void> {
return new Promise((res): number =>
setTimeout((): void => {
res();
}, ms)
);
}

View File

@ -1,76 +0,0 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
const { test } = Deno;
import { assert, assertEquals, assertStrictEq } from "../testing/asserts.ts";
import { collectUint8Arrays, deferred, MuxAsyncIterator } from "./async.ts";
test("asyncDeferred", function (): Promise<void> {
const d = deferred<number>();
d.resolve(12);
return Promise.resolve();
});
// eslint-disable-next-line require-await
async function* gen123(): AsyncIterableIterator<number> {
yield 1;
yield 2;
yield 3;
}
// eslint-disable-next-line require-await
async function* gen456(): AsyncIterableIterator<number> {
yield 4;
yield 5;
yield 6;
}
test("asyncMuxAsyncIterator", async function (): Promise<void> {
const mux = new MuxAsyncIterator<number>();
mux.add(gen123());
mux.add(gen456());
const results = new Set();
for await (const value of mux) {
results.add(value);
}
assertEquals(results.size, 6);
});
test("collectUint8Arrays0", async function (): Promise<void> {
async function* gen(): AsyncIterableIterator<Uint8Array> {}
const result = await collectUint8Arrays(gen());
assert(result instanceof Uint8Array);
assertEquals(result.length, 0);
});
test("collectUint8Arrays0", async function (): Promise<void> {
async function* gen(): AsyncIterableIterator<Uint8Array> {}
const result = await collectUint8Arrays(gen());
assert(result instanceof Uint8Array);
assertStrictEq(result.length, 0);
});
test("collectUint8Arrays1", async function (): Promise<void> {
const buf = new Uint8Array([1, 2, 3]);
// eslint-disable-next-line require-await
async function* gen(): AsyncIterableIterator<Uint8Array> {
yield buf;
}
const result = await collectUint8Arrays(gen());
assertStrictEq(result, buf);
assertStrictEq(result.length, 3);
});
test("collectUint8Arrays4", async function (): Promise<void> {
// eslint-disable-next-line require-await
async function* gen(): AsyncIterableIterator<Uint8Array> {
yield new Uint8Array([1, 2, 3]);
yield new Uint8Array([]);
yield new Uint8Array([4, 5]);
yield new Uint8Array([6]);
}
const result = await collectUint8Arrays(gen());
assert(result instanceof Uint8Array);
assertStrictEq(result.length, 6);
for (let i = 0; i < 6; i++) {
assertStrictEq(result[i], i + 1);
}
});

View File

@ -6,7 +6,7 @@ import {
stringToBytes,
uuidToBytes,
} from "./_common.ts";
import { Sha1 } from "../util/sha1.ts";
import { Sha1 } from "../hash/sha1.ts";
import { isString } from "../node/util.ts";
import { assert } from "../testing/asserts.ts";

View File

@ -3,57 +3,59 @@ import {
isWebSocketCloseEvent,
isWebSocketPingEvent,
isWebSocketPongEvent,
} from "../ws/mod.ts";
} from "./mod.ts";
import { encode } from "../encoding/utf8.ts";
import { BufReader } from "../io/bufio.ts";
import { TextProtoReader } from "../textproto/mod.ts";
import { blue, green, red, yellow } from "../fmt/colors.ts";
const endpoint = Deno.args[0] || "ws://127.0.0.1:8080";
/** simple websocket cli */
try {
const sock = await connectWebSocket(endpoint);
console.log(green("ws connected! (type 'close' to quit)"));
if (import.meta.main) {
const endpoint = Deno.args[0] || "ws://127.0.0.1:8080";
/** simple websocket cli */
try {
const sock = await connectWebSocket(endpoint);
console.log(green("ws connected! (type 'close' to quit)"));
const messages = async (): Promise<void> => {
for await (const msg of sock) {
if (typeof msg === "string") {
console.log(yellow(`< ${msg}`));
} else if (isWebSocketPingEvent(msg)) {
console.log(blue("< ping"));
} else if (isWebSocketPongEvent(msg)) {
console.log(blue("< pong"));
} else if (isWebSocketCloseEvent(msg)) {
console.log(red(`closed: code=${msg.code}, reason=${msg.reason}`));
const messages = async (): Promise<void> => {
for await (const msg of sock) {
if (typeof msg === "string") {
console.log(yellow(`< ${msg}`));
} else if (isWebSocketPingEvent(msg)) {
console.log(blue("< ping"));
} else if (isWebSocketPongEvent(msg)) {
console.log(blue("< pong"));
} else if (isWebSocketCloseEvent(msg)) {
console.log(red(`closed: code=${msg.code}, reason=${msg.reason}`));
}
}
};
const cli = async (): Promise<void> => {
const tpr = new TextProtoReader(new BufReader(Deno.stdin));
while (true) {
await Deno.stdout.write(encode("> "));
const line = await tpr.readLine();
if (line === null) {
break;
}
if (line === "close") {
break;
} else if (line === "ping") {
await sock.ping();
} else {
await sock.send(line);
}
}
};
await Promise.race([messages(), cli()]).catch(console.error);
if (!sock.isClosed) {
await sock.close(1000).catch(console.error);
}
};
const cli = async (): Promise<void> => {
const tpr = new TextProtoReader(new BufReader(Deno.stdin));
while (true) {
await Deno.stdout.write(encode("> "));
const line = await tpr.readLine();
if (line === null) {
break;
}
if (line === "close") {
break;
} else if (line === "ping") {
await sock.ping();
} else {
await sock.send(line);
}
}
};
await Promise.race([messages(), cli()]).catch(console.error);
if (!sock.isClosed) {
await sock.close(1000).catch(console.error);
} catch (err) {
console.error(red(`Could not connect to WebSocket: '${err}'`));
}
} catch (err) {
console.error(red(`Could not connect to WebSocket: '${err}'`));
}
Deno.exit(0);
Deno.exit(0);
}

View File

@ -6,50 +6,52 @@ import {
isWebSocketPingEvent,
} from "./mod.ts";
/** websocket echo server */
const port = Deno.args[0] || "8080";
console.log(`websocket server is running on :${port}`);
for await (const req of serve(`:${port}`)) {
const { conn, r: bufReader, w: bufWriter, headers } = req;
try {
const sock = await acceptWebSocket({
conn,
bufReader,
bufWriter,
headers,
});
console.log("socket connected!");
if (import.meta.main) {
/** websocket echo server */
const port = Deno.args[0] || "8080";
console.log(`websocket server is running on :${port}`);
for await (const req of serve(`:${port}`)) {
const { conn, r: bufReader, w: bufWriter, headers } = req;
try {
for await (const ev of sock) {
if (typeof ev === "string") {
// text message
console.log("ws:Text", ev);
await sock.send(ev);
} else if (ev instanceof Uint8Array) {
// binary message
console.log("ws:Binary", ev);
} else if (isWebSocketPingEvent(ev)) {
const [, body] = ev;
// ping
console.log("ws:Ping", body);
} else if (isWebSocketCloseEvent(ev)) {
// close
const { code, reason } = ev;
console.log("ws:Close", code, reason);
const sock = await acceptWebSocket({
conn,
bufReader,
bufWriter,
headers,
});
console.log("socket connected!");
try {
for await (const ev of sock) {
if (typeof ev === "string") {
// text message
console.log("ws:Text", ev);
await sock.send(ev);
} else if (ev instanceof Uint8Array) {
// binary message
console.log("ws:Binary", ev);
} else if (isWebSocketPingEvent(ev)) {
const [, body] = ev;
// ping
console.log("ws:Ping", body);
} else if (isWebSocketCloseEvent(ev)) {
// close
const { code, reason } = ev;
console.log("ws:Close", code, reason);
}
}
} catch (err) {
console.error(`failed to receive frame: ${err}`);
if (!sock.isClosed) {
await sock.close(1000).catch(console.error);
}
}
} catch (err) {
console.error(`failed to receive frame: ${err}`);
if (!sock.isClosed) {
await sock.close(1000).catch(console.error);
}
console.error(`failed to accept websocket: ${err}`);
await req.respond({ status: 400 });
}
} catch (err) {
console.error(`failed to accept websocket: ${err}`);
await req.respond({ status: 400 });
}
}

View File

@ -1,13 +1,13 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { decode, encode } from "../encoding/utf8.ts";
import { hasOwnProperty } from "../util/has_own_property.ts";
import { hasOwnProperty } from "../_util/has_own_property.ts";
import { BufReader, BufWriter } from "../io/bufio.ts";
import { readLong, readShort, sliceLongToBytes } from "../io/ioutil.ts";
import { Sha1 } from "../util/sha1.ts";
import { writeResponse } from "../http/io.ts";
import { Sha1 } from "../hash/sha1.ts";
import { writeResponse } from "../http/_io.ts";
import { TextProtoReader } from "../textproto/mod.ts";
import { Deferred, deferred } from "../util/async.ts";
import { Deferred, deferred } from "../async/deferred.ts";
import { assert } from "../testing/asserts.ts";
import { concat } from "../bytes/mod.ts";
import Conn = Deno.Conn;

View File

@ -21,7 +21,7 @@ import Writer = Deno.Writer;
import Reader = Deno.Reader;
import Conn = Deno.Conn;
import Buffer = Deno.Buffer;
import { delay } from "../util/async.ts";
import { delay } from "../async/delay.ts";
test("[ws] read unmasked text frame", async () => {
// unmasked single text frame with payload "Hello"