@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.
Files changed (60) hide show
  1. package/README.md +323 -0
  2. package/bin/run.js +5 -0
  3. package/dist/commands/config/get.d.ts +13 -0
  4. package/dist/commands/config/get.js +38 -0
  5. package/dist/commands/config/list.d.ts +10 -0
  6. package/dist/commands/config/list.js +45 -0
  7. package/dist/commands/config/set.d.ts +14 -0
  8. package/dist/commands/config/set.js +67 -0
  9. package/dist/commands/credits/balance.d.ts +10 -0
  10. package/dist/commands/credits/balance.js +38 -0
  11. package/dist/commands/credits/history.d.ts +11 -0
  12. package/dist/commands/credits/history.js +88 -0
  13. package/dist/commands/doctor.d.ts +23 -0
  14. package/dist/commands/doctor.js +336 -0
  15. package/dist/commands/keys/create.d.ts +12 -0
  16. package/dist/commands/keys/create.js +47 -0
  17. package/dist/commands/keys/list.d.ts +10 -0
  18. package/dist/commands/keys/list.js +65 -0
  19. package/dist/commands/keys/revoke.d.ts +15 -0
  20. package/dist/commands/keys/revoke.js +68 -0
  21. package/dist/commands/login.d.ts +12 -0
  22. package/dist/commands/login.js +114 -0
  23. package/dist/commands/logout.d.ts +10 -0
  24. package/dist/commands/logout.js +20 -0
  25. package/dist/commands/logs/tail.d.ts +17 -0
  26. package/dist/commands/logs/tail.js +183 -0
  27. package/dist/commands/sms/batch.d.ts +16 -0
  28. package/dist/commands/sms/batch.js +163 -0
  29. package/dist/commands/sms/cancel.d.ts +13 -0
  30. package/dist/commands/sms/cancel.js +46 -0
  31. package/dist/commands/sms/get.d.ts +13 -0
  32. package/dist/commands/sms/get.js +51 -0
  33. package/dist/commands/sms/list.d.ts +12 -0
  34. package/dist/commands/sms/list.js +79 -0
  35. package/dist/commands/sms/schedule.d.ts +14 -0
  36. package/dist/commands/sms/schedule.js +91 -0
  37. package/dist/commands/sms/scheduled.d.ts +12 -0
  38. package/dist/commands/sms/scheduled.js +82 -0
  39. package/dist/commands/sms/send.d.ts +13 -0
  40. package/dist/commands/sms/send.js +70 -0
  41. package/dist/commands/webhooks/list.d.ts +10 -0
  42. package/dist/commands/webhooks/list.js +80 -0
  43. package/dist/commands/webhooks/listen.d.ts +20 -0
  44. package/dist/commands/webhooks/listen.js +202 -0
  45. package/dist/commands/whoami.d.ts +10 -0
  46. package/dist/commands/whoami.js +51 -0
  47. package/dist/index.d.ts +26 -0
  48. package/dist/index.js +27 -0
  49. package/dist/lib/api-client.d.ts +52 -0
  50. package/dist/lib/api-client.js +129 -0
  51. package/dist/lib/auth.d.ts +52 -0
  52. package/dist/lib/auth.js +171 -0
  53. package/dist/lib/base-command.d.ts +17 -0
  54. package/dist/lib/base-command.js +60 -0
  55. package/dist/lib/config.d.ts +54 -0
  56. package/dist/lib/config.js +182 -0
  57. package/dist/lib/output.d.ts +43 -0
  58. package/dist/lib/output.js +222 -0
  59. package/oclif.manifest.json +1147 -0
  60. package/package.json +98 -0
