@sendly/cli 1.0.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/README.md +323 -0
- package/bin/run.js +5 -0
- package/dist/commands/config/get.d.ts +13 -0
- package/dist/commands/config/get.js +38 -0
- package/dist/commands/config/list.d.ts +10 -0
- package/dist/commands/config/list.js +45 -0
- package/dist/commands/config/set.d.ts +14 -0
- package/dist/commands/config/set.js +67 -0
- package/dist/commands/credits/balance.d.ts +10 -0
- package/dist/commands/credits/balance.js +38 -0
- package/dist/commands/credits/history.d.ts +11 -0
- package/dist/commands/credits/history.js +88 -0
- package/dist/commands/doctor.d.ts +23 -0
- package/dist/commands/doctor.js +336 -0
- package/dist/commands/keys/create.d.ts +12 -0
- package/dist/commands/keys/create.js +47 -0
- package/dist/commands/keys/list.d.ts +10 -0
- package/dist/commands/keys/list.js +65 -0
- package/dist/commands/keys/revoke.d.ts +15 -0
- package/dist/commands/keys/revoke.js +68 -0
- package/dist/commands/login.d.ts +12 -0
- package/dist/commands/login.js +114 -0
- package/dist/commands/logout.d.ts +10 -0
- package/dist/commands/logout.js +20 -0
- package/dist/commands/logs/tail.d.ts +17 -0
- package/dist/commands/logs/tail.js +183 -0
- package/dist/commands/sms/batch.d.ts +16 -0
- package/dist/commands/sms/batch.js +163 -0
- package/dist/commands/sms/cancel.d.ts +13 -0
- package/dist/commands/sms/cancel.js +46 -0
- package/dist/commands/sms/get.d.ts +13 -0
- package/dist/commands/sms/get.js +51 -0
- package/dist/commands/sms/list.d.ts +12 -0
- package/dist/commands/sms/list.js +79 -0
- package/dist/commands/sms/schedule.d.ts +14 -0
- package/dist/commands/sms/schedule.js +91 -0
- package/dist/commands/sms/scheduled.d.ts +12 -0
- package/dist/commands/sms/scheduled.js +82 -0
- package/dist/commands/sms/send.d.ts +13 -0
- package/dist/commands/sms/send.js +70 -0
- package/dist/commands/webhooks/list.d.ts +10 -0
- package/dist/commands/webhooks/list.js +80 -0
- package/dist/commands/webhooks/listen.d.ts +20 -0
- package/dist/commands/webhooks/listen.js +202 -0
- package/dist/commands/whoami.d.ts +10 -0
- package/dist/commands/whoami.js +51 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +27 -0
- package/dist/lib/api-client.d.ts +52 -0
- package/dist/lib/api-client.js +129 -0
- package/dist/lib/auth.d.ts +52 -0
- package/dist/lib/auth.js +171 -0
- package/dist/lib/base-command.d.ts +17 -0
- package/dist/lib/base-command.js +60 -0
- package/dist/lib/config.d.ts +54 -0
- package/dist/lib/config.js +182 -0
- package/dist/lib/output.d.ts +43 -0
- package/dist/lib/output.js +222 -0
- package/oclif.manifest.json +1147 -0
- package/package.json +98 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
import { AuthenticatedCommand } from "../../lib/base-command.js";
|
|
3
|
+
import { apiClient } from "../../lib/api-client.js";
|
|
4
|
+
import { table, json, info, formatRelativeTime, colors, isJsonMode, } from "../../lib/output.js";
|
|
5
|
+
export default class CreditsHistory extends AuthenticatedCommand {
|
|
6
|
+
static description = "View credit transaction history";
|
|
7
|
+
static examples = [
|
|
8
|
+
"<%= config.bin %> credits history",
|
|
9
|
+
"<%= config.bin %> credits history --limit 10",
|
|
10
|
+
"<%= config.bin %> credits history --json",
|
|
11
|
+
];
|
|
12
|
+
static flags = {
|
|
13
|
+
...AuthenticatedCommand.baseFlags,
|
|
14
|
+
limit: Flags.integer({
|
|
15
|
+
char: "l",
|
|
16
|
+
description: "Number of transactions to show",
|
|
17
|
+
default: 20,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
async run() {
|
|
21
|
+
const { flags } = await this.parse(CreditsHistory);
|
|
22
|
+
const response = await apiClient.get("/api/credits/transactions", { limit: flags.limit });
|
|
23
|
+
if (isJsonMode()) {
|
|
24
|
+
json(response.transactions);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (response.transactions.length === 0) {
|
|
28
|
+
info("No transactions found");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
console.log();
|
|
32
|
+
table(response.transactions, [
|
|
33
|
+
{
|
|
34
|
+
header: "Type",
|
|
35
|
+
key: "type",
|
|
36
|
+
width: 10,
|
|
37
|
+
formatter: (v) => {
|
|
38
|
+
switch (v) {
|
|
39
|
+
case "purchase":
|
|
40
|
+
return colors.success("purchase");
|
|
41
|
+
case "usage":
|
|
42
|
+
return colors.warning("usage");
|
|
43
|
+
case "bonus":
|
|
44
|
+
return colors.primary("bonus");
|
|
45
|
+
case "refund":
|
|
46
|
+
return colors.info("refund");
|
|
47
|
+
default:
|
|
48
|
+
return String(v);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
header: "Amount",
|
|
54
|
+
key: "amount",
|
|
55
|
+
width: 12,
|
|
56
|
+
formatter: (v) => {
|
|
57
|
+
const num = v;
|
|
58
|
+
if (num > 0) {
|
|
59
|
+
return colors.success(`+${num.toLocaleString()}`);
|
|
60
|
+
}
|
|
61
|
+
return colors.error(num.toLocaleString());
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
header: "Balance",
|
|
66
|
+
key: "balanceAfter",
|
|
67
|
+
width: 12,
|
|
68
|
+
formatter: (v) => `${v.toLocaleString()}`,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
header: "Description",
|
|
72
|
+
key: "description",
|
|
73
|
+
width: 35,
|
|
74
|
+
formatter: (v) => {
|
|
75
|
+
const desc = String(v);
|
|
76
|
+
return desc.length > 32 ? desc.slice(0, 32) + "..." : desc;
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
header: "When",
|
|
81
|
+
key: "createdAt",
|
|
82
|
+
width: 12,
|
|
83
|
+
formatter: (v) => formatRelativeTime(String(v)),
|
|
84
|
+
},
|
|
85
|
+
]);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGlzdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9jcmVkaXRzL2hpc3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNwQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDcEQsT0FBTyxFQUNMLEtBQUssRUFDTCxJQUFJLEVBQ0osSUFBSSxFQUNKLGtCQUFrQixFQUNsQixNQUFNLEVBQ04sVUFBVSxHQUNYLE1BQU0scUJBQXFCLENBQUM7QUFlN0IsTUFBTSxDQUFDLE9BQU8sT0FBTyxjQUFlLFNBQVEsb0JBQW9CO0lBQzlELE1BQU0sQ0FBQyxXQUFXLEdBQUcsaUNBQWlDLENBQUM7SUFFdkQsTUFBTSxDQUFDLFFBQVEsR0FBRztRQUNoQixtQ0FBbUM7UUFDbkMsOENBQThDO1FBQzlDLDBDQUEwQztLQUMzQyxDQUFDO0lBRUYsTUFBTSxDQUFDLEtBQUssR0FBRztRQUNiLEdBQUcsb0JBQW9CLENBQUMsU0FBUztRQUNqQyxLQUFLLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQztZQUNuQixJQUFJLEVBQUUsR0FBRztZQUNULFdBQVcsRUFBRSxnQ0FBZ0M7WUFDN0MsT0FBTyxFQUFFLEVBQUU7U0FDWixDQUFDO0tBQ0gsQ0FBQztJQUVGLEtBQUssQ0FBQyxHQUFHO1FBQ1AsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUVuRCxNQUFNLFFBQVEsR0FBRyxNQUFNLFNBQVMsQ0FBQyxHQUFHLENBQ2xDLDJCQUEyQixFQUMzQixFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQ3ZCLENBQUM7UUFFRixJQUFJLFVBQVUsRUFBRSxFQUFFLENBQUM7WUFDakIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUM1QixPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksUUFBUSxDQUFDLFlBQVksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDdkMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLENBQUM7WUFDOUIsT0FBTztRQUNULENBQUM7UUFFRCxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFZCxLQUFLLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRTtZQUMzQjtnQkFDRSxNQUFNLEVBQUUsTUFBTTtnQkFDZCxHQUFHLEVBQUUsTUFBTTtnQkFDWCxLQUFLLEVBQUUsRUFBRTtnQkFDVCxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtvQkFDZixRQUFRLENBQUMsRUFBRSxDQUFDO3dCQUNWLEtBQUssVUFBVTs0QkFDYixPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7d0JBQ3BDLEtBQUssT0FBTzs0QkFDVixPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7d0JBQ2pDLEtBQUssT0FBTzs0QkFDVixPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7d0JBQ2pDLEtBQUssUUFBUTs0QkFDWCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7d0JBQy9COzRCQUNFLE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNyQixDQUFDO2dCQUNILENBQUM7YUFDRjtZQUNEO2dCQUNFLE1BQU0sRUFBRSxRQUFRO2dCQUNoQixHQUFHLEVBQUUsUUFBUTtnQkFDYixLQUFLLEVBQUUsRUFBRTtnQkFDVCxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtvQkFDZixNQUFNLEdBQUcsR0FBRyxDQUFXLENBQUM7b0JBQ3hCLElBQUksR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDO3dCQUNaLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEdBQUcsQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDLENBQUM7b0JBQ3BELENBQUM7b0JBQ0QsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDO2dCQUM1QyxDQUFDO2FBQ0Y7WUFDRDtnQkFDRSxNQUFNLEVBQUUsU0FBUztnQkFDakIsR0FBRyxFQUFFLGNBQWM7Z0JBQ25CLEtBQUssRUFBRSxFQUFFO2dCQUNULFNBQVMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBSSxDQUFZLENBQUMsY0FBYyxFQUFFLEVBQUU7YUFDdEQ7WUFDRDtnQkFDRSxNQUFNLEVBQUUsYUFBYTtnQkFDckIsR0FBRyxFQUFFLGFBQWE7Z0JBQ2xCLEtBQUssRUFBRSxFQUFFO2dCQUNULFNBQVMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFO29CQUNmLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDdkIsT0FBTyxJQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQzdELENBQUM7YUFDRjtZQUNEO2dCQUNFLE1BQU0sRUFBRSxNQUFNO2dCQUNkLEdBQUcsRUFBRSxXQUFXO2dCQUNoQixLQUFLLEVBQUUsRUFBRTtnQkFDVCxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUNoRDtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGbGFncyB9IGZyb20gXCJAb2NsaWYvY29yZVwiO1xuaW1wb3J0IHsgQXV0aGVudGljYXRlZENvbW1hbmQgfSBmcm9tIFwiLi4vLi4vbGliL2Jhc2UtY29tbWFuZC5qc1wiO1xuaW1wb3J0IHsgYXBpQ2xpZW50IH0gZnJvbSBcIi4uLy4uL2xpYi9hcGktY2xpZW50LmpzXCI7XG5pbXBvcnQge1xuICB0YWJsZSxcbiAganNvbixcbiAgaW5mbyxcbiAgZm9ybWF0UmVsYXRpdmVUaW1lLFxuICBjb2xvcnMsXG4gIGlzSnNvbk1vZGUsXG59IGZyb20gXCIuLi8uLi9saWIvb3V0cHV0LmpzXCI7XG5cbmludGVyZmFjZSBUcmFuc2FjdGlvbiB7XG4gIGlkOiBzdHJpbmc7XG4gIGFtb3VudDogbnVtYmVyO1xuICBiYWxhbmNlQWZ0ZXI6IG51bWJlcjtcbiAgdHlwZTogXCJwdXJjaGFzZVwiIHwgXCJ1c2FnZVwiIHwgXCJib251c1wiIHwgXCJyZWZ1bmRcIjtcbiAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgY3JlYXRlZEF0OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBUcmFuc2FjdGlvbnNSZXNwb25zZSB7XG4gIHRyYW5zYWN0aW9uczogVHJhbnNhY3Rpb25bXTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ3JlZGl0c0hpc3RvcnkgZXh0ZW5kcyBBdXRoZW50aWNhdGVkQ29tbWFuZCB7XG4gIHN0YXRpYyBkZXNjcmlwdGlvbiA9IFwiVmlldyBjcmVkaXQgdHJhbnNhY3Rpb24gaGlzdG9yeVwiO1xuXG4gIHN0YXRpYyBleGFtcGxlcyA9IFtcbiAgICBcIjwlPSBjb25maWcuYmluICU+IGNyZWRpdHMgaGlzdG9yeVwiLFxuICAgIFwiPCU9IGNvbmZpZy5iaW4gJT4gY3JlZGl0cyBoaXN0b3J5IC0tbGltaXQgMTBcIixcbiAgICBcIjwlPSBjb25maWcuYmluICU+IGNyZWRpdHMgaGlzdG9yeSAtLWpzb25cIixcbiAgXTtcblxuICBzdGF0aWMgZmxhZ3MgPSB7XG4gICAgLi4uQXV0aGVudGljYXRlZENvbW1hbmQuYmFzZUZsYWdzLFxuICAgIGxpbWl0OiBGbGFncy5pbnRlZ2VyKHtcbiAgICAgIGNoYXI6IFwibFwiLFxuICAgICAgZGVzY3JpcHRpb246IFwiTnVtYmVyIG9mIHRyYW5zYWN0aW9ucyB0byBzaG93XCIsXG4gICAgICBkZWZhdWx0OiAyMCxcbiAgICB9KSxcbiAgfTtcblxuICBhc3luYyBydW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBmbGFncyB9ID0gYXdhaXQgdGhpcy5wYXJzZShDcmVkaXRzSGlzdG9yeSk7XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGFwaUNsaWVudC5nZXQ8VHJhbnNhY3Rpb25zUmVzcG9uc2U+KFxuICAgICAgXCIvYXBpL2NyZWRpdHMvdHJhbnNhY3Rpb25zXCIsXG4gICAgICB7IGxpbWl0OiBmbGFncy5saW1pdCB9XG4gICAgKTtcblxuICAgIGlmIChpc0pzb25Nb2RlKCkpIHtcbiAgICAgIGpzb24ocmVzcG9uc2UudHJhbnNhY3Rpb25zKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAocmVzcG9uc2UudHJhbnNhY3Rpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaW5mbyhcIk5vIHRyYW5zYWN0aW9ucyBmb3VuZFwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZygpO1xuXG4gICAgdGFibGUocmVzcG9uc2UudHJhbnNhY3Rpb25zLCBbXG4gICAgICB7XG4gICAgICAgIGhlYWRlcjogXCJUeXBlXCIsXG4gICAgICAgIGtleTogXCJ0eXBlXCIsXG4gICAgICAgIHdpZHRoOiAxMCxcbiAgICAgICAgZm9ybWF0dGVyOiAodikgPT4ge1xuICAgICAgICAgIHN3aXRjaCAodikge1xuICAgICAgICAgICAgY2FzZSBcInB1cmNoYXNlXCI6XG4gICAgICAgICAgICAgIHJldHVybiBjb2xvcnMuc3VjY2VzcyhcInB1cmNoYXNlXCIpO1xuICAgICAgICAgICAgY2FzZSBcInVzYWdlXCI6XG4gICAgICAgICAgICAgIHJldHVybiBjb2xvcnMud2FybmluZyhcInVzYWdlXCIpO1xuICAgICAgICAgICAgY2FzZSBcImJvbnVzXCI6XG4gICAgICAgICAgICAgIHJldHVybiBjb2xvcnMucHJpbWFyeShcImJvbnVzXCIpO1xuICAgICAgICAgICAgY2FzZSBcInJlZnVuZFwiOlxuICAgICAgICAgICAgICByZXR1cm4gY29sb3JzLmluZm8oXCJyZWZ1bmRcIik7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKHYpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGhlYWRlcjogXCJBbW91bnRcIixcbiAgICAgICAga2V5OiBcImFtb3VudFwiLFxuICAgICAgICB3aWR0aDogMTIsXG4gICAgICAgIGZvcm1hdHRlcjogKHYpID0+IHtcbiAgICAgICAgICBjb25zdCBudW0gPSB2IGFzIG51bWJlcjtcbiAgICAgICAgICBpZiAobnVtID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbG9ycy5zdWNjZXNzKGArJHtudW0udG9Mb2NhbGVTdHJpbmcoKX1gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGNvbG9ycy5lcnJvcihudW0udG9Mb2NhbGVTdHJpbmcoKSk7XG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBoZWFkZXI6IFwiQmFsYW5jZVwiLFxuICAgICAgICBrZXk6IFwiYmFsYW5jZUFmdGVyXCIsXG4gICAgICAgIHdpZHRoOiAxMixcbiAgICAgICAgZm9ybWF0dGVyOiAodikgPT4gYCR7KHYgYXMgbnVtYmVyKS50b0xvY2FsZVN0cmluZygpfWAsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBoZWFkZXI6IFwiRGVzY3JpcHRpb25cIixcbiAgICAgICAga2V5OiBcImRlc2NyaXB0aW9uXCIsXG4gICAgICAgIHdpZHRoOiAzNSxcbiAgICAgICAgZm9ybWF0dGVyOiAodikgPT4ge1xuICAgICAgICAgIGNvbnN0IGRlc2MgPSBTdHJpbmcodik7XG4gICAgICAgICAgcmV0dXJuIGRlc2MubGVuZ3RoID4gMzIgPyBkZXNjLnNsaWNlKDAsIDMyKSArIFwiLi4uXCIgOiBkZXNjO1xuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgaGVhZGVyOiBcIldoZW5cIixcbiAgICAgICAga2V5OiBcImNyZWF0ZWRBdFwiLFxuICAgICAgICB3aWR0aDogMTIsXG4gICAgICAgIGZvcm1hdHRlcjogKHYpID0+IGZvcm1hdFJlbGF0aXZlVGltZShTdHJpbmcodikpLFxuICAgICAgfSxcbiAgICBdKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sendly Doctor Command
|
|
3
|
+
* Diagnoses CLI setup and connectivity issues
|
|
4
|
+
*/
|
|
5
|
+
import { BaseCommand } from "../lib/base-command.js";
|
|
6
|
+
export default class Doctor extends BaseCommand {
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
json: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
11
|
+
quiet: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
private results;
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
private addResult;
|
|
16
|
+
private checkApiKey;
|
|
17
|
+
private checkNetwork;
|
|
18
|
+
private checkClockSkew;
|
|
19
|
+
private checkCredits;
|
|
20
|
+
private checkEnvironment;
|
|
21
|
+
private checkConfig;
|
|
22
|
+
private generateReport;
|
|
23
|
+
}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sendly Doctor Command
|
|
3
|
+
* Diagnoses CLI setup and connectivity issues
|
|
4
|
+
*/
|
|
5
|
+
import { BaseCommand } from "../lib/base-command.js";
|
|
6
|
+
import { isAuthenticated, getAuthToken, getConfigPath, getConfigDir, getEffectiveValue, isCI, isColorDisabled, } from "../lib/config.js";
|
|
7
|
+
import { success, error, warn, json, colors } from "../lib/output.js";
|
|
8
|
+
import * as fs from "node:fs";
|
|
9
|
+
export default class Doctor extends BaseCommand {
|
|
10
|
+
static description = "Diagnose CLI setup and connectivity issues";
|
|
11
|
+
static examples = [
|
|
12
|
+
"<%= config.bin %> doctor",
|
|
13
|
+
"<%= config.bin %> doctor --json",
|
|
14
|
+
];
|
|
15
|
+
static flags = {
|
|
16
|
+
...BaseCommand.baseFlags,
|
|
17
|
+
};
|
|
18
|
+
results = [];
|
|
19
|
+
async run() {
|
|
20
|
+
const { flags } = await this.parse(Doctor);
|
|
21
|
+
if (!flags.json) {
|
|
22
|
+
console.log();
|
|
23
|
+
console.log(colors.primary("Sendly CLI Diagnostics"));
|
|
24
|
+
console.log();
|
|
25
|
+
}
|
|
26
|
+
// Run all diagnostics
|
|
27
|
+
await this.checkApiKey();
|
|
28
|
+
await this.checkNetwork();
|
|
29
|
+
await this.checkClockSkew();
|
|
30
|
+
await this.checkCredits();
|
|
31
|
+
await this.checkEnvironment();
|
|
32
|
+
await this.checkConfig();
|
|
33
|
+
// Generate report
|
|
34
|
+
const report = this.generateReport();
|
|
35
|
+
if (flags.json) {
|
|
36
|
+
json(report);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Print summary
|
|
40
|
+
console.log();
|
|
41
|
+
if (report.summary.errors > 0) {
|
|
42
|
+
error(`${report.summary.errors} issue(s) found. Please resolve before using the CLI.`);
|
|
43
|
+
this.exit(1);
|
|
44
|
+
}
|
|
45
|
+
else if (report.summary.warnings > 0) {
|
|
46
|
+
warn(`${report.summary.warnings} warning(s). CLI should work but may have issues.`);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
success("All systems operational!");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
addResult(result) {
|
|
53
|
+
this.results.push(result);
|
|
54
|
+
// Print result immediately (unless in JSON mode)
|
|
55
|
+
const { flags } = this;
|
|
56
|
+
if (flags?.json)
|
|
57
|
+
return;
|
|
58
|
+
const icon = result.status === "ok"
|
|
59
|
+
? colors.success("\u2714")
|
|
60
|
+
: result.status === "warning"
|
|
61
|
+
? colors.warning("\u26A0")
|
|
62
|
+
: colors.error("\u2718");
|
|
63
|
+
console.log(`${icon} ${result.name}: ${result.message}`);
|
|
64
|
+
if (result.details) {
|
|
65
|
+
console.log(colors.dim(` ${result.details}`));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async checkApiKey() {
|
|
69
|
+
const token = getAuthToken();
|
|
70
|
+
const fromEnv = !!process.env.SENDLY_API_KEY;
|
|
71
|
+
if (!token) {
|
|
72
|
+
this.addResult({
|
|
73
|
+
name: "API Key",
|
|
74
|
+
status: "error",
|
|
75
|
+
message: "Not configured",
|
|
76
|
+
details: "Run 'sendly login' or set SENDLY_API_KEY environment variable",
|
|
77
|
+
});
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Check key format
|
|
81
|
+
const isTestKey = token.startsWith("sk_test_");
|
|
82
|
+
const isLiveKey = token.startsWith("sk_live_");
|
|
83
|
+
if (!isTestKey && !isLiveKey) {
|
|
84
|
+
this.addResult({
|
|
85
|
+
name: "API Key",
|
|
86
|
+
status: "error",
|
|
87
|
+
message: "Invalid format",
|
|
88
|
+
details: "API key should start with sk_test_ or sk_live_",
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const keyType = isTestKey ? "test" : "live";
|
|
93
|
+
const source = fromEnv ? "environment variable" : "config file";
|
|
94
|
+
this.addResult({
|
|
95
|
+
name: "API Key",
|
|
96
|
+
status: "ok",
|
|
97
|
+
message: `Valid (${keyType} mode, from ${source})`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async checkNetwork() {
|
|
101
|
+
const baseUrl = getEffectiveValue("baseUrl");
|
|
102
|
+
const startTime = Date.now();
|
|
103
|
+
try {
|
|
104
|
+
const response = await fetch(`${baseUrl}/health`, {
|
|
105
|
+
method: "GET",
|
|
106
|
+
signal: AbortSignal.timeout(10000),
|
|
107
|
+
});
|
|
108
|
+
const latency = Date.now() - startTime;
|
|
109
|
+
if (response.ok) {
|
|
110
|
+
this.addResult({
|
|
111
|
+
name: "Network",
|
|
112
|
+
status: "ok",
|
|
113
|
+
message: `Connected to ${new URL(baseUrl).host} (${latency}ms)`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
this.addResult({
|
|
118
|
+
name: "Network",
|
|
119
|
+
status: "warning",
|
|
120
|
+
message: `API returned ${response.status}`,
|
|
121
|
+
details: `Endpoint: ${baseUrl}/health`,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
this.addResult({
|
|
127
|
+
name: "Network",
|
|
128
|
+
status: "error",
|
|
129
|
+
message: "Cannot reach API",
|
|
130
|
+
details: err.message || "Check your internet connection",
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async checkClockSkew() {
|
|
135
|
+
const baseUrl = getEffectiveValue("baseUrl");
|
|
136
|
+
try {
|
|
137
|
+
const response = await fetch(`${baseUrl}/health`, {
|
|
138
|
+
method: "GET",
|
|
139
|
+
signal: AbortSignal.timeout(5000),
|
|
140
|
+
});
|
|
141
|
+
const serverDate = response.headers.get("date");
|
|
142
|
+
if (!serverDate) {
|
|
143
|
+
this.addResult({
|
|
144
|
+
name: "Clock",
|
|
145
|
+
status: "warning",
|
|
146
|
+
message: "Could not verify (no server date header)",
|
|
147
|
+
});
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const serverTime = new Date(serverDate).getTime();
|
|
151
|
+
const localTime = Date.now();
|
|
152
|
+
const skewSeconds = Math.abs(serverTime - localTime) / 1000;
|
|
153
|
+
if (skewSeconds > 300) {
|
|
154
|
+
// 5 minutes
|
|
155
|
+
this.addResult({
|
|
156
|
+
name: "Clock",
|
|
157
|
+
status: "error",
|
|
158
|
+
message: `Significant drift detected (${skewSeconds.toFixed(0)}s)`,
|
|
159
|
+
details: "This may cause webhook signature verification to fail",
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
else if (skewSeconds > 30) {
|
|
163
|
+
this.addResult({
|
|
164
|
+
name: "Clock",
|
|
165
|
+
status: "warning",
|
|
166
|
+
message: `Minor drift detected (${skewSeconds.toFixed(1)}s)`,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
this.addResult({
|
|
171
|
+
name: "Clock",
|
|
172
|
+
status: "ok",
|
|
173
|
+
message: `Synchronized (drift: ${skewSeconds.toFixed(1)}s)`,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
this.addResult({
|
|
179
|
+
name: "Clock",
|
|
180
|
+
status: "warning",
|
|
181
|
+
message: "Could not verify (network error)",
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async checkCredits() {
|
|
186
|
+
if (!isAuthenticated()) {
|
|
187
|
+
this.addResult({
|
|
188
|
+
name: "Credits",
|
|
189
|
+
status: "warning",
|
|
190
|
+
message: "Cannot check (not authenticated)",
|
|
191
|
+
});
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const baseUrl = getEffectiveValue("baseUrl");
|
|
195
|
+
const token = getAuthToken();
|
|
196
|
+
try {
|
|
197
|
+
const response = await fetch(`${baseUrl}/api/credits`, {
|
|
198
|
+
method: "GET",
|
|
199
|
+
headers: {
|
|
200
|
+
Authorization: `Bearer ${token}`,
|
|
201
|
+
"Content-Type": "application/json",
|
|
202
|
+
},
|
|
203
|
+
signal: AbortSignal.timeout(10000),
|
|
204
|
+
});
|
|
205
|
+
if (response.ok) {
|
|
206
|
+
const data = (await response.json());
|
|
207
|
+
const balance = data.balance || 0;
|
|
208
|
+
if (balance === 0) {
|
|
209
|
+
this.addResult({
|
|
210
|
+
name: "Credits",
|
|
211
|
+
status: "warning",
|
|
212
|
+
message: "0 available",
|
|
213
|
+
details: "Add credits to send messages",
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
this.addResult({
|
|
218
|
+
name: "Credits",
|
|
219
|
+
status: "ok",
|
|
220
|
+
message: `${balance.toLocaleString()} available`,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else if (response.status === 401) {
|
|
225
|
+
this.addResult({
|
|
226
|
+
name: "Credits",
|
|
227
|
+
status: "error",
|
|
228
|
+
message: "API key invalid or expired",
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
this.addResult({
|
|
233
|
+
name: "Credits",
|
|
234
|
+
status: "warning",
|
|
235
|
+
message: `Could not fetch (HTTP ${response.status})`,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
this.addResult({
|
|
241
|
+
name: "Credits",
|
|
242
|
+
status: "warning",
|
|
243
|
+
message: "Could not fetch",
|
|
244
|
+
details: err.message,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async checkEnvironment() {
|
|
249
|
+
const checks = [];
|
|
250
|
+
if (isCI()) {
|
|
251
|
+
checks.push("CI mode detected");
|
|
252
|
+
}
|
|
253
|
+
if (isColorDisabled()) {
|
|
254
|
+
checks.push("color disabled");
|
|
255
|
+
}
|
|
256
|
+
if (process.env.SENDLY_API_KEY) {
|
|
257
|
+
checks.push("using SENDLY_API_KEY env var");
|
|
258
|
+
}
|
|
259
|
+
if (process.env.SENDLY_BASE_URL) {
|
|
260
|
+
checks.push(`custom base URL: ${process.env.SENDLY_BASE_URL}`);
|
|
261
|
+
}
|
|
262
|
+
this.addResult({
|
|
263
|
+
name: "Environment",
|
|
264
|
+
status: "ok",
|
|
265
|
+
message: checks.length > 0 ? checks.join(", ") : "Standard terminal mode",
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
async checkConfig() {
|
|
269
|
+
const configPath = getConfigPath();
|
|
270
|
+
const configDir = getConfigDir();
|
|
271
|
+
// Check if config directory exists
|
|
272
|
+
if (!fs.existsSync(configDir)) {
|
|
273
|
+
this.addResult({
|
|
274
|
+
name: "Config",
|
|
275
|
+
status: "warning",
|
|
276
|
+
message: "Config directory not found",
|
|
277
|
+
details: `Expected: ${configDir}`,
|
|
278
|
+
});
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
// Check if config file exists
|
|
282
|
+
if (!fs.existsSync(configPath)) {
|
|
283
|
+
this.addResult({
|
|
284
|
+
name: "Config",
|
|
285
|
+
status: "warning",
|
|
286
|
+
message: "Config file not found (using defaults)",
|
|
287
|
+
details: configPath,
|
|
288
|
+
});
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
// Check file permissions (should be readable only by owner)
|
|
292
|
+
try {
|
|
293
|
+
const stats = fs.statSync(configPath);
|
|
294
|
+
const mode = stats.mode & 0o777;
|
|
295
|
+
if (mode & 0o077) {
|
|
296
|
+
// Group or others have access
|
|
297
|
+
this.addResult({
|
|
298
|
+
name: "Config",
|
|
299
|
+
status: "warning",
|
|
300
|
+
message: "Config file has loose permissions",
|
|
301
|
+
details: `${configPath} (mode: ${mode.toString(8)})`,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
this.addResult({
|
|
306
|
+
name: "Config",
|
|
307
|
+
status: "ok",
|
|
308
|
+
message: configPath,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
this.addResult({
|
|
314
|
+
name: "Config",
|
|
315
|
+
status: "ok",
|
|
316
|
+
message: configPath,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
generateReport() {
|
|
321
|
+
const passed = this.results.filter((r) => r.status === "ok").length;
|
|
322
|
+
const warnings = this.results.filter((r) => r.status === "warning").length;
|
|
323
|
+
const errors = this.results.filter((r) => r.status === "error").length;
|
|
324
|
+
return {
|
|
325
|
+
timestamp: new Date().toISOString(),
|
|
326
|
+
version: "1.0.0",
|
|
327
|
+
results: this.results,
|
|
328
|
+
summary: {
|
|
329
|
+
passed,
|
|
330
|
+
warnings,
|
|
331
|
+
errors,
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9jdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL2RvY3Rvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDckQsT0FBTyxFQUNMLGVBQWUsRUFDZixZQUFZLEVBQ1osYUFBYSxFQUNiLFlBQVksRUFDWixpQkFBaUIsRUFDakIsSUFBSSxFQUNKLGVBQWUsR0FDaEIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQVEsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzVFLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBcUI5QixNQUFNLENBQUMsT0FBTyxPQUFPLE1BQU8sU0FBUSxXQUFXO0lBQzdDLE1BQU0sQ0FBQyxXQUFXLEdBQUcsNENBQTRDLENBQUM7SUFFbEUsTUFBTSxDQUFDLFFBQVEsR0FBRztRQUNoQiwwQkFBMEI7UUFDMUIsaUNBQWlDO0tBQ2xDLENBQUM7SUFFRixNQUFNLENBQUMsS0FBSyxHQUFHO1FBQ2IsR0FBRyxXQUFXLENBQUMsU0FBUztLQUN6QixDQUFDO0lBRU0sT0FBTyxHQUF1QixFQUFFLENBQUM7SUFFekMsS0FBSyxDQUFDLEdBQUc7UUFDUCxNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTNDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDaEIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ2QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLHdCQUF3QixDQUFDLENBQUMsQ0FBQztZQUN0RCxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDaEIsQ0FBQztRQUVE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QyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDM0UsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLEtBQUssT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDO1FBRXZFLE9BQU87WUFDTCxTQUFTLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUU7WUFDbkMsT0FBTyxFQUFFLE9BQU87WUFDaEIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO1lBQ3JCLE9BQU8sRUFBRTtnQkFDUCxNQUFNO2dCQUNOLFFBQVE7Z0JBQ1IsTUFBTTthQUNQO1NBQ0YsQ0FBQztJQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNlbmRseSBEb2N0b3IgQ29tbWFuZFxuICogRGlhZ25vc2VzIENMSSBzZXR1cCBhbmQgY29ubmVjdGl2aXR5IGlzc3Vlc1xuICovXG5cbmltcG9ydCB7IEJhc2VDb21tYW5kIH0gZnJvbSBcIi4uL2xpYi9iYXNlLWNvbW1hbmQuanNcIjtcbmltcG9ydCB7XG4gIGlzQXV0aGVudGljYXRlZCxcbiAgZ2V0QXV0aFRva2VuLFxuICBnZXRDb25maWdQYXRoLFxuICBnZXRDb25maWdEaXIsXG4gIGdldEVmZmVjdGl2ZVZhbHVlLFxuICBpc0NJLFxuICBpc0NvbG9yRGlzYWJsZWQsXG59IGZyb20gXCIuLi9saWIvY29uZmlnLmpzXCI7XG5pbXBvcnQgeyBzdWNjZXNzLCBlcnJvciwgd2FybiwgaW5mbywganNvbiwgY29sb3JzIH0gZnJvbSBcIi4uL2xpYi9vdXRwdXQuanNcIjtcbmltcG9ydCAqIGFzIGZzIGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcblxuaW50ZXJmYWNlIERpYWdub3N0aWNSZXN1bHQge1xuICBuYW1lOiBzdHJpbmc7XG4gIHN0YXR1czogXCJva1wiIHwgXCJ3YXJuaW5nXCIgfCBcImVycm9yXCI7XG4gIG1lc3NhZ2U6IHN0cmluZztcbiAgZGV0YWlscz86IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIERvY3RvclJlcG9ydCB7XG4gIHRpbWVzdGFtcDogc3RyaW5nO1xuICB2ZXJzaW9uOiBzdHJpbmc7XG4gIHJlc3VsdHM6IERpYWdub3N0aWNSZXN1bHRbXTtcbiAgc3VtbWFyeToge1xuICAgIHBhc3NlZDogbnVtYmVyO1xuICAgIHdhcm5pbmdzOiBudW1iZXI7XG4gICAgZXJyb3JzOiBudW1iZXI7XG4gIH07XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERvY3RvciBleHRlbmRzIEJhc2VDb21tYW5kIHtcbiAgc3RhdGljIGRlc2NyaXB0aW9uID0gXCJEaWFnbm9zZSBDTEkgc2V0dXAgYW5kIGNvbm5lY3Rpdml0eSBpc3N1ZXNcIjtcblxuICBzdGF0aWMgZXhhbXBsZXMgPSBbXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiBkb2N0b3JcIixcbiAgICBcIjwlPSBjb25maWcuYmluICU+IGRvY3RvciAtLWpzb25cIixcbiAgXTtcblxuICBzdGF0aWMgZmxhZ3MgPSB7XG4gICAgLi4uQmFzZUNvbW1hbmQuYmFzZUZsYWdzLFxuICB9O1xuXG4gIHByaXZhdGUgcmVzdWx0czogRGlhZ25vc3RpY1Jlc3VsdFtdID0gW107XG5cbiAgYXN5bmMgcnVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgZmxhZ3MgfSA9IGF3YWl0IHRoaXMucGFyc2UoRG9jdG9yKTtcblxuICAgIGlmICghZmxhZ3MuanNvbikge1xuICAgICAgY29uc29sZS5sb2coKTtcbiAgICAgIGNvbnNvbGUubG9nKGNvbG9ycy5wcmltYXJ5KFwiU2VuZGx5IENMSSBEaWFnbm9zdGljc1wiKSk7XG4gICAgICBjb25zb2xlLmxvZygpO1xuICAgIH1cblxuICAgIC8vIFJ1biBhbGwgZGlhZ25vc3RpY3NcbiAgICBhd2FpdCB0aGlzLmNoZWNrQXBpS2V5KCk7XG4gICAgYXdhaXQgdGhpcy5jaGVja05ldHdvcmsoKTtcbiAgICBhd2FpdCB0aGlzLmNoZWNrQ2xvY2tTa2V3KCk7XG4gICAgYXdhaXQgdGhpcy5jaGVja0NyZWRpdHMoKTtcbiAgICBhd2FpdCB0aGlzLmNoZWNrRW52aXJvbm1lbnQoKTtcbiAgICBhd2FpdCB0aGlzLmNoZWNrQ29uZmlnKCk7XG5cbiAgICAvLyBHZW5lcmF0ZSByZXBvcnRcbiAgICBjb25zdCByZXBvcnQgPSB0aGlzLmdlbmVyYXRlUmVwb3J0KCk7XG5cbiAgICBpZiAoZmxhZ3MuanNvbikge1xuICAgICAganNvbihyZXBvcnQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFByaW50IHN1bW1hcnlcbiAgICBjb25zb2xlLmxvZygpO1xuICAgIGlmIChyZXBvcnQuc3VtbWFyeS5lcnJvcnMgPiAwKSB7XG4gICAgICBlcnJvcihcbiAgICAgICAgYCR7cmVwb3J0LnN1bW1hcnkuZXJyb3JzfSBpc3N1ZShzKSBmb3VuZC4gUGxlYXNlIHJlc29sdmUgYmVmb3JlIHVzaW5nIHRoZSBDTEkuYCxcbiAgICAgICk7XG4gICAgICB0aGlzLmV4aXQoMSk7XG4gICAgfSBlbHNlIGlmIChyZXBvcnQuc3VtbWFyeS53YXJuaW5ncyA+IDApIHtcbiAgICAgIHdhcm4oXG4gICAgICAgIGAke3JlcG9ydC5zdW1tYXJ5Lndhcm5pbmdzfSB3YXJuaW5nKHMpLiBDTEkgc2hvdWxkIHdvcmsgYnV0IG1heSBoYXZlIGlzc3Vlcy5gLFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3VjY2VzcyhcIkFsbCBzeXN0ZW1zIG9wZXJhdGlvbmFsIVwiKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFkZFJlc3VsdChyZXN1bHQ6IERpYWdub3N0aWNSZXN1bHQpOiB2b2lkIHtcbiAgICB0aGlzLnJlc3VsdHMucHVzaChyZXN1bHQpO1xuXG4gICAgLy8gUHJpbnQgcmVzdWx0IGltbWVkaWF0ZWx5ICh1bmxlc3MgaW4gSlNPTiBtb2RlKVxuICAgIGNvbnN0IHsgZmxhZ3MgfSA9IHRoaXMgYXMgYW55O1xuICAgIGlmIChmbGFncz8uanNvbikgcmV0dXJuO1xuXG4gICAgY29uc3QgaWNvbiA9XG4gICAgICByZXN1bHQuc3RhdHVzID09PSBcIm9rXCJcbiAgICAgICAgPyBjb2xvcnMuc3VjY2VzcyhcIlxcdTI3MTRcIilcbiAgICAgICAgOiByZXN1bHQuc3RhdHVzID09PSBcIndhcm5pbmdcIlxuICAgICAgICAgID8gY29sb3JzLndhcm5pbmcoXCJcXHUyNkEwXCIpXG4gICAgICAgICAgOiBjb2xvcnMuZXJyb3IoXCJcXHUyNzE4XCIpO1xuXG4gICAgY29uc29sZS5sb2coYCR7aWNvbn0gJHtyZXN1bHQubmFtZX06ICR7cmVzdWx0Lm1lc3NhZ2V9YCk7XG4gICAgaWYgKHJlc3VsdC5kZXRhaWxzKSB7XG4gICAgICBjb25zb2xlLmxvZyhjb2xvcnMuZGltKGAgICAke3Jlc3VsdC5kZXRhaWxzfWApKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNoZWNrQXBpS2V5KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHRva2VuID0gZ2V0QXV0aFRva2VuKCk7XG4gICAgY29uc3QgZnJvbUVudiA9ICEhcHJvY2Vzcy5lbnYuU0VORExZX0FQSV9LRVk7XG5cbiAgICBpZiAoIXRva2VuKSB7XG4gICAgICB0aGlzLmFkZFJlc3VsdCh7XG4gICAgICAgIG5hbWU6IFwiQVBJIEtleVwiLFxuICAgICAgICBzdGF0dXM6IFwiZXJyb3JcIixcbiAgICAgICAgbWVzc2FnZTogXCJOb3QgY29uZmlndXJlZFwiLFxuICAgICAgICBkZXRhaWxzOlxuICAgICAgICAgIFwiUnVuICdzZW5kbHkgbG9naW4nIG9yIHNldCBTRU5ETFlfQVBJX0tFWSBlbnZpcm9ubWVudCB2YXJpYWJsZVwiLFxuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sga2V5IGZvcm1hdFxuICAgIGNvbnN0IGlzVGVzdEtleSA9IHRva2VuLnN0YXJ0c1dpdGgoXCJza190ZXN0X1wiKTtcbiAgICBjb25zdCBpc0xpdmVLZXkgPSB0b2tlbi5zdGFydHNXaXRoKFwic2tfbGl2ZV9cIik7XG5cbiAgICBpZiAoIWlzVGVzdEtleSAmJiAhaXNMaXZlS2V5KSB7XG4gICAgICB0aGlzLmFkZFJlc3VsdCh7XG4gICAgICAgIG5hbWU6IFwiQVBJIEtleVwiLFxuICAgICAgICBzdGF0dXM6IFwiZXJyb3JcIixcbiAgICAgICAgbWVzc2FnZTogXCJJbnZhbGlkIGZvcm1hdFwiLFxuICAgICAgICBkZXRhaWxzOiBcIkFQSSBrZXkgc2hvdWxkIHN0YXJ0IHdpdGggc2tfdGVzdF8gb3Igc2tfbGl2ZV9cIixcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGtleVR5cGUgPSBpc1Rlc3RLZXkgPyBcInRlc3RcIiA6IFwibGl2ZVwiO1xuICAgIGNvbnN0IHNvdXJjZSA9IGZyb21FbnYgPyBcImVudmlyb25tZW50IHZhcmlhYmxlXCIgOiBcImNvbmZpZyBmaWxlXCI7XG5cbiAgICB0aGlzLmFkZFJlc3VsdCh7XG4gICAgICBuYW1lOiBcIkFQSSBLZXlcIixcbiAgICAgIHN0YXR1czogXCJva1wiLFxuICAgICAgbWVzc2FnZTogYFZhbGlkICgke2tleVR5cGV9IG1vZGUsIGZyb20gJHtzb3VyY2V9KWAsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNoZWNrTmV0d29yaygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBiYXNlVXJsID0gZ2V0RWZmZWN0aXZlVmFsdWUoXCJiYXNlVXJsXCIpO1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHtiYXNlVXJsfS9oZWFsdGhgLCB7XG4gICAgICAgIG1ldGhvZDogXCJHRVRcIixcbiAgICAgICAgc2lnbmFsOiBBYm9ydFNpZ25hbC50aW1lb3V0KDEwMDAwKSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBsYXRlbmN5ID0gRGF0ZS5ub3coKSAtIHN0YXJ0VGltZTtcblxuICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICAgIHRoaXMuYWRkUmVzdWx0KHtcbiAgICAgICAgICBuYW1lOiBcIk5ldHdvcmtcIixcbiAgICAgICAgICBzdGF0dXM6IFwib2tcIixcbiAgICAgICAgICBtZXNzYWdlOiBgQ29ubmVjdGVkIHRvICR7bmV3IFVSTChiYXNlVXJsKS5ob3N0fSAoJHtsYXRlbmN5fW1zKWAsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hZGRSZXN1bHQoe1xuICAgICAgICAgIG5hbWU6IFwiTmV0d29ya1wiLFxuICAgICAgICAgIHN0YXR1czogXCJ3YXJuaW5nXCIsXG4gICAgICAgICAgbWVzc2FnZTogYEFQSSByZXR1cm5lZCAke3Jlc3BvbnNlLnN0YXR1c31gLFxuICAgICAgICAgIGRldGFpbHM6IGBFbmRwb2ludDogJHtiYXNlVXJsfS9oZWFsdGhgLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgdGhpcy5hZGRSZXN1bHQoe1xuICAgICAgICBuYW1lOiBcIk5ldHdvcmtcIixcbiAgICAgICAgc3RhdHVzOiBcImVycm9yXCIsXG4gICAgICAgIG1lc3NhZ2U6IFwiQ2Fubm90IHJlYWNoIEFQSVwiLFxuICAgICAgICBkZXRhaWxzOiBlcnIubWVzc2FnZSB8fCBcIkNoZWNrIHlvdXIgaW50ZXJuZXQgY29ubmVjdGlvblwiLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjaGVja0Nsb2NrU2tldygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBiYXNlVXJsID0gZ2V0RWZmZWN0aXZlVmFsdWUoXCJiYXNlVXJsXCIpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYCR7YmFzZVVybH0vaGVhbHRoYCwge1xuICAgICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICAgIHNpZ25hbDogQWJvcnRTaWduYWwudGltZW91dCg1MDAwKSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzZXJ2ZXJEYXRlID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoXCJkYXRlXCIpO1xuICAgICAgaWYgKCFzZXJ2ZXJEYXRlKSB7XG4gICAgICAgIHRoaXMuYWRkUmVzdWx0KHtcbiAgICAgICAgICBuYW1lOiBcIkNsb2NrXCIsXG4gICAgICAgICAgc3RhdHVzOiBcIndhcm5pbmdcIixcbiAgICAgICAgICBtZXNzYWdlOiBcIkNvdWxkIG5vdCB2ZXJpZnkgKG5vIHNlcnZlciBkYXRlIGhlYWRlcilcIixcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2VydmVyVGltZSA9IG5ldyBEYXRlKHNlcnZlckRhdGUpLmdldFRpbWUoKTtcbiAgICAgIGNvbnN0IGxvY2FsVGltZSA9IERhdGUubm93KCk7XG4gICAgICBjb25zdCBza2V3U2Vjb25kcyA9IE1hdGguYWJzKHNlcnZlclRpbWUgLSBsb2NhbFRpbWUpIC8gMTAwMDtcblxuICAgICAgaWYgKHNrZXdTZWNvbmRzID4gMzAwKSB7XG4gICAgICAgIC8vIDUgbWludXRlc1xuICAgICAgICB0aGlzLmFkZFJlc3VsdCh7XG4gICAgICAgICAgbmFtZTogXCJDbG9ja1wiLFxuICAgICAgICAgIHN0YXR1czogXCJlcnJvclwiLFxuICAgICAgICAgIG1lc3NhZ2U6IGBTaWduaWZpY2FudCBkcmlmdCBkZXRlY3RlZCAoJHtza2V3U2Vjb25kcy50b0ZpeGVkKDApfXMpYCxcbiAgICAgICAgICBkZXRhaWxzOiBcIlRoaXMgbWF5IGNhdXNlIHdlYmhvb2sgc2lnbmF0dXJlIHZlcmlmaWNhdGlvbiB0byBmYWlsXCIsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChza2V3U2Vjb25kcyA+IDMwKSB7XG4gICAgICAgIHRoaXMuYWRkUmVzdWx0KHtcbiAgICAgICAgICBuYW1lOiBcIkNsb2NrXCIsXG4gICAgICAgICAgc3RhdHVzOiBcIndhcm5pbmdcIixcbiAgICAgICAgICBtZXNzYWdlOiBgTWlub3IgZHJpZnQgZGV0ZWN0ZWQgKCR7c2tld1NlY29uZHMudG9GaXhlZCgxKX1zKWAsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hZGRSZXN1bHQoe1xuICAgICAgICAgIG5hbWU6IFwiQ2xvY2tcIixcbiAgICAgICAgICBzdGF0dXM6IFwib2tcIixcbiAgICAgICAgICBtZXNzYWdlOiBgU3luY2hyb25pemVkIChkcmlmdDogJHtza2V3U2Vjb25kcy50b0ZpeGVkKDEpfXMpYCxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICB0aGlzLmFkZFJlc3VsdCh7XG4gICAgICAgIG5hbWU6IFwiQ2xvY2tcIixcbiAgICAgICAgc3RhdHVzOiBcIndhcm5pbmdcIixcbiAgICAgICAgbWVzc2FnZTogXCJDb3VsZCBub3QgdmVyaWZ5IChuZXR3b3JrIGVycm9yKVwiLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjaGVja0NyZWRpdHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc0F1dGhlbnRpY2F0ZWQoKSkge1xuICAgICAgdGhpcy5hZGRSZXN1bHQoe1xuICAgICAgICBuYW1lOiBcIkNyZWRpdHNcIixcbiAgICAgICAgc3RhdHVzOiBcIndhcm5pbmdcIixcbiAgICAgICAgbWVzc2FnZTogXCJDYW5ub3QgY2hlY2sgKG5vdCBhdXRoZW50aWNhdGVkKVwiLFxuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgYmFzZVVybCA9IGdldEVmZmVjdGl2ZVZhbHVlKFwiYmFzZVVybFwiKTtcbiAgICBjb25zdCB0b2tlbiA9IGdldEF1dGhUb2tlbigpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYCR7YmFzZVVybH0vYXBpL2NyZWRpdHNgLCB7XG4gICAgICAgIG1ldGhvZDogXCJHRVRcIixcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHt0b2tlbn1gLFxuICAgICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgICB9LFxuICAgICAgICBzaWduYWw6IEFib3J0U2lnbmFsLnRpbWVvdXQoMTAwMDApLFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgICBjb25zdCBkYXRhID0gKGF3YWl0IHJlc3BvbnNlLmpzb24oKSkgYXMgeyBiYWxhbmNlPzogbnVtYmVyIH07XG4gICAgICAgIGNvbnN0IGJhbGFuY2UgPSBkYXRhLmJhbGFuY2UgfHwgMDtcblxuICAgICAgICBpZiAoYmFsYW5jZSA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuYWRkUmVzdWx0KHtcbiAgICAgICAgICAgIG5hbWU6IFwiQ3JlZGl0c1wiLFxuICAgICAgICAgICAgc3RhdHVzOiBcIndhcm5pbmdcIixcbiAgICAgICAgICAgIG1lc3NhZ2U6IFwiMCBhdmFpbGFibGVcIixcbiAgICAgICAgICAgIGRldGFpbHM6IFwiQWRkIGNyZWRpdHMgdG8gc2VuZCBtZXNzYWdlc1wiLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuYWRkUmVzdWx0KHtcbiAgICAgICAgICAgIG5hbWU6IFwiQ3JlZGl0c1wiLFxuICAgICAgICAgICAgc3RhdHVzOiBcIm9rXCIsXG4gICAgICAgICAgICBtZXNzYWdlOiBgJHtiYWxhbmNlLnRvTG9jYWxlU3RyaW5nKCl9IGF2YWlsYWJsZWAsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MDEpIHtcbiAgICAgICAgdGhpcy5hZGRSZXN1bHQoe1xuICAgICAgICAgIG5hbWU6IFwiQ3JlZGl0c1wiLFxuICAgICAgICAgIHN0YXR1czogXCJlcnJvclwiLFxuICAgICAgICAgIG1lc3NhZ2U6IFwiQVBJIGtleSBpbnZhbGlkIG9yIGV4cGlyZWRcIixcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmFkZFJlc3VsdCh7XG4gICAgICAgICAgbmFtZTogXCJDcmVkaXRzXCIsXG4gICAgICAgICAgc3RhdHVzOiBcIndhcm5pbmdcIixcbiAgICAgICAgICBtZXNzYWdlOiBgQ291bGQgbm90IGZldGNoIChIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfSlgLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgdGhpcy5hZGRSZXN1bHQoe1xuICAgICAgICBuYW1lOiBcIkNyZWRpdHNcIixcbiAgICAgICAgc3RhdHVzOiBcIndhcm5pbmdcIixcbiAgICAgICAgbWVzc2FnZTogXCJDb3VsZCBub3QgZmV0Y2hcIixcbiAgICAgICAgZGV0YWlsczogZXJyLm1lc3NhZ2UsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNoZWNrRW52aXJvbm1lbnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2hlY2tzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgaWYgKGlzQ0koKSkge1xuICAgICAgY2hlY2tzLnB1c2goXCJDSSBtb2RlIGRldGVjdGVkXCIpO1xuICAgIH1cblxuICAgIGlmIChpc0NvbG9yRGlzYWJsZWQoKSkge1xuICAgICAgY2hlY2tzLnB1c2goXCJjb2xvciBkaXNhYmxlZFwiKTtcbiAgICB9XG5cbiAgICBpZiAocHJvY2Vzcy5lbnYuU0VORExZX0FQSV9LRVkpIHtcbiAgICAgIGNoZWNrcy5wdXNoKFwidXNpbmcgU0VORExZX0FQSV9LRVkgZW52IHZhclwiKTtcbiAgICB9XG5cbiAgICBpZiAocHJvY2Vzcy5lbnYuU0VORExZX0JBU0VfVVJMKSB7XG4gICAgICBjaGVja3MucHVzaChgY3VzdG9tIGJhc2UgVVJMOiAke3Byb2Nlc3MuZW52LlNFTkRMWV9CQVNFX1VSTH1gKTtcbiAgICB9XG5cbiAgICB0aGlzLmFkZFJlc3VsdCh7XG4gICAgICBuYW1lOiBcIkVudmlyb25tZW50XCIsXG4gICAgICBzdGF0dXM6IFwib2tcIixcbiAgICAgIG1lc3NhZ2U6IGNoZWNrcy5sZW5ndGggPiAwID8gY2hlY2tzLmpvaW4oXCIsIFwiKSA6IFwiU3RhbmRhcmQgdGVybWluYWwgbW9kZVwiLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjaGVja0NvbmZpZygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjb25maWdQYXRoID0gZ2V0Q29uZmlnUGF0aCgpO1xuICAgIGNvbnN0IGNvbmZpZ0RpciA9IGdldENvbmZpZ0RpcigpO1xuXG4gICAgLy8gQ2hlY2sgaWYgY29uZmlnIGRpcmVjdG9yeSBleGlzdHNcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoY29uZmlnRGlyKSkge1xuICAgICAgdGhpcy5hZGRSZXN1bHQoe1xuICAgICAgICBuYW1lOiBcIkNvbmZpZ1wiLFxuICAgICAgICBzdGF0dXM6IFwid2FybmluZ1wiLFxuICAgICAgICBtZXNzYWdlOiBcIkNvbmZpZyBkaXJlY3Rvcnkgbm90IGZvdW5kXCIsXG4gICAgICAgIGRldGFpbHM6IGBFeHBlY3RlZDogJHtjb25maWdEaXJ9YCxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIGNvbmZpZyBmaWxlIGV4aXN0c1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhjb25maWdQYXRoKSkge1xuICAgICAgdGhpcy5hZGRSZXN1bHQoe1xuICAgICAgICBuYW1lOiBcIkNvbmZpZ1wiLFxuICAgICAgICBzdGF0dXM6IFwid2FybmluZ1wiLFxuICAgICAgICBtZXNzYWdlOiBcIkNvbmZpZyBmaWxlIG5vdCBmb3VuZCAodXNpbmcgZGVmYXVsdHMpXCIsXG4gICAgICAgIGRldGFpbHM6IGNvbmZpZ1BhdGgsXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBmaWxlIHBlcm1pc3Npb25zIChzaG91bGQgYmUgcmVhZGFibGUgb25seSBieSBvd25lcilcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc3RhdHMgPSBmcy5zdGF0U3luYyhjb25maWdQYXRoKTtcbiAgICAgIGNvbnN0IG1vZGUgPSBzdGF0cy5tb2RlICYgMG83Nzc7XG5cbiAgICAgIGlmIChtb2RlICYgMG8wNzcpIHtcbiAgICAgICAgLy8gR3JvdXAgb3Igb3RoZXJzIGhhdmUgYWNjZXNzXG4gICAgICAgIHRoaXMuYWRkUmVzdWx0KHtcbiAgICAgICAgICBuYW1lOiBcIkNvbmZpZ1wiLFxuICAgICAgICAgIHN0YXR1czogXCJ3YXJuaW5nXCIsXG4gICAgICAgICAgbWVzc2FnZTogXCJDb25maWcgZmlsZSBoYXMgbG9vc2UgcGVybWlzc2lvbnNcIixcbiAgICAgICAgICBkZXRhaWxzOiBgJHtjb25maWdQYXRofSAobW9kZTogJHttb2RlLnRvU3RyaW5nKDgpfSlgLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYWRkUmVzdWx0KHtcbiAgICAgICAgICBuYW1lOiBcIkNvbmZpZ1wiLFxuICAgICAgICAgIHN0YXR1czogXCJva1wiLFxuICAgICAgICAgIG1lc3NhZ2U6IGNvbmZpZ1BhdGgsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gY2F0Y2gge1xuICAgICAgdGhpcy5hZGRSZXN1bHQoe1xuICAgICAgICBuYW1lOiBcIkNvbmZpZ1wiLFxuICAgICAgICBzdGF0dXM6IFwib2tcIixcbiAgICAgICAgbWVzc2FnZTogY29uZmlnUGF0aCxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2VuZXJhdGVSZXBvcnQoKTogRG9jdG9yUmVwb3J0IHtcbiAgICBjb25zdCBwYXNzZWQgPSB0aGlzLnJlc3VsdHMuZmlsdGVyKChyKSA9PiByLnN0YXR1cyA9PT0gXCJva1wiKS5sZW5ndGg7XG4gICAgY29uc3Qgd2FybmluZ3MgPSB0aGlzLnJlc3VsdHMuZmlsdGVyKChyKSA9PiByLnN0YXR1cyA9PT0gXCJ3YXJuaW5nXCIpLmxlbmd0aDtcbiAgICBjb25zdCBlcnJvcnMgPSB0aGlzLnJlc3VsdHMuZmlsdGVyKChyKSA9PiByLnN0YXR1cyA9PT0gXCJlcnJvclwiKS5sZW5ndGg7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICB2ZXJzaW9uOiBcIjEuMC4wXCIsXG4gICAgICByZXN1bHRzOiB0aGlzLnJlc3VsdHMsXG4gICAgICBzdW1tYXJ5OiB7XG4gICAgICAgIHBhc3NlZCxcbiAgICAgICAgd2FybmluZ3MsXG4gICAgICAgIGVycm9ycyxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AuthenticatedCommand } from "../../lib/base-command.js";
|
|
2
|
+
export default class KeysCreate extends AuthenticatedCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
name: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
7
|
+
type: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
8
|
+
json: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
9
|
+
quiet: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
import { AuthenticatedCommand } from "../../lib/base-command.js";
|
|
3
|
+
import { apiClient } from "../../lib/api-client.js";
|
|
4
|
+
import { success, warn, json, colors, codeBlock, isJsonMode, } from "../../lib/output.js";
|
|
5
|
+
export default class KeysCreate extends AuthenticatedCommand {
|
|
6
|
+
static description = "Create a new API key";
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> keys create --name "Production"',
|
|
9
|
+
'<%= config.bin %> keys create --name "CI Testing" --type test',
|
|
10
|
+
'<%= config.bin %> keys create --name "Backend" --type live --json',
|
|
11
|
+
];
|
|
12
|
+
static flags = {
|
|
13
|
+
...AuthenticatedCommand.baseFlags,
|
|
14
|
+
name: Flags.string({
|
|
15
|
+
char: "n",
|
|
16
|
+
description: "Name for the API key",
|
|
17
|
+
required: true,
|
|
18
|
+
}),
|
|
19
|
+
type: Flags.string({
|
|
20
|
+
char: "t",
|
|
21
|
+
description: "Key type (test or live)",
|
|
22
|
+
options: ["test", "live"],
|
|
23
|
+
default: "test",
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
async run() {
|
|
27
|
+
const { flags } = await this.parse(KeysCreate);
|
|
28
|
+
const response = await apiClient.post("/api/keys", {
|
|
29
|
+
name: flags.name,
|
|
30
|
+
type: flags.type,
|
|
31
|
+
});
|
|
32
|
+
if (isJsonMode()) {
|
|
33
|
+
json(response);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
success("API key created", {
|
|
37
|
+
Name: response.name,
|
|
38
|
+
"Key ID": response.keyId,
|
|
39
|
+
Type: flags.type === "test" ? colors.warning("test") : colors.success("live"),
|
|
40
|
+
});
|
|
41
|
+
console.log();
|
|
42
|
+
warn("Copy your API key now. You won't be able to see it again!");
|
|
43
|
+
codeBlock(response.key);
|
|
44
|
+
console.log(colors.dim("Store this key securely. It provides access to your Sendly account."));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2tleXMvY3JlYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDcEMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDakUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BELE9BQU8sRUFDTCxPQUFPLEVBQ1AsSUFBSSxFQUNKLElBQUksRUFDSixNQUFNLEVBQ04sU0FBUyxFQUNULFVBQVUsR0FDWCxNQUFNLHFCQUFxQixDQUFDO0FBWTdCLE1BQU0sQ0FBQyxPQUFPLE9BQU8sVUFBVyxTQUFRLG9CQUFvQjtJQUMxRCxNQUFNLENBQUMsV0FBVyxHQUFHLHNCQUFzQixDQUFDO0lBRTVDLE1BQU0sQ0FBQyxRQUFRLEdBQUc7UUFDaEIsbURBQW1EO1FBQ25ELCtEQUErRDtRQUMvRCxtRUFBbUU7S0FDcEUsQ0FBQztJQUVGLE1BQU0sQ0FBQyxLQUFLLEdBQUc7UUFDYixHQUFHLG9CQUFvQixDQUFDLFNBQVM7UUFDakMsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUM7WUFDakIsSUFBSSxFQUFFLEdBQUc7WUFDVCxXQUFXLEVBQUUsc0JBQXNCO1lBQ25DLFFBQVEsRUFBRSxJQUFJO1NBQ2YsQ0FBQztRQUNGLElBQUksRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDO1lBQ2pCLElBQUksRUFBRSxHQUFHO1lBQ1QsV0FBVyxFQUFFLHlCQUF5QjtZQUN0QyxPQUFPLEVBQUUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDO1lBQ3pCLE9BQU8sRUFBRSxNQUFNO1NBQ2hCLENBQUM7S0FDSCxDQUFDO0lBRUYsS0FBSyxDQUFDLEdBQUc7UUFDUCxNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRS9DLE1BQU0sUUFBUSxHQUFHLE1BQU0sU0FBUyxDQUFDLElBQUksQ0FBb0IsV0FBVyxFQUFFO1lBQ3BFLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtZQUNoQixJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7U0FDakIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxVQUFVLEVBQUUsRUFBRSxDQUFDO1lBQ2pCLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNmLE9BQU87UUFDVCxDQUFDO1FBRUQsT0FBTyxDQUFDLGlCQUFpQixFQUFFO1lBQ3pCLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSTtZQUNuQixRQUFRLEVBQUUsUUFBUSxDQUFDLEtBQUs7WUFDeEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztTQUM5RSxDQUFDLENBQUM7UUFFSCxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDZCxJQUFJLENBQUMsMkRBQTJELENBQUMsQ0FBQztRQUNsRSxTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRXhCLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxxRUFBcUUsQ0FBQyxDQUFDLENBQUM7SUFDakcsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEZsYWdzIH0gZnJvbSBcIkBvY2xpZi9jb3JlXCI7XG5pbXBvcnQgeyBBdXRoZW50aWNhdGVkQ29tbWFuZCB9IGZyb20gXCIuLi8uLi9saWIvYmFzZS1jb21tYW5kLmpzXCI7XG5pbXBvcnQgeyBhcGlDbGllbnQgfSBmcm9tIFwiLi4vLi4vbGliL2FwaS1jbGllbnQuanNcIjtcbmltcG9ydCB7XG4gIHN1Y2Nlc3MsXG4gIHdhcm4sXG4gIGpzb24sXG4gIGNvbG9ycyxcbiAgY29kZUJsb2NrLFxuICBpc0pzb25Nb2RlLFxufSBmcm9tIFwiLi4vLi4vbGliL291dHB1dC5qc1wiO1xuXG5pbnRlcmZhY2UgQ3JlYXRlS2V5UmVzcG9uc2Uge1xuICBpZDogc3RyaW5nO1xuICBrZXlJZDogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIGtleTogc3RyaW5nOyAvLyBPbmx5IHJldHVybmVkIG9uIGNyZWF0aW9uXG4gIGtleVByZWZpeDogc3RyaW5nO1xuICB0eXBlOiBcInRlc3RcIiB8IFwibGl2ZVwiO1xuICBjcmVhdGVkQXQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgS2V5c0NyZWF0ZSBleHRlbmRzIEF1dGhlbnRpY2F0ZWRDb21tYW5kIHtcbiAgc3RhdGljIGRlc2NyaXB0aW9uID0gXCJDcmVhdGUgYSBuZXcgQVBJIGtleVwiO1xuXG4gIHN0YXRpYyBleGFtcGxlcyA9IFtcbiAgICAnPCU9IGNvbmZpZy5iaW4gJT4ga2V5cyBjcmVhdGUgLS1uYW1lIFwiUHJvZHVjdGlvblwiJyxcbiAgICAnPCU9IGNvbmZpZy5iaW4gJT4ga2V5cyBjcmVhdGUgLS1uYW1lIFwiQ0kgVGVzdGluZ1wiIC0tdHlwZSB0ZXN0JyxcbiAgICAnPCU9IGNvbmZpZy5iaW4gJT4ga2V5cyBjcmVhdGUgLS1uYW1lIFwiQmFja2VuZFwiIC0tdHlwZSBsaXZlIC0tanNvbicsXG4gIF07XG5cbiAgc3RhdGljIGZsYWdzID0ge1xuICAgIC4uLkF1dGhlbnRpY2F0ZWRDb21tYW5kLmJhc2VGbGFncyxcbiAgICBuYW1lOiBGbGFncy5zdHJpbmcoe1xuICAgICAgY2hhcjogXCJuXCIsXG4gICAgICBkZXNjcmlwdGlvbjogXCJOYW1lIGZvciB0aGUgQVBJIGtleVwiLFxuICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgfSksXG4gICAgdHlwZTogRmxhZ3Muc3RyaW5nKHtcbiAgICAgIGNoYXI6IFwidFwiLFxuICAgICAgZGVzY3JpcHRpb246IFwiS2V5IHR5cGUgKHRlc3Qgb3IgbGl2ZSlcIixcbiAgICAgIG9wdGlvbnM6IFtcInRlc3RcIiwgXCJsaXZlXCJdLFxuICAgICAgZGVmYXVsdDogXCJ0ZXN0XCIsXG4gICAgfSksXG4gIH07XG5cbiAgYXN5bmMgcnVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgZmxhZ3MgfSA9IGF3YWl0IHRoaXMucGFyc2UoS2V5c0NyZWF0ZSk7XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGFwaUNsaWVudC5wb3N0PENyZWF0ZUtleVJlc3BvbnNlPihcIi9hcGkva2V5c1wiLCB7XG4gICAgICBuYW1lOiBmbGFncy5uYW1lLFxuICAgICAgdHlwZTogZmxhZ3MudHlwZSxcbiAgICB9KTtcblxuICAgIGlmIChpc0pzb25Nb2RlKCkpIHtcbiAgICAgIGpzb24ocmVzcG9uc2UpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHN1Y2Nlc3MoXCJBUEkga2V5IGNyZWF0ZWRcIiwge1xuICAgICAgTmFtZTogcmVzcG9uc2UubmFtZSxcbiAgICAgIFwiS2V5IElEXCI6IHJlc3BvbnNlLmtleUlkLFxuICAgICAgVHlwZTogZmxhZ3MudHlwZSA9PT0gXCJ0ZXN0XCIgPyBjb2xvcnMud2FybmluZyhcInRlc3RcIikgOiBjb2xvcnMuc3VjY2VzcyhcImxpdmVcIiksXG4gICAgfSk7XG5cbiAgICBjb25zb2xlLmxvZygpO1xuICAgIHdhcm4oXCJDb3B5IHlvdXIgQVBJIGtleSBub3cuIFlvdSB3b24ndCBiZSBhYmxlIHRvIHNlZSBpdCBhZ2FpbiFcIik7XG4gICAgY29kZUJsb2NrKHJlc3BvbnNlLmtleSk7XG5cbiAgICBjb25zb2xlLmxvZyhjb2xvcnMuZGltKFwiU3RvcmUgdGhpcyBrZXkgc2VjdXJlbHkuIEl0IHByb3ZpZGVzIGFjY2VzcyB0byB5b3VyIFNlbmRseSBhY2NvdW50LlwiKSk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AuthenticatedCommand } from "../../lib/base-command.js";
|
|
2
|
+
export default class KeysList extends AuthenticatedCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
json: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
7
|
+
quiet: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|