2024-11-04 14:58:17 +01:00
import {
type Application ,
2025-04-10 19:15:31 +02:00
db ,
2024-11-04 14:58:17 +01:00
type Emoji ,
type Instance ,
2025-01-28 19:07:55 +01:00
type Media ,
2024-11-04 14:58:17 +01:00
type Role ,
type Token ,
type User ,
} from "@versia/kit/db" ;
import type { Users } from "@versia/kit/tables" ;
2024-11-03 17:45:21 +01:00
import { type InferSelectModel , type SQL , sql } from "drizzle-orm" ;
2023-10-23 07:39:42 +02:00
2024-11-03 17:45:21 +01:00
export const userRelations = {
2024-04-11 13:39:07 +02:00
instance : true ,
emojis : {
with : {
emoji : {
with : {
instance : true ,
2025-01-28 17:43:43 +01:00
media : true ,
2024-04-11 13:39:07 +02:00
} ,
} ,
} ,
} ,
2025-01-28 19:07:55 +01:00
avatar : true ,
header : true ,
2024-06-08 06:57:29 +02:00
roles : {
with : {
role : true ,
} ,
} ,
2024-11-03 17:45:21 +01:00
} as const ;
2024-04-11 13:39:07 +02:00
export const userExtras = {
followerCount :
2024-04-17 08:36:01 +02:00
sql ` (SELECT COUNT(*) FROM "Relationships" "relationships" WHERE ("relationships"."ownerId" = "Users".id AND "relationships"."following" = true)) ` . as (
2024-04-11 13:39:07 +02:00
"follower_count" ,
) ,
followingCount :
2024-04-17 08:36:01 +02:00
sql ` (SELECT COUNT(*) FROM "Relationships" "relationshipSubjects" WHERE ("relationshipSubjects"."subjectId" = "Users".id AND "relationshipSubjects"."following" = true)) ` . as (
2024-04-11 13:39:07 +02:00
"following_count" ,
) ,
statusCount :
2024-04-17 08:36:01 +02:00
sql ` (SELECT COUNT(*) FROM "Notes" WHERE "Notes"."authorId" = "Users".id) ` . as (
2024-04-11 13:39:07 +02:00
"status_count" ,
) ,
} ;
2023-11-04 04:34:31 +01:00
2024-11-02 00:43:33 +01:00
export const userExtrasTemplate = (
name : string ,
) : {
followerCount : SQL.Aliased < unknown > ;
followingCount : SQL.Aliased < unknown > ;
statusCount : SQL.Aliased < unknown > ;
} = > ( {
2024-10-03 10:26:58 +02:00
// @ts-expect-error sql is a template tag, so it gets confused when we use it as a function
2024-04-11 13:39:07 +02:00
followerCount : sql ( [
2024-04-17 08:36:01 +02:00
` (SELECT COUNT(*) FROM "Relationships" "relationships" WHERE ("relationships"."ownerId" = " ${ name } ".id AND "relationships"."following" = true)) ` ,
2024-04-11 13:39:07 +02:00
] ) . as ( "follower_count" ) ,
2024-10-03 10:26:58 +02:00
// @ts-expect-error sql is a template tag, so it gets confused when we use it as a function
2024-04-11 13:39:07 +02:00
followingCount : sql ( [
2024-04-17 08:36:01 +02:00
` (SELECT COUNT(*) FROM "Relationships" "relationshipSubjects" WHERE ("relationshipSubjects"."subjectId" = " ${ name } ".id AND "relationshipSubjects"."following" = true)) ` ,
2024-04-11 13:39:07 +02:00
] ) . as ( "following_count" ) ,
2024-10-03 10:26:58 +02:00
// @ts-expect-error sql is a template tag, so it gets confused when we use it as a function
2024-04-11 13:39:07 +02:00
statusCount : sql ( [
2024-04-17 08:36:01 +02:00
` (SELECT COUNT(*) FROM "Notes" WHERE "Notes"."authorId" = " ${ name } ".id) ` ,
2024-04-11 13:39:07 +02:00
] ) . as ( "status_count" ) ,
2023-11-27 01:56:16 +01:00
} ) ;
2024-04-11 13:39:07 +02:00
export interface AuthData {
2024-04-25 05:40:27 +02:00
user : User | null ;
2024-11-03 17:45:21 +01:00
token : Token | null ;
application : Application | null ;
2024-04-11 13:39:07 +02:00
}
2023-10-08 22:20:42 +02:00
2024-04-11 13:39:07 +02:00
export const transformOutputToUserWithRelations = (
2024-11-04 14:58:17 +01:00
user : Omit < InferSelectModel < typeof Users > , "endpoints" > & {
2024-04-11 13:39:07 +02:00
followerCount : unknown ;
followingCount : unknown ;
statusCount : unknown ;
2025-01-28 19:07:55 +01:00
avatar : typeof Media . $type | null ;
header : typeof Media . $type | null ;
2024-04-11 13:39:07 +02:00
emojis : {
2024-04-14 03:21:38 +02:00
userId : string ;
emojiId : string ;
2024-11-04 14:58:17 +01:00
emoji? : typeof Emoji . $type ;
2024-04-11 13:39:07 +02:00
} [ ] ;
2024-11-04 14:58:17 +01:00
instance : typeof Instance . $type | null ;
2024-06-08 06:57:29 +02:00
roles : {
userId : string ;
roleId : string ;
2024-11-04 14:58:17 +01:00
role? : typeof Role . $type ;
2024-06-08 06:57:29 +02:00
} [ ] ;
2024-04-11 13:39:07 +02:00
endpoints : unknown ;
} ,
2024-11-04 14:58:17 +01:00
) : typeof User . $type = > {
2024-04-11 13:39:07 +02:00
return {
. . . user ,
followerCount : Number ( user . followerCount ) ,
followingCount : Number ( user . followingCount ) ,
statusCount : Number ( user . statusCount ) ,
endpoints :
user . endpoints ? ?
( { } as Partial < {
dislikes : string ;
featured : string ;
likes : string ;
followers : string ;
following : string ;
inbox : string ;
outbox : string ;
} > ) ,
emojis : user.emojis.map (
( emoji ) = >
( emoji as unknown as Record < string , object > )
2024-11-04 14:58:17 +01:00
. emoji as typeof Emoji . $type ,
2024-04-11 13:39:07 +02:00
) ,
2024-06-08 06:57:29 +02:00
roles : user.roles
. map ( ( role ) = > role . role )
2024-11-04 14:58:17 +01:00
. filter ( Boolean ) as ( typeof Role . $type ) [ ] ,
2024-04-11 13:39:07 +02:00
} ;
} ;
export const findManyUsers = async (
2024-04-17 08:36:01 +02:00
query : Parameters < typeof db.query.Users.findMany > [ 0 ] ,
2024-11-04 14:58:17 +01:00
) : Promise < ( typeof User . $type ) [ ] > = > {
2024-04-17 08:36:01 +02:00
const output = await db . query . Users . findMany ( {
2024-04-11 13:39:07 +02:00
. . . query ,
with : {
. . . userRelations ,
. . . query ? . with ,
} ,
extras : {
. . . userExtras ,
. . . query ? . extras ,
} ,
} ) ;
return output . map ( ( user ) = > transformOutputToUserWithRelations ( user ) ) ;
} ;