Skip to content

Conversation

@narekhovhannisyan
Copy link
Collaborator

@narekhovhannisyan narekhovhannisyan commented Oct 29, 2025

Motivation

Add support for the Contact Imports API to enable bulk importing of contacts into Mailtrap accounts. This feature allows users to efficiently import multiple contacts at once with optional fields, contact lists inclusion/exclusion, and tracking of import status. The implementation follows the existing patterns used for other contact management APIs (Contacts, Contact Lists, Contact Fields) to maintain consistency across the SDK. Fixes #74

Changes

  • Added Contact Imports API implementation (src/lib/api/resources/ContactImports.ts)
    • create() method to bulk import contacts with optional fields and list assignments
    • get() method to retrieve import status by ID with progress tracking
  • Added Contact Imports API wrapper (src/lib/api/ContactImports.ts)
    • Base API class that provides the same interface pattern as other contact APIs
  • Added TypeScript types (src/types/api/contact-imports.ts)
    • ContactImportResponse type with status, counts, and import metadata
    • ImportContactsRequest type supporting contacts with fields, list inclusions/exclusions
  • Integrated Contact Imports into MailtrapClient (src/lib/MailtrapClient.ts)
    • Added contactImports getter method following the same pattern as other API getters
    • Improved code organization by alphabetizing imports
    • Fixed sendingDomains getter to use consistent pattern
  • Added comprehensive unit tests (src/__tests__/lib/api/resources/ContactImports.test.ts)
    • 9 test cases covering success scenarios, error handling, and edge cases
    • Tests for creating imports with full data and minimal data
    • Tests for various error scenarios (400, 404, 422 status codes)
    • Tests for array-based validation errors with name/base fields
    • Tests for retrieving import status with all optional fields
  • Added API wrapper tests (src/__tests__/lib/api/ContactImports.test.ts)
    • Basic initialization tests to ensure proper API structure
  • Added example usage (examples/contact-imports/everything.ts)
    • Demonstrates basic contact import workflow
  • Updated README documentation (README.md)
    • Added "Contact Imports (bulk import contacts)" to supported functionality list
    • Added "Contact Imports API" section with link to example

How to test

  • Run all unit tests to ensure no regressions: npm test (expect 247+ passing tests)
  • Run Contact Imports resource tests: npm test -- src/__tests__/lib/api/resources/ContactImports.test.ts (should pass 9 tests)
  • Run Contact Imports API wrapper tests: npm test -- src/__tests__/lib/api/ContactImports.test.ts (should pass 1 test)
  • Verify linting passes: npm run lint
  • Check TypeScript compilation: npm run lint:tsc
  • Review README.md to ensure Contact Imports section is correctly formatted and linked
  • Verify example file works correctly: Review examples/contact-imports/everything.ts for proper usage patterns
  • Test integration: Create a MailtrapClient instance and verify client.contactImports getter is accessible
  • Verify error handling: Confirm tests cover validation errors, not found errors, and server errors
  • Check API response types: Ensure ContactImportResponse matches expected API structure with all status values

Summary by CodeRabbit

  • New Features

    • Contact Imports: bulk import contacts with create and retrieve operations exposed via the client.
  • Documentation

    • README updated to document Contact Imports and link to an example.
  • Examples

    • Added a complete example demonstrating the contact imports workflow.
  • Tests

    • Unit tests added covering contact imports behavior and error handling.

@coderabbitai
Copy link

coderabbitai bot commented Oct 29, 2025

Walkthrough

Adds a new Contact Imports feature: README docs and example, resource and wrapper API classes, TypeScript types, MailtrapClient getter, and unit tests enabling create/get contact-import operations (no other API changes).

Changes

