{"version":3,"file":"brand.mjs","sources":["../../src/brand/brand.mts"],"sourcesContent":["import { pipe, Result } from 'ts-data-forge';\nimport { type Brand, type Primitive, type StrictExtract } from 'ts-type-forge';\nimport { type Type } from '../type.mjs';\nimport { createType, type ValidationError } from '../utils/index.mjs';\n\nexport type { Brand } from 'ts-type-forge';\n\ntype ArrayToUnion<A extends readonly unknown[]> = A extends readonly []\n  ? never\n  : A[number];\n\nexport const brand = <\n  const A extends StrictExtract<Primitive, string | number | bigint | boolean>,\n  const BrandTrueKeys extends readonly string[],\n  const BrandFalseKeys extends readonly string[] = readonly [],\n>({\n  baseType,\n  brandFalseKeys,\n  brandKeys,\n  defaultValue: defaultValue_,\n  is: is_,\n  typeName,\n}: Readonly<{\n  baseType: Type<A>;\n  is?: (\n    a: A,\n  ) => a is Brand<A, ArrayToUnion<BrandTrueKeys>, ArrayToUnion<BrandFalseKeys>>;\n  defaultValue?: A;\n  typeName?: string;\n  brandKeys: BrandTrueKeys;\n  brandFalseKeys?: BrandFalseKeys;\n}>): Type<\n  Brand<A, ArrayToUnion<BrandTrueKeys>, ArrayToUnion<BrandFalseKeys>>\n> => {\n  type T = Brand<A, ArrayToUnion<BrandTrueKeys>, ArrayToUnion<BrandFalseKeys>>;\n\n  const is: (a: A) => a is T = is_ ?? ((_a): _a is T => true);\n\n  const defaultValue: A = defaultValue_ ?? baseType.defaultValue;\n\n  if (!is(defaultValue)) {\n    throw new Error(\n      `defaultValue ${defaultValue} doesn't pass \\`is\\` function`,\n    );\n  }\n\n  const brandKeysStr = [\n    ...brandKeys.map((s) => `\"${s}\"`),\n    ...(brandFalseKeys?.map((s) => `not(\"${s}\")`) ?? []),\n  ].join(' & ');\n\n  const typeNameFilled = typeName ?? brandKeysStr;\n\n  const validate: Type<T>['validate'] = (a) =>\n    pipe(a)\n      .map(baseType.validate)\n      .map((res): Result<T, readonly ValidationError[]> =>\n        Result.isErr(res)\n          ? res\n          : is(res.value)\n            ? Result.ok(res.value satisfies T)\n            : Result.err([\n                {\n                  path: [],\n                  actualValue: res.value,\n                  expectedType: typeNameFilled,\n                  typeName: typeNameFilled,\n                  details:\n                    // If typeName is specified, it will be used in the error message, so no further information is required.\n                    typeName === undefined\n                      ? {\n                          kind: 'brand' as const,\n                          description: brandKeysStr,\n                        }\n                      : undefined,\n                } satisfies ValidationError,\n              ]),\n      ).value;\n\n  return createType({\n    typeName: typeNameFilled,\n    defaultValue,\n    validate,\n  });\n};\n"],"names":[],"mappings":";;;;AAWO,MAAM,QAAQ,CAInB;AAAA,EACA,QAAA;AAAA,EACA,cAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA,EAAc,aAAA;AAAA,EACd,EAAA,EAAI,GAAA;AAAA,EACJ;AACF,CAAA,KAWK;AAGH,EAAA,MAAM,EAAA,GAAuB,GAAA,KAAQ,CAAC,EAAA,KAAgB,IAAA,CAAA;AAEtD,EAAA,MAAM,YAAA,GAAkB,iBAAiB,QAAA,CAAS,YAAA;AAElD,EAAA,IAAI,CAAC,EAAA,CAAG,YAAY,CAAA,EAAG;AACrB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,gBAAgB,YAAY,CAAA,6BAAA;AAAA,KAC9B;AAAA,EACF;AAEA,EAAA,MAAM,YAAA,GAAe;AAAA,IACnB,GAAG,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,IAChC,GAAI,gBAAgB,GAAA,CAAI,CAAC,MAAM,CAAA,KAAA,EAAQ,CAAC,CAAA,EAAA,CAAI,CAAA,IAAK;AAAC,GACpD,CAAE,KAAK,KAAK,CAAA;AAEZ,EAAA,MAAM,iBAAiB,QAAA,IAAY,YAAA;AAEnC,EAAA,MAAM,QAAA,GAAgC,CAAC,CAAA,KACrC,IAAA,CAAK,CAAC,CAAA,CACH,GAAA,CAAI,QAAA,CAAS,QAAQ,CAAA,CACrB,GAAA;AAAA,IAAI,CAAC,GAAA,KACJ,MAAA,CAAO,KAAA,CAAM,GAAG,IACZ,GAAA,GACA,EAAA,CAAG,GAAA,CAAI,KAAK,IACV,MAAA,CAAO,EAAA,CAAG,IAAI,KAAiB,CAAA,GAC/B,OAAO,GAAA,CAAI;AAAA,MACT;AAAA,QACE,MAAM,EAAC;AAAA,QACP,aAAa,GAAA,CAAI,KAAA;AAAA,QACjB,YAAA,EAAc,cAAA;AAAA,QACd,QAAA,EAAU,cAAA;AAAA,QACV,OAAA;AAAA;AAAA,UAEE,aAAa,MAAA,GACT;AAAA,YACE,IAAA,EAAM,OAAA;AAAA,YACN,WAAA,EAAa;AAAA,WACf,GACA;AAAA;AAAA;AACR,KACD;AAAA,GACT,CAAE,KAAA;AAEN,EAAA,OAAO,UAAA,CAAW;AAAA,IAChB,QAAA,EAAU,cAAA;AAAA,IACV,YAAA;AAAA,IACA;AAAA,GACD,CAAA;AACH;;;;"}