@mailmodo/cli 0.0.46 → 0.0.47-beta.pr49.75
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 +7 -1
- package/dist/commands/deploy/index.d.ts +1 -0
- package/dist/commands/deploy/index.js +18 -9
- package/dist/commands/init/index.js +7 -2
- package/dist/commands/settings/index.js +29 -7
- package/dist/lib/base-command.d.ts +39 -0
- package/dist/lib/base-command.js +59 -5
- package/dist/lib/constants.d.ts +0 -3
- package/dist/lib/constants.js +0 -3
- package/dist/lib/messages.d.ts +1 -0
- package/dist/lib/messages.js +1 -0
- package/oclif.manifest.json +28 -28
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import open from 'open';
|
|
4
|
-
import { BaseCommand } from '../../lib/base-command.js';
|
|
4
|
+
import { BaseCommand, FREE_TIER } from '../../lib/base-command.js';
|
|
5
5
|
import { API_ENDPOINTS } from '../../lib/constants.js';
|
|
6
6
|
import { INFO } from '../../lib/messages.js';
|
|
7
7
|
import { loadYaml, saveYaml } from '../../lib/yaml-config.js';
|
|
@@ -200,6 +200,12 @@ export default class Billing extends BaseCommand {
|
|
|
200
200
|
this.log('');
|
|
201
201
|
}
|
|
202
202
|
async setCap(cap, autoChargeBlockCount, jsonOutput) {
|
|
203
|
+
this.validateBillingCapInputs({ autoChargeBlockCount, cap });
|
|
204
|
+
const tier = await this.fetchBillingTier();
|
|
205
|
+
if (tier === FREE_TIER) {
|
|
206
|
+
this.warnFreeTierCapBlocked(jsonOutput);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
203
209
|
const data = await this.applyBillingCap({
|
|
204
210
|
autoChargeBlockCount,
|
|
205
211
|
cap,
|
|
@@ -10,6 +10,7 @@ export default class Deploy extends BaseCommand {
|
|
|
10
10
|
run(): Promise<void>;
|
|
11
11
|
private validateSequence;
|
|
12
12
|
private buildDeployPayload;
|
|
13
|
+
private resolveMonthlyCapForDeploy;
|
|
13
14
|
private mapEmailToPayload;
|
|
14
15
|
private buildBrandSection;
|
|
15
16
|
private buildProductSection;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { confirm, input } from '@inquirer/prompts';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { BaseCommand } from '../../lib/base-command.js';
|
|
4
|
-
import { API_ENDPOINTS, DEFAULT_BRAND_COLOR
|
|
4
|
+
import { API_ENDPOINTS, DEFAULT_BRAND_COLOR } from '../../lib/constants.js';
|
|
5
5
|
import { ERRORS, INFO, PROMPTS, SEPARATOR } from '../../lib/messages.js';
|
|
6
6
|
import { loadTemplate, } from '../../lib/yaml-config.js';
|
|
7
7
|
export default class Deploy extends BaseCommand {
|
|
@@ -61,16 +61,25 @@ export default class Deploy extends BaseCommand {
|
|
|
61
61
|
return response.data;
|
|
62
62
|
}
|
|
63
63
|
async buildDeployPayload(yamlConfig) {
|
|
64
|
-
const emailsWithHtml = await Promise.all(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
const [emailsWithHtml, monthlyCap] = await Promise.all([
|
|
65
|
+
Promise.all(yamlConfig.emails.map(async (email) => {
|
|
66
|
+
const html = (await loadTemplate(`${email.id}.html`)) || '';
|
|
67
|
+
const plainHtml = (await loadTemplate(`${email.id}_plain.html`)) || html;
|
|
68
|
+
return { ...this.mapEmailToPayload(email), html, plainHtml };
|
|
69
|
+
})),
|
|
70
|
+
this.resolveMonthlyCapForDeploy(yamlConfig.project.monthlyCap),
|
|
71
|
+
]);
|
|
69
72
|
return {
|
|
70
|
-
...this.buildProjectPayload(yamlConfig.project),
|
|
73
|
+
...this.buildProjectPayload(yamlConfig.project, monthlyCap),
|
|
71
74
|
emails: emailsWithHtml,
|
|
72
75
|
};
|
|
73
76
|
}
|
|
77
|
+
async resolveMonthlyCapForDeploy(yamlMonthlyCap) {
|
|
78
|
+
if (yamlMonthlyCap !== undefined)
|
|
79
|
+
return yamlMonthlyCap;
|
|
80
|
+
const billingStatus = await this.fetchBillingStatus();
|
|
81
|
+
return billingStatus?.cap?.inBlocks ?? undefined;
|
|
82
|
+
}
|
|
74
83
|
mapEmailToPayload(email) {
|
|
75
84
|
return {
|
|
76
85
|
condition: email.condition || null,
|
|
@@ -111,11 +120,11 @@ export default class Deploy extends BaseCommand {
|
|
|
111
120
|
replyTo: project?.replyTo || project?.fromEmail || '',
|
|
112
121
|
};
|
|
113
122
|
}
|
|
114
|
-
buildProjectPayload(project) {
|
|
123
|
+
buildProjectPayload(project, monthlyCap) {
|
|
115
124
|
return {
|
|
116
125
|
brand: this.buildBrandSection(project),
|
|
117
126
|
emailStyle: project?.emailStyle || 'branded',
|
|
118
|
-
monthlyCap:
|
|
127
|
+
...(monthlyCap === undefined ? {} : { monthlyCap }),
|
|
119
128
|
product: this.buildProductSection(project),
|
|
120
129
|
senderDetails: this.buildSenderSection(project),
|
|
121
130
|
...(project?.webhookUrl ? { webhookUrl: project.webhookUrl } : {}),
|
|
@@ -2,7 +2,7 @@ import { Flags } from '@oclif/core';
|
|
|
2
2
|
import { confirm, editor, input, select } from '@inquirer/prompts';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { BaseCommand } from '../../lib/base-command.js';
|
|
5
|
-
import { API_ENDPOINTS, DEFAULT_BRAND_COLOR
|
|
5
|
+
import { API_ENDPOINTS, DEFAULT_BRAND_COLOR } from '../../lib/constants.js';
|
|
6
6
|
import { loadYaml, saveTemplate, saveYaml, } from '../../lib/yaml-config.js';
|
|
7
7
|
function isValidUrl(value) {
|
|
8
8
|
try {
|
|
@@ -143,7 +143,6 @@ export default class Init extends BaseCommand {
|
|
|
143
143
|
fromEmail: '',
|
|
144
144
|
fromName: `Team ${analysisPayload.productName}`,
|
|
145
145
|
logoUrl: analysisPayload.brand?.logoUrl || '',
|
|
146
|
-
monthlyCap: DEFAULT_MONTHLY_CAP,
|
|
147
146
|
name: analysisPayload.productName,
|
|
148
147
|
pricingModel: analysisPayload.pricingModel,
|
|
149
148
|
replyTo: '',
|
|
@@ -155,6 +154,12 @@ export default class Init extends BaseCommand {
|
|
|
155
154
|
},
|
|
156
155
|
};
|
|
157
156
|
await saveYaml(yamlConfig);
|
|
157
|
+
const billingStatus = await this.fetchBillingStatus();
|
|
158
|
+
const monthlyCap = billingStatus?.cap?.inBlocks;
|
|
159
|
+
if (monthlyCap !== null && monthlyCap !== undefined) {
|
|
160
|
+
yamlConfig.project.monthlyCap = monthlyCap;
|
|
161
|
+
await saveYaml(yamlConfig);
|
|
162
|
+
}
|
|
158
163
|
const templateSaves = analysisPayload.recommendedEmails.flatMap((rec, index) => {
|
|
159
164
|
const generated = generatedEmails[index];
|
|
160
165
|
const saves = [];
|
|
@@ -4,7 +4,7 @@ import chalk from 'chalk';
|
|
|
4
4
|
import { existsSync } from 'node:fs';
|
|
5
5
|
import { readFile } from 'node:fs/promises';
|
|
6
6
|
import { resolve } from 'node:path';
|
|
7
|
-
import { BaseCommand } from '../../lib/base-command.js';
|
|
7
|
+
import { BaseCommand, FREE_TIER } from '../../lib/base-command.js';
|
|
8
8
|
import { API_ENDPOINTS } from '../../lib/constants.js';
|
|
9
9
|
import { INFO } from '../../lib/messages.js';
|
|
10
10
|
import { saveYaml } from '../../lib/yaml-config.js';
|
|
@@ -48,17 +48,30 @@ export default class Settings extends BaseCommand {
|
|
|
48
48
|
await this.applySetFlag(flags.set, yamlConfig, flags.json ?? false);
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
|
+
const [domainVerified, billingStatus] = await Promise.all([
|
|
52
|
+
flags.json
|
|
53
|
+
? Promise.resolve(null)
|
|
54
|
+
: this.fetchDomainVerified(yamlConfig.project.domain),
|
|
55
|
+
this.fetchBillingStatus(),
|
|
56
|
+
]);
|
|
57
|
+
const tier = billingStatus?.tier ?? null;
|
|
58
|
+
const capFromApi = billingStatus?.cap?.inBlocks ?? null;
|
|
59
|
+
if (capFromApi !== null) {
|
|
60
|
+
yamlConfig.project.monthlyCap = capFromApi;
|
|
61
|
+
await saveYaml(yamlConfig);
|
|
62
|
+
}
|
|
51
63
|
if (flags.json) {
|
|
52
64
|
this.log(JSON.stringify({ settings: yamlConfig.project }, null, 2));
|
|
53
65
|
return;
|
|
54
66
|
}
|
|
55
|
-
const domainVerified = await this.fetchDomainVerified(yamlConfig.project.domain);
|
|
56
67
|
this.log(`\n Current settings for ${chalk.bold(yamlConfig.project.name || 'project')}:\n`);
|
|
57
68
|
for (const [group, keys] of Object.entries(SETTINGS_GROUPS)) {
|
|
69
|
+
if (group === 'billing' && tier === FREE_TIER)
|
|
70
|
+
continue;
|
|
58
71
|
this.displaySettingsGroup(group, keys, yamlConfig.project, domainVerified);
|
|
59
72
|
}
|
|
60
73
|
if (!flags.yes) {
|
|
61
|
-
await this.promptEditSetting(yamlConfig);
|
|
74
|
+
await this.promptEditSetting(yamlConfig, tier);
|
|
62
75
|
}
|
|
63
76
|
}
|
|
64
77
|
async applySetFlag(setFlag, yamlConfig, isJson) {
|
|
@@ -74,7 +87,7 @@ export default class Settings extends BaseCommand {
|
|
|
74
87
|
this.error(`Unknown setting: ${key}`);
|
|
75
88
|
}
|
|
76
89
|
if (propKey === 'monthlyCap') {
|
|
77
|
-
await this.applyMonthlyCapChange(yamlConfig, value, isJson);
|
|
90
|
+
await this.applyMonthlyCapChange(yamlConfig, value, isJson, null);
|
|
78
91
|
return;
|
|
79
92
|
}
|
|
80
93
|
project[propKey] = value;
|
|
@@ -86,12 +99,17 @@ export default class Settings extends BaseCommand {
|
|
|
86
99
|
this.log(`\n ${chalk.green('✓')} ${key} updated to ${chalk.cyan(value)}`);
|
|
87
100
|
this.log(` ${INFO.DEPLOY_TO_APPLY}\n`);
|
|
88
101
|
}
|
|
89
|
-
async applyMonthlyCapChange(yamlConfig, rawValue, isJson) {
|
|
102
|
+
async applyMonthlyCapChange(yamlConfig, rawValue, isJson, knownTier) {
|
|
90
103
|
const parsed = Number(rawValue);
|
|
91
104
|
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
92
105
|
this.error('monthly_cap must be a positive integer (blocks).');
|
|
93
106
|
}
|
|
94
107
|
await this.ensureAuth();
|
|
108
|
+
const tier = knownTier ?? (await this.fetchBillingTier());
|
|
109
|
+
if (tier === FREE_TIER) {
|
|
110
|
+
this.warnFreeTierCapBlocked(isJson);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
95
113
|
const data = await this.applyBillingCap({ cap: parsed, json: isJson });
|
|
96
114
|
yamlConfig.project.monthlyCap = data.capBlocks;
|
|
97
115
|
await saveYaml(yamlConfig);
|
|
@@ -146,7 +164,7 @@ export default class Settings extends BaseCommand {
|
|
|
146
164
|
* Prompts the user to pick a setting key to edit and dispatches
|
|
147
165
|
* to the appropriate handler for that key.
|
|
148
166
|
*/
|
|
149
|
-
async promptEditSetting(yamlConfig) {
|
|
167
|
+
async promptEditSetting(yamlConfig, tier) {
|
|
150
168
|
const { project } = yamlConfig;
|
|
151
169
|
const editKey = await input({
|
|
152
170
|
default: 'n',
|
|
@@ -154,6 +172,10 @@ export default class Settings extends BaseCommand {
|
|
|
154
172
|
});
|
|
155
173
|
if (editKey === 'n')
|
|
156
174
|
return;
|
|
175
|
+
if (editKey === 'monthly_cap' && tier === FREE_TIER) {
|
|
176
|
+
this.warnFreeTierCapBlocked(false);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
157
179
|
const editPropKey = settingKeyToProp(editKey);
|
|
158
180
|
if (!(editPropKey in project)) {
|
|
159
181
|
if (editKey === 'logo_file') {
|
|
@@ -181,7 +203,7 @@ export default class Settings extends BaseCommand {
|
|
|
181
203
|
const newValue = await input({
|
|
182
204
|
message: 'New monthly cap (blocks):',
|
|
183
205
|
});
|
|
184
|
-
await this.applyMonthlyCapChange(yamlConfig, newValue, false);
|
|
206
|
+
await this.applyMonthlyCapChange(yamlConfig, newValue, false, tier);
|
|
185
207
|
return;
|
|
186
208
|
}
|
|
187
209
|
if (editKey === 'email_style') {
|
|
@@ -8,6 +8,15 @@ export interface BillingCapUpdateResult {
|
|
|
8
8
|
capEmails: number;
|
|
9
9
|
message: string;
|
|
10
10
|
}
|
|
11
|
+
export interface BillingStatusResult {
|
|
12
|
+
cap?: {
|
|
13
|
+
capUpdatedAt: null | string;
|
|
14
|
+
inBlocks: null | number;
|
|
15
|
+
inEmails: null | number;
|
|
16
|
+
};
|
|
17
|
+
tier?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const FREE_TIER = "free";
|
|
11
20
|
/**
|
|
12
21
|
* Abstract base command providing shared functionality for all Mailmodo CLI commands.
|
|
13
22
|
* Subclasses inherit --json and --yes base flags, authentication enforcement,
|
|
@@ -74,6 +83,15 @@ export declare abstract class BaseCommand extends Command {
|
|
|
74
83
|
fromName: string;
|
|
75
84
|
replyTo: string;
|
|
76
85
|
}>;
|
|
86
|
+
/**
|
|
87
|
+
* Validates the inputs that would be sent to `POST /billing/cap`. Extracted
|
|
88
|
+
* so callers can run cheap, no-API local checks (positive integers) before
|
|
89
|
+
* the tier lookup or any other network round trip.
|
|
90
|
+
*/
|
|
91
|
+
protected validateBillingCapInputs(options: {
|
|
92
|
+
autoChargeBlockCount?: number;
|
|
93
|
+
cap: number;
|
|
94
|
+
}): void;
|
|
77
95
|
/**
|
|
78
96
|
* Updates the account's monthly sending cap on the server.
|
|
79
97
|
* Validates inputs, wraps the POST /billing/cap call in a spinner, and
|
|
@@ -85,6 +103,27 @@ export declare abstract class BaseCommand extends Command {
|
|
|
85
103
|
cap: number;
|
|
86
104
|
json: boolean;
|
|
87
105
|
}): Promise<BillingCapUpdateResult>;
|
|
106
|
+
/**
|
|
107
|
+
* Shared "free-tier users can't set a monthly cap" notice for both the
|
|
108
|
+
* billing and settings commands. Prints a yellow warning in text mode and a
|
|
109
|
+
* `status: 'blocked'` payload in JSON mode so machine-readable callers can
|
|
110
|
+
* distinguish from a successful update.
|
|
111
|
+
*/
|
|
112
|
+
protected warnFreeTierCapBlocked(jsonOutput: boolean): void;
|
|
113
|
+
/**
|
|
114
|
+
* Fetches the full billing status from `/billing/status`. Returns `null`
|
|
115
|
+
* when the request cannot be completed (no credentials, network failure,
|
|
116
|
+
* non-OK response) so callers can degrade gracefully without halting.
|
|
117
|
+
*/
|
|
118
|
+
protected fetchBillingStatus(): Promise<BillingStatusResult | null>;
|
|
119
|
+
/**
|
|
120
|
+
* Fetches the account's billing tier from `/billing/status`. Returns `null`
|
|
121
|
+
* when the request cannot be completed (no credentials, network failure,
|
|
122
|
+
* non-OK response) so callers can degrade gracefully without halting.
|
|
123
|
+
* Callers that need a hard "free vs paid" decision should treat `null` as
|
|
124
|
+
* unknown and fall through to their default behavior.
|
|
125
|
+
*/
|
|
126
|
+
protected fetchBillingTier(): Promise<null | string>;
|
|
88
127
|
protected registerDomain(yamlConfig: MailmodoYaml, inputs: {
|
|
89
128
|
address: string;
|
|
90
129
|
domain: string;
|
package/dist/lib/base-command.js
CHANGED
|
@@ -7,6 +7,7 @@ import { loadConfig } from './config.js';
|
|
|
7
7
|
import { API_ENDPOINTS } from './constants.js';
|
|
8
8
|
import { ERRORS, INFO, PROMPTS, recordLabel, VALIDATION } from './messages.js';
|
|
9
9
|
import { loadYaml, saveYaml } from './yaml-config.js';
|
|
10
|
+
export const FREE_TIER = 'free';
|
|
10
11
|
/**
|
|
11
12
|
* Abstract base command providing shared functionality for all Mailmodo CLI commands.
|
|
12
13
|
* Subclasses inherit --json and --yes base flags, authentication enforcement,
|
|
@@ -146,12 +147,11 @@ export class BaseCommand extends Command {
|
|
|
146
147
|
return { address, domain, fromEmail, fromName, replyTo };
|
|
147
148
|
}
|
|
148
149
|
/**
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* local persistence (e.g. writing `monthlyCap` to mailmodo.yaml).
|
|
150
|
+
* Validates the inputs that would be sent to `POST /billing/cap`. Extracted
|
|
151
|
+
* so callers can run cheap, no-API local checks (positive integers) before
|
|
152
|
+
* the tier lookup or any other network round trip.
|
|
153
153
|
*/
|
|
154
|
-
|
|
154
|
+
validateBillingCapInputs(options) {
|
|
155
155
|
if (options.cap < 1) {
|
|
156
156
|
this.error('Cap must be at least 1 block.');
|
|
157
157
|
}
|
|
@@ -159,6 +159,15 @@ export class BaseCommand extends Command {
|
|
|
159
159
|
options.autoChargeBlockCount < 1) {
|
|
160
160
|
this.error('Auto-charge block count must be at least 1 block.');
|
|
161
161
|
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Updates the account's monthly sending cap on the server.
|
|
165
|
+
* Validates inputs, wraps the POST /billing/cap call in a spinner, and
|
|
166
|
+
* surfaces errors via handleApiError. The caller is responsible for any
|
|
167
|
+
* local persistence (e.g. writing `monthlyCap` to mailmodo.yaml).
|
|
168
|
+
*/
|
|
169
|
+
async applyBillingCap(options) {
|
|
170
|
+
this.validateBillingCapInputs(options);
|
|
162
171
|
const payload = options.autoChargeBlockCount === undefined
|
|
163
172
|
? { cap: options.cap }
|
|
164
173
|
: {
|
|
@@ -171,6 +180,51 @@ export class BaseCommand extends Command {
|
|
|
171
180
|
}
|
|
172
181
|
return response.data;
|
|
173
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Shared "free-tier users can't set a monthly cap" notice for both the
|
|
185
|
+
* billing and settings commands. Prints a yellow warning in text mode and a
|
|
186
|
+
* `status: 'blocked'` payload in JSON mode so machine-readable callers can
|
|
187
|
+
* distinguish from a successful update.
|
|
188
|
+
*/
|
|
189
|
+
warnFreeTierCapBlocked(jsonOutput) {
|
|
190
|
+
if (jsonOutput) {
|
|
191
|
+
this.log(JSON.stringify({
|
|
192
|
+
message: INFO.FREE_TIER_CAP_BLOCKED,
|
|
193
|
+
status: 'blocked',
|
|
194
|
+
tier: FREE_TIER,
|
|
195
|
+
}, null, 2));
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
this.warn(chalk.yellow(INFO.FREE_TIER_CAP_BLOCKED));
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Fetches the full billing status from `/billing/status`. Returns `null`
|
|
202
|
+
* when the request cannot be completed (no credentials, network failure,
|
|
203
|
+
* non-OK response) so callers can degrade gracefully without halting.
|
|
204
|
+
*/
|
|
205
|
+
async fetchBillingStatus() {
|
|
206
|
+
try {
|
|
207
|
+
await this.ensureAuth();
|
|
208
|
+
const response = await this.apiClient.get(API_ENDPOINTS.BILLING_STATUS);
|
|
209
|
+
if (!response.ok)
|
|
210
|
+
return null;
|
|
211
|
+
return response.data ?? null;
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Fetches the account's billing tier from `/billing/status`. Returns `null`
|
|
219
|
+
* when the request cannot be completed (no credentials, network failure,
|
|
220
|
+
* non-OK response) so callers can degrade gracefully without halting.
|
|
221
|
+
* Callers that need a hard "free vs paid" decision should treat `null` as
|
|
222
|
+
* unknown and fall through to their default behavior.
|
|
223
|
+
*/
|
|
224
|
+
async fetchBillingTier() {
|
|
225
|
+
const status = await this.fetchBillingStatus();
|
|
226
|
+
return status?.tier ?? null;
|
|
227
|
+
}
|
|
174
228
|
async registerDomain(yamlConfig, inputs, json) {
|
|
175
229
|
const apiPayload = {
|
|
176
230
|
address: inputs.address,
|
package/dist/lib/constants.d.ts
CHANGED
|
@@ -23,10 +23,7 @@ export declare const API_ENDPOINTS: Readonly<{
|
|
|
23
23
|
SEQUENCES_VALIDATE: "/sequences/validate";
|
|
24
24
|
}>;
|
|
25
25
|
export declare const LOGIN_URL = "https://app-vertex-debug.azurewebsites.net/signup.html";
|
|
26
|
-
export declare const DOCS_URL = "https://mailmodo.com/docs/cli";
|
|
27
|
-
export declare const DNS_GUIDE_URL = "https://mailmodo.com/docs/dns";
|
|
28
26
|
export declare const PREVIEW_PORT = 3421;
|
|
29
27
|
export declare const DEFAULT_BRAND_COLOR = "#1A56DB";
|
|
30
|
-
export declare const DEFAULT_MONTHLY_CAP = 5;
|
|
31
28
|
export declare const TEMPLATES_DIR = "mailmodo";
|
|
32
29
|
export declare const YAML_FILE = "mailmodo.yaml";
|
package/dist/lib/constants.js
CHANGED
|
@@ -34,10 +34,7 @@ const PRODUCTION_LOGIN_URL = 'https://app-vertex-debug.azurewebsites.net/signup.
|
|
|
34
34
|
export const LOGIN_URL = process.env.MAILMODO_DEV_TSX
|
|
35
35
|
? DEV_LOGIN_URL
|
|
36
36
|
: PRODUCTION_LOGIN_URL;
|
|
37
|
-
export const DOCS_URL = 'https://mailmodo.com/docs/cli';
|
|
38
|
-
export const DNS_GUIDE_URL = 'https://mailmodo.com/docs/dns';
|
|
39
37
|
export const PREVIEW_PORT = 3421;
|
|
40
38
|
export const DEFAULT_BRAND_COLOR = '#1A56DB';
|
|
41
|
-
export const DEFAULT_MONTHLY_CAP = 5;
|
|
42
39
|
export const TEMPLATES_DIR = 'mailmodo';
|
|
43
40
|
export const YAML_FILE = 'mailmodo.yaml';
|
package/dist/lib/messages.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ export declare const INFO: {
|
|
|
32
32
|
readonly DOMAIN_NOT_DEPLOYED_HINT: `When ready, run: ${string}
|
|
33
33
|
Then: ${string}`;
|
|
34
34
|
readonly DOMAIN_PENDING_VERIFICATION: `Your domain is not verified yet. Please verify it first. Run ${string} to check the status.`;
|
|
35
|
+
readonly FREE_TIER_CAP_BLOCKED: `Monthly cap is a paid-tier setting and is not available on the free tier. Run ${string} to add a payment method, then set a cap.`;
|
|
35
36
|
readonly SEQUENCES_NOT_DEPLOYED: `Sequences saved but ${string}.`;
|
|
36
37
|
};
|
|
37
38
|
export declare function yamlParseError(detail: string): string;
|
package/dist/lib/messages.js
CHANGED
|
@@ -32,6 +32,7 @@ export const INFO = {
|
|
|
32
32
|
DNS_RECORDS_FAILED: chalk.yellow('Some records failed.'),
|
|
33
33
|
DOMAIN_NOT_DEPLOYED_HINT: `When ready, run: ${chalk.cyan('mailmodo domain')}\n Then: ${chalk.cyan('mailmodo deploy')}`,
|
|
34
34
|
DOMAIN_PENDING_VERIFICATION: `Your domain is not verified yet. Please verify it first. Run ${chalk.cyan('mailmodo domain --verify')} to check the status.`,
|
|
35
|
+
FREE_TIER_CAP_BLOCKED: `Monthly cap is a paid-tier setting and is not available on the free tier. Run ${chalk.cyan("'mailmodo billing --checkout'")} to add a payment method, then set a cap.`,
|
|
35
36
|
SEQUENCES_NOT_DEPLOYED: `Sequences saved but ${chalk.yellow('NOT deployed')}.`,
|
|
36
37
|
};
|
|
37
38
|
export function yamlParseError(detail) {
|
package/oclif.manifest.json
CHANGED
|
@@ -228,13 +228,19 @@
|
|
|
228
228
|
"index.js"
|
|
229
229
|
]
|
|
230
230
|
},
|
|
231
|
-
"
|
|
231
|
+
"edit": {
|
|
232
232
|
"aliases": [],
|
|
233
|
-
"args": {
|
|
234
|
-
|
|
233
|
+
"args": {
|
|
234
|
+
"id": {
|
|
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",
|
|
235
241
|
"examples": [
|
|
236
|
-
"<%= config.bin %>
|
|
237
|
-
"<%= config.bin %>
|
|
242
|
+
"<%= config.bin %> edit welcome",
|
|
243
|
+
"<%= config.bin %> edit welcome --change \"make subject more urgent\" --yes"
|
|
238
244
|
],
|
|
239
245
|
"flags": {
|
|
240
246
|
"json": {
|
|
@@ -249,11 +255,18 @@
|
|
|
249
255
|
"name": "yes",
|
|
250
256
|
"allowNo": false,
|
|
251
257
|
"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"
|
|
252
265
|
}
|
|
253
266
|
},
|
|
254
267
|
"hasDynamicHelp": false,
|
|
255
268
|
"hiddenAliases": [],
|
|
256
|
-
"id": "
|
|
269
|
+
"id": "edit",
|
|
257
270
|
"pluginAlias": "@mailmodo/cli",
|
|
258
271
|
"pluginName": "@mailmodo/cli",
|
|
259
272
|
"pluginType": "core",
|
|
@@ -263,23 +276,17 @@
|
|
|
263
276
|
"relativePath": [
|
|
264
277
|
"dist",
|
|
265
278
|
"commands",
|
|
266
|
-
"
|
|
279
|
+
"edit",
|
|
267
280
|
"index.js"
|
|
268
281
|
]
|
|
269
282
|
},
|
|
270
|
-
"
|
|
283
|
+
"emails": {
|
|
271
284
|
"aliases": [],
|
|
272
|
-
"args": {
|
|
273
|
-
|
|
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",
|
|
285
|
+
"args": {},
|
|
286
|
+
"description": "List and view configured email sequences",
|
|
280
287
|
"examples": [
|
|
281
|
-
"<%= config.bin %>
|
|
282
|
-
"<%= config.bin %>
|
|
288
|
+
"<%= config.bin %> emails",
|
|
289
|
+
"<%= config.bin %> emails --json"
|
|
283
290
|
],
|
|
284
291
|
"flags": {
|
|
285
292
|
"json": {
|
|
@@ -294,18 +301,11 @@
|
|
|
294
301
|
"name": "yes",
|
|
295
302
|
"allowNo": false,
|
|
296
303
|
"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": "emails",
|
|
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
|
+
"emails",
|
|
319
319
|
"index.js"
|
|
320
320
|
]
|
|
321
321
|
},
|
|
@@ -657,5 +657,5 @@
|
|
|
657
657
|
]
|
|
658
658
|
}
|
|
659
659
|
},
|
|
660
|
-
"version": "0.0.
|
|
660
|
+
"version": "0.0.47-beta.pr49.75"
|
|
661
661
|
}
|