BREAKING CHANGE(core): Introduce RecordManager and ConvenientDnsProvider; rename list/get methods for consistent API and deprecate convenience namespace
This commit is contained in:
213
readme.md
213
readme.md
@@ -8,10 +8,10 @@ An elegant, class-based TypeScript client for the Cloudflare API that makes mana
|
||||
## Features
|
||||
|
||||
- **Comprehensive coverage** of the Cloudflare API including zones, DNS records, and Workers
|
||||
- **Class-based design** with intuitive methods for all Cloudflare operations
|
||||
- **Clean manager-based architecture** with intuitive methods for all Cloudflare operations
|
||||
- **Strong TypeScript typing** for excellent IDE autocompletion and type safety
|
||||
- **Fully integrated with the official Cloudflare client** using modern async iterators
|
||||
- **Convenience methods** for common operations to reduce boilerplate code
|
||||
- **IConvenientDnsProvider compatibility** for seamless integration with third-party modules
|
||||
- **Promise-based API** for easy async/await usage
|
||||
- **ESM compatible** for modern JavaScript projects
|
||||
- **Comprehensive error handling** for robust applications
|
||||
@@ -37,12 +37,13 @@ import * as cflare from '@apiclient.xyz/cloudflare';
|
||||
// Initialize with your API token
|
||||
const cfAccount = new cflare.CloudflareAccount('your-cloudflare-api-token');
|
||||
|
||||
// Use convenience methods for quick operations
|
||||
await cfAccount.convenience.createRecord('subdomain.example.com', 'A', '192.0.2.1', 3600);
|
||||
// Use the clean manager-based API
|
||||
await cfAccount.recordManager.createRecord('subdomain.example.com', 'A', '192.0.2.1', 3600);
|
||||
await cfAccount.zoneManager.purgeZone('example.com');
|
||||
|
||||
// Or work with the powerful class-based API
|
||||
const zone = await cfAccount.zoneManager.getZoneByName('example.com');
|
||||
await zone.purgeCache();
|
||||
// Or use the IConvenientDnsProvider interface for third-party modules
|
||||
const dnsProvider = cfAccount.getConvenientDnsProvider();
|
||||
await dnsProvider.createRecord('subdomain.example.com', 'A', '192.0.2.1');
|
||||
```
|
||||
|
||||
## Usage Guide
|
||||
@@ -68,20 +69,20 @@ const myAccounts = await cfAccount.listAccounts();
|
||||
Zones represent your domains in Cloudflare.
|
||||
|
||||
```typescript
|
||||
// Get all zones in your account
|
||||
const allZones = await cfAccount.convenience.listZones();
|
||||
// List all zones in your account
|
||||
const allZones = await cfAccount.zoneManager.listZones();
|
||||
|
||||
// Get a specific zone by domain name
|
||||
const myZone = await cfAccount.zoneManager.getZoneByName('example.com');
|
||||
|
||||
// Get zone ID directly
|
||||
const zoneId = await cfAccount.convenience.getZoneId('example.com');
|
||||
const zoneId = await cfAccount.zoneManager.getZoneId('example.com');
|
||||
|
||||
// Create a new zone
|
||||
const newZone = await cfAccount.zoneManager.createZone('newdomain.com');
|
||||
|
||||
// Purge cache for an entire zone
|
||||
await cfAccount.convenience.purgeZone('example.com');
|
||||
await cfAccount.zoneManager.purgeZone('example.com');
|
||||
// Or using the zone object
|
||||
await myZone.purgeCache();
|
||||
|
||||
@@ -99,36 +100,40 @@ const usingCfNameservers = await myZone.isUsingCloudflareNameservers();
|
||||
|
||||
### DNS Record Management
|
||||
|
||||
Manage DNS records for your domains with ease.
|
||||
Manage DNS records for your domains with ease using the RecordManager.
|
||||
|
||||
```typescript
|
||||
// List all DNS records for a domain
|
||||
const allRecords = await cfAccount.convenience.listRecords('example.com');
|
||||
const allRecords = await cfAccount.recordManager.listRecords('example.com');
|
||||
|
||||
// Create a new DNS record
|
||||
await cfAccount.convenience.createRecord('api.example.com', 'A', '192.0.2.1', 3600);
|
||||
await cfAccount.recordManager.createRecord('api.example.com', 'A', '192.0.2.1', 3600);
|
||||
|
||||
// Create a CNAME record
|
||||
await cfAccount.convenience.createRecord('www.example.com', 'CNAME', 'example.com', 3600);
|
||||
await cfAccount.recordManager.createRecord('www.example.com', 'CNAME', 'example.com', 3600);
|
||||
|
||||
// Get a specific DNS record
|
||||
const record = await cfAccount.convenience.getRecord('api.example.com', 'A');
|
||||
const record = await cfAccount.recordManager.getRecord('api.example.com', 'A');
|
||||
|
||||
// Update a DNS record (automatically creates it if it doesn't exist)
|
||||
await cfAccount.convenience.updateRecord('api.example.com', 'A', '192.0.2.2', 3600);
|
||||
await cfAccount.recordManager.updateRecord('api.example.com', 'A', '192.0.2.2', 3600);
|
||||
|
||||
// Remove a specific DNS record
|
||||
await cfAccount.convenience.removeRecord('api.example.com', 'A');
|
||||
// Delete a specific DNS record
|
||||
await cfAccount.recordManager.deleteRecord('api.example.com', 'A');
|
||||
|
||||
// Clean (remove) all records of a specific type
|
||||
await cfAccount.convenience.cleanRecord('example.com', 'TXT');
|
||||
// Clean (remove) all records of a specific type for a domain
|
||||
await cfAccount.recordManager.cleanRecords('example.com', 'TXT');
|
||||
|
||||
// For third-party modules requiring IConvenientDnsProvider interface
|
||||
const dnsProvider = cfAccount.getConvenientDnsProvider();
|
||||
await dnsProvider.createRecord('api.example.com', 'A', '192.0.2.1');
|
||||
|
||||
// Support for ACME DNS challenges (for certificate issuance)
|
||||
await cfAccount.convenience.acmeSetDnsChallenge({
|
||||
await dnsProvider.acmeSetDnsChallenge({
|
||||
hostName: '_acme-challenge.example.com',
|
||||
challenge: 'token-validation-string',
|
||||
});
|
||||
await cfAccount.convenience.acmeRemoveDnsChallenge({
|
||||
await dnsProvider.acmeRemoveDnsChallenge({
|
||||
hostName: '_acme-challenge.example.com',
|
||||
challenge: 'token-validation-string',
|
||||
});
|
||||
@@ -148,7 +153,7 @@ addEventListener('fetch', event => {
|
||||
const worker = await cfAccount.workerManager.createWorker('my-worker', workerScript);
|
||||
|
||||
// List all workers
|
||||
const allWorkers = await cfAccount.workerManager.listWorkerScripts();
|
||||
const allWorkers = await cfAccount.workerManager.listWorkers();
|
||||
|
||||
// Get an existing worker
|
||||
const existingWorker = await cfAccount.workerManager.getWorker('my-worker');
|
||||
@@ -165,8 +170,8 @@ await worker.setRoutes([
|
||||
},
|
||||
]);
|
||||
|
||||
// Get all routes for a worker
|
||||
const routes = await worker.getRoutes();
|
||||
// List all routes for a worker
|
||||
const routes = await worker.listRoutes();
|
||||
|
||||
// Update a worker's script
|
||||
await worker.updateScript(`
|
||||
@@ -200,9 +205,9 @@ async function manageCloudflare() {
|
||||
console.log(`Zone active: ${await myZone.isActive()}`);
|
||||
console.log(`Using CF nameservers: ${await myZone.isUsingCloudflareNameservers()}`);
|
||||
|
||||
// Configure DNS
|
||||
await cfAccount.convenience.createRecord('api.example.com', 'A', '192.0.2.1');
|
||||
await cfAccount.convenience.createRecord('www.example.com', 'CNAME', 'example.com');
|
||||
// Configure DNS using RecordManager
|
||||
await cfAccount.recordManager.createRecord('api.example.com', 'A', '192.0.2.1');
|
||||
await cfAccount.recordManager.createRecord('www.example.com', 'CNAME', 'example.com');
|
||||
|
||||
// Create a worker and set up routes
|
||||
const workerCode = `
|
||||
@@ -247,42 +252,78 @@ class CloudflareAccount {
|
||||
async listAccounts(): Promise<Array<ICloudflareTypes['Account']>>;
|
||||
async preselectAccountByName(accountName: string): Promise<void>;
|
||||
|
||||
// Managers
|
||||
// Managers - Clean, logical API
|
||||
readonly zoneManager: ZoneManager;
|
||||
readonly workerManager: WorkerManager;
|
||||
readonly recordManager: RecordManager;
|
||||
|
||||
// Get IConvenientDnsProvider adapter for third-party modules
|
||||
getConvenientDnsProvider(): ConvenientDnsProvider;
|
||||
|
||||
// Official Cloudflare client
|
||||
readonly apiAccount: cloudflare.Cloudflare;
|
||||
|
||||
// Convenience namespace with helper methods
|
||||
readonly convenience: {
|
||||
// Zone operations
|
||||
listZones(domainName?: string): Promise<CloudflareZone[]>;
|
||||
getZoneId(domainName: string): Promise<string>;
|
||||
purgeZone(domainName: string): Promise<void>;
|
||||
// ⚠️ Deprecated: convenience namespace (kept for backward compatibility)
|
||||
// Use the managers instead: recordManager, zoneManager, workerManager
|
||||
readonly convenience: { /* deprecated methods */ };
|
||||
}
|
||||
```
|
||||
|
||||
// DNS operations
|
||||
listRecords(domainName: string): Promise<CloudflareRecord[]>;
|
||||
getRecord(domainName: string, recordType: string): Promise<CloudflareRecord | undefined>;
|
||||
createRecord(
|
||||
domainName: string,
|
||||
recordType: string,
|
||||
content: string,
|
||||
ttl?: number,
|
||||
): Promise<any>;
|
||||
updateRecord(
|
||||
domainName: string,
|
||||
recordType: string,
|
||||
content: string,
|
||||
ttl?: number,
|
||||
): Promise<any>;
|
||||
removeRecord(domainName: string, recordType: string): Promise<any>;
|
||||
cleanRecord(domainName: string, recordType: string): Promise<void>;
|
||||
### RecordManager
|
||||
|
||||
// ACME operations
|
||||
acmeSetDnsChallenge(dnsChallenge: IDnsChallenge): Promise<any>;
|
||||
acmeRemoveDnsChallenge(dnsChallenge: IDnsChallenge): Promise<any>;
|
||||
};
|
||||
Clean DNS record management (recommended over deprecated convenience methods).
|
||||
|
||||
```typescript
|
||||
class RecordManager {
|
||||
async listRecords(domainName: string): Promise<CloudflareRecord[]>;
|
||||
async getRecord(domainName: string, recordType: string): Promise<CloudflareRecord | undefined>;
|
||||
async createRecord(domainName: string, recordType: string, content: string, ttl?: number): Promise<CloudflareRecord>;
|
||||
async updateRecord(domainName: string, recordType: string, content: string, ttl?: number): Promise<CloudflareRecord>;
|
||||
async deleteRecord(domainName: string, recordType: string): Promise<void>;
|
||||
async cleanRecords(domainName: string, recordType: string): Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
### ZoneManager
|
||||
|
||||
```typescript
|
||||
class ZoneManager {
|
||||
async listZones(zoneName?: string): Promise<CloudflareZone[]>;
|
||||
async getZoneById(zoneId: string): Promise<CloudflareZone | undefined>;
|
||||
async getZoneByName(zoneName: string): Promise<CloudflareZone | undefined>;
|
||||
async getZoneId(domainName: string): Promise<string>;
|
||||
async createZone(zoneName: string): Promise<CloudflareZone | undefined>;
|
||||
async deleteZone(zoneId: string): Promise<boolean>;
|
||||
async purgeZone(domainName: string): Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
### WorkerManager
|
||||
|
||||
```typescript
|
||||
class WorkerManager {
|
||||
async listWorkers(): Promise<Array<ICloudflareTypes['Script']>>;
|
||||
async getWorker(workerName: string): Promise<CloudflareWorker | undefined>;
|
||||
async createWorker(workerName: string, workerScript: string): Promise<CloudflareWorker>;
|
||||
async deleteWorker(workerName: string): Promise<boolean>;
|
||||
}
|
||||
```
|
||||
|
||||
### ConvenientDnsProvider
|
||||
|
||||
Adapter for third-party modules requiring `IConvenientDnsProvider` interface.
|
||||
|
||||
```typescript
|
||||
class ConvenientDnsProvider implements IConvenientDnsProvider {
|
||||
async createRecord(domainName: string, recordType: string, content: string, ttl?: number): Promise<any>;
|
||||
async updateRecord(domainName: string, recordType: string, content: string, ttl?: number): Promise<any>;
|
||||
async removeRecord(domainName: string, recordType: string): Promise<any>;
|
||||
async getRecord(domainName: string, recordType: string): Promise<any | undefined>;
|
||||
async listRecords(domainName: string): Promise<any[]>;
|
||||
async cleanRecord(domainName: string, recordType: string): Promise<void>;
|
||||
async isDomainSupported(domainName: string): Promise<boolean>;
|
||||
async acmeSetDnsChallenge(dnsChallenge: IDnsChallenge): Promise<void>;
|
||||
async acmeRemoveDnsChallenge(dnsChallenge: IDnsChallenge): Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -343,7 +384,7 @@ class CloudflareWorker {
|
||||
readonly routes: IWorkerRoute[];
|
||||
|
||||
// Methods
|
||||
async getRoutes(): Promise<IWorkerRoute[]>;
|
||||
async listRoutes(): Promise<void>; // Populates the routes property
|
||||
async setRoutes(routes: Array<IWorkerRouteDefinition>): Promise<void>;
|
||||
async updateScript(scriptContent: string): Promise<CloudflareWorker>;
|
||||
async delete(): Promise<boolean>;
|
||||
@@ -376,13 +417,57 @@ CloudflareUtils.formatUrlForPurge('example.com/page'); // 'https://example.com/p
|
||||
CloudflareUtils.formatTtl(3600); // '1 hour'
|
||||
```
|
||||
|
||||
## What's New in 6.2.0
|
||||
## What's New in 7.0.0
|
||||
|
||||
- **Improved async iterator support**: Fully leverages the official Cloudflare client's async iterator pattern
|
||||
- **Enhanced error handling**: Better error detection and recovery
|
||||
- **Simplified API**: More consistent method signatures and return types
|
||||
- **Better type safety**: Improved TypeScript typing throughout the library
|
||||
- **Detailed logging**: More informative logging for easier debugging
|
||||
- **🎨 Clean Manager-Based Architecture**: New RecordManager, improved ZoneManager and WorkerManager with consistent naming
|
||||
- **🔌 IConvenientDnsProvider Compatibility**: New ConvenientDnsProvider adapter for seamless third-party module integration
|
||||
- **📝 Consistent Method Naming**:
|
||||
- `listZones()`, `listWorkers()`, `listRecords()` - consistent list* pattern
|
||||
- `deleteRecord()` instead of `removeRecord()` - clearer semantics
|
||||
- `listRoutes()` instead of `getRoutes()` - consistent with other list methods
|
||||
- **⚠️ Deprecated convenience Namespace**: Old methods still work but are deprecated - use managers instead
|
||||
- **✅ Backward Compatible**: All existing code continues to work with deprecation warnings
|
||||
|
||||
## Migration Guide (6.x → 7.0)
|
||||
|
||||
### DNS Record Operations
|
||||
```typescript
|
||||
// Old (deprecated):
|
||||
await cfAccount.convenience.createRecord('example.com', 'A', '1.2.3.4');
|
||||
await cfAccount.convenience.listRecords('example.com');
|
||||
await cfAccount.convenience.removeRecord('example.com', 'A');
|
||||
|
||||
// New (recommended):
|
||||
await cfAccount.recordManager.createRecord('example.com', 'A', '1.2.3.4');
|
||||
await cfAccount.recordManager.listRecords('example.com');
|
||||
await cfAccount.recordManager.deleteRecord('example.com', 'A');
|
||||
|
||||
// For third-party modules:
|
||||
const dnsProvider = cfAccount.getConvenientDnsProvider();
|
||||
await dnsProvider.createRecord('example.com', 'A', '1.2.3.4');
|
||||
```
|
||||
|
||||
### Zone Operations
|
||||
```typescript
|
||||
// Old (deprecated):
|
||||
await cfAccount.convenience.listZones();
|
||||
await cfAccount.convenience.purgeZone('example.com');
|
||||
|
||||
// New (recommended):
|
||||
await cfAccount.zoneManager.listZones();
|
||||
await cfAccount.zoneManager.purgeZone('example.com');
|
||||
```
|
||||
|
||||
### Worker Operations
|
||||
```typescript
|
||||
// Old:
|
||||
await cfAccount.workerManager.listWorkerScripts();
|
||||
await worker.getRoutes();
|
||||
|
||||
// New:
|
||||
await cfAccount.workerManager.listWorkers();
|
||||
await worker.listRoutes();
|
||||
```
|
||||
|
||||
## Development & Testing
|
||||
|
||||
|
||||
Reference in New Issue
Block a user