1 | import { Metadata } from "grpc";
|
2 | import { Status } from "./generated/status_pb";
|
3 | import {
|
4 | RetryInfo,
|
5 | DebugInfo,
|
6 | QuotaFailure,
|
7 | PreconditionFailure,
|
8 | BadRequest,
|
9 | RequestInfo,
|
10 | ResourceInfo,
|
11 | Help,
|
12 | LocalizedMessage
|
13 | } from "./generated/error_details_pb";
|
14 |
|
15 | export const googleDeserializeMap = {
|
16 | "google.rpc.RetryInfo": RetryInfo.deserializeBinary,
|
17 | "google.rpc.DebugInfo": DebugInfo.deserializeBinary,
|
18 | "google.rpc.QuotaFailure": QuotaFailure.deserializeBinary,
|
19 | "google.rpc.PreconditionFailure": PreconditionFailure.deserializeBinary,
|
20 | "google.rpc.BadRequest": BadRequest.deserializeBinary,
|
21 | "google.rpc.RequestInfo": RequestInfo.deserializeBinary,
|
22 | "google.rpc.ResourceInfo": ResourceInfo.deserializeBinary,
|
23 | "google.rpc.Help": Help.deserializeBinary,
|
24 | "google.rpc.LocalizedMessage": LocalizedMessage.deserializeBinary
|
25 | };
|
26 |
|
27 | interface ServiceError {
|
28 | metadata?: Metadata;
|
29 | }
|
30 |
|
31 | export function deserializeGrpcStatusDetails<
|
32 | TMap extends Record<string, (bytes: Uint8Array) => any>
|
33 | >(
|
34 | error: ServiceError,
|
35 | deserializeMap: TMap
|
36 | ): {
|
37 | status: Status;
|
38 | details: Array<ReturnType<TMap[keyof TMap]>>;
|
39 | } | null {
|
40 | if (!error.metadata) {
|
41 | return null;
|
42 | }
|
43 |
|
44 | const buffer = error.metadata.get("grpc-status-details-bin")[0];
|
45 |
|
46 | if (!buffer || typeof buffer === "string") {
|
47 | return null;
|
48 | }
|
49 |
|
50 | let status: Status | undefined;
|
51 |
|
52 | status = Status.deserializeBinary(buffer);
|
53 |
|
54 | const details: Array<ReturnType<TMap[keyof TMap]>> = status
|
55 | .getDetailsList()
|
56 | .map(detail => {
|
57 | const deserialize = deserializeMap[detail.getTypeName()];
|
58 | if (deserialize) {
|
59 | const message = detail.unpack(deserialize, detail.getTypeName());
|
60 |
|
61 | return message;
|
62 | }
|
63 | return null;
|
64 | })
|
65 | .filter(notEmpty);
|
66 |
|
67 | return {
|
68 | status,
|
69 | details
|
70 | };
|
71 | }
|
72 |
|
73 | export function deserializeGoogleGrpcStatusDetails(error: ServiceError) {
|
74 | return deserializeGrpcStatusDetails(error, googleDeserializeMap);
|
75 | }
|
76 |
|
77 | const notEmpty = <TValue>(
|
78 | value: TValue | null | undefined
|
79 | ): value is TValue => {
|
80 | return value !== null && value !== undefined;
|
81 | };
|