@itentialopensource/adapter-winston_syslog 1.0.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.
Files changed (45) hide show
  1. package/.eslintignore +5 -0
  2. package/.eslintrc.js +18 -0
  3. package/.jshintrc +3 -0
  4. package/CHANGELOG.md +9 -0
  5. package/LICENSE +201 -0
  6. package/README.md +285 -0
  7. package/adapter.js +250 -0
  8. package/adapterBase.js +1782 -0
  9. package/entities/.generic/action.json +214 -0
  10. package/entities/.generic/schema.json +28 -0
  11. package/entities/.system/action.json +50 -0
  12. package/entities/.system/mockdatafiles/getToken-default.json +3 -0
  13. package/entities/.system/mockdatafiles/healthcheck-default.json +3 -0
  14. package/entities/.system/schema.json +19 -0
  15. package/entities/.system/schemaTokenReq.json +53 -0
  16. package/entities/.system/schemaTokenResp.json +53 -0
  17. package/error.json +190 -0
  18. package/package.json +87 -0
  19. package/pronghorn.json +93 -0
  20. package/propertiesDecorators.json +14 -0
  21. package/propertiesSchema.json +1243 -0
  22. package/refs?service=git-upload-pack +0 -0
  23. package/report/adapterInfo.json +10 -0
  24. package/sampleProperties.json +60 -0
  25. package/test/integration/adapterTestIntegration.js +329 -0
  26. package/test/unit/adapterBaseTestUnit.js +949 -0
  27. package/test/unit/adapterTestUnit.js +1207 -0
  28. package/utils/adapterInfo.js +206 -0
  29. package/utils/addAuth.js +94 -0
  30. package/utils/artifactize.js +146 -0
  31. package/utils/basicGet.js +50 -0
  32. package/utils/checkMigrate.js +63 -0
  33. package/utils/entitiesToDB.js +179 -0
  34. package/utils/findPath.js +74 -0
  35. package/utils/modify.js +154 -0
  36. package/utils/packModificationScript.js +35 -0
  37. package/utils/patches2bundledDeps.js +90 -0
  38. package/utils/pre-commit.sh +30 -0
  39. package/utils/removeHooks.js +20 -0
  40. package/utils/setup.js +33 -0
  41. package/utils/tbScript.js +184 -0
  42. package/utils/tbUtils.js +469 -0
  43. package/utils/testRunner.js +298 -0
  44. package/utils/troubleshootingAdapter.js +190 -0
  45. package/workflows/README.md +3 -0
