cht-conf 3.10.0 → 3.10.1

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.10.1](https://github.com/medic/cht-conf/compare/v3.10.0...v3.10.1) (2022-02-23)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **#465:** remove process.exit and extraneous require ([058e651](https://github.com/medic/cht-conf/commit/058e65182928cdefdd5bb8fb41849fb9b5164631)), closes [#465](https://github.com/medic/cht-conf/issues/465)
7
+
1
8
  # [3.10.0](https://github.com/medic/cht-conf/compare/v3.9.5...v3.10.0) (2022-02-02)
2
9
 
3
10
 
package/README.md CHANGED
@@ -91,6 +91,8 @@ If a different username is required, add the `--user` switch:
91
91
 
92
92
  cht --url=https://username:password@example.com:12345
93
93
 
94
+ **NB** - When specifying the URL with `--url`, be sure not to specify the CouchDB database name in the URL. The CHT API will find the correct database.
95
+
94
96
  ### Into an archive to be uploaded later
95
97
 
96
98
  cht --archive
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cht-conf",
3
- "version": "3.10.0",
3
+ "version": "3.10.1",
4
4
  "description": "Configure CHT deployments",
5
5
  "main": "./src/lib/main.js",
6
6
  "engines": {
@@ -62,6 +62,7 @@
62
62
  "request-promise-native": "^1.0.9",
63
63
  "semver": "^6.1.1",
64
64
  "svgo": "^1.3.2",
65
+ "terser-webpack-plugin": "^1.4.3",
65
66
  "uuid": "^8.3.2",
66
67
  "webpack": "^4.46.0",
67
68
  "xmldom": "^0.6.0"
package/src/bin/index.js CHANGED
@@ -1,20 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { error } = require('../lib/log');
4
- require('../cli/check-node-version');
3
+ const { info, error } = require('../lib/log');
4
+ const checkNodeVersion = require('../cli/check-node-version');
5
5
 
6
- const main = require('../lib/main');
6
+ try {
7
+ checkNodeVersion();
8
+ } catch (e) {
9
+ error(e.message);
10
+ process.exitCode = 1;
11
+ }
7
12
 
13
+ const main = require('../lib/main');
8
14
  (async () => {
9
- let returnCode;
10
15
  try {
11
- returnCode = await main(process.argv, process.env);
12
- }
13
- catch (e) {
14
- error(e);
15
- returnCode = 1;
16
- }
17
- finally {
18
- process.exit(returnCode);
16
+ await main(process.argv, process.env);
17
+ } catch (e) {
18
+ info(e); // log the details for debugging
19
+ error(e.message); // error the message to make it clear
20
+ process.exitCode = 1; // emit a non-zero exit code for scripting
19
21
  }
20
22
  })();
@@ -1,10 +1,12 @@
1
1
  const MIN_NODE_VERSION = 6;
2
2
  const currentNodeVersion = process.versions.node;
3
3
 
4
- if(Number.parseInt(currentNodeVersion.split('.')[0]) < MIN_NODE_VERSION) {
5
- console.log(`\x1b[31mYour NodeJS is too old.
6
- You are running node version: ${currentNodeVersion}
7
- cht-conf requires version: ${MIN_NODE_VERSION}
8
- Please upgrade node to continue.\x1b[0m`);
9
- process.exit(1);
10
- }
4
+ module.exports = () => {
5
+ const currentMajor = process.versions.node.split('.')[0];
6
+ if(Number.parseInt(currentMajor) < MIN_NODE_VERSION) {
7
+ throw new Error(`Your NodeJS is too old.
8
+ You are running node version: ${currentNodeVersion}
9
+ cht-conf requires version: ${MIN_NODE_VERSION}
10
+ Please upgrade node to continue.`);
11
+ }
12
+ };
@@ -1,20 +1,17 @@
1
1
  const fs = require('../lib/sync-fs');
2
- const { error } = require('../lib/log');
3
2
 
4
- const supported_shells = ['bash'];
3
+ const SUPPORTED_SHELLS = ['bash'];
5
4
 
6
5
  module.exports = shell => {
7
-
8
- if (supported_shells.includes(shell)){
6
+ if (SUPPORTED_SHELLS.includes(shell)){
9
7
  const completionFile = `${__dirname}/shell-completion.${shell}`;
10
8
  if (fs.exists(completionFile)){
11
9
  console.log(fs.read(completionFile));
12
- process.exit(0);
10
+ return;
13
11
  }
14
12
  } else if (shell === true){
15
- error('shell type argument not specified e.g. --shell-completion=bash');
13
+ throw new Error('shell type argument not specified e.g. --shell-completion=bash');
16
14
  } else {
17
- error(`completion not yet supported for '${shell}' shell`);
15
+ throw new Error(`completion not yet supported for '${shell}' shell`);
18
16
  }
19
- process.exit(1);
20
17
  };
@@ -1,5 +1,5 @@
1
1
  const git = require('../lib/git-exec');
2
- const { info, warn, error } = require('../lib/log');
2
+ const { info, warn } = require('../lib/log');
3
3
  const userPrompt = require('../lib/user-prompt');
4
4
  const environment = require('../lib/environment');
5
5
 
@@ -17,8 +17,7 @@ module.exports = {
17
17
  'not staged for commit.');
18
18
  warn('Changes untracked or to be committed:\n' + status);
19
19
  if (!userPrompt.keyInYN('Are you sure you want to continue?')) {
20
- error('User failed to confirm action.');
21
- process.exit(1);
20
+ throw new Error('User aborted execution.');
22
21
  }
23
22
  }
24
23
  info('Fetching git upstream...');
@@ -26,8 +25,7 @@ module.exports = {
26
25
  if (syncStatus) {
27
26
  warn(syncStatus);
28
27
  if (!userPrompt.keyInYN('Are you sure you want to continue?')) {
29
- error('User failed to confirm action.');
30
- process.exit(1);
28
+ throw new Error('User aborted execution.');
31
29
  }
32
30
  }
33
31
  }
@@ -1,3 +1,4 @@
1
+ /*eslint node/no-missing-require: "off"*/
1
2
  const compressPng = require('../lib/compress-png').execute;
2
3
  const compressSvg = require('../lib/compress-svg').execute;
3
4
 
@@ -4,7 +4,7 @@ const userPrompt = require('../../src/lib/user-prompt');
4
4
  const api = require('../lib/api');
5
5
  const environment = require('../lib/environment');
6
6
  const fs = require('../lib/sync-fs');
7
- const { info, warn, error } = require('../lib/log');
7
+ const { info, warn } = require('../lib/log');
8
8
 
9
9
  const nestPrefixedProperties = (obj, name) => {
10
10
  const nested = {};
@@ -61,7 +61,7 @@ const getUserInfo = async (user) => {
61
61
 
62
62
  const execute = async () => {
63
63
  const csvPath = `${environment.pathToProject}/users.csv`;
64
- if(!fs.exists(csvPath)) {
64
+ if (!fs.exists(csvPath)) {
65
65
  throw new Error(`User csv file not found at ${csvPath}`);
66
66
  }
67
67
 
@@ -76,11 +76,8 @@ const execute = async () => {
76
76
  if (warnings.length) {
77
77
  warnings.forEach(warning => warn(warning));
78
78
  warn('Are you sure you want to continue?');
79
- if(!userPrompt.keyInYN()) {
80
- error('User failed to confirm action.');
81
- process.exit(1);
82
- // stop execution in tests
83
- return; // eslint-disable-line no-unreachable
79
+ if (!userPrompt.keyInYN()) {
80
+ throw new Error('User aborted execution.');
84
81
  }
85
82
  }
86
83
 
@@ -7,7 +7,7 @@ const fs = require('../lib/sync-fs');
7
7
  const lineageManipulation = require('../lib/lineage-manipulation');
8
8
  const lineageConstraints = require('../lib/lineage-constraints');
9
9
  const pouch = require('../lib/db');
10
- const { warn, trace, info, error } = require('../lib/log');
10
+ const { warn, trace, info } = require('../lib/log');
11
11
 
12
12
  const HIERARCHY_ROOT = 'root';
13
13
  const BATCH_SIZE = 10000;
@@ -125,8 +125,7 @@ const prepareDocumentDirectory = ({ docDirectoryPath, force }) => {
125
125
  if(userPrompt.keyInYN()) {
126
126
  fs.deleteFilesInFolder(docDirectoryPath);
127
127
  } else {
128
- error('User failed to confirm action.');
129
- process.exit(1);
128
+ throw new Error('User aborted execution.');
130
129
  }
131
130
  }
132
131
  };
@@ -65,8 +65,7 @@ const execute = async () => {
65
65
  if (placeholderErrorsFound > 0) {
66
66
  errMsg += '\nYou can use messages-ex.properties to add placeholders missing from the reference context.';
67
67
  }
68
- log.error(errMsg);
69
- return process.exit(1);
68
+ throw new Error(errMsg);
70
69
  }
71
70
  } else {
72
71
  throw err;
@@ -77,8 +76,7 @@ const execute = async () => {
77
76
  const id = idFor(fileName);
78
77
  const languageCode = id.substring('messages-'.length);
79
78
  if (!isLanguageCodeValid(languageCode)) {
80
- log.error(`The language code '${languageCode}' is not valid. It must begin with a letter(a–z, A-Z), followed by any number of hyphens, underscores, letters, or numbers.`);
81
- return process.exit(1);
79
+ throw new Error(`The language code '${languageCode}' is not valid. It must begin with a letter(a-z, A-Z), followed by any number of hyphens, underscores, letters, or numbers.`);
82
80
  }
83
81
 
84
82
  let languageName = iso639.getName(languageCode);
@@ -8,7 +8,7 @@ const log = require('../lib/log');
8
8
  const pouch = require('../lib/db');
9
9
  const progressBar = require('../lib/progress-bar');
10
10
 
11
- const { info, trace, warn, error } = log;
11
+ const { info, trace, warn } = log;
12
12
 
13
13
  const FILE_EXTENSION = '.doc.json';
14
14
  const INITIAL_BATCH_SIZE = 100;
@@ -34,9 +34,8 @@ const execute = async () => {
34
34
  }
35
35
 
36
36
  warn(`This operation will permanently write ${totalCount} docs. Are you sure you want to continue?`);
37
- if(!userPrompt.keyInYN()) {
38
- error('User failed to confirm action.');
39
- process.exit(1);
37
+ if (!userPrompt.keyInYN()) {
38
+ throw new Error('User aborted execution.');
40
39
  }
41
40
 
42
41
  const results = { ok:[], failed:{} };
package/src/lib/api.js CHANGED
@@ -94,25 +94,24 @@ const api = {
94
94
  */
95
95
  available: async () => {
96
96
  const url = `${environment.apiUrl}/`;
97
+ log.info(`Checking that ${url} is available...`);
97
98
  try {
98
- log.info(`Checking that ${url} is available...`);
99
99
  await request.get(url);
100
- return true;
101
100
  } catch (err) {
102
101
  if (err.statusCode === 401) {
103
- log.error(`Authentication failed connecting to ${url}. `
104
- + 'Check the supplied username and password and try again.');
105
- } else if (err.statusCode === 403) {
106
- log.error(`Insufficient permissions connecting to ${url}. `
107
- + 'You need to use admin permissions to execute this command.');
108
- } else if (err.statusCode) {
109
- log.error(`Received error code ${err.statusCode} connecting to ${url}. `
110
- + 'Check the server and and try again.');
111
- } else {
112
- log.error(`Failed to get a response from ${url}. Maybe you entered the wrong URL, `
113
- + 'wrong port or the instance is not started. Please check and try again.');
102
+ throw new Error(`Authentication failed connecting to ${url}. `
103
+ + 'Check the supplied username and password and try again.');
104
+ }
105
+ if (err.statusCode === 403) {
106
+ throw new Error(`Insufficient permissions connecting to ${url}. `
107
+ + 'You need to use admin permissions to execute this command.');
108
+ }
109
+ if (err.statusCode) {
110
+ throw new Error(`Received error code ${err.statusCode} connecting to ${url}. `
111
+ + 'Check the server and and try again.');
114
112
  }
115
- return false;
113
+ throw new Error(`Failed to get a response from ${url}. Maybe you entered the wrong URL, `
114
+ + 'wrong port or the instance is not started. Please check and try again.');
116
115
  }
117
116
  },
118
117
 
package/src/lib/main.js CHANGED
@@ -12,7 +12,7 @@ const supportedActions = require('../cli/supported-actions');
12
12
  const usage = require('../cli/usage');
13
13
  const api = require('../lib/api');
14
14
 
15
- const { error, info, warn } = log;
15
+ const { info, warn } = log;
16
16
  const defaultActions = [
17
17
  'check-git',
18
18
  'compile-app-settings',
@@ -55,9 +55,9 @@ module.exports = async (argv, env) => {
55
55
  warn('The "medic-conf" cli command is deprecated. Please use "cht" instead');
56
56
  }
57
57
 
58
- if(argv.length <= 2) {
59
- usage(0);
60
- return 1;
58
+ if (argv.length <= 2) {
59
+ usage();
60
+ throw new Error('Invalid number of arguments.');
61
61
  }
62
62
 
63
63
  const cmdArgs = require('minimist')(argv.slice(2), {
@@ -69,8 +69,8 @@ module.exports = async (argv, env) => {
69
69
  // General single use actions
70
70
  //
71
71
  if (cmdArgs.help) {
72
- usage(0);
73
- return 0;
72
+ usage();
73
+ return;
74
74
  }
75
75
 
76
76
  if (cmdArgs['shell-completion']) {
@@ -79,22 +79,21 @@ module.exports = async (argv, env) => {
79
79
 
80
80
  if (cmdArgs['supported-actions']) {
81
81
  info('Supported actions:\n', supportedActions.join('\n '));
82
- return 0;
82
+ return;
83
83
  }
84
84
 
85
85
  if (cmdArgs.version) {
86
86
  info(require('../../package.json').version);
87
- return 0;
87
+ return;
88
88
  }
89
89
 
90
90
  if (cmdArgs.changelog) {
91
91
  await open('https://github.com/medic/cht-conf/releases', { url: true });
92
- return process.exit(0);
92
+ return;
93
93
  }
94
94
 
95
95
  if (cmdArgs.archive && !cmdArgs.destination) {
96
- error('--destination=<path to save files> is required with --archive.');
97
- return 1;
96
+ throw new Error('--destination=<path to save files> is required with --archive.');
98
97
  }
99
98
 
100
99
  if (cmdArgs['accept-self-signed-certs']) {
@@ -130,8 +129,7 @@ module.exports = async (argv, env) => {
130
129
 
131
130
  const unsupported = actions.filter(a => !supportedActions.includes(a));
132
131
  if(unsupported.length) {
133
- error(`Unsupported action(s): ${unsupported.join(' ')}`);
134
- return 1;
132
+ throw new Error(`Unsupported action(s): ${unsupported.join(' ')}`);
135
133
  }
136
134
 
137
135
  if (cmdArgs['skip-git-check']) {
@@ -163,8 +161,7 @@ module.exports = async (argv, env) => {
163
161
  if (actions.some(action => action.requiresInstance)) {
164
162
  apiUrl = getApiUrl(cmdArgs, env);
165
163
  if (!apiUrl) {
166
- error('Failed to obtain a url to the API');
167
- return 1;
164
+ throw new Error('Failed to obtain a url to the API');
168
165
  }
169
166
  }
170
167
 
@@ -183,8 +180,8 @@ module.exports = async (argv, env) => {
183
180
  cmdArgs['skip-translation-check']
184
181
  );
185
182
 
186
- if (apiUrl && !await api().available()) {
187
- return 1;
183
+ if (apiUrl) {
184
+ await api().available();
188
185
  }
189
186
 
190
187
  const productionUrlMatch = environment.instanceUrl && environment.instanceUrl.match(/^https:\/\/(?:[^@]*@)?(.*)\.(app|dev)\.medicmobile\.org(?:$|\/)/);
@@ -192,9 +189,8 @@ module.exports = async (argv, env) => {
192
189
  if (productionUrlMatch && !expectedOptions.includes(productionUrlMatch[1])) {
193
190
  warn(`Attempting to use project for \x1b[31m${projectName}\x1b[33m`,
194
191
  `against non-matching instance: \x1b[31m${redactBasicAuth(environment.instanceUrl)}\x1b[33m`);
195
- if(!userPrompt.keyInYN()) {
196
- error('User failed to confirm action.');
197
- return 1;
192
+ if (!userPrompt.keyInYN()) {
193
+ throw new Error('User aborted execution.');
198
194
  }
199
195
  }
200
196
 
@@ -218,8 +214,6 @@ module.exports = async (argv, env) => {
218
214
  if (actions.length > 1) {
219
215
  await info('All actions completed.');
220
216
  }
221
-
222
- return 0;
223
217
  };
224
218
 
225
219
  // Exists for generic mocking purposes