@alva-ai/toolkit 0.1.4 → 0.2.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/browser.global.js +1 -1
- package/dist/browser.global.js.map +1 -1
- package/dist/cli.js +305 -50
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +18 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -1
- package/dist/index.d.ts +35 -1
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,14 @@ var AlvaError = class extends Error {
|
|
|
11
11
|
this.status = status;
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
|
+
var CliUsageError = class extends Error {
|
|
15
|
+
command;
|
|
16
|
+
constructor(message, command) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = "CliUsageError";
|
|
19
|
+
this.command = command;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
14
22
|
|
|
15
23
|
// src/resources/fs.ts
|
|
16
24
|
var FsResource = class {
|
|
@@ -200,6 +208,23 @@ var DeployResource = class {
|
|
|
200
208
|
`/api/v1/deploy/cronjob/${params.id}/resume`
|
|
201
209
|
);
|
|
202
210
|
}
|
|
211
|
+
async listRuns(params) {
|
|
212
|
+
this.client._requireAuth();
|
|
213
|
+
return this.client._request(
|
|
214
|
+
"GET",
|
|
215
|
+
`/api/v1/deploy/cronjob/${params.cronjob_id}/runs`,
|
|
216
|
+
{
|
|
217
|
+
query: { first: params.first, cursor: params.cursor }
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
async getRunLogs(params) {
|
|
222
|
+
this.client._requireAuth();
|
|
223
|
+
return this.client._request(
|
|
224
|
+
"GET",
|
|
225
|
+
`/api/v1/deploy/cronjob/${params.cronjob_id}/runs/${params.run_id}/logs`
|
|
226
|
+
);
|
|
227
|
+
}
|
|
203
228
|
};
|
|
204
229
|
|
|
205
230
|
// src/resources/release.ts
|
|
@@ -681,16 +706,16 @@ function parseFlag(argv, flag) {
|
|
|
681
706
|
return void 0;
|
|
682
707
|
}
|
|
683
708
|
function loadConfig(deps) {
|
|
684
|
-
const { argv, env, readFile:
|
|
709
|
+
const { argv, env, readFile: readFile3, homedir: homedir3 } = deps;
|
|
685
710
|
const profileName = parseFlag(argv, "--profile") || env.ALVA_PROFILE || "default";
|
|
686
711
|
const baseUrlFlag = parseFlag(argv, "--base-url");
|
|
687
712
|
const baseUrlEnv = env.ALVA_ENDPOINT;
|
|
688
713
|
const apiKeyFlag = parseFlag(argv, "--api-key");
|
|
689
714
|
const apiKeyEnv = env.ALVA_API_KEY;
|
|
690
715
|
let fileProfile = {};
|
|
691
|
-
const path = configPath({ env, homedir:
|
|
716
|
+
const path = configPath({ env, homedir: homedir3 });
|
|
692
717
|
try {
|
|
693
|
-
const raw =
|
|
718
|
+
const raw = readFile3(path);
|
|
694
719
|
let config;
|
|
695
720
|
try {
|
|
696
721
|
config = readConfigFile(raw);
|
|
@@ -710,11 +735,135 @@ function loadConfig(deps) {
|
|
|
710
735
|
};
|
|
711
736
|
}
|
|
712
737
|
|
|
713
|
-
// src/cli/
|
|
714
|
-
import * as
|
|
738
|
+
// src/cli/auth.ts
|
|
739
|
+
import * as crypto from "crypto";
|
|
740
|
+
import * as http from "http";
|
|
741
|
+
import { exec } from "child_process";
|
|
715
742
|
import * as os from "os";
|
|
716
743
|
import * as fsPromises from "fs/promises";
|
|
717
|
-
|
|
744
|
+
function generateState() {
|
|
745
|
+
return crypto.randomBytes(32).toString("hex");
|
|
746
|
+
}
|
|
747
|
+
function parseFlags(argv) {
|
|
748
|
+
const flags = {};
|
|
749
|
+
for (let i = 0; i < argv.length; i++) {
|
|
750
|
+
const arg = argv[i];
|
|
751
|
+
if (arg.startsWith("--")) {
|
|
752
|
+
const eqIdx = arg.indexOf("=");
|
|
753
|
+
if (eqIdx !== -1) {
|
|
754
|
+
flags[arg.slice(2, eqIdx)] = arg.slice(eqIdx + 1);
|
|
755
|
+
} else if (i + 1 < argv.length && !argv[i + 1].startsWith("--")) {
|
|
756
|
+
flags[arg.slice(2)] = argv[i + 1];
|
|
757
|
+
i++;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return flags;
|
|
762
|
+
}
|
|
763
|
+
function defaultOpenBrowser(url) {
|
|
764
|
+
return new Promise((resolve) => {
|
|
765
|
+
const platform = process.platform;
|
|
766
|
+
let cmd;
|
|
767
|
+
if (platform === "darwin") {
|
|
768
|
+
cmd = `open "${url}"`;
|
|
769
|
+
} else if (platform === "win32") {
|
|
770
|
+
cmd = `start "${url}"`;
|
|
771
|
+
} else {
|
|
772
|
+
cmd = `xdg-open "${url}"`;
|
|
773
|
+
}
|
|
774
|
+
exec(cmd, () => {
|
|
775
|
+
resolve();
|
|
776
|
+
});
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
function defaultDeps() {
|
|
780
|
+
return {
|
|
781
|
+
generateState,
|
|
782
|
+
openBrowser: defaultOpenBrowser,
|
|
783
|
+
writeConfigDeps: {
|
|
784
|
+
env: process.env,
|
|
785
|
+
homedir: () => os.homedir(),
|
|
786
|
+
mkdir: (path, options) => fsPromises.mkdir(path, options).then(() => void 0),
|
|
787
|
+
writeFile: (path, data, options) => fsPromises.writeFile(path, data, options).then(() => void 0),
|
|
788
|
+
readFile: (path) => fsPromises.readFile(path, "utf-8")
|
|
789
|
+
},
|
|
790
|
+
createServer: (handler) => http.createServer(handler),
|
|
791
|
+
timeout: 12e4,
|
|
792
|
+
log: (msg) => process.stderr.write(msg)
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
async function handleAuthLogin(args, deps) {
|
|
796
|
+
const d = { ...defaultDeps(), ...deps };
|
|
797
|
+
const flags = parseFlags(args.slice(1));
|
|
798
|
+
const profileName = flags.profile || "default";
|
|
799
|
+
const authUrl = flags["auth-url"] || "https://alva.ai";
|
|
800
|
+
const timeout = d.timeout ?? 12e4;
|
|
801
|
+
const state = d.generateState();
|
|
802
|
+
return new Promise((resolve, reject) => {
|
|
803
|
+
const server = d.createServer((req, res) => {
|
|
804
|
+
const reqUrl = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
805
|
+
if (reqUrl.pathname !== "/callback") {
|
|
806
|
+
res.writeHead(404);
|
|
807
|
+
res.end("Not found");
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
const callbackState = reqUrl.searchParams.get("state");
|
|
811
|
+
const apiKey = reqUrl.searchParams.get("api_key");
|
|
812
|
+
if (callbackState !== state) {
|
|
813
|
+
res.writeHead(400);
|
|
814
|
+
res.end(
|
|
815
|
+
"<html><body><h1>Error</h1><p>State mismatch. Please try again.</p></body></html>"
|
|
816
|
+
);
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
if (!apiKey) {
|
|
820
|
+
res.writeHead(400);
|
|
821
|
+
res.end(
|
|
822
|
+
"<html><body><h1>Error</h1><p>Missing API key. Please try again.</p></body></html>"
|
|
823
|
+
);
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
827
|
+
res.end(
|
|
828
|
+
`<html><body style="display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:rgba(246,246,246,1);font-family:system-ui,sans-serif"><div style="text-align:center;display:flex;flex-direction:column;align-items:center;gap:40px"><h1 style="font-size:45px;font-weight:400;line-height:120%;margin:0">Turn Ideas into Live<br>Investing Playbooks in Minutes</h1><p style="font-size:24px;font-weight:400;margin:0">You're all set for Alva.</p></div></body></html>`
|
|
829
|
+
);
|
|
830
|
+
server.close();
|
|
831
|
+
clearTimeout(timer);
|
|
832
|
+
writeConfig({ apiKey }, d.writeConfigDeps, profileName).then(() => {
|
|
833
|
+
resolve({ status: "logged_in", apiKey, profile: profileName });
|
|
834
|
+
}, reject);
|
|
835
|
+
});
|
|
836
|
+
server.on("error", (err) => {
|
|
837
|
+
clearTimeout(timer);
|
|
838
|
+
reject(err);
|
|
839
|
+
});
|
|
840
|
+
server.listen(0, "127.0.0.1", () => {
|
|
841
|
+
const addr = server.address();
|
|
842
|
+
const callbackUrl = `http://127.0.0.1:${addr.port}/callback`;
|
|
843
|
+
const loginUrl = `${authUrl}/authorize?callback_url=${encodeURIComponent(callbackUrl)}&state=${state}`;
|
|
844
|
+
d.log(
|
|
845
|
+
`Opening browser...
|
|
846
|
+
If it doesn't open, visit:
|
|
847
|
+
${loginUrl}
|
|
848
|
+
|
|
849
|
+
Waiting for login callback...
|
|
850
|
+
`
|
|
851
|
+
);
|
|
852
|
+
d.openBrowser(loginUrl).catch(() => {
|
|
853
|
+
});
|
|
854
|
+
});
|
|
855
|
+
const timer = setTimeout(() => {
|
|
856
|
+
server.close();
|
|
857
|
+
reject(new Error("Login timed out waiting for callback"));
|
|
858
|
+
}, timeout);
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// src/cli/index.ts
|
|
863
|
+
import * as fs from "fs";
|
|
864
|
+
import * as os2 from "os";
|
|
865
|
+
import * as fsPromises2 from "fs/promises";
|
|
866
|
+
var CLI_VERSION = true ? "0.2.0" : "dev";
|
|
718
867
|
function isVersionOlderThan(a, b) {
|
|
719
868
|
const parse = (v) => {
|
|
720
869
|
if (!v) return null;
|
|
@@ -747,6 +896,7 @@ Commands:
|
|
|
747
896
|
comments Playbook comments (create, pin, unpin)
|
|
748
897
|
remix Save playbook remix lineage
|
|
749
898
|
trading Trading operations (accounts, portfolio, orders, subscriptions, equity-history, risk-rules, subscribe, unsubscribe, execute, update-risk-rules)
|
|
899
|
+
auth Authentication (login via browser)
|
|
750
900
|
screenshot Capture a web screenshot as PNG
|
|
751
901
|
|
|
752
902
|
Global options:
|
|
@@ -790,6 +940,14 @@ Examples:
|
|
|
790
940
|
alva configure --api-key alva_abc123 --base-url http://localhost:8080
|
|
791
941
|
alva configure --profile staging --api-key alva_stg_key --base-url https://api-llm.stg.alva.ai
|
|
792
942
|
alva --profile staging whoami`,
|
|
943
|
+
auth: `Usage: alva auth <subcommand>
|
|
944
|
+
|
|
945
|
+
Subcommands:
|
|
946
|
+
login Open browser to authenticate and save credentials
|
|
947
|
+
|
|
948
|
+
Examples:
|
|
949
|
+
alva auth login
|
|
950
|
+
alva auth login --profile staging`,
|
|
793
951
|
whoami: `Usage: alva whoami [--profile <name>]
|
|
794
952
|
|
|
795
953
|
Verify that your credentials are valid by calling the Alva API. Shows your
|
|
@@ -877,11 +1035,13 @@ data SDKs, ALFS, HTTP networking, and the Feed SDK.
|
|
|
877
1035
|
|
|
878
1036
|
Options:
|
|
879
1037
|
--code <code> Inline JavaScript code to execute
|
|
1038
|
+
--local-file <path> Path to a local file whose contents are sent as code
|
|
880
1039
|
--entry-path <path> Path to a script file on ALFS (home-relative)
|
|
881
1040
|
--working-dir <dir> Working directory for require() (inline code only)
|
|
882
1041
|
--args <json> JSON object passed to require("env").args
|
|
883
1042
|
|
|
884
|
-
At least one of --code or --entry-path is required.
|
|
1043
|
+
At least one of --code, --local-file, or --entry-path is required.
|
|
1044
|
+
These three options are mutually exclusive.
|
|
885
1045
|
|
|
886
1046
|
Response fields:
|
|
887
1047
|
result JSON-encoded return value of the script
|
|
@@ -908,7 +1068,8 @@ Examples:
|
|
|
908
1068
|
alva run --code "1 + 2 + 3;"
|
|
909
1069
|
alva run --code "JSON.stringify(require('env').args);" --args '{"symbol":"BTC"}'
|
|
910
1070
|
alva run --entry-path ~/feeds/my-feed/v1/src/index.js
|
|
911
|
-
alva run --entry-path ~/tasks/analyze/src/index.js --args '{"symbol":"NVDA","limit":50}'
|
|
1071
|
+
alva run --entry-path ~/tasks/analyze/src/index.js --args '{"symbol":"NVDA","limit":50}'
|
|
1072
|
+
alva run --local-file ./my-script.js --args '{"symbol":"BTC"}'`,
|
|
912
1073
|
deploy: `Usage: alva deploy <subcommand> [options]
|
|
913
1074
|
|
|
914
1075
|
Manage scheduled cronjobs that run your scripts on a cron schedule.
|
|
@@ -957,7 +1118,10 @@ Examples:
|
|
|
957
1118
|
alva deploy update --id 42 --cron "0 */2 * * *" --no-push-notify
|
|
958
1119
|
alva deploy pause --id 42
|
|
959
1120
|
alva deploy resume --id 42
|
|
960
|
-
alva deploy delete --id 42
|
|
1121
|
+
alva deploy delete --id 42
|
|
1122
|
+
alva deploy runs --id 42
|
|
1123
|
+
alva deploy runs --id 42 --first 10
|
|
1124
|
+
alva deploy run-logs --id 42 --run-id 123`,
|
|
961
1125
|
release: `Usage: alva release <subcommand> [options]
|
|
962
1126
|
|
|
963
1127
|
Publish feeds and playbooks to the Alva platform. The typical workflow:
|
|
@@ -1187,12 +1351,10 @@ Examples:
|
|
|
1187
1351
|
alva trading update-risk-rules --max-single-order-value 10000 --max-single-order-enabled true --max-daily-turnover-value 50000 --max-daily-turnover-enabled true --max-daily-orders-value 100 --max-daily-orders-enabled true`
|
|
1188
1352
|
};
|
|
1189
1353
|
async function handleConfigure(args, deps) {
|
|
1190
|
-
const flags =
|
|
1354
|
+
const flags = parseFlags2(args.slice(1));
|
|
1191
1355
|
const apiKey = flags["api-key"];
|
|
1192
1356
|
if (!apiKey) {
|
|
1193
|
-
throw new
|
|
1194
|
-
"--api-key is required. Usage: alva configure --api-key <key> [--base-url <url>] [--profile <name>]"
|
|
1195
|
-
);
|
|
1357
|
+
throw new CliUsageError("--api-key is required", "configure");
|
|
1196
1358
|
}
|
|
1197
1359
|
if (!apiKey.startsWith("alva_")) {
|
|
1198
1360
|
process.stderr?.write?.(
|
|
@@ -1205,10 +1367,10 @@ async function handleConfigure(args, deps) {
|
|
|
1205
1367
|
if (baseUrl) configInput.baseUrl = baseUrl;
|
|
1206
1368
|
const writeDeps = deps ?? {
|
|
1207
1369
|
env: process.env,
|
|
1208
|
-
homedir: () =>
|
|
1209
|
-
mkdir: (path, options) =>
|
|
1210
|
-
writeFile: (path, data, options) =>
|
|
1211
|
-
readFile: (path) =>
|
|
1370
|
+
homedir: () => os2.homedir(),
|
|
1371
|
+
mkdir: (path, options) => fsPromises2.mkdir(path, options).then(() => void 0),
|
|
1372
|
+
writeFile: (path, data, options) => fsPromises2.writeFile(path, data, options).then(() => void 0),
|
|
1373
|
+
readFile: (path) => fsPromises2.readFile(path, "utf-8")
|
|
1212
1374
|
};
|
|
1213
1375
|
const result = await writeConfig(configInput, writeDeps, profileName);
|
|
1214
1376
|
return {
|
|
@@ -1226,7 +1388,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
1226
1388
|
"execute-latest",
|
|
1227
1389
|
"dry-run"
|
|
1228
1390
|
]);
|
|
1229
|
-
function
|
|
1391
|
+
function parseFlags2(argv) {
|
|
1230
1392
|
const flags = {};
|
|
1231
1393
|
for (let i = 0; i < argv.length; i++) {
|
|
1232
1394
|
const arg = argv[i];
|
|
@@ -1254,7 +1416,8 @@ function boolFlag(val) {
|
|
|
1254
1416
|
function requireFlag(flags, name, command) {
|
|
1255
1417
|
const val = flags[name];
|
|
1256
1418
|
if (val === void 0) {
|
|
1257
|
-
|
|
1419
|
+
const group = command.split(" ")[0];
|
|
1420
|
+
throw new CliUsageError(`--${name} is required for '${command}'`, group);
|
|
1258
1421
|
}
|
|
1259
1422
|
return val;
|
|
1260
1423
|
}
|
|
@@ -1262,8 +1425,10 @@ function requireNumericFlag(flags, name, command) {
|
|
|
1262
1425
|
const val = requireFlag(flags, name, command);
|
|
1263
1426
|
const n = Number(val);
|
|
1264
1427
|
if (Number.isNaN(n)) {
|
|
1265
|
-
|
|
1266
|
-
|
|
1428
|
+
const group = command.split(" ")[0];
|
|
1429
|
+
throw new CliUsageError(
|
|
1430
|
+
`--${name} must be a number for '${command}', got '${val}'`,
|
|
1431
|
+
group
|
|
1267
1432
|
);
|
|
1268
1433
|
}
|
|
1269
1434
|
return n;
|
|
@@ -1307,7 +1472,7 @@ async function dispatch(client, args, meta) {
|
|
|
1307
1472
|
return result;
|
|
1308
1473
|
}
|
|
1309
1474
|
const subcommand = args[1];
|
|
1310
|
-
const flags =
|
|
1475
|
+
const flags = parseFlags2(
|
|
1311
1476
|
args.slice(
|
|
1312
1477
|
group === "run" || group === "remix" || group === "screenshot" ? 1 : 2
|
|
1313
1478
|
)
|
|
@@ -1318,11 +1483,13 @@ async function dispatch(client, args, meta) {
|
|
|
1318
1483
|
}
|
|
1319
1484
|
switch (group) {
|
|
1320
1485
|
case "user":
|
|
1321
|
-
if (!subcommand)
|
|
1486
|
+
if (!subcommand)
|
|
1487
|
+
throw new CliUsageError("Missing subcommand for user", "user");
|
|
1322
1488
|
if (subcommand === "me") return client.user.me();
|
|
1323
|
-
throw new
|
|
1489
|
+
throw new CliUsageError(`Unknown subcommand: user ${subcommand}`, "user");
|
|
1324
1490
|
case "fs": {
|
|
1325
|
-
if (!subcommand)
|
|
1491
|
+
if (!subcommand)
|
|
1492
|
+
throw new CliUsageError("Missing subcommand for fs", "fs");
|
|
1326
1493
|
switch (subcommand) {
|
|
1327
1494
|
case "read":
|
|
1328
1495
|
return client.fs.read({
|
|
@@ -1399,18 +1566,33 @@ async function dispatch(client, args, meta) {
|
|
|
1399
1566
|
permission: requireFlag(flags, "permission", "fs revoke")
|
|
1400
1567
|
});
|
|
1401
1568
|
default:
|
|
1402
|
-
throw new
|
|
1569
|
+
throw new CliUsageError(`Unknown subcommand: fs ${subcommand}`, "fs");
|
|
1403
1570
|
}
|
|
1404
1571
|
}
|
|
1405
|
-
case "run":
|
|
1572
|
+
case "run": {
|
|
1573
|
+
const sourceFlags = ["code", "local-file", "entry-path"].filter(
|
|
1574
|
+
(f) => flags[f] !== void 0
|
|
1575
|
+
);
|
|
1576
|
+
if (sourceFlags.length > 1) {
|
|
1577
|
+
throw new CliUsageError(
|
|
1578
|
+
`--${sourceFlags.join(" and --")} are mutually exclusive`,
|
|
1579
|
+
"run"
|
|
1580
|
+
);
|
|
1581
|
+
}
|
|
1582
|
+
let code = flags["code"];
|
|
1583
|
+
if (flags["local-file"]) {
|
|
1584
|
+
code = fs.readFileSync(flags["local-file"], "utf-8");
|
|
1585
|
+
}
|
|
1406
1586
|
return client.run.execute({
|
|
1407
|
-
code
|
|
1587
|
+
code,
|
|
1408
1588
|
entry_path: flags["entry-path"],
|
|
1409
1589
|
working_dir: flags["working-dir"],
|
|
1410
1590
|
args: jsonParse(flags["args"])
|
|
1411
1591
|
});
|
|
1592
|
+
}
|
|
1412
1593
|
case "deploy": {
|
|
1413
|
-
if (!subcommand)
|
|
1594
|
+
if (!subcommand)
|
|
1595
|
+
throw new CliUsageError("Missing subcommand for deploy", "deploy");
|
|
1414
1596
|
switch (subcommand) {
|
|
1415
1597
|
case "create":
|
|
1416
1598
|
return client.deploy.create({
|
|
@@ -1449,12 +1631,27 @@ async function dispatch(client, args, meta) {
|
|
|
1449
1631
|
return client.deploy.resume({
|
|
1450
1632
|
id: requireNumericFlag(flags, "id", "deploy resume")
|
|
1451
1633
|
});
|
|
1634
|
+
case "runs":
|
|
1635
|
+
return client.deploy.listRuns({
|
|
1636
|
+
cronjob_id: requireNumericFlag(flags, "id", "deploy runs"),
|
|
1637
|
+
first: num(flags["first"]),
|
|
1638
|
+
cursor: num(flags["cursor"])
|
|
1639
|
+
});
|
|
1640
|
+
case "run-logs":
|
|
1641
|
+
return client.deploy.getRunLogs({
|
|
1642
|
+
cronjob_id: requireNumericFlag(flags, "id", "deploy run-logs"),
|
|
1643
|
+
run_id: requireNumericFlag(flags, "run-id", "deploy run-logs")
|
|
1644
|
+
});
|
|
1452
1645
|
default:
|
|
1453
|
-
throw new
|
|
1646
|
+
throw new CliUsageError(
|
|
1647
|
+
`Unknown subcommand: deploy ${subcommand}`,
|
|
1648
|
+
"deploy"
|
|
1649
|
+
);
|
|
1454
1650
|
}
|
|
1455
1651
|
}
|
|
1456
1652
|
case "release": {
|
|
1457
|
-
if (!subcommand)
|
|
1653
|
+
if (!subcommand)
|
|
1654
|
+
throw new CliUsageError("Missing subcommand for release", "release");
|
|
1458
1655
|
switch (subcommand) {
|
|
1459
1656
|
case "feed":
|
|
1460
1657
|
return client.release.feed({
|
|
@@ -1493,11 +1690,15 @@ async function dispatch(client, args, meta) {
|
|
|
1493
1690
|
changelog: requireFlag(flags, "changelog", "release playbook")
|
|
1494
1691
|
});
|
|
1495
1692
|
default:
|
|
1496
|
-
throw new
|
|
1693
|
+
throw new CliUsageError(
|
|
1694
|
+
`Unknown subcommand: release ${subcommand}`,
|
|
1695
|
+
"release"
|
|
1696
|
+
);
|
|
1497
1697
|
}
|
|
1498
1698
|
}
|
|
1499
1699
|
case "secrets": {
|
|
1500
|
-
if (!subcommand)
|
|
1700
|
+
if (!subcommand)
|
|
1701
|
+
throw new CliUsageError("Missing subcommand for secrets", "secrets");
|
|
1501
1702
|
switch (subcommand) {
|
|
1502
1703
|
case "create":
|
|
1503
1704
|
return client.secrets.create({
|
|
@@ -1520,11 +1721,15 @@ async function dispatch(client, args, meta) {
|
|
|
1520
1721
|
name: requireFlag(flags, "name", "secrets delete")
|
|
1521
1722
|
});
|
|
1522
1723
|
default:
|
|
1523
|
-
throw new
|
|
1724
|
+
throw new CliUsageError(
|
|
1725
|
+
`Unknown subcommand: secrets ${subcommand}`,
|
|
1726
|
+
"secrets"
|
|
1727
|
+
);
|
|
1524
1728
|
}
|
|
1525
1729
|
}
|
|
1526
1730
|
case "sdk": {
|
|
1527
|
-
if (!subcommand)
|
|
1731
|
+
if (!subcommand)
|
|
1732
|
+
throw new CliUsageError("Missing subcommand for sdk", "sdk");
|
|
1528
1733
|
switch (subcommand) {
|
|
1529
1734
|
case "doc":
|
|
1530
1735
|
return client.sdk.doc({
|
|
@@ -1537,11 +1742,15 @@ async function dispatch(client, args, meta) {
|
|
|
1537
1742
|
partition: requireFlag(flags, "partition", "sdk partition-summary")
|
|
1538
1743
|
});
|
|
1539
1744
|
default:
|
|
1540
|
-
throw new
|
|
1745
|
+
throw new CliUsageError(
|
|
1746
|
+
`Unknown subcommand: sdk ${subcommand}`,
|
|
1747
|
+
"sdk"
|
|
1748
|
+
);
|
|
1541
1749
|
}
|
|
1542
1750
|
}
|
|
1543
1751
|
case "comments": {
|
|
1544
|
-
if (!subcommand)
|
|
1752
|
+
if (!subcommand)
|
|
1753
|
+
throw new CliUsageError("Missing subcommand for comments", "comments");
|
|
1545
1754
|
switch (subcommand) {
|
|
1546
1755
|
case "create":
|
|
1547
1756
|
return client.comments.create({
|
|
@@ -1563,7 +1772,10 @@ async function dispatch(client, args, meta) {
|
|
|
1563
1772
|
)
|
|
1564
1773
|
});
|
|
1565
1774
|
default:
|
|
1566
|
-
throw new
|
|
1775
|
+
throw new CliUsageError(
|
|
1776
|
+
`Unknown subcommand: comments ${subcommand}`,
|
|
1777
|
+
"comments"
|
|
1778
|
+
);
|
|
1567
1779
|
}
|
|
1568
1780
|
}
|
|
1569
1781
|
case "remix":
|
|
@@ -1586,7 +1798,8 @@ async function dispatch(client, args, meta) {
|
|
|
1586
1798
|
return { written: outFile, bytes: buf.length };
|
|
1587
1799
|
}
|
|
1588
1800
|
case "trading": {
|
|
1589
|
-
if (!subcommand)
|
|
1801
|
+
if (!subcommand)
|
|
1802
|
+
throw new CliUsageError("Missing subcommand for trading", "trading");
|
|
1590
1803
|
switch (subcommand) {
|
|
1591
1804
|
case "accounts":
|
|
1592
1805
|
return client.trading.accounts();
|
|
@@ -1687,13 +1900,21 @@ async function dispatch(client, args, meta) {
|
|
|
1687
1900
|
}
|
|
1688
1901
|
});
|
|
1689
1902
|
default:
|
|
1690
|
-
throw new
|
|
1903
|
+
throw new CliUsageError(
|
|
1904
|
+
`Unknown subcommand: trading ${subcommand}`,
|
|
1905
|
+
"trading"
|
|
1906
|
+
);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
case "auth": {
|
|
1910
|
+
const authSub = args[1];
|
|
1911
|
+
if (!authSub || authSub === "--help" || authSub === "-h" || args[2] === "--help" || args[2] === "-h") {
|
|
1912
|
+
return { _help: true, text: COMMAND_HELP.auth };
|
|
1691
1913
|
}
|
|
1914
|
+
throw new CliUsageError(`Unknown auth subcommand: '${authSub}'`, "auth");
|
|
1692
1915
|
}
|
|
1693
1916
|
default:
|
|
1694
|
-
throw new
|
|
1695
|
-
`Unknown command: '${group}'. Run 'alva --help' to see available commands.`
|
|
1696
|
-
);
|
|
1917
|
+
throw new CliUsageError(`Unknown command: '${group}'`);
|
|
1697
1918
|
}
|
|
1698
1919
|
}
|
|
1699
1920
|
async function main() {
|
|
@@ -1713,11 +1934,28 @@ async function main() {
|
|
|
1713
1934
|
process.stdout.write(JSON.stringify(result2, null, 2) + "\n");
|
|
1714
1935
|
return;
|
|
1715
1936
|
}
|
|
1937
|
+
if (rawArgs[0] === "auth") {
|
|
1938
|
+
const authSub = rawArgs[1];
|
|
1939
|
+
if (!authSub || authSub === "--help" || authSub === "-h" || rawArgs[2] === "--help" || rawArgs[2] === "-h") {
|
|
1940
|
+
process.stdout.write(`${COMMAND_HELP.auth}
|
|
1941
|
+
`);
|
|
1942
|
+
return;
|
|
1943
|
+
}
|
|
1944
|
+
if (authSub === "login") {
|
|
1945
|
+
const result2 = await handleAuthLogin(rawArgs);
|
|
1946
|
+
process.stdout.write(`${JSON.stringify(result2, null, 2)}
|
|
1947
|
+
`);
|
|
1948
|
+
return;
|
|
1949
|
+
}
|
|
1950
|
+
process.stdout.write(`${COMMAND_HELP.auth}
|
|
1951
|
+
`);
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1716
1954
|
const config = loadConfig({
|
|
1717
1955
|
argv: rawArgs,
|
|
1718
1956
|
env: process.env,
|
|
1719
1957
|
readFile: (path) => fs.readFileSync(path, "utf-8"),
|
|
1720
|
-
homedir: () =>
|
|
1958
|
+
homedir: () => os2.homedir()
|
|
1721
1959
|
});
|
|
1722
1960
|
const client = new AlvaClient({
|
|
1723
1961
|
apiKey: config.apiKey,
|
|
@@ -1759,12 +1997,29 @@ async function main() {
|
|
|
1759
1997
|
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
1760
1998
|
}
|
|
1761
1999
|
} catch (err) {
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
2000
|
+
if (err instanceof CliUsageError) {
|
|
2001
|
+
const help = err.command ? COMMAND_HELP[err.command] : HELP_TEXT;
|
|
2002
|
+
process.stderr.write(`Error: ${err.message}
|
|
2003
|
+
`);
|
|
2004
|
+
if (help) process.stderr.write(`
|
|
2005
|
+
${help}
|
|
2006
|
+
`);
|
|
2007
|
+
process.exit(1);
|
|
2008
|
+
} else if (err instanceof AlvaError) {
|
|
2009
|
+
const error = {
|
|
2010
|
+
code: err.code,
|
|
2011
|
+
message: err.message,
|
|
2012
|
+
status: err.status
|
|
2013
|
+
};
|
|
2014
|
+
process.stderr.write(`${JSON.stringify({ error }, null, 2)}
|
|
2015
|
+
`);
|
|
2016
|
+
process.exit(1);
|
|
2017
|
+
} else {
|
|
2018
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2019
|
+
process.stderr.write(`Error: ${message}
|
|
2020
|
+
`);
|
|
2021
|
+
process.exit(1);
|
|
2022
|
+
}
|
|
1768
2023
|
}
|
|
1769
2024
|
}
|
|
1770
2025
|
var isDirectRun = typeof process !== "undefined" && process.argv[1] && (process.argv[1].endsWith("cli.mjs") || process.argv[1].endsWith("cli.js") || process.argv[1].endsWith("/alva") || process.argv[1].endsWith("\\alva"));
|