mirror of
https://github.com/versia-pub/server.git
synced 2026-03-13 05:49:16 +01:00
refactor: ♻️ Always use explicit types in every function
This commit is contained in:
parent
54cea29ce9
commit
c1dcdc78ae
62 changed files with 359 additions and 226 deletions
|
|
@ -82,7 +82,8 @@ export class Application extends BaseInterface<typeof Applications> {
|
|||
token: string,
|
||||
): Promise<Application | null> {
|
||||
const result = await db.query.Tokens.findFirst({
|
||||
where: (tokens, { eq }) => eq(tokens.accessToken, token),
|
||||
where: (tokens, { eq }): SQL | undefined =>
|
||||
eq(tokens.accessToken, token),
|
||||
with: {
|
||||
application: true,
|
||||
},
|
||||
|
|
@ -141,7 +142,7 @@ export class Application extends BaseInterface<typeof Applications> {
|
|||
return application;
|
||||
}
|
||||
|
||||
public get id() {
|
||||
public get id(): string {
|
||||
return this.data.id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -148,11 +148,11 @@ export class Attachment extends BaseInterface<typeof Attachments> {
|
|||
return attachment;
|
||||
}
|
||||
|
||||
public get id() {
|
||||
public get id(): string {
|
||||
return this.data.id;
|
||||
}
|
||||
|
||||
public static getUrl(name: string) {
|
||||
public static getUrl(name: string): string {
|
||||
if (config.media.backend === MediaBackendType.Local) {
|
||||
return new URL(`/media/${name}`, config.http.base_url).toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ export class Emoji extends BaseInterface<typeof Emojis, EmojiWithInstance> {
|
|||
return await Emoji.fromVersia(emojiToFetch, foundInstance?.id ?? null);
|
||||
}
|
||||
|
||||
public get id() {
|
||||
public get id(): string {
|
||||
return this.data.id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
return instance;
|
||||
}
|
||||
|
||||
public get id() {
|
||||
public get id(): string {
|
||||
return this.data.id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export class Like extends BaseInterface<typeof Likes, LikeType> {
|
|||
public static async fromSql(
|
||||
sql: SQL<unknown> | undefined,
|
||||
orderBy: SQL<unknown> | undefined = desc(Likes.id),
|
||||
) {
|
||||
): Promise<Like | null> {
|
||||
const found = await db.query.Likes.findFirst({
|
||||
where: sql,
|
||||
orderBy,
|
||||
|
|
@ -81,7 +81,7 @@ export class Like extends BaseInterface<typeof Likes, LikeType> {
|
|||
limit?: number,
|
||||
offset?: number,
|
||||
extra?: Parameters<typeof db.query.Likes.findMany>[0],
|
||||
) {
|
||||
): Promise<Like[]> {
|
||||
const found = await db.query.Likes.findMany({
|
||||
where: sql,
|
||||
orderBy,
|
||||
|
|
@ -135,7 +135,7 @@ export class Like extends BaseInterface<typeof Likes, LikeType> {
|
|||
return role;
|
||||
}
|
||||
|
||||
public get id() {
|
||||
public get id(): string {
|
||||
return this.data.id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
|||
return found.map((s) => new Note(s));
|
||||
}
|
||||
|
||||
public get id() {
|
||||
public get id(): string {
|
||||
return this.data.id;
|
||||
}
|
||||
|
||||
|
|
@ -319,7 +319,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
|||
{
|
||||
with: {
|
||||
relationships: {
|
||||
where: (relationship, { eq, and }) =>
|
||||
where: (relationship, { eq, and }): SQL | undefined =>
|
||||
and(
|
||||
eq(relationship.subjectId, this.data.authorId),
|
||||
eq(relationship.following, true),
|
||||
|
|
@ -339,7 +339,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
|||
return deduplicatedUsersById;
|
||||
}
|
||||
|
||||
public get author() {
|
||||
public get author(): User {
|
||||
return new User(this.data.author);
|
||||
}
|
||||
|
||||
|
|
@ -369,7 +369,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
|||
);
|
||||
}
|
||||
|
||||
public isRemote() {
|
||||
public isRemote(): boolean {
|
||||
return this.author.isRemote();
|
||||
}
|
||||
|
||||
|
|
@ -846,7 +846,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
|||
if (this.data.visibility === "private") {
|
||||
return user
|
||||
? !!(await db.query.Relationships.findFirst({
|
||||
where: (relationship, { and, eq }) =>
|
||||
where: (relationship, { and, eq }): SQL | undefined =>
|
||||
and(
|
||||
eq(relationship.ownerId, user?.id),
|
||||
eq(relationship.subjectId, Notes.authorId),
|
||||
|
|
@ -877,7 +877,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
|||
// Rewrite all src tags to go through proxy
|
||||
let replacedContent = new HTMLRewriter()
|
||||
.on("[src]", {
|
||||
element(element) {
|
||||
element(element): void {
|
||||
element.setAttribute(
|
||||
"src",
|
||||
proxyUrl(element.getAttribute("src") ?? "") ?? "",
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ export class Relationship extends BaseInterface<
|
|||
ownerId: string;
|
||||
}): Promise<RelationshipType> {
|
||||
let output = await db.query.Relationships.findFirst({
|
||||
where: (rel, { and, eq }) =>
|
||||
where: (rel, { and, eq }): SQL | undefined =>
|
||||
and(
|
||||
eq(rel.ownerId, oppositeTo.subjectId),
|
||||
eq(rel.subjectId, oppositeTo.ownerId),
|
||||
|
|
@ -286,7 +286,7 @@ export class Relationship extends BaseInterface<
|
|||
return relationship;
|
||||
}
|
||||
|
||||
public get id() {
|
||||
public get id(): string {
|
||||
return this.data.id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import { proxyUrl } from "@/response";
|
||||
import { RolePermission } from "@versia/client/types";
|
||||
import {
|
||||
type VersiaRole as APIRole,
|
||||
RolePermission,
|
||||
} from "@versia/client/types";
|
||||
import { db } from "@versia/kit/db";
|
||||
import { RoleToUsers, Roles } from "@versia/kit/tables";
|
||||
import {
|
||||
|
|
@ -53,7 +56,7 @@ export class Role extends BaseInterface<typeof Roles> {
|
|||
public static async fromSql(
|
||||
sql: SQL<unknown> | undefined,
|
||||
orderBy: SQL<unknown> | undefined = desc(Roles.id),
|
||||
) {
|
||||
): Promise<Role | null> {
|
||||
const found = await db.query.Roles.findFirst({
|
||||
where: sql,
|
||||
orderBy,
|
||||
|
|
@ -65,10 +68,14 @@ export class Role extends BaseInterface<typeof Roles> {
|
|||
return new Role(found);
|
||||
}
|
||||
|
||||
public static async getUserRoles(userId: string, isAdmin: boolean) {
|
||||
public static async getUserRoles(
|
||||
userId: string,
|
||||
isAdmin: boolean,
|
||||
): Promise<Role[]> {
|
||||
return (
|
||||
await db.query.RoleToUsers.findMany({
|
||||
where: (role, { eq }) => eq(role.userId, userId),
|
||||
where: (role, { eq }): SQL | undefined =>
|
||||
eq(role.userId, userId),
|
||||
with: {
|
||||
role: true,
|
||||
user: {
|
||||
|
|
@ -115,7 +122,7 @@ export class Role extends BaseInterface<typeof Roles> {
|
|||
limit?: number,
|
||||
offset?: number,
|
||||
extra?: Parameters<typeof db.query.Roles.findMany>[0],
|
||||
) {
|
||||
): Promise<Role[]> {
|
||||
const found = await db.query.Roles.findMany({
|
||||
where: sql,
|
||||
orderBy,
|
||||
|
|
@ -165,14 +172,14 @@ export class Role extends BaseInterface<typeof Roles> {
|
|||
return role;
|
||||
}
|
||||
|
||||
public async linkUser(userId: string) {
|
||||
public async linkUser(userId: string): Promise<void> {
|
||||
await db.insert(RoleToUsers).values({
|
||||
userId,
|
||||
roleId: this.id,
|
||||
});
|
||||
}
|
||||
|
||||
public async unlinkUser(userId: string) {
|
||||
public async unlinkUser(userId: string): Promise<void> {
|
||||
await db
|
||||
.delete(RoleToUsers)
|
||||
.where(
|
||||
|
|
@ -183,11 +190,11 @@ export class Role extends BaseInterface<typeof Roles> {
|
|||
);
|
||||
}
|
||||
|
||||
public get id() {
|
||||
public get id(): string {
|
||||
return this.data.id;
|
||||
}
|
||||
|
||||
public toApi() {
|
||||
public toApi(): APIRole {
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.data.name,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export class Timeline<Type extends Note | User> {
|
|||
limit: number,
|
||||
url: string,
|
||||
userId?: string,
|
||||
) {
|
||||
): Promise<{ link: string; objects: Note[] }> {
|
||||
return new Timeline<Note>(TimelineType.Note).fetchTimeline(
|
||||
sql,
|
||||
limit,
|
||||
|
|
@ -30,7 +30,7 @@ export class Timeline<Type extends Note | User> {
|
|||
sql: SQL<unknown> | undefined,
|
||||
limit: number,
|
||||
url: string,
|
||||
) {
|
||||
): Promise<{ link: string; objects: User[] }> {
|
||||
return new Timeline<User>(TimelineType.User).fetchTimeline(
|
||||
sql,
|
||||
limit,
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
public static async fromSql(
|
||||
sql: SQL<unknown> | undefined,
|
||||
orderBy: SQL<unknown> | undefined = desc(Users.id),
|
||||
) {
|
||||
): Promise<User | null> {
|
||||
const found = await findManyUsers({
|
||||
where: sql,
|
||||
orderBy,
|
||||
|
|
@ -168,7 +168,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
limit?: number,
|
||||
offset?: number,
|
||||
extra?: Parameters<typeof db.query.Users.findMany>[0],
|
||||
) {
|
||||
): Promise<User[]> {
|
||||
const found = await findManyUsers({
|
||||
where: sql,
|
||||
orderBy,
|
||||
|
|
@ -180,34 +180,38 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
return found.map((s) => new User(s));
|
||||
}
|
||||
|
||||
public get id() {
|
||||
public get id(): string {
|
||||
return this.data.id;
|
||||
}
|
||||
|
||||
public isLocal() {
|
||||
public isLocal(): boolean {
|
||||
return this.data.instanceId === null;
|
||||
}
|
||||
|
||||
public isRemote() {
|
||||
public isRemote(): boolean {
|
||||
return !this.isLocal();
|
||||
}
|
||||
|
||||
public getUri() {
|
||||
public getUri(): string {
|
||||
return (
|
||||
this.data.uri ||
|
||||
new URL(`/users/${this.data.id}`, config.http.base_url).toString()
|
||||
);
|
||||
}
|
||||
|
||||
public static getUri(id: string, uri: string | null, baseUrl: string) {
|
||||
public static getUri(
|
||||
id: string,
|
||||
uri: string | null,
|
||||
baseUrl: string,
|
||||
): string {
|
||||
return uri || new URL(`/users/${id}`, baseUrl).toString();
|
||||
}
|
||||
|
||||
public hasPermission(permission: RolePermissions) {
|
||||
public hasPermission(permission: RolePermissions): boolean {
|
||||
return this.getAllPermissions().includes(permission);
|
||||
}
|
||||
|
||||
public getAllPermissions() {
|
||||
public getAllPermissions(): RolePermissions[] {
|
||||
return (
|
||||
this.data.roles
|
||||
.flatMap((role) => role.permissions)
|
||||
|
|
@ -270,7 +274,10 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
return foundRelationship;
|
||||
}
|
||||
|
||||
public async unfollow(followee: User, relationship: Relationship) {
|
||||
public async unfollow(
|
||||
followee: User,
|
||||
relationship: Relationship,
|
||||
): Promise<boolean> {
|
||||
if (followee.isRemote()) {
|
||||
// TODO: This should reschedule for a later time and maybe notify the server admin if it fails too often
|
||||
const { ok } = await this.federateToUser(
|
||||
|
|
@ -348,7 +355,9 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
return db.$count(Users, isNull(Users.instanceId));
|
||||
}
|
||||
|
||||
public static async getActiveInPeriod(milliseconds: number) {
|
||||
public static async getActiveInPeriod(
|
||||
milliseconds: number,
|
||||
): Promise<number> {
|
||||
return (
|
||||
await db
|
||||
.select({
|
||||
|
|
@ -376,7 +385,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
}
|
||||
}
|
||||
|
||||
public async resetPassword() {
|
||||
public async resetPassword(): Promise<string> {
|
||||
const resetToken = randomString(32, "hex");
|
||||
|
||||
await this.update({
|
||||
|
|
@ -386,30 +395,22 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
return resetToken;
|
||||
}
|
||||
|
||||
public async pin(note: Note) {
|
||||
return (
|
||||
await db
|
||||
.insert(UserToPinnedNotes)
|
||||
.values({
|
||||
noteId: note.id,
|
||||
userId: this.id,
|
||||
})
|
||||
.returning()
|
||||
)[0];
|
||||
public async pin(note: Note): Promise<void> {
|
||||
await db.insert(UserToPinnedNotes).values({
|
||||
noteId: note.id,
|
||||
userId: this.id,
|
||||
});
|
||||
}
|
||||
|
||||
public async unpin(note: Note) {
|
||||
return (
|
||||
await db
|
||||
.delete(UserToPinnedNotes)
|
||||
.where(
|
||||
and(
|
||||
eq(NoteToMentions.noteId, note.id),
|
||||
eq(NoteToMentions.userId, this.id),
|
||||
),
|
||||
)
|
||||
.returning()
|
||||
)[0];
|
||||
public async unpin(note: Note): Promise<void> {
|
||||
await db
|
||||
.delete(UserToPinnedNotes)
|
||||
.where(
|
||||
and(
|
||||
eq(NoteToMentions.noteId, note.id),
|
||||
eq(NoteToMentions.userId, this.id),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public save(): Promise<UserWithRelations> {
|
||||
|
|
@ -434,7 +435,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
> {
|
||||
// Get all linked accounts
|
||||
const accounts = await db.query.OpenIdAccounts.findMany({
|
||||
where: (User, { eq }) => eq(User.userId, this.id),
|
||||
where: (User, { eq }): SQL | undefined => eq(User.userId, this.id),
|
||||
});
|
||||
|
||||
return accounts
|
||||
|
|
@ -715,7 +716,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
* @param config The config to use
|
||||
* @returns The raw URL for the user's avatar
|
||||
*/
|
||||
public getAvatarUrl(config: Config) {
|
||||
public getAvatarUrl(config: Config): string {
|
||||
if (!this.data.avatar) {
|
||||
return (
|
||||
config.defaults.avatar ||
|
||||
|
|
@ -725,7 +726,10 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
return this.data.avatar;
|
||||
}
|
||||
|
||||
public static async generateKeys() {
|
||||
public static async generateKeys(): Promise<{
|
||||
private_key: string;
|
||||
public_key: string;
|
||||
}> {
|
||||
const keys = await crypto.subtle.generateKey("Ed25519", true, [
|
||||
"sign",
|
||||
"verify",
|
||||
|
|
@ -807,14 +811,14 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
* @param config The config to use
|
||||
* @returns The raw URL for the user's header
|
||||
*/
|
||||
public getHeaderUrl(config: Config) {
|
||||
public getHeaderUrl(config: Config): string {
|
||||
if (!this.data.header) {
|
||||
return config.defaults.header || "";
|
||||
}
|
||||
return this.data.header;
|
||||
}
|
||||
|
||||
public getAcct() {
|
||||
public getAcct(): string {
|
||||
return this.isLocal()
|
||||
? this.data.username
|
||||
: `${this.data.username}@${this.data.instance?.baseUrl}`;
|
||||
|
|
@ -824,7 +828,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
isLocal: boolean,
|
||||
username: string,
|
||||
baseUrl?: string,
|
||||
) {
|
||||
): string {
|
||||
return isLocal ? username : `${username}@${baseUrl}`;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ export const parseTextMentions = async (
|
|||
|
||||
const baseUrlHost = new URL(config.http.base_url).host;
|
||||
|
||||
const isLocal = (host?: string) => host === baseUrlHost || !host;
|
||||
const isLocal = (host?: string): boolean => host === baseUrlHost || !host;
|
||||
|
||||
const foundUsers = await db
|
||||
.select({
|
||||
|
|
@ -326,7 +326,7 @@ export const parseTextMentions = async (
|
|||
return finalList;
|
||||
};
|
||||
|
||||
export const replaceTextMentions = (text: string, mentions: User[]) => {
|
||||
export const replaceTextMentions = (text: string, mentions: User[]): string => {
|
||||
let finalText = text;
|
||||
for (const mention of mentions) {
|
||||
const user = mention.data;
|
||||
|
|
@ -405,7 +405,7 @@ export const contentToHtml = async (
|
|||
htmlContent = linkifyHtml(htmlContent, {
|
||||
defaultProtocol: "https",
|
||||
validate: {
|
||||
email: () => false,
|
||||
email: (): false => false,
|
||||
},
|
||||
target: "_blank",
|
||||
rel: "nofollow noopener noreferrer",
|
||||
|
|
@ -414,11 +414,11 @@ export const contentToHtml = async (
|
|||
return htmlContent;
|
||||
};
|
||||
|
||||
export const markdownParse = async (content: string) => {
|
||||
export const markdownParse = async (content: string): Promise<string> => {
|
||||
return (await getMarkdownRenderer()).render(content);
|
||||
};
|
||||
|
||||
export const getMarkdownRenderer = () => {
|
||||
export const getMarkdownRenderer = (): MarkdownIt => {
|
||||
const renderer = MarkdownIt({
|
||||
html: true,
|
||||
linkify: true,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
Tokens,
|
||||
type Users,
|
||||
} from "@versia/kit/tables";
|
||||
import { type InferSelectModel, eq, sql } from "drizzle-orm";
|
||||
import { type InferSelectModel, type SQL, eq, sql } from "drizzle-orm";
|
||||
import type { ApplicationType } from "~/classes/database/application.ts";
|
||||
import type { EmojiWithInstance } from "~/classes/database/emoji.ts";
|
||||
import type { Token } from "./token.ts";
|
||||
|
|
@ -80,7 +80,13 @@ export const userExtras = {
|
|||
),
|
||||
};
|
||||
|
||||
export const userExtrasTemplate = (name: string) => ({
|
||||
export const userExtrasTemplate = (
|
||||
name: string,
|
||||
): {
|
||||
followerCount: SQL.Aliased<unknown>;
|
||||
followingCount: SQL.Aliased<unknown>;
|
||||
statusCount: SQL.Aliased<unknown>;
|
||||
} => ({
|
||||
// @ts-expect-error sql is a template tag, so it gets confused when we use it as a function
|
||||
followerCount: sql([
|
||||
`(SELECT COUNT(*) FROM "Relationships" "relationships" WHERE ("relationships"."ownerId" = "${name}".id AND "relationships"."following" = true))`,
|
||||
|
|
@ -214,7 +220,8 @@ export const retrieveToken = async (
|
|||
|
||||
return (
|
||||
(await db.query.Tokens.findFirst({
|
||||
where: (tokens, { eq }) => eq(tokens.accessToken, accessToken),
|
||||
where: (tokens, { eq }): SQL | undefined =>
|
||||
eq(tokens.accessToken, accessToken),
|
||||
})) ?? null
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -219,14 +219,18 @@ export class InboxProcessor {
|
|||
|
||||
try {
|
||||
return await handler.parseBody<Response>({
|
||||
note: () => this.processNote(),
|
||||
follow: () => this.processFollowRequest(),
|
||||
followAccept: () => this.processFollowAccept(),
|
||||
followReject: () => this.processFollowReject(),
|
||||
"pub.versia:likes/Like": () => this.processLikeRequest(),
|
||||
delete: () => this.processDelete(),
|
||||
user: () => this.processUserRequest(),
|
||||
unknown: () =>
|
||||
note: (): Promise<Response> => this.processNote(),
|
||||
follow: (): Promise<Response> => this.processFollowRequest(),
|
||||
followAccept: (): Promise<Response> =>
|
||||
this.processFollowAccept(),
|
||||
followReject: (): Promise<Response> =>
|
||||
this.processFollowReject(),
|
||||
"pub.versia:likes/Like": (): Promise<Response> =>
|
||||
this.processLikeRequest(),
|
||||
delete: (): Promise<Response> => this.processDelete(),
|
||||
user: (): Promise<Response> => this.processUserRequest(),
|
||||
unknown: (): Response &
|
||||
TypedResponse<{ error: string }, 400, "json"> =>
|
||||
this.context.json({ error: "Unknown entity type" }, 400),
|
||||
});
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ describe("S3MediaDriver", () => {
|
|||
putObject: mock(() => Promise.resolve()),
|
||||
getObject: mock(() =>
|
||||
Promise.resolve({
|
||||
arrayBuffer: () => Promise.resolve(new ArrayBuffer(8)),
|
||||
arrayBuffer: (): Promise<ArrayBuffer> =>
|
||||
Promise.resolve(new ArrayBuffer(8)),
|
||||
headers: new Headers({ "Content-Type": "image/webp" }),
|
||||
}),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ describe("BlurhashPreprocessor", () => {
|
|||
});
|
||||
|
||||
mock.module("blurhash", () => ({
|
||||
encode: () => {
|
||||
encode: (): void => {
|
||||
throw new Error("Test error");
|
||||
},
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@ describe("PluginLoader", () => {
|
|||
|
||||
test("getDirectories should return directories", async () => {
|
||||
mockReaddir.mockResolvedValue([
|
||||
{ name: "dir1", isDirectory: () => true },
|
||||
{ name: "file1", isDirectory: () => false },
|
||||
{ name: "dir2", isDirectory: () => true },
|
||||
{ name: "dir1", isDirectory: (): true => true },
|
||||
{ name: "file1", isDirectory: (): false => false },
|
||||
{ name: "dir2", isDirectory: (): true => true },
|
||||
]);
|
||||
|
||||
// biome-ignore lint/complexity/useLiteralKeys: Private method
|
||||
|
|
@ -80,7 +80,8 @@ describe("PluginLoader", () => {
|
|||
test("parseManifestFile should parse JSON manifest", async () => {
|
||||
const manifestContent = { name: "test-plugin" };
|
||||
Bun.file = jest.fn().mockReturnValue({
|
||||
text: () => Promise.resolve(JSON.stringify(manifestContent)),
|
||||
text: (): Promise<string> =>
|
||||
Promise.resolve(JSON.stringify(manifestContent)),
|
||||
});
|
||||
|
||||
// biome-ignore lint/complexity/useLiteralKeys: Private method
|
||||
|
|
@ -94,8 +95,8 @@ describe("PluginLoader", () => {
|
|||
test("findPlugins should return plugin directories with valid manifest and entrypoint", async () => {
|
||||
mockReaddir
|
||||
.mockResolvedValueOnce([
|
||||
{ name: "plugin1", isDirectory: () => true },
|
||||
{ name: "plugin2", isDirectory: () => true },
|
||||
{ name: "plugin1", isDirectory: (): true => true },
|
||||
{ name: "plugin2", isDirectory: (): true => true },
|
||||
])
|
||||
.mockResolvedValue(["manifest.json", "index.ts"]);
|
||||
|
||||
|
|
@ -111,7 +112,8 @@ describe("PluginLoader", () => {
|
|||
};
|
||||
mockReaddir.mockResolvedValue(["manifest.json"]);
|
||||
Bun.file = jest.fn().mockReturnValue({
|
||||
text: () => Promise.resolve(JSON.stringify(manifestContent)),
|
||||
text: (): Promise<string> =>
|
||||
Promise.resolve(JSON.stringify(manifestContent)),
|
||||
});
|
||||
manifestSchema.safeParseAsync = jest.fn().mockResolvedValue({
|
||||
success: true,
|
||||
|
|
@ -141,7 +143,8 @@ describe("PluginLoader", () => {
|
|||
};
|
||||
mockReaddir.mockResolvedValue(["manifest.json"]);
|
||||
Bun.file = jest.fn().mockReturnValue({
|
||||
text: () => Promise.resolve(JSON.stringify(manifestContent)),
|
||||
text: (): Promise<string> =>
|
||||
Promise.resolve(JSON.stringify(manifestContent)),
|
||||
});
|
||||
manifestSchema.safeParseAsync = jest.fn().mockResolvedValue({
|
||||
success: false,
|
||||
|
|
@ -183,12 +186,13 @@ describe("PluginLoader", () => {
|
|||
|
||||
mockReaddir
|
||||
.mockResolvedValueOnce([
|
||||
{ name: "plugin1", isDirectory: () => true },
|
||||
{ name: "plugin2", isDirectory: () => true },
|
||||
{ name: "plugin1", isDirectory: (): true => true },
|
||||
{ name: "plugin2", isDirectory: (): true => true },
|
||||
])
|
||||
.mockResolvedValue(["manifest.json", "index.ts"]);
|
||||
Bun.file = jest.fn().mockReturnValue({
|
||||
text: () => Promise.resolve(JSON.stringify(manifestContent)),
|
||||
text: (): Promise<string> =>
|
||||
Promise.resolve(JSON.stringify(manifestContent)),
|
||||
});
|
||||
manifestSchema.safeParseAsync = jest.fn().mockResolvedValue({
|
||||
success: true,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { getLogger } from "@logtape/logtape";
|
||||
import { Note, User, db } from "@versia/kit/db";
|
||||
import type { SQL, ValueOrArray } from "drizzle-orm";
|
||||
import {
|
||||
Ingest as SonicChannelIngest,
|
||||
Search as SonicChannelSearch,
|
||||
|
|
@ -63,21 +64,21 @@ export class SonicSearchManager {
|
|||
// Connect to Sonic
|
||||
await new Promise<boolean>((resolve, reject) => {
|
||||
this.searchChannel.connect({
|
||||
connected: () => {
|
||||
connected: (): void => {
|
||||
!silent &&
|
||||
this.logger.info`Connected to Sonic Search Channel`;
|
||||
resolve(true);
|
||||
},
|
||||
disconnected: () =>
|
||||
disconnected: (): void =>
|
||||
this.logger
|
||||
.error`Disconnected from Sonic Search Channel. You might be using an incorrect password.`,
|
||||
timeout: () =>
|
||||
timeout: (): void =>
|
||||
this.logger
|
||||
.error`Sonic Search Channel connection timed out`,
|
||||
retrying: () =>
|
||||
retrying: (): void =>
|
||||
this.logger
|
||||
.warn`Retrying connection to Sonic Search Channel`,
|
||||
error: (error) => {
|
||||
error: (error): void => {
|
||||
this.logger
|
||||
.error`Failed to connect to Sonic Search Channel: ${error}`;
|
||||
reject(error);
|
||||
|
|
@ -87,20 +88,20 @@ export class SonicSearchManager {
|
|||
|
||||
await new Promise<boolean>((resolve, reject) => {
|
||||
this.ingestChannel.connect({
|
||||
connected: () => {
|
||||
connected: (): void => {
|
||||
!silent &&
|
||||
this.logger.info`Connected to Sonic Ingest Channel`;
|
||||
resolve(true);
|
||||
},
|
||||
disconnected: () =>
|
||||
disconnected: (): void =>
|
||||
this.logger.error`Disconnected from Sonic Ingest Channel`,
|
||||
timeout: () =>
|
||||
timeout: (): void =>
|
||||
this.logger
|
||||
.error`Sonic Ingest Channel connection timed out`,
|
||||
retrying: () =>
|
||||
retrying: (): void =>
|
||||
this.logger
|
||||
.warn`Retrying connection to Sonic Ingest Channel`,
|
||||
error: (error) => {
|
||||
error: (error): void => {
|
||||
this.logger
|
||||
.error`Failed to connect to Sonic Ingest Channel: ${error}`;
|
||||
reject(error);
|
||||
|
|
@ -161,7 +162,7 @@ export class SonicSearchManager {
|
|||
note: true,
|
||||
createdAt: true,
|
||||
},
|
||||
orderBy: (user, { asc }) => asc(user.createdAt),
|
||||
orderBy: (user, { asc }): ValueOrArray<SQL> => asc(user.createdAt),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -182,7 +183,8 @@ export class SonicSearchManager {
|
|||
content: true,
|
||||
createdAt: true,
|
||||
},
|
||||
orderBy: (status, { asc }) => asc(status.createdAt),
|
||||
orderBy: (status, { asc }): ValueOrArray<SQL> =>
|
||||
asc(status.createdAt),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue