@wervt/cli 0.1.0 → 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/index.mjs +87 -3
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, join, relative, resolve } from "node:path";
|
|
4
|
+
import { styleText } from "node:util";
|
|
4
5
|
import * as p from "@clack/prompts";
|
|
5
6
|
import { defineCommand, runMain } from "citty";
|
|
6
7
|
import { detectPackageManager } from "nypm";
|
|
@@ -78,7 +79,7 @@ const connection = {
|
|
|
78
79
|
},
|
|
79
80
|
token: {
|
|
80
81
|
type: "string",
|
|
81
|
-
description: "Deploy token (or WERVT_TOKEN)"
|
|
82
|
+
description: "Deploy or read token (or WERVT_TOKEN)"
|
|
82
83
|
}
|
|
83
84
|
};
|
|
84
85
|
async function api(path, flags, init = {}) {
|
|
@@ -91,7 +92,12 @@ async function api(path, flags, init = {}) {
|
|
|
91
92
|
});
|
|
92
93
|
if (!res.ok) {
|
|
93
94
|
const body = await res.text();
|
|
94
|
-
|
|
95
|
+
let message = body;
|
|
96
|
+
try {
|
|
97
|
+
message = JSON.parse(body).error ?? body;
|
|
98
|
+
} catch {}
|
|
99
|
+
console.error(styleText("red", `Error (${res.status}): ${message}`));
|
|
100
|
+
process.exit(1);
|
|
95
101
|
}
|
|
96
102
|
return res;
|
|
97
103
|
}
|
|
@@ -409,6 +415,83 @@ const remove = defineCommand({
|
|
|
409
415
|
console.log(`Deleted ${args.app}${dropDb ? " and its database" : ""}`);
|
|
410
416
|
}
|
|
411
417
|
});
|
|
418
|
+
const LEVEL_COLORS = {
|
|
419
|
+
error: "red",
|
|
420
|
+
warn: "yellow",
|
|
421
|
+
info: "cyan",
|
|
422
|
+
debug: "gray"
|
|
423
|
+
};
|
|
424
|
+
/** `09:07:52.060 error <message>`, or the entry as one JSON line. */
|
|
425
|
+
function printLog(entry, asJson) {
|
|
426
|
+
if (asJson) return console.log(JSON.stringify(entry));
|
|
427
|
+
const time = new Date(entry._time).toISOString().slice(11, 23);
|
|
428
|
+
const level = String(entry.level ?? "info");
|
|
429
|
+
const color = LEVEL_COLORS[level] ?? "white";
|
|
430
|
+
console.log(`${styleText("dim", time)} ${styleText(color, level.padEnd(5))} ${entry._msg ?? ""}`);
|
|
431
|
+
}
|
|
432
|
+
const logs = defineCommand({
|
|
433
|
+
meta: {
|
|
434
|
+
name: "logs",
|
|
435
|
+
description: "Show an app's logs: console output, request events and isolate events"
|
|
436
|
+
},
|
|
437
|
+
args: {
|
|
438
|
+
app: {
|
|
439
|
+
type: "positional",
|
|
440
|
+
required: true,
|
|
441
|
+
description: "App name"
|
|
442
|
+
},
|
|
443
|
+
query: {
|
|
444
|
+
type: "positional",
|
|
445
|
+
required: false,
|
|
446
|
+
description: "LogsQL filter, e.g. 'level:error' or 'status:>=500' (default: all)"
|
|
447
|
+
},
|
|
448
|
+
since: {
|
|
449
|
+
type: "string",
|
|
450
|
+
default: "1h",
|
|
451
|
+
description: "How far back, e.g. 15m, 6h, 2d"
|
|
452
|
+
},
|
|
453
|
+
until: {
|
|
454
|
+
type: "string",
|
|
455
|
+
description: "End of the range (default: now)"
|
|
456
|
+
},
|
|
457
|
+
limit: {
|
|
458
|
+
type: "string",
|
|
459
|
+
default: "100",
|
|
460
|
+
description: "Newest entries to show (max 1000)"
|
|
461
|
+
},
|
|
462
|
+
follow: {
|
|
463
|
+
type: "boolean",
|
|
464
|
+
alias: "f",
|
|
465
|
+
description: "Keep printing new entries"
|
|
466
|
+
},
|
|
467
|
+
json: {
|
|
468
|
+
type: "boolean",
|
|
469
|
+
description: "One JSON object per line, with every field"
|
|
470
|
+
},
|
|
471
|
+
...connection
|
|
472
|
+
},
|
|
473
|
+
async run({ args }) {
|
|
474
|
+
const params = new URLSearchParams();
|
|
475
|
+
if (args.query) params.set("query", args.query);
|
|
476
|
+
if (args.follow) {
|
|
477
|
+
params.set("since", args.since);
|
|
478
|
+
const res = await api(`/v1/apps/${args.app}/logs/tail?${params.toString()}`, args);
|
|
479
|
+
let rest = "";
|
|
480
|
+
for await (const chunk of res.body.pipeThrough(new TextDecoderStream())) {
|
|
481
|
+
const lines = (rest + chunk).split("\n");
|
|
482
|
+
rest = lines.pop() ?? "";
|
|
483
|
+
for (const line of lines) if (line) printLog(JSON.parse(line), Boolean(args.json));
|
|
484
|
+
}
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
params.set("start", args.since);
|
|
488
|
+
if (args.until) params.set("end", args.until);
|
|
489
|
+
params.set("limit", args.limit);
|
|
490
|
+
const entries = await (await api(`/v1/apps/${args.app}/logs?${params.toString()}`, args)).json();
|
|
491
|
+
if (!entries.length && !args.json) return console.error(`No logs in the last ${args.since}.`);
|
|
492
|
+
for (const entry of entries.reverse()) printLog(entry, Boolean(args.json));
|
|
493
|
+
}
|
|
494
|
+
});
|
|
412
495
|
const login = defineCommand({
|
|
413
496
|
meta: {
|
|
414
497
|
name: "login",
|
|
@@ -423,7 +506,7 @@ const login = defineCommand({
|
|
|
423
506
|
token: {
|
|
424
507
|
type: "string",
|
|
425
508
|
required: true,
|
|
426
|
-
description: "Deploy token"
|
|
509
|
+
description: "Deploy token, or the read token"
|
|
427
510
|
}
|
|
428
511
|
},
|
|
429
512
|
async run({ args }) {
|
|
@@ -445,6 +528,7 @@ runMain(defineCommand({
|
|
|
445
528
|
deploy,
|
|
446
529
|
apps,
|
|
447
530
|
releases,
|
|
531
|
+
logs,
|
|
448
532
|
activate,
|
|
449
533
|
rollback,
|
|
450
534
|
reprovision,
|