Files
scrum-manager/server/app_spin.js.bak

138 lines
5.5 KiB
JavaScript

import { Hono } from 'hono';
import { handleRequest } from '@fermyon/spin-sdk';
const app = new Hono();
// Middleware to mock Express request/response specific methods if needed
// Or we just rewrite routes to use Hono context.
// Since rewriting all routes is heavy, let's try to mount simple wrappers
// or just import the router logic if we refactor routes.
// Given the implementation plan said "Re-implement routing logic",
// and the routes are currently Express routers, we probably need to wrap them
// or quickly rewrite them to Hono.
// Strategy: Import the routes and mount them.
// BUT Express routers won't work in Hono.
// We must rewrite the route definitions in this file or transformed files.
// For "quick deployment", I will inline the mounting of existing logic where possible,
// using the db_spin adapter.
import pool from './db_spin.js';
import bcrypt from 'bcryptjs';
// import { randomUUID } from 'crypto'; // Use global crypto
const randomUUID = () => crypto.randomUUID();
// --- AUTH ROUTES ---
app.post('/api/auth/login', async (c) => {
try {
const { email, password } = await c.req.json();
if (!email || !password) return c.json({ error: 'Email and password required' }, 400);
const [rows] = await pool.query('SELECT * FROM users WHERE email = ?', [email]);
if (rows.length === 0) return c.json({ error: 'Invalid email or password' }, 401);
const user = rows[0];
const valid = await bcrypt.compare(password, user.password_hash);
if (!valid) return c.json({ error: 'Invalid email or password' }, 401);
return c.json({
id: user.id, name: user.name, role: user.role, email: user.email,
color: user.color, avatar: user.avatar, dept: user.dept,
});
} catch (e) {
console.error(e);
return c.json({ error: 'Internal server error' }, 500);
}
});
app.post('/api/auth/register', async (c) => {
try {
const { name, email, password, role, dept } = await c.req.json();
if (!name || !email || !password) return c.json({ error: 'Required fields missing' }, 400);
const [existing] = await pool.query('SELECT id FROM users WHERE email = ?', [email]);
if (existing.length > 0) return c.json({ error: 'Email already registered' }, 409);
const id = randomUUID();
const password_hash = await bcrypt.hash(password, 10);
// ... (simplified avatar logic)
const avatar = name.substring(0, 2).toUpperCase();
const color = '#818cf8';
await pool.query(
'INSERT INTO users (id, name, role, email, password_hash, color, avatar, dept) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
[id, name, role || 'employee', email, password_hash, color, avatar, dept || '']
);
return c.json({ id, name, role: role || 'employee', email, color, avatar, dept: dept || '' }, 201);
} catch (e) {
console.error(e);
return c.json({ error: 'Internal server error' }, 500);
}
});
// --- TASKS ROUTES (Simplified for Wasm demo) ---
async function getFullTask(taskId) {
const [taskRows] = await pool.query('SELECT * FROM tasks WHERE id = ?', [taskId]);
if (taskRows.length === 0) return null;
const task = taskRows[0];
// For brevity, not fetching sub-resources in this quick conversion,
// but in full prod we would.
// ... complete implementation would replicate existing logic ...
return task;
}
app.get('/api/tasks', async (c) => {
try {
const [rows] = await pool.query('SELECT * FROM tasks ORDER BY created_at DESC');
// Simplify for now: Just return tasks
return c.json(rows);
} catch (e) {
console.error(e);
return c.json({ error: 'Internal server error' }, 500);
}
});
app.post('/api/tasks', async (c) => {
try {
const { title, description, status, priority, assignee, reporter, dueDate } = await c.req.json();
const id = randomUUID();
await pool.query(
'INSERT INTO tasks (id, title, description, status, priority, assignee_id, reporter_id, due_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
[id, title, description || '', status || 'todo', priority || 'medium', assignee || null, reporter || null, dueDate || null]
);
return c.json({ id, title, status }, 201);
} catch (e) {
console.error(e);
return c.json({ error: 'Internal server error' }, 500);
}
});
// Health check
app.get('/api/health', (c) => c.json({ status: 'ok', engine: 'spin-wasm' }));
// Export the Spin handler
export const spinHandler = async (req, res) => {
// Spin generic handler interacting with Hono?
// Hono has a fetch method: app.fetch(request, env, ctx)
// Spin request is slightly different, but let's see if we can adapt.
// Actually, Spin JS SDK v2 exports `handleRequest` which takes (request, response).
// Hono might need an adapter.
// Simple adapter for Hono .fetch to Spin
// Construct standard Request object from Spin calls if needed,
// but simpler to use Hono's handle() if passing standard web standards.
// Assuming standard web signature is passed by recent Spin SDKs or we use 'node-adapter' if built via bundling.
// But since we are likely using a bundler, strict Spin API is:
// export async function handleRequest(request: Request): Promise<Response>
return app.fetch(req);
};
// If using valid Spin JS plugin that looks for `handleRequest` as default export or named export
// We will export it as `handleRequest` (default)
export default async function (req) {
return await app.fetch(req);
}