Password Manager experiment built on ATProto Spaces
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106import http from 'node:http';import fs from 'node:fs';import path from 'node:path';import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));const DIST_DIR = path.resolve(__dirname, 'dist');const PORT = parseInt(process.env.PORT || '3000', 10);const HOST = process.env.HOST || '0.0.0.0';
const MIME_TYPES = { '.html': 'text/html; charset=utf-8', '.js': 'application/javascript; charset=utf-8', '.mjs': 'application/javascript; charset=utf-8', '.css': 'text/css; charset=utf-8', '.json': 'application/json; charset=utf-8', '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml', '.ico': 'image/x-icon', '.woff': 'font/woff', '.woff2': 'font/woff2', '.ttf': 'font/ttf', '.wasm': 'application/wasm'};
const server = http.createServer((req, res) => { // CORS Headers res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', '*');
if (req.method === 'OPTIONS') { res.writeHead(204); res.end(); return; }
if (req.method !== 'GET' && req.method !== 'HEAD') { res.writeHead(405, { 'Content-Type': 'text/plain; charset=utf-8' }); res.end('Method Not Allowed'); return; }
const url = new URL(req.url, `http://${req.headers.host || 'localhost'}`); const urlPath = url.pathname;
// Handle /oauth-client-metadata.json specially if (urlPath === '/oauth-client-metadata.json') { const metadataPath = path.join(DIST_DIR, 'oauth-client-metadata.json'); if (fs.existsSync(metadataPath)) { const body = fs.readFileSync(metadataPath, 'utf8'); res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Content-Length': Buffer.byteLength(body), 'Cache-Control': 'no-cache' }); if (req.method === 'HEAD') { res.end(); return; } res.end(body); return; } }
let safePath = path.normalize(urlPath).replace(/^(\.\.[\/\\])+/, ''); let filePath = path.join(DIST_DIR, safePath);
// If path is a directory, check index.html if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) { filePath = path.join(filePath, 'index.html'); }
// SPA fallback: if file does not exist, serve index.html if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile()) { filePath = path.join(DIST_DIR, 'index.html'); }
const ext = path.extname(filePath).toLowerCase(); const contentType = MIME_TYPES[ext] || 'application/octet-stream';
const stat = fs.statSync(filePath); res.writeHead(200, { 'Content-Type': contentType, 'Content-Length': stat.size, 'Cache-Control': filePath.includes('/assets/') ? 'public, max-age=31536000, immutable' : 'no-cache' });
if (req.method === 'HEAD') { res.end(); return; }
const stream = fs.createReadStream(filePath); stream.pipe(res);});
server.listen(PORT, HOST, () => { console.log(`2password web app listening on http://${HOST}:${PORT}`);});