b0f5d6a51c
Split platform admin and ops APIs into standalone admin-server.mjs with network guards; simplify billing to RMB token pricing, refactor user auth, and add rsync deploy plus local-test scripts and docs. Co-authored-by: Cursor <cursoragent@cursor.com>
84 lines
3.0 KiB
JavaScript
84 lines
3.0 KiB
JavaScript
/**
|
|
* Shared local test domain configuration.
|
|
*
|
|
* Default: *.localhost — browsers resolve these to 127.0.0.1 without /etc/hosts
|
|
* or fighting Cloudflare wildcard DNS on *.tkmind.cn (which serves AndU publicly).
|
|
*
|
|
* h5.localhost → MindSpace H5 (Vite :5173)
|
|
* adm.localhost → memind_adm (:8082)
|
|
* pla.localhost → Plaza Next.js (:3001)
|
|
* ops.localhost → Ops console SPA (:3002)
|
|
*
|
|
* HTTPS unified entry: https://<host>:8443 (pnpm dev:local-proxy, no sudo)
|
|
*/
|
|
import fs from 'node:fs';
|
|
|
|
export const LOCAL_IP = process.env.LOCAL_TEST_IP ?? '127.0.0.1';
|
|
export const DNS_PORT = Number(process.env.LOCAL_TEST_DNS_PORT ?? 5533);
|
|
export const DNS_MARKER = 'tkmind-local-test';
|
|
|
|
export const H5_HOST = process.env.H5_LOCAL_HOST ?? 'h5.localhost';
|
|
export const ADMIN_HOST = process.env.ADMIN_LOCAL_HOST ?? 'adm.localhost';
|
|
export const PLAZA_HOST = process.env.PLAZA_LOCAL_HOST ?? 'pla.localhost';
|
|
export const OPS_HOST = process.env.OPS_LOCAL_HOST ?? 'ops.localhost';
|
|
|
|
export const TEST_HOSTS = [H5_HOST, ADMIN_HOST, PLAZA_HOST, OPS_HOST];
|
|
|
|
export const USES_LOCALHOST = TEST_HOSTS.every((host) => host === 'localhost' || host.endsWith('.localhost'));
|
|
|
|
export const PUBLIC_SCHEME = (
|
|
process.env.LOCAL_TEST_SCHEME ??
|
|
(String(process.env.LOCAL_TEST_HTTPS ?? '1') === '0' ? 'http' : 'https')
|
|
).replace(/:$/, '');
|
|
|
|
export const PUBLIC_PORT = Number(
|
|
process.env.LOCAL_TEST_PUBLIC_PORT ?? (USES_LOCALHOST ? 8443 : PUBLIC_SCHEME === 'https' ? 443 : 80),
|
|
);
|
|
|
|
export function publicUrl(host, { path = '' } = {}) {
|
|
const defaultPort = PUBLIC_SCHEME === 'https' ? 443 : 80;
|
|
const portSuffix = PUBLIC_PORT === defaultPort ? '' : `:${PUBLIC_PORT}`;
|
|
const normalizedPath = path.startsWith('/') ? path : path ? `/${path}` : '';
|
|
return `${PUBLIC_SCHEME}://${host}${portSuffix}${normalizedPath}`;
|
|
}
|
|
|
|
export const H5_PUBLIC_BASE = (process.env.H5_PUBLIC_BASE_URL ?? publicUrl(H5_HOST)).replace(/\/$/, '');
|
|
export const ADMIN_PUBLIC_BASE = publicUrl(ADMIN_HOST).replace(/\/$/, '');
|
|
export const PLAZA_PUBLIC_BASE = (process.env.PLAZA_PUBLIC_BASE ?? publicUrl(PLAZA_HOST)).replace(/\/$/, '');
|
|
export const OPS_PUBLIC_BASE = publicUrl(OPS_HOST, { path: '/ops/' }).replace(/\/$/, '') + '/';
|
|
|
|
export function isLocalDevHostname(hostname) {
|
|
return (
|
|
hostname === 'localhost' ||
|
|
hostname === '127.0.0.1' ||
|
|
hostname === '::1' ||
|
|
hostname.endsWith('.localhost')
|
|
);
|
|
}
|
|
|
|
export function hostConfigured(host) {
|
|
if (isLocalDevHostname(host)) return true;
|
|
try {
|
|
const hosts = fs.readFileSync('/etc/hosts', 'utf8');
|
|
return new RegExp(`^\\s*${LOCAL_IP.replace('.', '\\.')}\\s+${host.replace('.', '\\.')}(\\s|$)`, 'm').test(
|
|
hosts,
|
|
);
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function resolverConfigured(host) {
|
|
if (isLocalDevHostname(host)) return true;
|
|
try {
|
|
const body = fs.readFileSync(`/etc/resolver/${host}`, 'utf8');
|
|
return body.includes(DNS_MARKER);
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function allHostsConfigured() {
|
|
return TEST_HOSTS.every((host) => hostConfigured(host) && resolverConfigured(host));
|
|
}
|