@adtrackify/at-service-common 1.0.0 → 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 (139) hide show
  1. package/.babelrc +22 -0
  2. package/.editorconfig +12 -0
  3. package/.eslintrc.json +33 -0
  4. package/.husky/pre-push +4 -0
  5. package/dist/clients/dynamodb-client.d.ts +15 -0
  6. package/dist/clients/dynamodb-client.js +126 -0
  7. package/dist/clients/dynamodb-client.js.map +1 -0
  8. package/dist/clients/eventbridge-client.d.ts +13 -0
  9. package/dist/clients/eventbridge-client.js +43 -0
  10. package/dist/clients/eventbridge-client.js.map +1 -0
  11. package/dist/clients/http-client.d.ts +30 -0
  12. package/dist/clients/http-client.js +39 -0
  13. package/dist/clients/http-client.js.map +1 -0
  14. package/dist/clients/index.d.ts +3 -0
  15. package/dist/clients/index.js +20 -0
  16. package/dist/clients/index.js.map +1 -0
  17. package/dist/helpers/index.d.ts +3 -0
  18. package/dist/helpers/index.js +20 -0
  19. package/dist/helpers/index.js.map +1 -0
  20. package/dist/helpers/input-validation-helper.d.ts +2 -0
  21. package/dist/helpers/input-validation-helper.js +52 -0
  22. package/dist/helpers/input-validation-helper.js.map +1 -0
  23. package/dist/helpers/logging-helper.d.ts +1 -0
  24. package/dist/helpers/logging-helper.js +38 -0
  25. package/dist/helpers/logging-helper.js.map +1 -0
  26. package/dist/helpers/response-helper.d.ts +36 -0
  27. package/dist/helpers/response-helper.js +43 -0
  28. package/dist/helpers/response-helper.js.map +1 -0
  29. package/dist/index.d.ts +4 -0
  30. package/dist/index.js +21 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/libs/crypto.d.ts +1 -0
  33. package/dist/libs/crypto.js +13 -0
  34. package/dist/libs/crypto.js.map +1 -0
  35. package/dist/libs/dates.d.ts +3 -0
  36. package/dist/libs/dates.js +17 -0
  37. package/dist/libs/dates.js.map +1 -0
  38. package/dist/libs/http-error.d.ts +21 -0
  39. package/dist/libs/http-error.js +70 -0
  40. package/dist/libs/http-error.js.map +1 -0
  41. package/dist/libs/http-status-codes.d.ts +344 -0
  42. package/dist/libs/http-status-codes.js +349 -0
  43. package/dist/libs/http-status-codes.js.map +1 -0
  44. package/dist/libs/index.d.ts +4 -0
  45. package/dist/libs/index.js +21 -0
  46. package/dist/libs/index.js.map +1 -0
  47. package/dist/types/db/index.d.ts +1 -0
  48. package/dist/types/db/index.js +18 -0
  49. package/dist/types/db/index.js.map +1 -0
  50. package/dist/types/db/shopify-app-install.d.ts +28 -0
  51. package/dist/types/db/shopify-app-install.js +3 -0
  52. package/dist/types/db/shopify-app-install.js.map +1 -0
  53. package/dist/types/index.d.ts +1 -0
  54. package/dist/{cjs → types}/index.js +17 -17
  55. package/dist/types/index.js.map +1 -0
  56. package/env.yml +9 -0
  57. package/jest.config.js +39 -0
  58. package/package.json +53 -63
  59. package/prettier.config.js +9 -0
  60. package/src/clients/axios.d.ts +8 -0
  61. package/src/clients/dynamodb-client.ts +85 -0
  62. package/src/clients/eventbridge-client.ts +38 -0
  63. package/src/clients/http-client.ts +36 -0
  64. package/src/clients/index.ts +3 -0
  65. package/src/helpers/index.ts +3 -0
  66. package/src/helpers/input-validation-helper.ts +22 -0
  67. package/src/helpers/logging-helper.ts +10 -0
  68. package/src/helpers/response-helper.ts +40 -0
  69. package/src/index.ts +4 -0
  70. package/src/libs/crypto.ts +6 -0
  71. package/src/libs/dates.ts +14 -0
  72. package/src/libs/http-error.ts +100 -0
  73. package/src/libs/http-status-codes.ts +344 -0
  74. package/src/libs/index.ts +4 -0
  75. package/src/types/db/index.ts +1 -0
  76. package/src/types/db/shopify-app-install.ts +31 -0
  77. package/src/types/index.ts +1 -0
  78. package/tsconfig.json +25 -0
  79. package/tslint.json +6 -0
  80. package/README.md +0 -1
  81. package/dist/cjs/fingerprint.d.ts +0 -3
  82. package/dist/cjs/fingerprint.js +0 -9
  83. package/dist/cjs/fingerprint.js.map +0 -1
  84. package/dist/cjs/index.d.ts +0 -1
  85. package/dist/cjs/index.js.map +0 -1
  86. package/dist/cjs/sources/architecture.d.ts +0 -1
  87. package/dist/cjs/sources/architecture.js +0 -16
  88. package/dist/cjs/sources/architecture.js.map +0 -1
  89. package/dist/cjs/sources/cookie-enabled.d.ts +0 -1
  90. package/dist/cjs/sources/cookie-enabled.js +0 -12
  91. package/dist/cjs/sources/cookie-enabled.js.map +0 -1
  92. package/dist/cjs/sources/cpu-class.d.ts +0 -1
  93. package/dist/cjs/sources/cpu-class.js +0 -12
  94. package/dist/cjs/sources/cpu-class.js.map +0 -1
  95. package/dist/cjs/sources/device-memory.d.ts +0 -1
  96. package/dist/cjs/sources/device-memory.js +0 -12
  97. package/dist/cjs/sources/device-memory.js.map +0 -1
  98. package/dist/cjs/sources/platform.d.ts +0 -1
  99. package/dist/cjs/sources/platform.js +0 -12
  100. package/dist/cjs/sources/platform.js.map +0 -1
  101. package/dist/cjs/sources/plugins.d.ts +0 -1
  102. package/dist/cjs/sources/plugins.js +0 -26
  103. package/dist/cjs/sources/plugins.js.map +0 -1
  104. package/dist/cjs/sources/timezone.d.ts +0 -1
  105. package/dist/cjs/sources/timezone.js +0 -12
  106. package/dist/cjs/sources/timezone.js.map +0 -1
  107. package/dist/cjs/sources/user-agent.d.ts +0 -1
  108. package/dist/cjs/sources/user-agent.js +0 -12
  109. package/dist/cjs/sources/user-agent.js.map +0 -1
  110. package/dist/esm/fingerprint.d.ts +0 -3
  111. package/dist/esm/fingerprint.js +0 -5
  112. package/dist/esm/fingerprint.js.map +0 -1
  113. package/dist/esm/index.d.ts +0 -1
  114. package/dist/esm/index.js +0 -2
  115. package/dist/esm/index.js.map +0 -1
  116. package/dist/esm/sources/architecture.d.ts +0 -1
  117. package/dist/esm/sources/architecture.js +0 -13
  118. package/dist/esm/sources/architecture.js.map +0 -1
  119. package/dist/esm/sources/cookie-enabled.d.ts +0 -1
  120. package/dist/esm/sources/cookie-enabled.js +0 -9
  121. package/dist/esm/sources/cookie-enabled.js.map +0 -1
  122. package/dist/esm/sources/cpu-class.d.ts +0 -1
  123. package/dist/esm/sources/cpu-class.js +0 -9
  124. package/dist/esm/sources/cpu-class.js.map +0 -1
  125. package/dist/esm/sources/device-memory.d.ts +0 -1
  126. package/dist/esm/sources/device-memory.js +0 -9
  127. package/dist/esm/sources/device-memory.js.map +0 -1
  128. package/dist/esm/sources/platform.d.ts +0 -1
  129. package/dist/esm/sources/platform.js +0 -9
  130. package/dist/esm/sources/platform.js.map +0 -1
  131. package/dist/esm/sources/plugins.d.ts +0 -1
  132. package/dist/esm/sources/plugins.js +0 -22
  133. package/dist/esm/sources/plugins.js.map +0 -1
  134. package/dist/esm/sources/timezone.d.ts +0 -1
  135. package/dist/esm/sources/timezone.js +0 -9
  136. package/dist/esm/sources/timezone.js.map +0 -1
  137. package/dist/esm/sources/user-agent.d.ts +0 -1
  138. package/dist/esm/sources/user-agent.js +0 -9
  139. package/dist/esm/sources/user-agent.js.map +0 -1
package/package.json CHANGED
@@ -1,27 +1,19 @@
1
1
  {
2
2
  "name": "@adtrackify/at-service-common",
3
- "version": "1.0.0",
4
- "description": "Upstackified fingerprint module",
5
- "files": [
6
- "dist/*"
7
- ],
8
- "main": "./dist/cjs/index.js",
9
- "module": "./dist/esm/index.js",
10
- "type": "module",
11
- "engines": {
12
- "npm": ">=8.0.0 <9.0.0",
13
- "node": ">=16.0.0 <18.14.2"
14
- },
3
+ "version": "1.0.1",
4
+ "description": "",
5
+ "main": "dist/index.ts",
6
+ "types": "dist/index.d.ts",
15
7
  "scripts": {
16
8
  "clean": "rimraf dist",
17
- "build": "cross-env NODE_ENV=production npm run tsc",
9
+ "build": "node ./node_modules/typescript/bin/tsc",
18
10
  "build:dev": "npm run clean && npm run verify && cross-env NODE_ENV=production stage=dev APP_ENV=dev npm run build",
19
- "build:qa": "npm run clean && npm run verify && cross-env NODE_ENV=production stage=qa APP_ENV=qa npm run build",
20
- "build:prod": "npm run clean && npm run verify && cross-env NODE_ENV=production stage=prod APP_ENV=prod npm run build",
21
- "elint": "eslint .",
11
+ "build:qa": "npm run clean && npm run verify && cross-env NODE_ENV=production stage=qa APP_ENV=qa webpack",
12
+ "build:prod": "npm run clean && npm run verify && cross-env NODE_ENV=production stage=prod APP_ENV=prod webpack",
13
+ "elint": "eslint --ignore-path .gitignore .",
22
14
  "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
23
- "lint": "eslint src/",
24
- "lint:fix": "eslint . --fix",
15
+ "lint": "tslint -p tsconfig.json",
16
+ "lint:fix": "eslint --ignore-path .gitignore . --fix",
25
17
  "coverage": "npm run test:all -- --coverage --group=unit",
26
18
  "test": "jest --group=unit --coverage",
27
19
  "test:all": "cross-env AWS_REGION=us-east-2 NODE_ENV=test jest --group=unit --coverage",
@@ -29,72 +21,70 @@
29
21
  "verify": "npm run clean && npm run type-check && npm run lint:fix",
30
22
  "version": "npm run format && git add -A src",
31
23
  "postversion": "git push && git push --tags",
32
- "tsc": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json",
33
- "push": "npm install && npm run build:dev && npm publish --verbose",
34
- "type-check": "tsc --noEmit",
35
- "prepublishOnly": "npm run tsc"
24
+ "type-check": "tsc --noEmit"
25
+ },
26
+ "dependencies": {
27
+ "@types/axios": "^0.14.0",
28
+ "@types/deep-freeze": "^0.1.2",
29
+ "@types/ua-parser-js": "^0.7.36",
30
+ "aws-sdk": "^2.1189.0",
31
+ "axios": "^0.27.2",
32
+ "axios-retry": "^3.3.1",
33
+ "crypto": "^1.0.1",
34
+ "esbuild": "^0.14.53",
35
+ "http-status-codes": "^2.2.0",
36
+ "joi": "^17.6.0",
37
+ "lambda-log": "^3.1.0",
38
+ "typescript": "^4.7.4",
39
+ "ua-parser-js": "^1.0.2"
36
40
  },
37
- "dependencies": {},
38
- "peerDependencies": {},
39
41
  "devDependencies": {
40
- "@adtrackify/at-tracking-event-types": "^2.0.42",
41
- "@aws-sdk/client-cognito-identity-provider": "^3.345.0",
42
- "@aws-sdk/client-dynamodb": "^3.345.0",
43
- "@aws-sdk/client-eventbridge": "^3.345.0",
44
- "@aws-sdk/client-s3": "^3.345.0",
45
- "@aws-sdk/client-sqs": "^3.345.0",
46
- "@aws-sdk/lib-dynamodb": "^3.345.0",
47
- "@faker-js/faker": "^7.5.0",
48
- "@swc/core": "^1.3.1",
49
- "@swc/jest": "^0.2.22",
50
- "@types/jest": "^28.1.8",
51
- "@types/lambda-log": "^3.0.0",
52
- "@types/luxon": "^3.0.1",
42
+ "@babel/cli": "^7.13.16",
43
+ "@babel/core": "^7.13.10",
44
+ "@babel/plugin-proposal-optional-chaining": "^7.13.8",
45
+ "@babel/plugin-transform-runtime": "^7.10.3",
46
+ "@babel/preset-env": "^7.16.8",
47
+ "@babel/preset-typescript": "^7.16.7",
48
+ "@babel/runtime-corejs3": "^7.13.17",
49
+ "@types/jest": "^27.4.1",
50
+ "@types/lambda-log": "^2.2.1",
51
+ "@types/luxon": "^3.0.0",
53
52
  "@types/node": "^17.0.8",
54
- "@types/ua-parser-js": "^0.7.36",
55
- "@types/uuid": "^8.3.4",
56
- "@typescript-eslint/eslint-plugin": "^5.37.0",
57
- "@typescript-eslint/parser": "^5.37.0",
58
- "core-js": "^3.25.1",
53
+ "@typescript-eslint/eslint-plugin": "^5.21.0",
54
+ "@typescript-eslint/parser": "^5.21.0",
55
+ "babel-eslint": "^10.1.0",
56
+ "babel-jest": "^26.6.3",
57
+ "babel-loader": "^8.2.2",
58
+ "babel-polyfill": "^6.26.0",
59
+ "core-js": "^3.21.1",
59
60
  "cross-env": "^7.0.3",
60
- "esbuild": "^0.17.1",
61
- "eslint": "^8.23.1",
61
+ "eslint": "^8.14.0",
62
62
  "eslint-config-standard": "^17.0.0",
63
+ "eslint-loader": "^4.0.2",
63
64
  "eslint-plugin-babel": "^5.3.1",
64
65
  "eslint-plugin-import": "^2.26.0",
65
- "eslint-plugin-n": "^15.2.5",
66
- "eslint-plugin-promise": "^6.0.1",
66
+ "eslint-plugin-n": "^15.2.0",
67
+ "eslint-plugin-promise": "^6.0.0",
68
+ "eslint-webpack-plugin": "^3.1.1",
67
69
  "glob": "^8.0.3",
68
70
  "husky": "^6.0.0",
69
- "jest": "^29.2.1",
71
+ "jest": "^27.5.1",
70
72
  "jest-cucumber": "3.0.1",
71
73
  "jest-junit": "13.0.0",
72
- "jest-runner": "^29.0.2",
73
- "jest-runner-groups": "2.2.0",
74
- "npm-dts": "^1.3.12",
74
+ "jest-runner-groups": "2.1.0",
75
75
  "npm-run-all": "^4.1.5",
76
76
  "npm-scripts-info": "^0.3.9",
77
77
  "prettier": "^2.7.1",
78
78
  "regenerator-runtime": "^0.13.9",
79
79
  "rimraf": "^3.0.2",
80
- "swc-loader": "^0.2.3",
81
- "ts-jest": "^29.0.5",
82
- "ts-jest-resolver": "^2.0.1",
83
- "ts-loader": "^9.4.2",
84
- "ts-node": "^10.9.1",
85
80
  "tslint": "^6.1.3",
86
- "tslint-config-prettier": "^1.18.0",
87
- "typescript": "4.9.5"
81
+ "tslint-config-prettier": "^1.18.0"
88
82
  },
89
83
  "repository": {
90
84
  "type": "git",
91
- "url": "git+https://yash-upstackified@bitbucket.org/eacap/fingerprint.git"
85
+ "url": "git+ssh://git@bitbucket.org/eacap/at-tracking-event-types.git"
92
86
  },
93
87
  "author": "",
94
88
  "license": "ISC",
95
- "keywords": [],
96
- "bugs": {
97
- "url": "https://bitbucket.org/eacap/fingerprint/issues"
98
- },
99
- "homepage": "https://bitbucket.org/eacap/fingerprint#readme"
89
+ "homepage": "https://bitbucket.org/eacap/at-tracking-event-types#readme"
100
90
  }
