@fishjam-cloud/ts-client 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import * as _m0 from "protobufjs/minimal";
1
+ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
2
2
  export declare const protobufPackage = "fishjam";
3
3
  /** Defines any type of message sent between FJ and a peer */
4
4
  export interface PeerMessage {
@@ -25,46 +25,11 @@ export interface PeerMessage_MediaEvent {
25
25
  export interface PeerMessage_RTCStatsReport {
26
26
  data: string;
27
27
  }
28
- export declare const PeerMessage: {
29
- encode(message: PeerMessage, writer?: _m0.Writer): _m0.Writer;
30
- decode(input: _m0.Reader | Uint8Array, length?: number): PeerMessage;
31
- fromJSON(object: any): PeerMessage;
32
- toJSON(message: PeerMessage): unknown;
33
- create<I extends Exact<DeepPartial<PeerMessage>, I>>(base?: I): PeerMessage;
34
- fromPartial<I extends Exact<DeepPartial<PeerMessage>, I>>(object: I): PeerMessage;
35
- };
36
- export declare const PeerMessage_Authenticated: {
37
- encode(_: PeerMessage_Authenticated, writer?: _m0.Writer): _m0.Writer;
38
- decode(input: _m0.Reader | Uint8Array, length?: number): PeerMessage_Authenticated;
39
- fromJSON(_: any): PeerMessage_Authenticated;
40
- toJSON(_: PeerMessage_Authenticated): unknown;
41
- create<I extends Exact<DeepPartial<PeerMessage_Authenticated>, I>>(base?: I): PeerMessage_Authenticated;
42
- fromPartial<I extends Exact<DeepPartial<PeerMessage_Authenticated>, I>>(_: I): PeerMessage_Authenticated;
43
- };
44
- export declare const PeerMessage_AuthRequest: {
45
- encode(message: PeerMessage_AuthRequest, writer?: _m0.Writer): _m0.Writer;
46
- decode(input: _m0.Reader | Uint8Array, length?: number): PeerMessage_AuthRequest;
47
- fromJSON(object: any): PeerMessage_AuthRequest;
48
- toJSON(message: PeerMessage_AuthRequest): unknown;
49
- create<I extends Exact<DeepPartial<PeerMessage_AuthRequest>, I>>(base?: I): PeerMessage_AuthRequest;
50
- fromPartial<I extends Exact<DeepPartial<PeerMessage_AuthRequest>, I>>(object: I): PeerMessage_AuthRequest;
51
- };
52
- export declare const PeerMessage_MediaEvent: {
53
- encode(message: PeerMessage_MediaEvent, writer?: _m0.Writer): _m0.Writer;
54
- decode(input: _m0.Reader | Uint8Array, length?: number): PeerMessage_MediaEvent;
55
- fromJSON(object: any): PeerMessage_MediaEvent;
56
- toJSON(message: PeerMessage_MediaEvent): unknown;
57
- create<I extends Exact<DeepPartial<PeerMessage_MediaEvent>, I>>(base?: I): PeerMessage_MediaEvent;
58
- fromPartial<I extends Exact<DeepPartial<PeerMessage_MediaEvent>, I>>(object: I): PeerMessage_MediaEvent;
59
- };
60
- export declare const PeerMessage_RTCStatsReport: {
61
- encode(message: PeerMessage_RTCStatsReport, writer?: _m0.Writer): _m0.Writer;
62
- decode(input: _m0.Reader | Uint8Array, length?: number): PeerMessage_RTCStatsReport;
63
- fromJSON(object: any): PeerMessage_RTCStatsReport;
64
- toJSON(message: PeerMessage_RTCStatsReport): unknown;
65
- create<I extends Exact<DeepPartial<PeerMessage_RTCStatsReport>, I>>(base?: I): PeerMessage_RTCStatsReport;
66
- fromPartial<I extends Exact<DeepPartial<PeerMessage_RTCStatsReport>, I>>(object: I): PeerMessage_RTCStatsReport;
67
- };
28
+ export declare const PeerMessage: MessageFns<PeerMessage>;
29
+ export declare const PeerMessage_Authenticated: MessageFns<PeerMessage_Authenticated>;
30
+ export declare const PeerMessage_AuthRequest: MessageFns<PeerMessage_AuthRequest>;
31
+ export declare const PeerMessage_MediaEvent: MessageFns<PeerMessage_MediaEvent>;
32
+ export declare const PeerMessage_RTCStatsReport: MessageFns<PeerMessage_RTCStatsReport>;
68
33
  type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
69
34
  export type DeepPartial<T> = T extends Builtin ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {} ? {
70
35
  [K in keyof T]?: DeepPartial<T[K]>;
@@ -75,4 +40,12 @@ export type Exact<P, I extends P> = P extends Builtin ? P : P & {
75
40
  } & {
76
41
  [K in Exclude<keyof I, KeysOfUnion<P>>]: never;
77
42
  };
43
+ export interface MessageFns<T> {
44
+ encode(message: T, writer?: BinaryWriter): BinaryWriter;
45
+ decode(input: BinaryReader | Uint8Array, length?: number): T;
46
+ fromJSON(object: any): T;
47
+ toJSON(message: T): unknown;
48
+ create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
49
+ fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
50
+ }
78
51
  export {};
@@ -1,66 +1,70 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v1.181.1
4
- // protoc v4.25.1
3
+ // protoc-gen-ts_proto v2.2.3
4
+ // protoc v5.26.1
5
5
  // source: protos/fishjam/peer_notifications.proto
6
6
  /* eslint-disable */
7
- import * as _m0 from "protobufjs/minimal";
7
+ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
8
8
  export const protobufPackage = "fishjam";
9
9
  function createBasePeerMessage() {
10
10
  return { authenticated: undefined, authRequest: undefined, mediaEvent: undefined, rtcStatsReport: undefined };
11
11
  }
12
12
  export const PeerMessage = {
13
- encode(message, writer = _m0.Writer.create()) {
13
+ encode(message, writer = new BinaryWriter()) {
14
14
  if (message.authenticated !== undefined) {
15
- PeerMessage_Authenticated.encode(message.authenticated, writer.uint32(10).fork()).ldelim();
15
+ PeerMessage_Authenticated.encode(message.authenticated, writer.uint32(10).fork()).join();
16
16
  }
17
17
  if (message.authRequest !== undefined) {
18
- PeerMessage_AuthRequest.encode(message.authRequest, writer.uint32(18).fork()).ldelim();
18
+ PeerMessage_AuthRequest.encode(message.authRequest, writer.uint32(18).fork()).join();
19
19
  }
20
20
  if (message.mediaEvent !== undefined) {
21
- PeerMessage_MediaEvent.encode(message.mediaEvent, writer.uint32(26).fork()).ldelim();
21
+ PeerMessage_MediaEvent.encode(message.mediaEvent, writer.uint32(26).fork()).join();
22
22
  }
23
23
  if (message.rtcStatsReport !== undefined) {
24
- PeerMessage_RTCStatsReport.encode(message.rtcStatsReport, writer.uint32(34).fork()).ldelim();
24
+ PeerMessage_RTCStatsReport.encode(message.rtcStatsReport, writer.uint32(34).fork()).join();
25
25
  }
26
26
  return writer;
27
27
  },
28
28
  decode(input, length) {
29
- const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
29
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
30
30
  let end = length === undefined ? reader.len : reader.pos + length;
31
31
  const message = createBasePeerMessage();
32
32
  while (reader.pos < end) {
33
33
  const tag = reader.uint32();
34
34
  switch (tag >>> 3) {
35
- case 1:
35
+ case 1: {
36
36
  if (tag !== 10) {
37
37
  break;
38
38
  }
39
39
  message.authenticated = PeerMessage_Authenticated.decode(reader, reader.uint32());
40
40
  continue;
41
- case 2:
41
+ }
42
+ case 2: {
42
43
  if (tag !== 18) {
43
44
  break;
44
45
  }
45
46
  message.authRequest = PeerMessage_AuthRequest.decode(reader, reader.uint32());
46
47
  continue;
47
- case 3:
48
+ }
49
+ case 3: {
48
50
  if (tag !== 26) {
49
51
  break;
50
52
  }
51
53
  message.mediaEvent = PeerMessage_MediaEvent.decode(reader, reader.uint32());
52
54
  continue;
53
- case 4:
55
+ }
56
+ case 4: {
54
57
  if (tag !== 34) {
55
58
  break;
56
59
  }
57
60
  message.rtcStatsReport = PeerMessage_RTCStatsReport.decode(reader, reader.uint32());
58
61
  continue;
62
+ }
59
63
  }
60
64
  if ((tag & 7) === 4 || tag === 0) {
61
65
  break;
62
66
  }
63
- reader.skipType(tag & 7);
67
+ reader.skip(tag & 7);
64
68
  }
65
69
  return message;
66
70
  },
@@ -114,11 +118,11 @@ function createBasePeerMessage_Authenticated() {
114
118
  return {};
115
119
  }
116
120
  export const PeerMessage_Authenticated = {
117
- encode(_, writer = _m0.Writer.create()) {
121
+ encode(_, writer = new BinaryWriter()) {
118
122
  return writer;
119
123
  },
120
124
  decode(input, length) {
121
- const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
125
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
122
126
  let end = length === undefined ? reader.len : reader.pos + length;
123
127
  const message = createBasePeerMessage_Authenticated();
124
128
  while (reader.pos < end) {
@@ -128,7 +132,7 @@ export const PeerMessage_Authenticated = {
128
132
  if ((tag & 7) === 4 || tag === 0) {
129
133
  break;
130
134
  }
131
- reader.skipType(tag & 7);
135
+ reader.skip(tag & 7);
132
136
  }
133
137
  return message;
134
138
  },
@@ -151,30 +155,31 @@ function createBasePeerMessage_AuthRequest() {
151
155
  return { token: "" };
152
156
  }
153
157
  export const PeerMessage_AuthRequest = {
154
- encode(message, writer = _m0.Writer.create()) {
158
+ encode(message, writer = new BinaryWriter()) {
155
159
  if (message.token !== "") {
156
160
  writer.uint32(10).string(message.token);
157
161
  }
158
162
  return writer;
159
163
  },
160
164
  decode(input, length) {
161
- const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
165
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
162
166
  let end = length === undefined ? reader.len : reader.pos + length;
163
167
  const message = createBasePeerMessage_AuthRequest();
164
168
  while (reader.pos < end) {
165
169
  const tag = reader.uint32();
166
170
  switch (tag >>> 3) {
167
- case 1:
171
+ case 1: {
168
172
  if (tag !== 10) {
169
173
  break;
170
174
  }
171
175
  message.token = reader.string();
172
176
  continue;
177
+ }
173
178
  }
174
179
  if ((tag & 7) === 4 || tag === 0) {
175
180
  break;
176
181
  }
177
- reader.skipType(tag & 7);
182
+ reader.skip(tag & 7);
178
183
  }
179
184
  return message;
180
185
  },
@@ -201,30 +206,31 @@ function createBasePeerMessage_MediaEvent() {
201
206
  return { data: "" };
202
207
  }
203
208
  export const PeerMessage_MediaEvent = {
204
- encode(message, writer = _m0.Writer.create()) {
209
+ encode(message, writer = new BinaryWriter()) {
205
210
  if (message.data !== "") {
206
211
  writer.uint32(10).string(message.data);
207
212
  }
208
213
  return writer;
209
214
  },
210
215
  decode(input, length) {
211
- const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
216
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
212
217
  let end = length === undefined ? reader.len : reader.pos + length;
213
218
  const message = createBasePeerMessage_MediaEvent();
214
219
  while (reader.pos < end) {
215
220
  const tag = reader.uint32();
216
221
  switch (tag >>> 3) {
217
- case 1:
222
+ case 1: {
218
223
  if (tag !== 10) {
219
224
  break;
220
225
  }
221
226
  message.data = reader.string();
222
227
  continue;
228
+ }
223
229
  }
224
230
  if ((tag & 7) === 4 || tag === 0) {
225
231
  break;
226
232
  }
227
- reader.skipType(tag & 7);
233
+ reader.skip(tag & 7);
228
234
  }
229
235
  return message;
230
236
  },
@@ -251,30 +257,31 @@ function createBasePeerMessage_RTCStatsReport() {
251
257
  return { data: "" };
252
258
  }
253
259
  export const PeerMessage_RTCStatsReport = {
254
- encode(message, writer = _m0.Writer.create()) {
260
+ encode(message, writer = new BinaryWriter()) {
255
261
  if (message.data !== "") {
256
262
  writer.uint32(10).string(message.data);
257
263
  }
258
264
  return writer;
259
265
  },
260
266
  decode(input, length) {
261
- const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
267
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
262
268
  let end = length === undefined ? reader.len : reader.pos + length;
263
269
  const message = createBasePeerMessage_RTCStatsReport();
264
270
  while (reader.pos < end) {
265
271
  const tag = reader.uint32();
266
272
  switch (tag >>> 3) {
267
- case 1:
273
+ case 1: {
268
274
  if (tag !== 10) {
269
275
  break;
270
276
  }
271
277
  message.data = reader.string();
272
278
  continue;
279
+ }
273
280
  }
274
281
  if ((tag & 7) === 4 || tag === 0) {
275
282
  break;
276
283
  }
277
- reader.skipType(tag & 7);
284
+ reader.skip(tag & 7);
278
285
  }
279
286
  return message;
280
287
  },
@@ -2,10 +2,10 @@ import type { Deferred } from './deferred';
2
2
  import type { LocalTrackManager } from './tracks/LocalTrackManager';
3
3
  import type { ConnectionManager } from './ConnectionManager';
4
4
  export type Command = {
5
- handler: () => void;
5
+ handler: () => Promise<void>;
6
6
  parse?: () => void;
7
7
  resolutionNotifier: Deferred<void>;
8
- resolve: 'after-renegotiation' | 'immediately';
8
+ resolve: 'after-renegotiation' | 'on-handler-resolve';
9
9
  };
10
10
  export declare class CommandsQueue<EndpointMetadata, TrackMetadata> {
11
11
  private readonly localTrackManager;
@@ -56,11 +56,12 @@ export class CommandsQueue {
56
56
  this.commandResolutionNotifier = command.resolutionNotifier;
57
57
  this.handleCommand(command);
58
58
  };
59
- handleCommand = (command) => {
59
+ handleCommand = async (command) => {
60
60
  try {
61
61
  command.parse?.();
62
- command.handler();
63
- if (command.resolve === 'immediately') {
62
+ const promise = command.handler();
63
+ if (command.resolve === 'on-handler-resolve') {
64
+ await promise;
64
65
  this.resolvePreviousCommand();
65
66
  this.processNextCommand();
66
67
  }
@@ -1,7 +1,8 @@
1
- import { generateCustomEvent, generateMediaEvent } from '../mediaEvent';
1
+ import { generateCustomEvent } from '../mediaEvent';
2
2
  import { defaultBitrates, defaultSimulcastBitrates, UNLIMITED_BANDWIDTH } from '../bitrate';
3
3
  import { getEncodingParameters } from './encodings';
4
4
  import { createTransceiverConfig } from './transceivers';
5
+ import { emitMutableEvents, getActionType } from './muteTrackUtils';
5
6
  /**
6
7
  * This is a wrapper over `TrackContext` that adds additional properties such as:
7
8
  * - `MLineId`: required to generate sdpOffer
@@ -99,6 +100,7 @@ export class LocalTrack {
99
100
  replaceTrack = async (newTrack, webrtc) => {
100
101
  const trackId = this.id;
101
102
  const stream = this.trackContext.stream;
103
+ const oldTrack = this.trackContext.track;
102
104
  if (!this.sender)
103
105
  throw Error('There is no RTCRtpSender for this track id!');
104
106
  stream?.getTracks().forEach((track) => {
@@ -107,25 +109,25 @@ export class LocalTrack {
107
109
  if (newTrack) {
108
110
  stream?.addTrack(newTrack);
109
111
  }
110
- if (this.trackContext.track && !newTrack) {
111
- const mediaEvent = generateMediaEvent('muteTrack', { trackId: trackId });
112
- webrtc.sendMediaEvent(mediaEvent);
113
- webrtc.emit('localTrackMuted', { trackId: trackId });
114
- }
115
- else if (!this.trackContext.track && newTrack) {
116
- const mediaEvent = generateMediaEvent('unmuteTrack', {
117
- trackId: trackId,
118
- });
119
- webrtc.sendMediaEvent(mediaEvent);
120
- webrtc.emit('localTrackUnmuted', { trackId: trackId });
121
- }
112
+ this.trackContext.track = newTrack;
122
113
  this.mediaStreamTrackId = newTrack?.id ?? null;
114
+ const action = getActionType(this.trackContext.track, newTrack);
115
+ if (action === 'mute' || action === 'unmute') {
116
+ emitMutableEvents(action, webrtc, trackId);
117
+ }
123
118
  try {
124
119
  await this.sender.replaceTrack(newTrack);
125
- this.trackContext.track = newTrack;
126
120
  }
127
121
  catch (_error) {
128
- // ignore
122
+ // rollback: emit opposite events and revert internal state
123
+ if (action === 'mute') {
124
+ emitMutableEvents('unmute', webrtc, trackId);
125
+ }
126
+ else if (action === 'unmute') {
127
+ emitMutableEvents('mute', webrtc, trackId);
128
+ }
129
+ this.trackContext.track = oldTrack;
130
+ this.mediaStreamTrackId = oldTrack?.id ?? null;
129
131
  }
130
132
  };
131
133
  setTrackBandwidth = (bandwidth) => {
@@ -0,0 +1,3 @@
1
+ import type { WebRTCEndpoint } from '../webRTCEndpoint';
2
+ export declare function emitMutableEvents<EndpointMetadata, TrackMetadata>(action: 'mute' | 'unmute', webrtc: WebRTCEndpoint<EndpointMetadata, TrackMetadata>, trackId: string): void;
3
+ export declare function getActionType(currentTrack: MediaStreamTrack | null, newTrack: MediaStreamTrack | null): 'mute' | 'unmute' | 'replace';
@@ -0,0 +1,19 @@
1
+ import { generateMediaEvent } from '../mediaEvent';
2
+ export function emitMutableEvents(action, webrtc, trackId) {
3
+ const mediaEventType = action === 'mute' ? `muteTrack` : `unmuteTrack`;
4
+ const localEventType = action === 'mute' ? `localTrackMuted` : `localTrackUnmuted`;
5
+ const mediaEvent = generateMediaEvent(mediaEventType, { trackId: trackId });
6
+ webrtc.sendMediaEvent(mediaEvent);
7
+ webrtc.emit(localEventType, { trackId: trackId });
8
+ }
9
+ export function getActionType(currentTrack, newTrack) {
10
+ if (currentTrack && !newTrack) {
11
+ return 'mute';
12
+ }
13
+ else if (!currentTrack && newTrack) {
14
+ return 'unmute';
15
+ }
16
+ else {
17
+ return 'replace';
18
+ }
19
+ }
@@ -16,8 +16,22 @@ const createAudioTransceiverConfig = (stream) => {
16
16
  const createVideoTransceiverConfig = (trackContext, maxBandwidth) => {
17
17
  if (!trackContext.simulcastConfig)
18
18
  throw new Error(`Simulcast config for track ${trackContext.trackId} not found.`);
19
- if (typeof maxBandwidth !== 'number' && trackContext.simulcastConfig.enabled) {
20
- return createSimulcastTransceiverConfig(trackContext, maxBandwidth);
19
+ if (trackContext.simulcastConfig.enabled) {
20
+ let simulcastConfig;
21
+ if (maxBandwidth === 0) {
22
+ simulcastConfig = new Map([
23
+ ['l', 0],
24
+ ['m', 0],
25
+ ['h', 0],
26
+ ]);
27
+ }
28
+ else if (typeof maxBandwidth === 'number') {
29
+ throw new Error('Invalid bandwidth limit for simulcast track.');
30
+ }
31
+ else {
32
+ simulcastConfig = maxBandwidth;
33
+ }
34
+ return createSimulcastTransceiverConfig(trackContext, simulcastConfig);
21
35
  }
22
36
  if (typeof maxBandwidth === 'number') {
23
37
  return createNonSimulcastTransceiverConfig(trackContext, maxBandwidth);
@@ -327,9 +327,7 @@ export class WebRTCEndpoint extends EventEmitter {
327
327
  metadata = parsedMetadata;
328
328
  stream.addTrack(track);
329
329
  this.commandsQueue.pushCommand({
330
- handler: () => {
331
- this.localTrackManager.addTrackHandler(trackId, track, stream, parsedMetadata, simulcastConfig, maxBandwidth);
332
- },
330
+ handler: async () => this.localTrackManager.addTrackHandler(trackId, track, stream, parsedMetadata, simulcastConfig, maxBandwidth),
333
331
  parse: () => this.localTrackManager.parseAddTrack(track, simulcastConfig, maxBandwidth),
334
332
  resolve: 'after-renegotiation',
335
333
  resolutionNotifier,
@@ -397,11 +395,9 @@ export class WebRTCEndpoint extends EventEmitter {
397
395
  async replaceTrack(trackId, newTrack) {
398
396
  const resolutionNotifier = new Deferred();
399
397
  this.commandsQueue.pushCommand({
400
- handler: () => {
401
- this.localTrackManager.replaceTrackHandler(this, trackId, newTrack);
402
- },
398
+ handler: () => this.localTrackManager.replaceTrackHandler(this, trackId, newTrack),
403
399
  resolutionNotifier,
404
- resolve: 'immediately',
400
+ resolve: 'on-handler-resolve',
405
401
  });
406
402
  return resolutionNotifier.promise.then(() => {
407
403
  this.emit('localTrackReplaced', { trackId, track: newTrack });
@@ -466,9 +462,7 @@ export class WebRTCEndpoint extends EventEmitter {
466
462
  async removeTrack(trackId) {
467
463
  const resolutionNotifier = new Deferred();
468
464
  this.commandsQueue.pushCommand({
469
- handler: () => {
470
- this.localTrackManager.removeTrackHandler(trackId);
471
- },
465
+ handler: async () => this.localTrackManager.removeTrackHandler(trackId),
472
466
  resolutionNotifier,
473
467
  resolve: 'after-renegotiation',
474
468
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fishjam-cloud/ts-client",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Typescript client library for Fishjam Cloud",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Fishjam Cloud Team",
@@ -53,20 +53,20 @@
53
53
  "devDependencies": {
54
54
  "@playwright/test": "^1.47.2",
55
55
  "@types/events": "^3.0.3",
56
- "@types/node": "^22.7.4",
56
+ "@types/node": "^22.7.5",
57
57
  "@types/uuid": "^10.0.0",
58
- "@vitest/coverage-v8": "^2.1.1",
58
+ "@vitest/coverage-v8": "^2.1.2",
59
59
  "fake-mediastreamtrack": "^1.2.0",
60
60
  "husky": "^9.1.6",
61
61
  "lint-staged": "^15.2.10",
62
62
  "react": "^18.2.0",
63
- "ts-proto": "^2.2.1",
63
+ "ts-proto": "^2.2.3",
64
64
  "typed-emitter": "^2.1.0",
65
- "typedoc": "^0.26.7",
65
+ "typedoc": "^0.26.8",
66
66
  "typedoc-plugin-external-resolver": "^1.0.3",
67
67
  "typedoc-plugin-mdn-links": "^3.3.2",
68
68
  "typescript": "^5.6.2",
69
- "vitest": "^2.1.1",
69
+ "vitest": "^2.1.2",
70
70
  "zod": "^3.23.6"
71
71
  },
72
72
  "lint-staged": {