@go-mailer/jarvis 5.0.5 → 5.0.6

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 ADDED
@@ -0,0 +1 @@
1
+ test/
package/.eslintrc.yml ADDED
@@ -0,0 +1,10 @@
1
+ env:
2
+ commonjs: true
3
+ es2021: true
4
+ node: true
5
+ extends:
6
+ - standard
7
+ parserOptions:
8
+ ecmaVersion: latest
9
+ rules:
10
+ camelcase: 0
package/index.js CHANGED
@@ -1,12 +1,12 @@
1
- const EnvVar = require("./lib/env");
2
- const FeatureFlag = require("./lib/flag");
3
- const Redis = require("./lib/redis/index");
4
- const QueryBuilder = require("./lib/query");
5
- const HTTP = require("./lib/middlewares/http");
6
- const Authenticator = require("./lib/middlewares/auth");
7
- const AutomationConstants = require("./lib/constants/automation");
8
- const { RequestLogger, ProcessLogger } = require("./lib/middlewares/logger");
9
- const Utility = require("./lib/utilitiy/index");
1
+ const EnvVar = require('./lib/env')
2
+ const FeatureFlag = require('./lib/flag')
3
+ const Redis = require('./lib/redis/index')
4
+ const QueryBuilder = require('./lib/query')
5
+ const HTTP = require('./lib/middlewares/http')
6
+ const Authenticator = require('./lib/middlewares/auth')
7
+ const AutomationConstants = require('./lib/constants/automation')
8
+ const { RequestLogger, ProcessLogger } = require('./lib/middlewares/logger')
9
+ const Utility = require('./lib/utilitiy/index')
10
10
 
11
11
  module.exports = {
12
12
  Authenticator,
@@ -18,5 +18,5 @@ module.exports = {
18
18
  QueryBuilder,
19
19
  Redis,
20
20
  RequestLogger,
21
- Utility,
22
- };
21
+ Utility
22
+ }
@@ -1,7 +1,7 @@
1
- const axios = require("axios");
2
- const Env = require("../env");
3
- const BASE_URI = Env.fetch("GO_FLAGS_URI", true);
4
- const API_KEY = Env.fetch("GO_FLAGS_KEY", true);
1
+ const axios = require('axios')
2
+ const Env = require('../env')
3
+ const BASE_URI = Env.fetch('GO_FLAGS_URI', true)
4
+ const API_KEY = Env.fetch('GO_FLAGS_KEY', true)
5
5
 
6
6
  const verifyFeatureFlag = async (flag_name, criteria = {}, environment = '') => {
7
7
  const { error, payload } = (
@@ -9,19 +9,19 @@ const verifyFeatureFlag = async (flag_name, criteria = {}, environment = '') =>
9
9
  `${BASE_URI}/api/v1/flags/${flag_name}`,
10
10
  {
11
11
  payload: criteria,
12
- environment: environment || Env.fetch("GO_FLAGS_ENV", true)
12
+ environment: environment || Env.fetch('GO_FLAGS_ENV', true)
13
13
  },
14
14
  {
15
15
  headers: {
16
- authorization: `Bearer ${API_KEY}`,
17
- },
16
+ authorization: `Bearer ${API_KEY}`
17
+ }
18
18
  }
19
19
  )
20
- ).data;
20
+ ).data
21
21
 
22
- if (error) throw new Error(error);
22
+ if (error) throw new Error(error)
23
23
 
24
- return payload.is_permitted;
25
- };
24
+ return payload.is_permitted
25
+ }
26
26
 
27
- module.exports = { verifyFeatureFlag };
27
+ module.exports = { verifyFeatureFlag }
@@ -1,21 +1,35 @@
1
- const axios = require("axios");
2
- const Env = require("../env");
3
- const IAM_URI = Env.fetch("IAM_SERVICE_URI", true);
4
- const DEFAULT_TOKEN = Env.fetch("DEFAULT_TOKEN", true);
1
+ const axios = require('axios').default
2
+ const Env = require('../env')
3
+ const IAM_URI = Env.fetch('IAM_SERVICE_URI', true)
4
+ const DEFAULT_TOKEN = Env.fetch('DEFAULT_TOKEN', true)
5
+
6
+ const checkAuthority = async ({ action, resource, user_id, tenant_id }) => {
7
+ const { error, payload } = (
8
+ await axios.post(`${IAM_URI}/authorizer`, {
9
+ action,
10
+ resource,
11
+ tenant_id,
12
+ user_id
13
+ })
14
+ ).data
15
+
16
+ if (error || !payload.is_permitted) throw new Error('Unauthorized')
17
+ return payload.is_permitted
18
+ }
5
19
 
6
20
  const verifyAPIKey = async (key) => {
7
21
  const { error, payload } = (
8
22
  await axios.get(`${IAM_URI}/keys/verify/${key}`, {
9
23
  headers: {
10
- authorization: `Bearer ${DEFAULT_TOKEN}`,
11
- },
24
+ authorization: `Bearer ${DEFAULT_TOKEN}`
25
+ }
12
26
  })
13
- ).data;
27
+ ).data
14
28
 
15
- if (error) throw new Error("Unauthorized");
29
+ if (error) throw new Error('Unauthorized')
16
30
 
17
- return payload.org_id;
18
- };
31
+ return payload.org_id
32
+ }
19
33
 
20
34
  const verifyFeatureFlag = async (flag_name, criteria = {}) => {
21
35
  const { error, payload } = (
@@ -23,20 +37,20 @@ const verifyFeatureFlag = async (flag_name, criteria = {}) => {
23
37
  `${IAM_URI}/flags`,
24
38
  {
25
39
  criteria,
26
- environment: Env.fetch("NODE_ENV"),
27
- name: flag_name,
40
+ environment: Env.fetch('NODE_ENV'),
41
+ name: flag_name
28
42
  },
29
43
  {
30
44
  headers: {
31
- authorization: `Bearer ${DEFAULT_TOKEN}`,
32
- },
45
+ authorization: `Bearer ${DEFAULT_TOKEN}`
46
+ }
33
47
  }
34
48
  )
35
- ).data;
49
+ ).data
36
50
 
37
- if (error) throw new Error(error);
51
+ if (error) throw new Error(error)
38
52
 
39
- return payload.is_permitted;
40
- };
53
+ return payload.is_permitted
54
+ }
41
55
 
42
- module.exports = { verifyAPIKey, verifyFeatureFlag };
56
+ module.exports = { checkAuthority, verifyAPIKey, verifyFeatureFlag }
@@ -7,7 +7,7 @@ module.exports = {
7
7
  EVENT_OPENED_TRANSACTIONAL: 'opened_transactional',
8
8
  EVENT_SUBSCRIPTION: 'joined_audience',
9
9
  EVENT_UNSUBSCRIPTION: 'left_audience',
10
-
10
+
11
11
  //
12
12
  EFFECT_REMOVE_CONTACT: 'delete_contact',
13
13
  EFFECT_SEND_TRANSACTIONAL: 'send_transactional_email',
package/lib/env.js CHANGED
@@ -1,24 +1,24 @@
1
- require("dotenv").config();
1
+ require('dotenv').config()
2
2
 
3
3
  /** */
4
4
  class EnvVar {
5
- constructor() {
6
- this.config = {};
5
+ constructor () {
6
+ this.config = {}
7
7
  }
8
8
 
9
- set(config = {}) {
9
+ set (config = {}) {
10
10
  this.config = {
11
11
  ...this.config,
12
- ...config,
13
- };
12
+ ...config
13
+ }
14
14
  }
15
15
 
16
- fetch(var_name = "", is_required = false) {
17
- if (!var_name) throw new Error(`Variable name is required.`);
18
- const value = process.env[var_name] || this.config[var_name];
19
- if (is_required && !value) throw new Error(`Required EnvVar ${var_name} not found`);
20
- return value;
16
+ fetch (var_name = '', is_required = false) {
17
+ if (!var_name) throw new Error('Variable name is required.')
18
+ const value = process.env[var_name] || this.config[var_name]
19
+ if (is_required && !value) throw new Error(`Required EnvVar ${var_name} not found`)
20
+ return value
21
21
  }
22
22
  }
23
23
 
24
- module.exports = new EnvVar();
24
+ module.exports = new EnvVar()
package/lib/flag.js CHANGED
@@ -4,10 +4,10 @@ const flagLogger = new ProcessLogger('FeatureFlag')
4
4
 
5
5
  const verify = async (flag_name = '', criteria = {}) => {
6
6
  try {
7
- if (!flag_name) throw new Error('Unspecified flag name');
8
- if (!Object.keys(criteria)) throw new Error('Unspecified criteria');
9
-
10
- const result = await verifyFeatureFlag(flag_name, criteria);
7
+ if (!flag_name) throw new Error('Unspecified flag name')
8
+ if (!Object.keys(criteria)) throw new Error('Unspecified criteria')
9
+
10
+ const result = await verifyFeatureFlag(flag_name, criteria)
11
11
  return result
12
12
  } catch (e) {
13
13
  flagLogger.error(e, 'verify')
@@ -2,98 +2,113 @@
2
2
  * User Authentication Middleware
3
3
  */
4
4
 
5
- const jwt = require("jsonwebtoken");
6
- const Env = require("../env");
7
- const Errors = require("./errors");
8
- const { ProcessLogger } = require("./logger");
9
- const { verifyAPIKey } = require("../clients/iam");
10
- const authLogger = new ProcessLogger("Authenticator");
11
-
12
- // helpers
13
- const extractToken = (headers) => {
14
- const { authorization } = headers;
15
- if (!authorization) throw new Error("Unauthorized");
16
-
17
- const [, token] = authorization.split(" ");
18
- if (!token) throw new Error("Unauthorized");
19
-
20
- return token;
21
- };
22
-
23
- const extractId = (request, key) => {
24
- const { params, query, body } = request;
25
- let id = { $exists: true };
26
- if (query[key]) id = query[key];
27
- if (params[key]) id = params[key];
28
- if (body[key]) id = body[key];
29
-
30
- return id;
31
- };
32
-
33
- // main
34
-
35
- const authenticateAdmin = async (request, response, next) => {
36
- const { is_admin } = request;
37
- if (!is_admin) return response.status(403).json(Errors.UNAUTHORIZED);
38
-
39
- next();
40
- };
41
-
42
- const authenticateBearerKey = async (request, response, next) => {
43
- try {
44
- const token = extractToken(request.headers);
45
- request.tenant_id = await verifyAPIKey(token);
46
- next();
47
- } catch (e) {
48
- authLogger.error(e, "authenticateBearerKey");
49
- return response.status(403).json(Errors.UNAUTHORIZED);
50
- }
51
- };
52
-
53
- const authenticateParamKey = async (request, response, next) => {
54
- try {
55
- const { api_key: token } = request.params;
56
- request.tenant_id = await verifyAPIKey(token);
57
- next();
58
- } catch (e) {
59
- authLogger.error(e, "authenticateParamKey");
60
- return response.status(403).json(Errors.UNAUTHORIZED);
61
- }
62
- };
63
-
64
- const authenticateUser = async (request, response, next) => {
65
- try {
66
- // env vars
67
- const DEFAULT_TOKEN = Env.fetch("DEFAULT_TOKEN", true);
68
- const ISSUER = Env.fetch("JWT_ISSUER", true);
69
- const SECRET = Env.fetch("JWT_SECRET", true);
70
-
71
- const token = extractToken(request.headers);
72
- if (token === DEFAULT_TOKEN) {
73
- // inter-service requests
74
- request.is_service_request = true;
75
- // typically scope requests by tenant_id
76
- request.tenant_id = request.body.tenant_id || request.query.tenant_id || { $exists: true };
77
- request.user_id = request.body.user_id || request.query.user_id || { $exists: true };
78
- return next();
79
- }
80
-
81
- const { id: user_id, is_admin, tenant_id } = await jwt.verify(token, SECRET, { issuer: ISSUER });
82
- request.is_admin = !!is_admin;
83
- request.user_id = is_admin ? extractId(request, "user_id") : user_id;
84
- request.tenant_id = is_admin ? extractId(request, "tenant_id") : tenant_id;
85
-
86
- next();
87
- } catch (e) {
88
- authLogger.error(e, "authenticateUser");
89
- return response.status(403).json(Errors.UNAUTHORIZED);
90
- }
91
- };
92
-
93
- module.exports = {
94
- authenticateAdmin,
95
- authenticateBearerKey,
96
- authenticateParamKey,
97
- authenticateUser,
98
- };
99
-
5
+ const jwt = require('jsonwebtoken')
6
+ const Env = require('../env')
7
+ const Errors = require('./errors')
8
+ const { ProcessLogger } = require('./logger')
9
+ const { checkAuthority, verifyAPIKey } = require('../clients/iam')
10
+ const authLogger = new ProcessLogger('Authenticator')
11
+
12
+ // helpers
13
+ const extractToken = (headers) => {
14
+ const { authorization } = headers
15
+ if (!authorization) throw new Error('Unauthorized')
16
+
17
+ const [, token] = authorization.split(' ')
18
+ if (!token) throw new Error('Unauthorized')
19
+
20
+ return token
21
+ }
22
+
23
+ const extractId = (request, key) => {
24
+ const { params, query, body } = request
25
+ let id = { $exists: true }
26
+ if (query[key]) id = query[key]
27
+ if (params[key]) id = params[key]
28
+ if (body[key]) id = body[key]
29
+
30
+ return id
31
+ }
32
+
33
+ // main
34
+
35
+ const authenticateAdmin = async (request, response, next) => {
36
+ const { is_admin } = request
37
+ if (!is_admin) return response.status(403).json(Errors.UNAUTHORIZED)
38
+
39
+ next()
40
+ }
41
+
42
+ const authenticateBearerKey = async (request, response, next) => {
43
+ try {
44
+ const token = extractToken(request.headers)
45
+ request.tenant_id = await verifyAPIKey(token)
46
+ next()
47
+ } catch (e) {
48
+ authLogger.error(e, 'authenticateBearerKey')
49
+ return response.status(403).json(Errors.UNAUTHORIZED)
50
+ }
51
+ }
52
+
53
+ const authenticateParamKey = async (request, response, next) => {
54
+ try {
55
+ const { api_key: token } = request.params
56
+ request.tenant_id = await verifyAPIKey(token)
57
+ next()
58
+ } catch (e) {
59
+ authLogger.error(e, 'authenticateParamKey')
60
+ return response.status(403).json(Errors.UNAUTHORIZED)
61
+ }
62
+ }
63
+
64
+ const authenticateUser = async (request, response, next) => {
65
+ try {
66
+ // env vars
67
+ const DEFAULT_TOKEN = Env.fetch('DEFAULT_TOKEN', true)
68
+ const ISSUER = Env.fetch('JWT_ISSUER', true)
69
+ const SECRET = Env.fetch('JWT_SECRET', true)
70
+
71
+ const token = extractToken(request.headers)
72
+ if (token === DEFAULT_TOKEN) {
73
+ // inter-service requests
74
+ request.is_service_request = true
75
+ // typically scope requests by tenant_id
76
+ request.tenant_id = request.body.tenant_id || request.query.tenant_id || { $exists: true }
77
+ request.user_id = request.body.user_id || request.query.user_id || { $exists: true }
78
+ return next()
79
+ }
80
+
81
+ const { id: user_id, is_admin, tenant_id } = await jwt.verify(token, SECRET, { issuer: ISSUER })
82
+ request.is_admin = !!is_admin
83
+ request.user_id = is_admin ? extractId(request, 'user_id') : user_id
84
+ request.tenant_id = is_admin ? extractId(request, 'tenant_id') : tenant_id
85
+
86
+ next()
87
+ } catch (e) {
88
+ authLogger.error(e, 'authenticateUser')
89
+ return response.status(403).json(Errors.UNAUTHORIZED)
90
+ }
91
+ }
92
+
93
+ const authorizeUser = async ({ action, resource }) => {
94
+ return async (request, response, next) => {
95
+ try {
96
+ const { is_admin, tenant_id, user_id } = request
97
+ if (is_admin) next()
98
+
99
+ await checkAuthority({ action, resource, tenant_id, user_id })
100
+ next()
101
+ } catch (e) {
102
+ authLogger.error(e, 'authorizeUser')
103
+ return response.status(403).json(Errors.UNAUTHORIZED)
104
+ }
105
+ }
106
+ }
107
+
108
+ module.exports = {
109
+ authenticateAdmin,
110
+ authenticateBearerKey,
111
+ authenticateParamKey,
112
+ authenticateUser,
113
+ authorizeUser
114
+ }
@@ -1,52 +1,52 @@
1
1
  /** **/
2
- const { ProcessLogger } = require("./logger");
3
- const HTTPLogger = new ProcessLogger("HTTPSetup");
2
+ const { ProcessLogger } = require('./logger')
3
+ const HTTPLogger = new ProcessLogger('HTTPSetup')
4
4
 
5
5
  module.exports = {
6
- handle404(_, __, next) {
6
+ handle404 (_, __, next) {
7
7
  const return_data = {
8
8
  status_code: 404,
9
9
  success: false,
10
- error: "Resource not found",
11
- payload: null,
12
- };
10
+ error: 'Resource not found',
11
+ payload: null
12
+ }
13
13
 
14
- next(return_data);
14
+ next(return_data)
15
15
  },
16
16
 
17
- handleError(error, __, response, ____) {
17
+ handleError (error, __, response, ____) {
18
18
  // Log errors
19
19
  if (error.error) {
20
- HTTPLogger.info(error.error, "handleError");
20
+ HTTPLogger.info(error.error, 'handleError')
21
21
  } else {
22
- HTTPLogger.error(error, "handleError");
22
+ HTTPLogger.error(error, 'handleError')
23
23
  }
24
24
 
25
25
  // return error
26
26
  return response.status(error.status_code || 500).json({
27
27
  success: false,
28
28
  status_code: error.status_code || 500,
29
- error: error.error || "Internal Server Error",
30
- payload: null,
31
- });
29
+ error: error.error || 'Internal Server Error',
30
+ payload: null
31
+ })
32
32
  },
33
33
 
34
- processResponse(request, response, next) {
35
- if (!request.payload) return next();
34
+ processResponse (request, response, next) {
35
+ if (!request.payload) return next()
36
36
 
37
- const { status_code } = request.payload;
38
- return response.status(status_code).json(request.payload);
37
+ const { status_code } = request.payload
38
+ return response.status(status_code).json(request.payload)
39
39
  },
40
40
 
41
- setupRequest(request, response, next) {
42
- request.headers["access-control-allow-origin"] = "*";
43
- request.headers["access-control-allow-headers"] = "*";
41
+ setupRequest (request, response, next) {
42
+ request.headers['access-control-allow-origin'] = '*'
43
+ request.headers['access-control-allow-headers'] = '*'
44
44
 
45
- if (request.method === "OPTIONS") {
46
- request.headers["access-control-allow-methods"] = "GET, POST, PUT, PATCH, DELETE";
47
- response.status(200).json();
45
+ if (request.method === 'OPTIONS') {
46
+ request.headers['access-control-allow-methods'] = 'GET, POST, PUT, PATCH, DELETE'
47
+ response.status(200).json()
48
48
  }
49
49
 
50
- next();
51
- },
52
- };
50
+ next()
51
+ }
52
+ }
@@ -2,41 +2,38 @@
2
2
  * @author Oguntuberu Nathan O. <nateoguns.work@gmail.com>
3
3
  **/
4
4
 
5
- const Env = require("../env");
6
- const { randomUUID } = require("crypto");
7
- const { Logtail } = require("@logtail/node");
8
- const LOGTAIL_SECRET = Env.fetch("LOGTAIL_SECRET", true);
9
- const logtail = new Logtail(LOGTAIL_SECRET);
5
+ const Env = require('../env')
6
+ const { randomUUID } = require('crypto')
10
7
 
11
8
  function hashLogData (log = {}) {
12
9
  const hashed = JSON.stringify(log).replace(/\w+@/gi, '************')
13
10
  return JSON.parse(hashed)
14
11
  }
15
12
 
16
- function RequestLogger() {
17
- const app_name = Env.fetch("APP_NAME", true);
13
+ function RequestLogger () {
14
+ const app_name = Env.fetch('APP_NAME', true)
18
15
  return (request, response, next) => {
19
- if (!request.request_id) request.request_id = randomUUID();
16
+ if (!request.request_id) request.request_id = randomUUID()
20
17
 
21
18
  //
22
19
  const {
23
20
  query,
24
21
  params,
25
- headers: { host, origin, "user-agent": user_agent, "sec-ch-ua-platform": os, referer },
22
+ headers: { host, origin, 'user-agent': user_agent, 'sec-ch-ua-platform': os, referer },
26
23
  request_id,
27
- tenant_id,
28
- } = request;
24
+ tenant_id
25
+ } = request
29
26
 
30
- response.on("finish", () => {
27
+ response.on('finish', () => {
31
28
  const {
32
29
  _parsedUrl: { pathname },
33
30
  httpVersion,
34
31
  _startTime,
35
32
  _remoteAddress,
36
- payload,
37
- } = response.req;
38
- const { statusCode, statusMessage } = response.req.res;
39
- const duration = Date.now() - Date.parse(_startTime);
33
+ payload
34
+ } = response.req
35
+ const { statusCode, statusMessage } = response.req.res
36
+ const duration = Date.now() - Date.parse(_startTime)
40
37
  const log = {
41
38
  app_name,
42
39
  request_id,
@@ -52,11 +49,11 @@ function RequestLogger() {
52
49
  _remoteAddress,
53
50
  pathname,
54
51
  duration,
55
- type: "request",
56
- status_code: payload ? payload.status_code : statusCode,
57
- };
52
+ type: 'request',
53
+ status_code: payload ? payload.status_code : statusCode
54
+ }
58
55
 
59
- let error = payload ? payload.error : statusMessage;
56
+ const error = payload ? payload.error : statusMessage
60
57
  // if (error) {
61
58
  // log.error = error;
62
59
  // logtail.error(pathname, hashLogData(log));
@@ -65,18 +62,19 @@ function RequestLogger() {
65
62
  // }
66
63
 
67
64
  // logtail.flush();
68
- });
65
+ console.log(pathname, hashLogData({ ...log, error }))
66
+ })
69
67
 
70
- next();
71
- };
68
+ next()
69
+ }
72
70
  }
73
71
 
74
72
  class ProcessLogger {
75
- constructor(service = "System") {
76
- this.service = service;
73
+ constructor (service = 'System') {
74
+ this.service = service
77
75
  }
78
76
 
79
- error(error, method = "unspecified_method", params = {}) {
77
+ error (error, method = 'unspecified_method', params = {}) {
80
78
  // logtail.error(`${this.service}:${method}:${error.message}`, hashLogData({
81
79
  // app_name: Env.fetch("APP_NAME", true),
82
80
  // type: "process",
@@ -85,12 +83,12 @@ class ProcessLogger {
85
83
  // params,
86
84
  // }));
87
85
  // logtail.flush();
88
- console.log(`${this.service}:${method}:${error.message}`, error.stack)
86
+ console.log(`${this.service}:${method}:${error.message}`, params, error.stack)
89
87
  }
90
88
 
91
- info(info, method = "unspecified_method", params = {}) {
92
- const message_str = `${this.service}:${method}:${info}`;
93
- console.log(message_str);
89
+ info (info, method = 'unspecified_method', params = {}) {
90
+ const message_str = `${this.service}:${method}:${info}`
91
+ console.log(message_str, params)
94
92
  // logtail.info(message_str, hashLogData({
95
93
  // app_name: Env.fetch("APP_NAME", true),
96
94
  // type: "process",
@@ -101,4 +99,4 @@ class ProcessLogger {
101
99
  }
102
100
  }
103
101
 
104
- module.exports = { RequestLogger, ProcessLogger };
102
+ module.exports = { RequestLogger, ProcessLogger }
package/lib/query.js CHANGED
@@ -2,7 +2,7 @@ const buildQuery = (options) => {
2
2
  const sort_condition = options.sort_by ? buildSortOrderString(options.sort_by) : {}
3
3
  const fields_to_return = options.return_only ? buildReturnFieldsString(options.return_only) : ''
4
4
  const count = options.count || false
5
-
5
+
6
6
  const group_by = options.group_by
7
7
  const sum = options.sum
8
8
  const is_pipeline = group_by || sum
@@ -179,7 +179,7 @@ const generatePipeline = ({ group_by, seek_conditions, sort_condition, sum, fiel
179
179
  })
180
180
 
181
181
  let sort_options = sort_condition
182
- if (sort_condition && typeof(sort_condition) === 'string') {
182
+ if (sort_condition && typeof (sort_condition) === 'string') {
183
183
  sort_options = sort_condition.split(' ').reduce((sac, condition) => {
184
184
  let key = condition
185
185
  let value = 1
@@ -219,7 +219,7 @@ const generatePipeline = ({ group_by, seek_conditions, sort_condition, sum, fiel
219
219
  const sum_field = sum.split(',')[0]
220
220
  pipeline.push({
221
221
  $group: {
222
- _id: { tenant_id: "$tenant_id" },
222
+ _id: { tenant_id: '$tenant_id' },
223
223
  [sum_field]: { $sum: `$${sum_field}` }
224
224
  }
225
225
  })
@@ -227,7 +227,7 @@ const generatePipeline = ({ group_by, seek_conditions, sort_condition, sum, fiel
227
227
 
228
228
  if (count) {
229
229
  pipeline.push({
230
- $count: "size"
230
+ $count: 'size'
231
231
  })
232
232
  }
233
233
 
@@ -29,8 +29,8 @@ class RedisClient {
29
29
  }
30
30
  }
31
31
  //
32
- const redisClient = new RedisClient()
33
- module.exports ={
32
+ const redisClient = new RedisClient()
33
+ module.exports = {
34
34
  RedisClient: redisClient,
35
35
  Schemas
36
36
  }
@@ -1,69 +1,69 @@
1
1
  const processRangeInDays = (min = 0, seconds_in_day = 86400000) => {
2
- const ranges = [];
3
- let x = min;
2
+ const ranges = []
3
+ let x = min
4
4
  for (let i = 0; i < 31; i++) {
5
- const [, mmm, dd] = new Date(x).toDateString().split(" ");
6
- ranges.push({ start: x, end: x + seconds_in_day - 1000, label: `${mmm} ${dd}` });
7
- x += seconds_in_day;
5
+ const [, mmm, dd] = new Date(x).toDateString().split(' ')
6
+ ranges.push({ start: x, end: x + seconds_in_day - 1000, label: `${mmm} ${dd}` })
7
+ x += seconds_in_day
8
8
  }
9
9
 
10
- return ranges;
11
- };
10
+ return ranges
11
+ }
12
12
 
13
13
  const processRangeInWeeks = (min = 0, seconds_in_day = 86400000) => {
14
- const ranges = [];
15
- let x = min;
16
- const [, mmm, dd] = new Date(x).toDateString().split(" ");
14
+ const ranges = []
15
+ let x = min
16
+ const [, mmm, dd] = new Date(x).toDateString().split(' ')
17
17
  for (let i = 0; i < Math.ceil(100 / 7); i++) {
18
18
  ranges[i] = {
19
19
  start: x,
20
20
  end: x + 6 * seconds_in_day - 1000,
21
- label: `${mmm} ${dd}`,
22
- };
23
- x += 6 * seconds_in_day;
21
+ label: `${mmm} ${dd}`
22
+ }
23
+ x += 6 * seconds_in_day
24
24
  }
25
25
 
26
- return ranges;
27
- };
26
+ return ranges
27
+ }
28
28
 
29
29
  const processRangeInMonths = (min, max) => {
30
30
  // group in months
31
- const d = new Date(min);
32
- const year = d.getFullYear();
33
- const month = d.getUTCMonth();
31
+ const d = new Date(min)
32
+ const year = d.getFullYear()
33
+ const month = d.getUTCMonth()
34
34
 
35
- const ranges = [];
36
- let x = min;
35
+ const ranges = []
36
+ let x = min
37
37
  for (let i = 1; x <= max; i++) {
38
- const [, mmm, , yyyy] = new Date(x).toDateString().split(" ");
38
+ const [, mmm, , yyyy] = new Date(x).toDateString().split(' ')
39
39
  ranges.push({
40
40
  start: x,
41
41
  end: Date.parse(new Date(year, month + i, 1)) - 1000,
42
- label: `${mmm} ${yyyy}`,
43
- });
42
+ label: `${mmm} ${yyyy}`
43
+ })
44
44
 
45
- x = Date.parse(new Date(year, month + i, 1));
45
+ x = Date.parse(new Date(year, month + i, 1))
46
46
  }
47
47
 
48
- return ranges;
49
- };
48
+ return ranges
49
+ }
50
50
 
51
51
  module.exports = {
52
52
  processDateRange: (start, stop) => {
53
- const min = Date.parse(start);
54
- const max = Date.parse(stop);
55
- const difference = max - min;
56
- const seconds_in_day = 86400000;
53
+ const min = Date.parse(start)
54
+ const max = Date.parse(stop)
55
+ const difference = max - min
56
+ const seconds_in_day = 86400000
57
57
 
58
- let ranges = [];
58
+ let ranges = []
59
59
  if (difference / seconds_in_day <= 31) {
60
- ranges = processRangeInDays(min, seconds_in_day);
60
+ ranges = processRangeInDays(min, seconds_in_day)
61
61
  } else if (difference / seconds_in_day <= 100) {
62
- ranges = processRangeInWeeks(min, seconds_in_day);
62
+ ranges = processRangeInWeeks(min, seconds_in_day)
63
63
  } else {
64
- ranges = processRangeInMonths(min, max);
64
+ ranges = processRangeInMonths(min, max)
65
65
  }
66
66
 
67
- return ranges;
68
- },
69
- };
67
+ return ranges
68
+ }
69
+ }
@@ -1,35 +1,35 @@
1
1
  /** */
2
- const MONTH_MAP = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
3
- const NUM_OF_MILLISECONDS_IN_ONE_DAY = 86400000;
2
+ const MONTH_MAP = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
3
+ const NUM_OF_MILLISECONDS_IN_ONE_DAY = 86400000
4
4
 
5
5
  /** */
6
6
  const convertDateFromIsoToHTMLFormat = (iso_date) => {
7
- const date = new Date(iso_date);
8
- const day = padDateValue(date.getDate());
9
- const month = padDateValue(date.getMonth() + 1);
10
- const year = date.getFullYear();
7
+ const date = new Date(iso_date)
8
+ const day = padDateValue(date.getDate())
9
+ const month = padDateValue(date.getMonth() + 1)
10
+ const year = date.getFullYear()
11
11
 
12
- const converted_date = `${year}-${month}-${day}`;
13
- return iso_date ? converted_date : "";
14
- };
12
+ const converted_date = `${year}-${month}-${day}`
13
+ return iso_date ? converted_date : ''
14
+ }
15
15
 
16
16
  /**
17
17
  * Extracts day string of the given timestamp for graphs. Return ex. 'Jan 10'
18
18
  * @param {Number} timestamp
19
19
  */
20
20
  const extractDayStringForGraph = (timestamp) => {
21
- const date = new Date(timestamp);
22
- const month = MONTH_MAP[date.getMonth()];
23
- const day = padDateValue(date.getDate());
21
+ const date = new Date(timestamp)
22
+ const month = MONTH_MAP[date.getMonth()]
23
+ const day = padDateValue(date.getDate())
24
24
 
25
- return `${month} ${day}`;
26
- };
25
+ return `${month} ${day}`
26
+ }
27
27
 
28
28
  const generateHTMLFormDateTimeDefaults = () => {
29
- const date = new Date().toISOString();
30
- const generated_date = `${convertDateFromIsoToHTMLFormat(date)}`;
31
- return generated_date;
32
- };
29
+ const date = new Date().toISOString()
30
+ const generated_date = `${convertDateFromIsoToHTMLFormat(date)}`
31
+ return generated_date
32
+ }
33
33
 
34
34
  /**
35
35
  * Generates a configuration of back-counted days starting from a base time.
@@ -38,20 +38,20 @@ const generateHTMLFormDateTimeDefaults = () => {
38
38
  * @param {*} spread The numbers of days to count back.
39
39
  */
40
40
  const generateDaysConfigurationForGraph = (base_timestamp, spread = 7, key_values) => {
41
- let curr_timestamp = getDayTimestampForRawTimestamp(base_timestamp);
42
- const config = {};
41
+ let curr_timestamp = getDayTimestampForRawTimestamp(base_timestamp)
42
+ const config = {}
43
43
  for (let i = 0; i < spread; i++) {
44
- const date_string = extractDayStringForGraph(curr_timestamp);
44
+ const date_string = extractDayStringForGraph(curr_timestamp)
45
45
  // key_values = [subscribers , unsubscribers]; [opens, bounces]
46
46
  config[date_string] = {
47
47
  date: date_string,
48
48
  [key_values[0]]: 0,
49
- [key_values[1]]: 0,
50
- };
51
- curr_timestamp -= NUM_OF_MILLISECONDS_IN_ONE_DAY;
49
+ [key_values[1]]: 0
50
+ }
51
+ curr_timestamp -= NUM_OF_MILLISECONDS_IN_ONE_DAY
52
52
  }
53
- return config;
54
- };
53
+ return config
54
+ }
55
55
 
56
56
  /**
57
57
  * Generates the number of milliseconds at (12:00AM) for the date specified in the raw_timestamp.
@@ -59,83 +59,83 @@ const generateDaysConfigurationForGraph = (base_timestamp, spread = 7, key_value
59
59
  * @param {Number} raw_timestamp number of milliseconds
60
60
  */
61
61
  const getDayTimestampForRawTimestamp = (raw_timestamp) => {
62
- const date = new Date(raw_timestamp);
63
- const day = `${padDateValue(date.getMonth() + 1)}/${padDateValue(date.getDate())}/${date.getFullYear()}`;
64
- return Date.parse(day);
65
- };
62
+ const date = new Date(raw_timestamp)
63
+ const day = `${padDateValue(date.getMonth() + 1)}/${padDateValue(date.getDate())}/${date.getFullYear()}`
64
+ return Date.parse(day)
65
+ }
66
66
 
67
67
  /**
68
68
  * Get the timestamp of the first and last days of the month
69
69
  */
70
70
 
71
71
  const getMonthTimeRange = () => {
72
- const year = new Date().getFullYear();
73
- const current_month = new Date().getMonth();
74
- const start = Date.parse(new Date(year, current_month, 1));
75
- const end = Date.parse(new Date(year, current_month + 1, 1)) - 1000;
72
+ const year = new Date().getFullYear()
73
+ const current_month = new Date().getMonth()
74
+ const start = Date.parse(new Date(year, current_month, 1))
75
+ const end = Date.parse(new Date(year, current_month + 1, 1)) - 1000
76
76
 
77
- return { start, end };
78
- };
77
+ return { start, end }
78
+ }
79
79
 
80
80
  /**
81
81
  * Get today's midnight time stamp
82
82
  */
83
83
 
84
84
  const getCurrentDayTimestamp = () => {
85
- const date = new Date();
86
- const year = date.getFullYear();
87
- const month = padDateValue(date.getMonth() + 1);
88
- const day = padDateValue(date.getDate());
89
- const date_string = `${year}-${month}-${day}`;
90
- return Date.parse(date_string);
91
- };
85
+ const date = new Date()
86
+ const year = date.getFullYear()
87
+ const month = padDateValue(date.getMonth() + 1)
88
+ const day = padDateValue(date.getDate())
89
+ const date_string = `${year}-${month}-${day}`
90
+ return Date.parse(date_string)
91
+ }
92
92
 
93
93
  /**
94
94
  * prefixes 0 on numbers with single digits.
95
95
  * @param {Number} value
96
96
  */
97
97
  const padDateValue = (value) => {
98
- return value < 10 ? `0${value}` : value;
99
- };
98
+ return value < 10 ? `0${value}` : value
99
+ }
100
100
 
101
101
  const isCampaignSendDateValid = (chosen_date) => {
102
- const today = new Date().toDateString();
103
- return new Date(`${chosen_date}`) >= new Date(today);
104
- };
102
+ const today = new Date().toDateString()
103
+ return new Date(`${chosen_date}`) >= new Date(today)
104
+ }
105
105
 
