@mailmodo/cli 0.0.15-beta.pr17.25 → 0.0.15-beta.pr18.27

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.
@@ -1,7 +1,6 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import { confirm } from '@inquirer/prompts';
3
3
  import chalk from 'chalk';
4
- import { writeFile } from 'node:fs/promises';
5
4
  import { BaseCommand } from '../../lib/base-command.js';
6
5
  import { API_ENDPOINTS } from '../../lib/constants.js';
7
6
  export default class Contacts extends BaseCommand {
@@ -9,7 +8,7 @@ export default class Contacts extends BaseCommand {
9
8
  static examples = [
10
9
  '<%= config.bin %> contacts',
11
10
  '<%= config.bin %> contacts --search sarah@example.com',
12
- "<%= config.bin %> contacts --export # GDPR CSV → contacts.csv",
11
+ '<%= config.bin %> contacts --export',
13
12
  '<%= config.bin %> contacts --delete sarah@example.com',
14
13
  ];
15
14
  static flags = {
@@ -19,7 +18,7 @@ export default class Contacts extends BaseCommand {
19
18
  }),
20
19
  export: Flags.boolean({
21
20
  default: false,
22
- description: 'Export all contacts as GDPR-compliant CSV (writes contacts.csv in the current directory)',
21
+ description: 'Export all contacts as CSV',
23
22
  }),
24
23
  search: Flags.string({ description: 'Search for a contact by email' }),
25
24
  };
@@ -107,19 +106,10 @@ export default class Contacts extends BaseCommand {
107
106
  return;
108
107
  }
109
108
  this.log(`\n ${chalk.green('✓')} Contact export started.`);
110
- const { downloadUrl, status } = response.data;
111
- if (!downloadUrl) {
112
- this.log(`\n Export status: ${status ?? 'unknown'}. No download URL yet.\n`);
113
- return;
114
- }
115
- const url = `https://${downloadUrl}`;
116
- const fileResult = await this.apiClient.getFile(url);
117
- if (!fileResult.ok) {
118
- this.error(`Download failed: ${fileResult.status} ${fileResult.error ?? ''}\n` +
119
- ` URL: ${fileResult.debug.fullUrl}`);
109
+ if (response.data?.downloadUrl) {
110
+ this.log(` Download: ${chalk.cyan(response.data.downloadUrl)}`);
120
111
  }
121
- await writeFile('contacts.csv', Buffer.from(fileResult.body));
122
- this.log(`\n ${chalk.green('✓')} Contact export saved to ${chalk.cyan('contacts.csv')}\n`);
112
+ this.log('');
123
113
  }
124
114
  /**
125
115
  * Performs a GDPR-compliant hard delete of a contact and all their
@@ -110,8 +110,7 @@ export default class Init extends BaseCommand {
110
110
  json: flags.json,
111
111
  text: ' Generating email templates...',
112
112
  }, () => this.apiClient.post(API_ENDPOINTS.GENERATE, {
113
- analysis: analysisPayload,
114
- productUrl,
113
+ ...analysisPayload,
115
114
  }));
116
115
  if (!generateResponse.ok) {
117
116
  this.handleApiError(generateResponse);
@@ -1,4 +1,3 @@
1
- import { type FileFetchResult } from './fetch-file.js';
2
1
  /**
3
2
  * Request context attached to API responses for troubleshooting failed calls.
4
3
  * Only the resolved URL is stored; it encodes origin, path, and query string.
@@ -39,11 +38,6 @@ export declare class ApiClient {
39
38
  private request;
40
39
  delete<T = Record<string, unknown>>(path: string): Promise<ApiResponse<T>>;
41
40
  get<T = Record<string, unknown>>(path: string, params?: Record<string, string>): Promise<ApiResponse<T>>;
42
- /**
43
- * GET an absolute URL and return the raw body (e.g. CSV export). Uses the same
44
- * Bearer auth as other requests; does not parse JSON.
45
- */
46
- getFile(url: string): Promise<FileFetchResult>;
47
41
  patch<T = Record<string, unknown>>(path: string, body?: Record<string, unknown>): Promise<ApiResponse<T>>;
48
42
  post<T = Record<string, unknown>>(path: string, body?: Record<string, unknown> | unknown): Promise<ApiResponse<T>>;
49
43
  postFormData<T = Record<string, unknown>>(path: string, formData: FormData): Promise<ApiResponse<T>>;
@@ -1,5 +1,4 @@
1
1
  import { API_BASE_URL } from './constants.js';
2
- import { fetchFileWithBearerAuth, } from './fetch-file.js';
3
2
  /**
4
3
  * HTTP client for the Mailmodo CLI API.
5
4
  * Wraps the native fetch API with Bearer token authentication,
@@ -116,13 +115,6 @@ export class ApiClient {
116
115
  async get(path, params) {
117
116
  return this.request('GET', path, undefined, params);
118
117
  }
119
- /**
120
- * GET an absolute URL and return the raw body (e.g. CSV export). Uses the same
121
- * Bearer auth as other requests; does not parse JSON.
122
- */
123
- async getFile(url) {
124
- return fetchFileWithBearerAuth(url, this.apiKey);
125
- }
126
118
  async patch(path, body) {
127
119
  return this.request('PATCH', path, body);
128
120
  }
@@ -13,7 +13,7 @@ export declare const API_ENDPOINTS: Readonly<{
13
13
  DOMAIN_VERIFY: "/domain/verify";
14
14
  EDIT: "/edit";
15
15
  EVENTS: "/events";
16
- GENERATE: "/generate";
16
+ GENERATE: "/email/generate";
17
17
  LOGS: "/logs";
18
18
  PREVIEW: "/preview";
19
19
  SEQUENCES: "/sequences";
@@ -19,7 +19,7 @@ export const API_ENDPOINTS = Object.freeze({
19
19
  DOMAIN_VERIFY: '/domain/verify',
20
20
  EDIT: '/edit',
21
21
  EVENTS: '/events',
22
- GENERATE: '/generate',
22
+ GENERATE: '/email/generate',
23
23
  LOGS: '/logs',
24
24
  PREVIEW: '/preview',
25
25
  SEQUENCES: '/sequences',
@@ -60,7 +60,7 @@
60
60
  "examples": [
61
61
  "<%= config.bin %> contacts",
62
62
  "<%= config.bin %> contacts --search sarah@example.com",
63
- "<%= config.bin %> contacts --export # GDPR CSV → contacts.csv",
63
+ "<%= config.bin %> contacts --export",
64
64
  "<%= config.bin %> contacts --delete sarah@example.com"
65
65
  ],
66
66
  "flags": {
@@ -85,7 +85,7 @@
85
85
  "type": "option"
86
86
  },
87
87
  "export": {
88
- "description": "Export all contacts as GDPR-compliant CSV (writes contacts.csv in the current directory)",
88
+ "description": "Export all contacts as CSV",
89
89
  "name": "export",
90
90
  "allowNo": false,
91
91
  "type": "boolean"
@@ -205,13 +205,19 @@
205
205
  "index.js"
206
206
  ]
207
207
  },
208
- "emails": {
208
+ "edit": {
209
209
  "aliases": [],
210
- "args": {},
211
- "description": "List and view configured email sequences",
210
+ "args": {
211
+ "id": {
212
+ "description": "Email ID to edit",
213
+ "name": "id",
214
+ "required": true
215
+ }
216
+ },
217
+ "description": "Edit an email using AI-assisted natural language changes",
212
218
  "examples": [
213
- "<%= config.bin %> emails",
214
- "<%= config.bin %> emails --json"
219
+ "<%= config.bin %> edit welcome",
220
+ "<%= config.bin %> edit welcome --change \"make subject more urgent\" --yes"
215
221
  ],
216
222
  "flags": {
217
223
  "json": {
@@ -226,11 +232,18 @@
226
232
  "name": "yes",
227
233
  "allowNo": false,
228
234
  "type": "boolean"
235
+ },
236
+ "change": {
237
+ "description": "Natural language description of the change",
238
+ "name": "change",
239
+ "hasDynamicHelp": false,
240
+ "multiple": false,
241
+ "type": "option"
229
242
  }
230
243
  },
231
244
  "hasDynamicHelp": false,
232
245
  "hiddenAliases": [],
233
- "id": "emails",
246
+ "id": "edit",
234
247
  "pluginAlias": "@mailmodo/cli",
235
248
  "pluginName": "@mailmodo/cli",
236
249
  "pluginType": "core",
@@ -240,23 +253,17 @@
240
253
  "relativePath": [
241
254
  "dist",
242
255
  "commands",
243
- "emails",
256
+ "edit",
244
257
  "index.js"
245
258
  ]
246
259
  },
247
- "edit": {
260
+ "emails": {
248
261
  "aliases": [],
249
- "args": {
250
- "id": {
251
- "description": "Email ID to edit",
252
- "name": "id",
253
- "required": true
254
- }
255
- },
256
- "description": "Edit an email using AI-assisted natural language changes",
262
+ "args": {},
263
+ "description": "List and view configured email sequences",
257
264
  "examples": [
258
- "<%= config.bin %> edit welcome",
259
- "<%= config.bin %> edit welcome --change \"make subject more urgent\" --yes"
265
+ "<%= config.bin %> emails",
266
+ "<%= config.bin %> emails --json"
260
267
  ],
261
268
  "flags": {
262
269
  "json": {
@@ -271,18 +278,11 @@
271
278
  "name": "yes",
272
279
  "allowNo": false,
273
280
  "type": "boolean"
274
- },
275
- "change": {
276
- "description": "Natural language description of the change",
277
- "name": "change",
278
- "hasDynamicHelp": false,
279
- "multiple": false,
280
- "type": "option"
281
281
  }
282
282
  },
283
283
  "hasDynamicHelp": false,
284
284
  "hiddenAliases": [],
285
- "id": "edit",
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
- "edit",
295
+ "emails",
296
296
  "index.js"
297
297
  ]
298
298
  },
@@ -531,13 +531,14 @@
531
531
  "index.js"
532
532
  ]
533
533
  },
534
- "status": {
534
+ "settings": {
535
535
  "aliases": [],
536
536
  "args": {},
537
- "description": "View email performance metrics and quota usage",
537
+ "description": "View and update project settings",
538
538
  "examples": [
539
- "<%= config.bin %> status",
540
- "<%= config.bin %> status --json"
539
+ "<%= config.bin %> settings",
540
+ "<%= config.bin %> settings --set brand_color=#0F3460",
541
+ "<%= config.bin %> settings --json"
541
542
  ],
542
543
  "flags": {
543
544
  "json": {
@@ -552,11 +553,18 @@
552
553
  "name": "yes",
553
554
  "allowNo": false,
554
555
  "type": "boolean"
556
+ },
557
+ "set": {
558
+ "description": "Set a setting (format: key=value)",
559
+ "name": "set",
560
+ "hasDynamicHelp": false,
561
+ "multiple": false,
562
+ "type": "option"
555
563
  }
556
564
  },
557
565
  "hasDynamicHelp": false,
558
566
  "hiddenAliases": [],
559
- "id": "status",
567
+ "id": "settings",
560
568
  "pluginAlias": "@mailmodo/cli",
561
569
  "pluginName": "@mailmodo/cli",
562
570
  "pluginType": "core",
@@ -566,18 +574,17 @@
566
574
  "relativePath": [
567
575
  "dist",
568
576
  "commands",
569
- "status",
577
+ "settings",
570
578
  "index.js"
571
579
  ]
572
580
  },
573
- "settings": {
581
+ "status": {
574
582
  "aliases": [],
575
583
  "args": {},
576
- "description": "View and update project settings",
584
+ "description": "View email performance metrics and quota usage",
577
585
  "examples": [
578
- "<%= config.bin %> settings",
579
- "<%= config.bin %> settings --set brand_color=#0F3460",
580
- "<%= config.bin %> settings --json"
586
+ "<%= config.bin %> status",
587
+ "<%= config.bin %> status --json"
581
588
  ],
582
589
  "flags": {
583
590
  "json": {
@@ -592,18 +599,11 @@
592
599
  "name": "yes",
593
600
  "allowNo": false,
594
601
  "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"
602
602
  }
603
603
  },
604
604
  "hasDynamicHelp": false,
605
605
  "hiddenAliases": [],
606
- "id": "settings",
606
+ "id": "status",
607
607
  "pluginAlias": "@mailmodo/cli",
608
608
  "pluginName": "@mailmodo/cli",
609
609
  "pluginType": "core",
@@ -613,10 +613,10 @@
613
613
  "relativePath": [
614
614
  "dist",
615
615
  "commands",
616
- "settings",
616
+ "status",
617
617
  "index.js"
618
618
  ]
619
619
  }
620
620
  },
621
- "version": "0.0.15-beta.pr17.25"
621
+ "version": "0.0.15-beta.pr18.27"
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.15-beta.pr17.25",
4
+ "version": "0.0.15-beta.pr18.27",
5
5
  "author": "provishalk",
6
6
  "bin": {
7
7
  "mailmodo": "bin/run.js"
@@ -1,14 +0,0 @@
1
- export interface FileFetchResult {
2
- body: ArrayBuffer;
3
- debug: {
4
- fullUrl: string;
5
- };
6
- error?: string;
7
- ok: boolean;
8
- status: number;
9
- }
10
- /**
11
- * GET an absolute URL and return the raw body (e.g. CSV). Uses Bearer auth;
12
- * does not parse JSON.
13
- */
14
- export declare function fetchFileWithBearerAuth(url: string, apiKey: string): Promise<FileFetchResult>;
@@ -1,51 +0,0 @@
1
- const USER_AGENT = '@mailmodo/cli';
2
- /**
3
- * GET an absolute URL and return the raw body (e.g. CSV). Uses Bearer auth;
4
- * does not parse JSON.
5
- */
6
- export async function fetchFileWithBearerAuth(url, apiKey) {
7
- let href;
8
- try {
9
- href = new URL(url.trim()).toString();
10
- }
11
- catch {
12
- return {
13
- body: new ArrayBuffer(0),
14
- debug: { fullUrl: url.trim() },
15
- error: 'Invalid URL',
16
- ok: false,
17
- status: 0,
18
- };
19
- }
20
- const debug = { fullUrl: href };
21
- try {
22
- const response = await fetch(href, {
23
- headers: {
24
- Authorization: `Bearer ${apiKey}`,
25
- 'User-Agent': USER_AGENT,
26
- },
27
- method: 'GET',
28
- });
29
- const body = await response.arrayBuffer();
30
- if (!response.ok) {
31
- return {
32
- body: new ArrayBuffer(0),
33
- debug,
34
- error: response.statusText,
35
- ok: false,
36
- status: response.status,
37
- };
38
- }
39
- return { body, debug, ok: true, status: response.status };
40
- }
41
- catch (error) {
42
- const err = error;
43
- return {
44
- body: new ArrayBuffer(0),
45
- debug,
46
- error: err?.message || 'Request failed.',
47
- ok: false,
48
- status: 0,
49
- };
50
- }
51
- }