Cohort / File(s) Summary
Documentation
README.md
Adds "Contact Imports (bulk import contacts)" to capabilities and a "Contact Imports API" examples section with a link.
Example
examples/contact-imports/everything.ts
New example demonstrating MailtrapClient usage for creating a contact import and retrieving its status (init, create, get, error handling).
Client surface
src/lib/MailtrapClient.ts
Adds get contactImports() which validates accountId and returns a ContactImportsBaseAPI instance; minor reordering of related imports.
API wrapper
src/lib/api/ContactImports.ts
New ContactImportsBaseAPI class that re-exports create and get methods from the resource API.
Resource implementation
src/lib/api/resources/ContactImports.ts
New ContactImportsApi class implementing create(data: ImportContactsRequest) and get(importId: number) against /api/accounts/{accountId}/contacts/imports.
Types
src/types/api/contact-imports.ts
Adds ContactImportResponse and ImportContactsRequest types describing request payload and response shape.
Tests
src/__tests__/lib/api/ContactImports.test.ts, src/__tests__/lib/api/resources/ContactImports.test.ts
New unit tests verifying instantiation, presence of create/get, successful flows and error handling (400, 422, 404), and MailtrapError propagation/message composition.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Client as MailtrapClient
    participant Wrapper as ContactImportsBaseAPI
    participant Resource as ContactImportsApi
    participant API as HTTP API

    User->>Client: request contactImports
    Client->>Client: validateAccountIdPresence()
    Client-->>User: ContactImportsBaseAPI instance

    rect rgb(230,245,245)
      Note over User,API: Create import (async processing)
      User->>Wrapper: create(ImportContactsRequest)
      Wrapper->>Resource: create(...)
      Resource->>API: POST /api/accounts/{accountId}/contacts/imports
      API-->>Resource: ContactImportResponse { id, status, ... }
      Resource-->>Wrapper: response
      Wrapper-->>User: ContactImportResponse
    end

    rect rgb(245,235,245)
      Note over User,API: Retrieve import status
      User->>Wrapper: get(importId)
      Wrapper->>Resource: get(importId)
      Resource->>API: GET /api/accounts/{accountId}/contacts/imports/{importId}
      API-->>Resource: ContactImportResponse
      Resource-->>Wrapper: response
      Wrapper-->>User: ContactImportResponse
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay extra attention to:
    • HTTP endpoint construction in src/lib/api/resources/ContactImports.ts.
    • Method binding and export surface in src/lib/api/ContactImports.ts.
    • Account ID validation and instance creation in src/lib/MailtrapClient.ts.
    • Tests validating multi-field 422 error aggregation and MailtrapError messages (src/__tests__/.../ContactImports.test.ts).

Possibly related issues

  • #74: Contacts Batch API Import — This PR implements the Contact Imports endpoints, types, and client getter requested by the issue.

Suggested reviewers

  • IgorDobryn
  • mklocek

Poem

"I hopped along the SDK trail,
Brought contacts in a handy pail,
Create, then ask for how they fare,
I nibble bugs with tender care. 🐇📬"

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Contact imports' is concise and clearly summarizes the main change—adding support for a new Contact Imports API feature to the SDK.
Description check ✅ Passed The pull request description is well-structured, following the template with clear sections for Motivation, Changes, and How to test. It provides comprehensive details about all modifications made.
Linked Issues check ✅ Passed The PR fully implements the Contact Imports API as specified in issue #74, including bulk import support (create method), import status retrieval (get method), custom fields, list management, and comprehensive testing.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the Contact Imports API feature. Minor organizational improvements (alphabetizing imports, fixing sendingDomains pattern) are reasonable scope within API implementation.
✨ 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 contact-imports

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ad0109 and 0cc415c.

📒 Files selected for processing (1)
  • src/__tests__/lib/api/resources/ContactImports.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/tests/lib/api/resources/ContactImports.test.ts

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.

@narekhovhannisyan narekhovhannisyan marked this pull request as ready for review October 29, 2025 14:34
@narekhovhannisyan narekhovhannisyan self-assigned this Oct 29, 2025
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 (8)
src/types/api/contact-imports.ts (1)

13-17: Preserve ZIP leading zeros by widening type.

Use string | number for zip_code to avoid truncating leading zeros (e.g., "02108").

       fields?: {
         first_name?: string;
         last_name?: string;
-        zip_code?: number;
+        zip_code?: string | number;
         [key: string]: string | number | undefined;
       };
src/__tests__/lib/api/ContactImports.test.ts (1)

11-14: Strengthen assertions (optional).

Also assert members are functions to catch mis‑binding regressions.

         expect(contactImportsAPI).toHaveProperty("create");
         expect(contactImportsAPI).toHaveProperty("get");
+        expect(typeof (contactImportsAPI as any).create).toBe("function");
+        expect(typeof (contactImportsAPI as any).get).toBe("function");
README.md (1)

130-133: Add note about required accountId.

Contact Imports requires accountId in MailtrapClient config. Add a one‑liner to reduce setup confusion.

-### Contact Imports API
+### Contact Imports API
+Note: Contact Imports require providing `accountId` when initializing `MailtrapClient`.
 
 - [Contact Imports](examples/contact-imports/everything.ts)
src/lib/api/ContactImports.ts (1)

6-14: Make bound methods readonly.

Prevents accidental reassignment of API surface.

