@stream-io/video-client 1.10.5 → 1.11.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,6 @@
1
- import type { JsonReadOptions, JsonValue, JsonWriteOptions } from '@protobuf-ts/runtime';
1
+ import type { JsonValue } from '@protobuf-ts/runtime';
2
+ import type { JsonReadOptions } from '@protobuf-ts/runtime';
3
+ import type { JsonWriteOptions } from '@protobuf-ts/runtime';
2
4
  import { MessageType } from '@protobuf-ts/runtime';
3
5
  /**
4
6
  * `Struct` represents a structured data value, consisting of fields
@@ -1,4 +1,6 @@
1
- import type { JsonReadOptions, JsonValue, JsonWriteOptions } from '@protobuf-ts/runtime';
1
+ import type { JsonValue } from '@protobuf-ts/runtime';
2
+ import type { JsonReadOptions } from '@protobuf-ts/runtime';
3
+ import type { JsonWriteOptions } from '@protobuf-ts/runtime';
2
4
  import { MessageType } from '@protobuf-ts/runtime';
3
5
  /**
4
6
  * A Timestamp represents a point in time independent of any time zone or local
@@ -1,6 +1,24 @@
1
1
  import { MessageType } from '@protobuf-ts/runtime';
2
- import { CallEndedReason, CallGrants, CallState, ClientDetails, Codec, ConnectionQuality, Error as Error$, GoAwayReason, ICETrickle as ICETrickle$, Participant, ParticipantCount, PeerType, Pin, TrackInfo, TrackType, TrackUnpublishReason, WebsocketReconnectStrategy } from '../models/models';
2
+ import { CallEndedReason } from '../models/models';
3
+ import { GoAwayReason } from '../models/models';
4
+ import { CallGrants } from '../models/models';
5
+ import { Codec } from '../models/models';
6
+ import { ConnectionQuality } from '../models/models';
7
+ import { PublishOptions } from '../models/models';
8
+ import { CallState } from '../models/models';
3
9
  import { TrackSubscriptionDetails } from '../signal_rpc/signal';
10
+ import { TrackInfo } from '../models/models';
11
+ import { ClientDetails } from '../models/models';
12
+ import { TrackUnpublishReason } from '../models/models';
13
+ import { Participant } from '../models/models';
14
+ import { TrackType } from '../models/models';
15
+ import { ParticipantCount } from '../models/models';
16
+ import { PeerType } from '../models/models';
17
+ import { WebsocketReconnectStrategy } from '../models/models';
18
+ import { Error as Error$ } from '../models/models';
19
+ import { Pin } from '../models/models';
20
+ import { PublishOption } from '../models/models';
21
+ import { ICETrickle as ICETrickle$ } from '../models/models';
4
22
  /**
5
23
  * SFUEvent is a message that is sent from the SFU to the client.
6
24
  *
@@ -200,10 +218,41 @@ export interface SfuEvent {
200
218
  * @generated from protobuf field: stream.video.sfu.event.ParticipantMigrationComplete participant_migration_complete = 25;
201
219
  */
202
220
  participantMigrationComplete: ParticipantMigrationComplete;
221
+ } | {
222
+ oneofKind: 'codecNegotiationComplete';
223
+ /**
224
+ * CodecNegotiationComplete is sent to signal the completion of a codec negotiation.
225
+ * SDKs can safely stop previous transceivers
226
+ *
227
+ * @generated from protobuf field: stream.video.sfu.event.CodecNegotiationComplete codec_negotiation_complete = 26;
228
+ */
229
+ codecNegotiationComplete: CodecNegotiationComplete;
230
+ } | {
231
+ oneofKind: 'changePublishOptions';
232
+ /**
233
+ * ChangePublishOptions is sent to signal the change in publish options such as a new codec or simulcast layers
234
+ *
235
+ * @generated from protobuf field: stream.video.sfu.event.ChangePublishOptions change_publish_options = 27;
236
+ */
237
+ changePublishOptions: ChangePublishOptions;
203
238
  } | {
204
239
  oneofKind: undefined;
205
240
  };
206
241
  }
