@slingr/slingr-services 0.0.5

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.
@@ -0,0 +1,93 @@
1
+ const definitions = require('../configuration/configuration').definitions;
2
+ const httpModule = require('../httpModule/httpModule');
3
+
4
+ const DATASTORES_API_PATH = '/services/dataStores/';
5
+
6
+ const isEmpty = (obj) => {
7
+ return obj
8
+ && Object.keys(obj).length === 0
9
+ && Object.getPrototypeOf(obj) === Object.prototype;
10
+ }
11
+
12
+ const dataStores = {
13
+ find: async (dataStoreName, filter) => {
14
+ if (isEmpty(filter)) filter = null;
15
+ const dataStoreResponse = await httpModule.get(DATASTORES_API_PATH+dataStoreName,{
16
+ params: {
17
+ ...filter
18
+ }
19
+ });
20
+ return dataStoreResponse.data;
21
+ },
22
+ findById: async (dataStoreName,documentId) => {
23
+ if (!documentId || documentId === '') throw new Error('The documentId can\'t be empty');
24
+ const dataStoreResponse = await httpModule.get(DATASTORES_API_PATH+dataStoreName+'/'+documentId);
25
+ return dataStoreResponse.data;
26
+ },
27
+ save: async (dataStoreName,document) => {
28
+ if (isEmpty(document)) throw new Error('The document to save can\'t be empty');
29
+ const dataStoreResponse = await httpModule.post(DATASTORES_API_PATH+dataStoreName,document);
30
+ return dataStoreResponse.data;
31
+ },
32
+ update: async (dataStoreName,documentId,newDocument) => {
33
+ if (!documentId) throw new Error('The documentId can\'t be empty');
34
+ if (isEmpty(newDocument)) throw new Error('The document to update can\'t be empty');
35
+ const dataStoreResponse = await httpModule.put(DATASTORES_API_PATH+dataStoreName+'/'+documentId,newDocument);
36
+ return dataStoreResponse.data;
37
+ },
38
+ remove: async (dataStoreName,filter) => {
39
+ if (isEmpty(filter)) filter = null;
40
+ const dataStoreResponse = await httpModule.delete(DATASTORES_API_PATH+dataStoreName,{
41
+ params: {
42
+ ...filter
43
+ }
44
+ });
45
+ return dataStoreResponse.data;
46
+ },
47
+ removeById: async (dataStoreName,documentId) => {
48
+ if (!documentId || documentId === '') throw new Error('The documentId can\'t be empty');
49
+ const dataStoreResponse = await httpModule.delete(DATASTORES_API_PATH+dataStoreName+'/'+documentId);
50
+ return dataStoreResponse.data;
51
+ },
52
+ count: async (dataStoreName, filter) => {
53
+ if (isEmpty(filter)) filter = null;
54
+ const dataStoreResponse = await httpModule.get(DATASTORES_API_PATH+dataStoreName+'/count',{
55
+ params: {
56
+ ...filter
57
+ }
58
+ });
59
+ return dataStoreResponse.data;
60
+ }
61
+ };
62
+
63
+ for (const dataStore of definitions.stores) {
64
+ const dataStoreName = dataStore.name;
65
+ dataStores[dataStoreName] = {
66
+ find: async (filter) => {
67
+ return await dataStores.find(dataStoreName,filter);
68
+ },
69
+ findOne: async (filter) => {
70
+ return (await dataStores.find(dataStoreName,filter)).items[0];
71
+ },
72
+ findById: async (documentId) => {
73
+ return await dataStores.findById(dataStoreName,documentId);
74
+ },
75
+ save: async (document) => {
76
+ return await dataStores.save(dataStoreName,document);
77
+ },
78
+ update: async (documentId,newDocument) => {
79
+ return await dataStores.update(dataStoreName,documentId,newDocument);
80
+ },
81
+ remove: async (filter) => {
82
+ return await dataStores.remove(filter);
83
+ },
84
+ removeById: async (documentId) => {
85
+ return await dataStores.removeById(dataStoreName,documentId);
86
+ },
87
+ count: async (filter) => {
88
+ return await dataStores.count(dataStoreName,filter);
89
+ }
90
+ }
91
+ }
92
+
93
+ module.exports = dataStores
@@ -0,0 +1,69 @@
1
+ const util = require('util');
2
+ const httpModule = require('../httpModule/httpModule');
3
+ const logger = require('../loggers/logs');
4
+
5
+ const EVENTS_API_PATH = '/services/events';
6
+ const EVENTS_SYNC_API_PATH = '/services/events/sync';
7
+
8
+
9
+ let lastStatistic = null;
10
+
11
+ const handleSendEvent = async (eventName, data, fromFunction, userId, userEmail, isSync) => {
12
+ if (!eventName) {
13
+ throw 'Event name is empty'
14
+ }
15
+ if (!data) {
16
+ data = {}
17
+ }
18
+ let eventBody = {
19
+ date: new Date().getTime(),
20
+ event: eventName,
21
+ data: data,
22
+ ...(fromFunction && { fromFunction: fromFunction }),
23
+ ...(userId && { userId: userId }),
24
+ ...(userEmail && { userEmail: userEmail }),
25
+ };
26
+
27
+ let response = null;
28
+
29
+ if (isSync) {
30
+ response = await httpModule.post(EVENTS_SYNC_API_PATH, eventBody);
31
+ } else {
32
+ httpModule.post(EVENTS_SYNC_API_PATH, eventBody);
33
+ }
34
+ if (!lastStatistic || (new Date() - 3600000) > lastStatistic) {
35
+ lastStatistic = new Date();
36
+ logger.info(">>> mem usage: " + util.inspect(process.memoryUsage(), { showHidden: true, depth: null }));
37
+ }
38
+ return response;
39
+
40
+ }
41
+ //handle sync responses from platform
42
+ const send = (eventName, data, fromFunction, userId, userEmail) => {
43
+ handleSendEvent(eventName, data, fromFunction, userId, userEmail, false).then(
44
+ (data) => {
45
+ logger.debug('[EVENT][' + eventName + '] >> [SENT]')
46
+ }
47
+ ).catch(
48
+ (err) => {
49
+ logger.debug('[EVENT][' + eventName + '] >> [NO SENT]');
50
+ logger.info('Error when try to send event to ES [' + err + ']');
51
+ }
52
+ );
53
+ };
54
+
55
+ const sendSync = async (eventName, data, fromFunction, userId, userEmail) => {
56
+ try {
57
+ let response = await handleSendEvent(eventName, data, fromFunction, userId, userEmail, true);
58
+ logger.debug('[SYNC EVENT][' + eventName + '] >> [SENT]');
59
+ return response.data;
60
+ } catch (error) {
61
+ logger.debug('[SYNC EVENT][' + eventName + '] >> [NO SENT]');
62
+ logger.info('Error when try to send sync event to ES [' + error + ']');
63
+ }
64
+ }
65
+
66
+ module.exports = {
67
+ send,
68
+ sendSync
69
+ }
@@ -0,0 +1,114 @@
1
+ const httpModule = require('../httpModule/httpModule');
2
+ const logger = require('../loggers/logs');
3
+ const appLogger = require('../loggers/appLogs');
4
+ const fs = require('fs');
5
+ const stream = require('node:stream');
6
+ const pStream = stream.promises;
7
+ const FormData = require('form-data');
8
+
9
+ const FILES_API_PATH = '/svcss/files'
10
+ const TMP_FILES_PATH = './tmp/'
11
+
12
+ const clearTmpFile = async (filePath) => {
13
+ fs.unlink(filePath,(err) => {
14
+ if (err) throw err;
15
+ logger.debug(filePath + ' was deleted.');
16
+ });
17
+ }
18
+
19
+ const createTmpFile = async (fileName, fileContents) => {
20
+ const filePath = TMP_FILES_PATH + new Date().getTime() + '_' + (fileName ? fileName : 'file');
21
+ if (!fs.existsSync(TMP_FILES_PATH)) fs.mkdirSync(TMP_FILES_PATH);
22
+
23
+ if (fileContents instanceof stream.Stream){
24
+ const writer = fs.createWriteStream(filePath);
25
+ fileContents.pipe(writer);
26
+ await pStream.finished(writer);
27
+ } else {
28
+ fs.writeFileSync(filePath, fileContents);
29
+ }
30
+ return filePath;
31
+ }
32
+
33
+ const download = async (fileId) => {
34
+ if (!fileId) {
35
+ throw new Error('The file ID cannot be empty when downloading files.');
36
+ }
37
+
38
+ let downloadResponse;
39
+ try {
40
+ downloadResponse = await httpModule.get(FILES_API_PATH + '/' + fileId, {responseType: 'stream'});
41
+ } catch (error) {
42
+ logger.error('Error while downloading file from platform.',error);
43
+ }
44
+ const tmpFilePath = await createTmpFile(fileId, downloadResponse.data);
45
+ const downloadData = fs.readFileSync(tmpFilePath);
46
+ clearTmpFile(tmpFilePath);
47
+ return downloadData;
48
+ };
49
+
50
+ const upload = async (fileName, fileContents) => {
51
+ if (!fileName) {
52
+ logger.error('Cannot upload a file if fileName is empty.');
53
+ appLogger.error('Error while uploading a file because no fileName was provided.');
54
+ return;
55
+ }
56
+ if (!fileContents) {
57
+ logger.error('Cannot upload a file if fileContents is empty.');
58
+ appLogger.error('Error while uploading the file ['+fileName+'] because of empty content.');
59
+ return;
60
+ }
61
+
62
+ let tmpFilePath;
63
+ try {
64
+ tmpFilePath = await createTmpFile(fileName, fileContents);
65
+ } catch (err) {
66
+ logger.error('The temporal file for ['+fileName+']could not be created. The file wont be uploaded to the app.',err);
67
+ appLogger.error('Error while uploading the file ['+fileName+']. It wasn\'t uploaded to the app.');
68
+ return;
69
+ }
70
+
71
+ const formData = new FormData();
72
+ formData.append('file', fs.createReadStream(tmpFilePath));
73
+ let options = {
74
+ headers: {
75
+ ...formData.getHeaders()
76
+ }
77
+ };
78
+
79
+ let fileResponse;
80
+ try {
81
+ fileResponse = await httpModule.post(FILES_API_PATH, formData, options);
82
+ logger.debug('Uploaded file to application');
83
+ } catch (error) {
84
+ logger.info('Error while trying to upload a file to app [' + error + ']');
85
+ appLogger.error('Error while trying to upload a file from service to application');
86
+ return;
87
+ }
88
+ clearTmpFile(tmpFilePath);
89
+ return fileResponse.data;
90
+ };
91
+
92
+ const getFileMetadata = async (fileId) => {
93
+ if (!fileId) {
94
+ logger.error('The fileId cannot be empty when getting files metadata.')
95
+ appLogger.error('Error while getting app metadata because no fileId was provided.')
96
+ return;
97
+ }
98
+
99
+ let metadataResponse;
100
+ try {
101
+ metadataResponse = await httpModule.get(FILES_API_PATH+'/'+fileId+'/metadata');
102
+ } catch (error) {
103
+ logger.info('Error when try to fetch metadata from file [' + fileId + ']');
104
+ appLogger.error('Error when try to fetch metadata from file [' + fileId + ']',error);
105
+ }
106
+ logger.debug('File Metadata fetched.');
107
+ return metadataResponse.data;
108
+ }
109
+
110
+ module.exports = {
111
+ download,
112
+ upload,
113
+ getFileMetadata
114
+ }
@@ -0,0 +1,31 @@
1
+ const https = require('https');
2
+
3
+ const {
4
+ applicationName,
5
+ environment,
6
+ token,
7
+ _extension_broker_api,
8
+ } = require('../configuration/configuration').settings;
9
+ const axiosInstance = require('axios').create(
10
+ {
11
+ baseURL: _extension_broker_api,
12
+ headers: {
13
+ app: applicationName,
14
+ env: environment,
15
+ token: token,
16
+ version: 'v1'
17
+ },
18
+ httpsAgent: new https.Agent({
19
+ rejectUnauthorized: false
20
+ }),
21
+ }
22
+ );
23
+ // require('axios-retry')(
24
+ // httpModule, {
25
+ // retries: 5,
26
+ // retryDelay: 5000,
27
+ // shouldResetTimeout: true
28
+ // }
29
+ // );
30
+
31
+ module.exports = axiosInstance;
@@ -0,0 +1,37 @@
1
+ const logger = require('../loggers/logs');
2
+ const httpModule = require('../httpModule/httpModule');
3
+
4
+ const LOCKS_API_PATH = '/locks/';
5
+
6
+ const acquireLock = async (key) => {
7
+ if(!key) {
8
+ throw new Error('Key can\'t be empty to aquire a lock.');
9
+ }
10
+ let lock;
11
+ try {
12
+ lock = await httpModule.post(LOCKS_API_PATH+key);
13
+ } catch (error) {
14
+ logger.error('Error while triying to get lock for key ['+key+'].')
15
+ throw new Error('Error while triying to get lock for key ['+key+'].')
16
+ }
17
+ return lock;
18
+ }
19
+
20
+ const releaseLock = async (key) => {
21
+ if(!key) {
22
+ throw new Error('Key can\'t be empty to release a lock.');
23
+ }
24
+ let unlock;
25
+ try {
26
+ unlock = await httpModule.delete(LOCKS_API_PATH+key);
27
+ } catch (error) {
28
+ logger.error('Error while triying to release lock for key ['+key+'].')
29
+ throw new Error('Error while triying to release lock for key ['+key+'].')
30
+ }
31
+ return unlock;
32
+ }
33
+
34
+ module.exports = {
35
+ acquireLock,
36
+ releaseLock
37
+ }
@@ -0,0 +1,42 @@
1
+ const
2
+ logger = require('./logs'),
3
+ {
4
+ applicationName,
5
+ svcName,
6
+ environment
7
+ } = require('../configuration/configuration').settings,
8
+ httpModule = require('../httpModule/httpModule');
9
+
10
+ // app log (POST /api/services/logs)
11
+ const sendAppLog = (level, message, additionalInfo) => {
12
+ if (!additionalInfo) {
13
+ additionalInfo = {}
14
+ }
15
+ additionalInfo.app = applicationName;
16
+ additionalInfo.svc = svcName;
17
+ additionalInfo.env = environment;
18
+
19
+ let appLog = {
20
+ date: +new Date(),
21
+ level: level,
22
+ message: message,
23
+ additionalInfo: additionalInfo
24
+ };
25
+ httpModule.post('/services/logs', appLog)
26
+ .then(body => logger.debug('[APP LOG][' + level + '] ' + appLog.message))
27
+ .catch(error => {
28
+ logger.debug('[APP LOG][' + level + '] ' + appLog.message + ' >> [NO SENT]');
29
+ logger.error('Error when try to send app log to ES [' + error + ']')
30
+ })
31
+ };
32
+ const appLogDebug = (message, additionalInfo) => sendAppLog('DEBUG', message, additionalInfo);
33
+ const appLogInfo = (message, additionalInfo) => sendAppLog('INFO', message, additionalInfo);
34
+ const appLogWarn = (message, additionalInfo) => sendAppLog('WARN', message, additionalInfo);
35
+ const appLogError = (message, additionalInfo) => sendAppLog('ERROR', message, additionalInfo);
36
+
37
+ module.exports = {
38
+ debug: appLogDebug,
39
+ info: appLogInfo,
40
+ warn: appLogWarn,
41
+ error: appLogError
42
+ }
@@ -0,0 +1,68 @@
1
+ const {
2
+ podId,
3
+ applicationName,
4
+ svcName,
5
+ environment,
6
+ debug
7
+ } = require('../configuration/configuration').settings;
8
+ const dayjs = require('dayjs');
9
+
10
+ const formatLog = (level, message) => {
11
+ return dayjs().format('YYYY-MM-DD HH:mm:ss.SSS ZZ') + ' ' +
12
+ 'comp=svc ' +
13
+ 'level=' + level + ' ' +
14
+ 'podId=' + podId + ' ' +
15
+ 'app=' + applicationName + ' ' +
16
+ 'svc=' + svcName + ' ' +
17
+ 'env=' + environment + ' ' +
18
+ message;
19
+ }
20
+
21
+ const logDebug = (message, obj) => {
22
+ if (message && debug) {
23
+ if (obj) {
24
+ console.log(formatLog('DEBUG', message),obj);
25
+ } else {
26
+ console.log(formatLog('DEBUG', message));
27
+ }
28
+ }
29
+ };
30
+
31
+ const logInfo = (message, obj) => {
32
+ if (message) {
33
+ if (obj) {
34
+ console.info(formatLog('INFO', message),obj);
35
+ } else {
36
+ console.info(formatLog('INFO', message));
37
+ }
38
+ }
39
+ };
40
+
41
+ const logWarn = (message, obj) => {
42
+ if (message) {
43
+ if (obj) {
44
+ console.warn(formatLog('WARN', message),obj);
45
+ } else {
46
+ console.warn(formatLog('WARN', message));
47
+ }
48
+ }
49
+ };
50
+
51
+ const logError = (message, obj) => {
52
+ if (message) {
53
+ if (message) {
54
+ if (obj) {
55
+ console.error(formatLog('ERROR', message),obj);
56
+ } else {
57
+ console.error(formatLog('ERROR', message));
58
+ }
59
+ }
60
+ }
61
+ };
62
+
63
+ module.exports = {
64
+ debug: logDebug,
65
+ info: logInfo,
66
+ warn: logWarn,
67
+ error: logError
68
+ }
@@ -0,0 +1,26 @@
1
+ const httpModule = require('../httpModule/httpModule');
2
+ const {setPropertyOnSettings} = require('../configuration/configuration');
3
+
4
+
5
+ const checkProxyStatus = async () => {
6
+ try {
7
+ let res = await httpModule.get('/services/configuration');
8
+ let data = res.data;
9
+ return data.proxy
10
+ } catch (err) {
11
+ console.log("err is:",err);
12
+ }
13
+ }
14
+
15
+ const refreshCache = async () => {
16
+ try {
17
+ await httpModule.put('/services/management/clearCache');
18
+ } catch (err) {
19
+ console.log("err is:",err);
20
+ }
21
+ }
22
+
23
+ module.exports = {
24
+ checkProxyStatus,
25
+ refreshCache
26
+ }
@@ -0,0 +1,112 @@
1
+ const dataStores = require('../dataStores/dataStores');
2
+ const events = require('../events/events');
3
+
4
+ const USER_DATASTORE_NAME = '__svc_users__';
5
+ const USER_CONNECTED_EVENT = 'userConnected';
6
+ const USER_DISCONNECTED_EVENT = 'userDisconnected';
7
+
8
+ const findById = async (userId) => {
9
+ if (!userId) {
10
+ throw new Error('User id cannot be empty.')
11
+ }
12
+ try {
13
+ const user = await dataStores.findById(USER_DATASTORE_NAME, userId);
14
+ } catch (error) {
15
+
16
+ }
17
+ return user;
18
+ };
19
+
20
+ const save = async (userId, userInfo) => {
21
+ if (!userId) {
22
+ throw new Error('User id cannot be empty.')
23
+ }
24
+ try {
25
+ const user = await dataStores.findById(USER_DATASTORE_NAME, userId);
26
+ } catch (error) {
27
+
28
+ }
29
+ try {
30
+ const savedUser = await dataStores.save(USER_DATASTORE_NAME, user, userInfo);
31
+ } catch (error) {
32
+
33
+ }
34
+ return savedUser;
35
+ };
36
+
37
+ const removeById = async (userId) => {
38
+ if (!userId) {
39
+ throw new Error('User id cannot be empty.')
40
+ }
41
+ try {
42
+ const user = await dataStores.removeById(USER_DATASTORE_NAME, userId);
43
+ } catch (error) {
44
+
45
+ }
46
+ };
47
+
48
+ //Kind of a check and update
49
+ const checkUserConnection = async (userId, newInfo) => {
50
+ if (!userId) {
51
+ throw new Error('User id cannot be empty.')
52
+ }
53
+ try {
54
+ const user = await dataStores.findById(USER_DATASTORE_NAME, userId);
55
+ } catch (error) {
56
+
57
+ }
58
+ if (!user) {
59
+ throw new Error('User with id [' + userId + '] is not connected.');
60
+ }
61
+ user = {
62
+ ...user,
63
+ ...newInfo
64
+ };
65
+ return user;
66
+ }
67
+
68
+ const connect = async (userId, userInfo, functionId) => {
69
+ if (!userId) {
70
+ throw new Error('User id cannot be empty.')
71
+ }
72
+ let user;
73
+ try {
74
+ user = await save(userId, userInfo);
75
+ } catch (error) {
76
+
77
+ }
78
+ sendUserConnectedEvent(userId, userInfo, functionId);
79
+ return user;
80
+ }
81
+
82
+ const disconnect = async (userId, functionId) => {
83
+ if (!userId) {
84
+ throw new Error('User id cannot be empty.')
85
+ }
86
+ let user;
87
+ try {
88
+ await removeById(userId);
89
+ } catch (error) {
90
+
91
+ }
92
+ sendUserDisconnectedEvent(userId, null, functionId);
93
+ return user;
94
+ }
95
+
96
+ const sendUserConnectedEvent = (userId, userInfo, functionId) => {
97
+ events.send(USER_CONNECTED_EVENT, userInfo, functionId, userId);
98
+ }
99
+
100
+ const sendUserDisconnectedEvent = (userId, functionId) => {
101
+ events.send(USER_DISCONNECTED_EVENT, null, functionId, userId);
102
+ }
103
+
104
+ module.exports = {
105
+ findById,
106
+ save,
107
+ removeById,
108
+ connect,
109
+ disconnect,
110
+ sendUserConnectedEvent,
111
+ sendUserDisconnectedEvent
112
+ }