@mailmodo/cli 0.0.36 → 0.0.37
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.d.ts +1 -0
- package/dist/commands/billing/index.js +43 -33
- package/dist/commands/settings/index.d.ts +1 -0
- package/dist/commands/settings/index.js +28 -4
- package/dist/lib/base-command.d.ts +17 -0
- package/dist/lib/base-command.js +26 -0
- package/oclif.manifest.json +96 -96
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import open from 'open';
|
|
|
4
4
|
import { BaseCommand } from '../../lib/base-command.js';
|
|
5
5
|
import { API_ENDPOINTS } from '../../lib/constants.js';
|
|
6
6
|
import { INFO } from '../../lib/messages.js';
|
|
7
|
+
import { loadYaml, saveYaml } from '../../lib/yaml-config.js';
|
|
7
8
|
export default class Billing extends BaseCommand {
|
|
8
9
|
static description = 'View billing status, purchase blocks, set cap, or add a payment method';
|
|
9
10
|
static examples = [
|
|
@@ -89,18 +90,23 @@ export default class Billing extends BaseCommand {
|
|
|
89
90
|
this.log(` Tier: ${data.tier}`);
|
|
90
91
|
this.log(` Payment: ${this.formatPaymentMethod(data)}`);
|
|
91
92
|
this.log(` Auto-charge: ${this.formatAutoCharge(data)}`);
|
|
92
|
-
|
|
93
|
+
if (data.tier !== 'free') {
|
|
94
|
+
this.log(` Monthly cap: ${this.formatCap(data.cap)}`);
|
|
95
|
+
}
|
|
93
96
|
this.log(` Total spent: ${this.formatCurrency(data.totalSpent, data.spentCurrency)}`);
|
|
94
97
|
if (data.activeBlocks.length === 0) {
|
|
95
98
|
this.log(' Active blocks: none');
|
|
96
|
-
this.log('');
|
|
97
|
-
return;
|
|
98
99
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
else {
|
|
101
|
+
this.log(' Active blocks:');
|
|
102
|
+
for (const block of data.activeBlocks) {
|
|
103
|
+
this.log(` - ${this.formatUsageBlock(block)}`);
|
|
104
|
+
}
|
|
102
105
|
}
|
|
103
106
|
this.log('');
|
|
107
|
+
if (!data.hasPaymentMethod) {
|
|
108
|
+
await this.startCheckout(jsonOutput);
|
|
109
|
+
}
|
|
104
110
|
}
|
|
105
111
|
formatAutoCharge(data) {
|
|
106
112
|
if (!data.autoChargeEnabled) {
|
|
@@ -112,14 +118,18 @@ export default class Billing extends BaseCommand {
|
|
|
112
118
|
return `enabled (${data.autoChargeBlockCount} ${this.pluralize('block', data.autoChargeBlockCount)})`;
|
|
113
119
|
}
|
|
114
120
|
formatCap(cap) {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
const hasBlocks = typeof cap.inBlocks === 'number';
|
|
122
|
+
const hasEmails = typeof cap.inEmails === 'number';
|
|
123
|
+
if (hasBlocks && hasEmails) {
|
|
124
|
+
return `${cap.inBlocks} ${this.pluralize('block', cap.inBlocks)} (${cap.inEmails.toLocaleString()} ${this.pluralize('email', cap.inEmails)})`;
|
|
118
125
|
}
|
|
119
|
-
if (
|
|
120
|
-
|
|
126
|
+
if (hasBlocks) {
|
|
127
|
+
return `${cap.inBlocks} ${this.pluralize('block', cap.inBlocks)}`;
|
|
121
128
|
}
|
|
122
|
-
|
|
129
|
+
if (hasEmails) {
|
|
130
|
+
return `${cap.inEmails.toLocaleString()} ${this.pluralize('email', cap.inEmails)}`;
|
|
131
|
+
}
|
|
132
|
+
return 'not set';
|
|
123
133
|
}
|
|
124
134
|
formatCurrency(amount, currency) {
|
|
125
135
|
const numericAmount = typeof amount === 'number' ? amount : Number.parseFloat(amount);
|
|
@@ -154,9 +164,18 @@ export default class Billing extends BaseCommand {
|
|
|
154
164
|
const allowance = block.blockAllowance ?? Math.max(block.blocksCount * block.blockSize, 0);
|
|
155
165
|
const used = Math.max(block.emailsSent ?? 0, 0);
|
|
156
166
|
const activationSuffix = block.activatedAt
|
|
157
|
-
? `, activated ${new Date(block.activatedAt).toLocaleDateString('en-US')}`
|
|
167
|
+
? `, activated at ${new Date(block.activatedAt).toLocaleDateString('en-US')}`
|
|
158
168
|
: '';
|
|
159
|
-
return `${block.type} block: ${used.
|
|
169
|
+
return `${block.type} block (${used + allowance}): ${used} ${this.pluralize('email', used)} sent, ${allowance} ${this.pluralize('email', allowance)} remaining${activationSuffix}`;
|
|
170
|
+
}
|
|
171
|
+
async persistMonthlyCap(capBlocks) {
|
|
172
|
+
const yamlConfig = await loadYaml();
|
|
173
|
+
if (!yamlConfig)
|
|
174
|
+
return;
|
|
175
|
+
if (yamlConfig.project.monthlyCap === capBlocks)
|
|
176
|
+
return;
|
|
177
|
+
yamlConfig.project.monthlyCap = capBlocks;
|
|
178
|
+
await saveYaml(yamlConfig);
|
|
160
179
|
}
|
|
161
180
|
pluralize(word, count) {
|
|
162
181
|
return count === 1 ? word : `${word}s`;
|
|
@@ -181,29 +200,20 @@ export default class Billing extends BaseCommand {
|
|
|
181
200
|
this.log('');
|
|
182
201
|
}
|
|
183
202
|
async setCap(cap, autoChargeBlockCount, jsonOutput) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
this.error('Auto-charge block count must be at least 1 block.');
|
|
189
|
-
}
|
|
190
|
-
const response = await this.withApiSpinner({ json: jsonOutput, text: ' Updating spending cap...' }, () => {
|
|
191
|
-
const payload = autoChargeBlockCount === undefined
|
|
192
|
-
? { cap }
|
|
193
|
-
: { autoChargeBlockCount, cap };
|
|
194
|
-
return this.apiClient.post(API_ENDPOINTS.BILLING_CAP, payload);
|
|
203
|
+
const data = await this.applyBillingCap({
|
|
204
|
+
autoChargeBlockCount,
|
|
205
|
+
cap,
|
|
206
|
+
json: jsonOutput,
|
|
195
207
|
});
|
|
196
|
-
|
|
197
|
-
this.handleApiError(response);
|
|
198
|
-
}
|
|
208
|
+
await this.persistMonthlyCap(data.capBlocks);
|
|
199
209
|
if (jsonOutput) {
|
|
200
|
-
this.log(JSON.stringify(
|
|
210
|
+
this.log(JSON.stringify(data, null, 2));
|
|
201
211
|
return;
|
|
202
212
|
}
|
|
203
|
-
this.log(`\n ${chalk.green('✓')} ${
|
|
204
|
-
this.log(` Monthly cap: ${chalk.bold(String(
|
|
205
|
-
if (
|
|
206
|
-
this.log(` Auto-charge: ${
|
|
213
|
+
this.log(`\n ${chalk.green('✓')} ${data.message}`);
|
|
214
|
+
this.log(` Monthly cap: ${chalk.bold(String(data.capBlocks))} ${this.pluralize('block', data.capBlocks)} (${data.capEmails.toLocaleString()} emails)`);
|
|
215
|
+
if (data.autoChargeBlockCount !== undefined) {
|
|
216
|
+
this.log(` Auto-charge: ${data.autoChargeBlockCount} ${this.pluralize('block', data.autoChargeBlockCount)}`);
|
|
207
217
|
}
|
|
208
218
|
this.log('');
|
|
209
219
|
}
|
|
@@ -73,8 +73,11 @@ export default class Settings extends BaseCommand {
|
|
|
73
73
|
if (!(propKey in project) && key !== 'logo_file') {
|
|
74
74
|
this.error(`Unknown setting: ${key}`);
|
|
75
75
|
}
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
if (propKey === 'monthlyCap') {
|
|
77
|
+
await this.applyMonthlyCapChange(yamlConfig, value, isJson);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
project[propKey] = value;
|
|
78
81
|
await saveYaml(yamlConfig);
|
|
79
82
|
if (isJson) {
|
|
80
83
|
this.log(JSON.stringify({ [propKey]: value, status: 'updated' }, null, 2));
|
|
@@ -83,6 +86,21 @@ export default class Settings extends BaseCommand {
|
|
|
83
86
|
this.log(`\n ${chalk.green('✓')} ${key} updated to ${chalk.cyan(value)}`);
|
|
84
87
|
this.log(` ${INFO.DEPLOY_TO_APPLY}\n`);
|
|
85
88
|
}
|
|
89
|
+
async applyMonthlyCapChange(yamlConfig, rawValue, isJson) {
|
|
90
|
+
const parsed = Number(rawValue);
|
|
91
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
92
|
+
this.error('monthly_cap must be a positive integer (blocks).');
|
|
93
|
+
}
|
|
94
|
+
await this.ensureAuth();
|
|
95
|
+
const data = await this.applyBillingCap({ cap: parsed, json: isJson });
|
|
96
|
+
yamlConfig.project.monthlyCap = data.capBlocks;
|
|
97
|
+
await saveYaml(yamlConfig);
|
|
98
|
+
if (isJson) {
|
|
99
|
+
this.log(JSON.stringify({ monthlyCap: data.capBlocks, status: 'updated' }, null, 2));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
this.log(`\n ${chalk.green('✓')} monthly_cap updated to ${chalk.cyan(String(data.capBlocks))} (${data.capEmails.toLocaleString()} emails)\n`);
|
|
103
|
+
}
|
|
86
104
|
displaySettingsGroup(group, keys, project, domainVerified) {
|
|
87
105
|
const availableKeys = keys.filter((key) => {
|
|
88
106
|
if (group === 'brand' && key === 'logo_file')
|
|
@@ -159,6 +177,13 @@ export default class Settings extends BaseCommand {
|
|
|
159
177
|
await this.handleDomainChange(yamlConfig);
|
|
160
178
|
return;
|
|
161
179
|
}
|
|
180
|
+
if (editKey === 'monthly_cap') {
|
|
181
|
+
const newValue = await input({
|
|
182
|
+
message: 'New monthly cap (blocks):',
|
|
183
|
+
});
|
|
184
|
+
await this.applyMonthlyCapChange(yamlConfig, newValue, false);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
162
187
|
if (editKey === 'email_style') {
|
|
163
188
|
const style = await select({
|
|
164
189
|
choices: [
|
|
@@ -176,8 +201,7 @@ export default class Settings extends BaseCommand {
|
|
|
176
201
|
const newValue = await input({
|
|
177
202
|
message: `New value for ${editKey}:`,
|
|
178
203
|
});
|
|
179
|
-
project[editPropKey] =
|
|
180
|
-
editPropKey === 'monthlyCap' ? Number(newValue) : newValue;
|
|
204
|
+
project[editPropKey] = newValue;
|
|
181
205
|
await saveYaml(yamlConfig);
|
|
182
206
|
this.log(`\n ${chalk.green('✓')} Updated. ${INFO.DEPLOY_TO_APPLY}\n`);
|
|
183
207
|
}
|
|
@@ -2,6 +2,12 @@ import { Command } from '@oclif/core';
|
|
|
2
2
|
import { ApiClient, type ApiRequestDebugInfo } from './api-client.js';
|
|
3
3
|
import { type MailmodoConfig } from './config.js';
|
|
4
4
|
import { type MailmodoYaml } from './yaml-config.js';
|
|
5
|
+
export interface BillingCapUpdateResult {
|
|
6
|
+
autoChargeBlockCount?: number;
|
|
7
|
+
capBlocks: number;
|
|
8
|
+
capEmails: number;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
5
11
|
/**
|
|
6
12
|
* Abstract base command providing shared functionality for all Mailmodo CLI commands.
|
|
7
13
|
* Subclasses inherit --json and --yes base flags, authentication enforcement,
|
|
@@ -68,6 +74,17 @@ export declare abstract class BaseCommand extends Command {
|
|
|
68
74
|
fromName: string;
|
|
69
75
|
replyTo: string;
|
|
70
76
|
}>;
|
|
77
|
+
/**
|
|
78
|
+
* Updates the account's monthly sending cap on the server.
|
|
79
|
+
* Validates inputs, wraps the POST /billing/cap call in a spinner, and
|
|
80
|
+
* surfaces errors via handleApiError. The caller is responsible for any
|
|
81
|
+
* local persistence (e.g. writing `monthlyCap` to mailmodo.yaml).
|
|
82
|
+
*/
|
|
83
|
+
protected applyBillingCap(options: {
|
|
84
|
+
autoChargeBlockCount?: number;
|
|
85
|
+
cap: number;
|
|
86
|
+
json: boolean;
|
|
87
|
+
}): Promise<BillingCapUpdateResult>;
|
|
71
88
|
protected registerDomain(yamlConfig: MailmodoYaml, inputs: {
|
|
72
89
|
address: string;
|
|
73
90
|
domain: string;
|
package/dist/lib/base-command.js
CHANGED
|
@@ -145,6 +145,32 @@ export class BaseCommand extends Command {
|
|
|
145
145
|
});
|
|
146
146
|
return { address, domain, fromEmail, fromName, replyTo };
|
|
147
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Updates the account's monthly sending cap on the server.
|
|
150
|
+
* Validates inputs, wraps the POST /billing/cap call in a spinner, and
|
|
151
|
+
* surfaces errors via handleApiError. The caller is responsible for any
|
|
152
|
+
* local persistence (e.g. writing `monthlyCap` to mailmodo.yaml).
|
|
153
|
+
*/
|
|
154
|
+
async applyBillingCap(options) {
|
|
155
|
+
if (options.cap < 1) {
|
|
156
|
+
this.error('Cap must be at least 1 block.');
|
|
157
|
+
}
|
|
158
|
+
if (options.autoChargeBlockCount !== undefined &&
|
|
159
|
+
options.autoChargeBlockCount < 1) {
|
|
160
|
+
this.error('Auto-charge block count must be at least 1 block.');
|
|
161
|
+
}
|
|
162
|
+
const payload = options.autoChargeBlockCount === undefined
|
|
163
|
+
? { cap: options.cap }
|
|
164
|
+
: {
|
|
165
|
+
autoChargeBlockCount: options.autoChargeBlockCount,
|
|
166
|
+
cap: options.cap,
|
|
167
|
+
};
|
|
168
|
+
const response = await this.withApiSpinner({ json: options.json, text: ' Updating spending cap...' }, () => this.apiClient.post(API_ENDPOINTS.BILLING_CAP, payload));
|
|
169
|
+
if (!response.ok) {
|
|
170
|
+
this.handleApiError(response);
|
|
171
|
+
}
|
|
172
|
+
return response.data;
|
|
173
|
+
}
|
|
148
174
|
async registerDomain(yamlConfig, inputs, json) {
|
|
149
175
|
const apiPayload = {
|
|
150
176
|
address: inputs.address,
|
package/oclif.manifest.json
CHANGED
|
@@ -137,13 +137,14 @@
|
|
|
137
137
|
"index.js"
|
|
138
138
|
]
|
|
139
139
|
},
|
|
140
|
-
"
|
|
140
|
+
"domain": {
|
|
141
141
|
"aliases": [],
|
|
142
142
|
"args": {},
|
|
143
|
-
"description": "
|
|
143
|
+
"description": "Set up and verify your sending domain",
|
|
144
144
|
"examples": [
|
|
145
|
-
"<%= config.bin %>
|
|
146
|
-
"<%= config.bin %>
|
|
145
|
+
"<%= config.bin %> domain",
|
|
146
|
+
"<%= config.bin %> domain --verify",
|
|
147
|
+
"<%= config.bin %> domain --status"
|
|
147
148
|
],
|
|
148
149
|
"flags": {
|
|
149
150
|
"json": {
|
|
@@ -158,11 +159,23 @@
|
|
|
158
159
|
"name": "yes",
|
|
159
160
|
"allowNo": false,
|
|
160
161
|
"type": "boolean"
|
|
162
|
+
},
|
|
163
|
+
"status": {
|
|
164
|
+
"description": "Show domain health status",
|
|
165
|
+
"name": "status",
|
|
166
|
+
"allowNo": false,
|
|
167
|
+
"type": "boolean"
|
|
168
|
+
},
|
|
169
|
+
"verify": {
|
|
170
|
+
"description": "Verify DNS records",
|
|
171
|
+
"name": "verify",
|
|
172
|
+
"allowNo": false,
|
|
173
|
+
"type": "boolean"
|
|
161
174
|
}
|
|
162
175
|
},
|
|
163
176
|
"hasDynamicHelp": false,
|
|
164
177
|
"hiddenAliases": [],
|
|
165
|
-
"id": "
|
|
178
|
+
"id": "domain",
|
|
166
179
|
"pluginAlias": "@mailmodo/cli",
|
|
167
180
|
"pluginName": "@mailmodo/cli",
|
|
168
181
|
"pluginType": "core",
|
|
@@ -172,18 +185,17 @@
|
|
|
172
185
|
"relativePath": [
|
|
173
186
|
"dist",
|
|
174
187
|
"commands",
|
|
175
|
-
"
|
|
188
|
+
"domain",
|
|
176
189
|
"index.js"
|
|
177
190
|
]
|
|
178
191
|
},
|
|
179
|
-
"
|
|
192
|
+
"deploy": {
|
|
180
193
|
"aliases": [],
|
|
181
194
|
"args": {},
|
|
182
|
-
"description": "
|
|
195
|
+
"description": "Deploy email sequences and verify sending domain",
|
|
183
196
|
"examples": [
|
|
184
|
-
"<%= config.bin %>
|
|
185
|
-
"<%= config.bin %>
|
|
186
|
-
"<%= config.bin %> domain --status"
|
|
197
|
+
"<%= config.bin %> deploy",
|
|
198
|
+
"<%= config.bin %> deploy --yes"
|
|
187
199
|
],
|
|
188
200
|
"flags": {
|
|
189
201
|
"json": {
|
|
@@ -198,23 +210,11 @@
|
|
|
198
210
|
"name": "yes",
|
|
199
211
|
"allowNo": false,
|
|
200
212
|
"type": "boolean"
|
|
201
|
-
},
|
|
202
|
-
"status": {
|
|
203
|
-
"description": "Show domain health status",
|
|
204
|
-
"name": "status",
|
|
205
|
-
"allowNo": false,
|
|
206
|
-
"type": "boolean"
|
|
207
|
-
},
|
|
208
|
-
"verify": {
|
|
209
|
-
"description": "Verify DNS records",
|
|
210
|
-
"name": "verify",
|
|
211
|
-
"allowNo": false,
|
|
212
|
-
"type": "boolean"
|
|
213
213
|
}
|
|
214
214
|
},
|
|
215
215
|
"hasDynamicHelp": false,
|
|
216
216
|
"hiddenAliases": [],
|
|
217
|
-
"id": "
|
|
217
|
+
"id": "deploy",
|
|
218
218
|
"pluginAlias": "@mailmodo/cli",
|
|
219
219
|
"pluginName": "@mailmodo/cli",
|
|
220
220
|
"pluginType": "core",
|
|
@@ -224,23 +224,17 @@
|
|
|
224
224
|
"relativePath": [
|
|
225
225
|
"dist",
|
|
226
226
|
"commands",
|
|
227
|
-
"
|
|
227
|
+
"deploy",
|
|
228
228
|
"index.js"
|
|
229
229
|
]
|
|
230
230
|
},
|
|
231
|
-
"
|
|
231
|
+
"emails": {
|
|
232
232
|
"aliases": [],
|
|
233
|
-
"args": {
|
|
234
|
-
|
|
235
|
-
"description": "Email template ID to edit",
|
|
236
|
-
"name": "id",
|
|
237
|
-
"required": true
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
"description": "Edit an email using AI-assisted natural language changes",
|
|
233
|
+
"args": {},
|
|
234
|
+
"description": "List and view configured email sequences",
|
|
241
235
|
"examples": [
|
|
242
|
-
"<%= config.bin %>
|
|
243
|
-
"<%= config.bin %>
|
|
236
|
+
"<%= config.bin %> emails",
|
|
237
|
+
"<%= config.bin %> emails --json"
|
|
244
238
|
],
|
|
245
239
|
"flags": {
|
|
246
240
|
"json": {
|
|
@@ -255,18 +249,11 @@
|
|
|
255
249
|
"name": "yes",
|
|
256
250
|
"allowNo": false,
|
|
257
251
|
"type": "boolean"
|
|
258
|
-
},
|
|
259
|
-
"change": {
|
|
260
|
-
"description": "Natural language description of the change",
|
|
261
|
-
"name": "change",
|
|
262
|
-
"hasDynamicHelp": false,
|
|
263
|
-
"multiple": false,
|
|
264
|
-
"type": "option"
|
|
265
252
|
}
|
|
266
253
|
},
|
|
267
254
|
"hasDynamicHelp": false,
|
|
268
255
|
"hiddenAliases": [],
|
|
269
|
-
"id": "
|
|
256
|
+
"id": "emails",
|
|
270
257
|
"pluginAlias": "@mailmodo/cli",
|
|
271
258
|
"pluginName": "@mailmodo/cli",
|
|
272
259
|
"pluginType": "core",
|
|
@@ -276,17 +263,23 @@
|
|
|
276
263
|
"relativePath": [
|
|
277
264
|
"dist",
|
|
278
265
|
"commands",
|
|
279
|
-
"
|
|
266
|
+
"emails",
|
|
280
267
|
"index.js"
|
|
281
268
|
]
|
|
282
269
|
},
|
|
283
|
-
"
|
|
270
|
+
"edit": {
|
|
284
271
|
"aliases": [],
|
|
285
|
-
"args": {
|
|
286
|
-
|
|
272
|
+
"args": {
|
|
273
|
+
"id": {
|
|
274
|
+
"description": "Email template ID to edit",
|
|
275
|
+
"name": "id",
|
|
276
|
+
"required": true
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
"description": "Edit an email using AI-assisted natural language changes",
|
|
287
280
|
"examples": [
|
|
288
|
-
"<%= config.bin %>
|
|
289
|
-
"<%= config.bin %>
|
|
281
|
+
"<%= config.bin %> edit welcome",
|
|
282
|
+
"<%= config.bin %> edit welcome --change \"make subject more urgent\" --yes"
|
|
290
283
|
],
|
|
291
284
|
"flags": {
|
|
292
285
|
"json": {
|
|
@@ -301,11 +294,18 @@
|
|
|
301
294
|
"name": "yes",
|
|
302
295
|
"allowNo": false,
|
|
303
296
|
"type": "boolean"
|
|
297
|
+
},
|
|
298
|
+
"change": {
|
|
299
|
+
"description": "Natural language description of the change",
|
|
300
|
+
"name": "change",
|
|
301
|
+
"hasDynamicHelp": false,
|
|
302
|
+
"multiple": false,
|
|
303
|
+
"type": "option"
|
|
304
304
|
}
|
|
305
305
|
},
|
|
306
306
|
"hasDynamicHelp": false,
|
|
307
307
|
"hiddenAliases": [],
|
|
308
|
-
"id": "
|
|
308
|
+
"id": "edit",
|
|
309
309
|
"pluginAlias": "@mailmodo/cli",
|
|
310
310
|
"pluginName": "@mailmodo/cli",
|
|
311
311
|
"pluginType": "core",
|
|
@@ -315,7 +315,7 @@
|
|
|
315
315
|
"relativePath": [
|
|
316
316
|
"dist",
|
|
317
317
|
"commands",
|
|
318
|
-
"
|
|
318
|
+
"edit",
|
|
319
319
|
"index.js"
|
|
320
320
|
]
|
|
321
321
|
},
|
|
@@ -512,14 +512,19 @@
|
|
|
512
512
|
"index.js"
|
|
513
513
|
]
|
|
514
514
|
},
|
|
515
|
-
"
|
|
515
|
+
"preview": {
|
|
516
516
|
"aliases": [],
|
|
517
|
-
"args": {
|
|
518
|
-
|
|
517
|
+
"args": {
|
|
518
|
+
"id": {
|
|
519
|
+
"description": "Email template ID to preview",
|
|
520
|
+
"name": "id"
|
|
521
|
+
}
|
|
522
|
+
},
|
|
523
|
+
"description": "Preview an email in browser, as text, or send a test",
|
|
519
524
|
"examples": [
|
|
520
|
-
"<%= config.bin %>
|
|
521
|
-
"<%= config.bin %>
|
|
522
|
-
"<%= config.bin %>
|
|
525
|
+
"<%= config.bin %> preview welcome",
|
|
526
|
+
"<%= config.bin %> preview welcome --text",
|
|
527
|
+
"<%= config.bin %> preview welcome --send me@example.com"
|
|
523
528
|
],
|
|
524
529
|
"flags": {
|
|
525
530
|
"json": {
|
|
@@ -535,17 +540,23 @@
|
|
|
535
540
|
"allowNo": false,
|
|
536
541
|
"type": "boolean"
|
|
537
542
|
},
|
|
538
|
-
"
|
|
539
|
-
"description": "
|
|
540
|
-
"name": "
|
|
543
|
+
"send": {
|
|
544
|
+
"description": "Send test email to this address",
|
|
545
|
+
"name": "send",
|
|
541
546
|
"hasDynamicHelp": false,
|
|
542
547
|
"multiple": false,
|
|
543
548
|
"type": "option"
|
|
549
|
+
},
|
|
550
|
+
"text": {
|
|
551
|
+
"description": "Output plain text version (for AI agents)",
|
|
552
|
+
"name": "text",
|
|
553
|
+
"allowNo": false,
|
|
554
|
+
"type": "boolean"
|
|
544
555
|
}
|
|
545
556
|
},
|
|
546
557
|
"hasDynamicHelp": false,
|
|
547
558
|
"hiddenAliases": [],
|
|
548
|
-
"id": "
|
|
559
|
+
"id": "preview",
|
|
549
560
|
"pluginAlias": "@mailmodo/cli",
|
|
550
561
|
"pluginName": "@mailmodo/cli",
|
|
551
562
|
"pluginType": "core",
|
|
@@ -555,17 +566,18 @@
|
|
|
555
566
|
"relativePath": [
|
|
556
567
|
"dist",
|
|
557
568
|
"commands",
|
|
558
|
-
"
|
|
569
|
+
"preview",
|
|
559
570
|
"index.js"
|
|
560
571
|
]
|
|
561
572
|
},
|
|
562
|
-
"
|
|
573
|
+
"settings": {
|
|
563
574
|
"aliases": [],
|
|
564
575
|
"args": {},
|
|
565
|
-
"description": "View
|
|
576
|
+
"description": "View and update project settings",
|
|
566
577
|
"examples": [
|
|
567
|
-
"<%= config.bin %>
|
|
568
|
-
"<%= config.bin %>
|
|
578
|
+
"<%= config.bin %> settings",
|
|
579
|
+
"<%= config.bin %> settings --set brand_color=#0F3460",
|
|
580
|
+
"<%= config.bin %> settings --json"
|
|
569
581
|
],
|
|
570
582
|
"flags": {
|
|
571
583
|
"json": {
|
|
@@ -580,11 +592,18 @@
|
|
|
580
592
|
"name": "yes",
|
|
581
593
|
"allowNo": false,
|
|
582
594
|
"type": "boolean"
|
|
595
|
+
},
|
|
596
|
+
"set": {
|
|
597
|
+
"description": "Set a setting (format: key=value)",
|
|
598
|
+
"name": "set",
|
|
599
|
+
"hasDynamicHelp": false,
|
|
600
|
+
"multiple": false,
|
|
601
|
+
"type": "option"
|
|
583
602
|
}
|
|
584
603
|
},
|
|
585
604
|
"hasDynamicHelp": false,
|
|
586
605
|
"hiddenAliases": [],
|
|
587
|
-
"id": "
|
|
606
|
+
"id": "settings",
|
|
588
607
|
"pluginAlias": "@mailmodo/cli",
|
|
589
608
|
"pluginName": "@mailmodo/cli",
|
|
590
609
|
"pluginType": "core",
|
|
@@ -594,23 +613,17 @@
|
|
|
594
613
|
"relativePath": [
|
|
595
614
|
"dist",
|
|
596
615
|
"commands",
|
|
597
|
-
"
|
|
616
|
+
"settings",
|
|
598
617
|
"index.js"
|
|
599
618
|
]
|
|
600
619
|
},
|
|
601
|
-
"
|
|
620
|
+
"status": {
|
|
602
621
|
"aliases": [],
|
|
603
|
-
"args": {
|
|
604
|
-
|
|
605
|
-
"description": "Email template ID to preview",
|
|
606
|
-
"name": "id"
|
|
607
|
-
}
|
|
608
|
-
},
|
|
609
|
-
"description": "Preview an email in browser, as text, or send a test",
|
|
622
|
+
"args": {},
|
|
623
|
+
"description": "View email performance metrics and quota usage",
|
|
610
624
|
"examples": [
|
|
611
|
-
"<%= config.bin %>
|
|
612
|
-
"<%= config.bin %>
|
|
613
|
-
"<%= config.bin %> preview welcome --send me@example.com"
|
|
625
|
+
"<%= config.bin %> status",
|
|
626
|
+
"<%= config.bin %> status --json"
|
|
614
627
|
],
|
|
615
628
|
"flags": {
|
|
616
629
|
"json": {
|
|
@@ -625,24 +638,11 @@
|
|
|
625
638
|
"name": "yes",
|
|
626
639
|
"allowNo": false,
|
|
627
640
|
"type": "boolean"
|
|
628
|
-
},
|
|
629
|
-
"send": {
|
|
630
|
-
"description": "Send test email to this address",
|
|
631
|
-
"name": "send",
|
|
632
|
-
"hasDynamicHelp": false,
|
|
633
|
-
"multiple": false,
|
|
634
|
-
"type": "option"
|
|
635
|
-
},
|
|
636
|
-
"text": {
|
|
637
|
-
"description": "Output plain text version (for AI agents)",
|
|
638
|
-
"name": "text",
|
|
639
|
-
"allowNo": false,
|
|
640
|
-
"type": "boolean"
|
|
641
641
|
}
|
|
642
642
|
},
|
|
643
643
|
"hasDynamicHelp": false,
|
|
644
644
|
"hiddenAliases": [],
|
|
645
|
-
"id": "
|
|
645
|
+
"id": "status",
|
|
646
646
|
"pluginAlias": "@mailmodo/cli",
|
|
647
647
|
"pluginName": "@mailmodo/cli",
|
|
648
648
|
"pluginType": "core",
|
|
@@ -652,10 +652,10 @@
|
|
|
652
652
|
"relativePath": [
|
|
653
653
|
"dist",
|
|
654
654
|
"commands",
|
|
655
|
-
"
|
|
655
|
+
"status",
|
|
656
656
|
"index.js"
|
|
657
657
|
]
|
|
658
658
|
}
|
|
659
659
|
},
|
|
660
|
-
"version": "0.0.
|
|
660
|
+
"version": "0.0.37"
|
|
661
661
|
}
|