{"version":3,"file":"OpenApiOneOfValidator.mjs","sources":["../../../src/utils/internal/OpenApiOneOfValidator.ts"],"sourcesContent":["import { OpenApi } from \"../../OpenApi\";\nimport { MapUtil } from \"../MapUtil\";\nimport { OpenApiTypeChecker } from \"../OpenApiTypeChecker\";\nimport { IOpenApiValidatorContext } from \"./IOpenApiValidatorContext\";\nimport { OpenApiStationValidator } from \"./OpenApiStationValidator\";\n\nexport namespace OpenApiOneOfValidator {\n  export const validate = (\n    ctx: IOpenApiValidatorContext<OpenApi.IJsonSchema.IOneOf>,\n  ): boolean => {\n    const discriminator: IDiscriminator = getDiscriminator(ctx);\n    for (const item of discriminator.branches)\n      if (item.predicator(ctx.value))\n        return OpenApiStationValidator.validate({\n          ...ctx,\n          schema: item.schema,\n        });\n    if (discriminator.branches.length !== 0)\n      return validate({\n        ...ctx,\n        schema: {\n          oneOf: discriminator.remainders,\n        },\n      });\n    const matched: OpenApi.IJsonSchema | undefined =\n      discriminator.remainders.find(\n        (schema) =>\n          OpenApiStationValidator.validate({\n            ...ctx,\n            schema,\n            exceptionable: false,\n            equals: false,\n          }) === true,\n      );\n    if (matched === undefined) return ctx.report(ctx);\n    return ctx.equals === true\n      ? OpenApiStationValidator.validate({\n          ...ctx,\n          schema: matched,\n        })\n      : true;\n  };\n\n  const getDiscriminator = (\n    ctx: IOpenApiValidatorContext<OpenApi.IJsonSchema.IOneOf>,\n  ): IDiscriminator => {\n    const resolvedList: IFlatSchema[] = ctx.schema.oneOf.map((schema) =>\n      getFlattened({\n        components: ctx.components,\n        schema,\n        visited: new Set(),\n      }),\n    );\n\n    // FIND ANY TYPE\n    const anything: IFlatSchema | undefined = resolvedList.find((resolved) =>\n      OpenApiTypeChecker.isUnknown(resolved.escaped),\n    );\n    if (anything)\n      return {\n        branches: [],\n        remainders: [anything.schema],\n      };\n\n    // CHECK NULLABLES\n    const nullables: IFlatSchema<OpenApi.IJsonSchema.INull>[] =\n      resolvedList.filter(\n        (resolved): resolved is IFlatSchema<OpenApi.IJsonSchema.INull> =>\n          OpenApiTypeChecker.isNull(resolved.schema),\n      );\n    const significant: IFlatSchema<OpenApi.IJsonSchema>[] = resolvedList.filter(\n      (resolved) => false === OpenApiTypeChecker.isNull(resolved.escaped),\n    );\n    if (significant.length === 1)\n      return {\n        branches: [\n          {\n            schema: significant[0].schema,\n            predicator: (value) => value !== null,\n          },\n        ],\n        remainders: nullables.map((nullable) => nullable.schema),\n      };\n\n    // DISCRIMINATIONS\n    const tuples = significant.filter((flat) =>\n      OpenApiTypeChecker.isTuple(flat.escaped),\n    );\n    const arrays = significant.filter(\n      (flat): flat is IFlatSchema<OpenApi.IJsonSchema.IArray> =>\n        OpenApiTypeChecker.isArray(flat.escaped),\n    );\n    const branches: IDiscriminatorBranch[] = [\n      ...(tuples.length === 0 && arrays.length !== 0\n        ? discriminateArrays(\n            ctx,\n            significant.filter(\n              (flat): flat is IFlatSchema<OpenApi.IJsonSchema.IArray> =>\n                OpenApiTypeChecker.isArray(flat.schema),\n            ),\n          )\n        : []),\n      ...discriminateObjects(\n        ctx,\n        significant.filter(\n          (flat): flat is IFlatSchema<OpenApi.IJsonSchema.IObject> =>\n            OpenApiTypeChecker.isObject(flat.escaped),\n        ),\n        tuples.length + arrays.length === 0,\n      ),\n    ];\n    return {\n      branches,\n      remainders: ctx.schema.oneOf.filter(\n        (x) => branches.some((y) => y.schema === x) === false,\n      ),\n    };\n  };\n\n  const discriminateArrays = (\n    ctx: IOpenApiValidatorContext<OpenApi.IJsonSchema.IOneOf>,\n    arraySchemas: IFlatSchema<OpenApi.IJsonSchema.IArray>[],\n  ): IDiscriminatorBranch[] => {\n    if (arraySchemas.length === 1)\n      return [\n        {\n          schema: arraySchemas[0].schema,\n          predicator: (value) => Array.isArray(value),\n        },\n      ];\n    return arraySchemas\n      .filter((flat, i, array) =>\n        array.every(\n          (item, j) =>\n            i === j ||\n            OpenApiTypeChecker.covers({\n              components: ctx.components,\n              x: item.escaped.items,\n              y: flat.escaped.items,\n            }) === false,\n        ),\n      )\n      .map(\n        (flat) =>\n          ({\n            schema: flat.schema,\n            predicator: (value) =>\n              Array.isArray(value) &&\n              (value.length === 0 ||\n                OpenApiStationValidator.validate({\n                  ...ctx,\n                  schema: (flat.escaped as OpenApi.IJsonSchema.IArray).items,\n                  value: value[0]!,\n                  path: `${ctx.path}[0]`,\n                  exceptionable: false,\n                  equals: false,\n                })),\n          }) satisfies IDiscriminatorBranch,\n      );\n  };\n\n  const discriminateObjects = (\n    ctx: IOpenApiValidatorContext<OpenApi.IJsonSchema.IOneOf>,\n    objectSchemas: IFlatSchema<OpenApi.IJsonSchema.IObject>[],\n    noArray: boolean,\n  ): IDiscriminatorBranch[] => {\n    if (objectSchemas.length === 1)\n      return [\n        {\n          schema: objectSchemas[0].schema,\n          predicator: noArray\n            ? (value) => typeof value === \"object\" && value !== null\n            : (value) =>\n                typeof value === \"object\" &&\n                value !== null &&\n                Array.isArray(value) === false,\n        },\n      ];\n\n    // KEEP ONLY REQUIRED PROPERTIES\n    objectSchemas = objectSchemas\n      .filter(\n        (flat) =>\n          flat.escaped.properties !== undefined &&\n          flat.escaped.required !== undefined,\n      )\n      .map(\n        (flat) =>\n          ({\n            ...flat,\n            escaped: {\n              ...flat.escaped,\n              properties: Object.fromEntries(\n                Object.entries(flat.escaped.properties ?? {}).map(\n                  ([key, value]) => [\n                    key,\n                    getFlattened({\n                      components: ctx.components,\n                      schema: value,\n                      visited: new Set(),\n                    }).escaped,\n                  ],\n                ),\n              ),\n            },\n          }) satisfies IFlatSchema<OpenApi.IJsonSchema.IObject>,\n      );\n\n    // PROPERTY MATRIX\n    const matrix: Map<string, Array<OpenApi.IJsonSchema | null>> = new Map();\n    objectSchemas.forEach((obj, i) => {\n      for (const [key, value] of Object.entries(obj.escaped.properties ?? {})) {\n        if (!!obj.escaped.required?.includes(key) === false) continue;\n        MapUtil.take(matrix)(key)(() =>\n          new Array(objectSchemas.length).fill(null),\n        )[i] = value;\n      }\n    });\n\n    // THE BRANCHES\n    return objectSchemas\n      .map((obj, i) => {\n        const candidates: string[] = [];\n        for (const [key, value] of Object.entries(\n          obj.escaped.properties ?? {},\n        )) {\n          if (!!obj.escaped.required?.includes(key) === false) continue;\n\n          const neighbors: OpenApi.IJsonSchema[] = matrix\n            .get(key)!\n            .filter((_oppo, j) => i !== j)\n            .filter((oppo) => oppo !== null);\n          const unique: boolean = OpenApiTypeChecker.isConstant(value)\n            ? neighbors.every(\n                (oppo) =>\n                  OpenApiTypeChecker.isConstant(oppo) &&\n                  value.const !== oppo.const,\n              )\n            : neighbors.length === 0;\n          if (unique) candidates.push(key);\n        }\n        if (candidates.length === 0) return null;\n        const top: string =\n          candidates.find((key) =>\n            OpenApiTypeChecker.isConstant(obj.escaped.properties![key]),\n          ) ?? candidates[0];\n        const target: OpenApi.IJsonSchema = obj.escaped.properties![top];\n        return {\n          schema: obj.schema,\n          predicator: OpenApiTypeChecker.isConstant(target)\n            ? (value) =>\n                typeof value === \"object\" &&\n                value !== null &&\n                (value as any)[top] === target.const\n            : (value) =>\n                typeof value === \"object\" &&\n                value !== null &&\n                (value as any)[top] !== undefined,\n        } satisfies IDiscriminatorBranch;\n      })\n      .filter((b) => b !== null);\n  };\n}\n\nconst getFlattened = (props: {\n  components: OpenApi.IComponents;\n  schema: OpenApi.IJsonSchema;\n  visited: Set<string>;\n}): IFlatSchema => {\n  if (OpenApiTypeChecker.isReference(props.schema)) {\n    const key: string = props.schema.$ref.split(\"/\").pop() ?? \"\";\n    if (props.visited.has(key))\n      return {\n        schema: props.schema,\n        escaped: {},\n      };\n    props.visited.add(key);\n    return {\n      ...getFlattened({\n        components: props.components,\n        schema: props.components.schemas?.[key] ?? {},\n        visited: props.visited,\n      }),\n      schema: props.schema,\n    };\n  }\n  return {\n    schema: props.schema,\n    escaped: props.schema,\n  };\n};\n\ninterface IDiscriminator {\n  branches: IDiscriminatorBranch[];\n  remainders: OpenApi.IJsonSchema[];\n}\n\ninterface IDiscriminatorBranch {\n  schema: OpenApi.IJsonSchema;\n  predicator: (value: unknown) => boolean;\n}\n\ninterface IFlatSchema<\n  Schema extends OpenApi.IJsonSchema = OpenApi.IJsonSchema,\n> {\n  schema: OpenApi.IJsonSchema;\n  escaped: Schema;\n}\n"],"names":["OpenApiOneOfValidator","validate","ctx","discriminator","getDiscriminator","item","branches","predicator","value","OpenApiStationValidator","schema","length","oneOf","remainders","matched","find","exceptionable","equals","undefined","report","resolvedList","map","getFlattened","components","visited","Set","anything","resolved","OpenApiTypeChecker","isUnknown","escaped","nullables","filter","isNull","significant","nullable","tuples","flat","isTuple","arrays","isArray","discriminateArrays","discriminateObjects","isObject","x","some","y","arraySchemas","Array","i","array","every","j","covers","items","path","objectSchemas","noArray","properties","required","Object","fromEntries","entries","key","matrix","Map","forEach","obj","includes","MapUtil","take","fill","candidates","neighbors","get","_oppo","oppo","unique","isConstant","const","push","top","target","b","props","isReference","$ref","split","pop","has","add","schemas"],"mappings":"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"}