{"version":3,"sources":["../../src/api-envelope.ts","../../src/lib/internal/error-envelope-send.ts","../../src/lib/api-envelope/response-helpers.ts"],"sourcesContent":["export * from './lib/api-envelope/api-envelope-types';\nexport * from './lib/api-envelope/response-helpers';\n","import type { FastifyRequest, FastifyReply } from 'fastify';\nimport type { OutgoingHttpHeaders } from 'node:http';\nimport type {\n  APIErrorResponse,\n  BaseMeta,\n  PageErrorResponse,\n} from '../api-envelope/api-envelope-types';\n\n/**\n * Sends an error envelope immediately via the raw/hijacked response path.\n *\n * This is shared by controlled reply wrappers and the public helper fallback so\n * both paths apply the same CORS/header logic before writing the final JSON\n * body directly to the socket.\n */\nexport async function sendRawErrorEnvelopeResponse(\n  request: FastifyRequest,\n  reply: FastifyReply,\n  statusCode: number,\n  errorResponse: APIErrorResponse<BaseMeta> | PageErrorResponse<BaseMeta>,\n): Promise<void> {\n  const body = JSON.stringify(errorResponse);\n\n  // Raw/hijacked sends bypass Fastify's normal onSend pipeline, so any\n  // plugin-managed headers that still matter here must be applied explicitly\n  // before we snapshot reply.getHeaders() for writeHead(). Keep this ahead of\n  // reply.hijack() so header-application failures still propagate through\n  // Fastify's normal error handling instead of failing after raw ownership has\n  // already been taken.\n  await request.applyCORSHeaders?.(reply);\n\n  // Keep Fastify's reply state aligned with the status/content-type we are\n  // about to send even though the final body write happens on reply.raw.\n  reply.code(statusCode);\n  reply.type('application/json; charset=utf-8');\n  reply.header('Content-Length', String(Buffer.byteLength(body)));\n\n  // Hijack before writeHead() so Fastify does not attempt its own send path\n  // after this helper has already fully terminated the response.\n  reply.hijack();\n  reply.raw.writeHead(statusCode, reply.getHeaders() as OutgoingHttpHeaders);\n\n  // Error envelopes are always JSON here, so a single buffered end() keeps the\n  // transport simple and makes the termination point explicit.\n  reply.raw.end(request.method === 'HEAD' ? undefined : body);\n}\n","import type { FastifyRequest, FastifyReply } from 'fastify';\nimport type {\n  ErrorDetailsValue,\n  BaseMeta,\n  APIErrorResponse,\n  APISuccessResponse,\n  PageErrorResponse,\n  PageSuccessResponse,\n  PageRedirectResponse,\n  RedirectInfo,\n  PageMetadata,\n  APIResponseEnvelope,\n  PageResponseEnvelope,\n} from './api-envelope-types';\nimport type { ControlledReply } from '../types';\nimport { sendRawErrorEnvelopeResponse } from '../internal/error-envelope-send';\n\n/**\n * Helper utilities for constructing API/Page response envelopes.\n *\n * These are static so the class can be easily subclassed or the methods can be\n * re-exported. Users may extend this class to inject their own default meta or\n * wrap additional logic (e.g., account metadata, logging, etc.).\n */\nexport class APIResponseHelpers {\n  // API Response Helpers\n\n  /**\n   * Creates a standardized API success response envelope for API (AJAX/JSON) endpoints.\n   *\n   * @typeParam T - The type of the response data payload.\n   * @typeParam M - Meta type that extends BaseMeta.\n   *   Allows consumers to add application specific meta keys\n   *   (e.g. `account`, `pagination`, etc.).\n   * @param params - Object containing request, data, statusCode (default 200), and optional meta.\n   * @returns An APISuccessResponse envelope with merged meta and a request_id.\n   */\n\n  public static createAPISuccessResponse<\n    T,\n    M extends BaseMeta = BaseMeta,\n  >(params: {\n    request: FastifyRequest;\n    data: T;\n    statusCode?: number;\n    meta?: Partial<M>;\n  }): APISuccessResponse<T, M> {\n    const { request, data, statusCode = 200, meta } = params;\n\n    // API responses should not include page metadata by default\n    // Only include meta if explicitly provided\n    const defaultMeta = {} as M;\n\n    const receivedAt = (request as { receivedAt?: number }).receivedAt;\n\n    return {\n      status: 'success',\n      status_code: statusCode,\n      request_id: (request as { requestID?: string }).requestID ?? 'unknown',\n      ...(receivedAt !== undefined\n        ? { request_timestamp: new Date(receivedAt).toISOString() }\n        : {}),\n      type: 'api',\n      data,\n      meta: { ...defaultMeta, ...(meta as Partial<M>) } as M,\n    };\n  }\n\n  /**\n   * Creates a standardized API error response envelope for API (AJAX/JSON) endpoints.\n   *\n   * @typeParam M - Meta type that extends BaseMeta.\n   *   Allows consumers to add application specific meta keys\n   *   (e.g. `account`, `pagination`, etc.).\n   * @param params - Object containing request, statusCode, errorCode, errorMessage, optional errorDetails, and optional meta.\n   * @returns An APIErrorResponse envelope with merged meta and a request_id.\n   */\n  public static createAPIErrorResponse<M extends BaseMeta = BaseMeta>(params: {\n    request: FastifyRequest;\n    statusCode: number;\n    errorCode: string;\n    errorMessage: string;\n    errorDetails?: ErrorDetailsValue;\n    meta?: Partial<M>;\n  }): APIErrorResponse<M> {\n    const { request, statusCode, errorCode, errorMessage, errorDetails, meta } =\n      params;\n\n    // API responses should not include page metadata by default\n    // Only include meta if explicitly provided\n    const defaultMeta = {} as M;\n\n    const receivedAt = (request as { receivedAt?: number }).receivedAt;\n\n    return {\n      status: 'error',\n      status_code: statusCode,\n      request_id: (request as { requestID?: string }).requestID ?? 'unknown',\n      ...(receivedAt !== undefined\n        ? { request_timestamp: new Date(receivedAt).toISOString() }\n        : {}),\n      type: 'api',\n      data: null,\n      meta: { ...defaultMeta, ...(meta as Partial<M>) } as M,\n      error: {\n        code: errorCode,\n        message: errorMessage,\n        ...(errorDetails && { details: errorDetails }),\n      },\n    };\n  }\n\n  // Page Response Helpers\n\n  /**\n   * Creates a standardized Page success response envelope for SSR/data loaders.\n   *\n   * @typeParam T - The type of the response data payload.\n   * @typeParam M - Meta type that extends BaseMeta.\n   *   Allows consumers to add application specific meta keys\n   *   (e.g. `account`, `pagination`, etc.).\n   * @param params - Object containing request, data, pageMetadata, statusCode (default 200), and optional meta.\n   * @returns A PageSuccessResponse envelope with merged meta and a request_id.\n   */\n  public static createPageSuccessResponse<\n    T,\n    M extends BaseMeta = BaseMeta,\n  >(params: {\n    request: FastifyRequest;\n    data: T;\n    pageMetadata: PageMetadata;\n    statusCode?: number;\n    meta?: Partial<M>;\n  }): PageSuccessResponse<T, M> {\n    const { request, data, pageMetadata, statusCode = 200, meta } = params;\n\n    const baseMeta: BaseMeta = {\n      page: pageMetadata,\n    };\n\n    // Auto-populate ssr_request_context from request.requestContext if available and non-empty\n    const requestContext = (\n      request as { requestContext?: Record<string, unknown> }\n    ).requestContext;\n\n    const receivedAt = (request as { receivedAt?: number }).receivedAt;\n\n    return {\n      status: 'success',\n      status_code: statusCode,\n      request_id: (request as { requestID?: string }).requestID ?? 'unknown',\n      ...(receivedAt !== undefined\n        ? { request_timestamp: new Date(receivedAt).toISOString() }\n        : {}),\n      type: 'page',\n      data,\n      meta: { ...(baseMeta as M), ...(meta as Partial<M>) } as M,\n      ...(requestContext &&\n      typeof requestContext === 'object' &&\n      !Array.isArray(requestContext) &&\n      Object.keys(requestContext).length > 0\n        ? { ssr_request_context: requestContext }\n        : {}),\n    };\n  }\n\n  /**\n   * Creates a standardized Page redirect response envelope for SSR/data loaders.\n   * Always uses status code 200 to avoid confusion with HTTP redirects.\n   *\n   * @typeParam M - Meta type that extends BaseMeta.\n   *   Allows consumers to add application specific meta keys.\n   * @param params - Object containing request, redirectInfo, pageMetadata, and optional meta.\n   * @returns A PageRedirectResponse envelope with merged meta and a request_id.\n   */\n  public static createPageRedirectResponse<\n    M extends BaseMeta = BaseMeta,\n  >(params: {\n    request: FastifyRequest;\n    redirectInfo: RedirectInfo;\n    pageMetadata: PageMetadata;\n    meta?: Partial<M>;\n  }): PageRedirectResponse<M> {\n    const { request, redirectInfo, pageMetadata, meta } = params;\n\n    const baseMeta: BaseMeta = {\n      page: pageMetadata,\n    };\n\n    // Auto-populate ssr_request_context from request.requestContext if available and non-empty\n    const requestContext = (\n      request as { requestContext?: Record<string, unknown> }\n    ).requestContext;\n\n    const receivedAt = (request as { receivedAt?: number }).receivedAt;\n\n    return {\n      status: 'redirect',\n      status_code: 200,\n      request_id: (request as { requestID?: string }).requestID ?? 'unknown',\n      ...(receivedAt !== undefined\n        ? { request_timestamp: new Date(receivedAt).toISOString() }\n        : {}),\n      type: 'page',\n      data: null,\n      meta: { ...(baseMeta as M), ...(meta as Partial<M>) } as M,\n      redirect: redirectInfo,\n      ...(requestContext &&\n      typeof requestContext === 'object' &&\n      !Array.isArray(requestContext) &&\n      Object.keys(requestContext).length > 0\n        ? { ssr_request_context: requestContext }\n        : {}),\n    };\n  }\n\n  /**\n   * Creates a standardized Page error response envelope for SSR/data loaders.\n   *\n   * @typeParam M - Meta type that extends BaseMeta.\n   *   Allows consumers to add application specific meta keys\n   *   (e.g. `account`, `pagination`, etc.).\n   * @param params - Object containing request, statusCode, errorCode, errorMessage,\n   *   optional errorDetails, pageMetadata, and optional meta.\n   * @returns A PageErrorResponse envelope with merged meta and a request_id.\n   */\n\n  public static createPageErrorResponse<M extends BaseMeta = BaseMeta>(params: {\n    request: FastifyRequest;\n    statusCode: number;\n    errorCode: string;\n    errorMessage: string;\n    errorDetails?: ErrorDetailsValue;\n    pageMetadata: PageMetadata;\n    meta?: Partial<M>;\n  }): PageErrorResponse<M> {\n    const {\n      request,\n      statusCode,\n      errorCode,\n      errorMessage,\n      pageMetadata,\n      errorDetails,\n      meta,\n    } = params;\n\n    const baseMeta: BaseMeta = {\n      page: pageMetadata,\n    };\n\n    // Auto-populate ssr_request_context from request.requestContext if available and non-empty\n    const requestContext = (\n      request as { requestContext?: Record<string, unknown> }\n    ).requestContext;\n\n    const receivedAt = (request as { receivedAt?: number }).receivedAt;\n\n    return {\n      status: 'error',\n      status_code: statusCode,\n      request_id: (request as { requestID?: string }).requestID ?? 'unknown',\n      ...(receivedAt !== undefined\n        ? { request_timestamp: new Date(receivedAt).toISOString() }\n        : {}),\n      type: 'page',\n      data: null,\n      meta: { ...(baseMeta as M), ...(meta as Partial<M>) } as M,\n      error: {\n        code: errorCode,\n        message: errorMessage,\n        ...(errorDetails && { details: errorDetails }),\n      },\n      ...(requestContext &&\n      typeof requestContext === 'object' &&\n      !Array.isArray(requestContext) &&\n      Object.keys(requestContext).length > 0\n        ? { ssr_request_context: requestContext }\n        : {}),\n    };\n  }\n\n  // Validation Helpers\n\n  /**\n   * Send an error envelope response with the appropriate method\n   * Works with both FastifyReply and ControlledReply\n   *\n   * This is a public utility for sending error responses in a way that works\n   * with both standard Fastify handlers and controlled reply handlers.\n   *\n   * @param reply - Fastify reply object or ControlledReply\n   * @param statusCode - HTTP status code to send\n   * @param errorResponse - Error envelope to send\n   *\n   * @example\n   * ```typescript\n   * const errorResponse = APIResponseHelpers.createAPIErrorResponse({\n   *   request,\n   *   statusCode: 400,\n   *   errorCode: 'invalid_input',\n   *   errorMessage: 'Invalid input provided',\n   * });\n   *\n   * await APIResponseHelpers.sendErrorEnvelope(\n   *   request,\n   *   reply,\n   *   400,\n   *   errorResponse,\n   * );\n   * ```\n   *\n   * This helper is usable directly, but it is also part of the framework's\n   * controlled early-termination path. Unlike the envelope creation helpers,\n   * it has transport semantics (shared headers, hijack/raw write, immediate\n   * response finalization), so overriding it in a custom helpers subclass is\n   * discouraged unless you intend to preserve that contract.\n   */\n  public static async sendErrorEnvelope(\n    request: FastifyRequest,\n    reply: FastifyReply | ControlledReply,\n    statusCode: number,\n    errorResponse: APIErrorResponse<BaseMeta> | PageErrorResponse<BaseMeta>,\n  ): Promise<void> {\n    // Controlled handlers are intentionally not given general-purpose send\n    // methods. When the framework wrapped the reply, use its internal\n    // _sendErrorEnvelope hook; otherwise fall back to the shared raw-send path\n    // for direct FastifyReply usage (including tests and non-controlled routes).\n    if ('_sendErrorEnvelope' in reply) {\n      await reply._sendErrorEnvelope(statusCode, errorResponse);\n      return;\n    }\n\n    await sendRawErrorEnvelopeResponse(\n      request,\n      reply,\n      statusCode,\n      errorResponse,\n    );\n  }\n\n  /**\n   * Ensures an incoming Fastify request has a valid JSON body.\n   * If invalid, sends a standardized error response and returns false.\n   *\n   * Use this helper for POST, PUT, PATCH, and DELETE endpoints that expect JSON payloads.\n   * This is a pre-validation convenience before using schema validators like Zod.\n   *\n   * @param request - Fastify request object\n   * @param reply - Fastify reply object or ControlledReply\n   * @returns true if body is valid JSON, otherwise false (error envelope already sent)\n   *\n   * @example\n   * ```typescript\n   * server.api.post('users', async (request, reply) => {\n   *   if (!(await APIResponseHelpers.ensureJSONBody(request, reply))) {\n   *     return false; // Error envelope already sent\n   *   }\n   *\n   *   // Now safe to validate using a schema validator (e.g. Zod) or process the body\n   *   const validated = userSchema.parse(request.body);\n   *   // ...\n   * });\n   * ```\n   */\n  public static async ensureJSONBody(\n    request: FastifyRequest,\n    reply: FastifyReply | ControlledReply,\n  ): Promise<boolean> {\n    // Check Content-Type header first\n    const contentType = request.headers['content-type'];\n\n    if (!contentType || !contentType.includes('application/json')) {\n      const errorResponse = this.createAPIErrorResponse({\n        request,\n        statusCode: 415, // Unsupported Media Type\n        errorCode: 'invalid_content_type',\n        errorMessage: 'Content-Type must be application/json',\n        errorDetails: {\n          received_content_type: contentType || 'none',\n          expected_content_type: 'application/json',\n        },\n      });\n\n      // Send the standardized error envelope and terminate early.\n      await this.sendErrorEnvelope(request, reply, 415, errorResponse);\n      return false;\n    }\n\n    // Then validate the parsed body exists and is an object\n    if (!request.body || typeof request.body !== 'object') {\n      const errorResponse = this.createAPIErrorResponse({\n        request,\n        statusCode: 400,\n        errorCode: 'invalid_request_body_format',\n        errorMessage:\n          'Request body is required and must be a valid JSON object',\n        errorDetails: {\n          received_body_type: typeof request.body,\n        },\n      });\n\n      // Send the standardized error envelope and terminate early.\n      await this.sendErrorEnvelope(request, reply, 400, errorResponse);\n      return false;\n    }\n\n    return true;\n  }\n\n  /**\n   * Ensures an incoming Fastify request has a valid URL-encoded form body.\n   * If invalid, sends a standardized error response and returns false.\n   *\n   * Use this helper for POST, PUT, or PATCH endpoints that expect URL-encoded form data.\n   * This is a pre-validation convenience before processing form fields.\n   *\n   * Note: For file uploads with multipart/form-data, use ensureMultipartBody instead.\n   *\n   * @param request - Fastify request object\n   * @param reply - Fastify reply object or ControlledReply\n   * @returns true if form body is valid, otherwise false (error envelope already sent)\n   *\n   * @example\n   * ```typescript\n   * server.api.post('contact', async (request, reply) => {\n   *   if (!(await APIResponseHelpers.ensureURLEncodedBody(request, reply))) {\n   *     return false; // Error envelope already sent\n   *   }\n   *\n   *   // Now safe to process form fields\n   *   const formData = request.body as Record<string, unknown>;\n   *   // ...\n   * });\n   * ```\n   */\n  public static async ensureURLEncodedBody(\n    request: FastifyRequest,\n    reply: FastifyReply | ControlledReply,\n  ): Promise<boolean> {\n    // Check Content-Type header first\n    const contentType = request.headers['content-type'];\n\n    if (\n      !contentType ||\n      !contentType.includes('application/x-www-form-urlencoded')\n    ) {\n      const errorResponse = this.createAPIErrorResponse({\n        request,\n        statusCode: 415, // Unsupported Media Type\n        errorCode: 'invalid_content_type',\n        errorMessage: 'Content-Type must be application/x-www-form-urlencoded',\n        errorDetails: {\n          received_content_type: contentType || 'none',\n          expected_content_type: 'application/x-www-form-urlencoded',\n        },\n      });\n\n      // Send the standardized error envelope and terminate early.\n      await this.sendErrorEnvelope(request, reply, 415, errorResponse);\n      return false;\n    }\n\n    // Validate the parsed body exists and is an object\n    if (!request.body || typeof request.body !== 'object') {\n      const errorResponse = this.createAPIErrorResponse({\n        request,\n        statusCode: 400,\n        errorCode: 'invalid_request_body_format',\n        errorMessage:\n          'Request body is required and must be valid URL-encoded form data',\n        errorDetails: {\n          received_body_type: typeof request.body,\n        },\n      });\n\n      // Send the standardized error envelope and terminate early.\n      await this.sendErrorEnvelope(request, reply, 400, errorResponse);\n      return false;\n    }\n\n    return true;\n  }\n\n  /**\n   * Ensures an incoming Fastify request has multipart/form-data Content-Type.\n   * If invalid, sends a standardized error response and returns false.\n   *\n   * **Note:** `processFileUpload()` automatically validates Content-Type,\n   * so you typically don't need this helper when using `processFileUpload()`.\n   *\n   * **Advanced use case:** Use this for early validation in middleware (e.g., auth/rate-limiting)\n   * before multipart parsing begins:\n   *\n   * ```typescript\n   * // Block uploads for non-premium users before parsing\n   * pluginHost.addHook('preHandler', async (request, reply) => {\n   *   if (request.headers['content-type']?.includes('multipart/form-data')) {\n   *     if (!user.isPremium) {\n   *       return reply.code(403).send({ error: 'Premium feature' });\n   *     }\n   *   }\n   * });\n   * ```\n   *\n   * For standard file uploads, use `processFileUpload()` instead:\n   * ```typescript\n   * import { processFileUpload } from 'unirend/server';\n   *\n   * const results = await processFileUpload({\n   *   request,\n   *   reply,\n   *   maxSizePerFile: 5 * 1024 * 1024,\n   *   allowedMimeTypes: ['image/jpeg', 'image/png'],\n   *   processor: async (stream, metadata, context) => {\n   *     // ... handle upload\n   *   },\n   * });\n   * ```\n   *\n   * @param request - Fastify request object\n   * @param reply - Fastify reply object or ControlledReply\n   * @returns true if Content-Type is multipart/form-data, otherwise false (error envelope already sent)\n   *\n   */\n  public static async ensureMultipartBody(\n    request: FastifyRequest,\n    reply: FastifyReply | ControlledReply,\n  ): Promise<boolean> {\n    // Check Content-Type header\n    const contentType = request.headers['content-type'];\n\n    if (!contentType || !contentType.includes('multipart/form-data')) {\n      const errorResponse = this.createAPIErrorResponse({\n        request,\n        statusCode: 415, // Unsupported Media Type\n        errorCode: 'invalid_content_type',\n        errorMessage: 'Content-Type must be multipart/form-data',\n        errorDetails: {\n          received_content_type: contentType || 'none',\n          expected_content_type: 'multipart/form-data',\n        },\n      });\n\n      // Send the standardized error envelope and terminate early.\n      await this.sendErrorEnvelope(request, reply, 415, errorResponse);\n      return false;\n    }\n\n    // Note: This helper only validates the Content-Type header.\n    // In this codebase, multipart payloads are consumed later through the\n    // streaming request.file()/request.files() APIs, so we do not validate\n    // request.body here.\n    return true;\n  }\n\n  // ---------------------------------------------------------------------------\n  // Static Type-Guard Helpers\n  // ---------------------------------------------------------------------------\n\n  /** Determines if envelope is a success response */\n  public static isSuccessResponse<T, M extends BaseMeta = BaseMeta>(\n    response: APIResponseEnvelope<T, M> | PageResponseEnvelope<T, M>,\n  ): response is APISuccessResponse<T, M> | PageSuccessResponse<T, M> {\n    return response.status === 'success';\n  }\n\n  /** Determines if envelope is an error response */\n  public static isErrorResponse<M extends BaseMeta = BaseMeta>(\n    response:\n      | APIResponseEnvelope<unknown, M>\n      | PageResponseEnvelope<unknown, M>,\n  ): response is APIErrorResponse<M> | PageErrorResponse<M> {\n    return response.status === 'error';\n  }\n\n  /** Determines if envelope is a redirect response */\n  public static isRedirectResponse<M extends BaseMeta = BaseMeta>(\n    response:\n      | APIResponseEnvelope<unknown, M>\n      | PageResponseEnvelope<unknown, M>,\n  ): response is PageRedirectResponse<M> {\n    return response.status === 'redirect';\n  }\n\n  /** Determines if envelope is a page (SSR) response */\n  public static isPageResponse<T, M extends BaseMeta = BaseMeta>(\n    response: APIResponseEnvelope<T, M> | PageResponseEnvelope<T, M>,\n  ): response is PageResponseEnvelope<T, M> {\n    return response.type === 'page';\n  }\n\n  /**\n   * Validates that an unknown value is a proper envelope object\n   * This is a catch-all validation function that checks for proper envelope structure\n   * without requiring specific typing - useful for runtime validation of handler responses\n   */\n  public static isValidEnvelope(\n    result: unknown,\n  ): result is PageResponseEnvelope | APIResponseEnvelope {\n    if (!result || typeof result !== 'object') {\n      return false;\n    }\n\n    const envelope = result as Record<string, unknown>;\n\n    // Check required fields\n    const hasStatus =\n      typeof envelope.status === 'string' &&\n      ['success', 'error', 'redirect'].includes(envelope.status);\n\n    const hasStatusCode = typeof envelope.status_code === 'number';\n\n    const hasType =\n      typeof envelope.type === 'string' &&\n      ['api', 'page'].includes(envelope.type);\n\n    const hasRequestID = typeof envelope.request_id === 'string';\n    const hasMeta = envelope.meta && typeof envelope.meta === 'object';\n\n    // Basic structure validation\n    if (!hasStatus || !hasStatusCode || !hasType || !hasRequestID || !hasMeta) {\n      return false;\n    }\n\n    // Validate meta has required page field ONLY for page type envelopes\n    // API type envelopes do not require page metadata\n    if (envelope.type === 'page') {\n      const meta = envelope.meta as Record<string, unknown>;\n\n      if (!meta.page || typeof meta.page !== 'object') {\n        return false;\n      }\n\n      const page = meta.page as Record<string, unknown>;\n\n      if (\n        typeof page.title !== 'string' ||\n        typeof page.description !== 'string'\n      ) {\n        return false;\n      }\n    }\n\n    // Status-specific validation\n    if (envelope.status === 'success') {\n      return (\n        envelope.data !== undefined &&\n        (envelope.error === undefined || envelope.error === null)\n      );\n    } else if (envelope.status === 'error') {\n      return (\n        envelope.data === null &&\n        envelope.error !== null &&\n        typeof envelope.error === 'object'\n      );\n    } else if (envelope.status === 'redirect') {\n      return (\n        envelope.data === null &&\n        (envelope.error === undefined || envelope.error === null) &&\n        envelope.redirect !== null &&\n        typeof envelope.redirect === 'object'\n      );\n    }\n\n    return false;\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACeA,eAAsB,6BACpB,SACA,OACA,YACA,eACe;AACf,QAAM,OAAO,KAAK,UAAU,aAAa;AAQzC,QAAM,QAAQ,mBAAmB,KAAK;AAItC,QAAM,KAAK,UAAU;AACrB,QAAM,KAAK,iCAAiC;AAC5C,QAAM,OAAO,kBAAkB,OAAO,OAAO,WAAW,IAAI,CAAC,CAAC;AAI9D,QAAM,OAAO;AACb,QAAM,IAAI,UAAU,YAAY,MAAM,WAAW,CAAwB;AAIzE,QAAM,IAAI,IAAI,QAAQ,WAAW,SAAS,SAAY,IAAI;AAC5D;;;ACrBO,IAAM,qBAAN,MAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAc9B,OAAc,yBAGZ,QAK2B;AAC3B,UAAM,EAAE,SAAS,MAAM,aAAa,KAAK,KAAK,IAAI;AAIlD,UAAM,cAAc,CAAC;AAErB,UAAM,aAAc,QAAoC;AAExD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,YAAa,QAAmC,aAAa;AAAA,MAC7D,GAAI,eAAe,SACf,EAAE,mBAAmB,IAAI,KAAK,UAAU,EAAE,YAAY,EAAE,IACxD,CAAC;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,MAAM,EAAE,GAAG,aAAa,GAAI,KAAoB;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAc,uBAAsD,QAO5C;AACtB,UAAM,EAAE,SAAS,YAAY,WAAW,cAAc,cAAc,KAAK,IACvE;AAIF,UAAM,cAAc,CAAC;AAErB,UAAM,aAAc,QAAoC;AAExD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,YAAa,QAAmC,aAAa;AAAA,MAC7D,GAAI,eAAe,SACf,EAAE,mBAAmB,IAAI,KAAK,UAAU,EAAE,YAAY,EAAE,IACxD,CAAC;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM,EAAE,GAAG,aAAa,GAAI,KAAoB;AAAA,MAChD,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS;AAAA,QACT,GAAI,gBAAgB,EAAE,SAAS,aAAa;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,OAAc,0BAGZ,QAM4B;AAC5B,UAAM,EAAE,SAAS,MAAM,cAAc,aAAa,KAAK,KAAK,IAAI;AAEhE,UAAM,WAAqB;AAAA,MACzB,MAAM;AAAA,IACR;AAGA,UAAM,iBACJ,QACA;AAEF,UAAM,aAAc,QAAoC;AAExD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,YAAa,QAAmC,aAAa;AAAA,MAC7D,GAAI,eAAe,SACf,EAAE,mBAAmB,IAAI,KAAK,UAAU,EAAE,YAAY,EAAE,IACxD,CAAC;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,MAAM,EAAE,GAAI,UAAgB,GAAI,KAAoB;AAAA,MACpD,GAAI,kBACJ,OAAO,mBAAmB,YAC1B,CAAC,MAAM,QAAQ,cAAc,KAC7B,OAAO,KAAK,cAAc,EAAE,SAAS,IACjC,EAAE,qBAAqB,eAAe,IACtC,CAAC;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAc,2BAEZ,QAK0B;AAC1B,UAAM,EAAE,SAAS,cAAc,cAAc,KAAK,IAAI;AAEtD,UAAM,WAAqB;AAAA,MACzB,MAAM;AAAA,IACR;AAGA,UAAM,iBACJ,QACA;AAEF,UAAM,aAAc,QAAoC;AAExD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,YAAa,QAAmC,aAAa;AAAA,MAC7D,GAAI,eAAe,SACf,EAAE,mBAAmB,IAAI,KAAK,UAAU,EAAE,YAAY,EAAE,IACxD,CAAC;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM,EAAE,GAAI,UAAgB,GAAI,KAAoB;AAAA,MACpD,UAAU;AAAA,MACV,GAAI,kBACJ,OAAO,mBAAmB,YAC1B,CAAC,MAAM,QAAQ,cAAc,KAC7B,OAAO,KAAK,cAAc,EAAE,SAAS,IACjC,EAAE,qBAAqB,eAAe,IACtC,CAAC;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAc,wBAAuD,QAQ5C;AACvB,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI;AAEJ,UAAM,WAAqB;AAAA,MACzB,MAAM;AAAA,IACR;AAGA,UAAM,iBACJ,QACA;AAEF,UAAM,aAAc,QAAoC;AAExD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,YAAa,QAAmC,aAAa;AAAA,MAC7D,GAAI,eAAe,SACf,EAAE,mBAAmB,IAAI,KAAK,UAAU,EAAE,YAAY,EAAE,IACxD,CAAC;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM,EAAE,GAAI,UAAgB,GAAI,KAAoB;AAAA,MACpD,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS;AAAA,QACT,GAAI,gBAAgB,EAAE,SAAS,aAAa;AAAA,MAC9C;AAAA,MACA,GAAI,kBACJ,OAAO,mBAAmB,YAC1B,CAAC,MAAM,QAAQ,cAAc,KAC7B,OAAO,KAAK,cAAc,EAAE,SAAS,IACjC,EAAE,qBAAqB,eAAe,IACtC,CAAC;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsCA,aAAoB,kBAClB,SACA,OACA,YACA,eACe;AAKf,QAAI,wBAAwB,OAAO;AACjC,YAAM,MAAM,mBAAmB,YAAY,aAAa;AACxD;AAAA,IACF;AAEA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,aAAoB,eAClB,SACA,OACkB;AAElB,UAAM,cAAc,QAAQ,QAAQ,cAAc;AAElD,QAAI,CAAC,eAAe,CAAC,YAAY,SAAS,kBAAkB,GAAG;AAC7D,YAAM,gBAAgB,KAAK,uBAAuB;AAAA,QAChD;AAAA,QACA,YAAY;AAAA;AAAA,QACZ,WAAW;AAAA,QACX,cAAc;AAAA,QACd,cAAc;AAAA,UACZ,uBAAuB,eAAe;AAAA,UACtC,uBAAuB;AAAA,QACzB;AAAA,MACF,CAAC;AAGD,YAAM,KAAK,kBAAkB,SAAS,OAAO,KAAK,aAAa;AAC/D,aAAO;AAAA,IACT;AAGA,QAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,UAAU;AACrD,YAAM,gBAAgB,KAAK,uBAAuB;AAAA,QAChD;AAAA,QACA,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,cACE;AAAA,QACF,cAAc;AAAA,UACZ,oBAAoB,OAAO,QAAQ;AAAA,QACrC;AAAA,MACF,CAAC;AAGD,YAAM,KAAK,kBAAkB,SAAS,OAAO,KAAK,aAAa;AAC/D,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BA,aAAoB,qBAClB,SACA,OACkB;AAElB,UAAM,cAAc,QAAQ,QAAQ,cAAc;AAElD,QACE,CAAC,eACD,CAAC,YAAY,SAAS,mCAAmC,GACzD;AACA,YAAM,gBAAgB,KAAK,uBAAuB;AAAA,QAChD;AAAA,QACA,YAAY;AAAA;AAAA,QACZ,WAAW;AAAA,QACX,cAAc;AAAA,QACd,cAAc;AAAA,UACZ,uBAAuB,eAAe;AAAA,UACtC,uBAAuB;AAAA,QACzB;AAAA,MACF,CAAC;AAGD,YAAM,KAAK,kBAAkB,SAAS,OAAO,KAAK,aAAa;AAC/D,aAAO;AAAA,IACT;AAGA,QAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,UAAU;AACrD,YAAM,gBAAgB,KAAK,uBAAuB;AAAA,QAChD;AAAA,QACA,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,cACE;AAAA,QACF,cAAc;AAAA,UACZ,oBAAoB,OAAO,QAAQ;AAAA,QACrC;AAAA,MACF,CAAC;AAGD,YAAM,KAAK,kBAAkB,SAAS,OAAO,KAAK,aAAa;AAC/D,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2CA,aAAoB,oBAClB,SACA,OACkB;AAElB,UAAM,cAAc,QAAQ,QAAQ,cAAc;AAElD,QAAI,CAAC,eAAe,CAAC,YAAY,SAAS,qBAAqB,GAAG;AAChE,YAAM,gBAAgB,KAAK,uBAAuB;AAAA,QAChD;AAAA,QACA,YAAY;AAAA;AAAA,QACZ,WAAW;AAAA,QACX,cAAc;AAAA,QACd,cAAc;AAAA,UACZ,uBAAuB,eAAe;AAAA,UACtC,uBAAuB;AAAA,QACzB;AAAA,MACF,CAAC;AAGD,YAAM,KAAK,kBAAkB,SAAS,OAAO,KAAK,aAAa;AAC/D,aAAO;AAAA,IACT;AAMA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,kBACZ,UACkE;AAClE,WAAO,SAAS,WAAW;AAAA,EAC7B;AAAA;AAAA,EAGA,OAAc,gBACZ,UAGwD;AACxD,WAAO,SAAS,WAAW;AAAA,EAC7B;AAAA;AAAA,EAGA,OAAc,mBACZ,UAGqC;AACrC,WAAO,SAAS,WAAW;AAAA,EAC7B;AAAA;AAAA,EAGA,OAAc,eACZ,UACwC;AACxC,WAAO,SAAS,SAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,gBACZ,QACsD;AACtD,QAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,aAAO;AAAA,IACT;AAEA,UAAM,WAAW;AAGjB,UAAM,YACJ,OAAO,SAAS,WAAW,YAC3B,CAAC,WAAW,SAAS,UAAU,EAAE,SAAS,SAAS,MAAM;AAE3D,UAAM,gBAAgB,OAAO,SAAS,gBAAgB;AAEtD,UAAM,UACJ,OAAO,SAAS,SAAS,YACzB,CAAC,OAAO,MAAM,EAAE,SAAS,SAAS,IAAI;AAExC,UAAM,eAAe,OAAO,SAAS,eAAe;AACpD,UAAM,UAAU,SAAS,QAAQ,OAAO,SAAS,SAAS;AAG1D,QAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,WAAW,CAAC,gBAAgB,CAAC,SAAS;AACzE,aAAO;AAAA,IACT;AAIA,QAAI,SAAS,SAAS,QAAQ;AAC5B,YAAM,OAAO,SAAS;AAEtB,UAAI,CAAC,KAAK,QAAQ,OAAO,KAAK,SAAS,UAAU;AAC/C,eAAO;AAAA,MACT;AAEA,YAAM,OAAO,KAAK;AAElB,UACE,OAAO,KAAK,UAAU,YACtB,OAAO,KAAK,gBAAgB,UAC5B;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAGA,QAAI,SAAS,WAAW,WAAW;AACjC,aACE,SAAS,SAAS,WACjB,SAAS,UAAU,UAAa,SAAS,UAAU;AAAA,IAExD,WAAW,SAAS,WAAW,SAAS;AACtC,aACE,SAAS,SAAS,QAClB,SAAS,UAAU,QACnB,OAAO,SAAS,UAAU;AAAA,IAE9B,WAAW,SAAS,WAAW,YAAY;AACzC,aACE,SAAS,SAAS,SACjB,SAAS,UAAU,UAAa,SAAS,UAAU,SACpD,SAAS,aAAa,QACtB,OAAO,SAAS,aAAa;AAAA,IAEjC;AAEA,WAAO;AAAA,EACT;AACF;","names":[]}