242
+ /**
243
+ * @generated from protobuf message stream.video.sfu.event.ChangePublishOptions
244
+ */
245
+ export interface ChangePublishOptions {
246
+ /**
247
+ * @generated from protobuf field: stream.video.sfu.models.PublishOption publish_option = 1;
248
+ */
249
+ publishOption?: PublishOption;
250
+ }
251
+ /**
252
+ * @generated from protobuf message stream.video.sfu.event.CodecNegotiationComplete
253
+ */
254
+ export interface CodecNegotiationComplete {
255
+ }
207
256
  /**
208
257
  * @generated from protobuf message stream.video.sfu.event.ParticipantMigrationComplete
209
258
  */
@@ -392,6 +441,10 @@ export interface JoinRequest {
392
441
  * @generated from protobuf field: string subscriber_sdp = 3;
393
442
  */
394
443
  subscriberSdp: string;
444
+ /**
445
+ * @generated from protobuf field: string publisher_sdp = 8;
446
+ */
447
+ publisherSdp: string;
395
448
  /**
396
449
  * @generated from protobuf field: stream.video.sfu.models.ClientDetails client_details = 4;
397
450
  */
@@ -487,6 +540,10 @@ export interface JoinResponse {
487
540
  * @generated from protobuf field: int32 fast_reconnect_deadline_seconds = 3;
488
541
  */
489
542
  fastReconnectDeadlineSeconds: number;
543
+ /**
544
+ * @generated from protobuf field: stream.video.sfu.models.PublishOptions publish_options = 4;
545
+ */
546
+ publishOptions?: PublishOptions;
490
547
  }
491
548
  /**
492
549
  * ParticipantJoined is fired when a user joins a call
@@ -770,6 +827,20 @@ declare class SfuEvent$Type extends MessageType<SfuEvent> {
770
827
  * @generated MessageType for protobuf message stream.video.sfu.event.SfuEvent
771
828
  */
772
829
  export declare const SfuEvent: SfuEvent$Type;
830
+ declare class ChangePublishOptions$Type extends MessageType<ChangePublishOptions> {
831
+ constructor();
832
+ }
833
+ /**
834
+ * @generated MessageType for protobuf message stream.video.sfu.event.ChangePublishOptions
835
+ */
836
+ export declare const ChangePublishOptions: ChangePublishOptions$Type;
837
+ declare class CodecNegotiationComplete$Type extends MessageType<CodecNegotiationComplete> {
838
+ constructor();
839
+ }
840
+ /**
841
+ * @generated MessageType for protobuf message stream.video.sfu.event.CodecNegotiationComplete
842
+ */
843
+ export declare const CodecNegotiationComplete: CodecNegotiationComplete$Type;
773
844
  declare class ParticipantMigrationComplete$Type extends MessageType<ParticipantMigrationComplete> {
774
845
  constructor();
775
846
  }
@@ -189,34 +189,68 @@ export interface VideoLayer {
189
189
  */
190
190
  quality: VideoQuality;
191
191
  }
192
+ /**
193
+ * @generated from protobuf message stream.video.sfu.models.PublishOptions
194
+ */
195
+ export interface PublishOptions {
196
+ /**
197
+ * @generated from protobuf field: repeated stream.video.sfu.models.PublishOption codecs = 1;
198
+ */
199
+ codecs: PublishOption[];
200
+ }
201
+ /**
202
+ * @generated from protobuf message stream.video.sfu.models.PublishOption
203
+ */
204
+ export interface PublishOption {
205
+ /**
206
+ * @generated from protobuf field: stream.video.sfu.models.TrackType track_type = 1;
207
+ */
208
+ trackType: TrackType;
209
+ /**
210
+ * @generated from protobuf field: stream.video.sfu.models.Codec codec = 2;
211
+ */
212
+ codec?: Codec;
213
+ /**
214
+ * @generated from protobuf field: int32 bitrate = 3;
215
+ */
216
+ bitrate: number;
217
+ /**
218
+ * @generated from protobuf field: int32 fps = 4;
219
+ */
220
+ fps: number;
221
+ /**
222
+ * @generated from protobuf field: int32 max_spatial_layers = 5;
223
+ */
224
+ maxSpatialLayers: number;
225
+ /**
226
+ * @generated from protobuf field: int32 max_temporal_layers = 6;
227
+ */
228
+ maxTemporalLayers: number;
229
+ }
192
230
  /**
193
231
  * @generated from protobuf message stream.video.sfu.models.Codec
194
232
  */
195
233
  export interface Codec {
196
234
  /**
197
- * @generated from protobuf field: uint32 payload_type = 1;
235
+ * @generated from protobuf field: uint32 payload_type = 11;
198
236
  */
199
237
  payloadType: number;
200
238
  /**
201
- * @generated from protobuf field: string name = 2;
239
+ * @generated from protobuf field: string name = 10;
202
240
  */
203
241
  name: string;
204
242
  /**
205
- * @generated from protobuf field: string fmtp_line = 3;
206
- */
207
- fmtpLine: string;
208
- /**
209
- * @generated from protobuf field: uint32 clock_rate = 4;
243
+ * @generated from protobuf field: uint32 clock_rate = 14;
210
244
  */
211
245
  clockRate: number;
212
246
  /**
213
- * @generated from protobuf field: string encoding_parameters = 5;
247
+ * @generated from protobuf field: string encoding_parameters = 13;
214
248
  */
215
249
  encodingParameters: string;
216
250
  /**
217
- * @generated from protobuf field: repeated string feedbacks = 6;
251
+ * @generated from protobuf field: string fmtp = 12;
218
252
  */
219
- feedbacks: string[];
253
+ fmtp: string;
220
254
  }
221
255
  /**
222
256
  * @generated from protobuf message stream.video.sfu.models.ICETrickle
@@ -930,6 +964,20 @@ declare class VideoLayer$Type extends MessageType<VideoLayer> {
930
964
  * @generated MessageType for protobuf message stream.video.sfu.models.VideoLayer
931
965
  */
932
966
  export declare const VideoLayer: VideoLayer$Type;
967
+ declare class PublishOptions$Type extends MessageType<PublishOptions> {
968
+ constructor();
969
+ }
970
+ /**
971
+ * @generated MessageType for protobuf message stream.video.sfu.models.PublishOptions
972
+ */
973
+ export declare const PublishOptions: PublishOptions$Type;
974
+ declare class PublishOption$Type extends MessageType<PublishOption> {
975
+ constructor();
976
+ }
977
+ /**
978
+ * @generated MessageType for protobuf message stream.video.sfu.models.PublishOption
979
+ */
980
+ export declare const PublishOption: PublishOption$Type;
933
981
  declare class Codec$Type extends MessageType<Codec> {
934
982
  constructor();
935
983
  }
@@ -1,6 +1,25 @@
1
- import type { RpcOptions, RpcTransport, ServiceInfo, UnaryCall } from '@protobuf-ts/runtime-rpc';
2
- import type { ICERestartRequest, ICERestartResponse, ICETrickleResponse, SendAnswerRequest, SendAnswerResponse, SendStatsRequest, SendStatsResponse, SetPublisherRequest, SetPublisherResponse, StartNoiseCancellationRequest, StartNoiseCancellationResponse, StopNoiseCancellationRequest, StopNoiseCancellationResponse, UpdateMuteStatesRequest, UpdateMuteStatesResponse, UpdateSubscriptionsRequest, UpdateSubscriptionsResponse } from './signal';
1
+ import type { RpcTransport } from '@protobuf-ts/runtime-rpc';
2
+ import type { ServiceInfo } from '@protobuf-ts/runtime-rpc';
3
+ import type { StopNoiseCancellationResponse } from './signal';
4
+ import type { StopNoiseCancellationRequest } from './signal';
5
+ import type { StartNoiseCancellationResponse } from './signal';
6
+ import type { StartNoiseCancellationRequest } from './signal';
7
+ import type { SendStatsResponse } from './signal';
8
+ import type { SendStatsRequest } from './signal';
9
+ import type { ICERestartResponse } from './signal';
10
+ import type { ICERestartRequest } from './signal';
11
+ import type { UpdateMuteStatesResponse } from './signal';
12
+ import type { UpdateMuteStatesRequest } from './signal';
13
+ import type { UpdateSubscriptionsResponse } from './signal';
14
+ import type { UpdateSubscriptionsRequest } from './signal';
15
+ import type { ICETrickleResponse } from './signal';
3
16
  import type { ICETrickle } from '../models/models';
17
+ import type { SendAnswerResponse } from './signal';
18
+ import type { SendAnswerRequest } from './signal';
19
+ import type { SetPublisherResponse } from './signal';
20
+ import type { SetPublisherRequest } from './signal';
21
+ import type { UnaryCall } from '@protobuf-ts/runtime-rpc';
22
+ import type { RpcOptions } from '@protobuf-ts/runtime-rpc';
4
23
  /**
5
24
  * @generated from protobuf service stream.video.sfu.signal.SignalServer
6
25
  */
@@ -1,6 +1,14 @@
1
- import { AndroidState, AppleState, Error, InputDevices, PeerType, TrackInfo, TrackType, VideoDimension } from '../models/models';
2
1
  import { ServiceType } from '@protobuf-ts/runtime-rpc';
3
2
  import { MessageType } from '@protobuf-ts/runtime';
3
+ import { TrackInfo } from '../models/models';
4
+ import { VideoDimension } from '../models/models';
5
+ import { TrackType } from '../models/models';
6
+ import { PeerType } from '../models/models';
7
+ import { AppleState } from '../models/models';
8
+ import { AndroidState } from '../models/models';
9
+ import { InputDevices } from '../models/models';
10
+ import { WebsocketReconnectStrategy } from '../models/models';
11
+ import { Error } from '../models/models';
4
12
  /**
5
13
  * @generated from protobuf message stream.video.sfu.signal.StartNoiseCancellationRequest
6
14
  */
@@ -37,6 +45,42 @@ export interface StopNoiseCancellationResponse {
37
45
  */
38
46
  error?: Error;
39
47
  }
48
+ /**
49
+ * @generated from protobuf message stream.video.sfu.signal.Reconnection
50
+ */
51
+ export interface Reconnection {
52
+ /**
53
+ * @generated from protobuf field: float time_seconds = 1;
54
+ */
55
+ timeSeconds: number;
56
+ /**
57
+ * @generated from protobuf field: stream.video.sfu.models.WebsocketReconnectStrategy strategy = 2;
58
+ */
59
+ strategy: WebsocketReconnectStrategy;
60
+ }
61
+ /**
62
+ * @generated from protobuf message stream.video.sfu.signal.Telemetry
63
+ */
64
+ export interface Telemetry {
65
+ /**
66
+ * @generated from protobuf oneof: data
67
+ */
68
+ data: {
69
+ oneofKind: 'connectionTimeSeconds';
70
+ /**
71
+ * @generated from protobuf field: float connection_time_seconds = 1;
72
+ */
73
+ connectionTimeSeconds: number;
74
+ } | {
75
+ oneofKind: 'reconnection';
76
+ /**
77
+ * @generated from protobuf field: stream.video.sfu.signal.Reconnection reconnection = 2;
78
+ */
79
+ reconnection: Reconnection;
80
+ } | {
81
+ oneofKind: undefined;
82
+ };
83
+ }
40
84
  /**
41
85
  * @generated from protobuf message stream.video.sfu.signal.SendStatsRequest
42
86
  */
@@ -91,6 +135,10 @@ export interface SendStatsRequest {
91
135
  } | {
92
136
  oneofKind: undefined;
93
137
  };
138
+ /**
139
+ * @generated from protobuf field: stream.video.sfu.signal.Telemetry telemetry = 11;
140
+ */
141
+ telemetry?: Telemetry;
94
142
  }
95
143
  /**
96
144
  * @generated from protobuf message stream.video.sfu.signal.SendStatsResponse
@@ -324,6 +372,20 @@ declare class StopNoiseCancellationResponse$Type extends MessageType<StopNoiseCa
324
372
  * @generated MessageType for protobuf message stream.video.sfu.signal.StopNoiseCancellationResponse
325
373
  */
326
374
  export declare const StopNoiseCancellationResponse: StopNoiseCancellationResponse$Type;
375
+ declare class Reconnection$Type extends MessageType<Reconnection> {
376
+ constructor();
377
+ }
378
+ /**
379
+ * @generated MessageType for protobuf message stream.video.sfu.signal.Reconnection
380
+ */
381
+ export declare const Reconnection: Reconnection$Type;
382
+ declare class Telemetry$Type extends MessageType<Telemetry> {
383
+ constructor();
384
+ }
385
+ /**
386
+ * @generated MessageType for protobuf message stream.video.sfu.signal.Telemetry
387
+ */
388
+ export declare const Telemetry: Telemetry$Type;
327
389
  declare class SendStatsRequest$Type extends MessageType<SendStatsRequest> {
328
390
  constructor();
329
391
  }
@@ -4,6 +4,7 @@ import { Publisher, Subscriber } from '../rtc';
4
4
  import { LocalClientDetailsType } from '../client-details';
