@studiometa/trafic-agent 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +92 -89
- package/dist/cli.js.map +1 -1
- package/dist/index.js +3 -41
- package/dist/server-D0N_6y4c.js +687 -0
- package/dist/server-D0N_6y4c.js.map +1 -0
- package/dist/server.js +2 -9
- package/dist/setup/ddev.d.ts.map +1 -1
- package/dist/setup-BfiuQiwa.js +933 -0
- package/dist/setup-BfiuQiwa.js.map +1 -0
- package/package.json +6 -6
- package/dist/index-CqtdZoAx.js +0 -904
- package/dist/index-CqtdZoAx.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/server-CHT47EXr.js +0 -618
- package/dist/server-CHT47EXr.js.map +0 -1
- package/dist/server.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server-CHT47EXr.js","sources":["../src/utils/auth.ts","../src/utils/ddev.ts","../src/utils/db.ts","../src/utils/project-config.ts","../src/server.ts"],"sourcesContent":["import type { AuthConfig, AuthRequest, AuthResult, AuthRule } from \"../types.js\";\n\n/**\n * Check if an IP matches a pattern (supports CIDR notation)\n */\nexport function matchIp(ip: string, pattern: string): boolean {\n // Exact match\n if (ip === pattern) return true;\n\n // CIDR notation\n if (pattern.includes(\"/\")) {\n return matchCidr(ip, pattern);\n }\n\n // Wildcard (e.g., 192.168.*)\n if (pattern.includes(\"*\")) {\n const regex = new RegExp(\n \"^\" + pattern.replace(/\\./g, \"\\\\.\").replace(/\\*/g, \".*\") + \"$\",\n );\n return regex.test(ip);\n }\n\n return false;\n}\n\n/**\n * Match IP against CIDR range\n */\nfunction matchCidr(ip: string, cidr: string): boolean {\n const [range, bits] = cidr.split(\"/\");\n const mask = parseInt(bits, 10);\n\n const ipNum = ipToNumber(ip);\n const rangeNum = ipToNumber(range);\n\n if (ipNum === null || rangeNum === null) return false;\n\n const maskNum = ~((1 << (32 - mask)) - 1);\n return (ipNum & maskNum) === (rangeNum & maskNum);\n}\n\n/**\n * Convert IP string to number\n */\nfunction ipToNumber(ip: string): number | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) return null;\n\n let num = 0;\n for (const part of parts) {\n const n = parseInt(part, 10);\n if (isNaN(n) || n < 0 || n > 255) return null;\n num = (num << 8) | n;\n }\n return num >>> 0; // Convert to unsigned\n}\n\n/**\n * Match hostname against a glob pattern\n */\nexport function matchHostname(hostname: string, pattern: string): boolean {\n // Exact match\n if (hostname === pattern) return true;\n\n // Glob pattern\n const regex = new RegExp(\n \"^\" +\n pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*/g, \".*\")\n .replace(/\\?/g, \".\") +\n \"$\",\n );\n return regex.test(hostname);\n}\n\n/**\n * Parse Basic auth header\n */\nexport function parseBasicAuth(\n header: string,\n): { username: string; password: string } | null {\n if (!header.startsWith(\"Basic \")) return null;\n\n try {\n const encoded = header.slice(6);\n const decoded = Buffer.from(encoded, \"base64\").toString(\"utf-8\");\n const colonIndex = decoded.indexOf(\":\");\n if (colonIndex === -1) return null;\n\n return {\n username: decoded.slice(0, colonIndex),\n password: decoded.slice(colonIndex + 1),\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Parse Bearer token from header\n */\nexport function parseBearerToken(header: string): string | null {\n if (!header.startsWith(\"Bearer \")) return null;\n return header.slice(7);\n}\n\n/**\n * Check authentication for a request\n */\nexport function checkAuth(request: AuthRequest, config: AuthConfig): AuthResult {\n const { hostname, ip, authorization } = request;\n\n // Get real IP (handle X-Forwarded-For)\n const realIp = request.forwardedFor?.split(\",\")[0].trim() ?? ip;\n\n // Check IP whitelist first (always allows)\n for (const pattern of config.allowedIps) {\n if (matchIp(realIp, pattern)) {\n return { allowed: true, reason: \"ip\" };\n }\n }\n\n // Check per-hostname rules\n for (const rule of config.rules) {\n if (matchHostname(hostname, rule.match)) {\n return checkRule(rule, realIp, authorization, config);\n }\n }\n\n // Apply default policy\n return applyDefaultPolicy(config, realIp, authorization);\n}\n\n/**\n * Check a specific rule\n */\nfunction checkRule(\n rule: AuthRule,\n ip: string,\n authorization: string | undefined,\n config: AuthConfig,\n): AuthResult {\n // Rule-specific IP whitelist\n if (rule.allowedIps) {\n for (const pattern of rule.allowedIps) {\n if (matchIp(ip, pattern)) {\n return { allowed: true, reason: \"rule\" };\n }\n }\n }\n\n switch (rule.policy) {\n case \"allow\":\n return { allowed: true, reason: \"rule\" };\n\n case \"deny\":\n return { allowed: false, reason: \"rule\" };\n\n case \"token\": {\n if (!authorization) return { allowed: false, reason: \"rule\" };\n const token = parseBearerToken(authorization);\n const tokens = rule.tokens ?? config.tokens;\n if (token && tokens.includes(token)) {\n return { allowed: true, reason: \"token\" };\n }\n return { allowed: false, reason: \"rule\" };\n }\n\n case \"basic\": {\n if (!authorization) return { allowed: false, reason: \"rule\" };\n const creds = parseBasicAuth(authorization);\n if (creds) {\n const credString = `${creds.username}:${creds.password}`;\n if (config.basicAuth.includes(credString)) {\n return { allowed: true, reason: \"basic\" };\n }\n }\n return { allowed: false, reason: \"rule\" };\n }\n\n default:\n return { allowed: false, reason: \"rule\" };\n }\n}\n\n/**\n * Apply default policy\n */\nfunction applyDefaultPolicy(\n config: AuthConfig,\n ip: string,\n authorization: string | undefined,\n): AuthResult {\n switch (config.defaultPolicy) {\n case \"allow\":\n return { allowed: true, reason: \"default\" };\n\n case \"deny\":\n return { allowed: false, reason: \"default\" };\n\n case \"basic\": {\n if (!authorization) return { allowed: false, reason: \"default\" };\n const creds = parseBasicAuth(authorization);\n if (creds) {\n const credString = `${creds.username}:${creds.password}`;\n if (config.basicAuth.includes(credString)) {\n return { allowed: true, reason: \"basic\" };\n }\n }\n // Also check tokens as fallback\n const token = parseBearerToken(authorization);\n if (token && config.tokens.includes(token)) {\n return { allowed: true, reason: \"token\" };\n }\n return { allowed: false, reason: \"default\" };\n }\n\n case \"token\": {\n if (!authorization) return { allowed: false, reason: \"default\" };\n const token = parseBearerToken(authorization);\n if (token && config.tokens.includes(token)) {\n return { allowed: true, reason: \"token\" };\n }\n return { allowed: false, reason: \"default\" };\n }\n\n default:\n return { allowed: false, reason: \"default\" };\n }\n}\n","import { readFileSync, existsSync, watch } from \"node:fs\";\nimport { execSync } from \"node:child_process\";\nimport type { DdevProject } from \"../types.js\";\n\n// Simple YAML parser for project_list.yaml (avoid dependencies)\n// The file format is simple: key: value pairs with quoted strings\nfunction parseSimpleYaml(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n const lines = content.split(\"\\n\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n const colonIndex = trimmed.indexOf(\":\");\n if (colonIndex === -1) continue;\n\n const key = trimmed.slice(0, colonIndex).trim();\n let value = trimmed.slice(colonIndex + 1).trim();\n\n // Remove quotes\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n result[key] = value;\n }\n\n return result;\n}\n\n/**\n * Load projects from DDEV's project_list.yaml\n * Returns a map of project name -> app root path\n */\nexport function loadProjectList(\n projectListPath: string,\n): Map<string, string> {\n if (!existsSync(projectListPath)) {\n return new Map();\n }\n\n const content = readFileSync(projectListPath, \"utf-8\");\n const parsed = parseSimpleYaml(content);\n\n return new Map(Object.entries(parsed));\n}\n\n/**\n * Build a hostname -> project name index\n */\nexport function buildHostnameIndex(\n projects: Map<string, string>,\n tld: string,\n): Map<string, string> {\n const index = new Map<string, string>();\n\n for (const [name] of projects) {\n // Primary hostname: project-name.tld\n index.set(`${name}.${tld}`, name);\n }\n\n return index;\n}\n\n/**\n * Get project name from hostname\n */\nexport function getProjectFromHostname(\n hostname: string,\n index: Map<string, string>,\n): string | undefined {\n return index.get(hostname);\n}\n\n/**\n * Watch project_list.yaml for changes\n */\nexport function watchProjectList(\n projectListPath: string,\n onChange: () => void,\n): void {\n if (!existsSync(projectListPath)) {\n console.warn(`Project list not found: ${projectListPath}`);\n return;\n }\n\n watch(projectListPath, (eventType) => {\n if (eventType === \"change\") {\n onChange();\n }\n });\n}\n\n/**\n * Get detailed project info using ddev describe\n */\nexport function getProjectInfo(name: string): DdevProject | undefined {\n try {\n const output = execSync(`ddev describe ${name} -j`, {\n encoding: \"utf-8\",\n timeout: 10000,\n });\n const data = JSON.parse(output);\n\n if (!data.raw) return undefined;\n\n const raw = data.raw;\n return {\n name: raw.name,\n status: raw.status,\n appRoot: raw.approot,\n httpURLs: raw.httpURLs ?? [],\n httpsURLs: raw.httpsURLs ?? [],\n type: raw.type,\n phpVersion: raw.php_version,\n dbType: raw.dbinfo?.dbType,\n };\n } catch {\n return undefined;\n }\n}\n\n/**\n * Start a DDEV project\n */\nexport function startProject(name: string): boolean {\n try {\n execSync(`ddev start ${name}`, {\n encoding: \"utf-8\",\n timeout: 120000, // 2 minutes\n stdio: \"pipe\",\n });\n return true;\n } catch (error) {\n console.error(`Failed to start project ${name}:`, error);\n return false;\n }\n}\n\n/**\n * Stop a DDEV project\n */\nexport function stopProject(name: string): boolean {\n try {\n execSync(`ddev stop ${name}`, {\n encoding: \"utf-8\",\n timeout: 60000, // 1 minute\n stdio: \"pipe\",\n });\n return true;\n } catch (error) {\n console.error(`Failed to stop project ${name}:`, error);\n return false;\n }\n}\n\n/**\n * List all DDEV projects with their status\n */\nexport function listProjects(): DdevProject[] {\n try {\n const output = execSync(\"ddev list -j\", {\n encoding: \"utf-8\",\n timeout: 30000,\n });\n const data = JSON.parse(output);\n\n if (!Array.isArray(data)) return [];\n\n return data.map((p: Record<string, unknown>) => ({\n name: p.name as string,\n status: p.status as DdevProject[\"status\"],\n appRoot: p.approot as string,\n httpURLs: (p.httpURLs as string[]) ?? [],\n httpsURLs: (p.httpsURLs as string[]) ?? [],\n type: p.type as string,\n }));\n } catch {\n return [];\n }\n}\n","import Database from \"better-sqlite3\";\nimport type { ProjectRecord, AccessLog } from \"../types.js\";\n\nlet db: Database.Database | null = null;\n\n/**\n * Initialize the database connection and schema\n */\nexport function initDb(dbPath: string): Database.Database {\n db = new Database(dbPath);\n db.pragma(\"journal_mode = WAL\");\n\n // Create tables\n db.exec(`\n CREATE TABLE IF NOT EXISTS projects (\n name TEXT PRIMARY KEY,\n last_access INTEGER NOT NULL,\n status TEXT NOT NULL DEFAULT 'stopped'\n );\n\n CREATE TABLE IF NOT EXISTS access_logs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project TEXT NOT NULL,\n timestamp INTEGER NOT NULL,\n ip TEXT NOT NULL,\n user_agent TEXT NOT NULL,\n path TEXT NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_access_logs_project ON access_logs(project);\n CREATE INDEX IF NOT EXISTS idx_access_logs_timestamp ON access_logs(timestamp);\n `);\n\n return db;\n}\n\n/**\n * Get the database instance\n */\nexport function getDb(): Database.Database {\n if (!db) {\n throw new Error(\"Database not initialized. Call initDb first.\");\n }\n return db;\n}\n\n/**\n * Close the database connection\n */\nexport function closeDb(): void {\n if (db) {\n db.close();\n db = null;\n }\n}\n\n/**\n * Update project last access time\n */\nexport function updateProjectAccess(name: string): void {\n const database = getDb();\n const stmt = database.prepare(`\n INSERT INTO projects (name, last_access, status)\n VALUES (?, ?, 'running')\n ON CONFLICT(name) DO UPDATE SET last_access = excluded.last_access\n `);\n stmt.run(name, Date.now());\n}\n\n/**\n * Get project record\n */\nexport function getProject(name: string): ProjectRecord | undefined {\n const database = getDb();\n const stmt = database.prepare(\n \"SELECT name, last_access as lastAccess, status FROM projects WHERE name = ?\",\n );\n return stmt.get(name) as ProjectRecord | undefined;\n}\n\n/**\n * Set project status\n */\nexport function setProjectStatus(\n name: string,\n status: ProjectRecord[\"status\"],\n): void {\n const database = getDb();\n const stmt = database.prepare(`\n INSERT INTO projects (name, last_access, status)\n VALUES (?, ?, ?)\n ON CONFLICT(name) DO UPDATE SET status = excluded.status\n `);\n stmt.run(name, Date.now(), status);\n}\n\n/**\n * Get idle projects (last access older than threshold)\n */\nexport function getIdleProjects(thresholdMs: number): ProjectRecord[] {\n const database = getDb();\n const cutoff = Date.now() - thresholdMs;\n const stmt = database.prepare(`\n SELECT name, last_access as lastAccess, status\n FROM projects\n WHERE last_access < ? AND status = 'running'\n `);\n return stmt.all(cutoff) as ProjectRecord[];\n}\n\n/**\n * Log an access\n */\nexport function logAccess(log: Omit<AccessLog, \"id\">): void {\n const database = getDb();\n const stmt = database.prepare(`\n INSERT INTO access_logs (project, timestamp, ip, user_agent, path)\n VALUES (?, ?, ?, ?, ?)\n `);\n stmt.run(log.project, log.timestamp, log.ip, log.userAgent, log.path);\n}\n\n/**\n * Get recent access logs for a project\n */\nexport function getAccessLogs(project: string, limit = 100): AccessLog[] {\n const database = getDb();\n const stmt = database.prepare(`\n SELECT id, project, timestamp, ip, user_agent as userAgent, path\n FROM access_logs\n WHERE project = ?\n ORDER BY timestamp DESC\n LIMIT ?\n `);\n return stmt.all(project, limit) as AccessLog[];\n}\n\n/**\n * Clean old access logs (older than given days)\n */\nexport function cleanOldLogs(days: number): number {\n const database = getDb();\n const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;\n const stmt = database.prepare(\"DELETE FROM access_logs WHERE timestamp < ?\");\n const result = stmt.run(cutoff);\n return result.changes;\n}\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Per-project Trafic configuration\n * Read from .ddev/config.trafic.yaml\n */\nexport interface ProjectConfig {\n /** Auth policy override: allow | deny | basic | token */\n auth_policy?: \"allow\" | \"deny\" | \"basic\" | \"token\";\n /** Idle timeout override: \"never\" or duration like \"30m\", \"4h\" */\n idle_timeout?: string;\n}\n\n/**\n * Simple YAML parser for config.trafic.yaml\n * Only supports simple key: value pairs (no nesting, no arrays)\n */\nfunction parseSimpleYaml(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n const lines = content.split(\"\\n\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Skip empty lines and comments\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n const colonIndex = trimmed.indexOf(\":\");\n if (colonIndex === -1) continue;\n\n const key = trimmed.slice(0, colonIndex).trim();\n let value = trimmed.slice(colonIndex + 1).trim();\n\n // Remove quotes if present\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n result[key] = value;\n }\n\n return result;\n}\n\n/**\n * Load project-specific Trafic config from .ddev/config.trafic.yaml\n */\nexport function loadProjectConfig(projectDir: string): ProjectConfig {\n const configPath = join(projectDir, \".ddev\", \"config.trafic.yaml\");\n\n if (!existsSync(configPath)) {\n return {};\n }\n\n try {\n const content = readFileSync(configPath, \"utf-8\");\n const parsed = parseSimpleYaml(content);\n\n const config: ProjectConfig = {};\n\n // Validate auth_policy\n if (parsed.auth_policy) {\n const policy = parsed.auth_policy.toLowerCase();\n if ([\"allow\", \"deny\", \"basic\", \"token\"].includes(policy)) {\n config.auth_policy = policy as ProjectConfig[\"auth_policy\"];\n }\n }\n\n // Validate idle_timeout\n if (parsed.idle_timeout) {\n config.idle_timeout = parsed.idle_timeout;\n }\n\n return config;\n } catch (error) {\n console.warn(`Failed to load project config from ${configPath}:`, error);\n return {};\n }\n}\n\n/**\n * Check if a project should never be stopped (idle_timeout = \"never\")\n */\nexport function shouldNeverStop(config: ProjectConfig): boolean {\n return config.idle_timeout?.toLowerCase() === \"never\";\n}\n\n/**\n * Get idle timeout in milliseconds, or undefined to use global default\n */\nexport function getIdleTimeoutMs(config: ProjectConfig): number | undefined {\n if (!config.idle_timeout) return undefined;\n if (shouldNeverStop(config)) return undefined;\n\n // Parse duration string (e.g., \"30m\", \"4h\", \"2h30m\")\n const regex = /(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?/;\n const match = config.idle_timeout.match(regex);\n if (!match) return undefined;\n\n const hours = parseInt(match[1] ?? \"0\", 10);\n const minutes = parseInt(match[2] ?? \"0\", 10);\n const seconds = parseInt(match[3] ?? \"0\", 10);\n\n const ms = (hours * 3600 + minutes * 60 + seconds) * 1000;\n return ms > 0 ? ms : undefined;\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { readFileSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { AgentConfig, AuthConfig } from \"./types.js\";\nimport { checkAuth } from \"./utils/auth.js\";\nimport {\n loadProjectList,\n buildHostnameIndex,\n watchProjectList,\n startProject,\n getProjectInfo,\n} from \"./utils/ddev.js\";\nimport {\n initDb,\n updateProjectAccess,\n logAccess,\n setProjectStatus,\n getProject,\n} from \"./utils/db.js\";\nimport { loadProjectConfig } from \"./utils/project-config.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// State\nlet config: AgentConfig;\nlet projectList: Map<string, string>;\nlet hostnameIndex: Map<string, string>;\n// Cache of per-project configs (project name -> config)\nconst projectConfigs = new Map<string, ReturnType<typeof loadProjectConfig>>();\n\n/**\n * Load HTML template\n */\nfunction loadTemplate(name: string): string {\n const templatePath = resolve(__dirname, \"..\", \"templates\", `${name}.html`);\n try {\n return readFileSync(templatePath, \"utf-8\");\n } catch {\n return `<html><body><h1>${name}</h1></body></html>`;\n }\n}\n\n/**\n * Get effective auth config for a project (merges global + per-project)\n */\nfunction getEffectiveAuthConfig(projectName: string | undefined): AuthConfig {\n if (!projectName) return config.auth;\n\n const projectConfig = projectConfigs.get(projectName);\n if (!projectConfig?.auth_policy) return config.auth;\n\n // Override default policy with project-specific policy\n return {\n ...config.auth,\n defaultPolicy: projectConfig.auth_policy,\n };\n}\n\n/**\n * Handle forward auth requests from Traefik\n * Traefik sends the original request headers, we return 200 (allow) or 401 (deny)\n */\nfunction handleAuth(req: IncomingMessage, res: ServerResponse): void {\n const hostname = req.headers[\"x-forwarded-host\"] as string ?? \"\";\n const ip = req.headers[\"x-forwarded-for\"] as string ?? req.socket.remoteAddress ?? \"\";\n const authorization = req.headers[\"authorization\"];\n const path = req.headers[\"x-forwarded-uri\"] as string ?? \"/\";\n\n // Find project from hostname\n const projectName = hostnameIndex.get(hostname);\n\n // Get effective auth config (global + per-project overrides)\n const authConfig = getEffectiveAuthConfig(projectName);\n\n const result = checkAuth(\n {\n hostname,\n ip: ip.split(\",\")[0].trim(),\n authorization,\n forwardedFor: ip,\n },\n authConfig,\n );\n\n if (result.allowed) {\n // Log access and update last access time\n if (projectName) {\n updateProjectAccess(projectName);\n logAccess({\n project: projectName,\n timestamp: Date.now(),\n ip: ip.split(\",\")[0].trim(),\n userAgent: req.headers[\"user-agent\"] ?? \"\",\n path,\n });\n }\n\n res.writeHead(200);\n res.end();\n } else {\n // Return 401 with WWW-Authenticate header for basic auth\n res.writeHead(401, {\n \"WWW-Authenticate\": 'Basic realm=\"Trafic\"',\n });\n res.end(\"Unauthorized\");\n }\n}\n\n/**\n * Handle errors middleware requests (502 from Traefik)\n * When a project is stopped, Traefik returns 502. We show a waiting page and start the project.\n */\nasync function handleErrors(\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<void> {\n const hostname = req.headers[\"x-forwarded-host\"] as string ?? req.headers.host ?? \"\";\n const projectName = hostnameIndex.get(hostname);\n\n if (!projectName) {\n // Unknown project\n const template = loadTemplate(\"error\");\n res.writeHead(404, { \"Content-Type\": \"text/html\" });\n res.end(template.replace(\"{{message}}\", \"Project not found\"));\n return;\n }\n\n // Check if project is already starting\n const record = getProject(projectName);\n if (record?.status === \"starting\") {\n // Show waiting page\n const template = loadTemplate(\"wait\");\n res.writeHead(503, {\n \"Content-Type\": \"text/html\",\n \"Retry-After\": \"5\",\n });\n res.end(\n template\n .replace(/\\{\\{project\\}\\}/g, projectName)\n .replace(/\\{\\{hostname\\}\\}/g, hostname),\n );\n return;\n }\n\n // Mark as starting\n setProjectStatus(projectName, \"starting\");\n\n // Show waiting page immediately\n const template = loadTemplate(\"wait\");\n res.writeHead(503, {\n \"Content-Type\": \"text/html\",\n \"Retry-After\": \"5\",\n });\n res.end(\n template\n .replace(/\\{\\{project\\}\\}/g, projectName)\n .replace(/\\{\\{hostname\\}\\}/g, hostname),\n );\n\n // Start project in background\n setTimeout(() => {\n const success = startProject(projectName);\n setProjectStatus(projectName, success ? \"running\" : \"stopped\");\n }, 100);\n}\n\n/**\n * Handle status polling requests\n */\nfunction handleStatus(req: IncomingMessage, res: ServerResponse): void {\n const url = new URL(req.url ?? \"/\", `http://${req.headers.host}`);\n const projectName = url.searchParams.get(\"project\");\n\n if (!projectName) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Missing project parameter\" }));\n return;\n }\n\n const info = getProjectInfo(projectName);\n const record = getProject(projectName);\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n name: projectName,\n status: info?.status ?? record?.status ?? \"unknown\",\n ready: info?.status === \"running\",\n }),\n );\n}\n\n/**\n * Request handler\n */\nasync function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<void> {\n const url = req.url ?? \"/\";\n\n try {\n // Route requests\n if (url === \"/__auth__\" || url.startsWith(\"/__auth__/\")) {\n handleAuth(req, res);\n } else if (url === \"/__status__\" || url.startsWith(\"/__status__/\")) {\n handleStatus(req, res);\n } else if (url === \"/__health__\") {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ status: \"ok\", version: \"__VERSION__\" }));\n } else {\n // Default: errors middleware\n await handleErrors(req, res);\n }\n } catch (error) {\n console.error(\"Request error:\", error);\n res.writeHead(500, { \"Content-Type\": \"text/plain\" });\n res.end(\"Internal Server Error\");\n }\n}\n\n/**\n * Reload project list and their configs\n */\nfunction reloadProjects(): void {\n projectList = loadProjectList(config.projectListPath);\n hostnameIndex = buildHostnameIndex(projectList, config.tld);\n\n // Load per-project configs\n projectConfigs.clear();\n for (const [name, projectDir] of projectList) {\n const projectConfig = loadProjectConfig(projectDir);\n if (projectConfig.auth_policy || projectConfig.idle_timeout) {\n projectConfigs.set(name, projectConfig);\n console.log(` ${name}: auth=${projectConfig.auth_policy ?? \"default\"}, idle=${projectConfig.idle_timeout ?? \"default\"}`);\n }\n }\n\n console.log(`Loaded ${projectList.size} projects (${projectConfigs.size} with custom config)`);\n}\n\n/**\n * Start the agent server\n */\nexport function startServer(agentConfig: AgentConfig): void {\n config = agentConfig;\n\n // Initialize database\n initDb(config.dbPath);\n\n // Load projects\n reloadProjects();\n\n // Watch for changes\n watchProjectList(config.projectListPath, () => {\n console.log(\"Project list changed, reloading...\");\n reloadProjects();\n });\n\n // Create HTTP server\n const server = createServer((req, res) => {\n handleRequest(req, res).catch((error) => {\n console.error(\"Unhandled error:\", error);\n if (!res.headersSent) {\n res.writeHead(500);\n res.end(\"Internal Server Error\");\n }\n });\n });\n\n server.listen(config.port, () => {\n console.log(`Trafic agent listening on port ${config.port}`);\n console.log(`TLD: ${config.tld}`);\n console.log(`Projects: ${projectList.size}`);\n });\n}\n"],"names":["config","parseSimpleYaml","__dirname","template"],"mappings":"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"}
|
package/dist/server.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
|