@zlink-systems/stream-connector 0.13.0 → 0.15.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/browser/Contracts/IZlinkStreamConnector.d.ts +1 -2
- package/dist/browser/Contracts/ZlinkStreamConnectorOptions.d.ts +0 -6
- package/dist/browser/Contracts/ZlinkStreamEnums.d.ts +0 -3
- package/dist/browser/Contracts/ZlinkStreamModels.d.ts +0 -13
- package/dist/browser/Contracts/index.d.ts +1 -1
- package/dist/browser/Runtime/ZlinkStreamConnector.d.ts +1 -3
- package/dist/browser/Runtime/ZlinkStreamConnectorLifecycle.d.ts +18 -1
- package/dist/browser/Runtime/ZlinkStreamReceiveDispatcher.d.ts +1 -3
- package/dist/browser/Runtime/ZlinkStreamReceivedMessages.d.ts +31 -4
- package/dist/browser/index.global.js +2934 -0
- package/dist/browser/index.mjs +172 -206
- package/package.json +2 -2
- package/dist/browser/Runtime/ZlinkStreamInboundObservers.d.ts +0 -25
|
@@ -0,0 +1,2934 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var ZlinkStreamConnectorBundle = (() => {
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
22
|
+
|
|
23
|
+
// packages/stream-connector/src/index.ts
|
|
24
|
+
var index_exports = {};
|
|
25
|
+
__export(index_exports, {
|
|
26
|
+
DefaultZlinkStreamConnector: () => DefaultZlinkStreamConnector,
|
|
27
|
+
ZlinkStreamCodec: () => ZlinkStreamCodec,
|
|
28
|
+
ZlinkStreamCompression: () => ZlinkStreamCompression,
|
|
29
|
+
ZlinkStreamConnectionState: () => ZlinkStreamConnectionState,
|
|
30
|
+
ZlinkStreamDiagnosticsLevel: () => ZlinkStreamDiagnosticsLevel,
|
|
31
|
+
ZlinkStreamDispatchMode: () => ZlinkStreamDispatchMode,
|
|
32
|
+
ZlinkStreamErrorCode: () => ZlinkStreamErrorCode,
|
|
33
|
+
ZlinkStreamException: () => ZlinkStreamException,
|
|
34
|
+
ZlinkStreamHeaderFlags: () => ZlinkStreamHeaderFlags,
|
|
35
|
+
ZlinkStreamMessageKind: () => ZlinkStreamMessageKind,
|
|
36
|
+
ZlinkStreamMetadataMap: () => ZlinkStreamMetadataMap,
|
|
37
|
+
ZlinkStreamTransport: () => ZlinkStreamTransport,
|
|
38
|
+
fromJson: () => fromJson,
|
|
39
|
+
toJson: () => toJson,
|
|
40
|
+
validateMetadataKey: () => validateMetadataKey,
|
|
41
|
+
zlinkStreamAssert: () => zlinkStreamAssert,
|
|
42
|
+
zlinkStreamConnectorFactory: () => zlinkStreamConnectorFactory,
|
|
43
|
+
zlinkStreamJsonCodec: () => zlinkStreamJsonCodec,
|
|
44
|
+
zlinkStreamJsonCodecName: () => zlinkStreamJsonCodecName
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// packages/stream-wire/src/lz4-pickle.ts
|
|
48
|
+
var defaultMaxDecompressedPayloadSize = 64 * 1024;
|
|
49
|
+
function lz4PickleUncompressed(payload) {
|
|
50
|
+
if (payload.length === 0) {
|
|
51
|
+
return new Uint8Array();
|
|
52
|
+
}
|
|
53
|
+
const pickled = new Uint8Array(payload.length + 1);
|
|
54
|
+
pickled[0] = 0;
|
|
55
|
+
pickled.set(payload, 1);
|
|
56
|
+
return pickled;
|
|
57
|
+
}
|
|
58
|
+
function lz4UnpicklePayload(payload, maxSize) {
|
|
59
|
+
const maxDecompressedSize = maxSize != null ? maxSize : defaultMaxDecompressedPayloadSize;
|
|
60
|
+
if (payload.length === 0) {
|
|
61
|
+
return new Uint8Array();
|
|
62
|
+
}
|
|
63
|
+
const header = payload[0];
|
|
64
|
+
if ((header & 7) !== 0) {
|
|
65
|
+
throw new Error("Unexpected LZ4 pickle version.");
|
|
66
|
+
}
|
|
67
|
+
const sizeOfDiff = decodeDiffSize(header >>> 6 & 3);
|
|
68
|
+
const dataOffset = 1 + sizeOfDiff;
|
|
69
|
+
if (payload.length < dataOffset) {
|
|
70
|
+
throw new Error("LZ4 pickle header is incomplete.");
|
|
71
|
+
}
|
|
72
|
+
const data = payload.subarray(dataOffset);
|
|
73
|
+
const resultDiff = sizeOfDiff === 0 ? 0 : readLittleEndian(payload, 1, sizeOfDiff);
|
|
74
|
+
const resultLength = data.length + resultDiff;
|
|
75
|
+
if (resultLength > maxDecompressedSize) {
|
|
76
|
+
throw new Error("LZ4 decoded payload exceeds maximum stream payload size.");
|
|
77
|
+
}
|
|
78
|
+
if (resultDiff === 0) {
|
|
79
|
+
return data.slice();
|
|
80
|
+
}
|
|
81
|
+
return decodeLz4Block(data, resultLength);
|
|
82
|
+
}
|
|
83
|
+
function decodeDiffSize(encoded) {
|
|
84
|
+
return encoded === 3 ? 4 : encoded;
|
|
85
|
+
}
|
|
86
|
+
function readLittleEndian(source, offset, size) {
|
|
87
|
+
if (size === 1) {
|
|
88
|
+
return source[offset];
|
|
89
|
+
}
|
|
90
|
+
if (size === 2) {
|
|
91
|
+
return source[offset] | source[offset + 1] << 8;
|
|
92
|
+
}
|
|
93
|
+
if (size === 4) {
|
|
94
|
+
return source[offset] | source[offset + 1] << 8 | source[offset + 2] << 16 | source[offset + 3] * 16777216;
|
|
95
|
+
}
|
|
96
|
+
throw new Error(`Unexpected LZ4 pickle field size: ${size}`);
|
|
97
|
+
}
|
|
98
|
+
function decodeLz4Block(source, resultLength) {
|
|
99
|
+
const target = new Uint8Array(resultLength);
|
|
100
|
+
let sourceOffset = 0;
|
|
101
|
+
let targetOffset = 0;
|
|
102
|
+
while (sourceOffset < source.length) {
|
|
103
|
+
const token = source[sourceOffset++];
|
|
104
|
+
const literalLength = readLz4Length(source, token >>> 4, () => sourceOffset++);
|
|
105
|
+
if (source.length - sourceOffset < literalLength) {
|
|
106
|
+
throw new Error("LZ4 literal run is incomplete.");
|
|
107
|
+
}
|
|
108
|
+
if (target.length - targetOffset < literalLength) {
|
|
109
|
+
throw new Error("LZ4 literal run exceeds output size.");
|
|
110
|
+
}
|
|
111
|
+
target.set(source.subarray(sourceOffset, sourceOffset + literalLength), targetOffset);
|
|
112
|
+
sourceOffset += literalLength;
|
|
113
|
+
targetOffset += literalLength;
|
|
114
|
+
if (sourceOffset >= source.length) {
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
if (source.length - sourceOffset < 2) {
|
|
118
|
+
throw new Error("LZ4 match offset is incomplete.");
|
|
119
|
+
}
|
|
120
|
+
const matchOffset = source[sourceOffset] | source[sourceOffset + 1] << 8;
|
|
121
|
+
sourceOffset += 2;
|
|
122
|
+
if (matchOffset === 0 || matchOffset > targetOffset) {
|
|
123
|
+
throw new Error("LZ4 match offset is invalid.");
|
|
124
|
+
}
|
|
125
|
+
const matchLength = readLz4Length(source, token & 15, () => sourceOffset++) + 4;
|
|
126
|
+
if (target.length - targetOffset < matchLength) {
|
|
127
|
+
throw new Error("LZ4 match run exceeds output size.");
|
|
128
|
+
}
|
|
129
|
+
for (let index = 0; index < matchLength; index += 1) {
|
|
130
|
+
target[targetOffset + index] = target[targetOffset - matchOffset + index];
|
|
131
|
+
}
|
|
132
|
+
targetOffset += matchLength;
|
|
133
|
+
}
|
|
134
|
+
if (targetOffset !== resultLength) {
|
|
135
|
+
throw new Error("LZ4 decoded length does not match pickle header.");
|
|
136
|
+
}
|
|
137
|
+
return target;
|
|
138
|
+
}
|
|
139
|
+
function readLz4Length(source, nibble, nextOffset) {
|
|
140
|
+
let length = nibble;
|
|
141
|
+
if (length !== 15) {
|
|
142
|
+
return length;
|
|
143
|
+
}
|
|
144
|
+
for (; ; ) {
|
|
145
|
+
const offset = nextOffset();
|
|
146
|
+
if (offset >= source.length) {
|
|
147
|
+
throw new Error("LZ4 extended length is incomplete.");
|
|
148
|
+
}
|
|
149
|
+
const value = source[offset];
|
|
150
|
+
length += value;
|
|
151
|
+
if (value !== 255) {
|
|
152
|
+
return length;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// packages/stream-wire/src/index.ts
|
|
158
|
+
var ZlinkStreamCodec = /* @__PURE__ */ ((ZlinkStreamCodec2) => {
|
|
159
|
+
ZlinkStreamCodec2[ZlinkStreamCodec2["Raw"] = 0] = "Raw";
|
|
160
|
+
ZlinkStreamCodec2[ZlinkStreamCodec2["Json"] = 1] = "Json";
|
|
161
|
+
ZlinkStreamCodec2[ZlinkStreamCodec2["MessagePack"] = 2] = "MessagePack";
|
|
162
|
+
ZlinkStreamCodec2[ZlinkStreamCodec2["Protobuf"] = 3] = "Protobuf";
|
|
163
|
+
return ZlinkStreamCodec2;
|
|
164
|
+
})(ZlinkStreamCodec || {});
|
|
165
|
+
var defaultHeaderFlags = {
|
|
166
|
+
hasRequestSeq: 1,
|
|
167
|
+
hasMetadata: 2,
|
|
168
|
+
hasCorrelationId: 8,
|
|
169
|
+
hasFlowId: 16
|
|
170
|
+
};
|
|
171
|
+
var ZLINK_STREAM_FORMAT_MARKER = 242;
|
|
172
|
+
var ZLINK_STREAM_RESPONSE_KIND = 3;
|
|
173
|
+
var ZLINK_STREAM_ERROR_KIND = 4;
|
|
174
|
+
function encodeStreamWireFrame(header, payload) {
|
|
175
|
+
if (header.length > 65535) {
|
|
176
|
+
throw new Error("Stream header is too large.");
|
|
177
|
+
}
|
|
178
|
+
if (payload.length > 4294967295) {
|
|
179
|
+
throw new Error("Stream payload is too large.");
|
|
180
|
+
}
|
|
181
|
+
const frame = new Uint8Array(6 + header.length + payload.length);
|
|
182
|
+
writeUInt16BE(frame, 0, header.length);
|
|
183
|
+
writeUInt32BE(frame, 2, payload.length);
|
|
184
|
+
frame.set(header, 6);
|
|
185
|
+
frame.set(payload, 6 + header.length);
|
|
186
|
+
return frame;
|
|
187
|
+
}
|
|
188
|
+
function decodeStreamWireFrame(frame) {
|
|
189
|
+
if (frame.length < 6) {
|
|
190
|
+
throw new Error("Stream frame prefix is incomplete.");
|
|
191
|
+
}
|
|
192
|
+
const headerLength = readUInt16BE(frame, 0);
|
|
193
|
+
const payloadLength = readUInt32BE(frame, 2);
|
|
194
|
+
if (frame.length !== 6 + headerLength + payloadLength) {
|
|
195
|
+
throw new Error("Stream frame length does not match prefix.");
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
header: frame.slice(6, 6 + headerLength),
|
|
199
|
+
payload: frame.slice(6 + headerLength)
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function encodeStreamWireHeader(header, flagOverrides) {
|
|
203
|
+
const flags = flagOverrides != null ? flagOverrides : defaultHeaderFlags;
|
|
204
|
+
const reply = isReplyKind(header.kind);
|
|
205
|
+
const packetName = reply ? "" : header.name;
|
|
206
|
+
if (!reply) validateStreamWirePacketName(packetName);
|
|
207
|
+
const nameBytes = utf8Encode(packetName);
|
|
208
|
+
const hasRequestSeq = header.requestSeq !== void 0;
|
|
209
|
+
const hasMetadata = header.metadata.size > 0;
|
|
210
|
+
const correlationBytes = header.correlationId !== void 0 && header.correlationId.length > 0 ? utf8Encode(header.correlationId) : void 0;
|
|
211
|
+
if (correlationBytes !== void 0 && correlationBytes.length > 255) {
|
|
212
|
+
throw new Error("Stream correlation id is too large.");
|
|
213
|
+
}
|
|
214
|
+
const hasCorrelation = correlationBytes !== void 0;
|
|
215
|
+
const hasFlow = header.flowId !== void 0 || header.flowOrigin !== void 0;
|
|
216
|
+
if (hasFlow && (header.flowId === void 0 || header.flowOrigin === void 0)) {
|
|
217
|
+
throw new Error("Stream flow id and origin must be provided together.");
|
|
218
|
+
}
|
|
219
|
+
if (header.flowId !== void 0) validateFlowId(header.flowId);
|
|
220
|
+
if (header.flowOrigin !== void 0 && ![1, 2, 3, 4].includes(header.flowOrigin)) {
|
|
221
|
+
throw new Error("Stream flow origin is invalid.");
|
|
222
|
+
}
|
|
223
|
+
let headerFlags = header.flags;
|
|
224
|
+
headerFlags = hasRequestSeq ? headerFlags | flags.hasRequestSeq : headerFlags & ~flags.hasRequestSeq;
|
|
225
|
+
headerFlags = hasMetadata ? headerFlags | flags.hasMetadata : headerFlags & ~flags.hasMetadata;
|
|
226
|
+
headerFlags = hasCorrelation ? headerFlags | flags.hasCorrelationId : headerFlags & ~flags.hasCorrelationId;
|
|
227
|
+
headerFlags = hasFlow ? headerFlags | flags.hasFlowId : headerFlags & ~flags.hasFlowId;
|
|
228
|
+
const metadataBytes = hasMetadata ? encodeStreamWireMetadata(header.metadata) : new Uint8Array();
|
|
229
|
+
const size = 4 + (hasRequestSeq ? 8 : 0) + 1 + nameBytes.length + (hasMetadata ? 2 + metadataBytes.length : 0) + (hasCorrelation ? 1 + correlationBytes.length : 0) + (hasFlow ? 37 : 0);
|
|
230
|
+
const buffer = new Uint8Array(size);
|
|
231
|
+
let offset = 0;
|
|
232
|
+
buffer[offset++] = ZLINK_STREAM_FORMAT_MARKER;
|
|
233
|
+
buffer[offset++] = header.kind;
|
|
234
|
+
buffer[offset++] = header.codec;
|
|
235
|
+
buffer[offset++] = headerFlags;
|
|
236
|
+
if (hasRequestSeq) {
|
|
237
|
+
if (header.requestSeq === 0n) {
|
|
238
|
+
throw new Error("Request sequence must not be zero.");
|
|
239
|
+
}
|
|
240
|
+
writeBigUInt64BE(buffer, offset, header.requestSeq);
|
|
241
|
+
offset += 8;
|
|
242
|
+
}
|
|
243
|
+
buffer[offset++] = nameBytes.length;
|
|
244
|
+
buffer.set(nameBytes, offset);
|
|
245
|
+
offset += nameBytes.length;
|
|
246
|
+
if (hasMetadata) {
|
|
247
|
+
writeUInt16BE(buffer, offset, metadataBytes.length);
|
|
248
|
+
offset += 2;
|
|
249
|
+
buffer.set(metadataBytes, offset);
|
|
250
|
+
offset += metadataBytes.length;
|
|
251
|
+
}
|
|
252
|
+
if (hasCorrelation) {
|
|
253
|
+
buffer[offset++] = correlationBytes.length;
|
|
254
|
+
buffer.set(correlationBytes, offset);
|
|
255
|
+
offset += correlationBytes.length;
|
|
256
|
+
}
|
|
257
|
+
if (hasFlow) {
|
|
258
|
+
buffer.set(asciiEncode(header.flowId), offset);
|
|
259
|
+
offset += 36;
|
|
260
|
+
buffer[offset++] = header.flowOrigin;
|
|
261
|
+
}
|
|
262
|
+
return buffer;
|
|
263
|
+
}
|
|
264
|
+
function decodeStreamWireHeader(header, flagOverrides, includeFlow = true) {
|
|
265
|
+
const flags = flagOverrides != null ? flagOverrides : defaultHeaderFlags;
|
|
266
|
+
let offset = 0;
|
|
267
|
+
if (header.length < 5) {
|
|
268
|
+
throw new Error("Stream header is incomplete.");
|
|
269
|
+
}
|
|
270
|
+
if (header[offset++] !== ZLINK_STREAM_FORMAT_MARKER) {
|
|
271
|
+
throw new Error("Stream header format marker is invalid.");
|
|
272
|
+
}
|
|
273
|
+
const kind = header[offset++];
|
|
274
|
+
const codec = header[offset++];
|
|
275
|
+
const headerFlags = header[offset++];
|
|
276
|
+
const hasRequestSeq = (headerFlags & flags.hasRequestSeq) !== 0;
|
|
277
|
+
const hasMetadata = (headerFlags & flags.hasMetadata) !== 0;
|
|
278
|
+
const hasCorrelation = (headerFlags & flags.hasCorrelationId) !== 0;
|
|
279
|
+
const hasFlow = (headerFlags & flags.hasFlowId) !== 0;
|
|
280
|
+
if ((headerFlags & ~31) !== 0) {
|
|
281
|
+
throw new Error("Unknown mandatory stream header flag.");
|
|
282
|
+
}
|
|
283
|
+
let requestSeq;
|
|
284
|
+
if (hasRequestSeq) {
|
|
285
|
+
if (header.length - offset < 8) {
|
|
286
|
+
throw new Error("Stream request sequence is incomplete.");
|
|
287
|
+
}
|
|
288
|
+
requestSeq = readBigUInt64BE(header, offset);
|
|
289
|
+
if (requestSeq === 0n) {
|
|
290
|
+
throw new Error("Request sequence must not be zero.");
|
|
291
|
+
}
|
|
292
|
+
offset += 8;
|
|
293
|
+
}
|
|
294
|
+
if (header.length - offset < 1) {
|
|
295
|
+
throw new Error("Stream packet name length is missing.");
|
|
296
|
+
}
|
|
297
|
+
const nameLength = header[offset++];
|
|
298
|
+
if (!isReplyKind(kind) && nameLength === 0 || header.length - offset < nameLength) {
|
|
299
|
+
throw new Error("Stream packet name is invalid.");
|
|
300
|
+
}
|
|
301
|
+
const decodedName = utf8Decode(header.subarray(offset, offset + nameLength));
|
|
302
|
+
const name = isReplyKind(kind) ? "" : decodedName;
|
|
303
|
+
offset += nameLength;
|
|
304
|
+
const decodedMetadata = hasMetadata ? decodeStreamWireHeaderMetadata(header, offset) : { metadata: /* @__PURE__ */ new Map(), offset };
|
|
305
|
+
offset = decodedMetadata.offset;
|
|
306
|
+
let correlationId;
|
|
307
|
+
if (hasCorrelation) {
|
|
308
|
+
if (header.length - offset < 1) {
|
|
309
|
+
throw new Error("Stream correlation id is incomplete.");
|
|
310
|
+
}
|
|
311
|
+
const correlationLength = header[offset++];
|
|
312
|
+
if (header.length - offset < correlationLength) {
|
|
313
|
+
throw new Error("Stream correlation id is incomplete.");
|
|
314
|
+
}
|
|
315
|
+
correlationId = utf8Decode(header.subarray(offset, offset + correlationLength));
|
|
316
|
+
offset += correlationLength;
|
|
317
|
+
}
|
|
318
|
+
let flowId;
|
|
319
|
+
let flowOrigin;
|
|
320
|
+
if (hasFlow) {
|
|
321
|
+
if (header.length - offset < 37) {
|
|
322
|
+
throw new Error("Stream flow fields are incomplete.");
|
|
323
|
+
}
|
|
324
|
+
if (includeFlow) {
|
|
325
|
+
flowId = asciiDecode(header.subarray(offset, offset + 36));
|
|
326
|
+
validateFlowId(flowId);
|
|
327
|
+
}
|
|
328
|
+
offset += 36;
|
|
329
|
+
const decodedFlowOrigin = header[offset++];
|
|
330
|
+
if (includeFlow && ![1, 2, 3, 4].includes(decodedFlowOrigin)) {
|
|
331
|
+
throw new Error("Stream flow origin is invalid.");
|
|
332
|
+
}
|
|
333
|
+
flowOrigin = includeFlow ? decodedFlowOrigin : void 0;
|
|
334
|
+
}
|
|
335
|
+
if (offset !== header.length) {
|
|
336
|
+
throw new Error("Stream header has trailing bytes.");
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
kind,
|
|
340
|
+
codec,
|
|
341
|
+
flags: headerFlags,
|
|
342
|
+
requestSeq,
|
|
343
|
+
name,
|
|
344
|
+
metadata: decodedMetadata.metadata,
|
|
345
|
+
correlationId,
|
|
346
|
+
flowId,
|
|
347
|
+
flowOrigin
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
function validateFlowId(flowId) {
|
|
351
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(flowId)) {
|
|
352
|
+
throw new Error("Stream flow id must be a lowercase UUIDv7.");
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function asciiEncode(value) {
|
|
356
|
+
return Uint8Array.from(value, (character) => character.charCodeAt(0));
|
|
357
|
+
}
|
|
358
|
+
function asciiDecode(value) {
|
|
359
|
+
if (value.some((byte) => byte > 127)) throw new Error("Stream flow id must be ASCII.");
|
|
360
|
+
return String.fromCharCode(...value);
|
|
361
|
+
}
|
|
362
|
+
function encodeStreamWireMetadata(metadata) {
|
|
363
|
+
if (metadata.size > 255) {
|
|
364
|
+
throw new Error("Metadata entry count must not exceed 255.");
|
|
365
|
+
}
|
|
366
|
+
let size = 1;
|
|
367
|
+
const encoded = [...metadata].map(([key, value]) => {
|
|
368
|
+
const keyBytes = utf8Encode(key);
|
|
369
|
+
const valueBytes = utf8Encode(value);
|
|
370
|
+
if (keyBytes.length === 0 || keyBytes.length > 255) {
|
|
371
|
+
throw new Error("Metadata key length is invalid.");
|
|
372
|
+
}
|
|
373
|
+
if (valueBytes.length > 65535) {
|
|
374
|
+
throw new Error("Metadata value is too large.");
|
|
375
|
+
}
|
|
376
|
+
size += 1 + keyBytes.length + 2 + valueBytes.length;
|
|
377
|
+
return { keyBytes, valueBytes };
|
|
378
|
+
});
|
|
379
|
+
const buffer = new Uint8Array(size);
|
|
380
|
+
let offset = 0;
|
|
381
|
+
buffer[offset++] = metadata.size;
|
|
382
|
+
for (const { keyBytes, valueBytes } of encoded) {
|
|
383
|
+
buffer[offset++] = keyBytes.length;
|
|
384
|
+
buffer.set(keyBytes, offset);
|
|
385
|
+
offset += keyBytes.length;
|
|
386
|
+
writeUInt16BE(buffer, offset, valueBytes.length);
|
|
387
|
+
offset += 2;
|
|
388
|
+
buffer.set(valueBytes, offset);
|
|
389
|
+
offset += valueBytes.length;
|
|
390
|
+
}
|
|
391
|
+
return buffer;
|
|
392
|
+
}
|
|
393
|
+
function decodeStreamWireMetadata(metadata) {
|
|
394
|
+
const decoded = decodeStreamWireMetadataAt(metadata, 0, metadata.length);
|
|
395
|
+
if (decoded.offset !== metadata.length) {
|
|
396
|
+
throw new Error("Stream metadata payload has trailing bytes.");
|
|
397
|
+
}
|
|
398
|
+
return decoded.metadata;
|
|
399
|
+
}
|
|
400
|
+
function lz4PickleUncompressed2(payload) {
|
|
401
|
+
return lz4PickleUncompressed(payload);
|
|
402
|
+
}
|
|
403
|
+
function lz4UnpicklePayload2(payload, maxDecompressedSize) {
|
|
404
|
+
return lz4UnpicklePayload(payload, maxDecompressedSize != null ? maxDecompressedSize : defaultMaxDecompressedPayloadSize);
|
|
405
|
+
}
|
|
406
|
+
function utf8Encode(value) {
|
|
407
|
+
return new TextEncoder().encode(value);
|
|
408
|
+
}
|
|
409
|
+
function utf8Decode(value) {
|
|
410
|
+
return new TextDecoder().decode(value);
|
|
411
|
+
}
|
|
412
|
+
function decodeStreamWireHeaderMetadata(header, offset) {
|
|
413
|
+
if (header.length - offset < 2) {
|
|
414
|
+
throw new Error("Stream metadata section is incomplete.");
|
|
415
|
+
}
|
|
416
|
+
const metadataLength = readUInt16BE(header, offset);
|
|
417
|
+
offset += 2;
|
|
418
|
+
if (header.length - offset < metadataLength) {
|
|
419
|
+
throw new Error("Stream metadata payload is incomplete.");
|
|
420
|
+
}
|
|
421
|
+
return decodeStreamWireMetadataAt(header, offset, offset + metadataLength);
|
|
422
|
+
}
|
|
423
|
+
function decodeStreamWireMetadataAt(source, offset, end) {
|
|
424
|
+
if (offset >= end) {
|
|
425
|
+
throw new Error("Stream metadata entry count is missing.");
|
|
426
|
+
}
|
|
427
|
+
const count = source[offset++];
|
|
428
|
+
const metadata = /* @__PURE__ */ new Map();
|
|
429
|
+
for (let index = 0; index < count; index += 1) {
|
|
430
|
+
if (offset >= end) {
|
|
431
|
+
throw new Error("Stream metadata key length is missing.");
|
|
432
|
+
}
|
|
433
|
+
const keyLength = source[offset++];
|
|
434
|
+
if (keyLength === 0 || end - offset < keyLength) {
|
|
435
|
+
throw new Error("Stream metadata key is invalid.");
|
|
436
|
+
}
|
|
437
|
+
const key = utf8Decode(source.subarray(offset, offset + keyLength));
|
|
438
|
+
offset += keyLength;
|
|
439
|
+
if (end - offset < 2) {
|
|
440
|
+
throw new Error("Stream metadata value length is missing.");
|
|
441
|
+
}
|
|
442
|
+
const valueLength = readUInt16BE(source, offset);
|
|
443
|
+
offset += 2;
|
|
444
|
+
if (end - offset < valueLength) {
|
|
445
|
+
throw new Error("Stream metadata value is incomplete.");
|
|
446
|
+
}
|
|
447
|
+
if (metadata.has(key)) {
|
|
448
|
+
throw new Error("Duplicate metadata key is duplicated.");
|
|
449
|
+
}
|
|
450
|
+
metadata.set(key, utf8Decode(source.subarray(offset, offset + valueLength)));
|
|
451
|
+
offset += valueLength;
|
|
452
|
+
}
|
|
453
|
+
if (offset !== end) {
|
|
454
|
+
throw new Error("Stream metadata payload has trailing bytes.");
|
|
455
|
+
}
|
|
456
|
+
return { metadata, offset };
|
|
457
|
+
}
|
|
458
|
+
function validateStreamWirePacketName(name) {
|
|
459
|
+
const nameBytes = utf8Encode(name);
|
|
460
|
+
if (name.trim().length === 0 || nameBytes.length > 255) {
|
|
461
|
+
throw new Error("Stream packet name is invalid.");
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
function isReplyKind(kind) {
|
|
465
|
+
return kind === ZLINK_STREAM_RESPONSE_KIND || kind === ZLINK_STREAM_ERROR_KIND;
|
|
466
|
+
}
|
|
467
|
+
function writeUInt16BE(buffer, offset, value) {
|
|
468
|
+
buffer[offset] = value >>> 8 & 255;
|
|
469
|
+
buffer[offset + 1] = value & 255;
|
|
470
|
+
}
|
|
471
|
+
function readUInt16BE(buffer, offset) {
|
|
472
|
+
return buffer[offset] << 8 | buffer[offset + 1];
|
|
473
|
+
}
|
|
474
|
+
function readUInt32BE(buffer, offset) {
|
|
475
|
+
return buffer[offset] * 16777216 + (buffer[offset + 1] << 16 | buffer[offset + 2] << 8 | buffer[offset + 3]);
|
|
476
|
+
}
|
|
477
|
+
function writeUInt32BE(buffer, offset, value) {
|
|
478
|
+
buffer[offset] = value >>> 24 & 255;
|
|
479
|
+
buffer[offset + 1] = value >>> 16 & 255;
|
|
480
|
+
buffer[offset + 2] = value >>> 8 & 255;
|
|
481
|
+
buffer[offset + 3] = value & 255;
|
|
482
|
+
}
|
|
483
|
+
function writeBigUInt64BE(buffer, offset, value) {
|
|
484
|
+
for (let index = 7; index >= 0; index -= 1) {
|
|
485
|
+
buffer[offset + index] = Number(value & 0xffn);
|
|
486
|
+
value >>= 8n;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
function readBigUInt64BE(buffer, offset) {
|
|
490
|
+
let value = 0n;
|
|
491
|
+
for (let index = 0; index < 8; index += 1) {
|
|
492
|
+
value = value << 8n | BigInt(buffer[offset + index]);
|
|
493
|
+
}
|
|
494
|
+
return value;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// packages/stream-connector/src/Contracts/ZlinkStreamEnums.ts
|
|
498
|
+
var ZlinkStreamTransport = /* @__PURE__ */ ((ZlinkStreamTransport2) => {
|
|
499
|
+
ZlinkStreamTransport2["WebSocket"] = "webSocket";
|
|
500
|
+
ZlinkStreamTransport2["WebSocketSecure"] = "webSocketSecure";
|
|
501
|
+
return ZlinkStreamTransport2;
|
|
502
|
+
})(ZlinkStreamTransport || {});
|
|
503
|
+
var ZlinkStreamCompression = /* @__PURE__ */ ((ZlinkStreamCompression2) => {
|
|
504
|
+
ZlinkStreamCompression2["None"] = "none";
|
|
505
|
+
ZlinkStreamCompression2["Lz4"] = "lz4";
|
|
506
|
+
return ZlinkStreamCompression2;
|
|
507
|
+
})(ZlinkStreamCompression || {});
|
|
508
|
+
var ZlinkStreamDispatchMode = /* @__PURE__ */ ((ZlinkStreamDispatchMode2) => {
|
|
509
|
+
ZlinkStreamDispatchMode2["Manual"] = "manual";
|
|
510
|
+
ZlinkStreamDispatchMode2["Immediate"] = "immediate";
|
|
511
|
+
return ZlinkStreamDispatchMode2;
|
|
512
|
+
})(ZlinkStreamDispatchMode || {});
|
|
513
|
+
var ZlinkStreamDiagnosticsLevel = /* @__PURE__ */ ((ZlinkStreamDiagnosticsLevel4) => {
|
|
514
|
+
ZlinkStreamDiagnosticsLevel4["Off"] = "off";
|
|
515
|
+
ZlinkStreamDiagnosticsLevel4["Errors"] = "errors";
|
|
516
|
+
ZlinkStreamDiagnosticsLevel4["Normal"] = "normal";
|
|
517
|
+
ZlinkStreamDiagnosticsLevel4["Detailed"] = "detailed";
|
|
518
|
+
return ZlinkStreamDiagnosticsLevel4;
|
|
519
|
+
})(ZlinkStreamDiagnosticsLevel || {});
|
|
520
|
+
var ZlinkStreamMessageKind = /* @__PURE__ */ ((ZlinkStreamMessageKind2) => {
|
|
521
|
+
ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Send"] = 1] = "Send";
|
|
522
|
+
ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Request"] = 2] = "Request";
|
|
523
|
+
ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Response"] = 3] = "Response";
|
|
524
|
+
ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Error"] = 4] = "Error";
|
|
525
|
+
ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Control"] = 5] = "Control";
|
|
526
|
+
return ZlinkStreamMessageKind2;
|
|
527
|
+
})(ZlinkStreamMessageKind || {});
|
|
528
|
+
var ZlinkStreamHeaderFlags = /* @__PURE__ */ ((ZlinkStreamHeaderFlags2) => {
|
|
529
|
+
ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["None"] = 0] = "None";
|
|
530
|
+
ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasRequestSeq"] = 1] = "HasRequestSeq";
|
|
531
|
+
ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasMetadata"] = 2] = "HasMetadata";
|
|
532
|
+
ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["PayloadCompressed"] = 4] = "PayloadCompressed";
|
|
533
|
+
ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasCorrelationId"] = 8] = "HasCorrelationId";
|
|
534
|
+
ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasFlowId"] = 16] = "HasFlowId";
|
|
535
|
+
return ZlinkStreamHeaderFlags2;
|
|
536
|
+
})(ZlinkStreamHeaderFlags || {});
|
|
537
|
+
var ZlinkStreamErrorCode = /* @__PURE__ */ ((ZlinkStreamErrorCode2) => {
|
|
538
|
+
ZlinkStreamErrorCode2["Disconnected"] = "disconnected";
|
|
539
|
+
ZlinkStreamErrorCode2["ConfigurationError"] = "configurationError";
|
|
540
|
+
ZlinkStreamErrorCode2["ValidationFailed"] = "validationFailed";
|
|
541
|
+
ZlinkStreamErrorCode2["RequestTimeout"] = "requestTimeout";
|
|
542
|
+
ZlinkStreamErrorCode2["ConnectTimeout"] = "connectTimeout";
|
|
543
|
+
ZlinkStreamErrorCode2["FrameDecodeFailed"] = "frameDecodeFailed";
|
|
544
|
+
ZlinkStreamErrorCode2["FrameTooLarge"] = "frameTooLarge";
|
|
545
|
+
ZlinkStreamErrorCode2["SendFailed"] = "sendFailed";
|
|
546
|
+
ZlinkStreamErrorCode2["CompressionFailed"] = "compressionFailed";
|
|
547
|
+
ZlinkStreamErrorCode2["DecompressionFailed"] = "decompressionFailed";
|
|
548
|
+
ZlinkStreamErrorCode2["UserCallbackFailed"] = "userCallbackFailed";
|
|
549
|
+
ZlinkStreamErrorCode2["RemoteError"] = "remoteError";
|
|
550
|
+
return ZlinkStreamErrorCode2;
|
|
551
|
+
})(ZlinkStreamErrorCode || {});
|
|
552
|
+
var ZlinkStreamConnectionState = /* @__PURE__ */ ((ZlinkStreamConnectionState3) => {
|
|
553
|
+
ZlinkStreamConnectionState3["Created"] = "created";
|
|
554
|
+
ZlinkStreamConnectionState3["Connecting"] = "connecting";
|
|
555
|
+
ZlinkStreamConnectionState3["Connected"] = "connected";
|
|
556
|
+
ZlinkStreamConnectionState3["Reconnecting"] = "reconnecting";
|
|
557
|
+
ZlinkStreamConnectionState3["Disconnected"] = "disconnected";
|
|
558
|
+
ZlinkStreamConnectionState3["Closed"] = "closed";
|
|
559
|
+
return ZlinkStreamConnectionState3;
|
|
560
|
+
})(ZlinkStreamConnectionState || {});
|
|
561
|
+
|
|
562
|
+
// packages/stream-connector/src/Contracts/ZlinkStreamMetadata.ts
|
|
563
|
+
var _ZlinkStreamMetadataMap = class _ZlinkStreamMetadataMap {
|
|
564
|
+
constructor(values) {
|
|
565
|
+
this.values = values;
|
|
566
|
+
}
|
|
567
|
+
get count() {
|
|
568
|
+
return this.values.size;
|
|
569
|
+
}
|
|
570
|
+
get(key) {
|
|
571
|
+
return this.values.get(key);
|
|
572
|
+
}
|
|
573
|
+
with(key, value) {
|
|
574
|
+
validateMetadataKey(key);
|
|
575
|
+
const next = new Map(this.values);
|
|
576
|
+
next.set(key, value);
|
|
577
|
+
return new _ZlinkStreamMetadataMap(next);
|
|
578
|
+
}
|
|
579
|
+
withMany(values) {
|
|
580
|
+
const next = new Map(this.values);
|
|
581
|
+
for (const [key, value] of values) {
|
|
582
|
+
validateMetadataKey(key);
|
|
583
|
+
next.set(key, value);
|
|
584
|
+
}
|
|
585
|
+
return new _ZlinkStreamMetadataMap(next);
|
|
586
|
+
}
|
|
587
|
+
static from(values) {
|
|
588
|
+
return _ZlinkStreamMetadataMap.empty.withMany(values);
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
__publicField(_ZlinkStreamMetadataMap, "empty", new _ZlinkStreamMetadataMap(/* @__PURE__ */ new Map()));
|
|
592
|
+
var ZlinkStreamMetadataMap = _ZlinkStreamMetadataMap;
|
|
593
|
+
function validateMetadataKey(key) {
|
|
594
|
+
if (key.length === 0) {
|
|
595
|
+
throw new Error("Metadata key must not be empty.");
|
|
596
|
+
}
|
|
597
|
+
for (let index = 0; index < key.length; index++) {
|
|
598
|
+
const code = key.charCodeAt(index);
|
|
599
|
+
if (code < 32 || code > 126 || key[index] === "=") {
|
|
600
|
+
throw new Error('Metadata key must contain printable ASCII characters except "=".');
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// packages/stream-connector/src/Contracts/ZlinkStreamModels.ts
|
|
606
|
+
var ZlinkStreamException = class extends Error {
|
|
607
|
+
constructor(error) {
|
|
608
|
+
super(error.message);
|
|
609
|
+
this.error = error;
|
|
610
|
+
this.name = "ZlinkStreamException";
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
// packages/stream-connector/src/Contracts/ZlinkStreamJsonCodec.ts
|
|
615
|
+
var zlinkStreamJsonCodecName = "json";
|
|
616
|
+
var codecOptions = {};
|
|
617
|
+
var zlinkStreamJsonCodec = {
|
|
618
|
+
configure(options) {
|
|
619
|
+
codecOptions = options;
|
|
620
|
+
},
|
|
621
|
+
encode(payload, messageType) {
|
|
622
|
+
return toJson(payload, messageType);
|
|
623
|
+
},
|
|
624
|
+
decode(payload) {
|
|
625
|
+
return fromJson(payload);
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
function toJson(value, messageType) {
|
|
629
|
+
return {
|
|
630
|
+
codec: 1 /* Json */,
|
|
631
|
+
payload: new TextEncoder().encode(JSON.stringify(value, codecOptions.replacer)),
|
|
632
|
+
messageType: messageType != null ? messageType : inferMessageType(value)
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
function fromJson(payload) {
|
|
636
|
+
ensureJson(payload);
|
|
637
|
+
return JSON.parse(new TextDecoder().decode(payload.payload), safeJsonReviver);
|
|
638
|
+
}
|
|
639
|
+
function ensureJson(payload) {
|
|
640
|
+
if (payload.codec !== 1 /* Json */) {
|
|
641
|
+
throw new Error(`Stream payload codec is ${payload.codec}, not Json.`);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
function inferMessageType(value) {
|
|
645
|
+
var _a;
|
|
646
|
+
if (value === null || value === void 0) {
|
|
647
|
+
return void 0;
|
|
648
|
+
}
|
|
649
|
+
const constructor = (_a = Object.getPrototypeOf(value)) == null ? void 0 : _a.constructor;
|
|
650
|
+
return constructor === Object ? void 0 : constructor;
|
|
651
|
+
}
|
|
652
|
+
function safeJsonReviver(key, value) {
|
|
653
|
+
if (isPrototypeKey(key)) {
|
|
654
|
+
throw new Error(`JSON payload key '${key}' is not allowed.`);
|
|
655
|
+
}
|
|
656
|
+
if (codecOptions.reviver !== void 0) {
|
|
657
|
+
return codecOptions.reviver.call(this, key, value);
|
|
658
|
+
}
|
|
659
|
+
return value;
|
|
660
|
+
}
|
|
661
|
+
function isPrototypeKey(key) {
|
|
662
|
+
return key === "__proto__" || key === "constructor" || key === "prototype";
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamSupport.ts
|
|
666
|
+
function connectorError(code, message, cause) {
|
|
667
|
+
return new ZlinkStreamException({ code, message, cause });
|
|
668
|
+
}
|
|
669
|
+
function toStreamError(cause, code, message) {
|
|
670
|
+
if (cause instanceof ZlinkStreamException) {
|
|
671
|
+
return cause.error;
|
|
672
|
+
}
|
|
673
|
+
return { code, message, cause };
|
|
674
|
+
}
|
|
675
|
+
function unwrapStreamError(error) {
|
|
676
|
+
if (error instanceof ZlinkStreamException) {
|
|
677
|
+
return error.error;
|
|
678
|
+
}
|
|
679
|
+
return { code: "remoteError" /* RemoteError */, message: error instanceof Error ? error.message : String(error), cause: error };
|
|
680
|
+
}
|
|
681
|
+
function subscription(dispose) {
|
|
682
|
+
return { dispose };
|
|
683
|
+
}
|
|
684
|
+
function throwIfAborted(signal) {
|
|
685
|
+
if ((signal == null ? void 0 : signal.aborted) === true) {
|
|
686
|
+
throw connectorError("disconnected" /* Disconnected */, "Operation canceled.");
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
function delay(delayMs, signal) {
|
|
690
|
+
throwIfAborted(signal);
|
|
691
|
+
return new Promise((resolve, reject) => {
|
|
692
|
+
const timeout = setTimeout(() => {
|
|
693
|
+
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
694
|
+
resolve();
|
|
695
|
+
}, delayMs);
|
|
696
|
+
const onAbort = () => {
|
|
697
|
+
clearTimeout(timeout);
|
|
698
|
+
reject(connectorError("disconnected" /* Disconnected */, "Operation canceled."));
|
|
699
|
+
};
|
|
700
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
function utf8Encode2(value) {
|
|
704
|
+
return new TextEncoder().encode(value);
|
|
705
|
+
}
|
|
706
|
+
function utf8Decode2(value) {
|
|
707
|
+
return new TextDecoder().decode(value);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// packages/stream-connector/src/Runtime/Protocol/ZlinkStreamPacketNameValidator.ts
|
|
711
|
+
function validateName(name, allowReserved = false) {
|
|
712
|
+
if (name.length === 0) {
|
|
713
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Message name must not be empty.");
|
|
714
|
+
}
|
|
715
|
+
if (!allowReserved && name.startsWith("$zlink.")) {
|
|
716
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Message name uses a reserved zlink prefix.");
|
|
717
|
+
}
|
|
718
|
+
if (utf8Encode2(name).length > 255) {
|
|
719
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Message name must not exceed 255 UTF-8 bytes.");
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// packages/stream-connector/src/Runtime/Calls/ZlinkStreamCallBuilders.ts
|
|
724
|
+
var ZlinkStreamCallBuilderState = class {
|
|
725
|
+
constructor(name) {
|
|
726
|
+
__publicField(this, "executed", false);
|
|
727
|
+
__publicField(this, "name");
|
|
728
|
+
__publicField(this, "metadata", ZlinkStreamMetadataMap.empty);
|
|
729
|
+
__publicField(this, "timeoutMs");
|
|
730
|
+
__publicField(this, "compress", false);
|
|
731
|
+
__publicField(this, "flow");
|
|
732
|
+
this.name = name;
|
|
733
|
+
}
|
|
734
|
+
ensureNotExecuted() {
|
|
735
|
+
if (this.executed) {
|
|
736
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Builder instances can be executed only once.");
|
|
737
|
+
}
|
|
738
|
+
this.executed = true;
|
|
739
|
+
}
|
|
740
|
+
resolveMessageName() {
|
|
741
|
+
if (this.name === void 0) {
|
|
742
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Message name is required when the encoded stream payload has no message type.");
|
|
743
|
+
}
|
|
744
|
+
return this.name;
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
var ZlinkStreamSendBuilder = class {
|
|
748
|
+
constructor(connector, name, payload) {
|
|
749
|
+
this.connector = connector;
|
|
750
|
+
this.payload = payload;
|
|
751
|
+
__publicField(this, "state");
|
|
752
|
+
this.state = new ZlinkStreamCallBuilderState(name);
|
|
753
|
+
}
|
|
754
|
+
packetName(name) {
|
|
755
|
+
validateName(name);
|
|
756
|
+
this.state.name = name;
|
|
757
|
+
return this;
|
|
758
|
+
}
|
|
759
|
+
metadata(keyOrMetadata, value) {
|
|
760
|
+
this.state.metadata = typeof keyOrMetadata === "string" ? this.state.metadata.with(keyOrMetadata, value != null ? value : "") : keyOrMetadata;
|
|
761
|
+
return this;
|
|
762
|
+
}
|
|
763
|
+
compress() {
|
|
764
|
+
this.state.compress = true;
|
|
765
|
+
return this;
|
|
766
|
+
}
|
|
767
|
+
flowFrom(flow) {
|
|
768
|
+
this.state.flow = flow;
|
|
769
|
+
return this;
|
|
770
|
+
}
|
|
771
|
+
async submit(signal) {
|
|
772
|
+
throwIfAborted(signal);
|
|
773
|
+
this.state.ensureNotExecuted();
|
|
774
|
+
await this.connector.sendEncoded(
|
|
775
|
+
1 /* Send */,
|
|
776
|
+
this.state.resolveMessageName(),
|
|
777
|
+
this.payload,
|
|
778
|
+
this.state.metadata,
|
|
779
|
+
this.state.compress,
|
|
780
|
+
void 0,
|
|
781
|
+
signal,
|
|
782
|
+
this.state.flow
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
var ZlinkStreamRequestBuilder = class {
|
|
787
|
+
constructor(connector, name, payload) {
|
|
788
|
+
this.connector = connector;
|
|
789
|
+
this.payload = payload;
|
|
790
|
+
__publicField(this, "state");
|
|
791
|
+
this.state = new ZlinkStreamCallBuilderState(name);
|
|
792
|
+
}
|
|
793
|
+
packetName(name) {
|
|
794
|
+
validateName(name);
|
|
795
|
+
this.state.name = name;
|
|
796
|
+
return this;
|
|
797
|
+
}
|
|
798
|
+
metadata(keyOrMetadata, value) {
|
|
799
|
+
this.state.metadata = typeof keyOrMetadata === "string" ? this.state.metadata.with(keyOrMetadata, value != null ? value : "") : keyOrMetadata;
|
|
800
|
+
return this;
|
|
801
|
+
}
|
|
802
|
+
timeout(timeoutMs) {
|
|
803
|
+
this.state.timeoutMs = timeoutMs;
|
|
804
|
+
return this;
|
|
805
|
+
}
|
|
806
|
+
compress() {
|
|
807
|
+
this.state.compress = true;
|
|
808
|
+
return this;
|
|
809
|
+
}
|
|
810
|
+
flowFrom(flow) {
|
|
811
|
+
this.state.flow = flow;
|
|
812
|
+
return this;
|
|
813
|
+
}
|
|
814
|
+
submit(signalOrCallback) {
|
|
815
|
+
var _a;
|
|
816
|
+
this.state.ensureNotExecuted();
|
|
817
|
+
const operation = this.connector.requestEncoded(
|
|
818
|
+
this.state.resolveMessageName(),
|
|
819
|
+
this.payload,
|
|
820
|
+
this.state.metadata,
|
|
821
|
+
this.state.compress,
|
|
822
|
+
(_a = this.state.timeoutMs) != null ? _a : this.connector.options.requestTimeoutMs,
|
|
823
|
+
typeof signalOrCallback === "function" ? void 0 : signalOrCallback,
|
|
824
|
+
this.state.flow
|
|
825
|
+
);
|
|
826
|
+
if (typeof signalOrCallback === "function") {
|
|
827
|
+
operation.then(
|
|
828
|
+
(value) => signalOrCallback({ isSuccess: true, value }),
|
|
829
|
+
(error) => signalOrCallback({ isSuccess: false, error: unwrapStreamError(error) })
|
|
830
|
+
);
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
return operation.then((value) => {
|
|
834
|
+
var _a2;
|
|
835
|
+
return ((_a2 = this.connector.options.codec) != null ? _a2 : zlinkStreamJsonCodec).decode(value);
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
submitEncoded(signal) {
|
|
839
|
+
var _a;
|
|
840
|
+
this.state.ensureNotExecuted();
|
|
841
|
+
return this.connector.requestEncoded(
|
|
842
|
+
this.state.resolveMessageName(),
|
|
843
|
+
this.payload,
|
|
844
|
+
this.state.metadata,
|
|
845
|
+
this.state.compress,
|
|
846
|
+
(_a = this.state.timeoutMs) != null ? _a : this.connector.options.requestTimeoutMs,
|
|
847
|
+
signal,
|
|
848
|
+
this.state.flow
|
|
849
|
+
);
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
var ZlinkStreamWaitBuilder = class {
|
|
853
|
+
constructor(connector, name) {
|
|
854
|
+
this.connector = connector;
|
|
855
|
+
this.name = name;
|
|
856
|
+
__publicField(this, "executed", false);
|
|
857
|
+
__publicField(this, "timeoutMs");
|
|
858
|
+
__publicField(this, "predicate", () => true);
|
|
859
|
+
}
|
|
860
|
+
where(predicate) {
|
|
861
|
+
this.ensureConfigurable();
|
|
862
|
+
this.predicate = predicate;
|
|
863
|
+
return this;
|
|
864
|
+
}
|
|
865
|
+
timeout(timeoutMs) {
|
|
866
|
+
this.ensureConfigurable();
|
|
867
|
+
this.timeoutMs = timeoutMs;
|
|
868
|
+
return this;
|
|
869
|
+
}
|
|
870
|
+
submit(signal) {
|
|
871
|
+
var _a;
|
|
872
|
+
this.markExecuted();
|
|
873
|
+
return this.connector.waitForMessage(
|
|
874
|
+
this.name,
|
|
875
|
+
(_a = this.timeoutMs) != null ? _a : this.connector.options.waitTimeoutMs,
|
|
876
|
+
this.predicate,
|
|
877
|
+
signal
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
ensureConfigurable() {
|
|
881
|
+
if (this.executed) {
|
|
882
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Builder instances can be executed only once.");
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
markExecuted() {
|
|
886
|
+
this.ensureConfigurable();
|
|
887
|
+
this.executed = true;
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
|
|
891
|
+
// packages/stream-connector/src/Runtime/Calls/ZlinkStreamObservationBuilders.ts
|
|
892
|
+
var ZlinkStreamExpectNoneBuilder = class {
|
|
893
|
+
constructor(connector, name) {
|
|
894
|
+
this.connector = connector;
|
|
895
|
+
this.name = name;
|
|
896
|
+
__publicField(this, "windowMs");
|
|
897
|
+
__publicField(this, "executed", false);
|
|
898
|
+
}
|
|
899
|
+
within(windowMs) {
|
|
900
|
+
this.ensureConfigurable();
|
|
901
|
+
validateTimeout(windowMs);
|
|
902
|
+
this.windowMs = windowMs;
|
|
903
|
+
return this;
|
|
904
|
+
}
|
|
905
|
+
async run(signal) {
|
|
906
|
+
this.markExecuted();
|
|
907
|
+
if (this.windowMs === void 0) {
|
|
908
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "expectNone requires within(windowMs).");
|
|
909
|
+
}
|
|
910
|
+
try {
|
|
911
|
+
await this.connector.waitForMessage(this.name, this.windowMs, () => true, signal);
|
|
912
|
+
} catch (error) {
|
|
913
|
+
if (unwrapStreamError(error).code === "requestTimeout" /* RequestTimeout */) {
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
throw error;
|
|
917
|
+
}
|
|
918
|
+
throw connectorError(
|
|
919
|
+
"validationFailed" /* ValidationFailed */,
|
|
920
|
+
`Expected no '${this.name}' message within ${this.windowMs}ms.`
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
ensureConfigurable() {
|
|
924
|
+
if (this.executed) {
|
|
925
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Builder instances can be executed only once.");
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
markExecuted() {
|
|
929
|
+
this.ensureConfigurable();
|
|
930
|
+
this.executed = true;
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
var ZlinkStreamSequenceBuilder = class {
|
|
934
|
+
constructor(connector, name) {
|
|
935
|
+
this.connector = connector;
|
|
936
|
+
this.name = name;
|
|
937
|
+
__publicField(this, "predicates", []);
|
|
938
|
+
__publicField(this, "timeoutMs");
|
|
939
|
+
__publicField(this, "executed", false);
|
|
940
|
+
}
|
|
941
|
+
expect(predicate) {
|
|
942
|
+
this.ensureConfigurable();
|
|
943
|
+
this.predicates.push(predicate);
|
|
944
|
+
return this;
|
|
945
|
+
}
|
|
946
|
+
timeout(timeoutMs) {
|
|
947
|
+
this.ensureConfigurable();
|
|
948
|
+
validateTimeout(timeoutMs);
|
|
949
|
+
this.timeoutMs = timeoutMs;
|
|
950
|
+
return this;
|
|
951
|
+
}
|
|
952
|
+
async run(signal) {
|
|
953
|
+
var _a;
|
|
954
|
+
this.markExecuted();
|
|
955
|
+
if (this.predicates.length === 0) {
|
|
956
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "waitForSequence requires at least one expectation.");
|
|
957
|
+
}
|
|
958
|
+
const timeoutMs = (_a = this.timeoutMs) != null ? _a : this.connector.options.waitTimeoutMs;
|
|
959
|
+
const deadline = Date.now() + timeoutMs;
|
|
960
|
+
const payloads = [];
|
|
961
|
+
for (const predicate of this.predicates) {
|
|
962
|
+
const message = await this.connector.waitForMessage(
|
|
963
|
+
this.name,
|
|
964
|
+
Math.max(0, deadline - Date.now()),
|
|
965
|
+
(candidate) => {
|
|
966
|
+
if (!predicate(candidate.payload)) {
|
|
967
|
+
throw connectorError(
|
|
968
|
+
"validationFailed" /* ValidationFailed */,
|
|
969
|
+
`Message '${this.name}' arrived out of the expected sequence.`
|
|
970
|
+
);
|
|
971
|
+
}
|
|
972
|
+
return true;
|
|
973
|
+
},
|
|
974
|
+
signal
|
|
975
|
+
);
|
|
976
|
+
payloads.push(message.payload);
|
|
977
|
+
}
|
|
978
|
+
return payloads;
|
|
979
|
+
}
|
|
980
|
+
ensureConfigurable() {
|
|
981
|
+
if (this.executed) {
|
|
982
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Builder instances can be executed only once.");
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
markExecuted() {
|
|
986
|
+
this.ensureConfigurable();
|
|
987
|
+
this.executed = true;
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
function validateTimeout(timeoutMs) {
|
|
991
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
|
|
992
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Timeout must be a non-negative finite number.");
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// packages/stream-connector/src/Runtime/Protocol/Compression/ZlinkStreamCompressionCodec.ts
|
|
997
|
+
var zlinkStreamLz4CompressionCodec = {
|
|
998
|
+
compress(payload) {
|
|
999
|
+
return lz4PickleUncompressed2(payload);
|
|
1000
|
+
},
|
|
1001
|
+
decompress(payload, maxDecompressedSize) {
|
|
1002
|
+
return lz4UnpicklePayload2(payload, maxDecompressedSize);
|
|
1003
|
+
}
|
|
1004
|
+
};
|
|
1005
|
+
function compressPayload(payload, compression, compressionCodec) {
|
|
1006
|
+
const codec = resolveCompressionCodec(compression, compressionCodec);
|
|
1007
|
+
if (codec === void 0) {
|
|
1008
|
+
throw connectorError("compressionFailed" /* CompressionFailed */, "Compression codec is not configured.");
|
|
1009
|
+
}
|
|
1010
|
+
return codec.compress(payload);
|
|
1011
|
+
}
|
|
1012
|
+
function decompressIfNeeded(header, payload, compression, compressionCodec, maxDecompressedSize) {
|
|
1013
|
+
if ((header.flags & 4 /* PayloadCompressed */) === 0) {
|
|
1014
|
+
return payload;
|
|
1015
|
+
}
|
|
1016
|
+
const codec = resolveCompressionCodec(compression, compressionCodec);
|
|
1017
|
+
if (codec === void 0) {
|
|
1018
|
+
throw connectorError("decompressionFailed" /* DecompressionFailed */, "Compression codec is not configured.");
|
|
1019
|
+
}
|
|
1020
|
+
try {
|
|
1021
|
+
const decompressed = codec.decompress(payload, maxDecompressedSize);
|
|
1022
|
+
if (decompressed.length > maxDecompressedSize) {
|
|
1023
|
+
throw new Error("Decoded payload exceeds MaxReceivePayloadSize.");
|
|
1024
|
+
}
|
|
1025
|
+
return decompressed;
|
|
1026
|
+
} catch (cause) {
|
|
1027
|
+
throw connectorError("decompressionFailed" /* DecompressionFailed */, "Decompression failed.", cause);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
function resolveCompressionCodec(compression, compressionCodec) {
|
|
1031
|
+
if (compression === "none" /* None */) {
|
|
1032
|
+
return void 0;
|
|
1033
|
+
}
|
|
1034
|
+
return compressionCodec != null ? compressionCodec : zlinkStreamLz4CompressionCodec;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// packages/stream-connector/src/Runtime/Protocol/ZlinkStreamFrameCodec.ts
|
|
1038
|
+
var ZlinkStreamFrameCodec = class {
|
|
1039
|
+
static encode(header, payload, maxPayloadSize = 64 * 1024) {
|
|
1040
|
+
validatePayload(payload.length, maxPayloadSize);
|
|
1041
|
+
try {
|
|
1042
|
+
return encodeStreamWireFrame(header, payload);
|
|
1043
|
+
} catch (cause) {
|
|
1044
|
+
throw connectorError("frameTooLarge" /* FrameTooLarge */, "Frame is too large.", cause);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
static decode(frame) {
|
|
1048
|
+
try {
|
|
1049
|
+
return decodeStreamWireFrame(frame);
|
|
1050
|
+
} catch (cause) {
|
|
1051
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Frame length does not match prefix.", cause);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
function splitZlinkStreamFrames(chunk) {
|
|
1056
|
+
if (chunk.length === 0) {
|
|
1057
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Stream frame prefix is incomplete.");
|
|
1058
|
+
}
|
|
1059
|
+
const frames = [];
|
|
1060
|
+
let offset = 0;
|
|
1061
|
+
while (offset < chunk.length) {
|
|
1062
|
+
const remaining = chunk.length - offset;
|
|
1063
|
+
if (remaining < 6) {
|
|
1064
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Stream frame prefix is incomplete.");
|
|
1065
|
+
}
|
|
1066
|
+
const headerLength = chunk[offset] << 8 | chunk[offset + 1];
|
|
1067
|
+
const payloadLength = chunk[offset + 2] * 16777216 + (chunk[offset + 3] << 16) + (chunk[offset + 4] << 8) + chunk[offset + 5];
|
|
1068
|
+
const frameLength = 6 + headerLength + payloadLength;
|
|
1069
|
+
if (frameLength > remaining) {
|
|
1070
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Frame length does not match prefix.");
|
|
1071
|
+
}
|
|
1072
|
+
frames.push(chunk.subarray(offset, offset + frameLength));
|
|
1073
|
+
offset += frameLength;
|
|
1074
|
+
}
|
|
1075
|
+
return frames;
|
|
1076
|
+
}
|
|
1077
|
+
function validatePayload(payloadLength, maxPayloadSize) {
|
|
1078
|
+
if (payloadLength > maxPayloadSize) {
|
|
1079
|
+
throw connectorError("frameTooLarge" /* FrameTooLarge */, "Payload exceeds MaxSendPayloadSize.");
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// packages/stream-connector/src/Runtime/Protocol/ZlinkStreamMetadataCodec.ts
|
|
1084
|
+
var ZLINK_STREAM_MAX_METADATA_BYTES = 1024;
|
|
1085
|
+
var ZlinkStreamMetadataCodec = class {
|
|
1086
|
+
static size(metadata) {
|
|
1087
|
+
try {
|
|
1088
|
+
const size = metadata.count === 0 ? 0 : encodeStreamWireMetadata(metadata.values).length;
|
|
1089
|
+
if (size > ZLINK_STREAM_MAX_METADATA_BYTES) {
|
|
1090
|
+
throw connectorError(
|
|
1091
|
+
"validationFailed" /* ValidationFailed */,
|
|
1092
|
+
`Metadata must not exceed ${ZLINK_STREAM_MAX_METADATA_BYTES} bytes.`
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
return size;
|
|
1096
|
+
} catch (cause) {
|
|
1097
|
+
throw connectorError("validationFailed" /* ValidationFailed */, streamWireErrorMessage(cause), cause);
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
static write(metadata, destination) {
|
|
1101
|
+
try {
|
|
1102
|
+
destination.set(encodeStreamWireMetadata(metadata.values));
|
|
1103
|
+
} catch (cause) {
|
|
1104
|
+
throw connectorError("validationFailed" /* ValidationFailed */, streamWireErrorMessage(cause), cause);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
static decode(metadata) {
|
|
1108
|
+
try {
|
|
1109
|
+
const values = decodeStreamWireMetadata(metadata);
|
|
1110
|
+
return values.size === 0 ? ZlinkStreamMetadataMap.empty : ZlinkStreamMetadataMap.from(values);
|
|
1111
|
+
} catch (cause) {
|
|
1112
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, streamWireErrorMessage(cause), cause);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
function streamWireErrorMessage(cause) {
|
|
1117
|
+
return cause instanceof Error ? cause.message : "Metadata is invalid.";
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
// packages/stream-connector/src/Runtime/Protocol/ZlinkStreamHeaderCodec.ts
|
|
1121
|
+
var ZlinkStreamHeaderCodec = class {
|
|
1122
|
+
static encode(header) {
|
|
1123
|
+
const reply = isReplyKind2(header.kind);
|
|
1124
|
+
if (!reply) validateName(header.name, header.kind === 5 /* Control */);
|
|
1125
|
+
validateHeaderSemantics(header);
|
|
1126
|
+
ZlinkStreamMetadataCodec.size(header.metadata);
|
|
1127
|
+
try {
|
|
1128
|
+
return encodeStreamWireHeader({
|
|
1129
|
+
kind: header.kind,
|
|
1130
|
+
codec: header.codec,
|
|
1131
|
+
flags: header.flags,
|
|
1132
|
+
requestSeq: header.requestSeq,
|
|
1133
|
+
name: header.name,
|
|
1134
|
+
metadata: header.metadata.values,
|
|
1135
|
+
correlationId: header.correlationId,
|
|
1136
|
+
flowId: header.flowId,
|
|
1137
|
+
flowOrigin: encodeFlowOrigin(header.flowOrigin)
|
|
1138
|
+
});
|
|
1139
|
+
} catch (cause) {
|
|
1140
|
+
throw connectorError("validationFailed" /* ValidationFailed */, streamWireErrorMessage2(cause), cause);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
/**
|
|
1144
|
+
* `includeFlow=false` (diagnostics Off, spec 27 §4) skips reading and
|
|
1145
|
+
* validating the inbound flow fields while the structural length checks in
|
|
1146
|
+
* the wire decoder are preserved.
|
|
1147
|
+
*/
|
|
1148
|
+
static decode(header, includeFlow = true) {
|
|
1149
|
+
let decoded;
|
|
1150
|
+
try {
|
|
1151
|
+
const wire = decodeStreamWireHeader(header, void 0, includeFlow);
|
|
1152
|
+
const metadata = wire.metadata.size === 0 ? ZlinkStreamMetadataMap.empty : ZlinkStreamMetadataMap.from(wire.metadata);
|
|
1153
|
+
decoded = {
|
|
1154
|
+
kind: wire.kind,
|
|
1155
|
+
codec: wire.codec,
|
|
1156
|
+
flags: wire.flags,
|
|
1157
|
+
requestSeq: wire.requestSeq,
|
|
1158
|
+
name: wire.name,
|
|
1159
|
+
metadata,
|
|
1160
|
+
correlationId: wire.correlationId,
|
|
1161
|
+
flowId: wire.flowId,
|
|
1162
|
+
flowOrigin: decodeFlowOrigin(wire.flowOrigin)
|
|
1163
|
+
};
|
|
1164
|
+
} catch (cause) {
|
|
1165
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, streamWireErrorMessage2(cause), cause);
|
|
1166
|
+
}
|
|
1167
|
+
validateEnum(decoded.kind, decoded.codec, decoded.flags);
|
|
1168
|
+
if (!isReplyKind2(decoded.kind)) {
|
|
1169
|
+
validateName(decoded.name, decoded.kind === 5 /* Control */);
|
|
1170
|
+
}
|
|
1171
|
+
validateHeaderSemantics(decoded);
|
|
1172
|
+
return decoded;
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
function isReplyKind2(kind) {
|
|
1176
|
+
return kind === 3 /* Response */ || kind === 4 /* Error */;
|
|
1177
|
+
}
|
|
1178
|
+
function streamWireErrorMessage2(cause) {
|
|
1179
|
+
return cause instanceof Error ? cause.message : "Stream header is invalid.";
|
|
1180
|
+
}
|
|
1181
|
+
function buildHeader(kind, name, codec, metadata, compress, requestSeq, correlationId, flowId, flowOrigin) {
|
|
1182
|
+
let flags = 0 /* None */;
|
|
1183
|
+
if (requestSeq !== void 0) {
|
|
1184
|
+
flags |= 1 /* HasRequestSeq */;
|
|
1185
|
+
}
|
|
1186
|
+
if (metadata.count > 0) {
|
|
1187
|
+
flags |= 2 /* HasMetadata */;
|
|
1188
|
+
}
|
|
1189
|
+
if (compress) {
|
|
1190
|
+
flags |= 4 /* PayloadCompressed */;
|
|
1191
|
+
}
|
|
1192
|
+
if (correlationId !== void 0 && correlationId.length > 0) {
|
|
1193
|
+
flags |= 8 /* HasCorrelationId */;
|
|
1194
|
+
}
|
|
1195
|
+
if (flowId !== void 0) flags |= 16 /* HasFlowId */;
|
|
1196
|
+
return { kind, codec, flags, requestSeq, name, metadata, correlationId, flowId, flowOrigin };
|
|
1197
|
+
}
|
|
1198
|
+
function validateHeaderSemantics(header) {
|
|
1199
|
+
validateEnum(header.kind, header.codec, header.flags);
|
|
1200
|
+
const hasRequestSeq = header.requestSeq !== void 0 || (header.flags & 1 /* HasRequestSeq */) !== 0;
|
|
1201
|
+
const hasMetadata = header.metadata.count > 0 || (header.flags & 2 /* HasMetadata */) !== 0;
|
|
1202
|
+
if (header.kind === 1 /* Send */ && hasRequestSeq) {
|
|
1203
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Send packet must not contain a request sequence.");
|
|
1204
|
+
}
|
|
1205
|
+
if ((header.kind === 2 /* Request */ || header.kind === 3 /* Response */) && !hasRequestSeq) {
|
|
1206
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Request and response packets must contain a request sequence.");
|
|
1207
|
+
}
|
|
1208
|
+
if (header.kind === 4 /* Error */ && header.codec !== 1 /* Json */) {
|
|
1209
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Error packet must use the JSON codec.");
|
|
1210
|
+
}
|
|
1211
|
+
if (header.kind === 5 /* Control */) {
|
|
1212
|
+
const hasCorrelation = header.correlationId !== void 0 && header.correlationId.length > 0 || (header.flags & 8 /* HasCorrelationId */) !== 0;
|
|
1213
|
+
const hasFlow = header.flowId !== void 0 || header.flowOrigin !== void 0 || (header.flags & 16 /* HasFlowId */) !== 0;
|
|
1214
|
+
if (header.flags !== 0 /* None */ || hasRequestSeq || hasMetadata || hasCorrelation || hasFlow || header.codec !== 0 /* Raw */) {
|
|
1215
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Control packet must use raw codec and must not contain flags.");
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
function validateEnum(kind, codec, flags) {
|
|
1220
|
+
if (![1, 2, 3, 4, 5].includes(kind)) {
|
|
1221
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown stream message kind.");
|
|
1222
|
+
}
|
|
1223
|
+
if (![0, 1, 2, 3].includes(codec)) {
|
|
1224
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown stream codec.");
|
|
1225
|
+
}
|
|
1226
|
+
const known = 1 /* HasRequestSeq */ | 2 /* HasMetadata */ | 4 /* PayloadCompressed */ | 8 /* HasCorrelationId */ | 16 /* HasFlowId */;
|
|
1227
|
+
if ((flags & ~known) !== 0) {
|
|
1228
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown stream header flag.");
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
function encodeFlowOrigin(origin) {
|
|
1232
|
+
return origin === void 0 ? void 0 : { Inbound: 1, Timer: 2, Application: 3, Lifecycle: 4 }[origin];
|
|
1233
|
+
}
|
|
1234
|
+
function decodeFlowOrigin(origin) {
|
|
1235
|
+
return origin === void 0 ? void 0 : { 1: "Inbound", 2: "Timer", 3: "Application", 4: "Lifecycle" }[origin];
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
// packages/stream-connector/src/Runtime/Protocol/ZlinkStreamFrameProtocol.ts
|
|
1239
|
+
var ZLINK_STREAM_HEARTBEAT_PING = "$zlink.heartbeat.ping";
|
|
1240
|
+
var ZLINK_STREAM_HEARTBEAT_PONG = "$zlink.heartbeat.pong";
|
|
1241
|
+
var ZlinkStreamFrameProtocol = class {
|
|
1242
|
+
constructor(options) {
|
|
1243
|
+
this.options = options;
|
|
1244
|
+
}
|
|
1245
|
+
encode(kind, name, payload, metadata, compress, requestSeq, correlationId, flowId, flowOrigin) {
|
|
1246
|
+
const payloadBytes = compress ? compressPayload(payload.payload, this.options.compression, this.options.compressionCodec) : payload.payload;
|
|
1247
|
+
const header = buildHeader(kind, name, payload.codec, metadata, compress, requestSeq, correlationId, flowId, flowOrigin);
|
|
1248
|
+
return this.encodeFrame(header, payloadBytes);
|
|
1249
|
+
}
|
|
1250
|
+
encodeControl(name, payload = new Uint8Array()) {
|
|
1251
|
+
return this.encodeFrame({
|
|
1252
|
+
kind: 5 /* Control */,
|
|
1253
|
+
codec: 0 /* Raw */,
|
|
1254
|
+
flags: 0 /* None */,
|
|
1255
|
+
name,
|
|
1256
|
+
metadata: ZlinkStreamMetadataMap.empty
|
|
1257
|
+
}, payload);
|
|
1258
|
+
}
|
|
1259
|
+
decode(frameBytes, flowEnabled = this.flowEnabled()) {
|
|
1260
|
+
const frame = ZlinkStreamFrameCodec.decode(frameBytes);
|
|
1261
|
+
return {
|
|
1262
|
+
// Spec 27 §4: with diagnostics Off the inbound flow fields are neither
|
|
1263
|
+
// read nor validated (structural length checks are preserved).
|
|
1264
|
+
header: ZlinkStreamHeaderCodec.decode(frame.header, flowEnabled),
|
|
1265
|
+
payload: frame.payload
|
|
1266
|
+
};
|
|
1267
|
+
}
|
|
1268
|
+
flowEnabled() {
|
|
1269
|
+
return this.options.diagnosticsLevel !== "off" /* Off */;
|
|
1270
|
+
}
|
|
1271
|
+
decodeFrames(chunk, flowEnabled = this.flowEnabled()) {
|
|
1272
|
+
return splitZlinkStreamFrames(chunk).map((frame) => {
|
|
1273
|
+
const decoded = this.decode(frame, flowEnabled);
|
|
1274
|
+
if (decoded.payload.length > this.options.maxReceivePayloadSize) {
|
|
1275
|
+
throw connectorError("frameTooLarge" /* FrameTooLarge */, "Payload exceeds MaxReceivePayloadSize.");
|
|
1276
|
+
}
|
|
1277
|
+
return decoded;
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
decodePayload(header, payload) {
|
|
1281
|
+
return decompressIfNeeded(
|
|
1282
|
+
header,
|
|
1283
|
+
payload,
|
|
1284
|
+
this.options.compression,
|
|
1285
|
+
this.options.compressionCodec,
|
|
1286
|
+
this.options.maxReceivePayloadSize
|
|
1287
|
+
);
|
|
1288
|
+
}
|
|
1289
|
+
encodeFrame(header, payload) {
|
|
1290
|
+
return ZlinkStreamFrameCodec.encode(
|
|
1291
|
+
ZlinkStreamHeaderCodec.encode(header),
|
|
1292
|
+
payload,
|
|
1293
|
+
this.options.maxSendPayloadSize
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1296
|
+
};
|
|
1297
|
+
|
|
1298
|
+
// packages/stream-connector/src/Runtime/Transport/ZlinkStreamEndpoint.ts
|
|
1299
|
+
function inferTransport(endpoint) {
|
|
1300
|
+
const url = parseEndpoint(endpoint);
|
|
1301
|
+
switch (url.protocol) {
|
|
1302
|
+
case "ws:":
|
|
1303
|
+
return "webSocket" /* WebSocket */;
|
|
1304
|
+
case "wss:":
|
|
1305
|
+
return "webSocketSecure" /* WebSocketSecure */;
|
|
1306
|
+
default:
|
|
1307
|
+
throw connectorError(
|
|
1308
|
+
"configurationError" /* ConfigurationError */,
|
|
1309
|
+
"The TypeScript Stream Connector supports only ws:// and wss:// endpoints."
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
function parseEndpoint(endpoint) {
|
|
1314
|
+
try {
|
|
1315
|
+
return new URL(endpoint);
|
|
1316
|
+
} catch (cause) {
|
|
1317
|
+
throw connectorError("configurationError" /* ConfigurationError */, "Endpoint is invalid.", cause);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamConnectorOptions.ts
|
|
1322
|
+
var validDiagnosticsLevels = /* @__PURE__ */ new Set([
|
|
1323
|
+
"off" /* Off */,
|
|
1324
|
+
"errors" /* Errors */,
|
|
1325
|
+
"normal" /* Normal */,
|
|
1326
|
+
"detailed" /* Detailed */
|
|
1327
|
+
]);
|
|
1328
|
+
function normalizeOptions(options, defaultTransportFactory) {
|
|
1329
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E;
|
|
1330
|
+
const endpoint = options.endpoint;
|
|
1331
|
+
if (endpoint.trim().length === 0) {
|
|
1332
|
+
throw connectorError("configurationError" /* ConfigurationError */, "Endpoint must not be empty.");
|
|
1333
|
+
}
|
|
1334
|
+
const inferredTransport = inferTransport(endpoint);
|
|
1335
|
+
if (options.transport !== void 0 && options.transport !== inferredTransport) {
|
|
1336
|
+
throw connectorError("configurationError" /* ConfigurationError */, "Configured transport conflicts with endpoint scheme.");
|
|
1337
|
+
}
|
|
1338
|
+
validatePositive((_a = options.connectTimeoutMs) != null ? _a : 5e3, "ConnectTimeout");
|
|
1339
|
+
validatePositive((_b = options.requestTimeoutMs) != null ? _b : 3e4, "RequestTimeout");
|
|
1340
|
+
validatePositive((_c = options.waitTimeoutMs) != null ? _c : 5e3, "WaitTimeout");
|
|
1341
|
+
validatePositive((_d = options.maxSendPayloadSize) != null ? _d : 64 * 1024, "MaxSendPayloadSize");
|
|
1342
|
+
validatePositive((_e = options.maxReceivePayloadSize) != null ? _e : 64 * 1024, "MaxReceivePayloadSize");
|
|
1343
|
+
validateHeartbeat(options.heartbeat);
|
|
1344
|
+
validateReconnect(options.reconnect);
|
|
1345
|
+
validateDiagnosticsLevel(options.diagnosticsLevel);
|
|
1346
|
+
return {
|
|
1347
|
+
endpoint,
|
|
1348
|
+
transport: inferredTransport,
|
|
1349
|
+
connectTimeoutMs: (_f = options.connectTimeoutMs) != null ? _f : 5e3,
|
|
1350
|
+
requestTimeoutMs: (_g = options.requestTimeoutMs) != null ? _g : 3e4,
|
|
1351
|
+
waitTimeoutMs: (_h = options.waitTimeoutMs) != null ? _h : 5e3,
|
|
1352
|
+
heartbeat: {
|
|
1353
|
+
enabled: (_j = (_i = options.heartbeat) == null ? void 0 : _i.enabled) != null ? _j : true,
|
|
1354
|
+
intervalMs: (_l = (_k = options.heartbeat) == null ? void 0 : _k.intervalMs) != null ? _l : 1e3,
|
|
1355
|
+
timeoutMs: (_n = (_m = options.heartbeat) == null ? void 0 : _m.timeoutMs) != null ? _n : 5e3
|
|
1356
|
+
},
|
|
1357
|
+
reconnect: {
|
|
1358
|
+
enabled: (_p = (_o = options.reconnect) == null ? void 0 : _o.enabled) != null ? _p : true,
|
|
1359
|
+
initialDelayMs: (_r = (_q = options.reconnect) == null ? void 0 : _q.initialDelayMs) != null ? _r : 250,
|
|
1360
|
+
maxDelayMs: (_t = (_s = options.reconnect) == null ? void 0 : _s.maxDelayMs) != null ? _t : 5e3,
|
|
1361
|
+
backoffFactor: (_v = (_u = options.reconnect) == null ? void 0 : _u.backoffFactor) != null ? _v : 2,
|
|
1362
|
+
maxAttempts: (_x = (_w = options.reconnect) == null ? void 0 : _w.maxAttempts) != null ? _x : 3
|
|
1363
|
+
},
|
|
1364
|
+
maxSendPayloadSize: (_y = options.maxSendPayloadSize) != null ? _y : 64 * 1024,
|
|
1365
|
+
maxReceivePayloadSize: (_z = options.maxReceivePayloadSize) != null ? _z : 64 * 1024,
|
|
1366
|
+
dispatchMode: (_A = options.dispatchMode) != null ? _A : "manual" /* Manual */,
|
|
1367
|
+
compression: (_B = options.compression) != null ? _B : "lz4" /* Lz4 */,
|
|
1368
|
+
compressionCodec: resolveCompressionCodec2(options),
|
|
1369
|
+
nameResolver: (_C = options.nameResolver) != null ? _C : { resolve: (type) => type.name },
|
|
1370
|
+
transportFactory: (_D = options.transportFactory) != null ? _D : defaultTransportFactory,
|
|
1371
|
+
codec: options.codec,
|
|
1372
|
+
meterProvider: options.meterProvider,
|
|
1373
|
+
// Spec 26 §4: the default diagnostics level is Errors, which preserves
|
|
1374
|
+
// the connector's established wire behavior.
|
|
1375
|
+
diagnosticsLevel: (_E = options.diagnosticsLevel) != null ? _E : "errors" /* Errors */
|
|
1376
|
+
};
|
|
1377
|
+
}
|
|
1378
|
+
function resolveCompressionCodec2(options) {
|
|
1379
|
+
var _a;
|
|
1380
|
+
const compression = (_a = options.compression) != null ? _a : "lz4" /* Lz4 */;
|
|
1381
|
+
if (compression === "none" /* None */) {
|
|
1382
|
+
if (options.compressionCodec !== void 0) {
|
|
1383
|
+
throw connectorError("configurationError" /* ConfigurationError */, "compressionCodec cannot be set when compression is none.");
|
|
1384
|
+
}
|
|
1385
|
+
return void 0;
|
|
1386
|
+
}
|
|
1387
|
+
return options.compressionCodec;
|
|
1388
|
+
}
|
|
1389
|
+
function validateDiagnosticsLevel(level) {
|
|
1390
|
+
if (level !== void 0 && !validDiagnosticsLevels.has(level)) {
|
|
1391
|
+
throw connectorError("configurationError" /* ConfigurationError */, "DiagnosticsLevel is invalid.");
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
function validatePositive(value, name) {
|
|
1395
|
+
if (value <= 0) {
|
|
1396
|
+
throw connectorError("validationFailed" /* ValidationFailed */, `${name} must be positive.`);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
function validateHeartbeat(options) {
|
|
1400
|
+
var _a, _b, _c;
|
|
1401
|
+
const enabled = (_a = options == null ? void 0 : options.enabled) != null ? _a : true;
|
|
1402
|
+
const intervalMs = (_b = options == null ? void 0 : options.intervalMs) != null ? _b : 1e3;
|
|
1403
|
+
const timeoutMs = (_c = options == null ? void 0 : options.timeoutMs) != null ? _c : 5e3;
|
|
1404
|
+
if (!enabled) {
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1407
|
+
validatePositive(intervalMs, "Heartbeat interval");
|
|
1408
|
+
validatePositive(timeoutMs, "Heartbeat timeout");
|
|
1409
|
+
if (timeoutMs <= intervalMs) {
|
|
1410
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Heartbeat timeout must be greater than the heartbeat interval.");
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
function validateReconnect(options) {
|
|
1414
|
+
var _a, _b, _c, _d, _e;
|
|
1415
|
+
const enabled = (_a = options == null ? void 0 : options.enabled) != null ? _a : true;
|
|
1416
|
+
if (!enabled) {
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
validatePositive((_b = options == null ? void 0 : options.initialDelayMs) != null ? _b : 250, "Reconnect InitialDelay");
|
|
1420
|
+
validatePositive((_c = options == null ? void 0 : options.maxDelayMs) != null ? _c : 5e3, "Reconnect MaxDelay");
|
|
1421
|
+
if (((_d = options == null ? void 0 : options.backoffFactor) != null ? _d : 2) < 1) {
|
|
1422
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Reconnect BackoffFactor must be at least 1.0.");
|
|
1423
|
+
}
|
|
1424
|
+
if (((_e = options == null ? void 0 : options.maxAttempts) != null ? _e : 3) <= 0) {
|
|
1425
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Reconnect MaxAttempts must be null or positive.");
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamDiagnosticsLevelCell.ts
|
|
1430
|
+
var ZlinkStreamDiagnosticsLevelCell = class {
|
|
1431
|
+
constructor(initial) {
|
|
1432
|
+
__publicField(this, "current");
|
|
1433
|
+
this.current = initial;
|
|
1434
|
+
}
|
|
1435
|
+
get level() {
|
|
1436
|
+
return this.current;
|
|
1437
|
+
}
|
|
1438
|
+
set(level) {
|
|
1439
|
+
const candidate = level;
|
|
1440
|
+
if (candidate === void 0 || candidate === null) {
|
|
1441
|
+
throw connectorError("configurationError" /* ConfigurationError */, "DiagnosticsLevel is invalid.");
|
|
1442
|
+
}
|
|
1443
|
+
validateDiagnosticsLevel(level);
|
|
1444
|
+
this.current = level;
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
|
|
1448
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamPendingRequests.ts
|
|
1449
|
+
var ZlinkStreamPendingRequests = class {
|
|
1450
|
+
constructor() {
|
|
1451
|
+
__publicField(this, "nextRequestSeq", 1n);
|
|
1452
|
+
__publicField(this, "active", /* @__PURE__ */ new Map());
|
|
1453
|
+
}
|
|
1454
|
+
get count() {
|
|
1455
|
+
return this.active.size;
|
|
1456
|
+
}
|
|
1457
|
+
create(packetName, timeoutMs) {
|
|
1458
|
+
const requestSeq = this.nextRequestSeq++;
|
|
1459
|
+
let timeout;
|
|
1460
|
+
let resolvePending;
|
|
1461
|
+
let rejectPending;
|
|
1462
|
+
const promise = new Promise((resolve, reject) => {
|
|
1463
|
+
timeout = setTimeout(() => {
|
|
1464
|
+
this.active.delete(requestSeq);
|
|
1465
|
+
reject(connectorError("requestTimeout" /* RequestTimeout */, `Request '${packetName}' timed out.`));
|
|
1466
|
+
}, timeoutMs);
|
|
1467
|
+
resolvePending = resolve;
|
|
1468
|
+
rejectPending = (error) => reject(connectorError(error.code, error.message, error.cause));
|
|
1469
|
+
});
|
|
1470
|
+
this.active.set(requestSeq, {
|
|
1471
|
+
packetName,
|
|
1472
|
+
promise,
|
|
1473
|
+
resolve: (value) => {
|
|
1474
|
+
if (timeout !== void 0) {
|
|
1475
|
+
clearTimeout(timeout);
|
|
1476
|
+
}
|
|
1477
|
+
resolvePending(value);
|
|
1478
|
+
},
|
|
1479
|
+
reject: (error) => {
|
|
1480
|
+
if (timeout !== void 0) {
|
|
1481
|
+
clearTimeout(timeout);
|
|
1482
|
+
}
|
|
1483
|
+
rejectPending(error);
|
|
1484
|
+
},
|
|
1485
|
+
cancel: () => {
|
|
1486
|
+
if (timeout !== void 0) {
|
|
1487
|
+
clearTimeout(timeout);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
});
|
|
1491
|
+
return { requestSeq, promise };
|
|
1492
|
+
}
|
|
1493
|
+
/* stream connector spec §5.2: a pending request is matched by request_seq alone. Diagnostics
|
|
1494
|
+
* use the original request name retained by this registry, never a legacy reply name. */
|
|
1495
|
+
resolve(requestSeq, value) {
|
|
1496
|
+
const pending = this.active.get(requestSeq);
|
|
1497
|
+
if (pending === void 0) {
|
|
1498
|
+
return false;
|
|
1499
|
+
}
|
|
1500
|
+
this.active.delete(requestSeq);
|
|
1501
|
+
pending.resolve(value);
|
|
1502
|
+
return true;
|
|
1503
|
+
}
|
|
1504
|
+
reject(requestSeq, error) {
|
|
1505
|
+
const pending = this.active.get(requestSeq);
|
|
1506
|
+
if (pending === void 0) {
|
|
1507
|
+
return false;
|
|
1508
|
+
}
|
|
1509
|
+
this.active.delete(requestSeq);
|
|
1510
|
+
pending.reject(error);
|
|
1511
|
+
return true;
|
|
1512
|
+
}
|
|
1513
|
+
cancel(requestSeq) {
|
|
1514
|
+
const pending = this.active.get(requestSeq);
|
|
1515
|
+
if (pending === void 0) {
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
this.active.delete(requestSeq);
|
|
1519
|
+
pending.cancel();
|
|
1520
|
+
}
|
|
1521
|
+
failAll(error) {
|
|
1522
|
+
for (const [requestSeq, pending] of this.active) {
|
|
1523
|
+
this.active.delete(requestSeq);
|
|
1524
|
+
pending.reject(error);
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
};
|
|
1528
|
+
|
|
1529
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamReceivedMessages.ts
|
|
1530
|
+
var ZlinkStreamReceivedMessages = class {
|
|
1531
|
+
/**
|
|
1532
|
+
* @param deliverOnArrival `Immediate` runs registered handlers on the receive
|
|
1533
|
+
* path; `Manual` leaves them queued until {@link pump} runs them on the
|
|
1534
|
+
* caller's thread (spec stream-connector 32 §7). Wait surfaces observe the
|
|
1535
|
+
* queue in both modes, so they never depend on this flag.
|
|
1536
|
+
*/
|
|
1537
|
+
constructor(events, deliverOnArrival) {
|
|
1538
|
+
this.events = events;
|
|
1539
|
+
this.deliverOnArrival = deliverOnArrival;
|
|
1540
|
+
__publicField(this, "handlers", /* @__PURE__ */ new Map());
|
|
1541
|
+
__publicField(this, "observers", /* @__PURE__ */ new Map());
|
|
1542
|
+
// A handler can be registered after messages for another name arrive, so the
|
|
1543
|
+
// queue is not a simple FIFO. Tombstones let us remove a deliverable entry
|
|
1544
|
+
// without shifting every later message on the hot receive path.
|
|
1545
|
+
__publicField(this, "queue", []);
|
|
1546
|
+
__publicField(this, "queueHead", 0);
|
|
1547
|
+
__publicField(this, "queuedCount", 0);
|
|
1548
|
+
__publicField(this, "drainTask");
|
|
1549
|
+
}
|
|
1550
|
+
on(name, handler) {
|
|
1551
|
+
validateName(name);
|
|
1552
|
+
let set = this.handlers.get(name);
|
|
1553
|
+
if (set === void 0) {
|
|
1554
|
+
set = /* @__PURE__ */ new Set();
|
|
1555
|
+
this.handlers.set(name, set);
|
|
1556
|
+
}
|
|
1557
|
+
set.add(handler);
|
|
1558
|
+
if (this.deliverOnArrival && this.hasQueuedMessage(name)) {
|
|
1559
|
+
queueMicrotask(() => this.scheduleDrain());
|
|
1560
|
+
}
|
|
1561
|
+
return subscription(() => {
|
|
1562
|
+
set.delete(handler);
|
|
1563
|
+
if (set.size === 0 && this.handlers.get(name) === set) {
|
|
1564
|
+
this.handlers.delete(name);
|
|
1565
|
+
}
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
/**
|
|
1569
|
+
* Registers a wait surface over the receive queue. Spec stream-connector 32
|
|
1570
|
+
* §7: these are not registered callbacks — they observe and consume the
|
|
1571
|
+
* packets the queue has not delivered yet, in both dispatch modes, so
|
|
1572
|
+
* `Manual` needs no dispatch pump to complete a wait. The queue is scanned in
|
|
1573
|
+
* a microtask so a message that arrived before the wait started is still
|
|
1574
|
+
* observed, and so the caller has its subscription in hand by then.
|
|
1575
|
+
*/
|
|
1576
|
+
observe(name, observer) {
|
|
1577
|
+
validateName(name);
|
|
1578
|
+
let set = this.observers.get(name);
|
|
1579
|
+
if (set === void 0) {
|
|
1580
|
+
set = /* @__PURE__ */ new Set();
|
|
1581
|
+
this.observers.set(name, set);
|
|
1582
|
+
}
|
|
1583
|
+
set.add(observer);
|
|
1584
|
+
queueMicrotask(() => {
|
|
1585
|
+
var _a;
|
|
1586
|
+
if (((_a = this.observers.get(name)) == null ? void 0 : _a.has(observer)) === true) {
|
|
1587
|
+
this.offerQueued(name, observer);
|
|
1588
|
+
}
|
|
1589
|
+
});
|
|
1590
|
+
return subscription(() => {
|
|
1591
|
+
set.delete(observer);
|
|
1592
|
+
if (set.size === 0 && this.observers.get(name) === set) {
|
|
1593
|
+
this.observers.delete(name);
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
}
|
|
1597
|
+
enqueue(message, signal) {
|
|
1598
|
+
var _a;
|
|
1599
|
+
for (const observer of [...(_a = this.observers.get(message.name)) != null ? _a : []]) {
|
|
1600
|
+
if (observer(message)) {
|
|
1601
|
+
return;
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
this.queue.push({ message, signal });
|
|
1605
|
+
this.queuedCount += 1;
|
|
1606
|
+
if (this.deliverOnArrival) {
|
|
1607
|
+
this.scheduleDrain();
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Runs the registered handlers the receive path left queued. `Manual` calls
|
|
1612
|
+
* this from `dispatch`; `Immediate` has already drained on arrival.
|
|
1613
|
+
*/
|
|
1614
|
+
async pump() {
|
|
1615
|
+
this.scheduleDrain();
|
|
1616
|
+
await this.drainTask;
|
|
1617
|
+
}
|
|
1618
|
+
offerQueued(name, observer) {
|
|
1619
|
+
for (let index = this.queueHead; index < this.queue.length; index += 1) {
|
|
1620
|
+
const queued = this.queue[index];
|
|
1621
|
+
if (queued === void 0 || queued.message.name !== name) {
|
|
1622
|
+
continue;
|
|
1623
|
+
}
|
|
1624
|
+
if (!observer(queued.message)) {
|
|
1625
|
+
continue;
|
|
1626
|
+
}
|
|
1627
|
+
this.removeAt(index);
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
scheduleDrain() {
|
|
1632
|
+
if (this.drainTask !== void 0) {
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
this.drainTask = this.drain().finally(() => {
|
|
1636
|
+
this.drainTask = void 0;
|
|
1637
|
+
if (this.deliverOnArrival && this.findDeliverableIndex() >= 0) {
|
|
1638
|
+
this.scheduleDrain();
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1641
|
+
}
|
|
1642
|
+
async drain() {
|
|
1643
|
+
for (let index = this.findDeliverableIndex(); index >= 0; index = this.findDeliverableIndex()) {
|
|
1644
|
+
const queued = this.queue[index];
|
|
1645
|
+
if (queued === void 0) continue;
|
|
1646
|
+
this.removeAt(index);
|
|
1647
|
+
const { message, signal } = queued;
|
|
1648
|
+
const handlers = [...this.handlers.get(message.name)];
|
|
1649
|
+
for (const handler of handlers) {
|
|
1650
|
+
try {
|
|
1651
|
+
await handler(message, signal);
|
|
1652
|
+
} catch (cause) {
|
|
1653
|
+
await this.events.publishError({
|
|
1654
|
+
code: "userCallbackFailed" /* UserCallbackFailed */,
|
|
1655
|
+
message: "Typed message handler failed.",
|
|
1656
|
+
cause
|
|
1657
|
+
}, signal);
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
removeAt(index) {
|
|
1663
|
+
this.queue[index] = void 0;
|
|
1664
|
+
this.queuedCount -= 1;
|
|
1665
|
+
this.advanceHead();
|
|
1666
|
+
this.compactQueue();
|
|
1667
|
+
}
|
|
1668
|
+
findDeliverableIndex() {
|
|
1669
|
+
var _a, _b;
|
|
1670
|
+
for (let index = this.queueHead; index < this.queue.length; index += 1) {
|
|
1671
|
+
const queued = this.queue[index];
|
|
1672
|
+
if (queued !== void 0 && ((_b = (_a = this.handlers.get(queued.message.name)) == null ? void 0 : _a.size) != null ? _b : 0) > 0) {
|
|
1673
|
+
return index;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
return -1;
|
|
1677
|
+
}
|
|
1678
|
+
hasQueuedMessage(name) {
|
|
1679
|
+
var _a;
|
|
1680
|
+
for (let index = this.queueHead; index < this.queue.length; index += 1) {
|
|
1681
|
+
if (((_a = this.queue[index]) == null ? void 0 : _a.message.name) === name) return true;
|
|
1682
|
+
}
|
|
1683
|
+
return false;
|
|
1684
|
+
}
|
|
1685
|
+
advanceHead() {
|
|
1686
|
+
while (this.queueHead < this.queue.length && this.queue[this.queueHead] === void 0) {
|
|
1687
|
+
this.queueHead += 1;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
compactQueue() {
|
|
1691
|
+
if (this.queuedCount === 0) {
|
|
1692
|
+
this.queue.length = 0;
|
|
1693
|
+
this.queueHead = 0;
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1696
|
+
if (this.queueHead >= 1024 && this.queueHead * 2 >= this.queue.length) {
|
|
1697
|
+
this.queue.splice(0, this.queueHead);
|
|
1698
|
+
this.queueHead = 0;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
};
|
|
1702
|
+
|
|
1703
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamFrameSender.ts
|
|
1704
|
+
var ZlinkStreamFrameSender = class {
|
|
1705
|
+
constructor(protocol, flowContext, metrics) {
|
|
1706
|
+
this.protocol = protocol;
|
|
1707
|
+
this.flowContext = flowContext;
|
|
1708
|
+
this.metrics = metrics;
|
|
1709
|
+
__publicField(this, "pendingWrites", /* @__PURE__ */ new Set());
|
|
1710
|
+
}
|
|
1711
|
+
async send(connection, kind, name, payload, metadata, compress, requestSeq, signal, correlationId, explicitFlow) {
|
|
1712
|
+
throwIfAborted(signal);
|
|
1713
|
+
const flow = this.protocol.flowEnabled() ? this.flowContext.currentOrCreate(explicitFlow) : void 0;
|
|
1714
|
+
await this.write(
|
|
1715
|
+
connection,
|
|
1716
|
+
this.protocol.encode(kind, name, payload, metadata, compress, requestSeq, correlationId, flow == null ? void 0 : flow.flowId, flow == null ? void 0 : flow.flowOrigin),
|
|
1717
|
+
signal
|
|
1718
|
+
);
|
|
1719
|
+
}
|
|
1720
|
+
async sendControl(connection, name, signal) {
|
|
1721
|
+
await this.write(connection, this.protocol.encodeControl(name), signal);
|
|
1722
|
+
}
|
|
1723
|
+
async drain(signal) {
|
|
1724
|
+
while (this.pendingWrites.size > 0) {
|
|
1725
|
+
throwIfAborted(signal);
|
|
1726
|
+
await Promise.allSettled([...this.pendingWrites]);
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
async write(connection, frame, signal) {
|
|
1730
|
+
const write = connection.write(frame, signal);
|
|
1731
|
+
this.pendingWrites.add(write);
|
|
1732
|
+
try {
|
|
1733
|
+
await write;
|
|
1734
|
+
this.metrics.outbound(frame.byteLength);
|
|
1735
|
+
} finally {
|
|
1736
|
+
this.pendingWrites.delete(write);
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
};
|
|
1740
|
+
|
|
1741
|
+
// packages/stream-connector/src/Runtime/Protocol/ZlinkSessionClosing.ts
|
|
1742
|
+
var ZLINK_SESSION_CLOSING = "session-closing";
|
|
1743
|
+
var reasons = {
|
|
1744
|
+
1: "ClientClose",
|
|
1745
|
+
2: "IdleTimeout",
|
|
1746
|
+
3: "HeartbeatTimeout",
|
|
1747
|
+
4: "ServerDrain",
|
|
1748
|
+
5: "ProtocolError",
|
|
1749
|
+
6: "TransportError"
|
|
1750
|
+
};
|
|
1751
|
+
function decodeSessionClosing(payload) {
|
|
1752
|
+
if (payload.length < 4 || payload[0] !== 1) throw new Error("Unsupported session-closing version.");
|
|
1753
|
+
const closeReason = reasons[payload[1]];
|
|
1754
|
+
if (closeReason === void 0) throw new Error("Unknown session-closing reason.");
|
|
1755
|
+
const length = payload[2] << 8 | payload[3];
|
|
1756
|
+
if (length > 512 || payload.length !== 4 + length) throw new Error("Invalid session-closing diagnostic length.");
|
|
1757
|
+
const diagnostic = length === 0 ? void 0 : new TextDecoder("utf-8", { fatal: true }).decode(payload.subarray(4));
|
|
1758
|
+
return { closeReason, diagnostic };
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamReceiveDispatcher.ts
|
|
1762
|
+
var ZlinkStreamReceiveDispatcher = class {
|
|
1763
|
+
constructor(protocol, pendingRequests, receivedMessages, frameSender, events, flowContext, metrics, serverClosing) {
|
|
1764
|
+
this.protocol = protocol;
|
|
1765
|
+
this.pendingRequests = pendingRequests;
|
|
1766
|
+
this.receivedMessages = receivedMessages;
|
|
1767
|
+
this.frameSender = frameSender;
|
|
1768
|
+
this.events = events;
|
|
1769
|
+
this.flowContext = flowContext;
|
|
1770
|
+
this.metrics = metrics;
|
|
1771
|
+
this.serverClosing = serverClosing;
|
|
1772
|
+
}
|
|
1773
|
+
async readAndDispatch(connection, signal, isCurrent) {
|
|
1774
|
+
if ((connection == null ? void 0 : connection.read) === void 0) {
|
|
1775
|
+
return { available: false, inbound: false };
|
|
1776
|
+
}
|
|
1777
|
+
const frameBytes = await connection.read(signal);
|
|
1778
|
+
if (isCurrent !== void 0 && !isCurrent()) {
|
|
1779
|
+
return { available: false, inbound: false };
|
|
1780
|
+
}
|
|
1781
|
+
if (frameBytes === void 0) {
|
|
1782
|
+
return { available: false, inbound: false };
|
|
1783
|
+
}
|
|
1784
|
+
this.metrics.inbound(frameBytes.byteLength);
|
|
1785
|
+
const flowEnabled = this.protocol.flowEnabled();
|
|
1786
|
+
let frames;
|
|
1787
|
+
try {
|
|
1788
|
+
frames = this.protocol.decodeFrames(frameBytes, flowEnabled);
|
|
1789
|
+
} catch (cause) {
|
|
1790
|
+
await this.events.publishError(
|
|
1791
|
+
toStreamError(cause, "frameDecodeFailed" /* FrameDecodeFailed */, "Frame decode failed."),
|
|
1792
|
+
signal
|
|
1793
|
+
);
|
|
1794
|
+
return { available: true, inbound: false };
|
|
1795
|
+
}
|
|
1796
|
+
for (const frame of frames) {
|
|
1797
|
+
try {
|
|
1798
|
+
await this.dispatch(connection, frame.header, frame.payload, signal, flowEnabled);
|
|
1799
|
+
} catch (cause) {
|
|
1800
|
+
if (frame.header.kind === 5 /* Control */ && frame.header.name === ZLINK_STREAM_HEARTBEAT_PING) {
|
|
1801
|
+
throw cause;
|
|
1802
|
+
}
|
|
1803
|
+
await this.events.publishError(
|
|
1804
|
+
toStreamError(cause, "frameDecodeFailed" /* FrameDecodeFailed */, "Frame dispatch failed."),
|
|
1805
|
+
signal
|
|
1806
|
+
);
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
return { available: true, inbound: true };
|
|
1810
|
+
}
|
|
1811
|
+
async dispatch(connection, header, payload, signal, flowEnabled) {
|
|
1812
|
+
if (header.kind === 3 /* Response */ && header.requestSeq !== void 0) {
|
|
1813
|
+
try {
|
|
1814
|
+
if (!this.pendingRequests.resolve(header.requestSeq, {
|
|
1815
|
+
codec: header.codec,
|
|
1816
|
+
payload: this.protocol.decodePayload(header, payload)
|
|
1817
|
+
})) {
|
|
1818
|
+
await this.events.publishError({
|
|
1819
|
+
code: "frameDecodeFailed" /* FrameDecodeFailed */,
|
|
1820
|
+
message: `Response request sequence '${header.requestSeq}' has no pending request.`
|
|
1821
|
+
}, signal);
|
|
1822
|
+
}
|
|
1823
|
+
} catch (cause) {
|
|
1824
|
+
const decodeError = toStreamError(
|
|
1825
|
+
cause,
|
|
1826
|
+
"decompressionFailed" /* DecompressionFailed */,
|
|
1827
|
+
"Decompression failed."
|
|
1828
|
+
);
|
|
1829
|
+
if (!this.pendingRequests.reject(
|
|
1830
|
+
header.requestSeq,
|
|
1831
|
+
decodeError
|
|
1832
|
+
)) {
|
|
1833
|
+
await this.events.publishError(decodeError, signal);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
return;
|
|
1837
|
+
}
|
|
1838
|
+
if (header.kind === 4 /* Error */ && header.requestSeq !== void 0) {
|
|
1839
|
+
try {
|
|
1840
|
+
const remoteError = decodeRemoteError(this.protocol, header, payload);
|
|
1841
|
+
if (!this.pendingRequests.reject(header.requestSeq, remoteError)) {
|
|
1842
|
+
await this.events.publishError(remoteError, signal);
|
|
1843
|
+
}
|
|
1844
|
+
} catch (cause) {
|
|
1845
|
+
const decodeError = toStreamError(
|
|
1846
|
+
cause,
|
|
1847
|
+
"frameDecodeFailed" /* FrameDecodeFailed */,
|
|
1848
|
+
"Remote error payload is invalid."
|
|
1849
|
+
);
|
|
1850
|
+
if (!this.pendingRequests.reject(
|
|
1851
|
+
header.requestSeq,
|
|
1852
|
+
decodeError
|
|
1853
|
+
)) {
|
|
1854
|
+
await this.events.publishError(decodeError, signal);
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
if (header.kind === 4 /* Error */) {
|
|
1860
|
+
await this.events.publishError(decodeRemoteError(this.protocol, header, payload), signal);
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
if (header.kind === 5 /* Control */) {
|
|
1864
|
+
await this.dispatchControl(connection, header, payload, signal);
|
|
1865
|
+
return;
|
|
1866
|
+
}
|
|
1867
|
+
if (header.kind === 1 /* Send */) {
|
|
1868
|
+
const flow = flowEnabled ? this.flowContext.createInbound(header.flowId, header.flowOrigin) : void 0;
|
|
1869
|
+
this.receivedMessages.enqueue({
|
|
1870
|
+
name: header.name,
|
|
1871
|
+
metadata: header.metadata,
|
|
1872
|
+
payload: { codec: header.codec, payload: this.protocol.decodePayload(header, payload) },
|
|
1873
|
+
flowId: flow == null ? void 0 : flow.flowId,
|
|
1874
|
+
flowOrigin: flow == null ? void 0 : flow.flowOrigin
|
|
1875
|
+
}, signal);
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
async dispatchControl(connection, header, payload, signal) {
|
|
1879
|
+
var _a;
|
|
1880
|
+
if (header.name === ZLINK_SESSION_CLOSING) {
|
|
1881
|
+
const closing = decodeSessionClosing(payload);
|
|
1882
|
+
await ((_a = this.serverClosing) == null ? void 0 : _a.call(this, closing.closeReason));
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
if (payload.length !== 0) {
|
|
1886
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Control packet payload must be empty.");
|
|
1887
|
+
}
|
|
1888
|
+
if (header.name === ZLINK_STREAM_HEARTBEAT_PING) {
|
|
1889
|
+
try {
|
|
1890
|
+
await this.frameSender.sendControl(connection, ZLINK_STREAM_HEARTBEAT_PONG, signal);
|
|
1891
|
+
} catch (cause) {
|
|
1892
|
+
throw connectorError(
|
|
1893
|
+
"sendFailed" /* SendFailed */,
|
|
1894
|
+
cause instanceof Error ? cause.message : "Heartbeat pong send failed."
|
|
1895
|
+
);
|
|
1896
|
+
}
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1899
|
+
if (header.name !== ZLINK_STREAM_HEARTBEAT_PONG) {
|
|
1900
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown control packet.");
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
};
|
|
1904
|
+
function decodeRemoteError(protocol, header, payload) {
|
|
1905
|
+
const decodedPayload = protocol.decodePayload(header, payload);
|
|
1906
|
+
let decoded;
|
|
1907
|
+
try {
|
|
1908
|
+
decoded = JSON.parse(utf8Decode2(decodedPayload));
|
|
1909
|
+
} catch (cause) {
|
|
1910
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Remote error payload must be a JSON object.", cause);
|
|
1911
|
+
}
|
|
1912
|
+
if (decoded === null || typeof decoded !== "object" || Array.isArray(decoded) || typeof decoded.code !== "string" || typeof decoded.message !== "string") {
|
|
1913
|
+
throw connectorError(
|
|
1914
|
+
"frameDecodeFailed" /* FrameDecodeFailed */,
|
|
1915
|
+
"Remote error payload must contain string code and message fields."
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
const remote = decoded;
|
|
1919
|
+
return { code: "remoteError" /* RemoteError */, message: remote.message, cause: remote };
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamConnectorLifecycle.ts
|
|
1923
|
+
var ZlinkStreamConnectorLifecycle = class {
|
|
1924
|
+
constructor(options, pendingRequests, frameSender, receiveDispatcher, receivedMessages, events, metrics) {
|
|
1925
|
+
this.options = options;
|
|
1926
|
+
this.pendingRequests = pendingRequests;
|
|
1927
|
+
this.frameSender = frameSender;
|
|
1928
|
+
this.receiveDispatcher = receiveDispatcher;
|
|
1929
|
+
this.receivedMessages = receivedMessages;
|
|
1930
|
+
this.events = events;
|
|
1931
|
+
this.metrics = metrics;
|
|
1932
|
+
__publicField(this, "receiveLoopAbort");
|
|
1933
|
+
__publicField(this, "receiveLoopSleeping", false);
|
|
1934
|
+
__publicField(this, "receiveLoopWake");
|
|
1935
|
+
__publicField(this, "receiveLoopSettled", []);
|
|
1936
|
+
__publicField(this, "currentConnection");
|
|
1937
|
+
__publicField(this, "connectionGeneration", 0);
|
|
1938
|
+
__publicField(this, "currentState", "created" /* Created */);
|
|
1939
|
+
__publicField(this, "heartbeatTimer");
|
|
1940
|
+
__publicField(this, "lastInboundAt", 0);
|
|
1941
|
+
__publicField(this, "closeTask");
|
|
1942
|
+
__publicField(this, "connectTask");
|
|
1943
|
+
__publicField(this, "disconnectTask");
|
|
1944
|
+
__publicField(this, "closeRequested", false);
|
|
1945
|
+
__publicField(this, "disconnectedPublished", false);
|
|
1946
|
+
__publicField(this, "closeReasonValue");
|
|
1947
|
+
__publicField(this, "lateConnectCleanupError");
|
|
1948
|
+
}
|
|
1949
|
+
get isConnected() {
|
|
1950
|
+
return this.currentState === "connected" /* Connected */;
|
|
1951
|
+
}
|
|
1952
|
+
get state() {
|
|
1953
|
+
return this.currentState;
|
|
1954
|
+
}
|
|
1955
|
+
get closeReason() {
|
|
1956
|
+
return this.closeReasonValue;
|
|
1957
|
+
}
|
|
1958
|
+
async connect(signal) {
|
|
1959
|
+
var _a;
|
|
1960
|
+
throwIfAborted(signal);
|
|
1961
|
+
await ((_a = this.disconnectTask) == null ? void 0 : _a.catch(() => void 0));
|
|
1962
|
+
if (this.closeRequested || this.currentState === "closed" /* Closed */) {
|
|
1963
|
+
throw connectorError("disconnected" /* Disconnected */, "Connector is closed.");
|
|
1964
|
+
}
|
|
1965
|
+
if (this.currentState === "connected" /* Connected */) {
|
|
1966
|
+
return;
|
|
1967
|
+
}
|
|
1968
|
+
if (this.connectTask !== void 0) {
|
|
1969
|
+
return await this.connectTask;
|
|
1970
|
+
}
|
|
1971
|
+
this.connectTask = this.connectOnce(signal).finally(() => {
|
|
1972
|
+
this.connectTask = void 0;
|
|
1973
|
+
});
|
|
1974
|
+
return await this.connectTask;
|
|
1975
|
+
}
|
|
1976
|
+
async connectOnce(signal) {
|
|
1977
|
+
await this.setState("connecting" /* Connecting */, void 0, signal);
|
|
1978
|
+
try {
|
|
1979
|
+
const connection = await this.connectWithReconnect(signal);
|
|
1980
|
+
if (this.closeRequested) {
|
|
1981
|
+
try {
|
|
1982
|
+
await connection.close(signal);
|
|
1983
|
+
} catch (error) {
|
|
1984
|
+
this.lateConnectCleanupError = error;
|
|
1985
|
+
throw error;
|
|
1986
|
+
}
|
|
1987
|
+
throw connectorError("disconnected" /* Disconnected */, "Connector closed while connecting.");
|
|
1988
|
+
}
|
|
1989
|
+
this.currentConnection = connection;
|
|
1990
|
+
this.connectionGeneration += 1;
|
|
1991
|
+
this.disconnectedPublished = false;
|
|
1992
|
+
this.lastInboundAt = Date.now();
|
|
1993
|
+
await this.setState("connected" /* Connected */, void 0, signal);
|
|
1994
|
+
this.startHeartbeat();
|
|
1995
|
+
this.startReceiveLoop();
|
|
1996
|
+
} catch (cause) {
|
|
1997
|
+
if (this.closeRequested) {
|
|
1998
|
+
const message = cause instanceof Error ? cause.message : "Connector closed while connecting.";
|
|
1999
|
+
const error2 = toStreamError(cause, "disconnected" /* Disconnected */, message);
|
|
2000
|
+
throw new ZlinkStreamException(error2);
|
|
2001
|
+
}
|
|
2002
|
+
const error = toStreamError(cause, "connectTimeout" /* ConnectTimeout */, "Connect failed.");
|
|
2003
|
+
await this.setState("disconnected" /* Disconnected */, error, signal);
|
|
2004
|
+
throw new ZlinkStreamException(error);
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
async close(signal) {
|
|
2008
|
+
this.closeReasonValue = "ClientClose";
|
|
2009
|
+
this.closeRequested = true;
|
|
2010
|
+
if (this.closeTask !== void 0) {
|
|
2011
|
+
return await this.closeTask;
|
|
2012
|
+
}
|
|
2013
|
+
if (this.currentState === "closed" /* Closed */) {
|
|
2014
|
+
return;
|
|
2015
|
+
}
|
|
2016
|
+
this.closeTask = this.closeOnce(signal).finally(() => {
|
|
2017
|
+
this.closeTask = void 0;
|
|
2018
|
+
});
|
|
2019
|
+
return await this.closeTask;
|
|
2020
|
+
}
|
|
2021
|
+
async serverClosing(reason) {
|
|
2022
|
+
this.closeReasonValue = reason;
|
|
2023
|
+
const error = { code: "disconnected" /* Disconnected */, message: `Server closed the session: ${reason}.` };
|
|
2024
|
+
await this.disconnectForTransportFailure(error, this.currentConnection, this.connectionGeneration);
|
|
2025
|
+
}
|
|
2026
|
+
async closeOnce(signal) {
|
|
2027
|
+
var _a, _b;
|
|
2028
|
+
await ((_a = this.connectTask) == null ? void 0 : _a.catch(() => void 0));
|
|
2029
|
+
await ((_b = this.disconnectTask) == null ? void 0 : _b.catch(() => void 0));
|
|
2030
|
+
const connection = this.currentConnection;
|
|
2031
|
+
this.stopHeartbeat();
|
|
2032
|
+
this.stopReceiveLoop();
|
|
2033
|
+
this.currentConnection = void 0;
|
|
2034
|
+
const errors = [];
|
|
2035
|
+
if (this.lateConnectCleanupError !== void 0) {
|
|
2036
|
+
errors.push(this.lateConnectCleanupError);
|
|
2037
|
+
this.lateConnectCleanupError = void 0;
|
|
2038
|
+
}
|
|
2039
|
+
try {
|
|
2040
|
+
await this.frameSender.drain(signal);
|
|
2041
|
+
} catch (error) {
|
|
2042
|
+
errors.push(error);
|
|
2043
|
+
}
|
|
2044
|
+
try {
|
|
2045
|
+
await (connection == null ? void 0 : connection.close(signal));
|
|
2046
|
+
} catch (error) {
|
|
2047
|
+
errors.push(error);
|
|
2048
|
+
}
|
|
2049
|
+
this.pendingRequests.failAll({ code: "disconnected" /* Disconnected */, message: "Connector closed." });
|
|
2050
|
+
await this.setState("closed" /* Closed */, void 0, signal);
|
|
2051
|
+
await this.publishDisconnectedOnce(signal);
|
|
2052
|
+
if (errors.length === 1) throw errors[0];
|
|
2053
|
+
if (errors.length > 1) throw new AggregateError(errors, "Stream connector close failed.");
|
|
2054
|
+
}
|
|
2055
|
+
/**
|
|
2056
|
+
* Spec stream-connector 32 §7: `dispatch` runs the callbacks the receive loop
|
|
2057
|
+
* queued, it does not drive the transport. Receiving is the receive loop's
|
|
2058
|
+
* job in both dispatch modes, which is what lets a `Manual` consumer complete
|
|
2059
|
+
* a `waitFor` without pumping, and what keeps this call from blocking on an
|
|
2060
|
+
* idle connection. In `Manual` it first lets the loop settle whatever has
|
|
2061
|
+
* already arrived, so a packet the transport is holding is delivered by this
|
|
2062
|
+
* pump rather than the next one.
|
|
2063
|
+
*/
|
|
2064
|
+
async dispatch(signal) {
|
|
2065
|
+
throwIfAborted(signal);
|
|
2066
|
+
if (this.options.dispatchMode !== "immediate" /* Immediate */) {
|
|
2067
|
+
await this.settleReceiveLoop();
|
|
2068
|
+
}
|
|
2069
|
+
await this.receivedMessages.pump();
|
|
2070
|
+
}
|
|
2071
|
+
connectionForSend() {
|
|
2072
|
+
if (this.currentConnection === void 0 || this.currentState !== "connected" /* Connected */) {
|
|
2073
|
+
throw connectorError("disconnected" /* Disconnected */, "Connector is not connected.");
|
|
2074
|
+
}
|
|
2075
|
+
return this.currentConnection;
|
|
2076
|
+
}
|
|
2077
|
+
async dispatchAvailable(connection, generation, signal) {
|
|
2078
|
+
throwIfAborted(signal);
|
|
2079
|
+
const result = await this.receiveDispatcher.readAndDispatch(
|
|
2080
|
+
connection,
|
|
2081
|
+
signal,
|
|
2082
|
+
() => this.isCurrentConnection(connection, generation)
|
|
2083
|
+
);
|
|
2084
|
+
if (result.inbound && this.isCurrentConnection(connection, generation)) {
|
|
2085
|
+
this.lastInboundAt = Date.now();
|
|
2086
|
+
}
|
|
2087
|
+
return result.available;
|
|
2088
|
+
}
|
|
2089
|
+
async connectWithReconnect(signal) {
|
|
2090
|
+
let attempt = 0;
|
|
2091
|
+
let delayMs = this.options.reconnect.initialDelayMs;
|
|
2092
|
+
let lastError;
|
|
2093
|
+
const maxAttempts = this.options.reconnect.enabled ? this.options.reconnect.maxAttempts : 1;
|
|
2094
|
+
while (attempt < maxAttempts) {
|
|
2095
|
+
attempt += 1;
|
|
2096
|
+
if (attempt > 1) {
|
|
2097
|
+
this.metrics.reconnect();
|
|
2098
|
+
}
|
|
2099
|
+
const handshakeStartedAt = performance.now();
|
|
2100
|
+
try {
|
|
2101
|
+
const connection = await this.options.transportFactory.connect(this.options, signal);
|
|
2102
|
+
this.metrics.handshakeCompleted(handshakeStartedAt);
|
|
2103
|
+
return connection;
|
|
2104
|
+
} catch (cause) {
|
|
2105
|
+
this.metrics.handshakeCompleted(handshakeStartedAt);
|
|
2106
|
+
this.metrics.handshakeFailed(cause);
|
|
2107
|
+
lastError = toStreamError(cause, "connectTimeout" /* ConnectTimeout */, "Connect failed.");
|
|
2108
|
+
if (!this.options.reconnect.enabled || attempt >= maxAttempts) {
|
|
2109
|
+
break;
|
|
2110
|
+
}
|
|
2111
|
+
await this.setState("reconnecting" /* Reconnecting */, lastError, signal);
|
|
2112
|
+
await delay(delayMs, signal);
|
|
2113
|
+
delayMs = Math.min(
|
|
2114
|
+
this.options.reconnect.maxDelayMs,
|
|
2115
|
+
Math.ceil(delayMs * this.options.reconnect.backoffFactor)
|
|
2116
|
+
);
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
throw new ZlinkStreamException(
|
|
2120
|
+
lastError != null ? lastError : { code: "connectTimeout" /* ConnectTimeout */, message: "Connect failed." }
|
|
2121
|
+
);
|
|
2122
|
+
}
|
|
2123
|
+
startHeartbeat() {
|
|
2124
|
+
this.stopHeartbeat();
|
|
2125
|
+
if (!this.options.heartbeat.enabled) {
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
2128
|
+
this.heartbeatTimer = setInterval(() => {
|
|
2129
|
+
void this.runHeartbeatTick();
|
|
2130
|
+
}, this.options.heartbeat.intervalMs);
|
|
2131
|
+
}
|
|
2132
|
+
stopHeartbeat() {
|
|
2133
|
+
if (this.heartbeatTimer !== void 0) {
|
|
2134
|
+
clearInterval(this.heartbeatTimer);
|
|
2135
|
+
this.heartbeatTimer = void 0;
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
// Spec stream-connector 32 §7: the receive loop runs in both dispatch modes.
|
|
2139
|
+
// `Manual` only changes what the loop does with a frame — it queues the
|
|
2140
|
+
// registered callbacks instead of running them — never whether frames are
|
|
2141
|
+
// read off the transport.
|
|
2142
|
+
startReceiveLoop() {
|
|
2143
|
+
var _a;
|
|
2144
|
+
if (((_a = this.currentConnection) == null ? void 0 : _a.read) === void 0) {
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
this.stopReceiveLoop();
|
|
2148
|
+
const abort = new AbortController();
|
|
2149
|
+
const connection = this.currentConnection;
|
|
2150
|
+
const generation = this.connectionGeneration;
|
|
2151
|
+
this.receiveLoopAbort = abort;
|
|
2152
|
+
void this.runReceiveLoop(connection, generation, abort.signal);
|
|
2153
|
+
}
|
|
2154
|
+
stopReceiveLoop() {
|
|
2155
|
+
var _a;
|
|
2156
|
+
(_a = this.receiveLoopAbort) == null ? void 0 : _a.abort();
|
|
2157
|
+
this.receiveLoopAbort = void 0;
|
|
2158
|
+
this.receiveLoopSleeping = false;
|
|
2159
|
+
this.releaseReceiveLoopSettled();
|
|
2160
|
+
}
|
|
2161
|
+
async runReceiveLoop(connection, generation, signal) {
|
|
2162
|
+
try {
|
|
2163
|
+
while (this.shouldContinueReceiveLoop(connection, generation, signal)) {
|
|
2164
|
+
const dispatched = await this.dispatchAvailable(connection, generation, signal);
|
|
2165
|
+
if (!dispatched && this.shouldContinueReceiveLoop(connection, generation, signal)) {
|
|
2166
|
+
await this.sleepUntilWork(signal);
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
} catch (cause) {
|
|
2170
|
+
if (signal.aborted) return;
|
|
2171
|
+
const error = toStreamError(cause, "frameDecodeFailed" /* FrameDecodeFailed */, "Receive loop failed.");
|
|
2172
|
+
await this.disconnectForTransportFailure(error, connection, generation);
|
|
2173
|
+
} finally {
|
|
2174
|
+
this.receiveLoopSleeping = false;
|
|
2175
|
+
this.releaseReceiveLoopSettled();
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
// A transport whose read resolves only when a frame arrives parks the loop
|
|
2179
|
+
// inside that read; one that reports "nothing available" instead parks it
|
|
2180
|
+
// here. Both are the loop waiting for new data, and `dispatch` treats them
|
|
2181
|
+
// the same way.
|
|
2182
|
+
async sleepUntilWork(signal) {
|
|
2183
|
+
this.receiveLoopSleeping = true;
|
|
2184
|
+
this.releaseReceiveLoopSettled();
|
|
2185
|
+
try {
|
|
2186
|
+
await new Promise((resolve) => {
|
|
2187
|
+
const finish = () => {
|
|
2188
|
+
clearTimeout(timer);
|
|
2189
|
+
signal.removeEventListener("abort", onAbort);
|
|
2190
|
+
this.receiveLoopWake = void 0;
|
|
2191
|
+
resolve();
|
|
2192
|
+
};
|
|
2193
|
+
const onAbort = () => finish();
|
|
2194
|
+
const timer = setTimeout(finish, 1);
|
|
2195
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2196
|
+
this.receiveLoopWake = finish;
|
|
2197
|
+
});
|
|
2198
|
+
} finally {
|
|
2199
|
+
this.receiveLoopSleeping = false;
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
// Returns once the loop has consumed everything the transport already had.
|
|
2203
|
+
// A loop that is mid-batch, or parked inside a read that has not produced a
|
|
2204
|
+
// frame, is already caught up, so only a sleeping loop is woken and awaited.
|
|
2205
|
+
async settleReceiveLoop() {
|
|
2206
|
+
var _a;
|
|
2207
|
+
if (this.receiveLoopAbort === void 0 || !this.receiveLoopSleeping) {
|
|
2208
|
+
return;
|
|
2209
|
+
}
|
|
2210
|
+
const settled = new Promise((resolve) => {
|
|
2211
|
+
this.receiveLoopSettled.push(resolve);
|
|
2212
|
+
});
|
|
2213
|
+
(_a = this.receiveLoopWake) == null ? void 0 : _a.call(this);
|
|
2214
|
+
await settled;
|
|
2215
|
+
}
|
|
2216
|
+
releaseReceiveLoopSettled() {
|
|
2217
|
+
for (const resolve of this.receiveLoopSettled.splice(0)) {
|
|
2218
|
+
resolve();
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
shouldContinueReceiveLoop(connection, generation, signal) {
|
|
2222
|
+
return !signal.aborted && this.currentState === "connected" /* Connected */ && this.isCurrentConnection(connection, generation);
|
|
2223
|
+
}
|
|
2224
|
+
async runHeartbeatTick() {
|
|
2225
|
+
if (!this.isConnected) {
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2228
|
+
if (Date.now() - this.lastInboundAt > this.options.heartbeat.timeoutMs) {
|
|
2229
|
+
this.closeReasonValue = "HeartbeatTimeout";
|
|
2230
|
+
const error = { code: "disconnected" /* Disconnected */, message: "Heartbeat timed out." };
|
|
2231
|
+
await this.disconnectForTransportFailure(error, this.currentConnection, this.connectionGeneration);
|
|
2232
|
+
return;
|
|
2233
|
+
}
|
|
2234
|
+
const connection = this.currentConnection;
|
|
2235
|
+
const generation = this.connectionGeneration;
|
|
2236
|
+
try {
|
|
2237
|
+
await this.frameSender.sendControl(this.connectionForSend(), ZLINK_STREAM_HEARTBEAT_PING);
|
|
2238
|
+
} catch (cause) {
|
|
2239
|
+
const error = toStreamError(cause, "sendFailed" /* SendFailed */, "Heartbeat send failed.");
|
|
2240
|
+
await this.disconnectForTransportFailure(error, connection, generation);
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
async disconnectForTransportFailure(error, origin, generation) {
|
|
2244
|
+
var _a;
|
|
2245
|
+
(_a = this.closeReasonValue) != null ? _a : this.closeReasonValue = "TransportError";
|
|
2246
|
+
if (this.closeRequested || this.currentState === "closed" /* Closed */) {
|
|
2247
|
+
return;
|
|
2248
|
+
}
|
|
2249
|
+
if (origin !== void 0 && !this.isCurrentConnection(origin, generation)) {
|
|
2250
|
+
return;
|
|
2251
|
+
}
|
|
2252
|
+
if (this.disconnectTask !== void 0) {
|
|
2253
|
+
return await this.disconnectTask;
|
|
2254
|
+
}
|
|
2255
|
+
this.disconnectTask = this.disconnectOnce(error).finally(() => {
|
|
2256
|
+
this.disconnectTask = void 0;
|
|
2257
|
+
});
|
|
2258
|
+
return await this.disconnectTask;
|
|
2259
|
+
}
|
|
2260
|
+
isCurrentConnection(connection, generation) {
|
|
2261
|
+
return !this.closeRequested && this.currentConnection === connection && this.connectionGeneration === generation;
|
|
2262
|
+
}
|
|
2263
|
+
async disconnectOnce(error) {
|
|
2264
|
+
this.stopHeartbeat();
|
|
2265
|
+
this.stopReceiveLoop();
|
|
2266
|
+
const connection = this.currentConnection;
|
|
2267
|
+
this.currentConnection = void 0;
|
|
2268
|
+
this.pendingRequests.failAll(error);
|
|
2269
|
+
try {
|
|
2270
|
+
await (connection == null ? void 0 : connection.close());
|
|
2271
|
+
} catch {
|
|
2272
|
+
}
|
|
2273
|
+
if (this.closeRequested) return;
|
|
2274
|
+
await this.setState("disconnected" /* Disconnected */, error);
|
|
2275
|
+
await this.publishDisconnectedOnce();
|
|
2276
|
+
if (this.shouldReconnect()) {
|
|
2277
|
+
queueMicrotask(() => {
|
|
2278
|
+
void this.connect().catch(() => void 0);
|
|
2279
|
+
});
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
shouldReconnect() {
|
|
2283
|
+
return this.options.reconnect.enabled && !this.closeRequested;
|
|
2284
|
+
}
|
|
2285
|
+
async publishDisconnectedOnce(signal) {
|
|
2286
|
+
if (this.disconnectedPublished) return;
|
|
2287
|
+
this.disconnectedPublished = true;
|
|
2288
|
+
await this.events.publishDisconnected(signal);
|
|
2289
|
+
}
|
|
2290
|
+
async setState(current, error, signal) {
|
|
2291
|
+
const previous = this.currentState;
|
|
2292
|
+
this.currentState = current;
|
|
2293
|
+
if (previous === current && error === void 0) {
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2296
|
+
await this.events.publishStateChanged({ previous, current, error }, signal);
|
|
2297
|
+
if (error !== void 0) {
|
|
2298
|
+
await this.events.publishError(error, signal);
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
};
|
|
2302
|
+
|
|
2303
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamConnectorEvents.ts
|
|
2304
|
+
var ZlinkStreamConnectorEvents = class {
|
|
2305
|
+
constructor() {
|
|
2306
|
+
__publicField(this, "errorHandlers", /* @__PURE__ */ new Set());
|
|
2307
|
+
__publicField(this, "disconnectedHandlers", /* @__PURE__ */ new Set());
|
|
2308
|
+
__publicField(this, "stateHandlers", /* @__PURE__ */ new Set());
|
|
2309
|
+
}
|
|
2310
|
+
onError(handler) {
|
|
2311
|
+
this.errorHandlers.add(handler);
|
|
2312
|
+
return subscription(() => this.errorHandlers.delete(handler));
|
|
2313
|
+
}
|
|
2314
|
+
onDisconnected(handler) {
|
|
2315
|
+
this.disconnectedHandlers.add(handler);
|
|
2316
|
+
return subscription(() => this.disconnectedHandlers.delete(handler));
|
|
2317
|
+
}
|
|
2318
|
+
onStateChanged(handler) {
|
|
2319
|
+
this.stateHandlers.add(handler);
|
|
2320
|
+
return subscription(() => this.stateHandlers.delete(handler));
|
|
2321
|
+
}
|
|
2322
|
+
async publishError(error, signal) {
|
|
2323
|
+
await this.publish([...this.errorHandlers].map((handler) => () => handler(error, signal)));
|
|
2324
|
+
}
|
|
2325
|
+
async publishDisconnected(signal) {
|
|
2326
|
+
await this.publish([...this.disconnectedHandlers].map((handler) => () => handler(signal)));
|
|
2327
|
+
}
|
|
2328
|
+
async publishStateChanged(change, signal) {
|
|
2329
|
+
await this.publish([...this.stateHandlers].map((handler) => () => handler(change, signal)));
|
|
2330
|
+
}
|
|
2331
|
+
async publish(handlers) {
|
|
2332
|
+
await Promise.allSettled(handlers.map(async (handler) => handler()));
|
|
2333
|
+
}
|
|
2334
|
+
};
|
|
2335
|
+
|
|
2336
|
+
// packages/stream-connector/src/Runtime/ZlinkFlowContext.ts
|
|
2337
|
+
var BrowserZlinkFlowContext = class {
|
|
2338
|
+
currentOrCreate(explicit) {
|
|
2339
|
+
return explicit != null ? explicit : { flowId: this.createUuidV7(), flowOrigin: "Application" };
|
|
2340
|
+
}
|
|
2341
|
+
createInbound(flowId, flowOrigin) {
|
|
2342
|
+
return { flowId: flowId != null ? flowId : this.createUuidV7(), flowOrigin: flowOrigin != null ? flowOrigin : "Inbound" };
|
|
2343
|
+
}
|
|
2344
|
+
createUuidV7() {
|
|
2345
|
+
const crypto = globalThis.crypto;
|
|
2346
|
+
if (crypto === void 0) {
|
|
2347
|
+
throw connectorError(
|
|
2348
|
+
"configurationError" /* ConfigurationError */,
|
|
2349
|
+
"The browser entrypoint requires the platform Web Crypto API."
|
|
2350
|
+
);
|
|
2351
|
+
}
|
|
2352
|
+
return formatUuidV7(crypto.getRandomValues(new Uint8Array(16)));
|
|
2353
|
+
}
|
|
2354
|
+
};
|
|
2355
|
+
function formatUuidV7(bytes) {
|
|
2356
|
+
const timestamp = BigInt(Date.now());
|
|
2357
|
+
for (let index = 5; index >= 0; index -= 1) {
|
|
2358
|
+
bytes[index] = Number(timestamp >> BigInt((5 - index) * 8) & 0xffn);
|
|
2359
|
+
}
|
|
2360
|
+
bytes[6] = 112 | bytes[6] & 15;
|
|
2361
|
+
bytes[8] = 128 | bytes[8] & 63;
|
|
2362
|
+
const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
2363
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
// packages/stream-connector/src/Runtime/Transport/BrowserWebSocketConnection.ts
|
|
2367
|
+
var BrowserStreamTransportFactory = class {
|
|
2368
|
+
async connect(options, signal) {
|
|
2369
|
+
throwIfAborted(signal);
|
|
2370
|
+
const WebSocketConstructor = globalThis.WebSocket;
|
|
2371
|
+
if (WebSocketConstructor === void 0) {
|
|
2372
|
+
throw connectorError(
|
|
2373
|
+
"configurationError" /* ConfigurationError */,
|
|
2374
|
+
"The browser entrypoint requires the platform WebSocket API."
|
|
2375
|
+
);
|
|
2376
|
+
}
|
|
2377
|
+
const socket = new WebSocketConstructor(options.endpoint);
|
|
2378
|
+
socket.binaryType = "arraybuffer";
|
|
2379
|
+
await waitForOpen(socket, options.connectTimeoutMs, signal);
|
|
2380
|
+
return new BrowserWebSocketConnection(socket);
|
|
2381
|
+
}
|
|
2382
|
+
};
|
|
2383
|
+
var BrowserWebSocketConnection = class {
|
|
2384
|
+
constructor(socket) {
|
|
2385
|
+
this.socket = socket;
|
|
2386
|
+
__publicField(this, "messages", []);
|
|
2387
|
+
__publicField(this, "messageHead", 0);
|
|
2388
|
+
__publicField(this, "closed", false);
|
|
2389
|
+
__publicField(this, "error");
|
|
2390
|
+
__publicField(this, "readWaiter");
|
|
2391
|
+
__publicField(this, "onMessage", (event) => {
|
|
2392
|
+
try {
|
|
2393
|
+
const message = toUint8Array(event.data);
|
|
2394
|
+
this.messages.push(message);
|
|
2395
|
+
} catch (cause) {
|
|
2396
|
+
this.error = cause instanceof Error ? cause : connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "WebSocket message decode failed.", cause);
|
|
2397
|
+
this.closed = true;
|
|
2398
|
+
this.socket.close();
|
|
2399
|
+
}
|
|
2400
|
+
this.wakeReader();
|
|
2401
|
+
});
|
|
2402
|
+
__publicField(this, "onClose", () => {
|
|
2403
|
+
if (!this.closed) {
|
|
2404
|
+
this.error = connectorError("disconnected" /* Disconnected */, "Remote stream closed the WebSocket connection.");
|
|
2405
|
+
}
|
|
2406
|
+
this.closed = true;
|
|
2407
|
+
this.wakeReader();
|
|
2408
|
+
});
|
|
2409
|
+
__publicField(this, "onError", () => {
|
|
2410
|
+
this.error = connectorError("disconnected" /* Disconnected */, "Remote stream closed after a WebSocket error.");
|
|
2411
|
+
this.closed = true;
|
|
2412
|
+
this.wakeReader();
|
|
2413
|
+
});
|
|
2414
|
+
socket.addEventListener("message", this.onMessage);
|
|
2415
|
+
socket.addEventListener("close", this.onClose);
|
|
2416
|
+
socket.addEventListener("error", this.onError);
|
|
2417
|
+
}
|
|
2418
|
+
async write(frame, signal) {
|
|
2419
|
+
throwIfAborted(signal);
|
|
2420
|
+
if (this.closed || this.socket.readyState !== 1) {
|
|
2421
|
+
throw connectorError("disconnected" /* Disconnected */, "Remote stream is not connected.");
|
|
2422
|
+
}
|
|
2423
|
+
try {
|
|
2424
|
+
this.socket.send(frame);
|
|
2425
|
+
} catch (cause) {
|
|
2426
|
+
throw connectorError("sendFailed" /* SendFailed */, "Send failed.", cause);
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
async read(signal) {
|
|
2430
|
+
throwIfAborted(signal);
|
|
2431
|
+
for (; ; ) {
|
|
2432
|
+
const message = this.takeMessage();
|
|
2433
|
+
if (message !== void 0) {
|
|
2434
|
+
return message;
|
|
2435
|
+
}
|
|
2436
|
+
if (this.error !== void 0) {
|
|
2437
|
+
throw this.error;
|
|
2438
|
+
}
|
|
2439
|
+
if (this.closed) {
|
|
2440
|
+
return void 0;
|
|
2441
|
+
}
|
|
2442
|
+
await this.waitForMessage(signal);
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
async close(signal) {
|
|
2446
|
+
throwIfAborted(signal);
|
|
2447
|
+
if (!this.closed) {
|
|
2448
|
+
this.closed = true;
|
|
2449
|
+
this.socket.close();
|
|
2450
|
+
this.wakeReader();
|
|
2451
|
+
}
|
|
2452
|
+
try {
|
|
2453
|
+
await waitForClose(this.socket, signal);
|
|
2454
|
+
} finally {
|
|
2455
|
+
this.removeListeners();
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
waitForMessage(signal) {
|
|
2459
|
+
if (this.readWaiter !== void 0) {
|
|
2460
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Only one pending stream read is supported.");
|
|
2461
|
+
}
|
|
2462
|
+
return new Promise((resolve, reject) => {
|
|
2463
|
+
const onAbort = () => {
|
|
2464
|
+
this.readWaiter = void 0;
|
|
2465
|
+
reject(connectorError("disconnected" /* Disconnected */, "Operation canceled."));
|
|
2466
|
+
};
|
|
2467
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
2468
|
+
this.readWaiter = () => {
|
|
2469
|
+
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
2470
|
+
this.readWaiter = void 0;
|
|
2471
|
+
resolve();
|
|
2472
|
+
};
|
|
2473
|
+
if (this.hasQueuedMessage() || this.closed) {
|
|
2474
|
+
this.wakeReader();
|
|
2475
|
+
}
|
|
2476
|
+
});
|
|
2477
|
+
}
|
|
2478
|
+
wakeReader() {
|
|
2479
|
+
var _a;
|
|
2480
|
+
(_a = this.readWaiter) == null ? void 0 : _a.call(this);
|
|
2481
|
+
}
|
|
2482
|
+
removeListeners() {
|
|
2483
|
+
this.socket.removeEventListener("message", this.onMessage);
|
|
2484
|
+
this.socket.removeEventListener("close", this.onClose);
|
|
2485
|
+
this.socket.removeEventListener("error", this.onError);
|
|
2486
|
+
}
|
|
2487
|
+
hasQueuedMessage() {
|
|
2488
|
+
return this.messageHead < this.messages.length;
|
|
2489
|
+
}
|
|
2490
|
+
takeMessage() {
|
|
2491
|
+
if (!this.hasQueuedMessage()) return void 0;
|
|
2492
|
+
const message = this.messages[this.messageHead];
|
|
2493
|
+
this.messages[this.messageHead] = void 0;
|
|
2494
|
+
this.messageHead += 1;
|
|
2495
|
+
if (this.messageHead >= 1024 && this.messageHead * 2 >= this.messages.length) {
|
|
2496
|
+
this.messages.splice(0, this.messageHead);
|
|
2497
|
+
this.messageHead = 0;
|
|
2498
|
+
}
|
|
2499
|
+
return message;
|
|
2500
|
+
}
|
|
2501
|
+
};
|
|
2502
|
+
function waitForClose(socket, signal) {
|
|
2503
|
+
if (socket.readyState === 3) return Promise.resolve();
|
|
2504
|
+
return new Promise((resolve, reject) => {
|
|
2505
|
+
const onClose = () => finish();
|
|
2506
|
+
const onAbort = () => finish(connectorError("disconnected" /* Disconnected */, "Close canceled."));
|
|
2507
|
+
const finish = (error) => {
|
|
2508
|
+
socket.removeEventListener("close", onClose);
|
|
2509
|
+
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
2510
|
+
if (error === void 0) resolve();
|
|
2511
|
+
else reject(error);
|
|
2512
|
+
};
|
|
2513
|
+
socket.addEventListener("close", onClose, { once: true });
|
|
2514
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
2515
|
+
});
|
|
2516
|
+
}
|
|
2517
|
+
async function waitForOpen(socket, connectTimeoutMs, signal) {
|
|
2518
|
+
throwIfAborted(signal);
|
|
2519
|
+
await new Promise((resolve, reject) => {
|
|
2520
|
+
const timeout = setTimeout(() => finish(
|
|
2521
|
+
connectorError("connectTimeout" /* ConnectTimeout */, "Connect timed out.")
|
|
2522
|
+
), connectTimeoutMs);
|
|
2523
|
+
const onOpen = () => finish();
|
|
2524
|
+
const onClose = () => finish(connectorError("connectTimeout" /* ConnectTimeout */, "Connect closed before opening."));
|
|
2525
|
+
const onError = () => finish(connectorError("connectTimeout" /* ConnectTimeout */, "Connect failed."));
|
|
2526
|
+
const onAbort = () => finish(connectorError("disconnected" /* Disconnected */, "Connect canceled."));
|
|
2527
|
+
const finish = (error) => {
|
|
2528
|
+
clearTimeout(timeout);
|
|
2529
|
+
socket.removeEventListener("open", onOpen);
|
|
2530
|
+
socket.removeEventListener("close", onClose);
|
|
2531
|
+
socket.removeEventListener("error", onError);
|
|
2532
|
+
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
2533
|
+
if (error === void 0) {
|
|
2534
|
+
resolve();
|
|
2535
|
+
} else {
|
|
2536
|
+
socket.close();
|
|
2537
|
+
reject(error);
|
|
2538
|
+
}
|
|
2539
|
+
};
|
|
2540
|
+
socket.addEventListener("open", onOpen, { once: true });
|
|
2541
|
+
socket.addEventListener("close", onClose, { once: true });
|
|
2542
|
+
socket.addEventListener("error", onError, { once: true });
|
|
2543
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
2544
|
+
});
|
|
2545
|
+
}
|
|
2546
|
+
function toUint8Array(data) {
|
|
2547
|
+
if (data instanceof ArrayBuffer) {
|
|
2548
|
+
return new Uint8Array(data);
|
|
2549
|
+
}
|
|
2550
|
+
if (ArrayBuffer.isView(data)) {
|
|
2551
|
+
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
2552
|
+
}
|
|
2553
|
+
throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "WebSocket text messages are not supported.");
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamRuntimeMetrics.ts
|
|
2557
|
+
var ZlinkStreamRuntimeMetrics = class {
|
|
2558
|
+
constructor(options) {
|
|
2559
|
+
this.options = options;
|
|
2560
|
+
__publicField(this, "reconnects");
|
|
2561
|
+
__publicField(this, "handshakeDuration");
|
|
2562
|
+
__publicField(this, "handshakeFailures");
|
|
2563
|
+
__publicField(this, "inboundBytes");
|
|
2564
|
+
__publicField(this, "outboundBytes");
|
|
2565
|
+
var _a;
|
|
2566
|
+
const meter = (_a = options.meterProvider) == null ? void 0 : _a.getMeter("zlink.framework");
|
|
2567
|
+
this.reconnects = meter == null ? void 0 : meter.createCounter("zlink.stream.reconnects", { unit: "{event}" });
|
|
2568
|
+
this.handshakeDuration = meter == null ? void 0 : meter.createHistogram("zlink.stream.handshake.duration", { unit: "s" });
|
|
2569
|
+
this.handshakeFailures = meter == null ? void 0 : meter.createCounter("zlink.stream.handshake.failures", { unit: "{failure}" });
|
|
2570
|
+
this.inboundBytes = meter == null ? void 0 : meter.createCounter("zlink.stream.inbound.bytes", { unit: "By" });
|
|
2571
|
+
this.outboundBytes = meter == null ? void 0 : meter.createCounter("zlink.stream.outbound.bytes", { unit: "By" });
|
|
2572
|
+
}
|
|
2573
|
+
reconnect() {
|
|
2574
|
+
this.safe(() => {
|
|
2575
|
+
var _a;
|
|
2576
|
+
return (_a = this.reconnects) == null ? void 0 : _a.add(1, { transport: this.transportLabel() });
|
|
2577
|
+
});
|
|
2578
|
+
}
|
|
2579
|
+
handshakeCompleted(startedAt) {
|
|
2580
|
+
const seconds = (performance.now() - startedAt) / 1e3;
|
|
2581
|
+
this.safe(() => {
|
|
2582
|
+
var _a;
|
|
2583
|
+
return (_a = this.handshakeDuration) == null ? void 0 : _a.record(seconds, { transport: this.transportLabel() });
|
|
2584
|
+
});
|
|
2585
|
+
}
|
|
2586
|
+
handshakeFailed(error) {
|
|
2587
|
+
const reason = error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError") ? "canceled" : "transport_error";
|
|
2588
|
+
this.safe(() => {
|
|
2589
|
+
var _a;
|
|
2590
|
+
return (_a = this.handshakeFailures) == null ? void 0 : _a.add(1, { transport: this.transportLabel(), reason });
|
|
2591
|
+
});
|
|
2592
|
+
}
|
|
2593
|
+
inbound(byteCount) {
|
|
2594
|
+
this.safe(() => {
|
|
2595
|
+
var _a;
|
|
2596
|
+
return (_a = this.inboundBytes) == null ? void 0 : _a.add(byteCount, { transport: this.transportLabel() });
|
|
2597
|
+
});
|
|
2598
|
+
}
|
|
2599
|
+
outbound(byteCount) {
|
|
2600
|
+
this.safe(() => {
|
|
2601
|
+
var _a;
|
|
2602
|
+
return (_a = this.outboundBytes) == null ? void 0 : _a.add(byteCount, { transport: this.transportLabel() });
|
|
2603
|
+
});
|
|
2604
|
+
}
|
|
2605
|
+
transportLabel() {
|
|
2606
|
+
return this.options.endpoint.startsWith("wss:") ? "wss" : "ws";
|
|
2607
|
+
}
|
|
2608
|
+
safe(record) {
|
|
2609
|
+
try {
|
|
2610
|
+
record();
|
|
2611
|
+
} catch {
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
};
|
|
2615
|
+
|
|
2616
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamConnector.ts
|
|
2617
|
+
var DefaultZlinkStreamConnector = class {
|
|
2618
|
+
constructor(options) {
|
|
2619
|
+
__publicField(this, "receivedMessages");
|
|
2620
|
+
__publicField(this, "lifecycle");
|
|
2621
|
+
__publicField(this, "events", new ZlinkStreamConnectorEvents());
|
|
2622
|
+
__publicField(this, "correlationCounter", 0n);
|
|
2623
|
+
__publicField(this, "pendingRequests", new ZlinkStreamPendingRequests());
|
|
2624
|
+
__publicField(this, "frameSender");
|
|
2625
|
+
__publicField(this, "receiveDispatcher");
|
|
2626
|
+
__publicField(this, "diagnosticsLevelCell");
|
|
2627
|
+
__publicField(this, "options");
|
|
2628
|
+
const flowContext = new BrowserZlinkFlowContext();
|
|
2629
|
+
this.options = normalizeOptions(options, new BrowserStreamTransportFactory());
|
|
2630
|
+
this.diagnosticsLevelCell = new ZlinkStreamDiagnosticsLevelCell(this.options.diagnosticsLevel);
|
|
2631
|
+
Object.defineProperty(this.options, "diagnosticsLevel", {
|
|
2632
|
+
enumerable: true,
|
|
2633
|
+
configurable: true,
|
|
2634
|
+
get: () => this.diagnosticsLevelCell.level
|
|
2635
|
+
});
|
|
2636
|
+
const metrics = new ZlinkStreamRuntimeMetrics(this.options);
|
|
2637
|
+
const protocol = new ZlinkStreamFrameProtocol(this.options);
|
|
2638
|
+
this.frameSender = new ZlinkStreamFrameSender(protocol, flowContext, metrics);
|
|
2639
|
+
this.receivedMessages = new ZlinkStreamReceivedMessages(
|
|
2640
|
+
this.events,
|
|
2641
|
+
this.options.dispatchMode === "immediate" /* Immediate */
|
|
2642
|
+
);
|
|
2643
|
+
this.receiveDispatcher = new ZlinkStreamReceiveDispatcher(
|
|
2644
|
+
protocol,
|
|
2645
|
+
this.pendingRequests,
|
|
2646
|
+
this.receivedMessages,
|
|
2647
|
+
this.frameSender,
|
|
2648
|
+
this.events,
|
|
2649
|
+
flowContext,
|
|
2650
|
+
metrics,
|
|
2651
|
+
(reason) => this.lifecycle.serverClosing(reason)
|
|
2652
|
+
);
|
|
2653
|
+
this.lifecycle = new ZlinkStreamConnectorLifecycle(
|
|
2654
|
+
this.options,
|
|
2655
|
+
this.pendingRequests,
|
|
2656
|
+
this.frameSender,
|
|
2657
|
+
this.receiveDispatcher,
|
|
2658
|
+
this.receivedMessages,
|
|
2659
|
+
this.events,
|
|
2660
|
+
metrics
|
|
2661
|
+
);
|
|
2662
|
+
}
|
|
2663
|
+
get isConnected() {
|
|
2664
|
+
return this.lifecycle.isConnected;
|
|
2665
|
+
}
|
|
2666
|
+
get closeReason() {
|
|
2667
|
+
return this.lifecycle.closeReason;
|
|
2668
|
+
}
|
|
2669
|
+
get state() {
|
|
2670
|
+
return this.lifecycle.state;
|
|
2671
|
+
}
|
|
2672
|
+
get pendingDispatchCount() {
|
|
2673
|
+
return this.pendingRequests.count;
|
|
2674
|
+
}
|
|
2675
|
+
/**
|
|
2676
|
+
* Current diagnostics level (spec 26 §4.1, spec stream-connector 32 §13).
|
|
2677
|
+
* Reflects the level set by the most recent {@link setDiagnosticsLevel}
|
|
2678
|
+
* call, or the construction-time option (default
|
|
2679
|
+
* {@link ZlinkStreamDiagnosticsLevel.Errors}) if it was never changed.
|
|
2680
|
+
*/
|
|
2681
|
+
get diagnosticsLevel() {
|
|
2682
|
+
return this.diagnosticsLevelCell.level;
|
|
2683
|
+
}
|
|
2684
|
+
/**
|
|
2685
|
+
* Changes the diagnostics level in place without recreating the connector
|
|
2686
|
+
* (spec 26 §4.1, spec stream-connector 32 §13). The change is an atomic
|
|
2687
|
+
* state update: it applies to processing points that read the level after
|
|
2688
|
+
* this call returns and is never applied retroactively to frames already
|
|
2689
|
+
* built. Rejects unknown values with {@link ZlinkStreamErrorCode.ConfigurationError}.
|
|
2690
|
+
* Do not call this synchronous bridge from a framework execution context such
|
|
2691
|
+
* as a handler or callback; use setDiagnosticsLevelAsync there.
|
|
2692
|
+
*/
|
|
2693
|
+
setDiagnosticsLevel(level) {
|
|
2694
|
+
void this.setDiagnosticsLevelAsync(level);
|
|
2695
|
+
}
|
|
2696
|
+
setDiagnosticsLevelAsync(level) {
|
|
2697
|
+
this.diagnosticsLevelCell.set(level);
|
|
2698
|
+
return Promise.resolve();
|
|
2699
|
+
}
|
|
2700
|
+
onErrorReceived(handler) {
|
|
2701
|
+
return this.events.onError(handler);
|
|
2702
|
+
}
|
|
2703
|
+
onDisconnected(handler) {
|
|
2704
|
+
return this.events.onDisconnected(handler);
|
|
2705
|
+
}
|
|
2706
|
+
onConnectionStateChanged(handler) {
|
|
2707
|
+
return this.events.onStateChanged(handler);
|
|
2708
|
+
}
|
|
2709
|
+
async connect(signal) {
|
|
2710
|
+
await this.lifecycle.connect(signal);
|
|
2711
|
+
}
|
|
2712
|
+
async close(signal) {
|
|
2713
|
+
await this.lifecycle.close(signal);
|
|
2714
|
+
}
|
|
2715
|
+
async dispatch(signal) {
|
|
2716
|
+
await this.lifecycle.dispatch(signal);
|
|
2717
|
+
}
|
|
2718
|
+
send(payload, messageType) {
|
|
2719
|
+
const encoded = this.encodePayload(payload, messageType);
|
|
2720
|
+
return new ZlinkStreamSendBuilder(this, this.resolveNameOrDefault(encoded), encoded);
|
|
2721
|
+
}
|
|
2722
|
+
request(payload, messageType) {
|
|
2723
|
+
const encoded = this.encodePayload(payload, messageType);
|
|
2724
|
+
return new ZlinkStreamRequestBuilder(this, this.resolveNameOrDefault(encoded), encoded);
|
|
2725
|
+
}
|
|
2726
|
+
on(name, handler, messageType) {
|
|
2727
|
+
const encodedHandler = (message, signal) => handler({
|
|
2728
|
+
name: message.name,
|
|
2729
|
+
metadata: message.metadata,
|
|
2730
|
+
payload: this.decodePayload(message.payload, messageType),
|
|
2731
|
+
flowId: message.flowId,
|
|
2732
|
+
flowOrigin: message.flowOrigin
|
|
2733
|
+
}, signal);
|
|
2734
|
+
return this.receivedMessages.on(name, encodedHandler);
|
|
2735
|
+
}
|
|
2736
|
+
waitFor(name) {
|
|
2737
|
+
validateName(name);
|
|
2738
|
+
return new ZlinkStreamWaitBuilder(this, name);
|
|
2739
|
+
}
|
|
2740
|
+
expectNone(name) {
|
|
2741
|
+
validateName(name);
|
|
2742
|
+
return new ZlinkStreamExpectNoneBuilder(this, name);
|
|
2743
|
+
}
|
|
2744
|
+
waitForSequence(name) {
|
|
2745
|
+
validateName(name);
|
|
2746
|
+
return new ZlinkStreamSequenceBuilder(this, name);
|
|
2747
|
+
}
|
|
2748
|
+
waitForMessage(name, timeoutMs, predicate, signal) {
|
|
2749
|
+
validateName(name);
|
|
2750
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
|
|
2751
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Timeout must be a non-negative finite number.");
|
|
2752
|
+
}
|
|
2753
|
+
throwIfAborted(signal);
|
|
2754
|
+
return new Promise((resolve, reject) => {
|
|
2755
|
+
let done = false;
|
|
2756
|
+
let timer;
|
|
2757
|
+
let disposable;
|
|
2758
|
+
const onAbort = () => finish(connectorError("disconnected" /* Disconnected */, "Operation canceled."));
|
|
2759
|
+
const finish = (error, message) => {
|
|
2760
|
+
if (done) {
|
|
2761
|
+
return;
|
|
2762
|
+
}
|
|
2763
|
+
done = true;
|
|
2764
|
+
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
2765
|
+
if (timer !== void 0) {
|
|
2766
|
+
clearTimeout(timer);
|
|
2767
|
+
}
|
|
2768
|
+
disposable == null ? void 0 : disposable.dispose();
|
|
2769
|
+
if (error !== void 0) {
|
|
2770
|
+
reject(error);
|
|
2771
|
+
} else {
|
|
2772
|
+
resolve(message);
|
|
2773
|
+
}
|
|
2774
|
+
};
|
|
2775
|
+
timer = setTimeout(() => {
|
|
2776
|
+
finish(connectorError("requestTimeout" /* RequestTimeout */, "Wait for stream message timed out."));
|
|
2777
|
+
}, timeoutMs);
|
|
2778
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
2779
|
+
disposable = this.receivedMessages.observe(name, (message) => {
|
|
2780
|
+
if (done) {
|
|
2781
|
+
return false;
|
|
2782
|
+
}
|
|
2783
|
+
try {
|
|
2784
|
+
const decoded = {
|
|
2785
|
+
name: message.name,
|
|
2786
|
+
metadata: message.metadata,
|
|
2787
|
+
payload: this.decodeWaitPayload(message.payload),
|
|
2788
|
+
flowId: message.flowId,
|
|
2789
|
+
flowOrigin: message.flowOrigin
|
|
2790
|
+
};
|
|
2791
|
+
if (!predicate(decoded)) {
|
|
2792
|
+
return false;
|
|
2793
|
+
}
|
|
2794
|
+
finish(void 0, decoded);
|
|
2795
|
+
} catch (cause) {
|
|
2796
|
+
finish(cause);
|
|
2797
|
+
}
|
|
2798
|
+
return true;
|
|
2799
|
+
});
|
|
2800
|
+
});
|
|
2801
|
+
}
|
|
2802
|
+
encodePayload(payload, messageType) {
|
|
2803
|
+
var _a;
|
|
2804
|
+
if (isEncodedPayload(payload)) {
|
|
2805
|
+
return payload;
|
|
2806
|
+
}
|
|
2807
|
+
const codec = (_a = this.options.codec) != null ? _a : zlinkStreamJsonCodec;
|
|
2808
|
+
return codec.encode(payload, messageType);
|
|
2809
|
+
}
|
|
2810
|
+
decodePayload(payload, messageType) {
|
|
2811
|
+
var _a;
|
|
2812
|
+
if (messageType === void 0 && this.options.codec === void 0) {
|
|
2813
|
+
return payload;
|
|
2814
|
+
}
|
|
2815
|
+
return ((_a = this.options.codec) != null ? _a : zlinkStreamJsonCodec).decode(payload, messageType);
|
|
2816
|
+
}
|
|
2817
|
+
decodeWaitPayload(payload) {
|
|
2818
|
+
var _a;
|
|
2819
|
+
if (this.options.codec !== void 0 || payload.codec === 1 /* Json */) {
|
|
2820
|
+
return ((_a = this.options.codec) != null ? _a : zlinkStreamJsonCodec).decode(payload);
|
|
2821
|
+
}
|
|
2822
|
+
return payload;
|
|
2823
|
+
}
|
|
2824
|
+
async sendEncoded(kind, name, payload, metadata, compress, requestSeq, signal, flow, correlationId) {
|
|
2825
|
+
await this.frameSender.send(
|
|
2826
|
+
this.lifecycle.connectionForSend(),
|
|
2827
|
+
kind,
|
|
2828
|
+
name,
|
|
2829
|
+
payload,
|
|
2830
|
+
metadata,
|
|
2831
|
+
compress,
|
|
2832
|
+
requestSeq,
|
|
2833
|
+
signal,
|
|
2834
|
+
correlationId,
|
|
2835
|
+
flow
|
|
2836
|
+
);
|
|
2837
|
+
}
|
|
2838
|
+
/**
|
|
2839
|
+
* Per-connector monotonic correlation id (hex). The client generates it on each request
|
|
2840
|
+
* and the server echoes it back on the reply, so flows can be joined across the wire.
|
|
2841
|
+
*/
|
|
2842
|
+
nextCorrelationId() {
|
|
2843
|
+
this.correlationCounter += 1n;
|
|
2844
|
+
return this.correlationCounter.toString(16);
|
|
2845
|
+
}
|
|
2846
|
+
async requestEncoded(name, payload, metadata, compress, timeoutMs, signal, flow) {
|
|
2847
|
+
const pending = this.pendingRequests.create(name, timeoutMs);
|
|
2848
|
+
try {
|
|
2849
|
+
await this.sendEncoded(
|
|
2850
|
+
2 /* Request */,
|
|
2851
|
+
name,
|
|
2852
|
+
payload,
|
|
2853
|
+
metadata,
|
|
2854
|
+
compress,
|
|
2855
|
+
pending.requestSeq,
|
|
2856
|
+
signal,
|
|
2857
|
+
flow,
|
|
2858
|
+
this.nextCorrelationId()
|
|
2859
|
+
);
|
|
2860
|
+
return await pending.promise;
|
|
2861
|
+
} catch (error) {
|
|
2862
|
+
this.pendingRequests.cancel(pending.requestSeq);
|
|
2863
|
+
throw error;
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
resolveNameOrDefault(payload) {
|
|
2867
|
+
if (payload.messageType === void 0) {
|
|
2868
|
+
return void 0;
|
|
2869
|
+
}
|
|
2870
|
+
return this.options.nameResolver.resolve(payload.messageType);
|
|
2871
|
+
}
|
|
2872
|
+
};
|
|
2873
|
+
__publicField(DefaultZlinkStreamConnector, "heartbeatPingName", ZLINK_STREAM_HEARTBEAT_PING);
|
|
2874
|
+
__publicField(DefaultZlinkStreamConnector, "heartbeatPongName", ZLINK_STREAM_HEARTBEAT_PONG);
|
|
2875
|
+
function isEncodedPayload(value) {
|
|
2876
|
+
if (value === null || typeof value !== "object") {
|
|
2877
|
+
return false;
|
|
2878
|
+
}
|
|
2879
|
+
const candidate = value;
|
|
2880
|
+
return typeof candidate.codec === "number" && candidate.payload instanceof Uint8Array;
|
|
2881
|
+
}
|
|
2882
|
+
|
|
2883
|
+
// packages/stream-connector/src/Runtime/ZlinkStreamAssertions.ts
|
|
2884
|
+
var zlinkStreamAssert = {
|
|
2885
|
+
ensure(condition, message) {
|
|
2886
|
+
if (!condition) {
|
|
2887
|
+
throw connectorError("validationFailed" /* ValidationFailed */, message);
|
|
2888
|
+
}
|
|
2889
|
+
},
|
|
2890
|
+
async expectFailure(action, errorKind) {
|
|
2891
|
+
let failure;
|
|
2892
|
+
try {
|
|
2893
|
+
await action();
|
|
2894
|
+
} catch (error) {
|
|
2895
|
+
failure = error;
|
|
2896
|
+
}
|
|
2897
|
+
if (failure === void 0) {
|
|
2898
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Expected action to fail.");
|
|
2899
|
+
}
|
|
2900
|
+
const streamError = unwrapStreamError(failure);
|
|
2901
|
+
if (errorKind !== void 0 && streamError.code !== errorKind) {
|
|
2902
|
+
throw connectorError(
|
|
2903
|
+
"validationFailed" /* ValidationFailed */,
|
|
2904
|
+
`Expected failure kind '${errorKind}', got '${streamError.code}'.`,
|
|
2905
|
+
failure
|
|
2906
|
+
);
|
|
2907
|
+
}
|
|
2908
|
+
return streamError;
|
|
2909
|
+
},
|
|
2910
|
+
async expectTimeout(action) {
|
|
2911
|
+
let failure;
|
|
2912
|
+
try {
|
|
2913
|
+
await action();
|
|
2914
|
+
} catch (error) {
|
|
2915
|
+
failure = error;
|
|
2916
|
+
}
|
|
2917
|
+
if (failure === void 0) {
|
|
2918
|
+
throw connectorError("validationFailed" /* ValidationFailed */, "Expected action to time out.");
|
|
2919
|
+
}
|
|
2920
|
+
const code = unwrapStreamError(failure).code;
|
|
2921
|
+
if (code !== "requestTimeout" /* RequestTimeout */ && code !== "connectTimeout" /* ConnectTimeout */) {
|
|
2922
|
+
throw failure;
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
};
|
|
2926
|
+
|
|
2927
|
+
// packages/stream-connector/src/index.ts
|
|
2928
|
+
var zlinkStreamConnectorFactory = {
|
|
2929
|
+
create(options) {
|
|
2930
|
+
return new DefaultZlinkStreamConnector(options);
|
|
2931
|
+
}
|
|
2932
|
+
};
|
|
2933
|
+
return __toCommonJS(index_exports);
|
|
2934
|
+
})();
|