From 106e34848a1bd138ca479367166c50b2937edc2e Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Fri, 28 Jun 2024 20:36:15 -1000 Subject: [PATCH] refactor(api): :label: Replace API types with those from @lysand-org/client --- CHANGELOG.md | 1 - bun.lockb | Bin 248924 -> 249692 bytes classes/functions/application.ts | 4 +- classes/functions/notification.ts | 4 +- classes/functions/relationship.ts | 4 +- drizzle/schema.ts | 4 +- package.json | 1 + packages/database-interface/attachment.ts | 12 +++-- packages/database-interface/emoji.ts | 4 +- packages/database-interface/note.ts | 25 +++++---- packages/database-interface/role.ts | 3 +- packages/database-interface/user.ts | 10 ++-- server/api/api/v1/accounts/:id/block.test.ts | 6 +-- server/api/api/v1/accounts/:id/follow.test.ts | 6 +-- .../api/api/v1/accounts/:id/followers.test.ts | 6 +-- .../api/api/v1/accounts/:id/following.test.ts | 6 +-- server/api/api/v1/accounts/:id/index.test.ts | 6 +-- server/api/api/v1/accounts/:id/mute.test.ts | 6 +-- .../api/api/v1/accounts/:id/statuses.test.ts | 12 ++--- server/api/api/v1/accounts/:id/unmute.test.ts | 6 +-- .../api/api/v1/accounts/lookup/index.test.ts | 4 +- .../api/api/v1/accounts/search/index.test.ts | 4 +- server/api/api/v1/instance/index.ts | 3 +- server/api/api/v1/markers/index.ts | 6 +-- .../api/v1/notifications/:id/dismiss.test.ts | 4 +- .../api/v1/notifications/:id/index.test.ts | 6 +-- .../api/v1/notifications/clear/index.test.ts | 4 +- .../destroy_multiple/index.test.ts | 4 +- server/api/api/v1/notifications/index.test.ts | 6 +-- .../api/api/v1/statuses/:id/favourite.test.ts | 6 +-- .../api/v1/statuses/:id/favourited_by.test.ts | 4 +- .../api/v1/statuses/:id/reblogged_by.test.ts | 4 +- server/api/api/v1/statuses/:id/source.ts | 4 +- .../api/v1/statuses/:id/unfavourite.test.ts | 6 +-- server/api/api/v1/statuses/index.test.ts | 29 +++++----- server/api/api/v1/timelines/home.test.ts | 12 ++--- server/api/api/v1/timelines/public.test.ts | 16 +++--- server/api/api/v2/instance/index.ts | 7 +-- tests/api/accounts.test.ts | 32 +++++------ tests/api/statuses.test.ts | 32 +++++------ tests/oauth.test.ts | 10 ++-- types/entity.ts | 0 types/mastodon/account.ts | 36 ------------- types/mastodon/activity.ts | 6 --- types/mastodon/announcement.ts | 39 -------------- types/mastodon/application.ts | 5 -- types/mastodon/async_attachment.ts | 13 ----- types/mastodon/attachment.ts | 47 ---------------- types/mastodon/card.ts | 16 ------ types/mastodon/context.ts | 6 --- types/mastodon/conversation.ts | 9 ---- types/mastodon/emoji.ts | 7 --- types/mastodon/featured_tag.ts | 6 --- types/mastodon/field.ts | 6 --- types/mastodon/filter.ts | 10 ---- types/mastodon/follow_request.ts | 25 --------- types/mastodon/history.ts | 5 -- types/mastodon/identity_proof.ts | 7 --- types/mastodon/instance.ts | 38 ------------- types/mastodon/list.ts | 7 --- types/mastodon/lysand.ts | 11 ---- types/mastodon/marker.ts | 13 ----- types/mastodon/mention.ts | 6 --- types/mastodon/notification.ts | 15 ------ types/mastodon/poll.ts | 14 ----- types/mastodon/preferences.ts | 9 ---- types/mastodon/push_subscription.ts | 14 ----- types/mastodon/reaction.ts | 11 ---- types/mastodon/relationship.ts | 16 ------ types/mastodon/report.ts | 16 ------ types/mastodon/results.ts | 9 ---- types/mastodon/role.ts | 3 -- types/mastodon/scheduled_status.ts | 9 ---- types/mastodon/source.ts | 9 ---- types/mastodon/stats.ts | 5 -- types/mastodon/status.ts | 50 ------------------ types/mastodon/status_params.ts | 12 ----- types/mastodon/status_source.ts | 5 -- types/mastodon/tag.ts | 8 --- types/mastodon/token.ts | 6 --- types/mastodon/urls.ts | 3 -- 81 files changed, 171 insertions(+), 690 deletions(-) delete mode 100644 types/entity.ts delete mode 100644 types/mastodon/account.ts delete mode 100644 types/mastodon/activity.ts delete mode 100644 types/mastodon/announcement.ts delete mode 100644 types/mastodon/application.ts delete mode 100644 types/mastodon/async_attachment.ts delete mode 100644 types/mastodon/attachment.ts delete mode 100644 types/mastodon/card.ts delete mode 100644 types/mastodon/context.ts delete mode 100644 types/mastodon/conversation.ts delete mode 100644 types/mastodon/emoji.ts delete mode 100644 types/mastodon/featured_tag.ts delete mode 100644 types/mastodon/field.ts delete mode 100644 types/mastodon/filter.ts delete mode 100644 types/mastodon/follow_request.ts delete mode 100644 types/mastodon/history.ts delete mode 100644 types/mastodon/identity_proof.ts delete mode 100644 types/mastodon/instance.ts delete mode 100644 types/mastodon/list.ts delete mode 100644 types/mastodon/lysand.ts delete mode 100644 types/mastodon/marker.ts delete mode 100644 types/mastodon/mention.ts delete mode 100644 types/mastodon/notification.ts delete mode 100644 types/mastodon/poll.ts delete mode 100644 types/mastodon/preferences.ts delete mode 100644 types/mastodon/push_subscription.ts delete mode 100644 types/mastodon/reaction.ts delete mode 100644 types/mastodon/relationship.ts delete mode 100644 types/mastodon/report.ts delete mode 100644 types/mastodon/results.ts delete mode 100644 types/mastodon/role.ts delete mode 100644 types/mastodon/scheduled_status.ts delete mode 100644 types/mastodon/source.ts delete mode 100644 types/mastodon/stats.ts delete mode 100644 types/mastodon/status.ts delete mode 100644 types/mastodon/status_params.ts delete mode 100644 types/mastodon/status_source.ts delete mode 100644 types/mastodon/tag.ts delete mode 100644 types/mastodon/token.ts delete mode 100644 types/mastodon/urls.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 82d3710e..59585295 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,6 @@ Lysand Server `0.7.0` is backwards compatible with `0.6.0`. However, some new fe ## Features -- Switched over to [**`@lysand-org/federation`**](https://github.com/lysand-org/api), our new federation library, for the federation logic. - Upgrade Bun to `1.1.17`. This brings performance upgrades and better stability. - Note deletions are now federated. - Note edits are now federated. diff --git a/bun.lockb b/bun.lockb index 7ab43b582b900cb663096895c83673ce306f03c4..0959b7535a024455710bdeedbe5fb199a0735fa0 100755 GIT binary patch delta 40879 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 delta 40608 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 @@ -27,7 +27,7 @@ export const getFromToken = async ( * Converts this application to an API application. * @returns The API application representation of this application. */ -export const applicationToApi = (app: Application): apiApplication => { +export const applicationToApi = (app: Application): APIApplication => { return { name: app.name, website: app.website, diff --git a/classes/functions/notification.ts b/classes/functions/notification.ts index adf5699c..9b880de8 100644 --- a/classes/functions/notification.ts +++ b/classes/functions/notification.ts @@ -1,9 +1,9 @@ +import type { Notification as ApiNotification } from "@lysand-org/client/types"; import type { InferSelectModel } from "drizzle-orm"; import { db } from "~/drizzle/db"; import type { Notifications } from "~/drizzle/schema"; import { Note } from "~/packages/database-interface/note"; import { User } from "~/packages/database-interface/user"; -import type { Notification as apiNotification } from "~/types/mastodon/notification"; import type { StatusWithRelations } from "./status"; import { type UserWithRelations, @@ -50,7 +50,7 @@ export const findManyNotifications = async ( export const notificationToApi = async ( notification: NotificationWithRelations, -): Promise => { +): Promise => { const account = new User(notification.account); return { account: account.toApi(), diff --git a/classes/functions/relationship.ts b/classes/functions/relationship.ts index 83061526..90a18531 100644 --- a/classes/functions/relationship.ts +++ b/classes/functions/relationship.ts @@ -1,8 +1,8 @@ +import type { Relationship as ApiRelationship } from "@lysand-org/client/types"; import type { InferSelectModel } from "drizzle-orm"; import { db } from "~/drizzle/db"; import { Relationships } from "~/drizzle/schema"; import type { User } from "~/packages/database-interface/user"; -import type { Relationship as apiRelationship } from "~/types/mastodon/relationship"; export type Relationship = InferSelectModel & { requestedBy: boolean; @@ -76,7 +76,7 @@ export const checkForBidirectionalRelationships = async ( * Converts the relationship to an API-friendly format. * @returns The API-friendly relationship. */ -export const relationshipToApi = (rel: Relationship): apiRelationship => { +export const relationshipToApi = (rel: Relationship): ApiRelationship => { return { blocked_by: rel.blockedBy, blocking: rel.blocking, diff --git a/drizzle/schema.ts b/drizzle/schema.ts index 127a467f..14c910e5 100644 --- a/drizzle/schema.ts +++ b/drizzle/schema.ts @@ -1,3 +1,4 @@ +import type { Source as ApiSource } from "@lysand-org/client/types"; import type { ContentFormat } from "@lysand-org/federation/types"; import type { Challenge } from "altcha-lib/types"; import { relations, sql } from "drizzle-orm"; @@ -14,7 +15,6 @@ import { uniqueIndex, uuid, } from "drizzle-orm/pg-core"; -import type { Source as apiSource } from "~/types/mastodon/source"; export const Challenges = pgTable("Challenges", { id: uuid("id").default(sql`uuid_generate_v7()`).primaryKey().notNull(), @@ -388,7 +388,7 @@ export const Users = pgTable( inbox: string; outbox: string; }> | null>(), - source: jsonb("source").notNull().$type(), + source: jsonb("source").notNull().$type(), avatar: text("avatar").notNull(), header: text("header").notNull(), createdAt: timestamp("created_at", { precision: 3, mode: "string" }) diff --git a/package.json b/package.json index edb111cc..1562e372 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "@inquirer/input": "^2.1.11", "@json2csv/plainjs": "^7.0.6", "@logtape/logtape": "npm:@jsr/logtape__logtape", + "@lysand-org/client": "^0.2.3", "@lysand-org/federation": "^2.0.0", "@oclif/core": "^4.0.7", "@tufjs/canonical-json": "^2.0.0", diff --git a/packages/database-interface/attachment.ts b/packages/database-interface/attachment.ts index 00601696..8ce327f2 100644 --- a/packages/database-interface/attachment.ts +++ b/packages/database-interface/attachment.ts @@ -1,4 +1,8 @@ import { proxyUrl } from "@/response"; +import type { + AsyncAttachment as ApiAsyncAttachment, + Attachment as ApiAttachment, +} from "@lysand-org/client/types"; import type { ContentFormat } from "@lysand-org/federation/types"; import { config } from "config-manager"; import { MediaBackendType } from "config-manager/config.type"; @@ -12,8 +16,6 @@ import { } from "drizzle-orm"; import { db } from "~/drizzle/db"; import { Attachments } from "~/drizzle/schema"; -import type { AsyncAttachment as APIAsyncAttachment } from "~/types/mastodon/async_attachment"; -import type { Attachment as APIAttachment } from "~/types/mastodon/attachment"; import { BaseInterface } from "./base"; export type AttachmentType = InferSelectModel; @@ -136,7 +138,7 @@ export class Attachment extends BaseInterface { return ""; } - public getMastodonType(): APIAttachment["type"] { + public getMastodonType(): ApiAttachment["type"] { if (this.data.mimeType.startsWith("image/")) { return "image"; } @@ -150,7 +152,7 @@ export class Attachment extends BaseInterface { return "unknown"; } - public toApiMeta(): APIAttachment["meta"] { + public toApiMeta(): ApiAttachment["meta"] { return { width: this.data.width || undefined, height: this.data.height || undefined, @@ -181,7 +183,7 @@ export class Attachment extends BaseInterface { }; } - public toApi(): APIAttachment | APIAsyncAttachment { + public toApi(): ApiAttachment | ApiAsyncAttachment { return { id: this.data.id, type: this.getMastodonType(), diff --git a/packages/database-interface/emoji.ts b/packages/database-interface/emoji.ts index b3e0a33c..ed8b374e 100644 --- a/packages/database-interface/emoji.ts +++ b/packages/database-interface/emoji.ts @@ -1,4 +1,5 @@ import { proxyUrl } from "@/response"; +import type { Emoji as ApiEmoji } from "@lysand-org/client/types"; import type { CustomEmojiExtension } from "@lysand-org/federation/types"; import { type InferInsertModel, @@ -12,7 +13,6 @@ import type { EmojiWithInstance } from "~/classes/functions/emoji"; import { addInstanceIfNotExists } from "~/classes/functions/instance"; import { db } from "~/drizzle/db"; import { Emojis, Instances } from "~/drizzle/schema"; -import type { Emoji as APIEmoji } from "~/types/mastodon/emoji"; import { BaseInterface } from "./base"; export class Emoji extends BaseInterface { @@ -152,7 +152,7 @@ export class Emoji extends BaseInterface { return this.data.id; } - public toApi(): APIEmoji { + public toApi(): ApiEmoji { return { // @ts-expect-error ID is not in regular Mastodon API id: this.id, diff --git a/packages/database-interface/note.ts b/packages/database-interface/note.ts index 39357551..53162de5 100644 --- a/packages/database-interface/note.ts +++ b/packages/database-interface/note.ts @@ -2,6 +2,10 @@ import { idValidator } from "@/api"; import { proxyUrl } from "@/response"; import { sanitizedHtmlStrip } from "@/sanitization"; import { getLogger } from "@logtape/logtape"; +import type { + Attachment as ApiAttachment, + Status as ApiStatus, +} from "@lysand-org/client/types"; import { EntityValidator } from "@lysand-org/federation"; import type { ContentFormat, @@ -42,8 +46,6 @@ import { Users, } from "~/drizzle/schema"; import { config } from "~/packages/config-manager"; -import type { Attachment as apiAttachment } from "~/types/mastodon/attachment"; -import type { Status as APIStatus } from "~/types/mastodon/status"; import { Attachment } from "./attachment"; import { BaseInterface } from "./base"; import { Emoji } from "./emoji"; @@ -306,7 +308,7 @@ export class Note extends BaseInterface { static async fromData(data: { author: User; content: ContentFormat; - visibility: APIStatus["visibility"]; + visibility: ApiStatus["visibility"]; isSensitive: boolean; spoilerText: string; emojis?: Emoji[]; @@ -396,7 +398,7 @@ export class Note extends BaseInterface { async updateFromData(data: { author?: User; content?: ContentFormat; - visibility?: APIStatus["visibility"]; + visibility?: ApiStatus["visibility"]; isSensitive?: boolean; spoilerText?: string; emojis?: Emoji[]; @@ -659,7 +661,7 @@ export class Note extends BaseInterface { content: "", }, }, - visibility: note.visibility as APIStatus["visibility"], + visibility: note.visibility as ApiStatus["visibility"], isSensitive: note.is_sensitive ?? false, spoilerText: note.subject ?? "", emojis, @@ -755,7 +757,7 @@ export class Note extends BaseInterface { * @param userFetching - The user fetching the note (used to check if the note is favourite and such) * @returns The note in the Mastodon API format */ - async toApi(userFetching?: User | null): Promise { + async toApi(userFetching?: User | null): Promise { const data = this.data; // Convert mentions of local users from @username@host to @username @@ -804,7 +806,7 @@ export class Note extends BaseInterface { favourited: data.liked, favourites_count: data.likeCount, media_attachments: (data.attachments ?? []).map( - (a) => new Attachment(a).toApi() as apiAttachment, + (a) => new Attachment(a).toApi() as ApiAttachment, ), mentions: data.mentions.map((mention) => ({ id: mention.id, @@ -833,16 +835,19 @@ export class Note extends BaseInterface { spoiler_text: data.spoilerText, tags: [], uri: data.uri || this.getUri(), - visibility: data.visibility as APIStatus["visibility"], + visibility: data.visibility as ApiStatus["visibility"], url: data.uri || this.getMastoUri(), bookmarked: false, - // @ts-expect-error Glitch-SOC extension quote: data.quotingId ? (await Note.fromId(data.quotingId, userFetching?.id).then( (n) => n?.toApi(userFetching), )) ?? null : null, - quote_id: data.quotingId || undefined, + edited_at: data.updatedAt + ? new Date(data.updatedAt).toISOString() + : null, + emoji_reactions: [], + plain_content: data.contentSource, }; } diff --git a/packages/database-interface/role.ts b/packages/database-interface/role.ts index cc3a1adc..675ad9b4 100644 --- a/packages/database-interface/role.ts +++ b/packages/database-interface/role.ts @@ -1,4 +1,5 @@ import { proxyUrl } from "@/response"; +import type { RolePermission } from "@lysand-org/client/types"; import { config } from "config-manager"; import { type InferInsertModel, @@ -181,7 +182,7 @@ export class Role extends BaseInterface { return { id: this.id, name: this.data.name, - permissions: this.data.permissions, + permissions: this.data.permissions as unknown as RolePermission[], priority: this.data.priority, description: this.data.description, visible: this.data.visible, diff --git a/packages/database-interface/user.ts b/packages/database-interface/user.ts index 84806066..9469b106 100644 --- a/packages/database-interface/user.ts +++ b/packages/database-interface/user.ts @@ -3,6 +3,10 @@ import { getBestContentType, urlToContentFormat } from "@/content_types"; import { randomString } from "@/math"; import { addUserToMeilisearch } from "@/meilisearch"; import { proxyUrl } from "@/response"; +import type { + Account as ApiAccount, + Mention as ApiMention, +} from "@lysand-org/client/types"; import { EntityValidator } from "@lysand-org/federation"; import type { Entity, User as LysandUser } from "@lysand-org/federation/types"; import { @@ -38,8 +42,6 @@ import { Users, } from "~/drizzle/schema"; import { type Config, config } from "~/packages/config-manager"; -import type { Account as apiAccount } from "~/types/mastodon/account"; -import type { Mention as apiMention } from "~/types/mastodon/mention"; import { BaseInterface } from "./base"; import { Emoji } from "./emoji"; import type { Note } from "./note"; @@ -558,7 +560,7 @@ export class User extends BaseInterface { } } - toApi(isOwnAccount = false): apiAccount { + toApi(isOwnAccount = false): ApiAccount { const user = this.data; return { id: user.id, @@ -698,7 +700,7 @@ export class User extends BaseInterface { }; } - toMention(): apiMention { + toMention(): ApiMention { return { url: this.getUri(), username: this.data.username, diff --git a/server/api/api/v1/accounts/:id/block.test.ts b/server/api/api/v1/accounts/:id/block.test.ts index ef4dc669..7b1d6a38 100644 --- a/server/api/api/v1/accounts/:id/block.test.ts +++ b/server/api/api/v1/accounts/:id/block.test.ts @@ -1,7 +1,7 @@ import { afterAll, describe, expect, test } from "bun:test"; +import type { Relationship as ApiRelationship } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Relationship as apiRelationship } from "~/types/mastodon/relationship"; import { meta } from "./block"; const { users, tokens, deleteUsers } = await getTestUsers(2); @@ -65,7 +65,7 @@ describe(meta.route, () => { ); expect(response.status).toBe(200); - const relationship = (await response.json()) as apiRelationship; + const relationship = (await response.json()) as ApiRelationship; expect(relationship.blocking).toBe(true); }); @@ -86,7 +86,7 @@ describe(meta.route, () => { ); expect(response.status).toBe(200); - const relationship = (await response.json()) as apiRelationship; + const relationship = (await response.json()) as ApiRelationship; expect(relationship.blocking).toBe(true); }); }); diff --git a/server/api/api/v1/accounts/:id/follow.test.ts b/server/api/api/v1/accounts/:id/follow.test.ts index e8cdaa53..a7b3599f 100644 --- a/server/api/api/v1/accounts/:id/follow.test.ts +++ b/server/api/api/v1/accounts/:id/follow.test.ts @@ -1,7 +1,7 @@ import { afterAll, describe, expect, test } from "bun:test"; +import type { Relationship as ApiRelationship } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Relationship as apiRelationship } from "~/types/mastodon/relationship"; import { meta } from "./follow"; const { users, tokens, deleteUsers } = await getTestUsers(2); @@ -73,7 +73,7 @@ describe(meta.route, () => { ); expect(response.status).toBe(200); - const relationship = (await response.json()) as apiRelationship; + const relationship = (await response.json()) as ApiRelationship; expect(relationship.following).toBe(true); }); @@ -96,7 +96,7 @@ describe(meta.route, () => { ); expect(response.status).toBe(200); - const relationship = (await response.json()) as apiRelationship; + const relationship = (await response.json()) as ApiRelationship; expect(relationship.following).toBe(true); }); }); diff --git a/server/api/api/v1/accounts/:id/followers.test.ts b/server/api/api/v1/accounts/:id/followers.test.ts index 339c1b8a..cdcce2b1 100644 --- a/server/api/api/v1/accounts/:id/followers.test.ts +++ b/server/api/api/v1/accounts/:id/followers.test.ts @@ -1,7 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Account as ApiAccount } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Account as apiAccount } from "~/types/mastodon/account"; import { meta } from "./followers"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -51,7 +51,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const data = (await response.json()) as apiAccount[]; + const data = (await response.json()) as ApiAccount[]; expect(data).toBeInstanceOf(Array); expect(data.length).toBe(1); @@ -93,7 +93,7 @@ describe(meta.route, () => { expect(response2.status).toBe(200); - const data = (await response2.json()) as apiAccount[]; + const data = (await response2.json()) as ApiAccount[]; expect(data).toBeInstanceOf(Array); expect(data.length).toBe(0); diff --git a/server/api/api/v1/accounts/:id/following.test.ts b/server/api/api/v1/accounts/:id/following.test.ts index 43b07ea0..eb3dfcb9 100644 --- a/server/api/api/v1/accounts/:id/following.test.ts +++ b/server/api/api/v1/accounts/:id/following.test.ts @@ -1,7 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Account as ApiAccount } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Account as apiAccount } from "~/types/mastodon/account"; import { meta } from "./following"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -51,7 +51,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const data = (await response.json()) as apiAccount[]; + const data = (await response.json()) as ApiAccount[]; expect(data).toBeInstanceOf(Array); expect(data.length).toBe(1); @@ -93,7 +93,7 @@ describe(meta.route, () => { expect(response2.status).toBe(200); - const data = (await response2.json()) as apiAccount[]; + const data = (await response2.json()) as ApiAccount[]; expect(data).toBeInstanceOf(Array); expect(data.length).toBe(0); diff --git a/server/api/api/v1/accounts/:id/index.test.ts b/server/api/api/v1/accounts/:id/index.test.ts index c20a9ef7..75466da1 100644 --- a/server/api/api/v1/accounts/:id/index.test.ts +++ b/server/api/api/v1/accounts/:id/index.test.ts @@ -1,7 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Account as ApiAccount } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Account as apiAccount } from "~/types/mastodon/account"; import { meta } from "./index"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -58,7 +58,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const data = (await response.json()) as apiAccount; + const data = (await response.json()) as ApiAccount; expect(data).toMatchObject({ id: users[0].id, username: users[0].data.username, @@ -93,6 +93,6 @@ describe(meta.route, () => { icon: null, }), ]), - } satisfies apiAccount); + } satisfies ApiAccount); }); }); diff --git a/server/api/api/v1/accounts/:id/mute.test.ts b/server/api/api/v1/accounts/:id/mute.test.ts index 04cb4b9b..60dd4c4c 100644 --- a/server/api/api/v1/accounts/:id/mute.test.ts +++ b/server/api/api/v1/accounts/:id/mute.test.ts @@ -1,7 +1,7 @@ import { afterAll, describe, expect, test } from "bun:test"; +import type { Relationship as ApiRelationship } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Relationship as apiRelationship } from "~/types/mastodon/relationship"; import { meta } from "./mute"; const { users, tokens, deleteUsers } = await getTestUsers(2); @@ -73,7 +73,7 @@ describe(meta.route, () => { ); expect(response.status).toBe(200); - const relationship = (await response.json()) as apiRelationship; + const relationship = (await response.json()) as ApiRelationship; expect(relationship.muting).toBe(true); }); @@ -96,7 +96,7 @@ describe(meta.route, () => { ); expect(response.status).toBe(200); - const relationship = (await response.json()) as apiRelationship; + const relationship = (await response.json()) as ApiRelationship; expect(relationship.muting).toBe(true); }); }); diff --git a/server/api/api/v1/accounts/:id/statuses.test.ts b/server/api/api/v1/accounts/:id/statuses.test.ts index 3ff8345f..9ef31fe8 100644 --- a/server/api/api/v1/accounts/:id/statuses.test.ts +++ b/server/api/api/v1/accounts/:id/statuses.test.ts @@ -1,7 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Status as ApiStatus } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Status as apiStatus } from "~/types/mastodon/status"; import { meta } from "./statuses"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -50,7 +50,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const data = (await response.json()) as apiStatus[]; + const data = (await response.json()) as ApiStatus[]; expect(data.length).toBe(20); // Should have reblogs @@ -77,7 +77,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const data = (await response.json()) as apiStatus[]; + const data = (await response.json()) as ApiStatus[]; expect(data.length).toBe(20); // Should not have reblogs @@ -121,7 +121,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const data = (await response.json()) as apiStatus[]; + const data = (await response.json()) as ApiStatus[]; expect(data.length).toBe(20); // Should not have replies @@ -145,7 +145,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const data = (await response.json()) as apiStatus[]; + const data = (await response.json()) as ApiStatus[]; expect(data.length).toBe(0); @@ -183,7 +183,7 @@ describe(meta.route, () => { expect(response2.status).toBe(200); - const data2 = (await response2.json()) as apiStatus[]; + const data2 = (await response2.json()) as ApiStatus[]; expect(data2.length).toBe(1); }); diff --git a/server/api/api/v1/accounts/:id/unmute.test.ts b/server/api/api/v1/accounts/:id/unmute.test.ts index 6663b968..2a0e67af 100644 --- a/server/api/api/v1/accounts/:id/unmute.test.ts +++ b/server/api/api/v1/accounts/:id/unmute.test.ts @@ -1,7 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Relationship as ApiRelationship } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Relationship as apiRelationship } from "~/types/mastodon/relationship"; import { meta } from "./unmute"; const { users, tokens, deleteUsers } = await getTestUsers(2); @@ -82,7 +82,7 @@ describe(meta.route, () => { ); expect(response.status).toBe(200); - const relationship = (await response.json()) as apiRelationship; + const relationship = (await response.json()) as ApiRelationship; expect(relationship.muting).toBe(false); }); @@ -103,7 +103,7 @@ describe(meta.route, () => { ); expect(response.status).toBe(200); - const relationship = (await response.json()) as apiRelationship; + const relationship = (await response.json()) as ApiRelationship; expect(relationship.muting).toBe(false); }); }); diff --git a/server/api/api/v1/accounts/lookup/index.test.ts b/server/api/api/v1/accounts/lookup/index.test.ts index 51255a0e..ab9421b4 100644 --- a/server/api/api/v1/accounts/lookup/index.test.ts +++ b/server/api/api/v1/accounts/lookup/index.test.ts @@ -1,7 +1,7 @@ import { afterAll, describe, expect, test } from "bun:test"; +import type { Account as ApiAccount } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Account as apiAccount } from "~/types/mastodon/account"; import { meta } from "./index"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -29,7 +29,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const data = (await response.json()) as apiAccount[]; + const data = (await response.json()) as ApiAccount[]; expect(data).toEqual( expect.objectContaining({ id: users[0].id, diff --git a/server/api/api/v1/accounts/search/index.test.ts b/server/api/api/v1/accounts/search/index.test.ts index 50f0534a..89e69c27 100644 --- a/server/api/api/v1/accounts/search/index.test.ts +++ b/server/api/api/v1/accounts/search/index.test.ts @@ -1,7 +1,7 @@ import { afterAll, describe, expect, test } from "bun:test"; +import type { Account as ApiAccount } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Account as apiAccount } from "~/types/mastodon/account"; import { meta } from "./index"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -29,7 +29,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const data = (await response.json()) as apiAccount[]; + const data = (await response.json()) as ApiAccount[]; expect(data).toEqual( expect.arrayContaining([ expect.objectContaining({ diff --git a/server/api/api/v1/instance/index.ts b/server/api/api/v1/instance/index.ts index a9cea161..a03e3dbf 100644 --- a/server/api/api/v1/instance/index.ts +++ b/server/api/api/v1/instance/index.ts @@ -8,7 +8,6 @@ import manifest from "~/package.json"; import { config } from "~/packages/config-manager"; import { Note } from "~/packages/database-interface/note"; import { User } from "~/packages/database-interface/user"; -import type { Instance as apiInstance } from "~/types/mastodon/instance"; export const meta = applyConfig({ allowedMethods: ["GET"], @@ -97,7 +96,7 @@ export default (app: Hono) => })), }, contact_account: contactAccount?.toApi() || undefined, - } satisfies apiInstance & { + } satisfies Record & { banner: string | null; lysand_version: string; sso: { diff --git a/server/api/api/v1/markers/index.ts b/server/api/api/v1/markers/index.ts index 57aa49e8..a8562963 100644 --- a/server/api/api/v1/markers/index.ts +++ b/server/api/api/v1/markers/index.ts @@ -1,12 +1,12 @@ import { applyConfig, auth, handleZodError, idValidator } from "@/api"; import { errorResponse, jsonResponse } from "@/response"; import { zValidator } from "@hono/zod-validator"; +import type { Marker as ApiMarker } from "@lysand-org/client/types"; import { and, count, eq } from "drizzle-orm"; import type { Hono } from "hono"; import { z } from "zod"; import { db } from "~/drizzle/db"; import { Markers, RolePermissions } from "~/drizzle/schema"; -import type { Marker as apiMarker } from "~/types/mastodon/marker"; export const meta = applyConfig({ allowedMethods: ["GET", "POST"], @@ -58,7 +58,7 @@ export default (app: Hono) => return jsonResponse({}); } - const markers: apiMarker = { + const markers: ApiMarker = { home: undefined, notifications: undefined, }; @@ -136,7 +136,7 @@ export default (app: Hono) => "notifications[last_read_id]": notificationsId, } = context.req.valid("query"); - const markers: apiMarker = { + const markers: ApiMarker = { home: undefined, notifications: undefined, }; diff --git a/server/api/api/v1/notifications/:id/dismiss.test.ts b/server/api/api/v1/notifications/:id/dismiss.test.ts index c502146b..53ea6de5 100644 --- a/server/api/api/v1/notifications/:id/dismiss.test.ts +++ b/server/api/api/v1/notifications/:id/dismiss.test.ts @@ -1,11 +1,11 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Notification as ApiNotification } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Notification as apiNotification } from "~/types/mastodon/notification"; import { meta } from "./dismiss"; const { users, tokens, deleteUsers } = await getTestUsers(2); -let notifications: apiNotification[] = []; +let notifications: ApiNotification[] = []; // Create some test notifications: follow, favourite, reblog, mention beforeAll(async () => { diff --git a/server/api/api/v1/notifications/:id/index.test.ts b/server/api/api/v1/notifications/:id/index.test.ts index 6ac40cfa..36846dda 100644 --- a/server/api/api/v1/notifications/:id/index.test.ts +++ b/server/api/api/v1/notifications/:id/index.test.ts @@ -1,11 +1,11 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Notification as ApiNotification } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Notification as apiNotification } from "~/types/mastodon/notification"; import { meta } from "./index"; const { users, tokens, deleteUsers } = await getTestUsers(2); -let notifications: apiNotification[] = []; +let notifications: ApiNotification[] = []; // Create some test notifications: follow, favourite, reblog, mention beforeAll(async () => { @@ -114,7 +114,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const notification = (await response.json()) as apiNotification; + const notification = (await response.json()) as ApiNotification; expect(notification).toBeDefined(); expect(notification.id).toBe(notifications[0].id); diff --git a/server/api/api/v1/notifications/clear/index.test.ts b/server/api/api/v1/notifications/clear/index.test.ts index bb4d5de1..7a62da95 100644 --- a/server/api/api/v1/notifications/clear/index.test.ts +++ b/server/api/api/v1/notifications/clear/index.test.ts @@ -1,11 +1,11 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Notification as ApiNotification } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Notification as apiNotification } from "~/types/mastodon/notification"; import { meta } from "./index"; const { users, tokens, deleteUsers } = await getTestUsers(2); -let notifications: apiNotification[] = []; +let notifications: ApiNotification[] = []; // Create some test notifications: follow, favourite, reblog, mention beforeAll(async () => { diff --git a/server/api/api/v1/notifications/destroy_multiple/index.test.ts b/server/api/api/v1/notifications/destroy_multiple/index.test.ts index 763501d2..75e3b4cc 100644 --- a/server/api/api/v1/notifications/destroy_multiple/index.test.ts +++ b/server/api/api/v1/notifications/destroy_multiple/index.test.ts @@ -1,12 +1,12 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Notification as ApiNotification } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Notification as apiNotification } from "~/types/mastodon/notification"; import { meta } from "./index"; const { users, tokens, deleteUsers } = await getTestUsers(2); const statuses = await getTestStatuses(40, users[0]); -let notifications: apiNotification[] = []; +let notifications: ApiNotification[] = []; // Create some test notifications beforeAll(async () => { diff --git a/server/api/api/v1/notifications/index.test.ts b/server/api/api/v1/notifications/index.test.ts index 1112a4e9..5db11cc9 100644 --- a/server/api/api/v1/notifications/index.test.ts +++ b/server/api/api/v1/notifications/index.test.ts @@ -1,7 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Notification as ApiNotification } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Notification as apiNotification } from "~/types/mastodon/notification"; import { meta } from "./index"; const getFormData = (object: Record) => @@ -113,7 +113,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiNotification[]; + const objects = (await response.json()) as ApiNotification[]; expect(objects.length).toBe(4); for (const [index, notification] of objects.entries()) { @@ -165,7 +165,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiNotification[]; + const objects = (await response.json()) as ApiNotification[]; expect(objects.length).toBe(2); // There should be no element with a status with id of timeline[0].id diff --git a/server/api/api/v1/statuses/:id/favourite.test.ts b/server/api/api/v1/statuses/:id/favourite.test.ts index 2ff3d66d..2e2a9fe2 100644 --- a/server/api/api/v1/statuses/:id/favourite.test.ts +++ b/server/api/api/v1/statuses/:id/favourite.test.ts @@ -1,7 +1,7 @@ import { afterAll, describe, expect, test } from "bun:test"; +import type { Status as ApiStatus } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Status as apiStatus } from "~/types/mastodon/status"; import { meta } from "./favourite"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -47,7 +47,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const json = (await response.json()) as apiStatus; + const json = (await response.json()) as ApiStatus; expect(json.favourited).toBe(true); expect(json.favourites_count).toBe(1); @@ -70,7 +70,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const json = (await response.json()) as apiStatus; + const json = (await response.json()) as ApiStatus; expect(json.favourited).toBe(true); expect(json.favourites_count).toBe(1); diff --git a/server/api/api/v1/statuses/:id/favourited_by.test.ts b/server/api/api/v1/statuses/:id/favourited_by.test.ts index fbb29518..b668fe70 100644 --- a/server/api/api/v1/statuses/:id/favourited_by.test.ts +++ b/server/api/api/v1/statuses/:id/favourited_by.test.ts @@ -1,7 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Account as ApiAccount } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Account as apiAccount } from "~/types/mastodon/account"; import { meta } from "./favourited_by"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -63,7 +63,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiAccount[]; + const objects = (await response.json()) as ApiAccount[]; expect(objects.length).toBe(1); for (const [, status] of objects.entries()) { diff --git a/server/api/api/v1/statuses/:id/reblogged_by.test.ts b/server/api/api/v1/statuses/:id/reblogged_by.test.ts index 9c1a8e70..5d3be646 100644 --- a/server/api/api/v1/statuses/:id/reblogged_by.test.ts +++ b/server/api/api/v1/statuses/:id/reblogged_by.test.ts @@ -1,7 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Account as ApiAccount } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Account as apiAccount } from "~/types/mastodon/account"; import { meta } from "./reblogged_by"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -63,7 +63,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiAccount[]; + const objects = (await response.json()) as ApiAccount[]; expect(objects.length).toBe(1); for (const [, status] of objects.entries()) { diff --git a/server/api/api/v1/statuses/:id/source.ts b/server/api/api/v1/statuses/:id/source.ts index 33eee9db..310c7c11 100644 --- a/server/api/api/v1/statuses/:id/source.ts +++ b/server/api/api/v1/statuses/:id/source.ts @@ -1,11 +1,11 @@ import { applyConfig, auth, handleZodError } from "@/api"; import { errorResponse, jsonResponse } from "@/response"; import { zValidator } from "@hono/zod-validator"; +import type { StatusSource as ApiStatusSource } from "@lysand-org/client/types"; import type { Hono } from "hono"; import { z } from "zod"; import { RolePermissions } from "~/drizzle/schema"; import { Note } from "~/packages/database-interface/note"; -import type { StatusSource as apiStatusSource } from "~/types/mastodon/status_source"; export const meta = applyConfig({ allowedMethods: ["GET"], @@ -53,6 +53,6 @@ export default (app: Hono) => // TODO: Give real source for spoilerText spoiler_text: status.data.spoilerText, text: status.data.contentSource, - } as apiStatusSource); + } as ApiStatusSource); }, ); diff --git a/server/api/api/v1/statuses/:id/unfavourite.test.ts b/server/api/api/v1/statuses/:id/unfavourite.test.ts index f71a1f60..59161af7 100644 --- a/server/api/api/v1/statuses/:id/unfavourite.test.ts +++ b/server/api/api/v1/statuses/:id/unfavourite.test.ts @@ -1,7 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Status as ApiStatus } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Status as apiStatus } from "~/types/mastodon/status"; import { meta } from "./unfavourite"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -83,7 +83,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const json = (await response.json()) as apiStatus; + const json = (await response.json()) as ApiStatus; expect(json.favourited).toBe(false); expect(json.favourites_count).toBe(0); @@ -106,7 +106,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); - const json = (await response.json()) as apiStatus; + const json = (await response.json()) as ApiStatus; expect(json.favourited).toBe(false); expect(json.favourites_count).toBe(0); diff --git a/server/api/api/v1/statuses/index.test.ts b/server/api/api/v1/statuses/index.test.ts index 96713918..2fed2793 100644 --- a/server/api/api/v1/statuses/index.test.ts +++ b/server/api/api/v1/statuses/index.test.ts @@ -1,10 +1,10 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import type { Status as ApiStatus } from "@lysand-org/client/types"; import { config } from "config-manager"; import { eq } from "drizzle-orm"; import { db } from "~/drizzle/db"; import { Emojis } from "~/drizzle/schema"; import { getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Status as apiStatus } from "~/types/mastodon/status"; import { meta } from "./index"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -175,7 +175,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const object = (await response.json()) as apiStatus; + const object = (await response.json()) as ApiStatus; expect(object.content).toBe("

