From adfd9cd3b32cfabdcc45ec90f535b2852a3ca4a6 Mon Sep 17 00:00:00 2001 From: Qjuh <76154676+Qjuh@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:09:13 +0100 Subject: [PATCH] refactor: use interfaces for AsyncEventEmitter event maps (#10044) * refactor: use interfaces for AsyncEventEmitter event maps * refactor: apply suggestions from code review and add tests * refactor: better errors on missing dispatch types --- packages/brokers/package.json | 2 +- packages/core/package.json | 2 +- packages/core/src/client.ts | 14 +-- packages/rest/package.json | 2 +- packages/rest/src/lib/REST.ts | 4 +- packages/rest/src/lib/utils/types.ts | 4 +- .../types/WebSocketManager.test-d.ts | 15 ++++ packages/ws/package.json | 3 +- packages/ws/src/ws/WebSocketManager.ts | 27 ++++-- packages/ws/src/ws/WebSocketShard.ts | 5 +- pnpm-lock.yaml | 90 ++++++++++--------- 11 files changed, 102 insertions(+), 66 deletions(-) create mode 100644 packages/ws/__tests__/types/WebSocketManager.test-d.ts diff --git a/packages/brokers/package.json b/packages/brokers/package.json index f8e77975f..1ccf0022b 100644 --- a/packages/brokers/package.json +++ b/packages/brokers/package.json @@ -67,7 +67,7 @@ "homepage": "https://discord.js.org", "dependencies": { "@msgpack/msgpack": "^3.0.0-beta2", - "@vladfrangu/async_event_emitter": "^2.2.2", + "@vladfrangu/async_event_emitter": "^2.2.4", "ioredis": "^5.3.2" }, "devDependencies": { diff --git a/packages/core/package.json b/packages/core/package.json index f10d72425..53610a1bd 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -68,7 +68,7 @@ "@discordjs/util": "workspace:^", "@discordjs/ws": "workspace:^", "@sapphire/snowflake": "^3.5.1", - "@vladfrangu/async_event_emitter": "^2.2.2", + "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "0.37.61" }, "devDependencies": { diff --git a/packages/core/src/client.ts b/packages/core/src/client.ts index 06252c855..c875058c8 100644 --- a/packages/core/src/client.ts +++ b/packages/core/src/client.ts @@ -163,9 +163,7 @@ export interface MappedEvents { [GatewayDispatchEvents.WebhooksUpdate]: [WithIntrinsicProps]; } -export type ManagerShardEventsMap = { - [K in keyof MappedEvents]: MappedEvents[K]; -}; +export interface ManagerShardEventsMap extends MappedEvents {} export interface ClientOptions { gateway: Gateway; @@ -179,7 +177,7 @@ export interface RequestGuildMembersResult { presences: NonNullable; } -export class Client extends AsyncEventEmitter { +export class Client extends AsyncEventEmitter { public readonly rest: REST; public readonly gateway: Gateway; @@ -193,8 +191,12 @@ export class Client extends AsyncEventEmitter { this.api = new API(rest); this.gateway.on(WebSocketShardEvents.Dispatch, ({ data: dispatch, shardId }) => { - // @ts-expect-error event props can't be resolved properly, but they are correct - this.emit(dispatch.t, this.wrapIntrinsicProps(dispatch.d, shardId)); + this.emit( + // TODO: move this expect-error down to the next line once entitlements get merged, so missing dispatch types result in errors + // @ts-expect-error event props can't be resolved properly, but they are correct + dispatch.t, + this.wrapIntrinsicProps(dispatch.d, shardId), + ); }); } diff --git a/packages/rest/package.json b/packages/rest/package.json index 38e64583b..0742af354 100644 --- a/packages/rest/package.json +++ b/packages/rest/package.json @@ -86,7 +86,7 @@ "@discordjs/util": "workspace:^", "@sapphire/async-queue": "^1.5.0", "@sapphire/snowflake": "^3.5.1", - "@vladfrangu/async_event_emitter": "^2.2.2", + "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "0.37.61", "magic-bytes.js": "^1.5.0", "tslib": "^2.6.2", diff --git a/packages/rest/src/lib/REST.ts b/packages/rest/src/lib/REST.ts index d879ad6ea..d396b4952 100644 --- a/packages/rest/src/lib/REST.ts +++ b/packages/rest/src/lib/REST.ts @@ -18,7 +18,7 @@ import { RequestMethod } from './utils/types.js'; import type { RESTOptions, ResponseLike, - RestEventsMap, + RestEvents, HashData, InternalRequest, RouteLike, @@ -31,7 +31,7 @@ import { isBufferLike, parseResponse } from './utils/utils.js'; /** * Represents the class that manages handlers for endpoints */ -export class REST extends AsyncEventEmitter { +export class REST extends AsyncEventEmitter { /** * The {@link https://undici.nodejs.org/#/docs/api/Agent | Agent} for all requests * performed by this manager. diff --git a/packages/rest/src/lib/utils/types.ts b/packages/rest/src/lib/utils/types.ts index 0b204a01d..a3f1c7da6 100644 --- a/packages/rest/src/lib/utils/types.ts +++ b/packages/rest/src/lib/utils/types.ts @@ -14,9 +14,7 @@ export interface RestEvents { restDebug: [info: string]; } -export type RestEventsMap = { - [K in keyof RestEvents]: RestEvents[K]; -}; +export interface RestEventsMap extends RestEvents {} /** * Options to be passed when creating the REST instance diff --git a/packages/ws/__tests__/types/WebSocketManager.test-d.ts b/packages/ws/__tests__/types/WebSocketManager.test-d.ts new file mode 100644 index 000000000..68f73bf86 --- /dev/null +++ b/packages/ws/__tests__/types/WebSocketManager.test-d.ts @@ -0,0 +1,15 @@ +import type { AsyncEventEmitter } from '@vladfrangu/async_event_emitter'; +import { expectType, expectAssignable } from 'tsd'; +import type { ManagerShardEventsMap, WebSocketShardEventsMap, WebSocketManager } from '../../src/index.js'; + +declare const manager: WebSocketManager; +declare const eventMap: ManagerShardEventsMap; + +type AugmentedShardEventsMap = { + [K in keyof WebSocketShardEventsMap]: [ + WebSocketShardEventsMap[K] extends [] ? { shardId: number } : WebSocketShardEventsMap[K][0] & { shardId: number }, + ]; +}; + +expectType(eventMap); +expectAssignable>(manager); diff --git a/packages/ws/package.json b/packages/ws/package.json index df1235209..79e202dfd 100644 --- a/packages/ws/package.json +++ b/packages/ws/package.json @@ -77,7 +77,7 @@ "@discordjs/util": "workspace:^", "@sapphire/async-queue": "^1.5.0", "@types/ws": "^8.5.9", - "@vladfrangu/async_event_emitter": "^2.2.2", + "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "0.37.61", "tslib": "^2.6.2", "ws": "^8.14.2" @@ -94,6 +94,7 @@ "eslint-formatter-pretty": "^5.0.0", "mock-socket": "^9.3.1", "prettier": "^3.1.0", + "tsd": "^0.29.0", "tsup": "^7.2.0", "turbo": "^1.10.17-canary.0", "typescript": "^5.2.2", diff --git a/packages/ws/src/ws/WebSocketManager.ts b/packages/ws/src/ws/WebSocketManager.ts index 5627b854b..eb8976738 100644 --- a/packages/ws/src/ws/WebSocketManager.ts +++ b/packages/ws/src/ws/WebSocketManager.ts @@ -9,11 +9,13 @@ import { type RESTGetAPIGatewayBotResult, type GatewayIntentBits, type GatewaySendPayload, + type GatewayDispatchPayload, + type GatewayReadyDispatchData, } from 'discord-api-types/v10'; import type { IShardingStrategy } from '../strategies/sharding/IShardingStrategy.js'; import type { IIdentifyThrottler } from '../throttling/IIdentifyThrottler.js'; import { DefaultWebSocketManagerOptions, type CompressionMethod, type Encoding } from '../utils/constants.js'; -import type { WebSocketShardDestroyOptions, WebSocketShardEventsMap } from './WebSocketShard.js'; +import type { WebSocketShardDestroyOptions, WebSocketShardEvents } from './WebSocketShard.js'; /** * Represents a range of shard ids @@ -178,13 +180,24 @@ export interface OptionalWebSocketManagerOptions { version: string; } -export type WebSocketManagerOptions = OptionalWebSocketManagerOptions & RequiredWebSocketManagerOptions; +export interface WebSocketManagerOptions extends OptionalWebSocketManagerOptions, RequiredWebSocketManagerOptions {} -export type ManagerShardEventsMap = { - [K in keyof WebSocketShardEventsMap]: [ - WebSocketShardEventsMap[K] extends [] ? { shardId: number } : WebSocketShardEventsMap[K][0] & { shardId: number }, +export interface CreateWebSocketManagerOptions + extends Partial, + RequiredWebSocketManagerOptions {} + +export interface ManagerShardEventsMap { + [WebSocketShardEvents.Closed]: [{ code: number; shardId: number }]; + [WebSocketShardEvents.Debug]: [payload: { message: string; shardId: number }]; + [WebSocketShardEvents.Dispatch]: [payload: { data: GatewayDispatchPayload; shardId: number }]; + [WebSocketShardEvents.Error]: [payload: { error: Error; shardId: number }]; + [WebSocketShardEvents.Hello]: [{ shardId: number }]; + [WebSocketShardEvents.Ready]: [payload: { data: GatewayReadyDispatchData; shardId: number }]; + [WebSocketShardEvents.Resumed]: [{ shardId: number }]; + [WebSocketShardEvents.HeartbeatComplete]: [ + payload: { ackAt: number; heartbeatAt: number; latency: number; shardId: number }, ]; -}; +} export class WebSocketManager extends AsyncEventEmitter { /** @@ -212,7 +225,7 @@ export class WebSocketManager extends AsyncEventEmitter { */ private readonly strategy: IShardingStrategy; - public constructor(options: Partial & RequiredWebSocketManagerOptions) { + public constructor(options: CreateWebSocketManagerOptions) { super(); this.options = { ...DefaultWebSocketManagerOptions, ...options }; this.strategy = this.options.buildStrategy(this); diff --git a/packages/ws/src/ws/WebSocketShard.ts b/packages/ws/src/ws/WebSocketShard.ts index 6575de946..c1e14cdbd 100644 --- a/packages/ws/src/ws/WebSocketShard.ts +++ b/packages/ws/src/ws/WebSocketShard.ts @@ -52,8 +52,7 @@ export enum WebSocketShardDestroyRecovery { Resume, } -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export type WebSocketShardEventsMap = { +export interface WebSocketShardEventsMap { [WebSocketShardEvents.Closed]: [{ code: number }]; [WebSocketShardEvents.Debug]: [payload: { message: string }]; [WebSocketShardEvents.Dispatch]: [payload: { data: GatewayDispatchPayload }]; @@ -62,7 +61,7 @@ export type WebSocketShardEventsMap = { [WebSocketShardEvents.Ready]: [payload: { data: GatewayReadyDispatchData }]; [WebSocketShardEvents.Resumed]: []; [WebSocketShardEvents.HeartbeatComplete]: [payload: { ackAt: number; heartbeatAt: number; latency: number }]; -}; +} export interface WebSocketShardDestroyOptions { code?: number; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b3ec5ddf..fe467f68e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -607,8 +607,8 @@ importers: specifier: ^3.0.0-beta2 version: 3.0.0-beta2 '@vladfrangu/async_event_emitter': - specifier: ^2.2.2 - version: 2.2.2 + specifier: ^2.2.4 + version: 2.2.4 ioredis: specifier: ^5.3.2 version: 5.3.2 @@ -786,8 +786,8 @@ importers: specifier: ^3.5.1 version: 3.5.1 '@vladfrangu/async_event_emitter': - specifier: ^2.2.2 - version: 2.2.2 + specifier: ^2.2.4 + version: 2.2.4 discord-api-types: specifier: 0.37.61 version: 0.37.61 @@ -1280,8 +1280,8 @@ importers: specifier: ^3.5.1 version: 3.5.1 '@vladfrangu/async_event_emitter': - specifier: ^2.2.2 - version: 2.2.2 + specifier: ^2.2.4 + version: 2.2.4 discord-api-types: specifier: 0.37.61 version: 0.37.61 @@ -1662,8 +1662,8 @@ importers: specifier: ^8.5.9 version: 8.5.9 '@vladfrangu/async_event_emitter': - specifier: ^2.2.2 - version: 2.2.2 + specifier: ^2.2.4 + version: 2.2.4 discord-api-types: specifier: 0.37.61 version: 0.37.61 @@ -1707,6 +1707,9 @@ importers: prettier: specifier: ^3.1.0 version: 3.1.0 + tsd: + specifier: ^0.29.0 + version: 0.29.0 tsup: specifier: ^7.2.0 version: 7.2.0(typescript@5.2.2) @@ -3940,25 +3943,25 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true - /@definitelytyped/header-parser@0.0.188: - resolution: {integrity: sha512-s2223ipUtaKy68u7Ku4QsB3ZmRLMKYGMlOrKALbG9dhkOF/zTO/jckcn1ZAU338oL0q+q5xDFMHja9qxs4TEaw==} + /@definitelytyped/header-parser@0.0.190: + resolution: {integrity: sha512-awWRynVpFt6uAVDzgOa1Ry0ttjQywtt4nh9wa3/MbSTEx6PNohL1X6xDjifUElLSTIUMDSAJyWO9FuKBjnX7IQ==} engines: {node: '>=16.17.0'} dependencies: - '@definitelytyped/typescript-versions': 0.0.181 - '@definitelytyped/utils': 0.0.186 + '@definitelytyped/typescript-versions': 0.0.182 + '@definitelytyped/utils': 0.0.188 semver: 7.5.4 dev: true - /@definitelytyped/typescript-versions@0.0.181: - resolution: {integrity: sha512-D3iVQSPLNg8r9xissfcrBP0dsv9hsexz1z/KXBJ97fsqSLIGIiAzaDJJnY9NLzbAOzeazk6Ezetn8k0sIlXetg==} + /@definitelytyped/typescript-versions@0.0.182: + resolution: {integrity: sha512-ebGzGyZJW3ZSuE/nfAokKBo40HKnq/XvBbBnmCTR/3FCDX4aT7/6pQYEu2ihVI/2tf4+76GMoq0jRE69QWJ93g==} engines: {node: '>=16.17.0'} dev: true - /@definitelytyped/utils@0.0.186: - resolution: {integrity: sha512-T2e5QTVRFBP49B5yfk5kjbr3YYE2q1WqLkTTQNhhkJTTLoVFjhBSYF4PnWA0Op302aRiiCwDIuweqMmu3Zt8wg==} + /@definitelytyped/utils@0.0.188: + resolution: {integrity: sha512-NPUP1FvRbpac09qETtr1dw3Ri7Q07hp9WGOBjqhzXeXOSxfKs7c3BY6I+XJ2yxexG05LKrCKwgKRKgZlj+Zjzw==} engines: {node: '>=16.17.0'} dependencies: - '@definitelytyped/typescript-versions': 0.0.181 + '@definitelytyped/typescript-versions': 0.0.182 '@qiwi/npm-registry-client': 8.9.1 '@types/node': 16.18.61 charm: 1.0.2 @@ -4430,7 +4433,7 @@ packages: engines: {node: ^8.13.0 || >=10.10.0} dependencies: '@grpc/proto-loader': 0.7.10 - '@types/node': 18.18.8 + '@types/node': 18.18.9 dev: false /@grpc/proto-loader@0.7.10: @@ -4723,7 +4726,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.5 '@types/istanbul-reports': 3.0.3 - '@types/node': 18.18.8 + '@types/node': 18.18.9 '@types/yargs': 16.0.7 chalk: 4.1.2 dev: true @@ -7182,7 +7185,7 @@ packages: '@storybook/telemetry': 7.5.3 '@storybook/types': 7.5.3 '@types/detect-port': 1.3.4 - '@types/node': 18.18.8 + '@types/node': 18.18.9 '@types/pretty-hrtime': 1.0.2 '@types/semver': 7.5.5 better-opn: 3.0.2 @@ -7684,7 +7687,7 @@ packages: resolution: {integrity: sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==} dependencies: '@types/connect': 3.4.37 - '@types/node': 18.18.8 + '@types/node': 18.18.9 dev: true /@types/chai-subset@1.3.4: @@ -7700,13 +7703,13 @@ packages: /@types/concat-stream@2.0.1: resolution: {integrity: sha512-v5HP9ZsRbzFq5XRo2liUZPKzwbGK5SuGVMWZjE6iJOm/JNdESk3/rkfcPe0lcal0C32PTLVlYUYqGpMGNdDsDg==} dependencies: - '@types/node': 18.18.8 + '@types/node': 18.18.9 dev: true /@types/connect@3.4.37: resolution: {integrity: sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==} dependencies: - '@types/node': 18.18.8 + '@types/node': 18.18.9 dev: true /@types/cookiejar@2.1.4: @@ -7716,7 +7719,7 @@ packages: /@types/cross-spawn@6.0.4: resolution: {integrity: sha512-GGLpeThc2Bu8FBGmVn76ZU3lix17qZensEI4/MPty0aZpm2CHfgEMis31pf5X5EiudYKcPAsWciAsCALoPo5dw==} dependencies: - '@types/node': 18.18.8 + '@types/node': 18.18.9 dev: true /@types/debug@4.1.10: @@ -7777,7 +7780,7 @@ packages: /@types/express-serve-static-core@4.17.40: resolution: {integrity: sha512-dzQWNQktgK3AyMpPeIeWbnR/ve2wU0bDSfdhf+RSt1ivelrO3hwfrKjTZvJDK4IyGWlDoRj+knNSePnL7OUqOA==} dependencies: - '@types/node': 18.18.8 + '@types/node': 18.18.9 '@types/qs': 6.9.9 '@types/range-parser': 1.2.6 '@types/send': 0.17.3 @@ -7800,7 +7803,7 @@ packages: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 18.18.8 + '@types/node': 18.18.9 dev: true /@types/graceful-fs@4.1.8: @@ -7973,6 +7976,7 @@ packages: resolution: {integrity: sha512-OLGBaaK5V3VRBS1bAkMVP2/W9B+H8meUfl866OrMNQqt7wDgdpWPp5o6gmIc9pB+lIQHSq4ZL8ypeH1vPxcPaQ==} dependencies: undici-types: 5.26.5 + dev: true /@types/node@18.18.9: resolution: {integrity: sha512-0f5klcuImLnG4Qreu9hPj/rEfFq6YRc5n2mAjSsH+ec/mJL+3voBH0+8T7o8RpFjH7ovc+TRsL/c7OYIQsPTfQ==} @@ -8048,7 +8052,7 @@ packages: resolution: {integrity: sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==} dependencies: '@types/mime': 1.3.4 - '@types/node': 18.18.8 + '@types/node': 18.18.9 dev: true /@types/serve-static@1.15.4: @@ -8056,7 +8060,7 @@ packages: dependencies: '@types/http-errors': 2.0.3 '@types/mime': 3.0.3 - '@types/node': 18.18.8 + '@types/node': 18.18.9 dev: true /@types/stack-utils@2.0.2: @@ -8082,7 +8086,7 @@ packages: /@types/through@0.0.32: resolution: {integrity: sha512-7XsfXIsjdfJM2wFDRAtEWp3zb2aVPk5QeyZxGlVK57q4u26DczMHhJmlhr0Jqv0THwxam/L8REXkj8M2I/lcvw==} dependencies: - '@types/node': 18.18.8 + '@types/node': 18.18.9 dev: true /@types/tinycolor2@1.4.5: @@ -9073,8 +9077,8 @@ packages: pretty-format: 29.7.0 dev: true - /@vladfrangu/async_event_emitter@2.2.2: - resolution: {integrity: sha512-HIzRG7sy88UZjBJamssEczH5q7t5+axva19UbZLO6u0ySbYPrwzWiXBcC0WuHyhKKoeCyneH+FvYzKQq/zTtkQ==} + /@vladfrangu/async_event_emitter@2.2.4: + resolution: {integrity: sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug==} engines: {node: '>=v14.0.0', npm: '>=7.0.0'} dev: false @@ -10606,6 +10610,7 @@ packages: engines: {node: '>=0.10.0'} requiresBuild: true dev: true + optional: true /collect-all@1.0.4: resolution: {integrity: sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==} @@ -11401,7 +11406,7 @@ packages: supports-color: optional: true dependencies: - ms: 2.1.1 + ms: 2.1.3 dev: true /debug@4.3.4: @@ -11781,7 +11786,7 @@ packages: dependencies: semver: 7.5.4 shelljs: 0.8.5 - typescript: 5.4.0-dev.20231113 + typescript: 5.4.0-dev.20231211 dev: true /dts-critic@3.3.11(typescript@5.2.2): @@ -11793,7 +11798,7 @@ packages: typescript: optional: true dependencies: - '@definitelytyped/header-parser': 0.0.188 + '@definitelytyped/header-parser': 0.0.190 command-exists: 1.2.9 rimraf: 3.0.2 semver: 6.3.1 @@ -11812,9 +11817,9 @@ packages: typescript: optional: true dependencies: - '@definitelytyped/header-parser': 0.0.188 - '@definitelytyped/typescript-versions': 0.0.181 - '@definitelytyped/utils': 0.0.186 + '@definitelytyped/header-parser': 0.0.190 + '@definitelytyped/typescript-versions': 0.0.182 + '@definitelytyped/utils': 0.0.188 dts-critic: 3.3.11(typescript@5.2.2) fs-extra: 6.0.1 json-stable-stringify: 1.0.2 @@ -14944,6 +14949,7 @@ packages: dependencies: number-is-nan: 1.0.1 dev: true + optional: true /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} @@ -17969,6 +17975,7 @@ packages: engines: {node: '>=0.10.0'} requiresBuild: true dev: true + optional: true /nwsapi@2.2.7: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} @@ -18903,7 +18910,7 @@ packages: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 18.18.8 + '@types/node': 18.18.9 long: 5.2.3 dev: false @@ -20571,6 +20578,7 @@ packages: is-fullwidth-code-point: 1.0.0 strip-ansi: 3.0.1 dev: true + optional: true /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -21749,8 +21757,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - /typescript@5.4.0-dev.20231113: - resolution: {integrity: sha512-5K165L/tImARYZDKwwT2ER9qKt0n56E8jxldXfAVpq8qNqX5o2SvpoPrzCi+eddkHJHl1gPf26xiE+7R6//1Gg==} + /typescript@5.4.0-dev.20231211: + resolution: {integrity: sha512-QbX1BYW7kMO+l74HzSfmOSGl66t/DmtqnNRcaUTeowtc/SX/v7WCV3jpuaHgAIS0eDKorcRoRizmWrxlvBOeUQ==} engines: {node: '>=14.17'} hasBin: true dev: true @@ -22859,7 +22867,7 @@ packages: /wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} dependencies: - string-width: 1.0.2 + string-width: 4.2.3 dev: true /wordwrap@1.0.0: