@procedures/client 0.47.2 → 0.48.1

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 (138) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/adapters/http/client/batch.d.ts.map +1 -1
  4. package/dist/adapters/http/client/batch.js.map +1 -1
  5. package/dist/adapters/http/server/body.d.ts.map +1 -1
  6. package/dist/adapters/http/server/body.js.map +1 -1
  7. package/dist/adapters/http/shared/constants.d.ts +82 -78
  8. package/dist/adapters/http/shared/constants.d.ts.map +1 -1
  9. package/dist/adapters/http/shared/constants.js +78 -80
  10. package/dist/adapters/http/shared/constants.js.map +1 -1
  11. package/dist/adapters/http/shared/errors.d.ts +15 -13
  12. package/dist/adapters/http/shared/errors.d.ts.map +1 -1
  13. package/dist/adapters/http/shared/errors.js +13 -14
  14. package/dist/adapters/http/shared/errors.js.map +1 -1
  15. package/dist/adapters/port/transport.d.ts.map +1 -1
  16. package/dist/adapters/port/transport.js.map +1 -1
  17. package/dist/adapters/sequence.d.ts.map +1 -1
  18. package/dist/adapters/sequence.js.map +1 -1
  19. package/dist/adapters/websocket/client/types.d.ts +16 -6
  20. package/dist/adapters/websocket/client/types.d.ts.map +1 -1
  21. package/dist/adapters/websocket/client/types.js +7 -8
  22. package/dist/adapters/websocket/client/types.js.map +1 -1
  23. package/dist/adapters/websocket/shared/rpc.d.ts.map +1 -1
  24. package/dist/adapters/websocket/shared/rpc.js.map +1 -1
  25. package/dist/browser.d.ts +3 -1
  26. package/dist/browser.d.ts.map +1 -1
  27. package/dist/browser.js +2 -0
  28. package/dist/browser.js.map +1 -1
  29. package/dist/client/batch-executor.d.ts.map +1 -1
  30. package/dist/client/batch-executor.js.map +1 -1
  31. package/dist/client/client.d.ts.map +1 -1
  32. package/dist/client/client.js +3 -4
  33. package/dist/client/client.js.map +1 -1
  34. package/dist/client/errors/codes.d.ts +66 -64
  35. package/dist/client/errors/codes.d.ts.map +1 -1
  36. package/dist/client/errors/codes.js +64 -65
  37. package/dist/client/errors/codes.js.map +1 -1
  38. package/dist/client/errors/http-status.d.ts +69 -67
  39. package/dist/client/errors/http-status.d.ts.map +1 -1
  40. package/dist/client/errors/http-status.js +67 -68
  41. package/dist/client/errors/http-status.js.map +1 -1
  42. package/dist/client/errors/types.d.ts +38 -15
  43. package/dist/client/errors/types.d.ts.map +1 -1
  44. package/dist/client/errors/types.js +17 -19
  45. package/dist/client/errors/types.js.map +1 -1
  46. package/dist/client/middleware/circuit-breaker.d.ts.map +1 -1
  47. package/dist/client/middleware/circuit-breaker.js.map +1 -1
  48. package/dist/client/middleware/lru.d.ts +1 -1
  49. package/dist/client/middleware/lru.d.ts.map +1 -1
  50. package/dist/client/middleware/lru.js.map +1 -1
  51. package/dist/client/middleware/rate-limit.d.ts.map +1 -1
  52. package/dist/client/middleware/rate-limit.js.map +1 -1
  53. package/dist/client/middleware/resilience.d.ts.map +1 -1
  54. package/dist/client/middleware/resilience.js +2 -1
  55. package/dist/client/middleware/resilience.js.map +1 -1
  56. package/dist/client/route-resolver.d.ts.map +1 -1
  57. package/dist/client/route-resolver.js.map +1 -1
  58. package/dist/client/types.d.ts.map +1 -1
  59. package/dist/client/types.js.map +1 -1
  60. package/dist/client/validation/types.d.ts +1 -7
  61. package/dist/client/validation/types.d.ts.map +1 -1
  62. package/dist/client/validation/types.js +4 -7
  63. package/dist/client/validation/types.js.map +1 -1
  64. package/dist/events/bus.d.ts +35 -0
  65. package/dist/events/bus.d.ts.map +1 -1
  66. package/dist/events/bus.js +135 -22
  67. package/dist/events/bus.js.map +1 -1
  68. package/dist/events/index.d.ts +5 -1
  69. package/dist/events/index.d.ts.map +1 -1
  70. package/dist/events/index.js +3 -0
  71. package/dist/events/index.js.map +1 -1
  72. package/dist/events/live-state.d.ts +289 -0
  73. package/dist/events/live-state.d.ts.map +1 -0
  74. package/dist/events/live-state.js +501 -0
  75. package/dist/events/live-state.js.map +1 -0
  76. package/dist/events/live-view.d.ts +38 -0
  77. package/dist/events/live-view.d.ts.map +1 -0
  78. package/dist/events/live-view.js +109 -0
  79. package/dist/events/live-view.js.map +1 -0
  80. package/dist/events/publisher.d.ts +18 -1
  81. package/dist/events/publisher.d.ts.map +1 -1
  82. package/dist/events/publisher.js +27 -8
  83. package/dist/events/publisher.js.map +1 -1
  84. package/dist/events/recheck.d.ts.map +1 -1
  85. package/dist/events/recheck.js.map +1 -1
  86. package/dist/events/remote.d.ts +1 -7
  87. package/dist/events/remote.d.ts.map +1 -1
  88. package/dist/events/remote.js +4 -7
  89. package/dist/events/remote.js.map +1 -1
  90. package/dist/events/types.d.ts +30 -0
  91. package/dist/events/types.d.ts.map +1 -1
  92. package/dist/middleware/compose.d.ts.map +1 -1
  93. package/dist/middleware/compose.js +6 -10
  94. package/dist/middleware/compose.js.map +1 -1
  95. package/dist/procedures/collection/hint-filter.d.ts +1 -7
  96. package/dist/procedures/collection/hint-filter.d.ts.map +1 -1
  97. package/dist/procedures/collection/hint-filter.js +4 -7
  98. package/dist/procedures/collection/hint-filter.js.map +1 -1
  99. package/dist/server/procedure-server.d.ts.map +1 -1
  100. package/dist/server/procedure-server.js +3 -0
  101. package/dist/server/procedure-server.js.map +1 -1
  102. package/dist/server/types.d.ts.map +1 -1
  103. package/dist/server/types.js.map +1 -1
  104. package/package.json +7 -4
  105. package/src/adapters/http/client/batch.ts +4 -1
  106. package/src/adapters/http/server/body.ts +4 -1
  107. package/src/adapters/http/shared/constants.ts +84 -78
  108. package/src/adapters/http/shared/errors.ts +16 -13
  109. package/src/adapters/port/transport.ts +4 -1
  110. package/src/adapters/sequence.ts +5 -1
  111. package/src/adapters/websocket/client/types.ts +19 -6
  112. package/src/adapters/websocket/shared/rpc.ts +15 -3
  113. package/src/browser.ts +20 -0
  114. package/src/client/batch-executor.ts +5 -1
  115. package/src/client/client.ts +3 -4
  116. package/src/client/errors/README.md +12 -12
  117. package/src/client/errors/codes.ts +67 -64
  118. package/src/client/errors/http-status.ts +70 -67
  119. package/src/client/errors/types.ts +44 -15
  120. package/src/client/middleware/circuit-breaker.ts +7 -2
  121. package/src/client/middleware/lru.ts +7 -2
  122. package/src/client/middleware/rate-limit.ts +4 -1
  123. package/src/client/middleware/resilience.ts +2 -1
  124. package/src/client/route-resolver.ts +5 -1
  125. package/src/client/types.ts +7 -2
  126. package/src/client/validation/types.ts +13 -6
  127. package/src/events/bus.ts +152 -23
  128. package/src/events/index.ts +30 -0
  129. package/src/events/live-state.ts +666 -0
  130. package/src/events/live-view.ts +134 -0
  131. package/src/events/publisher.ts +53 -10
  132. package/src/events/recheck.ts +4 -1
  133. package/src/events/remote.ts +33 -12
  134. package/src/events/types.ts +34 -0
  135. package/src/middleware/compose.ts +6 -22
  136. package/src/procedures/collection/hint-filter.ts +13 -6
  137. package/src/server/procedure-server.ts +2 -0
  138. package/src/server/types.ts +7 -2
@@ -1,105 +1,111 @@
1
1
  /**
2
2
  * HTTP Constants
3
3
  *
4
- * Shared HTTP enums and constants used by both client and server adapters.
4
+ * Shared HTTP constants used by both client and server adapters.
5
5
  */
6
6
 
7
7
  /**
8
8
  * HTTP Methods
9
9
  */
10
- export enum HTTPMethod {
11
- GET = "GET",
12
- POST = "POST",
13
- PUT = "PUT",
14
- PATCH = "PATCH",
15
- DELETE = "DELETE",
16
- OPTIONS = "OPTIONS",
17
- HEAD = "HEAD",
18
- }
10
+ export const HTTPMethod = {
11
+ GET: "GET",
12
+ POST: "POST",
13
+ PUT: "PUT",
14
+ PATCH: "PATCH",
15
+ DELETE: "DELETE",
16
+ OPTIONS: "OPTIONS",
17
+ HEAD: "HEAD",
18
+ } as const;
19
+
20
+ /** This type is the union of the values of `HTTPMethod`. */
21
+ export type HTTPMethod = (typeof HTTPMethod)[keyof typeof HTTPMethod];
19
22
 
20
23
  /**
21
24
  * HTTP Status Codes
22
25
  *
23
- * Comprehensive enum of all standard HTTP status codes.
26
+ * All standard HTTP status codes.
24
27
  */