5
5
  import { CameraManager, MicrophoneManager } from '../devices';
6
6
  import { CallState } from '../store';
7
+ import { Telemetry } from '../gen/video/sfu/signal_rpc/signal';
7
8
  export type SfuStatsReporterOptions = {
8
9
  options: StatsOptions;
9
10
  clientDetails: LocalClientDetailsType;
@@ -31,6 +32,7 @@ export declare class SfuStatsReporter {
31
32
  private readonly inputDevices;
32
33
  constructor(sfuClient: StreamSfuClient, { options, clientDetails, subscriber, publisher, microphone, camera, state, }: SfuStatsReporterOptions);
33
34
  private observeDevice;
35
+ sendTelemetryData: (telemetryData: Telemetry) => Promise<void>;
34
36
  private run;
35
37
  start: () => void;
36
38
  stop: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-client",
3
- "version": "1.10.5",
3
+ "version": "1.11.0",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.es.js",
package/src/Call.ts CHANGED
@@ -725,6 +725,7 @@ export class Call {
725
725
  * @returns a promise which resolves once the call join-flow has finished.
726
726
  */
727
727
  join = async (data?: JoinCallData): Promise<void> => {
728
+ const connectStartTime = Date.now();
728
729
  await this.setup();
729
730
  const callingState = this.state.callingState;
730
731
  if ([CallingState.JOINED, CallingState.JOINING].includes(callingState)) {
@@ -793,11 +794,11 @@ export class Call {
793
794
  : undefined;
794
795
  const { callState, fastReconnectDeadlineSeconds } = await sfuClient.join({
795
796
  subscriberSdp: receivingCapabilitiesSdp,
797
+ publisherSdp: '',
796
798
  clientDetails,
797
799
  fastReconnect: performingFastReconnect,
798
800
  reconnectDetails,
799
801
  });
800
-
801
802
  this.fastReconnectDeadlineSeconds = fastReconnectDeadlineSeconds;
802
803
  if (callState) {
803
804
  this.state.updateFromSfuCallState(
@@ -831,6 +832,16 @@ export class Call {
831
832
  });
832
833
  }
833
834
 
835
+ // make sure we only track connection timing if we are not calling this method as part of a reconnection flow
836
+ if (!performingRejoin && !performingFastReconnect && !performingMigration) {
837
+ this.sfuStatsReporter?.sendTelemetryData({
838
+ data: {
839
+ oneofKind: 'connectionTimeSeconds',
840
+ connectionTimeSeconds: (Date.now() - connectStartTime) / 1000,
841
+ },
842
+ });
843
+ }
844
+
834
845
  if (performingRejoin) {
835
846
  const strategy = WebsocketReconnectStrategy[this.reconnectStrategy];
836
847
  await previousSfuClient?.leaveAndClose(
@@ -1130,9 +1141,19 @@ export class Call {
1130
1141
  * @internal
1131
1142
  */
1132
1143
  private reconnectFast = async () => {
1144
+ let reconnectStartTime = Date.now();
1133
1145
  this.reconnectStrategy = WebsocketReconnectStrategy.FAST;
1134
1146
  this.state.setCallingState(CallingState.RECONNECTING);
1135
- return this.join(this.joinCallData);
1147
+ await this.join(this.joinCallData);
1148
+ this.sfuStatsReporter?.sendTelemetryData({
1149
+ data: {
1150
+ oneofKind: 'reconnection',
1151
+ reconnection: {
1152
+ timeSeconds: (Date.now() - reconnectStartTime) / 1000,
1153
+ strategy: WebsocketReconnectStrategy.FAST,
1154
+ },
1155
+ },
1156
+ });
1136
1157
  };
1137
1158
 
1138
1159
  /**
@@ -1140,11 +1161,21 @@ export class Call {
1140
1161
  * @internal
1141
1162
  */
1142
1163
  private reconnectRejoin = async () => {
1164
+ let reconnectStartTime = Date.now();
1143
1165
  this.reconnectStrategy = WebsocketReconnectStrategy.REJOIN;
1144
1166
  this.state.setCallingState(CallingState.RECONNECTING);
1145
1167
  await this.join(this.joinCallData);
1146
1168
  await this.restorePublishedTracks();
1147
1169
  this.restoreSubscribedTracks();
1170
+ this.sfuStatsReporter?.sendTelemetryData({
1171
+ data: {
1172
+ oneofKind: 'reconnection',
1173
+ reconnection: {
1174
+ timeSeconds: (Date.now() - reconnectStartTime) / 1000,
1175
+ strategy: WebsocketReconnectStrategy.REJOIN,
1176
+ },
1177
+ },
1178
+ });
1148
1179
  };
1149
1180
 
1150
1181
  /**
@@ -1152,6 +1183,7 @@ export class Call {
1152
1183
  * @internal
1153
1184
  */
1154
1185
  private reconnectMigrate = async () => {
1186
+ let reconnectStartTime = Date.now();
1155
1187
  const currentSfuClient = this.sfuClient;
1156
1188
  if (!currentSfuClient) {
1157
1189
  throw new Error('Cannot migrate without an active SFU client');
@@ -1196,6 +1228,15 @@ export class Call {
1196
1228
  // and close the previous SFU client, without specifying close code
1197
1229
  currentSfuClient.close();
1198
1230
  }
1231
+ this.sfuStatsReporter?.sendTelemetryData({
1232
+ data: {
1233
+ oneofKind: 'reconnection',
1234
+ reconnection: {
1235
+ timeSeconds: (Date.now() - reconnectStartTime) / 1000,
1236
+ strategy: WebsocketReconnectStrategy.MIGRATE,
1237
+ },
1238
+ },
1239
+ });
1199
1240
  };
1200
1241
 
1201
1242
  /**
@@ -33,18 +33,13 @@
33
33
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
34
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
35
  //
36
- import type {
37
- JsonObject,
38
- JsonReadOptions,
39
- JsonValue,
40
- JsonWriteOptions,
41
- } from '@protobuf-ts/runtime';
42
- import {
43
- isJsonObject,
44
- MessageType,
45
- typeofJsonValue,
46
- } from '@protobuf-ts/runtime';
47
-
36
+ import { isJsonObject } from '@protobuf-ts/runtime';
37
+ import { typeofJsonValue } from '@protobuf-ts/runtime';
38
+ import type { JsonValue } from '@protobuf-ts/runtime';
39
+ import type { JsonReadOptions } from '@protobuf-ts/runtime';
40
+ import type { JsonWriteOptions } from '@protobuf-ts/runtime';
41
+ import type { JsonObject } from '@protobuf-ts/runtime';
42
+ import { MessageType } from '@protobuf-ts/runtime';
48
43
  /**
49
44
  * `Struct` represents a structured data value, consisting of fields
50
45
  * which map to dynamically typed values. In some languages, `Struct`
@@ -33,13 +33,12 @@
33
33
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
34
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
35
  //
36
- import type {
37
- JsonReadOptions,
38
- JsonValue,
39
- JsonWriteOptions,
40
- } from '@protobuf-ts/runtime';
41
- import { MessageType, PbLong, typeofJsonValue } from '@protobuf-ts/runtime';
42
-
36
+ import { typeofJsonValue } from '@protobuf-ts/runtime';
37
+ import type { JsonValue } from '@protobuf-ts/runtime';
38
+ import type { JsonReadOptions } from '@protobuf-ts/runtime';
39
+ import type { JsonWriteOptions } from '@protobuf-ts/runtime';
40
+ import { PbLong } from '@protobuf-ts/runtime';
41
+ import { MessageType } from '@protobuf-ts/runtime';
43
42
  /**
44
43
  * A Timestamp represents a point in time independent of any time zone or local
45
44
  * calendar, encoded as a count of seconds and fractions of seconds at