Skip to content

Conversation

@narekhovhannisyan
Copy link
Collaborator

@narekhovhannisyan narekhovhannisyan commented Nov 11, 2025

Motivation

Add support for the Billing API to allow users to retrieve current billing cycle usage information for their Mailtrap accounts. This enables developers to programmatically check billing cycle dates, plan information, and usage statistics for both sending and testing services.

Fixes #100

Changes

  • Added BillingApi class in src/lib/api/resources/Billing.ts with getCurrentBillingCycleUsage() method
  • Added BillingCycleUsage TypeScript type definition in src/types/api/billing.ts covering billing cycle, sending plan/usage, and testing plan/usage
  • Integrated billing API into GeneralAPI class as a lazy-instantiated getter property
  • Created example file examples/general/billing.ts demonstrating how to use the billing API
  • Updated README.md to include billing usage management in supported functionality and added billing example link
  • Added comprehensive unit tests in src/__tests__/lib/api/resources/Billing.test.ts covering:
    • Successful billing cycle usage retrieval
    • Error handling for invalid accountId (404)
    • Error handling for access denied scenarios (403)
    • Error handling for server errors without error body (500)
    • Status code verification via error cause property
  • Updated src/__tests__/lib/api/General.test.ts to include billing API tests for:
    • Property initialization
    • Lazy instantiation
    • Error handling when accountId is missing
    • Backward compatibility
    • Edge cases

How to test

  • Run npm test -- --testPathPattern="Billing" to verify all billing API tests pass
  • Run npm test -- --testPathPattern="General" to verify General API tests including billing integration pass
  • Verify the example file examples/general/billing.ts follows the same pattern as other examples
  • Check that README.md correctly displays billing usage management in the supported functionality section
  • Test the billing API integration manually by creating a client instance and calling client.general.billing.getCurrentBillingCycleUsage() with valid credentials
  • Verify error handling works correctly by testing with invalid accountId and checking that status codes are accessible via error.cause.response.status

Summary by CodeRabbit

  • New Features

    • Billing usage management added to the General API.
    • Retrieve current billing cycle usage (sending and testing plans, usage counts and limits).
  • Documentation

    • README updated to reference billing usage management.
    • New example added demonstrating how to access billing usage.

@coderabbitai
Copy link

coderabbitai bot commented Nov 11, 2025

Walkthrough

Adds Billing usage management: a new BillingApi with getCurrentBillingCycleUsage(), a BillingCycleUsage type, integration into General via a lazy billing getter that requires accountId, example usage, and tests covering success and error cases.

Changes

Cohort / File(s) Summary
Documentation & Examples
README.md, examples/general/billing.ts
Added "Billing usage management" to README and a new example demonstrating general.billing.getCurrentBillingCycleUsage() with error handling.
Type Definitions
src/types/api/billing.ts
Added BillingCycleUsage type describing billing cycle window and sending/testing plan usage (current/limit counts).
API Implementation
src/lib/api/General.ts
Added private billingInstance, public get billing() (lazy, calls checkAccountIdPresence()), and private checkAccountIdPresence(); account-scoped instances created only when accountId present.
API Resource
src/lib/api/resources/Billing.ts
New BillingApi class constructing /api/accounts/{accountId}/billing/usage and exposing getCurrentBillingCycleUsage() which returns BillingCycleUsage.
Tests
src/__tests__/lib/api/General.test.ts, src/__tests__/lib/api/resources/Billing.test.ts
Extended General tests to expect billing presence and lazy-access error; added Billing tests for success and error scenarios (404, 403, 500) verifying MailtrapError propagation and URL/response handling.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant General
    participant BillingApi
    participant Axios
    participant Server

    rect rgb(240,248,255)
        Note over General: Lazy initialization of billing
        User->>General: access .billing
        General->>General: checkAccountIdPresence()
        alt accountId present
            General->>BillingApi: instantiate (axios, accountId)
            General-->>User: return BillingApi
        else accountId missing
            General-->>User: throw Error("accountId required")
        end
    end

    rect rgb(245,255,240)
        Note over BillingApi: Fetch billing usage
        User->>BillingApi: getCurrentBillingCycleUsage()
        BillingApi->>Axios: GET /api/accounts/{accountId}/billing/usage
        Axios->>Server: HTTP GET
        alt 200 Success
            Server-->>Axios: 200 + data
            Axios-->>BillingApi: response.data
            BillingApi-->>User: BillingCycleUsage
        else 4xx/5xx Error
            Server-->>Axios: error response
            Axios->>Axios: handleSendingError()
            Axios-->>BillingApi: MailtrapError
            BillingApi-->>User: throw MailtrapError
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to checkAccountIdPresence() semantics and error message consistency.
  • Verify lazy-instantiation mirrors other account-scoped getters in General.
  • Confirm endpoint construction in BillingApi matches GENERAL_ENDPOINT/api/accounts/{accountId}/billing/usage.
  • Review tests for correct Axios mocking and MailtrapError cause/status assertions.

