@kopai/cli 0.5.2 → 0.6.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.mjs +118 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import { KopaiClient } from "@kopai/sdk";
|
|
4
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { chmodSync, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { join } from "node:path";
|
|
7
|
+
import { createInterface } from "node:readline";
|
|
7
8
|
|
|
8
9
|
//#region src/config.ts
|
|
9
10
|
const CONFIG_FILENAME = ".kopairc";
|
|
11
|
+
const TOKEN_PREFIX_LENGTH = 10;
|
|
12
|
+
const DEFAULT_URL$1 = "http://localhost:8000/signals";
|
|
13
|
+
/** Owner read+write only (rw-------). Used for files containing secrets. */
|
|
14
|
+
const OWNER_READ_WRITE = 384;
|
|
10
15
|
function loadConfigFile(path) {
|
|
11
16
|
if (!existsSync(path)) return null;
|
|
12
17
|
try {
|
|
@@ -24,6 +29,44 @@ function loadConfig(configPath) {
|
|
|
24
29
|
}
|
|
25
30
|
return {};
|
|
26
31
|
}
|
|
32
|
+
function resolveConfigPath(global) {
|
|
33
|
+
return global ? join(homedir(), CONFIG_FILENAME) : join(process.cwd(), CONFIG_FILENAME);
|
|
34
|
+
}
|
|
35
|
+
function saveConfig(updates, targetPath) {
|
|
36
|
+
let existing = {};
|
|
37
|
+
if (existsSync(targetPath)) try {
|
|
38
|
+
const content = readFileSync(targetPath, "utf-8");
|
|
39
|
+
existing = JSON.parse(content);
|
|
40
|
+
} catch {}
|
|
41
|
+
const merged = {
|
|
42
|
+
...existing,
|
|
43
|
+
...updates
|
|
44
|
+
};
|
|
45
|
+
writeFileSync(targetPath, JSON.stringify(merged, null, 2) + "\n", {
|
|
46
|
+
encoding: "utf-8",
|
|
47
|
+
mode: OWNER_READ_WRITE
|
|
48
|
+
});
|
|
49
|
+
chmodSync(targetPath, OWNER_READ_WRITE);
|
|
50
|
+
}
|
|
51
|
+
function removeConfigToken(targetPath) {
|
|
52
|
+
if (!existsSync(targetPath)) return false;
|
|
53
|
+
try {
|
|
54
|
+
const content = readFileSync(targetPath, "utf-8");
|
|
55
|
+
const config = JSON.parse(content);
|
|
56
|
+
if (!config.token) return false;
|
|
57
|
+
delete config.token;
|
|
58
|
+
writeFileSync(targetPath, JSON.stringify(config, null, 2) + "\n", {
|
|
59
|
+
encoding: "utf-8",
|
|
60
|
+
mode: OWNER_READ_WRITE
|
|
61
|
+
});
|
|
62
|
+
} catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
chmodSync(targetPath, OWNER_READ_WRITE);
|
|
67
|
+
} catch {}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
27
70
|
|
|
28
71
|
//#endregion
|
|
29
72
|
//#region src/client.ts
|
|
@@ -256,14 +299,86 @@ function collect(value, previous) {
|
|
|
256
299
|
return previous.concat([value]);
|
|
257
300
|
}
|
|
258
301
|
|
|
302
|
+
//#endregion
|
|
303
|
+
//#region src/commands/login.ts
|
|
304
|
+
function readTokenFromStdin() {
|
|
305
|
+
return new Promise((resolve) => {
|
|
306
|
+
const rl = createInterface({
|
|
307
|
+
input: process.stdin,
|
|
308
|
+
output: process.stderr
|
|
309
|
+
});
|
|
310
|
+
rl.question("Token: ", (answer) => {
|
|
311
|
+
rl.close();
|
|
312
|
+
resolve(answer.trim());
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function createLoginCommand() {
|
|
317
|
+
return new Command("login").description("Save an API token to .kopairc").option("--url <url>", "API base URL to save alongside token").option("--global", "Write to ~/.kopairc instead of ./.kopairc").action(async (opts) => {
|
|
318
|
+
const token = await readTokenFromStdin();
|
|
319
|
+
if (!token) {
|
|
320
|
+
console.error("Token cannot be empty.");
|
|
321
|
+
process.exitCode = 2;
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
saveConfig({
|
|
325
|
+
token,
|
|
326
|
+
url: opts.url ?? DEFAULT_URL$1
|
|
327
|
+
}, resolveConfigPath(opts.global ?? false));
|
|
328
|
+
if (!opts.global) {
|
|
329
|
+
if (existsSync(join(process.cwd(), ".git"))) {
|
|
330
|
+
const gitignorePath = join(process.cwd(), ".gitignore");
|
|
331
|
+
let isIgnored = false;
|
|
332
|
+
if (existsSync(gitignorePath)) isIgnored = readFileSync(gitignorePath, "utf-8").split("\n").some((line) => line.trim() === ".kopairc");
|
|
333
|
+
if (!isIgnored) console.error("Warning: .kopairc is not in .gitignore. Add it to avoid committing secrets.");
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
console.log(`Logged in. Token: ${token.slice(0, TOKEN_PREFIX_LENGTH)}...`);
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
//#endregion
|
|
341
|
+
//#region src/commands/logout.ts
|
|
342
|
+
function createLogoutCommand() {
|
|
343
|
+
return new Command("logout").description("Remove saved API token from .kopairc").option("--global", "Remove from ~/.kopairc instead of ./.kopairc").action((opts) => {
|
|
344
|
+
if (removeConfigToken(resolveConfigPath(opts.global ?? false))) console.log("Logged out.");
|
|
345
|
+
else console.log("Not logged in.");
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
//#endregion
|
|
350
|
+
//#region src/commands/whoami.ts
|
|
351
|
+
function createWhoamiCommand() {
|
|
352
|
+
return new Command("whoami").description("Show current authentication status").option("-c, --config <path>", "Config file path").action(async (opts) => {
|
|
353
|
+
const config = loadConfig(opts.config);
|
|
354
|
+
if (!config.token) {
|
|
355
|
+
console.log("Not logged in.");
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
console.log(`Token: ${config.token.slice(0, TOKEN_PREFIX_LENGTH)}...`);
|
|
359
|
+
console.log(`URL: ${config.url ?? `${DEFAULT_URL$1} (default)`}`);
|
|
360
|
+
try {
|
|
361
|
+
await new KopaiClient({
|
|
362
|
+
baseUrl: config.url ?? DEFAULT_URL$1,
|
|
363
|
+
token: config.token
|
|
364
|
+
}).searchTracesPage({ limit: 1 });
|
|
365
|
+
console.log("Token is valid.");
|
|
366
|
+
} catch (err) {
|
|
367
|
+
if ((err && typeof err === "object" && "status" in err ? err.status : void 0) === 401) console.log("Token is invalid or expired.");
|
|
368
|
+
else console.log("Could not reach server to validate token.");
|
|
369
|
+
process.exitCode = 1;
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
|
|
259
374
|
//#endregion
|
|
260
375
|
//#region package.json
|
|
261
|
-
var version = "0.
|
|
376
|
+
var version = "0.6.0";
|
|
262
377
|
|
|
263
378
|
//#endregion
|
|
264
379
|
//#region src/index.ts
|
|
265
380
|
const program = new Command();
|
|
266
|
-
program.name("@kopai/cli").description("|--k> kopai - Query OpenTelemetry data").version(version).addCommand(createTracesCommand()).addCommand(createLogsCommand()).addCommand(createMetricsCommand()).addHelpText("after", `
|
|
381
|
+
program.name("@kopai/cli").description("|--k> kopai - Query OpenTelemetry data").version(version).addCommand(createTracesCommand()).addCommand(createLogsCommand()).addCommand(createMetricsCommand()).addCommand(createLoginCommand()).addCommand(createLogoutCommand()).addCommand(createWhoamiCommand()).addHelpText("after", `
|
|
267
382
|
Examples:
|
|
268
383
|
$ kopai traces search # localhost:8000 (default, for @kopai/app running locally)
|
|
269
384
|
$ kopai traces search --url https://example.com/signals # remote instance
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["collect","collect","pkg.version"],"sources":["../src/config.ts","../src/client.ts","../src/output.ts","../src/commands/traces.ts","../src/commands/logs.ts","../src/commands/metrics.ts","../package.json","../src/index.ts"],"sourcesContent":["import { readFileSync, existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface Config {\n url?: string;\n token?: string;\n}\n\nconst CONFIG_FILENAME = \".kopairc\";\n\nfunction loadConfigFile(path: string): Config | null {\n if (!existsSync(path)) return null;\n try {\n const content = readFileSync(path, \"utf-8\");\n return JSON.parse(content) as Config;\n } catch {\n return null;\n }\n}\n\nexport function loadConfig(configPath?: string): Config {\n // Priority: --config flag > ./.kopairc > ~/.kopairc\n const paths = configPath\n ? [configPath]\n : [join(process.cwd(), CONFIG_FILENAME), join(homedir(), CONFIG_FILENAME)];\n\n for (const path of paths) {\n const config = loadConfigFile(path);\n if (config) return config;\n }\n\n return {};\n}\n","import type { Command } from \"commander\";\nimport { KopaiClient } from \"@kopai/sdk\";\nimport { loadConfig } from \"./config.js\";\n\nexport function withConnectionOptions<T extends Command>(cmd: T): T {\n return cmd\n .option(\"--url <url>\", \"API base URL\")\n .option(\"--token <token>\", \"Auth token\")\n .option(\"-c, --config <path>\", \"Config file path\")\n .option(\"--timeout <ms>\", \"Request timeout\") as T;\n}\n\nexport interface ClientOptions {\n config?: string;\n url?: string;\n token?: string;\n timeout?: number;\n}\n\nconst DEFAULT_URL = \"http://localhost:8000/signals\";\n\nexport function createClient(opts: ClientOptions): KopaiClient {\n const fileConfig = loadConfig(opts.config);\n\n const url = opts.url ?? fileConfig.url ?? DEFAULT_URL;\n const token = opts.token ?? fileConfig.token;\n\n const timeout =\n opts.timeout != null ? parseInt(String(opts.timeout), 10) : undefined;\n\n return new KopaiClient({\n baseUrl: url,\n token,\n timeout: Number.isNaN(timeout) ? undefined : timeout,\n });\n}\n\nexport function parseAttributes(attrs?: string[]): Record<string, string> {\n if (!attrs || attrs.length === 0) return {};\n const result: Record<string, string> = {};\n for (const attr of attrs) {\n const idx = attr.indexOf(\"=\");\n if (idx === -1) {\n console.error(`Invalid attribute format: ${attr}. Use key=value`);\n process.exit(2);\n }\n result[attr.slice(0, idx)] = attr.slice(idx + 1);\n }\n return result;\n}\n","export type OutputFormat = \"json\" | \"table\";\n\nexport interface OutputOptions {\n format: OutputFormat;\n fields?: string[];\n}\n\nexport function detectFormat(json?: boolean, table?: boolean): OutputFormat {\n if (json) return \"json\";\n if (table) return \"table\";\n // Default: table for TTY, JSON for pipes\n return process.stdout.isTTY ? \"table\" : \"json\";\n}\n\nfunction countAttributes(attr: { values: Record<string, string[]> }): number {\n return Object.keys(attr.values).length;\n}\n\nfunction filterFields<T extends object>(data: T, fields: string[]): Partial<T> {\n return Object.fromEntries(\n Object.entries(data).filter(([key]) => fields.includes(key))\n ) as Partial<T>;\n}\n\nexport function parseFields(fieldsStr?: string): string[] | undefined {\n if (!fieldsStr) return undefined;\n return fieldsStr.split(\",\").map((f) => f.trim());\n}\n\nfunction isMetricsDiscoverData(data: unknown[]): data is Array<{\n attributes: { values: Record<string, string[]> };\n resourceAttributes: { values: Record<string, string[]> };\n}> {\n return (\n data.length > 0 &&\n typeof data[0] === \"object\" &&\n data[0] !== null &&\n \"attributes\" in data[0] &&\n \"resourceAttributes\" in data[0] &&\n typeof (data[0] as Record<string, unknown>).attributes === \"object\" &&\n (data[0] as Record<string, unknown>).attributes !== null &&\n \"values\" in ((data[0] as Record<string, unknown>).attributes as object)\n );\n}\n\nexport function output<T>(data: T, opts: OutputOptions): void {\n let outputData = data;\n\n // Apply field filtering\n if (opts.fields && opts.fields.length > 0) {\n if (Array.isArray(data)) {\n outputData = data.map((item) =>\n typeof item === \"object\" && item !== null\n ? filterFields(item as object, opts.fields!)\n : item\n ) as T;\n } else if (typeof data === \"object\" && data !== null) {\n outputData = filterFields(data as object, opts.fields) as T;\n }\n }\n\n if (opts.format === \"json\") {\n console.log(JSON.stringify(outputData, null, 2));\n } else {\n if (Array.isArray(outputData)) {\n if (outputData.length === 0) {\n console.log(\"No results found.\");\n } else if (!opts.fields && isMetricsDiscoverData(outputData)) {\n const transformed = outputData.map((m) => ({\n name: m.name,\n type: m.type,\n unit: m.unit,\n description: m.description,\n attrs: countAttributes(m.attributes),\n resourceAttrs: countAttributes(m.resourceAttributes),\n }));\n console.table(transformed);\n console.log(\"\\nUse --json for full attribute details.\");\n } else {\n console.table(outputData);\n }\n } else {\n console.log(outputData);\n }\n }\n}\n\nexport function outputError(error: unknown, json: boolean): void {\n const err =\n error instanceof Error\n ? { name: error.name, message: error.message }\n : { message: String(error) };\n\n if (json) {\n console.error(JSON.stringify({ error: err }));\n } else {\n console.error(`Error: ${err.message}`);\n }\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface TracesGetOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n}\n\ninterface TracesSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n traceId?: string;\n spanId?: string;\n parentSpanId?: string;\n service?: string;\n spanName?: string;\n spanKind?: string;\n statusCode?: string;\n scope?: string;\n timestampMin?: string;\n timestampMax?: string;\n durationMin?: string;\n durationMax?: string;\n spanAttr?: string[];\n resourceAttr?: string[];\n sort?: string;\n}\n\nexport function createTracesCommand(): Command {\n const traces = new Command(\"traces\").description(\"Query traces\");\n\n withConnectionOptions(\n traces\n .command(\"get\")\n .description(\"Get all spans for a trace by ID\")\n .argument(\"<traceId>\", \"Trace ID\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n ).action(async (traceId: string, opts: TracesGetOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const spans = await client.getTrace(traceId);\n output(spans, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n withConnectionOptions(\n traces\n .command(\"search\")\n .description(\"Search traces\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"--trace-id <id>\", \"Filter by trace ID\")\n .option(\"--span-id <id>\", \"Filter by span ID\")\n .option(\"--parent-span-id <id>\", \"Filter by parent span ID\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--span-name <name>\", \"Filter by span name\")\n .option(\"--span-kind <kind>\", \"Filter by span kind\")\n .option(\"--status-code <code>\", \"Filter by status code\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--timestamp-min <ns>\", \"Min timestamp (nanoseconds)\")\n .option(\"--timestamp-max <ns>\", \"Max timestamp (nanoseconds)\")\n .option(\"--duration-min <ns>\", \"Min duration (nanoseconds)\")\n .option(\"--duration-max <ns>\", \"Max duration (nanoseconds)\")\n .option(\n \"--span-attr <key=value>\",\n \"Span attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: TracesSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n traceId: opts.traceId,\n spanId: opts.spanId,\n parentSpanId: opts.parentSpanId,\n serviceName: opts.service,\n spanName: opts.spanName,\n spanKind: opts.spanKind,\n statusCode: opts.statusCode,\n scopeName: opts.scope,\n timestampMin: opts.timestampMin,\n timestampMax: opts.timestampMax,\n durationMin: opts.durationMin,\n durationMax: opts.durationMax,\n spanAttributes: parseAttributes(opts.spanAttr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchTracesPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return traces;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface LogsSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n traceId?: string;\n spanId?: string;\n service?: string;\n scope?: string;\n severityText?: string;\n severityMin?: string;\n severityMax?: string;\n body?: string;\n timestampMin?: string;\n timestampMax?: string;\n logAttr?: string[];\n resourceAttr?: string[];\n scopeAttr?: string[];\n sort?: string;\n}\n\nexport function createLogsCommand(): Command {\n const logs = new Command(\"logs\").description(\"Query logs\");\n\n withConnectionOptions(\n logs\n .command(\"search\")\n .description(\"Search logs\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"--trace-id <id>\", \"Filter by trace ID\")\n .option(\"--span-id <id>\", \"Filter by span ID\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--severity-text <level>\", \"Filter by severity text\")\n .option(\"--severity-min <n>\", \"Min severity number\")\n .option(\"--severity-max <n>\", \"Max severity number\")\n .option(\"-b, --body <text>\", \"Filter by body contains\")\n .option(\"--timestamp-min <ns>\", \"Min timestamp (nanoseconds)\")\n .option(\"--timestamp-max <ns>\", \"Max timestamp (nanoseconds)\")\n .option(\n \"--log-attr <key=value>\",\n \"Log attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--scope-attr <key=value>\",\n \"Scope attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: LogsSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n traceId: opts.traceId,\n spanId: opts.spanId,\n serviceName: opts.service,\n scopeName: opts.scope,\n severityText: opts.severityText,\n severityNumberMin: opts.severityMin\n ? parseInt(opts.severityMin, 10)\n : undefined,\n severityNumberMax: opts.severityMax\n ? parseInt(opts.severityMax, 10)\n : undefined,\n bodyContains: opts.body,\n timestampMin: opts.timestampMin,\n timestampMax: opts.timestampMax,\n logAttributes: parseAttributes(opts.logAttr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n scopeAttributes: parseAttributes(opts.scopeAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchLogsPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return logs;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface MetricsSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n type: string;\n name?: string;\n service?: string;\n scope?: string;\n timeMin?: string;\n timeMax?: string;\n attr?: string[];\n resourceAttr?: string[];\n scopeAttr?: string[];\n sort?: string;\n}\n\ninterface MetricsDiscoverOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n}\n\nexport function createMetricsCommand(): Command {\n const metrics = new Command(\"metrics\").description(\"Query metrics\");\n\n withConnectionOptions(\n metrics\n .command(\"search\")\n .description(\"Search metrics\")\n .requiredOption(\n \"--type <type>\",\n \"Metric type (Gauge|Sum|Histogram|ExponentialHistogram|Summary)\"\n )\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"-n, --name <name>\", \"Filter by metric name\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--time-min <ns>\", \"Min time (nanoseconds)\")\n .option(\"--time-max <ns>\", \"Max time (nanoseconds)\")\n .option(\n \"-a, --attr <key=value>\",\n \"Attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--scope-attr <key=value>\",\n \"Scope attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: MetricsSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n metricType: opts.type as\n | \"Gauge\"\n | \"Sum\"\n | \"Histogram\"\n | \"ExponentialHistogram\"\n | \"Summary\",\n metricName: opts.name,\n serviceName: opts.service,\n scopeName: opts.scope,\n timeUnixMin: opts.timeMin,\n timeUnixMax: opts.timeMax,\n attributes: parseAttributes(opts.attr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n scopeAttributes: parseAttributes(opts.scopeAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchMetricsPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n withConnectionOptions(\n metrics\n .command(\"discover\")\n .description(\"List available metrics\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n ).action(async (opts: MetricsDiscoverOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const result = await client.discoverMetrics();\n output(result.metrics, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return metrics;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { createTracesCommand } from \"./commands/traces.js\";\nimport { createLogsCommand } from \"./commands/logs.js\";\nimport { createMetricsCommand } from \"./commands/metrics.js\";\nimport pkg from \"../package.json\" with { type: \"json\" };\n\nconst program = new Command();\n\nprogram\n .name(\"@kopai/cli\")\n .description(\"|--k> kopai - Query OpenTelemetry data\")\n .version(pkg.version)\n .addCommand(createTracesCommand())\n .addCommand(createLogsCommand())\n .addCommand(createMetricsCommand())\n .addHelpText(\n \"after\",\n `\nExamples:\n $ kopai traces search # localhost:8000 (default, for @kopai/app running locally)\n $ kopai traces search --url https://example.com/signals # remote instance\n $ kopai logs search --url https://example.com/signals --token kpi_… # with auth`\n );\n\nprogram.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["DEFAULT_URL","collect","collect","DEFAULT_URL","DEFAULT_URL","pkg.version"],"sources":["../src/config.ts","../src/client.ts","../src/output.ts","../src/commands/traces.ts","../src/commands/logs.ts","../src/commands/metrics.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/commands/whoami.ts","../package.json","../src/index.ts"],"sourcesContent":["import { readFileSync, existsSync, writeFileSync, chmodSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface Config {\n url?: string;\n token?: string;\n}\n\nexport const CONFIG_FILENAME = \".kopairc\";\nexport const TOKEN_PREFIX_LENGTH = 10;\nexport const DEFAULT_URL = \"http://localhost:8000/signals\";\n\n/** Owner read+write only (rw-------). Used for files containing secrets. */\nconst OWNER_READ_WRITE = 0o600;\n\nfunction loadConfigFile(path: string): Config | null {\n if (!existsSync(path)) return null;\n try {\n const content = readFileSync(path, \"utf-8\");\n return JSON.parse(content) as Config;\n } catch {\n return null;\n }\n}\n\nexport function loadConfig(configPath?: string): Config {\n // Priority: --config flag > ./.kopairc > ~/.kopairc\n const paths = configPath\n ? [configPath]\n : [join(process.cwd(), CONFIG_FILENAME), join(homedir(), CONFIG_FILENAME)];\n\n for (const path of paths) {\n const config = loadConfigFile(path);\n if (config) return config;\n }\n\n return {};\n}\n\nexport function resolveConfigPath(global: boolean): string {\n return global\n ? join(homedir(), CONFIG_FILENAME)\n : join(process.cwd(), CONFIG_FILENAME);\n}\n\nexport function saveConfig(updates: Partial<Config>, targetPath: string): void {\n let existing: Config = {};\n if (existsSync(targetPath)) {\n try {\n const content = readFileSync(targetPath, \"utf-8\");\n existing = JSON.parse(content) as Config;\n } catch {\n // ignore parse errors, overwrite\n }\n }\n const merged = { ...existing, ...updates };\n writeFileSync(targetPath, JSON.stringify(merged, null, 2) + \"\\n\", {\n encoding: \"utf-8\",\n mode: OWNER_READ_WRITE,\n });\n chmodSync(targetPath, OWNER_READ_WRITE);\n}\n\nexport function removeConfigToken(targetPath: string): boolean {\n if (!existsSync(targetPath)) return false;\n try {\n const content = readFileSync(targetPath, \"utf-8\");\n const config = JSON.parse(content) as Config;\n if (!config.token) return false;\n delete config.token;\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\", {\n encoding: \"utf-8\",\n mode: OWNER_READ_WRITE,\n });\n } catch {\n return false;\n }\n try {\n chmodSync(targetPath, OWNER_READ_WRITE);\n } catch {\n // chmod failure does not affect the successful token removal\n }\n return true;\n}\n","import type { Command } from \"commander\";\nimport { KopaiClient } from \"@kopai/sdk\";\nimport { loadConfig } from \"./config.js\";\n\nexport function withConnectionOptions<T extends Command>(cmd: T): T {\n return cmd\n .option(\"--url <url>\", \"API base URL\")\n .option(\"--token <token>\", \"Auth token\")\n .option(\"-c, --config <path>\", \"Config file path\")\n .option(\"--timeout <ms>\", \"Request timeout\") as T;\n}\n\nexport interface ClientOptions {\n config?: string;\n url?: string;\n token?: string;\n timeout?: number;\n}\n\nconst DEFAULT_URL = \"http://localhost:8000/signals\";\n\nexport function createClient(opts: ClientOptions): KopaiClient {\n const fileConfig = loadConfig(opts.config);\n\n const url = opts.url ?? fileConfig.url ?? DEFAULT_URL;\n const token = opts.token ?? fileConfig.token;\n\n const timeout =\n opts.timeout != null ? parseInt(String(opts.timeout), 10) : undefined;\n\n return new KopaiClient({\n baseUrl: url,\n token,\n timeout: Number.isNaN(timeout) ? undefined : timeout,\n });\n}\n\nexport function parseAttributes(attrs?: string[]): Record<string, string> {\n if (!attrs || attrs.length === 0) return {};\n const result: Record<string, string> = {};\n for (const attr of attrs) {\n const idx = attr.indexOf(\"=\");\n if (idx === -1) {\n console.error(`Invalid attribute format: ${attr}. Use key=value`);\n process.exit(2);\n }\n result[attr.slice(0, idx)] = attr.slice(idx + 1);\n }\n return result;\n}\n","export type OutputFormat = \"json\" | \"table\";\n\nexport interface OutputOptions {\n format: OutputFormat;\n fields?: string[];\n}\n\nexport function detectFormat(json?: boolean, table?: boolean): OutputFormat {\n if (json) return \"json\";\n if (table) return \"table\";\n // Default: table for TTY, JSON for pipes\n return process.stdout.isTTY ? \"table\" : \"json\";\n}\n\nfunction countAttributes(attr: { values: Record<string, string[]> }): number {\n return Object.keys(attr.values).length;\n}\n\nfunction filterFields<T extends object>(data: T, fields: string[]): Partial<T> {\n return Object.fromEntries(\n Object.entries(data).filter(([key]) => fields.includes(key))\n ) as Partial<T>;\n}\n\nexport function parseFields(fieldsStr?: string): string[] | undefined {\n if (!fieldsStr) return undefined;\n return fieldsStr.split(\",\").map((f) => f.trim());\n}\n\nfunction isMetricsDiscoverData(data: unknown[]): data is Array<{\n attributes: { values: Record<string, string[]> };\n resourceAttributes: { values: Record<string, string[]> };\n}> {\n return (\n data.length > 0 &&\n typeof data[0] === \"object\" &&\n data[0] !== null &&\n \"attributes\" in data[0] &&\n \"resourceAttributes\" in data[0] &&\n typeof (data[0] as Record<string, unknown>).attributes === \"object\" &&\n (data[0] as Record<string, unknown>).attributes !== null &&\n \"values\" in ((data[0] as Record<string, unknown>).attributes as object)\n );\n}\n\nexport function output<T>(data: T, opts: OutputOptions): void {\n let outputData = data;\n\n // Apply field filtering\n if (opts.fields && opts.fields.length > 0) {\n if (Array.isArray(data)) {\n outputData = data.map((item) =>\n typeof item === \"object\" && item !== null\n ? filterFields(item as object, opts.fields!)\n : item\n ) as T;\n } else if (typeof data === \"object\" && data !== null) {\n outputData = filterFields(data as object, opts.fields) as T;\n }\n }\n\n if (opts.format === \"json\") {\n console.log(JSON.stringify(outputData, null, 2));\n } else {\n if (Array.isArray(outputData)) {\n if (outputData.length === 0) {\n console.log(\"No results found.\");\n } else if (!opts.fields && isMetricsDiscoverData(outputData)) {\n const transformed = outputData.map((m) => ({\n name: m.name,\n type: m.type,\n unit: m.unit,\n description: m.description,\n attrs: countAttributes(m.attributes),\n resourceAttrs: countAttributes(m.resourceAttributes),\n }));\n console.table(transformed);\n console.log(\"\\nUse --json for full attribute details.\");\n } else {\n console.table(outputData);\n }\n } else {\n console.log(outputData);\n }\n }\n}\n\nexport function outputError(error: unknown, json: boolean): void {\n const err =\n error instanceof Error\n ? { name: error.name, message: error.message }\n : { message: String(error) };\n\n if (json) {\n console.error(JSON.stringify({ error: err }));\n } else {\n console.error(`Error: ${err.message}`);\n }\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface TracesGetOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n}\n\ninterface TracesSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n traceId?: string;\n spanId?: string;\n parentSpanId?: string;\n service?: string;\n spanName?: string;\n spanKind?: string;\n statusCode?: string;\n scope?: string;\n timestampMin?: string;\n timestampMax?: string;\n durationMin?: string;\n durationMax?: string;\n spanAttr?: string[];\n resourceAttr?: string[];\n sort?: string;\n}\n\nexport function createTracesCommand(): Command {\n const traces = new Command(\"traces\").description(\"Query traces\");\n\n withConnectionOptions(\n traces\n .command(\"get\")\n .description(\"Get all spans for a trace by ID\")\n .argument(\"<traceId>\", \"Trace ID\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n ).action(async (traceId: string, opts: TracesGetOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const spans = await client.getTrace(traceId);\n output(spans, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n withConnectionOptions(\n traces\n .command(\"search\")\n .description(\"Search traces\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"--trace-id <id>\", \"Filter by trace ID\")\n .option(\"--span-id <id>\", \"Filter by span ID\")\n .option(\"--parent-span-id <id>\", \"Filter by parent span ID\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--span-name <name>\", \"Filter by span name\")\n .option(\"--span-kind <kind>\", \"Filter by span kind\")\n .option(\"--status-code <code>\", \"Filter by status code\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--timestamp-min <ns>\", \"Min timestamp (nanoseconds)\")\n .option(\"--timestamp-max <ns>\", \"Max timestamp (nanoseconds)\")\n .option(\"--duration-min <ns>\", \"Min duration (nanoseconds)\")\n .option(\"--duration-max <ns>\", \"Max duration (nanoseconds)\")\n .option(\n \"--span-attr <key=value>\",\n \"Span attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: TracesSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n traceId: opts.traceId,\n spanId: opts.spanId,\n parentSpanId: opts.parentSpanId,\n serviceName: opts.service,\n spanName: opts.spanName,\n spanKind: opts.spanKind,\n statusCode: opts.statusCode,\n scopeName: opts.scope,\n timestampMin: opts.timestampMin,\n timestampMax: opts.timestampMax,\n durationMin: opts.durationMin,\n durationMax: opts.durationMax,\n spanAttributes: parseAttributes(opts.spanAttr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchTracesPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return traces;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface LogsSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n traceId?: string;\n spanId?: string;\n service?: string;\n scope?: string;\n severityText?: string;\n severityMin?: string;\n severityMax?: string;\n body?: string;\n timestampMin?: string;\n timestampMax?: string;\n logAttr?: string[];\n resourceAttr?: string[];\n scopeAttr?: string[];\n sort?: string;\n}\n\nexport function createLogsCommand(): Command {\n const logs = new Command(\"logs\").description(\"Query logs\");\n\n withConnectionOptions(\n logs\n .command(\"search\")\n .description(\"Search logs\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"--trace-id <id>\", \"Filter by trace ID\")\n .option(\"--span-id <id>\", \"Filter by span ID\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--severity-text <level>\", \"Filter by severity text\")\n .option(\"--severity-min <n>\", \"Min severity number\")\n .option(\"--severity-max <n>\", \"Max severity number\")\n .option(\"-b, --body <text>\", \"Filter by body contains\")\n .option(\"--timestamp-min <ns>\", \"Min timestamp (nanoseconds)\")\n .option(\"--timestamp-max <ns>\", \"Max timestamp (nanoseconds)\")\n .option(\n \"--log-attr <key=value>\",\n \"Log attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--scope-attr <key=value>\",\n \"Scope attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: LogsSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n traceId: opts.traceId,\n spanId: opts.spanId,\n serviceName: opts.service,\n scopeName: opts.scope,\n severityText: opts.severityText,\n severityNumberMin: opts.severityMin\n ? parseInt(opts.severityMin, 10)\n : undefined,\n severityNumberMax: opts.severityMax\n ? parseInt(opts.severityMax, 10)\n : undefined,\n bodyContains: opts.body,\n timestampMin: opts.timestampMin,\n timestampMax: opts.timestampMax,\n logAttributes: parseAttributes(opts.logAttr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n scopeAttributes: parseAttributes(opts.scopeAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchLogsPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return logs;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface MetricsSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n type: string;\n name?: string;\n service?: string;\n scope?: string;\n timeMin?: string;\n timeMax?: string;\n attr?: string[];\n resourceAttr?: string[];\n scopeAttr?: string[];\n sort?: string;\n}\n\ninterface MetricsDiscoverOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n}\n\nexport function createMetricsCommand(): Command {\n const metrics = new Command(\"metrics\").description(\"Query metrics\");\n\n withConnectionOptions(\n metrics\n .command(\"search\")\n .description(\"Search metrics\")\n .requiredOption(\n \"--type <type>\",\n \"Metric type (Gauge|Sum|Histogram|ExponentialHistogram|Summary)\"\n )\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"-n, --name <name>\", \"Filter by metric name\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--time-min <ns>\", \"Min time (nanoseconds)\")\n .option(\"--time-max <ns>\", \"Max time (nanoseconds)\")\n .option(\n \"-a, --attr <key=value>\",\n \"Attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--scope-attr <key=value>\",\n \"Scope attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: MetricsSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n metricType: opts.type as\n | \"Gauge\"\n | \"Sum\"\n | \"Histogram\"\n | \"ExponentialHistogram\"\n | \"Summary\",\n metricName: opts.name,\n serviceName: opts.service,\n scopeName: opts.scope,\n timeUnixMin: opts.timeMin,\n timeUnixMax: opts.timeMax,\n attributes: parseAttributes(opts.attr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n scopeAttributes: parseAttributes(opts.scopeAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchMetricsPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n withConnectionOptions(\n metrics\n .command(\"discover\")\n .description(\"List available metrics\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n ).action(async (opts: MetricsDiscoverOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const result = await client.discoverMetrics();\n output(result.metrics, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return metrics;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport { createInterface } from \"node:readline\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n saveConfig,\n resolveConfigPath,\n TOKEN_PREFIX_LENGTH,\n DEFAULT_URL,\n type Config,\n} from \"../config.js\";\n\nfunction readTokenFromStdin(): Promise<string> {\n return new Promise((resolve) => {\n const rl = createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n rl.question(\"Token: \", (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nexport function createLoginCommand(): Command {\n return new Command(\"login\")\n .description(\"Save an API token to .kopairc\")\n .option(\"--url <url>\", \"API base URL to save alongside token\")\n .option(\"--global\", \"Write to ~/.kopairc instead of ./.kopairc\")\n .action(async (opts: { url?: string; global?: boolean }) => {\n const token = await readTokenFromStdin();\n if (!token) {\n console.error(\"Token cannot be empty.\");\n process.exitCode = 2;\n return;\n }\n\n const updates: Partial<Config> = {\n token,\n url: opts.url ?? DEFAULT_URL,\n };\n\n const targetPath = resolveConfigPath(opts.global ?? false);\n saveConfig(updates, targetPath);\n\n // Warn if in a git repo and .kopairc is not gitignored\n if (!opts.global) {\n const gitDir = join(process.cwd(), \".git\");\n if (existsSync(gitDir)) {\n const gitignorePath = join(process.cwd(), \".gitignore\");\n let isIgnored = false;\n if (existsSync(gitignorePath)) {\n const content = readFileSync(gitignorePath, \"utf-8\");\n isIgnored = content\n .split(\"\\n\")\n .some((line) => line.trim() === \".kopairc\");\n }\n if (!isIgnored) {\n console.error(\n \"Warning: .kopairc is not in .gitignore. Add it to avoid committing secrets.\"\n );\n }\n }\n }\n\n console.log(\n `Logged in. Token: ${token.slice(0, TOKEN_PREFIX_LENGTH)}...`\n );\n });\n}\n","import { Command } from \"commander\";\nimport { removeConfigToken, resolveConfigPath } from \"../config.js\";\n\nexport function createLogoutCommand(): Command {\n return new Command(\"logout\")\n .description(\"Remove saved API token from .kopairc\")\n .option(\"--global\", \"Remove from ~/.kopairc instead of ./.kopairc\")\n .action((opts: { global?: boolean }) => {\n const targetPath = resolveConfigPath(opts.global ?? false);\n const removed = removeConfigToken(targetPath);\n\n if (removed) {\n console.log(\"Logged out.\");\n } else {\n console.log(\"Not logged in.\");\n }\n });\n}\n","import { Command } from \"commander\";\nimport { KopaiClient } from \"@kopai/sdk\";\nimport { loadConfig, TOKEN_PREFIX_LENGTH, DEFAULT_URL } from \"../config.js\";\n\nexport function createWhoamiCommand(): Command {\n return new Command(\"whoami\")\n .description(\"Show current authentication status\")\n .option(\"-c, --config <path>\", \"Config file path\")\n .action(async (opts: { config?: string }) => {\n const config = loadConfig(opts.config);\n\n if (!config.token) {\n console.log(\"Not logged in.\");\n return;\n }\n\n console.log(`Token: ${config.token.slice(0, TOKEN_PREFIX_LENGTH)}...`);\n console.log(`URL: ${config.url ?? `${DEFAULT_URL} (default)`}`);\n\n // Try to validate token against server\n try {\n const client = new KopaiClient({\n baseUrl: config.url ?? DEFAULT_URL,\n token: config.token,\n });\n await client.searchTracesPage({ limit: 1 });\n console.log(\"Token is valid.\");\n } catch (err: unknown) {\n const status =\n err && typeof err === \"object\" && \"status\" in err\n ? (err as { status: number }).status\n : undefined;\n if (status === 401) {\n console.log(\"Token is invalid or expired.\");\n } else {\n console.log(\"Could not reach server to validate token.\");\n }\n process.exitCode = 1;\n }\n });\n}\n","","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { createTracesCommand } from \"./commands/traces.js\";\nimport { createLogsCommand } from \"./commands/logs.js\";\nimport { createMetricsCommand } from \"./commands/metrics.js\";\nimport { createLoginCommand } from \"./commands/login.js\";\nimport { createLogoutCommand } from \"./commands/logout.js\";\nimport { createWhoamiCommand } from \"./commands/whoami.js\";\nimport pkg from \"../package.json\" with { type: \"json\" };\n\nconst program = new Command();\n\nprogram\n .name(\"@kopai/cli\")\n .description(\"|--k> kopai - Query OpenTelemetry data\")\n .version(pkg.version)\n .addCommand(createTracesCommand())\n .addCommand(createLogsCommand())\n .addCommand(createMetricsCommand())\n .addCommand(createLoginCommand())\n .addCommand(createLogoutCommand())\n .addCommand(createWhoamiCommand())\n .addHelpText(\n \"after\",\n `\nExamples:\n $ kopai traces search # localhost:8000 (default, for @kopai/app running locally)\n $ kopai traces search --url https://example.com/signals # remote instance\n $ kopai logs search --url https://example.com/signals --token kpi_… # with auth`\n );\n\nprogram.parse();\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kopai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "CLI for querying OpenTelemetry data from Kopai - traces, logs, and metrics",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"opentelemetry",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"commander": "^14.0.3",
|
|
39
|
-
"@kopai/core": "0.
|
|
40
|
-
"@kopai/sdk": "0.3.
|
|
39
|
+
"@kopai/core": "0.6.0",
|
|
40
|
+
"@kopai/sdk": "0.3.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"tsdown": "^0.20.3",
|