{"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Failure } from './error.js';\nimport type {\n  Struct,\n  Infer,\n  Result,\n  Context,\n  Describe,\n  ExactOptionalStruct,\n} from './struct.js';\n\n/**\n * Check if a value is an iterator.\n *\n * @param value - The value to check.\n * @returns Whether the value is an iterator.\n */\nfunction isIterable<Type>(value: unknown): value is Iterable<Type> {\n  return isObject(value) && typeof value[Symbol.iterator] === 'function';\n}\n\n/**\n * Check if a value is a plain object.\n *\n * @param value - The value to check.\n * @returns Whether the value is a plain object.\n */\nexport function isObject(\n  value: unknown,\n): value is Record<PropertyKey, unknown> {\n  return typeof value === 'object' && value !== null;\n}\n\n/**\n * Check if a value is a plain object.\n *\n * @param value - The value to check.\n * @returns Whether the value is a plain object.\n */\nexport function isPlainObject(value: unknown): value is { [key: string]: any } {\n  if (Object.prototype.toString.call(value) !== '[object Object]') {\n    return false;\n  }\n\n  const prototype = Object.getPrototypeOf(value);\n  return prototype === null || prototype === Object.prototype;\n}\n\n/**\n * Return a value as a printable string.\n *\n * @param value - The value to print.\n * @returns The value as a string.\n */\nexport function print(value: any): string {\n  if (typeof value === 'symbol') {\n    return value.toString();\n  }\n\n  // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n  return typeof value === 'string' ? JSON.stringify(value) : `${value}`;\n}\n\n/**\n * Shift (remove and return) the first value from the `input` iterator.\n * Like `Array.prototype.shift()` but for an `Iterator`.\n *\n * @param input - The iterator to shift.\n * @returns The first value of the iterator, or `undefined` if the iterator is\n * empty.\n */\nexport function shiftIterator<Type>(input: Iterator<Type>): Type | undefined {\n  const { done, value } = input.next();\n  return done ? undefined : value;\n}\n\n/**\n * Convert a single validation result to a failure.\n *\n * @param result - The result to convert.\n * @param context - The context of the validation.\n * @param struct - The struct being validated.\n * @param value - The value being validated.\n * @returns A failure if the result is a failure, or `undefined` if the result\n * is a success.\n */\nexport function toFailure<Type, Schema>(\n  result: string | boolean | Partial<Failure>,\n  context: Context,\n  struct: Struct<Type, Schema>,\n  value: any,\n): Failure | undefined {\n  if (result === true) {\n    return undefined;\n  } else if (result === false) {\n    // eslint-disable-next-line no-param-reassign\n    result = {};\n  } else if (typeof result === 'string') {\n    // eslint-disable-next-line no-param-reassign\n    result = { message: result };\n  }\n\n  const { path, branch } = context;\n  const { type } = struct;\n  const {\n    refinement,\n    message = `Expected a value of type \\`${type}\\`${\n      refinement ? ` with refinement \\`${refinement}\\`` : ''\n    }, but received: \\`${print(value)}\\``,\n  } = result;\n\n  return {\n    value,\n    type,\n    refinement,\n    key: path[path.length - 1],\n    path,\n    branch,\n    ...result,\n    message,\n  };\n}\n\n/**\n * Convert a validation result to an iterable of failures.\n *\n * @param result - The result to convert.\n * @param context - The context of the validation.\n * @param struct - The struct being validated.\n * @param value - The value being validated.\n * @yields The failures.\n * @returns An iterable of failures.\n */\nexport function* toFailures<Type, Schema>(\n  result: Result,\n  context: Context,\n  struct: Struct<Type, Schema>,\n  value: any,\n): IterableIterator<Failure> {\n  if (!isIterable(result)) {\n    // eslint-disable-next-line no-param-reassign\n    result = [result];\n  }\n\n  for (const validationResult of result) {\n    const failure = toFailure(validationResult, context, struct, value);\n\n    if (failure) {\n      yield failure;\n    }\n  }\n}\n\n/**\n * Check a value against a struct, traversing deeply into nested values, and\n * returning an iterator of failures or success.\n *\n * @param value - The value to check.\n * @param struct - The struct to check against.\n * @param options - Optional settings.\n * @param options.path - The path to the value in the input data.\n * @param options.branch - The branch of the value in the input data.\n * @param options.coerce - Whether to coerce the value before validating it.\n * @param options.mask - Whether to mask the value before validating it.\n * @param options.message - An optional message to include in the error.\n * @yields An iterator of failures or success.\n * @returns An iterator of failures or success.\n */\nexport function* run<Type, Schema>(\n  value: unknown,\n  struct: Struct<Type, Schema>,\n  options: {\n    path?: any[] | undefined;\n    branch?: any[] | undefined;\n    coerce?: boolean | undefined;\n    mask?: boolean | undefined;\n    message?: string | undefined;\n  } = {},\n): IterableIterator<[Failure, undefined] | [undefined, Type]> {\n  const { path = [], branch = [value], coerce = false, mask = false } = options;\n  const context: Context = { path, branch };\n\n  if (coerce) {\n    // eslint-disable-next-line no-param-reassign\n    value = struct.coercer(value, context);\n\n    if (\n      mask &&\n      struct.type !== 'type' &&\n      isObject(struct.schema) &&\n      isObject(value) &&\n      !Array.isArray(value)\n    ) {\n      for (const key in value) {\n        if (struct.schema[key] === undefined) {\n          delete value[key];\n        }\n      }\n    }\n  }\n\n  let status: 'valid' | 'not_refined' | 'not_valid' = 'valid';\n\n  for (const failure of struct.validator(value, context)) {\n    failure.explanation = options.message;\n    status = 'not_valid';\n    yield [failure, undefined];\n  }\n\n  // eslint-disable-next-line prefer-const\n  for (let [innerKey, innerValue, innerStruct] of struct.entries(\n    value,\n    context,\n  )) {\n    const iterable = run(innerValue, innerStruct as Struct, {\n      path: innerKey === undefined ? path : [...path, innerKey],\n      branch: innerKey === undefined ? branch : [...branch, innerValue],\n      coerce,\n      mask,\n      message: options.message,\n    });\n\n    for (const result of iterable) {\n      if (result[0]) {\n        status =\n          result[0].refinement === null || result[0].refinement === undefined\n            ? 'not_valid'\n            : 'not_refined';\n\n        yield [result[0], undefined];\n      } else if (coerce) {\n        innerValue = result[1];\n\n        if (innerKey === undefined) {\n          // eslint-disable-next-line no-param-reassign\n          value = innerValue;\n        } else if (value instanceof Map) {\n          value.set(innerKey, innerValue);\n        } else if (value instanceof Set) {\n          value.add(innerValue);\n        } else if (isObject(value)) {\n          if (innerValue !== undefined || innerKey in value) {\n            value[innerKey] = innerValue;\n          }\n        }\n      }\n    }\n  }\n\n  if (status !== 'not_valid') {\n    for (const failure of struct.refiner(value as Type, context)) {\n      failure.explanation = options.message;\n      status = 'not_refined';\n      yield [failure, undefined];\n    }\n  }\n\n  if (status === 'valid') {\n    yield [undefined, value as Type];\n  }\n}\n\n/**\n * Convert a union of type to an intersection.\n */\nexport type UnionToIntersection<Union> = (\n  Union extends any ? (arg: Union) => any : never\n) extends (arg: infer Type) => void\n  ? Type\n  : never;\n\n/**\n * Assign properties from one type to another, overwriting existing.\n */\nexport type Assign<Type, OtherType> = Simplify<\n  OtherType & Omit<Type, keyof OtherType>\n>;\n\n/**\n * A schema for enum structs.\n */\nexport type EnumSchema<Type extends string | number | undefined | null> = {\n  [Key in NonNullable<Type>]: Key;\n};\n\n/**\n * Check if a type is a match for another whilst treating overlapping\n * unions as a match.\n */\nexport type IsMatch<Type, OtherType> = Type extends OtherType\n  ? OtherType extends Type\n    ? Type\n    : never\n  : never;\n\n/**\n * Check if a type is an exact match.\n */\nexport type IsExactMatch<Type, OtherType> = (<Inner>() => Inner extends Type\n  ? 1\n  : 2) extends <Inner>() => Inner extends OtherType ? 1 : 2\n  ? Type\n  : never;\n\n/**\n * Check if a type is a record type.\n */\nexport type IsRecord<Type> = Type extends object\n  ? string extends keyof Type\n    ? Type\n    : never\n  : never;\n\n/**\n * Check if a type is a tuple.\n */\nexport type IsTuple<Type> = Type extends [any]\n  ? Type\n  : Type extends [any, any]\n  ? Type\n  : Type extends [any, any, any]\n  ? Type\n  : Type extends [any, any, any, any]\n  ? Type\n  : Type extends [any, any, any, any, any]\n  ? Type\n  : never;\n\n/**\n * Check if a type is a union.\n */\nexport type IsUnion<Type, Union extends Type = Type> = (\n  Type extends any ? (Union extends Type ? false : true) : false\n) extends false\n  ? never\n  : Type;\n\n/**\n * A schema for object structs.\n */\nexport type ObjectSchema = Record<string, Struct<any, any>>;\n\n/**\n * Infer a type from an object struct schema.\n */\nexport type ObjectType<Schema extends ObjectSchema> = Simplify<\n  // ExactOptionalize first ensures that properties of `exactOptional()` structs\n  // are optional, then Optionalize ensures that properties that can have the\n  // value `undefined` are optional.\n  Optionalize<ExactOptionalize<Schema>>\n>;\n\n/**\n * Make properties of `exactOptional()` structs optional.\n */\nexport type ExactOptionalize<Schema extends ObjectSchema> = {\n  [K in keyof OmitExactOptional<Schema>]: Infer<OmitExactOptional<Schema>[K]>;\n} & {\n  [K in keyof PickExactOptional<Schema>]?: Infer<PickExactOptional<Schema>[K]>;\n};\n\ntype OmitExactOptional<Schema extends ObjectSchema> = Omit<\n  Schema,\n  {\n    [K in keyof Schema]: Schema[K] extends ExactOptionalStruct<any, any>\n      ? Schema[K] extends never\n        ? never\n        : K\n      : never;\n  }[keyof Schema]\n>;\n\ntype PickExactOptional<Schema extends ObjectSchema> = Pick<\n  Schema,\n  {\n    [K in keyof Schema]: Schema[K] extends ExactOptionalStruct<any, any>\n      ? Schema[K] extends never\n        ? never\n        : K\n      : never;\n  }[keyof Schema]\n>;\n\n/**\n * Make properties that can have the value `undefined` optional.\n */\nexport type Optionalize<Schema extends object> = OmitBy<Schema, undefined> &\n  Partial<PickBy<Schema, undefined>>;\n\n/**\n * Omit properties from a type that extend from a specific type.\n */\nexport type OmitBy<Type, Value> = Omit<\n  Type,\n  {\n    [Key in keyof Type]: Value extends Extract<Type[Key], Value> ? Key : never;\n  }[keyof Type]\n>;\n\n/**\n * Pick properties from a type that extend from a specific type.\n */\nexport type PickBy<Type, Value> = Pick<\n  Type,\n  {\n    [Key in keyof Type]: Value extends Extract<Type[Key], Value> ? Key : never;\n  }[keyof Type]\n>;\n\n/**\n * Transform an object schema type to represent a partial.\n */\nexport type PartialObjectSchema<Schema extends ObjectSchema> = {\n  [K in keyof Schema]: Struct<Infer<Schema[K]> | undefined>;\n};\n\n/**\n * Simplifies a type definition to its most basic representation.\n */\nexport type Simplify<Type> = Type extends any[] | Date\n  ? Type\n  : // eslint-disable-next-line @typescript-eslint/ban-types\n    { [Key in keyof Type]: Type[Key] } & {};\n\nexport type If<Condition extends boolean, Then, Else> = Condition extends true\n  ? Then\n  : Else;\n\n/**\n * A schema for any type of struct.\n */\nexport type StructSchema<Type> = [Type] extends [string | undefined | null]\n  ? [Type] extends [IsMatch<Type, string | undefined | null>]\n    ? null\n    : [Type] extends [IsUnion<Type>]\n    ? EnumSchema<Type>\n    : Type\n  : [Type] extends [number | undefined | null]\n  ? [Type] extends [IsMatch<Type, number | undefined | null>]\n    ? null\n    : [Type] extends [IsUnion<Type>]\n    ? EnumSchema<Type>\n    : Type\n  : [Type] extends [boolean]\n  ? [Type] extends [IsExactMatch<Type, boolean>]\n    ? null\n    : Type\n  : Type extends\n      | bigint\n      | symbol\n      | undefined\n      | null\n      // eslint-disable-next-line @typescript-eslint/ban-types\n      | Function\n      | Date\n      | Error\n      | RegExp\n      | Map<any, any>\n      | WeakMap<any, any>\n      | Set<any>\n      | WeakSet<any>\n      | Promise<any>\n  ? null\n  : Type extends (infer Inner)[]\n  ? Type extends IsTuple<Type>\n    ? null\n    : Struct<Inner>\n  : Type extends object\n  ? Type extends IsRecord<Type>\n    ? null\n    : { [K in keyof Type]: Describe<Type[K]> }\n  : null;\n\n/**\n * A schema for tuple structs.\n */\nexport type TupleSchema<Type> = { [K in keyof Type]: Struct<Type[K]> };\n\n/**\n * Shorthand type for matching any `Struct`.\n */\nexport type AnyStruct = Struct<any, any>;\n\n/**\n * Infer a tuple of types from a tuple of `Struct`s.\n *\n * This is used to recursively retrieve the type from `union` `intersection` and\n * `tuple` structs.\n */\nexport type InferStructTuple<\n  Tuple extends AnyStruct[],\n  Length extends number = Tuple['length'],\n> = Length extends Length\n  ? number extends Length\n    ? Tuple\n    : InferTuple<Tuple, Length, []>\n  : never;\n\ntype InferTuple<\n  Tuple extends AnyStruct[],\n  Length extends number,\n  Accumulated extends unknown[],\n  Index extends number = Accumulated['length'],\n> = Index extends Length\n  ? Accumulated\n  : InferTuple<Tuple, Length, [...Accumulated, Infer<Tuple[Index]>]>;\n"]}