vnsh-cli 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 +98 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +216 -0
- package/dist/cli.js.map +1 -0
- package/dist/crypto.d.ts +42 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +138 -0
- package/dist/crypto.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# vnsh-cli
|
|
2
|
+
|
|
3
|
+
The Ephemeral Dropbox for AI - CLI tool for encrypted file sharing.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/vnsh-cli)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **End-to-end encryption**: AES-256-CBC encryption happens locally
|
|
11
|
+
- **Host-blind**: Server never sees your encryption keys
|
|
12
|
+
- **Ephemeral**: Data auto-destructs after 24 hours (configurable)
|
|
13
|
+
- **Simple**: Pipe anything, get a shareable URL
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g vnsh-cli
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## CLI Usage
|
|
22
|
+
|
|
23
|
+
### Upload content
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Pipe text
|
|
27
|
+
echo "hello world" | vn
|
|
28
|
+
|
|
29
|
+
# Upload a file
|
|
30
|
+
vn secret.env
|
|
31
|
+
|
|
32
|
+
# Pipe from command
|
|
33
|
+
git diff | vn
|
|
34
|
+
cat crash.log | vn
|
|
35
|
+
docker logs app | vn
|
|
36
|
+
|
|
37
|
+
# Set custom expiry (1-168 hours)
|
|
38
|
+
vn -t 1 temp.txt # Expires in 1 hour
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Read content
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Decrypt and display content from a vnsh URL
|
|
45
|
+
vn read "https://vnsh.dev/v/abc123#k=...&iv=..."
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Options
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
-t, --ttl <hours> Set expiry time (default: 24, max: 168)
|
|
52
|
+
-p, --price <usd> Set price for x402 payment
|
|
53
|
+
-H, --host <url> Override API host
|
|
54
|
+
-l, --local Output encrypted blob locally (no upload)
|
|
55
|
+
-v, --version Show version
|
|
56
|
+
-h, --help Show help
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Programmatic Usage
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { share, read, readString } from 'vnsh-cli';
|
|
63
|
+
|
|
64
|
+
// Share content
|
|
65
|
+
const url = await share('Hello, World!');
|
|
66
|
+
console.log(url);
|
|
67
|
+
// https://vnsh.dev/v/abc123#k=...&iv=...
|
|
68
|
+
|
|
69
|
+
// Share with options
|
|
70
|
+
const url2 = await share(buffer, { ttl: 1 }); // 1 hour expiry
|
|
71
|
+
|
|
72
|
+
// Read content as Buffer
|
|
73
|
+
const buffer = await read(url);
|
|
74
|
+
|
|
75
|
+
// Read content as string
|
|
76
|
+
const text = await readString(url);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Environment Variables
|
|
80
|
+
|
|
81
|
+
- `VNSH_HOST` - Override the default API host (default: `https://vnsh.dev`)
|
|
82
|
+
|
|
83
|
+
## Security
|
|
84
|
+
|
|
85
|
+
- Encryption keys are generated locally and never sent to the server
|
|
86
|
+
- Keys travel only in the URL fragment (`#k=...`), which is never transmitted to servers
|
|
87
|
+
- The server stores only encrypted binary blobs
|
|
88
|
+
- All data auto-destructs after the configured TTL
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT
|
|
93
|
+
|
|
94
|
+
## Links
|
|
95
|
+
|
|
96
|
+
- [Website](https://vnsh.dev)
|
|
97
|
+
- [GitHub](https://github.com/raullenchai/vnsh)
|
|
98
|
+
- [Documentation](https://github.com/raullenchai/vnsh#readme)
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;GAIG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* vnsh CLI - The Ephemeral Dropbox for AI
|
|
5
|
+
*
|
|
6
|
+
* Encrypt and share content via host-blind data tunnel.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
const commander_1 = require("commander");
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const crypto_js_1 = require("./crypto.js");
|
|
45
|
+
const VERSION = '1.0.0';
|
|
46
|
+
const DEFAULT_HOST = process.env.VNSH_HOST || 'https://vnsh.dev';
|
|
47
|
+
const MAX_SIZE = 25 * 1024 * 1024; // 25MB
|
|
48
|
+
// Colors for terminal output
|
|
49
|
+
const colors = {
|
|
50
|
+
red: (s) => process.stderr.isTTY ? `\x1b[31m${s}\x1b[0m` : s,
|
|
51
|
+
green: (s) => process.stderr.isTTY ? `\x1b[32m${s}\x1b[0m` : s,
|
|
52
|
+
yellow: (s) => process.stderr.isTTY ? `\x1b[33m${s}\x1b[0m` : s,
|
|
53
|
+
cyan: (s) => process.stderr.isTTY ? `\x1b[36m${s}\x1b[0m` : s,
|
|
54
|
+
};
|
|
55
|
+
function info(msg) {
|
|
56
|
+
console.error(`${colors.cyan('→')} ${msg}`);
|
|
57
|
+
}
|
|
58
|
+
function error(msg) {
|
|
59
|
+
console.error(`${colors.red('error:')} ${msg}`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
function formatBytes(bytes) {
|
|
63
|
+
if (bytes < 1024)
|
|
64
|
+
return `${bytes}B`;
|
|
65
|
+
if (bytes < 1024 * 1024)
|
|
66
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
67
|
+
return `${(bytes / 1024 / 1024).toFixed(2)}MB`;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Upload content (file or stdin)
|
|
71
|
+
*/
|
|
72
|
+
async function upload(input, options) {
|
|
73
|
+
const host = options.host || DEFAULT_HOST;
|
|
74
|
+
let data;
|
|
75
|
+
if (input) {
|
|
76
|
+
// File mode
|
|
77
|
+
if (!fs.existsSync(input)) {
|
|
78
|
+
error(`File not found: ${input}`);
|
|
79
|
+
}
|
|
80
|
+
const stats = fs.statSync(input);
|
|
81
|
+
if (stats.size > MAX_SIZE) {
|
|
82
|
+
error(`File too large: ${formatBytes(stats.size)} (max: ${formatBytes(MAX_SIZE)})`);
|
|
83
|
+
}
|
|
84
|
+
info(`Encrypting ${input} (${formatBytes(stats.size)})...`);
|
|
85
|
+
data = fs.readFileSync(input);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// Stdin mode
|
|
89
|
+
if (process.stdin.isTTY) {
|
|
90
|
+
error('No input provided. Use: echo "text" | vn or vn <file>');
|
|
91
|
+
}
|
|
92
|
+
info('Encrypting stdin...');
|
|
93
|
+
const chunks = [];
|
|
94
|
+
for await (const chunk of process.stdin) {
|
|
95
|
+
chunks.push(chunk);
|
|
96
|
+
}
|
|
97
|
+
data = Buffer.concat(chunks);
|
|
98
|
+
if (data.length > MAX_SIZE) {
|
|
99
|
+
error(`Input too large: ${formatBytes(data.length)} (max: ${formatBytes(MAX_SIZE)})`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Generate key and IV
|
|
103
|
+
const key = (0, crypto_js_1.generateKey)();
|
|
104
|
+
const iv = (0, crypto_js_1.generateIV)();
|
|
105
|
+
// Encrypt
|
|
106
|
+
const encrypted = (0, crypto_js_1.encrypt)(data, key, iv);
|
|
107
|
+
// Local mode - output encrypted blob
|
|
108
|
+
if (options.local) {
|
|
109
|
+
console.log(`\n${colors.green('Encrypted blob (base64):')}`);
|
|
110
|
+
console.log(encrypted.toString('base64'));
|
|
111
|
+
console.log(`\n${colors.green('Decryption key:')} ${(0, crypto_js_1.bufferToHex)(key)}`);
|
|
112
|
+
console.log(`${colors.green('IV:')} ${(0, crypto_js_1.bufferToHex)(iv)}`);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Build API URL
|
|
116
|
+
let apiUrl = `${host}/api/drop`;
|
|
117
|
+
const params = new URLSearchParams();
|
|
118
|
+
if (options.ttl) {
|
|
119
|
+
const ttl = parseInt(options.ttl, 10);
|
|
120
|
+
if (isNaN(ttl) || ttl < 1 || ttl > 168) {
|
|
121
|
+
error('TTL must be between 1 and 168 hours');
|
|
122
|
+
}
|
|
123
|
+
params.set('ttl', options.ttl);
|
|
124
|
+
}
|
|
125
|
+
if (options.price) {
|
|
126
|
+
params.set('price', options.price);
|
|
127
|
+
}
|
|
128
|
+
if (params.toString()) {
|
|
129
|
+
apiUrl += `?${params.toString()}`;
|
|
130
|
+
}
|
|
131
|
+
info(`Uploading encrypted blob (${formatBytes(encrypted.length)})...`);
|
|
132
|
+
// Upload
|
|
133
|
+
const response = await fetch(apiUrl, {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
headers: { 'Content-Type': 'application/octet-stream' },
|
|
136
|
+
body: encrypted,
|
|
137
|
+
});
|
|
138
|
+
if (!response.ok) {
|
|
139
|
+
const text = await response.text();
|
|
140
|
+
error(`Upload failed (HTTP ${response.status}): ${text}`);
|
|
141
|
+
}
|
|
142
|
+
const result = await response.json();
|
|
143
|
+
// Build final URL
|
|
144
|
+
const finalUrl = (0, crypto_js_1.buildVnshUrl)(host, result.id, key, iv);
|
|
145
|
+
console.log('');
|
|
146
|
+
console.log(colors.green('✓ Uploaded successfully'));
|
|
147
|
+
console.log('');
|
|
148
|
+
console.log(finalUrl);
|
|
149
|
+
console.log('');
|
|
150
|
+
if (result.expires) {
|
|
151
|
+
console.log(`${colors.yellow('Expires:')} ${result.expires}`);
|
|
152
|
+
}
|
|
153
|
+
if (options.price) {
|
|
154
|
+
console.log(`${colors.yellow('Price:')} $${options.price} (x402 payment required)`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Read and decrypt a vnsh URL
|
|
159
|
+
*/
|
|
160
|
+
async function read(url) {
|
|
161
|
+
const { host, id, key, iv } = (0, crypto_js_1.parseVnshUrl)(url);
|
|
162
|
+
info(`Fetching blob ${id} from ${host}...`);
|
|
163
|
+
const response = await fetch(`${host}/api/blob/${id}`);
|
|
164
|
+
if (response.status === 402) {
|
|
165
|
+
error('Payment required. This blob requires payment to access.');
|
|
166
|
+
}
|
|
167
|
+
if (response.status === 404) {
|
|
168
|
+
error('Blob not found. It may have expired or been deleted.');
|
|
169
|
+
}
|
|
170
|
+
if (response.status === 410) {
|
|
171
|
+
error('Blob has expired and is no longer available.');
|
|
172
|
+
}
|
|
173
|
+
if (!response.ok) {
|
|
174
|
+
error(`Failed to fetch blob (HTTP ${response.status})`);
|
|
175
|
+
}
|
|
176
|
+
const encrypted = Buffer.from(await response.arrayBuffer());
|
|
177
|
+
info(`Decrypting blob (${formatBytes(encrypted.length)})...`);
|
|
178
|
+
try {
|
|
179
|
+
const decrypted = (0, crypto_js_1.decrypt)(encrypted, key, iv);
|
|
180
|
+
process.stdout.write(decrypted);
|
|
181
|
+
}
|
|
182
|
+
catch (e) {
|
|
183
|
+
error('Decryption failed. The key or IV may be incorrect.');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Setup CLI
|
|
187
|
+
commander_1.program
|
|
188
|
+
.name('vn')
|
|
189
|
+
.description('vnsh - The Ephemeral Dropbox for AI\n\nEncrypt and share content via host-blind data tunnel.')
|
|
190
|
+
.version(VERSION, '-v, --version')
|
|
191
|
+
.argument('[file]', 'File to encrypt and upload')
|
|
192
|
+
.option('-t, --ttl <hours>', 'Set expiry time in hours (default: 24, max: 168)')
|
|
193
|
+
.option('-p, --price <usd>', 'Set price in USD for x402 payment')
|
|
194
|
+
.option('-H, --host <url>', 'Override API host', DEFAULT_HOST)
|
|
195
|
+
.option('-l, --local', 'Output encrypted blob locally (no upload)')
|
|
196
|
+
.action(async (file, options) => {
|
|
197
|
+
try {
|
|
198
|
+
await upload(file, options);
|
|
199
|
+
}
|
|
200
|
+
catch (e) {
|
|
201
|
+
error(e instanceof Error ? e.message : String(e));
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
commander_1.program
|
|
205
|
+
.command('read <url>')
|
|
206
|
+
.description('Decrypt and read a vnsh URL')
|
|
207
|
+
.action(async (url) => {
|
|
208
|
+
try {
|
|
209
|
+
await read(url);
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
error(e instanceof Error ? e.message : String(e));
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
commander_1.program.parse();
|
|
216
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crypto utilities for vnsh CLI
|
|
3
|
+
* Compatible with OpenSSL AES-256-CBC encryption
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generate a random encryption key
|
|
7
|
+
*/
|
|
8
|
+
export declare function generateKey(): Buffer;
|
|
9
|
+
/**
|
|
10
|
+
* Generate a random IV
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateIV(): Buffer;
|
|
13
|
+
/**
|
|
14
|
+
* Encrypt data using AES-256-CBC
|
|
15
|
+
*/
|
|
16
|
+
export declare function encrypt(data: Buffer, key: Buffer, iv: Buffer): Buffer;
|
|
17
|
+
/**
|
|
18
|
+
* Decrypt data using AES-256-CBC
|
|
19
|
+
*/
|
|
20
|
+
export declare function decrypt(data: Buffer, key: Buffer, iv: Buffer): Buffer;
|
|
21
|
+
/**
|
|
22
|
+
* Convert buffer to hex string
|
|
23
|
+
*/
|
|
24
|
+
export declare function bufferToHex(buffer: Buffer): string;
|
|
25
|
+
/**
|
|
26
|
+
* Convert hex string to buffer
|
|
27
|
+
*/
|
|
28
|
+
export declare function hexToBuffer(hex: string): Buffer;
|
|
29
|
+
/**
|
|
30
|
+
* Parse a vnsh URL to extract components
|
|
31
|
+
*/
|
|
32
|
+
export declare function parseVnshUrl(url: string): {
|
|
33
|
+
host: string;
|
|
34
|
+
id: string;
|
|
35
|
+
key: Buffer;
|
|
36
|
+
iv: Buffer;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Build a vnsh URL from components
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildVnshUrl(host: string, id: string, key: Buffer, iv: Buffer): string;
|
|
42
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAGrE;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAGrE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;CACZ,CA0CA;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAItF"}
|
package/dist/crypto.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Crypto utilities for vnsh CLI
|
|
4
|
+
* Compatible with OpenSSL AES-256-CBC encryption
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.generateKey = generateKey;
|
|
41
|
+
exports.generateIV = generateIV;
|
|
42
|
+
exports.encrypt = encrypt;
|
|
43
|
+
exports.decrypt = decrypt;
|
|
44
|
+
exports.bufferToHex = bufferToHex;
|
|
45
|
+
exports.hexToBuffer = hexToBuffer;
|
|
46
|
+
exports.parseVnshUrl = parseVnshUrl;
|
|
47
|
+
exports.buildVnshUrl = buildVnshUrl;
|
|
48
|
+
const crypto = __importStar(require("crypto"));
|
|
49
|
+
const ALGORITHM = 'aes-256-cbc';
|
|
50
|
+
const KEY_LENGTH = 32; // 256 bits
|
|
51
|
+
const IV_LENGTH = 16; // 128 bits
|
|
52
|
+
/**
|
|
53
|
+
* Generate a random encryption key
|
|
54
|
+
*/
|
|
55
|
+
function generateKey() {
|
|
56
|
+
return crypto.randomBytes(KEY_LENGTH);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Generate a random IV
|
|
60
|
+
*/
|
|
61
|
+
function generateIV() {
|
|
62
|
+
return crypto.randomBytes(IV_LENGTH);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Encrypt data using AES-256-CBC
|
|
66
|
+
*/
|
|
67
|
+
function encrypt(data, key, iv) {
|
|
68
|
+
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
|
|
69
|
+
return Buffer.concat([cipher.update(data), cipher.final()]);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Decrypt data using AES-256-CBC
|
|
73
|
+
*/
|
|
74
|
+
function decrypt(data, key, iv) {
|
|
75
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
|
|
76
|
+
return Buffer.concat([decipher.update(data), decipher.final()]);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Convert buffer to hex string
|
|
80
|
+
*/
|
|
81
|
+
function bufferToHex(buffer) {
|
|
82
|
+
return buffer.toString('hex');
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Convert hex string to buffer
|
|
86
|
+
*/
|
|
87
|
+
function hexToBuffer(hex) {
|
|
88
|
+
return Buffer.from(hex, 'hex');
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Parse a vnsh URL to extract components
|
|
92
|
+
*/
|
|
93
|
+
function parseVnshUrl(url) {
|
|
94
|
+
// URL format: https://vnsh.dev/v/{id}#k={key}&iv={iv}
|
|
95
|
+
const hashIndex = url.indexOf('#');
|
|
96
|
+
if (hashIndex === -1) {
|
|
97
|
+
throw new Error('Invalid URL: missing fragment (#k=...&iv=...)');
|
|
98
|
+
}
|
|
99
|
+
const pathPart = url.substring(0, hashIndex);
|
|
100
|
+
const fragment = url.substring(hashIndex + 1);
|
|
101
|
+
// Extract host
|
|
102
|
+
const hostMatch = pathPart.match(/^(https?:\/\/[^/]+)/);
|
|
103
|
+
if (!hostMatch) {
|
|
104
|
+
throw new Error('Invalid URL: cannot extract host');
|
|
105
|
+
}
|
|
106
|
+
const host = hostMatch[1];
|
|
107
|
+
// Extract blob ID
|
|
108
|
+
const idMatch = pathPart.match(/\/v\/([a-f0-9-]+)/);
|
|
109
|
+
if (!idMatch) {
|
|
110
|
+
throw new Error('Invalid URL: cannot extract blob ID');
|
|
111
|
+
}
|
|
112
|
+
const id = idMatch[1];
|
|
113
|
+
// Parse fragment parameters
|
|
114
|
+
const params = new URLSearchParams(fragment);
|
|
115
|
+
const keyHex = params.get('k');
|
|
116
|
+
const ivHex = params.get('iv');
|
|
117
|
+
if (!keyHex || keyHex.length !== 64) {
|
|
118
|
+
throw new Error(`Invalid URL: missing or malformed key (expected 64 hex chars)`);
|
|
119
|
+
}
|
|
120
|
+
if (!ivHex || ivHex.length !== 32) {
|
|
121
|
+
throw new Error(`Invalid URL: missing or malformed IV (expected 32 hex chars)`);
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
host,
|
|
125
|
+
id,
|
|
126
|
+
key: hexToBuffer(keyHex),
|
|
127
|
+
iv: hexToBuffer(ivHex),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Build a vnsh URL from components
|
|
132
|
+
*/
|
|
133
|
+
function buildVnshUrl(host, id, key, iv) {
|
|
134
|
+
const keyHex = bufferToHex(key);
|
|
135
|
+
const ivHex = bufferToHex(iv);
|
|
136
|
+
return `${host}/v/${id}#k=${keyHex}&iv=${ivHex}`;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vnsh-cli - Programmatic API
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { share, read } from 'vnsh-cli';
|
|
7
|
+
*
|
|
8
|
+
* // Share content
|
|
9
|
+
* const url = await share('Hello, World!');
|
|
10
|
+
* console.log(url);
|
|
11
|
+
*
|
|
12
|
+
* // Read content
|
|
13
|
+
* const content = await read(url);
|
|
14
|
+
* console.log(content);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export { encrypt, decrypt, generateKey, generateIV, bufferToHex, hexToBuffer, parseVnshUrl, buildVnshUrl, } from './crypto.js';
|
|
18
|
+
interface ShareOptions {
|
|
19
|
+
host?: string;
|
|
20
|
+
ttl?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Share content via vnsh
|
|
24
|
+
* @param content - String or Buffer to share
|
|
25
|
+
* @param options - Optional configuration
|
|
26
|
+
* @returns The shareable URL
|
|
27
|
+
*/
|
|
28
|
+
export declare function share(content: string | Buffer, options?: ShareOptions): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Read content from a vnsh URL
|
|
31
|
+
* @param url - The vnsh URL to read
|
|
32
|
+
* @returns The decrypted content as a Buffer
|
|
33
|
+
*/
|
|
34
|
+
export declare function read(url: string): Promise<Buffer>;
|
|
35
|
+
/**
|
|
36
|
+
* Read content as string
|
|
37
|
+
* @param url - The vnsh URL to read
|
|
38
|
+
* @returns The decrypted content as a string
|
|
39
|
+
*/
|
|
40
|
+
export declare function readString(url: string): Promise<string>;
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,OAAO,EACP,OAAO,EACP,WAAW,EACX,UAAU,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,aAAa,CAAC;AAIrB,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAOD;;;;;GAKG;AACH,wBAAsB,KAAK,CACzB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,MAAM,CAAC,CAiCjB;AAED;;;;GAIG;AACH,wBAAsB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBvD;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7D"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* vnsh-cli - Programmatic API
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { share, read } from 'vnsh-cli';
|
|
8
|
+
*
|
|
9
|
+
* // Share content
|
|
10
|
+
* const url = await share('Hello, World!');
|
|
11
|
+
* console.log(url);
|
|
12
|
+
*
|
|
13
|
+
* // Read content
|
|
14
|
+
* const content = await read(url);
|
|
15
|
+
* console.log(content);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.buildVnshUrl = exports.parseVnshUrl = exports.hexToBuffer = exports.bufferToHex = exports.generateIV = exports.generateKey = exports.decrypt = exports.encrypt = void 0;
|
|
20
|
+
exports.share = share;
|
|
21
|
+
exports.read = read;
|
|
22
|
+
exports.readString = readString;
|
|
23
|
+
var crypto_js_1 = require("./crypto.js");
|
|
24
|
+
Object.defineProperty(exports, "encrypt", { enumerable: true, get: function () { return crypto_js_1.encrypt; } });
|
|
25
|
+
Object.defineProperty(exports, "decrypt", { enumerable: true, get: function () { return crypto_js_1.decrypt; } });
|
|
26
|
+
Object.defineProperty(exports, "generateKey", { enumerable: true, get: function () { return crypto_js_1.generateKey; } });
|
|
27
|
+
Object.defineProperty(exports, "generateIV", { enumerable: true, get: function () { return crypto_js_1.generateIV; } });
|
|
28
|
+
Object.defineProperty(exports, "bufferToHex", { enumerable: true, get: function () { return crypto_js_1.bufferToHex; } });
|
|
29
|
+
Object.defineProperty(exports, "hexToBuffer", { enumerable: true, get: function () { return crypto_js_1.hexToBuffer; } });
|
|
30
|
+
Object.defineProperty(exports, "parseVnshUrl", { enumerable: true, get: function () { return crypto_js_1.parseVnshUrl; } });
|
|
31
|
+
Object.defineProperty(exports, "buildVnshUrl", { enumerable: true, get: function () { return crypto_js_1.buildVnshUrl; } });
|
|
32
|
+
const DEFAULT_HOST = process.env.VNSH_HOST || 'https://vnsh.dev';
|
|
33
|
+
/**
|
|
34
|
+
* Share content via vnsh
|
|
35
|
+
* @param content - String or Buffer to share
|
|
36
|
+
* @param options - Optional configuration
|
|
37
|
+
* @returns The shareable URL
|
|
38
|
+
*/
|
|
39
|
+
async function share(content, options = {}) {
|
|
40
|
+
const { generateKey, generateIV, encrypt, buildVnshUrl } = await import('./crypto.js');
|
|
41
|
+
const host = options.host || DEFAULT_HOST;
|
|
42
|
+
const data = typeof content === 'string' ? Buffer.from(content, 'utf-8') : content;
|
|
43
|
+
// Generate key and IV
|
|
44
|
+
const key = generateKey();
|
|
45
|
+
const iv = generateIV();
|
|
46
|
+
// Encrypt
|
|
47
|
+
const encrypted = encrypt(data, key, iv);
|
|
48
|
+
// Build API URL
|
|
49
|
+
let apiUrl = `${host}/api/drop`;
|
|
50
|
+
if (options.ttl) {
|
|
51
|
+
apiUrl += `?ttl=${options.ttl}`;
|
|
52
|
+
}
|
|
53
|
+
// Upload
|
|
54
|
+
const response = await fetch(apiUrl, {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers: { 'Content-Type': 'application/octet-stream' },
|
|
57
|
+
body: encrypted,
|
|
58
|
+
});
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
throw new Error(`Upload failed: HTTP ${response.status}`);
|
|
61
|
+
}
|
|
62
|
+
const result = await response.json();
|
|
63
|
+
return buildVnshUrl(host, result.id, key, iv);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Read content from a vnsh URL
|
|
67
|
+
* @param url - The vnsh URL to read
|
|
68
|
+
* @returns The decrypted content as a Buffer
|
|
69
|
+
*/
|
|
70
|
+
async function read(url) {
|
|
71
|
+
const { parseVnshUrl, decrypt } = await import('./crypto.js');
|
|
72
|
+
const { host, id, key, iv } = parseVnshUrl(url);
|
|
73
|
+
const response = await fetch(`${host}/api/blob/${id}`);
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
if (response.status === 404) {
|
|
76
|
+
throw new Error('Blob not found. It may have expired or been deleted.');
|
|
77
|
+
}
|
|
78
|
+
if (response.status === 410) {
|
|
79
|
+
throw new Error('Blob has expired and is no longer available.');
|
|
80
|
+
}
|
|
81
|
+
throw new Error(`Failed to fetch blob: HTTP ${response.status}`);
|
|
82
|
+
}
|
|
83
|
+
const encrypted = Buffer.from(await response.arrayBuffer());
|
|
84
|
+
return decrypt(encrypted, key, iv);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Read content as string
|
|
88
|
+
* @param url - The vnsh URL to read
|
|
89
|
+
* @returns The decrypted content as a string
|
|
90
|
+
*/
|
|
91
|
+
async function readString(url) {
|
|
92
|
+
const buffer = await read(url);
|
|
93
|
+
return buffer.toString('utf-8');
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vnsh-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "The Ephemeral Dropbox for AI - CLI tool for encrypted file sharing",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"vnsh",
|
|
7
|
+
"encryption",
|
|
8
|
+
"file-sharing",
|
|
9
|
+
"cli",
|
|
10
|
+
"claude",
|
|
11
|
+
"ai",
|
|
12
|
+
"secure",
|
|
13
|
+
"ephemeral",
|
|
14
|
+
"pastebin"
|
|
15
|
+
],
|
|
16
|
+
"author": "raullenchai",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/raullenchai/vnsh.git"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://vnsh.dev",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/raullenchai/vnsh/issues"
|
|
25
|
+
},
|
|
26
|
+
"bin": {
|
|
27
|
+
"vn": "./dist/cli.js",
|
|
28
|
+
"vnsh": "./dist/cli.js"
|
|
29
|
+
},
|
|
30
|
+
"main": "./dist/index.js",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc",
|
|
37
|
+
"prepublishOnly": "npm run build",
|
|
38
|
+
"test": "vitest run"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"commander": "^12.1.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^22.10.0",
|
|
45
|
+
"typescript": "^5.7.0",
|
|
46
|
+
"vitest": "^2.1.0"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=18.0.0"
|
|
50
|
+
}
|
|
51
|
+
}
|