UNPKG

@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
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