25
- export enum HTTPStatus {
28
+ export const HTTPStatus = {
26
29
  // Unknown
27
- UNKNOWN = 0,
30
+ UNKNOWN: 0,
28
31
 
29
32
  // 1xx Informational
30
- CONTINUE = 100,
31
- SWITCHING_PROTOCOLS = 101,
32
- PROCESSING = 102,
33
- EARLY_HINTS = 103,
34
- RESPONSE_IS_TOO_LARGE = 104,
33
+ CONTINUE: 100,
34
+ SWITCHING_PROTOCOLS: 101,
35
+ PROCESSING: 102,
36
+ EARLY_HINTS: 103,
37
+ RESPONSE_IS_TOO_LARGE: 104,
35
38
 
36
39
  // 2xx Success
37
- OK = 200,
38
- CREATED = 201,
39
- ACCEPTED = 202,
40
- NON_AUTHORITATIVE_INFORMATION = 203,
41
- NO_CONTENT = 204,
42
- RESET_CONTENT = 205,
43
- PARTIAL_CONTENT = 206,
44
- MULTI_STATUS = 207,
45
- ALREADY_REPORTED = 208,
46
- IM_USED = 226,
40
+ OK: 200,
41
+ CREATED: 201,
42
+ ACCEPTED: 202,
43
+ NON_AUTHORITATIVE_INFORMATION: 203,
44
+ NO_CONTENT: 204,
45
+ RESET_CONTENT: 205,
46
+ PARTIAL_CONTENT: 206,
47
+ MULTI_STATUS: 207,
48
+ ALREADY_REPORTED: 208,
49
+ IM_USED: 226,
47
50
 
48
51
  // 3xx Redirection
49
- MULTIPLE_CHOICES = 300,
50
- MOVED_PERMANENTLY = 301,
51
- FOUND = 302,
52
- SEE_OTHER = 303,
53
- NOT_MODIFIED = 304,
54
- USE_PROXY = 305,
55
- TEMPORARY_REDIRECT = 307,
56
- PERMANENT_REDIRECT = 308,
52
+ MULTIPLE_CHOICES: 300,
53
+ MOVED_PERMANENTLY: 301,
54
+ FOUND: 302,
55
+ SEE_OTHER: 303,
56
+ NOT_MODIFIED: 304,
57
+ USE_PROXY: 305,
58
+ TEMPORARY_REDIRECT: 307,
59
+ PERMANENT_REDIRECT: 308,
57
60
 
58
61
  // 4xx Client Errors
59
- BAD_REQUEST = 400,
60
- UNAUTHORIZED = 401,
61
- FORBIDDEN = 403,
62
- NOT_FOUND = 404,
63
- METHOD_NOT_ALLOWED = 405,
64
- NOT_ACCEPTABLE = 406,
65
- PROXY_AUTHENTICATION_REQUIRED = 407,
66
- REQUEST_TIMEOUT = 408,
67
- CONFLICT = 409,
68
- GONE = 410,
69
- LENGTH_REQUIRED = 411,
70
- PRECONDITION_FAILED = 412,
71
- PAYLOAD_TOO_LARGE = 413,
72
- URI_TOO_LONG = 414,
73
- UNSUPPORTED_MEDIA_TYPE = 415,
74
- RANGE_NOT_SATISFIABLE = 416,
75
- EXPECTATION_FAILED = 417,
76
- IM_A_TEAPOT = 418,
77
- MISDIRECTED_REQUEST = 421,
78
- UNPROCESSABLE_ENTITY = 422,
79
- LOCKED = 423,
80
- FAILED_DEPENDENCY = 424,
81
- TOO_EARLY = 425,
82
- UPGRADE_REQUIRED = 426,
83
- PRECONDITION_REQUIRED = 428,
84
- TOO_MANY_REQUESTS = 429,
85
- REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
86
- UNAVAILABLE_FOR_LEGAL_REASONS = 451,
87
- CLIENT_CLOSED_REQUEST = 499,
62
+ BAD_REQUEST: 400,
63
+ UNAUTHORIZED: 401,
64
+ FORBIDDEN: 403,
65
+ NOT_FOUND: 404,
66
+ METHOD_NOT_ALLOWED: 405,
67
+ NOT_ACCEPTABLE: 406,
68
+ PROXY_AUTHENTICATION_REQUIRED: 407,
69
+ REQUEST_TIMEOUT: 408,
70
+ CONFLICT: 409,
71
+ GONE: 410,
72
+ LENGTH_REQUIRED: 411,
73
+ PRECONDITION_FAILED: 412,
74
+ PAYLOAD_TOO_LARGE: 413,
75
+ URI_TOO_LONG: 414,
76
+ UNSUPPORTED_MEDIA_TYPE: 415,
77
+ RANGE_NOT_SATISFIABLE: 416,
78
+ EXPECTATION_FAILED: 417,
79
+ IM_A_TEAPOT: 418,
80
+ MISDIRECTED_REQUEST: 421,
81
+ UNPROCESSABLE_ENTITY: 422,
82
+ LOCKED: 423,
83
+ FAILED_DEPENDENCY: 424,
84
+ TOO_EARLY: 425,
85
+ UPGRADE_REQUIRED: 426,
86
+ PRECONDITION_REQUIRED: 428,
87
+ TOO_MANY_REQUESTS: 429,
88
+ REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
89
+ UNAVAILABLE_FOR_LEGAL_REASONS: 451,
90
+ CLIENT_CLOSED_REQUEST: 499,
88
91
 
89
92
  // 5xx Server Errors
90
- INTERNAL_SERVER_ERROR = 500,
91
- NOT_IMPLEMENTED = 501,
92
- BAD_GATEWAY = 502,
93
- SERVICE_UNAVAILABLE = 503,
94
- GATEWAY_TIMEOUT = 504,
95
- HTTP_VERSION_NOT_SUPPORTED = 505,
96
- VARIANT_ALSO_NEGOTIATES = 506,
97
- INSUFFICIENT_STORAGE = 507,
98
- LOOP_DETECTED = 508,
99
- NOT_EXTENDED = 510,
100
- NETWORK_AUTHENTICATION_REQUIRED = 511,
101
- HTTP_NETWORK_CONNECT_TIMEOUT_ERROR = 599,
102
- }
93
+ INTERNAL_SERVER_ERROR: 500,
94
+ NOT_IMPLEMENTED: 501,
95
+ BAD_GATEWAY: 502,
96
+ SERVICE_UNAVAILABLE: 503,
97
+ GATEWAY_TIMEOUT: 504,
98
+ HTTP_VERSION_NOT_SUPPORTED: 505,
99
+ VARIANT_ALSO_NEGOTIATES: 506,
100
+ INSUFFICIENT_STORAGE: 507,
101
+ LOOP_DETECTED: 508,
102
+ NOT_EXTENDED: 510,
103
+ NETWORK_AUTHENTICATION_REQUIRED: 511,
104
+ HTTP_NETWORK_CONNECT_TIMEOUT_ERROR: 599,
105
+ } as const;
106
+
107
+ /** This type is the union of the values of `HTTPStatus`. */
108
+ export type HTTPStatus = (typeof HTTPStatus)[keyof typeof HTTPStatus];
103
109
 
104
110
  /**
105
111
  * HTTP Transport Protocol Name
@@ -15,28 +15,31 @@ import { httpStatusToErrorCode } from "../../../client/errors/http-errors.js";
15
15
  *
16
16
  * Categorizes errors into semantic codes instead of magic strings.
17
17
  */
18
- export enum HTTPErrorCode {
18
+ export const HTTPErrorCode = {
19
19
  // Network errors
20
- NETWORK_ERROR = "NETWORK_ERROR",
21
- CONNECTION_REFUSED = "CONNECTION_REFUSED",
22
- TIMEOUT = "TIMEOUT",
23
- ABORTED = "ABORTED",
20
+ NETWORK_ERROR: "NETWORK_ERROR",
21
+ CONNECTION_REFUSED: "CONNECTION_REFUSED",
22
+ TIMEOUT: "TIMEOUT",
23
+ ABORTED: "ABORTED",
24
24
 
25
25
  // HTTP errors (mapped from status codes)
26
- HTTP_ERROR = "HTTP_ERROR",
26
+ HTTP_ERROR: "HTTP_ERROR",
27
27
 
28
28
  // Parse/serialization errors
29
- INVALID_RESPONSE = "INVALID_RESPONSE",
30
- PARSE_ERROR = "PARSE_ERROR",
31
- SERIALIZE_ERROR = "SERIALIZE_ERROR",
29
+ INVALID_RESPONSE: "INVALID_RESPONSE",
30
+ PARSE_ERROR: "PARSE_ERROR",
31
+ SERIALIZE_ERROR: "SERIALIZE_ERROR",
32
32
 
33
33
  // Configuration errors
34
- INVALID_URL = "INVALID_URL",
35
- INVALID_METHOD = "INVALID_METHOD",
34
+ INVALID_URL: "INVALID_URL",
35
+ INVALID_METHOD: "INVALID_METHOD",
36
36
 
37
37
  // Unknown
38
- UNKNOWN = "UNKNOWN",
39
- }
38
+ UNKNOWN: "UNKNOWN",
39
+ } as const;
40
+
41
+ /** This type is the union of the values of `HTTPErrorCode`. */
42
+ export type HTTPErrorCode = (typeof HTTPErrorCode)[keyof typeof HTTPErrorCode];
40
43
 
