All files / kernel-utils/src types.ts

100% Statements 27/27
100% Branches 8/8
100% Functions 12/12
100% Lines 19/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109                                                      158x                   158x 17x   158x       15x   158x   17x   6x                                     158x           158x         158x 147x             158x           1942x 147x               158x   158x 48x 37x  
import type { Primitive } from '@endo/captp';
import type { PromiseKit } from '@endo/promise-kit';
import type { Infer, Struct } from '@metamask/superstruct';
import { array, empty, is, object, string, union } from '@metamask/superstruct';
import {
  isObject,
  UnsafeJsonStruct,
  JsonRpcRequestStruct,
  JsonRpcResponseStruct,
  JsonRpcNotificationStruct,
} from '@metamask/utils';
import type {
  JsonRpcNotification,
  JsonRpcRequest,
  JsonRpcResponse,
} from '@metamask/utils';
 
export type TypeGuard<Type> = (value: unknown) => value is Type;
 
export type ExtractGuardType<Guard, Bound = unknown> = Guard extends (
  value: unknown,
) => value is infer Type
  ? Type extends Bound
    ? Type
    : never
  : never;
 
const primitives = new Set([
  'string',
  'number',
  'bigint',
  'boolean',
  'symbol',
  'null',
  'undefined',
]);
 
export const isPrimitive = (value: unknown): value is Primitive =>
  value === null || primitives.has(typeof value);
 
export const isTypedArray = <ElementType>(
  value: unknown,
  isElement: TypeGuard<ElementType>,
): value is ElementType[] =>
  Array.isArray(value) && !value.some((ele) => !isElement(ele));
 
export const isTypedObject = <ValueType>(
  value: unknown,
  isValue: TypeGuard<ValueType>,
): value is { [Key in keyof object]: ValueType } =>
  isObject(value) && !Object.values(value).some((val) => !isValue(val));
 
export type PromiseCallbacks<Resolve = unknown> = Omit<
  PromiseKit<Resolve>,
  'promise'
>;
 
/**
 * Utility type that wraps all method return types in Promise.
 * Methods already returning Promise<T> remain Promise<T>.
 */
export type Promisified<T> = {
  [K in keyof T]: T[K] extends (...args: infer A) => Promise<infer R>
    ? (...args: A) => Promise<R>
    : T[K] extends (...args: infer A) => infer R
      ? (...args: A) => Promise<R>
      : T[K];
};
 
export const EmptyJsonArray = empty(array(UnsafeJsonStruct));
 
export type EmptyJsonArray = Infer<typeof EmptyJsonArray>;
 
export type JsonRpcCall = JsonRpcRequest | JsonRpcNotification;
 
export const JsonRpcCallStruct: Struct<JsonRpcCall> = union([
  JsonRpcRequestStruct,
  JsonRpcNotificationStruct,
]);
 
export const isJsonRpcCall = (value: unknown): value is JsonRpcCall =>
  is(value, JsonRpcCallStruct);
 
export type JsonRpcMessage =
  | JsonRpcNotification
  | JsonRpcRequest
  | JsonRpcResponse;
 
export const JsonRpcMessageStruct: Struct<JsonRpcMessage> = union([
  JsonRpcNotificationStruct,
  JsonRpcRequestStruct,
  JsonRpcResponseStruct,
]);
 
export const isJsonRpcMessage = (value: unknown): value is JsonRpcMessage =>
  is(value, JsonRpcMessageStruct);
 
/**
 * Check whether a value has the shape of Endo CapData (`{ body: string, slots: string[] }`).
 *
 * @param value - The value to check.
 * @returns `true` when `value` looks like CapData.
 */
export const CapDataStruct = object({ body: string(), slots: array(string()) });
 
export const isCapData = (
  value: unknown,
): value is { body: string; slots: string[] } => is(value, CapDataStruct);