{"version":3,"file":"server-CwbdGhuX.mjs","names":["timestampRaw: string | undefined","signature: string | undefined"],"sources":["../src/server.ts"],"sourcesContent":["import { createHmac, timingSafeEqual } from \"node:crypto\";\n\nimport { createRelioClient, type RelioClient } from \"./client\";\nimport { RelioApiError } from \"./core\";\nimport type { RelioClientOptions } from \"./core\";\n\nexport const RELIO_SIGNATURE_HEADER = \"x-relio-signature\";\nexport const RELIO_EVENT_HEADER = \"x-relio-event\";\nexport const RELIO_WEBHOOK_ID_HEADER = \"x-relio-webhook-id\";\n\nexport type RelioWebhookVerificationOptions = {\n  secret: string;\n  payload: string;\n  signatureHeader: string | null | undefined;\n  toleranceSeconds?: number;\n  nowMs?: number;\n};\n\nexport type RelioWebhookHeaders = {\n  signature: string | null;\n  event: string | null;\n  webhookId: string | null;\n};\n\nexport type VerifiedRelioWebhook<TPayload = unknown> = {\n  event: string | null;\n  webhookId: string | null;\n  payload: TPayload;\n};\n\nexport class RelioWebhookSignatureError extends RelioApiError {\n  constructor(message: string) {\n    super(message, { code: \"RELIO_WEBHOOK_INVALID_SIGNATURE\", status: 401 });\n    this.name = \"RelioWebhookSignatureError\";\n  }\n}\n\nexport function parseRelioSignatureHeader(\n  signatureHeader: string | null | undefined,\n): { timestamp: number; signature: string } | null {\n  if (!signatureHeader) return null;\n\n  const parts = signatureHeader\n    .split(\",\")\n    .map((part) => part.trim())\n    .filter(Boolean);\n\n  let timestampRaw: string | undefined;\n  let signature: string | undefined;\n\n  for (const part of parts) {\n    const [key, value] = part.split(\"=\");\n    if (key === \"t\" && value) timestampRaw = value;\n    if (key === \"v1\" && value) signature = value;\n  }\n\n  if (!timestampRaw || !signature) return null;\n  const timestamp = Number.parseInt(timestampRaw, 10);\n  if (!Number.isFinite(timestamp)) return null;\n\n  return { timestamp, signature };\n}\n\nexport function buildRelioWebhookSignature(\n  payload: string,\n  secret: string,\n  timestamp = Math.floor(Date.now() / 1000),\n): string {\n  const signedPayload = `${timestamp}.${payload}`;\n  const digest = createHmac(\"sha256\", secret).update(signedPayload).digest(\"hex\");\n  return `t=${timestamp},v1=${digest}`;\n}\n\nexport function verifyRelioWebhookSignature(\n  options: RelioWebhookVerificationOptions,\n): boolean {\n  const parsed = parseRelioSignatureHeader(options.signatureHeader);\n  if (!parsed) return false;\n\n  const nowMs = options.nowMs ?? Date.now();\n  const toleranceMs = (options.toleranceSeconds ?? 300) * 1000;\n  const ageMs = Math.abs(nowMs - parsed.timestamp * 1000);\n  if (ageMs > toleranceMs) return false;\n\n  const signedPayload = `${parsed.timestamp}.${options.payload}`;\n  const expected = createHmac(\"sha256\", options.secret).update(signedPayload).digest(\"hex\");\n\n  const expectedBuffer = Buffer.from(expected, \"hex\");\n  const incomingBuffer = Buffer.from(parsed.signature, \"hex\");\n  if (expectedBuffer.length !== incomingBuffer.length) return false;\n\n  return timingSafeEqual(expectedBuffer, incomingBuffer);\n}\n\nexport function assertRelioWebhookSignature(\n  options: RelioWebhookVerificationOptions,\n): void {\n  const valid = verifyRelioWebhookSignature(options);\n  if (!valid) {\n    throw new RelioWebhookSignatureError(\"Invalid or expired Relio webhook signature.\");\n  }\n}\n\nexport function readRelioWebhookHeaders(\n  headers: Headers | Record<string, string | string[] | undefined>,\n): RelioWebhookHeaders {\n  const getHeader = (name: string): string | null => {\n    if (headers instanceof Headers) return headers.get(name);\n\n    const direct = headers[name] ?? headers[name.toLowerCase()] ?? headers[name.toUpperCase()];\n    if (Array.isArray(direct)) return direct[0] ?? null;\n    return direct ?? null;\n  };\n\n  return {\n    signature: getHeader(RELIO_SIGNATURE_HEADER),\n    event: getHeader(RELIO_EVENT_HEADER),\n    webhookId: getHeader(RELIO_WEBHOOK_ID_HEADER),\n  };\n}\n\nexport async function verifyRelioWebhookRequest<TPayload = unknown>(options: {\n  request: Request;\n  secret: string;\n  parseJson?: boolean;\n  toleranceSeconds?: number;\n}): Promise<VerifiedRelioWebhook<TPayload | string>> {\n  const rawPayload = await options.request.text();\n  const headers = readRelioWebhookHeaders(options.request.headers);\n\n  assertRelioWebhookSignature({\n    secret: options.secret,\n    payload: rawPayload,\n    signatureHeader: headers.signature,\n    toleranceSeconds: options.toleranceSeconds,\n  });\n\n  if (options.parseJson === false) {\n    return {\n      event: headers.event,\n      webhookId: headers.webhookId,\n      payload: rawPayload,\n    };\n  }\n\n  return {\n    event: headers.event,\n    webhookId: headers.webhookId,\n    payload: JSON.parse(rawPayload) as TPayload,\n  };\n}\n\n/**\n * Server-oriented Relio API client.\n * Uses the same transport as `createRelioClient`, but exposed from `@relio/sdk/server`\n * for backend integrations.\n */\nexport function createRelioServerClient(options: RelioClientOptions): RelioClient {\n  return createRelioClient(options);\n}\n"],"mappings":";;;;;AAMA,MAAa,yBAAyB;AACtC,MAAa,qBAAqB;AAClC,MAAa,0BAA0B;AAsBvC,IAAa,6BAAb,cAAgD,cAAc;CAC5D,YAAY,SAAiB;AAC3B,QAAM,SAAS;GAAE,MAAM;GAAmC,QAAQ;GAAK,CAAC;AACxE,OAAK,OAAO;;;AAIhB,SAAgB,0BACd,iBACiD;AACjD,KAAI,CAAC,gBAAiB,QAAO;CAE7B,MAAM,QAAQ,gBACX,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ;CAElB,IAAIA;CACJ,IAAIC;AAEJ,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,CAAC,KAAK,SAAS,KAAK,MAAM,IAAI;AACpC,MAAI,QAAQ,OAAO,MAAO,gBAAe;AACzC,MAAI,QAAQ,QAAQ,MAAO,aAAY;;AAGzC,KAAI,CAAC,gBAAgB,CAAC,UAAW,QAAO;CACxC,MAAM,YAAY,OAAO,SAAS,cAAc,GAAG;AACnD,KAAI,CAAC,OAAO,SAAS,UAAU,CAAE,QAAO;AAExC,QAAO;EAAE;EAAW;EAAW;;AAGjC,SAAgB,2BACd,SACA,QACA,YAAY,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,EACjC;CACR,MAAM,gBAAgB,GAAG,UAAU,GAAG;AAEtC,QAAO,KAAK,UAAU,MADP,WAAW,UAAU,OAAO,CAAC,OAAO,cAAc,CAAC,OAAO,MAAM;;AAIjF,SAAgB,4BACd,SACS;CACT,MAAM,SAAS,0BAA0B,QAAQ,gBAAgB;AACjE,KAAI,CAAC,OAAQ,QAAO;CAEpB,MAAM,QAAQ,QAAQ,SAAS,KAAK,KAAK;CACzC,MAAM,eAAe,QAAQ,oBAAoB,OAAO;AAExD,KADc,KAAK,IAAI,QAAQ,OAAO,YAAY,IAAK,GAC3C,YAAa,QAAO;CAEhC,MAAM,gBAAgB,GAAG,OAAO,UAAU,GAAG,QAAQ;CACrD,MAAM,WAAW,WAAW,UAAU,QAAQ,OAAO,CAAC,OAAO,cAAc,CAAC,OAAO,MAAM;CAEzF,MAAM,iBAAiB,OAAO,KAAK,UAAU,MAAM;CACnD,MAAM,iBAAiB,OAAO,KAAK,OAAO,WAAW,MAAM;AAC3D,KAAI,eAAe,WAAW,eAAe,OAAQ,QAAO;AAE5D,QAAO,gBAAgB,gBAAgB,eAAe;;AAGxD,SAAgB,4BACd,SACM;AAEN,KAAI,CADU,4BAA4B,QAAQ,CAEhD,OAAM,IAAI,2BAA2B,8CAA8C;;AAIvF,SAAgB,wBACd,SACqB;CACrB,MAAM,aAAa,SAAgC;AACjD,MAAI,mBAAmB,QAAS,QAAO,QAAQ,IAAI,KAAK;EAExD,MAAM,SAAS,QAAQ,SAAS,QAAQ,KAAK,aAAa,KAAK,QAAQ,KAAK,aAAa;AACzF,MAAI,MAAM,QAAQ,OAAO,CAAE,QAAO,OAAO,MAAM;AAC/C,SAAO,UAAU;;AAGnB,QAAO;EACL,WAAW,UAAU,uBAAuB;EAC5C,OAAO,UAAU,mBAAmB;EACpC,WAAW,UAAU,wBAAwB;EAC9C;;AAGH,eAAsB,0BAA8C,SAKf;CACnD,MAAM,aAAa,MAAM,QAAQ,QAAQ,MAAM;CAC/C,MAAM,UAAU,wBAAwB,QAAQ,QAAQ,QAAQ;AAEhE,6BAA4B;EAC1B,QAAQ,QAAQ;EAChB,SAAS;EACT,iBAAiB,QAAQ;EACzB,kBAAkB,QAAQ;EAC3B,CAAC;AAEF,KAAI,QAAQ,cAAc,MACxB,QAAO;EACL,OAAO,QAAQ;EACf,WAAW,QAAQ;EACnB,SAAS;EACV;AAGH,QAAO;EACL,OAAO,QAAQ;EACf,WAAW,QAAQ;EACnB,SAAS,KAAK,MAAM,WAAW;EAChC;;;;;;;AAQH,SAAgB,wBAAwB,SAA0C;AAChF,QAAO,kBAAkB,QAAQ"}