Revert "统一 SSH 工作台与主界面视觉,隔离主题适配层"

This reverts commit 68e0ac1588.
This commit is contained in:
gdz66601 committed 2026-09-21 03:40:03 +08:00
1 parent 68e0ac1588
commit cbcccc570e
58 files changed
+117 -5801

No files matched your search

-143
View File
@@ -1,143 +0,0 @@
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const CLOUDFLARE_API = 'https://api.cloudflare.com/client/v4';
const PROJECT_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
function requireValue(value, name) {
const normalized = value?.trim();
if (!normalized) throw new Error(`缺少 ${name}`);
return normalized;
}
function validateName(value, name, pattern) {
if (!pattern.test(value)) throw new Error(`${name} 格式无效:${value}`);
return value;
}
function normalizeDomain(value) {
const domain = value?.trim().toLowerCase();
if (!domain) return '';
const parsed = new URL(`https://${domain}`);
if (parsed.hostname !== domain || parsed.port || parsed.pathname !== '/' || parsed.search || parsed.hash) {
throw new Error(`CUSTOM_DOMAIN 必须是纯域名,不能包含协议、端口或路径:${domain}`);
}
return domain;
}
export function deploymentSettings(env = process.env) {
const workerName = validateName(
env.WORKER_NAME?.trim() || 'edgessh',
'WORKER_NAME',
/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/,
);
const databaseName = validateName(
env.D1_DATABASE_NAME?.trim() || `${workerName}-accounts`,
'D1_DATABASE_NAME',
/^[A-Za-z0-9](?:[A-Za-z0-9_-]{0,62}[A-Za-z0-9])?$/,
);
return {
accountId: requireValue(env.CLOUDFLARE_ACCOUNT_ID, 'CLOUDFLARE_ACCOUNT_ID'),
apiToken: requireValue(env.CLOUDFLARE_API_TOKEN, 'CLOUDFLARE_API_TOKEN'),
workerName,
databaseName,
customDomain: normalizeDomain(env.CUSTOM_DOMAIN),
};
}
async function cloudflareRequest(settings, pathname, init, fetchImpl) {
const response = await fetchImpl(`${CLOUDFLARE_API}/accounts/${settings.accountId}${pathname}`, {
...init,
headers: {
Authorization: `Bearer ${settings.apiToken}`,
'Content-Type': 'application/json',
...init?.headers,
},
});
const payload = await response.json();
if (!response.ok || !payload.success) {
const message = payload.errors?.map((error) => error.message).filter(Boolean).join('; ') || response.statusText;
throw new Error(`Cloudflare API 请求失败(${response.status}):${message}`);
}
return payload.result;
}
async function findDatabase(settings, fetchImpl) {
const query = new URLSearchParams({ name: settings.databaseName, per_page: '100' });
const databases = await cloudflareRequest(settings, `/d1/database?${query}`, undefined, fetchImpl);
return databases.find((database) => database.name === settings.databaseName);
}
export async function ensureDatabase(settings, fetchImpl = fetch) {
const existing = await findDatabase(settings, fetchImpl);
if (existing) return { id: existing.uuid, created: false };
try {
const created = await cloudflareRequest(
settings,
'/d1/database',
{ method: 'POST', body: JSON.stringify({ name: settings.databaseName }) },
fetchImpl,
);
return { id: created.uuid, created: true };
} catch (error) {
// 并行部署可能在查询后率先创建同名数据库,重新查询即可继续复用该资源。
const concurrentlyCreated = await findDatabase(settings, fetchImpl);
if (concurrentlyCreated) return { id: concurrentlyCreated.uuid, created: false };
throw error;
}
}
function replaceOnce(source, pattern, replacement, label) {
if (!pattern.test(source)) throw new Error(`wrangler.toml 缺少 ${label} 配置`);
return source.replace(pattern, replacement);
}
export function renderWranglerConfig(baseConfig, settings, databaseId) {
let config = replaceOnce(baseConfig, /^name = ".*"$/m, `name = ${JSON.stringify(settings.workerName)}`, 'Worker name');
config = replaceOnce(
config,
/^database_name = ".*"$/m,
`database_name = ${JSON.stringify(settings.databaseName)}`,
'D1 database_name',
);
config = replaceOnce(
config,
/^database_id = ".*"$/m,
`database_id = ${JSON.stringify(databaseId)}`,
'D1 database_id',
);
if (settings.customDomain) {
const routes = `routes = [\n { pattern = ${JSON.stringify(settings.customDomain)}, custom_domain = true }\n]`;
config = replaceOnce(config, /^preview_urls = false$/m, `preview_urls = false\n\n${routes}`, 'preview_urls');
}
return config;
}
export async function prepareDeployment(env = process.env, fetchImpl = fetch) {
const settings = deploymentSettings(env);
const baseConfigPath = env.WRANGLER_BASE_CONFIG || path.join(PROJECT_ROOT, 'wrangler.toml');
const deployConfigPath = env.WRANGLER_DEPLOY_CONFIG || path.join(PROJECT_ROOT, 'wrangler.deploy.toml');
const database = await ensureDatabase(settings, fetchImpl);
const baseConfig = await readFile(baseConfigPath, 'utf8');
const deployConfig = renderWranglerConfig(baseConfig, settings, database.id);
await mkdir(path.dirname(deployConfigPath), { recursive: true });
await writeFile(deployConfigPath, deployConfig, 'utf8');
console.log(`${database.created ? '已创建' : '已复用'} D1 数据库:${settings.databaseName}`);
console.log(`Worker:${settings.workerName}`);
console.log(settings.customDomain ? `自定义域名:${settings.customDomain}` : '自定义域名:未配置,仅发布 workers.dev');
return { settings, database, deployConfigPath };
}
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
prepareDeployment().catch((error) => {
console.error(`部署准备失败:${error instanceof Error ? error.message : String(error)}`);
process.exitCode = 1;
});
}
-92
View File
@@ -1,92 +0,0 @@
import { spawnSync } from 'node:child_process';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const CLOUDFLARE_API = 'https://api.cloudflare.com/client/v4';
const PROJECT_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const WRANGLER_BIN = path.join(PROJECT_ROOT, 'node_modules', 'wrangler', 'bin', 'wrangler.js');
function requireValue(value, name) {
const normalized = value?.trim();
if (!normalized) throw new Error(`缺少 ${name}`);
return normalized;
}
export function pagesProjectSettings(env = process.env) {
const projectName = env.DOCS_PROJECT_NAME?.trim() || 'edgessh-docs';
if (!/^[a-z0-9](?:[a-z0-9-]{0,56}[a-z0-9])?$/.test(projectName)) {
throw new Error(`DOCS_PROJECT_NAME 格式无效:${projectName}`);
}
return {
accountId: requireValue(env.CLOUDFLARE_ACCOUNT_ID, 'CLOUDFLARE_ACCOUNT_ID'),
apiToken: requireValue(env.CLOUDFLARE_API_TOKEN, 'CLOUDFLARE_API_TOKEN'),
projectName,
};
}
async function parseCloudflareResponse(response) {
const payload = await response.json();
if (!response.ok || !payload.success) {
const message = payload.errors?.map((error) => error.message).filter(Boolean).join('; ') || response.statusText;
throw new Error(`Cloudflare Pages API 请求失败(${response.status}):${message}`);
}
return payload.result;
}
export async function ensurePagesProject(settings, fetchImpl = fetch) {
const endpoint = `${CLOUDFLARE_API}/accounts/${settings.accountId}/pages/projects/${settings.projectName}`;
const headers = { Authorization: `Bearer ${settings.apiToken}`, 'Content-Type': 'application/json' };
const existing = await fetchImpl(endpoint, { headers });
if (existing.ok) {
return { project: await parseCloudflareResponse(existing), created: false };
}
if (existing.status !== 404) await parseCloudflareResponse(existing);
const created = await fetchImpl(`${CLOUDFLARE_API}/accounts/${settings.accountId}/pages/projects`, {
method: 'POST',
headers,
body: JSON.stringify({ name: settings.projectName, production_branch: 'main' }),
});
return { project: await parseCloudflareResponse(created), created: true };
}
export async function preparePagesProject(env = process.env, fetchImpl = fetch) {
const settings = pagesProjectSettings(env);
const result = await ensurePagesProject(settings, fetchImpl);
console.log(`${result.created ? '已创建' : '已复用'} Cloudflare Pages 项目:${settings.projectName}`);
return { settings, ...result };
}
function deployPages(settings, env = process.env) {
const result = spawnSync(
process.execPath,
[
WRANGLER_BIN,
'pages',
'deploy',
'.vitepress/dist',
'--project-name',
settings.projectName,
'--branch',
'main',
'--commit-dirty=true',
],
{ cwd: path.join(PROJECT_ROOT, 'docs'), env, stdio: 'inherit' },
);
if (result.error) throw result.error;
if (result.status !== 0) throw new Error(`Cloudflare Pages 部署失败,退出码:${result.status}`);
}
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
preparePagesProject()
.then(({ settings }) => {
if (process.argv.includes('--deploy')) deployPages(settings);
})
.catch((error) => {
console.error(`文档站部署准备失败:${error instanceof Error ? error.message : String(error)}`);
process.exitCode = 1;
});
}
-66
View File
@@ -1,66 +0,0 @@
import { spawnSync } from 'node:child_process';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const PROJECT_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const WRANGLER_BIN = path.join(PROJECT_ROOT, 'node_modules', 'wrangler', 'bin', 'wrangler.js');
function requireSecret(value, name) {
const normalized = value?.trim();
if (!normalized) throw new Error(`缺少 ${name}`);
return normalized;
}
function accessTeamDomain(value) {
const domain = requireSecret(value, 'ACCESS_TEAM_DOMAIN').toLowerCase();
if (!/^[a-z0-9-]+\.cloudflareaccess\.com$/.test(domain)) {
throw new Error('ACCESS_TEAM_DOMAIN 必须是 Cloudflare Access Team Domain,且不含协议或路径');
}
return domain;
}
function encryptionKey(value) {
const key = requireSecret(value, 'ENCRYPTION_KEY');
const decoded = Buffer.from(key, 'base64');
if (decoded.length !== 32 || decoded.toString('base64') !== key) {
throw new Error('ENCRYPTION_KEY 必须是 32 字节安全随机数的标准 Base64');
}
return key;
}
export function deploymentSecrets(env = process.env) {
return {
ACCESS_TEAM_DOMAIN: accessTeamDomain(env.ACCESS_TEAM_DOMAIN),
ACCESS_AUD: requireSecret(env.ACCESS_AUD, 'ACCESS_AUD'),
ENCRYPTION_KEY: encryptionKey(env.ENCRYPTION_KEY),
};
}
export function syncWorkerSecrets(env = process.env) {
const secrets = deploymentSecrets(env);
const deployConfigPath = env.WRANGLER_DEPLOY_CONFIG || path.join(PROJECT_ROOT, 'wrangler.deploy.toml');
// Secret 仅经标准输入交给 Wrangler,避免在命令参数、配置文件或日志中留下明文。
const result = spawnSync(
process.execPath,
[WRANGLER_BIN, 'secret', 'bulk', '--config', deployConfigPath],
{
cwd: PROJECT_ROOT,
env,
input: JSON.stringify(secrets),
stdio: ['pipe', 'inherit', 'inherit'],
},
);
if (result.error) throw result.error;
if (result.status !== 0) throw new Error(`Wrangler Secret 同步失败,退出码:${result.status}`);
}
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
try {
syncWorkerSecrets();
} catch (error) {
console.error(`Worker Secret 同步失败:${error instanceof Error ? error.message : String(error)}`);
process.exitCode = 1;
}
}