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