{"version":3,"file":"NestiaSimulator.mjs","names":[],"sources":["../src/NestiaSimulator.ts"],"sourcesContent":["import { HttpError } from \"./HttpError\";\nimport { join_host_and_path } from \"./internal/join_host_and_path\";\n\n/**\n * Request validation for the mockup simulator of a generated SDK.\n *\n * A simulated function does not call a server. It validates its input with\n * typia and, when the input is wrong, throws the `HttpError` with status 400\n * that the real server would answer with.\n *\n * @evidence contracts/common.md#principled-implementation Each validator runs the caller's assertion and converts a readable typia `TypeGuardError` shape into an `HttpError` 400 whose JSON body carries the method, path, expected type and value plus a message naming the failing part. A shared snapshot reads each needed property once; malformed or unreadable shapes rethrow the caller's original value. Payload values must support JSON serialization, whose errors still propagate.\n * @evidence contracts/common.md#clear-and-simple-design One public entry point, `assert`, returns four validators that differ only in their message, sharing one private conversion; the shape snapshot reader and the error interface are module-private.\n * @evidence contracts/common.md#prohibited-implementation-shortcuts Classification checks the readable error structure (method, path, expected type, name, message and stack) rather than its class, then captures the payload value. A value that lacks any of those fields with the expected types, or whose property access throws, is not classified as a type guard failure and is rethrown unchanged; unrelated task errors are neither replaced nor swallowed.\n * @evidence contracts/common.md#meaningful-documentation The comment states what the simulator validates and what it throws.\n */\nexport namespace NestiaSimulator {\n  /**\n   * Route facts the simulator needs to build its 400 error: the host, the path,\n   * and the method.\n   *\n   * `contentType` is the content type of the route's success response, which\n   * the generated code answers with; the simulated 400 is JSON whatever it is.\n   *\n   * @evidence contracts/common.md#principled-implementation The host, path, and method identify the request in the error, and the content type describes the success response of the generated function, which the generated code answers with.\n   * @evidence contracts/common.md#clear-and-simple-design A four-field record with no behavior.\n   * @evidence contracts/common.md#prohibited-implementation-shortcuts The values are supplied by the generated SDK for its own route.\n   * @evidence contracts/common.md#meaningful-documentation The comment says what each part is used for, with the `contentType` member documenting when it is `null`.\n   */\n  export interface IProps {\n    host: string;\n    path: string;\n    method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\" | \"HEAD\";\n\n    /**\n     * Content type of the route's success response, `null` for one without a\n     * body such as `HEAD`'s. The simulated 400 is JSON whatever it is, as the\n     * server's is.\n     */\n    contentType: string | null;\n  }\n\n  /**\n   * Creates the validators of one simulated route: `param(name)`, `query`,\n   * `body`, and `headers`.\n   *\n   * Each validator takes the closure that performs the typia assertion. A\n   * failed assertion throws an `HttpError` with status 400 and a JSON body; any\n   * other error is rethrown as it is.\n   *\n   * @evidence contracts/common.md#principled-implementation The four validators share the conversion in `validate` and differ in the message they attach, which names the URL parameter or states that the query, body, or headers do not follow the promised type.\n   * @evidence contracts/common.md#clear-and-simple-design One function returning the four validators as an object, so a generated simulator has one import.\n   * @evidence contracts/common.md#prohibited-implementation-shortcuts The HTTP error is the one the real server returns; nothing is simulated beyond running the assertion.\n   * @evidence contracts/common.md#meaningful-documentation The comment states what it returns and what each validator throws.\n   */\n  export const assert = (props: IProps) => {\n    return {\n      param: param(props),\n      query: query(props),\n      body: body(props),\n      headers: headers(props),\n    };\n  };\n  const param =\n    (props: IProps) =>\n    (name: string) =>\n    <T>(task: () => T): void => {\n      validate((exp) => `URL parameter \"${name}\" is not ${exp.expected} type.`)(\n        props,\n      )(task);\n    };\n\n  const query =\n    (props: IProps) =>\n    <T>(task: () => T): void =>\n      validate(\n        () => \"Request query parameters are not following the promised type.\",\n      )(props)(task);\n\n  const body =\n    (props: IProps) =>\n    <T>(task: () => T): void =>\n      validate(() => \"Request body is not following the promised type.\")(props)(\n        task,\n      );\n\n  const headers =\n    (props: IProps) =>\n    <T>(task: () => T): void =>\n      validate(() => \"Request headers are not following the promised type.\")(\n        props,\n      )(task);\n\n  const validate =\n    (message: (exp: TypeGuardError) => string) =>\n    (props: IProps) =>\n    <T>(task: () => T): void => {\n      try {\n        task();\n      } catch (exp) {\n        const guard: TypeGuardError | null = readTypeGuardError(exp);\n        if (guard !== null)\n          throw new HttpError(\n            props.method,\n            join_host_and_path(props.host, props.path),\n            400,\n            {\n              \"Content-Type\": \"application/json\",\n            },\n            JSON.stringify({\n              method: guard.method,\n              path: guard.path,\n              expected: guard.expected,\n              value: guard.value,\n              message: message(guard),\n            }),\n          );\n        throw exp;\n      }\n    };\n}\n\nconst readTypeGuardError = (input: any): TypeGuardError | null => {\n  if (typeof input !== \"object\" || input === null) return null;\n  try {\n    const method: unknown = input.method;\n    if (typeof method !== \"string\") return null;\n    const path: unknown = input.path;\n    if (path !== undefined && typeof path !== \"string\") return null;\n    const expected: unknown = input.expected;\n    if (typeof expected !== \"string\") return null;\n    const name: unknown = input.name;\n    if (typeof name !== \"string\") return null;\n    const message: unknown = input.message;\n    if (typeof message !== \"string\") return null;\n    const stack: unknown = input.stack;\n    if (stack !== undefined && typeof stack !== \"string\") return null;\n    const value: unknown = input.value;\n    return { method, path, expected, name, message, stack, value };\n  } catch {\n    return null;\n  }\n};\n\ninterface TypeGuardError extends Error {\n  method: string;\n  path: string | undefined;\n  expected: string;\n  value: any;\n}\n"],"mappings":";;;AAeO,IAAA;;4BAuCkB,UAAkB;EACvC,OAAO;GACL,OAAO,MAAM,KAAK;GAClB,OAAO,MAAM,KAAK;GAClB,MAAM,KAAK,KAAK;GAChB,SAAS,QAAQ,KAAK;EACxB;CACF;CACA,MAAM,SACH,WACA,UACG,SAAwB;EAC1B,UAAU,QAAQ,kBAAkB,KAAK,WAAW,IAAI,SAAS,OAAO,CAAC,CACvE,KACF,CAAC,CAAC,IAAI;CACR;CAEF,MAAM,SACH,WACG,SACF,eACQ,+DACR,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI;CAEjB,MAAM,QACH,WACG,SACF,eAAe,kDAAkD,CAAC,CAAC,KAAK,CAAC,CACvE,IACF;CAEJ,MAAM,WACH,WACG,SACF,eAAe,sDAAsD,CAAC,CACpE,KACF,CAAC,CAAC,IAAI;CAEV,MAAM,YACH,aACA,WACG,SAAwB;EAC1B,IAAI;GACF,KAAK;EACP,SAAS,KAAK;GACZ,MAAM,QAA+B,mBAAmB,GAAG;GAC3D,IAAI,UAAU,MACZ,MAAM,IAAI,UACR,MAAM,QACN,mBAAmB,MAAM,MAAM,MAAM,IAAI,GACzC,KACA,EACE,gBAAgB,mBAClB,GACA,KAAK,UAAU;IACb,QAAQ,MAAM;IACd,MAAM,MAAM;IACZ,UAAU,MAAM;IAChB,OAAO,MAAM;IACb,SAAS,QAAQ,KAAK;GACxB,CAAC,CACH;GACF,MAAM;EACR;CACF;GACH,oBAAA,kBAAA,CAAA,EAAD;AAEA,MAAM,sBAAsB,UAAsC;CAChE,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,IAAI;EACF,MAAM,SAAkB,MAAM;EAC9B,IAAI,OAAO,WAAW,UAAU,OAAO;EACvC,MAAM,OAAgB,MAAM;EAC5B,IAAI,SAAS,KAAA,KAAa,OAAO,SAAS,UAAU,OAAO;EAC3D,MAAM,WAAoB,MAAM;EAChC,IAAI,OAAO,aAAa,UAAU,OAAO;EACzC,MAAM,OAAgB,MAAM;EAC5B,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,MAAM,UAAmB,MAAM;EAC/B,IAAI,OAAO,YAAY,UAAU,OAAO;EACxC,MAAM,QAAiB,MAAM;EAC7B,IAAI,UAAU,KAAA,KAAa,OAAO,UAAU,UAAU,OAAO;EAE7D,OAAO;GAAE;GAAQ;GAAM;GAAU;GAAM;GAAS;GAAO,OADhC,MAAM;EACgC;CAC/D,QAAQ;EACN,OAAO;CACT;AACF"}