Advanced Usage

Advanced patterns and customization for the Acme SDK.

Advanced Usage

Learn advanced patterns for getting the most out of the Acme SDK.

Middleware

Add custom middleware to intercept requests and responses:

import { Acme } from '@acme/sdk';

const client = new Acme({
  apiKey: process.env.ACME_API_KEY,
  middleware: [
    // Logging middleware
    async (request, next) => {
      console.log(`[Acme] ${request.method} ${request.url}`);
      const start = Date.now();
      const response = await next(request);
      console.log(`[Acme] Completed in ${Date.now() - start}ms`);
      return response;
    },
    // Auth refresh middleware
    async (request, next) => {
      try {
        return await next(request);
      } catch (error) {
        if (error.code === 'TOKEN_EXPIRED') {
          await refreshToken();
          return next(request);
        }
        throw error;
      }
    },
  ],
});

Batching Requests

Batch multiple operations for better performance:

const results = await client.batch([
  { method: 'users.get', params: { id: 'user_1' } },
  { method: 'users.get', params: { id: 'user_2' } },
  { method: 'users.get', params: { id: 'user_3' } },
]);

// results[0] = user_1 data
// results[1] = user_2 data
// results[2] = user_3 data

Pagination

Handle paginated responses with built-in iterators:

// Manual pagination
let page = await client.users.list({ limit: 100 });

while (page.hasMore) {
  for (const user of page.data) {
    console.log(user.name);
  }
  page = await page.next();
}

// Async iterator (recommended)
for await (const user of client.users.listAll()) {
  console.log(user.name);
}

Custom HTTP Client

Use your own HTTP client for advanced networking needs:

import { Acme } from '@acme/sdk';
import axios from 'axios';

const httpClient = {
  async request(config) {
    const response = await axios({
      url: config.url,
      method: config.method,
      headers: config.headers,
      data: config.body,
    });
    return {
      status: response.status,
      headers: response.headers,
      body: response.data,
    };
  },
};

const client = new Acme({
  apiKey: process.env.ACME_API_KEY,
  httpClient,
});

Webhooks

Verify and handle incoming webhooks:

import { Acme, WebhookError } from '@acme/sdk';
import express from 'express';

const app = express();

app.post('/webhooks/acme', express.raw({ type: '*/*' }), (req, res) => {
  const signature = req.headers['x-acme-signature'];

  try {
    const event = Acme.webhooks.verify(
      req.body,
      signature,
      process.env.ACME_WEBHOOK_SECRET
    );

    switch (event.type) {
      case 'user.created':
        handleUserCreated(event.data);
        break;
      case 'user.deleted':
        handleUserDeleted(event.data);
        break;
    }

    res.status(200).send('OK');
  } catch (error) {
    if (error instanceof WebhookError) {
      console.error('Invalid webhook signature');
      res.status(400).send('Invalid signature');
    }
  }
});

Caching

Implement response caching for improved performance:

import { Acme } from '@acme/sdk';

const cache = new Map();

const client = new Acme({
  apiKey: process.env.ACME_API_KEY,
  cache: {
    get: (key) => cache.get(key),
    set: (key, value, ttl) => {
      cache.set(key, value);
      setTimeout(() => cache.delete(key), ttl);
    },
  },
  cacheTTL: 60000, // 1 minute
});

Migration from v1.1.x

Breaking Changes in v1.2.0

Async/Await

All methods now return Promises instead of using callbacks:

// v1.1.x (deprecated)
client.users.get('user_123', (err, user) => {
  if (err) throw err;
  console.log(user);
});

// v1.2.x
const user = await client.users.get('user_123');

Import Changes

// v1.1.x
const Acme = require('@acme/sdk');

// v1.2.x
import { Acme } from '@acme/sdk';
// or
const { Acme } = require('@acme/sdk');