@trpc/server 11.0.0-alpha-tmp-app-router-example.388 → 11.0.0-alpha-tmp-issues-5851-take-two.451

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.
Files changed (139) hide show
  1. package/dist/@trpc/server/http.d.ts +1 -2
  2. package/dist/@trpc/server/http.d.ts.map +1 -1
  3. package/dist/@trpc/server/index.d.ts +1 -1
  4. package/dist/@trpc/server/index.d.ts.map +1 -1
  5. package/dist/@trpc/server/rpc.d.ts +1 -1
  6. package/dist/@trpc/server/rpc.d.ts.map +1 -1
  7. package/dist/adapters/aws-lambda/getPlanner.d.ts.map +1 -1
  8. package/dist/adapters/aws-lambda/getPlanner.js +19 -2
  9. package/dist/adapters/aws-lambda/getPlanner.mjs +19 -2
  10. package/dist/adapters/next-app-dir/nextAppDirCaller.d.ts.map +1 -1
  11. package/dist/adapters/next-app-dir/nextAppDirCaller.js +1 -1
  12. package/dist/adapters/next-app-dir/nextAppDirCaller.mjs +1 -1
  13. package/dist/adapters/next-app-dir/redirect.d.ts.map +1 -1
  14. package/dist/adapters/next.js +1 -1
  15. package/dist/adapters/next.mjs +1 -1
  16. package/dist/adapters/node-http/incomingMessageToRequest.d.ts +0 -1
  17. package/dist/adapters/node-http/incomingMessageToRequest.d.ts.map +1 -1
  18. package/dist/adapters/node-http/incomingMessageToRequest.js +3 -1
  19. package/dist/adapters/node-http/incomingMessageToRequest.mjs +3 -1
  20. package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts.map +1 -1
  21. package/dist/adapters/node-http/nodeHTTPRequestHandler.js +30 -7
  22. package/dist/adapters/node-http/nodeHTTPRequestHandler.mjs +30 -7
  23. package/dist/adapters/node-http/types.d.ts +0 -1
  24. package/dist/adapters/node-http/types.d.ts.map +1 -1
  25. package/dist/adapters/standalone.d.ts +0 -1
  26. package/dist/adapters/standalone.d.ts.map +1 -1
  27. package/dist/adapters/ws.d.ts +3 -4
  28. package/dist/adapters/ws.d.ts.map +1 -1
  29. package/dist/adapters/ws.js +172 -114
  30. package/dist/adapters/ws.mjs +172 -114
  31. package/dist/bundle-analysis.json +235 -154
  32. package/dist/http.js +3 -0
  33. package/dist/http.mjs +1 -0
  34. package/dist/index.js +7 -5
  35. package/dist/index.mjs +3 -2
  36. package/dist/observable/observable.d.ts +1 -0
  37. package/dist/observable/observable.d.ts.map +1 -1
  38. package/dist/observable/observable.js +55 -0
  39. package/dist/observable/observable.mjs +55 -1
  40. package/dist/unstable-core-do-not-import/createProxy.d.ts +3 -3
  41. package/dist/unstable-core-do-not-import/createProxy.d.ts.map +1 -1
  42. package/dist/unstable-core-do-not-import/createProxy.js +15 -6
  43. package/dist/unstable-core-do-not-import/createProxy.mjs +15 -6
  44. package/dist/unstable-core-do-not-import/http/contentType.d.ts +7 -4
  45. package/dist/unstable-core-do-not-import/http/contentType.d.ts.map +1 -1
  46. package/dist/unstable-core-do-not-import/http/contentType.js +60 -17
  47. package/dist/unstable-core-do-not-import/http/contentType.mjs +61 -18
  48. package/dist/unstable-core-do-not-import/http/formDataToObject.d.ts.map +1 -0
  49. package/dist/unstable-core-do-not-import/http/formDataToObject.js +40 -0
  50. package/dist/unstable-core-do-not-import/http/formDataToObject.mjs +38 -0
  51. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.d.ts.map +1 -1
  52. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.js +4 -4
  53. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.mjs +4 -4
  54. package/dist/unstable-core-do-not-import/http/parseConnectionParams.d.ts +4 -0
  55. package/dist/unstable-core-do-not-import/http/parseConnectionParams.d.ts.map +1 -0
  56. package/dist/unstable-core-do-not-import/http/parseConnectionParams.js +42 -0
  57. package/dist/unstable-core-do-not-import/http/parseConnectionParams.mjs +39 -0
  58. package/dist/unstable-core-do-not-import/http/resolveResponse.d.ts.map +1 -1
  59. package/dist/unstable-core-do-not-import/http/resolveResponse.js +302 -149
  60. package/dist/unstable-core-do-not-import/http/resolveResponse.mjs +301 -148
  61. package/dist/unstable-core-do-not-import/http/types.d.ts +26 -2
  62. package/dist/unstable-core-do-not-import/http/types.d.ts.map +1 -1
  63. package/dist/unstable-core-do-not-import/initTRPC.d.ts +12 -12
  64. package/dist/unstable-core-do-not-import/initTRPC.d.ts.map +1 -1
  65. package/dist/unstable-core-do-not-import/middleware.d.ts +3 -3
  66. package/dist/unstable-core-do-not-import/middleware.d.ts.map +1 -1
  67. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts +3 -1
  68. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts.map +1 -1
  69. package/dist/unstable-core-do-not-import/rootConfig.d.ts +12 -0
  70. package/dist/unstable-core-do-not-import/rootConfig.d.ts.map +1 -1
  71. package/dist/unstable-core-do-not-import/router.d.ts +2 -2
  72. package/dist/unstable-core-do-not-import/router.d.ts.map +1 -1
  73. package/dist/unstable-core-do-not-import/router.js +7 -2
  74. package/dist/unstable-core-do-not-import/router.mjs +7 -2
  75. package/dist/unstable-core-do-not-import/rpc/envelopes.d.ts +7 -0
  76. package/dist/unstable-core-do-not-import/rpc/envelopes.d.ts.map +1 -1
  77. package/dist/unstable-core-do-not-import/rpc/index.d.ts +1 -1
  78. package/dist/unstable-core-do-not-import/rpc/index.d.ts.map +1 -1
  79. package/dist/unstable-core-do-not-import/stream/{stream.d.ts → jsonl.d.ts} +12 -8
  80. package/dist/unstable-core-do-not-import/stream/jsonl.d.ts.map +1 -0
  81. package/dist/unstable-core-do-not-import/stream/{stream.js → jsonl.js} +158 -119
  82. package/dist/unstable-core-do-not-import/stream/{stream.mjs → jsonl.mjs} +157 -118
  83. package/dist/unstable-core-do-not-import/stream/sse.d.ts +86 -0
  84. package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -0
  85. package/dist/unstable-core-do-not-import/stream/sse.js +178 -0
  86. package/dist/unstable-core-do-not-import/stream/sse.mjs +172 -0
  87. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts +18 -0
  88. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts.map +1 -0
  89. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.js +46 -0
  90. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.mjs +43 -0
  91. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts +10 -0
  92. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts.map +1 -0
  93. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.js +31 -0
  94. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.mjs +29 -0
  95. package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts +7 -0
  96. package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts.map +1 -0
  97. package/dist/unstable-core-do-not-import/transformer.d.ts +5 -5
  98. package/dist/unstable-core-do-not-import/utils.d.ts +4 -0
  99. package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
  100. package/dist/unstable-core-do-not-import/utils.js +4 -0
  101. package/dist/unstable-core-do-not-import/utils.mjs +4 -1
  102. package/dist/unstable-core-do-not-import.d.ts +5 -2
  103. package/dist/unstable-core-do-not-import.d.ts.map +1 -1
  104. package/dist/unstable-core-do-not-import.js +19 -7
  105. package/dist/unstable-core-do-not-import.mjs +6 -3
  106. package/package.json +6 -6
  107. package/src/@trpc/server/http.ts +7 -2
  108. package/src/@trpc/server/index.ts +1 -0
  109. package/src/@trpc/server/rpc.ts +1 -0
  110. package/src/adapters/aws-lambda/getPlanner.ts +21 -2
  111. package/src/adapters/next-app-dir/nextAppDirCaller.ts +2 -1
  112. package/src/adapters/node-http/incomingMessageToRequest.ts +3 -2
  113. package/src/adapters/node-http/nodeHTTPRequestHandler.ts +32 -7
  114. package/src/adapters/ws.ts +193 -107
  115. package/src/observable/observable.ts +63 -0
  116. package/src/unstable-core-do-not-import/createProxy.ts +23 -8
  117. package/src/unstable-core-do-not-import/http/contentType.ts +83 -21
  118. package/src/{adapters/next-app-dir → unstable-core-do-not-import/http}/formDataToObject.ts +18 -10
  119. package/src/unstable-core-do-not-import/http/getHTTPStatusCode.ts +4 -7
  120. package/src/unstable-core-do-not-import/http/parseConnectionParams.ts +49 -0
  121. package/src/unstable-core-do-not-import/http/resolveResponse.ts +333 -164
  122. package/src/unstable-core-do-not-import/http/types.ts +31 -2
  123. package/src/unstable-core-do-not-import/procedureBuilder.ts +8 -1
  124. package/src/unstable-core-do-not-import/rootConfig.ts +12 -0
  125. package/src/unstable-core-do-not-import/router.ts +47 -35
  126. package/src/unstable-core-do-not-import/rpc/envelopes.ts +9 -0
  127. package/src/unstable-core-do-not-import/rpc/index.ts +1 -0
  128. package/src/unstable-core-do-not-import/stream/{stream.ts → jsonl.ts} +186 -127
  129. package/src/unstable-core-do-not-import/stream/sse.ts +288 -0
  130. package/src/unstable-core-do-not-import/stream/utils/createDeferred.ts +48 -0
  131. package/src/unstable-core-do-not-import/stream/utils/createReadableStream.ts +31 -0
  132. package/src/unstable-core-do-not-import/stream/utils/createServer.ts +44 -0
  133. package/src/unstable-core-do-not-import/utils.ts +5 -0
  134. package/src/unstable-core-do-not-import.ts +5 -2
  135. package/dist/adapters/next-app-dir/formDataToObject.d.ts.map +0 -1
  136. package/dist/adapters/next-app-dir/formDataToObject.js +0 -34
  137. package/dist/adapters/next-app-dir/formDataToObject.mjs +0 -32
  138. package/dist/unstable-core-do-not-import/stream/stream.d.ts.map +0 -1
  139. /package/dist/{adapters/next-app-dir → unstable-core-do-not-import/http}/formDataToObject.d.ts +0 -0
