@opencrvs/create-countryconfig 2.1.0-rc.f29a266 → 2.1.0-rc.f5ea803
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/index.js +176 -2
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
const path = require('path')
|
|
15
15
|
const fs = require('fs')
|
|
16
|
+
const readline = require('readline/promises')
|
|
16
17
|
const degit = require('degit').default
|
|
17
18
|
|
|
18
19
|
const INFRASTRUCTURE_REPOSITORY = 'opencrvs/infrastructure'
|
|
@@ -64,6 +65,166 @@ function ensureTargetDirectoryDoesNotExist(directoryName) {
|
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Asks whether to enable telemetry. Defaults to yes, and answers yes without
|
|
70
|
+
* prompting when not attached to a terminal (e.g. non-interactive scaffolding).
|
|
71
|
+
*/
|
|
72
|
+
async function promptEnableTelemetry() {
|
|
73
|
+
if (!process.stdin.isTTY) {
|
|
74
|
+
return true
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const rl = readline.createInterface({
|
|
78
|
+
input: process.stdin,
|
|
79
|
+
output: process.stdout
|
|
80
|
+
})
|
|
81
|
+
try {
|
|
82
|
+
const answer = (
|
|
83
|
+
await rl.question(
|
|
84
|
+
'\nEnable anonymous usage telemetry to help improve OpenCRVS? Only ' +
|
|
85
|
+
'aggregate metrics are shared — no personal or protected data. [Y/n] '
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
.trim()
|
|
89
|
+
.toLowerCase()
|
|
90
|
+
return answer === '' || answer === 'y' || answer === 'yes'
|
|
91
|
+
} finally {
|
|
92
|
+
rl.close()
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Prompts for a single line of input, re-asking until `validate` accepts the
|
|
98
|
+
* trimmed answer. `validate` returns an error message string when the answer is
|
|
99
|
+
* invalid, or a falsy value when it is accepted. Exits when not attached to a
|
|
100
|
+
* terminal, since a mandatory value cannot be gathered non-interactively.
|
|
101
|
+
*/
|
|
102
|
+
async function promptRequired(question, validate) {
|
|
103
|
+
if (!process.stdin.isTTY) {
|
|
104
|
+
console.error(
|
|
105
|
+
'\nError: interactive input is required to set the organisation name and country code.'
|
|
106
|
+
)
|
|
107
|
+
process.exit(1)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const rl = readline.createInterface({
|
|
111
|
+
input: process.stdin,
|
|
112
|
+
output: process.stdout
|
|
113
|
+
})
|
|
114
|
+
try {
|
|
115
|
+
while (true) {
|
|
116
|
+
const answer = (await rl.question(question)).trim()
|
|
117
|
+
const error = validate(answer)
|
|
118
|
+
if (!error) {
|
|
119
|
+
return answer
|
|
120
|
+
}
|
|
121
|
+
console.error(error)
|
|
122
|
+
}
|
|
123
|
+
} finally {
|
|
124
|
+
rl.close()
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Prompts for the organisation name reported with telemetry. Mandatory.
|
|
130
|
+
*/
|
|
131
|
+
function promptOrganisation() {
|
|
132
|
+
return promptRequired('\nOrganisation running this instance: ', (answer) =>
|
|
133
|
+
answer === '' ? 'Please enter an organisation name.' : undefined
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Prompts for the alpha-3 ISO country code reported with telemetry, re-asking
|
|
139
|
+
* until a valid three-letter code is given. Mandatory.
|
|
140
|
+
*/
|
|
141
|
+
async function promptCountryCode() {
|
|
142
|
+
const answer = await promptRequired(
|
|
143
|
+
'\nAlpha-3 ISO country code of this instance (e.g. "GBR"): ',
|
|
144
|
+
(value) =>
|
|
145
|
+
/^[A-Za-z]{3}$/.test(value)
|
|
146
|
+
? undefined
|
|
147
|
+
: 'Please enter a three-letter alpha-3 ISO country code (e.g. "GBR").'
|
|
148
|
+
)
|
|
149
|
+
return answer.toUpperCase()
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Flips the `TELEMETRY_ENABLED` env var default in the cloned country config's
|
|
154
|
+
* environment to `true`. The template ships it defaulting to `false`.
|
|
155
|
+
*/
|
|
156
|
+
function enableTelemetryInEnvironment(targetPath) {
|
|
157
|
+
const environmentPath = path.join(targetPath, 'src', 'environment.ts')
|
|
158
|
+
if (!fs.existsSync(environmentPath)) {
|
|
159
|
+
console.warn(
|
|
160
|
+
'\nWarning: could not find src/environment.ts; telemetry default not changed.'
|
|
161
|
+
)
|
|
162
|
+
return
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const original = fs.readFileSync(environmentPath, 'utf-8')
|
|
166
|
+
const updated = original.replace(
|
|
167
|
+
/(TELEMETRY_ENABLED:\s*bool\(\{[\s\S]*?default:\s*)false/,
|
|
168
|
+
'$1true'
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
if (updated === original) {
|
|
172
|
+
console.warn(
|
|
173
|
+
'\nWarning: could not update the TELEMETRY_ENABLED default in src/environment.ts.'
|
|
174
|
+
)
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
fs.writeFileSync(environmentPath, updated)
|
|
179
|
+
console.log('\nTelemetry enabled (TELEMETRY_ENABLED now defaults to true).')
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Replaces the string `default` of an envalid `str({ ... })` field in the
|
|
184
|
+
* cloned country config's environment. Returns the updated source, or the
|
|
185
|
+
* original source (with a warning) when the field could not be located.
|
|
186
|
+
*/
|
|
187
|
+
function setEnvironmentStringDefault(source, key, value) {
|
|
188
|
+
const pattern = new RegExp(
|
|
189
|
+
`(${key}:\\s*str\\(\\{[\\s\\S]*?default:\\s*)'[^']*'`
|
|
190
|
+
)
|
|
191
|
+
// Escape for a single-quoted TS string literal, and use a function replacer
|
|
192
|
+
// so `$` in the value is not treated as a replacement pattern.
|
|
193
|
+
const literal = "'" + value.replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'"
|
|
194
|
+
const updated = source.replace(pattern, (_, prefix) => prefix + literal)
|
|
195
|
+
|
|
196
|
+
if (updated === source) {
|
|
197
|
+
console.warn(
|
|
198
|
+
`\nWarning: could not update the ${key} default in src/environment.ts.`
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return updated
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Writes the given organisation name and alpha-3 country code as the defaults
|
|
207
|
+
* for the `ORGANISATION` and `COUNTRY_CODE` env vars in the cloned country
|
|
208
|
+
* config's environment.
|
|
209
|
+
*/
|
|
210
|
+
function setTelemetryIdentityInEnvironment(
|
|
211
|
+
targetPath,
|
|
212
|
+
{ organisation, countryCode }
|
|
213
|
+
) {
|
|
214
|
+
const environmentPath = path.join(targetPath, 'src', 'environment.ts')
|
|
215
|
+
if (!fs.existsSync(environmentPath)) {
|
|
216
|
+
console.warn(
|
|
217
|
+
'\nWarning: could not find src/environment.ts; organisation and country code defaults not changed.'
|
|
218
|
+
)
|
|
219
|
+
return
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
let source = fs.readFileSync(environmentPath, 'utf-8')
|
|
223
|
+
source = setEnvironmentStringDefault(source, 'ORGANISATION', organisation)
|
|
224
|
+
source = setEnvironmentStringDefault(source, 'COUNTRY_CODE', countryCode)
|
|
225
|
+
fs.writeFileSync(environmentPath, source)
|
|
226
|
+
}
|
|
227
|
+
|
|
67
228
|
function updatePackageJsonName(targetPath, newName) {
|
|
68
229
|
console.log('\nUpdating package.json with project name: ' + newName + '\n')
|
|
69
230
|
|
|
@@ -110,12 +271,16 @@ async function main() {
|
|
|
110
271
|
ensureTargetDirectoryDoesNotExist(countryconfigDirName)
|
|
111
272
|
ensureTargetDirectoryDoesNotExist(infrastructureDirName)
|
|
112
273
|
|
|
274
|
+
// Gather all answers up front so the operator isn't interrupted mid-clone.
|
|
275
|
+
const organisation = await promptOrganisation()
|
|
276
|
+
const countryCode = await promptCountryCode()
|
|
277
|
+
const telemetryEnabled = await promptEnableTelemetry()
|
|
278
|
+
|
|
113
279
|
try {
|
|
114
280
|
await cloneRepository(
|
|
115
281
|
{
|
|
116
282
|
repository: CORE_REPOSITORY,
|
|
117
|
-
repositorySubPath: COUNTRYCONFIG_TEMPLATE_REPOSITORY_SUBPATH
|
|
118
|
-
branch: 'ocrvs-13179' // @todo: remove this hardcoded branch once the countryconfig-template is merged into main
|
|
283
|
+
repositorySubPath: COUNTRYCONFIG_TEMPLATE_REPOSITORY_SUBPATH
|
|
119
284
|
},
|
|
120
285
|
countryconfigTargetPath
|
|
121
286
|
)
|
|
@@ -136,6 +301,15 @@ async function main() {
|
|
|
136
301
|
process.exit(1)
|
|
137
302
|
}
|
|
138
303
|
|
|
304
|
+
setTelemetryIdentityInEnvironment(countryconfigTargetPath, {
|
|
305
|
+
organisation,
|
|
306
|
+
countryCode
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
if (telemetryEnabled) {
|
|
310
|
+
enableTelemetryInEnvironment(countryconfigTargetPath)
|
|
311
|
+
}
|
|
312
|
+
|
|
139
313
|
console.log('\nDone! Your project has been set up in two directories:\n')
|
|
140
314
|
console.log(' ./' + countryconfigDirName + ' -- country configuration')
|
|
141
315
|
console.log(' ./' + infrastructureDirName + ' -- server infrastructure\n')
|