@mailmodo/cli 0.0.17 → 0.0.18-beta.pr20.29
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.
|
@@ -6,7 +6,10 @@ import { API_ENDPOINTS } from '../../lib/constants.js';
|
|
|
6
6
|
import { loadTemplate, saveTemplate, saveYaml, } from '../../lib/yaml-config.js';
|
|
7
7
|
export default class Edit extends BaseCommand {
|
|
8
8
|
static args = {
|
|
9
|
-
id: Args.string({
|
|
9
|
+
id: Args.string({
|
|
10
|
+
description: 'Email template ID to edit',
|
|
11
|
+
required: true,
|
|
12
|
+
}),
|
|
10
13
|
};
|
|
11
14
|
static description = 'Edit an email using AI-assisted natural language changes';
|
|
12
15
|
static examples = [
|
|
@@ -19,27 +19,30 @@ export default class Emails extends BaseCommand {
|
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
21
|
this.log(`\n ${chalk.bold(String(emails.length))} emails configured in mailmodo.yaml:\n`);
|
|
22
|
-
const
|
|
23
|
-
const
|
|
22
|
+
const idColW = Math.max(...emails.map((e) => e.id.length), 'ID'.length) + 2;
|
|
23
|
+
const triggerColW = Math.max(...emails.map((e) => e.trigger.length), 'Trigger'.length) + 2;
|
|
24
|
+
const delayColW = Math.max(...emails.map((e) => String(e.delay).length), 'Delay'.length) +
|
|
25
|
+
2;
|
|
26
|
+
const hasConditions = emails.some((e) => e.condition);
|
|
27
|
+
this.log(` ${chalk.bold('ID'.padEnd(idColW))}${chalk.bold('Trigger'.padEnd(triggerColW))}${chalk.bold('Delay'.padEnd(delayColW))}${hasConditions ? chalk.bold('Condition') : ''}`);
|
|
28
|
+
this.log(` ${'─'.repeat(idColW + triggerColW + delayColW + (hasConditions ? 'Condition'.length : 0))}`);
|
|
24
29
|
for (const email of emails) {
|
|
25
|
-
const id = email.id.padEnd(
|
|
26
|
-
const trigger =
|
|
27
|
-
const delay =
|
|
28
|
-
const condition = email.condition
|
|
29
|
-
|
|
30
|
-
: '';
|
|
31
|
-
this.log(` ${chalk.cyan(id)} ${trigger} ${delay}${condition}`);
|
|
30
|
+
const id = chalk.cyan(email.id.padEnd(idColW));
|
|
31
|
+
const trigger = email.trigger.padEnd(triggerColW);
|
|
32
|
+
const delay = String(email.delay).padEnd(delayColW);
|
|
33
|
+
const condition = email.condition ? chalk.dim(email.condition) : '';
|
|
34
|
+
this.log(` ${id}${trigger}${delay}${condition}`);
|
|
32
35
|
}
|
|
33
36
|
this.log('');
|
|
34
37
|
if (!flags.yes) {
|
|
35
|
-
const
|
|
38
|
+
const templateId = await input({
|
|
36
39
|
default: 'n',
|
|
37
40
|
message: "View an email? (id or 'n'):",
|
|
38
41
|
});
|
|
39
|
-
if (
|
|
40
|
-
const email = emails.find((e) => e.id ===
|
|
42
|
+
if (templateId !== 'n') {
|
|
43
|
+
const email = emails.find((e) => e.id === templateId);
|
|
41
44
|
if (!email) {
|
|
42
|
-
this.log(`\n
|
|
45
|
+
this.log(`\n Template '${templateId}' not found.\n`);
|
|
43
46
|
return;
|
|
44
47
|
}
|
|
45
48
|
this.log('');
|
|
@@ -40,11 +40,11 @@ export default class Logs extends BaseCommand {
|
|
|
40
40
|
if (entries?.length) {
|
|
41
41
|
for (const entry of entries) {
|
|
42
42
|
const time = (entry.timestamp || '').padEnd(18);
|
|
43
|
-
const
|
|
43
|
+
const templateId = (entry.emailId || '').padEnd(24);
|
|
44
44
|
const statusColor = this.statusColor(entry.status);
|
|
45
45
|
const status = statusColor((entry.status || '').padEnd(10));
|
|
46
46
|
const contact = entry.contact || '';
|
|
47
|
-
this.log(` ${time}${
|
|
47
|
+
this.log(` ${time}${templateId}${status}${contact}`);
|
|
48
48
|
if (entry.reason) {
|
|
49
49
|
this.log(` ${' '.repeat(52)}${chalk.dim(`(reason: ${entry.reason})`)}`);
|
|
50
50
|
}
|
|
@@ -52,7 +52,7 @@ function htmlToText(html) {
|
|
|
52
52
|
}
|
|
53
53
|
export default class Preview extends BaseCommand {
|
|
54
54
|
static args = {
|
|
55
|
-
id: Args.string({ description: 'Email ID to preview' }),
|
|
55
|
+
id: Args.string({ description: 'Email template ID to preview' }),
|
|
56
56
|
};
|
|
57
57
|
static description = 'Preview an email in browser, as text, or send a test';
|
|
58
58
|
static examples = [
|
|
@@ -71,13 +71,13 @@ export default class Preview extends BaseCommand {
|
|
|
71
71
|
async run() {
|
|
72
72
|
const { args, flags } = await this.parse(Preview);
|
|
73
73
|
const yamlConfig = await this.ensureYaml();
|
|
74
|
-
const
|
|
75
|
-
if (!
|
|
74
|
+
const templateId = args.id || yamlConfig.emails[0]?.id;
|
|
75
|
+
if (!templateId) {
|
|
76
76
|
this.error('No emails configured. Run mailmodo init first.');
|
|
77
77
|
}
|
|
78
|
-
const email = yamlConfig.emails.find((e) => e.id ===
|
|
78
|
+
const email = yamlConfig.emails.find((e) => e.id === templateId);
|
|
79
79
|
if (!email) {
|
|
80
|
-
this.error(`
|
|
80
|
+
this.error(`Template '${templateId}' not found in mailmodo.yaml.`);
|
|
81
81
|
}
|
|
82
82
|
const sampleData = {
|
|
83
83
|
...SAMPLE_DATA,
|
|
@@ -85,7 +85,7 @@ export default class Preview extends BaseCommand {
|
|
|
85
85
|
product_name: yamlConfig.project?.name || 'YourApp', // eslint-disable-line camelcase
|
|
86
86
|
};
|
|
87
87
|
if (flags.send) {
|
|
88
|
-
await this.sendTestEmail(
|
|
88
|
+
await this.sendTestEmail(templateId, flags.send, flags.json);
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
91
|
const templateHtml = await loadTemplate(`${email.id}.html`);
|
|
@@ -123,16 +123,16 @@ export default class Preview extends BaseCommand {
|
|
|
123
123
|
* Calls the API to send a test email to the specified address.
|
|
124
124
|
* Before domain verification, tests send via the mailmodo.com domain.
|
|
125
125
|
*/
|
|
126
|
-
async sendTestEmail(
|
|
126
|
+
async sendTestEmail(templateId, toAddress, jsonOutput) {
|
|
127
127
|
await this.ensureAuth();
|
|
128
|
-
const response = await this.withApiSpinner({ json: jsonOutput, text: ' Sending test email...' }, () => this.apiClient.post(`${API_ENDPOINTS.PREVIEW}/${
|
|
128
|
+
const response = await this.withApiSpinner({ json: jsonOutput, text: ' Sending test email...' }, () => this.apiClient.post(`${API_ENDPOINTS.PREVIEW}/${templateId}/send`, {
|
|
129
129
|
to: toAddress,
|
|
130
130
|
}));
|
|
131
131
|
if (!response.ok) {
|
|
132
132
|
this.handleApiError(response);
|
|
133
133
|
}
|
|
134
134
|
if (jsonOutput) {
|
|
135
|
-
this.log(JSON.stringify({
|
|
135
|
+
this.log(JSON.stringify({ templateId, sentTo: toAddress, status: 'sent' }, null, 2));
|
|
136
136
|
return;
|
|
137
137
|
}
|
|
138
138
|
this.log(`\n Sending test to ${chalk.cyan(toAddress)}...`);
|
package/oclif.manifest.json
CHANGED
|
@@ -209,7 +209,7 @@
|
|
|
209
209
|
"aliases": [],
|
|
210
210
|
"args": {
|
|
211
211
|
"id": {
|
|
212
|
-
"description": "Email ID to edit",
|
|
212
|
+
"description": "Email template ID to edit",
|
|
213
213
|
"name": "id",
|
|
214
214
|
"required": true
|
|
215
215
|
}
|
|
@@ -419,15 +419,19 @@
|
|
|
419
419
|
"index.js"
|
|
420
420
|
]
|
|
421
421
|
},
|
|
422
|
-
"
|
|
422
|
+
"preview": {
|
|
423
423
|
"aliases": [],
|
|
424
|
-
"args": {
|
|
425
|
-
|
|
424
|
+
"args": {
|
|
425
|
+
"id": {
|
|
426
|
+
"description": "Email template ID to preview",
|
|
427
|
+
"name": "id"
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
"description": "Preview an email in browser, as text, or send a test",
|
|
426
431
|
"examples": [
|
|
427
|
-
"<%= config.bin %>
|
|
428
|
-
"<%= config.bin %>
|
|
429
|
-
"<%= config.bin %>
|
|
430
|
-
"<%= config.bin %> logs --json"
|
|
432
|
+
"<%= config.bin %> preview welcome",
|
|
433
|
+
"<%= config.bin %> preview welcome --text",
|
|
434
|
+
"<%= config.bin %> preview welcome --send me@example.com"
|
|
431
435
|
],
|
|
432
436
|
"flags": {
|
|
433
437
|
"json": {
|
|
@@ -443,23 +447,23 @@
|
|
|
443
447
|
"allowNo": false,
|
|
444
448
|
"type": "boolean"
|
|
445
449
|
},
|
|
446
|
-
"
|
|
447
|
-
"description": "
|
|
448
|
-
"name": "
|
|
450
|
+
"send": {
|
|
451
|
+
"description": "Send test email to this address",
|
|
452
|
+
"name": "send",
|
|
449
453
|
"hasDynamicHelp": false,
|
|
450
454
|
"multiple": false,
|
|
451
455
|
"type": "option"
|
|
452
456
|
},
|
|
453
|
-
"
|
|
454
|
-
"description": "
|
|
455
|
-
"name": "
|
|
457
|
+
"text": {
|
|
458
|
+
"description": "Output plain text version (for AI agents)",
|
|
459
|
+
"name": "text",
|
|
456
460
|
"allowNo": false,
|
|
457
461
|
"type": "boolean"
|
|
458
462
|
}
|
|
459
463
|
},
|
|
460
464
|
"hasDynamicHelp": false,
|
|
461
465
|
"hiddenAliases": [],
|
|
462
|
-
"id": "
|
|
466
|
+
"id": "preview",
|
|
463
467
|
"pluginAlias": "@mailmodo/cli",
|
|
464
468
|
"pluginName": "@mailmodo/cli",
|
|
465
469
|
"pluginType": "core",
|
|
@@ -469,23 +473,19 @@
|
|
|
469
473
|
"relativePath": [
|
|
470
474
|
"dist",
|
|
471
475
|
"commands",
|
|
472
|
-
"
|
|
476
|
+
"preview",
|
|
473
477
|
"index.js"
|
|
474
478
|
]
|
|
475
479
|
},
|
|
476
|
-
"
|
|
480
|
+
"logs": {
|
|
477
481
|
"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",
|
|
482
|
+
"args": {},
|
|
483
|
+
"description": "View email send logs and delivery events",
|
|
485
484
|
"examples": [
|
|
486
|
-
"<%= config.bin %>
|
|
487
|
-
"<%= config.bin %>
|
|
488
|
-
"<%= config.bin %>
|
|
485
|
+
"<%= config.bin %> logs",
|
|
486
|
+
"<%= config.bin %> logs --email sarah@example.com",
|
|
487
|
+
"<%= config.bin %> logs --failed",
|
|
488
|
+
"<%= config.bin %> logs --json"
|
|
489
489
|
],
|
|
490
490
|
"flags": {
|
|
491
491
|
"json": {
|
|
@@ -501,23 +501,23 @@
|
|
|
501
501
|
"allowNo": false,
|
|
502
502
|
"type": "boolean"
|
|
503
503
|
},
|
|
504
|
-
"
|
|
505
|
-
"description": "
|
|
506
|
-
"name": "
|
|
504
|
+
"email": {
|
|
505
|
+
"description": "Filter logs by contact email",
|
|
506
|
+
"name": "email",
|
|
507
507
|
"hasDynamicHelp": false,
|
|
508
508
|
"multiple": false,
|
|
509
509
|
"type": "option"
|
|
510
510
|
},
|
|
511
|
-
"
|
|
512
|
-
"description": "
|
|
513
|
-
"name": "
|
|
511
|
+
"failed": {
|
|
512
|
+
"description": "Show only failed/bounced events",
|
|
513
|
+
"name": "failed",
|
|
514
514
|
"allowNo": false,
|
|
515
515
|
"type": "boolean"
|
|
516
516
|
}
|
|
517
517
|
},
|
|
518
518
|
"hasDynamicHelp": false,
|
|
519
519
|
"hiddenAliases": [],
|
|
520
|
-
"id": "
|
|
520
|
+
"id": "logs",
|
|
521
521
|
"pluginAlias": "@mailmodo/cli",
|
|
522
522
|
"pluginName": "@mailmodo/cli",
|
|
523
523
|
"pluginType": "core",
|
|
@@ -527,7 +527,7 @@
|
|
|
527
527
|
"relativePath": [
|
|
528
528
|
"dist",
|
|
529
529
|
"commands",
|
|
530
|
-
"
|
|
530
|
+
"logs",
|
|
531
531
|
"index.js"
|
|
532
532
|
]
|
|
533
533
|
},
|
|
@@ -618,5 +618,5 @@
|
|
|
618
618
|
]
|
|
619
619
|
}
|
|
620
620
|
},
|
|
621
|
-
"version": "0.0.
|
|
621
|
+
"version": "0.0.18-beta.pr20.29"
|
|
622
622
|
}
|
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.
|
|
4
|
+
"version": "0.0.18-beta.pr20.29",
|
|
5
5
|
"author": "provishalk",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mailmodo": "bin/run.js"
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"@inquirer/prompts": "^8.3.2",
|
|
12
12
|
"@oclif/core": "^4",
|
|
13
13
|
"@oclif/plugin-help": "^6",
|
|
14
|
+
"@oclif/plugin-not-found": "^3",
|
|
14
15
|
"@oclif/plugin-plugins": "^5",
|
|
15
16
|
"chalk": "^5.6.2",
|
|
16
17
|
"js-yaml": "^4.1.1",
|
|
@@ -61,6 +62,7 @@
|
|
|
61
62
|
"commands": "./dist/commands",
|
|
62
63
|
"plugins": [
|
|
63
64
|
"@oclif/plugin-help",
|
|
65
|
+
"@oclif/plugin-not-found",
|
|
64
66
|
"@oclif/plugin-plugins"
|
|
65
67
|
],
|
|
66
68
|
"topicSeparator": " "
|