Hello, world!

"); }); @@ -200,7 +200,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const object = (await response.json()) as apiStatus; + const object = (await response.json()) as ApiStatus; expect(object.content).toBe("

Hello, world!

"); expect(object.visibility).toBe("unlisted"); @@ -220,7 +220,7 @@ describe(meta.route, () => { }), ); - const object = (await response.json()) as apiStatus; + const object = (await response.json()) as ApiStatus; const response2 = await sendTestRequest( new Request(new URL(meta.route, config.http.base_url), { @@ -239,7 +239,7 @@ describe(meta.route, () => { expect(response2.status).toBe(200); expect(response2.headers.get("content-type")).toBe("application/json"); - const object2 = (await response2.json()) as apiStatus; + const object2 = (await response2.json()) as ApiStatus; expect(object2.content).toBe("

Hello, world again!

"); expect(object2.in_reply_to_id).toBe(object.id); @@ -259,7 +259,7 @@ describe(meta.route, () => { }), ); - const object = (await response.json()) as apiStatus; + const object = (await response.json()) as ApiStatus; const response2 = await sendTestRequest( new Request(new URL(meta.route, config.http.base_url), { @@ -278,12 +278,9 @@ describe(meta.route, () => { expect(response2.status).toBe(200); expect(response2.headers.get("content-type")).toBe("application/json"); - const object2 = (await response2.json()) as apiStatus; + const object2 = (await response2.json()) as ApiStatus; expect(object2.content).toBe("

