@cerbos/grpc
Version:
Client library for interacting with the Cerbos policy decision point service over gRPC from server-side Node.js applications
90 lines • 3.04 kB
JavaScript
import { fromBinary as bufFromBinary, toBinary } from "@bufbuild/protobuf";
import { Metadata } from "@grpc/grpc-js";
import { StatusSchema } from "@cerbos/api/google/rpc/status_pb";
import { AbstractErrorResponse, isObject, methodName, } from "@cerbos/core/~internal";
export class Transport {
client;
constructor(client) {
this.client = client;
}
async unary(method, request, headers, abortHandler) {
return await new Promise((resolve, reject) => {
abortHandler.throwIfAborted();
const call = this.client.makeUnaryRequest(path(method), serialize(method.input), deserialize(method.output), request, metadata(headers), (error, response) => {
if (error) {
reject(new ErrorResponse(error));
}
else if (!response) {
reject(new Error("No response received"));
}
else {
resolve(response);
}
});
abortHandler.onAbort((error) => {
reject(error);
call.cancel();
});
});
}
async *serverStream(method, request, headers, abortHandler) {
abortHandler.throwIfAborted();
try {
const stream = this.client.makeServerStreamRequest(path(method), serialize(method.input), deserialize(method.output), request, metadata(headers));
abortHandler.onAbort(() => {
stream.cancel();
});
for await (const response of stream) {
yield response;
}
}
catch (error) {
if (isStatus(error)) {
throw new ErrorResponse(error);
}
throw error;
}
}
}
class ErrorResponse extends AbstractErrorResponse {
metadata;
constructor({ code, details, metadata }) {
super(code, details);
this.metadata = metadata;
}
*details() {
const [encoded] = this.metadata.get("grpc-status-details-bin");
if (!(encoded instanceof Uint8Array)) {
return;
}
const { details } = fromBinary(StatusSchema, encoded);
yield* details;
}
parseDetails = fromBinary;
}
function isStatus(error) {
return (isObject(error) &&
typeof error["code"] === "number" &&
typeof error["details"] === "string" &&
error["metadata"] instanceof Metadata);
}
function metadata(headers) {
const metadata = new Metadata();
for (const [name, value] of headers) {
metadata.set(name, value);
}
return metadata;
}
function path(method) {
return `/${methodName(method)}`;
}
function serialize(schema) {
return (request) => Buffer.from(toBinary(schema, request).buffer);
}
function deserialize(schema) {
return (output) => fromBinary(schema, output);
}
function fromBinary(schema, bytes) {
return bufFromBinary(schema, bytes, { readUnknownFields: false });
}
//# sourceMappingURL=transport.js.map