@trpc/client 9.18.0 → 10.0.0-alpha.3
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/dist/TRPCClientError-17b117e1.mjs +81 -0
- package/dist/TRPCClientError-ec6bd2ca.js +94 -0
- package/dist/{declarations/src/TRPCClientError.d.ts → TRPCClientError.d.ts} +29 -33
- package/dist/TRPCClientError.d.ts.map +1 -0
- package/dist/createChain-389cc116.mjs +25 -0
- package/dist/createChain-864dbb30.js +27 -0
- package/dist/{declarations/src/createTRPCClient.d.ts → createTRPCClient.d.ts} +5 -6
- package/dist/createTRPCClient.d.ts.map +1 -0
- package/dist/{declarations/src/getFetch.d.ts → getFetch.d.ts} +1 -1
- package/dist/getFetch.d.ts.map +1 -0
- package/dist/httpUtils-1f9e4e3c.js +97 -0
- package/dist/httpUtils-c09d7b79.mjs +91 -0
- package/dist/{declarations/src/index.d.ts → index.d.ts} +4 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +314 -0
- package/dist/index.mjs +299 -0
- package/dist/index.ts.js +1 -0
- package/dist/{declarations/src/internals → internals}/TRPCClient.d.ts +64 -61
- package/dist/internals/TRPCClient.d.ts.map +1 -0
- package/dist/{declarations/src/internals → internals}/dataLoader.d.ts +14 -16
- package/dist/internals/dataLoader.d.ts.map +1 -0
- package/dist/{declarations/src/internals → internals}/fetchHelpers.d.ts +2 -2
- package/dist/internals/fetchHelpers.d.ts.map +1 -0
- package/dist/{declarations/src/internals → internals}/retryDelay.d.ts +1 -1
- package/dist/internals/retryDelay.d.ts.map +1 -0
- package/dist/internals/transformRPCResponse.d.ts +15 -0
- package/dist/internals/transformRPCResponse.d.ts.map +1 -0
- package/dist/links/dedupeLink.d.ts +4 -0
- package/dist/links/dedupeLink.d.ts.map +1 -0
- package/dist/links/httpBatchLink.d.ts +5 -0
- package/dist/links/httpBatchLink.d.ts.map +1 -0
- package/dist/links/httpBatchLink.js +189 -0
- package/dist/links/httpBatchLink.mjs +185 -0
- package/dist/links/httpBatchLink.ts.js +1 -0
- package/dist/{declarations/src/links → links}/httpLink.d.ts +4 -3
- package/dist/links/httpLink.d.ts.map +1 -0
- package/dist/links/httpLink.js +44 -0
- package/dist/links/httpLink.mjs +40 -0
- package/dist/links/httpLink.ts.js +1 -0
- package/dist/links/httpUtils.d.ts +22 -0
- package/dist/links/httpUtils.d.ts.map +1 -0
- package/dist/links/internals/createChain.d.ts +8 -0
- package/dist/links/internals/createChain.d.ts.map +1 -0
- package/dist/links/internals/transformOperationResult.d.ts +16 -0
- package/dist/links/internals/transformOperationResult.d.ts.map +1 -0
- package/dist/{declarations/src/links → links}/loggerLink.d.ts +38 -37
- package/dist/links/loggerLink.d.ts.map +1 -0
- package/dist/links/loggerLink.js +108 -0
- package/dist/links/loggerLink.mjs +99 -0
- package/dist/links/loggerLink.ts.js +1 -0
- package/dist/links/retryLink.d.ts +6 -0
- package/dist/links/retryLink.d.ts.map +1 -0
- package/dist/links/splitLink.d.ts +14 -0
- package/dist/links/splitLink.d.ts.map +1 -0
- package/dist/links/splitLink.js +32 -0
- package/dist/links/splitLink.mjs +28 -0
- package/dist/links/splitLink.ts.js +1 -0
- package/dist/links/transformerLink.d.ts +4 -0
- package/dist/links/transformerLink.d.ts.map +1 -0
- package/dist/links/transformerLink.js +75 -0
- package/dist/links/transformerLink.mjs +67 -0
- package/dist/links/transformerLink.ts.js +1 -0
- package/dist/links/types.d.ts +40 -0
- package/dist/links/types.d.ts.map +1 -0
- package/dist/{declarations/src/links → links}/wsLink.d.ts +19 -26
- package/dist/links/wsLink.d.ts.map +1 -0
- package/dist/links/wsLink.js +384 -0
- package/dist/links/wsLink.mjs +370 -0
- package/dist/links/wsLink.ts.js +1 -0
- package/dist/observable-7e66cb56.mjs +102 -0
- package/dist/observable-85669100.js +104 -0
- package/dist/rx/index.d.ts +3 -0
- package/dist/rx/index.d.ts.map +1 -0
- package/dist/rx/index.js +9 -0
- package/dist/rx/index.mjs +1 -0
- package/dist/rx/index.ts.js +1 -0
- package/dist/rx/observable.d.ts +4 -0
- package/dist/rx/observable.d.ts.map +1 -0
- package/dist/rx/operators/index.d.ts +4 -0
- package/dist/rx/operators/index.d.ts.map +1 -0
- package/dist/rx/operators/index.js +38 -0
- package/dist/rx/operators/index.mjs +32 -0
- package/dist/rx/operators/index.ts.js +1 -0
- package/dist/rx/operators/map.d.ts +3 -0
- package/dist/rx/operators/map.d.ts.map +1 -0
- package/dist/rx/operators/share.d.ts +6 -0
- package/dist/rx/operators/share.d.ts.map +1 -0
- package/dist/rx/operators/tap.d.ts +3 -0
- package/dist/rx/operators/tap.d.ts.map +1 -0
- package/dist/rx/types.d.ts +29 -0
- package/dist/rx/types.d.ts.map +1 -0
- package/dist/rx/util/identity.d.ts +2 -0
- package/dist/rx/util/identity.d.ts.map +1 -0
- package/dist/rx/util/observableToPromise.d.ts +10 -0
- package/dist/rx/util/observableToPromise.d.ts.map +1 -0
- package/dist/rx/util/pipe.d.ts +4 -0
- package/dist/rx/util/pipe.d.ts.map +1 -0
- package/dist/share-4d79dc49.js +110 -0
- package/dist/share-671b63fa.mjs +108 -0
- package/dist/tap-538fa07f.mjs +30 -0
- package/dist/tap-799a2d33.js +32 -0
- package/links/httpBatchLink/index.d.ts +1 -0
- package/links/httpBatchLink/index.js +1 -0
- package/links/httpLink/index.d.ts +1 -0
- package/links/httpLink/index.js +1 -0
- package/links/loggerLink/index.d.ts +1 -0
- package/links/loggerLink/index.js +1 -0
- package/links/splitLink/index.d.ts +1 -0
- package/links/splitLink/index.js +1 -0
- package/links/transformerLink/index.d.ts +1 -0
- package/links/transformerLink/index.js +1 -0
- package/links/wsLink/index.d.ts +1 -0
- package/links/wsLink/index.js +1 -0
- package/package.json +58 -18
- package/rx/dist/trpc-client-rx.cjs.d.ts +1 -0
- package/rx/dist/trpc-client-rx.cjs.dev.js +9 -0
- package/rx/dist/trpc-client-rx.cjs.js +7 -0
- package/rx/dist/trpc-client-rx.cjs.prod.js +9 -0
- package/rx/dist/trpc-client-rx.esm.js +1 -0
- package/rx/index.d.ts +1 -0
- package/rx/index.js +1 -0
- package/rx/operators/dist/trpc-client-rx-operators.cjs.d.ts +1 -0
- package/rx/operators/dist/trpc-client-rx-operators.cjs.dev.js +39 -0
- package/rx/operators/dist/trpc-client-rx-operators.cjs.js +7 -0
- package/rx/operators/dist/trpc-client-rx-operators.cjs.prod.js +39 -0
- package/rx/operators/dist/trpc-client-rx-operators.esm.js +33 -0
- package/rx/operators/index.d.ts +1 -0
- package/rx/operators/index.js +1 -0
- package/src/TRPCClientError.ts +17 -21
- package/src/createTRPCClient.ts +4 -3
- package/src/index.ts +1 -1
- package/src/internals/TRPCClient.ts +80 -88
- package/src/internals/dataLoader.ts +2 -14
- package/src/internals/transformRPCResponse.ts +2 -2
- package/src/links/dedupeLink.test.ts +134 -0
- package/src/links/dedupeLink.ts +53 -0
- package/src/links/httpBatchLink.ts +36 -52
- package/src/links/httpLink.ts +26 -37
- package/src/{internals/httpRequest.ts → links/httpUtils.ts} +30 -21
- package/src/links/internals/createChain.test.ts +132 -0
- package/src/links/internals/createChain.ts +31 -0
- package/src/links/internals/transformOperationResult.ts +25 -0
- package/src/links/loggerLink.ts +40 -22
- package/src/links/retryLink.ts +45 -14
- package/src/links/splitLink.test.ts +56 -0
- package/src/links/splitLink.ts +23 -38
- package/src/links/transformerLink.ts +70 -0
- package/src/links/{core.ts → types.ts} +40 -46
- package/src/links/wsLink.ts +56 -77
- package/src/rx/index.ts +2 -0
- package/src/rx/observable.test.ts +83 -0
- package/src/rx/observable.ts +70 -0
- package/src/rx/operators/index.ts +3 -0
- package/src/rx/operators/map.test.ts +92 -0
- package/src/rx/operators/map.ts +25 -0
- package/src/rx/operators/share.test.ts +60 -0
- package/src/rx/operators/share.ts +67 -0
- package/src/rx/operators/tap.ts +26 -0
- package/src/rx/types.ts +69 -0
- package/src/rx/util/identity.ts +3 -0
- package/src/rx/util/observableToPromise.ts +49 -0
- package/src/rx/util/pipe.ts +22 -0
- package/dist/TRPCClientError-09b8a26b.esm.js +0 -77
- package/dist/TRPCClientError-bfee2bf5.cjs.dev.js +0 -79
- package/dist/TRPCClientError-e9bf96e9.cjs.prod.js +0 -79
- package/dist/declarations/src/TRPCClientError.d.ts.map +0 -1
- package/dist/declarations/src/createTRPCClient.d.ts.map +0 -1
- package/dist/declarations/src/getFetch.d.ts.map +0 -1
- package/dist/declarations/src/index.d.ts.map +0 -1
- package/dist/declarations/src/internals/TRPCAbortError.d.ts +0 -4
- package/dist/declarations/src/internals/TRPCAbortError.d.ts.map +0 -1
- package/dist/declarations/src/internals/TRPCClient.d.ts.map +0 -1
- package/dist/declarations/src/internals/dataLoader.d.ts.map +0 -1
- package/dist/declarations/src/internals/executeChain.d.ts +0 -8
- package/dist/declarations/src/internals/executeChain.d.ts.map +0 -1
- package/dist/declarations/src/internals/fetchHelpers.d.ts.map +0 -1
- package/dist/declarations/src/internals/httpRequest.d.ts +0 -14
- package/dist/declarations/src/internals/httpRequest.d.ts.map +0 -1
- package/dist/declarations/src/internals/observable.d.ts +0 -18
- package/dist/declarations/src/internals/observable.d.ts.map +0 -1
- package/dist/declarations/src/internals/retryDelay.d.ts.map +0 -1
- package/dist/declarations/src/internals/transformRPCResponse.d.ts +0 -7
- package/dist/declarations/src/internals/transformRPCResponse.d.ts.map +0 -1
- package/dist/declarations/src/links/core.d.ts +0 -45
- package/dist/declarations/src/links/core.d.ts.map +0 -1
- package/dist/declarations/src/links/httpBatchLink.d.ts +0 -7
- package/dist/declarations/src/links/httpBatchLink.d.ts.map +0 -1
- package/dist/declarations/src/links/httpLink.d.ts.map +0 -1
- package/dist/declarations/src/links/loggerLink.d.ts.map +0 -1
- package/dist/declarations/src/links/splitLink.d.ts +0 -24
- package/dist/declarations/src/links/splitLink.d.ts.map +0 -1
- package/dist/declarations/src/links/wsLink.d.ts.map +0 -1
- package/dist/transformRPCResponse-57e80136.cjs.dev.js +0 -133
- package/dist/transformRPCResponse-739c13d0.cjs.prod.js +0 -133
- package/dist/transformRPCResponse-f7f8b0e1.esm.js +0 -129
- package/dist/trpc-client.cjs.d.ts +0 -1
- package/dist/trpc-client.cjs.dev.js +0 -379
- package/dist/trpc-client.cjs.js +0 -7
- package/dist/trpc-client.cjs.prod.js +0 -379
- package/dist/trpc-client.esm.js +0 -374
- package/links/httpBatchLink/package.json +0 -4
- package/links/httpLink/package.json +0 -4
- package/links/loggerLink/package.json +0 -4
- package/links/splitLink/package.json +0 -4
- package/links/wsLink/package.json +0 -4
- package/src/internals/TRPCAbortError.ts +0 -7
- package/src/internals/executeChain.ts +0 -67
- package/src/internals/observable.ts +0 -89
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var share = require('../../../dist/share-5a8c2543.cjs.prod.js');
|
|
6
|
+
var tap = require('../../../dist/tap-d907998d.cjs.prod.js');
|
|
7
|
+
require('@babel/runtime/helpers/createForOfIteratorHelper');
|
|
8
|
+
|
|
9
|
+
function map(project) {
|
|
10
|
+
return function (originalObserver) {
|
|
11
|
+
return {
|
|
12
|
+
subscribe: function subscribe(observer) {
|
|
13
|
+
var index = 0;
|
|
14
|
+
var subscription = originalObserver.subscribe({
|
|
15
|
+
next: function next(value) {
|
|
16
|
+
var _observer$next;
|
|
17
|
+
|
|
18
|
+
(_observer$next = observer.next) === null || _observer$next === void 0 ? void 0 : _observer$next.call(observer, project(value, index++));
|
|
19
|
+
},
|
|
20
|
+
error: function error(_error) {
|
|
21
|
+
var _observer$error;
|
|
22
|
+
|
|
23
|
+
(_observer$error = observer.error) === null || _observer$error === void 0 ? void 0 : _observer$error.call(observer, _error);
|
|
24
|
+
},
|
|
25
|
+
complete: function complete() {
|
|
26
|
+
var _observer$complete;
|
|
27
|
+
|
|
28
|
+
(_observer$complete = observer.complete) === null || _observer$complete === void 0 ? void 0 : _observer$complete.call(observer);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return subscription;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
exports.share = share.share;
|
|
38
|
+
exports.tap = tap.tap;
|
|
39
|
+
exports.map = map;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export { s as share } from '../../../dist/share-ca585761.esm.js';
|
|
2
|
+
export { t as tap } from '../../../dist/tap-606957cb.esm.js';
|
|
3
|
+
import '@babel/runtime/helpers/createForOfIteratorHelper';
|
|
4
|
+
|
|
5
|
+
function map(project) {
|
|
6
|
+
return function (originalObserver) {
|
|
7
|
+
return {
|
|
8
|
+
subscribe: function subscribe(observer) {
|
|
9
|
+
var index = 0;
|
|
10
|
+
var subscription = originalObserver.subscribe({
|
|
11
|
+
next: function next(value) {
|
|
12
|
+
var _observer$next;
|
|
13
|
+
|
|
14
|
+
(_observer$next = observer.next) === null || _observer$next === void 0 ? void 0 : _observer$next.call(observer, project(value, index++));
|
|
15
|
+
},
|
|
16
|
+
error: function error(_error) {
|
|
17
|
+
var _observer$error;
|
|
18
|
+
|
|
19
|
+
(_observer$error = observer.error) === null || _observer$error === void 0 ? void 0 : _observer$error.call(observer, _error);
|
|
20
|
+
},
|
|
21
|
+
complete: function complete() {
|
|
22
|
+
var _observer$complete;
|
|
23
|
+
|
|
24
|
+
(_observer$complete = observer.complete) === null || _observer$complete === void 0 ? void 0 : _observer$complete.call(observer);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return subscription;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { map };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../dist/rx/operators';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('../../dist/rx/operators/index');
|
package/src/TRPCClientError.ts
CHANGED
|
@@ -18,58 +18,54 @@ export class TRPCClientError<TRouter extends AnyRouter>
|
|
|
18
18
|
public readonly cause;
|
|
19
19
|
public readonly shape: Maybe<inferRouterError<TRouter>>;
|
|
20
20
|
public readonly data: Maybe<inferRouterError<TRouter>['data']>;
|
|
21
|
-
|
|
22
|
-
* Fatal error - expect no more results after this error
|
|
23
|
-
* Used for when WebSockets disconnect prematurely.
|
|
24
|
-
*/
|
|
25
|
-
public readonly isDone: boolean;
|
|
21
|
+
public readonly meta;
|
|
26
22
|
|
|
27
23
|
constructor(
|
|
28
24
|
message: string,
|
|
29
|
-
opts
|
|
25
|
+
opts?: {
|
|
30
26
|
result: Maybe<TRPCErrorResponse<inferRouterError<TRouter>>>;
|
|
31
27
|
/**
|
|
32
|
-
* @deprecated use cause
|
|
28
|
+
* @deprecated use `cause`
|
|
33
29
|
**/
|
|
34
30
|
originalError?: Maybe<Error>;
|
|
35
31
|
cause?: Maybe<Error>;
|
|
36
|
-
|
|
32
|
+
meta?: Record<string, unknown>;
|
|
37
33
|
},
|
|
38
34
|
) {
|
|
39
|
-
const cause = opts
|
|
35
|
+
const cause = opts?.cause ?? opts?.originalError;
|
|
40
36
|
|
|
41
37
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
42
38
|
// @ts-ignore https://github.com/tc39/proposal-error-cause
|
|
43
39
|
super(message, { cause });
|
|
44
40
|
|
|
45
|
-
this.
|
|
41
|
+
this.meta = opts?.meta;
|
|
46
42
|
|
|
47
43
|
this.cause = this.originalError = cause;
|
|
48
|
-
this.shape = opts
|
|
49
|
-
this.data = opts
|
|
44
|
+
this.shape = opts?.result?.error;
|
|
45
|
+
this.data = opts?.result?.error.data;
|
|
50
46
|
this.name = 'TRPCClientError';
|
|
51
47
|
|
|
52
48
|
Object.setPrototypeOf(this, TRPCClientError.prototype);
|
|
53
49
|
}
|
|
54
50
|
|
|
55
51
|
public static from<TRouter extends AnyRouter>(
|
|
56
|
-
|
|
57
|
-
opts: {
|
|
52
|
+
cause: Error | TRPCErrorResponse<any>,
|
|
53
|
+
opts: { meta?: Record<string, unknown> } = {},
|
|
58
54
|
): TRPCClientError<TRouter> {
|
|
59
|
-
if (!(
|
|
60
|
-
return new TRPCClientError<TRouter>((
|
|
55
|
+
if (!(cause instanceof Error)) {
|
|
56
|
+
return new TRPCClientError<TRouter>((cause.error as any).message ?? '', {
|
|
61
57
|
...opts,
|
|
62
58
|
cause: null,
|
|
63
|
-
result:
|
|
59
|
+
result: cause,
|
|
64
60
|
});
|
|
65
61
|
}
|
|
66
|
-
if (
|
|
67
|
-
return
|
|
62
|
+
if (cause.name === 'TRPCClientError') {
|
|
63
|
+
return cause as TRPCClientError<any>;
|
|
68
64
|
}
|
|
69
65
|
|
|
70
|
-
return new TRPCClientError<TRouter>(
|
|
66
|
+
return new TRPCClientError<TRouter>(cause.message, {
|
|
71
67
|
...opts,
|
|
72
|
-
cause
|
|
68
|
+
cause,
|
|
73
69
|
result: null,
|
|
74
70
|
});
|
|
75
71
|
}
|
package/src/createTRPCClient.ts
CHANGED
|
@@ -11,8 +11,9 @@ export function createTRPCClient<TRouter extends AnyRouter>(
|
|
|
11
11
|
return new Client<TRouter>(opts);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export type { CreateTRPCClientOptions } from './internals/TRPCClient';
|
|
15
|
-
|
|
16
14
|
export type TRPCClient<TRouter extends AnyRouter> = Client<TRouter>;
|
|
17
15
|
|
|
18
|
-
export type {
|
|
16
|
+
export type {
|
|
17
|
+
TRPCRequestOptions,
|
|
18
|
+
CreateTRPCClientOptions,
|
|
19
|
+
} from './internals/TRPCClient';
|
package/src/index.ts
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AnyRouter,
|
|
3
|
-
ClientDataTransformerOptions,
|
|
4
|
-
DataTransformer,
|
|
5
3
|
inferHandlerInput,
|
|
6
4
|
inferProcedureInput,
|
|
7
5
|
inferProcedureOutput,
|
|
8
6
|
inferSubscriptionOutput,
|
|
9
7
|
} from '@trpc/server';
|
|
10
8
|
import { TRPCResult } from '@trpc/server/rpc';
|
|
11
|
-
import {
|
|
12
|
-
import { getAbortController } from './fetchHelpers';
|
|
9
|
+
import { CancelFn } from '..';
|
|
13
10
|
import { getFetch } from '../getFetch';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
11
|
+
import { httpBatchLink } from '../links/httpBatchLink';
|
|
12
|
+
import { createChain } from '../links/internals/createChain';
|
|
13
|
+
import { transformOperationResult } from '../links/internals/transformOperationResult';
|
|
16
14
|
import {
|
|
17
|
-
CancelFn,
|
|
18
15
|
HTTPHeaders,
|
|
19
|
-
|
|
16
|
+
LinkRuntime,
|
|
20
17
|
OperationContext,
|
|
21
18
|
OperationLink,
|
|
22
19
|
TRPCLink,
|
|
23
|
-
} from '../links/
|
|
24
|
-
import {
|
|
20
|
+
} from '../links/types';
|
|
21
|
+
import { UnsubscribeFn } from '../rx';
|
|
22
|
+
import { inferObservableValue } from '../rx/observable';
|
|
23
|
+
import { share } from '../rx/operators';
|
|
24
|
+
import { Observer } from '../rx/types';
|
|
25
|
+
import { observableToPromise } from '../rx/util/observableToPromise';
|
|
25
26
|
import { TRPCClientError } from '../TRPCClientError';
|
|
27
|
+
import { getAbortController } from './fetchHelpers';
|
|
26
28
|
|
|
27
29
|
type CancellablePromise<T = unknown> = Promise<T> & {
|
|
28
30
|
cancel: CancelFn;
|
|
@@ -39,8 +41,7 @@ let idCounter = 0;
|
|
|
39
41
|
function getRequestId() {
|
|
40
42
|
return ++idCounter;
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
export type CreateTRPCClientOptions<TRouter extends AnyRouter> = {
|
|
44
|
+
interface CreateTRPCClientBaseOptions {
|
|
44
45
|
/**
|
|
45
46
|
* Add ponyfill for fetch
|
|
46
47
|
*/
|
|
@@ -53,25 +54,26 @@ export type CreateTRPCClientOptions<TRouter extends AnyRouter> = {
|
|
|
53
54
|
* headers to be set on outgoing requests / callback that of said headers
|
|
54
55
|
*/
|
|
55
56
|
headers?: HTTPHeaders | (() => HTTPHeaders | Promise<HTTPHeaders>);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** @internal */
|
|
60
|
+
export interface CreateTRPCClientWithURLOptions
|
|
61
|
+
extends CreateTRPCClientBaseOptions {
|
|
56
62
|
/**
|
|
57
|
-
*
|
|
58
|
-
* @link http://localhost:3000/docs/data-transformers
|
|
63
|
+
* HTTP URL of API
|
|
59
64
|
**/
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
links: TRPCLink<TRouter>[];
|
|
73
|
-
}
|
|
74
|
-
);
|
|
65
|
+
url: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** @internal */
|
|
69
|
+
export interface CreateTRPCClientWithLinksOptions<TRouter extends AnyRouter>
|
|
70
|
+
extends CreateTRPCClientBaseOptions {
|
|
71
|
+
/**
|
|
72
|
+
* @link http://localhost:3000/docs/links
|
|
73
|
+
**/
|
|
74
|
+
links: TRPCLink<TRouter>[];
|
|
75
|
+
}
|
|
76
|
+
|
|
75
77
|
type TRPCType = 'subscription' | 'query' | 'mutation';
|
|
76
78
|
export interface TRPCRequestOptions {
|
|
77
79
|
/**
|
|
@@ -79,27 +81,20 @@ export interface TRPCRequestOptions {
|
|
|
79
81
|
*/
|
|
80
82
|
context?: OperationContext;
|
|
81
83
|
}
|
|
84
|
+
|
|
85
|
+
/** @internal */
|
|
86
|
+
export type CreateTRPCClientOptions<TRouter extends AnyRouter> =
|
|
87
|
+
| CreateTRPCClientWithLinksOptions<TRouter>
|
|
88
|
+
| CreateTRPCClientWithURLOptions;
|
|
82
89
|
export class TRPCClient<TRouter extends AnyRouter> {
|
|
83
90
|
private readonly links: OperationLink<TRouter>[];
|
|
84
|
-
public readonly runtime:
|
|
91
|
+
public readonly runtime: LinkRuntime;
|
|
85
92
|
|
|
86
93
|
constructor(opts: CreateTRPCClientOptions<TRouter>) {
|
|
87
|
-
const transformer: DataTransformer = opts.transformer
|
|
88
|
-
? 'input' in opts.transformer
|
|
89
|
-
? {
|
|
90
|
-
serialize: opts.transformer.input.serialize,
|
|
91
|
-
deserialize: opts.transformer.output.deserialize,
|
|
92
|
-
}
|
|
93
|
-
: opts.transformer
|
|
94
|
-
: {
|
|
95
|
-
serialize: (data) => data,
|
|
96
|
-
deserialize: (data) => data,
|
|
97
|
-
};
|
|
98
|
-
|
|
99
94
|
const _fetch = getFetch(opts?.fetch);
|
|
100
95
|
const AC = getAbortController(opts?.AbortController);
|
|
101
96
|
|
|
102
|
-
function getHeadersFn():
|
|
97
|
+
function getHeadersFn(): LinkRuntime['headers'] {
|
|
103
98
|
if (opts.headers) {
|
|
104
99
|
const headers = opts.headers;
|
|
105
100
|
return typeof headers === 'function' ? headers : () => headers;
|
|
@@ -107,7 +102,6 @@ export class TRPCClient<TRouter extends AnyRouter> {
|
|
|
107
102
|
return () => ({});
|
|
108
103
|
}
|
|
109
104
|
this.runtime = {
|
|
110
|
-
transformer,
|
|
111
105
|
AbortController: AC as any,
|
|
112
106
|
fetch: _fetch,
|
|
113
107
|
headers: getHeadersFn(),
|
|
@@ -135,8 +129,8 @@ export class TRPCClient<TRouter extends AnyRouter> {
|
|
|
135
129
|
path: string;
|
|
136
130
|
context?: OperationContext;
|
|
137
131
|
}) {
|
|
138
|
-
const $
|
|
139
|
-
links: this.links as any,
|
|
132
|
+
const chain$ = createChain<TRouter, TInput, TOutput>({
|
|
133
|
+
links: this.links as OperationLink<any, any, any>[],
|
|
140
134
|
op: {
|
|
141
135
|
id: getRequestId(),
|
|
142
136
|
type,
|
|
@@ -145,8 +139,7 @@ export class TRPCClient<TRouter extends AnyRouter> {
|
|
|
145
139
|
context,
|
|
146
140
|
},
|
|
147
141
|
});
|
|
148
|
-
|
|
149
|
-
return $result;
|
|
142
|
+
return chain$.pipe(share());
|
|
150
143
|
}
|
|
151
144
|
private requestAsPromise<TInput = unknown, TOutput = unknown>(opts: {
|
|
152
145
|
type: TRPCType;
|
|
@@ -154,38 +147,29 @@ export class TRPCClient<TRouter extends AnyRouter> {
|
|
|
154
147
|
path: string;
|
|
155
148
|
context?: OperationContext;
|
|
156
149
|
}): CancellablePromise<TOutput> {
|
|
157
|
-
const $
|
|
150
|
+
const req$ = this.$request<TInput, TOutput>(opts);
|
|
151
|
+
type TValue = inferObservableValue<typeof req$>;
|
|
152
|
+
const { promise, abort } = observableToPromise<TValue>(req$);
|
|
158
153
|
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
reject(err);
|
|
177
|
-
$result.done();
|
|
178
|
-
},
|
|
179
|
-
onDone() {
|
|
180
|
-
reject(TRPCClientError.from(new TRPCAbortError()));
|
|
181
|
-
},
|
|
182
|
-
});
|
|
183
|
-
}) as CancellablePromise<TOutput>;
|
|
184
|
-
promise.cancel = () => {
|
|
185
|
-
$result.done();
|
|
186
|
-
};
|
|
154
|
+
const cancellablePromise: CancellablePromise<any> = new Promise<TOutput>(
|
|
155
|
+
(resolve, reject) => {
|
|
156
|
+
promise
|
|
157
|
+
.then((result) => {
|
|
158
|
+
const transformed = transformOperationResult(result);
|
|
159
|
+
if (transformed.ok) {
|
|
160
|
+
resolve(transformed.data as any);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
reject(transformed.error);
|
|
164
|
+
})
|
|
165
|
+
.catch((err) => {
|
|
166
|
+
reject(TRPCClientError.from(err));
|
|
167
|
+
});
|
|
168
|
+
},
|
|
169
|
+
) as any;
|
|
170
|
+
cancellablePromise.cancel = abort;
|
|
187
171
|
|
|
188
|
-
return
|
|
172
|
+
return cancellablePromise;
|
|
189
173
|
}
|
|
190
174
|
public query<
|
|
191
175
|
TQueries extends TRouter['_def']['queries'],
|
|
@@ -233,27 +217,35 @@ export class TRPCClient<TRouter extends AnyRouter> {
|
|
|
233
217
|
path: TPath,
|
|
234
218
|
input: TInput,
|
|
235
219
|
opts: TRPCRequestOptions &
|
|
236
|
-
|
|
220
|
+
Partial<Observer<TRPCResult<TOutput>, TRPCClientError<TRouter>>>,
|
|
237
221
|
): UnsubscribeFn {
|
|
238
|
-
const $
|
|
222
|
+
const observable$ = this.$request<TInput, TOutput>({
|
|
239
223
|
type: 'subscription',
|
|
240
224
|
path,
|
|
241
225
|
input,
|
|
242
226
|
context: opts.context,
|
|
243
227
|
});
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
if (
|
|
247
|
-
|
|
228
|
+
const observer = observable$.subscribe({
|
|
229
|
+
next(result) {
|
|
230
|
+
if ('error' in result.data) {
|
|
231
|
+
const err = TRPCClientError.from(result.data, {
|
|
232
|
+
meta: result.context,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
opts.error?.(err);
|
|
236
|
+
return;
|
|
248
237
|
}
|
|
238
|
+
opts.next?.(result.data.result);
|
|
239
|
+
},
|
|
240
|
+
error(err) {
|
|
241
|
+
opts.error?.(err);
|
|
249
242
|
},
|
|
250
|
-
|
|
251
|
-
opts.
|
|
243
|
+
complete() {
|
|
244
|
+
opts.complete?.();
|
|
252
245
|
},
|
|
253
|
-
onDone: opts.onDone,
|
|
254
246
|
});
|
|
255
247
|
return () => {
|
|
256
|
-
|
|
248
|
+
observer.unsubscribe();
|
|
257
249
|
};
|
|
258
250
|
}
|
|
259
251
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CancelFn, PromiseAndCancel } from '../links/
|
|
1
|
+
import { CancelFn, PromiseAndCancel } from '../links/types';
|
|
2
2
|
|
|
3
3
|
type BatchItem<TKey, TValue> = {
|
|
4
4
|
cancelled: boolean;
|
|
@@ -20,10 +20,7 @@ type BatchLoadFn<TKey, TValue> = (keys: TKey[]) => {
|
|
|
20
20
|
* Less configuration, no caching, and allows you to cancel requests
|
|
21
21
|
* When cancelling a single fetch the whole batch will be cancelled only when _all_ items are cancelled
|
|
22
22
|
*/
|
|
23
|
-
export function dataLoader<TKey, TValue>(
|
|
24
|
-
fetchMany: BatchLoadFn<TKey, TValue>,
|
|
25
|
-
opts?: { maxBatchSize?: number },
|
|
26
|
-
) {
|
|
23
|
+
export function dataLoader<TKey, TValue>(fetchMany: BatchLoadFn<TKey, TValue>) {
|
|
27
24
|
let batch: Batch<TKey, TValue> | null = null;
|
|
28
25
|
let dispatchTimer: NodeJS.Timer | number | null = null;
|
|
29
26
|
|
|
@@ -72,16 +69,7 @@ export function dataLoader<TKey, TValue>(
|
|
|
72
69
|
item.reject = reject;
|
|
73
70
|
item.resolve = resolve;
|
|
74
71
|
thisBatch.items.push(item);
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
typeof opts?.maxBatchSize !== 'undefined' &&
|
|
78
|
-
thisBatch.items.length >= opts.maxBatchSize
|
|
79
|
-
) {
|
|
80
|
-
dispatch();
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
72
|
});
|
|
84
|
-
|
|
85
73
|
if (!dispatchTimer) {
|
|
86
74
|
dispatchTimer = setTimeout(dispatch);
|
|
87
75
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { TRPCResponse } from '@trpc/server/rpc';
|
|
2
2
|
import { TRPCClientError } from '../TRPCClientError';
|
|
3
|
-
import {
|
|
3
|
+
import { LinkRuntime } from '../links/types';
|
|
4
4
|
|
|
5
5
|
export function transformRPCResponse({
|
|
6
6
|
envelope,
|
|
7
7
|
runtime,
|
|
8
8
|
}: {
|
|
9
9
|
envelope: TRPCResponse;
|
|
10
|
-
runtime:
|
|
10
|
+
runtime: LinkRuntime;
|
|
11
11
|
}) {
|
|
12
12
|
if ('error' in envelope) {
|
|
13
13
|
return TRPCClientError.from({
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { waitFor } from '@testing-library/dom';
|
|
2
|
+
import { AnyRouter } from '@trpc/server';
|
|
3
|
+
import { OperationLink } from '..';
|
|
4
|
+
import { observable } from '../rx/observable';
|
|
5
|
+
import { dedupeLink } from './dedupeLink';
|
|
6
|
+
import { createChain } from './internals/createChain';
|
|
7
|
+
|
|
8
|
+
test('dedupeLink', async () => {
|
|
9
|
+
const endingLinkTriggered = jest.fn();
|
|
10
|
+
const timerTriggered = jest.fn();
|
|
11
|
+
const links: OperationLink<AnyRouter, any, any>[] = [
|
|
12
|
+
// "dedupe link"
|
|
13
|
+
dedupeLink()(null as any),
|
|
14
|
+
({ op }) => {
|
|
15
|
+
return observable((subscribe) => {
|
|
16
|
+
endingLinkTriggered();
|
|
17
|
+
const timer = setTimeout(() => {
|
|
18
|
+
timerTriggered();
|
|
19
|
+
subscribe.next({
|
|
20
|
+
data: {
|
|
21
|
+
id: null,
|
|
22
|
+
result: {
|
|
23
|
+
type: 'data',
|
|
24
|
+
data: {
|
|
25
|
+
input: op.input,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
subscribe.complete();
|
|
31
|
+
}, 1);
|
|
32
|
+
return () => clearTimeout(timer);
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
{
|
|
37
|
+
const call1 = createChain<AnyRouter, unknown, unknown>({
|
|
38
|
+
links,
|
|
39
|
+
op: {
|
|
40
|
+
type: 'query',
|
|
41
|
+
id: 1,
|
|
42
|
+
input: 'world',
|
|
43
|
+
path: 'hello',
|
|
44
|
+
context: {},
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const call2 = createChain<AnyRouter, unknown, unknown>({
|
|
49
|
+
links,
|
|
50
|
+
op: {
|
|
51
|
+
type: 'query',
|
|
52
|
+
id: 1,
|
|
53
|
+
input: 'world',
|
|
54
|
+
path: 'hello',
|
|
55
|
+
context: {},
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
const next = jest.fn();
|
|
59
|
+
call1.subscribe({ next });
|
|
60
|
+
call2.subscribe({ next });
|
|
61
|
+
|
|
62
|
+
expect(endingLinkTriggered).toHaveBeenCalledTimes(1);
|
|
63
|
+
await waitFor(() => {
|
|
64
|
+
expect(timerTriggered).toHaveBeenCalledTimes(1);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
expect(next).toHaveBeenCalledTimes(2);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('dedupe - cancel one does not cancel the other', async () => {
|
|
72
|
+
const endingLinkTriggered = jest.fn();
|
|
73
|
+
const timerTriggered = jest.fn();
|
|
74
|
+
const links: OperationLink<AnyRouter, any, any>[] = [
|
|
75
|
+
// "dedupe link"
|
|
76
|
+
dedupeLink()(null as any),
|
|
77
|
+
({ op }) => {
|
|
78
|
+
return observable((subscribe) => {
|
|
79
|
+
endingLinkTriggered();
|
|
80
|
+
const timer = setTimeout(() => {
|
|
81
|
+
timerTriggered();
|
|
82
|
+
subscribe.next({
|
|
83
|
+
data: {
|
|
84
|
+
id: null,
|
|
85
|
+
result: {
|
|
86
|
+
type: 'data',
|
|
87
|
+
data: {
|
|
88
|
+
input: op.input,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
subscribe.complete();
|
|
94
|
+
}, 1);
|
|
95
|
+
return () => clearTimeout(timer);
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
{
|
|
101
|
+
const call1 = createChain<AnyRouter, unknown, unknown>({
|
|
102
|
+
links,
|
|
103
|
+
op: {
|
|
104
|
+
type: 'query',
|
|
105
|
+
id: 1,
|
|
106
|
+
input: 'world',
|
|
107
|
+
path: 'hello',
|
|
108
|
+
context: {},
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const call2 = createChain<AnyRouter, unknown, unknown>({
|
|
113
|
+
links,
|
|
114
|
+
op: {
|
|
115
|
+
type: 'query',
|
|
116
|
+
id: 1,
|
|
117
|
+
input: 'world',
|
|
118
|
+
path: 'hello',
|
|
119
|
+
context: {},
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
const next = jest.fn();
|
|
123
|
+
const call1$ = call1.subscribe({ next });
|
|
124
|
+
call2.subscribe({ next });
|
|
125
|
+
call1$.unsubscribe();
|
|
126
|
+
|
|
127
|
+
expect(endingLinkTriggered).toHaveBeenCalledTimes(1);
|
|
128
|
+
await waitFor(() => {
|
|
129
|
+
expect(timerTriggered).toHaveBeenCalledTimes(1);
|
|
130
|
+
|
|
131
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { AnyRouter } from '@trpc/server';
|
|
2
|
+
import { observable } from '../rx/observable';
|
|
3
|
+
import { share } from '../rx/operators';
|
|
4
|
+
import { Observable } from '../rx/types';
|
|
5
|
+
import { TRPCLink } from './types';
|
|
6
|
+
|
|
7
|
+
export function dedupeLink<
|
|
8
|
+
TRouter extends AnyRouter = AnyRouter,
|
|
9
|
+
>(): TRPCLink<TRouter> {
|
|
10
|
+
// initialized config
|
|
11
|
+
return () => {
|
|
12
|
+
// initialized in app
|
|
13
|
+
const pending: Record<string, Observable<any, any>> = {};
|
|
14
|
+
return ({ op, next }) => {
|
|
15
|
+
// initialized for request
|
|
16
|
+
|
|
17
|
+
if (op.type !== 'query') {
|
|
18
|
+
// pass through
|
|
19
|
+
return next(op);
|
|
20
|
+
}
|
|
21
|
+
const key = JSON.stringify([op.path, op.input]);
|
|
22
|
+
if (pending[key]) {
|
|
23
|
+
// console.log('hooking into pending', { op });
|
|
24
|
+
return observable((observer) => pending[key].subscribe(observer));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const shared$ = observable((observer) => {
|
|
28
|
+
function reset() {
|
|
29
|
+
delete pending[key];
|
|
30
|
+
}
|
|
31
|
+
const next$ = next(op).subscribe({
|
|
32
|
+
next(v) {
|
|
33
|
+
observer.next(v);
|
|
34
|
+
},
|
|
35
|
+
error(e) {
|
|
36
|
+
reset();
|
|
37
|
+
observer.error(e);
|
|
38
|
+
},
|
|
39
|
+
complete() {
|
|
40
|
+
reset();
|
|
41
|
+
observer.complete();
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
return () => {
|
|
45
|
+
reset();
|
|
46
|
+
next$.unsubscribe();
|
|
47
|
+
};
|
|
48
|
+
}).pipe(share());
|
|
49
|
+
pending[key] = shared$;
|
|
50
|
+
return shared$;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
}
|