Skip to content
Merged
6,067 changes: 2,742 additions & 3,325 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"@toruslabs/eslint-config-typescript": "^4.1.4",
"@toruslabs/torus-scripts": "^7.1.6",
"@types/color": "^4.2.0",
"@types/deep-freeze-strict": "^1.1.2",
"@types/elliptic": "^6.4.18",
"@types/end-of-stream": "^1.4.4",
"@types/json-stable-stringify": "^1.2.0",
Expand Down Expand Up @@ -129,11 +130,13 @@
"base64url": "^3.0.1",
"bip39": "^3.1.0",
"bn.js": "^5.2.2",
"deep-freeze-strict": "^1.1.1",
"deepmerge": "^4.3.1",
"enc-utils": "^3.0.0",
"end-of-stream": "^1.4.5",
"events": "^3.3.0",
"json-stable-stringify": "^1.3.0",
"klona": "^2.0.6",
"loglevel": "^1.9.2",
"once": "^1.4.0",
"pump": "^3.0.3",
Expand Down
13 changes: 7 additions & 6 deletions src/jrpc/errors/error-classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,14 @@
};

if (this.data !== undefined) {
// `this.data` is not guaranteed to be a plain object, but this simplifies
// the type guard below. We can safely cast it because we know it's a
// JSON-serializable value.
serialized.data = this.data as { [key: string]: Json };

if (isPlainObject(this.data)) {
serialized.data.cause = serializeCause((this.data as { cause?: unknown }).cause);
// Spread to avoid mutating `this.data` when setting `cause`.
serialized.data = {
...(this.data as { [key: string]: Json }),
cause: serializeCause((this.data as { cause?: unknown }).cause),
};
} else {
serialized.data = this.data as { [key: string]: Json };
}
}

Expand All @@ -112,7 +113,7 @@

/**
* Error subclass implementing Ethereum Provider errors per EIP-1193.
* Permits integer error codes in the [ 1000 <= 4999 ] range.

Check warning on line 116 in src/jrpc/errors/error-classes.ts

View workflow job for this annotation

GitHub Actions / test (22.x, ubuntu-latest)

tsdoc-malformed-html-name: Invalid HTML element: Expecting an HTML name
*/
export class EthereumProviderError<Data extends OptionalDataWithOptionalCause> extends JsonRpcError<Data> {
/**
Expand Down
5 changes: 5 additions & 0 deletions src/jrpc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ export { PostMessageStream } from "./postMessageStream";
export { SafeEventEmitter } from "./safeEventEmitter";
export { SerializableError } from "./serializableError";
export { Substream } from "./substream";

/**
* Export the v2 module.
*/
export * from "./v2";
1 change: 1 addition & 0 deletions src/jrpc/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface JRPCNotification<Params extends JRPCParams = JRPCParams> {
}

export interface JRPCRequest<Params extends JRPCParams = JRPCParams> extends JRPCBase {
id: JRPCId;
method: string;
params?: Params;
}
Expand Down
85 changes: 85 additions & 0 deletions src/jrpc/v2/MiddlewareContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { entriesFromKeyValues, isInstance, isIterable } from "../../utils/jrpc";

const MiddlewareContextSymbol = Symbol.for("json-rpc-engine#MiddlewareContext");

/**
* A context object for middleware that attempts to protect against accidental
* modifications. Its interface is frozen.
*
* Map keys may not be directly overridden with {@link set}. Instead, use
* {@link delete} to remove a key and then {@link set} to add a new value.
*
* The override protections are circumvented when using e.g. `Reflect.set`, so
* don't do that.
*
* @template KeyValues - The type of the keys and values in the context.

Check warning on line 15 in src/jrpc/v2/MiddlewareContext.ts

View workflow job for this annotation

GitHub Actions / test (22.x, ubuntu-latest)

tsdoc-undefined-tag: The TSDoc tag "@template" is not defined in this configuration
* @example
* // By default, the context permits any PropertyKey as a key.
* const context = new MiddlewareContext();
* context.set('foo', 'bar');
* context.get('foo'); // 'bar'
* context.get('fizz'); // undefined
* @example
* // By specifying an object type, the context permits only the keys of the object.
* type Context = MiddlewareContext<{ foo: string }>;

Check warning on line 24 in src/jrpc/v2/MiddlewareContext.ts

View workflow job for this annotation

GitHub Actions / test (22.x, ubuntu-latest)

tsdoc-escape-greater-than: The ">" character should be escaped using a backslash to avoid confusion with an HTML tag

Check warning on line 24 in src/jrpc/v2/MiddlewareContext.ts

View workflow job for this annotation

GitHub Actions / test (22.x, ubuntu-latest)

tsdoc-escape-right-brace: The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag

Check warning on line 24 in src/jrpc/v2/MiddlewareContext.ts

View workflow job for this annotation

GitHub Actions / test (22.x, ubuntu-latest)

tsdoc-malformed-inline-tag: Expecting a TSDoc tag starting with "{@"

Check warning on line 24 in src/jrpc/v2/MiddlewareContext.ts

View workflow job for this annotation

GitHub Actions / test (22.x, ubuntu-latest)

tsdoc-malformed-html-name: Invalid HTML element: Expecting an HTML name
* const context = new Context([['foo', 'bar']]);
* context.get('foo'); // 'bar'
* context.get('fizz'); // Type error
*/
export class MiddlewareContext<KeyValues extends Record<PropertyKey, unknown> = Record<PropertyKey, unknown>> extends Map<
keyof KeyValues,
KeyValues[keyof KeyValues]
> {
// @ts-expect-error - TS6133: read via Symbol key in isInstance()
private readonly [MiddlewareContextSymbol] = true;

constructor(entries?: Iterable<readonly [keyof KeyValues, KeyValues[keyof KeyValues]]> | KeyValues) {
super(entries && isIterable(entries) ? entries : entriesFromKeyValues(entries ?? {}));
Object.freeze(this);
}

/**
* Check if a value is a {@link MiddlewareContext} instance.
* Works across different package versions in the same realm.
*
* @param value - The value to check.
* @returns Whether the value is a {@link MiddlewareContext} instance.
*/
static isInstance(value: unknown): value is MiddlewareContext {
return isInstance(value, MiddlewareContextSymbol);
}

get<Key extends keyof KeyValues>(key: Key): KeyValues[Key] | undefined {
return super.get(key) as KeyValues[Key] | undefined;
}

/**
* Get a value from the context. Throws if the key is not found.
*
* @param key - The key to get the value for.
* @returns The value.
*/
assertGet<Key extends keyof KeyValues>(key: Key): KeyValues[Key] {
if (!super.has(key)) {
throw new Error(`Context key "${String(key)}" not found`);
}
return super.get(key) as KeyValues[Key];
}

/**
* Set a value in the context. Throws if the key already exists.
* {@link delete} an existing key before setting it to a new value.
*
* @throws If the key already exists.
* @param key - The key to set the value for.
* @param value - The value to set.
* @returns The context.
*/
set<Key extends keyof KeyValues>(key: Key, value: KeyValues[Key]): this {
if (super.has(key)) {
throw new Error(`MiddlewareContext key "${String(key)}" already exists`);
}
super.set(key, value);
return this;
}
}
Loading
Loading