Clarify receive requests and add retry countdowns and device unblock controls

This commit is contained in:
2026-10-14 12:22:07 +09:00
parent ff89daac8c
commit 3852c87e2e
16 changed files with 739 additions and 60 deletions

View File

@@ -281,7 +281,23 @@ export async function createApp(cfg: Config, options: { mailer?: Mailer } = {})
code = 'INVALID_REQUEST';
message = '요청 형식이나 크기를 확인해 주세요.';
}
reply.status(status).send({ code, message, requestId: req.id });
const retryAfterSeconds =
err instanceof ApiError && err.retryAt
? Math.max(1, Math.ceil((err.retryAt - Date.now()) / 1000))
: undefined;
if (retryAfterSeconds) reply.header('Retry-After', retryAfterSeconds);
reply.status(status).send({
code,
message,
requestId: req.id,
...(retryAfterSeconds
? {
retryAfterSeconds,
retryAt: (err as ApiError).retryAt,
limitScope: (err as ApiError).limitScope,
}
: {}),
});
});
const setCookie = (reply: any, token: string, expiresAt: number) =>
reply.setCookie('hop_guest', token, {
@@ -354,6 +370,11 @@ export async function createApp(cfg: Config, options: { mailer?: Mailer } = {})
service.patchDevice(guest, devicePatch.parse(req.body));
return { device: service.device(guest.id) };
});
app.get('/api/device/blocks', async (req) => ({ blocks: service.listBlocks(auth(req)) }));
app.delete('/api/device/blocks/:id', async (req) => {
service.unblock(auth(req), id(req));
return { ok: true };
});
app.post('/api/device/reset', async (req, reply) => {
const guest = auth(req);
service.reset(guest);