@mailmodo/cli 0.0.9-beta.pr11.15 → 0.0.9
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/dist/commands/billing/index.js +3 -3
- package/dist/commands/contacts/index.js +4 -4
- package/dist/commands/deploy/index.d.ts +0 -17
- package/dist/commands/deploy/index.js +17 -37
- package/dist/commands/domain/index.js +7 -4
- package/dist/commands/edit/index.js +2 -2
- package/dist/commands/init/index.js +16 -34
- package/dist/commands/login/index.js +3 -26
- package/dist/commands/logs/index.js +1 -1
- package/dist/commands/preview/index.js +2 -2
- package/dist/commands/settings/index.d.ts +0 -1
- package/dist/commands/settings/index.js +3 -4
- package/dist/commands/status/index.js +1 -1
- package/dist/lib/base-command.d.ts +0 -16
- package/dist/lib/base-command.js +0 -31
- package/dist/lib/config.d.ts +0 -5
- package/dist/lib/config.js +2 -15
- package/oclif.manifest.json +66 -104
- package/package.json +2 -3
- package/dist/commands/logout/index.d.ts +0 -10
- package/dist/commands/logout/index.js +0 -28
|
@@ -35,7 +35,7 @@ export default class Billing extends BaseCommand {
|
|
|
35
35
|
* opens Stripe Checkout if no card is on file.
|
|
36
36
|
*/
|
|
37
37
|
async showStatus(jsonOutput) {
|
|
38
|
-
const response = await this.
|
|
38
|
+
const response = await this.apiClient.get(API_ENDPOINTS.BILLING_STATUS);
|
|
39
39
|
if (!response.ok) {
|
|
40
40
|
this.handleApiError(response);
|
|
41
41
|
}
|
|
@@ -84,9 +84,9 @@ export default class Billing extends BaseCommand {
|
|
|
84
84
|
* @param {boolean} jsonOutput - Whether to output JSON instead of formatted text.
|
|
85
85
|
*/
|
|
86
86
|
async setCap(cap, jsonOutput) {
|
|
87
|
-
const response = await this.
|
|
87
|
+
const response = await this.apiClient.patch(API_ENDPOINTS.BILLING_CAP, {
|
|
88
88
|
cap,
|
|
89
|
-
})
|
|
89
|
+
});
|
|
90
90
|
if (!response.ok) {
|
|
91
91
|
this.handleApiError(response);
|
|
92
92
|
}
|
|
@@ -43,7 +43,7 @@ export default class Contacts extends BaseCommand {
|
|
|
43
43
|
* Displays aggregate contact counts: total, active, unsubscribed, bounced.
|
|
44
44
|
*/
|
|
45
45
|
async showSummary(jsonOutput) {
|
|
46
|
-
const response = await this.
|
|
46
|
+
const response = await this.apiClient.get(API_ENDPOINTS.CONTACTS);
|
|
47
47
|
if (!response.ok) {
|
|
48
48
|
this.handleApiError(response);
|
|
49
49
|
}
|
|
@@ -62,7 +62,7 @@ export default class Contacts extends BaseCommand {
|
|
|
62
62
|
* status, properties, and pending emails.
|
|
63
63
|
*/
|
|
64
64
|
async searchContact(email, jsonOutput) {
|
|
65
|
-
const response = await this.
|
|
65
|
+
const response = await this.apiClient.get(`${API_ENDPOINTS.CONTACTS}/${encodeURIComponent(email)}`);
|
|
66
66
|
if (!response.ok) {
|
|
67
67
|
if (response.status === 404) {
|
|
68
68
|
if (jsonOutput) {
|
|
@@ -97,7 +97,7 @@ export default class Contacts extends BaseCommand {
|
|
|
97
97
|
* for the generated file.
|
|
98
98
|
*/
|
|
99
99
|
async exportContacts(jsonOutput) {
|
|
100
|
-
const response = await this.
|
|
100
|
+
const response = await this.apiClient.get(API_ENDPOINTS.CONTACTS_EXPORT);
|
|
101
101
|
if (!response.ok) {
|
|
102
102
|
this.handleApiError(response);
|
|
103
103
|
}
|
|
@@ -126,7 +126,7 @@ export default class Contacts extends BaseCommand {
|
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
const response = await this.
|
|
129
|
+
const response = await this.apiClient.delete(`${API_ENDPOINTS.CONTACTS}/${encodeURIComponent(email)}`);
|
|
130
130
|
if (!response.ok) {
|
|
131
131
|
this.handleApiError(response);
|
|
132
132
|
}
|
|
@@ -6,24 +6,7 @@ export default class Deploy extends BaseCommand {
|
|
|
6
6
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
7
|
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
8
|
};
|
|
9
|
-
/**
|
|
10
|
-
* Fetches current DNS verification status for the deploy flow.
|
|
11
|
-
*
|
|
12
|
-
* @param jsonOutput - When true, spinner uses stderr for stdout-safe JSON runs.
|
|
13
|
-
*/
|
|
14
|
-
private fetchDomainVerifyForDeploy;
|
|
15
9
|
run(): Promise<void>;
|
|
16
|
-
/**
|
|
17
|
-
* Lists emails about to be deployed (skipped when `--json` is set).
|
|
18
|
-
*
|
|
19
|
-
* @param yamlConfig - Loaded project YAML.
|
|
20
|
-
* @param jsonOutput - When true, skip human-readable output.
|
|
21
|
-
*/
|
|
22
|
-
private logPreDeploySummary;
|
|
23
|
-
/**
|
|
24
|
-
* Prints the post-deploy success message and SDK install snippet for interactive runs.
|
|
25
|
-
*/
|
|
26
|
-
private logDeploySuccessInstructions;
|
|
27
10
|
/**
|
|
28
11
|
* Interactive domain setup flow. Collects domain, sender email, and business
|
|
29
12
|
* address from the user, then calls the API to get DNS records to configure.
|
|
@@ -12,19 +12,11 @@ export default class Deploy extends BaseCommand {
|
|
|
12
12
|
static flags = {
|
|
13
13
|
...BaseCommand.baseFlags,
|
|
14
14
|
};
|
|
15
|
-
/**
|
|
16
|
-
* Fetches current DNS verification status for the deploy flow.
|
|
17
|
-
*
|
|
18
|
-
* @param jsonOutput - When true, spinner uses stderr for stdout-safe JSON runs.
|
|
19
|
-
*/
|
|
20
|
-
fetchDomainVerifyForDeploy(jsonOutput) {
|
|
21
|
-
return this.withApiSpinner({ json: jsonOutput, text: ' Checking domain verification...' }, () => this.apiClient.get(API_ENDPOINTS.DOMAIN_VERIFY));
|
|
22
|
-
}
|
|
23
15
|
async run() {
|
|
24
16
|
const { flags } = await this.parse(Deploy);
|
|
25
17
|
await this.ensureAuth();
|
|
26
18
|
const yamlConfig = await this.ensureYaml();
|
|
27
|
-
const domainVerify = await this.
|
|
19
|
+
const domainVerify = await this.apiClient.get(API_ENDPOINTS.DOMAIN_VERIFY);
|
|
28
20
|
const domainVerified = domainVerify.ok &&
|
|
29
21
|
domainVerify.data?.spf === 'pass' &&
|
|
30
22
|
domainVerify.data?.dkim === 'pass' &&
|
|
@@ -52,7 +44,14 @@ export default class Deploy extends BaseCommand {
|
|
|
52
44
|
if (!completed)
|
|
53
45
|
return;
|
|
54
46
|
}
|
|
55
|
-
|
|
47
|
+
if (!flags.json) {
|
|
48
|
+
this.log(`\n ${chalk.green('✓')} Domain: ${yamlConfig.project?.domain || 'verified'}\n`);
|
|
49
|
+
this.log(` Deploying:`);
|
|
50
|
+
for (const email of yamlConfig.emails) {
|
|
51
|
+
this.log(` ${chalk.green('+')} ${email.id.padEnd(24)} ${email.trigger}`);
|
|
52
|
+
}
|
|
53
|
+
this.log('');
|
|
54
|
+
}
|
|
56
55
|
if (!flags.yes) {
|
|
57
56
|
const proceed = await confirm({
|
|
58
57
|
default: true,
|
|
@@ -63,10 +62,10 @@ export default class Deploy extends BaseCommand {
|
|
|
63
62
|
return;
|
|
64
63
|
}
|
|
65
64
|
}
|
|
66
|
-
const response = await this.
|
|
65
|
+
const response = await this.apiClient.post(API_ENDPOINTS.SEQUENCES, {
|
|
67
66
|
emails: yamlConfig.emails,
|
|
68
67
|
project: yamlConfig.project,
|
|
69
|
-
})
|
|
68
|
+
});
|
|
70
69
|
if (!response.ok) {
|
|
71
70
|
this.handleApiError(response);
|
|
72
71
|
}
|
|
@@ -78,28 +77,6 @@ export default class Deploy extends BaseCommand {
|
|
|
78
77
|
}, null, 2));
|
|
79
78
|
return;
|
|
80
79
|
}
|
|
81
|
-
this.logDeploySuccessInstructions();
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Lists emails about to be deployed (skipped when `--json` is set).
|
|
85
|
-
*
|
|
86
|
-
* @param yamlConfig - Loaded project YAML.
|
|
87
|
-
* @param jsonOutput - When true, skip human-readable output.
|
|
88
|
-
*/
|
|
89
|
-
logPreDeploySummary(yamlConfig, jsonOutput) {
|
|
90
|
-
if (jsonOutput)
|
|
91
|
-
return;
|
|
92
|
-
this.log(`\n ${chalk.green('✓')} Domain: ${yamlConfig.project?.domain || 'verified'}\n`);
|
|
93
|
-
this.log(` Deploying:`);
|
|
94
|
-
for (const email of yamlConfig.emails) {
|
|
95
|
-
this.log(` ${chalk.green('+')} ${email.id.padEnd(24)} ${email.trigger}`);
|
|
96
|
-
}
|
|
97
|
-
this.log('');
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Prints the post-deploy success message and SDK install snippet for interactive runs.
|
|
101
|
-
*/
|
|
102
|
-
logDeploySuccessInstructions() {
|
|
103
80
|
this.log(` ${chalk.green('Deployed.')} Emails are live.\n`);
|
|
104
81
|
this.log(` ${'─'.repeat(53)}`);
|
|
105
82
|
this.log(` ${chalk.bold('ADD THIS TO YOUR APP (one-time only):')}`);
|
|
@@ -148,11 +125,11 @@ export default class Deploy extends BaseCommand {
|
|
|
148
125
|
validate: (v) => (v?.trim() ? true : 'Address is required'),
|
|
149
126
|
});
|
|
150
127
|
}
|
|
151
|
-
const domainResponse = await this.
|
|
128
|
+
const domainResponse = await this.apiClient.post(API_ENDPOINTS.DOMAIN, {
|
|
152
129
|
address,
|
|
153
130
|
domain,
|
|
154
131
|
fromEmail: senderEmail,
|
|
155
|
-
})
|
|
132
|
+
});
|
|
156
133
|
if (!domainResponse.ok) {
|
|
157
134
|
this.handleApiError(domainResponse);
|
|
158
135
|
}
|
|
@@ -194,7 +171,10 @@ export default class Deploy extends BaseCommand {
|
|
|
194
171
|
* @returns {Promise<boolean>} true if all records pass.
|
|
195
172
|
*/
|
|
196
173
|
async verifyDomain(jsonOutput) {
|
|
197
|
-
|
|
174
|
+
if (!jsonOutput) {
|
|
175
|
+
this.log(`\n Checking DNS...`);
|
|
176
|
+
}
|
|
177
|
+
const verify = await this.apiClient.get(API_ENDPOINTS.DOMAIN_VERIFY);
|
|
198
178
|
if (!verify.ok) {
|
|
199
179
|
this.handleApiError(verify);
|
|
200
180
|
}
|
|
@@ -72,11 +72,11 @@ export default class Domain extends BaseCommand {
|
|
|
72
72
|
validate: (v) => (v?.trim() ? true : 'Address is required'),
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
|
-
const response = await this.
|
|
75
|
+
const response = await this.apiClient.post(API_ENDPOINTS.DOMAIN, {
|
|
76
76
|
address,
|
|
77
77
|
domain,
|
|
78
78
|
fromEmail: senderEmail,
|
|
79
|
-
})
|
|
79
|
+
});
|
|
80
80
|
if (!response.ok) {
|
|
81
81
|
this.handleApiError(response);
|
|
82
82
|
}
|
|
@@ -112,7 +112,10 @@ export default class Domain extends BaseCommand {
|
|
|
112
112
|
* Calls the domain verification API and displays pass/fail for each DNS record.
|
|
113
113
|
*/
|
|
114
114
|
async verifyDomain(jsonOutput) {
|
|
115
|
-
|
|
115
|
+
if (!jsonOutput) {
|
|
116
|
+
this.log(`\n Checking DNS...`);
|
|
117
|
+
}
|
|
118
|
+
const response = await this.apiClient.get(API_ENDPOINTS.DOMAIN_VERIFY);
|
|
116
119
|
if (!response.ok) {
|
|
117
120
|
this.handleApiError(response);
|
|
118
121
|
}
|
|
@@ -145,7 +148,7 @@ export default class Domain extends BaseCommand {
|
|
|
145
148
|
* bounce rate, and spam complaint rate.
|
|
146
149
|
*/
|
|
147
150
|
async showDomainStatus(jsonOutput) {
|
|
148
|
-
const response = await this.
|
|
151
|
+
const response = await this.apiClient.get(API_ENDPOINTS.DOMAIN_STATUS);
|
|
149
152
|
if (!response.ok) {
|
|
150
153
|
this.handleApiError(response);
|
|
151
154
|
}
|
|
@@ -39,7 +39,7 @@ export default class Edit extends BaseCommand {
|
|
|
39
39
|
validate: (value) => value?.trim() ? true : 'Please describe the change',
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
|
-
const response = await this.
|
|
42
|
+
const response = await this.apiClient.post(API_ENDPOINTS.EDIT, {
|
|
43
43
|
changeRequest: changeDescription,
|
|
44
44
|
currentEmail: {
|
|
45
45
|
condition: email.condition,
|
|
@@ -50,7 +50,7 @@ export default class Edit extends BaseCommand {
|
|
|
50
50
|
subject: email.subject,
|
|
51
51
|
trigger: email.trigger,
|
|
52
52
|
},
|
|
53
|
-
})
|
|
53
|
+
});
|
|
54
54
|
if (!response.ok) {
|
|
55
55
|
this.handleApiError(response);
|
|
56
56
|
}
|
|
@@ -12,23 +12,6 @@ function isValidUrl(value) {
|
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Prints the human-readable analysis summary using the provided line writer.
|
|
17
|
-
* Use stderr when `--json` is set so stdout stays free for machine-readable JSON.
|
|
18
|
-
*
|
|
19
|
-
* @param analysis - Parsed analyze API payload.
|
|
20
|
-
* @param logLine - Line writer (typically bound `this.log` or `this.logToStderr`).
|
|
21
|
-
*/
|
|
22
|
-
function logAnalysisSummary(analysis, logLine) {
|
|
23
|
-
logLine(` Detected:`);
|
|
24
|
-
logLine(` - Type: ${analysis.businessType} — ${analysis.description}`);
|
|
25
|
-
logLine(` - Model: ${analysis.pricingModel}`);
|
|
26
|
-
logLine(` - Users: ${analysis.targetUser}`);
|
|
27
|
-
if (analysis.events?.length) {
|
|
28
|
-
logLine(` - Events: ${analysis.events.join(', ')}`);
|
|
29
|
-
}
|
|
30
|
-
logLine('');
|
|
31
|
-
}
|
|
32
15
|
export default class Init extends BaseCommand {
|
|
33
16
|
static description = 'Analyze your product and generate email sequences';
|
|
34
17
|
static examples = [
|
|
@@ -55,22 +38,22 @@ export default class Init extends BaseCommand {
|
|
|
55
38
|
},
|
|
56
39
|
});
|
|
57
40
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}, () => this.apiClient.post(API_ENDPOINTS.ANALYZE, {
|
|
62
|
-
url: productUrl,
|
|
63
|
-
}));
|
|
41
|
+
this.log(`\n Analyzing your product...`);
|
|
42
|
+
this.log(` Scraping: homepage, pricing, features\n`);
|
|
43
|
+
const analysisResponse = await this.apiClient.post(API_ENDPOINTS.ANALYZE, { url: productUrl });
|
|
64
44
|
if (!analysisResponse.ok) {
|
|
65
45
|
this.handleApiError(analysisResponse);
|
|
66
46
|
}
|
|
67
47
|
const analysis = analysisResponse.data;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
48
|
+
if (!flags.json) {
|
|
49
|
+
this.log(` Detected:`);
|
|
50
|
+
this.log(` - Type: ${analysis.businessType} — ${analysis.description}`);
|
|
51
|
+
this.log(` - Model: ${analysis.pricingModel}`);
|
|
52
|
+
this.log(` - Users: ${analysis.targetUser}`);
|
|
53
|
+
if (analysis.events?.length) {
|
|
54
|
+
this.log(` - Events: ${analysis.events.join(', ')}`);
|
|
55
|
+
}
|
|
56
|
+
this.log('');
|
|
74
57
|
}
|
|
75
58
|
let analysisPayload = analysis;
|
|
76
59
|
if (!flags.yes) {
|
|
@@ -106,13 +89,12 @@ export default class Init extends BaseCommand {
|
|
|
106
89
|
analysisPayload = JSON.parse(editedAnalysis);
|
|
107
90
|
}
|
|
108
91
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}, () => this.apiClient.post(API_ENDPOINTS.GENERATE, {
|
|
92
|
+
this.log('analysisPayload', analysisPayload);
|
|
93
|
+
this.log('\n Generating emails...\n');
|
|
94
|
+
const generateResponse = await this.apiClient.post(API_ENDPOINTS.GENERATE, {
|
|
113
95
|
analysis: analysisPayload,
|
|
114
96
|
productUrl,
|
|
115
|
-
})
|
|
97
|
+
});
|
|
116
98
|
if (!generateResponse.ok) {
|
|
117
99
|
this.handleApiError(generateResponse);
|
|
118
100
|
}
|
|
@@ -3,7 +3,7 @@ import chalk from 'chalk';
|
|
|
3
3
|
import open from 'open';
|
|
4
4
|
import { BaseCommand } from '../../lib/base-command.js';
|
|
5
5
|
import { ApiClient } from '../../lib/api-client.js';
|
|
6
|
-
import {
|
|
6
|
+
import { saveConfig } from '../../lib/config.js';
|
|
7
7
|
import { API_ENDPOINTS, SIGNUP_URL } from '../../lib/constants.js';
|
|
8
8
|
export default class Login extends BaseCommand {
|
|
9
9
|
static description = 'Authenticate with Mailmodo using your API key';
|
|
@@ -16,30 +16,7 @@ export default class Login extends BaseCommand {
|
|
|
16
16
|
};
|
|
17
17
|
async run() {
|
|
18
18
|
const { flags } = await this.parse(Login);
|
|
19
|
-
|
|
20
|
-
if (!envKey) {
|
|
21
|
-
const existing = await loadConfig();
|
|
22
|
-
if (existing?.apiKey) {
|
|
23
|
-
if (flags.json) {
|
|
24
|
-
this.log(JSON.stringify({
|
|
25
|
-
accountName: existing.accountName ?? null,
|
|
26
|
-
email: existing.email ?? null,
|
|
27
|
-
freeRemaining: existing.freeRemaining ?? null,
|
|
28
|
-
status: 'already_logged_in',
|
|
29
|
-
}, null, 2));
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
this.log('\n You are already logged in.\n');
|
|
33
|
-
const emailDisplay = existing.email?.trim()
|
|
34
|
-
? chalk.green(existing.email.trim())
|
|
35
|
-
: chalk.dim('(unknown)');
|
|
36
|
-
this.log(` Email: ${emailDisplay}\n`);
|
|
37
|
-
this.log(` ${chalk.dim('1.')} Run ${chalk.cyan('mailmodo init')} to generate an email sequence.`);
|
|
38
|
-
this.log(` ${chalk.dim('2.')} Run ${chalk.cyan('mailmodo logout')} to log in with another account.\n`);
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
let apiKey = envKey;
|
|
19
|
+
let apiKey = process.env.MAILMODO_API_KEY;
|
|
43
20
|
if (apiKey) {
|
|
44
21
|
this.log('Detected MAILMODO_API_KEY from environment.');
|
|
45
22
|
}
|
|
@@ -63,7 +40,7 @@ export default class Login extends BaseCommand {
|
|
|
63
40
|
}
|
|
64
41
|
const trimmedKey = apiKey.trim();
|
|
65
42
|
const client = new ApiClient(trimmedKey);
|
|
66
|
-
const response = await
|
|
43
|
+
const response = await client.post(API_ENDPOINTS.AUTH_VALIDATE, {});
|
|
67
44
|
if (!response.ok) {
|
|
68
45
|
this.handleApiError(response);
|
|
69
46
|
}
|
|
@@ -26,7 +26,7 @@ export default class Logs extends BaseCommand {
|
|
|
26
26
|
params.email = flags.email;
|
|
27
27
|
if (flags.failed)
|
|
28
28
|
params.failed = 'true';
|
|
29
|
-
const response = await this.
|
|
29
|
+
const response = await this.apiClient.get(API_ENDPOINTS.LOGS, params);
|
|
30
30
|
if (!response.ok) {
|
|
31
31
|
this.handleApiError(response);
|
|
32
32
|
}
|
|
@@ -125,9 +125,9 @@ export default class Preview extends BaseCommand {
|
|
|
125
125
|
*/
|
|
126
126
|
async sendTestEmail(emailId, toAddress, jsonOutput) {
|
|
127
127
|
await this.ensureAuth();
|
|
128
|
-
const response = await this.
|
|
128
|
+
const response = await this.apiClient.post(`${API_ENDPOINTS.PREVIEW}/${emailId}/send`, {
|
|
129
129
|
to: toAddress,
|
|
130
|
-
})
|
|
130
|
+
});
|
|
131
131
|
if (!response.ok) {
|
|
132
132
|
this.handleApiError(response);
|
|
133
133
|
}
|
|
@@ -14,7 +14,6 @@ export default class Settings extends BaseCommand {
|
|
|
14
14
|
* and logoUrl in the project config.
|
|
15
15
|
*
|
|
16
16
|
* @param {import('../../lib/yaml-config.js').MailmodoYaml} yamlConfig - The full YAML config to update and save.
|
|
17
|
-
* @param {boolean} jsonOutput - When true, spinner uses stderr so stdout stays clean.
|
|
18
17
|
*/
|
|
19
18
|
private handleLogoUpload;
|
|
20
19
|
}
|
|
@@ -89,7 +89,7 @@ export default class Settings extends BaseCommand {
|
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
91
|
if (editKey === 'logo_file') {
|
|
92
|
-
await this.handleLogoUpload(yamlConfig
|
|
92
|
+
await this.handleLogoUpload(yamlConfig);
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
95
|
if (editKey === 'email_style') {
|
|
@@ -122,9 +122,8 @@ export default class Settings extends BaseCommand {
|
|
|
122
122
|
* and logoUrl in the project config.
|
|
123
123
|
*
|
|
124
124
|
* @param {import('../../lib/yaml-config.js').MailmodoYaml} yamlConfig - The full YAML config to update and save.
|
|
125
|
-
* @param {boolean} jsonOutput - When true, spinner uses stderr so stdout stays clean.
|
|
126
125
|
*/
|
|
127
|
-
async handleLogoUpload(yamlConfig
|
|
126
|
+
async handleLogoUpload(yamlConfig) {
|
|
128
127
|
const logoPath = await input({ message: 'Path to logo file:' });
|
|
129
128
|
const resolvedPath = resolve(logoPath);
|
|
130
129
|
if (!existsSync(resolvedPath)) {
|
|
@@ -135,7 +134,7 @@ export default class Settings extends BaseCommand {
|
|
|
135
134
|
const fileBuffer = await readFile(resolvedPath);
|
|
136
135
|
const formData = new FormData();
|
|
137
136
|
formData.append('logo', new Blob([new Uint8Array(fileBuffer)]), logoPath.split(/[/\\]/).pop() || 'logo.png');
|
|
138
|
-
const response = await this.
|
|
137
|
+
const response = await this.apiClient.postFormData(API_ENDPOINTS.ASSETS_LOGO, formData);
|
|
139
138
|
if (!response.ok) {
|
|
140
139
|
this.handleApiError(response);
|
|
141
140
|
}
|
|
@@ -13,7 +13,7 @@ export default class Status extends BaseCommand {
|
|
|
13
13
|
async run() {
|
|
14
14
|
const { flags } = await this.parse(Status);
|
|
15
15
|
await this.ensureAuth();
|
|
16
|
-
const response = await this.
|
|
16
|
+
const response = await this.apiClient.get(API_ENDPOINTS.ANALYTICS);
|
|
17
17
|
if (!response.ok) {
|
|
18
18
|
this.handleApiError(response);
|
|
19
19
|
}
|
|
@@ -22,22 +22,6 @@ export declare abstract class BaseCommand extends Command {
|
|
|
22
22
|
* @returns {Promise<MailmodoConfig>} The resolved configuration containing the API key.
|
|
23
23
|
*/
|
|
24
24
|
protected ensureAuth(): Promise<MailmodoConfig>;
|
|
25
|
-
/**
|
|
26
|
-
* Runs an async function (typically an API call) while showing a cyan ora spinner.
|
|
27
|
-
* When `options.json` is true, the leading blank line is written to stderr so stdout stays
|
|
28
|
-
* free for machine-readable JSON (e.g. piping to `jq`).
|
|
29
|
-
*
|
|
30
|
-
* @template T - Resolved type of the work promise (often the API client response).
|
|
31
|
-
* @param {{ json: boolean; text: string }} options - Spinner options.
|
|
32
|
-
* @param {boolean} options.json - If true, stderr for the blank line before the spinner.
|
|
33
|
-
* @param {string} options.text - Spinner label (often two leading spaces).
|
|
34
|
-
* @param {() => Promise<T>} work - Zero-argument async function that performs the request.
|
|
35
|
-
* @returns {Promise<T>} The fulfilled value from `work`.
|
|
36
|
-
*/
|
|
37
|
-
protected withApiSpinner<T>(options: {
|
|
38
|
-
json: boolean;
|
|
39
|
-
text: string;
|
|
40
|
-
}, work: () => Promise<T>): Promise<T>;
|
|
41
25
|
/**
|
|
42
26
|
* Loads and returns the mailmodo.yaml configuration from the current directory.
|
|
43
27
|
* Exits with an error if the file is not found, directing the user to run init.
|
package/dist/lib/base-command.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import ora from 'ora';
|
|
4
3
|
import { ApiClient } from './api-client.js';
|
|
5
4
|
import { loadConfig } from './config.js';
|
|
6
5
|
import { loadYaml } from './yaml-config.js';
|
|
@@ -40,36 +39,6 @@ export class BaseCommand extends Command {
|
|
|
40
39
|
this.apiClient = new ApiClient(config.apiKey);
|
|
41
40
|
return config;
|
|
42
41
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Runs an async function (typically an API call) while showing a cyan ora spinner.
|
|
45
|
-
* When `options.json` is true, the leading blank line is written to stderr so stdout stays
|
|
46
|
-
* free for machine-readable JSON (e.g. piping to `jq`).
|
|
47
|
-
*
|
|
48
|
-
* @template T - Resolved type of the work promise (often the API client response).
|
|
49
|
-
* @param {{ json: boolean; text: string }} options - Spinner options.
|
|
50
|
-
* @param {boolean} options.json - If true, stderr for the blank line before the spinner.
|
|
51
|
-
* @param {string} options.text - Spinner label (often two leading spaces).
|
|
52
|
-
* @param {() => Promise<T>} work - Zero-argument async function that performs the request.
|
|
53
|
-
* @returns {Promise<T>} The fulfilled value from `work`.
|
|
54
|
-
*/
|
|
55
|
-
async withApiSpinner(options, work) {
|
|
56
|
-
if (options.json) {
|
|
57
|
-
this.logToStderr('');
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
this.log('');
|
|
61
|
-
}
|
|
62
|
-
const spinner = ora({
|
|
63
|
-
color: 'cyan',
|
|
64
|
-
text: options.text,
|
|
65
|
-
}).start();
|
|
66
|
-
try {
|
|
67
|
-
return await work();
|
|
68
|
-
}
|
|
69
|
-
finally {
|
|
70
|
-
spinner.stop();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
42
|
/**
|
|
74
43
|
* Loads and returns the mailmodo.yaml configuration from the current directory.
|
|
75
44
|
* Exits with an error if the file is not found, directing the user to run init.
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -22,11 +22,6 @@ export declare function loadConfig(): Promise<MailmodoConfig | null>;
|
|
|
22
22
|
* at minimum an apiKey. Optional fields: email, accountName, freeRemaining.
|
|
23
23
|
*/
|
|
24
24
|
export declare function saveConfig(config: MailmodoConfig): Promise<void>;
|
|
25
|
-
/**
|
|
26
|
-
* Deletes the saved CLI config file (~/.mailmodo/config), removing the stored API key.
|
|
27
|
-
* No-op if the file does not exist.
|
|
28
|
-
*/
|
|
29
|
-
export declare function clearConfig(): Promise<void>;
|
|
30
25
|
/**
|
|
31
26
|
* Returns the absolute path to the Mailmodo config directory (~/.mailmodo).
|
|
32
27
|
*
|
package/dist/lib/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
-
import { mkdir, readFile,
|
|
2
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
const CONFIG_DIR = join(homedir(), '.mailmodo');
|
|
@@ -13,6 +13,7 @@ const CONFIG_FILE = join(CONFIG_DIR, 'config');
|
|
|
13
13
|
* or null if the config file does not exist or is corrupted.
|
|
14
14
|
*/
|
|
15
15
|
export async function loadConfig() {
|
|
16
|
+
console.log('Loading config from', CONFIG_FILE);
|
|
16
17
|
if (!existsSync(CONFIG_FILE))
|
|
17
18
|
return null;
|
|
18
19
|
try {
|
|
@@ -37,20 +38,6 @@ export async function saveConfig(config) {
|
|
|
37
38
|
}
|
|
38
39
|
await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
39
40
|
}
|
|
40
|
-
/**
|
|
41
|
-
* Deletes the saved CLI config file (~/.mailmodo/config), removing the stored API key.
|
|
42
|
-
* No-op if the file does not exist.
|
|
43
|
-
*/
|
|
44
|
-
export async function clearConfig() {
|
|
45
|
-
if (!existsSync(CONFIG_FILE))
|
|
46
|
-
return;
|
|
47
|
-
try {
|
|
48
|
-
await unlink(CONFIG_FILE);
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
// Ignore missing file or permission errors; caller can treat as best-effort sign-out.
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
41
|
/**
|
|
55
42
|
* Returns the absolute path to the Mailmodo config directory (~/.mailmodo).
|
|
56
43
|
*
|
package/oclif.manifest.json
CHANGED
|
@@ -153,13 +153,14 @@
|
|
|
153
153
|
"index.js"
|
|
154
154
|
]
|
|
155
155
|
},
|
|
156
|
-
"
|
|
156
|
+
"domain": {
|
|
157
157
|
"aliases": [],
|
|
158
158
|
"args": {},
|
|
159
|
-
"description": "
|
|
159
|
+
"description": "Set up and verify your sending domain",
|
|
160
160
|
"examples": [
|
|
161
|
-
"<%= config.bin %>
|
|
162
|
-
"<%= config.bin %>
|
|
161
|
+
"<%= config.bin %> domain",
|
|
162
|
+
"<%= config.bin %> domain --verify",
|
|
163
|
+
"<%= config.bin %> domain --status"
|
|
163
164
|
],
|
|
164
165
|
"flags": {
|
|
165
166
|
"json": {
|
|
@@ -174,11 +175,23 @@
|
|
|
174
175
|
"name": "yes",
|
|
175
176
|
"allowNo": false,
|
|
176
177
|
"type": "boolean"
|
|
178
|
+
},
|
|
179
|
+
"status": {
|
|
180
|
+
"description": "Show domain health status",
|
|
181
|
+
"name": "status",
|
|
182
|
+
"allowNo": false,
|
|
183
|
+
"type": "boolean"
|
|
184
|
+
},
|
|
185
|
+
"verify": {
|
|
186
|
+
"description": "Verify DNS records",
|
|
187
|
+
"name": "verify",
|
|
188
|
+
"allowNo": false,
|
|
189
|
+
"type": "boolean"
|
|
177
190
|
}
|
|
178
191
|
},
|
|
179
192
|
"hasDynamicHelp": false,
|
|
180
193
|
"hiddenAliases": [],
|
|
181
|
-
"id": "
|
|
194
|
+
"id": "domain",
|
|
182
195
|
"pluginAlias": "@mailmodo/cli",
|
|
183
196
|
"pluginName": "@mailmodo/cli",
|
|
184
197
|
"pluginType": "core",
|
|
@@ -188,7 +201,7 @@
|
|
|
188
201
|
"relativePath": [
|
|
189
202
|
"dist",
|
|
190
203
|
"commands",
|
|
191
|
-
"
|
|
204
|
+
"domain",
|
|
192
205
|
"index.js"
|
|
193
206
|
]
|
|
194
207
|
},
|
|
@@ -244,14 +257,13 @@
|
|
|
244
257
|
"index.js"
|
|
245
258
|
]
|
|
246
259
|
},
|
|
247
|
-
"
|
|
260
|
+
"emails": {
|
|
248
261
|
"aliases": [],
|
|
249
262
|
"args": {},
|
|
250
|
-
"description": "
|
|
263
|
+
"description": "List and view configured email sequences",
|
|
251
264
|
"examples": [
|
|
252
|
-
"<%= config.bin %>
|
|
253
|
-
"<%= config.bin %>
|
|
254
|
-
"<%= config.bin %> domain --status"
|
|
265
|
+
"<%= config.bin %> emails",
|
|
266
|
+
"<%= config.bin %> emails --json"
|
|
255
267
|
],
|
|
256
268
|
"flags": {
|
|
257
269
|
"json": {
|
|
@@ -266,23 +278,11 @@
|
|
|
266
278
|
"name": "yes",
|
|
267
279
|
"allowNo": false,
|
|
268
280
|
"type": "boolean"
|
|
269
|
-
},
|
|
270
|
-
"status": {
|
|
271
|
-
"description": "Show domain health status",
|
|
272
|
-
"name": "status",
|
|
273
|
-
"allowNo": false,
|
|
274
|
-
"type": "boolean"
|
|
275
|
-
},
|
|
276
|
-
"verify": {
|
|
277
|
-
"description": "Verify DNS records",
|
|
278
|
-
"name": "verify",
|
|
279
|
-
"allowNo": false,
|
|
280
|
-
"type": "boolean"
|
|
281
281
|
}
|
|
282
282
|
},
|
|
283
283
|
"hasDynamicHelp": false,
|
|
284
284
|
"hiddenAliases": [],
|
|
285
|
-
"id": "
|
|
285
|
+
"id": "emails",
|
|
286
286
|
"pluginAlias": "@mailmodo/cli",
|
|
287
287
|
"pluginName": "@mailmodo/cli",
|
|
288
288
|
"pluginType": "core",
|
|
@@ -292,7 +292,7 @@
|
|
|
292
292
|
"relativePath": [
|
|
293
293
|
"dist",
|
|
294
294
|
"commands",
|
|
295
|
-
"
|
|
295
|
+
"emails",
|
|
296
296
|
"index.js"
|
|
297
297
|
]
|
|
298
298
|
},
|
|
@@ -435,12 +435,14 @@
|
|
|
435
435
|
"index.js"
|
|
436
436
|
]
|
|
437
437
|
},
|
|
438
|
-
"
|
|
438
|
+
"settings": {
|
|
439
439
|
"aliases": [],
|
|
440
440
|
"args": {},
|
|
441
|
-
"description": "
|
|
441
|
+
"description": "View and update project settings",
|
|
442
442
|
"examples": [
|
|
443
|
-
"<%= config.bin %>
|
|
443
|
+
"<%= config.bin %> settings",
|
|
444
|
+
"<%= config.bin %> settings --set brand_color=#0F3460",
|
|
445
|
+
"<%= config.bin %> settings --json"
|
|
444
446
|
],
|
|
445
447
|
"flags": {
|
|
446
448
|
"json": {
|
|
@@ -455,11 +457,18 @@
|
|
|
455
457
|
"name": "yes",
|
|
456
458
|
"allowNo": false,
|
|
457
459
|
"type": "boolean"
|
|
460
|
+
},
|
|
461
|
+
"set": {
|
|
462
|
+
"description": "Set a setting (format: key=value)",
|
|
463
|
+
"name": "set",
|
|
464
|
+
"hasDynamicHelp": false,
|
|
465
|
+
"multiple": false,
|
|
466
|
+
"type": "option"
|
|
458
467
|
}
|
|
459
468
|
},
|
|
460
469
|
"hasDynamicHelp": false,
|
|
461
470
|
"hiddenAliases": [],
|
|
462
|
-
"id": "
|
|
471
|
+
"id": "settings",
|
|
463
472
|
"pluginAlias": "@mailmodo/cli",
|
|
464
473
|
"pluginName": "@mailmodo/cli",
|
|
465
474
|
"pluginType": "core",
|
|
@@ -469,23 +478,17 @@
|
|
|
469
478
|
"relativePath": [
|
|
470
479
|
"dist",
|
|
471
480
|
"commands",
|
|
472
|
-
"
|
|
481
|
+
"settings",
|
|
473
482
|
"index.js"
|
|
474
483
|
]
|
|
475
484
|
},
|
|
476
|
-
"
|
|
485
|
+
"status": {
|
|
477
486
|
"aliases": [],
|
|
478
|
-
"args": {
|
|
479
|
-
|
|
480
|
-
"description": "Email ID to preview",
|
|
481
|
-
"name": "id"
|
|
482
|
-
}
|
|
483
|
-
},
|
|
484
|
-
"description": "Preview an email in browser, as text, or send a test",
|
|
487
|
+
"args": {},
|
|
488
|
+
"description": "View email performance metrics and quota usage",
|
|
485
489
|
"examples": [
|
|
486
|
-
"<%= config.bin %>
|
|
487
|
-
"<%= config.bin %>
|
|
488
|
-
"<%= config.bin %> preview welcome --send me@example.com"
|
|
490
|
+
"<%= config.bin %> status",
|
|
491
|
+
"<%= config.bin %> status --json"
|
|
489
492
|
],
|
|
490
493
|
"flags": {
|
|
491
494
|
"json": {
|
|
@@ -500,24 +503,11 @@
|
|
|
500
503
|
"name": "yes",
|
|
501
504
|
"allowNo": false,
|
|
502
505
|
"type": "boolean"
|
|
503
|
-
},
|
|
504
|
-
"send": {
|
|
505
|
-
"description": "Send test email to this address",
|
|
506
|
-
"name": "send",
|
|
507
|
-
"hasDynamicHelp": false,
|
|
508
|
-
"multiple": false,
|
|
509
|
-
"type": "option"
|
|
510
|
-
},
|
|
511
|
-
"text": {
|
|
512
|
-
"description": "Output plain text version (for AI agents)",
|
|
513
|
-
"name": "text",
|
|
514
|
-
"allowNo": false,
|
|
515
|
-
"type": "boolean"
|
|
516
506
|
}
|
|
517
507
|
},
|
|
518
508
|
"hasDynamicHelp": false,
|
|
519
509
|
"hiddenAliases": [],
|
|
520
|
-
"id": "
|
|
510
|
+
"id": "status",
|
|
521
511
|
"pluginAlias": "@mailmodo/cli",
|
|
522
512
|
"pluginName": "@mailmodo/cli",
|
|
523
513
|
"pluginType": "core",
|
|
@@ -527,18 +517,23 @@
|
|
|
527
517
|
"relativePath": [
|
|
528
518
|
"dist",
|
|
529
519
|
"commands",
|
|
530
|
-
"
|
|
520
|
+
"status",
|
|
531
521
|
"index.js"
|
|
532
522
|
]
|
|
533
523
|
},
|
|
534
|
-
"
|
|
524
|
+
"preview": {
|
|
535
525
|
"aliases": [],
|
|
536
|
-
"args": {
|
|
537
|
-
|
|
526
|
+
"args": {
|
|
527
|
+
"id": {
|
|
528
|
+
"description": "Email ID to preview",
|
|
529
|
+
"name": "id"
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
"description": "Preview an email in browser, as text, or send a test",
|
|
538
533
|
"examples": [
|
|
539
|
-
"<%= config.bin %>
|
|
540
|
-
"<%= config.bin %>
|
|
541
|
-
"<%= config.bin %>
|
|
534
|
+
"<%= config.bin %> preview welcome",
|
|
535
|
+
"<%= config.bin %> preview welcome --text",
|
|
536
|
+
"<%= config.bin %> preview welcome --send me@example.com"
|
|
542
537
|
],
|
|
543
538
|
"flags": {
|
|
544
539
|
"json": {
|
|
@@ -554,56 +549,23 @@
|
|
|
554
549
|
"allowNo": false,
|
|
555
550
|
"type": "boolean"
|
|
556
551
|
},
|
|
557
|
-
"
|
|
558
|
-
"description": "
|
|
559
|
-
"name": "
|
|
552
|
+
"send": {
|
|
553
|
+
"description": "Send test email to this address",
|
|
554
|
+
"name": "send",
|
|
560
555
|
"hasDynamicHelp": false,
|
|
561
556
|
"multiple": false,
|
|
562
557
|
"type": "option"
|
|
563
|
-
}
|
|
564
|
-
},
|
|
565
|
-
"hasDynamicHelp": false,
|
|
566
|
-
"hiddenAliases": [],
|
|
567
|
-
"id": "settings",
|
|
568
|
-
"pluginAlias": "@mailmodo/cli",
|
|
569
|
-
"pluginName": "@mailmodo/cli",
|
|
570
|
-
"pluginType": "core",
|
|
571
|
-
"strict": true,
|
|
572
|
-
"enableJsonFlag": false,
|
|
573
|
-
"isESM": true,
|
|
574
|
-
"relativePath": [
|
|
575
|
-
"dist",
|
|
576
|
-
"commands",
|
|
577
|
-
"settings",
|
|
578
|
-
"index.js"
|
|
579
|
-
]
|
|
580
|
-
},
|
|
581
|
-
"status": {
|
|
582
|
-
"aliases": [],
|
|
583
|
-
"args": {},
|
|
584
|
-
"description": "View email performance metrics and quota usage",
|
|
585
|
-
"examples": [
|
|
586
|
-
"<%= config.bin %> status",
|
|
587
|
-
"<%= config.bin %> status --json"
|
|
588
|
-
],
|
|
589
|
-
"flags": {
|
|
590
|
-
"json": {
|
|
591
|
-
"description": "Output as JSON",
|
|
592
|
-
"name": "json",
|
|
593
|
-
"allowNo": false,
|
|
594
|
-
"type": "boolean"
|
|
595
558
|
},
|
|
596
|
-
"
|
|
597
|
-
"
|
|
598
|
-
"
|
|
599
|
-
"name": "yes",
|
|
559
|
+
"text": {
|
|
560
|
+
"description": "Output plain text version (for AI agents)",
|
|
561
|
+
"name": "text",
|
|
600
562
|
"allowNo": false,
|
|
601
563
|
"type": "boolean"
|
|
602
564
|
}
|
|
603
565
|
},
|
|
604
566
|
"hasDynamicHelp": false,
|
|
605
567
|
"hiddenAliases": [],
|
|
606
|
-
"id": "
|
|
568
|
+
"id": "preview",
|
|
607
569
|
"pluginAlias": "@mailmodo/cli",
|
|
608
570
|
"pluginName": "@mailmodo/cli",
|
|
609
571
|
"pluginType": "core",
|
|
@@ -613,10 +575,10 @@
|
|
|
613
575
|
"relativePath": [
|
|
614
576
|
"dist",
|
|
615
577
|
"commands",
|
|
616
|
-
"
|
|
578
|
+
"preview",
|
|
617
579
|
"index.js"
|
|
618
580
|
]
|
|
619
581
|
}
|
|
620
582
|
},
|
|
621
|
-
"version": "0.0.9
|
|
583
|
+
"version": "0.0.9"
|
|
622
584
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mailmodo/cli",
|
|
3
3
|
"description": "Email lifecycle automation for the AI-native builder generation.",
|
|
4
|
-
"version": "0.0.9
|
|
4
|
+
"version": "0.0.9",
|
|
5
5
|
"author": "provishalk",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mailmodo": "bin/run.js"
|
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
"@oclif/plugin-plugins": "^5",
|
|
15
15
|
"chalk": "^5.6.2",
|
|
16
16
|
"js-yaml": "^4.1.1",
|
|
17
|
-
"open": "^11.0.0"
|
|
18
|
-
"ora": "^9.3.0"
|
|
17
|
+
"open": "^11.0.0"
|
|
19
18
|
},
|
|
20
19
|
"devDependencies": {
|
|
21
20
|
"@eslint/compat": "^1",
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from '../../lib/base-command.js';
|
|
2
|
-
export default class Logout extends BaseCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
-
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
-
};
|
|
9
|
-
run(): Promise<void>;
|
|
10
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { BaseCommand } from '../../lib/base-command.js';
|
|
3
|
-
import { clearConfig, loadConfig } from '../../lib/config.js';
|
|
4
|
-
export default class Logout extends BaseCommand {
|
|
5
|
-
static description = 'Sign out by removing saved credentials from this machine';
|
|
6
|
-
static examples = ['<%= config.bin %> logout'];
|
|
7
|
-
static flags = {
|
|
8
|
-
...BaseCommand.baseFlags,
|
|
9
|
-
};
|
|
10
|
-
async run() {
|
|
11
|
-
const { flags } = await this.parse(Logout);
|
|
12
|
-
const config = await loadConfig();
|
|
13
|
-
if (!config?.apiKey) {
|
|
14
|
-
if (flags.json) {
|
|
15
|
-
this.log(JSON.stringify({ status: 'not_logged_in' }, null, 2));
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
this.log('You are not logged in.');
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
await clearConfig();
|
|
22
|
-
if (flags.json) {
|
|
23
|
-
this.log(JSON.stringify({ status: 'logged_out' }, null, 2));
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
this.log(`\n Signed out. Run ${chalk.cyan('mailmodo login')} to authenticate again.\n`);
|
|
27
|
-
}
|
|
28
|
-
}
|