refactor(database): ♻️ Move Applications to our custom ORM

This commit is contained in:
Jesse Wierzbinski 2024-10-23 17:56:47 +02:00
parent e8827bccfa
commit 9e96eca032
No known key found for this signature in database
23 changed files with 424 additions and 381 deletions

View file

@ -0,0 +1,155 @@
import type { Application as APIApplication } from "@versia/client/types";
import {
type InferInsertModel,
type InferSelectModel,
type SQL,
desc,
eq,
inArray,
} from "drizzle-orm";
import { z } from "zod";
import { db } from "~/drizzle/db";
import { Applications } from "~/drizzle/schema";
import { BaseInterface } from "./base.ts";
export type ApplicationType = InferSelectModel<typeof Applications>;
export class Application extends BaseInterface<typeof Applications> {
static schema: z.ZodType<APIApplication> = z.object({
name: z.string(),
website: z.string().url().optional().nullable(),
vapid_key: z.string().optional().nullable(),
redirect_uris: z.string().optional(),
scopes: z.string().optional(),
});
async reload(): Promise<void> {
const reloaded = await Application.fromId(this.data.id);
if (!reloaded) {
throw new Error("Failed to reload application");
}
this.data = reloaded.data;
}
public static async fromId(id: string | null): Promise<Application | null> {
if (!id) {
return null;
}
return await Application.fromSql(eq(Applications.id, id));
}
public static async fromIds(ids: string[]): Promise<Application[]> {
return await Application.manyFromSql(inArray(Applications.id, ids));
}
public static async fromSql(
sql: SQL<unknown> | undefined,
orderBy: SQL<unknown> | undefined = desc(Applications.id),
): Promise<Application | null> {
const found = await db.query.Applications.findFirst({
where: sql,
orderBy,
});
if (!found) {
return null;
}
return new Application(found);
}
public static async manyFromSql(
sql: SQL<unknown> | undefined,
orderBy: SQL<unknown> | undefined = desc(Applications.id),
limit?: number,
offset?: number,
extra?: Parameters<typeof db.query.Applications.findMany>[0],
): Promise<Application[]> {
const found = await db.query.Applications.findMany({
where: sql,
orderBy,
limit,
offset,
with: extra?.with,
});
return found.map((s) => new Application(s));
}
public static async getFromToken(
token: string,
): Promise<Application | null> {
const result = await db.query.Tokens.findFirst({
where: (tokens, { eq }) => eq(tokens.accessToken, token),
with: {
application: true,
},
});
return result?.application ? new Application(result.application) : null;
}
public static fromClientId(clientId: string): Promise<Application | null> {
return Application.fromSql(eq(Applications.clientId, clientId));
}
async update(
newApplication: Partial<ApplicationType>,
): Promise<ApplicationType> {
await db
.update(Applications)
.set(newApplication)
.where(eq(Applications.id, this.id));
const updated = await Application.fromId(this.data.id);
if (!updated) {
throw new Error("Failed to update application");
}
this.data = updated.data;
return updated.data;
}
save(): Promise<ApplicationType> {
return this.update(this.data);
}
async delete(ids?: string[]): Promise<void> {
if (Array.isArray(ids)) {
await db.delete(Applications).where(inArray(Applications.id, ids));
} else {
await db.delete(Applications).where(eq(Applications.id, this.id));
}
}
public static async insert(
data: InferInsertModel<typeof Applications>,
): Promise<Application> {
const inserted = (
await db.insert(Applications).values(data).returning()
)[0];
const application = await Application.fromId(inserted.id);
if (!application) {
throw new Error("Failed to insert application");
}
return application;
}
get id() {
return this.data.id;
}
public toApi(): APIApplication {
return {
name: this.data.name,
website: this.data.website,
vapid_key: this.data.vapidKey,
};
}
}

View file

@ -27,10 +27,6 @@ import {
import { htmlToText } from "html-to-text";
import { createRegExp, exactly, global } from "magic-regexp";
import { z } from "zod";
import {
type Application,
applicationToApi,
} from "~/classes/functions/application";
import {
type StatusWithRelations,
contentToHtml,
@ -47,6 +43,7 @@ import {
Users,
} from "~/drizzle/schema";
import { config } from "~/packages/config-manager";
import { Application } from "./application.ts";
import { Attachment } from "./attachment.ts";
import { BaseInterface } from "./base.ts";
import { Emoji } from "./emoji.ts";
@ -904,7 +901,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
account: this.author.toApi(userFetching?.id === data.authorId),
created_at: new Date(data.createdAt).toISOString(),
application: data.application
? applicationToApi(data.application)
? new Application(data.application).toApi()
: null,
card: null,
content: replacedContent,

View file

@ -6,4 +6,5 @@ export { Emoji } from "~/packages/database-interface/emoji";
export { Instance } from "~/packages/database-interface/instance";
export { Note } from "~/packages/database-interface/note";
export { Timeline } from "~/packages/database-interface/timeline";
export { Application } from "~/packages/database-interface/application";
export { db } from "~/drizzle/db";