npm package: @saleandwin/cloudflare-api
Description: Cloudflare API client library for framework-ts projects with Zone, DNS, and Pages management
Author: SaleAndWin
Latest version: 1.0.4

# @saleandwin/cloudflare-api

Cloudflare API client library for framework-ts projects with Zone, DNS, and Pages management.

## 🌟 特性

- **完整的 Cloudflare API 支持**: Zone、DNS、Pages 项目管理
- **类型安全**: 完整的 TypeScript 类型定义
- **分层架构**: Handler -> Service -> Client 清晰的架构模式
- **数据验证**: 内置的请求数据验证
- **错误处理**: 统一的错误处理机制
- **分页支持**: 完整的分页查询支持
- **统计信息**: 资源使用统计和监控

## 🏗️ 架构

该库遵循清晰的分层架构模式：

```
Handler -> Service -> Client
```

- **Handler**: HTTP 请求处理层，提供统一的 API 接口给 Next.js 路由使用
- **Service**: 业务逻辑层，处理验证和数据处理
- **Client**: API 客户端层，直接与 Cloudflare API 交互

## 📦 安装

```bash
npm install @saleandwin/cloudflare-api
# 或
pnpm add @saleandwin/cloudflare-api
# 或
yarn add @saleandwin/cloudflare-api
```

## 🚀 快速开始

### 1. 基础配置

```typescript
import { CloudflareHandler, type CloudflareConfig } from '@saleandwin/cloudflare-api';

const config: CloudflareConfig = {
  apiToken: 'your-cloudflare-api-token',
  accountId: 'your-account-id', // 可选
  enableLogging: true // 可选，开启日志
};

const cloudflareHandler = CloudflareHandler.createInstance(config);
```

### 2. Zone 管理

```typescript
// 获取 Zone 列表
const zones = await cloudflareHandler.handleGetZones({
  page: 1,
  perPage: 20
});

// 创建新 Zone
const newZone = await cloudflareHandler.handleCreateZone({
  name: 'example.com',
  jumpStart: true
});

// 获取特定 Zone
const zone = await cloudflareHandler.handleGetZoneById('zone-id');

// 删除 Zone
const result = await cloudflareHandler.handleDeleteZone('zone-id');
```

### 3. DNS 记录管理

```typescript
// 获取 DNS 记录列表
const dnsRecords = await cloudflareHandler.handleGetDnsRecords({
  zoneId: 'zone-id',
  page: 1,
  perPage: 20
});

// 创建 DNS 记录
const newRecord = await cloudflareHandler.handleCreateDnsRecord({
  zoneId: 'zone-id',
  type: 'A',
  name: 'www',
  content: '192.168.1.1',
  ttl: 3600,
  proxied: true
});

// 更新 DNS 记录
const updatedRecord = await cloudflareHandler.handleUpdateDnsRecord(
  'zone-id',
  'record-id',
  {
    content: '192.168.1.2',
    ttl: 7200
  }
);

// 删除 DNS 记录
const deleteResult = await cloudflareHandler.handleDeleteDnsRecord('zone-id', 'record-id');
```

### 4. Pages 项目管理

```typescript
// 获取 Pages 项目列表
const projects = await cloudflareHandler.handleGetPagesProjects({
  page: 1,
  perPage: 20
});

// 创建 Pages 项目
const newProject = await cloudflareHandler.handleCreatePagesProject({
  name: 'my-project',
  productionBranch: 'main',
  buildConfig: {
    buildCommand: 'npm run build',
    destinationDir: 'dist'
  }
});

// 添加自定义域名
const customDomain = await cloudflareHandler.handleAddPagesCustomDomain({
  projectName: 'my-project',
  domainName: 'example.com'
});

// 删除项目
const deleteResult = await cloudflareHandler.handleDeletePagesProject('my-project');
```

### 5. Worker 脚本管理

