From fca0428fc42a4420ffb4751d7033dd3d527df937 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 12 Oct 2021 14:36:59 +0200 Subject: [PATCH 1/3] feat(node): v16.11 --- types/node/crypto.d.ts | 2 +- types/node/diagnostics_channel.d.ts | 6 ++++++ types/node/fs.d.ts | 12 +++++------- types/node/http.d.ts | 4 ++-- types/node/test/util.ts | 4 ++++ types/node/util.d.ts | 10 ++++++++++ 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/types/node/crypto.d.ts b/types/node/crypto.d.ts index f91f1c4c845d44..a896ae713da799 100644 --- a/types/node/crypto.d.ts +++ b/types/node/crypto.d.ts @@ -1175,7 +1175,7 @@ declare module 'crypto' { * generateKeySync * } = await import('crypto'); * - * const key = generateKeySync('hmac', 64); + * const key = generateKeySync('hmac', { length: 64 }); * console.log(key.export().toString('hex')); // e89..........41e * ``` * @since v15.0.0 diff --git a/types/node/diagnostics_channel.d.ts b/types/node/diagnostics_channel.d.ts index a59478e955f348..d6747dad5fe178 100644 --- a/types/node/diagnostics_channel.d.ts +++ b/types/node/diagnostics_channel.d.ts @@ -37,6 +37,7 @@ declare module 'diagnostics_channel' { * // There are subscribers, prepare and publish message * } * ``` + * @since v15.1.0, v14.17.0 * @param name The channel name * @return If there are active subscribers */ @@ -51,6 +52,7 @@ declare module 'diagnostics_channel' { * * const channel = diagnostics_channel.channel('my-channel'); * ``` + * @since v15.1.0, v14.17.0 * @param name The channel name * @return The named channel object */ @@ -63,6 +65,7 @@ declare module 'diagnostics_channel' { * lookups at publish time, enabling very fast publish speeds and allowing * for heavy use while incurring very minimal cost. Channels are created with {@link channel}, constructing a channel directly * with `new Channel(name)` is not supported. + * @since v15.1.0, v14.17.0 */ class Channel { readonly name: string; @@ -82,6 +85,7 @@ declare module 'diagnostics_channel' { * // There are subscribers, prepare and publish message * } * ``` + * @since v15.1.0, v14.17.0 */ readonly hasSubscribers: boolean; private constructor(name: string); @@ -99,6 +103,7 @@ declare module 'diagnostics_channel' { * // Received data * }); * ``` + * @since v15.1.0, v14.17.0 * @param onMessage The handler to receive channel messages */ subscribe(onMessage: ChannelListener): void; @@ -118,6 +123,7 @@ declare module 'diagnostics_channel' { * * channel.unsubscribe(onMessage); * ``` + * @since v15.1.0, v14.17.0 * @param onMessage The previous subscribed handler to remove */ unsubscribe(onMessage: ChannelListener): void; diff --git a/types/node/fs.d.ts b/types/node/fs.d.ts index 4339a852a69369..2fa5b2fa1416f3 100644 --- a/types/node/fs.d.ts +++ b/types/node/fs.d.ts @@ -306,7 +306,7 @@ declare module 'fs' { /** * The path to the file the stream is reading from as specified in the first * argument to `fs.createReadStream()`. If `path` is passed as a string, then`readStream.path` will be a string. If `path` is passed as a `Buffer`, then`readStream.path` will be a - * `Buffer`. + * `Buffer`. If `fd` is specified, then`readStream.path` will be `undefined`. * @since v0.1.93 */ path: string | Buffer; @@ -2762,7 +2762,7 @@ declare module 'fs' { * the numeric values in these objects are specified as `BigInt`s. * * To be notified when the file was modified, not just accessed, it is necessary - * to compare `curr.mtime` and `prev.mtime`. + * to compare `curr.mtimeMs` and `prev.mtimeMs`. * * When an `fs.watchFile` operation results in an `ENOENT` error, it * will invoke the listener once, with all the fields zeroed (or, for dates, the @@ -3360,7 +3360,7 @@ declare module 'fs' { end?: number | undefined; } /** - * Unlike the 16 kb default `highWaterMark` for a readable stream, the stream + * Unlike the 16 kb default `highWaterMark` for a `stream.Readable`, the stream * returned by this method has a default `highWaterMark` of 64 kb. * * `options` can include `start` and `end` values to read a range of bytes from @@ -3380,7 +3380,7 @@ declare module 'fs' { * closing naturally. * * By default, the stream will emit a `'close'` event after it has been - * destroyed, like most `Readable` streams. Set the `emitClose` option to`false` to change this behavior. + * destroyed. Set the `emitClose` option to `false` to change this behavior. * * By providing the `fs` option, it is possible to override the corresponding `fs`implementations for `open`, `read`, and `close`. When providing the `fs` option, * an override for `read` is required. If no `fd` is provided, an override for`open` is also required. If `autoClose` is `true`, an override for `close` is @@ -3422,7 +3422,6 @@ declare module 'fs' { * * If `options` is a string, then it specifies the encoding. * @since v0.1.31 - * @return See `Readable Stream`. */ export function createReadStream(path: PathLike, options?: BufferEncoding | ReadStreamOptions): ReadStream; /** @@ -3438,7 +3437,7 @@ declare module 'fs' { * file descriptor leak. * * By default, the stream will emit a `'close'` event after it has been - * destroyed, like most `Writable` streams. Set the `emitClose` option to`false` to change this behavior. + * destroyed. Set the `emitClose` option to `false` to change this behavior. * * By providing the `fs` option it is possible to override the corresponding `fs`implementations for `open`, `write`, `writev` and `close`. Overriding `write()`without `writev()` can reduce * performance as some optimizations (`_writev()`) @@ -3451,7 +3450,6 @@ declare module 'fs' { * * If `options` is a string, then it specifies the encoding. * @since v0.1.31 - * @return See `Writable Stream`. */ export function createWriteStream(path: PathLike, options?: BufferEncoding | StreamOptions): WriteStream; /** diff --git a/types/node/http.d.ts b/types/node/http.d.ts index 68a63ba13dc246..9081954bde481d 100644 --- a/types/node/http.d.ts +++ b/types/node/http.d.ts @@ -187,9 +187,9 @@ declare module 'http' { * The maximum number of requests socket can handle * before closing keep alive connection. * - * A value of `null` will disable the limit. + * A value of `0` will disable the limit. * - * When limit is reach it will set `Connection` header value to `closed`, + * When the limit is reached it will set the `Connection` header value to `close`, * but will not actually close the connection, subsequent requests sent * after the limit is reached will get `503 Service Unavailable` as a response. * @since v16.10.0 diff --git a/types/node/test/util.ts b/types/node/test/util.ts index 3ef109a6a55cfd..281f999071fda8 100644 --- a/types/node/test/util.ts +++ b/types/node/test/util.ts @@ -187,3 +187,7 @@ const errorMap: Map = util.getSystemErrorMap(); { const foo: string = util.toUSVString('foo'); } + +{ + util.stripVTControlCharacters('\u001B[4mvalue\u001B[0m'); // $ExpectType string +} diff --git a/types/node/util.d.ts b/types/node/util.d.ts index b866e89d5aaf7a..480d6aee3a020f 100644 --- a/types/node/util.d.ts +++ b/types/node/util.d.ts @@ -789,6 +789,16 @@ declare module 'util' { * @since v9.0.0 */ export function isDeepStrictEqual(val1: unknown, val2: unknown): boolean; + /** + * Returns `str` with any ANSI escape codes removed. + * + * ```js + * console.log(util.stripVTControlCharacters('\u001B[4mvalue\u001B[0m')); + * // Prints "value" + * ``` + * @since v16.11.0 + */ + export function stripVTControlCharacters(str: string): string; /** * Takes an `async` function (or a function that returns a `Promise`) and returns a * function following the error-first callback style, i.e. taking From cf46e168d20895c34c311424ef43fcf244fe518a Mon Sep 17 00:00:00 2001 From: Dmitry Semigradsky Date: Mon, 11 Oct 2021 09:36:14 +0300 Subject: [PATCH 2/3] `util` module fixes. node 16.x - Add `debug` alias. - Add `getSystemErrorName`. - Add `stripVTControlCharacters`. node 14.x - Add `debug` alias. Fix `debuglog` types. - Add `getSystemErrorName`. --- types/node/index.d.ts | 2 +- types/node/test/util.ts | 8 +++++++- types/node/util.d.ts | 21 +++++++++++++++++++++ types/node/v14/test/util.ts | 16 +++++++++++++++- types/node/v14/util.d.ts | 8 +++++++- 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/types/node/index.d.ts b/types/node/index.d.ts index 8d7e97e6bf9e3d..4ff0a920959a70 100644 --- a/types/node/index.d.ts +++ b/types/node/index.d.ts @@ -1,4 +1,4 @@ -// Type definitions for non-npm package Node.js 16.10 +// Type definitions for non-npm package Node.js 16.11 // Project: https://nodejs.org/ // Definitions by: Microsoft TypeScript // DefinitelyTyped diff --git a/types/node/test/util.ts b/types/node/test/util.ts index 281f999071fda8..1c12c91d561316 100644 --- a/types/node/test/util.ts +++ b/types/node/test/util.ts @@ -1,6 +1,6 @@ import * as util from 'node:util'; import assert = require('node:assert'); -import { readFile } from 'node:fs'; +import { access, readFile } from 'node:fs'; // Old and new util.inspect APIs util.inspect(["This is nice"], false, 5); @@ -182,12 +182,18 @@ const errorMap: Map = util.getSystemErrorMap(); const logger: util.DebugLogger = util.debuglog('section'); logger.enabled; // $ExpectType boolean util.debuglog('section', (fn: util.DebugLoggerFunction) => { }); + util.debug('section', (fn: util.DebugLoggerFunction) => { }); } { const foo: string = util.toUSVString('foo'); } +access('file/that/does/not/exist', (err) => { + const name = util.getSystemErrorName(err!.errno!); + console.error(name); +}); + { util.stripVTControlCharacters('\u001B[4mvalue\u001B[0m'); // $ExpectType string } diff --git a/types/node/util.d.ts b/types/node/util.d.ts index 480d6aee3a020f..d0f4c176476c8b 100644 --- a/types/node/util.d.ts +++ b/types/node/util.d.ts @@ -113,6 +113,20 @@ declare module 'util' { * @since v10.0.0 */ export function formatWithOptions(inspectOptions: InspectOptions, format?: any, ...param: any[]): string; + /** + * Returns the string name for a numeric error code that comes from a Node.js API. + * The mapping between error codes and error names is platform-dependent. + * See `Common System Errors` for the names of common errors. + * + * ```js + * fs.access('file/that/does/not/exist', (err) => { + * const name = util.getSystemErrorName(err.errno); + * console.error(name); // ENOENT + * }); + * ``` + * @since v9.7.0 + */ + export function getSystemErrorName(err: number): string; /** * Returns a Map of all system error codes available from the Node.js API. * The mapping between error codes and error names is platform-dependent. @@ -314,6 +328,9 @@ declare module 'util' { * Allows changing inspect settings from the repl. */ let replDefaults: InspectOptions; + /** + * That can be used to declare custom inspect functions. + */ const custom: unique symbol; } /** @@ -520,6 +537,7 @@ declare module 'util' { * @return The logging function */ export function debuglog(section: string, callback?: (fn: DebugLoggerFunction) => void): DebugLogger; + export const debug: typeof debuglog; /** * Returns `true` if the given `object` is a `Boolean`. Otherwise, returns `false`. * @@ -971,6 +989,9 @@ declare module 'util' { ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise; export function promisify(fn: Function): Function; export namespace promisify { + /** + * That can be used to declare custom promisified variants of functions. + */ const custom: unique symbol; } /** diff --git a/types/node/v14/test/util.ts b/types/node/v14/test/util.ts index e0614448b85a54..64729a6ca51773 100644 --- a/types/node/v14/test/util.ts +++ b/types/node/v14/test/util.ts @@ -1,6 +1,6 @@ import * as util from 'util'; import assert = require('assert'); -import { readFile } from 'fs'; +import { access, readFile } from 'fs'; { // Old and new util.inspect APIs @@ -323,3 +323,17 @@ function testUtilTypes( object; // $ExpectType WeakSet } } + +{ + const logger: util.DebugLogger = util.debuglog('section'); + logger.enabled; // $ExpectType boolean + util.debuglog('section', (fn: util.DebugLoggerFunction) => { }); + util.debug('section', (fn: util.DebugLoggerFunction) => { }); +} + +{ + access('file/that/does/not/exist', (err) => { + const name = util.getSystemErrorName(err!.errno!); + console.error(name); + }); +} diff --git a/types/node/v14/util.d.ts b/types/node/v14/util.d.ts index 85ae358c4040bb..c6d4224b3cd417 100644 --- a/types/node/v14/util.d.ts +++ b/types/node/v14/util.d.ts @@ -7,6 +7,7 @@ declare module 'util' { } function format(format?: any, ...param: any[]): string; function formatWithOptions(inspectOptions: InspectOptions, format?: any, ...param: any[]): string; + function getSystemErrorName(err: number): string; /** @deprecated since v0.11.3 - use a third party module instead. */ function log(string: string): void; function inspect(object: any, showHidden?: boolean, depth?: number | null, color?: boolean): string; @@ -32,7 +33,12 @@ declare module 'util' { /** @deprecated since v4.0.0 - use `util.types.isNativeError()` instead. */ function isError(object: any): object is Error; function inherits(constructor: any, superConstructor: any): void; - function debuglog(key: string): (msg: string, ...param: any[]) => void; + type DebugLoggerFunction = (msg: string, ...param: any[]) => void; + interface DebugLogger extends DebugLoggerFunction { + enabled: boolean; + } + function debuglog(key: string, callback?: (fn: DebugLoggerFunction) => void): DebugLogger; + const debug: typeof debuglog; /** @deprecated since v4.0.0 - use `typeof value === 'boolean'` instead. */ function isBoolean(object: any): object is boolean; /** @deprecated since v4.0.0 - use `Buffer.isBuffer()` instead. */ From 9364324ca7b0d1e94610ba8ac17735a7348d8756 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 12 Oct 2021 17:42:51 +0200 Subject: [PATCH 3/3] add stream utilities to FileHandle --- types/node/fs/promises.d.ts | 87 +++++++++++++++++++++++++++++++++++++ types/node/test/fs.ts | 18 ++++++++ 2 files changed, 105 insertions(+) diff --git a/types/node/fs/promises.d.ts b/types/node/fs/promises.d.ts index e4e04a84045c74..994157a3018e00 100644 --- a/types/node/fs/promises.d.ts +++ b/types/node/fs/promises.d.ts @@ -31,6 +31,8 @@ declare module 'fs/promises' { WatchOptions, WatchEventType, CopyOptions, + ReadStream, + WriteStream, } from 'node:fs'; interface FileChangeInfo { eventType: WatchEventType; @@ -59,6 +61,20 @@ declare module 'fs/promises' { length?: number | null; position?: number | null; } + interface CreateReadStreamOptions { + encoding?: BufferEncoding | null | undefined; + autoClose?: boolean | undefined; + emitClose?: boolean | undefined; + start?: number | undefined; + end?: number | undefined; + highWaterMark?: number | undefined; + } + interface CreateWriteStreamOptions { + encoding?: BufferEncoding | null | undefined; + autoClose?: boolean | undefined; + emitClose?: boolean | undefined; + start?: number | undefined; + } // TODO: Add `EventEmitter` close interface FileHandle { /** @@ -90,6 +106,77 @@ declare module 'fs/promises' { * @return Fulfills with `undefined` upon success. */ chmod(mode: Mode): Promise; + /** + * Unlike the 16 kb default `highWaterMark` for a `stream.Readable`, the stream + * returned by this method has a default `highWaterMark` of 64 kb. + * + * `options` can include `start` and `end` values to read a range of bytes from + * the file instead of the entire file. Both `start` and `end` are inclusive and + * start counting at 0, allowed values are in the + * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. If `start` is + * omitted or `undefined`, `filehandle.createReadStream()` reads sequentially from + * the current file position. The `encoding` can be any one of those accepted by `Buffer`. + * + * If the `FileHandle` points to a character device that only supports blocking + * reads (such as keyboard or sound card), read operations do not finish until data + * is available. This can prevent the process from exiting and the stream from + * closing naturally. + * + * By default, the stream will emit a `'close'` event after it has been + * destroyed. Set the `emitClose` option to `false` to change this behavior. + * + * ```js + * import { open } from 'fs/promises'; + * + * const fd = await open('/dev/input/event0'); + * // Create a stream from some character device. + * const stream = fd.createReadStream(); + * setTimeout(() => { + * stream.close(); // This may not close the stream. + * // Artificially marking end-of-stream, as if the underlying resource had + * // indicated end-of-file by itself, allows the stream to close. + * // This does not cancel pending read operations, and if there is such an + * // operation, the process may still not be able to exit successfully + * // until it finishes. + * stream.push(null); + * stream.read(0); + * }, 100); + * ``` + * + * If `autoClose` is false, then the file descriptor won't be closed, even if + * there's an error. It is the application's responsibility to close it and make + * sure there's no file descriptor leak. If `autoClose` is set to true (default + * behavior), on `'error'` or `'end'` the file descriptor will be closed + * automatically. + * + * An example to read the last 10 bytes of a file which is 100 bytes long: + * + * ```js + * import { open } from 'fs/promises'; + * + * const fd = await open('sample.txt'); + * fd.createReadStream({ start: 90, end: 99 }); + * ``` + * @since v16.11.0 + */ + createReadStream(options?: CreateReadStreamOptions): ReadStream; + /** + * `options` may also include a `start` option to allow writing data at some + * position past the beginning of the file, allowed values are in the + * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. Modifying a file rather than replacing + * it may require the `flags` `open` option to be set to `r+` rather than the + * default `r`. The `encoding` can be any one of those accepted by `Buffer`. + * + * If `autoClose` is set to true (default behavior) on `'error'` or `'finish'`the file descriptor will be closed automatically. If `autoClose` is false, + * then the file descriptor won't be closed, even if there's an error. + * It is the application's responsibility to close it and make sure there's no + * file descriptor leak. + * + * By default, the stream will emit a `'close'` event after it has been + * destroyed. Set the `emitClose` option to `false` to change this behavior. + * @since v16.11.0 + */ + createWriteStream(options?: CreateWriteStreamOptions): WriteStream; /** * Forces all currently queued I/O operations associated with the file to the * operating system's synchronized I/O completion state. Refer to the POSIX [`fdatasync(2)`](http://man7.org/linux/man-pages/man2/fdatasync.2.html) documentation for details. diff --git a/types/node/test/fs.ts b/types/node/test/fs.ts index 162147220c34f1..258c658f7ac605 100644 --- a/types/node/test/fs.ts +++ b/types/node/test/fs.ts @@ -630,3 +630,21 @@ const anyStats: fs.Stats | fs.BigIntStats = fs.statSync('.', { bigint: Math.rand cpAsync('src', 'dest'); // $ExpectType Promise cpAsync('src', 'dest', opts); // $ExpectType Promise } + +{ + fs.promises.open('/dev/input/event0', 'r').then((fd) => { + // Create a stream from some character device. + const stream = fd.createReadStream(); // $ExpectType ReadStream + stream.close(); + stream.push(null); + stream.read(0); + }); +} + +{ + fs.promises.open('/tmp/tmp.txt', 'w').then((fd) => { + // Create a stream from some character device. + const stream = fd.createWriteStream(); // $ExpectType WriteStream + stream.close(); + }); +}