refactor(ts): day 3 batch 6 — final 8 routes renamed
admin.ts adminConfig.ts adminMilestones.ts
auth.ts oidc.ts
learningHub.ts learningAI.ts learningAdmin.ts
These were the largest files (auth alone is ~600 lines). Minimum-
viable conversion: extension change + spot-fix the few places where
TypeScript's default inference caught genuine `unknown` escapes
from fetch().json() — patched with `: any` type annotations so the
compile passes. Day 5 strict-mode pass will replace those `any`s
with proper response type narrowing.
Fixes in this batch:
- adminConfig.ts: sttResp var shadowing (two declarations of same
name with different types); renamed to sttRespFetch / sttRespAxios
- auth.ts: turnstileData + tsData from fetch(...).json() now `: any`
- auth.ts: resp object for password change / reset now typed
{ success: boolean; message?: string; passwordWarning?: string }
- learningAI.ts: parseInt(questionCount) cast through `any`
All 29 of 29 routes now .ts. Backend progress: 30/54 files
migrated (server.ts + 29 routes). Remaining: 2 middleware + 20
utils + 2 db files. Day 4 handles those.
tsc --noEmit green (EXIT 0).
This commit is contained in:
parent
acdd9313d0
commit
3d597d61a8
8 changed files with 15 additions and 15 deletions
|
|
@ -780,22 +780,22 @@ router.post('/config/stt/test', async function(req, res) {
|
|||
form.append('model', sttModel);
|
||||
var fetchHeaders = {};
|
||||
if (process.env.LITELLM_API_KEY) fetchHeaders['Authorization'] = 'Bearer ' + process.env.LITELLM_API_KEY;
|
||||
var sttResp = await fetch(gatewayUrl('/audio/transcriptions'), {
|
||||
var sttRespFetch: any = await fetch(gatewayUrl('/audio/transcriptions'), {
|
||||
method: 'POST', headers: fetchHeaders, body: form
|
||||
}).then(function(r) { return r.json().then(function(d) { return { data: d }; }); });
|
||||
text = sttResp.data && sttResp.data.text ? sttResp.data.text : '';
|
||||
}).then(function(r) { return r.json().then(function(d: any) { return { data: d }; }); });
|
||||
text = sttRespFetch.data && sttRespFetch.data.text ? sttRespFetch.data.text : '';
|
||||
} else {
|
||||
var headers = { 'Content-Type': 'application/json' };
|
||||
var headers: any = { 'Content-Type': 'application/json' };
|
||||
if (process.env.LITELLM_API_KEY) headers['Authorization'] = 'Bearer ' + process.env.LITELLM_API_KEY;
|
||||
var sttResp = await axios.post(gatewayUrl('/chat/completions'), {
|
||||
var sttRespAxios: any = await axios.post(gatewayUrl('/chat/completions'), {
|
||||
model: sttModel,
|
||||
messages: [{ role: 'user', content: [
|
||||
{ type: 'input_audio', input_audio: { data: audioBase64, format: mime.split('/')[1] || 'webm' } },
|
||||
{ type: 'text', text: 'Transcribe this audio. Output the spoken words only.' }
|
||||
]}]
|
||||
}, { headers: headers, timeout: 60000 });
|
||||
if (sttResp.data && sttResp.data.choices && sttResp.data.choices[0]) {
|
||||
text = (sttResp.data.choices[0].message && sttResp.data.choices[0].message.content) || '';
|
||||
if (sttRespAxios.data && sttRespAxios.data.choices && sttRespAxios.data.choices[0]) {
|
||||
text = (sttRespAxios.data.choices[0].message && sttRespAxios.data.choices[0].message.content) || '';
|
||||
}
|
||||
}
|
||||
} else if (provider === 'openai') {
|
||||
|
|
@ -193,7 +193,7 @@ router.post('/register', async (req, res) => {
|
|||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ secret: process.env.TURNSTILE_SECRET_KEY, response: turnstileToken, remoteip: req.ip })
|
||||
});
|
||||
var turnstileData = await turnstileRes.json();
|
||||
var turnstileData: any = await turnstileRes.json();
|
||||
if (!turnstileData.success) {
|
||||
console.error('[Auth] Turnstile verification failed:', turnstileData['error-codes']);
|
||||
return res.status(400).json({ error: 'Bot verification failed. Please try again.' });
|
||||
|
|
@ -309,7 +309,7 @@ router.post('/login', async (req, res) => {
|
|||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ secret: process.env.TURNSTILE_SECRET_KEY, response: turnstileToken, remoteip: req.ip })
|
||||
});
|
||||
var tsData = await tsRes.json();
|
||||
var tsData: any = await tsRes.json();
|
||||
if (!tsData.success) return res.status(400).json({ error: 'Verification failed. Please try again.' });
|
||||
}
|
||||
|
||||
|
|
@ -556,7 +556,7 @@ router.post('/forgot-password', async (req, res) => {
|
|||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ secret: process.env.TURNSTILE_SECRET_KEY, response: turnstileToken, remoteip: req.ip })
|
||||
});
|
||||
var tsData = await tsRes.json();
|
||||
var tsData: any = await tsRes.json();
|
||||
if (!tsData.success) return res.status(400).json({ error: 'Verification failed. Please try again.' });
|
||||
}
|
||||
|
||||
|
|
@ -601,10 +601,10 @@ router.post('/reset-password', async (req, res) => {
|
|||
await db.run('UPDATE users SET password = ?, reset_token = NULL, reset_expires = NULL WHERE id = ?', [hash, user.id]);
|
||||
// Force logout — destroy all sessions for this user
|
||||
try { await db.run('DELETE FROM user_sessions WHERE user_id = ?', [user.id]); } catch (e) { /* best effort */ }
|
||||
var resp = { success: true };
|
||||
var resp: { success: boolean; passwordWarning?: string } = { success: true };
|
||||
if (pwnedCount > 0) resp.passwordWarning = 'This password has appeared in ' + pwnedCount.toLocaleString() + ' data breaches. Consider changing it to something unique.';
|
||||
res.json(resp);
|
||||
} catch (err) { console.error('[Auth] Reset password error:', err.message); res.status(500).json({ error: 'Password reset failed' }); }
|
||||
} catch (err: any) { console.error('[Auth] Reset password error:', err.message); res.status(500).json({ error: 'Password reset failed' }); }
|
||||
});
|
||||
|
||||
// Logout — destroy session and clear cookie
|
||||
|
|
@ -656,10 +656,10 @@ router.post('/change-password', authMiddleware, async (req, res) => {
|
|||
logger.audit(req.user.id, 'password_changed', 'Password changed', req, { category: 'auth' });
|
||||
notifyPasswordChanged(req.user.id);
|
||||
|
||||
var resp = { success: true, message: 'Password changed. All other sessions have been logged out.' };
|
||||
var resp: { success: boolean; message: string; passwordWarning?: string } = { success: true, message: 'Password changed. All other sessions have been logged out.' };
|
||||
if (pwnedCount > 0) resp.passwordWarning = 'This password has appeared in ' + pwnedCount.toLocaleString() + ' data breaches. Consider choosing a different one.';
|
||||
res.json(resp);
|
||||
} catch (err) { console.error('[Auth] Change password error:', err.message); res.status(500).json({ error: 'Password change failed' }); }
|
||||
} catch (err: any) { console.error('[Auth] Change password error:', err.message); res.status(500).json({ error: 'Password change failed' }); }
|
||||
});
|
||||
|
||||
// Get current user
|
||||
|
|
@ -310,7 +310,7 @@ router.post('/ai-generate', upload.array('files', 10), async function(req, res)
|
|||
|
||||
var raw = result.content.trim();
|
||||
// Strip any leading text before the first { or --- (models sometimes add preamble)
|
||||
if (contentType !== 'presentation' || parseInt(questionCount) > 0) {
|
||||
if (contentType !== 'presentation' || parseInt(questionCount as any) > 0) {
|
||||
var jsonStart = raw.indexOf('{');
|
||||
if (jsonStart > 0) raw = raw.substring(jsonStart);
|
||||
}
|
||||
Loading…
Reference in a new issue