```typescript
// 获取 Worker 脚本列表
const scripts = await cloudflareHandler.handleGetWorkerScripts({
  page: 1,
  perPage: 20
});

// 创建新 Worker 脚本
const newScript = await cloudflareHandler.handleCreateWorkerScript({
  scriptName: 'my-worker',
  script: `
    addEventListener('fetch', event => {
      event.respondWith(handleRequest(event.request))
    })

    async function handleRequest(request) {
      return new Response('Hello World!', {
        headers: { 'content-type': 'text/plain' }
      })
    }
  `,
  compatibility_date: '2023-05-18',
  usage_model: 'bundled'
});

// 更新 Worker 脚本
const updatedScript = await cloudflareHandler.handleUpdateWorkerScript({
  scriptName: 'my-worker',
  script: 'updated script content...',
  bindings: [
    {
      name: 'MY_KV',
      type: 'kv_namespace',
      namespace_id: 'your-kv-namespace-id'
    }
  ]
});

// 删除 Worker 脚本
const deleteResult = await cloudflareHandler.handleDeleteWorkerScript('my-worker');
```

### 6. Worker 路由管理

```typescript
// 获取 Worker 路由列表
const routes = await cloudflareHandler.handleGetWorkerRoutes({
  scriptName: 'my-worker',
  page: 1,
  perPage: 20
});

// 创建 Worker 路由
const newRoute = await cloudflareHandler.handleCreateWorkerRoute({
  pattern: 'example.com/api/*',
  script: 'my-worker',
  zone_id: 'your-zone-id'
});

// 删除 Worker 路由
const deleteRouteResult = await cloudflareHandler.handleDeleteWorkerRoute('route-id');
```

### 7. Worker 自定义域名管理

```typescript
// 获取 Worker 自定义域名列表
const customDomains = await cloudflareHandler.handleGetWorkerCustomDomains('my-worker');

// 绑定 Worker 自定义域名
const bindResult = await cloudflareHandler.handleBindWorkerCustomDomain({
  scriptName: 'my-worker',
  hostname: 'api.example.com',
  zone_id: 'your-zone-id'
});

// 解绑 Worker 自定义域名
const unbindResult = await cloudflareHandler.handleUnbindWorkerCustomDomain(
  'my-worker',
  'domain-id'
);
```

### 8. 令牌管理

```typescript
import { TokenHandler, TokenService, CloudflareTokenManager } from '@saleandwin/cloudflare-api';

// 创建令牌管理实例
const tokenHandler = await TokenHandler.createInstance();
const tokenService = await TokenService.createInstance();

// 创建新令牌
const newToken = await tokenService.createToken({
  account_id: 'your-account-id',
  account_name: 'My Account',
  api_token: 'your-cloudflare-api-token',
  email: 'admin@example.com',
  is_default: true,
  description: 'Production API token'
});

// 获取默认令牌
const defaultToken = await tokenService.getDefaultToken();

// 获取指定账户的令牌
const accountTokens = await tokenService.getTokensByAccountId('account-id');

// 自动选择最佳令牌
const tokenManager = await CloudflareTokenManager.createInstance();
const bestToken = await tokenManager.getBestToken('account-id');

// 使用中间件自动处理令牌
const zones = await withCloudflareToken(async (token) => {
  const client = new CloudflareApiClient({ apiToken: token });
  return await client.getZones();
}, 'account-id');
```

### 9. 用户和账号信息

```typescript
// 获取当前用户信息
const user = await cloudflareHandler.handleGetCurrentUser();

// 获取账号列表
const accounts = await cloudflareHandler.handleGetAccounts();

// 验证配置
const validation = await cloudflareHandler.handleValidateConfiguration();
```

### 6. 统计信息

```typescript
// 获取资源统计信息
const stats = await cloudflareHandler.handleGetStats();
console.log('Zones:', stats.data?.zones);
console.log('DNS Records:', stats.data?.dnsRecords);
console.log('Pages Projects:', stats.data?.pagesProjects);
console.log('Workers:', stats.data?.workers);

// 令牌统计
const tokenStats = await tokenService.getAllTokens();
console.log('Total Tokens:', tokenStats.pagination?.totalCount);
```

