cht-conf 3.10.2 → 3.12.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/.eslintignore CHANGED
@@ -1 +1,2 @@
1
- **/build
1
+ **/build
2
+ test/data/**
package/.releaserc.json CHANGED
@@ -18,5 +18,5 @@
18
18
  }
19
19
  ]
20
20
  ],
21
- "branches": ["master"]
21
+ "branches": ["main"]
22
22
  }
package/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ # [3.12.0](https://github.com/medic/cht-conf/compare/v3.11.1...v3.12.0) (2022-06-23)
2
+
3
+
4
+ ### Features
5
+
6
+ * **#484:** add actions for validating forms ([f2a6a8e](https://github.com/medic/cht-conf/commit/f2a6a8ef75561426ce2a6b542cdf1a255c869c6e)), closes [#484](https://github.com/medic/cht-conf/issues/484) [#481](https://github.com/medic/cht-conf/issues/481)
7
+
8
+ ## [3.11.1](https://github.com/medic/cht-conf/compare/v3.11.0...v3.11.1) (2022-06-13)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **#482:** move-contacts usage docs ([5fa86c8](https://github.com/medic/cht-conf/commit/5fa86c8e98797d8920ee20f2e7f16c98aa969201)), closes [#482](https://github.com/medic/cht-conf/issues/482)
14
+
15
+ # [3.11.0](https://github.com/medic/cht-conf/compare/v3.10.2...v3.11.0) (2022-04-19)
16
+
17
+
18
+ ### Features
19
+
20
+ * **#477:** adds watch-project action ([7a3efc5](https://github.com/medic/cht-conf/commit/7a3efc5efcbd98d8a6b03e801945201ed17ac00f)), closes [#477](https://github.com/medic/cht-conf/issues/477)
21
+
1
22
  ## [3.10.2](https://github.com/medic/cht-conf/compare/v3.10.1...v3.10.2) (2022-03-29)
2
23
 
3
24
 
@@ -199,7 +220,7 @@ As of this release no docs on the server will be touched unless some configurati
199
220
 
200
221
  ### New action to bulk-edit contacts
201
222
 
202
- You can now bulk edit contacts at once by providing a CSV. For more information, read [the documentation](https://github.com/medic/cht-conf/blob/master/README.md#editing-contacts-across-the-hierarchy).
223
+ You can now bulk edit contacts at once by providing a CSV. For more information, read [the documentation](https://github.com/medic/cht-conf/blob/main/README.md#editing-contacts-across-the-hierarchy).
203
224
 
204
225
  [#297](https://github.com/medic/cht-conf/issues/297)
205
226
 
package/README.md CHANGED
@@ -317,7 +317,7 @@ Breaking| perf(#2): remove reporting rates feature <br/> BREAKING CHANGE: report
317
317
 
318
318
  ### Releasing betas
319
319
 
320
- 1. Checkout `master`
320
+ 1. Checkout the default branch, for example `main`
321
321
  1. Run `npm version --no-git-tag-version <major>.<minor>.<patch>-beta.1`. This will only update the versions in `package.json` and `package-lock.json`. It will not create a git tag and not create an associated commit.
322
322
  1. Run `npm publish --tag beta`. This will publish your beta tag to npm's beta channel.
323
323
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cht-conf",
3
- "version": "3.10.2",
3
+ "version": "3.12.0",
4
4
  "description": "Configure CHT deployments",
5
5
  "main": "./src/lib/main.js",
6
6
  "engines": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "scripts": {
10
10
  "clean": "rm -rf ./build/",
11
- "eslint": "eslint src/**/*.js test/*.js test/**/*.js",
11
+ "eslint": "eslint 'src/**/*.js' test/*.js 'test/**/*.js'",
12
12
  "docker-start-couchdb": "npm run docker-stop-couchdb && docker run -d -p 6984:5984 --rm --name cht-conf-couchdb couchdb:2.3.1 && sh test/scripts/wait_for_response_code.sh 6984 200 CouchDB",
