-
Notifications
You must be signed in to change notification settings - Fork 120
Expand file tree
/
Copy pathcloudflare.js
More file actions
142 lines (116 loc) · 3.04 KB
/
cloudflare.js
File metadata and controls
142 lines (116 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
'use strict'
// @ts-ignore
const dnslink = require('dnslink-cloudflare')
const isEmpty = require('lodash.isempty')
const got = require('got')
class CloudflareWeb3GatewayClient {
// @ts-ignore
async getZoneId (api, name) {
let res
for (let i = 1; (res = await api(`zones?page=${i}`)) && res.body.result_info.total_pages >= i; i++) {
for (const zone of res.body.result) {
if (zone.name === name) {
return zone.id
}
}
}
throw new Error(`zone ${name} couldn't be found`)
}
// https://api.cloudflare.com/#web3-hostname-list-web3-hostnames
// @ts-ignore
async getRecord (api, id, name) {
const res = await api(`zones/${id}/web3/hostnames`)
// @ts-ignore
const record = res.body.result.find(r => r.name === name)
return record
}
// @ts-ignore
getClient (apiOpts) {
const opts = {
prefixUrl: 'https://api.cloudflare.com/client/v4',
responseType: 'json'
}
if (apiOpts.token) {
// @ts-ignore
opts.headers = {
Authorization: `Bearer ${apiOpts.token}`
}
} else {
// @ts-ignore
opts.headers = {
'X-Auth-Email': apiOpts.email,
'X-Auth-Key': apiOpts.key
}
}
// @ts-ignore
return got.extend(opts)
}
// @ts-ignore
async update (apiOpts, { zone, link, record }) {
const api = this.getClient(apiOpts)
const id = await this.getZoneId(api, zone)
const rec = await this.getRecord(api, id, record)
if (!rec) {
throw new Error(`web3 gw for ${record} couldn't be found, must be created first`)
}
await api.patch(`zones/${id}/web3/hostnames/${rec.id}`, {
json: {
dnslink: link
}
})
return `dnslink=${link}`
}
}
/**
* @typedef {import('./types').DNSRecord} DNSRecord
* @typedef {import('./types').CloudflareOptions} CloudflareOptions
*/
class Cloudflare {
/**
* @param {CloudflareOptions} options
*/
constructor ({ apiEmail, apiKey, apiToken, zone, record, useWeb3Gw }) {
if ([apiKey, apiEmail, apiToken].every(isEmpty)) {
throw new Error('apiEmail and apiKey or apiToken are required for Cloudflare')
}
if ([zone, record].some(isEmpty)) {
throw new Error('zone and record are required for CloudFlare')
}
if (isEmpty(apiKey)) {
this.api = { token: apiToken }
} else {
this.api = {
email: apiEmail,
key: apiKey
}
}
this.opts = { record, zone, useWeb3Gw: Boolean(useWeb3Gw) }
}
/**
* @param {string} cid
* @returns {Promise<DNSRecord>}
*/
async link (cid) {
const opts = {
...this.opts,
link: `/ipfs/${cid}`
}
const content = this.opts.useWeb3Gw
? await (new CloudflareWeb3GatewayClient()).update(this.api, opts)
: await dnslink(this.api, opts)
return {
record: opts.record,
value: content
}
}
static get displayName () {
return 'Cloudflare'
}
get displayName () {
return Cloudflare.displayName
}
static get slug () {
return 'cloudflare'
}
}
module.exports = Cloudflare