@trpc/client 11.0.0-alpha-tmp-issues-5851-take-two.496 → 11.0.0-alpha-tmp-subscription-connection-state.485

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.
@@ -6,7 +6,7 @@ export declare const resultOf: <T>(value: T | (() => T)) => T;
6
6
  /**
7
7
  * A value that can be wrapped in callback
8
8
  */
9
- type CallbackOrValue<T> = T | (() => T | Promise<T>);
9
+ export type CallbackOrValue<T> = T | (() => T | Promise<T>);
10
10
  export interface UrlOptionsWithConnectionParams {
11
11
  /**
12
12
  * The URL to connect to (can be a function that returns a URL)
@@ -19,5 +19,4 @@ export interface UrlOptionsWithConnectionParams {
19
19
  */
20
20
  connectionParams?: CallbackOrValue<TRPCRequestInfo['connectionParams']>;
21
21
  }
22
- export {};
23
22
  //# sourceMappingURL=urlWithConnectionParams.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"urlWithConnectionParams.d.ts","sourceRoot":"","sources":["../../../src/links/internals/urlWithConnectionParams.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAG,CAElD,CAAC;AAEF;;GAEG;AACH,KAAK,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAErD,MAAM,WAAW,8BAA8B;IAC7C;;OAEG;IACH,GAAG,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAE7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,eAAe,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC,CAAC;CACzE"}
