@milaboratories/pl-client 3.11.4 → 3.12.0

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 (193) hide show
  1. package/dist/core/PromiseTracker.cjs.map +1 -1
  2. package/dist/core/PromiseTracker.d.ts.map +1 -1
  3. package/dist/core/PromiseTracker.js.map +1 -1
  4. package/dist/core/StatefulPromise.cjs +2 -0
  5. package/dist/core/StatefulPromise.cjs.map +1 -1
  6. package/dist/core/StatefulPromise.js +2 -0
  7. package/dist/core/StatefulPromise.js.map +1 -1
  8. package/dist/core/abstract_stream.d.ts +1 -1
  9. package/dist/core/advisory_locks.cjs.map +1 -1
  10. package/dist/core/advisory_locks.js.map +1 -1
  11. package/dist/core/auth.cjs.map +1 -1
  12. package/dist/core/auth.d.ts.map +1 -1
  13. package/dist/core/auth.js.map +1 -1
  14. package/dist/core/cache.d.ts.map +1 -1
  15. package/dist/core/capabilities.cjs.map +1 -1
  16. package/dist/core/capabilities.d.ts.map +1 -1
  17. package/dist/core/capabilities.js.map +1 -1
  18. package/dist/core/client.cjs +3 -3
  19. package/dist/core/client.cjs.map +1 -1
  20. package/dist/core/client.d.ts.map +1 -1
  21. package/dist/core/client.js +2 -2
  22. package/dist/core/client.js.map +1 -1
  23. package/dist/core/config.cjs.map +1 -1
  24. package/dist/core/config.d.ts.map +1 -1
  25. package/dist/core/config.js.map +1 -1
  26. package/dist/core/default_client.cjs +5 -5
  27. package/dist/core/default_client.cjs.map +1 -1
  28. package/dist/core/default_client.d.ts.map +1 -1
  29. package/dist/core/default_client.js.map +1 -1
  30. package/dist/core/driver.cjs.map +1 -1
  31. package/dist/core/driver.d.ts.map +1 -1
  32. package/dist/core/driver.js.map +1 -1
  33. package/dist/core/error_resource.cjs.map +1 -1
  34. package/dist/core/error_resource.js.map +1 -1
  35. package/dist/core/errors.cjs +10 -11
  36. package/dist/core/errors.cjs.map +1 -1
  37. package/dist/core/errors.d.ts.map +1 -1
  38. package/dist/core/errors.js +10 -10
  39. package/dist/core/errors.js.map +1 -1
  40. package/dist/core/final.cjs +2 -1
  41. package/dist/core/final.cjs.map +1 -1
  42. package/dist/core/final.d.ts.map +1 -1
  43. package/dist/core/final.js.map +1 -1
  44. package/dist/core/ll_client.cjs +14 -9
  45. package/dist/core/ll_client.cjs.map +1 -1
  46. package/dist/core/ll_client.d.ts +1 -0
  47. package/dist/core/ll_client.d.ts.map +1 -1
  48. package/dist/core/ll_client.js +15 -9
  49. package/dist/core/ll_client.js.map +1 -1
  50. package/dist/core/ll_transaction.cjs +3 -1
  51. package/dist/core/ll_transaction.cjs.map +1 -1
  52. package/dist/core/ll_transaction.d.ts +1 -1
  53. package/dist/core/ll_transaction.d.ts.map +1 -1
  54. package/dist/core/ll_transaction.js +2 -1
  55. package/dist/core/ll_transaction.js.map +1 -1
  56. package/dist/core/stat.cjs.map +1 -1
  57. package/dist/core/stat.js.map +1 -1
  58. package/dist/core/transaction.cjs +11 -5
  59. package/dist/core/transaction.cjs.map +1 -1
  60. package/dist/core/transaction.d.ts.map +1 -1
  61. package/dist/core/transaction.js +11 -4
  62. package/dist/core/transaction.js.map +1 -1
  63. package/dist/core/tree_filter.cjs +73 -18
  64. package/dist/core/tree_filter.cjs.map +1 -1
  65. package/dist/core/tree_filter.d.ts +1 -1
  66. package/dist/core/tree_filter.d.ts.map +1 -1
  67. package/dist/core/tree_filter.js +72 -19
  68. package/dist/core/tree_filter.js.map +1 -1
  69. package/dist/core/type_conversion.cjs +19 -20
  70. package/dist/core/type_conversion.cjs.map +1 -1
  71. package/dist/core/type_conversion.js +19 -19
  72. package/dist/core/type_conversion.js.map +1 -1
  73. package/dist/core/types.cjs +2 -3
  74. package/dist/core/types.cjs.map +1 -1
  75. package/dist/core/types.d.ts.map +1 -1
  76. package/dist/core/types.js +2 -2
  77. package/dist/core/types.js.map +1 -1
  78. package/dist/core/unauth_client.cjs +7 -6
  79. package/dist/core/unauth_client.cjs.map +1 -1
  80. package/dist/core/unauth_client.d.ts +9 -0
  81. package/dist/core/unauth_client.d.ts.map +1 -1
  82. package/dist/core/unauth_client.js +7 -5
  83. package/dist/core/unauth_client.js.map +1 -1
  84. package/dist/core/user_resources.cjs +3 -1
  85. package/dist/core/user_resources.cjs.map +1 -1
  86. package/dist/core/user_resources.d.ts.map +1 -1
  87. package/dist/core/user_resources.js +3 -0
  88. package/dist/core/user_resources.js.map +1 -1
  89. package/dist/core/websocket_stream.cjs +17 -20
  90. package/dist/core/websocket_stream.cjs.map +1 -1
  91. package/dist/core/websocket_stream.js +16 -19
  92. package/dist/core/websocket_stream.js.map +1 -1
  93. package/dist/core/wire.d.ts.map +1 -1
  94. package/dist/helpers/pl.cjs +25 -0
  95. package/dist/helpers/pl.cjs.map +1 -1
  96. package/dist/helpers/pl.d.ts +1 -1
  97. package/dist/helpers/pl.d.ts.map +1 -1
  98. package/dist/helpers/pl.js +1 -1
  99. package/dist/helpers/pl.js.map +1 -1
  100. package/dist/helpers/poll.cjs +5 -1
  101. package/dist/helpers/poll.cjs.map +1 -1
  102. package/dist/helpers/poll.d.ts.map +1 -1
  103. package/dist/helpers/poll.js +4 -0
  104. package/dist/helpers/poll.js.map +1 -1
  105. package/dist/helpers/retry_strategy.cjs +1 -0
  106. package/dist/helpers/retry_strategy.cjs.map +1 -1
  107. package/dist/helpers/retry_strategy.js +1 -1
  108. package/dist/helpers/retry_strategy.js.map +1 -1
  109. package/dist/helpers/tx_helpers.cjs +0 -1
  110. package/dist/helpers/tx_helpers.cjs.map +1 -1
  111. package/dist/helpers/tx_helpers.d.ts.map +1 -1
  112. package/dist/helpers/tx_helpers.js.map +1 -1
  113. package/dist/index.cjs +0 -1
  114. package/dist/index.d.ts +1 -1
  115. package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.cjs +0 -1
  116. package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.cjs.map +1 -1
  117. package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.d.ts.map +1 -1
  118. package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.js.map +1 -1
  119. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +531 -77
  120. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
  121. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs +11 -4
  122. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs.map +1 -1
  123. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts +12 -6
  124. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts.map +1 -1
  125. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.js +11 -3
  126. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.js.map +1 -1
  127. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +106 -1
  128. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
  129. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +330 -77
  130. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
  131. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs +23 -7
  132. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs.map +1 -1
  133. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts +10 -3
  134. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts.map +1 -1
  135. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.js +18 -7
  136. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.js.map +1 -1
  137. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs +1 -2
  138. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs.map +1 -1
  139. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.d.ts.map +1 -1
  140. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.js +1 -1
  141. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.js.map +1 -1
  142. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.cjs +2 -2
  143. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.cjs.map +1 -1
  144. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.d.ts +1 -1
  145. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.d.ts.map +1 -1
  146. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.js +2 -2
  147. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.js.map +1 -1
  148. package/dist/proto-grpc/google/protobuf/any.cjs +1 -2
  149. package/dist/proto-grpc/google/protobuf/any.cjs.map +1 -1
  150. package/dist/proto-grpc/google/protobuf/any.d.ts.map +1 -1
  151. package/dist/proto-grpc/google/protobuf/any.js +1 -1
  152. package/dist/proto-grpc/google/protobuf/any.js.map +1 -1
  153. package/dist/proto-grpc/google/protobuf/duration.cjs +0 -1
  154. package/dist/proto-grpc/google/protobuf/duration.cjs.map +1 -1
  155. package/dist/proto-grpc/google/protobuf/duration.d.ts.map +1 -1
  156. package/dist/proto-grpc/google/protobuf/duration.js.map +1 -1
  157. package/dist/proto-grpc/google/protobuf/timestamp.cjs +0 -1
  158. package/dist/proto-grpc/google/protobuf/timestamp.cjs.map +1 -1
  159. package/dist/proto-grpc/google/protobuf/timestamp.d.ts.map +1 -1
  160. package/dist/proto-grpc/google/protobuf/timestamp.js.map +1 -1
  161. package/dist/proto-grpc/google/rpc/code.d.ts.map +1 -1
  162. package/dist/proto-rest/index.cjs +1 -1
  163. package/dist/proto-rest/index.cjs.map +1 -1
  164. package/dist/proto-rest/index.d.ts +1 -1
  165. package/dist/proto-rest/index.d.ts.map +1 -1
  166. package/dist/proto-rest/index.js.map +1 -1
  167. package/dist/proto-rest/plapi.d.ts +30 -9
  168. package/dist/proto-rest/plapi.d.ts.map +1 -1
  169. package/dist/test/tcp-proxy.cjs +2 -2
  170. package/dist/test/tcp-proxy.cjs.map +1 -1
  171. package/dist/test/tcp-proxy.d.ts +1 -1
  172. package/dist/test/tcp-proxy.js.map +1 -1
  173. package/dist/test/test_config.cjs +8 -2
  174. package/dist/test/test_config.cjs.map +1 -1
  175. package/dist/test/test_config.d.ts +1 -1
  176. package/dist/test/test_config.d.ts.map +1 -1
  177. package/dist/test/test_config.js +1 -1
  178. package/dist/test/test_config.js.map +1 -1
  179. package/dist/util/pl.cjs.map +1 -1
  180. package/dist/util/pl.js.map +1 -1
  181. package/dist/util/util.cjs.map +1 -1
  182. package/dist/util/util.js.map +1 -1
  183. package/package.json +6 -6
  184. package/src/core/ll_client.ts +7 -2
  185. package/src/core/unauth_client.ts +17 -2
  186. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.ts +16 -3
  187. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +326 -3
  188. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.ts +21 -7
  189. package/src/proto-rest/plapi.ts +29 -8
  190. package/dist/proto-grpc/google/rpc/code.cjs +0 -224
  191. package/dist/proto-grpc/google/rpc/code.cjs.map +0 -1
  192. package/dist/proto-grpc/google/rpc/code.js +0 -224
  193. package/dist/proto-grpc/google/rpc/code.js.map +0 -1
@@ -2,24 +2,20 @@ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
2
  const require_errors = require("./errors.cjs");
3
3
  const require_retry_strategy = require("../helpers/retry_strategy.cjs");
4
4
  let denque = require("denque");
5
- denque = require_runtime.__toESM(denque);
5
+ denque = require_runtime.__toESM(denque, 1);
6
6
  let undici = require("undici");
7
7
  //#region src/core/websocket_stream.ts
8
- var ConnectionState = /* @__PURE__ */ function(ConnectionState) {
9
- ConnectionState[ConnectionState["NEW"] = 0] = "NEW";
10
- ConnectionState[ConnectionState["CONNECTING"] = 1] = "CONNECTING";
11
- ConnectionState[ConnectionState["CONNECTED"] = 2] = "CONNECTED";
12
- ConnectionState[ConnectionState["CLOSING"] = 3] = "CLOSING";
13
- ConnectionState[ConnectionState["CLOSED"] = 4] = "CLOSED";
14
- return ConnectionState;
15
- }(ConnectionState || {});
16
8
  /**
17
9
  * WebSocket-based bidirectional stream implementation for LLTransaction.
18
10
  * Implements BiDiStream interface which is compatible with DuplexStreamingCall.
19
11
  */
