hdw2
Version:
鸿蒙 hdc 调试工具
1,431 lines (1,392 loc) • 73.6 kB
JavaScript
#!/usr/bin/env node
// src/index.ts
import { cyan as cyan4 } from "colorette";
import { Command } from "commander";
// package.json
var version = "2.3.7";
// src/core/logger.ts
import { cyan, dim, green, red, yellow } from "colorette";
import util from "util";
var useColor = process.stdout.isTTY || !!process.env.CI || process.env.JENKINS_URL;
var TAG = "[hdw]";
var logger = class _logger {
static format(level, args) {
return util.format(level, ...args);
}
static debug(...args) {
const msg = _logger.format("D", args);
console.log(TAG, useColor ? dim(msg) : msg);
}
static info(...args) {
const msg = _logger.format("I", args);
console.log(TAG, useColor ? cyan(msg) : msg);
}
static warn(...args) {
const msg = _logger.format("W", args);
console.log(TAG, useColor ? yellow(msg) : msg);
}
static success(...args) {
const msg = _logger.format("S", args);
console.log(TAG, useColor ? green(msg) : msg);
}
static error(...args) {
const msg = _logger.format("E", args);
console.log(TAG, useColor ? red(msg) : msg);
}
static line(line = 1) {
for (let i = 0; i < line; i++) {
console.log("");
}
}
};
// src/core/device-manager.ts
import shell2 from "shelljs";
// src/core/const.ts
import os from "os";
import path from "path";
var HOME = process.env.HOME || os.homedir();
var CONFIG_PATH = path.join(HOME, "./.hdwrc");
var CONFIG_KEY_MAP = {
useGlobalHdc: "\u5168\u5C40hdc\u5B58\u5728\u65F6,\u662F\u5426\u4F7F\u7528\u5168\u5C40hdc",
bundleName: "\u76EE\u6807\u5E94\u7528bundleName",
abilityName: "\u76EE\u6807\u5E94\u7528abilityName",
sandboxRootPath: "\u76EE\u6807\u5E94\u7528\u6C99\u7BB1\u6839\u76EE\u5F55",
defaultDevice: "\u9ED8\u8BA4\u8BBE\u5907ID",
devices: "\u8BBE\u5907\u8BB0\u5F55\u5217\u8868"
};
var EXIT_CODE_ERROR = 1;
var DEFAULT_WEBVIEW_DEBUG_PORT = 9222;
var DEFAULT_FTP_PORT = 9200;
var HDC_SUCCESS_KEYWORD = "successfully";
var HDC_FINISH_KEYWORD = "finish";
var CONFIG_BUNDLE_MAP = {
sirius: { bundle: "com.zybank.siriusdemo", ability: "EntryAbility" },
pmobile: { bundle: "com.zybank.pmobile.hmos", ability: "EntryAbility" },
yuanxin: { bundle: "com.zyb.yuanxin.hmos", ability: "EntryAbility" },
emobile: { bundle: "com.zyebank.emobile.hmos", ability: "EntryAbility" },
ibh: { bundle: "com.zybank.ibh.hmos", ability: "EntryAbility" }
};
var REMOTE_PATH_MAP = {
temp: "/data/local/tmp",
download: "/storage/media/100/local/files/Docs/Download",
share: "/storage/media/100/local/files/Docs/Huawei Share"
};
var OS_MAP = {
win32: "win",
darwin: "mac",
linux: "linux"
};
var ARCH_MAP = {
x64: "x86",
ia32: "x86",
arm64: "arm",
arm: "arm"
};
// src/core/util.ts
import { execSync } from "child_process";
import fs from "fs";
import os2 from "os";
import path2 from "path";
import { fileURLToPath } from "url";
import shell from "shelljs";
var __filename = fileURLToPath(import.meta.url);
var __dirname = path2.dirname(__filename);
function hasGlobalHdc() {
const hasHdcShell = shell.which("hdc");
return hasHdcShell && hasHdcShell.code === 0;
}
function hasHdc() {
if (hasGlobalHdc()) {
return true;
}
const hdc2 = getHdc();
if (!hdc2) {
return false;
}
const hasHdcShell2 = shell.which(hdc2);
return hasHdcShell2 ? hasHdcShell2.code === 0 : false;
}
function getHdc() {
if (process.env.NODE_ENV === "development") {
return "hdc";
}
const useGlobalHdc = getHdwConfig("useGlobalHdc");
const isExitGlobalHdc = hasGlobalHdc();
if (useGlobalHdc && isExitGlobalHdc) {
return "hdc";
}
const platformArch = getPlatformArch();
if (!process.env.HDW_PLATFORM_LOGGED) {
logger.debug("\u5F53\u524D\u5E73\u53F0:", platformArch);
process.env.HDW_PLATFORM_LOGGED = "true";
}
if (platformArch === "win-x86") {
return path2.join(__dirname, "../toolchains/win-x86/hdc");
}
if (platformArch === "mac-x86") {
return path2.join(__dirname, "../toolchains/mac-x86/hdc");
}
if (platformArch === "mac-arm") {
return path2.join(__dirname, "../toolchains/mac-arm/hdc");
}
if (platformArch === "linux-x86") {
return path2.join(__dirname, "../toolchains/linux-x86/hdc");
}
if (isExitGlobalHdc) {
return "hdc";
}
return "";
}
function getHdcWithDevice() {
const hdc2 = getHdc();
if (hdc2) {
const deviceId = deviceManager.getDefaultDevice()?.deviceId;
const tmd = deviceId ? ` -t ${deviceId}` : "";
return `${hdc2}${tmd}`;
}
return hdc2;
}
function getConfigPath() {
return CONFIG_PATH;
}
function isConfigExist() {
const configPath = getConfigPath();
return fs.existsSync(configPath);
}
function formatValue(value) {
if (value === "true" || value === "false") {
return value === "true";
}
if (/^\d+$/.test(value)) {
return Number(value);
}
return value;
}
function getHdwConfig(key) {
if (!isConfigExist()) {
if (key) {
return void 0;
}
return {};
}
const configPath = getConfigPath();
const configStr = fs.readFileSync(configPath, "utf-8");
try {
const hdwConfig = JSON.parse(configStr);
if (key) {
const value = hdwConfig[key];
return value;
}
return hdwConfig;
} catch (error) {
logger.error(`hdw\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF,\u8BF7\u4FEE\u6539\u672A\u6807\u51C6json\u683C\u5F0F,\u8DEF\u5F84\u4E3A: ${configPath}`);
process.exit(EXIT_CODE_ERROR);
}
}
function setHdwConfig(config, force) {
if (!config || typeof config !== "object") {
logger.error(`hdw\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF,\u8BF7\u4FEE\u6539\u672A\u6807\u51C6json\u683C\u5F0F`);
process.exit(EXIT_CODE_ERROR);
}
const newConfig = {};
Object.entries(config).forEach(([key, value]) => {
if (value !== void 0) {
newConfig[key] = formatValue(value);
}
});
let oldConfig = {};
if (!force) {
oldConfig = getHdwConfig();
}
const hdwConfig = {
...oldConfig,
...newConfig
};
const configPath = getConfigPath();
fs.writeFileSync(configPath, JSON.stringify(hdwConfig, null, 2));
}
function writeToClipboard(text) {
try {
const platform = process.platform;
let cmd;
if (platform === "win32") {
cmd = "clip";
execSync(cmd, { input: text });
} else if (platform === "darwin") {
cmd = "pbcopy";
execSync(cmd, { input: text });
} else {
cmd = "xclip -selection clipboard";
execSync(cmd, { input: text });
}
} catch (error) {
logger.warn("\u65E0\u6CD5\u590D\u5236\u5230\u526A\u8D34\u677F\uFF0C\u8BF7\u624B\u52A8\u590D\u5236\u8C03\u8BD5\u5730\u5740");
}
}
function getPlatformArch() {
const platform = os2.platform();
const arch = os2.arch();
const osPart = OS_MAP[platform] || platform;
const archPart = ARCH_MAP[arch] || arch;
return osPart && archPart ? `${osPart}-${archPart}` : "";
}
// src/core/device-manager.ts
import { intro, isCancel, select } from "@clack/prompts";
import { cyan as cyan2 } from "colorette";
var DeviceManager = class {
config = {};
constructor() {
this.config = getHdwConfig();
}
/**
* 检查设备连接
* @returns
*/
checkDevices() {
const devices2 = this.getRawDevices();
if (devices2.length === 0) {
logger.error("\u8BF7\u786E\u8BA4\u8BBE\u5907\u5DF2\u901A\u8FC7USB\u8FDE\u63A5,\u5F00\u542F\u5F00\u53D1\u8005\u6A21\u5F0F\u5E76\u6253\u5F00USB\u8C03\u8BD5\u5F00\u5173");
process.exit(EXIT_CODE_ERROR);
}
return devices2;
}
/**
* 获取原始设备列表
* @returns
*/
getRawDevices() {
const hdc2 = getHdc();
const deviceListCmd = `${hdc2} list targets`;
const deviceListExec = shell2.exec(deviceListCmd, { silent: true });
if (deviceListExec.code !== 0 || deviceListExec.stderr) {
logger.error("\u67E5\u8BE2\u8BBE\u5907\u5217\u8868\u5931\u8D25", deviceListExec.stdout || deviceListExec.stderr);
process.exit(EXIT_CODE_ERROR);
}
const deviceListStdout = deviceListExec.stdout;
if (deviceListStdout.includes("[Empty]")) {
return [];
}
const devices2 = deviceListStdout.split("\n").filter((line) => line.trim());
return devices2;
}
/**
* 获取当前设备列表
* 返回实时连接的设备列表,不更新配置文件
*/
getConnectedDevices(rawDevices) {
const devices2 = rawDevices || this.getRawDevices();
if (!devices2) {
return [];
}
const connectedDevices = [];
for (const device of devices2) {
const parts = device.trim().split(/\s+/);
const isDefault = device.startsWith("*");
const deviceId = isDefault ? parts[1] : parts[0];
const deviceName = parts.slice(isDefault ? 2 : 1).join(" ");
if (!this.config.devices) {
this.config.devices = [];
}
const index = this.config.devices.findIndex((d) => d.deviceId === deviceId);
if (index === -1) {
logger.line();
logger.info(`\u6B63\u5728\u83B7\u53D6\u65B0\u8BBE\u5907 [${deviceId}] \u7684\u540D\u79F0...`);
const modelName = this.getDeviceModel(deviceId);
logger.debug(`\u8BBE\u5907 ${deviceId} \u540D\u79F0: ${modelName}`);
const newDevice = {
deviceId,
name: modelName,
nickname: deviceName,
lastConnected: (/* @__PURE__ */ new Date()).toLocaleString()
};
this.config.devices.push(newDevice);
connectedDevices.push({
...newDevice,
connected: true
});
} else {
const existingDevice = this.config.devices[index];
existingDevice.lastConnected = (/* @__PURE__ */ new Date()).toLocaleString();
if (!existingDevice.name || existingDevice.name === existingDevice.deviceId) {
logger.debug(`\u6B63\u5728\u66F4\u65B0\u73B0\u6709\u8BBE\u5907 ${deviceId} \u7684\u540D\u79F0...`);
const modelName = this.getDeviceModel(deviceId);
logger.debug(`\u8BBE\u5907 ${deviceId} \u65B0\u540D\u79F0: ${modelName}`);
if (modelName && modelName !== existingDevice.deviceId && modelName !== "null" && modelName !== "undefined") {
existingDevice.name = modelName;
logger.debug(`\u5DF2\u66F4\u65B0\u8BBE\u5907 ${deviceId} \u7684\u540D\u79F0\u4E3A: ${modelName}`);
}
}
connectedDevices.push({
...existingDevice,
connected: true
});
}
}
return connectedDevices;
}
/**
* 设置设备列表
* @returns 设备列表
*/
setDevices(devices2, isOverwrite = false) {
if (!this.config.devices) {
this.config.devices = [];
}
if (isOverwrite) {
this.config.devices = devices2;
} else {
for (const device of devices2) {
const index = this.config.devices.findIndex((d) => d.deviceId === device.deviceId);
delete device.connected;
if (index !== -1) {
this.config.devices[index] = {
...this.config.devices[index],
...device,
lastConnected: device.lastConnected || this.config.devices[index].lastConnected
};
} else {
this.config.devices.push(device);
}
}
}
this.saveConfig();
}
/**
* 打印设备列表
* @param connectedDevices
*/
printConnectedDevices(rawDevices) {
const connectedDevices = deviceManager.getConnectedDevices(rawDevices);
logger.line();
logger.info("=== \u5F53\u524D\u5DF2\u8FDE\u63A5\u8BBE\u5907 ===");
if (connectedDevices.length > 0) {
const defaultDevice = deviceManager.getDefaultDevice();
connectedDevices.forEach((device) => {
const displayName = device.nickname || device.name || device.deviceId;
const isDefault = device.deviceId === defaultDevice?.deviceId;
const status = device.connected ? "[\u5728\u7EBF]" : "[\u79BB\u7EBF]";
const mark = isDefault ? "[\u9ED8\u8BA4]" : "";
logger.info(` ${device.deviceId} ${displayName} ${status} ${mark}`);
});
} else {
logger.warn("\u6CA1\u6709\u5DF2\u8FDE\u63A5\u7684\u8BBE\u5907");
}
return connectedDevices;
}
/**
* 获取所有设备记录(包含连接状态)
*/
getAllDevicesWithStatus(formDevices) {
let connectedDevices;
if (formDevices) {
if (typeof formDevices[0] === "string") {
connectedDevices = deviceManager.getConnectedDevices(formDevices);
} else {
connectedDevices = formDevices;
}
} else {
connectedDevices = deviceManager.getConnectedDevices();
}
const connectedDevicesSets = new Set(connectedDevices.map((d) => d.deviceId));
const devices2 = this.config.devices || [];
return devices2.map((device) => ({
...device,
connected: connectedDevicesSets.has(device.deviceId)
}));
}
/**
* 获取默认设备
*/
getDefaultDevice() {
const defaultId = this.config.defaultDevice;
if (!defaultId) return null;
const allDevices = this.getAllDevicesWithStatus();
const device = allDevices.find((d) => d.deviceId === defaultId);
if (device && device.connected) {
return device;
}
const firstConnected = allDevices.find((d) => d.connected);
return firstConnected || null;
}
/**
* 设置默认设备
*/
setDefaultDevice(deviceId) {
const devices2 = this.config.devices || [];
const device = devices2.find((d) => d.deviceId === deviceId);
if (!device) {
logger.error(`\u8BBE\u5907\u4E0D\u5B58\u5728: ${deviceId}`);
return false;
}
this.config.defaultDevice = deviceId;
const displayName = device.nickname || device.name || device.deviceId;
this.saveConfig();
logger.success(`\u5DF2\u8BBE\u7F6E\u9ED8\u8BA4\u8BBE\u5907: ${deviceId}${displayName ? ` (${displayName})` : ""}`);
return true;
}
/**
* 清除默认设备
*/
clearDefaultDevice() {
delete this.config.defaultDevice;
this.saveConfig();
logger.success("\u5DF2\u6E05\u9664\u9ED8\u8BA4\u8BBE\u5907");
return true;
}
/**
* 清除默认设备
*/
clearDevices() {
delete this.config.devices;
this.saveConfig();
logger.success("\u5DF2\u6E05\u9664\u8BBE\u5907\u5217\u8868");
return true;
}
/**
* 清除默认设备和设备列表
*/
clearDefaultDeviceAndDevices() {
delete this.config.defaultDevice;
delete this.config.devices;
this.saveConfig();
logger.success("\u5DF2\u6E05\u9664\u9ED8\u8BA4\u8BBE\u5907\u548C\u8BBE\u5907\u5217\u8868");
return true;
}
/**
* 设置设备备注
*/
setDeviceNickname(deviceId, nickname) {
const devices2 = this.config.devices || [];
const device = devices2.find((d) => d.deviceId === deviceId);
if (!device) {
logger.error(`\u8BBE\u5907\u4E0D\u5B58\u5728: ${deviceId}`);
return false;
}
device.nickname = nickname;
this.saveConfig();
logger.success(`\u5DF2\u8BBE\u7F6E\u8BBE\u5907\u5907\u6CE8: ${deviceId} -> ${nickname}`);
return true;
}
/**
* 获取所有设备记录(包含实时连接状态)
*/
getAllDevices(formDevices) {
return this.getAllDevicesWithStatus(formDevices);
}
/**
* 获取设备显示名称(优先显示备注)
*/
getDeviceDisplayName(device) {
return device.nickname || device.name || device.deviceId;
}
/**
* 移除设备记录
*/
removeDevice(deviceId) {
const devices2 = this.config.devices || [];
if (!devices2 || devices2.length === 0) {
logger.error(`\u8BBE\u5907\u4E0D\u5B58\u5728: ${deviceId}`);
return false;
}
const index = devices2.findIndex((d) => d.deviceId === deviceId);
if (index === -1) {
logger.error(`\u8BBE\u5907\u4E0D\u5B58\u5728: ${deviceId}`);
return false;
}
devices2.splice(index, 1);
if (this.config.defaultDevice === deviceId) {
delete this.config.defaultDevice;
}
this.saveConfig();
logger.success(`\u5DF2\u79FB\u9664\u8BBE\u5907\u8BB0\u5F55: ${deviceId}`);
return true;
}
/**
* 获取设备名称
*/
getDeviceModel(deviceId) {
const hdc2 = getHdc();
const cmd = `${hdc2} -t ${deviceId} shell param get const.product.name`;
logger.debug(`\u6267\u884C\u547D\u4EE4: ${cmd}`);
const exec = shell2.exec(cmd, { silent: true });
logger.debug(
`\u83B7\u53D6\u8BBE\u5907\u540D\u79F0\u7ED3\u679C: code=${exec.code}, stdout="${exec.stdout.trim()}", stderr="${exec.stderr.replace(/\n/g, "")}"`
);
if (exec.code === 0 && exec.stdout && !exec.stdout.includes("[Fail]") && !exec.stdout.includes("[Fail]ExecuteCommand")) {
const name = exec.stdout.trim();
if (name && name !== "" && name !== "null" && name !== "undefined") {
logger.debug(`\u6210\u529F\u83B7\u53D6\u8BBE\u5907\u540D\u79F0: ${name}`);
return name;
}
}
const cmd2 = `${hdc2} -t ${deviceId} shell param const.product.model`;
logger.debug(`\u6267\u884C\u547D\u4EE4\u83B7\u53D6\u8BBE\u5907\u578B\u53F7: ${cmd2}`);
const cmd2Exec = shell2.exec(cmd2, { silent: true });
logger.debug(`\u83B7\u53D6\u8BBE\u5907\u578B\u53F7\u7ED3\u679C: code=${cmd2Exec.code}, stdout="${cmd2Exec.stdout}"`);
if (cmd2Exec.code === 0 && cmd2Exec.stdout && !cmd2Exec.stdout.includes("[Fail]")) {
const model = cmd2Exec.stdout.trim();
if (model && model !== "") {
logger.debug(`\u6210\u529F\u83B7\u53D6\u8BBE\u5907\u578B\u53F7: ${model}`);
return model;
}
}
logger.debug(`\u4F7F\u7528\u8BBE\u5907ID\u4F5C\u4E3A\u5907\u6CE8: ${deviceId}`);
return deviceId;
}
/**
* 保存配置到本地
*/
saveConfig() {
setHdwConfig(this.config, true);
}
/**
* 设备选择交互界面
*/
async createDeviceSelectUI(devices2) {
const defaultDevice = this.config.defaultDevice;
logger.line();
intro(cyan2("\u9ED8\u8BA4\u8BBE\u5907\u9009\u62E9"));
const device = await select({
message: "\u8BF7\u4F7F\u7528\u4E0A\u4E0B\u952E\u9009\u62E9,\u56DE\u8F66\u952E\u786E\u8BA4",
options: devices2.map((d) => ({
value: d,
label: `${d.deviceId} (${d.nickname || d.name}) ${d.deviceId === defaultDevice ? "(\u5F53\u524D\u9ED8\u8BA4\u8BBE\u5907)" : ""}`
}))
});
if (isCancel(device)) {
logger.info("\u5DF2\u53D6\u6D88\u9009\u62E9");
process.exit(EXIT_CODE_ERROR);
}
return device;
}
};
var deviceManager = new DeviceManager();
// src/core/check.ts
function check(options = {}) {
logger.debug("\u68C0\u67E5\u9E3F\u8499\u8BBE\u5907\u8FDE\u63A5\u72B6\u6001...");
const devices2 = deviceManager.checkDevices();
logger.success("\u8BBE\u5907\u8FDE\u63A5\u6B63\u5E38");
const connectedDevices = deviceManager.printConnectedDevices(devices2);
deviceManager.setDevices(connectedDevices);
}
// src/commands/check.ts
function registerCheckCommand(program2) {
program2.command("check").description("\u68C0\u67E5\u5F53\u524D\u73AF\u5883\u662F\u5426\u53EF\u8FDB\u884Cwebview\u8C03\u8BD5").action(async (options) => {
check(options);
});
}
// src/core/clear.ts
import shell4 from "shelljs";
// src/core/list.ts
import shell3 from "shelljs";
function list(options = {}) {
const hdc2 = getHdcWithDevice();
if (!options.isGetValue) {
logger.debug("\u67E5\u8BE2\u7AEF\u53E3\u6620\u5C04\u5217\u8868...");
}
const fportLsCmd = `${hdc2} fport ls`;
logger.debug("\u6267\u884C\u547D\u4EE4:", fportLsCmd);
const fportLsExec = shell3.exec(fportLsCmd, { silent: true });
if (fportLsExec.code !== 0 || /\[Fail\]/.test(fportLsExec.stdout)) {
logger.error("\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04\u67E5\u8BE2\u5931\u8D25");
process.exit(EXIT_CODE_ERROR);
}
const fportLsStdout = fportLsExec.stdout;
const isEmpty = fportLsStdout.includes("[Empty]");
if (isEmpty) {
if (options.isGetValue) {
return "";
}
logger.warn("\u5F53\u524D\u65E0\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04");
process.exit(0);
}
if (!options.isGetValue) {
logger.success(`\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04\u5217\u8868:
${fportLsStdout}`);
}
return fportLsStdout;
}
// src/core/clear.ts
function clear(options = {}) {
const hdc2 = getHdcWithDevice();
logger.debug("\u6E05\u7A7A\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04...");
const fportLsStdout = list({ isGetValue: true });
if (!fportLsStdout) {
logger.success("\u5F53\u524D\u65E0\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04");
process.exit(0);
}
if (!options.isGetValue) {
logger.debug("\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04\u5217\u8868:", fportLsStdout);
}
const fportList = Array.from(new Set(fportLsStdout.split(/\n|\r/).filter((item) => item)));
const localRemoteArr = fportList.map((item) => {
const arr = item.split(/\s+/);
const localRemoteArr2 = arr.slice(1, 3);
if (localRemoteArr2.length === 2) {
return localRemoteArr2;
}
return null;
}).filter((item) => !!item);
for (let i = 0; i < localRemoteArr.length; i++) {
const localRemote = localRemoteArr[i];
const fportCmd = `${hdc2} fport rm ${localRemote[0]} ${localRemote[1]}`;
if (!options.isGetValue) {
logger.debug("\u6267\u884C\u547D\u4EE4:", fportCmd);
}
const pidExec = shell4.exec(fportCmd, { silent: true });
if (pidExec.code !== 0 || !/success/.test(pidExec.stdout)) {
logger.error("\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04\u6E05\u9664\u5931\u8D25", pidExec.stdout);
process.exit(EXIT_CODE_ERROR);
}
}
logger.success("\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04\u6E05\u9664\u6210\u529F");
}
// src/commands/clear.ts
function registerClearCommand(program2) {
program2.command("clear").description("\u6E05\u7A7A\u5F53\u524Dwebview\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04").action(async (options) => {
clear(options);
});
}
// src/core/config/del-handler.ts
function registerDelHandler(manager) {
manager.register("del", {
format: "<key>",
desc: "\u5220\u9664\u914D\u7F6E\u9879",
handler: delHandler
});
}
function delHandler(key) {
if (!key) {
logger.error("\u8BF7\u8F93\u5165\u8981\u5220\u9664\u7684key");
process.exit(EXIT_CODE_ERROR);
}
const configPath = getConfigPath();
logger.debug("\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84:", configPath);
const config = getHdwConfig();
delete config[key];
setHdwConfig(config, true);
logger.success(`\u5220\u9664\u6210\u529F:
${JSON.stringify(config, null, 2)}`);
}
// src/core/config/get-handler.ts
function registerGetHandler(manager) {
manager.register("get", {
format: "<key>",
desc: "\u83B7\u53D6\u914D\u7F6E\u9879",
handler: getHandler
});
}
function getHandler(key) {
if (!key) {
logger.error("\u8BF7\u8F93\u5165\u8981\u83B7\u53D6\u7684key");
process.exit(EXIT_CODE_ERROR);
}
const configPath = getConfigPath();
logger.debug("\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84:", configPath);
const configValue = getHdwConfig(key);
if (typeof configValue === "undefined") {
logger.warn(`${key} \u5BF9\u5E94\u7684\u914D\u7F6E\u9879\u4E0D\u5B58\u5728`);
process.exit(0);
}
logger.success(`${key}\u7684\u503C\u4E3A: ${configValue}`);
}
// src/core/config/list-handler.ts
function registerListHandler(manager) {
manager.register("list", {
format: "",
desc: "\u83B7\u53D6\u5F53\u524D\u914D\u7F6E\u9879\u5217\u8868",
handler: listHandler
});
}
function listHandler() {
const configPath = getConfigPath();
logger.debug("\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84:", configPath);
const config = getHdwConfig();
logger.success(`\u914D\u7F6E\u5217\u8868:
${JSON.stringify(config, null, 2)}`);
}
// src/core/config/set-handler.ts
function registerSetHandler(manager) {
manager.register("set", {
format: "<key> <value>",
desc: "\u8BBE\u7F6E\u914D\u7F6E\u9879",
handler: setHandler
});
}
function setHandler(key, value) {
if (!key) {
logger.error("\u8BF7\u8F93\u5165\u8981\u8BBE\u7F6E\u7684key");
process.exit(EXIT_CODE_ERROR);
}
if (!value) {
logger.error("\u8BF7\u8F93\u5165\u8981\u8BBE\u7F6E\u7684\u503C");
process.exit(EXIT_CODE_ERROR);
}
const configPath = getConfigPath();
logger.debug("\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84:", configPath);
setHdwConfig({
[key]: value
});
const config = getHdwConfig();
logger.success(`\u8BBE\u7F6E\u6210\u529F:
${JSON.stringify(config, null, 2)}`);
}
// src/core/config/index.ts
function registerConfigHandlers(manager) {
registerListHandler(manager);
registerSetHandler(manager);
registerGetHandler(manager);
registerDelHandler(manager);
}
// src/core/keyed-manager.ts
var KeyedManager = class {
defines = /* @__PURE__ */ new Map();
register(key, keyedItem) {
this.defines.set(key, keyedItem);
}
has(key) {
return this.defines.has(key);
}
getKeys() {
return Array.from(this.defines.keys());
}
getHandler(key) {
const item = this.defines.get(key);
if (!item) {
return null;
}
return item.handler;
}
getHelp() {
const title = "\n\u652F\u6301\u7684\u547D\u4EE4\u5217\u8868:";
const defines = Array.from(this.defines.entries());
const helpContents = defines.map(([key, item]) => {
return `${" ".repeat(2)} ${key} ${item.format} ${item.desc}`;
});
return `${title}
${helpContents.join("\n")}`;
}
};
// src/commands/config.ts
function registerConfigCommand(program2) {
const manager = new KeyedManager();
registerConfigHandlers(manager);
program2.command("config").description("hdw\u914D\u7F6E\u8BBE\u7F6E\u3001\u83B7\u53D6\u3001\u5220\u9664\u7B49\u64CD\u4F5C").argument("<action>", `\u8981\u6267\u884C\u7684\u547D\u4EE4(\u652F\u6301: ${manager.getKeys().join(", ")})`, (action) => {
if (!manager.has(action)) {
logger.error(`\u8F93\u5165\u7684\u547D\u4EE4: ${action}\u4E0D\u5B58\u5728`);
process.exit(1);
}
return action;
}).argument("[values...]", "\u8981\u8BBE\u7F6E\u7684\u503C,\u591A\u4E2A\u4F7F\u7528\u7A7A\u683C\u9694\u5F00").addHelpText("after", () => {
const managerHap = manager.getHelp();
const configureHelp = getConfigHelp();
return `${managerHap}
${configureHelp}`;
}).action(async (key, values) => {
manager.getHandler(key)?.(...values);
});
}
function getConfigHelp() {
const configEntries = Object.entries(CONFIG_KEY_MAP);
const helpTitle = "\n\u652F\u6301\u7684\u5B8C\u6574\u914D\u7F6E:\n";
const helpContext = configEntries.map(([key, value]) => {
return `${" ".repeat(2)}${key}: ${value}`;
});
return `${helpTitle}${helpContext.join("\n")}`;
}
// src/core/debug.ts
import shell5 from "shelljs";
function debug(options = {}) {
const hdc2 = getHdcWithDevice();
const fportLsStdout = list({ isGetValue: true });
if (fportLsStdout) {
clear({ isGetValue: true });
}
logger.debug("\u6620\u5C04\u8C03\u8BD5\u7AEF\u53E3...");
logger.debug("\u67E5\u8BE2\u53EF\u8C03\u8BD5\u5E94\u7528PID\u5217\u8868...");
const catCmd = `${hdc2} shell "cat /proc/net/unix | grep devtools"`;
logger.debug("\u6267\u884C\u547D\u4EE4:", catCmd);
const pidListExec = shell5.exec(catCmd, { silent: true });
if (pidListExec.code !== 0 || !pidListExec.stdout) {
logger.error("\u67E5\u8BE2\u53EF\u8C03\u8BD5\u5E94\u7528PID\u5217\u8868\u5931\u8D25");
process.exit(EXIT_CODE_ERROR);
}
const pidListStdout = pidListExec.stdout;
const lines = pidListStdout.split(/\n|\r/).filter((item) => item.includes("webview_devtools_remote_")).map((item) => {
return item.split("webview_devtools_remote_")[1];
});
const pidArr = Array.from(new Set(lines));
if (!pidArr.length) {
logger.error("\u672A\u67E5\u8BE2\u5230\u53EF\u8C03\u8BD5\u5E94\u7528PID\u5217\u8868");
process.exit(EXIT_CODE_ERROR);
}
logger.debug("\u5E94\u7528PID\u5217\u8868:", pidArr.join(" "));
logger.debug("\u8FDB\u884C\u7AEF\u53E3\u6620\u5C04...");
const inputPort = parseInt(options.port || "");
let port = inputPort || DEFAULT_WEBVIEW_DEBUG_PORT;
logger.debug(`\u6620\u5C04\u8D77\u59CB\u7AEF\u53E3\u53F7: ${port}`);
for (let i = 0; i < pidArr.length; i++) {
const pid = pidArr[i];
const fportCmd = `${hdc2} fport tcp:${port} localabstract:webview_devtools_remote_${pid}`;
logger.debug("\u6267\u884C\u547D\u4EE4:", fportCmd);
const pidExec = shell5.exec(fportCmd, { silent: true });
if (pidExec.code !== 0 || /\[Fail\]/.test(pidExec.stdout)) {
logger.error(`\u6620\u5C04\u7AEF\u53E3${port}\u5931\u8D25`);
process.exit(EXIT_CODE_ERROR);
}
port++;
}
logger.debug("\u67E5\u8BE2\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04\u7ED3\u679C...");
const fportLsCmd = `${hdc2} fport ls`;
logger.debug("\u6267\u884C\u547D\u4EE4:", fportLsCmd);
const fportLsExec = shell5.exec(fportLsCmd, { silent: true });
if (fportLsExec.code !== 0 || /\[Fail\]/.test(fportLsExec.stdout)) {
logger.error("\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04\u67E5\u8BE2\u5931\u8D25");
process.exit(EXIT_CODE_ERROR);
}
const fportLs = fportLsExec.stdout;
logger.debug(`\u8C03\u8BD5\u6620\u5C04\u5217\u8868:
${fportLs}`);
logger.success("\u6620\u5C04\u7AEF\u53E3\u6210\u529F");
logger.line();
const edgeUrl = "edge://inspect/#devices";
const chromeUrl = "chrome://inspect/#devices";
const suffix = " ==>\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F";
logger.info("\u8BF7\u6253\u5F00\u6D4F\u89C8\u5668\u8BBF\u95EE\u4EE5\u4E0B\u5730\u5740\u8FDB\u884C\u8C03\u8BD5:");
logger.info("edge: ", edgeUrl, options.chrome ? "" : suffix);
logger.info("chrome: ", chromeUrl, options.chrome ? suffix : "");
const curUrl = options.chrome ? chromeUrl : edgeUrl;
writeToClipboard(curUrl);
}
// src/commands/debug.ts
function registerDebugCommand(program2) {
program2.command("debug").option("-p --port <\u7AEF\u53E3\u53F7>", "\u81EA\u5B9A\u4E49\u8C03\u8BD5\u6620\u5C04\u7AEF\u53E3").option("-c --chrome", "\u4F7F\u7528Chrome\u6D4F\u89C8\u5668\u8C03\u8BD5,\u9ED8\u8BA4\u4F7F\u7528Edge", false).description("\u5F00\u59CBwebview\u8C03\u8BD5").action(async (options) => {
debug(options);
});
}
// src/core/devices.ts
function devices(options = {}) {
logger.debug("\u68C0\u67E5\u9E3F\u8499\u8BBE\u5907\u8FDE\u63A5\u72B6\u6001...");
const devices2 = deviceManager.checkDevices();
const connectedDevices = deviceManager.printConnectedDevices(devices2);
const allDevices = deviceManager.getAllDevices(connectedDevices);
if (connectedDevices.length > 1 && !deviceManager.getDefaultDevice()) {
logger.info('\u63D0\u793A\uFF1A\u4F7F\u7528 "hdw use" \u9009\u62E9\u9ED8\u8BA4\u8BBE\u5907');
}
deviceManager.setDevices(connectedDevices);
if (options.all && allDevices.length > connectedDevices.length) {
logger.line();
logger.debug("=== \u5386\u53F2\u8BBE\u5907 ===");
allDevices.filter((device) => !device.connected).forEach((device) => {
const displayName = device.nickname || device.name || device.deviceId;
const lastConnected = new Date(device.lastConnected).toLocaleString();
logger.debug(` ${device.deviceId} ${displayName} - \u6700\u540E\u8FDE\u63A5: ${lastConnected}`);
logger.line();
});
}
}
// src/commands/devices.ts
function registerDevicesCommand(program2) {
program2.command("devices").option("-a --all", "\u663E\u793A\u6240\u6709\u8BBE\u5907", false).description("\u68C0\u67E5\u5F53\u524D\u73AF\u5883,\u83B7\u53D6\u8BBE\u5907\u5217\u8868").action(async (options) => {
devices(options);
});
}
// src/core/get/api-version-handler.ts
import shell6 from "shelljs";
function registerApiVersionHandler(manager) {
manager.register("apiVersion", {
format: "",
desc: "\u83B7\u53D6\u7CFB\u7EDFapi\u7248\u672C",
handler: apiVersionHandler
});
}
function apiVersionHandler() {
const hdc2 = getHdcWithDevice();
logger.debug("\u83B7\u53D6\u7CFB\u7EDFAPI\u7248\u672C...");
const apiCmd = `${hdc2} shell param get const.ohos.apiversion`;
logger.debug("\u6267\u884C\u547D\u4EE4:", apiCmd);
const apiExec = shell6.exec(apiCmd, { silent: true });
if (apiExec.code !== 0) {
logger.error("\u83B7\u53D6\u7CFB\u7EDFAPI\u7248\u672C\u5931\u8D25", apiExec.stdout);
process.exit(EXIT_CODE_ERROR);
}
const apiVersion = apiExec.replace(/\s*/g, "");
if (!apiVersion || !/^d+$/.test(apiVersion)) {
logger.error("\u83B7\u53D6\u7CFB\u7EDFAPI\u7248\u672C\u5931\u8D25", apiExec.stdout);
process.exit(EXIT_CODE_ERROR);
}
logger.debug("\u83B7\u53D6\u7CFB\u7EDFAPI\u7248\u672C\u6210\u529F");
logger.success(`\u7CFB\u7EDFAPI\u7248\u672C: ${apiVersion}`);
}
// src/core/get/hdc-handler.ts
function registerHdcHandler(manager) {
manager.register("hdc", {
format: "",
desc: "\u83B7\u53D6hdc\u547D\u4EE4\u8DEF\u5F84",
handler: hdcHandler
});
}
function hdcHandler() {
const hdc2 = getHdc();
logger.debug("\u83B7\u53D6hdc\u547D\u4EE4\u8DEF\u5F84...");
logger.debug("\u83B7\u53D6hdc\u547D\u4EE4\u8DEF\u5F84\u6210\u529F");
logger.success(`hdc\u547D\u4EE4\u8DEF\u5F84: ${hdc2}`);
}
// src/core/get/udid-handler.ts
import shell7 from "shelljs";
function registerUdidHandler(manager) {
manager.register("udid", {
format: "",
desc: "\u83B7\u53D6\u8BBE\u5907UDID",
handler: udidHandler
});
}
function udidHandler() {
const hdc2 = getHdcWithDevice();
logger.debug("\u67E5\u8BE2\u8BBE\u5907udid...");
const udidCmd = `${hdc2} shell bm get --udid`;
logger.debug("\u6267\u884C\u547D\u4EE4:", udidCmd);
const udidExec = shell7.exec(udidCmd, { silent: true });
if (udidExec.code !== 0) {
logger.error("\u83B7\u53D6\u8BBE\u5907udid\u5931\u8D25");
process.exit(EXIT_CODE_ERROR);
}
const udid = udidExec.stdout.split(/[\r\n]/).find((item) => /^[a-zA-z0-9]{64,}$/.test(item));
if (!udid) {
logger.error("\u83B7\u53D6\u8BBE\u5907udid\u5931\u8D25");
process.exit(EXIT_CODE_ERROR);
}
logger.debug("\u67E5\u8BE2\u8BBE\u5907udid\u6210\u529F");
logger.success(`UDID: ${udid}`);
}
// src/core/get/index.ts
function registerGetHandlers(manager) {
registerHdcHandler(manager);
registerUdidHandler(manager);
registerApiVersionHandler(manager);
}
// src/commands/get.ts
function registerGetCommand(program2) {
const manager = new KeyedManager();
registerGetHandlers(manager);
program2.command("get").description("\u83B7\u53D6Hdc\u7684\u5E38\u7528\u6570\u636E").argument("<name>", `\u8981\u83B7\u53D6\u7684\u6570\u636E\u540D\u79F0(\u652F\u6301: ${manager.getKeys().join(", ")})`, (key) => {
if (!manager.has(key)) {
logger.error(`\u8F93\u5165\u7684\u6570\u636E\u540D\u79F0: ${key}\u4E0D\u5B58\u5728`);
process.exit(1);
}
return key;
}).addHelpText("after", manager.getHelp()).action(async (key) => {
manager.getHandler(key)?.();
});
}
// src/core/hdc.ts
import shell8 from "shelljs";
function hdc(options = {}, extArgs = []) {
const rawHdc = getHdc();
if (options.V) {
extArgs.push("-v");
} else if (options.H) {
extArgs.push("-h");
}
logger.debug("\u6267\u884Chdc\u547D\u4EE4...");
const hdcCmd = `${rawHdc} ${extArgs.join(" ")}`;
logger.debug(`\u6267\u884Chdc\u547D\u4EE4: ${hdcCmd}`);
const hdcCmdExec = shell8.exec(hdcCmd, { silent: true, async: true });
let hdcStdout = "";
hdcCmdExec.stdout?.once("data", () => {
logger.debug("HDC\u547D\u4EE4\u8F93\u51FA:");
});
hdcCmdExec.stdout?.on("data", (data) => {
hdcStdout += data;
logger.debug(data);
});
hdcCmdExec.stderr?.on("data", (data) => {
if (options.H) {
logger.debug(data);
return;
}
logger.error(data);
});
hdcCmdExec.on("error", (err) => {
logger.error("HDC\u547D\u4EE4\u6267\u884C\u5931\u8D25", err);
process.exit(EXIT_CODE_ERROR);
});
hdcCmdExec.on("close", () => {
logger.success("HDC\u547D\u4EE4\u6267\u884C\u5B8C\u6210");
});
}
// src/commands/hdc.ts
function registerHdcCommand(program2) {
program2.command("hdc [extArgs...]").description("\u6267\u884Chdc\u547D\u4EE4").option("-V", "hdc\u7248\u672C\u53F7").option("-H", "hdc\u5E2E\u52A9\u4FE1\u606F").allowUnknownOption(true).action(async (extArgs = [], options) => {
hdc(options, extArgs);
});
}
// src/core/install.ts
import AdmZip from "adm-zip";
import fs2 from "fs";
import path3 from "path";
import shell9 from "shelljs";
function cleanupTempDir(tempDirPath) {
try {
if (fs2.existsSync(tempDirPath)) {
shell9.rm("-rf", tempDirPath);
logger.debug("\u5DF2\u6E05\u7406\u4E34\u65F6\u76EE\u5F55:", tempDirPath);
}
} catch (err) {
logger.warn("\u6E05\u7406\u4E34\u65F6\u76EE\u5F55\u5931\u8D25:", err);
}
}
function install(_options = {}, extArgs = []) {
const hdc2 = getHdcWithDevice();
const installPath = extArgs[0];
if (!installPath) {
logger.error("\u8BF7\u63D0\u4F9B\u8981\u5B89\u88C5\u7684\u6587\u4EF6\u8DEF\u5F84");
process.exit(EXIT_CODE_ERROR);
}
logger.debug("\u5B89\u88C5\u5E94\u7528...");
let installTarget;
let bundleName = "";
let tempDirPath = "";
const lowerInstallPath = installPath.toLowerCase();
if (!lowerInstallPath.endsWith(".hap") && !lowerInstallPath.endsWith(".zip")) {
logger.error("\u5B89\u88C5\u5305\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u4EC5\u652F\u6301.hap\u6216.zip\u6587\u4EF6");
process.exit(EXIT_CODE_ERROR);
}
const isZip = lowerInstallPath.endsWith(".zip");
if (isZip) {
const zipPath = path3.resolve(installPath);
if (!fs2.existsSync(zipPath)) {
logger.error("ZIP\u6587\u4EF6\u4E0D\u5B58\u5728");
process.exit(EXIT_CODE_ERROR);
}
const dirName = path3.dirname(zipPath);
const fileNameWithoutExt = path3.basename(zipPath, ".zip");
const tempDirName = `${fileNameWithoutExt.replace(/\s+/g, "")}_temp`;
tempDirPath = path3.join(dirName, tempDirName);
if (fs2.existsSync(tempDirPath)) {
shell9.rm("-rf", tempDirPath);
logger.debug(`\u5DF2\u5220\u9664\u5DF2\u5B58\u5728\u7684\u4E34\u65F6\u76EE\u5F55: ${tempDirPath}`);
}
logger.debug(`\u6B63\u5728\u89E3\u538BZIP\u6587\u4EF6: ${zipPath}`);
logger.debug(`\u89E3\u538B\u5230\u4E34\u65F6\u76EE\u5F55: ${tempDirPath}`);
try {
if (!fs2.existsSync(tempDirPath)) {
fs2.mkdirSync(tempDirPath, { recursive: true });
}
const zip = new AdmZip(zipPath);
const fileList = zip.getEntries();
const fmtList = fileList.map((file, index) => `${index + 1}. ${file.entryName}`);
logger.debug(`\u6587\u4EF6\u5217\u8868(\u5171${fmtList.length}\u4E2A):
${fmtList.join("\n")}`);
const isApp = fileList.some((file) => file.entryName.endsWith(".app"));
if (isApp) {
logger.error("app\u6587\u4EF6\u4E0D\u652F\u6301\u5B89\u88C5");
cleanupTempDir(tempDirPath);
process.exit(EXIT_CODE_ERROR);
}
const hapFile = fileList.find((file) => file.entryName.endsWith(".hap"));
if (!hapFile) {
logger.error("\u672A\u627E\u5230hap\u6587\u4EF6");
cleanupTempDir(tempDirPath);
process.exit(EXIT_CODE_ERROR);
}
zip.extractAllTo(tempDirPath, true);
logger.debug("\u89E3\u538B\u5B8C\u6210");
logger.debug(`\u627E\u5230hap\u6587\u4EF6: ${hapFile.entryName}`);
bundleName = getBundleName(path3.join(tempDirPath, hapFile.entryName));
} catch (err) {
logger.error("\u89E3\u538B\u5931\u8D25", err);
cleanupTempDir(tempDirPath);
process.exit(EXIT_CODE_ERROR);
}
installTarget = tempDirPath;
} else {
const hapPath = path3.resolve(installPath);
if (!fs2.existsSync(hapPath)) {
logger.error(`HAP\u6587\u4EF6\u4E0D\u5B58\u5728: ${hapPath}`);
process.exit(EXIT_CODE_ERROR);
}
installTarget = hapPath;
bundleName = getBundleName(hapPath);
}
if (bundleName) {
uninstall(bundleName);
}
const hdcCmd = `${hdc2} install ${installTarget}`;
logger.debug("\u6267\u884C\u547D\u4EE4:", hdcCmd);
const hdcCmdExec = shell9.exec(hdcCmd, { silent: true, async: true });
let hdcStdout = "";
hdcCmdExec.stdout?.once("data", () => {
logger.debug("HDC\u547D\u4EE4\u8F93\u51FA:");
});
hdcCmdExec.stdout?.on("data", (data) => {
hdcStdout += data;
logger.debug(data);
});
hdcCmdExec.stderr?.on("data", (data) => {
logger.error(data);
});
hdcCmdExec.on("error", () => {
logger.error("\u5E94\u7528\u5B89\u88C5\u5931\u8D25");
cleanupTempDir(tempDirPath);
process.exit(EXIT_CODE_ERROR);
});
hdcCmdExec.on("close", () => {
const isSuccess = hdcStdout.includes(HDC_SUCCESS_KEYWORD);
if (isSuccess) {
logger.success("\u5E94\u7528\u5B89\u88C5\u6210\u529F");
cleanupTempDir(tempDirPath);
} else {
logger.error("\u5E94\u7528\u5B89\u88C5\u5931\u8D25,\u8BF7\u5148\u624B\u52A8\u5378\u8F7D\u5E94\u7528\u540E\u91CD\u8BD5");
cleanupTempDir(tempDirPath);
process.exit(EXIT_CODE_ERROR);
}
});
}
function uninstall(bundleName) {
const hdc2 = getHdcWithDevice();
const uninstallCmd = `${hdc2} uninstall ${bundleName}`;
logger.debug("\u6267\u884C\u547D\u4EE4:", uninstallCmd);
const fportLsExec = shell9.exec(uninstallCmd, { silent: true });
if (fportLsExec.code !== 0) {
logger.warn("\u5E94\u7528\u5378\u8F7D\u5931\u8D25", fportLsExec.stdout);
return;
}
if (fportLsExec.stdout.includes("code:9568386")) {
logger.success("\u5E94\u7528\u672A\u5B89\u88C5,\u65E0\u9700\u5378\u8F7D");
return;
}
if (!fportLsExec.stdout.includes(HDC_SUCCESS_KEYWORD)) {
logger.warn("\u5E94\u7528\u5378\u8F7D\u5931\u8D25", fportLsExec.stdout);
return;
}
logger.success(`\u5E94\u7528\u5378\u8F7D\u6210\u529F,bundleName: ${bundleName}`);
}
function getBundleName(hapPath) {
logger.debug("hap\u6587\u4EF6\u8DEF\u5F84:", hapPath);
const hapZip = new AdmZip(hapPath);
const packInfoEntry = hapZip.getEntry("pack.info");
if (!packInfoEntry) {
logger.error("hap\u4E2D\u672A\u627E\u5230pack.info\u6587\u4EF6");
return "";
}
const packInfoContent = hapZip.readAsText(packInfoEntry, "utf8");
const packInfo = JSON.parse(packInfoContent);
const bundleName = packInfo.summary?.app?.bundleName;
logger.debug("bundleName:", bundleName || "");
if (!bundleName) {
logger.warn("\u672A\u627E\u5230bundleName");
return "";
}
return bundleName;
}
// src/commands/install.ts
function registerInstallCommand(program2) {
program2.command("install [extArgs...]").description("\u5E94\u7528\u5B89\u88C5,\u4F20\u53C2\u540Chdc install,\u652F\u6301zip\u3001hap\u683C\u5F0F").action(async (extArgs = [], options) => {
install(options, extArgs);
});
}
// src/commands/list.ts
function registerListCommand(program2) {
program2.command("list").description("\u67E5\u8BE2\u5F53\u524Dwebview\u8C03\u8BD5\u7AEF\u53E3\u6620\u5C04\u5217\u8868").action(async (options) => {
list(options);
});
}
// src/core/ls.ts
import shell10 from "shelljs";
import { bold, cyan as cyan3, dim as dim2, green as green2, yellow as yellow2 } from "colorette";
// src/core/fs-utils.ts
import fs3 from "fs";
import path4 from "path";
function formatFileSize(size) {
if (size === 0) return "0 B";
const units = ["B", "KB", "MB", "GB", "TB"];
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex++;
}
return `${parseFloat(size.toFixed(2))} ${units[unitIndex]}`;
}
function getFileTypeDesc(name, isDir) {
if (isDir) return "\u76EE\u5F55";
const ext = path4.extname(name).toLowerCase();
const typeMap = {
".txt": "\u6587\u672C\u6587\u4EF6",
".log": "\u65E5\u5FD7\u6587\u4EF6",
".hap": "HAP\u5E94\u7528\u5305",
".hsp": "HSP\u5171\u4EAB\u5305",
".zip": "ZIP\u538B\u7F29\u5305",
".rar": "RAR\u538B\u7F29\u5305",
".7z": "7Z\u538B\u7F29\u5305",
".tar": "TAR\u5F52\u6863",
".gz": "GZ\u538B\u7F29\u5305",
".so": "\u52A8\u6001\u5E93",
".apk": "APK\u5B89\u88C5\u5305",
".exe": "\u53EF\u6267\u884C\u6587\u4EF6",
".dll": "DLL\u52A8\u6001\u5E93",
".png": "PNG\u56FE\u7247",
".jpg": "JPG\u56FE\u7247",
".jpeg": "JPEG\u56FE\u7247",
".gif": "GIF\u56FE\u7247",
".svg": "SVG\u56FE\u7247",
".webp": "WebP\u56FE\u7247",
".mp4": "MP4\u89C6\u9891",
".mp3": "MP3\u97F3\u9891",
".wav": "WAV\u97F3\u9891",
".pdf": "PDF\u6587\u6863",
".doc": "Word\u6587\u6863",
".docx": "Word\u6587\u6863",
".xls": "Excel\u8868\u683C",
".xlsx": "Excel\u8868\u683C",
".ppt": "PPT\u6F14\u793A",
".pptx": "PPT\u6F14\u793A",
".html": "HTML\u6587\u4EF6",
".css": "CSS\u6587\u4EF6",
".js": "JS\u6587\u4EF6",
".ts": "TS\u6587\u4EF6",
".json": "JSON\u6587\u4EF6",
".xml": "XML\u6587\u4EF6",
".md": "Markdown\u6587\u4EF6",
".vsix": "VSCode\u6269\u5C55"
};
return typeMap[ext] || "\u6587\u4EF6";
}
function parseLsOutput(output) {
const entries = [];
const lines = output.split("\n").filter((line) => line.trim());
for (const line of lines) {
const trimmed = line.trim();
if (/^total\s+/i.test(trimmed)) continue;
if (!/^[dlcbps-][rwxlsStT-]{9}/.test(trimmed)) continue;
const parts = trimmed.split(/\s+/);
if (parts.length < 8) continue;
const perms = parts[0];
const sizeStr = parts[4];
const rawName = parts.slice(7).join(" ");
const name = rawName.split(" -> ")[0];
if (name === "." || name === "..") continue;
entries.push({
name,
isDir: perms[0] === "d",
size: parseInt(sizeStr, 10) || 0
});
}
return entries;
}
// src/core/ls.ts
import path5 from "path";
function getDisplayWidth(s) {
return [...s].reduce((w, c) => w + (c.charCodeAt(0) > 127 ? 2 : 1), 0);
}
function printFileList(entries) {
const dirs = entries.filter((e) => e.isDir);
const files = entries.filter((e) => !e.isDir);
const sorted = [...dirs, ...files];
logger.success(`\u6587\u4EF6\u5217\u8868 (\u5171 ${sorted.length} \u9879, ${dirs.length} \u4E2A\u76EE\u5F55, ${files.length} \u4E2A\u6587\u4EF6):`);
const maxNameLen = Math.max(...sorted.map((e) => getDisplayWidth(e.name) + (e.isDir ? 1 : 0)));
const maxSizeLen = Math.max(8, ...sorted.filter((e) => !e.isDir).map((e) => formatFileSize(e.size).length));
const headerName = "\u540D\u79F0".padEnd(maxNameLen - 2);
const headerSize = "\u5927\u5C0F".padEnd(maxSizeLen - 2);
const headerType = "\u7C7B\u578B".padEnd(8 - 2);
logger.line();
console.log(` ${headerName} ${headerSize} ${headerType}`);
console.log(` ${"\u2500".repeat(maxNameLen)} ${"\u2500".repeat(maxSizeLen)} ${"\u2500".repeat(8)}`);
for (const entry of sorted) {
const namePart = entry.isDir ? `${entry.name}/` : entry.name;
const padSpaces = Math.max(0, maxNameLen - getDisplayWidth(namePart));
const displayName = entry.isDir ? bold(cyan3(namePart)) + " ".repeat(padSpaces) : namePart + " ".repeat(padSpaces);
const sizeStr = entry.isDir ? "-".padEnd(maxSizeLen) : formatFileSize(entry.size).padEnd(maxSizeLen);
const displaySize = entry.isDir ? dim2(sizeStr) : yellow2(sizeStr);
const typeStr = entry.isDir ? cyan3(getFileTypeDesc(entry.name, entry.isDir)) : green2(getFileTypeDesc(entry.name, entry.isDir));
console.log(` ${displayName} ${displaySize} ${typeStr}`);
}
logger.line();
}
function ls(options = {}, extArgs = []) {
const hdc2 = getHdcWithDevice();
if (!options.remote) {
if (options.download) {
options.remote = REMOTE_PATH_MAP.download;
} else if (options.share) {
options.remote = REMOTE_PATH_MAP.share;
} else {
options.remote = REMOTE_PATH_MAP.temp;
}
}
if (extArgs.length) {
const remoteArg = extArgs[0];
options.remote = path5.posix.resolve(options.remote, remoteArg);
}
logger.debug("\u8FDC\u7AEF\u8DEF\u5F84:", options.remote);
logger.debug("\u83B7\u53D6\u6587\u4EF6\u5217\u8868...");
const lsCmd = `${hdc2} shell ls -l "${options.remote}"`;
logger.debug("\u6267\u884C\u547D\u4EE4:", lsCmd);
const lsExec = shell10.exec(lsCmd, { silent: true });
if (lsExec.code !== 0) {
logger.debug("\u8BE6\u7EC6\u5217\u8868\u6A21\u5F0F\u5931\u8D25, \u56DE\u9000\u5230\u7B80\u5355\u5217\u8868\u6A21\u5F0F");
const simpleCmd = `${hdc2} shell ls "${options.remote}"`;
logger.debug("\u6267\u884C\u547D\u4EE4:", simpleCmd);
const simpleExec = shell10.exec(simpleCmd, { silent: true });
if (simpleExec.code !== 0) {
logger.error("\u83B7\u53D6\u6587\u4EF6\u5217\u8868\u5931\u8D25");
process.exit(EXIT_CODE_ERROR);
}
const stdout = simpleExec.stdout;
if (stdout.includes("No such file or directory")) {
logger.warn(`\u8DEF\u5F84: ${options.remote} \u4E0D\u5B58\u5728`);
process.exit(EXIT_CODE_ERROR);
}
if (!stdout) {
logger.warn(`\u8DEF\u5F84: ${options.remote} \u4E3A\u7A7A`);
process.exit(0);
}
logger.success(`\u6587\u4EF6\u5217\u8868:
${stdout}`);
return;
}
const lsStdout = lsExec.stdout;
if (lsStdout.includes("No such file or directory")) {
logger.warn(`\u8DEF\u5F84: ${options.remote} \u4E0D\u5B58\u5728`);
process.exit(EXIT_CODE_ERROR);
}
const entries = parseLsOutput(lsStdout);
if (entries.length === 0) {
const lines = lsStdout.split("\n").filter((l) => l.trim() && !l.trim().startsWith("total"));
if (lines.length === 0) {
logger.warn(`\u8DEF\u5F84: ${options.remote} \u4E3A\u7A7A`);
process.exit(0);
}
logger.success(`\u6587\u4EF6\u5217\u8868:
${lines.join("\n")}`);
return;
}
printFileList(entries);
}
// src/commands/ls.ts
function registerLsCommand(program2) {
program2.command("ls [extArgs...]").description("\u83B7\u53D6\u624B\u673A\u7AEF\u6307\u5B9A\u76EE\u5F55\u6587\u4EF6\u5217\u8868,\u9ED8\u8BA4\u4E3A/data/local/tmp/").option("-r --remote <\u8DEF\u5F84>", "\u6307\u5B9A\u8BBE\u5907\u7AEF\u6587\u4EF6\u8DEF\u5F84").option("-d --download", "\u6307\u5B9A\u8BBE\u5907\u7AEFdownload\u76EE\u5F55", false).option("-s --share", "\u6307\u5B9A\u8BBE\u5907\u7AEF\u5206\u4EAB\u76EE\u5F55", false).action(async (extArgs = [], options) => {
ls(options, extArgs);
});
}
// src/core/pull.ts
import path6 from "path";
import shell11 from "shelljs";
function pull(options = {}, extArgs = []) {
const hdc2 = getHdcWithDevice();
const remoteFilePathName = extArgs[0];
if (!remoteFilePathName && !options.remote) {
logger.error("\u7F3A\u5C11\u8BBE\u5907\u7AEF\u6587\u4EF6\u8DEF\u5F84\u6216\u6587\u4EF6\u540D");
process.exit(EXIT_CODE_ERROR);
}
logger.debug("\u62C9\u53D6\u6587\u4EF6...");
if (!options.remote) {
if (options.download) {
options.remote = REMOTE_PATH_MAP.download;
} else if (options.share) {
options.remote = REMOTE_PATH_MAP.share;
} else {
options.remote = REMOTE_PATH_MAP.temp;
}
}
if (!options.