cht-conf 3.20.0 → 3.21.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [3.21.0](https://github.com/medic/cht-conf/compare/v3.20.0...v3.21.0) (2023-12-06)
2
+
3
+
4
+ ### Features
5
+
6
+ * **#575:** retry failed HTTP requests ([#583](https://github.com/medic/cht-conf/issues/583)) ([bc5b0bc](https://github.com/medic/cht-conf/commit/bc5b0bc702e43faf93c495b7fb1197b495c5f66d)), closes [#575](https://github.com/medic/cht-conf/issues/575)
7
+
1
8
  # [3.20.0](https://github.com/medic/cht-conf/compare/v3.19.0...v3.20.0) (2023-10-25)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cht-conf",
3
- "version": "3.20.0",
3
+ "version": "3.21.0",
4
4
  "description": "Configure CHT deployments",
5
5
  "main": "./src/lib/main.js",
6
6
  "engines": {
@@ -35,22 +35,23 @@
35
35
  },
36
36
  "homepage": "https://github.com/medic/cht-conf#readme",
37
37
  "dependencies": {
38
- "joi": "^17.9.2",
39
38
  "@medic/translation-checker": "^1.0.1",
40
39
  "@parcel/watcher": "^2.0.5",
41
- "@xmldom/xmldom": "^0.8.2",
40
+ "@xmldom/xmldom": "^0.8.10",
41
+ "async-retry": "^1.3.3",
42
42
  "canonical-json": "0.0.4",
43
43
  "csv-parse": "^4.16.0",
44
44
  "dom-compare": "^0.6.0",
45
45
  "eslint": "^6.8.0",
46
46
  "eslint-loader": "^3.0.4",
47
47
  "googleapis": "^84.0.0",
48
- "iso-639-1": "^2.1.9",
48
+ "iso-639-1": "^3.1.0",
49
+ "joi": "^17.11.0",
49
50
  "json-diff": "^0.5.4",
50
51
  "json-stringify-safe": "^5.0.1",
51
52
  "json2csv": "^4.5.4",
52
- "mime-types": "^2.1.32",
53
- "minimist": "^1.2.5",
53
+ "mime-types": "^2.1.35",
54
+ "minimist": "^1.2.8",
54
55
  "mkdirp": "^1.0.4",
55
56
  "open": "^7.4.2",
56
57
  "pluralize": "^8.0.0",
@@ -68,21 +69,21 @@
68
69
  "terser-webpack-plugin": "^1.4.3",
69
70
  "uuid": "^8.3.2",
70
71
  "webpack": "^4.46.0",
71
- "xpath": "0.0.32"
72
+ "xpath": "0.0.33"
72
73
  },
73
74
  "devDependencies": {
74
75
  "@commitlint/cli": "^13.2.0",
75
76
  "@commitlint/config-conventional": "^13.2.0",
76
- "@semantic-release/changelog": "^6.0.0",
77
- "@semantic-release/git": "^10.0.0",
78
- "body-parser": "^1.19.0",
79
- "chai": "^4.3.4",
77
+ "@semantic-release/changelog": "^6.0.3",
78
+ "@semantic-release/git": "^10.0.1",
79
+ "body-parser": "^1.20.2",
80
+ "chai": "^4.3.10",
80
81
  "chai-as-promised": "^7.1.1",
81
- "chai-exclude": "^2.0.3",
82
+ "chai-exclude": "^2.1.0",
82
83
  "chai-shallow-deep-equal": "^1.4.6",
83
- "chai-xml": "^0.4.0",
84
+ "chai-xml": "^0.4.1",
84
85
  "eslint-plugin-node": "^11.1.0",
85
- "express": "^4.17.1",
86
+ "express": "^4.18.2",
86
87
  "express-pouchdb": "^4.2.0",
87
88
  "fs-extra": "8.1.0",
88
89
  "husky": "^7.0.2",
@@ -91,6 +92,6 @@
91
92
  "pouchdb-adapter-memory": "^7.2.2",
92
93
  "rewire": "^5.0.0",
93
94
  "semantic-release": "^18.0.0",
94
- "sinon": "^7.3.2"
95
+ "sinon": "^8.1.1"
95
96
  }
96
97
  }
package/src/lib/api.js CHANGED
@@ -1,4 +1,5 @@
1
- const request = require('request-promise-native');
1
+ const retry = require('async-retry');
2
+ const rpn = require('request-promise-native');
2
3
 
3
4
  const archivingApi = require('./archiving-api');
4
5
  const environment = require('./environment');
@@ -7,6 +8,13 @@ const url = require('url');
7
8
 
8
9
  const cache = new Map();
9
10
 
