mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
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:
parent
45aafa4b27
commit
1eecc5c7d0
33
README.md
33
README.md
@ -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
26
async/deferred.ts
Normal 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
8
async/deferred_test.ts
Normal 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
9
async/delay.ts
Normal 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
4
async/mod.ts
Normal 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";
|
58
async/mux_async_iterator.ts
Normal file
58
async/mux_async_iterator.ts
Normal 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();
|
||||
}
|
||||
}
|
28
async/mux_async_iterator_test.ts
Normal file
28
async/mux_async_iterator_test.ts
Normal 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);
|
||||
});
|
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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";
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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));
|
||||
}
|
@ -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
|
||||
|
@ -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`.
|
||||
*/
|
||||
|
@ -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";
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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[];
|
||||
|
@ -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;
|
||||
|
@ -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 () => {
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 ? /[\\/]+/ : /\/+/;
|
@ -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 };
|
@ -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") {
|
@ -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.
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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
4
path/separator.ts
Normal 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 ? /[\\/]+/ : /\/+/;
|
@ -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 = "\\";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { MuxAsyncIterator } from "../util/async.ts";
|
||||
import { MuxAsyncIterator } from "../async/mux_async_iterator.ts";
|
||||
|
||||
export type Disposable = { dispose: () => void };
|
||||
|
||||
|
@ -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({
|
||||
|
117
util/async.ts
117
util/async.ts
@ -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)
|
||||
);
|
||||
}
|
@ -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);
|
||||
}
|
||||
});
|
@ -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";
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 });
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user