@hasna/connectors 0.0.6 → 0.2.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 (118) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +67 -41
  3. package/bin/index.js +1390 -745
  4. package/bin/mcp.js +184 -19
  5. package/bin/serve.js +1118 -0
  6. package/connectors/connect-anthropic/package.json +4 -4
  7. package/connectors/connect-aws/package.json +4 -4
  8. package/connectors/connect-brandsight/package.json +4 -4
  9. package/connectors/connect-cloudflare/.env.example +0 -5
  10. package/connectors/connect-cloudflare/package.json +4 -4
  11. package/connectors/connect-discord/package.json +4 -4
  12. package/connectors/connect-docker/package.json +4 -4
  13. package/connectors/connect-e2b/package.json +4 -4
  14. package/connectors/connect-elevenlabs/package.json +4 -4
  15. package/connectors/connect-exa/package.json +4 -4
  16. package/connectors/connect-figma/package.json +4 -4
  17. package/connectors/connect-firecrawl/package.json +4 -4
  18. package/connectors/connect-github/package.json +4 -4
  19. package/connectors/connect-gmail/package.json +4 -4
  20. package/connectors/connect-google/package.json +4 -4
  21. package/connectors/connect-googlecalendar/package.json +4 -4
  22. package/connectors/connect-googlecloud/package.json +4 -4
  23. package/connectors/connect-googlecontacts/package.json +4 -4
  24. package/connectors/connect-googledocs/package.json +4 -4
  25. package/connectors/connect-googledrive/package.json +4 -4
  26. package/connectors/connect-googlegemini/package.json +4 -4
  27. package/connectors/connect-googlemaps/package.json +2 -2
  28. package/connectors/connect-googlesheets/package.json +4 -4
  29. package/connectors/connect-googletasks/package.json +2 -2
  30. package/connectors/connect-hedra/package.json +4 -4
  31. package/connectors/connect-heygen/package.json +4 -4
  32. package/connectors/connect-huggingface/package.json +4 -4
  33. package/connectors/connect-icons8/package.json +4 -4
  34. package/connectors/connect-maropost/package.json +4 -4
  35. package/connectors/connect-mercury/package.json +4 -4
  36. package/connectors/connect-meta/package.json +4 -4
  37. package/connectors/connect-midjourney/package.json +4 -4
  38. package/connectors/connect-mistral/package.json +4 -4
  39. package/connectors/connect-mixpanel/package.json +4 -4
  40. package/connectors/connect-notion/.env.example +0 -5
  41. package/connectors/connect-notion/package.json +2 -2
  42. package/connectors/connect-openai/package.json +4 -4
  43. package/connectors/connect-openweathermap/package.json +4 -4
  44. package/connectors/connect-pandadoc/package.json +4 -4
  45. package/connectors/connect-quo/package.json +4 -4
  46. package/connectors/connect-reddit/package.json +4 -4
  47. package/connectors/connect-reducto/package.json +1 -1
  48. package/connectors/connect-resend/package.json +4 -4
  49. package/connectors/connect-revolut/package.json +4 -4
  50. package/connectors/connect-sedo/package.json +4 -4
  51. package/connectors/connect-sentry/package.json +4 -4
  52. package/connectors/connect-shadcn/package.json +4 -4
  53. package/connectors/connect-shopify/package.json +2 -2
  54. package/connectors/connect-snap/package.json +4 -4
  55. package/connectors/connect-stabilityai/package.json +4 -4
  56. package/connectors/connect-stripe/package.json +4 -4
  57. package/connectors/connect-stripeatlas/package.json +4 -4
  58. package/connectors/connect-substack/package.json +4 -4
  59. package/connectors/connect-tiktok/package.json +4 -4
  60. package/connectors/connect-tinker/package.json +4 -4
  61. package/connectors/connect-twilio/package.json +6 -6
  62. package/connectors/connect-uspto/package.json +4 -4
  63. package/connectors/connect-webflow/package.json +2 -2
  64. package/connectors/connect-wix/package.json +2 -2
  65. package/connectors/connect-x/package.json +4 -4
  66. package/connectors/connect-xads/package.json +4 -4
  67. package/connectors/connect-xai/package.json +4 -4
  68. package/connectors/connect-youtube/package.json +4 -4
  69. package/connectors/connect-zoom/package.json +4 -4
  70. package/dashboard/dist/assets/index-BZZ_709y.css +1 -0
  71. package/dashboard/dist/assets/index-CBroKWCD.js +234 -0
  72. package/dashboard/dist/index.html +13 -0
  73. package/dashboard/dist/logo.jpg +0 -0
  74. package/dist/cli/cli.test.d.ts +1 -0
  75. package/dist/cli/components/App.d.ts +6 -0
  76. package/dist/cli/components/CategorySelect.d.ts +6 -0
  77. package/dist/cli/components/ConnectorSelect.d.ts +10 -0
  78. package/dist/cli/components/Header.d.ts +6 -0
  79. package/dist/cli/components/InstallProgress.d.ts +8 -0
  80. package/dist/cli/components/SearchView.d.ts +8 -0
  81. package/dist/cli/components/components.test.d.ts +1 -0
  82. package/dist/cli/index.d.ts +2 -0
  83. package/dist/index.d.ts +11 -0
  84. package/dist/index.js +11 -16
  85. package/dist/lib/installer.d.ts +55 -0
  86. package/dist/lib/installer.test.d.ts +1 -0
  87. package/dist/lib/registry.d.ts +18 -0
  88. package/dist/lib/registry.test.d.ts +1 -0
  89. package/dist/mcp/index.d.ts +2 -0
  90. package/dist/mcp/mcp.test.d.ts +1 -0
  91. package/dist/server/auth.d.ts +70 -0
  92. package/dist/server/dashboard.d.ts +5 -0
  93. package/dist/server/index.d.ts +6 -0
  94. package/dist/server/serve.d.ts +12 -0
  95. package/dist/server/server.test.d.ts +1 -0
  96. package/package.json +11 -6
  97. package/connectors/connect-browseruse/.env.example +0 -7
  98. package/connectors/connect-browseruse/.npmrc.example +0 -2
  99. package/connectors/connect-browseruse/AGENTS.md +0 -172
  100. package/connectors/connect-browseruse/CLAUDE.md +0 -172
  101. package/connectors/connect-browseruse/GEMINI.md +0 -172
  102. package/connectors/connect-browseruse/README.md +0 -153
  103. package/connectors/connect-browseruse/package.json +0 -52
  104. package/connectors/connect-browseruse/src/api/billing.ts +0 -32
  105. package/connectors/connect-browseruse/src/api/browsers.ts +0 -50
  106. package/connectors/connect-browseruse/src/api/client.ts +0 -168
  107. package/connectors/connect-browseruse/src/api/files.ts +0 -70
  108. package/connectors/connect-browseruse/src/api/index.ts +0 -95
  109. package/connectors/connect-browseruse/src/api/profiles.ts +0 -59
  110. package/connectors/connect-browseruse/src/api/sessions.ts +0 -88
  111. package/connectors/connect-browseruse/src/api/skills.ts +0 -194
  112. package/connectors/connect-browseruse/src/api/tasks.ts +0 -127
  113. package/connectors/connect-browseruse/src/cli/index.ts +0 -888
  114. package/connectors/connect-browseruse/src/index.ts +0 -35
  115. package/connectors/connect-browseruse/src/types/index.ts +0 -312
  116. package/connectors/connect-browseruse/src/utils/config.ts +0 -212
  117. package/connectors/connect-browseruse/src/utils/output.ts +0 -119
  118. package/connectors/connect-browseruse/tsconfig.json +0 -16
