@sachitv/avro-typescript 0.4.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/esm/_dnt.polyfills.d.ts +11 -0
- package/esm/_dnt.polyfills.js +15 -0
- package/esm/avro_reader.d.ts +156 -0
- package/esm/avro_reader.js +201 -0
- package/esm/avro_writer.d.ts +75 -0
- package/esm/avro_writer.js +105 -0
- package/esm/internal/collections/array_utils.d.ts +4 -0
- package/esm/internal/collections/array_utils.js +18 -0
- package/esm/internal/collections/circular_buffer.d.ts +48 -0
- package/esm/internal/collections/circular_buffer.js +129 -0
- package/esm/internal/crypto/md5.d.ts +12 -0
- package/esm/internal/crypto/md5.js +158 -0
- package/esm/internal/varint.d.ts +6 -0
- package/esm/internal/varint.js +30 -0
- package/esm/mod.d.ts +77 -0
- package/esm/mod.js +73 -0
- package/esm/package.json +3 -0
- package/esm/rpc/definitions/message_definition.d.ts +34 -0
- package/esm/rpc/definitions/message_definition.js +105 -0
- package/esm/rpc/definitions/protocol_definitions.d.ts +197 -0
- package/esm/rpc/definitions/protocol_definitions.js +1 -0
- package/esm/rpc/message_endpoint/base.d.ts +43 -0
- package/esm/rpc/message_endpoint/base.js +81 -0
- package/esm/rpc/message_endpoint/emitter.d.ts +96 -0
- package/esm/rpc/message_endpoint/emitter.js +245 -0
- package/esm/rpc/message_endpoint/helpers.d.ts +37 -0
- package/esm/rpc/message_endpoint/helpers.js +68 -0
- package/esm/rpc/message_endpoint/listener.d.ts +37 -0
- package/esm/rpc/message_endpoint/listener.js +212 -0
- package/esm/rpc/protocol/frame_assembler.d.ts +11 -0
- package/esm/rpc/protocol/frame_assembler.js +77 -0
- package/esm/rpc/protocol/protocol_helpers.d.ts +59 -0
- package/esm/rpc/protocol/protocol_helpers.js +123 -0
- package/esm/rpc/protocol/transports/fetch.d.ts +9 -0
- package/esm/rpc/protocol/transports/fetch.js +30 -0
- package/esm/rpc/protocol/transports/in_memory.d.ts +27 -0
- package/esm/rpc/protocol/transports/in_memory.js +125 -0
- package/esm/rpc/protocol/transports/transport_helpers.d.ts +118 -0
- package/esm/rpc/protocol/transports/transport_helpers.js +112 -0
- package/esm/rpc/protocol/transports/websocket.d.ts +9 -0
- package/esm/rpc/protocol/transports/websocket.js +102 -0
- package/esm/rpc/protocol/wire_format/framing.d.ts +44 -0
- package/esm/rpc/protocol/wire_format/framing.js +74 -0
- package/esm/rpc/protocol/wire_format/handshake.d.ts +110 -0
- package/esm/rpc/protocol/wire_format/handshake.js +239 -0
- package/esm/rpc/protocol/wire_format/messages.d.ts +192 -0
- package/esm/rpc/protocol/wire_format/messages.js +175 -0
- package/esm/rpc/protocol/wire_format/metadata.d.ts +44 -0
- package/esm/rpc/protocol/wire_format/metadata.js +74 -0
- package/esm/rpc/protocol_core.d.ts +121 -0
- package/esm/rpc/protocol_core.js +285 -0
- package/esm/schemas/base_type.d.ts +41 -0
- package/esm/schemas/base_type.js +49 -0
- package/esm/schemas/complex/array_type.d.ts +100 -0
- package/esm/schemas/complex/array_type.js +299 -0
- package/esm/schemas/complex/enum_type.d.ts +81 -0
- package/esm/schemas/complex/enum_type.js +217 -0
- package/esm/schemas/complex/fixed_type.d.ts +99 -0
- package/esm/schemas/complex/fixed_type.js +208 -0
- package/esm/schemas/complex/map_type.d.ts +97 -0
- package/esm/schemas/complex/map_type.js +290 -0
- package/esm/schemas/complex/named_type.d.ts +30 -0
- package/esm/schemas/complex/named_type.js +57 -0
- package/esm/schemas/complex/record_type.d.ts +165 -0
- package/esm/schemas/complex/record_type.js +547 -0
- package/esm/schemas/complex/resolve_names.d.ts +32 -0
- package/esm/schemas/complex/resolve_names.js +85 -0
- package/esm/schemas/complex/union_type.d.ts +116 -0
- package/esm/schemas/complex/union_type.js +392 -0
- package/esm/schemas/error.d.ts +31 -0
- package/esm/schemas/error.js +67 -0
- package/esm/schemas/json.d.ts +6 -0
- package/esm/schemas/json.js +35 -0
- package/esm/schemas/logical/decimal_logical_type.d.ts +49 -0
- package/esm/schemas/logical/decimal_logical_type.js +145 -0
- package/esm/schemas/logical/duration_logical_type.d.ts +66 -0
- package/esm/schemas/logical/duration_logical_type.js +112 -0
- package/esm/schemas/logical/logical_type.d.ts +138 -0
- package/esm/schemas/logical/logical_type.js +240 -0
- package/esm/schemas/logical/temporal_logical_types.d.ts +215 -0
- package/esm/schemas/logical/temporal_logical_types.js +364 -0
- package/esm/schemas/logical/uuid_logical_type.d.ts +63 -0
- package/esm/schemas/logical/uuid_logical_type.js +146 -0
- package/esm/schemas/primitive/boolean_type.d.ts +49 -0
- package/esm/schemas/primitive/boolean_type.js +75 -0
- package/esm/schemas/primitive/bytes_type.d.ts +49 -0
- package/esm/schemas/primitive/bytes_type.js +136 -0
- package/esm/schemas/primitive/double_type.d.ts +38 -0
- package/esm/schemas/primitive/double_type.js +98 -0
- package/esm/schemas/primitive/fixed_size_base_type.d.ts +28 -0
- package/esm/schemas/primitive/fixed_size_base_type.js +33 -0
- package/esm/schemas/primitive/float_type.d.ts +38 -0
- package/esm/schemas/primitive/float_type.js +88 -0
- package/esm/schemas/primitive/int_type.d.ts +31 -0
- package/esm/schemas/primitive/int_type.js +63 -0
- package/esm/schemas/primitive/long_type.d.ts +36 -0
- package/esm/schemas/primitive/long_type.js +95 -0
- package/esm/schemas/primitive/null_type.d.ts +45 -0
- package/esm/schemas/primitive/null_type.js +71 -0
- package/esm/schemas/primitive/primitive_type.d.ts +17 -0
- package/esm/schemas/primitive/primitive_type.js +27 -0
- package/esm/schemas/primitive/string_type.d.ts +34 -0
- package/esm/schemas/primitive/string_type.js +81 -0
- package/esm/schemas/resolver.d.ts +25 -0
- package/esm/schemas/resolver.js +25 -0
- package/esm/schemas/type.d.ts +101 -0
- package/esm/schemas/type.js +6 -0
- package/esm/serialization/avro_constants.d.ts +13 -0
- package/esm/serialization/avro_constants.js +29 -0
- package/esm/serialization/avro_file_parser.d.ts +68 -0
- package/esm/serialization/avro_file_parser.js +191 -0
- package/esm/serialization/avro_file_writer.d.ts +63 -0
- package/esm/serialization/avro_file_writer.js +235 -0
- package/esm/serialization/buffers/blob_readable_buffer.d.ts +53 -0
- package/esm/serialization/buffers/blob_readable_buffer.js +80 -0
- package/esm/serialization/buffers/buffer.d.ts +37 -0
- package/esm/serialization/buffers/buffer.js +1 -0
- package/esm/serialization/buffers/in_memory_buffer.d.ts +121 -0
- package/esm/serialization/buffers/in_memory_buffer.js +206 -0
- package/esm/serialization/clamp.d.ts +10 -0
- package/esm/serialization/clamp.js +19 -0
- package/esm/serialization/compare_bytes.d.ts +9 -0
- package/esm/serialization/compare_bytes.js +45 -0
- package/esm/serialization/conversion.d.ts +8 -0
- package/esm/serialization/conversion.js +15 -0
- package/esm/serialization/decoders/decoder.d.ts +16 -0
- package/esm/serialization/decoders/decoder.js +1 -0
- package/esm/serialization/decoders/deflate_decoder.d.ts +15 -0
- package/esm/serialization/decoders/deflate_decoder.js +26 -0
- package/esm/serialization/decoders/null_decoder.d.ts +12 -0
- package/esm/serialization/decoders/null_decoder.js +13 -0
- package/esm/serialization/encoders/deflate_encoder.d.ts +15 -0
- package/esm/serialization/encoders/deflate_encoder.js +26 -0
- package/esm/serialization/encoders/encoder.d.ts +16 -0
- package/esm/serialization/encoders/encoder.js +1 -0
- package/esm/serialization/encoders/null_encoder.d.ts +12 -0
- package/esm/serialization/encoders/null_encoder.js +13 -0
- package/esm/serialization/manipulate_bytes.d.ts +6 -0
- package/esm/serialization/manipulate_bytes.js +13 -0
- package/esm/serialization/read_uint_le.d.ts +4 -0
- package/esm/serialization/read_uint_le.js +14 -0
- package/esm/serialization/streams/fixed_size_stream_readable_buffer_adapter.d.ts +52 -0
- package/esm/serialization/streams/fixed_size_stream_readable_buffer_adapter.js +129 -0
- package/esm/serialization/streams/forward_only_stream_readable_buffer_adapter.d.ts +36 -0
- package/esm/serialization/streams/forward_only_stream_readable_buffer_adapter.js +114 -0
- package/esm/serialization/streams/stream_readable_buffer.d.ts +41 -0
- package/esm/serialization/streams/stream_readable_buffer.js +64 -0
- package/esm/serialization/streams/stream_readable_buffer_adapter.d.ts +38 -0
- package/esm/serialization/streams/stream_readable_buffer_adapter.js +105 -0
- package/esm/serialization/streams/stream_writable_buffer.d.ts +42 -0
- package/esm/serialization/streams/stream_writable_buffer.js +64 -0
- package/esm/serialization/streams/stream_writable_buffer_adapter.d.ts +36 -0
- package/esm/serialization/streams/stream_writable_buffer_adapter.js +65 -0
- package/esm/serialization/streams/streams.d.ts +29 -0
- package/esm/serialization/streams/streams.js +1 -0
- package/esm/serialization/tap.d.ts +427 -0
- package/esm/serialization/tap.js +605 -0
- package/esm/serialization/text_encoding.d.ts +12 -0
- package/esm/serialization/text_encoding.js +14 -0
- package/esm/type/create_type.d.ts +54 -0
- package/esm/type/create_type.js +401 -0
- package/package.json +33 -0
- package/sachitv-avro-typescript-0.4.0.tgz +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { BinaryReadable } from "../protocol/transports/transport_helpers.js";
|
|
2
|
+
import type { CallRequestEnvelope, CallResponseEnvelope } from "../protocol/wire_format/messages.js";
|
|
3
|
+
import type { Message } from "../definitions/message_definition.js";
|
|
4
|
+
import type { ResolverEntry } from "../definitions/protocol_definitions.js";
|
|
5
|
+
/**
|
|
6
|
+
* Reads a single framed message from a binary readable stream in the context of message endpoints.
|
|
7
|
+
* Uses a FrameAssembler to accumulate chunks until a complete message is formed.
|
|
8
|
+
* @param readable The binary readable stream to read from.
|
|
9
|
+
* @returns A promise that resolves to the Uint8Array of the framed message.
|
|
10
|
+
* @throws Error if no framed message is received.
|
|
11
|
+
*/
|
|
12
|
+
export declare function readSingleMessage(readable: BinaryReadable): Promise<Uint8Array>;
|
|
13
|
+
/**
|
|
14
|
+
* Drains a binary readable stream by consuming all remaining bytes in the context of message endpoints.
|
|
15
|
+
* Useful for clearing the stream after processing.
|
|
16
|
+
* @param readable The binary readable stream to drain.
|
|
17
|
+
* @returns A promise that resolves when the stream is fully drained.
|
|
18
|
+
*/
|
|
19
|
+
export declare function drainReadable(readable: BinaryReadable): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Reads the payload from a call response envelope in the context of message endpoints.
|
|
22
|
+
* Handles error responses and uses a resolver for schema resolution if provided.
|
|
23
|
+
* @param envelope The call response envelope containing the body tap.
|
|
24
|
+
* @param message The message definition for type information.
|
|
25
|
+
* @param resolver Optional resolver entry for custom schema resolution.
|
|
26
|
+
* @returns A promise that resolves to the deserialized response payload.
|
|
27
|
+
*/
|
|
28
|
+
export declare function readResponsePayload(envelope: CallResponseEnvelope, message: Message, resolver?: ResolverEntry): Promise<unknown>;
|
|
29
|
+
/**
|
|
30
|
+
* Reads the payload from a call request envelope in the context of message endpoints.
|
|
31
|
+
* Uses a resolver for schema resolution if provided, otherwise falls back to message types.
|
|
32
|
+
* @param envelope The call request envelope containing the body tap.
|
|
33
|
+
* @param message The message definition for type information.
|
|
34
|
+
* @param resolver Optional resolver entry for custom schema resolution.
|
|
35
|
+
* @returns A promise that resolves to the deserialized request payload.
|
|
36
|
+
*/
|
|
37
|
+
export declare function readRequestPayload(envelope: CallRequestEnvelope, message: Message, resolver?: ResolverEntry): Promise<unknown>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { FrameAssembler } from "../protocol/frame_assembler.js";
|
|
2
|
+
/**
|
|
3
|
+
* Reads a single framed message from a binary readable stream in the context of message endpoints.
|
|
4
|
+
* Uses a FrameAssembler to accumulate chunks until a complete message is formed.
|
|
5
|
+
* @param readable The binary readable stream to read from.
|
|
6
|
+
* @returns A promise that resolves to the Uint8Array of the framed message.
|
|
7
|
+
* @throws Error if no framed message is received.
|
|
8
|
+
*/
|
|
9
|
+
export async function readSingleMessage(readable) {
|
|
10
|
+
const assembler = new FrameAssembler();
|
|
11
|
+
while (true) {
|
|
12
|
+
const chunk = await readable.read();
|
|
13
|
+
if (chunk === null) {
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
const messages = assembler.push(chunk);
|
|
17
|
+
if (messages.length) {
|
|
18
|
+
return messages[0];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
throw new Error("no framed message received");
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Drains a binary readable stream by consuming all remaining bytes in the context of message endpoints.
|
|
25
|
+
* Useful for clearing the stream after processing.
|
|
26
|
+
* @param readable The binary readable stream to drain.
|
|
27
|
+
* @returns A promise that resolves when the stream is fully drained.
|
|
28
|
+
*/
|
|
29
|
+
export async function drainReadable(readable) {
|
|
30
|
+
while ((await readable.read()) !== null) {
|
|
31
|
+
// consume remaining bytes
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Reads the payload from a call response envelope in the context of message endpoints.
|
|
36
|
+
* Handles error responses and uses a resolver for schema resolution if provided.
|
|
37
|
+
* @param envelope The call response envelope containing the body tap.
|
|
38
|
+
* @param message The message definition for type information.
|
|
39
|
+
* @param resolver Optional resolver entry for custom schema resolution.
|
|
40
|
+
* @returns A promise that resolves to the deserialized response payload.
|
|
41
|
+
*/
|
|
42
|
+
export async function readResponsePayload(envelope, message, resolver) {
|
|
43
|
+
const tap = envelope.bodyTap;
|
|
44
|
+
if (envelope.isError) {
|
|
45
|
+
if (resolver?.error) {
|
|
46
|
+
return await resolver.error.read(tap);
|
|
47
|
+
}
|
|
48
|
+
return await message.errorType.read(tap);
|
|
49
|
+
}
|
|
50
|
+
if (resolver?.response) {
|
|
51
|
+
return await resolver.response.read(tap);
|
|
52
|
+
}
|
|
53
|
+
return await message.responseType.read(tap);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Reads the payload from a call request envelope in the context of message endpoints.
|
|
57
|
+
* Uses a resolver for schema resolution if provided, otherwise falls back to message types.
|
|
58
|
+
* @param envelope The call request envelope containing the body tap.
|
|
59
|
+
* @param message The message definition for type information.
|
|
60
|
+
* @param resolver Optional resolver entry for custom schema resolution.
|
|
61
|
+
* @returns A promise that resolves to the deserialized request payload.
|
|
62
|
+
*/
|
|
63
|
+
export async function readRequestPayload(envelope, message, resolver) {
|
|
64
|
+
if (resolver?.request) {
|
|
65
|
+
return await resolver.request.read(envelope.bodyTap);
|
|
66
|
+
}
|
|
67
|
+
return await message.requestType.read(envelope.bodyTap);
|
|
68
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { BinaryDuplexLike } from "../protocol/transports/transport_helpers.js";
|
|
2
|
+
import { MessageEndpoint } from "./base.js";
|
|
3
|
+
import type { MessageTransportOptions, ProtocolFactory, ProtocolLike } from "../definitions/protocol_definitions.js";
|
|
4
|
+
/**
|
|
5
|
+
* Abstract base class for message listeners.
|
|
6
|
+
* Listens for incoming RPC requests and dispatches them to handlers.
|
|
7
|
+
*/
|
|
8
|
+
export declare abstract class MessageListener extends MessageEndpoint {
|
|
9
|
+
/**
|
|
10
|
+
* Destroys the listener, stopping it from accepting new requests.
|
|
11
|
+
* @param noWait If true, does not wait for pending requests to complete (if applicable).
|
|
12
|
+
*/
|
|
13
|
+
abstract destroy(noWait?: boolean): void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Stateless implementation of MessageListener.
|
|
17
|
+
* Handles one request per connection, common in HTTP-based transports.
|
|
18
|
+
*/
|
|
19
|
+
export declare class StatelessListener extends MessageListener {
|
|
20
|
+
#private;
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new StatelessListener.
|
|
23
|
+
* @param protocol The protocol definition.
|
|
24
|
+
* @param transport The binary transport to read from/write to.
|
|
25
|
+
* @param opts Configuration options.
|
|
26
|
+
* @param protocolFactory Factory for creating protocol instances from schema.
|
|
27
|
+
*/
|
|
28
|
+
constructor(protocol: ProtocolLike, transport: BinaryDuplexLike, opts: MessageTransportOptions, protocolFactory: ProtocolFactory);
|
|
29
|
+
/**
|
|
30
|
+
* Destroys the listener.
|
|
31
|
+
*/
|
|
32
|
+
destroy(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Waits for the listener's main loop to exit.
|
|
35
|
+
*/
|
|
36
|
+
waitForClose(): Promise<void>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _StatelessListener_instances, _StatelessListener_transport, _StatelessListener_destroyed, _StatelessListener_protocolFactory, _StatelessListener_requestDecoder, _StatelessListener_runPromise, _StatelessListener_exposeProtocol, _StatelessListener_maxRequestSize, _StatelessListener_requestTimeout, _StatelessListener_run, _StatelessListener_handleRequest, _StatelessListener_validateHandshake;
|
|
13
|
+
import { encodeCallResponse } from "../protocol/wire_format/messages.js";
|
|
14
|
+
import { frameMessage } from "../protocol/wire_format/framing.js";
|
|
15
|
+
import { bytesEqual, bytesToHex, errorToPayload, textEncoder, toArrayBuffer, } from "../protocol/protocol_helpers.js";
|
|
16
|
+
import { createType } from "../../type/create_type.js";
|
|
17
|
+
import { toBinaryDuplex } from "../protocol/transports/transport_helpers.js";
|
|
18
|
+
import { MessageEndpoint } from "./base.js";
|
|
19
|
+
import { decodeCallRequestEnvelope } from "../protocol/wire_format/messages.js";
|
|
20
|
+
import { readRequestPayload } from "./helpers.js";
|
|
21
|
+
import { FrameAssembler } from "../protocol/frame_assembler.js";
|
|
22
|
+
/**
|
|
23
|
+
* Abstract base class for message listeners.
|
|
24
|
+
* Listens for incoming RPC requests and dispatches them to handlers.
|
|
25
|
+
*/
|
|
26
|
+
export class MessageListener extends MessageEndpoint {
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Stateless implementation of MessageListener.
|
|
30
|
+
* Handles one request per connection, common in HTTP-based transports.
|
|
31
|
+
*/
|
|
32
|
+
export class StatelessListener extends MessageListener {
|
|
33
|
+
/**
|
|
34
|
+
* Creates a new StatelessListener.
|
|
35
|
+
* @param protocol The protocol definition.
|
|
36
|
+
* @param transport The binary transport to read from/write to.
|
|
37
|
+
* @param opts Configuration options.
|
|
38
|
+
* @param protocolFactory Factory for creating protocol instances from schema.
|
|
39
|
+
*/
|
|
40
|
+
constructor(protocol, transport, opts, protocolFactory) {
|
|
41
|
+
super(protocol, opts);
|
|
42
|
+
_StatelessListener_instances.add(this);
|
|
43
|
+
_StatelessListener_transport.set(this, void 0);
|
|
44
|
+
_StatelessListener_destroyed.set(this, false);
|
|
45
|
+
_StatelessListener_protocolFactory.set(this, void 0);
|
|
46
|
+
_StatelessListener_requestDecoder.set(this, void 0);
|
|
47
|
+
_StatelessListener_runPromise.set(this, void 0);
|
|
48
|
+
_StatelessListener_exposeProtocol.set(this, void 0);
|
|
49
|
+
_StatelessListener_maxRequestSize.set(this, void 0);
|
|
50
|
+
_StatelessListener_requestTimeout.set(this, void 0);
|
|
51
|
+
__classPrivateFieldSet(this, _StatelessListener_transport, transport, "f");
|
|
52
|
+
__classPrivateFieldSet(this, _StatelessListener_protocolFactory, protocolFactory, "f");
|
|
53
|
+
__classPrivateFieldSet(this, _StatelessListener_requestDecoder, opts.requestDecoder ?? decodeCallRequestEnvelope, "f");
|
|
54
|
+
__classPrivateFieldSet(this, _StatelessListener_exposeProtocol, opts.exposeProtocol ?? false, "f");
|
|
55
|
+
// Security: limit request size to prevent DoS (default 10MB)
|
|
56
|
+
__classPrivateFieldSet(this, _StatelessListener_maxRequestSize, opts.maxRequestSize ?? 10 * 1024 * 1024, "f");
|
|
57
|
+
// Security: timeout to prevent hanging requests (default 30 seconds)
|
|
58
|
+
__classPrivateFieldSet(this, _StatelessListener_requestTimeout, opts.requestTimeout ?? 30000, "f");
|
|
59
|
+
__classPrivateFieldSet(this, _StatelessListener_runPromise, __classPrivateFieldGet(this, _StatelessListener_instances, "m", _StatelessListener_run).call(this), "f");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Destroys the listener.
|
|
63
|
+
*/
|
|
64
|
+
destroy() {
|
|
65
|
+
if (!__classPrivateFieldGet(this, _StatelessListener_destroyed, "f")) {
|
|
66
|
+
__classPrivateFieldSet(this, _StatelessListener_destroyed, true, "f");
|
|
67
|
+
this.dispatchEot(0);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Waits for the listener's main loop to exit.
|
|
72
|
+
*/
|
|
73
|
+
waitForClose() {
|
|
74
|
+
return __classPrivateFieldGet(this, _StatelessListener_runPromise, "f");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
_StatelessListener_transport = new WeakMap(), _StatelessListener_destroyed = new WeakMap(), _StatelessListener_protocolFactory = new WeakMap(), _StatelessListener_requestDecoder = new WeakMap(), _StatelessListener_runPromise = new WeakMap(), _StatelessListener_exposeProtocol = new WeakMap(), _StatelessListener_maxRequestSize = new WeakMap(), _StatelessListener_requestTimeout = new WeakMap(), _StatelessListener_instances = new WeakSet(), _StatelessListener_run = async function _StatelessListener_run() {
|
|
78
|
+
const duplex = toBinaryDuplex(__classPrivateFieldGet(this, _StatelessListener_transport, "f"));
|
|
79
|
+
const assembler = new FrameAssembler();
|
|
80
|
+
let totalSize = 0;
|
|
81
|
+
try {
|
|
82
|
+
// Set up timeout for the entire request processing
|
|
83
|
+
const timeoutController = new AbortController();
|
|
84
|
+
const timeoutId = setTimeout(() => {
|
|
85
|
+
timeoutController.abort();
|
|
86
|
+
}, __classPrivateFieldGet(this, _StatelessListener_requestTimeout, "f"));
|
|
87
|
+
try {
|
|
88
|
+
while (!timeoutController.signal.aborted) {
|
|
89
|
+
const chunk = await duplex.readable.read();
|
|
90
|
+
if (chunk === null) {
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
// Security: check size limit to prevent DoS
|
|
94
|
+
totalSize += chunk.length;
|
|
95
|
+
if (totalSize > __classPrivateFieldGet(this, _StatelessListener_maxRequestSize, "f")) {
|
|
96
|
+
throw new Error(`request too large: ${totalSize} bytes (max: ${__classPrivateFieldGet(this, _StatelessListener_maxRequestSize, "f")})`);
|
|
97
|
+
}
|
|
98
|
+
const messages = assembler.push(chunk);
|
|
99
|
+
if (messages.length > 0) {
|
|
100
|
+
// Process the first complete message
|
|
101
|
+
await __classPrivateFieldGet(this, _StatelessListener_instances, "m", _StatelessListener_handleRequest).call(this, messages[0], duplex);
|
|
102
|
+
return; // Only process one request per connection in stateless mode
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (timeoutController.signal.aborted) {
|
|
106
|
+
throw new Error("request timeout");
|
|
107
|
+
}
|
|
108
|
+
throw new Error("no request payload");
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
clearTimeout(timeoutId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
this.dispatchError(err);
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
await duplex.writable.close();
|
|
119
|
+
this.destroy();
|
|
120
|
+
}
|
|
121
|
+
}, _StatelessListener_handleRequest = async function _StatelessListener_handleRequest(payload, duplex) {
|
|
122
|
+
const envelope = await __classPrivateFieldGet(this, _StatelessListener_requestDecoder, "f").call(this, toArrayBuffer(payload), { expectHandshake: true });
|
|
123
|
+
if (!envelope.handshake) {
|
|
124
|
+
throw new Error("missing handshake request");
|
|
125
|
+
}
|
|
126
|
+
const { response: handshakeResponse, requestResolverKey, } = await __classPrivateFieldGet(this, _StatelessListener_instances, "m", _StatelessListener_validateHandshake).call(this, envelope.handshake);
|
|
127
|
+
let message;
|
|
128
|
+
let result;
|
|
129
|
+
let isError = false;
|
|
130
|
+
let errorPayload;
|
|
131
|
+
try {
|
|
132
|
+
message = this.protocol.getMessages().get(envelope.messageName);
|
|
133
|
+
if (!message) {
|
|
134
|
+
throw new Error(`unsupported message: ${envelope.messageName}`);
|
|
135
|
+
}
|
|
136
|
+
const resolver = this.protocol.getListenerResolvers(requestResolverKey, message.name);
|
|
137
|
+
const requestValue = await readRequestPayload(envelope, message, resolver);
|
|
138
|
+
const handler = this.protocol.getHandler(message.name);
|
|
139
|
+
if (!handler) {
|
|
140
|
+
throw new Error(`unsupported message: ${message.name}`);
|
|
141
|
+
}
|
|
142
|
+
result = await handler(requestValue, this, {
|
|
143
|
+
metadata: envelope.metadata,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
isError = true;
|
|
148
|
+
errorPayload = errorToPayload(err);
|
|
149
|
+
}
|
|
150
|
+
const responsePayload = await encodeCallResponse({
|
|
151
|
+
handshake: handshakeResponse,
|
|
152
|
+
metadata: envelope.metadata,
|
|
153
|
+
isError,
|
|
154
|
+
payload: isError ? errorPayload : result,
|
|
155
|
+
responseType: message ? message.responseType : createType("null"),
|
|
156
|
+
errorType: message ? message.errorType : createType(["string"]),
|
|
157
|
+
});
|
|
158
|
+
const framed = frameMessage(responsePayload, { frameSize: this.frameSize });
|
|
159
|
+
await duplex.writable.write(framed);
|
|
160
|
+
}, _StatelessListener_validateHandshake =
|
|
161
|
+
// deno-lint-ignore require-await
|
|
162
|
+
async function _StatelessListener_validateHandshake(handshake) {
|
|
163
|
+
let validationError = null;
|
|
164
|
+
let resolverError = null;
|
|
165
|
+
const clientHashKey = bytesToHex(handshake.clientHash);
|
|
166
|
+
const needsResolver = clientHashKey !== this.protocol.hashKey;
|
|
167
|
+
if (needsResolver && !this.protocol.hasListenerResolvers(clientHashKey)) {
|
|
168
|
+
if (handshake.clientProtocol) {
|
|
169
|
+
// Security: validate JSON before parsing
|
|
170
|
+
if (typeof handshake.clientProtocol !== "string" ||
|
|
171
|
+
handshake.clientProtocol.length > 1024 * 1024) { // 1MB limit
|
|
172
|
+
validationError = new Error("invalid client protocol: too large or not a string");
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
try {
|
|
176
|
+
// Basic JSON validation
|
|
177
|
+
const parsedProtocol = JSON.parse(handshake.clientProtocol);
|
|
178
|
+
const emitterProtocol = __classPrivateFieldGet(this, _StatelessListener_protocolFactory, "f").call(this, parsedProtocol);
|
|
179
|
+
this.protocol.ensureListenerResolvers(clientHashKey, emitterProtocol);
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
validationError = err instanceof Error
|
|
183
|
+
? err
|
|
184
|
+
: new Error("invalid client protocol JSON");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
resolverError = new Error("unknown client protocol hash");
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const handshakeIssue = validationError ?? resolverError;
|
|
193
|
+
const serverMatch = bytesEqual(handshake.serverHash, this.protocol.getHashBytes());
|
|
194
|
+
// Protocol exposure logic:
|
|
195
|
+
// - Expose when server hash doesn't match AND client hash is known (normal schema evolution)
|
|
196
|
+
// - Expose when exposeProtocol is true (explicit discovery mode)
|
|
197
|
+
// - Never expose when there are validation errors (malformed input)
|
|
198
|
+
const clientHashKnown = !needsResolver;
|
|
199
|
+
const shouldExposeProtocol = ((!serverMatch && clientHashKnown) ||
|
|
200
|
+
__classPrivateFieldGet(this, _StatelessListener_exposeProtocol, "f")) && !validationError;
|
|
201
|
+
const response = {
|
|
202
|
+
match: handshakeIssue ? "NONE" : serverMatch ? "BOTH" : "CLIENT",
|
|
203
|
+
serverProtocol: shouldExposeProtocol ? this.protocol.toString() : null,
|
|
204
|
+
serverHash: serverMatch ? null : this.protocol.getHashBytes(),
|
|
205
|
+
meta: validationError
|
|
206
|
+
? new Map([["error", textEncoder.encode(String(validationError))]])
|
|
207
|
+
: resolverError
|
|
208
|
+
? new Map([["error", textEncoder.encode(String(resolverError))]])
|
|
209
|
+
: null,
|
|
210
|
+
};
|
|
211
|
+
return { response, requestResolverKey: clientHashKey };
|
|
212
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incrementally collects framed Avro messages from arbitrary binary chunks.
|
|
3
|
+
* Counterpart to the `frameMessage` function in `framing.ts`, which frames messages for sending.
|
|
4
|
+
*/
|
|
5
|
+
export declare class FrameAssembler {
|
|
6
|
+
#private;
|
|
7
|
+
/** Pushes a chunk and returns complete frames */
|
|
8
|
+
push(chunk: Uint8Array): Uint8Array[];
|
|
9
|
+
/** Resets the assembler */
|
|
10
|
+
reset(): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
7
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
|
+
};
|
|
12
|
+
var _FrameAssembler_instances, _FrameAssembler_buffer, _FrameAssembler_frames, _FrameAssembler_flushFrames, _FrameAssembler_readUint32BE;
|
|
13
|
+
import { concatUint8Arrays } from "../../internal/collections/array_utils.js";
|
|
14
|
+
/**
|
|
15
|
+
* Incrementally collects framed Avro messages from arbitrary binary chunks.
|
|
16
|
+
* Counterpart to the `frameMessage` function in `framing.ts`, which frames messages for sending.
|
|
17
|
+
*/
|
|
18
|
+
export class FrameAssembler {
|
|
19
|
+
constructor() {
|
|
20
|
+
_FrameAssembler_instances.add(this);
|
|
21
|
+
_FrameAssembler_buffer.set(this, new Uint8Array(0));
|
|
22
|
+
_FrameAssembler_frames.set(this, []);
|
|
23
|
+
}
|
|
24
|
+
/** Pushes a chunk and returns complete frames */
|
|
25
|
+
push(chunk) {
|
|
26
|
+
if (!chunk.length) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
if (!__classPrivateFieldGet(this, _FrameAssembler_buffer, "f").length) {
|
|
30
|
+
__classPrivateFieldSet(this, _FrameAssembler_buffer, chunk.slice(), "f");
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const combined = new Uint8Array(__classPrivateFieldGet(this, _FrameAssembler_buffer, "f").length + chunk.length);
|
|
34
|
+
combined.set(__classPrivateFieldGet(this, _FrameAssembler_buffer, "f"), 0);
|
|
35
|
+
combined.set(chunk, __classPrivateFieldGet(this, _FrameAssembler_buffer, "f").length);
|
|
36
|
+
__classPrivateFieldSet(this, _FrameAssembler_buffer, combined, "f");
|
|
37
|
+
}
|
|
38
|
+
const output = [];
|
|
39
|
+
let offset = 0;
|
|
40
|
+
while (__classPrivateFieldGet(this, _FrameAssembler_buffer, "f").length - offset >= 4) {
|
|
41
|
+
const frameLength = __classPrivateFieldGet(this, _FrameAssembler_instances, "m", _FrameAssembler_readUint32BE).call(this, offset);
|
|
42
|
+
offset += 4;
|
|
43
|
+
if (frameLength === 0) {
|
|
44
|
+
output.push(__classPrivateFieldGet(this, _FrameAssembler_instances, "m", _FrameAssembler_flushFrames).call(this));
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (offset + frameLength > __classPrivateFieldGet(this, _FrameAssembler_buffer, "f").length) {
|
|
48
|
+
offset -= 4; // rewind header, wait for more data
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
__classPrivateFieldGet(this, _FrameAssembler_frames, "f").push(__classPrivateFieldGet(this, _FrameAssembler_buffer, "f").subarray(offset, offset + frameLength));
|
|
52
|
+
offset += frameLength;
|
|
53
|
+
}
|
|
54
|
+
if (offset > 0) {
|
|
55
|
+
__classPrivateFieldSet(this, _FrameAssembler_buffer, __classPrivateFieldGet(this, _FrameAssembler_buffer, "f").subarray(offset), "f");
|
|
56
|
+
}
|
|
57
|
+
return output;
|
|
58
|
+
}
|
|
59
|
+
/** Resets the assembler */
|
|
60
|
+
reset() {
|
|
61
|
+
__classPrivateFieldSet(this, _FrameAssembler_buffer, new Uint8Array(0), "f");
|
|
62
|
+
__classPrivateFieldSet(this, _FrameAssembler_frames, [], "f");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
_FrameAssembler_buffer = new WeakMap(), _FrameAssembler_frames = new WeakMap(), _FrameAssembler_instances = new WeakSet(), _FrameAssembler_flushFrames = function _FrameAssembler_flushFrames() {
|
|
66
|
+
if (!__classPrivateFieldGet(this, _FrameAssembler_frames, "f").length) {
|
|
67
|
+
return new Uint8Array(0);
|
|
68
|
+
}
|
|
69
|
+
const payload = __classPrivateFieldGet(this, _FrameAssembler_frames, "f").length === 1
|
|
70
|
+
? __classPrivateFieldGet(this, _FrameAssembler_frames, "f")[0]
|
|
71
|
+
: concatUint8Arrays(__classPrivateFieldGet(this, _FrameAssembler_frames, "f"));
|
|
72
|
+
__classPrivateFieldSet(this, _FrameAssembler_frames, [], "f");
|
|
73
|
+
return payload;
|
|
74
|
+
}, _FrameAssembler_readUint32BE = function _FrameAssembler_readUint32BE(offset) {
|
|
75
|
+
const view = new DataView(__classPrivateFieldGet(this, _FrameAssembler_buffer, "f").buffer, __classPrivateFieldGet(this, _FrameAssembler_buffer, "f").byteOffset + offset, 4);
|
|
76
|
+
return view.getUint32(0, false); // big-endian
|
|
77
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ProtocolLike } from "../definitions/protocol_definitions.js";
|
|
2
|
+
import type { MetadataInit } from "./wire_format/metadata.js";
|
|
3
|
+
/** TextEncoder instance for encoding strings to UTF-8 bytes. */
|
|
4
|
+
export declare const textEncoder: TextEncoder;
|
|
5
|
+
/** TextDecoder instance for decoding UTF-8 bytes to strings. */
|
|
6
|
+
export declare const textDecoder: TextDecoder;
|
|
7
|
+
/**
|
|
8
|
+
* Normalizes a protocol name by prepending the namespace if the name does not already contain a dot.
|
|
9
|
+
* @param name The protocol name.
|
|
10
|
+
* @param namespace Optional namespace to prepend.
|
|
11
|
+
* @returns The normalized protocol name.
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizeProtocolName(name: string, namespace?: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Serializes a protocol to a JSON string containing the protocol name, types, and messages.
|
|
16
|
+
* @param protocol The protocol to stringify.
|
|
17
|
+
* @returns The JSON string representation of the protocol.
|
|
18
|
+
*/
|
|
19
|
+
export declare function stringifyProtocol(protocol: ProtocolLike): string;
|
|
20
|
+
/**
|
|
21
|
+
* Creates metadata with a given ID, optionally copying from a base metadata.
|
|
22
|
+
* @param id The ID to set in the metadata.
|
|
23
|
+
* @param base Optional base metadata to copy from.
|
|
24
|
+
* @returns The new metadata with the ID.
|
|
25
|
+
*/
|
|
26
|
+
export declare function metadataWithId(id: number, base?: MetadataInit | null): MetadataInit;
|
|
27
|
+
/**
|
|
28
|
+
* Converts a 32-bit integer to a Uint8Array of 4 bytes in big-endian order.
|
|
29
|
+
* @param value The integer value to convert.
|
|
30
|
+
* @returns The Uint8Array representation of the integer.
|
|
31
|
+
*/
|
|
32
|
+
export declare function int32ToBytes(value: number): Uint8Array;
|
|
33
|
+
/**
|
|
34
|
+
* Converts a Uint8Array to a hexadecimal string representation.
|
|
35
|
+
* @param bytes The bytes to convert.
|
|
36
|
+
* @returns The hexadecimal string.
|
|
37
|
+
*/
|
|
38
|
+
export declare function bytesToHex(bytes: Uint8Array): string;
|
|
39
|
+
/**
|
|
40
|
+
* Checks if two Uint8Arrays are equal by comparing their lengths and contents.
|
|
41
|
+
* @param a The first Uint8Array.
|
|
42
|
+
* @param b The second Uint8Array.
|
|
43
|
+
* @returns True if the arrays are equal, false otherwise.
|
|
44
|
+
*/
|
|
45
|
+
export declare function bytesEqual(a: Uint8Array, b: Uint8Array): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Converts a Uint8Array to an ArrayBuffer by slicing the underlying buffer.
|
|
48
|
+
* @param bytes The Uint8Array to convert.
|
|
49
|
+
* @returns The corresponding ArrayBuffer.
|
|
50
|
+
*/
|
|
51
|
+
export declare function toArrayBuffer(bytes: Uint8Array): ArrayBuffer;
|
|
52
|
+
/**
|
|
53
|
+
* Converts an error or unknown value to a payload object with a string property.
|
|
54
|
+
* @param err The error or value to convert.
|
|
55
|
+
* @returns An object with a 'string' property containing the error message or string representation.
|
|
56
|
+
*/
|
|
57
|
+
export declare function errorToPayload(err: unknown): {
|
|
58
|
+
string: string;
|
|
59
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/** TextEncoder instance for encoding strings to UTF-8 bytes. */
|
|
2
|
+
export const textEncoder = new TextEncoder();
|
|
3
|
+
/** TextDecoder instance for decoding UTF-8 bytes to strings. */
|
|
4
|
+
export const textDecoder = new TextDecoder();
|
|
5
|
+
/**
|
|
6
|
+
* Normalizes a protocol name by prepending the namespace if the name does not already contain a dot.
|
|
7
|
+
* @param name The protocol name.
|
|
8
|
+
* @param namespace Optional namespace to prepend.
|
|
9
|
+
* @returns The normalized protocol name.
|
|
10
|
+
*/
|
|
11
|
+
export function normalizeProtocolName(name, namespace) {
|
|
12
|
+
if (!name) {
|
|
13
|
+
throw new Error("missing protocol name");
|
|
14
|
+
}
|
|
15
|
+
if (namespace && !name.includes(".")) {
|
|
16
|
+
return `${namespace}.${name}`;
|
|
17
|
+
}
|
|
18
|
+
return name;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Serializes a protocol to a JSON string containing the protocol name, types, and messages.
|
|
22
|
+
* @param protocol The protocol to stringify.
|
|
23
|
+
* @returns The JSON string representation of the protocol.
|
|
24
|
+
*/
|
|
25
|
+
export function stringifyProtocol(protocol) {
|
|
26
|
+
const namedTypes = protocol.getNamedTypes();
|
|
27
|
+
const messages = {};
|
|
28
|
+
for (const [name, message] of protocol.getMessages()) {
|
|
29
|
+
messages[name] = message;
|
|
30
|
+
}
|
|
31
|
+
// The types/messages already implement toJSON, so JSON.stringify will invoke
|
|
32
|
+
// their serialization helpers automatically.
|
|
33
|
+
return JSON.stringify({
|
|
34
|
+
protocol: protocol.getName(),
|
|
35
|
+
types: namedTypes.length ? namedTypes : undefined,
|
|
36
|
+
messages,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Creates metadata with a given ID, optionally copying from a base metadata.
|
|
41
|
+
* @param id The ID to set in the metadata.
|
|
42
|
+
* @param base Optional base metadata to copy from.
|
|
43
|
+
* @returns The new metadata with the ID.
|
|
44
|
+
*/
|
|
45
|
+
export function metadataWithId(id, base) {
|
|
46
|
+
const map = new Map();
|
|
47
|
+
if (base instanceof Map) {
|
|
48
|
+
for (const [key, value] of base) {
|
|
49
|
+
map.set(key, value.slice());
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (Array.isArray(base)) {
|
|
53
|
+
for (const [key, value] of base) {
|
|
54
|
+
map.set(key, value.slice());
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else if (base && typeof base === "object") {
|
|
58
|
+
for (const [key, value] of Object.entries(base)) {
|
|
59
|
+
map.set(key, value.slice());
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
map.set("id", int32ToBytes(id));
|
|
63
|
+
return map;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Converts a 32-bit integer to a Uint8Array of 4 bytes in big-endian order.
|
|
67
|
+
* @param value The integer value to convert.
|
|
68
|
+
* @returns The Uint8Array representation of the integer.
|
|
69
|
+
*/
|
|
70
|
+
export function int32ToBytes(value) {
|
|
71
|
+
const buffer = new ArrayBuffer(4);
|
|
72
|
+
new DataView(buffer).setInt32(0, value, false);
|
|
73
|
+
return new Uint8Array(buffer);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Converts a Uint8Array to a hexadecimal string representation.
|
|
77
|
+
* @param bytes The bytes to convert.
|
|
78
|
+
* @returns The hexadecimal string.
|
|
79
|
+
*/
|
|
80
|
+
export function bytesToHex(bytes) {
|
|
81
|
+
return Array.from(bytes)
|
|
82
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
83
|
+
.join("");
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Checks if two Uint8Arrays are equal by comparing their lengths and contents.
|
|
87
|
+
* @param a The first Uint8Array.
|
|
88
|
+
* @param b The second Uint8Array.
|
|
89
|
+
* @returns True if the arrays are equal, false otherwise.
|
|
90
|
+
*/
|
|
91
|
+
export function bytesEqual(a, b) {
|
|
92
|
+
if (a.length !== b.length) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
for (let i = 0; i < a.length; i++) {
|
|
96
|
+
if (a[i] !== b[i]) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Converts a Uint8Array to an ArrayBuffer by slicing the underlying buffer.
|
|
104
|
+
* @param bytes The Uint8Array to convert.
|
|
105
|
+
* @returns The corresponding ArrayBuffer.
|
|
106
|
+
*/
|
|
107
|
+
export function toArrayBuffer(bytes) {
|
|
108
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Converts an error or unknown value to a payload object with a string property.
|
|
112
|
+
* @param err The error or value to convert.
|
|
113
|
+
* @returns An object with a 'string' property containing the error message or string representation.
|
|
114
|
+
*/
|
|
115
|
+
export function errorToPayload(err) {
|
|
116
|
+
if (err instanceof Error) {
|
|
117
|
+
return { string: err.message };
|
|
118
|
+
}
|
|
119
|
+
if (typeof err === "string") {
|
|
120
|
+
return { string: err };
|
|
121
|
+
}
|
|
122
|
+
return { string: String(err) };
|
|
123
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FetchTransportOptions, StatelessTransportFactory } from "./transport_helpers.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a stateless transport factory using the Fetch API.
|
|
4
|
+
*
|
|
5
|
+
* @param endpoint The URL to send requests to.
|
|
6
|
+
* @param options Configuration options for the fetch transport.
|
|
7
|
+
* @returns A factory function that creates a new transport for each request.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createFetchTransport(endpoint: string | URL, options?: FetchTransportOptions): StatelessTransportFactory;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a stateless transport factory using the Fetch API.
|
|
3
|
+
*
|
|
4
|
+
* @param endpoint The URL to send requests to.
|
|
5
|
+
* @param options Configuration options for the fetch transport.
|
|
6
|
+
* @returns A factory function that creates a new transport for each request.
|
|
7
|
+
*/
|
|
8
|
+
export function createFetchTransport(endpoint, options = {}) {
|
|
9
|
+
const url = typeof endpoint === "string" ? endpoint : endpoint.toString();
|
|
10
|
+
return async () => {
|
|
11
|
+
const stream = new TransformStream();
|
|
12
|
+
const fetchFn = options.fetch ?? fetch;
|
|
13
|
+
const init = { ...(options.init ?? {}) };
|
|
14
|
+
const headers = new Headers(init.headers ?? options.headers);
|
|
15
|
+
if (!headers.has("content-type")) {
|
|
16
|
+
headers.set("content-type", "avro/binary");
|
|
17
|
+
}
|
|
18
|
+
init.method = options.method ?? init.method ?? "POST";
|
|
19
|
+
init.headers = headers;
|
|
20
|
+
init.body = stream.readable;
|
|
21
|
+
const response = await fetchFn(url, init);
|
|
22
|
+
if (!response.body) {
|
|
23
|
+
throw new Error("Fetch response has no body.");
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
readable: response.body,
|
|
27
|
+
writable: stream.writable,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
}
|