Compare commits

..

47 Commits

Author SHA1 Message Date
4600749442 6.0.5 2024-06-17 01:36:40 +02:00
b0f8d1e4d0 fix(start supporting workers again): update 2024-06-17 01:36:39 +02:00
902ca30529 update license info 2024-06-15 19:56:32 +02:00
5731150157 update readme 2024-06-15 19:55:48 +02:00
f39f8cd33c switch to official cloudflare api client while keeping class based approach 2024-06-15 19:47:09 +02:00
1d2e0974b2 6.0.4 2024-06-15 17:08:04 +02:00
801f86fede fix(core): update 2024-06-15 17:08:03 +02:00
42feb09b4f 6.0.3 2023-06-13 19:01:56 +02:00
d72bb28cf9 fix(core): update 2023-06-13 19:01:56 +02:00
b9f0b798c9 6.0.2 2023-06-13 18:54:26 +02:00
9b5f42ef9b fix(core): update 2023-06-13 18:54:25 +02:00
4e3355dc43 6.0.1 2022-09-27 19:24:52 +02:00
fc0a27f5b6 fix(core): update 2022-09-27 19:24:52 +02:00
0248d52548 6.0.0 2022-09-27 19:24:00 +02:00
c3984819cc BREAKING CHANGE(core): switch to esm 2022-09-27 19:24:00 +02:00
045b87a4a2 5.0.10 2022-09-27 19:23:21 +02:00
48ca9fdbb9 fix(core): update 2022-09-27 19:23:20 +02:00
e466944c55 5.0.9 2021-01-22 21:12:42 +00:00
6d8deca9d4 fix(core): update 2021-01-22 21:12:42 +00:00
a4518f3068 5.0.8 2021-01-22 20:46:26 +00:00
9e338354c6 fix(core): update 2021-01-22 20:46:26 +00:00
9d8c14d187 5.0.7 2021-01-22 20:45:36 +00:00
5a0b12f6aa fix(core): update 2021-01-22 20:45:35 +00:00
387f00078f 5.0.6 2020-06-10 05:34:48 +00:00
fe2f45e3a9 fix(core): update 2020-06-10 05:34:47 +00:00
90c9bfc906 5.0.5 2020-06-10 05:15:23 +00:00
4f9e81f612 fix(core): update 2020-06-10 05:15:22 +00:00
a4e280f9f0 5.0.4 2020-02-28 14:57:42 +00:00
52bd80aebd fix(core): update 2020-02-28 14:57:41 +00:00
15e3cdae83 5.0.3 2020-02-28 14:55:34 +00:00
c72147b469 fix(core): update 2020-02-28 14:55:33 +00:00
d98c2f89c5 5.0.2 2020-02-28 14:47:04 +00:00
2b722816f6 fix(core): update 2020-02-28 14:47:03 +00:00
91d58277dd 5.0.1 2020-02-28 14:24:37 +00:00
2458da6754 fix(core): update 2020-02-28 14:24:36 +00:00
d4379d19d3 5.0.0 2020-02-19 17:00:32 +00:00
b0fdd520f3 BREAKING CHANGE(account): authorization now uses the new Account API 2020-02-19 17:00:31 +00:00
a746577945 4.0.5 2020-02-19 16:58:47 +00:00
bc4cae3333 fix(core): update 2020-02-19 16:58:46 +00:00
e0614b5956 4.0.4 2020-02-19 14:16:24 +00:00
f568949085 fix(core): update 2020-02-19 14:16:23 +00:00
bee256416f 4.0.3 2020-02-10 14:40:56 +00:00
afa2679501 fix(core): update 2020-02-10 14:40:55 +00:00
7838642fd5 4.0.2 2020-02-10 14:38:45 +00:00
7a992badf4 fix(core): update 2020-02-10 14:38:44 +00:00
c65790e2f9 4.0.1 2020-02-10 11:26:13 +00:00
7ec0fe78fc fix(core): update 2020-02-10 11:26:13 +00:00
29 changed files with 7471 additions and 2492 deletions

4
.gitignore vendored
View File

@ -15,8 +15,6 @@ node_modules/
# builds # builds
dist/ dist/
dist_web/ dist_*/
dist_serve/
dist_ts_web/
# custom # custom

View File

@ -1,126 +0,0 @@
# gitzone ci_default
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache:
paths:
- .npmci_cache/
key: '$CI_BUILD_STAGE'
stages:
- security
- test
- release
- metadata
# ====================
# security stage
# ====================
mirror:
stage: security
script:
- npmci git mirror
tags:
- lossless
- docker
- notpriv
snyk:
image: registry.gitlab.com/hosttoday/ht-docker-node:snyk
stage: security
script:
- npmci npm prepare
- npmci command npm install --ignore-scripts
- npmci command snyk test
tags:
- lossless
- docker
- notpriv
# ====================
# test stage
# ====================
testStable:
stage: test
script:
- npmci npm prepare
- npmci node install stable
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- lossless
- docker
- priv
testBuild:
stage: test
script:
- npmci npm prepare
- npmci node install stable
- npmci npm install
- npmci command npm run build
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- lossless
- docker
- notpriv
release:
stage: release
script:
- npmci node install stable
- npmci npm publish
only:
- tags
tags:
- lossless
- docker
- notpriv
# ====================
# metadata stage
# ====================
codequality:
stage: metadata
allow_failure: true
script:
- npmci command npm install -g tslint typescript
- npmci npm prepare
- npmci npm install
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
tags:
- lossless
- docker
- priv
trigger:
stage: metadata
script:
- npmci trigger
only:
- tags
tags:
- lossless
- docker
- notpriv
pages:
stage: metadata
script:
- npmci node install lts
- npmci command npm install -g @gitzone/tsdoc
- npmci npm prepare
- npmci npm install
- npmci command tsdoc
tags:
- lossless
- docker
- notpriv
only:
- tags
artifacts:
expire_in: 1 week
paths:
- public
allow_failure: true

24
.vscode/launch.json vendored
View File

@ -2,28 +2,10 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "current file", "command": "npm test",
"type": "node", "name": "Run npm test",
"request": "launch", "request": "launch",
"args": [ "type": "node-terminal"
"${relativeFile}"
],
"runtimeArgs": ["-r", "@gitzone/tsrun"],
"cwd": "${workspaceRoot}",
"protocol": "inspector",
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": "test.ts",
"type": "node",
"request": "launch",
"args": [
"test/test.ts"
],
"runtimeArgs": ["-r", "@gitzone/tsrun"],
"cwd": "${workspaceRoot}",
"protocol": "inspector",
"internalConsoleOptions": "openOnSessionStart"
} }
] ]
} }

