🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@connectrpc/connect

Package Overview
Dependencies
Maintainers
6
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@connectrpc/connect - npm Package Compare versions

Comparing version
2.0.2
to
2.0.3
+2
-2
dist/cjs/callback-client.js

@@ -46,3 +46,3 @@ "use strict";

function createUnaryFn(transport, method) {
return function (requestMessage, callback, options) {
return (requestMessage, callback, options) => {
const abort = new AbortController();

@@ -69,3 +69,3 @@ options = wrapSignal(abort, options);

function createServerStreamingFn(transport, method) {
return function (input, onResponse, onClose, options) {
return (input, onResponse, onClose, options) => {
const abort = new AbortController();

@@ -72,0 +72,0 @@ async function run() {

@@ -59,4 +59,4 @@ import { Code } from "./code.js";

* - If the value is already a ConnectError, return it as is.
* - If the value is an AbortError from the fetch API, return the message
* of the AbortError with code Canceled.
* - If the value is an AbortError or TimeoutError from the fetch API, return
* the message of the error with code Canceled.
* - For other Errors, return the error message with code Unknown by default.

@@ -63,0 +63,0 @@ * - For other values, return the values String representation as a message,

@@ -56,4 +56,4 @@ "use strict";

* - If the value is already a ConnectError, return it as is.
* - If the value is an AbortError from the fetch API, return the message
* of the AbortError with code Canceled.
* - If the value is an AbortError or TimeoutError from the fetch API, return
* the message of the error with code Canceled.
* - For other Errors, return the error message with code Unknown by default.

@@ -70,6 +70,5 @@ * - For other values, return the values String representation as a message,

if (reason instanceof Error) {
if (reason.name == "AbortError") {
// Fetch requests can only be canceled with an AbortController.
// We detect that condition by looking at the name of the raised
// error object, and translate to the appropriate status code.
if (reason.name == "AbortError" || reason.name == "TimeoutError") {
// Fetch requests can only be canceled with an AbortController,
// or with AbortSignal.timeout().
return new ConnectError(reason.message, code_js_1.Code.Canceled);

@@ -76,0 +75,0 @@ }

@@ -23,6 +23,9 @@ "use strict";

function applyInterceptors(next, interceptors) {
var _a;
return ((_a = interceptors === null || interceptors === void 0 ? void 0 : interceptors.concat().reverse().reduce(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
(n, i) => i(n), next)) !== null && _a !== void 0 ? _a : next);
if (!interceptors) {
return next;
}
for (const i of interceptors.concat().reverse()) {
next = i(next);
}
return next;
}

@@ -71,3 +71,3 @@ "use strict";

function createUnaryFn(transport, method) {
return async function (input, options) {
return async (input, options) => {
var _a, _b;

@@ -81,8 +81,6 @@ const response = await transport.unary(method, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.timeoutMs, options === null || options === void 0 ? void 0 : options.headers, input, options === null || options === void 0 ? void 0 : options.contextValues);

function createServerStreamingFn(transport, method) {
return function (input, options) {
return handleStreamResponse(transport.stream(method, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.timeoutMs, options === null || options === void 0 ? void 0 : options.headers, (0, async_iterable_js_1.createAsyncIterable)([input]), options === null || options === void 0 ? void 0 : options.contextValues), options);
};
return (input, options) => handleStreamResponse(transport.stream(method, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.timeoutMs, options === null || options === void 0 ? void 0 : options.headers, (0, async_iterable_js_1.createAsyncIterable)([input]), options === null || options === void 0 ? void 0 : options.contextValues), options);
}
function createClientStreamingFn(transport, method) {
return async function (request, options) {
return async (request, options) => {
var _a, e_1, _b, _c;

@@ -121,5 +119,3 @@ var _d, _e;

function createBiDiStreamingFn(transport, method) {
return function (request, options) {
return handleStreamResponse(transport.stream(method, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.timeoutMs, options === null || options === void 0 ? void 0 : options.headers, request, options === null || options === void 0 ? void 0 : options.contextValues), options);
};
return (request, options) => handleStreamResponse(transport.stream(method, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.timeoutMs, options === null || options === void 0 ? void 0 : options.headers, request, options === null || options === void 0 ? void 0 : options.contextValues), options);
}

@@ -126,0 +122,0 @@ function handleStreamResponse(stream, options) {

@@ -25,5 +25,3 @@ "use strict";

}
else {
return encodeURIComponent(new TextDecoder().decode(message));
}
return encodeURIComponent(new TextDecoder().decode(message));
}

@@ -52,5 +50,5 @@ /**

const url = request.url + query;
const header = new Headers(request.header);
// Omit headers that are not used for unary GET requests.
const header = new Headers(request.header);
[
for (const h of [
headers_js_1.headerProtocolVersion,

@@ -61,5 +59,7 @@ headers_js_1.headerContentType,

headers_js_1.headerUnaryAcceptEncoding,
].forEach((h) => header.delete(h));
]) {
header.delete(h);
}
return Object.assign(Object.assign({}, request), { requestMethod: "GET", url,
header });
}

@@ -43,3 +43,3 @@ "use strict";

// See https://github.com/grpc/grpc/blob/c462bb8d485fc1434ecfae438823ca8d14cf3154/doc/PROTOCOL-HTTP2.md#user-agents
result.set(headers_js_1.headerUserAgent, "connect-es/2.0.2");
result.set(headers_js_1.headerUserAgent, "connect-es/2.0.3");
}

@@ -46,0 +46,0 @@ return result;

@@ -40,3 +40,3 @@ "use strict";

}
else if (v !== exports.protocolVersion) {
if (v !== exports.protocolVersion) {
throw new connect_error_js_1.ConnectError(`${headers_js_1.headerProtocolVersion} must be "${exports.protocolVersion}": got "${v}"`, code_js_1.Code.InvalidArgument);

@@ -56,5 +56,5 @@ }

}
else if (v !== `v${exports.protocolVersion}`) {
if (v !== `v${exports.protocolVersion}`) {
throw new connect_error_js_1.ConnectError(`${query_params_js_1.paramConnectVersion} must be "v${exports.protocolVersion}": got "${v}"`, code_js_1.Code.InvalidArgument);
}
}

@@ -26,2 +26,3 @@ "use strict";

function requestHeader(useBinaryFormat, timeoutMs, userProvidedHeaders, setUserAgent) {
var _a, _b;
const result = new Headers(userProvidedHeaders !== null && userProvidedHeaders !== void 0 ? userProvidedHeaders : {});

@@ -35,8 +36,3 @@ // Note that we do not support the grpc-web-text format.

// See https://github.com/grpc/grpc/blob/c462bb8d485fc1434ecfae438823ca8d14cf3154/doc/PROTOCOL-HTTP2.md#user-agents
let userAgent = "connect-es/2.0.2";
userAgent = result.has(headers_js_1.headerUserAgent)
? result.get(headers_js_1.headerUserAgent)
: result.has(headers_js_1.headerXUserAgent)
? result.get(headers_js_1.headerXUserAgent)
: userAgent;
const userAgent = (_b = (_a = result.get(headers_js_1.headerUserAgent)) !== null && _a !== void 0 ? _a : result.get(headers_js_1.headerXUserAgent)) !== null && _b !== void 0 ? _b : "connect-es/2.0.3";
result.set(headers_js_1.headerXUserAgent, userAgent);

@@ -43,0 +39,0 @@ if (setUserAgent) {

@@ -1,2 +0,2 @@

import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv1";
import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2";
import type { Any } from "@bufbuild/protobuf/wkt";

@@ -3,0 +3,0 @@ import type { Message } from "@bufbuild/protobuf";

@@ -17,3 +17,3 @@ "use strict";

exports.StatusSchema = exports.file_status = void 0;
const codegenv1_1 = require("@bufbuild/protobuf/codegenv1");
const codegenv2_1 = require("@bufbuild/protobuf/codegenv2");
const wkt_1 = require("@bufbuild/protobuf/wkt");

@@ -23,3 +23,3 @@ /**

*/
exports.file_status = (0, codegenv1_1.fileDesc)("CgxzdGF0dXMucHJvdG8SCmdvb2dsZS5ycGMiTgoGU3RhdHVzEgwKBGNvZGUYASABKAUSDwoHbWVzc2FnZRgCIAEoCRIlCgdkZXRhaWxzGAMgAygLMhQuZ29vZ2xlLnByb3RvYnVmLkFueUJeCg5jb20uZ29vZ2xlLnJwY0ILU3RhdHVzUHJvdG9QAVo3Z29vZ2xlLmdvbGFuZy5vcmcvZ2VucHJvdG8vZ29vZ2xlYXBpcy9ycGMvc3RhdHVzO3N0YXR1c6ICA1JQQ2IGcHJvdG8z", [wkt_1.file_google_protobuf_any]);
exports.file_status = (0, codegenv2_1.fileDesc)("CgxzdGF0dXMucHJvdG8SCmdvb2dsZS5ycGMiTgoGU3RhdHVzEgwKBGNvZGUYASABKAUSDwoHbWVzc2FnZRgCIAEoCRIlCgdkZXRhaWxzGAMgAygLMhQuZ29vZ2xlLnByb3RvYnVmLkFueUJeCg5jb20uZ29vZ2xlLnJwY0ILU3RhdHVzUHJvdG9QAVo3Z29vZ2xlLmdvbGFuZy5vcmcvZ2VucHJvdG8vZ29vZ2xlYXBpcy9ycGMvc3RhdHVzO3N0YXR1c6ICA1JQQ2IGcHJvdG8z", [wkt_1.file_google_protobuf_any]);
/**

@@ -29,2 +29,2 @@ * Describes the message google.rpc.Status.

*/
exports.StatusSchema = (0, codegenv1_1.messageDesc)(exports.file_status, 0);
exports.StatusSchema = (0, codegenv2_1.messageDesc)(exports.file_status, 0);

@@ -32,3 +32,3 @@ "use strict";

// See https://github.com/grpc/grpc/blob/c462bb8d485fc1434ecfae438823ca8d14cf3154/doc/PROTOCOL-HTTP2.md#user-agents
result.set(headers_js_1.headerUserAgent, "connect-es/2.0.2");
result.set(headers_js_1.headerUserAgent, "connect-es/2.0.3");
}

@@ -35,0 +35,0 @@ if (timeoutMs !== undefined) {

@@ -1,2 +0,2 @@

import type { EnvelopedMessage } from "./envelope.js";
import { type EnvelopedMessage } from "./envelope.js";
import type { Serialization } from "./serialization.js";

@@ -3,0 +3,0 @@ import type { Compression } from "./compression.js";

@@ -64,2 +64,3 @@ "use strict";

const envelope_js_1 = require("./envelope.js");
const envelope_js_2 = require("./envelope.js");
const limit_io_js_1 = require("./limit-io.js");

@@ -73,3 +74,2 @@ function pipeTo(source, ...rest) {

}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore

@@ -99,3 +99,3 @@ iterable = pipe(iterable, ...transforms, { propagateDownStreamError: false });

function sinkAll() {
return async function (iterable) {
return async (iterable) => {
var _a, e_1, _b, _c;

@@ -136,5 +136,3 @@ const all = [];

function sinkAllBytes(readMaxBytes, lengthHint) {
return async function (iterable) {
return await readAllBytes(iterable, readMaxBytes, lengthHint);
};
return async (iterable) => await readAllBytes(iterable, readMaxBytes, lengthHint);
}

@@ -487,3 +485,3 @@ function pipe(source, ...rest) {

const env = _c;
yield yield __await(yield __await((0, envelope_js_1.envelopeCompress)(env, compression, compressMinBytes)));
yield yield __await(yield __await((0, envelope_js_2.envelopeCompress)(env, compression, compressMinBytes)));
}

@@ -519,3 +517,3 @@ }

const env = _c;
yield yield __await(yield __await((0, envelope_js_1.envelopeDecompress)(env, compression, readMaxBytes)));
yield yield __await(yield __await((0, envelope_js_2.envelopeDecompress)(env, compression, readMaxBytes)));
}

@@ -548,3 +546,3 @@ }

const { flags, data } = _c;
yield yield __await((0, envelope_js_1.encodeEnvelope)(flags, data));
yield yield __await((0, envelope_js_2.encodeEnvelope)(flags, data));
}

@@ -574,34 +572,6 @@ }

function transformSplitEnvelope(readMaxBytes) {
// append chunk to buffer, returning updated buffer
function append(buffer, chunk) {
const n = new Uint8Array(buffer.byteLength + chunk.byteLength);
n.set(buffer);
n.set(chunk, buffer.length);
return n;
}
// tuple 0: envelope, or undefined if incomplete
// tuple 1: remainder of the buffer
function shiftEnvelope(buffer, header) {
if (buffer.byteLength < 5 + header.length) {
return [undefined, buffer];
}
return [
{ flags: header.flags, data: buffer.subarray(5, 5 + header.length) },
buffer.subarray(5 + header.length),
];
}
// undefined: header is incomplete
function peekHeader(buffer) {
if (buffer.byteLength < 5) {
return undefined;
}
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
const length = view.getUint32(1); // 4 bytes message length
const flags = view.getUint8(0); // first byte is flags
return { length, flags };
}
return function (iterable) {
return __asyncGenerator(this, arguments, function* () {
var _a, e_11, _b, _c;
let buffer = new Uint8Array(0);
const buffer = (0, envelope_js_1.createEnvelopeDecoder)(readMaxBytes);
try {

@@ -612,14 +582,3 @@ for (var _d = true, iterable_11 = __asyncValues(iterable), iterable_11_1; iterable_11_1 = yield __await(iterable_11.next()), _a = iterable_11_1.done, !_a; _d = true) {

const chunk = _c;
buffer = append(buffer, chunk);
for (;;) {
const header = peekHeader(buffer);
if (!header) {
break;
}
(0, limit_io_js_1.assertReadMaxBytes)(readMaxBytes, header.length, true);
let env;
[env, buffer] = shiftEnvelope(buffer, header);
if (!env) {
break;
}
for (const env of buffer.decode(chunk)) {
yield yield __await(env);

@@ -637,8 +596,3 @@ }

if (buffer.byteLength > 0) {
const header = peekHeader(buffer);
let message = "protocol error: incomplete envelope";
if (header) {
message = `protocol error: promised ${header.length} bytes in enveloped message, got ${buffer.byteLength - 5} bytes`;
}
throw new connect_error_js_1.ConnectError(message, code_js_1.Code.InvalidArgument);
throw new connect_error_js_1.ConnectError("protocol error: incomplete envelope", code_js_1.Code.InvalidArgument);
}

@@ -752,7 +706,5 @@ });

if (it.throw !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- can't handle mutated object sensibly
w.throw = (e) => it.throw(e);
}
if (it.return !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion,@typescript-eslint/no-explicit-any -- can't handle mutated object sensibly
w.return = (value) => it.return(value);

@@ -927,4 +879,7 @@ }

let readResolve;
const readPromise = new Promise((resolve) => (readResolve = resolve));
readQueue.push(readResolve); // eslint-disable-line @typescript-eslint/no-non-null-assertion
const readPromise = new Promise((resolve) => {
readResolve = resolve;
});
// biome-ignore lint/style/noNonNullAssertion: initialized by promise executor
readQueue.push(readResolve);
return readPromise;

@@ -966,3 +921,2 @@ },

*/
// eslint-disable-next-line @typescript-eslint/require-await
function createAsyncIterable(items) {

@@ -969,0 +923,0 @@ return __asyncGenerator(this, arguments, function* createAsyncIterable_1() {

@@ -19,2 +19,33 @@ import type { Compression } from "./compression.js";

/**
* Decodes chunks of raw bytes into enveloped messages.
*
* @private Internal code, does not follow semantic versioning.
*/
export type EnvelopeDecoder = {
/**
* Decode enveloped messages.
*
* If the chunk is incomplete, buffer for subsequent calls.
*
* If a message exceeds `readMaxBytes`, raise an error. The decoder must be
* discarded.
*/
decode(chunk: Uint8Array): EnvelopedMessage[];
/**
* Size of the buffer. Use this property to check for incomplete data.
*/
readonly byteLength: number;
/**
* Maximum size for individual messages.
*/
readonly readMaxBytes: number;
};
/**
* Create an EnvelopeDecoder. The `readMaxBytes` argument limits the maximum
* size for individual messages.
*
* @private Internal code, does not follow semantic versioning.
*/
export declare function createEnvelopeDecoder(readMaxBytes: number): EnvelopeDecoder;
/**
* Create a WHATWG ReadableStream of enveloped messages from a ReadableStream

@@ -21,0 +52,0 @@ * of bytes.

@@ -16,2 +16,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.createEnvelopeDecoder = createEnvelopeDecoder;
exports.createEnvelopeReadableStream = createEnvelopeReadableStream;

@@ -25,3 +26,86 @@ exports.envelopeCompress = envelopeCompress;

const compression_js_1 = require("./compression.js");
const limit_io_js_1 = require("./limit-io.js");
/**
* Create an EnvelopeDecoder. The `readMaxBytes` argument limits the maximum
* size for individual messages.
*
* @private Internal code, does not follow semantic versioning.
*/
function createEnvelopeDecoder(readMaxBytes) {
return new EnvelopeDecoderImpl(readMaxBytes);
}
class EnvelopeDecoderImpl {
constructor(readMaxBytes) {
this.readMaxBytes = readMaxBytes;
// Envelope headers are 5 bytes: 1 byte for flags, 4 bytes message length
this.header = new Uint8Array(5);
this.headerView = new DataView(this.header.buffer);
this.buf = [];
}
get byteLength() {
return this.buf.reduce((a, b) => a + b.byteLength, 0);
}
decode(chunk) {
this.buf.push(chunk);
const envs = [];
for (;;) {
let env = this.pop();
if (!env) {
break;
}
envs.push(env);
}
return envs;
}
// consume an enveloped message
pop() {
if (!this.env) {
this.env = this.head();
if (!this.env) {
return undefined;
}
}
if (this.cons(this.env.data)) {
const env = this.env;
this.env = undefined;
return env;
}
return undefined;
}
// consume header
head() {
if (!this.cons(this.header)) {
return undefined;
}
const flags = this.headerView.getUint8(0); // first byte is flags
const length = this.headerView.getUint32(1); // 4 bytes message length
(0, limit_io_js_1.assertReadMaxBytes)(this.readMaxBytes, length, true);
return {
flags,
data: new Uint8Array(length),
};
}
// consume from buffer, fill target
cons(target) {
const wantLength = target.byteLength;
if (this.byteLength < wantLength) {
return false;
}
let offset = 0;
while (offset < wantLength) {
const chunk = this.buf.shift(); // we check length above
if (chunk.byteLength > wantLength - offset) {
target.set(chunk.subarray(0, wantLength - offset), offset);
this.buf.unshift(chunk.subarray(wantLength - offset));
offset += wantLength - offset;
}
else {
target.set(chunk, offset);
offset += chunk.byteLength;
}
}
return true;
}
}
/**
* Create a WHATWG ReadableStream of enveloped messages from a ReadableStream

@@ -37,9 +121,3 @@ * of bytes.

let reader;
let buffer = new Uint8Array(0);
function append(chunk) {
const n = new Uint8Array(buffer.length + chunk.length);
n.set(buffer);
n.set(chunk, buffer.length);
buffer = n;
}
const buffer = createEnvelopeDecoder(0xffffffff);
return new ReadableStream({

@@ -50,34 +128,18 @@ start() {

async pull(controller) {
let header = undefined;
for (;;) {
if (header === undefined && buffer.byteLength >= 5) {
let length = 0;
for (let i = 1; i < 5; i++) {
length = (length << 8) + buffer[i];
}
header = { flags: buffer[0], length };
}
if (header !== undefined && buffer.byteLength >= header.length + 5) {
break;
}
let enqueuedOnce = false;
while (!enqueuedOnce) {
const result = await reader.read();
if (result.done) {
break;
}
append(result.value);
}
if (header === undefined) {
if (buffer.byteLength == 0) {
if (buffer.byteLength > 0) {
controller.error(new connect_error_js_1.ConnectError("protocol error: incomplete envelope", code_js_1.Code.InvalidArgument));
}
controller.close();
return;
}
controller.error(new connect_error_js_1.ConnectError("premature end of stream", code_js_1.Code.DataLoss));
return;
else {
for (const env of buffer.decode(result.value)) {
controller.enqueue(env);
enqueuedOnce = true;
}
}
}
const data = buffer.subarray(5, 5 + header.length);
buffer = buffer.subarray(5 + header.length);
controller.enqueue({
flags: header.flags,
data,
});
},

@@ -84,0 +146,0 @@ });

@@ -47,6 +47,6 @@ "use strict";

if (it.throw !== undefined) {
res.throw = (e) => it.throw(e).then(transform); // eslint-disable-line @typescript-eslint/no-non-null-assertion
res.throw = (e) => it.throw(e).then(transform);
}
if (it.return !== undefined) {
res.return = (v) => it.return(v).then(transform); // eslint-disable-line @typescript-eslint/no-non-null-assertion
res.return = (v) => it.return(v).then(transform);
}

@@ -53,0 +53,0 @@ return res;

@@ -58,7 +58,5 @@ "use strict";

if (it.throw !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- can't handle mutated object sensibly
w.throw = (e) => it.throw(e);
}
if (it.return !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion,@typescript-eslint/no-explicit-any -- can't handle mutated object sensibly
w.return = (value) => it.return(value);

@@ -65,0 +63,0 @@ }

@@ -43,3 +43,3 @@ // Copyright 2021-2025 The Connect Authors

function createUnaryFn(transport, method) {
return function (requestMessage, callback, options) {
return (requestMessage, callback, options) => {
const abort = new AbortController();

@@ -66,3 +66,3 @@ options = wrapSignal(abort, options);

function createServerStreamingFn(transport, method) {
return function (input, onResponse, onClose, options) {
return (input, onResponse, onClose, options) => {
const abort = new AbortController();

@@ -69,0 +69,0 @@ async function run() {

@@ -59,4 +59,4 @@ import { Code } from "./code.js";

* - If the value is already a ConnectError, return it as is.
* - If the value is an AbortError from the fetch API, return the message
* of the AbortError with code Canceled.
* - If the value is an AbortError or TimeoutError from the fetch API, return
* the message of the error with code Canceled.
* - For other Errors, return the error message with code Unknown by default.

@@ -63,0 +63,0 @@ * - For other values, return the values String representation as a message,

@@ -53,4 +53,4 @@ // Copyright 2021-2025 The Connect Authors

* - If the value is already a ConnectError, return it as is.
* - If the value is an AbortError from the fetch API, return the message
* of the AbortError with code Canceled.
* - If the value is an AbortError or TimeoutError from the fetch API, return
* the message of the error with code Canceled.
* - For other Errors, return the error message with code Unknown by default.

@@ -67,6 +67,5 @@ * - For other values, return the values String representation as a message,

if (reason instanceof Error) {
if (reason.name == "AbortError") {
// Fetch requests can only be canceled with an AbortController.
// We detect that condition by looking at the name of the raised
// error object, and translate to the appropriate status code.
if (reason.name == "AbortError" || reason.name == "TimeoutError") {
// Fetch requests can only be canceled with an AbortController,
// or with AbortSignal.timeout().
return new ConnectError(reason.message, Code.Canceled);

@@ -73,0 +72,0 @@ }

@@ -20,6 +20,9 @@ // Copyright 2021-2025 The Connect Authors

export function applyInterceptors(next, interceptors) {
var _a;
return ((_a = interceptors === null || interceptors === void 0 ? void 0 : interceptors.concat().reverse().reduce(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
(n, i) => i(n), next)) !== null && _a !== void 0 ? _a : next);
if (!interceptors) {
return next;
}
for (const i of interceptors.concat().reverse()) {
next = i(next);
}
return next;
}

@@ -64,3 +64,3 @@ // Copyright 2021-2025 The Connect Authors

export function createUnaryFn(transport, method) {
return async function (input, options) {
return async (input, options) => {
var _a, _b;

@@ -74,8 +74,6 @@ const response = await transport.unary(method, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.timeoutMs, options === null || options === void 0 ? void 0 : options.headers, input, options === null || options === void 0 ? void 0 : options.contextValues);

export function createServerStreamingFn(transport, method) {
return function (input, options) {
return handleStreamResponse(transport.stream(method, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.timeoutMs, options === null || options === void 0 ? void 0 : options.headers, createAsyncIterable([input]), options === null || options === void 0 ? void 0 : options.contextValues), options);
};
return (input, options) => handleStreamResponse(transport.stream(method, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.timeoutMs, options === null || options === void 0 ? void 0 : options.headers, createAsyncIterable([input]), options === null || options === void 0 ? void 0 : options.contextValues), options);
}
export function createClientStreamingFn(transport, method) {
return async function (request, options) {
return async (request, options) => {
var _a, e_1, _b, _c;

@@ -114,5 +112,3 @@ var _d, _e;

export function createBiDiStreamingFn(transport, method) {
return function (request, options) {
return handleStreamResponse(transport.stream(method, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.timeoutMs, options === null || options === void 0 ? void 0 : options.headers, request, options === null || options === void 0 ? void 0 : options.contextValues), options);
};
return (request, options) => handleStreamResponse(transport.stream(method, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.timeoutMs, options === null || options === void 0 ? void 0 : options.headers, request, options === null || options === void 0 ? void 0 : options.contextValues), options);
}

@@ -119,0 +115,0 @@ function handleStreamResponse(stream, options) {

@@ -22,5 +22,3 @@ // Copyright 2021-2025 The Connect Authors

}
else {
return encodeURIComponent(new TextDecoder().decode(message));
}
return encodeURIComponent(new TextDecoder().decode(message));
}

@@ -49,5 +47,5 @@ /**

const url = request.url + query;
const header = new Headers(request.header);
// Omit headers that are not used for unary GET requests.
const header = new Headers(request.header);
[
for (const h of [
headerProtocolVersion,

@@ -58,5 +56,7 @@ headerContentType,

headerUnaryAcceptEncoding,
].forEach((h) => header.delete(h));
]) {
header.delete(h);
}
return Object.assign(Object.assign({}, request), { requestMethod: "GET", url,
header });
}

@@ -39,3 +39,3 @@ // Copyright 2021-2025 The Connect Authors

// See https://github.com/grpc/grpc/blob/c462bb8d485fc1434ecfae438823ca8d14cf3154/doc/PROTOCOL-HTTP2.md#user-agents
result.set(headerUserAgent, "connect-es/2.0.2");
result.set(headerUserAgent, "connect-es/2.0.3");
}

@@ -42,0 +42,0 @@ return result;

@@ -35,3 +35,3 @@ // Copyright 2021-2025 The Connect Authors

}
else if (v !== protocolVersion) {
if (v !== protocolVersion) {
throw new ConnectError(`${headerProtocolVersion} must be "${protocolVersion}": got "${v}"`, Code.InvalidArgument);

@@ -51,5 +51,5 @@ }

}
else if (v !== `v${protocolVersion}`) {
if (v !== `v${protocolVersion}`) {
throw new ConnectError(`${paramConnectVersion} must be "v${protocolVersion}": got "${v}"`, Code.InvalidArgument);
}
}

@@ -22,2 +22,3 @@ // Copyright 2021-2025 The Connect Authors

export function requestHeader(useBinaryFormat, timeoutMs, userProvidedHeaders, setUserAgent) {
var _a, _b;
const result = new Headers(userProvidedHeaders !== null && userProvidedHeaders !== void 0 ? userProvidedHeaders : {});

@@ -31,8 +32,3 @@ // Note that we do not support the grpc-web-text format.

// See https://github.com/grpc/grpc/blob/c462bb8d485fc1434ecfae438823ca8d14cf3154/doc/PROTOCOL-HTTP2.md#user-agents
let userAgent = "connect-es/2.0.2";
userAgent = result.has(headerUserAgent)
? result.get(headerUserAgent)
: result.has(headerXUserAgent)
? result.get(headerXUserAgent)
: userAgent;
const userAgent = (_b = (_a = result.get(headerUserAgent)) !== null && _a !== void 0 ? _a : result.get(headerXUserAgent)) !== null && _b !== void 0 ? _b : "connect-es/2.0.3";
result.set(headerXUserAgent, userAgent);

@@ -39,0 +35,0 @@ if (setUserAgent) {

@@ -1,2 +0,2 @@

import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv1";
import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2";
import type { Any } from "@bufbuild/protobuf/wkt";

@@ -3,0 +3,0 @@ import type { Message } from "@bufbuild/protobuf";

@@ -14,3 +14,3 @@ // Copyright 2021-2025 The Connect Authors

// limitations under the License.
import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv1";
import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
import { file_google_protobuf_any } from "@bufbuild/protobuf/wkt";

@@ -17,0 +17,0 @@ /**

@@ -28,3 +28,3 @@ // Copyright 2021-2025 The Connect Authors

// See https://github.com/grpc/grpc/blob/c462bb8d485fc1434ecfae438823ca8d14cf3154/doc/PROTOCOL-HTTP2.md#user-agents
result.set(headerUserAgent, "connect-es/2.0.2");
result.set(headerUserAgent, "connect-es/2.0.3");
}

@@ -31,0 +31,0 @@ if (timeoutMs !== undefined) {

@@ -1,2 +0,2 @@

import type { EnvelopedMessage } from "./envelope.js";
import { type EnvelopedMessage } from "./envelope.js";
import type { Serialization } from "./serialization.js";

@@ -3,0 +3,0 @@ import type { Compression } from "./compression.js";

@@ -41,2 +41,3 @@ // Copyright 2021-2025 The Connect Authors

import { ConnectError } from "../connect-error.js";
import { createEnvelopeDecoder } from "./envelope.js";
import { encodeEnvelope, envelopeCompress, envelopeDecompress, } from "./envelope.js";

@@ -51,3 +52,2 @@ import { assertReadMaxBytes } from "./limit-io.js";

}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore

@@ -77,3 +77,3 @@ iterable = pipe(iterable, ...transforms, { propagateDownStreamError: false });

export function sinkAll() {
return async function (iterable) {
return async (iterable) => {
var _a, e_1, _b, _c;

@@ -114,5 +114,3 @@ const all = [];

export function sinkAllBytes(readMaxBytes, lengthHint) {
return async function (iterable) {
return await readAllBytes(iterable, readMaxBytes, lengthHint);
};
return async (iterable) => await readAllBytes(iterable, readMaxBytes, lengthHint);
}

@@ -549,34 +547,6 @@ export function pipe(source, ...rest) {

export function transformSplitEnvelope(readMaxBytes) {
// append chunk to buffer, returning updated buffer
function append(buffer, chunk) {
const n = new Uint8Array(buffer.byteLength + chunk.byteLength);
n.set(buffer);
n.set(chunk, buffer.length);
return n;
}
// tuple 0: envelope, or undefined if incomplete
// tuple 1: remainder of the buffer
function shiftEnvelope(buffer, header) {
if (buffer.byteLength < 5 + header.length) {
return [undefined, buffer];
}
return [
{ flags: header.flags, data: buffer.subarray(5, 5 + header.length) },
buffer.subarray(5 + header.length),
];
}
// undefined: header is incomplete
function peekHeader(buffer) {
if (buffer.byteLength < 5) {
return undefined;
}
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
const length = view.getUint32(1); // 4 bytes message length
const flags = view.getUint8(0); // first byte is flags
return { length, flags };
}
return function (iterable) {
return __asyncGenerator(this, arguments, function* () {
var _a, e_11, _b, _c;
let buffer = new Uint8Array(0);
const buffer = createEnvelopeDecoder(readMaxBytes);
try {

@@ -587,14 +557,3 @@ for (var _d = true, iterable_11 = __asyncValues(iterable), iterable_11_1; iterable_11_1 = yield __await(iterable_11.next()), _a = iterable_11_1.done, !_a; _d = true) {

const chunk = _c;
buffer = append(buffer, chunk);
for (;;) {
const header = peekHeader(buffer);
if (!header) {
break;
}
assertReadMaxBytes(readMaxBytes, header.length, true);
let env;
[env, buffer] = shiftEnvelope(buffer, header);
if (!env) {
break;
}
for (const env of buffer.decode(chunk)) {
yield yield __await(env);

@@ -612,8 +571,3 @@ }

if (buffer.byteLength > 0) {
const header = peekHeader(buffer);
let message = "protocol error: incomplete envelope";
if (header) {
message = `protocol error: promised ${header.length} bytes in enveloped message, got ${buffer.byteLength - 5} bytes`;
}
throw new ConnectError(message, Code.InvalidArgument);
throw new ConnectError("protocol error: incomplete envelope", Code.InvalidArgument);
}

@@ -727,7 +681,5 @@ });

if (it.throw !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- can't handle mutated object sensibly
w.throw = (e) => it.throw(e);
}
if (it.return !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion,@typescript-eslint/no-explicit-any -- can't handle mutated object sensibly
w.return = (value) => it.return(value);

@@ -902,4 +854,7 @@ }

let readResolve;
const readPromise = new Promise((resolve) => (readResolve = resolve));
readQueue.push(readResolve); // eslint-disable-line @typescript-eslint/no-non-null-assertion
const readPromise = new Promise((resolve) => {
readResolve = resolve;
});
// biome-ignore lint/style/noNonNullAssertion: initialized by promise executor
readQueue.push(readResolve);
return readPromise;

@@ -941,3 +896,2 @@ },

*/
// eslint-disable-next-line @typescript-eslint/require-await
export function createAsyncIterable(items) {

@@ -944,0 +898,0 @@ return __asyncGenerator(this, arguments, function* createAsyncIterable_1() {

@@ -19,2 +19,33 @@ import type { Compression } from "./compression.js";

/**
* Decodes chunks of raw bytes into enveloped messages.
*
* @private Internal code, does not follow semantic versioning.
*/
export type EnvelopeDecoder = {
/**
* Decode enveloped messages.
*
* If the chunk is incomplete, buffer for subsequent calls.
*
* If a message exceeds `readMaxBytes`, raise an error. The decoder must be
* discarded.
*/
decode(chunk: Uint8Array): EnvelopedMessage[];
/**
* Size of the buffer. Use this property to check for incomplete data.
*/
readonly byteLength: number;
/**
* Maximum size for individual messages.
*/
readonly readMaxBytes: number;
};
/**
* Create an EnvelopeDecoder. The `readMaxBytes` argument limits the maximum
* size for individual messages.
*
* @private Internal code, does not follow semantic versioning.
*/
export declare function createEnvelopeDecoder(readMaxBytes: number): EnvelopeDecoder;
/**
* Create a WHATWG ReadableStream of enveloped messages from a ReadableStream

@@ -21,0 +52,0 @@ * of bytes.

@@ -17,3 +17,86 @@ // Copyright 2021-2025 The Connect Authors

import { compressedFlag } from "./compression.js";
import { assertReadMaxBytes } from "./limit-io.js";
/**
* Create an EnvelopeDecoder. The `readMaxBytes` argument limits the maximum
* size for individual messages.
*
* @private Internal code, does not follow semantic versioning.
*/
export function createEnvelopeDecoder(readMaxBytes) {
return new EnvelopeDecoderImpl(readMaxBytes);
}
class EnvelopeDecoderImpl {
constructor(readMaxBytes) {
this.readMaxBytes = readMaxBytes;
// Envelope headers are 5 bytes: 1 byte for flags, 4 bytes message length
this.header = new Uint8Array(5);
this.headerView = new DataView(this.header.buffer);
this.buf = [];
}
get byteLength() {
return this.buf.reduce((a, b) => a + b.byteLength, 0);
}
decode(chunk) {
this.buf.push(chunk);
const envs = [];
for (;;) {
let env = this.pop();
if (!env) {
break;
}
envs.push(env);
}
return envs;
}
// consume an enveloped message
pop() {
if (!this.env) {
this.env = this.head();
if (!this.env) {
return undefined;
}
}
if (this.cons(this.env.data)) {
const env = this.env;
this.env = undefined;
return env;
}
return undefined;
}
// consume header
head() {
if (!this.cons(this.header)) {
return undefined;
}
const flags = this.headerView.getUint8(0); // first byte is flags
const length = this.headerView.getUint32(1); // 4 bytes message length
assertReadMaxBytes(this.readMaxBytes, length, true);
return {
flags,
data: new Uint8Array(length),
};
}
// consume from buffer, fill target
cons(target) {
const wantLength = target.byteLength;
if (this.byteLength < wantLength) {
return false;
}
let offset = 0;
while (offset < wantLength) {
const chunk = this.buf.shift(); // we check length above
if (chunk.byteLength > wantLength - offset) {
target.set(chunk.subarray(0, wantLength - offset), offset);
this.buf.unshift(chunk.subarray(wantLength - offset));
offset += wantLength - offset;
}
else {
target.set(chunk, offset);
offset += chunk.byteLength;
}
}
return true;
}
}
/**
* Create a WHATWG ReadableStream of enveloped messages from a ReadableStream

@@ -29,9 +112,3 @@ * of bytes.

let reader;
let buffer = new Uint8Array(0);
function append(chunk) {
const n = new Uint8Array(buffer.length + chunk.length);
n.set(buffer);
n.set(chunk, buffer.length);
buffer = n;
}
const buffer = createEnvelopeDecoder(0xffffffff);
return new ReadableStream({

@@ -42,34 +119,18 @@ start() {

async pull(controller) {
let header = undefined;
for (;;) {
if (header === undefined && buffer.byteLength >= 5) {
let length = 0;
for (let i = 1; i < 5; i++) {
length = (length << 8) + buffer[i];
}
header = { flags: buffer[0], length };
}
if (header !== undefined && buffer.byteLength >= header.length + 5) {
break;
}
let enqueuedOnce = false;
while (!enqueuedOnce) {
const result = await reader.read();
if (result.done) {
break;
}
append(result.value);
}
if (header === undefined) {
if (buffer.byteLength == 0) {
if (buffer.byteLength > 0) {
controller.error(new ConnectError("protocol error: incomplete envelope", Code.InvalidArgument));
}
controller.close();
return;
}
controller.error(new ConnectError("premature end of stream", Code.DataLoss));
return;
else {
for (const env of buffer.decode(result.value)) {
controller.enqueue(env);
enqueuedOnce = true;
}
}
}
const data = buffer.subarray(5, 5 + header.length);
buffer = buffer.subarray(5 + header.length);
controller.enqueue({
flags: header.flags,
data,
});
},

@@ -76,0 +137,0 @@ });

@@ -43,6 +43,6 @@ // Copyright 2021-2025 The Connect Authors

if (it.throw !== undefined) {
res.throw = (e) => it.throw(e).then(transform); // eslint-disable-line @typescript-eslint/no-non-null-assertion
res.throw = (e) => it.throw(e).then(transform);
}
if (it.return !== undefined) {
res.return = (v) => it.return(v).then(transform); // eslint-disable-line @typescript-eslint/no-non-null-assertion
res.return = (v) => it.return(v).then(transform);
}

@@ -49,0 +49,0 @@ return res;

@@ -55,7 +55,5 @@ // Copyright 2021-2025 The Connect Authors

if (it.throw !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- can't handle mutated object sensibly
w.throw = (e) => it.throw(e);
}
if (it.return !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion,@typescript-eslint/no-explicit-any -- can't handle mutated object sensibly
w.return = (value) => it.return(value);

@@ -62,0 +60,0 @@ }

{
"name": "@connectrpc/connect",
"version": "2.0.2",
"version": "2.0.3",
"description": "Type-safe APIs with Protobuf and TypeScript.",

@@ -20,5 +20,5 @@ "license": "Apache-2.0",

"test": "jasmine --config=jasmine.json",
"format": "prettier --write --ignore-unknown '.' '!dist' '!src/protocol-grpc/gen'",
"format": "biome format --write",
"license-header": "license-header",
"lint": "eslint --max-warnings 0 .",
"lint": "biome lint --error-on-warnings",
"attw": "attw --pack"

@@ -53,14 +53,6 @@ },

"*": {
"protocol": [
"./dist/cjs/protocol/index.d.ts"
],
"protocol-connect": [
"./dist/cjs/protocol-connect/index.d.ts"
],
"protocol-grpc": [
"./dist/cjs/protocol-grpc/index.d.ts"
],
"protocol-grpc-web": [
"./dist/cjs/protocol-grpc-web/index.d.ts"
]
"protocol": ["./dist/cjs/protocol/index.d.ts"],
"protocol-connect": ["./dist/cjs/protocol-connect/index.d.ts"],
"protocol-grpc": ["./dist/cjs/protocol-grpc/index.d.ts"],
"protocol-grpc-web": ["./dist/cjs/protocol-grpc-web/index.d.ts"]
}

@@ -72,7 +64,7 @@ },

"devDependencies": {
"@bufbuild/buf": "^1.50.0",
"@bufbuild/protoc-gen-es": "^2.2.3",
"@types/jasmine": "^5.1.5",
"jasmine": "^5.5.0"
"@bufbuild/buf": "^1.55.1",
"@bufbuild/protoc-gen-es": "^2.6.0",
"@types/jasmine": "^5.1.8",
"jasmine": "^5.8.0"
}
}

@@ -9,3 +9,3 @@ # @connectrpc/connect

```
```proto
service ElizaService {

@@ -12,0 +12,0 @@ rpc Say(SayRequest) returns (SayResponse) {}