All files / src/lib/db user-feedback-store.ts

91.67% Statements 22/24
100% Branches 0/0
75% Functions 9/12
90.91% Lines 20/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115                  69x 69x                 69x             69x             69x           87x 87x       4x         4x             1x           1x       6x             6x                   5x           2x       2x 2x                     1x       1x       69x  
import { Knex } from 'knex';
import { EventEmitter } from 'events';
import { LogProvider, Logger } from '../logger';
import {
    IUserFeedback,
    IUserFeedbackKey,
    IUserFeedbackStore,
} from '../types/stores/user-feedback-store';
 
const COLUMNS = ['given', 'user_id', 'feedback_id', 'nevershow'];
const TABLE = 'user_feedback';
 
interface IUserFeedbackTable {
    nevershow?: boolean;
    feedback_id: string;
    given?: Date;
    user_id: number;
}
 
const fieldToRow = (fields: IUserFeedback): IUserFeedbackTable => ({
    nevershow: fields.neverShow,
    feedback_id: fields.feedbackId,
    given: fields.given,
    user_id: fields.userId,
});
 
const rowToField = (row: IUserFeedbackTable): IUserFeedback => ({
    neverShow: row.nevershow,
    feedbackId: row.feedback_id,
    given: row.given,
    userId: row.user_id,
});
 
export default class UserFeedbackStore implements IUserFeedbackStore {
    private db: Knex;
 
    private logger: Logger;
 
    constructor(db: Knex, eventBus: EventEmitter, getLogger: LogProvider) {
        this.db = db;
        this.logger = getLogger('user-feedback-store.ts');
    }
 
    async getAllUserFeedback(userId: number): Promise<IUserFeedback[]> {
        const userFeedback = await this.db
            .table<IUserFeedbackTable>(TABLE)
            .select()
            .where({ user_id: userId });
 
        return userFeedback.map(rowToField);
    }
 
    async getFeedback(
        userId: number,
        feedbackId: string,
    ): Promise<IUserFeedback> {
        const userFeedback = await this.db
            .table<IUserFeedbackTable>(TABLE)
            .select()
            .where({ user_id: userId, feedback_id: feedbackId })
            .first();
 
        return rowToField(userFeedback);
    }
 
    async updateFeedback(feedback: IUserFeedback): Promise<IUserFeedback> {
        const insertedFeedback = await this.db
            .table<IUserFeedbackTable>(TABLE)
            .insert(fieldToRow(feedback))
            .onConflict(['user_id', 'feedback_id'])
            .merge()
            .returning(COLUMNS);
 
        return rowToField(insertedFeedback[0]);
    }
 
    async delete({ userId, feedbackId }: IUserFeedbackKey): Promise<void> {
        await this.db(TABLE)
            .where({ user_id: userId, feedback_id: feedbackId })
            .del();
    }
 
    async deleteAll(): Promise<void> {
        await this.db(TABLE).del();
    }
 
    destroy(): void {}
 
    async exists({ userId, feedbackId }: IUserFeedbackKey): Promise<boolean> {
        const result = await this.db.raw(
            `SELECT EXISTS (SELECT 1 FROM ${TABLE} WHERE user_id = ? AND feedback_id = ?) AS present`,
            [userId, feedbackId],
        );
        const { present } = result.rows[0];
        return present;
    }
 
    async get({
        userId,
        feedbackId,
    }: IUserFeedbackKey): Promise<IUserFeedback> {
        return this.getFeedback(userId, feedbackId);
    }
 
    async getAll(): Promise<IUserFeedback[]> {
        const userFeedbacks = await this.db
            .table<IUserFeedbackTable>(TABLE)
            .select();
 
        return userFeedbacks.map(rowToField);
    }
}
 
module.exports = UserFeedbackStore;