From 37f68bbffd9c9db6a413ce5cdcd99f271abaab78 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sun, 30 Mar 2025 22:10:33 +0200 Subject: [PATCH] refactor(database): :heavy_minus_sign: Remove dependency on pg_uuidv7 extension --- CHANGELOG.md | 1 + api/api/auth/login/index.test.ts | 2 + api/api/auth/reset/index.test.ts | 2 + .../[id]/roles/[role_id]/index.test.ts | 4 +- api/api/v1/accounts/[id]/roles/index.test.ts | 2 + api/api/v1/apps/index.ts | 2 + api/api/v1/emojis/index.ts | 2 + api/api/v1/markers/index.ts | 3 + api/api/v1/push/subscription/index.post.ts | 2 + api/api/v1/push/subscription/index.test.ts | 5 + api/api/v1/roles/[id]/index.test.ts | 4 + api/api/v1/roles/index.test.ts | 2 + api/api/v1/roles/index.ts | 2 + api/api/v1/statuses/[id]/reblog.ts | 2 + api/api/v1/statuses/index.test.ts | 4 + api/api/v2/filters/index.ts | 3 + classes/database/emoji.ts | 2 + classes/database/instance.ts | 2 + classes/database/media.ts | 3 + classes/database/note.ts | 2 + classes/database/reaction.ts | 2 + classes/database/relationship.ts | 4 + classes/database/user.ts | 9 + cli/user/token.ts | 2 + drizzle/migrations/0048_chilly_vector.sql | 22 + drizzle/migrations/meta/0048_snapshot.json | 2341 +++++++++++++++++ drizzle/migrations/meta/_journal.json | 7 + drizzle/schema.ts | 3 +- plugins/openid/routes/authorize.test.ts | 2 + plugins/openid/routes/authorize.ts | 2 + plugins/openid/routes/jwks.test.ts | 2 + plugins/openid/routes/oauth/callback.ts | 4 + plugins/openid/routes/oauth/revoke.test.ts | 4 + plugins/openid/routes/oauth/sso.ts | 2 + plugins/openid/routes/oauth/token.test.ts | 4 + plugins/openid/routes/sso/index.ts | 3 + tests/utils.ts | 5 +- 37 files changed, 2465 insertions(+), 4 deletions(-) create mode 100644 drizzle/migrations/0048_chilly_vector.sql create mode 100644 drizzle/migrations/meta/0048_snapshot.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 849afc41..a179b19d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Versia Server now serves static files directly from a configurable path, and `ve ### Backend - [x] 🚀 Upgraded Bun to `1.2.7` +- [x] 🔥 Removed dependency on the `pg_uuidv7` extension. Versia Server can now be used with "vanilla" PostgreSQL. - [x] 🖼️ Simplified media pipeline: this will improve S3 performance - [ ] 📈 It is now possible to disable media proxying for your CDN (offloading considerable bandwidth to your more optimized CDN). - [x] 👷 Outbound federation, inbox processing, data fetching and media processing are now handled by a queue system. diff --git a/api/api/auth/login/index.test.ts b/api/api/auth/login/index.test.ts index b29028fe..a2c269c0 100644 --- a/api/api/auth/login/index.test.ts +++ b/api/api/auth/login/index.test.ts @@ -1,6 +1,7 @@ import { afterAll, describe, expect, test } from "bun:test"; import { randomString } from "@/math"; import { Application } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { config } from "~/config.ts"; import { fakeRequest, getTestUsers } from "~/tests/utils"; @@ -8,6 +9,7 @@ const { users, deleteUsers, passwords } = await getTestUsers(1); // Create application const application = await Application.insert({ + id: randomUUIDv7(), name: "Test Application", clientId: randomString(32, "hex"), secret: "test", diff --git a/api/api/auth/reset/index.test.ts b/api/api/auth/reset/index.test.ts index cd3e829e..a35a1977 100644 --- a/api/api/auth/reset/index.test.ts +++ b/api/api/auth/reset/index.test.ts @@ -1,6 +1,7 @@ import { afterAll, describe, expect, test } from "bun:test"; import { randomString } from "@/math"; import { Application } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { config } from "~/config.ts"; import { fakeRequest, getTestUsers } from "~/tests/utils"; @@ -10,6 +11,7 @@ const newPassword = randomString(16, "hex"); // Create application const application = await Application.insert({ + id: randomUUIDv7(), name: "Test Application", clientId: randomString(32, "hex"), secret: "test", diff --git a/api/api/v1/accounts/[id]/roles/[role_id]/index.test.ts b/api/api/v1/accounts/[id]/roles/[role_id]/index.test.ts index e3914169..02d10864 100644 --- a/api/api/v1/accounts/[id]/roles/[role_id]/index.test.ts +++ b/api/api/v1/accounts/[id]/roles/[role_id]/index.test.ts @@ -1,8 +1,8 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import { RolePermission } from "@versia/client/schemas"; import { Role } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { generateClient, getTestUsers } from "~/tests/utils"; - const { users, deleteUsers } = await getTestUsers(2); let role: Role; let higherPriorityRole: Role; @@ -10,6 +10,7 @@ let higherPriorityRole: Role; beforeAll(async () => { // Create new role role = await Role.insert({ + id: randomUUIDv7(), name: "test", permissions: [RolePermission.ManageRoles], priority: 2, @@ -24,6 +25,7 @@ beforeAll(async () => { // Create a role with higher priority than the user's role higherPriorityRole = await Role.insert({ + id: randomUUIDv7(), name: "higherPriorityRole", permissions: [RolePermission.ManageRoles], priority: 3, // Higher priority than the user's role diff --git a/api/api/v1/accounts/[id]/roles/index.test.ts b/api/api/v1/accounts/[id]/roles/index.test.ts index 3ff9bd15..b85cbf98 100644 --- a/api/api/v1/accounts/[id]/roles/index.test.ts +++ b/api/api/v1/accounts/[id]/roles/index.test.ts @@ -1,6 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import { RolePermission } from "@versia/client/schemas"; import { Role } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { generateClient, getTestUsers } from "~/tests/utils"; const { users, deleteUsers } = await getTestUsers(2); @@ -9,6 +10,7 @@ let role: Role; beforeAll(async () => { // Create new role role = await Role.insert({ + id: randomUUIDv7(), name: "test", permissions: [RolePermission.ManageRoles], priority: 2, diff --git a/api/api/v1/apps/index.ts b/api/api/v1/apps/index.ts index aeb097f6..bbe31b2b 100644 --- a/api/api/v1/apps/index.ts +++ b/api/api/v1/apps/index.ts @@ -5,6 +5,7 @@ import { CredentialApplication as CredentialApplicationSchema, } from "@versia/client/schemas"; import { Application } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { describeRoute } from "hono-openapi"; import { resolver, validator } from "hono-openapi/zod"; import { z } from "zod"; @@ -66,6 +67,7 @@ export default apiRoute((app) => context.req.valid("json"); const app = await Application.insert({ + id: randomUUIDv7(), name: client_name, redirectUri: redirect_uris.join("\n"), scopes: scopes.join(" "), diff --git a/api/api/v1/emojis/index.ts b/api/api/v1/emojis/index.ts index 57c198b2..9f9b74de 100644 --- a/api/api/v1/emojis/index.ts +++ b/api/api/v1/emojis/index.ts @@ -4,6 +4,7 @@ import { CustomEmoji as CustomEmojiSchema } from "@versia/client/schemas"; import { RolePermission } from "@versia/client/schemas"; import { Emoji, Media } from "@versia/kit/db"; import { Emojis } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { and, eq, isNull, or } from "drizzle-orm"; import { describeRoute } from "hono-openapi"; import { resolver, validator } from "hono-openapi/zod"; @@ -124,6 +125,7 @@ export default apiRoute((app) => }); const emoji = await Emoji.insert({ + id: randomUUIDv7(), shortcode, mediaId: media.id, visibleInPicker: true, diff --git a/api/api/v1/markers/index.ts b/api/api/v1/markers/index.ts index d353ce78..4bc1b48e 100644 --- a/api/api/v1/markers/index.ts +++ b/api/api/v1/markers/index.ts @@ -7,6 +7,7 @@ import { import { RolePermission } from "@versia/client/schemas"; import { db } from "@versia/kit/db"; import { Markers } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { type SQL, and, eq } from "drizzle-orm"; import { describeRoute } from "hono-openapi"; import { resolver, validator } from "hono-openapi/zod"; @@ -189,6 +190,7 @@ export default apiRoute((app) => { await db .insert(Markers) .values({ + id: randomUUIDv7(), userId: user.id, timeline: "home", noteId: homeId, @@ -218,6 +220,7 @@ export default apiRoute((app) => { await db .insert(Markers) .values({ + id: randomUUIDv7(), userId: user.id, timeline: "notifications", notificationId: notificationsId, diff --git a/api/api/v1/push/subscription/index.post.ts b/api/api/v1/push/subscription/index.post.ts index b4255228..47376416 100644 --- a/api/api/v1/push/subscription/index.post.ts +++ b/api/api/v1/push/subscription/index.post.ts @@ -6,6 +6,7 @@ import { } from "@versia/client/schemas"; import { RolePermission } from "@versia/client/schemas"; import { PushSubscription } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { describeRoute } from "hono-openapi"; import { resolver, validator } from "hono-openapi/zod"; import { ApiError } from "~/classes/errors/api-error"; @@ -64,6 +65,7 @@ export default apiRoute((app) => await PushSubscription.clearAllOfToken(token); const ps = await PushSubscription.insert({ + id: randomUUIDv7(), alerts: data.alerts, policy, endpoint: subscription.endpoint, diff --git a/api/api/v1/push/subscription/index.test.ts b/api/api/v1/push/subscription/index.test.ts index 29344980..0485c2df 100644 --- a/api/api/v1/push/subscription/index.test.ts +++ b/api/api/v1/push/subscription/index.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeEach, describe, expect, test } from "bun:test"; import { PushSubscription } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { generateClient, getTestUsers } from "~/tests/utils"; const { users, tokens, deleteUsers } = await getTestUsers(2); @@ -44,6 +45,7 @@ describe("/api/v1/push/subscriptions", () => { await using client = await generateClient(users[1]); await PushSubscription.insert({ + id: randomUUIDv7(), endpoint: "https://example.com", alerts: { update: true, @@ -76,6 +78,7 @@ describe("/api/v1/push/subscriptions", () => { await using client = await generateClient(users[0]); await PushSubscription.insert({ + id: randomUUIDv7(), endpoint: "https://example.com", alerts: { update: true, @@ -175,6 +178,7 @@ describe("/api/v1/push/subscriptions", () => { await using client = await generateClient(users[0]); await PushSubscription.insert({ + id: randomUUIDv7(), endpoint: "https://example.com", alerts: { update: true, @@ -217,6 +221,7 @@ describe("/api/v1/push/subscriptions", () => { await using client = await generateClient(users[0]); await PushSubscription.insert({ + id: randomUUIDv7(), endpoint: "https://example.com", alerts: { update: true, diff --git a/api/api/v1/roles/[id]/index.test.ts b/api/api/v1/roles/[id]/index.test.ts index 8102f0e1..f18f6f11 100644 --- a/api/api/v1/roles/[id]/index.test.ts +++ b/api/api/v1/roles/[id]/index.test.ts @@ -1,6 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import { RolePermission } from "@versia/client/schemas"; import { Role } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { generateClient, getTestUsers } from "~/tests/utils"; const { users, deleteUsers } = await getTestUsers(2); @@ -10,6 +11,7 @@ let higherPriorityRole: Role; beforeAll(async () => { // Create new role role = await Role.insert({ + id: randomUUIDv7(), name: "test", permissions: [RolePermission.ManageRoles], priority: 2, @@ -24,6 +26,7 @@ beforeAll(async () => { // Create a role with higher priority than the user's role higherPriorityRole = await Role.insert({ + id: randomUUIDv7(), name: "higherPriorityRole", permissions: [RolePermission.ManageRoles], priority: 3, // Higher priority than the user's role @@ -173,6 +176,7 @@ describe("/api/v1/roles/:id", () => { test("should delete role", async () => { const newRole = await Role.insert({ + id: randomUUIDv7(), name: "test2", permissions: [RolePermission.ManageRoles], priority: 2, diff --git a/api/api/v1/roles/index.test.ts b/api/api/v1/roles/index.test.ts index 6cd5c5c3..ae8cf568 100644 --- a/api/api/v1/roles/index.test.ts +++ b/api/api/v1/roles/index.test.ts @@ -1,6 +1,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import { RolePermission } from "@versia/client/schemas"; import { Role } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { config } from "~/config.ts"; import { generateClient, getTestUsers } from "~/tests/utils"; @@ -10,6 +11,7 @@ let role: Role; beforeAll(async () => { // Create new role role = await Role.insert({ + id: randomUUIDv7(), name: "test", permissions: [RolePermission.ManageRoles], priority: 10, diff --git a/api/api/v1/roles/index.ts b/api/api/v1/roles/index.ts index 343de167..cccda125 100644 --- a/api/api/v1/roles/index.ts +++ b/api/api/v1/roles/index.ts @@ -2,6 +2,7 @@ import { apiRoute, auth, handleZodError } from "@/api"; import { Role as RoleSchema } from "@versia/client/schemas"; import { RolePermission } from "@versia/client/schemas"; import { Role } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { describeRoute } from "hono-openapi"; import { resolver, validator } from "hono-openapi/zod"; import { z } from "zod"; @@ -105,6 +106,7 @@ export default apiRoute((app) => { } const newRole = await Role.insert({ + id: randomUUIDv7(), description, icon, name, diff --git a/api/api/v1/statuses/[id]/reblog.ts b/api/api/v1/statuses/[id]/reblog.ts index 30dc7c59..433419e5 100644 --- a/api/api/v1/statuses/[id]/reblog.ts +++ b/api/api/v1/statuses/[id]/reblog.ts @@ -3,6 +3,7 @@ import { Status as StatusSchema } from "@versia/client/schemas"; import { RolePermission } from "@versia/client/schemas"; import { Note } from "@versia/kit/db"; import { Notes } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { and, eq } from "drizzle-orm"; import { describeRoute } from "hono-openapi"; import { resolver, validator } from "hono-openapi/zod"; @@ -66,6 +67,7 @@ export default apiRoute((app) => } const newReblog = await Note.insert({ + id: randomUUIDv7(), authorId: user.id, reblogId: note.data.id, visibility, diff --git a/api/api/v1/statuses/index.test.ts b/api/api/v1/statuses/index.test.ts index 57b43dc5..6f6cc6e2 100644 --- a/api/api/v1/statuses/index.test.ts +++ b/api/api/v1/statuses/index.test.ts @@ -2,6 +2,7 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import type { Status } from "@versia/client/schemas"; import { Media, db } from "@versia/kit/db"; import { Emojis } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { eq } from "drizzle-orm"; import type { z } from "zod"; import { config } from "~/config.ts"; @@ -17,6 +18,7 @@ afterAll(async () => { beforeAll(async () => { media = await Media.insert({ + id: randomUUIDv7(), content: { "image/png": { content: "https://example.com/test.png", @@ -24,7 +26,9 @@ beforeAll(async () => { }, }, }); + await db.insert(Emojis).values({ + id: randomUUIDv7(), shortcode: "test", mediaId: media.id, visibleInPicker: true, diff --git a/api/api/v2/filters/index.ts b/api/api/v2/filters/index.ts index c98f13ef..8e4e7097 100644 --- a/api/api/v2/filters/index.ts +++ b/api/api/v2/filters/index.ts @@ -6,6 +6,7 @@ import { import { RolePermission } from "@versia/client/schemas"; import { db } from "@versia/kit/db"; import { FilterKeywords, Filters } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import type { SQL } from "drizzle-orm"; import { describeRoute } from "hono-openapi"; import { resolver, validator } from "hono-openapi/zod"; @@ -139,6 +140,7 @@ export default apiRoute((app) => { await db .insert(Filters) .values({ + id: randomUUIDv7(), title, context: ctx, filterAction: filter_action, @@ -160,6 +162,7 @@ export default apiRoute((app) => { .insert(FilterKeywords) .values( keywords_attributes?.map((keyword) => ({ + id: randomUUIDv7(), filterId: newFilter.id, keyword: keyword.keyword, wholeWord: keyword.whole_word ?? false, diff --git a/classes/database/emoji.ts b/classes/database/emoji.ts index 0f7904c1..14da1e69 100644 --- a/classes/database/emoji.ts +++ b/classes/database/emoji.ts @@ -4,6 +4,7 @@ import type { CustomEmoji } from "@versia/client/schemas"; import type { CustomEmojiExtension } from "@versia/federation/types"; import { type Instance, Media, db } from "@versia/kit/db"; import { Emojis, type Instances, type Medias } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { type InferInsertModel, type InferSelectModel, @@ -212,6 +213,7 @@ export class Emoji extends BaseInterface { const media = await Media.fromVersia(emoji.url); return Emoji.insert({ + id: randomUUIDv7(), shortcode, mediaId: media.id, visibleInPicker: true, diff --git a/classes/database/instance.ts b/classes/database/instance.ts index 26433542..6302aaf2 100644 --- a/classes/database/instance.ts +++ b/classes/database/instance.ts @@ -3,6 +3,7 @@ import { EntityValidator, type ResponseError } from "@versia/federation"; import type { InstanceMetadata } from "@versia/federation/types"; import { db } from "@versia/kit/db"; import { Instances } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import chalk from "chalk"; import { type InferInsertModel, @@ -337,6 +338,7 @@ export class Instance extends BaseInterface { const { metadata, protocol } = output; return Instance.insert({ + id: randomUUIDv7(), baseUrl: host, name: metadata.name, version: metadata.software.version, diff --git a/classes/database/media.ts b/classes/database/media.ts index bc998eef..1e90dfcf 100644 --- a/classes/database/media.ts +++ b/classes/database/media.ts @@ -200,6 +200,7 @@ export class Media extends BaseInterface { : undefined; const newAttachment = await Media.insert({ + id: randomUUIDv7(), content, thumbnail: thumbnailContent, }); @@ -242,6 +243,7 @@ export class Media extends BaseInterface { }; const newAttachment = await Media.insert({ + id: randomUUIDv7(), content, }); @@ -525,6 +527,7 @@ export class Media extends BaseInterface { public static fromVersia(contentFormat: ContentFormat): Promise { return Media.insert({ + id: randomUUIDv7(), content: contentFormat, originalContent: contentFormat, }); diff --git a/classes/database/note.ts b/classes/database/note.ts index 6a96439c..66adc099 100644 --- a/classes/database/note.ts +++ b/classes/database/note.ts @@ -18,6 +18,7 @@ import { Notes, Users, } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { type InferInsertModel, type InferSelectModel, @@ -369,6 +370,7 @@ export class Note extends BaseInterface { const htmlContent = await contentToHtml(data.content, parsedMentions); const newNote = await Note.insert({ + id: randomUUIDv7(), authorId: data.author.id, content: htmlContent, contentSource: diff --git a/classes/database/reaction.ts b/classes/database/reaction.ts index 48f08ebf..63d4fc2d 100644 --- a/classes/database/reaction.ts +++ b/classes/database/reaction.ts @@ -1,6 +1,7 @@ import type { ReactionExtension } from "@versia/federation/types"; import { Emoji, Instance, type Note, User, db } from "@versia/kit/db"; import { type Notes, Reactions, type Users } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { type InferInsertModel, type InferSelectModel, @@ -231,6 +232,7 @@ export class Reaction extends BaseInterface { : null; return Reaction.insert({ + id: randomUUIDv7(), uri: reactionToConvert.uri, authorId: author.id, noteId: note.id, diff --git a/classes/database/relationship.ts b/classes/database/relationship.ts index 9c30a595..ac3aec72 100644 --- a/classes/database/relationship.ts +++ b/classes/database/relationship.ts @@ -1,6 +1,7 @@ import type { Relationship as RelationshipSchema } from "@versia/client/schemas"; import { db } from "@versia/kit/db"; import { Relationships } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { type InferInsertModel, type InferSelectModel, @@ -83,6 +84,7 @@ export class Relationship extends BaseInterface< if (!found) { // Create a new relationship if one doesn't exist return await Relationship.insert({ + id: randomUUIDv7(), ownerId: owner.id, subjectId: subject.id, languages: [], @@ -119,6 +121,7 @@ export class Relationship extends BaseInterface< for (const subjectId of missingSubjectsIds) { await Relationship.insert({ + id: randomUUIDv7(), ownerId: owner.id, subjectId, languages: [], @@ -213,6 +216,7 @@ export class Relationship extends BaseInterface< await db .insert(Relationships) .values({ + id: randomUUIDv7(), ownerId: oppositeTo.subjectId, subjectId: oppositeTo.ownerId, languages: [], diff --git a/classes/database/user.ts b/classes/database/user.ts index 0a4ac350..28858db3 100644 --- a/classes/database/user.ts +++ b/classes/database/user.ts @@ -33,6 +33,7 @@ import { UserToPinnedNotes, Users, } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import chalk from "chalk"; import { type InferInsertModel, @@ -471,6 +472,7 @@ export class User extends BaseInterface { } const newLike = await Like.insert({ + id: randomUUIDv7(), likerId: this.id, likedId: note.id, uri, @@ -520,6 +522,7 @@ export class User extends BaseInterface { note?: Note, ): Promise { const notification = await Notification.insert({ + id: randomUUIDv7(), accountId: relatedUser.id, type, notifiedId: this.id, @@ -723,6 +726,7 @@ export class User extends BaseInterface { ); } else { avatar = await Media.insert({ + id: randomUUIDv7(), content: user.avatar, }); } @@ -737,6 +741,7 @@ export class User extends BaseInterface { ); } else { header = await Media.insert({ + id: randomUUIDv7(), content: user.header, }); } @@ -755,17 +760,20 @@ export class User extends BaseInterface { // Else, create a new user const avatar = user.avatar ? await Media.insert({ + id: randomUUIDv7(), content: user.avatar, }) : null; const header = user.header ? await Media.insert({ + id: randomUUIDv7(), content: user.header, }) : null; const newUser = await User.insert({ + id: randomUUIDv7(), ...data, avatarId: avatar?.id, headerId: header?.id, @@ -876,6 +884,7 @@ export class User extends BaseInterface { await db .insert(Users) .values({ + id: randomUUIDv7(), username: data.username, displayName: data.display_name ?? data.username, password: diff --git a/cli/user/token.ts b/cli/user/token.ts index 3e237005..20b35155 100644 --- a/cli/user/token.ts +++ b/cli/user/token.ts @@ -1,4 +1,5 @@ import { randomString } from "@/math.ts"; +import { randomUUIDv7 } from "bun"; import chalk from "chalk"; // @ts-expect-error - Root import is required or the Clec type definitions won't work // biome-ignore lint/correctness/noUnusedImports: Root import is required or the Clec type definitions won't work @@ -22,6 +23,7 @@ export const generateTokenCommand = defineCommand( } const token = await Token.insert({ + id: randomUUIDv7(), accessToken: randomString(64, "base64url"), code: null, scope: "read write follow", diff --git a/drizzle/migrations/0048_chilly_vector.sql b/drizzle/migrations/0048_chilly_vector.sql new file mode 100644 index 00000000..e82ebeb8 --- /dev/null +++ b/drizzle/migrations/0048_chilly_vector.sql @@ -0,0 +1,22 @@ +ALTER TABLE "Applications" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Challenges" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Emojis" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "FilterKeywords" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Filters" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Flags" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Instances" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Likes" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Markers" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Medias" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "ModNotes" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "ModTags" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Notes" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Notifications" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "OpenIdAccounts" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "OpenIdLoginFlows" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "PushSubscriptions" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Reaction" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Relationships" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Roles" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Tokens" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "Users" ALTER COLUMN "id" DROP DEFAULT; \ No newline at end of file diff --git a/drizzle/migrations/meta/0048_snapshot.json b/drizzle/migrations/meta/0048_snapshot.json new file mode 100644 index 00000000..36de4704 --- /dev/null +++ b/drizzle/migrations/meta/0048_snapshot.json @@ -0,0 +1,2341 @@ +{ + "id": "3d550e4c-d07c-43f7-b511-0ead30032540", + "prevId": "c03419b8-3ff7-4e43-a273-9681c4ce61e1", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.Applications": { + "name": "Applications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "website": { + "name": "website", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "vapid_key": { + "name": "vapid_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scopes": { + "name": "scopes", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "redirect_uri": { + "name": "redirect_uri", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "Applications_client_id_index": { + "name": "Applications_client_id_index", + "columns": [ + { + "expression": "client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Challenges": { + "name": "Challenges", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "challenge": { + "name": "challenge", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "NOW() + INTERVAL '5 minutes'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.EmojiToNote": { + "name": "EmojiToNote", + "schema": "", + "columns": { + "emojiId": { + "name": "emojiId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "noteId": { + "name": "noteId", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "EmojiToNote_emojiId_noteId_index": { + "name": "EmojiToNote_emojiId_noteId_index", + "columns": [ + { + "expression": "emojiId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "noteId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "EmojiToNote_noteId_index": { + "name": "EmojiToNote_noteId_index", + "columns": [ + { + "expression": "noteId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "EmojiToNote_emojiId_Emojis_id_fk": { + "name": "EmojiToNote_emojiId_Emojis_id_fk", + "tableFrom": "EmojiToNote", + "tableTo": "Emojis", + "columnsFrom": ["emojiId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "EmojiToNote_noteId_Notes_id_fk": { + "name": "EmojiToNote_noteId_Notes_id_fk", + "tableFrom": "EmojiToNote", + "tableTo": "Notes", + "columnsFrom": ["noteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.EmojiToUser": { + "name": "EmojiToUser", + "schema": "", + "columns": { + "emojiId": { + "name": "emojiId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "EmojiToUser_emojiId_userId_index": { + "name": "EmojiToUser_emojiId_userId_index", + "columns": [ + { + "expression": "emojiId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "EmojiToUser_userId_index": { + "name": "EmojiToUser_userId_index", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "EmojiToUser_emojiId_Emojis_id_fk": { + "name": "EmojiToUser_emojiId_Emojis_id_fk", + "tableFrom": "EmojiToUser", + "tableTo": "Emojis", + "columnsFrom": ["emojiId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "EmojiToUser_userId_Users_id_fk": { + "name": "EmojiToUser_userId_Users_id_fk", + "tableFrom": "EmojiToUser", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Emojis": { + "name": "Emojis", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "shortcode": { + "name": "shortcode", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mediaId": { + "name": "mediaId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "visible_in_picker": { + "name": "visible_in_picker", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "instanceId": { + "name": "instanceId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "ownerId": { + "name": "ownerId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "category": { + "name": "category", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "Emojis_mediaId_Medias_id_fk": { + "name": "Emojis_mediaId_Medias_id_fk", + "tableFrom": "Emojis", + "tableTo": "Medias", + "columnsFrom": ["mediaId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Emojis_instanceId_Instances_id_fk": { + "name": "Emojis_instanceId_Instances_id_fk", + "tableFrom": "Emojis", + "tableTo": "Instances", + "columnsFrom": ["instanceId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Emojis_ownerId_Users_id_fk": { + "name": "Emojis_ownerId_Users_id_fk", + "tableFrom": "Emojis", + "tableTo": "Users", + "columnsFrom": ["ownerId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.FilterKeywords": { + "name": "FilterKeywords", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "filterId": { + "name": "filterId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "keyword": { + "name": "keyword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "whole_word": { + "name": "whole_word", + "type": "boolean", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "FilterKeywords_filterId_Filters_id_fk": { + "name": "FilterKeywords_filterId_Filters_id_fk", + "tableFrom": "FilterKeywords", + "tableTo": "Filters", + "columnsFrom": ["filterId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Filters": { + "name": "Filters", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "context": { + "name": "context", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "filter_action": { + "name": "filter_action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "Filters_userId_Users_id_fk": { + "name": "Filters_userId_Users_id_fk", + "tableFrom": "Filters", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Flags": { + "name": "Flags", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "flag_type": { + "name": "flag_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'other'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "noteId": { + "name": "noteId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "Flags_noteId_Notes_id_fk": { + "name": "Flags_noteId_Notes_id_fk", + "tableFrom": "Flags", + "tableTo": "Notes", + "columnsFrom": ["noteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Flags_userId_Users_id_fk": { + "name": "Flags_userId_Users_id_fk", + "tableFrom": "Flags", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Instances": { + "name": "Instances", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "base_url": { + "name": "base_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "logo": { + "name": "logo", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "disable_automoderation": { + "name": "disable_automoderation", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "protocol": { + "name": "protocol", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'versia'" + }, + "inbox": { + "name": "inbox", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "extensions": { + "name": "extensions", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Likes": { + "name": "Likes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "uri": { + "name": "uri", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "likerId": { + "name": "likerId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "likedId": { + "name": "likedId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "Likes_likerId_Users_id_fk": { + "name": "Likes_likerId_Users_id_fk", + "tableFrom": "Likes", + "tableTo": "Users", + "columnsFrom": ["likerId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Likes_likedId_Notes_id_fk": { + "name": "Likes_likedId_Notes_id_fk", + "tableFrom": "Likes", + "tableTo": "Notes", + "columnsFrom": ["likedId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "Likes_uri_unique": { + "name": "Likes_uri_unique", + "nullsNotDistinct": false, + "columns": ["uri"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Markers": { + "name": "Markers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "noteId": { + "name": "noteId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "notificationId": { + "name": "notificationId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "timeline": { + "name": "timeline", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "Markers_noteId_Notes_id_fk": { + "name": "Markers_noteId_Notes_id_fk", + "tableFrom": "Markers", + "tableTo": "Notes", + "columnsFrom": ["noteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Markers_notificationId_Notifications_id_fk": { + "name": "Markers_notificationId_Notifications_id_fk", + "tableFrom": "Markers", + "tableTo": "Notifications", + "columnsFrom": ["notificationId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Markers_userId_Users_id_fk": { + "name": "Markers_userId_Users_id_fk", + "tableFrom": "Markers", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Medias": { + "name": "Medias", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "content": { + "name": "content", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "original_content": { + "name": "original_content", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "thumbnail": { + "name": "thumbnail", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "blurhash": { + "name": "blurhash", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.MediasToNote": { + "name": "MediasToNote", + "schema": "", + "columns": { + "mediaId": { + "name": "mediaId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "noteId": { + "name": "noteId", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "MediasToNote_mediaId_index": { + "name": "MediasToNote_mediaId_index", + "columns": [ + { + "expression": "mediaId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "MediasToNote_noteId_index": { + "name": "MediasToNote_noteId_index", + "columns": [ + { + "expression": "noteId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "MediasToNote_mediaId_Medias_id_fk": { + "name": "MediasToNote_mediaId_Medias_id_fk", + "tableFrom": "MediasToNote", + "tableTo": "Medias", + "columnsFrom": ["mediaId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "MediasToNote_noteId_Notes_id_fk": { + "name": "MediasToNote_noteId_Notes_id_fk", + "tableFrom": "MediasToNote", + "tableTo": "Notes", + "columnsFrom": ["noteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ModNotes": { + "name": "ModNotes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "noteId": { + "name": "noteId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "modId": { + "name": "modId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "ModNotes_noteId_Notes_id_fk": { + "name": "ModNotes_noteId_Notes_id_fk", + "tableFrom": "ModNotes", + "tableTo": "Notes", + "columnsFrom": ["noteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "ModNotes_userId_Users_id_fk": { + "name": "ModNotes_userId_Users_id_fk", + "tableFrom": "ModNotes", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "ModNotes_modId_Users_id_fk": { + "name": "ModNotes_modId_Users_id_fk", + "tableFrom": "ModNotes", + "tableTo": "Users", + "columnsFrom": ["modId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ModTags": { + "name": "ModTags", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "noteId": { + "name": "noteId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "modId": { + "name": "modId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "ModTags_noteId_Notes_id_fk": { + "name": "ModTags_noteId_Notes_id_fk", + "tableFrom": "ModTags", + "tableTo": "Notes", + "columnsFrom": ["noteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "ModTags_userId_Users_id_fk": { + "name": "ModTags_userId_Users_id_fk", + "tableFrom": "ModTags", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "ModTags_modId_Users_id_fk": { + "name": "ModTags_modId_Users_id_fk", + "tableFrom": "ModTags", + "tableTo": "Users", + "columnsFrom": ["modId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.NoteToMentions": { + "name": "NoteToMentions", + "schema": "", + "columns": { + "noteId": { + "name": "noteId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "NoteToMentions_noteId_userId_index": { + "name": "NoteToMentions_noteId_userId_index", + "columns": [ + { + "expression": "noteId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "NoteToMentions_userId_index": { + "name": "NoteToMentions_userId_index", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "NoteToMentions_noteId_Notes_id_fk": { + "name": "NoteToMentions_noteId_Notes_id_fk", + "tableFrom": "NoteToMentions", + "tableTo": "Notes", + "columnsFrom": ["noteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "NoteToMentions_userId_Users_id_fk": { + "name": "NoteToMentions_userId_Users_id_fk", + "tableFrom": "NoteToMentions", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Notes": { + "name": "Notes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "uri": { + "name": "uri", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "authorId": { + "name": "authorId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "reblogId": { + "name": "reblogId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text/plain'" + }, + "visibility": { + "name": "visibility", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "replyId": { + "name": "replyId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "quoteId": { + "name": "quoteId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "sensitive": { + "name": "sensitive", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "spoiler_text": { + "name": "spoiler_text", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "applicationId": { + "name": "applicationId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "content_source": { + "name": "content_source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + } + }, + "indexes": {}, + "foreignKeys": { + "Notes_authorId_Users_id_fk": { + "name": "Notes_authorId_Users_id_fk", + "tableFrom": "Notes", + "tableTo": "Users", + "columnsFrom": ["authorId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Notes_reblogId_Notes_id_fk": { + "name": "Notes_reblogId_Notes_id_fk", + "tableFrom": "Notes", + "tableTo": "Notes", + "columnsFrom": ["reblogId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Notes_replyId_Notes_id_fk": { + "name": "Notes_replyId_Notes_id_fk", + "tableFrom": "Notes", + "tableTo": "Notes", + "columnsFrom": ["replyId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Notes_quoteId_Notes_id_fk": { + "name": "Notes_quoteId_Notes_id_fk", + "tableFrom": "Notes", + "tableTo": "Notes", + "columnsFrom": ["quoteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Notes_applicationId_Applications_id_fk": { + "name": "Notes_applicationId_Applications_id_fk", + "tableFrom": "Notes", + "tableTo": "Applications", + "columnsFrom": ["applicationId"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "Notes_uri_unique": { + "name": "Notes_uri_unique", + "nullsNotDistinct": false, + "columns": ["uri"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Notifications": { + "name": "Notifications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "notifiedId": { + "name": "notifiedId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "accountId": { + "name": "accountId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "noteId": { + "name": "noteId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "dismissed": { + "name": "dismissed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "Notifications_notifiedId_Users_id_fk": { + "name": "Notifications_notifiedId_Users_id_fk", + "tableFrom": "Notifications", + "tableTo": "Users", + "columnsFrom": ["notifiedId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Notifications_accountId_Users_id_fk": { + "name": "Notifications_accountId_Users_id_fk", + "tableFrom": "Notifications", + "tableTo": "Users", + "columnsFrom": ["accountId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Notifications_noteId_Notes_id_fk": { + "name": "Notifications_noteId_Notes_id_fk", + "tableFrom": "Notifications", + "tableTo": "Notes", + "columnsFrom": ["noteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.OpenIdAccounts": { + "name": "OpenIdAccounts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "server_id": { + "name": "server_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "issuer_id": { + "name": "issuer_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "OpenIdAccounts_userId_Users_id_fk": { + "name": "OpenIdAccounts_userId_Users_id_fk", + "tableFrom": "OpenIdAccounts", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.OpenIdLoginFlows": { + "name": "OpenIdLoginFlows", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "code_verifier": { + "name": "code_verifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "issuer_id": { + "name": "issuer_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "OpenIdLoginFlows_applicationId_Applications_id_fk": { + "name": "OpenIdLoginFlows_applicationId_Applications_id_fk", + "tableFrom": "OpenIdLoginFlows", + "tableTo": "Applications", + "columnsFrom": ["applicationId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.PushSubscriptions": { + "name": "PushSubscriptions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "auth_secret": { + "name": "auth_secret", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "alerts": { + "name": "alerts", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "policy": { + "name": "policy", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "tokenId": { + "name": "tokenId", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "PushSubscriptions_tokenId_Tokens_id_fk": { + "name": "PushSubscriptions_tokenId_Tokens_id_fk", + "tableFrom": "PushSubscriptions", + "tableTo": "Tokens", + "columnsFrom": ["tokenId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "PushSubscriptions_tokenId_unique": { + "name": "PushSubscriptions_tokenId_unique", + "nullsNotDistinct": false, + "columns": ["tokenId"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Reaction": { + "name": "Reaction", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "uri": { + "name": "uri", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "emojiId": { + "name": "emojiId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "emoji_text": { + "name": "emoji_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "noteId": { + "name": "noteId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "authorId": { + "name": "authorId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "Reaction_emojiId_Emojis_id_fk": { + "name": "Reaction_emojiId_Emojis_id_fk", + "tableFrom": "Reaction", + "tableTo": "Emojis", + "columnsFrom": ["emojiId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Reaction_noteId_Notes_id_fk": { + "name": "Reaction_noteId_Notes_id_fk", + "tableFrom": "Reaction", + "tableTo": "Notes", + "columnsFrom": ["noteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Reaction_authorId_Users_id_fk": { + "name": "Reaction_authorId_Users_id_fk", + "tableFrom": "Reaction", + "tableTo": "Users", + "columnsFrom": ["authorId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "Reaction_uri_unique": { + "name": "Reaction_uri_unique", + "nullsNotDistinct": false, + "columns": ["uri"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Relationships": { + "name": "Relationships", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "ownerId": { + "name": "ownerId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "subjectId": { + "name": "subjectId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "following": { + "name": "following", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "showing_reblogs": { + "name": "showing_reblogs", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "notifying": { + "name": "notifying", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "blocking": { + "name": "blocking", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "muting": { + "name": "muting", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "muting_notifications": { + "name": "muting_notifications", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "requested": { + "name": "requested", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "domain_blocking": { + "name": "domain_blocking", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "endorsed": { + "name": "endorsed", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "languages": { + "name": "languages", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "Relationships_ownerId_Users_id_fk": { + "name": "Relationships_ownerId_Users_id_fk", + "tableFrom": "Relationships", + "tableTo": "Users", + "columnsFrom": ["ownerId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Relationships_subjectId_Users_id_fk": { + "name": "Relationships_subjectId_Users_id_fk", + "tableFrom": "Relationships", + "tableTo": "Users", + "columnsFrom": ["subjectId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.RoleToUsers": { + "name": "RoleToUsers", + "schema": "", + "columns": { + "roleId": { + "name": "roleId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "RoleToUsers_roleId_Roles_id_fk": { + "name": "RoleToUsers_roleId_Roles_id_fk", + "tableFrom": "RoleToUsers", + "tableTo": "Roles", + "columnsFrom": ["roleId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "RoleToUsers_userId_Users_id_fk": { + "name": "RoleToUsers_userId_Users_id_fk", + "tableFrom": "RoleToUsers", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Roles": { + "name": "Roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "priority": { + "name": "priority", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "visible": { + "name": "visible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Tokens": { + "name": "Tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "redirect_uri": { + "name": "redirect_uri", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "Tokens_userId_Users_id_fk": { + "name": "Tokens_userId_Users_id_fk", + "tableFrom": "Tokens", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Tokens_applicationId_Applications_id_fk": { + "name": "Tokens_applicationId_Applications_id_fk", + "tableFrom": "Tokens", + "tableTo": "Applications", + "columnsFrom": ["applicationId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.UserToPinnedNotes": { + "name": "UserToPinnedNotes", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "noteId": { + "name": "noteId", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "UserToPinnedNotes_userId_noteId_index": { + "name": "UserToPinnedNotes_userId_noteId_index", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "noteId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "UserToPinnedNotes_noteId_index": { + "name": "UserToPinnedNotes_noteId_index", + "columns": [ + { + "expression": "noteId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "UserToPinnedNotes_userId_Users_id_fk": { + "name": "UserToPinnedNotes_userId_Users_id_fk", + "tableFrom": "UserToPinnedNotes", + "tableTo": "Users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "UserToPinnedNotes_noteId_Notes_id_fk": { + "name": "UserToPinnedNotes_noteId_Notes_id_fk", + "tableFrom": "UserToPinnedNotes", + "tableTo": "Notes", + "columnsFrom": ["noteId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.Users": { + "name": "Users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "uri": { + "name": "uri", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "email_verification_token": { + "name": "email_verification_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password_reset_token": { + "name": "password_reset_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fields": { + "name": "fields", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "endpoints": { + "name": "endpoints", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "avatarId": { + "name": "avatarId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "headerId": { + "name": "headerId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "is_bot": { + "name": "is_bot", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_locked": { + "name": "is_locked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_discoverable": { + "name": "is_discoverable", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_hiding_collections": { + "name": "is_hiding_collections", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_indexable": { + "name": "is_indexable", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "sanctions": { + "name": "sanctions", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "instanceId": { + "name": "instanceId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "disable_automoderation": { + "name": "disable_automoderation", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "Users_uri_index": { + "name": "Users_uri_index", + "columns": [ + { + "expression": "uri", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "Users_username_index": { + "name": "Users_username_index", + "columns": [ + { + "expression": "username", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "Users_email_index": { + "name": "Users_email_index", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "Users_avatarId_Medias_id_fk": { + "name": "Users_avatarId_Medias_id_fk", + "tableFrom": "Users", + "tableTo": "Medias", + "columnsFrom": ["avatarId"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "Users_headerId_Medias_id_fk": { + "name": "Users_headerId_Medias_id_fk", + "tableFrom": "Users", + "tableTo": "Medias", + "columnsFrom": ["headerId"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "Users_instanceId_Instances_id_fk": { + "name": "Users_instanceId_Instances_id_fk", + "tableFrom": "Users", + "tableTo": "Instances", + "columnsFrom": ["instanceId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "Users_uri_unique": { + "name": "Users_uri_unique", + "nullsNotDistinct": false, + "columns": ["uri"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/drizzle/migrations/meta/_journal.json b/drizzle/migrations/meta/_journal.json index f2d6c60b..c22b687e 100644 --- a/drizzle/migrations/meta/_journal.json +++ b/drizzle/migrations/meta/_journal.json @@ -337,6 +337,13 @@ "when": 1743359397906, "tag": "0047_black_vermin", "breakpoints": true + }, + { + "idx": 48, + "version": "7", + "when": 1743365238468, + "tag": "0048_chilly_vector", + "breakpoints": true } ] } diff --git a/drizzle/schema.ts b/drizzle/schema.ts index abdbe3b5..0b95d7d4 100644 --- a/drizzle/schema.ts +++ b/drizzle/schema.ts @@ -37,8 +37,7 @@ const updatedAt = () => const uri = () => text("uri").unique(); // biome-ignore lint/nursery/useExplicitType: Type is too complex -const id = () => - uuid("id").default(sql`uuid_generate_v7()`).primaryKey().notNull(); +const id = () => uuid("id").primaryKey().notNull(); export const Challenges = pgTable("Challenges", { id: id(), diff --git a/plugins/openid/routes/authorize.test.ts b/plugins/openid/routes/authorize.test.ts index a2e41527..9bafe6b2 100644 --- a/plugins/openid/routes/authorize.test.ts +++ b/plugins/openid/routes/authorize.test.ts @@ -2,6 +2,7 @@ import { afterAll, describe, expect, test } from "bun:test"; import { randomString } from "@/math"; import { RolePermission } from "@versia/client/schemas"; import { Application } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { SignJWT } from "jose"; import { config } from "~/config.ts"; import { fakeRequest, getTestUsers } from "~/tests/utils"; @@ -19,6 +20,7 @@ const privateKey = await crypto.subtle.importKey( ); const application = await Application.insert({ + id: randomUUIDv7(), clientId: "test-client-id", redirectUri: "https://example.com/callback", scopes: "openid profile email", diff --git a/plugins/openid/routes/authorize.ts b/plugins/openid/routes/authorize.ts index a0e9706c..f3365fe9 100644 --- a/plugins/openid/routes/authorize.ts +++ b/plugins/openid/routes/authorize.ts @@ -2,6 +2,7 @@ import { auth, handleZodError, jsonOrForm } from "@/api"; import { randomString } from "@/math"; import { RolePermission } from "@versia/client/schemas"; import { Application, Token, User } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { describeRoute } from "hono-openapi"; import { validator } from "hono-openapi/zod"; import { type JWTPayload, SignJWT, jwtVerify } from "jose"; @@ -241,6 +242,7 @@ export default (plugin: PluginType): void => .sign(keys.private); await Token.insert({ + id: randomUUIDv7(), accessToken: randomString(64, "base64url"), code, scope: scope ?? application.data.scopes, diff --git a/plugins/openid/routes/jwks.test.ts b/plugins/openid/routes/jwks.test.ts index 45342c89..876769c1 100644 --- a/plugins/openid/routes/jwks.test.ts +++ b/plugins/openid/routes/jwks.test.ts @@ -1,8 +1,10 @@ import { afterAll, describe, expect, test } from "bun:test"; import { Application } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { fakeRequest } from "~/tests/utils"; const application = await Application.insert({ + id: randomUUIDv7(), clientId: "test-client-id", redirectUri: "https://example.com/callback", scopes: "openid profile email", diff --git a/plugins/openid/routes/oauth/callback.ts b/plugins/openid/routes/oauth/callback.ts index 929047df..2f7c6bff 100644 --- a/plugins/openid/routes/oauth/callback.ts +++ b/plugins/openid/routes/oauth/callback.ts @@ -5,6 +5,7 @@ import { RolePermission } from "@versia/client/schemas"; import { Media, Token, User, db } from "@versia/kit/db"; import { type SQL, and, eq, isNull } from "@versia/kit/drizzle"; import { OpenIdAccounts, Users } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { describeRoute } from "hono-openapi"; import { validator } from "hono-openapi/zod"; import { setCookie } from "hono/cookie"; @@ -175,6 +176,7 @@ export default (plugin: PluginType): void => { // Link the account await db.insert(OpenIdAccounts).values({ + id: randomUUIDv7(), serverId: sub, issuerId: issuer.id, userId: user_id, @@ -242,6 +244,7 @@ export default (plugin: PluginType): void => { // Link account await db.insert(OpenIdAccounts).values({ + id: randomUUIDv7(), serverId: sub, issuerId: issuer.id, userId: user.id, @@ -294,6 +297,7 @@ export default (plugin: PluginType): void => { const code = randomString(32, "hex"); await Token.insert({ + id: randomUUIDv7(), accessToken: randomString(64, "base64url"), code, scope: flow.application.scopes, diff --git a/plugins/openid/routes/oauth/revoke.test.ts b/plugins/openid/routes/oauth/revoke.test.ts index 2d520be0..14a74d45 100644 --- a/plugins/openid/routes/oauth/revoke.test.ts +++ b/plugins/openid/routes/oauth/revoke.test.ts @@ -1,17 +1,21 @@ import { afterAll, describe, expect, test } from "bun:test"; import { Application, Token } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { fakeRequest, getTestUsers } from "~/tests/utils"; const { deleteUsers, users } = await getTestUsers(1); const application = await Application.insert({ + id: randomUUIDv7(), clientId: "test-client-id", redirectUri: "https://example.com/callback", scopes: "openid profile email", secret: "test-secret", name: "Test Application", }); + const token = await Token.insert({ + id: randomUUIDv7(), code: "test-code", redirectUri: application.data.redirectUri, clientId: application.data.clientId, diff --git a/plugins/openid/routes/oauth/sso.ts b/plugins/openid/routes/oauth/sso.ts index a18445ad..f3c98cf4 100644 --- a/plugins/openid/routes/oauth/sso.ts +++ b/plugins/openid/routes/oauth/sso.ts @@ -1,6 +1,7 @@ import { handleZodError } from "@/api.ts"; import { Application, db } from "@versia/kit/db"; import { OpenIdLoginFlows } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { describeRoute } from "hono-openapi"; import { validator } from "hono-openapi/zod"; import { @@ -103,6 +104,7 @@ export default (plugin: PluginType): void => { await db .insert(OpenIdLoginFlows) .values({ + id: randomUUIDv7(), codeVerifier, applicationId: application.id, issuerId, diff --git a/plugins/openid/routes/oauth/token.test.ts b/plugins/openid/routes/oauth/token.test.ts index da02b019..f30d5ab6 100644 --- a/plugins/openid/routes/oauth/token.test.ts +++ b/plugins/openid/routes/oauth/token.test.ts @@ -1,17 +1,21 @@ import { afterAll, describe, expect, test } from "bun:test"; import { Application, Token } from "@versia/kit/db"; +import { randomUUIDv7 } from "bun"; import { fakeRequest, getTestUsers } from "~/tests/utils"; const { deleteUsers, users } = await getTestUsers(1); const application = await Application.insert({ + id: randomUUIDv7(), clientId: "test-client-id", redirectUri: "https://example.com/callback", scopes: "openid profile email", secret: "test-secret", name: "Test Application", }); + const token = await Token.insert({ + id: randomUUIDv7(), code: "test-code", redirectUri: application.data.redirectUri, clientId: application.data.clientId, diff --git a/plugins/openid/routes/sso/index.ts b/plugins/openid/routes/sso/index.ts index 7c172a7b..7a48d126 100644 --- a/plugins/openid/routes/sso/index.ts +++ b/plugins/openid/routes/sso/index.ts @@ -2,6 +2,7 @@ import { auth, handleZodError } from "@/api"; import { RolePermission } from "@versia/client/schemas"; import { Application, db } from "@versia/kit/db"; import { OpenIdLoginFlows } from "@versia/kit/tables"; +import { randomUUIDv7 } from "bun"; import { describeRoute } from "hono-openapi"; import { resolver, validator } from "hono-openapi/zod"; import { @@ -117,6 +118,7 @@ export default (plugin: PluginType): void => { ); const application = await Application.insert({ + id: randomUUIDv7(), clientId: user.id + Buffer.from( @@ -133,6 +135,7 @@ export default (plugin: PluginType): void => { await db .insert(OpenIdLoginFlows) .values({ + id: randomUUIDv7(), codeVerifier, issuerId, applicationId: application.id, diff --git a/tests/utils.ts b/tests/utils.ts index 5b1d76e7..508d92d1 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -5,7 +5,7 @@ import { Client as VersiaClient } from "@versia/client"; import { Note, Token, User, db } from "@versia/kit/db"; import { Notes, Users } from "@versia/kit/tables"; import { solveChallenge } from "altcha-lib"; -import { env } from "bun"; +import { env, randomUUIDv7 } from "bun"; import { type InferSelectModel, asc, inArray, like } from "drizzle-orm"; import { appFactory } from "~/app"; import { searchManager } from "~/classes/search/search-manager"; @@ -46,6 +46,7 @@ export const generateClient = async ( > => { const token = user ? await Token.insert({ + id: randomUUIDv7(), accessToken: randomString(32, "hex"), tokenType: "bearer", userId: user.id, @@ -118,6 +119,7 @@ export const getTestUsers = async ( const tokens = await Token.insertMany( users.map((u) => ({ + id: randomUUIDv7(), accessToken: randomString(32, "hex"), tokenType: "bearer", userId: u.id, @@ -155,6 +157,7 @@ export const getTestStatuses = async ( for (let i = 0; i < count; i++) { const newStatus = await Note.insert({ + id: randomUUIDv7(), content: `${i} ${randomString(32, "hex")}`, authorId: user.id, sensitive: false,