41
44
  export const HTTPErrorMessage : Record<HTTPErrorCode, string> = {
42
45
  [HTTPErrorCode.PARSE_ERROR] : "Failed to parse response",
@@ -69,6 +69,8 @@ function isFrame(value: unknown): value is WebSocketMessage {
69
69
 
70
70
  /** The transport over a message port, in the two directions. */
71
71
  export class PortTransport implements Transport {
72
+ private readonly port: PortLike;
73
+
72
74
  readonly name = "port";
73
75
  private readonly outgoing: OutgoingCalls;
74
76
  private readonly incoming: IncomingCalls | undefined;
@@ -77,9 +79,10 @@ export class PortTransport implements Transport {
77
79
  private readonly onNodeMessage = (data: unknown): void => this.receive(data);
78
80
 
79
81
  constructor(
80
- private readonly port: PortLike,
82
+ port: PortLike,
81
83
  options: PortTransportOptions = {},
82
84
  ) {
85
+ this.port = port;
83
86
  const send = (frame: WebSocketMessage): void => this.port.postMessage(frame);
84
87
  const isOpen = (): boolean => this.open;
85
88
  this.outgoing = new OutgoingCalls({
@@ -32,10 +32,14 @@ export const STREAM_ITEM_METADATA_KEY = "stream";
32
32
 
33
33
  /** The order of the stream frames of one call, at the side that receives them. */
34
34
  export class StreamSequence {
35
+ private readonly logger?: Logger | undefined;
36
+
35
37
  private last = 0;
36
38
 
37
39
  /** The logger of the warning of a gap (CLI-87). Without it, the warning goes to `console.warn`. */
38
- constructor(private readonly logger?: Logger | undefined) {}
40
+ constructor(logger?: Logger | undefined) {
41
+ this.logger = logger;
42
+ }
39
43
 
40
44
  /**
41
45
  * This function examines the `seq` of a frame. It gives -1 for a frame to drop: its `seq` is
@@ -190,12 +190,25 @@ export type WebSocketClass = new (url: string) => unknown;
190
190
  /**
191
191
  * WebSocket connection state.
192
192
  */
193
- export enum WebSocketState {
194
- CONNECTING = "CONNECTING",
195
- CONNECTED = "CONNECTED",
196
- DISCONNECTING = "DISCONNECTING",
197
- DISCONNECTED = "DISCONNECTED",
198
- RECONNECTING = "RECONNECTING",
193
+ export const WebSocketState = {
194
+ CONNECTING: "CONNECTING",
195
+ CONNECTED: "CONNECTED",
196
+ DISCONNECTING: "DISCONNECTING",
197
+ DISCONNECTED: "DISCONNECTED",
198
+ RECONNECTING: "RECONNECTING",
199
+ } as const;
200
+
201
+ /** This type is the union of the values of `WebSocketState`. */
202
+ export type WebSocketState = (typeof WebSocketState)[keyof typeof WebSocketState];
203
+
204
+ /** These types keep each member of `WebSocketState` usable as a type. */
205
+ // eslint-disable-next-line @typescript-eslint/no-namespace
206
+ export declare namespace WebSocketState {
207
+ export type CONNECTING = typeof WebSocketState.CONNECTING;
208
+ export type CONNECTED = typeof WebSocketState.CONNECTED;
209
+ export type DISCONNECTING = typeof WebSocketState.DISCONNECTING;
210
+ export type DISCONNECTED = typeof WebSocketState.DISCONNECTED;
211
+ export type RECONNECTING = typeof WebSocketState.RECONNECTING;
199
212
  }
200
213
 
201
214
  /**
@@ -72,9 +72,13 @@ export class ItemQueue<T> {
72
72
  * The stream takes one for each item that it sends, and waits when it has none.
73
73
  */
74
74
  export class StreamCredit {
75
+ private credit: number;
76
+
75
77
  private wake: (() => void) | undefined;
76
78
 
77
- constructor(private credit: number) {}
79
+ constructor(credit: number) {
80
+ this.credit = credit;
81
+ }
78
82
 
79
83
  grant(n: number): void {
80
84
  this.credit += n;
@@ -175,10 +179,14 @@ export interface OutgoingCallsOptions {
175
179
 
176
180
  /** The calls that this side sends on one socket. */
177
181
  export class OutgoingCalls {
182
+ private readonly options: OutgoingCallsOptions;
183
+
178
184
  private readonly pending = new Map<string, PendingCall>();
179
185
  private seq = 0;
180
186
 
181
- constructor(private readonly options: OutgoingCallsOptions) {}
187
+ constructor(options: OutgoingCallsOptions) {
188
+ this.options = options;
189
+ }
182
190
 
183
191
  /** The number of calls that wait for their frames. */
184
192
  get size(): number {
@@ -332,12 +340,16 @@ export interface IncomingCallsOptions {
332
340
 
333
341
  /** The calls that the other side sends on one socket, served by a handler. */
334
342
  export class IncomingCalls {
343
+ private readonly options: IncomingCallsOptions;
344
+
335
345
  /** The calls that run, by wire id: a cancel frame or a closed socket aborts them */
336
346
  private readonly inflight = new Map<string, AbortController>();
337
347
  /** The flow control of the streams that run, by wire id */
338
348
  private readonly credits = new Map<string, StreamCredit>();
339
349
 
340
- constructor(private readonly options: IncomingCallsOptions) {}
350
+ constructor(options: IncomingCallsOptions) {
351
+ this.options = options;
352
+ }
341
353
 
342
354
  /** The number of calls that run. */
343
355
  get size(): number {
package/src/browser.ts CHANGED
@@ -609,12 +609,32 @@ export type {
609
609
  TypedEventBus,
610
610
  EventHandler,
611
611
  EventBusOptions,
612
+ EventFanOutOptions,
612
613
  EventListenOptions,
613
614
  EventWaitOptions,
614
615
  ChannelMap,
615
616
  } from "./events/index.js";
616
617
  // The remote events: a peer subscribes to the topics of the bus of another peer (EVENTS.md)
617
618
  export { EventPublisher, topicMatcher, EVENTS_SUBSCRIBE_PATH, SubscriptionError, remoteEvents, subscribeRemote } from "./events/index.js";
619
+ // The live state: keyed values in memory on a topic (LIVE-STATE-2026-11.md)
620
+ export { LiveState, liveTopic, liveTopicTarget, liveView, LIVE_SET_PATH, LIVE_SNAPSHOT_PATH, LIVE_LEAVE_PATH, MAX_LIVE_KEY_LENGTH, DEFAULT_LIVE_KEYS, DEFAULT_LIVE_TOPICS, DEFAULT_LIVE_VALUE_BYTES } from "./events/index.js";
621
+ export type {
622
+ AdmitLiveSet,
623
+ AdmitLiveLeave,
624
+ LiveLeaveCall,
625
+ LiveAdmission,
626
+ LiveClient,
627
+ LiveEntry,
628
+ LiveEvent,
629
+ LiveGone,
630
+ LiveGoneReason,
631
+ LiveSetCall,
632
+ LiveSetOptions,
633
+ LiveStateHost,
634
+ LiveStateOptions,
635
+ LiveView,
636
+ LiveViewOptions,
637
+ } from "./events/index.js";
618
638
  export type {
619
639
  EventPublisherOptions,
620
640
  TopicRule,
@@ -110,7 +110,11 @@ function cancelledResult(path: ProcedurePath, message: string): ProcedureCallRes
110
110
  * ```
111
111
  */
112
112
  export class BatchExecutor {
113
- constructor(private readonly execute: ProcedureExecutor) {}
113
+ private readonly execute: ProcedureExecutor;
114
+
115
+ constructor(execute: ProcedureExecutor) {
116
+ this.execute = execute;
117
+ }
114
118
 
115
119
  /**
116
120
  * Execute resolved routes with the specified strategy.
@@ -38,7 +38,7 @@ import type {
38
38
  TypedClientMiddleware,
39
39
  } from "./types.js";
40
40
  import { ClientError } from "./types.js";
41
- import { compose } from "../middleware/compose.js";
41
+ import { compose } from "@mark1russell7/collections/layers";
42
42
  import { pathToMethod } from "../server/method.js";
43
43
  import type { CallOptions, ClientContextInput } from "./context.js";
44
44
  import { mergeContext, normalizeCallOptions } from "./context.js";
@@ -920,9 +920,8 @@ export class Client<TContext = {}> {
920
920
  yield* self.transport.send<TReq, TRes>(context.message);
921
921
  };
922
922
 
923
- // Use universal middleware composition
924
- // compose(...middleware, finalRunner) applies middleware in order (onion model)
925
- return compose<false>(...(this.middleware as any[]), transportRunner) as ClientRunner<TReq, TRes>;
923
+ // The first middleware is the outermost one (onion model)
924
+ return compose(...(this.middleware as ClientMiddleware<TReq, TRes>[]))(transportRunner);
926
925
  }
927
926
 
928
927
  /**
@@ -4,8 +4,8 @@ Protocol-agnostic error handling with rich metadata and bidirectional HTTP statu
4
4
 
5
5
  ## Zero Magic Strings & Numbers
6
6
 
7
- - **ErrorCode enum** - All error codes use enum values (no string literals)
8
- - **HTTPStatus enum** - All HTTP status codes use enum values (no magic numbers)
7
+ - **ErrorCode** - All error codes use the values of this object (no string literals)
8
+ - **HTTPStatus** - All HTTP status codes use the values of this object (no magic numbers)
9
9
  - **Single source of truth** - `HTTP_STATUS_ERROR_MAP` defines bidirectional mapping
10
10
 
11
11
  ## Architecture
@@ -67,7 +67,7 @@ import { errorCodeToHTTPStatus, ErrorCode, HTTPStatus } from "@common/client/err
67
67
  // Map error code to HTTP status
68
68
  function handleError(code: ErrorCode): number {
69
69
  const status = errorCodeToHTTPStatus(code);
70
- return status; // Returns HTTPStatus enum value (404, 500, etc.)
70
+ return status; // Returns a value of HTTPStatus (404, 500, etc.)
71
71
  }
72
72
 
73
73
  // Example
@@ -100,8 +100,8 @@ try {
100
100
  common/src/client/errors/
101
101
  ├── README.md ← You are here
102
102
  ├── index.ts ← Public API exports
103
- ├── codes.ts ← ErrorCode enum (70+ codes)
104
- ├── http-status.ts ← HTTPStatus enum (all HTTP status codes)
103
+ ├── codes.ts ← ErrorCode (70+ codes)
104
+ ├── http-status.ts ← HTTPStatus (all HTTP status codes)
105
105
  ├── types.ts ← TypeScript interfaces
106
106
  ├── registry.ts ← ERROR_REGISTRY with full metadata
107
107
  ├── http-errors.ts ← HTTP-specific errors + bidirectional mapping
@@ -135,7 +135,7 @@ Works across all transports:
135
135
 
136
136
  Full TypeScript support:
137
137
  ```typescript
138
- // All enums are type-safe
138
+ // All values are type-safe
139
139
  const code: ErrorCode = ErrorCode.TIMEOUT;
140
140
  const status: HTTPStatus = HTTPStatus.NOT_FOUND;
141
141
 
@@ -201,7 +201,7 @@ console.error(formatError(error, true)); // include stack trace
201
201
 
202
202
  ## Best Practices
203
203
 
204
- 1. **Always use enum values** - Never use string literals or magic numbers
204
+ 1. **Always use the named values** - Never use string literals or magic numbers
205
205
  2. **Use the registry** - Don't create error metadata manually
206
206
  3. **Provide context** - Include requestId, transport, method when creating errors
207
207
  4. **Check retryable flag** - Respect the metadata when implementing retry logic
@@ -209,7 +209,7 @@ console.error(formatError(error, true)); // include stack trace
209
209
 
210
210
  ## Adding New Errors
211
211
 
212
- 1. Add to `ErrorCode` enum in `codes.ts`
212
+ 1. Add to `ErrorCode` in `codes.ts`
213
213
  2. Add metadata to `ERROR_REGISTRY` in `registry.ts` or `HTTP_ERROR_REGISTRY` in `http-errors.ts`
214
214
  3. If HTTP-related, add to `HTTP_STATUS_ERROR_MAP` in `http-errors.ts`
215
215
 
@@ -217,11 +217,11 @@ console.error(formatError(error, true)); // include stack trace
217
217
 
218
218
  Example:
219
219
  ```typescript
220
- // 1. Add to ErrorCode enum
221
- export enum ErrorCode {
220
+ // 1. Add to ErrorCode
221
+ export const ErrorCode = {
222
222
  // ... existing codes
223
- MY_NEW_ERROR = "MY_NEW_ERROR",
224
- }
223
+ MY_NEW_ERROR: "MY_NEW_ERROR",
224
+ } as const;
225
225
 
226
226
  // 2. Add to registry
227
227
  export const ERROR_REGISTRY: ErrorRegistry = {
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Error Code Enums
2
+ * Error Codes
3
3
  *
4
- * Comprehensive enum of ALL error codes.
5
- * NO MAGIC STRINGS - use these enums everywhere!
4
+ * ALL error codes.
5
+ * NO MAGIC STRINGS - use these values everywhere!
6
6
  */
7
7
 
8
8
  /**
@@ -10,81 +10,84 @@
10
10
  *
11
11
  * Protocol-agnostic error codes that work across all transports.
12
12
  */
13
- export enum ErrorCode {
13
+ export const ErrorCode = {
14
14
  // Network errors
15
- NETWORK_ERROR = "NETWORK_ERROR",
16
- CONNECTION_REFUSED = "CONNECTION_REFUSED",
17
- DNS_ERROR = "DNS_ERROR",
18
- STREAM_ENDED = "STREAM_ENDED",
15
+ NETWORK_ERROR: "NETWORK_ERROR",
16
+ CONNECTION_REFUSED: "CONNECTION_REFUSED",
17
+ DNS_ERROR: "DNS_ERROR",
18
+ STREAM_ENDED: "STREAM_ENDED",
19
19
 
20
20
  // Timeout errors
21
- TIMEOUT = "TIMEOUT",
22
- CONNECTION_TIMEOUT = "CONNECTION_TIMEOUT",
23
- READ_TIMEOUT = "READ_TIMEOUT",
24
- DEADLINE_EXCEEDED = "DEADLINE_EXCEEDED",
21
+ TIMEOUT: "TIMEOUT",
22
+ CONNECTION_TIMEOUT: "CONNECTION_TIMEOUT",
23
+ READ_TIMEOUT: "READ_TIMEOUT",
24
+ DEADLINE_EXCEEDED: "DEADLINE_EXCEEDED",
25
25
 
26
26
  // Cancellation
27
- ABORTED = "ABORTED",
27
+ ABORTED: "ABORTED",
28
28
 
29
29
  // Protocol/parsing errors
30
- PARSE_ERROR = "PARSE_ERROR",
31
- SERIALIZE_ERROR = "SERIALIZE_ERROR",
32
- INVALID_RESPONSE = "INVALID_RESPONSE",
33
- PROTOCOL_ERROR = "PROTOCOL_ERROR",
30
+ PARSE_ERROR: "PARSE_ERROR",
31
+ SERIALIZE_ERROR: "SERIALIZE_ERROR",
32
+ INVALID_RESPONSE: "INVALID_RESPONSE",
33
+ PROTOCOL_ERROR: "PROTOCOL_ERROR",
34
34
 
35
35
  // Client errors (4xx equivalent)
36
- BAD_REQUEST = "BAD_REQUEST",
37
- UNAUTHORIZED = "UNAUTHORIZED",
38
- FORBIDDEN = "FORBIDDEN",
39
- NOT_FOUND = "NOT_FOUND",
40
- METHOD_NOT_ALLOWED = "METHOD_NOT_ALLOWED",
41
- NOT_ACCEPTABLE = "NOT_ACCEPTABLE",
42
- PROXY_AUTHENTICATION_REQUIRED = "PROXY_AUTHENTICATION_REQUIRED",
43
- CONFLICT = "CONFLICT",
44
- GONE = "GONE",
45
- LENGTH_REQUIRED = "LENGTH_REQUIRED",
46
- PRECONDITION_FAILED = "PRECONDITION_FAILED",
47
- PAYLOAD_TOO_LARGE = "PAYLOAD_TOO_LARGE",
48
- URI_TOO_LONG = "URI_TOO_LONG",
49
- UNSUPPORTED_MEDIA_TYPE = "UNSUPPORTED_MEDIA_TYPE",
50
- RANGE_NOT_SATISFIABLE = "RANGE_NOT_SATISFIABLE",
51
- EXPECTATION_FAILED = "EXPECTATION_FAILED",
52
- IM_A_TEAPOT = "IM_A_TEAPOT",
53
- MISDIRECTED_REQUEST = "MISDIRECTED_REQUEST",
54
- UNPROCESSABLE_ENTITY = "UNPROCESSABLE_ENTITY",
55
- LOCKED = "LOCKED",
56
- FAILED_DEPENDENCY = "FAILED_DEPENDENCY",
57
- TOO_EARLY = "TOO_EARLY",
58
- UPGRADE_REQUIRED = "UPGRADE_REQUIRED",
59
- PRECONDITION_REQUIRED = "PRECONDITION_REQUIRED",
60
- TOO_MANY_REQUESTS = "TOO_MANY_REQUESTS",
61
- REQUEST_HEADER_FIELDS_TOO_LARGE = "REQUEST_HEADER_FIELDS_TOO_LARGE",
62
- UNAVAILABLE_FOR_LEGAL_REASONS = "UNAVAILABLE_FOR_LEGAL_REASONS",
63
- CLIENT_CLOSED_REQUEST = "CLIENT_CLOSED_REQUEST",
64
- METADATA_TOO_LARGE = "METADATA_TOO_LARGE",
36
+ BAD_REQUEST: "BAD_REQUEST",
37
+ UNAUTHORIZED: "UNAUTHORIZED",
38
+ FORBIDDEN: "FORBIDDEN",
39
+ NOT_FOUND: "NOT_FOUND",
40
+ METHOD_NOT_ALLOWED: "METHOD_NOT_ALLOWED",
41
+ NOT_ACCEPTABLE: "NOT_ACCEPTABLE",
42
+ PROXY_AUTHENTICATION_REQUIRED: "PROXY_AUTHENTICATION_REQUIRED",
43
+ CONFLICT: "CONFLICT",
44
+ GONE: "GONE",
45
+ LENGTH_REQUIRED: "LENGTH_REQUIRED",
46
+ PRECONDITION_FAILED: "PRECONDITION_FAILED",
47
+ PAYLOAD_TOO_LARGE: "PAYLOAD_TOO_LARGE",
48
+ URI_TOO_LONG: "URI_TOO_LONG",
49
+ UNSUPPORTED_MEDIA_TYPE: "UNSUPPORTED_MEDIA_TYPE",
50
+ RANGE_NOT_SATISFIABLE: "RANGE_NOT_SATISFIABLE",
51
+ EXPECTATION_FAILED: "EXPECTATION_FAILED",
52
+ IM_A_TEAPOT: "IM_A_TEAPOT",
53
+ MISDIRECTED_REQUEST: "MISDIRECTED_REQUEST",
54
+ UNPROCESSABLE_ENTITY: "UNPROCESSABLE_ENTITY",
55
+ LOCKED: "LOCKED",
56
+ FAILED_DEPENDENCY: "FAILED_DEPENDENCY",
57
+ TOO_EARLY: "TOO_EARLY",
58
+ UPGRADE_REQUIRED: "UPGRADE_REQUIRED",
59
+ PRECONDITION_REQUIRED: "PRECONDITION_REQUIRED",
60
+ TOO_MANY_REQUESTS: "TOO_MANY_REQUESTS",
61
+ REQUEST_HEADER_FIELDS_TOO_LARGE: "REQUEST_HEADER_FIELDS_TOO_LARGE",
62
+ UNAVAILABLE_FOR_LEGAL_REASONS: "UNAVAILABLE_FOR_LEGAL_REASONS",
63
+ CLIENT_CLOSED_REQUEST: "CLIENT_CLOSED_REQUEST",
64
+ METADATA_TOO_LARGE: "METADATA_TOO_LARGE",
65
65
 
66
66
  // Server errors (5xx equivalent)
67
- INTERNAL_ERROR = "INTERNAL_ERROR",
68
- NOT_IMPLEMENTED = "NOT_IMPLEMENTED",
69
- BAD_GATEWAY = "BAD_GATEWAY",
70
- SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE",
71
- GATEWAY_TIMEOUT = "GATEWAY_TIMEOUT",
72
- HTTP_VERSION_NOT_SUPPORTED = "HTTP_VERSION_NOT_SUPPORTED",
73
- VARIANT_ALSO_NEGOTIATES = "VARIANT_ALSO_NEGOTIATES",
74
- INSUFFICIENT_STORAGE = "INSUFFICIENT_STORAGE",
75
- LOOP_DETECTED = "LOOP_DETECTED",
76
- NOT_EXTENDED = "NOT_EXTENDED",
77
- NETWORK_AUTHENTICATION_REQUIRED = "NETWORK_AUTHENTICATION_REQUIRED",
78
- HTTP_NETWORK_CONNECT_TIMEOUT = "HTTP_NETWORK_CONNECT_TIMEOUT",
67
+ INTERNAL_ERROR: "INTERNAL_ERROR",
68
+ NOT_IMPLEMENTED: "NOT_IMPLEMENTED",
69
+ BAD_GATEWAY: "BAD_GATEWAY",
70
+ SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE",
71
+ GATEWAY_TIMEOUT: "GATEWAY_TIMEOUT",
72
+ HTTP_VERSION_NOT_SUPPORTED: "HTTP_VERSION_NOT_SUPPORTED",
73
+ VARIANT_ALSO_NEGOTIATES: "VARIANT_ALSO_NEGOTIATES",
74
+ INSUFFICIENT_STORAGE: "INSUFFICIENT_STORAGE",
75
+ LOOP_DETECTED: "LOOP_DETECTED",
76
+ NOT_EXTENDED: "NOT_EXTENDED",
77
+ NETWORK_AUTHENTICATION_REQUIRED: "NETWORK_AUTHENTICATION_REQUIRED",
78
+ HTTP_NETWORK_CONNECT_TIMEOUT: "HTTP_NETWORK_CONNECT_TIMEOUT",
79
79
 
80
80
  // Configuration errors
81
- INVALID_CONFIG = "INVALID_CONFIG",
82
- INVALID_URL = "INVALID_URL",
83
- INVALID_METHOD = "INVALID_METHOD",
81
+ INVALID_CONFIG: "INVALID_CONFIG",
82
+ INVALID_URL: "INVALID_URL",
83
+ INVALID_METHOD: "INVALID_METHOD",
84
84
 
85
85
  // HTTP-specific
86
- HTTP_ERROR = "HTTP_ERROR",
86
+ HTTP_ERROR: "HTTP_ERROR",
87
87
 
88
88
  // Unknown
89
- UNKNOWN = "UNKNOWN",
90
- }
89
+ UNKNOWN: "UNKNOWN",
90
+ } as const;
91
+
92
+ /** This type is the union of the values of `ErrorCode`. */
93
+ export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];