// src/server.mjs import { readFileSync } from 'node:fs'; import { createServer } from 'node:http'; import { createScheduleRouter, scheduleDeclarations } from '@turnzero/schedule'; import { jobs } from './jobs.mjs'; // The router for the schedules manifest.json declares, each answered by its // handler in jobs.mjs. It refuses a handler the manifest does not declare // and a declared schedule with no handler, so a mismatch stops the service // as it starts, before any run. export function createJobRouter() { const manifest = JSON.parse(readFileSync(new URL('../manifest.json', import.meta.url), 'utf8')); return createScheduleRouter({ schedules: scheduleDeclarations(manifest), handlers: jobs }); } export function createAppServer() { const router = createJobRouter(); return createServer(async (request, response) => { // The deployed runtime's abort signal: end the response when it fires. request.signal?.addEventListener('abort', () => response.destroy(), { once: true }); // The schedule's path first: the router answers it, and leaves every other path to the routes below. if (await router.handle(request, response)) return; const send = (status, type, body) => { if (response.destroyed) return; response.writeHead(status, { 'content-type': type }); response.end(body); }; // A target that does not parse as a URL names no route, so it is answered 404 below. let pathname = null; try { pathname = new URL(request.url, 'http://localhost').pathname; } catch {} if (request.method === 'GET' && pathname === '/health') return send(200, 'application/json', JSON.stringify({ ok: true })); if (request.method === 'GET' && pathname === '/api/hello') return send(200, 'text/plain; charset=utf-8', 'hello world'); send(404, 'application/json', JSON.stringify({ error: 'not_found' })); }); }