@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
package/README.md ADDED
@@ -0,0 +1,323 @@
1
+ # @sendly/cli
2
+
3
+ Official command-line interface for the [Sendly](https://sendly.live) SMS API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @sendly/cli
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```bash
14
+ # Login to your Sendly account
15
+ sendly login
16
+
17
+ # Send an SMS
18
+ sendly sms send --to "+15551234567" --text "Hello from Sendly CLI!"
19
+
20
+ # Check your credit balance
21
+ sendly credits balance
22
+ ```
23
+
24
+ ## Authentication
25
+
26
+ The CLI supports two authentication methods:
27
+
28
+ ### Browser Login (Recommended)
29
+
30
+ ```bash
31
+ sendly login
32
+ ```
33
+
34
+ This opens your browser to authenticate via Sendly's secure login flow. After authorization, your credentials are stored locally.
35
+
36
+ ### API Key Login
37
+
38
+ ```bash
39
+ sendly login --api-key sk_test_v1_your_key
40
+ ```
41
+
42
+ Or interactively:
43
+
44
+ ```bash
45
+ sendly login -i
46
+ ```
47
+
48
+ ### Check Authentication Status
49
+
50
+ ```bash
51
+ sendly whoami
52
+ ```
53
+
54
+ ### Logout
55
+
56
+ ```bash
57
+ sendly logout
58
+ ```
59
+
60
+ ## Commands
61
+
62
+ ### SMS Commands
63
+
64
+ #### Send a Message
65
+
66
+ ```bash
67
+ sendly sms send --to "+15551234567" --text "Hello!"
68
+
69
+ # With sender ID (international)
70
+ sendly sms send --to "+447700900000" --text "Hello!" --from "MyBrand"
71
+ ```
72
+
73
+ #### List Messages
74
+
75
+ ```bash
76
+ sendly sms list
77
+
78
+ # Filter by status
79
+ sendly sms list --status delivered
80
+
81
+ # Limit results
82
+ sendly sms list --limit 10
83
+ ```
84
+
85
+ #### Get Message Details
86
+
87
+ ```bash
88
+ sendly sms get msg_abc123
89
+ ```
90
+
91
+ #### Send Batch Messages
92
+
93
+ ```bash
94
+ # From a CSV file
95
+ sendly sms batch --file recipients.csv --text "Hello {name}!"
96
+
97
+ # Multiple recipients inline
98
+ sendly sms batch --to "+15551234567,+15559876543" --text "Hello everyone!"
99
+ ```
100
+
101
+ #### Schedule a Message
102
+
103
+ ```bash
104
+ sendly sms schedule --to "+15551234567" --text "Reminder!" --at "2025-12-25T10:00:00Z"
105
+ ```
106
+
107
+ #### List Scheduled Messages
108
+
109
+ ```bash
110
+ sendly sms scheduled
111
+ ```
112
+
113
+ #### Cancel a Scheduled Message
114
+
115
+ ```bash
116
+ sendly sms cancel sched_abc123
117
+ ```
118
+
119
+ ### API Key Commands
120
+
121
+ #### List API Keys
122
+
123
+ ```bash
124
+ sendly keys list
125
+ ```
126
+
127
+ #### Create a New Key
128
+
129
+ ```bash
130
+ sendly keys create --name "Production Key" --type live
131
+ ```
132
+
133
+ #### Revoke a Key
134
+
135
+ ```bash
136
+ sendly keys revoke key_abc123
137
+ ```
138
+
139
+ ### Credit Commands
140
+
141
+ #### Check Balance
142
+
143
+ ```bash
144
+ sendly credits balance
145
+ ```
146
+
147
+ Output includes:
148
+ - Current balance
149
+ - Reserved credits
150
+ - Estimated messages remaining
151
+
152
+ #### View Transaction History
153
+
154
+ ```bash
155
+ sendly credits history
156
+
157
+ # Limit results
158
+ sendly credits history --limit 20
159
+ ```
160
+
161
+ ### Webhook Commands
162
+
163
+ #### List Webhooks
164
+
165
+ ```bash
166
+ sendly webhooks list
167
+ ```
168
+
169
+ #### Listen for Webhooks Locally
170
+
171
+ Start a local tunnel to receive webhook events during development (similar to Stripe CLI):
172
+
173
+ ```bash
174
+ sendly webhooks listen
175
+
176
+ # Forward to a specific URL
177
+ sendly webhooks listen --forward http://localhost:3000/webhook
178
+
179
+ # Listen for specific events
180
+ sendly webhooks listen --events message.delivered,message.failed
181
+ ```
182
+
183
+ This creates a secure tunnel and displays:
184
+ - Tunnel URL
185
+ - Webhook secret for signature verification
186
+ - Real-time event stream
187
+
188
+ ### Logs Commands
189
+
190
+ #### Tail Logs
191
+
192
+ Stream real-time API activity:
193
+
194
+ ```bash
195
+ sendly logs tail
196
+
197
+ # Filter by status
198
+ sendly logs tail --status error
199
+ ```
200
+
201
+ ### Configuration Commands
202
+
203
+ #### Get Configuration Value
204
+
205
+ ```bash
206
+ sendly config get baseUrl
207
+ ```
208
+
209
+ #### Set Configuration Value
210
+
211
+ ```bash
212
+ sendly config set baseUrl https://api.sendly.live
213
+ ```
214
+
215
+ #### List All Configuration
216
+
217
+ ```bash
218
+ sendly config list
219
+ ```
220
+
221
+ ### Diagnostics
222
+
223
+ Run diagnostics to check your setup:
224
+
225
+ ```bash
226
+ sendly doctor
227
+ ```
228
+
229
+ This checks:
230
+ - Authentication status
231
+ - API connectivity
232
+ - Configuration validity
233
+ - Network issues
234
+
235
+ ## Environment Variables
236
+
237
+ Override CLI configuration with environment variables:
238
+
239
+ | Variable | Description |
240
+ |----------|-------------|
241
+ | `SENDLY_API_KEY` | API key for authentication |
242
+ | `SENDLY_BASE_URL` | API base URL (default: `https://sendly.live`) |
243
+ | `SENDLY_OUTPUT_FORMAT` | Output format: `text` or `json` |
244
+ | `SENDLY_NO_COLOR` | Disable colored output |
245
+ | `SENDLY_TIMEOUT` | Request timeout in milliseconds |
246
+ | `SENDLY_MAX_RETRIES` | Maximum retry attempts |
247
+
248
+ ## Output Formats
249
+
250
+ ### Text (Default)
251
+
252
+ Human-readable formatted output with colors.
253
+
254
+ ### JSON
255
+
256
+ Machine-readable JSON output for scripting:
257
+
258
+ ```bash
259
+ sendly sms list --json
260
+ sendly credits balance --json
261
+ ```
262
+
263
+ ## CI/CD Usage
264
+
265
+ For non-interactive environments:
266
+
267
+ ```bash
268
+ # Set API key via environment variable
269
+ export SENDLY_API_KEY=sk_live_v1_your_key
270
+
271
+ # Or pass directly
272
+ sendly sms send --api-key sk_live_v1_your_key --to "+15551234567" --text "Hello!"
273
+
274
+ # Use JSON output for parsing
275
+ sendly credits balance --json | jq '.balance'
276
+ ```
277
+
278
+ ## Configuration Storage
279
+
280
+ Configuration is stored in:
281
+ - **macOS**: `~/.config/sendly/`
282
+ - **Linux**: `~/.config/sendly/`
283
+ - **Windows**: `%APPDATA%\sendly\`
284
+
285
+ ## Webhook Signature Verification
286
+
287
+ When using `sendly webhooks listen`, verify signatures in your app:
288
+
289
+ ```javascript
290
+ import crypto from 'crypto';
291
+
292
+ function verifyWebhook(payload, signature, secret) {
293
+ const expectedSig = 'v1=' + crypto
294
+ .createHmac('sha256', secret)
295
+ .update(payload)
296
+ .digest('hex');
297
+
298
+ return crypto.timingSafeEqual(
299
+ Buffer.from(signature),
300
+ Buffer.from(expectedSig)
301
+ );
302
+ }
303
+ ```
304
+
305
+ ## Requirements
306
+
307
+ - Node.js 18.0.0 or higher
308
+ - A Sendly account ([sign up free](https://sendly.live))
309
+
310
+ ## Documentation
311
+
312
+ - [CLI Documentation](https://sendly.live/docs/cli)
313
+ - [API Reference](https://sendly.live/docs/api)
314
+ - [Sendly Dashboard](https://sendly.live/dashboard)
315
+
316
+ ## Support
317
+
318
+ - [GitHub Issues](https://github.com/sendly-live/sendly-cli/issues)
319
+ - Email: support@sendly.live
320
+
321
+ ## License
322
+
323
+ MIT
package/bin/run.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execute } from "@oclif/core";
4
+
5
+ await execute({ dir: import.meta.url });
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from "../../lib/base-command.js";
2
+ export default class ConfigGet extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ key: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
10
+ quiet: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,38 @@
1
+ import { Args } from "@oclif/core";
2
+ import { BaseCommand } from "../../lib/base-command.js";
3
+ import { getConfigValue } from "../../lib/config.js";
4
+ import { colors, json, isJsonMode } from "../../lib/output.js";
5
+ const ALLOWED_KEYS = [
6
+ "environment",
7
+ "baseUrl",
8
+ "defaultFormat",
9
+ "colorEnabled",
10
+ ];
11
+ export default class ConfigGet extends BaseCommand {
12
+ static description = "Get a configuration value";
13
+ static examples = [
14
+ "<%= config.bin %> config get environment",
15
+ "<%= config.bin %> config get baseUrl",
16
+ ];
17
+ static args = {
18
+ key: Args.string({
19
+ description: "Configuration key",
20
+ required: true,
21
+ options: ALLOWED_KEYS,
22
+ }),
23
+ };
24
+ static flags = {
25
+ ...BaseCommand.baseFlags,
26
+ };
27
+ async run() {
28
+ const { args, flags } = await this.parse(ConfigGet);
29
+ const key = args.key;
30
+ const value = getConfigValue(key);
31
+ if (isJsonMode()) {
32
+ json({ [key]: value });
33
+ return;
34
+ }
35
+ console.log(`${colors.dim(key + ":")} ${colors.primary(String(value))}`);
36
+ }
37
+ }
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2NvbmZpZy9nZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNuQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGNBQWMsRUFBcUIsTUFBTSxxQkFBcUIsQ0FBQztBQUN4RSxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUUvRCxNQUFNLFlBQVksR0FBMkI7SUFDM0MsYUFBYTtJQUNiLFNBQVM7SUFDVCxlQUFlO0lBQ2YsY0FBYztDQUNmLENBQUM7QUFFRixNQUFNLENBQUMsT0FBTyxPQUFPLFNBQVUsU0FBUSxXQUFXO0lBQ2hELE1BQU0sQ0FBQyxXQUFXLEdBQUcsMkJBQTJCLENBQUM7SUFFakQsTUFBTSxDQUFDLFFBQVEsR0FBRztRQUNoQiwwQ0FBMEM7UUFDMUMsc0NBQXNDO0tBQ3ZDLENBQUM7SUFFRixNQUFNLENBQUMsSUFBSSxHQUFHO1FBQ1osR0FBRyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUM7WUFDZixXQUFXLEVBQUUsbUJBQW1CO1lBQ2hDLFFBQVEsRUFBRSxJQUFJO1lBQ2QsT0FBTyxFQUFFLFlBQXdCO1NBQ2xDLENBQUM7S0FDSCxDQUFDO0lBRUYsTUFBTSxDQUFDLEtBQUssR0FBRztRQUNiLEdBQUcsV0FBVyxDQUFDLFNBQVM7S0FDekIsQ0FBQztJQUVGLEtBQUssQ0FBQyxHQUFHO1FBQ1AsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFcEQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQXlCLENBQUM7UUFDM0MsTUFBTSxLQUFLLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRWxDLElBQUksVUFBVSxFQUFFLEVBQUUsQ0FBQztZQUNqQixJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDdkIsT0FBTztRQUNULENBQUM7UUFFRCxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDM0UsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFyZ3MgfSBmcm9tIFwiQG9jbGlmL2NvcmVcIjtcbmltcG9ydCB7IEJhc2VDb21tYW5kIH0gZnJvbSBcIi4uLy4uL2xpYi9iYXNlLWNvbW1hbmQuanNcIjtcbmltcG9ydCB7IGdldENvbmZpZ1ZhbHVlLCB0eXBlIFNlbmRseUNvbmZpZyB9IGZyb20gXCIuLi8uLi9saWIvY29uZmlnLmpzXCI7XG5pbXBvcnQgeyBjb2xvcnMsIGpzb24sIGlzSnNvbk1vZGUgfSBmcm9tIFwiLi4vLi4vbGliL291dHB1dC5qc1wiO1xuXG5jb25zdCBBTExPV0VEX0tFWVM6IChrZXlvZiBTZW5kbHlDb25maWcpW10gPSBbXG4gIFwiZW52aXJvbm1lbnRcIixcbiAgXCJiYXNlVXJsXCIsXG4gIFwiZGVmYXVsdEZvcm1hdFwiLFxuICBcImNvbG9yRW5hYmxlZFwiLFxuXTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ29uZmlnR2V0IGV4dGVuZHMgQmFzZUNvbW1hbmQge1xuICBzdGF0aWMgZGVzY3JpcHRpb24gPSBcIkdldCBhIGNvbmZpZ3VyYXRpb24gdmFsdWVcIjtcblxuICBzdGF0aWMgZXhhbXBsZXMgPSBbXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiBjb25maWcgZ2V0IGVudmlyb25tZW50XCIsXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiBjb25maWcgZ2V0IGJhc2VVcmxcIixcbiAgXTtcblxuICBzdGF0aWMgYXJncyA9IHtcbiAgICBrZXk6IEFyZ3Muc3RyaW5nKHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkNvbmZpZ3VyYXRpb24ga2V5XCIsXG4gICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgIG9wdGlvbnM6IEFMTE9XRURfS0VZUyBhcyBzdHJpbmdbXSxcbiAgICB9KSxcbiAgfTtcblxuICBzdGF0aWMgZmxhZ3MgPSB7XG4gICAgLi4uQmFzZUNvbW1hbmQuYmFzZUZsYWdzLFxuICB9O1xuXG4gIGFzeW5jIHJ1bigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGFyZ3MsIGZsYWdzIH0gPSBhd2FpdCB0aGlzLnBhcnNlKENvbmZpZ0dldCk7XG5cbiAgICBjb25zdCBrZXkgPSBhcmdzLmtleSBhcyBrZXlvZiBTZW5kbHlDb25maWc7XG4gICAgY29uc3QgdmFsdWUgPSBnZXRDb25maWdWYWx1ZShrZXkpO1xuXG4gICAgaWYgKGlzSnNvbk1vZGUoKSkge1xuICAgICAganNvbih7IFtrZXldOiB2YWx1ZSB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZyhgJHtjb2xvcnMuZGltKGtleSArIFwiOlwiKX0gJHtjb2xvcnMucHJpbWFyeShTdHJpbmcodmFsdWUpKX1gKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,10 @@
1
+ import { BaseCommand } from "../../lib/base-command.js";
2
+ export default class ConfigList extends BaseCommand {
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
+ }
@@ -0,0 +1,45 @@
1
+ import { BaseCommand } from "../../lib/base-command.js";
2
+ import { getConfig, getConfigPath, } from "../../lib/config.js";
3
+ import { colors, keyValue, json, isJsonMode, header } from "../../lib/output.js";
4
+ export default class ConfigList extends BaseCommand {
5
+ static description = "List all configuration values";
6
+ static examples = [
7
+ "<%= config.bin %> config list",
8
+ "<%= config.bin %> config list --json",
9
+ ];
10
+ static flags = {
11
+ ...BaseCommand.baseFlags,
12
+ };
13
+ async run() {
14
+ const config = getConfig();
15
+ if (isJsonMode()) {
16
+ // Don't expose sensitive data in JSON output
17
+ const safeConfig = {
18
+ environment: config.environment,
19
+ baseUrl: config.baseUrl,
20
+ defaultFormat: config.defaultFormat,
21
+ colorEnabled: config.colorEnabled,
22
+ hasApiKey: !!config.apiKey,
23
+ hasAccessToken: !!config.accessToken,
24
+ configPath: getConfigPath(),
25
+ };
26
+ json(safeConfig);
27
+ return;
28
+ }
29
+ header("Configuration");
30
+ const displayConfig = {
31
+ Environment: config.environment === "live"
32
+ ? colors.success(config.environment)
33
+ : colors.warning(config.environment),
34
+ "Base URL": config.baseUrl,
35
+ "Output Format": config.defaultFormat,
36
+ "Colors": config.colorEnabled ? colors.success("enabled") : colors.dim("disabled"),
37
+ "API Key": config.apiKey ? colors.success("configured") : colors.dim("not set"),
38
+ "Access Token": config.accessToken ? colors.success("configured") : colors.dim("not set"),
39
+ };
40
+ keyValue(displayConfig);
41
+ console.log();
42
+ console.log(colors.dim(`Config file: ${getConfigPath()}`));
43
+ }
44
+ }
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9jb25maWcvbGlzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDeEQsT0FBTyxFQUNMLFNBQVMsRUFDVCxhQUFhLEdBRWQsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRWpGLE1BQU0sQ0FBQyxPQUFPLE9BQU8sVUFBVyxTQUFRLFdBQVc7SUFDakQsTUFBTSxDQUFDLFdBQVcsR0FBRywrQkFBK0IsQ0FBQztJQUVyRCxNQUFNLENBQUMsUUFBUSxHQUFHO1FBQ2hCLCtCQUErQjtRQUMvQixzQ0FBc0M7S0FDdkMsQ0FBQztJQUVGLE1BQU0sQ0FBQyxLQUFLLEdBQUc7UUFDYixHQUFHLFdBQVcsQ0FBQyxTQUFTO0tBQ3pCLENBQUM7SUFFRixLQUFLLENBQUMsR0FBRztRQUNQLE1BQU0sTUFBTSxHQUFHLFNBQVMsRUFBRSxDQUFDO1FBRTNCLElBQUksVUFBVSxFQUFFLEVBQUUsQ0FBQztZQUNqQiw2Q0FBNkM7WUFDN0MsTUFBTSxVQUFVLEdBQUc7Z0JBQ2pCLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVztnQkFDL0IsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO2dCQUN2QixhQUFhLEVBQUUsTUFBTSxDQUFDLGFBQWE7Z0JBQ25DLFlBQVksRUFBRSxNQUFNLENBQUMsWUFBWTtnQkFDakMsU0FBUyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTTtnQkFDMUIsY0FBYyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsV0FBVztnQkFDcEMsVUFBVSxFQUFFLGFBQWEsRUFBRTthQUM1QixDQUFDO1lBQ0YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ2pCLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBRXhCLE1BQU0sYUFBYSxHQUEyQjtZQUM1QyxXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVcsS0FBSyxNQUFNO2dCQUN4QyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDO2dCQUNwQyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDO1lBQ3RDLFVBQVUsRUFBRSxNQUFNLENBQUMsT0FBTztZQUMxQixlQUFlLEVBQUUsTUFBTSxDQUFDLGFBQWE7WUFDckMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO1lBQ2xGLFNBQVMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQztZQUMvRSxjQUFjLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUM7U0FDMUYsQ0FBQztRQUVGLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUV4QixPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDZCxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzdELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCYXNlQ29tbWFuZCB9IGZyb20gXCIuLi8uLi9saWIvYmFzZS1jb21tYW5kLmpzXCI7XG5pbXBvcnQge1xuICBnZXRDb25maWcsXG4gIGdldENvbmZpZ1BhdGgsXG4gIHR5cGUgU2VuZGx5Q29uZmlnLFxufSBmcm9tIFwiLi4vLi4vbGliL2NvbmZpZy5qc1wiO1xuaW1wb3J0IHsgY29sb3JzLCBrZXlWYWx1ZSwganNvbiwgaXNKc29uTW9kZSwgaGVhZGVyIH0gZnJvbSBcIi4uLy4uL2xpYi9vdXRwdXQuanNcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ29uZmlnTGlzdCBleHRlbmRzIEJhc2VDb21tYW5kIHtcbiAgc3RhdGljIGRlc2NyaXB0aW9uID0gXCJMaXN0IGFsbCBjb25maWd1cmF0aW9uIHZhbHVlc1wiO1xuXG4gIHN0YXRpYyBleGFtcGxlcyA9IFtcbiAgICBcIjwlPSBjb25maWcuYmluICU+IGNvbmZpZyBsaXN0XCIsXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiBjb25maWcgbGlzdCAtLWpzb25cIixcbiAgXTtcblxuICBzdGF0aWMgZmxhZ3MgPSB7XG4gICAgLi4uQmFzZUNvbW1hbmQuYmFzZUZsYWdzLFxuICB9O1xuXG4gIGFzeW5jIHJ1bigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjb25maWcgPSBnZXRDb25maWcoKTtcblxuICAgIGlmIChpc0pzb25Nb2RlKCkpIHtcbiAgICAgIC8vIERvbid0IGV4cG9zZSBzZW5zaXRpdmUgZGF0YSBpbiBKU09OIG91dHB1dFxuICAgICAgY29uc3Qgc2FmZUNvbmZpZyA9IHtcbiAgICAgICAgZW52aXJvbm1lbnQ6IGNvbmZpZy5lbnZpcm9ubWVudCxcbiAgICAgICAgYmFzZVVybDogY29uZmlnLmJhc2VVcmwsXG4gICAgICAgIGRlZmF1bHRGb3JtYXQ6IGNvbmZpZy5kZWZhdWx0Rm9ybWF0LFxuICAgICAgICBjb2xvckVuYWJsZWQ6IGNvbmZpZy5jb2xvckVuYWJsZWQsXG4gICAgICAgIGhhc0FwaUtleTogISFjb25maWcuYXBpS2V5LFxuICAgICAgICBoYXNBY2Nlc3NUb2tlbjogISFjb25maWcuYWNjZXNzVG9rZW4sXG4gICAgICAgIGNvbmZpZ1BhdGg6IGdldENvbmZpZ1BhdGgoKSxcbiAgICAgIH07XG4gICAgICBqc29uKHNhZmVDb25maWcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGhlYWRlcihcIkNvbmZpZ3VyYXRpb25cIik7XG5cbiAgICBjb25zdCBkaXNwbGF5Q29uZmlnOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgICAgRW52aXJvbm1lbnQ6IGNvbmZpZy5lbnZpcm9ubWVudCA9PT0gXCJsaXZlXCJcbiAgICAgICAgPyBjb2xvcnMuc3VjY2Vzcyhjb25maWcuZW52aXJvbm1lbnQpXG4gICAgICAgIDogY29sb3JzLndhcm5pbmcoY29uZmlnLmVudmlyb25tZW50KSxcbiAgICAgIFwiQmFzZSBVUkxcIjogY29uZmlnLmJhc2VVcmwsXG4gICAgICBcIk91dHB1dCBGb3JtYXRcIjogY29uZmlnLmRlZmF1bHRGb3JtYXQsXG4gICAgICBcIkNvbG9yc1wiOiBjb25maWcuY29sb3JFbmFibGVkID8gY29sb3JzLnN1Y2Nlc3MoXCJlbmFibGVkXCIpIDogY29sb3JzLmRpbShcImRpc2FibGVkXCIpLFxuICAgICAgXCJBUEkgS2V5XCI6IGNvbmZpZy5hcGlLZXkgPyBjb2xvcnMuc3VjY2VzcyhcImNvbmZpZ3VyZWRcIikgOiBjb2xvcnMuZGltKFwibm90IHNldFwiKSxcbiAgICAgIFwiQWNjZXNzIFRva2VuXCI6IGNvbmZpZy5hY2Nlc3NUb2tlbiA/IGNvbG9ycy5zdWNjZXNzKFwiY29uZmlndXJlZFwiKSA6IGNvbG9ycy5kaW0oXCJub3Qgc2V0XCIpLFxuICAgIH07XG5cbiAgICBrZXlWYWx1ZShkaXNwbGF5Q29uZmlnKTtcblxuICAgIGNvbnNvbGUubG9nKCk7XG4gICAgY29uc29sZS5sb2coY29sb3JzLmRpbShgQ29uZmlnIGZpbGU6ICR7Z2V0Q29uZmlnUGF0aCgpfWApKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from "../../lib/base-command.js";
2
+ export default class ConfigSet extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ key: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
7
+ value: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
8
+ };
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
+ run(): Promise<void>;
14
+ }
@@ -0,0 +1,67 @@
1
+ import { Args } from "@oclif/core";
2
+ import { BaseCommand } from "../../lib/base-command.js";
3
+ import { setConfig } from "../../lib/config.js";
4
+ import { success, error, colors } from "../../lib/output.js";
5
+ const ALLOWED_KEYS = [
6
+ "environment",
7
+ "baseUrl",
8
+ "defaultFormat",
9
+ "colorEnabled",
10
+ ];
11
+ export default class ConfigSet extends BaseCommand {
12
+ static description = "Set a configuration value";
13
+ static examples = [
14
+ "<%= config.bin %> config set environment live",
15
+ "<%= config.bin %> config set defaultFormat json",
16
+ "<%= config.bin %> config set baseUrl https://api.sendly.live",
17
+ ];
18
+ static args = {
19
+ key: Args.string({
20
+ description: "Configuration key",
21
+ required: true,
22
+ options: ALLOWED_KEYS,
23
+ }),
24
+ value: Args.string({
25
+ description: "Configuration value",
26
+ required: true,
27
+ }),
28
+ };
29
+ static flags = {
30
+ ...BaseCommand.baseFlags,
31
+ };
32
+ async run() {
33
+ const { args } = await this.parse(ConfigSet);
34
+ const key = args.key;
35
+ // Validate and transform value
36
+ let value = args.value;
37
+ switch (key) {
38
+ case "environment":
39
+ if (!["test", "live"].includes(value)) {
40
+ error("Invalid environment. Use 'test' or 'live'");
41
+ this.exit(1);
42
+ }
43
+ break;
44
+ case "defaultFormat":
45
+ if (!["human", "json"].includes(value)) {
46
+ error("Invalid format. Use 'human' or 'json'");
47
+ this.exit(1);
48
+ }
49
+ break;
50
+ case "colorEnabled":
51
+ value = value === "true" || value === "1";
52
+ break;
53
+ case "baseUrl":
54
+ try {
55
+ new URL(value);
56
+ }
57
+ catch {
58
+ error("Invalid URL format");
59
+ this.exit(1);
60
+ }
61
+ break;
62
+ }
63
+ setConfig(key, value);
64
+ success(`Set ${colors.code(key)} = ${colors.primary(String(value))}`);
65
+ }
66
+ }
67
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2NvbmZpZy9zZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNuQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFNBQVMsRUFBcUIsTUFBTSxxQkFBcUIsQ0FBQztBQUNuRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUU3RCxNQUFNLFlBQVksR0FBMkI7SUFDM0MsYUFBYTtJQUNiLFNBQVM7SUFDVCxlQUFlO0lBQ2YsY0FBYztDQUNmLENBQUM7QUFFRixNQUFNLENBQUMsT0FBTyxPQUFPLFNBQVUsU0FBUSxXQUFXO0lBQ2hELE1BQU0sQ0FBQyxXQUFXLEdBQUcsMkJBQTJCLENBQUM7SUFFakQsTUFBTSxDQUFDLFFBQVEsR0FBRztRQUNoQiwrQ0FBK0M7UUFDL0MsaURBQWlEO1FBQ2pELDhEQUE4RDtLQUMvRCxDQUFDO0lBRUYsTUFBTSxDQUFDLElBQUksR0FBRztRQUNaLEdBQUcsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQ2YsV0FBVyxFQUFFLG1CQUFtQjtZQUNoQyxRQUFRLEVBQUUsSUFBSTtZQUNkLE9BQU8sRUFBRSxZQUF3QjtTQUNsQyxDQUFDO1FBQ0YsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUM7WUFDakIsV0FBVyxFQUFFLHFCQUFxQjtZQUNsQyxRQUFRLEVBQUUsSUFBSTtTQUNmLENBQUM7S0FDSCxDQUFDO0lBRUYsTUFBTSxDQUFDLEtBQUssR0FBRztRQUNiLEdBQUcsV0FBVyxDQUFDLFNBQVM7S0FDekIsQ0FBQztJQUVGLEtBQUssQ0FBQyxHQUFHO1FBQ1AsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUU3QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBeUIsQ0FBQztRQUUzQywrQkFBK0I7UUFDL0IsSUFBSSxLQUFLLEdBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUU1QixRQUFRLEdBQUcsRUFBRSxDQUFDO1lBQ1osS0FBSyxhQUFhO2dCQUNoQixJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7b0JBQ3RDLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO29CQUNuRCxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNmLENBQUM7Z0JBQ0QsTUFBTTtZQUNSLEtBQUssZUFBZTtnQkFDbEIsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO29CQUN2QyxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztvQkFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDZixDQUFDO2dCQUNELE1BQU07WUFDUixLQUFLLGNBQWM7Z0JBQ2pCLEtBQUssR0FBRyxLQUFLLEtBQUssTUFBTSxJQUFJLEtBQUssS0FBSyxHQUFHLENBQUM7Z0JBQzFDLE1BQU07WUFDUixLQUFLLFNBQVM7Z0JBQ1osSUFBSSxDQUFDO29CQUNILElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNqQixDQUFDO2dCQUFDLE1BQU0sQ0FBQztvQkFDUCxLQUFLLENBQUMsb0JBQW9CLENBQUMsQ0FBQztvQkFDNUIsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDZixDQUFDO2dCQUNELE1BQU07UUFDVixDQUFDO1FBRUQsU0FBUyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN0QixPQUFPLENBQUMsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3hFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBcmdzIH0gZnJvbSBcIkBvY2xpZi9jb3JlXCI7XG5pbXBvcnQgeyBCYXNlQ29tbWFuZCB9IGZyb20gXCIuLi8uLi9saWIvYmFzZS1jb21tYW5kLmpzXCI7XG5pbXBvcnQgeyBzZXRDb25maWcsIHR5cGUgU2VuZGx5Q29uZmlnIH0gZnJvbSBcIi4uLy4uL2xpYi9jb25maWcuanNcIjtcbmltcG9ydCB7IHN1Y2Nlc3MsIGVycm9yLCBjb2xvcnMgfSBmcm9tIFwiLi4vLi4vbGliL291dHB1dC5qc1wiO1xuXG5jb25zdCBBTExPV0VEX0tFWVM6IChrZXlvZiBTZW5kbHlDb25maWcpW10gPSBbXG4gIFwiZW52aXJvbm1lbnRcIixcbiAgXCJiYXNlVXJsXCIsXG4gIFwiZGVmYXVsdEZvcm1hdFwiLFxuICBcImNvbG9yRW5hYmxlZFwiLFxuXTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ29uZmlnU2V0IGV4dGVuZHMgQmFzZUNvbW1hbmQge1xuICBzdGF0aWMgZGVzY3JpcHRpb24gPSBcIlNldCBhIGNvbmZpZ3VyYXRpb24gdmFsdWVcIjtcblxuICBzdGF0aWMgZXhhbXBsZXMgPSBbXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiBjb25maWcgc2V0IGVudmlyb25tZW50IGxpdmVcIixcbiAgICBcIjwlPSBjb25maWcuYmluICU+IGNvbmZpZyBzZXQgZGVmYXVsdEZvcm1hdCBqc29uXCIsXG4gICAgXCI8JT0gY29uZmlnLmJpbiAlPiBjb25maWcgc2V0IGJhc2VVcmwgaHR0cHM6Ly9hcGkuc2VuZGx5LmxpdmVcIixcbiAgXTtcblxuICBzdGF0aWMgYXJncyA9IHtcbiAgICBrZXk6IEFyZ3Muc3RyaW5nKHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkNvbmZpZ3VyYXRpb24ga2V5XCIsXG4gICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgIG9wdGlvbnM6IEFMTE9XRURfS0VZUyBhcyBzdHJpbmdbXSxcbiAgICB9KSxcbiAgICB2YWx1ZTogQXJncy5zdHJpbmcoe1xuICAgICAgZGVzY3JpcHRpb246IFwiQ29uZmlndXJhdGlvbiB2YWx1ZVwiLFxuICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgfSksXG4gIH07XG5cbiAgc3RhdGljIGZsYWdzID0ge1xuICAgIC4uLkJhc2VDb21tYW5kLmJhc2VGbGFncyxcbiAgfTtcblxuICBhc3luYyBydW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBhcmdzIH0gPSBhd2FpdCB0aGlzLnBhcnNlKENvbmZpZ1NldCk7XG5cbiAgICBjb25zdCBrZXkgPSBhcmdzLmtleSBhcyBrZXlvZiBTZW5kbHlDb25maWc7XG5cbiAgICAvLyBWYWxpZGF0ZSBhbmQgdHJhbnNmb3JtIHZhbHVlXG4gICAgbGV0IHZhbHVlOiBhbnkgPSBhcmdzLnZhbHVlO1xuXG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgIGNhc2UgXCJlbnZpcm9ubWVudFwiOlxuICAgICAgICBpZiAoIVtcInRlc3RcIiwgXCJsaXZlXCJdLmluY2x1ZGVzKHZhbHVlKSkge1xuICAgICAgICAgIGVycm9yKFwiSW52YWxpZCBlbnZpcm9ubWVudC4gVXNlICd0ZXN0JyBvciAnbGl2ZSdcIik7XG4gICAgICAgICAgdGhpcy5leGl0KDEpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcImRlZmF1bHRGb3JtYXRcIjpcbiAgICAgICAgaWYgKCFbXCJodW1hblwiLCBcImpzb25cIl0uaW5jbHVkZXModmFsdWUpKSB7XG4gICAgICAgICAgZXJyb3IoXCJJbnZhbGlkIGZvcm1hdC4gVXNlICdodW1hbicgb3IgJ2pzb24nXCIpO1xuICAgICAgICAgIHRoaXMuZXhpdCgxKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJjb2xvckVuYWJsZWRcIjpcbiAgICAgICAgdmFsdWUgPSB2YWx1ZSA9PT0gXCJ0cnVlXCIgfHwgdmFsdWUgPT09IFwiMVwiO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJiYXNlVXJsXCI6XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgbmV3IFVSTCh2YWx1ZSk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIGVycm9yKFwiSW52YWxpZCBVUkwgZm9ybWF0XCIpO1xuICAgICAgICAgIHRoaXMuZXhpdCgxKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBzZXRDb25maWcoa2V5LCB2YWx1ZSk7XG4gICAgc3VjY2VzcyhgU2V0ICR7Y29sb3JzLmNvZGUoa2V5KX0gPSAke2NvbG9ycy5wcmltYXJ5KFN0cmluZyh2YWx1ZSkpfWApO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,10 @@
1
+ import { AuthenticatedCommand } from "../../lib/base-command.js";
2
+ export default class CreditsBalance 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
+ }
@@ -0,0 +1,38 @@
1
+ import { AuthenticatedCommand } from "../../lib/base-command.js";
2
+ import { apiClient } from "../../lib/api-client.js";
3
+ import { json, keyValue, colors, header, isJsonMode, } from "../../lib/output.js";
4
+ export default class CreditsBalance extends AuthenticatedCommand {
5
+ static description = "Check your credit balance";
6
+ static examples = [
7
+ "<%= config.bin %> credits balance",
8
+ "<%= config.bin %> credits balance --json",
9
+ ];
10
+ static flags = {
11
+ ...AuthenticatedCommand.baseFlags,
12
+ };
13
+ async run() {
14
+ const credits = await apiClient.get("/api/credits");
15
+ if (isJsonMode()) {
16
+ json(credits);
17
+ return;
18
+ }
19
+ header("Credit Balance");
20
+ const availableCredits = credits.balance - (credits.reservedBalance || 0);
21
+ keyValue({
22
+ Available: colors.primary(`${availableCredits.toLocaleString()} credits`),
23
+ Reserved: credits.reservedBalance
24
+ ? colors.warning(`${credits.reservedBalance.toLocaleString()} credits`)
25
+ : colors.dim("0 credits"),
26
+ "Total Balance": `${credits.balance.toLocaleString()} credits`,
27
+ "Lifetime Credits": colors.dim(`${credits.lifetimeCredits.toLocaleString()} credits`),
28
+ });
29
+ console.log();
30
+ // Show approximate message capacity
31
+ const domesticMessages = Math.floor(availableCredits / 1);
32
+ const internationalMessages = Math.floor(availableCredits / 8);
33
+ console.log(colors.dim("Estimated capacity:"));
34
+ console.log(` ${colors.dim("US/Canada:")} ~${domesticMessages.toLocaleString()} messages`);
35
+ console.log(` ${colors.dim("International:")} ~${internationalMessages.toLocaleString()} messages`);
36
+ }
37
+ }
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFsYW5jZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9jcmVkaXRzL2JhbGFuY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDakUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BELE9BQU8sRUFFTCxJQUFJLEVBQ0osUUFBUSxFQUNSLE1BQU0sRUFDTixNQUFNLEVBQ04sVUFBVSxHQUNYLE1BQU0scUJBQXFCLENBQUM7QUFRN0IsTUFBTSxDQUFDLE9BQU8sT0FBTyxjQUFlLFNBQVEsb0JBQW9CO0lBQzlELE1BQU0sQ0FBQyxXQUFXLEdBQUcsMkJBQTJCLENBQUM7SUFFakQsTUFBTSxDQUFDLFFBQVEsR0FBRztRQUNoQixtQ0FBbUM7UUFDbkMsMENBQTBDO0tBQzNDLENBQUM7SUFFRixNQUFNLENBQUMsS0FBSyxHQUFHO1FBQ2IsR0FBRyxvQkFBb0IsQ0FBQyxTQUFTO0tBQ2xDLENBQUM7SUFFRixLQUFLLENBQUMsR0FBRztRQUNQLE1BQU0sT0FBTyxHQUFHLE1BQU0sU0FBUyxDQUFDLEdBQUcsQ0FBa0IsY0FBYyxDQUFDLENBQUM7UUFFckUsSUFBSSxVQUFVLEVBQUUsRUFBRSxDQUFDO1lBQ2pCLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNkLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFFekIsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLGVBQWUsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUUxRSxRQUFRLENBQUM7WUFDUCxTQUFTLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLGdCQUFnQixDQUFDLGNBQWMsRUFBRSxVQUFVLENBQUM7WUFDekUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxlQUFlO2dCQUMvQixDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsY0FBYyxFQUFFLFVBQVUsQ0FBQztnQkFDdkUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDO1lBQzNCLGVBQWUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLFVBQVU7WUFDOUQsa0JBQWtCLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsY0FBYyxFQUFFLFVBQVUsQ0FBQztTQUN0RixDQUFDLENBQUM7UUFFSCxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFZCxvQ0FBb0M7UUFDcEMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzFELE1BQU0scUJBQXFCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUUvRCxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDO1FBQy9DLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxNQUFNLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxLQUFLLGdCQUFnQixDQUFDLGNBQWMsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUM1RixPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssTUFBTSxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLHFCQUFxQixDQUFDLGNBQWMsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUN2RyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXV0aGVudGljYXRlZENvbW1hbmQgfSBmcm9tIFwiLi4vLi4vbGliL2Jhc2UtY29tbWFuZC5qc1wiO1xuaW1wb3J0IHsgYXBpQ2xpZW50IH0gZnJvbSBcIi4uLy4uL2xpYi9hcGktY2xpZW50LmpzXCI7XG5pbXBvcnQge1xuICBzdWNjZXNzLFxuICBqc29uLFxuICBrZXlWYWx1ZSxcbiAgY29sb3JzLFxuICBoZWFkZXIsXG4gIGlzSnNvbk1vZGUsXG59IGZyb20gXCIuLi8uLi9saWIvb3V0cHV0LmpzXCI7XG5cbmludGVyZmFjZSBDcmVkaXRzUmVzcG9uc2Uge1xuICBiYWxhbmNlOiBudW1iZXI7XG4gIGxpZmV0aW1lQ3JlZGl0czogbnVtYmVyO1xuICByZXNlcnZlZEJhbGFuY2U6IG51bWJlcjtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ3JlZGl0c0JhbGFuY2UgZXh0ZW5kcyBBdXRoZW50aWNhdGVkQ29tbWFuZCB7XG4gIHN0YXRpYyBkZXNjcmlwdGlvbiA9IFwiQ2hlY2sgeW91ciBjcmVkaXQgYmFsYW5jZVwiO1xuXG4gIHN0YXRpYyBleGFtcGxlcyA9IFtcbiAgICBcIjwlPSBjb25maWcuYmluICU+IGNyZWRpdHMgYmFsYW5jZVwiLFxuICAgIFwiPCU9IGNvbmZpZy5iaW4gJT4gY3JlZGl0cyBiYWxhbmNlIC0tanNvblwiLFxuICBdO1xuXG4gIHN0YXRpYyBmbGFncyA9IHtcbiAgICAuLi5BdXRoZW50aWNhdGVkQ29tbWFuZC5iYXNlRmxhZ3MsXG4gIH07XG5cbiAgYXN5bmMgcnVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNyZWRpdHMgPSBhd2FpdCBhcGlDbGllbnQuZ2V0PENyZWRpdHNSZXNwb25zZT4oXCIvYXBpL2NyZWRpdHNcIik7XG5cbiAgICBpZiAoaXNKc29uTW9kZSgpKSB7XG4gICAgICBqc29uKGNyZWRpdHMpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGhlYWRlcihcIkNyZWRpdCBCYWxhbmNlXCIpO1xuXG4gICAgY29uc3QgYXZhaWxhYmxlQ3JlZGl0cyA9IGNyZWRpdHMuYmFsYW5jZSAtIChjcmVkaXRzLnJlc2VydmVkQmFsYW5jZSB8fCAwKTtcblxuICAgIGtleVZhbHVlKHtcbiAgICAgIEF2YWlsYWJsZTogY29sb3JzLnByaW1hcnkoYCR7YXZhaWxhYmxlQ3JlZGl0cy50b0xvY2FsZVN0cmluZygpfSBjcmVkaXRzYCksXG4gICAgICBSZXNlcnZlZDogY3JlZGl0cy5yZXNlcnZlZEJhbGFuY2VcbiAgICAgICAgPyBjb2xvcnMud2FybmluZyhgJHtjcmVkaXRzLnJlc2VydmVkQmFsYW5jZS50b0xvY2FsZVN0cmluZygpfSBjcmVkaXRzYClcbiAgICAgICAgOiBjb2xvcnMuZGltKFwiMCBjcmVkaXRzXCIpLFxuICAgICAgXCJUb3RhbCBCYWxhbmNlXCI6IGAke2NyZWRpdHMuYmFsYW5jZS50b0xvY2FsZVN0cmluZygpfSBjcmVkaXRzYCxcbiAgICAgIFwiTGlmZXRpbWUgQ3JlZGl0c1wiOiBjb2xvcnMuZGltKGAke2NyZWRpdHMubGlmZXRpbWVDcmVkaXRzLnRvTG9jYWxlU3RyaW5nKCl9IGNyZWRpdHNgKSxcbiAgICB9KTtcblxuICAgIGNvbnNvbGUubG9nKCk7XG5cbiAgICAvLyBTaG93IGFwcHJveGltYXRlIG1lc3NhZ2UgY2FwYWNpdHlcbiAgICBjb25zdCBkb21lc3RpY01lc3NhZ2VzID0gTWF0aC5mbG9vcihhdmFpbGFibGVDcmVkaXRzIC8gMSk7XG4gICAgY29uc3QgaW50ZXJuYXRpb25hbE1lc3NhZ2VzID0gTWF0aC5mbG9vcihhdmFpbGFibGVDcmVkaXRzIC8gOCk7XG5cbiAgICBjb25zb2xlLmxvZyhjb2xvcnMuZGltKFwiRXN0aW1hdGVkIGNhcGFjaXR5OlwiKSk7XG4gICAgY29uc29sZS5sb2coYCAgJHtjb2xvcnMuZGltKFwiVVMvQ2FuYWRhOlwiKX0gfiR7ZG9tZXN0aWNNZXNzYWdlcy50b0xvY2FsZVN0cmluZygpfSBtZXNzYWdlc2ApO1xuICAgIGNvbnNvbGUubG9nKGAgICR7Y29sb3JzLmRpbShcIkludGVybmF0aW9uYWw6XCIpfSB+JHtpbnRlcm5hdGlvbmFsTWVzc2FnZXMudG9Mb2NhbGVTdHJpbmcoKX0gbWVzc2FnZXNgKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,11 @@
1
+ import { AuthenticatedCommand } from "../../lib/base-command.js";
2
+ export default class CreditsHistory extends AuthenticatedCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ limit: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ json: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
8
+ quiet: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
9
+ };
10
+ run(): Promise<void>;
11
+ }