@ebowwa/crm 0.1.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.
- package/README.md +174 -0
- package/dist/cli/commands/activities.d.ts +11 -0
- package/dist/cli/commands/activities.d.ts.map +1 -0
- package/dist/cli/commands/activities.js +427 -0
- package/dist/cli/commands/activities.js.map +1 -0
- package/dist/cli/commands/contacts.d.ts +11 -0
- package/dist/cli/commands/contacts.d.ts.map +1 -0
- package/dist/cli/commands/contacts.js +458 -0
- package/dist/cli/commands/contacts.js.map +1 -0
- package/dist/cli/commands/deals.d.ts +11 -0
- package/dist/cli/commands/deals.d.ts.map +1 -0
- package/dist/cli/commands/deals.js +498 -0
- package/dist/cli/commands/deals.js.map +1 -0
- package/dist/cli/commands/media.d.ts +11 -0
- package/dist/cli/commands/media.d.ts.map +1 -0
- package/dist/cli/commands/media.js +417 -0
- package/dist/cli/commands/media.js.map +1 -0
- package/dist/cli/commands/search.d.ts +11 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +346 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +173 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/repl.d.ts +15 -0
- package/dist/cli/repl.d.ts.map +1 -0
- package/dist/cli/repl.js +318 -0
- package/dist/cli/repl.js.map +1 -0
- package/dist/cli/utils/config.d.ts +91 -0
- package/dist/cli/utils/config.d.ts.map +1 -0
- package/dist/cli/utils/config.js +212 -0
- package/dist/cli/utils/config.js.map +1 -0
- package/dist/cli/utils/output.d.ts +136 -0
- package/dist/cli/utils/output.d.ts.map +1 -0
- package/dist/cli/utils/output.js +323 -0
- package/dist/cli/utils/output.js.map +1 -0
- package/dist/cli/utils/prompt.d.ts +81 -0
- package/dist/cli/utils/prompt.d.ts.map +1 -0
- package/dist/cli/utils/prompt.js +341 -0
- package/dist/cli/utils/prompt.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +8 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +32 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/schemas.d.ts +3050 -0
- package/dist/core/schemas.d.ts.map +1 -0
- package/dist/core/schemas.js +667 -0
- package/dist/core/schemas.js.map +1 -0
- package/dist/core/types.d.ts +597 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +8 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.ts +14 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +18 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/storage/client.d.ts +109 -0
- package/dist/mcp/storage/client.d.ts.map +1 -0
- package/dist/mcp/storage/client.js +355 -0
- package/dist/mcp/storage/client.js.map +1 -0
- package/dist/mcp/storage/index.d.ts +7 -0
- package/dist/mcp/storage/index.d.ts.map +1 -0
- package/dist/mcp/storage/index.js +6 -0
- package/dist/mcp/storage/index.js.map +1 -0
- package/dist/mcp/storage/types.d.ts +44 -0
- package/dist/mcp/storage/types.d.ts.map +1 -0
- package/dist/mcp/storage/types.js +35 -0
- package/dist/mcp/storage/types.js.map +1 -0
- package/dist/mcp/tools/definitions.d.ts +16 -0
- package/dist/mcp/tools/definitions.d.ts.map +1 -0
- package/dist/mcp/tools/definitions.js +914 -0
- package/dist/mcp/tools/definitions.js.map +1 -0
- package/dist/mcp/tools/handlers.d.ts +50 -0
- package/dist/mcp/tools/handlers.d.ts.map +1 -0
- package/dist/mcp/tools/handlers.js +760 -0
- package/dist/mcp/tools/handlers.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +7 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +6 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/types.d.ts +314 -0
- package/dist/mcp/tools/types.d.ts.map +1 -0
- package/dist/mcp/tools/types.js +5 -0
- package/dist/mcp/tools/types.js.map +1 -0
- package/dist/mcp/transports/stdio.d.ts +27 -0
- package/dist/mcp/transports/stdio.d.ts.map +1 -0
- package/dist/mcp/transports/stdio.js +237 -0
- package/dist/mcp/transports/stdio.js.map +1 -0
- package/dist/telemetry/index.d.ts +58 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +109 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/logger.d.ts +116 -0
- package/dist/telemetry/logger.d.ts.map +1 -0
- package/dist/telemetry/logger.js +256 -0
- package/dist/telemetry/logger.js.map +1 -0
- package/dist/telemetry/metrics.d.ts +115 -0
- package/dist/telemetry/metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics.js +292 -0
- package/dist/telemetry/metrics.js.map +1 -0
- package/dist/telemetry/tracer.d.ts +227 -0
- package/dist/telemetry/tracer.d.ts.map +1 -0
- package/dist/telemetry/tracer.js +355 -0
- package/dist/telemetry/tracer.js.map +1 -0
- package/dist/web/app.d.ts +2 -0
- package/dist/web/app.d.ts.map +1 -0
- package/dist/web/app.js +115 -0
- package/dist/web/app.js.map +1 -0
- package/dist/web/components/ContactList.d.ts +3 -0
- package/dist/web/components/ContactList.d.ts.map +1 -0
- package/dist/web/components/ContactList.js +262 -0
- package/dist/web/components/ContactList.js.map +1 -0
- package/dist/web/components/Dashboard.d.ts +3 -0
- package/dist/web/components/Dashboard.d.ts.map +1 -0
- package/dist/web/components/Dashboard.js +158 -0
- package/dist/web/components/Dashboard.js.map +1 -0
- package/dist/web/components/DealPipeline.d.ts +3 -0
- package/dist/web/components/DealPipeline.d.ts.map +1 -0
- package/dist/web/components/DealPipeline.js +306 -0
- package/dist/web/components/DealPipeline.js.map +1 -0
- package/dist/web/index.d.ts +2 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +269 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/types.d.ts +75 -0
- package/dist/web/types.d.ts.map +1 -0
- package/dist/web/types.js +3 -0
- package/dist/web/types.js.map +1 -0
- package/native/index.d.ts +571 -0
- package/native/index.js +687 -0
- package/package.json +105 -0
- package/src/cli/commands/activities.ts +543 -0
- package/src/cli/commands/contacts.ts +563 -0
- package/src/cli/commands/deals.ts +637 -0
- package/src/cli/commands/media.ts +521 -0
- package/src/cli/commands/search.ts +426 -0
- package/src/cli/index.ts +203 -0
- package/src/cli/repl.ts +379 -0
- package/src/cli/utils/config.ts +299 -0
- package/src/cli/utils/output.ts +386 -0
- package/src/cli/utils/prompt.ts +444 -0
- package/src/cli.ts +11 -0
- package/src/core/index.ts +184 -0
- package/src/core/schemas.ts +770 -0
- package/src/core/types.ts +969 -0
- package/src/index.ts +8 -0
- package/src/mcp/index.ts +17 -0
- package/src/mcp/server.ts +26 -0
- package/src/mcp/storage/client.ts +408 -0
- package/src/mcp/storage/index.ts +7 -0
- package/src/mcp/storage/types.ts +72 -0
- package/src/mcp/tools/definitions.ts +961 -0
- package/src/mcp/tools/handlers.ts +805 -0
- package/src/mcp/tools/index.ts +7 -0
- package/src/mcp/tools/types.ts +390 -0
- package/src/mcp/transports/stdio.ts +225 -0
- package/src/telemetry/index.ts +131 -0
- package/src/telemetry/logger.ts +318 -0
- package/src/telemetry/metrics.ts +393 -0
- package/src/telemetry/tracer.ts +487 -0
- package/src/web/api/activities.ts +41 -0
- package/src/web/api/contacts.ts +114 -0
- package/src/web/api/deals.ts +108 -0
- package/src/web/api/media.ts +98 -0
- package/src/web/app.tsx +143 -0
- package/src/web/components/ActivityFeed.tsx +195 -0
- package/src/web/components/ContactList.tsx +340 -0
- package/src/web/components/Dashboard.tsx +214 -0
- package/src/web/components/DealPipeline.tsx +405 -0
- package/src/web/components/MediaGallery.tsx +334 -0
- package/src/web/index.html +14 -0
- package/src/web/index.ts +326 -0
- package/src/web/styles/main.css +180 -0
- package/src/web/types.ts +311 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Prompt Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides user-friendly prompts for CLI interactions.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as readline from 'readline';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Create a readline interface
|
|
11
|
+
*/
|
|
12
|
+
function createRL(): readline.ReadLine {
|
|
13
|
+
return readline.createInterface({
|
|
14
|
+
input: process.stdin,
|
|
15
|
+
output: process.stdout,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Prompt for text input
|
|
21
|
+
*/
|
|
22
|
+
export async function prompt(
|
|
23
|
+
message: string,
|
|
24
|
+
defaultValue?: string
|
|
25
|
+
): Promise<string> {
|
|
26
|
+
const rl = createRL();
|
|
27
|
+
|
|
28
|
+
const promptText = defaultValue
|
|
29
|
+
? `${message} ${`[${defaultValue}]`}: `
|
|
30
|
+
: `${message}: `;
|
|
31
|
+
|
|
32
|
+
return new Promise((resolve) => {
|
|
33
|
+
rl.question(promptText, (answer) => {
|
|
34
|
+
rl.close();
|
|
35
|
+
resolve(answer.trim() || defaultValue || '');
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Prompt for required text input (keeps asking until provided)
|
|
42
|
+
*/
|
|
43
|
+
export async function promptRequired(
|
|
44
|
+
message: string,
|
|
45
|
+
validate?: (value: string) => boolean | string
|
|
46
|
+
): Promise<string> {
|
|
47
|
+
while (true) {
|
|
48
|
+
const value = await prompt(message);
|
|
49
|
+
|
|
50
|
+
if (!value) {
|
|
51
|
+
console.log('\x1b[31m\u2717 This field is required\x1b[0m');
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (validate) {
|
|
56
|
+
const result = validate(value);
|
|
57
|
+
if (result !== true) {
|
|
58
|
+
console.log(`\x1b[31m\u2717 ${result}\x1b[0m`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Prompt for email input with validation
|
|
69
|
+
*/
|
|
70
|
+
export async function promptEmail(message = 'Email'): Promise<string> {
|
|
71
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
72
|
+
|
|
73
|
+
return promptRequired(message, (value) => {
|
|
74
|
+
if (!emailRegex.test(value)) {
|
|
75
|
+
return 'Please enter a valid email address';
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Prompt for phone input
|
|
83
|
+
*/
|
|
84
|
+
export async function promptPhone(message = 'Phone'): Promise<string> {
|
|
85
|
+
return prompt(message);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Prompt for number input
|
|
90
|
+
*/
|
|
91
|
+
export async function promptNumber(
|
|
92
|
+
message: string,
|
|
93
|
+
defaultValue?: number,
|
|
94
|
+
min?: number,
|
|
95
|
+
max?: number
|
|
96
|
+
): Promise<number> {
|
|
97
|
+
while (true) {
|
|
98
|
+
const input = await prompt(message, defaultValue?.toString());
|
|
99
|
+
const value = parseFloat(input);
|
|
100
|
+
|
|
101
|
+
if (isNaN(value)) {
|
|
102
|
+
console.log('\x1b[31m\u2717 Please enter a valid number\x1b[0m');
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (min !== undefined && value < min) {
|
|
107
|
+
console.log(`\x1b[31m\u2717 Value must be at least ${min}\x1b[0m`);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (max !== undefined && value > max) {
|
|
112
|
+
console.log(`\x1b[31m\u2717 Value must be at most ${max}\x1b[0m`);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Prompt for integer input
|
|
122
|
+
*/
|
|
123
|
+
export async function promptInt(
|
|
124
|
+
message: string,
|
|
125
|
+
defaultValue?: number,
|
|
126
|
+
min?: number,
|
|
127
|
+
max?: number
|
|
128
|
+
): Promise<number> {
|
|
129
|
+
while (true) {
|
|
130
|
+
const value = await promptNumber(message, defaultValue, min, max);
|
|
131
|
+
if (Number.isInteger(value)) {
|
|
132
|
+
return value;
|
|
133
|
+
}
|
|
134
|
+
console.log('\x1b[31m\u2717 Please enter a whole number\x1b[0m');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Prompt for yes/no confirmation
|
|
140
|
+
*/
|
|
141
|
+
export async function confirm(
|
|
142
|
+
message: string,
|
|
143
|
+
defaultValue = false
|
|
144
|
+
): Promise<boolean> {
|
|
145
|
+
const hint = defaultValue ? '[Y/n]' : '[y/N]';
|
|
146
|
+
const answer = await prompt(`${message} ${hint}`);
|
|
147
|
+
|
|
148
|
+
if (!answer) {
|
|
149
|
+
return defaultValue;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return ['y', 'yes', 'true', '1'].includes(answer.toLowerCase());
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Prompt to select from a list of options
|
|
157
|
+
*/
|
|
158
|
+
export async function select<T extends string>(
|
|
159
|
+
message: string,
|
|
160
|
+
options: T[],
|
|
161
|
+
defaultValue?: T
|
|
162
|
+
): Promise<T> {
|
|
163
|
+
console.log(`\n${message}\n`);
|
|
164
|
+
|
|
165
|
+
options.forEach((option, index) => {
|
|
166
|
+
const num = `\x1b[36m${index + 1}.\x1b[0m`;
|
|
167
|
+
const marker = option === defaultValue ? ' (default)' : '';
|
|
168
|
+
console.log(` ${num} ${option}${marker}`);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
console.log();
|
|
172
|
+
|
|
173
|
+
while (true) {
|
|
174
|
+
const answer = await prompt('Enter choice');
|
|
175
|
+
|
|
176
|
+
if (!answer && defaultValue) {
|
|
177
|
+
return defaultValue;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Check if it's a number selection
|
|
181
|
+
const num = parseInt(answer);
|
|
182
|
+
if (!isNaN(num) && num >= 1 && num <= options.length) {
|
|
183
|
+
return options[num - 1];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Check if it matches an option directly
|
|
187
|
+
const match = options.find(
|
|
188
|
+
(o) => o.toLowerCase() === answer.toLowerCase()
|
|
189
|
+
);
|
|
190
|
+
if (match) {
|
|
191
|
+
return match as T;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
console.log('\x1b[31m\u2717 Invalid choice\x1b[0m');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Prompt to select multiple options from a list
|
|
200
|
+
*/
|
|
201
|
+
export async function multiSelect<T extends string>(
|
|
202
|
+
message: string,
|
|
203
|
+
options: T[],
|
|
204
|
+
defaultValues: T[] = []
|
|
205
|
+
): Promise<T[]> {
|
|
206
|
+
console.log(`\n${message}`);
|
|
207
|
+
console.log('\x1b[90m(Enter numbers separated by commas, or "all" for all)\x1b[0m\n');
|
|
208
|
+
|
|
209
|
+
options.forEach((option, index) => {
|
|
210
|
+
const num = `\x1b[36m${index + 1}.\x1b[0m`;
|
|
211
|
+
const marker = defaultValues.includes(option) ? ' \x1b[32m*\x1b[0m' : '';
|
|
212
|
+
console.log(` ${num} ${option}${marker}`);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
console.log();
|
|
216
|
+
|
|
217
|
+
while (true) {
|
|
218
|
+
const answer = await prompt('Enter choices');
|
|
219
|
+
|
|
220
|
+
if (!answer) {
|
|
221
|
+
return defaultValues;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (answer.toLowerCase() === 'all') {
|
|
225
|
+
return [...options];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const indices = answer.split(',').map((s) => parseInt(s.trim()));
|
|
229
|
+
const valid = indices.every((n) => !isNaN(n) && n >= 1 && n <= options.length);
|
|
230
|
+
|
|
231
|
+
if (!valid) {
|
|
232
|
+
console.log('\x1b[31m\u2717 Invalid selection\x1b[0m');
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return indices.map((n) => options[n - 1]).filter((v): v is T => v !== undefined) as T[];
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Prompt for tags (comma-separated)
|
|
242
|
+
*/
|
|
243
|
+
export async function promptTags(
|
|
244
|
+
message = 'Tags (comma-separated)'
|
|
245
|
+
): Promise<string[]> {
|
|
246
|
+
const input = await prompt(message);
|
|
247
|
+
if (!input) return [];
|
|
248
|
+
|
|
249
|
+
return input
|
|
250
|
+
.split(',')
|
|
251
|
+
.map((t) => t.trim())
|
|
252
|
+
.filter((t) => t.length > 0);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Prompt for multiline text
|
|
257
|
+
*/
|
|
258
|
+
export async function promptMultiline(
|
|
259
|
+
message: string,
|
|
260
|
+
defaultValue?: string
|
|
261
|
+
): Promise<string> {
|
|
262
|
+
console.log(`\n${message}`);
|
|
263
|
+
console.log('\x1b[90m(Enter empty line to finish)\x1b[0m\n');
|
|
264
|
+
|
|
265
|
+
if (defaultValue) {
|
|
266
|
+
console.log(`\x1b[90mCurrent:\x1b[0m ${defaultValue.split('\n')[0]}...\n`);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const lines: string[] = [];
|
|
270
|
+
const rl = createRL();
|
|
271
|
+
|
|
272
|
+
return new Promise((resolve) => {
|
|
273
|
+
const askLine = () => {
|
|
274
|
+
rl.question('', (line) => {
|
|
275
|
+
if (line.trim() === '') {
|
|
276
|
+
rl.close();
|
|
277
|
+
resolve(lines.join('\n') || defaultValue || '');
|
|
278
|
+
} else {
|
|
279
|
+
lines.push(line);
|
|
280
|
+
askLine();
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
};
|
|
284
|
+
askLine();
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Prompt with auto-complete suggestions
|
|
290
|
+
*/
|
|
291
|
+
export async function promptWithSuggestions(
|
|
292
|
+
message: string,
|
|
293
|
+
suggestions: string[],
|
|
294
|
+
defaultValue?: string
|
|
295
|
+
): Promise<string> {
|
|
296
|
+
// Show suggestions
|
|
297
|
+
console.log(`\n${message}`);
|
|
298
|
+
if (suggestions.length > 0) {
|
|
299
|
+
console.log(`\x1b[90mSuggestions: ${suggestions.slice(0, 5).join(', ')}\x1b[0m`);
|
|
300
|
+
}
|
|
301
|
+
console.log();
|
|
302
|
+
|
|
303
|
+
return prompt('', defaultValue);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Display a preview and ask for confirmation
|
|
308
|
+
*/
|
|
309
|
+
export async function previewAndConfirm(
|
|
310
|
+
title: string,
|
|
311
|
+
data: Record<string, unknown>
|
|
312
|
+
): Promise<boolean> {
|
|
313
|
+
console.log(`\n${title}`);
|
|
314
|
+
console.log('\x1b[90m' + '\u2500'.repeat(40) + '\x1b[0m');
|
|
315
|
+
|
|
316
|
+
for (const [key, value] of Object.entries(data)) {
|
|
317
|
+
if (value !== undefined && value !== '') {
|
|
318
|
+
const displayValue = Array.isArray(value)
|
|
319
|
+
? value.join(', ')
|
|
320
|
+
: String(value);
|
|
321
|
+
console.log(` \x1b[36m${key}:\x1b[0m ${displayValue}`);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
console.log();
|
|
326
|
+
return confirm('Is this correct?', true);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Progress indicator for async operations
|
|
331
|
+
*/
|
|
332
|
+
export async function withProgress<T>(
|
|
333
|
+
message: string,
|
|
334
|
+
fn: () => Promise<T>
|
|
335
|
+
): Promise<T> {
|
|
336
|
+
const frames = ['\u28d7', '\u28d3', '\u28d2', '\u28d6', '\u28d4', '\u28d5'];
|
|
337
|
+
let i = 0;
|
|
338
|
+
let interval: Timer;
|
|
339
|
+
|
|
340
|
+
process.stdout.write(`${message} `);
|
|
341
|
+
|
|
342
|
+
interval = setInterval(() => {
|
|
343
|
+
process.stdout.write(`\r${message} ${frames[i]} `);
|
|
344
|
+
i = (i + 1) % frames.length;
|
|
345
|
+
}, 80);
|
|
346
|
+
|
|
347
|
+
try {
|
|
348
|
+
const result = await fn();
|
|
349
|
+
clearInterval(interval);
|
|
350
|
+
process.stdout.write(`\r${message} \x1b[32m\u2713\x1b[0m\n`);
|
|
351
|
+
return result;
|
|
352
|
+
} catch (error) {
|
|
353
|
+
clearInterval(interval);
|
|
354
|
+
process.stdout.write(`\r${message} \x1b[31m\u2717\x1b[0m\n`);
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Display a spinner
|
|
361
|
+
*/
|
|
362
|
+
export class Spinner {
|
|
363
|
+
private frames = ['\u28d7', '\u28d3', '\u28d2', '\u28d6', '\u28d4', '\u28d5'];
|
|
364
|
+
private i = 0;
|
|
365
|
+
private interval?: Timer;
|
|
366
|
+
|
|
367
|
+
constructor(private message: string) {}
|
|
368
|
+
|
|
369
|
+
start(): this {
|
|
370
|
+
process.stdout.write(`${this.message} `);
|
|
371
|
+
this.interval = setInterval(() => {
|
|
372
|
+
process.stdout.write(`\r${this.message} ${this.frames[this.i]} `);
|
|
373
|
+
this.i = (this.i + 1) % this.frames.length;
|
|
374
|
+
}, 80);
|
|
375
|
+
return this;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
succeed(message?: string): void {
|
|
379
|
+
this.stop();
|
|
380
|
+
process.stdout.write(`\r${message || this.message} \x1b[32m\u2713\x1b[0m\n`);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
fail(message?: string): void {
|
|
384
|
+
this.stop();
|
|
385
|
+
process.stdout.write(`\r${message || this.message} \x1b[31m\u2717\x1b[0m\n`);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
update(message: string): void {
|
|
389
|
+
this.message = message;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
private stop(): void {
|
|
393
|
+
if (this.interval) {
|
|
394
|
+
clearInterval(this.interval);
|
|
395
|
+
this.interval = undefined;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Password input (hidden)
|
|
402
|
+
*/
|
|
403
|
+
export async function promptPassword(message = 'Password'): Promise<string> {
|
|
404
|
+
const rl = createRL();
|
|
405
|
+
|
|
406
|
+
return new Promise((resolve) => {
|
|
407
|
+
process.stdout.write(`${message}: `);
|
|
408
|
+
|
|
409
|
+
// Hide input
|
|
410
|
+
process.stdin.setRawMode(true);
|
|
411
|
+
const password: string[] = [];
|
|
412
|
+
|
|
413
|
+
const onData = (char: Buffer) => {
|
|
414
|
+
const c = char.toString('utf8');
|
|
415
|
+
|
|
416
|
+
switch (c) {
|
|
417
|
+
case '\n':
|
|
418
|
+
case '\r':
|
|
419
|
+
case '\u0004': // Ctrl+D
|
|
420
|
+
process.stdin.setRawMode(false);
|
|
421
|
+
process.stdin.off('data', onData);
|
|
422
|
+
rl.close();
|
|
423
|
+
console.log();
|
|
424
|
+
resolve(password.join(''));
|
|
425
|
+
break;
|
|
426
|
+
case '\u0003': // Ctrl+C
|
|
427
|
+
process.exit();
|
|
428
|
+
break;
|
|
429
|
+
case '\u007F': // Backspace
|
|
430
|
+
if (password.length > 0) {
|
|
431
|
+
password.pop();
|
|
432
|
+
process.stdout.write('\b \b');
|
|
433
|
+
}
|
|
434
|
+
break;
|
|
435
|
+
default:
|
|
436
|
+
password.push(c);
|
|
437
|
+
process.stdout.write('*');
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
process.stdin.on('data', onData);
|
|
443
|
+
});
|
|
444
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core exports for CRM types and schemas
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Re-export all types
|
|
6
|
+
export type {
|
|
7
|
+
// Base types
|
|
8
|
+
UUID,
|
|
9
|
+
Timestamp,
|
|
10
|
+
Metadata,
|
|
11
|
+
BaseEntity,
|
|
12
|
+
// Contact types
|
|
13
|
+
PhoneNumber,
|
|
14
|
+
EmailAddress,
|
|
15
|
+
Address,
|
|
16
|
+
SocialProfile,
|
|
17
|
+
CustomField,
|
|
18
|
+
ContactSource,
|
|
19
|
+
ContactStatus,
|
|
20
|
+
Contact,
|
|
21
|
+
// Deal types
|
|
22
|
+
DealStage,
|
|
23
|
+
DealPriority,
|
|
24
|
+
Currency,
|
|
25
|
+
DealLineItem,
|
|
26
|
+
Competitor,
|
|
27
|
+
Deal,
|
|
28
|
+
// Activity types
|
|
29
|
+
ActivityType,
|
|
30
|
+
CallOutcome,
|
|
31
|
+
MeetingOutcome,
|
|
32
|
+
EmailStatus,
|
|
33
|
+
CallMetadata,
|
|
34
|
+
MeetingMetadata,
|
|
35
|
+
EmailMetadata,
|
|
36
|
+
TaskMetadata,
|
|
37
|
+
Activity,
|
|
38
|
+
// Media types
|
|
39
|
+
MediaType,
|
|
40
|
+
MimeType,
|
|
41
|
+
ImageMetadata,
|
|
42
|
+
VideoMetadata,
|
|
43
|
+
AudioMetadata,
|
|
44
|
+
DocumentMetadata,
|
|
45
|
+
Media,
|
|
46
|
+
// Note types
|
|
47
|
+
NoteVisibility,
|
|
48
|
+
Note,
|
|
49
|
+
// Tag types
|
|
50
|
+
TagCategory,
|
|
51
|
+
Tag,
|
|
52
|
+
// Company types
|
|
53
|
+
CompanySize,
|
|
54
|
+
Industry,
|
|
55
|
+
Company,
|
|
56
|
+
// Pipeline types
|
|
57
|
+
PipelineStage,
|
|
58
|
+
Pipeline,
|
|
59
|
+
// Search & Filter types
|
|
60
|
+
SortDirection,
|
|
61
|
+
SortOptions,
|
|
62
|
+
PaginationOptions,
|
|
63
|
+
PaginatedResponse,
|
|
64
|
+
DateRange,
|
|
65
|
+
ContactFilter,
|
|
66
|
+
DealFilter,
|
|
67
|
+
ActivityFilter,
|
|
68
|
+
// Analytics types
|
|
69
|
+
AggregationPeriod,
|
|
70
|
+
MetricDataPoint,
|
|
71
|
+
DashboardMetric,
|
|
72
|
+
// Export types
|
|
73
|
+
ExportFormat,
|
|
74
|
+
ExportStatus,
|
|
75
|
+
ExportJob,
|
|
76
|
+
// Integration types
|
|
77
|
+
IntegrationProvider,
|
|
78
|
+
IntegrationStatus,
|
|
79
|
+
Integration,
|
|
80
|
+
// Telemetry types
|
|
81
|
+
TelemetryEventType,
|
|
82
|
+
TelemetryEvent,
|
|
83
|
+
} from './types.js';
|
|
84
|
+
|
|
85
|
+
// Re-export all schemas
|
|
86
|
+
export {
|
|
87
|
+
// Base schemas
|
|
88
|
+
uuidSchema,
|
|
89
|
+
timestampSchema,
|
|
90
|
+
metadataSchema,
|
|
91
|
+
// Contact schemas
|
|
92
|
+
phoneNumberTypeSchema,
|
|
93
|
+
emailTypeSchema,
|
|
94
|
+
addressTypeSchema,
|
|
95
|
+
socialPlatformSchema,
|
|
96
|
+
customFieldTypeSchema,
|
|
97
|
+
contactSourceSchema,
|
|
98
|
+
contactStatusSchema,
|
|
99
|
+
phoneNumberSchema,
|
|
100
|
+
emailSchema,
|
|
101
|
+
addressSchema,
|
|
102
|
+
socialProfileSchema,
|
|
103
|
+
customFieldSchema,
|
|
104
|
+
contactSchema,
|
|
105
|
+
createContactSchema,
|
|
106
|
+
updateContactSchema,
|
|
107
|
+
// Deal schemas
|
|
108
|
+
dealStageSchema,
|
|
109
|
+
dealPrioritySchema,
|
|
110
|
+
currencySchema,
|
|
111
|
+
discountTypeSchema,
|
|
112
|
+
dealLineItemSchema,
|
|
113
|
+
competitorSchema,
|
|
114
|
+
dealSchema,
|
|
115
|
+
createDealSchema,
|
|
116
|
+
updateDealSchema,
|
|
117
|
+
// Activity schemas
|
|
118
|
+
activityTypeSchema,
|
|
119
|
+
callOutcomeSchema,
|
|
120
|
+
meetingOutcomeSchema,
|
|
121
|
+
emailStatusSchema,
|
|
122
|
+
taskStatusSchema,
|
|
123
|
+
taskPrioritySchema,
|
|
124
|
+
callDirectionSchema,
|
|
125
|
+
callMetadataSchema,
|
|
126
|
+
meetingMetadataSchema,
|
|
127
|
+
emailMetadataSchema,
|
|
128
|
+
checklistItemSchema,
|
|
129
|
+
taskMetadataSchema,
|
|
130
|
+
activityMetadataSchema,
|
|
131
|
+
activitySchema,
|
|
132
|
+
createActivitySchema,
|
|
133
|
+
updateActivitySchema,
|
|
134
|
+
// Media schemas
|
|
135
|
+
mediaTypeSchema,
|
|
136
|
+
mimeTypeSchema,
|
|
137
|
+
mediaEntityTypeSchema,
|
|
138
|
+
imageMetadataSchema,
|
|
139
|
+
videoMetadataSchema,
|
|
140
|
+
audioMetadataSchema,
|
|
141
|
+
documentMetadataSchema,
|
|
142
|
+
mediaSchema,
|
|
143
|
+
createMediaSchema,
|
|
144
|
+
updateMediaSchema,
|
|
145
|
+
// Note schemas
|
|
146
|
+
noteVisibilitySchema,
|
|
147
|
+
noteFormatSchema,
|
|
148
|
+
noteSchema,
|
|
149
|
+
createNoteSchema,
|
|
150
|
+
updateNoteSchema,
|
|
151
|
+
// Tag schemas
|
|
152
|
+
tagCategorySchema,
|
|
153
|
+
tagSchema,
|
|
154
|
+
createTagSchema,
|
|
155
|
+
updateTagSchema,
|
|
156
|
+
// Company schemas
|
|
157
|
+
companySizeSchema,
|
|
158
|
+
industrySchema,
|
|
159
|
+
companySchema,
|
|
160
|
+
createCompanySchema,
|
|
161
|
+
updateCompanySchema,
|
|
162
|
+
// Pipeline schemas
|
|
163
|
+
pipelineStageSchema,
|
|
164
|
+
pipelineSchema,
|
|
165
|
+
// Filter schemas
|
|
166
|
+
sortDirectionSchema,
|
|
167
|
+
paginationSchema,
|
|
168
|
+
dateRangeSchema,
|
|
169
|
+
contactFilterSchema,
|
|
170
|
+
dealFilterSchema,
|
|
171
|
+
activityFilterSchema,
|
|
172
|
+
// Helper schemas
|
|
173
|
+
paginatedResponseSchema,
|
|
174
|
+
// Export & Integration schemas
|
|
175
|
+
exportFormatSchema,
|
|
176
|
+
exportStatusSchema,
|
|
177
|
+
exportJobSchema,
|
|
178
|
+
integrationProviderSchema,
|
|
179
|
+
integrationStatusSchema,
|
|
180
|
+
integrationSchema,
|
|
181
|
+
// Telemetry schemas
|
|
182
|
+
telemetryEventTypeSchema,
|
|
183
|
+
telemetryEventSchema,
|
|
184
|
+
} from './schemas.js';
|