npm package: @relayer-ws/plain-proxy-sdk
Description: Cloudflare Worker SDK for Plain Proxy
Author: relayer.ws
Latest version: 1.0.0

# Plain Proxy SDK

A TypeScript SDK for making HTTP requests through Plain proxy-enabled Lambda functions from Cloudflare Workers.

> **Note**: All requests made through this SDK will appear to come from the IP address `3.38.55.163`. This is useful for scenarios where you need a consistent outbound IP address for your requests.

## Features

- 🚀 **Easy to use** - Simple API similar to native fetch
- 🔧 **TypeScript support** - Full type definitions included
- ⚡ **Cloudflare Workers ready** - Optimized for Cloudflare Workers environment
- 🛡️ **Timeout handling** - Built-in request timeout support
- 📦 **Multiple interfaces** - Both class-based and functional APIs
- 🔄 **All HTTP methods** - GET, POST, PUT, DELETE, PATCH, HEAD support
- 🌐 **Fixed IP address** - All requests are sent from IP address `3.38.55.163`

## Installation

```bash
npm install @relayer-ws/plain-proxy-sdk
```

## Quick Start

### Using the PlainProxyClient class

```typescript
import { PlainProxyClient } from "@relayer-ws/plain-proxy-sdk";

// Create a client with default settings
const proxy = new PlainProxyClient({});

// Make a proxied request
const response = await proxy.get("https://api.example.com/data", {
  Authorization: "Bearer your-token",
});

const data = await response.json();
console.log(data);
```

### Using the fetch-like API

```typescript
import { createPlainFetch } from "@relayer-ws/plain-proxy-sdk";

// Create a fetch-like function
const PlainFetch = createPlainFetch({
  proxyUrl: "https://gw.relayer.ws/plain",
});

// Use it just like the native fetch API
const response = await PlainFetch("https://api.example.com/data", {
  method: "POST",
  headers: {
    Authorization: "Bearer token",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ data: "value" }),
});

const result = await response.json();
```

## Configuration

### PlainProxyConfig

```typescript
interface PlainProxyConfig {
  /** The URL of the Plain proxy Lambda function (default: https://gw.relayer.ws/plain) */
  proxyUrl?: string;
  /** Optional timeout for requests (default: 30000ms) */
  timeout?: number;
}
```

### Example with custom configuration

```typescript
const proxy = new PlainProxyClient({
  proxyUrl: "https://your-custom-proxy.amazonaws.com",
  timeout: 60000, // 60 seconds
});
```

## API Reference

### PlainProxyClient

The main client class for making proxied requests.

#### Constructor

```typescript
new PlainProxyClient(config: PlainProxyConfig)
```

#### Methods

##### `request(options: ProxyRequestOptions): Promise<Response>`

Make a proxied request with full control over the request parameters.

```typescript
const response = await proxy.request({
  targetUrl: "https://api.example.com",
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ key: "value" }),
  timeout: 10000,
});
```

##### HTTP Method Helpers

Convenience methods for common HTTP methods:

```typescript
// GET request
await proxy.get("https://api.example.com/data", headers);

// POST request
await proxy.post("https://api.example.com/data", body, headers);

// PUT request
await proxy.put("https://api.example.com/data", body, headers);

// DELETE request
await proxy.delete("https://api.example.com/data", headers);

// PATCH request
await proxy.patch("https://api.example.com/data", body, headers);

// HEAD request
await proxy.head("https://api.example.com/data", headers);
```

### createPlainFetch

Create a fetch-like function that works like the native fetch API.

```typescript
const PlainFetch = createPlainFetch(config);
const response = await PlainFetch(url, init);
```

### createPlainProxyClient

Factory function to create a new PlainProxyClient instance.

```typescript
const client = createPlainProxyClient(config);
```

## Types

### ProxyRequestOptions

```typescript
interface ProxyRequestOptions {
  /** Target URL to proxy to */
  targetUrl: string;
  /** HTTP method */
  method?: string;
  /** Request headers */
  headers?: Record<string, string | undefined>;
  /** Request body */
  body?: string | ArrayBuffer | ReadableStream;
  /** Request timeout (overrides config timeout) */
  timeout?: number;
}
```

### ProxyResponse

```typescript
interface ProxyResponse {
  /** HTTP status code */
  status: number;
  /** HTTP status text */
  statusText: string;
  /** Response headers */
  headers: Record<string, string>;
  /** Response body */
  body: string;
  /** Whether the response body is base64 encoded */
  isBase64Encoded: boolean;
}
```

## Examples

### Basic GET request

```typescript
import { PlainProxyClient } from "@relayer-ws/plain-proxy-sdk";

const proxy = new PlainProxyClient({});

try {
  const response = await proxy.get("https://jsonip.com");
  const data = await response.json();
  console.log("Your IP:", data.ip); // Will always show: 3.38.55.163
} catch (error) {
  console.error("Request failed:", error);
}
```

### Verify IP address

```typescript
import { PlainProxyClient } from "@relayer-ws/plain-proxy-sdk";

const proxy = new PlainProxyClient({});

// Check what IP address your requests appear to come from
const response = await proxy.get("https://httpbin.org/ip");
const data = await response.json();
console.log("Outbound IP:", data.origin); // Will show: 3.38.55.163
```

### POST request with JSON data

```typescript
const response = await proxy.post(
  "https://api.example.com/users",
  JSON.stringify({ name: "John Doe", email: "john@example.com" }),
  { "Content-Type": "application/json" }
);

if (response.ok) {
  const user = await response.json();
  console.log("Created user:", user);
}
```

### Using with custom timeout

```typescript
const proxy = new PlainProxyClient({
  timeout: 5000, // 5 seconds
});

// Or override timeout for specific request
const response = await proxy.request({
  targetUrl: "https://slow-api.example.com",
  timeout: 10000, // 10 seconds for this request
});
```

### Error handling

```typescript
try {
  const response = await proxy.get("https://api.example.com");

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }

  const data = await response.json();
  console.log(data);
} catch (error) {
  if (error.message.includes("timeout")) {
    console.error("Request timed out");
  } else {
    console.error("Request failed:", error.message);
  }
}
```

## Development

### Building

```bash
npm run build
```

### Running tests

```bash
npm test
```

### Development mode

```bash
npm run dev
```

## License

MIT

## Author

[relayer.ws](https://relayer.ws)