Hello, world again!

"); - // @ts-expect-error Pleroma extension - expect(object2.quote_id).toBe(object.id); - // @ts-expect-error Glitch SOC extension expect(object2.quote?.id).toBe(object.id); }); @@ -304,7 +301,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const object = (await response.json()) as apiStatus; + const object = (await response.json()) as ApiStatus; expect(object.emojis).toBeArrayOfSize(1); expect(object.emojis[0]).toMatchObject({ @@ -333,7 +330,7 @@ describe(meta.route, () => { "application/json", ); - const object = (await response.json()) as apiStatus; + const object = (await response.json()) as ApiStatus; expect(object.mentions).toBeArrayOfSize(1); expect(object.mentions[0]).toMatchObject({ @@ -364,7 +361,7 @@ describe(meta.route, () => { "application/json", ); - const object = (await response.json()) as apiStatus; + const object = (await response.json()) as ApiStatus; expect(object.mentions).toBeArrayOfSize(1); expect(object.mentions[0]).toMatchObject({ @@ -395,7 +392,7 @@ describe(meta.route, () => { "application/json", ); - const object = (await response.json()) as apiStatus; + const object = (await response.json()) as ApiStatus; expect(object.content).toBe( "

Hi! <script>alert('Hello, world!');</script>

", @@ -423,7 +420,7 @@ describe(meta.route, () => { "application/json", ); - const object = (await response.json()) as apiStatus; + const object = (await response.json()) as ApiStatus; expect(object.spoiler_text).toBe( "uwu <script>alert('Hello, world!');</script>", @@ -449,7 +446,7 @@ describe(meta.route, () => { "application/json", ); - const object = (await response.json()) as apiStatus; + const object = (await response.json()) as ApiStatus; // Proxy url is base_url/media/proxy/ expect(object.content).toBe( `

{ expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(5); }); @@ -52,7 +52,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(20); for (const [index, status] of objects.entries()) { @@ -102,7 +102,7 @@ describe(meta.route, () => { "application/json", ); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(20); for (const [index, status] of objects.entries()) { @@ -154,7 +154,7 @@ describe(meta.route, () => { "application/json", ); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(20); for (const [index, status] of objects.entries()) { @@ -203,7 +203,7 @@ describe(meta.route, () => { "application/json", ); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(20); // There should be no element with id of timeline[0].id diff --git a/server/api/api/v1/timelines/public.test.ts b/server/api/api/v1/timelines/public.test.ts index 821e8508..e543556b 100644 --- a/server/api/api/v1/timelines/public.test.ts +++ b/server/api/api/v1/timelines/public.test.ts @@ -1,7 +1,7 @@ import { afterAll, describe, expect, test } from "bun:test"; +import type { Status as ApiStatus } from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils"; -import type { Status as apiStatus } from "~/types/mastodon/status"; import { meta } from "./public"; const { users, tokens, deleteUsers } = await getTestUsers(5); @@ -27,7 +27,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(5); }); @@ -44,7 +44,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(20); for (const [index, status] of objects.entries()) { @@ -74,7 +74,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(20); for (const [index, status] of objects.entries()) { @@ -104,7 +104,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects).toBeArray(); }); @@ -147,7 +147,7 @@ describe(meta.route, () => { "application/json", ); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(20); for (const [index, status] of objects.entries()) { @@ -199,7 +199,7 @@ describe(meta.route, () => { "application/json", ); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(20); for (const [index, status] of objects.entries()) { @@ -247,7 +247,7 @@ describe(meta.route, () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const objects = (await response.json()) as apiStatus[]; + const objects = (await response.json()) as ApiStatus[]; expect(objects.length).toBe(20); // There should be no element with id of timeline[0].id diff --git a/server/api/api/v2/instance/index.ts b/server/api/api/v2/instance/index.ts index 634c26e7..9cdda872 100644 --- a/server/api/api/v2/instance/index.ts +++ b/server/api/api/v2/instance/index.ts @@ -1,5 +1,6 @@ import { applyConfig } from "@/api"; import { jsonResponse, proxyUrl } from "@/response"; +import type { Instance as ApiInstance } from "@lysand-org/client/types"; import { and, eq, isNull } from "drizzle-orm"; import type { Hono } from "hono"; import { Users } from "~/drizzle/schema"; @@ -59,7 +60,6 @@ export default (app: Hono) => }, accounts: { max_featured_tags: 100, - max_note_characters: config.validation.max_bio_size, max_displayname_characters: config.validation.max_displayname_size, avatar_size_limit: config.validation.max_avatar_size, @@ -71,6 +71,7 @@ export default (app: Hono) => max_fields: config.validation.max_field_count, max_username_characters: config.validation.max_username_size, + max_note_characters: config.validation.max_bio_size, }, statuses: { max_characters: config.validation.max_note_size, @@ -118,9 +119,9 @@ export default (app: Hono) => forced: false, providers: config.oidc.providers.map((p) => ({ name: p.name, - icon: proxyUrl(p.icon) || undefined, + icon: proxyUrl(p.icon) ?? "", id: p.id, })), }, - }); + } satisfies ApiInstance); }); diff --git a/tests/api/accounts.test.ts b/tests/api/accounts.test.ts index 39b33e3e..e148fff6 100644 --- a/tests/api/accounts.test.ts +++ b/tests/api/accounts.test.ts @@ -2,10 +2,12 @@ * @deprecated */ import { afterAll, describe, expect, test } from "bun:test"; +import type { + Account as ApiAccount, + Relationship as ApiRelationship, +} from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest, wrapRelativeUrl } from "~/tests/utils"; -import type { Account as apiAccount } from "~/types/mastodon/account"; -import type { Relationship as apiRelationship } from "~/types/mastodon/relationship"; const baseUrl = config.http.base_url; @@ -50,7 +52,7 @@ describe("API Tests", () => { "application/json", ); - const user = (await response.json()) as apiAccount; + const user = (await response.json()) as ApiAccount; expect(user.display_name).toBe("New Display Name"); }); @@ -77,7 +79,7 @@ describe("API Tests", () => { "application/json", ); - const account = (await response.json()) as apiAccount; + const account = (await response.json()) as ApiAccount; expect(account.username).toBe(user.data.username); expect(account.bot).toBe(false); @@ -131,7 +133,7 @@ describe("API Tests", () => { "application/json", ); - const account = (await response.json()) as apiRelationship; + const account = (await response.json()) as ApiRelationship; expect(account.id).toBe(user2.id); expect(account.followed_by).toBe(false); @@ -162,7 +164,7 @@ describe("API Tests", () => { "application/json", ); - const account = (await response.json()) as apiRelationship; + const account = (await response.json()) as ApiRelationship; expect(account.id).toBe(user2.id); expect(account.blocking).toBe(true); @@ -184,7 +186,7 @@ describe("API Tests", () => { expect(response.headers.get("content-type")).toBe( "application/json", ); - const body = (await response.json()) as apiAccount[]; + const body = (await response.json()) as ApiAccount[]; expect(Array.isArray(body)).toBe(true); expect(body.length).toBe(1); @@ -216,7 +218,7 @@ describe("API Tests", () => { "application/json", ); - const account = (await response.json()) as apiRelationship; + const account = (await response.json()) as ApiRelationship; expect(account.id).toBe(user2.id); expect(account.blocking).toBe(false); @@ -247,7 +249,7 @@ describe("API Tests", () => { "application/json", ); - const account = (await response.json()) as apiRelationship; + const account = (await response.json()) as ApiRelationship; expect(account.id).toBe(user2.id); expect(account.endorsed).toBe(true); @@ -278,7 +280,7 @@ describe("API Tests", () => { "application/json", ); - const account = (await response.json()) as apiRelationship; + const account = (await response.json()) as ApiRelationship; expect(account.id).toBe(user2.id); expect(account.endorsed).toBe(false); @@ -309,7 +311,7 @@ describe("API Tests", () => { "application/json", ); - const account = (await response.json()) as apiAccount; + const account = (await response.json()) as ApiAccount; expect(account.id).toBe(user2.id); expect(account.note).toBe("This is a new note"); @@ -338,7 +340,7 @@ describe("API Tests", () => { "application/json", ); - const relationships = (await response.json()) as apiRelationship[]; + const relationships = (await response.json()) as ApiRelationship[]; expect(Array.isArray(relationships)).toBe(true); expect(relationships.length).toBeGreaterThan(0); @@ -373,7 +375,7 @@ describe("API Tests", () => { "application/json", ); - const account = (await response.json()) as apiAccount; + const account = (await response.json()) as ApiAccount; expect(account.id).toBeDefined(); expect(account.avatar).toBeDefined(); @@ -399,7 +401,7 @@ describe("API Tests", () => { "application/json", ); - const account = (await response.json()) as apiAccount; + const account = (await response.json()) as ApiAccount; expect(account.id).toBeDefined(); expect(account.header).toBe(""); @@ -454,7 +456,7 @@ describe("API Tests", () => { const familiarFollowers = (await response.json()) as { id: string; - accounts: apiAccount[]; + accounts: ApiAccount[]; }[]; expect(Array.isArray(familiarFollowers)).toBe(true); diff --git a/tests/api/statuses.test.ts b/tests/api/statuses.test.ts index dd553717..0864b24e 100644 --- a/tests/api/statuses.test.ts +++ b/tests/api/statuses.test.ts @@ -2,20 +2,22 @@ * @deprecated */ import { afterAll, describe, expect, test } from "bun:test"; +import type { + AsyncAttachment as ApiAsyncAttachment, + Context as ApiContext, + Status as ApiStatus, +} from "@lysand-org/client/types"; import { config } from "config-manager"; import { getTestUsers, sendTestRequest, wrapRelativeUrl } from "~/tests/utils"; -import type { AsyncAttachment as apiAsyncAttachment } from "~/types/mastodon/async_attachment"; -import type { Context as apiContext } from "~/types/mastodon/context"; -import type { Status as apiStatus } from "~/types/mastodon/status"; const baseUrl = config.http.base_url; const { users, tokens, deleteUsers } = await getTestUsers(1); const user = users[0]; const token = tokens[0]; -let status: apiStatus | null = null; -let status2: apiStatus | null = null; -let media1: apiAsyncAttachment | null = null; +let status: ApiStatus | null = null; +let status2: ApiStatus | null = null; +let media1: ApiAsyncAttachment | null = null; describe("API Tests", () => { afterAll(async () => { @@ -45,7 +47,7 @@ describe("API Tests", () => { "application/json", ); - media1 = (await response.json()) as apiAsyncAttachment; + media1 = (await response.json()) as ApiAsyncAttachment; expect(media1.id).toBeDefined(); expect(media1.type).toBe("unknown"); @@ -78,7 +80,7 @@ describe("API Tests", () => { "application/json", ); - status = (await response.json()) as apiStatus; + status = (await response.json()) as ApiStatus; expect(status.content).toContain("Hello, world!"); expect(status.visibility).toBe("public"); expect(status.account.id).toBe(user.id); @@ -125,7 +127,7 @@ describe("API Tests", () => { "application/json", ); - status2 = (await response.json()) as apiStatus; + status2 = (await response.json()) as ApiStatus; expect(status2.content).toContain("This is a reply!"); expect(status2.visibility).toBe("public"); expect(status2.account.id).toBe(user.id); @@ -170,7 +172,7 @@ describe("API Tests", () => { "application/json", ); - const statusJson = (await response.json()) as apiStatus; + const statusJson = (await response.json()) as ApiStatus; expect(statusJson.id).toBe(status?.id || ""); expect(statusJson.content).toBeDefined(); @@ -220,7 +222,7 @@ describe("API Tests", () => { "application/json", ); - const rebloggedStatus = (await response.json()) as apiStatus; + const rebloggedStatus = (await response.json()) as ApiStatus; expect(rebloggedStatus.id).toBeDefined(); expect(rebloggedStatus.reblog?.id).toEqual(status?.id ?? ""); @@ -250,7 +252,7 @@ describe("API Tests", () => { "application/json", ); - const unrebloggedStatus = (await response.json()) as apiStatus; + const unrebloggedStatus = (await response.json()) as ApiStatus; expect(unrebloggedStatus.id).toBeDefined(); expect(unrebloggedStatus.reblogged).toBe(false); @@ -278,7 +280,7 @@ describe("API Tests", () => { "application/json", ); - const context = (await response.json()) as apiContext; + const context = (await response.json()) as ApiContext; expect(context.ancestors.length).toBe(0); expect(context.descendants.length).toBe(1); @@ -310,7 +312,7 @@ describe("API Tests", () => { "application/json", ); - const statuses = (await response.json()) as apiStatus[]; + const statuses = (await response.json()) as ApiStatus[]; expect(statuses.length).toBe(2); @@ -367,7 +369,7 @@ describe("API Tests", () => { "application/json", ); - const updatedStatus = (await response.json()) as apiStatus; + const updatedStatus = (await response.json()) as ApiStatus; expect(updatedStatus.favourited).toBe(false); expect(updatedStatus.favourites_count).toBe(0); diff --git a/tests/oauth.test.ts b/tests/oauth.test.ts index 78b6a146..6041af04 100644 --- a/tests/oauth.test.ts +++ b/tests/oauth.test.ts @@ -2,9 +2,11 @@ * @deprecated */ import { afterAll, describe, expect, test } from "bun:test"; +import type { + Application as ApiApplication, + Token as ApiToken, +} from "@lysand-org/client/types"; import { config } from "~/packages/config-manager"; -import type { Application as apiApplication } from "~/types/mastodon/application"; -import type { Token as apiToken } from "~/types/mastodon/token"; import { getTestUsers, sendTestRequest, wrapRelativeUrl } from "./utils"; const baseUrl = config.http.base_url; @@ -13,7 +15,7 @@ let clientId: string; let clientSecret: string; let code: string; let jwt: string; -let token: apiToken; +let token: ApiToken; const { users, passwords, deleteUsers } = await getTestUsers(1); afterAll(async () => { @@ -178,7 +180,7 @@ describe("GET /api/v1/apps/verify_credentials", () => { expect(response.status).toBe(200); expect(response.headers.get("content-type")).toBe("application/json"); - const credentials = (await response.json()) as Partial; + const credentials = (await response.json()) as Partial; expect(credentials.name).toBe("Test Application"); expect(credentials.website).toBe("https://example.com"); diff --git a/types/entity.ts b/types/entity.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/types/mastodon/account.ts b/types/mastodon/account.ts deleted file mode 100644 index 0a9f43fe..00000000 --- a/types/mastodon/account.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { Emoji } from "./emoji"; -import type { Field } from "./field"; -import type { LysandRole } from "./lysand"; -import type { Role } from "./role"; -import type { Source } from "./source"; - -export type Account = { - id: string; - username: string; - acct: string; - display_name: string; - locked: boolean; - discoverable?: boolean; - group: boolean | null; - noindex: boolean | null; - suspended: boolean | null; - limited: boolean | null; - created_at: string; - followers_count: number; - following_count: number; - statuses_count: number; - note: string; - url: string; - avatar: string; - avatar_static: string; - header: string; - header_static: string; - emojis: Emoji[]; - moved: Account | null; - fields: Field[]; - bot: boolean | null; - source?: Source; - role?: Role; - roles: LysandRole[]; - mute_expires_at?: string; -}; diff --git a/types/mastodon/activity.ts b/types/mastodon/activity.ts deleted file mode 100644 index 8dbc511e..00000000 --- a/types/mastodon/activity.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type Activity = { - week: string; - statuses: string; - logins: string; - registrations: string; -}; diff --git a/types/mastodon/announcement.ts b/types/mastodon/announcement.ts deleted file mode 100644 index 0a3cb108..00000000 --- a/types/mastodon/announcement.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { Emoji } from "./emoji"; -import type { StatusTag } from "./status"; - -export type Announcement = { - id: string; - content: string; - starts_at: string | null; - ends_at: string | null; - published: boolean; - all_day: boolean; - published_at: string; - updated_at: string | null; - read: boolean | null; - mentions: AnnouncementAccount[]; - statuses: AnnouncementStatus[]; - tags: StatusTag[]; - emojis: Emoji[]; - reactions: AnnouncementReaction[]; -}; - -export type AnnouncementAccount = { - id: string; - username: string; - url: string; - acct: string; -}; - -export type AnnouncementStatus = { - id: string; - url: string; -}; - -export type AnnouncementReaction = { - name: string; - count: number; - me: boolean | null; - url: string | null; - static_url: string | null; -}; diff --git a/types/mastodon/application.ts b/types/mastodon/application.ts deleted file mode 100644 index fa350331..00000000 --- a/types/mastodon/application.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type Application = { - name: string; - website?: string | null; - vapid_key?: string | null; -}; diff --git a/types/mastodon/async_attachment.ts b/types/mastodon/async_attachment.ts deleted file mode 100644 index 7b2b5b05..00000000 --- a/types/mastodon/async_attachment.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Meta } from "./attachment"; - -export type AsyncAttachment = { - id: string; - type: "unknown" | "image" | "gifv" | "video" | "audio"; - url: string | null; - remote_url: string | null; - preview_url: string; - text_url: string | null; - meta: Meta | null; - description: string | null; - blurhash: string | null; -}; diff --git a/types/mastodon/attachment.ts b/types/mastodon/attachment.ts deleted file mode 100644 index c3a36977..00000000 --- a/types/mastodon/attachment.ts +++ /dev/null @@ -1,47 +0,0 @@ -export type Sub = { - // For Image, Gifv, and Video - width?: number; - height?: number; - size?: string; - aspect?: number; - - // For Gifv and Video - frame_rate?: string; - - // For Audio, Gifv, and Video - duration?: number; - bitrate?: number; -}; - -export type Focus = { - x: number; - y: number; -}; - -export type Meta = { - original?: Sub; - small?: Sub; - focus?: Focus; - length?: string; - duration?: number; - fps?: number; - size?: string; - width?: number; - height?: number; - aspect?: number; - audio_encode?: string; - audio_bitrate?: string; - audio_channel?: string; -}; - -export type Attachment = { - id: string; - type: "unknown" | "image" | "gifv" | "video" | "audio"; - url: string; - remote_url: string | null; - preview_url: string | null; - text_url: string | null; - meta: Meta | null; - description: string | null; - blurhash: string | null; -}; diff --git a/types/mastodon/card.ts b/types/mastodon/card.ts deleted file mode 100644 index 6d12122a..00000000 --- a/types/mastodon/card.ts +++ /dev/null @@ -1,16 +0,0 @@ -export type Card = { - url: string; - title: string; - description: string; - type: "link" | "photo" | "video" | "rich"; - image: string | null; - author_name: string | null; - author_url: string | null; - provider_name: string | null; - provider_url: string | null; - html: string | null; - width: number | null; - height: number | null; - embed_url: string | null; - blurhash: string | null; -}; diff --git a/types/mastodon/context.ts b/types/mastodon/context.ts deleted file mode 100644 index c053f512..00000000 --- a/types/mastodon/context.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { Status } from "./status"; - -export type Context = { - ancestors: Status[]; - descendants: Status[]; -}; diff --git a/types/mastodon/conversation.ts b/types/mastodon/conversation.ts deleted file mode 100644 index 5edf6091..00000000 --- a/types/mastodon/conversation.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Account } from "./account"; -import type { Status } from "./status"; - -export type Conversation = { - id: string; - accounts: Account[]; - last_status: Status | null; - unread: boolean; -}; diff --git a/types/mastodon/emoji.ts b/types/mastodon/emoji.ts deleted file mode 100644 index cc8de673..00000000 --- a/types/mastodon/emoji.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type Emoji = { - shortcode: string; - static_url: string; - url: string; - visible_in_picker: boolean; - category?: string; -}; diff --git a/types/mastodon/featured_tag.ts b/types/mastodon/featured_tag.ts deleted file mode 100644 index 2fe3ba6d..00000000 --- a/types/mastodon/featured_tag.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type FeaturedTag = { - id: string; - name: string; - statuses_count: number; - last_status_at: string; -}; diff --git a/types/mastodon/field.ts b/types/mastodon/field.ts deleted file mode 100644 index 77982696..00000000 --- a/types/mastodon/field.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type Field = { - name: string; - value: string; - verified_at?: string | null; - verified?: boolean | false; -}; diff --git a/types/mastodon/filter.ts b/types/mastodon/filter.ts deleted file mode 100644 index da97b419..00000000 --- a/types/mastodon/filter.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type Filter = { - id: string; - phrase: string; - context: FilterContext[]; - expires_at: string | null; - irreversible: boolean; - whole_word: boolean; -}; - -export type FilterContext = string; diff --git a/types/mastodon/follow_request.ts b/types/mastodon/follow_request.ts deleted file mode 100644 index 676b583a..00000000 --- a/types/mastodon/follow_request.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { Emoji } from "./emoji"; -import type { Field } from "./field"; - -export type FollowRequest = { - id: number; - username: string; - acct: string; - display_name: string; - locked: boolean; - bot: boolean; - discoverable?: boolean; - group: boolean; - created_at: string; - note: string; - url: string; - avatar: string; - avatar_static: string; - header: string; - header_static: string; - followers_count: number; - following_count: number; - statuses_count: number; - emojis: Emoji[]; - fields: Field[]; -}; diff --git a/types/mastodon/history.ts b/types/mastodon/history.ts deleted file mode 100644 index 22176bde..00000000 --- a/types/mastodon/history.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type History = { - day: string; - uses: number; - accounts: number; -}; diff --git a/types/mastodon/identity_proof.ts b/types/mastodon/identity_proof.ts deleted file mode 100644 index 00d9efcd..00000000 --- a/types/mastodon/identity_proof.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type IdentityProof = { - provider: string; - provider_username: string; - updated_at: string; - proof_url: string; - profile_url: string; -}; diff --git a/types/mastodon/instance.ts b/types/mastodon/instance.ts deleted file mode 100644 index c5030964..00000000 --- a/types/mastodon/instance.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { Account } from "./account"; -import type { Stats } from "./stats"; -import type { URLs } from "./urls"; - -export type Instance = { - uri: string; - title: string; - description: string; - email: string; - version: string; - thumbnail: string | null; - urls: URLs | null; - stats: Stats; - languages: string[]; - registrations: boolean; - approval_required: boolean; - invites_enabled?: boolean; - configuration: { - statuses: { - max_characters: number; - max_media_attachments?: number; - characters_reserved_per_url?: number; - }; - polls?: { - max_options: number; - max_characters_per_option: number; - min_expiration: number; - max_expiration: number; - }; - }; - contact_account?: Account; - rules?: InstanceRule[]; -}; - -export type InstanceRule = { - id: string; - text: string; -}; diff --git a/types/mastodon/list.ts b/types/mastodon/list.ts deleted file mode 100644 index 3ae0d375..00000000 --- a/types/mastodon/list.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type List = { - id: string; - title: string; - replies_policy: RepliesPolicy | null; -}; - -export type RepliesPolicy = "followed" | "list" | "none"; diff --git a/types/mastodon/lysand.ts b/types/mastodon/lysand.ts deleted file mode 100644 index 3a407f36..00000000 --- a/types/mastodon/lysand.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { RolePermissions } from "~/drizzle/schema"; - -export type LysandRole = { - id: string; - name: string; - permissions: RolePermissions[]; - priority: number; - description: string | null; - visible: boolean; - icon: string | null; -}; diff --git a/types/mastodon/marker.ts b/types/mastodon/marker.ts deleted file mode 100644 index d69b0ef8..00000000 --- a/types/mastodon/marker.ts +++ /dev/null @@ -1,13 +0,0 @@ -export type Marker = { - home?: { - last_read_id: string; - version: number; - updated_at: string; - }; - notifications?: { - last_read_id: string; - version: number; - updated_at: string; - unread_count?: number; - }; -}; diff --git a/types/mastodon/mention.ts b/types/mastodon/mention.ts deleted file mode 100644 index dba8929b..00000000 --- a/types/mastodon/mention.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type Mention = { - id: string; - username: string; - url: string; - acct: string; -}; diff --git a/types/mastodon/notification.ts b/types/mastodon/notification.ts deleted file mode 100644 index d240f498..00000000 --- a/types/mastodon/notification.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Account } from "./account"; -import type { Reaction } from "./reaction"; -import type { Status } from "./status"; - -export type Notification = { - account: Account | null; - created_at: string; - id: string; - status?: Status; - reaction?: Reaction; - type: NotificationType; - target?: Account; -}; - -export type NotificationType = string; diff --git a/types/mastodon/poll.ts b/types/mastodon/poll.ts deleted file mode 100644 index 33fef2f8..00000000 --- a/types/mastodon/poll.ts +++ /dev/null @@ -1,14 +0,0 @@ -export type Poll = { - id: string; - expires_at: string | null; - expired: boolean; - multiple: boolean; - votes_count: number; - options: PollOption[]; - voted: boolean; -}; - -export type PollOption = { - title: string; - votes_count: number | null; -}; diff --git a/types/mastodon/preferences.ts b/types/mastodon/preferences.ts deleted file mode 100644 index c0efe96c..00000000 --- a/types/mastodon/preferences.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { StatusVisibility } from "./status"; - -export type Preferences = { - "posting:default:visibility": StatusVisibility; - "posting:default:sensitive": boolean; - "posting:default:language": string | null; - "reading:expand:media": "default" | "show_all" | "hide_all"; - "reading:expand:spoilers": boolean; -}; diff --git a/types/mastodon/push_subscription.ts b/types/mastodon/push_subscription.ts deleted file mode 100644 index 0449551e..00000000 --- a/types/mastodon/push_subscription.ts +++ /dev/null @@ -1,14 +0,0 @@ -export type Alerts = { - follow: boolean; - favourite: boolean; - mention: boolean; - reblog: boolean; - poll: boolean; -}; - -export type PushSubscription = { - id: string; - endpoint: string; - server_key: string; - alerts: Alerts; -}; diff --git a/types/mastodon/reaction.ts b/types/mastodon/reaction.ts deleted file mode 100644 index 74832695..00000000 --- a/types/mastodon/reaction.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { Account } from "./account"; - -export type Reaction = { - count: number; - me: boolean; - name: string; - url?: string; - static_url?: string; - accounts?: Account[]; - account_ids?: string[]; -}; diff --git a/types/mastodon/relationship.ts b/types/mastodon/relationship.ts deleted file mode 100644 index c2bb9c2a..00000000 --- a/types/mastodon/relationship.ts +++ /dev/null @@ -1,16 +0,0 @@ -export type Relationship = { - id: string; - following: boolean; - followed_by: boolean; - blocking: boolean; - blocked_by: boolean; - muting: boolean; - muting_notifications: boolean; - requested: boolean; - requested_by: boolean; - domain_blocking: boolean; - showing_reblogs: boolean; - endorsed: boolean; - notifying: boolean; - note: string | null; -}; diff --git a/types/mastodon/report.ts b/types/mastodon/report.ts deleted file mode 100644 index ee98aa33..00000000 --- a/types/mastodon/report.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { Account } from "./account"; - -export type Report = { - id: string; - action_taken: boolean; - action_taken_at: string | null; - status_ids: string[] | null; - rule_ids: string[] | null; - // These parameters don't exist in Pleroma - category: Category | null; - comment: string | null; - forwarded: boolean | null; - target_account?: Account | null; -}; - -export type Category = "spam" | "violation" | "other"; diff --git a/types/mastodon/results.ts b/types/mastodon/results.ts deleted file mode 100644 index 229f98ee..00000000 --- a/types/mastodon/results.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Account } from "./account"; -import type { Status } from "./status"; -import type { Tag } from "./tag"; - -export type Results = { - accounts: Account[]; - statuses: Status[]; - hashtags: Tag[]; -}; diff --git a/types/mastodon/role.ts b/types/mastodon/role.ts deleted file mode 100644 index fdb98cab..00000000 --- a/types/mastodon/role.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type Role = { - name: string; -}; diff --git a/types/mastodon/scheduled_status.ts b/types/mastodon/scheduled_status.ts deleted file mode 100644 index 69389ef8..00000000 --- a/types/mastodon/scheduled_status.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Attachment } from "./attachment"; -import type { StatusParams } from "./status_params"; - -export type ScheduledStatus = { - id: string; - scheduled_at: string; - params: StatusParams; - media_attachments: Attachment[] | null; -}; diff --git a/types/mastodon/source.ts b/types/mastodon/source.ts deleted file mode 100644 index cab190e5..00000000 --- a/types/mastodon/source.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Field } from "./field"; - -export type Source = { - privacy: string | null; - sensitive: boolean | null; - language: string | null; - note: string; - fields: Field[]; -}; diff --git a/types/mastodon/stats.ts b/types/mastodon/stats.ts deleted file mode 100644 index 7654b385..00000000 --- a/types/mastodon/stats.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type Stats = { - user_count: number; - status_count: number; - domain_count: number; -}; diff --git a/types/mastodon/status.ts b/types/mastodon/status.ts deleted file mode 100644 index 30f9df6c..00000000 --- a/types/mastodon/status.ts +++ /dev/null @@ -1,50 +0,0 @@ -import type { Account } from "./account"; -import type { Application } from "./application"; -import type { Attachment } from "./attachment"; -import type { Card } from "./card"; -import type { Emoji } from "./emoji"; -import type { Mention } from "./mention"; -import type { Poll } from "./poll"; -import type { Reaction } from "./reaction"; - -export type Status = { - id: string; - uri: string; - url: string; - account: Account; - in_reply_to_id: string | null; - in_reply_to_account_id: string | null; - reblog: Status | null; - content: string; - plain_content: string | null; - created_at: string; - edited_at: string | null; - emojis: Emoji[]; - replies_count: number; - reblogs_count: number; - favourites_count: number; - reblogged: boolean | null; - favourited: boolean | null; - muted: boolean | null; - sensitive: boolean; - spoiler_text: string; - visibility: StatusVisibility; - media_attachments: Attachment[]; - mentions: Mention[]; - tags: StatusTag[]; - card: Card | null; - poll: Poll | null; - application: Application | null; - language: string | null; - pinned: boolean | null; - emoji_reactions: Reaction[]; - quote: boolean; - bookmarked: boolean; -}; - -export type StatusTag = { - name: string; - url: string; -}; - -export type StatusVisibility = "public" | "unlisted" | "private" | "direct"; diff --git a/types/mastodon/status_params.ts b/types/mastodon/status_params.ts deleted file mode 100644 index 56c1874c..00000000 --- a/types/mastodon/status_params.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { StatusVisibility } from "./status"; - -export type StatusParams = { - text: string; - in_reply_to_id: string | null; - media_ids: string[] | null; - sensitive: boolean | null; - spoiler_text: string | null; - visibility: StatusVisibility | null; - scheduled_at: string | null; - application_id: number | null; -}; diff --git a/types/mastodon/status_source.ts b/types/mastodon/status_source.ts deleted file mode 100644 index 346c346a..00000000 --- a/types/mastodon/status_source.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type StatusSource = { - id: string; - text: string; - spoiler_text: string; -}; diff --git a/types/mastodon/tag.ts b/types/mastodon/tag.ts deleted file mode 100644 index 69237425..00000000 --- a/types/mastodon/tag.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { History } from "./history"; - -export type Tag = { - name: string; - url: string; - history: History[]; - following?: boolean; -}; diff --git a/types/mastodon/token.ts b/types/mastodon/token.ts deleted file mode 100644 index 0021a493..00000000 --- a/types/mastodon/token.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type Token = { - access_token: string; - token_type: string; - scope: string; - created_at: number; -}; diff --git a/types/mastodon/urls.ts b/types/mastodon/urls.ts deleted file mode 100644 index 59cca700..00000000 --- a/types/mastodon/urls.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type URLs = { - streaming_api: string; -};