@@ -1,35 +0,0 @@
1
- // Browser Use Connector
2
- // TypeScript wrapper for the Browser Use Cloud API
3
-
4
- export { BrowserUse } from './api';
5
- export * from './types';
6
-
7
- // Re-export individual API classes for advanced usage
8
- export {
9
- BrowserUseClient,
10
- TasksApi,
11
- SessionsApi,
12
- ProfilesApi,
13
- BrowsersApi,
14
- SkillsApi,
15
- MarketplaceApi,
16
- FilesApi,
17
- BillingApi,
18
- } from './api';
19
-
20
- // Export config utilities
21
- export {
22
- getApiKey,
23
- setApiKey,
24
- getBaseUrl,
25
- setBaseUrl,
26
- getCurrentProfile,
27
- setCurrentProfile,
28
- listProfiles,
29
- createProfile,
30
- deleteProfile,
31
- loadProfile,
32
- saveProfile,
33
- clearConfig,
34
- hasApiKey,
35
- } from './utils/config';
@@ -1,312 +0,0 @@
1
- /**
2
- * Browser Use API Types
3
- */
4
-
5
- // ============================================
6
- // Common Types
7
- // ============================================
8
-
9
- export type OutputFormat = 'json' | 'pretty';
10
-
11
- export interface PaginatedResponse<T> {
12
- data: T[];
13
- hasMore: boolean;
14
- nextCursor?: string;
15
- }
16
-
17
- export class BrowserUseApiError extends Error {
18
- constructor(
19
- message: string,
20
- public statusCode: number,
21
- public details?: unknown
22
- ) {
23
- super(message);
24
- this.name = 'BrowserUseApiError';
25
- }
26
- }
27
-
28
- // ============================================
29
- // Task Types
30
- // ============================================
31
-
32
- export type TaskStatus =
33
- | 'created'
34
- | 'queued'
35
- | 'running'
36
- | 'paused'
37
- | 'stopped'
38
- | 'completed'
39
- | 'failed';
40
-
41
- export interface TaskStep {
42
- id: string;
43
- type: string;
44
- description: string;
45
- status: 'pending' | 'running' | 'completed' | 'failed';
46
- result?: unknown;
47
- error?: string;
48
- createdAt: string;
49
- completedAt?: string;
50
- }
51
-
52
- export interface Task {
53
- id: string;
54
- task: string;
55
- status: TaskStatus;
56
- sessionId?: string;
57
- steps: TaskStep[];
58
- output?: unknown;
59
- error?: string;
60
- liveUrl?: string;
61
- createdAt: string;
62
- updatedAt: string;
63
- completedAt?: string;
64
- }
65
-
66
- /**
67
- * Sensitive data configuration for secure credential handling.
68
- * The LLM only sees placeholder names (e.g., 'x_user', 'x_pass'),
69
- * actual values are injected directly into forms without LLM exposure.
70
- */
71
- export type SensitiveData =
72
- | Record<string, string> // Global: applies to all domains
73
- | Record<string, Record<string, string>>; // Per-domain: 'https://*.example.com': { user: '...', pass: '...' }
74
-
75
- export interface CreateTaskParams {
76
- task: string;
77
- sessionId?: string;
78
- schema?: Record<string, unknown>;
79
- save_browser_data?: boolean;
80
- /**
81
- * Sensitive data like credentials to handle securely.
82
- * Can be global (applies everywhere) or per-domain.
83
- * @example { 'x_user': 'email@example.com', 'x_pass': 'password123' }
84
- * @example { 'https://*.mysite.com': { 'user': 'admin', 'pass': 'secret' } }
85
- */
86
- sensitive_data?: SensitiveData;
87
- /** Disable vision to prevent LLM from seeing sensitive data in screenshots */
88
- use_vision?: boolean;
89
- /** Allowed domains to restrict agent navigation (security) */
90
- allowed_domains?: string[];
91
- }
92
-
93
- export interface UpdateTaskParams {
94
- action: 'stop' | 'pause' | 'resume' | 'stop-and-close-session';
95
- }
96
-
97
- export interface ListTasksParams {
98
- limit?: number;
99
- cursor?: string;
100
- sessionId?: string;
101
- status?: TaskStatus;
102
- }
103
-
104
- // ============================================
105
- // Session Types
106
- // ============================================
107
-
108
- export type SessionStatus = 'active' | 'inactive' | 'closed';
109
-
110
- export interface Session {
111
- id: string;
112
- status: SessionStatus;
113
- profileId?: string;
114
- liveUrl?: string;
115
- connectUrl?: string;
116
- proxyUrl?: string;
117
- keepAlive: boolean;
118
- createdAt: string;
119
- updatedAt: string;
120
- }
121
-
122
- export interface CreateSessionParams {
123
- task?: string;
124
- profileId?: string;
125
- proxyUrl?: string;
126
- keepAlive?: boolean;
127
- save_browser_data?: boolean;
128
- }
129
-
130
- export interface ListSessionsParams {
131
- limit?: number;
132
- cursor?: string;
133
- status?: SessionStatus;
134
- }
135
-
136
- export interface SessionPublicShare {
137
- id: string;
138
- sessionId: string;
139
- publicUrl: string;
140
- expiresAt: string;
141
- }
142
-
143
- // ============================================
144
- // Profile Types
145
- // ============================================
146
-
147
- export interface Profile {
148
- id: string;
149
- name: string;
150
- description?: string;
151
- createdAt: string;
152
- updatedAt: string;
153
- }
154
-
155
- export interface CreateProfileParams {
156
- name: string;
157
- description?: string;
158
- }
159
-
160
- export interface UpdateProfileParams {
161
- name?: string;
162
- description?: string;
163
- }
164
-
165
- export interface ListProfilesParams {
166
- limit?: number;
167
- cursor?: string;
168
- }
169
-
170
- // ============================================
171
- // Browser Session Types
172
- // ============================================
173
-
174
- export interface BrowserSession {
175
- id: string;
176
- status: 'active' | 'stopped';
177
- liveUrl?: string;
178
- connectUrl?: string;
179
- wsUrl?: string;
180
- createdAt: string;
181
- stoppedAt?: string;
182
- }
183
-
184
- export interface CreateBrowserSessionParams {
185
- profileId?: string;
186
- proxyUrl?: string;
187
- }
188
-
189
- export interface ListBrowserSessionsParams {
190
- limit?: number;
191
- cursor?: string;
192
- }
193
-
194
- // ============================================
195
- // Skill Types
196
- // ============================================
197
-
198
- export type SkillStatus = 'draft' | 'generating' | 'ready' | 'failed';
199
-
200
- export interface SkillParameter {
201
- name: string;
202
- type: 'string' | 'number' | 'boolean' | 'object' | 'array';
203
- description?: string;
204
- required?: boolean;
205
- default?: unknown;
206
- }
207
-
208
- export interface SkillSchema {
209
- parameters: SkillParameter[];
210
- output?: Record<string, unknown>;
211
- }
212
-
213
- export interface Skill {
214
- id: string;
215
- name: string;
216
- description?: string;
217
- status: SkillStatus;
218
- schema?: SkillSchema;
219
- isPublic: boolean;
220
- version: number;
221
- createdAt: string;
222
- updatedAt: string;
223
- }
224
-
225
- export interface CreateSkillParams {
226
- name: string;
227
- description?: string;
228
- task: string;
229
- exampleInputs?: Record<string, unknown>[];
230
- }
231
-
232
- export interface UpdateSkillParams {
233
- name?: string;
234
- description?: string;
235
- isPublic?: boolean;
236
- }
237
-
238
- export interface ExecuteSkillParams {
239
- parameters: Record<string, unknown>;
240
- sessionId?: string;
241
- }
242
-
243
- export interface RefineSkillParams {
244
- feedback: string;
245
- }
246
-
247
- export interface SkillExecution {
248
- id: string;
249
- skillId: string;
250
- status: 'queued' | 'running' | 'completed' | 'failed';
251
- input: Record<string, unknown>;
252
- output?: unknown;
253
- error?: string;
254
- createdAt: string;
255
- completedAt?: string;
256
- }
257
-
258
- export interface ListSkillsParams {
259
- limit?: number;
260
- cursor?: string;
261
- status?: SkillStatus;
262
- }
263
-
264
- export interface ListSkillExecutionsParams {
265
- limit?: number;
266
- cursor?: string;
267
- }
268
-
269
- // ============================================
270
- // File Types
271
- // ============================================
272
-
273
- export interface PresignedUrl {
274
- url: string;
275
- expiresAt: string;
276
- }
277
-
278
- export interface UploadFileParams {
279
- fileName: string;
280
- contentType?: string;
281
- }
282
-
283
- // ============================================
284
- // Billing Types
285
- // ============================================
286
-
287
- export interface AccountBilling {
288
- accountId: string;
289
- email: string;
290
- credits: number;
291
- plan: 'free' | 'payg' | 'business' | 'enterprise';
292
- createdAt: string;
293
- }
294
-
295
- // ============================================
296
- // Marketplace Types
297
- // ============================================
298
-
299
- export interface MarketplaceSkill {
300
- id: string;
301
- name: string;
302
- description?: string;
303
- author: string;
304
- schema?: SkillSchema;
305
- downloads: number;
306
- rating?: number;
307
- createdAt: string;
308
- }
309
-
310
- export interface CloneSkillParams {
311
- name?: string;
312
- }
@@ -1,212 +0,0 @@
1
- import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, rmSync } from 'fs';
2
- import { homedir } from 'os';
3
- import { join } from 'path';
4
-
5
- const CONNECTOR_NAME = 'connect-browseruse';
6
- const DEFAULT_PROFILE = 'default';
7
-
8
- export interface ProfileConfig {
9
- apiKey?: string;
10
- baseUrl?: string;
11
- }
12
-
13
- // Store for --profile flag override (set by CLI before commands run)
14
- let profileOverride: string | undefined;
15
-
16
- // Config directory: ~/.connect/{connector-name}/
17
- const CONFIG_DIR = join(homedir(), '.connect', CONNECTOR_NAME);
18
- const PROFILES_DIR = join(CONFIG_DIR, 'profiles');
19
- const CURRENT_PROFILE_FILE = join(CONFIG_DIR, 'current_profile');
20
-
21
- // ============================================
22
- // Profile Management
23
- // ============================================
24
-
25
- export function setProfileOverride(profile: string | undefined): void {
26
- profileOverride = profile;
27
- }
28
-
29
- export function ensureConfigDir(): void {
30
- if (!existsSync(CONFIG_DIR)) {
31
- mkdirSync(CONFIG_DIR, { recursive: true });
32
- }
33
- if (!existsSync(PROFILES_DIR)) {
34
- mkdirSync(PROFILES_DIR, { recursive: true });
35
- }
36
- }
37
-
38
- function getProfilePath(profile: string): string {
39
- return join(PROFILES_DIR, `${profile}.json`);
40
- }
41
-
42
- /**
43
- * Get the current active profile name
44
- */
45
- export function getCurrentProfile(): string {
46
- if (profileOverride) {
47
- return profileOverride;
48
- }
49
-
50
- ensureConfigDir();
51
-
52
- if (existsSync(CURRENT_PROFILE_FILE)) {
53
- try {
54
- const profile = readFileSync(CURRENT_PROFILE_FILE, 'utf-8').trim();
55
- if (profile && profileExists(profile)) {
56
- return profile;
57
- }
58
- } catch {
59
- // Fall through to default
60
- }
61
- }
62
-
63
- return DEFAULT_PROFILE;
64
- }
65
-
66
- /**
67
- * Set the current active profile
68
- */
69
- export function setCurrentProfile(profile: string): void {
70
- ensureConfigDir();
71
-
72
- if (!profileExists(profile) && profile !== DEFAULT_PROFILE) {
73
- throw new Error(`Profile "${profile}" does not exist`);
74
- }
75
-
76
- writeFileSync(CURRENT_PROFILE_FILE, profile);
77
- }
78
-
79
- /**
80
- * Check if a profile exists
81
- */
82
- export function profileExists(profile: string): boolean {
83
- return existsSync(getProfilePath(profile));
84
- }
85
-
86
- /**
87
- * List all available profiles
88
- */
89
- export function listProfiles(): string[] {
90
- ensureConfigDir();
91
-
92
- if (!existsSync(PROFILES_DIR)) {
93
- return [];
94
- }
95
-
96
- return readdirSync(PROFILES_DIR)
97
- .filter(f => f.endsWith('.json'))
98
- .map(f => f.replace('.json', ''))
99
- .sort();
100
- }
101
-
102
- /**
103
- * Create a new profile
104
- */
105
- export function createProfile(profile: string, config: ProfileConfig = {}): boolean {
106
- ensureConfigDir();
107
-
108
- if (profileExists(profile)) {
109
- return false;
110
- }
111
-
112
- // Validate profile name
113
- if (!/^[a-zA-Z0-9_-]+$/.test(profile)) {
114
- throw new Error('Profile name can only contain letters, numbers, hyphens, and underscores');
115
- }
116
-
117
- writeFileSync(getProfilePath(profile), JSON.stringify(config, null, 2));
118
- return true;
119
- }
120
-
121
- /**
122
- * Delete a profile
123
- */
124
- export function deleteProfile(profile: string): boolean {
125
- if (profile === DEFAULT_PROFILE) {
126
- return false;
127
- }
128
-
129
- if (!profileExists(profile)) {
130
- return false;
131
- }
132
-
133
- // Switch to default if deleting current profile
134
- if (getCurrentProfile() === profile) {
135
- setCurrentProfile(DEFAULT_PROFILE);
136
- }
137
-
138
- rmSync(getProfilePath(profile));
139
- return true;
140
- }
141
-
142
- /**
143
- * Load profile config
144
- */
145
- export function loadProfile(profile?: string): ProfileConfig {
146
- ensureConfigDir();
147
- const profileName = profile || getCurrentProfile();
148
- const profilePath = getProfilePath(profileName);
149
-
150
- if (!existsSync(profilePath)) {
151
- return {};
152
- }
153
-
154
- try {
155
- return JSON.parse(readFileSync(profilePath, 'utf-8'));
156
- } catch {
157
- return {};
158
- }
159
- }
160
-
161
- /**
162
- * Save profile config
163
- */
164
- export function saveProfile(config: ProfileConfig, profile?: string): void {
165
- ensureConfigDir();
166
- const profileName = profile || getCurrentProfile();
167
- writeFileSync(getProfilePath(profileName), JSON.stringify(config, null, 2));
168
- }
169
-
170
- // ============================================
171
- // Browser Use Credentials Management
172
- // ============================================
173
-
174
- export function getApiKey(): string | undefined {
175
- return process.env.BROWSER_USE_API_KEY || loadProfile().apiKey;
176
- }
177
-
178
- export function setApiKey(apiKey: string): void {
179
- const config = loadProfile();
180
- config.apiKey = apiKey;
181
- saveProfile(config);
182
- }
183
-
184
- export function getBaseUrl(): string {
185
- return process.env.BROWSER_USE_BASE_URL || loadProfile().baseUrl || 'https://api.browser-use.com/api/v2';
186
- }
187
-
188
- export function setBaseUrl(baseUrl: string): void {
189
- const config = loadProfile();
190
- config.baseUrl = baseUrl;
191
- saveProfile(config);
192
- }
193
-
194
- // ============================================
195
- // Utility Functions
196
- // ============================================
197
-
198
- export function clearConfig(): void {
199
- saveProfile({});
200
- }
201
-
202
- export function getConfigDir(): string {
203
- return CONFIG_DIR;
204
- }
205
-
206
- export function getActiveProfileName(): string {
207
- return getCurrentProfile();
208
- }
209
-
210
- export function hasApiKey(): boolean {
211
- return !!getApiKey();
212
- }
@@ -1,119 +0,0 @@
1
- import chalk from 'chalk';
2
-
3
- export type OutputFormat = 'json' | 'table' | 'pretty';
4
-
5
- export function formatOutput(data: unknown, format: OutputFormat = 'pretty'): string {
6
- switch (format) {
7
- case 'json':
8
- return JSON.stringify(data, null, 2);
9
- case 'table':
10
- return formatAsTable(data);
11
- case 'pretty':
12
- default:
13
- return formatPretty(data);
14
- }
15
- }
16
-
17
- function formatAsTable(data: unknown): string {
18
- if (!Array.isArray(data)) {
19
- data = [data];
20
- }
21
-
22
- const items = data as Record<string, unknown>[];
23
- if (items.length === 0) {
24
- return 'No data';
25
- }
26
-
27
- const firstItem = items[0];
28
- if (!firstItem || typeof firstItem !== 'object') {
29
- return 'No data';
30
- }
31
-
32
- const keys = Object.keys(firstItem);
33
- const colWidths = keys.map(key => {
34
- const maxValue = Math.max(
35
- key.length,
36
- ...items.map(item => String(item[key] ?? '').length)
37
- );
38
- return Math.min(maxValue, 40);
39
- });
40
-
41
- const header = keys.map((key, i) => key.padEnd(colWidths[i] ?? 10)).join(' | ');
42
- const separator = colWidths.map(w => '-'.repeat(w)).join('-+-');
43
-
44
- const rows = items.map(item =>
45
- keys.map((key, i) => {
46
- const value = String(item[key] ?? '');
47
- const width = colWidths[i] ?? 10;
48
- return value.length > width
49
- ? value.substring(0, width - 3) + '...'
50
- : value.padEnd(width);
51
- }).join(' | ')
52
- );
53
-
54
- return [header, separator, ...rows].join('\n');
55
- }
56
-
57
- function formatPretty(data: unknown): string {
58
- if (Array.isArray(data)) {
59
- return data.map((item, i) => `${chalk.cyan(`[${i + 1}]`)} ${formatPrettyItem(item)}`).join('\n\n');
60
- }
61
- return formatPrettyItem(data);
62
- }
63
-
64
- function formatPrettyItem(item: unknown, indent = 0): string {
65
- if (item === null || item === undefined) {
66
- return chalk.gray('null');
67
- }
68
-
69
- if (typeof item !== 'object') {
70
- return String(item);
71
- }
72
-
73
- const spaces = ' '.repeat(indent);
74
- const entries = Object.entries(item as Record<string, unknown>);
75
-
76
- return entries
77
- .map(([key, value]) => {
78
- if (Array.isArray(value)) {
79
- if (value.length === 0) {
80
- return `${spaces}${chalk.blue(key)}: ${chalk.gray('[]')}`;
81
- }
82
- if (typeof value[0] === 'object') {
83
- return `${spaces}${chalk.blue(key)}:\n${value.map(v => formatPrettyItem(v, indent + 1)).join('\n')}`;
84
- }
85
- return `${spaces}${chalk.blue(key)}: ${value.join(', ')}`;
86
- }
87
-
88
- if (typeof value === 'object' && value !== null) {
89
- return `${spaces}${chalk.blue(key)}:\n${formatPrettyItem(value, indent + 1)}`;
90
- }
91
-
92
- return `${spaces}${chalk.blue(key)}: ${chalk.white(String(value))}`;
93
- })
94
- .join('\n');
95
- }
96
-
97
- export function success(message: string): void {
98
- console.log(chalk.green('✓'), message);
99
- }
100
-
101
- export function error(message: string): void {
102
- console.error(chalk.red('✗'), message);
103
- }
104
-
105
- export function warn(message: string): void {
106
- console.warn(chalk.yellow('⚠'), message);
107
- }
108
-
109
- export function info(message: string): void {
110
- console.log(chalk.blue('ℹ'), message);
111
- }
112
-
113
- export function heading(message: string): void {
114
- console.log(chalk.bold.cyan(`\n${message}\n`));
115
- }
116
-
117
- export function print(data: unknown, format: OutputFormat = 'pretty'): void {
118
- console.log(formatOutput(data, format));
119
- }
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ESNext",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "esModuleInterop": true,
7
- "strict": true,
8
- "skipLibCheck": true,
9
- "declaration": true,
10
- "outDir": "./dist",
11
- "rootDir": "./src",
12
- "types": ["bun-types"]
13
- },
14
- "include": ["src/**/*"],
15
- "exclude": ["node_modules", "dist", "bin"]
16
- }