{"version":3,"file":"standardSchemaValidator.cjs","sources":["../../src/standardSchemaValidator.ts"],"sourcesContent":["import type { ValidationSource } from './types'\n\nexport type TStandardSchemaValidatorValue<\n  TData,\n  TSource extends ValidationSource = ValidationSource,\n> = {\n  value: TData\n  validationSource: TSource\n}\n\nexport type TStandardSchemaValidatorIssue<\n  TSource extends ValidationSource = ValidationSource,\n> = TSource extends 'form'\n  ? {\n      form: Record<string, StandardSchemaV1Issue[]>\n      fields: Record<string, StandardSchemaV1Issue[]>\n    }\n  : TSource extends 'field'\n    ? StandardSchemaV1Issue[]\n    : never\n\nfunction prefixSchemaToErrors(\n  issues: readonly StandardSchemaV1Issue[],\n  formValue: unknown,\n) {\n  const schema = new Map<string, StandardSchemaV1Issue[]>()\n\n  for (const issue of issues) {\n    const issuePath = issue.path ?? []\n\n    let currentFormValue = formValue\n    let path = ''\n\n    for (let i = 0; i < issuePath.length; i++) {\n      const pathSegment = issuePath[i]\n      if (pathSegment === undefined) continue\n\n      const segment =\n        typeof pathSegment === 'object' ? pathSegment.key : pathSegment\n\n      // Standard Schema doesn't specify if paths should use numbers or stringified numbers for array access.\n      // However, if we follow the path it provides and encounter an array, then we can assume it's intended for array access.\n      const segmentAsNumber = Number(segment)\n      if (Array.isArray(currentFormValue) && !Number.isNaN(segmentAsNumber)) {\n        path += `[${segmentAsNumber}]`\n      } else {\n        path += (i > 0 ? '.' : '') + String(segment)\n      }\n\n      if (typeof currentFormValue === 'object' && currentFormValue !== null) {\n        currentFormValue = currentFormValue[segment as never]\n      } else {\n        currentFormValue = undefined\n      }\n    }\n    schema.set(path, (schema.get(path) ?? []).concat(issue))\n  }\n\n  return Object.fromEntries(schema)\n}\n\nconst transformFormIssues = <TSource extends ValidationSource>(\n  issues: readonly StandardSchemaV1Issue[],\n  formValue: unknown,\n): TStandardSchemaValidatorIssue<TSource> => {\n  const schemaErrors = prefixSchemaToErrors(issues, formValue)\n  return {\n    form: schemaErrors,\n    fields: schemaErrors,\n  } as TStandardSchemaValidatorIssue<TSource>\n}\n\nexport const standardSchemaValidators = {\n  validate<TSource extends ValidationSource = ValidationSource>(\n    {\n      value,\n      validationSource,\n    }: TStandardSchemaValidatorValue<unknown, TSource>,\n    schema: StandardSchemaV1,\n  ): TStandardSchemaValidatorIssue<TSource> | undefined {\n    const result = schema['~standard'].validate(value)\n\n    if (result instanceof Promise) {\n      throw new Error('async function passed to sync validator')\n    }\n\n    if (!result.issues) return\n\n    if (validationSource === 'field')\n      return result.issues as TStandardSchemaValidatorIssue<TSource>\n    return transformFormIssues<TSource>(result.issues, value)\n  },\n  async validateAsync<TSource extends ValidationSource>(\n    {\n      value,\n      validationSource,\n    }: TStandardSchemaValidatorValue<unknown, TSource>,\n    schema: StandardSchemaV1,\n  ): Promise<TStandardSchemaValidatorIssue<TSource> | undefined> {\n    const result = await schema['~standard'].validate(value)\n\n    if (!result.issues) return\n\n    if (validationSource === 'field')\n      return result.issues as TStandardSchemaValidatorIssue<TSource>\n    return transformFormIssues<TSource>(result.issues, value)\n  },\n}\n\nexport const isStandardSchemaValidator = (\n  validator: unknown,\n): validator is StandardSchemaV1 =>\n  !!validator && '~standard' in (validator as object)\n\n/**\n * The Standard Schema interface.\n */\nexport type StandardSchemaV1<Input = unknown, Output = Input> = {\n  /**\n   * The Standard Schema properties.\n   */\n  readonly '~standard': StandardSchemaV1Props<Input, Output>\n}\n\n/**\n * The Standard Schema properties interface.\n */\ninterface StandardSchemaV1Props<Input = unknown, Output = Input> {\n  /**\n   * The version number of the standard.\n   */\n  readonly version: 1\n  /**\n   * The vendor name of the schema library.\n   */\n  readonly vendor: string\n  /**\n   * Validates unknown input values.\n   */\n  readonly validate: (\n    value: unknown,\n  ) => StandardSchemaV1Result<Output> | Promise<StandardSchemaV1Result<Output>>\n  /**\n   * Inferred types associated with the schema.\n   */\n  readonly types?: StandardSchemaV1Types<Input, Output> | undefined\n}\n/**\n * The result interface of the validate function.\n */\ntype StandardSchemaV1Result<Output> =\n  | StandardSchemaV1SuccessResult<Output>\n  | StandardSchemaV1FailureResult\n/**\n * The result interface if validation succeeds.\n */\ninterface StandardSchemaV1SuccessResult<Output> {\n  /**\n   * The typed output value.\n   */\n  readonly value: Output\n  /**\n   * The non-existent issues.\n   */\n  readonly issues?: undefined\n}\n/**\n * The result interface if validation fails.\n */\ninterface StandardSchemaV1FailureResult {\n  /**\n   * The issues of failed validation.\n   */\n  readonly issues: ReadonlyArray<StandardSchemaV1Issue>\n}\n/**\n * The issue interface of the failure output.\n */\nexport interface StandardSchemaV1Issue {\n  /**\n   * The error message of the issue.\n   */\n  readonly message: string\n  /**\n   * The path of the issue, if any.\n   */\n  readonly path?:\n    | ReadonlyArray<PropertyKey | StandardSchemaV1PathSegment>\n    | undefined\n}\n/**\n * The path segment interface of the issue.\n */\ninterface StandardSchemaV1PathSegment {\n  /**\n   * The key representing a path segment.\n   */\n  readonly key: PropertyKey\n}\n/**\n * The Standard Schema types interface.\n */\ninterface StandardSchemaV1Types<Input = unknown, Output = Input> {\n  /**\n   * The input type of the schema.\n   */\n  readonly input: Input\n  /**\n   * The output type of the schema.\n   */\n  readonly output: Output\n}\n"],"names":[],"mappings":";;AAqBA,SAAS,qBACP,QACA,WACA;AACA,QAAM,6BAAa,IAAA;AAEnB,aAAW,SAAS,QAAQ;AAC1B,UAAM,YAAY,MAAM,QAAQ,CAAA;AAEhC,QAAI,mBAAmB;AACvB,QAAI,OAAO;AAEX,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,YAAM,cAAc,UAAU,CAAC;AAC/B,UAAI,gBAAgB,OAAW;AAE/B,YAAM,UACJ,OAAO,gBAAgB,WAAW,YAAY,MAAM;AAItD,YAAM,kBAAkB,OAAO,OAAO;AACtC,UAAI,MAAM,QAAQ,gBAAgB,KAAK,CAAC,OAAO,MAAM,eAAe,GAAG;AACrE,gBAAQ,IAAI,eAAe;AAAA,MAC7B,OAAO;AACL,iBAAS,IAAI,IAAI,MAAM,MAAM,OAAO,OAAO;AAAA,MAC7C;AAEA,UAAI,OAAO,qBAAqB,YAAY,qBAAqB,MAAM;AACrE,2BAAmB,iBAAiB,OAAgB;AAAA,MACtD,OAAO;AACL,2BAAmB;AAAA,MACrB;AAAA,IACF;AACA,WAAO,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,CAAA,GAAI,OAAO,KAAK,CAAC;AAAA,EACzD;AAEA,SAAO,OAAO,YAAY,MAAM;AAClC;AAEA,MAAM,sBAAsB,CAC1B,QACA,cAC2C;AAC3C,QAAM,eAAe,qBAAqB,QAAQ,SAAS;AAC3D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAEZ;AAEO,MAAM,2BAA2B;AAAA,EACtC,SACE;AAAA,IACE;AAAA,IACA;AAAA,EAAA,GAEF,QACoD;AACpD,UAAM,SAAS,OAAO,WAAW,EAAE,SAAS,KAAK;AAEjD,QAAI,kBAAkB,SAAS;AAC7B,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAEA,QAAI,CAAC,OAAO,OAAQ;AAEpB,QAAI,qBAAqB;AACvB,aAAO,OAAO;AAChB,WAAO,oBAA6B,OAAO,QAAQ,KAAK;AAAA,EAC1D;AAAA,EACA,MAAM,cACJ;AAAA,IACE;AAAA,IACA;AAAA,EAAA,GAEF,QAC6D;AAC7D,UAAM,SAAS,MAAM,OAAO,WAAW,EAAE,SAAS,KAAK;AAEvD,QAAI,CAAC,OAAO,OAAQ;AAEpB,QAAI,qBAAqB;AACvB,aAAO,OAAO;AAChB,WAAO,oBAA6B,OAAO,QAAQ,KAAK;AAAA,EAC1D;AACF;AAEO,MAAM,4BAA4B,CACvC,cAEA,CAAC,CAAC,aAAa,eAAgB;;;"}