View File

@ -15,7 +15,7 @@
"properties": { "properties": {
"projectType": { "projectType": {
"type": "string", "type": "string",
"enum": ["website", "element", "service", "npm"] "enum": ["website", "element", "service", "npm", "wcc"]
} }
} }
} }

View File

@ -1,6 +1,4 @@
The MIT License (MIT) Copyright (c) 2014 Task Venture Capital GmbH (hello@task.vc)
Copyright (c) 2016 Lossless GmbH
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -9,9 +9,21 @@
"githost": "gitlab.com", "githost": "gitlab.com",
"gitscope": "mojoio", "gitscope": "mojoio",
"gitrepo": "cloudflare", "gitrepo": "cloudflare",
"shortDescription": "easy cloudflare management", "description": "A TypeScript client for managing Cloudflare accounts, zones, DNS records, and workers with ease.",
"npmPackagename": "@mojoio/cloudflare", "npmPackagename": "@apiclient.xyz/cloudflare",
"license": "MIT" "license": "MIT",
"keywords": [
"Cloudflare",
"DNS management",
"zone management",
"worker management",
"TypeScript",
"API client",
"cloud infrastructure",
"automated DNS",
"CDN management",
"open source"
]
} }
} }
} }

1989
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,32 @@
{ {
"name": "@mojoio/cloudflare", "name": "@apiclient.xyz/cloudflare",
"version": "4.0.0", "version": "6.0.5",
"private": false, "private": false,
"description": "easy cloudflare management", "description": "A TypeScript client for managing Cloudflare accounts, zones, DNS records, and workers with ease.",
"main": "dist/index.js", "main": "dist_ts/index.js",
"typings": "dist/index.d.ts", "typings": "dist_ts/index.d.ts",
"type": "module",
"scripts": { "scripts": {
"test": "(tstest test/)", "test": "(tstest test/)",
"build": "(tsbuild)" "build": "(tsbuild --web --allowimplicitany)",
"buildDocs": "tsdoc",
"updateOpenapi": "openapi-typescript https://raw.githubusercontent.com/cloudflare/api-schemas/main/openapi.yaml --output ts/openapi.spec.ts"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://gitlab.com/pushrocks/cflare.git" "url": "git+https://gitlab.com/pushrocks/cflare.git"
}, },
"keywords": [ "keywords": [
"Push.Rocks", "Cloudflare",
"cloudflare" "DNS management",
"zone management",
"worker management",
"TypeScript",
"API client",
"cloud infrastructure",
"automated DNS",
"CDN management",
"open source"
], ],
"author": "Lossless GmbH", "author": "Lossless GmbH",
"license": "MIT", "license": "MIT",
@ -24,32 +35,36 @@
}, },
"homepage": "https://gitlab.com/pushrocks/cflare#readme", "homepage": "https://gitlab.com/pushrocks/cflare#readme",
"dependencies": { "dependencies": {
"@pushrocks/smartdelay": "^2.0.6", "@push.rocks/smartdelay": "^3.0.1",
"@pushrocks/smartlog": "^2.0.21", "@push.rocks/smartlog": "^3.0.2",
"@pushrocks/smartpromise": "^3.0.6", "@push.rocks/smartpromise": "^4.0.2",
"@pushrocks/smartrequest": "^1.1.47", "@push.rocks/smartrequest": "^2.0.15",
"@pushrocks/smartstring": "^3.0.18", "@push.rocks/smartstring": "^4.0.5",
"@tsclass/tsclass": "^3.0.4" "@tsclass/tsclass": "^4.0.58",
"cloudflare": "^3.2.0"
}, },
"devDependencies": { "devDependencies": {
"@gitzone/tsbuild": "^2.1.17", "@git.zone/tsbuild": "^2.1.66",
"@gitzone/tsrun": "^1.2.8", "@git.zone/tsrun": "^1.2.42",
"@gitzone/tstest": "^1.0.28", "@git.zone/tstest": "^1.0.74",
"@pushrocks/qenv": "^4.0.6", "@push.rocks/qenv": "^6.0.5",
"@pushrocks/tapbundle": "^3.2.0", "@push.rocks/tapbundle": "^5.0.4",
"@types/node": "^13.7.0", "@types/node": "^20.3.1",
"tslint": "^6.0.0", "openapi-typescript": "^6.7.6"
"tslint-config-prettier": "^1.18.0"
}, },
"files": [ "files": [
"ts/**/*", "ts/**/*",
"ts_web/**/*", "ts_web/**/*",
"dist/**/*", "dist/**/*",
"dist_web/**/*", "dist_*/**/*",
"dist_ts/**/*",
"dist_ts_web/**/*", "dist_ts_web/**/*",
"assets/**/*", "assets/**/*",
"cli.js", "cli.js",
"npmextra.json", "npmextra.json",
"readme.md" "readme.md"
],
"browserslist": [
"last 1 chrome versions"
] ]
} }

6877
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,2 @@
required: required:
- CF_EMAIL
- CF_KEY - CF_KEY

1
readme.hints.md Normal file
View File

@ -0,0 +1 @@
- unofficial TypeScript cloudflare api client coming with a lot of convenience.

269
readme.md
View File