@@ -1,18 +1,8 @@
1
- import { isObject, isFunction, isAsyncIterable } from '../utils.mjs';
1
+ import { getTRPCErrorFromUnknown } from '../error/TRPCError.mjs';
2
+ import { isObject, isFunction, isAsyncIterable, run } from '../utils.mjs';
3
+ import { createDeferred } from './utils/createDeferred.mjs';
4
+ import { createReadableStream } from './utils/createReadableStream.mjs';
2
5
 
3
- // ---------- utils
4
- function createReadableStream() {
5
- let controller = null;
6
- const stream = new ReadableStream({
7
- start (c) {
8
- controller = c;
9
- }
10
- });
11
- return [
12
- stream,
13
- controller
14
- ];
15
- }
16
6
  // ---------- types
17
7
  const CHUNK_VALUE_TYPE_PROMISE = 0;
18
8
  const CHUNK_VALUE_TYPE_ASYNC_ITERABLE = 1;
@@ -34,14 +24,14 @@ function createBatchStreamProducer(opts) {
34
24
  const { data } = opts;
35
25
  let counter = 0;
36
26
  const placeholder = 0;
37
- const [stream, controller] = createReadableStream();
27
+ const stream = createReadableStream();
38
28
  const pending = new Set();
39
29
  function maybeClose() {
40
- if (pending.size === 0) {
41
- controller.close();
30
+ if (pending.size === 0 && !stream.cancelled()) {
31
+ stream.controller.close();
42
32
  }
43
33
  }
44
- function hydratePromise(promise, path) {
34
+ function dehydratePromise(promise, path) {
45
35
  //
46
36
  const error = checkMaxDepth(path);
47
37
  if (error) {
@@ -52,25 +42,28 @@ function createBatchStreamProducer(opts) {
52
42
  }
53
43
  const idx = counter++;
54
44
  pending.add(idx);
55
- const enqueue = (value)=>{
56
- controller.enqueue(value);
57
- };
58
- promise.then((it)=>{
59
- enqueue([
45
+ Promise.race([
46
+ promise,
47
+ stream.cancelledPromise
48
+ ]).then((it)=>{
49
+ if (it === null) {
50
+ return;
51
+ }
52
+ stream.controller.enqueue([
60
53
  idx,
61
54
  PROMISE_STATUS_FULFILLED,
62
- hydrate(it, path)
55
+ dehydrate(it, path)
63
56
  ]);
64
- }).catch((error)=>{
57
+ }).catch((cause)=>{
65
58
  opts.onError?.({
66
- error,
59
+ error: cause,
67
60
  path
68
61
  });
69
- enqueue([
62
+ stream.controller.enqueue([
70
63
  idx,
71
64
  PROMISE_STATUS_REJECTED,
72
65
  opts.formatError?.({
73
- error,
66
+ error: cause,
74
67
  path
75
68
  })
76
69
  ]);
@@ -80,7 +73,7 @@ function createBatchStreamProducer(opts) {
80
73
  });
81
74
  return idx;
82
75
  }
83
- function hydrateAsyncIterable(iterable, path) {
76
+ function dehydrateAsyncIterable(iterable, path) {
84
77
  const error = checkMaxDepth(path);
85
78
  if (error) {
86
79
  iterable = {
@@ -91,37 +84,58 @@ function createBatchStreamProducer(opts) {
91
84
  }
92
85
  const idx = counter++;
93
86
  pending.add(idx);
94
- void (async ()=>{
95
- try {
96
- for await (const item of iterable){
97
- controller.enqueue([
87
+ run(async ()=>{
88
+ const iterator = iterable[Symbol.asyncIterator]();
89
+ while(true){
90
+ const next = await Promise.race([
91
+ iterator.next().catch(getTRPCErrorFromUnknown),
92
+ stream.cancelledPromise
93
+ ]);
94
+ if (next instanceof Error) {
95
+ opts.onError?.({
96
+ error: next,
97
+ path
98
+ });
99
+ stream.controller.enqueue([
98
100
  idx,
99
- ASYNC_ITERABLE_STATUS_VALUE,
100
- hydrate(item, path)
101
+ ASYNC_ITERABLE_STATUS_ERROR,
102
+ opts.formatError?.({
103
+ error: next,
104
+ path
105
+ })
101
106
  ]);
107
+ return;
102
108
  }
103
- controller.enqueue([
104
- idx,
105
- ASYNC_ITERABLE_STATUS_DONE
106
- ]);
107
- } catch (error) {
108
- opts.onError?.({
109
- error,
110
- path
111
- });
112
- controller.enqueue([
109
+ if (next === 'cancelled') {
110
+ await iterator.return?.();
111
+ break;
112
+ }
113
+ if (next.done) {
114
+ stream.controller.enqueue([
115
+ idx,
116
+ ASYNC_ITERABLE_STATUS_DONE
117
+ ]);
118
+ break;
119
+ }
120
+ stream.controller.enqueue([
113
121
  idx,
114
- ASYNC_ITERABLE_STATUS_ERROR,
115
- opts.formatError?.({
116
- error,
117
- path
118
- })
122
+ ASYNC_ITERABLE_STATUS_VALUE,
123
+ dehydrate(next.value, path)
119
124
  ]);
120
- } finally{
121
- pending.delete(idx);
122
- maybeClose();
123
125
  }
124
- })();
126
+ pending.delete(idx);
127
+ maybeClose();
128
+ }).catch((cause)=>{
129
+ // this shouldn't happen, but node crashes if we don't catch it
130
+ opts.onError?.({
131
+ error: new Error('You found a bug - please report it on https://github.com/trpc/trpc', // eslint-disable-next-line @typescript-eslint/ban-ts-comment
132
+ // @ts-ignore https://github.com/tc39/proposal-error-cause
133
+ {
134
+ cause
135
+ }),
136
+ path
137
+ });
138
+ });
125
139
  return idx;
126
140
  }
127
141
  function checkMaxDepth(path) {
@@ -130,11 +144,11 @@ function createBatchStreamProducer(opts) {
130
144
  }
131
145
  return null;
132
146
  }
133
- function hydrateChunk(value, path) {
147
+ function dehydrateChunk(value, path) {
134
148
  if (isPromise(value)) {
135
149
  return [
136
150
  CHUNK_VALUE_TYPE_PROMISE,
137
- hydratePromise(value, path)
151
+ dehydratePromise(value, path)
138
152
  ];
139
153
  }
140
154
  if (isAsyncIterable(value)) {
@@ -143,13 +157,13 @@ function createBatchStreamProducer(opts) {
143
157
  }
144
158
  return [
145
159
  CHUNK_VALUE_TYPE_ASYNC_ITERABLE,
146
- hydrateAsyncIterable(value, path)
160
+ dehydrateAsyncIterable(value, path)
147
161
  ];
148
162
  }
149
163
  return null;
150
164
  }
151
- function hydrate(value, path) {
152
- const reg = hydrateChunk(value, path);
165
+ function dehydrate(value, path) {
166
+ const reg = dehydrateChunk(value, path);
153
167
  if (reg) {
154
168
  return [
155
169
  [
@@ -171,7 +185,7 @@ function createBatchStreamProducer(opts) {
171
185
  const newObj = {};
172
186
  const asyncValues = [];
173
187
  for (const [key, item] of Object.entries(value)){
174
- const transformed = hydrateChunk(item, [
188
+ const transformed = dehydrateChunk(item, [
175
189
  ...path,
176
190
  key
177
191
  ]);
@@ -194,13 +208,13 @@ function createBatchStreamProducer(opts) {
194
208
  }
195
209
  const newHead = {};
196
210
  for (const [key, item] of Object.entries(data)){
197
- newHead[key] = hydrate(item, [
211
+ newHead[key] = dehydrate(item, [
198
212
  key
199
213
  ]);
200
214
  }
201
215
  return [
202
216
  newHead,
203
- stream
217
+ stream.readable
204
218
  ];
205
219
  }
206
220
  /**
@@ -244,7 +258,7 @@ class AsyncError extends Error {
244
258
  const nodeJsStreamToReaderEsque = (source)=>{
245
259
  return {
246
260
  getReader () {
247
- const [stream, controller] = createReadableStream();
261
+ const { readable , controller } = createReadableStream();
248
262
  source.on('data', (chunk)=>{
249
263
  controller.enqueue(chunk);
250
264
  });
@@ -254,7 +268,7 @@ const nodeJsStreamToReaderEsque = (source)=>{
254
268
  source.on('error', (error)=>{
255
269
  controller.error(error);
256
270
  });
257
- return stream.getReader();
271
+ return readable.getReader();
258
272
  }
259
273
  };
260
274
  };
@@ -300,24 +314,12 @@ function createConsumerStream(from) {
300
314
  }
301
315
  }));
302
316
  }
303
- function createDeferred() {
304
- let resolve;
305
- let reject;
306
- const promise = new Promise((res, rej)=>{
307
- resolve = res;
308
- reject = rej;
309
- });
310
- return {
311
- promise,
312
- resolve: resolve,
313
- reject: reject
314
- };
315
- }
316
317
  /**
317
318
  * JSON Lines stream consumer
318
319
  * @see https://jsonlines.org/
319
320
  */ async function jsonlStreamConsumer(opts) {
320
321
  const { deserialize =(v)=>v } = opts;
322
+ const streamAbortController = new AbortController();
321
323
  let source = createConsumerStream(opts.from);
322
324
  if (deserialize) {
323
325
  source = source.pipeThrough(new TransformStream({
@@ -329,14 +331,18 @@ function createDeferred() {
329
331
  let headDeferred = createDeferred();
330
332
  const chunkDeferred = new Map();
331
333
  const controllers = new Map();
332
- function dehydrateChunkDefinition(value) {
334
+ function hydrateChunkDefinition(value, path) {
333
335
  const [_path, type, chunkId] = value;
334
- const [stream, controller] = createReadableStream();
335
- controllers.set(chunkId, controller);
336
+ const { readable , controller } = createReadableStream();
337
+ const wrapper = {
338
+ controller,
339
+ abortController: new AbortController()
340
+ };
341
+ controllers.set(chunkId, wrapper);
336
342
  // resolve chunk deferred if it exists
337
343
  const deferred = chunkDeferred.get(chunkId);
338
344
  if (deferred) {
339
- deferred.resolve(controller);
345
+ deferred.resolve(wrapper);
340
346
  chunkDeferred.delete(chunkId);
341
347
  }
342
348
  switch(type){
@@ -344,7 +350,7 @@ function createDeferred() {
344
350
  {
345
351
  return new Promise((resolve, reject)=>{
346
352
  // listen for next value in the stream
347
- const reader = stream.getReader();
353
+ const reader = readable.getReader();
348
354
  reader.read().then((it)=>{
349
355
  if (it.done) {
350
356
  reject(new Error('Promise chunk ended without value'));
@@ -358,7 +364,7 @@ function createDeferred() {
358
364
  const [_chunkId, status, data] = value;
359
365
  switch(status){
360
366
  case PROMISE_STATUS_FULFILLED:
361
- resolve(dehydrate(data));
367
+ resolve(hydrate(data, path));
362
368
  break;
363
369
  case PROMISE_STATUS_REJECTED:
364
370
  reject(opts.formatError?.({
@@ -375,45 +381,71 @@ function createDeferred() {
375
381
  case CHUNK_VALUE_TYPE_ASYNC_ITERABLE:
376
382
  {
377
383
  return {
378
- [Symbol.asyncIterator]: async function*() {
379
- const reader = stream.getReader();
380
- while(true){
381
- const { done , value } = await reader.read();
382
- if (done) {
383
- break;
384
- }
385
- if (value instanceof StreamInterruptedError) {
386
- throw value;
387
- }
388
- const [_chunkId, status, data] = value;
389
- switch(status){
390
- case ASYNC_ITERABLE_STATUS_VALUE:
391
- yield dehydrate(data);
392
- break;
393
- case ASYNC_ITERABLE_STATUS_DONE:
394
- controllers.delete(chunkId);
395
- return;
396
- case ASYNC_ITERABLE_STATUS_ERROR:
384
+ [Symbol.asyncIterator]: ()=>{
385
+ const reader = readable.getReader();
386
+ const iterator = {
387
+ next: async ()=>{
388
+ const { done , value } = await reader.read();
389
+ if (value instanceof StreamInterruptedError) {
390
+ throw value;
391
+ }
392
+ if (done) {
397
393
  controllers.delete(chunkId);
398
- throw opts.formatError?.({
399
- error: data
400
- }) ?? new AsyncError(data);
394
+ return {
395
+ done: true,
396
+ value: undefined
397
+ };
398
+ }
399
+ const [_chunkId, status, data] = value;
400
+ switch(status){
401
+ case ASYNC_ITERABLE_STATUS_VALUE:
402
+ return {
403
+ done: false,
404
+ value: hydrate(data, path)
405
+ };
406
+ case ASYNC_ITERABLE_STATUS_DONE:
407
+ controllers.delete(chunkId);
408
+ return {
409
+ done: true,
410
+ value: undefined
411
+ };
412
+ case ASYNC_ITERABLE_STATUS_ERROR:
413
+ controllers.delete(chunkId);
414
+ throw opts.formatError?.({
415
+ error: data
416
+ }) ?? new AsyncError(data);
417
+ }
418
+ },
419
+ return: async ()=>{
420
+ wrapper.abortController.abort();
421
+ if (chunkDeferred.size === 0 && Array.from(controllers.values()).every((it)=>it.abortController.signal.aborted)) {
422
+ // nothing is listening to the stream anymore
423
+ streamAbortController.abort();
424
+ }
425
+ return {
426
+ done: true,
427
+ value: undefined
428
+ };
401
429
  }
402
- }
430
+ };
431
+ return iterator;
403
432
  }
404
433
  };
405
434
  }
406
435
  }
407
436
  }
408
- function dehydrate(value) {
437
+ function hydrate(value, path) {
409
438
  const [[data], ...asyncProps] = value;
410
439
  for (const value1 of asyncProps){
411
- const dehydrated = dehydrateChunkDefinition(value1);
412
- const [path] = value1;
413
- if (path === null) {
414
- return dehydrated;
440
+ const [key] = value1;
441
+ const hydrated = hydrateChunkDefinition(value1, key === null ? path : [
442
+ ...path,
443
+ key
444
+ ]);
445
+ if (key === null) {
446
+ return hydrated;
415
447
  }
416
- data[path] = dehydrated;
448
+ data[key] = hydrated;
417
449
  }
418
450
  return data;
419
451
  }
@@ -424,18 +456,25 @@ function createDeferred() {
424
456
  deferred.reject(error);
425
457
  }
426
458
  chunkDeferred.clear();
427
- for (const controller of controllers.values()){
459
+ for (const { controller } of controllers.values()){
428
460
  controller.enqueue(error);
429
461
  controller.close();
430
462
  }
431
463
  controllers.clear();
432
464
  };
433
465
  source.pipeTo(new WritableStream({
466
+ start (controller) {
467
+ streamAbortController.signal.addEventListener('abort', ()=>{
468
+ controller.error(streamAbortController.signal.reason);
469
+ });
470
+ },
434
471
  async write (chunkOrHead) {
435
472
  if (headDeferred) {
436
473
  const head = chunkOrHead;
437
474
  for (const [key, value] of Object.entries(chunkOrHead)){
438
- const parsed = dehydrate(value);
475
+ const parsed = hydrate(value, [
476
+ key
477
+ ]);
439
478
  head[key] = parsed;
440
479
  }
441
480
  headDeferred.resolve(head);
@@ -444,16 +483,16 @@ function createDeferred() {
444
483
  }
445
484
  const chunk = chunkOrHead;
446
485
  const [idx] = chunk;
447
- let controller = controllers.get(idx);
448
- if (!controller) {
486
+ let wrapper = controllers.get(idx);
487
+ if (!wrapper) {
449
488
  let deferred = chunkDeferred.get(idx);
450
489
  if (!deferred) {
451
490
  deferred = createDeferred();
452
491
  chunkDeferred.set(idx, deferred);
453
492
  }
454
- controller = await deferred.promise;
493
+ wrapper = await deferred.promise;
455
494
  }
456
- controller.enqueue(chunk);
495
+ wrapper.controller.enqueue(chunk);
457
496
  },
458
497
  close: closeOrAbort,
459
498
  abort: closeOrAbort
@@ -0,0 +1,86 @@
1
+ import type { ValidateShape } from '../types';
2
+ import type { ConsumerOnError } from './jsonl';
3
+ type Serialize = (value: any) => any;
4
+ type Deserialize = (value: any) => any;
5
+ /**
6
+ * Server-sent Event Message
7
+ * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
8
+ * @public
9
+ */
10
+ export interface SSEMessage {
11
+ /**
12
+ * The data field of the message - this can be anything
13
+ */
14
+ data: unknown;
15
+ /**
16
+ * The id for this message
17
+ * Passing this id will allow the client to resume the connection from this point if the connection is lost
18
+ * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#the-last-event-id-header
19
+ */
20
+ id: string;
21
+ }
22
+ declare const sseSymbol: unique symbol;
23
+ export type SSEMessageEnvelope<TData> = [typeof sseSymbol, TData];
24
+ /**
25
+ * Produce a typed server-sent event message
26
+ */
27
+ export declare function sse<TData extends SSEMessage>(event: ValidateShape<TData, SSEMessage>): SSEMessageEnvelope<TData>;
28
+ export declare function isSSEMessageEnvelope<TData extends SSEMessage>(value: unknown): value is SSEMessageEnvelope<TData>;
29
+ export type SerializedSSEvent = Omit<SSEMessage, 'data'> & {
30
+ data?: string;
31
+ };
32
+ /**
33
+ * @internal
34
+ */
35
+ export interface PingOptions {
36
+ /**
37
+ * Enable ping comments sent from the server
38
+ * @default false
39
+ */
40
+ enabled: boolean;
41
+ /**
42
+ * Interval in milliseconds
43
+ * @default 1000
44
+ */
45
+ intervalMs?: number;
46
+ }
47
+ export interface SSEStreamProducerOptions {
48
+ serialize?: Serialize;
49
+ data: AsyncIterable<unknown>;
50
+ maxDepth?: number;
51
+ ping?: PingOptions;
52
+ /**
53
+ * Maximum duration in milliseconds for the request before ending the stream
54
+ * Only useful for serverless runtimes
55
+ * @default undefined
56
+ */
57
+ maxDurationMs?: number;
58
+ /**
59
+ * End the request immediately after data is sent
60
+ * Only useful for serverless runtimes that do not support streaming responses
61
+ * @default false
62
+ */
63
+ emitAndEndImmediately?: boolean;
64
+ }
65
+ /**
66
+ *
67
+ * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
68
+ */
69
+ export declare function sseStreamProducer(opts: SSEStreamProducerOptions): ReadableStream<string>;
70
+ export type inferSSEOutput<TData> = TData extends SSEMessageEnvelope<infer $Data> ? $Data : TData;
71
+ /**
72
+ * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
73
+ */
74
+ export declare function sseStreamConsumer<TData>(opts: {
75
+ from: EventSource;
76
+ onError?: ConsumerOnError;
77
+ deserialize?: Deserialize;
78
+ }): AsyncIterable<inferSSEOutput<TData>>;
79
+ export declare const sseHeaders: {
80
+ readonly 'Content-Type': "text/event-stream";
81
+ readonly 'Cache-Control': "no-cache, no-transform";
82
+ readonly 'X-Accel-Buffering': "no";
83
+ readonly Connection: "keep-alive";
84
+ };
85
+ export {};
86
+ //# sourceMappingURL=sse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../src/unstable-core-do-not-import/stream/sse.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAI/C,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;AACrC,KAAK,WAAW,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;AAEvC;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IACd;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,QAAA,MAAM,SAAS,eAA+B,CAAC;AAC/C,MAAM,MAAM,kBAAkB,CAAC,KAAK,IAAI,CAAC,OAAO,SAAS,EAAE,KAAK,CAAC,CAAC;AAElE;;GAEG;AACH,wBAAgB,GAAG,CAAC,KAAK,SAAS,UAAU,EAC1C,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,UAAU,CAAC,GACtC,kBAAkB,CAAC,KAAK,CAAC,CAQ3B;AAED,wBAAgB,oBAAoB,CAAC,KAAK,SAAS,UAAU,EAC3D,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,kBAAkB,CAAC,KAAK,CAAC,CAEpC;AAED,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAQD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,0BA2G/D;AACD,MAAM,MAAM,cAAc,CAAC,KAAK,IAAI,KAAK,SAAS,kBAAkB,CAClE,MAAM,KAAK,CACZ,GACG,KAAK,GACL,KAAK,CAAC;AACV;;GAEG;AAEH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE;IAC7C,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,GAAG,aAAa,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CA0DvC;AAED,eAAO,MAAM,UAAU;;;;;CAKb,CAAC"}