cht-conf 5.1.0 → 5.2.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 +14 -0
- package/README.md +0 -18
- package/commitlint.config.js +1 -1
- package/package.json +1 -3
- package/src/cli/usage.js +11 -3
- package/src/lib/api.js +16 -0
- package/src/lib/check-for-updates.js +23 -27
- package/src/lib/hierarchy-operations/hierarchy-data-source.js +41 -17
- package/src/lib/main.js +3 -5
- package/src/bin/cht-logs.bash +0 -62
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [5.2.1](https://github.com/medic/cht-conf/compare/v5.2.0...v5.2.1) (2025-08-27)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **#390:** notify user of new cht-conf versions ([#730](https://github.com/medic/cht-conf/issues/730)) ([9d36c21](https://github.com/medic/cht-conf/commit/9d36c215f5b6406233b856b6348fe949757ab0b8)), closes [#390](https://github.com/medic/cht-conf/issues/390)
|
|
7
|
+
|
|
8
|
+
# [5.2.0](https://github.com/medic/cht-conf/compare/v5.1.0...v5.2.0) (2025-08-07)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* refactor requests from freetexts views to other similar views ([#660](https://github.com/medic/cht-conf/issues/660)) ([292565d](https://github.com/medic/cht-conf/commit/292565de488e05e630a21d5046215fa19910a1fb))
|
|
14
|
+
|
|
1
15
|
# [5.1.0](https://github.com/medic/cht-conf/compare/v5.0.0...v5.1.0) (2025-07-02)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -293,24 +293,6 @@ To achieve this, create a file called `settings.inherit.json` in your project's
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
# Fetching logs
|
|
297
|
-
|
|
298
|
-
Fetch logs from a CHT v2.x production server.
|
|
299
|
-
|
|
300
|
-
This is a standalone command installed alongside `cht-conf`. For usage information, run `cht-logs --help`.
|
|
301
|
-
|
|
302
|
-
## Usage
|
|
303
|
-
|
|
304
|
-
cht-logs <instance-name> <log-types...>
|
|
305
|
-
|
|
306
|
-
Accepted log types:
|
|
307
|
-
|
|
308
|
-
api
|
|
309
|
-
couchdb
|
|
310
|
-
gardener
|
|
311
|
-
nginx
|
|
312
|
-
sentinel
|
|
313
|
-
|
|
314
296
|
# Development
|
|
315
297
|
|
|
316
298
|
To develop a new action or improve an existing one, check the ["Actions" doc](src/fn/README.md).
|
package/commitlint.config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = {extends: ['@commitlint/config-conventional']}
|
|
1
|
+
module.exports = {extends: ['@commitlint/config-conventional']};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cht-conf",
|
|
3
|
-
"version": "5.1
|
|
3
|
+
"version": "5.2.1",
|
|
4
4
|
"description": "Configure CHT deployments",
|
|
5
5
|
"main": "./src/lib/main.js",
|
|
6
6
|
"engines": {
|
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
"bin": {
|
|
17
17
|
"medic-conf": "src/bin/index.js",
|
|
18
18
|
"cht": "src/bin/index.js",
|
|
19
|
-
"medic-logs": "src/bin/cht-logs.bash",
|
|
20
|
-
"cht-logs": "src/bin/cht-logs.bash",
|
|
21
19
|
"shell-completion-for-medic-conf": "src/bin/shell-completion.js",
|
|
22
20
|
"shell-completion-for-cht": "src/bin/shell-completion.js",
|
|
23
21
|
"pngout-medic": "bin/pngout",
|
package/src/cli/usage.js
CHANGED
|
@@ -8,9 +8,13 @@ ${bold('NAME')}
|
|
|
8
8
|
|
|
9
9
|
${bold('SYNOPSIS')}
|
|
10
10
|
cht <--local|--instance=instance-name|--url=url>
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
Or
|
|
13
|
+
|
|
12
14
|
cht <--local|--instance=instance-name|--url=url|--archive> <actions> <options> -- <params>
|
|
13
15
|
|
|
16
|
+
${underscore('Note')}: If <actions>,<options> or <params> are ${bold('not')} passed but one of --local or --instance or --url ${bold('is')} passed, ${bold('all')} supported actions are called.
|
|
17
|
+
|
|
14
18
|
${bold('DESCRIPTION')}
|
|
15
19
|
This script updates and uploads a project's configuration.
|
|
16
20
|
|
|
@@ -58,6 +62,9 @@ ${bold('OPTIONS')}
|
|
|
58
62
|
--skip-dependency-check
|
|
59
63
|
Skips checking the version running is set to the same version in the package.json
|
|
60
64
|
|
|
65
|
+
--skip-version-check
|
|
66
|
+
Skips the automatic check for new cht-conf versions
|
|
67
|
+
|
|
61
68
|
--skip-git-check
|
|
62
69
|
Skips checking the status of the current repository that holds the configuration
|
|
63
70
|
|
|
@@ -65,12 +72,13 @@ ${bold('OPTIONS')}
|
|
|
65
72
|
Skips checking message translations
|
|
66
73
|
|
|
67
74
|
--skip-validate
|
|
68
|
-
Skips form validation
|
|
75
|
+
Skips form validation
|
|
69
76
|
|
|
70
77
|
--force
|
|
71
|
-
CAN BE DANGEROUS! Passes yes to all commands and any where that would prompt to overwrite changes will overwrite automatically.
|
|
78
|
+
CAN BE DANGEROUS! Passes yes to all commands and any where that would prompt to overwrite changes will overwrite automatically.
|
|
72
79
|
`);
|
|
73
80
|
/* eslint-enable max-len */
|
|
74
81
|
};
|
|
75
82
|
|
|
76
83
|
const bold = text => `\x1b[1m${text}\x1b[0m`;
|
|
84
|
+
const underscore = text => `\x1b[4m${text}\x1b[0m`;
|
package/src/lib/api.js
CHANGED
|
@@ -254,6 +254,22 @@ const api = {
|
|
|
254
254
|
}
|
|
255
255
|
return [];
|
|
256
256
|
}
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
async getReportsByCreatedByIds (createdByIds, limit, skip) {
|
|
260
|
+
const queryString = createdByIds.map(id => `exact_match:"contact:${id}"`).join(' OR ');
|
|
261
|
+
const res = await request.get(`${environment.apiUrl}/_design/medic/_nouveau/reports_by_freetext`, {
|
|
262
|
+
qs: {
|
|
263
|
+
// sorting by this field ensures that the output are same with the clouseau views
|
|
264
|
+
// https://github.com/medic/cht-core/pull/9541
|
|
265
|
+
sort: '"reported_date"',
|
|
266
|
+
q: queryString,
|
|
267
|
+
include_docs: true,
|
|
268
|
+
limit,
|
|
269
|
+
skip
|
|
270
|
+
}, json: true
|
|
271
|
+
});
|
|
272
|
+
return res.hits.map(item => item.doc);
|
|
257
273
|
}
|
|
258
274
|
};
|
|
259
275
|
|
|
@@ -1,39 +1,35 @@
|
|
|
1
|
-
const info = require('../lib/log').info;
|
|
2
1
|
const request = require('request-promise-native');
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
module.exports = (options) => {
|
|
6
|
-
const current = require('../../package').version;
|
|
7
|
-
info(`Current version: ${current}. Checking NPM for updates…`);
|
|
8
|
-
|
|
9
|
-
if (!options) {
|
|
10
|
-
options = {};
|
|
11
|
-
}
|
|
2
|
+
const log = require('../lib/log');
|
|
3
|
+
const current = require('../../package.json').version;
|
|
12
4
|
|
|
5
|
+
module.exports = (options = {}) => {
|
|
13
6
|
return request
|
|
14
7
|
.get('https://registry.npmjs.org/cht-conf')
|
|
15
8
|
.then(res => {
|
|
16
9
|
const json = JSON.parse(res);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
return json['dist-tags'].latest;
|
|
11
|
+
})
|
|
12
|
+
.catch(err => {
|
|
13
|
+
log.warn(`Could not check NPM for updates: ${err.message}`);
|
|
14
|
+
if (!options.nonFatal) {
|
|
15
|
+
throw err;
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
.then(latest => {
|
|
19
|
+
if (latest && latest !== current) {
|
|
20
|
+
log.warn(`New version available!
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
${current} -> ${latest}
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
To install:
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (options.nonFatal
|
|
34
|
-
|
|
35
|
-
} else {
|
|
36
|
-
warn(`Could not check NPM for updates. Error: ${err.message}`);
|
|
26
|
+
npm install -g cht-conf
|
|
27
|
+
`);
|
|
28
|
+
if (!options.nonFatal) {
|
|
29
|
+
throw new Error('You are not running the latest version of cht-conf!');
|
|
30
|
+
}
|
|
31
|
+
} else if (!options.nonFatal) {
|
|
32
|
+
log.info('You are already on the latest version :¬)');
|
|
37
33
|
}
|
|
38
34
|
});
|
|
39
35
|
};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
const lineageManipulation = require('./lineage-manipulation');
|
|
2
|
+
const {getValidApiVersion} = require('../get-api-version');
|
|
3
|
+
const semver = require('semver');
|
|
4
|
+
const api = require('../api');
|
|
2
5
|
|
|
3
6
|
const HIERARCHY_ROOT = 'root';
|
|
4
7
|
const BATCH_SIZE = 10000;
|
|
8
|
+
const NOUVEAU_MIN_VERSION = '5.0.0';
|
|
5
9
|
|
|
6
10
|
/*
|
|
7
11
|
Fetches all of the documents associated with the "contactIds" and confirms they exist.
|
|
@@ -56,28 +60,48 @@ async function getContactWithDescendants(db, contactId) {
|
|
|
56
60
|
.filter(doc => doc && doc.type !== 'tombstone');
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
async
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
[`patient_id:${createdAtId}`],
|
|
63
|
-
[`patient_uuid:${createdAtId}`],
|
|
64
|
-
[`place_id:${createdAtId}`],
|
|
65
|
-
[`place_uuid:${createdAtId}`]
|
|
66
|
-
] : [];
|
|
67
|
-
|
|
68
|
-
const reports = await db.query('medic-client/reports_by_freetext', {
|
|
69
|
-
keys: [
|
|
70
|
-
...createdByKeys,
|
|
71
|
-
...createdAtKeys,
|
|
72
|
-
],
|
|
63
|
+
const getFromDbView = async (db, view, keys, skip) => {
|
|
64
|
+
const res = await db.query(view, {
|
|
65
|
+
keys,
|
|
73
66
|
include_docs: true,
|
|
74
67
|
limit: BATCH_SIZE,
|
|
75
|
-
skip
|
|
68
|
+
skip
|
|
76
69
|
});
|
|
70
|
+
return res.rows.map(row => row.doc);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const fetchReportsByCreator = async (db, createdByIds, skip) => {
|
|
74
|
+
if (createdByIds.length === 0) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const coreVersion = await getValidApiVersion();
|
|
79
|
+
if (coreVersion && semver.gte(coreVersion, NOUVEAU_MIN_VERSION)) {
|
|
80
|
+
return await api().getReportsByCreatedByIds(createdByIds, BATCH_SIZE, skip);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const createdByKeys = createdByIds.map(id => [`contact:${id}`]);
|
|
84
|
+
return await getFromDbView(db, 'medic-client/reports_by_freetext', createdByKeys, skip);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const fetchReportsBySubject = async (db, createdAtId, skip) => {
|
|
88
|
+
if (!createdAtId) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
return await getFromDbView(db, 'medic-client/reports_by_subject', [createdAtId], skip);
|
|
92
|
+
};
|
|
77
93
|
|
|
78
|
-
|
|
94
|
+
const getReportsForContacts = async (db, createdByIds, createdAtId, skip) => {
|
|
95
|
+
const [creatorReports, subjectReports] = await Promise.all([
|
|
96
|
+
fetchReportsByCreator(db, createdByIds, skip),
|
|
97
|
+
fetchReportsBySubject(db, createdAtId, skip)
|
|
98
|
+
]);
|
|
99
|
+
|
|
100
|
+
const allRows = [...creatorReports, ...subjectReports];
|
|
101
|
+
|
|
102
|
+
const docsWithId = allRows.map(( doc ) => [doc._id, doc]);
|
|
79
103
|
return Array.from(new Map(docsWithId).values());
|
|
80
|
-
}
|
|
104
|
+
};
|
|
81
105
|
|
|
82
106
|
async function getAncestorsOf(db, contactDoc) {
|
|
83
107
|
const ancestorIds = lineageManipulation.pluckIdsFromLineage(contactDoc.parent);
|
package/src/lib/main.js
CHANGED
|
@@ -187,11 +187,6 @@ module.exports = async (argv, env) => {
|
|
|
187
187
|
info(`Processing config in ${projectName}.`);
|
|
188
188
|
info('Actions:\n -', actions.map(({name}) => name).join('\n - '));
|
|
189
189
|
|
|
190
|
-
const skipCheckForUpdates = cmdArgs.check === false;
|
|
191
|
-
if (actions.some(action => action.name === 'check-for-updates') && !skipCheckForUpdates) {
|
|
192
|
-
await checkForUpdates({ nonFatal: true });
|
|
193
|
-
}
|
|
194
|
-
|
|
195
190
|
for (const action of actions) {
|
|
196
191
|
info(`Starting action: ${action.name}…`);
|
|
197
192
|
await executeAction(action);
|
|
@@ -201,6 +196,9 @@ module.exports = async (argv, env) => {
|
|
|
201
196
|
if (actions.length > 1) {
|
|
202
197
|
await info('All actions completed.');
|
|
203
198
|
}
|
|
199
|
+
if (!actions.some(action => action.name === 'check-for-updates') && !cmdArgs['skip-version-check']) {
|
|
200
|
+
await checkForUpdates({ nonFatal: true });
|
|
201
|
+
}
|
|
204
202
|
};
|
|
205
203
|
|
|
206
204
|
function buildActions(cmdArgs, skipValidate) {
|
package/src/bin/cht-logs.bash
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
#!/bin/bash -eu
|
|
2
|
-
|
|
3
|
-
usage() {
|
|
4
|
-
cat <<EOF
|
|
5
|
-
cht-logs
|
|
6
|
-
==========
|
|
7
|
-
|
|
8
|
-
Fetch logs from production CHT servers.
|
|
9
|
-
|
|
10
|
-
USAGE
|
|
11
|
-
$0 <instance-name> <log-types...>
|
|
12
|
-
|
|
13
|
-
Accepted log types:
|
|
14
|
-
|
|
15
|
-
api
|
|
16
|
-
couchdb
|
|
17
|
-
gardener
|
|
18
|
-
nginx
|
|
19
|
-
sentinel
|
|
20
|
-
EOF
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if [[ $# = 0 ]]; then usage; exit 1; fi
|
|
24
|
-
if [[ "$1" = "--help" ]]; then usage; exit; fi
|
|
25
|
-
if [[ $# < 2 ]]; then usage; exit 1; fi
|
|
26
|
-
|
|
27
|
-
instanceName="$1"
|
|
28
|
-
shift
|
|
29
|
-
|
|
30
|
-
domain="${instanceName}.medicmobile.org"
|
|
31
|
-
|
|
32
|
-
localRoot="fetched-logs/${instanceName}"
|
|
33
|
-
|
|
34
|
-
while [[ $# > 0 ]]; do
|
|
35
|
-
logType="$1"
|
|
36
|
-
shift
|
|
37
|
-
|
|
38
|
-
case "$logType" in
|
|
39
|
-
nginx) logPath="/var/log/medic-core/nginx"; realLogType=nginx ;;
|
|
40
|
-
|
|
41
|
-
gardener) logPath="/var/log/gardener"; realLogType=gardener ;;
|
|
42
|
-
api) logPath="/var/log/gardener"; realLogType=gardener ;;
|
|
43
|
-
medic-api) logPath="/var/log/gardener"; realLogType=gardener ;;
|
|
44
|
-
sentinel) logPath="/var/log/gardener"; realLogType=gardener ;;
|
|
45
|
-
|
|
46
|
-
couch) logPath="/var/log/medic-core/couchdb";realLogType=couchdb ;;
|
|
47
|
-
couchdb) logPath="/var/log/medic-core/couchdb";realLogType=couchdb ;;
|
|
48
|
-
|
|
49
|
-
*) echo "ERROR: Cannot fetch logs of type: $logType"; exit 1 ;;
|
|
50
|
-
esac
|
|
51
|
-
|
|
52
|
-
localDir="${localRoot}/${realLogType}"
|
|
53
|
-
mkdir -p "$localDir"
|
|
54
|
-
|
|
55
|
-
echo "[logs:$logType] Fetching logs to ${localDir}..."
|
|
56
|
-
rsync -az --progress -e 'ssh -p 33696' "vm@${domain}:${logPath}/*" "$localDir"
|
|
57
|
-
|
|
58
|
-
echo "[logs:$logType] Decompressing logs..."
|
|
59
|
-
(cd "$localDir" && find . -name \*.bz2 | xargs bzip2 -dk)
|
|
60
|
-
|
|
61
|
-
echo "[logs:$logType] Completed. Logs saved in: ${localDir}"
|
|
62
|
-
done
|