@tangle-network/tcloud 0.2.0 → 0.4.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/dist/{chunk-HL4CXKET.js → chunk-AKR7CS4P.js} +231 -30
- package/dist/{chunk-VD4RNZOC.js → chunk-MKLCBBHZ.js} +1 -1
- package/dist/{chunk-STNZT6YR.js → chunk-QNIJ7KAA.js} +2 -2
- package/dist/cli.cjs +368 -54
- package/dist/cli.js +141 -27
- package/dist/{client-CcuHG7_w.d.ts → client-_ghO89WM.d.cts} +402 -13
- package/dist/{client-CcuHG7_w.d.cts → client-_ghO89WM.d.ts} +402 -13
- package/dist/index.cjs +232 -30
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5 -3
- package/dist/instance.cjs +230 -30
- package/dist/instance.d.cts +1 -1
- package/dist/instance.d.ts +1 -1
- package/dist/instance.js +1 -1
- package/dist/shielded.cjs +230 -30
- package/dist/shielded.d.cts +1 -1
- package/dist/shielded.d.ts +1 -1
- package/dist/shielded.js +2 -2
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
TCloud
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QNIJ7KAA.js";
|
|
5
5
|
import {
|
|
6
6
|
generateWallet
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-MKLCBBHZ.js";
|
|
8
|
+
import "./chunk-AKR7CS4P.js";
|
|
9
9
|
|
|
10
10
|
// src/cli.ts
|
|
11
11
|
import { Command } from "commander";
|
|
12
12
|
import * as fs from "fs";
|
|
13
13
|
import * as path from "path";
|
|
14
14
|
import * as readline from "readline";
|
|
15
|
+
import { spawn } from "child_process";
|
|
15
16
|
var CONFIG_DIR = path.join(process.env.HOME || "~", ".tcloud");
|
|
16
17
|
var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
17
18
|
var WALLETS_FILE = path.join(CONFIG_DIR, "wallets.json");
|
|
@@ -60,23 +61,52 @@ program.command("config").description("View or update configuration").option("--
|
|
|
60
61
|
console.log(JSON.stringify(c, null, 2));
|
|
61
62
|
});
|
|
62
63
|
var auth = program.command("auth").description("Authentication");
|
|
63
|
-
|
|
64
|
+
function openBrowser(url) {
|
|
65
|
+
if (process.env.NO_BROWSER || process.env.CI) return false;
|
|
66
|
+
if (!process.stdout.isTTY) return false;
|
|
67
|
+
try {
|
|
68
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
69
|
+
const child = spawn(cmd, [url], { stdio: "ignore", detached: true });
|
|
70
|
+
child.unref();
|
|
71
|
+
return true;
|
|
72
|
+
} catch {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
77
|
+
async function runDeviceFlow(mode) {
|
|
64
78
|
const config = loadConfig();
|
|
79
|
+
const initRes = await fetch(`${config.apiUrl}/api/auth/device`, { method: "POST" });
|
|
80
|
+
if (!initRes.ok) {
|
|
81
|
+
console.error(`
|
|
82
|
+
\u2717 Auth server returned ${initRes.status}.`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
const d = await initRes.json();
|
|
86
|
+
const urlWithCode = `${d.verification_url}?user_code=${encodeURIComponent(d.user_code)}`;
|
|
87
|
+
const opened = openBrowser(urlWithCode);
|
|
88
|
+
const header = mode === "signup" ? "Creating your Tangle account" : "Signing you in";
|
|
89
|
+
console.log(`
|
|
90
|
+
${header}
|
|
91
|
+
`);
|
|
92
|
+
console.log(` ${opened ? "Browser opened:" : "Open this URL:"}`);
|
|
93
|
+
console.log(` ${urlWithCode}
|
|
94
|
+
`);
|
|
95
|
+
console.log(` Verification code: ${d.user_code}
|
|
96
|
+
`);
|
|
97
|
+
const deadline = Date.now() + (d.expires_in || 600) * 1e3;
|
|
98
|
+
const interval = Math.max(2, d.interval || 5) * 1e3;
|
|
99
|
+
const spinnerEnabled = process.stdout.isTTY && !process.env.CI;
|
|
100
|
+
let frame = 0;
|
|
101
|
+
function tickSpinner() {
|
|
102
|
+
if (!spinnerEnabled) return;
|
|
103
|
+
const remaining = Math.max(0, Math.round((deadline - Date.now()) / 1e3));
|
|
104
|
+
process.stdout.write(`\r ${SPINNER_FRAMES[frame++ % SPINNER_FRAMES.length]} waiting for browser confirmation (${remaining}s remaining) `);
|
|
105
|
+
}
|
|
106
|
+
const spinnerTimer = spinnerEnabled ? setInterval(tickSpinner, 100) : null;
|
|
65
107
|
try {
|
|
66
|
-
const res = await fetch(`${config.apiUrl}/api/auth/device`, { method: "POST" });
|
|
67
|
-
if (!res.ok) {
|
|
68
|
-
console.error("Auth server error");
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
71
|
-
const d = await res.json();
|
|
72
|
-
console.log(`
|
|
73
|
-
Open: ${d.verification_url}
|
|
74
|
-
Code: ${d.user_code}
|
|
75
|
-
|
|
76
|
-
Waiting...`);
|
|
77
|
-
const deadline = Date.now() + (d.expires_in || 600) * 1e3;
|
|
78
108
|
while (Date.now() < deadline) {
|
|
79
|
-
await new Promise((r2) => setTimeout(r2,
|
|
109
|
+
await new Promise((r2) => setTimeout(r2, interval));
|
|
80
110
|
const r = await fetch(`${config.apiUrl}/api/auth/device/token`, {
|
|
81
111
|
method: "POST",
|
|
82
112
|
headers: { "Content-Type": "application/json" },
|
|
@@ -86,31 +116,112 @@ auth.command("login").description("Log in via browser (device flow)").action(asy
|
|
|
86
116
|
if (t.access_token) {
|
|
87
117
|
config.apiKey = t.access_token;
|
|
88
118
|
saveConfig(config);
|
|
89
|
-
|
|
119
|
+
if (spinnerTimer) {
|
|
120
|
+
clearInterval(spinnerTimer);
|
|
121
|
+
process.stdout.write("\r" + " ".repeat(80) + "\r");
|
|
122
|
+
}
|
|
123
|
+
console.log(` \u2713 Authenticated`);
|
|
124
|
+
console.log(` \u2713 API key saved to ${CONFIG_FILE}
|
|
125
|
+
`);
|
|
126
|
+
console.log(` Try it:`);
|
|
127
|
+
console.log(` tcloud whoami`);
|
|
128
|
+
console.log(` tcloud chat "hello world"
|
|
129
|
+
`);
|
|
90
130
|
return;
|
|
91
131
|
}
|
|
92
132
|
if (t.error === "expired_token") {
|
|
93
|
-
|
|
133
|
+
if (spinnerTimer) {
|
|
134
|
+
clearInterval(spinnerTimer);
|
|
135
|
+
process.stdout.write("\r" + " ".repeat(80) + "\r");
|
|
136
|
+
}
|
|
137
|
+
console.error(` \u2717 Code expired. Run 'tcloud auth ${mode}' again.`);
|
|
94
138
|
process.exit(1);
|
|
95
139
|
}
|
|
96
|
-
process.stdout.write(".");
|
|
97
140
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
141
|
+
if (spinnerTimer) {
|
|
142
|
+
clearInterval(spinnerTimer);
|
|
143
|
+
process.stdout.write("\r" + " ".repeat(80) + "\r");
|
|
144
|
+
}
|
|
145
|
+
console.error(` \u2717 Timed out after ${Math.round((d.expires_in || 600) / 60)} minutes.`);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
} finally {
|
|
148
|
+
if (spinnerTimer) clearInterval(spinnerTimer);
|
|
101
149
|
}
|
|
150
|
+
}
|
|
151
|
+
auth.command("signup").description("Create an account via browser (device flow)").action(() => runDeviceFlow("signup"));
|
|
152
|
+
auth.command("login").description("Log in via browser (device flow)").action(() => runDeviceFlow("login"));
|
|
153
|
+
auth.command("logout").description("Remove stored credentials").action(() => {
|
|
154
|
+
const c = loadConfig();
|
|
155
|
+
delete c.apiKey;
|
|
156
|
+
saveConfig(c);
|
|
157
|
+
console.log(` \u2713 Logged out. Config kept at ${CONFIG_FILE}.`);
|
|
102
158
|
});
|
|
103
159
|
auth.command("set-key").description("Set API key directly").argument("<key>").action((key) => {
|
|
104
160
|
const c = loadConfig();
|
|
105
161
|
c.apiKey = key;
|
|
106
162
|
saveConfig(c);
|
|
107
|
-
console.log("API key saved.");
|
|
163
|
+
console.log(" \u2713 API key saved.");
|
|
108
164
|
});
|
|
109
165
|
auth.command("status").description("Show auth status").action(() => {
|
|
110
166
|
const c = loadConfig();
|
|
111
|
-
console.log(c.apiKey ? `Authenticated: ${c.apiKey.slice(0, 15)}
|
|
167
|
+
console.log(c.apiKey ? ` \u2713 Authenticated: ${c.apiKey.slice(0, 15)}...${c.apiKey.slice(-4)}` : " \u2717 Not authenticated. Run: tcloud auth signup");
|
|
112
168
|
const w = loadWallets();
|
|
113
|
-
if (w.length) console.log(`Shielded wallets: ${w.length}`);
|
|
169
|
+
if (w.length) console.log(` Shielded wallets: ${w.length}`);
|
|
170
|
+
});
|
|
171
|
+
auth.command("whoami").description("Show logged-in account details").action(async () => {
|
|
172
|
+
const c = loadConfig();
|
|
173
|
+
if (!c.apiKey) {
|
|
174
|
+
console.log(" \u2717 Not authenticated. Run: tcloud auth signup");
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
const res = await fetch(`${c.apiUrl}/api/auth/userinfo`, {
|
|
179
|
+
headers: { Authorization: `Bearer ${c.apiKey}` }
|
|
180
|
+
});
|
|
181
|
+
if (!res.ok) {
|
|
182
|
+
console.log(` \u2717 Auth check failed (${res.status}). Your key may be revoked \u2014 run: tcloud auth login`);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const me = await res.json();
|
|
186
|
+
const user = me.user ?? {};
|
|
187
|
+
const sub = me.subscription;
|
|
188
|
+
console.log(` Email: ${user.email ?? "n/a"}`);
|
|
189
|
+
console.log(` User: ${user.name ?? user.id ?? "n/a"}`);
|
|
190
|
+
console.log(` Plan: ${sub?.plan ?? "free"}`);
|
|
191
|
+
console.log(` Balance: $${Number(me.balance ?? 0).toFixed(4)}`);
|
|
192
|
+
console.log(` Key: ${c.apiKey.slice(0, 15)}...${c.apiKey.slice(-4)}`);
|
|
193
|
+
console.log(` API: ${c.apiUrl}`);
|
|
194
|
+
} catch (e) {
|
|
195
|
+
console.log(` \u2717 ${e.message ?? e}`);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
program.command("signup").description("Create an account via browser (alias for `auth signup`)").action(() => runDeviceFlow("signup"));
|
|
199
|
+
program.command("login").description("Log in via browser (alias for `auth login`)").action(() => runDeviceFlow("login"));
|
|
200
|
+
program.command("logout").description("Remove stored credentials (alias for `auth logout`)").action(() => {
|
|
201
|
+
const c = loadConfig();
|
|
202
|
+
delete c.apiKey;
|
|
203
|
+
saveConfig(c);
|
|
204
|
+
console.log(` \u2713 Logged out.`);
|
|
205
|
+
});
|
|
206
|
+
program.command("whoami").description("Show logged-in account (alias for `auth whoami`)").action(async () => {
|
|
207
|
+
const c = loadConfig();
|
|
208
|
+
if (!c.apiKey) {
|
|
209
|
+
console.log(" \u2717 Not authenticated. Run: tcloud signup");
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
const res = await fetch(`${c.apiUrl}/api/auth/userinfo`, { headers: { Authorization: `Bearer ${c.apiKey}` } });
|
|
214
|
+
if (!res.ok) {
|
|
215
|
+
console.log(` \u2717 Auth failed (${res.status}). Run: tcloud login`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const me = await res.json();
|
|
219
|
+
const user = me.user ?? {};
|
|
220
|
+
const sub = me.subscription;
|
|
221
|
+
console.log(` ${user.email ?? user.name ?? user.id} \xB7 $${Number(me.balance ?? 0).toFixed(4)} \xB7 ${sub?.plan ?? "free"}`);
|
|
222
|
+
} catch (e) {
|
|
223
|
+
console.log(` \u2717 ${e.message ?? e}`);
|
|
224
|
+
}
|
|
114
225
|
});
|
|
115
226
|
var wallet = program.command("wallet").description("Shielded wallet management");
|
|
116
227
|
wallet.command("generate").description("Generate ephemeral wallet").option("-l, --label <name>").action((opts) => {
|
|
@@ -231,7 +342,10 @@ credits.command("add").description("Add credits").argument("<amount>").action(as
|
|
|
231
342
|
const client = getClient();
|
|
232
343
|
try {
|
|
233
344
|
const data = await client.addCredits(parseFloat(amount));
|
|
234
|
-
|
|
345
|
+
if (data.url) {
|
|
346
|
+
console.log(`Checkout URL: ${data.url}`);
|
|
347
|
+
console.log("Complete payment to add credits.");
|
|
348
|
+
}
|
|
235
349
|
} catch (e) {
|
|
236
350
|
console.error("Error:", e.message);
|
|
237
351
|
}
|