feat: add push tokens

This commit is contained in:
Steve Korshakov 2025-07-17 20:31:18 -07:00
parent 332ad7b91c
commit 93c55df649
3 changed files with 126 additions and 7 deletions

View File

@ -0,0 +1,16 @@
-- CreateTable
CREATE TABLE "AccountPushToken" (
"id" TEXT NOT NULL,
"accountId" TEXT NOT NULL,
"token" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "AccountPushToken_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "AccountPushToken_accountId_token_key" ON "AccountPushToken"("accountId", "token");
-- AddForeignKey
ALTER TABLE "AccountPushToken" ADD CONSTRAINT "AccountPushToken_accountId_fkey" FOREIGN KEY ("accountId") REFERENCES "Account"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -19,13 +19,25 @@ datasource db {
//
model Account {
id String @id @default(cuid())
publicKey String @unique
seq Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
Session Session[]
Update Update[]
id String @id @default(cuid())
publicKey String @unique
seq Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
Session Session[]
Update Update[]
AccountPushToken AccountPushToken[]
}
model AccountPushToken {
id String @id @default(cuid())
accountId String
account Account @relation(fields: [accountId], references: [id])
token String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([accountId, token])
}
//
@ -61,6 +73,7 @@ model SessionMessage {
content Json
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([sessionId, localId])
}

View File

@ -342,6 +342,96 @@ export async function startApi() {
}
});
// Push Token Registration API
typed.post('/v1/push-tokens', {
schema: {
body: z.object({
token: z.string()
})
},
preHandler: app.authenticate
}, async (request, reply) => {
const userId = request.user.id;
const { token } = request.body;
try {
await db.accountPushToken.upsert({
where: {
accountId_token: {
accountId: userId,
token: token
}
},
update: {
updatedAt: new Date()
},
create: {
accountId: userId,
token: token
}
});
return reply.send({ success: true });
} catch (error) {
return reply.code(500).send({ error: 'Failed to register push token' });
}
});
// Delete Push Token API
typed.delete('/v1/push-tokens/:token', {
schema: {
params: z.object({
token: z.string()
})
},
preHandler: app.authenticate
}, async (request, reply) => {
const userId = request.user.id;
const { token } = request.params;
try {
await db.accountPushToken.deleteMany({
where: {
accountId: userId,
token: token
}
});
return reply.send({ success: true });
} catch (error) {
return reply.code(500).send({ error: 'Failed to delete push token' });
}
});
// Get Push Tokens API
typed.get('/v1/push-tokens', {
preHandler: app.authenticate
}, async (request, reply) => {
const userId = request.user.id;
try {
const tokens = await db.accountPushToken.findMany({
where: {
accountId: userId
},
orderBy: {
createdAt: 'desc'
}
});
return reply.send({
tokens: tokens.map(t => ({
id: t.id,
token: t.token,
createdAt: t.createdAt.getTime(),
updatedAt: t.updatedAt.getTime()
}))
});
} catch (error) {
return reply.code(500).send({ error: 'Failed to get push tokens' });
}
});
// Messages API
typed.get('/v1/sessions/:sessionId/messages', {
schema: {