{"version":3,"file":"index.cjs","names":[],"sources":["../../../twenty-shared/dist/application-runtime.mjs","../../src/sdk/utils/get-application-access-token.ts","../../src/sdk/billing/charge-credits.ts","../../src/sdk/billing/get-credit-availability.ts"],"sourcesContent":["//#region src/application-runtime/constants/ConnectionScopeByLegacyVisibility.ts\nvar e = {\n\tuser: \"USER\",\n\tworkspace: \"WORKSPACE\"\n}, t = \"TWENTY_API_KEY\", n = \"TWENTY_API_URL\", r = \"TWENTY_APP_ACCESS_TOKEN\", i = \"TWENTY_APP_APPLICATION_ACCESS_TOKEN\", a = \"TWENTY_FUNCTIONS_URL\", o = {\n\tUSER: \"user\",\n\tWORKSPACE: \"workspace\"\n}, s = [\n\t\"workspace-suspended\",\n\t\"no-subscription\",\n\t\"no-credits\"\n];\n//#endregion\nexport { e as CONNECTION_SCOPE_BY_LEGACY_VISIBILITY, s as CREDIT_UNAVAILABLE_REASONS, t as DEFAULT_API_KEY_NAME, n as DEFAULT_API_URL_NAME, r as DEFAULT_APP_ACCESS_TOKEN_NAME, i as DEFAULT_APP_APPLICATION_ACCESS_TOKEN_NAME, a as DEFAULT_FUNCTIONS_URL_NAME, o as LEGACY_CONNECTION_VISIBILITY_BY_SCOPE };\n","import {\n  DEFAULT_APP_ACCESS_TOKEN_NAME,\n  DEFAULT_APP_APPLICATION_ACCESS_TOKEN_NAME,\n} from 'twenty-shared/application-runtime';\n\n// These reach the application's own resources, so prefer the application token when the runtime injects one\nexport const getApplicationAccessToken = (): string | undefined =>\n  process.env[DEFAULT_APP_APPLICATION_ACCESS_TOKEN_NAME] ??\n  process.env[DEFAULT_APP_ACCESS_TOKEN_NAME];\n","import { type UsageOperationTypeValue } from 'twenty-shared/application';\nimport { DEFAULT_API_URL_NAME } from 'twenty-shared/application-runtime';\n\nimport { getApplicationAccessToken } from '@/sdk/utils/get-application-access-token';\n\nconst BILLING_CHARGE_TIMEOUT_MS = 5_000;\n\nexport type ChargeCreditsParams = {\n  creditsUsedMicro: number;\n  quantity?: number;\n  // Who the spend belongs to when no user triggered the run (webhook, cron); ignored otherwise\n  userWorkspaceId?: string;\n} & (\n  | {\n      // An operation declared in the manifest's `billing.operations`; the platform resolves its category and label\n      operation: string;\n      operationType?: never;\n      resourceContext?: never;\n    }\n  | {\n      // For applications that declare no billable operations: names the platform billing category directly\n      operationType: UsageOperationTypeValue;\n      operation?: never;\n      resourceContext?: string;\n    }\n);\n\n// No-ops without an API URL or access token, and never throws: a billing error must not fail a tool\nexport const chargeCredits = async ({\n  creditsUsedMicro,\n  quantity = 1,\n  operation,\n  operationType,\n  resourceContext,\n  userWorkspaceId,\n}: ChargeCreditsParams): Promise<void> => {\n  const apiUrl = process.env[DEFAULT_API_URL_NAME];\n  const token = getApplicationAccessToken();\n\n  if (!apiUrl || !token) {\n    return;\n  }\n\n  try {\n    const response = await fetch(\n      `${apiUrl.replace(/\\/$/, '')}/app/billing/charge`,\n      {\n        method: 'POST',\n        headers: {\n          Authorization: `Bearer ${token}`,\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify({\n          creditsUsedMicro,\n          quantity,\n          operation,\n          operationType,\n          resourceContext,\n          userWorkspaceId,\n        }),\n        signal: AbortSignal.timeout(BILLING_CHARGE_TIMEOUT_MS),\n      },\n    );\n\n    if (!response.ok) {\n      const body = await response.text().catch(() => '');\n\n      console.error(\n        `chargeCredits: ${response.status} ${response.statusText}: ${body}`,\n      );\n    }\n  } catch (error) {\n    console.error(\n      `chargeCredits: ${error instanceof Error ? error.message : String(error)}`,\n    );\n  }\n};\n","import {\n  CREDIT_UNAVAILABLE_REASONS,\n  type CreditAvailability,\n  type CreditUnavailableReason,\n  DEFAULT_API_URL_NAME,\n} from 'twenty-shared/application-runtime';\n\nimport { getApplicationAccessToken } from '@/sdk/utils/get-application-access-token';\n\nconst CREDIT_AVAILABILITY_TIMEOUT_MS = 5_000;\n\n// A fresh object per call, since app code could mutate a shared constant\nconst available = (): CreditAvailability => ({ hasAvailableCredits: true });\n\nconst parseCreditAvailability = (body: unknown): CreditAvailability | null => {\n  if (typeof body !== 'object' || body === null) {\n    return null;\n  }\n\n  const { hasAvailableCredits, reason } = body as {\n    hasAvailableCredits?: unknown;\n    reason?: unknown;\n  };\n\n  if (hasAvailableCredits === true) {\n    return { hasAvailableCredits: true };\n  }\n\n  if (\n    hasAvailableCredits === false &&\n    CREDIT_UNAVAILABLE_REASONS.includes(reason as CreditUnavailableReason)\n  ) {\n    return {\n      hasAvailableCredits: false,\n      reason: reason as CreditUnavailableReason,\n    };\n  }\n\n  return null;\n};\n\n// Fails open on timeouts or bad responses: a hint before expensive work, never an authorization decision\nexport const getCreditAvailability = async (): Promise<CreditAvailability> => {\n  const apiUrl = process.env[DEFAULT_API_URL_NAME];\n  const token = getApplicationAccessToken();\n\n  if (!apiUrl || !token) {\n    return available();\n  }\n\n  try {\n    const response = await fetch(\n      `${apiUrl.replace(/\\/$/, '')}/app/billing/credits`,\n      {\n        method: 'GET',\n        headers: {\n          Authorization: `Bearer ${token}`,\n          Accept: 'application/json',\n        },\n        signal: AbortSignal.timeout(CREDIT_AVAILABILITY_TIMEOUT_MS),\n      },\n    );\n\n    if (!response.ok) {\n      console.error(\n        `getCreditAvailability: ${response.status} ${response.statusText}`,\n      );\n\n      return available();\n    }\n\n    const creditAvailability = parseCreditAvailability(await response.json());\n\n    if (creditAvailability === null) {\n      console.error('getCreditAvailability: unexpected response shape');\n\n      return available();\n    }\n\n    return creditAvailability;\n  } catch (error) {\n    console.error(\n      `getCreditAvailability: ${error instanceof Error ? error.message : String(error)}`,\n    );\n\n    return available();\n  }\n};\n"],"mappings":"uEAIyB,EAAI,iBAG1B,EAAI,CACN,sBACA,kBACA,YACD,ECLa,MACX,QAAQ,IAAA,qCACR,QAAQ,IAAA,wBCHJ,EAA4B,IAuBrB,EAAgB,MAAO,CAClC,mBACA,WAAW,EACX,YACA,gBACA,kBACA,qBACwC,CACxC,IAAM,EAAS,QAAQ,IAAI,GACrB,EAAQ,EAA0B,EAEpC,MAAC,GAAU,CAAC,GAIhB,GAAI,CACF,IAAM,EAAW,MAAM,MACrB,GAAG,EAAO,QAAQ,MAAO,EAAE,EAAE,qBAC7B,CACE,OAAQ,OACR,QAAS,CACP,cAAe,UAAU,IACzB,eAAgB,kBAClB,EACA,KAAM,KAAK,UAAU,CACnB,mBACA,WACA,YACA,gBACA,kBACA,iBACF,CAAC,EACD,OAAQ,YAAY,QAAQ,CAAyB,CACvD,CACF,EAEA,GAAI,CAAC,EAAS,GAAI,CAChB,IAAM,EAAO,MAAM,EAAS,KAAK,CAAC,CAAC,UAAY,EAAE,EAEjD,QAAQ,MACN,kBAAkB,EAAS,OAAO,GAAG,EAAS,WAAW,IAAI,GAC/D,CACF,CACF,OAAS,EAAO,CACd,QAAQ,MACN,kBAAkB,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,GACzE,CACF,CACF,ECnEM,EAAiC,IAGjC,OAAuC,CAAE,oBAAqB,EAAK,GAEnE,EAA2B,GAA6C,CAC5E,GAAI,OAAO,GAAS,WAAY,EAC9B,OAAO,KAGT,GAAM,CAAE,sBAAqB,UAAW,EAmBxC,OAdI,IAAwB,GACnB,CAAE,oBAAqB,EAAK,EAInC,IAAwB,IACxB,EAA2B,SAAS,CAAiC,EAE9D,CACL,oBAAqB,GACb,QACV,EAGK,IACT,EAGa,EAAwB,SAAyC,CAC5E,IAAM,EAAS,QAAQ,IAAI,GACrB,EAAQ,EAA0B,EAExC,GAAI,CAAC,GAAU,CAAC,EACd,OAAO,EAAU,EAGnB,GAAI,CACF,IAAM,EAAW,MAAM,MACrB,GAAG,EAAO,QAAQ,MAAO,EAAE,EAAE,sBAC7B,CACE,OAAQ,MACR,QAAS,CACP,cAAe,UAAU,IACzB,OAAQ,kBACV,EACA,OAAQ,YAAY,QAAQ,CAA8B,CAC5D,CACF,EAEA,GAAI,CAAC,EAAS,GAKZ,OAJA,QAAQ,MACN,0BAA0B,EAAS,OAAO,GAAG,EAAS,YACxD,EAEO,EAAU,EAGnB,IAAM,EAAqB,EAAwB,MAAM,EAAS,KAAK,CAAC,EAQxE,OANI,IAAuB,MACzB,QAAQ,MAAM,kDAAkD,EAEzD,EAAU,GAGZ,CACT,OAAS,EAAO,CAKd,OAJA,QAAQ,MACN,0BAA0B,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,GACjF,EAEO,EAAU,CACnB,CACF"}