Suggested reviewers

  • mklocek
  • VladimirTaytor

Poem

🐰 I hopped to fetch the billing light,
Lazy paws woke just when right.
Types snug, tests standing guard,
A tiny API, tidy and hard—
Metrics hum into the night.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Billing api' is vague and generic; it lacks specificity about what the billing API implementation entails or what core change is being delivered. Consider a more descriptive title such as 'Add Billing API support for retrieving current billing cycle usage' to clearly convey the main feature being implemented.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description comprehensively covers motivation, all changes made, detailed testing instructions, and aligns with the repository template structure.
Linked Issues check ✅ Passed The PR implementation fully addresses linked issue #100 by providing a BillingApi class, BillingCycleUsage type, integration into GeneralAPI, usage examples, and comprehensive test coverage for the getCurrentBillingCycleUsage endpoint.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing billing API support as specified in issue #100; no unrelated or extraneous modifications were identified.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch billing-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/lib/api/resources/Billing.ts (1)

23-26: Optional: Simplify by using this.billingURL directly.

The local variable url is only used once and could be eliminated for brevity.

Apply this diff if you prefer a more concise implementation:

  public async getCurrentBillingCycleUsage() {
-    const url = this.billingURL;
-
-    return this.client.get<BillingCycleUsage, BillingCycleUsage>(url);
+    return this.client.get<BillingCycleUsage, BillingCycleUsage>(this.billingURL);
  }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0fa2b59 and e45fe96.

📒 Files selected for processing (7)
  • README.md (2 hunks)
  • examples/general/billing.ts (1 hunks)
  • src/__tests__/lib/api/General.test.ts (4 hunks)
  • src/__tests__/lib/api/resources/Billing.test.ts (1 hunks)
  • src/lib/api/General.ts (6 hunks)
  • src/lib/api/resources/Billing.ts (1 hunks)
  • src/types/api/billing.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/lib/api/resources/Billing.ts (1)
src/types/api/billing.ts (1)
  • BillingCycleUsage (1-32)
src/lib/api/General.ts (1)
src/lib/api/resources/Billing.ts (1)
  • BillingApi (10-28)
src/__tests__/lib/api/resources/Billing.test.ts (2)
src/lib/axios-logger.ts (1)
  • handleSendingError (20-69)
src/lib/MailtrapError.ts (1)
  • MailtrapError (1-1)
🔇 Additional comments (16)
README.md (2)

44-44: LGTM!

The documentation update appropriately lists the new billing usage management feature.


182-182: LGTM!

The example link is properly formatted and follows the existing documentation pattern.

examples/general/billing.ts (1)

1-20: LGTM!

The example clearly demonstrates billing API usage and follows the established pattern of other examples in the codebase. The error handling and result logging are appropriate.

src/lib/api/resources/Billing.ts (1)

10-18: LGTM!

The constructor properly initializes the Billing API with the required dependencies and correctly constructs the billing endpoint URL using the account ID.

src/__tests__/lib/api/resources/Billing.test.ts (4)

13-56: LGTM!

The test setup properly initializes the Billing API and defines a comprehensive response data fixture that matches the BillingCycleUsage type structure.


73-84: LGTM!

The success case test properly verifies the endpoint URL construction and response data handling.


86-130: LGTM!

The error handling tests comprehensively cover 404 and 403 scenarios, properly validating that MailtrapError is thrown with the correct message and that status codes are accessible via error.cause.response.status.


132-153: LGTM!

The test properly validates error handling when the server returns a 500 error without an error body, ensuring the fallback error message and status code accessibility work correctly.

src/lib/api/General.ts (3)

5-5: LGTM!

