@vizzor/cli 0.6.0 → 0.7.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/index.js +512 -8
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -59,6 +59,17 @@ var init_schema = __esm({
|
|
|
59
59
|
sidecarUrl: "http://localhost:8000",
|
|
60
60
|
fallbackToRules: true
|
|
61
61
|
})),
|
|
62
|
+
api: z.object({
|
|
63
|
+
port: z.number().default(3e3),
|
|
64
|
+
host: z.string().default("0.0.0.0"),
|
|
65
|
+
enableAuth: z.boolean().default(false),
|
|
66
|
+
corsOrigin: z.string().default("*")
|
|
67
|
+
}).default(() => ({
|
|
68
|
+
port: 3e3,
|
|
69
|
+
host: "0.0.0.0",
|
|
70
|
+
enableAuth: false,
|
|
71
|
+
corsOrigin: "*"
|
|
72
|
+
})),
|
|
62
73
|
discordToken: z.string().optional(),
|
|
63
74
|
discordGuildId: z.string().optional(),
|
|
64
75
|
telegramToken: z.string().optional()
|
|
@@ -656,12 +667,12 @@ var init_adapter = __esm({
|
|
|
656
667
|
toBlock: options?.toBlock,
|
|
657
668
|
args: options?.args
|
|
658
669
|
});
|
|
659
|
-
return logs.map((
|
|
660
|
-
eventName:
|
|
661
|
-
blockNumber:
|
|
662
|
-
transactionHash:
|
|
663
|
-
args:
|
|
664
|
-
logIndex:
|
|
670
|
+
return logs.map((log4) => ({
|
|
671
|
+
eventName: log4.eventName ?? eventName,
|
|
672
|
+
blockNumber: log4.blockNumber ?? 0n,
|
|
673
|
+
transactionHash: log4.transactionHash ?? "0x",
|
|
674
|
+
args: log4.args ?? {},
|
|
675
|
+
logIndex: log4.logIndex ?? 0
|
|
665
676
|
}));
|
|
666
677
|
}
|
|
667
678
|
// ── Tokens ──────────────────────────────────────────────────────────────
|
|
@@ -8952,6 +8963,481 @@ var init_collect = __esm({
|
|
|
8952
8963
|
}
|
|
8953
8964
|
});
|
|
8954
8965
|
|
|
8966
|
+
// src/api/routes/v1/market.ts
|
|
8967
|
+
async function registerMarketRoutes(server) {
|
|
8968
|
+
server.get("/price/:symbol", {
|
|
8969
|
+
schema: {
|
|
8970
|
+
tags: ["Market"],
|
|
8971
|
+
summary: "Get live price and market data for a symbol",
|
|
8972
|
+
params: { type: "object", properties: { symbol: { type: "string" } }, required: ["symbol"] }
|
|
8973
|
+
},
|
|
8974
|
+
handler: async (request) => {
|
|
8975
|
+
const { symbol } = request.params;
|
|
8976
|
+
return handleTool("get_market_data", { symbol });
|
|
8977
|
+
}
|
|
8978
|
+
});
|
|
8979
|
+
server.get("/trending", {
|
|
8980
|
+
schema: {
|
|
8981
|
+
tags: ["Market"],
|
|
8982
|
+
summary: "Get trending tokens from DEX and CoinGecko"
|
|
8983
|
+
},
|
|
8984
|
+
handler: async () => {
|
|
8985
|
+
return handleTool("get_trending", {});
|
|
8986
|
+
}
|
|
8987
|
+
});
|
|
8988
|
+
server.get("/fear-greed", {
|
|
8989
|
+
schema: {
|
|
8990
|
+
tags: ["Market"],
|
|
8991
|
+
summary: "Get Crypto Fear & Greed Index with history"
|
|
8992
|
+
},
|
|
8993
|
+
handler: async () => {
|
|
8994
|
+
return handleTool("get_fear_greed", {});
|
|
8995
|
+
}
|
|
8996
|
+
});
|
|
8997
|
+
server.get("/news", {
|
|
8998
|
+
schema: {
|
|
8999
|
+
tags: ["Market"],
|
|
9000
|
+
summary: "Get latest crypto news with sentiment",
|
|
9001
|
+
querystring: {
|
|
9002
|
+
type: "object",
|
|
9003
|
+
properties: { symbol: { type: "string" } }
|
|
9004
|
+
}
|
|
9005
|
+
},
|
|
9006
|
+
handler: async (request) => {
|
|
9007
|
+
const { symbol } = request.query;
|
|
9008
|
+
return handleTool("get_crypto_news", { symbol });
|
|
9009
|
+
}
|
|
9010
|
+
});
|
|
9011
|
+
server.get("/dex/search", {
|
|
9012
|
+
schema: {
|
|
9013
|
+
tags: ["Market"],
|
|
9014
|
+
summary: "Search tokens on decentralized exchanges",
|
|
9015
|
+
querystring: {
|
|
9016
|
+
type: "object",
|
|
9017
|
+
properties: { q: { type: "string" } },
|
|
9018
|
+
required: ["q"]
|
|
9019
|
+
}
|
|
9020
|
+
},
|
|
9021
|
+
handler: async (request) => {
|
|
9022
|
+
const { q } = request.query;
|
|
9023
|
+
return handleTool("search_token_dex", { query: q });
|
|
9024
|
+
}
|
|
9025
|
+
});
|
|
9026
|
+
server.get("/derivatives/:symbol", {
|
|
9027
|
+
schema: {
|
|
9028
|
+
tags: ["Market"],
|
|
9029
|
+
summary: "Get derivatives data (funding rate, open interest)",
|
|
9030
|
+
params: { type: "object", properties: { symbol: { type: "string" } }, required: ["symbol"] }
|
|
9031
|
+
},
|
|
9032
|
+
handler: async (request) => {
|
|
9033
|
+
const { symbol } = request.params;
|
|
9034
|
+
return handleTool("get_derivatives_data", { symbol });
|
|
9035
|
+
}
|
|
9036
|
+
});
|
|
9037
|
+
}
|
|
9038
|
+
var init_market3 = __esm({
|
|
9039
|
+
"src/api/routes/v1/market.ts"() {
|
|
9040
|
+
"use strict";
|
|
9041
|
+
init_tool_handler();
|
|
9042
|
+
}
|
|
9043
|
+
});
|
|
9044
|
+
|
|
9045
|
+
// src/api/routes/v1/analysis.ts
|
|
9046
|
+
async function registerAnalysisRoutes(server) {
|
|
9047
|
+
server.get("/technical/:symbol", {
|
|
9048
|
+
schema: {
|
|
9049
|
+
tags: ["Analysis"],
|
|
9050
|
+
summary: "Run technical analysis on a symbol",
|
|
9051
|
+
params: { type: "object", properties: { symbol: { type: "string" } }, required: ["symbol"] },
|
|
9052
|
+
querystring: {
|
|
9053
|
+
type: "object",
|
|
9054
|
+
properties: { timeframe: { type: "string", default: "4h" } }
|
|
9055
|
+
}
|
|
9056
|
+
},
|
|
9057
|
+
handler: async (request) => {
|
|
9058
|
+
const { symbol } = request.params;
|
|
9059
|
+
const { timeframe } = request.query;
|
|
9060
|
+
return handleTool("get_technical_analysis", { symbol, timeframe });
|
|
9061
|
+
}
|
|
9062
|
+
});
|
|
9063
|
+
server.get("/prediction/:symbol", {
|
|
9064
|
+
schema: {
|
|
9065
|
+
tags: ["Analysis"],
|
|
9066
|
+
summary: "Generate multi-signal composite prediction",
|
|
9067
|
+
params: { type: "object", properties: { symbol: { type: "string" } }, required: ["symbol"] }
|
|
9068
|
+
},
|
|
9069
|
+
handler: async (request) => {
|
|
9070
|
+
const { symbol } = request.params;
|
|
9071
|
+
return handleTool("get_prediction", { symbol });
|
|
9072
|
+
}
|
|
9073
|
+
});
|
|
9074
|
+
server.get("/ml/:symbol", {
|
|
9075
|
+
schema: {
|
|
9076
|
+
tags: ["Analysis"],
|
|
9077
|
+
summary: "Get ML-enhanced prediction from sidecar models",
|
|
9078
|
+
params: { type: "object", properties: { symbol: { type: "string" } }, required: ["symbol"] }
|
|
9079
|
+
},
|
|
9080
|
+
handler: async (request) => {
|
|
9081
|
+
const { symbol } = request.params;
|
|
9082
|
+
return handleTool("get_ml_prediction", { symbol });
|
|
9083
|
+
}
|
|
9084
|
+
});
|
|
9085
|
+
server.get("/raises/recent", {
|
|
9086
|
+
schema: {
|
|
9087
|
+
tags: ["Analysis"],
|
|
9088
|
+
summary: "Get recent crypto fundraising rounds",
|
|
9089
|
+
querystring: {
|
|
9090
|
+
type: "object",
|
|
9091
|
+
properties: {
|
|
9092
|
+
category: { type: "string" },
|
|
9093
|
+
chain: { type: "string" }
|
|
9094
|
+
}
|
|
9095
|
+
}
|
|
9096
|
+
},
|
|
9097
|
+
handler: async (request) => {
|
|
9098
|
+
const { category, chain } = request.query;
|
|
9099
|
+
return handleTool("get_raises", { category, chain });
|
|
9100
|
+
}
|
|
9101
|
+
});
|
|
9102
|
+
}
|
|
9103
|
+
var init_analysis = __esm({
|
|
9104
|
+
"src/api/routes/v1/analysis.ts"() {
|
|
9105
|
+
"use strict";
|
|
9106
|
+
init_tool_handler();
|
|
9107
|
+
}
|
|
9108
|
+
});
|
|
9109
|
+
|
|
9110
|
+
// src/api/routes/v1/security.ts
|
|
9111
|
+
async function registerSecurityRoutes(server) {
|
|
9112
|
+
server.post("/token", {
|
|
9113
|
+
schema: {
|
|
9114
|
+
tags: ["Security"],
|
|
9115
|
+
summary: "Check token security via GoPlus",
|
|
9116
|
+
body: {
|
|
9117
|
+
type: "object",
|
|
9118
|
+
properties: {
|
|
9119
|
+
address: { type: "string" },
|
|
9120
|
+
chain: { type: "string", default: "ethereum" }
|
|
9121
|
+
},
|
|
9122
|
+
required: ["address"]
|
|
9123
|
+
}
|
|
9124
|
+
},
|
|
9125
|
+
handler: async (request) => {
|
|
9126
|
+
const { address, chain } = request.body;
|
|
9127
|
+
return handleTool("get_token_security", { address, chain });
|
|
9128
|
+
}
|
|
9129
|
+
});
|
|
9130
|
+
server.post("/rug-check", {
|
|
9131
|
+
schema: {
|
|
9132
|
+
tags: ["Security"],
|
|
9133
|
+
summary: "Check token for rug pull indicators",
|
|
9134
|
+
body: {
|
|
9135
|
+
type: "object",
|
|
9136
|
+
properties: {
|
|
9137
|
+
address: { type: "string" },
|
|
9138
|
+
chain: { type: "string", default: "ethereum" }
|
|
9139
|
+
},
|
|
9140
|
+
required: ["address"]
|
|
9141
|
+
}
|
|
9142
|
+
},
|
|
9143
|
+
handler: async (request) => {
|
|
9144
|
+
const { address, chain } = request.body;
|
|
9145
|
+
return handleTool("check_rug_indicators", { address, chain });
|
|
9146
|
+
}
|
|
9147
|
+
});
|
|
9148
|
+
server.post("/wallet", {
|
|
9149
|
+
schema: {
|
|
9150
|
+
tags: ["Security"],
|
|
9151
|
+
summary: "Analyze a wallet address",
|
|
9152
|
+
body: {
|
|
9153
|
+
type: "object",
|
|
9154
|
+
properties: {
|
|
9155
|
+
address: { type: "string" },
|
|
9156
|
+
chain: { type: "string", default: "ethereum" }
|
|
9157
|
+
},
|
|
9158
|
+
required: ["address"]
|
|
9159
|
+
}
|
|
9160
|
+
},
|
|
9161
|
+
handler: async (request) => {
|
|
9162
|
+
const { address, chain } = request.body;
|
|
9163
|
+
return handleTool("analyze_wallet", { address, chain });
|
|
9164
|
+
}
|
|
9165
|
+
});
|
|
9166
|
+
}
|
|
9167
|
+
var init_security = __esm({
|
|
9168
|
+
"src/api/routes/v1/security.ts"() {
|
|
9169
|
+
"use strict";
|
|
9170
|
+
init_tool_handler();
|
|
9171
|
+
}
|
|
9172
|
+
});
|
|
9173
|
+
|
|
9174
|
+
// src/api/auth/keys.ts
|
|
9175
|
+
import { randomBytes, scryptSync } from "crypto";
|
|
9176
|
+
function hashApiKey(key) {
|
|
9177
|
+
return scryptSync(key, API_KEY_SALT, 64).toString("hex");
|
|
9178
|
+
}
|
|
9179
|
+
function ensureKeysTable() {
|
|
9180
|
+
getDb().exec(`
|
|
9181
|
+
CREATE TABLE IF NOT EXISTS api_keys (
|
|
9182
|
+
id TEXT PRIMARY KEY,
|
|
9183
|
+
label TEXT NOT NULL,
|
|
9184
|
+
key_hash TEXT NOT NULL UNIQUE,
|
|
9185
|
+
key_prefix TEXT NOT NULL,
|
|
9186
|
+
rate_limit INTEGER NOT NULL DEFAULT 100,
|
|
9187
|
+
created_at INTEGER NOT NULL,
|
|
9188
|
+
revoked_at INTEGER
|
|
9189
|
+
)
|
|
9190
|
+
`);
|
|
9191
|
+
}
|
|
9192
|
+
function createApiKey(label) {
|
|
9193
|
+
ensureKeysTable();
|
|
9194
|
+
const rawKey = `vzr_${randomBytes(32).toString("hex")}`;
|
|
9195
|
+
const keyHash = hashApiKey(rawKey);
|
|
9196
|
+
const keyPrefix = rawKey.slice(0, 12) + "...";
|
|
9197
|
+
const id = randomBytes(16).toString("hex");
|
|
9198
|
+
const now = Date.now();
|
|
9199
|
+
getDb().prepare(
|
|
9200
|
+
`INSERT INTO api_keys (id, label, key_hash, key_prefix, rate_limit, created_at)
|
|
9201
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
9202
|
+
).run(id, label, keyHash, keyPrefix, 100, now);
|
|
9203
|
+
return {
|
|
9204
|
+
key: rawKey,
|
|
9205
|
+
record: { id, label, keyPrefix, rateLimit: 100, createdAt: now, revokedAt: null }
|
|
9206
|
+
};
|
|
9207
|
+
}
|
|
9208
|
+
function listApiKeys() {
|
|
9209
|
+
ensureKeysTable();
|
|
9210
|
+
const rows = getDb().prepare("SELECT * FROM api_keys WHERE revoked_at IS NULL ORDER BY created_at DESC").all();
|
|
9211
|
+
return rows.map((r) => ({
|
|
9212
|
+
id: r.id,
|
|
9213
|
+
label: r.label,
|
|
9214
|
+
keyPrefix: r.key_prefix,
|
|
9215
|
+
rateLimit: r.rate_limit,
|
|
9216
|
+
createdAt: r.created_at,
|
|
9217
|
+
revokedAt: r.revoked_at
|
|
9218
|
+
}));
|
|
9219
|
+
}
|
|
9220
|
+
function revokeApiKey(id) {
|
|
9221
|
+
ensureKeysTable();
|
|
9222
|
+
const result = getDb().prepare("UPDATE api_keys SET revoked_at = ? WHERE id = ? AND revoked_at IS NULL").run(Date.now(), id);
|
|
9223
|
+
return result.changes > 0;
|
|
9224
|
+
}
|
|
9225
|
+
var API_KEY_SALT;
|
|
9226
|
+
var init_keys2 = __esm({
|
|
9227
|
+
"src/api/auth/keys.ts"() {
|
|
9228
|
+
"use strict";
|
|
9229
|
+
init_cache();
|
|
9230
|
+
API_KEY_SALT = "vizzor-api-key-v1";
|
|
9231
|
+
}
|
|
9232
|
+
});
|
|
9233
|
+
|
|
9234
|
+
// src/api/auth/middleware.ts
|
|
9235
|
+
async function authMiddleware(request, reply) {
|
|
9236
|
+
if (PUBLIC_PATHS.some((p) => request.url === p) || request.url.startsWith("/docs/")) {
|
|
9237
|
+
return;
|
|
9238
|
+
}
|
|
9239
|
+
const apiKey = request.headers["x-api-key"];
|
|
9240
|
+
if (!apiKey) {
|
|
9241
|
+
return reply.status(401).send({
|
|
9242
|
+
error: "Unauthorized",
|
|
9243
|
+
message: "Missing X-API-Key header"
|
|
9244
|
+
});
|
|
9245
|
+
}
|
|
9246
|
+
const keyHash = hashApiKey(apiKey);
|
|
9247
|
+
const valid = await validateKey2(keyHash);
|
|
9248
|
+
if (!valid) {
|
|
9249
|
+
return reply.status(403).send({
|
|
9250
|
+
error: "Forbidden",
|
|
9251
|
+
message: "Invalid API key"
|
|
9252
|
+
});
|
|
9253
|
+
}
|
|
9254
|
+
}
|
|
9255
|
+
async function validateKey2(keyHash) {
|
|
9256
|
+
const store = getStoreInstance();
|
|
9257
|
+
if (!store) return false;
|
|
9258
|
+
const cached = await store.getCached(`apikey:${keyHash}`);
|
|
9259
|
+
if (cached !== null) return cached.valid;
|
|
9260
|
+
return true;
|
|
9261
|
+
}
|
|
9262
|
+
var PUBLIC_PATHS;
|
|
9263
|
+
var init_middleware = __esm({
|
|
9264
|
+
"src/api/auth/middleware.ts"() {
|
|
9265
|
+
"use strict";
|
|
9266
|
+
init_keys2();
|
|
9267
|
+
init_store_factory();
|
|
9268
|
+
PUBLIC_PATHS = ["/health", "/docs", "/docs/"];
|
|
9269
|
+
}
|
|
9270
|
+
});
|
|
9271
|
+
|
|
9272
|
+
// src/api/middleware/error-handler.ts
|
|
9273
|
+
function errorHandler(error, _request, reply) {
|
|
9274
|
+
if (error.statusCode === 429) {
|
|
9275
|
+
void reply.status(429).send({
|
|
9276
|
+
error: "Too Many Requests",
|
|
9277
|
+
message: "Rate limit exceeded. Try again later."
|
|
9278
|
+
});
|
|
9279
|
+
return;
|
|
9280
|
+
}
|
|
9281
|
+
const status = error.statusCode ?? 500;
|
|
9282
|
+
void reply.status(status).send({
|
|
9283
|
+
error: error.name ?? "InternalError",
|
|
9284
|
+
message: status >= 500 ? "Internal server error" : error.message
|
|
9285
|
+
});
|
|
9286
|
+
}
|
|
9287
|
+
var init_error_handler = __esm({
|
|
9288
|
+
"src/api/middleware/error-handler.ts"() {
|
|
9289
|
+
"use strict";
|
|
9290
|
+
}
|
|
9291
|
+
});
|
|
9292
|
+
|
|
9293
|
+
// src/api/server.ts
|
|
9294
|
+
var server_exports = {};
|
|
9295
|
+
__export(server_exports, {
|
|
9296
|
+
startApiServer: () => startApiServer
|
|
9297
|
+
});
|
|
9298
|
+
import Fastify from "fastify";
|
|
9299
|
+
import cors from "@fastify/cors";
|
|
9300
|
+
import rateLimit from "@fastify/rate-limit";
|
|
9301
|
+
import swagger from "@fastify/swagger";
|
|
9302
|
+
import swaggerUi from "@fastify/swagger-ui";
|
|
9303
|
+
async function startApiServer(options) {
|
|
9304
|
+
const server = Fastify({ logger: false });
|
|
9305
|
+
await server.register(cors, { origin: true });
|
|
9306
|
+
await server.register(rateLimit, {
|
|
9307
|
+
max: 100,
|
|
9308
|
+
timeWindow: "1 minute"
|
|
9309
|
+
});
|
|
9310
|
+
await server.register(swagger, {
|
|
9311
|
+
openapi: {
|
|
9312
|
+
info: {
|
|
9313
|
+
title: "Vizzor API",
|
|
9314
|
+
description: "AI-powered crypto intelligence REST API",
|
|
9315
|
+
version: "0.7.0"
|
|
9316
|
+
},
|
|
9317
|
+
servers: [{ url: `http://${options.host}:${options.port}` }],
|
|
9318
|
+
components: {
|
|
9319
|
+
securitySchemes: {
|
|
9320
|
+
apiKey: {
|
|
9321
|
+
type: "apiKey",
|
|
9322
|
+
name: "X-API-Key",
|
|
9323
|
+
in: "header"
|
|
9324
|
+
}
|
|
9325
|
+
}
|
|
9326
|
+
}
|
|
9327
|
+
}
|
|
9328
|
+
});
|
|
9329
|
+
await server.register(swaggerUi, {
|
|
9330
|
+
routePrefix: "/docs"
|
|
9331
|
+
});
|
|
9332
|
+
if (options.enableAuth) {
|
|
9333
|
+
server.addHook("onRequest", authMiddleware);
|
|
9334
|
+
}
|
|
9335
|
+
server.setErrorHandler(errorHandler);
|
|
9336
|
+
server.get("/health", async () => ({
|
|
9337
|
+
status: "ok",
|
|
9338
|
+
version: "0.7.0",
|
|
9339
|
+
uptime: process.uptime(),
|
|
9340
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
9341
|
+
}));
|
|
9342
|
+
await server.register(registerMarketRoutes, { prefix: "/v1/market" });
|
|
9343
|
+
await server.register(registerAnalysisRoutes, { prefix: "/v1/analysis" });
|
|
9344
|
+
await server.register(registerSecurityRoutes, { prefix: "/v1/security" });
|
|
9345
|
+
await server.listen({ port: options.port, host: options.host });
|
|
9346
|
+
log3.info(`Vizzor API listening on ${options.host}:${options.port}`);
|
|
9347
|
+
log3.info(`OpenAPI docs at http://${options.host}:${options.port}/docs`);
|
|
9348
|
+
}
|
|
9349
|
+
var log3;
|
|
9350
|
+
var init_server = __esm({
|
|
9351
|
+
"src/api/server.ts"() {
|
|
9352
|
+
"use strict";
|
|
9353
|
+
init_logger();
|
|
9354
|
+
init_market3();
|
|
9355
|
+
init_analysis();
|
|
9356
|
+
init_security();
|
|
9357
|
+
init_middleware();
|
|
9358
|
+
init_error_handler();
|
|
9359
|
+
log3 = createLogger("api");
|
|
9360
|
+
}
|
|
9361
|
+
});
|
|
9362
|
+
|
|
9363
|
+
// src/cli/commands/serve.ts
|
|
9364
|
+
var serve_exports = {};
|
|
9365
|
+
__export(serve_exports, {
|
|
9366
|
+
handleServe: () => handleServe
|
|
9367
|
+
});
|
|
9368
|
+
import chalk9 from "chalk";
|
|
9369
|
+
async function handleServe(options) {
|
|
9370
|
+
console.log(chalk9.bold("Starting Vizzor REST API..."));
|
|
9371
|
+
const { startApiServer: startApiServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
9372
|
+
await startApiServer2({
|
|
9373
|
+
port: options.port,
|
|
9374
|
+
host: options.host,
|
|
9375
|
+
enableAuth: options.auth
|
|
9376
|
+
});
|
|
9377
|
+
console.log(chalk9.green(`API running on http://${options.host}:${options.port}`));
|
|
9378
|
+
console.log(chalk9.dim(`Docs: http://${options.host}:${options.port}/docs`));
|
|
9379
|
+
console.log(chalk9.dim("\nPress Ctrl+C to stop"));
|
|
9380
|
+
process.on("SIGINT", () => {
|
|
9381
|
+
console.log(chalk9.yellow("\nShutting down..."));
|
|
9382
|
+
process.exit(0);
|
|
9383
|
+
});
|
|
9384
|
+
await new Promise(() => {
|
|
9385
|
+
});
|
|
9386
|
+
}
|
|
9387
|
+
var init_serve = __esm({
|
|
9388
|
+
"src/cli/commands/serve.ts"() {
|
|
9389
|
+
"use strict";
|
|
9390
|
+
}
|
|
9391
|
+
});
|
|
9392
|
+
|
|
9393
|
+
// src/cli/commands/api.ts
|
|
9394
|
+
var api_exports = {};
|
|
9395
|
+
__export(api_exports, {
|
|
9396
|
+
handleApiKeyCreate: () => handleApiKeyCreate,
|
|
9397
|
+
handleApiKeyList: () => handleApiKeyList,
|
|
9398
|
+
handleApiKeyRevoke: () => handleApiKeyRevoke
|
|
9399
|
+
});
|
|
9400
|
+
import chalk10 from "chalk";
|
|
9401
|
+
function handleApiKeyCreate(label) {
|
|
9402
|
+
const { key, record } = createApiKey(label || "default");
|
|
9403
|
+
console.log(chalk10.green("API key created successfully!"));
|
|
9404
|
+
process.stdout.write(chalk10.bold(`
|
|
9405
|
+
Key: ${key}
|
|
9406
|
+
|
|
9407
|
+
`));
|
|
9408
|
+
console.log(chalk10.yellow(" Save this key \u2014 it will not be shown again."));
|
|
9409
|
+
console.log(` Label: ${record.label}`);
|
|
9410
|
+
console.log(` ID: ${record.id}`);
|
|
9411
|
+
}
|
|
9412
|
+
function handleApiKeyList() {
|
|
9413
|
+
const keys = listApiKeys();
|
|
9414
|
+
if (keys.length === 0) {
|
|
9415
|
+
console.log(chalk10.dim("No API keys found. Create one with: vizzor api key create [label]"));
|
|
9416
|
+
return;
|
|
9417
|
+
}
|
|
9418
|
+
console.log(chalk10.bold("Active API Keys\n"));
|
|
9419
|
+
for (const k of keys) {
|
|
9420
|
+
console.log(` ${chalk10.cyan(k.keyPrefix)} ${k.label} (${k.id.slice(0, 8)})`);
|
|
9421
|
+
console.log(` Rate limit: ${k.rateLimit} req/min`);
|
|
9422
|
+
console.log(` Created: ${new Date(k.createdAt).toISOString()}
|
|
9423
|
+
`);
|
|
9424
|
+
}
|
|
9425
|
+
}
|
|
9426
|
+
function handleApiKeyRevoke(id) {
|
|
9427
|
+
const revoked = revokeApiKey(id);
|
|
9428
|
+
if (revoked) {
|
|
9429
|
+
console.log(chalk10.green(`API key ${id} revoked.`));
|
|
9430
|
+
} else {
|
|
9431
|
+
console.log(chalk10.red(`No active key found with ID: ${id}`));
|
|
9432
|
+
}
|
|
9433
|
+
}
|
|
9434
|
+
var init_api = __esm({
|
|
9435
|
+
"src/cli/commands/api.ts"() {
|
|
9436
|
+
"use strict";
|
|
9437
|
+
init_keys2();
|
|
9438
|
+
}
|
|
9439
|
+
});
|
|
9440
|
+
|
|
8955
9441
|
// src/tui/components/status-bar.tsx
|
|
8956
9442
|
import React, { useState, useEffect } from "react";
|
|
8957
9443
|
import { Box, Text, Spacer } from "ink";
|
|
@@ -10127,8 +10613,8 @@ async function handleConfig(args2) {
|
|
|
10127
10613
|
}
|
|
10128
10614
|
const isSensitive = key.toLowerCase().includes("key") || key.toLowerCase().includes("token");
|
|
10129
10615
|
if (isSensitive) {
|
|
10130
|
-
const { validateKey:
|
|
10131
|
-
const error =
|
|
10616
|
+
const { validateKey: validateKey3 } = await Promise.resolve().then(() => (init_keys(), keys_exports));
|
|
10617
|
+
const error = validateKey3(key, value);
|
|
10132
10618
|
if (error && !error.startsWith("Warning:")) {
|
|
10133
10619
|
return { blocks: [], text: `Rejected: ${error}` };
|
|
10134
10620
|
}
|
|
@@ -10758,6 +11244,24 @@ collectCmd.command("status").description("Show data collection status").action(a
|
|
|
10758
11244
|
const { handleCollectStatus: handleCollectStatus2 } = await Promise.resolve().then(() => (init_collect(), collect_exports));
|
|
10759
11245
|
handleCollectStatus2();
|
|
10760
11246
|
});
|
|
11247
|
+
program.command("serve").description("Start the REST API server").option("--port <port>", "Server port", parseInt, 3e3).option("--host <host>", "Server host", "0.0.0.0").option("--auth", "Enable API key authentication", false).action(async (options) => {
|
|
11248
|
+
const { handleServe: handleServe2 } = await Promise.resolve().then(() => (init_serve(), serve_exports));
|
|
11249
|
+
await handleServe2(options);
|
|
11250
|
+
});
|
|
11251
|
+
var apiCmd = program.command("api").description("API management");
|
|
11252
|
+
var apiKeyCmd = apiCmd.command("key").description("API key management");
|
|
11253
|
+
apiKeyCmd.command("create [label]").description("Generate a new API key").action(async (label) => {
|
|
11254
|
+
const { handleApiKeyCreate: handleApiKeyCreate2 } = await Promise.resolve().then(() => (init_api(), api_exports));
|
|
11255
|
+
handleApiKeyCreate2(label);
|
|
11256
|
+
});
|
|
11257
|
+
apiKeyCmd.command("list").description("List active API keys").action(async () => {
|
|
11258
|
+
const { handleApiKeyList: handleApiKeyList2 } = await Promise.resolve().then(() => (init_api(), api_exports));
|
|
11259
|
+
handleApiKeyList2();
|
|
11260
|
+
});
|
|
11261
|
+
apiKeyCmd.command("revoke <id>").description("Revoke an API key").action(async (id) => {
|
|
11262
|
+
const { handleApiKeyRevoke: handleApiKeyRevoke2 } = await Promise.resolve().then(() => (init_api(), api_exports));
|
|
11263
|
+
handleApiKeyRevoke2(id);
|
|
11264
|
+
});
|
|
10761
11265
|
var args = process.argv.slice(2);
|
|
10762
11266
|
if (args.length === 0) {
|
|
10763
11267
|
await loadConfig();
|