@trpc/server 11.0.0-rc.474 → 11.0.0-rc.475

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 (38) hide show
  1. package/dist/@trpc/server/index.d.ts +5 -1
  2. package/dist/@trpc/server/index.d.ts.map +1 -1
  3. package/dist/adapters/ws.d.ts.map +1 -1
  4. package/dist/adapters/ws.js +36 -6
  5. package/dist/adapters/ws.mjs +37 -7
  6. package/dist/bundle-analysis.json +112 -97
  7. package/dist/index.js +3 -2
  8. package/dist/index.mjs +1 -1
  9. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts +2 -2
  10. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts.map +1 -1
  11. package/dist/unstable-core-do-not-import/rpc/envelopes.d.ts +8 -0
  12. package/dist/unstable-core-do-not-import/rpc/envelopes.d.ts.map +1 -1
  13. package/dist/unstable-core-do-not-import/rpc/parseTRPCMessage.d.ts.map +1 -1
  14. package/dist/unstable-core-do-not-import/rpc/parseTRPCMessage.js +6 -2
  15. package/dist/unstable-core-do-not-import/rpc/parseTRPCMessage.mjs +6 -2
  16. package/dist/unstable-core-do-not-import/stream/sse.d.ts +2 -30
  17. package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -1
  18. package/dist/unstable-core-do-not-import/stream/sse.js +4 -20
  19. package/dist/unstable-core-do-not-import/stream/sse.mjs +5 -19
  20. package/dist/unstable-core-do-not-import/stream/tracked.d.ts +31 -0
  21. package/dist/unstable-core-do-not-import/stream/tracked.d.ts.map +1 -0
  22. package/dist/unstable-core-do-not-import/stream/tracked.js +29 -0
  23. package/dist/unstable-core-do-not-import/stream/tracked.mjs +25 -0
  24. package/dist/unstable-core-do-not-import/transformer.d.ts +1 -0
  25. package/dist/unstable-core-do-not-import/transformer.d.ts.map +1 -1
  26. package/dist/unstable-core-do-not-import.d.ts +1 -0
  27. package/dist/unstable-core-do-not-import.d.ts.map +1 -1
  28. package/dist/unstable-core-do-not-import.js +4 -2
  29. package/dist/unstable-core-do-not-import.mjs +2 -1
  30. package/package.json +2 -2
  31. package/src/@trpc/server/index.ts +4 -0
  32. package/src/adapters/ws.ts +42 -6
  33. package/src/unstable-core-do-not-import/procedureBuilder.ts +2 -2
  34. package/src/unstable-core-do-not-import/rpc/envelopes.ts +18 -2
  35. package/src/unstable-core-do-not-import/rpc/parseTRPCMessage.ts +5 -1
  36. package/src/unstable-core-do-not-import/stream/sse.ts +21 -65
  37. package/src/unstable-core-do-not-import/stream/tracked.ts +55 -0
  38. package/src/unstable-core-do-not-import.ts +1 -0
@@ -40,8 +40,11 @@ import { isObject } from '../utils.mjs';
40
40
  }
41
41
  assertIsProcedureType(method);
42
42
  assertIsObject(params);
43
- const { input: rawInput , path } = params;
43
+ const { input: rawInput , path , lastEventId } = params;
44
44
  assertIsString(path);
45
+ if (lastEventId !== undefined) {
46
+ assertIsString(lastEventId);
47
+ }
45
48
  const input = transformer.input.deserialize(rawInput);
46
49
  return {
47
50
  id,
@@ -49,7 +52,8 @@ import { isObject } from '../utils.mjs';
49
52
  method,
50
53
  params: {
51
54
  input,
52
- path
55
+ path,
56
+ lastEventId
53
57
  }
54
58
  };
55
59
  }
@@ -1,34 +1,7 @@
1
- import type { ValidateShape } from '../types';
2
1
  import type { ConsumerOnError } from './jsonl';
2
+ import type { inferTrackedOutput } from './tracked';
3
3
  type Serialize = (value: any) => any;
4
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
5
  /**
33
6
  * @internal
34
7
  */
@@ -67,7 +40,6 @@ export interface SSEStreamProducerOptions {
67
40
  * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
68
41
  */
69
42
  export declare function sseStreamProducer(opts: SSEStreamProducerOptions): ReadableStream<string>;
70
- export type inferSSEOutput<TData> = TData extends SSEMessageEnvelope<infer $Data> ? $Data : TData;
71
43
  /**
72
44
  * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
73
45
  */
@@ -75,7 +47,7 @@ export declare function sseStreamConsumer<TData>(opts: {
75
47
  from: EventSource;
76
48
  onError?: ConsumerOnError;
77
49
  deserialize?: Deserialize;
78
- }): AsyncIterable<inferSSEOutput<TData>>;
50
+ }): AsyncIterable<inferTrackedOutput<TData>>;
79
51
  export declare const sseHeaders: {
80
52
  readonly 'Content-Type': "text/event-stream";
81
53
  readonly 'Cache-Control': "no-cache, no-transform";
@@ -1 +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"}
1
+ {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../src/unstable-core-do-not-import/stream/sse.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAKpD,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;AACrC,KAAK,WAAW,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;AAEvC;;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,0BA8G/D;AACD;;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,kBAAkB,CAAC,KAAK,CAAC,CAAC,CA6D3C;AAED,eAAO,MAAM,UAAU;;;;;CAKb,CAAC"}
@@ -2,25 +2,10 @@
2
2
 
3
3
  var TRPCError = require('../error/TRPCError.js');
4
4
  var utils = require('../utils.js');
5
+ var tracked = require('./tracked.js');
5
6
  var createDeferred = require('./utils/createDeferred.js');
6
7
  var createReadableStream = require('./utils/createReadableStream.js');
7
8
 
8
- const sseSymbol = Symbol('SSEMessageEnvelope');
9
- /**
10
- * Produce a typed server-sent event message
11
- */ function sse(event) {
12
- if (event.id === '') {
13
- // This could be removed by using different event names for `yield sse(x)`-emitted events and `yield y`-emitted events
14
- throw new Error('`id` must not be an empty string as empty string is the same as not setting the id at all');
15
- }
16
- return [
17
- sseSymbol,
18
- event
19
- ];
20
- }
21
- function isSSEMessageEnvelope(value) {
22
- return Array.isArray(value) && value[0] === sseSymbol;
23
- }
24
9
  /**
25
10
  *
26
11
  * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
@@ -68,8 +53,9 @@ function isSSEMessageEnvelope(value) {
68
53
  break;
69
54
  }
70
55
  const value = next.value;
71
- const chunk = isSSEMessageEnvelope(value) ? {
72
- ...value[1]
56
+ const chunk = tracked.isTrackedEnvelope(value) ? {
57
+ id: value[0],
58
+ data: value[1]
73
59
  } : {
74
60
  data: value
75
61
  };
@@ -171,8 +157,6 @@ const sseHeaders = {
171
157
  Connection: 'keep-alive'
172
158
  };
173
159
 
174
- exports.isSSEMessageEnvelope = isSSEMessageEnvelope;
175
- exports.sse = sse;
176
160
  exports.sseHeaders = sseHeaders;
177
161
  exports.sseStreamConsumer = sseStreamConsumer;
178
162
  exports.sseStreamProducer = sseStreamProducer;
@@ -1,24 +1,9 @@
1
1
  import { getTRPCErrorFromUnknown } from '../error/TRPCError.mjs';
2
2
  import { run } from '../utils.mjs';
3
+ import { isTrackedEnvelope } from './tracked.mjs';
3
4
  import { createTimeoutPromise } from './utils/createDeferred.mjs';
4
5
  import { createReadableStream } from './utils/createReadableStream.mjs';
5
6
 
6
- const sseSymbol = Symbol('SSEMessageEnvelope');
7
- /**
8
- * Produce a typed server-sent event message
9
- */ function sse(event) {
10
- if (event.id === '') {
11
- // This could be removed by using different event names for `yield sse(x)`-emitted events and `yield y`-emitted events
12
- throw new Error('`id` must not be an empty string as empty string is the same as not setting the id at all');
13
- }
14
- return [
15
- sseSymbol,
16
- event
17
- ];
18
- }
19
- function isSSEMessageEnvelope(value) {
20
- return Array.isArray(value) && value[0] === sseSymbol;
21
- }
22
7
  /**
23
8
  *
24
9
  * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
@@ -66,8 +51,9 @@ function isSSEMessageEnvelope(value) {
66
51
  break;
67
52
  }
68
53
  const value = next.value;
69
- const chunk = isSSEMessageEnvelope(value) ? {
70
- ...value[1]
54
+ const chunk = isTrackedEnvelope(value) ? {
55
+ id: value[0],
56
+ data: value[1]
71
57
  } : {
72
58
  data: value
73
59
  };
@@ -169,4 +155,4 @@ const sseHeaders = {
169
155
  Connection: 'keep-alive'
170
156
  };
171
157
 
172
- export { isSSEMessageEnvelope, sse, sseHeaders, sseStreamConsumer, sseStreamProducer };
158
+ export { sseHeaders, sseStreamConsumer, sseStreamProducer };
@@ -0,0 +1,31 @@
1
+ declare const trackedSymbol: unique symbol;
2
+ type TrackedId = string & {
3
+ __brand: 'TrackedId';
4
+ };
5
+ export type TrackedEnvelope<TData> = [TrackedId, TData, typeof trackedSymbol];
6
+ type Tracked<TData> = {
7
+ /**
8
+ * The id of the message to keep track of in case the connection gets lost
9
+ */
10
+ id: string;
11
+ /**
12
+ * The data field of the message - this can be anything
13
+ */
14
+ data: TData;
15
+ };
16
+ /**
17
+ * Produce a typed server-sent event message
18
+ * @deprecated use `tracked(id, data)` instead
19
+ */
20
+ export declare function sse<TData>(event: {
21
+ id: string;
22
+ data: TData;
23
+ }): TrackedEnvelope<TData>;
24
+ export declare function isTrackedEnvelope<TData>(value: unknown): value is TrackedEnvelope<TData>;
25
+ /**
26
+ * Automatically track an event so that it can be resumed from a given id if the connection is lost
27
+ */
28
+ export declare function tracked<TData>(id: string, data: TData): TrackedEnvelope<TData>;
29
+ export type inferTrackedOutput<TData> = TData extends TrackedEnvelope<infer $Data> ? Tracked<$Data> : TData;
30
+ export {};
31
+ //# sourceMappingURL=tracked.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracked.d.ts","sourceRoot":"","sources":["../../../src/unstable-core-do-not-import/stream/tracked.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,aAAa,eAA4B,CAAC;AAEhD,KAAK,SAAS,GAAG,MAAM,GAAG;IACxB,OAAO,EAAE,WAAW,CAAC;CACtB,CAAC;AACF,MAAM,MAAM,eAAe,CAAC,KAAK,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,aAAa,CAAC,CAAC;AAE9E,KAAK,OAAO,CAAC,KAAK,IAAI;IACpB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AACF;;;GAGG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,CAAC;CACb,GAAG,eAAe,CAAC,KAAK,CAAC,CAEzB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EACrC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,eAAe,CAAC,KAAK,CAAC,CAEjC;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAC3B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,KAAK,GACV,eAAe,CAAC,KAAK,CAAC,CAQxB;AAED,MAAM,MAAM,kBAAkB,CAAC,KAAK,IAAI,KAAK,SAAS,eAAe,CACnE,MAAM,KAAK,CACZ,GACG,OAAO,CAAC,KAAK,CAAC,GACd,KAAK,CAAC"}
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const trackedSymbol = Symbol('TrackedEnvelope');
4
+ /**
5
+ * Produce a typed server-sent event message
6
+ * @deprecated use `tracked(id, data)` instead
7
+ */ function sse(event) {
8
+ return tracked(event.id, event.data);
9
+ }
10
+ function isTrackedEnvelope(value) {
11
+ return Array.isArray(value) && value[2] === trackedSymbol;
12
+ }
13
+ /**
14
+ * Automatically track an event so that it can be resumed from a given id if the connection is lost
15
+ */ function tracked(id, data) {
16
+ if (id === '') {
17
+ // This limitation could be removed by using different SSE event names / channels for tracked event and non-tracked event
18
+ throw new Error('`id` must not be an empty string as empty string is the same as not setting the id at all');
19
+ }
20
+ return [
21
+ id,
22
+ data,
23
+ trackedSymbol
24
+ ];
25
+ }
26
+
27
+ exports.isTrackedEnvelope = isTrackedEnvelope;
28
+ exports.sse = sse;
29
+ exports.tracked = tracked;
@@ -0,0 +1,25 @@
1
+ const trackedSymbol = Symbol('TrackedEnvelope');
2
+ /**
3
+ * Produce a typed server-sent event message
4
+ * @deprecated use `tracked(id, data)` instead
5
+ */ function sse(event) {
6
+ return tracked(event.id, event.data);
7
+ }
8
+ function isTrackedEnvelope(value) {
9
+ return Array.isArray(value) && value[2] === trackedSymbol;
10
+ }
11
+ /**
12
+ * Automatically track an event so that it can be resumed from a given id if the connection is lost
13
+ */ function tracked(id, data) {
14
+ if (id === '') {
15
+ // This limitation could be removed by using different SSE event names / channels for tracked event and non-tracked event
16
+ throw new Error('`id` must not be an empty string as empty string is the same as not setting the id at all');
17
+ }
18
+ return [
19
+ id,
20
+ data,
21
+ trackedSymbol
22
+ ];
23
+ }
24
+
25
+ export { isTrackedEnvelope, sse, tracked };
@@ -89,6 +89,7 @@ declare function transformResultInner<TRouter extends AnyRouter, TOutput>(respon
89
89
  data?: never;
90
90
  } | (import("./rpc").TRPCResult<TOutput> & {
91
91
  type: "data";
92
+ id?: string;
92
93
  });
93
94
  readonly error?: undefined;
94
95
  };
@@ -1 +1 @@
1
- {"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../../src/unstable-core-do-not-import/transformer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,OAAO,CAAC;AAGf;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;IAChC,WAAW,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;CACnC;AAED,UAAU,oBAAqB,SAAQ,eAAe;IACpD;;OAEG;IACH,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;IAChC;;OAEG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;CACnC;AAED,UAAU,qBAAsB,SAAQ,eAAe;IACrD;;OAEG;IACH,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;IAChC;;OAEG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,KAAK,EAAE,oBAAoB,CAAC;IAC5B;;OAEG;IACH,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C,KAAK,EAAE,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC;IAC3D,MAAM,EAAE,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC;CAChE,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,GAAG,eAAe,CAAC;AAE/E;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,sBAAsB,GAClC,uBAAuB,CAKzB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,uBAGhC,CAAC;AAyBF;;IAEI;AACJ,wBAAgB,qBAAqB,CACnC,SAAS,SACL,YAAY,GACZ,YAAY,EAAE,GACd,mBAAmB,GACnB,mBAAmB,EAAE,EACzB,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,SAAS;;yEAIzD;AAKD,gBAAgB;AAChB,iBAAS,oBAAoB,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,EAC9D,QAAQ,EACJ,YAAY,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAChD,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,EAC3D,WAAW,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;EAuB7B;AAQD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,EAChE,QAAQ,EACJ,YAAY,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAChD,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,EAC3D,WAAW,EAAE,eAAe,GAC3B,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAqBzC"}
1
+ {"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../../src/unstable-core-do-not-import/transformer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,OAAO,CAAC;AAGf;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;IAChC,WAAW,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;CACnC;AAED,UAAU,oBAAqB,SAAQ,eAAe;IACpD;;OAEG;IACH,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;IAChC;;OAEG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;CACnC;AAED,UAAU,qBAAsB,SAAQ,eAAe;IACrD;;OAEG;IACH,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;IAChC;;OAEG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,KAAK,EAAE,oBAAoB,CAAC;IAC5B;;OAEG;IACH,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C,KAAK,EAAE,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC;IAC3D,MAAM,EAAE,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC;CAChE,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,GAAG,eAAe,CAAC;AAE/E;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,sBAAsB,GAClC,uBAAuB,CAKzB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,uBAGhC,CAAC;AAyBF;;IAEI;AACJ,wBAAgB,qBAAqB,CACnC,SAAS,SACL,YAAY,GACZ,YAAY,EAAE,GACd,mBAAmB,GACnB,mBAAmB,EAAE,EACzB,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,SAAS;;yEAIzD;AAKD,gBAAgB;AAChB,iBAAS,oBAAoB,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,EAC9D,QAAQ,EACJ,YAAY,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAChD,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,EAC3D,WAAW,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;EAuB7B;AAQD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,EAChE,QAAQ,EACJ,YAAY,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAChD,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,EAC3D,WAAW,EAAE,eAAe,GAC3B,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAqBzC"}
@@ -34,6 +34,7 @@ export * from './unstable-core-do-not-import/router';
34
34
  export * from './unstable-core-do-not-import/rpc';
35
35
  export * from './unstable-core-do-not-import/stream/jsonl';
36
36
  export * from './unstable-core-do-not-import/stream/sse';
37
+ export * from './unstable-core-do-not-import/stream/tracked';
37
38
  export * from './unstable-core-do-not-import/stream/utils/createDeferred';
38
39
  export * from './unstable-core-do-not-import/transformer';
39
40
  export * from './unstable-core-do-not-import/types';
@@ -1 +1 @@
1
- {"version":3,"file":"unstable-core-do-not-import.d.ts","sourceRoot":"","sources":["../src/unstable-core-do-not-import.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,mDAAmD,CAAC;AAClE,cAAc,oDAAoD,CAAC;AACnE,cAAc,mDAAmD,CAAC;AAClE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,mDAAmD,CAAC;AAClE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,yDAAyD,CAAC;AACxE,cAAc,gDAAgD,CAAC;AAC/D,cAAc,uDAAuD,CAAC;AACtE,cAAc,qDAAqD,CAAC;AACpE,cAAc,sDAAsD,CAAC;AACrE,cAAc,0DAA0D,CAAC;AACzE,cAAc,oDAAoD,CAAC;AACnE,cAAc,0CAA0C,CAAC;AACzD,cAAc,0CAA0C,CAAC;AACzD,cAAc,wCAAwC,CAAC;AACvD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,mCAAmC,CAAC;AAClD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,0CAA0C,CAAC;AACzD,cAAc,2DAA2D,CAAC;AAC1E,cAAc,2CAA2C,CAAC;AAC1D,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC"}
1
+ {"version":3,"file":"unstable-core-do-not-import.d.ts","sourceRoot":"","sources":["../src/unstable-core-do-not-import.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,mDAAmD,CAAC;AAClE,cAAc,oDAAoD,CAAC;AACnE,cAAc,mDAAmD,CAAC;AAClE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,mDAAmD,CAAC;AAClE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,yDAAyD,CAAC;AACxE,cAAc,gDAAgD,CAAC;AAC/D,cAAc,uDAAuD,CAAC;AACtE,cAAc,qDAAqD,CAAC;AACpE,cAAc,sDAAsD,CAAC;AACrE,cAAc,0DAA0D,CAAC;AACzE,cAAc,oDAAoD,CAAC;AACnE,cAAc,0CAA0C,CAAC;AACzD,cAAc,0CAA0C,CAAC;AACzD,cAAc,wCAAwC,CAAC;AACvD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,mCAAmC,CAAC;AAClD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,0CAA0C,CAAC;AACzD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,2DAA2D,CAAC;AAC1E,cAAc,2CAA2C,CAAC;AAC1D,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC"}
@@ -23,6 +23,7 @@ var codes = require('./unstable-core-do-not-import/rpc/codes.js');
23
23
  var parseTRPCMessage = require('./unstable-core-do-not-import/rpc/parseTRPCMessage.js');
24
24
  var jsonl = require('./unstable-core-do-not-import/stream/jsonl.js');
25
25
  var sse = require('./unstable-core-do-not-import/stream/sse.js');
26
+ var tracked = require('./unstable-core-do-not-import/stream/tracked.js');
26
27
  var createDeferred = require('./unstable-core-do-not-import/stream/utils/createDeferred.js');
27
28
  var transformer = require('./unstable-core-do-not-import/transformer.js');
28
29
  var types = require('./unstable-core-do-not-import/types.js');
@@ -67,11 +68,12 @@ exports.parseTRPCMessage = parseTRPCMessage.parseTRPCMessage;
67
68
  exports.isPromise = jsonl.isPromise;
68
69
  exports.jsonlStreamConsumer = jsonl.jsonlStreamConsumer;
69
70
  exports.jsonlStreamProducer = jsonl.jsonlStreamProducer;
70
- exports.isSSEMessageEnvelope = sse.isSSEMessageEnvelope;
71
- exports.sse = sse.sse;
72
71
  exports.sseHeaders = sse.sseHeaders;
73
72
  exports.sseStreamConsumer = sse.sseStreamConsumer;
74
73
  exports.sseStreamProducer = sse.sseStreamProducer;
74
+ exports.isTrackedEnvelope = tracked.isTrackedEnvelope;
75
+ exports.sse = tracked.sse;
76
+ exports.tracked = tracked.tracked;
75
77
  exports.createDeferred = createDeferred.createDeferred;
76
78
  exports.createTimeoutPromise = createDeferred.createTimeoutPromise;
77
79
  exports.defaultTransformer = transformer.defaultTransformer;
@@ -20,7 +20,8 @@ export { callProcedure, createCallerFactory, createRouterFactory, mergeRouters }
20
20
  export { TRPC_ERROR_CODES_BY_KEY, TRPC_ERROR_CODES_BY_NUMBER } from './unstable-core-do-not-import/rpc/codes.mjs';
21
21
  export { parseTRPCMessage } from './unstable-core-do-not-import/rpc/parseTRPCMessage.mjs';
22
22
  export { isPromise, jsonlStreamConsumer, jsonlStreamProducer } from './unstable-core-do-not-import/stream/jsonl.mjs';
23
- export { isSSEMessageEnvelope, sse, sseHeaders, sseStreamConsumer, sseStreamProducer } from './unstable-core-do-not-import/stream/sse.mjs';
23
+ export { sseHeaders, sseStreamConsumer, sseStreamProducer } from './unstable-core-do-not-import/stream/sse.mjs';
24
+ export { isTrackedEnvelope, sse, tracked } from './unstable-core-do-not-import/stream/tracked.mjs';
24
25
  export { createDeferred, createTimeoutPromise } from './unstable-core-do-not-import/stream/utils/createDeferred.mjs';
25
26
  export { defaultTransformer, getDataTransformer, transformResult, transformTRPCResponse } from './unstable-core-do-not-import/transformer.mjs';
26
27
  export { ERROR_SYMBOL } from './unstable-core-do-not-import/types.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trpc/server",
3
- "version": "11.0.0-rc.474+42b880437",
3
+ "version": "11.0.0-rc.475+10b4bde0c",
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": "42b880437961af45a4e59ff33267acbaedc46cec"
152
+ "gitHead": "10b4bde0cb497c29d00f3c78c09fe8b64391f93c"
153
153
  }
@@ -37,7 +37,11 @@ export {
37
37
  type QueryProcedure as TRPCQueryProcedure,
38
38
  type SubscriptionProcedure as TRPCSubscriptionProcedure,
39
39
  type TRPCBuilder,
40
+ /**
41
+ * @deprecated use `tracked(id, data)` instead
42
+ */
40
43
  sse,
44
+ tracked,
41
45
  } from '../../unstable-core-do-not-import';
42
46
 
43
47
  export type {
@@ -21,6 +21,7 @@ import type {
21
21
  TRPCConnectionParamsMessage,
22
22
  TRPCReconnectNotification,
23
23
  TRPCResponseMessage,
24
+ TRPCResultMessage,
24
25
  } from '../@trpc/server/rpc';
25
26
  import { parseConnectionParamsFromUnknown } from '../http';
26
27
  import { isObservable } from '../observable';
@@ -29,6 +30,7 @@ import { observableToAsyncIterable } from '../observable/observable';
29
30
  import {
30
31
  isAsyncIterable,
31
32
  isObject,
33
+ isTrackedEnvelope,
32
34
  run,
33
35
  type MaybePromise,
34
36
  } from '../unstable-core-do-not-import';
@@ -171,6 +173,7 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
171
173
 
172
174
  async function handleRequest(msg: TRPCClientOutgoingMessage) {
173
175
  const { id, jsonrpc } = msg;
176
+
174
177
  /* istanbul ignore next -- @preserve */
175
178
  if (id === null) {
176
179
  throw new TRPCError({
@@ -182,9 +185,22 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
182
185
  clientSubscriptions.get(id)?.abort();
183
186
  return;
184
187
  }
185
- const { path, input } = msg.params;
188
+ const { path, lastEventId } = msg.params;
189
+ let { input } = msg.params;
186
190
  const type = msg.method;
187
191
  try {
192
+ if (lastEventId !== undefined) {
193
+ if (isObject(input)) {
194
+ input = {
195
+ ...input,
196
+ lastEventId: lastEventId,
197
+ };
198
+ } else {
199
+ input ??= {
200
+ lastEventId: lastEventId,
201
+ };
202
+ }
203
+ }
188
204
  await ctxPromise; // asserts context has been set
189
205
 
190
206
  const result = await callProcedure({
@@ -195,7 +211,16 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
195
211
  type,
196
212
  });
197
213
 
214
+ const isIterableResult =
215
+ isAsyncIterable(result) || isObservable(result);
216
+
198
217
  if (type !== 'subscription') {
218
+ if (isIterableResult) {
219
+ throw new TRPCError({
220
+ code: 'UNSUPPORTED_MEDIA_TYPE',
221
+ message: `Cannot return an async iterable or observable from a ${type} procedure with WebSockets`,
222
+ });
223
+ }
199
224
  // send the value as data if the method is not a subscription
200
225
  respond({
201
226
  id,
@@ -208,7 +233,7 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
208
233
  return;
209
234
  }
210
235
 
211
- if (!isObservable(result) && !isAsyncIterable(result)) {
236
+ if (!isIterableResult) {
212
237
  throw new TRPCError({
213
238
  message: `Subscription ${path} did not return an observable or a AsyncGenerator`,
214
239
  code: 'INTERNAL_SERVER_ERROR',
@@ -277,13 +302,24 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
277
302
  break;
278
303
  }
279
304
 
305
+ const result: TRPCResultMessage<unknown>['result'] = {
306
+ type: 'data',
307
+ data: next.value,
308
+ };
309
+
310
+ if (isTrackedEnvelope(next.value)) {
311
+ const [id, data] = next.value;
312
+ result.id = id;
313
+ result.data = {
314
+ id,
315
+ data,
316
+ };
317
+ }
318
+
280
319
  respond({
281
320
  id,
282
321
  jsonrpc,
283
- result: {
284
- type: 'data',
285
- data: next.value,
286
- },
322
+ result,
287
323
  });
288
324
  }
289
325
 
@@ -23,7 +23,7 @@ import type {
23
23
  QueryProcedure,
24
24
  SubscriptionProcedure,
25
25
  } from './procedure';
26
- import type { inferSSEOutput } from './stream/sse';
26
+ import type { inferTrackedOutput } from './stream/tracked';
27
27
  import type {
28
28
  GetRawInputFn,
29
29
  MaybePromise,
@@ -47,7 +47,7 @@ type DefaultValue<TValue, TFallback> = TValue extends UnsetMarker
47
47
  type inferSubscriptionOutput<TOutput> = TOutput extends AsyncIterable<
48
48
  infer $Output
49
49
  >
50
- ? inferSSEOutput<$Output>
50
+ ? inferTrackedOutput<$Output>
51
51
  : inferObservableValue<TOutput>;
52
52
 
53
53
  export type CallerOverride<TContext> = (opts: {
@@ -49,7 +49,17 @@ export namespace JSONRPC2 {
49
49
  /////////////////////////// HTTP envelopes ///////////////////////
50
50
 
51
51
  export interface TRPCRequest
52
- extends JSONRPC2.Request<ProcedureType, { path: string; input: unknown }> {}
52
+ extends JSONRPC2.Request<
53
+ ProcedureType,
54
+ {
55
+ path: string;
56
+ input: unknown;
57
+ /**
58
+ * The last event id that the client received
59
+ */
60
+ lastEventId?: string;
61
+ }
62
+ > {}
53
63
 
54
64
  export interface TRPCResult<TData = unknown> {
55
65
  data: TData;
@@ -101,7 +111,13 @@ export interface TRPCResultMessage<TData>
101
111
  extends JSONRPC2.ResultResponse<
102
112
  | { type: 'started'; data?: never }
103
113
  | { type: 'stopped'; data?: never }
104
- | (TRPCResult<TData> & { type: 'data' })
114
+ | (TRPCResult<TData> & {
115
+ type: 'data';
116
+ /**
117
+ * The id of the message to keep track of in case of a reconnect
118
+ */
119
+ id?: string;
120
+ })
105
121
  > {}
106
122
 
107
123
  export type TRPCResponseMessage<
@@ -67,9 +67,12 @@ export function parseTRPCMessage(
67
67
  }
68
68
  assertIsProcedureType(method);
69
69
  assertIsObject(params);
70
- const { input: rawInput, path } = params;
70
+ const { input: rawInput, path, lastEventId } = params;
71
71
 
72
72
  assertIsString(path);
73
+ if (lastEventId !== undefined) {
74
+ assertIsString(lastEventId);
75
+ }
73
76
 
74
77
  const input = transformer.input.deserialize(rawInput);
75
78
 
@@ -80,6 +83,7 @@ export function parseTRPCMessage(
80
83
  params: {
81
84
  input,
82
85
  path,
86
+ lastEventId,
83
87
  },
84
88
  };
85
89
  }