@airstrings/cli 0.13.5

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.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ require('../lib/run.js').run('airstrings-mcp');
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ require('../lib/run.js').run('airstrings');
package/install.js ADDED
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('crypto');
4
+ const fs = require('fs');
5
+ const os = require('os');
6
+ const path = require('path');
7
+ const { execFileSync } = require('child_process');
8
+
9
+ const { target, vendorDir, binaryPath } = require('./lib/binary.js');
10
+ const { checksumFor } = require('./lib/checksums.js');
11
+ const { version } = require('./package.json');
12
+
13
+ const RELEASE_BASE = `https://github.com/symbionix-sl/homebrew-airstrings/releases/download/v${version}`;
14
+
15
+ async function download(url) {
16
+ const res = await fetch(url, { redirect: 'follow' });
17
+ if (!res.ok) {
18
+ throw new Error(`airstrings: download failed with HTTP ${res.status} — ${url}`);
19
+ }
20
+ return Buffer.from(await res.arrayBuffer());
21
+ }
22
+
23
+ async function main() {
24
+ const { asset: platform, ext } = target();
25
+ const asset = `airstrings-v${version}-${platform}.${ext}`;
26
+
27
+ const [archive, sums] = await Promise.all([
28
+ download(`${RELEASE_BASE}/${asset}`),
29
+ download(`${RELEASE_BASE}/SHA256SUMS`),
30
+ ]);
31
+
32
+ const expected = checksumFor(sums, asset);
33
+ const actual = crypto.createHash('sha256').update(archive).digest('hex');
34
+ if (actual !== expected) {
35
+ throw new Error(
36
+ `airstrings: checksum mismatch for ${asset}\n expected ${expected}\n actual ${actual}\n` +
37
+ `Refusing to install a binary that does not match the published checksum.`
38
+ );
39
+ }
40
+
41
+ const tmp = path.join(fs.mkdtempSync(path.join(os.tmpdir(), 'airstrings-')), asset);
42
+ fs.writeFileSync(tmp, archive);
43
+
44
+ fs.rmSync(vendorDir, { recursive: true, force: true });
45
+ fs.mkdirSync(vendorDir, { recursive: true });
46
+ execFileSync('tar', ['-xf', tmp, '-C', vendorDir]);
47
+ fs.rmSync(path.dirname(tmp), { recursive: true, force: true });
48
+
49
+ if (process.platform !== 'win32') {
50
+ for (const name of ['airstrings', 'airstrings-mcp']) {
51
+ fs.chmodSync(binaryPath(name), 0o755);
52
+ }
53
+ }
54
+ }
55
+
56
+ main().catch((err) => {
57
+ console.error(err.message);
58
+ process.exit(1);
59
+ });
package/lib/binary.js ADDED
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+
5
+ const TARGETS = {
6
+ 'darwin-arm64': { asset: 'darwin-arm64', ext: 'tar.gz' },
7
+ 'darwin-x64': { asset: 'darwin-amd64', ext: 'tar.gz' },
8
+ 'linux-arm64': { asset: 'linux-arm64', ext: 'tar.gz' },
9
+ 'linux-x64': { asset: 'linux-amd64', ext: 'tar.gz' },
10
+ 'win32-x64': { asset: 'windows-amd64', ext: 'zip' },
11
+ };
12
+
13
+ const vendorDir = path.join(__dirname, '..', 'vendor');
14
+
15
+ function target() {
16
+ const key = `${process.platform}-${process.arch}`;
17
+ const found = TARGETS[key];
18
+ if (!found) {
19
+ throw new Error(
20
+ `airstrings: no prebuilt binary for ${key}. Supported: ${Object.keys(TARGETS).join(', ')}. ` +
21
+ `Install with Homebrew instead: brew install symbionix-sl/airstrings/airstrings`
22
+ );
23
+ }
24
+ return found;
25
+ }
26
+
27
+ function binaryPath(name) {
28
+ const ext = process.platform === 'win32' ? '.exe' : '';
29
+ return path.join(vendorDir, `${name}${ext}`);
30
+ }
31
+
32
+ module.exports = { target, vendorDir, binaryPath };
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ function checksumFor(sums, asset) {
4
+ const line = String(sums)
5
+ .split('\n')
6
+ .map((l) => l.trim().split(/\s+/))
7
+ .find(([, name]) => name === asset);
8
+ if (!line) {
9
+ throw new Error(`airstrings: no checksum published for ${asset}`);
10
+ }
11
+ return line[0];
12
+ }
13
+
14
+ module.exports = { checksumFor };
package/lib/run.js ADDED
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ const { spawnSync } = require('child_process');
4
+ const fs = require('fs');
5
+
6
+ const { binaryPath } = require('./binary.js');
7
+
8
+ function run(name) {
9
+ const bin = binaryPath(name);
10
+ if (!fs.existsSync(bin)) {
11
+ console.error(`airstrings: ${name} binary is missing — reinstall the package to fetch it.`);
12
+ process.exit(1);
13
+ }
14
+
15
+ const result = spawnSync(bin, process.argv.slice(2), { stdio: 'inherit' });
16
+
17
+ if (result.error) {
18
+ console.error(`airstrings: failed to run ${name} — ${result.error.message}`);
19
+ process.exit(1);
20
+ }
21
+ if (result.signal) {
22
+ process.kill(process.pid, result.signal);
23
+ return;
24
+ }
25
+ process.exit(result.status ?? 1);
26
+ }
27
+
28
+ module.exports = { run };
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@airstrings/cli",
3
+ "version": "0.13.5",
4
+ "description": "CLI for the AirStrings remote string management platform",
5
+ "homepage": "https://airstrings.com",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/symbionix-sl/airstrings-cli.git",
10
+ "directory": "npm"
11
+ },
12
+ "keywords": [
13
+ "airstrings",
14
+ "cli",
15
+ "localization",
16
+ "i18n",
17
+ "strings"
18
+ ],
19
+ "bin": {
20
+ "airstrings": "bin/airstrings.js",
21
+ "airstrings-mcp": "bin/airstrings-mcp.js"
22
+ },
23
+ "files": [
24
+ "bin",
25
+ "lib",
26
+ "install.js"
27
+ ],
28
+ "scripts": {
29
+ "postinstall": "node install.js",
30
+ "test": "node test.js"
31
+ },
32
+ "engines": {
33
+ "node": ">=18"
34
+ },
35
+ "os": [
36
+ "darwin",
37
+ "linux",
38
+ "win32"
39
+ ],
40
+ "cpu": [
41
+ "x64",
42
+ "arm64"
43
+ ],
44
+ "publishConfig": {
45
+ "access": "public"
46
+ }
47
+ }