@metamask/utils
Version:
Various JavaScript/TypeScript utilities of wide relevance to the MetaMask codebase
388 lines • 15.3 kB
text/typescript
import { Struct } from "@metamask/superstruct";
import type { Infer, ObjectSchema, Simplify, Optionalize } from "@metamask/superstruct";
import type { AssertionErrorConstructor } from "./assert.mjs";
/**
* Any JSON-compatible value.
*/
export type Json = null | boolean | number | string | Json[] | {
[prop: string]: Json;
};
/**
* A helper type to make properties with `undefined` in their type optional, but
* not `undefined` itself.
*
* @deprecated Use `ObjectType` and/or `ExactOptionalize` from `@metamask/superstruct@>=3.2.0` instead.
* @example
* ```ts
* type Foo = ObjectOptional<{ foo: string | undefined }>;
* // Foo is equivalent to { foo?: string }
* ```
*/
export type ObjectOptional<Schema extends Record<string, unknown>> = {
[Key in keyof Schema as Schema[Key] extends ExactOptionalGuard ? Key : never]?: Schema[Key] extends ExactOptionalGuard & infer Original ? Original : never;
} & {
[Key in keyof Schema as Schema[Key] extends ExactOptionalGuard ? never : Key]: Schema[Key];
};
/**
* An object type with support for exact optionals. This is used by the `object`
* struct. This uses the {@link ObjectOptional} helper to make properties with
* `undefined` in their type optional, but not `undefined` itself.
*
* @deprecated Use `ObjectType` from `@metamask/superstruct@>=3.2.0` instead.
*/
export type ObjectType<Schema extends ObjectSchema> = Simplify<ObjectOptional<Optionalize<{
[Key in keyof Schema]: Infer<Schema[Key]>;
}>>>;
/**
* A struct to check if the given value is a valid object, with support for
* {@link exactOptional} types.
*
* @deprecated Use `exactOptional` and `object` from `@metamask/superstruct@>=3.2.0` instead.
* @param schema - The schema of the object.
* @returns A struct to check if the given value is an object.
*/
export declare const object: <Schema extends ObjectSchema>(schema: Schema) => Struct<Simplify<ObjectOptional<Optionalize<{ [Key in keyof Schema]: Infer<Schema[Key]>; }>>>, unknown>;
declare const exactOptionalSymbol: unique symbol;
type ExactOptionalGuard = {
_exactOptionalGuard?: typeof exactOptionalSymbol;
};
/**
* A struct which allows the property of an object to be absent, or to be present
* as long as it's valid and not set to `undefined`.
*
* This struct should be used in conjunction with the {@link object} from this
* library, to get proper type inference.
*
* @deprecated Use `exactOptional` and `object` from `@metamask/superstruct@>=3.2.0` instead.
* @param struct - The struct to check the value against, if present.
* @returns A struct to check if the given value is valid, or not present.
* @example
* ```ts
* const struct = object({
* foo: exactOptional(string()),
* bar: exactOptional(number()),
* baz: optional(boolean()),
* qux: unknown(),
* });
*
* type Type = Infer<typeof struct>;
* // Type is equivalent to:
* // {
* // foo?: string;
* // bar?: number;
* // baz?: boolean | undefined;
* // qux: unknown;
* // }
* ```
*/
export declare function exactOptional<Type, Schema>(struct: Struct<Type, Schema>): Struct<Type & ExactOptionalGuard, Schema>;
/**
* A struct to check if the given value is a valid JSON-serializable value.
*
* Note that this struct is unsafe. For safe validation, use {@link JsonStruct}.
*/
export declare const UnsafeJsonStruct: Struct<Json>;
/**
* A struct to check if the given value is a valid JSON-serializable value.
*
* This struct sanitizes the value before validating it, so that it is safe to
* use with untrusted input.
*/
export declare const JsonStruct: Struct<Json, unknown>;
/**
* Check if the given value is a valid {@link Json} value, i.e., a value that is
* serializable to JSON.
*
* @param value - The value to check.
* @returns Whether the value is a valid {@link Json} value.
*/
export declare function isValidJson(value: unknown): value is Json;
/**
* Validate and return sanitized JSON.
*
* Note:
* This function uses sanitized JsonStruct for validation
* that applies stringify and then parse of a value provided
* to ensure that there are no getters which can have side effects
* that can cause security issues.
*
* @param value - JSON structure to be processed.
* @returns Sanitized JSON structure.
*/
export declare function getSafeJson<Type extends Json = Json>(value: unknown): Type;
/**
* Get the size of a JSON value in bytes. This also validates the value.
*
* @param value - The JSON value to get the size of.
* @returns The size of the JSON value in bytes.
*/
export declare function getJsonSize(value: unknown): number;
/**
* The string '2.0'.
*/
export declare const jsonrpc2: "2.0";
export declare const JsonRpcVersionStruct: Struct<"2.0", "2.0">;
/**
* A String specifying the version of the JSON-RPC protocol.
* MUST be exactly "2.0".
*/
export type JsonRpcVersion2 = typeof jsonrpc2;
export declare const JsonRpcIdStruct: Struct<string | number | null, null>;
/**
* An identifier established by the Client that MUST contain a String, Number,
* or NULL value if included. If it is not included it is assumed to be a
* notification. The value SHOULD normally not be Null and Numbers SHOULD
* NOT contain fractional parts.
*/
export type JsonRpcId = Infer<typeof JsonRpcIdStruct>;
export declare const JsonRpcErrorStruct: Struct<{
data?: Json & ExactOptionalGuard;
stack?: string;
code: number;
message: string;
}, unknown>;
/**
* Mark a certain key of a type as optional.
*/
export type OptionalField<Type extends Record<string, unknown>, Key extends keyof Type> = Omit<Type, Key> & Partial<Pick<Type, Key>>;
/**
* A JSON-RPC error object.
*
* Note that TypeScript infers `unknown | undefined` as `unknown`, meaning that
* the `data` field is not optional. To make it optional, we use the
* `OptionalField` helper, to explicitly make it optional.
*/
export type JsonRpcError = OptionalField<Infer<typeof JsonRpcErrorStruct>, 'data'>;
export declare const JsonRpcParamsStruct: Struct<Json[] | Record<string, Json>, null>;
export type JsonRpcParams = Json[] | Record<string, Json>;
export declare const JsonRpcRequestStruct: Struct<{
params?: (Json[] | Record<string, Json>) & ExactOptionalGuard;
id: string | number | null;
method: string;
jsonrpc: "2.0";
}, unknown>;
export type InferWithParams<Type extends Struct<any>, Params extends JsonRpcParams> = Infer<Type> & {
params?: Params;
};
/**
* A JSON-RPC request object.
*/
export type JsonRpcRequest<Params extends JsonRpcParams = JsonRpcParams> = InferWithParams<typeof JsonRpcRequestStruct, Params>;
export declare const JsonRpcNotificationStruct: Struct<{
params?: (Json[] | Record<string, Json>) & ExactOptionalGuard;
method: string;
jsonrpc: "2.0";
}, unknown>;
/**
* A JSON-RPC notification object.
*/
export type JsonRpcNotification<Params extends JsonRpcParams = JsonRpcParams> = InferWithParams<typeof JsonRpcNotificationStruct, Params>;
/**
* Check if the given value is a valid {@link JsonRpcNotification} object.
*
* @param value - The value to check.
* @returns Whether the given value is a valid {@link JsonRpcNotification}
* object.
*/
export declare function isJsonRpcNotification(value: unknown): value is JsonRpcNotification;
/**
* Assert that the given value is a valid {@link JsonRpcNotification} object.
*
* @param value - The value to check.
* @param ErrorWrapper - The error class to throw if the assertion fails.
* Defaults to {@link AssertionError}.
* @throws If the given value is not a valid {@link JsonRpcNotification} object.
*/
export declare function assertIsJsonRpcNotification(value: unknown, ErrorWrapper?: AssertionErrorConstructor): asserts value is JsonRpcNotification;
/**
* Check if the given value is a valid {@link JsonRpcRequest} object.
*
* @param value - The value to check.
* @returns Whether the given value is a valid {@link JsonRpcRequest} object.
*/
export declare function isJsonRpcRequest(value: unknown): value is JsonRpcRequest;
/**
* Assert that the given value is a valid {@link JsonRpcRequest} object.
*
* @param value - The JSON-RPC request or notification to check.
* @param ErrorWrapper - The error class to throw if the assertion fails.
* Defaults to {@link AssertionError}.
* @throws If the given value is not a valid {@link JsonRpcRequest} object.
*/
export declare function assertIsJsonRpcRequest(value: unknown, ErrorWrapper?: AssertionErrorConstructor): asserts value is JsonRpcRequest;
export declare const PendingJsonRpcResponseStruct: Struct<{
id: string | number | null;
jsonrpc: "2.0";
result: unknown;
error?: {
data?: Json & ExactOptionalGuard;
stack?: string;
code: number;
message: string;
} | undefined;
}, {
id: Struct<string | number | null, null>;
jsonrpc: Struct<"2.0", "2.0">;
result: Struct<unknown, null>;
error: Struct<{
data?: Json & ExactOptionalGuard;
stack?: string;
code: number;
message: string;
} | undefined, unknown>;
}>;
/**
* A JSON-RPC response object that has not yet been resolved.
*/
export type PendingJsonRpcResponse<Result extends Json = Json> = Omit<Infer<typeof PendingJsonRpcResponseStruct>, 'result'> & {
result?: Result;
};
export declare const JsonRpcSuccessStruct: Struct<{
id: string | number | null;
jsonrpc: "2.0";
result: Json;
}, unknown>;
/**
* A successful JSON-RPC response object.
*/
export type JsonRpcSuccess<Result extends Json = Json> = Omit<Infer<typeof JsonRpcSuccessStruct>, 'result'> & {
result: Result;
};
export declare const JsonRpcFailureStruct: Struct<{
error: JsonRpcError;
id: string | number | null;
jsonrpc: "2.0";
}, unknown>;
/**
* A failed JSON-RPC response object.
*/
export type JsonRpcFailure = Infer<typeof JsonRpcFailureStruct>;
export declare const JsonRpcResponseStruct: Struct<{
id: string | number | null;
jsonrpc: "2.0";
result: Json;
} | {
error: JsonRpcError;
id: string | number | null;
jsonrpc: "2.0";
}, null>;
/**
* A JSON-RPC response object. Must be checked to determine whether it's a
* success or failure.
*
* @template Result - The type of the result.
*/
export type JsonRpcResponse<Result extends Json = Json> = JsonRpcSuccess<Result> | JsonRpcFailure;
/**
* Type guard to check whether specified JSON-RPC response is a
* {@link PendingJsonRpcResponse}.
*
* @param response - The JSON-RPC response to check.
* @returns Whether the specified JSON-RPC response is pending.
*/
export declare function isPendingJsonRpcResponse(response: unknown): response is PendingJsonRpcResponse;
/**
* Assert that the given value is a valid {@link PendingJsonRpcResponse} object.
*
* @param response - The JSON-RPC response to check.
* @param ErrorWrapper - The error class to throw if the assertion fails.
* Defaults to {@link AssertionError}.
* @throws If the given value is not a valid {@link PendingJsonRpcResponse}
* object.
*/
export declare function assertIsPendingJsonRpcResponse(response: unknown, ErrorWrapper?: AssertionErrorConstructor): asserts response is PendingJsonRpcResponse;
/**
* Type guard to check if a value is a {@link JsonRpcResponse}.
*
* @param response - The object to check.
* @returns Whether the object is a JsonRpcResponse.
*/
export declare function isJsonRpcResponse(response: unknown): response is JsonRpcResponse;
/**
* Assert that the given value is a valid {@link JsonRpcResponse} object.
*
* @param value - The value to check.
* @param ErrorWrapper - The error class to throw if the assertion fails.
* Defaults to {@link AssertionError}.
* @throws If the given value is not a valid {@link JsonRpcResponse} object.
*/
export declare function assertIsJsonRpcResponse(value: unknown, ErrorWrapper?: AssertionErrorConstructor): asserts value is JsonRpcResponse;
/**
* Check if the given value is a valid {@link JsonRpcSuccess} object.
*
* @param value - The value to check.
* @returns Whether the given value is a valid {@link JsonRpcSuccess} object.
*/
export declare function isJsonRpcSuccess(value: unknown): value is JsonRpcSuccess;
/**
* Assert that the given value is a valid {@link JsonRpcSuccess} object.
*
* @param value - The value to check.
* @param ErrorWrapper - The error class to throw if the assertion fails.
* Defaults to {@link AssertionError}.
* @throws If the given value is not a valid {@link JsonRpcSuccess} object.
*/
export declare function assertIsJsonRpcSuccess(value: unknown, ErrorWrapper?: AssertionErrorConstructor): asserts value is JsonRpcSuccess;
/**
* Check if the given value is a valid {@link JsonRpcFailure} object.
*
* @param value - The value to check.
* @returns Whether the given value is a valid {@link JsonRpcFailure} object.
*/
export declare function isJsonRpcFailure(value: unknown): value is JsonRpcFailure;
/**
* Assert that the given value is a valid {@link JsonRpcFailure} object.
*
* @param value - The value to check.
* @param ErrorWrapper - The error class to throw if the assertion fails.
* Defaults to {@link AssertionError}.
* @throws If the given value is not a valid {@link JsonRpcFailure} object.
*/
export declare function assertIsJsonRpcFailure(value: unknown, ErrorWrapper?: AssertionErrorConstructor): asserts value is JsonRpcFailure;
/**
* Check if the given value is a valid {@link JsonRpcError} object.
*
* @param value - The value to check.
* @returns Whether the given value is a valid {@link JsonRpcError} object.
*/
export declare function isJsonRpcError(value: unknown): value is JsonRpcError;
/**
* Assert that the given value is a valid {@link JsonRpcError} object.
*
* @param value - The value to check.
* @param ErrorWrapper - The error class to throw if the assertion fails.
* Defaults to {@link AssertionError}.
* @throws If the given value is not a valid {@link JsonRpcError} object.
*/
export declare function assertIsJsonRpcError(value: unknown, ErrorWrapper?: AssertionErrorConstructor): asserts value is JsonRpcError;
type JsonRpcValidatorOptions = {
permitEmptyString?: boolean;
permitFractions?: boolean;
permitNull?: boolean;
};
/**
* Gets a function for validating JSON-RPC request / response `id` values.
*
* By manipulating the options of this factory, you can control the behavior
* of the resulting validator for some edge cases. This is useful because e.g.
* `null` should sometimes but not always be permitted.
*
* Note that the empty string (`''`) is always permitted by the JSON-RPC
* specification, but that kind of sucks and you may want to forbid it in some
* instances anyway.
*
* For more details, see the
* [JSON-RPC Specification](https://www.jsonrpc.org/specification).
*
* @param options - An options object.
* @param options.permitEmptyString - Whether the empty string (i.e. `''`)
* should be treated as a valid ID. Default: `true`
* @param options.permitFractions - Whether fractional numbers (e.g. `1.2`)
* should be treated as valid IDs. Default: `false`
* @param options.permitNull - Whether `null` should be treated as a valid ID.
* Default: `true`
* @returns The JSON-RPC ID validator function.
*/
export declare function getJsonRpcIdValidator(options?: JsonRpcValidatorOptions): (id: unknown) => id is string | number | null;
export {};
//# sourceMappingURL=json.d.mts.map