@nodeart/cloudflare-provisioning 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env sh
2
+ . "$(dirname -- "$0")/_/husky.sh"
3
+
4
+ npm run lint
package/README.md ADDED
File without changes
package/cloudflare.js ADDED
@@ -0,0 +1,603 @@
1
+ 'use strict'
2
+
3
+ const { request } = require('undici')
4
+
5
+ const CLOUDFLARE_API_URL = 'https://api.cloudflare.com/client/v4/'
6
+
7
+ class CloudFlare {
8
+ constructor (zoneId, options) {
9
+ this.zoneId = zoneId
10
+
11
+ this.authorizationHeaders = null
12
+ if (options.email !== undefined && options.apiKey !== undefined) {
13
+ this.authorizationHeaders = {
14
+ 'X-Auth-Email': options.email,
15
+ 'X-Auth-Key': options.apiKey
16
+ }
17
+ } else if (options.token !== undefined) {
18
+ this.authorizationHeaders = {
19
+ authorization: 'Bearer ' + options.token
20
+ }
21
+ } else {
22
+ throw new Error('You must provide either an email and api key or a token')
23
+ }
24
+ }
25
+
26
+ async setIPv6 (value) {
27
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/ipv6`
28
+
29
+ const { statusCode, body } = await request(url, {
30
+ method: 'PATCH',
31
+ headers: {
32
+ ...this.authorizationHeaders,
33
+ 'Content-Type': 'application/json'
34
+ },
35
+ body: JSON.stringify({ value })
36
+ })
37
+
38
+ const response = await body.json()
39
+
40
+ if (statusCode !== 200) {
41
+ throw new Error(`Could not change IPv6: ${statusCode}, error: ${JSON.stringify(response)}`)
42
+ }
43
+
44
+ return response
45
+ }
46
+
47
+ async setEmailObfuscation (value) {
48
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/email_obfuscation`
49
+
50
+ const { statusCode, body } = await request(url, {
51
+ method: 'PATCH',
52
+ headers: {
53
+ ...this.authorizationHeaders,
54
+ 'Content-Type': 'application/json'
55
+ },
56
+ body: JSON.stringify({ value })
57
+ })
58
+
59
+ const response = await body.json()
60
+
61
+ if (statusCode !== 200) {
62
+ throw new Error(`Could not change email obfuscation: ${statusCode}, error: ${JSON.stringify(response)}`)
63
+ }
64
+
65
+ return response
66
+ }
67
+
68
+ async setSSL (value) {
69
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/ssl`
70
+
71
+ const { statusCode, body } = await request(url, {
72
+ method: 'PATCH',
73
+ headers: {
74
+ ...this.authorizationHeaders,
75
+ 'Content-Type': 'application/json'
76
+ },
77
+ body: JSON.stringify({ value })
78
+ })
79
+
80
+ const response = await body.json()
81
+
82
+ if (statusCode !== 200) {
83
+ throw new Error(`Could not change SSL: ${statusCode}, error: ${JSON.stringify(response)}`)
84
+ }
85
+
86
+ return response
87
+ }
88
+
89
+ async setBrotli (value) {
90
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/brotli`
91
+
92
+ const { statusCode, body } = await request(url, {
93
+ method: 'PATCH',
94
+ headers: {
95
+ ...this.authorizationHeaders,
96
+ 'Content-Type': 'application/json'
97
+ },
98
+ body: JSON.stringify({ value })
99
+ })
100
+
101
+ const response = await body.json()
102
+
103
+ if (statusCode !== 200) {
104
+ throw new Error(`Could not change brotli: ${statusCode}, error: ${JSON.stringify(response)}`)
105
+ }
106
+
107
+ return response
108
+ }
109
+
110
+ async getDNSRecords () {
111
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/dns_records`
112
+
113
+ const { statusCode, body } = await request(url, {
114
+ method: 'GET',
115
+ headers: {
116
+ ...this.authorizationHeaders,
117
+ 'Content-Type': 'application/json'
118
+ }
119
+ })
120
+
121
+ const response = await body.json()
122
+
123
+ if (statusCode !== 200) {
124
+ throw new Error(`Could not get DNS records: ${statusCode}, error: ${JSON.stringify(response)}`)
125
+ }
126
+
127
+ return response
128
+ }
129
+
130
+ async rewriteDNSRecords (dnsRecords) {
131
+ const currentDNSRecords = await this.getDNSRecords()
132
+
133
+ for (const dnsRecord of dnsRecords) {
134
+ const currentDNSRecord = currentDNSRecords.result.find(
135
+ record => record.name === dnsRecord.name
136
+ )
137
+
138
+ try {
139
+ if (currentDNSRecord) {
140
+ await this.updateDNSRecord(currentDNSRecord.id, dnsRecord)
141
+ } else {
142
+ await this.createDNSRecord(dnsRecord)
143
+ }
144
+ } catch (error) {
145
+ console.error(`Could not update DNS record: ${JSON.stringify(dnsRecord)}, error: ${error}`)
146
+ }
147
+ }
148
+ }
149
+
150
+ async createDNSRecord (dnsRecord) {
151
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/dns_records`
152
+
153
+ const { statusCode, body } = await request(url, {
154
+ method: 'POST',
155
+ headers: {
156
+ ...this.authorizationHeaders,
157
+ 'Content-Type': 'application/json'
158
+ },
159
+ body: JSON.stringify(dnsRecord)
160
+ })
161
+
162
+ const response = await body.json()
163
+
164
+ if (statusCode !== 200) {
165
+ throw new Error(`Could not create DNS record: ${statusCode}, error: ${JSON.stringify(response)}`)
166
+ }
167
+
168
+ return response
169
+ }
170
+
171
+ async updateDNSRecord (id, dnsRecord) {
172
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/dns_records/${id}`
173
+
174
+ const { statusCode, body } = await request(url, {
175
+ method: 'PATCH',
176
+ headers: {
177
+ ...this.authorizationHeaders,
178
+ 'Content-Type': 'application/json'
179
+ },
180
+ body: JSON.stringify(dnsRecord)
181
+ })
182
+
183
+ const response = await body.json()
184
+
185
+ if (statusCode !== 200) {
186
+ throw new Error(`Could not update DNS record: ${statusCode}, error: ${JSON.stringify(response)}`)
187
+ }
188
+
189
+ return response
190
+ }
191
+
192
+ async createFirewallRule (firewallRule) {
193
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/firewall/rules`
194
+
195
+ const { statusCode, body } = await request(url, {
196
+ method: 'POST',
197
+ headers: {
198
+ ...this.authorizationHeaders,
199
+ 'Content-Type': 'application/json'
200
+ },
201
+ body: JSON.stringify([firewallRule])
202
+ })
203
+
204
+ const response = await body.json()
205
+
206
+ if (statusCode !== 200) {
207
+ throw new Error(`Could not create a firewall rule: ${statusCode}, error: ${JSON.stringify(response)}`)
208
+ }
209
+
210
+ return response
211
+ }
212
+
213
+ async createFirewallRules (firewallRules) {
214
+ const results = await Promise.allSettled(firewallRules.map(firewallRule => this.createFirewallRule(firewallRule)))
215
+
216
+ for (let i = 0; i < results.length; i++) {
217
+ const result = results[i]
218
+ const firewallRule = firewallRules[i]
219
+
220
+ if (result.status === 'rejected') {
221
+ console.log(`Could not create firewallRule route ${JSON.stringify(firewallRule)}: ${result.reason}\n`)
222
+ }
223
+ }
224
+ }
225
+
226
+ async setPolish (value) {
227
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/polish`
228
+
229
+ const { statusCode, body } = await request(url, {
230
+ method: 'PATCH',
231
+ headers: {
232
+ ...this.authorizationHeaders,
233
+ 'Content-Type': 'application/json'
234
+ },
235
+ body: JSON.stringify({ value })
236
+ })
237
+
238
+ const response = await body.json()
239
+
240
+ if (statusCode !== 200) {
241
+ throw new Error(`Could not set polish: ${statusCode}, error: ${JSON.stringify(response)}`)
242
+ }
243
+
244
+ return response
245
+ }
246
+
247
+ async setMinify (value) {
248
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/minify`
249
+
250
+ const { statusCode, body } = await request(url, {
251
+ method: 'PATCH',
252
+ headers: {
253
+ ...this.authorizationHeaders,
254
+ 'Content-Type': 'application/json'
255
+ },
256
+ body: JSON.stringify({ value })
257
+ })
258
+
259
+ const response = await body.json()
260
+
261
+ if (statusCode !== 200) {
262
+ throw new Error(`Could not set minify: ${statusCode}, error: ${JSON.stringify(response)}`)
263
+ }
264
+
265
+ return response
266
+ }
267
+
268
+ async setHTTP2Prioritization (value) {
269
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/h2_prioritization`
270
+
271
+ const { statusCode, body } = await request(url, {
272
+ method: 'PATCH',
273
+ headers: {
274
+ ...this.authorizationHeaders,
275
+ 'Content-Type': 'application/json'
276
+ },
277
+ body: JSON.stringify({ value })
278
+ })
279
+
280
+ const response = await body.json()
281
+
282
+ if (statusCode !== 200) {
283
+ throw new Error(`Could not set HTTP2 prioritization: ${statusCode}, error: ${JSON.stringify(response)}`)
284
+ }
285
+
286
+ return response
287
+ }
288
+
289
+ async setPrefetchURLs (value) {
290
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/prefetch_preload`
291
+
292
+ const { statusCode, body } = await request(url, {
293
+ method: 'PATCH',
294
+ headers: {
295
+ ...this.authorizationHeaders,
296
+ 'Content-Type': 'application/json'
297
+ },
298
+ body: JSON.stringify({ value })
299
+ })
300
+
301
+ const response = await body.json()
302
+
303
+ if (statusCode !== 200) {
304
+ throw new Error(`Could not set prefetch URLs: ${statusCode}, error: ${JSON.stringify(response)}`)
305
+ }
306
+
307
+ return response
308
+ }
309
+
310
+ async setHttp2 (value) {
311
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/http2`
312
+
313
+ const { statusCode, body } = await request(url, {
314
+ method: 'PATCH',
315
+ headers: {
316
+ ...this.authorizationHeaders,
317
+ 'Content-Type': 'application/json'
318
+ },
319
+ body: JSON.stringify({ value })
320
+ })
321
+
322
+ const response = await body.json()
323
+
324
+ if (statusCode !== 200) {
325
+ throw new Error(`Could not set HTTP2: ${statusCode}, error: ${JSON.stringify(response)}`)
326
+ }
327
+
328
+ return response
329
+ }
330
+
331
+ async setHttp3 (value) {
332
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/http3`
333
+
334
+ const { statusCode, body } = await request(url, {
335
+ method: 'PATCH',
336
+ headers: {
337
+ ...this.authorizationHeaders,
338
+ 'Content-Type': 'application/json'
339
+ },
340
+ body: JSON.stringify({ value })
341
+ })
342
+
343
+ const response = await body.json()
344
+
345
+ if (statusCode !== 200) {
346
+ throw new Error(`Could not set HTTP3: ${statusCode}, error: ${JSON.stringify(response)}`)
347
+ }
348
+
349
+ return response
350
+ }
351
+
352
+ async set0RTT (value) {
353
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/0rtt`
354
+
355
+ const { statusCode, body } = await request(url, {
356
+ method: 'PATCH',
357
+ headers: {
358
+ ...this.authorizationHeaders,
359
+ 'Content-Type': 'application/json'
360
+ },
361
+ body: JSON.stringify({ value })
362
+ })
363
+
364
+ const response = await body.json()
365
+
366
+ if (statusCode !== 200) {
367
+ throw new Error(`Could not set 0-RTT: ${statusCode}, error: ${JSON.stringify(response)}`)
368
+ }
369
+
370
+ return response
371
+ }
372
+
373
+ async setArgoSmartRouting (value) {
374
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/argo/smart_routing`
375
+
376
+ const { statusCode, body } = await request(url, {
377
+ method: 'PATCH',
378
+ headers: {
379
+ ...this.authorizationHeaders,
380
+ 'Content-Type': 'application/json'
381
+ },
382
+ body: JSON.stringify({ value })
383
+ })
384
+
385
+ const response = await body.json()
386
+
387
+ if (statusCode !== 200) {
388
+ throw new Error(`Could not set Argo Smart Routing: ${statusCode}, error: ${JSON.stringify(response)}`)
389
+ }
390
+
391
+ return response
392
+ }
393
+
394
+ async getPageRules () {
395
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/pagerules`
396
+
397
+ const { statusCode, body } = await request(url, {
398
+ method: 'GET',
399
+ headers: {
400
+ ...this.authorizationHeaders,
401
+ 'Content-Type': 'application/json'
402
+ }
403
+ })
404
+
405
+ const response = await body.json()
406
+
407
+ if (statusCode !== 200) {
408
+ throw new Error(`Could not get page rules: ${statusCode}, error: ${JSON.stringify(response)}`)
409
+ }
410
+
411
+ return response
412
+ }
413
+
414
+ async updatePageRule (pageRuleId, pageRule) {
415
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/pagerules/${pageRuleId}`
416
+
417
+ const { statusCode, body } = await request(url, {
418
+ method: 'PUT',
419
+ headers: {
420
+ ...this.authorizationHeaders,
421
+ 'Content-Type': 'application/json'
422
+ },
423
+ body: JSON.stringify(pageRule)
424
+ })
425
+
426
+ const response = await body.json()
427
+
428
+ if (statusCode !== 200) {
429
+ throw new Error(`Could not update page rule: ${statusCode}, error: ${JSON.stringify(response)}`)
430
+ }
431
+
432
+ return response
433
+ }
434
+
435
+ async createPageRule (pageRule) {
436
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/pagerules`
437
+
438
+ const { statusCode, body } = await request(url, {
439
+ method: 'POST',
440
+ headers: {
441
+ ...this.authorizationHeaders,
442
+ 'Content-Type': 'application/json'
443
+ },
444
+ body: JSON.stringify(pageRule)
445
+ })
446
+
447
+ const response = await body.json()
448
+
449
+ if (statusCode !== 200) {
450
+ throw new Error(`Could not create page rule: ${statusCode}, error: ${JSON.stringify(response)}`)
451
+ }
452
+
453
+ return response
454
+ }
455
+
456
+ async rewritePageRules (pageRules) {
457
+ const currentPageRules = await this.getPageRules()
458
+
459
+ for (const pageRule of pageRules) {
460
+ const currentPageRule = currentPageRules.result.find(currentPageRule => {
461
+ for (const currentPageRuleTarget of currentPageRule.targets) {
462
+ const pageRuleTarget = pageRule.targets.find(pageRuleTarget => {
463
+ return currentPageRuleTarget.target === pageRuleTarget.target &&
464
+ currentPageRuleTarget.constraint?.operator === pageRuleTarget.constraint?.operator &&
465
+ currentPageRuleTarget.constraint?.value === pageRuleTarget.constraint?.value
466
+ })
467
+ if (pageRuleTarget === undefined) return false
468
+ }
469
+ return true
470
+ })
471
+
472
+ try {
473
+ if (currentPageRule) {
474
+ await this.updatePageRule(currentPageRule.id, pageRule)
475
+ } else {
476
+ await this.createPageRule(pageRule)
477
+ }
478
+ } catch (error) {
479
+ console.log(`Could not update or create page rule: ${error.message}\n`)
480
+ }
481
+ }
482
+ }
483
+
484
+ async getAvailablePageRules () {
485
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/pagerules/settings`
486
+
487
+ const { statusCode, body } = await request(url, {
488
+ method: 'GET',
489
+ headers: {
490
+ ...this.authorizationHeaders,
491
+ 'Content-Type': 'application/json'
492
+ }
493
+ })
494
+
495
+ const response = await body.json()
496
+
497
+ if (statusCode !== 200) {
498
+ throw new Error(`Could not get available page rules: ${statusCode}, error: ${JSON.stringify(response)}`)
499
+ }
500
+
501
+ return response
502
+ }
503
+
504
+ async createWorkerRoute (workerRoute) {
505
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/workers/routes`
506
+
507
+ const { statusCode, body } = await request(url, {
508
+ method: 'POST',
509
+ headers: {
510
+ ...this.authorizationHeaders,
511
+ 'Content-Type': 'application/json'
512
+ },
513
+ body: JSON.stringify(workerRoute)
514
+ })
515
+
516
+ const response = await body.json()
517
+
518
+ if (statusCode !== 200) {
519
+ throw new Error(`Could not create worker routes: ${statusCode}, error: ${JSON.stringify(response)}`)
520
+ }
521
+
522
+ return response
523
+ }
524
+
525
+ async createWorkerRoutes (workerRoutes) {
526
+ const results = await Promise.allSettled(workerRoutes.map(workerRoute => this.createWorkerRoute(workerRoute)))
527
+
528
+ for (let i = 0; i < results.length; i++) {
529
+ const result = results[i]
530
+ const workerRoute = workerRoutes[i]
531
+
532
+ if (result.status === 'rejected') {
533
+ console.log(`Could not create worker route ${JSON.stringify(workerRoute)}: ${result.reason}\n`)
534
+ }
535
+ }
536
+ }
537
+
538
+ async getWorkerRoutes () {
539
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/workers/routes`
540
+
541
+ const { statusCode, body } = await request(url, {
542
+ method: 'GET',
543
+ headers: {
544
+ ...this.authorizationHeaders,
545
+ 'Content-Type': 'application/json'
546
+ }
547
+ })
548
+
549
+ const response = await body.json()
550
+
551
+ if (statusCode !== 200) {
552
+ throw new Error(`Could not get worker routes: ${statusCode}, error: ${JSON.stringify(response)}`)
553
+ }
554
+
555
+ return response
556
+ }
557
+
558
+ async deleteWorkerRoute (routeId) {
559
+ const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/workers/routes/${routeId}`
560
+
561
+ const { statusCode, body } = await request(url, {
562
+ method: 'DELETE',
563
+ headers: {
564
+ ...this.authorizationHeaders,
565
+ 'Content-Type': 'application/json'
566
+ }
567
+ })
568
+
569
+ const response = await body.json()
570
+
571
+ if (statusCode !== 200) {
572
+ throw new Error(`Could not delete worker route: ${statusCode}, error: ${JSON.stringify(response)}`)
573
+ }
574
+
575
+ return response
576
+ }
577
+
578
+ async deleteWorkerRoutes (routeIds) {
579
+ const results = await Promise.allSettled(routeIds.map(routeId => this.deleteWorkerRoute(routeId)))
580
+
581
+ for (let i = 0; i < results.length; i++) {
582
+ const result = results[i]
583
+ const routeId = routeIds[i]
584
+
585
+ if (result.status === 'rejected') {
586
+ console.log(`Could not delete worker route ${routeId}: ${result.reason}\n`)
587
+ }
588
+ }
589
+ }
590
+
591
+ async rewriteWorkerRoutes (workerRoutes) {
592
+ const currentWorkerRoutes = await this.getWorkerRoutes()
593
+ const currentWorkerRoutesIds = currentWorkerRoutes.result.map(route => route.id)
594
+
595
+ if (currentWorkerRoutesIds.length > 0) {
596
+ await this.deleteWorkerRoutes(currentWorkerRoutesIds)
597
+ }
598
+
599
+ await this.createWorkerRoutes(workerRoutes)
600
+ }
601
+ }
602
+
603
+ module.exports = CloudFlare
package/index.js ADDED
@@ -0,0 +1,73 @@
1
+ 'use strict'
2
+
3
+ const template = require('./template')
4
+ const CloudFlare = require('./cloudflare')
5
+
6
+ const cloudflareSettingsHandlers = {
7
+ ssl: CloudFlare.prototype.setSSL,
8
+ ipV6: CloudFlare.prototype.setIPv6,
9
+ emailObfuscation: CloudFlare.prototype.setEmailObfuscation,
10
+ brotli: CloudFlare.prototype.setBrotli,
11
+ dnsRecords: CloudFlare.prototype.rewriteDNSRecords,
12
+ firewallRules: CloudFlare.prototype.createFirewallRules,
13
+ polish: CloudFlare.prototype.setPolish,
14
+ minify: CloudFlare.prototype.setMinify,
15
+ http2Prioritization: CloudFlare.prototype.setHTTP2Prioritization,
16
+ prefetchURLs: CloudFlare.prototype.setPrefetchURLs,
17
+ http2: CloudFlare.prototype.setHttp2,
18
+ http3: CloudFlare.prototype.setHttp3,
19
+ '0-RTT': CloudFlare.prototype.set0RTT,
20
+ argoSmartRouting: CloudFlare.prototype.setArgoSmartRouting,
21
+ workers: CloudFlare.prototype.rewriteWorkerRoutes,
22
+ pageRules: CloudFlare.prototype.rewritePageRules
23
+ }
24
+
25
+ function substituteDomainName (settings, domainName) {
26
+ return JSON.parse(JSON.stringify(settings).replaceAll('$DOMAIN', domainName))
27
+ }
28
+
29
+ async function applyCloudflareSettings (config) {
30
+ if (config.domains === undefined) {
31
+ throw new Error('No domains defined in config')
32
+ }
33
+
34
+ const accountEmail = process.env.CLOUDFLARE_EMAIL
35
+ const accountKey = process.env.CLOUDFLARE_API_KEY
36
+
37
+ if (config.enabled === false) {
38
+ console.log('Config is disabled and would not be applied:', config.domains)
39
+ return
40
+ }
41
+
42
+ const { domains: sites, settings } = config
43
+
44
+ for (const site of sites) {
45
+ const zoneId = site.zoneId
46
+ if (zoneId === undefined) {
47
+ throw new Error('Cloudflare zone ID is not defined')
48
+ }
49
+
50
+ const options = site.token === undefined
51
+ ? { email: accountEmail, apiKey: accountKey }
52
+ : { token: site.token }
53
+
54
+ const cloudFlare = new CloudFlare(zoneId, options)
55
+ const domainSettings = substituteDomainName(settings, site.domain)
56
+
57
+ for (const [key, value] of Object.entries(domainSettings)) {
58
+ try {
59
+ const settingHandler = cloudflareSettingsHandlers[key]
60
+
61
+ if (settingHandler === undefined) {
62
+ throw new Error(`Unsupported Cloudflare setting: ${key}, for domain: ${site.domain}`)
63
+ }
64
+
65
+ await settingHandler.call(cloudFlare, value)
66
+ } catch (error) {
67
+ console.error(`Failed to set Cloudflare setting ${key} for domain ${site.domain}: ${error.message}\n`)
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ module.exports = { applyCloudflareSettings, template }
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@nodeart/cloudflare-provisioning",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "lint": "standard",
8
+ "prepare": "husky install"
9
+ },
10
+ "author": "",
11
+ "license": "ISC",
12
+ "devDependencies": {
13
+ "husky": "^8.0.1",
14
+ "standard": "^17.0.0"
15
+ },
16
+ "dependencies": {
17
+ "undici": "^5.6.1"
18
+ }
19
+ }
package/template.js ADDED
@@ -0,0 +1,128 @@
1
+ 'use strict'
2
+
3
+ module.exports = {
4
+ ssl: 'full',
5
+ firewallRules: {
6
+ blockSearchForMirrors: [
7
+ {
8
+ description: 'block bots',
9
+ action: 'block',
10
+ filter: {
11
+ enabled: true,
12
+ expression: '(cf.client.bot and not http.request.uri.path contains ".well-known")'
13
+ }
14
+ }
15
+ ],
16
+ bypassCMSApi: [
17
+ {
18
+ description: 'bypass cms api with proxy',
19
+ action: 'bypass',
20
+ products: ['uaBlock', 'bic', 'securityLevel'],
21
+ filter: {
22
+ enabled: true,
23
+ expression: '(http.request.uri.path contains "/api/cms/pages" and http.user_agent eq "sitemap-generator-ss") or (http.request.uri.path eq "/api/info/locales" and http.user_agent eq "sitemap-generator-ss")'
24
+ }
25
+ }
26
+ ],
27
+ allowHotlinkFromKingtraf: [
28
+ {
29
+ description: 'allow hotlink from kingtraf',
30
+ action: 'bypass',
31
+ products: ['hot'],
32
+ filter: {
33
+ enabled: true,
34
+ expression: '(http.referer contains "kingtraf.com")'
35
+ }
36
+ }
37
+ ]
38
+ },
39
+ speedOptimization: {
40
+ polish: 'lossy',
41
+ minify: { css: 'off', html: 'off', js: 'off' },
42
+ brotli: 'off',
43
+ http2Prioritization: 'on',
44
+ prefetchURLs: 'on'
45
+ },
46
+ workers: {
47
+ sitemapCurasao: {
48
+ pattern: '*$DOMAIN/sitemap.xml*',
49
+ script: 'sitemap-curasao'
50
+ },
51
+ sitemapMalta: {
52
+ pattern: '*$DOMAIN/sitemap.xml*',
53
+ script: 'sitemap-malta'
54
+ },
55
+ sitemapAustralia: {
56
+ pattern: '*$DOMAIN/sitemap.xml*',
57
+ script: 'sitemap-xml-au'
58
+ },
59
+ robotsCurasao: {
60
+ pattern: '*$DOMAIN/robots.txt*',
61
+ script: 'kingbillycasinocom-robotstxt'
62
+ },
63
+ robotsMalta: {
64
+ pattern: '*$DOMAIN/robots.txt*',
65
+ script: 'kingbillycom-robotstxt'
66
+ },
67
+ robotsAustralia: {
68
+ pattern: '*$DOMAIN/robots.txt*',
69
+ script: 'robots_block_seo'
70
+ },
71
+ disableApi: {
72
+ pattern: '*$DOMAIN/api/*',
73
+ script: null
74
+ },
75
+ rootDomainCookies: {
76
+ pattern: '*ia.$DOMAIN/C.ashx*',
77
+ script: 'root-domain-cookies'
78
+ },
79
+ lpGeoRedirect: {
80
+ pattern: 'lp.$DOMAIN/*',
81
+ script: 'lp-geo-redirect'
82
+ },
83
+ geoRedirect: {
84
+ pattern: '*$DOMAIN/*',
85
+ script: 'geo-redirect'
86
+ }
87
+ },
88
+ pageRules: {
89
+ ssApiRequirements: {
90
+ targets: [{ target: 'url', constraint: { operator: 'matches', value: '*$DOMAIN/api/*' } }],
91
+ actions: [{ id: 'disable_security' }, { id: 'security_level', value: 'essentially_off' }, { id: 'browser_check', value: 'off' }],
92
+ status: 'active'
93
+ },
94
+ lpCache: {
95
+ targets: [{ target: 'url', constraint: { operator: 'matches', value: 'lp.$DOMAIN/*' } }],
96
+ actions: [
97
+ { id: 'ssl', value: 'full' },
98
+ { id: 'cache_level', value: 'cache_everything' },
99
+ { id: 'edge_cache_ttl', value: 172800 }
100
+ ],
101
+ status: 'active'
102
+ },
103
+ dataExportCache: {
104
+ targets: [{ target: 'url', constraint: { operator: 'matches', value: 'https://www.$DOMAIN/export/*' } }],
105
+ actions: [{ id: 'cache_level', value: 'bypass' }],
106
+ status: 'active'
107
+ },
108
+ rootForward: {
109
+ targets: [{ target: 'url', constraint: { operator: 'matches', value: 'https://$DOMAIN/*' } }],
110
+ actions: [{ id: 'forwarding_url', value: { status_code: 301, url: 'https://www.$DOMAIN/$1' } }],
111
+ status: 'active'
112
+ },
113
+ ia: {
114
+ targets: [{ target: 'url', constraint: { operator: 'matches', value: '*ia.$DOMAIN/*' } }],
115
+ actions: [{ id: 'disable_security' }, { id: 'cache_level', value: 'bypass' }],
116
+ status: 'active'
117
+ }
118
+ },
119
+ network: {
120
+ http2: 'on',
121
+ http3: 'on',
122
+ '0-RTT': 'on',
123
+ ipV6: 'off'
124
+ },
125
+ traffic: {
126
+ argoSmartRouting: 'on'
127
+ }
128
+ }