@trpc/server 11.0.0-rc.560 → 11.0.0-rc.563
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/adapters/ws.d.ts.map +1 -1
- package/dist/bundle-analysis.json +70 -71
- package/dist/observable/index.d.ts +1 -1
- package/dist/observable/index.d.ts.map +1 -1
- package/dist/observable/index.js +1 -0
- package/dist/observable/index.mjs +1 -1
- package/dist/observable/observable.d.ts +1 -0
- package/dist/observable/observable.d.ts.map +1 -1
- package/dist/observable/observable.js +1 -1
- package/dist/observable/observable.mjs +1 -1
- package/dist/unstable-core-do-not-import/stream/jsonl.d.ts +3 -0
- package/dist/unstable-core-do-not-import/stream/jsonl.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/sse.d.ts +31 -12
- package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/sse.js +127 -46
- package/dist/unstable-core-do-not-import/stream/sse.mjs +127 -46
- package/package.json +2 -2
- package/src/adapters/ws.ts +1 -2
- package/src/observable/index.ts +1 -1
- package/src/observable/observable.ts +1 -0
- package/src/unstable-core-do-not-import/stream/jsonl.ts +3 -0
- package/src/unstable-core-do-not-import/stream/sse.ts +187 -73
|
@@ -105,60 +105,141 @@ const SERIALIZED_ERROR_EVENT = 'serialized-error';
|
|
|
105
105
|
/**
|
|
106
106
|
* @see https://html.spec.whatwg.org/multipage/server-sent-events.html
|
|
107
107
|
*/ function sseStreamConsumer(opts) {
|
|
108
|
-
const { deserialize =(v)=>v } = opts;
|
|
109
|
-
const
|
|
108
|
+
const { deserialize =(v)=>v , shouldRecreateOnError } = opts;
|
|
109
|
+
const signal = opts.signal;
|
|
110
|
+
let eventSource = null;
|
|
111
|
+
let lock = null;
|
|
110
112
|
const stream = createReadableStream.createReadableStream();
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
function createEventSource(...args) {
|
|
114
|
+
const es = new EventSource(...args);
|
|
115
|
+
if (signal.aborted) {
|
|
116
|
+
es.close();
|
|
117
|
+
} else {
|
|
118
|
+
signal.addEventListener('abort', ()=>es.close());
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Dispatch an event to the stream controller
|
|
122
|
+
*
|
|
123
|
+
* Will be a no-op if the event source has been replaced
|
|
124
|
+
*/ const dispatch = (fn)=>{
|
|
125
|
+
utils.run(async ()=>{
|
|
126
|
+
while(lock){
|
|
127
|
+
await lock;
|
|
128
|
+
}
|
|
129
|
+
if (es === eventSource) {
|
|
130
|
+
await fn(stream.controller);
|
|
131
|
+
}
|
|
132
|
+
}).catch((error)=>{
|
|
133
|
+
stream.controller.error(error);
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
const pauseDispatch = async (fn)=>{
|
|
137
|
+
while(lock){
|
|
138
|
+
await lock;
|
|
139
|
+
}
|
|
140
|
+
if (es !== eventSource) {
|
|
119
141
|
return;
|
|
120
142
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
143
|
+
const deferred = createDeferred.createDeferred();
|
|
144
|
+
lock = deferred.promise;
|
|
145
|
+
try {
|
|
146
|
+
await fn();
|
|
147
|
+
} finally{
|
|
148
|
+
lock = null;
|
|
149
|
+
deferred.resolve();
|
|
127
150
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
151
|
+
};
|
|
152
|
+
es.addEventListener('open', ()=>{
|
|
153
|
+
dispatch((controller)=>{
|
|
154
|
+
controller.enqueue({
|
|
155
|
+
type: 'opened',
|
|
156
|
+
eventSource: es
|
|
157
|
+
});
|
|
131
158
|
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
});
|
|
160
|
+
es.addEventListener(SERIALIZED_ERROR_EVENT, (msg)=>{
|
|
161
|
+
dispatch(async ()=>{
|
|
162
|
+
if (shouldRecreateOnError) {
|
|
163
|
+
await pauseDispatch(async ()=>{
|
|
164
|
+
const recreate = await shouldRecreateOnError({
|
|
165
|
+
type: SERIALIZED_ERROR_EVENT,
|
|
166
|
+
error: deserialize(JSON.parse(msg.data))
|
|
167
|
+
});
|
|
168
|
+
if (recreate) {
|
|
169
|
+
await recreateEventSource();
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
dispatch((controller)=>{
|
|
174
|
+
controller.enqueue({
|
|
175
|
+
type: 'error',
|
|
176
|
+
error: deserialize(JSON.parse(msg.data)),
|
|
177
|
+
eventSource: es
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
es.addEventListener('error', (event)=>{
|
|
183
|
+
dispatch(async ()=>{
|
|
184
|
+
if (shouldRecreateOnError) {
|
|
185
|
+
await pauseDispatch(async ()=>{
|
|
186
|
+
const recreate = await shouldRecreateOnError({
|
|
187
|
+
type: 'event',
|
|
188
|
+
event
|
|
189
|
+
});
|
|
190
|
+
if (recreate) {
|
|
191
|
+
await recreateEventSource();
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
dispatch((controller)=>{
|
|
196
|
+
if (es.readyState === EventSource.CLOSED) {
|
|
197
|
+
controller.error(event);
|
|
198
|
+
} else {
|
|
199
|
+
controller.enqueue({
|
|
200
|
+
type: 'connecting',
|
|
201
|
+
eventSource: es
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
es.addEventListener('message', (msg)=>{
|
|
208
|
+
dispatch((controller)=>{
|
|
209
|
+
const chunk = deserialize(JSON.parse(msg.data));
|
|
210
|
+
const def = {
|
|
211
|
+
data: chunk
|
|
212
|
+
};
|
|
213
|
+
if (msg.lastEventId) {
|
|
214
|
+
def.id = msg.lastEventId;
|
|
215
|
+
}
|
|
216
|
+
controller.enqueue({
|
|
217
|
+
type: 'data',
|
|
218
|
+
data: def,
|
|
219
|
+
eventSource: es
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
return es;
|
|
224
|
+
}
|
|
225
|
+
async function recreateEventSource() {
|
|
226
|
+
eventSource?.close();
|
|
227
|
+
const [url, init] = await Promise.all([
|
|
228
|
+
opts.url(),
|
|
229
|
+
opts.init()
|
|
230
|
+
]);
|
|
231
|
+
eventSource = createEventSource(url, init);
|
|
232
|
+
stream.controller.enqueue({
|
|
233
|
+
type: 'connecting',
|
|
234
|
+
eventSource
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
recreateEventSource().catch(()=>{
|
|
238
|
+
// prevent unhandled promise rejection
|
|
157
239
|
});
|
|
158
|
-
const readable = stream.readable.pipeThrough(transform);
|
|
159
240
|
return {
|
|
160
241
|
[Symbol.asyncIterator] () {
|
|
161
|
-
const reader = readable.getReader();
|
|
242
|
+
const reader = stream.readable.getReader();
|
|
162
243
|
const iterator = {
|
|
163
244
|
async next () {
|
|
164
245
|
const value = await reader.read();
|
|
@@ -103,60 +103,141 @@ const SERIALIZED_ERROR_EVENT = 'serialized-error';
|
|
|
103
103
|
/**
|
|
104
104
|
* @see https://html.spec.whatwg.org/multipage/server-sent-events.html
|
|
105
105
|
*/ function sseStreamConsumer(opts) {
|
|
106
|
-
const { deserialize =(v)=>v } = opts;
|
|
107
|
-
const
|
|
106
|
+
const { deserialize =(v)=>v , shouldRecreateOnError } = opts;
|
|
107
|
+
const signal = opts.signal;
|
|
108
|
+
let eventSource = null;
|
|
109
|
+
let lock = null;
|
|
108
110
|
const stream = createReadableStream();
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
111
|
+
function createEventSource(...args) {
|
|
112
|
+
const es = new EventSource(...args);
|
|
113
|
+
if (signal.aborted) {
|
|
114
|
+
es.close();
|
|
115
|
+
} else {
|
|
116
|
+
signal.addEventListener('abort', ()=>es.close());
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Dispatch an event to the stream controller
|
|
120
|
+
*
|
|
121
|
+
* Will be a no-op if the event source has been replaced
|
|
122
|
+
*/ const dispatch = (fn)=>{
|
|
123
|
+
run(async ()=>{
|
|
124
|
+
while(lock){
|
|
125
|
+
await lock;
|
|
126
|
+
}
|
|
127
|
+
if (es === eventSource) {
|
|
128
|
+
await fn(stream.controller);
|
|
129
|
+
}
|
|
130
|
+
}).catch((error)=>{
|
|
131
|
+
stream.controller.error(error);
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
const pauseDispatch = async (fn)=>{
|
|
135
|
+
while(lock){
|
|
136
|
+
await lock;
|
|
137
|
+
}
|
|
138
|
+
if (es !== eventSource) {
|
|
117
139
|
return;
|
|
118
140
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
141
|
+
const deferred = createDeferred();
|
|
142
|
+
lock = deferred.promise;
|
|
143
|
+
try {
|
|
144
|
+
await fn();
|
|
145
|
+
} finally{
|
|
146
|
+
lock = null;
|
|
147
|
+
deferred.resolve();
|
|
125
148
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
149
|
+
};
|
|
150
|
+
es.addEventListener('open', ()=>{
|
|
151
|
+
dispatch((controller)=>{
|
|
152
|
+
controller.enqueue({
|
|
153
|
+
type: 'opened',
|
|
154
|
+
eventSource: es
|
|
155
|
+
});
|
|
129
156
|
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
});
|
|
158
|
+
es.addEventListener(SERIALIZED_ERROR_EVENT, (msg)=>{
|
|
159
|
+
dispatch(async ()=>{
|
|
160
|
+
if (shouldRecreateOnError) {
|
|
161
|
+
await pauseDispatch(async ()=>{
|
|
162
|
+
const recreate = await shouldRecreateOnError({
|
|
163
|
+
type: SERIALIZED_ERROR_EVENT,
|
|
164
|
+
error: deserialize(JSON.parse(msg.data))
|
|
165
|
+
});
|
|
166
|
+
if (recreate) {
|
|
167
|
+
await recreateEventSource();
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
dispatch((controller)=>{
|
|
172
|
+
controller.enqueue({
|
|
173
|
+
type: 'error',
|
|
174
|
+
error: deserialize(JSON.parse(msg.data)),
|
|
175
|
+
eventSource: es
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
es.addEventListener('error', (event)=>{
|
|
181
|
+
dispatch(async ()=>{
|
|
182
|
+
if (shouldRecreateOnError) {
|
|
183
|
+
await pauseDispatch(async ()=>{
|
|
184
|
+
const recreate = await shouldRecreateOnError({
|
|
185
|
+
type: 'event',
|
|
186
|
+
event
|
|
187
|
+
});
|
|
188
|
+
if (recreate) {
|
|
189
|
+
await recreateEventSource();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
dispatch((controller)=>{
|
|
194
|
+
if (es.readyState === EventSource.CLOSED) {
|
|
195
|
+
controller.error(event);
|
|
196
|
+
} else {
|
|
197
|
+
controller.enqueue({
|
|
198
|
+
type: 'connecting',
|
|
199
|
+
eventSource: es
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
es.addEventListener('message', (msg)=>{
|
|
206
|
+
dispatch((controller)=>{
|
|
207
|
+
const chunk = deserialize(JSON.parse(msg.data));
|
|
208
|
+
const def = {
|
|
209
|
+
data: chunk
|
|
210
|
+
};
|
|
211
|
+
if (msg.lastEventId) {
|
|
212
|
+
def.id = msg.lastEventId;
|
|
213
|
+
}
|
|
214
|
+
controller.enqueue({
|
|
215
|
+
type: 'data',
|
|
216
|
+
data: def,
|
|
217
|
+
eventSource: es
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
return es;
|
|
222
|
+
}
|
|
223
|
+
async function recreateEventSource() {
|
|
224
|
+
eventSource?.close();
|
|
225
|
+
const [url, init] = await Promise.all([
|
|
226
|
+
opts.url(),
|
|
227
|
+
opts.init()
|
|
228
|
+
]);
|
|
229
|
+
eventSource = createEventSource(url, init);
|
|
230
|
+
stream.controller.enqueue({
|
|
231
|
+
type: 'connecting',
|
|
232
|
+
eventSource
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
recreateEventSource().catch(()=>{
|
|
236
|
+
// prevent unhandled promise rejection
|
|
155
237
|
});
|
|
156
|
-
const readable = stream.readable.pipeThrough(transform);
|
|
157
238
|
return {
|
|
158
239
|
[Symbol.asyncIterator] () {
|
|
159
|
-
const reader = readable.getReader();
|
|
240
|
+
const reader = stream.readable.getReader();
|
|
160
241
|
const iterator = {
|
|
161
242
|
async next () {
|
|
162
243
|
const value = await reader.read();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trpc/server",
|
|
3
|
-
"version": "11.0.0-rc.
|
|
3
|
+
"version": "11.0.0-rc.563+e5ae464b2",
|
|
4
4
|
"description": "The tRPC server library",
|
|
5
5
|
"author": "KATT",
|
|
6
6
|
"license": "MIT",
|
|
@@ -149,5 +149,5 @@
|
|
|
149
149
|
"funding": [
|
|
150
150
|
"https://trpc.io/sponsor"
|
|
151
151
|
],
|
|
152
|
-
"gitHead": "
|
|
152
|
+
"gitHead": "e5ae464b2428b591d816ee4e01725c86b232d620"
|
|
153
153
|
}
|
package/src/adapters/ws.ts
CHANGED
|
@@ -24,8 +24,7 @@ import type {
|
|
|
24
24
|
TRPCResultMessage,
|
|
25
25
|
} from '../@trpc/server/rpc';
|
|
26
26
|
import { parseConnectionParamsFromUnknown } from '../http';
|
|
27
|
-
import { isObservable } from '../observable';
|
|
28
|
-
import { observableToAsyncIterable } from '../observable/observable';
|
|
27
|
+
import { isObservable, observableToAsyncIterable } from '../observable';
|
|
29
28
|
// eslint-disable-next-line no-restricted-imports
|
|
30
29
|
import {
|
|
31
30
|
isAsyncIterable,
|
package/src/observable/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type { inferObservableValue } from './observable';
|
|
2
|
-
export { isObservable, observable, observableToPromise } from './observable';
|
|
2
|
+
export { isObservable, observable, observableToAsyncIterable, observableToPromise } from './observable';
|
|
3
3
|
export { map, share, tap } from './operators';
|
|
4
4
|
export type {
|
|
5
5
|
Observable,
|
|
@@ -436,6 +436,9 @@ export async function jsonlStreamConsumer<THead>(opts: {
|
|
|
436
436
|
deserialize?: Deserialize;
|
|
437
437
|
onError?: ConsumerOnError;
|
|
438
438
|
formatError?: (opts: { error: unknown }) => Error;
|
|
439
|
+
/**
|
|
440
|
+
* This `AbortController` will be triggered when there are no more listeners to the stream.
|
|
441
|
+
*/
|
|
439
442
|
abortController: AbortController | null;
|
|
440
443
|
}) {
|
|
441
444
|
const { deserialize = (v) => v } = opts;
|