106
- const toDateString = (date = "") => {
107
- if (!date) return "";
108
- return new Date(date).toDateString();
109
- };
106
+ const toDateString = (date = '') => {
107
+ if (!date) return ''
108
+ return new Date(date).toDateString()
109
+ }
110
110
 
111
- const formatDateWithoutDayOfWeek = (date = "") => {
112
- if (!date) return "";
113
- const options = { year: "numeric", month: "short", day: "numeric" };
114
- return new Date(date).toLocaleDateString(undefined, options);
115
- };
111
+ const formatDateWithoutDayOfWeek = (date = '') => {
112
+ if (!date) return ''
113
+ const options = { year: 'numeric', month: 'short', day: 'numeric' }
114
+ return new Date(date).toLocaleDateString(undefined, options)
115
+ }
116
116
 
117
117
  const formatDateForDisplay = (raw_value) => {
118
- const date = new Date(raw_value);
119
- if (!raw_value || !date) return raw_value;
120
- const [, mon, day, year, time] = date.toString().split(" ");
121
- return [mon, `${day},`, year, time].join(" ");
122
- };
123
-
124
- const toTimeString = (date = "") => {
125
- if (!date) return "";
118
+ const date = new Date(raw_value)
119
+ if (!raw_value || !date) return raw_value
120
+ const [, mon, day, year, time] = date.toString().split(' ')
121
+ return [mon, `${day},`, year, time].join(' ')
122
+ }
123
+
124
+ const toTimeString = (date = '') => {
125
+ if (!date) return ''
126
126
  const options = {
127
- hour: "numeric",
128
- minute: "numeric",
129
- hour12: true,
130
- };
131
- return new Date(date).toLocaleTimeString("en-US", options);
132
- };
127
+ hour: 'numeric',
128
+ minute: 'numeric',
129
+ hour12: true
130
+ }
131
+ return new Date(date).toLocaleTimeString('en-US', options)
132
+ }
133
133
 