## 🔧 在 Next.js 中使用

### API 路由示例

```typescript
// app/api/cloudflare/zones/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { CloudflareHandler } from '@saleandwin/cloudflare-api';

const cloudflareHandler = CloudflareHandler.createInstance({
  apiToken: process.env.CLOUDFLARE_API_TOKEN!,
  accountId: process.env.CLOUDFLARE_ACCOUNT_ID
});

export async function GET(request: NextRequest) {
  try {
    const { searchParams } = new URL(request.url);
    const page = parseInt(searchParams.get('page') || '1');
    const perPage = parseInt(searchParams.get('perPage') || '20');

    const result = await cloudflareHandler.handleGetZones({ page, perPage });
    
    if (!result.success) {
      return NextResponse.json({ error: result.error }, { status: 400 });
    }

    return NextResponse.json(result);
  } catch (error) {
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}

export async function POST(request: NextRequest) {
  try {
    const data = await request.json();
    const result = await cloudflareHandler.handleCreateZone(data);
    
    if (!result.success) {
      return NextResponse.json({ error: result.error }, { status: 400 });
    }

    return NextResponse.json(result, { status: 201 });
  } catch (error) {
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}
```

## 📚 API 参考

### CloudflareHandler

主要的处理器类，提供所有 Cloudflare API 操作的统一接口。

#### Zone 管理方法
- `handleGetZones(data: ZoneListRequest): Promise<PaginatedResponse<CloudflareZone>>`
- `handleGetZoneById(zoneId: string): Promise<ServiceResponse<CloudflareZone>>`
- `handleCreateZone(data: ZoneManagementRequest): Promise<ServiceResponse<CloudflareZone>>`
- `handleDeleteZone(zoneId: string): Promise<ServiceResponse<boolean>>`

#### DNS 记录管理方法
- `handleGetDnsRecords(data: DnsListRequest): Promise<PaginatedResponse<CloudflareDnsRecord>>`
- `handleGetDnsRecordById(zoneId: string, recordId: string): Promise<ServiceResponse<CloudflareDnsRecord>>`
- `handleCreateDnsRecord(data: DnsManagementRequest): Promise<ServiceResponse<CloudflareDnsRecord>>`
- `handleUpdateDnsRecord(zoneId: string, recordId: string, data: Partial<DnsManagementRequest>): Promise<ServiceResponse<CloudflareDnsRecord>>`
- `handleDeleteDnsRecord(zoneId: string, recordId: string): Promise<ServiceResponse<boolean>>`

#### Pages 项目管理方法
- `handleGetPagesProjects(data: PagesListRequest): Promise<PaginatedResponse<CloudflarePagesProject>>`
- `handleGetPagesProjectByName(projectName: string, accountId?: string): Promise<ServiceResponse<CloudflarePagesProject>>`
- `handleCreatePagesProject(data: PagesProjectRequest): Promise<ServiceResponse<CloudflarePagesProject>>`
- `handleDeletePagesProject(projectName: string, accountId?: string): Promise<ServiceResponse<boolean>>`
- `handleGetPagesCustomDomains(projectName: string, accountId?: string): Promise<ServiceResponse<CloudflarePagesCustomDomain[]>>`
- `handleAddPagesCustomDomain(data: PagesCustomDomainRequest): Promise<ServiceResponse<CloudflarePagesCustomDomain>>`
- `handleRemovePagesCustomDomain(projectName: string, domainName: string, accountId?: string): Promise<ServiceResponse<boolean>>`

## 🔒 环境变量

```env
CLOUDFLARE_API_TOKEN=your-api-token
CLOUDFLARE_ACCOUNT_ID=your-account-id
```

## 📄 许可证

MIT

## 🤝 贡献

欢迎提交 Issue 和 Pull Request！