shark-ai 0.0.1

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.
@@ -0,0 +1,538 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/ui/colors.ts
4
+ import pico from "picocolors";
5
+ var colors = {
6
+ // Semantic Colors
7
+ primary: (text2) => pico.cyan(text2),
8
+ secondary: (text2) => pico.blue(text2),
9
+ // Status Colors
10
+ success: (text2) => pico.green(text2),
11
+ error: (text2) => pico.red(text2),
12
+ warning: (text2) => pico.yellow(text2),
13
+ // Neutral Colors
14
+ dim: (text2) => pico.dim(text2),
15
+ inverse: (text2) => pico.inverse(text2),
16
+ white: (text2) => pico.white(text2),
17
+ gray: (text2) => pico.gray(text2),
18
+ // Styling
19
+ bold: (text2) => pico.bold(text2),
20
+ italic: (text2) => pico.italic(text2)
21
+ };
22
+
23
+ // src/commands/login.ts
24
+ import { Command } from "commander";
25
+
26
+ // src/ui/tui.ts
27
+ import * as p from "@clack/prompts";
28
+ var tui = {
29
+ intro(title) {
30
+ p.intro(colors.inverse(` ${title} `));
31
+ },
32
+ log: p.log,
33
+ isCancel: p.isCancel,
34
+ outro(msg) {
35
+ p.outro(colors.primary(msg));
36
+ },
37
+ spinner() {
38
+ const s = p.spinner();
39
+ return {
40
+ start: (msg) => s.start(msg),
41
+ stop: (msg, code = 0) => s.stop(msg, code),
42
+ message: (msg) => s.message(msg)
43
+ };
44
+ },
45
+ async text(opts) {
46
+ const result = await p.text(opts);
47
+ this.handleCancel(result);
48
+ return result;
49
+ },
50
+ async password(opts) {
51
+ const result = await p.password(opts);
52
+ this.handleCancel(result);
53
+ return result;
54
+ },
55
+ async confirm(opts) {
56
+ const result = await p.confirm(opts);
57
+ this.handleCancel(result);
58
+ return result;
59
+ },
60
+ async select(opts) {
61
+ const result = await p.select(opts);
62
+ this.handleCancel(result);
63
+ return result;
64
+ },
65
+ async multiselect(opts) {
66
+ const result = await p.multiselect(opts);
67
+ this.handleCancel(result);
68
+ return result;
69
+ },
70
+ /**
71
+ * Centralized cancel handler.
72
+ * If the user presses Ctrl+C, Clack returns a symbol.
73
+ * We detect it and exit gracefully.
74
+ */
75
+ handleCancel(value) {
76
+ if (p.isCancel(value)) {
77
+ p.cancel("Operation cancelled.");
78
+ process.exit(0);
79
+ }
80
+ },
81
+ // Expose raw clack for advanced use cases if strictly necessary
82
+ raw: p
83
+ };
84
+
85
+ // src/core/auth/stackspot-auth.ts
86
+ async function authenticate(realm, clientId, clientSecret) {
87
+ const url = `https://idm.stackspot.com/${realm}/oidc/oauth/token`;
88
+ const body = new URLSearchParams();
89
+ body.append("grant_type", "client_credentials");
90
+ body.append("client_id", clientId);
91
+ body.append("client_secret", clientSecret);
92
+ try {
93
+ const response = await fetch(url, {
94
+ method: "POST",
95
+ headers: {
96
+ "Content-Type": "application/x-www-form-urlencoded"
97
+ },
98
+ body
99
+ });
100
+ if (!response.ok) {
101
+ const errorText = await response.text();
102
+ throw new Error(`Authentication failed: ${response.status} ${response.statusText} - ${errorText}`);
103
+ }
104
+ const data = await response.json();
105
+ return data;
106
+ } catch (error) {
107
+ if (error instanceof Error) {
108
+ throw new Error(`Failed to authenticate with StackSpot: ${error.message}`);
109
+ }
110
+ throw error;
111
+ }
112
+ }
113
+
114
+ // src/core/auth/token-storage.ts
115
+ import keytar from "keytar";
116
+ var SERVICE_NAME = "shark-cli";
117
+ var CHUNK_SIZE = 2500;
118
+ var tokenStorage = {
119
+ /**
120
+ * Saves the access token for the given realm.
121
+ * Handles large tokens by splitting them into chunks if necessary.
122
+ */
123
+ async saveToken(realm, token) {
124
+ try {
125
+ await this.deleteToken(realm);
126
+ if (token.length <= CHUNK_SIZE) {
127
+ await keytar.setPassword(SERVICE_NAME, realm, token);
128
+ } else {
129
+ const chunks = [];
130
+ for (let i = 0; i < token.length; i += CHUNK_SIZE) {
131
+ chunks.push(token.slice(i, i + CHUNK_SIZE));
132
+ }
133
+ await keytar.setPassword(SERVICE_NAME, `${realm}_meta_chunks`, chunks.length.toString());
134
+ for (let i = 0; i < chunks.length; i++) {
135
+ await keytar.setPassword(SERVICE_NAME, `${realm}_chunk_${i}`, chunks[i]);
136
+ }
137
+ }
138
+ } catch (error) {
139
+ throw new Error(`Failed to save token to OS Keychain. If on Linux, ensure 'libsecret' is installed.
140
+ Original Error: ${error.message}`);
141
+ }
142
+ },
143
+ /**
144
+ * Retrieves the access token for the given realm.
145
+ * Reassembles chunks if they exist.
146
+ */
147
+ async getToken(realm) {
148
+ try {
149
+ const meta = await keytar.getPassword(SERVICE_NAME, `${realm}_meta_chunks`);
150
+ if (meta) {
151
+ const count = parseInt(meta, 10);
152
+ let fullToken = "";
153
+ for (let i = 0; i < count; i++) {
154
+ const chunk = await keytar.getPassword(SERVICE_NAME, `${realm}_chunk_${i}`);
155
+ if (!chunk) return null;
156
+ fullToken += chunk;
157
+ }
158
+ return fullToken;
159
+ } else {
160
+ return await keytar.getPassword(SERVICE_NAME, realm);
161
+ }
162
+ } catch (error) {
163
+ console.warn(`WARNING: Failed to access OS Keychain (${error.message}).`);
164
+ return null;
165
+ }
166
+ },
167
+ /**
168
+ * Deletes the access token for the given realm.
169
+ * Cleans up all chunks.
170
+ */
171
+ async deleteToken(realm) {
172
+ try {
173
+ const meta = await keytar.getPassword(SERVICE_NAME, `${realm}_meta_chunks`);
174
+ let deletedSomething = false;
175
+ if (meta) {
176
+ const count = parseInt(meta, 10);
177
+ for (let i = 0; i < count; i++) {
178
+ await keytar.deletePassword(SERVICE_NAME, `${realm}_chunk_${i}`);
179
+ }
180
+ await keytar.deletePassword(SERVICE_NAME, `${realm}_meta_chunks`);
181
+ deletedSomething = true;
182
+ }
183
+ const standardDelete = await keytar.deletePassword(SERVICE_NAME, realm);
184
+ return deletedSomething || standardDelete;
185
+ } catch (error) {
186
+ console.warn(`WARNING: Failed to delete from OS Keychain (${error.message}).`);
187
+ return false;
188
+ }
189
+ }
190
+ };
191
+
192
+ // src/core/network/connectivity.ts
193
+ import dns from "dns/promises";
194
+ var Connectivity = class _Connectivity {
195
+ static instance;
196
+ // Common reliable host to check connectivity
197
+ CHECK_HOST = "google.com";
198
+ TIMEOUT_MS = 3e3;
199
+ constructor() {
200
+ }
201
+ static getInstance() {
202
+ if (!_Connectivity.instance) {
203
+ _Connectivity.instance = new _Connectivity();
204
+ }
205
+ return _Connectivity.instance;
206
+ }
207
+ /**
208
+ * Checks if the user has internet connection.
209
+ * Uses DNS lookup which is generally faster and lighter than a full fetch.
210
+ */
211
+ async checkConnection() {
212
+ try {
213
+ await Promise.race([
214
+ dns.lookup(this.CHECK_HOST),
215
+ new Promise(
216
+ (_, reject) => setTimeout(() => reject(new Error("timeout")), this.TIMEOUT_MS)
217
+ )
218
+ ]);
219
+ return true;
220
+ } catch (error) {
221
+ return false;
222
+ }
223
+ }
224
+ /**
225
+ * Throws an error if the user is offline.
226
+ * Use this as a guard at the start of online-only commands.
227
+ */
228
+ async requireOnline() {
229
+ const isOnline = await this.checkConnection();
230
+ if (!isOnline) {
231
+ throw new Error(`\u26A0\uFE0F ${colors.bold("Offline Mode Detected")}
232
+ This command requires an active internet connection.
233
+ Please check your network and try again.`);
234
+ }
235
+ }
236
+ };
237
+ var connectivity = Connectivity.getInstance();
238
+
239
+ // src/core/config-manager.ts
240
+ import os2 from "os";
241
+ import path2 from "path";
242
+ import fs2 from "fs";
243
+
244
+ // src/core/config/schema.ts
245
+ import { z } from "zod";
246
+ var ConfigSchema = z.object({
247
+ logLevel: z.enum(["debug", "info", "warn", "error"]).default("info"),
248
+ preferredStack: z.array(z.string()).default([]),
249
+ apiBaseUrl: z.string().optional(),
250
+ language: z.enum(["pt-br", "en-us"]).default("pt-br"),
251
+ project: z.string().optional(),
252
+ environment: z.string().optional(),
253
+ activeRealm: z.string().optional()
254
+ // Currently logged-in realm
255
+ });
256
+
257
+ // src/core/config/sharkrc-loader.ts
258
+ import fs from "fs";
259
+ import path from "path";
260
+ import os from "os";
261
+ import { z as z2 } from "zod";
262
+ var SharkRCFileSchema = z2.object({
263
+ project: z2.string().optional(),
264
+ environment: z2.string().optional(),
265
+ logLevel: z2.string().optional(),
266
+ language: z2.string().optional(),
267
+ preferredStack: z2.array(z2.string()).optional()
268
+ // Add other keys as needed from the main config
269
+ }).passthrough();
270
+ function loadFile(filePath) {
271
+ try {
272
+ if (!fs.existsSync(filePath)) {
273
+ return {};
274
+ }
275
+ const content = fs.readFileSync(filePath, "utf-8");
276
+ const json = JSON.parse(content);
277
+ const result = SharkRCFileSchema.safeParse(json);
278
+ if (result.success) {
279
+ return result.data;
280
+ } else {
281
+ console.warn(colors.warning(`\u26A0\uFE0F Invalid config in ${filePath}: ${result.error.message}`));
282
+ return {};
283
+ }
284
+ } catch (error) {
285
+ console.warn(colors.warning(`\u26A0\uFE0F Failed to read ${filePath}: ${error.message}`));
286
+ return {};
287
+ }
288
+ }
289
+ function loadSharkRC() {
290
+ const homeDir = os.homedir();
291
+ const currentDir = process.cwd();
292
+ const globalPath = path.join(homeDir, ".sharkrc");
293
+ const localPath = path.join(currentDir, ".sharkrc");
294
+ const globalConfig = loadFile(globalPath);
295
+ const localConfig = loadFile(localPath);
296
+ return {
297
+ ...globalConfig,
298
+ ...localConfig
299
+ };
300
+ }
301
+ function saveGlobalRC(configUpdates) {
302
+ const homeDir = os.homedir();
303
+ const globalPath = path.join(homeDir, ".sharkrc");
304
+ const currentConfig = loadFile(globalPath);
305
+ const newConfig = { ...currentConfig, ...configUpdates };
306
+ try {
307
+ fs.writeFileSync(globalPath, JSON.stringify(newConfig, null, 2), "utf-8");
308
+ } catch (error) {
309
+ throw new Error(`Failed to save global config to ${globalPath}: ${error.message}`);
310
+ }
311
+ }
312
+
313
+ // src/core/config-manager.ts
314
+ var ConfigManager = class _ConfigManager {
315
+ static instance;
316
+ config = null;
317
+ constructor() {
318
+ }
319
+ static getInstance() {
320
+ if (!_ConfigManager.instance) {
321
+ _ConfigManager.instance = new _ConfigManager();
322
+ }
323
+ return _ConfigManager.instance;
324
+ }
325
+ getConfig() {
326
+ if (!this.config) {
327
+ this.config = this.loadConfig();
328
+ }
329
+ return this.config;
330
+ }
331
+ reloadConfig() {
332
+ this.config = this.loadConfig();
333
+ }
334
+ loadConfig() {
335
+ let mergedConfig = {};
336
+ const rcConfig = loadSharkRC();
337
+ mergedConfig = { ...mergedConfig, ...rcConfig };
338
+ const envConfig = this.loadEnvConfig();
339
+ mergedConfig = { ...mergedConfig, ...envConfig };
340
+ const parsed = ConfigSchema.safeParse(mergedConfig);
341
+ if (!parsed.success) {
342
+ console.warn("\u26A0\uFE0F Invalid configuration detected, falling back to defaults or partial config");
343
+ console.warn(parsed.error.message);
344
+ return ConfigSchema.parse({});
345
+ }
346
+ return parsed.data;
347
+ }
348
+ readJsonFile(filePath) {
349
+ try {
350
+ if (fs2.existsSync(filePath)) {
351
+ const content = fs2.readFileSync(filePath, "utf-8");
352
+ return JSON.parse(content);
353
+ }
354
+ } catch (error) {
355
+ console.warn(`Failed to read config file at ${filePath}`, error);
356
+ }
357
+ return {};
358
+ }
359
+ async set(key, value) {
360
+ if (!this.config) {
361
+ this.config = this.loadConfig();
362
+ }
363
+ this.config[key] = value;
364
+ const homeDir = os2.homedir();
365
+ const configPath = path2.join(homeDir, ".sharkrc");
366
+ try {
367
+ let currentFileConfig = {};
368
+ if (fs2.existsSync(configPath)) {
369
+ currentFileConfig = JSON.parse(fs2.readFileSync(configPath, "utf8"));
370
+ }
371
+ const newConfig = { ...currentFileConfig, [key]: value };
372
+ fs2.writeFileSync(configPath, JSON.stringify(newConfig, null, 2));
373
+ } catch (error) {
374
+ console.error("Failed to save configuration:", error);
375
+ }
376
+ }
377
+ loadEnvConfig() {
378
+ const config = {};
379
+ if (process.env.SHARK_LOG_LEVEL) {
380
+ config.logLevel = process.env.SHARK_LOG_LEVEL;
381
+ }
382
+ if (process.env.SHARK_API_BASE_URL) {
383
+ config.apiBaseUrl = process.env.SHARK_API_BASE_URL;
384
+ }
385
+ if (process.env.SHARK_LANGUAGE) {
386
+ config.language = process.env.SHARK_LANGUAGE;
387
+ }
388
+ if (process.env.SHARK_PREFERRED_STACK) {
389
+ config.preferredStack = process.env.SHARK_PREFERRED_STACK.split(",").map((s) => s.trim());
390
+ }
391
+ return config;
392
+ }
393
+ };
394
+
395
+ // src/commands/login.ts
396
+ var loginCommand = new Command("login").description("Authenticate with StackSpot").action(async () => {
397
+ try {
398
+ await connectivity.requireOnline();
399
+ tui.intro("Shark CLI Login");
400
+ const realm = await tui.text({
401
+ message: "Account Realm (Slug)",
402
+ placeholder: "e.g. stackspot-freemium",
403
+ validate: (value) => {
404
+ if (!value) return "Realm is required";
405
+ if (value.includes(" ")) return "Realm cannot contain spaces";
406
+ }
407
+ });
408
+ if (tui.isCancel(realm)) {
409
+ tui.outro("Login cancelled");
410
+ return;
411
+ }
412
+ const clientId = await tui.text({
413
+ message: "Client ID",
414
+ validate: (value) => {
415
+ if (!value) return "Client ID is required";
416
+ }
417
+ });
418
+ if (tui.isCancel(clientId)) {
419
+ tui.outro("Login cancelled");
420
+ return;
421
+ }
422
+ const clientKey = await tui.password({
423
+ message: "Client Key",
424
+ validate: (value) => {
425
+ if (!value) return "Client Key is required";
426
+ }
427
+ });
428
+ if (tui.isCancel(clientKey)) {
429
+ tui.outro("Login cancelled");
430
+ return;
431
+ }
432
+ const spinner2 = tui.spinner();
433
+ spinner2.start("Authenticating...");
434
+ try {
435
+ const tokens = await authenticate(
436
+ realm.trim(),
437
+ clientId.trim(),
438
+ clientKey.trim()
439
+ );
440
+ await tokenStorage.saveToken(realm, tokens.access_token);
441
+ const configManager = ConfigManager.getInstance();
442
+ await configManager.set("activeRealm", realm);
443
+ spinner2.stop("\u2705 Login successful");
444
+ tui.outro(`You are now authenticated as ${colors.primary(realm)}`);
445
+ } catch (error) {
446
+ spinner2.stop("Authentication failed.", 1);
447
+ tui.log.error(error.message);
448
+ process.exit(1);
449
+ }
450
+ } catch (error) {
451
+ tui.log.error(error.message);
452
+ process.exit(1);
453
+ }
454
+ });
455
+
456
+ // src/commands/config.ts
457
+ var configCommand = {
458
+ action: async () => {
459
+ tui.intro("Shark configuration");
460
+ const manager = ConfigManager.getInstance();
461
+ const currentConfig = manager.getConfig();
462
+ tui.log.info(colors.dim("Current Configuration:"));
463
+ tui.log.message(`\u2022 Project: ${colors.primary(currentConfig.project || "Not Set")}`);
464
+ tui.log.message(`\u2022 Language: ${colors.primary(currentConfig.language)}`);
465
+ tui.log.message(`\u2022 Log Level: ${colors.primary(currentConfig.logLevel)}`);
466
+ const action = await tui.select({
467
+ message: "What would you like to configure?",
468
+ options: [
469
+ { value: "project", label: "Set Default Project" },
470
+ { value: "language", label: "Set Language" },
471
+ { value: "logLevel", label: "Set Log Level" },
472
+ { value: "exit", label: "Exit" }
473
+ ]
474
+ });
475
+ if (tui.isCancel(action) || action === "exit") {
476
+ tui.outro("Configuration unchanged.");
477
+ return;
478
+ }
479
+ try {
480
+ if (action === "project") {
481
+ const project = await tui.text({
482
+ message: "Enter default project slug:",
483
+ initialValue: currentConfig.project,
484
+ placeholder: "e.g., my-awesome-project"
485
+ });
486
+ if (!tui.isCancel(project)) {
487
+ saveGlobalRC({ project });
488
+ tui.log.success(`Updated project to: ${project}`);
489
+ }
490
+ }
491
+ if (action === "language") {
492
+ const lang = await tui.select({
493
+ message: "Select language:",
494
+ options: [
495
+ { value: "pt-br", label: "Portuguese (Brazil)" },
496
+ { value: "en-us", label: "English (US)" }
497
+ ],
498
+ initialValue: currentConfig.language
499
+ });
500
+ if (!tui.isCancel(lang)) {
501
+ saveGlobalRC({ language: lang });
502
+ tui.log.success(`Updated language to: ${lang}`);
503
+ }
504
+ }
505
+ if (action === "logLevel") {
506
+ const level = await tui.select({
507
+ message: "Select log level:",
508
+ options: [
509
+ { value: "debug", label: "Debug (Verbose)" },
510
+ { value: "info", label: "Info (Standard)" },
511
+ { value: "warn", label: "Warn (Important only)" },
512
+ { value: "error", label: "Error (Critical only)" }
513
+ ],
514
+ initialValue: currentConfig.logLevel
515
+ });
516
+ if (!tui.isCancel(level)) {
517
+ saveGlobalRC({ logLevel: level });
518
+ tui.log.success(`Updated log level to: ${level}`);
519
+ }
520
+ }
521
+ manager.reloadConfig();
522
+ tui.outro("Configuration saved successfully to ~/.sharkrc");
523
+ } catch (error) {
524
+ tui.log.error(`Failed to save configuration: ${error.message}`);
525
+ process.exit(1);
526
+ }
527
+ }
528
+ };
529
+
530
+ export {
531
+ colors,
532
+ tui,
533
+ tokenStorage,
534
+ ConfigManager,
535
+ loginCommand,
536
+ configCommand
537
+ };
538
+ //# sourceMappingURL=chunk-B7PNFPUX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/colors.ts","../src/commands/login.ts","../src/ui/tui.ts","../src/core/auth/stackspot-auth.ts","../src/core/auth/token-storage.ts","../src/core/network/connectivity.ts","../src/core/config-manager.ts","../src/core/config/schema.ts","../src/core/config/sharkrc-loader.ts","../src/commands/config.ts"],"sourcesContent":["import pico from 'picocolors';\r\n\r\n// Deep Ocean Theme Palette\r\n// Primary (Action): Cyan\r\n// Secondary (Context): Blue\r\n// Text: White/Gray\r\n\r\nexport const colors = {\r\n // Semantic Colors\r\n primary: (text: string | number) => pico.cyan(text),\r\n secondary: (text: string | number) => pico.blue(text),\r\n\r\n // Status Colors\r\n success: (text: string | number) => pico.green(text),\r\n error: (text: string | number) => pico.red(text),\r\n warning: (text: string | number) => pico.yellow(text),\r\n\r\n // Neutral Colors\r\n dim: (text: string | number) => pico.dim(text),\r\n inverse: (text: string | number) => pico.inverse(text),\r\n white: (text: string | number) => pico.white(text),\r\n gray: (text: string | number) => pico.gray(text),\r\n\r\n // Styling\r\n bold: (text: string | number) => pico.bold(text),\r\n italic: (text: string | number) => pico.italic(text),\r\n};\r\n","import { Command } from 'commander';\r\nimport { tui } from '../ui/tui.js';\r\nimport { authenticate } from '../core/auth/stackspot-auth.js';\r\nimport { tokenStorage } from '../core/auth/token-storage.js';\r\nimport { connectivity } from '../core/network/connectivity.js';\r\nimport { ConfigManager } from '../core/config-manager.js';\r\nimport { colors } from '../ui/colors.js';\r\n\r\nexport const loginCommand = new Command('login')\r\n .description('Authenticate with StackSpot')\r\n .action(async () => {\r\n try {\r\n await connectivity.requireOnline();\r\n\r\n tui.intro('Shark CLI Login');\r\n\r\n const realm = await tui.text({\r\n message: 'Account Realm (Slug)',\r\n placeholder: 'e.g. stackspot-freemium',\r\n validate: (value) => {\r\n if (!value) return 'Realm is required';\r\n if (value.includes(' ')) return 'Realm cannot contain spaces';\r\n },\r\n });\r\n\r\n if (tui.isCancel(realm)) {\r\n tui.outro('Login cancelled');\r\n return;\r\n }\r\n\r\n const clientId = await tui.text({\r\n message: 'Client ID',\r\n validate: (value) => {\r\n if (!value) return 'Client ID is required';\r\n },\r\n });\r\n\r\n if (tui.isCancel(clientId)) {\r\n tui.outro('Login cancelled');\r\n return;\r\n }\r\n\r\n const clientKey = await tui.password({\r\n message: 'Client Key',\r\n validate: (value) => {\r\n if (!value) return 'Client Key is required';\r\n },\r\n });\r\n\r\n if (tui.isCancel(clientKey)) {\r\n tui.outro('Login cancelled');\r\n return;\r\n }\r\n\r\n const spinner = tui.spinner();\r\n spinner.start('Authenticating...');\r\n\r\n try {\r\n const tokens = await authenticate(\r\n (realm as string).trim(),\r\n (clientId as string).trim(),\r\n (clientKey as string).trim()\r\n );\r\n\r\n // Save token\r\n await tokenStorage.saveToken(realm as string, tokens.access_token);\r\n\r\n // Save active realm to config\r\n const configManager = ConfigManager.getInstance();\r\n await configManager.set('activeRealm', realm as string);\r\n\r\n spinner.stop('✅ Login successful');\r\n tui.outro(`You are now authenticated as ${colors.primary(realm as string)}`);\r\n\r\n } catch (error: any) {\r\n spinner.stop('Authentication failed.', 1);\r\n tui.log.error(error.message);\r\n process.exit(1);\r\n }\r\n } catch (error: any) {\r\n tui.log.error(error.message);\r\n process.exit(1);\r\n }\r\n });\r\n","import * as p from '@clack/prompts';\r\nimport { colors } from './colors.js';\r\n\r\nexport interface TuiSpinner {\r\n start(msg?: string): void;\r\n stop(msg?: string, code?: number): void;\r\n message(msg: string): void;\r\n}\r\n\r\nexport const tui = {\r\n intro(title: string) {\r\n p.intro(colors.inverse(` ${title} `));\r\n },\r\n\r\n log: p.log,\r\n isCancel: p.isCancel,\r\n\r\n outro(msg: string) {\r\n p.outro(colors.primary(msg));\r\n },\r\n\r\n spinner(): TuiSpinner {\r\n const s = p.spinner();\r\n return {\r\n start: (msg) => s.start(msg),\r\n stop: (msg, code = 0) => s.stop(msg, code),\r\n message: (msg) => s.message(msg),\r\n };\r\n },\r\n\r\n async text(opts: p.TextOptions): Promise<string> {\r\n const result = await p.text(opts);\r\n this.handleCancel(result);\r\n return result as string;\r\n },\r\n\r\n async password(opts: p.PasswordOptions): Promise<string> {\r\n const result = await p.password(opts);\r\n this.handleCancel(result);\r\n return result as string;\r\n },\r\n\r\n async confirm(opts: p.ConfirmOptions): Promise<boolean> {\r\n const result = await p.confirm(opts);\r\n this.handleCancel(result);\r\n return result as boolean;\r\n },\r\n\r\n async select<Value>(opts: p.SelectOptions<any, Value>): Promise<Value> {\r\n const result = await p.select(opts);\r\n this.handleCancel(result);\r\n return result as Value;\r\n },\r\n\r\n async multiselect<Value>(opts: p.MultiSelectOptions<any, Value>): Promise<Value[]> {\r\n const result = await p.multiselect(opts);\r\n this.handleCancel(result);\r\n return result as Value[];\r\n },\r\n\r\n /**\r\n * Centralized cancel handler.\r\n * If the user presses Ctrl+C, Clack returns a symbol.\r\n * We detect it and exit gracefully.\r\n */\r\n handleCancel(value: unknown) {\r\n if (p.isCancel(value)) {\r\n p.cancel('Operation cancelled.');\r\n process.exit(0);\r\n }\r\n },\r\n\r\n // Expose raw clack for advanced use cases if strictly necessary\r\n raw: p\r\n};\r\n","import { AuthToken } from './types.js';\r\n\r\n/**\r\n * Authenticates with StackSpot IDM using Client Credentials flow.\r\n * \r\n * @param realm The account realm (slug).\r\n * @param clientId The Client ID.\r\n * @param clientSecret The Client Secret.\r\n * @returns Promise resolving to the AuthToken.\r\n * @throws Error if authentication fails.\r\n */\r\nexport async function authenticate(realm: string, clientId: string, clientSecret: string): Promise<AuthToken> {\r\n const url = `https://idm.stackspot.com/${realm}/oidc/oauth/token`;\r\n\r\n const body = new URLSearchParams();\r\n body.append('grant_type', 'client_credentials');\r\n body.append('client_id', clientId);\r\n body.append('client_secret', clientSecret);\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/x-www-form-urlencoded',\r\n },\r\n body: body,\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n throw new Error(`Authentication failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n const data = (await response.json()) as AuthToken;\r\n return data;\r\n } catch (error: any) {\r\n // Wrap network errors or other failures\r\n if (error instanceof Error) {\r\n throw new Error(`Failed to authenticate with StackSpot: ${error.message}`);\r\n }\r\n throw error;\r\n }\r\n}\r\n","import keytar from 'keytar';\r\n\r\nconst SERVICE_NAME = 'shark-cli';\r\nconst CHUNK_SIZE = 2500; // Leave buffer to fit within common 2560 limits\r\n\r\n/**\r\n * Manages secure storage of authentication tokens using the OS Keychain.\r\n */\r\nexport const tokenStorage = {\r\n /**\r\n * Saves the access token for the given realm.\r\n * Handles large tokens by splitting them into chunks if necessary.\r\n */\r\n async saveToken(realm: string, token: string): Promise<void> {\r\n try {\r\n // Cleanup previous potential chunks first\r\n await this.deleteToken(realm);\r\n\r\n if (token.length <= CHUNK_SIZE) {\r\n await keytar.setPassword(SERVICE_NAME, realm, token);\r\n } else {\r\n const chunks = [];\r\n for (let i = 0; i < token.length; i += CHUNK_SIZE) {\r\n chunks.push(token.slice(i, i + CHUNK_SIZE));\r\n }\r\n\r\n // Save metadata indicating how many chunks\r\n await keytar.setPassword(SERVICE_NAME, `${realm}_meta_chunks`, chunks.length.toString());\r\n\r\n // Save each chunk\r\n for (let i = 0; i < chunks.length; i++) {\r\n await keytar.setPassword(SERVICE_NAME, `${realm}_chunk_${i}`, chunks[i]);\r\n }\r\n }\r\n } catch (error: any) {\r\n throw new Error(`Failed to save token to OS Keychain. If on Linux, ensure 'libsecret' is installed.\\nOriginal Error: ${error.message}`);\r\n }\r\n },\r\n\r\n /**\r\n * Retrieves the access token for the given realm.\r\n * Reassembles chunks if they exist.\r\n */\r\n async getToken(realm: string): Promise<string | null> {\r\n try {\r\n // Check for chunk metadata\r\n const meta = await keytar.getPassword(SERVICE_NAME, `${realm}_meta_chunks`);\r\n\r\n if (meta) {\r\n const count = parseInt(meta, 10);\r\n let fullToken = '';\r\n for (let i = 0; i < count; i++) {\r\n const chunk = await keytar.getPassword(SERVICE_NAME, `${realm}_chunk_${i}`);\r\n if (!chunk) return null; // Corrupted state\r\n fullToken += chunk;\r\n }\r\n return fullToken;\r\n } else {\r\n // Fallback to standard single entry\r\n return await keytar.getPassword(SERVICE_NAME, realm);\r\n }\r\n } catch (error: any) {\r\n console.warn(`WARNING: Failed to access OS Keychain (${error.message}).`);\r\n return null;\r\n }\r\n },\r\n\r\n /**\r\n * Deletes the access token for the given realm.\r\n * Cleans up all chunks.\r\n */\r\n async deleteToken(realm: string): Promise<boolean> {\r\n try {\r\n // Check for chunk metadata\r\n const meta = await keytar.getPassword(SERVICE_NAME, `${realm}_meta_chunks`);\r\n let deletedSomething = false;\r\n\r\n if (meta) {\r\n const count = parseInt(meta, 10);\r\n for (let i = 0; i < count; i++) {\r\n await keytar.deletePassword(SERVICE_NAME, `${realm}_chunk_${i}`);\r\n }\r\n await keytar.deletePassword(SERVICE_NAME, `${realm}_meta_chunks`);\r\n deletedSomething = true;\r\n }\r\n\r\n // Always try to delete the standard key too, just in case\r\n const standardDelete = await keytar.deletePassword(SERVICE_NAME, realm);\r\n\r\n return deletedSomething || standardDelete;\r\n } catch (error: any) {\r\n console.warn(`WARNING: Failed to delete from OS Keychain (${error.message}).`);\r\n return false;\r\n }\r\n }\r\n};\r\n","import dns from 'dns/promises';\r\nimport { colors } from '../../ui/colors.js';\r\n\r\nexport class Connectivity {\r\n private static instance: Connectivity;\r\n // Common reliable host to check connectivity\r\n private readonly CHECK_HOST = 'google.com';\r\n private readonly TIMEOUT_MS = 3000;\r\n\r\n private constructor() { }\r\n\r\n public static getInstance(): Connectivity {\r\n if (!Connectivity.instance) {\r\n Connectivity.instance = new Connectivity();\r\n }\r\n return Connectivity.instance;\r\n }\r\n\r\n /**\r\n * Checks if the user has internet connection.\r\n * Uses DNS lookup which is generally faster and lighter than a full fetch.\r\n */\r\n public async checkConnection(): Promise<boolean> {\r\n try {\r\n // Promise.race to enforce timeout\r\n await Promise.race([\r\n dns.lookup(this.CHECK_HOST),\r\n new Promise((_, reject) =>\r\n setTimeout(() => reject(new Error('timeout')), this.TIMEOUT_MS)\r\n )\r\n ]);\r\n return true;\r\n } catch (error) {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Throws an error if the user is offline.\r\n * Use this as a guard at the start of online-only commands.\r\n */\r\n public async requireOnline(): Promise<void> {\r\n const isOnline = await this.checkConnection();\r\n if (!isOnline) {\r\n throw new Error(`⚠️ ${colors.bold('Offline Mode Detected')}\\n This command requires an active internet connection.\\n Please check your network and try again.`);\r\n }\r\n }\r\n}\r\n\r\nexport const connectivity = Connectivity.getInstance();\r\n","import os from 'os';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport { ConfigSchema, type Config } from './config/schema.js';\r\nimport { loadSharkRC } from './config/sharkrc-loader.js';\r\n\r\nexport class ConfigManager {\r\n private static instance: ConfigManager;\r\n private config: Config | null = null;\r\n\r\n private constructor() { }\r\n\r\n public static getInstance(): ConfigManager {\r\n if (!ConfigManager.instance) {\r\n ConfigManager.instance = new ConfigManager();\r\n }\r\n return ConfigManager.instance;\r\n }\r\n\r\n public getConfig(): Config {\r\n if (!this.config) {\r\n this.config = this.loadConfig();\r\n }\r\n return this.config;\r\n }\r\n\r\n public reloadConfig(): void {\r\n this.config = this.loadConfig();\r\n }\r\n\r\n private loadConfig(): Config {\r\n // 1. Defaults (via Zod)\r\n let mergedConfig: any = {};\r\n\r\n // 2 & 3. Global & Local Config (.sharkrc)\r\n // Handled by SharkRCLoader which encapsulates precedence (Local > Global)\r\n const rcConfig = loadSharkRC();\r\n mergedConfig = { ...mergedConfig, ...rcConfig };\r\n\r\n // 4. Env Vars (SHARK_*)\r\n const envConfig = this.loadEnvConfig();\r\n mergedConfig = { ...mergedConfig, ...envConfig };\r\n\r\n // 5. Validation & Defaults\r\n const parsed = ConfigSchema.safeParse(mergedConfig);\r\n if (!parsed.success) {\r\n console.warn('⚠️ Invalid configuration detected, falling back to defaults or partial config');\r\n console.warn(parsed.error.message);\r\n // In a stricter mode we might throw, but CLI should try to run\r\n // For now, let's return a default parse to ensure we have a valid object\r\n return ConfigSchema.parse({});\r\n }\r\n\r\n return parsed.data;\r\n }\r\n\r\n private readJsonFile(filePath: string): any {\r\n try {\r\n if (fs.existsSync(filePath)) {\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n return JSON.parse(content);\r\n }\r\n } catch (error) {\r\n console.warn(`Failed to read config file at ${filePath}`, error);\r\n }\r\n return {};\r\n }\r\n\r\n\r\n public async set(key: string, value: any): Promise<void> {\r\n if (!this.config) {\r\n this.config = this.loadConfig();\r\n }\r\n (this.config as any)[key] = value;\r\n\r\n // Persist to .sharkrc in home directory\r\n const homeDir = os.homedir();\r\n const configPath = path.join(homeDir, '.sharkrc');\r\n\r\n try {\r\n let currentFileConfig = {};\r\n if (fs.existsSync(configPath)) {\r\n currentFileConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));\r\n }\r\n const newConfig = { ...currentFileConfig, [key]: value };\r\n fs.writeFileSync(configPath, JSON.stringify(newConfig, null, 2));\r\n } catch (error) {\r\n console.error('Failed to save configuration:', error);\r\n }\r\n }\r\n\r\n private loadEnvConfig(): any {\r\n const config: any = {};\r\n\r\n if (process.env.SHARK_LOG_LEVEL) {\r\n config.logLevel = process.env.SHARK_LOG_LEVEL;\r\n }\r\n if (process.env.SHARK_API_BASE_URL) {\r\n config.apiBaseUrl = process.env.SHARK_API_BASE_URL;\r\n }\r\n if (process.env.SHARK_LANGUAGE) {\r\n config.language = process.env.SHARK_LANGUAGE;\r\n }\r\n\r\n // Stack is list, requires splitting\r\n if (process.env.SHARK_PREFERRED_STACK) {\r\n config.preferredStack = process.env.SHARK_PREFERRED_STACK.split(',').map(s => s.trim());\r\n }\r\n\r\n return config;\r\n }\r\n}\r\n","import { z } from 'zod';\r\n\r\nexport const ConfigSchema = z.object({\r\n logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),\r\n preferredStack: z.array(z.string()).default([]),\r\n apiBaseUrl: z.string().optional(),\r\n language: z.enum(['pt-br', 'en-us']).default('pt-br'),\r\n project: z.string().optional(),\r\n environment: z.string().optional(),\r\n activeRealm: z.string().optional(), // Currently logged-in realm\r\n});\r\n\r\nexport type Config = z.infer<typeof ConfigSchema>;\r\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { z } from 'zod';\r\nimport { colors } from '../../ui/colors.js';\r\n\r\n// Reusing schema definition implicitly or we could export it from config-manager\r\n// For now, let's define a partial schema for RC files\r\nexport const SharkRCFileSchema = z.object({\r\n project: z.string().optional(),\r\n environment: z.string().optional(),\r\n logLevel: z.string().optional(),\r\n language: z.string().optional(),\r\n preferredStack: z.array(z.string()).optional(),\r\n // Add other keys as needed from the main config\r\n}).passthrough(); // Allow extra keys for forward compatibility\r\n\r\nexport type SharkRC = z.infer<typeof SharkRCFileSchema>;\r\n\r\nfunction loadFile(filePath: string): SharkRC {\r\n try {\r\n if (!fs.existsSync(filePath)) {\r\n return {};\r\n }\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n const json = JSON.parse(content);\r\n const result = SharkRCFileSchema.safeParse(json);\r\n\r\n if (result.success) {\r\n return result.data;\r\n } else {\r\n console.warn(colors.warning(`⚠️ Invalid config in ${filePath}: ${result.error.message}`));\r\n return {};\r\n }\r\n } catch (error: any) {\r\n console.warn(colors.warning(`⚠️ Failed to read ${filePath}: ${error.message}`));\r\n return {};\r\n }\r\n}\r\n\r\nexport function loadSharkRC(): SharkRC {\r\n const homeDir = os.homedir();\r\n const currentDir = process.cwd();\r\n\r\n const globalPath = path.join(homeDir, '.sharkrc');\r\n const localPath = path.join(currentDir, '.sharkrc');\r\n\r\n const globalConfig = loadFile(globalPath);\r\n const localConfig = loadFile(localPath);\r\n\r\n // Local overrides Global\r\n return {\r\n ...globalConfig,\r\n ...localConfig\r\n };\r\n}\r\n\r\nexport function saveGlobalRC(configUpdates: Partial<SharkRC>): void {\r\n const homeDir = os.homedir();\r\n const globalPath = path.join(homeDir, '.sharkrc');\r\n\r\n const currentConfig = loadFile(globalPath);\r\n const newConfig = { ...currentConfig, ...configUpdates };\r\n\r\n try {\r\n fs.writeFileSync(globalPath, JSON.stringify(newConfig, null, 2), 'utf-8');\r\n } catch (error: any) {\r\n throw new Error(`Failed to save global config to ${globalPath}: ${error.message}`);\r\n }\r\n}\r\n","import { tui } from '../ui/tui.js';\r\nimport { colors } from '../ui/colors.js';\r\nimport { ConfigManager } from '../core/config-manager.js';\r\nimport { saveGlobalRC } from '../core/config/sharkrc-loader.js';\r\n\r\nexport const configCommand = {\r\n action: async () => {\r\n tui.intro('Shark configuration');\r\n\r\n const manager = ConfigManager.getInstance();\r\n const currentConfig = manager.getConfig();\r\n\r\n // Show current status\r\n tui.log.info(colors.dim('Current Configuration:'));\r\n tui.log.message(`• Project: ${colors.primary(currentConfig.project || 'Not Set')}`);\r\n tui.log.message(`• Language: ${colors.primary(currentConfig.language)}`);\r\n tui.log.message(`• Log Level: ${colors.primary(currentConfig.logLevel)}`);\r\n\r\n const action = await tui.select({\r\n message: 'What would you like to configure?',\r\n options: [\r\n { value: 'project', label: 'Set Default Project' },\r\n { value: 'language', label: 'Set Language' },\r\n { value: 'logLevel', label: 'Set Log Level' },\r\n { value: 'exit', label: 'Exit' }\r\n ]\r\n });\r\n\r\n if (tui.isCancel(action) || action === 'exit') {\r\n tui.outro('Configuration unchanged.');\r\n return;\r\n }\r\n\r\n try {\r\n if (action === 'project') {\r\n const project = await tui.text({\r\n message: 'Enter default project slug:',\r\n initialValue: currentConfig.project,\r\n placeholder: 'e.g., my-awesome-project'\r\n });\r\n\r\n if (!tui.isCancel(project)) {\r\n saveGlobalRC({ project: project as string });\r\n tui.log.success(`Updated project to: ${project}`);\r\n }\r\n }\r\n\r\n if (action === 'language') {\r\n const lang = await tui.select({\r\n message: 'Select language:',\r\n options: [\r\n { value: 'pt-br', label: 'Portuguese (Brazil)' },\r\n { value: 'en-us', label: 'English (US)' }\r\n ],\r\n initialValue: currentConfig.language\r\n });\r\n\r\n if (!tui.isCancel(lang)) {\r\n saveGlobalRC({ language: lang as any });\r\n tui.log.success(`Updated language to: ${lang}`);\r\n }\r\n }\r\n\r\n if (action === 'logLevel') {\r\n const level = await tui.select({\r\n message: 'Select log level:',\r\n options: [\r\n { value: 'debug', label: 'Debug (Verbose)' },\r\n { value: 'info', label: 'Info (Standard)' },\r\n { value: 'warn', label: 'Warn (Important only)' },\r\n { value: 'error', label: 'Error (Critical only)' }\r\n ],\r\n initialValue: currentConfig.logLevel\r\n });\r\n\r\n if (!tui.isCancel(level)) {\r\n saveGlobalRC({ logLevel: level as any });\r\n tui.log.success(`Updated log level to: ${level}`);\r\n }\r\n }\r\n\r\n // Reload to confirm\r\n manager.reloadConfig();\r\n tui.outro('Configuration saved successfully to ~/.sharkrc');\r\n\r\n } catch (error: any) {\r\n tui.log.error(`Failed to save configuration: ${error.message}`);\r\n process.exit(1);\r\n }\r\n }\r\n};\r\n"],"mappings":"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","names":["text","os","path","fs","z","z","fs","os","path","spinner"]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ configCommand,
4
+ loginCommand
5
+ } from "./chunk-B7PNFPUX.js";
6
+
7
+ // src/index.ts
8
+ import { Command } from "commander";
9
+ var program = new Command();
10
+ program.name("shark").description("Shark CLI: AI-Native Collaborative Development Tool").version("0.0.1");
11
+ program.addCommand(loginCommand);
12
+ program.command("config").description("Manage global configuration").action(configCommand.action);
13
+ program.parse();
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Command } from 'commander';\r\nimport { loginCommand } from './commands/login.js';\r\nimport { configCommand } from './commands/config.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('shark')\r\n .description('Shark CLI: AI-Native Collaborative Development Tool')\r\n .version('0.0.1');\r\n\r\nprogram.addCommand(loginCommand);\r\n\r\nprogram\r\n .command('config')\r\n .description('Manage global configuration')\r\n .action(configCommand.action);\r\n\r\nprogram.parse();\r\n"],"mappings":";;;;;;;AAAA,SAAS,eAAe;AAIxB,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACK,KAAK,OAAO,EACZ,YAAY,qDAAqD,EACjE,QAAQ,OAAO;AAEpB,QAAQ,WAAW,YAAY;AAE/B,QACK,QAAQ,QAAQ,EAChB,YAAY,6BAA6B,EACzC,OAAO,cAAc,MAAM;AAEhC,QAAQ,MAAM;","names":[]}