qraftai-runner 0.1.0 → 0.3.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.js +61 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,6 +7,8 @@ import { createRequire } from "node:module";
|
|
|
7
7
|
import { writeFileSync, existsSync, statSync, mkdirSync } from "node:fs";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import { join } from "node:path";
|
|
10
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
11
|
+
import { promisify as promisify2 } from "node:util";
|
|
10
12
|
|
|
11
13
|
// ../server/mobile/appiumManager.js
|
|
12
14
|
import { spawn } from "node:child_process";
|
|
@@ -66,6 +68,7 @@ import { execFile } from "node:child_process";
|
|
|
66
68
|
import { promisify } from "node:util";
|
|
67
69
|
var pexec = promisify(execFile);
|
|
68
70
|
var DEFAULT_NEW_COMMAND_TIMEOUT = parseInt(process.env.APPIUM_CMD_TIMEOUT || "120");
|
|
71
|
+
var STUDIO_CMD_TIMEOUT = parseInt(process.env.STUDIO_APPIUM_CMD_TIMEOUT || "3600");
|
|
69
72
|
var MJPEG_PORT = parseInt(process.env.MOBILE_MJPEG_PORT || "9100");
|
|
70
73
|
async function listIosSimulators() {
|
|
71
74
|
try {
|
|
@@ -1070,6 +1073,7 @@ var AppiumDriver = class extends AutomationDriver {
|
|
|
1070
1073
|
};
|
|
1071
1074
|
|
|
1072
1075
|
// index.js
|
|
1076
|
+
var pexec2 = promisify2(execFile2);
|
|
1073
1077
|
var VERSION = (() => {
|
|
1074
1078
|
const req = createRequire(import.meta.url);
|
|
1075
1079
|
for (const p of ["./package.json", "../package.json"]) {
|
|
@@ -1087,10 +1091,49 @@ function parseArgs(argv) {
|
|
|
1087
1091
|
if (a === "--server" || a === "-s") out.server = argv[++i];
|
|
1088
1092
|
else if (a === "--token" || a === "-t") out.token = argv[++i];
|
|
1089
1093
|
else if (a === "--name" || a === "-n") out.name = argv[++i];
|
|
1094
|
+
else if (a === "--check" || a === "--doctor") out.check = true;
|
|
1095
|
+
else if (a === "--skip-check") out.skipCheck = true;
|
|
1090
1096
|
else if (a === "--help" || a === "-h") out.help = true;
|
|
1091
1097
|
}
|
|
1092
1098
|
return out;
|
|
1093
1099
|
}
|
|
1100
|
+
async function have(cmd, cmdArgs, re) {
|
|
1101
|
+
try {
|
|
1102
|
+
const { stdout, stderr } = await pexec2(cmd, cmdArgs, { timeout: 8e3 });
|
|
1103
|
+
return re ? re.test(`${stdout || ""}${stderr || ""}`) : true;
|
|
1104
|
+
} catch {
|
|
1105
|
+
return false;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
async function preflight() {
|
|
1109
|
+
const java = await have("java", ["-version"]);
|
|
1110
|
+
const adb = await have("adb", ["version"]);
|
|
1111
|
+
const appium = await have("appium", ["--version"]);
|
|
1112
|
+
const uia = appium ? await have("appium", ["driver", "list", "--installed"], /uiautomator2/i) : false;
|
|
1113
|
+
let device = false;
|
|
1114
|
+
try {
|
|
1115
|
+
device = (await listAdbDevices()).length > 0 || (await listAvds()).length > 0;
|
|
1116
|
+
} catch {
|
|
1117
|
+
}
|
|
1118
|
+
return [
|
|
1119
|
+
{ label: "Java (JDK 17+)", ok: java, critical: false, hint: "install a JDK 17+ (e.g. brew install openjdk)" },
|
|
1120
|
+
{ label: "adb (Android SDK platform-tools)", ok: adb, critical: true, hint: "install Android SDK; add platform-tools to PATH + set ANDROID_HOME" },
|
|
1121
|
+
{ label: "Appium 2", ok: appium, critical: true, hint: "npm i -g appium" },
|
|
1122
|
+
{ label: "uiautomator2 driver", ok: uia, critical: true, hint: "appium driver install uiautomator2" },
|
|
1123
|
+
{ label: "A device (booted emulator / USB phone)", ok: device, critical: false, hint: "boot an emulator or plug in a phone with USB debugging" }
|
|
1124
|
+
];
|
|
1125
|
+
}
|
|
1126
|
+
function reportPreflight(checks) {
|
|
1127
|
+
console.log("\nPrerequisite check:");
|
|
1128
|
+
let criticalMissing = false, deviceMissing = false;
|
|
1129
|
+
for (const c of checks) {
|
|
1130
|
+
console.log(` ${c.ok ? "\u2713" : "\u2717"} ${c.label}${c.ok ? "" : ` \u2192 ${c.hint}`}`);
|
|
1131
|
+
if (!c.ok && c.critical) criticalMissing = true;
|
|
1132
|
+
if (!c.ok && !c.critical && /device/i.test(c.label)) deviceMissing = true;
|
|
1133
|
+
}
|
|
1134
|
+
if (!criticalMissing && deviceMissing) console.log(" (no device yet \u2014 connect one and it'll appear on \u21BB Recheck in the app)");
|
|
1135
|
+
return { criticalMissing };
|
|
1136
|
+
}
|
|
1094
1137
|
var args = parseArgs(process.argv.slice(2));
|
|
1095
1138
|
if (args.help) {
|
|
1096
1139
|
console.log(`QraftAI Runner v${VERSION}
|
|
@@ -1103,11 +1146,18 @@ Options:
|
|
|
1103
1146
|
-s, --server wss://<your-qraftai-host>/runner-stream (or QRAFTAI_SERVER)
|
|
1104
1147
|
-t, --token org-scoped runner token from the Mobile tab (or QRAFTAI_TOKEN)
|
|
1105
1148
|
-n, --name a label shown in the app for this machine (or QRAFTAI_RUNNER_NAME)
|
|
1149
|
+
--check check prerequisites and exit (no connection; also --doctor)
|
|
1150
|
+
--skip-check connect without the startup prerequisite check
|
|
1106
1151
|
|
|
1107
1152
|
Prerequisites (on this machine): JDK 17+, Android SDK (adb + emulator),
|
|
1108
1153
|
Appium 2 + uiautomator2, and a device (AVD or USB phone with USB debugging).`);
|
|
1109
1154
|
process.exit(0);
|
|
1110
1155
|
}
|
|
1156
|
+
if (args.check) {
|
|
1157
|
+
const { criticalMissing } = reportPreflight(await preflight());
|
|
1158
|
+
console.log(criticalMissing ? "\n\u2716 Missing required tools above.\n" : "\n\u2713 Ready to run the runner.\n");
|
|
1159
|
+
process.exit(criticalMissing ? 1 : 0);
|
|
1160
|
+
}
|
|
1111
1161
|
var SERVER = args.server || process.env.QRAFTAI_SERVER;
|
|
1112
1162
|
var TOKEN = args.token || process.env.QRAFTAI_TOKEN;
|
|
1113
1163
|
var NAME = args.name || process.env.QRAFTAI_RUNNER_NAME || "";
|
|
@@ -1130,11 +1180,12 @@ function sendMsg(type, payload = {}, reqId) {
|
|
|
1130
1180
|
var ok = (reqId, result) => sendMsg("RESULT", { result }, reqId);
|
|
1131
1181
|
var err = (reqId, message) => sendMsg("ERROR", { message }, reqId);
|
|
1132
1182
|
var HANDLERS = {
|
|
1133
|
-
async OPEN_SESSION({ sessionId, device, kind = "avd", platform = "android", app }) {
|
|
1183
|
+
async OPEN_SESSION({ sessionId, device, kind = "avd", platform = "android", app, studio = false }) {
|
|
1134
1184
|
if (sessions.has(sessionId)) return { platform: sessions.get(sessionId).platform };
|
|
1135
1185
|
const resolvedApp = await resolveApp(app);
|
|
1136
1186
|
const { host, port } = await ensureAppium();
|
|
1137
|
-
const
|
|
1187
|
+
const overrides = studio ? { "appium:newCommandTimeout": STUDIO_CMD_TIMEOUT } : {};
|
|
1188
|
+
const capabilities = buildCapabilities(device, resolvedApp, kind, overrides, platform);
|
|
1138
1189
|
const driver = new AppiumDriver({
|
|
1139
1190
|
capabilities,
|
|
1140
1191
|
connection: { protocol: "http", hostname: host, port, path: "/" }
|
|
@@ -1296,4 +1347,12 @@ async function shutdown() {
|
|
|
1296
1347
|
}
|
|
1297
1348
|
process.on("SIGINT", shutdown);
|
|
1298
1349
|
process.on("SIGTERM", shutdown);
|
|
1350
|
+
if (!args.skipCheck) {
|
|
1351
|
+
const { criticalMissing } = reportPreflight(await preflight());
|
|
1352
|
+
if (criticalMissing) {
|
|
1353
|
+
console.error("\n\u2716 Fix the required tools above, then re-run. (bypass with --skip-check)\n");
|
|
1354
|
+
process.exit(1);
|
|
1355
|
+
}
|
|
1356
|
+
console.log("");
|
|
1357
|
+
}
|
|
1299
1358
|
connect();
|