@@ -0,0 +1,184 @@
1
+ /* eslint-disable no-console */
2
+ /* eslint import/no-unresolved: warn */
3
+ /* eslint global-require: warn */
4
+
5
+ // suppress eslint rule in adapter
6
+ /* eslint arrow-parens: warn */
7
+ /* eslint import/no-extraneous-dependencies: warn */
8
+ /* eslint import/no-dynamic-require: warn */
9
+
10
+ const program = require('commander');
11
+ const rls = require('readline-sync');
12
+ const utils = require('./tbUtils');
13
+ const basicGet = require('./basicGet');
14
+ const { name } = require('../package.json');
15
+ const sampleProperties = require('../sampleProperties.json');
16
+ const adapterPronghorn = require('../pronghorn.json');
17
+ const { addAuthInfo } = require('./addAuth');
18
+
19
+ const { troubleshoot, offline } = require('./troubleshootingAdapter');
20
+
21
+ const executeInStandaloneMode = async (command) => {
22
+ console.info('\n> Executing the script outside of IAP installation directory');
23
+ console.info('> Using sampleProperties.json configuration');
24
+ switch (command) {
25
+ case 'install': {
26
+ console.error('Not currently in IAP directory - installation not possible');
27
+ break;
28
+ }
29
+ case 'connectivity': {
30
+ const { host } = sampleProperties.properties;
31
+ console.log(`perform networking diagnositics to ${host}`);
32
+ utils.runConnectivity(host);
33
+ break;
34
+ }
35
+ case 'healthcheck': {
36
+ const a = basicGet.getAdapterInstance({ properties: sampleProperties });
37
+ await utils.healthCheck(a);
38
+ break;
39
+ }
40
+ case 'basicget': {
41
+ utils.runBasicGet();
42
+ break;
43
+ }
44
+ default: {
45
+ if (rls.keyInYN('Troubleshooting without IAP?')) {
46
+ await offline();
47
+ }
48
+ }
49
+ }
50
+ process.exit(0);
51
+ };
52
+
53
+ const executeUnderIAPInstallationDirectory = async (command) => {
54
+ if (command === undefined) {
55
+ await troubleshoot({}, true, true);
56
+ } else if (command === 'install') {
57
+ const { database, serviceItem, pronghornProps } = await utils.getAdapterConfig();
58
+ const filter = { id: pronghornProps.id };
59
+ const profileItem = await database.collection(utils.IAP_PROFILES_COLLECTION).findOne(filter);
60
+ if (!profileItem) {
61
+ console.log(`Could not find IAP profile for id ${pronghornProps.id}`);
62
+ process.exit(0);
63
+ }
64
+ if (serviceItem) {
65
+ console.log(`A service by the name ${name} already exits!`);
66
+ if (rls.keyInYN(`Do you want to completely remove ${name}?`)) {
67
+ console.log(`Removing ${name} from db...`);
68
+ await database.collection(utils.SERVICE_CONFIGS_COLLECTION).deleteOne({ model: name });
69
+ console.log(`${name} removed from db.`);
70
+ if (profileItem.services.includes(serviceItem.name)) {
71
+ const serviceIndex = profileItem.services.indexOf(serviceItem.name);
72
+ profileItem.services.splice(serviceIndex, 1);
73
+ const update = { $set: { services: profileItem.services } };
74
+ await database.collection(utils.IAP_PROFILES_COLLECTION).updateOne(
75
+ { id: pronghornProps.id }, update
76
+ );
77
+ console.log(`${serviceItem.name} removed from profileItem.services.`);
78
+ console.log(`Rerun the script to reinstall ${serviceItem.name}.`);
79
+ process.exit(0);
80
+ } else {
81
+ process.exit(0);
82
+ }
83
+ } else {
84
+ console.log('Exiting...');
85
+ process.exit(0);
86
+ }
87
+ } else {
88
+ const dirname = utils.getCurrentExecutionPath();
89
+ utils.verifyInstallationDir(dirname, name);
90
+ utils.runTest();
91
+ if (rls.keyInYN(`Do you want to install ${name} to IAP?`)) {
92
+ console.log('Creating database entries...');
93
+ const adapter = utils.createAdapter(
94
+ pronghornProps, profileItem, sampleProperties, adapterPronghorn
95
+ );
96
+
97
+ adapter.properties.properties = await addAuthInfo(adapter.properties.properties);
98
+
99
+ await database.collection(utils.SERVICE_CONFIGS_COLLECTION).insertOne(adapter);
100
+ profileItem.services.push(adapter.name);
101
+ const update = { $set: { services: profileItem.services } };
102
+ await database.collection(utils.IAP_PROFILES_COLLECTION).updateOne(
103
+ { id: pronghornProps.id }, update
104
+ );
105
+ console.log('Database entry creation complete.');
106
+ }
107
+ console.log('Exiting...');
108
+ process.exit(0);
109
+ }
110
+ } else if (['healthcheck', 'basicget', 'connectivity'].includes(command)) {
111
+ const { serviceItem } = await utils.getAdapterConfig();
112
+ if (serviceItem) {
113
+ const adapter = serviceItem;
114
+ const a = basicGet.getAdapterInstance(adapter);
115
+ if (command === 'healthcheck') {
116
+ await utils.healthCheck(a);
117
+ process.exit(0);
118
+ } else if (command === 'basicget') {
119
+ await utils.runBasicGet(true);
120
+ } else if (command === 'connectivity') {
121
+ const { host } = adapter.properties.properties;
122
+ console.log(`perform networking diagnositics to ${host}`);
123
+ await utils.runConnectivity(host, true);
124
+ process.exit(0);
125
+ }
126
+ } else {
127
+ console.log(`${name} not installed. Run npm \`run install:adapter\` to install.`);
128
+ process.exit(0);
129
+ }
130
+ }
131
+ };
132
+
133
+ const main = async (command) => {
134
+ if (!utils.areWeUnderIAPinstallationDirectory()) {
135
+ executeInStandaloneMode(command); // configuration from sampleproperties.json
136
+ } else {
137
+ executeUnderIAPInstallationDirectory(command); // configuration from $IAP_HOME/properties.json
138
+ }
139
+ };
140
+
141
+ program
142
+ .command('connectivity')
143
+ .alias('c')
144
+ .description('networking diagnostics')
145
+ .action(() => {
146
+ main('connectivity');
147
+ });
148
+
149
+ program
150
+ .command('install')
151
+ .alias('i')
152
+ .description('install current adapter')
153
+ .action(() => {
154
+ main('install');
155
+ });
156
+
157
+ program
158
+ .command('healthcheck')
159
+ .alias('hc')
160
+ .description('perfom none interative healthcheck with current setting')
161
+ .action(() => {
162
+ main('healthcheck');
163
+ });
164
+
165
+ program
166
+ .command('basicget')
167
+ .alias('bg')
168
+ .description('perfom basicget')
169
+ .action(() => {
170
+ main('basicget');
171
+ });
172
+
173
+ // Allow commander to parse `process.argv`
174
+ program.parse(process.argv);
175
+
176
+ if (process.argv.length < 3) {
177
+ main();
178
+ }
179
+ const allowedParams = ['install', 'healthcheck', 'basicget', 'connectivity'];
180
+ if (process.argv.length === 3 && !allowedParams.includes(process.argv[2])) {
181
+ console.log(`unknown parameter ${process.argv[2]}`);
182
+ console.log('try `node troubleshootingAdapter.js -h` to see allowed parameters. Exiting...');
183
+ process.exit(0);
184
+ }
@@ -0,0 +1,469 @@
1
+ /* @copyright Itential, LLC 2020 */
2
+
3
+ /* eslint import/no-extraneous-dependencies: warn */
4
+ /* eslint global-require: warn */
5
+ /* eslint import/no-dynamic-require: warn */
6
+ /* eslint-disable no-console */
7
+
8
+ const path = require('path');
9
+ const fs = require('fs-extra');
10
+ const cp = require('child_process');
11
+
12
+ module.exports = {
13
+ SERVICE_CONFIGS_COLLECTION: 'service_configs',
14
+ IAP_PROFILES_COLLECTION: 'iap_profiles',
15
+
16
+ /**
17
+ * @summary update newConnection properties in adapter config
18
+ *
19
+ * @function updateNewConnection
20
+ * @param {Object} config - adaper configuration object required by IAP
21
+ * @param {Object} newConnection - connection related property collection from user
22
+ */
23
+ updateNewConnection: (config, newConnection) => {
24
+ const updatedConfig = JSON.parse(JSON.stringify(config));
25
+ Object.keys(newConnection).forEach((key) => {
26
+ updatedConfig.properties.properties[key] = newConnection[key];
27
+ });
28
+ return updatedConfig;
29
+ },
30
+
31
+ /**
32
+ * @summary assemble heathcheck endpoint into an URL
33
+ *
34
+ * @function getHealthCheckEndpointURL
35
+ * @param {Object} endpoint - user updated healthcheck endpoint object
36
+ * @param {Object} config - adaper configuration object required by IAP
37
+ */
38
+ getHealthCheckEndpointURL: (endpoint, config) => {
39
+ const p = config.properties.properties;
40
+ const healthCheckEndpointURL = `${p.protocol}://${p.host}${p.base_path}${p.version}${endpoint.healthCheckEndpoint}`;
41
+ console.log({ healthCheckEndpointURL });
42
+ return healthCheckEndpointURL;
43
+ },
44
+
45
+ /**
46
+ * @summary persist healthcheck endpoint when user make update
47
+ *
48
+ * @function updateHealthCheckEndpoint
49
+ * @param {Object} newHealthCheckEndpoint - user confirmed healthcheck object
50
+ * @param {Object} healthCheckEndpoint - existing healthcheck object
51
+ * @param {Object} healthcheck - ./entities/.system/action.json object
52
+ */
53
+ updateHealthCheckEndpoint: (newHealthCheckEndpoint, healthCheckEndpoint, healthcheck) => {
54
+ if (newHealthCheckEndpoint.healthCheckEndpoint !== healthCheckEndpoint.healthCheckEndpoint) {
55
+ const p = healthcheck.actions[1].entitypath;
56
+ const newEntitypath = p.slice(0, 21) + newHealthCheckEndpoint.healthCheckEndpoint + p.slice(p.length - 8);
57
+ const updatedHealthcheck = JSON.parse(JSON.stringify(healthcheck));
58
+ updatedHealthcheck.actions[1].entitypath = newEntitypath;
59
+ console.log('updating healthcheck setting');
60
+ fs.writeFileSync('./entities/.system/action.json', JSON.stringify(updatedHealthcheck, null, 2));
61
+ }
62
+ },
63
+
64
+ /**
65
+ * @summary update authentication property given new input value from user
66
+ * compare values from auth and newAuth, if there's difference
67
+ * update adapter config
68
+ * @function updateAuth
69
+ * @param {Object} newAuth - user confirmed authentication object
70
+ * @param {Object} auth - existing authentication object
71
+ * @param {Object} config - adaper configuration object required by IAP
72
+ */
73
+ updateAuth: (newAuth, auth, config) => {
74
+ const updatedConfig = JSON.parse(JSON.stringify(config));
75
+ if (Object.keys(newAuth).every((key) => newAuth[key] === auth[key])) {
76
+ return config;
77
+ }
78
+ Object.keys(newAuth).forEach((key) => {
79
+ updatedConfig.properties.properties.authentication[key] = newAuth[key];
80
+ });
81
+ console.log(updatedConfig.properties.properties.authentication);
82
+ return updatedConfig;
83
+ },
84
+
85
+ /**
86
+ * @summary add mark current auth_method with `(current)`
87
+ *
88
+ * @function getDisplayAuthOptions
89
+ * @param {String} currentAuth - current auth method in adapter config
90
+ * @param {Array} authOptions - available auth method
91
+ */
92
+ getDisplayAuthOptions: (currentAuth, authOptions) => {
93
+ const displayAuthOptions = JSON.parse(JSON.stringify(authOptions));
94
+ displayAuthOptions[authOptions.indexOf(currentAuth)] += ' (current)';
95
+ return displayAuthOptions;
96
+ },
97
+
98
+ /**
99
+ * @summary decrypt IAP properties
100
+ * code from pronghorn-core/migration_scripts/installService.js
101
+ *
102
+ * @function decryptProperties
103
+ */
104
+ decryptProperties: (props, iapDir, discovery) => {
105
+ const propertyEncryptionClassPath = path.join(iapDir, 'node_modules/@itential/pronghorn-core/core/PropertyEncryption.js');
106
+ const isEncrypted = props.pathProps.encrypted;
107
+ const PropertyEncryption = discovery.require(propertyEncryptionClassPath, isEncrypted);
108
+ const propertyEncryption = new PropertyEncryption({
109
+ algorithm: 'aes-256-ctr',
110
+ key: 'TG9uZ0Rpc3RhbmNlUnVubmVyUHJvbmdob3JuCg==',
111
+ encoding: 'utf-8'
112
+ });
113
+ return propertyEncryption.decryptProps(props);
114
+ },
115
+
116
+ /**
117
+ * @summary create connection object for verification
118
+ *
119
+ * @function getConnection
120
+ * @param {Object} props - adapter config.properties
121
+ */
122
+ getConnection: (props) => {
123
+ const connection = {
124
+ host: props.properties.host,
125
+ base_path: props.properties.base_path,
126
+ protocol: props.properties.protocol,
127
+ version: props.properties.version,
128
+ port: props.properties.port
129
+ };
130
+ return connection;
131
+ },
132
+
133
+ /**
134
+ * @summary update connection properties based on user answer
135
+ *
136
+ * @function getNewProps
137
+ * @param {Array} answers - values collected from CLI
138
+ * @param {Object} connection - connection property verified by user
139
+ */
140
+ getNewProps: (answers, connection) => {
141
+ if (answers.every((answer) => answer === '')) {
142
+ return connection;
143
+ }
144
+ const newConnection = {};
145
+ const properties = Object.keys(connection);
146
+ for (let i = 0; i < answers.length; i += 1) {
147
+ if (answers[i]) {
148
+ newConnection[properties[i]] = Number.isNaN(Number(answers[i])) ? answers[i] : Number(answers[i]);
149
+ } else {
150
+ newConnection[properties[i]] = connection[properties[i]];
151
+ }
152
+ }
153
+ return newConnection;
154
+ },
155
+
156
+ /**
157
+ * @summary extract endpoint string from healthcheck object
158
+ *
159
+ * @function getHealthCheckEndpoint
160
+ * @param {Object} healthcheck - {Object} healthcheck - ./entities/.system/action.json object
161
+ */
162
+ getHealthCheckEndpoint: (healthcheck) => {
163
+ const endpoint = healthcheck.actions[1].entitypath.slice(21,
164
+ healthcheck.actions[1].entitypath.length - 8);
165
+ return { healthCheckEndpoint: endpoint };
166
+ },
167
+
168
+ /**
169
+ * @summary Verify that the adapter is in the correct directory
170
+ * - Within IAP
171
+ * - In node_modules/@ namespace
172
+ * verify the adapter is installed under node_modules/
173
+ * and is consistent with the name property of package.json
174
+ * and the node_modules/ is in the correct path within IAP
175
+ * @param {String} dirname - current path
176
+ * @param {String} name - name property from package.json
177
+ */
178
+ verifyInstallationDir: (dirname, name) => {
179
+ const pathArray = dirname.split(path.sep);
180
+ const expectedPath = `node_modules/${name}`;
181
+ const currentPath = pathArray.slice(pathArray.length - 3, pathArray.length).join('/');
182
+ if (currentPath.trim() !== expectedPath.trim()) {
183
+ throw new Error(`adapter should be installed under ${expectedPath} but is installed under ${currentPath}`);
184
+ }
185
+
186
+ const serverFile = path.join(dirname, '../../../', 'server.js');
187
+ if (!fs.existsSync(serverFile)) {
188
+ throw new Error(`adapter should be installed under IAP/${expectedPath}`);
189
+ }
190
+ console.log(`adapter correctly installed at ${currentPath}`);
191
+ },
192
+
193
+ /**
194
+ * @summary execute command and preserve the output the same as run command in shell
195
+ *
196
+ * @function systemSync
197
+ * @param {String} cmd - Command to execute
198
+ * @param {boolean} process - Whether stdout should be processed and returned
199
+ */
200
+ systemSync: function systemSync(cmd, process) {
201
+ if (process) {
202
+ let stdout;
203
+ try {
204
+ stdout = cp.execSync(cmd).toString();
205
+ } catch (error) {
206
+ stdout = error.stdout.toString();
207
+ }
208
+ const output = this.getTestCount(stdout);
209
+ output.stdout = stdout;
210
+ return output;
211
+ }
212
+ try {
213
+ return cp.execSync(cmd, { stdio: 'inherit' });
214
+ } catch (error) {
215
+ return console.error(error.stdout);
216
+ }
217
+ },
218
+
219
+ /**
220
+ * @summary parses a string and returns the number parsed from startIndex backwards
221
+ *
222
+ * @function parseNum
223
+ * @param {String} inputStr - Any String
224
+ * @param {Number} startIndex - Index to begin parsing
225
+ */
226
+ parseNum: function parseNum(inputStr, startIndex) {
227
+ let count = '';
228
+ let currChar;
229
+ let start = startIndex;
230
+ while (currChar !== ' ') {
231
+ currChar = inputStr.charAt(start);
232
+ count = currChar + count;
233
+ start -= 1;
234
+ }
235
+ return parseInt(count, 10);
236
+ },
237
+
238
+ /**
239
+ * @summary Parses a mocha test result and returns the count of passing and failing tests
240
+ *
241
+ * @function getTestCount
242
+ * @param {String} testStr - Output from mocha test
243
+ */
244
+ getTestCount: function getTestCount(testStr) {
245
+ const passIndex = testStr.search('passing');
246
+ const failIndex = testStr.search('failing');
247
+ const passCount = passIndex >= 0 ? this.parseNum(testStr, passIndex - 2) : 0;
248
+ const failCount = failIndex >= 0 ? this.parseNum(testStr, failIndex - 2) : 0;
249
+ return { passCount, failCount };
250
+ },
251
+
252
+ /**
253
+ * @summary remove package-lock.json and node_modules directory if exists
254
+ * run npm install and print result to stdout
255
+ */
256
+ npmInstall: function npmInstall() {
257
+ fs.removeSync('../package-lock.json');
258
+ fs.removeSync('../node_modules/');
259
+ console.log('Run npm install ...');
260
+ this.systemSync('npm install');
261
+ },
262
+
263
+ /**
264
+ * @summary run lint, unit test and integration test
265
+ * print result to stdout
266
+ */
267
+ runTest: function runTest() {
268
+ this.systemSync('npm run lint:errors');
269
+ this.systemSync('npm run test:unit');
270
+ this.systemSync('npm run test:integration');
271
+ },
272
+
273
+ /**
274
+ * @summary run basicget with mocha
275
+ * @param {boolean} scriptFlag - whether the function is ran from a script
276
+ * print result to stdout
277
+ * returns mocha test results otherwise
278
+ */
279
+ runBasicGet: function runBasicGet(scriptFlag) {
280
+ const testPath = path.resolve(__dirname, '..', 'test/integration/adapterTestBasicGet.js');
281
+ return this.systemSync(`mocha ${testPath} --exit`, !scriptFlag);
282
+ },
283
+
284
+ /**
285
+ * @summary run connectivity with mocha
286
+ * @param {String} host - Host url to run healthcheck
287
+ * @param {boolean} scriptFlag - Whether the function is ran from a script
288
+ * print result to stdout if ran from script
289
+ * returns mocha test results otherwise
290
+ */
291
+ runConnectivity: function runConnectivity(host, scriptFlag) {
292
+ let testPath = 'test/integration/adapterTestConnectivity.js';
293
+ if (!scriptFlag) {
294
+ testPath = path.resolve(__dirname, '..', testPath);
295
+ }
296
+ return this.systemSync(`mocha ${testPath} --HOST=${host} --timeout 10000 --exit`, !scriptFlag);
297
+ },
298
+
299
+ /**
300
+ * @summary create Adapter property
301
+ *
302
+ * @function createAdapter
303
+ * @param {Object} pronghornProps - decrypted 'properties.json' from IAP root directory
304
+ * @param {Object} profileItem - pronghorn props saved in database
305
+ * @param {Object} adapterPronghorn - ./pronghorn.json in adapter dir
306
+ * @param {Object} sampleProperties - './sampleProperties.json' in adapter dir
307
+ */
308
+ createAdapter: function createAdapter(pronghornProps, profileItem, sampleProperties, adapterPronghorn) {
309
+ const iapDir = this.getIAPHome();
310
+ const packageFile = path.join(iapDir, 'package.json');
311
+ const info = JSON.parse(fs.readFileSync(packageFile));
312
+ const version = parseInt(info.version.split('.')[0], 10);
313
+
314
+ let adapter = {};
315
+ if (version >= 2020) {
316
+ adapter = {
317
+ isEncrypted: pronghornProps.pathProps.encrypted,
318
+ model: adapterPronghorn.id,
319
+ name: sampleProperties.id,
320
+ type: adapterPronghorn.type,
321
+ properties: sampleProperties,
322
+ loggerProps: profileItem.loggerProps
323
+ };
324
+ } else {
325
+ adapter = {
326
+ mongoProps: pronghornProps.mongoProps,
327
+ isEncrypted: pronghornProps.pathProps.encrypted,
328
+ model: adapterPronghorn.id,
329
+ name: sampleProperties.id,
330
+ type: adapterPronghorn.type,
331
+ properties: sampleProperties,
332
+ redisProps: profileItem.redisProps,
333
+ loggerProps: profileItem.loggerProps,
334
+ rabbitmq: profileItem.rabbitmq
335
+ };
336
+ adapter.mongoProps.pdb = true;
337
+ }
338
+
339
+ adapter.loggerProps.log_filename = `adapter-${adapter.name}.log`;
340
+ return adapter;
341
+ },
342
+
343
+ getPronghornProps: function getPronghornProps(iapDir) {
344
+ console.log('Retrieving properties.json file...');
345
+ const rawProps = require(path.join(iapDir, 'properties.json'));
346
+ console.log('Decrypting properties...');
347
+ const { Discovery } = require(path.join(iapDir, 'node_modules/@itential/itential-utils'));
348
+ const discovery = new Discovery();
349
+ const pronghornProps = this.decryptProperties(rawProps, iapDir, discovery);
350
+ console.log('Found properties.\n');
351
+ return pronghornProps;
352
+ },
353
+
354
+ // get database connection and existing adapter config
355
+ getAdapterConfig: async function getAdapterConfig() {
356
+ const iapDir = this.getIAPHome();
357
+ const pronghornProps = this.getPronghornProps(iapDir);
358
+ console.log('Connecting to Database...');
359
+ const database = await this.connect(iapDir, pronghornProps);
360
+ console.log('Connection established.');
361
+ const { name } = require(path.join(__dirname, '..', 'package.json'));
362
+ const serviceItem = await database.collection(this.SERVICE_CONFIGS_COLLECTION).findOne(
363
+ { model: name }
364
+ );
365
+ return { database, serviceItem, pronghornProps };
366
+ },
367
+
368
+ /**
369
+ * @summary return async healthcheck result as a Promise
370
+ *
371
+ * @function request
372
+ * @param {Adapter} a - Adapter instance
373
+ */
374
+ request: function request(a) {
375
+ return new Promise((resolve, reject) => {
376
+ a.healthCheck(null, (data) => {
377
+ if (!data) reject(new Error('healthCheckEndpoint failed'));
378
+ resolve(data);
379
+ });
380
+ });
381
+ },
382
+
383
+ /**
384
+ * @summary deal with healthcheck response returned from adapter instace
385
+ *
386
+ * @function healthCheck
387
+ * @param {Adapter} a - Adapter instance
388
+ */
389
+ healthCheck: async function healthCheck(a) {
390
+ const result = await this.request(a)
391
+ .then((res) => {
392
+ console.log('healthCheckEndpoint OK');
393
+ return res;
394
+ })
395
+ .catch((error) => {
396
+ console.error(error.message);
397
+ return false;
398
+ });
399
+ return result;
400
+ },
401
+
402
+ /**
403
+ * @summary Obtain the IAP installation directory depending on how adapter is used:
404
+ * by IAP, or by npm run CLI interface
405
+ * @returns IAP installation directory or null if adapter running without IAP
406
+ * @function getIAPHome
407
+ */
408
+ getIAPHome: function getIAPHome() {
409
+ let IAPHomePath = null;
410
+ // check if adapter started via IAP, use path injected by core
411
+ if (process.env.iap_home) IAPHomePath = process.env.iap_home;
412
+ // check if adapter started via CLI `npm run <command>` so we have to be located under
413
+ // <IAP_HOME>/node_modules/@itentialopensource/<adapter_name>/ directory
414
+ const currentExecutionPath = this.getCurrentExecutionPath();
415
+ if (currentExecutionPath.indexOf('/node_modules') >= 0) {
416
+ [IAPHomePath] = currentExecutionPath.split('/node_modules');
417
+ }
418
+ return IAPHomePath;
419
+ },
420
+
421
+ /**
422
+ * @summary get current execution path without resolving symbolic links,
423
+ * use `pwd` command wihout '-P' option (resolving symlinks) https://linux.die.net/man/1/pwd
424
+ * @returns
425
+ * @function getCurrentExecutionPAth
426
+ */
427
+ getCurrentExecutionPath: function getCurrentExecutionPAth() {
428
+ const { stdout } = this.systemSync('pwd', true);
429
+ return stdout.trim();
430
+ },
431
+
432
+ /**
433
+ * @summary checks if command executed from <IAP_HOME>/node_modules/@itentialopensource/<adapter_name>/ location
434
+ * @returns true if command executed under <IAP_HOME>/node_modules/@itentialopensource/<adapter_name>/ path
435
+ * @function areWeUnderIAPinstallationDirectory
436
+ */
437
+ areWeUnderIAPinstallationDirectory: function areWeUnderIAPinstallationDirectory() {
438
+ return path.join(this.getCurrentExecutionPath(), '../../..') === this.getIAPHome();
439
+ },
440
+
441
+ /**
442
+ * @summary connect to mongodb
443
+ *
444
+ * @function connect
445
+ * @param {Object} properties - pronghornProps
446
+ */
447
+ connect: async function connect(iapDir, properties) {
448
+ let dbConnectionProperties = {};
449
+ if (properties.mongoProps) {
450
+ dbConnectionProperties = properties.mongoProps;
451
+ } else if (properties.mongo) {
452
+ if (properties.mongo.url) {
453
+ dbConnectionProperties.url = properties.mongo.url;
454
+ } else {
455
+ dbConnectionProperties.url = `mongodb://${properties.mongo.host}:${properties.mongo.port}`;
456
+ }
457
+ dbConnectionProperties.db = properties.mongo.database;
458
+ }
459
+ if (!dbConnectionProperties.url || !dbConnectionProperties.db) {
460
+ throw new Error('Mongo properties are not specified in IAP configuration!');
461
+ }
462
+
463
+ const { MongoDBConnection } = require(path.join(iapDir, 'node_modules/@itential/database'));
464
+ const connection = new MongoDBConnection(dbConnectionProperties);
465
+ const database = await connection.connect(true);
466
+ return database;
467
+ }
468
+
469
+ };