Skip to content

Commit

Permalink
Cast JsonRPC to Json (#51)
Browse files Browse the repository at this point in the history
* Cast JsonRPC to Json

JsonRpcStruct params was type Record<string, unknown> | unknown[], but
in other parts of the code we use Json to denote such structures.
unknown is not castable to Json because of undefined and classes.
This commit solves the compatibillity issue with other parts of the code

* PR review changes

* Nicer JSON validation msg

* Fix lint
  • Loading branch information
ritave authored Nov 7, 2022
1 parent 5cdc1e9 commit c10dd08
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 8 deletions.
21 changes: 17 additions & 4 deletions src/json.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as superstructModule from 'superstruct';
import { validate } from 'superstruct';
import {
ARRAY_OF_DIFFRENT_KINDS_OF_NUMBERS,
COMPLEX_OBJECT,
Expand All @@ -13,26 +14,38 @@ import {
NON_SERIALIZABLE_NESTED_OBJECT,
} from './__fixtures__';
import {
assert,
assertIsJsonRpcError,
assertIsJsonRpcFailure,
assertIsJsonRpcNotification,
assertIsJsonRpcRequest,
assertIsJsonRpcResponse,
assertIsJsonRpcSuccess,
assertIsPendingJsonRpcResponse,
getJsonRpcIdValidator,
isJsonRpcError,
isJsonRpcFailure,
isJsonRpcNotification,
isJsonRpcRequest,
isJsonRpcResponse,
isJsonRpcSuccess,
isPendingJsonRpcResponse,
isValidJson,
JsonStruct,
validateJsonAndGetSize,
isJsonRpcError,
assertIsJsonRpcError,
} from '.';

describe('json', () => {
describe('JsonStruct', () => {
it('returns error message', () => {
const [error] = validate(undefined, JsonStruct);
assert(error !== undefined);
expect(error.message).toStrictEqual(
'Expected a valid JSON-serializable value',
);
});
});

// TODO: Make this test suite exhaustive.
// The current implementation is guaranteed to be correct, but in the future
// we may opt for a bespoke implementation that is more performant, but may
Expand Down Expand Up @@ -425,11 +438,11 @@ describe('json', () => {
};

const validateAll = (
validate: ReturnType<typeof getJsonRpcIdValidator>,
validator: ReturnType<typeof getJsonRpcIdValidator>,
inputs: ReturnType<typeof getInputs>,
) => {
for (const input of Object.values(inputs)) {
expect(validate(input.value)).toStrictEqual(input.expected);
expect(validator(input.value)).toStrictEqual(input.expected);
}
};

Expand Down
13 changes: 9 additions & 4 deletions src/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,26 @@ import {
object,
omit,
optional,
record,
string,
Struct,
union,
unknown,
} from 'superstruct';
import { AssertionErrorConstructor, assertStruct } from './assert';
import {
calculateNumberSize,
calculateStringSize,
isPlainObject,
JsonSize,
} from './misc';
import { AssertionErrorConstructor, assertStruct } from './assert';

export const JsonStruct = define<Json>('Json', (value) => {
const [isValid] = validateJsonAndGetSize(value, true);
return isValid;
if (!isValid) {
return 'Expected a valid JSON-serializable value';
}
return true;
});

/**
Expand Down Expand Up @@ -99,8 +103,9 @@ export type JsonRpcError = OptionalField<
'data'
>;

export const JsonRpcParamsStruct = optional(union([object(), array()]));

export const JsonRpcParamsStruct = optional(
union([record(string(), JsonStruct), array(JsonStruct)]),
);
export type JsonRpcParams = Infer<typeof JsonRpcParamsStruct>;

export const JsonRpcRequestStruct = object({
Expand Down

0 comments on commit c10dd08

Please sign in to comment.