import { kv } from '@vercel/kv'
import { createBadgenHandler, PathArgs, BadgenResponse } from '../../libs/create-badgen-handler-next'
import type { NextApiRequest, NextApiResponse } from 'next'
const help = `
A badge with memory.
## Usage
A /memo
badge like:
https://badgen.net/memo/a-badge-with-memory
can be created/updated using a PUT
request with an Authorization: Bearer XXXXXX
header:
curl -LX PUT --header "Authorization: Bearer XXXXXX" https://badgen.net/memo/a-badge-with-memory/:label/:status/:color
Once created, this badge can only be updated with the same token, until it's expired.
## Expiration
A memo badge will be expired after 32 days since it's last modification, but you can update it again within the period to keep the badge.
- When a badge is updated, it gets another 32 days lifespan,
- When a badge is expired, it gets cleared like never exists.
To keep a memo badge, you need to update the badge at least on a monthly basis. Usually this should be done in CI or Cron jobs.
`
export default createBadgenHandler({
title: 'Memo',
help,
examples: {
'/memo/deployed': 'memoized badge for deploy status',
},
handlers: {
'/memo/:key': handler,
'/memo/:key/:label/:status/:color': putHandler
}
})
const MEMOIZED_TTL_SECONDS = 2764800 // 32 days
type MemoizedBadgeItem = {
token: string;
params: {
label: string;
status: string;
color: string;
}
}
async function handler ({ key }: PathArgs, req: NextApiRequest, res: NextApiResponse): Promise {
const storedData = await kv.get(key)
if (storedData === null || storedData === undefined) {
res.setHeader('cache-control', `s-maxage=1, stale-while-revalidate=1`)
return {
subject: key,
status: '404',
color: 'grey'
}
} else {
const ttl = await kv.ttl(key)
res.setHeader('cache-control', `public, max-age=86400, s-maxage=60, stale-while-revalidate=${ttl}`)
const { label, status, color } = storedData.params
return { subject: label, status, color }
}
}
async function putHandler (args: PathArgs, req: NextApiRequest, res: NextApiResponse): Promise {
// Only accept PUT request
if (req.method !== 'PUT') {
res.setHeader('Allow', 'PUT')
res.status(405)
return 'Method Not Allowed'
}
// Ensure token(authorization) is provided
const token = req.headers['authorization']
if (!token?.startsWith('Bearer ')) {
res.status(401)
return 'Unauthorized'
}
const { key, label, status, color } = args
const newData: MemoizedBadgeItem = { token, params: { label, status, color }}
const storedData = await kv.get(key)
if (storedData === null || storedData.token === token) {
// If the key is not found, or found and token is validate, ser/update data and ttl
await kv.set(key, newData, { ex: MEMOIZED_TTL_SECONDS })
return JSON.stringify(newData.params)
} else {
// The key is found but token is invalid, refuse to update the data
res.status(401)
return 'Unauthorized'
}
}