@eyevinn/player-analytics-shared 0.5.0

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 (56) hide show
  1. package/.github/workflows/build-test.yml +19 -0
  2. package/.github/workflows/release-gh-package.yml +24 -0
  3. package/.github/workflows/release-npmjs-package.yml +21 -0
  4. package/README.md +2 -0
  5. package/adapters/db/DynamoDBAdapter.ts +147 -0
  6. package/adapters/db/MongoDBAdapter.ts +79 -0
  7. package/adapters/queue/BeanstalkdAdapter.ts +41 -0
  8. package/adapters/queue/RedisAdapter.ts +34 -0
  9. package/adapters/queue/SqsQueueAdapter.ts +127 -0
  10. package/build/adapters/db/DynamoDBAdapter.d.ts +14 -0
  11. package/build/adapters/db/DynamoDBAdapter.js +138 -0
  12. package/build/adapters/db/DynamoDBAdapter.js.map +1 -0
  13. package/build/adapters/db/MongoDBAdapter.d.ts +16 -0
  14. package/build/adapters/db/MongoDBAdapter.js +98 -0
  15. package/build/adapters/db/MongoDBAdapter.js.map +1 -0
  16. package/build/adapters/queue/BeanstalkdAdapter.d.ts +13 -0
  17. package/build/adapters/queue/BeanstalkdAdapter.js +55 -0
  18. package/build/adapters/queue/BeanstalkdAdapter.js.map +1 -0
  19. package/build/adapters/queue/RedisAdapter.d.ts +12 -0
  20. package/build/adapters/queue/RedisAdapter.js +44 -0
  21. package/build/adapters/queue/RedisAdapter.js.map +1 -0
  22. package/build/adapters/queue/SqsQueueAdapter.d.ts +12 -0
  23. package/build/adapters/queue/SqsQueueAdapter.js +122 -0
  24. package/build/adapters/queue/SqsQueueAdapter.js.map +1 -0
  25. package/build/index.d.ts +6 -0
  26. package/build/index.js +19 -0
  27. package/build/index.js.map +1 -0
  28. package/build/types/db.d.ts +32 -0
  29. package/build/types/db.js +12 -0
  30. package/build/types/db.js.map +1 -0
  31. package/build/types/interfaces.d.ts +2 -0
  32. package/build/types/interfaces.js +15 -0
  33. package/build/types/interfaces.js.map +1 -0
  34. package/build/types/queue.d.ts +15 -0
  35. package/build/types/queue.js +7 -0
  36. package/build/types/queue.js.map +1 -0
  37. package/build/util/constants.d.ts +1 -0
  38. package/build/util/constants.js +5 -0
  39. package/build/util/constants.js.map +1 -0
  40. package/build/util/logger.d.ts +3 -0
  41. package/build/util/logger.js +37 -0
  42. package/build/util/logger.js.map +1 -0
  43. package/index.ts +8 -0
  44. package/package.json +43 -0
  45. package/spec/adapters/DynamoDBAdapter.spec.ts +275 -0
  46. package/spec/adapters/MongoDBAdapter.spec.ts +170 -0
  47. package/spec/adapters/SqsQueueAdapter.spec.ts +149 -0
  48. package/spec/support/jasmine.json +11 -0
  49. package/tsconfig-build.json +6 -0
  50. package/tsconfig.json +21 -0
  51. package/tslint.json +9 -0
  52. package/types/db.ts +39 -0
  53. package/types/interfaces.ts +2 -0
  54. package/types/queue.ts +17 -0
  55. package/util/constants.ts +1 -0
  56. package/util/logger.ts +45 -0
