Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Prod Release into Master #89

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ reports

# Dynamo
.dynamodb

.env.local
.vscode
2,355 changes: 2,297 additions & 58 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"test:unit:watch": "npm run test:unit -- --watch",
"test:unit:coverage": "cross-env npm run test:unit -- --coverage",
"test-i": "BRANCH=local npm run test:integration -- --globalSetup='./scripts/setup.ts' --globalTeardown='./scripts/teardown.ts'",
"test:integration": "cross-env NODE_ENV=test jest tests/integration",
"test:integration": "cross-env NODE_ENV=test jest tests/integration --detectOpenHandles",
"test:integration:watch": "npm run test:integration -- --watch",
"test:integration:coverage": "cross-env npm run test:integration -- --coverage",
"test": "npm-run-all test:unit:coverage",
Expand All @@ -47,10 +47,12 @@
"tools-setup": "node_modules/.bin/sls dynamodb install"
},
"dependencies": {
"@aws-sdk/client-dynamodb": "3.556.0",
"@aws-sdk/lib-dynamodb": "3.556.0",
"@smithy/smithy-client": "2.5.1",
"aws-lambda": "1.0.7",
"aws-sdk": "2.1421.0",
"dotenv": "16.3.1",
"express": "4.18.2",
"express": "4.19.2",
"jest-express": "1.12.0",
"joi": "17.9.2",
"serverless-http": "3.2.0",
Expand All @@ -65,13 +67,15 @@
"@semantic-release/github": "9.0.4",
"@semantic-release/npm": "10.0.4",
"@serverless/typescript": "3.30.1",
"@smithy/util-utf8": "2.3.0",
"@types/aws-lambda": "8.10.119",
"@types/express": "4.17.17",
"@types/jest": "29.5.3",
"@types/node": "20.4.4",
"@types/supertest": "2.0.12",
"@typescript-eslint/eslint-plugin": "6.2.0",
"@typescript-eslint/parser": "6.2.0",
"aws-sdk-client-mock": "4.0.0",
"clean-webpack-plugin": "4.0.0",
"commitlint-plugin-function-rules": "2.0.2",
"concurrently": "8.2.0",
Expand Down
2 changes: 1 addition & 1 deletion scripts/getDBPid.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#! /bin/sh

lsof -i:8020 | awk '{print $2}' | grep -v '^PID'
lsof -i:8020 | awk '{print $2}' | tail -1
2 changes: 0 additions & 2 deletions src/interfaces/controllers/deregister-trailer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
import { Request, Response, NextFunction } from 'express';
import * as domain from '../../domain';
import { log } from '../../utils/logger';
Expand All @@ -13,7 +12,6 @@ export class DeregisterTrailer extends TrailerRegistrationBase {
}

public async call(req: Request, res: Response, next: NextFunction): Promise<void> {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const deregisterTrailer = req.body as domain.DeregisterTrailerRequest;
const { trn } = req.params;

Expand Down
9 changes: 5 additions & 4 deletions src/utils/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ export class Configurations {
region: this.awsRegion,
endpoint: process.env.DYNAMO_ENDPOINT || 'http://127.0.1:8020',
convertEmptyValues: true,
accessKeyId: 'foo',
secretAccessKey: 'bar',
credentials: {
accessKeyId: 'foo',
secretAccessKey: 'bar',
},
};
if (this.branch !== 'local') {
delete dbParams.endpoint;
delete dbParams.region;
delete dbParams.accessKeyId;
delete dbParams.secretAccessKey;
delete dbParams.credentials;
}
return dbParams;
}
Expand Down
50 changes: 27 additions & 23 deletions src/utils/data-access.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import DynamoDB, { DocumentClient, QueryOutput } from 'aws-sdk/clients/dynamodb';
import { AWSError } from 'aws-sdk/lib/error';
import { PromiseResult } from 'aws-sdk/lib/request';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import {
QueryCommand,
DynamoDBDocumentClient,
QueryCommandOutput,
PutCommandOutput,
PutCommand,
BatchWriteCommand,
BatchWriteCommandOutput,
BatchWriteCommandInput,
} from '@aws-sdk/lib-dynamodb';
import { ServiceException } from '@smithy/smithy-client';
import * as domain from '../domain';
import { Configurations } from './configuration';
import { log } from './logger';
Expand All @@ -12,31 +19,32 @@ export class DataAccess {

private readonly tableName: string = Configurations.getInstance().dynamoTableName;

private docClient: DocumentClient;
private docClient: DynamoDBDocumentClient;

public constructor() {
this.docClient = new DynamoDB.DocumentClient(Configurations.getInstance().dynamoParams);
this.docClient = DynamoDBDocumentClient.from(new DynamoDBClient(Configurations.getInstance().dynamoParams));
}

private getById(options: {
private async getById(options: {
indexName: string;
keyCondition: string;
expressionAttributeValues: { [key: string]: string };
}): Promise<PromiseResult<QueryOutput, AWSError>> {
}): Promise<QueryCommandOutput | ServiceException> {
const params = {
TableName: this.tableName,
IndexName: options.indexName,
KeyConditionExpression: options.keyCondition,
ExpressionAttributeValues: options.expressionAttributeValues,
};
log.debug('params getbyId', params);
return this.docClient.query(params).promise();
const command = new QueryCommand(params);
return this.docClient.send(command);
}

private async put<T>(
payload: T,
options?: { conditionalExpression: string; expressionAttributeValues: { [key: string]: string } },
): Promise<PromiseResult<DocumentClient.PutItemOutput, AWSError>> {
): Promise<PutCommandOutput | ServiceException> {
let query = {
TableName: this.tableName,
Item: payload,
Expand All @@ -50,7 +58,8 @@ export class DataAccess {
ExpressionAttributeValues: options.expressionAttributeValues,
};
}
return this.docClient.put(query).promise();
const command = new PutCommand(query);
return this.docClient.send(command);
}

public async upsertTrailerRegistration(
Expand Down Expand Up @@ -93,27 +102,22 @@ export class DataAccess {

public async createMultiple(
trailerRegistrations: domain.TrailerRegistration[],
): Promise<PromiseResult<DocumentClient.BatchWriteItemOutput, AWSError>> {
): Promise<BatchWriteCommandOutput | ServiceException> {
const params = this.generateBatchWritePartialParams();

// eslint-disable-next-line @typescript-eslint/no-unsafe-call
params.RequestItems[this.tableName].push(
...trailerRegistrations.map((trailerRegistration) => ({
PutRequest: {
Item: trailerRegistration,
},
})),
);

return this.batchWrite(params);
}

public async deleteMultiple(
vinOrChassisWithMakeIds: string[],
): Promise<PromiseResult<DocumentClient.BatchWriteItemOutput, AWSError>> {
public async deleteMultiple(vinOrChassisWithMakeIds: string[]): Promise<BatchWriteCommandOutput | ServiceException> {
const params = this.generateBatchWritePartialParams();

// eslint-disable-next-line @typescript-eslint/no-unsafe-call
params.RequestItems[this.tableName].push(
...vinOrChassisWithMakeIds.map((id) => ({
DeleteRequest: {
Expand All @@ -127,13 +131,13 @@ export class DataAccess {
return this.batchWrite(params);
}

public batchWrite(params): Promise<PromiseResult<DocumentClient.BatchWriteItemOutput, AWSError>> {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return this.docClient.batchWrite(params).promise();
public async batchWrite(params: BatchWriteCommandInput): Promise<ServiceException | BatchWriteCommandOutput> {
const command = new BatchWriteCommand(params);
return this.docClient.send(command);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public generateBatchWritePartialParams(): any {
public generateBatchWritePartialParams(): BatchWriteCommandInput {
return {
RequestItems: {
[this.tableName]: [],
Expand Down
104 changes: 51 additions & 53 deletions tests/unit/data-access.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { mockClient } from 'aws-sdk-client-mock';
import {
BatchWriteCommand, DynamoDBDocumentClient, PutCommand, QueryCommand,
} from '@aws-sdk/lib-dynamodb';
import { DataAccess } from '../../src/utils/data-access';
import { TrailerRegistration } from '../../src/domain/trailer-registration';

let mockDAO: DataAccess;
describe('DataAccess', () => {
beforeEach(() => {
mockDAO = new DataAccess();
jest.resetModules();
});

afterEach(() => {
Expand All @@ -24,22 +27,18 @@ describe('DataAccess', () => {
},
];

const daoStub = jest.fn().mockImplementation(() => Promise.resolve({ Count: 1, Items: data }));

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
mockDAO.getById = daoStub;
const mockDAO = new DataAccess();
const mockDynamoClient = mockClient(DynamoDBDocumentClient);
mockDynamoClient.on(QueryCommand).resolves({ Count: 1, Items: data });

const result = await mockDAO.getByVinOrChassisWithMake('ABC1321234566big truck');
expect(result).toEqual(data);
});

test('return null if no record is found for the provided vinOrChassisWithMake', async () => {
const daoStub = jest.fn().mockImplementation(() => Promise.resolve({ Count: 0, Items: null }));

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
mockDAO.getById = daoStub;
const mockDAO = new DataAccess();
const mockDynamoClient = mockClient(DynamoDBDocumentClient);
mockDynamoClient.on(QueryCommand).resolves({ Count: 0, Items: null });

const result = await mockDAO.getByVinOrChassisWithMake('AB123ADbigtruck');
expect(result).toBeNull();
Expand All @@ -60,52 +59,51 @@ describe('getByTrn', () => {
},
];

const daoStub = jest.fn().mockImplementation(() => Promise.resolve({ Count: 1, Items: data }));

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
mockDAO.getById = daoStub;
const mockDAO = new DataAccess();
const mockDynamoClient = mockClient(DynamoDBDocumentClient);
mockDynamoClient.on(QueryCommand).resolves({ Count: 1, Items: data });

const result = await mockDAO.getByTrn('AB123AD');

expect(result).toEqual(data);
});

test('return null if no record is found for the provided trn', async () => {
const daoStub = jest.fn().mockImplementation(() => Promise.resolve({ Count: 0, Items: null }));

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
mockDAO.getById = daoStub;
const mockDAO = new DataAccess();
const mockDynamoClient = mockClient(DynamoDBDocumentClient);
mockDynamoClient.on(QueryCommand).resolves({ Count: 0, Items: null });

const result = await mockDAO.getByTrn('AB123AD');
expect(result).toBeNull();
});
});
describe('upsertTrailerRegistration', () => {
test('should successfully insert a valid record', () => {
const data = ({
const data = {
vinOrChassisWithMake: 'ABC1321234566big truck',
vin: 'ABC1321234566',
make: 'big truck',
trn: 'AB123AD',
certificateExpiryDate: '2021-12-12',
certificateIssueDate: '2021-01-01',
} as unknown) as TrailerRegistration;
} as unknown as TrailerRegistration;

const daoPutStub = jest.fn().mockImplementation(() => Promise.resolve());
const daoGetStub = jest.fn().mockImplementation(() => Promise.resolve([{
vinOrChassisWithMake: 'ABC1321234566big truck',
vin: 'ABC1321234566',
make: 'big truck',
trn: 'AB123AD',
certificateExpiryDate: '2021-12-12',
certificateIssueDate: '2021-01-01',
}]));
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
mockDAO.put = daoPutStub;
mockDAO.getByVinOrChassisWithMake = daoGetStub;
const mockDAO = new DataAccess();
const mockDynamoClient = mockClient(DynamoDBDocumentClient);
mockDynamoClient.on(QueryCommand).resolves({
Count: 1,
Items: [
{
vinOrChassisWithMake: 'ABC1321234566big truck',
vin: 'ABC1321234566',
make: 'big truck',
trn: 'AB123AD',
certificateExpiryDate: '2021-12-12',
certificateIssueDate: '2021-01-01',
},
],
});
mockDynamoClient.on(PutCommand).resolves({});

return mockDAO.upsertTrailerRegistration(data).then((result) => {
expect(result).toEqual(data);
Expand All @@ -115,19 +113,20 @@ describe('upsertTrailerRegistration', () => {

describe('createMultiple', () => {
test('should successfully insert a valid record', () => {
const data = ([{
vinOrChassisWithMake: 'ABC1321234566big truck',
vin: 'ABC1321234566',
make: 'big truck',
trn: 'AB123AD',
certificateExpiryDate: '2021-12-12',
certificateIssueDate: '2021-01-01',
}] as unknown) as TrailerRegistration[];
const data = [
{
vinOrChassisWithMake: 'ABC1321234566big truck',
vin: 'ABC1321234566',
make: 'big truck',
trn: 'AB123AD',
certificateExpiryDate: '2021-12-12',
certificateIssueDate: '2021-01-01',
},
] as unknown as TrailerRegistration[];

const batchWrite = jest.fn().mockImplementation(() => Promise.resolve({}));
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
mockDAO.batchWrite = batchWrite;
const mockDAO = new DataAccess();
const mockDynamoClient = mockClient(DynamoDBDocumentClient);
mockDynamoClient.on(BatchWriteCommand).resolves({});

return mockDAO.createMultiple(data).then((result) => {
expect(result).toEqual({});
Expand All @@ -139,10 +138,9 @@ describe('deleteMultiple', () => {
test('should successfully insert a valid record', () => {
const data = ['ABC1321234566big truck'];

const batchWrite = jest.fn().mockImplementation(() => Promise.resolve({}));
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
mockDAO.batchWrite = batchWrite;
const mockDAO = new DataAccess();
const mockDynamoClient = mockClient(DynamoDBDocumentClient);
mockDynamoClient.on(BatchWriteCommand).resolves({});

return mockDAO.deleteMultiple(data).then((result) => {
expect(result).toEqual({});
Expand Down
Loading