@@ -0,0 +1,9 @@
1
+ /*eslint-disable */
2
+
3
+ module.exports = {
4
+ trailingComma: 'es5',
5
+ tabWidth: 2,
6
+ semi: false,
7
+ singleQuote: true,
8
+ };
9
+ /*eslint-enable */
@@ -0,0 +1,8 @@
1
+ declare module 'axios/lib/adapters/http' {
2
+ import { AxiosAdapter } from 'axios';
3
+
4
+ const httpAdapter: AxiosAdapter;
5
+ namespace httpAdapter { }
6
+
7
+ export = httpAdapter;
8
+ }
@@ -0,0 +1,85 @@
1
+ import AWS from 'aws-sdk';
2
+ import * as log from 'lambda-log';
3
+ import { BatchGetItemInput, DeleteItemInput, GetItemInput, PutItemInput, QueryInput, QueryOutput, ScanInput, UpdateItemInput } from 'aws-sdk/clients/dynamodb';
4
+ const client = new AWS.DynamoDB.DocumentClient();
5
+
6
+ export default class DynamoDbClient {
7
+ static safeGet = async (tableName: string, keyName: string, keyValue: any) => {
8
+ try {
9
+ const params = {
10
+ TableName: tableName,
11
+ Key: {
12
+ [keyName]: keyValue
13
+ }
14
+ };
15
+ const res = await client.get(params).promise();
16
+ return res?.Item ?? null;
17
+ } catch (e: any) {
18
+ log.error(e, { message: 'Dynamo Client Get Failed' });
19
+ return null;
20
+ }
21
+ };
22
+
23
+ static safePut = async (tableName: string, data: any) => {
24
+ try {
25
+ const params = {
26
+ TableName: tableName,
27
+ Item: data
28
+ };
29
+ const res = await client.put(params).promise();
30
+ return res;
31
+ } catch (e: any) {
32
+ log.error(e, { message: 'Dynamo failed simplePut' })
33
+ return null;
34
+ }
35
+ };
36
+
37
+ static safeBatchGet = async (tableName: string, keys: AWS.DynamoDB.KeyList) => {
38
+ try {
39
+ const params: BatchGetItemInput = {
40
+ RequestItems: {}
41
+ };
42
+ params.RequestItems[tableName] = {
43
+ Keys: keys
44
+ };
45
+ const res = await client.batchGet(params).promise();
46
+ log.info('batchget res', { batchGetRes: res })
47
+ if (res?.Responses?.[tableName]) {
48
+ return res?.Responses?.[tableName];
49
+ }
50
+ return [];
51
+ } catch (e: any) {
52
+ log.error(e, { message: 'Dynamo failed safeBatchGet' })
53
+ return [];
54
+ }
55
+ };
56
+
57
+ static queryAll = async (params: QueryInput) => {
58
+ try {
59
+ log.info('Invoke Query All', { params });
60
+ let currentResult: QueryOutput, exclusiveStartKey;
61
+ let accumulatedResults: any[] = [];
62
+ do {
63
+ params.ExclusiveStartKey = exclusiveStartKey;
64
+ params.Limit = 200;
65
+ currentResult = await client.query(params).promise();
66
+ if (currentResult.Items) {
67
+ exclusiveStartKey = currentResult.LastEvaluatedKey;
68
+ accumulatedResults = [...accumulatedResults, ...currentResult.Items];
69
+ }
70
+ } while (currentResult.Items && currentResult.Items.length > 0 && currentResult.LastEvaluatedKey);
71
+ return accumulatedResults;
72
+ } catch (e: any) {
73
+ log.error(e, { message: 'Dynamo failed queryAll' })
74
+ return null;
75
+ }
76
+ };
77
+
78
+ static batchGet = (params: BatchGetItemInput) => client.batchGet(params).promise();
79
+ static get = (params: GetItemInput) => client.get(params).promise();
80
+ static put = (params: PutItemInput) => client.put(params).promise();
81
+ static query = (params: QueryInput) => client.query(params).promise();
82
+ static scan = (params: ScanInput) => client.scan(params).promise();
83
+ static update = (params: UpdateItemInput) => client.update(params).promise();
84
+ static delete = (params: DeleteItemInput) => client.delete(params).promise();
85
+ }
@@ -0,0 +1,38 @@
1
+ import { EventBridge } from 'aws-sdk';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+ import { getCurrentTimestamp } from '../libs/dates';
4
+
5
+ export class EventBridgeClient {
6
+ public eventBridge: EventBridge;
7
+ public EVENT_BUS_NAME: string;
8
+
9
+ constructor (eventBusName: string) {
10
+ this.eventBridge = new EventBridge();
11
+ this.EVENT_BUS_NAME = eventBusName;
12
+ }
13
+
14
+ public buildEvent = (eventType: string, eventData: any, eventId: string = uuidv4(), eventTime: string = getCurrentTimestamp()) => {
15
+ return {
16
+ eventId,
17
+ eventType,
18
+ eventTime,
19
+ eventData
20
+ };
21
+ };
22
+
23
+
24
+ public putEvent = async (source: string, detailType: string, data: any, headers: any = null) => {
25
+ const params = {
26
+ Entries: [ {
27
+ Detail: JSON.stringify({ headers, data }),
28
+ DetailType: detailType,
29
+ EventBusName: this.EVENT_BUS_NAME,
30
+ Source: source,
31
+ Time: new Date(),
32
+ } ],
33
+ };
34
+ return await this.eventBridge.putEvents(params).promise();
35
+ };
36
+
37
+ }
38
+
@@ -0,0 +1,36 @@
1
+ import axios, { AxiosRequestConfig } from 'axios';
2
+ import axiosRetry from 'axios-retry';
3
+ import https from 'https'
4
+ import httpAdapter from 'axios/lib/adapters/http';
5
+
6
+ const httpResponse = (res: any = {}) => {
7
+ return {
8
+ headers: res?.header || {},
9
+ data: res?.data || {},
10
+ status: res?.status || 0,
11
+ };
12
+ };
13
+
14
+ export const axiosHttpService = (config: AxiosRequestConfig = {}) => {
15
+ config.adapter = httpAdapter;
16
+ config.httpsAgent = new https.Agent({ keepAlive: true });
17
+ const axiosService = axios.create(config);
18
+
19
+ axiosRetry(axiosService, { retryDelay: axiosRetry.exponentialDelay, retries: 3 });
20
+
21
+ const handleAxiosError = (error: any) => {
22
+ if (!error?.response && !error?.request) throw error;
23
+ return error.response ? httpResponse(error.response) : httpResponse({ status: 500, data: { error: error.request } });
24
+ };
25
+
26
+ return {
27
+ instance: () => axiosService,
28
+ get: (url: string, config?: AxiosRequestConfig) => axiosService.get(url, config).then(httpResponse, handleAxiosError),
29
+ post: (url: string, data?: any, config?: AxiosRequestConfig) => axiosService.post(url, data, config).then(httpResponse, handleAxiosError),
30
+ delete: (url: string, config?: AxiosRequestConfig) => axiosService.delete(url, config).then(httpResponse, handleAxiosError),
31
+ put: (url: string, data?: any, config?: AxiosRequestConfig) => axiosService.put(url, data, config).then(httpResponse, handleAxiosError),
32
+ patch: (url: string, data?: any, config?: AxiosRequestConfig) => axiosService.patch(url, data, config).then(httpResponse, handleAxiosError),
33
+ setBaseUrl: (url: string) => !!(axiosService.defaults.baseURL = url)
34
+ }
35
+ }
36
+
@@ -0,0 +1,3 @@
1
+ export * from './dynamodb-client';
2
+ export * from './eventbridge-client';
3
+ export * from './http-client';
@@ -0,0 +1,3 @@
1
+ export * from './input-validation-helper';
2
+ export * from './logging-helper';
3
+ export * from './response-helper'
@@ -0,0 +1,22 @@
1
+ import HttpError from '../libs/http-error';
2
+ import * as log from 'lambda-log';
3
+ import Joi from 'joi';
4
+
5
+ export const validateInput = (schema: Joi.ObjectSchema<any>, input: any) => {
6
+ const { error, value } = schema.validate(input);
7
+ if (error) {
8
+ log.info('', { error });
9
+
10
+ const httperr = HttpError.badRequest('Input Validation Failure', {
11
+ errors: error.details.map(detail => ({
12
+ message: detail?.message,
13
+ key: detail?.context?.key,
14
+ path: detail?.path,
15
+ }))
16
+ });
17
+
18
+ log.info('', { httperr });
19
+ throw httperr;
20
+ }
21
+ return value;
22
+ }
@@ -0,0 +1,10 @@
1
+ import * as log from 'lambda-log';
2
+ const stage = process?.env?.STAGE;
3
+
4
+ export const configureLogger = (event: any, context: any, debug: boolean = true) => {
5
+ log.options.meta.stage = stage;
6
+ log.options.meta.source_name = context?.functionName || 'unknown';
7
+ log.options.meta.awsRequestId = context?.awsRequestId || 'unknown';
8
+ log.options.meta.lambdaEvent = event;
9
+ log.options.debug = debug;
10
+ }
@@ -0,0 +1,40 @@
1
+
2
+ export const success = (body: any) => {
3
+ return buildResponse(200, body);
4
+ }
5
+
6
+ const defaultError = {
7
+ message: 'internalServerError'
8
+ }
9
+
10
+ export const failure = (error: any, statusCode: number = 500) => {
11
+ statusCode = error?.statusCode ?? statusCode;
12
+
13
+ let body = defaultError;
14
+ if (error?.body) {
15
+ body = error.body;
16
+ }
17
+ else if (error?.message) {
18
+ body = { message: error.message };
19
+ } else if (statusCode === 500) {
20
+ body = defaultError;
21
+ }
22
+ return buildResponse(statusCode, body);
23
+ }
24
+
25
+ export const buildResponse = (statusCode: number, body: any = {}) => {
26
+ delete body.stack;
27
+ return {
28
+ statusCode: statusCode,
29
+ headers: {
30
+ 'Access-Control-Allow-Origin': '*',
31
+ 'Access-Control-Allow-Credentials': true,
32
+ 'cache-control': 'max-age=86400',
33
+ Date: new Date(),
34
+ 'Last-Modified': new Date(),
35
+ 'Access-Control-Allow-Headers':
36
+ 'Content-Type, Content-Encoding'
37
+ },
38
+ body: JSON.stringify(body),
39
+ };
40
+ }
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './clients';
2
+ export * from './helpers';
3
+ export * from './libs';
4
+ export * from './types';
@@ -0,0 +1,6 @@
1
+ import crypto from 'crypto';
2
+
3
+ export const generatePublicKey = (): string => {
4
+ const publicKey = crypto.randomBytes(26);
5
+ return publicKey.toString('utf8');
6
+ };
@@ -0,0 +1,14 @@
1
+
2
+ import { DateTime } from 'luxon';
3
+
4
+ export const getCurrentTimestamp = (): string => {
5
+ return DateTime.utc().toJSDate().toISOString();
6
+ }
7
+
8
+ export const getDateFromTimestamp = (timestamp: string) => {
9
+ return timestamp.split('T')[0];
10
+ }
11
+
12
+ export const getCurrentDate = (): string => {
13
+ return getDateFromTimestamp(getCurrentTimestamp());
14
+ }
@@ -0,0 +1,100 @@
1
+ /* eslint-disable no-dupe-class-members */
2
+ import { strict as assert } from 'assert';
3
+ import deepFreeze from 'deep-freeze';
4
+
5
+ const deepClone = (o = {}) => JSON.parse(JSON.stringify(o));
6
+ const containsStackTrace = (text: string = '') => /at.+\.js:\d+:\d+/.test(text);
7
+ const objectContainsStackTrace = (obj: any) =>
8
+ !obj ? false : containsStackTrace(JSON.stringify(obj));
9
+
10
+ // may only be expanded by governance, never reduced
11
+ const supportedStatusCodes: any = {
12
+ 400: 'Bad Request',
13
+ 401: 'Unauthorized',
14
+ 403: 'Forbidden',
15
+ 404: 'Not Found',
16
+ 405: 'Method Not Allowed',
17
+ 409: 'Conflict',
18
+ 412: 'Precondition Failed',
19
+ 413: 'Payload Too Large',
20
+ 415: 'Unsupported Media Type',
21
+ 428: 'Precondition Required',
22
+ 429: 'Too Many Requests',
23
+ 500: 'Internal Server Error',
24
+ 501: 'Not Implemented',
25
+ 502: 'Bad Gateway',
26
+ 503: 'Service Unavailable',
27
+ 504: 'Gateway Timeout'
28
+ };
29
+
30
+ const supportedStatusCodesMessage = `statusCode must be one of the following: ${JSON.stringify(Object.keys(supportedStatusCodes))}`;
31
+ const onlyStatusCodeMessage = 'Server errors may not specify any parameter except statusCode';
32
+
33
+ const isNullOrUndefined = (value: any) => value === null || value === undefined;
34
+
35
+ export default class HttpError extends Error {
36
+ body: {
37
+ [key: string]: any;
38
+ };
39
+ headers: object[];
40
+ statusCode: number;
41
+ isServerError: boolean;
42
+
43
+ constructor(statusCode: number,
44
+ message?: string,
45
+ body?: {
46
+ [key: string]: any;
47
+ },
48
+ headers?: object[]) {
49
+ assert(statusCode in supportedStatusCodes, supportedStatusCodesMessage);
50
+
51
+ const isServerError = statusCode > 499;
52
+
53
+ if (isServerError) {
54
+ assert(
55
+ isNullOrUndefined(message) && isNullOrUndefined(body),
56
+ onlyStatusCodeMessage
57
+ );
58
+
59
+ message = supportedStatusCodes[statusCode] as string;
60
+ } else {
61
+ assert(
62
+ body === undefined || typeof body === 'object',
63
+ 'body must be an object or omitted'
64
+ );
65
+ assert(
66
+ headers === undefined || typeof headers === 'object',
67
+ 'headers must be an object or omitted'
68
+ );
69
+
70
+ message = message ?? supportedStatusCodes[statusCode];
71
+
72
+ assert(
73
+ !containsStackTrace(message) && !objectContainsStackTrace(body),
74
+ 'the message or data parameters may not contain errors or stack traces'
75
+ );
76
+ }
77
+
78
+ super(message);
79
+
80
+ this.body = deepClone(body);
81
+ this.headers = deepFreeze(deepClone(headers));
82
+ this.statusCode = statusCode;
83
+ this.isServerError = isServerError;
84
+ if (!this?.body?.message) {
85
+ this.body.message = this.message;
86
+ }
87
+ }
88
+
89
+
90
+ static get supportedStatusCodes() { return supportedStatusCodes; }
91
+ static badRequest = (message?: string, body?: object, headers?: object[]) => { return new HttpError(400, message, body, headers) };
92
+ static unauthorized = (message?: string, body?: object, headers?: object[]) => new HttpError(401, message, body, headers);
93
+ static forbidden = (message?: string, body?: object, headers?: object[]) => new HttpError(403, message, body, headers);
94
+ static notFound = (message?: string, body?: object, headers?: object[]) => new HttpError(404, message, body, headers);
95
+ static internal = (message?: string, body?: object, headers?: object[]) => new HttpError(500, message, body, headers);
96
+ static notImplemented = () => new HttpError(501);
97
+ static badGateway = () => new HttpError(502);
98
+ static serviceUnavailable = (headers: object[]) => new HttpError(503, undefined, undefined, headers);
99
+ static gatewayTimeout = () => new HttpError(504);
100
+ }