13
13
  "docker-stop-couchdb": "docker stop cht-conf-couchdb || true",
14
14
  "test": "npm run eslint && npm run docker-start-couchdb && npm run clean && mkdir -p build/test && cp -r test/data build/test/data && cd build/test && nyc --reporter=html mocha --forbid-only ../../test/**/*.spec.js && cd ../.. && npm run docker-stop-couchdb",
@@ -37,6 +37,7 @@
37
37
  "dependencies": {
38
38
  "@hapi/joi": "^16.1.8",
39
39
  "@medic/translation-checker": "^1.0.1",
40
+ "@parcel/watcher": "^2.0.5",
40
41
  "canonical-json": "0.0.4",
41
42
  "csv-parse": "^4.16.0",
42
43
  "dom-compare": "^0.6.0",
@@ -56,6 +57,7 @@
56
57
  "pouchdb-core": "^7.2.2",
57
58
  "pouchdb-mapreduce": "^7.2.2",
58
59
  "properties": "^1.2.1",
60
+ "queue-promise": "^2.2.1",
59
61
  "readline-sync": "^1.4.10",
60
62
  "redact-basic-auth": "^1.0.1",
61
63
  "request": "^2.88.2",
@@ -86,6 +88,7 @@
86
88
  "pouchdb-adapter-memory": "^7.2.2",
87
89
  "rewire": "^5.0.0",
88
90
  "semantic-release": "^18.0.0",
89
- "sinon": "^7.3.2"
91
+ "sinon": "^7.3.2",
92
+ "fs-extra": "8.1.0"
90
93
  }
91
94
  }
package/release-notes.md CHANGED
@@ -134,7 +134,7 @@ As of this release no docs on the server will be touched unless some configurati
134
134
 
135
135
  ### New action to bulk-edit contacts
136
136
 
