cht-conf 5.0.0 → 5.2.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,17 @@
1
+ # [5.2.0](https://github.com/medic/cht-conf/compare/v5.1.0...v5.2.0) (2025-08-07)
2
+
3
+
4
+ ### Features
5
+
6
+ * 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))
7
+
8
+ # [5.1.0](https://github.com/medic/cht-conf/compare/v5.0.0...v5.1.0) (2025-07-02)
9
+
10
+
11
+ ### Features
12
+
13
+ * compile max_task_notifications ([#717](https://github.com/medic/cht-conf/issues/717)) ([3c68ea2](https://github.com/medic/cht-conf/commit/3c68ea251c73ecfca5a910060c28e68f932c9963))
14
+
1
15
  # [5.0.0](https://github.com/medic/cht-conf/compare/v4.10.0...v5.0.0) (2025-06-24)
2
16
 
3
17
 
@@ -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.0.0",
3
+ "version": "5.2.0",
4
4
  "description": "Configure CHT deployments",
5
5
  "main": "./src/lib/main.js",
6
6
  "engines": {
@@ -49,7 +49,7 @@
49
49
  "json-diff": "^1.0.6",
50
50
  "json-stringify-safe": "^5.0.1",
51
51
  "json2csv": "^5.0.7",
52
- "mime-types": "^2.1.35",
52
+ "mime-types": "^3.0.1",
53
53
  "minimist": "^1.2.8",
54
54
  "mkdirp": "^3.0.1",
55
55
  "open": "^8.4.2",
@@ -92,7 +92,7 @@
92
92
  "mocha": "^11.1.0",
93
93
  "nyc": "^17.1.0",
94
94
  "pouchdb-adapter-memory": "^9.0.0",
95
- "rewire": "^7.0.0",
95
+ "rewire": "^8.0.0",
96
96
  "semantic-release": "^24.2.4",
97
97
  "sinon": "^19.0.2"
98
98
  }
@@ -65,6 +65,13 @@ const compileAppSettingsForProject = async (projectDir, options) => {
65
65
  const baseSettingsPath = path.join(projectDir, `${APP_SETTINGS_DIR_PATH}/base_settings.json`);
66
66
  const appSettingsPath = path.join(projectDir, APP_SETTINGS_JSON_PATH);
67
67
  const esLintFilePath = path.join(projectDir, '.eslintrc');
68
+ const parseMaxTaskNotifications = (maxTaskNotifications) => {
69
+ if (typeof maxTaskNotifications !== 'number' || !Number.isInteger(maxTaskNotifications) ||
70
+ maxTaskNotifications < 0) {
71
+ throw new Error('max_task_notifications should be a positive integer number');
72
+ }
73
+ return maxTaskNotifications;
74
+ };
68
75
 
69
76
  // Fail if no eslintrc file is found
70
77
  if (!fs.exists(esLintFilePath)) {
@@ -130,6 +137,11 @@ const compileAppSettingsForProject = async (projectDir, options) => {
130
137
  targets: parseTargets(projectDir),
131
138
  };
132
139
 
140
+ if (appSettings.max_task_notifications) {
141
+ appSettings.tasks.max_task_notifications = parseMaxTaskNotifications(appSettings.max_task_notifications);
142
+ delete appSettings.max_task_notifications;
143
+ }
144
+
133
145
  const purgeConfig = parsePurge(projectDir);
134
146
  if (purgeConfig) {
135
147
  appSettings.purge = purgeConfig;
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,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 function getReportsForContacts(db, createdByIds, createdAtId, skip) {
60
- const createdByKeys = createdByIds.map(id => [`contact:${id}`]);
61
- const createdAtKeys = createdAtId ? [
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
- const docsWithId = reports.rows.map(({ doc }) => [doc._id, doc]);
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);