zgrzyt 2.2.1 → 2.2.3

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.
package/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import rc from 'rc';
2
2
  import prepareConfig from './lib/config.js';
3
- import { zgrzyt } from './lib/zgrzyt.js';
4
3
  import { report } from './lib/report.js';
5
4
  import { onExit } from './lib/state.js';
5
+ import { zgrzyt } from './lib/zgrzyt.js';
6
6
 
7
7
  const conf = rc('zgrzyt');
8
8
  const apis = prepareConfig(conf);
package/lib/check.js CHANGED
@@ -1,4 +1,3 @@
1
- import { readFileSync } from 'node:fs';
2
1
  import http from 'node:http';
3
2
  import https from 'node:https';
4
3
  import makeDebug from 'debug';
@@ -8,25 +7,28 @@ const debug = makeDebug('zgrzyt:check');
8
7
  import { resolve } from './dns.js';
9
8
  import { updateHealth } from './state.js';
10
9
 
10
+ import packageJson from '../package.json' with { type: 'json' };
11
11
  const {
12
12
  name,
13
13
  version,
14
14
  homepage = 'https://github.com/pirxpilot/zgrzyt'
15
- } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url)));
15
+ } = packageJson;
16
16
 
17
17
  const USER_AGENT = `${name}/${version} (${homepage})`;
18
18
 
19
19
  /* global URL */
20
20
 
21
- export {
22
- checkServices
23
- };
21
+ export { checkServices };
24
22
 
