@cakemail-org/cakemail-cli 1.5.0 → 2.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/.claude/settings.local.json +12 -0
- package/.env.example +40 -0
- package/.env.test.example +45 -0
- package/CHANGELOG.md +1031 -0
- package/README.md +319 -15
- package/audit-formats.js +128 -0
- package/cakemail.rb +20 -0
- package/dist/cli.js +27 -10
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +16 -6
- package/dist/client.js.map +1 -1
- package/dist/commands/account.js +1 -1
- package/dist/commands/account.js.map +1 -1
- package/dist/commands/attributes.js +1 -1
- package/dist/commands/attributes.js.map +1 -1
- package/dist/commands/campaigns.d.ts.map +1 -1
- package/dist/commands/campaigns.js +103 -8
- package/dist/commands/campaigns.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +63 -4
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/contacts.d.ts.map +1 -1
- package/dist/commands/contacts.js +91 -12
- package/dist/commands/contacts.js.map +1 -1
- package/dist/commands/emails.js +1 -1
- package/dist/commands/emails.js.map +1 -1
- package/dist/commands/interests.d.ts +5 -0
- package/dist/commands/interests.d.ts.map +1 -0
- package/dist/commands/interests.js +172 -0
- package/dist/commands/interests.js.map +1 -0
- package/dist/commands/lists.d.ts.map +1 -1
- package/dist/commands/lists.js +6 -8
- package/dist/commands/lists.js.map +1 -1
- package/dist/commands/logs.d.ts +5 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +237 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/reports.js +1 -1
- package/dist/commands/reports.js.map +1 -1
- package/dist/commands/segments.js +1 -1
- package/dist/commands/segments.js.map +1 -1
- package/dist/commands/senders.d.ts.map +1 -1
- package/dist/commands/senders.js +11 -8
- package/dist/commands/senders.js.map +1 -1
- package/dist/commands/suppressed.js +1 -1
- package/dist/commands/suppressed.js.map +1 -1
- package/dist/commands/tags.d.ts +5 -0
- package/dist/commands/tags.d.ts.map +1 -0
- package/dist/commands/tags.js +124 -0
- package/dist/commands/tags.js.map +1 -0
- package/dist/commands/templates.js +1 -1
- package/dist/commands/templates.js.map +1 -1
- package/dist/commands/transactional-templates.d.ts +5 -0
- package/dist/commands/transactional-templates.d.ts.map +1 -0
- package/dist/commands/transactional-templates.js +354 -0
- package/dist/commands/transactional-templates.js.map +1 -0
- package/dist/commands/webhooks.js +1 -1
- package/dist/commands/webhooks.js.map +1 -1
- package/dist/utils/auth.d.ts +8 -1
- package/dist/utils/auth.d.ts.map +1 -1
- package/dist/utils/auth.js +39 -11
- package/dist/utils/auth.js.map +1 -1
- package/dist/utils/config-file.d.ts +7 -0
- package/dist/utils/config-file.d.ts.map +1 -1
- package/dist/utils/config-file.js +15 -0
- package/dist/utils/config-file.js.map +1 -1
- package/dist/utils/config.d.ts +2 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +12 -4
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/errors.js +1 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/list-defaults.d.ts +33 -0
- package/dist/utils/list-defaults.d.ts.map +1 -0
- package/dist/utils/list-defaults.js +52 -0
- package/dist/utils/list-defaults.js.map +1 -0
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +36 -13
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/progress.d.ts.map +1 -1
- package/dist/utils/progress.js +32 -4
- package/dist/utils/progress.js.map +1 -1
- package/dist/utils/spinner.d.ts +17 -0
- package/dist/utils/spinner.d.ts.map +1 -0
- package/dist/utils/spinner.js +43 -0
- package/dist/utils/spinner.js.map +1 -0
- package/docs/DOCUMENTATION-STANDARD.md +1068 -0
- package/docs/README.md +161 -0
- package/docs/developer/ARCHITECTURE.md +516 -0
- package/docs/developer/AUTH.md +204 -0
- package/docs/developer/CONTRIBUTING.md +227 -0
- package/docs/developer/DOCUMENTATION_SUMMARY.md +346 -0
- package/docs/developer/PROJECT_INDEX.md +365 -0
- package/docs/planning/API_COVERAGE.md +1045 -0
- package/docs/planning/BACKLOG.md +1159 -0
- package/docs/planning/PROFILE_SYSTEM_TASKS.md +287 -0
- package/docs/planning/UX_IMPLEMENTATION_PLAN.md +691 -0
- package/docs/planning/archive/RELEASE_CHECKLIST_v1.3.0.md +332 -0
- package/docs/planning/archive/RELEASE_v1.3.0.md +428 -0
- package/docs/planning/archive/cakemail-cli-ux-improvements.md +438 -0
- package/docs/planning/cakemail-profile-system-plan.md +1121 -0
- package/docs/testing/AI_USER_SIMULATION_DESIGN.md +1342 -0
- package/docs/testing/KENOGAMI_BIDIRECTIONAL_FLOW.md +1517 -0
- package/docs/testing/KENOGAMI_TRUTH_RECONCILIATION_SYSTEM.md +1369 -0
- package/docs/user-manual/.obsidian/app.json +1 -0
- package/docs/user-manual/.obsidian/appearance.json +1 -0
- package/docs/user-manual/.obsidian/core-plugins.json +33 -0
- package/docs/user-manual/.obsidian/workspace.json +167 -0
- package/docs/user-manual/01-getting-started/01-installation.md +214 -0
- package/docs/user-manual/01-getting-started/02-quick-start.md +432 -0
- package/docs/user-manual/01-getting-started/03-authentication.md +448 -0
- package/docs/user-manual/01-getting-started/04-configuration.md +430 -0
- package/docs/user-manual/01-getting-started/05-output-formats.md +447 -0
- package/docs/user-manual/02-core-concepts/01-accounts.md +514 -0
- package/docs/user-manual/02-core-concepts/02-profile-system.md +771 -0
- package/docs/user-manual/02-core-concepts/03-smart-defaults.md +485 -0
- package/docs/user-manual/02-core-concepts/04-authentication-methods.md +435 -0
- package/docs/user-manual/02-core-concepts/05-pagination-filtering.md +600 -0
- package/docs/user-manual/02-core-concepts/06-error-handling.md +718 -0
- package/docs/user-manual/02-core-concepts/07-api-coverage.md +483 -0
- package/docs/user-manual/03-email-operations/01-senders.md +490 -0
- package/docs/user-manual/03-email-operations/02-templates.md +444 -0
- package/docs/user-manual/03-email-operations/03-transactional-emails.md +706 -0
- package/docs/user-manual/03-email-operations/04-email-tracking.md +407 -0
- package/docs/user-manual/04-campaign-management/01-campaigns-basics.md +394 -0
- package/docs/user-manual/04-campaign-management/02-campaign-scheduling.md +630 -0
- package/docs/user-manual/04-campaign-management/03-campaign-testing.md +997 -0
- package/docs/user-manual/04-campaign-management/04-campaign-lifecycle.md +709 -0
- package/docs/user-manual/04-campaign-management/05-campaign-links.md +934 -0
- package/docs/user-manual/05-contact-management/01-lists.md +836 -0
- package/docs/user-manual/05-contact-management/02-contacts.md +1035 -0
- package/docs/user-manual/05-contact-management/03-custom-attributes.md +788 -0
- package/docs/user-manual/05-contact-management/04-segments.md +1028 -0
- package/docs/user-manual/05-contact-management/05-contact-import-export.md +1031 -0
- package/docs/user-manual/06-analytics-reporting/01-campaign-analytics.md +867 -0
- package/docs/user-manual/06-analytics-reporting/02-account-reports.md +227 -0
- package/docs/user-manual/07-integrations/01-webhooks-integration.md +259 -0
- package/docs/user-manual/07-integrations/02-automation.md +326 -0
- package/docs/user-manual/08-advanced-usage/01-scripting-patterns.md +672 -0
- package/docs/user-manual/08-advanced-usage/02-bulk-operations.md +932 -0
- package/docs/user-manual/08-advanced-usage/03-ci-cd-integration.md +892 -0
- package/docs/user-manual/08-advanced-usage/04-performance-optimization.md +766 -0
- package/docs/user-manual/09-command-reference/01-config.md +776 -0
- package/docs/user-manual/09-command-reference/02-account.md +652 -0
- package/docs/user-manual/09-command-reference/03-lists.md +958 -0
- package/docs/user-manual/09-command-reference/04-contacts.md +1408 -0
- package/docs/user-manual/09-command-reference/05-attributes.md +617 -0
- package/docs/user-manual/09-command-reference/06-segments.md +894 -0
- package/docs/user-manual/09-command-reference/07-senders.md +803 -0
- package/docs/user-manual/09-command-reference/08-templates.md +818 -0
- package/docs/user-manual/09-command-reference/09-campaigns.md +1250 -0
- package/docs/user-manual/09-command-reference/10-emails.md +807 -0
- package/docs/user-manual/09-command-reference/11-reports.md +1135 -0
- package/docs/user-manual/09-command-reference/12-webhooks.md +773 -0
- package/docs/user-manual/09-command-reference/13-suppressed.md +797 -0
- package/docs/user-manual/09-command-reference/14-interests.md +630 -0
- package/docs/user-manual/09-command-reference/15-tags.md +584 -0
- package/docs/user-manual/09-command-reference/16-logs.md +656 -0
- package/docs/user-manual/09-command-reference/17-transactional-templates.md +850 -0
- package/docs/user-manual/10-troubleshooting/01-common-errors.md +457 -0
- package/docs/user-manual/10-troubleshooting/02-authentication-issues.md +558 -0
- package/docs/user-manual/10-troubleshooting/03-connection-problems.md +634 -0
- package/docs/user-manual/10-troubleshooting/04-debugging.md +725 -0
- package/docs/user-manual/11-appendix/04-faq.md +484 -0
- package/docs/user-manual/11-appendix/05-glossary.md +250 -0
- package/docs/user-manual/README.md +0 -0
- package/package.json +13 -47
- package/src/cli.ts +125 -0
- package/src/client.ts +16 -0
- package/src/commands/account.ts +267 -0
- package/src/commands/accounts.ts +78 -0
- package/src/commands/actions.ts +249 -0
- package/src/commands/attributes.ts +139 -0
- package/src/commands/campaign-blueprints.ts +106 -0
- package/src/commands/campaigns.ts +469 -0
- package/src/commands/config.ts +77 -0
- package/src/commands/contacts.ts +612 -0
- package/src/commands/custom-attributes.ts +127 -0
- package/src/commands/dkims.ts +117 -0
- package/src/commands/domains.ts +82 -0
- package/src/commands/email-apis.ts +569 -0
- package/src/commands/emails.ts +197 -0
- package/src/commands/forms.ts +283 -0
- package/src/commands/interests.ts +155 -0
- package/src/commands/links.ts +38 -0
- package/src/commands/lists.ts +406 -0
- package/src/commands/logos.ts +71 -0
- package/src/commands/logs.ts +386 -0
- package/src/commands/reports.ts +306 -0
- package/src/commands/segments.ts +158 -0
- package/src/commands/senders.ts +204 -0
- package/src/commands/sub-accounts.ts +271 -0
- package/src/commands/suppressed-emails.ts +234 -0
- package/src/commands/suppressed.ts +198 -0
- package/src/commands/system-emails.ts +85 -0
- package/src/commands/tags.ts +146 -0
- package/src/commands/tasks.ts +116 -0
- package/src/commands/templates.ts +189 -0
- package/src/commands/tokens.ts +83 -0
- package/src/commands/transactional-emails.ts +374 -0
- package/src/commands/transactional-templates.ts +385 -0
- package/src/commands/users.ts +506 -0
- package/src/commands/webhooks.ts +172 -0
- package/src/commands/workflow-blueprints.ts +123 -0
- package/src/commands/workflows.ts +265 -0
- package/src/types/profile.ts +93 -0
- package/src/utils/auth.ts +272 -0
- package/src/utils/config-file.ts +96 -0
- package/src/utils/config.ts +134 -0
- package/src/utils/confirm.ts +32 -0
- package/src/utils/defaults.ts +99 -0
- package/src/utils/errors.ts +116 -0
- package/src/utils/interactive.ts +91 -0
- package/src/utils/list-defaults.ts +74 -0
- package/src/utils/output.ts +190 -0
- package/src/utils/progress.ts +320 -0
- package/src/utils/spinner.ts +22 -0
- package/tests/IMPLEMENTATION_STATUS.md +258 -0
- package/tests/PTY_SETUP.md +118 -0
- package/tests/PTY_TESTING_GUIDE.md +507 -0
- package/tests/README.md +244 -0
- package/tests/fixtures/api-responses/campaigns.json +34 -0
- package/tests/fixtures/test-config.json +13 -0
- package/tests/helpers/cli-runner.ts +128 -0
- package/tests/helpers/mock-server.ts +301 -0
- package/tests/helpers/pty-runner.ts +181 -0
- package/tests/integration/campaigns-real-api.test.ts +196 -0
- package/tests/integration/setup-integration.ts +50 -0
- package/tests/pty/campaigns.test.ts +241 -0
- package/tests/setup.ts +34 -0
- package/tsconfig.json +15 -0
- package/vitest.config.ts +28 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Authentication Guide
|
|
2
|
+
|
|
3
|
+
## How Cakemail API Authentication Works
|
|
4
|
+
|
|
5
|
+
Cakemail uses **OAuth 2.0 Password Grant** for authentication, not traditional API keys.
|
|
6
|
+
|
|
7
|
+
### Authentication Flow
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
1. User provides email + password
|
|
11
|
+
2. CLI sends POST /token with credentials (application/x-www-form-urlencoded)
|
|
12
|
+
3. API returns: { access_token, refresh_token, expires_in }
|
|
13
|
+
4. CLI uses access_token for subsequent requests (Bearer token)
|
|
14
|
+
5. When access_token expires (401), CLI uses refresh_token to get new access_token
|
|
15
|
+
6. If refresh fails, CLI re-authenticates with email/password
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Two Ways to Authenticate
|
|
19
|
+
|
|
20
|
+
#### Option 1: Email + Password (Recommended for CLI)
|
|
21
|
+
|
|
22
|
+
The CLI automatically handles token management:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
export CAKEMAIL_EMAIL=your@email.com
|
|
26
|
+
export CAKEMAIL_PASSWORD=your_password
|
|
27
|
+
cakemail campaigns list
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**What happens:**
|
|
31
|
+
1. CLI calls `POST /token` with email/password
|
|
32
|
+
2. Receives `access_token` and `refresh_token`
|
|
33
|
+
3. Stores tokens in memory (not persisted)
|
|
34
|
+
4. Uses `access_token` for all API requests
|
|
35
|
+
5. Auto-refreshes when token expires
|
|
36
|
+
|
|
37
|
+
#### Option 2: Pre-existing Access Token
|
|
38
|
+
|
|
39
|
+
If you already have an access token (from another OAuth2 flow):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
export CAKEMAIL_ACCESS_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
43
|
+
cakemail campaigns list
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Note:** This won't auto-refresh since there's no refresh token.
|
|
47
|
+
|
|
48
|
+
## OAuth2 Token Request Format
|
|
49
|
+
|
|
50
|
+
The `/token` endpoint requires `application/x-www-form-urlencoded` format:
|
|
51
|
+
|
|
52
|
+
### Get Initial Token (Password Grant)
|
|
53
|
+
```http
|
|
54
|
+
POST /token
|
|
55
|
+
Content-Type: application/x-www-form-urlencoded
|
|
56
|
+
|
|
57
|
+
grant_type=password&username=user@example.com&password=secret123
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Response:
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
64
|
+
"refresh_token": "def50200a1b2c3d4...",
|
|
65
|
+
"token_type": "bearer",
|
|
66
|
+
"expires_in": 3600
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Refresh Token
|
|
71
|
+
```http
|
|
72
|
+
POST /token
|
|
73
|
+
Content-Type: application/x-www-form-urlencoded
|
|
74
|
+
|
|
75
|
+
grant_type=refresh_token&refresh_token=def50200a1b2c3d4...
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Response:
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
82
|
+
"refresh_token": "def50200e5f6g7h8...",
|
|
83
|
+
"token_type": "bearer",
|
|
84
|
+
"expires_in": 3600
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Token Storage
|
|
89
|
+
|
|
90
|
+
**Currently:** Tokens are stored in memory only (not persisted to disk)
|
|
91
|
+
|
|
92
|
+
**Pros:**
|
|
93
|
+
- More secure (tokens don't persist after CLI exits)
|
|
94
|
+
- No file permission issues
|
|
95
|
+
|
|
96
|
+
**Cons:**
|
|
97
|
+
- Must re-authenticate on every CLI invocation
|
|
98
|
+
- Slightly slower first request
|
|
99
|
+
|
|
100
|
+
### Future: Token Persistence
|
|
101
|
+
|
|
102
|
+
Could store tokens in `~/.cakemail/credentials.json`:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"access_token": "...",
|
|
107
|
+
"refresh_token": "...",
|
|
108
|
+
"expires_at": "2025-10-08T20:00:00Z"
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
This would:
|
|
113
|
+
- Speed up CLI (no re-authentication)
|
|
114
|
+
- Reduce API calls
|
|
115
|
+
- Require secure file permissions (0600)
|
|
116
|
+
|
|
117
|
+
## Multi-Factor Authentication (MFA)
|
|
118
|
+
|
|
119
|
+
If account has MFA enabled, the `/token` endpoint returns:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"challenge": "mfa-challenge-id-123"
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The CLI would need to:
|
|
128
|
+
1. Detect the challenge response
|
|
129
|
+
2. Prompt user for MFA code
|
|
130
|
+
3. Call `POST /token/challenge` with code
|
|
131
|
+
|
|
132
|
+
**Current Status:** MFA not yet implemented in CLI
|
|
133
|
+
|
|
134
|
+
## Security Considerations
|
|
135
|
+
|
|
136
|
+
### ✅ Current Implementation
|
|
137
|
+
- Tokens stored in memory only
|
|
138
|
+
- HTTPS enforced for all requests
|
|
139
|
+
- Automatic token refresh
|
|
140
|
+
- No plaintext tokens in logs
|
|
141
|
+
|
|
142
|
+
### 🚧 Future Improvements
|
|
143
|
+
- Token persistence with encryption
|
|
144
|
+
- Token expiration checking before requests
|
|
145
|
+
- MFA support
|
|
146
|
+
- Token revocation on logout
|
|
147
|
+
- Secure credential storage (OS keychain)
|
|
148
|
+
|
|
149
|
+
## Environment Variables
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Primary authentication (auto OAuth2)
|
|
153
|
+
CAKEMAIL_EMAIL=your@email.com
|
|
154
|
+
CAKEMAIL_PASSWORD=your_password
|
|
155
|
+
|
|
156
|
+
# Alternative: Use existing token
|
|
157
|
+
CAKEMAIL_ACCESS_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
158
|
+
|
|
159
|
+
# Optional: Override API base URL
|
|
160
|
+
CAKEMAIL_API_BASE=https://api.cakemail.dev
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## CLI Flags
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Override credentials via CLI
|
|
167
|
+
cakemail --email user@example.com --password secret123 campaigns list
|
|
168
|
+
|
|
169
|
+
# Use access token
|
|
170
|
+
cakemail --access-token eyJhbGci... campaigns list
|
|
171
|
+
|
|
172
|
+
# Flags take precedence over environment variables
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Debugging Authentication
|
|
176
|
+
|
|
177
|
+
Enable verbose logging to see auth flow:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Check if credentials are loaded
|
|
181
|
+
cakemail --email test@example.com --password wrong_password campaigns list
|
|
182
|
+
# Error: Authentication failed: ...
|
|
183
|
+
|
|
184
|
+
# Success
|
|
185
|
+
cakemail --email user@example.com --password correct_password campaigns list
|
|
186
|
+
# (Makes POST /token, then GET /campaigns)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Comparison: API Keys vs OAuth2 Tokens
|
|
190
|
+
|
|
191
|
+
| Feature | Traditional API Keys | Cakemail OAuth2 Tokens |
|
|
192
|
+
|---------|---------------------|------------------------|
|
|
193
|
+
| **Format** | Long-lived static key | Short-lived JWT |
|
|
194
|
+
| **Expiration** | Never (or very long) | 1 hour (configurable) |
|
|
195
|
+
| **Refresh** | N/A | Yes, via refresh token |
|
|
196
|
+
| **Scopes** | Often global | user/admin/internal |
|
|
197
|
+
| **Revocation** | Manual | Automatic on refresh |
|
|
198
|
+
| **Security** | Lower (if leaked) | Higher (expires quickly) |
|
|
199
|
+
|
|
200
|
+
## Summary
|
|
201
|
+
|
|
202
|
+
**There are NO traditional API keys in Cakemail.** The `CAKEMAIL_ACCESS_TOKEN` env var refers to an OAuth2 access token obtained from the `/token` endpoint.
|
|
203
|
+
|
|
204
|
+
For CLI usage, **email + password** is the simplest approach - the CLI handles all token management automatically.
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# Contributing to Cakemail CLI
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to the Cakemail CLI! This document provides guidelines and instructions for contributing.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
- Node.js >= 18.0.0
|
|
10
|
+
- npm
|
|
11
|
+
- A Cakemail account for testing
|
|
12
|
+
|
|
13
|
+
### Development Setup
|
|
14
|
+
|
|
15
|
+
1. **Clone the repository**
|
|
16
|
+
```bash
|
|
17
|
+
git clone https://github.com/cakemail/cakemail-cli.git
|
|
18
|
+
cd cli
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
2. **Install dependencies**
|
|
22
|
+
```bash
|
|
23
|
+
npm install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
3. **Set up environment**
|
|
27
|
+
```bash
|
|
28
|
+
cp .env.example .env
|
|
29
|
+
# Edit .env with your test credentials
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
4. **Build the project**
|
|
33
|
+
```bash
|
|
34
|
+
npm run build
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
5. **Test locally**
|
|
38
|
+
```bash
|
|
39
|
+
npm start -- campaigns list
|
|
40
|
+
# or
|
|
41
|
+
node dist/cli.js campaigns list
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Development Workflow
|
|
45
|
+
|
|
46
|
+
### Making Changes
|
|
47
|
+
|
|
48
|
+
1. **Create a feature branch**
|
|
49
|
+
```bash
|
|
50
|
+
git checkout -b feature/your-feature-name
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
2. **Make your changes**
|
|
54
|
+
- Write clean, readable code
|
|
55
|
+
- Follow existing code style and patterns
|
|
56
|
+
- Add TypeScript types for all new code
|
|
57
|
+
|
|
58
|
+
3. **Build and test**
|
|
59
|
+
```bash
|
|
60
|
+
npm run build
|
|
61
|
+
npm start -- <command> <args>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
4. **Commit your changes**
|
|
65
|
+
```bash
|
|
66
|
+
git add .
|
|
67
|
+
git commit -m "feat: add your feature description"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Commit Message Guidelines
|
|
71
|
+
|
|
72
|
+
We follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
73
|
+
|
|
74
|
+
- `feat:` - New features
|
|
75
|
+
- `fix:` - Bug fixes
|
|
76
|
+
- `docs:` - Documentation changes
|
|
77
|
+
- `chore:` - Maintenance tasks
|
|
78
|
+
- `refactor:` - Code refactoring
|
|
79
|
+
- `test:` - Test additions or changes
|
|
80
|
+
|
|
81
|
+
Examples:
|
|
82
|
+
```
|
|
83
|
+
feat: add reports command for campaign analytics
|
|
84
|
+
fix: correct sender confirmation flow
|
|
85
|
+
docs: update README with new examples
|
|
86
|
+
chore: update dependencies to latest versions
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Code Guidelines
|
|
90
|
+
|
|
91
|
+
### TypeScript
|
|
92
|
+
|
|
93
|
+
- Use TypeScript for all code
|
|
94
|
+
- Provide types for all function parameters and return values
|
|
95
|
+
- Avoid `any` type when possible
|
|
96
|
+
|
|
97
|
+
### Code Style
|
|
98
|
+
|
|
99
|
+
- Use 2 spaces for indentation
|
|
100
|
+
- Use single quotes for strings
|
|
101
|
+
- Add JSDoc comments for complex functions
|
|
102
|
+
- Keep functions small and focused
|
|
103
|
+
|
|
104
|
+
### Error Handling
|
|
105
|
+
|
|
106
|
+
- Always handle errors gracefully
|
|
107
|
+
- Provide clear, actionable error messages
|
|
108
|
+
- Exit with appropriate exit codes (1 for errors)
|
|
109
|
+
|
|
110
|
+
### Output
|
|
111
|
+
|
|
112
|
+
- Use the `OutputFormatter` for all output
|
|
113
|
+
- Support all three output formats: JSON, table, compact
|
|
114
|
+
- Use `ora` spinners for long-running operations
|
|
115
|
+
|
|
116
|
+
## Adding New Commands
|
|
117
|
+
|
|
118
|
+
To add a new command category:
|
|
119
|
+
|
|
120
|
+
1. **Create command file**: `src/commands/yourcommand.ts`
|
|
121
|
+
|
|
122
|
+
2. **Follow the pattern**:
|
|
123
|
+
```typescript
|
|
124
|
+
import { Command } from 'commander';
|
|
125
|
+
import { CakemailClient } from '../client.js';
|
|
126
|
+
import { OutputFormatter } from '../utils/output.js';
|
|
127
|
+
import ora from 'ora';
|
|
128
|
+
|
|
129
|
+
export function createYourCommand(client: CakemailClient, formatter: OutputFormatter): Command {
|
|
130
|
+
const cmd = new Command('yourcommand')
|
|
131
|
+
.description('Description of your command');
|
|
132
|
+
|
|
133
|
+
cmd
|
|
134
|
+
.command('list')
|
|
135
|
+
.description('List items')
|
|
136
|
+
.action(async (options) => {
|
|
137
|
+
const spinner = ora('Fetching...').start();
|
|
138
|
+
try {
|
|
139
|
+
const data = await client.sdk.yourService.list(options);
|
|
140
|
+
spinner.stop();
|
|
141
|
+
formatter.output(data);
|
|
142
|
+
} catch (error: any) {
|
|
143
|
+
spinner.stop();
|
|
144
|
+
formatter.error(error.message);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
return cmd;
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
3. **Register in CLI**: Add to `src/cli.ts`
|
|
154
|
+
```typescript
|
|
155
|
+
import { createYourCommand } from './commands/yourcommand.js';
|
|
156
|
+
// ...
|
|
157
|
+
program.addCommand(createYourCommand(client, formatter));
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
4. **Update documentation**:
|
|
161
|
+
- Add command to README.md
|
|
162
|
+
- Update API_COVERAGE.md
|
|
163
|
+
|
|
164
|
+
## SDK Integration
|
|
165
|
+
|
|
166
|
+
The CLI is built on the official [@cakemail-org/cakemail-sdk](https://www.npmjs.com/package/@cakemail-org/cakemail-sdk).
|
|
167
|
+
|
|
168
|
+
- Always use SDK methods: `client.sdk.serviceName.method()`
|
|
169
|
+
- Follow SDK 2.0 object-based API patterns
|
|
170
|
+
- Wrap request bodies in `requestBody` property
|
|
171
|
+
- Handle SDK errors appropriately
|
|
172
|
+
|
|
173
|
+
Example:
|
|
174
|
+
```typescript
|
|
175
|
+
// SDK 2.0 pattern
|
|
176
|
+
const data = await client.sdk.senderService.createSender({
|
|
177
|
+
requestBody: {
|
|
178
|
+
name: options.name,
|
|
179
|
+
email: options.email
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Testing
|
|
185
|
+
|
|
186
|
+
Currently, the CLI uses manual testing. Before submitting a PR:
|
|
187
|
+
|
|
188
|
+
1. Test all affected commands
|
|
189
|
+
2. Test with different output formats (`-f json`, `-f table`, `-f compact`)
|
|
190
|
+
3. Test error cases (invalid IDs, missing params, etc.)
|
|
191
|
+
4. Test with both email/password and access token authentication
|
|
192
|
+
|
|
193
|
+
## Documentation
|
|
194
|
+
|
|
195
|
+
- Update README.md for user-facing changes
|
|
196
|
+
- Update API_COVERAGE.md for new commands
|
|
197
|
+
- Add JSDoc comments for complex functions
|
|
198
|
+
- Include usage examples in command descriptions
|
|
199
|
+
|
|
200
|
+
## Pull Request Process
|
|
201
|
+
|
|
202
|
+
1. **Before submitting**:
|
|
203
|
+
- Ensure code builds: `npm run build`
|
|
204
|
+
- Test thoroughly
|
|
205
|
+
- Update documentation
|
|
206
|
+
- Write clear commit messages
|
|
207
|
+
|
|
208
|
+
2. **Submit PR**:
|
|
209
|
+
- Provide clear description of changes
|
|
210
|
+
- Reference any related issues
|
|
211
|
+
- List breaking changes (if any)
|
|
212
|
+
- Include testing steps
|
|
213
|
+
|
|
214
|
+
3. **PR Review**:
|
|
215
|
+
- Address review feedback promptly
|
|
216
|
+
- Keep commits clean and focused
|
|
217
|
+
- Squash commits if requested
|
|
218
|
+
|
|
219
|
+
## Questions or Issues?
|
|
220
|
+
|
|
221
|
+
- **Bug reports**: Open an issue with reproduction steps
|
|
222
|
+
- **Feature requests**: Open an issue describing the use case
|
|
223
|
+
- **Questions**: Open a discussion or issue
|
|
224
|
+
|
|
225
|
+
## License
|
|
226
|
+
|
|
227
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|