mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
refactor: 🏷️ Move all types that represent ORM abstractions to ORM class static properties
This commit is contained in:
parent
ca31830fb3
commit
02c3c9d0bf
|
|
@ -12,7 +12,7 @@ import {
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
|
|
||||||
export type ApplicationType = InferSelectModel<typeof Applications>;
|
type ApplicationType = InferSelectModel<typeof Applications>;
|
||||||
|
|
||||||
export class Application extends BaseInterface<typeof Applications> {
|
export class Application extends BaseInterface<typeof Applications> {
|
||||||
public static schema: z.ZodType<APIApplication> = z.object({
|
public static schema: z.ZodType<APIApplication> = z.object({
|
||||||
|
|
@ -23,6 +23,8 @@ export class Application extends BaseInterface<typeof Applications> {
|
||||||
scopes: z.string().optional(),
|
scopes: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static $type: ApplicationType;
|
||||||
|
|
||||||
public async reload(): Promise<void> {
|
public async reload(): Promise<void> {
|
||||||
const reloaded = await Application.fromId(this.data.id);
|
const reloaded = await Application.fromId(this.data.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import { MediaBackendType } from "~/packages/config-manager/config.type";
|
||||||
import { config } from "~/packages/config-manager/index.ts";
|
import { config } from "~/packages/config-manager/index.ts";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
|
|
||||||
export type AttachmentType = InferSelectModel<typeof Attachments>;
|
type AttachmentType = InferSelectModel<typeof Attachments>;
|
||||||
|
|
||||||
export class Attachment extends BaseInterface<typeof Attachments> {
|
export class Attachment extends BaseInterface<typeof Attachments> {
|
||||||
public static schema: z.ZodType<ApiAttachment> = z.object({
|
public static schema: z.ZodType<ApiAttachment> = z.object({
|
||||||
|
|
@ -47,6 +47,8 @@ export class Attachment extends BaseInterface<typeof Attachments> {
|
||||||
blurhash: z.string().nullable(),
|
blurhash: z.string().nullable(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static $type: AttachmentType;
|
||||||
|
|
||||||
public async reload(): Promise<void> {
|
public async reload(): Promise<void> {
|
||||||
const reloaded = await Attachment.fromId(this.data.id);
|
const reloaded = await Attachment.fromId(this.data.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import { z } from "zod";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
import { Instance } from "./instance.ts";
|
import { Instance } from "./instance.ts";
|
||||||
|
|
||||||
export type EmojiWithInstance = InferSelectModel<typeof Emojis> & {
|
type EmojiWithInstance = InferSelectModel<typeof Emojis> & {
|
||||||
instance: InferSelectModel<typeof Instances> | null;
|
instance: InferSelectModel<typeof Instances> | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -30,6 +30,8 @@ export class Emoji extends BaseInterface<typeof Emojis, EmojiWithInstance> {
|
||||||
static_url: z.string(),
|
static_url: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static $type: EmojiWithInstance;
|
||||||
|
|
||||||
public async reload(): Promise<void> {
|
public async reload(): Promise<void> {
|
||||||
const reloaded = await Emoji.fromId(this.data.id);
|
const reloaded = await Emoji.fromId(this.data.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@ import { config } from "~/packages/config-manager/index.ts";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
import { User } from "./user.ts";
|
import { User } from "./user.ts";
|
||||||
|
|
||||||
export type InstanceType = InferSelectModel<typeof Instances>;
|
type InstanceType = InferSelectModel<typeof Instances>;
|
||||||
|
|
||||||
export class Instance extends BaseInterface<typeof Instances> {
|
export class Instance extends BaseInterface<typeof Instances> {
|
||||||
|
public static $type: InstanceType;
|
||||||
|
|
||||||
public async reload(): Promise<void> {
|
public async reload(): Promise<void> {
|
||||||
const reloaded = await Instance.fromId(this.data.id);
|
const reloaded = await Instance.fromId(this.data.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
import { RolePermission } from "@versia/client/types";
|
import { RolePermission } from "@versia/client/types";
|
||||||
import type { Delete, LikeExtension } from "@versia/federation/types";
|
import type { Delete, LikeExtension } from "@versia/federation/types";
|
||||||
import { db } from "@versia/kit/db";
|
import { db } from "@versia/kit/db";
|
||||||
import { Likes, Notifications } from "@versia/kit/tables";
|
import {
|
||||||
|
Likes,
|
||||||
|
type Notes,
|
||||||
|
Notifications,
|
||||||
|
type Users,
|
||||||
|
} from "@versia/kit/tables";
|
||||||
import {
|
import {
|
||||||
type InferInsertModel,
|
type InferInsertModel,
|
||||||
type InferSelectModel,
|
type InferSelectModel,
|
||||||
|
|
@ -13,15 +18,13 @@ import {
|
||||||
} from "drizzle-orm";
|
} from "drizzle-orm";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { config } from "~/packages/config-manager/index.ts";
|
import { config } from "~/packages/config-manager/index.ts";
|
||||||
import type { Status } from "../functions/status.ts";
|
|
||||||
import type { UserType } from "../functions/user.ts";
|
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
import { Note } from "./note.ts";
|
import { Note } from "./note.ts";
|
||||||
import { User } from "./user.ts";
|
import { User } from "./user.ts";
|
||||||
|
|
||||||
export type LikeType = InferSelectModel<typeof Likes> & {
|
type LikeType = InferSelectModel<typeof Likes> & {
|
||||||
liker: UserType;
|
liker: InferSelectModel<typeof Users>;
|
||||||
liked: Status;
|
liked: InferSelectModel<typeof Notes>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Like extends BaseInterface<typeof Likes, LikeType> {
|
export class Like extends BaseInterface<typeof Likes, LikeType> {
|
||||||
|
|
@ -35,6 +38,8 @@ export class Like extends BaseInterface<typeof Likes, LikeType> {
|
||||||
icon: z.string().nullable(),
|
icon: z.string().nullable(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static $type: LikeType;
|
||||||
|
|
||||||
public async reload(): Promise<void> {
|
public async reload(): Promise<void> {
|
||||||
const reloaded = await Like.fromId(this.data.id);
|
const reloaded = await Like.fromId(this.data.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import type {
|
||||||
Delete as VersiaDelete,
|
Delete as VersiaDelete,
|
||||||
Note as VersiaNote,
|
Note as VersiaNote,
|
||||||
} from "@versia/federation/types";
|
} from "@versia/federation/types";
|
||||||
import { Notification, db } from "@versia/kit/db";
|
import { type Instance, Notification, db } from "@versia/kit/db";
|
||||||
import {
|
import {
|
||||||
Attachments,
|
Attachments,
|
||||||
EmojiToNote,
|
EmojiToNote,
|
||||||
|
|
@ -24,6 +24,7 @@ import {
|
||||||
} from "@versia/kit/tables";
|
} from "@versia/kit/tables";
|
||||||
import {
|
import {
|
||||||
type InferInsertModel,
|
type InferInsertModel,
|
||||||
|
type InferSelectModel,
|
||||||
type SQL,
|
type SQL,
|
||||||
and,
|
and,
|
||||||
desc,
|
desc,
|
||||||
|
|
@ -36,7 +37,6 @@ import { htmlToText } from "html-to-text";
|
||||||
import { createRegExp, exactly, global } from "magic-regexp";
|
import { createRegExp, exactly, global } from "magic-regexp";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import {
|
import {
|
||||||
type StatusWithRelations,
|
|
||||||
contentToHtml,
|
contentToHtml,
|
||||||
findManyNotes,
|
findManyNotes,
|
||||||
parseTextMentions,
|
parseTextMentions,
|
||||||
|
|
@ -48,10 +48,37 @@ import { BaseInterface } from "./base.ts";
|
||||||
import { Emoji } from "./emoji.ts";
|
import { Emoji } from "./emoji.ts";
|
||||||
import { User } from "./user.ts";
|
import { User } from "./user.ts";
|
||||||
|
|
||||||
|
type NoteType = InferSelectModel<typeof Notes>;
|
||||||
|
|
||||||
|
type NoteTypeWithRelations = NoteType & {
|
||||||
|
author: typeof User.$type;
|
||||||
|
mentions: (InferSelectModel<typeof Users> & {
|
||||||
|
instance: typeof Instance.$type | null;
|
||||||
|
})[];
|
||||||
|
attachments: (typeof Attachment.$type)[];
|
||||||
|
reblog: NoteTypeWithoutRecursiveRelations | null;
|
||||||
|
emojis: (typeof Emoji.$type)[];
|
||||||
|
reply: NoteType | null;
|
||||||
|
quote: NoteType | null;
|
||||||
|
application: typeof Application.$type | null;
|
||||||
|
reblogCount: number;
|
||||||
|
likeCount: number;
|
||||||
|
replyCount: number;
|
||||||
|
pinned: boolean;
|
||||||
|
reblogged: boolean;
|
||||||
|
muted: boolean;
|
||||||
|
liked: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NoteTypeWithoutRecursiveRelations = Omit<
|
||||||
|
NoteTypeWithRelations,
|
||||||
|
"reply" | "quote" | "reblog"
|
||||||
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives helpers to fetch notes from database in a nice format
|
* Gives helpers to fetch notes from database in a nice format
|
||||||
*/
|
*/
|
||||||
export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
|
||||||
public static schema: z.ZodType<ApiStatus> = z.object({
|
public static schema: z.ZodType<ApiStatus> = z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
uri: z.string().url(),
|
uri: z.string().url(),
|
||||||
|
|
@ -142,7 +169,9 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
||||||
bookmarked: z.boolean(),
|
bookmarked: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
public save(): Promise<StatusWithRelations> {
|
public static $type: NoteTypeWithRelations;
|
||||||
|
|
||||||
|
public save(): Promise<NoteTypeWithRelations> {
|
||||||
return this.update(this.data);
|
return this.update(this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -814,8 +843,8 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async update(
|
public async update(
|
||||||
newStatus: Partial<StatusWithRelations>,
|
newStatus: Partial<NoteTypeWithRelations>,
|
||||||
): Promise<StatusWithRelations> {
|
): Promise<NoteTypeWithRelations> {
|
||||||
await db.update(Notes).set(newStatus).where(eq(Notes.id, this.data.id));
|
await db.update(Notes).set(newStatus).where(eq(Notes.id, this.data.id));
|
||||||
|
|
||||||
const updated = await Note.fromId(this.data.id);
|
const updated = await Note.fromId(this.data.id);
|
||||||
|
|
@ -932,7 +961,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
||||||
// TODO: Add polls
|
// TODO: Add polls
|
||||||
poll: null,
|
poll: null,
|
||||||
reblog: data.reblog
|
reblog: data.reblog
|
||||||
? await new Note(data.reblog as StatusWithRelations).toApi(
|
? await new Note(data.reblog as NoteTypeWithRelations).toApi(
|
||||||
userFetching,
|
userFetching,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,7 @@ import {
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { MediaBackendType } from "~/packages/config-manager/config.type";
|
import { MediaBackendType } from "~/packages/config-manager/config.type";
|
||||||
import { config } from "~/packages/config-manager/index.ts";
|
import { config } from "~/packages/config-manager/index.ts";
|
||||||
import type { StatusWithRelations } from "../functions/status.ts";
|
|
||||||
import {
|
import {
|
||||||
type UserWithRelations,
|
|
||||||
transformOutputToUserWithRelations,
|
transformOutputToUserWithRelations,
|
||||||
userExtrasTemplate,
|
userExtrasTemplate,
|
||||||
userRelations,
|
userRelations,
|
||||||
|
|
@ -22,8 +20,8 @@ import {
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
|
|
||||||
export type NotificationType = InferSelectModel<typeof Notifications> & {
|
export type NotificationType = InferSelectModel<typeof Notifications> & {
|
||||||
status: StatusWithRelations | null;
|
status: typeof Note.$type | null;
|
||||||
account: UserWithRelations;
|
account: typeof User.$type;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Notification extends BaseInterface<
|
export class Notification extends BaseInterface<
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@ import { z } from "zod";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
import type { User } from "./user.ts";
|
import type { User } from "./user.ts";
|
||||||
|
|
||||||
export type RelationshipType = InferSelectModel<typeof Relationships>;
|
type RelationshipType = InferSelectModel<typeof Relationships>;
|
||||||
|
|
||||||
export type RelationshipWithOpposite = RelationshipType & {
|
type RelationshipWithOpposite = RelationshipType & {
|
||||||
followedBy: boolean;
|
followedBy: boolean;
|
||||||
blockedBy: boolean;
|
blockedBy: boolean;
|
||||||
requestedBy: boolean;
|
requestedBy: boolean;
|
||||||
|
|
@ -43,6 +43,8 @@ export class Relationship extends BaseInterface<
|
||||||
showing_reblogs: z.boolean(),
|
showing_reblogs: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static $type: RelationshipWithOpposite;
|
||||||
|
|
||||||
public async reload(): Promise<void> {
|
public async reload(): Promise<void> {
|
||||||
const reloaded = await Relationship.fromId(this.data.id);
|
const reloaded = await Relationship.fromId(this.data.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import { z } from "zod";
|
||||||
import { config } from "~/packages/config-manager/index.ts";
|
import { config } from "~/packages/config-manager/index.ts";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
|
|
||||||
export type RoleType = InferSelectModel<typeof Roles>;
|
type RoleType = InferSelectModel<typeof Roles>;
|
||||||
|
|
||||||
export class Role extends BaseInterface<typeof Roles> {
|
export class Role extends BaseInterface<typeof Roles> {
|
||||||
public static schema = z.object({
|
public static schema = z.object({
|
||||||
|
|
@ -31,6 +31,8 @@ export class Role extends BaseInterface<typeof Roles> {
|
||||||
icon: z.string().nullable(),
|
icon: z.string().nullable(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static $type: RoleType;
|
||||||
|
|
||||||
public async reload(): Promise<void> {
|
public async reload(): Promise<void> {
|
||||||
const reloaded = await Role.fromId(this.data.id);
|
const reloaded = await Role.fromId(this.data.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { Token as ApiToken } from "@versia/client/types";
|
import type { Token as ApiToken } from "@versia/client/types";
|
||||||
import { User, db } from "@versia/kit/db";
|
import { type Application, User, db } from "@versia/kit/db";
|
||||||
import { type Applications, Tokens } from "@versia/kit/tables";
|
import { Tokens } from "@versia/kit/tables";
|
||||||
import {
|
import {
|
||||||
type InferInsertModel,
|
type InferInsertModel,
|
||||||
type InferSelectModel,
|
type InferSelectModel,
|
||||||
|
|
@ -12,8 +12,8 @@ import {
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { BaseInterface } from "./base.ts";
|
import { BaseInterface } from "./base.ts";
|
||||||
|
|
||||||
export type TokenType = InferSelectModel<typeof Tokens> & {
|
type TokenType = InferSelectModel<typeof Tokens> & {
|
||||||
application: InferSelectModel<typeof Applications> | null;
|
application: typeof Application.$type | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Token extends BaseInterface<typeof Tokens, TokenType> {
|
export class Token extends BaseInterface<typeof Tokens, TokenType> {
|
||||||
|
|
@ -24,6 +24,8 @@ export class Token extends BaseInterface<typeof Tokens, TokenType> {
|
||||||
created_at: z.number(),
|
created_at: z.number(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static $type: TokenType;
|
||||||
|
|
||||||
public async reload(): Promise<void> {
|
public async reload(): Promise<void> {
|
||||||
const reloaded = await Token.fromId(this.data.id);
|
const reloaded = await Token.fromId(this.data.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import {
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import {
|
import {
|
||||||
type InferInsertModel,
|
type InferInsertModel,
|
||||||
|
type InferSelectModel,
|
||||||
type SQL,
|
type SQL,
|
||||||
and,
|
and,
|
||||||
countDistinct,
|
countDistinct,
|
||||||
|
|
@ -47,7 +48,6 @@ import {
|
||||||
import { htmlToText } from "html-to-text";
|
import { htmlToText } from "html-to-text";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import {
|
import {
|
||||||
type UserWithRelations,
|
|
||||||
findManyUsers,
|
findManyUsers,
|
||||||
followAcceptToVersia,
|
followAcceptToVersia,
|
||||||
followRejectToVersia,
|
followRejectToVersia,
|
||||||
|
|
@ -64,6 +64,18 @@ import type { Note } from "./note.ts";
|
||||||
import { Relationship } from "./relationship.ts";
|
import { Relationship } from "./relationship.ts";
|
||||||
import { Role } from "./role.ts";
|
import { Role } from "./role.ts";
|
||||||
|
|
||||||
|
type UserWithInstance = InferSelectModel<typeof Users> & {
|
||||||
|
instance: typeof Instance.$type | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserWithRelations = UserWithInstance & {
|
||||||
|
emojis: (typeof Emoji.$type)[];
|
||||||
|
followerCount: number;
|
||||||
|
followingCount: number;
|
||||||
|
statusCount: number;
|
||||||
|
roles: (typeof Role.$type)[];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives helpers to fetch users from database in a nice format
|
* Gives helpers to fetch users from database in a nice format
|
||||||
*/
|
*/
|
||||||
|
|
@ -125,6 +137,8 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
mute_expires_at: z.string().optional(),
|
mute_expires_at: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static $type: UserWithRelations;
|
||||||
|
|
||||||
public async reload(): Promise<void> {
|
public async reload(): Promise<void> {
|
||||||
const reloaded = await User.fromId(this.data.id);
|
const reloaded = await User.fromId(this.data.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,9 @@ import { mentionValidator } from "@/api";
|
||||||
import { sanitizeHtml, sanitizeHtmlInline } from "@/sanitization";
|
import { sanitizeHtml, sanitizeHtmlInline } from "@/sanitization";
|
||||||
import markdownItTaskLists from "@hackmd/markdown-it-task-lists";
|
import markdownItTaskLists from "@hackmd/markdown-it-task-lists";
|
||||||
import type { ContentFormat } from "@versia/federation/types";
|
import type { ContentFormat } from "@versia/federation/types";
|
||||||
import { User, db } from "@versia/kit/db";
|
import { type Note, User, db } from "@versia/kit/db";
|
||||||
import {
|
import { Instances, Users } from "@versia/kit/tables";
|
||||||
type Attachments,
|
import { and, eq, inArray, isNull, or, sql } from "drizzle-orm";
|
||||||
Instances,
|
|
||||||
type Notes,
|
|
||||||
Users,
|
|
||||||
} from "@versia/kit/tables";
|
|
||||||
import {
|
|
||||||
type InferSelectModel,
|
|
||||||
and,
|
|
||||||
eq,
|
|
||||||
inArray,
|
|
||||||
isNull,
|
|
||||||
or,
|
|
||||||
sql,
|
|
||||||
} from "drizzle-orm";
|
|
||||||
import linkifyHtml from "linkify-html";
|
import linkifyHtml from "linkify-html";
|
||||||
import {
|
import {
|
||||||
anyOf,
|
anyOf,
|
||||||
|
|
@ -31,42 +18,13 @@ import {
|
||||||
import MarkdownIt from "markdown-it";
|
import MarkdownIt from "markdown-it";
|
||||||
import markdownItContainer from "markdown-it-container";
|
import markdownItContainer from "markdown-it-container";
|
||||||
import markdownItTocDoneRight from "markdown-it-toc-done-right";
|
import markdownItTocDoneRight from "markdown-it-toc-done-right";
|
||||||
import type { ApplicationType } from "~/classes/database/application.ts";
|
|
||||||
import type { EmojiWithInstance } from "~/classes/database/emoji.ts";
|
|
||||||
import { config } from "~/packages/config-manager/index.ts";
|
import { config } from "~/packages/config-manager/index.ts";
|
||||||
import {
|
import {
|
||||||
type UserWithInstance,
|
|
||||||
type UserWithRelations,
|
|
||||||
transformOutputToUserWithRelations,
|
transformOutputToUserWithRelations,
|
||||||
userExtrasTemplate,
|
userExtrasTemplate,
|
||||||
userRelations,
|
userRelations,
|
||||||
} from "./user.ts";
|
} from "./user.ts";
|
||||||
|
|
||||||
export type Status = InferSelectModel<typeof Notes>;
|
|
||||||
|
|
||||||
export type StatusWithRelations = Status & {
|
|
||||||
author: UserWithRelations;
|
|
||||||
mentions: UserWithInstance[];
|
|
||||||
attachments: InferSelectModel<typeof Attachments>[];
|
|
||||||
reblog: StatusWithoutRecursiveRelations | null;
|
|
||||||
emojis: EmojiWithInstance[];
|
|
||||||
reply: Status | null;
|
|
||||||
quote: Status | null;
|
|
||||||
application: ApplicationType | null;
|
|
||||||
reblogCount: number;
|
|
||||||
likeCount: number;
|
|
||||||
replyCount: number;
|
|
||||||
pinned: boolean;
|
|
||||||
reblogged: boolean;
|
|
||||||
muted: boolean;
|
|
||||||
liked: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type StatusWithoutRecursiveRelations = Omit<
|
|
||||||
StatusWithRelations,
|
|
||||||
"reply" | "quote" | "reblog"
|
|
||||||
>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper against the Status object to make it easier to work with
|
* Wrapper against the Status object to make it easier to work with
|
||||||
* @param query
|
* @param query
|
||||||
|
|
@ -75,7 +33,7 @@ export type StatusWithoutRecursiveRelations = Omit<
|
||||||
export const findManyNotes = async (
|
export const findManyNotes = async (
|
||||||
query: Parameters<typeof db.query.Notes.findMany>[0],
|
query: Parameters<typeof db.query.Notes.findMany>[0],
|
||||||
userId?: string,
|
userId?: string,
|
||||||
): Promise<StatusWithRelations[]> => {
|
): Promise<(typeof Note.$type)[]> => {
|
||||||
const output = await db.query.Notes.findMany({
|
const output = await db.query.Notes.findMany({
|
||||||
...query,
|
...query,
|
||||||
with: {
|
with: {
|
||||||
|
|
|
||||||
|
|
@ -3,25 +3,17 @@ import type {
|
||||||
FollowAccept,
|
FollowAccept,
|
||||||
FollowReject,
|
FollowReject,
|
||||||
} from "@versia/federation/types";
|
} from "@versia/federation/types";
|
||||||
import { type Application, type Token, type User, db } from "@versia/kit/db";
|
import {
|
||||||
import type { Instances, Roles, Users } from "@versia/kit/tables";
|
type Application,
|
||||||
|
type Emoji,
|
||||||
|
type Instance,
|
||||||
|
type Role,
|
||||||
|
type Token,
|
||||||
|
type User,
|
||||||
|
db,
|
||||||
|
} from "@versia/kit/db";
|
||||||
|
import type { Users } from "@versia/kit/tables";
|
||||||
import { type InferSelectModel, type SQL, sql } from "drizzle-orm";
|
import { type InferSelectModel, type SQL, sql } from "drizzle-orm";
|
||||||
import type { EmojiWithInstance } from "~/classes/database/emoji.ts";
|
|
||||||
|
|
||||||
export type UserType = InferSelectModel<typeof Users>;
|
|
||||||
|
|
||||||
export type UserWithInstance = UserType & {
|
|
||||||
instance: InferSelectModel<typeof Instances> | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UserWithRelations = UserType & {
|
|
||||||
instance: InferSelectModel<typeof Instances> | null;
|
|
||||||
emojis: EmojiWithInstance[];
|
|
||||||
followerCount: number;
|
|
||||||
followingCount: number;
|
|
||||||
statusCount: number;
|
|
||||||
roles: InferSelectModel<typeof Roles>[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const userRelations = {
|
export const userRelations = {
|
||||||
instance: true,
|
instance: true,
|
||||||
|
|
@ -84,24 +76,24 @@ export interface AuthData {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const transformOutputToUserWithRelations = (
|
export const transformOutputToUserWithRelations = (
|
||||||
user: Omit<UserType, "endpoints"> & {
|
user: Omit<InferSelectModel<typeof Users>, "endpoints"> & {
|
||||||
followerCount: unknown;
|
followerCount: unknown;
|
||||||
followingCount: unknown;
|
followingCount: unknown;
|
||||||
statusCount: unknown;
|
statusCount: unknown;
|
||||||
emojis: {
|
emojis: {
|
||||||
userId: string;
|
userId: string;
|
||||||
emojiId: string;
|
emojiId: string;
|
||||||
emoji?: EmojiWithInstance;
|
emoji?: typeof Emoji.$type;
|
||||||
}[];
|
}[];
|
||||||
instance: InferSelectModel<typeof Instances> | null;
|
instance: typeof Instance.$type | null;
|
||||||
roles: {
|
roles: {
|
||||||
userId: string;
|
userId: string;
|
||||||
roleId: string;
|
roleId: string;
|
||||||
role?: InferSelectModel<typeof Roles>;
|
role?: typeof Role.$type;
|
||||||
}[];
|
}[];
|
||||||
endpoints: unknown;
|
endpoints: unknown;
|
||||||
},
|
},
|
||||||
): UserWithRelations => {
|
): typeof User.$type => {
|
||||||
return {
|
return {
|
||||||
...user,
|
...user,
|
||||||
followerCount: Number(user.followerCount),
|
followerCount: Number(user.followerCount),
|
||||||
|
|
@ -121,17 +113,17 @@ export const transformOutputToUserWithRelations = (
|
||||||
emojis: user.emojis.map(
|
emojis: user.emojis.map(
|
||||||
(emoji) =>
|
(emoji) =>
|
||||||
(emoji as unknown as Record<string, object>)
|
(emoji as unknown as Record<string, object>)
|
||||||
.emoji as EmojiWithInstance,
|
.emoji as typeof Emoji.$type,
|
||||||
),
|
),
|
||||||
roles: user.roles
|
roles: user.roles
|
||||||
.map((role) => role.role)
|
.map((role) => role.role)
|
||||||
.filter(Boolean) as InferSelectModel<typeof Roles>[],
|
.filter(Boolean) as (typeof Role.$type)[],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const findManyUsers = async (
|
export const findManyUsers = async (
|
||||||
query: Parameters<typeof db.query.Users.findMany>[0],
|
query: Parameters<typeof db.query.Users.findMany>[0],
|
||||||
): Promise<UserWithRelations[]> => {
|
): Promise<(typeof User.$type)[]> => {
|
||||||
const output = await db.query.Users.findMany({
|
const output = await db.query.Users.findMany({
|
||||||
...query,
|
...query,
|
||||||
with: {
|
with: {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,9 @@
|
||||||
import { parseUserAddress, userAddressValidator } from "@/api";
|
import { parseUserAddress, userAddressValidator } from "@/api";
|
||||||
import { Args, type Command, Flags, type Interfaces } from "@oclif/core";
|
import { Args, type Command, Flags, type Interfaces } from "@oclif/core";
|
||||||
import { Instance, User, db } from "@versia/kit/db";
|
import { type Emoji, Instance, User, db } from "@versia/kit/db";
|
||||||
import { Emojis, Instances, Users } from "@versia/kit/tables";
|
import { Emojis, Instances, Users } from "@versia/kit/tables";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import {
|
import { and, eq, getTableColumns, like } from "drizzle-orm";
|
||||||
type InferSelectModel,
|
|
||||||
and,
|
|
||||||
eq,
|
|
||||||
getTableColumns,
|
|
||||||
like,
|
|
||||||
} from "drizzle-orm";
|
|
||||||
import { BaseCommand } from "./base.ts";
|
import { BaseCommand } from "./base.ts";
|
||||||
|
|
||||||
export type FlagsType<T extends typeof Command> = Interfaces.InferredFlags<
|
export type FlagsType<T extends typeof Command> = Interfaces.InferredFlags<
|
||||||
|
|
@ -210,9 +204,12 @@ export abstract class EmojiFinderCommand<
|
||||||
}
|
}
|
||||||
|
|
||||||
public async findEmojis(): Promise<
|
public async findEmojis(): Promise<
|
||||||
(InferSelectModel<typeof Emojis> & {
|
Omit<
|
||||||
|
typeof Emoji.$type & {
|
||||||
instanceUrl: string | null;
|
instanceUrl: string | null;
|
||||||
})[]
|
},
|
||||||
|
"instance"
|
||||||
|
>[]
|
||||||
> {
|
> {
|
||||||
// Check if there are asterisks in the identifier but no pattern flag, warn the user if so
|
// Check if there are asterisks in the identifier but no pattern flag, warn the user if so
|
||||||
if (this.args.identifier.includes("*") && !this.flags.pattern) {
|
if (this.args.identifier.includes("*") && !this.flags.pattern) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { db } from "@versia/kit/db";
|
import { type Application, db } from "@versia/kit/db";
|
||||||
import type { InferSelectModel, SQL } from "@versia/kit/drizzle";
|
import type { InferSelectModel, SQL } from "@versia/kit/drizzle";
|
||||||
import type { Applications, OpenIdLoginFlows } from "@versia/kit/tables";
|
import type { OpenIdLoginFlows } from "@versia/kit/tables";
|
||||||
import {
|
import {
|
||||||
type AuthorizationResponseError,
|
type AuthorizationResponseError,
|
||||||
type AuthorizationServer,
|
type AuthorizationServer,
|
||||||
|
|
@ -18,7 +18,6 @@ import {
|
||||||
userInfoRequest,
|
userInfoRequest,
|
||||||
validateAuthResponse,
|
validateAuthResponse,
|
||||||
} from "oauth4webapi";
|
} from "oauth4webapi";
|
||||||
import type { ApplicationType } from "~/classes/database/application";
|
|
||||||
|
|
||||||
export const oauthDiscoveryRequest = (
|
export const oauthDiscoveryRequest = (
|
||||||
issuerUrl: string | URL,
|
issuerUrl: string | URL,
|
||||||
|
|
@ -37,7 +36,7 @@ const getFlow = (
|
||||||
flowId: string,
|
flowId: string,
|
||||||
): Promise<
|
): Promise<
|
||||||
| (InferSelectModel<typeof OpenIdLoginFlows> & {
|
| (InferSelectModel<typeof OpenIdLoginFlows> & {
|
||||||
application?: ApplicationType | null;
|
application?: typeof Application.$type | null;
|
||||||
})
|
})
|
||||||
| undefined
|
| undefined
|
||||||
> => {
|
> => {
|
||||||
|
|
@ -143,7 +142,7 @@ export const automaticOidcFlow = async (
|
||||||
message: string,
|
message: string,
|
||||||
flow:
|
flow:
|
||||||
| (InferSelectModel<typeof OpenIdLoginFlows> & {
|
| (InferSelectModel<typeof OpenIdLoginFlows> & {
|
||||||
application?: InferSelectModel<typeof Applications> | null;
|
application?: typeof Application.$type | null;
|
||||||
})
|
})
|
||||||
| null,
|
| null,
|
||||||
) => Response,
|
) => Response,
|
||||||
|
|
@ -152,7 +151,7 @@ export const automaticOidcFlow = async (
|
||||||
| {
|
| {
|
||||||
userInfo: UserInfoResponse;
|
userInfo: UserInfoResponse;
|
||||||
flow: InferSelectModel<typeof OpenIdLoginFlows> & {
|
flow: InferSelectModel<typeof OpenIdLoginFlows> & {
|
||||||
application?: ApplicationType | null;
|
application?: typeof Application.$type | null;
|
||||||
};
|
};
|
||||||
claims: Record<string, unknown>;
|
claims: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import { checkIfOauthIsValid } from "@/oauth";
|
import { checkIfOauthIsValid } from "@/oauth";
|
||||||
import { Application } from "@versia/kit/db";
|
import { Application } from "@versia/kit/db";
|
||||||
import type { ApplicationType } from "~/classes/database/application";
|
|
||||||
|
|
||||||
describe("checkIfOauthIsValid", () => {
|
describe("checkIfOauthIsValid", () => {
|
||||||
it("should return true when routeScopes and application.scopes are empty", () => {
|
it("should return true when routeScopes and application.scopes are empty", () => {
|
||||||
const application = new Application({ scopes: "" } as ApplicationType);
|
const application = new Application({
|
||||||
|
scopes: "",
|
||||||
|
} as typeof Application.$type);
|
||||||
const routeScopes: string[] = [];
|
const routeScopes: string[] = [];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
|
@ -14,7 +14,7 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return true when routeScopes is empty and application.scopes contains write:* or write", () => {
|
it("should return true when routeScopes is empty and application.scopes contains write:* or write", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "write:*",
|
scopes: "write:*",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes: string[] = [];
|
const routeScopes: string[] = [];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
|
@ -23,7 +23,7 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return true when routeScopes is empty and application.scopes contains read:* or read", () => {
|
it("should return true when routeScopes is empty and application.scopes contains read:* or read", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "read:*",
|
scopes: "read:*",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes: string[] = [];
|
const routeScopes: string[] = [];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
|
@ -32,7 +32,7 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return true when routeScopes contains only write: permissions and application.scopes contains write:* or write", () => {
|
it("should return true when routeScopes contains only write: permissions and application.scopes contains write:* or write", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "write:*",
|
scopes: "write:*",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes = ["write:users", "write:posts"];
|
const routeScopes = ["write:users", "write:posts"];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
|
@ -41,7 +41,7 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return true when routeScopes contains only read: permissions and application.scopes contains read:* or read", () => {
|
it("should return true when routeScopes contains only read: permissions and application.scopes contains read:* or read", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "read:*",
|
scopes: "read:*",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes = ["read:users", "read:posts"];
|
const routeScopes = ["read:users", "read:posts"];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
|
@ -50,7 +50,7 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return true when routeScopes contains both write: and read: permissions and application.scopes contains write:* or write and read:* or read", () => {
|
it("should return true when routeScopes contains both write: and read: permissions and application.scopes contains write:* or write and read:* or read", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "write:* read:*",
|
scopes: "write:* read:*",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes = ["write:users", "read:posts"];
|
const routeScopes = ["write:users", "read:posts"];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
|
@ -59,7 +59,7 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return false when routeScopes contains write: permissions but application.scopes does not contain write:* or write", () => {
|
it("should return false when routeScopes contains write: permissions but application.scopes does not contain write:* or write", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "read:*",
|
scopes: "read:*",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes = ["write:users", "write:posts"];
|
const routeScopes = ["write:users", "write:posts"];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
|
|
@ -68,14 +68,16 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return false when routeScopes contains read: permissions but application.scopes does not contain read:* or read", () => {
|
it("should return false when routeScopes contains read: permissions but application.scopes does not contain read:* or read", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "write:*",
|
scopes: "write:*",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes = ["read:users", "read:posts"];
|
const routeScopes = ["read:users", "read:posts"];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return false when routeScopes contains both write: and read: permissions but application.scopes does not contain write:* or write and read:* or read", () => {
|
it("should return false when routeScopes contains both write: and read: permissions but application.scopes does not contain write:* or write and read:* or read", () => {
|
||||||
const application = new Application({ scopes: "" } as ApplicationType);
|
const application = new Application({
|
||||||
|
scopes: "",
|
||||||
|
} as typeof Application.$type);
|
||||||
const routeScopes = ["write:users", "read:posts"];
|
const routeScopes = ["write:users", "read:posts"];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
|
|
@ -84,7 +86,7 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return true when routeScopes contains a mix of valid and invalid permissions and application.scopes contains all the required permissions", () => {
|
it("should return true when routeScopes contains a mix of valid and invalid permissions and application.scopes contains all the required permissions", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "write:* read:*",
|
scopes: "write:* read:*",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes = ["write:users", "invalid:permission", "read:posts"];
|
const routeScopes = ["write:users", "invalid:permission", "read:posts"];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
|
@ -93,7 +95,7 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return false when routeScopes contains a mix of valid and invalid permissions but application.scopes does not contain all the required permissions", () => {
|
it("should return false when routeScopes contains a mix of valid and invalid permissions but application.scopes does not contain all the required permissions", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "write:*",
|
scopes: "write:*",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes = ["write:users", "invalid:permission", "read:posts"];
|
const routeScopes = ["write:users", "invalid:permission", "read:posts"];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
|
|
@ -102,7 +104,7 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return true when routeScopes contains a mix of valid write and read permissions and application.scopes contains all the required permissions", () => {
|
it("should return true when routeScopes contains a mix of valid write and read permissions and application.scopes contains all the required permissions", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "write:* read:posts",
|
scopes: "write:* read:posts",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes = ["write:users", "read:posts"];
|
const routeScopes = ["write:users", "read:posts"];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
|
@ -111,7 +113,7 @@ describe("checkIfOauthIsValid", () => {
|
||||||
it("should return false when routeScopes contains a mix of valid write and read permissions but application.scopes does not contain all the required permissions", () => {
|
it("should return false when routeScopes contains a mix of valid write and read permissions but application.scopes does not contain all the required permissions", () => {
|
||||||
const application = new Application({
|
const application = new Application({
|
||||||
scopes: "write:*",
|
scopes: "write:*",
|
||||||
} as ApplicationType);
|
} as typeof Application.$type);
|
||||||
const routeScopes = ["write:users", "read:posts"];
|
const routeScopes = ["write:users", "read:posts"];
|
||||||
const result = checkIfOauthIsValid(application, routeScopes);
|
const result = checkIfOauthIsValid(application, routeScopes);
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,8 @@ import { randomString } from "@/math";
|
||||||
import { Note, Token, User, db } from "@versia/kit/db";
|
import { Note, Token, User, db } from "@versia/kit/db";
|
||||||
import { Notes, Users } from "@versia/kit/tables";
|
import { Notes, Users } from "@versia/kit/tables";
|
||||||
import { solveChallenge } from "altcha-lib";
|
import { solveChallenge } from "altcha-lib";
|
||||||
import { asc, inArray, like } from "drizzle-orm";
|
import { type InferSelectModel, asc, inArray, like } from "drizzle-orm";
|
||||||
import { appFactory } from "~/app";
|
import { appFactory } from "~/app";
|
||||||
import type { Status } from "~/classes/functions/status";
|
|
||||||
import { searchManager } from "~/classes/search/search-manager";
|
import { searchManager } from "~/classes/search/search-manager";
|
||||||
import { setupDatabase } from "~/drizzle/db";
|
import { setupDatabase } from "~/drizzle/db";
|
||||||
import { config } from "~/packages/config-manager";
|
import { config } from "~/packages/config-manager";
|
||||||
|
|
@ -92,7 +91,7 @@ export const getTestUsers = async (
|
||||||
export const getTestStatuses = async (
|
export const getTestStatuses = async (
|
||||||
count: number,
|
count: number,
|
||||||
user: User,
|
user: User,
|
||||||
partial?: Partial<Status>,
|
partial?: Partial<InferSelectModel<typeof Notes>>,
|
||||||
): Promise<Note["data"][]> => {
|
): Promise<Note["data"][]> => {
|
||||||
const statuses: Note[] = [];
|
const statuses: Note[] = [];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue