cht-conf 5.2.1 → 5.3.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
+ # [5.3.0](https://github.com/medic/cht-conf/compare/v5.2.1...v5.3.0) (2025-09-04)
2
+
3
+
4
+ ### Features
5
+
6
+ * **#512:** add form validation for instance::db-doc ([#737](https://github.com/medic/cht-conf/issues/737)) ([0db687e](https://github.com/medic/cht-conf/commit/0db687eb8f2c5dbb6a2d2e387857af50af81a917)), closes [#512](https://github.com/medic/cht-conf/issues/512)
7
+
1
8
  ## [5.2.1](https://github.com/medic/cht-conf/compare/v5.2.0...v5.2.1) (2025-08-27)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cht-conf",
3
- "version": "5.2.1",
3
+ "version": "5.3.0",
4
4
  "description": "Configure CHT deployments",
5
5
  "main": "./src/lib/main.js",
6
6
  "engines": {
@@ -92,6 +92,6 @@
92
92
  "pouchdb-adapter-memory": "^9.0.0",
93
93
  "rewire": "^8.0.0",
94
94
  "semantic-release": "^24.2.4",
95
- "sinon": "^19.0.2"
95
+ "sinon": "^21.0.0"
96
96
  }
97
97
  }
@@ -9,6 +9,14 @@ const getNode = (currentNode, path) =>
9
9
  const getNodes = (currentNode, path) =>
10
10
  xpath.parse(path).select({ node: currentNode, allowAnyNamespaceForNoPrefix: true });
11
11
 
12
+ const getFullNodePath = (childNode) => {
13
+ if (childNode.nodeType !== 1) {
14
+ return '';
15
+ }
16
+ const parentPath = getFullNodePath(childNode.parentNode);
17
+ return parentPath + '/' + childNode.nodeName;
18
+ };
19
+
12
20
  module.exports = {
13
21
  /**
14
22
  * Get the full path of the form, or null if the path doesn't exist.
@@ -68,6 +76,15 @@ module.exports = {
68
76
  */
69
77
  getPrimaryInstanceNode: xmlDoc => getNode(xmlDoc, `${XPATH_MODEL}/instance`),
70
78
 
79
+ /**
80
+ * Returns the path to the given child node relative to the primary instance node.
81
+ * This is useful for identifying the node in error/warning messages.
82
+ * @param childNode the child node
83
+ * @returns {string}
84
+ */
85
+ getPrimaryInstanceNodeChildPath: (childNode) => getFullNodePath(childNode)
86
+ .replace(`${XPATH_MODEL}/instance`, ''),
87
+
71
88
  /**
72
89
  * Check whether the XForm has the <instanceID/> tag.
73
90
  * @param {string} xmlDoc the XML document
@@ -0,0 +1,27 @@
1
+ const { getPrimaryInstanceNode, getNodes, getPrimaryInstanceNodeChildPath } = require('../../forms-utils');
2
+
3
+ module.exports = {
4
+ name: 'db-doc-is-valid.js',
5
+ requiresInstance: false,
6
+ execute: async ({ xmlDoc, xformPath }) => {
7
+ const errors = [];
8
+ const primaryInstance = getPrimaryInstanceNode(xmlDoc);
9
+ const dbDocNodes = getNodes(xmlDoc, '//*[@db-doc="true"]', primaryInstance);
10
+ dbDocNodes.forEach(node => {
11
+ const childNodes = node.childNodes.filter(n => n.nodeType === 1);
12
+ if (!childNodes.length) {
13
+ const nodeName = getPrimaryInstanceNodeChildPath(node);
14
+ errors.push(` - ${nodeName}: the db-doc attribute must only be set on groups.`);
15
+ return;
16
+ }
17
+ const hasTypeField = childNodes.some(child => child.nodeName === 'type');
18
+ if (!hasTypeField) {
19
+ const nodeName = getPrimaryInstanceNodeChildPath(node);
20
+ errors.push(` - ${nodeName}: groups configured with the db-doc attribute must contain a valid type field.`);
21
+ }
22
+ });
23
+
24
+ const header = `Form at ${xformPath} contains invalid db-doc configuration:`;
25
+ return { errors: errors.length ? [header, ...errors]: errors };
26
+ }
27
+ };