@@ -0,0 +1,182 @@
1
+ /**
2
+ * CLI Configuration Management
3
+ * Stores user preferences and credentials in ~/.sendly/
4
+ *
5
+ * Environment Variables (take precedence over config file):
6
+ * - SENDLY_API_KEY: API key for authentication
7
+ * - SENDLY_BASE_URL: Custom API endpoint
8
+ * - SENDLY_OUTPUT_FORMAT: Default output format (human/json)
9
+ * - SENDLY_NO_COLOR: Disable colored output (any value)
10
+ * - SENDLY_TIMEOUT: Request timeout in ms (default: 30000)
11
+ * - SENDLY_MAX_RETRIES: Max retry attempts (default: 3)
12
+ * - CI: Auto-detect CI mode (disables interactive prompts)
13
+ */
14
+ import Conf from "conf";
15
+ import * as fs from "node:fs";
16
+ import * as path from "node:path";
17
+ import * as os from "node:os";
18
+ /**
19
+ * Check if running in CI environment
20
+ */
21
+ export function isCI() {
22
+ return !!(process.env.CI ||
23
+ process.env.CONTINUOUS_INTEGRATION ||
24
+ process.env.GITHUB_ACTIONS ||
25
+ process.env.GITLAB_CI ||
26
+ process.env.CIRCLECI ||
27
+ process.env.TRAVIS ||
28
+ process.env.BUILDKITE);
29
+ }
30
+ /**
31
+ * Check if color output is disabled
32
+ */
33
+ export function isColorDisabled() {
34
+ return !!(process.env.SENDLY_NO_COLOR ||
35
+ process.env.NO_COLOR ||
36
+ process.env.TERM === "dumb");
37
+ }
38
+ const CONFIG_DIR = path.join(os.homedir(), ".sendly");
39
+ const CONFIG_FILE = "config.json";
40
+ // Ensure config directory exists
41
+ if (!fs.existsSync(CONFIG_DIR)) {
42
+ fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
43
+ }
44
+ const config = new Conf({
45
+ projectName: "sendly",
46
+ cwd: CONFIG_DIR,
47
+ configName: "config",
48
+ defaults: {
49
+ environment: "test",
50
+ baseUrl: "https://sendly.live",
51
+ defaultFormat: "human",
52
+ colorEnabled: true,
53
+ timeout: 30000,
54
+ maxRetries: 3,
55
+ },
56
+ // Encrypt sensitive data
57
+ encryptionKey: process.env.SENDLY_CONFIG_KEY || "sendly-cli-default-key-v1",
58
+ });
59
+ /**
60
+ * Get effective config value with environment variable override
61
+ * Priority: env var > config file > default
62
+ */
63
+ export function getEffectiveValue(key) {
64
+ // Environment variable overrides
65
+ switch (key) {
66
+ case "apiKey":
67
+ if (process.env.SENDLY_API_KEY) {
68
+ return process.env.SENDLY_API_KEY;
69
+ }
70
+ break;
71
+ case "baseUrl":
72
+ if (process.env.SENDLY_BASE_URL) {
73
+ return process.env.SENDLY_BASE_URL;
74
+ }
75
+ break;
76
+ case "defaultFormat":
77
+ if (process.env.SENDLY_OUTPUT_FORMAT) {
78
+ const format = process.env.SENDLY_OUTPUT_FORMAT.toLowerCase();
79
+ if (format === "json" || format === "human") {
80
+ return format;
81
+ }
82
+ }
83
+ break;
84
+ case "colorEnabled":
85
+ if (isColorDisabled()) {
86
+ return false;
87
+ }
88
+ break;
89
+ case "timeout":
90
+ if (process.env.SENDLY_TIMEOUT) {
91
+ const timeout = parseInt(process.env.SENDLY_TIMEOUT, 10);
92
+ if (!isNaN(timeout) && timeout > 0) {
93
+ return timeout;
94
+ }
95
+ }
96
+ break;
97
+ case "maxRetries":
98
+ if (process.env.SENDLY_MAX_RETRIES) {
99
+ const retries = parseInt(process.env.SENDLY_MAX_RETRIES, 10);
100
+ if (!isNaN(retries) && retries >= 0) {
101
+ return retries;
102
+ }
103
+ }
104
+ break;
105
+ }
106
+ // Fall back to config file value
107
+ return config.get(key);
108
+ }
109
+ export function getConfig() {
110
+ return config.store;
111
+ }
112
+ export function setConfig(key, value) {
113
+ config.set(key, value);
114
+ }
115
+ export function getConfigValue(key) {
116
+ return config.get(key);
117
+ }
118
+ export function clearConfig() {
119
+ config.clear();
120
+ }
121
+ export function clearAuth() {
122
+ config.delete("apiKey");
123
+ config.delete("accessToken");
124
+ config.delete("refreshToken");
125
+ config.delete("tokenExpiresAt");
126
+ config.delete("userId");
127
+ config.delete("email");
128
+ }
129
+ export function isAuthenticated() {
130
+ // Check env var first
131
+ if (process.env.SENDLY_API_KEY)
132
+ return true;
133
+ const apiKey = config.get("apiKey");
134
+ const accessToken = config.get("accessToken");
135
+ return !!(apiKey || accessToken);
136
+ }
137
+ export function getAuthToken() {
138
+ // Environment variable takes highest precedence
139
+ if (process.env.SENDLY_API_KEY) {
140
+ return process.env.SENDLY_API_KEY;
141
+ }
142
+ // Then stored API key
143
+ const apiKey = config.get("apiKey");
144
+ if (apiKey)
145
+ return apiKey;
146
+ // Finally, access token (if not expired)
147
+ const accessToken = config.get("accessToken");
148
+ const expiresAt = config.get("tokenExpiresAt");
149
+ if (accessToken && expiresAt && Date.now() < expiresAt) {
150
+ return accessToken;
151
+ }
152
+ return undefined;
153
+ }
154
+ export function setApiKey(apiKey) {
155
+ // Validate API key format
156
+ if (!/^sk_(test|live)_v1_[a-zA-Z0-9_-]+$/.test(apiKey)) {
157
+ throw new Error("Invalid API key format. Expected sk_test_v1_xxx or sk_live_v1_xxx");
158
+ }
159
+ config.set("apiKey", apiKey);
160
+ // Set environment based on key type
161
+ if (apiKey.startsWith("sk_test_")) {
162
+ config.set("environment", "test");
163
+ }
164
+ else {
165
+ config.set("environment", "live");
166
+ }
167
+ }
168
+ export function setAuthTokens(accessToken, refreshToken, expiresIn, userId, email) {
169
+ config.set("accessToken", accessToken);
170
+ config.set("refreshToken", refreshToken);
171
+ config.set("tokenExpiresAt", Date.now() + expiresIn * 1000);
172
+ config.set("userId", userId);
173
+ config.set("email", email);
174
+ }
175
+ export function getConfigPath() {
176
+ return path.join(CONFIG_DIR, CONFIG_FILE);
177
+ }
178
+ export function getConfigDir() {
179
+ return CONFIG_DIR;
180
+ }
181
+ export { config };
182
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7OztHQVlHO0FBRUgsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQ3hCLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBd0I5Qjs7R0FFRztBQUNILE1BQU0sVUFBVSxJQUFJO0lBQ2xCLE9BQU8sQ0FBQyxDQUFDLENBQ1AsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ2QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0I7UUFDbEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjO1FBQzFCLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUztRQUNyQixPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVE7UUFDcEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNO1FBQ2xCLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUN0QixDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGVBQWU7SUFDN0IsT0FBTyxDQUFDLENBQUMsQ0FDUCxPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWU7UUFDM0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRO1FBQ3BCLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FDNUIsQ0FBQztBQUNKLENBQUM7QUFFRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxTQUFTLENBQUMsQ0FBQztBQUN0RCxNQUFNLFdBQVcsR0FBRyxhQUFhLENBQUM7QUFFbEMsaUNBQWlDO0FBQ2pDLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUs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QztJQUN2QyxNQUFNLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQztJQUN6QyxNQUFNLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDNUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDN0IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDN0IsQ0FBQztBQUVELE1BQU0sVUFBVSxhQUFhO0lBQzNCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUFDLENBQUM7QUFDNUMsQ0FBQztBQUVELE1BQU0sVUFBVSxZQUFZO0lBQzFCLE9BQU8sVUFBVSxDQUFDO0FBQ3BCLENBQUM7QUFFRCxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENMSSBDb25maWd1cmF0aW9uIE1hbmFnZW1lbnRcbiAqIFN0b3JlcyB1c2VyIHByZWZlcmVuY2VzIGFuZCBjcmVkZW50aWFscyBpbiB+Ly5zZW5kbHkvXG4gKlxuICogRW52aXJvbm1lbnQgVmFyaWFibGVzICh0YWtlIHByZWNlZGVuY2Ugb3ZlciBjb25maWcgZmlsZSk6XG4gKiAtIFNFTkRMWV9BUElfS0VZOiBBUEkga2V5IGZvciBhdXRoZW50aWNhdGlvblxuICogLSBTRU5ETFlfQkFTRV9VUkw6IEN1c3RvbSBBUEkgZW5kcG9pbnRcbiAqIC0gU0VORExZX09VVFBVVF9GT1JNQVQ6IERlZmF1bHQgb3V0cHV0IGZvcm1hdCAoaHVtYW4vanNvbilcbiAqIC0gU0VORExZX05PX0NPTE9SOiBEaXNhYmxlIGNvbG9yZWQgb3V0cHV0IChhbnkgdmFsdWUpXG4gKiAtIFNFTkRMWV9USU1FT1VUOiBSZXF1ZXN0IHRpbWVvdXQgaW4gbXMgKGRlZmF1bHQ6IDMwMDAwKVxuICogLSBTRU5ETFlfTUFYX1JFVFJJRVM6IE1heCByZXRyeSBhdHRlbXB0cyAoZGVmYXVsdDogMylcbiAqIC0gQ0k6IEF1dG8tZGV0ZWN0IENJIG1vZGUgKGRpc2FibGVzIGludGVyYWN0aXZlIHByb21wdHMpXG4gKi9cblxuaW1wb3J0IENvbmYgZnJvbSBcImNvbmZcIjtcbmltcG9ydCAqIGFzIGZzIGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCAqIGFzIG9zIGZyb20gXCJub2RlOm9zXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VuZGx5Q29uZmlnIHtcbiAgLy8gQXV0aGVudGljYXRpb25cbiAgYXBpS2V5Pzogc3RyaW5nO1xuICBhY2Nlc3NUb2tlbj86IHN0cmluZztcbiAgcmVmcmVzaFRva2VuPzogc3RyaW5nO1xuICB0b2tlbkV4cGlyZXNBdD86IG51bWJlcjtcbiAgdXNlcklkPzogc3RyaW5nO1xuICBlbWFpbD86IHN0cmluZztcblxuICAvLyBFbnZpcm9ubWVudFxuICBlbnZpcm9ubWVudDogXCJ0ZXN0XCIgfCBcImxpdmVcIjtcbiAgYmFzZVVybDogc3RyaW5nO1xuXG4gIC8vIFByZWZlcmVuY2VzXG4gIGRlZmF1bHRGb3JtYXQ6IFwiaHVtYW5cIiB8IFwianNvblwiO1xuICBjb2xvckVuYWJsZWQ6IGJvb2xlYW47XG5cbiAgLy8gTmV0d29ya1xuICB0aW1lb3V0OiBudW1iZXI7XG4gIG1heFJldHJpZXM6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBydW5uaW5nIGluIENJIGVudmlyb25tZW50XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0NJKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gISEoXG4gICAgcHJvY2Vzcy5lbnYuQ0kgfHxcbiAgICBwcm9jZXNzLmVudi5DT05USU5VT1VTX0lOVEVHUkFUSU9OIHx8XG4gICAgcHJvY2Vzcy5lbnYuR0lUSFVCX0FDVElPTlMgfHxcbiAgICBwcm9jZXNzLmVudi5HSVRMQUJfQ0kgfHxcbiAgICBwcm9jZXNzLmVudi5DSVJDTEVDSSB8fFxuICAgIHByb2Nlc3MuZW52LlRSQVZJUyB8fFxuICAgIHByb2Nlc3MuZW52LkJVSUxES0lURVxuICApO1xufVxuXG4vKipcbiAqIENoZWNrIGlmIGNvbG9yIG91dHB1dCBpcyBkaXNhYmxlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNDb2xvckRpc2FibGVkKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gISEoXG4gICAgcHJvY2Vzcy5lbnYuU0VORExZX05PX0NPTE9SIHx8XG4gICAgcHJvY2Vzcy5lbnYuTk9fQ09MT1IgfHxcbiAgICBwcm9jZXNzLmVudi5URVJNID09PSBcImR1bWJcIlxuICApO1xufVxuXG5jb25zdCBDT05GSUdfRElSID0gcGF0aC5qb2luKG9zLmhvbWVkaXIoKSwgXCIuc2VuZGx5XCIpO1xuY29uc3QgQ09ORklHX0ZJTEUgPSBcImNvbmZpZy5qc29uXCI7XG5cbi8vIEVuc3VyZSBjb25maWcgZGlyZWN0b3J5IGV4aXN0c1xuaWYgKCFmcy5leGlzdHNTeW5jKENPTkZJR19ESVIpKSB7XG4gIGZzLm1rZGlyU3luYyhDT05GSUdfRElSLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgbW9kZTogMG83MDAgfSk7XG59XG5cbmNvbnN0IGNvbmZpZyA9IG5ldyBDb25mPFNlbmRseUNvbmZpZz4oe1xuICBwcm9qZWN0TmFtZTogXCJzZW5kbHlcIixcbiAgY3dkOiBDT05GSUdfRElSLFxuICBjb25maWdOYW1lOiBcImNvbmZpZ1wiLFxuICBkZWZhdWx0czoge1xuICAgIGVudmlyb25tZW50OiBcInRlc3RcIixcbiAgICBiYXNlVXJsOiBcImh0dHBzOi8vc2VuZGx5LmxpdmVcIixcbiAgICBkZWZhdWx0Rm9ybWF0OiBcImh1bWFuXCIsXG4gICAgY29sb3JFbmFibGVkOiB0cnVlLFxuICAgIHRpbWVvdXQ6IDMwMDAwLFxuICAgIG1heFJldHJpZXM6IDMsXG4gIH0sXG4gIC8vIEVuY3J5cHQgc2Vuc2l0aXZlIGRhdGFcbiAgZW5jcnlwdGlvbktleTogcHJvY2Vzcy5lbnYuU0VORExZX0NPTkZJR19LRVkgfHwgXCJzZW5kbHktY2xpLWRlZmF1bHQta2V5LXYxXCIsXG59KTtcblxuLyoqXG4gKiBHZXQgZWZmZWN0aXZlIGNvbmZpZyB2YWx1ZSB3aXRoIGVudmlyb25tZW50IHZhcmlhYmxlIG92ZXJyaWRlXG4gKiBQcmlvcml0eTogZW52IHZhciA+IGNvbmZpZyBmaWxlID4gZGVmYXVsdFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWZmZWN0aXZlVmFsdWU8SyBleHRlbmRzIGtleW9mIFNlbmRseUNvbmZpZz4oXG4gIGtleTogSyxcbik6IFNlbmRseUNvbmZpZ1tLXSB7XG4gIC8vIEVudmlyb25tZW50IHZhcmlhYmxlIG92ZXJyaWRlc1xuICBzd2l0Y2ggKGtleSkge1xuICAgIGNhc2UgXCJhcGlLZXlcIjpcbiAgICAgIGlmIChwcm9jZXNzLmVudi5TRU5ETFlfQVBJX0tFWSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzcy5lbnYuU0VORExZX0FQSV9LRVkgYXMgU2VuZGx5Q29uZmlnW0tdO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImJhc2VVcmxcIjpcbiAgICAgIGlmIChwcm9jZXNzLmVudi5TRU5ETFlfQkFTRV9VUkwpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3MuZW52LlNFTkRMWV9CQVNFX1VSTCBhcyBTZW5kbHlDb25maWdbS107XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwiZGVmYXVsdEZvcm1hdFwiOlxuICAgICAgaWYgKHByb2Nlc3MuZW52LlNFTkRMWV9PVVRQVVRfRk9STUFUKSB7XG4gICAgICAgIGNvbnN0IGZvcm1hdCA9IHByb2Nlc3MuZW52LlNFTkRMWV9PVVRQVVRfRk9STUFULnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIGlmIChmb3JtYXQgPT09IFwianNvblwiIHx8IGZvcm1hdCA9PT0gXCJodW1hblwiKSB7XG4gICAgICAgICAgcmV0dXJuIGZvcm1hdCBhcyBTZW5kbHlDb25maWdbS107XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJjb2xvckVuYWJsZWRcIjpcbiAgICAgIGlmIChpc0NvbG9yRGlzYWJsZWQoKSkge1xuICAgICAgICByZXR1cm4gZmFsc2UgYXMgU2VuZGx5Q29uZmlnW0tdO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcInRpbWVvdXRcIjpcbiAgICAgIGlmIChwcm9jZXNzLmVudi5TRU5ETFlfVElNRU9VVCkge1xuICAgICAgICBjb25zdCB0aW1lb3V0ID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuU0VORExZX1RJTUVPVVQsIDEwKTtcbiAgICAgICAgaWYgKCFpc05hTih0aW1lb3V0KSAmJiB0aW1lb3V0ID4gMCkge1xuICAgICAgICAgIHJldHVybiB0aW1lb3V0IGFzIFNlbmRseUNvbmZpZ1tLXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcIm1heFJldHJpZXNcIjpcbiAgICAgIGlmIChwcm9jZXNzLmVudi5TRU5ETFlfTUFYX1JFVFJJRVMpIHtcbiAgICAgICAgY29uc3QgcmV0cmllcyA9IHBhcnNlSW50KHByb2Nlc3MuZW52LlNFTkRMWV9NQVhfUkVUUklFUywgMTApO1xuICAgICAgICBpZiAoIWlzTmFOKHJldHJpZXMpICYmIHJldHJpZXMgPj0gMCkge1xuICAgICAgICAgIHJldHVybiByZXRyaWVzIGFzIFNlbmRseUNvbmZpZ1tLXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYnJlYWs7XG4gIH1cblxuICAvLyBGYWxsIGJhY2sgdG8gY29uZmlnIGZpbGUgdmFsdWVcbiAgcmV0dXJuIGNvbmZpZy5nZXQoa2V5KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENvbmZpZygpOiBTZW5kbHlDb25maWcge1xuICByZXR1cm4gY29uZmlnLnN0b3JlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0Q29uZmlnPEsgZXh0ZW5kcyBrZXlvZiBTZW5kbHlDb25maWc+KFxuICBrZXk6IEssXG4gIHZhbHVlOiBTZW5kbHlDb25maWdbS10sXG4pOiB2b2lkIHtcbiAgY29uZmlnLnNldChrZXksIHZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENvbmZpZ1ZhbHVlPEsgZXh0ZW5kcyBrZXlvZiBTZW5kbHlDb25maWc+KFxuICBrZXk6IEssXG4pOiBTZW5kbHlDb25maWdbS10ge1xuICByZXR1cm4gY29uZmlnLmdldChrZXkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJDb25maWcoKTogdm9pZCB7XG4gIGNvbmZpZy5jbGVhcigpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJBdXRoKCk6IHZvaWQge1xuICBjb25maWcuZGVsZXRlKFwiYXBpS2V5XCIpO1xuICBjb25maWcuZGVsZXRlKFwiYWNjZXNzVG9rZW5cIik7XG4gIGNvbmZpZy5kZWxldGUoXCJyZWZyZXNoVG9rZW5cIik7XG4gIGNvbmZpZy5kZWxldGUoXCJ0b2tlbkV4cGlyZXNBdFwiKTtcbiAgY29uZmlnLmRlbGV0ZShcInVzZXJJZFwiKTtcbiAgY29uZmlnLmRlbGV0ZShcImVtYWlsXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNBdXRoZW50aWNhdGVkKCk6IGJvb2xlYW4ge1xuICAvLyBDaGVjayBlbnYgdmFyIGZpcnN0XG4gIGlmIChwcm9jZXNzLmVudi5TRU5ETFlfQVBJX0tFWSkgcmV0dXJuIHRydWU7XG5cbiAgY29uc3QgYXBpS2V5ID0gY29uZmlnLmdldChcImFwaUtleVwiKTtcbiAgY29uc3QgYWNjZXNzVG9rZW4gPSBjb25maWcuZ2V0KFwiYWNjZXNzVG9rZW5cIik7XG4gIHJldHVybiAhIShhcGlLZXkgfHwgYWNjZXNzVG9rZW4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QXV0aFRva2VuKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIC8vIEVudmlyb25tZW50IHZhcmlhYmxlIHRha2VzIGhpZ2hlc3QgcHJlY2VkZW5jZVxuICBpZiAocHJvY2Vzcy5lbnYuU0VORExZX0FQSV9LRVkpIHtcbiAgICByZXR1cm4gcHJvY2Vzcy5lbnYuU0VORExZX0FQSV9LRVk7XG4gIH1cblxuICAvLyBUaGVuIHN0b3JlZCBBUEkga2V5XG4gIGNvbnN0IGFwaUtleSA9IGNvbmZpZy5nZXQoXCJhcGlLZXlcIik7XG4gIGlmIChhcGlLZXkpIHJldHVybiBhcGlLZXk7XG5cbiAgLy8gRmluYWxseSwgYWNjZXNzIHRva2VuIChpZiBub3QgZXhwaXJlZClcbiAgY29uc3QgYWNjZXNzVG9rZW4gPSBjb25maWcuZ2V0KFwiYWNjZXNzVG9rZW5cIik7XG4gIGNvbnN0IGV4cGlyZXNBdCA9IGNvbmZpZy5nZXQoXCJ0b2tlbkV4cGlyZXNBdFwiKTtcblxuICBpZiAoYWNjZXNzVG9rZW4gJiYgZXhwaXJlc0F0ICYmIERhdGUubm93KCkgPCBleHBpcmVzQXQpIHtcbiAgICByZXR1cm4gYWNjZXNzVG9rZW47XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0QXBpS2V5KGFwaUtleTogc3RyaW5nKTogdm9pZCB7XG4gIC8vIFZhbGlkYXRlIEFQSSBrZXkgZm9ybWF0XG4gIGlmICghL15za18odGVzdHxsaXZlKV92MV9bYS16QS1aMC05Xy1dKyQvLnRlc3QoYXBpS2V5KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIFwiSW52YWxpZCBBUEkga2V5IGZvcm1hdC4gRXhwZWN0ZWQgc2tfdGVzdF92MV94eHggb3Igc2tfbGl2ZV92MV94eHhcIixcbiAgICApO1xuICB9XG5cbiAgY29uZmlnLnNldChcImFwaUtleVwiLCBhcGlLZXkpO1xuXG4gIC8vIFNldCBlbnZpcm9ubWVudCBiYXNlZCBvbiBrZXkgdHlwZVxuICBpZiAoYXBpS2V5LnN0YXJ0c1dpdGgoXCJza190ZXN0X1wiKSkge1xuICAgIGNvbmZpZy5zZXQoXCJlbnZpcm9ubWVudFwiLCBcInRlc3RcIik7XG4gIH0gZWxzZSB7XG4gICAgY29uZmlnLnNldChcImVudmlyb25tZW50XCIsIFwibGl2ZVwiKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0QXV0aFRva2VucyhcbiAgYWNjZXNzVG9rZW46IHN0cmluZyxcbiAgcmVmcmVzaFRva2VuOiBzdHJpbmcsXG4gIGV4cGlyZXNJbjogbnVtYmVyLFxuICB1c2VySWQ6IHN0cmluZyxcbiAgZW1haWw6IHN0cmluZyxcbik6IHZvaWQge1xuICBjb25maWcuc2V0KFwiYWNjZXNzVG9rZW5cIiwgYWNjZXNzVG9rZW4pO1xuICBjb25maWcuc2V0KFwicmVmcmVzaFRva2VuXCIsIHJlZnJlc2hUb2tlbik7XG4gIGNvbmZpZy5zZXQoXCJ0b2tlbkV4cGlyZXNBdFwiLCBEYXRlLm5vdygpICsgZXhwaXJlc0luICogMTAwMCk7XG4gIGNvbmZpZy5zZXQoXCJ1c2VySWRcIiwgdXNlcklkKTtcbiAgY29uZmlnLnNldChcImVtYWlsXCIsIGVtYWlsKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENvbmZpZ1BhdGgoKTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhdGguam9pbihDT05GSUdfRElSLCBDT05GSUdfRklMRSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb25maWdEaXIoKTogc3RyaW5nIHtcbiAgcmV0dXJuIENPTkZJR19ESVI7XG59XG5cbmV4cG9ydCB7IGNvbmZpZyB9O1xuIl19
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Output Formatting Utilities
3
+ * Handles human-readable and JSON output modes
4
+ */
5
+ import { type Ora } from "ora";
6
+ export type OutputFormat = "human" | "json";
7
+ export declare function setOutputFormat(format: OutputFormat): void;
8
+ export declare function setQuietMode(quiet: boolean): void;
9
+ export declare function getOutputFormat(): OutputFormat;
10
+ export declare function isJsonMode(): boolean;
11
+ export declare function isQuietMode(): boolean;
12
+ export declare const colors: {
13
+ primary: import("chalk").ChalkInstance;
14
+ success: import("chalk").ChalkInstance;
15
+ error: import("chalk").ChalkInstance;
16
+ warning: import("chalk").ChalkInstance;
17
+ info: import("chalk").ChalkInstance;
18
+ dim: import("chalk").ChalkInstance;
19
+ bold: import("chalk").ChalkInstance;
20
+ code: import("chalk").ChalkInstance;
21
+ };
22
+ export declare function success(message: string, data?: Record<string, unknown>): void;
23
+ export declare function error(message: string, details?: Record<string, unknown>): void;
24
+ export declare function warn(message: string): void;
25
+ export declare function info(message: string): void;
26
+ export declare function json(data: unknown): void;
27
+ export interface TableColumn {
28
+ header: string;
29
+ key: string;
30
+ width?: number;
31
+ formatter?: (value: unknown) => string;
32
+ }
33
+ export declare function table(data: Array<Record<string, any>>, columns: TableColumn[]): void;
34
+ export declare function spinner(text: string): Ora;
35
+ export declare function formatStatus(status: string): string;
36
+ export declare function formatDate(date: string | Date | number): string;
37
+ export declare function formatRelativeTime(date: string | Date | number): string;
38
+ export declare function formatCredits(credits: number): string;
39
+ export declare function formatPhone(phone: string): string;
40
+ export declare function header(title: string): void;
41
+ export declare function divider(): void;
42
+ export declare function keyValue(data: Record<string, unknown>): void;
43
+ export declare function codeBlock(code: string, language?: string): void;
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Output Formatting Utilities
3
+ * Handles human-readable and JSON output modes
4
+ */
5
+ import chalk from "chalk";
6
+ import Table from "cli-table3";
7
+ import ora from "ora";
8
+ let currentFormat = "human";
9
+ let quietMode = false;
10
+ export function setOutputFormat(format) {
11
+ currentFormat = format;
12
+ }
13
+ export function setQuietMode(quiet) {
14
+ quietMode = quiet;
15
+ }
16
+ export function getOutputFormat() {
17
+ return currentFormat;
18
+ }
19
+ export function isJsonMode() {
20
+ return currentFormat === "json";
21
+ }
22
+ export function isQuietMode() {
23
+ return quietMode;
24
+ }
25
+ // Colors
26
+ export const colors = {
27
+ primary: chalk.hex("#F59E0B"), // Amber/Orange - Sendly brand
28
+ success: chalk.green,
29
+ error: chalk.red,
30
+ warning: chalk.yellow,
31
+ info: chalk.blue,
32
+ dim: chalk.dim,
33
+ bold: chalk.bold,
34
+ code: chalk.cyan,
35
+ };
36
+ // Success output
37
+ export function success(message, data) {
38
+ if (isJsonMode()) {
39
+ console.log(JSON.stringify({ success: true, message, ...data }, null, 2));
40
+ return;
41
+ }
42
+ if (quietMode) {
43
+ if (data?.id)
44
+ console.log(data.id);
45
+ return;
46
+ }
47
+ console.log(`${colors.success("✓")} ${message}`);
48
+ if (data) {
49
+ Object.entries(data).forEach(([key, value]) => {
50
+ console.log(` ${colors.dim(key + ":")} ${value}`);
51
+ });
52
+ }
53
+ }
54
+ // Error output
55
+ export function error(message, details) {
56
+ if (isJsonMode()) {
57
+ console.error(JSON.stringify({ error: true, message, ...details }, null, 2));
58
+ return;
59
+ }
60
+ console.error(`${colors.error("✗")} ${message}`);
61
+ if (details && !quietMode) {
62
+ Object.entries(details).forEach(([key, value]) => {
63
+ console.error(` ${colors.dim(key + ":")} ${value}`);
64
+ });
65
+ }
66
+ }
67
+ // Warning output
68
+ export function warn(message) {
69
+ if (isJsonMode())
70
+ return;
71
+ if (quietMode)
72
+ return;
73
+ console.log(`${colors.warning("⚠")} ${message}`);
74
+ }
75
+ // Info output
76
+ export function info(message) {
77
+ if (isJsonMode())
78
+ return;
79
+ if (quietMode)
80
+ return;
81
+ console.log(`${colors.info("ℹ")} ${message}`);
82
+ }
83
+ // Print raw JSON
84
+ export function json(data) {
85
+ console.log(JSON.stringify(data, null, 2));
86
+ }
87
+ export function table(data, columns) {
88
+ if (isJsonMode()) {
89
+ console.log(JSON.stringify(data, null, 2));
90
+ return;
91
+ }
92
+ if (data.length === 0) {
93
+ info("No data to display");
94
+ return;
95
+ }
96
+ const t = new Table({
97
+ head: columns.map((c) => colors.bold(c.header)),
98
+ style: {
99
+ head: [],
100
+ border: [],
101
+ },
102
+ colWidths: columns.map((c) => c.width ?? null),
103
+ });
104
+ data.forEach((row) => {
105
+ t.push(columns.map((col) => {
106
+ const value = row[col.key];
107
+ if (col.formatter) {
108
+ return col.formatter(value);
109
+ }
110
+ return String(value ?? "-");
111
+ }));
112
+ });
113
+ console.log(t.toString());
114
+ }
115
+ // Spinner for long operations
116
+ export function spinner(text) {
117
+ if (isJsonMode() || quietMode) {
118
+ return {
119
+ start: () => ({ stop: () => { }, succeed: () => { }, fail: () => { } }),
120
+ stop: () => { },
121
+ succeed: () => { },
122
+ fail: () => { },
123
+ };
124
+ }
125
+ return ora({
126
+ text,
127
+ color: "yellow",
128
+ spinner: "dots",
129
+ });
130
+ }
131
+ // Status formatters
132
+ export function formatStatus(status) {
133
+ switch (status.toLowerCase()) {
134
+ case "delivered":
135
+ case "success":
136
+ case "active":
137
+ case "verified":
138
+ return colors.success(status);
139
+ case "failed":
140
+ case "error":
141
+ case "revoked":
142
+ case "rejected":
143
+ return colors.error(status);
144
+ case "queued":
145
+ case "pending":
146
+ case "processing":
147
+ return colors.warning(status);
148
+ case "sent":
149
+ return colors.info(status);
150
+ default:
151
+ return status;
152
+ }
153
+ }
154
+ // Format date
155
+ export function formatDate(date) {
156
+ const d = new Date(date);
157
+ return d.toLocaleString();
158
+ }
159
+ // Format relative time
160
+ export function formatRelativeTime(date) {
161
+ const d = new Date(date);
162
+ const now = new Date();
163
+ const diff = now.getTime() - d.getTime();
164
+ const seconds = Math.floor(diff / 1000);
165
+ const minutes = Math.floor(seconds / 60);
166
+ const hours = Math.floor(minutes / 60);
167
+ const days = Math.floor(hours / 24);
168
+ if (days > 0)
169
+ return `${days}d ago`;
170
+ if (hours > 0)
171
+ return `${hours}h ago`;
172
+ if (minutes > 0)
173
+ return `${minutes}m ago`;
174
+ return `${seconds}s ago`;
175
+ }
176
+ // Format credits
177
+ export function formatCredits(credits) {
178
+ return `${credits.toLocaleString()} credits`;
179
+ }
180
+ // Format phone number
181
+ export function formatPhone(phone) {
182
+ return colors.code(phone);
183
+ }
184
+ // Header for commands
185
+ export function header(title) {
186
+ if (isJsonMode() || quietMode)
187
+ return;
188
+ console.log();
189
+ console.log(colors.bold(colors.primary(title)));
190
+ console.log(colors.dim("─".repeat(40)));
191
+ }
192
+ // Divider
193
+ export function divider() {
194
+ if (isJsonMode() || quietMode)
195
+ return;
196
+ console.log();
197
+ }
198
+ // Key-value display
199
+ export function keyValue(data) {
200
+ if (isJsonMode()) {
201
+ console.log(JSON.stringify(data, null, 2));
202
+ return;
203
+ }
204
+ const maxKeyLength = Math.max(...Object.keys(data).map((k) => k.length));
205
+ Object.entries(data).forEach(([key, value]) => {
206
+ const paddedKey = key.padEnd(maxKeyLength);
207
+ console.log(` ${colors.dim(paddedKey)} ${value}`);
208
+ });
209
+ }
210
+ // Code block
211
+ export function codeBlock(code, language) {
212
+ if (isJsonMode()) {
213
+ console.log(JSON.stringify({ code, language }, null, 2));
214
+ return;
215
+ }
216
+ console.log();
217
+ console.log(colors.dim("```" + (language || "")));
218
+ console.log(colors.code(code));
219
+ console.log(colors.dim("```"));
220
+ console.log();
221
+ }
222
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0cHV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9vdXRwdXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sS0FBSyxNQUFNLFlBQVksQ0FBQztBQUMvQixPQUFPLEdBQWlCLE1BQU0sS0FBSyxDQUFDO0FBS3BDLElBQUksYUFBYSxHQUFpQixPQUFPLENBQUM7QUFDMUMsSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFDO0FBRXRCLE1BQU0sVUFBVSxlQUFlLENBQUMsTUFBb0I7SUFDbEQsYUFBYSxHQUFHLE1BQU0sQ0FBQztBQUN6QixDQUFDO0FBRUQsTUFBTSxVQUFVLFlBQVksQ0FBQyxLQUFjO0lBQ3pDLFNBQVMsR0FBRyxLQUFLLENBQUM7QUFDcEIsQ0FBQztBQUVELE1BQU0sVUFBVSxlQUFlO0lBQzdCLE9BQU8sYUFBYSxDQUFDO0FBQ3ZCLENBQUM7QUFFRCxNQUFNLFVBQVUsVUFBVTtJQUN4QixPQUFPLGFBQWEsS0FBSyxNQUFNLENBQUM7QUFDbEMsQ0FBQztBQUVELE1BQU0sVUFBVSxXQUFXO0lBQ3pCLE9BQU8sU0FBUyxDQUFDO0FBQ25CLENBQUM7QUFFRCxTQUFTO0FBQ1QsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFHO0lBQ3BCLE9BQU8sRUFBRSxLQUFLLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFLDhCQUE4QjtJQUM3RCxPQUFPLEVBQUUsS0FBSyxDQUFDLEtBQUs7SUFDcEIsS0FBSyxFQUFFLEtBQUssQ0FBQyxHQUFHO0lBQ2hCLE9BQU8sRUFBRSxLQUFLLENBQUMsTUFBTTtJQUNyQixJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7SUFDaEIsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHO0lBQ2QsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO0lBQ2hCLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtDQUNqQixD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LEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQy9CLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNoQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPdXRwdXQgRm9ybWF0dGluZyBVdGlsaXRpZXNcbiAqIEhhbmRsZXMgaHVtYW4tcmVhZGFibGUgYW5kIEpTT04gb3V0cHV0IG1vZGVzXG4gKi9cblxuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiO1xuaW1wb3J0IFRhYmxlIGZyb20gXCJjbGktdGFibGUzXCI7XG5pbXBvcnQgb3JhLCB7IHR5cGUgT3JhIH0gZnJvbSBcIm9yYVwiO1xuaW1wb3J0IHsgZ2V0Q29uZmlnVmFsdWUgfSBmcm9tIFwiLi9jb25maWcuanNcIjtcblxuZXhwb3J0IHR5cGUgT3V0cHV0Rm9ybWF0ID0gXCJodW1hblwiIHwgXCJqc29uXCI7XG5cbmxldCBjdXJyZW50Rm9ybWF0OiBPdXRwdXRGb3JtYXQgPSBcImh1bWFuXCI7XG5sZXQgcXVpZXRNb2RlID0gZmFsc2U7XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRPdXRwdXRGb3JtYXQoZm9ybWF0OiBPdXRwdXRGb3JtYXQpOiB2b2lkIHtcbiAgY3VycmVudEZvcm1hdCA9IGZvcm1hdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldFF1aWV0TW9kZShxdWlldDogYm9vbGVhbik6IHZvaWQge1xuICBxdWlldE1vZGUgPSBxdWlldDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE91dHB1dEZvcm1hdCgpOiBPdXRwdXRGb3JtYXQge1xuICByZXR1cm4gY3VycmVudEZvcm1hdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzSnNvbk1vZGUoKTogYm9vbGVhbiB7XG4gIHJldHVybiBjdXJyZW50Rm9ybWF0ID09PSBcImpzb25cIjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzUXVpZXRNb2RlKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gcXVpZXRNb2RlO1xufVxuXG4vLyBDb2xvcnNcbmV4cG9ydCBjb25zdCBjb2xvcnMgPSB7XG4gIHByaW1hcnk6IGNoYWxrLmhleChcIiNGNTlFMEJcIiksIC8vIEFtYmVyL09yYW5nZSAtIFNlbmRseSBicmFuZFxuICBzdWNjZXNzOiBjaGFsay5ncmVlbixcbiAgZXJyb3I6IGNoYWxrLnJlZCxcbiAgd2FybmluZzogY2hhbGsueWVsbG93LFxuICBpbmZvOiBjaGFsay5ibHVlLFxuICBkaW06IGNoYWxrLmRpbSxcbiAgYm9sZDogY2hhbGsuYm9sZCxcbiAgY29kZTogY2hhbGsuY3lhbixcbn07XG5cbi8vIFN1Y2Nlc3Mgb3V0cHV0XG5leHBvcnQgZnVuY3Rpb24gc3VjY2VzcyhtZXNzYWdlOiBzdHJpbmcsIGRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHZvaWQge1xuICBpZiAoaXNKc29uTW9kZSgpKSB7XG4gICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoeyBzdWNjZXNzOiB0cnVlLCBtZXNzYWdlLCAuLi5kYXRhIH0sIG51bGwsIDIpKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAocXVpZXRNb2RlKSB7XG4gICAgaWYgKGRhdGE/LmlkKSBjb25zb2xlLmxvZyhkYXRhLmlkKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zb2xlLmxvZyhgJHtjb2xvcnMuc3VjY2VzcyhcIuKck1wiKX0gJHttZXNzYWdlfWApO1xuICBpZiAoZGF0YSkge1xuICAgIE9iamVjdC5lbnRyaWVzKGRhdGEpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgY29uc29sZS5sb2coYCAgJHtjb2xvcnMuZGltKGtleSArIFwiOlwiKX0gJHt2YWx1ZX1gKTtcbiAgICB9KTtcbiAgfVxufVxuXG4vLyBFcnJvciBvdXRwdXRcbmV4cG9ydCBmdW5jdGlvbiBlcnJvcihcbiAgbWVzc2FnZTogc3RyaW5nLFxuICBkZXRhaWxzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4pOiB2b2lkIHtcbiAgaWYgKGlzSnNvbk1vZGUoKSkge1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICBKU09OLnN0cmluZ2lmeSh7IGVycm9yOiB0cnVlLCBtZXNzYWdlLCAuLi5kZXRhaWxzIH0sIG51bGwsIDIpLFxuICAgICk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc29sZS5lcnJvcihgJHtjb2xvcnMuZXJyb3IoXCLinJdcIil9ICR7bWVzc2FnZX1gKTtcbiAgaWYgKGRldGFpbHMgJiYgIXF1aWV0TW9kZSkge1xuICAgIE9iamVjdC5lbnRyaWVzKGRldGFpbHMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgY29uc29sZS5lcnJvcihgICAke2NvbG9ycy5kaW0oa2V5ICsgXCI6XCIpfSAke3ZhbHVlfWApO1xuICAgIH0pO1xuICB9XG59XG5cbi8vIFdhcm5pbmcgb3V0cHV0XG5leHBvcnQgZnVuY3Rpb24gd2FybihtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKGlzSnNvbk1vZGUoKSkgcmV0dXJuO1xuICBpZiAocXVpZXRNb2RlKSByZXR1cm47XG4gIGNvbnNvbGUubG9nKGAke2NvbG9ycy53YXJuaW5nKFwi4pqgXCIpfSAke21lc3NhZ2V9YCk7XG59XG5cbi8vIEluZm8gb3V0cHV0XG5leHBvcnQgZnVuY3Rpb24gaW5mbyhtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKGlzSnNvbk1vZGUoKSkgcmV0dXJuO1xuICBpZiAocXVpZXRNb2RlKSByZXR1cm47XG4gIGNvbnNvbGUubG9nKGAke2NvbG9ycy5pbmZvKFwi4oS5XCIpfSAke21lc3NhZ2V9YCk7XG59XG5cbi8vIFByaW50IHJhdyBKU09OXG5leHBvcnQgZnVuY3Rpb24ganNvbihkYXRhOiB1bmtub3duKTogdm9pZCB7XG4gIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KGRhdGEsIG51bGwsIDIpKTtcbn1cblxuLy8gUHJpbnQgYSB0YWJsZVxuZXhwb3J0IGludGVyZmFjZSBUYWJsZUNvbHVtbiB7XG4gIGhlYWRlcjogc3RyaW5nO1xuICBrZXk6IHN0cmluZztcbiAgd2lkdGg/OiBudW1iZXI7XG4gIGZvcm1hdHRlcj86ICh2YWx1ZTogdW5rbm93bikgPT4gc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdGFibGUoXG4gIGRhdGE6IEFycmF5PFJlY29yZDxzdHJpbmcsIGFueT4+LFxuICBjb2x1bW5zOiBUYWJsZUNvbHVtbltdLFxuKTogdm9pZCB7XG4gIGlmIChpc0pzb25Nb2RlKCkpIHtcbiAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeShkYXRhLCBudWxsLCAyKSk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKGRhdGEubGVuZ3RoID09PSAwKSB7XG4gICAgaW5mbyhcIk5vIGRhdGEgdG8gZGlzcGxheVwiKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCB0ID0gbmV3IFRhYmxlKHtcbiAgICBoZWFkOiBjb2x1bW5zLm1hcCgoYykgPT4gY29sb3JzLmJvbGQoYy5oZWFkZXIpKSxcbiAgICBzdHlsZToge1xuICAgICAgaGVhZDogW10sXG4gICAgICBib3JkZXI6IFtdLFxuICAgIH0sXG4gICAgY29sV2lkdGhzOiBjb2x1bW5zLm1hcCgoYykgPT4gYy53aWR0aCA/PyBudWxsKSxcbiAgfSk7XG5cbiAgZGF0YS5mb3JFYWNoKChyb3cpID0+IHtcbiAgICB0LnB1c2goXG4gICAgICBjb2x1bW5zLm1hcCgoY29sKSA9PiB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gcm93W2NvbC5rZXldO1xuICAgICAgICBpZiAoY29sLmZvcm1hdHRlcikge1xuICAgICAgICAgIHJldHVybiBjb2wuZm9ybWF0dGVyKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gU3RyaW5nKHZhbHVlID8/IFwiLVwiKTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH0pO1xuXG4gIGNvbnNvbGUubG9nKHQudG9TdHJpbmcoKSk7XG59XG5cbi8vIFNwaW5uZXIgZm9yIGxvbmcgb3BlcmF0aW9uc1xuZXhwb3J0IGZ1bmN0aW9uIHNwaW5uZXIodGV4dDogc3RyaW5nKTogT3JhIHtcbiAgaWYgKGlzSnNvbk1vZGUoKSB8fCBxdWlldE1vZGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3RhcnQ6ICgpID0+ICh7IHN0b3A6ICgpID0+IHt9LCBzdWNjZWVkOiAoKSA9PiB7fSwgZmFpbDogKCkgPT4ge30gfSksXG4gICAgICBzdG9wOiAoKSA9PiB7fSxcbiAgICAgIHN1Y2NlZWQ6ICgpID0+IHt9LFxuICAgICAgZmFpbDogKCkgPT4ge30sXG4gICAgfSBhcyB1bmtub3duIGFzIE9yYTtcbiAgfVxuXG4gIHJldHVybiBvcmEoe1xuICAgIHRleHQsXG4gICAgY29sb3I6IFwieWVsbG93XCIsXG4gICAgc3Bpbm5lcjogXCJkb3RzXCIsXG4gIH0pO1xufVxuXG4vLyBTdGF0dXMgZm9ybWF0dGVyc1xuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFN0YXR1cyhzdGF0dXM6IHN0cmluZyk6IHN0cmluZyB7XG4gIHN3aXRjaCAoc3RhdHVzLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlIFwiZGVsaXZlcmVkXCI6XG4gICAgY2FzZSBcInN1Y2Nlc3NcIjpcbiAgICBjYXNlIFwiYWN0aXZlXCI6XG4gICAgY2FzZSBcInZlcmlmaWVkXCI6XG4gICAgICByZXR1cm4gY29sb3JzLnN1Y2Nlc3Moc3RhdHVzKTtcbiAgICBjYXNlIFwiZmFpbGVkXCI6XG4gICAgY2FzZSBcImVycm9yXCI6XG4gICAgY2FzZSBcInJldm9rZWRcIjpcbiAgICBjYXNlIFwicmVqZWN0ZWRcIjpcbiAgICAgIHJldHVybiBjb2xvcnMuZXJyb3Ioc3RhdHVzKTtcbiAgICBjYXNlIFwicXVldWVkXCI6XG4gICAgY2FzZSBcInBlbmRpbmdcIjpcbiAgICBjYXNlIFwicHJvY2Vzc2luZ1wiOlxuICAgICAgcmV0dXJuIGNvbG9ycy53YXJuaW5nKHN0YXR1cyk7XG4gICAgY2FzZSBcInNlbnRcIjpcbiAgICAgIHJldHVybiBjb2xvcnMuaW5mbyhzdGF0dXMpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gc3RhdHVzO1xuICB9XG59XG5cbi8vIEZvcm1hdCBkYXRlXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0RGF0ZShkYXRlOiBzdHJpbmcgfCBEYXRlIHwgbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgZCA9IG5ldyBEYXRlKGRhdGUpO1xuICByZXR1cm4gZC50b0xvY2FsZVN0cmluZygpO1xufVxuXG4vLyBGb3JtYXQgcmVsYXRpdmUgdGltZVxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFJlbGF0aXZlVGltZShkYXRlOiBzdHJpbmcgfCBEYXRlIHwgbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgZCA9IG5ldyBEYXRlKGRhdGUpO1xuICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICBjb25zdCBkaWZmID0gbm93LmdldFRpbWUoKSAtIGQuZ2V0VGltZSgpO1xuXG4gIGNvbnN0IHNlY29uZHMgPSBNYXRoLmZsb29yKGRpZmYgLyAxMDAwKTtcbiAgY29uc3QgbWludXRlcyA9IE1hdGguZmxvb3Ioc2Vjb25kcyAvIDYwKTtcbiAgY29uc3QgaG91cnMgPSBNYXRoLmZsb29yKG1pbnV0ZXMgLyA2MCk7XG4gIGNvbnN0IGRheXMgPSBNYXRoLmZsb29yKGhvdXJzIC8gMjQpO1xuXG4gIGlmIChkYXlzID4gMCkgcmV0dXJuIGAke2RheXN9ZCBhZ29gO1xuICBpZiAoaG91cnMgPiAwKSByZXR1cm4gYCR7aG91cnN9aCBhZ29gO1xuICBpZiAobWludXRlcyA+IDApIHJldHVybiBgJHttaW51dGVzfW0gYWdvYDtcbiAgcmV0dXJuIGAke3NlY29uZHN9cyBhZ29gO1xufVxuXG4vLyBGb3JtYXQgY3JlZGl0c1xuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdENyZWRpdHMoY3JlZGl0czogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke2NyZWRpdHMudG9Mb2NhbGVTdHJpbmcoKX0gY3JlZGl0c2A7XG59XG5cbi8vIEZvcm1hdCBwaG9uZSBudW1iZXJcbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRQaG9uZShwaG9uZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGNvbG9ycy5jb2RlKHBob25lKTtcbn1cblxuLy8gSGVhZGVyIGZvciBjb21tYW5kc1xuZXhwb3J0IGZ1bmN0aW9uIGhlYWRlcih0aXRsZTogc3RyaW5nKTogdm9pZCB7XG4gIGlmIChpc0pzb25Nb2RlKCkgfHwgcXVpZXRNb2RlKSByZXR1cm47XG4gIGNvbnNvbGUubG9nKCk7XG4gIGNvbnNvbGUubG9nKGNvbG9ycy5ib2xkKGNvbG9ycy5wcmltYXJ5KHRpdGxlKSkpO1xuICBjb25zb2xlLmxvZyhjb2xvcnMuZGltKFwi4pSAXCIucmVwZWF0KDQwKSkpO1xufVxuXG4vLyBEaXZpZGVyXG5leHBvcnQgZnVuY3Rpb24gZGl2aWRlcigpOiB2b2lkIHtcbiAgaWYgKGlzSnNvbk1vZGUoKSB8fCBxdWlldE1vZGUpIHJldHVybjtcbiAgY29uc29sZS5sb2coKTtcbn1cblxuLy8gS2V5LXZhbHVlIGRpc3BsYXlcbmV4cG9ydCBmdW5jdGlvbiBrZXlWYWx1ZShkYXRhOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHZvaWQge1xuICBpZiAoaXNKc29uTW9kZSgpKSB7XG4gICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoZGF0YSwgbnVsbCwgMikpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IG1heEtleUxlbmd0aCA9IE1hdGgubWF4KC4uLk9iamVjdC5rZXlzKGRhdGEpLm1hcCgoaykgPT4gay5sZW5ndGgpKTtcblxuICBPYmplY3QuZW50cmllcyhkYXRhKS5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICBjb25zdCBwYWRkZWRLZXkgPSBrZXkucGFkRW5kKG1heEtleUxlbmd0aCk7XG4gICAgY29uc29sZS5sb2coYCAgJHtjb2xvcnMuZGltKHBhZGRlZEtleSl9ICAke3ZhbHVlfWApO1xuICB9KTtcbn1cblxuLy8gQ29kZSBibG9ja1xuZXhwb3J0IGZ1bmN0aW9uIGNvZGVCbG9jayhjb2RlOiBzdHJpbmcsIGxhbmd1YWdlPzogc3RyaW5nKTogdm9pZCB7XG4gIGlmIChpc0pzb25Nb2RlKCkpIHtcbiAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7IGNvZGUsIGxhbmd1YWdlIH0sIG51bGwsIDIpKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zb2xlLmxvZygpO1xuICBjb25zb2xlLmxvZyhjb2xvcnMuZGltKFwiYGBgXCIgKyAobGFuZ3VhZ2UgfHwgXCJcIikpKTtcbiAgY29uc29sZS5sb2coY29sb3JzLmNvZGUoY29kZSkpO1xuICBjb25zb2xlLmxvZyhjb2xvcnMuZGltKFwiYGBgXCIpKTtcbiAgY29uc29sZS5sb2coKTtcbn1cbiJdfQ==