lib/models/Alias.ts
import { DynamoDB } from "aws-sdk";
import config from "../config";
import generateAliasValue from "./generateAliasValue";
export interface AliasData {
value: string;
description: string;
creationDate: Date;
countReceived: number;
countSent: number;
lastReceivedDate?: Date;
lastSentDate?: Date;
}
export interface GetAliasesResult {
aliases: Array<Alias>;
lastEvaluatedKey?: DynamoDB.Key;
}
export default class Alias implements AliasData {
private _value: string;
private _description: string;
private _creationDate: Date;
private _countReceived: number;
private _countSent: number;
private _lastReceivedDate?: Date;
private _lastSentDate?: Date;
private static client = new DynamoDB.DocumentClient();
// Public getters (readonly properties)
get value(): string {
return this._value;
}
get description(): string {
return this._description;
}
get creationDate(): Date {
return this._creationDate;
}
get countReceived(): number {
return this._countReceived;
}
get countSent(): number {
return this._countSent;
}
get lastReceivedDate(): Date | undefined {
return this._lastReceivedDate;
}
get lastSentDate(): Date | undefined {
return this._lastSentDate;
}
protected constructor(options: AliasData) {
this._value = options.value;
this._description = options.description;
this._creationDate = options.creationDate;
this._countReceived = options.countReceived;
this._countSent = options.countSent;
this._lastReceivedDate = options.lastReceivedDate;
this._lastSentDate = options.lastSentDate;
}
// Utils
private static generateGetParams(
aliasValue: string
): DynamoDB.DocumentClient.GetItemInput {
return {
TableName: config.tableName,
Key: {
alias: aliasValue
}
};
}
private static generatePutParams(
alias: AliasData
): DynamoDB.DocumentClient.PutItemInput {
return {
TableName: config.tableName,
Item: {
alias: alias.value,
description: alias.description,
creationDate: alias.creationDate.getTime(),
countReceived: alias.countReceived,
countSent: alias.countSent,
lastReceivedDate: alias.lastReceivedDate?.getTime(),
lastSentDate: alias.lastSentDate?.getTime()
}
};
}
private static convertRawDataToAlias(
rawAlias: DynamoDB.DocumentClient.AttributeMap
): Alias {
return new Alias({
value: rawAlias.alias,
description: rawAlias.description,
creationDate: new Date(rawAlias.creationDate),
countReceived: rawAlias.countReceived,
countSent: rawAlias.countSent,
lastReceivedDate: rawAlias.lastReceivedDate
? new Date(rawAlias.lastReceivedDate)
: undefined,
lastSentDate: rawAlias.lastSentDate
? new Date(rawAlias.lastSentDate)
: undefined
});
}
// Dependency injection for testing
static useClient(client: DynamoDB.DocumentClient) {
this.client = client;
}
// Static methods
static async aliasExists(aliasValue: string): Promise<boolean> {
console.log(`Checking if alias of value=${aliasValue} exists`);
const possibleAlias = await Alias.getAlias(aliasValue);
return possibleAlias !== undefined;
}
static async generateAlias(description: string): Promise<Alias> {
console.log(`Generating new alias for description=${description}`);
let generatedAliasValue: string;
do {
generatedAliasValue = generateAliasValue();
} while (await Alias.aliasExists(generatedAliasValue));
console.log(
`Generated aliasValue=${generatedAliasValue} for description=${description}`
);
const alias = new Alias({
value: generatedAliasValue,
description,
creationDate: new Date(),
countReceived: 0,
countSent: 0
});
await Alias.putAlias(alias);
return alias;
}
static async getAlias(aliasValue: string): Promise<Alias | void> {
console.log(`Attempting to get alias of value=${aliasValue} from table`);
const params = Alias.generateGetParams(aliasValue);
const res = await Alias.client.get(params).promise();
const rawAlias = res.Item;
if (rawAlias === undefined) {
console.log(`Alias of value=${aliasValue} does not exist`);
return;
}
const alias = Alias.convertRawDataToAlias(rawAlias);
return alias;
}
static async getAllAliases(): Promise<GetAliasesResult> {
console.log("Scanning table for alias records");
const records: DynamoDB.DocumentClient.ScanOutput = await Alias.client
.scan({
TableName: config.tableName
})
.promise();
console.log("Scan operation completed");
if (records.Items === undefined || records.Items.length === 0) {
return {
aliases: []
};
}
return {
aliases: records.Items.map(Alias.convertRawDataToAlias),
lastEvaluatedKey: records.LastEvaluatedKey
};
}
static async putAlias(alias: AliasData): Promise<void> {
console.log(`Attempting to put alias=${alias} into table`);
const params = Alias.generatePutParams(alias);
await Alias.client.put(params).promise();
console.log("Successfully put alias into table");
}
// Instance methods
async didReceiveEmail(): Promise<void> {
this._countReceived += 1;
this._lastReceivedDate = new Date();
await Alias.putAlias(this);
}
async didSendEmail(): Promise<void> {
this._countSent += 1;
this._lastSentDate = new Date();
await Alias.putAlias(this);
}
}