mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-19 12:34:22 +08:00
feat:android build
This commit is contained in:
+68
-68
@@ -1,127 +1,127 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { execSync, spawn } = require('node:child_process');
|
||||
const net = require('node:net');
|
||||
const readline = require('node:readline');
|
||||
const { execSync, spawn } = require("node:child_process")
|
||||
const net = require("node:net")
|
||||
const readline = require("node:readline")
|
||||
|
||||
function getAvailableDevices() {
|
||||
const raw = execSync('xcrun simctl list devices available -j', {
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
});
|
||||
const parsed = JSON.parse(raw);
|
||||
const devicesByRuntime = parsed.devices || {};
|
||||
const all = [];
|
||||
const raw = execSync("xcrun simctl list devices available -j", {
|
||||
encoding: "utf8",
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
})
|
||||
const parsed = JSON.parse(raw)
|
||||
const devicesByRuntime = parsed.devices || {}
|
||||
const all = []
|
||||
|
||||
for (const [runtime, devices] of Object.entries(devicesByRuntime)) {
|
||||
for (const device of devices) {
|
||||
if (!device.isAvailable) continue;
|
||||
if (device.name.includes('iPad') || device.name.includes('iPhone')) {
|
||||
if (!device.isAvailable) continue
|
||||
if (device.name.includes("iPad") || device.name.includes("iPhone")) {
|
||||
all.push({
|
||||
name: device.name,
|
||||
udid: device.udid,
|
||||
state: device.state,
|
||||
runtime,
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
all.sort((a, b) => a.name.localeCompare(b.name) || a.runtime.localeCompare(b.runtime));
|
||||
return all;
|
||||
all.sort((a, b) => a.name.localeCompare(b.name) || a.runtime.localeCompare(b.runtime))
|
||||
return all
|
||||
}
|
||||
|
||||
function promptChoice(max) {
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
})
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
rl.question('请输入要使用的机型编号: ', (answer) => {
|
||||
rl.close();
|
||||
const idx = Number(answer.trim());
|
||||
rl.question("请输入要使用的机型编号: ", (answer) => {
|
||||
rl.close()
|
||||
const idx = Number(answer.trim())
|
||||
if (!Number.isInteger(idx) || idx < 1 || idx > max) {
|
||||
reject(new Error(`无效编号: ${answer}`));
|
||||
return;
|
||||
reject(new Error(`无效编号: ${answer}`))
|
||||
return
|
||||
}
|
||||
resolve(idx - 1);
|
||||
});
|
||||
});
|
||||
resolve(idx - 1)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function isPortListening(port, host = '127.0.0.1') {
|
||||
function isPortListening(port, host = "127.0.0.1") {
|
||||
return new Promise((resolve) => {
|
||||
const socket = new net.Socket();
|
||||
let settled = false;
|
||||
const socket = new net.Socket()
|
||||
let settled = false
|
||||
|
||||
const finalize = (result) => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
socket.destroy();
|
||||
resolve(result);
|
||||
};
|
||||
if (settled) return
|
||||
settled = true
|
||||
socket.destroy()
|
||||
resolve(result)
|
||||
}
|
||||
|
||||
socket.setTimeout(500);
|
||||
socket.once('connect', () => finalize(true));
|
||||
socket.once('timeout', () => finalize(false));
|
||||
socket.once('error', () => finalize(false));
|
||||
socket.connect(port, host);
|
||||
});
|
||||
socket.setTimeout(500)
|
||||
socket.once("connect", () => finalize(true))
|
||||
socket.once("timeout", () => finalize(false))
|
||||
socket.once("error", () => finalize(false))
|
||||
socket.connect(port, host)
|
||||
})
|
||||
}
|
||||
|
||||
async function hasListeningDevServer(port) {
|
||||
const checks = await Promise.all([
|
||||
isPortListening(port, '127.0.0.1'),
|
||||
isPortListening(port, '::1'),
|
||||
isPortListening(port, 'localhost'),
|
||||
]);
|
||||
return checks.some(Boolean);
|
||||
isPortListening(port, "127.0.0.1"),
|
||||
isPortListening(port, "::1"),
|
||||
isPortListening(port, "localhost"),
|
||||
])
|
||||
return checks.some(Boolean)
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const devices = getAvailableDevices();
|
||||
const devices = getAvailableDevices()
|
||||
|
||||
if (devices.length === 0) {
|
||||
throw new Error('未找到可用 iOS 模拟器,请先在 Xcode 安装模拟器运行时。');
|
||||
throw new Error("未找到可用 iOS 模拟器,请先在 Xcode 安装模拟器运行时。")
|
||||
}
|
||||
|
||||
console.log('可用 iOS 模拟器:');
|
||||
console.log("可用 iOS 模拟器:")
|
||||
devices.forEach((d, i) => {
|
||||
const runtime = d.runtime.replace('com.apple.CoreSimulator.SimRuntime.', '');
|
||||
console.log(`${i + 1}. ${d.name} | ${runtime} | ${d.state} | ${d.udid}`);
|
||||
});
|
||||
const runtime = d.runtime.replace("com.apple.CoreSimulator.SimRuntime.", "")
|
||||
console.log(`${i + 1}. ${d.name} | ${runtime} | ${d.state} | ${d.udid}`)
|
||||
})
|
||||
|
||||
const pickedIndex = await promptChoice(devices.length);
|
||||
const picked = devices[pickedIndex];
|
||||
console.log(`\n已选择: ${picked.name} (${picked.runtime})`);
|
||||
const pickedIndex = await promptChoice(devices.length)
|
||||
const picked = devices[pickedIndex]
|
||||
console.log(`\n已选择: ${picked.name} (${picked.runtime})`)
|
||||
|
||||
const args = ['tauri', 'ios', 'dev', picked.name];
|
||||
const tauriDevPort = Number(process.env.TAURI_DEV_PORT || 1420);
|
||||
const hasExistingDevServer = await hasListeningDevServer(tauriDevPort);
|
||||
const args = ["tauri", "ios", "dev", picked.name]
|
||||
const tauriDevPort = Number(process.env.TAURI_DEV_PORT || 1420)
|
||||
const hasExistingDevServer = await hasListeningDevServer(tauriDevPort)
|
||||
if (hasExistingDevServer) {
|
||||
console.log(`检测到 ${tauriDevPort} 端口已有 dev server,复用现有服务并跳过 beforeDevCommand。`);
|
||||
console.log(`检测到 ${tauriDevPort} 端口已有 dev server,复用现有服务并跳过 beforeDevCommand。`)
|
||||
args.push(
|
||||
'--config',
|
||||
"--config",
|
||||
JSON.stringify({
|
||||
build: {
|
||||
beforeDevCommand: `echo using-existing-dev-server-on-${tauriDevPort}`,
|
||||
},
|
||||
})
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
const child = spawn('pnpm', args, {
|
||||
stdio: 'inherit',
|
||||
shell: process.platform === 'win32',
|
||||
});
|
||||
const child = spawn("pnpm", args, {
|
||||
stdio: "inherit",
|
||||
shell: process.platform === "win32",
|
||||
})
|
||||
|
||||
child.on('exit', (code) => {
|
||||
process.exit(code ?? 1);
|
||||
});
|
||||
child.on("exit", (code) => {
|
||||
process.exit(code ?? 1)
|
||||
})
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(`执行失败: ${err.message}`);
|
||||
process.exit(1);
|
||||
});
|
||||
console.error(`执行失败: ${err.message}`)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
+41
-23
@@ -1,21 +1,24 @@
|
||||
const net = require('node:net')
|
||||
const { spawn } = require('node:child_process')
|
||||
const net = require("node:net")
|
||||
const { spawn } = require("node:child_process")
|
||||
const { writeFileSync, unlinkSync, existsSync } = require("node:fs")
|
||||
const { join } = require("node:path")
|
||||
const os = require("node:os")
|
||||
|
||||
const START_PORT = Number.parseInt(process.env.TAURI_DEV_PORT_START || '1420', 10)
|
||||
const START_PORT = Number.parseInt(process.env.TAURI_DEV_PORT_START || "1420", 10)
|
||||
|
||||
function canUsePort(port) {
|
||||
return new Promise((resolve) => {
|
||||
const server = net.createServer()
|
||||
|
||||
server.once('error', () => {
|
||||
server.once("error", () => {
|
||||
resolve(false)
|
||||
})
|
||||
|
||||
server.once('listening', () => {
|
||||
server.once("listening", () => {
|
||||
server.close(() => resolve(true))
|
||||
})
|
||||
|
||||
server.listen(port, '127.0.0.1')
|
||||
server.listen(port, "127.0.0.1")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -38,27 +41,42 @@ async function main() {
|
||||
|
||||
console.log(`[tauri:dev] 使用端口 ${port}`)
|
||||
|
||||
const extraArgs = process.argv.slice(2)
|
||||
const pnpmCmd = process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm'
|
||||
const child = spawn(
|
||||
pnpmCmd,
|
||||
['tauri', 'dev', '-c', JSON.stringify(overrideConfig), ...extraArgs],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
env: process.env,
|
||||
}
|
||||
)
|
||||
const tempDir = os.tmpdir()
|
||||
const tempConfigPath = join(tempDir, `tauri-config-${Date.now()}.json`)
|
||||
|
||||
child.on('exit', (code, signal) => {
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal)
|
||||
return
|
||||
try {
|
||||
writeFileSync(tempConfigPath, JSON.stringify(overrideConfig), "utf-8")
|
||||
|
||||
const extraArgs = process.argv.slice(2)
|
||||
const cmd = "pnpm"
|
||||
const args = ["tauri", "dev", "--config", tempConfigPath, ...extraArgs]
|
||||
|
||||
const child = spawn(cmd, args, {
|
||||
stdio: "inherit",
|
||||
env: process.env,
|
||||
shell: true,
|
||||
windowsHide: false,
|
||||
})
|
||||
|
||||
child.on("exit", (code, signal) => {
|
||||
if (existsSync(tempConfigPath)) {
|
||||
unlinkSync(tempConfigPath)
|
||||
}
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal)
|
||||
return
|
||||
}
|
||||
process.exit(code ?? 1)
|
||||
})
|
||||
} catch (error) {
|
||||
if (existsSync(tempConfigPath)) {
|
||||
unlinkSync(tempConfigPath)
|
||||
}
|
||||
process.exit(code ?? 1)
|
||||
})
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('[tauri:dev] 启动失败:', error)
|
||||
console.error("[tauri:dev] 启动失败:", error)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user