/**
 * Static file server injector.
 *
 * When a framework has no start command (e.g., static-only builds from
 * Vite SPA, Gatsby, Eleventy), this module injects a minimal file server
 * so there's always a valid start command in launch.json.
 *
 * The server is a small Node.js http script that:
 * - Serves files from the build output directory
 * - Returns index.html for non-file routes (SPA support)
 * - Sets appropriate cache headers
 */
import { join } from 'node:path';
import { writeFileSync, mkdirSync } from 'node:fs';
/**
 * The static server script, inlined as a string.
 *
 * Written as ESM so it works under projects that ship
 * `"type": "module"` in package.json (which is the modern default,
 * including create-vite, create-next-app, etc.). Node treats `.js`
 * files as ESM when the surrounding package.json says so, and CJS
 * `require` is undefined in that scope.
 *
 * For projects with `"type": "commonjs"` (or no type field at all,
 * which defaults to CJS), Node also accepts ESM `.js` modules —
 * the import statements just work via the static-import path.
 */
const STATIC_SERVER_SCRIPT = `#!/usr/bin/env node
/**
 * Minimal static file server — auto-generated by Agentuity build.
 * Serves files from the current directory with SPA fallback.
 */
import path from 'node:path';
import fs from 'node:fs';
import http from 'node:http';
import { fileURLToPath } from 'node:url';

const PORT = parseInt(process.env.PORT || '3000', 10);
const ROOT = path.dirname(fileURLToPath(import.meta.url));

const MIME_TYPES = {
   '.html': 'text/html',
   '.js': 'application/javascript',
   '.css': 'text/css',
   '.json': 'application/json',
   '.png': 'image/png',
   '.jpg': 'image/jpeg',
   '.jpeg': 'image/jpeg',
   '.gif': 'image/gif',
   '.svg': 'image/svg+xml',
   '.ico': 'image/x-icon',
   '.webp': 'image/webp',
   '.avif': 'image/avif',
   '.woff': 'font/woff',
   '.woff2': 'font/woff2',
   '.ttf': 'font/ttf',
   '.otf': 'font/otf',
   '.map': 'application/json',
   '.txt': 'text/plain',
   '.xml': 'application/xml',
   '.webmanifest': 'application/manifest+json',
};

function getMimeType(filePath) {
   const ext = path.extname(filePath).toLowerCase();
   return MIME_TYPES[ext] || 'application/octet-stream';
}

function isImmutableAsset(filePath) {
   // Hashed assets from bundlers (e.g., main-abc123.js)
   return /\\.[a-f0-9]{8,}\\./i.test(filePath);
}

const server = http.createServer((req, res) => {
   const url = new URL(req.url, \`http://localhost:\${PORT}\`);
   const filePath = path.join(ROOT, url.pathname);

   // Security: prevent directory traversal
   if (!filePath.startsWith(ROOT)) {
      res.writeHead(403);
      res.end('Forbidden');
      return;
   }

   // Try to serve the exact file
   if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
      const content = fs.readFileSync(filePath);
      const mime = getMimeType(filePath);
      const headers = { 'Content-Type': mime };

      // Immutable caching for hashed assets
      if (isImmutableAsset(filePath)) {
         headers['Cache-Control'] = 'public, max-age=31536000, immutable';
      } else {
         headers['Cache-Control'] = 'public, max-age=0, must-revalidate';
      }

      res.writeHead(200, headers);
      res.end(content);
      return;
   }

   // Try index.html in the directory
   if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {
      const indexPath = path.join(filePath, 'index.html');
      if (fs.existsSync(indexPath)) {
         const content = fs.readFileSync(indexPath);
         res.writeHead(200, { 'Content-Type': 'text/html', 'Cache-Control': 'public, max-age=0, must-revalidate' });
         res.end(content);
         return;
      }
   }

   // SPA fallback: serve root index.html for non-file routes
   const indexPath = path.join(ROOT, 'index.html');
   if (fs.existsSync(indexPath)) {
      const content = fs.readFileSync(indexPath);
      res.writeHead(200, { 'Content-Type': 'text/html', 'Cache-Control': 'public, max-age=0, must-revalidate' });
      res.end(content);
      return;
   }

   res.writeHead(404);
   res.end('Not Found');
});

server.listen(PORT, () => {
   console.log(\`Static server listening on port \${PORT}\`);
});
`;
/**
 * Inject a static file server into the build output directory.
 *
 * @param outputDir - Absolute path to the build output
 * @returns The start command for the injected server
 */
export function injectStaticServer(outputDir) {
    mkdirSync(outputDir, { recursive: true });
    const serverPath = join(outputDir, '_serve.js');
    writeFileSync(serverPath, STATIC_SERVER_SCRIPT, 'utf-8');
    return {
        startCommand: 'node _serve.js',
        serverEntry: '_serve.js',
    };
}
//# sourceMappingURL=static-server.js.map