[READ-ONLY] One Calendar is a privacy-first calendar web app built with Next.js. It has modern security features, including e2ee, password-protected sharing, and self-destructing share links 馃搮 calendar.xyehr.cn
nextjs
0

Configure Feed

Select the types of activity you want to include in your feed.

One-Calendar / lib / evlog.ts
2.4 kB 95 lines
1import { 2 auditEnricher, 3 auditOnly, 4 signed, 5 type AuditActor, 6 type RequestLogger, 7} from 'evlog' 8import { createAuthMiddleware } from 'evlog/better-auth' 9import { createEvlog } from 'evlog/next' 10import { auth } from '@/lib/auth' 11 12const identify = createAuthMiddleware(auth) 13 14const mainDrain = async (ctx: unknown) => { 15 console.log(JSON.stringify(ctx)) 16} 17 18const auditDrain = auditOnly( 19 signed( 20 async (ctx: unknown) => { 21 console.log(JSON.stringify(ctx)) 22 }, 23 { 24 strategy: 'hash-chain', 25 }, 26 ), 27 { await: true }, 28) 29 30export const anonymousAuditActor = { 31 type: 'system', 32 id: 'anonymous', 33} satisfies AuditActor 34 35function actorFromEvent(event: Record<string, unknown>): AuditActor | null { 36 const user = event.user 37 if (user && typeof user === 'object') { 38 const candidate = user as Record<string, unknown> 39 if (typeof candidate.id === 'string') { 40 return { 41 type: 'user', 42 id: candidate.id, 43 ...(typeof candidate.email === 'string' 44 ? { email: candidate.email } 45 : {}), 46 ...(typeof candidate.name === 'string' 47 ? { displayName: candidate.name } 48 : {}), 49 } 50 } 51 } 52 53 if (typeof event.userId === 'string') { 54 return { type: 'user', id: event.userId } 55 } 56 57 return null 58} 59 60export function getAuditActor( 61 logger: Pick<RequestLogger, 'getContext'>, 62 fallback: AuditActor = anonymousAuditActor, 63) { 64 return actorFromEvent(logger.getContext()) ?? fallback 65} 66 67const auditEnrich = auditEnricher({ 68 bridge: { 69 getSession: ({ event }) => actorFromEvent(event as Record<string, unknown>), 70 }, 71}) 72 73const evlog = createEvlog({ 74 service: 'one-calendar', 75 drain: async (ctx) => { 76 const results = await Promise.allSettled([mainDrain(ctx), auditDrain(ctx)]) 77 const rejected = results.find((r) => r.status === 'rejected') 78 if (rejected?.status === 'rejected') throw rejected.reason 79 }, 80 enrich: auditEnrich, 81}) 82 83const withEvlogBase = evlog.withEvlog 84 85export const withEvlog: typeof evlog.withEvlog = (handler) => 86 withEvlogBase(async (...args: Parameters<typeof handler>) => { 87 const request = args[0] 88 if (request instanceof Request) { 89 const log = evlog.useLogger() 90 await identify(log, request.headers, new URL(request.url).pathname) 91 } 92 return handler(...args) 93 }) 94 95export const { useLogger, log, createError, createEvlogError } = evlog