@aispace-sh/cli 0.1.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 ADDED
@@ -0,0 +1,12 @@
1
+ # aispace CLI for npm
2
+
3
+ Installs the native [`aispace`](https://github.com/aispace-sh/aispace-client) binary for macOS or
4
+ Linux and verifies it against the SHA-256 checksums published with the matching GitHub release.
5
+
6
+ ```sh
7
+ npm install -g @aispace-sh/cli
8
+ aispace login --key ask_...
9
+ ```
10
+
11
+ Supported platforms: macOS and Linux on x64 or ARM64. Node.js 20 or newer is required for the
12
+ installer and wrapper; the installed Go binary itself has no Node.js runtime dependency.
package/bin/aispace.js ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const { spawnSync } = require('node:child_process');
5
+ const path = require('node:path');
6
+
7
+ const binary = path.join(__dirname, 'aispace');
8
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: 'inherit' });
9
+ if (result.error) {
10
+ console.error(`aispace: ${result.error.message}`);
11
+ process.exit(1);
12
+ }
13
+ process.exit(result.status ?? 1);
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@aispace-sh/cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI for aispace.sh, a bot-friendly file drop with expiring links",
5
+ "license": "MIT",
6
+ "homepage": "https://aispace.sh",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/aispace-sh/aispace-client.git"
10
+ },
11
+ "bugs": "https://github.com/aispace-sh/aispace-client/issues",
12
+ "bin": {
13
+ "aispace": "bin/aispace.js"
14
+ },
15
+ "files": [
16
+ "bin/aispace.js",
17
+ "scripts/install.js",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "postinstall": "node scripts/install.js",
22
+ "test": "node --test test/*.test.js"
23
+ },
24
+ "engines": {
25
+ "node": ">=20"
26
+ },
27
+ "keywords": [
28
+ "ai",
29
+ "agent",
30
+ "cli",
31
+ "file-sharing",
32
+ "llm"
33
+ ],
34
+ "packageManager": "npm@11.17.0+sha512.3eeaf18997b11070d313849268b23766b9db0068997dec9471073170fe43fa17f2b4d0337bf0f52330ee2274e7f5754b21b01052742e48f5c9c74d8b1e32ef43"
35
+ }
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const crypto = require('node:crypto');
5
+ const fs = require('node:fs');
6
+ const https = require('node:https');
7
+ const path = require('node:path');
8
+
9
+ const REPOSITORY = 'aispace-sh/aispace-client';
10
+
11
+ function platformAsset(platform = process.platform, arch = process.arch) {
12
+ const os = { darwin: 'darwin', linux: 'linux' }[platform];
13
+ const cpu = { x64: 'amd64', arm64: 'arm64' }[arch];
14
+ if (!os || !cpu) throw new Error(`unsupported platform: ${platform}/${arch}`);
15
+ return `aispace_${os}_${cpu}`;
16
+ }
17
+
18
+ function download(url, redirects = 0) {
19
+ if (redirects > 5) return Promise.reject(new Error('too many redirects'));
20
+ return new Promise((resolve, reject) => {
21
+ https.get(url, { headers: { 'User-Agent': 'aispace-cli npm installer' } }, (response) => {
22
+ if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
23
+ response.resume();
24
+ download(new URL(response.headers.location, url), redirects + 1).then(resolve, reject);
25
+ return;
26
+ }
27
+ if (response.statusCode !== 200) {
28
+ response.resume();
29
+ reject(new Error(`download failed with HTTP ${response.statusCode}`));
30
+ return;
31
+ }
32
+ const chunks = [];
33
+ response.on('data', (chunk) => chunks.push(chunk));
34
+ response.on('end', () => resolve(Buffer.concat(chunks)));
35
+ response.on('error', reject);
36
+ }).on('error', reject);
37
+ });
38
+ }
39
+
40
+ function expectedChecksum(checksums, asset) {
41
+ const line = checksums.split(/\r?\n/).find((entry) => entry.endsWith(` ${asset}`));
42
+ if (!line || !/^[a-f0-9]{64} /.test(line)) throw new Error(`checksum missing for ${asset}`);
43
+ return line.slice(0, 64);
44
+ }
45
+
46
+ async function main() {
47
+ const pkg = require('../package.json');
48
+ const target = path.join(__dirname, '..', 'bin', 'aispace');
49
+ if (process.env.AISPACE_NPM_BINARY) {
50
+ fs.copyFileSync(process.env.AISPACE_NPM_BINARY, target);
51
+ fs.chmodSync(target, 0o755);
52
+ return;
53
+ }
54
+ const asset = platformAsset();
55
+ const base = `https://github.com/${REPOSITORY}/releases/download/v${pkg.version}`;
56
+ const [binary, checksumFile] = await Promise.all([
57
+ download(`${base}/${asset}`),
58
+ download(`${base}/checksums.txt`),
59
+ ]);
60
+ const actual = crypto.createHash('sha256').update(binary).digest('hex');
61
+ const expected = expectedChecksum(checksumFile.toString('utf8'), asset);
62
+ if (actual !== expected) throw new Error(`checksum mismatch for ${asset}`);
63
+ fs.writeFileSync(target, binary, { mode: 0o755 });
64
+ }
65
+
66
+ if (require.main === module) {
67
+ main().catch((error) => {
68
+ console.error(`aispace-cli install failed: ${error.message}`);
69
+ process.exit(1);
70
+ });
71
+ }
72
+
73
+ module.exports = { expectedChecksum, platformAsset };