137
- You can now bulk edit contacts at once by providing a CSV. For more information, read [the documentation](https://github.com/medic/cht-conf/blob/master/README.md#editing-contacts-across-the-hierarchy).
137
+ You can now bulk edit contacts at once by providing a CSV. For more information, read [the documentation](https://github.com/medic/cht-conf/blob/main/README.md#editing-contacts-across-the-hierarchy).
138
138
 
139
139
  [#297](https://github.com/medic/cht-conf/issues/297)
140
140
 
package/src/cli/usage.js CHANGED
@@ -63,6 +63,9 @@ ${bold('OPTIONS')}
63
63
  --skip-translation-check
64
64
  Skips checking message translations
65
65
 
66
+ --skip-validate
67
+ Skips form validation
68
+
66
69
  --force
67
70
  CAN BE DANGEROUS! Passes yes to all commands and any where that would prompt to overwrite changes will overwrite automatically.
68
71
  `);
@@ -8,6 +8,21 @@ const parseTargets = require('../lib/parse-targets');
8
8
  const { warn } = require('../lib/log');
9
9
  const parsePurge = require('../lib/parse-purge');
10
10
  const validateAppSettings = require('../lib/validate-app-settings');
11
+ const { APP_SETTINGS_DIR_PATH, APP_SETTINGS_JSON_PATH } = require('../lib/project-paths');
12
+
13
+ // we can't used named capture groups yet
14
+ const JS_FILE_MATCHER = /^(.+)(\.js)$/; // 2 groups get the file name and extension
15
+ const JSON_FILE_MATCHER = /^(.+)(\.json)$/;
16
+ const configFileMatcher = (fileName) => {
17
+ const jsFileMatchResult = fileName.match(JS_FILE_MATCHER);
18
+ // the first element is always the whole matched string, then our first file name group
19
+ if (jsFileMatchResult) return jsFileMatchResult[1];
20
+
21
+ const jsonFileMatchResult = fileName.match(JSON_FILE_MATCHER);
22
+ if (jsonFileMatchResult) return jsonFileMatchResult[1];
23
+
24
+ return null;
25
+ };
11
26
 
12
27
  const compileAppSettings = async () => {
13
28
  const options = parseExtraArgs(environment.extraArgs);
@@ -23,7 +38,7 @@ const compileAppSettings = async () => {
23
38
  appSettings = await compileAppSettingsForProject(projectDir, options);
24
39
  }
25
40
 
26
- fs.writeJson(path.join(projectDir, 'app_settings.json'), appSettings);
41
+ fs.writeJson(path.join(projectDir, APP_SETTINGS_JSON_PATH), appSettings);
27
42
  };
28
43
 
29
44
  const compileAppSettingsForProject = async (projectDir, options) => {
@@ -41,8 +56,8 @@ const compileAppSettingsForProject = async (projectDir, options) => {
41
56
 
42
57
  const readOptionalJson = path => fs.exists(path) ? fs.readJson(path) : undefined;
43
58
  let appSettings;
44
- const baseSettingsPath = path.join(projectDir, 'app_settings/base_settings.json');
45
- const appSettingsPath = path.join(projectDir, 'app_settings.json');
59
+ const baseSettingsPath = path.join(projectDir, `${APP_SETTINGS_DIR_PATH}/base_settings.json`);
60
+ const appSettingsPath = path.join(projectDir, APP_SETTINGS_JSON_PATH);
46
61
  const esLintFilePath = path.join(projectDir, '.eslintrc');
47
62
 
48
63
  // Fail if no eslintrc file is found
@@ -56,10 +71,10 @@ const compileAppSettingsForProject = async (projectDir, options) => {
56
71
  if (fs.exists(baseSettingsPath)) {
57
72
  // using modular config so should override anything already defined in app_settings.json
58
73
  appSettings = fs.readJson(baseSettingsPath);
59
- if(appSettings.forms) {
74
+ if (appSettings.forms) {
60
75
  warn('forms should be defined in a separate <config_repo>/app_settings/forms.json file.');
61
76
  }
62
- if(appSettings.schedules) {
77
+ if (appSettings.schedules) {
63
78
  warn('schedules should be defined in a separate <config_repo>/app_settings/schedules.json file.');
64
79
  }
65
80
  const formSettings = readOptionalJson(path.join(projectDir, 'app_settings/forms.json'));
@@ -107,7 +122,7 @@ function applyTransforms(app_settings, inherited) {
107
122
  rules.forEach(k => {
108
123
  const parts = k.split('.');
109
124
  let t = target;
110
- while(parts.length > 1) {
125
+ while (parts.length > 1) {
111
126
  t = t[parts[0]];
112
127
  parts.shift();
113
128
  }
@@ -122,7 +137,7 @@ function applyTransforms(app_settings, inherited) {
122
137
  .forEach(k => {
123
138
  const parts = k.split('.');
124
139
  let t = target;
125
- while(parts.length > 1) {
140
+ while (parts.length > 1) {
126
141
  t = t[parts[0]];
127
142
  parts.shift();
128
143
  }
@@ -146,7 +161,7 @@ function applyTransforms(app_settings, inherited) {
146
161
  .forEach(k => {
147
162
  const parts = k.split('.');
148
163
  let t = target;
149
- while(parts.length > 1) {
164
+ while (parts.length > 1) {
150
165
  t = t[parts[0]];
151
166
  parts.shift();
152
167
  }
@@ -178,5 +193,7 @@ const parseExtraArgs = (extraArgs = []) => {
178
193
 
179
194
  module.exports = {
180
195
  requiresInstance: false,
196
+ APP_SETTINGS_DIR_PATH,
197
+ configFileMatcher,
181
198
  execute: compileAppSettings
182
199
  };
@@ -16,6 +16,6 @@ module.exports = {
16
16
  .then(() => svgo.optimize(fs.read(path), { path }))
17
17
  .then(result => fs.write(path, result.data))
18
18
  .then(() => trace('Compressed', path))
19
- .then(() => warn('Make sure you compare the content of your SVG files before merging to the master branch - sometimes optimising can change their contents!')),
19
+ .then(() => warn('Make sure you compare the content of your SVG files before merging to the default branch - sometimes optimising can change their contents!')),
20
20
  Promise.resolve())
21
21
  };
@@ -1,11 +1,18 @@
1
- const convertForms = require('../lib/convert-forms');
1
+ const convertForms = require('../lib/convert-forms').execute;
2
2
  const environment = require('../lib/environment');
3
+ const { APP_FORMS_PATH } = require('../lib/project-paths');
3
4
 
4
- module.exports = {
5
- requiresInstance: false,
6
- execute: () => convertForms(environment.pathToProject, 'app', {
5
+ const convertAppForms = (forms) => {
6
+ return convertForms(environment.pathToProject, 'app', {
7
7
  enketo: true,
8
- forms: environment.extraArgs,
8
+ forms: forms,
9
9
  transformer: xml => xml.replace('</instance>', '</instance>\n <instance id="contact-summary"/>'),
10
- })
10
+ });
11
+ };
12
+
13
+ module.exports = {
14
+ requiresInstance: false,
15
+ convertAppForms,
16
+ APP_FORMS_PATH,
17
+ execute: () => convertAppForms(environment.extraArgs)
11
18
  };
@@ -1,9 +1,16 @@
1
- const convertForms = require('../lib/convert-forms');
1
+ const convertForms = require('../lib/convert-forms').execute;
2
2
  const environment = require('../lib/environment');
3
+ const { COLLECT_FORMS_PATH } = require('../lib/project-paths');
4
+
5
+ const convertCollectForms = (forms) => {
6
+ return convertForms(environment.pathToProject, 'collect', {
7
+ forms: forms,
8
+ });
9
+ };
3
10
 
4
11
  module.exports = {
5
12
  requiresInstance: false,
6
- execute: () => convertForms(environment.pathToProject, 'collect', {
7
- forms: environment.extraArgs,
8
- })
13
+ COLLECT_FORMS_PATH,
14
+ convertCollectForms,
15
+ execute: () => convertCollectForms(environment.extraArgs)
9
16
  };
@@ -1,92 +1,95 @@
1
- const convertForms = require('../lib/convert-forms');
1
+ const convertForms = require('../lib/convert-forms').execute;
2
2
  const environment = require('../lib/environment');
3
3
  const fs = require('../lib/sync-fs');
4
+ const { CONTACT_FORMS_PATH } = require('../lib/project-paths');
4
5
 
5
- const execute = () => {
6
- const dir = `${environment.pathToProject}/forms/contact`;
6
+ const convertContactForm = (forms) => {
7
+ const dir = `${environment.pathToProject}/${CONTACT_FORMS_PATH}`;
7
8
  const placeTypesJson = `${dir}/place-types.json`;
8
9
 
9
10
  let PLACE_TYPES;
10
- if(fs.exists(placeTypesJson)) {
11
+ if (fs.exists(placeTypesJson)) {
11
12
  PLACE_TYPES = fs.readJson(placeTypesJson);
12
13
  Object.keys(PLACE_TYPES)
13
14
  .forEach(type => {
14
- fs.copy(`${dir}/PLACE_TYPE-create.xlsx`, `${dir}/${type}-create.xlsx`,{ overwrite: false });
15
+ fs.copy(`${dir}/PLACE_TYPE-create.xlsx`, `${dir}/${type}-create.xlsx`, { overwrite: false });
15
16
  fs.copy(`${dir}/PLACE_TYPE-edit.xlsx`, `${dir}/${type}-edit.xlsx`, { overwrite: false });
16
17
  });
17
18
  }
18
19
 
19
20
  return convertForms(environment.pathToProject, 'contact', {
20
- enketo: true,
21
- force_data_node: 'data',
22
- forms: environment.extraArgs,
23
- transformer: (xml, path) => {
24
- const type = path.replace(/.*\/(.*?)(-(create|edit))?\.xml/, '$1');
21
+ enketo: true,
22
+ force_data_node: 'data',
23
+ forms: forms,
24
+ transformer: (xml, path) => {
25
+ const type = path.replace(/.*\/(.*?)(-(create|edit))?\.xml/, '$1');
25
26
 
26
- if(PLACE_TYPES) {
27
- xml = xml
28
- .replace(/PLACE_TYPE/g, type)
29
- .replace(/PLACE_NAME/g, PLACE_TYPES[type]);
30
- }
27
+ if (PLACE_TYPES) {
28
+ xml = xml
29
+ .replace(/PLACE_TYPE/g, type)
30
+ .replace(/PLACE_NAME/g, PLACE_TYPES[type]);
31
+ }
31
32
 
32
- // The ordering of elements in the <model> has an arcane affect on the
33
- // order that docs are saved in the database when processing a form.
34
- // Move the main doc's element down to the bottom.
35
- // For templated PLACE_TYPE forms, shifting must be done _after_ templating.
36
- if(xml.includes('</inputs>')) {
37
- let matchedBlock;
38
- const matcher = new RegExp(`\\s*<${type}>[\\s\\S]*</${type}>\\s*(\\r|\\n)`);
33
+ // The ordering of elements in the <model> has an arcane affect on the
34
+ // order that docs are saved in the database when processing a form.
35
+ // Move the main doc's element down to the bottom.
36
+ // For templated PLACE_TYPE forms, shifting must be done _after_ templating.
37
+ if (xml.includes('</inputs>')) {
38
+ let matchedBlock;
39
+ const matcher = new RegExp(`\\s*<${type}>[\\s\\S]*</${type}>\\s*(\\r|\\n)`);
39
40
 
40
- xml = xml.replace(matcher, match => {
41
- matchedBlock = match;
42
- return '\n';
43
- });
41
+ xml = xml.replace(matcher, match => {
42
+ matchedBlock = match;
43
+ return '\n';
44
+ });
44
45
 
45
- if(matchedBlock) {
46
- xml = xml.replace(/<\/inputs>(\r|\n)/, '</inputs>' + matchedBlock);
47
- }
46
+ if (matchedBlock) {
47
+ xml = xml.replace(/<\/inputs>(\r|\n)/, '</inputs>' + matchedBlock);
48
48
  }
49
+ }
49
50
 
50
- if(xml.includes('/data/init/custom_place_name')) {
51
- let matchedBlock;
52
- xml = xml.replace(/\s*<input ref="\/data\/init\/custom_place_name">[^]*?<\/input>/, match => {
53
- matchedBlock = match;
54
- return '';
55
- });
51
+ if (xml.includes('/data/init/custom_place_name')) {
52
+ let matchedBlock;
53
+ xml = xml.replace(/\s*<input ref="\/data\/init\/custom_place_name">[^]*?<\/input>/, match => {
54
+ matchedBlock = match;
55
+ return '';
56
+ });
56
57
 
57
- if(matchedBlock) {
58
- const targetMatcher = new RegExp(`\\s*<input ref="/data/${type}/external_id">\\s*(\\r|\\n)`);
59
- xml = xml.replace(targetMatcher, match => matchedBlock + match);
60
- }
58
+ if (matchedBlock) {
59
+ const targetMatcher = new RegExp(`\\s*<input ref="/data/${type}/external_id">\\s*(\\r|\\n)`);
60
+ xml = xml.replace(targetMatcher, match => matchedBlock + match);
61
61
  }
62
+ }
62
63
 
63
- if(xml.includes('ref="/data/contact"')) {
64
- const groupRegex = name => new RegExp(`(\\s*)<group(\\s.*)?\\sref="${name}"(\\s.*)?>[^]*?</group>`);
65
- let matchedBlock;
64
+ if (xml.includes('ref="/data/contact"')) {
65
+ const groupRegex = name => new RegExp(`(\\s*)<group(\\s.*)?\\sref="${name}"(\\s.*)?>[^]*?</group>`);
66
+ let matchedBlock;
66
67
 
67
- if(xml.match(groupRegex('/data/init'))) {
68
- xml = xml.replace(groupRegex('/data/contact'), match => {
69
- matchedBlock = match;
70
- return '';
71
- });
68
+ if (xml.match(groupRegex('/data/init'))) {
69
+ xml = xml.replace(groupRegex('/data/contact'), match => {
70
+ matchedBlock = match;
71
+ return '';
72
+ });
72
73
 
73
- if(matchedBlock) {
74
- const stripTrailingGroup = s => s.replace(/[\r\n\s]*<\/group>$/, '');
75
- xml = xml.replace(groupRegex('/data/init'), match => {
76
- return stripTrailingGroup(match) +
77
- stripTrailingGroup(matchedBlock).replace(/\n/g, '\n ') +
78
- '\n </group>\n </group>';
79
- });
80
- }
74
+ if (matchedBlock) {
75
+ const stripTrailingGroup = s => s.replace(/[\r\n\s]*<\/group>$/, '');
76
+ xml = xml.replace(groupRegex('/data/init'), match => {
77
+ return stripTrailingGroup(match) +
78
+ stripTrailingGroup(matchedBlock).replace(/\n/g, '\n ') +
79
+ '\n </group>\n </group>';
80
+ });
81
81
  }
82
82
  }
83
+ }
83
84
 
84
- return xml;
85
- },
86
- });
85
+ return xml;
86
+ },
87
+ });
87
88
  };
88
89
 
89
90
  module.exports = {
90
91
  requiresInstance: false,
91
- execute
92
+ convertContactForm,
93
+ CONTACT_FORMS_PATH,
94
+ execute: () => convertContactForm(environment.extraArgs)
92
95
  };
@@ -2,22 +2,23 @@ const environment = require('../lib/environment');
2
2
  const { info, warn } = require('../lib/log');
3
3
  const pouch = require('../lib/db');
4
4
 
5
+ const deleteForms = (forms) => {
6
+ if (!forms || !forms.length) {
7
+ warn('No forms specified for deleting.');
8
+ return;
9
+ }
10
+ const db = pouch();
11
+ return Promise.all(forms.map(formName => {
12
+ const docId = `form:${formName}`;
13
+ return db.get(docId)
14
+ .then(doc => db.remove(doc))
15
+ .then(() => info('Deleted form:', formName))
16
+ .catch(e => warn(`Failed to remove form with doc ID ${docId}`, e));
17
+ }));
18
+ };
19
+
5
20
  module.exports = {
6
21
  requiresInstance: true,
7
- execute: () => {
8
- const db = pouch();
9
- const { extraArgs } = environment;
10
- if (!extraArgs || !extraArgs.length) {
11
- warn('No forms specified for deleting.');
12
- return;
13
- }
14
-
15
- return Promise.all(extraArgs.map(formName => {
16
- const docId = `form:${formName}`;
17
- return db.get(docId)
18
- .then(doc => db.remove(doc))
19
- .then(() => info('Deleted form:', formName))
20
- .catch(e => warn(`Failed to remove form with doc ID ${docId}`, e));
21
- }));
22
- }
22
+ execute: () => deleteForms(environment.extraArgs),
23
+ deleteForms,
23
24
  };
@@ -101,7 +101,7 @@ const parseExtraArgs = (projectDir, extraArgs = []) => {
101
101
 
102
102
  if (contactIds.length === 0) {
103
103
  usage();
104
- throw Error('Action "move-contacts" is missing required list of contact_id to be moved');
104
+ throw Error('Action "move-contacts" is missing required list of contacts to be moved');
105
105
  }
106
106
 
107
107
  if (!args.parent) {
@@ -137,7 +137,7 @@ ${bold('cht-conf\'s move-contacts action')}
137
137
  When combined with 'upload-docs' this action effectively moves a contact from one place in the hierarchy to another.
138
138
 
139
139
  ${bold('USAGE')}
140
- cht --local move-contacts -- --contactIds=<id1>,<id2> --parent=<parent_id>
140
+ cht --local move-contacts -- --contacts=<id1>,<id2> --parent=<parent_id>
141
141
 
142
142
  ${bold('OPTIONS')}
143
143
  --contacts=<id1>,<id2>
@@ -1,9 +1,16 @@
1
1
  const environment = require('../lib/environment');
2
- const uploadForms = require('../lib/upload-forms');
2
+ const uploadForms = require('../lib/upload-forms').execute;
3
+ const { APP_FORMS_PATH } = require('../lib/project-paths');
4
+
5
+ const uploadAppForms = (forms) => {
6
+ return uploadForms(environment.pathToProject, 'app', {
7
+ forms: forms,
8
+ });
9
+ };
3
10
 
4
11
  module.exports = {
5
12
  requiresInstance: true,
6
- execute: () => uploadForms(environment.pathToProject, 'app', {
7
- forms: environment.extraArgs,
8
- })
13
+ uploadAppForms,
14
+ APP_FORMS_PATH: APP_FORMS_PATH,
15
+ execute: () => uploadAppForms(environment.extraArgs)
9
16
  };
@@ -2,29 +2,35 @@ const api = require('../lib/api');
2
2
  const environment = require('../lib/environment');
3
3
  const fs = require('../lib/sync-fs');
4
4
  const { info } = require('../lib/log');
5
+ const { APP_SETTINGS_DIR_PATH, APP_SETTINGS_JSON_PATH } = require('../lib/project-paths');
5
6
 
6
- module.exports = {
7
- requiresInstance: true,
8
- execute: () => {
9
- const settings = fs.read(`${environment.pathToProject}/app_settings.json`);
10
- return api().updateAppSettings(settings)
11
- .then(JSON.parse)
12
- .then(json => {
13
- // As per https://github.com/medic/cht-core/issues/3674, this endpoint
14
- // will return 200 even when upload fails.
15
- if (!json.success) {
16
- throw new Error(json.error);
17
- }
7
+ const uploadAppSettings = (api) => {
8
+ const settings = fs.read(`${environment.pathToProject}/${APP_SETTINGS_JSON_PATH}`);
9
+ return api.updateAppSettings(settings)
10
+ .then(JSON.parse)
11
+ .then(json => {
12
+ // As per https://github.com/medic/cht-core/issues/3674, this endpoint
13
+ // will return 200 even when upload fails.
14
+ if (!json.success) {
15
+ throw new Error(json.error);
16
+ }
18
17
 
19
- if ('updated' in json) {
20
- // the `updated` param was added in 3.9
21
- // https://github.com/medic/cht-core/issues/6315
22
- if (!json.updated) {
23
- info('Settings not updated - no changes detected');
24
- } else {
25
- info('Settings updated successfully');
26
- }
18
+ if ('updated' in json) {
19
+ // the `updated` param was added in 3.9
20
+ // https://github.com/medic/cht-core/issues/6315
21
+ if (!json.updated) {
22
+ info('Settings not updated - no changes detected');
23
+ } else {
24
+ info('Settings updated successfully');
27
25
  }
28
- });
29
- }
26
+ }
27
+ });
28
+ };
29
+
30
+ module.exports = {
31
+ uploadAppSettings,
32
+ APP_SETTINGS_DIR_PATH,
33
+ APP_SETTINGS_JSON_PATH,
34
+ requiresInstance: true,
35
+ execute: () => uploadAppSettings(api())
30
36
  };
@@ -1,10 +1,15 @@
1
1
  const environment = require('../lib/environment');
2
- const uploadForms = require('../lib/upload-forms');
2
+ const uploadForms = require('../lib/upload-forms').execute;
3
+
4
+ const uploadCollectForms = (forms) => {
5
+ return uploadForms(environment.pathToProject, 'collect', {
6
+ forms: forms,
7
+ default_context: { collect: true },
8
+ });
9
+ };
3
10
 
4
11
  module.exports = {
5
12
  requiresInstance: true,
6
- execute: () => uploadForms(environment.pathToProject, 'collect', {
7
- forms: environment.extraArgs,
8
- default_context: { collect:true },
9
- })
13
+ uploadCollectForms,
14
+ execute: () => uploadCollectForms(environment.extraArgs)
10
15
  };
@@ -1,11 +1,18 @@
1
1
  const environment = require('../lib/environment');
2
- const uploadForms = require('../lib/upload-forms');
2
+ const uploadForms = require('../lib/upload-forms').execute;
3
+ const CONTACT_FORMS_PATH = require('../lib/project-paths');
4
+
5
+ const uploadContactForms = (forms) => {
6
+ return uploadForms(environment.pathToProject, 'contact', {
7
+ id_prefix: 'contact:',
8
+ forms: forms,
9
+ default_context: { person: false, place: false },
10
+ });
11
+ };
3
12
 
4
13
  module.exports = {
5
14
  requiresInstance: true,
6
- execute: () => uploadForms(environment.pathToProject, 'contact', {
7
- id_prefix: 'contact:',
8
- forms: environment.extraArgs,
9
- default_context: { person:false, place:false },
10
- })
15
+ uploadContactForms,
16
+ CONTACT_FORMS_PATH,
17
+ execute: () => uploadContactForms(environment.extraArgs)
11
18
  };
@@ -13,10 +13,12 @@ const {
13
13
  TranslationException
14
14
  } = require('@medic/translation-checker');
15
15
 
16
+ const { TRANSLATIONS_DIR_PATH } = require('../lib/project-paths');
17
+
16
18
  const execute = async () => {
17
19
  const db = pouch(environment.apiUrl);
18
20
 
19
- const dir = `${environment.pathToProject}/translations`;
21
+ const dir = `${environment.pathToProject}/${TRANSLATIONS_DIR_PATH}`;
20
22
 
21
23
  let fileNames;
22
24
  let formatErrorsFound = 0;
@@ -85,7 +87,7 @@ const execute = async () => {
85
87
  languageName = 'TODO: please ask admin to set this in settings UI';
86
88
  } else {
87
89
  let languageNativeName = iso639.getNativeName(languageCode);
88
- if (languageNativeName !== languageName){
90
+ if (languageNativeName !== languageName) {
89
91
  languageName = `${languageNativeName} (${languageName})`;
90
92
  }
91
93
  }
@@ -95,7 +97,7 @@ const execute = async () => {
95
97
  let doc;
96
98
  try {
97
99
  doc = await db.get(id);
98
- } catch(e) {
100
+ } catch (e) {
99
101
  if (e.status === 404) {
100
102
  doc = await newDocFor(fileName, db, languageName, languageCode);
101
103
  }
@@ -127,7 +129,7 @@ function parse(filePath, options) {
127
129
  }
128
130
 
129
131
  function overwriteProperties(doc, props) {
130
- if(doc.generic) {
132
+ if (doc.generic) {
131
133
  // 3.4.0 translation structure
132
134
  doc.custom = props;
133
135
  } else if (doc.values) {
@@ -179,5 +181,6 @@ async function genericTranslationsStructure(db) {
179
181
 
180
182
  module.exports = {
181
183
  requiresInstance: true,
184
+ TRANSLATIONS_DIR_PATH,
182
185
  execute
183
186
  };