@trpc/client 10.0.0-alpha.8 → 10.0.0-proxy-alpha.53
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.
- package/README.md +58 -1
- package/dist/TRPCClientError.d.ts +16 -20
- package/dist/TRPCClientError.d.ts.map +1 -1
- package/dist/createTRPCClient.d.ts +2 -3
- package/dist/createTRPCClient.d.ts.map +1 -1
- package/dist/createTRPCClientProxy.d.ts +37 -0
- package/dist/createTRPCClientProxy.d.ts.map +1 -0
- package/dist/httpUtils-44781613.mjs +76 -0
- package/dist/httpUtils-801112a6.js +79 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +260 -280
- package/dist/index.mjs +253 -271
- package/dist/internals/TRPCClient.d.ts +39 -21
- package/dist/internals/TRPCClient.d.ts.map +1 -1
- package/dist/internals/dataLoader.d.ts +7 -6
- package/dist/internals/dataLoader.d.ts.map +1 -1
- package/dist/internals/fetchHelpers.d.ts +1 -1
- package/dist/internals/fetchHelpers.d.ts.map +1 -1
- package/dist/internals/retryDelay.d.ts.map +1 -1
- package/dist/links/dedupeLink.d.ts.map +1 -1
- package/dist/links/httpBatchLink.d.ts +2 -2
- package/dist/links/httpBatchLink.d.ts.map +1 -1
- package/dist/links/httpBatchLink.js +189 -172
- package/dist/links/httpBatchLink.mjs +189 -172
- package/dist/links/httpLink.d.ts +1 -1
- package/dist/links/httpLink.d.ts.map +1 -1
- package/dist/links/httpLink.js +31 -35
- package/dist/links/httpLink.mjs +31 -35
- package/dist/links/index.d.ts +9 -0
- package/dist/links/index.d.ts.map +1 -0
- package/dist/links/internals/createChain.d.ts.map +1 -1
- package/dist/links/internals/httpUtils.d.ts +31 -0
- package/dist/links/internals/httpUtils.d.ts.map +1 -0
- package/dist/links/internals/transformResult.d.ts +28 -0
- package/dist/links/internals/transformResult.d.ts.map +1 -0
- package/dist/links/loggerLink.d.ts +3 -3
- package/dist/links/loggerLink.d.ts.map +1 -1
- package/dist/links/loggerLink.js +90 -96
- package/dist/links/loggerLink.mjs +90 -91
- package/dist/links/retryLink.d.ts.map +1 -1
- package/dist/links/splitLink.d.ts +1 -1
- package/dist/links/splitLink.d.ts.map +1 -1
- package/dist/links/splitLink.js +3 -25
- package/dist/links/splitLink.mjs +2 -28
- package/dist/links/types.d.ts +13 -12
- package/dist/links/types.d.ts.map +1 -1
- package/dist/links/wsLink.d.ts +12 -5
- package/dist/links/wsLink.d.ts.map +1 -1
- package/dist/links/wsLink.js +250 -358
- package/dist/links/wsLink.mjs +250 -348
- package/dist/splitLink-695ae288.js +48 -0
- package/dist/splitLink-ad44a55d.mjs +45 -0
- package/dist/transformResult-106791d7.mjs +62 -0
- package/dist/transformResult-e15ccdf6.js +65 -0
- package/links/httpBatchLink/dist/trpc-client-links-httpBatchLink.cjs.dev.js +15 -13
- package/links/httpBatchLink/dist/trpc-client-links-httpBatchLink.cjs.prod.js +15 -13
- package/links/httpBatchLink/dist/trpc-client-links-httpBatchLink.esm.js +12 -10
- package/links/httpLink/dist/trpc-client-links-httpLink.cjs.dev.js +4 -4
- package/links/httpLink/dist/trpc-client-links-httpLink.cjs.prod.js +4 -4
- package/links/httpLink/dist/trpc-client-links-httpLink.esm.js +1 -1
- package/links/wsLink/dist/trpc-client-links-wsLink.cjs.dev.js +3 -1
- package/links/wsLink/dist/trpc-client-links-wsLink.cjs.prod.js +3 -1
- package/links/wsLink/dist/trpc-client-links-wsLink.esm.js +3 -1
- package/package.json +23 -34
- package/src/TRPCClientError.ts +38 -28
- package/src/createTRPCClient.ts +8 -3
- package/src/createTRPCClientProxy.ts +113 -0
- package/src/index.ts +2 -1
- package/src/internals/TRPCClient.ts +118 -77
- package/src/internals/dataLoader.ts +116 -53
- package/src/internals/fetchHelpers.ts +2 -2
- package/src/links/dedupeLink.test.ts +9 -15
- package/src/links/dedupeLink.ts +6 -7
- package/src/links/httpBatchLink.ts +73 -36
- package/src/links/httpLink.ts +18 -6
- package/src/links/index.ts +8 -0
- package/src/links/internals/createChain.test.ts +23 -38
- package/src/links/internals/createChain.ts +8 -3
- package/src/links/internals/httpUtils.ts +117 -0
- package/src/links/internals/transformResult.ts +40 -0
- package/src/links/loggerLink.ts +6 -7
- package/src/links/retryLink.ts +2 -3
- package/src/links/splitLink.test.ts +3 -3
- package/src/links/splitLink.ts +5 -5
- package/src/links/types.ts +15 -12
- package/src/links/wsLink.ts +57 -23
- package/dist/TRPCClientError-17b117e1.mjs +0 -81
- package/dist/TRPCClientError-ec6bd2ca.js +0 -94
- package/dist/createChain-389cc116.mjs +0 -25
- package/dist/createChain-864dbb30.js +0 -27
- package/dist/httpUtils-1f9e4e3c.js +0 -97
- package/dist/httpUtils-c09d7b79.mjs +0 -91
- package/dist/index.ts.js +0 -1
- package/dist/internals/transformRPCResponse.d.ts +0 -15
- package/dist/internals/transformRPCResponse.d.ts.map +0 -1
- package/dist/links/httpBatchLink.ts.js +0 -1
- package/dist/links/httpLink.ts.js +0 -1
- package/dist/links/httpUtils.d.ts +0 -22
- package/dist/links/httpUtils.d.ts.map +0 -1
- package/dist/links/internals/transformOperationResult.d.ts +0 -16
- package/dist/links/internals/transformOperationResult.d.ts.map +0 -1
- package/dist/links/loggerLink.ts.js +0 -1
- package/dist/links/splitLink.ts.js +0 -1
- package/dist/links/transformerLink.d.ts +0 -4
- package/dist/links/transformerLink.d.ts.map +0 -1
- package/dist/links/transformerLink.js +0 -75
- package/dist/links/transformerLink.mjs +0 -67
- package/dist/links/transformerLink.ts.js +0 -1
- package/dist/links/wsLink.ts.js +0 -1
- package/dist/observable-7e66cb56.mjs +0 -102
- package/dist/observable-85669100.js +0 -104
- package/dist/rx/index.d.ts +0 -3
- package/dist/rx/index.d.ts.map +0 -1
- package/dist/rx/index.js +0 -9
- package/dist/rx/index.mjs +0 -1
- package/dist/rx/index.ts.js +0 -1
- package/dist/rx/observable.d.ts +0 -4
- package/dist/rx/observable.d.ts.map +0 -1
- package/dist/rx/operators/index.d.ts +0 -4
- package/dist/rx/operators/index.d.ts.map +0 -1
- package/dist/rx/operators/index.js +0 -38
- package/dist/rx/operators/index.mjs +0 -32
- package/dist/rx/operators/index.ts.js +0 -1
- package/dist/rx/operators/map.d.ts +0 -3
- package/dist/rx/operators/map.d.ts.map +0 -1
- package/dist/rx/operators/share.d.ts +0 -6
- package/dist/rx/operators/share.d.ts.map +0 -1
- package/dist/rx/operators/tap.d.ts +0 -3
- package/dist/rx/operators/tap.d.ts.map +0 -1
- package/dist/rx/types.d.ts +0 -29
- package/dist/rx/types.d.ts.map +0 -1
- package/dist/rx/util/identity.d.ts +0 -2
- package/dist/rx/util/identity.d.ts.map +0 -1
- package/dist/rx/util/observableToPromise.d.ts +0 -10
- package/dist/rx/util/observableToPromise.d.ts.map +0 -1
- package/dist/rx/util/pipe.d.ts +0 -4
- package/dist/rx/util/pipe.d.ts.map +0 -1
- package/dist/share-4d79dc49.js +0 -110
- package/dist/share-671b63fa.mjs +0 -108
- package/dist/tap-538fa07f.mjs +0 -30
- package/dist/tap-799a2d33.js +0 -32
- package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.d.ts +0 -1
- package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.dev.js +0 -67
- package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.js +0 -7
- package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.prod.js +0 -67
- package/links/transformerLink/dist/trpc-client-links-transformerLink.esm.js +0 -63
- package/links/transformerLink/index.d.ts +0 -1
- package/links/transformerLink/index.js +0 -1
- package/rx/dist/trpc-client-rx.cjs.d.ts +0 -1
- package/rx/dist/trpc-client-rx.cjs.dev.js +0 -9
- package/rx/dist/trpc-client-rx.cjs.js +0 -7
- package/rx/dist/trpc-client-rx.cjs.prod.js +0 -9
- package/rx/dist/trpc-client-rx.esm.js +0 -1
- package/rx/index.d.ts +0 -1
- package/rx/index.js +0 -1
- package/rx/operators/dist/trpc-client-rx-operators.cjs.d.ts +0 -1
- package/rx/operators/dist/trpc-client-rx-operators.cjs.dev.js +0 -39
- package/rx/operators/dist/trpc-client-rx-operators.cjs.js +0 -7
- package/rx/operators/dist/trpc-client-rx-operators.cjs.prod.js +0 -39
- package/rx/operators/dist/trpc-client-rx-operators.esm.js +0 -33
- package/rx/operators/index.d.ts +0 -1
- package/rx/operators/index.js +0 -1
- package/src/internals/transformRPCResponse.ts +0 -25
- package/src/links/httpUtils.ts +0 -94
- package/src/links/internals/transformOperationResult.ts +0 -25
- package/src/links/transformerLink.ts +0 -70
- package/src/rx/index.ts +0 -2
- package/src/rx/observable.test.ts +0 -83
- package/src/rx/observable.ts +0 -70
- package/src/rx/operators/index.ts +0 -3
- package/src/rx/operators/map.test.ts +0 -92
- package/src/rx/operators/map.ts +0 -25
- package/src/rx/operators/share.test.ts +0 -60
- package/src/rx/operators/share.ts +0 -67
- package/src/rx/operators/tap.ts +0 -26
- package/src/rx/types.ts +0 -69
- package/src/rx/util/identity.ts +0 -3
- package/src/rx/util/observableToPromise.ts +0 -49
- package/src/rx/util/pipe.ts +0 -22
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { ProcedureType } from '@trpc/server';
|
|
2
|
+
import { TRPCResponse } from '@trpc/server/rpc';
|
|
3
|
+
import { PromiseAndCancel, TRPCClientRuntime } from '../types';
|
|
4
|
+
|
|
5
|
+
export interface HTTPLinkOptions {
|
|
6
|
+
url: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// https://github.com/trpc/trpc/pull/669
|
|
10
|
+
function arrayToDict(array: unknown[]) {
|
|
11
|
+
const dict: Record<number, unknown> = {};
|
|
12
|
+
for (let index = 0; index < array.length; index++) {
|
|
13
|
+
const element = array[index];
|
|
14
|
+
dict[index] = element;
|
|
15
|
+
}
|
|
16
|
+
return dict;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const METHOD = {
|
|
20
|
+
query: 'GET',
|
|
21
|
+
mutation: 'POST',
|
|
22
|
+
subscription: 'PATCH',
|
|
23
|
+
} as const;
|
|
24
|
+
|
|
25
|
+
export interface HTTPResult {
|
|
26
|
+
json: TRPCResponse;
|
|
27
|
+
meta: {
|
|
28
|
+
response: Response;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type GetInputOptions = {
|
|
33
|
+
runtime: TRPCClientRuntime;
|
|
34
|
+
} & ({ inputs: unknown[] } | { input: unknown });
|
|
35
|
+
|
|
36
|
+
function getInput(opts: GetInputOptions) {
|
|
37
|
+
return 'input' in opts
|
|
38
|
+
? opts.runtime.transformer.serialize(opts.input)
|
|
39
|
+
: arrayToDict(
|
|
40
|
+
opts.inputs.map((_input) => opts.runtime.transformer.serialize(_input)),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type HTTPRequestOptions = HTTPLinkOptions &
|
|
45
|
+
GetInputOptions & {
|
|
46
|
+
type: ProcedureType;
|
|
47
|
+
path: string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export function getUrl(opts: HTTPRequestOptions) {
|
|
51
|
+
let url = opts.url + '/' + opts.path;
|
|
52
|
+
const queryParts: string[] = [];
|
|
53
|
+
if ('inputs' in opts) {
|
|
54
|
+
queryParts.push('batch=1');
|
|
55
|
+
}
|
|
56
|
+
if (opts.type === 'query') {
|
|
57
|
+
const input = getInput(opts);
|
|
58
|
+
if (input !== undefined) {
|
|
59
|
+
queryParts.push(`input=${encodeURIComponent(JSON.stringify(input))}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (queryParts.length) {
|
|
63
|
+
url += '?' + queryParts.join('&');
|
|
64
|
+
}
|
|
65
|
+
return url;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type GetBodyOptions = { type: ProcedureType } & GetInputOptions;
|
|
69
|
+
|
|
70
|
+
export function getBody(opts: GetBodyOptions) {
|
|
71
|
+
if (opts.type === 'query') {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
const input = getInput(opts);
|
|
75
|
+
return input !== undefined ? JSON.stringify(input) : undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function httpRequest(
|
|
79
|
+
opts: HTTPRequestOptions,
|
|
80
|
+
): PromiseAndCancel<HTTPResult> {
|
|
81
|
+
const { type, runtime } = opts;
|
|
82
|
+
const ac = runtime.AbortController ? new runtime.AbortController() : null;
|
|
83
|
+
|
|
84
|
+
const promise = new Promise<HTTPResult>((resolve, reject) => {
|
|
85
|
+
const url = getUrl(opts);
|
|
86
|
+
const body = getBody(opts);
|
|
87
|
+
|
|
88
|
+
const meta = {} as HTTPResult['meta'];
|
|
89
|
+
Promise.resolve(runtime.headers())
|
|
90
|
+
.then((headers) =>
|
|
91
|
+
runtime.fetch(url, {
|
|
92
|
+
method: METHOD[type],
|
|
93
|
+
signal: ac?.signal,
|
|
94
|
+
body: body,
|
|
95
|
+
headers: {
|
|
96
|
+
'content-type': 'application/json',
|
|
97
|
+
...headers,
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
100
|
+
)
|
|
101
|
+
.then((_res) => {
|
|
102
|
+
meta.response = _res;
|
|
103
|
+
return _res.json();
|
|
104
|
+
})
|
|
105
|
+
.then((json) => {
|
|
106
|
+
resolve({
|
|
107
|
+
json,
|
|
108
|
+
meta,
|
|
109
|
+
});
|
|
110
|
+
})
|
|
111
|
+
.catch(reject);
|
|
112
|
+
});
|
|
113
|
+
const cancel = () => {
|
|
114
|
+
ac?.abort();
|
|
115
|
+
};
|
|
116
|
+
return { promise, cancel };
|
|
117
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AnyRouter, inferRouterError } from '@trpc/server';
|
|
2
|
+
import {
|
|
3
|
+
TRPCResponse,
|
|
4
|
+
TRPCResponseMessage,
|
|
5
|
+
TRPCResultMessage,
|
|
6
|
+
} from '@trpc/server/rpc';
|
|
7
|
+
import { TRPCClientRuntime } from '..';
|
|
8
|
+
|
|
9
|
+
// FIXME:
|
|
10
|
+
// - the generics here are probably unnecessary
|
|
11
|
+
// - the RPC-spec could probably be simplified to combine HTTP + WS
|
|
12
|
+
/** @internal */
|
|
13
|
+
export function transformResult<TRouter extends AnyRouter, TOutput>(
|
|
14
|
+
response:
|
|
15
|
+
| TRPCResponseMessage<TOutput, inferRouterError<TRouter>>
|
|
16
|
+
| TRPCResponse<TOutput, inferRouterError<TRouter>>,
|
|
17
|
+
runtime: TRPCClientRuntime,
|
|
18
|
+
) {
|
|
19
|
+
if ('error' in response) {
|
|
20
|
+
const error = runtime.transformer.deserialize(
|
|
21
|
+
response.error,
|
|
22
|
+
) as inferRouterError<TRouter>;
|
|
23
|
+
return {
|
|
24
|
+
ok: false,
|
|
25
|
+
error: {
|
|
26
|
+
...response,
|
|
27
|
+
error,
|
|
28
|
+
},
|
|
29
|
+
} as const;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const result = {
|
|
33
|
+
...response.result,
|
|
34
|
+
...((!response.result.type || response.result.type === 'data') && {
|
|
35
|
+
type: 'data',
|
|
36
|
+
data: runtime.transformer.deserialize(response.result.data),
|
|
37
|
+
}),
|
|
38
|
+
} as TRPCResultMessage<TOutput>['result'];
|
|
39
|
+
return { ok: true, result } as const;
|
|
40
|
+
}
|
package/src/links/loggerLink.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { AnyRouter } from '@trpc/server';
|
|
2
|
+
import { observable, tap } from '@trpc/server/observable';
|
|
2
3
|
import { TRPCClientError } from '..';
|
|
3
|
-
import {
|
|
4
|
-
import { tap } from '../rx/operators';
|
|
5
|
-
import { Operation, OperationResult, TRPCLink } from './types';
|
|
4
|
+
import { Operation, OperationResultEnvelope, TRPCLink } from './types';
|
|
6
5
|
|
|
7
6
|
type ConsoleEsque = {
|
|
8
7
|
log: (...args: any[]) => void;
|
|
@@ -15,7 +14,7 @@ type EnableFnOptions<TRouter extends AnyRouter> =
|
|
|
15
14
|
})
|
|
16
15
|
| {
|
|
17
16
|
direction: 'down';
|
|
18
|
-
result:
|
|
17
|
+
result: OperationResultEnvelope<unknown> | TRPCClientError<TRouter>;
|
|
19
18
|
};
|
|
20
19
|
type EnabledFn<TRouter extends AnyRouter> = (
|
|
21
20
|
opts: EnableFnOptions<TRouter>,
|
|
@@ -34,7 +33,7 @@ type LogFnOptions<TRouter extends AnyRouter> = Operation &
|
|
|
34
33
|
* Request result
|
|
35
34
|
*/
|
|
36
35
|
direction: 'down';
|
|
37
|
-
result:
|
|
36
|
+
result: OperationResultEnvelope<unknown> | TRPCClientError<TRouter>;
|
|
38
37
|
elapsedMs: number;
|
|
39
38
|
}
|
|
40
39
|
);
|
|
@@ -93,7 +92,7 @@ const defaultLogger =
|
|
|
93
92
|
const fn: 'error' | 'log' =
|
|
94
93
|
props.direction === 'down' &&
|
|
95
94
|
props.result &&
|
|
96
|
-
(props.result instanceof Error || 'error' in props.result.
|
|
95
|
+
(props.result instanceof Error || 'error' in props.result.result)
|
|
97
96
|
? 'error'
|
|
98
97
|
: 'log';
|
|
99
98
|
|
|
@@ -117,7 +116,7 @@ export function loggerLink<TRouter extends AnyRouter = AnyRouter>(
|
|
|
117
116
|
});
|
|
118
117
|
const requestStartTime = Date.now();
|
|
119
118
|
function logResult(
|
|
120
|
-
result:
|
|
119
|
+
result: OperationResultEnvelope<unknown> | TRPCClientError<TRouter>,
|
|
121
120
|
) {
|
|
122
121
|
const elapsedMs = Date.now() - requestStartTime;
|
|
123
122
|
|
package/src/links/retryLink.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { AnyRouter } from '@trpc/server';
|
|
2
|
-
import { observable } from '
|
|
3
|
-
import { Unsubscribable } from '../rx/types';
|
|
2
|
+
import { Unsubscribable, observable } from '@trpc/server/observable';
|
|
4
3
|
import { TRPCLink } from './types';
|
|
5
4
|
|
|
6
5
|
export function retryLink<TRouter extends AnyRouter = AnyRouter>(opts: {
|
|
@@ -27,7 +26,7 @@ export function retryLink<TRouter extends AnyRouter = AnyRouter>(opts: {
|
|
|
27
26
|
attempt();
|
|
28
27
|
},
|
|
29
28
|
next(result) {
|
|
30
|
-
if ('result' in result.
|
|
29
|
+
if ('result' in result.result) {
|
|
31
30
|
isDone = true;
|
|
32
31
|
observer.next(result);
|
|
33
32
|
return;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
2
|
+
import { observable } from '@trpc/server/observable';
|
|
3
|
+
import { splitLink } from '../';
|
|
4
|
+
import { OperationLink, TRPCLink } from '../';
|
|
2
5
|
import { AnyRouter } from '../../../server/src';
|
|
3
6
|
import { createChain } from '../links/internals/createChain';
|
|
4
|
-
import { splitLink } from '../links/splitLink';
|
|
5
|
-
import { OperationLink, TRPCLink } from '../links/types';
|
|
6
|
-
import { observable } from '../rx';
|
|
7
7
|
|
|
8
8
|
test('splitLink', () => {
|
|
9
9
|
const wsLinkSpy = jest.fn();
|
package/src/links/splitLink.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AnyRouter } from '@trpc/server';
|
|
2
|
-
import { observable } from '
|
|
3
|
-
import { TRPCLink, Operation } from './types';
|
|
2
|
+
import { observable } from '@trpc/server/observable';
|
|
4
3
|
import { createChain } from './internals/createChain';
|
|
4
|
+
import { Operation, TRPCLink } from './types';
|
|
5
5
|
|
|
6
6
|
function asArray<T>(value: T | T[]) {
|
|
7
7
|
return Array.isArray(value) ? value : [value];
|
|
@@ -17,9 +17,9 @@ export function splitLink<TRouter extends AnyRouter = AnyRouter>(opts: {
|
|
|
17
17
|
*/
|
|
18
18
|
false: TRPCLink<TRouter> | TRPCLink<TRouter>[];
|
|
19
19
|
}): TRPCLink<TRouter> {
|
|
20
|
-
return (
|
|
21
|
-
const yes = asArray(opts.true).map((link) => link(
|
|
22
|
-
const no = asArray(opts.false).map((link) => link(
|
|
20
|
+
return (runtime) => {
|
|
21
|
+
const yes = asArray(opts.true).map((link) => link(runtime));
|
|
22
|
+
const no = asArray(opts.false).map((link) => link(runtime));
|
|
23
23
|
return (props) => {
|
|
24
24
|
return observable((observer) => {
|
|
25
25
|
const links = opts.condition(props.op) ? yes : no;
|
package/src/links/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AnyRouter,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { AnyRouter, DataTransformer } from '@trpc/server';
|
|
2
|
+
import { Observable, Observer } from '@trpc/server/observable';
|
|
3
|
+
import { TRPCResultMessage, TRPCSuccessResponse } from '@trpc/server/rpc';
|
|
4
4
|
import { TRPCClientError } from '../TRPCClientError';
|
|
5
5
|
|
|
6
6
|
export type CancelFn = () => void;
|
|
@@ -16,10 +16,10 @@ export type Operation<TInput = unknown> = {
|
|
|
16
16
|
type: 'query' | 'mutation' | 'subscription';
|
|
17
17
|
input: TInput;
|
|
18
18
|
path: string;
|
|
19
|
-
context
|
|
19
|
+
context: OperationContext;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
export type HTTPHeaders =
|
|
22
|
+
export type HTTPHeaders = Record<string, string | string[]>;
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* The default `fetch` implementation has an overloaded signature. By convention this library
|
|
@@ -30,26 +30,29 @@ export type TRPCFetch = (
|
|
|
30
30
|
options?: RequestInit,
|
|
31
31
|
) => Promise<Response>;
|
|
32
32
|
|
|
33
|
-
export interface
|
|
34
|
-
headers: () => HTTPHeaders | Promise<HTTPHeaders>;
|
|
33
|
+
export interface TRPCClientRuntime {
|
|
35
34
|
fetch: TRPCFetch;
|
|
36
35
|
AbortController?: typeof AbortController;
|
|
36
|
+
headers: () => HTTPHeaders | Promise<HTTPHeaders>;
|
|
37
|
+
transformer: DataTransformer;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
export interface
|
|
40
|
-
|
|
40
|
+
export interface OperationResultEnvelope<TOutput> {
|
|
41
|
+
result:
|
|
42
|
+
| TRPCSuccessResponse<TOutput>['result']
|
|
43
|
+
| TRPCResultMessage<TOutput>['result'];
|
|
41
44
|
context?: OperationContext;
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
export type OperationResultObservable<
|
|
45
48
|
TRouter extends AnyRouter,
|
|
46
49
|
TOutput,
|
|
47
|
-
> = Observable<
|
|
50
|
+
> = Observable<OperationResultEnvelope<TOutput>, TRPCClientError<TRouter>>;
|
|
48
51
|
|
|
49
52
|
export type OperationResultObserver<
|
|
50
53
|
TRouter extends AnyRouter,
|
|
51
54
|
TOutput,
|
|
52
|
-
> = Observer<
|
|
55
|
+
> = Observer<OperationResultEnvelope<TOutput>, TRPCClientError<TRouter>>;
|
|
53
56
|
|
|
54
57
|
export type OperationLink<
|
|
55
58
|
TRouter extends AnyRouter,
|
|
@@ -61,5 +64,5 @@ export type OperationLink<
|
|
|
61
64
|
}) => OperationResultObservable<TRouter, TOutput>;
|
|
62
65
|
|
|
63
66
|
export type TRPCLink<TRouter extends AnyRouter> = (
|
|
64
|
-
opts:
|
|
67
|
+
opts: TRPCClientRuntime,
|
|
65
68
|
) => OperationLink<TRouter>;
|
package/src/links/wsLink.ts
CHANGED
|
@@ -1,26 +1,42 @@
|
|
|
1
|
-
import { AnyRouter, ProcedureType } from '@trpc/server';
|
|
1
|
+
import { AnyRouter, ProcedureType, inferRouterError } from '@trpc/server';
|
|
2
|
+
import { Observer, UnsubscribeFn, observable } from '@trpc/server/observable';
|
|
2
3
|
import {
|
|
3
4
|
TRPCClientIncomingMessage,
|
|
4
5
|
TRPCClientIncomingRequest,
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
TRPCClientOutgoingMessage,
|
|
7
|
+
TRPCRequestMessage,
|
|
8
|
+
TRPCResponseMessage,
|
|
7
9
|
} from '@trpc/server/rpc';
|
|
8
|
-
import { retryDelay } from '../internals/retryDelay';
|
|
9
|
-
import { UnsubscribeFn } from '../rx';
|
|
10
|
-
import { observable } from '../rx/observable';
|
|
11
10
|
import { TRPCClientError } from '../TRPCClientError';
|
|
12
|
-
import {
|
|
11
|
+
import { retryDelay } from '../internals/retryDelay';
|
|
12
|
+
import { transformResult } from './internals/transformResult';
|
|
13
|
+
import { Operation, TRPCLink } from './types';
|
|
14
|
+
|
|
15
|
+
type WSCallbackResult<TRouter extends AnyRouter, TOutput> = TRPCResponseMessage<
|
|
16
|
+
TOutput,
|
|
17
|
+
inferRouterError<TRouter>
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
type WSCallbackObserver<TRouter extends AnyRouter, TOutput> = Observer<
|
|
21
|
+
WSCallbackResult<TRouter, TOutput>,
|
|
22
|
+
TRPCClientError<TRouter>
|
|
23
|
+
>;
|
|
13
24
|
|
|
14
25
|
export interface WebSocketClientOptions {
|
|
15
26
|
url: string;
|
|
16
|
-
WebSocket?: WebSocket;
|
|
27
|
+
WebSocket?: typeof WebSocket;
|
|
17
28
|
retryDelayMs?: typeof retryDelay;
|
|
29
|
+
onOpen?: () => void;
|
|
30
|
+
onClose?: () => void;
|
|
18
31
|
}
|
|
32
|
+
|
|
19
33
|
export function createWSClient(opts: WebSocketClientOptions) {
|
|
20
34
|
const {
|
|
21
35
|
url,
|
|
22
36
|
WebSocket: WebSocketImpl = WebSocket,
|
|
23
37
|
retryDelayMs: retryDelayFn = retryDelay,
|
|
38
|
+
onOpen,
|
|
39
|
+
onClose,
|
|
24
40
|
} = opts;
|
|
25
41
|
/* istanbul ignore next */
|
|
26
42
|
if (!WebSocketImpl) {
|
|
@@ -31,11 +47,11 @@ export function createWSClient(opts: WebSocketClientOptions) {
|
|
|
31
47
|
/**
|
|
32
48
|
* outgoing messages buffer whilst not open
|
|
33
49
|
*/
|
|
34
|
-
let outgoing:
|
|
50
|
+
let outgoing: TRPCClientOutgoingMessage[] = [];
|
|
35
51
|
/**
|
|
36
52
|
* pending outgoing requests that are awaiting callback
|
|
37
53
|
*/
|
|
38
|
-
type TCallbacks =
|
|
54
|
+
type TCallbacks = WSCallbackObserver<AnyRouter, unknown>;
|
|
39
55
|
type TRequest = {
|
|
40
56
|
/**
|
|
41
57
|
* Reference to the WebSocket instance this request was made to
|
|
@@ -112,7 +128,7 @@ export function createWSClient(opts: WebSocketClientOptions) {
|
|
|
112
128
|
}
|
|
113
129
|
|
|
114
130
|
function createWS() {
|
|
115
|
-
const conn = new
|
|
131
|
+
const conn = new WebSocketImpl(url);
|
|
116
132
|
clearTimeout(connectTimer as any);
|
|
117
133
|
connectTimer = null;
|
|
118
134
|
|
|
@@ -123,6 +139,7 @@ export function createWSClient(opts: WebSocketClientOptions) {
|
|
|
123
139
|
}
|
|
124
140
|
connectAttempt = 0;
|
|
125
141
|
state = 'open';
|
|
142
|
+
onOpen?.();
|
|
126
143
|
dispatch();
|
|
127
144
|
});
|
|
128
145
|
conn.addEventListener('error', () => {
|
|
@@ -132,6 +149,9 @@ export function createWSClient(opts: WebSocketClientOptions) {
|
|
|
132
149
|
});
|
|
133
150
|
const handleIncomingRequest = (req: TRPCClientIncomingRequest) => {
|
|
134
151
|
if (req.method === 'reconnect' && conn === activeConnection) {
|
|
152
|
+
if (state === 'open') {
|
|
153
|
+
onClose?.();
|
|
154
|
+
}
|
|
135
155
|
reconnect();
|
|
136
156
|
// notify subscribers
|
|
137
157
|
for (const pendingReq of Object.values(pendingRequests)) {
|
|
@@ -141,14 +161,14 @@ export function createWSClient(opts: WebSocketClientOptions) {
|
|
|
141
161
|
}
|
|
142
162
|
}
|
|
143
163
|
};
|
|
144
|
-
const handleIncomingResponse = (data:
|
|
164
|
+
const handleIncomingResponse = (data: TRPCResponseMessage) => {
|
|
145
165
|
const req = data.id !== null && pendingRequests[data.id];
|
|
146
166
|
if (!req) {
|
|
147
167
|
// do something?
|
|
148
168
|
return;
|
|
149
169
|
}
|
|
150
170
|
|
|
151
|
-
req.callbacks.next?.(
|
|
171
|
+
req.callbacks.next?.(data);
|
|
152
172
|
if (req.ws !== activeConnection && conn === activeConnection) {
|
|
153
173
|
const oldWs = req.ws;
|
|
154
174
|
// gracefully replace old connection with this
|
|
@@ -179,13 +199,16 @@ export function createWSClient(opts: WebSocketClientOptions) {
|
|
|
179
199
|
});
|
|
180
200
|
|
|
181
201
|
conn.addEventListener('close', () => {
|
|
202
|
+
if (state === 'open') {
|
|
203
|
+
onClose?.();
|
|
204
|
+
}
|
|
205
|
+
|
|
182
206
|
if (activeConnection === conn) {
|
|
183
207
|
// connection might have been replaced already
|
|
184
208
|
tryReconnect();
|
|
185
209
|
}
|
|
186
210
|
|
|
187
|
-
for (const key
|
|
188
|
-
const req = pendingRequests[key];
|
|
211
|
+
for (const [key, req] of Object.entries(pendingRequests)) {
|
|
189
212
|
if (req.ws !== conn) {
|
|
190
213
|
continue;
|
|
191
214
|
}
|
|
@@ -208,9 +231,8 @@ export function createWSClient(opts: WebSocketClientOptions) {
|
|
|
208
231
|
|
|
209
232
|
function request(op: Operation, callbacks: TCallbacks): UnsubscribeFn {
|
|
210
233
|
const { type, input, path, id } = op;
|
|
211
|
-
const envelope:
|
|
234
|
+
const envelope: TRPCRequestMessage = {
|
|
212
235
|
id,
|
|
213
|
-
jsonrpc: '2.0',
|
|
214
236
|
method: type,
|
|
215
237
|
params: {
|
|
216
238
|
input,
|
|
@@ -238,7 +260,6 @@ export function createWSClient(opts: WebSocketClientOptions) {
|
|
|
238
260
|
outgoing.push({
|
|
239
261
|
id,
|
|
240
262
|
method: 'subscription.stop',
|
|
241
|
-
params: undefined,
|
|
242
263
|
});
|
|
243
264
|
dispatch();
|
|
244
265
|
}
|
|
@@ -247,7 +268,10 @@ export function createWSClient(opts: WebSocketClientOptions) {
|
|
|
247
268
|
return {
|
|
248
269
|
close: () => {
|
|
249
270
|
state = 'closed';
|
|
271
|
+
onClose?.();
|
|
250
272
|
closeIfNoPending(activeConnection);
|
|
273
|
+
clearTimeout(connectTimer as any);
|
|
274
|
+
connectTimer = null;
|
|
251
275
|
},
|
|
252
276
|
request,
|
|
253
277
|
getConnection() {
|
|
@@ -279,11 +303,13 @@ class TRPCSubscriptionEndedError extends Error {
|
|
|
279
303
|
export function wsLink<TRouter extends AnyRouter>(
|
|
280
304
|
opts: WebSocketLinkOptions,
|
|
281
305
|
): TRPCLink<TRouter> {
|
|
282
|
-
return () => {
|
|
306
|
+
return (runtime) => {
|
|
283
307
|
const { client } = opts;
|
|
284
308
|
return ({ op }) => {
|
|
285
309
|
return observable((observer) => {
|
|
286
|
-
const { type,
|
|
310
|
+
const { type, path, id, context } = op;
|
|
311
|
+
|
|
312
|
+
const input = runtime.transformer.serialize(op.input);
|
|
287
313
|
|
|
288
314
|
let isDone = false;
|
|
289
315
|
const unsub = client.request(
|
|
@@ -291,7 +317,7 @@ export function wsLink<TRouter extends AnyRouter>(
|
|
|
291
317
|
{
|
|
292
318
|
error(err) {
|
|
293
319
|
isDone = true;
|
|
294
|
-
observer.error(err);
|
|
320
|
+
observer.error(err as TRPCClientError<any>);
|
|
295
321
|
unsub();
|
|
296
322
|
},
|
|
297
323
|
complete() {
|
|
@@ -308,8 +334,16 @@ export function wsLink<TRouter extends AnyRouter>(
|
|
|
308
334
|
observer.complete();
|
|
309
335
|
}
|
|
310
336
|
},
|
|
311
|
-
next(
|
|
312
|
-
|
|
337
|
+
next(message) {
|
|
338
|
+
const transformed = transformResult(message, runtime);
|
|
339
|
+
|
|
340
|
+
if (!transformed.ok) {
|
|
341
|
+
observer.error(TRPCClientError.from(transformed.error));
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
observer.next({
|
|
345
|
+
result: transformed.result,
|
|
346
|
+
});
|
|
313
347
|
|
|
314
348
|
if (op.type !== 'subscription') {
|
|
315
349
|
// if it isn't a subscription we don't care about next response
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
2
|
-
import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
|
|
3
|
-
import _createClass from '@babel/runtime/helpers/createClass';
|
|
4
|
-
import _assertThisInitialized from '@babel/runtime/helpers/assertThisInitialized';
|
|
5
|
-
import _inherits from '@babel/runtime/helpers/inherits';
|
|
6
|
-
import _possibleConstructorReturn from '@babel/runtime/helpers/possibleConstructorReturn';
|
|
7
|
-
import _getPrototypeOf from '@babel/runtime/helpers/getPrototypeOf';
|
|
8
|
-
import _wrapNativeSuper from '@babel/runtime/helpers/wrapNativeSuper';
|
|
9
|
-
|
|
10
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
11
|
-
|
|
12
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
13
|
-
|
|
14
|
-
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
|
15
|
-
|
|
16
|
-
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
17
|
-
|
|
18
|
-
var TRPCClientError = /*#__PURE__*/function (_Error) {
|
|
19
|
-
_inherits(TRPCClientError, _Error);
|
|
20
|
-
|
|
21
|
-
var _super = /*#__PURE__*/_createSuper(TRPCClientError);
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @deprecated use `cause`
|
|
25
|
-
*/
|
|
26
|
-
function TRPCClientError(message, opts) {
|
|
27
|
-
var _opts$cause, _opts$result, _opts$result2;
|
|
28
|
-
|
|
29
|
-
var _this;
|
|
30
|
-
|
|
31
|
-
_classCallCheck(this, TRPCClientError);
|
|
32
|
-
|
|
33
|
-
var cause = (_opts$cause = opts === null || opts === void 0 ? void 0 : opts.cause) !== null && _opts$cause !== void 0 ? _opts$cause : opts === null || opts === void 0 ? void 0 : opts.originalError; // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
34
|
-
// @ts-ignore https://github.com/tc39/proposal-error-cause
|
|
35
|
-
|
|
36
|
-
_this = _super.call(this, message, {
|
|
37
|
-
cause: cause
|
|
38
|
-
});
|
|
39
|
-
_this.originalError = void 0;
|
|
40
|
-
_this.cause = void 0;
|
|
41
|
-
_this.shape = void 0;
|
|
42
|
-
_this.data = void 0;
|
|
43
|
-
_this.meta = void 0;
|
|
44
|
-
_this.meta = opts === null || opts === void 0 ? void 0 : opts.meta;
|
|
45
|
-
_this.cause = _this.originalError = cause;
|
|
46
|
-
_this.shape = opts === null || opts === void 0 ? void 0 : (_opts$result = opts.result) === null || _opts$result === void 0 ? void 0 : _opts$result.error;
|
|
47
|
-
_this.data = opts === null || opts === void 0 ? void 0 : (_opts$result2 = opts.result) === null || _opts$result2 === void 0 ? void 0 : _opts$result2.error.data;
|
|
48
|
-
_this.name = 'TRPCClientError';
|
|
49
|
-
Object.setPrototypeOf(_assertThisInitialized(_this), TRPCClientError.prototype);
|
|
50
|
-
return _this;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
_createClass(TRPCClientError, null, [{
|
|
54
|
-
key: "from",
|
|
55
|
-
value: function from(cause) {
|
|
56
|
-
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
57
|
-
|
|
58
|
-
if (!(cause instanceof Error)) {
|
|
59
|
-
var _message;
|
|
60
|
-
|
|
61
|
-
return new TRPCClientError((_message = cause.error.message) !== null && _message !== void 0 ? _message : '', _objectSpread(_objectSpread({}, opts), {}, {
|
|
62
|
-
cause: null,
|
|
63
|
-
result: cause
|
|
64
|
-
}));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (cause.name === 'TRPCClientError') {
|
|
68
|
-
return cause;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return new TRPCClientError(cause.message, _objectSpread(_objectSpread({}, opts), {}, {
|
|
72
|
-
cause: cause,
|
|
73
|
-
result: null
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
}]);
|
|
77
|
-
|
|
78
|
-
return TRPCClientError;
|
|
79
|
-
}( /*#__PURE__*/_wrapNativeSuper(Error));
|
|
80
|
-
|
|
81
|
-
export { TRPCClientError as T };
|