@8bitbish/screenshot-service 1.0.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/README.md +142 -0
- package/bin/setup.js +307 -0
- package/dist/android-device.d.ts +10 -0
- package/dist/android-device.d.ts.map +1 -0
- package/dist/android-device.js +161 -0
- package/dist/android-device.js.map +1 -0
- package/dist/device.d.ts +18 -0
- package/dist/device.d.ts.map +1 -0
- package/dist/device.js +77 -0
- package/dist/device.js.map +1 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +340 -0
- package/dist/index.js.map +1 -0
- package/dist/location.d.ts +9 -0
- package/dist/location.d.ts.map +1 -0
- package/dist/location.js +68 -0
- package/dist/location.js.map +1 -0
- package/package.json +30 -0
package/dist/device.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDeviceInfo = getDeviceInfo;
|
|
4
|
+
exports.getForegroundApp = getForegroundApp;
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const util_1 = require("util");
|
|
7
|
+
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
8
|
+
const PMD3 = ["-m", "pymobiledevice3"];
|
|
9
|
+
const MODEL_NAMES = {
|
|
10
|
+
"iPhone12,1": "iPhone 11",
|
|
11
|
+
"iPhone12,3": "iPhone 11 Pro",
|
|
12
|
+
"iPhone12,5": "iPhone 11 Pro Max",
|
|
13
|
+
"iPhone12,8": "iPhone SE (2nd gen)",
|
|
14
|
+
"iPhone13,1": "iPhone 12 mini",
|
|
15
|
+
"iPhone13,2": "iPhone 12",
|
|
16
|
+
"iPhone13,3": "iPhone 12 Pro",
|
|
17
|
+
"iPhone13,4": "iPhone 12 Pro Max",
|
|
18
|
+
"iPhone14,2": "iPhone 13 Pro",
|
|
19
|
+
"iPhone14,3": "iPhone 13 Pro Max",
|
|
20
|
+
"iPhone14,4": "iPhone 13 mini",
|
|
21
|
+
"iPhone14,5": "iPhone 13",
|
|
22
|
+
"iPhone14,6": "iPhone SE (3rd gen)",
|
|
23
|
+
"iPhone14,7": "iPhone 14",
|
|
24
|
+
"iPhone14,8": "iPhone 14 Plus",
|
|
25
|
+
"iPhone15,2": "iPhone 14 Pro",
|
|
26
|
+
"iPhone15,3": "iPhone 14 Pro Max",
|
|
27
|
+
"iPhone15,4": "iPhone 15",
|
|
28
|
+
"iPhone15,5": "iPhone 15 Plus",
|
|
29
|
+
"iPhone16,1": "iPhone 15 Pro",
|
|
30
|
+
"iPhone16,2": "iPhone 15 Pro Max",
|
|
31
|
+
"iPhone16,3": "iPhone 16e",
|
|
32
|
+
"iPhone17,1": "iPhone 16 Pro",
|
|
33
|
+
"iPhone17,2": "iPhone 16 Pro Max",
|
|
34
|
+
"iPhone17,3": "iPhone 16",
|
|
35
|
+
"iPhone17,4": "iPhone 16 Plus",
|
|
36
|
+
};
|
|
37
|
+
async function getDeviceInfo(python) {
|
|
38
|
+
const { stdout } = await execFileAsync(python, [...PMD3, "usbmux", "list"], { timeout: 5000 });
|
|
39
|
+
const devices = JSON.parse(stdout);
|
|
40
|
+
if (!devices.length)
|
|
41
|
+
throw new Error("No iPhone found. Is it plugged in or on the same WiFi?");
|
|
42
|
+
const d = devices[0];
|
|
43
|
+
return {
|
|
44
|
+
model: d.ProductType,
|
|
45
|
+
name: MODEL_NAMES[d.ProductType] ?? d.ProductType,
|
|
46
|
+
iosVersion: d.ProductVersion,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Returns the foreground app at time of call.
|
|
51
|
+
* Uses foregroundRunning flag from proclist; cross-references applist for version.
|
|
52
|
+
* Returns null if detection fails — this is best-effort.
|
|
53
|
+
*/
|
|
54
|
+
async function getForegroundApp(python) {
|
|
55
|
+
try {
|
|
56
|
+
const { stdout } = await execFileAsync(python, [...PMD3, "developer", "dvt", "proclist"], { timeout: 10000 });
|
|
57
|
+
const procs = JSON.parse(stdout);
|
|
58
|
+
const fg = procs.find(p => p["foregroundRunning"] && p["isApplication"]);
|
|
59
|
+
if (!fg)
|
|
60
|
+
return null;
|
|
61
|
+
const bundleId = String(fg["bundleIdentifier"] ?? "");
|
|
62
|
+
const name = String(fg["displayLocalizedAppName"] ?? fg["name"] ?? bundleId);
|
|
63
|
+
if (!bundleId)
|
|
64
|
+
return null;
|
|
65
|
+
// apps query gives CFBundleShortVersionString + CFBundleVersion for this one app
|
|
66
|
+
const { stdout: qOut } = await execFileAsync(python, [...PMD3, "apps", "query", bundleId], { timeout: 8000 });
|
|
67
|
+
const meta = JSON.parse(qOut)?.[bundleId] ?? {};
|
|
68
|
+
const short = meta["CFBundleShortVersionString"] ?? null;
|
|
69
|
+
const build = meta["CFBundleVersion"] ?? null;
|
|
70
|
+
const version = short && build ? `${short} (${build})` : short ?? build ?? null;
|
|
71
|
+
return { bundleId, name, version };
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=device.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device.js","sourceRoot":"","sources":["../device.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { DeviceInfo, ForegroundApp } from "./device";
|
|
2
|
+
import { AndroidDeviceInfo } from "./android-device";
|
|
3
|
+
import { Location } from "./location";
|
|
4
|
+
export type { DeviceInfo, ForegroundApp, Location, AndroidDeviceInfo };
|
|
5
|
+
export declare function isTunnelRunning(): boolean;
|
|
6
|
+
export declare function startTunnel(): Promise<void>;
|
|
7
|
+
/** Manually stop the tunnel. */
|
|
8
|
+
export declare function stopTunnel(): void;
|
|
9
|
+
export interface AndroidScreenshotResult {
|
|
10
|
+
/** PNG image as a Buffer */
|
|
11
|
+
image: Buffer;
|
|
12
|
+
/** Device metadata */
|
|
13
|
+
device: AndroidDeviceInfo;
|
|
14
|
+
/** Foreground app at time of capture (null if detection failed) */
|
|
15
|
+
foregroundApp: ForegroundApp | null;
|
|
16
|
+
/** When the screenshot was taken */
|
|
17
|
+
capturedAt: Date;
|
|
18
|
+
/** Approximate location via IP geolocation (null if includeLocation is false or lookup failed) */
|
|
19
|
+
location: Location | null;
|
|
20
|
+
}
|
|
21
|
+
export interface ScreenshotResult {
|
|
22
|
+
/** PNG image as a Buffer */
|
|
23
|
+
image: Buffer;
|
|
24
|
+
/** Device metadata */
|
|
25
|
+
device: DeviceInfo;
|
|
26
|
+
/** Foreground app at time of capture (null if detection failed) */
|
|
27
|
+
foregroundApp: ForegroundApp | null;
|
|
28
|
+
/** When the screenshot was taken */
|
|
29
|
+
capturedAt: Date;
|
|
30
|
+
/** Approximate location via IP geolocation (null if includeLocation is false or lookup failed) */
|
|
31
|
+
location: Location | null;
|
|
32
|
+
}
|
|
33
|
+
export declare function triggerPhoneScreenshot(options?: {
|
|
34
|
+
/** Max ms to wait for the screenshot. Default: 30000 */
|
|
35
|
+
timeout?: number;
|
|
36
|
+
/** Include approximate location via IP geolocation. Default: false */
|
|
37
|
+
includeLocation?: boolean;
|
|
38
|
+
}): Promise<ScreenshotResult>;
|
|
39
|
+
export declare function triggerAndroidScreenshot(options?: {
|
|
40
|
+
/** Max ms to wait for the screenshot. Default: 30000 */
|
|
41
|
+
timeout?: number;
|
|
42
|
+
/** Include approximate location via IP geolocation. Default: false */
|
|
43
|
+
includeLocation?: boolean;
|
|
44
|
+
}): Promise<AndroidScreenshotResult>;
|
|
45
|
+
export interface PhoneRecordingResult {
|
|
46
|
+
video: Buffer;
|
|
47
|
+
device: DeviceInfo;
|
|
48
|
+
foregroundApp: ForegroundApp | null;
|
|
49
|
+
capturedAt: Date;
|
|
50
|
+
location: Location | null;
|
|
51
|
+
}
|
|
52
|
+
export interface AndroidRecordingResult {
|
|
53
|
+
video: Buffer;
|
|
54
|
+
device: AndroidDeviceInfo;
|
|
55
|
+
foregroundApp: ForegroundApp | null;
|
|
56
|
+
capturedAt: Date;
|
|
57
|
+
location: Location | null;
|
|
58
|
+
}
|
|
59
|
+
export declare function fetchLatestPhoneRecording(options?: {
|
|
60
|
+
waitForNew?: boolean;
|
|
61
|
+
waitTimeout?: number;
|
|
62
|
+
timeout?: number;
|
|
63
|
+
includeLocation?: boolean;
|
|
64
|
+
}): Promise<PhoneRecordingResult>;
|
|
65
|
+
export declare function fetchLatestAndroidRecording(options?: {
|
|
66
|
+
waitForNew?: boolean;
|
|
67
|
+
waitTimeout?: number;
|
|
68
|
+
timeout?: number;
|
|
69
|
+
includeLocation?: boolean;
|
|
70
|
+
}): Promise<AndroidRecordingResult>;
|
|
71
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAmC,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACtF,OAAO,EAAiD,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAe,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnD,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC;AAkCvE,wBAAgB,eAAe,IAAI,OAAO,CAOzC;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAqBjD;AAED,gCAAgC;AAChC,wBAAgB,UAAU,IAAI,IAAI,CAMjC;AAgFD,MAAM,WAAW,uBAAuB;IACtC,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,sBAAsB;IACtB,MAAM,EAAE,iBAAiB,CAAA;IACzB,mEAAmE;IACnE,aAAa,EAAE,aAAa,GAAG,IAAI,CAAA;IACnC,oCAAoC;IACpC,UAAU,EAAE,IAAI,CAAA;IAChB,kGAAkG;IAClG,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,sBAAsB;IACtB,MAAM,EAAE,UAAU,CAAA;IAClB,mEAAmE;IACnE,aAAa,EAAE,aAAa,GAAG,IAAI,CAAA;IACnC,oCAAoC;IACpC,UAAU,EAAE,IAAI,CAAA;IAChB,kGAAkG;IAClG,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;CAC1B;AAID,wBAAsB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IACrD,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2C5B;AAID,wBAAsB,wBAAwB,CAAC,OAAO,CAAC,EAAE;IACvD,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA0BnC;AAID,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,UAAU,CAAA;IAClB,aAAa,EAAE,aAAa,GAAG,IAAI,CAAA;IACnC,UAAU,EAAE,IAAI,CAAA;IAChB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,iBAAiB,CAAA;IACzB,aAAa,EAAE,aAAa,GAAG,IAAI,CAAA;IACnC,UAAU,EAAE,IAAI,CAAA;IAChB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;CAC1B;AAcD,wBAAsB,yBAAyB,CAAC,OAAO,CAAC,EAAE;IACxD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAkDhC;AAmCD,wBAAsB,2BAA2B,CAAC,OAAO,CAAC,EAAE;IAC1D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA+ClC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isTunnelRunning = isTunnelRunning;
|
|
4
|
+
exports.startTunnel = startTunnel;
|
|
5
|
+
exports.stopTunnel = stopTunnel;
|
|
6
|
+
exports.triggerPhoneScreenshot = triggerPhoneScreenshot;
|
|
7
|
+
exports.triggerAndroidScreenshot = triggerAndroidScreenshot;
|
|
8
|
+
exports.fetchLatestPhoneRecording = fetchLatestPhoneRecording;
|
|
9
|
+
exports.fetchLatestAndroidRecording = fetchLatestAndroidRecording;
|
|
10
|
+
const child_process_1 = require("child_process");
|
|
11
|
+
const util_1 = require("util");
|
|
12
|
+
const promises_1 = require("fs/promises");
|
|
13
|
+
const fs_1 = require("fs");
|
|
14
|
+
const path_1 = require("path");
|
|
15
|
+
const os_1 = require("os");
|
|
16
|
+
const device_1 = require("./device");
|
|
17
|
+
const android_device_1 = require("./android-device");
|
|
18
|
+
const location_1 = require("./location");
|
|
19
|
+
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
20
|
+
const PMD3 = ["-m", "pymobiledevice3"];
|
|
21
|
+
// ── Python detection ──────────────────────────────────────────────────────────
|
|
22
|
+
function findPython() {
|
|
23
|
+
// pymobiledevice3 requires Python 3.11+. Prefer newer versions, then fall back to PATH `python3`.
|
|
24
|
+
const candidates = [
|
|
25
|
+
"/opt/homebrew/bin/python3.14",
|
|
26
|
+
"/opt/homebrew/bin/python3.13",
|
|
27
|
+
"/opt/homebrew/bin/python3.12",
|
|
28
|
+
"/opt/homebrew/bin/python3.11",
|
|
29
|
+
"/usr/local/bin/python3.14",
|
|
30
|
+
"/usr/local/bin/python3.13",
|
|
31
|
+
"/usr/local/bin/python3.12",
|
|
32
|
+
"/usr/local/bin/python3.11",
|
|
33
|
+
"python3",
|
|
34
|
+
];
|
|
35
|
+
const probe = "import sys, pymobiledevice3; sys.exit(0 if sys.version_info >= (3, 11) else 1)";
|
|
36
|
+
for (const p of candidates) {
|
|
37
|
+
try {
|
|
38
|
+
(0, child_process_1.execFileSync)(p, ["-c", probe], { stdio: "ignore" });
|
|
39
|
+
return p;
|
|
40
|
+
}
|
|
41
|
+
catch { }
|
|
42
|
+
}
|
|
43
|
+
throw new Error("Python 3.11+ with pymobiledevice3 not found. Run: npx @8bitbish/screenshot-service setup-ios");
|
|
44
|
+
}
|
|
45
|
+
// ── Tunnel management ─────────────────────────────────────────────────────────
|
|
46
|
+
function isTunnelRunning() {
|
|
47
|
+
try {
|
|
48
|
+
(0, child_process_1.execFileSync)("pgrep", ["-f", "pymobiledevice3 remote tunneld"], { stdio: "ignore" });
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function startTunnel() {
|
|
56
|
+
if (isTunnelRunning())
|
|
57
|
+
return;
|
|
58
|
+
const python = findPython();
|
|
59
|
+
const log = (0, fs_1.createWriteStream)((0, path_1.join)((0, os_1.homedir)(), ".tunneld.log"), { flags: "a" });
|
|
60
|
+
const child = (0, child_process_1.spawn)("sudo", [python, ...PMD3, "remote", "tunneld"], {
|
|
61
|
+
detached: true,
|
|
62
|
+
stdio: ["ignore", log, log],
|
|
63
|
+
});
|
|
64
|
+
child.unref();
|
|
65
|
+
// Poll until the process is confirmed running (typically < 1s)
|
|
66
|
+
const deadline = Date.now() + 10000;
|
|
67
|
+
while (Date.now() < deadline) {
|
|
68
|
+
if (isTunnelRunning()) {
|
|
69
|
+
registerExitHandler();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
73
|
+
}
|
|
74
|
+
throw new Error("Tunnel did not start within 10s. Check ~/.tunneld.log");
|
|
75
|
+
}
|
|
76
|
+
/** Manually stop the tunnel. */
|
|
77
|
+
function stopTunnel() {
|
|
78
|
+
try {
|
|
79
|
+
(0, child_process_1.execFileSync)("pkill", ["-f", "pymobiledevice3 remote tunneld"], { stdio: "ignore" });
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// already stopped
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
let exitHandlerRegistered = false;
|
|
86
|
+
function registerExitHandler() {
|
|
87
|
+
if (exitHandlerRegistered)
|
|
88
|
+
return;
|
|
89
|
+
exitHandlerRegistered = true;
|
|
90
|
+
const stop = () => stopTunnel();
|
|
91
|
+
process.on("exit", stop);
|
|
92
|
+
process.on("SIGINT", () => { stop(); process.exit(0); });
|
|
93
|
+
process.on("SIGTERM", () => { stop(); process.exit(0); });
|
|
94
|
+
}
|
|
95
|
+
// ── ADB detection & auto-reconnect ───────────────────────────────────────────
|
|
96
|
+
const ANDROID_IP_FILE = (0, path_1.join)((0, os_1.homedir)(), ".screenshotAssistent-android-ip");
|
|
97
|
+
function findAdb() {
|
|
98
|
+
for (const p of ["/opt/homebrew/bin/adb", "/usr/local/bin/adb", "adb"]) {
|
|
99
|
+
try {
|
|
100
|
+
(0, child_process_1.execFileSync)(p, ["version"], { stdio: "ignore" });
|
|
101
|
+
return p;
|
|
102
|
+
}
|
|
103
|
+
catch { }
|
|
104
|
+
}
|
|
105
|
+
throw new Error("adb not found. Run: npx @8bitbish/screenshot-service setup-android");
|
|
106
|
+
}
|
|
107
|
+
function getConnectedAdbLines(adb) {
|
|
108
|
+
try {
|
|
109
|
+
const stdout = (0, child_process_1.execFileSync)(adb, ["devices"], { encoding: "utf8", timeout: 5000 });
|
|
110
|
+
return stdout.split("\n").slice(1).filter((l) => l.includes("\tdevice"));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function saveAndroidIp(lines) {
|
|
117
|
+
// Wireless devices appear as "192.168.x.x:5555 device"
|
|
118
|
+
const wireless = lines.find((l) => /^\d+\.\d+\.\d+\.\d+:\d+/.test(l.trim()));
|
|
119
|
+
if (wireless) {
|
|
120
|
+
try {
|
|
121
|
+
(0, fs_1.writeFileSync)(ANDROID_IP_FILE, wireless.trim().split(/\s/)[0], "utf8");
|
|
122
|
+
}
|
|
123
|
+
catch { }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function ensureAndroidDevice(adb) {
|
|
127
|
+
let lines = getConnectedAdbLines(adb);
|
|
128
|
+
if (lines.length) {
|
|
129
|
+
saveAndroidIp(lines);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// No device — try reconnecting to the last known wireless IP
|
|
133
|
+
let saved = "";
|
|
134
|
+
try {
|
|
135
|
+
saved = (0, fs_1.readFileSync)(ANDROID_IP_FILE, "utf8").trim();
|
|
136
|
+
}
|
|
137
|
+
catch { }
|
|
138
|
+
if (saved) {
|
|
139
|
+
try {
|
|
140
|
+
await execFileAsync(adb, ["connect", saved], { timeout: 5000 });
|
|
141
|
+
}
|
|
142
|
+
catch { }
|
|
143
|
+
lines = getConnectedAdbLines(adb);
|
|
144
|
+
if (lines.length) {
|
|
145
|
+
saveAndroidIp(lines);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
throw new Error("No Android device found.\n" +
|
|
150
|
+
"If using wireless: open Settings → Developer Options → Wireless Debugging on your phone and make sure it is ON.\n" +
|
|
151
|
+
"Then run: npx @8bitbish/screenshot-service setup-android");
|
|
152
|
+
}
|
|
153
|
+
// ── Screenshot ────────────────────────────────────────────────────────────────
|
|
154
|
+
async function triggerPhoneScreenshot(options) {
|
|
155
|
+
const timeout = options?.timeout ?? 30000;
|
|
156
|
+
const includeLocation = options?.includeLocation ?? false;
|
|
157
|
+
const python = findPython();
|
|
158
|
+
// Start tunnel on first call — stays alive for the session
|
|
159
|
+
await startTunnel();
|
|
160
|
+
// Mount developer image (instant no-op if already mounted)
|
|
161
|
+
await execFileAsync(python, [...PMD3, "mounter", "auto-mount"], { timeout }).catch(() => { });
|
|
162
|
+
// Kick off non-DVT metadata fetches in parallel with the screenshot
|
|
163
|
+
const deviceInfoPromise = (0, device_1.getDeviceInfo)(python);
|
|
164
|
+
const locationPromise = includeLocation ? (0, location_1.getLocation)() : Promise.resolve(null);
|
|
165
|
+
// Retry screenshot until tunnel has connected to device (typically 1–3 retries)
|
|
166
|
+
const outPath = (0, path_1.join)((0, os_1.tmpdir)(), `iphone-screenshot-${Date.now()}.png`);
|
|
167
|
+
const maxAttempts = 12;
|
|
168
|
+
try {
|
|
169
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
170
|
+
try {
|
|
171
|
+
await execFileAsync(python, [...PMD3, "developer", "dvt", "screenshot", outPath], { timeout });
|
|
172
|
+
if ((0, fs_1.existsSync)(outPath))
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
catch { }
|
|
176
|
+
if (i === maxAttempts - 1) {
|
|
177
|
+
throw new Error("Screenshot failed — is the iPhone unlocked and connected?");
|
|
178
|
+
}
|
|
179
|
+
await new Promise((r) => setTimeout(r, 800));
|
|
180
|
+
}
|
|
181
|
+
// getForegroundApp uses dvt proclist — run after screenshot to avoid DVT session contention
|
|
182
|
+
const [image, device, foregroundApp, location] = await Promise.all([
|
|
183
|
+
(0, promises_1.readFile)(outPath),
|
|
184
|
+
deviceInfoPromise,
|
|
185
|
+
(0, device_1.getForegroundApp)(python),
|
|
186
|
+
locationPromise,
|
|
187
|
+
]);
|
|
188
|
+
return { image, device, foregroundApp, capturedAt: new Date(), location };
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
await (0, promises_1.unlink)(outPath).catch(() => { });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// ── Android Screenshot ────────────────────────────────────────────────────────
|
|
195
|
+
async function triggerAndroidScreenshot(options) {
|
|
196
|
+
const timeout = options?.timeout ?? 30000;
|
|
197
|
+
const includeLocation = options?.includeLocation ?? false;
|
|
198
|
+
const adb = findAdb();
|
|
199
|
+
// Verify a device is reachable (auto-reconnects to last known wireless IP if needed)
|
|
200
|
+
await ensureAndroidDevice(adb);
|
|
201
|
+
// Non-screenshot metadata can run in parallel
|
|
202
|
+
const deviceInfoPromise = (0, android_device_1.getAndroidDeviceInfo)(adb);
|
|
203
|
+
const locationPromise = includeLocation ? (0, location_1.getLocation)() : Promise.resolve(null);
|
|
204
|
+
// Capture screenshot — adb exec-out returns raw PNG bytes directly
|
|
205
|
+
const { stdout: image } = await execFileAsync(adb, ["exec-out", "screencap", "-p"], { timeout, encoding: "buffer", maxBuffer: 50 * 1024 * 1024 });
|
|
206
|
+
// Run foreground app detection after screenshot (avoids any command contention)
|
|
207
|
+
const [device, foregroundApp, location] = await Promise.all([
|
|
208
|
+
deviceInfoPromise,
|
|
209
|
+
(0, android_device_1.getAndroidForegroundApp)(adb),
|
|
210
|
+
locationPromise,
|
|
211
|
+
]);
|
|
212
|
+
return { image, device, foregroundApp, capturedAt: new Date(), location };
|
|
213
|
+
}
|
|
214
|
+
// ── iOS recording fetch ───────────────────────────────────────────────────────
|
|
215
|
+
async function listDcim(python) {
|
|
216
|
+
const { stdout } = await execFileAsync(python, [...PMD3, "afc", "ls", "/DCIM/100APPLE"], { timeout: 10000 });
|
|
217
|
+
return stdout.split("\n")
|
|
218
|
+
.map((l) => l.trim())
|
|
219
|
+
.filter((l) => /\.(mov|mp4|MOV|MP4)$/.test(l));
|
|
220
|
+
}
|
|
221
|
+
async function fetchLatestPhoneRecording(options) {
|
|
222
|
+
const waitForNew = options?.waitForNew ?? false;
|
|
223
|
+
const waitTimeout = options?.waitTimeout ?? 300000;
|
|
224
|
+
const timeout = options?.timeout ?? 60000;
|
|
225
|
+
const includeLocation = options?.includeLocation ?? false;
|
|
226
|
+
const python = findPython();
|
|
227
|
+
await startTunnel();
|
|
228
|
+
const deviceInfoPromise = (0, device_1.getDeviceInfo)(python);
|
|
229
|
+
const locationPromise = includeLocation ? (0, location_1.getLocation)() : Promise.resolve(null);
|
|
230
|
+
let targetFile;
|
|
231
|
+
if (waitForNew) {
|
|
232
|
+
const snapshot = new Set(await listDcim(python));
|
|
233
|
+
const deadline = Date.now() + waitTimeout;
|
|
234
|
+
let found;
|
|
235
|
+
while (Date.now() < deadline) {
|
|
236
|
+
const current = await listDcim(python);
|
|
237
|
+
found = current.find(f => !snapshot.has(f));
|
|
238
|
+
if (found)
|
|
239
|
+
break;
|
|
240
|
+
await new Promise(r => setTimeout(r, 500));
|
|
241
|
+
}
|
|
242
|
+
if (!found)
|
|
243
|
+
throw new Error(`No new recording appeared within ${Math.round(waitTimeout / 1000)}s`);
|
|
244
|
+
targetFile = found;
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
const files = await listDcim(python);
|
|
248
|
+
if (!files.length)
|
|
249
|
+
throw new Error("No video files found in DCIM/100APPLE on the device");
|
|
250
|
+
targetFile = files.sort()[files.length - 1];
|
|
251
|
+
}
|
|
252
|
+
const tmpPath = (0, path_1.join)((0, os_1.tmpdir)(), `iphone-recording-${Date.now()}.mov`);
|
|
253
|
+
try {
|
|
254
|
+
await execFileAsync(python, [...PMD3, "afc", "pull", "-i", targetFile, tmpPath], { timeout });
|
|
255
|
+
const [video, device, foregroundApp, location] = await Promise.all([
|
|
256
|
+
(0, promises_1.readFile)(tmpPath),
|
|
257
|
+
deviceInfoPromise,
|
|
258
|
+
(0, device_1.getForegroundApp)(python),
|
|
259
|
+
locationPromise,
|
|
260
|
+
]);
|
|
261
|
+
return { video, device, foregroundApp, capturedAt: new Date(), location };
|
|
262
|
+
}
|
|
263
|
+
finally {
|
|
264
|
+
await (0, promises_1.unlink)(tmpPath).catch(() => { });
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// ── Android recording fetch ───────────────────────────────────────────────────
|
|
268
|
+
async function queryLatestAndroidVideo(adb) {
|
|
269
|
+
const { stdout } = await execFileAsync(adb, ["shell", "content", "query",
|
|
270
|
+
"--uri", "content://media/external/video/media",
|
|
271
|
+
"--projection", "_id:_data:date_modified"], { timeout: 8000, maxBuffer: 5 * 1024 * 1024 });
|
|
272
|
+
// Each row: "Row: N _id=X, _data=/path/to/file.mp4, date_modified=Y"
|
|
273
|
+
const rows = stdout.split("\n").filter((l) => l.trim().startsWith("Row:"));
|
|
274
|
+
if (!rows.length)
|
|
275
|
+
return null;
|
|
276
|
+
let bestId = "";
|
|
277
|
+
let bestPath = "";
|
|
278
|
+
let bestTs = -1;
|
|
279
|
+
for (const row of rows) {
|
|
280
|
+
const id = row.match(/_id=(\d+)/)?.[1];
|
|
281
|
+
const path = row.match(/_data=([^,\n]+)/)?.[1]?.trim();
|
|
282
|
+
const tsStr = row.match(/date_modified=(\d+)/)?.[1];
|
|
283
|
+
const ts = tsStr ? parseInt(tsStr, 10) : -1;
|
|
284
|
+
if (id && path && ts > bestTs) {
|
|
285
|
+
bestId = id;
|
|
286
|
+
bestPath = path;
|
|
287
|
+
bestTs = ts;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return bestId ? { id: bestId, path: bestPath } : null;
|
|
291
|
+
}
|
|
292
|
+
async function fetchLatestAndroidRecording(options) {
|
|
293
|
+
const waitForNew = options?.waitForNew ?? false;
|
|
294
|
+
const waitTimeout = options?.waitTimeout ?? 300000;
|
|
295
|
+
const timeout = options?.timeout ?? 60000;
|
|
296
|
+
const includeLocation = options?.includeLocation ?? false;
|
|
297
|
+
const adb = findAdb();
|
|
298
|
+
await ensureAndroidDevice(adb);
|
|
299
|
+
const deviceInfoPromise = (0, android_device_1.getAndroidDeviceInfo)(adb);
|
|
300
|
+
const locationPromise = includeLocation ? (0, location_1.getLocation)() : Promise.resolve(null);
|
|
301
|
+
let devicePath;
|
|
302
|
+
if (waitForNew) {
|
|
303
|
+
const snapshot = await queryLatestAndroidVideo(adb);
|
|
304
|
+
const snapshotId = snapshot?.id ?? null;
|
|
305
|
+
const deadline = Date.now() + waitTimeout;
|
|
306
|
+
let found;
|
|
307
|
+
while (Date.now() < deadline) {
|
|
308
|
+
const latest = await queryLatestAndroidVideo(adb);
|
|
309
|
+
if (latest && latest.id !== snapshotId) {
|
|
310
|
+
found = latest.path;
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
await new Promise(r => setTimeout(r, 500));
|
|
314
|
+
}
|
|
315
|
+
if (!found)
|
|
316
|
+
throw new Error(`No new recording appeared within ${Math.round(waitTimeout / 1000)}s`);
|
|
317
|
+
devicePath = found;
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
const latest = await queryLatestAndroidVideo(adb);
|
|
321
|
+
if (!latest)
|
|
322
|
+
throw new Error("No video files found on the Android device");
|
|
323
|
+
devicePath = latest.path;
|
|
324
|
+
}
|
|
325
|
+
const tmpPath = (0, path_1.join)((0, os_1.tmpdir)(), `android-recording-${Date.now()}.mp4`);
|
|
326
|
+
try {
|
|
327
|
+
await execFileAsync(adb, ["pull", devicePath, tmpPath], { timeout });
|
|
328
|
+
const [video, device, foregroundApp, location] = await Promise.all([
|
|
329
|
+
(0, promises_1.readFile)(tmpPath),
|
|
330
|
+
deviceInfoPromise,
|
|
331
|
+
(0, android_device_1.getAndroidForegroundApp)(adb),
|
|
332
|
+
locationPromise,
|
|
333
|
+
]);
|
|
334
|
+
return { video, device, foregroundApp, capturedAt: new Date(), location };
|
|
335
|
+
}
|
|
336
|
+
finally {
|
|
337
|
+
await (0, promises_1.unlink)(tmpPath).catch(() => { });
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;AA4CA,0CAOC;AAED,kCAqBC;AAGD,gCAMC;AA4GD,wDAgDC;AAID,4DA+BC;AAgCD,8DAuDC;AAmCD,kEAoDC;AAhcD,iDAA8D;AAC9D,+BAAiC;AACjC,0CAA+C;AAC/C,2BAAgF;AAChF,+BAA4B;AAC5B,2BAAqC;AACrC,qCAAsF;AACtF,qDAAoG;AACpG,yCAAmD;AAInD,MAAM,aAAa,GAAG,IAAA,gBAAS,EAAC,wBAAQ,CAAC,CAAC;AAC1C,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;AAEvC,iFAAiF;AAEjF,SAAS,UAAU;IACjB,kGAAkG;IAClG,MAAM,UAAU,GAAG;QACjB,8BAA8B;QAC9B,8BAA8B;QAC9B,8BAA8B;QAC9B,8BAA8B;QAC9B,2BAA2B;QAC3B,2BAA2B;QAC3B,2BAA2B;QAC3B,2BAA2B;QAC3B,SAAS;KACV,CAAC;IACF,MAAM,KAAK,GAAG,gFAAgF,CAAC;IAC/F,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,IAAA,4BAAY,EAAC,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACpD,OAAO,CAAC,CAAC;QACX,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IACD,MAAM,IAAI,KAAK,CACb,8FAA8F,CAC/F,CAAC;AACJ,CAAC;AAED,iFAAiF;AAEjF,SAAgB,eAAe;IAC7B,IAAI,CAAC;QACH,IAAA,4BAAY,EAAC,OAAO,EAAE,CAAC,IAAI,EAAE,gCAAgC,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,WAAW;IAC/B,IAAI,eAAe,EAAE;QAAE,OAAO;IAE9B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,IAAA,sBAAiB,EAAC,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,cAAc,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/E,MAAM,KAAK,GAAG,IAAA,qBAAK,EAAC,MAAM,EAAE,CAAC,MAAM,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE;QAClE,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC;KAC5B,CAAC,CAAC;IACH,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,+DAA+D;IAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAM,CAAC;IACrC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,IAAI,eAAe,EAAE,EAAE,CAAC;YACtB,mBAAmB,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;AAC3E,CAAC;AAED,gCAAgC;AAChC,SAAgB,UAAU;IACxB,IAAI,CAAC;QACH,IAAA,4BAAY,EAAC,OAAO,EAAE,CAAC,IAAI,EAAE,gCAAgC,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvF,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;AACH,CAAC;AAED,IAAI,qBAAqB,GAAG,KAAK,CAAC;AAClC,SAAS,mBAAmB;IAC1B,IAAI,qBAAqB;QAAE,OAAO;IAClC,qBAAqB,GAAG,IAAI,CAAC;IAC7B,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAG,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,gFAAgF;AAEhF,MAAM,eAAe,GAAG,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,iCAAiC,CAAC,CAAC;AAE3E,SAAS,OAAO;IACd,KAAK,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC;QACvE,IAAI,CAAC;YACH,IAAA,4BAAY,EAAC,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAClD,OAAO,CAAC,CAAC;QACX,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IACD,MAAM,IAAI,KAAK,CACb,oEAAoE,CACrE,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,GAAW;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,4BAAY,EAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACnF,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,KAAe;IACpC,wDAAwD;IACxD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrF,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC;YACH,IAAA,kBAAa,EAAC,eAAe,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzE,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,GAAW;IAC5C,IAAI,KAAK,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,6DAA6D;IAC7D,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,CAAC;QACH,KAAK,GAAG,IAAA,iBAAY,EAAC,eAAe,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,KAAK,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CACb,4BAA4B;QAC5B,mHAAmH;QACnH,0DAA0D,CAC3D,CAAC;AACJ,CAAC;AA8BD,iFAAiF;AAE1E,KAAK,UAAU,sBAAsB,CAAC,OAK5C;IACC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,KAAM,CAAC;IAC3C,MAAM,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,KAAK,CAAC;IAC1D,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,2DAA2D;IAC3D,MAAM,WAAW,EAAE,CAAC;IAEpB,2DAA2D;IAC3D,MAAM,aAAa,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAE7F,oEAAoE;IACpE,MAAM,iBAAiB,GAAG,IAAA,sBAAa,EAAC,MAAM,CAAC,CAAC;IAChD,MAAM,eAAe,GAAK,eAAe,CAAC,CAAC,CAAC,IAAA,sBAAW,GAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAElF,gFAAgF;IAChF,MAAM,OAAO,GAAG,IAAA,WAAI,EAAC,IAAA,WAAM,GAAE,EAAE,qBAAqB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACtE,MAAM,WAAW,GAAG,EAAE,CAAC;IAEvB,IAAI,CAAC;QACH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,IAAI,CAAC;gBACH,MAAM,aAAa,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC/F,IAAI,IAAA,eAAU,EAAC,OAAO,CAAC;oBAAE,MAAM;YACjC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,IAAI,CAAC,KAAK,WAAW,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;YAC/E,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC/C,CAAC;QAED,4FAA4F;QAC5F,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACjE,IAAA,mBAAQ,EAAC,OAAO,CAAC;YACjB,iBAAiB;YACjB,IAAA,yBAAgB,EAAC,MAAM,CAAC;YACxB,eAAe;SAChB,CAAC,CAAC;QAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC;IAC5E,CAAC;YAAS,CAAC;QACT,MAAM,IAAA,iBAAM,EAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED,iFAAiF;AAE1E,KAAK,UAAU,wBAAwB,CAAC,OAK9C;IACC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,KAAM,CAAC;IAC3C,MAAM,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,KAAK,CAAC;IAC1D,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IAEtB,qFAAqF;IACrF,MAAM,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAE/B,8CAA8C;IAC9C,MAAM,iBAAiB,GAAG,IAAA,qCAAoB,EAAC,GAAG,CAAC,CAAC;IACpD,MAAM,eAAe,GAAK,eAAe,CAAC,CAAC,CAAC,IAAA,sBAAW,GAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAElF,mEAAmE;IACnE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,aAAa,CAC3C,GAAG,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,IAAI,CAAC,EACpC,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,CAC5B,CAAC;IAEnC,gFAAgF;IAChF,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1D,iBAAiB;QACjB,IAAA,wCAAuB,EAAC,GAAG,CAAC;QAC5B,eAAe;KAChB,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC;AAC5E,CAAC;AAoBD,iFAAiF;AAEjF,KAAK,UAAU,QAAQ,CAAC,MAAc;IACpC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,CAAC,EAChD,EAAE,OAAO,EAAE,KAAK,EAAE,CACnB,CAAC;IACF,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;SACtB,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAEM,KAAK,UAAU,yBAAyB,CAAC,OAK/C;IACC,MAAM,UAAU,GAAM,OAAO,EAAE,UAAU,IAAO,KAAK,CAAC;IACtD,MAAM,WAAW,GAAK,OAAO,EAAE,WAAW,IAAM,MAAO,CAAC;IACxD,MAAM,OAAO,GAAS,OAAO,EAAE,OAAO,IAAU,KAAM,CAAC;IACvD,MAAM,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,KAAK,CAAC;IAC1D,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,MAAM,WAAW,EAAE,CAAC;IAEpB,MAAM,iBAAiB,GAAG,IAAA,sBAAa,EAAC,MAAM,CAAC,CAAC;IAChD,MAAM,eAAe,GAAK,eAAe,CAAC,CAAC,CAAC,IAAA,sBAAW,GAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAElF,IAAI,UAAkB,CAAC;IAEvB,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC;QAC1C,IAAI,KAAyB,CAAC;QAC9B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;YACvC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5C,IAAI,KAAK;gBAAE,MAAM;YACjB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACnG,UAAU,GAAG,KAAK,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAC1F,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,OAAO,GAAG,IAAA,WAAI,EAAC,IAAA,WAAM,GAAE,EAAE,oBAAoB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACrE,IAAI,CAAC;QACH,MAAM,aAAa,CACjB,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAC3D,EAAE,OAAO,EAAE,CACZ,CAAC;QAEF,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACjE,IAAA,mBAAQ,EAAC,OAAO,CAAC;YACjB,iBAAiB;YACjB,IAAA,yBAAgB,EAAC,MAAM,CAAC;YACxB,eAAe;SAChB,CAAC,CAAC;QAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC;IAC5E,CAAC;YAAS,CAAC;QACT,MAAM,IAAA,iBAAM,EAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF,KAAK,UAAU,uBAAuB,CAAC,GAAW;IAChD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,GAAG,EACH,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO;QAC1B,OAAO,EAAE,sCAAsC;QAC/C,cAAc,EAAE,yBAAyB,CAAC,EAC5C,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,CAC9C,CAAC;IACF,qEAAqE;IACrE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IACnF,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAE9B,IAAI,MAAM,GAAK,EAAE,CAAC;IAClB,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,MAAM,GAAK,CAAC,CAAC,CAAC;IAElB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,EAAE,GAAK,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,EAAE,GAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;YAC9B,MAAM,GAAK,EAAE,CAAC;YACd,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM,GAAK,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC;AAEM,KAAK,UAAU,2BAA2B,CAAC,OAKjD;IACC,MAAM,UAAU,GAAM,OAAO,EAAE,UAAU,IAAO,KAAK,CAAC;IACtD,MAAM,WAAW,GAAK,OAAO,EAAE,WAAW,IAAM,MAAO,CAAC;IACxD,MAAM,OAAO,GAAS,OAAO,EAAE,OAAO,IAAU,KAAM,CAAC;IACvD,MAAM,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,KAAK,CAAC;IAC1D,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IAEtB,MAAM,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAM,iBAAiB,GAAG,IAAA,qCAAoB,EAAC,GAAG,CAAC,CAAC;IACpD,MAAM,eAAe,GAAK,eAAe,CAAC,CAAC,CAAC,IAAA,sBAAW,GAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAElF,IAAI,UAAkB,CAAC;IAEvB,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC,GAAG,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,QAAQ,EAAE,EAAE,IAAI,IAAI,CAAC;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC;QAC1C,IAAI,KAAyB,CAAC;QAC9B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,MAAM,IAAI,MAAM,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;gBAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;gBAAC,MAAM;YAAC,CAAC;YACvE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACnG,UAAU,GAAG,KAAK,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,GAAG,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC3E,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,MAAM,OAAO,GAAG,IAAA,WAAI,EAAC,IAAA,WAAM,GAAE,EAAE,qBAAqB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACtE,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAErE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACjE,IAAA,mBAAQ,EAAC,OAAO,CAAC;YACjB,iBAAiB;YACjB,IAAA,wCAAuB,EAAC,GAAG,CAAC;YAC5B,eAAe;SAChB,CAAC,CAAC;QAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC;IAC5E,CAAC;YAAS,CAAC;QACT,MAAM,IAAA,iBAAM,EAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../location.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,wBAAgB,WAAW,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA+BtD"}
|
package/dist/location.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getLocation = getLocation;
|
|
37
|
+
const http = __importStar(require("http"));
|
|
38
|
+
function getLocation() {
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
const req = http.get("http://ip-api.com/json/?fields=status,lat,lon,city,country", { timeout: 5000 }, (res) => {
|
|
41
|
+
let data = "";
|
|
42
|
+
res.on("data", (chunk) => (data += chunk));
|
|
43
|
+
res.on("end", () => {
|
|
44
|
+
try {
|
|
45
|
+
const json = JSON.parse(data);
|
|
46
|
+
if (json.status === "success") {
|
|
47
|
+
resolve({
|
|
48
|
+
latitude: json.lat,
|
|
49
|
+
longitude: json.lon,
|
|
50
|
+
city: json.city,
|
|
51
|
+
country: json.country,
|
|
52
|
+
source: "ip-geolocation",
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
resolve(null);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
resolve(null);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
req.on("error", () => resolve(null));
|
|
65
|
+
req.on("timeout", () => { req.destroy(); resolve(null); });
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=location.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"location.js","sourceRoot":"","sources":["../location.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,kCA+BC;AAzCD,2CAA6B;AAU7B,SAAgB,WAAW;IACzB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAClB,4DAA4D,EAC5D,EAAE,OAAO,EAAE,IAAI,EAAE,EACjB,CAAC,GAAG,EAAE,EAAE;YACN,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC;YAC3C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC9B,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;wBAC9B,OAAO,CAAC;4BACN,QAAQ,EAAG,IAAI,CAAC,GAAG;4BACnB,SAAS,EAAE,IAAI,CAAC,GAAG;4BACnB,IAAI,EAAO,IAAI,CAAC,IAAI;4BACpB,OAAO,EAAI,IAAI,CAAC,OAAO;4BACvB,MAAM,EAAK,gBAAgB;yBAC5B,CAAC,CAAC;oBACL,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,IAAI,CAAC,CAAC;oBAChB,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CACF,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACrC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@8bitbish/screenshot-service",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Take screenshots and fetch recordings from connected iPhone and Android devices",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"require": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"screenshot-service": "bin/setup.js"
|
|
15
|
+
},
|
|
16
|
+
"files": ["dist", "bin"],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"prepare": "npm run build",
|
|
23
|
+
"clean": "rm -rf dist"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^20.0.0",
|
|
27
|
+
"ts-node": "^10.9.0",
|
|
28
|
+
"typescript": "^5.4.0"
|
|
29
|
+
}
|
|
30
|
+
}
|