20
12
  var WebSocketBiDiStream = class {
13
+ url;
14
+ serializeClientMessage;
15
+ parseServerMessage;
16
+ options;
21
17
  ws = null;
22
- connectionState = ConnectionState.NEW;
18
+ connectionState = 0;
23
19
  reconnection;
24
20
  sendQueue = new denque.default();
25
21
  sendCompleted = false;
@@ -44,12 +40,12 @@ var WebSocketBiDiStream = class {
44
40
  responses = { [Symbol.asyncIterator]: () => this.createResponseIterator() };
45
41
  close() {
46
42
  this.reconnection.cancel();
47
- if (this.connectionState < ConnectionState.CONNECTED) {
43
+ if (this.connectionState < 2) {
48
44
  this.ws?.close();
49
45
  this.onClose();
50
46
  return;
51
47
  }
52
- if (!this.progressConnectionState(ConnectionState.CLOSING)) return;
48
+ if (!this.progressConnectionState(3)) return;
53
49
  this.ws.close();
54
50
  }
55
51
  constructor(url, serializeClientMessage, parseServerMessage, options = {}) {
@@ -58,14 +54,15 @@ var WebSocketBiDiStream = class {
58
54
  this.parseServerMessage = parseServerMessage;
59
55
  this.options = options;
60
56
  this.onComplete = this.options.onComplete ?? ((stream) => stream.close());
61
- this.reconnection = new require_retry_strategy.RetryStrategy(this.options.retryConfig ?? {}, {
57
+ const retryConfig = this.options.retryConfig ?? {};
58
+ this.reconnection = new require_retry_strategy.RetryStrategy(retryConfig, {
62
59
  onRetry: () => {
63
60
  this.connect();
64
61
  },
65
62
  onMaxAttemptsReached: (error) => this.handleError(error)
66
63
  });
67
64
  if (this.options.abortSignal?.aborted) {
68
- this.progressConnectionState(ConnectionState.CLOSED);
65
+ this.progressConnectionState(4);
69
66
  return;
70
67
  }
71
68
  this.abortHandler = () => this.close();
@@ -74,7 +71,7 @@ var WebSocketBiDiStream = class {
74
71
  }
75
72
  connect() {
76
73
  if (this.options.abortSignal?.aborted) return;
77
- if (!this.progressConnectionState(ConnectionState.CONNECTING)) return;
74
+ if (!this.progressConnectionState(1)) return;
78
75
  try {
79
76
  this.ws = this.createWebSocket();
80
77
  this.ws.addEventListener("open", () => this.onOpen());
@@ -95,7 +92,7 @@ var WebSocketBiDiStream = class {
95
92
  return ws;
96
93
  }
97
94
  onOpen() {
98
- this.progressConnectionState(ConnectionState.CONNECTED);
95
+ this.progressConnectionState(2);
99
96
  this.processSendQueue();
100
97
  }
101
98
  onMessage(data) {
@@ -111,7 +108,7 @@ var WebSocketBiDiStream = class {
111
108
  }
112
109
  }
113
110
  onError(error) {
114
- if (this.connectionState < ConnectionState.CONNECTED) {
111
+ if (this.connectionState < 2) {
115
112
  this.lastError = this.toError(error);
116
113
  this.reconnection.schedule();
117
114
  return;
@@ -119,7 +116,7 @@ var WebSocketBiDiStream = class {
119
116
  this.handleError(this.toError(error));
120
117
  }
121
118
  onClose() {
122
- this.progressConnectionState(ConnectionState.CLOSED);
119
+ this.progressConnectionState(4);
123
120
  if (this.abortHandler) this.options.abortSignal?.removeEventListener("abort", this.abortHandler);
124
121
  if (this.options.abortSignal?.aborted && !this.lastError) {
125
122
  const reason = this.options.abortSignal.reason;
@@ -152,7 +149,7 @@ var WebSocketBiDiStream = class {
152
149
  }
153
150
  }
154
151
  canSendMessages() {
155
- return this.connectionState === ConnectionState.CONNECTED;
152
+ return this.connectionState === 2;
156
153
  }
157
154
  sendQueuedMessage(queued) {
158
155
  try {
@@ -254,7 +251,7 @@ var WebSocketBiDiStream = class {
254
251
  return /* @__PURE__ */ new Error("Stream closed");
255
252
  }
256
253
  isStreamEnded() {
257
- return this.connectionState === ConnectionState.CLOSED || this.options.abortSignal?.aborted || false;
254
+ return this.connectionState === 4 || this.options.abortSignal?.aborted || false;
258
255
  }
259
256
  toError(error) {
260
257
  if (error instanceof Error) return error;
@@ -1 +1 @@
1
- {"version":3,"file":"websocket_stream.cjs","names":["Denque","RetryStrategy","WebSocket","ErrorEvent","DisconnectedError"],"sources":["../../src/core/websocket_stream.ts"],"sourcesContent":["import { WebSocket, type WebSocketInit, type Dispatcher, ErrorEvent } from \"undici\";\nimport type { BiDiStream } from \"./abstract_stream\";\nimport Denque from \"denque\";\nimport type { RetryConfig } from \"../helpers/retry_strategy\";\nimport { RetryStrategy } from \"../helpers/retry_strategy\";\nimport { DisconnectedError } from \"./errors\";\n\ninterface QueuedMessage<InType extends object> {\n message: InType;\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\ninterface ResponseResolver<OutType extends object> {\n resolve: (value: IteratorResult<OutType>) => void;\n reject: (error: Error) => void;\n}\n\nenum ConnectionState {\n NEW = 0,\n CONNECTING = 1,\n CONNECTED = 2,\n CLOSING = 3,\n CLOSED = 4,\n}\n\nexport type WSStreamOptions<ClientMsg extends object, ServerMsg extends object> = {\n abortSignal?: AbortSignal;\n\n dispatcher?: Dispatcher;\n jwtToken?: string;\n retryConfig?: Partial<RetryConfig>;\n\n onComplete?: (stream: WebSocketBiDiStream<ClientMsg, ServerMsg>) => void | Promise<void>;\n};\n\n/**\n * WebSocket-based bidirectional stream implementation for LLTransaction.\n * Implements BiDiStream interface which is compatible with DuplexStreamingCall.\n */\nexport class WebSocketBiDiStream<\n ClientMsg extends object,\n ServerMsg extends object,\n> implements BiDiStream<ClientMsg, ServerMsg> {\n // Connection\n private ws: WebSocket | null = null;\n private connectionState: ConnectionState = ConnectionState.NEW;\n private readonly reconnection: RetryStrategy;\n\n // Send management\n private readonly sendQueue = new Denque<QueuedMessage<ClientMsg>>();\n private sendCompleted = false;\n private readonly onComplete: (\n stream: WebSocketBiDiStream<ClientMsg, ServerMsg>,\n ) => void | Promise<void>;\n\n // Response management\n private readonly responseQueue = new Denque<ServerMsg>();\n private responseResolvers: ResponseResolver<ServerMsg>[] = [];\n\n // Error tracking\n private lastError?: Error;\n\n // Abort listener reference for cleanup\n private readonly abortHandler?: () => void;\n\n // === Public API ===\n\n public readonly requests = {\n send: async (message: ClientMsg): Promise<void> => {\n return await this.enqueueSend(message);\n },\n\n complete: async (): Promise<void> => {\n if (this.sendCompleted) return;\n\n await this.drainSendQueue(); // ensure we sent all already queued messages before closing the stream\n try {\n await this.onComplete(this); // custom onComplete may send additional messages\n } catch {\n // When 'complete' gets called concurrently with connection break or over a broken\n // transaction stream (server decided it should drop transaction), server would close\n // connection anyway on its end. We can safely ignore error here and just continue working.\n }\n this.sendCompleted = true;\n },\n };\n\n public readonly responses: AsyncIterable<ServerMsg> = {\n [Symbol.asyncIterator]: () => this.createResponseIterator(),\n };\n\n public close(): void {\n this.reconnection.cancel();\n\n if (this.connectionState < ConnectionState.CONNECTED) {\n // Never reached CONNECTED state. ws.close() will never trigger 'close' event.\n this.ws?.close();\n this.onClose();\n return;\n }\n\n if (!this.progressConnectionState(ConnectionState.CLOSING)) return;\n this.ws!.close();\n }\n\n constructor(\n private readonly url: string,\n private readonly serializeClientMessage: (message: ClientMsg) => Uint8Array,\n private readonly parseServerMessage: (data: Uint8Array) => ServerMsg,\n private readonly options: WSStreamOptions<ClientMsg, ServerMsg> = {},\n ) {\n this.onComplete = this.options.onComplete ?? ((stream) => stream.close());\n\n const retryConfig = this.options.retryConfig ?? {};\n this.reconnection = new RetryStrategy(retryConfig, {\n onRetry: () => {\n void this.connect();\n },\n onMaxAttemptsReached: (error) => this.handleError(error),\n });\n\n if (this.options.abortSignal?.aborted) {\n this.progressConnectionState(ConnectionState.CLOSED);\n return;\n }\n\n this.abortHandler = () => this.close();\n this.options.abortSignal?.addEventListener(\"abort\", this.abortHandler, { once: true });\n this.connect();\n }\n\n // === Connection Lifecycle ===\n\n private connect(): void {\n if (this.options.abortSignal?.aborted) return;\n\n // Prevent reconnecting after first successful connection.\n if (!this.progressConnectionState(ConnectionState.CONNECTING)) return;\n\n try {\n this.ws = this.createWebSocket();\n\n this.ws.addEventListener(\"open\", () => this.onOpen());\n this.ws.addEventListener(\"message\", (event) => this.onMessage(event.data));\n this.ws.addEventListener(\"error\", (error) => this.onError(error));\n this.ws.addEventListener(\"close\", () => this.onClose());\n } catch (error) {\n this.lastError = this.toError(error);\n this.reconnection.schedule();\n }\n }\n\n private createWebSocket(): WebSocket {\n const options: WebSocketInit = {};\n\n if (this.options.jwtToken)\n options.headers = { authorization: `Bearer ${this.options.jwtToken}` };\n if (this.options.dispatcher) options.dispatcher = this.options.dispatcher;\n\n const ws = new WebSocket(this.url, options);\n ws.binaryType = \"arraybuffer\";\n return ws;\n }\n\n private onOpen(): void {\n this.progressConnectionState(ConnectionState.CONNECTED);\n this.processSendQueue();\n }\n\n private onMessage(data: unknown): void {\n if (!(data instanceof ArrayBuffer)) {\n this.handleError(new Error(`Unexpected WS message format: ${typeof data}`));\n return;\n }\n\n try {\n const message = this.parseServerMessage(new Uint8Array(data));\n this.deliverResponse(message);\n } catch (error) {\n this.handleError(this.toError(error));\n }\n }\n\n private onError(error: unknown): void {\n if (this.connectionState < ConnectionState.CONNECTED) {\n // Try to connect several times until we succeed or run out of attempts.\n this.lastError = this.toError(error);\n this.reconnection.schedule();\n return;\n }\n\n this.handleError(this.toError(error));\n }\n\n private onClose(): void {\n this.progressConnectionState(ConnectionState.CLOSED);\n\n // Clean up abort listener to prevent memory leaks\n if (this.abortHandler) {\n this.options.abortSignal?.removeEventListener(\"abort\", this.abortHandler);\n }\n\n // If abort signal was triggered, use that as the error source\n if (this.options.abortSignal?.aborted && !this.lastError) {\n const reason = this.options.abortSignal.reason;\n if (reason instanceof Error) {\n this.lastError = reason;\n } else if (reason !== undefined) {\n this.lastError = new Error(String(reason), { cause: reason });\n } else {\n this.lastError = this.createStreamClosedError();\n }\n }\n\n if (!this.lastError) {\n this.rejectAllSendOperations(this.createStreamClosedError());\n this.resolveAllPendingResponses(); // unblock active async iterator\n } else {\n this.rejectAllPendingOperations(this.lastError);\n }\n }\n\n // === Send Queue Management ===\n\n private enqueueSend(message: ClientMsg): Promise<void> {\n if (this.sendCompleted) {\n throw new Error(\"Cannot send: stream already completed\");\n }\n\n if (this.options.abortSignal?.aborted) {\n throw new Error(\"Cannot send: stream aborted\");\n }\n\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push({ message, resolve, reject });\n this.processSendQueue();\n });\n }\n\n private processSendQueue(): void {\n if (!this.canSendMessages()) return;\n\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n this.sendQueuedMessage(queued);\n }\n }\n\n private canSendMessages(): boolean {\n return this.connectionState === ConnectionState.CONNECTED;\n }\n\n private sendQueuedMessage(queued: QueuedMessage<ClientMsg>): void {\n try {\n const ws = this.ws;\n if (!ws) {\n throw new Error(\"WebSocket is not connected\");\n }\n\n // Check if WebSocket is in a valid state for sending\n if (ws.readyState !== WebSocket.OPEN) {\n throw new Error(`WebSocket is not open (readyState: ${ws.readyState})`);\n }\n\n const binary = this.serializeClientMessage(queued.message);\n ws.send(binary);\n queued.resolve();\n } catch (error) {\n queued.reject(this.toError(error));\n }\n }\n\n private async drainSendQueue(): Promise<void> {\n const POLL_INTERVAL_MS = 5;\n\n while (this.sendQueue.length > 0) {\n await this.waitForCondition(() => this.sendQueue.length === 0, POLL_INTERVAL_MS);\n }\n }\n\n private waitForCondition(condition: () => boolean, intervalMs: number): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (this.options.abortSignal?.aborted) {\n return reject(this.toError(this.options.abortSignal.reason) ?? new Error(\"Stream aborted\"));\n }\n\n let timeoutId: ReturnType<typeof setTimeout>;\n const onAbort = () => {\n clearTimeout(timeoutId);\n reject(this.toError(this.options.abortSignal?.reason) ?? new Error(\"Stream aborted\"));\n };\n\n this.options.abortSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n const check = () => {\n if (condition() || this.isStreamEnded()) {\n this.options.abortSignal?.removeEventListener(\"abort\", onAbort);\n resolve();\n } else {\n timeoutId = setTimeout(check, intervalMs);\n }\n };\n\n check();\n });\n }\n\n // === Response Delivery ===\n\n private deliverResponse(message: ServerMsg): void {\n if (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: message, done: false });\n } else {\n this.responseQueue.push(message);\n }\n }\n\n private async *createResponseIterator(): AsyncIterator<ServerMsg> {\n while (true) {\n const result = await this.nextResponse();\n\n if (result.done) break;\n\n yield result.value;\n }\n }\n\n private nextResponse(): Promise<IteratorResult<ServerMsg>> {\n return new Promise<IteratorResult<ServerMsg>>((resolve, reject) => {\n // Fast path: message already available\n if (this.responseQueue.length > 0) {\n const message = this.responseQueue.shift()!;\n resolve({ value: message, done: false });\n return;\n }\n\n // Stream ended\n if (this.isStreamEnded()) {\n if (this.lastError) {\n reject(this.lastError);\n } else {\n resolve({ value: undefined as any, done: true });\n }\n return;\n }\n\n // Wait for next message\n this.responseResolvers.push({ resolve, reject });\n });\n }\n\n private resolveAllPendingResponses(): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: undefined as any, done: true });\n }\n }\n\n // === Error Handling ===\n\n private handleError(error: Error): void {\n this.lastError = error;\n this.close();\n }\n\n private rejectAllPendingOperations(error: Error): void {\n this.rejectAllSendOperations(error);\n this.rejectAllResponseResolvers(error);\n }\n\n private rejectAllSendOperations(error: Error): void {\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n queued.reject(error);\n }\n }\n\n private rejectAllResponseResolvers(error: Error): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.reject(error);\n }\n }\n\n private createStreamClosedError(): Error {\n if (this.options.abortSignal?.aborted) {\n const reason = this.options.abortSignal.reason;\n if (reason instanceof Error) {\n return reason;\n }\n return new Error(\"Stream aborted\", { cause: reason });\n }\n\n return new Error(\"Stream closed\");\n }\n\n // === Helpers ===\n\n private isStreamEnded(): boolean {\n return (\n this.connectionState === ConnectionState.CLOSED || this.options.abortSignal?.aborted || false\n );\n }\n\n private toError(error: unknown): Error {\n if (error instanceof Error) return error;\n if (error instanceof ErrorEvent) {\n const err = error.error;\n // undici WebSocket throws TypeError with empty message on socket close\n // (e.g., when connection is lost or server disconnects)\n if (err instanceof TypeError && !err.message) {\n return new DisconnectedError(\"WebSocket connection closed unexpectedly\");\n }\n return err instanceof Error ? err : new Error(\"WebSocket error\", { cause: error });\n }\n return new Error(String(error));\n }\n\n /**\n * Connection state progresses linearly from NEW to CLOSED and never goes back.\n * This internal contract dramatically simplifies the internal stream state management.\n *\n * If you ever feel the need to make this contract less strict, think twice.\n */\n private progressConnectionState(newState: ConnectionState): boolean {\n if (newState < this.connectionState) {\n return false;\n }\n this.connectionState = newState;\n return true;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"websocket_stream.cjs","names":["Denque","RetryStrategy","WebSocket","ErrorEvent","DisconnectedError"],"sources":["../../src/core/websocket_stream.ts"],"sourcesContent":["import { WebSocket, type WebSocketInit, type Dispatcher, ErrorEvent } from \"undici\";\nimport type { BiDiStream } from \"./abstract_stream\";\nimport Denque from \"denque\";\nimport type { RetryConfig } from \"../helpers/retry_strategy\";\nimport { RetryStrategy } from \"../helpers/retry_strategy\";\nimport { DisconnectedError } from \"./errors\";\n\ninterface QueuedMessage<InType extends object> {\n message: InType;\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\ninterface ResponseResolver<OutType extends object> {\n resolve: (value: IteratorResult<OutType>) => void;\n reject: (error: Error) => void;\n}\n\nenum ConnectionState {\n NEW = 0,\n CONNECTING = 1,\n CONNECTED = 2,\n CLOSING = 3,\n CLOSED = 4,\n}\n\nexport type WSStreamOptions<ClientMsg extends object, ServerMsg extends object> = {\n abortSignal?: AbortSignal;\n\n dispatcher?: Dispatcher;\n jwtToken?: string;\n retryConfig?: Partial<RetryConfig>;\n\n onComplete?: (stream: WebSocketBiDiStream<ClientMsg, ServerMsg>) => void | Promise<void>;\n};\n\n/**\n * WebSocket-based bidirectional stream implementation for LLTransaction.\n * Implements BiDiStream interface which is compatible with DuplexStreamingCall.\n */\nexport class WebSocketBiDiStream<\n ClientMsg extends object,\n ServerMsg extends object,\n> implements BiDiStream<ClientMsg, ServerMsg> {\n // Connection\n private ws: WebSocket | null = null;\n private connectionState: ConnectionState = ConnectionState.NEW;\n private readonly reconnection: RetryStrategy;\n\n // Send management\n private readonly sendQueue = new Denque<QueuedMessage<ClientMsg>>();\n private sendCompleted = false;\n private readonly onComplete: (\n stream: WebSocketBiDiStream<ClientMsg, ServerMsg>,\n ) => void | Promise<void>;\n\n // Response management\n private readonly responseQueue = new Denque<ServerMsg>();\n private responseResolvers: ResponseResolver<ServerMsg>[] = [];\n\n // Error tracking\n private lastError?: Error;\n\n // Abort listener reference for cleanup\n private readonly abortHandler?: () => void;\n\n // === Public API ===\n\n public readonly requests = {\n send: async (message: ClientMsg): Promise<void> => {\n return await this.enqueueSend(message);\n },\n\n complete: async (): Promise<void> => {\n if (this.sendCompleted) return;\n\n await this.drainSendQueue(); // ensure we sent all already queued messages before closing the stream\n try {\n await this.onComplete(this); // custom onComplete may send additional messages\n } catch {\n // When 'complete' gets called concurrently with connection break or over a broken\n // transaction stream (server decided it should drop transaction), server would close\n // connection anyway on its end. We can safely ignore error here and just continue working.\n }\n this.sendCompleted = true;\n },\n };\n\n public readonly responses: AsyncIterable<ServerMsg> = {\n [Symbol.asyncIterator]: () => this.createResponseIterator(),\n };\n\n public close(): void {\n this.reconnection.cancel();\n\n if (this.connectionState < ConnectionState.CONNECTED) {\n // Never reached CONNECTED state. ws.close() will never trigger 'close' event.\n this.ws?.close();\n this.onClose();\n return;\n }\n\n if (!this.progressConnectionState(ConnectionState.CLOSING)) return;\n this.ws!.close();\n }\n\n constructor(\n private readonly url: string,\n private readonly serializeClientMessage: (message: ClientMsg) => Uint8Array,\n private readonly parseServerMessage: (data: Uint8Array) => ServerMsg,\n private readonly options: WSStreamOptions<ClientMsg, ServerMsg> = {},\n ) {\n this.onComplete = this.options.onComplete ?? ((stream) => stream.close());\n\n const retryConfig = this.options.retryConfig ?? {};\n this.reconnection = new RetryStrategy(retryConfig, {\n onRetry: () => {\n void this.connect();\n },\n onMaxAttemptsReached: (error) => this.handleError(error),\n });\n\n if (this.options.abortSignal?.aborted) {\n this.progressConnectionState(ConnectionState.CLOSED);\n return;\n }\n\n this.abortHandler = () => this.close();\n this.options.abortSignal?.addEventListener(\"abort\", this.abortHandler, { once: true });\n this.connect();\n }\n\n // === Connection Lifecycle ===\n\n private connect(): void {\n if (this.options.abortSignal?.aborted) return;\n\n // Prevent reconnecting after first successful connection.\n if (!this.progressConnectionState(ConnectionState.CONNECTING)) return;\n\n try {\n this.ws = this.createWebSocket();\n\n this.ws.addEventListener(\"open\", () => this.onOpen());\n this.ws.addEventListener(\"message\", (event) => this.onMessage(event.data));\n this.ws.addEventListener(\"error\", (error) => this.onError(error));\n this.ws.addEventListener(\"close\", () => this.onClose());\n } catch (error) {\n this.lastError = this.toError(error);\n this.reconnection.schedule();\n }\n }\n\n private createWebSocket(): WebSocket {\n const options: WebSocketInit = {};\n\n if (this.options.jwtToken)\n options.headers = { authorization: `Bearer ${this.options.jwtToken}` };\n if (this.options.dispatcher) options.dispatcher = this.options.dispatcher;\n\n const ws = new WebSocket(this.url, options);\n ws.binaryType = \"arraybuffer\";\n return ws;\n }\n\n private onOpen(): void {\n this.progressConnectionState(ConnectionState.CONNECTED);\n this.processSendQueue();\n }\n\n private onMessage(data: unknown): void {\n if (!(data instanceof ArrayBuffer)) {\n this.handleError(new Error(`Unexpected WS message format: ${typeof data}`));\n return;\n }\n\n try {\n const message = this.parseServerMessage(new Uint8Array(data));\n this.deliverResponse(message);\n } catch (error) {\n this.handleError(this.toError(error));\n }\n }\n\n private onError(error: unknown): void {\n if (this.connectionState < ConnectionState.CONNECTED) {\n // Try to connect several times until we succeed or run out of attempts.\n this.lastError = this.toError(error);\n this.reconnection.schedule();\n return;\n }\n\n this.handleError(this.toError(error));\n }\n\n private onClose(): void {\n this.progressConnectionState(ConnectionState.CLOSED);\n\n // Clean up abort listener to prevent memory leaks\n if (this.abortHandler) {\n this.options.abortSignal?.removeEventListener(\"abort\", this.abortHandler);\n }\n\n // If abort signal was triggered, use that as the error source\n if (this.options.abortSignal?.aborted && !this.lastError) {\n const reason = this.options.abortSignal.reason;\n if (reason instanceof Error) {\n this.lastError = reason;\n } else if (reason !== undefined) {\n this.lastError = new Error(String(reason), { cause: reason });\n } else {\n this.lastError = this.createStreamClosedError();\n }\n }\n\n if (!this.lastError) {\n this.rejectAllSendOperations(this.createStreamClosedError());\n this.resolveAllPendingResponses(); // unblock active async iterator\n } else {\n this.rejectAllPendingOperations(this.lastError);\n }\n }\n\n // === Send Queue Management ===\n\n private enqueueSend(message: ClientMsg): Promise<void> {\n if (this.sendCompleted) {\n throw new Error(\"Cannot send: stream already completed\");\n }\n\n if (this.options.abortSignal?.aborted) {\n throw new Error(\"Cannot send: stream aborted\");\n }\n\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push({ message, resolve, reject });\n this.processSendQueue();\n });\n }\n\n private processSendQueue(): void {\n if (!this.canSendMessages()) return;\n\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n this.sendQueuedMessage(queued);\n }\n }\n\n private canSendMessages(): boolean {\n return this.connectionState === ConnectionState.CONNECTED;\n }\n\n private sendQueuedMessage(queued: QueuedMessage<ClientMsg>): void {\n try {\n const ws = this.ws;\n if (!ws) {\n throw new Error(\"WebSocket is not connected\");\n }\n\n // Check if WebSocket is in a valid state for sending\n if (ws.readyState !== WebSocket.OPEN) {\n throw new Error(`WebSocket is not open (readyState: ${ws.readyState})`);\n }\n\n const binary = this.serializeClientMessage(queued.message);\n ws.send(binary);\n queued.resolve();\n } catch (error) {\n queued.reject(this.toError(error));\n }\n }\n\n private async drainSendQueue(): Promise<void> {\n const POLL_INTERVAL_MS = 5;\n\n while (this.sendQueue.length > 0) {\n await this.waitForCondition(() => this.sendQueue.length === 0, POLL_INTERVAL_MS);\n }\n }\n\n private waitForCondition(condition: () => boolean, intervalMs: number): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (this.options.abortSignal?.aborted) {\n return reject(this.toError(this.options.abortSignal.reason) ?? new Error(\"Stream aborted\"));\n }\n\n let timeoutId: ReturnType<typeof setTimeout>;\n const onAbort = () => {\n clearTimeout(timeoutId);\n reject(this.toError(this.options.abortSignal?.reason) ?? new Error(\"Stream aborted\"));\n };\n\n this.options.abortSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n const check = () => {\n if (condition() || this.isStreamEnded()) {\n this.options.abortSignal?.removeEventListener(\"abort\", onAbort);\n resolve();\n } else {\n timeoutId = setTimeout(check, intervalMs);\n }\n };\n\n check();\n });\n }\n\n // === Response Delivery ===\n\n private deliverResponse(message: ServerMsg): void {\n if (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: message, done: false });\n } else {\n this.responseQueue.push(message);\n }\n }\n\n private async *createResponseIterator(): AsyncIterator<ServerMsg> {\n while (true) {\n const result = await this.nextResponse();\n\n if (result.done) break;\n\n yield result.value;\n }\n }\n\n private nextResponse(): Promise<IteratorResult<ServerMsg>> {\n return new Promise<IteratorResult<ServerMsg>>((resolve, reject) => {\n // Fast path: message already available\n if (this.responseQueue.length > 0) {\n const message = this.responseQueue.shift()!;\n resolve({ value: message, done: false });\n return;\n }\n\n // Stream ended\n if (this.isStreamEnded()) {\n if (this.lastError) {\n reject(this.lastError);\n } else {\n resolve({ value: undefined as any, done: true });\n }\n return;\n }\n\n // Wait for next message\n this.responseResolvers.push({ resolve, reject });\n });\n }\n\n private resolveAllPendingResponses(): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: undefined as any, done: true });\n }\n }\n\n // === Error Handling ===\n\n private handleError(error: Error): void {\n this.lastError = error;\n this.close();\n }\n\n private rejectAllPendingOperations(error: Error): void {\n this.rejectAllSendOperations(error);\n this.rejectAllResponseResolvers(error);\n }\n\n private rejectAllSendOperations(error: Error): void {\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n queued.reject(error);\n }\n }\n\n private rejectAllResponseResolvers(error: Error): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.reject(error);\n }\n }\n\n private createStreamClosedError(): Error {\n if (this.options.abortSignal?.aborted) {\n const reason = this.options.abortSignal.reason;\n if (reason instanceof Error) {\n return reason;\n }\n return new Error(\"Stream aborted\", { cause: reason });\n }\n\n return new Error(\"Stream closed\");\n }\n\n // === Helpers ===\n\n private isStreamEnded(): boolean {\n return (\n this.connectionState === ConnectionState.CLOSED || this.options.abortSignal?.aborted || false\n );\n }\n\n private toError(error: unknown): Error {\n if (error instanceof Error) return error;\n if (error instanceof ErrorEvent) {\n const err = error.error;\n // undici WebSocket throws TypeError with empty message on socket close\n // (e.g., when connection is lost or server disconnects)\n if (err instanceof TypeError && !err.message) {\n return new DisconnectedError(\"WebSocket connection closed unexpectedly\");\n }\n return err instanceof Error ? err : new Error(\"WebSocket error\", { cause: error });\n }\n return new Error(String(error));\n }\n\n /**\n * Connection state progresses linearly from NEW to CLOSED and never goes back.\n * This internal contract dramatically simplifies the internal stream state management.\n *\n * If you ever feel the need to make this contract less strict, think twice.\n */\n private progressConnectionState(newState: ConnectionState): boolean {\n if (newState < this.connectionState) {\n return false;\n }\n this.connectionState = newState;\n return true;\n }\n}\n"],"mappings":"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"}
@@ -3,21 +3,17 @@ import { RetryStrategy } from "../helpers/retry_strategy.js";
3
3
  import Denque from "denque";
4
4
  import { ErrorEvent, WebSocket } from "undici";
5
5
  //#region src/core/websocket_stream.ts
6
- var ConnectionState = /* @__PURE__ */ function(ConnectionState) {
7
- ConnectionState[ConnectionState["NEW"] = 0] = "NEW";
8
- ConnectionState[ConnectionState["CONNECTING"] = 1] = "CONNECTING";
9
- ConnectionState[ConnectionState["CONNECTED"] = 2] = "CONNECTED";
10
- ConnectionState[ConnectionState["CLOSING"] = 3] = "CLOSING";
11
- ConnectionState[ConnectionState["CLOSED"] = 4] = "CLOSED";
12
- return ConnectionState;
13
- }(ConnectionState || {});
14
6
  /**
15
7
  * WebSocket-based bidirectional stream implementation for LLTransaction.
16
8
  * Implements BiDiStream interface which is compatible with DuplexStreamingCall.
17
9
  */
18
10
  var WebSocketBiDiStream = class {
11
+ url;
12
+ serializeClientMessage;
13
+ parseServerMessage;
14
+ options;
19
15
  ws = null;
20
- connectionState = ConnectionState.NEW;
16
+ connectionState = 0;
21
17
  reconnection;
22
18
  sendQueue = new Denque();
23
19
  sendCompleted = false;
@@ -42,12 +38,12 @@ var WebSocketBiDiStream = class {
42
38
  responses = { [Symbol.asyncIterator]: () => this.createResponseIterator() };
43
39
  close() {
44
40
  this.reconnection.cancel();
45
- if (this.connectionState < ConnectionState.CONNECTED) {
41
+ if (this.connectionState < 2) {
46
42
  this.ws?.close();
47
43
  this.onClose();
48
44
  return;
49
45
  }
50
- if (!this.progressConnectionState(ConnectionState.CLOSING)) return;
46
+ if (!this.progressConnectionState(3)) return;
51
47
  this.ws.close();
52
48
  }
53
49
  constructor(url, serializeClientMessage, parseServerMessage, options = {}) {
@@ -56,14 +52,15 @@ var WebSocketBiDiStream = class {
56
52
  this.parseServerMessage = parseServerMessage;
57
53
  this.options = options;
58
54
  this.onComplete = this.options.onComplete ?? ((stream) => stream.close());
59
- this.reconnection = new RetryStrategy(this.options.retryConfig ?? {}, {
55
+ const retryConfig = this.options.retryConfig ?? {};
56
+ this.reconnection = new RetryStrategy(retryConfig, {
60
57
  onRetry: () => {
61
58
  this.connect();
62
59
  },
63
60
  onMaxAttemptsReached: (error) => this.handleError(error)
64
61
  });
65
62
  if (this.options.abortSignal?.aborted) {
66
- this.progressConnectionState(ConnectionState.CLOSED);
63
+ this.progressConnectionState(4);
67
64
  return;
68
65
  }
69
66
  this.abortHandler = () => this.close();
@@ -72,7 +69,7 @@ var WebSocketBiDiStream = class {
72
69
  }
73
70
  connect() {
74
71
  if (this.options.abortSignal?.aborted) return;
75
- if (!this.progressConnectionState(ConnectionState.CONNECTING)) return;
72
+ if (!this.progressConnectionState(1)) return;
76
73
  try {
77
74
  this.ws = this.createWebSocket();
78
75
  this.ws.addEventListener("open", () => this.onOpen());
@@ -93,7 +90,7 @@ var WebSocketBiDiStream = class {
93
90
  return ws;
94
91
  }
95
92
  onOpen() {
96
- this.progressConnectionState(ConnectionState.CONNECTED);
93
+ this.progressConnectionState(2);
97
94
  this.processSendQueue();
98
95
  }
99
96
  onMessage(data) {
@@ -109,7 +106,7 @@ var WebSocketBiDiStream = class {
109
106
  }
110
107
  }
111
108
  onError(error) {
112
- if (this.connectionState < ConnectionState.CONNECTED) {
109
+ if (this.connectionState < 2) {
113
110
  this.lastError = this.toError(error);
114
111
  this.reconnection.schedule();
115
112
  return;
@@ -117,7 +114,7 @@ var WebSocketBiDiStream = class {
117
114
  this.handleError(this.toError(error));
118
115
  }
119
116
  onClose() {
120
- this.progressConnectionState(ConnectionState.CLOSED);
117
+ this.progressConnectionState(4);
121
118
  if (this.abortHandler) this.options.abortSignal?.removeEventListener("abort", this.abortHandler);
122
119
  if (this.options.abortSignal?.aborted && !this.lastError) {
123
120
  const reason = this.options.abortSignal.reason;
@@ -150,7 +147,7 @@ var WebSocketBiDiStream = class {
150
147
  }
151
148
  }
152
149
  canSendMessages() {
153
- return this.connectionState === ConnectionState.CONNECTED;
150
+ return this.connectionState === 2;
154
151
  }
155
152
  sendQueuedMessage(queued) {
156
153
  try {
@@ -252,7 +249,7 @@ var WebSocketBiDiStream = class {
252
249
  return /* @__PURE__ */ new Error("Stream closed");
253
250
  }
254
251
  isStreamEnded() {
255
- return this.connectionState === ConnectionState.CLOSED || this.options.abortSignal?.aborted || false;
252
+ return this.connectionState === 4 || this.options.abortSignal?.aborted || false;
256
253
  }
257
254
  toError(error) {
258
255
  if (error instanceof Error) return error;
@@ -1 +1 @@
1
- {"version":3,"file":"websocket_stream.js","names":[],"sources":["../../src/core/websocket_stream.ts"],"sourcesContent":["import { WebSocket, type WebSocketInit, type Dispatcher, ErrorEvent } from \"undici\";\nimport type { BiDiStream } from \"./abstract_stream\";\nimport Denque from \"denque\";\nimport type { RetryConfig } from \"../helpers/retry_strategy\";\nimport { RetryStrategy } from \"../helpers/retry_strategy\";\nimport { DisconnectedError } from \"./errors\";\n\ninterface QueuedMessage<InType extends object> {\n message: InType;\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\ninterface ResponseResolver<OutType extends object> {\n resolve: (value: IteratorResult<OutType>) => void;\n reject: (error: Error) => void;\n}\n\nenum ConnectionState {\n NEW = 0,\n CONNECTING = 1,\n CONNECTED = 2,\n CLOSING = 3,\n CLOSED = 4,\n}\n\nexport type WSStreamOptions<ClientMsg extends object, ServerMsg extends object> = {\n abortSignal?: AbortSignal;\n\n dispatcher?: Dispatcher;\n jwtToken?: string;\n retryConfig?: Partial<RetryConfig>;\n\n onComplete?: (stream: WebSocketBiDiStream<ClientMsg, ServerMsg>) => void | Promise<void>;\n};\n\n/**\n * WebSocket-based bidirectional stream implementation for LLTransaction.\n * Implements BiDiStream interface which is compatible with DuplexStreamingCall.\n */\nexport class WebSocketBiDiStream<\n ClientMsg extends object,\n ServerMsg extends object,\n> implements BiDiStream<ClientMsg, ServerMsg> {\n // Connection\n private ws: WebSocket | null = null;\n private connectionState: ConnectionState = ConnectionState.NEW;\n private readonly reconnection: RetryStrategy;\n\n // Send management\n private readonly sendQueue = new Denque<QueuedMessage<ClientMsg>>();\n private sendCompleted = false;\n private readonly onComplete: (\n stream: WebSocketBiDiStream<ClientMsg, ServerMsg>,\n ) => void | Promise<void>;\n\n // Response management\n private readonly responseQueue = new Denque<ServerMsg>();\n private responseResolvers: ResponseResolver<ServerMsg>[] = [];\n\n // Error tracking\n private lastError?: Error;\n\n // Abort listener reference for cleanup\n private readonly abortHandler?: () => void;\n\n // === Public API ===\n\n public readonly requests = {\n send: async (message: ClientMsg): Promise<void> => {\n return await this.enqueueSend(message);\n },\n\n complete: async (): Promise<void> => {\n if (this.sendCompleted) return;\n\n await this.drainSendQueue(); // ensure we sent all already queued messages before closing the stream\n try {\n await this.onComplete(this); // custom onComplete may send additional messages\n } catch {\n // When 'complete' gets called concurrently with connection break or over a broken\n // transaction stream (server decided it should drop transaction), server would close\n // connection anyway on its end. We can safely ignore error here and just continue working.\n }\n this.sendCompleted = true;\n },\n };\n\n public readonly responses: AsyncIterable<ServerMsg> = {\n [Symbol.asyncIterator]: () => this.createResponseIterator(),\n };\n\n public close(): void {\n this.reconnection.cancel();\n\n if (this.connectionState < ConnectionState.CONNECTED) {\n // Never reached CONNECTED state. ws.close() will never trigger 'close' event.\n this.ws?.close();\n this.onClose();\n return;\n }\n\n if (!this.progressConnectionState(ConnectionState.CLOSING)) return;\n this.ws!.close();\n }\n\n constructor(\n private readonly url: string,\n private readonly serializeClientMessage: (message: ClientMsg) => Uint8Array,\n private readonly parseServerMessage: (data: Uint8Array) => ServerMsg,\n private readonly options: WSStreamOptions<ClientMsg, ServerMsg> = {},\n ) {\n this.onComplete = this.options.onComplete ?? ((stream) => stream.close());\n\n const retryConfig = this.options.retryConfig ?? {};\n this.reconnection = new RetryStrategy(retryConfig, {\n onRetry: () => {\n void this.connect();\n },\n onMaxAttemptsReached: (error) => this.handleError(error),\n });\n\n if (this.options.abortSignal?.aborted) {\n this.progressConnectionState(ConnectionState.CLOSED);\n return;\n }\n\n this.abortHandler = () => this.close();\n this.options.abortSignal?.addEventListener(\"abort\", this.abortHandler, { once: true });\n this.connect();\n }\n\n // === Connection Lifecycle ===\n\n private connect(): void {\n if (this.options.abortSignal?.aborted) return;\n\n // Prevent reconnecting after first successful connection.\n if (!this.progressConnectionState(ConnectionState.CONNECTING)) return;\n\n try {\n this.ws = this.createWebSocket();\n\n this.ws.addEventListener(\"open\", () => this.onOpen());\n this.ws.addEventListener(\"message\", (event) => this.onMessage(event.data));\n this.ws.addEventListener(\"error\", (error) => this.onError(error));\n this.ws.addEventListener(\"close\", () => this.onClose());\n } catch (error) {\n this.lastError = this.toError(error);\n this.reconnection.schedule();\n }\n }\n\n private createWebSocket(): WebSocket {\n const options: WebSocketInit = {};\n\n if (this.options.jwtToken)\n options.headers = { authorization: `Bearer ${this.options.jwtToken}` };\n if (this.options.dispatcher) options.dispatcher = this.options.dispatcher;\n\n const ws = new WebSocket(this.url, options);\n ws.binaryType = \"arraybuffer\";\n return ws;\n }\n\n private onOpen(): void {\n this.progressConnectionState(ConnectionState.CONNECTED);\n this.processSendQueue();\n }\n\n private onMessage(data: unknown): void {\n if (!(data instanceof ArrayBuffer)) {\n this.handleError(new Error(`Unexpected WS message format: ${typeof data}`));\n return;\n }\n\n try {\n const message = this.parseServerMessage(new Uint8Array(data));\n this.deliverResponse(message);\n } catch (error) {\n this.handleError(this.toError(error));\n }\n }\n\n private onError(error: unknown): void {\n if (this.connectionState < ConnectionState.CONNECTED) {\n // Try to connect several times until we succeed or run out of attempts.\n this.lastError = this.toError(error);\n this.reconnection.schedule();\n return;\n }\n\n this.handleError(this.toError(error));\n }\n\n private onClose(): void {\n this.progressConnectionState(ConnectionState.CLOSED);\n\n // Clean up abort listener to prevent memory leaks\n if (this.abortHandler) {\n this.options.abortSignal?.removeEventListener(\"abort\", this.abortHandler);\n }\n\n // If abort signal was triggered, use that as the error source\n if (this.options.abortSignal?.aborted && !this.lastError) {\n const reason = this.options.abortSignal.reason;\n if (reason instanceof Error) {\n this.lastError = reason;\n } else if (reason !== undefined) {\n this.lastError = new Error(String(reason), { cause: reason });\n } else {\n this.lastError = this.createStreamClosedError();\n }\n }\n\n if (!this.lastError) {\n this.rejectAllSendOperations(this.createStreamClosedError());\n this.resolveAllPendingResponses(); // unblock active async iterator\n } else {\n this.rejectAllPendingOperations(this.lastError);\n }\n }\n\n // === Send Queue Management ===\n\n private enqueueSend(message: ClientMsg): Promise<void> {\n if (this.sendCompleted) {\n throw new Error(\"Cannot send: stream already completed\");\n }\n\n if (this.options.abortSignal?.aborted) {\n throw new Error(\"Cannot send: stream aborted\");\n }\n\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push({ message, resolve, reject });\n this.processSendQueue();\n });\n }\n\n private processSendQueue(): void {\n if (!this.canSendMessages()) return;\n\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n this.sendQueuedMessage(queued);\n }\n }\n\n private canSendMessages(): boolean {\n return this.connectionState === ConnectionState.CONNECTED;\n }\n\n private sendQueuedMessage(queued: QueuedMessage<ClientMsg>): void {\n try {\n const ws = this.ws;\n if (!ws) {\n throw new Error(\"WebSocket is not connected\");\n }\n\n // Check if WebSocket is in a valid state for sending\n if (ws.readyState !== WebSocket.OPEN) {\n throw new Error(`WebSocket is not open (readyState: ${ws.readyState})`);\n }\n\n const binary = this.serializeClientMessage(queued.message);\n ws.send(binary);\n queued.resolve();\n } catch (error) {\n queued.reject(this.toError(error));\n }\n }\n\n private async drainSendQueue(): Promise<void> {\n const POLL_INTERVAL_MS = 5;\n\n while (this.sendQueue.length > 0) {\n await this.waitForCondition(() => this.sendQueue.length === 0, POLL_INTERVAL_MS);\n }\n }\n\n private waitForCondition(condition: () => boolean, intervalMs: number): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (this.options.abortSignal?.aborted) {\n return reject(this.toError(this.options.abortSignal.reason) ?? new Error(\"Stream aborted\"));\n }\n\n let timeoutId: ReturnType<typeof setTimeout>;\n const onAbort = () => {\n clearTimeout(timeoutId);\n reject(this.toError(this.options.abortSignal?.reason) ?? new Error(\"Stream aborted\"));\n };\n\n this.options.abortSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n const check = () => {\n if (condition() || this.isStreamEnded()) {\n this.options.abortSignal?.removeEventListener(\"abort\", onAbort);\n resolve();\n } else {\n timeoutId = setTimeout(check, intervalMs);\n }\n };\n\n check();\n });\n }\n\n // === Response Delivery ===\n\n private deliverResponse(message: ServerMsg): void {\n if (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: message, done: false });\n } else {\n this.responseQueue.push(message);\n }\n }\n\n private async *createResponseIterator(): AsyncIterator<ServerMsg> {\n while (true) {\n const result = await this.nextResponse();\n\n if (result.done) break;\n\n yield result.value;\n }\n }\n\n private nextResponse(): Promise<IteratorResult<ServerMsg>> {\n return new Promise<IteratorResult<ServerMsg>>((resolve, reject) => {\n // Fast path: message already available\n if (this.responseQueue.length > 0) {\n const message = this.responseQueue.shift()!;\n resolve({ value: message, done: false });\n return;\n }\n\n // Stream ended\n if (this.isStreamEnded()) {\n if (this.lastError) {\n reject(this.lastError);\n } else {\n resolve({ value: undefined as any, done: true });\n }\n return;\n }\n\n // Wait for next message\n this.responseResolvers.push({ resolve, reject });\n });\n }\n\n private resolveAllPendingResponses(): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: undefined as any, done: true });\n }\n }\n\n // === Error Handling ===\n\n private handleError(error: Error): void {\n this.lastError = error;\n this.close();\n }\n\n private rejectAllPendingOperations(error: Error): void {\n this.rejectAllSendOperations(error);\n this.rejectAllResponseResolvers(error);\n }\n\n private rejectAllSendOperations(error: Error): void {\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n queued.reject(error);\n }\n }\n\n private rejectAllResponseResolvers(error: Error): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.reject(error);\n }\n }\n\n private createStreamClosedError(): Error {\n if (this.options.abortSignal?.aborted) {\n const reason = this.options.abortSignal.reason;\n if (reason instanceof Error) {\n return reason;\n }\n return new Error(\"Stream aborted\", { cause: reason });\n }\n\n return new Error(\"Stream closed\");\n }\n\n // === Helpers ===\n\n private isStreamEnded(): boolean {\n return (\n this.connectionState === ConnectionState.CLOSED || this.options.abortSignal?.aborted || false\n );\n }\n\n private toError(error: unknown): Error {\n if (error instanceof Error) return error;\n if (error instanceof ErrorEvent) {\n const err = error.error;\n // undici WebSocket throws TypeError with empty message on socket close\n // (e.g., when connection is lost or server disconnects)\n if (err instanceof TypeError && !err.message) {\n return new DisconnectedError(\"WebSocket connection closed unexpectedly\");\n }\n return err instanceof Error ? err : new Error(\"WebSocket error\", { cause: error });\n }\n return new Error(String(error));\n }\n\n /**\n * Connection state progresses linearly from NEW to CLOSED and never goes back.\n * This internal contract dramatically simplifies the internal stream state management.\n *\n * If you ever feel the need to make this contract less strict, think twice.\n */\n private progressConnectionState(newState: ConnectionState): boolean {\n if (newState < this.connectionState) {\n return false;\n }\n this.connectionState = newState;\n return true;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"websocket_stream.js","names":[],"sources":["../../src/core/websocket_stream.ts"],"sourcesContent":["import { WebSocket, type WebSocketInit, type Dispatcher, ErrorEvent } from \"undici\";\nimport type { BiDiStream } from \"./abstract_stream\";\nimport Denque from \"denque\";\nimport type { RetryConfig } from \"../helpers/retry_strategy\";\nimport { RetryStrategy } from \"../helpers/retry_strategy\";\nimport { DisconnectedError } from \"./errors\";\n\ninterface QueuedMessage<InType extends object> {\n message: InType;\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\ninterface ResponseResolver<OutType extends object> {\n resolve: (value: IteratorResult<OutType>) => void;\n reject: (error: Error) => void;\n}\n\nenum ConnectionState {\n NEW = 0,\n CONNECTING = 1,\n CONNECTED = 2,\n CLOSING = 3,\n CLOSED = 4,\n}\n\nexport type WSStreamOptions<ClientMsg extends object, ServerMsg extends object> = {\n abortSignal?: AbortSignal;\n\n dispatcher?: Dispatcher;\n jwtToken?: string;\n retryConfig?: Partial<RetryConfig>;\n\n onComplete?: (stream: WebSocketBiDiStream<ClientMsg, ServerMsg>) => void | Promise<void>;\n};\n\n/**\n * WebSocket-based bidirectional stream implementation for LLTransaction.\n * Implements BiDiStream interface which is compatible with DuplexStreamingCall.\n */\nexport class WebSocketBiDiStream<\n ClientMsg extends object,\n ServerMsg extends object,\n> implements BiDiStream<ClientMsg, ServerMsg> {\n // Connection\n private ws: WebSocket | null = null;\n private connectionState: ConnectionState = ConnectionState.NEW;\n private readonly reconnection: RetryStrategy;\n\n // Send management\n private readonly sendQueue = new Denque<QueuedMessage<ClientMsg>>();\n private sendCompleted = false;\n private readonly onComplete: (\n stream: WebSocketBiDiStream<ClientMsg, ServerMsg>,\n ) => void | Promise<void>;\n\n // Response management\n private readonly responseQueue = new Denque<ServerMsg>();\n private responseResolvers: ResponseResolver<ServerMsg>[] = [];\n\n // Error tracking\n private lastError?: Error;\n\n // Abort listener reference for cleanup\n private readonly abortHandler?: () => void;\n\n // === Public API ===\n\n public readonly requests = {\n send: async (message: ClientMsg): Promise<void> => {\n return await this.enqueueSend(message);\n },\n\n complete: async (): Promise<void> => {\n if (this.sendCompleted) return;\n\n await this.drainSendQueue(); // ensure we sent all already queued messages before closing the stream\n try {\n await this.onComplete(this); // custom onComplete may send additional messages\n } catch {\n // When 'complete' gets called concurrently with connection break or over a broken\n // transaction stream (server decided it should drop transaction), server would close\n // connection anyway on its end. We can safely ignore error here and just continue working.\n }\n this.sendCompleted = true;\n },\n };\n\n public readonly responses: AsyncIterable<ServerMsg> = {\n [Symbol.asyncIterator]: () => this.createResponseIterator(),\n };\n\n public close(): void {\n this.reconnection.cancel();\n\n if (this.connectionState < ConnectionState.CONNECTED) {\n // Never reached CONNECTED state. ws.close() will never trigger 'close' event.\n this.ws?.close();\n this.onClose();\n return;\n }\n\n if (!this.progressConnectionState(ConnectionState.CLOSING)) return;\n this.ws!.close();\n }\n\n constructor(\n private readonly url: string,\n private readonly serializeClientMessage: (message: ClientMsg) => Uint8Array,\n private readonly parseServerMessage: (data: Uint8Array) => ServerMsg,\n private readonly options: WSStreamOptions<ClientMsg, ServerMsg> = {},\n ) {\n this.onComplete = this.options.onComplete ?? ((stream) => stream.close());\n\n const retryConfig = this.options.retryConfig ?? {};\n this.reconnection = new RetryStrategy(retryConfig, {\n onRetry: () => {\n void this.connect();\n },\n onMaxAttemptsReached: (error) => this.handleError(error),\n });\n\n if (this.options.abortSignal?.aborted) {\n this.progressConnectionState(ConnectionState.CLOSED);\n return;\n }\n\n this.abortHandler = () => this.close();\n this.options.abortSignal?.addEventListener(\"abort\", this.abortHandler, { once: true });\n this.connect();\n }\n\n // === Connection Lifecycle ===\n\n private connect(): void {\n if (this.options.abortSignal?.aborted) return;\n\n // Prevent reconnecting after first successful connection.\n if (!this.progressConnectionState(ConnectionState.CONNECTING)) return;\n\n try {\n this.ws = this.createWebSocket();\n\n this.ws.addEventListener(\"open\", () => this.onOpen());\n this.ws.addEventListener(\"message\", (event) => this.onMessage(event.data));\n this.ws.addEventListener(\"error\", (error) => this.onError(error));\n this.ws.addEventListener(\"close\", () => this.onClose());\n } catch (error) {\n this.lastError = this.toError(error);\n this.reconnection.schedule();\n }\n }\n\n private createWebSocket(): WebSocket {\n const options: WebSocketInit = {};\n\n if (this.options.jwtToken)\n options.headers = { authorization: `Bearer ${this.options.jwtToken}` };\n if (this.options.dispatcher) options.dispatcher = this.options.dispatcher;\n\n const ws = new WebSocket(this.url, options);\n ws.binaryType = \"arraybuffer\";\n return ws;\n }\n\n private onOpen(): void {\n this.progressConnectionState(ConnectionState.CONNECTED);\n this.processSendQueue();\n }\n\n private onMessage(data: unknown): void {\n if (!(data instanceof ArrayBuffer)) {\n this.handleError(new Error(`Unexpected WS message format: ${typeof data}`));\n return;\n }\n\n try {\n const message = this.parseServerMessage(new Uint8Array(data));\n this.deliverResponse(message);\n } catch (error) {\n this.handleError(this.toError(error));\n }\n }\n\n private onError(error: unknown): void {\n if (this.connectionState < ConnectionState.CONNECTED) {\n // Try to connect several times until we succeed or run out of attempts.\n this.lastError = this.toError(error);\n this.reconnection.schedule();\n return;\n }\n\n this.handleError(this.toError(error));\n }\n\n private onClose(): void {\n this.progressConnectionState(ConnectionState.CLOSED);\n\n // Clean up abort listener to prevent memory leaks\n if (this.abortHandler) {\n this.options.abortSignal?.removeEventListener(\"abort\", this.abortHandler);\n }\n\n // If abort signal was triggered, use that as the error source\n if (this.options.abortSignal?.aborted && !this.lastError) {\n const reason = this.options.abortSignal.reason;\n if (reason instanceof Error) {\n this.lastError = reason;\n } else if (reason !== undefined) {\n this.lastError = new Error(String(reason), { cause: reason });\n } else {\n this.lastError = this.createStreamClosedError();\n }\n }\n\n if (!this.lastError) {\n this.rejectAllSendOperations(this.createStreamClosedError());\n this.resolveAllPendingResponses(); // unblock active async iterator\n } else {\n this.rejectAllPendingOperations(this.lastError);\n }\n }\n\n // === Send Queue Management ===\n\n private enqueueSend(message: ClientMsg): Promise<void> {\n if (this.sendCompleted) {\n throw new Error(\"Cannot send: stream already completed\");\n }\n\n if (this.options.abortSignal?.aborted) {\n throw new Error(\"Cannot send: stream aborted\");\n }\n\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push({ message, resolve, reject });\n this.processSendQueue();\n });\n }\n\n private processSendQueue(): void {\n if (!this.canSendMessages()) return;\n\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n this.sendQueuedMessage(queued);\n }\n }\n\n private canSendMessages(): boolean {\n return this.connectionState === ConnectionState.CONNECTED;\n }\n\n private sendQueuedMessage(queued: QueuedMessage<ClientMsg>): void {\n try {\n const ws = this.ws;\n if (!ws) {\n throw new Error(\"WebSocket is not connected\");\n }\n\n // Check if WebSocket is in a valid state for sending\n if (ws.readyState !== WebSocket.OPEN) {\n throw new Error(`WebSocket is not open (readyState: ${ws.readyState})`);\n }\n\n const binary = this.serializeClientMessage(queued.message);\n ws.send(binary);\n queued.resolve();\n } catch (error) {\n queued.reject(this.toError(error));\n }\n }\n\n private async drainSendQueue(): Promise<void> {\n const POLL_INTERVAL_MS = 5;\n\n while (this.sendQueue.length > 0) {\n await this.waitForCondition(() => this.sendQueue.length === 0, POLL_INTERVAL_MS);\n }\n }\n\n private waitForCondition(condition: () => boolean, intervalMs: number): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (this.options.abortSignal?.aborted) {\n return reject(this.toError(this.options.abortSignal.reason) ?? new Error(\"Stream aborted\"));\n }\n\n let timeoutId: ReturnType<typeof setTimeout>;\n const onAbort = () => {\n clearTimeout(timeoutId);\n reject(this.toError(this.options.abortSignal?.reason) ?? new Error(\"Stream aborted\"));\n };\n\n this.options.abortSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n const check = () => {\n if (condition() || this.isStreamEnded()) {\n this.options.abortSignal?.removeEventListener(\"abort\", onAbort);\n resolve();\n } else {\n timeoutId = setTimeout(check, intervalMs);\n }\n };\n\n check();\n });\n }\n\n // === Response Delivery ===\n\n private deliverResponse(message: ServerMsg): void {\n if (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: message, done: false });\n } else {\n this.responseQueue.push(message);\n }\n }\n\n private async *createResponseIterator(): AsyncIterator<ServerMsg> {\n while (true) {\n const result = await this.nextResponse();\n\n if (result.done) break;\n\n yield result.value;\n }\n }\n\n private nextResponse(): Promise<IteratorResult<ServerMsg>> {\n return new Promise<IteratorResult<ServerMsg>>((resolve, reject) => {\n // Fast path: message already available\n if (this.responseQueue.length > 0) {\n const message = this.responseQueue.shift()!;\n resolve({ value: message, done: false });\n return;\n }\n\n // Stream ended\n if (this.isStreamEnded()) {\n if (this.lastError) {\n reject(this.lastError);\n } else {\n resolve({ value: undefined as any, done: true });\n }\n return;\n }\n\n // Wait for next message\n this.responseResolvers.push({ resolve, reject });\n });\n }\n\n private resolveAllPendingResponses(): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: undefined as any, done: true });\n }\n }\n\n // === Error Handling ===\n\n private handleError(error: Error): void {\n this.lastError = error;\n this.close();\n }\n\n private rejectAllPendingOperations(error: Error): void {\n this.rejectAllSendOperations(error);\n this.rejectAllResponseResolvers(error);\n }\n\n private rejectAllSendOperations(error: Error): void {\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n queued.reject(error);\n }\n }\n\n private rejectAllResponseResolvers(error: Error): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.reject(error);\n }\n }\n\n private createStreamClosedError(): Error {\n if (this.options.abortSignal?.aborted) {\n const reason = this.options.abortSignal.reason;\n if (reason instanceof Error) {\n return reason;\n }\n return new Error(\"Stream aborted\", { cause: reason });\n }\n\n return new Error(\"Stream closed\");\n }\n\n // === Helpers ===\n\n private isStreamEnded(): boolean {\n return (\n this.connectionState === ConnectionState.CLOSED || this.options.abortSignal?.aborted || false\n );\n }\n\n private toError(error: unknown): Error {\n if (error instanceof Error) return error;\n if (error instanceof ErrorEvent) {\n const err = error.error;\n // undici WebSocket throws TypeError with empty message on socket close\n // (e.g., when connection is lost or server disconnects)\n if (err instanceof TypeError && !err.message) {\n return new DisconnectedError(\"WebSocket connection closed unexpectedly\");\n }\n return err instanceof Error ? err : new Error(\"WebSocket error\", { cause: error });\n }\n return new Error(String(error));\n }\n\n /**\n * Connection state progresses linearly from NEW to CLOSED and never goes back.\n * This internal contract dramatically simplifies the internal stream state management.\n *\n * If you ever feel the need to make this contract less strict, think twice.\n */\n private progressConnectionState(newState: ConnectionState): boolean {\n if (newState < this.connectionState) {\n return false;\n }\n this.connectionState = newState;\n return true;\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"wire.d.ts","names":[],"sources":["../../src/core/wire.ts"],"mappings":";;;;;;;;AASA;;KAAY,cAAA;EACV,IAAA;EACA,MAAA,EAAQ,cAAA;EACR,UAAA,EAAY,UAAA;EACZ,WAAA,EAAa,UAAA;AAAA;AAAA,KAGH,cAAA;EACV,IAAA;EACA,SAAA,EAAW,aAAA;AAAA;AAAA,KAGD,cAAA,GAAiB,cAAA,GAAiB,cAAA;;;;;AAL9C;UAciB,kBAAA;EACf,GAAA,IAAO,MAAA;AAAA;;;;UAMQ,yBAAA;EACf,wBAAA,SACE,iBAAA,GAAoB,SAAA,EAAW,cAAA,KAAmB,MAAA,GACjD,kBAAA,CAAmB,MAAA;AAAA"}
1
+ {"version":3,"file":"wire.d.ts","names":[],"sources":["../../src/core/wire.ts"],"mappings":";;;;;;;;AASA;;KAAY,cAAA;EACV,IAAA;EACA,MAAA,EAAQ,cAAA;EACR,UAAA,EAAY,UAAA;EACZ,WAAA,EAAa,UAAA;AAAA;AAAA,KAGH,cAAA;EACV,IAAA;EACA,SAAA,EAAW,aAAa;AAAA;AAAA,KAGd,cAAA,GAAiB,cAAA,GAAiB,cAAc;;;;AARnC;AAGzB;UAciB,kBAAA;EACf,GAAA,IAAO,MAAM;AAAA;;;;UAME,yBAAA;EACf,wBAAA,SACE,iBAAA,GAAoB,SAAA,EAAW,cAAA,KAAmB,MAAA,GACjD,kBAAA,CAAmB,MAAA;AAAA"}
@@ -108,13 +108,38 @@ function unwrapHolder(tx, ref) {
108
108
  }
109
109
  //#endregion
110
110
  exports.ClientRoot = ClientRoot;
111
+ exports.EphHolder = EphHolder;
112
+ exports.EphStdMap = EphStdMap;
113
+ exports.Holder = Holder;
114
+ exports.JsonArray = JsonArray;
115
+ exports.JsonBool = JsonBool;
111
116
  exports.JsonGzObject = JsonGzObject;
117
+ exports.JsonNull = JsonNull;
118
+ exports.JsonNumber = JsonNumber;
112
119
  exports.JsonObject = JsonObject;
120
+ exports.JsonString = JsonString;
121
+ exports.RNull = RNull;
122
+ exports.StdMap = StdMap;
123
+ exports.StructTestResource = StructTestResource;
124
+ exports.ValueTestResource = ValueTestResource;
125
+ exports.createPlArray = createPlArray;
126
+ exports.createPlBool = createPlBool;
127
+ exports.createPlMap = createPlMap;
128
+ exports.createPlNull = createPlNull;
129
+ exports.createPlNumber = createPlNumber;
130
+ exports.createPlObject = createPlObject;
131
+ exports.createPlString = createPlString;
132
+ exports.futureRecord = futureRecord;
133
+ exports.plEntries = plEntries;
134
+ exports.plEntry = plEntry;
113
135
  Object.defineProperty(exports, "pl_exports", {
114
136
  enumerable: true,
115
137
  get: function() {
116
138
  return pl_exports;
117
139
  }
118
140
  });
141
+ exports.unwrapHolder = unwrapHolder;
142
+ exports.wrapInEphHolder = wrapInEphHolder;
143
+ exports.wrapInHolder = wrapInHolder;
119
144
 
120
145
  //# sourceMappingURL=pl.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pl.cjs","names":["field"],"sources":["../../src/helpers/pl.ts"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * This file is exported under Pl \"namespace\" to the client users.\n *\n * It defines well known pl types, and methods to manipulate them.\n *\n */\n\nimport type { FutureFieldType, ResourceType } from \"../core/types\";\nimport type { AnyRef, FieldRef, PlTransaction, ResourceRef } from \"../core/transaction\";\nimport { field } from \"../core/transaction\";\n\nfunction rt(name: string, version: string): ResourceType {\n return { name, version };\n}\n\nexport const ClientRoot = rt(\"ClientRoot\", \"1\");\n\nexport const StructTestResource = rt(\"StructTest\", \"1\");\nexport const ValueTestResource = rt(\"ValueTest\", \"1\");\n\nexport const JsonString = rt(\"json/string\", \"1\");\nexport const JsonBool = rt(\"json/bool\", \"1\");\nexport const JsonObject = rt(\"json/object\", \"1\");\nexport const JsonGzObject = rt(\"json-gz/object\", \"1\");\nexport const JsonArray = rt(\"json/array\", \"1\");\nexport const JsonNumber = rt(\"json/number\", \"1\");\nexport const JsonNull = rt(\"json/null\", \"1\");\n\nexport const RNull = rt(\"Null\", \"1\");\n\nexport const EphStdMap: ResourceType = rt(\"EphStdMap\", \"1\");\nexport const StdMap: ResourceType = rt(\"StdMap\", \"1\");\n\n//\n// Standard value resources\n//\n\nexport function createPlNull(tx: PlTransaction): ResourceRef {\n return tx.createValue(JsonNull, Buffer.from(JSON.stringify(null)));\n}\n\nexport function createPlBool(tx: PlTransaction, val: boolean): ResourceRef {\n return tx.createValue(JsonBool, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlNumber(tx: PlTransaction, val: number): ResourceRef {\n return tx.createValue(JsonNumber, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlString(tx: PlTransaction, val: string): ResourceRef {\n return tx.createValue(JsonString, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlArray(tx: PlTransaction, val: any[]): ResourceRef {\n return tx.createValue(JsonArray, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlObject(tx: PlTransaction, val: object): ResourceRef {\n return tx.createValue(JsonObject, Buffer.from(JSON.stringify(val)));\n}\n\n//\n// Pl Map\n//\n\nexport type PlRecordEntry<Key extends string = string, Ref extends AnyRef = AnyRef> = [Key, Ref];\n\nexport type PlRecord<Key extends string = string, Ref extends AnyRef = AnyRef> = Record<Key, Ref>;\n\nexport function plEntry<Key extends string = string, Ref extends AnyRef = AnyRef>(\n key: Key,\n ref: Ref,\n): PlRecordEntry<Key, Ref> {\n return [key, ref];\n}\n\nexport function plEntries<Key extends string = string, Ref extends AnyRef = AnyRef>(\n record: PlRecord<Key, Ref>,\n fields?: Key[],\n): PlRecordEntry<Key, Ref>[] {\n return fields === undefined\n ? (Object.entries(record) as PlRecordEntry<Key, Ref>[])\n : fields.map((key) => plEntry(key, record[key]));\n}\n\n/** Helper method to build standard pl map from a set of entries */\nexport function createPlMap(\n tx: PlTransaction,\n entries: PlRecordEntry[] | PlRecord,\n ephemeral: boolean,\n type?: ResourceType,\n): ResourceRef {\n const actualType = type ?? (ephemeral ? EphStdMap : StdMap);\n const rId = ephemeral ? tx.createEphemeral(actualType) : tx.createStruct(actualType);\n\n for (const [name, value] of Array.isArray(entries) ? entries : plEntries(entries))\n tx.createField(field(rId, name), \"Input\", value);\n\n tx.lock(rId);\n\n return rId;\n}\n\nexport function futureRecord<Key extends string>(\n tx: PlTransaction,\n rId: AnyRef,\n keys: Key[],\n fieldType: FutureFieldType,\n prefix: string = \"\",\n): PlRecord<Key, FieldRef> {\n return Object.fromEntries(\n keys.map((k) => plEntry(k, tx.getFutureFieldValue(rId, `${prefix}${k}`, fieldType))),\n ) as PlRecord<Key, FieldRef>;\n}\n\n//\n// Holder\n//\n\n/** Name of the field in block holder, that references the actual block-pack. */\nexport const Holder = StdMap;\nexport const EphHolder = EphStdMap;\nexport const HolderRefField = \"ref\";\n\nexport function wrapInHolder(tx: PlTransaction, ref: AnyRef): ResourceRef {\n const holder = tx.createStruct(Holder);\n const mainHolderField = field(holder, HolderRefField);\n tx.createField(mainHolderField, \"Input\", ref);\n tx.lock(holder);\n return holder;\n}\n\nexport function wrapInEphHolder(tx: PlTransaction, ref: AnyRef): ResourceRef {\n const holder = tx.createEphemeral(EphHolder);\n const mainHolderField = field(holder, HolderRefField);\n tx.createField(mainHolderField, \"Input\", ref);\n tx.lock(holder);\n return holder;\n}\n\nexport function unwrapHolder(tx: PlTransaction, ref: AnyRef): FieldRef {\n return tx.getFutureFieldValue(ref, HolderRefField, \"Input\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pl.cjs","names":["field"],"sources":["../../src/helpers/pl.ts"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * This file is exported under Pl \"namespace\" to the client users.\n *\n * It defines well known pl types, and methods to manipulate them.\n *\n */\n\nimport type { FutureFieldType, ResourceType } from \"../core/types\";\nimport type { AnyRef, FieldRef, PlTransaction, ResourceRef } from \"../core/transaction\";\nimport { field } from \"../core/transaction\";\n\nfunction rt(name: string, version: string): ResourceType {\n return { name, version };\n}\n\nexport const ClientRoot = rt(\"ClientRoot\", \"1\");\n\nexport const StructTestResource = rt(\"StructTest\", \"1\");\nexport const ValueTestResource = rt(\"ValueTest\", \"1\");\n\nexport const JsonString = rt(\"json/string\", \"1\");\nexport const JsonBool = rt(\"json/bool\", \"1\");\nexport const JsonObject = rt(\"json/object\", \"1\");\nexport const JsonGzObject = rt(\"json-gz/object\", \"1\");\nexport const JsonArray = rt(\"json/array\", \"1\");\nexport const JsonNumber = rt(\"json/number\", \"1\");\nexport const JsonNull = rt(\"json/null\", \"1\");\n\nexport const RNull = rt(\"Null\", \"1\");\n\nexport const EphStdMap: ResourceType = rt(\"EphStdMap\", \"1\");\nexport const StdMap: ResourceType = rt(\"StdMap\", \"1\");\n\n//\n// Standard value resources\n//\n\nexport function createPlNull(tx: PlTransaction): ResourceRef {\n return tx.createValue(JsonNull, Buffer.from(JSON.stringify(null)));\n}\n\nexport function createPlBool(tx: PlTransaction, val: boolean): ResourceRef {\n return tx.createValue(JsonBool, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlNumber(tx: PlTransaction, val: number): ResourceRef {\n return tx.createValue(JsonNumber, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlString(tx: PlTransaction, val: string): ResourceRef {\n return tx.createValue(JsonString, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlArray(tx: PlTransaction, val: any[]): ResourceRef {\n return tx.createValue(JsonArray, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlObject(tx: PlTransaction, val: object): ResourceRef {\n return tx.createValue(JsonObject, Buffer.from(JSON.stringify(val)));\n}\n\n//\n// Pl Map\n//\n\nexport type PlRecordEntry<Key extends string = string, Ref extends AnyRef = AnyRef> = [Key, Ref];\n\nexport type PlRecord<Key extends string = string, Ref extends AnyRef = AnyRef> = Record<Key, Ref>;\n\nexport function plEntry<Key extends string = string, Ref extends AnyRef = AnyRef>(\n key: Key,\n ref: Ref,\n): PlRecordEntry<Key, Ref> {\n return [key, ref];\n}\n\nexport function plEntries<Key extends string = string, Ref extends AnyRef = AnyRef>(\n record: PlRecord<Key, Ref>,\n fields?: Key[],\n): PlRecordEntry<Key, Ref>[] {\n return fields === undefined\n ? (Object.entries(record) as PlRecordEntry<Key, Ref>[])\n : fields.map((key) => plEntry(key, record[key]));\n}\n\n/** Helper method to build standard pl map from a set of entries */\nexport function createPlMap(\n tx: PlTransaction,\n entries: PlRecordEntry[] | PlRecord,\n ephemeral: boolean,\n type?: ResourceType,\n): ResourceRef {\n const actualType = type ?? (ephemeral ? EphStdMap : StdMap);\n const rId = ephemeral ? tx.createEphemeral(actualType) : tx.createStruct(actualType);\n\n for (const [name, value] of Array.isArray(entries) ? entries : plEntries(entries))\n tx.createField(field(rId, name), \"Input\", value);\n\n tx.lock(rId);\n\n return rId;\n}\n\nexport function futureRecord<Key extends string>(\n tx: PlTransaction,\n rId: AnyRef,\n keys: Key[],\n fieldType: FutureFieldType,\n prefix: string = \"\",\n): PlRecord<Key, FieldRef> {\n return Object.fromEntries(\n keys.map((k) => plEntry(k, tx.getFutureFieldValue(rId, `${prefix}${k}`, fieldType))),\n ) as PlRecord<Key, FieldRef>;\n}\n\n//\n// Holder\n//\n\n/** Name of the field in block holder, that references the actual block-pack. */\nexport const Holder = StdMap;\nexport const EphHolder = EphStdMap;\nexport const HolderRefField = \"ref\";\n\nexport function wrapInHolder(tx: PlTransaction, ref: AnyRef): ResourceRef {\n const holder = tx.createStruct(Holder);\n const mainHolderField = field(holder, HolderRefField);\n tx.createField(mainHolderField, \"Input\", ref);\n tx.lock(holder);\n return holder;\n}\n\nexport function wrapInEphHolder(tx: PlTransaction, ref: AnyRef): ResourceRef {\n const holder = tx.createEphemeral(EphHolder);\n const mainHolderField = field(holder, HolderRefField);\n tx.createField(mainHolderField, \"Input\", ref);\n tx.lock(holder);\n return holder;\n}\n\nexport function unwrapHolder(tx: PlTransaction, ref: AnyRef): FieldRef {\n return tx.getFutureFieldValue(ref, HolderRefField, \"Input\");\n}\n"],"mappings":"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"}
@@ -39,5 +39,5 @@ declare function wrapInHolder(tx: PlTransaction, ref: AnyRef): ResourceRef;
39
39
  declare function wrapInEphHolder(tx: PlTransaction, ref: AnyRef): ResourceRef;
40
40
  declare function unwrapHolder(tx: PlTransaction, ref: AnyRef): FieldRef;
41
41
  //#endregion
42
- export { pl_d_exports };
42
+ export { ClientRoot, EphHolder, EphStdMap, Holder, HolderRefField, JsonArray, JsonBool, JsonGzObject, JsonNull, JsonNumber, JsonObject, JsonString, PlRecord, PlRecordEntry, RNull, StdMap, StructTestResource, ValueTestResource, createPlArray, createPlBool, createPlMap, createPlNull, createPlNumber, createPlObject, createPlString, futureRecord, plEntries, plEntry, pl_d_exports, unwrapHolder, wrapInEphHolder, wrapInHolder };
43
43
  //# sourceMappingURL=pl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pl.d.ts","names":[],"sources":["../../src/helpers/pl.ts"],"mappings":";;;;;;;cAiBa,UAAA,EAAU,YAAA;AAAA,cAEV,kBAAA,EAAkB,YAAA;AAAA,cAClB,iBAAA,EAAiB,YAAA;AAAA,cAEjB,UAAA,EAAU,YAAA;AAAA,cACV,QAAA,EAAQ,YAAA;AAAA,cACR,UAAA,EAAU,YAAA;AAAA,cACV,YAAA,EAAY,YAAA;AAAA,cACZ,SAAA,EAAS,YAAA;AAAA,cACT,UAAA,EAAU,YAAA;AAAA,cACV,QAAA,EAAQ,YAAA;AAAA,cAER,KAAA,EAAK,YAAA;AAAA,cAEL,SAAA,EAAW,YAAA;AAAA,cACX,MAAA,EAAQ,YAAA;AAAA,iBAML,YAAA,CAAa,EAAA,EAAI,aAAA,GAAgB,WAAA;AAAA,iBAIjC,YAAA,CAAa,EAAA,EAAI,aAAA,EAAe,GAAA,YAAe,WAAA;AAAA,iBAI/C,cAAA,CAAe,EAAA,EAAI,aAAA,EAAe,GAAA,WAAc,WAAA;AAAA,iBAIhD,cAAA,CAAe,EAAA,EAAI,aAAA,EAAe,GAAA,WAAc,WAAA;AAAA,iBAIhD,aAAA,CAAc,EAAA,EAAI,aAAA,EAAe,GAAA,UAAa,WAAA;AAAA,iBAI9C,cAAA,CAAe,EAAA,EAAI,aAAA,EAAe,GAAA,WAAc,WAAA;AAAA,KAQpD,aAAA,0CAAuD,MAAA,GAAS,MAAA,KAAW,GAAA,EAAK,GAAA;AAAA,KAEhF,QAAA,0CAAkD,MAAA,GAAS,MAAA,IAAU,MAAA,CAAO,GAAA,EAAK,GAAA;AAAA,iBAE7E,OAAA,0CAAiD,MAAA,GAAS,MAAA,CAAA,CACxE,GAAA,EAAK,GAAA,EACL,GAAA,EAAK,GAAA,GACJ,aAAA,CAAc,GAAA,EAAK,GAAA;AAAA,iBAIN,SAAA,0CAAmD,MAAA,GAAS,MAAA,CAAA,CAC1E,MAAA,EAAQ,QAAA,CAAS,GAAA,EAAK,GAAA,GACtB,MAAA,GAAS,GAAA,KACR,aAAA,CAAc,GAAA,EAAK,GAAA;;iBAON,WAAA,CACd,EAAA,EAAI,aAAA,EACJ,OAAA,EAAS,aAAA,KAAkB,QAAA,EAC3B,SAAA,WACA,IAAA,GAAO,YAAA,GACN,WAAA;AAAA,iBAYa,YAAA,oBAAA,CACd,EAAA,EAAI,aAAA,EACJ,GAAA,EAAK,MAAA,EACL,IAAA,EAAM,GAAA,IACN,SAAA,EAAW,eAAA,EACX,MAAA,YACC,QAAA,CAAS,GAAA,EAAK,QAAA;;cAWJ,MAAA,EAAM,YAAA;AAAA,cACN,SAAA,EAAS,YAAA;AAAA,cACT,cAAA;AAAA,iBAEG,YAAA,CAAa,EAAA,EAAI,aAAA,EAAe,GAAA,EAAK,MAAA,GAAS,WAAA;AAAA,iBAQ9C,eAAA,CAAgB,EAAA,EAAI,aAAA,EAAe,GAAA,EAAK,MAAA,GAAS,WAAA;AAAA,iBAQjD,YAAA,CAAa,EAAA,EAAI,aAAA,EAAe,GAAA,EAAK,MAAA,GAAS,QAAA"}
1
+ {"version":3,"file":"pl.d.ts","names":[],"sources":["../../src/helpers/pl.ts"],"mappings":";;;;;;;cAiBa,UAAA,EAAU,YAAwB;AAAA,cAElC,kBAAA,EAAkB,YAAwB;AAAA,cAC1C,iBAAA,EAAiB,YAAuB;AAAA,cAExC,UAAA,EAAU,YAAyB;AAAA,cACnC,QAAA,EAAQ,YAAuB;AAAA,cAC/B,UAAA,EAAU,YAAyB;AAAA,cACnC,YAAA,EAAY,YAA4B;AAAA,cACxC,SAAA,EAAS,YAAwB;AAAA,cACjC,UAAA,EAAU,YAAyB;AAAA,cACnC,QAAA,EAAQ,YAAuB;AAAA,cAE/B,KAAA,EAAK,YAAkB;AAAA,cAEvB,SAAA,EAAW,YAAmC;AAAA,cAC9C,MAAA,EAAQ,YAAgC;AAAA,iBAMrC,YAAA,CAAa,EAAA,EAAI,aAAA,GAAgB,WAAW;AAAA,iBAI5C,YAAA,CAAa,EAAA,EAAI,aAAA,EAAe,GAAA,YAAe,WAAW;AAAA,iBAI1D,cAAA,CAAe,EAAA,EAAI,aAAA,EAAe,GAAA,WAAc,WAAW;AAAA,iBAI3D,cAAA,CAAe,EAAA,EAAI,aAAA,EAAe,GAAA,WAAc,WAAW;AAAA,iBAI3D,aAAA,CAAc,EAAA,EAAI,aAAA,EAAe,GAAA,UAAa,WAAW;AAAA,iBAIzD,cAAA,CAAe,EAAA,EAAI,aAAA,EAAe,GAAA,WAAc,WAAW;AAAA,KAQ/D,aAAA,0CAAuD,MAAA,GAAS,MAAA,KAAW,GAAA,EAAK,GAAA;AAAA,KAEhF,QAAA,0CAAkD,MAAA,GAAS,MAAA,IAAU,MAAA,CAAO,GAAA,EAAK,GAAA;AAAA,iBAE7E,OAAA,0CAAiD,MAAA,GAAS,MAAA,EACxE,GAAA,EAAK,GAAA,EACL,GAAA,EAAK,GAAA,GACJ,aAAA,CAAc,GAAA,EAAK,GAAA;AAAA,iBAIN,SAAA,0CAAmD,MAAA,GAAS,MAAA,EAC1E,MAAA,EAAQ,QAAA,CAAS,GAAA,EAAK,GAAA,GACtB,MAAA,GAAS,GAAA,KACR,aAAA,CAAc,GAAA,EAAK,GAAA;;iBAON,WAAA,CACd,EAAA,EAAI,aAAA,EACJ,OAAA,EAAS,aAAA,KAAkB,QAAA,EAC3B,SAAA,WACA,IAAA,GAAO,YAAA,GACN,WAAA;AAAA,iBAYa,YAAA,qBACd,EAAA,EAAI,aAAA,EACJ,GAAA,EAAK,MAAA,EACL,IAAA,EAAM,GAAA,IACN,SAAA,EAAW,eAAA,EACX,MAAA,YACC,QAAA,CAAS,GAAA,EAAK,QAAA;;cAWJ,MAAA,EAAM,YAAS;AAAA,cACf,SAAA,EAAS,YAAY;AAAA,cACrB,cAAA;AAAA,iBAEG,YAAA,CAAa,EAAA,EAAI,aAAA,EAAe,GAAA,EAAK,MAAA,GAAS,WAAA;AAAA,iBAQ9C,eAAA,CAAgB,EAAA,EAAI,aAAA,EAAe,GAAA,EAAK,MAAA,GAAS,WAAA;AAAA,iBAQjD,YAAA,CAAa,EAAA,EAAI,aAAA,EAAe,GAAA,EAAK,MAAA,GAAS,QAAA"}
@@ -107,6 +107,6 @@ function unwrapHolder(tx, ref) {
107
107
  return tx.getFutureFieldValue(ref, "ref", "Input");
108
108
  }
109
109
  //#endregion
110
- export { ClientRoot, JsonGzObject, JsonObject, pl_exports };
110
+ export { ClientRoot, EphHolder, EphStdMap, Holder, JsonArray, JsonBool, JsonGzObject, JsonNull, JsonNumber, JsonObject, JsonString, RNull, StdMap, StructTestResource, ValueTestResource, createPlArray, createPlBool, createPlMap, createPlNull, createPlNumber, createPlObject, createPlString, futureRecord, plEntries, plEntry, pl_exports, unwrapHolder, wrapInEphHolder, wrapInHolder };
111
111
 
112
112
  //# sourceMappingURL=pl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pl.js","names":[],"sources":["../../src/helpers/pl.ts"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * This file is exported under Pl \"namespace\" to the client users.\n *\n * It defines well known pl types, and methods to manipulate them.\n *\n */\n\nimport type { FutureFieldType, ResourceType } from \"../core/types\";\nimport type { AnyRef, FieldRef, PlTransaction, ResourceRef } from \"../core/transaction\";\nimport { field } from \"../core/transaction\";\n\nfunction rt(name: string, version: string): ResourceType {\n return { name, version };\n}\n\nexport const ClientRoot = rt(\"ClientRoot\", \"1\");\n\nexport const StructTestResource = rt(\"StructTest\", \"1\");\nexport const ValueTestResource = rt(\"ValueTest\", \"1\");\n\nexport const JsonString = rt(\"json/string\", \"1\");\nexport const JsonBool = rt(\"json/bool\", \"1\");\nexport const JsonObject = rt(\"json/object\", \"1\");\nexport const JsonGzObject = rt(\"json-gz/object\", \"1\");\nexport const JsonArray = rt(\"json/array\", \"1\");\nexport const JsonNumber = rt(\"json/number\", \"1\");\nexport const JsonNull = rt(\"json/null\", \"1\");\n\nexport const RNull = rt(\"Null\", \"1\");\n\nexport const EphStdMap: ResourceType = rt(\"EphStdMap\", \"1\");\nexport const StdMap: ResourceType = rt(\"StdMap\", \"1\");\n\n//\n// Standard value resources\n//\n\nexport function createPlNull(tx: PlTransaction): ResourceRef {\n return tx.createValue(JsonNull, Buffer.from(JSON.stringify(null)));\n}\n\nexport function createPlBool(tx: PlTransaction, val: boolean): ResourceRef {\n return tx.createValue(JsonBool, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlNumber(tx: PlTransaction, val: number): ResourceRef {\n return tx.createValue(JsonNumber, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlString(tx: PlTransaction, val: string): ResourceRef {\n return tx.createValue(JsonString, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlArray(tx: PlTransaction, val: any[]): ResourceRef {\n return tx.createValue(JsonArray, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlObject(tx: PlTransaction, val: object): ResourceRef {\n return tx.createValue(JsonObject, Buffer.from(JSON.stringify(val)));\n}\n\n//\n// Pl Map\n//\n\nexport type PlRecordEntry<Key extends string = string, Ref extends AnyRef = AnyRef> = [Key, Ref];\n\nexport type PlRecord<Key extends string = string, Ref extends AnyRef = AnyRef> = Record<Key, Ref>;\n\nexport function plEntry<Key extends string = string, Ref extends AnyRef = AnyRef>(\n key: Key,\n ref: Ref,\n): PlRecordEntry<Key, Ref> {\n return [key, ref];\n}\n\nexport function plEntries<Key extends string = string, Ref extends AnyRef = AnyRef>(\n record: PlRecord<Key, Ref>,\n fields?: Key[],\n): PlRecordEntry<Key, Ref>[] {\n return fields === undefined\n ? (Object.entries(record) as PlRecordEntry<Key, Ref>[])\n : fields.map((key) => plEntry(key, record[key]));\n}\n\n/** Helper method to build standard pl map from a set of entries */\nexport function createPlMap(\n tx: PlTransaction,\n entries: PlRecordEntry[] | PlRecord,\n ephemeral: boolean,\n type?: ResourceType,\n): ResourceRef {\n const actualType = type ?? (ephemeral ? EphStdMap : StdMap);\n const rId = ephemeral ? tx.createEphemeral(actualType) : tx.createStruct(actualType);\n\n for (const [name, value] of Array.isArray(entries) ? entries : plEntries(entries))\n tx.createField(field(rId, name), \"Input\", value);\n\n tx.lock(rId);\n\n return rId;\n}\n\nexport function futureRecord<Key extends string>(\n tx: PlTransaction,\n rId: AnyRef,\n keys: Key[],\n fieldType: FutureFieldType,\n prefix: string = \"\",\n): PlRecord<Key, FieldRef> {\n return Object.fromEntries(\n keys.map((k) => plEntry(k, tx.getFutureFieldValue(rId, `${prefix}${k}`, fieldType))),\n ) as PlRecord<Key, FieldRef>;\n}\n\n//\n// Holder\n//\n\n/** Name of the field in block holder, that references the actual block-pack. */\nexport const Holder = StdMap;\nexport const EphHolder = EphStdMap;\nexport const HolderRefField = \"ref\";\n\nexport function wrapInHolder(tx: PlTransaction, ref: AnyRef): ResourceRef {\n const holder = tx.createStruct(Holder);\n const mainHolderField = field(holder, HolderRefField);\n tx.createField(mainHolderField, \"Input\", ref);\n tx.lock(holder);\n return holder;\n}\n\nexport function wrapInEphHolder(tx: PlTransaction, ref: AnyRef): ResourceRef {\n const holder = tx.createEphemeral(EphHolder);\n const mainHolderField = field(holder, HolderRefField);\n tx.createField(mainHolderField, \"Input\", ref);\n tx.lock(holder);\n return holder;\n}\n\nexport function unwrapHolder(tx: PlTransaction, ref: AnyRef): FieldRef {\n return tx.getFutureFieldValue(ref, HolderRefField, \"Input\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pl.js","names":[],"sources":["../../src/helpers/pl.ts"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * This file is exported under Pl \"namespace\" to the client users.\n *\n * It defines well known pl types, and methods to manipulate them.\n *\n */\n\nimport type { FutureFieldType, ResourceType } from \"../core/types\";\nimport type { AnyRef, FieldRef, PlTransaction, ResourceRef } from \"../core/transaction\";\nimport { field } from \"../core/transaction\";\n\nfunction rt(name: string, version: string): ResourceType {\n return { name, version };\n}\n\nexport const ClientRoot = rt(\"ClientRoot\", \"1\");\n\nexport const StructTestResource = rt(\"StructTest\", \"1\");\nexport const ValueTestResource = rt(\"ValueTest\", \"1\");\n\nexport const JsonString = rt(\"json/string\", \"1\");\nexport const JsonBool = rt(\"json/bool\", \"1\");\nexport const JsonObject = rt(\"json/object\", \"1\");\nexport const JsonGzObject = rt(\"json-gz/object\", \"1\");\nexport const JsonArray = rt(\"json/array\", \"1\");\nexport const JsonNumber = rt(\"json/number\", \"1\");\nexport const JsonNull = rt(\"json/null\", \"1\");\n\nexport const RNull = rt(\"Null\", \"1\");\n\nexport const EphStdMap: ResourceType = rt(\"EphStdMap\", \"1\");\nexport const StdMap: ResourceType = rt(\"StdMap\", \"1\");\n\n//\n// Standard value resources\n//\n\nexport function createPlNull(tx: PlTransaction): ResourceRef {\n return tx.createValue(JsonNull, Buffer.from(JSON.stringify(null)));\n}\n\nexport function createPlBool(tx: PlTransaction, val: boolean): ResourceRef {\n return tx.createValue(JsonBool, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlNumber(tx: PlTransaction, val: number): ResourceRef {\n return tx.createValue(JsonNumber, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlString(tx: PlTransaction, val: string): ResourceRef {\n return tx.createValue(JsonString, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlArray(tx: PlTransaction, val: any[]): ResourceRef {\n return tx.createValue(JsonArray, Buffer.from(JSON.stringify(val)));\n}\n\nexport function createPlObject(tx: PlTransaction, val: object): ResourceRef {\n return tx.createValue(JsonObject, Buffer.from(JSON.stringify(val)));\n}\n\n//\n// Pl Map\n//\n\nexport type PlRecordEntry<Key extends string = string, Ref extends AnyRef = AnyRef> = [Key, Ref];\n\nexport type PlRecord<Key extends string = string, Ref extends AnyRef = AnyRef> = Record<Key, Ref>;\n\nexport function plEntry<Key extends string = string, Ref extends AnyRef = AnyRef>(\n key: Key,\n ref: Ref,\n): PlRecordEntry<Key, Ref> {\n return [key, ref];\n}\n\nexport function plEntries<Key extends string = string, Ref extends AnyRef = AnyRef>(\n record: PlRecord<Key, Ref>,\n fields?: Key[],\n): PlRecordEntry<Key, Ref>[] {\n return fields === undefined\n ? (Object.entries(record) as PlRecordEntry<Key, Ref>[])\n : fields.map((key) => plEntry(key, record[key]));\n}\n\n/** Helper method to build standard pl map from a set of entries */\nexport function createPlMap(\n tx: PlTransaction,\n entries: PlRecordEntry[] | PlRecord,\n ephemeral: boolean,\n type?: ResourceType,\n): ResourceRef {\n const actualType = type ?? (ephemeral ? EphStdMap : StdMap);\n const rId = ephemeral ? tx.createEphemeral(actualType) : tx.createStruct(actualType);\n\n for (const [name, value] of Array.isArray(entries) ? entries : plEntries(entries))\n tx.createField(field(rId, name), \"Input\", value);\n\n tx.lock(rId);\n\n return rId;\n}\n\nexport function futureRecord<Key extends string>(\n tx: PlTransaction,\n rId: AnyRef,\n keys: Key[],\n fieldType: FutureFieldType,\n prefix: string = \"\",\n): PlRecord<Key, FieldRef> {\n return Object.fromEntries(\n keys.map((k) => plEntry(k, tx.getFutureFieldValue(rId, `${prefix}${k}`, fieldType))),\n ) as PlRecord<Key, FieldRef>;\n}\n\n//\n// Holder\n//\n\n/** Name of the field in block holder, that references the actual block-pack. */\nexport const Holder = StdMap;\nexport const EphHolder = EphStdMap;\nexport const HolderRefField = \"ref\";\n\nexport function wrapInHolder(tx: PlTransaction, ref: AnyRef): ResourceRef {\n const holder = tx.createStruct(Holder);\n const mainHolderField = field(holder, HolderRefField);\n tx.createField(mainHolderField, \"Input\", ref);\n tx.lock(holder);\n return holder;\n}\n\nexport function wrapInEphHolder(tx: PlTransaction, ref: AnyRef): ResourceRef {\n const holder = tx.createEphemeral(EphHolder);\n const mainHolderField = field(holder, HolderRefField);\n tx.createField(mainHolderField, \"Input\", ref);\n tx.lock(holder);\n return holder;\n}\n\nexport function unwrapHolder(tx: PlTransaction, ref: AnyRef): FieldRef {\n return tx.getFutureFieldValue(ref, HolderRefField, \"Input\");\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
2
  const require_types = require("../core/types.cjs");
3
3
  let _milaboratories_ts_helpers = require("@milaboratories/ts-helpers");
4
4
  let node_timers_promises = require("node:timers/promises");
5
- node_timers_promises = require_runtime.__toESM(node_timers_promises);
5
+ node_timers_promises = require_runtime.__toESM(node_timers_promises, 1);
6
6
  //#region src/helpers/poll.ts
7
7
  /** This error tells state assertion mechanism that required state is not yet ready */
8
8
  var ContinuePolling = class extends Error {
@@ -13,6 +13,9 @@ const DefaultPollFieldTraverseOps = {
13
13
  onlyFinal: false
14
14
  };
15
15
  var PollResourceAccessor = class {
16
+ tx;
17
+ data;
18
+ path;
16
19
  constructor(tx, data, path) {
17
20
  this.tx = tx;
18
21
  this.data = data;
@@ -66,6 +69,7 @@ var PollResourceAccessor = class {
66
69
  }
67
70
  };
68
71
  var PollTxAccessor = class {
72
+ tx;
69
73
  constructor(tx) {
70
74
  this.tx = tx;
71
75
  }