@trpc/client 11.0.0-rc.413 → 11.0.0-rc.419
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/bundle-analysis.json +55 -40
- package/dist/createTRPCClient.d.ts.map +1 -1
- package/dist/createTRPCClient.js +9 -9
- package/dist/createTRPCClient.mjs +10 -10
- package/dist/index.js +2 -0
- package/dist/index.mjs +1 -0
- package/dist/internals/TRPCUntypedClient.d.ts +3 -1
- package/dist/internals/TRPCUntypedClient.d.ts.map +1 -1
- package/dist/internals/TRPCUntypedClient.js +3 -1
- package/dist/internals/TRPCUntypedClient.mjs +3 -1
- package/dist/internals/dataLoader.d.ts.map +1 -1
- package/dist/links/httpBatchLink.d.ts.map +1 -1
- package/dist/links/httpBatchLink.js +3 -2
- package/dist/links/httpBatchLink.mjs +3 -2
- package/dist/links/httpBatchStreamLink.d.ts.map +1 -1
- package/dist/links/httpBatchStreamLink.js +5 -6
- package/dist/links/httpBatchStreamLink.mjs +5 -6
- package/dist/links/httpLink.d.ts +2 -2
- package/dist/links/httpLink.d.ts.map +1 -1
- package/dist/links/httpLink.js +3 -0
- package/dist/links/httpLink.mjs +3 -0
- package/dist/links/httpSubscriptionLink.d.ts +19 -0
- package/dist/links/httpSubscriptionLink.d.ts.map +1 -0
- package/dist/links/httpSubscriptionLink.js +87 -0
- package/dist/links/httpSubscriptionLink.mjs +85 -0
- package/dist/links/internals/contentTypes.d.ts +3 -3
- package/dist/links/internals/contentTypes.d.ts.map +1 -1
- package/dist/links/internals/httpUtils.d.ts +4 -4
- package/dist/links/internals/httpUtils.d.ts.map +1 -1
- package/dist/links/internals/httpUtils.js +6 -7
- package/dist/links/internals/httpUtils.mjs +6 -7
- package/dist/links/loggerLink.d.ts +0 -1
- package/dist/links/loggerLink.d.ts.map +1 -1
- package/dist/links/wsLink.d.ts +4 -4
- package/dist/links/wsLink.d.ts.map +1 -1
- package/dist/links.d.ts +1 -0
- package/dist/links.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/createTRPCClient.ts +11 -8
- package/src/internals/TRPCUntypedClient.ts +4 -2
- package/src/links/httpBatchLink.ts +8 -5
- package/src/links/httpBatchStreamLink.ts +10 -7
- package/src/links/httpLink.ts +8 -2
- package/src/links/httpSubscriptionLink.ts +121 -0
- package/src/links/internals/httpUtils.ts +10 -11
- package/src/links.ts +1 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { observable } from '@trpc/server/observable';
|
|
2
|
+
import type {
|
|
3
|
+
AnyClientTypes,
|
|
4
|
+
inferClientTypes,
|
|
5
|
+
InferrableClientTypes,
|
|
6
|
+
MaybePromise,
|
|
7
|
+
SSEvent,
|
|
8
|
+
} from '@trpc/server/unstable-core-do-not-import';
|
|
9
|
+
import {
|
|
10
|
+
run,
|
|
11
|
+
sseStreamConsumer,
|
|
12
|
+
} from '@trpc/server/unstable-core-do-not-import';
|
|
13
|
+
import { TRPCClientError } from '../TRPCClientError';
|
|
14
|
+
import { getTransformer, type TransformerOptions } from '../unstable-internals';
|
|
15
|
+
import { getUrl } from './internals/httpUtils';
|
|
16
|
+
import type { TRPCLink } from './types';
|
|
17
|
+
|
|
18
|
+
type HTTPSubscriptionLinkOptions<TRoot extends AnyClientTypes> = {
|
|
19
|
+
/**
|
|
20
|
+
* The URL to connect to (can be a function that returns a URL)
|
|
21
|
+
*/
|
|
22
|
+
url: string | (() => MaybePromise<string>);
|
|
23
|
+
/**
|
|
24
|
+
* EventSource options
|
|
25
|
+
*/
|
|
26
|
+
eventSourceOptions?: EventSourceInit;
|
|
27
|
+
} & TransformerOptions<TRoot>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the result of a value or function that returns a value
|
|
31
|
+
*/
|
|
32
|
+
const resultOf = <T>(value: T | (() => T)): T => {
|
|
33
|
+
return typeof value === 'function' ? (value as () => T)() : value;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @see https://trpc.io/docs/client/links/httpSubscriptionLink
|
|
38
|
+
*/
|
|
39
|
+
export function unstable_httpSubscriptionLink<
|
|
40
|
+
TInferrable extends InferrableClientTypes,
|
|
41
|
+
>(
|
|
42
|
+
opts: HTTPSubscriptionLinkOptions<inferClientTypes<TInferrable>>,
|
|
43
|
+
): TRPCLink<TInferrable> {
|
|
44
|
+
const transformer = getTransformer(opts.transformer);
|
|
45
|
+
return () => {
|
|
46
|
+
return ({ op }) => {
|
|
47
|
+
return observable((observer) => {
|
|
48
|
+
const { type, path, input } = op;
|
|
49
|
+
/* istanbul ignore if -- @preserve */
|
|
50
|
+
if (type !== 'subscription') {
|
|
51
|
+
throw new Error('httpSubscriptionLink only supports subscriptions');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let eventSource: EventSource | null = null;
|
|
55
|
+
let unsubscribed = false;
|
|
56
|
+
|
|
57
|
+
run(async () => {
|
|
58
|
+
const url = getUrl({
|
|
59
|
+
transformer,
|
|
60
|
+
url: await resultOf(opts.url),
|
|
61
|
+
input,
|
|
62
|
+
path,
|
|
63
|
+
type,
|
|
64
|
+
AbortController: null,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
/* istanbul ignore if -- @preserve */
|
|
68
|
+
if (unsubscribed) {
|
|
69
|
+
// already unsubscribed - rare race condition
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
eventSource = new EventSource(url, opts.eventSourceOptions);
|
|
73
|
+
const onStarted = () => {
|
|
74
|
+
observer.next({
|
|
75
|
+
result: {
|
|
76
|
+
type: 'started',
|
|
77
|
+
},
|
|
78
|
+
context: {
|
|
79
|
+
eventSource,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
84
|
+
eventSource!.removeEventListener('open', onStarted);
|
|
85
|
+
};
|
|
86
|
+
// console.log('starting', new Date());
|
|
87
|
+
eventSource.addEventListener('open', onStarted);
|
|
88
|
+
const iterable = sseStreamConsumer<SSEvent>({
|
|
89
|
+
from: eventSource,
|
|
90
|
+
deserialize: transformer.input.deserialize,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
for await (const chunk of iterable) {
|
|
94
|
+
// if the `sse({})`-helper is used, we always have an `id` field
|
|
95
|
+
const data = 'id' in chunk ? chunk : chunk.data;
|
|
96
|
+
observer.next({
|
|
97
|
+
result: {
|
|
98
|
+
data,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
observer.next({
|
|
104
|
+
result: {
|
|
105
|
+
type: 'stopped',
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
observer.complete();
|
|
109
|
+
}).catch((error) => {
|
|
110
|
+
observer.error(TRPCClientError.from(error));
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return () => {
|
|
114
|
+
observer.complete();
|
|
115
|
+
eventSource?.close();
|
|
116
|
+
unsubscribed = true;
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
2
|
+
AnyClientTypes,
|
|
3
3
|
CombinedDataTransformer,
|
|
4
4
|
ProcedureType,
|
|
5
|
+
TRPCAcceptHeader,
|
|
5
6
|
TRPCResponse,
|
|
6
7
|
} from '@trpc/server/unstable-core-do-not-import';
|
|
7
8
|
import { getFetch } from '../../getFetch';
|
|
@@ -22,7 +23,7 @@ import type { HTTPHeaders, PromiseAndCancel } from '../types';
|
|
|
22
23
|
* @internal
|
|
23
24
|
*/
|
|
24
25
|
export type HTTPLinkBaseOptions<
|
|
25
|
-
TRoot extends Pick<
|
|
26
|
+
TRoot extends Pick<AnyClientTypes, 'transformer'>,
|
|
26
27
|
> = {
|
|
27
28
|
url: string | URL;
|
|
28
29
|
/**
|
|
@@ -50,10 +51,10 @@ export interface ResolvedHTTPLinkOptions {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
export function resolveHTTPLinkOptions(
|
|
53
|
-
opts: HTTPLinkBaseOptions<
|
|
54
|
+
opts: HTTPLinkBaseOptions<AnyClientTypes>,
|
|
54
55
|
): ResolvedHTTPLinkOptions {
|
|
55
56
|
return {
|
|
56
|
-
url: opts.url.toString()
|
|
57
|
+
url: opts.url.toString(),
|
|
57
58
|
fetch: opts.fetch,
|
|
58
59
|
AbortController: getAbortController(opts.AbortController),
|
|
59
60
|
transformer: getTransformer(opts.transformer),
|
|
@@ -74,6 +75,7 @@ function arrayToDict(array: unknown[]) {
|
|
|
74
75
|
const METHOD = {
|
|
75
76
|
query: 'GET',
|
|
76
77
|
mutation: 'POST',
|
|
78
|
+
subscription: 'PATCH',
|
|
77
79
|
} as const;
|
|
78
80
|
|
|
79
81
|
export interface HTTPResult {
|
|
@@ -106,19 +108,20 @@ type GetUrl = (opts: HTTPBaseRequestOptions) => string;
|
|
|
106
108
|
type GetBody = (opts: HTTPBaseRequestOptions) => RequestInitEsque['body'];
|
|
107
109
|
|
|
108
110
|
export type ContentOptions = {
|
|
109
|
-
trpcAcceptHeader?:
|
|
111
|
+
trpcAcceptHeader?: TRPCAcceptHeader;
|
|
110
112
|
contentTypeHeader?: string;
|
|
111
113
|
getUrl: GetUrl;
|
|
112
114
|
getBody: GetBody;
|
|
113
115
|
};
|
|
114
116
|
|
|
115
117
|
export const getUrl: GetUrl = (opts) => {
|
|
116
|
-
|
|
118
|
+
const base = opts.url.replace(/\/$/, ''); // Remove any trailing slashes
|
|
119
|
+
let url = base + '/' + opts.path;
|
|
117
120
|
const queryParts: string[] = [];
|
|
118
121
|
if ('inputs' in opts) {
|
|
119
122
|
queryParts.push('batch=1');
|
|
120
123
|
}
|
|
121
|
-
if (opts.type === 'query') {
|
|
124
|
+
if (opts.type === 'query' || opts.type === 'subscription') {
|
|
122
125
|
const input = getInput(opts);
|
|
123
126
|
if (input !== undefined && opts.methodOverride !== 'POST') {
|
|
124
127
|
queryParts.push(`input=${encodeURIComponent(JSON.stringify(input))}`);
|
|
@@ -172,10 +175,6 @@ export async function fetchHTTPResponse(
|
|
|
172
175
|
}
|
|
173
176
|
return heads;
|
|
174
177
|
})();
|
|
175
|
-
/* istanbul ignore if -- @preserve */
|
|
176
|
-
if (type === 'subscription') {
|
|
177
|
-
throw new Error('Subscriptions should use wsLink');
|
|
178
|
-
}
|
|
179
178
|
const headers = {
|
|
180
179
|
...(opts.contentTypeHeader
|
|
181
180
|
? { 'content-type': opts.contentTypeHeader }
|
package/src/links.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './links/httpLink';
|
|
|
7
7
|
export * from './links/loggerLink';
|
|
8
8
|
export * from './links/splitLink';
|
|
9
9
|
export * from './links/wsLink';
|
|
10
|
+
export * from './links/httpSubscriptionLink';
|
|
10
11
|
|
|
11
12
|
// These are not public (yet) as we get this functionality from tanstack query
|
|
12
13
|
// export * from './links/internals/retryLink';
|