@gelglx/arjunakey 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 +66 -0
- package/cli.js +376 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# arjuna-key-cli
|
|
2
|
+
|
|
3
|
+
CLI satu akun untuk:
|
|
4
|
+
|
|
5
|
+
1. membuat informasi akun acak,
|
|
6
|
+
2. register ke `https://dash.arjuna.dev/register`,
|
|
7
|
+
3. login,
|
|
8
|
+
4. klaim kode welcome/voucher,
|
|
9
|
+
5. mengambil API key dari `/api/me`.
|
|
10
|
+
|
|
11
|
+
Tidak ada dependency npm eksternal.
|
|
12
|
+
|
|
13
|
+
## Instalasi lokal
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd /home/ubuntu/arjuna-key-cli
|
|
17
|
+
npm install -g .
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Pemakaian
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
arjunakey create
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Kode default:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
ONE-GROUP-6T2E-2V7N-H37Q
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Kode tersebut adalah welcome-group code. Website memprosesnya melalui `/api/billing/signup-bonus`, bukan form voucher billing biasa. CLI mencoba welcome endpoint lebih dulu lalu fallback ke `/api/billing/redeem` untuk voucher biasa.
|
|
33
|
+
|
|
34
|
+
Output hanya API key:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
arjunakey create --raw
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Simpan key sebagai teks polos, satu key per baris:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
arjunakey create --raw --save ./api-keys.txt
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Simpan data akun lengkap sebagai JSON Lines:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
arjunakey create --account-out ./accounts.jsonl
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Gunakan akun yang sudah ada:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
ARJUNA_EMAIL='user@example.com' \
|
|
56
|
+
ARJUNA_PASSWORD='password' \
|
|
57
|
+
arjunakey login --no-claim --raw
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Lihat semua opsi:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
arjunakey --help
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
CLI sengaja hanya memproses satu akun per eksekusi; tidak menyediakan farm, worker paralel, proxy rotation, atau batch account creation.
|
package/cli.js
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const http = require('http');
|
|
7
|
+
const https = require('https');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { URL } = require('url');
|
|
10
|
+
|
|
11
|
+
const VERSION = '1.0.0';
|
|
12
|
+
const DEFAULT_BASE_URL = 'https://dash.arjuna.dev';
|
|
13
|
+
const DEFAULT_CODE = 'ONE-GROUP-6T2E-2V7N-H37Q';
|
|
14
|
+
|
|
15
|
+
class ApiError extends Error {
|
|
16
|
+
constructor(message, response = null) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = 'ApiError';
|
|
19
|
+
this.response = response;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class Client {
|
|
24
|
+
constructor(baseUrl, timeoutMs) {
|
|
25
|
+
this.baseUrl = new URL(baseUrl);
|
|
26
|
+
this.timeoutMs = timeoutMs;
|
|
27
|
+
this.cookies = new Map();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
cookieHeader() {
|
|
31
|
+
return [...this.cookies.entries()].map(([name, value]) => `${name}=${value}`).join('; ');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
captureCookies(headers) {
|
|
35
|
+
const values = headers['set-cookie'];
|
|
36
|
+
if (!values) return;
|
|
37
|
+
for (const line of Array.isArray(values) ? values : [values]) {
|
|
38
|
+
const pair = line.split(';', 1)[0];
|
|
39
|
+
const equals = pair.indexOf('=');
|
|
40
|
+
if (equals > 0) this.cookies.set(pair.slice(0, equals).trim(), pair.slice(equals + 1).trim());
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
request(method, pathname, body = undefined) {
|
|
45
|
+
const target = new URL(pathname, this.baseUrl);
|
|
46
|
+
const payload = body === undefined ? null : JSON.stringify(body);
|
|
47
|
+
const headers = {
|
|
48
|
+
Accept: 'application/json',
|
|
49
|
+
Origin: this.baseUrl.origin,
|
|
50
|
+
Referer: `${this.baseUrl.origin}/`,
|
|
51
|
+
'User-Agent': `arjuna-key-cli/${VERSION}`,
|
|
52
|
+
};
|
|
53
|
+
if (payload !== null) {
|
|
54
|
+
headers['Content-Type'] = 'application/json';
|
|
55
|
+
headers['Content-Length'] = Buffer.byteLength(payload);
|
|
56
|
+
}
|
|
57
|
+
const cookie = this.cookieHeader();
|
|
58
|
+
if (cookie) headers.Cookie = cookie;
|
|
59
|
+
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
const transport = target.protocol === 'https:' ? https : http;
|
|
62
|
+
const req = transport.request({
|
|
63
|
+
protocol: target.protocol,
|
|
64
|
+
hostname: target.hostname,
|
|
65
|
+
port: target.port || undefined,
|
|
66
|
+
path: target.pathname + target.search,
|
|
67
|
+
method,
|
|
68
|
+
headers,
|
|
69
|
+
timeout: this.timeoutMs,
|
|
70
|
+
}, res => {
|
|
71
|
+
this.captureCookies(res.headers);
|
|
72
|
+
const chunks = [];
|
|
73
|
+
res.on('data', chunk => chunks.push(chunk));
|
|
74
|
+
res.on('end', () => {
|
|
75
|
+
const text = Buffer.concat(chunks).toString('utf8');
|
|
76
|
+
let data = null;
|
|
77
|
+
try { data = text ? JSON.parse(text) : {}; }
|
|
78
|
+
catch { data = { raw: text }; }
|
|
79
|
+
resolve({ status: res.statusCode || 0, headers: res.headers, data, text });
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
req.on('timeout', () => req.destroy(new Error(`Request timeout after ${this.timeoutMs} ms`)));
|
|
83
|
+
req.on('error', reject);
|
|
84
|
+
if (payload !== null) req.write(payload);
|
|
85
|
+
req.end();
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function apiMessage(response, fallback) {
|
|
91
|
+
return response?.data?.error || response?.data?.message || fallback;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function assertOk(response, fallback) {
|
|
95
|
+
if (response.status < 200 || response.status >= 300) {
|
|
96
|
+
throw new ApiError(apiMessage(response, `${fallback} (HTTP ${response.status})`), response);
|
|
97
|
+
}
|
|
98
|
+
return response.data;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const FIRST_NAMES = ['Adit', 'Bagas', 'Bima', 'Dian', 'Fajar', 'Galih', 'Intan', 'Nadia', 'Raka', 'Rizky', 'Salsa', 'Tegar'];
|
|
102
|
+
const LAST_NAMES = ['Kusuma', 'Maulana', 'Nugroho', 'Pratama', 'Ramadhan', 'Saputra', 'Setiawan', 'Utami', 'Wijaya', 'Wulandari'];
|
|
103
|
+
|
|
104
|
+
function randomItem(items) {
|
|
105
|
+
return items[crypto.randomInt(items.length)];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function randomProfile(emailDomain) {
|
|
109
|
+
const first = randomItem(FIRST_NAMES);
|
|
110
|
+
const last = randomItem(LAST_NAMES);
|
|
111
|
+
const suffix = crypto.randomBytes(6).toString('hex');
|
|
112
|
+
return {
|
|
113
|
+
name: `${first} ${last}`,
|
|
114
|
+
email: `${first}.${last}.${suffix}@${emailDomain}`.toLowerCase(),
|
|
115
|
+
password: `A!7a${crypto.randomBytes(15).toString('base64url')}`,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function validateProfile(profile) {
|
|
120
|
+
if (profile.name.length < 2 || profile.name.length > 80) throw new Error('Nama harus 2-80 karakter.');
|
|
121
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(profile.email) || profile.email.length > 254) throw new Error('Alamat email tidak valid.');
|
|
122
|
+
if (profile.password.length < 8 || profile.password.length > 128) throw new Error('Password harus 8-128 karakter.');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function login(client, email, password) {
|
|
126
|
+
const response = await client.request('POST', '/api/auth/login', { email, password });
|
|
127
|
+
assertOk(response, 'Gagal masuk');
|
|
128
|
+
if (!client.cookies.size) throw new Error('Server tidak mengirim cookie sesi setelah login.');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function register(client, profile) {
|
|
132
|
+
const response = await client.request('POST', '/api/auth/register', {
|
|
133
|
+
name: profile.name,
|
|
134
|
+
email: profile.email,
|
|
135
|
+
password: profile.password,
|
|
136
|
+
website: '',
|
|
137
|
+
});
|
|
138
|
+
assertOk(response, 'Gagal membuat akun');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function claimCode(client, code) {
|
|
142
|
+
const groupResponse = await client.request('POST', '/api/billing/signup-bonus', { code });
|
|
143
|
+
if (groupResponse.status >= 200 && groupResponse.status < 300) {
|
|
144
|
+
return { kind: 'welcome-group', ...groupResponse.data };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (![400, 404].includes(groupResponse.status)) {
|
|
148
|
+
throw new ApiError(apiMessage(groupResponse, 'Gagal klaim welcome code'), groupResponse);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const voucherResponse = await client.request('POST', '/api/billing/redeem', { code });
|
|
152
|
+
if (voucherResponse.status >= 200 && voucherResponse.status < 300) {
|
|
153
|
+
return { kind: 'voucher', ...voucherResponse.data };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const groupError = apiMessage(groupResponse, 'Welcome code ditolak');
|
|
157
|
+
const voucherError = apiMessage(voucherResponse, 'Voucher ditolak');
|
|
158
|
+
throw new ApiError(`${groupError}; ${voucherError}`, voucherResponse);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function getAccount(client) {
|
|
162
|
+
const response = await client.request('GET', '/api/me');
|
|
163
|
+
const account = assertOk(response, 'Gagal mengambil informasi akun');
|
|
164
|
+
if (!account.apiKey || typeof account.apiKey !== 'string') throw new Error('API key tidak ditemukan pada respons /api/me.');
|
|
165
|
+
return account;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function parseArgs(argv) {
|
|
169
|
+
const opts = {
|
|
170
|
+
command: 'create',
|
|
171
|
+
baseUrl: process.env.ARJUNA_BASE_URL || DEFAULT_BASE_URL,
|
|
172
|
+
voucher: process.env.ARJUNA_VOUCHER || DEFAULT_CODE,
|
|
173
|
+
emailDomain: process.env.ARJUNA_EMAIL_DOMAIN || 'example.com',
|
|
174
|
+
timeout: Number(process.env.ARJUNA_TIMEOUT || 30),
|
|
175
|
+
json: false,
|
|
176
|
+
raw: false,
|
|
177
|
+
noClaim: false,
|
|
178
|
+
quiet: false,
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const input = [...argv];
|
|
182
|
+
if (input[0] && !input[0].startsWith('-')) opts.command = input.shift();
|
|
183
|
+
const valueFlags = new Set(['--base-url', '--voucher', '--email-domain', '--name', '--email', '--password', '--save', '--account-out', '--timeout']);
|
|
184
|
+
|
|
185
|
+
for (let i = 0; i < input.length; i++) {
|
|
186
|
+
let flag = input[i];
|
|
187
|
+
let inlineValue;
|
|
188
|
+
if (flag.startsWith('--') && flag.includes('=')) {
|
|
189
|
+
const at = flag.indexOf('=');
|
|
190
|
+
inlineValue = flag.slice(at + 1);
|
|
191
|
+
flag = flag.slice(0, at);
|
|
192
|
+
}
|
|
193
|
+
let value;
|
|
194
|
+
if (valueFlags.has(flag)) {
|
|
195
|
+
value = inlineValue !== undefined ? inlineValue : input[++i];
|
|
196
|
+
if (value === undefined) throw new Error(`${flag} membutuhkan nilai.`);
|
|
197
|
+
} else if (inlineValue !== undefined) {
|
|
198
|
+
throw new Error(`Flag ${flag} tidak menerima nilai.`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
switch (flag) {
|
|
202
|
+
case '--base-url': opts.baseUrl = value; break;
|
|
203
|
+
case '--voucher': opts.voucher = value; break;
|
|
204
|
+
case '--email-domain': opts.emailDomain = value; break;
|
|
205
|
+
case '--name': opts.name = value; break;
|
|
206
|
+
case '--email': opts.email = value; break;
|
|
207
|
+
case '--password': opts.password = value; break;
|
|
208
|
+
case '--save': opts.save = value; break;
|
|
209
|
+
case '--account-out': opts.accountOut = value; break;
|
|
210
|
+
case '--timeout': opts.timeout = Number(value); break;
|
|
211
|
+
case '--json': opts.json = true; break;
|
|
212
|
+
case '--raw': opts.raw = true; break;
|
|
213
|
+
case '--no-claim': opts.noClaim = true; break;
|
|
214
|
+
case '--quiet': opts.quiet = true; break;
|
|
215
|
+
case '-h': case '--help': opts.command = 'help'; break;
|
|
216
|
+
case '-v': case '--version': opts.command = 'version'; break;
|
|
217
|
+
default: throw new Error(`Flag tidak dikenal: ${flag}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return opts;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function validateOptions(opts) {
|
|
224
|
+
if (!['create', 'login', 'help', 'version'].includes(opts.command)) throw new Error(`Perintah tidak dikenal: ${opts.command}`);
|
|
225
|
+
const base = new URL(opts.baseUrl);
|
|
226
|
+
if (!['http:', 'https:'].includes(base.protocol)) throw new Error('Base URL harus memakai http atau https.');
|
|
227
|
+
opts.baseUrl = base.origin;
|
|
228
|
+
if (!Number.isFinite(opts.timeout) || opts.timeout < 1 || opts.timeout > 300) throw new Error('Timeout harus 1-300 detik.');
|
|
229
|
+
if (opts.raw && opts.json) throw new Error('Pilih salah satu: --raw atau --json.');
|
|
230
|
+
if (opts.command === 'login' && !(opts.email || process.env.ARJUNA_EMAIL)) throw new Error('login membutuhkan --email atau ARJUNA_EMAIL.');
|
|
231
|
+
if (opts.command === 'login' && !(opts.password || process.env.ARJUNA_PASSWORD)) throw new Error('login membutuhkan --password atau ARJUNA_PASSWORD.');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function secureAppend(file, line) {
|
|
235
|
+
const resolved = path.resolve(file);
|
|
236
|
+
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
237
|
+
const fd = fs.openSync(resolved, 'a', 0o600);
|
|
238
|
+
try { fs.writeSync(fd, `${line}\n`); }
|
|
239
|
+
finally { fs.closeSync(fd); }
|
|
240
|
+
try { fs.chmodSync(resolved, 0o600); } catch {}
|
|
241
|
+
return resolved;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function printResult(result, opts) {
|
|
245
|
+
if (opts.raw) {
|
|
246
|
+
process.stdout.write(`${result.apiKey}\n`);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (opts.json) {
|
|
250
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
console.log(`name=${result.name}`);
|
|
254
|
+
console.log(`email=${result.email}`);
|
|
255
|
+
if (result.password) console.log(`password=${result.password}`);
|
|
256
|
+
if (result.claim) {
|
|
257
|
+
console.log(`claim_type=${result.claim.kind}`);
|
|
258
|
+
console.log(`claim_tokens=${result.claim.tokenAmount ?? ''}`);
|
|
259
|
+
}
|
|
260
|
+
console.log(`balance=${result.balance}`);
|
|
261
|
+
console.log(`status=${result.status}`);
|
|
262
|
+
console.log(`base_url=${result.baseUrl}`);
|
|
263
|
+
console.log(`api_key=${result.apiKey}`);
|
|
264
|
+
if (result.savedKeyFile) console.log(`key_file=${result.savedKeyFile}`);
|
|
265
|
+
if (result.savedAccountFile) console.log(`account_file=${result.savedAccountFile}`);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function help() {
|
|
269
|
+
console.log(`arjunakey ${VERSION}
|
|
270
|
+
|
|
271
|
+
Pemakaian:
|
|
272
|
+
arjunakey create [opsi]
|
|
273
|
+
arjunakey login --email EMAIL --password PASSWORD [opsi]
|
|
274
|
+
|
|
275
|
+
create membuat satu akun acak, login, klaim kode, lalu mengambil API key.
|
|
276
|
+
Kode default: ${DEFAULT_CODE}
|
|
277
|
+
|
|
278
|
+
Opsi:
|
|
279
|
+
--voucher CODE Welcome/voucher code
|
|
280
|
+
--email-domain HOST Domain email acak (default: example.com)
|
|
281
|
+
--name NAME Ganti nama acak
|
|
282
|
+
--email EMAIL Ganti email acak
|
|
283
|
+
--password PASS Ganti password acak
|
|
284
|
+
--no-claim Lewati klaim kode
|
|
285
|
+
--save FILE Tambahkan API key ke FILE (satu key per baris)
|
|
286
|
+
--account-out FILE Tambahkan data akun JSON ke FILE
|
|
287
|
+
--raw Hanya cetak API key
|
|
288
|
+
--json Cetak hasil JSON
|
|
289
|
+
--base-url URL Dashboard URL (default: ${DEFAULT_BASE_URL})
|
|
290
|
+
--timeout SEC Timeout request (default: 30)
|
|
291
|
+
-h, --help Bantuan
|
|
292
|
+
-v, --version Versi
|
|
293
|
+
|
|
294
|
+
Environment:
|
|
295
|
+
ARJUNA_EMAIL, ARJUNA_PASSWORD, ARJUNA_BASE_URL,
|
|
296
|
+
ARJUNA_VOUCHER, ARJUNA_EMAIL_DOMAIN, ARJUNA_TIMEOUT`);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async function main() {
|
|
300
|
+
const opts = parseArgs(process.argv.slice(2));
|
|
301
|
+
validateOptions(opts);
|
|
302
|
+
if (opts.command === 'help') return help();
|
|
303
|
+
if (opts.command === 'version') return console.log(VERSION);
|
|
304
|
+
|
|
305
|
+
const client = new Client(opts.baseUrl, opts.timeout * 1000);
|
|
306
|
+
let profile;
|
|
307
|
+
let claim = null;
|
|
308
|
+
|
|
309
|
+
if (opts.command === 'create') {
|
|
310
|
+
profile = randomProfile(opts.emailDomain);
|
|
311
|
+
if (opts.name) profile.name = opts.name;
|
|
312
|
+
if (opts.email) profile.email = opts.email.toLowerCase();
|
|
313
|
+
if (opts.password) profile.password = opts.password;
|
|
314
|
+
validateProfile(profile);
|
|
315
|
+
if (!opts.quiet && !opts.raw && !opts.json) console.error('Membuat akun...');
|
|
316
|
+
await register(client, profile);
|
|
317
|
+
if (!opts.quiet && !opts.raw && !opts.json) console.error('Masuk ke akun...');
|
|
318
|
+
await login(client, profile.email, profile.password);
|
|
319
|
+
} else {
|
|
320
|
+
profile = {
|
|
321
|
+
email: (opts.email || process.env.ARJUNA_EMAIL).toLowerCase(),
|
|
322
|
+
password: opts.password || process.env.ARJUNA_PASSWORD,
|
|
323
|
+
};
|
|
324
|
+
if (!opts.quiet && !opts.raw && !opts.json) console.error('Masuk ke akun...');
|
|
325
|
+
await login(client, profile.email, profile.password);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (!opts.noClaim && opts.voucher) {
|
|
329
|
+
if (!opts.quiet && !opts.raw && !opts.json) console.error('Mengklaim kode...');
|
|
330
|
+
try {
|
|
331
|
+
claim = await claimCode(client, opts.voucher);
|
|
332
|
+
} catch (error) {
|
|
333
|
+
if (opts.command === 'login' && error instanceof ApiError && /already|sudah|claimed/i.test(error.message)) {
|
|
334
|
+
claim = { kind: 'already-claimed' };
|
|
335
|
+
} else {
|
|
336
|
+
throw error;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (!opts.quiet && !opts.raw && !opts.json) console.error('Mengambil API key...');
|
|
342
|
+
const account = await getAccount(client);
|
|
343
|
+
const result = {
|
|
344
|
+
name: account.name || profile.name || '',
|
|
345
|
+
email: account.email || profile.email,
|
|
346
|
+
...(opts.command === 'create' ? { password: profile.password } : {}),
|
|
347
|
+
claim,
|
|
348
|
+
balance: account.token_balance,
|
|
349
|
+
status: account.status,
|
|
350
|
+
baseUrl: account.baseUrl,
|
|
351
|
+
apiKey: account.apiKey,
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
if (opts.save) result.savedKeyFile = secureAppend(opts.save, result.apiKey);
|
|
355
|
+
if (opts.accountOut) {
|
|
356
|
+
result.savedAccountFile = secureAppend(opts.accountOut, JSON.stringify({
|
|
357
|
+
name: result.name,
|
|
358
|
+
email: result.email,
|
|
359
|
+
password: profile.password,
|
|
360
|
+
apiKey: result.apiKey,
|
|
361
|
+
baseUrl: result.baseUrl,
|
|
362
|
+
balance: result.balance,
|
|
363
|
+
status: result.status,
|
|
364
|
+
}));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
printResult(result, opts);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
main().catch(error => {
|
|
371
|
+
const message = error instanceof ApiError && error.response?.data?.code
|
|
372
|
+
? `${error.message} [${error.response.data.code}]`
|
|
373
|
+
: error.message;
|
|
374
|
+
console.error(`error=${message}`);
|
|
375
|
+
process.exitCode = 1;
|
|
376
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gelglx/arjunakey",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Single-account CLI for OneStore registration, welcome-code claiming, and API-key retrieval",
|
|
5
|
+
"bin": {
|
|
6
|
+
"arjunakey": "cli.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"cli.js",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "node tests/smoke.js"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18"
|
|
17
|
+
},
|
|
18
|
+
"preferGlobal": true,
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"arjuna",
|
|
25
|
+
"onestore",
|
|
26
|
+
"api-key",
|
|
27
|
+
"cli",
|
|
28
|
+
"ai-gateway"
|
|
29
|
+
]
|
|
30
|
+
}
|