The import and instance field for BillingApi follow the established pattern used for other account-scoped APIs.

Also applies to: 19-19


36-46: LGTM!

The checkAccountIdPresence() helper method properly validates that an account ID is present before instantiating account-scoped APIs and provides a clear error message.


75-85: LGTM!

The billing getter properly implements lazy instantiation of the BillingApi, following the established pattern used for other account-scoped APIs. The implementation includes proper account ID validation and singleton behavior.

src/types/api/billing.ts (1)

1-32: LGTM!

The BillingCycleUsage type is well-structured and clearly defines the shape of the billing API response, with properly nested objects for billing cycle information, sending plan/usage, and testing plan/usage.

src/__tests__/lib/api/General.test.ts (4)

12-24: LGTM!

The test updates properly validate that the billing property is present and accessible when an account ID is provided, following the established pattern for other account-scoped APIs.


62-69: LGTM!

The test properly validates that accessing the billing API without an account ID throws the expected error, maintaining consistency with other account-scoped API behaviors.


89-100: LGTM!

The backward compatibility test updates properly validate that the billing API is defined and exposes the expected getCurrentBillingCycleUsage() method, ensuring the new API integrates seamlessly with existing functionality.


122-135: LGTM!

The edge case test properly validates that the billing API works correctly when accountId is 0, ensuring that falsy numeric values are handled appropriately. This is an important test for preventing bugs with truthy/falsy checks.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/lib/api/General.ts (1)

75-85: Implementation looks good; consider JSDoc consistency.

The lazy instantiation pattern and error handling are correctly implemented and consistent with the other getters.

However, the JSDoc says "Getter for Billing API" while accountAccesses and permissions say "Singleton getter for..." Consider updating for consistency.

Apply this diff to align the JSDoc with the existing pattern:

  /**
-  * Getter for Billing API.
+  * Singleton getter for Billing API.
   */
  public get billing(): BillingApi {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e45fe96 and c008f8d.

📒 Files selected for processing (1)
  • src/lib/api/General.ts (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/lib/api/General.ts (1)
src/lib/api/resources/Billing.ts (1)
  • BillingApi (10-28)
🔇 Additional comments (3)
src/lib/api/General.ts (3)

5-5: LGTM!

The import and field declaration follow the established patterns for other API resources in this class.

Also applies to: 19-19


36-46: LGTM!

The checkAccountIdPresence() helper effectively eliminates code duplication across the getter methods and provides a clear, actionable error message when accountId is missing.


48-50: LGTM!

The JSDoc has been correctly updated to describe the accountAccesses getter. The past review comment has been properly addressed.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/lib/api/General.ts (1)

75-85: Well-implemented billing getter.

The implementation correctly follows the singleton pattern and uses the checkAccountIdPresence() helper for validation. The JSDoc is clear and matches the pattern of other getters.

Minor observation: accountAccessesInstance and permissionsInstance are instantiated eagerly in the constructor when accountId is provided (lines 26-33), while billingInstance is always instantiated lazily. While this doesn't affect functionality, you could consider making the pattern consistent by either:

  • Instantiating billingInstance in the constructor alongside the others, or
  • Moving all three to pure lazy instantiation (removing lines 26-33)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c008f8d and 796b710.

📒 Files selected for processing (1)
  • src/lib/api/General.ts (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/lib/api/General.ts (1)
src/lib/api/resources/Billing.ts (1)
  • BillingApi (10-28)
🔇 Additional comments (5)
src/lib/api/General.ts (5)

5-5: LGTM!

The import follows the established pattern for resource APIs and is correctly placed.


19-19: LGTM!

The private field follows the singleton pattern established by other API instances in this class.


36-46: Excellent refactoring with the validation helper.

The checkAccountIdPresence() method centralizes the accountId validation logic and provides a clear, actionable error message. The number return type improves type safety for callers by eliminating the nullable type.


51-61: LGTM!

The refactoring to use checkAccountIdPresence() improves consistency and maintainability while preserving the lazy instantiation pattern.


66-73: LGTM!

Consistent refactoring that aligns with the accountAccesses getter pattern.

@narekhovhannisyan narekhovhannisyan merged commit c66d455 into main Nov 13, 2025
4 checks passed
@narekhovhannisyan narekhovhannisyan deleted the billing-api branch November 13, 2025 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

General - Billing API

4 participants