25
23
  async function checkService(server, api) {
26
24
  const { ipv4 = true, ipv6 = false } = api;
27
25
  const addresses = await resolve(server, { ipv4, ipv6 });
28
26
  if (debug.enabled) {
29
- debug('Resolved %s to %s', server, addresses.map(a => a.address).join(', '));
27
+ debug(
28
+ 'Resolved %s to %s',
29
+ server,
30
+ addresses.map(a => a.address).join(', ')
31
+ );
30
32
  }
31
33
  const oks = await Promise.all(addresses.map(a => checkApi(api, a)));
32
34
  // collate results
@@ -41,13 +43,7 @@ async function checkService(server, api) {
41
43
  }
42
44
 
43
45
  async function checkApi(api, { address, family }) {
44
-
45
- const {
46
- url,
47
- method = 'HEAD',
48
- timeout = 5000,
49
- headers = {}
50
- } = api;
46
+ const { url, method = 'HEAD', timeout = 5000, headers = {} } = api;
51
47
 
52
48
  debug('Checking %s on %s with timeout %dms', url, address, timeout);
53
49
 
@@ -67,26 +63,28 @@ async function checkApi(api, { address, family }) {
67
63
  return result;
68
64
 
69
65
  function makeRequest() {
70
- return new Promise(resolve => request(url, {
71
- method,
72
- family,
73
- lookup,
74
- timeout,
75
- headers: {
76
- 'User-Agent': USER_AGENT,
77
- ...headers
78
- }
79
- })
80
- .on('timeout', function () {
81
- debug('Timeout for %s on %s', url, address);
82
- this.destroy(new Error('Request timeout.'));
83
- })
84
- .on('response', res => resolve(isOk(res)))
85
- .on('error', e => {
86
- debug('request error:', e);
87
- resolve(false);
66
+ return new Promise(resolve =>
67
+ request(url, {
68
+ method,
69
+ family,
70
+ lookup,
71
+ timeout,
72
+ headers: {
73
+ 'User-Agent': USER_AGENT,
74
+ ...headers
75
+ }
88
76
  })
89
- .end());
77
+ .on('timeout', function () {
78
+ debug('Timeout for %s on %s', url, address);
79
+ this.destroy(new Error('Request timeout.'));
80
+ })
81
+ .on('response', res => resolve(isOk(res)))
82
+ .on('error', e => {
83
+ debug('request error:', e);
84
+ resolve(false);
85
+ })
86
+ .end()
87
+ );
90
88
 
91
89
  function isOk({ statusCode }) {
92
90
  const ok = statusCode >= 200 && statusCode < 300;
package/lib/cloudflare.js CHANGED
@@ -4,8 +4,6 @@ const debug = makeDebug('zgrzyt:cloudflare');
4
4
 
5
5
  export default client;
6
6
 
7
- /* global AbortController, fetch, URLSearchParams */
8
-
9
7
  class CloudflareError extends Error {
10
8
  constructor(errors) {
11
9
  super(`Cloudflare API error: ${errors[0].message}`);
@@ -32,8 +30,6 @@ function makeFetch({ token, timeout, retry }) {
32
30
  }
33
31
 
34
32
  async function doFetch(method, command, { searchParams, json }) {
35
- const controller = new AbortController();
36
- const id = setTimeout(() => controller.abort(), timeout);
37
33
  const url = new URL(command, 'https://api.cloudflare.com/client/v4/');
38
34
  if (searchParams) {
39
35
  url.search = new URLSearchParams(searchParams);
@@ -41,14 +37,13 @@ function makeFetch({ token, timeout, retry }) {
41
37
  const options = {
42
38
  method,
43
39
  headers: { authorization },
44
- signal: controller.signal
40
+ signal: AbortSignal.timeout(timeout)
45
41
  };
46
42
  if (json) {
47
43
  options.headers['Content-Type'] = 'application/json';
48
44
  options.body = JSON.stringify(json);
49
45
  }
50
46
  const res = await fetch(url, options);
51
- clearTimeout(id);
52
47
  return res.json();
53
48
  }
54
49
  }
@@ -67,9 +62,8 @@ function client({ token, timeout = 4000, retry = 2 }) {
67
62
  const record = await getRecord(zone.id, domain);
68
63
  if (record.type === 'CNAME') {
69
64
  return updateRecord(zone.id, record.id, record.proxied, domain, good);
70
- } else {
71
- console.error('Cannot only update CNAME records');
72
65
  }
66
+ console.error('Cannot only update CNAME records');
73
67
  }
74
68
 
75
69
  async function listRecords(zoneName, domain) {
@@ -100,12 +94,7 @@ function client({ token, timeout = 4000, retry = 2 }) {
100
94
 
101
95
  async function getPage(page) {
102
96
  debug('Getting page %d', page);
103
- const {
104
- success,
105
- errors,
106
- result,
107
- result_info: { total_count }
108
- } = await cf.get('zones', {
97
+ const { success, errors, result, result_info } = await cf.get('zones', {
109
98
  searchParams: {
110
99
  status: 'active',
111
100
  page,
@@ -118,23 +107,26 @@ function client({ token, timeout = 4000, retry = 2 }) {
118
107
  }
119
108
 
120
109
  zones.push(...result);
121
- return zones.length < total_count;
110
+ return zones.length < result_info.total_count;
122
111
  }
123
112
 
124
113
  debug('Listing zones...');
125
- for (let page = 1; await getPage(page); page++) { }
114
+ for (let page = 1; await getPage(page); page++) {}
126
115
  debug('Listing zones done.');
127
116
 
128
117
  return zones;
129
118
  }
130
119
 
131
120
  async function getRecord(zoneId, domain) {
132
- const { success, result, errors } = await cf.get(`zones/${zoneId}/dns_records`, {
133
- searchParams: {
134
- name: domain,
135
- type: 'CNAME'
121
+ const { success, result, errors } = await cf.get(
122
+ `zones/${zoneId}/dns_records`,
123
+ {
124
+ searchParams: {
125
+ name: domain,
126
+ type: 'CNAME'
127
+ }
136
128
  }
137
- });
129
+ );
138
130
 
139
131
  if (!success) {
140
132
  throw new CloudflareError(errors);
@@ -148,14 +140,17 @@ function client({ token, timeout = 4000, retry = 2 }) {
148
140
  }
149
141
 
150
142
  async function updateRecord(zoneId, recordId, proxied, domain, good) {
151
- const { success, errors, result } = await cf.put(`zones/${zoneId}/dns_records/${recordId}`, {
152
- json: {
153
- name: domain,
154
- proxied,
155
- content: good.server,
156
- type: 'CNAME'
143
+ const { success, errors, result } = await cf.put(
144
+ `zones/${zoneId}/dns_records/${recordId}`,
145
+ {
146
+ json: {
147
+ name: domain,
148
+ proxied,
149
+ content: good.server,
150
+ type: 'CNAME'
151
+ }
157
152
  }
158
- });
153
+ );
159
154
 
160
155
  debug('Update record', success, errors, result);
161
156
 
package/lib/config.js CHANGED
@@ -1,4 +1,4 @@
1
- import { parseDomain, fromUrl } from 'parse-domain';
1
+ import { fromUrl, parseDomain } from 'parse-domain';
2
2
  import makeClient from './cloudflare.js';
3
3
 
4
4
  export default prepareConfig;
@@ -15,21 +15,17 @@ function getDomainAndZone({ url, domain: apiDomain }) {
15
15
  }
16
16
 
17
17
  function prepareConfig(config) {
18
- const {
19
- cloudflare,
20
- api = {},
21
- cluster = {}
22
- } = config;
18
+ const { cloudflare, api = {}, cluster = {} } = config;
23
19
 
24
20
  if (!cloudflare?.token) {
25
21
  console.error('Cloudflare API token not configured');
26
22
  return;
27
23
  }
28
24
  if (typeof cloudflare.timeout === 'string') {
29
- cloudflare.timeout = parseInt(cloudflare.timeout);
25
+ cloudflare.timeout = Number.parseInt(cloudflare.timeout);
30
26
  }
31
27
  if (typeof cloudflare.retry === 'string') {
32
- cloudflare.retry = parseInt(cloudflare.retry);
28
+ cloudflare.retry = Number.parseInt(cloudflare.retry);
33
29
  }
34
30
 
35
31
  // collect all APIs
@@ -49,10 +45,10 @@ function prepareConfig(config) {
49
45
  }
50
46
 
51
47
  const { domain, zone } = getDomainAndZone(api);
52
- const timeout = parseInt(api.timeout || config.timeout, 10) || 250;
53
- const retry = parseInt(api.retry || config.retry, 10) || 2;
48
+ const timeout = Number.parseInt(api.timeout || config.timeout, 10) || 250;
49
+ const retry = Number.parseInt(api.retry || config.retry, 10) || 2;
54
50
  const force = 'force' in api ? api.force : config.force;
55
- const repair = parseInt(api.repair || config.repair, 10) || 5;
51
+ const repair = Number.parseInt(api.repair || config.repair, 10) || 5;
56
52
  const ipv6 = Boolean(api.ipv6 ?? config.ipv6);
57
53
  const ipv4 = Boolean(api.ipv4 ?? config.ipv4 ?? true);
58
54
 
@@ -88,6 +84,5 @@ function prepareConfig(config) {
88
84
  force,
89
85
  repair
90
86
  };
91
-
92
87
  }
93
88
  }
package/lib/dns.js CHANGED
@@ -39,7 +39,10 @@ async function doResolve(domain) {
39
39
  async function resolveWithFamily(rrtype) {
40
40
  try {
41
41
  const addresses = await resolver.resolve(domain, rrtype);
42
- return addresses.map(address => ({ address, family: RRTYPE_TO_FAMILY[rrtype] }));
42
+ return addresses.map(address => ({
43
+ address,
44
+ family: RRTYPE_TO_FAMILY[rrtype]
45
+ }));
43
46
  } catch (error) {
44
47
  debug('Failed to resolve %s with type %s: %s', domain, rrtype, error);
45
48
  return [];
package/lib/report.js CHANGED
@@ -13,10 +13,21 @@ function collect(context, { url, domain, record, good, switched }) {
13
13
  if (!good) {
14
14
  context.missing.push(url);
15
15
  } else if (switched) {
16
- const line = sprintf('%-25s %-25s => %-25s [%s]', domain, record.content, good.server, good.address);
16
+ const line = sprintf(
17
+ '%-25s %-25s => %-25s [%s]',
18
+ domain,
19
+ record.content,
20
+ good.server,
21
+ good.address
22
+ );
17
23
  context.switched.push(line);
18
24
  } else {
19
- const line = sprintf('%-25s %-25s [%s]', record.name, good.server, good.address);
25
+ const line = sprintf(
26
+ '%-25s %-25s [%s]',
27
+ record.name,
28
+ good.server,
29
+ good.address
30
+ );
20
31
  context.noops.push(line);
21
32
  }
22
33
  return context;
@@ -28,11 +39,7 @@ function formatError(err) {
28
39
  }
29
40
 
30
41
  function reportAll(collected, errors) {
31
- const {
32
- missing,
33
- noops,
34
- switched
35
- } = collected;
42
+ const { missing, noops, switched } = collected;
36
43
 
37
44
  let exitCode = 0;
38
45
  const lines = [];
@@ -49,7 +56,7 @@ function reportAll(collected, errors) {
49
56
  lines.push('No changes:\n', ...noops, '\n');
50
57
  }
51
58
  if (errors.length) {
52
- lines.push('Errors:\n', ...errors, `\n`);
59
+ lines.push('Errors:\n', ...errors, '\n');
53
60
  exitCode = -1;
54
61
  }
55
62
 
package/lib/state.js CHANGED
@@ -1,14 +1,8 @@
1
- import { readFile, writeFile, } from 'node:fs/promises';
1
+ import { readFile, writeFile } from 'node:fs/promises';
2
2
 
3
- export {
4
- updateHealth,
5
- onExit
6
- };
7
-
8
- const {
9
- ZGRZYT_STATE = '/var/lib/zgrzyt/state.json'
10
- } = process.env;
3
+ export { updateHealth, onExit };
11
4
 
5
+ const { ZGRZYT_STATE = '/var/lib/zgrzyt/state.json' } = process.env;
12
6
 
13
7
  const state_p = read();
14
8
  let hook;
package/lib/zgrzyt.js CHANGED
@@ -3,7 +3,10 @@ import { checkServices } from './check.js';
3
3
  export async function zgrzyt({ servers, api, client, force, repair }) {
4
4
  const { domain, zone } = api;
5
5
  const record = await client.listRecords(zone, domain);
6
- const good = await checkServices(servers, record.content, api, { force, repair });
6
+ const good = await checkServices(servers, record.content, api, {
7
+ force,
8
+ repair
9
+ });
7
10
  const result = {
8
11
  url: api.url,
9
12
  domain,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zgrzyt",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "Poor man's load balancing DNS switcher.",
5
5
  "type": "module",
6
6
  "author": {
@@ -32,7 +32,7 @@
32
32
  "sprintfjs": "^1.2.16"
33
33
  },
34
34
  "devDependencies": {
35
- "@pirxpilot/jshint": "^3.0.0"
35
+ "@biomejs/biome": "^1.9.4"
36
36
  },
37
37
  "scripts": {
38
38
  "test": "make check"