Rebuild Mode1Svelte with SvelteKit + Node.js adapter

- Migrated from Bun/Hono to modern SvelteKit tech stack
- Implemented complete authentication module (Azure MSAL + PocketBase)
- Created 5 API endpoints for auth operations (config, graph token, validate, refresh, compare)
- Built interactive Svelte dashboard with mobile optimization (iPhone 16)
- Added Node.js adapter (@sveltejs/adapter-node) for production deployment
- Integrated Tailwind CSS with responsive design
- Fixed orchestrator to spawn Mode1Svelte with Node.js on port 3005
- Updated systemd service (job-info-test.service) to start orchestrator on port 3006
- Port configuration locked: 3005 = Mode1Svelte, 3006 = Orchestrator
- Full TypeScript type safety throughout application
- Services auto-managed by orchestrator with systemd integration
This commit is contained in:
2026-01-23 02:18:34 +00:00
parent d8d53ece93
commit 7b997dc354
33 changed files with 3793 additions and 1462 deletions
@@ -0,0 +1,54 @@
import { json, type RequestHandler } from '@sveltejs/kit';
import { BackendAuth, AuthConfigManager } from '$lib/auth/backend';
const backendAuth = new BackendAuth(
{
clientId: process.env.CLIENT_ID,
tenantId: process.env.TENANT_ID,
clientSecret: process.env.CLIENT_SECRET,
},
process.env.PB_DB
);
export const GET: RequestHandler = async () => {
try {
const { token, expiresOnISO } = await backendAuth.graphTokenManager.getTokenWithExpiry();
if (!token) {
return json({ success: false, error: 'Failed to acquire Graph token' }, { status: 500 });
}
// Decode JWT to show token details (for verification)
const parts = token.split('.');
let payload: any = {};
if (parts.length === 3) {
try {
const decoded = JSON.parse(Buffer.from(parts[1], 'base64').toString());
payload = {
aud: decoded.aud,
iss: decoded.iss,
scp: decoded.scp,
app_displayname: decoded.app_displayname,
iat: new Date(decoded.iat * 1000).toISOString(),
exp: new Date(decoded.exp * 1000).toISOString(),
};
} catch (e) {
// Silent fail - just show truncated token
}
}
return json({
success: true,
token: token.substring(0, 50) + '...',
fullToken: token, // Include full token for testing
expiresOn: expiresOnISO,
isValid: backendAuth.graphTokenManager.isTokenValid(),
tokenDetails: Object.keys(payload).length > 0 ? payload : 'Could not decode',
});
} catch (error) {
return json(
{ success: false, error: error instanceof Error ? error.message : 'Failed to acquire token' },
{ status: 500 }
);
}
};