@mailmodo/cli 0.0.20-beta.pr23.34 → 0.0.21-beta.pr23.39
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/deploy/index.d.ts +3 -0
- package/dist/commands/deploy/index.js +29 -20
- package/dist/commands/domain/index.js +11 -6
- package/dist/commands/edit/index.d.ts +10 -0
- package/dist/commands/edit/index.js +127 -9
- package/dist/commands/preview/index.js +7 -2
- package/dist/commands/settings/index.d.ts +2 -0
- package/dist/commands/settings/index.js +67 -60
- package/dist/lib/constants.d.ts +1 -1
- package/dist/lib/constants.js +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -16,6 +16,9 @@ export default class Deploy extends BaseCommand {
|
|
|
16
16
|
run(): Promise<void>;
|
|
17
17
|
private buildDeployPayload;
|
|
18
18
|
private mapEmailToPayload;
|
|
19
|
+
private buildBrandSection;
|
|
20
|
+
private buildProductSection;
|
|
21
|
+
private buildSenderSection;
|
|
19
22
|
private buildProjectPayload;
|
|
20
23
|
private confirmDeploy;
|
|
21
24
|
private ensureDomainReady;
|
|
@@ -77,30 +77,39 @@ export default class Deploy extends BaseCommand {
|
|
|
77
77
|
trigger: email.trigger,
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
|
+
buildBrandSection(project) {
|
|
81
|
+
return {
|
|
82
|
+
colors: [project?.brandColor || DEFAULT_BRAND_COLOR],
|
|
83
|
+
logoUrl: project?.logoUrl || '',
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
buildProductSection(project) {
|
|
87
|
+
return {
|
|
88
|
+
businessType: project?.type || '',
|
|
89
|
+
description: '',
|
|
90
|
+
pricingModel: '',
|
|
91
|
+
productName: project?.name || '',
|
|
92
|
+
saasModel: '',
|
|
93
|
+
targetUser: '',
|
|
94
|
+
url: project?.url || '',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
buildSenderSection(project) {
|
|
98
|
+
return {
|
|
99
|
+
address: project?.address || '',
|
|
100
|
+
domain: project?.domain || '',
|
|
101
|
+
fromEmail: project?.fromEmail || '',
|
|
102
|
+
fromName: project?.fromName || '',
|
|
103
|
+
replyTo: project?.replyTo || project?.fromEmail || '',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
80
106
|
buildProjectPayload(project) {
|
|
81
107
|
return {
|
|
82
|
-
brand:
|
|
83
|
-
colors: [project?.brandColor || DEFAULT_BRAND_COLOR],
|
|
84
|
-
logoUrl: project?.logoUrl || '',
|
|
85
|
-
},
|
|
108
|
+
brand: this.buildBrandSection(project),
|
|
86
109
|
emailStyle: project?.emailStyle || 'branded',
|
|
87
110
|
monthlyCap: project?.monthlyCap ?? DEFAULT_MONTHLY_CAP,
|
|
88
|
-
product:
|
|
89
|
-
|
|
90
|
-
description: '',
|
|
91
|
-
pricingModel: '',
|
|
92
|
-
productName: project?.name || '',
|
|
93
|
-
saasModel: '',
|
|
94
|
-
targetUser: '',
|
|
95
|
-
url: project?.url || '',
|
|
96
|
-
},
|
|
97
|
-
senderDetails: {
|
|
98
|
-
address: project?.address || '',
|
|
99
|
-
domain: project?.domain || '',
|
|
100
|
-
fromEmail: project?.fromEmail || '',
|
|
101
|
-
fromName: project?.fromName || '',
|
|
102
|
-
replyTo: project?.replyTo || project?.fromEmail || '',
|
|
103
|
-
},
|
|
111
|
+
product: this.buildProductSection(project),
|
|
112
|
+
senderDetails: this.buildSenderSection(project),
|
|
104
113
|
webhookUrl: project?.webhookUrl || '',
|
|
105
114
|
};
|
|
106
115
|
}
|
|
@@ -124,15 +124,15 @@ export default class Domain extends BaseCommand {
|
|
|
124
124
|
if (!response.ok) {
|
|
125
125
|
this.handleApiError(response);
|
|
126
126
|
}
|
|
127
|
-
const { dkim, dmarc,
|
|
127
|
+
const { dkim, dmarc, returnPath, domainStatus } = response.data;
|
|
128
128
|
if (jsonOutput) {
|
|
129
|
-
this.log(JSON.stringify({ dkim, dmarc,
|
|
129
|
+
this.log(JSON.stringify({ dkim, dmarc, returnPath, domainStatus }, null, 2));
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
132
|
-
this.log(`
|
|
133
|
-
this.log(`
|
|
134
|
-
this.log(`
|
|
135
|
-
const allPassed =
|
|
132
|
+
this.log(` DKIM ${dkim ? chalk.green('✓') : chalk.red('✗ Not found')}`);
|
|
133
|
+
this.log(` DMARC ${dmarc ? chalk.green('✓') : chalk.red('✗ Not found')}`);
|
|
134
|
+
this.log(` Return Path ${returnPath ? chalk.green('✓') : chalk.red('✗ Not found')}`);
|
|
135
|
+
const allPassed = domainStatus === 'VERIFIED';
|
|
136
136
|
if (allPassed) {
|
|
137
137
|
this.log(`\n ${chalk.green('✓')} Domain verified.\n`);
|
|
138
138
|
}
|
|
@@ -144,6 +144,11 @@ export default class Domain extends BaseCommand {
|
|
|
144
144
|
this.log(` - Including the full domain in the Host field`);
|
|
145
145
|
this.log(` - Cloudflare: proxy must be OFF (grey cloud, not orange)`);
|
|
146
146
|
}
|
|
147
|
+
if (!returnPath) {
|
|
148
|
+
this.log(`\n Return Path common mistakes:`);
|
|
149
|
+
this.log(` - Missing or incorrect CNAME for mm-bounce subdomain`);
|
|
150
|
+
this.log(` - Cloudflare: proxy must be OFF (grey cloud, not orange)`);
|
|
151
|
+
}
|
|
147
152
|
this.log(`\n Fix the records and run ${chalk.cyan('mailmodo domain --verify')} again.`);
|
|
148
153
|
this.log(` Help: ${chalk.cyan(DNS_GUIDE_URL)}\n`);
|
|
149
154
|
}
|
|
@@ -10,5 +10,15 @@ export default class Edit extends BaseCommand {
|
|
|
10
10
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
12
|
};
|
|
13
|
+
private showFieldDiff;
|
|
14
|
+
private stripHtml;
|
|
15
|
+
private truncate;
|
|
16
|
+
private showHtmlChange;
|
|
17
|
+
private showUnchangedField;
|
|
18
|
+
private showUnchangedHtml;
|
|
19
|
+
private showSuggestedChanges;
|
|
20
|
+
private showUnchanged;
|
|
21
|
+
private buildDiffPreview;
|
|
22
|
+
private showChangeSummary;
|
|
13
23
|
run(): Promise<void>;
|
|
14
24
|
}
|
|
@@ -22,6 +22,123 @@ export default class Edit extends BaseCommand {
|
|
|
22
22
|
description: 'Natural language description of the change',
|
|
23
23
|
}),
|
|
24
24
|
};
|
|
25
|
+
showFieldDiff(label, oldVal, newVal) {
|
|
26
|
+
if (!newVal || oldVal === newVal)
|
|
27
|
+
return false;
|
|
28
|
+
this.log(`\n ${label}:`);
|
|
29
|
+
if (oldVal)
|
|
30
|
+
this.log(` ${chalk.red(`- ${oldVal}`)}`);
|
|
31
|
+
this.log(` ${chalk.green(`+ ${newVal}`)}`);
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
stripHtml(html) {
|
|
35
|
+
return html
|
|
36
|
+
.replaceAll(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
|
|
37
|
+
.replaceAll(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
|
|
38
|
+
.replaceAll(/<[^>]+>/g, ' ')
|
|
39
|
+
.replaceAll(' ', ' ')
|
|
40
|
+
.replaceAll('&', '&')
|
|
41
|
+
.replaceAll('<', '<')
|
|
42
|
+
.replaceAll('>', '>')
|
|
43
|
+
.replaceAll(/\s+/g, ' ')
|
|
44
|
+
.trim();
|
|
45
|
+
}
|
|
46
|
+
truncate(text, max) {
|
|
47
|
+
return text.length > max ? `${text.slice(0, max)}…` : text;
|
|
48
|
+
}
|
|
49
|
+
showHtmlChange(oldHtml, newHtml) {
|
|
50
|
+
if (!newHtml || oldHtml === newHtml)
|
|
51
|
+
return false;
|
|
52
|
+
this.log(`\n HTML Body:`);
|
|
53
|
+
const MAX = 500;
|
|
54
|
+
if (oldHtml) {
|
|
55
|
+
const oldText = this.truncate(this.stripHtml(oldHtml), MAX);
|
|
56
|
+
this.log(` ${chalk.red(`- ${oldText}`)}`);
|
|
57
|
+
}
|
|
58
|
+
const newText = this.truncate(this.stripHtml(newHtml), MAX);
|
|
59
|
+
this.log(` ${chalk.green(`+ ${newText}`)}`);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
showUnchangedField(label, value) {
|
|
63
|
+
if (!value)
|
|
64
|
+
return;
|
|
65
|
+
this.log(`\n ${label}:`);
|
|
66
|
+
this.log(` ${chalk.dim(value)}`);
|
|
67
|
+
}
|
|
68
|
+
showUnchangedHtml(templateHtml) {
|
|
69
|
+
if (!templateHtml)
|
|
70
|
+
return;
|
|
71
|
+
this.log(`\n HTML Body:`);
|
|
72
|
+
this.log(` ${chalk.dim(this.truncate(this.stripHtml(templateHtml), 500))}`);
|
|
73
|
+
}
|
|
74
|
+
showSuggestedChanges(email, updated, templateHtml, changed) {
|
|
75
|
+
this.log('\n Suggested Changes:');
|
|
76
|
+
if (changed.subject)
|
|
77
|
+
this.showFieldDiff('Subject', email.subject, updated.subject);
|
|
78
|
+
if (changed.preview)
|
|
79
|
+
this.showFieldDiff('Preview Text', email.previewText, updated.previewText);
|
|
80
|
+
if (changed.html)
|
|
81
|
+
this.showHtmlChange(templateHtml, updated.html);
|
|
82
|
+
if (changed.cta)
|
|
83
|
+
this.showFieldDiff('CTA Text', undefined, updated.ctaText);
|
|
84
|
+
if (!changed.subject && !changed.preview && !changed.html && !changed.cta) {
|
|
85
|
+
this.log(`\n ${chalk.dim('No changes detected.')}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
showUnchanged(email, templateHtml, changed) {
|
|
89
|
+
const hasContent = !changed.subject ||
|
|
90
|
+
(!changed.preview && Boolean(email.previewText)) ||
|
|
91
|
+
(!changed.html && Boolean(templateHtml));
|
|
92
|
+
if (!hasContent)
|
|
93
|
+
return;
|
|
94
|
+
this.log('\n Unchanged:');
|
|
95
|
+
if (!changed.subject)
|
|
96
|
+
this.showUnchangedField('Subject', email.subject);
|
|
97
|
+
if (!changed.preview)
|
|
98
|
+
this.showUnchangedField('Preview Text', email.previewText);
|
|
99
|
+
if (!changed.html)
|
|
100
|
+
this.showUnchangedHtml(templateHtml);
|
|
101
|
+
}
|
|
102
|
+
buildDiffPreview(email, updated, templateHtml) {
|
|
103
|
+
const subjectChanged = Boolean(updated.subject) && updated.subject !== email.subject;
|
|
104
|
+
const previewChanged = Boolean(updated.previewText) && updated.previewText !== email.previewText;
|
|
105
|
+
const htmlChanged = Boolean(updated.html) && updated.html !== templateHtml;
|
|
106
|
+
const diff = {};
|
|
107
|
+
diff.subject = subjectChanged
|
|
108
|
+
? { new: updated.subject, old: email.subject }
|
|
109
|
+
: { unchanged: true, value: email.subject };
|
|
110
|
+
if (email.previewText ?? updated.previewText) {
|
|
111
|
+
diff.previewText = previewChanged
|
|
112
|
+
? { new: updated.previewText, old: email.previewText }
|
|
113
|
+
: { unchanged: true, value: email.previewText };
|
|
114
|
+
}
|
|
115
|
+
if (templateHtml ?? updated.html) {
|
|
116
|
+
const oldText = templateHtml
|
|
117
|
+
? this.truncate(this.stripHtml(templateHtml), 500)
|
|
118
|
+
: null;
|
|
119
|
+
const newText = updated.html
|
|
120
|
+
? this.truncate(this.stripHtml(updated.html), 500)
|
|
121
|
+
: null;
|
|
122
|
+
diff.html = htmlChanged
|
|
123
|
+
? { new: newText, old: oldText }
|
|
124
|
+
: { unchanged: true, value: oldText };
|
|
125
|
+
}
|
|
126
|
+
if (updated.ctaText) {
|
|
127
|
+
diff.ctaText = { new: updated.ctaText };
|
|
128
|
+
}
|
|
129
|
+
return { diff };
|
|
130
|
+
}
|
|
131
|
+
showChangeSummary(email, updated, templateHtml) {
|
|
132
|
+
const changed = {
|
|
133
|
+
cta: Boolean(updated.ctaText),
|
|
134
|
+
html: Boolean(updated.html) && updated.html !== templateHtml,
|
|
135
|
+
preview: Boolean(updated.previewText) &&
|
|
136
|
+
updated.previewText !== email.previewText,
|
|
137
|
+
subject: Boolean(updated.subject) && updated.subject !== email.subject,
|
|
138
|
+
};
|
|
139
|
+
this.showSuggestedChanges(email, updated, templateHtml, changed);
|
|
140
|
+
this.showUnchanged(email, templateHtml, changed);
|
|
141
|
+
}
|
|
25
142
|
async run() {
|
|
26
143
|
const { args, flags } = await this.parse(Edit);
|
|
27
144
|
await this.ensureAuth();
|
|
@@ -32,9 +149,6 @@ export default class Edit extends BaseCommand {
|
|
|
32
149
|
}
|
|
33
150
|
const email = yamlConfig.emails[emailIndex];
|
|
34
151
|
const templateHtml = await loadTemplate(`${email.id}.html`);
|
|
35
|
-
if (!flags.json) {
|
|
36
|
-
this.log(`\n Current subject: '${chalk.cyan(email.subject)}'`);
|
|
37
|
-
}
|
|
38
152
|
let changeDescription = flags.change;
|
|
39
153
|
if (!changeDescription) {
|
|
40
154
|
changeDescription = await input({
|
|
@@ -58,12 +172,11 @@ export default class Edit extends BaseCommand {
|
|
|
58
172
|
this.handleApiError(response);
|
|
59
173
|
}
|
|
60
174
|
const updated = response.data;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
this.
|
|
66
|
-
this.log(` ${chalk.green(`+ ${newSubject}`)}`);
|
|
175
|
+
if (flags.json) {
|
|
176
|
+
this.log(JSON.stringify(this.buildDiffPreview(email, updated, templateHtml), null, 2));
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
this.showChangeSummary(email, updated, templateHtml);
|
|
67
180
|
}
|
|
68
181
|
if (!flags.yes) {
|
|
69
182
|
const accepted = await confirm({
|
|
@@ -75,6 +188,8 @@ export default class Edit extends BaseCommand {
|
|
|
75
188
|
return;
|
|
76
189
|
}
|
|
77
190
|
}
|
|
191
|
+
const oldSubject = email.subject;
|
|
192
|
+
const newSubject = updated.subject || email.subject;
|
|
78
193
|
if (updated.subject)
|
|
79
194
|
email.subject = updated.subject;
|
|
80
195
|
if (updated.previewText)
|
|
@@ -91,6 +206,9 @@ export default class Edit extends BaseCommand {
|
|
|
91
206
|
if (flags.json) {
|
|
92
207
|
this.log(JSON.stringify({
|
|
93
208
|
diff: {
|
|
209
|
+
previewText: updated.previewText && updated.previewText !== email.previewText
|
|
210
|
+
? { new: updated.previewText, old: email.previewText }
|
|
211
|
+
: undefined,
|
|
94
212
|
subject: oldSubject === newSubject
|
|
95
213
|
? undefined
|
|
96
214
|
: { new: newSubject, old: oldSubject },
|
|
@@ -89,7 +89,11 @@ export default class Preview extends BaseCommand {
|
|
|
89
89
|
const rendered = templateHtml
|
|
90
90
|
? renderTemplate(templateHtml, sampleData)
|
|
91
91
|
: '';
|
|
92
|
-
await this.sendTestEmail(email, rendered,
|
|
92
|
+
await this.sendTestEmail(email, rendered, {
|
|
93
|
+
domain: yamlConfig.project?.domain,
|
|
94
|
+
jsonOutput: flags.json,
|
|
95
|
+
toAddress: flags.send,
|
|
96
|
+
});
|
|
93
97
|
return;
|
|
94
98
|
}
|
|
95
99
|
if (flags.text) {
|
|
@@ -126,7 +130,8 @@ export default class Preview extends BaseCommand {
|
|
|
126
130
|
* Calls the API to send a test email to the specified address.
|
|
127
131
|
* Before domain verification, tests send via the mailmodo.com domain.
|
|
128
132
|
*/
|
|
129
|
-
async sendTestEmail(email, html,
|
|
133
|
+
async sendTestEmail(email, html, opts) {
|
|
134
|
+
const { domain, jsonOutput, toAddress } = opts;
|
|
130
135
|
await this.ensureAuth();
|
|
131
136
|
const response = await this.withApiSpinner({ json: jsonOutput, text: ' Sending test email...' }, () => this.apiClient.post(`${API_ENDPOINTS.PREVIEW}/send`, {
|
|
132
137
|
domain,
|
|
@@ -8,6 +8,8 @@ export default class Settings extends BaseCommand {
|
|
|
8
8
|
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
9
|
};
|
|
10
10
|
run(): Promise<void>;
|
|
11
|
+
private applySetFlag;
|
|
12
|
+
private displaySettingsGroup;
|
|
11
13
|
/**
|
|
12
14
|
* Prompts the user to pick a setting key to edit and dispatches
|
|
13
15
|
* to the appropriate handler for that key.
|
|
@@ -43,78 +43,85 @@ export default class Settings extends BaseCommand {
|
|
|
43
43
|
async run() {
|
|
44
44
|
const { flags } = await this.parse(Settings);
|
|
45
45
|
const yamlConfig = await this.ensureYaml();
|
|
46
|
-
const { project } = yamlConfig;
|
|
47
46
|
if (flags.set) {
|
|
48
|
-
|
|
49
|
-
if (eqIndex === -1) {
|
|
50
|
-
this.error('Invalid format. Use --set key=value (e.g., --set brand_color=#0F3460)');
|
|
51
|
-
}
|
|
52
|
-
const key = flags.set.slice(0, eqIndex).trim();
|
|
53
|
-
const propKey = settingKeyToProp(key);
|
|
54
|
-
const value = flags.set.slice(eqIndex + 1).trim();
|
|
55
|
-
if (!(propKey in project) && key !== 'logo_file') {
|
|
56
|
-
this.error(`Unknown setting: ${key}`);
|
|
57
|
-
}
|
|
58
|
-
project[propKey] =
|
|
59
|
-
propKey === 'monthlyCap' ? Number(value) : value;
|
|
60
|
-
await saveYaml(yamlConfig);
|
|
61
|
-
if (flags.json) {
|
|
62
|
-
this.log(JSON.stringify({ [propKey]: value, status: 'updated' }, null, 2));
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
this.log(`\n ${chalk.green('✓')} ${key} updated to ${chalk.cyan(value)}`);
|
|
66
|
-
this.log(` Run ${chalk.cyan("'mailmodo deploy'")} to apply.\n`);
|
|
47
|
+
await this.applySetFlag(flags.set, yamlConfig, flags.json ?? false);
|
|
67
48
|
return;
|
|
68
49
|
}
|
|
69
50
|
if (flags.json) {
|
|
70
|
-
this.log(JSON.stringify({ settings: project }, null, 2));
|
|
51
|
+
this.log(JSON.stringify({ settings: yamlConfig.project }, null, 2));
|
|
71
52
|
return;
|
|
72
53
|
}
|
|
73
|
-
const domainVerified = await this.fetchDomainVerified(project.domain);
|
|
74
|
-
this.log(`\n Current settings for ${chalk.bold(project.name || 'project')}:\n`);
|
|
54
|
+
const domainVerified = await this.fetchDomainVerified(yamlConfig.project.domain);
|
|
55
|
+
this.log(`\n Current settings for ${chalk.bold(yamlConfig.project.name || 'project')}:\n`);
|
|
75
56
|
for (const [group, keys] of Object.entries(SETTINGS_GROUPS)) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
57
|
+
this.displaySettingsGroup(group, keys, yamlConfig.project, domainVerified);
|
|
58
|
+
}
|
|
59
|
+
if (!flags.yes) {
|
|
60
|
+
await this.promptEditSetting(yamlConfig);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async applySetFlag(setFlag, yamlConfig, isJson) {
|
|
64
|
+
const { project } = yamlConfig;
|
|
65
|
+
const eqIndex = setFlag.indexOf('=');
|
|
66
|
+
if (eqIndex === -1) {
|
|
67
|
+
this.error('Invalid format. Use --set key=value (e.g., --set brand_color=#0F3460)');
|
|
68
|
+
}
|
|
69
|
+
const key = setFlag.slice(0, eqIndex).trim();
|
|
70
|
+
const propKey = settingKeyToProp(key);
|
|
71
|
+
const value = setFlag.slice(eqIndex + 1).trim();
|
|
72
|
+
if (!(propKey in project) && key !== 'logo_file') {
|
|
73
|
+
this.error(`Unknown setting: ${key}`);
|
|
74
|
+
}
|
|
75
|
+
project[propKey] =
|
|
76
|
+
propKey === 'monthlyCap' ? Number(value) : value;
|
|
77
|
+
await saveYaml(yamlConfig);
|
|
78
|
+
if (isJson) {
|
|
79
|
+
this.log(JSON.stringify({ [propKey]: value, status: 'updated' }, null, 2));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
this.log(`\n ${chalk.green('✓')} ${key} updated to ${chalk.cyan(value)}`);
|
|
83
|
+
this.log(` Run ${chalk.cyan("'mailmodo deploy'")} to apply.\n`);
|
|
84
|
+
}
|
|
85
|
+
displaySettingsGroup(group, keys, project, domainVerified) {
|
|
86
|
+
const availableKeys = keys.filter((key) => {
|
|
87
|
+
if (group === 'brand' && key === 'logo_file')
|
|
88
|
+
return true;
|
|
89
|
+
return settingKeyToProp(key) in project;
|
|
90
|
+
});
|
|
91
|
+
const groupTitle = ` ${chalk.bold(group.charAt(0).toUpperCase() + group.slice(1))}`;
|
|
92
|
+
if (availableKeys.length === 0) {
|
|
93
|
+
const hint = SETUP_HINTS[settingKeyToProp(keys[0])];
|
|
94
|
+
if (hint) {
|
|
95
|
+
this.log(groupTitle);
|
|
96
|
+
this.log(` ${'─'.repeat(49)}`);
|
|
97
|
+
this.log(` ${chalk.dim(`Run ${hint} to configure.`)}`);
|
|
98
|
+
this.log('');
|
|
90
99
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
displayValue += ` ${chalk.red('✗ not verified')}`;
|
|
102
|
-
}
|
|
103
|
-
this.log(` ${key.padEnd(16)} ${displayValue}`);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
this.log(groupTitle);
|
|
103
|
+
this.log(` ${'─'.repeat(49)}`);
|
|
104
|
+
for (const key of availableKeys) {
|
|
105
|
+
const propKey = settingKeyToProp(key);
|
|
106
|
+
const value = project[propKey];
|
|
107
|
+
let displayValue = value ? String(value) : chalk.dim('(not set)');
|
|
108
|
+
if (key === 'domain' && value && domainVerified === true) {
|
|
109
|
+
displayValue += ` ${chalk.green('✓ verified')}`;
|
|
104
110
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
for (const key of missingKeys) {
|
|
108
|
-
const hint = SETUP_HINTS[settingKeyToProp(key)];
|
|
109
|
-
if (hint) {
|
|
110
|
-
this.log(` ${key.padEnd(16)} ${chalk.dim(`(run ${hint} to set up)`)}`);
|
|
111
|
-
}
|
|
111
|
+
else if (key === 'domain' && value && domainVerified === false) {
|
|
112
|
+
displayValue += ` ${chalk.red('✗ not verified')}`;
|
|
112
113
|
}
|
|
113
|
-
this.log(
|
|
114
|
+
this.log(` ${key.padEnd(16)} ${displayValue}`);
|
|
114
115
|
}
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
const missingKeys = keys.filter((key) => !(settingKeyToProp(key) in project) &&
|
|
117
|
+
!(group === 'brand' && key === 'logo_file'));
|
|
118
|
+
for (const key of missingKeys) {
|
|
119
|
+
const hint = SETUP_HINTS[settingKeyToProp(key)];
|
|
120
|
+
if (hint) {
|
|
121
|
+
this.log(` ${key.padEnd(16)} ${chalk.dim(`(run ${hint} to set up)`)}`);
|
|
122
|
+
}
|
|
117
123
|
}
|
|
124
|
+
this.log('');
|
|
118
125
|
}
|
|
119
126
|
/**
|
|
120
127
|
* Prompts the user to pick a setting key to edit and dispatches
|
package/dist/lib/constants.d.ts
CHANGED
package/dist/lib/constants.js
CHANGED
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED