@cakemail-org/cakemail-cli 1.3.0 → 1.5.0

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.
Files changed (80) hide show
  1. package/dist/cli.js +40 -6
  2. package/dist/cli.js.map +1 -1
  3. package/dist/client.js +0 -2
  4. package/dist/client.js.map +1 -1
  5. package/dist/commands/account.d.ts +5 -0
  6. package/dist/commands/account.d.ts.map +1 -0
  7. package/dist/commands/account.js +231 -0
  8. package/dist/commands/account.js.map +1 -0
  9. package/dist/commands/attributes.d.ts.map +1 -1
  10. package/dist/commands/attributes.js +43 -15
  11. package/dist/commands/attributes.js.map +1 -1
  12. package/dist/commands/campaigns.d.ts.map +1 -1
  13. package/dist/commands/campaigns.js +153 -19
  14. package/dist/commands/campaigns.js.map +1 -1
  15. package/dist/commands/config.d.ts +8 -0
  16. package/dist/commands/config.d.ts.map +1 -0
  17. package/dist/commands/config.js +235 -0
  18. package/dist/commands/config.js.map +1 -0
  19. package/dist/commands/contacts.d.ts.map +1 -1
  20. package/dist/commands/contacts.js +233 -38
  21. package/dist/commands/contacts.js.map +1 -1
  22. package/dist/commands/lists.d.ts.map +1 -1
  23. package/dist/commands/lists.js +160 -23
  24. package/dist/commands/lists.js.map +1 -1
  25. package/dist/commands/reports.d.ts.map +1 -1
  26. package/dist/commands/reports.js +90 -13
  27. package/dist/commands/reports.js.map +1 -1
  28. package/dist/commands/segments.d.ts.map +1 -1
  29. package/dist/commands/segments.js +59 -21
  30. package/dist/commands/segments.js.map +1 -1
  31. package/dist/commands/senders.d.ts.map +1 -1
  32. package/dist/commands/senders.js +36 -5
  33. package/dist/commands/senders.js.map +1 -1
  34. package/dist/commands/suppressed.d.ts.map +1 -1
  35. package/dist/commands/suppressed.js +20 -6
  36. package/dist/commands/suppressed.js.map +1 -1
  37. package/dist/commands/templates.d.ts.map +1 -1
  38. package/dist/commands/templates.js +11 -3
  39. package/dist/commands/templates.js.map +1 -1
  40. package/dist/types/profile.d.ts +92 -0
  41. package/dist/types/profile.d.ts.map +1 -0
  42. package/dist/types/profile.js +119 -0
  43. package/dist/types/profile.js.map +1 -0
  44. package/dist/utils/auth.d.ts +26 -0
  45. package/dist/utils/auth.d.ts.map +1 -0
  46. package/dist/utils/auth.js +198 -0
  47. package/dist/utils/auth.js.map +1 -0
  48. package/dist/utils/config-file.d.ts +92 -0
  49. package/dist/utils/config-file.d.ts.map +1 -0
  50. package/dist/utils/config-file.js +244 -0
  51. package/dist/utils/config-file.js.map +1 -0
  52. package/dist/utils/config.d.ts +11 -2
  53. package/dist/utils/config.d.ts.map +1 -1
  54. package/dist/utils/config.js +74 -8
  55. package/dist/utils/config.js.map +1 -1
  56. package/dist/utils/confirm.d.ts +38 -0
  57. package/dist/utils/confirm.d.ts.map +1 -0
  58. package/dist/utils/confirm.js +124 -0
  59. package/dist/utils/confirm.js.map +1 -0
  60. package/dist/utils/defaults.d.ts +39 -0
  61. package/dist/utils/defaults.d.ts.map +1 -0
  62. package/dist/utils/defaults.js +195 -0
  63. package/dist/utils/defaults.js.map +1 -0
  64. package/dist/utils/errors.d.ts +67 -0
  65. package/dist/utils/errors.d.ts.map +1 -0
  66. package/dist/utils/errors.js +395 -0
  67. package/dist/utils/errors.js.map +1 -0
  68. package/dist/utils/interactive.d.ts +97 -0
  69. package/dist/utils/interactive.d.ts.map +1 -0
  70. package/dist/utils/interactive.js +265 -0
  71. package/dist/utils/interactive.js.map +1 -0
  72. package/dist/utils/output.d.ts +72 -2
  73. package/dist/utils/output.d.ts.map +1 -1
  74. package/dist/utils/output.js +383 -37
  75. package/dist/utils/output.js.map +1 -1
  76. package/dist/utils/progress.d.ts +139 -0
  77. package/dist/utils/progress.d.ts.map +1 -0
  78. package/dist/utils/progress.js +216 -0
  79. package/dist/utils/progress.js.map +1 -0
  80. package/package.json +3 -1
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Configuration File Management
3
+ *
4
+ * Handles reading/writing ~/.cakemail/config.json
5
+ * Supports migration from .env to config file
6
+ */
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import * as os from 'os';
10
+ import { getDefaultProfile } from '../types/profile.js';
11
+ const CONFIG_DIR = path.join(os.homedir(), '.cakemail');
12
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
13
+ /**
14
+ * Ensure config directory exists
15
+ */
16
+ export function ensureConfigDir() {
17
+ if (!fs.existsSync(CONFIG_DIR)) {
18
+ fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
19
+ }
20
+ }
21
+ /**
22
+ * Check if config file exists
23
+ */
24
+ export function configFileExists() {
25
+ return fs.existsSync(CONFIG_FILE);
26
+ }
27
+ /**
28
+ * Load config file
29
+ * Returns undefined if file doesn't exist
30
+ */
31
+ export function loadConfigFile() {
32
+ if (!configFileExists()) {
33
+ return undefined;
34
+ }
35
+ try {
36
+ const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
37
+ return JSON.parse(content);
38
+ }
39
+ catch (error) {
40
+ console.error(`Error reading config file: ${error}`);
41
+ return undefined;
42
+ }
43
+ }
44
+ /**
45
+ * Save config file
46
+ */
47
+ export function saveConfigFile(config) {
48
+ ensureConfigDir();
49
+ try {
50
+ const content = JSON.stringify(config, null, 2);
51
+ fs.writeFileSync(CONFIG_FILE, content, { mode: 0o600 });
52
+ }
53
+ catch (error) {
54
+ throw new Error(`Failed to save config file: ${error}`);
55
+ }
56
+ }
57
+ /**
58
+ * Update config file (merge with existing)
59
+ */
60
+ export function updateConfigFile(updates) {
61
+ const existing = loadConfigFile() || { version: '1.0' };
62
+ const merged = mergeConfig(existing, updates);
63
+ saveConfigFile(merged);
64
+ }
65
+ /**
66
+ * Deep merge two config objects
67
+ */
68
+ function mergeConfig(base, updates) {
69
+ return {
70
+ ...base,
71
+ ...updates,
72
+ auth: updates.auth ? { ...base.auth, ...updates.auth } : base.auth,
73
+ profiles: updates.profiles ? { ...base.profiles, ...updates.profiles } : base.profiles,
74
+ defaults: updates.defaults ? { ...base.defaults, ...updates.defaults } : base.defaults,
75
+ };
76
+ }
77
+ /**
78
+ * Get current profile from config file
79
+ */
80
+ export function getCurrentProfile() {
81
+ const config = loadConfigFile();
82
+ return config?.profile || 'balanced';
83
+ }
84
+ /**
85
+ * Set current profile in config file
86
+ */
87
+ export function setCurrentProfile(profile) {
88
+ updateConfigFile({ profile });
89
+ }
90
+ /**
91
+ * Get profile configuration
92
+ * Merges default profile with custom overrides
93
+ */
94
+ export function getProfileConfig(profileType) {
95
+ const profile = profileType || getCurrentProfile();
96
+ const defaults = getDefaultProfile(profile);
97
+ const config = loadConfigFile();
98
+ // No config file, return defaults
99
+ if (!config) {
100
+ return defaults;
101
+ }
102
+ // Merge profile-specific overrides
103
+ const profileOverrides = config.profiles?.[profile];
104
+ const customOverrides = config.profiles?.custom;
105
+ return mergeProfileConfig(defaults, profileOverrides || {}, customOverrides || {});
106
+ }
107
+ /**
108
+ * Deep merge profile configurations
109
+ */
110
+ function mergeProfileConfig(base, ...overrides) {
111
+ let result = { ...base };
112
+ for (const override of overrides) {
113
+ result = {
114
+ output: { ...result.output, ...override.output },
115
+ behavior: { ...result.behavior, ...override.behavior },
116
+ display: { ...result.display, ...override.display },
117
+ };
118
+ }
119
+ return result;
120
+ }
121
+ /**
122
+ * Set a custom profile config value
123
+ * Example: setProfileConfigValue('output.format', 'table')
124
+ */
125
+ export function setProfileConfigValue(key, value) {
126
+ const config = loadConfigFile() || { version: '1.0' };
127
+ if (!config.profiles) {
128
+ config.profiles = {};
129
+ }
130
+ if (!config.profiles.custom) {
131
+ config.profiles.custom = {};
132
+ }
133
+ // Parse nested key (e.g., "output.format")
134
+ const parts = key.split('.');
135
+ let target = config.profiles.custom;
136
+ for (let i = 0; i < parts.length - 1; i++) {
137
+ const part = parts[i];
138
+ if (!target[part]) {
139
+ target[part] = {};
140
+ }
141
+ target = target[part];
142
+ }
143
+ target[parts[parts.length - 1]] = value;
144
+ saveConfigFile(config);
145
+ }
146
+ /**
147
+ * Reset custom profile config
148
+ */
149
+ export function resetProfileConfig() {
150
+ const config = loadConfigFile();
151
+ if (!config)
152
+ return;
153
+ if (config.profiles) {
154
+ delete config.profiles.custom;
155
+ }
156
+ saveConfigFile(config);
157
+ }
158
+ /**
159
+ * Migrate .env to config file
160
+ * This runs once when user first upgrades to profile system
161
+ */
162
+ export function migrateFromEnv() {
163
+ // Check if config already exists
164
+ if (configFileExists()) {
165
+ return loadConfigFile();
166
+ }
167
+ // Try to read from .env
168
+ const envPath = path.join(process.cwd(), '.env');
169
+ if (!fs.existsSync(envPath)) {
170
+ return undefined;
171
+ }
172
+ const config = {
173
+ version: '1.0',
174
+ profile: 'balanced', // Default for existing users
175
+ };
176
+ // Read .env file
177
+ const envContent = fs.readFileSync(envPath, 'utf-8');
178
+ const lines = envContent.split('\n');
179
+ for (const line of lines) {
180
+ const trimmed = line.trim();
181
+ if (!trimmed || trimmed.startsWith('#'))
182
+ continue;
183
+ const [key, value] = trimmed.split('=').map(s => s.trim());
184
+ if (!key || !value)
185
+ continue;
186
+ // Remove quotes
187
+ const cleanValue = value.replace(/^["']|["']$/g, '');
188
+ // Map env vars to config
189
+ if (key === 'CAKEMAIL_EMAIL' || key === 'CAKEMAIL_USERNAME') {
190
+ if (!config.auth)
191
+ config.auth = {};
192
+ config.auth.email = cleanValue;
193
+ }
194
+ else if (key === 'CAKEMAIL_ACCESS_TOKEN') {
195
+ if (!config.auth)
196
+ config.auth = {};
197
+ config.auth.token = cleanValue;
198
+ }
199
+ else if (key === 'CAKEMAIL_API_BASE') {
200
+ if (!config.auth)
201
+ config.auth = {};
202
+ config.auth.base_url = cleanValue;
203
+ }
204
+ else if (key === 'CAKEMAIL_CURRENT_ACCOUNT_ID') {
205
+ if (!config.defaults)
206
+ config.defaults = {};
207
+ config.defaults.account_id = cleanValue;
208
+ }
209
+ }
210
+ // Save migrated config
211
+ if (config.auth) {
212
+ saveConfigFile(config);
213
+ return config;
214
+ }
215
+ return undefined;
216
+ }
217
+ /**
218
+ * Get defaults (list_id, sender_id, account_id)
219
+ */
220
+ export function getDefaults() {
221
+ const config = loadConfigFile();
222
+ return {
223
+ list_id: config?.defaults?.list_id,
224
+ sender_id: config?.defaults?.sender_id,
225
+ account_id: config?.defaults?.account_id,
226
+ };
227
+ }
228
+ /**
229
+ * Set a default value
230
+ */
231
+ export function setDefault(key, value) {
232
+ const config = loadConfigFile() || { version: '1.0' };
233
+ if (!config.defaults) {
234
+ config.defaults = {};
235
+ }
236
+ if (key === 'account_id') {
237
+ config.defaults.account_id = value;
238
+ }
239
+ else {
240
+ config.defaults[key] = value;
241
+ }
242
+ saveConfigFile(config);
243
+ }
244
+ //# sourceMappingURL=config-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-file.js","sourceRoot":"","sources":["../../src/utils/config-file.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,16 @@
1
1
  import { CakemailConfig } from '../client.js';
2
- export type OutputFormat = 'json' | 'table' | 'compact';
2
+ import { ProfileType, ProfileConfig, OutputFormat } from '../types/profile.js';
3
+ export type { OutputFormat, ProfileType, ProfileConfig };
3
4
  export interface FullConfig extends CakemailConfig {
4
5
  outputFormat?: OutputFormat;
6
+ currentAccountId?: string;
7
+ profile?: ProfileType;
8
+ profileConfig?: ProfileConfig;
5
9
  }
6
- export declare function getConfig(required?: boolean): FullConfig;
10
+ export declare function getConfig(required?: boolean, interactive?: boolean): Promise<FullConfig>;
11
+ /**
12
+ * Synchronous version of getConfig for backwards compatibility
13
+ * Use this only when you're certain credentials are already set
14
+ */
15
+ export declare function getConfigSync(required?: boolean): FullConfig;
7
16
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAK9C,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,wBAAgB,SAAS,CAAC,QAAQ,GAAE,OAAc,GAAG,UAAU,CAoB9D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAa/E,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;AAEzD,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,wBAAsB,SAAS,CAAC,QAAQ,GAAE,OAAc,EAAE,WAAW,GAAE,OAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAqD1G;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,GAAE,OAAc,GAAG,UAAU,CAuClE"}
@@ -1,14 +1,77 @@
1
1
  import { config } from 'dotenv';
2
- // Load .env from current working directory
2
+ import { authenticateInteractively } from './auth.js';
3
+ import { loadConfigFile, getProfileConfig, getCurrentProfile, migrateFromEnv } from './config-file.js';
4
+ // Load .env from current working directory (fallback for backward compatibility)
3
5
  config({ path: process.cwd() + '/.env' });
4
- export function getConfig(required = true) {
5
- const accessToken = process.env.CAKEMAIL_ACCESS_TOKEN;
6
- const email = process.env.CAKEMAIL_EMAIL || process.env.CAKEMAIL_USERNAME;
7
- const password = process.env.CAKEMAIL_PASSWORD;
8
- const baseURL = process.env.CAKEMAIL_API_BASE;
9
- const outputFormat = (process.env.CAKEMAIL_OUTPUT_FORMAT || 'json');
6
+ export async function getConfig(required = true, interactive = true) {
7
+ // Try to load from config file first
8
+ let configFile = loadConfigFile();
9
+ // If no config file exists, try to migrate from .env
10
+ if (!configFile) {
11
+ configFile = migrateFromEnv();
12
+ }
13
+ // Load credentials from config file or .env
14
+ let accessToken = configFile?.auth?.token || process.env.CAKEMAIL_ACCESS_TOKEN;
15
+ let email = configFile?.auth?.email || process.env.CAKEMAIL_EMAIL || process.env.CAKEMAIL_USERNAME;
16
+ let password = process.env.CAKEMAIL_PASSWORD; // Password not stored in config (security)
17
+ const baseURL = configFile?.auth?.base_url || process.env.CAKEMAIL_API_BASE;
18
+ const currentAccountId = configFile?.defaults?.account_id || process.env.CAKEMAIL_CURRENT_ACCOUNT_ID || undefined;
19
+ // Load profile configuration
20
+ const profile = getCurrentProfile();
21
+ const profileConfig = getProfileConfig(profile);
22
+ // Output format priority: env var > profile config > default
23
+ const outputFormat = process.env.CAKEMAIL_OUTPUT_FORMAT || profileConfig.output.format;
24
+ // If credentials are missing and interactive mode is enabled, prompt the user
25
+ if (required && !accessToken && (!email || !password)) {
26
+ if (interactive) {
27
+ // Interactive authentication flow
28
+ const credentials = await authenticateInteractively();
29
+ email = credentials.email;
30
+ password = credentials.password;
31
+ // Reload config file (it was updated by auth flow)
32
+ configFile = loadConfigFile();
33
+ // Reload .env to get any updates from authentication (backward compatibility)
34
+ config({ path: process.cwd() + '/.env', override: true });
35
+ }
36
+ else {
37
+ throw new Error('Missing credentials. Set CAKEMAIL_ACCESS_TOKEN or (CAKEMAIL_EMAIL and CAKEMAIL_PASSWORD) in environment variables, .env file, or run authentication');
38
+ }
39
+ }
40
+ return {
41
+ accessToken,
42
+ email,
43
+ password,
44
+ baseURL,
45
+ outputFormat,
46
+ currentAccountId,
47
+ profile,
48
+ profileConfig,
49
+ };
50
+ }
51
+ /**
52
+ * Synchronous version of getConfig for backwards compatibility
53
+ * Use this only when you're certain credentials are already set
54
+ */
55
+ export function getConfigSync(required = true) {
56
+ // Try to load from config file first
57
+ let configFile = loadConfigFile();
58
+ // If no config file exists, try to migrate from .env
59
+ if (!configFile) {
60
+ configFile = migrateFromEnv();
61
+ }
62
+ // Load credentials from config file or .env
63
+ const accessToken = configFile?.auth?.token || process.env.CAKEMAIL_ACCESS_TOKEN;
64
+ const email = configFile?.auth?.email || process.env.CAKEMAIL_EMAIL || process.env.CAKEMAIL_USERNAME;
65
+ const password = process.env.CAKEMAIL_PASSWORD; // Password not stored in config (security)
66
+ const baseURL = configFile?.auth?.base_url || process.env.CAKEMAIL_API_BASE;
67
+ const currentAccountId = configFile?.defaults?.account_id || process.env.CAKEMAIL_CURRENT_ACCOUNT_ID || undefined;
68
+ // Load profile configuration
69
+ const profile = getCurrentProfile();
70
+ const profileConfig = getProfileConfig(profile);
71
+ // Output format priority: env var > profile config > default
72
+ const outputFormat = process.env.CAKEMAIL_OUTPUT_FORMAT || profileConfig.output.format;
10
73
  if (required && !accessToken && (!email || !password)) {
11
- throw new Error('Missing credentials. Set CAKEMAIL_ACCESS_TOKEN or (CAKEMAIL_EMAIL and CAKEMAIL_PASSWORD) in environment variables or .env file');
74
+ throw new Error('Missing credentials. Set CAKEMAIL_ACCESS_TOKEN or (CAKEMAIL_EMAIL and CAKEMAIL_PASSWORD) in environment variables, .env file, or run authentication');
12
75
  }
13
76
  return {
14
77
  accessToken,
@@ -16,6 +79,9 @@ export function getConfig(required = true) {
16
79
  password,
17
80
  baseURL,
18
81
  outputFormat,
82
+ currentAccountId,
83
+ profile,
84
+ profileConfig,
19
85
  };
20
86
  }
21
87
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,2CAA2C;AAC3C,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AAQ1C,MAAM,UAAU,SAAS,CAAC,WAAoB,IAAI;IAChD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC1E,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC9C,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,MAAM,CAAiB,CAAC;IAEpF,IAAI,QAAQ,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,gIAAgI,CACjI,CAAC;IACJ,CAAC;IAED,OAAO;QACL,WAAW;QACX,KAAK;QACL,QAAQ;QACR,OAAO;QACP,YAAY;KACb,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { ProfileConfig } from '../types/profile.js';
2
+ /**
3
+ * Interactive confirmation utilities for destructive operations
4
+ * Profile-aware: adapts behavior based on user profile settings
5
+ */
6
+ export interface ConfirmOptions {
7
+ message?: string;
8
+ resourceType?: string;
9
+ resourceId?: string | number;
10
+ details?: string[];
11
+ dangerLevel?: 'low' | 'medium' | 'high';
12
+ profileConfig?: ProfileConfig;
13
+ }
14
+ /**
15
+ * Display confirmation prompt for destructive operations
16
+ * Returns true if user confirms, false if they cancel
17
+ * Profile-aware: skips confirmation for developer profile
18
+ */
19
+ export declare function confirm(options?: ConfirmOptions): Promise<boolean>;
20
+ /**
21
+ * Confirm deletion of a resource
22
+ */
23
+ export declare function confirmDelete(resourceType: string, resourceId: string | number, details?: string[], profileConfig?: ProfileConfig): Promise<boolean>;
24
+ /**
25
+ * Confirm deletion with high danger level (permanent, no recovery)
26
+ */
27
+ export declare function confirmDangerousDelete(resourceType: string, resourceId: string | number, details?: string[], profileConfig?: ProfileConfig): Promise<boolean>;
28
+ /**
29
+ * Confirm a custom action
30
+ */
31
+ export declare function confirmAction(message: string, details?: string[], dangerLevel?: 'low' | 'medium' | 'high', profileConfig?: ProfileConfig): Promise<boolean>;
32
+ /**
33
+ * Check if force flag is present (for backwards compatibility)
34
+ * If force flag is present, skip confirmation
35
+ * If not present, show interactive confirmation
36
+ */
37
+ export declare function shouldProceed(forceFlag: boolean, confirmOptions: ConfirmOptions): Promise<boolean>;
38
+ //# sourceMappingURL=confirm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm.d.ts","sourceRoot":"","sources":["../../src/utils/confirm.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD;;;GAGG;AAEH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACxC,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAoBD;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAmE5E;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAAG,MAAM,EAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,EAClB,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAAG,MAAM,EAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,EAClB,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,EAAE,EAClB,WAAW,GAAE,KAAK,GAAG,QAAQ,GAAG,MAAiB,EACjD,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,OAAO,EAClB,cAAc,EAAE,cAAc,GAC7B,OAAO,CAAC,OAAO,CAAC,CAQlB"}
@@ -0,0 +1,124 @@
1
+ import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+ import { isScriptingMode } from './interactive.js';
4
+ /**
5
+ * Determine if confirmation should be shown based on profile
6
+ */
7
+ function shouldConfirm(profileConfig) {
8
+ // Always skip in scripting mode
9
+ if (isScriptingMode()) {
10
+ return false;
11
+ }
12
+ // No profile config - default to confirming
13
+ if (!profileConfig) {
14
+ return true;
15
+ }
16
+ // Check profile setting for destructive operations
17
+ return profileConfig.behavior.confirm_destructive;
18
+ }
19
+ /**
20
+ * Display confirmation prompt for destructive operations
21
+ * Returns true if user confirms, false if they cancel
22
+ * Profile-aware: skips confirmation for developer profile
23
+ */
24
+ export async function confirm(options = {}) {
25
+ const { message, resourceType, resourceId, details = [], dangerLevel = 'medium', profileConfig } = options;
26
+ // Check if confirmation is needed based on profile
27
+ if (!shouldConfirm(profileConfig)) {
28
+ return true; // Auto-confirm for developer profile or scripting mode
29
+ }
30
+ // Build the confirmation message
31
+ let confirmMessage = message;
32
+ if (!confirmMessage && resourceType) {
33
+ if (resourceId) {
34
+ confirmMessage = `Delete ${resourceType} ${chalk.bold(resourceId)}?`;
35
+ }
36
+ else {
37
+ confirmMessage = `Delete this ${resourceType}?`;
38
+ }
39
+ }
40
+ if (!confirmMessage) {
41
+ confirmMessage = 'Are you sure?';
42
+ }
43
+ // Show danger level indicator
44
+ const dangerIndicators = {
45
+ low: chalk.yellow('⚠'),
46
+ medium: chalk.red('⚠'),
47
+ high: chalk.red.bold('⚠⚠⚠')
48
+ };
49
+ console.log('');
50
+ console.log(dangerIndicators[dangerLevel], chalk.bold('Confirmation Required'));
51
+ console.log('');
52
+ // Show details if provided
53
+ if (details.length > 0) {
54
+ console.log(chalk.gray('This will:'));
55
+ details.forEach(detail => {
56
+ console.log(chalk.gray(` • ${detail}`));
57
+ });
58
+ console.log('');
59
+ }
60
+ // Show warning for high danger operations
61
+ if (dangerLevel === 'high') {
62
+ console.log(chalk.red.bold('⚠ WARNING: This action cannot be undone!'));
63
+ console.log('');
64
+ }
65
+ // Prompt for confirmation
66
+ const answer = await inquirer.prompt([
67
+ {
68
+ type: 'confirm',
69
+ name: 'confirmed',
70
+ message: confirmMessage,
71
+ default: false
72
+ }
73
+ ]);
74
+ return answer.confirmed;
75
+ }
76
+ /**
77
+ * Confirm deletion of a resource
78
+ */
79
+ export async function confirmDelete(resourceType, resourceId, details, profileConfig) {
80
+ return confirm({
81
+ resourceType,
82
+ resourceId,
83
+ details,
84
+ dangerLevel: 'medium',
85
+ profileConfig
86
+ });
87
+ }
88
+ /**
89
+ * Confirm deletion with high danger level (permanent, no recovery)
90
+ */
91
+ export async function confirmDangerousDelete(resourceType, resourceId, details, profileConfig) {
92
+ return confirm({
93
+ resourceType,
94
+ resourceId,
95
+ details,
96
+ dangerLevel: 'high',
97
+ profileConfig
98
+ });
99
+ }
100
+ /**
101
+ * Confirm a custom action
102
+ */
103
+ export async function confirmAction(message, details, dangerLevel = 'medium', profileConfig) {
104
+ return confirm({
105
+ message,
106
+ details,
107
+ dangerLevel,
108
+ profileConfig
109
+ });
110
+ }
111
+ /**
112
+ * Check if force flag is present (for backwards compatibility)
113
+ * If force flag is present, skip confirmation
114
+ * If not present, show interactive confirmation
115
+ */
116
+ export async function shouldProceed(forceFlag, confirmOptions) {
117
+ // If force flag is present, skip confirmation
118
+ if (forceFlag) {
119
+ return true;
120
+ }
121
+ // Otherwise show interactive confirmation
122
+ return confirm(confirmOptions);
123
+ }
124
+ //# sourceMappingURL=confirm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm.js","sourceRoot":"","sources":["../../src/utils/confirm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { CakemailClient } from '../client.js';
2
+ import { OutputFormatter } from './output.js';
3
+ /**
4
+ * Auto-detect list ID when only one exists
5
+ * Returns the list ID if only one list exists, otherwise undefined
6
+ */
7
+ export declare function autoDetectList(client: CakemailClient, formatter: OutputFormatter, providedListId?: string | number, options?: {
8
+ silent?: boolean;
9
+ useCache?: boolean;
10
+ }): Promise<number | undefined>;
11
+ /**
12
+ * Auto-detect sender ID when only one verified sender exists
13
+ */
14
+ export declare function autoDetectSender(client: CakemailClient, formatter: OutputFormatter, providedSenderId?: string | number, options?: {
15
+ silent?: boolean;
16
+ useCache?: boolean;
17
+ requireConfirmed?: boolean;
18
+ }): Promise<string | undefined>;
19
+ /**
20
+ * Get last used list from cache
21
+ */
22
+ export declare function getLastList(): number | undefined;
23
+ /**
24
+ * Get last used sender from cache
25
+ */
26
+ export declare function getLastSender(): string | undefined;
27
+ /**
28
+ * Clear session cache (useful for testing)
29
+ */
30
+ export declare function clearCache(): void;
31
+ /**
32
+ * Suggest a default value for a missing required option
33
+ * Returns the detected value or undefined
34
+ */
35
+ export declare function suggestDefault(client: CakemailClient, formatter: OutputFormatter, type: 'list' | 'sender', options?: {
36
+ silent?: boolean;
37
+ useCache?: boolean;
38
+ }): Promise<string | number | undefined>;
39
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/utils/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA+B9C;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,eAAe,EAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,EAChC,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACrD,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuE7B;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,eAAe,EAC1B,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,EAClC,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAO,GACjF,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAkF7B;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,GAAG,SAAS,CAKhD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAKlD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAIjC;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,MAAM,GAAG,QAAQ,EACvB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACrD,OAAO,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAStC"}