refactor(database): ♻️ Use dates instead of strings in database
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 1s
Build Docker Images / lint (push) Failing after 7s
Build Docker Images / check (push) Failing after 7s
Build Docker Images / tests (push) Failing after 7s
Build Docker Images / detect-circular (push) Failing after 7s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Mirror to Codeberg / Mirror (push) Failing after 0s
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s

This commit is contained in:
Jesse Wierzbinski 2025-12-11 04:03:57 +01:00
parent 1fefafdbad
commit 6056a6622c
No known key found for this signature in database
25 changed files with 2548 additions and 67 deletions

View file

@ -31,7 +31,9 @@ export const deleteUserCommand = defineCommand({
console.info(`About to delete user ${chalk.gray(user.data.username)}!`); console.info(`About to delete user ${chalk.gray(user.data.username)}!`);
console.info(`Username: ${chalk.blue(user.data.username)}`); console.info(`Username: ${chalk.blue(user.data.username)}`);
console.info(`Display Name: ${chalk.blue(user.data.displayName)}`); console.info(`Display Name: ${chalk.blue(user.data.displayName)}`);
console.info(`Created At: ${chalk.blue(user.data.createdAt)}`); console.info(
`Created At: ${chalk.blue(user.data.createdAt.toISOString())}`,
);
console.info( console.info(
`Instance: ${chalk.blue(user.data.instance?.baseUrl || "Local")}`, `Instance: ${chalk.blue(user.data.instance?.baseUrl || "Local")}`,
); );

View file

@ -44,7 +44,7 @@ describe("/api/v1/accounts/:id", () => {
avatar: expect.any(String), avatar: expect.any(String),
header: expect.any(String), header: expect.any(String),
locked: users[0].data.isLocked, locked: users[0].data.isLocked,
created_at: new Date(users[0].data.createdAt).toISOString(), created_at: users[0].data.createdAt.toISOString(),
followers_count: 0, followers_count: 0,
following_count: 0, following_count: 0,
statuses_count: 5, statuses_count: 5,

View file

@ -48,9 +48,7 @@ describe("/api/v1/accounts/verify_credentials", () => {
expect(data.moved).toBeNull(); expect(data.moved).toBeNull();
expect(data.suspended).toBe(false); expect(data.suspended).toBe(false);
expect(data.limited).toBe(false); expect(data.limited).toBe(false);
expect(data.created_at).toBe( expect(data.created_at).toBe(users[0].data.createdAt.toISOString());
new Date(users[0].data.createdAt).toISOString(),
);
expect(data.last_status_at).toBeNull(); expect(data.last_status_at).toBeNull();
expect(data.statuses_count).toBe(0); expect(data.statuses_count).toBe(0);
expect(data.followers_count).toBe(0); expect(data.followers_count).toBe(0);

View file

@ -98,7 +98,7 @@ export default apiRoute((app) => {
markers.home = { markers.home = {
last_read_id: found.noteId, last_read_id: found.noteId,
version: totalCount, version: totalCount,
updated_at: new Date(found.createdAt).toISOString(), updated_at: found.createdAt.toISOString(),
}; };
} }
} }
@ -124,7 +124,7 @@ export default apiRoute((app) => {
markers.notifications = { markers.notifications = {
last_read_id: found.notificationId, last_read_id: found.notificationId,
version: totalCount, version: totalCount,
updated_at: new Date(found.createdAt).toISOString(), updated_at: found.createdAt.toISOString(),
}; };
} }
} }
@ -212,9 +212,7 @@ export default apiRoute((app) => {
markers.home = { markers.home = {
last_read_id: homeId, last_read_id: homeId,
version: totalCount, version: totalCount,
updated_at: new Date( updated_at: insertedMarker.createdAt.toISOString(),
insertedMarker.createdAt,
).toISOString(),
}; };
} }
@ -242,9 +240,7 @@ export default apiRoute((app) => {
markers.notifications = { markers.notifications = {
last_read_id: notificationsId, last_read_id: notificationsId,
version: totalCount, version: totalCount,
updated_at: new Date( updated_at: insertedMarker.createdAt.toISOString(),
insertedMarker.createdAt,
).toISOString(),
}; };
} }

View file

@ -184,9 +184,7 @@ export default apiRoute((app) => {
title, title,
context: ctx ?? [], context: ctx ?? [],
filterAction: filter_action, filterAction: filter_action,
expireAt: new Date( expireAt: new Date(Date.now() + (expires_in ?? 0)),
Date.now() + (expires_in ?? 0),
).toISOString(),
}) })
.where(and(eq(Filters.userId, user.id), eq(Filters.id, id))); .where(and(eq(Filters.userId, user.id), eq(Filters.id, id)));
@ -244,9 +242,7 @@ export default apiRoute((app) => {
id: updatedFilter.id, id: updatedFilter.id,
title: updatedFilter.title, title: updatedFilter.title,
context: updatedFilter.context, context: updatedFilter.context,
expires_at: updatedFilter.expireAt expires_at: updatedFilter.expireAt?.toISOString() || null,
? new Date(updatedFilter.expireAt).toISOString()
: null,
filter_action: updatedFilter.filterAction, filter_action: updatedFilter.filterAction,
keywords: updatedFilter.keywords.map((keyword) => ({ keywords: updatedFilter.keywords.map((keyword) => ({
id: keyword.id, id: keyword.id,

View file

@ -59,9 +59,7 @@ export default apiRoute((app) => {
id: filter.id, id: filter.id,
title: filter.title, title: filter.title,
context: filter.context, context: filter.context,
expires_at: filter.expireAt expires_at: filter.expireAt?.toISOString() || null,
? new Date(Date.now() + filter.expireAt).toISOString()
: null,
filter_action: filter.filterAction, filter_action: filter.filterAction,
keywords: filter.keywords.map((keyword) => ({ keywords: filter.keywords.map((keyword) => ({
id: keyword.id, id: keyword.id,
@ -147,9 +145,7 @@ export default apiRoute((app) => {
title, title,
context: ctx, context: ctx,
filterAction: filter_action, filterAction: filter_action,
expireAt: new Date( expireAt: new Date(Date.now() + (expires_in ?? 0)),
Date.now() + (expires_in ?? 0),
).toISOString(),
userId: user.id, userId: user.id,
}) })
.returning() .returning()

View file

@ -17,8 +17,8 @@ const token = await Token.insert({
id: randomUUIDv7(), id: randomUUIDv7(),
clientId: application.id, clientId: application.id,
accessToken: "test-access-token", accessToken: "test-access-token",
expiresAt: new Date(Date.now() + 3600 * 1000).toISOString(), expiresAt: new Date(Date.now() + 3600 * 1000),
createdAt: new Date().toISOString(), createdAt: new Date(),
scopes: application.data.scopes, scopes: application.data.scopes,
userId: users[0].id, userId: users[0].id,
}); });

View file

@ -278,7 +278,7 @@ export default apiRoute((app) => {
await db.insert(AuthorizationCodes).values({ await db.insert(AuthorizationCodes).values({
clientId: flow.client.id, clientId: flow.client.id,
code, code,
expiresAt: new Date(Date.now() + 10 * 60 * 1000).toISOString(), // 10 minutes expiresAt: new Date(Date.now() + 10 * 60 * 1000), // 10 minutes
redirectUri: flow.clientRedirectUri ?? undefined, redirectUri: flow.clientRedirectUri ?? undefined,
userId: user.id, userId: user.id,
scopes: flow.clientScopes ?? [], scopes: flow.clientScopes ?? [],

View file

@ -24,7 +24,7 @@ const authorizationCode = (
code: randomString(10), code: randomString(10),
redirectUri: application.data.redirectUris[0], redirectUri: application.data.redirectUris[0],
userId: users[0].id, userId: users[0].id,
expiresAt: new Date(Date.now() + 300 * 1000).toISOString(), expiresAt: new Date(Date.now() + 300 * 1000),
}) })
.returning() .returning()
)[0]; )[0];

View file

@ -101,7 +101,7 @@ export default apiRoute((app) => {
if ( if (
!authorizationCode || !authorizationCode ||
new Date(authorizationCode.expiresAt).getTime() < Date.now() authorizationCode.expiresAt.getTime() < Date.now()
) { ) {
return context.json( return context.json(
{ {
@ -131,8 +131,7 @@ export default apiRoute((app) => {
...token.toApi(), ...token.toApi(),
expires_in: token.data.expiresAt expires_in: token.data.expiresAt
? Math.floor( ? Math.floor(
(new Date(token.data.expiresAt).getTime() - (token.data.expiresAt.getTime() - Date.now()) /
Date.now()) /
1000, 1000,
) )
: null, : null,

View file

@ -73,9 +73,7 @@ export default apiRoute((app) =>
"/inbox", "/inbox",
config.http.base_url, config.http.base_url,
).toString(), ).toString(),
created_at: new Date( created_at: firstUser?.data.createdAt.toISOString(),
firstUser?.data.createdAt ?? 0,
).toISOString(),
extensions: { extensions: {
"pub.versia:instance_messaging": { "pub.versia:instance_messaging": {
endpoint: new URL( endpoint: new URL(

View file

@ -137,7 +137,7 @@ export const checkRouteNeedsChallenge = async (
// Expire the challenge // Expire the challenge
await db await db
.update(Challenges) .update(Challenges)
.set({ expiresAt: new Date().toISOString() }) .set({ expiresAt: new Date() })
.where(eq(Challenges.id, challenge_id)); .where(eq(Challenges.id, challenge_id));
}; };

View file

@ -153,7 +153,7 @@ export class Like extends BaseInterface<typeof Likes, LikeType> {
this.data.liker.uri ? new URL(this.data.liker.uri) : null, this.data.liker.uri ? new URL(this.data.liker.uri) : null,
).href, ).href,
type: "pub.versia:likes/Like", type: "pub.versia:likes/Like",
created_at: new Date(this.data.createdAt).toISOString(), created_at: this.data.createdAt.toISOString(),
liked: this.data.liked.uri liked: this.data.liked.uri
? new URL(this.data.liked.uri).href ? new URL(this.data.liked.uri).href
: new URL(`/notes/${this.data.liked.id}`, config.http.base_url) : new URL(`/notes/${this.data.liked.id}`, config.http.base_url)

View file

@ -513,7 +513,7 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
reblogId: this.id, reblogId: this.id,
visibility, visibility,
sensitive: false, sensitive: false,
updatedAt: new Date().toISOString(), updatedAt: new Date(),
clientId: null, clientId: null,
uri: uri?.href, uri: uri?.href,
}); });
@ -979,7 +979,7 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
authorId: author.id, authorId: author.id,
visibility: "public", visibility: "public",
uri, uri,
createdAt: new Date(created_at).toISOString(), createdAt: new Date(created_at),
})); }));
const attachments = await Promise.all( const attachments = await Promise.all(
@ -1150,7 +1150,7 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
in_reply_to_id: data.replyId || null, in_reply_to_id: data.replyId || null,
in_reply_to_account_id: data.reply?.authorId || null, in_reply_to_account_id: data.reply?.authorId || null,
account: this.author.toApi(userFetching?.id === data.authorId), account: this.author.toApi(userFetching?.id === data.authorId),
created_at: new Date(data.createdAt).toISOString(), created_at: data.createdAt.toISOString(),
application: data.client application: data.client
? new Client(data.client).toApi() ? new Client(data.client).toApi()
: undefined, : undefined,
@ -1200,9 +1200,7 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
(n) => n?.toApi(userFetching), (n) => n?.toApi(userFetching),
)) ?? null) )) ?? null)
: null, : null,
edited_at: data.updatedAt edited_at: data.updatedAt.toISOString(),
? new Date(data.updatedAt).toISOString()
: null,
reactions, reactions,
text: data.contentSource, text: data.contentSource,
}; };
@ -1246,7 +1244,7 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
const status = this.data; const status = this.data;
return new VersiaEntities.Note({ return new VersiaEntities.Note({
type: "Note", type: "Note",
created_at: new Date(status.createdAt).toISOString(), created_at: status.createdAt.toISOString(),
id: status.id, id: status.id,
author: this.author.uri.href, author: this.author.uri.href,
uri: this.getUri().href, uri: this.getUri().href,

View file

@ -186,7 +186,7 @@ export class Notification extends BaseInterface<
return { return {
account: account.toApi(), account: account.toApi(),
created_at: new Date(this.data.createdAt).toISOString(), created_at: this.data.createdAt.toISOString(),
id: this.data.id, id: this.data.id,
type: this.data.type, type: this.data.type,
status: this.data.status status: this.data.status

View file

@ -217,7 +217,7 @@ export class Reaction extends BaseInterface<typeof Reactions, ReactionType> {
this.data.authorId, this.data.authorId,
this.data.author.uri ? new URL(this.data.author.uri) : null, this.data.author.uri ? new URL(this.data.author.uri) : null,
).href, ).href,
created_at: new Date(this.data.createdAt).toISOString(), created_at: this.data.createdAt.toISOString(),
id: this.id, id: this.id,
object: this.data.note.uri object: this.data.note.uri
? new URL(this.data.note.uri).href ? new URL(this.data.note.uri).href

View file

@ -160,9 +160,7 @@ export class Token extends BaseInterface<typeof Tokens, TokenType> {
access_token: this.data.accessToken, access_token: this.data.accessToken,
token_type: "Bearer", token_type: "Bearer",
scope: this.data.scopes.join(" "), scope: this.data.scopes.join(" "),
created_at: Math.floor( created_at: Math.floor(this.data.createdAt.getTime() / 1000),
new Date(this.data.createdAt).getTime() / 1000,
),
}; };
} }
} }

View file

@ -475,7 +475,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
isNull(Users.instanceId), isNull(Users.instanceId),
gte( gte(
Notes.createdAt, Notes.createdAt,
new Date(Date.now() - milliseconds).toISOString(), new Date(Date.now() - milliseconds),
), ),
), ),
) )
@ -803,7 +803,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
} }
await user.update({ await user.update({
createdAt: new Date(created_at).toISOString(), createdAt: new Date(created_at),
endpoints: { endpoints: {
inbox, inbox,
outbox: collections.outbox, outbox: collections.outbox,
@ -940,7 +940,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
publicKey: keys.public_key, publicKey: keys.public_key,
fields: [], fields: [],
privateKey: keys.private_key, privateKey: keys.private_key,
updatedAt: new Date().toISOString(), updatedAt: new Date(),
source: { source: {
language: "en", language: "en",
note: "", note: "",
@ -1116,7 +1116,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
avatar: this.getAvatarUrl().proxied, avatar: this.getAvatarUrl().proxied,
header: this.getHeaderUrl()?.proxied ?? "", header: this.getHeaderUrl()?.proxied ?? "",
locked: user.isLocked, locked: user.isLocked,
created_at: new Date(user.createdAt).toISOString(), created_at: user.createdAt.toISOString(),
followers_count: followers_count:
user.isHidingCollections && !isOwnAccount user.isHidingCollections && !isOwnAccount
? 0 ? 0
@ -1177,7 +1177,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
remote: false, remote: false,
}, },
}, },
created_at: new Date(user.createdAt).toISOString(), created_at: user.createdAt.toISOString(),
collections: { collections: {
featured: new URL( featured: new URL(
`/users/${user.id}/featured`, `/users/${user.id}/featured`,

View file

@ -0,0 +1,45 @@
ALTER TABLE "AuthorizationCodes" ALTER COLUMN "expires_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "AuthorizationCodes" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "AuthorizationCodes" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Challenges" ALTER COLUMN "expires_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Challenges" ALTER COLUMN "expires_at" SET DEFAULT NOW() + INTERVAL '5 minutes';--> statement-breakpoint
ALTER TABLE "Challenges" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Challenges" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Filters" ALTER COLUMN "expires_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Filters" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Filters" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Flags" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Flags" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Likes" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Likes" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Markers" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Markers" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "ModNotes" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "ModNotes" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "ModTags" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "ModTags" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Notes" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Notes" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Notes" ALTER COLUMN "updated_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Notes" ALTER COLUMN "updated_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Notifications" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Notifications" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "PushSubscriptions" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "PushSubscriptions" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "PushSubscriptions" ALTER COLUMN "updated_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "PushSubscriptions" ALTER COLUMN "updated_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Reaction" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Reaction" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Reaction" ALTER COLUMN "updated_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Reaction" ALTER COLUMN "updated_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Relationships" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Relationships" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Relationships" ALTER COLUMN "updated_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Relationships" ALTER COLUMN "updated_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Tokens" ALTER COLUMN "expires_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Tokens" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Tokens" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Users" ALTER COLUMN "created_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Users" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "Users" ALTER COLUMN "updated_at" SET DATA TYPE timestamp (3) with time zone;--> statement-breakpoint
ALTER TABLE "Users" ALTER COLUMN "updated_at" SET DEFAULT now();

File diff suppressed because it is too large Load diff

View file

@ -372,6 +372,13 @@
"when": 1755732000165, "when": 1755732000165,
"tag": "0052_complete_hellfire_club", "tag": "0052_complete_hellfire_club",
"breakpoints": true "breakpoints": true
},
{
"idx": 53,
"version": "7",
"when": 1765422160004,
"tag": "0053_lively_hellfire_club",
"breakpoints": true
} }
] ]
} }

View file

@ -28,13 +28,12 @@ import {
import type { z } from "zod"; import type { z } from "zod";
const createdAt = () => const createdAt = () =>
// TODO: Change mode to Date timestamp("created_at", { precision: 3, mode: "date", withTimezone: true })
timestamp("created_at", { precision: 3, mode: "string" })
.defaultNow() .defaultNow()
.notNull(); .notNull();
const updatedAt = () => const updatedAt = () =>
timestamp("updated_at", { precision: 3, mode: "string" }) timestamp("updated_at", { precision: 3, mode: "date", withTimezone: true })
.defaultNow() .defaultNow()
.notNull(); .notNull();
@ -47,7 +46,8 @@ export const Challenges = pgTable("Challenges", {
challenge: jsonb("challenge").notNull().$type<Challenge>(), challenge: jsonb("challenge").notNull().$type<Challenge>(),
expiresAt: timestamp("expires_at", { expiresAt: timestamp("expires_at", {
precision: 3, precision: 3,
mode: "string", mode: "date",
withTimezone: true,
}) })
.default( .default(
// 5 minutes // 5 minutes
@ -191,7 +191,11 @@ export const Filters = pgTable("Filters", {
>(), >(),
title: text("title").notNull(), title: text("title").notNull(),
filterAction: text("filter_action").notNull().$type<"warn" | "hide">(), filterAction: text("filter_action").notNull().$type<"warn" | "hide">(),
expireAt: timestamp("expires_at", { precision: 3, mode: "string" }), expireAt: timestamp("expires_at", {
precision: 3,
mode: "date",
withTimezone: true,
}),
createdAt: createdAt(), createdAt: createdAt(),
}); });
@ -330,7 +334,11 @@ export const Tokens = pgTable("Tokens", {
id: id(), id: id(),
scopes: text("scopes").array().notNull().default(sql`ARRAY[]::text[]`), scopes: text("scopes").array().notNull().default(sql`ARRAY[]::text[]`),
accessToken: text("access_token").notNull(), accessToken: text("access_token").notNull(),
expiresAt: timestamp("expires_at", { precision: 3, mode: "string" }), expiresAt: timestamp("expires_at", {
precision: 3,
mode: "date",
withTimezone: true,
}),
createdAt: createdAt(), createdAt: createdAt(),
userId: uuid("userId") userId: uuid("userId")
.references(() => Users.id, { .references(() => Users.id, {
@ -363,7 +371,8 @@ export const AuthorizationCodes = pgTable("AuthorizationCodes", {
redirectUri: text("redirect_uri"), redirectUri: text("redirect_uri"),
expiresAt: timestamp("expires_at", { expiresAt: timestamp("expires_at", {
precision: 3, precision: 3,
mode: "string", mode: "date",
withTimezone: true,
}).notNull(), }).notNull(),
createdAt: createdAt(), createdAt: createdAt(),
codeChallenge: text("code_challenge"), codeChallenge: text("code_challenge"),

View file

@ -180,7 +180,7 @@ export const getTestStatuses = async (
content: `${i} ${randomString(32, "hex")}`, content: `${i} ${randomString(32, "hex")}`,
authorId: user.id, authorId: user.id,
sensitive: false, sensitive: false,
updatedAt: new Date().toISOString(), updatedAt: new Date(),
visibility: "public", visibility: "public",
clientId: null, clientId: null,
...partial, ...partial,

View file

@ -10,8 +10,8 @@ export const generateChallenge = async (
): Promise<{ ): Promise<{
id: string; id: string;
challenge: Challenge; challenge: Challenge;
expiresAt: string; expiresAt: Date;
createdAt: string; createdAt: Date;
}> => { }> => {
if (!config.validation.challenges) { if (!config.validation.challenges) {
throw new Error("Challenges are not enabled"); throw new Error("Challenges are not enabled");
@ -39,7 +39,7 @@ export const generateChallenge = async (
.values({ .values({
id: uuid, id: uuid,
challenge, challenge,
expiresAt: expirationDate.toISOString(), expiresAt: expirationDate,
}) })
.returning() .returning()
)[0]; )[0];

View file

@ -58,12 +58,12 @@ export const getFeed = async (user: User, page = 0): Promise<Feed> => {
config.http.base_url, config.http.base_url,
).href, ).href,
content: note.data.content, content: note.data.content,
date: new Date(note.data.createdAt), date: note.data.createdAt,
id: new URL( id: new URL(
`/@${user.data.username}/${note.id}`, `/@${user.data.username}/${note.id}`,
config.http.base_url, config.http.base_url,
).href, ).href,
published: new Date(note.data.createdAt), published: note.data.createdAt,
title: "", title: "",
image: image image: image
? { ? {