// Static preview of the prebuilt frontend. No API or backend services.consthttp=require('node:http');constfs=require('node:fs');constpath=require('node:path');constroot=path.join(__dirname,'dist');constport=Number(process.env.PORT||process.argv[2]||5175);consttypes={'.html':'text/html; charset=utf-8','.js':'text/javascript; charset=utf-8','.css':'text/css; charset=utf-8','.svg':'image/svg+xml','.png':'image/png','.jpg':'image/jpeg','.woff2':'font/woff2'};if (!fs.existsSync(path.join(root,'index.html'))){console.error('Build files are missing. Run npm install and npm run build first.');process.exit(1);}constserver=http.createServer((request,response)=>{if (!['GET','HEAD'].includes(request.method)){response.writeHead(405);response.end();return;}letpathname;try{pathname=decodeURIComponent(newURL(request.url,'http://localhost').pathname);}catch{response.writeHead(400);response.end();return;}constfile=path.resolve(root,'.'+pathname+(pathname.endsWith('/')?'index.html':''));if (!file.startsWith(root+path.sep)){response.writeHead(403);response.end();return;}fs.stat(file,(error,stat)=>{if (error||!stat.isFile()){response.writeHead(404);response.end('Not found');return;}response.writeHead(200,{'Content-Type':types[path.extname(file)]||'application/octet-stream','Cache-Control':'no-store','X-Content-Type-Options':'nosniff'});if (request.method==='HEAD')response.end();elsefs.createReadStream(file).pipe(response);});});server.on('error',error=>{console.error(error.code==='EADDRINUSE'?`Port ${port} is already in use. Close the existing preview, or set a different PORT.`:error.message);process.exit(1);});server.listen(port,'127.0.0.1',()=>console.log(`Testcraft Studio: http://127.0.0.1:${port}/\nKeep this terminal open. Press Ctrl+C to stop.`));
Top comments (0)
Subscribe
We're a place where coders share, stay up-to-date and grow their careers.
Top comments (0)