1
+ {"version":3,"file":"urlWithConnectionParams.d.ts","sourceRoot":"","sources":["../../../src/links/internals/urlWithConnectionParams.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAG,CAElD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5D,MAAM,WAAW,8BAA8B;IAC7C;;OAEG;IACH,GAAG,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAE7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,eAAe,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC,CAAC;CACzE"}
@@ -33,17 +33,37 @@ export type HTTPHeaders = HeadersInitEsque | Record<string, string[] | string |
33
33
  export type TRPCFetch = (url: string, options?: RequestInit) => Promise<ResponseEsque>;
34
34
  export interface TRPCClientRuntime {
35
35
  }
36
+ export type ConnectionState = 'idle' | 'connecting' | 'pending' | 'error';
37
+ export interface ConnectionStateMessageBase {
38
+ type: 'state';
39
+ }
40
+ export interface IdleStateMessage extends ConnectionStateMessageBase {
41
+ state: 'idle';
42
+ }
43
+ export interface ConnectingStateMessage<TError> extends ConnectionStateMessageBase {
44
+ state: 'connecting';
45
+ data: TError | null;
46
+ }
47
+ export interface PendingStateMessage extends ConnectionStateMessageBase {
48
+ state: 'pending';
49
+ }
50
+ export interface ErrorStateMessage<TError> extends ConnectionStateMessageBase {
51
+ state: 'error';
52
+ data: TError;
53
+ }
54
+ export type TRPCConnectionStateMessage<TError> = IdleStateMessage | ConnectingStateMessage<TError> | PendingStateMessage | ErrorStateMessage<TError>;
55
+ export declare const isConnectionStateMessage: <TError>(msg: unknown) => msg is TRPCConnectionStateMessage<TError>;
36
56
  /**
37
57
  * @internal
38
58
  */
39
- export interface OperationResultEnvelope<TOutput> {
40
- result: TRPCResultMessage<TOutput>['result'] | TRPCSuccessResponse<TOutput>['result'];
59
+ export interface OperationResultEnvelope<TOutput, TError = unknown> {
60
+ result: TRPCConnectionStateMessage<TError> | TRPCResultMessage<TOutput>['result'] | TRPCSuccessResponse<TOutput>['result'];
41
61
  context?: OperationContext;
42
62
  }
43
63
  /**
44
64
  * @internal
45
65
  */
46
- export type OperationResultObservable<TInferrable extends InferrableClientTypes, TOutput> = Observable<OperationResultEnvelope<TOutput>, TRPCClientError<TInferrable>>;
66
+ export type OperationResultObservable<TInferrable extends InferrableClientTypes, TOutput> = Observable<OperationResultEnvelope<TOutput, TRPCClientError<TInferrable>>, TRPCClientError<TInferrable>>;
47
67
  /**
48
68
  * @internal
49
69
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/links/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,KAAK,EACV,qBAAqB,EACrB,KAAK,EACL,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EACL,qBAAqB,EACrB,UAAU,EACV,WAAW,GACZ,MAAM,0BAA0B,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAAG;AAEpE;;GAEG;AACH,MAAM,MAAM,SAAS,CAAC,MAAM,GAAG,OAAO,IAAI;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,cAAc,CAAC;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;CAC5B,CAAC;AAEF,UAAU,gBAAgB;IACxB,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACzD;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB,gBAAgB,GAChB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,CACtB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,WAAW,KAClB,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,MAAM,WAAW,iBAAiB;CAEjC;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB,CAAC,OAAO;IAC9C,MAAM,EACF,iBAAiB,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,GACpC,mBAAmB,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,MAAM,yBAAyB,CACnC,WAAW,SAAS,qBAAqB,EACzC,OAAO,IACL,UAAU,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;AAE/E;;GAEG;AACH,MAAM,MAAM,uBAAuB,CACjC,WAAW,SAAS,qBAAqB,EACzC,OAAO,IACL,QAAQ,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;AAE7E;;GAEG;AACH,MAAM,MAAM,aAAa,CACvB,WAAW,SAAS,qBAAqB,EACzC,MAAM,GAAG,OAAO,EAChB,OAAO,GAAG,OAAO,IACf,CAAC,IAAI,EAAE;IACT,EAAE,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACtB,IAAI,EAAE,CACJ,EAAE,EAAE,SAAS,CAAC,MAAM,CAAC,KAClB,yBAAyB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACtD,KAAK,yBAAyB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,WAAW,SAAS,qBAAqB,IAAI,CAChE,IAAI,EAAE,iBAAiB,KACpB,aAAa,CAAC,WAAW,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/links/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,KAAK,EACV,qBAAqB,EACrB,KAAK,EACL,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EACL,qBAAqB,EACrB,UAAU,EACV,WAAW,GACZ,MAAM,0BAA0B,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAAG;AAEpE;;GAEG;AACH,MAAM,MAAM,SAAS,CAAC,MAAM,GAAG,OAAO,IAAI;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,cAAc,CAAC;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;CAC5B,CAAC;AAEF,UAAU,gBAAgB;IACxB,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACzD;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB,gBAAgB,GAChB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,CACtB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,WAAW,KAClB,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,MAAM,WAAW,iBAAiB;CAEjC;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1E,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,gBAAiB,SAAQ,0BAA0B;IAClE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB,CAAC,MAAM,CAC5C,SAAQ,0BAA0B;IAClC,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,mBAAoB,SAAQ,0BAA0B;IACrE,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB,CAAC,MAAM,CAAE,SAAQ,0BAA0B;IAC3E,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,0BAA0B,CAAC,MAAM,IACzC,gBAAgB,GAChB,sBAAsB,CAAC,MAAM,CAAC,GAC9B,mBAAmB,GACnB,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE9B,eAAO,MAAM,wBAAwB,GAAI,MAAM,OACxC,OAAO,KACX,GAAG,IAAI,0BAA0B,CAAC,MAAM,CAO1C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAChE,MAAM,EACF,0BAA0B,CAAC,MAAM,CAAC,GAClC,iBAAiB,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,GACpC,mBAAmB,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,MAAM,yBAAyB,CACnC,WAAW,SAAS,qBAAqB,EACzC,OAAO,IACL,UAAU,CACZ,uBAAuB,CAAC,OAAO,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC,EAC9D,eAAe,CAAC,WAAW,CAAC,CAC7B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,CACjC,WAAW,SAAS,qBAAqB,EACzC,OAAO,IACL,QAAQ,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;AAE7E;;GAEG;AACH,MAAM,MAAM,aAAa,CACvB,WAAW,SAAS,qBAAqB,EACzC,MAAM,GAAG,OAAO,EAChB,OAAO,GAAG,OAAO,IACf,CAAC,IAAI,EAAE;IACT,EAAE,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACtB,IAAI,EAAE,CACJ,EAAE,EAAE,SAAS,CAAC,MAAM,CAAC,KAClB,yBAAyB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACtD,KAAK,yBAAyB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,WAAW,SAAS,qBAAqB,IAAI,CAChE,IAAI,EAAE,iBAAiB,KACpB,aAAa,CAAC,WAAW,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ const isConnectionStateMessage = (msg)=>{
4
+ return typeof msg === 'object' && msg !== null && 'type' in msg && msg.type === 'state';
5
+ };
6
+
7
+ exports.isConnectionStateMessage = isConnectionStateMessage;
@@ -0,0 +1,5 @@
1
+ const isConnectionStateMessage = (msg)=>{
2
+ return typeof msg === 'object' && msg !== null && 'type' in msg && msg.type === 'state';
3
+ };
4
+
5
+ export { isConnectionStateMessage };
@@ -3,8 +3,10 @@ import type { AnyRouter, inferClientTypes, inferRouterError, TRPCResponseMessage
3
3
  import { TRPCClientError } from '../TRPCClientError';
4
4
  import type { TransformerOptions } from '../unstable-internals';
5
5
  import { type UrlOptionsWithConnectionParams } from './internals/urlWithConnectionParams';
6
- import type { Operation, TRPCLink } from './types';
7
- type WSCallbackResult<TRouter extends AnyRouter, TOutput> = TRPCResponseMessage<TOutput, inferRouterError<TRouter>>;
6
+ import { type Operation, type TRPCConnectionStateMessage, type TRPCLink } from './types';
7
+ type WSCallbackResult<TRouter extends AnyRouter, TOutput> = TRPCResponseMessage<TOutput, inferRouterError<TRouter>> | {
8
+ result: TRPCConnectionStateMessage<inferRouterError<TRouter>>;
9
+ };
8
10
  type WSCallbackObserver<TRouter extends AnyRouter, TOutput> = Observer<WSCallbackResult<TRouter, TOutput>, TRPCClientError<TRouter>>;
9
11
  declare const exponentialBackoff: (attemptIndex: number) => number;
10
12
  export interface WebSocketClientOptions extends UrlOptionsWithConnectionParams {
@@ -61,7 +63,7 @@ export declare function createWSClient(opts: WebSocketClientOptions): {
61
63
  /**
62
64
  * Reconnect to the WebSocket server
63
65
  */
64
- reconnect: () => void;
66
+ reconnect: (cause: Error | null) => void;
65
67
  };
66
68
  export type TRPCWebSocketClient = ReturnType<typeof createWSClient>;
67
69
  export type WebSocketLinkOptions<TRouter extends AnyRouter> = {
@@ -1 +1 @@
1
- {"version":3,"file":"wsLink.d.ts","sourceRoot":"","sources":["../../src/links/wsLink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGvE,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAMhB,mBAAmB,EACpB,MAAM,0CAA0C,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAInD,KAAK,gBAAgB,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,IAAI,mBAAmB,CAC7E,OAAO,EACP,gBAAgB,CAAC,OAAO,CAAC,CAC1B,CAAC;AAEF,KAAK,kBAAkB,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,IAAI,QAAQ,CACpE,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,EAClC,eAAe,CAAC,OAAO,CAAC,CACzB,CAAC;AAEF,QAAA,MAAM,kBAAkB,iBAAkB,MAAM,WACoB,CAAC;AAErE,MAAM,WAAW,sBAAuB,SAAQ,8BAA8B;IAC5E;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,kBAAkB,CAAC;IACzC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9C;;OAEG;IACH,IAAI,CAAC,EAAE;QACL;;;WAGG;QACH,OAAO,EAAE,OAAO,CAAC;QACjB;;;WAGG;QACH,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAOD,wBAAgB,cAAc,CAAC,IAAI,EAAE,sBAAsB;;kBAuTpC,SAAS,wDAA0B,aAAa;;YAxQ/D,MAAM;;eAGC,MAAM;YACT,SAAS;;eAGN,QAAQ;YACX,SAAS;;eAGN,YAAY;aACd,SAAS;;IA2TlB;;OAEG;;EAGN;AACD,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAEpE,MAAM,MAAM,oBAAoB,CAAC,OAAO,SAAS,SAAS,IAAI;IAC5D,MAAM,EAAE,mBAAmB,CAAC;CAC7B,GAAG,kBAAkB,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;AASlD;;GAEG;AACH,wBAAgB,MAAM,CAAC,OAAO,SAAS,SAAS,EAC9C,IAAI,EAAE,oBAAoB,CAAC,OAAO,CAAC,GAClC,QAAQ,CAAC,OAAO,CAAC,CA8CnB"}
1
+ {"version":3,"file":"wsLink.d.ts","sourceRoot":"","sources":["../../src/links/wsLink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGvE,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAMhB,mBAAmB,EACpB,MAAM,0CAA0C,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,0BAA0B,EAC/B,KAAK,QAAQ,EACd,MAAM,SAAS,CAAC;AAIjB,KAAK,gBAAgB,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,IACpD,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,GACvD;IAAE,MAAM,EAAE,0BAA0B,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAA;CAAE,CAAC;AAEtE,KAAK,kBAAkB,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,IAAI,QAAQ,CACpE,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,EAClC,eAAe,CAAC,OAAO,CAAC,CACzB,CAAC;AAEF,QAAA,MAAM,kBAAkB,iBAAkB,MAAM,WACoB,CAAC;AAErE,MAAM,WAAW,sBAAuB,SAAQ,8BAA8B;IAC5E;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,kBAAkB,CAAC;IACzC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9C;;OAEG;IACH,IAAI,CAAC,EAAE;QACL;;;WAGG;QACH,OAAO,EAAE,OAAO,CAAC;QACjB;;;WAGG;QACH,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAOD,wBAAgB,cAAc,CAAC,IAAI,EAAE,sBAAsB;;kBAoVpC,SAAS,wDAA0B,aAAa;;YArS/D,MAAM;;eAGC,MAAM;YACT,SAAS;;eAGN,QAAQ;YACX,SAAS;;eAGN,YAAY;aACd,SAAS;;IAwVlB;;OAEG;uBAtSqB,KAAK,GAAG,IAAI;EAySvC;AACD,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAEpE,MAAM,MAAM,oBAAoB,CAAC,OAAO,SAAS,SAAS,IAAI;IAC5D,MAAM,EAAE,mBAAmB,CAAC;CAC7B,GAAG,kBAAkB,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;AASlD;;GAEG;AACH,wBAAgB,MAAM,CAAC,OAAO,SAAS,SAAS,EAC9C,IAAI,EAAE,oBAAoB,CAAC,OAAO,CAAC,GAClC,QAAQ,CAAC,OAAO,CAAC,CAoGnB"}
@@ -5,6 +5,7 @@ var unstableCoreDoNotImport = require('@trpc/server/unstable-core-do-not-import'
5
5
  var TRPCClientError = require('../TRPCClientError.js');
6
6
  var transformer = require('../internals/transformer.js');
7
7
  var urlWithConnectionParams = require('./internals/urlWithConnectionParams.js');
8
+ var types = require('./types.js');
8
9
 
9
10
  const run = (fn)=>fn();
10
11
  const exponentialBackoff = (attemptIndex)=>attemptIndex === 0 ? 0 : Math.min(1000 * 2 ** attemptIndex, 30000);
@@ -29,12 +30,12 @@ function createWSClient(opts) {
29
30
  let connectTimer = undefined;
30
31
  let connectionIndex = 0;
31
32
  let lazyDisconnectTimer = undefined;
32
- let activeConnection = lazyOpts.enabled ? null : createConnection();
33
+ let activeConnection = lazyOpts.enabled ? null : createConnection(null);
33
34
  /**
34
35
  * tries to send the list of messages
35
36
  */ function dispatch() {
36
37
  if (!activeConnection) {
37
- activeConnection = createConnection();
38
+ activeConnection = createConnection(null);
38
39
  return;
39
40
  }
40
41
  // using a timeout to batch messages
@@ -59,13 +60,13 @@ function createWSClient(opts) {
59
60
  startLazyDisconnectTimer();
60
61
  });
61
62
  }
62
- function tryReconnect(conn) {
63
+ function tryReconnect(conn, cause) {
63
64
  if (!!connectTimer) {
64
65
  return;
65
66
  }
66
67
  conn.state = 'connecting';
67
68
  const timeout = retryDelayFn(connectAttempt++);
68
- reconnectInMs(timeout);
69
+ reconnectInMs(timeout, cause);
69
70
  }
70
71
  function hasPendingRequests(conn) {
71
72
  const requests = Object.values(pendingRequests);
@@ -74,20 +75,20 @@ function createWSClient(opts) {
74
75
  }
75
76
  return requests.some((req)=>req.connection === conn);
76
77
  }
77
- function reconnect() {
78
+ function reconnect(cause) {
78
79
  if (lazyOpts.enabled && !hasPendingRequests()) {
79
80
  // Skip reconnecting if there are pending requests and we're in lazy mode
80
81
  return;
81
82
  }
82
83
  const oldConnection = activeConnection;
83
- activeConnection = createConnection();
84
+ activeConnection = createConnection(cause);
84
85
  oldConnection && closeIfNoPending(oldConnection);
85
86
  }
86
- function reconnectInMs(ms) {
87
+ function reconnectInMs(ms, cause) {
87
88
  if (connectTimer) {
88
89
  return;
89
90
  }
90
- connectTimer = setTimeout(reconnect, ms);
91
+ connectTimer = setTimeout(reconnect, ms, cause);
91
92
  }
92
93
  function closeIfNoPending(conn) {
93
94
  // disconnect as soon as there are are no pending requests
@@ -116,16 +117,27 @@ function createWSClient(opts) {
116
117
  }
117
118
  }, lazyOpts.closeMs);
118
119
  };
119
- function createConnection() {
120
+ function createConnection(cause) {
120
121
  const self = {
121
122
  id: ++connectionIndex,
122
123
  state: 'connecting'
123
124
  };
125
+ for (const req of Object.values(pendingRequests)){
126
+ if (req.type === 'subscription') {
127
+ req.callbacks.next?.({
128
+ result: {
129
+ type: 'state',
130
+ state: 'connecting',
131
+ data: cause ?? null
132
+ }
133
+ });
134
+ }
135
+ }
124
136
  clearTimeout(lazyDisconnectTimer);
125
- const onError = ()=>{
137
+ const onError = (cause)=>{
126
138
  self.state = 'closed';
127
139
  if (self === activeConnection) {
128
- tryReconnect(self);
140
+ tryReconnect(self, cause);
129
141
  }
130
142
  };
131
143
  run(async ()=>{
@@ -153,21 +165,37 @@ function createWSClient(opts) {
153
165
  }
154
166
  connectAttempt = 0;
155
167
  self.state = 'open';
168
+ for (const req of Object.values(pendingRequests)){
169
+ if (req.type === 'subscription') {
170
+ req.callbacks.next?.({
171
+ result: {
172
+ type: 'state',
173
+ state: 'pending'
174
+ }
175
+ });
176
+ }
177
+ }
156
178
  onOpen?.();
157
179
  dispatch();
158
180
  }).catch((cause)=>{
159
181
  ws.close(// "Status codes in the range 3000-3999 are reserved for use by libraries, frameworks, and applications"
160
182
  3000, cause);
161
- onError();
183
+ onError(cause);
162
184
  });
163
185
  });
164
- ws.addEventListener('error', onError);
186
+ ws.addEventListener('error', (event)=>{
187
+ if (event instanceof ErrorEvent) {
188
+ onError(event.error);
189
+ } else {
190
+ onError(new Error('Unknown WebSocket error'));
191
+ }
192
+ });
165
193
  const handleIncomingRequest = (req)=>{
166
194
  if (self !== activeConnection) {
167
195
  return;
168
196
  }
169
197
  if (req.method === 'reconnect') {
170
- reconnect();
198
+ reconnect(new Error('Server requested reconnect'));
171
199
  // notify subscribers
172
200
  for (const pendingReq of Object.values(pendingRequests)){
173
201
  if (pendingReq.type === 'subscription') {
@@ -206,7 +234,7 @@ function createWSClient(opts) {
206
234
  closeIfNoPending(self);
207
235
  }
208
236
  });
209
- ws.addEventListener('close', ({ code })=>{
237
+ ws.addEventListener('close', ({ code , reason })=>{
210
238
  if (self.state === 'open') {
211
239
  onClose?.({
212
240
  code
@@ -215,7 +243,7 @@ function createWSClient(opts) {
215
243
  self.state = 'closed';
216
244
  if (activeConnection === self) {
217
245
  // connection might have been replaced already
218
- tryReconnect(self);
246
+ tryReconnect(self, new Error(reason));
219
247
  }
220
248
  for (const [key, req] of Object.entries(pendingRequests)){
221
249
  if (req.connection !== self) {
@@ -327,19 +355,53 @@ class TRPCWebSocketClosedError extends Error {
327
355
  }, {
328
356
  error (err) {
329
357
  observer.error(err);
358
+ observer.next({
359
+ result: {
360
+ type: 'state',
361
+ state: 'error',
362
+ data: err
363
+ },
364
+ context: context
365
+ });
330
366
  unsub();
331
367
  },
332
368
  complete () {
333
369
  observer.complete();
370
+ observer.next({
371
+ result: {
372
+ type: 'state',
373
+ state: 'idle'
374
+ },
375
+ context: context
376
+ });
334
377
  },
335
378
  next (message) {
379
+ if ('result' in message && types.isConnectionStateMessage(message.result)) {
380
+ message.result;
381
+ observer.next({
382
+ result: message.result,
383
+ context: context
384
+ });
385
+ return;
386
+ }
387
+ if (!('id' in message)) return;
336
388
  const transformed = unstableCoreDoNotImport.transformResult(message, transformer$1.output);
337
389
  if (!transformed.ok) {
390
+ const error = TRPCClientError.TRPCClientError.from(transformed.error);
391
+ observer.next({
392
+ result: {
393
+ type: 'state',
394
+ state: 'error',
395
+ data: error
396
+ },
397
+ context: context
398
+ });
338
399
  observer.error(TRPCClientError.TRPCClientError.from(transformed.error));
339
400
  return;
340
401
  }
341
402
  observer.next({
342
- result: transformed.result
403
+ result: transformed.result,
404
+ context: context
343
405
  });
344
406
  if (op.type !== 'subscription') {
345
407
  // if it isn't a subscription we don't care about next response
@@ -350,6 +412,13 @@ class TRPCWebSocketClosedError extends Error {
350
412
  });
351
413
  return ()=>{
352
414
  unsub();
415
+ observer.next({
416
+ result: {
417
+ type: 'state',
418
+ state: 'idle'
419
+ },
420
+ context: context
421
+ });
353
422
  };
354
423
  });
355
424
  };
@@ -3,6 +3,7 @@ import { transformResult } from '@trpc/server/unstable-core-do-not-import';
3
3
  import { TRPCClientError } from '../TRPCClientError.mjs';
4
4
  import { getTransformer } from '../internals/transformer.mjs';
5
5
  import { resultOf } from './internals/urlWithConnectionParams.mjs';
6
+ import { isConnectionStateMessage } from './types.mjs';
6
7
 
7
8
  const run = (fn)=>fn();
8
9
  const exponentialBackoff = (attemptIndex)=>attemptIndex === 0 ? 0 : Math.min(1000 * 2 ** attemptIndex, 30000);
@@ -27,12 +28,12 @@ function createWSClient(opts) {
27
28
  let connectTimer = undefined;
28
29
  let connectionIndex = 0;
29
30
  let lazyDisconnectTimer = undefined;
30
- let activeConnection = lazyOpts.enabled ? null : createConnection();
31
+ let activeConnection = lazyOpts.enabled ? null : createConnection(null);
31
32
  /**
32
33
  * tries to send the list of messages
33
34
  */ function dispatch() {
34
35
  if (!activeConnection) {
35
- activeConnection = createConnection();
36
+ activeConnection = createConnection(null);
36
37
  return;
37
38
  }
38
39
  // using a timeout to batch messages
@@ -57,13 +58,13 @@ function createWSClient(opts) {
57
58
  startLazyDisconnectTimer();
58
59
  });
59
60
  }
60
- function tryReconnect(conn) {
61
+ function tryReconnect(conn, cause) {
61
62
  if (!!connectTimer) {
62
63
  return;
63
64
  }
64
65
  conn.state = 'connecting';
65
66
  const timeout = retryDelayFn(connectAttempt++);
66
- reconnectInMs(timeout);
67
+ reconnectInMs(timeout, cause);
67
68
  }
68
69
  function hasPendingRequests(conn) {
69
70
  const requests = Object.values(pendingRequests);
@@ -72,20 +73,20 @@ function createWSClient(opts) {
72
73
  }
73
74
  return requests.some((req)=>req.connection === conn);
74
75
  }
75
- function reconnect() {
76
+ function reconnect(cause) {
76
77
  if (lazyOpts.enabled && !hasPendingRequests()) {
77
78
  // Skip reconnecting if there are pending requests and we're in lazy mode
78
79
  return;
79
80
  }
80
81
  const oldConnection = activeConnection;
81
- activeConnection = createConnection();
82
+ activeConnection = createConnection(cause);
82
83
  oldConnection && closeIfNoPending(oldConnection);
83
84
  }
84
- function reconnectInMs(ms) {
85
+ function reconnectInMs(ms, cause) {
85
86
  if (connectTimer) {
86
87
  return;
87
88
  }
88
- connectTimer = setTimeout(reconnect, ms);
89
+ connectTimer = setTimeout(reconnect, ms, cause);
89
90
  }
90
91
  function closeIfNoPending(conn) {
91
92
  // disconnect as soon as there are are no pending requests
@@ -114,16 +115,27 @@ function createWSClient(opts) {
114
115
  }
115
116
  }, lazyOpts.closeMs);
116
117
  };
117
- function createConnection() {
118
+ function createConnection(cause) {
118
119
  const self = {
119
120
  id: ++connectionIndex,
120
121
  state: 'connecting'
121
122
  };
123
+ for (const req of Object.values(pendingRequests)){
124
+ if (req.type === 'subscription') {
125
+ req.callbacks.next?.({
126
+ result: {
127
+ type: 'state',
128
+ state: 'connecting',
129
+ data: cause ?? null
130
+ }
131
+ });
132
+ }
133
+ }
122
134
  clearTimeout(lazyDisconnectTimer);
123
- const onError = ()=>{
135
+ const onError = (cause)=>{
124
136
  self.state = 'closed';
125
137
  if (self === activeConnection) {
126
- tryReconnect(self);
138
+ tryReconnect(self, cause);
127
139
  }
128
140
  };
129
141
  run(async ()=>{
@@ -151,21 +163,37 @@ function createWSClient(opts) {
151
163
  }
152
164
  connectAttempt = 0;
153
165
  self.state = 'open';
166
+ for (const req of Object.values(pendingRequests)){
167
+ if (req.type === 'subscription') {
168
+ req.callbacks.next?.({
169
+ result: {
170
+ type: 'state',
171
+ state: 'pending'
172
+ }
173
+ });
174
+ }
175
+ }
154
176
  onOpen?.();
155
177
  dispatch();
156
178
  }).catch((cause)=>{
157
179
  ws.close(// "Status codes in the range 3000-3999 are reserved for use by libraries, frameworks, and applications"
158
180
  3000, cause);
159
- onError();
181
+ onError(cause);
160
182
  });
161
183
  });
162
- ws.addEventListener('error', onError);
184
+ ws.addEventListener('error', (event)=>{
185
+ if (event instanceof ErrorEvent) {
186
+ onError(event.error);
187
+ } else {
188
+ onError(new Error('Unknown WebSocket error'));
189
+ }
190
+ });
163
191
  const handleIncomingRequest = (req)=>{
164
192
  if (self !== activeConnection) {
165
193
  return;
166
194
  }
167
195
  if (req.method === 'reconnect') {
168
- reconnect();
196
+ reconnect(new Error('Server requested reconnect'));
169
197
  // notify subscribers
170
198
  for (const pendingReq of Object.values(pendingRequests)){
171
199
  if (pendingReq.type === 'subscription') {
@@ -204,7 +232,7 @@ function createWSClient(opts) {
204
232
  closeIfNoPending(self);
205
233
  }
206
234
  });
207
- ws.addEventListener('close', ({ code })=>{
235
+ ws.addEventListener('close', ({ code , reason })=>{
208
236
  if (self.state === 'open') {
209
237
  onClose?.({
210
238
  code
@@ -213,7 +241,7 @@ function createWSClient(opts) {
213
241
  self.state = 'closed';
214
242
  if (activeConnection === self) {
215
243
  // connection might have been replaced already
216
- tryReconnect(self);
244
+ tryReconnect(self, new Error(reason));
217
245
  }
218
246
  for (const [key, req] of Object.entries(pendingRequests)){
219
247
  if (req.connection !== self) {
@@ -325,19 +353,53 @@ class TRPCWebSocketClosedError extends Error {
325
353
  }, {
326
354
  error (err) {
327
355
  observer.error(err);
356
+ observer.next({
357
+ result: {
358
+ type: 'state',
359
+ state: 'error',
360
+ data: err
361
+ },
362
+ context: context
363
+ });
328
364
  unsub();
329
365
  },
330
366
  complete () {
331
367
  observer.complete();
368
+ observer.next({
369
+ result: {
370
+ type: 'state',
371
+ state: 'idle'
372
+ },
373
+ context: context
374
+ });
332
375
  },
333
376
  next (message) {
377
+ if ('result' in message && isConnectionStateMessage(message.result)) {
378
+ message.result;
379
+ observer.next({
380
+ result: message.result,
381
+ context: context
382
+ });
383
+ return;
384
+ }
385
+ if (!('id' in message)) return;
334
386
  const transformed = transformResult(message, transformer.output);
335
387
  if (!transformed.ok) {
388
+ const error = TRPCClientError.from(transformed.error);
389
+ observer.next({
390
+ result: {
391
+ type: 'state',
392
+ state: 'error',
393
+ data: error
394
+ },
395
+ context: context
396
+ });
336
397
  observer.error(TRPCClientError.from(transformed.error));
337
398
  return;
338
399
  }
339
400
  observer.next({
340
- result: transformed.result
401
+ result: transformed.result,
402
+ context: context
341
403
  });
342
404
  if (op.type !== 'subscription') {
343
405
  // if it isn't a subscription we don't care about next response
@@ -348,6 +410,13 @@ class TRPCWebSocketClosedError extends Error {
348
410
  });
349
411
  return ()=>{
350
412
  unsub();
413
+ observer.next({
414
+ result: {
415
+ type: 'state',
416
+ state: 'idle'
417
+ },
418
+ context: context
419
+ });
351
420
  };
352
421
  });
353
422
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trpc/client",
3
- "version": "11.0.0-alpha-tmp-issues-5851-take-two.496+f0729daa3",
3
+ "version": "11.0.0-alpha-tmp-subscription-connection-state.485+386eae02c",
4
4
  "description": "The tRPC client library",
5
5
  "author": "KATT",
6
6
  "license": "MIT",
@@ -76,10 +76,10 @@
76
76
  "!**/*.test.*"
77
77
  ],
78
78
  "peerDependencies": {
79
- "@trpc/server": "11.0.0-alpha-tmp-issues-5851-take-two.496+f0729daa3"
79
+ "@trpc/server": "11.0.0-alpha-tmp-subscription-connection-state.485+386eae02c"
80
80
  },
81
81
  "devDependencies": {
82
- "@trpc/server": "11.0.0-alpha-tmp-issues-5851-take-two.496+f0729daa3",
82
+ "@trpc/server": "11.0.0-alpha-tmp-subscription-connection-state.485+386eae02c",
83
83
  "@types/isomorphic-fetch": "^0.0.39",
84
84
  "@types/node": "^20.10.0",
85
85
  "eslint": "^8.56.0",
@@ -96,5 +96,5 @@
96
96
  "funding": [
97
97
  "https://trpc.io/sponsor"
98
98
  ],
99
- "gitHead": "f0729daa3e95b1f21cd082e04c21377b550f5625"
99
+ "gitHead": "386eae02c675ba0fe0feda78188b6975e56d0e49"
100
100
  }
@@ -14,6 +14,7 @@ import type {
14
14
  OperationContext,
15
15
  OperationLink,
16
16
  TRPCClientRuntime,
17
+ TRPCConnectionStateMessage,
17
18
  TRPCLink,
18
19
  } from '../links/types';
19
20
  import { TRPCClientError } from '../TRPCClientError';
@@ -33,6 +34,7 @@ export interface TRPCSubscriptionObserver<TValue, TError> {
33
34
  onError: (err: TError) => void;
34
35
  onStopped: () => void;
35
36
  onComplete: () => void;
37
+ onStateChange: (state: TRPCConnectionStateMessage<TError>) => void;
36
38
  }
37
39
 
38
40
  /** @internal */
@@ -143,6 +145,8 @@ export class TRPCUntypedClient<TRouter extends AnyRouter> {
143
145
  });
144
146
  } else if (envelope.result.type === 'stopped') {
145
147
  opts.onStopped?.();
148
+ } else if (envelope.result.type === 'state') {
149
+ opts.onStateChange?.(envelope.result);
146
150
  } else {
147
151
  opts.onData?.(envelope.result.data);
148
152
  }