CI / Build & Test (push) Failing after 28s
Split monolithic dashboard.js (2753 lines) into 18 focused modules
under dashboard/{core,data,ui,pages}/ with refresh.js and events.js
as orchestrators. Extracted ~900-line inline <style> into dashboard.css
and moved dashboard.html to dashboard/dashboard.html.
Split background.js (609 lines) into background/{logs,state,proxy,
native-messaging,tab-lifecycle,message-router}.js with a thin entry
point using importScripts().
Deleted dead files: wrong-domain.js (duplicate of inline script).
Updated manifest.json web_accessible_resources for new paths.
Updated docs/ARCHITECTURE.md to reflect the new file structure.
No functionality changed. No build step introduced.
46 lines
2.0 KiB
JavaScript
46 lines
2.0 KiB
JavaScript
// Depends on: data/tlds.js (REAL_TLDS, REAL_SLD_TLDS)
|
|
|
|
/**
|
|
* Validate a virtual host hostname.
|
|
* Rules:
|
|
* 1. Must have at least 2 dots (3 labels minimum: host.second.tld)
|
|
* 2. Each label: only [a-z0-9-], no leading/trailing hyphen, non-empty
|
|
* 3. The last two labels (base domain, e.g. "hole.sail") must not be a
|
|
* real public TLD or second-level public suffix
|
|
* Returns { ok: true } or { ok: false, error: string }
|
|
*/
|
|
function isValidVhostHostname(hostname) {
|
|
if (!hostname) return { ok: false, error: 'Hostname is required' };
|
|
const labels = hostname.split('.');
|
|
if (labels.length < 3) {
|
|
return { ok: false, error: 'Hostname must have the form host.second.tld (e.g. myapp.hole.sail) — single-dot names are not allowed' };
|
|
}
|
|
for (const label of labels) {
|
|
if (!label) return { ok: false, error: 'Hostname contains empty labels' };
|
|
if (!/^[a-z0-9-]+$/.test(label)) return { ok: false, error: 'Hostname contains invalid characters — only letters, digits and hyphens allowed' };
|
|
if (label.startsWith('-') || label.endsWith('-')) return { ok: false, error: 'Hostname labels must not start or end with a hyphen' };
|
|
}
|
|
const tld = labels[labels.length - 1];
|
|
const baseDomain = labels.slice(-2).join('.');
|
|
if (REAL_TLDS.has(tld) || REAL_SLD_TLDS.has(baseDomain)) {
|
|
return { ok: false, error: 'The TLD ".' + baseDomain + '" is a real registered domain — use a private TLD like .hole.sail or .my.internal' };
|
|
}
|
|
return { ok: true };
|
|
}
|
|
|
|
/** Extract the two-label base domain from a hostname (e.g. "hole.sail" from "myapp.hole.sail") */
|
|
function extractBaseDomain(hostname) {
|
|
const parts = hostname.split('.');
|
|
return parts.slice(-2).join('.');
|
|
}
|
|
|
|
/** Extract unique two-label base domains from a list of virtual host objects */
|
|
function extractActiveTlds(virtualHosts) {
|
|
const seen = new Set();
|
|
seen.add('hole.sail'); // always include baseline
|
|
for (const v of (virtualHosts || [])) {
|
|
if (v.hostname) seen.add(extractBaseDomain(v.hostname));
|
|
}
|
|
return Array.from(seen).map(b => '.' + b);
|
|
}
|