11
+ const _request = (method) => (...args) => retry(() => rpn[method](...args), { retries: 5, randomize: false, factor: 1.5 });
12
+ const request = {
13
+ get: _request('get'),
14
+ post: _request('post'),
15
+ put: _request('put'),
16
+ };
17
+
10
18
  const logDeprecatedTransitions = (settings) => {
11
19
  const appSettings = JSON.parse(settings);
12
20
 
@@ -15,7 +23,7 @@ const logDeprecatedTransitions = (settings) => {
15
23
  }
16
24
 
17
25
  const uri = `${environment.instanceUrl}/api/v1/settings/deprecated-transitions`;
18
- return request({ uri, method: 'GET', json: true })
26
+ return request.get({ uri, json: true })
19
27
  .then(transitions => {
20
28
  (transitions || []).forEach(transition => {
21
29
  const transitionSetting = appSettings.transitions[transition.name];
@@ -34,8 +42,7 @@ const logDeprecatedTransitions = (settings) => {
34
42
  };
35
43
 
36
44
  const updateAppSettings = (settings) => {
37
- return request({
38
- method: 'PUT',
45
+ return request.put({
39
46
  url: `${environment.apiUrl}/_design/medic/_rewrite/update_settings/medic?replace=1`,
40
47
  headers: {'Content-Type': 'application/json'},
41
48
  body: settings,
@@ -45,7 +52,7 @@ const updateAppSettings = (settings) => {
45
52
  const api = {
46
53
  getAppSettings: () => {
47
54
  const url = `${environment.apiUrl}/_design/medic/_rewrite/app_settings/medic`;
48
- return request({ url, json: true })
55
+ return request.get({ url, json: true })
49
56
  .catch(err => {
50
57
  if(err.statusCode === 404) {
51
58
  throw new Error(`Failed to fetch existing app_settings from ${url}.\n` +
@@ -66,9 +73,8 @@ const api = {
66
73
  },
67
74
 
68
75
  createUser(userData) {
69
- return request({
76
+ return request.post({
70
77
  uri: `${environment.instanceUrl}/api/v1/users`,
71
- method: 'POST',
72
78
  json: true,
73
79
  body: userData,
74
80
  });
@@ -79,9 +85,8 @@ const api = {
79
85
  },
80
86
 
81
87
  uploadSms(messages) {
82
- return request({
88
+ return request.post({
83
89
  uri: `${environment.instanceUrl}/api/sms`,
84
- method: 'POST',
85
90
  json: true,
86
91
  body: { messages },
87
92
  });
@@ -116,7 +121,7 @@ const api = {
116
121
  },
117
122
 
118
123
  version() {
119
- return request({ uri: `${environment.instanceUrl}/api/deploy-info`, method: 'GET', json: true }) // endpoint added in 3.5
124
+ return request.get({ uri: `${environment.instanceUrl}/api/deploy-info`, json: true }) // endpoint added in 3.5
120
125
  .then(deploy_info => deploy_info && deploy_info.version);
121
126
  },
122
127
 
@@ -150,8 +155,7 @@ const api = {
150
155
  // (old version), so we assume form is valid but return special result
151
156
  return Promise.resolve({ok: true, formsValidateEndpointFound: false});
152
157
  }
153
- return request({
154
- method: 'POST',
158
+ return request.post({
155
159
  uri: `${environment.instanceUrl}/api/v1/forms/validate`,
156
160
  headers: { 'Content-Type': 'application/xml' },
157
161
  body: formXml,
@@ -20,7 +20,7 @@ const initialize = (
20
20
  }
21
21
 
22
22
  Object.assign(state, {
23
- apiUrl,
23
+ apiUrl: apiUrl.toString(),
24
24
  archiveDestination,
25
25
  extraArgs,
26
26
  initialized: true,
@@ -36,7 +36,16 @@ const getApiUrl = (cmdArgs, env = {}) => {
36
36
  instanceUrl = new url.URL(cmdArgs.url);
37
37
  }
38
38
 
39
- return `${instanceUrl.href}medic`;
39
+ instanceUrl.pathname = `${instanceUrl.pathname}medic`;
40
+ return instanceUrl;
41
+ };
42
+
43
+ const isLocalhost = (apiUrl) => {
44
+ if (!apiUrl) {
45
+ return false;
46
+ }
47
+ const localhosts = [/^localhost$/, /^127\.0\.0\.\d+$/];
48
+ return !!localhosts.find(localhost => localhost.test(apiUrl.hostname));
40
49
  };
41
50
 
42
51
  const parseLocalUrl = (couchUrl) => {
@@ -56,4 +65,7 @@ const parseLocalUrl = (couchUrl) => {
56
65
  return new url.URL('http://admin:pass@localhost:5988');
57
66
  };
58
67
 
59
- module.exports = getApiUrl;
68
+ module.exports = {
69
+ getApiUrl,
70
+ isLocalhost,
71
+ };
package/src/lib/main.js CHANGED
@@ -3,7 +3,7 @@ const checkForUpdates = require('../lib/check-for-updates');
3
3
  const checkChtConfDependencyVersion = require('../lib/check-cht-conf-dependency-version');
4
4
  const environment = require('./environment');
5
5
  const fs = require('../lib/sync-fs');
6
- const getApiUrl = require('../lib/get-api-url');
6
+ const { getApiUrl, isLocalhost } = require('../lib/get-api-url');
7
7
  const log = require('../lib/log');
8
8
  const userPrompt = require('../lib/user-prompt');
9
9
  const redactBasicAuth = require('redact-basic-auth');
@@ -110,10 +110,6 @@ module.exports = async (argv, env) => {
110
110
  throw new Error('--destination=<path to save files> is required with --archive.');
111
111
  }
112
112
 
113
- if (cmdArgs['accept-self-signed-certs']) {
114
- process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
115
- }
116
-
117
113
  //
118
114
  // Logging
119
115
  //
@@ -147,6 +143,10 @@ module.exports = async (argv, env) => {
147
143
  const requiresInstance = actions.some(action => action.requiresInstance);
148
144
  const apiUrl = requiresInstance && getApiUrl(cmdArgs, env);
149
145
 
146
+ if (cmdArgs['accept-self-signed-certs'] || isLocalhost(apiUrl)) {
147
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
148
+ }
149
+
150
150
  let extraArgs = cmdArgs['--'];
151
151
  if (!extraArgs.length) {
152
152
  extraArgs = undefined;