Files

117 lines
3.7 KiB
JavaScript
Raw Permalink Normal View History

#!/usr/bin/env node
/**
* Map plaza.tkmind.cn -> 127.0.0.1 for local Plaza dev.
* Requires sudo to edit /etc/hosts and /etc/resolver.
*
* macOS + Tailscale/Clash fake-ip: /etc/hosts alone is not enough — browsers may
* still resolve 198.18.x.x. Per-domain resolver forces local DNS server.
*
* Usage:
* node scripts/setup-plaza-local-dns.mjs
* node scripts/setup-plaza-local-dns.mjs --remove
*/
import fs from 'node:fs';
import path from 'node:path';
import { execSync } from 'node:child_process';
const HOST = process.env.PLAZA_LOCAL_HOST ?? 'plaza.tkmind.cn';
const IP = process.env.PLAZA_LOCAL_IP ?? '127.0.0.1';
const DNS_PORT = Number(process.env.PLAZA_LOCAL_DNS_PORT ?? 5533);
const MARKER = '# tkmind-plaza-local';
const RESOLVER_MARKER = '# tkmind-plaza-local';
const LINE = `${IP} ${HOST} ${MARKER}`;
const remove = process.argv.includes('--remove');
const hostsPath = '/etc/hosts';
const resolverDir = '/etc/resolver';
const resolverPath = path.join(resolverDir, HOST);
const resolverBody = `nameserver 127.0.0.1\nport ${DNS_PORT}\n${RESOLVER_MARKER}\n`;
function flushDnsCache() {
try {
execSync('dscacheutil -flushcache', { stdio: 'ignore' });
execSync('killall -HUP mDNSResponder', { stdio: 'ignore' });
} catch {
// best effort
}
}
function writeResolver() {
fs.mkdirSync(resolverDir, { recursive: true });
fs.writeFileSync(resolverPath, resolverBody, 'utf8');
}
function removeResolver() {
try {
if (fs.existsSync(resolverPath)) fs.unlinkSync(resolverPath);
} catch {
// ignore
}
}
const current = fs.readFileSync(hostsPath, 'utf8');
const lines = current.split('\n');
const filtered = lines.filter(
(line) => !line.includes(MARKER) && !line.match(new RegExp(`\\s${HOST.replace('.', '\\.')}(\\s|$)`)),
);
if (remove) {
const next = filtered.join('\n').replace(/\n?$/, '\n');
if (filtered.length !== lines.length) {
execSync(`tee ${hostsPath}`, { input: next, stdio: ['pipe', 'inherit', 'inherit'] });
console.log(`已移除 hosts 中的 ${HOST}`);
} else {
console.log(`hosts 中未找到 ${HOST},无需移除`);
}
removeResolver();
flushDnsCache();
console.log('已移除 per-domain resolver');
process.exit(0);
}
const hostsReady = lines.some(
(line) => line.includes(MARKER) || new RegExp(`\\s${HOST.replace('.', '\\.')}(\\s|$)`).test(line),
);
const resolverReady =
fs.existsSync(resolverPath) && fs.readFileSync(resolverPath, 'utf8').trim() === resolverBody.trim();
if (hostsReady && resolverReady) {
console.log(`${HOST} 本地解析已配置(hosts + resolver)`);
process.exit(0);
}
if (process.getuid?.() !== 0) {
console.log('需要 root 权限写入 /etc/hosts 和 /etc/resolver,请执行:');
console.log(` sudo node ${process.argv[1]}`);
process.exit(1);
}
if (!hostsReady) {
const next = `${filtered.join('\n').replace(/\n?$/, '\n')}${LINE}\n`;
try {
execSync(`tee ${hostsPath}`, { input: next, stdio: ['pipe', 'inherit', 'inherit'] });
console.log(`已添加 hosts:${LINE}`);
} catch {
console.error('写入 /etc/hosts 失败,请手动执行:');
console.error(` sudo sh -c 'echo "${LINE}" >> /etc/hosts'`);
process.exit(1);
}
} else {
console.log(`${HOST} 已在 /etc/hosts 中指向本地`);
}
try {
writeResolver();
console.log(`已添加 resolver:${resolverPath} -> 127.0.0.1:${DNS_PORT}`);
} catch (err) {
console.error('写入 /etc/resolver 失败:', err instanceof Error ? err.message : err);
process.exit(1);
}
flushDnsCache();
console.log('已刷新 DNS 缓存');
console.log('');
console.log('下一步:');
console.log(' pnpm dev:plaza # 含本地 DNS + Plaza 服务');
console.log(' sudo pnpm dev:plaza-proxy # HTTPS :443 代理');