Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit beabb80

Browse filesBrowse files
feat: decode grpc status objects and map them to protocol types
Status object thrown by grpc commands contains metadata that needs to be serialized in order to map it to custom errors generated through proto files grpc/grpc-web#399
1 parent 1ec0a8c commit beabb80
Copy full SHA for beabb80

File tree

Expand file treeCollapse file tree

1 file changed

+42
-2
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+42
-2
lines changed

‎arduino-ide-extension/src/node/service-error.ts

Copy file name to clipboardExpand all lines: arduino-ide-extension/src/node/service-error.ts
+42-2Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,54 @@
11
import { Metadata, StatusObject } from '@grpc/grpc-js';
2+
import { Status } from './cli-protocol/google/rpc/status_pb';
3+
import { stringToUint8Array } from '../common/utils';
4+
import { ProgrammerIsRequiredForUploadError } from './cli-protocol/cc/arduino/cli/commands/v1/upload_pb';
5+
6+
type ProtoError = typeof ProgrammerIsRequiredForUploadError;
7+
const protoErrorsMap = new Map<string, ProtoError>([
8+
[
9+
'type.googleapis.com/cc.arduino.cli.commands.v1.ProgrammerIsRequiredForUploadError',
10+
ProgrammerIsRequiredForUploadError,
11+
],
12+
// handle other cli defined errors here
13+
]);
214

315
export type ServiceError = StatusObject & Error;
416
export namespace ServiceError {
517
export function isCancel(arg: unknown): arg is ServiceError & { code: 1 } {
618
return is(arg) && arg.code === 1; // https://grpc.github.io/grpc/core/md_doc_statuscodes.html
719
}
20+
821
export function is(arg: unknown): arg is ServiceError {
9-
return arg instanceof Error && isStatusObjet(arg);
22+
return arg instanceof Error && isStatusObject(arg);
1023
}
11-
function isStatusObjet(arg: unknown): arg is StatusObject {
24+
25+
export function isInstanceOf(arg: unknown, type: unknown): boolean {
26+
if (!isStatusObject(arg)) {
27+
return false;
28+
}
29+
30+
const bin = arg.metadata.get('grpc-status-details-bin')[0];
31+
32+
const uint8Array =
33+
typeof bin === 'string'
34+
? stringToUint8Array(bin)
35+
: new Uint8Array(bin.buffer, bin.byteOffset, bin.byteLength);
36+
37+
const errors = Status.deserializeBinary(uint8Array)
38+
.getDetailsList()
39+
.map((details) => {
40+
const typeUrl = details.getTypeUrl();
41+
const ErrorType = protoErrorsMap.get(typeUrl);
42+
return ErrorType?.deserializeBinary(details.getValue_asU8());
43+
});
44+
45+
return !!errors.find((error) => {
46+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
47+
return error && error instanceof <any>type;
48+
});
49+
}
50+
51+
function isStatusObject(arg: unknown): arg is StatusObject {
1252
if (typeof arg === 'object') {
1353
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1454
const any = arg as any;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.