134
134
  const generateDefaultRange = () => {
135
- const [today] = new Date().toISOString().split("T");
136
- const [thirty_days_ago] = new Date(Date.parse(today) - 30 * 86400000).toISOString().split("T");
137
- return [thirty_days_ago, today];
138
- };
135
+ const [today] = new Date().toISOString().split('T')
136
+ const [thirty_days_ago] = new Date(Date.parse(today) - 30 * 86400000).toISOString().split('T')
137
+ return [thirty_days_ago, today]
138
+ }
139
139
 
140
140
  /**
141
141
  *
@@ -143,45 +143,45 @@ const generateDefaultRange = () => {
143
143
  * @returns {startDate, endDate}
144
144
  */
145
145
  const getYearRange = (year) => {
146
- const startDate = new Date(year, 0, 1).getTime(); // January 1st
147
- const endDate = new Date(year, 11, 31).getTime() + 86400000 - 1; // December 31st (23:59:59)
148
- return { startDate, endDate };
149
- };
146
+ const startDate = new Date(year, 0, 1).getTime() // January 1st
147
+ const endDate = new Date(year, 11, 31).getTime() + 86400000 - 1 // December 31st (23:59:59)
148
+ return { startDate, endDate }
149
+ }
150
150
 
151
151
  const getMonthTimestamps = (year) => {
152
- const timestamps = [];
152
+ const timestamps = []
153
153
 
154
154
  for (let month = 0; month < 12; month++) {
155
- const startDate = new Date(year, month, 1);
156
- const endDate = new Date(year, month + 1, 0, 23, 59, 59, 999); // Last day of the month
155
+ const startDate = new Date(year, month, 1)
156
+ const endDate = new Date(year, month + 1, 0, 23, 59, 59, 999) // Last day of the month
157
157
 
158
158
  timestamps.push({
159
159
  start: startDate.getTime(),
160
- end: endDate.getTime(),
161
- });
160
+ end: endDate.getTime()
161
+ })
162
162
  }
163
163
 
164
- return timestamps;
165
- };
164
+ return timestamps
165
+ }
166
166
 
167
167
  const getMonthNameFromTimestamp = (timestamp) => {
168
- const date = new Date(timestamp);
168
+ const date = new Date(timestamp)
169
169
  const months = [
170
- "January",
171
- "February",
172
- "March",
173
- "April",
174
- "May",
175
- "June",
176
- "July",
177
- "August",
178
- "September",
179
- "October",
180
- "November",
181
- "December",
182
- ];
183
- return months[date.getMonth()];
184
- };
170
+ 'January',
171
+ 'February',
172
+ 'March',
173
+ 'April',
174
+ 'May',
175
+ 'June',
176
+ 'July',
177
+ 'August',
178
+ 'September',
179
+ 'October',
180
+ 'November',
181
+ 'December'
182
+ ]
183
+ return months[date.getMonth()]
184
+ }
185
185
 
186
186
  module.exports = {
187
187
  convertDateFromIsoToHTMLFormat,
@@ -200,5 +200,5 @@ module.exports = {
200
200
  toTimeString,
201
201
  getYearRange,
202
202
  getMonthTimestamps,
203
- getMonthNameFromTimestamp,
204
- };
203
+ getMonthNameFromTimestamp
204
+ }
@@ -1,9 +1,9 @@
1
- const Chart = require("./chart");
2
- const Date = require("./date");
3
- const Number = require("./number");
1
+ const Chart = require('./chart')
2
+ const Date = require('./date')
3
+ const Number = require('./number')
4
4
 
