Source

classes/systemRelation.ts

import Snowflake from "./snowflake";
import { UserType } from "../types/basicUser";
import User from "./user";
import UserClient from "./userClient";
import Collection from "@discordjs/collection";
import { SnowflakeString } from "../types/snowflake";
import { RequestContext } from "./requestContext";
import {
    DBSystemRelation, DBSystemRelationAuthor, DBSystemRelationFull, DBSystemRelationTarget, prisma
} from "../../prisma";

/**
 * Holds data about system - user relation
 */
class SystemRelation {
    id: Snowflake;
    ctx: RequestContext;

    type: UserType;
    target: User;
    author: User;

    /**
     * Creates new system relation data
     * @param {Object} data
     */
    constructor({
        id,
        ctx,
        type,
        target,
        author
    }: {
        id: Snowflake,
        ctx: RequestContext,
        type: UserType,
        target: User,
        author: User
    }) {
        this.id = id;
        this.ctx = ctx;
        this.type = type;
        this.target = target;
        this.author = author;
    }

    /**
     * Creates object from database
     * @param {DBSystemRelation | DBSystemRelationAuthor |
     * DBSystemRelationTarget | DBSystemRelationFull} data
     * @param {RequestContext} ctx
     * @return {SystemRelation}
     */
    static async fromDatabase(data: DBSystemRelation | DBSystemRelationAuthor |
        DBSystemRelationTarget | DBSystemRelationFull, ctx: RequestContext) {
        return new SystemRelation({
            id: new Snowflake(data.snowflake),
            ctx,
            type: data.type,
            target: "target" in data ? await User.fromDatabase(data.target, ctx) :
                await User.getUser(data.targetId, ctx),
            author: "author" in data ? await User.fromDatabase(data.author, ctx) :
                await User.getUser(data.authorId, ctx)
        });
    }

    /**
     * Updates relation
     * @param {UserType} type
     * @return {Promise<SystemRelation>}
     */
    async updateRelation(type: UserType): Promise<SystemRelation> {
        if(!this.ctx.hasClient()) throw new Error("Client required for relation updates");

        return await SystemRelation.createRelation(this.ctx, this.target, type);
    }

    /**
     * Creates or updates relation
     * @param {RequestContext} ctx
     * @param {User} target
     * @param {UserType} type
     * @deprecated
     */
    static async upsertRelation(ctx: RequestContext, target: User, type: UserType):
        Promise<never> {
        if(!ctx.hasClient()) throw new Error("Client required for relation updates");
        throw new Error("upsertRelation is deprecated, use createRelation instead");
    }

    /**
     * Creates relation
     * @param {RequestContext} ctx
     * @param {User} target
     * @param {UserType} type
     * @param {Pool} conn
     * @return {Promise<SystemRelation>}
     */
    static async createRelation(ctx: RequestContext, target: User, type: UserType):
        Promise<SystemRelation> {
        if(!ctx.hasClient()) throw new Error("Client required for relation updates");
        const data = await prisma.systemRelation.create({
            data: {
                snowflake: Snowflake.newSnowflake().toBigInt(),
                type,
                author: {
                    connect: {
                        snowflake: ctx.client.user.id.toBigInt()
                    }
                },
                target: {
                    connect: {
                        snowflake: target.id.toBigInt()
                    }
                }
            }
        });

        return await SystemRelation.fromDatabase(data, ctx);
    }

    /**
     * Gets current system relation
     * @param {User} target user
     * @param {RequestContext} ctx
     * @param {UserClient} client
     * @return {Promise<SystemRelation|null>} Systerm relation or null if default
     */
    static async getRelation(target: User, ctx: RequestContext, client?: UserClient):
        Promise<SystemRelation|null> {
        const data = await prisma.systemRelation.findFirst({
            where: {
                targetId: target.id.toBigInt()
            },
            orderBy: {
                snowflake: "desc"
            }
        });

        if(!data) return null;
        return await SystemRelation.fromDatabase(data, ctx);
    }

    /**
     * Gets all (even past) relations. Limits to 150.
     * @param {User} target
     * @param {RequestContext} ctx
     * @return {Promise<Collection<SystemRelation>>}
     */
    static async getRelations(target: User, ctx: RequestContext):
        Promise<Collection<SnowflakeString, SystemRelation>> {
        const data = await prisma.systemRelation.findMany({
            where: {
                targetId: target.id.toBigInt()
            },
            orderBy: {
                snowflake: "desc"
            },
            take: 150
        });

        var col = new Collection<SnowflakeString, SystemRelation>();
        for(var rel of data) {
            col.set(rel.snowflake.toString(), await SystemRelation.fromDatabase(rel, ctx));
        }
        return col;
    }

    /**
     * Creates a JSON-compatible object
     * @return {Object}
     */
    toJSON() {
        return {
            id: this.id.getSnowflake(),
            type: this.type,
            author: this.author.toJSON(),
            target: this.target.toJSON()
        };
    }
}

export default SystemRelation;