@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.
- package/dist/core/PromiseTracker.cjs.map +1 -1
- package/dist/core/PromiseTracker.d.ts.map +1 -1
- package/dist/core/PromiseTracker.js.map +1 -1
- package/dist/core/StatefulPromise.cjs +2 -0
- package/dist/core/StatefulPromise.cjs.map +1 -1
- package/dist/core/StatefulPromise.js +2 -0
- package/dist/core/StatefulPromise.js.map +1 -1
- package/dist/core/abstract_stream.d.ts +1 -1
- package/dist/core/advisory_locks.cjs.map +1 -1
- package/dist/core/advisory_locks.js.map +1 -1
- package/dist/core/auth.cjs.map +1 -1
- package/dist/core/auth.d.ts.map +1 -1
- package/dist/core/auth.js.map +1 -1
- package/dist/core/cache.d.ts.map +1 -1
- package/dist/core/capabilities.cjs.map +1 -1
- package/dist/core/capabilities.d.ts.map +1 -1
- package/dist/core/capabilities.js.map +1 -1
- package/dist/core/client.cjs +3 -3
- package/dist/core/client.cjs.map +1 -1
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +2 -2
- package/dist/core/client.js.map +1 -1
- package/dist/core/config.cjs.map +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/default_client.cjs +5 -5
- package/dist/core/default_client.cjs.map +1 -1
- package/dist/core/default_client.d.ts.map +1 -1
- package/dist/core/default_client.js.map +1 -1
- package/dist/core/driver.cjs.map +1 -1
- package/dist/core/driver.d.ts.map +1 -1
- package/dist/core/driver.js.map +1 -1
- package/dist/core/error_resource.cjs.map +1 -1
- package/dist/core/error_resource.js.map +1 -1
- package/dist/core/errors.cjs +10 -11
- package/dist/core/errors.cjs.map +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +10 -10
- package/dist/core/errors.js.map +1 -1
- package/dist/core/final.cjs +2 -1
- package/dist/core/final.cjs.map +1 -1
- package/dist/core/final.d.ts.map +1 -1
- package/dist/core/final.js.map +1 -1
- package/dist/core/ll_client.cjs +14 -9
- package/dist/core/ll_client.cjs.map +1 -1
- package/dist/core/ll_client.d.ts +1 -0
- package/dist/core/ll_client.d.ts.map +1 -1
- package/dist/core/ll_client.js +15 -9
- package/dist/core/ll_client.js.map +1 -1
- package/dist/core/ll_transaction.cjs +3 -1
- package/dist/core/ll_transaction.cjs.map +1 -1
- package/dist/core/ll_transaction.d.ts +1 -1
- package/dist/core/ll_transaction.d.ts.map +1 -1
- package/dist/core/ll_transaction.js +2 -1
- package/dist/core/ll_transaction.js.map +1 -1
- package/dist/core/stat.cjs.map +1 -1
- package/dist/core/stat.js.map +1 -1
- package/dist/core/transaction.cjs +11 -5
- package/dist/core/transaction.cjs.map +1 -1
- package/dist/core/transaction.d.ts.map +1 -1
- package/dist/core/transaction.js +11 -4
- package/dist/core/transaction.js.map +1 -1
- package/dist/core/tree_filter.cjs +73 -18
- package/dist/core/tree_filter.cjs.map +1 -1
- package/dist/core/tree_filter.d.ts +1 -1
- package/dist/core/tree_filter.d.ts.map +1 -1
- package/dist/core/tree_filter.js +72 -19
- package/dist/core/tree_filter.js.map +1 -1
- package/dist/core/type_conversion.cjs +19 -20
- package/dist/core/type_conversion.cjs.map +1 -1
- package/dist/core/type_conversion.js +19 -19
- package/dist/core/type_conversion.js.map +1 -1
- package/dist/core/types.cjs +2 -3
- package/dist/core/types.cjs.map +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +2 -2
- package/dist/core/types.js.map +1 -1
- package/dist/core/unauth_client.cjs +7 -6
- package/dist/core/unauth_client.cjs.map +1 -1
- package/dist/core/unauth_client.d.ts +9 -0
- package/dist/core/unauth_client.d.ts.map +1 -1
- package/dist/core/unauth_client.js +7 -5
- package/dist/core/unauth_client.js.map +1 -1
- package/dist/core/user_resources.cjs +3 -1
- package/dist/core/user_resources.cjs.map +1 -1
- package/dist/core/user_resources.d.ts.map +1 -1
- package/dist/core/user_resources.js +3 -0
- package/dist/core/user_resources.js.map +1 -1
- package/dist/core/websocket_stream.cjs +17 -20
- package/dist/core/websocket_stream.cjs.map +1 -1
- package/dist/core/websocket_stream.js +16 -19
- package/dist/core/websocket_stream.js.map +1 -1
- package/dist/core/wire.d.ts.map +1 -1
- package/dist/helpers/pl.cjs +25 -0
- package/dist/helpers/pl.cjs.map +1 -1
- package/dist/helpers/pl.d.ts +1 -1
- package/dist/helpers/pl.d.ts.map +1 -1
- package/dist/helpers/pl.js +1 -1
- package/dist/helpers/pl.js.map +1 -1
- package/dist/helpers/poll.cjs +5 -1
- package/dist/helpers/poll.cjs.map +1 -1
- package/dist/helpers/poll.d.ts.map +1 -1
- package/dist/helpers/poll.js +4 -0
- package/dist/helpers/poll.js.map +1 -1
- package/dist/helpers/retry_strategy.cjs +1 -0
- package/dist/helpers/retry_strategy.cjs.map +1 -1
- package/dist/helpers/retry_strategy.js +1 -1
- package/dist/helpers/retry_strategy.js.map +1 -1
- package/dist/helpers/tx_helpers.cjs +0 -1
- package/dist/helpers/tx_helpers.cjs.map +1 -1
- package/dist/helpers/tx_helpers.d.ts.map +1 -1
- package/dist/helpers/tx_helpers.js.map +1 -1
- package/dist/index.cjs +0 -1
- package/dist/index.d.ts +1 -1
- package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.cjs +0 -1
- package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.cjs.map +1 -1
- package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +531 -77
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs +11 -4
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts +12 -6
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.js +11 -3
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +106 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +330 -77
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs +23 -7
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts +10 -3
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.js +18 -7
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs +1 -2
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.js +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.cjs +2 -2
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.d.ts +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.js +2 -2
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.js.map +1 -1
- package/dist/proto-grpc/google/protobuf/any.cjs +1 -2
- package/dist/proto-grpc/google/protobuf/any.cjs.map +1 -1
- package/dist/proto-grpc/google/protobuf/any.d.ts.map +1 -1
- package/dist/proto-grpc/google/protobuf/any.js +1 -1
- package/dist/proto-grpc/google/protobuf/any.js.map +1 -1
- package/dist/proto-grpc/google/protobuf/duration.cjs +0 -1
- package/dist/proto-grpc/google/protobuf/duration.cjs.map +1 -1
- package/dist/proto-grpc/google/protobuf/duration.d.ts.map +1 -1
- package/dist/proto-grpc/google/protobuf/duration.js.map +1 -1
- package/dist/proto-grpc/google/protobuf/timestamp.cjs +0 -1
- package/dist/proto-grpc/google/protobuf/timestamp.cjs.map +1 -1
- package/dist/proto-grpc/google/protobuf/timestamp.d.ts.map +1 -1
- package/dist/proto-grpc/google/protobuf/timestamp.js.map +1 -1
- package/dist/proto-grpc/google/rpc/code.d.ts.map +1 -1
- package/dist/proto-rest/index.cjs +1 -1
- package/dist/proto-rest/index.cjs.map +1 -1
- package/dist/proto-rest/index.d.ts +1 -1
- package/dist/proto-rest/index.d.ts.map +1 -1
- package/dist/proto-rest/index.js.map +1 -1
- package/dist/proto-rest/plapi.d.ts +30 -9
- package/dist/proto-rest/plapi.d.ts.map +1 -1
- package/dist/test/tcp-proxy.cjs +2 -2
- package/dist/test/tcp-proxy.cjs.map +1 -1
- package/dist/test/tcp-proxy.d.ts +1 -1
- package/dist/test/tcp-proxy.js.map +1 -1
- package/dist/test/test_config.cjs +8 -2
- package/dist/test/test_config.cjs.map +1 -1
- package/dist/test/test_config.d.ts +1 -1
- package/dist/test/test_config.d.ts.map +1 -1
- package/dist/test/test_config.js +1 -1
- package/dist/test/test_config.js.map +1 -1
- package/dist/util/pl.cjs.map +1 -1
- package/dist/util/pl.js.map +1 -1
- package/dist/util/util.cjs.map +1 -1
- package/dist/util/util.js.map +1 -1
- package/package.json +6 -6
- package/src/core/ll_client.ts +7 -2
- package/src/core/unauth_client.ts +17 -2
- package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.ts +16 -3
- package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +326 -3
- package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.ts +21 -7
- package/src/proto-rest/plapi.ts +29 -8
- package/dist/proto-grpc/google/rpc/code.cjs +0 -224
- package/dist/proto-grpc/google/rpc/code.cjs.map +0 -1
- package/dist/proto-grpc/google/rpc/code.js +0 -224
- 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 =
|
|
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 <
|
|
43
|
+
if (this.connectionState < 2) {
|
|
48
44
|
this.ws?.close();
|
|
49
45
|
this.onClose();
|
|
50
46
|
return;
|
|
51
47
|
}
|
|
52
|
-
if (!this.progressConnectionState(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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 <
|
|
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(
|
|
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 ===
|
|
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 ===
|
|
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 =
|
|
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 <
|
|
41
|
+
if (this.connectionState < 2) {
|
|
46
42
|
this.ws?.close();
|
|
47
43
|
this.onClose();
|
|
48
44
|
return;
|
|
49
45
|
}
|
|
50
|
-
if (!this.progressConnectionState(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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 <
|
|
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(
|
|
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 ===
|
|
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 ===
|
|
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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"}
|
package/dist/core/wire.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/helpers/pl.cjs
CHANGED
|
@@ -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
|
package/dist/helpers/pl.cjs.map
CHANGED
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,SAAS,GAAG,MAAc,SAA+B;
|
|
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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"}
|
package/dist/helpers/pl.d.ts
CHANGED
|
@@ -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
|
package/dist/helpers/pl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pl.d.ts","names":[],"sources":["../../src/helpers/pl.ts"],"mappings":";;;;;;;cAiBa,UAAA,EAAU,
|
|
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"}
|
package/dist/helpers/pl.js
CHANGED
|
@@ -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
|
package/dist/helpers/pl.js.map
CHANGED
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,SAAS,GAAG,MAAc,SAA+B;
|
|
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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"}
|
package/dist/helpers/poll.cjs
CHANGED
|
@@ -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
|
}
|