osx-query 0.1.2
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 +21 -0
- package/bin/osx.js +24 -0
- package/lib/install.js +118 -0
- package/lib/platform.js +21 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# osx-query
|
|
2
|
+
|
|
3
|
+
Install:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm i -g osx-query
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
This package downloads the signed and notarized native `osx` CLI from the matching GitHub release for your macOS architecture.
|
|
10
|
+
|
|
11
|
+
Example:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
osx query --app focused "AXWindow AXButton"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Supported platforms:
|
|
18
|
+
|
|
19
|
+
- macOS `arm64`
|
|
20
|
+
- macOS `x64`
|
|
21
|
+
|
package/bin/osx.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const path = require("node:path");
|
|
5
|
+
const { spawnSync } = require("node:child_process");
|
|
6
|
+
|
|
7
|
+
const binaryPath = path.join(__dirname, "..", "lib", "vendor", "osx");
|
|
8
|
+
|
|
9
|
+
if (!fs.existsSync(binaryPath)) {
|
|
10
|
+
console.error("osx-query is not installed correctly: native binary is missing");
|
|
11
|
+
console.error("Try reinstalling: npm i -g osx-query");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const result = spawnSync(binaryPath, process.argv.slice(2), {
|
|
16
|
+
stdio: "inherit",
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
if (result.error) {
|
|
20
|
+
console.error(result.error.message);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
process.exit(result.status === null ? 1 : result.status);
|
package/lib/install.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const os = require("node:os");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
const https = require("node:https");
|
|
7
|
+
const { pipeline } = require("node:stream/promises");
|
|
8
|
+
const { createWriteStream } = require("node:fs");
|
|
9
|
+
const { spawnSync } = require("node:child_process");
|
|
10
|
+
|
|
11
|
+
const pkg = require("../package.json");
|
|
12
|
+
const { getAssetName } = require("./platform");
|
|
13
|
+
|
|
14
|
+
async function download(url, destination) {
|
|
15
|
+
await new Promise((resolve, reject) => {
|
|
16
|
+
const request = https.get(
|
|
17
|
+
url,
|
|
18
|
+
{
|
|
19
|
+
headers: {
|
|
20
|
+
"User-Agent": "osx-query-installer",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
async (response) => {
|
|
24
|
+
if (
|
|
25
|
+
response.statusCode &&
|
|
26
|
+
response.statusCode >= 300 &&
|
|
27
|
+
response.statusCode < 400 &&
|
|
28
|
+
response.headers.location
|
|
29
|
+
) {
|
|
30
|
+
response.resume();
|
|
31
|
+
try {
|
|
32
|
+
await download(response.headers.location, destination);
|
|
33
|
+
resolve();
|
|
34
|
+
} catch (error) {
|
|
35
|
+
reject(error);
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (response.statusCode !== 200) {
|
|
41
|
+
reject(
|
|
42
|
+
new Error(
|
|
43
|
+
`Failed to download ${url} (status ${response.statusCode || "unknown"})`
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
await pipeline(response, createWriteStream(destination));
|
|
51
|
+
resolve();
|
|
52
|
+
} catch (error) {
|
|
53
|
+
reject(error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
request.on("error", reject);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function extract(zipPath, outputDir) {
|
|
63
|
+
const result = spawnSync("ditto", ["-x", "-k", zipPath, outputDir], {
|
|
64
|
+
stdio: "inherit",
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (result.status !== 0) {
|
|
68
|
+
throw new Error("Failed to extract release archive");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function installBinary(extractedRoot, vendorDir) {
|
|
73
|
+
const entries = fs.readdirSync(extractedRoot, { withFileTypes: true });
|
|
74
|
+
const packageDir = entries.find((entry) => entry.isDirectory());
|
|
75
|
+
|
|
76
|
+
if (!packageDir) {
|
|
77
|
+
throw new Error("Release archive did not contain the expected directory");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const sourceBinary = path.join(extractedRoot, packageDir.name, "osx");
|
|
81
|
+
const targetBinary = path.join(vendorDir, "osx");
|
|
82
|
+
|
|
83
|
+
if (!fs.existsSync(sourceBinary)) {
|
|
84
|
+
throw new Error("Release archive did not contain the osx binary");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
fs.mkdirSync(vendorDir, { recursive: true });
|
|
88
|
+
fs.copyFileSync(sourceBinary, targetBinary);
|
|
89
|
+
fs.chmodSync(targetBinary, 0o755);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function main() {
|
|
93
|
+
const version = pkg.version;
|
|
94
|
+
const assetName = getAssetName(version);
|
|
95
|
+
const url = `https://github.com/Moulik-Budhiraja/OSX-Query/releases/download/v${version}/${assetName}`;
|
|
96
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "osx-query-"));
|
|
97
|
+
const zipPath = path.join(tempDir, assetName);
|
|
98
|
+
const extractDir = path.join(tempDir, "extract");
|
|
99
|
+
const vendorDir = path.join(__dirname, "vendor");
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
console.log(`Downloading ${assetName}`);
|
|
103
|
+
await download(url, zipPath);
|
|
104
|
+
|
|
105
|
+
fs.rmSync(vendorDir, { recursive: true, force: true });
|
|
106
|
+
fs.mkdirSync(extractDir, { recursive: true });
|
|
107
|
+
|
|
108
|
+
extract(zipPath, extractDir);
|
|
109
|
+
installBinary(extractDir, vendorDir);
|
|
110
|
+
} finally {
|
|
111
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
main().catch((error) => {
|
|
116
|
+
console.error(error.message);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
});
|
package/lib/platform.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function getAssetName(version) {
|
|
4
|
+
if (process.platform !== "darwin") {
|
|
5
|
+
throw new Error("osx-query only supports macOS");
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (process.arch === "arm64") {
|
|
9
|
+
return `osx-v${version}-arm64.zip`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (process.arch === "x64") {
|
|
13
|
+
return `osx-v${version}-x86_64.zip`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
throw new Error(`Unsupported architecture: ${process.arch}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
getAssetName,
|
|
21
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "osx-query",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "macOS Accessibility query CLI",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Moulik-Budhiraja/OSX-Query.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/Moulik-Budhiraja/OSX-Query#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/Moulik-Budhiraja/OSX-Query/issues"
|
|
13
|
+
},
|
|
14
|
+
"os": [
|
|
15
|
+
"darwin"
|
|
16
|
+
],
|
|
17
|
+
"cpu": [
|
|
18
|
+
"arm64",
|
|
19
|
+
"x64"
|
|
20
|
+
],
|
|
21
|
+
"preferGlobal": true,
|
|
22
|
+
"bin": {
|
|
23
|
+
"osx": "bin/osx.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"bin",
|
|
27
|
+
"lib"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"postinstall": "node ./lib/install.js"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
}
|
|
35
|
+
}
|