{"version":3,"file":"index.mjs","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":";IAIyB,IAAI,kBAG1B,IAAI;CACN;CACA;CACA;AACD,GCLa,UACX,QAAQ,IAAA,uCACR,QAAQ,IAAA,yBCHJ,IAA4B,KAuBrB,IAAgB,OAAO,EAClC,qBACA,cAAW,GACX,cACA,kBACA,oBACA,yBACwC;CACxC,IAAM,IAAS,QAAQ,IAAI,IACrB,IAAQ,EAA0B;CAEpC,OAAC,KAAU,CAAC,IAIhB,IAAI;EACF,IAAM,IAAW,MAAM,MACrB,GAAG,EAAO,QAAQ,OAAO,EAAE,EAAE,sBAC7B;GACE,QAAQ;GACR,SAAS;IACP,eAAe,UAAU;IACzB,gBAAgB;GAClB;GACA,MAAM,KAAK,UAAU;IACnB;IACA;IACA;IACA;IACA;IACA;GACF,CAAC;GACD,QAAQ,YAAY,QAAQ,CAAyB;EACvD,CACF;EAEA,IAAI,CAAC,EAAS,IAAI;GAChB,IAAM,IAAO,MAAM,EAAS,KAAK,CAAC,CAAC,YAAY,EAAE;GAEjD,QAAQ,MACN,kBAAkB,EAAS,OAAO,GAAG,EAAS,WAAW,IAAI,GAC/D;EACF;CACF,SAAS,GAAO;EACd,QAAQ,MACN,kBAAkB,aAAiB,QAAQ,EAAM,UAAU,OAAO,CAAK,GACzE;CACF;AACF,GCnEM,IAAiC,KAGjC,WAAuC,EAAE,qBAAqB,GAAK,IAEnE,KAA2B,MAA6C;CAC5E,IAAI,OAAO,KAAS,aAAY,GAC9B,OAAO;CAGT,IAAM,EAAE,wBAAqB,cAAW;CAmBxC,OAdI,MAAwB,KACnB,EAAE,qBAAqB,GAAK,IAInC,MAAwB,MACxB,EAA2B,SAAS,CAAiC,IAE9D;EACL,qBAAqB;EACb;CACV,IAGK;AACT,GAGa,IAAwB,YAAyC;CAC5E,IAAM,IAAS,QAAQ,IAAI,IACrB,IAAQ,EAA0B;CAExC,IAAI,CAAC,KAAU,CAAC,GACd,OAAO,EAAU;CAGnB,IAAI;EACF,IAAM,IAAW,MAAM,MACrB,GAAG,EAAO,QAAQ,OAAO,EAAE,EAAE,uBAC7B;GACE,QAAQ;GACR,SAAS;IACP,eAAe,UAAU;IACzB,QAAQ;GACV;GACA,QAAQ,YAAY,QAAQ,CAA8B;EAC5D,CACF;EAEA,IAAI,CAAC,EAAS,IAKZ,OAJA,QAAQ,MACN,0BAA0B,EAAS,OAAO,GAAG,EAAS,YACxD,GAEO,EAAU;EAGnB,IAAM,IAAqB,EAAwB,MAAM,EAAS,KAAK,CAAC;EAQxE,OANI,MAAuB,QACzB,QAAQ,MAAM,kDAAkD,GAEzD,EAAU,KAGZ;CACT,SAAS,GAAO;EAKd,OAJA,QAAQ,MACN,0BAA0B,aAAiB,QAAQ,EAAM,UAAU,OAAO,CAAK,GACjF,GAEO,EAAU;CACnB;AACF"}