All remaining backend files renamed:
src/middleware/auth.ts, logging.ts (2 files)
src/utils/*.ts (20 files: ai, auditQueue, config, crypto,
embeddings, errors, fileType, logger, models,
notify, passwords, platform, promptSafe,
prompts, redact, sessions, transcribe*,
ttsGoogle)
src/db/database.ts, migrate.ts (2 files)
Spot-fixes to satisfy tsc (all within the spirit of 'no behavior
change' — added `: any` annotations where the original JS relied on
duck typing that tsc's default inference narrows too aggressively):
utils/ai.ts — body, converseParams, request literals + fallback
result object + err.code/model/message casts. AI client has lots
of provider-specific ad-hoc object shapes; Day 5 will replace the
`any`s with proper provider-response interfaces.
utils/embeddings.ts — payload + request as `any`; generateEmbedding
call sites pass `undefined as any` for the now-required second
arg (model) until we refactor the signature.
utils/prompts.ts — PROMPTS typed as Record<string, any> so
.loadFromDb / .updatePrompt / .getAllPrompts attachments after
the const literal compile.
utils/transcribeLocal.ts — buildArgs() has two `var args = [...]`
in the same function scope (var-hoisted); both now typed as
any[] so they don't type-clash across conditionals.
Backend is now 54 of 54 TypeScript files, permissive mode.
`npm run typecheck` EXIT 0. Prod container still running the old
JS image — no Dockerfile change yet.
Next: Day 5 flips strict: true, fixes every error tsc surfaces, adds
Vitest + Zod + Knip tooling.
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
// ============================================================
|
|
// LOGGING MIDDLEWARE — Logs all API calls
|
|
// ============================================================
|
|
|
|
var logger = require('../utils/logger');
|
|
|
|
function loggingMiddleware(req, res, next) {
|
|
var startTime = Date.now();
|
|
|
|
// Capture original json method
|
|
var originalJson = res.json.bind(res);
|
|
|
|
res.json = function(data) {
|
|
var duration = Date.now() - startTime;
|
|
|
|
// Log API calls (skip static, health, models)
|
|
if (req.path.startsWith('/api/') &&
|
|
req.path !== '/api/health' &&
|
|
req.path !== '/api/models' &&
|
|
req.method !== 'GET') {
|
|
|
|
var userId = req.user ? req.user.id : null;
|
|
var responseStr = '';
|
|
try { responseStr = JSON.stringify(data); } catch(e) { responseStr = ''; }
|
|
|
|
logger.apiCall(userId, req.path, {
|
|
method: req.method,
|
|
statusCode: res.statusCode,
|
|
requestSize: parseInt(req.headers['content-length'] || 0),
|
|
responseSize: responseStr.length,
|
|
model: (data && data.model) || (req.body && req.body.model) || null,
|
|
tokensInput: (data && data.usage && data.usage.prompt_tokens) ? data.usage.prompt_tokens : 0,
|
|
tokensOutput: (data && data.usage && data.usage.completion_tokens) ? data.usage.completion_tokens : 0,
|
|
duration: duration,
|
|
ip: req.ip || (req.connection && req.connection.remoteAddress) || null,
|
|
error: (data && data.error) || null
|
|
});
|
|
}
|
|
|
|
return originalJson(data);
|
|
};
|
|
|
|
next();
|
|
}
|
|
|
|
module.exports = loggingMiddleware;
|