Skip to content

Commit

Permalink
feat(common): add isGrpcStatusObjectWithCode user-defined type guard
Browse files Browse the repository at this point in the history
1. User-defined Typescript type-guard function that asserts whether a value or
object is a `@grpc/grpc-js` {Partial<StatusObject>} or not.
The reason why it checks for {Partial} is because all of the properties of
the {StatusObject} are defined as optional for some reason, hence we cannot
assume anything about those being present or not by default.
2. Therefore this method will just check if the `code` property is set or not
and return `true` or `false` based on that.
3. The above is also the reason why the name of the function is slightly more
verbose than your average user-defined type-guard that could be named just
"isGrpcStatusObject()" but we wanted to make sure that more specific type-guards
can be added later that check for other optional properities or for the
presence of all of them together.

Link to the status builder within grpc-js:
https://github.com/grpc/grpc-node/blob/master/packages/grpc-js/src/status-builder.ts

Signed-off-by: Peter Somogyvari <[email protected]>
  • Loading branch information
petermetz committed Mar 19, 2024
1 parent 154ea7d commit ed46f02
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/cactus-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"sha3": "2.1.4"
},
"devDependencies": {
"@grpc/grpc-js": "1.10.3",
"@types/json-stable-stringify": "1.0.33",
"@types/sanitize-html": "2.9.5",
"@types/secp256k1": "4.0.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { StatusObject } from "@grpc/grpc-js";

/**
* User-defined Typescript type-guard function that asserts whether a value or
* object is a `@grpc/grpc-js` {Partial<StatusObject>} or not.
*
* The reason why it checks for {Partial} is because all of the properties of
* the {StatusObject} are defined as optional for some reason, hence we cannot
* assume anything about those being present or not by default.
* Therefore this method will just check if the `code` property is set or not
* and return `true` or `false` based on that.
*
* The above is also the reason why the name of the function is slightly more
* verbose than your average user-defined type-guard that could be named just
* "isGrpcStatusObject()" but we wanted to make sure that more specific type-guards
* can be added later that check for other optional properities or for the
* presence of all of them together.
*
* @param x Literally any value or object that will be checked at runtime to have
* the `code` property defined as a number.
* @returns `true` if `x` qualifies, `false` otherwise.
*
* @see {StatusObject} of the @grpc/grpc-js library.
*/
export function isGrpcStatusObjectWithCode(
x: unknown,
): x is Partial<StatusObject> {
return (
!!x &&
typeof (x as StatusObject).code === "number" &&
isFinite((x as StatusObject).code)
);
}
2 changes: 2 additions & 0 deletions packages/cactus-common/src/main/typescript/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ export {
ExpressHttpVerbMethodName,
isExpressHttpVerbMethodName,
} from "./http/express-http-verb-method-name";

export { isGrpcStatusObjectWithCode } from "./grpc/is-grpc-status-object-with-code";
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import "jest-extended";
import { isGrpcStatusObjectWithCode } from "../../../../main/typescript";

describe("isGrpcStatusObjectWithCode()", () => {
test("returns true for POJO with correct shape and valid data", () => {
expect(isGrpcStatusObjectWithCode({ code: 1 })).toBeTrue();
expect(isGrpcStatusObjectWithCode({ code: 0 })).toBeTrue();
expect(isGrpcStatusObjectWithCode({ code: -1 })).toBeTrue();
});

test("returns false for POJO with correct shape and invalid data", () => {
expect(isGrpcStatusObjectWithCode({ code: NaN })).toBeFalse();
expect(isGrpcStatusObjectWithCode({ code: "" })).toBeFalse();
expect(isGrpcStatusObjectWithCode({ code: "Hello" })).toBeFalse();
expect(isGrpcStatusObjectWithCode({ code: true })).toBeFalse();
expect(isGrpcStatusObjectWithCode({ code: [] })).toBeFalse();

expect(isGrpcStatusObjectWithCode({ codeX: NaN })).toBeFalse();
expect(isGrpcStatusObjectWithCode({ codeY: "" })).toBeFalse();
expect(isGrpcStatusObjectWithCode({ codeZ: "Hello" })).toBeFalse();
expect(isGrpcStatusObjectWithCode({ codeK: 1 })).toBeFalse();
});

test("returns false for non-POJO input", () => {
expect(isGrpcStatusObjectWithCode(NaN)).toBeFalse();
expect(isGrpcStatusObjectWithCode(null)).toBeFalse();
expect(isGrpcStatusObjectWithCode(undefined)).toBeFalse();
expect(isGrpcStatusObjectWithCode([])).toBeFalse();
expect(isGrpcStatusObjectWithCode(Symbol)).toBeFalse();
});
});
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7660,6 +7660,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@hyperledger/cactus-common@workspace:packages/cactus-common"
dependencies:
"@grpc/grpc-js": "npm:1.10.3"
"@types/json-stable-stringify": "npm:1.0.33"
"@types/sanitize-html": "npm:2.9.5"
"@types/secp256k1": "npm:4.0.3"
Expand Down

0 comments on commit ed46f02

Please sign in to comment.