Skip to content

feat: Rewrite SDK in TypeScript with full type definitions#11

Open
emilio-kariuki wants to merge 6 commits intoIntaSend:masterfrom
emilio-kariuki:feat/typescript-rewrite
Open

feat: Rewrite SDK in TypeScript with full type definitions#11
emilio-kariuki wants to merge 6 commits intoIntaSend:masterfrom
emilio-kariuki:feat/typescript-rewrite

Conversation

@emilio-kariuki
Copy link

feat: Rewrite SDK in TypeScript with full type definitions

Summary

Complete rewrite of the IntaSend Node.js SDK from JavaScript to TypeScript, providing full type safety, improved developer experience, and IDE autocompletion.

Changes

New Features

  • Full TypeScript source with strict mode enabled
  • Strongly typed interfaces for all API payloads (ChargePayload, PayoutPayload, etc.)
  • IntelliSense/autocomplete support in modern IDEs
  • Type declarations (.d.ts) generated and published automatically

Improvements

  • Typed method signatures across all service classes
  • Generic send<T>() method on the HTTP client for typed responses
  • Cleaner module structure with centralized type definitions

API Coverage

  • Collection - M-Pesa STK Push, checkout, payment status
  • Payouts - M-Pesa B2C/B2B, bank transfers, airtime, IntaSend transfers
  • Wallets - Create, list, get, transactions, intra-transfer, funding
  • Refunds - Create, list, get chargebacks

Testing

  • 74 unit tests across 6 test suites (Jest + ts-jest)
  • Full https module mocking — no network calls required
  • Coverage: client init, HTTP layer, collection, payouts, wallets, refunds

Migration

This is a non-breaking change. Existing JavaScript users can continue using const IntaSend = require('intasend-node') without modifications, while TypeScript users gain full type safety.


Usage Examples

Initialize Client

import IntaSend from 'intasend-node';

// Test mode
const intasend = new IntaSend('ISPubKey_test_xxx', 'ISSecretKey_test_xxx', true);

// Production mode
const intasend = new IntaSend('ISPubKey_live_xxx', 'ISSecretKey_live_xxx', false);

Collection - M-Pesa STK Push

const response = await intasend.collection().mpesaStkPush({
  phone_number: '254712345678',
  name: 'John Doe',
  email: 'john@example.com',
  amount: 100,
  api_ref: 'order-123',
});

Collection - Checkout

const checkout = await intasend.collection().charge({
  first_name: 'John',
  last_name: 'Doe',
  email: 'john@example.com',
  host: 'https://yoursite.com',
  amount: 1000,
  currency: 'KES',
  api_ref: 'order-456',
});
// Redirect customer to checkout.url

Payouts - M-Pesa

const payout = await intasend.payouts().mpesa({
  currency: 'KES',
  transactions: [
    { name: 'John Doe', account: '254712345678', amount: '500' },
  ],
});

// Approve payout
await intasend.payouts().approve(payout);

Wallets

// List wallets
const wallets = await intasend.wallets().list();

// Create wallet
const wallet = await intasend.wallets().create({
  label: 'Operations Wallet',
  wallet_type: 'WORKING',
  currency: 'KES',
});

// Get transactions
const transactions = await intasend.wallets().transactions('WALLET_ID');

// Intra-wallet transfer
await intasend.wallets().intraTransfer('SOURCE_ID', 'DEST_ID', 1000, 'Transfer');

Refunds

// Create refund
const refund = await intasend.refunds().create({
  invoice: 'INV-123',
  amount: 500,
  reason: 'CUSTOMER_REQUEST',
  reason_details: 'Customer cancelled order',
});

// List refunds
const refunds = await intasend.refunds().list();

Type Definitions

All interfaces are exported for use in your TypeScript projects:

import IntaSend, {
  ChargePayload,
  MpesaStkPushPayload,
  PayoutPayload,
  PayoutTransaction,
  PayoutProvider,
  CreateWalletPayload,
  CreateRefundPayload,
  FundMpesaPayload,
  FundCheckoutPayload,
} from 'intasend-node';

Breaking Changes

None. This is a backward-compatible rewrite. Both require() and import patterns work.

- Convert all 6 source modules (requests, intasend, collection, payouts,
  wallets, refunds) from JS to fully typed TypeScript
- Add src/types.ts with shared interfaces for all API payloads
  (ChargePayload, MpesaStkPushPayload, PayoutPayload, etc.)
- Enable strict mode in tsconfig with ES2018 target
- Split tsconfig: root for IDE support, tsconfig.build.json for
  compilation (src only)
- Use ES module imports internally, compile to CommonJS
- Re-export all types and service classes from main entry point
- Add generic send<T>() method on RequestClient for typed responses
- Add Jest + ts-jest for TypeScript test execution
- Add test helper (tests/helpers.ts) with https mock utilities:
  mockHttpsRequest, mockHttpsError, mockHttpsNetworkError
- Add 74 unit tests across 6 test files:
  - intasend.test.ts: client init, service factories, credential propagation
  - requests.test.ts: auth headers, routing, request body, response handling
  - collection.test.ts: charge, mpesaStkPush, status (with/without signature)
  - payouts.test.ts: initiate, mpesa, mpesaB2B, bank, intasend, airtime,
    approve, status
  - wallets.test.ts: list, create, get, transactions, intraTransfer,
    fundMPesa, fundCheckout
  - refunds.test.ts: list, create, get
- All tests mock https.request — no network calls required
- Remove src/example.js from compiled source
- Add examples/example.ts with typed usage of the SDK
- Keeps example out of the published dist/ package
- Add requires_approval ('YES' | 'NO') option to PayoutPayload type,
  aligning with the latest API on the dev branch
- Update example to demonstrate conditional approval flow
- Add module.exports assignment so `require('intasend-node')` returns
  the IntaSend class directly (matching the old JS behavior)
- Both `require()` and `import` patterns now work
- Fix PULL_REQUEST.md: correct type names, remove references to
  nonexistent features (error classes, JSDoc, ESM), update code
  examples to match actual interfaces
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.

1 participant

Comments