ui布局自适应

This commit is contained in:
tianmo committed 2026-11-09 10:08:29 +08:00
1 parent 98f44890f8
commit 3587129b90
40 files changed
+929 -142

No files matched your search

+2 -2
View File
@@ -29,8 +29,8 @@ async function buildMac() {
run(process.env.CXX || 'clang++', [
'-std=c++17', '-O2', '-Wall', '-Wextra', '-Werror', '-fobjc-arc',
'-arch', 'arm64', '-arch', 'x86_64', '-mmacosx-version-min=11.0',
...commonSources, join(native, 'app_macos.mm'),
'-framework', 'AppKit', '-framework', 'Foundation', '-o', executable,
...commonSources, join(native, 'local_certificate.mm'), join(native, 'app_macos.mm'),
'-framework', 'AppKit', '-framework', 'Foundation', '-framework', 'Security', '-o', executable,
])
await chmod(executable, 0o755)
await writeFile(join(app, 'Contents', 'Info.plist'), `<?xml version="1.0" encoding="UTF-8"?>
+107
View File
@@ -0,0 +1,107 @@
import { spawn } from 'node:child_process'
import { mkdtemp, rm, stat } from 'node:fs/promises'
import { createServer } from 'node:net'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
import https from 'node:https'
import { readFile } from 'node:fs/promises'
const projectDir = resolve(import.meta.dirname, '..')
function freePort() {
return new Promise((resolvePort, reject) => {
const server = createServer()
server.once('error', reject)
server.listen(0, '127.0.0.1', () => {
const { port } = server.address()
server.close((error) => error ? reject(error) : resolvePort(port))
})
})
}
function requestJson(url, options, ca) {
return new Promise((resolveRequest, reject) => {
const request = https.request(url, { ...options, ca }, (response) => {
const chunks = []
response.on('data', (chunk) => chunks.push(chunk))
response.on('end', () => {
try {
resolveRequest({
status: response.statusCode,
headers: response.headers,
body: JSON.parse(Buffer.concat(chunks).toString('utf8')),
})
} catch (error) {
reject(error)
}
})
})
request.once('error', reject)
request.end()
})
}
async function waitForConnector(url, ca) {
const deadline = Date.now() + 10_000
let lastError
while (Date.now() < deadline) {
try {
const response = await requestJson(url, { headers: { Origin: 'https://safari.test' } }, ca)
if (response.status === 200) return response
lastError = new Error(`健康检查返回 ${response.status}`)
} catch (error) {
lastError = error
}
await new Promise((resolveDelay) => setTimeout(resolveDelay, 150))
}
throw lastError || new Error('HTTPS 连接器启动超时')
}
const temp = await mkdtemp(join(tmpdir(), 'spine-connector-tls-test-'))
const [httpPort, httpsPort] = await Promise.all([freePort(), freePort()])
const certificateDir = join(temp, 'tls')
const processHandle = spawn(process.execPath, [join(projectDir, 'connector', 'spine-connector.mjs')], {
cwd: projectDir,
env: {
...process.env,
SPINE_CONNECTOR_PORT: String(httpPort),
SPINE_CONNECTOR_TLS_PORT: String(httpsPort),
SPINE_CONNECTOR_CONFIG: join(temp, 'config.json'),
SPINE_CONNECTOR_TLS_DIR: certificateDir,
},
stdio: ['ignore', 'pipe', 'pipe'],
})
let output = ''
processHandle.stdout.on('data', (chunk) => { output += chunk })
processHandle.stderr.on('data', (chunk) => { output += chunk })
try {
const ca = await readFile(join(certificateDir, 'ca.pem')).catch(() => null)
|| await new Promise((resolveCa, reject) => {
const timer = setInterval(async () => {
try {
const value = await readFile(join(certificateDir, 'ca.pem'))
clearInterval(timer)
resolveCa(value)
} catch {
// The connector creates the certificate asynchronously during startup.
}
}, 100)
setTimeout(() => {
clearInterval(timer)
reject(new Error(`TLS 证书未生成\n${output}`))
}, 10_000)
})
const response = await waitForConnector(`https://127.0.0.1:${httpsPort}/v1/health`, ca)
if (!response.body.secureAvailable) throw new Error('健康检查未报告 HTTPS 可用')
if (response.headers['access-control-allow-origin'] !== 'https://safari.test') throw new Error('HTTPS CORS 来源不正确')
if (!String(response.body.pairUrl).startsWith(`https://127.0.0.1:${httpsPort}/pair`)) throw new Error('授权链接未使用 HTTPS')
for (const name of ['server-key.pem', 'identity.p12']) {
if (((await stat(join(certificateDir, name))).mode & 0o077) !== 0) throw new Error(`${name} 权限过宽`)
}
console.log(`连接器 HTTPS 验证通过:https://127.0.0.1:${httpsPort}`)
} finally {
if (!processHandle.killed) processHandle.kill('SIGTERM')
await new Promise((resolveExit) => processHandle.once('exit', resolveExit)).catch(() => {})
await rm(temp, { recursive: true, force: true })
}