@oniroproject/core 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +360 -232
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +91 -3
- package/dist/index.d.ts +91 -3
- package/dist/index.js +354 -233
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -47,6 +47,7 @@ __export(index_exports, {
|
|
|
47
47
|
VERSION: () => VERSION,
|
|
48
48
|
applyChanges: () => applyChanges,
|
|
49
49
|
attemptHdcConnection: () => attemptHdcConnection,
|
|
50
|
+
buildCmdWrapper: () => buildCmdWrapper,
|
|
50
51
|
buildGestureCommands: () => buildGestureCommands,
|
|
51
52
|
buildGestureUitestCommand: () => buildGestureUitestCommand,
|
|
52
53
|
buildHap: () => buildHap,
|
|
@@ -83,6 +84,8 @@ __export(index_exports, {
|
|
|
83
84
|
ensureOhModules: () => ensureOhModules,
|
|
84
85
|
ensureOk: () => ensureOk,
|
|
85
86
|
ensureRemoteOk: () => ensureRemoteOk,
|
|
87
|
+
escapeCmdArgument: () => escapeCmdArgument,
|
|
88
|
+
escapeCmdCommand: () => escapeCmdCommand,
|
|
86
89
|
extractTarball: () => extractTarball,
|
|
87
90
|
extractZipWithProgress: () => extractZipWithProgress,
|
|
88
91
|
findAppProcessId: () => findAppProcessId,
|
|
@@ -121,12 +124,14 @@ __export(index_exports, {
|
|
|
121
124
|
isRamBackedPath: () => isRamBackedPath,
|
|
122
125
|
isValidBundleName: () => isValidBundleName,
|
|
123
126
|
isValidProjectName: () => isValidProjectName,
|
|
127
|
+
killProcessTree: () => killProcessTree,
|
|
124
128
|
launchApp: () => launchApp,
|
|
125
129
|
listAbilities: () => listAbilities,
|
|
126
130
|
listDevices: () => listDevices,
|
|
127
131
|
listModules: () => listModules,
|
|
128
132
|
listRunningProcesses: () => listRunningProcesses,
|
|
129
133
|
listTemplates: () => listTemplates,
|
|
134
|
+
needsCmdWrapper: () => needsCmdWrapper,
|
|
130
135
|
nonInteractivePrompter: () => nonInteractivePrompter,
|
|
131
136
|
noopLogger: () => noopLogger,
|
|
132
137
|
noopProgress: () => noopProgress,
|
|
@@ -163,11 +168,13 @@ __export(index_exports, {
|
|
|
163
168
|
setHilogLevel: () => setHilogLevel,
|
|
164
169
|
shell: () => shell,
|
|
165
170
|
shellChecked: () => shellChecked,
|
|
171
|
+
spawnCompat: () => spawnCompat,
|
|
166
172
|
startEmulator: () => startEmulator,
|
|
167
173
|
staticConfig: () => staticConfig,
|
|
168
174
|
stopEmulator: () => stopEmulator,
|
|
169
175
|
streamHilog: () => streamHilog,
|
|
170
176
|
takeScreenshot: () => takeScreenshot,
|
|
177
|
+
toLongPath: () => toLongPath,
|
|
171
178
|
toSpaceError: () => toSpaceError,
|
|
172
179
|
uninstallApp: () => uninstallApp,
|
|
173
180
|
validateTemplateLayout: () => validateTemplateLayout,
|
|
@@ -402,6 +409,14 @@ function getCmdToolsPath(config) {
|
|
|
402
409
|
function getEmulatorDir(config) {
|
|
403
410
|
return config.get("emulatorDir", defaultPaths.emulatorDir());
|
|
404
411
|
}
|
|
412
|
+
function toLongPath(p, platform7 = os3.platform()) {
|
|
413
|
+
if (platform7 !== "win32") return p;
|
|
414
|
+
try {
|
|
415
|
+
return fs.realpathSync.native(p);
|
|
416
|
+
} catch {
|
|
417
|
+
return p;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
405
420
|
function pickExisting(candidates) {
|
|
406
421
|
for (const c of candidates) {
|
|
407
422
|
if (fs.existsSync(c)) return c;
|
|
@@ -437,12 +452,11 @@ function getHdcPath(config) {
|
|
|
437
452
|
}
|
|
438
453
|
return path2.join(base, "hdc");
|
|
439
454
|
}
|
|
440
|
-
function getHvigorwPath(config, projectDir) {
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
]);
|
|
455
|
+
function getHvigorwPath(config, projectDir, platform7 = os3.platform()) {
|
|
456
|
+
const posixFirst = ["hvigorw", "hvigorw.bat", "hvigorw.cmd"];
|
|
457
|
+
const windowsFirst = ["hvigorw.bat", "hvigorw.cmd", "hvigorw"];
|
|
458
|
+
const names = platform7 === "win32" ? windowsFirst : posixFirst;
|
|
459
|
+
const local = pickExisting(names.map((n) => path2.join(projectDir, n)));
|
|
446
460
|
if (fs.existsSync(local) && isProjectLocalHvigorwWorking(projectDir)) {
|
|
447
461
|
return local;
|
|
448
462
|
}
|
|
@@ -974,8 +988,82 @@ async function downloadAndInstallSdk(opts) {
|
|
|
974
988
|
// src/cmdTools/install.ts
|
|
975
989
|
var fs10 = __toESM(require("fs"), 1);
|
|
976
990
|
var os6 = __toESM(require("os"), 1);
|
|
991
|
+
var path11 = __toESM(require("path"), 1);
|
|
992
|
+
var import_node_child_process2 = require("child_process");
|
|
993
|
+
|
|
994
|
+
// src/hdc/spawnCompat.ts
|
|
977
995
|
var path10 = __toESM(require("path"), 1);
|
|
978
996
|
var import_node_child_process = require("child_process");
|
|
997
|
+
var WINDOWS_BATCH_RE = /\.(bat|cmd)$/i;
|
|
998
|
+
var CMD_META_RE = /([()[\]%!^"`<>&|;, *?])/g;
|
|
999
|
+
var CMD_SHIM_RE = /node_modules[\\/]\.bin[\\/][^\\/]+\.cmd$/i;
|
|
1000
|
+
var UNSAFE_CMD_CHARS_RE = /["\r\n\0]/;
|
|
1001
|
+
function needsCmdWrapper(command, platform7 = process.platform) {
|
|
1002
|
+
return platform7 === "win32" && WINDOWS_BATCH_RE.test(command);
|
|
1003
|
+
}
|
|
1004
|
+
function escapeCmdArgument(arg, doubleEscapeMetaChars = false) {
|
|
1005
|
+
let out = String(arg);
|
|
1006
|
+
out = out.replace(/(\\*)"/g, '$1$1\\"');
|
|
1007
|
+
out = out.replace(/(\\*)$/, "$1$1");
|
|
1008
|
+
out = `"${out}"`;
|
|
1009
|
+
out = out.replace(CMD_META_RE, "^$1");
|
|
1010
|
+
if (doubleEscapeMetaChars) out = out.replace(CMD_META_RE, "^$1");
|
|
1011
|
+
return out;
|
|
1012
|
+
}
|
|
1013
|
+
function escapeCmdCommand(command) {
|
|
1014
|
+
return command.replace(CMD_META_RE, "^$1");
|
|
1015
|
+
}
|
|
1016
|
+
function buildCmdWrapper(command, args) {
|
|
1017
|
+
assertCmdSafe(command, `command ${command}`);
|
|
1018
|
+
args.forEach((a, i) => assertCmdSafe(a, `argument ${i} (${a})`));
|
|
1019
|
+
const normalized = path10.normalize(command);
|
|
1020
|
+
const double = CMD_SHIM_RE.test(normalized);
|
|
1021
|
+
const line = [escapeCmdCommand(normalized), ...args.map((a) => escapeCmdArgument(a, double))].join(" ");
|
|
1022
|
+
return {
|
|
1023
|
+
command: process.env.ComSpec ?? process.env.COMSPEC ?? "cmd.exe",
|
|
1024
|
+
args: ["/d", "/s", "/c", `"${line}"`]
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
function assertCmdSafe(value, label) {
|
|
1028
|
+
if (UNSAFE_CMD_CHARS_RE.test(value)) {
|
|
1029
|
+
throw new OniroError(
|
|
1030
|
+
`Cannot run a Windows batch wrapper with a quote, newline or NUL in the ${label}: cmd.exe cannot pass it through unambiguously.`
|
|
1031
|
+
);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
function spawnCompat(command, args, options = {}) {
|
|
1035
|
+
if (!needsCmdWrapper(command)) {
|
|
1036
|
+
return (0, import_node_child_process.spawn)(command, [...args], { ...options, shell: false });
|
|
1037
|
+
}
|
|
1038
|
+
const wrapped = buildCmdWrapper(command, args);
|
|
1039
|
+
return (0, import_node_child_process.spawn)(wrapped.command, wrapped.args, {
|
|
1040
|
+
...options,
|
|
1041
|
+
shell: false,
|
|
1042
|
+
// The line is already escaped; stop Node from re-quoting it.
|
|
1043
|
+
windowsVerbatimArguments: true
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
function killProcessTree(child) {
|
|
1047
|
+
if (process.platform === "win32" && typeof child.pid === "number") {
|
|
1048
|
+
try {
|
|
1049
|
+
const killer = (0, import_node_child_process.spawn)("taskkill", ["/pid", String(child.pid), "/T", "/F"], { stdio: "ignore" });
|
|
1050
|
+
killer.on("error", () => {
|
|
1051
|
+
try {
|
|
1052
|
+
child.kill("SIGKILL");
|
|
1053
|
+
} catch {
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
return;
|
|
1057
|
+
} catch {
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
try {
|
|
1061
|
+
child.kill("SIGKILL");
|
|
1062
|
+
} catch {
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
// src/cmdTools/install.ts
|
|
979
1067
|
function getCmdToolsDownloadUrl(config, platform7 = os6.platform()) {
|
|
980
1068
|
if (platform7 === "linux") {
|
|
981
1069
|
return config.get("cmdToolsUrlLinux", defaultPaths.cmdToolsUrlLinux);
|
|
@@ -1002,16 +1090,16 @@ function getCmdToolsDownloadUrl(config, platform7 = os6.platform()) {
|
|
|
1002
1090
|
}
|
|
1003
1091
|
function findCmdToolsSourceDir(extractPath) {
|
|
1004
1092
|
const known = [
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1093
|
+
path11.join(extractPath, "command-line-tools"),
|
|
1094
|
+
path11.join(extractPath, "oh-command-line-tools"),
|
|
1095
|
+
path11.join(extractPath, "commandline-tools")
|
|
1008
1096
|
];
|
|
1009
1097
|
for (const c of known) {
|
|
1010
1098
|
if (fs10.existsSync(c)) return c;
|
|
1011
1099
|
}
|
|
1012
|
-
const entries = fs10.readdirSync(extractPath, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) =>
|
|
1100
|
+
const entries = fs10.readdirSync(extractPath, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path11.join(extractPath, e.name));
|
|
1013
1101
|
for (const dir of entries) {
|
|
1014
|
-
if (fs10.existsSync(
|
|
1102
|
+
if (fs10.existsSync(path11.join(dir, "bin"))) return dir;
|
|
1015
1103
|
}
|
|
1016
1104
|
throw new OniroError("Could not locate command line tools folder in the extracted archive.");
|
|
1017
1105
|
}
|
|
@@ -1023,12 +1111,12 @@ async function installCmdTools(opts) {
|
|
|
1023
1111
|
const { dir: tmpDir, root: tmpRoot } = createInstallTempDir({
|
|
1024
1112
|
config,
|
|
1025
1113
|
override: opts.tmpDir,
|
|
1026
|
-
installRoot:
|
|
1114
|
+
installRoot: path11.dirname(CMD_PATH),
|
|
1027
1115
|
prefix: "oniro-cmdtools-",
|
|
1028
1116
|
logger
|
|
1029
1117
|
});
|
|
1030
|
-
const zipPath = opts.localZipPath ??
|
|
1031
|
-
const extractPath =
|
|
1118
|
+
const zipPath = opts.localZipPath ?? path11.join(tmpDir, "oh-command-line-tools.zip");
|
|
1119
|
+
const extractPath = path11.join(tmpDir, "oh-command-line-tools");
|
|
1032
1120
|
try {
|
|
1033
1121
|
if (!opts.localZipPath) {
|
|
1034
1122
|
const url = getCmdToolsDownloadUrl(config);
|
|
@@ -1040,8 +1128,8 @@ async function installCmdTools(opts) {
|
|
|
1040
1128
|
fs10.mkdirSync(CMD_PATH, { recursive: true });
|
|
1041
1129
|
const srcDir = findCmdToolsSourceDir(extractPath);
|
|
1042
1130
|
for (const entry of fs10.readdirSync(srcDir)) {
|
|
1043
|
-
const src =
|
|
1044
|
-
const dest =
|
|
1131
|
+
const src = path11.join(srcDir, entry);
|
|
1132
|
+
const dest = path11.join(CMD_PATH, entry);
|
|
1045
1133
|
if (fs10.statSync(src).isDirectory()) {
|
|
1046
1134
|
if (fs10.existsSync(dest)) fs10.rmSync(dest, { recursive: true, force: true });
|
|
1047
1135
|
movePath(src, dest);
|
|
@@ -1049,10 +1137,10 @@ async function installCmdTools(opts) {
|
|
|
1049
1137
|
fs10.copyFileSync(src, dest);
|
|
1050
1138
|
}
|
|
1051
1139
|
}
|
|
1052
|
-
const binDir =
|
|
1140
|
+
const binDir = path11.join(CMD_PATH, "bin");
|
|
1053
1141
|
if (fs10.existsSync(binDir) && os6.platform() !== "win32") {
|
|
1054
1142
|
for (const file of fs10.readdirSync(binDir)) {
|
|
1055
|
-
fs10.chmodSync(
|
|
1143
|
+
fs10.chmodSync(path11.join(binDir, file), 493);
|
|
1056
1144
|
}
|
|
1057
1145
|
}
|
|
1058
1146
|
progress?.report({ message: "Finalizing installation...", increment: 5 });
|
|
@@ -1065,14 +1153,14 @@ async function installCmdTools(opts) {
|
|
|
1065
1153
|
}
|
|
1066
1154
|
function getCmdToolsStatus(config) {
|
|
1067
1155
|
const cmdPath = getCmdToolsPath(config);
|
|
1068
|
-
const binDir =
|
|
1156
|
+
const binDir = path11.join(cmdPath, "bin");
|
|
1069
1157
|
const candidates = os6.platform() === "win32" ? ["ohpm.exe", "ohpm.cmd", "ohpm.bat", "ohpm"] : ["ohpm"];
|
|
1070
|
-
const bin = candidates.map((c) =>
|
|
1158
|
+
const bin = candidates.map((c) => path11.join(binDir, c)).find((p) => fs10.existsSync(p));
|
|
1071
1159
|
if (!bin) {
|
|
1072
1160
|
return { installed: false, status: "Not installed" };
|
|
1073
1161
|
}
|
|
1074
1162
|
try {
|
|
1075
|
-
const versionFile =
|
|
1163
|
+
const versionFile = path11.join(cmdPath, "version.txt");
|
|
1076
1164
|
if (fs10.existsSync(versionFile)) {
|
|
1077
1165
|
const content = fs10.readFileSync(versionFile, "utf8");
|
|
1078
1166
|
for (const line of content.split(/\r?\n/)) {
|
|
@@ -1083,7 +1171,14 @@ function getCmdToolsStatus(config) {
|
|
|
1083
1171
|
} catch {
|
|
1084
1172
|
}
|
|
1085
1173
|
try {
|
|
1086
|
-
const
|
|
1174
|
+
const wrapped = needsCmdWrapper(bin);
|
|
1175
|
+
const probe = wrapped ? buildCmdWrapper(bin, ["-v"]) : { command: bin, args: ["-v"] };
|
|
1176
|
+
const res = (0, import_node_child_process2.spawnSync)(probe.command, probe.args, {
|
|
1177
|
+
encoding: "utf8",
|
|
1178
|
+
windowsVerbatimArguments: wrapped
|
|
1179
|
+
});
|
|
1180
|
+
if (res.error || res.status !== 0) throw res.error ?? new Error(`exit ${String(res.status)}`);
|
|
1181
|
+
const version = res.stdout.trim();
|
|
1087
1182
|
return { installed: true, status: `Installed (${version})` };
|
|
1088
1183
|
} catch {
|
|
1089
1184
|
return { installed: true, status: "Installed (version unknown)" };
|
|
@@ -1101,7 +1196,7 @@ function removeCmdTools(config) {
|
|
|
1101
1196
|
|
|
1102
1197
|
// src/sign/encryptKey.ts
|
|
1103
1198
|
var fs11 = __toESM(require("fs"), 1);
|
|
1104
|
-
var
|
|
1199
|
+
var path12 = __toESM(require("path"), 1);
|
|
1105
1200
|
var crypto2 = __toESM(require("crypto"), 1);
|
|
1106
1201
|
var DAEMON_ROOT_KEY_COMPONENT_LENGTH = 16;
|
|
1107
1202
|
var DAEMON_SALT_KEY_LENGTH = 16;
|
|
@@ -1173,7 +1268,7 @@ function getRootKey(fdComponents, salt) {
|
|
|
1173
1268
|
function createAndStoreKey(dir, keyLength) {
|
|
1174
1269
|
const key = crypto2.randomBytes(keyLength);
|
|
1175
1270
|
const hash = crypto2.createHash("sha256").update(key).digest("hex");
|
|
1176
|
-
const filePath =
|
|
1271
|
+
const filePath = path12.join(dir, hash);
|
|
1177
1272
|
fs11.writeFileSync(filePath, key);
|
|
1178
1273
|
fs11.chmodSync(filePath, KEY_FILE_PERMISSIONS);
|
|
1179
1274
|
return key;
|
|
@@ -1182,23 +1277,23 @@ function createAndStoreEnKey(rootKey, ceDir) {
|
|
|
1182
1277
|
const workKey = crypto2.randomBytes(DAEMON_WORK_KEY_LENGTH);
|
|
1183
1278
|
const encrypted = encrypt(rootKey, workKey);
|
|
1184
1279
|
const hash = crypto2.createHash("sha256").update(encrypted).digest("hex");
|
|
1185
|
-
const filePath =
|
|
1280
|
+
const filePath = path12.join(ceDir, hash);
|
|
1186
1281
|
fs11.writeFileSync(filePath, encrypted);
|
|
1187
1282
|
fs11.chmodSync(filePath, KEY_FILE_PERMISSIONS);
|
|
1188
1283
|
}
|
|
1189
1284
|
function createMaterial(materialPath) {
|
|
1190
1285
|
fs11.mkdirSync(materialPath, { recursive: true });
|
|
1191
1286
|
fs11.chmodSync(materialPath, KEY_FILE_DIRECTORY_PERMISSIONS);
|
|
1192
|
-
const fdDir =
|
|
1193
|
-
const acDir =
|
|
1194
|
-
const ceDir =
|
|
1287
|
+
const fdDir = path12.join(materialPath, "fd");
|
|
1288
|
+
const acDir = path12.join(materialPath, "ac");
|
|
1289
|
+
const ceDir = path12.join(materialPath, "ce");
|
|
1195
1290
|
fs11.mkdirSync(fdDir, { recursive: true });
|
|
1196
1291
|
fs11.mkdirSync(acDir, { recursive: true });
|
|
1197
1292
|
fs11.mkdirSync(ceDir, { recursive: true });
|
|
1198
1293
|
const fdSubDirs = ["0", "1", "2"];
|
|
1199
1294
|
const fdComponents = [];
|
|
1200
1295
|
for (const sub of fdSubDirs) {
|
|
1201
|
-
const subDir =
|
|
1296
|
+
const subDir = path12.join(fdDir, sub);
|
|
1202
1297
|
fs11.mkdirSync(subDir, { recursive: true });
|
|
1203
1298
|
const comp = createAndStoreKey(subDir, DAEMON_ROOT_KEY_COMPONENT_LENGTH);
|
|
1204
1299
|
fdComponents.push(comp);
|
|
@@ -1215,17 +1310,17 @@ function readSingleFile(dir) {
|
|
|
1215
1310
|
if (files.length !== 1) {
|
|
1216
1311
|
throw new Error(`Signing material in ${dir} is illegal (expected exactly one file).`);
|
|
1217
1312
|
}
|
|
1218
|
-
return fs11.readFileSync(
|
|
1313
|
+
return fs11.readFileSync(path12.join(dir, files[0]));
|
|
1219
1314
|
}
|
|
1220
1315
|
function getKey(materialPath) {
|
|
1221
1316
|
if (!fs11.existsSync(materialPath) || !fs11.statSync(materialPath).isDirectory()) {
|
|
1222
1317
|
throw new Error("Material directory does not exist.");
|
|
1223
1318
|
}
|
|
1224
|
-
const fdDir =
|
|
1225
|
-
const fdComponents = ["0", "1", "2"].map((sub) => readSingleFile(
|
|
1226
|
-
const salt = readSingleFile(
|
|
1319
|
+
const fdDir = path12.join(materialPath, "fd");
|
|
1320
|
+
const fdComponents = ["0", "1", "2"].map((sub) => readSingleFile(path12.join(fdDir, sub)));
|
|
1321
|
+
const salt = readSingleFile(path12.join(materialPath, "ac"));
|
|
1227
1322
|
const rootKey = getRootKey(fdComponents, salt);
|
|
1228
|
-
const workMaterial = readSingleFile(
|
|
1323
|
+
const workMaterial = readSingleFile(path12.join(materialPath, "ce"));
|
|
1229
1324
|
return decrypt(rootKey, workMaterial);
|
|
1230
1325
|
}
|
|
1231
1326
|
function encryptPwd(password, materialPath) {
|
|
@@ -1241,8 +1336,8 @@ function decryptPwd(encryptedHex, materialPath) {
|
|
|
1241
1336
|
|
|
1242
1337
|
// src/sign/generateSigningConfigs.ts
|
|
1243
1338
|
var fs12 = __toESM(require("fs"), 1);
|
|
1244
|
-
var
|
|
1245
|
-
var
|
|
1339
|
+
var path13 = __toESM(require("path"), 1);
|
|
1340
|
+
var import_node_child_process3 = require("child_process");
|
|
1246
1341
|
var import_json52 = __toESM(require("json5"), 1);
|
|
1247
1342
|
|
|
1248
1343
|
// src/sign/applicationCert.ts
|
|
@@ -1311,13 +1406,13 @@ var SIGNING_KIND_CONFIG = {
|
|
|
1311
1406
|
};
|
|
1312
1407
|
function copyFilesToProject(projectDir, paths, kind, logger, applicationCertPath) {
|
|
1313
1408
|
logger.info("[sign] Copying signing material into project...");
|
|
1314
|
-
const signaturesDir =
|
|
1409
|
+
const signaturesDir = path13.join(projectDir, "signatures");
|
|
1315
1410
|
fs12.mkdirSync(signaturesDir, { recursive: true });
|
|
1316
|
-
fs12.copyFileSync(paths.keystore,
|
|
1317
|
-
fs12.copyFileSync(paths.profileCert,
|
|
1318
|
-
fs12.copyFileSync(paths.unsignedProfileTemplate,
|
|
1411
|
+
fs12.copyFileSync(paths.keystore, path13.join(signaturesDir, "OpenHarmony.p12"));
|
|
1412
|
+
fs12.copyFileSync(paths.profileCert, path13.join(signaturesDir, "OpenHarmonyProfileRelease.pem"));
|
|
1413
|
+
fs12.copyFileSync(paths.unsignedProfileTemplate, path13.join(signaturesDir, "UnsgnedReleasedProfileTemplate.json"));
|
|
1319
1414
|
if (kind === "application-release") {
|
|
1320
|
-
const dest =
|
|
1415
|
+
const dest = path13.join(signaturesDir, "OpenHarmonyApplication.cer");
|
|
1321
1416
|
if (applicationCertPath) {
|
|
1322
1417
|
fs12.copyFileSync(applicationCertPath, dest);
|
|
1323
1418
|
} else {
|
|
@@ -1340,8 +1435,8 @@ function extractLeafCertificate(chainPath) {
|
|
|
1340
1435
|
function modifyProfileTemplate(projectDir, apl, appFeature, logger, options = {}) {
|
|
1341
1436
|
const kind = options.kind ?? pickSigningKind(apl);
|
|
1342
1437
|
logger.info(`[sign] Modifying profile template (apl=${apl}, app-feature=${appFeature}, kind=${kind})...`);
|
|
1343
|
-
const appJsonPath =
|
|
1344
|
-
const profileTemplatePath =
|
|
1438
|
+
const appJsonPath = path13.join(projectDir, "AppScope/app.json5");
|
|
1439
|
+
const profileTemplatePath = path13.join(projectDir, "signatures/UnsgnedReleasedProfileTemplate.json");
|
|
1345
1440
|
if (!fs12.existsSync(appJsonPath)) {
|
|
1346
1441
|
throw new OniroError(`${appJsonPath} does not exist.`);
|
|
1347
1442
|
}
|
|
@@ -1366,7 +1461,7 @@ function modifyProfileTemplate(projectDir, apl, appFeature, logger, options = {}
|
|
|
1366
1461
|
profileTemplate["bundle-info"]["bundle-name"] = appJson.app.bundleName;
|
|
1367
1462
|
profileTemplate["bundle-info"]["apl"] = apl;
|
|
1368
1463
|
profileTemplate["bundle-info"]["app-feature"] = appFeature;
|
|
1369
|
-
const distCertChainPath =
|
|
1464
|
+
const distCertChainPath = path13.join(
|
|
1370
1465
|
projectDir,
|
|
1371
1466
|
"signatures",
|
|
1372
1467
|
SIGNING_KIND_CONFIG[kind].certBasename
|
|
@@ -1380,9 +1475,9 @@ function modifyProfileTemplate(projectDir, apl, appFeature, logger, options = {}
|
|
|
1380
1475
|
}
|
|
1381
1476
|
function generateP7bFile(projectDir, paths, logger, passwords) {
|
|
1382
1477
|
logger.info("[sign] Generating P7b profile via hap-sign-tool...");
|
|
1383
|
-
const signaturesDir =
|
|
1384
|
-
const profileTemplatePath =
|
|
1385
|
-
const outputProfilePath =
|
|
1478
|
+
const signaturesDir = path13.join(projectDir, "signatures");
|
|
1479
|
+
const profileTemplatePath = path13.join(signaturesDir, "UnsgnedReleasedProfileTemplate.json");
|
|
1480
|
+
const outputProfilePath = path13.join(signaturesDir, "app1-profile.p7b");
|
|
1386
1481
|
const args = [
|
|
1387
1482
|
"-jar",
|
|
1388
1483
|
paths.signTool,
|
|
@@ -1407,7 +1502,7 @@ function generateP7bFile(projectDir, paths, logger, passwords) {
|
|
|
1407
1502
|
passwords.store
|
|
1408
1503
|
];
|
|
1409
1504
|
try {
|
|
1410
|
-
(0,
|
|
1505
|
+
(0, import_node_child_process3.execFileSync)("java", args, { stdio: "inherit" });
|
|
1411
1506
|
} catch (e) {
|
|
1412
1507
|
throw new OniroError(
|
|
1413
1508
|
`hap-sign-tool failed. Ensure a JDK (with keytool/java) is on PATH. Underlying error: ${e.message}`,
|
|
@@ -1416,7 +1511,7 @@ function generateP7bFile(projectDir, paths, logger, passwords) {
|
|
|
1416
1511
|
}
|
|
1417
1512
|
}
|
|
1418
1513
|
function detectSigningConfigNames(projectDir) {
|
|
1419
|
-
const buildProfilePath =
|
|
1514
|
+
const buildProfilePath = path13.join(projectDir, "build-profile.json5");
|
|
1420
1515
|
if (!fs12.existsSync(buildProfilePath)) return ["default"];
|
|
1421
1516
|
let parsed;
|
|
1422
1517
|
try {
|
|
@@ -1437,8 +1532,8 @@ function detectSigningConfigNames(projectDir) {
|
|
|
1437
1532
|
}
|
|
1438
1533
|
function updateBuildProfile(projectDir, kind, logger, passwords) {
|
|
1439
1534
|
logger.info("[sign] Writing signing configs into build-profile.json5...");
|
|
1440
|
-
const materialDir =
|
|
1441
|
-
const buildProfilePath =
|
|
1535
|
+
const materialDir = path13.join(projectDir, "signatures", "material");
|
|
1536
|
+
const buildProfilePath = path13.join(projectDir, "build-profile.json5");
|
|
1442
1537
|
const encryptedStorePassword = encryptPwd(passwords.store, materialDir);
|
|
1443
1538
|
const encryptedKeyPassword = encryptPwd(passwords.key, materialDir);
|
|
1444
1539
|
let buildProfile = { app: {} };
|
|
@@ -1469,7 +1564,7 @@ function updateBuildProfile(projectDir, kind, logger, passwords) {
|
|
|
1469
1564
|
}
|
|
1470
1565
|
function prepareMaterialDirectory(projectDir, logger) {
|
|
1471
1566
|
logger.info("[sign] Generating fresh signing material...");
|
|
1472
|
-
const materialDir =
|
|
1567
|
+
const materialDir = path13.join(projectDir, "signatures", "material");
|
|
1473
1568
|
if (fs12.existsSync(materialDir)) {
|
|
1474
1569
|
fs12.rmSync(materialDir, { recursive: true, force: true });
|
|
1475
1570
|
}
|
|
@@ -1494,15 +1589,15 @@ function generateSigningConfigs(options) {
|
|
|
1494
1589
|
"Could not detect project SDK version (compileSdkVersion missing in build-profile.json5)."
|
|
1495
1590
|
);
|
|
1496
1591
|
}
|
|
1497
|
-
const sdkPath =
|
|
1592
|
+
const sdkPath = path13.join(sdkHome, String(sdkVersion));
|
|
1498
1593
|
if (!fs12.existsSync(sdkPath)) {
|
|
1499
1594
|
throw new OniroError(`SDK path does not exist: ${sdkPath}`);
|
|
1500
1595
|
}
|
|
1501
1596
|
const paths = {
|
|
1502
|
-
signTool:
|
|
1503
|
-
keystore:
|
|
1504
|
-
profileCert:
|
|
1505
|
-
unsignedProfileTemplate:
|
|
1597
|
+
signTool: path13.join(sdkPath, "toolchains/lib/hap-sign-tool.jar"),
|
|
1598
|
+
keystore: path13.join(sdkPath, "toolchains/lib/OpenHarmony.p12"),
|
|
1599
|
+
profileCert: path13.join(sdkPath, "toolchains/lib/OpenHarmonyProfileRelease.pem"),
|
|
1600
|
+
unsignedProfileTemplate: path13.join(sdkPath, "toolchains/lib/UnsgnedReleasedProfileTemplate.json")
|
|
1506
1601
|
};
|
|
1507
1602
|
const kind = pickSigningKind(apl);
|
|
1508
1603
|
const passwords = options.passwords ?? DEFAULT_PASSWORDS;
|
|
@@ -1517,7 +1612,7 @@ function generateSigningConfigs(options) {
|
|
|
1517
1612
|
|
|
1518
1613
|
// src/emulator/install.ts
|
|
1519
1614
|
var fs13 = __toESM(require("fs"), 1);
|
|
1520
|
-
var
|
|
1615
|
+
var path14 = __toESM(require("path"), 1);
|
|
1521
1616
|
async function installEmulator(opts) {
|
|
1522
1617
|
const { config, progress, abortSignal } = opts;
|
|
1523
1618
|
const logger = opts.logger ?? noopLogger;
|
|
@@ -1527,18 +1622,18 @@ async function installEmulator(opts) {
|
|
|
1527
1622
|
const { dir: tmpDir, root: tmpRoot } = createInstallTempDir({
|
|
1528
1623
|
config,
|
|
1529
1624
|
override: opts.tmpDir,
|
|
1530
|
-
installRoot:
|
|
1625
|
+
installRoot: path14.dirname(emulatorDir),
|
|
1531
1626
|
prefix: "oniro-emulator-",
|
|
1532
1627
|
logger
|
|
1533
1628
|
});
|
|
1534
|
-
const tmpZip =
|
|
1629
|
+
const tmpZip = path14.join(tmpDir, "oniro_emulator.zip");
|
|
1535
1630
|
try {
|
|
1536
1631
|
fs13.mkdirSync(emulatorDir, { recursive: true });
|
|
1537
1632
|
progress?.report({ message: "Downloading emulator...", increment: 0 });
|
|
1538
1633
|
await downloadFile({ url, dest: tmpZip, progress, abortSignal, start: 0, range: 50, what, tmpRoot });
|
|
1539
1634
|
progress?.report({ message: "Extracting emulator...", increment: 0 });
|
|
1540
1635
|
await extractZipWithProgress({ zipPath: tmpZip, dest: emulatorDir, progress, start: 50, range: 45, logger });
|
|
1541
|
-
const runSh =
|
|
1636
|
+
const runSh = path14.join(emulatorDir, "images", "run.sh");
|
|
1542
1637
|
if (fs13.existsSync(runSh)) {
|
|
1543
1638
|
fs13.chmodSync(runSh, 493);
|
|
1544
1639
|
}
|
|
@@ -1550,8 +1645,8 @@ async function installEmulator(opts) {
|
|
|
1550
1645
|
}
|
|
1551
1646
|
}
|
|
1552
1647
|
function isEmulatorInstalled(config) {
|
|
1553
|
-
const imagesDir =
|
|
1554
|
-
return fs13.existsSync(
|
|
1648
|
+
const imagesDir = path14.join(getEmulatorDir(config), "images");
|
|
1649
|
+
return fs13.existsSync(path14.join(imagesDir, "run.sh")) || fs13.existsSync(path14.join(imagesDir, "run.bat"));
|
|
1555
1650
|
}
|
|
1556
1651
|
function removeEmulator(config) {
|
|
1557
1652
|
const emulatorDir = getEmulatorDir(config);
|
|
@@ -1561,13 +1656,16 @@ function removeEmulator(config) {
|
|
|
1561
1656
|
}
|
|
1562
1657
|
|
|
1563
1658
|
// src/emulator/lifecycle.ts
|
|
1564
|
-
var
|
|
1659
|
+
var fs15 = __toESM(require("fs"), 1);
|
|
1565
1660
|
var os7 = __toESM(require("os"), 1);
|
|
1566
|
-
var
|
|
1661
|
+
var path15 = __toESM(require("path"), 1);
|
|
1567
1662
|
var import_node_child_process4 = require("child_process");
|
|
1568
1663
|
|
|
1569
1664
|
// src/hdc/exec.ts
|
|
1570
|
-
var
|
|
1665
|
+
var fs14 = __toESM(require("fs"), 1);
|
|
1666
|
+
function errorMessage(err) {
|
|
1667
|
+
return err instanceof Error ? err.message : String(err);
|
|
1668
|
+
}
|
|
1571
1669
|
function runProcess(opts) {
|
|
1572
1670
|
const { command, args, cwd, env, onOutput } = opts;
|
|
1573
1671
|
const timeoutMs = opts.timeoutMs ?? 6e4;
|
|
@@ -1577,7 +1675,17 @@ function runProcess(opts) {
|
|
|
1577
1675
|
reject(new CancelledError(`Command aborted before start: ${command}`));
|
|
1578
1676
|
return;
|
|
1579
1677
|
}
|
|
1580
|
-
|
|
1678
|
+
if (needsCmdWrapper(command) && !fs14.existsSync(command)) {
|
|
1679
|
+
reject(new OniroError(`Failed to spawn ${command}: ENOENT (no such file)`));
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
let child;
|
|
1683
|
+
try {
|
|
1684
|
+
child = spawnCompat(command, args, { cwd, env });
|
|
1685
|
+
} catch (err) {
|
|
1686
|
+
reject(new OniroError(`Failed to spawn ${command}: ${errorMessage(err)}`, err));
|
|
1687
|
+
return;
|
|
1688
|
+
}
|
|
1581
1689
|
let stdout = "";
|
|
1582
1690
|
let stderr = "";
|
|
1583
1691
|
let settled = false;
|
|
@@ -1590,26 +1698,20 @@ function runProcess(opts) {
|
|
|
1590
1698
|
if (settled) return;
|
|
1591
1699
|
settled = true;
|
|
1592
1700
|
cleanup();
|
|
1593
|
-
|
|
1594
|
-
child.kill("SIGKILL");
|
|
1595
|
-
} catch {
|
|
1596
|
-
}
|
|
1701
|
+
killProcessTree(child);
|
|
1597
1702
|
reject(new CancelledError(`Command aborted: ${command} ${args.join(" ")}`));
|
|
1598
1703
|
};
|
|
1599
1704
|
const timer = setTimeout(() => {
|
|
1600
1705
|
timedOut = true;
|
|
1601
|
-
|
|
1602
|
-
child.kill("SIGKILL");
|
|
1603
|
-
} catch {
|
|
1604
|
-
}
|
|
1706
|
+
killProcessTree(child);
|
|
1605
1707
|
}, timeoutMs);
|
|
1606
1708
|
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
1607
|
-
child.stdout
|
|
1709
|
+
child.stdout?.on("data", (d) => {
|
|
1608
1710
|
const s = d.toString();
|
|
1609
1711
|
stdout += s;
|
|
1610
1712
|
onOutput?.(s, "stdout");
|
|
1611
1713
|
});
|
|
1612
|
-
child.stderr
|
|
1714
|
+
child.stderr?.on("data", (d) => {
|
|
1613
1715
|
const s = d.toString();
|
|
1614
1716
|
stderr += s;
|
|
1615
1717
|
onOutput?.(s, "stderr");
|
|
@@ -1681,7 +1783,7 @@ function ensureRemoteOk(result, command) {
|
|
|
1681
1783
|
}
|
|
1682
1784
|
|
|
1683
1785
|
// src/emulator/lifecycle.ts
|
|
1684
|
-
var PID_FILE =
|
|
1786
|
+
var PID_FILE = path15.join(os7.tmpdir(), "oniro_emulator.pid");
|
|
1685
1787
|
async function attemptHdcConnection(config, address = "127.0.0.1:55555", logger = noopLogger) {
|
|
1686
1788
|
try {
|
|
1687
1789
|
await hdcExec({ config, args: ["start", "-r"], logger });
|
|
@@ -1694,24 +1796,24 @@ async function attemptHdcConnection(config, address = "127.0.0.1:55555", logger
|
|
|
1694
1796
|
}
|
|
1695
1797
|
}
|
|
1696
1798
|
function resolveLauncher(imagesPath, headless, connect) {
|
|
1697
|
-
const runSh =
|
|
1698
|
-
const runBat =
|
|
1799
|
+
const runSh = path15.join(imagesPath, "run.sh");
|
|
1800
|
+
const runBat = path15.join(imagesPath, "run.bat");
|
|
1699
1801
|
const extra = [];
|
|
1700
1802
|
if (headless) extra.push("--headless");
|
|
1701
1803
|
if (connect) extra.push("--connect", connect);
|
|
1702
1804
|
if (os7.platform() === "win32") {
|
|
1703
|
-
if (
|
|
1805
|
+
if (fs15.existsSync(runBat)) {
|
|
1704
1806
|
return { command: "cmd.exe", args: ["/c", runBat, ...extra], cwd: imagesPath };
|
|
1705
1807
|
}
|
|
1706
|
-
if (
|
|
1808
|
+
if (fs15.existsSync(runSh)) {
|
|
1707
1809
|
return { command: "bash", args: [runSh, ...extra], cwd: imagesPath };
|
|
1708
1810
|
}
|
|
1709
1811
|
throw new OniroError(`No emulator launcher (run.bat or run.sh) found in ${imagesPath}.`);
|
|
1710
1812
|
}
|
|
1711
|
-
if (
|
|
1813
|
+
if (fs15.existsSync(runSh)) {
|
|
1712
1814
|
return { command: "bash", args: [runSh, ...extra], cwd: imagesPath };
|
|
1713
1815
|
}
|
|
1714
|
-
if (
|
|
1816
|
+
if (fs15.existsSync(runBat)) {
|
|
1715
1817
|
return { command: "bash", args: [runBat, ...extra], cwd: imagesPath };
|
|
1716
1818
|
}
|
|
1717
1819
|
throw new OniroError(`No emulator launcher (run.sh or run.bat) found in ${imagesPath}.`);
|
|
@@ -1719,9 +1821,9 @@ function resolveLauncher(imagesPath, headless, connect) {
|
|
|
1719
1821
|
async function startEmulator(opts) {
|
|
1720
1822
|
const { config } = opts;
|
|
1721
1823
|
const logger = opts.logger ?? noopLogger;
|
|
1722
|
-
if (os7.platform() !== "win32" &&
|
|
1824
|
+
if (os7.platform() !== "win32" && fs15.existsSync(PID_FILE)) {
|
|
1723
1825
|
try {
|
|
1724
|
-
const pid = Number(
|
|
1826
|
+
const pid = Number(fs15.readFileSync(PID_FILE, "utf8").trim());
|
|
1725
1827
|
if (Number.isFinite(pid) && pid > 0) {
|
|
1726
1828
|
try {
|
|
1727
1829
|
process.kill(pid, 0);
|
|
@@ -1737,13 +1839,13 @@ async function startEmulator(opts) {
|
|
|
1737
1839
|
logger.warn(`Could not read PID file: ${err.message}`);
|
|
1738
1840
|
}
|
|
1739
1841
|
}
|
|
1740
|
-
const imagesPath =
|
|
1741
|
-
if (!
|
|
1842
|
+
const imagesPath = path15.join(getEmulatorDir(config), "images");
|
|
1843
|
+
if (!fs15.existsSync(imagesPath)) {
|
|
1742
1844
|
throw new OniroError(`Emulator images directory not found at ${imagesPath}. Run \`oniro-app emulator install\` first.`);
|
|
1743
1845
|
}
|
|
1744
1846
|
const launcher = resolveLauncher(imagesPath, opts.headless === true, opts.connect);
|
|
1745
1847
|
const logPath = opts.logFile ?? (os7.platform() === "win32" ? "NUL" : "/dev/null");
|
|
1746
|
-
const logFd =
|
|
1848
|
+
const logFd = fs15.openSync(logPath, "a");
|
|
1747
1849
|
let child;
|
|
1748
1850
|
try {
|
|
1749
1851
|
child = (0, import_node_child_process4.spawn)(launcher.command, [...launcher.args], {
|
|
@@ -1753,12 +1855,12 @@ async function startEmulator(opts) {
|
|
|
1753
1855
|
windowsHide: true
|
|
1754
1856
|
});
|
|
1755
1857
|
} finally {
|
|
1756
|
-
|
|
1858
|
+
fs15.closeSync(logFd);
|
|
1757
1859
|
}
|
|
1758
1860
|
if (!child.pid) {
|
|
1759
1861
|
throw new OniroError(`Failed to spawn launcher (${launcher.command} ${launcher.args.join(" ")}).`);
|
|
1760
1862
|
}
|
|
1761
|
-
|
|
1863
|
+
fs15.writeFileSync(PID_FILE, String(child.pid));
|
|
1762
1864
|
child.unref();
|
|
1763
1865
|
logger.info(`Emulator launched (PID ${child.pid}). Logs: ${logPath}`);
|
|
1764
1866
|
const earlyExit = new Promise((resolve4) => {
|
|
@@ -1805,24 +1907,24 @@ ${tail}` : ""}`);
|
|
|
1805
1907
|
}
|
|
1806
1908
|
function readTail(filePath, bytes) {
|
|
1807
1909
|
try {
|
|
1808
|
-
const stat =
|
|
1910
|
+
const stat = fs15.statSync(filePath);
|
|
1809
1911
|
const start = Math.max(0, stat.size - bytes);
|
|
1810
|
-
const fd =
|
|
1912
|
+
const fd = fs15.openSync(filePath, "r");
|
|
1811
1913
|
try {
|
|
1812
1914
|
const buf = Buffer.alloc(stat.size - start);
|
|
1813
|
-
|
|
1915
|
+
fs15.readSync(fd, buf, 0, buf.length, start);
|
|
1814
1916
|
return buf.toString("utf8");
|
|
1815
1917
|
} finally {
|
|
1816
|
-
|
|
1918
|
+
fs15.closeSync(fd);
|
|
1817
1919
|
}
|
|
1818
1920
|
} catch {
|
|
1819
1921
|
return "";
|
|
1820
1922
|
}
|
|
1821
1923
|
}
|
|
1822
1924
|
async function stopEmulator(logger = noopLogger) {
|
|
1823
|
-
if (
|
|
1925
|
+
if (fs15.existsSync(PID_FILE)) {
|
|
1824
1926
|
try {
|
|
1825
|
-
const pid = Number(
|
|
1927
|
+
const pid = Number(fs15.readFileSync(PID_FILE, "utf8").trim());
|
|
1826
1928
|
if (Number.isFinite(pid) && pid > 0) {
|
|
1827
1929
|
try {
|
|
1828
1930
|
process.kill(pid, "SIGTERM");
|
|
@@ -1841,7 +1943,7 @@ async function stopEmulator(logger = noopLogger) {
|
|
|
1841
1943
|
} catch (err) {
|
|
1842
1944
|
logger.warn(`[emulator] could not run ${killCmd}: ${err.message}`);
|
|
1843
1945
|
}
|
|
1844
|
-
|
|
1946
|
+
fs15.rm(PID_FILE, { force: true }, (err) => {
|
|
1845
1947
|
if (err) logger.warn(`Could not remove PID file: ${err.message}`);
|
|
1846
1948
|
});
|
|
1847
1949
|
}
|
|
@@ -2008,21 +2110,20 @@ async function waitForCondition(opts) {
|
|
|
2008
2110
|
}
|
|
2009
2111
|
|
|
2010
2112
|
// src/hdc/app.ts
|
|
2011
|
-
var
|
|
2012
|
-
var
|
|
2013
|
-
var import_node_child_process5 = require("child_process");
|
|
2113
|
+
var fs17 = __toESM(require("fs"), 1);
|
|
2114
|
+
var path17 = __toESM(require("path"), 1);
|
|
2014
2115
|
|
|
2015
2116
|
// src/hdc/project.ts
|
|
2016
|
-
var
|
|
2017
|
-
var
|
|
2117
|
+
var fs16 = __toESM(require("fs"), 1);
|
|
2118
|
+
var path16 = __toESM(require("path"), 1);
|
|
2018
2119
|
var import_json53 = __toESM(require("json5"), 1);
|
|
2019
2120
|
function readJson5(filePath) {
|
|
2020
|
-
const content =
|
|
2121
|
+
const content = fs16.readFileSync(filePath, "utf-8");
|
|
2021
2122
|
return import_json53.default.parse(content);
|
|
2022
2123
|
}
|
|
2023
2124
|
function getBundleName(projectDir) {
|
|
2024
|
-
const appJsonPath =
|
|
2025
|
-
if (!
|
|
2125
|
+
const appJsonPath = path16.join(projectDir, "AppScope", "app.json5");
|
|
2126
|
+
if (!fs16.existsSync(appJsonPath)) {
|
|
2026
2127
|
throw new OniroError(`Could not find app.json5 at ${appJsonPath}`);
|
|
2027
2128
|
}
|
|
2028
2129
|
const appJson = readJson5(appJsonPath);
|
|
@@ -2032,8 +2133,8 @@ function getBundleName(projectDir) {
|
|
|
2032
2133
|
return appJson.app.bundleName;
|
|
2033
2134
|
}
|
|
2034
2135
|
function getMainAbility(projectDir, moduleName = "entry", abilityName) {
|
|
2035
|
-
const moduleJsonPath =
|
|
2036
|
-
if (!
|
|
2136
|
+
const moduleJsonPath = path16.join(projectDir, moduleName, "src", "main", "module.json5");
|
|
2137
|
+
if (!fs16.existsSync(moduleJsonPath)) {
|
|
2037
2138
|
throw new OniroError(`Could not find module.json5 at ${moduleJsonPath}`);
|
|
2038
2139
|
}
|
|
2039
2140
|
const moduleJson = readJson5(moduleJsonPath);
|
|
@@ -2056,8 +2157,8 @@ function getMainAbility(projectDir, moduleName = "entry", abilityName) {
|
|
|
2056
2157
|
async function installApp(opts) {
|
|
2057
2158
|
const logger = scopedLogger(opts.logger ?? noopLogger, "hdc");
|
|
2058
2159
|
const relativeHapPath = opts.hapPath ?? opts.config.get("hapPath", defaultPaths.hapPath);
|
|
2059
|
-
const hapPath =
|
|
2060
|
-
if (!
|
|
2160
|
+
const hapPath = path17.isAbsolute(relativeHapPath) ? relativeHapPath : path17.join(opts.projectDir, relativeHapPath);
|
|
2161
|
+
if (!fs17.existsSync(hapPath)) {
|
|
2061
2162
|
throw new OniroError(`HAP file not found at: ${hapPath}. Build and sign the app first.`);
|
|
2062
2163
|
}
|
|
2063
2164
|
const result = await hdcExec({ config: opts.config, args: ["install", hapPath], timeoutMs: 3e5 });
|
|
@@ -2142,10 +2243,16 @@ function listRunningProcesses(config, options = {}) {
|
|
|
2142
2243
|
const timeoutMs = options.timeoutMs ?? 1e3;
|
|
2143
2244
|
const hdc = getHdcPath(config);
|
|
2144
2245
|
return new Promise((resolve4, reject) => {
|
|
2145
|
-
|
|
2246
|
+
let proc;
|
|
2247
|
+
try {
|
|
2248
|
+
proc = spawnCompat(hdc, ["track-jpid"]);
|
|
2249
|
+
} catch (err) {
|
|
2250
|
+
reject(new OniroError(`Failed to spawn ${hdc}: ${err instanceof Error ? err.message : String(err)}`, err));
|
|
2251
|
+
return;
|
|
2252
|
+
}
|
|
2146
2253
|
const processes = [];
|
|
2147
2254
|
let resolved = false;
|
|
2148
|
-
proc.stdout
|
|
2255
|
+
proc.stdout?.on("data", (data) => {
|
|
2149
2256
|
for (const line of data.toString().split("\n").filter(Boolean)) {
|
|
2150
2257
|
const match = line.match(/^(\d+)\s+(.+)$/);
|
|
2151
2258
|
if (!match) continue;
|
|
@@ -2154,13 +2261,13 @@ function listRunningProcesses(config, options = {}) {
|
|
|
2154
2261
|
processes.push({ pid, name });
|
|
2155
2262
|
if (options.targetProcessName && name === options.targetProcessName && !resolved) {
|
|
2156
2263
|
resolved = true;
|
|
2157
|
-
proc
|
|
2264
|
+
killProcessTree(proc);
|
|
2158
2265
|
resolve4(pid);
|
|
2159
2266
|
return;
|
|
2160
2267
|
}
|
|
2161
2268
|
}
|
|
2162
2269
|
});
|
|
2163
|
-
proc.stderr
|
|
2270
|
+
proc.stderr?.on("data", (data) => {
|
|
2164
2271
|
logger.warn(`[hdc track-jpid] ${data.toString()}`);
|
|
2165
2272
|
});
|
|
2166
2273
|
proc.on("error", (err) => {
|
|
@@ -2172,7 +2279,7 @@ function listRunningProcesses(config, options = {}) {
|
|
|
2172
2279
|
const timeout = setTimeout(() => {
|
|
2173
2280
|
if (resolved) return;
|
|
2174
2281
|
resolved = true;
|
|
2175
|
-
proc
|
|
2282
|
+
killProcessTree(proc);
|
|
2176
2283
|
if (options.targetProcessName) {
|
|
2177
2284
|
reject(new OniroError(`Could not find process for bundle: ${options.targetProcessName}`));
|
|
2178
2285
|
} else {
|
|
@@ -2330,12 +2437,12 @@ async function reboot(opts) {
|
|
|
2330
2437
|
}
|
|
2331
2438
|
|
|
2332
2439
|
// src/hdc/screen.ts
|
|
2333
|
-
var
|
|
2440
|
+
var fs18 = __toESM(require("fs"), 1);
|
|
2334
2441
|
var os8 = __toESM(require("os"), 1);
|
|
2335
|
-
var
|
|
2442
|
+
var path18 = __toESM(require("path"), 1);
|
|
2336
2443
|
var import_node_crypto = require("crypto");
|
|
2337
2444
|
function tmpName(ext) {
|
|
2338
|
-
return
|
|
2445
|
+
return path18.join(os8.tmpdir(), `oniro_screen_${(0, import_node_crypto.randomBytes)(6).toString("hex")}.${ext}`);
|
|
2339
2446
|
}
|
|
2340
2447
|
async function takeScreenshot(opts) {
|
|
2341
2448
|
const remote = "/data/local/tmp/oniro_screenshot.jpeg";
|
|
@@ -2345,11 +2452,11 @@ async function takeScreenshot(opts) {
|
|
|
2345
2452
|
const local = tmpName("jpeg");
|
|
2346
2453
|
try {
|
|
2347
2454
|
await recvFile({ config: opts.config, remote, local, deviceSerial: opts.deviceSerial, timeoutMs });
|
|
2348
|
-
const pixels = await
|
|
2455
|
+
const pixels = await fs18.promises.readFile(local);
|
|
2349
2456
|
const size = await getDisplaySize(opts.config, { deviceSerial: opts.deviceSerial }) ?? { width: 0, height: 0 };
|
|
2350
2457
|
return { pixels, width: size.width, height: size.height };
|
|
2351
2458
|
} finally {
|
|
2352
|
-
|
|
2459
|
+
fs18.promises.unlink(local).catch(() => {
|
|
2353
2460
|
});
|
|
2354
2461
|
void shell({ config: opts.config, command: `rm -f ${remote}`, deviceSerial: opts.deviceSerial }).catch(() => {
|
|
2355
2462
|
});
|
|
@@ -2368,9 +2475,9 @@ async function captureBurst(opts) {
|
|
|
2368
2475
|
const local = tmpName(`burst_${i}.jpeg`);
|
|
2369
2476
|
try {
|
|
2370
2477
|
await recvFile({ config: opts.config, remote: `${remoteDir}/f${i}.jpeg`, local, deviceSerial: opts.deviceSerial });
|
|
2371
|
-
frames.push(await
|
|
2478
|
+
frames.push(await fs18.promises.readFile(local));
|
|
2372
2479
|
} finally {
|
|
2373
|
-
|
|
2480
|
+
fs18.promises.unlink(local).catch(() => {
|
|
2374
2481
|
});
|
|
2375
2482
|
}
|
|
2376
2483
|
}
|
|
@@ -2496,9 +2603,9 @@ async function sendRawTouch(opts) {
|
|
|
2496
2603
|
}
|
|
2497
2604
|
|
|
2498
2605
|
// src/hdc/dump.ts
|
|
2499
|
-
var
|
|
2606
|
+
var fs19 = __toESM(require("fs"), 1);
|
|
2500
2607
|
var os9 = __toESM(require("os"), 1);
|
|
2501
|
-
var
|
|
2608
|
+
var path19 = __toESM(require("path"), 1);
|
|
2502
2609
|
var import_node_crypto2 = require("crypto");
|
|
2503
2610
|
function parseBounds(s) {
|
|
2504
2611
|
const m = /^\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]$/.exec(s ?? "");
|
|
@@ -2583,10 +2690,10 @@ async function dumpLayout(opts) {
|
|
|
2583
2690
|
if (!m) throw new OniroError(`Could not parse dumpLayout output:
|
|
2584
2691
|
${dump.stdout}`);
|
|
2585
2692
|
const remote = m[1];
|
|
2586
|
-
const local =
|
|
2693
|
+
const local = path19.join(os9.tmpdir(), `oniro_layout_${(0, import_node_crypto2.randomBytes)(6).toString("hex")}.json`);
|
|
2587
2694
|
try {
|
|
2588
2695
|
await recvFile({ config: opts.config, remote, local, deviceSerial: opts.deviceSerial, timeoutMs });
|
|
2589
|
-
const parsed = JSON.parse(await
|
|
2696
|
+
const parsed = JSON.parse(await fs19.promises.readFile(local, "utf8"));
|
|
2590
2697
|
const display = await getDisplaySize(opts.config, { deviceSerial: opts.deviceSerial });
|
|
2591
2698
|
if (opts.prune === false) {
|
|
2592
2699
|
return { display, tree: parsed };
|
|
@@ -2595,7 +2702,7 @@ ${dump.stdout}`);
|
|
|
2595
2702
|
const tree = Array.isArray(prunedRaw) ? { children: prunedRaw } : prunedRaw ?? { children: [] };
|
|
2596
2703
|
return { display, tree };
|
|
2597
2704
|
} finally {
|
|
2598
|
-
|
|
2705
|
+
fs19.promises.unlink(local).catch(() => {
|
|
2599
2706
|
});
|
|
2600
2707
|
void shell({ config: opts.config, command: `rm -f ${remote}`, deviceSerial: opts.deviceSerial }).catch(() => {
|
|
2601
2708
|
});
|
|
@@ -2603,14 +2710,21 @@ ${dump.stdout}`);
|
|
|
2603
2710
|
}
|
|
2604
2711
|
|
|
2605
2712
|
// src/hdc/hilog.ts
|
|
2606
|
-
var import_node_child_process6 = require("child_process");
|
|
2607
2713
|
function setHilogLevel(opts) {
|
|
2608
2714
|
const logger = opts.logger ?? noopLogger;
|
|
2609
2715
|
const hdc = getHdcPath(opts.config);
|
|
2610
2716
|
return new Promise((resolve4, reject) => {
|
|
2611
|
-
|
|
2717
|
+
let child;
|
|
2718
|
+
try {
|
|
2719
|
+
child = spawnCompat(hdc, ["shell", "hilog", "-b", opts.level]);
|
|
2720
|
+
} catch (err) {
|
|
2721
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2722
|
+
logger.error(`[hilog] failed to spawn hdc: ${msg}`);
|
|
2723
|
+
reject(err instanceof Error ? err : new Error(msg));
|
|
2724
|
+
return;
|
|
2725
|
+
}
|
|
2612
2726
|
let stderr = "";
|
|
2613
|
-
child.stderr
|
|
2727
|
+
child.stderr?.on("data", (chunk) => {
|
|
2614
2728
|
stderr += chunk.toString();
|
|
2615
2729
|
});
|
|
2616
2730
|
child.once("error", (err) => {
|
|
@@ -2639,7 +2753,7 @@ function streamHilog(opts) {
|
|
|
2639
2753
|
if (opts.domain !== void 0 && `${opts.domain}` !== "") {
|
|
2640
2754
|
args.push("-D", `${opts.domain}`);
|
|
2641
2755
|
}
|
|
2642
|
-
return (
|
|
2756
|
+
return spawnCompat(hdc, args);
|
|
2643
2757
|
}
|
|
2644
2758
|
var HILOG_LINE_RE = /^(\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})\s+(\d+)\s+(\d+)\s+([DIWEF])\s+(\S+):\s+(.*)$/;
|
|
2645
2759
|
function parseHilogLine(line) {
|
|
@@ -2685,10 +2799,7 @@ function waitForLog(opts) {
|
|
|
2685
2799
|
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
2686
2800
|
opts.abortSignal?.removeEventListener("abort", onAbort);
|
|
2687
2801
|
if (child) {
|
|
2688
|
-
|
|
2689
|
-
child.kill("SIGKILL");
|
|
2690
|
-
} catch {
|
|
2691
|
-
}
|
|
2802
|
+
killProcessTree(child);
|
|
2692
2803
|
child = null;
|
|
2693
2804
|
}
|
|
2694
2805
|
};
|
|
@@ -2704,6 +2815,7 @@ function waitForLog(opts) {
|
|
|
2704
2815
|
cleanup();
|
|
2705
2816
|
reject(err);
|
|
2706
2817
|
};
|
|
2818
|
+
const failWith = (err) => fail(err instanceof Error ? err : new Error(String(err)));
|
|
2707
2819
|
const onAbort = () => fail(new CancelledError("waitForLog cancelled."));
|
|
2708
2820
|
const timer = setTimeout(
|
|
2709
2821
|
() => fail(new OniroError(`No log line matched ${String(opts.pattern)} within ${opts.timeoutMs}ms.`)),
|
|
@@ -2733,13 +2845,13 @@ function waitForLog(opts) {
|
|
|
2733
2845
|
if (settled || child !== stream) return;
|
|
2734
2846
|
child = null;
|
|
2735
2847
|
if (Date.now() < deadline) {
|
|
2736
|
-
reconnectTimer = setTimeout(() => void spawnStream(), 1e3);
|
|
2848
|
+
reconnectTimer = setTimeout(() => void spawnStream().catch(failWith), 1e3);
|
|
2737
2849
|
}
|
|
2738
2850
|
};
|
|
2739
2851
|
stream.once("close", onEnd);
|
|
2740
2852
|
stream.once("error", onEnd);
|
|
2741
2853
|
};
|
|
2742
|
-
void spawnStream();
|
|
2854
|
+
void spawnStream().catch(failWith);
|
|
2743
2855
|
});
|
|
2744
2856
|
}
|
|
2745
2857
|
function watchLog(opts) {
|
|
@@ -2752,10 +2864,7 @@ function watchLog(opts) {
|
|
|
2752
2864
|
clearTimeout(timer);
|
|
2753
2865
|
opts.abortSignal?.removeEventListener("abort", onAbort);
|
|
2754
2866
|
if (child) {
|
|
2755
|
-
|
|
2756
|
-
child.kill("SIGKILL");
|
|
2757
|
-
} catch {
|
|
2758
|
-
}
|
|
2867
|
+
killProcessTree(child);
|
|
2759
2868
|
child = null;
|
|
2760
2869
|
}
|
|
2761
2870
|
};
|
|
@@ -2788,7 +2897,12 @@ function watchLog(opts) {
|
|
|
2788
2897
|
if (entry && opts.pattern.test(entryText(entry))) matches.push(entry);
|
|
2789
2898
|
}
|
|
2790
2899
|
});
|
|
2791
|
-
})()
|
|
2900
|
+
})().catch((err) => {
|
|
2901
|
+
if (settled) return;
|
|
2902
|
+
settled = true;
|
|
2903
|
+
cleanup();
|
|
2904
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
2905
|
+
});
|
|
2792
2906
|
});
|
|
2793
2907
|
}
|
|
2794
2908
|
async function dumpLog(opts) {
|
|
@@ -2815,9 +2929,8 @@ async function dumpLog(opts) {
|
|
|
2815
2929
|
}
|
|
2816
2930
|
|
|
2817
2931
|
// src/build/runHvigorw.ts
|
|
2818
|
-
var
|
|
2819
|
-
var
|
|
2820
|
-
var import_node_child_process7 = require("child_process");
|
|
2932
|
+
var fs20 = __toESM(require("fs"), 1);
|
|
2933
|
+
var path20 = __toESM(require("path"), 1);
|
|
2821
2934
|
function buildHvigorwArgs(opts) {
|
|
2822
2935
|
const args = [opts.task ?? "assembleHap", "--mode", "module"];
|
|
2823
2936
|
args.push("-p", `product=${opts.product ?? "default"}`);
|
|
@@ -2829,19 +2942,23 @@ function buildHvigorwArgs(opts) {
|
|
|
2829
2942
|
return args;
|
|
2830
2943
|
}
|
|
2831
2944
|
function runHvigorw(opts) {
|
|
2832
|
-
const { config
|
|
2945
|
+
const { config } = opts;
|
|
2946
|
+
const projectDir = toLongPath(opts.projectDir);
|
|
2833
2947
|
const logger = opts.logger ?? noopLogger;
|
|
2834
|
-
if (!
|
|
2948
|
+
if (!fs20.existsSync(path20.join(projectDir, "build-profile.json5"))) {
|
|
2835
2949
|
throw new OniroError(`Not an OpenHarmony project: ${projectDir} (build-profile.json5 not found).`);
|
|
2836
2950
|
}
|
|
2837
|
-
if (!
|
|
2951
|
+
if (!fs20.existsSync(getCmdToolsPath(config))) {
|
|
2838
2952
|
throw new CmdToolsNotInstalledError(getCmdToolsPath(config));
|
|
2839
2953
|
}
|
|
2840
2954
|
const hvigorw = getHvigorwPath(config, projectDir);
|
|
2955
|
+
if (!fs20.existsSync(hvigorw)) {
|
|
2956
|
+
throw new OniroError(`hvigorw wrapper not found at ${hvigorw}.`);
|
|
2957
|
+
}
|
|
2841
2958
|
const args = buildHvigorwArgs(opts);
|
|
2842
2959
|
if (process.platform !== "win32") {
|
|
2843
2960
|
try {
|
|
2844
|
-
|
|
2961
|
+
fs20.chmodSync(hvigorw, 493);
|
|
2845
2962
|
} catch {
|
|
2846
2963
|
}
|
|
2847
2964
|
}
|
|
@@ -2855,26 +2972,29 @@ function runHvigorw(opts) {
|
|
|
2855
2972
|
return;
|
|
2856
2973
|
}
|
|
2857
2974
|
logger.info(`[build] ${hvigorw} ${args.join(" ")}`);
|
|
2858
|
-
|
|
2975
|
+
let child;
|
|
2976
|
+
try {
|
|
2977
|
+
child = spawnCompat(hvigorw, args, { cwd: projectDir, env });
|
|
2978
|
+
} catch (err) {
|
|
2979
|
+
reject(new OniroError(`Failed to start hvigorw: ${err instanceof Error ? err.message : String(err)}`, err));
|
|
2980
|
+
return;
|
|
2981
|
+
}
|
|
2859
2982
|
let settled = false;
|
|
2860
2983
|
const cleanup = () => opts.abortSignal?.removeEventListener("abort", onAbort);
|
|
2861
2984
|
const onAbort = () => {
|
|
2862
2985
|
if (settled) return;
|
|
2863
2986
|
settled = true;
|
|
2864
2987
|
cleanup();
|
|
2865
|
-
|
|
2866
|
-
child.kill("SIGKILL");
|
|
2867
|
-
} catch {
|
|
2868
|
-
}
|
|
2988
|
+
killProcessTree(child);
|
|
2869
2989
|
reject(new CancelledError("hvigorw build cancelled."));
|
|
2870
2990
|
};
|
|
2871
2991
|
opts.abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
2872
|
-
child.stdout
|
|
2992
|
+
child.stdout?.on("data", (chunk) => {
|
|
2873
2993
|
const text = chunk.toString();
|
|
2874
2994
|
opts.onOutput?.(text, "stdout");
|
|
2875
2995
|
logger.info(text.trimEnd());
|
|
2876
2996
|
});
|
|
2877
|
-
child.stderr
|
|
2997
|
+
child.stderr?.on("data", (chunk) => {
|
|
2878
2998
|
const text = chunk.toString();
|
|
2879
2999
|
opts.onOutput?.(text, "stderr");
|
|
2880
3000
|
logger.warn(text.trimEnd());
|
|
@@ -2897,8 +3017,8 @@ function runHvigorw(opts) {
|
|
|
2897
3017
|
}
|
|
2898
3018
|
|
|
2899
3019
|
// src/build/discoverHaps.ts
|
|
2900
|
-
var
|
|
2901
|
-
var
|
|
3020
|
+
var fs21 = __toESM(require("fs"), 1);
|
|
3021
|
+
var path21 = __toESM(require("path"), 1);
|
|
2902
3022
|
function moduleOfHap(hapFileName) {
|
|
2903
3023
|
const dash = hapFileName.indexOf("-");
|
|
2904
3024
|
return dash > 0 ? hapFileName.slice(0, dash) : hapFileName.replace(/\.hap$/i, "");
|
|
@@ -2909,9 +3029,9 @@ async function discoverHaps(opts) {
|
|
|
2909
3029
|
const result = {};
|
|
2910
3030
|
const walk = async (dir, depth) => {
|
|
2911
3031
|
if (depth > maxDepth) return;
|
|
2912
|
-
const entries = await
|
|
3032
|
+
const entries = await fs21.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
2913
3033
|
for (const e of entries) {
|
|
2914
|
-
const full =
|
|
3034
|
+
const full = path21.join(dir, e.name);
|
|
2915
3035
|
if (e.isDirectory()) {
|
|
2916
3036
|
if (e.name === "node_modules" || e.name === "oh_modules" || e.name === ".git") continue;
|
|
2917
3037
|
await walk(full, depth + 1);
|
|
@@ -2928,8 +3048,8 @@ async function discoverHaps(opts) {
|
|
|
2928
3048
|
}
|
|
2929
3049
|
|
|
2930
3050
|
// src/build/ohpm.ts
|
|
2931
|
-
var
|
|
2932
|
-
var
|
|
3051
|
+
var fs22 = __toESM(require("fs"), 1);
|
|
3052
|
+
var path22 = __toESM(require("path"), 1);
|
|
2933
3053
|
function runOhpm(opts) {
|
|
2934
3054
|
return runProcess({
|
|
2935
3055
|
command: getOhpmPath(opts.config),
|
|
@@ -2942,7 +3062,7 @@ function runOhpm(opts) {
|
|
|
2942
3062
|
});
|
|
2943
3063
|
}
|
|
2944
3064
|
async function ensureOhModules(opts) {
|
|
2945
|
-
if (
|
|
3065
|
+
if (fs22.existsSync(path22.join(opts.projectDir, "oh_modules"))) {
|
|
2946
3066
|
return { installed: false };
|
|
2947
3067
|
}
|
|
2948
3068
|
const res = await runOhpm({
|
|
@@ -2994,10 +3114,11 @@ async function buildHap(opts) {
|
|
|
2994
3114
|
const logger = scopedLogger(opts.logger ?? noopLogger, "build");
|
|
2995
3115
|
const warnings = [];
|
|
2996
3116
|
const start = Date.now();
|
|
3117
|
+
const projectDir = toLongPath(opts.projectDir);
|
|
2997
3118
|
if (opts.autoInstallDeps !== false) {
|
|
2998
3119
|
const r = await ensureOhModules({
|
|
2999
3120
|
config: opts.config,
|
|
3000
|
-
projectDir
|
|
3121
|
+
projectDir,
|
|
3001
3122
|
abortSignal: opts.abortSignal,
|
|
3002
3123
|
onOutput: opts.onOutput,
|
|
3003
3124
|
logger: opts.logger
|
|
@@ -3006,7 +3127,7 @@ async function buildHap(opts) {
|
|
|
3006
3127
|
}
|
|
3007
3128
|
const { exitCode } = await runHvigorw({
|
|
3008
3129
|
config: opts.config,
|
|
3009
|
-
projectDir
|
|
3130
|
+
projectDir,
|
|
3010
3131
|
product: opts.product,
|
|
3011
3132
|
module: opts.module,
|
|
3012
3133
|
buildMode: opts.mode,
|
|
@@ -3016,7 +3137,7 @@ async function buildHap(opts) {
|
|
|
3016
3137
|
onOutput: opts.onOutput,
|
|
3017
3138
|
logger: opts.logger
|
|
3018
3139
|
});
|
|
3019
|
-
const discoveredHaps = await discoverHaps({ projectDir
|
|
3140
|
+
const discoveredHaps = await discoverHaps({ projectDir });
|
|
3020
3141
|
const anySigned = Object.values(discoveredHaps).some((m) => m.signed.length > 0);
|
|
3021
3142
|
if (!anySigned) {
|
|
3022
3143
|
warnings.push(
|
|
@@ -3037,21 +3158,21 @@ function isValidBundleName(bundleName) {
|
|
|
3037
3158
|
}
|
|
3038
3159
|
|
|
3039
3160
|
// src/project/templates.ts
|
|
3040
|
-
var
|
|
3041
|
-
var
|
|
3161
|
+
var fs23 = __toESM(require("fs"), 1);
|
|
3162
|
+
var path23 = __toESM(require("path"), 1);
|
|
3042
3163
|
function toHumanTemplateName(folderName) {
|
|
3043
3164
|
return folderName.replace(/([a-z])([A-Z])/g, "$1 $2");
|
|
3044
3165
|
}
|
|
3045
3166
|
function listTemplates(templateRoot) {
|
|
3046
|
-
if (!
|
|
3047
|
-
const entries =
|
|
3167
|
+
if (!fs23.existsSync(templateRoot)) return [];
|
|
3168
|
+
const entries = fs23.readdirSync(templateRoot, { withFileTypes: true });
|
|
3048
3169
|
return entries.filter((e) => e.isDirectory()).map((e) => {
|
|
3049
|
-
const dir =
|
|
3050
|
-
const metaPath =
|
|
3170
|
+
const dir = path23.join(templateRoot, e.name);
|
|
3171
|
+
const metaPath = path23.join(dir, "template.json");
|
|
3051
3172
|
let meta = {};
|
|
3052
|
-
if (
|
|
3173
|
+
if (fs23.existsSync(metaPath)) {
|
|
3053
3174
|
try {
|
|
3054
|
-
meta = JSON.parse(
|
|
3175
|
+
meta = JSON.parse(fs23.readFileSync(metaPath, "utf8"));
|
|
3055
3176
|
} catch {
|
|
3056
3177
|
}
|
|
3057
3178
|
}
|
|
@@ -3066,57 +3187,57 @@ function listTemplates(templateRoot) {
|
|
|
3066
3187
|
function validateTemplateLayout(templateDir, defaultModuleName) {
|
|
3067
3188
|
const required = [
|
|
3068
3189
|
"build-profile.json5",
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3190
|
+
path23.join("AppScope", "app.json5"),
|
|
3191
|
+
path23.join(defaultModuleName, "src", "main", "module.json5"),
|
|
3192
|
+
path23.join(defaultModuleName, "oh-package.json5"),
|
|
3072
3193
|
"hvigorfile.ts"
|
|
3073
3194
|
];
|
|
3074
|
-
return required.filter((rel) => !
|
|
3195
|
+
return required.filter((rel) => !fs23.existsSync(path23.join(templateDir, rel)));
|
|
3075
3196
|
}
|
|
3076
3197
|
|
|
3077
3198
|
// src/project/createScaffold.ts
|
|
3078
|
-
var
|
|
3079
|
-
var
|
|
3199
|
+
var fs25 = __toESM(require("fs"), 1);
|
|
3200
|
+
var path24 = __toESM(require("path"), 1);
|
|
3080
3201
|
|
|
3081
3202
|
// src/project/jsonHelpers.ts
|
|
3082
|
-
var
|
|
3203
|
+
var fs24 = __toESM(require("fs"), 1);
|
|
3083
3204
|
var import_json54 = __toESM(require("json5"), 1);
|
|
3084
3205
|
function readJson5File(filePath) {
|
|
3085
|
-
return import_json54.default.parse(
|
|
3206
|
+
return import_json54.default.parse(fs24.readFileSync(filePath, "utf8"));
|
|
3086
3207
|
}
|
|
3087
3208
|
function writeJson5File(filePath, value) {
|
|
3088
|
-
|
|
3209
|
+
fs24.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
|
|
3089
3210
|
}
|
|
3090
3211
|
function readJsonFile(filePath) {
|
|
3091
|
-
return JSON.parse(
|
|
3212
|
+
return JSON.parse(fs24.readFileSync(filePath, "utf8"));
|
|
3092
3213
|
}
|
|
3093
3214
|
function writeJsonFile(filePath, value) {
|
|
3094
|
-
|
|
3215
|
+
fs24.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
|
|
3095
3216
|
}
|
|
3096
3217
|
|
|
3097
3218
|
// src/project/createScaffold.ts
|
|
3098
3219
|
var IGNORED_DIRS = /* @__PURE__ */ new Set(["oh_modules", "node_modules", "build", ".hvigor"]);
|
|
3099
3220
|
async function pathExists(p) {
|
|
3100
3221
|
try {
|
|
3101
|
-
await
|
|
3222
|
+
await fs25.promises.access(p);
|
|
3102
3223
|
return true;
|
|
3103
3224
|
} catch {
|
|
3104
3225
|
return false;
|
|
3105
3226
|
}
|
|
3106
3227
|
}
|
|
3107
3228
|
async function copyDirRecursive(srcDir, destDir) {
|
|
3108
|
-
await
|
|
3109
|
-
const entries = await
|
|
3229
|
+
await fs25.promises.mkdir(destDir, { recursive: true });
|
|
3230
|
+
const entries = await fs25.promises.readdir(srcDir, { withFileTypes: true });
|
|
3110
3231
|
for (const entry of entries) {
|
|
3111
|
-
const src =
|
|
3112
|
-
const dest =
|
|
3232
|
+
const src = path24.join(srcDir, entry.name);
|
|
3233
|
+
const dest = path24.join(destDir, entry.name);
|
|
3113
3234
|
if (entry.isDirectory()) {
|
|
3114
3235
|
await copyDirRecursive(src, dest);
|
|
3115
3236
|
} else if (entry.isSymbolicLink()) {
|
|
3116
3237
|
continue;
|
|
3117
3238
|
} else if (entry.isFile()) {
|
|
3118
3239
|
if (entry.name === "template.json") continue;
|
|
3119
|
-
await
|
|
3240
|
+
await fs25.promises.copyFile(src, dest);
|
|
3120
3241
|
}
|
|
3121
3242
|
}
|
|
3122
3243
|
}
|
|
@@ -3124,9 +3245,9 @@ async function normalizeJson5ToJson(projectDir, logger) {
|
|
|
3124
3245
|
const stack = [projectDir];
|
|
3125
3246
|
while (stack.length > 0) {
|
|
3126
3247
|
const currentDir = stack.pop();
|
|
3127
|
-
const entries = await
|
|
3248
|
+
const entries = await fs25.promises.readdir(currentDir, { withFileTypes: true });
|
|
3128
3249
|
for (const entry of entries) {
|
|
3129
|
-
const fullPath =
|
|
3250
|
+
const fullPath = path24.join(currentDir, entry.name);
|
|
3130
3251
|
if (entry.isDirectory()) {
|
|
3131
3252
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
3132
3253
|
stack.push(fullPath);
|
|
@@ -3148,23 +3269,23 @@ function toJavaPropertiesPath(p) {
|
|
|
3148
3269
|
function createOrUpdateLocalProperties(projectDir, sdkDir) {
|
|
3149
3270
|
const content = `sdk.dir=${toJavaPropertiesPath(sdkDir)}
|
|
3150
3271
|
`;
|
|
3151
|
-
|
|
3272
|
+
fs25.writeFileSync(path24.join(projectDir, "local.properties"), content, "utf8");
|
|
3152
3273
|
}
|
|
3153
3274
|
function renameIfExists(fromPath, toPath) {
|
|
3154
|
-
if (
|
|
3155
|
-
|
|
3275
|
+
if (fs25.existsSync(fromPath) && fromPath !== toPath) {
|
|
3276
|
+
fs25.renameSync(fromPath, toPath);
|
|
3156
3277
|
}
|
|
3157
3278
|
}
|
|
3158
3279
|
function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
|
|
3159
|
-
const appJsonPath =
|
|
3160
|
-
if (
|
|
3280
|
+
const appJsonPath = path24.join(projectDir, "AppScope", "app.json5");
|
|
3281
|
+
if (fs25.existsSync(appJsonPath)) {
|
|
3161
3282
|
const appJson = readJson5File(appJsonPath);
|
|
3162
3283
|
appJson.app = appJson.app ?? {};
|
|
3163
3284
|
appJson.app.bundleName = args.bundleName;
|
|
3164
3285
|
writeJson5File(appJsonPath, appJson);
|
|
3165
3286
|
}
|
|
3166
|
-
const stringsPath =
|
|
3167
|
-
if (
|
|
3287
|
+
const stringsPath = path24.join(projectDir, "AppScope", "resources", "base", "element", "string.json");
|
|
3288
|
+
if (fs25.existsSync(stringsPath)) {
|
|
3168
3289
|
const strings = readJsonFile(stringsPath);
|
|
3169
3290
|
if (Array.isArray(strings.string)) {
|
|
3170
3291
|
const appName = strings.string.find((s) => s.name === "app_name");
|
|
@@ -3172,8 +3293,8 @@ function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
|
|
|
3172
3293
|
}
|
|
3173
3294
|
writeJsonFile(stringsPath, strings);
|
|
3174
3295
|
}
|
|
3175
|
-
const buildProfilePath =
|
|
3176
|
-
if (
|
|
3296
|
+
const buildProfilePath = path24.join(projectDir, "build-profile.json5");
|
|
3297
|
+
if (fs25.existsSync(buildProfilePath)) {
|
|
3177
3298
|
const buildProfile = readJson5File(buildProfilePath);
|
|
3178
3299
|
buildProfile.app = buildProfile.app ?? {};
|
|
3179
3300
|
if (Array.isArray(buildProfile.app.products) && buildProfile.app.products.length > 0) {
|
|
@@ -3186,23 +3307,23 @@ function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
|
|
|
3186
3307
|
}
|
|
3187
3308
|
writeJson5File(buildProfilePath, buildProfile);
|
|
3188
3309
|
}
|
|
3189
|
-
const moduleJsonPath =
|
|
3190
|
-
if (
|
|
3310
|
+
const moduleJsonPath = path24.join(projectDir, args.moduleName, "src", "main", "module.json5");
|
|
3311
|
+
if (fs25.existsSync(moduleJsonPath)) {
|
|
3191
3312
|
const moduleJson = readJson5File(moduleJsonPath);
|
|
3192
3313
|
moduleJson.module = moduleJson.module ?? {};
|
|
3193
3314
|
moduleJson.module.name = args.moduleName;
|
|
3194
3315
|
writeJson5File(moduleJsonPath, moduleJson);
|
|
3195
3316
|
}
|
|
3196
|
-
const moduleOhPackagePath =
|
|
3197
|
-
if (
|
|
3317
|
+
const moduleOhPackagePath = path24.join(projectDir, args.moduleName, "oh-package.json5");
|
|
3318
|
+
if (fs25.existsSync(moduleOhPackagePath)) {
|
|
3198
3319
|
const pkg = readJson5File(moduleOhPackagePath);
|
|
3199
3320
|
pkg.name = args.moduleName;
|
|
3200
3321
|
writeJson5File(moduleOhPackagePath, pkg);
|
|
3201
3322
|
}
|
|
3202
|
-
const vscodeDir =
|
|
3203
|
-
|
|
3323
|
+
const vscodeDir = path24.join(projectDir, ".vscode");
|
|
3324
|
+
fs25.mkdirSync(vscodeDir, { recursive: true });
|
|
3204
3325
|
const hapPath = `${args.moduleName}/build/default/outputs/default/${args.moduleName}-default-signed.hap`;
|
|
3205
|
-
writeJsonFile(
|
|
3326
|
+
writeJsonFile(path24.join(vscodeDir, "settings.json"), {
|
|
3206
3327
|
"oniro.hapPath": hapPath,
|
|
3207
3328
|
"files.associations": { "*.json5": "jsonc" }
|
|
3208
3329
|
});
|
|
@@ -3219,7 +3340,7 @@ async function createScaffold(opts) {
|
|
|
3219
3340
|
if (!opts.location || !await pathExists(opts.location)) {
|
|
3220
3341
|
throw new OniroError(`Location does not exist: ${opts.location}`);
|
|
3221
3342
|
}
|
|
3222
|
-
const templateDir =
|
|
3343
|
+
const templateDir = path24.join(opts.templateRoot, opts.templateId);
|
|
3223
3344
|
if (!await pathExists(templateDir)) {
|
|
3224
3345
|
throw new OniroError(`Template not found: ${templateDir}`);
|
|
3225
3346
|
}
|
|
@@ -3232,17 +3353,17 @@ async function createScaffold(opts) {
|
|
|
3232
3353
|
throw new OniroError(`Template '${opts.templateId}' is missing required files:
|
|
3233
3354
|
- ${missing.join("\n- ")}`);
|
|
3234
3355
|
}
|
|
3235
|
-
const projectDir =
|
|
3356
|
+
const projectDir = path24.join(opts.location, opts.projectName);
|
|
3236
3357
|
if (await pathExists(projectDir)) {
|
|
3237
3358
|
if (!opts.overwrite) {
|
|
3238
3359
|
throw new OniroError(`Destination already exists: ${projectDir}. Pass overwrite: true to replace it.`);
|
|
3239
3360
|
}
|
|
3240
|
-
await
|
|
3361
|
+
await fs25.promises.rm(projectDir, { recursive: true, force: true });
|
|
3241
3362
|
}
|
|
3242
3363
|
logger.info(`[create] Scaffolding ${opts.templateId} at ${projectDir}`);
|
|
3243
3364
|
await copyDirRecursive(templateDir, projectDir);
|
|
3244
3365
|
if (moduleName !== defaultModuleName) {
|
|
3245
|
-
renameIfExists(
|
|
3366
|
+
renameIfExists(path24.join(projectDir, defaultModuleName), path24.join(projectDir, moduleName));
|
|
3246
3367
|
}
|
|
3247
3368
|
updateTemplateConfigs(
|
|
3248
3369
|
projectDir,
|
|
@@ -3259,11 +3380,11 @@ async function createScaffold(opts) {
|
|
|
3259
3380
|
}
|
|
3260
3381
|
|
|
3261
3382
|
// src/project/listModules.ts
|
|
3262
|
-
var
|
|
3263
|
-
var
|
|
3383
|
+
var fs26 = __toESM(require("fs"), 1);
|
|
3384
|
+
var path25 = __toESM(require("path"), 1);
|
|
3264
3385
|
function listModules(opts) {
|
|
3265
|
-
const buildProfile =
|
|
3266
|
-
if (!
|
|
3386
|
+
const buildProfile = path25.join(opts.projectDir, "build-profile.json5");
|
|
3387
|
+
if (!fs26.existsSync(buildProfile)) {
|
|
3267
3388
|
throw new OniroError(`build-profile.json5 not found at ${buildProfile}`);
|
|
3268
3389
|
}
|
|
3269
3390
|
const parsed = readJson5File(buildProfile);
|
|
@@ -3275,12 +3396,12 @@ function listModules(opts) {
|
|
|
3275
3396
|
}
|
|
3276
3397
|
|
|
3277
3398
|
// src/project/abilities.ts
|
|
3278
|
-
var
|
|
3279
|
-
var
|
|
3399
|
+
var fs27 = __toESM(require("fs"), 1);
|
|
3400
|
+
var path26 = __toESM(require("path"), 1);
|
|
3280
3401
|
function listAbilities(opts) {
|
|
3281
3402
|
const moduleName = opts.moduleName ?? "entry";
|
|
3282
|
-
const moduleJsonPath =
|
|
3283
|
-
if (!
|
|
3403
|
+
const moduleJsonPath = path26.join(opts.projectDir, moduleName, "src", "main", "module.json5");
|
|
3404
|
+
if (!fs27.existsSync(moduleJsonPath)) {
|
|
3284
3405
|
throw new OniroError(`Could not find module.json5 at ${moduleJsonPath}`);
|
|
3285
3406
|
}
|
|
3286
3407
|
const parsed = readJson5File(moduleJsonPath);
|
|
@@ -3288,12 +3409,12 @@ function listAbilities(opts) {
|
|
|
3288
3409
|
}
|
|
3289
3410
|
|
|
3290
3411
|
// src/project/prepareSigning.ts
|
|
3291
|
-
var
|
|
3292
|
-
var
|
|
3412
|
+
var fs28 = __toESM(require("fs"), 1);
|
|
3413
|
+
var path27 = __toESM(require("path"), 1);
|
|
3293
3414
|
function hasSigningArtifacts(dir) {
|
|
3294
|
-
if (!
|
|
3295
|
-
const buildProfile =
|
|
3296
|
-
if (!
|
|
3415
|
+
if (!fs28.existsSync(path27.join(dir, "signatures"))) return false;
|
|
3416
|
+
const buildProfile = path27.join(dir, "build-profile.json5");
|
|
3417
|
+
if (!fs28.existsSync(buildProfile)) return false;
|
|
3297
3418
|
try {
|
|
3298
3419
|
const parsed = readJson5File(buildProfile);
|
|
3299
3420
|
return Array.isArray(parsed.app?.signingConfigs) && parsed.app.signingConfigs.length > 0;
|
|
@@ -3383,8 +3504,8 @@ async function diffHapAssets(opts) {
|
|
|
3383
3504
|
}
|
|
3384
3505
|
|
|
3385
3506
|
// src/install/apply.ts
|
|
3386
|
-
var
|
|
3387
|
-
var
|
|
3507
|
+
var fs29 = __toESM(require("fs"), 1);
|
|
3508
|
+
var path28 = __toESM(require("path"), 1);
|
|
3388
3509
|
function decideInstallMethod(s) {
|
|
3389
3510
|
if (!s.signInfoInconsistent) return "replace";
|
|
3390
3511
|
if (s.isSystemBundle && !s.allowUninstall) return "refuse";
|
|
@@ -3405,7 +3526,7 @@ async function pidOf(config, bundle, deviceSerial) {
|
|
|
3405
3526
|
async function resolveHapPath(opts) {
|
|
3406
3527
|
let hapPath = opts.hapPath;
|
|
3407
3528
|
if (hapPath) {
|
|
3408
|
-
if (!
|
|
3529
|
+
if (!path28.isAbsolute(hapPath) && opts.projectDir) hapPath = path28.join(opts.projectDir, hapPath);
|
|
3409
3530
|
} else {
|
|
3410
3531
|
if (!opts.projectDir) throw new OniroError("applyChanges requires hapPath or projectDir.");
|
|
3411
3532
|
const haps = await discoverHaps({ projectDir: opts.projectDir });
|
|
@@ -3424,7 +3545,7 @@ async function resolveHapPath(opts) {
|
|
|
3424
3545
|
hapPath = withSigned[0][1].signed[0];
|
|
3425
3546
|
}
|
|
3426
3547
|
}
|
|
3427
|
-
if (!
|
|
3548
|
+
if (!fs29.existsSync(hapPath)) throw new OniroError(`HAP not found at ${hapPath}.`);
|
|
3428
3549
|
return hapPath;
|
|
3429
3550
|
}
|
|
3430
3551
|
async function applyChanges(opts) {
|
|
@@ -3434,7 +3555,7 @@ async function applyChanges(opts) {
|
|
|
3434
3555
|
const allowUninstall = opts.allowUninstall ?? false;
|
|
3435
3556
|
const hapPath = await resolveHapPath(opts);
|
|
3436
3557
|
let assetsChanged = false;
|
|
3437
|
-
if (opts.installedHapPath &&
|
|
3558
|
+
if (opts.installedHapPath && fs29.existsSync(opts.installedHapPath)) {
|
|
3438
3559
|
try {
|
|
3439
3560
|
const diff = await diffHapAssets({ installedHap: opts.installedHapPath, newHap: hapPath });
|
|
3440
3561
|
assetsChanged = diff.addedAssetPaths.length > 0 || diff.removedAssetPaths.length > 0;
|
|
@@ -3476,7 +3597,7 @@ async function applyChanges(opts) {
|
|
|
3476
3597
|
}
|
|
3477
3598
|
|
|
3478
3599
|
// src/index.ts
|
|
3479
|
-
var VERSION = "0.
|
|
3600
|
+
var VERSION = "0.9.0";
|
|
3480
3601
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3481
3602
|
0 && (module.exports = {
|
|
3482
3603
|
ALL_SDKS,
|
|
@@ -3496,6 +3617,7 @@ var VERSION = "0.8.0";
|
|
|
3496
3617
|
VERSION,
|
|
3497
3618
|
applyChanges,
|
|
3498
3619
|
attemptHdcConnection,
|
|
3620
|
+
buildCmdWrapper,
|
|
3499
3621
|
buildGestureCommands,
|
|
3500
3622
|
buildGestureUitestCommand,
|
|
3501
3623
|
buildHap,
|
|
@@ -3532,6 +3654,8 @@ var VERSION = "0.8.0";
|
|
|
3532
3654
|
ensureOhModules,
|
|
3533
3655
|
ensureOk,
|
|
3534
3656
|
ensureRemoteOk,
|
|
3657
|
+
escapeCmdArgument,
|
|
3658
|
+
escapeCmdCommand,
|
|
3535
3659
|
extractTarball,
|
|
3536
3660
|
extractZipWithProgress,
|
|
3537
3661
|
findAppProcessId,
|
|
@@ -3570,12 +3694,14 @@ var VERSION = "0.8.0";
|
|
|
3570
3694
|
isRamBackedPath,
|
|
3571
3695
|
isValidBundleName,
|
|
3572
3696
|
isValidProjectName,
|
|
3697
|
+
killProcessTree,
|
|
3573
3698
|
launchApp,
|
|
3574
3699
|
listAbilities,
|
|
3575
3700
|
listDevices,
|
|
3576
3701
|
listModules,
|
|
3577
3702
|
listRunningProcesses,
|
|
3578
3703
|
listTemplates,
|
|
3704
|
+
needsCmdWrapper,
|
|
3579
3705
|
nonInteractivePrompter,
|
|
3580
3706
|
noopLogger,
|
|
3581
3707
|
noopProgress,
|
|
@@ -3612,11 +3738,13 @@ var VERSION = "0.8.0";
|
|
|
3612
3738
|
setHilogLevel,
|
|
3613
3739
|
shell,
|
|
3614
3740
|
shellChecked,
|
|
3741
|
+
spawnCompat,
|
|
3615
3742
|
startEmulator,
|
|
3616
3743
|
staticConfig,
|
|
3617
3744
|
stopEmulator,
|
|
3618
3745
|
streamHilog,
|
|
3619
3746
|
takeScreenshot,
|
|
3747
|
+
toLongPath,
|
|
3620
3748
|
toSpaceError,
|
|
3621
3749
|
uninstallApp,
|
|
3622
3750
|
validateTemplateLayout,
|