@ -1,49 +1,250 @@
# @mojoio/cloudflare # @apiclient.xyz/cloudflare
easy cloudflare management easy cloudflare management
## Availabililty and Links ## Install
* [npmjs.org (npm package)](https://www.npmjs.com/package/@mojoio/cloudflare) To install the `@apiclient.xyz/cloudflare` package, you can use npm. Simply run the following command:
* [gitlab.com (source)](https://gitlab.com/mojoio/cloudflare)
* [github.com (source mirror)](https://github.com/mojoio/cloudflare)
* [docs (typedoc)](https://mojoio.gitlab.io/cloudflare/)
## Status for master ```bash
[![pipeline status](https://gitlab.com/mojoio/cloudflare/badges/master/pipeline.svg)](https://gitlab.com/mojoio/cloudflare/commits/master) npm install @apiclient.xyz/cloudflare
[![coverage report](https://gitlab.com/mojoio/cloudflare/badges/master/coverage.svg)](https://gitlab.com/mojoio/cloudflare/commits/master) ```
[![npm downloads per month](https://img.shields.io/npm/dm/@mojoio/cloudflare.svg)](https://www.npmjs.com/package/@mojoio/cloudflare)
[![Known Vulnerabilities](https://snyk.io/test/npm/@mojoio/cloudflare/badge.svg)](https://snyk.io/test/npm/@mojoio/cloudflare) Make sure to include it in your `dependencies` in `package.json`.
[![TypeScript](https://img.shields.io/badge/TypeScript->=%203.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-prettier-ff69b4.svg)](https://prettier.io/)
## Usage ## Usage
Use TypeScript for best in class instellisense. ### Initial Setup
```javascript First, let's start by importing the required modules and setting up an instance of `CloudflareAccount` with your API token. This instance will be used to interact with the Cloudflare API.
import * as cflare from '@mojoio/cloudflare'
const myCflareAccount = new cflare.CflareAccount() ```typescript
testCflareAccount.auth({ import * as cflare from '@apiclient.xyz/cloudflare';
email: 'someuser@example.com',
key: 'someLongApiKey'
})
const myAsyncCflareManagement = async () => { // Initialize Cloudflare Account
// get things const myCflareAccount = new cflare.CloudflareAccount('mySuperAwesomeAccountToken');
const myZones = await myCflareAccount.listZones() // zones are fully typed
const myIdForADomain = await myCflareAccount.getZoneId('example.com') // type number
const myRecordsForADomain = await myCflareAccount.listRecords('example.com') // records are fully typed
}
``` ```
## Contribution ### Managing Zones
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :) #### List All Zones
For further information read the linked docs at the top of this readme. To list all zones in your Cloudflare account, you can use the `listZones` method:
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh) ```typescript
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy) const listAllZones = async () => {
const myZones = await myCflareAccount.convenience.listZones();
console.log(myZones);
};
```
[![repo-footer](https://lossless.gitlab.io/publicrelations/repofooter.svg)](https://maintainedby.lossless.com) #### Get Zone ID
To get the ID of a specific zone (domain), use the `getZoneId` method:
```typescript
const getZoneId = async (domainName: string) => {
try {
const zoneId = await myCflareAccount.convenience.getZoneId(domainName);
console.log(`Zone ID for ${domainName}:`, zoneId);
} catch (error) {
console.error('Error getting zone ID:', error);
}
};
```
#### Purge Cache for a Zone
To purge all cache for a specific zone:
```typescript
const purgeZoneCache = async (domainName: string) => {
await myCflareAccount.convenience.purgeZone(domainName);
console.log(`Purged cache for ${domainName}`);
};
```
### Managing DNS Records
#### List DNS Records
To list all DNS records for a specific zone:
```typescript
const listDnsRecords = async (domainName: string) => {
try {
const records = await myCflareAccount.convenience.listRecords(domainName);
console.log(`DNS Records for ${domainName}:`, records);
} catch (error) {
console.error('Error listing DNS records:', error);
}
};
```
#### Get a Specific Record
To get a specific DNS record by type (e.g., A, AAAA, CNAME, etc.):
```typescript
const getDnsRecord = async (domainName: string, recordType: string) => {
try {
const record = await myCflareAccount.convenience.getRecord(domainName, recordType);
console.log(`DNS Record (${recordType}) for ${domainName}:`, record);
} catch (error) {
console.error('Error getting DNS record:', error);
}
};
```
#### Create a DNS Record
To create a new DNS record:
```typescript
const createDnsRecord = async (domainName: string, recordType: string, content: string) => {
try {
const response = await myCflareAccount.convenience.createRecord(domainName, recordType, content, 120);
console.log(`Created DNS record (${recordType}) for ${domainName}:`, response);
} catch (error) {
console.error('Error creating DNS record:', error);
}
};
```
#### Remove a DNS Record
To remove a DNS record:
```typescript
const removeDnsRecord = async (domainName: string, recordType: string) => {
try {
await myCflareAccount.convenience.removeRecord(domainName, recordType);
console.log(`Removed DNS record (${recordType}) for ${domainName}`);
} catch (error) {
console.error('Error removing DNS record:', error);
}
};
```
#### Clean a DNS Record
To clean (remove) all records of a specific type for a domain:
```typescript
const cleanDnsRecord = async (domainName: string, recordType: string) => {
try {
await myCflareAccount.convenience.cleanRecord(domainName, recordType);
console.log(`Cleaned DNS records (${recordType}) for ${domainName}`);
} catch (error) {
console.error('Error cleaning DNS record:', error);
}
};
```
### Managing Workers
#### Create a Worker
To create a new Cloudflare Worker:
```typescript
const createWorker = async (workerName: string, workerScript: string) => {
try {
const worker = await myCflareAccount.workerManager.createWorker(workerName, workerScript);
console.log(`Created Worker (${workerName}):`, worker);
} catch (error) {
console.error('Error creating Worker:', error);
}
};
```
#### List Workers
To list all workers in your Cloudflare account:
```typescript
const listWorkers = async () => {
try {
const workers = await myCflareAccount.workerManager.listWorkers();
console.log('Workers:', workers);
} catch (error) {
console.error('Error listing workers:', error);
}
};
```
#### Set Worker Routes
To set routes for a Cloudflare Worker:
```typescript
import { CloudflareWorker } from '@apiclient.xyz/cloudflare';
const setWorkerRoutes = async (worker: CloudflareWorker, routes: Array<{ zoneName: string, pattern: string }>) => {
try {
await worker.setRoutes(routes);
console.log('Routes set successfully for Worker:', worker.id);
} catch (error) {
console.error('Error setting routes for Worker:', error);
}
};
```
#### Sample Complete Workflow
Below is a sample workflow that includes all the above features:
```typescript
import * as cflare from '@apiclient.xyz/cloudflare';
const myCflareAccount = new cflare.CloudflareAccount('mySuperAwesomeAccountToken');
const manageCloudflare = async () => {
try {
// List all zones
const myZones = await myCflareAccount.convenience.listZones();
console.log('Zones:', myZones);
// Get Zone ID for a specific domain
const myZoneId = await myCflareAccount.convenience.getZoneId('example.com');
console.log('Zone ID:', myZoneId);
// Purge cache for a zone
await myCflareAccount.convenience.purgeZone('example.com');
console.log('Cache purged for example.com');
// List DNS records for a domain
const myRecords = await myCflareAccount.convenience.listRecords('example.com');
console.log('DNS Records:', myRecords);
// Get a specific DNS record
const myRecord = await myCflareAccount.convenience.getRecord('sub.example.com', 'A');
console.log('Specific DNS Record:', myRecord);
// Create a DNS record
const createResponse = await myCflareAccount.convenience.createRecord('sub.example.com', 'A', '127.0.0.1');
console.log('Created DNS Record:', createResponse);
// Clean DNS records
await myCflareAccount.convenience.cleanRecord('sub.example.com', 'A');
console.log('Cleaned DNS Records for sub.example.com');
// Create a Cloudflare Worker
const myWorker = await myCflareAccount.workerManager.createWorker('myWorker', `addEventListener('fetch', event => { event.respondWith(fetch(event.request)) })`);
console.log('Created Worker:', myWorker);
// Set routes for the Worker
await myWorker.setRoutes([{ zoneName: 'example.com', pattern: 'https://*example.com/*' }]);
console.log('Routes set for Worker');
// List all Workers
const workers = await myCflareAccount.workerManager.listWorkers();
console.log('Workers:', workers);
} catch (error) {
console.error('Error managing Cloudflare:', error);
}
};
manageCloudflare();
```
This complete guide covers initialization, managing Cloudflare zones, DNS records, and Cloudflare Workers comprehensively using TypeScript for enhanced type safety and intellisense. Always ensure to keep your API keys secure and avoid hardcoding them directly in your scripts.
undefined

View File

@ -1,9 +1,9 @@
// tslint:disable-next-line: no-implicit-dependencies // tslint:disable-next-line: no-implicit-dependencies
import { expect, tap } from '@pushrocks/tapbundle'; import { expect, tap } from '@push.rocks/tapbundle';
// tslint:disable-next-line: no-implicit-dependencies // tslint:disable-next-line: no-implicit-dependencies
import { Qenv } from '@pushrocks/qenv'; import { Qenv } from '@push.rocks/qenv';
import cloudflare = require('../ts/index'); import * as cloudflare from '../ts/index.js';
const testQenv = new Qenv(process.cwd(), process.cwd() + '/.nogit'); const testQenv = new Qenv(process.cwd(), process.cwd() + '/.nogit');
@ -11,57 +11,63 @@ const randomPrefix = Math.floor(Math.random() * 2000);
let testCloudflareAccount: cloudflare.CloudflareAccount; let testCloudflareAccount: cloudflare.CloudflareAccount;
tap.test('should create a valid instance of CloudflareAccount', async () => { tap.test('should create a valid instance of CloudflareAccount', async () => {
testCloudflareAccount = new cloudflare.CloudflareAccount({ testCloudflareAccount = new cloudflare.CloudflareAccount(await testQenv.getEnvVarOnDemand('CF_KEY'));
email: testQenv.getEnvVarOnDemand('CF_EMAIL'),
key: testQenv.getEnvVarOnDemand('CF_KEY')
});
}); });
tap.test('.listZones() -> should display an entire account', async tools => { tap.test('should preselect an account', async () => {
await testCloudflareAccount.preselectAccountByName('Sandbox Account');
})
tap.test('.listZones() -> should display an entire account', async (tools) => {
tools.timeout(600000); tools.timeout(600000);
const result = await testCloudflareAccount.convenience.listZones(); const result = await testCloudflareAccount.convenience.listZones();
console.log(result); console.log(result);
// await tools.delayFor(10000);
}); });
tap.test( tap.test(
'.getZoneId(domainName) -> should get an Cloudflare Id for a domain string', '.getZoneId(domainName) -> should get an Cloudflare Id for a domain string',
async tools => { async (tools) => {
tools.timeout(600000); tools.timeout(600000);
await testCloudflareAccount.getZoneId('bleu.de'); const id = await testCloudflareAccount.convenience.getZoneId('bleu.de');
console.log(`The account id for bleu.de is: ${id}`);
} }
); );
tap.test( tap.test(
'.listRecords(domainName) -> should list all records for a specific Domain Name', '.listRecords(domainName) -> should list all records for a specific Domain Name',
async tools => { async (tools) => {
tools.timeout(600000); tools.timeout(600000);
await testCloudflareAccount.convenience.listRecords('bleu.de').then(async responseArg => { await testCloudflareAccount.convenience.listRecords('bleu.de').then(async (responseArg) => {
console.log(responseArg); console.log(responseArg);
}); });
} }
); );
tap.test('should create a valid record for a subdomain', async tools => { tap.test('should create a valid record for a subdomain', async (tools) => {
tools.timeout(600000); tools.timeout(600000);
await testCloudflareAccount.convenience.createRecord(`${randomPrefix}subdomain.bleu.de`, 'A', '127.0.0.1'); await testCloudflareAccount.convenience.createRecord(
`${randomPrefix}subdomain.bleu.de`,
'A',
'127.0.0.1',
120
);
}); });
tap.test('should get a record from Cloudflare', async tools => { tap.test('should get a record from Cloudflare', async (tools) => {
tools.timeout(600000); tools.timeout(600000);
await testCloudflareAccount await testCloudflareAccount.convenience
.convenience
.getRecord(`${randomPrefix}subdomain.bleu.de`, 'A') .getRecord(`${randomPrefix}subdomain.bleu.de`, 'A')
.then(responseArg => { .then((responseArg) => {
console.log(responseArg); console.log(responseArg);
}); });
}); });
tap.test('should remove a subdomain record from Cloudflare', async tools => { tap.test('should remove a subdomain record from Cloudflare', async (tools) => {
tools.timeout(600000); tools.timeout(600000);
await testCloudflareAccount await testCloudflareAccount.convenience
.convenience
.removeRecord(`${randomPrefix}subdomain.bleu.de`, 'A') .removeRecord(`${randomPrefix}subdomain.bleu.de`, 'A')
.then(async responseArg => { .then(async (responseArg) => {
console.log(responseArg); console.log(responseArg);
}); });
}); });
@ -70,6 +76,11 @@ tap.test('.purge(some.domain) -> should purge everything', async () => {
await testCloudflareAccount.convenience.purgeZone('bleu.de'); await testCloudflareAccount.convenience.purgeZone('bleu.de');
}); });
tap.test('should list workers', async () => {
const workerArray = await testCloudflareAccount.workerManager.listWorkerScripts();
console.log(workerArray);
});
// WORKERS // WORKERS
tap.test('should create a worker', async () => { tap.test('should create a worker', async () => {
const worker = await testCloudflareAccount.workerManager.createWorker( const worker = await testCloudflareAccount.workerManager.createWorker(
@ -79,14 +90,14 @@ tap.test('should create a worker', async () => {
await worker.setRoutes([ await worker.setRoutes([
{ {
zoneName: 'bleu.de', zoneName: 'bleu.de',
pattern: 'https://*bleu.de/hello' pattern: 'https://*bleu.de/hello',
} },
]); ]);
console.log(worker); console.log(worker);
}); });
tap.test('should get workers', async () => { tap.test('should get workers again', async () => {
const workerArray = await testCloudflareAccount.workerManager.listWorkers(); const workerArray = await testCloudflareAccount.workerManager.listWorkerScripts();
console.log(workerArray); console.log(workerArray);
}); });

8
ts/00_commitinfo_data.ts Normal file
View File

@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @pushrocks/commitinfo
*/
export const commitinfo = {
name: '@apiclient.xyz/cloudflare',
version: '6.0.5',
description: 'A TypeScript client for managing Cloudflare accounts, zones, DNS records, and workers with ease.'
}

View File

@ -1,61 +1,71 @@
import plugins = require('./cloudflare.plugins'); import * as plugins from './cloudflare.plugins.js';
import * as interfaces from './interfaces'; import { logger } from './cloudflare.logger.js';
import * as interfaces from './interfaces/index.js';
// interfaces // interfaces
import { WorkerManager } from './cloudflare.classes.workermanager'; import { WorkerManager } from './cloudflare.classes.workermanager.js';
import { ZoneManager } from './cloudflare.classes.zonemanager'; import { ZoneManager } from './cloudflare.classes.zonemanager.js';
export class CloudflareAccount { export class CloudflareAccount {
private authEmail: string; private authToken: string;
private authKey: string; public preselectedAccountId: string;
private accountIdentifier: string;
public workerManager = new WorkerManager(this); public workerManager = new WorkerManager(this);
public zoneManager = new ZoneManager(this); public zoneManager = new ZoneManager(this);
public apiAccount: plugins.cloudflare.Cloudflare;
/** /**
* constructor sets auth information on the CloudflareAccountInstance * constructor sets auth information on the CloudflareAccountInstance
* @param optionsArg * @param optionsArg
*/ */
constructor(optionsArg: { email: string; key: string }) { constructor(authTokenArg: string) {
this.authEmail = optionsArg.email; this.authToken = authTokenArg;
this.authKey = optionsArg.key; this.apiAccount = new plugins.cloudflare.Cloudflare({
apiToken: this.authToken,
});
} }
public async preselectAccountByName(nameArg: string) {
const accounts = await this.convenience.listAccounts();
const account = accounts.find((accountArg) => {
return accountArg.name === nameArg;
});
if (account) {
this.preselectedAccountId = account.id;
} else {
throw new Error(`account with name ${nameArg} not found`);
}
}
public convenience = {
/** /**
* gets you the account identifier * listAccounts
*/ */
public async getAccountIdentifier() { listAccounts: async () => {
if (!this.accountIdentifier) { const accounts: plugins.ICloudflareTypes['Account'][] = [];
const route = `/accounts?page=1&per_page=20&direction=desc`; for await (const account of this.apiAccount.accounts.list()) {
const response: any = await this.request('GET', route); accounts.push(account as interfaces.ICloudflareApiAccountObject);
this.accountIdentifier = response.result[0].id;
} }
return this.accountIdentifier; return accounts;
} },
/** /**
* gets a zone id of a domain from cloudflare * gets a zone id of a domain from cloudflare
* @param domainName * @param domainName
*/ */
public async getZoneId(domainName: string) { getZoneId: async (domainName: string) => {
const domain = new plugins.smartstring.Domain(domainName); const domain = new plugins.smartstring.Domain(domainName);
const zoneArray = await this.convenience.listZones(domain.zoneName); const zoneArray = await this.convenience.listZones(domain.zoneName);
const filteredResponse = zoneArray.filter(zoneArg => { const filteredResponse = zoneArray.filter((zoneArg) => {
return zoneArg.name === domainName; return zoneArg.name === domainName;
}); });
if (filteredResponse.length >= 1) { if (filteredResponse.length >= 1) {
return filteredResponse[0].id; return filteredResponse[0].id;
} else { } else {
plugins.smartlog.defaultLogger.log( logger.log('error', `the domain ${domainName} does not appear to be in this account!`);
'error',
`the domain ${domainName} does not appear to be in this account!`
);
throw new Error(`the domain ${domainName} does not appear to be in this account!`); throw new Error(`the domain ${domainName} does not appear to be in this account!`);
} }
} },
public convenience = {
/** /**
* gets a record * gets a record
* @param domainNameArg * @param domainNameArg
@ -63,11 +73,11 @@ export class CloudflareAccount {
*/ */
getRecord: async ( getRecord: async (
domainNameArg: string, domainNameArg: string,
typeArg: plugins.tsclass.network.TDnsRecord typeArg: plugins.tsclass.network.TDnsRecordType
): Promise<interfaces.ICflareRecord> => { ): Promise<plugins.ICloudflareTypes['Record']> => {
const domain = new plugins.smartstring.Domain(domainNameArg); const domain = new plugins.smartstring.Domain(domainNameArg);
const recordArrayArg = await this.convenience.listRecords(domain.zoneName); const recordArrayArg = await this.convenience.listRecords(domain.zoneName);
const filteredResponse = recordArrayArg.filter(recordArg => { const filteredResponse = recordArrayArg.filter((recordArg) => {
return recordArg.type === typeArg && recordArg.name === domainNameArg; return recordArg.type === typeArg && recordArg.name === domainNameArg;
}); });
return filteredResponse[0]; return filteredResponse[0];
@ -77,21 +87,19 @@ export class CloudflareAccount {
*/ */
createRecord: async ( createRecord: async (
domainNameArg: string, domainNameArg: string,
typeArg: plugins.tsclass.network.TDnsRecord, typeArg: plugins.tsclass.network.TDnsRecordType,
contentArg: string contentArg: string,
ttlArg = 1
): Promise<any> => { ): Promise<any> => {
const domain = new plugins.smartstring.Domain(domainNameArg); const domain = new plugins.smartstring.Domain(domainNameArg);
const domainIdArg = await this.getZoneId(domain.zoneName); const zoneId = await this.convenience.getZoneId(domain.zoneName);
const dataObject = { const response = await this.apiAccount.dns.records.create({
zone_id: zoneId,
type: typeArg as any,
name: domain.fullName, name: domain.fullName,
type: typeArg, content: contentArg,
content: contentArg ttl: ttlArg,
}; })
const response = await this.request(
'POST',
'/zones/' + domainIdArg + '/dns_records',
dataObject
);
return response; return response;
}, },
/** /**
@ -101,24 +109,50 @@ export class CloudflareAccount {
*/ */
removeRecord: async ( removeRecord: async (
domainNameArg: string, domainNameArg: string,
typeArg: plugins.tsclass.network.TDnsRecord typeArg: plugins.tsclass.network.TDnsRecordType
): Promise<any> => { ): Promise<any> => {
const domain = new plugins.smartstring.Domain(domainNameArg); const domain = new plugins.smartstring.Domain(domainNameArg);
const cflareRecord = await this.convenience.getRecord(domain.fullName, typeArg); const zoneId = await this.convenience.getZoneId(domain.zoneName);
if (cflareRecord) { const records = await this.convenience.listRecords(domain.zoneName);
const requestRoute: string = `/zones/${cflareRecord.zone_id}/dns_records/${cflareRecord.id}`; const recordToDelete = records.find((recordArg) => {
return await this.request('DELETE', requestRoute); return recordArg.name === domainNameArg && recordArg.type === typeArg;
});
if (recordToDelete) {
await this.apiAccount.dns.records.delete(recordToDelete.id, {
zone_id: zoneId,
});
} else { } else {
throw new Error(`could not remove record for ${domainNameArg} with type ${typeArg}`); logger.log('warn', `record ${domainNameArg} of type ${typeArg} not found`);
} }
}, },
/**
* cleanrecord allows the cleaning of any previous records to avoid unwanted sideeffects
*/
cleanRecord: async (domainNameArg: string, typeArg: plugins.tsclass.network.TDnsRecordType) => {
console.log(`cleaning record for ${domainNameArg}`);
const records = await this.convenience.listRecords(domainNameArg);
const recordsToDelete = records.filter((recordArg) => {
return recordArg.type === typeArg;
});
for (const recordToDelete of recordsToDelete) {
await this.apiAccount.dns.records.delete(recordToDelete.id, {
zone_id: recordToDelete.zone_id,
});
}
},
/** /**
* updates a record * updates a record
* @param domainNameArg * @param domainNameArg
* @param typeArg * @param typeArg
* @param valueArg * @param valueArg
*/ */
updateRecord: async (domainNameArg: string, typeArg: string, valueArg) => { updateRecord: async (
domainNameArg: string,
typeArg: plugins.tsclass.network.TDnsRecordType,
valueArg
) => {
// TODO: implement // TODO: implement
const domain = new plugins.smartstring.Domain(domainNameArg); const domain = new plugins.smartstring.Domain(domainNameArg);
}, },
@ -126,103 +160,52 @@ export class CloudflareAccount {
* list all records of a specified domain name * list all records of a specified domain name
* @param domainNameArg - the domain name that you want to get the records from * @param domainNameArg - the domain name that you want to get the records from
*/ */
listRecords: async (domainNameArg: string): Promise<interfaces.ICflareRecord[]> => { listRecords: async (domainNameArg: string) => {
const domain = new plugins.smartstring.Domain(domainNameArg); const domain = new plugins.smartstring.Domain(domainNameArg);
const domainId = await this.getZoneId(domain.zoneName); const zoneId = await this.convenience.getZoneId(domain.zoneName);
const responseArg: any = await this.request( const records: plugins.ICloudflareTypes['Record'][] = [];
'GET', for await (const record of this.apiAccount.dns.records.list({
'/zones/' + domainId + '/dns_records?per_page=100' zone_id: zoneId,
); })) {
const result: interfaces.ICflareRecord[] = responseArg.result; records.push(record);
return result; }
return records;
}, },
/** /**
* list all zones in the associated authenticated account * list all zones in the associated authenticated account
* @param domainName * @param domainName
*/ */
listZones: async (domainName?: string): Promise<interfaces.ICflareZone[]> => { listZones: async (domainName?: string) => {
// TODO: handle pagination const zones: plugins.ICloudflareTypes['Zone'][] = [];
let requestRoute = `/zones?per_page=50`; for await (const zone of this.apiAccount.zones.list()) {
zones.push(zone);
// may be optionally filtered by domain name
if (domainName) {
requestRoute = `${requestRoute}&name=${domainName}`;
} }
return zones;
const response: any = await this.request('GET', requestRoute);
const result = response.result;
return result;
}, },
/** /**
* purges a zone * purges a zone
*/ */
purgeZone: async (domainName: string): Promise<void> => { purgeZone: async (domainName: string): Promise<void> => {
const domain = new plugins.smartstring.Domain(domainName); const domain = new plugins.smartstring.Domain(domainName);
const domainId = await this.getZoneId(domain.zoneName); const zoneId = await this.convenience.getZoneId(domain.zoneName);
const requestUrl = `/zones/${domainId}/purge_cache`; await this.apiAccount.cache.purge({
const payload = { zone_id: zoneId,
purge_everything: true purge_everything: true,
}; });
const respone = await this.request('DELETE', requestUrl, payload);
}
};
public request(
methodArg: string,
routeArg: string,
dataArg: any = {},
requestHeadersArg = {}
): Promise<any> {
const done = plugins.smartpromise.defer();
const options: plugins.smartrequest.ISmartRequestOptions = {
method: methodArg,
headers: {
'Content-Type': 'application/json',
'X-Auth-Email': this.authEmail,
'X-Auth-Key': this.authKey,
'Content-Length': Buffer.byteLength(JSON.stringify(dataArg)),
...requestHeadersArg
}, },
requestBody: dataArg
};
// console.log(options); // acme convenience functions
acmeSetDnsChallenge: async (dnsChallenge: plugins.tsclass.network.IDnsChallenge) => {
let retryCount = 0; // count the amount of retries await this.convenience.cleanRecord(dnsChallenge.hostName, 'TXT');
await this.convenience.createRecord(
const makeRequest = async () => { dnsChallenge.hostName,
const response: any = await plugins.smartrequest.request( 'TXT',
`https://api.cloudflare.com/client/v4${routeArg}`, dnsChallenge.challenge,
options 120
); );
if (response.statusCode === 200) { },
done.resolve(response.body); acmeRemoveDnsChallenge: async (dnsChallenge: plugins.tsclass.network.IDnsChallenge) => {
} else if (response.statusCode === 429) { await this.convenience.removeRecord(dnsChallenge.hostName, 'TXT');
console.log('rate limited! Waiting for retry!'); },
retryRequest();
} else if (response.statusCode === 400) {
console.log(`bad request for route ${routeArg}! Going to retry!`);
console.log(response.body);
} else {
console.log(response.statusCode);
done.reject(new Error('request failed'));
}
}; };
const retryRequest = async (
delayTimeArg = Math.floor(Math.random() * (60000 - 8000) + 8000)
) => {
console.log(`retry started and waiting for ${delayTimeArg} ms`);
await plugins.smartdelay.delayFor(delayTimeArg);
if (retryCount < 10) {
retryCount++;
return await makeRequest();
}
};
makeRequest();
return done.promise;
}
private authCheck() {
return this.authEmail && this.authKey; // check if auth is available
}
} }

View File

@ -0,0 +1,3 @@
import * as plugins from './cloudflare.plugins.js';
export class CloudflareRecord {}

View File

@ -1,6 +1,7 @@
import * as plugins from './cloudflare.plugins'; import * as plugins from './cloudflare.plugins.js';
import * as interfaces from './interfaces'; import * as interfaces from './interfaces/index.js';
import { WorkerManager } from './cloudflare.classes.workermanager'; import { WorkerManager } from './cloudflare.classes.workermanager.js';
import { logger } from './cloudflare.logger.js';
export interface IWorkerRoute extends interfaces.ICflareWorkerRoute { export interface IWorkerRoute extends interfaces.ICflareWorkerRoute {
zoneName: string; zoneName: string;
@ -66,25 +67,25 @@ export class CloudflareWorker {
routeIdForUpdate = existingRoute.id; routeIdForUpdate = existingRoute.id;
if (existingRoute.script === this.id) { if (existingRoute.script === this.id) {
routeStatus = 'alreadyUpToDate'; routeStatus = 'alreadyUpToDate';
plugins.smartlog.defaultLogger.log('info', `route already exists, no update needed`); logger.log('info', `route already exists, no update needed`);
} }
} }
} }
// lets care about actually setting routes // lets care about actually setting routes
if (routeStatus === 'new') { if (routeStatus === 'new') {
const zoneId = await this.workerManager.cfAccount.getZoneId(newRoute.zoneName); const zoneId = await this.workerManager.cfAccount.convenience.getZoneId(newRoute.zoneName);
const requestRoute = `/zones/${zoneId}/workers/routes`; const requestRoute = `/zones/${zoneId}/workers/routes`;
await this.workerManager.cfAccount.request('POST', requestRoute, { await this.workerManager.cfAccount.request('POST', requestRoute, {
pattern: newRoute.pattern, pattern: newRoute.pattern,
script: this.id script: this.id,
}); });
} else if (routeStatus === 'needsUpdate') { } else if (routeStatus === 'needsUpdate') {
const zoneId = await this.workerManager.cfAccount.getZoneId(newRoute.zoneName); const zoneId = await this.workerManager.cfAccount.convenience.getZoneId(newRoute.zoneName);
const requestRoute = `/zones/${zoneId}/workers/routes/${routeIdForUpdate}`; const requestRoute = `/zones/${zoneId}/workers/routes/${routeIdForUpdate}`;
await this.workerManager.cfAccount.request('PUT', requestRoute, { await this.workerManager.cfAccount.request('PUT', requestRoute, {
pattern: newRoute.pattern, pattern: newRoute.pattern,
script: this.id script: this.id,
}); });
} }
} }

View File

@ -1,6 +1,6 @@
import * as plugins from './cloudflare.plugins'; import * as plugins from './cloudflare.plugins.js';
import { CloudflareAccount } from './cloudflare.classes.account'; import { CloudflareAccount } from './cloudflare.classes.account.js';
import { CloudflareWorker } from './cloudflare.classes.worker'; import { CloudflareWorker } from './cloudflare.classes.worker.js';
export class WorkerManager { export class WorkerManager {
public cfAccount: CloudflareAccount; public cfAccount: CloudflareAccount;
@ -9,28 +9,30 @@ export class WorkerManager {
this.cfAccount = cfAccountArg; this.cfAccount = cfAccountArg;
} }
public async createWorker(workerName: string, workerScript: string): Promise<CloudflareWorker> { public async createWorker(workerName: string, workerScript: string): Promise<plugins.ICloudflareTypes['Script']> {
const accountIdentifier = await this.cfAccount.getAccountIdentifier(); if (!this.cfAccount.preselectedAccountId) {
const route = `/accounts/${accountIdentifier}/workers/scripts/${workerName}`; throw new Error('No account selected. Please select it first on the account.');
const responseBody = await this.cfAccount.request('PUT', route, workerScript, { }
'Content-Type': 'application/javascript', const worker = await this.cfAccount.apiAccount.workers.scripts.content.update(workerName, {
'Content-Length': Buffer.byteLength(workerScript) account_id: this.cfAccount.preselectedAccountId,
"CF-WORKER-BODY-PART": workerScript,
}); });
return CloudflareWorker.fromApiObject(this, responseBody.result); return worker;
} }
/** /**
* lists workers * lists workers
*/ */
public async listWorkers() { public async listWorkerScripts() {
const accountIdentifier = await this.cfAccount.getAccountIdentifier(); if (!this.cfAccount.preselectedAccountId) {
const route = `/accounts/${accountIdentifier}/workers/scripts`; throw new Error('No account selected. Please select it first on the account.');
const response = await this.cfAccount.request('GET', route);
const results = response.result;
const workers: CloudflareWorker[] = [];
for (const apiObject of results) {
workers.push(await CloudflareWorker.fromApiObject(this, apiObject));
} }
return workers; const workerScripts: plugins.ICloudflareTypes['Script'][] = [];
for await (const scriptArg of this.cfAccount.apiAccount.workers.scripts.list({
account_id: this.cfAccount.preselectedAccountId,
})) {
workerScripts.push(scriptArg);
}
return workerScripts;
} }
} }

View File

@ -1,6 +1,9 @@
import * as plugins from './cloudflare.plugins'; import * as plugins from './cloudflare.plugins.js';
import * as interfaces from './interfaces';
export class CloudflareZone { export class CloudflareZone {
// TODO public static createFromApiObject(apiObject: plugins.ICloudflareTypes['Zone']) {
const cloudflareZone = new CloudflareZone();
Object.assign(cloudflareZone, apiObject);
return cloudflareZone;
}
} }

View File

@ -1,5 +1,7 @@
import * as plugins from './cloudflare.plugins'; import * as plugins from './cloudflare.plugins.js';
import { CloudflareAccount } from './cloudflare.classes.account'; import * as interfaces from './interfaces/index.js';
import { CloudflareAccount } from './cloudflare.classes.account.js';
import { CloudflareZone } from './cloudflare.classes.zone.js';
export class ZoneManager { export class ZoneManager {
public cfAccount: CloudflareAccount; public cfAccount: CloudflareAccount;
@ -8,4 +10,23 @@ export class ZoneManager {
constructor(cfAccountArg: CloudflareAccount) { constructor(cfAccountArg: CloudflareAccount) {
this.cfAccount = cfAccountArg; this.cfAccount = cfAccountArg;
} }
public async getZones(zoneName: string) {
let requestRoute = `/zones?per_page=50`;
// may be optionally filtered by domain name
if (zoneName) {
requestRoute = `${requestRoute}&name=${zoneName}`;
}
const response: any = await this.cfAccount.request('GET', requestRoute);
const apiObjects: interfaces.ICflareZone[] = response.result;
const cloudflareZoneArray = [];
for (const apiObject of apiObjects) {
cloudflareZoneArray.push(CloudflareZone.createFromApiObject(apiObject));
}
return cloudflareZoneArray;
}
} }

3
ts/cloudflare.logger.ts Normal file
View File

@ -0,0 +1,3 @@
import * as plugins from './cloudflare.plugins.js';
export const logger = new plugins.smartlog.ConsoleLog();

View File

@ -1,8 +1,24 @@
import * as smartlog from '@pushrocks/smartlog'; import * as smartlog from '@push.rocks/smartlog';
import * as smartpromise from '@pushrocks/smartpromise'; import * as smartpromise from '@push.rocks/smartpromise';
import * as smartdelay from '@pushrocks/smartdelay'; import * as smartdelay from '@push.rocks/smartdelay';
import * as smartrequest from '@pushrocks/smartrequest'; import * as smartrequest from '@push.rocks/smartrequest';
import * as smartstring from '@pushrocks/smartstring'; import * as smartstring from '@push.rocks/smartstring';
import * as tsclass from '@tsclass/tsclass'; import * as tsclass from '@tsclass/tsclass';
export { smartlog, smartpromise, smartdelay, smartrequest, smartstring, tsclass }; export { smartlog, smartpromise, smartdelay, smartrequest, smartstring, tsclass };
// third party
import * as cloudflare from 'cloudflare';
import * as interfaces from './interfaces/index.js';
import type { Zone } from 'cloudflare/resources/zones/zones.js';
import type { Record } from 'cloudflare/resources/dns/records.js';
import type { Script } from 'cloudflare/resources/workers/scripts/index.js';
export interface ICloudflareTypes {
Account: interfaces.ICloudflareApiAccountObject;
Record: Record;
Zone: Zone;
Script: Script;
}
export { cloudflare };

View File

@ -1,2 +1,2 @@
export { CloudflareAccount } from './cloudflare.classes.account'; export { CloudflareAccount } from './cloudflare.classes.account.js';
export { CloudflareWorker } from './cloudflare.classes.worker'; export { CloudflareWorker } from './cloudflare.classes.worker.js';

View File

@ -0,0 +1,20 @@
export interface ICloudflareApiAccountObject {
id: string;
name: string;
type: 'standard' | 'enterprise' | 'pro' | 'free'; // Assuming other possible types
settings: {
enforce_twofactor: boolean;
api_access_enabled: boolean | null;
access_approval_expiry: string | null; // Assuming ISO date string or null
use_account_custom_ns_by_default: boolean;
default_nameservers: string;
};
legacy_flags: {
enterprise_zone_quota: {
maximum: number;
current: number;
available: number;
};
};
created_on: string; // Assuming ISO date string
}

View File

@ -1,15 +0,0 @@
export interface ICflareRecord {
id: string;
type: string;
name: string;
content: string;
proxiable: boolean;
proxied: boolean;
ttl: number;
locked: boolean;
zone_id: string;
zone_name: string;
created_on: string;
modified_on: string;
data: any;
}

View File

@ -1,41 +0,0 @@
export interface ICflareZone {
id: string;
name: string;
development_mode: number;
original_name_servers: string[];
original_registrar: string;
original_dnshost: string;
created_on: string;
modified_on: string;
name_servers: string[];
owner: {
id: string;
email: string;
owner_type: string;
};
permissions: string[];
plan: {
id: string;
name: string;
price: number;
currency: string;
frequency: string;
legacy_id: string;
is_subscribed: boolean;
can_subscribe: boolean;
};
plan_pending: {
id: string;
name: string;
price: number;
currency: string;
frequency: string;
legacy_id: string;
is_subscribed: string;
can_subscribe: string;
};
status: string;
paused: boolean;
type: string;
checked_on: string;
}

View File

@ -1,3 +1,2 @@
export * from './cloudflare.api.record'; export * from './cloudflare.api.account.js';
export * from './cloudflare.api.zone'; export * from './cloudflare.api.workerroute.js';
export * from './cloudflare.api.workerroute';

14
tsconfig.json Normal file
View File

@ -0,0 +1,14 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": false,
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"verbatimModuleSyntax": true
},
"exclude": [
"dist_*/**/*.d.ts"
]
}

View File

@ -1,17 +0,0 @@
{
"extends": ["tslint:latest", "tslint-config-prettier"],
"rules": {
"semicolon": [true, "always"],
"no-console": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"member-ordering": {
"options":{
"order": [
"static-method"
]
}
}
},
"defaultSeverity": "warning"
}