feat: 笔记和文件夹云端同步路由
This commit is contained in:
parent
c8ba2a8a51
commit
2178247093
44
server/routes/folders.ts
Normal file
44
server/routes/folders.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { Hono } from 'hono'
|
||||
import { eq, and } from 'drizzle-orm'
|
||||
import { db, folders, users } from '../db'
|
||||
import { requireAuth } from '../middleware/auth'
|
||||
|
||||
export const foldersRouter = new Hono()
|
||||
foldersRouter.use('*', requireAuth)
|
||||
|
||||
async function checkCloud(c: any): Promise<string | null> {
|
||||
const userId = c.get('userId')
|
||||
const [user] = db.select().from(users).where(eq(users.id, userId)).all()
|
||||
if (!user?.cloudEnabled) {
|
||||
await c.json({ error: '请先激活云存储(填写邀请码)' }, 403)
|
||||
return null
|
||||
}
|
||||
return userId
|
||||
}
|
||||
|
||||
foldersRouter.put('/:id', async (c) => {
|
||||
const userId = await checkCloud(c)
|
||||
if (!userId) return
|
||||
const f = await c.req.json<any>()
|
||||
|
||||
db.insert(folders).values({
|
||||
id: c.req.param('id'), userId, name: f.name,
|
||||
parentId: f.parentId ?? null, order: f.order ?? 0, createdAt: f.createdAt,
|
||||
}).onConflictDoUpdate({
|
||||
target: folders.id,
|
||||
set: { name: f.name, parentId: f.parentId ?? null, order: f.order ?? 0 },
|
||||
}).run()
|
||||
|
||||
return c.json({ ok: true })
|
||||
})
|
||||
|
||||
foldersRouter.delete('/:id', async (c) => {
|
||||
const userId = await checkCloud(c)
|
||||
if (!userId) return
|
||||
|
||||
db.delete(folders)
|
||||
.where(and(eq(folders.id, c.req.param('id')), eq(folders.userId, userId)))
|
||||
.run()
|
||||
|
||||
return c.json({ ok: true })
|
||||
})
|
||||
102
server/routes/notes.ts
Normal file
102
server/routes/notes.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import { Hono } from 'hono'
|
||||
import { eq, and } from 'drizzle-orm'
|
||||
import { db, notes, folders, users } from '../db'
|
||||
import { requireAuth } from '../middleware/auth'
|
||||
|
||||
export const notesRouter = new Hono()
|
||||
notesRouter.use('*', requireAuth)
|
||||
|
||||
async function checkCloud(c: any): Promise<string | null> {
|
||||
const userId = c.get('userId')
|
||||
const [user] = db.select().from(users).where(eq(users.id, userId)).all()
|
||||
if (!user?.cloudEnabled) {
|
||||
await c.json({ error: '请先激活云存储(填写邀请码)' }, 403)
|
||||
return null
|
||||
}
|
||||
return userId
|
||||
}
|
||||
|
||||
notesRouter.get('/sync', async (c) => {
|
||||
const userId = await checkCloud(c)
|
||||
if (!userId) return
|
||||
|
||||
const userNotes = db.select().from(notes).where(eq(notes.userId, userId)).all()
|
||||
const userFolders = db.select().from(folders).where(eq(folders.userId, userId)).all()
|
||||
|
||||
return c.json({
|
||||
notes: userNotes.map(n => ({ ...n, tags: JSON.parse(n.tags) })),
|
||||
folders: userFolders,
|
||||
})
|
||||
})
|
||||
|
||||
notesRouter.post('/sync', async (c) => {
|
||||
const userId = await checkCloud(c)
|
||||
if (!userId) return
|
||||
|
||||
const { notes: clientNotes, folders: clientFolders } = await c.req.json<{
|
||||
notes: any[]
|
||||
folders: any[]
|
||||
}>()
|
||||
|
||||
for (const n of clientNotes ?? []) {
|
||||
db.insert(notes).values({
|
||||
id: n.id, userId, title: n.title, content: n.content,
|
||||
folderId: n.folderId ?? null, tags: JSON.stringify(n.tags ?? []),
|
||||
starred: n.starred ? 1 : 0, wordCount: n.wordCount ?? 0,
|
||||
deletedAt: n.deletedAt ?? null, createdAt: n.createdAt, updatedAt: n.updatedAt,
|
||||
}).onConflictDoUpdate({
|
||||
target: notes.id,
|
||||
set: {
|
||||
title: n.title, content: n.content, folderId: n.folderId ?? null,
|
||||
tags: JSON.stringify(n.tags ?? []), starred: n.starred ? 1 : 0,
|
||||
wordCount: n.wordCount ?? 0, deletedAt: n.deletedAt ?? null, updatedAt: n.updatedAt,
|
||||
},
|
||||
}).run()
|
||||
}
|
||||
|
||||
for (const f of clientFolders ?? []) {
|
||||
db.insert(folders).values({
|
||||
id: f.id, userId, name: f.name, parentId: f.parentId ?? null,
|
||||
order: f.order ?? 0, createdAt: f.createdAt,
|
||||
}).onConflictDoUpdate({
|
||||
target: folders.id,
|
||||
set: { name: f.name, parentId: f.parentId ?? null, order: f.order ?? 0 },
|
||||
}).run()
|
||||
}
|
||||
|
||||
return c.json({ synced: (clientNotes?.length ?? 0) + (clientFolders?.length ?? 0) })
|
||||
})
|
||||
|
||||
notesRouter.put('/:id', async (c) => {
|
||||
const userId = await checkCloud(c)
|
||||
if (!userId) return
|
||||
const n = await c.req.json<any>()
|
||||
|
||||
db.insert(notes).values({
|
||||
id: c.req.param('id'), userId, title: n.title, content: n.content,
|
||||
folderId: n.folderId ?? null, tags: JSON.stringify(n.tags ?? []),
|
||||
starred: n.starred ? 1 : 0, wordCount: n.wordCount ?? 0,
|
||||
deletedAt: n.deletedAt ?? null, createdAt: n.createdAt, updatedAt: n.updatedAt,
|
||||
}).onConflictDoUpdate({
|
||||
target: notes.id,
|
||||
set: {
|
||||
title: n.title, content: n.content, folderId: n.folderId ?? null,
|
||||
tags: JSON.stringify(n.tags ?? []), starred: n.starred ? 1 : 0,
|
||||
wordCount: n.wordCount ?? 0, deletedAt: n.deletedAt ?? null, updatedAt: n.updatedAt,
|
||||
},
|
||||
}).run()
|
||||
|
||||
return c.json({ ok: true })
|
||||
})
|
||||
|
||||
notesRouter.delete('/:id', async (c) => {
|
||||
const userId = await checkCloud(c)
|
||||
if (!userId) return
|
||||
|
||||
db.update(notes)
|
||||
.set({ deletedAt: Date.now() })
|
||||
.where(and(eq(notes.id, c.req.param('id')), eq(notes.userId, userId)))
|
||||
.run()
|
||||
|
||||
return c.json({ ok: true })
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user