@@ -0,0 +1,19 @@
1
+ name: Run tests
2
+ on: push
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ matrix:
8
+ node-version: [14.x]
9
+ steps:
10
+ - uses: actions/checkout@v1
11
+ - name: Use Node.js ${{ matrix.node-version }}
12
+ uses: actions/setup-node@v1
13
+ with:
14
+ node-version: ${{ matrix.node-version }}
15
+ - name: Install dependencies and run tests
16
+ run: |
17
+ npm ci
18
+ npm install
19
+ npm test
@@ -0,0 +1,24 @@
1
+
2
+ name: Publish GitHub Package
3
+ on:
4
+ release:
5
+ types: [published]
6
+ jobs:
7
+ publish-gpr:
8
+ runs-on: ubuntu-latest
9
+ permissions:
10
+ packages: write
11
+ contents: read
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - uses: actions/setup-node@v2
15
+ with:
16
+ node-version: 14.x
17
+ registry-url: https://npm.pkg.github.com/
18
+ - run: npm ci
19
+ - run: npm install
20
+ - run: npm test
21
+ - run: npm run build --if-present
22
+ - run: npm publish
23
+ env:
24
+ NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
@@ -0,0 +1,21 @@
1
+
2
+ name: Publish Package on NPM
3
+ on:
4
+ release:
5
+ types: [published]
6
+ jobs:
7
+ publish-npmjs:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/checkout@v2
11
+ - uses: actions/setup-node@v2
12
+ with:
13
+ node-version: 14.x
14
+ registry-url: https://registry.npmjs.org/
15
+ - run: npm ci
16
+ - run: npm install
17
+ - run: npm test
18
+ - run: npm run build --if-present
19
+ - run: npm publish --access public
20
+ env:
21
+ NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
package/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # player-analytics-shared
2
+ Shared modules & adapters for EPAS components
@@ -0,0 +1,147 @@
1
+ import {
2
+ CreateTableCommand,
3
+ ListTablesCommand,
4
+ PutItemCommand,
5
+ DynamoDBClient,
6
+ GetItemCommand,
7
+ DeleteItemCommand,
8
+ QueryCommand,
9
+ QueryCommandInput,
10
+ QueryCommandOutput,
11
+ DescribeTableCommand,
12
+ DescribeTableCommandInput
13
+ } from '@aws-sdk/client-dynamodb';
14
+ import { marshall, unmarshall } from '@aws-sdk/util-dynamodb';
15
+ import winston from 'winston';
16
+ import {
17
+ AbstractDBAdapter,
18
+ IGetItemInput,
19
+ IGetItems,
20
+ IPutItemInput,
21
+ IHandleErrorOutput,
22
+ ErrorType,
23
+ } from '../../types/interfaces';
24
+
25
+ export class DynamoDBAdapter implements AbstractDBAdapter {
26
+ logger: winston.Logger;
27
+ dbClient: DynamoDBClient;
28
+
29
+ constructor(logger: winston.Logger) {
30
+ this.dbClient = new DynamoDBClient({
31
+ region: process.env.AWS_REGION,
32
+ maxAttempts: 5,
33
+ });
34
+ this.logger = logger;
35
+ }
36
+
37
+ async tableExists(name: string): Promise<boolean> {
38
+ try {
39
+ const params: DescribeTableCommandInput = { TableName: name };
40
+ const tablesData = await this.dbClient.send(new DescribeTableCommand(params));
41
+ if (tablesData['Table'] && tablesData['Table'].TableStatus === 'ACTIVE') return true;
42
+ return false;
43
+ } catch (awsError) {
44
+ if (awsError.name && awsError.name === 'ResourceNotFoundException') {
45
+ return false;
46
+ } else {
47
+ this.logger.error(awsError);
48
+ throw new Error(awsError);
49
+ }
50
+ }
51
+ }
52
+
53
+ async putItem(params: IPutItemInput): Promise<boolean> {
54
+ try {
55
+ const data = await this.dbClient.send(
56
+ new PutItemCommand({
57
+ TableName: params.tableName,
58
+ Item: marshall(params.data),
59
+ })
60
+ );
61
+ return data.$metadata.httpStatusCode === 200;
62
+ } catch (err) {
63
+ throw this.handleError(err);
64
+ }
65
+ }
66
+
67
+ async getItem(params: IGetItemInput): Promise<any> {
68
+ try {
69
+ const data = await this.dbClient.send(
70
+ new GetItemCommand({
71
+ TableName: params.tableName,
72
+ Key: marshall({
73
+ sessionId: params.sessionId,
74
+ timestamp: params.timestamp,
75
+ }),
76
+ })
77
+ );
78
+ this.logger.debug('Read Item from Table');
79
+ return data;
80
+ } catch (err) {
81
+ throw this.handleError(err);
82
+ }
83
+ }
84
+
85
+ async deleteItem(params: IGetItemInput): Promise<boolean> {
86
+ try {
87
+ const data = await this.dbClient.send(
88
+ new DeleteItemCommand({
89
+ TableName: params.tableName,
90
+ Key: marshall({
91
+ sessionId: params.sessionId,
92
+ timestamp: params.timestamp,
93
+ }),
94
+ })
95
+ );
96
+ this.logger.debug('Deleted Item from Table', data);
97
+ return data.$metadata.httpStatusCode === 200;
98
+ } catch (err) {
99
+ throw this.handleError(err);
100
+ }
101
+ }
102
+
103
+ async getItemsBySession(params: IGetItems): Promise<any[]> {
104
+ try {
105
+ const inputData: QueryCommandInput = {
106
+ TableName: params.tableName,
107
+ KeyConditionExpression: '#sid = :sid',
108
+ ExpressionAttributeNames: {
109
+ '#sid': 'sessionId',
110
+ },
111
+ ExpressionAttributeValues: marshall({
112
+ ':sid': params.sessionId,
113
+ }),
114
+ };
115
+ const queryData: QueryCommandOutput = await this.dbClient.send(
116
+ new QueryCommand(inputData)
117
+ );
118
+ if (queryData.Items && queryData.Items.length > 0) {
119
+ let items: any[] = [];
120
+ for (let i = 0; i < queryData.Items.length; i++) {
121
+ items[i] = unmarshall(queryData.Items[i]);
122
+ }
123
+ return items;
124
+ }
125
+ return [];
126
+ } catch (err) {
127
+ throw this.handleError(err);
128
+ }
129
+ }
130
+
131
+ handleError(errorObject: any): IHandleErrorOutput {
132
+ this.logger.error(errorObject);
133
+ const errorOutput: IHandleErrorOutput = {
134
+ errorType: ErrorType.ABORT,
135
+ error: errorObject,
136
+ };
137
+ if (errorObject.name) {
138
+ if (
139
+ errorObject.name === 'ResourceNotFoundException' ||
140
+ errorObject.name === 'ResourceInUseException'
141
+ ) {
142
+ errorOutput['errorType'] = ErrorType.CONTINUE;
143
+ }
144
+ }
145
+ return errorOutput;
146
+ }
147
+ }
@@ -0,0 +1,79 @@
1
+ import { Logger } from "winston";
2
+ import { AbstractDBAdapter, IHandleErrorOutput, ErrorType, IPutItemInput, IGetItemInput, IGetItems } from "../../types/interfaces";
3
+ import { MongoClient } from "mongodb";
4
+
5
+ const DB_NAME = "EPAS";
6
+
7
+ export class MongoDBAdapter implements AbstractDBAdapter {
8
+ logger: Logger;
9
+ dbClient: MongoClient;
10
+
11
+ constructor(logger: Logger) {
12
+ const connectionString = process.env.MONGODB_URI || "mongodb://localhost";
13
+ this.dbClient = new MongoClient(connectionString);
14
+ this.connect()
15
+ this.logger = logger;
16
+ }
17
+
18
+ private async isConnected(): Promise<boolean> {
19
+ return !!await this.dbClient.db("admin").command({ ping: 1 });
20
+ }
21
+
22
+ private async connect(): Promise<void> {
23
+ await this.dbClient.connect();
24
+ }
25
+
26
+ public async tableExists(tableName: string): Promise<boolean> {
27
+ if (!await this.isConnected()) await this.connect();
28
+ const collections = await this.dbClient.db().collections();
29
+ const tableNames = collections.map((collection) => collection.collectionName);
30
+ return tableNames.includes(tableName);
31
+ }
32
+
33
+ public async putItem({ tableName, data }: IPutItemInput): Promise<boolean> {
34
+ try {
35
+ const collection = await this.dbClient.db().collection(tableName);
36
+ const result = await collection.insertOne(data);
37
+ return result.acknowledged;
38
+ } catch (error) {
39
+ throw this.handleError(error);
40
+ }
41
+ }
42
+
43
+ public async getItem({ sessionId, tableName, timestamp }: IGetItemInput): Promise<any> {
44
+ try {
45
+ const collection = await this.dbClient.db().collection(tableName);
46
+ const result = await collection.findOne({ sessionId: sessionId, timestamp: timestamp });
47
+ return result;
48
+ } catch (error) {
49
+ throw this.handleError(error);
50
+ }
51
+ }
52
+
53
+ public async deleteItem({ sessionId, tableName, timestamp }: IGetItemInput): Promise<boolean> {
54
+ try {
55
+ const collection = await this.dbClient.db().collection(tableName);
56
+ const result = await collection.deleteOne({ sessionId: sessionId, timestamp: timestamp });
57
+ return result.acknowledged;
58
+ } catch (error) {
59
+ throw this.handleError(error);
60
+ }
61
+ }
62
+ public async getItemsBySession({ tableName, sessionId }: IGetItems): Promise<any[]> {
63
+ try {
64
+ const collection = await this.dbClient.db().collection(tableName);
65
+ return await collection.find({ sessionId: sessionId }).toArray();
66
+ } catch (error) {
67
+ throw this.handleError(error);
68
+ }
69
+ }
70
+
71
+ public handleError(error: any): IHandleErrorOutput {
72
+ this.logger.error(error);
73
+ return {
74
+ errorType: ErrorType.ABORT,
75
+ error: error,
76
+ };
77
+ }
78
+
79
+ }
@@ -0,0 +1,41 @@
1
+ import { Client } from "node-beanstalk";
2
+ import winston from "winston";
3
+ import { AbstractQueueAdapter } from "../../types/interfaces";
4
+
5
+ export class BeanstalkdAdapter implements AbstractQueueAdapter {
6
+ logger: winston.Logger;
7
+ client: Client;
8
+
9
+ constructor(logger: winston.Logger) {
10
+ this.logger = logger;
11
+ this.client = new Client();
12
+ }
13
+
14
+ private async connect(): Promise<void> {
15
+ await this.client.connect();
16
+ }
17
+
18
+ async pushToQueue(body: Object): Promise<Object> {
19
+ if (!this.client.isConnected) await this.connect();
20
+ const result = await this.client.put(body);
21
+ return result;
22
+ }
23
+
24
+ async pullFromQueue(): Promise<Object> {
25
+ if (!this.client.isConnected) await this.connect();
26
+ const job = await this.client.reserveWithTimeout(1);
27
+ return job || {};
28
+ }
29
+
30
+ async removeFromQueue(body: Record<string, any>): Promise<boolean> {
31
+ if (!this.client.isConnected) await this.connect();
32
+ const jobId = body.id;
33
+ const result = await this.client.delete(jobId);
34
+ return result;
35
+ }
36
+
37
+ getEventJSONsFromMessages(body: any[]): Object[] {
38
+ this.logger.warn("Method not implemented.");
39
+ return body;
40
+ }
41
+ }
@@ -0,0 +1,34 @@
1
+ import RedisTaskQueue = require("redis-task-queue");
2
+ import winston from "winston";
3
+ import { AbstractQueueAdapter } from "../../types/interfaces";
4
+
5
+ export class RedisAdapter implements AbstractQueueAdapter {
6
+ logger: winston.Logger;
7
+ client: RedisTaskQueue;
8
+
9
+ constructor(logger: winston.Logger) {
10
+ this.logger = logger;
11
+ this.client = new RedisTaskQueue();
12
+ }
13
+
14
+ async pushToQueue(body: Object): Promise<Object> {
15
+ const result = await this.client.add({ data: body });
16
+ return result;
17
+ }
18
+
19
+ async pullFromQueue(): Promise<Object> {
20
+ const job = await this.client.get();
21
+ return job || {};
22
+ }
23
+
24
+ async removeFromQueue(body: Record<string, any>): Promise<boolean> {
25
+ const jobId = body.id;
26
+ const result = await this.client.getStatus(jobId);
27
+ return result === 'completed';
28
+ }
29
+
30
+ getEventJSONsFromMessages(body: any[]): Object[] {
31
+ this.logger.warn("Method not implemented.");
32
+ return body;
33
+ }
34
+ }
@@ -0,0 +1,127 @@
1
+ import {
2
+ SQSClient,
3
+ SendMessageCommand,
4
+ SendMessageCommandInput,
5
+ ReceiveMessageCommandInput,
6
+ ReceiveMessageCommand,
7
+ DeleteMessageCommandInput,
8
+ Message,
9
+ DeleteMessageCommand,
10
+ } from '@aws-sdk/client-sqs';
11
+ import { AbstractQueueAdapter } from '../../types/interfaces';
12
+ import winston from 'winston';
13
+
14
+ export class SqsQueueAdapter implements AbstractQueueAdapter {
15
+ logger: winston.Logger;
16
+ client: SQSClient;
17
+
18
+ constructor(logger: winston.Logger) {
19
+ this.logger = logger;
20
+ let region: any;
21
+ if ('QUEUE_REGION' in process.env) {
22
+ region = process.env.QUEUE_REGION;
23
+ } else {
24
+ region = process.env.AWS_REGION;
25
+ }
26
+ this.logger.info(`SQS Region: ${region}`);
27
+ this.client = new SQSClient({ region: region });
28
+ }
29
+
30
+ async pushToQueue(event: Object): Promise<any> {
31
+ if (process.env.SQS_QUEUE_URL === 'undefined') {
32
+ return { message: 'SQS_QUEUE_URL is undefined' };
33
+ }
34
+ const params: SendMessageCommandInput = {
35
+ MessageAttributes: {
36
+ Event: {
37
+ DataType: 'String',
38
+ StringValue: event['event'],
39
+ },
40
+ Time: {
41
+ DataType: 'String',
42
+ StringValue: event['timestamp']
43
+ ? event['timestamp']
44
+ : new Date().toISOString(),
45
+ },
46
+ },
47
+ QueueUrl: process.env.SQS_QUEUE_URL,
48
+ MessageBody: JSON.stringify(event),
49
+ };
50
+ const sendMessageCommand = new SendMessageCommand(params);
51
+ try {
52
+ const sendMessageResult = await this.client.send(sendMessageCommand);
53
+ this.logger.info(
54
+ `Response from SQS: ${JSON.stringify(sendMessageResult)}`
55
+ );
56
+ return sendMessageResult;
57
+ } catch (err) {
58
+ this.logger.error(err);
59
+ return err;
60
+ }
61
+ }
62
+
63
+ async pullFromQueue(): Promise<any> {
64
+ if (process.env.SQS_QUEUE_URL === 'undefined') {
65
+ return { message: 'SQS_QUEUE_URL is undefined' };
66
+ }
67
+ let maxMessages: number = 10;
68
+ if (typeof process.env.SQS_MAX_MESSAGES === 'number') {
69
+ maxMessages = process.env.SQS_MAX_MESSAGES;
70
+ }
71
+ let waitTime: number = 20;
72
+ if (typeof process.env.SQS_WAIT_TIME === 'number') {
73
+ waitTime = process.env.SQS_WAIT_TIME;
74
+ }
75
+ const params: ReceiveMessageCommandInput = {
76
+ QueueUrl: process.env.SQS_QUEUE_URL,
77
+ MaxNumberOfMessages: maxMessages,
78
+ MessageAttributeNames: ['All'],
79
+ WaitTimeSeconds: waitTime,
80
+ };
81
+ const receiveMessageCommand = new ReceiveMessageCommand(params);
82
+ try {
83
+ const receiveMessageResult = await this.client.send(
84
+ receiveMessageCommand
85
+ );
86
+ this.logger.info(
87
+ `Reserved Messages From SQS Count: ${
88
+ receiveMessageResult.Messages
89
+ ? receiveMessageResult.Messages.length
90
+ : 0
91
+ }`
92
+ );
93
+ if (!receiveMessageResult.Messages) {
94
+ return [];
95
+ }
96
+ return receiveMessageResult.Messages;
97
+ } catch (err) {
98
+ this.logger.error(err);
99
+ return err;
100
+ }
101
+ }
102
+
103
+ async removeFromQueue(queueMsg: Message) {
104
+ if (process.env.SQS_QUEUE_URL === 'undefined') {
105
+ return { message: 'SQS_QUEUE_URL is undefined' };
106
+ }
107
+ const params: DeleteMessageCommandInput = {
108
+ QueueUrl: process.env.SQS_QUEUE_URL,
109
+ ReceiptHandle: queueMsg.ReceiptHandle,
110
+ };
111
+ const deleteMessageCommand = new DeleteMessageCommand(params);
112
+ try {
113
+ const deleteMessageResult = await this.client.send(deleteMessageCommand);
114
+ this.logger.info(
115
+ `Response from SQS: ${JSON.stringify(deleteMessageResult)}`
116
+ );
117
+ return deleteMessageResult;
118
+ } catch (err) {
119
+ this.logger.error(JSON.stringify(err));
120
+ return err;
121
+ }
122
+ }
123
+
124
+ getEventJSONsFromMessages(messages: Message[]): any[] {
125
+ return messages.map((item) => (item.Body ? JSON.parse(item.Body) : {}));
126
+ }
127
+ }
@@ -0,0 +1,14 @@
1
+ import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
2
+ import winston from 'winston';
3
+ import { AbstractDBAdapter, IGetItemInput, IGetItems, IPutItemInput, IHandleErrorOutput } from '../../types/interfaces';
4
+ export declare class DynamoDBAdapter implements AbstractDBAdapter {
5
+ logger: winston.Logger;
6
+ dbClient: DynamoDBClient;
7
+ constructor(logger: winston.Logger);
8
+ tableExists(name: string): Promise<boolean>;
9
+ putItem(params: IPutItemInput): Promise<boolean>;
10
+ getItem(params: IGetItemInput): Promise<any>;
11
+ deleteItem(params: IGetItemInput): Promise<boolean>;
12
+ getItemsBySession(params: IGetItems): Promise<any[]>;
13
+ handleError(errorObject: any): IHandleErrorOutput;
14
+ }
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DynamoDBAdapter = void 0;
13
+ const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
14
+ const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
15
+ const interfaces_1 = require("../../types/interfaces");
16
+ class DynamoDBAdapter {
17
+ constructor(logger) {
18
+ this.dbClient = new client_dynamodb_1.DynamoDBClient({
19
+ region: process.env.AWS_REGION,
20
+ maxAttempts: 5,
21
+ });
22
+ this.logger = logger;
23
+ }
24
+ tableExists(name) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ try {
27
+ const params = { TableName: name };
28
+ const tablesData = yield this.dbClient.send(new client_dynamodb_1.DescribeTableCommand(params));
29
+ if (tablesData['Table'] && tablesData['Table'].TableStatus === 'ACTIVE')
30
+ return true;
31
+ return false;
32
+ }
33
+ catch (awsError) {
34
+ if (awsError.name && awsError.name === 'ResourceNotFoundException') {
35
+ return false;
36
+ }
37
+ else {
38
+ this.logger.error(awsError);
39
+ throw new Error(awsError);
40
+ }
41
+ }
42
+ });
43
+ }
44
+ putItem(params) {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ try {
47
+ const data = yield this.dbClient.send(new client_dynamodb_1.PutItemCommand({
48
+ TableName: params.tableName,
49
+ Item: (0, util_dynamodb_1.marshall)(params.data),
50
+ }));
51
+ return data.$metadata.httpStatusCode === 200;
52
+ }
53
+ catch (err) {
54
+ throw this.handleError(err);
55
+ }
56
+ });
57
+ }
58
+ getItem(params) {
59
+ return __awaiter(this, void 0, void 0, function* () {
60
+ try {
61
+ const data = yield this.dbClient.send(new client_dynamodb_1.GetItemCommand({
62
+ TableName: params.tableName,
63
+ Key: (0, util_dynamodb_1.marshall)({
64
+ sessionId: params.sessionId,
65
+ timestamp: params.timestamp,
66
+ }),
67
+ }));
68
+ this.logger.debug('Read Item from Table');
69
+ return data;
70
+ }
71
+ catch (err) {
72
+ throw this.handleError(err);
73
+ }
74
+ });
75
+ }
76
+ deleteItem(params) {
77
+ return __awaiter(this, void 0, void 0, function* () {
78
+ try {
79
+ const data = yield this.dbClient.send(new client_dynamodb_1.DeleteItemCommand({
80
+ TableName: params.tableName,
81
+ Key: (0, util_dynamodb_1.marshall)({
82
+ sessionId: params.sessionId,
83
+ timestamp: params.timestamp,
84
+ }),
85
+ }));
86
+ this.logger.debug('Deleted Item from Table', data);
87
+ return data.$metadata.httpStatusCode === 200;
88
+ }
89
+ catch (err) {
90
+ throw this.handleError(err);
91
+ }
92
+ });
93
+ }
94
+ getItemsBySession(params) {
95
+ return __awaiter(this, void 0, void 0, function* () {
96
+ try {
97
+ const inputData = {
98
+ TableName: params.tableName,
99
+ KeyConditionExpression: '#sid = :sid',
100
+ ExpressionAttributeNames: {
101
+ '#sid': 'sessionId',
102
+ },
103
+ ExpressionAttributeValues: (0, util_dynamodb_1.marshall)({
104
+ ':sid': params.sessionId,
105
+ }),
106
+ };
107
+ const queryData = yield this.dbClient.send(new client_dynamodb_1.QueryCommand(inputData));
108
+ if (queryData.Items && queryData.Items.length > 0) {
109
+ let items = [];
110
+ for (let i = 0; i < queryData.Items.length; i++) {
111
+ items[i] = (0, util_dynamodb_1.unmarshall)(queryData.Items[i]);
112
+ }
113
+ return items;
114
+ }
115
+ return [];
116
+ }
117
+ catch (err) {
118
+ throw this.handleError(err);
119
+ }
120
+ });
121
+ }
122
+ handleError(errorObject) {
123
+ this.logger.error(errorObject);
124
+ const errorOutput = {
125
+ errorType: interfaces_1.ErrorType.ABORT,
126
+ error: errorObject,
127
+ };
128
+ if (errorObject.name) {
129
+ if (errorObject.name === 'ResourceNotFoundException' ||
130
+ errorObject.name === 'ResourceInUseException') {
131
+ errorOutput['errorType'] = interfaces_1.ErrorType.CONTINUE;
132
+ }
133
+ }
134
+ return errorOutput;
135
+ }
136
+ }
137
+ exports.DynamoDBAdapter = DynamoDBAdapter;
138
+ //# sourceMappingURL=DynamoDBAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DynamoDBAdapter.js","sourceRoot":"","sources":["../../../adapters/db/DynamoDBAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { Logger } from "winston";
2
+ import { AbstractDBAdapter, IHandleErrorOutput, IPutItemInput, IGetItemInput, IGetItems } from "../../types/interfaces";
3
+ import { MongoClient } from "mongodb";
4
+ export declare class MongoDBAdapter implements AbstractDBAdapter {
5
+ logger: Logger;
6
+ dbClient: MongoClient;
7
+ constructor(logger: Logger);
8
+ private isConnected;
9
+ private connect;
10
+ tableExists(tableName: string): Promise<boolean>;
11
+ putItem({ tableName, data }: IPutItemInput): Promise<boolean>;
12
+ getItem({ sessionId, tableName, timestamp }: IGetItemInput): Promise<any>;
13
+ deleteItem({ sessionId, tableName, timestamp }: IGetItemInput): Promise<boolean>;
14
+ getItemsBySession({ tableName, sessionId }: IGetItems): Promise<any[]>;
15
+ handleError(error: any): IHandleErrorOutput;
16
+ }