-export default class ContactImportsBaseAPI {
-  public create: ContactImportsApi["create"];
-
-  public get: ContactImportsApi["get"];
+export default class ContactImportsBaseAPI {
+  public readonly create: ContactImportsApi["create"];
+
+  public readonly get: ContactImportsApi["get"];
src/__tests__/lib/api/resources/ContactImports.test.ts (1)

176-193: Nice coverage; consider adding base-only error case (optional).

Add a test where errors = { base: [...] } (no name) to assert logger falls back to base.

+    it("fails with base-only validation errors.", async () => {
+      const endpoint = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/contacts/imports`;
+      mock.onPost(endpoint).reply(422, { errors: { base: ["Contact limit exceeded"] } });
+      await expect(contactImportsAPI.create(createImportRequest))
+        .rejects.toThrow("Contact limit exceeded");
+    });
src/lib/api/resources/ContactImports.ts (3)

36-36: Remove redundant URL variable.

The url constant is unnecessary here since it's just assigning the same value as this.contactImportsURL.

Apply this diff to simplify:

-    const url = `${this.contactImportsURL}`;
-
     return this.client.post<ContactImportResponse, ContactImportResponse>(
-      url,
+      this.contactImportsURL,
       data
     );

35-42: Add explicit return type annotation.

Public API methods should have explicit return type annotations for better type safety and documentation.

Apply this diff:

-  public async create(data: ImportContactsRequest) {
+  public async create(data: ImportContactsRequest): Promise<ContactImportResponse> {
     const url = `${this.contactImportsURL}`;

26-30: Add explicit return type annotation.

Public API methods should have explicit return type annotations. The axios client is configured with a response interceptor that extracts response.data directly, so the method implicitly returns Promise<ContactImportResponse>.

-  public async get(importId: number) {
+  public async get(importId: number): Promise<ContactImportResponse> {
     const url = `${this.contactImportsURL}/${importId}`;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 70796f4 and 1ad0109.

📒 Files selected for processing (8)
  • README.md (2 hunks)
  • examples/contact-imports/everything.ts (1 hunks)
  • src/__tests__/lib/api/ContactImports.test.ts (1 hunks)
  • src/__tests__/lib/api/resources/ContactImports.test.ts (1 hunks)
  • src/lib/MailtrapClient.ts (3 hunks)
  • src/lib/api/ContactImports.ts (1 hunks)
  • src/lib/api/resources/ContactImports.ts (1 hunks)
  • src/types/api/contact-imports.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
src/__tests__/lib/api/resources/ContactImports.test.ts (4)
src/lib/api/resources/ContactImports.ts (1)
  • ContactImportsApi (13-43)
src/types/api/contact-imports.ts (2)
  • ImportContactsRequest (9-21)
  • ContactImportResponse (1-7)
src/lib/axios-logger.ts (1)
  • handleSendingError (20-69)
src/lib/MailtrapError.ts (1)
  • MailtrapError (1-1)
src/lib/api/ContactImports.ts (2)
src/lib/api/resources/ContactImports.ts (1)
  • ContactImportsApi (13-43)
src/lib/MailtrapClient.ts (1)
  • contactImports (153-156)
src/lib/api/resources/ContactImports.ts (1)
src/types/api/contact-imports.ts (2)
  • ContactImportResponse (1-7)
  • ImportContactsRequest (9-21)
src/lib/MailtrapClient.ts (2)
src/lib/api/ContactImports.ts (1)
  • ContactImportsBaseAPI (5-15)
src/lib/api/SendingDomains.ts (1)
  • SendingDomainsBaseAPI (5-28)
🔇 Additional comments (4)
src/lib/MailtrapClient.ts (2)

150-156: LGTM: new contactImports getter is correctly wired.


178-180: LGTM: sendingDomains getter now consistently validates accountId.

src/lib/api/resources/ContactImports.ts (2)

1-11: LGTM!

The imports and configuration setup are clean and appropriate for the API resource implementation.


18-21: Validation for accountId is present but limited to presence checking.

The contactImports getter in MailtrapClient (line 154) calls validateAccountIdPresence() before instantiating ContactImportsBaseAPI. However, this validation only checks if accountId is truthy—it does not validate that it's a positive integer. Zero would be rejected even if it might be a valid account ID. Consider whether stricter range validation is needed, or if relying on the API endpoint to validate the account ID is sufficient for your use case.

Comment on lines 177 to 179
// API returns errors as an array in data.errors
mock.onPost(endpoint).reply(422, {
errors: {
Copy link
Contributor

Choose a reason for hiding this comment

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

So does it return data.errors as array or object? Because comment says one and test does the opposite 🤔 According to docs it should be an array of objects https://api-docs.mailtrap.io/docs/mailtrap-api-docs/b46b1fe35bdf1-import-contacts

@narekhovhannisyan narekhovhannisyan merged commit e4dded0 into main Nov 6, 2025
4 checks passed
@narekhovhannisyan narekhovhannisyan deleted the contact-imports branch November 6, 2025 12:36
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.

Contacts Batch API Import

4 participants