5
5
  module.exports = {
6
6
  Chart,
7
7
  Date,
8
- Number,
9
- };
8
+ Number
9
+ }
@@ -1,7 +1,7 @@
1
1
  module.exports = {
2
2
  toReadableNumber: (value) => {
3
- if (!value) return 0;
4
- if (isNaN(value)) return value;
5
- return Number(Number(value).toFixed(2)).toLocaleString();
6
- },
7
- };
3
+ if (!value) return 0
4
+ if (isNaN(value)) return value
5
+ return Number(Number(value).toFixed(2)).toLocaleString()
6
+ }
7
+ }
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@go-mailer/jarvis",
3
- "version": "5.0.5",
3
+ "version": "5.0.6",
4
4
  "main": "index.js",
5
5
  "repository": "git@github.com:go-mailer-ltd/jarvis-node.git",
6
6
  "author": "Nathan Oguntuberu <nateoguns.work@gmail.com>",
7
7
  "license": "MIT",
8
8
  "scripts": {
9
- "test": "mocha --recursive -w -c || true"
9
+ "test": "mocha --recursive -w -c || true",
10
+ "lint:fix": "eslint --fix . --ext .js"
10
11
  },
11
12
  "dependencies": {
12
13
  "@logtail/node": "^0.3.3",
@@ -18,6 +19,11 @@
18
19
  },
19
20
  "devDependencies": {
20
21
  "chai": "^4.3.7",
22
+ "eslint": "^7.32.0",
23
+ "eslint-config-standard": "^16.0.3",
24
+ "eslint-plugin-import": "^2.25.4",
25
+ "eslint-plugin-node": "^11.1.0",
26
+ "eslint-plugin-promise": "^5.2.0",
21
27
  "mocha": "^10.2.0"
22
28
  }
23
29
  }