{"version":3,"file":"structs.cjs","sourceRoot":"","sources":["../src/structs.ts"],"names":[],"mappings":"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","sourcesContent":["import { union } from '@metamask/snaps-sdk';\nimport type {\n  AnyStruct,\n  Assign,\n  Failure,\n  ObjectSchema,\n  ObjectType,\n} from '@metamask/superstruct';\nimport {\n  assign,\n  is,\n  validate,\n  type as superstructType,\n  Struct,\n  StructError,\n  create,\n} from '@metamask/superstruct';\nimport type { NonEmptyArray } from '@metamask/utils';\nimport { assert, isObject } from '@metamask/utils';\nimport { bold, green, red } from 'chalk';\n\nimport { indent } from './strings';\n\n/**\n * Infer a struct type, only if it matches the specified type. This is useful\n * for defining types and structs that are related to each other in separate\n * files.\n *\n * @example\n * ```typescript\n * // In file A\n * export type GetFileArgs = {\n *   path: string;\n *   encoding?: EnumToUnion<AuxiliaryFileEncoding>;\n * };\n *\n * // In file B\n * export const GetFileArgsStruct = object(...);\n *\n * // If the type and struct are in the same file, this will return the type.\n * // Otherwise, it will return `never`.\n * export type GetFileArgs =\n *   InferMatching<typeof GetFileArgsStruct, GetFileArgs>;\n * ```\n */\nexport type InferMatching<\n  StructType extends Struct<any, any>,\n  Type,\n> = StructType['TYPE'] extends Type ? Type : never;\n\n/**\n * Colorize a value with a color function. This is useful for colorizing values\n * in error messages. If colorization is disabled, the original value is\n * returned.\n *\n * @param value - The value to colorize.\n * @param colorFunction - The color function to use.\n * @param enabled - Whether to colorize the value.\n * @returns The colorized value, or the original value if colorization is\n * disabled.\n */\nfunction color(\n  value: string,\n  colorFunction: (value: string) => string,\n  enabled: boolean,\n) {\n  if (enabled) {\n    return colorFunction(value);\n  }\n\n  return value;\n}\n\n/**\n * Define a struct, and also define the name of the struct as the given name.\n *\n * This is useful for improving the error messages returned by `superstruct`.\n *\n * @param name - The name of the struct.\n * @param struct - The struct.\n * @returns The struct.\n */\nexport function named<Type, Schema>(\n  name: string,\n  struct: Struct<Type, Schema>,\n) {\n  return new Struct({\n    ...struct,\n    type: name,\n  });\n}\n\nexport class SnapsStructError<Type, Schema> extends StructError {\n  constructor(\n    struct: Struct<Type, Schema>,\n    prefix: string,\n    suffix: string,\n    failure: StructError,\n    failures: () => Generator<Failure>,\n    colorize = true,\n  ) {\n    super(failure, failures);\n\n    this.name = 'SnapsStructError';\n    this.message = `${prefix}.\\n\\n${getStructErrorMessage(\n      struct,\n      [...failures()],\n      colorize,\n    )}${suffix ? `\\n\\n${suffix}` : ''}`;\n  }\n}\n\ntype GetErrorOptions<Type, Schema> = {\n  struct: Struct<Type, Schema>;\n  prefix: string;\n  suffix?: string;\n  error: StructError;\n  colorize?: boolean;\n};\n\n/**\n * Converts an array to a generator function that yields the items in the\n * array.\n *\n * @param array - The array.\n * @returns A generator function.\n * @yields The items in the array.\n */\nexport function* arrayToGenerator<Type>(\n  array: Type[],\n): Generator<Type, void, undefined> {\n  for (const item of array) {\n    yield item;\n  }\n}\n\n/**\n * Returns a `SnapsStructError` with the given prefix and suffix.\n *\n * @param options - The options.\n * @param options.struct - The struct that caused the error.\n * @param options.prefix - The prefix to add to the error message.\n * @param options.suffix - The suffix to add to the error message. Defaults to\n * an empty string.\n * @param options.error - The `superstruct` error to wrap.\n * @param options.colorize - Whether to colorize the value. Defaults to `true`.\n * @returns The `SnapsStructError`.\n */\nexport function getError<Type, Schema>({\n  struct,\n  prefix,\n  suffix = '',\n  error,\n  colorize,\n}: GetErrorOptions<Type, Schema>) {\n  return new SnapsStructError(\n    struct,\n    prefix,\n    suffix,\n    error,\n    () => arrayToGenerator(error.failures()),\n    colorize,\n  );\n}\n\n/**\n * A wrapper of `superstruct`'s `create` function that throws a\n * `SnapsStructError` instead of a `StructError`. This is useful for improving\n * the error messages returned by `superstruct`.\n *\n * @param value - The value to validate.\n * @param struct - The `superstruct` struct to validate the value against.\n * @param prefix - The prefix to add to the error message.\n * @param suffix - The suffix to add to the error message. Defaults to an empty\n * string.\n * @returns The validated value.\n */\nexport function createFromStruct<Type, Schema>(\n  value: unknown,\n  struct: Struct<Type, Schema>,\n  prefix: string,\n  suffix = '',\n) {\n  try {\n    return create(value, struct);\n  } catch (error) {\n    if (error instanceof StructError) {\n      throw getError({ struct, prefix, suffix, error });\n    }\n\n    throw error;\n  }\n}\n\n/**\n * Get a struct from a failure path.\n *\n * @param struct - The struct.\n * @param path - The failure path.\n * @returns The struct at the failure path.\n */\nexport function getStructFromPath<Type, Schema>(\n  struct: Struct<Type, Schema>,\n  path: string[],\n) {\n  return path.reduce<AnyStruct>((result, key) => {\n    if (isObject(struct.schema) && struct.schema[key]) {\n      return struct.schema[key] as AnyStruct;\n    }\n\n    return result;\n  }, struct);\n}\n\n/**\n * Get the union struct names from a struct.\n *\n * @param struct - The struct.\n * @param colorize - Whether to colorize the value. Defaults to `true`.\n * @returns The union struct names, or `null` if the struct is not a union\n * struct.\n */\nexport function getUnionStructNames<Type, Schema>(\n  struct: Struct<Type, Schema>,\n  colorize = true,\n) {\n  if (Array.isArray(struct.schema)) {\n    return struct.schema.map(({ type }) => color(type, green, colorize));\n  }\n\n  return null;\n}\n\n/**\n * Get an error prefix from a `superstruct` failure. This is useful for\n * formatting the error message returned by `superstruct`.\n *\n * @param failure - The `superstruct` failure.\n * @param colorize - Whether to colorize the value. Defaults to `true`.\n * @returns The error prefix.\n */\nexport function getStructErrorPrefix(failure: Failure, colorize = true) {\n  if (failure.type === 'never' || failure.path.length === 0) {\n    return '';\n  }\n\n  return `At path: ${color(failure.path.join('.'), bold, colorize)} — `;\n}\n\n/**\n * Get a string describing the failure. This is similar to the `message`\n * property of `superstruct`'s `Failure` type, but formats the value in a more\n * readable way.\n *\n * @param struct - The struct that caused the failure.\n * @param failure - The `superstruct` failure.\n * @param colorize - Whether to colorize the value. Defaults to `true`.\n * @returns A string describing the failure.\n */\nexport function getStructFailureMessage<Type, Schema>(\n  struct: Struct<Type, Schema>,\n  failure: Failure,\n  colorize = true,\n) {\n  const received = color(JSON.stringify(failure.value), red, colorize);\n  const prefix = getStructErrorPrefix(failure, colorize);\n\n  if (failure.type === 'union') {\n    const childStruct = getStructFromPath(struct, failure.path);\n    const unionNames = getUnionStructNames(childStruct, colorize);\n\n    if (unionNames) {\n      return `${prefix}Expected the value to be one of: ${unionNames.join(\n        ', ',\n      )}, but received: ${received}.`;\n    }\n\n    return `${prefix}${failure.message}.`;\n  }\n\n  if (failure.type === 'literal') {\n    // Superstruct's failure does not provide information about which literal\n    // value was expected, so we need to parse the message to get the literal.\n    const message = failure.message\n      .replace(\n        /the literal `(.+)`,/u,\n        `the value to be \\`${color('$1', green, colorize)}\\`,`,\n      )\n      .replace(\n        /, but received: (.+)/u,\n        `, but received: ${color('$1', red, colorize)}`,\n      );\n\n    return `${prefix}${message}.`;\n  }\n\n  if (failure.type === 'never') {\n    return `Unknown key: ${color(\n      failure.path.join('.'),\n      bold,\n      colorize,\n    )}, received: ${received}.`;\n  }\n\n  if (failure.refinement === 'size') {\n    const message = failure.message\n      .replace(\n        /length between `(\\d+)` and `(\\d+)`/u,\n        `length between ${color('$1', green, colorize)} and ${color(\n          '$2',\n          green,\n          colorize,\n        )},`,\n      )\n      .replace(/length of `(\\d+)`/u, `length of ${color('$1', red, colorize)}`)\n      .replace(/a array/u, 'an array');\n\n    return `${prefix}${message}.`;\n  }\n\n  // Refinements we built ourselves have nice error messages\n  if (failure.refinement !== undefined) {\n    return `${prefix}${failure.message}.`;\n  }\n\n  return `${prefix}Expected a value of type ${color(\n    failure.type,\n    green,\n    colorize,\n  )}, but received: ${received}.`;\n}\n\n/**\n * Get a string describing the errors. This formats all the errors in a\n * human-readable way.\n *\n * @param struct - The struct that caused the failures.\n * @param failures - The `superstruct` failures.\n * @param colorize - Whether to colorize the value. Defaults to `true`.\n * @returns A string describing the errors.\n */\nexport function getStructErrorMessage<Type, Schema>(\n  struct: Struct<Type, Schema>,\n  failures: Failure[],\n  colorize = true,\n) {\n  const formattedFailures = failures.map((failure) =>\n    indent(`• ${getStructFailureMessage(struct, failure, colorize)}`),\n  );\n\n  return formattedFailures.join('\\n');\n}\n\n/**\n * Validate a union struct, and throw readable errors if the value does not\n * satisfy the struct. This is useful for improving the error messages returned\n * by `superstruct`.\n *\n * @param value - The value to validate.\n * @param struct - The `superstruct` union struct to validate the value against.\n * This struct must be a union of object structs, and must have at least one\n * shared key to validate against.\n * @param structKey - The key to validate against. This key must be present in\n * all the object structs in the union struct, and is expected to be a literal\n * value.\n * @param coerce - Whether to coerce the value to satisfy the struct. Defaults\n * to `false`.\n * @returns The validated value.\n * @throws If the value does not satisfy the struct.\n * @example\n * const struct = union([\n *   object({ type: literal('a'), value: string() }),\n *   object({ type: literal('b'), value: number() }),\n *   object({ type: literal('c'), value: boolean() }),\n *   // ...\n * ]);\n *\n * // At path: type — Expected the value to be one of: \"a\", \"b\", \"c\", but received: \"d\".\n * validateUnion({ type: 'd', value: 'foo' }, struct, 'type');\n *\n * // At path: value — Expected a value of type string, but received: 42.\n * validateUnion({ type: 'a', value: 42 }, struct, 'value');\n */\nexport function validateUnion<Type, Schema extends readonly Struct<any, any>[]>(\n  value: unknown,\n  struct: Struct<Type, Schema>,\n  structKey: keyof Type,\n  coerce = false,\n) {\n  assert(\n    struct.schema,\n    'Expected a struct with a schema. Make sure to use `union` from `@metamask/snaps-sdk`.',\n  );\n  assert(struct.schema.length > 0, 'Expected a non-empty array of structs.');\n\n  const keyUnion = struct.schema.map(\n    (innerStruct) => innerStruct.schema[structKey],\n    // This is guaranteed to be a non-empty array by the assertion above. We\n    // need to cast it since `superstruct` requires a non-empty array of structs\n    // for the `union` struct.\n  ) as NonEmptyArray<Struct>;\n\n  const key = superstructType({\n    [structKey]: union(keyUnion),\n  });\n\n  const [keyError] = validate(value, key, { coerce });\n  if (keyError) {\n    throw new Error(\n      getStructFailureMessage(key, keyError.failures()[0], false),\n    );\n  }\n\n  // At this point it's guaranteed that the value is an object, so we can safely\n  // cast it to a Record.\n  const objectValue = value as Record<PropertyKey, unknown>;\n  const objectStructs = struct.schema.filter((innerStruct) =>\n    is(objectValue[structKey], innerStruct.schema[structKey]),\n  );\n\n  assert(objectStructs.length > 0, 'Expected a struct to match the value.');\n\n  // We need to validate the value against all the object structs that match the\n  // struct key, and return the first validated value.\n  const validationResults = objectStructs.map((objectStruct) =>\n    validate(objectValue, objectStruct, { coerce }),\n  );\n\n  const validatedValue = validationResults.find(([error]) => !error);\n  if (validatedValue) {\n    return validatedValue[1];\n  }\n\n  assert(validationResults[0][0], 'Expected at least one error.');\n\n  // If there is no validated value, we need to find the error with the least\n  // number of failures (with the assumption that it's the most specific error).\n  const validationError = validationResults.reduce((error, [innerError]) => {\n    assert(innerError, 'Expected an error.');\n    if (innerError.failures().length < error.failures().length) {\n      return innerError;\n    }\n\n    return error;\n  }, validationResults[0][0]);\n\n  throw new Error(\n    getStructFailureMessage(struct, validationError.failures()[0], false),\n  );\n}\n\n/**\n * Create a value with the coercion logic of a union struct, and throw readable\n * errors if the value does not satisfy the struct. This is useful for improving\n * the error messages returned by `superstruct`.\n *\n * @param value - The value to validate.\n * @param struct - The `superstruct` union struct to validate the value against.\n * This struct must be a union of object structs, and must have at least one\n * shared key to validate against.\n * @param structKey - The key to validate against. This key must be present in\n * all the object structs in the union struct, and is expected to be a literal\n * value.\n * @returns The validated value.\n * @throws If the value does not satisfy the struct.\n * @see validateUnion\n */\nexport function createUnion<Type, Schema extends readonly Struct<any, any>[]>(\n  value: unknown,\n  struct: Struct<Type, Schema>,\n  structKey: keyof Type,\n) {\n  return validateUnion(value, struct, structKey, true);\n}\n\n// These types are copied from Superstruct, to mirror `assign`.\nexport function mergeStructs<\n  ObjectA extends ObjectSchema,\n  ObjectB extends ObjectSchema,\n>(\n  A: Struct<ObjectType<ObjectA>, ObjectA>,\n  B: Struct<ObjectType<ObjectB>, ObjectB>,\n): Struct<ObjectType<Assign<ObjectA, ObjectB>>, Assign<ObjectA, ObjectB>>;\nexport function mergeStructs<\n  ObjectA extends ObjectSchema,\n  ObjectB extends ObjectSchema,\n  ObjectC extends ObjectSchema,\n>(\n  A: Struct<ObjectType<ObjectA>, ObjectA>,\n  B: Struct<ObjectType<ObjectB>, ObjectB>,\n  C: Struct<ObjectType<ObjectC>, ObjectC>,\n): Struct<\n  ObjectType<Assign<Assign<ObjectA, ObjectB>, ObjectC>>,\n  Assign<Assign<ObjectA, ObjectB>, ObjectC>\n>;\nexport function mergeStructs<\n  ObjectA extends ObjectSchema,\n  ObjectB extends ObjectSchema,\n  ObjectC extends ObjectSchema,\n  ObjectD extends ObjectSchema,\n>(\n  A: Struct<ObjectType<ObjectA>, ObjectA>,\n  B: Struct<ObjectType<ObjectB>, ObjectB>,\n  C: Struct<ObjectType<ObjectC>, ObjectC>,\n  D: Struct<ObjectType<ObjectD>, ObjectD>,\n): Struct<\n  ObjectType<Assign<Assign<Assign<ObjectA, ObjectB>, ObjectC>, ObjectD>>,\n  Assign<Assign<Assign<ObjectA, ObjectB>, ObjectC>, ObjectD>\n>;\nexport function mergeStructs<\n  ObjectA extends ObjectSchema,\n  ObjectB extends ObjectSchema,\n  ObjectC extends ObjectSchema,\n  ObjectD extends ObjectSchema,\n  ObjectE extends ObjectSchema,\n>(\n  A: Struct<ObjectType<ObjectA>, ObjectA>,\n  B: Struct<ObjectType<ObjectB>, ObjectB>,\n  C: Struct<ObjectType<ObjectC>, ObjectC>,\n  D: Struct<ObjectType<ObjectD>, ObjectD>,\n  E: Struct<ObjectType<ObjectE>, ObjectE>,\n): Struct<\n  ObjectType<\n    Assign<Assign<Assign<Assign<ObjectA, ObjectB>, ObjectC>, ObjectD>, ObjectE>\n  >,\n  Assign<Assign<Assign<Assign<ObjectA, ObjectB>, ObjectC>, ObjectD>, ObjectE>\n>;\n\n/**\n * Merge multiple structs into one, using superstruct `assign`.\n *\n * Differently from plain `assign`, this function also copies over refinements from each struct.\n *\n * @param structs - The `superstruct` structs to merge.\n * @returns The merged struct.\n */\nexport function mergeStructs(...structs: Struct<any>[]): Struct<any> {\n  const mergedStruct = (assign as (...structs: Struct<any>[]) => Struct)(\n    ...structs,\n  );\n  return new Struct({\n    ...mergedStruct,\n    *refiner(value, ctx) {\n      for (const struct of structs) {\n        yield* struct.refiner(value, ctx);\n      }\n    },\n  });\n}\n"]}