@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
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,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
|
+
}
|