@geekapps/billing-fastify 0.7.3 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -121,6 +121,8 @@ interface Customer {
121
121
  interface BillingItem {
122
122
  id: string;
123
123
  org_id: string;
124
+ /** "dev" (Stripe test mode) ou "prod" (Stripe live mode) — mesmo ambiente do BillingProviderConfig usado. */
125
+ mode: string;
124
126
  name: string;
125
127
  description: string | null;
126
128
  amount: number;
@@ -295,6 +297,8 @@ interface CreateCouponInput {
295
297
  interface Coupon {
296
298
  id: string;
297
299
  org_id: string;
300
+ /** "dev" (Stripe test mode) ou "prod" (Stripe live mode) — o código é único por (org, mode). */
301
+ mode: string;
298
302
  code: string;
299
303
  type: CouponType;
300
304
  value: number;
@@ -402,6 +406,49 @@ interface SubscriptionStatusResult {
402
406
  plan: SubscriptionPlanSummary | null;
403
407
  available_plans: SubscriptionPlanSummary[];
404
408
  }
409
+ type SwapPolicy = "IMMEDIATE" | "AT_RENEWAL" | "FIXED_AMOUNT";
410
+ type SwapMode = "IMMEDIATE_CHARGE" | "SCHEDULED" | "FIXED_AMOUNT_CHARGE";
411
+ interface SwapPlanInput {
412
+ newPlanId: string;
413
+ policy: SwapPolicy;
414
+ /** Valor de ajuste assinado (cents) — positivo cobra o cliente, negativo estorna.
415
+ * Obrigatório quando `policy` é `"FIXED_AMOUNT"`. */
416
+ manualAmount?: number;
417
+ /** Segundos até a cobrança de proration (se houver) vencer — opcional, default 1h. */
418
+ expiresInSeconds?: number;
419
+ couponCode?: string;
420
+ }
421
+ interface SwapPlanResult {
422
+ mode: SwapMode;
423
+ /** Pode ser negativo (estorno). */
424
+ due_amount: number;
425
+ /** Presente apenas quando há cobrança pendente de confirmação (PIX/boleto). */
426
+ checkout_url: string | null;
427
+ /** Presente apenas quando `mode` é `"SCHEDULED"`. */
428
+ effective_at: string | null;
429
+ }
430
+ interface SwapPlanPreviewResult {
431
+ mode: SwapMode;
432
+ old_plan: {
433
+ id: string;
434
+ name: string;
435
+ amount: number;
436
+ currency: string;
437
+ };
438
+ new_plan: {
439
+ id: string;
440
+ name: string;
441
+ amount: number;
442
+ currency: string;
443
+ };
444
+ due_amount: number;
445
+ suggested_amount: number | null;
446
+ effective_at_estimate: string | null;
447
+ discount?: {
448
+ coupon_code: string;
449
+ exact: boolean;
450
+ };
451
+ }
405
452
  interface CreateOrderInput {
406
453
  amount?: number;
407
454
  currency?: string;
@@ -644,28 +691,48 @@ declare class SubscriptionsResource {
644
691
  /** Requer autenticação (service account). */
645
692
  cancel(id: string): Promise<Subscription>;
646
693
  /**
647
- * Inicia uma troca de plano/item de uma assinatura já existente (upgrade/downgrade de
648
- * tier) — requer autenticação (service account). NÃO executa a troca diretamente: retorna
649
- * um link de confirmação para o cliente final revisar custo e vigência e confirmar
650
- * expressamente antes de qualquer cobrança ou mudança de plano acontecer.
694
+ * Reverte um cancelamento agendado (cancel_at_period_end) — requer autenticação
695
+ * (service account). Só se aplica enquanto a assinatura ainda está ACTIVE com o
696
+ * cancelamento agendado pro fim do período vigente (ver SUBSCRIPTION_CANCEL_SCHEDULE);
697
+ * uma vez CANCELLED de fato, a Subscription já foi encerrada no Stripe e não há o que
698
+ * reverter — chame `cancel`/checkout novamente para recomeçar.
699
+ */
700
+ resume(id: string): Promise<Subscription>;
701
+ /**
702
+ * Calcula o preview de uma troca de plano (não muta nada) — requer autenticação
703
+ * (service account). Use para mostrar ao dono da org o valor devido/estimado antes de
704
+ * confirmar com `swapPlan`.
705
+ *
706
+ * ```ts
707
+ * const preview = await client.subscriptions.previewPlanSwap(subId, {
708
+ * newPlanId, policy: "AT_RENEWAL",
709
+ * });
710
+ * ```
711
+ */
712
+ previewPlanSwap(id: string, input: SwapPlanInput): Promise<SwapPlanPreviewResult>;
713
+ /**
714
+ * Executa a troca de plano/item de uma assinatura já existente (upgrade/downgrade de
715
+ * tier) — requer autenticação (service account). Executa a troca diretamente, sem
716
+ * confirmação posterior do cliente final; o dono do org escolhe `policy` (cobrar/estornar
717
+ * agora, aplicar só na próxima renovação, ou valor definido manualmente) antes de chamar.
718
+ *
719
+ * `manualAmount`: obrigatório quando `policy` é `"FIXED_AMOUNT"` — valor de ajuste assinado
720
+ * (cents), positivo cobra o cliente, negativo estorna.
651
721
  *
652
722
  * `couponCode`: aplica um cupom na troca — se a assinatura for Stripe, o desconto passa a
653
723
  * valer também nas renovações futuras (recorrente, direto na Subscription); se for
654
724
  * PIX/boleto, o desconto vale só para a cobrança de proration desta troca.
655
725
  *
656
726
  * ```ts
657
- * const { confirmation_url } = await client.subscriptions.requestPlanSwap(subId, newPlanId, {
658
- * couponCode: "PROMO20",
727
+ * const result = await client.subscriptions.swapPlan(subId, {
728
+ * newPlanId, policy: "IMMEDIATE", couponCode: "PROMO20",
659
729
  * });
660
- * // redirecione o cliente final para confirmation_url
730
+ * if (result.checkout_url) {
731
+ * // redirecione o cliente final para result.checkout_url para pagar a cobrança de ajuste
732
+ * }
661
733
  * ```
662
734
  */
663
- requestPlanSwap(id: string, newPlanId: string, options?: {
664
- expiresInSeconds?: number;
665
- couponCode?: string;
666
- }): Promise<{
667
- confirmation_url: string;
668
- }>;
735
+ swapPlan(id: string, input: SwapPlanInput): Promise<SwapPlanResult>;
669
736
  /**
670
737
  * Verifica se uma assinatura está ativa e qual item ela cobre, usando o
671
738
  * `management_token` retornado por `plans.checkout()` — rota pública, sem
@@ -912,4 +979,4 @@ type ExpirationUnit = "seconds" | "minutes" | "hours" | "days";
912
979
  */
913
980
  declare function expiresIn(value: number, unit: ExpirationUnit): number;
914
981
 
915
- export { type AppliedDiscount, BillingApiError, BillingClient, type BillingClientOptions, type BillingItem, type BillingPeriod, type BillingPlanSummary, type BillingPluginOptions, type BillingRecurringInterval, type BillingRecurringStatus, type BillingSubscriptionCancelReason, type Charge, type ChargeEventData, type ChargeStatus, ChargesResource, type CheckoutForCustomerInput, type CheckoutForCustomerResult, CheckoutResource, type CheckoutSessionStatus, type CheckoutStatusResult, type Coupon, type CouponDuration, type CouponType, CouponsResource, type CreateBillingPlanInput, type CreateChargeInput, type CreateChargeResult, type CreateCouponInput, type CreateOrderInput, type CreateOrderResult, type CreateSubscriptionInput, type CreateSubscriptionResult, type Customer, type CustomerInput, CustomersResource, type ExpirationUnit, type GetPublicPlanPageResult, HttpClient, type HttpClientOptions, type ItemInput, ItemsResource, type ListPublicPlansResult, OrdersResource, type OutboundWebhookEventType, type PaymentMethod, type PlanCheckoutCustomerInput, type PlanCheckoutInput, type PlanCheckoutResult, type PlanSubscriptionStatusResult, PlansResource, type ProrationPolicy, type PublicBillingPlan, type PublicOrganization, type PublicPlanBranding, type QuickChargeInput, type QuickChargeResult, type ServiceAccountOptions, ServiceAccountTokenProvider, type Subscription, type SubscriptionItemSummary, type SubscriptionPlanSummary, type SubscriptionStatusResult, SubscriptionsResource, type TokenResolver, type WaitUntilPaidOptions, type WebhookEndpointInput, type WebhookEndpointSummary, type WebhookEvent, WebhooksResource, _default as billingPlugin, createServiceAccountToken, expiresIn };
982
+ export { type AppliedDiscount, BillingApiError, BillingClient, type BillingClientOptions, type BillingItem, type BillingPeriod, type BillingPlanSummary, type BillingPluginOptions, type BillingRecurringInterval, type BillingRecurringStatus, type BillingSubscriptionCancelReason, type Charge, type ChargeEventData, type ChargeStatus, ChargesResource, type CheckoutForCustomerInput, type CheckoutForCustomerResult, CheckoutResource, type CheckoutSessionStatus, type CheckoutStatusResult, type Coupon, type CouponDuration, type CouponType, CouponsResource, type CreateBillingPlanInput, type CreateChargeInput, type CreateChargeResult, type CreateCouponInput, type CreateOrderInput, type CreateOrderResult, type CreateSubscriptionInput, type CreateSubscriptionResult, type Customer, type CustomerInput, CustomersResource, type ExpirationUnit, type GetPublicPlanPageResult, HttpClient, type HttpClientOptions, type ItemInput, ItemsResource, type ListPublicPlansResult, OrdersResource, type OutboundWebhookEventType, type PaymentMethod, type PlanCheckoutCustomerInput, type PlanCheckoutInput, type PlanCheckoutResult, type PlanSubscriptionStatusResult, PlansResource, type ProrationPolicy, type PublicBillingPlan, type PublicOrganization, type PublicPlanBranding, type QuickChargeInput, type QuickChargeResult, type ServiceAccountOptions, ServiceAccountTokenProvider, type Subscription, type SubscriptionItemSummary, type SubscriptionPlanSummary, type SubscriptionStatusResult, SubscriptionsResource, type SwapMode, type SwapPlanInput, type SwapPlanPreviewResult, type SwapPlanResult, type SwapPolicy, type TokenResolver, type WaitUntilPaidOptions, type WebhookEndpointInput, type WebhookEndpointSummary, type WebhookEvent, WebhooksResource, _default as billingPlugin, createServiceAccountToken, expiresIn };
package/dist/index.js CHANGED
@@ -524,27 +524,61 @@ var SubscriptionsResource = class {
524
524
  return this.http.patch(`/billing-subscriptions/${id}/cancel`);
525
525
  }
526
526
  /**
527
- * Inicia uma troca de plano/item de uma assinatura já existente (upgrade/downgrade de
528
- * tier) — requer autenticação (service account). NÃO executa a troca diretamente: retorna
529
- * um link de confirmação para o cliente final revisar custo e vigência e confirmar
530
- * expressamente antes de qualquer cobrança ou mudança de plano acontecer.
527
+ * Reverte um cancelamento agendado (cancel_at_period_end) — requer autenticação
528
+ * (service account). Só se aplica enquanto a assinatura ainda está ACTIVE com o
529
+ * cancelamento agendado pro fim do período vigente (ver SUBSCRIPTION_CANCEL_SCHEDULE);
530
+ * uma vez CANCELLED de fato, a Subscription já foi encerrada no Stripe e não há o que
531
+ * reverter — chame `cancel`/checkout novamente para recomeçar.
532
+ */
533
+ resume(id) {
534
+ return this.http.patch(`/billing-subscriptions/${id}/resume`);
535
+ }
536
+ /**
537
+ * Calcula o preview de uma troca de plano (não muta nada) — requer autenticação
538
+ * (service account). Use para mostrar ao dono da org o valor devido/estimado antes de
539
+ * confirmar com `swapPlan`.
540
+ *
541
+ * ```ts
542
+ * const preview = await client.subscriptions.previewPlanSwap(subId, {
543
+ * newPlanId, policy: "AT_RENEWAL",
544
+ * });
545
+ * ```
546
+ */
547
+ previewPlanSwap(id, input) {
548
+ const params = new URLSearchParams({ new_plan_id: input.newPlanId, policy: input.policy });
549
+ if (input.manualAmount !== void 0) params.set("manual_amount", String(input.manualAmount));
550
+ if (input.couponCode) params.set("coupon_code", input.couponCode);
551
+ return this.http.get(`/billing-subscriptions/${id}/swap-preview?${params.toString()}`);
552
+ }
553
+ /**
554
+ * Executa a troca de plano/item de uma assinatura já existente (upgrade/downgrade de
555
+ * tier) — requer autenticação (service account). Executa a troca diretamente, sem
556
+ * confirmação posterior do cliente final; o dono do org escolhe `policy` (cobrar/estornar
557
+ * agora, aplicar só na próxima renovação, ou valor definido manualmente) antes de chamar.
558
+ *
559
+ * `manualAmount`: obrigatório quando `policy` é `"FIXED_AMOUNT"` — valor de ajuste assinado
560
+ * (cents), positivo cobra o cliente, negativo estorna.
531
561
  *
532
562
  * `couponCode`: aplica um cupom na troca — se a assinatura for Stripe, o desconto passa a
533
563
  * valer também nas renovações futuras (recorrente, direto na Subscription); se for
534
564
  * PIX/boleto, o desconto vale só para a cobrança de proration desta troca.
535
565
  *
536
566
  * ```ts
537
- * const { confirmation_url } = await client.subscriptions.requestPlanSwap(subId, newPlanId, {
538
- * couponCode: "PROMO20",
567
+ * const result = await client.subscriptions.swapPlan(subId, {
568
+ * newPlanId, policy: "IMMEDIATE", couponCode: "PROMO20",
539
569
  * });
540
- * // redirecione o cliente final para confirmation_url
570
+ * if (result.checkout_url) {
571
+ * // redirecione o cliente final para result.checkout_url para pagar a cobrança de ajuste
572
+ * }
541
573
  * ```
542
574
  */
543
- requestPlanSwap(id, newPlanId, options) {
575
+ swapPlan(id, input) {
544
576
  return this.http.patch(`/billing-subscriptions/${id}/swap`, {
545
- new_plan_id: newPlanId,
546
- ...options?.expiresInSeconds ? { expires_in: options.expiresInSeconds } : {},
547
- ...options?.couponCode ? { coupon_code: options.couponCode } : {}
577
+ new_plan_id: input.newPlanId,
578
+ policy: input.policy,
579
+ ...input.manualAmount !== void 0 ? { manual_amount: input.manualAmount } : {},
580
+ ...input.expiresInSeconds ? { expires_in: input.expiresInSeconds } : {},
581
+ ...input.couponCode ? { coupon_code: input.couponCode } : {}
548
582
  });
549
583
  }
550
584
  /**
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/lib/getPluginName.js","../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/lib/toCamelCase.js","../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/index.js","../src/errors.ts","../src/http.ts","../src/resources/charges.ts","../src/resources/checkout.ts","../src/resources/coupons.ts","../src/resources/customers.ts","../src/resources/items.ts","../src/resources/orders.ts","../src/resources/plans.ts","../src/resources/subscriptions.ts","../src/resources/webhooks.ts","../src/client.ts","../src/plugin.ts","../src/service-account.ts","../src/expiration.ts"],"sourcesContent":["'use strict'\n\nconst fpStackTracePattern = /at\\s(?:.*\\.)?plugin\\s.*\\n\\s*(.*)/\nconst fileNamePattern = /(\\w*(\\.\\w*)*)\\..*/\n\nmodule.exports = function getPluginName (fn) {\n if (fn.name.length > 0) return fn.name\n\n const stackTraceLimit = Error.stackTraceLimit\n Error.stackTraceLimit = 10\n try {\n throw new Error('anonymous function')\n } catch (e) {\n Error.stackTraceLimit = stackTraceLimit\n return extractPluginName(e.stack)\n }\n}\n\nfunction extractPluginName (stack) {\n const m = stack.match(fpStackTracePattern)\n\n // get last section of path and match for filename\n return m ? m[1].split(/[/\\\\]/).slice(-1)[0].match(fileNamePattern)[1] : 'anonymous'\n}\nmodule.exports.extractPluginName = extractPluginName\n","'use strict'\n\nmodule.exports = function toCamelCase (name) {\n if (name[0] === '@') {\n name = name.slice(1).replace('/', '-')\n }\n return name.replace(/-(.)/g, function (match, g1) {\n return g1.toUpperCase()\n })\n}\n","'use strict'\n\nconst getPluginName = require('./lib/getPluginName')\nconst toCamelCase = require('./lib/toCamelCase')\n\nlet count = 0\n\nfunction plugin (fn, options = {}) {\n let autoName = false\n\n if (fn.default !== undefined) {\n // Support for 'export default' behaviour in transpiled ECMAScript module\n fn = fn.default\n }\n\n if (typeof fn !== 'function') {\n throw new TypeError(\n `fastify-plugin expects a function, instead got a '${typeof fn}'`\n )\n }\n\n if (typeof options === 'string') {\n options = {\n fastify: options\n }\n }\n\n if (\n typeof options !== 'object' ||\n Array.isArray(options) ||\n options === null\n ) {\n throw new TypeError('The options object should be an object')\n }\n\n if (options.fastify !== undefined && typeof options.fastify !== 'string') {\n throw new TypeError(`fastify-plugin expects a version string, instead got '${typeof options.fastify}'`)\n }\n\n if (!options.name) {\n autoName = true\n options.name = getPluginName(fn) + '-auto-' + count++\n }\n\n fn[Symbol.for('skip-override')] = options.encapsulate !== true\n fn[Symbol.for('fastify.display-name')] = options.name\n fn[Symbol.for('plugin-meta')] = options\n\n // Faux modules support\n if (!fn.default) {\n fn.default = fn\n }\n\n // TypeScript support for named imports\n // See https://github.com/fastify/fastify/issues/2404 for more details\n // The type definitions would have to be update to match this.\n const camelCase = toCamelCase(options.name)\n if (!autoName && !fn[camelCase]) {\n fn[camelCase] = fn\n }\n\n return fn\n}\n\nmodule.exports = plugin\nmodule.exports.default = plugin\nmodule.exports.fastifyPlugin = plugin\n","export class BillingApiError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly detail?: string,\n ) {\n super(detail ? `${message}: ${detail}` : message);\n this.name = \"BillingApiError\";\n }\n\n get isNotFound() {\n return this.status === 404;\n }\n\n get isUnauthorized() {\n return this.status === 401;\n }\n\n get isForbidden() {\n return this.status === 403;\n }\n\n get isRateLimited() {\n return this.status === 429;\n }\n\n get isValidationError() {\n return this.status === 400 || this.status === 422;\n }\n}\n","import { BillingApiError } from \"./errors.js\";\n\nexport type TokenResolver = string | (() => string | Promise<string>);\n\nexport interface HttpClientOptions {\n baseUrl: string;\n token: TokenResolver;\n organizationId?: string | (() => string | Promise<string>);\n /**\n * Ambiente de billing (dev/prod) — enviado via header x-billing-mode em toda chamada\n * feita por esta instância. Defina uma vez aqui; os métodos individuais (charges.create,\n * customers.list, etc) nunca precisam recebê-lo de novo. Default: \"prod\".\n */\n mode?: string | (() => string | Promise<string>);\n}\n\nconst DEFAULT_MODE = \"prod\";\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly token: TokenResolver;\n private readonly organizationId?: string | (() => string | Promise<string>);\n private readonly mode: string | (() => string | Promise<string>);\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.token = options.token;\n this.organizationId = options.organizationId;\n this.mode = options.mode ?? DEFAULT_MODE;\n }\n\n private async resolveToken(): Promise<string> {\n return typeof this.token === \"function\" ? await this.token() : this.token;\n }\n\n private async resolveOrgId(): Promise<string | undefined> {\n if (!this.organizationId) return undefined;\n return typeof this.organizationId === \"function\"\n ? await this.organizationId()\n : this.organizationId;\n }\n\n private async resolveMode(): Promise<string> {\n return typeof this.mode === \"function\" ? await this.mode() : this.mode;\n }\n\n async request<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const token = await this.resolveToken();\n const orgId = await this.resolveOrgId();\n const mode = await this.resolveMode();\n\n const res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n ...(body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n ...(orgId ? { \"x-org-id\": orgId } : {}),\n \"x-billing-mode\": mode,\n },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as {\n error?: string;\n message?: string;\n };\n throw new BillingApiError(\n res.status,\n err.error ?? err.message ?? `HTTP ${res.status}`,\n );\n }\n\n if (res.status === 202 || res.status === 204) {\n if (res.status === 204) return undefined as T;\n return res.json().catch(() => undefined) as Promise<T>;\n }\n return res.json() as Promise<T>;\n }\n\n get<T>(path: string) {\n return this.request<T>(\"GET\", path);\n }\n\n post<T>(path: string, body?: unknown) {\n return this.request<T>(\"POST\", path, body);\n }\n\n put<T>(path: string, body?: unknown) {\n return this.request<T>(\"PUT\", path, body);\n }\n\n patch<T>(path: string, body?: unknown) {\n return this.request<T>(\"PATCH\", path, body);\n }\n\n delete<T = void>(path: string) {\n return this.request<T>(\"DELETE\", path);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Charge, CreateChargeInput, CreateChargeResult, QuickChargeInput, QuickChargeResult } from \"../types.js\";\n\nexport class ChargesResource {\n constructor(private readonly http: HttpClient) {}\n\n list(params?: { installment_group_id?: string }): Promise<Charge[]> {\n const qs = params?.installment_group_id\n ? `?installment_group_id=${encodeURIComponent(params.installment_group_id)}`\n : \"\";\n return this.http.get<Charge[]>(`/charges${qs}`);\n }\n\n /**\n * Cria uma cobrança (PIX, boleto ou cartão). A geração de fato acontece de forma\n * assíncrona no backend — a resposta volta com a charge em PENDING, sem os campos\n * do método (QR code, boleto, etc) ainda preenchidos. Use `get`/`getStatus` para\n * acompanhar até que estejam prontos.\n */\n create(input: CreateChargeInput): Promise<CreateChargeResult> {\n return this.http.post<CreateChargeResult>(\"/charges\", input);\n }\n\n /**\n * Cobrança avulsa simples, sempre em cartão — cobra direto no cartão padrão já\n * salvo do cliente (sem fricção nenhuma). Se ele ainda não tiver um cartão salvo,\n * retorna `checkout_url` para você abrir (ex: nova aba) e o cliente cadastrar o\n * cartão e pagar.\n *\n * ```ts\n * const result = await client.charges.charge(customerId, 5000); // R$ 50,00\n * if (!result.charged_off_session) {\n * window.open(result.checkout_url!, \"_blank\");\n * }\n * ```\n */\n charge(customerId: string, amountCents: number, options?: Omit<QuickChargeInput, \"customer_id\" | \"amount\">): Promise<QuickChargeResult> {\n return this.http.post<QuickChargeResult>(\"/charges/quick\", {\n customer_id: customerId,\n amount: amountCents,\n ...options,\n });\n }\n\n get(id: string): Promise<Charge> {\n return this.http.get<Charge>(`/charges/${id}`);\n }\n\n getStatus(id: string): Promise<{ status: Charge[\"status\"] }> {\n return this.http.get(`/charges/${id}/status`);\n }\n\n cancel(id: string): Promise<Charge> {\n return this.http.patch<Charge>(`/charges/${id}/cancel`);\n }\n\n refund(id: string): Promise<Charge> {\n return this.http.post<Charge>(`/charges/${id}/refund`);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { CheckoutStatusResult } from \"../types.js\";\n\nexport interface WaitUntilPaidOptions {\n /** Intervalo entre tentativas, em ms. Default: 2000. */\n intervalMs?: number;\n /** Tempo máximo de espera antes de desistir, em ms. Default: 5 minutos. */\n timeoutMs?: number;\n}\n\nexport class CheckoutResource {\n constructor(private readonly http: HttpClient) {}\n\n /** Consulta o status atual de uma cobrança/checkout pelo `checkout_token` retornado\n * por `plans.checkout()` (ou qualquer outro fluxo de cobrança do SDK). Sincroniza com\n * o provedor de pagamento sob o capô quando ainda está PENDING. */\n getStatus(checkoutToken: string): Promise<CheckoutStatusResult> {\n return this.http.get<CheckoutStatusResult>(`/checkout/${checkoutToken}/status`);\n }\n\n /**\n * Faz polling de `getStatus` até o pagamento ser confirmado (ou falhar/expirar) — é\n * a forma recomendada de confirmar, depois de redirecionar o cliente para a\n * `checkout_url`, que a assinatura realmente foi paga antes de liberar acesso.\n *\n * Resolve quando o status deixa de ser PENDING/PROCESSING. Lança um erro se o tempo\n * limite (`timeoutMs`) for atingido antes disso.\n */\n async waitUntilPaid(checkoutToken: string, options: WaitUntilPaidOptions = {}): Promise<CheckoutStatusResult> {\n const intervalMs = options.intervalMs ?? 2000;\n const timeoutMs = options.timeoutMs ?? 5 * 60 * 1000;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n const result = await this.getStatus(checkoutToken);\n if (result.status !== \"PENDING\" && result.status !== \"PROCESSING\") {\n return result;\n }\n if (Date.now() >= deadline) {\n throw new Error(`Tempo limite excedido aguardando confirmação de pagamento (checkout_token=${checkoutToken}).`);\n }\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Coupon, CreateCouponInput } from \"../types.js\";\n\nexport class CouponsResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<Coupon[]> {\n return this.http.get<Coupon[]>(\"/coupons\");\n }\n\n /** `idOrCode` aceita tanto o id interno (`coupon.id`) quanto o `code` legível que você\n * escolheu na criação (ex: `\"BEMVINDO20\"`) — normalmente é mais prático guardar/usar o\n * `code`, já que é você quem o define e é o que aparece para o cliente final. */\n get(idOrCode: string): Promise<Coupon> {\n return this.http.get<Coupon>(`/coupons/${idOrCode}`);\n }\n\n /**\n * Cria um cupom de desconto — o `code` é o que o cliente final informa no checkout\n * (`plans.checkout(planId, { coupon_code })`).\n *\n * ```ts\n * // 20% de desconto, aplicado só na primeira cobrança\n * await client.coupons.create({ code: \"BEMVINDO20\", type: \"PERCENTAGE\", value: 20, duration: \"ONCE\" });\n *\n * // R$10 de desconto, repetido pelas 3 primeiras renovações\n * await client.coupons.create({\n * code: \"R10X3\", type: \"FIXED\", value: 1000, duration: \"REPEATING\", duration_months: 3,\n * });\n * ```\n */\n create(input: CreateCouponInput): Promise<Coupon> {\n return this.http.post<Coupon>(\"/coupons\", input);\n }\n\n /** Só permite editar limites/validade/ativação — o desconto em si (type/value/duration)\n * de um cupom já criado é imutável; crie um novo código para mudar o valor do desconto.\n * `idOrCode` aceita id interno ou `code` (ver `get`). */\n update(idOrCode: string, input: Partial<Pick<CreateCouponInput, \"max_redemptions\" | \"expires_at\">> & { active?: boolean }): Promise<Coupon> {\n return this.http.patch<Coupon>(`/coupons/${idOrCode}`, input);\n }\n\n /** Desativa o cupom (soft-delete) — códigos já resgatados continuam no histórico.\n * `idOrCode` aceita id interno ou `code` (ver `get`). */\n remove(idOrCode: string): Promise<void> {\n return this.http.delete<void>(`/coupons/${idOrCode}`);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Customer, CustomerInput } from \"../types.js\";\n\nexport class CustomersResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<Customer[]> {\n return this.http.get<Customer[]>(\"/customers\");\n }\n\n create(input: CustomerInput): Promise<Customer> {\n return this.http.post<Customer>(\"/customers\", input);\n }\n\n get(id: string): Promise<Customer> {\n return this.http.get<Customer>(`/customers/${id}`);\n }\n\n update(id: string, input: Partial<CustomerInput>): Promise<Customer> {\n return this.http.patch<Customer>(`/customers/${id}`, input);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { BillingItem } from \"../types.js\";\n\nexport interface ItemInput {\n name: string;\n description?: string;\n amount: number;\n currency?: string;\n}\n\nexport class ItemsResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<BillingItem[]> {\n return this.http.get<BillingItem[]>(\"/items\");\n }\n\n create(input: ItemInput): Promise<BillingItem> {\n return this.http.post<BillingItem>(\"/items\", input);\n }\n\n get(id: string): Promise<BillingItem> {\n return this.http.get<BillingItem>(`/items/${id}`);\n }\n\n update(id: string, input: Partial<ItemInput>): Promise<BillingItem> {\n return this.http.patch<BillingItem>(`/items/${id}`, input);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { CreateOrderInput, CreateOrderResult } from \"../types.js\";\n\nexport class OrdersResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Cria um pedido parcelado (parcelamento real via cobranças avulsas agendadas,\n * não assinatura). Retorna o `client_secret` da 1ª parcela para o front-end\n * confirmar via Stripe Elements — as parcelas seguintes são cobradas\n * automaticamente pelo backend no cartão salvo.\n */\n create(input: CreateOrderInput): Promise<CreateOrderResult> {\n return this.http.post<CreateOrderResult>(\"/orders\", input);\n }\n\n list(): Promise<unknown[]> {\n return this.http.get(\"/orders\");\n }\n\n get(id: string): Promise<unknown> {\n return this.http.get(`/orders/${id}`);\n }\n}\n","import type { HttpClient } from \"../http.js\";\r\nimport type {\r\n BillingPlanSummary,\r\n CheckoutForCustomerInput,\r\n CheckoutForCustomerResult,\r\n CreateBillingPlanInput,\r\n GetPublicPlanPageResult,\r\n ListPublicPlansResult,\r\n PlanCheckoutInput,\r\n PlanCheckoutResult,\r\n PlanSubscriptionStatusResult,\r\n} from \"../types.js\";\r\n\r\nexport class PlansResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n list(): Promise<BillingPlanSummary[]> {\r\n return this.http.get<BillingPlanSummary[]>(\"/billing-plans\");\r\n }\r\n\r\n get(id: string): Promise<BillingPlanSummary> {\r\n return this.http.get<BillingPlanSummary>(`/billing-plans/${id}`);\r\n }\r\n\r\n create(input: CreateBillingPlanInput): Promise<BillingPlanSummary> {\r\n return this.http.post<BillingPlanSummary>(\"/billing-plans\", input);\r\n }\r\n\r\n update(id: string, input: Partial<CreateBillingPlanInput> & { active?: boolean }): Promise<BillingPlanSummary> {\r\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${id}`, input);\r\n }\r\n\r\n /** Não há hard-delete de planos (assinaturas existentes ainda referenciam) — para\r\n * remover um plano do catálogo público, arquive-o. */\r\n archive(id: string): Promise<BillingPlanSummary> {\r\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${id}`, { active: false });\r\n }\r\n\r\n /** Vincula um plano avulso a uma página de planos existente (mesma org). */\r\n attachToPage(planId: string, pageId: string): Promise<BillingPlanSummary> {\r\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${planId}`, { plan_page_id: pageId });\r\n }\r\n\r\n /** Desvincula um plano da sua página, tornando-o avulso (sem página pública). */\r\n detachFromPage(planId: string): Promise<BillingPlanSummary> {\r\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${planId}`, { plan_page_id: null });\r\n }\r\n\r\n /**\r\n * Fluxo simplificado de assinatura para um `Customer` já cadastrado na sua org\r\n * (autenticado, sem formulário de nome/e-mail): cria a assinatura + cobrança inicial e\r\n * retorna a URL de checkout hospedada.\r\n *\r\n * ```ts\r\n * const { checkout_url } = await client.plans.checkoutPlan(planId, customerId, {\r\n * return_url: \"https://meuapp.com/conta?upgraded=1\",\r\n * });\r\n * // redirecione o cliente para checkout_url; ele paga e volta para sua URL de retorno\r\n *\r\n * // depois que o cliente volta:\r\n * const { active, item } = await client.plans.confirmPlanSubscription(planId, customerId);\r\n * if (active) {\r\n * // ativa o plano real no seu sistema\r\n * }\r\n * ```\r\n */\r\n checkoutPlan(planId: string, customerId: string, input?: CheckoutForCustomerInput): Promise<CheckoutForCustomerResult> {\r\n return this.http.post<CheckoutForCustomerResult>(`/billing-plans/${planId}/checkout-for-customer`, {\r\n customer_id: customerId,\r\n ...(input?.return_url ? { return_url: input.return_url } : {}),\r\n ...(input?.expires_in ? { expires_in: input.expires_in } : {}),\r\n ...(input?.coupon_code ? { coupon_code: input.coupon_code } : {}),\r\n });\r\n }\r\n\r\n /** Verifica se um `Customer` tem uma assinatura ativa deste plano (a mais recente),\r\n * contraparte de `checkoutPlan` no fluxo simplificado autenticado. */\r\n confirmPlanSubscription(planId: string, customerId: string): Promise<PlanSubscriptionStatusResult> {\r\n return this.http.get<PlanSubscriptionStatusResult>(`/billing-plans/${planId}/subscription-status?customer_id=${encodeURIComponent(customerId)}`);\r\n }\r\n\r\n // ─── Rotas públicas (sem auth — usadas para montar sua própria página de preços) ──\r\n\r\n /** Lista os planos ativos de uma org pelo slug público — página fixa legada, sem\r\n * suporte a múltiplas páginas. Prefira `getPublicPage` para orgs com várias páginas. */\r\n listPublic(orgSlug: string): Promise<ListPublicPlansResult> {\r\n return this.http.get<ListPublicPlansResult>(`/public/orgs/${orgSlug}/billing-plans`);\r\n }\r\n\r\n /** Busca uma página de planos pública específica pelo slug da org + slug da página. */\r\n getPublicPage(orgSlug: string, pageSlug: string): Promise<GetPublicPlanPageResult> {\r\n return this.http.get<GetPublicPlanPageResult>(`/public/orgs/${orgSlug}/plan-pages/${pageSlug}`);\r\n }\r\n\r\n /**\r\n * Inicia a assinatura de um plano para um cliente final: cria (ou reaproveita) o\r\n * `Customer` pelo e-mail, cria a `Subscription` e retorna uma URL de checkout hospedada\r\n * pela Geekapps para o cliente confirmar o pagamento.\r\n *\r\n * Fluxo típico:\r\n * ```ts\r\n * const { checkout_url, checkout_token } = await client.plans.checkout(planId, {\r\n * customer: { name, email },\r\n * coupon_code: \"PROMO20\", // opcional — página já abre com o desconto aplicado\r\n * });\r\n * // redirecione o cliente (ou abra checkout_url em uma WebView/nova aba)\r\n * window.location.href = checkout_url;\r\n *\r\n * // depois do retorno, confirme se realmente foi pago:\r\n * const { status } = await client.checkout.waitUntilPaid(checkout_token);\r\n * if (status === \"PAID\") { /* liberar acesso *\\/ }\r\n * ```\r\n *\r\n * Não requer autenticação — pode ser chamado a partir do backend do dev sem token de\r\n * service account, ou do próprio SDK server-side usando qualquer token válido.\r\n */\r\n checkout(planId: string, input: PlanCheckoutInput): Promise<PlanCheckoutResult> {\r\n return this.http.post<PlanCheckoutResult>(`/public/billing-plans/${planId}/checkout`, input);\r\n }\r\n}\r\n","import type { HttpClient } from \"../http.js\";\r\nimport type { CreateSubscriptionInput, CreateSubscriptionResult, Subscription, SubscriptionStatusResult } from \"../types.js\";\r\n\r\nexport class SubscriptionsResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /** Requer autenticação (service account) — lista todas as assinaturas da sua org. */\r\n list(): Promise<Subscription[]> {\r\n return this.http.get<Subscription[]>(\"/billing-subscriptions\");\r\n }\r\n\r\n /**\r\n * Fluxo legado de assinatura por `BillingItem` avulso (sem `BillingPlan`) — requer\r\n * autenticação (service account) e que `customer_id`/`item_id` já existam na sua org.\r\n * Prefira `plans.checkout`/`plans.checkoutPlan` para novos catálogos baseados em plano.\r\n *\r\n * ```ts\r\n * await client.subscriptions.create({\r\n * customer_id, item_id, interval: \"MONTHLY\", coupon_code: \"PROMO20\",\r\n * });\r\n * ```\r\n */\r\n create(input: CreateSubscriptionInput): Promise<CreateSubscriptionResult> {\r\n return this.http.post<CreateSubscriptionResult>(\"/billing-subscriptions\", input);\r\n }\r\n\r\n /** Requer autenticação (service account). */\r\n get(id: string): Promise<Subscription> {\r\n return this.http.get<Subscription>(`/billing-subscriptions/${id}`);\r\n }\r\n\r\n /** Requer autenticação (service account). */\r\n cancel(id: string): Promise<Subscription> {\r\n return this.http.patch<Subscription>(`/billing-subscriptions/${id}/cancel`);\r\n }\r\n\r\n /**\r\n * Inicia uma troca de plano/item de uma assinatura já existente (upgrade/downgrade de\r\n * tier) — requer autenticação (service account). NÃO executa a troca diretamente: retorna\r\n * um link de confirmação para o cliente final revisar custo e vigência e confirmar\r\n * expressamente antes de qualquer cobrança ou mudança de plano acontecer.\r\n *\r\n * `couponCode`: aplica um cupom na troca — se a assinatura for Stripe, o desconto passa a\r\n * valer também nas renovações futuras (recorrente, direto na Subscription); se for\r\n * PIX/boleto, o desconto vale só para a cobrança de proration desta troca.\r\n *\r\n * ```ts\r\n * const { confirmation_url } = await client.subscriptions.requestPlanSwap(subId, newPlanId, {\r\n * couponCode: \"PROMO20\",\r\n * });\r\n * // redirecione o cliente final para confirmation_url\r\n * ```\r\n */\r\n requestPlanSwap(\r\n id: string,\r\n newPlanId: string,\r\n options?: { expiresInSeconds?: number; couponCode?: string },\r\n ): Promise<{ confirmation_url: string }> {\r\n return this.http.patch(`/billing-subscriptions/${id}/swap`, {\r\n new_plan_id: newPlanId,\r\n ...(options?.expiresInSeconds ? { expires_in: options.expiresInSeconds } : {}),\r\n ...(options?.couponCode ? { coupon_code: options.couponCode } : {}),\r\n });\r\n }\r\n\r\n /**\r\n * Verifica se uma assinatura está ativa e qual item ela cobre, usando o\r\n * `management_token` retornado por `plans.checkout()` — rota pública, sem\r\n * autenticação, segura para chamar tanto do seu backend quanto (via fetch direto,\r\n * sem o SDK) do client-side do seu app.\r\n *\r\n * ```ts\r\n * const status = await client.subscriptions.checkByToken(managementToken);\r\n * if (status.subscription.active) {\r\n * console.log(\"cobrando\", status.item.name);\r\n * }\r\n * ```\r\n */\r\n checkByToken(managementToken: string): Promise<SubscriptionStatusResult> {\r\n return this.http.get<SubscriptionStatusResult>(`/public/plan-management/${managementToken}`);\r\n }\r\n}\r\n","import type { HttpClient } from \"../http.js\";\r\n\r\nexport type OutboundWebhookEventType =\r\n | \"SUBSCRIPTION_CREATED\"\r\n | \"SUBSCRIPTION_ACTIVATED\"\r\n | \"SUBSCRIPTION_RENEWED\"\r\n | \"SUBSCRIPTION_PLAN_SWAPPED\"\r\n | \"SUBSCRIPTION_PAST_DUE\"\r\n | \"SUBSCRIPTION_CANCELLED\"\r\n | \"SUBSCRIPTION_CANCEL_SCHEDULE\"\r\n | \"SUBSCRIPTION_RESUMED\"\r\n | \"CHARGE_PAID\"\r\n | \"CHARGE_FAILED\"\r\n | \"CHARGE_EXPIRED\"\r\n | \"CHARGE_REFUNDED\";\r\n\r\n/** Payload de uma cobrança (`data`) nos eventos CHARGE_*. `description` é `null` quando\r\n * a cobrança não tem descrição definida. */\r\nexport interface ChargeEventData {\r\n chargeId: string;\r\n amountCents: number;\r\n description: string | null;\r\n}\r\n\r\n/** Union discriminada por `event_type` — use para tipar o corpo recebido na sua rota de\r\n * webhook (ver `X-Geekapps-Signature` para validar a assinatura antes de confiar no payload).\r\n *\r\n * ```ts\r\n * const event = JSON.parse(rawBody) as WebhookEvent;\r\n * switch (event.event_type) {\r\n * case \"CHARGE_PAID\":\r\n * // event.data: { chargeId, amountCents, description }\r\n * break;\r\n * case \"SUBSCRIPTION_CANCELLED\":\r\n * // event.data: { subscriptionId }\r\n * break;\r\n * }\r\n * ```\r\n */\r\nexport type WebhookEvent =\r\n | {\r\n event_type: \"SUBSCRIPTION_CREATED\";\r\n org_id: string;\r\n data: { subscriptionId: string; customerId: string; itemId: string; interval: string };\r\n }\r\n | {\r\n event_type: \"SUBSCRIPTION_ACTIVATED\";\r\n org_id: string;\r\n data: { subscriptionId: string };\r\n }\r\n | {\r\n /** Disparado a cada renovação paga com sucesso — em toda cobrança recorrente\r\n * confirmada, independente do status anterior da assinatura (distinto de\r\n * SUBSCRIPTION_ACTIVATED, que só marca a transição de volta pra ACTIVE). */\r\n event_type: \"SUBSCRIPTION_RENEWED\";\r\n org_id: string;\r\n data: { subscriptionId: string; chargeId: string | null };\r\n }\r\n | {\r\n event_type: \"SUBSCRIPTION_PLAN_SWAPPED\";\r\n org_id: string;\r\n data: { subscriptionId: string; oldPlanId: string; newPlanId: string; mode: string };\r\n }\r\n | {\r\n event_type: \"SUBSCRIPTION_PAST_DUE\";\r\n org_id: string;\r\n data: { subscriptionId: string };\r\n }\r\n | {\r\n event_type: \"SUBSCRIPTION_CANCELLED\";\r\n org_id: string;\r\n data: { subscriptionId: string };\r\n }\r\n | {\r\n /** Disparado quando um cancelamento é agendado para o fim do período vigente\r\n * (política END_OF_PERIOD ou cancelamento/reversão feito no Stripe Billing Portal) —\r\n * a assinatura continua ACTIVE até `data.effective_at`; distinto de\r\n * SUBSCRIPTION_CANCELLED, que marca o cancelamento definitivo. */\r\n event_type: \"SUBSCRIPTION_CANCEL_SCHEDULE\";\r\n org_id: string;\r\n data: { subscriptionId: string; effective_at: string | null };\r\n }\r\n | {\r\n /** Disparado quando um cancelamento agendado (SUBSCRIPTION_CANCEL_SCHEDULE) é\r\n * revertido antes do fim do período — a assinatura volta a renovar normalmente. */\r\n event_type: \"SUBSCRIPTION_RESUMED\";\r\n org_id: string;\r\n data: { subscriptionId: string };\r\n }\r\n | {\r\n event_type: \"CHARGE_PAID\";\r\n org_id: string;\r\n data: ChargeEventData;\r\n }\r\n | {\r\n event_type: \"CHARGE_FAILED\";\r\n org_id: string;\r\n data: ChargeEventData;\r\n }\r\n | {\r\n event_type: \"CHARGE_EXPIRED\";\r\n org_id: string;\r\n data: ChargeEventData;\r\n }\r\n | {\r\n event_type: \"CHARGE_REFUNDED\";\r\n org_id: string;\r\n data: ChargeEventData;\r\n };\r\n\r\nexport interface WebhookEndpointInput {\r\n url: string;\r\n eventTypes: OutboundWebhookEventType[];\r\n /** Opcional — quando omitido, o servidor gera um secret automaticamente. */\r\n secret?: string;\r\n}\r\n\r\nexport interface WebhookEndpointSummary {\r\n id: string;\r\n url: string;\r\n event_types: OutboundWebhookEventType[];\r\n active: boolean;\r\n /** Segredo completo apenas na primeira criação — em toda resposta subsequente vem mascarado. */\r\n secret: string;\r\n created_at: string;\r\n updated_at: string;\r\n}\r\n\r\nexport class WebhooksResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /** Lista os webhooks outbound cadastrados na sua org (secret sempre mascarado). */\r\n list(): Promise<WebhookEndpointSummary[]> {\r\n return this.http.get<WebhookEndpointSummary[]>(\"/webhook-endpoints\");\r\n }\r\n\r\n /**\r\n * Registra um webhook outbound — idempotente por (org, url): chamar de novo com a\r\n * mesma URL apenas atualiza os `eventTypes`, sem criar duplicata. Guarde o `secret`\r\n * retornado (só vem completo na primeira criação) para validar a assinatura\r\n * `X-Geekapps-Signature` nas entregas recebidas. Passe `secret` para definir o seu\r\n * próprio signing secret; se omitido, um valor aleatório é gerado automaticamente.\r\n */\r\n register(input: WebhookEndpointInput): Promise<WebhookEndpointSummary> {\r\n return this.http.post<WebhookEndpointSummary>(\"/webhook-endpoints\", {\r\n url: input.url,\r\n event_types: input.eventTypes,\r\n ...(input.secret ? { secret: input.secret } : {}),\r\n });\r\n }\r\n\r\n /** Edita um webhook existente — URL, eventos assinados e/ou status ativo/inativo. */\r\n update(id: string, input: Partial<WebhookEndpointInput> & { active?: boolean }): Promise<WebhookEndpointSummary> {\r\n return this.http.patch<WebhookEndpointSummary>(`/webhook-endpoints/${id}`, {\r\n ...(input.url ? { url: input.url } : {}),\r\n ...(input.eventTypes ? { event_types: input.eventTypes } : {}),\r\n ...(input.active !== undefined ? { active: input.active } : {}),\r\n });\r\n }\r\n\r\n /** Gera um novo secret e substitui o atual — a versão antiga deixa de validar imediatamente. */\r\n rotateSecret(id: string): Promise<WebhookEndpointSummary> {\r\n return this.http.post<WebhookEndpointSummary>(`/webhook-endpoints/${id}/rotate-secret`);\r\n }\r\n\r\n remove(id: string): Promise<void> {\r\n return this.http.delete<void>(`/webhook-endpoints/${id}`);\r\n }\r\n}\r\n","import { HttpClient, type HttpClientOptions } from \"./http.js\";\r\nimport { ChargesResource } from \"./resources/charges.js\";\r\nimport { CheckoutResource } from \"./resources/checkout.js\";\r\nimport { CouponsResource } from \"./resources/coupons.js\";\r\nimport { CustomersResource } from \"./resources/customers.js\";\r\nimport { ItemsResource } from \"./resources/items.js\";\r\nimport { OrdersResource } from \"./resources/orders.js\";\r\nimport { PlansResource } from \"./resources/plans.js\";\r\nimport { SubscriptionsResource } from \"./resources/subscriptions.js\";\r\nimport { WebhooksResource } from \"./resources/webhooks.js\";\r\n\r\nexport interface BillingClientOptions\r\n extends Omit<HttpClientOptions, \"baseUrl\"> {\r\n baseUrl?: string;\r\n}\r\n\r\nexport class BillingClient {\r\n private readonly http: HttpClient;\r\n\r\n readonly charges: ChargesResource;\r\n readonly checkout: CheckoutResource;\r\n readonly coupons: CouponsResource;\r\n readonly customers: CustomersResource;\r\n readonly items: ItemsResource;\r\n readonly orders: OrdersResource;\r\n readonly plans: PlansResource;\r\n readonly subscriptions: SubscriptionsResource;\r\n readonly webhooks: WebhooksResource;\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.http = new HttpClient(options);\r\n\r\n this.charges = new ChargesResource(this.http);\r\n this.checkout = new CheckoutResource(this.http);\r\n this.coupons = new CouponsResource(this.http);\r\n this.customers = new CustomersResource(this.http);\r\n this.items = new ItemsResource(this.http);\r\n this.orders = new OrdersResource(this.http);\r\n this.plans = new PlansResource(this.http);\r\n this.subscriptions = new SubscriptionsResource(this.http);\r\n this.webhooks = new WebhooksResource(this.http);\r\n }\r\n}\r\n","import type { FastifyInstance, FastifyPluginAsync } from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { BillingClient } from \"./client.js\";\nimport { ServiceAccountTokenProvider, type ServiceAccountOptions } from \"./service-account.js\";\n\nexport interface BillingPluginOptions {\n /** Geekapps Billing API base URL */\n baseUrl: string;\n /** Service account credentials — required */\n serviceAccount: ServiceAccountOptions;\n /** Ambiente de billing (dev/prod). Default: \"prod\". */\n mode?: string;\n}\n\ndeclare module \"fastify\" {\n interface FastifyInstance {\n billingClient: BillingClient;\n }\n}\n\nconst billingPlugin: FastifyPluginAsync<BillingPluginOptions> = async (\n fastify: FastifyInstance,\n options: BillingPluginOptions,\n) => {\n const tokenProvider = new ServiceAccountTokenProvider(options.serviceAccount);\n\n const client = new BillingClient({\n baseUrl: options.baseUrl,\n token: () => tokenProvider.getToken(),\n organizationId: () => tokenProvider.getOrganizationId() as Promise<string>,\n mode: options.mode,\n });\n\n fastify.decorate(\"billingClient\", client);\n};\n\nexport default fp(billingPlugin, {\n fastify: \">=4.0.0\",\n name: \"@geekapps/billing-fastify\",\n});\n","import type { TokenResolver } from \"./http.js\";\n\nexport interface ServiceAccountOptions {\n /** Geekapps Auth issuer base URL (e.g. https://accounts-api.geekapps.com.br) */\n issuerUrl: string;\n clientId: string;\n clientSecret: string;\n /** Seconds before expiry to proactively refresh. Defaults to 30. */\n refreshBeforeExpirySeconds?: number;\n}\n\ninterface CachedToken {\n value: string;\n expiresAt: number; // ms epoch\n organizationId: string | undefined;\n}\n\nfunction decodeJwtPayload(token: string): Record<string, unknown> {\n try {\n const [, payload] = token.split(\".\");\n if (!payload) return {};\n const json = Buffer.from(payload, \"base64url\").toString(\"utf-8\");\n return JSON.parse(json) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/**\n * Fetches a short-lived token from the Geekapps Auth service using\n * client_credentials grant and caches it until near expiry.\n *\n * The organizationId claim is extracted automatically from the JWT payload.\n */\nexport class ServiceAccountTokenProvider {\n private readonly issuerUrl: string;\n private readonly clientId: string;\n private readonly clientSecret: string;\n private readonly refreshBeforeMs: number;\n private cached: CachedToken | null = null;\n private inflight: Promise<CachedToken> | null = null;\n\n constructor(options: ServiceAccountOptions) {\n this.issuerUrl = options.issuerUrl.replace(/\\/$/, \"\");\n this.clientId = options.clientId;\n this.clientSecret = options.clientSecret;\n this.refreshBeforeMs = (options.refreshBeforeExpirySeconds ?? 30) * 1000;\n }\n\n private async ensureFresh(): Promise<CachedToken> {\n const now = Date.now();\n\n if (this.cached && this.cached.expiresAt - now > this.refreshBeforeMs) {\n return this.cached;\n }\n\n if (this.inflight) return this.inflight;\n\n this.inflight = this.fetchToken().finally(() => {\n this.inflight = null;\n });\n\n return this.inflight;\n }\n\n /** Returns a valid access token. */\n getToken(): Promise<string> {\n return this.ensureFresh().then((c) => c.value);\n }\n\n /** Returns the organizationId embedded in the service account JWT. */\n getOrganizationId(): Promise<string | undefined> {\n return this.ensureFresh().then((c) => c.organizationId);\n }\n\n private async fetchToken(): Promise<CachedToken> {\n const credentials = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString(\"base64\");\n\n const res = await fetch(`${this.issuerUrl}/auth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Basic ${credentials}`,\n },\n body: JSON.stringify({ grant_type: \"service_account\" }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n throw new Error(\n `ServiceAccount token fetch failed (${res.status}): ${err.error ?? \"unknown error\"}`,\n );\n }\n\n const data = await res.json() as { access_token: string; expires_in?: number };\n\n const claims = decodeJwtPayload(data.access_token);\n const organizationId =\n typeof claims.organizationId === \"string\" ? claims.organizationId :\n typeof claims.organization_id === \"string\" ? claims.organization_id :\n typeof claims.org_id === \"string\" ? claims.org_id :\n undefined;\n\n const expiresInMs = (data.expires_in ?? 420) * 1000;\n this.cached = {\n value: data.access_token,\n expiresAt: Date.now() + expiresInMs,\n organizationId,\n };\n\n return this.cached;\n }\n\n /** Returns this provider as a TokenResolver to pass directly to BillingClient. */\n asTokenResolver(): TokenResolver {\n return () => this.getToken();\n }\n}\n\n/** Convenience factory. Returns a TokenResolver ready for use in BillingClient. */\nexport function createServiceAccountToken(\n options: ServiceAccountOptions,\n): TokenResolver {\n return new ServiceAccountTokenProvider(options).asTokenResolver();\n}\n","export type ExpirationUnit = \"seconds\" | \"minutes\" | \"hours\" | \"days\";\n\nconst MULTIPLIERS: Record<ExpirationUnit, number> = {\n seconds: 1,\n minutes: 60,\n hours: 3600,\n days: 86400,\n};\n\n/**\n * Converte um valor + unidade para segundos, prontos para usar em `expires_in`.\n *\n * ```ts\n * await client.charges.create({ ..., expires_in: expiresIn(30, \"minutes\") });\n * ```\n */\nexport function expiresIn(value: number, unit: ExpirationUnit): number {\n return value * MULTIPLIERS[unit];\n}\n"],"mappings":"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","names":["fp"]}
1
+ {"version":3,"sources":["../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/lib/getPluginName.js","../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/lib/toCamelCase.js","../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/index.js","../src/errors.ts","../src/http.ts","../src/resources/charges.ts","../src/resources/checkout.ts","../src/resources/coupons.ts","../src/resources/customers.ts","../src/resources/items.ts","../src/resources/orders.ts","../src/resources/plans.ts","../src/resources/subscriptions.ts","../src/resources/webhooks.ts","../src/client.ts","../src/plugin.ts","../src/service-account.ts","../src/expiration.ts"],"sourcesContent":["'use strict'\n\nconst fpStackTracePattern = /at\\s(?:.*\\.)?plugin\\s.*\\n\\s*(.*)/\nconst fileNamePattern = /(\\w*(\\.\\w*)*)\\..*/\n\nmodule.exports = function getPluginName (fn) {\n if (fn.name.length > 0) return fn.name\n\n const stackTraceLimit = Error.stackTraceLimit\n Error.stackTraceLimit = 10\n try {\n throw new Error('anonymous function')\n } catch (e) {\n Error.stackTraceLimit = stackTraceLimit\n return extractPluginName(e.stack)\n }\n}\n\nfunction extractPluginName (stack) {\n const m = stack.match(fpStackTracePattern)\n\n // get last section of path and match for filename\n return m ? m[1].split(/[/\\\\]/).slice(-1)[0].match(fileNamePattern)[1] : 'anonymous'\n}\nmodule.exports.extractPluginName = extractPluginName\n","'use strict'\n\nmodule.exports = function toCamelCase (name) {\n if (name[0] === '@') {\n name = name.slice(1).replace('/', '-')\n }\n return name.replace(/-(.)/g, function (match, g1) {\n return g1.toUpperCase()\n })\n}\n","'use strict'\n\nconst getPluginName = require('./lib/getPluginName')\nconst toCamelCase = require('./lib/toCamelCase')\n\nlet count = 0\n\nfunction plugin (fn, options = {}) {\n let autoName = false\n\n if (fn.default !== undefined) {\n // Support for 'export default' behaviour in transpiled ECMAScript module\n fn = fn.default\n }\n\n if (typeof fn !== 'function') {\n throw new TypeError(\n `fastify-plugin expects a function, instead got a '${typeof fn}'`\n )\n }\n\n if (typeof options === 'string') {\n options = {\n fastify: options\n }\n }\n\n if (\n typeof options !== 'object' ||\n Array.isArray(options) ||\n options === null\n ) {\n throw new TypeError('The options object should be an object')\n }\n\n if (options.fastify !== undefined && typeof options.fastify !== 'string') {\n throw new TypeError(`fastify-plugin expects a version string, instead got '${typeof options.fastify}'`)\n }\n\n if (!options.name) {\n autoName = true\n options.name = getPluginName(fn) + '-auto-' + count++\n }\n\n fn[Symbol.for('skip-override')] = options.encapsulate !== true\n fn[Symbol.for('fastify.display-name')] = options.name\n fn[Symbol.for('plugin-meta')] = options\n\n // Faux modules support\n if (!fn.default) {\n fn.default = fn\n }\n\n // TypeScript support for named imports\n // See https://github.com/fastify/fastify/issues/2404 for more details\n // The type definitions would have to be update to match this.\n const camelCase = toCamelCase(options.name)\n if (!autoName && !fn[camelCase]) {\n fn[camelCase] = fn\n }\n\n return fn\n}\n\nmodule.exports = plugin\nmodule.exports.default = plugin\nmodule.exports.fastifyPlugin = plugin\n","export class BillingApiError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly detail?: string,\n ) {\n super(detail ? `${message}: ${detail}` : message);\n this.name = \"BillingApiError\";\n }\n\n get isNotFound() {\n return this.status === 404;\n }\n\n get isUnauthorized() {\n return this.status === 401;\n }\n\n get isForbidden() {\n return this.status === 403;\n }\n\n get isRateLimited() {\n return this.status === 429;\n }\n\n get isValidationError() {\n return this.status === 400 || this.status === 422;\n }\n}\n","import { BillingApiError } from \"./errors.js\";\n\nexport type TokenResolver = string | (() => string | Promise<string>);\n\nexport interface HttpClientOptions {\n baseUrl: string;\n token: TokenResolver;\n organizationId?: string | (() => string | Promise<string>);\n /**\n * Ambiente de billing (dev/prod) — enviado via header x-billing-mode em toda chamada\n * feita por esta instância. Defina uma vez aqui; os métodos individuais (charges.create,\n * customers.list, etc) nunca precisam recebê-lo de novo. Default: \"prod\".\n */\n mode?: string | (() => string | Promise<string>);\n}\n\nconst DEFAULT_MODE = \"prod\";\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly token: TokenResolver;\n private readonly organizationId?: string | (() => string | Promise<string>);\n private readonly mode: string | (() => string | Promise<string>);\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.token = options.token;\n this.organizationId = options.organizationId;\n this.mode = options.mode ?? DEFAULT_MODE;\n }\n\n private async resolveToken(): Promise<string> {\n return typeof this.token === \"function\" ? await this.token() : this.token;\n }\n\n private async resolveOrgId(): Promise<string | undefined> {\n if (!this.organizationId) return undefined;\n return typeof this.organizationId === \"function\"\n ? await this.organizationId()\n : this.organizationId;\n }\n\n private async resolveMode(): Promise<string> {\n return typeof this.mode === \"function\" ? await this.mode() : this.mode;\n }\n\n async request<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const token = await this.resolveToken();\n const orgId = await this.resolveOrgId();\n const mode = await this.resolveMode();\n\n const res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n ...(body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n ...(orgId ? { \"x-org-id\": orgId } : {}),\n \"x-billing-mode\": mode,\n },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as {\n error?: string;\n message?: string;\n };\n throw new BillingApiError(\n res.status,\n err.error ?? err.message ?? `HTTP ${res.status}`,\n );\n }\n\n if (res.status === 202 || res.status === 204) {\n if (res.status === 204) return undefined as T;\n return res.json().catch(() => undefined) as Promise<T>;\n }\n return res.json() as Promise<T>;\n }\n\n get<T>(path: string) {\n return this.request<T>(\"GET\", path);\n }\n\n post<T>(path: string, body?: unknown) {\n return this.request<T>(\"POST\", path, body);\n }\n\n put<T>(path: string, body?: unknown) {\n return this.request<T>(\"PUT\", path, body);\n }\n\n patch<T>(path: string, body?: unknown) {\n return this.request<T>(\"PATCH\", path, body);\n }\n\n delete<T = void>(path: string) {\n return this.request<T>(\"DELETE\", path);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Charge, CreateChargeInput, CreateChargeResult, QuickChargeInput, QuickChargeResult } from \"../types.js\";\n\nexport class ChargesResource {\n constructor(private readonly http: HttpClient) {}\n\n list(params?: { installment_group_id?: string }): Promise<Charge[]> {\n const qs = params?.installment_group_id\n ? `?installment_group_id=${encodeURIComponent(params.installment_group_id)}`\n : \"\";\n return this.http.get<Charge[]>(`/charges${qs}`);\n }\n\n /**\n * Cria uma cobrança (PIX, boleto ou cartão). A geração de fato acontece de forma\n * assíncrona no backend — a resposta volta com a charge em PENDING, sem os campos\n * do método (QR code, boleto, etc) ainda preenchidos. Use `get`/`getStatus` para\n * acompanhar até que estejam prontos.\n */\n create(input: CreateChargeInput): Promise<CreateChargeResult> {\n return this.http.post<CreateChargeResult>(\"/charges\", input);\n }\n\n /**\n * Cobrança avulsa simples, sempre em cartão — cobra direto no cartão padrão já\n * salvo do cliente (sem fricção nenhuma). Se ele ainda não tiver um cartão salvo,\n * retorna `checkout_url` para você abrir (ex: nova aba) e o cliente cadastrar o\n * cartão e pagar.\n *\n * ```ts\n * const result = await client.charges.charge(customerId, 5000); // R$ 50,00\n * if (!result.charged_off_session) {\n * window.open(result.checkout_url!, \"_blank\");\n * }\n * ```\n */\n charge(customerId: string, amountCents: number, options?: Omit<QuickChargeInput, \"customer_id\" | \"amount\">): Promise<QuickChargeResult> {\n return this.http.post<QuickChargeResult>(\"/charges/quick\", {\n customer_id: customerId,\n amount: amountCents,\n ...options,\n });\n }\n\n get(id: string): Promise<Charge> {\n return this.http.get<Charge>(`/charges/${id}`);\n }\n\n getStatus(id: string): Promise<{ status: Charge[\"status\"] }> {\n return this.http.get(`/charges/${id}/status`);\n }\n\n cancel(id: string): Promise<Charge> {\n return this.http.patch<Charge>(`/charges/${id}/cancel`);\n }\n\n refund(id: string): Promise<Charge> {\n return this.http.post<Charge>(`/charges/${id}/refund`);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { CheckoutStatusResult } from \"../types.js\";\n\nexport interface WaitUntilPaidOptions {\n /** Intervalo entre tentativas, em ms. Default: 2000. */\n intervalMs?: number;\n /** Tempo máximo de espera antes de desistir, em ms. Default: 5 minutos. */\n timeoutMs?: number;\n}\n\nexport class CheckoutResource {\n constructor(private readonly http: HttpClient) {}\n\n /** Consulta o status atual de uma cobrança/checkout pelo `checkout_token` retornado\n * por `plans.checkout()` (ou qualquer outro fluxo de cobrança do SDK). Sincroniza com\n * o provedor de pagamento sob o capô quando ainda está PENDING. */\n getStatus(checkoutToken: string): Promise<CheckoutStatusResult> {\n return this.http.get<CheckoutStatusResult>(`/checkout/${checkoutToken}/status`);\n }\n\n /**\n * Faz polling de `getStatus` até o pagamento ser confirmado (ou falhar/expirar) — é\n * a forma recomendada de confirmar, depois de redirecionar o cliente para a\n * `checkout_url`, que a assinatura realmente foi paga antes de liberar acesso.\n *\n * Resolve quando o status deixa de ser PENDING/PROCESSING. Lança um erro se o tempo\n * limite (`timeoutMs`) for atingido antes disso.\n */\n async waitUntilPaid(checkoutToken: string, options: WaitUntilPaidOptions = {}): Promise<CheckoutStatusResult> {\n const intervalMs = options.intervalMs ?? 2000;\n const timeoutMs = options.timeoutMs ?? 5 * 60 * 1000;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n const result = await this.getStatus(checkoutToken);\n if (result.status !== \"PENDING\" && result.status !== \"PROCESSING\") {\n return result;\n }\n if (Date.now() >= deadline) {\n throw new Error(`Tempo limite excedido aguardando confirmação de pagamento (checkout_token=${checkoutToken}).`);\n }\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Coupon, CreateCouponInput } from \"../types.js\";\n\nexport class CouponsResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<Coupon[]> {\n return this.http.get<Coupon[]>(\"/coupons\");\n }\n\n /** `idOrCode` aceita tanto o id interno (`coupon.id`) quanto o `code` legível que você\n * escolheu na criação (ex: `\"BEMVINDO20\"`) — normalmente é mais prático guardar/usar o\n * `code`, já que é você quem o define e é o que aparece para o cliente final. */\n get(idOrCode: string): Promise<Coupon> {\n return this.http.get<Coupon>(`/coupons/${idOrCode}`);\n }\n\n /**\n * Cria um cupom de desconto — o `code` é o que o cliente final informa no checkout\n * (`plans.checkout(planId, { coupon_code })`).\n *\n * ```ts\n * // 20% de desconto, aplicado só na primeira cobrança\n * await client.coupons.create({ code: \"BEMVINDO20\", type: \"PERCENTAGE\", value: 20, duration: \"ONCE\" });\n *\n * // R$10 de desconto, repetido pelas 3 primeiras renovações\n * await client.coupons.create({\n * code: \"R10X3\", type: \"FIXED\", value: 1000, duration: \"REPEATING\", duration_months: 3,\n * });\n * ```\n */\n create(input: CreateCouponInput): Promise<Coupon> {\n return this.http.post<Coupon>(\"/coupons\", input);\n }\n\n /** Só permite editar limites/validade/ativação — o desconto em si (type/value/duration)\n * de um cupom já criado é imutável; crie um novo código para mudar o valor do desconto.\n * `idOrCode` aceita id interno ou `code` (ver `get`). */\n update(idOrCode: string, input: Partial<Pick<CreateCouponInput, \"max_redemptions\" | \"expires_at\">> & { active?: boolean }): Promise<Coupon> {\n return this.http.patch<Coupon>(`/coupons/${idOrCode}`, input);\n }\n\n /** Desativa o cupom (soft-delete) — códigos já resgatados continuam no histórico.\n * `idOrCode` aceita id interno ou `code` (ver `get`). */\n remove(idOrCode: string): Promise<void> {\n return this.http.delete<void>(`/coupons/${idOrCode}`);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Customer, CustomerInput } from \"../types.js\";\n\nexport class CustomersResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<Customer[]> {\n return this.http.get<Customer[]>(\"/customers\");\n }\n\n create(input: CustomerInput): Promise<Customer> {\n return this.http.post<Customer>(\"/customers\", input);\n }\n\n get(id: string): Promise<Customer> {\n return this.http.get<Customer>(`/customers/${id}`);\n }\n\n update(id: string, input: Partial<CustomerInput>): Promise<Customer> {\n return this.http.patch<Customer>(`/customers/${id}`, input);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { BillingItem } from \"../types.js\";\n\nexport interface ItemInput {\n name: string;\n description?: string;\n amount: number;\n currency?: string;\n}\n\nexport class ItemsResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<BillingItem[]> {\n return this.http.get<BillingItem[]>(\"/items\");\n }\n\n create(input: ItemInput): Promise<BillingItem> {\n return this.http.post<BillingItem>(\"/items\", input);\n }\n\n get(id: string): Promise<BillingItem> {\n return this.http.get<BillingItem>(`/items/${id}`);\n }\n\n update(id: string, input: Partial<ItemInput>): Promise<BillingItem> {\n return this.http.patch<BillingItem>(`/items/${id}`, input);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { CreateOrderInput, CreateOrderResult } from \"../types.js\";\n\nexport class OrdersResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Cria um pedido parcelado (parcelamento real via cobranças avulsas agendadas,\n * não assinatura). Retorna o `client_secret` da 1ª parcela para o front-end\n * confirmar via Stripe Elements — as parcelas seguintes são cobradas\n * automaticamente pelo backend no cartão salvo.\n */\n create(input: CreateOrderInput): Promise<CreateOrderResult> {\n return this.http.post<CreateOrderResult>(\"/orders\", input);\n }\n\n list(): Promise<unknown[]> {\n return this.http.get(\"/orders\");\n }\n\n get(id: string): Promise<unknown> {\n return this.http.get(`/orders/${id}`);\n }\n}\n","import type { HttpClient } from \"../http.js\";\r\nimport type {\r\n BillingPlanSummary,\r\n CheckoutForCustomerInput,\r\n CheckoutForCustomerResult,\r\n CreateBillingPlanInput,\r\n GetPublicPlanPageResult,\r\n ListPublicPlansResult,\r\n PlanCheckoutInput,\r\n PlanCheckoutResult,\r\n PlanSubscriptionStatusResult,\r\n} from \"../types.js\";\r\n\r\nexport class PlansResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n list(): Promise<BillingPlanSummary[]> {\r\n return this.http.get<BillingPlanSummary[]>(\"/billing-plans\");\r\n }\r\n\r\n get(id: string): Promise<BillingPlanSummary> {\r\n return this.http.get<BillingPlanSummary>(`/billing-plans/${id}`);\r\n }\r\n\r\n create(input: CreateBillingPlanInput): Promise<BillingPlanSummary> {\r\n return this.http.post<BillingPlanSummary>(\"/billing-plans\", input);\r\n }\r\n\r\n update(id: string, input: Partial<CreateBillingPlanInput> & { active?: boolean }): Promise<BillingPlanSummary> {\r\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${id}`, input);\r\n }\r\n\r\n /** Não há hard-delete de planos (assinaturas existentes ainda referenciam) — para\r\n * remover um plano do catálogo público, arquive-o. */\r\n archive(id: string): Promise<BillingPlanSummary> {\r\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${id}`, { active: false });\r\n }\r\n\r\n /** Vincula um plano avulso a uma página de planos existente (mesma org). */\r\n attachToPage(planId: string, pageId: string): Promise<BillingPlanSummary> {\r\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${planId}`, { plan_page_id: pageId });\r\n }\r\n\r\n /** Desvincula um plano da sua página, tornando-o avulso (sem página pública). */\r\n detachFromPage(planId: string): Promise<BillingPlanSummary> {\r\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${planId}`, { plan_page_id: null });\r\n }\r\n\r\n /**\r\n * Fluxo simplificado de assinatura para um `Customer` já cadastrado na sua org\r\n * (autenticado, sem formulário de nome/e-mail): cria a assinatura + cobrança inicial e\r\n * retorna a URL de checkout hospedada.\r\n *\r\n * ```ts\r\n * const { checkout_url } = await client.plans.checkoutPlan(planId, customerId, {\r\n * return_url: \"https://meuapp.com/conta?upgraded=1\",\r\n * });\r\n * // redirecione o cliente para checkout_url; ele paga e volta para sua URL de retorno\r\n *\r\n * // depois que o cliente volta:\r\n * const { active, item } = await client.plans.confirmPlanSubscription(planId, customerId);\r\n * if (active) {\r\n * // ativa o plano real no seu sistema\r\n * }\r\n * ```\r\n */\r\n checkoutPlan(planId: string, customerId: string, input?: CheckoutForCustomerInput): Promise<CheckoutForCustomerResult> {\r\n return this.http.post<CheckoutForCustomerResult>(`/billing-plans/${planId}/checkout-for-customer`, {\r\n customer_id: customerId,\r\n ...(input?.return_url ? { return_url: input.return_url } : {}),\r\n ...(input?.expires_in ? { expires_in: input.expires_in } : {}),\r\n ...(input?.coupon_code ? { coupon_code: input.coupon_code } : {}),\r\n });\r\n }\r\n\r\n /** Verifica se um `Customer` tem uma assinatura ativa deste plano (a mais recente),\r\n * contraparte de `checkoutPlan` no fluxo simplificado autenticado. */\r\n confirmPlanSubscription(planId: string, customerId: string): Promise<PlanSubscriptionStatusResult> {\r\n return this.http.get<PlanSubscriptionStatusResult>(`/billing-plans/${planId}/subscription-status?customer_id=${encodeURIComponent(customerId)}`);\r\n }\r\n\r\n // ─── Rotas públicas (sem auth — usadas para montar sua própria página de preços) ──\r\n\r\n /** Lista os planos ativos de uma org pelo slug público — página fixa legada, sem\r\n * suporte a múltiplas páginas. Prefira `getPublicPage` para orgs com várias páginas. */\r\n listPublic(orgSlug: string): Promise<ListPublicPlansResult> {\r\n return this.http.get<ListPublicPlansResult>(`/public/orgs/${orgSlug}/billing-plans`);\r\n }\r\n\r\n /** Busca uma página de planos pública específica pelo slug da org + slug da página. */\r\n getPublicPage(orgSlug: string, pageSlug: string): Promise<GetPublicPlanPageResult> {\r\n return this.http.get<GetPublicPlanPageResult>(`/public/orgs/${orgSlug}/plan-pages/${pageSlug}`);\r\n }\r\n\r\n /**\r\n * Inicia a assinatura de um plano para um cliente final: cria (ou reaproveita) o\r\n * `Customer` pelo e-mail, cria a `Subscription` e retorna uma URL de checkout hospedada\r\n * pela Geekapps para o cliente confirmar o pagamento.\r\n *\r\n * Fluxo típico:\r\n * ```ts\r\n * const { checkout_url, checkout_token } = await client.plans.checkout(planId, {\r\n * customer: { name, email },\r\n * coupon_code: \"PROMO20\", // opcional — página já abre com o desconto aplicado\r\n * });\r\n * // redirecione o cliente (ou abra checkout_url em uma WebView/nova aba)\r\n * window.location.href = checkout_url;\r\n *\r\n * // depois do retorno, confirme se realmente foi pago:\r\n * const { status } = await client.checkout.waitUntilPaid(checkout_token);\r\n * if (status === \"PAID\") { /* liberar acesso *\\/ }\r\n * ```\r\n *\r\n * Não requer autenticação — pode ser chamado a partir do backend do dev sem token de\r\n * service account, ou do próprio SDK server-side usando qualquer token válido.\r\n */\r\n checkout(planId: string, input: PlanCheckoutInput): Promise<PlanCheckoutResult> {\r\n return this.http.post<PlanCheckoutResult>(`/public/billing-plans/${planId}/checkout`, input);\r\n }\r\n}\r\n","import type { HttpClient } from \"../http.js\";\r\nimport type {\r\n CreateSubscriptionInput,\r\n CreateSubscriptionResult,\r\n Subscription,\r\n SubscriptionStatusResult,\r\n SwapPlanInput,\r\n SwapPlanPreviewResult,\r\n SwapPlanResult,\r\n} from \"../types.js\";\r\n\r\nexport class SubscriptionsResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /** Requer autenticação (service account) — lista todas as assinaturas da sua org. */\r\n list(): Promise<Subscription[]> {\r\n return this.http.get<Subscription[]>(\"/billing-subscriptions\");\r\n }\r\n\r\n /**\r\n * Fluxo legado de assinatura por `BillingItem` avulso (sem `BillingPlan`) — requer\r\n * autenticação (service account) e que `customer_id`/`item_id` já existam na sua org.\r\n * Prefira `plans.checkout`/`plans.checkoutPlan` para novos catálogos baseados em plano.\r\n *\r\n * ```ts\r\n * await client.subscriptions.create({\r\n * customer_id, item_id, interval: \"MONTHLY\", coupon_code: \"PROMO20\",\r\n * });\r\n * ```\r\n */\r\n create(input: CreateSubscriptionInput): Promise<CreateSubscriptionResult> {\r\n return this.http.post<CreateSubscriptionResult>(\"/billing-subscriptions\", input);\r\n }\r\n\r\n /** Requer autenticação (service account). */\r\n get(id: string): Promise<Subscription> {\r\n return this.http.get<Subscription>(`/billing-subscriptions/${id}`);\r\n }\r\n\r\n /** Requer autenticação (service account). */\r\n cancel(id: string): Promise<Subscription> {\r\n return this.http.patch<Subscription>(`/billing-subscriptions/${id}/cancel`);\r\n }\r\n\r\n /**\r\n * Reverte um cancelamento agendado (cancel_at_period_end) — requer autenticação\r\n * (service account). Só se aplica enquanto a assinatura ainda está ACTIVE com o\r\n * cancelamento agendado pro fim do período vigente (ver SUBSCRIPTION_CANCEL_SCHEDULE);\r\n * uma vez CANCELLED de fato, a Subscription já foi encerrada no Stripe e não há o que\r\n * reverter — chame `cancel`/checkout novamente para recomeçar.\r\n */\r\n resume(id: string): Promise<Subscription> {\r\n return this.http.patch<Subscription>(`/billing-subscriptions/${id}/resume`);\r\n }\r\n\r\n /**\r\n * Calcula o preview de uma troca de plano (não muta nada) — requer autenticação\r\n * (service account). Use para mostrar ao dono da org o valor devido/estimado antes de\r\n * confirmar com `swapPlan`.\r\n *\r\n * ```ts\r\n * const preview = await client.subscriptions.previewPlanSwap(subId, {\r\n * newPlanId, policy: \"AT_RENEWAL\",\r\n * });\r\n * ```\r\n */\r\n previewPlanSwap(id: string, input: SwapPlanInput): Promise<SwapPlanPreviewResult> {\r\n const params = new URLSearchParams({ new_plan_id: input.newPlanId, policy: input.policy });\r\n if (input.manualAmount !== undefined) params.set(\"manual_amount\", String(input.manualAmount));\r\n if (input.couponCode) params.set(\"coupon_code\", input.couponCode);\r\n return this.http.get<SwapPlanPreviewResult>(`/billing-subscriptions/${id}/swap-preview?${params.toString()}`);\r\n }\r\n\r\n /**\r\n * Executa a troca de plano/item de uma assinatura já existente (upgrade/downgrade de\r\n * tier) — requer autenticação (service account). Executa a troca diretamente, sem\r\n * confirmação posterior do cliente final; o dono do org escolhe `policy` (cobrar/estornar\r\n * agora, aplicar só na próxima renovação, ou valor definido manualmente) antes de chamar.\r\n *\r\n * `manualAmount`: obrigatório quando `policy` é `\"FIXED_AMOUNT\"` — valor de ajuste assinado\r\n * (cents), positivo cobra o cliente, negativo estorna.\r\n *\r\n * `couponCode`: aplica um cupom na troca — se a assinatura for Stripe, o desconto passa a\r\n * valer também nas renovações futuras (recorrente, direto na Subscription); se for\r\n * PIX/boleto, o desconto vale só para a cobrança de proration desta troca.\r\n *\r\n * ```ts\r\n * const result = await client.subscriptions.swapPlan(subId, {\r\n * newPlanId, policy: \"IMMEDIATE\", couponCode: \"PROMO20\",\r\n * });\r\n * if (result.checkout_url) {\r\n * // redirecione o cliente final para result.checkout_url para pagar a cobrança de ajuste\r\n * }\r\n * ```\r\n */\r\n swapPlan(id: string, input: SwapPlanInput): Promise<SwapPlanResult> {\r\n return this.http.patch<SwapPlanResult>(`/billing-subscriptions/${id}/swap`, {\r\n new_plan_id: input.newPlanId,\r\n policy: input.policy,\r\n ...(input.manualAmount !== undefined ? { manual_amount: input.manualAmount } : {}),\r\n ...(input.expiresInSeconds ? { expires_in: input.expiresInSeconds } : {}),\r\n ...(input.couponCode ? { coupon_code: input.couponCode } : {}),\r\n });\r\n }\r\n\r\n /**\r\n * Verifica se uma assinatura está ativa e qual item ela cobre, usando o\r\n * `management_token` retornado por `plans.checkout()` — rota pública, sem\r\n * autenticação, segura para chamar tanto do seu backend quanto (via fetch direto,\r\n * sem o SDK) do client-side do seu app.\r\n *\r\n * ```ts\r\n * const status = await client.subscriptions.checkByToken(managementToken);\r\n * if (status.subscription.active) {\r\n * console.log(\"cobrando\", status.item.name);\r\n * }\r\n * ```\r\n */\r\n checkByToken(managementToken: string): Promise<SubscriptionStatusResult> {\r\n return this.http.get<SubscriptionStatusResult>(`/public/plan-management/${managementToken}`);\r\n }\r\n}\r\n","import type { HttpClient } from \"../http.js\";\r\n\r\nexport type OutboundWebhookEventType =\r\n | \"SUBSCRIPTION_CREATED\"\r\n | \"SUBSCRIPTION_ACTIVATED\"\r\n | \"SUBSCRIPTION_RENEWED\"\r\n | \"SUBSCRIPTION_PLAN_SWAPPED\"\r\n | \"SUBSCRIPTION_PAST_DUE\"\r\n | \"SUBSCRIPTION_CANCELLED\"\r\n | \"SUBSCRIPTION_CANCEL_SCHEDULE\"\r\n | \"SUBSCRIPTION_RESUMED\"\r\n | \"CHARGE_PAID\"\r\n | \"CHARGE_FAILED\"\r\n | \"CHARGE_EXPIRED\"\r\n | \"CHARGE_REFUNDED\";\r\n\r\n/** Payload de uma cobrança (`data`) nos eventos CHARGE_*. `description` é `null` quando\r\n * a cobrança não tem descrição definida. */\r\nexport interface ChargeEventData {\r\n chargeId: string;\r\n amountCents: number;\r\n description: string | null;\r\n}\r\n\r\n/** Union discriminada por `event_type` — use para tipar o corpo recebido na sua rota de\r\n * webhook (ver `X-Geekapps-Signature` para validar a assinatura antes de confiar no payload).\r\n *\r\n * ```ts\r\n * const event = JSON.parse(rawBody) as WebhookEvent;\r\n * switch (event.event_type) {\r\n * case \"CHARGE_PAID\":\r\n * // event.data: { chargeId, amountCents, description }\r\n * break;\r\n * case \"SUBSCRIPTION_CANCELLED\":\r\n * // event.data: { subscriptionId }\r\n * break;\r\n * }\r\n * ```\r\n */\r\nexport type WebhookEvent =\r\n | {\r\n event_type: \"SUBSCRIPTION_CREATED\";\r\n org_id: string;\r\n data: { subscriptionId: string; customerId: string; itemId: string; interval: string };\r\n }\r\n | {\r\n event_type: \"SUBSCRIPTION_ACTIVATED\";\r\n org_id: string;\r\n data: { subscriptionId: string };\r\n }\r\n | {\r\n /** Disparado a cada renovação paga com sucesso — em toda cobrança recorrente\r\n * confirmada, independente do status anterior da assinatura (distinto de\r\n * SUBSCRIPTION_ACTIVATED, que só marca a transição de volta pra ACTIVE). */\r\n event_type: \"SUBSCRIPTION_RENEWED\";\r\n org_id: string;\r\n data: { subscriptionId: string; chargeId: string | null };\r\n }\r\n | {\r\n event_type: \"SUBSCRIPTION_PLAN_SWAPPED\";\r\n org_id: string;\r\n data: { subscriptionId: string; oldPlanId: string; newPlanId: string; mode: string };\r\n }\r\n | {\r\n event_type: \"SUBSCRIPTION_PAST_DUE\";\r\n org_id: string;\r\n data: { subscriptionId: string };\r\n }\r\n | {\r\n event_type: \"SUBSCRIPTION_CANCELLED\";\r\n org_id: string;\r\n data: { subscriptionId: string };\r\n }\r\n | {\r\n /** Disparado quando um cancelamento é agendado para o fim do período vigente\r\n * (política END_OF_PERIOD ou cancelamento/reversão feito no Stripe Billing Portal) —\r\n * a assinatura continua ACTIVE até `data.effective_at`; distinto de\r\n * SUBSCRIPTION_CANCELLED, que marca o cancelamento definitivo. */\r\n event_type: \"SUBSCRIPTION_CANCEL_SCHEDULE\";\r\n org_id: string;\r\n data: { subscriptionId: string; effective_at: string | null };\r\n }\r\n | {\r\n /** Disparado quando um cancelamento agendado (SUBSCRIPTION_CANCEL_SCHEDULE) é\r\n * revertido antes do fim do período — a assinatura volta a renovar normalmente. */\r\n event_type: \"SUBSCRIPTION_RESUMED\";\r\n org_id: string;\r\n data: { subscriptionId: string };\r\n }\r\n | {\r\n event_type: \"CHARGE_PAID\";\r\n org_id: string;\r\n data: ChargeEventData;\r\n }\r\n | {\r\n event_type: \"CHARGE_FAILED\";\r\n org_id: string;\r\n data: ChargeEventData;\r\n }\r\n | {\r\n event_type: \"CHARGE_EXPIRED\";\r\n org_id: string;\r\n data: ChargeEventData;\r\n }\r\n | {\r\n event_type: \"CHARGE_REFUNDED\";\r\n org_id: string;\r\n data: ChargeEventData;\r\n };\r\n\r\nexport interface WebhookEndpointInput {\r\n url: string;\r\n eventTypes: OutboundWebhookEventType[];\r\n /** Opcional — quando omitido, o servidor gera um secret automaticamente. */\r\n secret?: string;\r\n}\r\n\r\nexport interface WebhookEndpointSummary {\r\n id: string;\r\n url: string;\r\n event_types: OutboundWebhookEventType[];\r\n active: boolean;\r\n /** Segredo completo apenas na primeira criação — em toda resposta subsequente vem mascarado. */\r\n secret: string;\r\n created_at: string;\r\n updated_at: string;\r\n}\r\n\r\nexport class WebhooksResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /** Lista os webhooks outbound cadastrados na sua org (secret sempre mascarado). */\r\n list(): Promise<WebhookEndpointSummary[]> {\r\n return this.http.get<WebhookEndpointSummary[]>(\"/webhook-endpoints\");\r\n }\r\n\r\n /**\r\n * Registra um webhook outbound — idempotente por (org, url): chamar de novo com a\r\n * mesma URL apenas atualiza os `eventTypes`, sem criar duplicata. Guarde o `secret`\r\n * retornado (só vem completo na primeira criação) para validar a assinatura\r\n * `X-Geekapps-Signature` nas entregas recebidas. Passe `secret` para definir o seu\r\n * próprio signing secret; se omitido, um valor aleatório é gerado automaticamente.\r\n */\r\n register(input: WebhookEndpointInput): Promise<WebhookEndpointSummary> {\r\n return this.http.post<WebhookEndpointSummary>(\"/webhook-endpoints\", {\r\n url: input.url,\r\n event_types: input.eventTypes,\r\n ...(input.secret ? { secret: input.secret } : {}),\r\n });\r\n }\r\n\r\n /** Edita um webhook existente — URL, eventos assinados e/ou status ativo/inativo. */\r\n update(id: string, input: Partial<WebhookEndpointInput> & { active?: boolean }): Promise<WebhookEndpointSummary> {\r\n return this.http.patch<WebhookEndpointSummary>(`/webhook-endpoints/${id}`, {\r\n ...(input.url ? { url: input.url } : {}),\r\n ...(input.eventTypes ? { event_types: input.eventTypes } : {}),\r\n ...(input.active !== undefined ? { active: input.active } : {}),\r\n });\r\n }\r\n\r\n /** Gera um novo secret e substitui o atual — a versão antiga deixa de validar imediatamente. */\r\n rotateSecret(id: string): Promise<WebhookEndpointSummary> {\r\n return this.http.post<WebhookEndpointSummary>(`/webhook-endpoints/${id}/rotate-secret`);\r\n }\r\n\r\n remove(id: string): Promise<void> {\r\n return this.http.delete<void>(`/webhook-endpoints/${id}`);\r\n }\r\n}\r\n","import { HttpClient, type HttpClientOptions } from \"./http.js\";\r\nimport { ChargesResource } from \"./resources/charges.js\";\r\nimport { CheckoutResource } from \"./resources/checkout.js\";\r\nimport { CouponsResource } from \"./resources/coupons.js\";\r\nimport { CustomersResource } from \"./resources/customers.js\";\r\nimport { ItemsResource } from \"./resources/items.js\";\r\nimport { OrdersResource } from \"./resources/orders.js\";\r\nimport { PlansResource } from \"./resources/plans.js\";\r\nimport { SubscriptionsResource } from \"./resources/subscriptions.js\";\r\nimport { WebhooksResource } from \"./resources/webhooks.js\";\r\n\r\nexport interface BillingClientOptions\r\n extends Omit<HttpClientOptions, \"baseUrl\"> {\r\n baseUrl?: string;\r\n}\r\n\r\nexport class BillingClient {\r\n private readonly http: HttpClient;\r\n\r\n readonly charges: ChargesResource;\r\n readonly checkout: CheckoutResource;\r\n readonly coupons: CouponsResource;\r\n readonly customers: CustomersResource;\r\n readonly items: ItemsResource;\r\n readonly orders: OrdersResource;\r\n readonly plans: PlansResource;\r\n readonly subscriptions: SubscriptionsResource;\r\n readonly webhooks: WebhooksResource;\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.http = new HttpClient(options);\r\n\r\n this.charges = new ChargesResource(this.http);\r\n this.checkout = new CheckoutResource(this.http);\r\n this.coupons = new CouponsResource(this.http);\r\n this.customers = new CustomersResource(this.http);\r\n this.items = new ItemsResource(this.http);\r\n this.orders = new OrdersResource(this.http);\r\n this.plans = new PlansResource(this.http);\r\n this.subscriptions = new SubscriptionsResource(this.http);\r\n this.webhooks = new WebhooksResource(this.http);\r\n }\r\n}\r\n","import type { FastifyInstance, FastifyPluginAsync } from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { BillingClient } from \"./client.js\";\nimport { ServiceAccountTokenProvider, type ServiceAccountOptions } from \"./service-account.js\";\n\nexport interface BillingPluginOptions {\n /** Geekapps Billing API base URL */\n baseUrl: string;\n /** Service account credentials — required */\n serviceAccount: ServiceAccountOptions;\n /** Ambiente de billing (dev/prod). Default: \"prod\". */\n mode?: string;\n}\n\ndeclare module \"fastify\" {\n interface FastifyInstance {\n billingClient: BillingClient;\n }\n}\n\nconst billingPlugin: FastifyPluginAsync<BillingPluginOptions> = async (\n fastify: FastifyInstance,\n options: BillingPluginOptions,\n) => {\n const tokenProvider = new ServiceAccountTokenProvider(options.serviceAccount);\n\n const client = new BillingClient({\n baseUrl: options.baseUrl,\n token: () => tokenProvider.getToken(),\n organizationId: () => tokenProvider.getOrganizationId() as Promise<string>,\n mode: options.mode,\n });\n\n fastify.decorate(\"billingClient\", client);\n};\n\nexport default fp(billingPlugin, {\n fastify: \">=4.0.0\",\n name: \"@geekapps/billing-fastify\",\n});\n","import type { TokenResolver } from \"./http.js\";\n\nexport interface ServiceAccountOptions {\n /** Geekapps Auth issuer base URL (e.g. https://accounts-api.geekapps.com.br) */\n issuerUrl: string;\n clientId: string;\n clientSecret: string;\n /** Seconds before expiry to proactively refresh. Defaults to 30. */\n refreshBeforeExpirySeconds?: number;\n}\n\ninterface CachedToken {\n value: string;\n expiresAt: number; // ms epoch\n organizationId: string | undefined;\n}\n\nfunction decodeJwtPayload(token: string): Record<string, unknown> {\n try {\n const [, payload] = token.split(\".\");\n if (!payload) return {};\n const json = Buffer.from(payload, \"base64url\").toString(\"utf-8\");\n return JSON.parse(json) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/**\n * Fetches a short-lived token from the Geekapps Auth service using\n * client_credentials grant and caches it until near expiry.\n *\n * The organizationId claim is extracted automatically from the JWT payload.\n */\nexport class ServiceAccountTokenProvider {\n private readonly issuerUrl: string;\n private readonly clientId: string;\n private readonly clientSecret: string;\n private readonly refreshBeforeMs: number;\n private cached: CachedToken | null = null;\n private inflight: Promise<CachedToken> | null = null;\n\n constructor(options: ServiceAccountOptions) {\n this.issuerUrl = options.issuerUrl.replace(/\\/$/, \"\");\n this.clientId = options.clientId;\n this.clientSecret = options.clientSecret;\n this.refreshBeforeMs = (options.refreshBeforeExpirySeconds ?? 30) * 1000;\n }\n\n private async ensureFresh(): Promise<CachedToken> {\n const now = Date.now();\n\n if (this.cached && this.cached.expiresAt - now > this.refreshBeforeMs) {\n return this.cached;\n }\n\n if (this.inflight) return this.inflight;\n\n this.inflight = this.fetchToken().finally(() => {\n this.inflight = null;\n });\n\n return this.inflight;\n }\n\n /** Returns a valid access token. */\n getToken(): Promise<string> {\n return this.ensureFresh().then((c) => c.value);\n }\n\n /** Returns the organizationId embedded in the service account JWT. */\n getOrganizationId(): Promise<string | undefined> {\n return this.ensureFresh().then((c) => c.organizationId);\n }\n\n private async fetchToken(): Promise<CachedToken> {\n const credentials = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString(\"base64\");\n\n const res = await fetch(`${this.issuerUrl}/auth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Basic ${credentials}`,\n },\n body: JSON.stringify({ grant_type: \"service_account\" }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n throw new Error(\n `ServiceAccount token fetch failed (${res.status}): ${err.error ?? \"unknown error\"}`,\n );\n }\n\n const data = await res.json() as { access_token: string; expires_in?: number };\n\n const claims = decodeJwtPayload(data.access_token);\n const organizationId =\n typeof claims.organizationId === \"string\" ? claims.organizationId :\n typeof claims.organization_id === \"string\" ? claims.organization_id :\n typeof claims.org_id === \"string\" ? claims.org_id :\n undefined;\n\n const expiresInMs = (data.expires_in ?? 420) * 1000;\n this.cached = {\n value: data.access_token,\n expiresAt: Date.now() + expiresInMs,\n organizationId,\n };\n\n return this.cached;\n }\n\n /** Returns this provider as a TokenResolver to pass directly to BillingClient. */\n asTokenResolver(): TokenResolver {\n return () => this.getToken();\n }\n}\n\n/** Convenience factory. Returns a TokenResolver ready for use in BillingClient. */\nexport function createServiceAccountToken(\n options: ServiceAccountOptions,\n): TokenResolver {\n return new ServiceAccountTokenProvider(options).asTokenResolver();\n}\n","export type ExpirationUnit = \"seconds\" | \"minutes\" | \"hours\" | \"days\";\n\nconst MULTIPLIERS: Record<ExpirationUnit, number> = {\n seconds: 1,\n minutes: 60,\n hours: 3600,\n days: 86400,\n};\n\n/**\n * Converte um valor + unidade para segundos, prontos para usar em `expires_in`.\n *\n * ```ts\n * await client.charges.create({ ..., expires_in: expiresIn(30, \"minutes\") });\n * ```\n */\nexport function expiresIn(value: number, unit: ExpirationUnit): number {\n return value * MULTIPLIERS[unit];\n}\n"],"mappings":"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","names":["fp"]}
package/package.json CHANGED
@@ -1,35 +1,35 @@
1
- {
2
- "name": "@geekapps/billing-fastify",
3
- "version": "0.7.3",
4
- "description": "Geekapps Billing SDK for Fastify",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "module": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "import": "./dist/index.js",
12
- "types": "./dist/index.d.ts"
13
- }
14
- },
15
- "scripts": {
16
- "build": "tsup",
17
- "dev": "tsup --watch"
18
- },
19
- "files": [
20
- "dist"
21
- ],
22
- "publishConfig": {
23
- "access": "public"
24
- },
25
- "devDependencies": {
26
- "@types/node": "^26.1.1",
27
- "fastify": "^5.10.0",
28
- "fastify-plugin": "^6.0.0",
29
- "tsup": "^8.5.1",
30
- "typescript": "^5.9.3"
31
- },
32
- "peerDependencies": {
33
- "fastify": ">=4.0.0"
34
- }
1
+ {
2
+ "name": "@geekapps/billing-fastify",
3
+ "version": "0.8.0",
4
+ "description": "Geekapps Billing SDK for Fastify",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsup",
17
+ "dev": "tsup --watch"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^26.1.1",
27
+ "fastify": "^5.10.0",
28
+ "fastify-plugin": "^6.0.0",
29
+ "tsup": "^8.5.1",
30
+ "typescript": "^5.9.3"
31
+ },
32
+ "peerDependencies": {
33
+ "fastify": ">=4.0.0"
34
+ }
35
35
  }