mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 13:00:39 +00:00
feat(pagination): add pagination utility functions for handling page size and continuation tokens
- Introduced `PaginationRequest` interface to define pagination parameters. - Implemented `parsePagination` function to extract and validate pagination parameters from a URL. - Added `encodeContinuationToken` and `decodeContinuationToken` functions for managing continuation tokens. - Ensured that pagination respects maximum page size limits defined in configuration.
This commit is contained in:
+51
-2
@@ -1,7 +1,40 @@
|
||||
import { Env, SyncResponse, CipherResponse, FolderResponse, ProfileResponse } from '../types';
|
||||
import { StorageService } from '../services/storage';
|
||||
import { jsonResponse, errorResponse } from '../utils/response';
|
||||
import { errorResponse } from '../utils/response';
|
||||
import { cipherToResponse } from './ciphers';
|
||||
import { LIMITS } from '../config/limits';
|
||||
|
||||
interface SyncCacheEntry {
|
||||
body: string;
|
||||
expiresAt: number;
|
||||
}
|
||||
|
||||
const syncResponseCache = new Map<string, SyncCacheEntry>();
|
||||
|
||||
function buildSyncCacheKey(userId: string, revisionDate: string, excludeDomains: boolean): string {
|
||||
return `${userId}:${revisionDate}:${excludeDomains ? '1' : '0'}`;
|
||||
}
|
||||
|
||||
function readSyncCache(key: string): string | null {
|
||||
const hit = syncResponseCache.get(key);
|
||||
if (!hit) return null;
|
||||
if (hit.expiresAt <= Date.now()) {
|
||||
syncResponseCache.delete(key);
|
||||
return null;
|
||||
}
|
||||
return hit.body;
|
||||
}
|
||||
|
||||
function writeSyncCache(key: string, body: string): void {
|
||||
if (syncResponseCache.size >= LIMITS.cache.syncResponseMaxEntries) {
|
||||
const oldestKey = syncResponseCache.keys().next().value as string | undefined;
|
||||
if (oldestKey) syncResponseCache.delete(oldestKey);
|
||||
}
|
||||
syncResponseCache.set(key, {
|
||||
body,
|
||||
expiresAt: Date.now() + LIMITS.cache.syncResponseTtlMs,
|
||||
});
|
||||
}
|
||||
|
||||
// GET /api/sync
|
||||
export async function handleSync(request: Request, env: Env, userId: string): Promise<Response> {
|
||||
@@ -15,6 +48,16 @@ export async function handleSync(request: Request, env: Env, userId: string): Pr
|
||||
return errorResponse('User not found', 404);
|
||||
}
|
||||
|
||||
const revisionDate = await storage.getRevisionDate(userId);
|
||||
const cacheKey = buildSyncCacheKey(userId, revisionDate, excludeDomains);
|
||||
const cachedBody = readSyncCache(cacheKey);
|
||||
if (cachedBody) {
|
||||
return new Response(cachedBody, {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
const ciphers = await storage.getAllCiphers(userId);
|
||||
const folders = await storage.getAllFolders(userId);
|
||||
const attachmentsByCipher = await storage.getAttachmentsByCipherIds(ciphers.map(c => c.id));
|
||||
@@ -107,5 +150,11 @@ export async function handleSync(request: Request, env: Env, userId: string): Pr
|
||||
object: 'sync',
|
||||
};
|
||||
|
||||
return jsonResponse(syncResponse);
|
||||
const body = JSON.stringify(syncResponse);
|
||||
writeSyncCache(cacheKey, body);
|
||||
|
||||
return new Response(body, {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user