From 3e22518f38988ed3455f659f4cadbe79d38e2968 Mon Sep 17 00:00:00 2001 From: DIHE-GitHub <52400738+DIHE-GitHub@users.noreply.github.com> Date: Tue, 9 Jan 2024 16:06:42 +0800 Subject: [PATCH 01/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#67450=20?= =?UTF-8?q?=E2=9C=A8=20feat(json-diff):=20Adapt=20to=20v1.0.2,=20add=20fun?= =?UTF-8?q?ctions=20colorize,=20colorizeToCallback=20type=20definition=20b?= =?UTF-8?q?y=20@DIHE-GitHub?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat: 添加导出函数 colorize, colorizeToCallback 详情参见v1.0.2 https://github.com/andreyvit/json-diff#change-log * 🐞 fix: 修复lint错误 * 🌈 style(json-diff): dprint fmt index.d.ts lib/colorize.d.ts * 🧪 test(json-diff): 添加测试 colorize和colorizeToCallback --------- Co-authored-by: limao --- types/json-diff/index.d.ts | 2 ++ types/json-diff/json-diff-tests.ts | 24 +++++++++++++++++++++++- types/json-diff/lib/colorize.d.ts | 18 ++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 types/json-diff/lib/colorize.d.ts diff --git a/types/json-diff/index.d.ts b/types/json-diff/index.d.ts index 8249da36b0a5e9..944cf367eff0fb 100644 --- a/types/json-diff/index.d.ts +++ b/types/json-diff/index.d.ts @@ -18,3 +18,5 @@ export interface DiffStringOptions extends DiffOptions { export function diff(obj1: unknown, obj2: unknown, options?: DiffOptions): any; export function diffString(obj1: unknown, obj2: unknown, options?: DiffStringOptions): string; + +export { colorize, colorizeToCallback } from "./lib/colorize"; diff --git a/types/json-diff/json-diff-tests.ts b/types/json-diff/json-diff-tests.ts index 2ff3684270a670..63ea800d4fb425 100644 --- a/types/json-diff/json-diff-tests.ts +++ b/types/json-diff/json-diff-tests.ts @@ -1,4 +1,4 @@ -import { diff, DiffOptions, diffString } from "json-diff"; +import { colorize, colorizeToCallback, diff, DiffOptions, diffString } from "json-diff"; const options: DiffOptions = { verbose: true, @@ -24,3 +24,25 @@ diffString({}, { Hello: "World" }, { ...options, color: true, }); + +colorize(diff({}, { Hello: "World" })); + +colorizeToCallback(diff({}, { Hello: "World" }), {}, (color, line) => { + switch (color) { + case " ": + // do something + + break; + case "-": + // do something + + break; + case "+": + // do something + + break; + + default: + break; + } +}); diff --git a/types/json-diff/lib/colorize.d.ts b/types/json-diff/lib/colorize.d.ts new file mode 100644 index 00000000000000..35788092f5de2f --- /dev/null +++ b/types/json-diff/lib/colorize.d.ts @@ -0,0 +1,18 @@ +export type DiffObject = object | string; + +export interface ColorizeOptions { + theme?: Theme; + color?: boolean; +} + +export type Theme = Record; +export type ThemeType = " " | "+" | "-"; +export type ThemeFunction = (str: string) => string; + +export interface OutputCallback { + (color: ThemeType, line: string): void; +} + +export function colorizeToCallback(diff: DiffObject, options: ColorizeOptions, output: OutputCallback): void; +export function colorize(diff: DiffObject, options?: ColorizeOptions): string; +export function colorizeToArray(diff: DiffObject, options: ColorizeOptions): string[]; From 266407a8b0e3b9ed7117cd7c9286aca0321d9447 Mon Sep 17 00:00:00 2001 From: Isaac Wong Date: Tue, 9 Jan 2024 18:08:15 +0800 Subject: [PATCH 02/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68108=20koa:?= =?UTF-8?q?=20support=20async=20local=20storage=20attribute=20by=20@fatwon?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat[koa]: support asyncLocalStorage * fix: simply use Application.Context * chore: update version number --- types/koa/index.d.ts | 9 +++++++++ types/koa/package.json | 2 +- types/koa/test/constructor.ts | 1 + types/koa/test/index.ts | 2 ++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/types/koa/index.d.ts b/types/koa/index.d.ts index 9b2ab04a0d09c1..28fc361148fa31 100644 --- a/types/koa/index.d.ts +++ b/types/koa/index.d.ts @@ -10,6 +10,7 @@ =============================================== */ /// import * as accepts from "accepts"; +import { AsyncLocalStorage } from "async_hooks"; import * as Cookies from "cookies"; import { EventEmitter } from "events"; import { IncomingHttpHeaders, IncomingMessage, OutgoingHttpHeaders, Server, ServerResponse } from "http"; @@ -443,6 +444,7 @@ declare class Application< response: Application.BaseResponse; silent: boolean; keys: Keygrip | string[]; + ctxStorage: AsyncLocalStorage | undefined; /** * @param {object} [options] Application options @@ -452,6 +454,7 @@ declare class Application< * @param {number} [options.subdomainOffset] Subdomain offset * @param {string} [options.proxyIpHeader] Proxy IP header, defaults to X-Forwarded-For * @param {number} [options.maxIpsCount] Max IPs read from proxy IP header, default to 0 (means infinity) + * @param {boolean} [options.asyncLocalStorage] Enable AsyncLocalStorage */ constructor(options?: { env?: string | undefined; @@ -460,6 +463,7 @@ declare class Application< subdomainOffset?: number | undefined; proxyIpHeader?: string | undefined; maxIpsCount?: number | undefined; + asyncLocalStorage?: boolean | undefined; }); /** @@ -520,6 +524,11 @@ declare class Application< * @api private */ onerror(err: Error): void; + + /** + * return currnect contenxt from async local storage + */ + readonly currentContext: Application.Context | undefined; } declare namespace Application { diff --git a/types/koa/package.json b/types/koa/package.json index 55272d135af08f..81a7117bb72013 100644 --- a/types/koa/package.json +++ b/types/koa/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@types/koa", - "version": "2.13.9999", + "version": "2.14.9999", "projects": [ "http://koajs.com" ], diff --git a/types/koa/test/constructor.ts b/types/koa/test/constructor.ts index f012aade213cdb..eb3c7debc44b04 100644 --- a/types/koa/test/constructor.ts +++ b/types/koa/test/constructor.ts @@ -7,6 +7,7 @@ const app = new Koa({ subdomainOffset: 2, proxyIpHeader: "XYZ-Forwarded-For", maxIpsCount: 2, + asyncLocalStorage: true, }); app.use(ctx => { diff --git a/types/koa/test/index.ts b/types/koa/test/index.ts index 6e0a6cb7eeffdc..d35dcd418b308b 100644 --- a/types/koa/test/index.ts +++ b/types/koa/test/index.ts @@ -75,4 +75,6 @@ app.use(ctx => { app.listen(3000); +app.currentContext; + const server = app.listen(); From 2c3935e7d9bd5853dd3a8c54ede337a3c652f4bf Mon Sep 17 00:00:00 2001 From: Alex A Yermoshenko Date: Tue, 9 Jan 2024 12:52:54 +0200 Subject: [PATCH 03/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#67927=20Adde?= =?UTF-8?q?d=20new=20ErrorCodeTypes=20and=20mark=20deprecated=20methods=20?= =?UTF-8?q?by=20@doterax?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alex A. Yermoshenko --- .../facebook-instant-games-tests.ts | 32 +++++++++++++++++++ types/facebook-instant-games/index.d.ts | 19 +++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/types/facebook-instant-games/facebook-instant-games-tests.ts b/types/facebook-instant-games/facebook-instant-games-tests.ts index feeab43df789cd..e4c49eefcaaa9f 100644 --- a/types/facebook-instant-games/facebook-instant-games-tests.ts +++ b/types/facebook-instant-games/facebook-instant-games-tests.ts @@ -304,3 +304,35 @@ FBInstant.squads.canUseSquadsAsync().then(isEligible => { }); } }); + +const allErrorCodes: FBInstant.ErrorCodeType[] = [ + "ADS_FREQUENT_LOAD", + "ADS_NOT_LOADED", + "ADS_NO_FILL", + "ADS_TOO_MANY_INSTANCES", + "ARENAS_NOT_FOUND", + "ANALYTICS_POST_EXCEPTION", + "CAMERA_EFFECT_NOT_FOUND", + "CLIENT_REQUIRES_UPDATE", + "CLIENT_UNSUPPORTED_OPERATION", + "DUPLICATE_POST", + "GAMING_SQUAD_NOT_FOUND", + "GROUP_NOT_LINKED", + "INVALID_OPERATION", + "INVALID_PARAM", + "LEADERBOARD_NOT_FOUND", + "LEADERBOARD_WRONG_CONTEXT", + "LIVE_MATCH_NOT_FOUND", + "LIVE_STREAMS_NOT_FOUND", + "NETWORK_FAILURE", + "PAGE_NOT_LINKED", + "PAYMENTS_NOT_INITIALIZED", + "PAYMENTS_OPERATION_FAILURE", + "PENDING_REQUEST", + "RATE_LIMITED", + "SAME_CONTEXT", + "TOURNAMENT_NOT_FOUND", + "UNKNOWN", + "USER_INPUT", + "VIDEO_NOT_FOUND", +]; diff --git a/types/facebook-instant-games/index.d.ts b/types/facebook-instant-games/index.d.ts index ea794f11b6f5c0..4702de30dd320c 100644 --- a/types/facebook-instant-games/index.d.ts +++ b/types/facebook-instant-games/index.d.ts @@ -790,6 +790,7 @@ declare namespace FBInstant { * @throws INVALID_PARAM * @throws NETWORK_FAILURE * @throws CLIENT_UNSUPPORTED_OPERATION + * @deprecated Stats APIs (getStatsAsync(), setStatsAsync() and incrementStatsAsync()) have been fully removed on September 28th, 2022. */ getStatsAsync(keys?: string[]): Promise; @@ -804,6 +805,7 @@ declare namespace FBInstant { * @throws NETWORK_FAILURE * @throws PENDING_REQUEST * @throws CLIENT_UNSUPPORTED_OPERATION + * @deprecated Stats APIs (getStatsAsync(), setStatsAsync() and incrementStatsAsync()) have been fully removed on September 28th, 2022. */ setStatsAsync(stats: StatsObject): Promise; @@ -819,6 +821,7 @@ declare namespace FBInstant { * @throws NETWORK_FAILURE * @throws PENDING_REQUEST * @throws CLIENT_UNSUPPORTED_OPERATION + * @deprecated Stats APIs (getStatsAsync(), setStatsAsync() and incrementStatsAsync()) have been fully removed on September 28th, 2022. */ incrementStatsAsync(increments: IncrementObject): Promise; @@ -2133,22 +2136,34 @@ declare namespace FBInstant { type ErrorCodeType = | "ADS_FREQUENT_LOAD" - | "ADS_NO_FILL" | "ADS_NOT_LOADED" + | "ADS_NO_FILL" | "ADS_TOO_MANY_INSTANCES" + | "ARENAS_NOT_FOUND" | "ANALYTICS_POST_EXCEPTION" + | "CAMERA_EFFECT_NOT_FOUND" | "CLIENT_REQUIRES_UPDATE" | "CLIENT_UNSUPPORTED_OPERATION" + | "DUPLICATE_POST" + | "GAMING_SQUAD_NOT_FOUND" + | "GROUP_NOT_LINKED" | "INVALID_OPERATION" | "INVALID_PARAM" | "LEADERBOARD_NOT_FOUND" | "LEADERBOARD_WRONG_CONTEXT" + | "LIVE_MATCH_NOT_FOUND" + | "LIVE_STREAMS_NOT_FOUND" | "NETWORK_FAILURE" + | "PAGE_NOT_LINKED" + | "PAYMENTS_NOT_INITIALIZED" + | "PAYMENTS_OPERATION_FAILURE" | "PENDING_REQUEST" | "RATE_LIMITED" | "SAME_CONTEXT" + | "TOURNAMENT_NOT_FOUND" | "UNKNOWN" - | "USER_INPUT"; + | "USER_INPUT" + | "VIDEO_NOT_FOUND"; /** * A function that will get called when user requested to capture a screenshot. From 39cc5808a7081cb92866dd3483cd47752a59869f Mon Sep 17 00:00:00 2001 From: Rohan Edman Date: Tue, 9 Jan 2024 09:25:29 -0500 Subject: [PATCH 04/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#67975=20Addi?= =?UTF-8?q?ng=20added=20missing=20nodeDataChanged=20by=20@zulander1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit missing nodeDataChanged --- types/drawflow/index.d.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/types/drawflow/index.d.ts b/types/drawflow/index.d.ts index 48c421d544b25c..9f2b04cb2c64e9 100644 --- a/types/drawflow/index.d.ts +++ b/types/drawflow/index.d.ts @@ -431,6 +431,11 @@ export default class Drawflow { * @param callback (event: id of Node) */ on(eventName: "nodeRemoved", callback: (event: number) => void): void; + /** + * @param eventName + * @param callback (event: id of Node df-* attributes changed.) + */ + on(eventName: "nodeDataChanged", callback: (event: number) => void): void; /** * @param eventName * @param callback (event: id of Node) From 302c7f2b1b4c16547ed09a34a27d1b8b241c9392 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 9 Jan 2024 15:44:59 +0100 Subject: [PATCH 05/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68096=20[rea?= =?UTF-8?q?ct-addons-linked-state-mixin]=20Use=20`Mixin`=20from=20`create-?= =?UTF-8?q?react-class`=20by=20@eps1lon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [react-addons-linked-state-mixin] Use `Mixin` from `create-react-class` * Fix module augmentation --- types/react-addons-linked-state-mixin/index.d.ts | 2 +- types/react-addons-linked-state-mixin/package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/types/react-addons-linked-state-mixin/index.d.ts b/types/react-addons-linked-state-mixin/index.d.ts index b913cf1dc31778..205f8d79be43bc 100644 --- a/types/react-addons-linked-state-mixin/index.d.ts +++ b/types/react-addons-linked-state-mixin/index.d.ts @@ -1,4 +1,4 @@ -import { Mixin } from "react"; +import { Mixin } from "create-react-class"; declare var LinkedStateMixin: LinkedStateMixin.LinkedStateMixin; type LinkedStateMixin = LinkedStateMixin.LinkedStateMixin; diff --git a/types/react-addons-linked-state-mixin/package.json b/types/react-addons-linked-state-mixin/package.json index 173dd57196f091..ee8b85d6dfea83 100644 --- a/types/react-addons-linked-state-mixin/package.json +++ b/types/react-addons-linked-state-mixin/package.json @@ -6,10 +6,10 @@ "http://facebook.github.io/react/" ], "dependencies": { - "@types/react": "*" + "@types/react": "*", + "@types/create-react-class": "*" }, "devDependencies": { - "@types/create-react-class": "*", "@types/react-dom-factories": "*", "@types/react-addons-linked-state-mixin": "workspace:." }, From c3e27b8988a697de062204706f5184e7ee59bb4a Mon Sep 17 00:00:00 2001 From: Dmitry Semigradsky Date: Tue, 9 Jan 2024 18:20:32 +0300 Subject: [PATCH 06/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#67573=20[nod?= =?UTF-8?q?e]=20Add=20`TracingChannel`=20by=20@Semigradsky?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/node/diagnostics_channel.d.ts | 356 ++++++++++++++++- types/node/test/diagnostics_channel.ts | 93 ++++- types/node/ts4.8/diagnostics_channel.d.ts | 356 ++++++++++++++++- types/node/ts4.8/test/diagnostics_channel.ts | 93 ++++- types/node/v18/diagnostics_channel.d.ts | 356 ++++++++++++++++- types/node/v18/test/diagnostics_channel.ts | 93 ++++- types/node/v18/ts4.8/diagnostics_channel.d.ts | 358 +++++++++++++++++- .../v18/ts4.8/test/diagnostics_channel.ts | 93 ++++- 8 files changed, 1789 insertions(+), 9 deletions(-) diff --git a/types/node/diagnostics_channel.d.ts b/types/node/diagnostics_channel.d.ts index b02f591787907a..cd4bd71b365a1f 100644 --- a/types/node/diagnostics_channel.d.ts +++ b/types/node/diagnostics_channel.d.ts @@ -23,6 +23,7 @@ * @see [source](https://github.com/nodejs/node/blob/v20.2.0/lib/diagnostics_channel.js) */ declare module "diagnostics_channel" { + import { AsyncLocalStorage } from "node:async_hooks"; /** * Check if there are active subscribers to the named channel. This is helpful if * the message you want to send might be expensive to prepare. @@ -95,6 +96,36 @@ declare module "diagnostics_channel" { * @return `true` if the handler was found, `false` otherwise. */ function unsubscribe(name: string | symbol, onMessage: ChannelListener): boolean; + /** + * Creates a `TracingChannel` wrapper for the given `TracingChannel Channels`. If a name is given, the corresponding tracing + * channels will be created in the form of `tracing:${name}:${eventType}` where`eventType` corresponds to the types of `TracingChannel Channels`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channelsByName = diagnostics_channel.tracingChannel('my-channel'); + * + * // or... + * + * const channelsByCollection = diagnostics_channel.tracingChannel({ + * start: diagnostics_channel.channel('tracing:my-channel:start'), + * end: diagnostics_channel.channel('tracing:my-channel:end'), + * asyncStart: diagnostics_channel.channel('tracing:my-channel:asyncStart'), + * asyncEnd: diagnostics_channel.channel('tracing:my-channel:asyncEnd'), + * error: diagnostics_channel.channel('tracing:my-channel:error'), + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param nameOrChannels Channel name or object containing all the `TracingChannel Channels` + * @return Collection of channels to trace with + */ + function tracingChannel< + StoreType = unknown, + ContextType extends object = StoreType extends object ? StoreType : object, + >( + nameOrChannels: string | TracingChannelCollection, + ): TracingChannel; /** * The class `Channel` represents an individual named channel within the data * pipeline. It is used to track subscribers and to publish messages when there @@ -104,7 +135,7 @@ declare module "diagnostics_channel" { * with `new Channel(name)` is not supported. * @since v15.1.0, v14.17.0 */ - class Channel { + class Channel { readonly name: string | symbol; /** * Check if there are active subscribers to this channel. This is helpful if @@ -184,6 +215,329 @@ declare module "diagnostics_channel" { * @return `true` if the handler was found, `false` otherwise. */ unsubscribe(onMessage: ChannelListener): void; + /** + * When `channel.runStores(context, ...)` is called, the given context data + * will be applied to any store bound to the channel. If the store has already been + * bound the previous `transform` function will be replaced with the new one. + * The `transform` function may be omitted to set the given context data as the + * context directly. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store, (data) => { + * return { data }; + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param store The store to which to bind the context data + * @param transform Transform context data before setting the store context + */ + bindStore(store: AsyncLocalStorage, transform?: (context: ContextType) => StoreType): void; + /** + * Remove a message handler previously registered to this channel with `channel.bindStore(store)`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store); + * channel.unbindStore(store); + * ``` + * @since v19.9.0 + * @experimental + * @param store The store to unbind from the channel. + * @return `true` if the store was found, `false` otherwise. + */ + unbindStore(store: any): void; + /** + * Applies the given data to any AsyncLocalStorage instances bound to the channel + * for the duration of the given function, then publishes to the channel within + * the scope of that data is applied to the stores. + * + * If a transform function was given to `channel.bindStore(store)` it will be + * applied to transform the message data before it becomes the context value for + * the store. The prior storage context is accessible from within the transform + * function in cases where context linking is required. + * + * The context applied to the store should be accessible in any async code which + * continues from execution which began during the given function, however + * there are some situations in which `context loss` may occur. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store, (message) => { + * const parent = store.getStore(); + * return new Span(message, parent); + * }); + * channel.runStores({ some: 'message' }, () => { + * store.getStore(); // Span({ some: 'message' }) + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param context Message to send to subscribers and bind to stores + * @param fn Handler to run within the entered storage context + * @param thisArg The receiver to be used for the function call. + * @param args Optional arguments to pass to the function. + */ + runStores(): void; + } + interface TracingChannelSubscribers { + start: (message: ContextType) => void; + end: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + asyncStart: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + asyncEnd: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + error: ( + message: ContextType & { + error: unknown; + }, + ) => void; + } + interface TracingChannelCollection { + start: Channel; + end: Channel; + asyncStart: Channel; + asyncEnd: Channel; + error: Channel; + } + /** + * The class `TracingChannel` is a collection of `TracingChannel Channels` which + * together express a single traceable action. It is used to formalize and + * simplify the process of producing events for tracing application flow.{@link tracingChannel} is used to construct a`TracingChannel`. As with `Channel` it is recommended to create and reuse a + * single `TracingChannel` at the top-level of the file rather than creating them + * dynamically. + * @since v19.9.0 + * @experimental + */ + class TracingChannel implements TracingChannelCollection { + start: Channel; + end: Channel; + asyncStart: Channel; + asyncEnd: Channel; + error: Channel; + /** + * Helper to subscribe a collection of functions to the corresponding channels. + * This is the same as calling `channel.subscribe(onMessage)` on each channel + * individually. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.subscribe({ + * start(message) { + * // Handle start message + * }, + * end(message) { + * // Handle end message + * }, + * asyncStart(message) { + * // Handle asyncStart message + * }, + * asyncEnd(message) { + * // Handle asyncEnd message + * }, + * error(message) { + * // Handle error message + * }, + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param subscribers Set of `TracingChannel Channels` subscribers + */ + subscribe(subscribers: TracingChannelSubscribers): void; + /** + * Helper to unsubscribe a collection of functions from the corresponding channels. + * This is the same as calling `channel.unsubscribe(onMessage)` on each channel + * individually. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.unsubscribe({ + * start(message) { + * // Handle start message + * }, + * end(message) { + * // Handle end message + * }, + * asyncStart(message) { + * // Handle asyncStart message + * }, + * asyncEnd(message) { + * // Handle asyncEnd message + * }, + * error(message) { + * // Handle error message + * }, + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param subscribers Set of `TracingChannel Channels` subscribers + * @return `true` if all handlers were successfully unsubscribed, and `false` otherwise. + */ + unsubscribe(subscribers: TracingChannelSubscribers): void; + /** + * Trace a synchronous function call. This will always produce a `start event` and `end event` around the execution and may produce an `error event` if the given function throws an error. + * This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.traceSync(() => { + * // Do something + * }, { + * some: 'thing', + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param fn Function to wrap a trace around + * @param context Shared object to correlate events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return The return value of the given function + */ + traceSync( + fn: (this: ThisArg, ...args: Args) => any, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): void; + /** + * Trace a promise-returning function call. This will always produce a `start event` and `end event` around the synchronous portion of the + * function execution, and will produce an `asyncStart event` and `asyncEnd event` when a promise continuation is reached. It may also + * produce an `error event` if the given function throws an error or the + * returned promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.tracePromise(async () => { + * // Do something + * }, { + * some: 'thing', + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param fn Promise-returning function to wrap a trace around + * @param context Shared object to correlate trace events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return Chained from promise returned by the given function + */ + tracePromise( + fn: (this: ThisArg, ...args: Args) => Promise, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): void; + /** + * Trace a callback-receiving function call. This will always produce a `start event` and `end event` around the synchronous portion of the + * function execution, and will produce a `asyncStart event` and `asyncEnd event` around the callback execution. It may also produce an `error event` if the given function throws an error or + * the returned + * promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * The `position` will be -1 by default to indicate the final argument should + * be used as the callback. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.traceCallback((arg1, callback) => { + * // Do something + * callback(null, 'result'); + * }, 1, { + * some: 'thing', + * }, thisArg, arg1, callback); + * ``` + * + * The callback will also be run with `channel.runStores(context, ...)` which + * enables context loss recovery in some cases. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * const myStore = new AsyncLocalStorage(); + * + * // The start channel sets the initial store data to something + * // and stores that store data value on the trace context object + * channels.start.bindStore(myStore, (data) => { + * const span = new Span(data); + * data.span = span; + * return span; + * }); + * + * // Then asyncStart can restore from that data it stored previously + * channels.asyncStart.bindStore(myStore, (data) => { + * return data.span; + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param fn callback using function to wrap a trace around + * @param position Zero-indexed argument position of expected callback + * @param context Shared object to correlate trace events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return The return value of the given function + */ + traceCallback any>( + fn: Fn, + position: number | undefined, + context: ContextType | undefined, + thisArg: any, + ...args: Parameters + ): void; } } declare module "node:diagnostics_channel" { diff --git a/types/node/test/diagnostics_channel.ts b/types/node/test/diagnostics_channel.ts index 348f68af4fb96c..2a288bf1b72868 100644 --- a/types/node/test/diagnostics_channel.ts +++ b/types/node/test/diagnostics_channel.ts @@ -1,4 +1,5 @@ -import { Channel, channel, hasSubscribers, subscribe, unsubscribe } from "node:diagnostics_channel"; +import { AsyncLocalStorage } from "node:async_hooks"; +import { Channel, channel, hasSubscribers, subscribe, unsubscribe, tracingChannel } from "node:diagnostics_channel"; const ch1: Channel = channel(Symbol.for("test")); function listener(data: unknown) {} @@ -22,3 +23,93 @@ subscribe(Symbol.for("test-symbol"), listener); unsubscribe(Symbol.for("test-symbol"), listener); const hasSubs = hasSubscribers("test"); + +{ + const channelsByName = tracingChannel('my-channel'); + channelsByName.start; // $ExpectType Channel + + type MyChannel = Channel + const channelsByCollection = tracingChannel({ + start: channel('tracing:my-channel:start') as MyChannel, + end: channel('tracing:my-channel:end') as MyChannel, + asyncStart: channel('tracing:my-channel:asyncStart') as MyChannel, + asyncEnd: channel('tracing:my-channel:asyncEnd') as MyChannel, + error: channel('tracing:my-channel:error') as MyChannel, + }); + channelsByCollection.start; // $ExpectType Channel +} + +{ + const channels = tracingChannel('my-channel'); + const store = new AsyncLocalStorage(); + + channels.start.bindStore(store); + channels.start.bindStore(store, (data) => { + return data.requestId; + }); + + channels.subscribe({ + start(message) { + message.requestId; // $ExpectType number + }, + end(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + asyncStart(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + asyncEnd(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + error(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + }, + }); + + const thisArg: string = 'hello' + const a: number = 1 + const b: string = '2' + + channels.traceSync(function (a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return 'something' + }, { requestId: 42 }, thisArg, a, b); + + channels.traceSync(function () { + return 'something' + }, { requestId: 42 }); + + channels.tracePromise(async function (a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return 'something' + }, { requestId: 42 }, thisArg, a, b); + + channels.tracePromise(async function () { + return 'something' + }, { requestId: 42 }); + + const callback = (err: unknown, result: string) => {} + + channels.traceCallback(function (arg1, callback) { + callback(null, 'result'); + }, 1, { + requestId: 42, + }, 'thisArg', 42, callback); + + channels.traceCallback(function (callback) { + callback(null, 'result'); + }, undefined, { + requestId: 42, + }, undefined, callback); +} diff --git a/types/node/ts4.8/diagnostics_channel.d.ts b/types/node/ts4.8/diagnostics_channel.d.ts index b02f591787907a..cd4bd71b365a1f 100644 --- a/types/node/ts4.8/diagnostics_channel.d.ts +++ b/types/node/ts4.8/diagnostics_channel.d.ts @@ -23,6 +23,7 @@ * @see [source](https://github.com/nodejs/node/blob/v20.2.0/lib/diagnostics_channel.js) */ declare module "diagnostics_channel" { + import { AsyncLocalStorage } from "node:async_hooks"; /** * Check if there are active subscribers to the named channel. This is helpful if * the message you want to send might be expensive to prepare. @@ -95,6 +96,36 @@ declare module "diagnostics_channel" { * @return `true` if the handler was found, `false` otherwise. */ function unsubscribe(name: string | symbol, onMessage: ChannelListener): boolean; + /** + * Creates a `TracingChannel` wrapper for the given `TracingChannel Channels`. If a name is given, the corresponding tracing + * channels will be created in the form of `tracing:${name}:${eventType}` where`eventType` corresponds to the types of `TracingChannel Channels`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channelsByName = diagnostics_channel.tracingChannel('my-channel'); + * + * // or... + * + * const channelsByCollection = diagnostics_channel.tracingChannel({ + * start: diagnostics_channel.channel('tracing:my-channel:start'), + * end: diagnostics_channel.channel('tracing:my-channel:end'), + * asyncStart: diagnostics_channel.channel('tracing:my-channel:asyncStart'), + * asyncEnd: diagnostics_channel.channel('tracing:my-channel:asyncEnd'), + * error: diagnostics_channel.channel('tracing:my-channel:error'), + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param nameOrChannels Channel name or object containing all the `TracingChannel Channels` + * @return Collection of channels to trace with + */ + function tracingChannel< + StoreType = unknown, + ContextType extends object = StoreType extends object ? StoreType : object, + >( + nameOrChannels: string | TracingChannelCollection, + ): TracingChannel; /** * The class `Channel` represents an individual named channel within the data * pipeline. It is used to track subscribers and to publish messages when there @@ -104,7 +135,7 @@ declare module "diagnostics_channel" { * with `new Channel(name)` is not supported. * @since v15.1.0, v14.17.0 */ - class Channel { + class Channel { readonly name: string | symbol; /** * Check if there are active subscribers to this channel. This is helpful if @@ -184,6 +215,329 @@ declare module "diagnostics_channel" { * @return `true` if the handler was found, `false` otherwise. */ unsubscribe(onMessage: ChannelListener): void; + /** + * When `channel.runStores(context, ...)` is called, the given context data + * will be applied to any store bound to the channel. If the store has already been + * bound the previous `transform` function will be replaced with the new one. + * The `transform` function may be omitted to set the given context data as the + * context directly. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store, (data) => { + * return { data }; + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param store The store to which to bind the context data + * @param transform Transform context data before setting the store context + */ + bindStore(store: AsyncLocalStorage, transform?: (context: ContextType) => StoreType): void; + /** + * Remove a message handler previously registered to this channel with `channel.bindStore(store)`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store); + * channel.unbindStore(store); + * ``` + * @since v19.9.0 + * @experimental + * @param store The store to unbind from the channel. + * @return `true` if the store was found, `false` otherwise. + */ + unbindStore(store: any): void; + /** + * Applies the given data to any AsyncLocalStorage instances bound to the channel + * for the duration of the given function, then publishes to the channel within + * the scope of that data is applied to the stores. + * + * If a transform function was given to `channel.bindStore(store)` it will be + * applied to transform the message data before it becomes the context value for + * the store. The prior storage context is accessible from within the transform + * function in cases where context linking is required. + * + * The context applied to the store should be accessible in any async code which + * continues from execution which began during the given function, however + * there are some situations in which `context loss` may occur. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store, (message) => { + * const parent = store.getStore(); + * return new Span(message, parent); + * }); + * channel.runStores({ some: 'message' }, () => { + * store.getStore(); // Span({ some: 'message' }) + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param context Message to send to subscribers and bind to stores + * @param fn Handler to run within the entered storage context + * @param thisArg The receiver to be used for the function call. + * @param args Optional arguments to pass to the function. + */ + runStores(): void; + } + interface TracingChannelSubscribers { + start: (message: ContextType) => void; + end: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + asyncStart: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + asyncEnd: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + error: ( + message: ContextType & { + error: unknown; + }, + ) => void; + } + interface TracingChannelCollection { + start: Channel; + end: Channel; + asyncStart: Channel; + asyncEnd: Channel; + error: Channel; + } + /** + * The class `TracingChannel` is a collection of `TracingChannel Channels` which + * together express a single traceable action. It is used to formalize and + * simplify the process of producing events for tracing application flow.{@link tracingChannel} is used to construct a`TracingChannel`. As with `Channel` it is recommended to create and reuse a + * single `TracingChannel` at the top-level of the file rather than creating them + * dynamically. + * @since v19.9.0 + * @experimental + */ + class TracingChannel implements TracingChannelCollection { + start: Channel; + end: Channel; + asyncStart: Channel; + asyncEnd: Channel; + error: Channel; + /** + * Helper to subscribe a collection of functions to the corresponding channels. + * This is the same as calling `channel.subscribe(onMessage)` on each channel + * individually. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.subscribe({ + * start(message) { + * // Handle start message + * }, + * end(message) { + * // Handle end message + * }, + * asyncStart(message) { + * // Handle asyncStart message + * }, + * asyncEnd(message) { + * // Handle asyncEnd message + * }, + * error(message) { + * // Handle error message + * }, + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param subscribers Set of `TracingChannel Channels` subscribers + */ + subscribe(subscribers: TracingChannelSubscribers): void; + /** + * Helper to unsubscribe a collection of functions from the corresponding channels. + * This is the same as calling `channel.unsubscribe(onMessage)` on each channel + * individually. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.unsubscribe({ + * start(message) { + * // Handle start message + * }, + * end(message) { + * // Handle end message + * }, + * asyncStart(message) { + * // Handle asyncStart message + * }, + * asyncEnd(message) { + * // Handle asyncEnd message + * }, + * error(message) { + * // Handle error message + * }, + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param subscribers Set of `TracingChannel Channels` subscribers + * @return `true` if all handlers were successfully unsubscribed, and `false` otherwise. + */ + unsubscribe(subscribers: TracingChannelSubscribers): void; + /** + * Trace a synchronous function call. This will always produce a `start event` and `end event` around the execution and may produce an `error event` if the given function throws an error. + * This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.traceSync(() => { + * // Do something + * }, { + * some: 'thing', + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param fn Function to wrap a trace around + * @param context Shared object to correlate events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return The return value of the given function + */ + traceSync( + fn: (this: ThisArg, ...args: Args) => any, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): void; + /** + * Trace a promise-returning function call. This will always produce a `start event` and `end event` around the synchronous portion of the + * function execution, and will produce an `asyncStart event` and `asyncEnd event` when a promise continuation is reached. It may also + * produce an `error event` if the given function throws an error or the + * returned promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.tracePromise(async () => { + * // Do something + * }, { + * some: 'thing', + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param fn Promise-returning function to wrap a trace around + * @param context Shared object to correlate trace events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return Chained from promise returned by the given function + */ + tracePromise( + fn: (this: ThisArg, ...args: Args) => Promise, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): void; + /** + * Trace a callback-receiving function call. This will always produce a `start event` and `end event` around the synchronous portion of the + * function execution, and will produce a `asyncStart event` and `asyncEnd event` around the callback execution. It may also produce an `error event` if the given function throws an error or + * the returned + * promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * The `position` will be -1 by default to indicate the final argument should + * be used as the callback. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.traceCallback((arg1, callback) => { + * // Do something + * callback(null, 'result'); + * }, 1, { + * some: 'thing', + * }, thisArg, arg1, callback); + * ``` + * + * The callback will also be run with `channel.runStores(context, ...)` which + * enables context loss recovery in some cases. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * const myStore = new AsyncLocalStorage(); + * + * // The start channel sets the initial store data to something + * // and stores that store data value on the trace context object + * channels.start.bindStore(myStore, (data) => { + * const span = new Span(data); + * data.span = span; + * return span; + * }); + * + * // Then asyncStart can restore from that data it stored previously + * channels.asyncStart.bindStore(myStore, (data) => { + * return data.span; + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param fn callback using function to wrap a trace around + * @param position Zero-indexed argument position of expected callback + * @param context Shared object to correlate trace events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return The return value of the given function + */ + traceCallback any>( + fn: Fn, + position: number | undefined, + context: ContextType | undefined, + thisArg: any, + ...args: Parameters + ): void; } } declare module "node:diagnostics_channel" { diff --git a/types/node/ts4.8/test/diagnostics_channel.ts b/types/node/ts4.8/test/diagnostics_channel.ts index 348f68af4fb96c..2a288bf1b72868 100644 --- a/types/node/ts4.8/test/diagnostics_channel.ts +++ b/types/node/ts4.8/test/diagnostics_channel.ts @@ -1,4 +1,5 @@ -import { Channel, channel, hasSubscribers, subscribe, unsubscribe } from "node:diagnostics_channel"; +import { AsyncLocalStorage } from "node:async_hooks"; +import { Channel, channel, hasSubscribers, subscribe, unsubscribe, tracingChannel } from "node:diagnostics_channel"; const ch1: Channel = channel(Symbol.for("test")); function listener(data: unknown) {} @@ -22,3 +23,93 @@ subscribe(Symbol.for("test-symbol"), listener); unsubscribe(Symbol.for("test-symbol"), listener); const hasSubs = hasSubscribers("test"); + +{ + const channelsByName = tracingChannel('my-channel'); + channelsByName.start; // $ExpectType Channel + + type MyChannel = Channel + const channelsByCollection = tracingChannel({ + start: channel('tracing:my-channel:start') as MyChannel, + end: channel('tracing:my-channel:end') as MyChannel, + asyncStart: channel('tracing:my-channel:asyncStart') as MyChannel, + asyncEnd: channel('tracing:my-channel:asyncEnd') as MyChannel, + error: channel('tracing:my-channel:error') as MyChannel, + }); + channelsByCollection.start; // $ExpectType Channel +} + +{ + const channels = tracingChannel('my-channel'); + const store = new AsyncLocalStorage(); + + channels.start.bindStore(store); + channels.start.bindStore(store, (data) => { + return data.requestId; + }); + + channels.subscribe({ + start(message) { + message.requestId; // $ExpectType number + }, + end(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + asyncStart(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + asyncEnd(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + error(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + }, + }); + + const thisArg: string = 'hello' + const a: number = 1 + const b: string = '2' + + channels.traceSync(function (a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return 'something' + }, { requestId: 42 }, thisArg, a, b); + + channels.traceSync(function () { + return 'something' + }, { requestId: 42 }); + + channels.tracePromise(async function (a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return 'something' + }, { requestId: 42 }, thisArg, a, b); + + channels.tracePromise(async function () { + return 'something' + }, { requestId: 42 }); + + const callback = (err: unknown, result: string) => {} + + channels.traceCallback(function (arg1, callback) { + callback(null, 'result'); + }, 1, { + requestId: 42, + }, 'thisArg', 42, callback); + + channels.traceCallback(function (callback) { + callback(null, 'result'); + }, undefined, { + requestId: 42, + }, undefined, callback); +} diff --git a/types/node/v18/diagnostics_channel.d.ts b/types/node/v18/diagnostics_channel.d.ts index eeb4d917a855e7..e5f1202b4dddaa 100644 --- a/types/node/v18/diagnostics_channel.d.ts +++ b/types/node/v18/diagnostics_channel.d.ts @@ -23,6 +23,7 @@ * @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/diagnostics_channel.js) */ declare module "diagnostics_channel" { + import { AsyncLocalStorage } from "node:async_hooks"; /** * Check if there are active subscribers to the named channel. This is helpful if * the message you want to send might be expensive to prepare. @@ -97,6 +98,36 @@ declare module "diagnostics_channel" { * @returns `true` if the handler was found, `false` otherwise */ function unsubscribe(name: string | symbol, onMessage: ChannelListener): boolean; + /** + * Creates a `TracingChannel` wrapper for the given `TracingChannel Channels`. If a name is given, the corresponding tracing + * channels will be created in the form of `tracing:${name}:${eventType}` where`eventType` corresponds to the types of `TracingChannel Channels`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channelsByName = diagnostics_channel.tracingChannel('my-channel'); + * + * // or... + * + * const channelsByCollection = diagnostics_channel.tracingChannel({ + * start: diagnostics_channel.channel('tracing:my-channel:start'), + * end: diagnostics_channel.channel('tracing:my-channel:end'), + * asyncStart: diagnostics_channel.channel('tracing:my-channel:asyncStart'), + * asyncEnd: diagnostics_channel.channel('tracing:my-channel:asyncEnd'), + * error: diagnostics_channel.channel('tracing:my-channel:error'), + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param nameOrChannels Channel name or object containing all the `TracingChannel Channels` + * @return Collection of channels to trace with + */ + function tracingChannel< + StoreType = unknown, + ContextType extends object = StoreType extends object ? StoreType : object, + >( + nameOrChannels: string | TracingChannelCollection, + ): TracingChannel; /** * The class `Channel` represents an individual named channel within the data * pipeline. It is use to track subscribers and to publish messages when there @@ -106,7 +137,7 @@ declare module "diagnostics_channel" { * with `new Channel(name)` is not supported. * @since v15.1.0, v14.17.0 */ - class Channel { + class Channel { readonly name: string | symbol; /** * Check if there are active subscribers to this channel. This is helpful if @@ -185,6 +216,329 @@ declare module "diagnostics_channel" { * @return `true` if the handler was found, `false` otherwise. */ unsubscribe(onMessage: ChannelListener): void; + /** + * When `channel.runStores(context, ...)` is called, the given context data + * will be applied to any store bound to the channel. If the store has already been + * bound the previous `transform` function will be replaced with the new one. + * The `transform` function may be omitted to set the given context data as the + * context directly. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store, (data) => { + * return { data }; + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param store The store to which to bind the context data + * @param transform Transform context data before setting the store context + */ + bindStore(store: AsyncLocalStorage, transform?: (context: ContextType) => StoreType): void; + /** + * Remove a message handler previously registered to this channel with `channel.bindStore(store)`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store); + * channel.unbindStore(store); + * ``` + * @since v18.19.0 + * @experimental + * @param store The store to unbind from the channel. + * @return `true` if the store was found, `false` otherwise. + */ + unbindStore(store: any): void; + /** + * Applies the given data to any AsyncLocalStorage instances bound to the channel + * for the duration of the given function, then publishes to the channel within + * the scope of that data is applied to the stores. + * + * If a transform function was given to `channel.bindStore(store)` it will be + * applied to transform the message data before it becomes the context value for + * the store. The prior storage context is accessible from within the transform + * function in cases where context linking is required. + * + * The context applied to the store should be accessible in any async code which + * continues from execution which began during the given function, however + * there are some situations in which `context loss` may occur. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store, (message) => { + * const parent = store.getStore(); + * return new Span(message, parent); + * }); + * channel.runStores({ some: 'message' }, () => { + * store.getStore(); // Span({ some: 'message' }) + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param context Message to send to subscribers and bind to stores + * @param fn Handler to run within the entered storage context + * @param thisArg The receiver to be used for the function call. + * @param args Optional arguments to pass to the function. + */ + runStores(): void; + } + interface TracingChannelSubscribers { + start: (message: ContextType) => void; + end: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + asyncStart: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + asyncEnd: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + error: ( + message: ContextType & { + error: unknown; + }, + ) => void; + } + interface TracingChannelCollection { + start: Channel; + end: Channel; + asyncStart: Channel; + asyncEnd: Channel; + error: Channel; + } + /** + * The class `TracingChannel` is a collection of `TracingChannel Channels` which + * together express a single traceable action. It is used to formalize and + * simplify the process of producing events for tracing application flow.{@link tracingChannel} is used to construct a`TracingChannel`. As with `Channel` it is recommended to create and reuse a + * single `TracingChannel` at the top-level of the file rather than creating them + * dynamically. + * @since v18.19.0 + * @experimental + */ + class TracingChannel implements TracingChannelCollection { + start: Channel; + end: Channel; + asyncStart: Channel; + asyncEnd: Channel; + error: Channel; + /** + * Helper to subscribe a collection of functions to the corresponding channels. + * This is the same as calling `channel.subscribe(onMessage)` on each channel + * individually. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.subscribe({ + * start(message) { + * // Handle start message + * }, + * end(message) { + * // Handle end message + * }, + * asyncStart(message) { + * // Handle asyncStart message + * }, + * asyncEnd(message) { + * // Handle asyncEnd message + * }, + * error(message) { + * // Handle error message + * }, + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param subscribers Set of `TracingChannel Channels` subscribers + */ + subscribe(subscribers: TracingChannelSubscribers): void; + /** + * Helper to unsubscribe a collection of functions from the corresponding channels. + * This is the same as calling `channel.unsubscribe(onMessage)` on each channel + * individually. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.unsubscribe({ + * start(message) { + * // Handle start message + * }, + * end(message) { + * // Handle end message + * }, + * asyncStart(message) { + * // Handle asyncStart message + * }, + * asyncEnd(message) { + * // Handle asyncEnd message + * }, + * error(message) { + * // Handle error message + * }, + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param subscribers Set of `TracingChannel Channels` subscribers + * @return `true` if all handlers were successfully unsubscribed, and `false` otherwise. + */ + unsubscribe(subscribers: TracingChannelSubscribers): void; + /** + * Trace a synchronous function call. This will always produce a `start event` and `end event` around the execution and may produce an `error event` if the given function throws an error. + * This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.traceSync(() => { + * // Do something + * }, { + * some: 'thing', + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param fn Function to wrap a trace around + * @param context Shared object to correlate events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return The return value of the given function + */ + traceSync( + fn: (this: ThisArg, ...args: Args) => any, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): void; + /** + * Trace a promise-returning function call. This will always produce a `start event` and `end event` around the synchronous portion of the + * function execution, and will produce an `asyncStart event` and `asyncEnd event` when a promise continuation is reached. It may also + * produce an `error event` if the given function throws an error or the + * returned promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.tracePromise(async () => { + * // Do something + * }, { + * some: 'thing', + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param fn Promise-returning function to wrap a trace around + * @param context Shared object to correlate trace events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return Chained from promise returned by the given function + */ + tracePromise( + fn: (this: ThisArg, ...args: Args) => Promise, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): void; + /** + * Trace a callback-receiving function call. This will always produce a `start event` and `end event` around the synchronous portion of the + * function execution, and will produce a `asyncStart event` and `asyncEnd event` around the callback execution. It may also produce an `error event` if the given function throws an error or + * the returned + * promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * The `position` will be -1 by default to indicate the final argument should + * be used as the callback. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.traceCallback((arg1, callback) => { + * // Do something + * callback(null, 'result'); + * }, 1, { + * some: 'thing', + * }, thisArg, arg1, callback); + * ``` + * + * The callback will also be run with `channel.runStores(context, ...)` which + * enables context loss recovery in some cases. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * const myStore = new AsyncLocalStorage(); + * + * // The start channel sets the initial store data to something + * // and stores that store data value on the trace context object + * channels.start.bindStore(myStore, (data) => { + * const span = new Span(data); + * data.span = span; + * return span; + * }); + * + * // Then asyncStart can restore from that data it stored previously + * channels.asyncStart.bindStore(myStore, (data) => { + * return data.span; + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param fn callback using function to wrap a trace around + * @param position Zero-indexed argument position of expected callback + * @param context Shared object to correlate trace events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return The return value of the given function + */ + traceCallback any>( + fn: Fn, + position: number | undefined, + context: ContextType | undefined, + thisArg: any, + ...args: Parameters + ): void; } } declare module "node:diagnostics_channel" { diff --git a/types/node/v18/test/diagnostics_channel.ts b/types/node/v18/test/diagnostics_channel.ts index 348f68af4fb96c..2a288bf1b72868 100644 --- a/types/node/v18/test/diagnostics_channel.ts +++ b/types/node/v18/test/diagnostics_channel.ts @@ -1,4 +1,5 @@ -import { Channel, channel, hasSubscribers, subscribe, unsubscribe } from "node:diagnostics_channel"; +import { AsyncLocalStorage } from "node:async_hooks"; +import { Channel, channel, hasSubscribers, subscribe, unsubscribe, tracingChannel } from "node:diagnostics_channel"; const ch1: Channel = channel(Symbol.for("test")); function listener(data: unknown) {} @@ -22,3 +23,93 @@ subscribe(Symbol.for("test-symbol"), listener); unsubscribe(Symbol.for("test-symbol"), listener); const hasSubs = hasSubscribers("test"); + +{ + const channelsByName = tracingChannel('my-channel'); + channelsByName.start; // $ExpectType Channel + + type MyChannel = Channel + const channelsByCollection = tracingChannel({ + start: channel('tracing:my-channel:start') as MyChannel, + end: channel('tracing:my-channel:end') as MyChannel, + asyncStart: channel('tracing:my-channel:asyncStart') as MyChannel, + asyncEnd: channel('tracing:my-channel:asyncEnd') as MyChannel, + error: channel('tracing:my-channel:error') as MyChannel, + }); + channelsByCollection.start; // $ExpectType Channel +} + +{ + const channels = tracingChannel('my-channel'); + const store = new AsyncLocalStorage(); + + channels.start.bindStore(store); + channels.start.bindStore(store, (data) => { + return data.requestId; + }); + + channels.subscribe({ + start(message) { + message.requestId; // $ExpectType number + }, + end(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + asyncStart(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + asyncEnd(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + error(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + }, + }); + + const thisArg: string = 'hello' + const a: number = 1 + const b: string = '2' + + channels.traceSync(function (a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return 'something' + }, { requestId: 42 }, thisArg, a, b); + + channels.traceSync(function () { + return 'something' + }, { requestId: 42 }); + + channels.tracePromise(async function (a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return 'something' + }, { requestId: 42 }, thisArg, a, b); + + channels.tracePromise(async function () { + return 'something' + }, { requestId: 42 }); + + const callback = (err: unknown, result: string) => {} + + channels.traceCallback(function (arg1, callback) { + callback(null, 'result'); + }, 1, { + requestId: 42, + }, 'thisArg', 42, callback); + + channels.traceCallback(function (callback) { + callback(null, 'result'); + }, undefined, { + requestId: 42, + }, undefined, callback); +} diff --git a/types/node/v18/ts4.8/diagnostics_channel.d.ts b/types/node/v18/ts4.8/diagnostics_channel.d.ts index f0cb779188f2f8..e5f1202b4dddaa 100644 --- a/types/node/v18/ts4.8/diagnostics_channel.d.ts +++ b/types/node/v18/ts4.8/diagnostics_channel.d.ts @@ -20,9 +20,10 @@ * should generally include the module name to avoid collisions with data from * other modules. * @experimental - * @see [source](https://github.com/nodejs/node/blob/v18.7.0/lib/diagnostics_channel.js) + * @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/diagnostics_channel.js) */ declare module "diagnostics_channel" { + import { AsyncLocalStorage } from "node:async_hooks"; /** * Check if there are active subscribers to the named channel. This is helpful if * the message you want to send might be expensive to prepare. @@ -97,6 +98,36 @@ declare module "diagnostics_channel" { * @returns `true` if the handler was found, `false` otherwise */ function unsubscribe(name: string | symbol, onMessage: ChannelListener): boolean; + /** + * Creates a `TracingChannel` wrapper for the given `TracingChannel Channels`. If a name is given, the corresponding tracing + * channels will be created in the form of `tracing:${name}:${eventType}` where`eventType` corresponds to the types of `TracingChannel Channels`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channelsByName = diagnostics_channel.tracingChannel('my-channel'); + * + * // or... + * + * const channelsByCollection = diagnostics_channel.tracingChannel({ + * start: diagnostics_channel.channel('tracing:my-channel:start'), + * end: diagnostics_channel.channel('tracing:my-channel:end'), + * asyncStart: diagnostics_channel.channel('tracing:my-channel:asyncStart'), + * asyncEnd: diagnostics_channel.channel('tracing:my-channel:asyncEnd'), + * error: diagnostics_channel.channel('tracing:my-channel:error'), + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param nameOrChannels Channel name or object containing all the `TracingChannel Channels` + * @return Collection of channels to trace with + */ + function tracingChannel< + StoreType = unknown, + ContextType extends object = StoreType extends object ? StoreType : object, + >( + nameOrChannels: string | TracingChannelCollection, + ): TracingChannel; /** * The class `Channel` represents an individual named channel within the data * pipeline. It is use to track subscribers and to publish messages when there @@ -106,7 +137,7 @@ declare module "diagnostics_channel" { * with `new Channel(name)` is not supported. * @since v15.1.0, v14.17.0 */ - class Channel { + class Channel { readonly name: string | symbol; /** * Check if there are active subscribers to this channel. This is helpful if @@ -185,6 +216,329 @@ declare module "diagnostics_channel" { * @return `true` if the handler was found, `false` otherwise. */ unsubscribe(onMessage: ChannelListener): void; + /** + * When `channel.runStores(context, ...)` is called, the given context data + * will be applied to any store bound to the channel. If the store has already been + * bound the previous `transform` function will be replaced with the new one. + * The `transform` function may be omitted to set the given context data as the + * context directly. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store, (data) => { + * return { data }; + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param store The store to which to bind the context data + * @param transform Transform context data before setting the store context + */ + bindStore(store: AsyncLocalStorage, transform?: (context: ContextType) => StoreType): void; + /** + * Remove a message handler previously registered to this channel with `channel.bindStore(store)`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store); + * channel.unbindStore(store); + * ``` + * @since v18.19.0 + * @experimental + * @param store The store to unbind from the channel. + * @return `true` if the store was found, `false` otherwise. + */ + unbindStore(store: any): void; + /** + * Applies the given data to any AsyncLocalStorage instances bound to the channel + * for the duration of the given function, then publishes to the channel within + * the scope of that data is applied to the stores. + * + * If a transform function was given to `channel.bindStore(store)` it will be + * applied to transform the message data before it becomes the context value for + * the store. The prior storage context is accessible from within the transform + * function in cases where context linking is required. + * + * The context applied to the store should be accessible in any async code which + * continues from execution which began during the given function, however + * there are some situations in which `context loss` may occur. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store, (message) => { + * const parent = store.getStore(); + * return new Span(message, parent); + * }); + * channel.runStores({ some: 'message' }, () => { + * store.getStore(); // Span({ some: 'message' }) + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param context Message to send to subscribers and bind to stores + * @param fn Handler to run within the entered storage context + * @param thisArg The receiver to be used for the function call. + * @param args Optional arguments to pass to the function. + */ + runStores(): void; + } + interface TracingChannelSubscribers { + start: (message: ContextType) => void; + end: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + asyncStart: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + asyncEnd: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + error: ( + message: ContextType & { + error: unknown; + }, + ) => void; + } + interface TracingChannelCollection { + start: Channel; + end: Channel; + asyncStart: Channel; + asyncEnd: Channel; + error: Channel; + } + /** + * The class `TracingChannel` is a collection of `TracingChannel Channels` which + * together express a single traceable action. It is used to formalize and + * simplify the process of producing events for tracing application flow.{@link tracingChannel} is used to construct a`TracingChannel`. As with `Channel` it is recommended to create and reuse a + * single `TracingChannel` at the top-level of the file rather than creating them + * dynamically. + * @since v18.19.0 + * @experimental + */ + class TracingChannel implements TracingChannelCollection { + start: Channel; + end: Channel; + asyncStart: Channel; + asyncEnd: Channel; + error: Channel; + /** + * Helper to subscribe a collection of functions to the corresponding channels. + * This is the same as calling `channel.subscribe(onMessage)` on each channel + * individually. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.subscribe({ + * start(message) { + * // Handle start message + * }, + * end(message) { + * // Handle end message + * }, + * asyncStart(message) { + * // Handle asyncStart message + * }, + * asyncEnd(message) { + * // Handle asyncEnd message + * }, + * error(message) { + * // Handle error message + * }, + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param subscribers Set of `TracingChannel Channels` subscribers + */ + subscribe(subscribers: TracingChannelSubscribers): void; + /** + * Helper to unsubscribe a collection of functions from the corresponding channels. + * This is the same as calling `channel.unsubscribe(onMessage)` on each channel + * individually. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.unsubscribe({ + * start(message) { + * // Handle start message + * }, + * end(message) { + * // Handle end message + * }, + * asyncStart(message) { + * // Handle asyncStart message + * }, + * asyncEnd(message) { + * // Handle asyncEnd message + * }, + * error(message) { + * // Handle error message + * }, + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param subscribers Set of `TracingChannel Channels` subscribers + * @return `true` if all handlers were successfully unsubscribed, and `false` otherwise. + */ + unsubscribe(subscribers: TracingChannelSubscribers): void; + /** + * Trace a synchronous function call. This will always produce a `start event` and `end event` around the execution and may produce an `error event` if the given function throws an error. + * This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.traceSync(() => { + * // Do something + * }, { + * some: 'thing', + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param fn Function to wrap a trace around + * @param context Shared object to correlate events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return The return value of the given function + */ + traceSync( + fn: (this: ThisArg, ...args: Args) => any, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): void; + /** + * Trace a promise-returning function call. This will always produce a `start event` and `end event` around the synchronous portion of the + * function execution, and will produce an `asyncStart event` and `asyncEnd event` when a promise continuation is reached. It may also + * produce an `error event` if the given function throws an error or the + * returned promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.tracePromise(async () => { + * // Do something + * }, { + * some: 'thing', + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param fn Promise-returning function to wrap a trace around + * @param context Shared object to correlate trace events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return Chained from promise returned by the given function + */ + tracePromise( + fn: (this: ThisArg, ...args: Args) => Promise, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): void; + /** + * Trace a callback-receiving function call. This will always produce a `start event` and `end event` around the synchronous portion of the + * function execution, and will produce a `asyncStart event` and `asyncEnd event` around the callback execution. It may also produce an `error event` if the given function throws an error or + * the returned + * promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * The `position` will be -1 by default to indicate the final argument should + * be used as the callback. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.traceCallback((arg1, callback) => { + * // Do something + * callback(null, 'result'); + * }, 1, { + * some: 'thing', + * }, thisArg, arg1, callback); + * ``` + * + * The callback will also be run with `channel.runStores(context, ...)` which + * enables context loss recovery in some cases. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * const myStore = new AsyncLocalStorage(); + * + * // The start channel sets the initial store data to something + * // and stores that store data value on the trace context object + * channels.start.bindStore(myStore, (data) => { + * const span = new Span(data); + * data.span = span; + * return span; + * }); + * + * // Then asyncStart can restore from that data it stored previously + * channels.asyncStart.bindStore(myStore, (data) => { + * return data.span; + * }); + * ``` + * @since v18.19.0 + * @experimental + * @param fn callback using function to wrap a trace around + * @param position Zero-indexed argument position of expected callback + * @param context Shared object to correlate trace events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return The return value of the given function + */ + traceCallback any>( + fn: Fn, + position: number | undefined, + context: ContextType | undefined, + thisArg: any, + ...args: Parameters + ): void; } } declare module "node:diagnostics_channel" { diff --git a/types/node/v18/ts4.8/test/diagnostics_channel.ts b/types/node/v18/ts4.8/test/diagnostics_channel.ts index 348f68af4fb96c..2a288bf1b72868 100644 --- a/types/node/v18/ts4.8/test/diagnostics_channel.ts +++ b/types/node/v18/ts4.8/test/diagnostics_channel.ts @@ -1,4 +1,5 @@ -import { Channel, channel, hasSubscribers, subscribe, unsubscribe } from "node:diagnostics_channel"; +import { AsyncLocalStorage } from "node:async_hooks"; +import { Channel, channel, hasSubscribers, subscribe, unsubscribe, tracingChannel } from "node:diagnostics_channel"; const ch1: Channel = channel(Symbol.for("test")); function listener(data: unknown) {} @@ -22,3 +23,93 @@ subscribe(Symbol.for("test-symbol"), listener); unsubscribe(Symbol.for("test-symbol"), listener); const hasSubs = hasSubscribers("test"); + +{ + const channelsByName = tracingChannel('my-channel'); + channelsByName.start; // $ExpectType Channel + + type MyChannel = Channel + const channelsByCollection = tracingChannel({ + start: channel('tracing:my-channel:start') as MyChannel, + end: channel('tracing:my-channel:end') as MyChannel, + asyncStart: channel('tracing:my-channel:asyncStart') as MyChannel, + asyncEnd: channel('tracing:my-channel:asyncEnd') as MyChannel, + error: channel('tracing:my-channel:error') as MyChannel, + }); + channelsByCollection.start; // $ExpectType Channel +} + +{ + const channels = tracingChannel('my-channel'); + const store = new AsyncLocalStorage(); + + channels.start.bindStore(store); + channels.start.bindStore(store, (data) => { + return data.requestId; + }); + + channels.subscribe({ + start(message) { + message.requestId; // $ExpectType number + }, + end(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + asyncStart(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + asyncEnd(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + message.result // $ExpectType unknown + }, + error(message) { + message.requestId; // $ExpectType number + message.error // $ExpectType unknown + }, + }); + + const thisArg: string = 'hello' + const a: number = 1 + const b: string = '2' + + channels.traceSync(function (a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return 'something' + }, { requestId: 42 }, thisArg, a, b); + + channels.traceSync(function () { + return 'something' + }, { requestId: 42 }); + + channels.tracePromise(async function (a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return 'something' + }, { requestId: 42 }, thisArg, a, b); + + channels.tracePromise(async function () { + return 'something' + }, { requestId: 42 }); + + const callback = (err: unknown, result: string) => {} + + channels.traceCallback(function (arg1, callback) { + callback(null, 'result'); + }, 1, { + requestId: 42, + }, 'thisArg', 42, callback); + + channels.traceCallback(function (callback) { + callback(null, 'result'); + }, undefined, { + requestId: 42, + }, undefined, callback); +} From 8f57a1d53135397fbd4ff8dc2d29d2fc1f069529 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 9 Jan 2024 15:21:38 +0000 Subject: [PATCH 07/23] =?UTF-8?q?=F0=9F=A4=96=20dprint=20fmt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/node/test/diagnostics_channel.ts | 123 +++++++++++------- types/node/ts4.8/test/diagnostics_channel.ts | 123 +++++++++++------- types/node/v18/test/diagnostics_channel.ts | 123 +++++++++++------- .../v18/ts4.8/test/diagnostics_channel.ts | 123 +++++++++++------- 4 files changed, 296 insertions(+), 196 deletions(-) diff --git a/types/node/test/diagnostics_channel.ts b/types/node/test/diagnostics_channel.ts index 2a288bf1b72868..97c49edbf61c7c 100644 --- a/types/node/test/diagnostics_channel.ts +++ b/types/node/test/diagnostics_channel.ts @@ -1,5 +1,5 @@ import { AsyncLocalStorage } from "node:async_hooks"; -import { Channel, channel, hasSubscribers, subscribe, unsubscribe, tracingChannel } from "node:diagnostics_channel"; +import { Channel, channel, hasSubscribers, subscribe, tracingChannel, unsubscribe } from "node:diagnostics_channel"; const ch1: Channel = channel(Symbol.for("test")); function listener(data: unknown) {} @@ -25,22 +25,22 @@ unsubscribe(Symbol.for("test-symbol"), listener); const hasSubs = hasSubscribers("test"); { - const channelsByName = tracingChannel('my-channel'); + const channelsByName = tracingChannel("my-channel"); channelsByName.start; // $ExpectType Channel - type MyChannel = Channel + type MyChannel = Channel; const channelsByCollection = tracingChannel({ - start: channel('tracing:my-channel:start') as MyChannel, - end: channel('tracing:my-channel:end') as MyChannel, - asyncStart: channel('tracing:my-channel:asyncStart') as MyChannel, - asyncEnd: channel('tracing:my-channel:asyncEnd') as MyChannel, - error: channel('tracing:my-channel:error') as MyChannel, + start: channel("tracing:my-channel:start") as MyChannel, + end: channel("tracing:my-channel:end") as MyChannel, + asyncStart: channel("tracing:my-channel:asyncStart") as MyChannel, + asyncEnd: channel("tracing:my-channel:asyncEnd") as MyChannel, + error: channel("tracing:my-channel:error") as MyChannel, }); channelsByCollection.start; // $ExpectType Channel } { - const channels = tracingChannel('my-channel'); + const channels = tracingChannel("my-channel"); const store = new AsyncLocalStorage(); channels.start.bindStore(store); @@ -54,62 +54,87 @@ const hasSubs = hasSubscribers("test"); }, end(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, asyncStart(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, asyncEnd(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, error(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown + message.error; // $ExpectType unknown }, }); - const thisArg: string = 'hello' - const a: number = 1 - const b: string = '2' + const thisArg: string = "hello"; + const a: number = 1; + const b: string = "2"; - channels.traceSync(function (a, b) { - this; // $ExpectType string - a; // $ExpectType number - b; // $ExpectType string - return 'something' - }, { requestId: 42 }, thisArg, a, b); - - channels.traceSync(function () { - return 'something' + channels.traceSync( + function(a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return "something"; + }, + { requestId: 42 }, + thisArg, + a, + b, + ); + + channels.traceSync(function() { + return "something"; }, { requestId: 42 }); - channels.tracePromise(async function (a, b) { - this; // $ExpectType string - a; // $ExpectType number - b; // $ExpectType string - return 'something' - }, { requestId: 42 }, thisArg, a, b); - - channels.tracePromise(async function () { - return 'something' + channels.tracePromise( + async function(a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return "something"; + }, + { requestId: 42 }, + thisArg, + a, + b, + ); + + channels.tracePromise(async function() { + return "something"; }, { requestId: 42 }); - const callback = (err: unknown, result: string) => {} - - channels.traceCallback(function (arg1, callback) { - callback(null, 'result'); - }, 1, { - requestId: 42, - }, 'thisArg', 42, callback); + const callback = (err: unknown, result: string) => {}; - channels.traceCallback(function (callback) { - callback(null, 'result'); - }, undefined, { - requestId: 42, - }, undefined, callback); + channels.traceCallback( + function(arg1, callback) { + callback(null, "result"); + }, + 1, + { + requestId: 42, + }, + "thisArg", + 42, + callback, + ); + + channels.traceCallback( + function(callback) { + callback(null, "result"); + }, + undefined, + { + requestId: 42, + }, + undefined, + callback, + ); } diff --git a/types/node/ts4.8/test/diagnostics_channel.ts b/types/node/ts4.8/test/diagnostics_channel.ts index 2a288bf1b72868..97c49edbf61c7c 100644 --- a/types/node/ts4.8/test/diagnostics_channel.ts +++ b/types/node/ts4.8/test/diagnostics_channel.ts @@ -1,5 +1,5 @@ import { AsyncLocalStorage } from "node:async_hooks"; -import { Channel, channel, hasSubscribers, subscribe, unsubscribe, tracingChannel } from "node:diagnostics_channel"; +import { Channel, channel, hasSubscribers, subscribe, tracingChannel, unsubscribe } from "node:diagnostics_channel"; const ch1: Channel = channel(Symbol.for("test")); function listener(data: unknown) {} @@ -25,22 +25,22 @@ unsubscribe(Symbol.for("test-symbol"), listener); const hasSubs = hasSubscribers("test"); { - const channelsByName = tracingChannel('my-channel'); + const channelsByName = tracingChannel("my-channel"); channelsByName.start; // $ExpectType Channel - type MyChannel = Channel + type MyChannel = Channel; const channelsByCollection = tracingChannel({ - start: channel('tracing:my-channel:start') as MyChannel, - end: channel('tracing:my-channel:end') as MyChannel, - asyncStart: channel('tracing:my-channel:asyncStart') as MyChannel, - asyncEnd: channel('tracing:my-channel:asyncEnd') as MyChannel, - error: channel('tracing:my-channel:error') as MyChannel, + start: channel("tracing:my-channel:start") as MyChannel, + end: channel("tracing:my-channel:end") as MyChannel, + asyncStart: channel("tracing:my-channel:asyncStart") as MyChannel, + asyncEnd: channel("tracing:my-channel:asyncEnd") as MyChannel, + error: channel("tracing:my-channel:error") as MyChannel, }); channelsByCollection.start; // $ExpectType Channel } { - const channels = tracingChannel('my-channel'); + const channels = tracingChannel("my-channel"); const store = new AsyncLocalStorage(); channels.start.bindStore(store); @@ -54,62 +54,87 @@ const hasSubs = hasSubscribers("test"); }, end(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, asyncStart(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, asyncEnd(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, error(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown + message.error; // $ExpectType unknown }, }); - const thisArg: string = 'hello' - const a: number = 1 - const b: string = '2' + const thisArg: string = "hello"; + const a: number = 1; + const b: string = "2"; - channels.traceSync(function (a, b) { - this; // $ExpectType string - a; // $ExpectType number - b; // $ExpectType string - return 'something' - }, { requestId: 42 }, thisArg, a, b); - - channels.traceSync(function () { - return 'something' + channels.traceSync( + function(a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return "something"; + }, + { requestId: 42 }, + thisArg, + a, + b, + ); + + channels.traceSync(function() { + return "something"; }, { requestId: 42 }); - channels.tracePromise(async function (a, b) { - this; // $ExpectType string - a; // $ExpectType number - b; // $ExpectType string - return 'something' - }, { requestId: 42 }, thisArg, a, b); - - channels.tracePromise(async function () { - return 'something' + channels.tracePromise( + async function(a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return "something"; + }, + { requestId: 42 }, + thisArg, + a, + b, + ); + + channels.tracePromise(async function() { + return "something"; }, { requestId: 42 }); - const callback = (err: unknown, result: string) => {} - - channels.traceCallback(function (arg1, callback) { - callback(null, 'result'); - }, 1, { - requestId: 42, - }, 'thisArg', 42, callback); + const callback = (err: unknown, result: string) => {}; - channels.traceCallback(function (callback) { - callback(null, 'result'); - }, undefined, { - requestId: 42, - }, undefined, callback); + channels.traceCallback( + function(arg1, callback) { + callback(null, "result"); + }, + 1, + { + requestId: 42, + }, + "thisArg", + 42, + callback, + ); + + channels.traceCallback( + function(callback) { + callback(null, "result"); + }, + undefined, + { + requestId: 42, + }, + undefined, + callback, + ); } diff --git a/types/node/v18/test/diagnostics_channel.ts b/types/node/v18/test/diagnostics_channel.ts index 2a288bf1b72868..97c49edbf61c7c 100644 --- a/types/node/v18/test/diagnostics_channel.ts +++ b/types/node/v18/test/diagnostics_channel.ts @@ -1,5 +1,5 @@ import { AsyncLocalStorage } from "node:async_hooks"; -import { Channel, channel, hasSubscribers, subscribe, unsubscribe, tracingChannel } from "node:diagnostics_channel"; +import { Channel, channel, hasSubscribers, subscribe, tracingChannel, unsubscribe } from "node:diagnostics_channel"; const ch1: Channel = channel(Symbol.for("test")); function listener(data: unknown) {} @@ -25,22 +25,22 @@ unsubscribe(Symbol.for("test-symbol"), listener); const hasSubs = hasSubscribers("test"); { - const channelsByName = tracingChannel('my-channel'); + const channelsByName = tracingChannel("my-channel"); channelsByName.start; // $ExpectType Channel - type MyChannel = Channel + type MyChannel = Channel; const channelsByCollection = tracingChannel({ - start: channel('tracing:my-channel:start') as MyChannel, - end: channel('tracing:my-channel:end') as MyChannel, - asyncStart: channel('tracing:my-channel:asyncStart') as MyChannel, - asyncEnd: channel('tracing:my-channel:asyncEnd') as MyChannel, - error: channel('tracing:my-channel:error') as MyChannel, + start: channel("tracing:my-channel:start") as MyChannel, + end: channel("tracing:my-channel:end") as MyChannel, + asyncStart: channel("tracing:my-channel:asyncStart") as MyChannel, + asyncEnd: channel("tracing:my-channel:asyncEnd") as MyChannel, + error: channel("tracing:my-channel:error") as MyChannel, }); channelsByCollection.start; // $ExpectType Channel } { - const channels = tracingChannel('my-channel'); + const channels = tracingChannel("my-channel"); const store = new AsyncLocalStorage(); channels.start.bindStore(store); @@ -54,62 +54,87 @@ const hasSubs = hasSubscribers("test"); }, end(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, asyncStart(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, asyncEnd(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, error(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown + message.error; // $ExpectType unknown }, }); - const thisArg: string = 'hello' - const a: number = 1 - const b: string = '2' + const thisArg: string = "hello"; + const a: number = 1; + const b: string = "2"; - channels.traceSync(function (a, b) { - this; // $ExpectType string - a; // $ExpectType number - b; // $ExpectType string - return 'something' - }, { requestId: 42 }, thisArg, a, b); - - channels.traceSync(function () { - return 'something' + channels.traceSync( + function(a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return "something"; + }, + { requestId: 42 }, + thisArg, + a, + b, + ); + + channels.traceSync(function() { + return "something"; }, { requestId: 42 }); - channels.tracePromise(async function (a, b) { - this; // $ExpectType string - a; // $ExpectType number - b; // $ExpectType string - return 'something' - }, { requestId: 42 }, thisArg, a, b); - - channels.tracePromise(async function () { - return 'something' + channels.tracePromise( + async function(a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return "something"; + }, + { requestId: 42 }, + thisArg, + a, + b, + ); + + channels.tracePromise(async function() { + return "something"; }, { requestId: 42 }); - const callback = (err: unknown, result: string) => {} - - channels.traceCallback(function (arg1, callback) { - callback(null, 'result'); - }, 1, { - requestId: 42, - }, 'thisArg', 42, callback); + const callback = (err: unknown, result: string) => {}; - channels.traceCallback(function (callback) { - callback(null, 'result'); - }, undefined, { - requestId: 42, - }, undefined, callback); + channels.traceCallback( + function(arg1, callback) { + callback(null, "result"); + }, + 1, + { + requestId: 42, + }, + "thisArg", + 42, + callback, + ); + + channels.traceCallback( + function(callback) { + callback(null, "result"); + }, + undefined, + { + requestId: 42, + }, + undefined, + callback, + ); } diff --git a/types/node/v18/ts4.8/test/diagnostics_channel.ts b/types/node/v18/ts4.8/test/diagnostics_channel.ts index 2a288bf1b72868..97c49edbf61c7c 100644 --- a/types/node/v18/ts4.8/test/diagnostics_channel.ts +++ b/types/node/v18/ts4.8/test/diagnostics_channel.ts @@ -1,5 +1,5 @@ import { AsyncLocalStorage } from "node:async_hooks"; -import { Channel, channel, hasSubscribers, subscribe, unsubscribe, tracingChannel } from "node:diagnostics_channel"; +import { Channel, channel, hasSubscribers, subscribe, tracingChannel, unsubscribe } from "node:diagnostics_channel"; const ch1: Channel = channel(Symbol.for("test")); function listener(data: unknown) {} @@ -25,22 +25,22 @@ unsubscribe(Symbol.for("test-symbol"), listener); const hasSubs = hasSubscribers("test"); { - const channelsByName = tracingChannel('my-channel'); + const channelsByName = tracingChannel("my-channel"); channelsByName.start; // $ExpectType Channel - type MyChannel = Channel + type MyChannel = Channel; const channelsByCollection = tracingChannel({ - start: channel('tracing:my-channel:start') as MyChannel, - end: channel('tracing:my-channel:end') as MyChannel, - asyncStart: channel('tracing:my-channel:asyncStart') as MyChannel, - asyncEnd: channel('tracing:my-channel:asyncEnd') as MyChannel, - error: channel('tracing:my-channel:error') as MyChannel, + start: channel("tracing:my-channel:start") as MyChannel, + end: channel("tracing:my-channel:end") as MyChannel, + asyncStart: channel("tracing:my-channel:asyncStart") as MyChannel, + asyncEnd: channel("tracing:my-channel:asyncEnd") as MyChannel, + error: channel("tracing:my-channel:error") as MyChannel, }); channelsByCollection.start; // $ExpectType Channel } { - const channels = tracingChannel('my-channel'); + const channels = tracingChannel("my-channel"); const store = new AsyncLocalStorage(); channels.start.bindStore(store); @@ -54,62 +54,87 @@ const hasSubs = hasSubscribers("test"); }, end(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, asyncStart(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, asyncEnd(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown - message.result // $ExpectType unknown + message.error; // $ExpectType unknown + message.result; // $ExpectType unknown }, error(message) { message.requestId; // $ExpectType number - message.error // $ExpectType unknown + message.error; // $ExpectType unknown }, }); - const thisArg: string = 'hello' - const a: number = 1 - const b: string = '2' + const thisArg: string = "hello"; + const a: number = 1; + const b: string = "2"; - channels.traceSync(function (a, b) { - this; // $ExpectType string - a; // $ExpectType number - b; // $ExpectType string - return 'something' - }, { requestId: 42 }, thisArg, a, b); - - channels.traceSync(function () { - return 'something' + channels.traceSync( + function(a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return "something"; + }, + { requestId: 42 }, + thisArg, + a, + b, + ); + + channels.traceSync(function() { + return "something"; }, { requestId: 42 }); - channels.tracePromise(async function (a, b) { - this; // $ExpectType string - a; // $ExpectType number - b; // $ExpectType string - return 'something' - }, { requestId: 42 }, thisArg, a, b); - - channels.tracePromise(async function () { - return 'something' + channels.tracePromise( + async function(a, b) { + this; // $ExpectType string + a; // $ExpectType number + b; // $ExpectType string + return "something"; + }, + { requestId: 42 }, + thisArg, + a, + b, + ); + + channels.tracePromise(async function() { + return "something"; }, { requestId: 42 }); - const callback = (err: unknown, result: string) => {} - - channels.traceCallback(function (arg1, callback) { - callback(null, 'result'); - }, 1, { - requestId: 42, - }, 'thisArg', 42, callback); + const callback = (err: unknown, result: string) => {}; - channels.traceCallback(function (callback) { - callback(null, 'result'); - }, undefined, { - requestId: 42, - }, undefined, callback); + channels.traceCallback( + function(arg1, callback) { + callback(null, "result"); + }, + 1, + { + requestId: 42, + }, + "thisArg", + 42, + callback, + ); + + channels.traceCallback( + function(callback) { + callback(null, "result"); + }, + undefined, + { + requestId: 42, + }, + undefined, + callback, + ); } From d7c170bfa8c02592f069874528104487c55b3484 Mon Sep 17 00:00:00 2001 From: Felix Uhl Date: Tue, 9 Jan 2024 19:59:25 +0100 Subject: [PATCH 08/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#67946=20[wha?= =?UTF-8?q?twg-url]=20Fix=20type=20of=20baseURL=20by=20@iFreilicht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `baseURL` being a string was incorrect. The `URL` class actually parses the `baseURL` before passing it to `parseURL`, see https://github.com/jsdom/whatwg-url/blob/6aa56a7ff00b24b45543d6efd7c1ae42c467bee9/lib/URL-impl.js#L13-L19 But both `parseURL` and `basicParseURL` just pass the base verbatim to `URLStateMachine`, which then tries to access members of that. I confirmed this by testing whatwg-url in node: ``` $ node Welcome to Node.js v18.18.2. Type ".help" for more information. > x = require('whatwg-url') ... > base = x.parseURL( > x.parseURL('/asdf?my=param', { baseURL: 'http://example.com' }) { scheme: undefined, username: undefined, password: undefined, host: undefined, port: undefined, path: [ 'asdf' ], query: 'my=param', fragment: null } > base = x.parseURL('http://example.com') { scheme: 'http', username: '', password: '', host: 'example.com', port: null, path: [ '' ], query: null, fragment: null } > x.parseURL('/asdf?my=param', { baseURL: base }) { scheme: 'http', username: '', password: '', host: 'example.com', port: null, path: [ 'asdf' ], query: 'my=param', fragment: null } ``` As you can see, passing a string causes multiple `undefined`s, while passing a URLRecord works as expected. --- types/whatwg-url/index.d.ts | 4 ++-- types/whatwg-url/test/whatwg-url.index.test.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/types/whatwg-url/index.d.ts b/types/whatwg-url/index.d.ts index 653e9e21e3b30f..2922d87f9b7261 100644 --- a/types/whatwg-url/index.d.ts +++ b/types/whatwg-url/index.d.ts @@ -88,13 +88,13 @@ export class URLSearchParams { } /** https://url.spec.whatwg.org/#concept-url-parser */ -export function parseURL(input: string, options?: { readonly baseURL?: string | undefined }): URLRecord | null; +export function parseURL(input: string, options?: { readonly baseURL?: URLRecord | undefined }): URLRecord | null; /** https://url.spec.whatwg.org/#concept-basic-url-parser */ export function basicURLParse( input: string, options?: { - baseURL?: string | undefined; + baseURL?: URLRecord | undefined; url?: URLRecord | undefined; stateOverride?: StateOverride | undefined; }, diff --git a/types/whatwg-url/test/whatwg-url.index.test.ts b/types/whatwg-url/test/whatwg-url.index.test.ts index 23d977459bb4e3..c2c8e350de2b9b 100644 --- a/types/whatwg-url/test/whatwg-url.index.test.ts +++ b/types/whatwg-url/test/whatwg-url.index.test.ts @@ -18,7 +18,6 @@ new whatwgUrl.URL("foo", "http://example.com"); // $ExpectType URLRecord | null const urlRecord = whatwgUrl.parseURL("http://example.com"); -whatwgUrl.parseURL("http://example.com", { baseURL: "foo" }); if (urlRecord !== null) { urlRecord.scheme; // $ExpectType string @@ -30,7 +29,7 @@ if (urlRecord !== null) { urlRecord.query; // $ExpectType string | null urlRecord.fragment; // $ExpectType string | null whatwgUrl.basicURLParse("http://example.com", { url: urlRecord }); // $ExpectType URLRecord | null - whatwgUrl.basicURLParse("http://example.com", { baseURL: "foo" }); // $ExpectType URLRecord | null + whatwgUrl.basicURLParse("/relative/path", { baseURL: urlRecord }); // $ExpectType URLRecord | null ( [ "scheme start", From ee7950d4cdbb51e56400f34ab8bc0abaa337fa9d Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 9 Jan 2024 20:24:20 +0100 Subject: [PATCH 09/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#67794=20[rea?= =?UTF-8?q?ct-animals]=20Ensure=20types=20use=20same=20React=20version=20a?= =?UTF-8?q?s=20runtime=20by=20@eps1lon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [react-animals] Ensure types use same React version as runtime * Use package.json --- types/react-animals/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/react-animals/package.json b/types/react-animals/package.json index 5989064404eb86..912c13f4cfc2d0 100644 --- a/types/react-animals/package.json +++ b/types/react-animals/package.json @@ -6,7 +6,7 @@ "https://github.com/arvinpoddar/react-animals" ], "dependencies": { - "@types/react": "*" + "@types/react": "^16" }, "devDependencies": { "@types/react-animals": "workspace:." From 26fed54062145973a3a8a5851437aa34f22b1e54 Mon Sep 17 00:00:00 2001 From: Sam Ramon <15154970+samantharamon@users.noreply.github.com> Date: Tue, 9 Jan 2024 12:27:07 -0800 Subject: [PATCH 10/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68150=20[off?= =?UTF-8?q?ice-js][office-js-preview]=20(Outlook)=20Clarify=20delayDeliver?= =?UTF-8?q?yTime.setAsync=20behavior=20by=20@samantharamon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/office-js-preview/index.d.ts | 12 ++++++++++++ types/office-js/index.d.ts | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/types/office-js-preview/index.d.ts b/types/office-js-preview/index.d.ts index 8784768c876236..dca0ca5e738549 100644 --- a/types/office-js-preview/index.d.ts +++ b/types/office-js-preview/index.d.ts @@ -13283,6 +13283,12 @@ declare namespace Office { * * **{@link https://learn.microsoft.com/office/dev/add-ins/outlook/outlook-add-ins-overview#extension-points | Applicable Outlook mode}**: Compose * + * **Important**: When `item.delayDeliveryTime.setAsync` is used to schedule the delivery of a message, the delay is processed on the server. + * This allows the message to be sent even if the Outlook client isn't running. However, because of this, the message doesn't appear in the + * **Outbox** folder, so you won't be able to edit the message or cancel its delivery after selecting **Send**. You'll only be able to review + * the mesasge from the **Sent Items** folder once the message is sent. To learn more, see + * {@link https://learn.microsoft.com/office/dev/add-ins/outlook/delay-delivery | Manage the delivery date and time of a message}. + * * **Errors**: * * - `InvalidFormatError` - The format of the specified data object is not valid. @@ -13304,6 +13310,12 @@ declare namespace Office { * * **{@link https://learn.microsoft.com/office/dev/add-ins/outlook/outlook-add-ins-overview#extension-points | Applicable Outlook mode}**: Compose * + * **Important**: When `item.delayDeliveryTime.setAsync` is used to schedule the delivery of a message, the delay is processed on the server. + * This allows the message to be sent even if the Outlook client isn't running. However, because of this, the message doesn't appear in the + * **Outbox** folder, so you won't be able to edit the message or cancel its delivery after selecting **Send**. You'll only be able to review + * the mesasge from the **Sent Items** folder once the message is sent. To learn more, see + * {@link https://learn.microsoft.com/office/dev/add-ins/outlook/delay-delivery | Manage the delivery date and time of a message}. + * * **Errors**: * * - `InvalidFormatError` - The format of the specified data object is not valid. diff --git a/types/office-js/index.d.ts b/types/office-js/index.d.ts index 7b0e41d145915b..707816f1b5b308 100644 --- a/types/office-js/index.d.ts +++ b/types/office-js/index.d.ts @@ -13088,6 +13088,12 @@ declare namespace Office { * * **{@link https://learn.microsoft.com/office/dev/add-ins/outlook/outlook-add-ins-overview#extension-points | Applicable Outlook mode}**: Compose * + * **Important**: When `item.delayDeliveryTime.setAsync` is used to schedule the delivery of a message, the delay is processed on the server. + * This allows the message to be sent even if the Outlook client isn't running. However, because of this, the message doesn't appear in the + * **Outbox** folder, so you won't be able to edit the message or cancel its delivery after selecting **Send**. You'll only be able to review + * the mesasge from the **Sent Items** folder once the message is sent. To learn more, see + * {@link https://learn.microsoft.com/office/dev/add-ins/outlook/delay-delivery | Manage the delivery date and time of a message}. + * * **Errors**: * * - `InvalidFormatError` - The format of the specified data object is not valid. @@ -13109,6 +13115,12 @@ declare namespace Office { * * **{@link https://learn.microsoft.com/office/dev/add-ins/outlook/outlook-add-ins-overview#extension-points | Applicable Outlook mode}**: Compose * + * **Important**: When `item.delayDeliveryTime.setAsync` is used to schedule the delivery of a message, the delay is processed on the server. + * This allows the message to be sent even if the Outlook client isn't running. However, because of this, the message doesn't appear in the + * **Outbox** folder, so you won't be able to edit the message or cancel its delivery after selecting **Send**. You'll only be able to review + * the mesasge from the **Sent Items** folder once the message is sent. To learn more, see + * {@link https://learn.microsoft.com/office/dev/add-ins/outlook/delay-delivery | Manage the delivery date and time of a message}. + * * **Errors**: * * - `InvalidFormatError` - The format of the specified data object is not valid. From bf9914fb2d465433a4c324312091da185cedc0fa Mon Sep 17 00:00:00 2001 From: Ben Asher Date: Tue, 9 Jan 2024 13:03:57 -0800 Subject: [PATCH 11/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68121=20[@ty?= =?UTF-8?q?pes/validator]=20Improve=20compatibility=20with=20TS=20NodeNext?= =?UTF-8?q?=20by=20@benasher44?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Improve compatibility with TS NodeNext * Actually do export = * semicolons * remove interface + add more exports + remove unused import * missing typeof * Fix bad refactor typo --- types/validator/index.d.ts | 306 +++++++++++++++-------------- types/validator/lib/isBoolean.d.ts | 1 - 2 files changed, 156 insertions(+), 151 deletions(-) diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index 4a7ef97b3cbd8e..3289af6a062442 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -9,13 +9,13 @@ import * as _isTaxID from "./lib/isTaxID"; import * as _isURL from "./lib/isURL"; declare namespace validator { - const version: string; + export const version: string; /****************** *** Validators *** ******************/ - interface ContainsOptions { + export interface ContainsOptions { /** * @default false */ @@ -31,23 +31,23 @@ declare namespace validator { * * @param seed - Seed */ - function contains(str: string, seed: any, options?: ContainsOptions): boolean; + export function contains(str: string, seed: any, options?: ContainsOptions): boolean; /** * Check if the string matches the comparison. * * @param comparison - String to compare */ - function equals(str: string, comparison: string): boolean; + export function equals(str: string, comparison: string): boolean; /** * Check if the string is a date that's after the specified date. * * @param [date] - Date string (defaults to now) */ - function isAfter(str: string, date?: string): boolean; + export function isAfter(str: string, date?: string): boolean; - type AlphaLocale = + export type AlphaLocale = | "en-US" | "bg-BG" | "cs-CZ" @@ -103,9 +103,9 @@ declare namespace validator { | "pt-BR" | "pl-Pl"; - const isAlphaLocales: AlphaLocale[]; + export const isAlphaLocales: AlphaLocale[]; - interface IsAlphaOptions { + export interface IsAlphaOptions { /** * @default undefined */ @@ -118,9 +118,9 @@ declare namespace validator { * @param [locale] - AlphaLocale * @param [options] - IsAlphaOptions */ - function isAlpha(str: string, locale?: AlphaLocale, options?: IsAlphaOptions): boolean; + export function isAlpha(str: string, locale?: AlphaLocale, options?: IsAlphaOptions): boolean; - type AlphanumericLocale = + export type AlphanumericLocale = | "en-US" | "bg-BG" | "cs-CZ" @@ -176,9 +176,9 @@ declare namespace validator { | "pt-BR" | "pl-Pl"; - const isAlphanumericLocales: AlphanumericLocale[]; + export const isAlphanumericLocales: AlphanumericLocale[]; - interface IsAlphanumericOptions { + export interface IsAlphanumericOptions { /** * @default undefined */ @@ -191,23 +191,23 @@ declare namespace validator { * @param [locale] - AlphanumericLocale * @param [options] - IsAlphanumericOptions */ - function isAlphanumeric(str: string, locale?: AlphanumericLocale, options?: IsAlphanumericOptions): boolean; + export function isAlphanumeric(str: string, locale?: AlphanumericLocale, options?: IsAlphanumericOptions): boolean; /** * Check if the string contains ASCII chars only. */ - function isAscii(str: string): boolean; + export function isAscii(str: string): boolean; /** * Check if a string is base32 encoded. */ - function isBase32(str: string): boolean; + export function isBase32(str: string): boolean; /** * check if a string is base58 encoded */ - function isBase58(str: string): boolean; + export function isBase58(str: string): boolean; - interface IsBase64Options { + export interface IsBase64Options { /** * @default false */ @@ -219,26 +219,26 @@ declare namespace validator { * * @param [options] - Options */ - function isBase64(str: string, options?: IsBase64Options): boolean; + export function isBase64(str: string, options?: IsBase64Options): boolean; /** * Check if the string is a date that's before the specified date. * * @param [date] - Date string (defaults to now) */ - function isBefore(str: string, date?: string): boolean; + export function isBefore(str: string, date?: string): boolean; - const isIBAN: typeof _isIBAN.default; - const ibanLocales: typeof _isIBAN.locales; + export const isIBAN: typeof _isIBAN.default; + export const ibanLocales: typeof _isIBAN.locales; /** * Check if a string is a BIC (Bank Identification Code) or SWIFT code. */ - function isBIC(str: string): boolean; + export function isBIC(str: string): boolean; - const isBoolean: typeof _isBoolean.default; + export const isBoolean: typeof _isBoolean.default; - interface IsByteLengthOptions { + export interface IsByteLengthOptions { /** * @default 0 */ @@ -254,9 +254,9 @@ declare namespace validator { * * @param [options] - Options */ - function isByteLength(str: string, options?: IsByteLengthOptions): boolean; + export function isByteLength(str: string, options?: IsByteLengthOptions): boolean; - interface IsCreditCardOptions { + export interface IsCreditCardOptions { /** * @default undefined */ @@ -266,9 +266,9 @@ declare namespace validator { /** * Check if the string is a credit card. */ - function isCreditCard(str: string, options?: IsCreditCardOptions): boolean; + export function isCreditCard(str: string, options?: IsCreditCardOptions): boolean; - interface IsCurrencyOptions { + export interface IsCurrencyOptions { /** * @default '$' */ @@ -338,24 +338,24 @@ declare namespace validator { * * @param [options] - Options */ - function isCurrency(str: string, options?: IsCurrencyOptions): boolean; + export function isCurrency(str: string, options?: IsCurrencyOptions): boolean; /** * Check if the string is an [Ethereum](https://ethereum.org/) address using basic regex. Does not validate address checksums. */ - function isEthereumAddress(str: string): boolean; + export function isEthereumAddress(str: string): boolean; /** * Check if the string is a valid BTC address. */ - function isBtcAddress(str: string): boolean; + export function isBtcAddress(str: string): boolean; /** * Check if the string is a [data uri format](https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs). */ - function isDataURI(str: string): boolean; + export function isDataURI(str: string): boolean; - interface IsDateOptions { + export interface IsDateOptions { /** * @default false */ @@ -378,11 +378,11 @@ declare namespace validator { /** * Check if the string is a valid date. */ - function isDate(str: string, options?: IsDateOptions): boolean; + export function isDate(str: string, options?: IsDateOptions): boolean; - type DecimalLocale = FloatLocale; + export type DecimalLocale = FloatLocale; - interface IsDecimalOptions { + export interface IsDecimalOptions { /** * @default false */ @@ -408,26 +408,26 @@ declare namespace validator { * * @param [options] - Options */ - function isDecimal(str: string, options?: IsDecimalOptions): boolean; + export function isDecimal(str: string, options?: IsDecimalOptions): boolean; /** * Check if the string is a number that's divisible by another. * * @param number - Divider number */ - function isDivisibleBy(str: string, number: number): boolean; + export function isDivisibleBy(str: string, number: number): boolean; - type IsEmailOptions = _isEmail.IsEmailOptions; - const isEmail: typeof _isEmail.default; + export type IsEmailOptions = _isEmail.IsEmailOptions; + export const isEmail: typeof _isEmail.default; /** * check if the string is a [Magnet URI format][Mailto URI Format].

`options` is an object of validating emails inside the URI (check `isEmail`s options for details). * @param str * @param [options] */ - function isMailtoURI(str: string, options?: IsEmailOptions): boolean; + export function isMailtoURI(str: string, options?: IsEmailOptions): boolean; - interface IsEmptyOptions { + export interface IsEmptyOptions { /** * @default false */ @@ -439,9 +439,9 @@ declare namespace validator { * * @param [options] - Options */ - function isEmpty(str: string, options?: IsEmptyOptions): boolean; + export function isEmpty(str: string, options?: IsEmptyOptions): boolean; - type FloatLocale = + export type FloatLocale = | "en-US" | "ar" | "en-AU" @@ -493,9 +493,9 @@ declare namespace validator { | "pt-BR" | "pl-Pl"; - const isFloatLocales: FloatLocale[]; + export const isFloatLocales: FloatLocale[]; - interface IsFloatOptions { + export interface IsFloatOptions { /** * less or equal */ @@ -523,22 +523,22 @@ declare namespace validator { * * @param [options] - Options */ - function isFloat(str: string, options?: IsFloatOptions): boolean; + export function isFloat(str: string, options?: IsFloatOptions): boolean; - type IsFQDNOptions = _isFQDN.IsFQDNOptions; - const isFQDN: typeof _isFQDN.default; + export type IsFQDNOptions = _isFQDN.IsFQDNOptions; + export const isFQDN: typeof _isFQDN.default; /** * Check if the string contains any full-width chars. */ - function isFullWidth(str: string): boolean; + export function isFullWidth(str: string): boolean; /** * Check if the string contains any half-width chars. */ - function isHalfWidth(str: string): boolean; + export function isHalfWidth(str: string): boolean; - type HashAlgorithm = + export type HashAlgorithm = | "md4" | "md5" | "sha1" @@ -554,36 +554,36 @@ declare namespace validator { | "crc32b"; /** - * Check if the string is a hash of type algorithm. + * Check if the string is a hash of export type algorithm. * * @param algorithm - HashAlgorithm */ - function isHash(str: string, algorithm: HashAlgorithm): boolean; + export function isHash(str: string, algorithm: HashAlgorithm): boolean; /** * Check if the string is a hexadecimal number. */ - function isHexadecimal(str: string): boolean; + export function isHexadecimal(str: string): boolean; /** * Check if the string is a hexadecimal color. */ - function isHexColor(str: string): boolean; + export function isHexColor(str: string): boolean; /** * Check if the string is an HSL (hue, saturation, lightness, optional alpha) color based on CSS Colors Level 4 specification. * Comma-separated format supported. Space-separated format supported with the exception of a few edge cases (ex: hsl(200grad+.1%62%/1)). */ - function isHSL(str: string): boolean; + export function isHSL(str: string): boolean; /** * Check if the string is a rgb or rgba color. * * @param [includePercentValues=true] - If you don't want to allow to set rgb or rgba values with percents, like rgb(5%,5%,5%), or rgba(90%,90%,90%,.3), then set it to false. (defaults to true) */ - function isRgbColor(str: string, includePercentValues?: boolean): boolean; + export function isRgbColor(str: string, includePercentValues?: boolean): boolean; - type IdentityCardLocale = + export type IdentityCardLocale = | "ar-LY" | "ar-TN" | "ES" @@ -605,9 +605,9 @@ declare namespace validator { * * @param [locale="any"] - IdentityCardLocale */ - function isIdentityCard(str: string, locale?: "any" | IdentityCardLocale): boolean; + export function isIdentityCard(str: string, locale?: "any" | IdentityCardLocale): boolean; - interface IsIMEIOptions { + export interface IsIMEIOptions { /** * This value is `false` by default. Set to `true` to allow IMEI with hyphens. */ @@ -621,16 +621,16 @@ declare namespace validator { * * @param [options] - Options */ - function isIMEI(str: string, options?: IsIMEIOptions): boolean; + export function isIMEI(str: string, options?: IsIMEIOptions): boolean; /** * Check if the string is in a array of allowed values. * * @param values - Allowed values. */ - function isIn(str: string, values: any[]): boolean; + export function isIn(str: string, values: any[]): boolean; - interface IsIntOptions { + export interface IsIntOptions { /** * to check the integer min boundary */ @@ -659,65 +659,65 @@ declare namespace validator { * * @param [options] - Options */ - function isInt(str: string, options?: IsIntOptions): boolean; + export function isInt(str: string, options?: IsIntOptions): boolean; - type IPVersion = "4" | "6" | 4 | 6; + export type IPVersion = "4" | "6" | 4 | 6; /** * Check if the string is an IP (version 4 or 6). * * @param [version] - IP Version */ - function isIP(str: string, version?: IPVersion): boolean; + export function isIP(str: string, version?: IPVersion): boolean; /** * Check if the string is an IP Range (version 4 or 6). */ - function isIPRange(str: string, version?: IPVersion): boolean; + export function isIPRange(str: string, version?: IPVersion): boolean; - type ISBNVersion = "10" | "13" | 10 | 13; + export type ISBNVersion = "10" | "13" | 10 | 13; /** * Check if the string is an ISBN (version 10 or 13). * * @param [version] - ISBN Version */ - function isISBN(str: string, version?: ISBNVersion): boolean; + export function isISBN(str: string, version?: ISBNVersion): boolean; /** * Check if the string is an EAN (European Article Number). */ - function isEAN(str: string): boolean; + export function isEAN(str: string): boolean; /** * Check if the string is an [ISIN](https://en.wikipedia.org/wiki/International_Securities_Identification_Number) (stock/security identifier). */ - function isISIN(str: string): boolean; + export function isISIN(str: string): boolean; - const isISO31661Alpha2: typeof _isISO31661Alpha2.default; + export const isISO31661Alpha2: typeof _isISO31661Alpha2.default; /** * Check if the string is a valid [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) officially assigned country code. */ - function isISO31661Alpha3(str: string): boolean; + export function isISO31661Alpha3(str: string): boolean; /** * check if the string is a valid [ISO 6346](https://en.wikipedia.org/wiki/ISO_6346) shipping container identification. * @param str */ - function isISO6346(str: string): boolean; + export function isISO6346(str: string): boolean; /** * alias for `isISO6346`, check if the string is a valid [ISO 6346](https://en.wikipedia.org/wiki/ISO_6346) shipping container identification. */ - const isFreightContainerID: typeof isISO6346; + export const isFreightContainerID: typeof isISO6346; /** * Check if the string is a valid [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) officially assigned language code. */ - const isISO6391: typeof _isISO6391.default; + export const isISO6391: typeof _isISO6391.default; - interface IsISO8601Options { + export interface IsISO8601Options { /** * If `strict` is `true`, performs additional checks for valid dates, * e.g. invalidates dates like `2009-02-29`. @@ -737,9 +737,9 @@ declare namespace validator { * * @param [options] - Options */ - function isISO8601(str: string, options?: IsISO8601Options): boolean; + export function isISO8601(str: string, options?: IsISO8601Options): boolean; - interface IsISSNOptions { + export interface IsISSNOptions { /** * If `case_sensitive` is `true`, ISSNs with a lowercase `x` as the check digit are rejected. * @@ -757,38 +757,38 @@ declare namespace validator { * * @param [options] - Options */ - function isISSN(str: string, options?: IsISSNOptions): boolean; + export function isISSN(str: string, options?: IsISSNOptions): boolean; - const isISO4217: typeof _isISO4217.default; + export const isISO4217: typeof _isISO4217.default; /** * Check if the string is a [ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code). */ - function isISRC(str: string): boolean; + export function isISRC(str: string): boolean; /** * Check if the string is a valid [RFC 3339](https://tools.ietf.org/html/rfc3339) date. */ - function isRFC3339(str: string): boolean; + export function isRFC3339(str: string): boolean; /** * Check if the string is valid JSON (note: uses `JSON.parse`). */ - function isJSON(str: string): boolean; + export function isJSON(str: string): boolean; /** * Check if the string is valid JWT token. */ - function isJWT(str: string): boolean; + export function isJWT(str: string): boolean; /** * Check if the string is a valid latitude-longitude coordinate in the format: * * `lat,long` or `lat, long`. */ - function isLatLong(str: string): boolean; + export function isLatLong(str: string): boolean; - interface IsLengthOptions { + export interface IsLengthOptions { /** * @default 0 */ @@ -802,23 +802,23 @@ declare namespace validator { /** * Check if the string's length falls in a range. * - * Note: this function takes into account surrogate pairs. + * Note: this export function takes into account surrogate pairs. * * @param [options] - Options */ - function isLength(str: string, options?: IsLengthOptions): boolean; + export function isLength(str: string, options?: IsLengthOptions): boolean; /** * Check if the string is a locale. */ - function isLocale(str: string): boolean; + export function isLocale(str: string): boolean; /** * Check if the string is lowercase. */ - function isLowercase(str: string): boolean; + export function isLowercase(str: string): boolean; - interface IsMACAddressOptions { + export interface IsMACAddressOptions { /** * If `no_colons` is `true`, the validator will allow MAC addresses without the colons. * Also, it allows the use of hyphens or spaces. @@ -835,25 +835,25 @@ declare namespace validator { * * @param [options] - Options */ - function isMACAddress(str: string, options?: IsMACAddressOptions): boolean; + export function isMACAddress(str: string, options?: IsMACAddressOptions): boolean; /** * Check if the string is a [magnet uri format](https://en.wikipedia.org/wiki/Magnet_URI_scheme). */ - function isMagnetURI(str: string): boolean; + export function isMagnetURI(str: string): boolean; /** * Check if the string is a MD5 hash. */ - function isMD5(str: string): boolean; + export function isMD5(str: string): boolean; /** - * Check if the string matches to a valid [MIME type](https://en.wikipedia.org/wiki/Media_type) format. + * Check if the string matches to a valid [MIME export type](https://en.wikipedia.org/wiki/Media_export type) format. */ - function isMimeType(str: string): boolean; + export function isMimeType(str: string): boolean; - type MobilePhoneLocale = PhoneLocale | PhoneLocaleAlias; - type PhoneLocale = + export type MobilePhoneLocale = PhoneLocale | PhoneLocaleAlias; + export type PhoneLocale = | "am-AM" | "ar-AE" | "ar-BH" @@ -969,11 +969,11 @@ declare namespace validator { | "vi-VN" | "zh-CN" | "zh-TW"; - type PhoneLocaleAlias = "en-CA" | "fr-CA" | "fr-BE" | "zh-HK" | "zh-MO" | "ga-IE" | "fr-CH" | "it-CH"; + export type PhoneLocaleAlias = "en-CA" | "fr-CA" | "fr-BE" | "zh-HK" | "zh-MO" | "ga-IE" | "fr-CH" | "it-CH"; - const isMobilePhoneLocales: MobilePhoneLocale[]; + export const isMobilePhoneLocales: MobilePhoneLocale[]; - interface IsMobilePhoneOptions { + export interface IsMobilePhoneOptions { /** * If this is set to `true`, the mobile phone number must be supplied with the country code and therefore must start with `+`. * @@ -988,7 +988,7 @@ declare namespace validator { * @param [locale] - MobilePhoneLocale(s) * @param [options] - Options */ - function isMobilePhone( + export function isMobilePhone( str: string, locale?: "any" | MobilePhoneLocale | MobilePhoneLocale[], options?: IsMobilePhoneOptions, @@ -997,14 +997,14 @@ declare namespace validator { /** * Check if the string is a valid hex-encoded representation of a [MongoDB ObjectId](http://docs.mongodb.org/manual/reference/object-id/). */ - function isMongoId(str: string): boolean; + export function isMongoId(str: string): boolean; /** * Check if the string contains one or more multibyte chars. */ - function isMultibyte(str: string): boolean; + export function isMultibyte(str: string): boolean; - interface IsNumericOptions { + export interface IsNumericOptions { /** * If `no_symbols` is true, the validator will reject numeric strings that feature a symbol (e.g. `+`, `-`, or `.`). * @@ -1019,26 +1019,26 @@ declare namespace validator { * * @param [options] - Options */ - function isNumeric(str: string, options?: IsNumericOptions): boolean; + export function isNumeric(str: string, options?: IsNumericOptions): boolean; /** * Check if the string is a valid octal number. */ - function isOctal(str: string): boolean; + export function isOctal(str: string): boolean; /** * Check if the string is a valid passport number relative to a specific country code. * * @param [countryCode] - Country code */ - function isPassportNumber(str: string, countryCode?: string): boolean; + export function isPassportNumber(str: string, countryCode?: string): boolean; /** * Check if the string is a valid port number. */ - function isPort(str: string): boolean; + export function isPort(str: string): boolean; - type PostalCodeLocale = + export type PostalCodeLocale = | "AD" | "AT" | "AU" @@ -1095,25 +1095,25 @@ declare namespace validator { | "ZA" | "ZM"; - const isPostalCodeLocales: PostalCodeLocale[]; + export const isPostalCodeLocales: PostalCodeLocale[]; /** * Check if the string is a postal code * * @param locale - PostalCodeLocale */ - function isPostalCode(str: string, locale: "any" | PostalCodeLocale): boolean; + export function isPostalCode(str: string, locale: "any" | PostalCodeLocale): boolean; /** * Check if the string is a Semantic Versioning Specification (SemVer). */ - function isSemVer(str: string): boolean; + export function isSemVer(str: string): boolean; /** * Check if string is considered a strong password. Allows options to be added */ - interface StrongPasswordOptions { + export interface StrongPasswordOptions { minLength?: number | undefined; minLowercase?: number | undefined; minUppercase?: number | undefined; @@ -1128,18 +1128,18 @@ declare namespace validator { pointsForContainingSymbol?: number | undefined; } - function isStrongPassword( + export function isStrongPassword( str: string, options?: StrongPasswordOptions & { returnScore?: false | undefined }, ): boolean; - function isStrongPassword(str: string, options: StrongPasswordOptions & { returnScore: true }): number; + export function isStrongPassword(str: string, options: StrongPasswordOptions & { returnScore: true }): number; /** * Check if the string contains any surrogate pairs chars. */ - function isSurrogatePair(str: string): boolean; + export function isSurrogatePair(str: string): boolean; - interface IsTimeOptions { + export interface IsTimeOptions { /** * 'hour24' will validate hours in 24 format and 'hour12' will validate hours in 12 format. * @default 'hour24' @@ -1156,61 +1156,61 @@ declare namespace validator { /** * Check if the string is a valid time. */ - function isTime(str: string, options?: IsTimeOptions): boolean; + export function isTime(str: string, options?: IsTimeOptions): boolean; - const isURL: typeof _isURL.default; - type IsURLOptions = _isURL.IsURLOptions; + export const isURL: typeof _isURL.default; + export type IsURLOptions = _isURL.IsURLOptions; - const isTaxID: typeof _isTaxID.default; + export const isTaxID: typeof _isTaxID.default; /** * Check if the string is uppercase. */ - function isUppercase(str: string): boolean; + export function isUppercase(str: string): boolean; - type UUIDVersion = "1" | "2" | "3" | "4" | "5" | "all" | 1 | 2 | 3 | 4 | 5; + export type UUIDVersion = "1" | "2" | "3" | "4" | "5" | "all" | 1 | 2 | 3 | 4 | 5; /** * Check if the string is a UUID (version 1, 2, 3, 4 or 5). * * @param [version="all"] - UUID version */ - function isUUID(str: string, version?: UUIDVersion): boolean; + export function isUUID(str: string, version?: UUIDVersion): boolean; /** * Check if the string contains a mixture of full and half-width chars. */ - function isVariableWidth(str: string): boolean; + export function isVariableWidth(str: string): boolean; /** * Checks that the string is a [valid VAT number */ - function isVAT(str: string, countryCode: string): boolean; + export function isVAT(str: string, countryCode: string): boolean; /** * Checks characters if they appear in the whitelist. * * @param chars - whitelist */ - function isWhitelisted(str: string, chars: string | string[]): boolean; + export function isWhitelisted(str: string, chars: string | string[]): boolean; /** * Check if string matches the pattern. * * @param pattern - `/foo/i` */ - function matches(str: string, pattern: RegExp): boolean; + export function matches(str: string, pattern: RegExp): boolean; /** * Check if string matches the pattern. * * @param pattern - `'foo'` * @param [modifiers] - `'i'` */ - function matches(str: string, pattern: string, modifiers?: string): boolean; + export function matches(str: string, pattern: string, modifiers?: string): boolean; /** - * Check if the string is of type slug. + * Check if the string is of export type slug. */ - function isSlug(str: string): boolean; + export function isSlug(str: string): boolean; /****************** *** Sanitizers *** @@ -1221,26 +1221,26 @@ declare namespace validator { * * @param chars - The characters are used in a `RegExp` and so you will need to escape some chars, e.g. `blacklist(input, '\\[\\]')`. */ - function blacklist(input: string, chars: string): string; + export function blacklist(input: string, chars: string): string; /** * Replace `<`, `>`, `&`, `'`, `"` and `/` with HTML entities. */ - function escape(input: string): string; + export function escape(input: string): string; /** * Replaces HTML encoded entities with `<`, `>`, `&`, `'`, `"` and `/`. */ - function unescape(input: string): string; + export function unescape(input: string): string; /** * Trim characters from the left-side of the input. * * @param [chars] - characters (defaults to whitespace) */ - function ltrim(input: string, chars?: string): string; + export function ltrim(input: string, chars?: string): string; - interface NormalizeEmailOptions { + export interface NormalizeEmailOptions { /** * Transforms the local part (before the @ symbol) of all email addresses to lowercase. * Please note that this may violate RFC 5321, which gives providers the possibility @@ -1327,14 +1327,14 @@ declare namespace validator { * * @param [options] - Options */ - function normalizeEmail(email: string, options?: NormalizeEmailOptions): string | false; + export function normalizeEmail(email: string, options?: NormalizeEmailOptions): string | false; /** * Trim characters from the right-side of the input. * * @param [chars] - characters (defaults to whitespace) */ - function rtrim(input: string, chars?: string): string; + export function rtrim(input: string, chars?: string): string; /** * Remove characters with a numerical value < `32` and `127`, mostly control characters. @@ -1342,7 +1342,7 @@ declare namespace validator { * * @param [keep_new_lines=false] - if `true`, newline characters are preserved (`\n` and `\r`, hex `0xA` and `0xD`). */ - function stripLow(input: string, keep_new_lines?: boolean): string; + export function stripLow(input: string, keep_new_lines?: boolean): string; /** * Convert the input string to a boolean. @@ -1350,44 +1350,50 @@ declare namespace validator { * * @param [strict=false] - in `strict` mode, only `'1'` and `'true'` return `true`. */ - function toBoolean(input: string, strict?: boolean): boolean; + export function toBoolean(input: string, strict?: boolean): boolean; /** * Convert the input string to a `Date`, or `null` if the input is not a date. */ - function toDate(input: string): Date | null; + export function toDate(input: string): Date | null; /** * Convert the input string to a float, or `NaN` if the input is not a float. */ - function toFloat(input: string): number; + export function toFloat(input: string): number; /** * Convert the input string to an integer, or `NaN` if the input is not an integer. * * @param [radix=10] - radix or base (defaults to 10) */ - function toInt(input: string, radix?: number): number; + export function toInt(input: string, radix?: number): number; /** * Trim characters from both sides of the input. * * @param [chars] - characters (defaults to whitespace) */ - function trim(input: string, chars?: string): string; + export function trim(input: string, chars?: string): string; /** * Remove characters that do not appear in the whitelist. * * @param chars - The characters are used in a `RegExp` and so you will need to escape some chars, e.g. `whitelist(input, '\\[\\]')`. */ - function whitelist(input: string, chars: string): string; + export function whitelist(input: string, chars: string): string; /** * Converts to string. */ - function toString(input: any): string; + export function toString(input: any): string; + + export const _default: typeof validator; + + export { _default as default }; } -export default validator; + +// eslint-disable-next-line @definitelytyped/export-just-namespace +export = validator; export as namespace validator; diff --git a/types/validator/lib/isBoolean.d.ts b/types/validator/lib/isBoolean.d.ts index 99bf4b1b224e2d..e6b205aec5da4c 100644 --- a/types/validator/lib/isBoolean.d.ts +++ b/types/validator/lib/isBoolean.d.ts @@ -1,4 +1,3 @@ -import validator from "../"; /** * check if a string is a boolean. */ From fba2208ba57cf9d675dc8de2cbca975b5b57b5cc Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 9 Jan 2024 22:11:45 +0100 Subject: [PATCH 12/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68117=20fix:?= =?UTF-8?q?=20missing=20factory=20parameter=20by=20@tpluscode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: missing factory parameter * style: pretty print * style: format --- types/clownface/clownface-tests.ts | 13 +++++++++++++ types/clownface/index.d.ts | 17 +++++++++++++++-- types/clownface/package.json | 5 +++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/types/clownface/clownface-tests.ts b/types/clownface/clownface-tests.ts index e5211f925ce8ad..44891c3a03c529 100644 --- a/types/clownface/clownface-tests.ts +++ b/types/clownface/clownface-tests.ts @@ -1,3 +1,4 @@ +import DataFactory from "@rdfjs/data-model/Factory.js"; import DatasetFactory from "@rdfjs/dataset/Factory.js"; import Environment from "@rdfjs/environment/Environment.js"; import { BlankNode, Dataset, DatasetCore, Literal, NamedNode, Quad_Graph, Term, Variable } from "@rdfjs/types"; @@ -196,6 +197,18 @@ function testFactory() { const namedNodeContext: AnyPointer = {}; const deriveContextFromOtherNamedNodeContext: AnyPointer = clownface(namedNodeContext); + + const factory = new Environment([ + DatasetFactory, + DataFactory, + ]); + const withFactory = clownface({ dataset, factory }); + + const incompatibleFactory = new Environment([ + DataFactory, + ]); + // @ts-expect-error + const withIncompatibleFactory = clownface({ dataset, factory: incompatibleFactory }); } function testFilter() { diff --git a/types/clownface/index.d.ts b/types/clownface/index.d.ts index 74b19eeb5f303c..886626fa572f10 100644 --- a/types/clownface/index.d.ts +++ b/types/clownface/index.d.ts @@ -1,4 +1,14 @@ -import { BlankNode, DatasetCore, DatasetCoreFactory, Literal, NamedNode, Quad_Graph, Term } from "@rdfjs/types"; +import { Environment } from "@rdfjs/environment/Environment.js"; +import { + BlankNode, + DataFactory, + DatasetCore, + DatasetCoreFactory, + Literal, + NamedNode, + Quad_Graph, + Term, +} from "@rdfjs/types"; import Context from "./lib/Context.js"; export type AnyContext = Term | Term[] | undefined; @@ -20,7 +30,10 @@ interface NodeOptions { } export type ClownfaceInit = Partial< - Pick, "dataset" | "_context"> & { graph: Quad_Graph } + Pick, "dataset" | "_context"> & { + graph: Quad_Graph; + factory: Environment; + } >; type Iteratee = T extends undefined ? never diff --git a/types/clownface/package.json b/types/clownface/package.json index dc982196085e45..4e6e681c6edc0a 100644 --- a/types/clownface/package.json +++ b/types/clownface/package.json @@ -7,12 +7,13 @@ ], "type": "module", "dependencies": { - "@rdfjs/types": ">=1.0.0" + "@rdfjs/types": ">=1.0.0", + "@types/rdfjs__environment": "*" }, "devDependencies": { "@types/clownface": "workspace:.", "@types/rdfjs__dataset": "*", - "@types/rdfjs__environment": "*" + "@types/rdfjs__data-model": "*" }, "owners": [ { From f172eeac7cf6dd18c7560c832a0202fffc1e9a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lazar=20Ljubenovi=C4=87?= Date: Wed, 10 Jan 2024 09:48:55 +0100 Subject: [PATCH 13/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68094=20[sin?= =?UTF-8?q?on]=20Fix=20`calledOnceWithMatch`=20to=20accept=20match-like=20?= =?UTF-8?q?arguments=20by=20@lazarljubenovic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [sinon] Fix `calledOnceWithMatch` to accept match-like arguments * add tests --- types/sinon/index.d.ts | 2 +- types/sinon/sinon-tests.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/types/sinon/index.d.ts b/types/sinon/index.d.ts index 667ece2b149526..4873d32b1b62b3 100644 --- a/types/sinon/index.d.ts +++ b/types/sinon/index.d.ts @@ -1165,7 +1165,7 @@ declare namespace Sinon { */ calledOnceWithMatch( spyOrSpyCall: SinonSpy | SinonSpyCall, - ...args: TArgs + ...args: MatchPartialArguments ): void; /** * Passes if spy was always called with matching arguments. diff --git a/types/sinon/sinon-tests.ts b/types/sinon/sinon-tests.ts index 5c931af339d9b3..b8568517f62ba5 100644 --- a/types/sinon/sinon-tests.ts +++ b/types/sinon/sinon-tests.ts @@ -396,6 +396,7 @@ function testAssert() { sinon.assert.calledWithMatch(spy, "a", "b", "c"); sinon.assert.calledWithMatch(spy.firstCall, "a", "b", "c"); sinon.assert.calledOnceWithMatch(spy, "a", "b", "c"); + sinon.assert.calledOnceWithMatch(spy, sinon.match("a"), "b", "c"); sinon.assert.calledOnceWithMatch(spy.firstCall, "a", "b", "c"); sinon.assert.alwaysCalledWithMatch(spy, "a", "b", "c"); sinon.assert.neverCalledWithMatch(spy, "a", "b", "c"); From bd172f1543eaf8d91de430837a9f45cc214a51bd Mon Sep 17 00:00:00 2001 From: dave caruso Date: Wed, 10 Jan 2024 02:59:35 -0800 Subject: [PATCH 14/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68155=20upda?= =?UTF-8?q?te=20`@types/bun`=20to=201.0.21=20by=20@paperdave?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/bun/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/bun/package.json b/types/bun/package.json index 9cae92cc6f4c18..c0898c26ae8bc6 100644 --- a/types/bun/package.json +++ b/types/bun/package.json @@ -6,7 +6,7 @@ "https://bun.sh" ], "dependencies": { - "bun-types": "1.0.18" + "bun-types": "1.0.21" }, "devDependencies": { "@types/bun": "workspace:." From c337f927157c094203e8836b76c17b00ce79f6d3 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 10 Jan 2024 17:36:11 +0100 Subject: [PATCH 15/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#67988=20[rea?= =?UTF-8?q?ct-sticky-el]=20Allow=20any=20host=20component=20`*Cmp`=20props?= =?UTF-8?q?=20by=20@eps1lon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [react-sticky-el] Allow any host component `*Cmp` props `ReactHTML` will be removed soon. It also needlessly restricts components to known HTML components when probably any host component was meant. This allows custom elements. * Add test --- types/react-sticky-el/index.d.ts | 4 ++-- types/react-sticky-el/react-sticky-el-tests.tsx | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/types/react-sticky-el/index.d.ts b/types/react-sticky-el/index.d.ts index 8099608943d1ee..60a775a1dd557b 100644 --- a/types/react-sticky-el/index.d.ts +++ b/types/react-sticky-el/index.d.ts @@ -34,7 +34,7 @@ declare namespace Sticky { * * Defaults to 'div'. */ - wrapperCmp?: keyof React.ReactHTML | React.ReactElement | undefined; + wrapperCmp?: keyof React.JSX.IntrinsicElements | React.ReactElement | undefined; /** * Anything that can be used by React.createElement. Used for holder @@ -43,7 +43,7 @@ declare namespace Sticky { * * Defaults to 'div'. */ - holderCmp?: keyof React.ReactHTML | React.ReactElement | undefined; + holderCmp?: keyof React.JSX.IntrinsicElements | React.ReactElement | undefined; /** * These props will be used to create `holderElement`. diff --git a/types/react-sticky-el/react-sticky-el-tests.tsx b/types/react-sticky-el/react-sticky-el-tests.tsx index 522802945a4b04..6f159f356270f1 100644 --- a/types/react-sticky-el/react-sticky-el-tests.tsx +++ b/types/react-sticky-el/react-sticky-el-tests.tsx @@ -1,6 +1,14 @@ import * as React from "react"; import Sticky from "react-sticky-el"; +declare module "react" { + namespace JSX { + interface IntrinsicElements { + "custom-element": unknown; + } + } +} + const StickyBasic = () => ; const StickyAllFeatures = () => ( ( children="a child" /> ); + +; From 3f2140b28191a96992e46becf412d0072d48fd02 Mon Sep 17 00:00:00 2001 From: Eldar B Date: Wed, 10 Jan 2024 23:41:44 +0200 Subject: [PATCH 16/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68049=20add?= =?UTF-8?q?=20react-tree-graph=20types=20by=20@PCOffline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add react-tree-graph types * chore: add myself as owner * chore: change owner name * format code * style: format index.d.ts * chore: remove unused tests file * feat: add override props & node id to event listener * style: format file * feat: add source & target node IDs to pathProps --------- Co-authored-by: Eldar Bakerman --- types/react-tree-graph/.npmignore | 5 ++ types/react-tree-graph/index.d.ts | 67 +++++++++++++++ types/react-tree-graph/package.json | 20 +++++ .../react-tree-graph-tests.tsx | 85 +++++++++++++++++++ types/react-tree-graph/tsconfig.json | 21 +++++ 5 files changed, 198 insertions(+) create mode 100644 types/react-tree-graph/.npmignore create mode 100644 types/react-tree-graph/index.d.ts create mode 100644 types/react-tree-graph/package.json create mode 100644 types/react-tree-graph/react-tree-graph-tests.tsx create mode 100644 types/react-tree-graph/tsconfig.json diff --git a/types/react-tree-graph/.npmignore b/types/react-tree-graph/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/react-tree-graph/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/react-tree-graph/index.d.ts b/types/react-tree-graph/index.d.ts new file mode 100644 index 00000000000000..a02d7c3dcbff51 --- /dev/null +++ b/types/react-tree-graph/index.d.ts @@ -0,0 +1,67 @@ +import type { FC, HTMLProps, ReactNode } from "react"; + +type EventListenerWithNodeId = T extends ((this: infer ListenerThis, ev: infer Event) => infer ListenerReturnType) + ? (this: ListenerThis, ev: Event, nodeId: string) => ListenerReturnType + : T; + +type EventListenerWithPathsId = T extends ((this: infer ListenerThis, ev: infer Event) => infer ListenerReturnType) + ? (this: ListenerThis, ev: Event, sourceNodeId: string, targetNodeId: string) => ListenerReturnType + : T; + +type AddPathsIdToElementEvents = { + [K in keyof T]: K extends `on${string}` ? EventListenerWithPathsId : T[K]; +}; + +type AddNodeIdToElementEvents = { + [K in keyof T]: K extends `on${string}` ? EventListenerWithNodeId : T[K]; +}; + +interface NodeProps { + keyProp?: string; + labelProp?: string; + shape?: "circle" | "image" | "polygon" | "rect"; + nodeProps?: + | AddNodeIdToElementEvents> + | AddNodeIdToElementEvents> + | AddNodeIdToElementEvents> + | AddNodeIdToElementEvents>; + gProps?: AddNodeIdToElementEvents>; + pathProps?: AddPathsIdToElementEvents>; + textProps?: AddNodeIdToElementEvents>; +} + +type R = NodeProps["gProps"]; + +interface Data extends NodeProps { + name: string; + children: Data[]; +} + +interface TreeProps extends Omit { + data: Data; + children?: ReactNode; + direction?: "ltr" | "rtl"; + getChildren?: (node: Data) => Data[]; + height: number; + width: number; + nodeShape?: NodeProps["shape"]; + margins?: { + bottom: number; + left: number; + right: number; + top: number; + }; + pathFunc?: (x1: number, y1: number, x2: number, y2: number) => string; + svgProps?: HTMLProps; +} + +interface AnimatedTreeProps extends TreeProps { + duration?: number; + easing?: (t: number) => number; + steps?: number; +} + +declare const Tree: FC; +declare const AnimatedTree: FC; + +export { AnimatedTree, AnimatedTreeProps, Data, Tree, TreeProps }; diff --git a/types/react-tree-graph/package.json b/types/react-tree-graph/package.json new file mode 100644 index 00000000000000..8fcf0d5dea2cd0 --- /dev/null +++ b/types/react-tree-graph/package.json @@ -0,0 +1,20 @@ +{ + "private": true, + "name": "@types/react-tree-graph", + "version": "8.0.9999", + "projects": [ + "https://jpb12.github.io/react-tree-graph" + ], + "dependencies": { + "@types/react": "*" + }, + "devDependencies": { + "@types/react-tree-graph": "workspace:." + }, + "owners": [ + { + "name": "PCOffline", + "githubUsername": "PCOffline" + } + ] +} diff --git a/types/react-tree-graph/react-tree-graph-tests.tsx b/types/react-tree-graph/react-tree-graph-tests.tsx new file mode 100644 index 00000000000000..68487cfc972ddd --- /dev/null +++ b/types/react-tree-graph/react-tree-graph-tests.tsx @@ -0,0 +1,85 @@ +import * as React from "react"; +import { AnimatedTree, Data, Tree } from "react-tree-graph"; + +const missingTreeProps = () => ( + // @ts-expect-error + +); + +const missingAnimatedTreeProps = () => ( + // @ts-expect-error + +); + +// @ts-expect-error +const invalidData: Data = []; +// @ts-expect-error +const invalidData2: Data = {}; +// @ts-expect-error +const invalidData3: Data = { name: 123, children: [] }; + +const data: Data = { name: "sample name", children: [] }; +const data2: Data = { name: "sample name", children: [data] }; + +const basicTree = () => ; + +const basicAnimatedTree = () => ; + +const complexTree = () => ( + node.children} + labelProp="name" + keyProp="id" + margins={{ top: 5, bottom: 5, right: 2, left: 2 }} + pathProps={{ + onFocus: (event, sourceNodeId, targetNodeId) => { + // $ExpectType string + sourceNodeId; + // $ExpectType string + targetNodeId; + }, + }} + textProps={{ color: "red" }} + gProps={{ autoFocus: true }} + nodeProps={{ disabled: true }} + /> +); + +const animatedTree = () => ( + t * 2} + steps={500} + /> +); + +const complexAnimatedTree = () => ( + t * 2} + steps={500} + nodeShape="circle" + direction="ltr" + getChildren={(node) => node.children} + textProps={{ color: "red" }} + gProps={{ + autoFocus: true, + onClick: (event, nodeId) => { + // $ExpectType string + nodeId; + }, + }} + nodeProps={{ disabled: true }} + /> +); diff --git a/types/react-tree-graph/tsconfig.json b/types/react-tree-graph/tsconfig.json new file mode 100644 index 00000000000000..704f9835e0e260 --- /dev/null +++ b/types/react-tree-graph/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6", + "DOM" + ], + "jsx": "react", + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "react-tree-graph-tests.tsx" + ] +} From 918176341954270398abf329116187dd37f036e7 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Wed, 10 Jan 2024 23:04:55 +0100 Subject: [PATCH 17/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68159=20rdf-?= =?UTF-8?q?utils-fs:=20remove=20rdf-js=20by=20@tpluscode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * rdf-utils-fs: remove rdf-js * style: format --- types/rdf-utils-fs/fromFile.d.ts | 2 +- types/rdf-utils-fs/package.json | 2 +- types/rdf-utils-fs/rdf-utils-fs-tests.ts | 2 +- types/rdf-utils-fs/toFile.d.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/types/rdf-utils-fs/fromFile.d.ts b/types/rdf-utils-fs/fromFile.d.ts index bea8a99e51eab7..8406d321561ac1 100644 --- a/types/rdf-utils-fs/fromFile.d.ts +++ b/types/rdf-utils-fs/fromFile.d.ts @@ -1,5 +1,5 @@ +import { Stream } from "@rdfjs/types"; import { PathLike } from "fs"; -import { Stream } from "rdf-js"; import defaults = require("./defaults"); type Options = Record & { diff --git a/types/rdf-utils-fs/package.json b/types/rdf-utils-fs/package.json index 69b11419b120e8..e8a16c561ffd88 100644 --- a/types/rdf-utils-fs/package.json +++ b/types/rdf-utils-fs/package.json @@ -6,7 +6,7 @@ "https://github.com/rdf-ext/rdf-utils-fs" ], "dependencies": { - "rdf-js": "^4.0.2" + "@rdfjs/types": ">=1.0.0" }, "devDependencies": { "@types/node": "*", diff --git a/types/rdf-utils-fs/rdf-utils-fs-tests.ts b/types/rdf-utils-fs/rdf-utils-fs-tests.ts index 45bf6478fbbfed..e4c4af0e885b0d 100644 --- a/types/rdf-utils-fs/rdf-utils-fs-tests.ts +++ b/types/rdf-utils-fs/rdf-utils-fs-tests.ts @@ -1,5 +1,5 @@ import rdfUtilsFs = require("rdf-utils-fs"); -import { Stream } from "rdf-js"; +import { Stream } from "@rdfjs/types"; import { URL } from "url"; let fromFile: Stream = rdfUtilsFs.fromFile("./file/path"); diff --git a/types/rdf-utils-fs/toFile.d.ts b/types/rdf-utils-fs/toFile.d.ts index f86c07e205a7cb..f79dd5b2cbda7c 100644 --- a/types/rdf-utils-fs/toFile.d.ts +++ b/types/rdf-utils-fs/toFile.d.ts @@ -1,5 +1,5 @@ +import { Stream } from "@rdfjs/types"; import { PathLike } from "fs"; -import { Stream } from "rdf-js"; import defaults = require("./defaults"); type Options = Record & { From 32f1650484c48b807304746b58fd2dff10c415f3 Mon Sep 17 00:00:00 2001 From: JounQin Date: Thu, 11 Jan 2024 09:37:53 +0800 Subject: [PATCH 18/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#67950=20feat?= =?UTF-8?q?(eslint):=20add=20`context.languageOptions`=20for=20FlatConfig?= =?UTF-8?q?=20rules=20by=20@JounQin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/eslint/eslint-tests.ts | 6 ++++++ types/eslint/index.d.ts | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts index 6bc0a5e8851f7e..063ce938da45bf 100644 --- a/types/eslint/eslint-tests.ts +++ b/types/eslint/eslint-tests.ts @@ -440,6 +440,12 @@ rule = { context.getScope(); + if (typeof context.parserPath === "string") { + context.parserPath; + } else { + context.languageOptions?.parser; + } + context.markVariableAsUsed("foo"); context.report({ message: "foo", node: AST }); diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts index 75ae420e38148c..3af1c5a76c2268 100644 --- a/types/eslint/index.d.ts +++ b/types/eslint/index.d.ts @@ -753,7 +753,8 @@ export namespace Rule { id: string; options: any[]; settings: { [name: string]: any }; - parserPath: string; + parserPath: string | undefined; + languageOptions: Linter.FlatConfig["languageOptions"]; parserOptions: Linter.ParserOptions; parserServices: SourceCode.ParserServices; cwd: string; From 68f9e9631c69bc86edb442c379332c1c7417d213 Mon Sep 17 00:00:00 2001 From: Dmitry Semigradsky Date: Thu, 11 Jan 2024 08:29:41 +0300 Subject: [PATCH 19/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68157=20[nod?= =?UTF-8?q?e]=20Update=20types=20to=20v20.11=20by=20@Semigradsky?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/nodejs/node/releases/tag/v20.11.0 - esm: add import.meta.dirname and import.meta.filename - test_runner: adds built in lcov reporter --- types/node/buffer.d.ts | 2 +- types/node/crypto.d.ts | 7 +-- types/node/dgram.d.ts | 8 ++-- types/node/http.d.ts | 13 +++--- types/node/module.d.ts | 14 ++++++ types/node/package.json | 2 +- types/node/perf_hooks.d.ts | 18 +++++--- types/node/process.d.ts | 11 +++-- types/node/querystring.d.ts | 6 +-- types/node/test.d.ts | 72 ++++++++++++++++++++++++++----- types/node/test/test.ts | 4 +- types/node/ts4.8/buffer.d.ts | 2 +- types/node/ts4.8/crypto.d.ts | 7 +-- types/node/ts4.8/dgram.d.ts | 8 ++-- types/node/ts4.8/http.d.ts | 13 +++--- types/node/ts4.8/module.d.ts | 14 ++++++ types/node/ts4.8/perf_hooks.d.ts | 20 ++++++--- types/node/ts4.8/process.d.ts | 11 +++-- types/node/ts4.8/querystring.d.ts | 6 +-- types/node/ts4.8/test.d.ts | 72 ++++++++++++++++++++++++++----- types/node/ts4.8/wasi.d.ts | 14 +++--- types/node/wasi.d.ts | 14 +++--- 22 files changed, 251 insertions(+), 87 deletions(-) diff --git a/types/node/buffer.d.ts b/types/node/buffer.d.ts index 1ee5c013552af2..2fa2e745ffbedb 100644 --- a/types/node/buffer.d.ts +++ b/types/node/buffer.d.ts @@ -564,7 +564,7 @@ declare module "buffer" { * * The `Buffer` module pre-allocates an internal `Buffer` instance of * size `Buffer.poolSize` that is used as a pool for the fast allocation of new`Buffer` instances created using `Buffer.allocUnsafe()`, `Buffer.from(array)`, - * and `Buffer.concat()` only when `size` is less than or equal to`Buffer.poolSize >> 1` (floor of `Buffer.poolSize` divided by two). + * and `Buffer.concat()` only when `size` is less than`Buffer.poolSize >>> 1` (floor of `Buffer.poolSize` divided by two). * * Use of this pre-allocated internal memory pool is a key difference between * calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. diff --git a/types/node/crypto.d.ts b/types/node/crypto.d.ts index e847507f2d8b59..638f9dc406a194 100644 --- a/types/node/crypto.d.ts +++ b/types/node/crypto.d.ts @@ -638,9 +638,10 @@ declare module "crypto" { export(options?: KeyExportOptions<"der">): Buffer; export(options?: JwkKeyExportOptions): JsonWebKey; /** - * Returns `true` or `false` depending on whether the keys have exactly the same type, value, and parameters. - * This method is not [constant time](https://en.wikipedia.org/wiki/Timing_attack). - * @since v16.15.0 + * Returns `true` or `false` depending on whether the keys have exactly the same + * type, value, and parameters. This method is not [constant time](https://en.wikipedia.org/wiki/Timing_attack). + * @since v17.7.0, v16.15.0 + * @param otherKeyObject A `KeyObject` with which to compare `keyObject`. */ equals(otherKeyObject: KeyObject): boolean; /** diff --git a/types/node/dgram.d.ts b/types/node/dgram.d.ts index ecbb6cf1382081..0b86ae735a2853 100644 --- a/types/node/dgram.d.ts +++ b/types/node/dgram.d.ts @@ -228,13 +228,13 @@ declare module "dgram" { */ getSendBufferSize(): number; /** - * @since v18.8.0,v16.19.0 - * @return the number of bytes queued for sending. + * @since v18.8.0, v16.19.0 + * @return Number of bytes queued for sending. */ getSendQueueSize(): number; /** - * @since v18.8.0,v16.19.0 - * @return the number of send requests currently in the queue awaiting to be processed. + * @since v18.8.0, v16.19.0 + * @return Number of send requests currently in the queue awaiting to be processed. */ getSendQueueCount(): number; /** diff --git a/types/node/http.d.ts b/types/node/http.d.ts index 9b2c3c2c6be6cd..710fe59423d657 100644 --- a/types/node/http.d.ts +++ b/types/node/http.d.ts @@ -9,12 +9,12 @@ * * HTTP message headers are represented by an object like this: * - * ```js - * { 'content-length': '123', - * 'content-type': 'text/plain', - * 'connection': 'keep-alive', - * 'host': 'example.com', - * 'accept': '*' } + * ```json + * { "content-length": "123", + * "content-type": "text/plain", + * "connection": "keep-alive", + * "host": "example.com", + * "accept": "*" } * ``` * * Keys are lowercased. Values are not modified. @@ -1814,7 +1814,6 @@ declare module "http" { * * It is not necessary to use this method before passing headers to an HTTP request * or response. The HTTP module will automatically validate such headers. - * Examples: * * Example: * diff --git a/types/node/module.d.ts b/types/node/module.d.ts index 68d59c7737bda5..1779e236c3d916 100644 --- a/types/node/module.d.ts +++ b/types/node/module.d.ts @@ -276,6 +276,20 @@ declare module "module" { } global { interface ImportMeta { + /** + * The directory name of the current module. This is the same as the `path.dirname()` of the `import.meta.filename`. + * **Caveat:** only present on `file:` modules. + */ + dirname?: string; + /** + * The full absolute path and filename of the current module, with symlinks resolved. + * This is the same as the `url.fileURLToPath()` of the `import.meta.url`. + * **Caveat:** only local modules support this property. Modules not using the `file:` protocol will not provide it. + */ + filename?: string; + /** + * The absolute `file:` URL of the module. + */ url: string; /** * Provides a module-relative resolution function scoped to each module, returning diff --git a/types/node/package.json b/types/node/package.json index edba842abb8b5b..193ccfeeef0e5d 100644 --- a/types/node/package.json +++ b/types/node/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@types/node", - "version": "20.10.9999", + "version": "20.11.9999", "nonNpm": true, "nonNpmDescription": "Node.js", "projects": [ diff --git a/types/node/perf_hooks.d.ts b/types/node/perf_hooks.d.ts index b369bb6944cb61..c0ce852a97b285 100644 --- a/types/node/perf_hooks.d.ts +++ b/types/node/perf_hooks.d.ts @@ -314,13 +314,15 @@ declare module "perf_hooks" { * * name: 'test', * * entryType: 'mark', * * startTime: 81.465639, - * * duration: 0 + * * duration: 0, + * * detail: null * * }, * * PerformanceEntry { * * name: 'meow', * * entryType: 'mark', * * startTime: 81.860064, - * * duration: 0 + * * duration: 0, + * * detail: null * * } * * ] * @@ -355,7 +357,8 @@ declare module "perf_hooks" { * * name: 'meow', * * entryType: 'mark', * * startTime: 98.545991, - * * duration: 0 + * * duration: 0, + * * detail: null * * } * * ] * @@ -368,7 +371,8 @@ declare module "perf_hooks" { * * name: 'test', * * entryType: 'mark', * * startTime: 63.518931, - * * duration: 0 + * * duration: 0, + * * detail: null * * } * * ] * @@ -404,13 +408,15 @@ declare module "perf_hooks" { * * name: 'test', * * entryType: 'mark', * * startTime: 55.897834, - * * duration: 0 + * * duration: 0, + * * detail: null * * }, * * PerformanceEntry { * * name: 'meow', * * entryType: 'mark', * * startTime: 56.350146, - * * duration: 0 + * * duration: 0, + * * detail: null * * } * * ] * diff --git a/types/node/process.d.ts b/types/node/process.d.ts index 0e2747376fc359..376b5417409130 100644 --- a/types/node/process.d.ts +++ b/types/node/process.d.ts @@ -903,9 +903,14 @@ declare module "process" { */ readonly sourceMapsEnabled: boolean; /** - * This function enables or disables the Source Map v3 support for stack traces. - * It provides same features as launching Node.js process with commandline options --enable-source-maps. - * @since v16.6.0 + * This function enables or disables the [Source Map v3](https://sourcemaps.info/spec.html) support for + * stack traces. + * + * It provides same features as launching Node.js process with commandline options`--enable-source-maps`. + * + * Only source maps in JavaScript files that are loaded after source maps has been + * enabled will be parsed and loaded. + * @since v16.6.0, v14.18.0 * @experimental */ setSourceMapsEnabled(value: boolean): void; diff --git a/types/node/querystring.d.ts b/types/node/querystring.d.ts index 54ecc967fff6e6..b36ea2c13014b6 100644 --- a/types/node/querystring.d.ts +++ b/types/node/querystring.d.ts @@ -74,10 +74,10 @@ declare module "querystring" { * * For example, the query string `'foo=bar&abc=xyz&abc=123'` is parsed into: * - * ```js + * ```json * { - * foo: 'bar', - * abc: ['xyz', '123'] + * "foo": "bar", + * "abc": ["xyz", "123"] * } * ``` * diff --git a/types/node/test.d.ts b/types/node/test.d.ts index 44b6a96408bf8f..95ce769dd2b6ed 100644 --- a/types/node/test.d.ts +++ b/types/node/test.d.ts @@ -82,6 +82,11 @@ declare module "node:test" { import { Readable } from "node:stream"; import { AsyncResource } from "node:async_hooks"; /** + * **Note:**`shard` is used to horizontally parallelize test running across + * machines or processes, ideal for large-scale executions across varied + * environments. It's incompatible with `watch` mode, tailored for rapid + * code iteration by automatically rerunning tests on file changes. + * * ```js * import { tap } from 'node:test/reporters'; * import { run } from 'node:test'; @@ -1013,6 +1018,8 @@ declare module "node:test" { * control the behavior of timers, such as `setInterval` and `setTimeout`, * without actually waiting for the specified time intervals. * + * MockTimers is also able to mock the `Date` object. + * * The `MockTracker` provides a top-level `timers` export * which is a `MockTimers` instance. * @since v20.4.0 @@ -1025,21 +1032,38 @@ declare module "node:test" { * **Note:** When you enable mocking for a specific timer, its associated * clear function will also be implicitly mocked. * - * Example usage: + * **Note:** Mocking `Date` will affect the behavior of the mocked timers + * as they use the same internal clock. + * + * Example usage without setting initial time: * * ```js * import { mock } from 'node:test'; - * mock.timers.enable(['setInterval']); + * mock.timers.enable({ apis: ['setInterval'] }); * ``` * * The above example enables mocking for the `setInterval` timer and * implicitly mocks the `clearInterval` function. Only the `setInterval`and `clearInterval` functions from `node:timers`,`node:timers/promises`, and`globalThis` will be mocked. * + * Example usage with initial time set + * + * ```js + * import { mock } from 'node:test'; + * mock.timers.enable({ apis: ['Date'], now: 1000 }); + * ``` + * + * Example usage with initial Date object as time set + * + * ```js + * import { mock } from 'node:test'; + * mock.timers.enable({ apis: ['Date'], now: new Date() }); + * ``` + * * Alternatively, if you call `mock.timers.enable()` without any parameters: * * All timers (`'setInterval'`, `'clearInterval'`, `'setTimeout'`, and `'clearTimeout'`) * will be mocked. The `setInterval`, `clearInterval`, `setTimeout`, and `clearTimeout`functions from `node:timers`, `node:timers/promises`, - * and `globalThis` will be mocked. + * and `globalThis` will be mocked. As well as the global `Date` object. * @since v20.4.0 */ enable(timers?: Timer[]): void; @@ -1076,7 +1100,7 @@ declare module "node:test" { * test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { * const fn = context.mock.fn(); * - * context.mock.timers.enable(['setTimeout']); + * context.mock.timers.enable({ apis: ['setTimeout'] }); * * setTimeout(fn, 9999); * @@ -1097,7 +1121,7 @@ declare module "node:test" { * * test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { * const fn = context.mock.fn(); - * context.mock.timers.enable(['setTimeout']); + * context.mock.timers.enable({ apis: ['setTimeout'] }); * const nineSecs = 9000; * setTimeout(fn, nineSecs); * @@ -1109,11 +1133,35 @@ declare module "node:test" { * assert.strictEqual(fn.mock.callCount(), 1); * }); * ``` + * + * Advancing time using `.tick` will also advance the time for any `Date` object + * created after the mock was enabled (if `Date` was also set to be mocked). + * + * ```js + * import assert from 'node:assert'; + * import { test } from 'node:test'; + * + * test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + * const fn = context.mock.fn(); + * + * context.mock.timers.enable({ apis: ['setTimeout', 'Date'] }); + * setTimeout(fn, 9999); + * + * assert.strictEqual(fn.mock.callCount(), 0); + * assert.strictEqual(Date.now(), 0); + * + * // Advance in time + * context.mock.timers.tick(9999); + * assert.strictEqual(fn.mock.callCount(), 1); + * assert.strictEqual(Date.now(), 9999); + * }); + * ``` * @since v20.4.0 */ tick(milliseconds: number): void; /** - * Triggers all pending mocked timers immediately. + * Triggers all pending mocked timers immediately. If the `Date` object is also + * mocked, it will also advance the `Date` object to the furthest timer's time. * * The example below triggers all pending timers immediately, * causing them to execute without any delay. @@ -1123,7 +1171,7 @@ declare module "node:test" { * import { test } from 'node:test'; * * test('runAll functions following the given order', (context) => { - * context.mock.timers.enable(['setTimeout']); + * context.mock.timers.enable({ apis: ['setTimeout', 'Date'] }); * const results = []; * setTimeout(() => results.push(1), 9999); * @@ -1135,8 +1183,9 @@ declare module "node:test" { * assert.deepStrictEqual(results, []); * * context.mock.timers.runAll(); - * * assert.deepStrictEqual(results, [3, 2, 1]); + * // The Date object is also advanced to the furthest timer's time + * assert.strictEqual(Date.now(), 9999); * }); * ``` * @@ -1343,7 +1392,7 @@ interface TestDequeue extends TestLocationInfo { * @see [source](https://github.com/nodejs/node/blob/v20.2.0/lib/test/reporters.js) */ declare module "node:test/reporters" { - import { Transform } from "node:stream"; + import { Transform, TransformOptions } from "node:stream"; type TestEvent = | { type: "test:diagnostic"; data: DiagnosticData } @@ -1378,5 +1427,8 @@ declare module "node:test/reporters" { * The `junit` reporter outputs test results in a jUnit XML format */ function junit(source: TestEventGenerator): AsyncGenerator; - export { dot, junit, Spec as spec, tap, TestEvent }; + class Lcov extends Transform { + constructor(opts?: TransformOptions); + } + export { dot, junit, Lcov as lcov, Spec as spec, tap, TestEvent }; } diff --git a/types/node/test/test.ts b/types/node/test/test.ts index df34d7152f06a5..ae4c314d446171 100644 --- a/types/node/test/test.ts +++ b/types/node/test/test.ts @@ -1,6 +1,6 @@ import { Transform, TransformCallback, TransformOptions } from "node:stream"; import { after, afterEach, before, beforeEach, describe, it, Mock, mock, only, run, skip, test, todo } from "node:test"; -import { dot, junit, spec, tap, TestEvent } from "node:test/reporters"; +import { dot, junit, spec, tap, lcov, TestEvent } from "node:test/reporters"; // run without options // $ExpectType TestsStream @@ -657,6 +657,8 @@ new spec(); junit(); // $ExpectType AsyncGenerator junit("" as any); +// $ExpectType Lcov +new lcov(); describe("Mock Timers Test Suite", () => { it((t) => { diff --git a/types/node/ts4.8/buffer.d.ts b/types/node/ts4.8/buffer.d.ts index 1ee5c013552af2..2fa2e745ffbedb 100644 --- a/types/node/ts4.8/buffer.d.ts +++ b/types/node/ts4.8/buffer.d.ts @@ -564,7 +564,7 @@ declare module "buffer" { * * The `Buffer` module pre-allocates an internal `Buffer` instance of * size `Buffer.poolSize` that is used as a pool for the fast allocation of new`Buffer` instances created using `Buffer.allocUnsafe()`, `Buffer.from(array)`, - * and `Buffer.concat()` only when `size` is less than or equal to`Buffer.poolSize >> 1` (floor of `Buffer.poolSize` divided by two). + * and `Buffer.concat()` only when `size` is less than`Buffer.poolSize >>> 1` (floor of `Buffer.poolSize` divided by two). * * Use of this pre-allocated internal memory pool is a key difference between * calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. diff --git a/types/node/ts4.8/crypto.d.ts b/types/node/ts4.8/crypto.d.ts index ead4a57247217f..3004bb1ed9dd8d 100644 --- a/types/node/ts4.8/crypto.d.ts +++ b/types/node/ts4.8/crypto.d.ts @@ -638,9 +638,10 @@ declare module "crypto" { export(options?: KeyExportOptions<"der">): Buffer; export(options?: JwkKeyExportOptions): JsonWebKey; /** - * Returns `true` or `false` depending on whether the keys have exactly the same type, value, and parameters. - * This method is not [constant time](https://en.wikipedia.org/wiki/Timing_attack). - * @since v16.15.0 + * Returns `true` or `false` depending on whether the keys have exactly the same + * type, value, and parameters. This method is not [constant time](https://en.wikipedia.org/wiki/Timing_attack). + * @since v17.7.0, v16.15.0 + * @param otherKeyObject A `KeyObject` with which to compare `keyObject`. */ equals(otherKeyObject: KeyObject): boolean; /** diff --git a/types/node/ts4.8/dgram.d.ts b/types/node/ts4.8/dgram.d.ts index ecbb6cf1382081..0b86ae735a2853 100644 --- a/types/node/ts4.8/dgram.d.ts +++ b/types/node/ts4.8/dgram.d.ts @@ -228,13 +228,13 @@ declare module "dgram" { */ getSendBufferSize(): number; /** - * @since v18.8.0,v16.19.0 - * @return the number of bytes queued for sending. + * @since v18.8.0, v16.19.0 + * @return Number of bytes queued for sending. */ getSendQueueSize(): number; /** - * @since v18.8.0,v16.19.0 - * @return the number of send requests currently in the queue awaiting to be processed. + * @since v18.8.0, v16.19.0 + * @return Number of send requests currently in the queue awaiting to be processed. */ getSendQueueCount(): number; /** diff --git a/types/node/ts4.8/http.d.ts b/types/node/ts4.8/http.d.ts index 9b2c3c2c6be6cd..710fe59423d657 100644 --- a/types/node/ts4.8/http.d.ts +++ b/types/node/ts4.8/http.d.ts @@ -9,12 +9,12 @@ * * HTTP message headers are represented by an object like this: * - * ```js - * { 'content-length': '123', - * 'content-type': 'text/plain', - * 'connection': 'keep-alive', - * 'host': 'example.com', - * 'accept': '*' } + * ```json + * { "content-length": "123", + * "content-type": "text/plain", + * "connection": "keep-alive", + * "host": "example.com", + * "accept": "*" } * ``` * * Keys are lowercased. Values are not modified. @@ -1814,7 +1814,6 @@ declare module "http" { * * It is not necessary to use this method before passing headers to an HTTP request * or response. The HTTP module will automatically validate such headers. - * Examples: * * Example: * diff --git a/types/node/ts4.8/module.d.ts b/types/node/ts4.8/module.d.ts index 68d59c7737bda5..1779e236c3d916 100644 --- a/types/node/ts4.8/module.d.ts +++ b/types/node/ts4.8/module.d.ts @@ -276,6 +276,20 @@ declare module "module" { } global { interface ImportMeta { + /** + * The directory name of the current module. This is the same as the `path.dirname()` of the `import.meta.filename`. + * **Caveat:** only present on `file:` modules. + */ + dirname?: string; + /** + * The full absolute path and filename of the current module, with symlinks resolved. + * This is the same as the `url.fileURLToPath()` of the `import.meta.url`. + * **Caveat:** only local modules support this property. Modules not using the `file:` protocol will not provide it. + */ + filename?: string; + /** + * The absolute `file:` URL of the module. + */ url: string; /** * Provides a module-relative resolution function scoped to each module, returning diff --git a/types/node/ts4.8/perf_hooks.d.ts b/types/node/ts4.8/perf_hooks.d.ts index 0e16e581819455..c0ce852a97b285 100644 --- a/types/node/ts4.8/perf_hooks.d.ts +++ b/types/node/ts4.8/perf_hooks.d.ts @@ -31,7 +31,7 @@ */ declare module "perf_hooks" { import { AsyncResource } from "node:async_hooks"; - type EntryType = "node" | "mark" | "measure" | "gc" | "function" | "http2" | "http"; + type EntryType = "node" | "mark" | "measure" | "gc" | "function" | "http2" | "http" | "dns" | "net"; interface NodeGCPerformanceDetail { /** * When `performanceEntry.entryType` is equal to 'gc', `the performance.kind` property identifies @@ -314,13 +314,15 @@ declare module "perf_hooks" { * * name: 'test', * * entryType: 'mark', * * startTime: 81.465639, - * * duration: 0 + * * duration: 0, + * * detail: null * * }, * * PerformanceEntry { * * name: 'meow', * * entryType: 'mark', * * startTime: 81.860064, - * * duration: 0 + * * duration: 0, + * * detail: null * * } * * ] * @@ -355,7 +357,8 @@ declare module "perf_hooks" { * * name: 'meow', * * entryType: 'mark', * * startTime: 98.545991, - * * duration: 0 + * * duration: 0, + * * detail: null * * } * * ] * @@ -368,7 +371,8 @@ declare module "perf_hooks" { * * name: 'test', * * entryType: 'mark', * * startTime: 63.518931, - * * duration: 0 + * * duration: 0, + * * detail: null * * } * * ] * @@ -404,13 +408,15 @@ declare module "perf_hooks" { * * name: 'test', * * entryType: 'mark', * * startTime: 55.897834, - * * duration: 0 + * * duration: 0, + * * detail: null * * }, * * PerformanceEntry { * * name: 'meow', * * entryType: 'mark', * * startTime: 56.350146, - * * duration: 0 + * * duration: 0, + * * detail: null * * } * * ] * diff --git a/types/node/ts4.8/process.d.ts b/types/node/ts4.8/process.d.ts index 0e2747376fc359..376b5417409130 100644 --- a/types/node/ts4.8/process.d.ts +++ b/types/node/ts4.8/process.d.ts @@ -903,9 +903,14 @@ declare module "process" { */ readonly sourceMapsEnabled: boolean; /** - * This function enables or disables the Source Map v3 support for stack traces. - * It provides same features as launching Node.js process with commandline options --enable-source-maps. - * @since v16.6.0 + * This function enables or disables the [Source Map v3](https://sourcemaps.info/spec.html) support for + * stack traces. + * + * It provides same features as launching Node.js process with commandline options`--enable-source-maps`. + * + * Only source maps in JavaScript files that are loaded after source maps has been + * enabled will be parsed and loaded. + * @since v16.6.0, v14.18.0 * @experimental */ setSourceMapsEnabled(value: boolean): void; diff --git a/types/node/ts4.8/querystring.d.ts b/types/node/ts4.8/querystring.d.ts index 54ecc967fff6e6..b36ea2c13014b6 100644 --- a/types/node/ts4.8/querystring.d.ts +++ b/types/node/ts4.8/querystring.d.ts @@ -74,10 +74,10 @@ declare module "querystring" { * * For example, the query string `'foo=bar&abc=xyz&abc=123'` is parsed into: * - * ```js + * ```json * { - * foo: 'bar', - * abc: ['xyz', '123'] + * "foo": "bar", + * "abc": ["xyz", "123"] * } * ``` * diff --git a/types/node/ts4.8/test.d.ts b/types/node/ts4.8/test.d.ts index 44b6a96408bf8f..95ce769dd2b6ed 100644 --- a/types/node/ts4.8/test.d.ts +++ b/types/node/ts4.8/test.d.ts @@ -82,6 +82,11 @@ declare module "node:test" { import { Readable } from "node:stream"; import { AsyncResource } from "node:async_hooks"; /** + * **Note:**`shard` is used to horizontally parallelize test running across + * machines or processes, ideal for large-scale executions across varied + * environments. It's incompatible with `watch` mode, tailored for rapid + * code iteration by automatically rerunning tests on file changes. + * * ```js * import { tap } from 'node:test/reporters'; * import { run } from 'node:test'; @@ -1013,6 +1018,8 @@ declare module "node:test" { * control the behavior of timers, such as `setInterval` and `setTimeout`, * without actually waiting for the specified time intervals. * + * MockTimers is also able to mock the `Date` object. + * * The `MockTracker` provides a top-level `timers` export * which is a `MockTimers` instance. * @since v20.4.0 @@ -1025,21 +1032,38 @@ declare module "node:test" { * **Note:** When you enable mocking for a specific timer, its associated * clear function will also be implicitly mocked. * - * Example usage: + * **Note:** Mocking `Date` will affect the behavior of the mocked timers + * as they use the same internal clock. + * + * Example usage without setting initial time: * * ```js * import { mock } from 'node:test'; - * mock.timers.enable(['setInterval']); + * mock.timers.enable({ apis: ['setInterval'] }); * ``` * * The above example enables mocking for the `setInterval` timer and * implicitly mocks the `clearInterval` function. Only the `setInterval`and `clearInterval` functions from `node:timers`,`node:timers/promises`, and`globalThis` will be mocked. * + * Example usage with initial time set + * + * ```js + * import { mock } from 'node:test'; + * mock.timers.enable({ apis: ['Date'], now: 1000 }); + * ``` + * + * Example usage with initial Date object as time set + * + * ```js + * import { mock } from 'node:test'; + * mock.timers.enable({ apis: ['Date'], now: new Date() }); + * ``` + * * Alternatively, if you call `mock.timers.enable()` without any parameters: * * All timers (`'setInterval'`, `'clearInterval'`, `'setTimeout'`, and `'clearTimeout'`) * will be mocked. The `setInterval`, `clearInterval`, `setTimeout`, and `clearTimeout`functions from `node:timers`, `node:timers/promises`, - * and `globalThis` will be mocked. + * and `globalThis` will be mocked. As well as the global `Date` object. * @since v20.4.0 */ enable(timers?: Timer[]): void; @@ -1076,7 +1100,7 @@ declare module "node:test" { * test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { * const fn = context.mock.fn(); * - * context.mock.timers.enable(['setTimeout']); + * context.mock.timers.enable({ apis: ['setTimeout'] }); * * setTimeout(fn, 9999); * @@ -1097,7 +1121,7 @@ declare module "node:test" { * * test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { * const fn = context.mock.fn(); - * context.mock.timers.enable(['setTimeout']); + * context.mock.timers.enable({ apis: ['setTimeout'] }); * const nineSecs = 9000; * setTimeout(fn, nineSecs); * @@ -1109,11 +1133,35 @@ declare module "node:test" { * assert.strictEqual(fn.mock.callCount(), 1); * }); * ``` + * + * Advancing time using `.tick` will also advance the time for any `Date` object + * created after the mock was enabled (if `Date` was also set to be mocked). + * + * ```js + * import assert from 'node:assert'; + * import { test } from 'node:test'; + * + * test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + * const fn = context.mock.fn(); + * + * context.mock.timers.enable({ apis: ['setTimeout', 'Date'] }); + * setTimeout(fn, 9999); + * + * assert.strictEqual(fn.mock.callCount(), 0); + * assert.strictEqual(Date.now(), 0); + * + * // Advance in time + * context.mock.timers.tick(9999); + * assert.strictEqual(fn.mock.callCount(), 1); + * assert.strictEqual(Date.now(), 9999); + * }); + * ``` * @since v20.4.0 */ tick(milliseconds: number): void; /** - * Triggers all pending mocked timers immediately. + * Triggers all pending mocked timers immediately. If the `Date` object is also + * mocked, it will also advance the `Date` object to the furthest timer's time. * * The example below triggers all pending timers immediately, * causing them to execute without any delay. @@ -1123,7 +1171,7 @@ declare module "node:test" { * import { test } from 'node:test'; * * test('runAll functions following the given order', (context) => { - * context.mock.timers.enable(['setTimeout']); + * context.mock.timers.enable({ apis: ['setTimeout', 'Date'] }); * const results = []; * setTimeout(() => results.push(1), 9999); * @@ -1135,8 +1183,9 @@ declare module "node:test" { * assert.deepStrictEqual(results, []); * * context.mock.timers.runAll(); - * * assert.deepStrictEqual(results, [3, 2, 1]); + * // The Date object is also advanced to the furthest timer's time + * assert.strictEqual(Date.now(), 9999); * }); * ``` * @@ -1343,7 +1392,7 @@ interface TestDequeue extends TestLocationInfo { * @see [source](https://github.com/nodejs/node/blob/v20.2.0/lib/test/reporters.js) */ declare module "node:test/reporters" { - import { Transform } from "node:stream"; + import { Transform, TransformOptions } from "node:stream"; type TestEvent = | { type: "test:diagnostic"; data: DiagnosticData } @@ -1378,5 +1427,8 @@ declare module "node:test/reporters" { * The `junit` reporter outputs test results in a jUnit XML format */ function junit(source: TestEventGenerator): AsyncGenerator; - export { dot, junit, Spec as spec, tap, TestEvent }; + class Lcov extends Transform { + constructor(opts?: TransformOptions); + } + export { dot, junit, Lcov as lcov, Spec as spec, tap, TestEvent }; } diff --git a/types/node/ts4.8/wasi.d.ts b/types/node/ts4.8/wasi.d.ts index caaf6095c1259e..337c0741203a05 100644 --- a/types/node/ts4.8/wasi.d.ts +++ b/types/node/ts4.8/wasi.d.ts @@ -1,6 +1,11 @@ /** - * The WASI API provides an implementation of the [WebAssembly System Interface](https://wasi.dev/) specification. WASI gives sandboxed WebAssembly applications access to the - * underlying operating system via a collection of POSIX-like functions. + * **The `node:wasi` module does not currently provide the** + * **comprehensive file system security properties provided by some WASI runtimes.** + * **Full support for secure file system sandboxing may or may not be implemented in** + * **future. In the mean time, do not rely on it to run untrusted code.** + * + * The WASI API provides an implementation of the [WebAssembly System Interface](https://wasi.dev/) specification. WASI gives WebAssembly applications access to the underlying + * operating system via a collection of POSIX-like functions. * * ```js * import { readFile } from 'node:fs/promises'; @@ -12,7 +17,7 @@ * args: argv, * env, * preopens: { - * '/sandbox': '/some/real/path/that/wasm/can/access', + * '/local': '/some/real/path/that/wasm/can/access', * }, * }); * @@ -117,8 +122,7 @@ declare module "wasi" { /** * The `WASI` class provides the WASI system call API and additional convenience * methods for working with WASI-based applications. Each `WASI` instance - * represents a distinct sandbox environment. For security purposes, each `WASI`instance must have its command-line arguments, environment variables, and - * sandbox directory structure configured explicitly. + * represents a distinct environment. * @since v13.3.0, v12.16.0 */ class WASI { diff --git a/types/node/wasi.d.ts b/types/node/wasi.d.ts index caaf6095c1259e..337c0741203a05 100644 --- a/types/node/wasi.d.ts +++ b/types/node/wasi.d.ts @@ -1,6 +1,11 @@ /** - * The WASI API provides an implementation of the [WebAssembly System Interface](https://wasi.dev/) specification. WASI gives sandboxed WebAssembly applications access to the - * underlying operating system via a collection of POSIX-like functions. + * **The `node:wasi` module does not currently provide the** + * **comprehensive file system security properties provided by some WASI runtimes.** + * **Full support for secure file system sandboxing may or may not be implemented in** + * **future. In the mean time, do not rely on it to run untrusted code.** + * + * The WASI API provides an implementation of the [WebAssembly System Interface](https://wasi.dev/) specification. WASI gives WebAssembly applications access to the underlying + * operating system via a collection of POSIX-like functions. * * ```js * import { readFile } from 'node:fs/promises'; @@ -12,7 +17,7 @@ * args: argv, * env, * preopens: { - * '/sandbox': '/some/real/path/that/wasm/can/access', + * '/local': '/some/real/path/that/wasm/can/access', * }, * }); * @@ -117,8 +122,7 @@ declare module "wasi" { /** * The `WASI` class provides the WASI system call API and additional convenience * methods for working with WASI-based applications. Each `WASI` instance - * represents a distinct sandbox environment. For security purposes, each `WASI`instance must have its command-line arguments, environment variables, and - * sandbox directory structure configured explicitly. + * represents a distinct environment. * @since v13.3.0, v12.16.0 */ class WASI { From ce5a510266c1630f927664f9837cc0f51b635b3d Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Thu, 11 Jan 2024 05:30:43 +0000 Subject: [PATCH 20/23] =?UTF-8?q?=F0=9F=A4=96=20dprint=20fmt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/node/test/test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/node/test/test.ts b/types/node/test/test.ts index ae4c314d446171..e2486d65b2f4d2 100644 --- a/types/node/test/test.ts +++ b/types/node/test/test.ts @@ -1,6 +1,6 @@ import { Transform, TransformCallback, TransformOptions } from "node:stream"; import { after, afterEach, before, beforeEach, describe, it, Mock, mock, only, run, skip, test, todo } from "node:test"; -import { dot, junit, spec, tap, lcov, TestEvent } from "node:test/reporters"; +import { dot, junit, lcov, spec, tap, TestEvent } from "node:test/reporters"; // run without options // $ExpectType TestsStream From b2814547727b5c4cfc220af2fabe5b5da116ca96 Mon Sep 17 00:00:00 2001 From: Tobias Tengler <45513122+tobias-tengler@users.noreply.github.com> Date: Thu, 11 Jan 2024 12:29:17 +0100 Subject: [PATCH 21/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68144=20Move?= =?UTF-8?q?=20PreloadableConcreteRequest=20from=20react-relay=20to=20relay?= =?UTF-8?q?-runtime=20by=20@tobias-tengler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Move PreloadableConcreteRequest from react-relay to relay-runtime * Format files --- types/react-relay/hooks.d.ts | 1 - .../relay-hooks/EntryPointTypes.d.ts | 10 +------ types/react-relay/relay-hooks/loadQuery.d.ts | 9 ++---- .../relay-hooks/useQueryLoader.d.ts | 11 ++++++-- .../relay-experimental/EntryPointTypes.d.ts | 10 +------ .../v7/lib/relay-experimental/loadQuery.d.ts | 9 ++---- .../relay-experimental/useQueryLoader.d.ts | 4 +-- types/relay-runtime/index.d.ts | 1 + .../lib/util/RelayConcreteNode.d.ts | 12 ++++++++ types/relay-runtime/relay-runtime-tests.tsx | 28 +++++++++++++++++++ 10 files changed, 58 insertions(+), 37 deletions(-) diff --git a/types/react-relay/hooks.d.ts b/types/react-relay/hooks.d.ts index ea67cacf1a9ff9..893120ce8fc092 100644 --- a/types/react-relay/hooks.d.ts +++ b/types/react-relay/hooks.d.ts @@ -6,7 +6,6 @@ export { IEnvironmentProvider, JSResourceReference, LoadQueryOptions, - PreloadableConcreteRequest, PreloadedEntryPoint, PreloadedQuery, PreloadFetchPolicy, diff --git a/types/react-relay/relay-hooks/EntryPointTypes.d.ts b/types/react-relay/relay-hooks/EntryPointTypes.d.ts index 9d33b1e2274b57..093bebcebd6dcf 100644 --- a/types/react-relay/relay-hooks/EntryPointTypes.d.ts +++ b/types/react-relay/relay-hooks/EntryPointTypes.d.ts @@ -8,7 +8,7 @@ import { IEnvironment, Observable, OperationType, - RequestParameters, + PreloadableConcreteRequest, VariablesOf, } from "relay-runtime"; import { GetEntryPointComponentFromEntryPoint, GetEntryPointParamsFromEntryPoint } from "./helpers"; @@ -37,14 +37,6 @@ export type LoadQueryOptions = Readonly<{ onQueryAstLoadTimeout?: (() => void) | null | undefined; }>; -// Note: the phantom type parameter here helps ensures that the -// $Parameters.js value matches the type param provided to preloadQuery. -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export type PreloadableConcreteRequest = { - kind: "PreloadableConcreteRequest"; - params: RequestParameters; -}; - export type EnvironmentProviderOptions = Record> = T; export interface PreloadedQuery< diff --git a/types/react-relay/relay-hooks/loadQuery.d.ts b/types/react-relay/relay-hooks/loadQuery.d.ts index df4b3bd2f0cb80..fe0094fe27fb2e 100644 --- a/types/react-relay/relay-hooks/loadQuery.d.ts +++ b/types/react-relay/relay-hooks/loadQuery.d.ts @@ -1,10 +1,5 @@ -import { GraphQLTaggedNode, IEnvironment, OperationType, VariablesOf } from "relay-runtime"; -import { - EnvironmentProviderOptions, - LoadQueryOptions, - PreloadableConcreteRequest, - PreloadedQuery, -} from "./EntryPointTypes"; +import { GraphQLTaggedNode, IEnvironment, OperationType, PreloadableConcreteRequest, VariablesOf } from "relay-runtime"; +import { EnvironmentProviderOptions, LoadQueryOptions, PreloadedQuery } from "./EntryPointTypes"; export function loadQuery< TQuery extends OperationType, diff --git a/types/react-relay/relay-hooks/useQueryLoader.d.ts b/types/react-relay/relay-hooks/useQueryLoader.d.ts index 042d849b51a376..605a1defd674e2 100644 --- a/types/react-relay/relay-hooks/useQueryLoader.d.ts +++ b/types/react-relay/relay-hooks/useQueryLoader.d.ts @@ -1,5 +1,12 @@ -import { DisposeFn, GraphQLTaggedNode, IEnvironment, OperationType, VariablesOf } from "relay-runtime"; -import { LoadQueryOptions, PreloadableConcreteRequest, PreloadedQuery } from "./EntryPointTypes"; +import { + DisposeFn, + GraphQLTaggedNode, + IEnvironment, + OperationType, + PreloadableConcreteRequest, + VariablesOf, +} from "relay-runtime"; +import { LoadQueryOptions, PreloadedQuery } from "./EntryPointTypes"; export type useQueryLoaderHookType = [ PreloadedQuery | null | undefined, diff --git a/types/react-relay/v7/lib/relay-experimental/EntryPointTypes.d.ts b/types/react-relay/v7/lib/relay-experimental/EntryPointTypes.d.ts index 4e869ca5edd2f7..ed87994dce454e 100644 --- a/types/react-relay/v7/lib/relay-experimental/EntryPointTypes.d.ts +++ b/types/react-relay/v7/lib/relay-experimental/EntryPointTypes.d.ts @@ -7,7 +7,7 @@ import { IEnvironment, Observable, OperationType, - RequestParameters, + PreloadableConcreteRequest, VariablesOf, } from "relay-runtime"; import { GetEntryPointComponentFromEntryPoint, GetEntryPointParamsFromEntryPoint } from "./helpers"; @@ -36,14 +36,6 @@ export type LoadQueryOptions = Readonly<{ onQueryAstLoadTimeout?: (() => void) | null | undefined; }>; -// Note: the phantom type parameter here helps ensures that the -// $Parameters.js value matches the type param provided to preloadQuery. -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export type PreloadableConcreteRequest = { - kind: "PreloadableConcreteRequest"; - params: RequestParameters; -}; - export type EnvironmentProviderOptions = Record> = T; export interface PreloadedQuery< diff --git a/types/react-relay/v7/lib/relay-experimental/loadQuery.d.ts b/types/react-relay/v7/lib/relay-experimental/loadQuery.d.ts index df4b3bd2f0cb80..fe0094fe27fb2e 100644 --- a/types/react-relay/v7/lib/relay-experimental/loadQuery.d.ts +++ b/types/react-relay/v7/lib/relay-experimental/loadQuery.d.ts @@ -1,10 +1,5 @@ -import { GraphQLTaggedNode, IEnvironment, OperationType, VariablesOf } from "relay-runtime"; -import { - EnvironmentProviderOptions, - LoadQueryOptions, - PreloadableConcreteRequest, - PreloadedQuery, -} from "./EntryPointTypes"; +import { GraphQLTaggedNode, IEnvironment, OperationType, PreloadableConcreteRequest, VariablesOf } from "relay-runtime"; +import { EnvironmentProviderOptions, LoadQueryOptions, PreloadedQuery } from "./EntryPointTypes"; export function loadQuery< TQuery extends OperationType, diff --git a/types/react-relay/v7/lib/relay-experimental/useQueryLoader.d.ts b/types/react-relay/v7/lib/relay-experimental/useQueryLoader.d.ts index c176035a945e28..b0727c0651af95 100644 --- a/types/react-relay/v7/lib/relay-experimental/useQueryLoader.d.ts +++ b/types/react-relay/v7/lib/relay-experimental/useQueryLoader.d.ts @@ -1,5 +1,5 @@ -import { DisposeFn, GraphQLTaggedNode, OperationType, VariablesOf } from "relay-runtime"; -import { LoadQueryOptions, PreloadableConcreteRequest, PreloadedQuery } from "./EntryPointTypes"; +import { DisposeFn, GraphQLTaggedNode, OperationType, PreloadableConcreteRequest, VariablesOf } from "relay-runtime"; +import { LoadQueryOptions, PreloadedQuery } from "./EntryPointTypes"; export type useQueryLoaderHookType = [ PreloadedQuery | null | undefined, diff --git a/types/relay-runtime/index.d.ts b/types/relay-runtime/index.d.ts index 3825fdc9eeae4b..662037190100f0 100644 --- a/types/relay-runtime/index.d.ts +++ b/types/relay-runtime/index.d.ts @@ -134,6 +134,7 @@ export { ConcreteRequest, ConcreteUpdatableQuery, GeneratedNode, + PreloadableConcreteRequest, RequestParameters, } from "./lib/util/RelayConcreteNode"; export { RelayReplaySubject as ReplaySubject } from "./lib/util/RelayReplaySubject"; diff --git a/types/relay-runtime/lib/util/RelayConcreteNode.d.ts b/types/relay-runtime/lib/util/RelayConcreteNode.d.ts index 3eedd7eed08603..1d3680a37daaae 100644 --- a/types/relay-runtime/lib/util/RelayConcreteNode.d.ts +++ b/types/relay-runtime/lib/util/RelayConcreteNode.d.ts @@ -1,5 +1,6 @@ import { NormalizationOperation, NormalizationSplitOperation } from "./NormalizationNode"; import { ReaderFragment, ReaderInlineDataFragment } from "./ReaderNode"; +import { OperationType } from "./RelayRuntimeTypes"; /** * Represents a common GraphQL request that can be executed, an `operation` @@ -14,6 +15,17 @@ export interface ConcreteRequest { readonly params: RequestParameters; } +/** + * Represents the minimal information necessary to identify and execute + * a particular GraphQL request. + */ +// Note: the phantom type parameter here helps ensures that the +// $Parameters.js value matches the type param provided to preloadQuery. +export interface PreloadableConcreteRequest { + readonly kind: string; // 'PreloadableConcreteRequest'; + readonly params: RequestParameters; +} + export interface ConcreteUpdatableQuery { readonly kind: string; // 'UpdatableQuery'; readonly fragment: ReaderFragment; diff --git a/types/relay-runtime/relay-runtime-tests.tsx b/types/relay-runtime/relay-runtime-tests.tsx index 37df1f5da1ee0f..c8a11aeeae1ba3 100644 --- a/types/relay-runtime/relay-runtime-tests.tsx +++ b/types/relay-runtime/relay-runtime-tests.tsx @@ -16,6 +16,7 @@ import { graphql, isPromise, Network, + PreloadableConcreteRequest, QueryResponseCache, ReaderFragment, ReaderInlineDataFragment, @@ -298,6 +299,33 @@ commitLocalUpdate(environment, store => { root!.setValue("foo", "localKey"); }); +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// PreloadableConcreteRequest +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +type FooQuery$variables = Record; +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type FooQuery$data = { + readonly foo: string | null | undefined; +}; +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type FooQuery = { + response: FooQuery$data; + variables: FooQuery$variables; +}; + +const preloadableNode: PreloadableConcreteRequest = { + kind: "PreloadableConcreteRequest", + params: { + operationKind: "query", + name: "FooQuery", + id: null, + cacheID: "2e5967148a8303de3c58059c0eaa87c6", + text: "query FooQuery {\n foo\n}\n", + metadata: {}, + }, +}; + // ~~~~~~~~~~~~~~~~~~~~~ // ConcreteRequest // ~~~~~~~~~~~~~~~~~~~~~ From 245cc9baace21b8c235b62727cf9eaea45d046d0 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Thu, 11 Jan 2024 15:17:55 +0100 Subject: [PATCH 22/23] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#68170=20fix:?= =?UTF-8?q?=20calling=20@rdfjs/fetch=20with=20URL=20by=20@tpluscode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: calling @rdfjs/fetch with URL * fix: calling @rdfjs/fetch with URL also with factory usage --- types/rdfjs__fetch-lite/Factory.d.ts | 2 +- types/rdfjs__fetch-lite/index.d.ts | 6 ++++-- types/rdfjs__fetch-lite/rdfjs__fetch-lite-tests.ts | 14 +++++++++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/types/rdfjs__fetch-lite/Factory.d.ts b/types/rdfjs__fetch-lite/Factory.d.ts index d4a0a9412fea26..3e8eebc37c925e 100644 --- a/types/rdfjs__fetch-lite/Factory.d.ts +++ b/types/rdfjs__fetch-lite/Factory.d.ts @@ -11,7 +11,7 @@ interface RdfFetchResponse< } interface Fetch { - (url: string, options?: FormatsInit): Promise>; + (url: Parameters[0], options?: FormatsInit): Promise>; config(key: string, value: unknown): void; Headers: Headers; } diff --git a/types/rdfjs__fetch-lite/index.d.ts b/types/rdfjs__fetch-lite/index.d.ts index 7fdb9ac58bb358..2f8a3a50dcb116 100644 --- a/types/rdfjs__fetch-lite/index.d.ts +++ b/types/rdfjs__fetch-lite/index.d.ts @@ -26,13 +26,15 @@ export interface DatasetResponse< dataset(): Promise; } -declare function rdfFetch(url: string, options: FormatsInit): Promise; +type FetchUrl = Parameters[0]; + +declare function rdfFetch(url: FetchUrl, options: FormatsInit): Promise; declare function rdfFetch< D extends DatasetCore, OutQuad extends BaseQuad = Quad, InQuad extends BaseQuad = OutQuad, >( - url: string, + url: FetchUrl, options: FactoryInit, ): Promise>; diff --git a/types/rdfjs__fetch-lite/rdfjs__fetch-lite-tests.ts b/types/rdfjs__fetch-lite/rdfjs__fetch-lite-tests.ts index 2ebee8e5944a68..1ff8b8eabcddcd 100644 --- a/types/rdfjs__fetch-lite/rdfjs__fetch-lite-tests.ts +++ b/types/rdfjs__fetch-lite/rdfjs__fetch-lite-tests.ts @@ -11,6 +11,17 @@ async function fetchString(): Promise { return response.text(); } +async function fetchURL(): Promise { + const response = await fetch(new URL("http://example.com"), { formats }); + return response.text(); +} + +async function fetchRequestInfo(): Promise { + const req: Request = {}; + const response = await fetch(req, { formats }); + return response.text(); +} + async function fetchQuadStream(): Promise { const response = await fetch("http://example.com", { formats }); return response.quadStream(); @@ -44,7 +55,8 @@ async function environmentRawFetch(): Promise { // $ExpectType Headers const headers = environmentTest.fetch.Headers; - const res = await environmentTest.fetch("foo", { formats }); + let res = await environmentTest.fetch("foo", { formats }); + res = await environmentTest.fetch(new URL("foo"), { formats }); return res.quadStream(); } From b0a62b6f70772fc34ef27affdcfc350ae7556916 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 11 Jan 2024 06:42:51 -0800 Subject: [PATCH 23/23] Fix sequelize's import of validator (#68172) Changed in #68121. Sequelize was missed because of a bug in the linter's setup code. --- types/sequelize/index.d.ts | 2 +- types/sequelize/v3/index.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/types/sequelize/index.d.ts b/types/sequelize/index.d.ts index fff4f5d2495e08..53db72a74982fb 100644 --- a/types/sequelize/index.d.ts +++ b/types/sequelize/index.d.ts @@ -9,7 +9,7 @@ import * as _ from "lodash"; import Promise = require("bluebird"); import * as cls from "continuation-local-storage"; -import ValidatorJS from "validator"; +import ValidatorJS = require("validator"); type Omit = Pick>; diff --git a/types/sequelize/v3/index.d.ts b/types/sequelize/v3/index.d.ts index 893b09a25deee9..116529fad0ecf5 100644 --- a/types/sequelize/v3/index.d.ts +++ b/types/sequelize/v3/index.d.ts @@ -3,7 +3,7 @@ import * as Promise from "bluebird"; import * as _ from "lodash"; -import ValidatorJS from "validator"; +import ValidatorJS = require("validator"); declare namespace sequelize { //