import bcrypt from "bcryptjs";
import { getRedisKey, generateShortLink } from "../utils";
import * as redis from "../redis";
import knex from "../knex";
interface GetTotal {
all: boolean;
userId: number;
search?: string;
}
export const getTotalQuery = async ({ all, search, userId }: GetTotal) => {
const query = knex("links").count("id");
if (!all) {
query.where("user_id", userId);
}
if (search) {
query.andWhereRaw("links.address || ' ' || target ILIKE '%' || ? || '%'", [
search
]);
}
const [{ count }] = await query;
return typeof count === "number" ? count : parseInt(count);
};
interface GetLinks {
all: boolean;
limit: number;
search?: string;
skip: number;
userId: number;
}
export const getLinksQuery = async ({
all,
limit,
search,
skip,
userId
}: GetLinks) => {
const query = knex("links")
.select(
"links.id",
"links.address",
"links.banned",
"links.created_at",
"links.domain_id",
"links.updated_at",
"links.password",
"links.target",
"links.visit_count",
"links.user_id",
"links.uuid",
"domains.address as domain"
)
.offset(skip)
.limit(limit)
.orderBy("created_at", "desc");
if (!all) {
query.where("links.user_id", userId);
}
if (search) {
query.andWhereRaw("links.address || ' ' || target ILIKE '%' || ? || '%'", [
search
]);
}
query.leftJoin("domains", "links.domain_id", "domains.id");
const links: LinkJoinedDomain[] = await query;
return links;
};
interface FindLink {
address?: string;
domainId?: number;
userId?: number;
target?: string;
}
export const findLinkQuery = async ({
address,
domainId,
userId,
target
}: FindLink): Promise => {
const redisKey = getRedisKey.link(address, domainId, userId);
const cachedLink = await redis.get(redisKey);
if (cachedLink) return JSON.parse(cachedLink);
const link = await knex("links")
.where({
...(address && { address }),
...(domainId && { domain_id: domainId }),
...(userId && { user_id: userId }),
...(target && { target })
})
.first();
if (link) {
redis.set(redisKey, JSON.stringify(link), "EX", 60 * 60 * 2);
}
return link;
};
interface CreateLink {
userId?: number;
domainAddress?: string;
domainId?: number;
password?: string;
address: string;
target: string;
}
export const createLinkQuery = async ({
password,
address,
target,
domainAddress,
domainId = null,
userId = null
}: CreateLink) => {
let encryptedPassword;
if (password) {
const salt = await bcrypt.genSalt(12);
encryptedPassword = await bcrypt.hash(password, salt);
}
const [link]: Link[] = await knex("links").insert(
{
password: encryptedPassword,
domain_id: domainId,
user_id: userId,
address,
target
},
"*"
);
return {
...link,
id: link.uuid,
password: !!password,
link: generateShortLink(address, domainAddress)
};
};