@tostudy-ai/cli 0.1.1 → 0.1.3

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/dist/cli.js CHANGED
@@ -5,9 +5,16 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __commonJS = (cb, mod) => function __require() {
9
12
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
13
  };
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
11
18
  var __copyProps = (to, from, except, desc) => {
12
19
  if (from && typeof from === "object" || typeof from === "function") {
13
20
  for (let key of __getOwnPropNames(from))
@@ -25,85 +32,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
32
  mod
26
33
  ));
27
34
 
28
- // ../../node_modules/picocolors/picocolors.js
29
- var require_picocolors = __commonJS({
30
- "../../node_modules/picocolors/picocolors.js"(exports, module) {
31
- var p = process || {};
32
- var argv = p.argv || [];
33
- var env = p.env || {};
34
- var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
35
- var formatter = (open, close, replace = open) => (input) => {
36
- let string = "" + input, index = string.indexOf(close, open.length);
37
- return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
38
- };
39
- var replaceClose = (string, close, replace, index) => {
40
- let result = "", cursor = 0;
41
- do {
42
- result += string.substring(cursor, index) + replace;
43
- cursor = index + close.length;
44
- index = string.indexOf(close, cursor);
45
- } while (~index);
46
- return result + string.substring(cursor);
47
- };
48
- var createColors = (enabled = isColorSupported) => {
49
- let f = enabled ? formatter : () => String;
50
- return {
51
- isColorSupported: enabled,
52
- reset: f("\x1B[0m", "\x1B[0m"),
53
- bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
54
- dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
55
- italic: f("\x1B[3m", "\x1B[23m"),
56
- underline: f("\x1B[4m", "\x1B[24m"),
57
- inverse: f("\x1B[7m", "\x1B[27m"),
58
- hidden: f("\x1B[8m", "\x1B[28m"),
59
- strikethrough: f("\x1B[9m", "\x1B[29m"),
60
- black: f("\x1B[30m", "\x1B[39m"),
61
- red: f("\x1B[31m", "\x1B[39m"),
62
- green: f("\x1B[32m", "\x1B[39m"),
63
- yellow: f("\x1B[33m", "\x1B[39m"),
64
- blue: f("\x1B[34m", "\x1B[39m"),
65
- magenta: f("\x1B[35m", "\x1B[39m"),
66
- cyan: f("\x1B[36m", "\x1B[39m"),
67
- white: f("\x1B[37m", "\x1B[39m"),
68
- gray: f("\x1B[90m", "\x1B[39m"),
69
- bgBlack: f("\x1B[40m", "\x1B[49m"),
70
- bgRed: f("\x1B[41m", "\x1B[49m"),
71
- bgGreen: f("\x1B[42m", "\x1B[49m"),
72
- bgYellow: f("\x1B[43m", "\x1B[49m"),
73
- bgBlue: f("\x1B[44m", "\x1B[49m"),
74
- bgMagenta: f("\x1B[45m", "\x1B[49m"),
75
- bgCyan: f("\x1B[46m", "\x1B[49m"),
76
- bgWhite: f("\x1B[47m", "\x1B[49m"),
77
- blackBright: f("\x1B[90m", "\x1B[39m"),
78
- redBright: f("\x1B[91m", "\x1B[39m"),
79
- greenBright: f("\x1B[92m", "\x1B[39m"),
80
- yellowBright: f("\x1B[93m", "\x1B[39m"),
81
- blueBright: f("\x1B[94m", "\x1B[39m"),
82
- magentaBright: f("\x1B[95m", "\x1B[39m"),
83
- cyanBright: f("\x1B[96m", "\x1B[39m"),
84
- whiteBright: f("\x1B[97m", "\x1B[39m"),
85
- bgBlackBright: f("\x1B[100m", "\x1B[49m"),
86
- bgRedBright: f("\x1B[101m", "\x1B[49m"),
87
- bgGreenBright: f("\x1B[102m", "\x1B[49m"),
88
- bgYellowBright: f("\x1B[103m", "\x1B[49m"),
89
- bgBlueBright: f("\x1B[104m", "\x1B[49m"),
90
- bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
91
- bgCyanBright: f("\x1B[106m", "\x1B[49m"),
92
- bgWhiteBright: f("\x1B[107m", "\x1B[49m")
93
- };
94
- };
95
- module.exports = createColors();
96
- module.exports.createColors = createColors;
97
- }
98
- });
99
-
100
- // src/cli.ts
101
- import { Command as Command15 } from "commander";
102
-
103
- // src/commands/login.ts
104
- import { Command } from "commander";
105
- import { execFile } from "node:child_process";
106
-
107
35
  // src/auth/oauth-server.ts
108
36
  import http from "node:http";
109
37
  function startCallbackServer(port) {
@@ -114,7 +42,9 @@ function startCallbackServer(port) {
114
42
  const code = url.searchParams.get("code");
115
43
  if (code) {
116
44
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
117
- res.end("<html><body><h1>Autenticado!</h1><p>Pode fechar esta aba.</p></body></html>");
45
+ res.end(
46
+ `<!DOCTYPE html><html lang="pt-BR"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>ToStudy</title><style>*{margin:0;padding:0;box-sizing:border-box}body{background:#0a0a0a;color:#fafafa;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh}.c{text-align:center;padding:2rem}.ck{width:80px;height:80px;border-radius:50%;border:3px solid #22d3ee;display:flex;align-items:center;justify-content:center;margin:0 auto 1.5rem;animation:s .4s ease-out}.cm{width:40px;height:40px;stroke:#22d3ee;stroke-width:3;fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:50;stroke-dashoffset:50;animation:d .5s ease-out .3s forwards}h1{font-size:1.5rem;font-weight:600;margin-bottom:.5rem}.s{color:#a1a1aa;font-size:.95rem;margin-bottom:.25rem}.b{color:#22d3ee;font-size:.85rem;margin-top:2rem;letter-spacing:.05em}@keyframes s{from{transform:scale(0);opacity:0}to{transform:scale(1);opacity:1}}@keyframes d{to{stroke-dashoffset:0}}</style></head><body><div class="c"><div class="ck"><svg class="cm" viewBox="0 0 40 40"><polyline points="12,20 18,26 28,14"/></svg></div><h1>Autenticado com sucesso!</h1><p class="s">Pode voltar ao terminal.</p><p class="s" id="m">Esta aba ser\xE1 fechada automaticamente.</p><p class="b">ToStudy</p></div><script>setTimeout(function(){window.close();document.getElementById('m').textContent='Pode fechar esta aba manualmente.'},3000)</script></body></html>`
47
+ );
118
48
  server.close();
119
49
  resolve({ code });
120
50
  } else {
@@ -135,12 +65,18 @@ function startCallbackServer(port) {
135
65
  reject(err);
136
66
  }
137
67
  });
138
- setTimeout(() => {
68
+ const timeoutId = setTimeout(() => {
139
69
  server.close();
140
70
  reject(new Error("Login timeout \u2014 nenhuma resposta em 2 minutos"));
141
71
  }, 12e4);
72
+ timeoutId.unref();
142
73
  });
143
74
  }
75
+ var init_oauth_server = __esm({
76
+ "src/auth/oauth-server.ts"() {
77
+ "use strict";
78
+ }
79
+ });
144
80
 
145
81
  // src/auth/session.ts
146
82
  import fs from "node:fs";
@@ -207,6 +143,11 @@ async function requireActiveCourse(configDir) {
207
143
  }
208
144
  return course;
209
145
  }
146
+ var init_session = __esm({
147
+ "src/auth/session.ts"() {
148
+ "use strict";
149
+ }
150
+ });
210
151
 
211
152
  // src/output/formatter.ts
212
153
  function output(data, opts) {
@@ -367,64 +308,84 @@ function formatModuleStart(data) {
367
308
  );
368
309
  return lines.join("\n");
369
310
  }
311
+ var init_formatter = __esm({
312
+ "src/output/formatter.ts"() {
313
+ "use strict";
314
+ }
315
+ });
370
316
 
371
317
  // src/commands/login.ts
372
- var DEFAULT_API_URL = "https://tostudy.ai";
373
- var PORT = 9876;
374
- var loginCommand = new Command("login").description("Autentica no ToStudy via browser").option("--manual", "Login manual (sem browser)").option("--api-url <url>", "API URL override", DEFAULT_API_URL).action(async (opts) => {
375
- const apiUrl = opts.apiUrl;
376
- if (opts.manual) {
377
- console.log(`
318
+ import { Command } from "commander";
319
+ import { execFile } from "node:child_process";
320
+ var DEFAULT_API_URL, PORT, loginCommand;
321
+ var init_login = __esm({
322
+ "src/commands/login.ts"() {
323
+ "use strict";
324
+ init_oauth_server();
325
+ init_session();
326
+ init_formatter();
327
+ DEFAULT_API_URL = "https://tostudy.ai";
328
+ PORT = 9876;
329
+ loginCommand = new Command("login").description("Autentica no ToStudy via browser").option("--manual", "Login manual (sem browser)").option("--api-url <url>", "API URL override", DEFAULT_API_URL).action(async (opts) => {
330
+ const apiUrl = opts.apiUrl;
331
+ if (opts.manual) {
332
+ console.log(`
378
333
  Acesse este endere\xE7o no seu browser:`);
379
- console.log(` ${apiUrl}/api/cli/auth/authorize?port=${PORT}
334
+ console.log(` ${apiUrl}/api/cli/auth/authorize?port=${PORT}
380
335
  `);
381
- console.log(" Ap\xF3s autorizar, o browser ser\xE1 redirecionado e o login ser\xE1 conclu\xEDdo.");
382
- console.log(" Certifique-se de rodar este comando sem --manual para o fluxo autom\xE1tico.\n");
383
- return;
384
- }
385
- console.log("\n Abrindo browser para autentica\xE7\xE3o...\n");
386
- const serverPromise = startCallbackServer(PORT);
387
- const authUrl = `${apiUrl}/api/cli/auth/authorize?port=${PORT}`;
388
- const openCmd = process.platform === "darwin" ? "open" : "xdg-open";
389
- execFile(openCmd, [authUrl], (err) => {
390
- if (err) {
391
- console.log(` N\xE3o foi poss\xEDvel abrir o browser automaticamente.`);
392
- console.log(` Abra manualmente: ${authUrl}
336
+ console.log(" Ap\xF3s autorizar, o browser ser\xE1 redirecionado e o login ser\xE1 conclu\xEDdo.");
337
+ console.log(" Certifique-se de rodar este comando sem --manual para o fluxo autom\xE1tico.\n");
338
+ return;
339
+ }
340
+ console.log("\n Abrindo browser para autentica\xE7\xE3o...\n");
341
+ const serverPromise = startCallbackServer(PORT);
342
+ const authUrl = `${apiUrl}/api/cli/auth/authorize?port=${PORT}`;
343
+ const openCmd = process.platform === "darwin" ? "open" : "xdg-open";
344
+ execFile(openCmd, [authUrl], (err) => {
345
+ if (err) {
346
+ console.log(` N\xE3o foi poss\xEDvel abrir o browser automaticamente.`);
347
+ console.log(` Abra manualmente: ${authUrl}
393
348
  `);
394
- }
395
- });
396
- try {
397
- const { code } = await serverPromise;
398
- const res = await fetch(`${apiUrl}/api/cli/auth/exchange`, {
399
- method: "POST",
400
- headers: { "Content-Type": "application/json" },
401
- body: JSON.stringify({ code })
402
- });
403
- if (!res.ok) {
404
- const body = await res.json();
405
- error(body.error ?? "Falha na autentica\xE7\xE3o");
406
- }
407
- const { token: token2, userId, userName, expiresAt } = await res.json();
408
- await saveSession({ token: token2, userId, userName, expiresAt, apiUrl });
409
- console.log(`
349
+ }
350
+ });
351
+ try {
352
+ const { code } = await serverPromise;
353
+ const res = await fetch(`${apiUrl}/api/cli/auth/exchange`, {
354
+ method: "POST",
355
+ headers: { "Content-Type": "application/json" },
356
+ body: JSON.stringify({ code })
357
+ });
358
+ if (!res.ok) {
359
+ const body = await res.json();
360
+ error(body.error ?? "Falha na autentica\xE7\xE3o");
361
+ }
362
+ const { token: token2, userId, userName, expiresAt } = await res.json();
363
+ await saveSession({ token: token2, userId, userName, expiresAt, apiUrl });
364
+ console.log(`
410
365
  Logado como ${userName}
411
366
  `);
412
- } catch (err) {
413
- const msg = err instanceof Error ? err.message : "Login falhou";
414
- error(msg);
367
+ } catch (err) {
368
+ const msg = err instanceof Error ? err.message : "Login falhou";
369
+ error(msg);
370
+ }
371
+ });
415
372
  }
416
373
  });
417
374
 
418
375
  // src/commands/logout.ts
419
376
  import { Command as Command2 } from "commander";
420
- var logoutCommand = new Command2("logout").description("Remove token local").action(async () => {
421
- await clearSession();
422
- console.log("\n Deslogado com sucesso.\n");
377
+ var logoutCommand;
378
+ var init_logout = __esm({
379
+ "src/commands/logout.ts"() {
380
+ "use strict";
381
+ init_session();
382
+ logoutCommand = new Command2("logout").description("Remove token local").action(async () => {
383
+ await clearSession();
384
+ console.log("\n Deslogado com sucesso.\n");
385
+ });
386
+ }
423
387
  });
424
388
 
425
- // src/commands/setup.ts
426
- import { Command as Command3 } from "commander";
427
-
428
389
  // src/installer/node-detector.ts
429
390
  import { execFileSync } from "node:child_process";
430
391
  function detectNode() {
@@ -444,6 +405,11 @@ function detectNode() {
444
405
  return { installed: false, version: null, meetsMinimum: false, path: null };
445
406
  }
446
407
  }
408
+ var init_node_detector = __esm({
409
+ "src/installer/node-detector.ts"() {
410
+ "use strict";
411
+ }
412
+ });
447
413
 
448
414
  // src/installer/ide-detector.ts
449
415
  import { execFileSync as execFileSync2 } from "node:child_process";
@@ -524,164 +490,230 @@ function detectIDEs() {
524
490
  }
525
491
  return ides;
526
492
  }
493
+ var init_ide_detector = __esm({
494
+ "src/installer/ide-detector.ts"() {
495
+ "use strict";
496
+ }
497
+ });
527
498
 
528
499
  // src/commands/setup.ts
529
- var setupCommand = new Command3("setup").description("Configura ambiente para estudar").option("--quick", "Setup r\xE1pido (sem wizard)").option("--ide <ide>", "Configura IDE espec\xEDfica").action(async (_opts) => {
530
- console.log("\n ToStudy Setup\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
531
- console.log(" 1. Verificando Node.js...");
532
- const node = detectNode();
533
- if (!node.installed) {
534
- console.log(" \u2717 Node.js n\xE3o encontrado");
535
- console.log(" \u2192 Instale via: https://nodejs.org/ ou `nvm install --lts`\n");
536
- process.exit(1);
537
- }
538
- if (!node.meetsMinimum) {
539
- console.log(` \u2717 Node.js ${node.version} \xE9 muito antigo (m\xEDnimo: v18)`);
540
- console.log(" \u2192 Atualize via: `nvm install --lts`\n");
541
- process.exit(1);
542
- }
543
- console.log(` \u2713 Node.js ${node.version}
500
+ import { Command as Command3 } from "commander";
501
+ var setupCommand;
502
+ var init_setup = __esm({
503
+ "src/commands/setup.ts"() {
504
+ "use strict";
505
+ init_node_detector();
506
+ init_ide_detector();
507
+ init_session();
508
+ setupCommand = new Command3("setup").description("Configura ambiente para estudar").option("--quick", "Setup r\xE1pido (sem wizard)").option("--ide <ide>", "Configura IDE espec\xEDfica").action(async (_opts) => {
509
+ console.log("\n ToStudy Setup\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
510
+ console.log(" 1. Verificando Node.js...");
511
+ const node = detectNode();
512
+ if (!node.installed) {
513
+ console.log(" \u2717 Node.js n\xE3o encontrado");
514
+ console.log(" \u2192 Instale via: https://nodejs.org/ ou `nvm install --lts`\n");
515
+ process.exit(1);
516
+ }
517
+ if (!node.meetsMinimum) {
518
+ console.log(` \u2717 Node.js ${node.version} \xE9 muito antigo (m\xEDnimo: v18)`);
519
+ console.log(" \u2192 Atualize via: `nvm install --lts`\n");
520
+ process.exit(1);
521
+ }
522
+ console.log(` \u2713 Node.js ${node.version}
544
523
  `);
545
- console.log(" 2. Verificando autentica\xE7\xE3o...");
546
- let session = null;
547
- try {
548
- session = await getSession();
549
- } catch {
550
- }
551
- if (!session) {
552
- console.log(" \u2717 N\xE3o autenticado");
553
- console.log(" \u2192 Rode: tostudy login\n");
554
- process.exit(1);
555
- }
556
- console.log(` \u2713 Logado como ${session.userName}
524
+ console.log(" 2. Verificando autentica\xE7\xE3o...");
525
+ let session = null;
526
+ try {
527
+ session = await getSession();
528
+ } catch {
529
+ }
530
+ if (!session) {
531
+ console.log(" \u2717 N\xE3o autenticado");
532
+ console.log(" \u2192 Rode: tostudy login\n");
533
+ process.exit(1);
534
+ }
535
+ console.log(` \u2713 Logado como ${session.userName}
557
536
  `);
558
- console.log(" 3. Detectando IDEs...");
559
- let ides = [];
560
- try {
561
- ides = detectIDEs();
562
- } catch {
563
- }
564
- const detected = ides.filter((ide) => ide.detected);
565
- if (detected.length === 0) {
566
- console.log(" \u25CB Nenhum IDE detectado");
567
- console.log(" \u2192 Use tostudy diretamente no terminal\n");
568
- } else {
569
- for (const ide of detected) {
570
- console.log(` \u2713 ${ide.name} detectado`);
571
- }
572
- console.log("");
537
+ console.log(" 3. Detectando IDEs...");
538
+ let ides = [];
539
+ try {
540
+ ides = detectIDEs();
541
+ } catch {
542
+ }
543
+ const detected = ides.filter((ide) => ide.detected);
544
+ if (detected.length === 0) {
545
+ console.log(" \u25CB Nenhum IDE detectado");
546
+ console.log(" \u2192 Use tostudy diretamente no terminal\n");
547
+ } else {
548
+ for (const ide of detected) {
549
+ console.log(` \u2713 ${ide.name} detectado`);
550
+ }
551
+ console.log("");
552
+ }
553
+ console.log(" Setup completo!");
554
+ console.log(" \u2192 tostudy courses (ver cursos matriculados)");
555
+ console.log(" \u2192 tostudy doctor (diagn\xF3stico completo)\n");
556
+ });
573
557
  }
574
- console.log(" Setup completo!");
575
- console.log(" \u2192 tostudy courses (ver cursos matriculados)");
576
- console.log(" \u2192 tostudy doctor (diagn\xF3stico completo)\n");
577
558
  });
578
559
 
579
560
  // src/commands/doctor.ts
580
561
  import { Command as Command4 } from "commander";
581
- var doctorCommand = new Command4("doctor").description("Diagn\xF3stico do ambiente").option("--json", "Output JSON").option("--fix", "Auto-corrigir problemas (reservado para vers\xF5es futuras)").action(async (opts) => {
582
- const checks = {};
583
- const node = detectNode();
584
- const envChecks = {
585
- os: { platform: process.platform, arch: process.arch },
586
- node: { ...node },
587
- pnpm: null,
588
- git: null
589
- };
590
- try {
591
- const { execFileSync: execFileSync3 } = await import("node:child_process");
592
- envChecks["pnpm"] = execFileSync3("pnpm", ["--version"], { encoding: "utf-8" }).trim();
593
- } catch {
594
- envChecks["pnpm"] = null;
595
- }
596
- try {
597
- const { execFileSync: execFileSync3 } = await import("node:child_process");
598
- envChecks["git"] = execFileSync3("git", ["--version"], { encoding: "utf-8" }).trim().replace("git version ", "");
599
- } catch {
600
- envChecks["git"] = null;
601
- }
602
- checks["environment"] = envChecks;
603
- let session = null;
604
- try {
605
- session = await getSession();
606
- } catch {
607
- }
608
- checks["auth"] = {
609
- loggedIn: !!session,
610
- userName: session?.userName ?? null,
611
- expiresAt: session?.expiresAt ?? null
612
- };
613
- try {
614
- const apiUrl = session?.apiUrl ?? "https://tostudy.ai";
615
- const start = Date.now();
616
- const res = await fetch(`${apiUrl}/api/mcp/heartbeat`, {
617
- method: "POST",
618
- headers: session ? { Authorization: `Bearer ${session.token}` } : {},
619
- signal: AbortSignal.timeout(5e3)
562
+ var doctorCommand;
563
+ var init_doctor = __esm({
564
+ "src/commands/doctor.ts"() {
565
+ "use strict";
566
+ init_node_detector();
567
+ init_ide_detector();
568
+ init_session();
569
+ init_formatter();
570
+ doctorCommand = new Command4("doctor").description("Diagn\xF3stico do ambiente").option("--json", "Output JSON").option("--fix", "Auto-corrigir problemas (reservado para vers\xF5es futuras)").action(async (opts) => {
571
+ const checks = {};
572
+ const node = detectNode();
573
+ const envChecks = {
574
+ os: { platform: process.platform, arch: process.arch },
575
+ node: { ...node },
576
+ pnpm: null,
577
+ git: null
578
+ };
579
+ try {
580
+ const { execFileSync: execFileSync3 } = await import("node:child_process");
581
+ envChecks["pnpm"] = execFileSync3("pnpm", ["--version"], { encoding: "utf-8" }).trim();
582
+ } catch {
583
+ envChecks["pnpm"] = null;
584
+ }
585
+ try {
586
+ const { execFileSync: execFileSync3 } = await import("node:child_process");
587
+ envChecks["git"] = execFileSync3("git", ["--version"], { encoding: "utf-8" }).trim().replace("git version ", "");
588
+ } catch {
589
+ envChecks["git"] = null;
590
+ }
591
+ checks["environment"] = envChecks;
592
+ let session = null;
593
+ try {
594
+ session = await getSession();
595
+ } catch {
596
+ }
597
+ checks["auth"] = {
598
+ loggedIn: !!session,
599
+ userName: session?.userName ?? null,
600
+ expiresAt: session?.expiresAt ?? null
601
+ };
602
+ try {
603
+ const apiUrl = session?.apiUrl ?? "https://tostudy.ai";
604
+ const start = Date.now();
605
+ const res = await fetch(`${apiUrl}/api/health`, {
606
+ signal: AbortSignal.timeout(5e3)
607
+ });
608
+ checks["connectivity"] = { ok: res.ok, latencyMs: Date.now() - start };
609
+ } catch {
610
+ checks["connectivity"] = { ok: false, latencyMs: null };
611
+ }
612
+ let ides = [];
613
+ try {
614
+ ides = detectIDEs();
615
+ } catch {
616
+ }
617
+ checks["ides"] = ides.filter((ide) => ide.detected);
618
+ if (opts.json) {
619
+ output(checks, { json: true });
620
+ return;
621
+ }
622
+ const pnpmVersion = envChecks["pnpm"];
623
+ const gitVersion = envChecks["git"];
624
+ const connectivity = checks["connectivity"];
625
+ console.log("\n Ambiente");
626
+ console.log(
627
+ ` ${node.installed ? "\u2713" : "\u2717"} Node ${node.version ?? "n\xE3o encontrado"}`
628
+ );
629
+ console.log(
630
+ ` ${node.meetsMinimum ? "\u2713" : "\u2717"} Vers\xE3o ${node.meetsMinimum ? "OK (>= 18)" : "Desatualizado"}`
631
+ );
632
+ console.log(` \u2713 OS ${process.platform} (${process.arch})`);
633
+ console.log(` ${pnpmVersion ? "\u2713" : "\u25CB"} pnpm ${pnpmVersion ?? "n\xE3o encontrado"}`);
634
+ console.log(` ${gitVersion ? "\u2713" : "\u25CB"} git ${gitVersion ?? "n\xE3o encontrado"}`);
635
+ console.log("\n Autentica\xE7\xE3o");
636
+ console.log(` ${session ? "\u2713" : "\u2717"} Token ${session ? "v\xE1lido" : "n\xE3o logado"}`);
637
+ if (session) {
638
+ console.log(` \u2713 Usu\xE1rio ${session.userName}`);
639
+ }
640
+ console.log("\n Conectividade");
641
+ console.log(
642
+ ` ${connectivity.ok ? "\u2713" : "\u2717"} API ${connectivity.ok ? `OK (${connectivity.latencyMs}ms)` : "indispon\xEDvel"}`
643
+ );
644
+ console.log("\n LLM Clients");
645
+ for (const ide of ides) {
646
+ console.log(
647
+ ` ${ide.detected ? "\u2713" : "\u25CB"} ${ide.name.padEnd(14)} ${ide.detected ? "detectado" : "n\xE3o detectado"}`
648
+ );
649
+ }
650
+ console.log("");
620
651
  });
621
- checks["connectivity"] = { ok: res.ok, latencyMs: Date.now() - start };
622
- } catch {
623
- checks["connectivity"] = { ok: false, latencyMs: null };
624
- }
625
- let ides = [];
626
- try {
627
- ides = detectIDEs();
628
- } catch {
629
652
  }
630
- checks["ides"] = ides.filter((ide) => ide.detected);
631
- if (opts.json) {
632
- output(checks, { json: true });
633
- return;
634
- }
635
- const pnpmVersion = envChecks["pnpm"];
636
- const gitVersion = envChecks["git"];
637
- const connectivity = checks["connectivity"];
638
- console.log("\n Ambiente");
639
- console.log(
640
- ` ${node.installed ? "\u2713" : "\u2717"} Node ${node.version ?? "n\xE3o encontrado"}`
641
- );
642
- console.log(
643
- ` ${node.meetsMinimum ? "\u2713" : "\u2717"} Vers\xE3o ${node.meetsMinimum ? "OK (>= 18)" : "Desatualizado"}`
644
- );
645
- console.log(` \u2713 OS ${process.platform} (${process.arch})`);
646
- console.log(` ${pnpmVersion ? "\u2713" : "\u25CB"} pnpm ${pnpmVersion ?? "n\xE3o encontrado"}`);
647
- console.log(` ${gitVersion ? "\u2713" : "\u25CB"} git ${gitVersion ?? "n\xE3o encontrado"}`);
648
- console.log("\n Autentica\xE7\xE3o");
649
- console.log(` ${session ? "\u2713" : "\u2717"} Token ${session ? "v\xE1lido" : "n\xE3o logado"}`);
650
- if (session) {
651
- console.log(` \u2713 Usu\xE1rio ${session.userName}`);
652
- }
653
- console.log("\n Conectividade");
654
- console.log(
655
- ` ${connectivity.ok ? "\u2713" : "\u2717"} API ${connectivity.ok ? `OK (${connectivity.latencyMs}ms)` : "indispon\xEDvel"}`
656
- );
657
- console.log("\n LLM Clients");
658
- for (const ide of ides) {
659
- console.log(
660
- ` ${ide.detected ? "\u2713" : "\u25CB"} ${ide.name.padEnd(14)} ${ide.detected ? "detectado" : "n\xE3o detectado"}`
661
- );
662
- }
663
- console.log("");
664
653
  });
665
654
 
666
- // src/commands/courses.ts
667
- import { Command as Command5 } from "commander";
668
-
669
655
  // ../../packages/logger/src/types.ts
670
- var LOG_LEVELS = {
671
- trace: 0,
672
- debug: 1,
673
- info: 2,
674
- warn: 3,
675
- error: 4,
676
- fatal: 5
677
- };
656
+ var LOG_LEVELS;
657
+ var init_types = __esm({
658
+ "../../packages/logger/src/types.ts"() {
659
+ "use strict";
660
+ LOG_LEVELS = {
661
+ trace: 0,
662
+ debug: 1,
663
+ info: 2,
664
+ warn: 3,
665
+ error: 4,
666
+ fatal: 5
667
+ };
668
+ }
669
+ });
678
670
 
679
671
  // ../../packages/logger/src/context/async-context.ts
680
672
  import { AsyncLocalStorage } from "node:async_hooks";
681
- var asyncLocalStorage = new AsyncLocalStorage();
682
673
  function getLogContext() {
683
674
  return asyncLocalStorage.getStore();
684
675
  }
676
+ var asyncLocalStorage;
677
+ var init_async_context = __esm({
678
+ "../../packages/logger/src/context/async-context.ts"() {
679
+ "use strict";
680
+ asyncLocalStorage = new AsyncLocalStorage();
681
+ }
682
+ });
683
+
684
+ // ../../packages/logger/src/context/span.shared.ts
685
+ var init_span_shared = __esm({
686
+ "../../packages/logger/src/context/span.shared.ts"() {
687
+ "use strict";
688
+ }
689
+ });
690
+
691
+ // ../../packages/logger/src/context/span.ts
692
+ var init_span = __esm({
693
+ "../../packages/logger/src/context/span.ts"() {
694
+ "use strict";
695
+ init_async_context();
696
+ init_span_shared();
697
+ }
698
+ });
699
+
700
+ // ../../packages/logger/src/context/w3c-trace.ts
701
+ var init_w3c_trace = __esm({
702
+ "../../packages/logger/src/context/w3c-trace.ts"() {
703
+ "use strict";
704
+ init_async_context();
705
+ }
706
+ });
707
+
708
+ // ../../packages/logger/src/context/index.ts
709
+ var init_context = __esm({
710
+ "../../packages/logger/src/context/index.ts"() {
711
+ "use strict";
712
+ init_async_context();
713
+ init_span();
714
+ init_w3c_trace();
715
+ }
716
+ });
685
717
 
686
718
  // ../../packages/logger/src/formatters/json.ts
687
719
  function formatJson(entry) {
@@ -700,18 +732,85 @@ function formatJson(entry) {
700
732
  }
701
733
  return JSON.stringify(output2);
702
734
  }
735
+ var init_json = __esm({
736
+ "../../packages/logger/src/formatters/json.ts"() {
737
+ "use strict";
738
+ }
739
+ });
740
+
741
+ // ../../node_modules/picocolors/picocolors.js
742
+ var require_picocolors = __commonJS({
743
+ "../../node_modules/picocolors/picocolors.js"(exports, module) {
744
+ var p = process || {};
745
+ var argv = p.argv || [];
746
+ var env = p.env || {};
747
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
748
+ var formatter = (open, close, replace = open) => (input) => {
749
+ let string = "" + input, index = string.indexOf(close, open.length);
750
+ return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
751
+ };
752
+ var replaceClose = (string, close, replace, index) => {
753
+ let result = "", cursor = 0;
754
+ do {
755
+ result += string.substring(cursor, index) + replace;
756
+ cursor = index + close.length;
757
+ index = string.indexOf(close, cursor);
758
+ } while (~index);
759
+ return result + string.substring(cursor);
760
+ };
761
+ var createColors = (enabled = isColorSupported) => {
762
+ let f = enabled ? formatter : () => String;
763
+ return {
764
+ isColorSupported: enabled,
765
+ reset: f("\x1B[0m", "\x1B[0m"),
766
+ bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
767
+ dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
768
+ italic: f("\x1B[3m", "\x1B[23m"),
769
+ underline: f("\x1B[4m", "\x1B[24m"),
770
+ inverse: f("\x1B[7m", "\x1B[27m"),
771
+ hidden: f("\x1B[8m", "\x1B[28m"),
772
+ strikethrough: f("\x1B[9m", "\x1B[29m"),
773
+ black: f("\x1B[30m", "\x1B[39m"),
774
+ red: f("\x1B[31m", "\x1B[39m"),
775
+ green: f("\x1B[32m", "\x1B[39m"),
776
+ yellow: f("\x1B[33m", "\x1B[39m"),
777
+ blue: f("\x1B[34m", "\x1B[39m"),
778
+ magenta: f("\x1B[35m", "\x1B[39m"),
779
+ cyan: f("\x1B[36m", "\x1B[39m"),
780
+ white: f("\x1B[37m", "\x1B[39m"),
781
+ gray: f("\x1B[90m", "\x1B[39m"),
782
+ bgBlack: f("\x1B[40m", "\x1B[49m"),
783
+ bgRed: f("\x1B[41m", "\x1B[49m"),
784
+ bgGreen: f("\x1B[42m", "\x1B[49m"),
785
+ bgYellow: f("\x1B[43m", "\x1B[49m"),
786
+ bgBlue: f("\x1B[44m", "\x1B[49m"),
787
+ bgMagenta: f("\x1B[45m", "\x1B[49m"),
788
+ bgCyan: f("\x1B[46m", "\x1B[49m"),
789
+ bgWhite: f("\x1B[47m", "\x1B[49m"),
790
+ blackBright: f("\x1B[90m", "\x1B[39m"),
791
+ redBright: f("\x1B[91m", "\x1B[39m"),
792
+ greenBright: f("\x1B[92m", "\x1B[39m"),
793
+ yellowBright: f("\x1B[93m", "\x1B[39m"),
794
+ blueBright: f("\x1B[94m", "\x1B[39m"),
795
+ magentaBright: f("\x1B[95m", "\x1B[39m"),
796
+ cyanBright: f("\x1B[96m", "\x1B[39m"),
797
+ whiteBright: f("\x1B[97m", "\x1B[39m"),
798
+ bgBlackBright: f("\x1B[100m", "\x1B[49m"),
799
+ bgRedBright: f("\x1B[101m", "\x1B[49m"),
800
+ bgGreenBright: f("\x1B[102m", "\x1B[49m"),
801
+ bgYellowBright: f("\x1B[103m", "\x1B[49m"),
802
+ bgBlueBright: f("\x1B[104m", "\x1B[49m"),
803
+ bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
804
+ bgCyanBright: f("\x1B[106m", "\x1B[49m"),
805
+ bgWhiteBright: f("\x1B[107m", "\x1B[49m")
806
+ };
807
+ };
808
+ module.exports = createColors();
809
+ module.exports.createColors = createColors;
810
+ }
811
+ });
703
812
 
704
813
  // ../../packages/logger/src/formatters/pretty.ts
705
- var import_picocolors = __toESM(require_picocolors(), 1);
706
- var LEVEL_COLORS = {
707
- trace: import_picocolors.default.gray,
708
- debug: import_picocolors.default.cyan,
709
- info: import_picocolors.default.green,
710
- warn: import_picocolors.default.yellow,
711
- error: import_picocolors.default.red,
712
- fatal: (s) => import_picocolors.default.bgRed(import_picocolors.default.white(s))
713
- };
714
- var LEVEL_WIDTH = 5;
715
814
  function formatTime(timestamp) {
716
815
  const date = new Date(timestamp);
717
816
  const hours = String(date.getUTCHours()).padStart(2, "0");
@@ -765,56 +864,24 @@ function formatPretty(entry) {
765
864
  }
766
865
  return output2;
767
866
  }
867
+ var import_picocolors, LEVEL_COLORS, LEVEL_WIDTH;
868
+ var init_pretty = __esm({
869
+ "../../packages/logger/src/formatters/pretty.ts"() {
870
+ "use strict";
871
+ import_picocolors = __toESM(require_picocolors(), 1);
872
+ LEVEL_COLORS = {
873
+ trace: import_picocolors.default.gray,
874
+ debug: import_picocolors.default.cyan,
875
+ info: import_picocolors.default.green,
876
+ warn: import_picocolors.default.yellow,
877
+ error: import_picocolors.default.red,
878
+ fatal: (s) => import_picocolors.default.bgRed(import_picocolors.default.white(s))
879
+ };
880
+ LEVEL_WIDTH = 5;
881
+ }
882
+ });
768
883
 
769
884
  // ../../packages/logger/src/sanitize.ts
770
- var SENSITIVE_FIELDS = [
771
- // Authentication
772
- "password",
773
- "senha",
774
- "pwd",
775
- "pass",
776
- "token",
777
- "accessToken",
778
- "access_token",
779
- "refreshToken",
780
- "refresh_token",
781
- "apiKey",
782
- "api_key",
783
- "apikey",
784
- "secret",
785
- "secretKey",
786
- "secret_key",
787
- "authorization",
788
- "auth",
789
- "bearer",
790
- // Payment
791
- "creditCard",
792
- "credit_card",
793
- "cardNumber",
794
- "card_number",
795
- "cvv",
796
- "cvc",
797
- "securityCode",
798
- "security_code",
799
- "accountNumber",
800
- "account_number",
801
- // Personal identification
802
- "cpf",
803
- "rg",
804
- "ssn",
805
- "cnh",
806
- "passport",
807
- "email",
808
- "phone",
809
- // Crypto
810
- "privateKey",
811
- "private_key",
812
- "privatekey",
813
- "mnemonic",
814
- "seed",
815
- "seedPhrase",
816
- "seed_phrase"
817
- ];
818
885
  function email(value) {
819
886
  if (!value || typeof value !== "string") return "[INVALID_EMAIL]";
820
887
  const atIndex = value.indexOf("@");
@@ -928,17 +995,71 @@ function headers(hdrs) {
928
995
  }
929
996
  return sanitized;
930
997
  }
931
- var sanitize = {
932
- email,
933
- phone,
934
- cpf,
935
- creditCard,
936
- ip,
937
- token,
938
- object,
939
- headers,
940
- isSensitiveKey
941
- };
998
+ var SENSITIVE_FIELDS, sanitize;
999
+ var init_sanitize = __esm({
1000
+ "../../packages/logger/src/sanitize.ts"() {
1001
+ "use strict";
1002
+ SENSITIVE_FIELDS = [
1003
+ // Authentication
1004
+ "password",
1005
+ "senha",
1006
+ "pwd",
1007
+ "pass",
1008
+ "token",
1009
+ "accessToken",
1010
+ "access_token",
1011
+ "refreshToken",
1012
+ "refresh_token",
1013
+ "apiKey",
1014
+ "api_key",
1015
+ "apikey",
1016
+ "secret",
1017
+ "secretKey",
1018
+ "secret_key",
1019
+ "authorization",
1020
+ "auth",
1021
+ "bearer",
1022
+ // Payment
1023
+ "creditCard",
1024
+ "credit_card",
1025
+ "cardNumber",
1026
+ "card_number",
1027
+ "cvv",
1028
+ "cvc",
1029
+ "securityCode",
1030
+ "security_code",
1031
+ "accountNumber",
1032
+ "account_number",
1033
+ // Personal identification
1034
+ "cpf",
1035
+ "rg",
1036
+ "ssn",
1037
+ "cnh",
1038
+ "passport",
1039
+ "email",
1040
+ "phone",
1041
+ // Crypto
1042
+ "privateKey",
1043
+ "private_key",
1044
+ "privatekey",
1045
+ "mnemonic",
1046
+ "seed",
1047
+ "seedPhrase",
1048
+ "seed_phrase"
1049
+ ];
1050
+ sanitize = {
1051
+ email,
1052
+ phone,
1053
+ cpf,
1054
+ creditCard,
1055
+ ip,
1056
+ token,
1057
+ object,
1058
+ headers,
1059
+ isSensitiveKey
1060
+ };
1061
+ }
1062
+ });
942
1063
 
943
1064
  // ../../packages/logger/src/logger.base.ts
944
1065
  function extractErrorInfo(error2, includeStack) {
@@ -957,230 +1078,252 @@ function extractErrorInfo(error2, includeStack) {
957
1078
  }
958
1079
  return info;
959
1080
  }
960
- var BaseLogger = class {
961
- level;
962
- format;
963
- module;
964
- service;
965
- environment;
966
- additionalContext;
967
- transports;
968
- shouldSanitize;
969
- sensitiveFields;
970
- includeCaller;
971
- constructor(options, defaults) {
972
- this.level = options.level ?? defaults.level;
973
- this.format = options.format ?? defaults.format;
974
- this.module = options.module;
975
- this.service = options.service ?? defaults.service;
976
- this.environment = options.environment ?? defaults.env;
977
- this.additionalContext = {};
978
- this.transports = [];
979
- this.shouldSanitize = options.sanitize ?? true;
980
- this.sensitiveFields = options.sensitiveFields;
981
- this.includeCaller = options.includeCaller ?? "errors";
982
- }
983
- /**
984
- * Get caller information for error logging (Node.js only).
985
- */
986
- getCaller() {
987
- return void 0;
988
- }
989
- /**
990
- * Flush any buffered logs (e.g., file transport).
991
- */
992
- flush() {
993
- }
994
- shouldLog(level) {
995
- return LOG_LEVELS[level] >= LOG_LEVELS[this.level];
996
- }
997
- buildEntry(level, message, data, error2) {
998
- const asyncContext = this.getLogContext() ?? {};
999
- const context = {
1000
- ...asyncContext,
1001
- ...this.additionalContext
1002
- };
1003
- if (this.module) {
1004
- context.module = this.module;
1005
- }
1006
- const shouldIncludeCaller = this.includeCaller === true || this.includeCaller === "errors" && (level === "error" || level === "fatal");
1007
- if (shouldIncludeCaller) {
1008
- const caller = this.getCaller();
1009
- if (caller) context.caller = caller;
1010
- }
1011
- return {
1012
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1013
- level,
1014
- message,
1015
- service: this.service,
1016
- environment: this.environment,
1017
- context,
1018
- data,
1019
- error: error2
1081
+ var BaseLogger;
1082
+ var init_logger_base = __esm({
1083
+ "../../packages/logger/src/logger.base.ts"() {
1084
+ "use strict";
1085
+ init_types();
1086
+ init_json();
1087
+ init_pretty();
1088
+ init_sanitize();
1089
+ BaseLogger = class {
1090
+ level;
1091
+ format;
1092
+ module;
1093
+ service;
1094
+ environment;
1095
+ additionalContext;
1096
+ transports;
1097
+ shouldSanitize;
1098
+ sensitiveFields;
1099
+ includeCaller;
1100
+ constructor(options, defaults) {
1101
+ this.level = options.level ?? defaults.level;
1102
+ this.format = options.format ?? defaults.format;
1103
+ this.module = options.module;
1104
+ this.service = options.service ?? defaults.service;
1105
+ this.environment = options.environment ?? defaults.env;
1106
+ this.additionalContext = {};
1107
+ this.transports = [];
1108
+ this.shouldSanitize = options.sanitize ?? true;
1109
+ this.sensitiveFields = options.sensitiveFields;
1110
+ this.includeCaller = options.includeCaller ?? "errors";
1111
+ }
1112
+ /**
1113
+ * Get caller information for error logging (Node.js only).
1114
+ */
1115
+ getCaller() {
1116
+ return void 0;
1117
+ }
1118
+ /**
1119
+ * Flush any buffered logs (e.g., file transport).
1120
+ */
1121
+ flush() {
1122
+ }
1123
+ shouldLog(level) {
1124
+ return LOG_LEVELS[level] >= LOG_LEVELS[this.level];
1125
+ }
1126
+ buildEntry(level, message, data, error2) {
1127
+ const asyncContext = this.getLogContext() ?? {};
1128
+ const context = {
1129
+ ...asyncContext,
1130
+ ...this.additionalContext
1131
+ };
1132
+ if (this.module) {
1133
+ context.module = this.module;
1134
+ }
1135
+ const shouldIncludeCaller = this.includeCaller === true || this.includeCaller === "errors" && (level === "error" || level === "fatal");
1136
+ if (shouldIncludeCaller) {
1137
+ const caller = this.getCaller();
1138
+ if (caller) context.caller = caller;
1139
+ }
1140
+ return {
1141
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1142
+ level,
1143
+ message,
1144
+ service: this.service,
1145
+ environment: this.environment,
1146
+ context,
1147
+ data,
1148
+ error: error2
1149
+ };
1150
+ }
1151
+ /**
1152
+ * Normalizes any data type to Record<string, unknown> for structured logging.
1153
+ */
1154
+ normalizeData(data) {
1155
+ if (data === null || data === void 0) {
1156
+ return void 0;
1157
+ }
1158
+ if (data instanceof Error) {
1159
+ return {
1160
+ error: data.message,
1161
+ errorName: data.name,
1162
+ stack: data.stack
1163
+ };
1164
+ }
1165
+ if (typeof data === "string" || typeof data === "number" || typeof data === "boolean") {
1166
+ return { value: data };
1167
+ }
1168
+ if (Array.isArray(data)) {
1169
+ return { items: data };
1170
+ }
1171
+ if (typeof data === "object") {
1172
+ const obj = data;
1173
+ return this.shouldSanitize ? sanitize.object(obj, this.sensitiveFields) : obj;
1174
+ }
1175
+ return { value: String(data) };
1176
+ }
1177
+ log(level, message, data, errorObj) {
1178
+ if (!this.shouldLog(level)) return;
1179
+ const normalizedData = this.normalizeData(data);
1180
+ const errorInfo = errorObj ? extractErrorInfo(errorObj, !this.isProd()) : void 0;
1181
+ const entry = this.buildEntry(level, message, normalizedData, errorInfo);
1182
+ const formatted = this.format === "json" ? formatJson(entry) : formatPretty(entry);
1183
+ for (const transport of this.transports) {
1184
+ transport.log(entry, formatted);
1185
+ }
1186
+ this.flush();
1187
+ }
1188
+ trace(message, ...args) {
1189
+ this.log("trace", message, args.length === 1 ? args[0] : args.length > 1 ? args : void 0);
1190
+ }
1191
+ debug(message, ...args) {
1192
+ this.log("debug", message, args.length === 1 ? args[0] : args.length > 1 ? args : void 0);
1193
+ }
1194
+ info(message, ...args) {
1195
+ this.log("info", message, args.length === 1 ? args[0] : args.length > 1 ? args : void 0);
1196
+ }
1197
+ warn(message, ...args) {
1198
+ this.log("warn", message, args.length === 1 ? args[0] : args.length > 1 ? args : void 0);
1199
+ }
1200
+ error(message, errorOrData, data) {
1201
+ if (errorOrData instanceof Error) {
1202
+ this.log("error", message, data, errorOrData);
1203
+ } else {
1204
+ this.log("error", message, errorOrData);
1205
+ }
1206
+ }
1207
+ /**
1208
+ * Log a fatal error (system-critical).
1209
+ */
1210
+ fatal(message, errorOrData, data) {
1211
+ if (errorOrData instanceof Error) {
1212
+ this.log("fatal", message, data, errorOrData);
1213
+ } else {
1214
+ this.log("fatal", message, errorOrData);
1215
+ }
1216
+ }
1217
+ /**
1218
+ * Get the current trace ID from context.
1219
+ */
1220
+ getTraceId() {
1221
+ const ctx = this.getLogContext();
1222
+ return ctx?.traceId ?? this.additionalContext.traceId;
1223
+ }
1224
+ /**
1225
+ * Get the current span ID from context.
1226
+ */
1227
+ getSpanId() {
1228
+ const ctx = this.getLogContext();
1229
+ return ctx?.spanId ?? this.additionalContext.spanId;
1230
+ }
1231
+ /**
1232
+ * Time an async operation and log its duration.
1233
+ */
1234
+ async time(operation, fn, data) {
1235
+ const start = Date.now();
1236
+ try {
1237
+ const result = await fn();
1238
+ const duration = Date.now() - start;
1239
+ this.info(`${operation} completed`, { ...data, duration, operation });
1240
+ return result;
1241
+ } catch (error2) {
1242
+ const duration = Date.now() - start;
1243
+ this.error(`${operation} failed`, error2, { ...data, duration, operation });
1244
+ throw error2;
1245
+ }
1246
+ }
1247
+ /**
1248
+ * Time a sync operation and log its duration.
1249
+ */
1250
+ timeSync(operation, fn, data) {
1251
+ const start = Date.now();
1252
+ try {
1253
+ const result = fn();
1254
+ const duration = Date.now() - start;
1255
+ this.info(`${operation} completed`, { ...data, duration, operation });
1256
+ return result;
1257
+ } catch (error2) {
1258
+ const duration = Date.now() - start;
1259
+ this.error(`${operation} failed`, error2, { ...data, duration, operation });
1260
+ throw error2;
1261
+ }
1262
+ }
1020
1263
  };
1021
1264
  }
1022
- /**
1023
- * Normalizes any data type to Record<string, unknown> for structured logging.
1024
- */
1025
- normalizeData(data) {
1026
- if (data === null || data === void 0) {
1027
- return void 0;
1028
- }
1029
- if (data instanceof Error) {
1030
- return {
1031
- error: data.message,
1032
- errorName: data.name,
1033
- stack: data.stack
1034
- };
1035
- }
1036
- if (typeof data === "string" || typeof data === "number" || typeof data === "boolean") {
1037
- return { value: data };
1038
- }
1039
- if (Array.isArray(data)) {
1040
- return { items: data };
1041
- }
1042
- if (typeof data === "object") {
1043
- const obj = data;
1044
- return this.shouldSanitize ? sanitize.object(obj, this.sensitiveFields) : obj;
1045
- }
1046
- return { value: String(data) };
1047
- }
1048
- log(level, message, data, errorObj) {
1049
- if (!this.shouldLog(level)) return;
1050
- const normalizedData = this.normalizeData(data);
1051
- const errorInfo = errorObj ? extractErrorInfo(errorObj, !this.isProd()) : void 0;
1052
- const entry = this.buildEntry(level, message, normalizedData, errorInfo);
1053
- const formatted = this.format === "json" ? formatJson(entry) : formatPretty(entry);
1054
- for (const transport of this.transports) {
1055
- transport.log(entry, formatted);
1056
- }
1057
- this.flush();
1058
- }
1059
- trace(message, ...args) {
1060
- this.log("trace", message, args.length === 1 ? args[0] : args.length > 1 ? args : void 0);
1061
- }
1062
- debug(message, ...args) {
1063
- this.log("debug", message, args.length === 1 ? args[0] : args.length > 1 ? args : void 0);
1064
- }
1065
- info(message, ...args) {
1066
- this.log("info", message, args.length === 1 ? args[0] : args.length > 1 ? args : void 0);
1067
- }
1068
- warn(message, ...args) {
1069
- this.log("warn", message, args.length === 1 ? args[0] : args.length > 1 ? args : void 0);
1070
- }
1071
- error(message, errorOrData, data) {
1072
- if (errorOrData instanceof Error) {
1073
- this.log("error", message, data, errorOrData);
1074
- } else {
1075
- this.log("error", message, errorOrData);
1076
- }
1077
- }
1078
- /**
1079
- * Log a fatal error (system-critical).
1080
- */
1081
- fatal(message, errorOrData, data) {
1082
- if (errorOrData instanceof Error) {
1083
- this.log("fatal", message, data, errorOrData);
1084
- } else {
1085
- this.log("fatal", message, errorOrData);
1086
- }
1087
- }
1088
- /**
1089
- * Get the current trace ID from context.
1090
- */
1091
- getTraceId() {
1092
- const ctx = this.getLogContext();
1093
- return ctx?.traceId ?? this.additionalContext.traceId;
1094
- }
1095
- /**
1096
- * Get the current span ID from context.
1097
- */
1098
- getSpanId() {
1099
- const ctx = this.getLogContext();
1100
- return ctx?.spanId ?? this.additionalContext.spanId;
1101
- }
1102
- /**
1103
- * Time an async operation and log its duration.
1104
- */
1105
- async time(operation, fn, data) {
1106
- const start = Date.now();
1107
- try {
1108
- const result = await fn();
1109
- const duration = Date.now() - start;
1110
- this.info(`${operation} completed`, { ...data, duration, operation });
1111
- return result;
1112
- } catch (error2) {
1113
- const duration = Date.now() - start;
1114
- this.error(`${operation} failed`, error2, { ...data, duration, operation });
1115
- throw error2;
1116
- }
1117
- }
1118
- /**
1119
- * Time a sync operation and log its duration.
1120
- */
1121
- timeSync(operation, fn, data) {
1122
- const start = Date.now();
1123
- try {
1124
- const result = fn();
1125
- const duration = Date.now() - start;
1126
- this.info(`${operation} completed`, { ...data, duration, operation });
1127
- return result;
1128
- } catch (error2) {
1129
- const duration = Date.now() - start;
1130
- this.error(`${operation} failed`, error2, { ...data, duration, operation });
1131
- throw error2;
1132
- }
1133
- }
1134
- };
1265
+ });
1135
1266
 
1136
1267
  // ../../packages/logger/src/transports/console.ts
1137
- var ConsoleTransport = class {
1138
- log(entry, formatted) {
1139
- if (entry.level === "error" || entry.level === "fatal") {
1140
- process.stderr.write(formatted + "\n");
1141
- } else {
1142
- process.stdout.write(formatted + "\n");
1143
- }
1268
+ var ConsoleTransport;
1269
+ var init_console = __esm({
1270
+ "../../packages/logger/src/transports/console.ts"() {
1271
+ "use strict";
1272
+ ConsoleTransport = class {
1273
+ log(entry, formatted) {
1274
+ if (entry.level === "error" || entry.level === "fatal") {
1275
+ process.stderr.write(formatted + "\n");
1276
+ } else {
1277
+ process.stdout.write(formatted + "\n");
1278
+ }
1279
+ }
1280
+ };
1144
1281
  }
1145
- };
1282
+ });
1146
1283
 
1147
1284
  // ../../packages/logger/src/transports/file.ts
1148
1285
  import { appendFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
1149
1286
  import { join } from "node:path";
1150
- var FileTransport = class {
1151
- dir;
1152
- initialized = false;
1153
- buffer = [];
1154
- constructor(options) {
1155
- this.dir = options.dir;
1156
- }
1157
- init() {
1158
- if (this.initialized) return;
1159
- if (!existsSync(this.dir)) {
1160
- mkdirSync(this.dir, { recursive: true });
1161
- }
1162
- const gitignore = join(this.dir, ".gitignore");
1163
- if (!existsSync(gitignore)) {
1164
- writeFileSync(gitignore, "*.log\n");
1165
- }
1166
- this.initialized = true;
1167
- }
1168
- log(entry, formatted) {
1169
- this.init();
1170
- const line = formatted + "\n";
1171
- this.buffer.push({ file: "combined.log", content: line });
1172
- if (entry.level === "error") {
1173
- this.buffer.push({ file: "error.log", content: line });
1174
- }
1175
- }
1176
- flush() {
1177
- for (const { file, content } of this.buffer) {
1178
- const filepath = join(this.dir, file);
1179
- appendFileSync(filepath, content);
1180
- }
1181
- this.buffer = [];
1287
+ var FileTransport;
1288
+ var init_file = __esm({
1289
+ "../../packages/logger/src/transports/file.ts"() {
1290
+ "use strict";
1291
+ FileTransport = class {
1292
+ dir;
1293
+ initialized = false;
1294
+ buffer = [];
1295
+ constructor(options) {
1296
+ this.dir = options.dir;
1297
+ }
1298
+ init() {
1299
+ if (this.initialized) return;
1300
+ if (!existsSync(this.dir)) {
1301
+ mkdirSync(this.dir, { recursive: true });
1302
+ }
1303
+ const gitignore = join(this.dir, ".gitignore");
1304
+ if (!existsSync(gitignore)) {
1305
+ writeFileSync(gitignore, "*.log\n");
1306
+ }
1307
+ this.initialized = true;
1308
+ }
1309
+ log(entry, formatted) {
1310
+ this.init();
1311
+ const line = formatted + "\n";
1312
+ this.buffer.push({ file: "combined.log", content: line });
1313
+ if (entry.level === "error") {
1314
+ this.buffer.push({ file: "error.log", content: line });
1315
+ }
1316
+ }
1317
+ flush() {
1318
+ for (const { file, content } of this.buffer) {
1319
+ const filepath = join(this.dir, file);
1320
+ appendFileSync(filepath, content);
1321
+ }
1322
+ this.buffer = [];
1323
+ }
1324
+ };
1182
1325
  }
1183
- };
1326
+ });
1184
1327
 
1185
1328
  // ../../packages/logger/src/logger.ts
1186
1329
  function detectEnvironment() {
@@ -1223,90 +1366,149 @@ function getCaller() {
1223
1366
  }
1224
1367
  return void 0;
1225
1368
  }
1226
- var Logger = class _Logger extends BaseLogger {
1227
- fileTransport;
1228
- _isProd;
1229
- constructor(options = {}) {
1230
- const { isProd, env } = detectEnvironment();
1231
- super(options, {
1232
- level: getDefaultLevel(),
1233
- format: getDefaultFormat(),
1234
- service: getDefaultService(),
1235
- env
1236
- });
1237
- this._isProd = isProd;
1238
- this.transports = [new ConsoleTransport()];
1239
- if (!isProd && !process.env.VERCEL && !process.env.RAILWAY_ENVIRONMENT) {
1240
- this.fileTransport = new FileTransport({ dir: "logs" });
1241
- this.transports.push(this.fileTransport);
1242
- }
1369
+ var Logger;
1370
+ var init_logger = __esm({
1371
+ "../../packages/logger/src/logger.ts"() {
1372
+ "use strict";
1373
+ init_types();
1374
+ init_context();
1375
+ init_logger_base();
1376
+ init_console();
1377
+ init_file();
1378
+ Logger = class _Logger extends BaseLogger {
1379
+ fileTransport;
1380
+ _isProd;
1381
+ constructor(options = {}) {
1382
+ const { isProd, env } = detectEnvironment();
1383
+ super(options, {
1384
+ level: getDefaultLevel(),
1385
+ format: getDefaultFormat(),
1386
+ service: getDefaultService(),
1387
+ env
1388
+ });
1389
+ this._isProd = isProd;
1390
+ this.transports = [new ConsoleTransport()];
1391
+ if (!isProd && !process.env.VERCEL && !process.env.RAILWAY_ENVIRONMENT) {
1392
+ this.fileTransport = new FileTransport({ dir: "logs" });
1393
+ this.transports.push(this.fileTransport);
1394
+ }
1395
+ }
1396
+ getLogContext() {
1397
+ return getLogContext();
1398
+ }
1399
+ isProd() {
1400
+ return this._isProd;
1401
+ }
1402
+ getCaller() {
1403
+ return getCaller();
1404
+ }
1405
+ flush() {
1406
+ this.fileTransport?.flush();
1407
+ }
1408
+ /**
1409
+ * Create a child logger with additional context.
1410
+ * Child shares transports with parent.
1411
+ */
1412
+ child(context) {
1413
+ const child = new _Logger({
1414
+ level: this.level,
1415
+ format: this.format,
1416
+ module: this.module,
1417
+ service: this.service,
1418
+ environment: this.environment,
1419
+ sanitize: this.shouldSanitize,
1420
+ sensitiveFields: this.sensitiveFields,
1421
+ includeCaller: this.includeCaller
1422
+ });
1423
+ child.additionalContext = { ...this.additionalContext, ...context };
1424
+ child.transports = this.transports;
1425
+ child.fileTransport = this.fileTransport;
1426
+ return child;
1427
+ }
1428
+ };
1243
1429
  }
1244
- getLogContext() {
1245
- return getLogContext();
1246
- }
1247
- isProd() {
1248
- return this._isProd;
1249
- }
1250
- getCaller() {
1251
- return getCaller();
1252
- }
1253
- flush() {
1254
- this.fileTransport?.flush();
1255
- }
1256
- /**
1257
- * Create a child logger with additional context.
1258
- * Child shares transports with parent.
1259
- */
1260
- child(context) {
1261
- const child = new _Logger({
1262
- level: this.level,
1263
- format: this.format,
1264
- module: this.module,
1265
- service: this.service,
1266
- environment: this.environment,
1267
- sanitize: this.shouldSanitize,
1268
- sensitiveFields: this.sensitiveFields,
1269
- includeCaller: this.includeCaller
1270
- });
1271
- child.additionalContext = { ...this.additionalContext, ...context };
1272
- child.transports = this.transports;
1273
- child.fileTransport = this.fileTransport;
1274
- return child;
1430
+ });
1431
+
1432
+ // ../../packages/logger/src/middleware/trpc.ts
1433
+ var init_trpc = __esm({
1434
+ "../../packages/logger/src/middleware/trpc.ts"() {
1435
+ "use strict";
1436
+ init_context();
1437
+ init_logger();
1275
1438
  }
1276
- };
1439
+ });
1440
+
1441
+ // ../../packages/logger/src/middleware/index.ts
1442
+ var init_middleware = __esm({
1443
+ "../../packages/logger/src/middleware/index.ts"() {
1444
+ "use strict";
1445
+ init_trpc();
1446
+ }
1447
+ });
1277
1448
 
1278
1449
  // ../../packages/logger/src/index.ts
1279
- var logger = new Logger();
1280
1450
  function createLogger(module, options) {
1281
1451
  return new Logger({ ...options, module });
1282
1452
  }
1453
+ var logger;
1454
+ var init_src = __esm({
1455
+ "../../packages/logger/src/index.ts"() {
1456
+ "use strict";
1457
+ init_logger();
1458
+ init_types();
1459
+ init_context();
1460
+ init_context();
1461
+ init_context();
1462
+ init_sanitize();
1463
+ init_middleware();
1464
+ logger = new Logger();
1465
+ }
1466
+ });
1283
1467
 
1284
1468
  // ../../packages/tostudy-core/src/courses/list-courses.ts
1285
1469
  async function listCourses(input, deps) {
1286
1470
  deps.logger.info("tostudy-core: listCourses", { userId: input.userId });
1287
1471
  return deps.data.courses.list(input.userId);
1288
1472
  }
1473
+ var init_list_courses = __esm({
1474
+ "../../packages/tostudy-core/src/courses/list-courses.ts"() {
1475
+ "use strict";
1476
+ }
1477
+ });
1289
1478
 
1290
1479
  // ../../packages/tostudy-core/src/courses/select-course.ts
1291
1480
  async function selectCourse(input, deps) {
1292
1481
  deps.logger.info("tostudy-core: selectCourse", input);
1293
1482
  return deps.data.courses.select(input.userId, input.courseId);
1294
1483
  }
1484
+ var init_select_course = __esm({
1485
+ "../../packages/tostudy-core/src/courses/select-course.ts"() {
1486
+ "use strict";
1487
+ }
1488
+ });
1295
1489
 
1296
1490
  // ../../packages/tostudy-core/src/courses/get-progress.ts
1297
1491
  async function getProgress(input, deps) {
1298
1492
  deps.logger.info("tostudy-core: getProgress", input);
1299
1493
  return deps.data.courses.getProgress(input.enrollmentId);
1300
1494
  }
1495
+ var init_get_progress = __esm({
1496
+ "../../packages/tostudy-core/src/courses/get-progress.ts"() {
1497
+ "use strict";
1498
+ }
1499
+ });
1301
1500
 
1302
- // ../../packages/tostudy-core/src/adapters/http.ts
1303
- var CliApiError = class extends Error {
1304
- constructor(message, status) {
1305
- super(message);
1306
- this.status = status;
1307
- this.name = "CliApiError";
1501
+ // ../../packages/tostudy-core/src/courses/index.ts
1502
+ var init_courses = __esm({
1503
+ "../../packages/tostudy-core/src/courses/index.ts"() {
1504
+ "use strict";
1505
+ init_list_courses();
1506
+ init_select_course();
1507
+ init_get_progress();
1308
1508
  }
1309
- };
1509
+ });
1510
+
1511
+ // ../../packages/tostudy-core/src/adapters/http.ts
1310
1512
  async function apiFetch(url, token2, init) {
1311
1513
  const response = await fetch(url, {
1312
1514
  ...init,
@@ -1382,200 +1584,314 @@ function createHttpProvider(apiUrl, token2) {
1382
1584
  }
1383
1585
  };
1384
1586
  }
1587
+ var CliApiError;
1588
+ var init_http = __esm({
1589
+ "../../packages/tostudy-core/src/adapters/http.ts"() {
1590
+ "use strict";
1591
+ CliApiError = class extends Error {
1592
+ constructor(message, status) {
1593
+ super(message);
1594
+ this.status = status;
1595
+ this.name = "CliApiError";
1596
+ }
1597
+ };
1598
+ }
1599
+ });
1385
1600
 
1386
1601
  // src/commands/courses.ts
1387
- var logger2 = createLogger("cli:courses");
1388
- var coursesCommand = new Command5("courses").description("List your enrolled courses with progress").option("--json", "Output structured JSON").action(async (opts) => {
1389
- try {
1390
- const session = await requireSession();
1391
- const data = createHttpProvider(session.apiUrl, session.token);
1392
- const deps = { data, logger: logger2 };
1393
- const courses = await listCourses({ userId: session.userId }, deps);
1394
- if (opts.json) {
1395
- output(courses, { json: true });
1396
- } else {
1397
- output(formatCourseList(courses), { json: false });
1398
- }
1399
- } catch (err) {
1400
- const msg = err instanceof Error ? err.message : String(err);
1401
- error(msg);
1602
+ import { Command as Command5 } from "commander";
1603
+ var logger2, coursesCommand;
1604
+ var init_courses2 = __esm({
1605
+ "src/commands/courses.ts"() {
1606
+ "use strict";
1607
+ init_src();
1608
+ init_courses();
1609
+ init_http();
1610
+ init_session();
1611
+ init_formatter();
1612
+ logger2 = createLogger("cli:courses");
1613
+ coursesCommand = new Command5("courses").description("List your enrolled courses with progress").option("--json", "Output structured JSON").action(async (opts) => {
1614
+ try {
1615
+ const session = await requireSession();
1616
+ const data = createHttpProvider(session.apiUrl, session.token);
1617
+ const deps = { data, logger: logger2 };
1618
+ const courses = await listCourses({ userId: session.userId }, deps);
1619
+ if (opts.json) {
1620
+ output(courses, { json: true });
1621
+ } else {
1622
+ output(formatCourseList(courses), { json: false });
1623
+ }
1624
+ } catch (err) {
1625
+ const msg = err instanceof Error ? err.message : String(err);
1626
+ error(msg);
1627
+ }
1628
+ });
1402
1629
  }
1403
1630
  });
1404
1631
 
1405
1632
  // src/commands/select.ts
1406
1633
  import { Command as Command6 } from "commander";
1407
- var logger3 = createLogger("cli:select");
1408
- var selectCommand = new Command6("select").description("Activate a course by ID or list index number").argument("<course>", "Course ID (UUID) or index number from `tostudy courses`").option("--json", "Output structured JSON").action(async (course, opts) => {
1409
- try {
1410
- const session = await requireSession();
1411
- const data = createHttpProvider(session.apiUrl, session.token);
1412
- const deps = { data, logger: logger3 };
1413
- const courses = await listCourses({ userId: session.userId }, deps);
1414
- let courseId = course;
1415
- let enrollmentId = "";
1416
- if (/^\d+$/.test(course)) {
1417
- const idx = parseInt(course, 10) - 1;
1418
- if (idx < 0 || idx >= courses.length) {
1419
- error(`\xCDndice ${course} inv\xE1lido. Voc\xEA tem ${courses.length} curso(s).`);
1420
- }
1421
- const found = courses[idx];
1422
- courseId = found.courseId;
1423
- enrollmentId = found.enrollmentId;
1424
- } else {
1425
- const found = courses.find((c) => c.courseId === course);
1426
- if (found) {
1427
- enrollmentId = found.enrollmentId;
1634
+ var logger3, selectCommand;
1635
+ var init_select = __esm({
1636
+ "src/commands/select.ts"() {
1637
+ "use strict";
1638
+ init_src();
1639
+ init_courses();
1640
+ init_http();
1641
+ init_session();
1642
+ init_formatter();
1643
+ logger3 = createLogger("cli:select");
1644
+ selectCommand = new Command6("select").description("Activate a course by ID or list index number").argument("<course>", "Course ID (UUID) or index number from `tostudy courses`").option("--json", "Output structured JSON").action(async (course, opts) => {
1645
+ try {
1646
+ const session = await requireSession();
1647
+ const data = createHttpProvider(session.apiUrl, session.token);
1648
+ const deps = { data, logger: logger3 };
1649
+ const courses = await listCourses({ userId: session.userId }, deps);
1650
+ let courseId = course;
1651
+ let enrollmentId = "";
1652
+ if (/^\d+$/.test(course)) {
1653
+ const idx = parseInt(course, 10) - 1;
1654
+ if (idx < 0 || idx >= courses.length) {
1655
+ error(`\xCDndice ${course} inv\xE1lido. Voc\xEA tem ${courses.length} curso(s).`);
1656
+ }
1657
+ const found = courses[idx];
1658
+ courseId = found.courseId;
1659
+ enrollmentId = found.enrollmentId;
1660
+ } else {
1661
+ const found = courses.find((c) => c.courseId === course);
1662
+ if (found) {
1663
+ enrollmentId = found.enrollmentId;
1664
+ }
1665
+ }
1666
+ const detail = await selectCourse({ userId: session.userId, courseId }, deps);
1667
+ await setActiveCourse({
1668
+ courseId: detail.courseId,
1669
+ courseTitle: detail.courseTitle,
1670
+ enrollmentId
1671
+ });
1672
+ if (opts.json) {
1673
+ output({ ...detail, enrollmentId }, { json: true });
1674
+ } else {
1675
+ output(
1676
+ [
1677
+ `\u2713 Curso ativado: ${detail.courseTitle}`,
1678
+ ` Progresso: ${detail.progress}% | ${detail.moduleCount} m\xF3dulos | ${detail.lessonCount} li\xE7\xF5es`,
1679
+ "",
1680
+ "\u2192 tostudy progress para ver seu progresso detalhado",
1681
+ "\u2192 tostudy start para come\xE7ar o m\xF3dulo atual",
1682
+ "\u2192 tostudy next para avan\xE7ar para a pr\xF3xima li\xE7\xE3o"
1683
+ ].join("\n"),
1684
+ { json: false }
1685
+ );
1686
+ }
1687
+ } catch (err) {
1688
+ const msg = err instanceof Error ? err.message : String(err);
1689
+ error(msg);
1428
1690
  }
1429
- }
1430
- const detail = await selectCourse({ userId: session.userId, courseId }, deps);
1431
- await setActiveCourse({
1432
- courseId: detail.courseId,
1433
- courseTitle: detail.courseTitle,
1434
- enrollmentId
1435
1691
  });
1436
- if (opts.json) {
1437
- output({ ...detail, enrollmentId }, { json: true });
1438
- } else {
1439
- output(
1440
- [
1441
- `\u2713 Curso ativado: ${detail.courseTitle}`,
1442
- ` Progresso: ${detail.progress}% | ${detail.moduleCount} m\xF3dulos | ${detail.lessonCount} li\xE7\xF5es`,
1443
- "",
1444
- "\u2192 tostudy progress para ver seu progresso detalhado",
1445
- "\u2192 tostudy start para come\xE7ar o m\xF3dulo atual",
1446
- "\u2192 tostudy next para avan\xE7ar para a pr\xF3xima li\xE7\xE3o"
1447
- ].join("\n"),
1448
- { json: false }
1449
- );
1450
- }
1451
- } catch (err) {
1452
- const msg = err instanceof Error ? err.message : String(err);
1453
- error(msg);
1454
1692
  }
1455
1693
  });
1456
1694
 
1457
1695
  // src/commands/progress.ts
1458
1696
  import { Command as Command7 } from "commander";
1459
- var logger4 = createLogger("cli:progress");
1460
- var progressCommand = new Command7("progress").description("Show your progress in the active course").option("--json", "Output structured JSON").action(async (opts) => {
1461
- try {
1462
- const session = await requireSession();
1463
- const activeCourse = await requireActiveCourse();
1464
- const data = createHttpProvider(session.apiUrl, session.token);
1465
- const deps = { data, logger: logger4 };
1466
- const progress = await getProgress({ enrollmentId: activeCourse.enrollmentId }, deps);
1467
- if (opts.json) {
1468
- output(progress, { json: true });
1469
- } else {
1470
- output(formatProgress(progress), { json: false });
1471
- }
1472
- } catch (err) {
1473
- const msg = err instanceof Error ? err.message : String(err);
1474
- error(msg);
1697
+ var logger4, progressCommand;
1698
+ var init_progress = __esm({
1699
+ "src/commands/progress.ts"() {
1700
+ "use strict";
1701
+ init_src();
1702
+ init_courses();
1703
+ init_http();
1704
+ init_session();
1705
+ init_formatter();
1706
+ logger4 = createLogger("cli:progress");
1707
+ progressCommand = new Command7("progress").description("Show your progress in the active course").option("--json", "Output structured JSON").action(async (opts) => {
1708
+ try {
1709
+ const session = await requireSession();
1710
+ const activeCourse = await requireActiveCourse();
1711
+ const data = createHttpProvider(session.apiUrl, session.token);
1712
+ const deps = { data, logger: logger4 };
1713
+ const progress = await getProgress({ enrollmentId: activeCourse.enrollmentId }, deps);
1714
+ if (opts.json) {
1715
+ output(progress, { json: true });
1716
+ } else {
1717
+ output(formatProgress(progress), { json: false });
1718
+ }
1719
+ } catch (err) {
1720
+ const msg = err instanceof Error ? err.message : String(err);
1721
+ error(msg);
1722
+ }
1723
+ });
1475
1724
  }
1476
1725
  });
1477
1726
 
1478
- // src/commands/start.ts
1479
- import { Command as Command8 } from "commander";
1480
-
1481
1727
  // ../../packages/tostudy-core/src/lessons/next-lesson.ts
1482
1728
  async function nextLesson(input, deps) {
1483
1729
  deps.logger.info("tostudy-core: nextLesson", { enrollmentId: input.enrollmentId });
1484
1730
  return deps.data.lessons.next(input.enrollmentId, input.userConfirmation);
1485
1731
  }
1732
+ var init_next_lesson = __esm({
1733
+ "../../packages/tostudy-core/src/lessons/next-lesson.ts"() {
1734
+ "use strict";
1735
+ }
1736
+ });
1486
1737
 
1487
1738
  // ../../packages/tostudy-core/src/lessons/get-content.ts
1488
1739
  async function getContent(input, deps) {
1489
1740
  deps.logger.info("tostudy-core: getContent", { lessonId: input.lessonId });
1490
1741
  return deps.data.lessons.getContent(input.lessonId, input.enrollmentId);
1491
1742
  }
1743
+ var init_get_content = __esm({
1744
+ "../../packages/tostudy-core/src/lessons/get-content.ts"() {
1745
+ "use strict";
1746
+ }
1747
+ });
1492
1748
 
1493
1749
  // ../../packages/tostudy-core/src/lessons/get-hint.ts
1494
1750
  async function getHint(input, deps) {
1495
1751
  deps.logger.info("tostudy-core: getHint", { userId: input.userId });
1496
1752
  return deps.data.lessons.getHint(input.userId, input.enrollmentId);
1497
1753
  }
1754
+ var init_get_hint = __esm({
1755
+ "../../packages/tostudy-core/src/lessons/get-hint.ts"() {
1756
+ "use strict";
1757
+ }
1758
+ });
1498
1759
 
1499
1760
  // ../../packages/tostudy-core/src/lessons/start-module.ts
1500
1761
  async function startModule(input, deps) {
1501
1762
  deps.logger.info("tostudy-core: startModule", { enrollmentId: input.enrollmentId });
1502
1763
  return deps.data.lessons.startModule(input.enrollmentId);
1503
1764
  }
1765
+ var init_start_module = __esm({
1766
+ "../../packages/tostudy-core/src/lessons/start-module.ts"() {
1767
+ "use strict";
1768
+ }
1769
+ });
1504
1770
 
1505
1771
  // ../../packages/tostudy-core/src/lessons/start-next-module.ts
1506
1772
  async function startNextModule(input, deps) {
1507
1773
  deps.logger.info("tostudy-core: startNextModule", { enrollmentId: input.enrollmentId });
1508
1774
  return deps.data.lessons.startNextModule(input.enrollmentId);
1509
1775
  }
1776
+ var init_start_next_module = __esm({
1777
+ "../../packages/tostudy-core/src/lessons/start-next-module.ts"() {
1778
+ "use strict";
1779
+ }
1780
+ });
1781
+
1782
+ // ../../packages/tostudy-core/src/lessons/index.ts
1783
+ var init_lessons = __esm({
1784
+ "../../packages/tostudy-core/src/lessons/index.ts"() {
1785
+ "use strict";
1786
+ init_next_lesson();
1787
+ init_get_content();
1788
+ init_get_hint();
1789
+ init_start_module();
1790
+ init_start_next_module();
1791
+ }
1792
+ });
1510
1793
 
1511
1794
  // src/commands/start.ts
1512
- var logger5 = createLogger("cli:start");
1513
- var startCommand = new Command8("start").description("Start (or resume) the current module of the active course").option("--json", "Output structured JSON").action(async (opts) => {
1514
- try {
1515
- const session = await requireSession();
1516
- const activeCourse = await requireActiveCourse();
1517
- const data = createHttpProvider(session.apiUrl, session.token);
1518
- const deps = { data, logger: logger5 };
1519
- const moduleData = await startModule({ enrollmentId: activeCourse.enrollmentId }, deps);
1520
- if (opts.json) {
1521
- output(moduleData, { json: true });
1522
- } else {
1523
- output(formatModuleStart(moduleData), { json: false });
1524
- }
1525
- } catch (err) {
1526
- const msg = err instanceof Error ? err.message : String(err);
1527
- error(msg);
1795
+ import { Command as Command8 } from "commander";
1796
+ var logger5, startCommand;
1797
+ var init_start = __esm({
1798
+ "src/commands/start.ts"() {
1799
+ "use strict";
1800
+ init_src();
1801
+ init_lessons();
1802
+ init_http();
1803
+ init_session();
1804
+ init_formatter();
1805
+ logger5 = createLogger("cli:start");
1806
+ startCommand = new Command8("start").description("Start (or resume) the current module of the active course").option("--json", "Output structured JSON").action(async (opts) => {
1807
+ try {
1808
+ const session = await requireSession();
1809
+ const activeCourse = await requireActiveCourse();
1810
+ const data = createHttpProvider(session.apiUrl, session.token);
1811
+ const deps = { data, logger: logger5 };
1812
+ const moduleData = await startModule({ enrollmentId: activeCourse.enrollmentId }, deps);
1813
+ if (opts.json) {
1814
+ output(moduleData, { json: true });
1815
+ } else {
1816
+ output(formatModuleStart(moduleData), { json: false });
1817
+ }
1818
+ } catch (err) {
1819
+ const msg = err instanceof Error ? err.message : String(err);
1820
+ error(msg);
1821
+ }
1822
+ });
1528
1823
  }
1529
1824
  });
1530
1825
 
1531
1826
  // src/commands/start-next.ts
1532
1827
  import { Command as Command9 } from "commander";
1533
- var logger6 = createLogger("cli:start-next");
1534
- var startNextCommand = new Command9("start-next").description("Transition to the next module after completing the current one").option("--json", "Output structured JSON").action(async (opts) => {
1535
- try {
1536
- const session = await requireSession();
1537
- const activeCourse = await requireActiveCourse();
1538
- const data = createHttpProvider(session.apiUrl, session.token);
1539
- const deps = { data, logger: logger6 };
1540
- const moduleData = await startNextModule({ enrollmentId: activeCourse.enrollmentId }, deps);
1541
- if (opts.json) {
1542
- output(moduleData, { json: true });
1543
- } else {
1544
- output(formatModuleStart(moduleData), { json: false });
1545
- }
1546
- } catch (err) {
1547
- const msg = err instanceof Error ? err.message : String(err);
1548
- error(msg);
1828
+ var logger6, startNextCommand;
1829
+ var init_start_next = __esm({
1830
+ "src/commands/start-next.ts"() {
1831
+ "use strict";
1832
+ init_src();
1833
+ init_lessons();
1834
+ init_http();
1835
+ init_session();
1836
+ init_formatter();
1837
+ logger6 = createLogger("cli:start-next");
1838
+ startNextCommand = new Command9("start-next").description("Transition to the next module after completing the current one").option("--json", "Output structured JSON").action(async (opts) => {
1839
+ try {
1840
+ const session = await requireSession();
1841
+ const activeCourse = await requireActiveCourse();
1842
+ const data = createHttpProvider(session.apiUrl, session.token);
1843
+ const deps = { data, logger: logger6 };
1844
+ const moduleData = await startNextModule({ enrollmentId: activeCourse.enrollmentId }, deps);
1845
+ if (opts.json) {
1846
+ output(moduleData, { json: true });
1847
+ } else {
1848
+ output(formatModuleStart(moduleData), { json: false });
1849
+ }
1850
+ } catch (err) {
1851
+ const msg = err instanceof Error ? err.message : String(err);
1852
+ error(msg);
1853
+ }
1854
+ });
1549
1855
  }
1550
1856
  });
1551
1857
 
1552
1858
  // src/commands/next.ts
1553
1859
  import { Command as Command10 } from "commander";
1554
- var logger7 = createLogger("cli:next");
1555
- var nextCommand = new Command10("next").description("Advance to the next lesson in the active course").option("--json", "Output structured JSON").action(async (opts) => {
1556
- try {
1557
- const session = await requireSession();
1558
- const activeCourse = await requireActiveCourse();
1559
- const data = createHttpProvider(session.apiUrl, session.token);
1560
- const deps = { data, logger: logger7 };
1561
- const lessonData = await nextLesson(
1562
- { enrollmentId: activeCourse.enrollmentId, userConfirmation: "cli-next" },
1563
- deps
1564
- );
1565
- if (opts.json) {
1566
- output(lessonData, { json: true });
1567
- } else {
1568
- output(formatLesson(lessonData), { json: false });
1569
- }
1570
- } catch (err) {
1571
- const msg = err instanceof Error ? err.message : String(err);
1572
- error(msg);
1860
+ var logger7, nextCommand;
1861
+ var init_next = __esm({
1862
+ "src/commands/next.ts"() {
1863
+ "use strict";
1864
+ init_src();
1865
+ init_lessons();
1866
+ init_http();
1867
+ init_session();
1868
+ init_formatter();
1869
+ logger7 = createLogger("cli:next");
1870
+ nextCommand = new Command10("next").description("Advance to the next lesson in the active course").option("--json", "Output structured JSON").action(async (opts) => {
1871
+ try {
1872
+ const session = await requireSession();
1873
+ const activeCourse = await requireActiveCourse();
1874
+ const data = createHttpProvider(session.apiUrl, session.token);
1875
+ const deps = { data, logger: logger7 };
1876
+ const lessonData = await nextLesson(
1877
+ { enrollmentId: activeCourse.enrollmentId, userConfirmation: "cli-next" },
1878
+ deps
1879
+ );
1880
+ if (opts.json) {
1881
+ output(lessonData, { json: true });
1882
+ } else {
1883
+ output(formatLesson(lessonData), { json: false });
1884
+ }
1885
+ } catch (err) {
1886
+ const msg = err instanceof Error ? err.message : String(err);
1887
+ error(msg);
1888
+ }
1889
+ });
1573
1890
  }
1574
1891
  });
1575
1892
 
1576
1893
  // src/commands/lesson.ts
1577
1894
  import { Command as Command11 } from "commander";
1578
- var logger8 = createLogger("cli:lesson");
1579
1895
  function formatLessonContent(data) {
1580
1896
  const lines = [
1581
1897
  `\u2501\u2501\u2501 Li\xE7\xE3o: ${data.title} \u2501\u2501\u2501`,
@@ -1598,56 +1914,75 @@ function formatLessonContent(data) {
1598
1914
  );
1599
1915
  return lines.join("\n");
1600
1916
  }
1601
- var lessonCommand = new Command11("lesson").description("Show the content of the current lesson").option("--json", "Output structured JSON").action(async (opts) => {
1602
- try {
1603
- const session = await requireSession();
1604
- const activeCourse = await requireActiveCourse();
1605
- const data = createHttpProvider(session.apiUrl, session.token);
1606
- const deps = { data, logger: logger8 };
1607
- const lessonId = activeCourse.currentLessonId;
1608
- if (!lessonId) {
1609
- error("Nenhuma li\xE7\xE3o ativa encontrada. Rode: tostudy start ou tostudy next");
1610
- }
1611
- const content = await getContent({ lessonId, enrollmentId: activeCourse.enrollmentId }, deps);
1612
- if (opts.json) {
1613
- output(content, { json: true });
1614
- } else {
1615
- output(formatLessonContent(content), { json: false });
1616
- }
1617
- } catch (err) {
1618
- const msg = err instanceof Error ? err.message : String(err);
1619
- error(msg);
1917
+ var logger8, lessonCommand;
1918
+ var init_lesson = __esm({
1919
+ "src/commands/lesson.ts"() {
1920
+ "use strict";
1921
+ init_src();
1922
+ init_lessons();
1923
+ init_http();
1924
+ init_session();
1925
+ init_formatter();
1926
+ logger8 = createLogger("cli:lesson");
1927
+ lessonCommand = new Command11("lesson").description("Show the content of the current lesson").option("--json", "Output structured JSON").action(async (opts) => {
1928
+ try {
1929
+ const session = await requireSession();
1930
+ const activeCourse = await requireActiveCourse();
1931
+ const data = createHttpProvider(session.apiUrl, session.token);
1932
+ const deps = { data, logger: logger8 };
1933
+ const lessonId = activeCourse.currentLessonId;
1934
+ if (!lessonId) {
1935
+ error("Nenhuma li\xE7\xE3o ativa encontrada. Rode: tostudy start ou tostudy next");
1936
+ }
1937
+ const content = await getContent({ lessonId, enrollmentId: activeCourse.enrollmentId }, deps);
1938
+ if (opts.json) {
1939
+ output(content, { json: true });
1940
+ } else {
1941
+ output(formatLessonContent(content), { json: false });
1942
+ }
1943
+ } catch (err) {
1944
+ const msg = err instanceof Error ? err.message : String(err);
1945
+ error(msg);
1946
+ }
1947
+ });
1620
1948
  }
1621
1949
  });
1622
1950
 
1623
1951
  // src/commands/hint.ts
1624
1952
  import { Command as Command12 } from "commander";
1625
- var logger9 = createLogger("cli:hint");
1626
- var hintCommand = new Command12("hint").description("Get a progressive hint for the current exercise").option("--json", "Output structured JSON").action(async (opts) => {
1627
- try {
1628
- const session = await requireSession();
1629
- const activeCourse = await requireActiveCourse();
1630
- const data = createHttpProvider(session.apiUrl, session.token);
1631
- const deps = { data, logger: logger9 };
1632
- const hint = await getHint(
1633
- { userId: session.userId, enrollmentId: activeCourse.enrollmentId },
1634
- deps
1635
- );
1636
- if (opts.json) {
1637
- output(hint, { json: true });
1638
- } else {
1639
- output(formatHint(hint), { json: false });
1640
- }
1641
- } catch (err) {
1642
- const msg = err instanceof Error ? err.message : String(err);
1643
- error(msg);
1953
+ var logger9, hintCommand;
1954
+ var init_hint = __esm({
1955
+ "src/commands/hint.ts"() {
1956
+ "use strict";
1957
+ init_src();
1958
+ init_lessons();
1959
+ init_http();
1960
+ init_session();
1961
+ init_formatter();
1962
+ logger9 = createLogger("cli:hint");
1963
+ hintCommand = new Command12("hint").description("Get a progressive hint for the current exercise").option("--json", "Output structured JSON").action(async (opts) => {
1964
+ try {
1965
+ const session = await requireSession();
1966
+ const activeCourse = await requireActiveCourse();
1967
+ const data = createHttpProvider(session.apiUrl, session.token);
1968
+ const deps = { data, logger: logger9 };
1969
+ const hint = await getHint(
1970
+ { userId: session.userId, enrollmentId: activeCourse.enrollmentId },
1971
+ deps
1972
+ );
1973
+ if (opts.json) {
1974
+ output(hint, { json: true });
1975
+ } else {
1976
+ output(formatHint(hint), { json: false });
1977
+ }
1978
+ } catch (err) {
1979
+ const msg = err instanceof Error ? err.message : String(err);
1980
+ error(msg);
1981
+ }
1982
+ });
1644
1983
  }
1645
1984
  });
1646
1985
 
1647
- // src/commands/validate.ts
1648
- import fs3 from "node:fs";
1649
- import { Command as Command13 } from "commander";
1650
-
1651
1986
  // ../../packages/tostudy-core/src/exercises/validate-solution.ts
1652
1987
  async function validateSolution(input, deps) {
1653
1988
  deps.logger.info("tostudy-core: validateSolution", { lessonId: input.lessonId });
@@ -1658,111 +1993,150 @@ async function validateSolution(input, deps) {
1658
1993
  input.enrollmentId
1659
1994
  );
1660
1995
  }
1996
+ var init_validate_solution = __esm({
1997
+ "../../packages/tostudy-core/src/exercises/validate-solution.ts"() {
1998
+ "use strict";
1999
+ }
2000
+ });
2001
+
2002
+ // ../../packages/tostudy-core/src/exercises/index.ts
2003
+ var init_exercises = __esm({
2004
+ "../../packages/tostudy-core/src/exercises/index.ts"() {
2005
+ "use strict";
2006
+ init_validate_solution();
2007
+ }
2008
+ });
1661
2009
 
1662
2010
  // src/commands/validate.ts
1663
- var logger10 = createLogger("cli:validate");
1664
- var validateCommand = new Command13("validate").description("Validate your solution for the current exercise").argument("[file]", "Path to the solution file to read").option("--stdin", "Read solution from stdin instead of a file").option("--json", "Output structured JSON").action(async (file, opts) => {
1665
- try {
1666
- const session = await requireSession();
1667
- const activeCourse = await requireActiveCourse();
1668
- const lessonId = activeCourse.currentLessonId;
1669
- if (!lessonId) {
1670
- error("Nenhuma li\xE7\xE3o ativa encontrada. Rode: tostudy start ou tostudy next");
1671
- }
1672
- let solution;
1673
- if (opts.stdin) {
1674
- solution = fs3.readFileSync("/dev/stdin", "utf-8");
1675
- } else if (file) {
1676
- if (!fs3.existsSync(file)) {
1677
- error(`Arquivo n\xE3o encontrado: ${file}`);
2011
+ import fs3 from "node:fs";
2012
+ import { Command as Command13 } from "commander";
2013
+ var logger10, validateCommand;
2014
+ var init_validate = __esm({
2015
+ "src/commands/validate.ts"() {
2016
+ "use strict";
2017
+ init_src();
2018
+ init_exercises();
2019
+ init_http();
2020
+ init_session();
2021
+ init_formatter();
2022
+ logger10 = createLogger("cli:validate");
2023
+ validateCommand = new Command13("validate").description("Validate your solution for the current exercise").argument("[file]", "Path to the solution file to read").option("--stdin", "Read solution from stdin instead of a file").option("--json", "Output structured JSON").action(async (file, opts) => {
2024
+ try {
2025
+ const session = await requireSession();
2026
+ const activeCourse = await requireActiveCourse();
2027
+ const lessonId = activeCourse.currentLessonId;
2028
+ if (!lessonId) {
2029
+ error("Nenhuma li\xE7\xE3o ativa encontrada. Rode: tostudy start ou tostudy next");
2030
+ }
2031
+ let solution;
2032
+ if (opts.stdin) {
2033
+ solution = fs3.readFileSync("/dev/stdin", "utf-8");
2034
+ } else if (file) {
2035
+ if (!fs3.existsSync(file)) {
2036
+ error(`Arquivo n\xE3o encontrado: ${file}`);
2037
+ }
2038
+ solution = fs3.readFileSync(file, "utf-8");
2039
+ } else {
2040
+ error("Forne\xE7a um arquivo ou use --stdin.\n\nExemplo: tostudy validate resposta.md");
2041
+ }
2042
+ const data = createHttpProvider(session.apiUrl, session.token);
2043
+ const deps = { data, logger: logger10 };
2044
+ const result = await validateSolution(
2045
+ {
2046
+ lessonId,
2047
+ solution,
2048
+ userId: session.userId,
2049
+ enrollmentId: activeCourse.enrollmentId
2050
+ },
2051
+ deps
2052
+ );
2053
+ if (opts.json) {
2054
+ output(result, { json: true });
2055
+ } else {
2056
+ output(formatValidation(result), { json: false });
2057
+ }
2058
+ process.exit(result.passed ? 0 : 1);
2059
+ } catch (err) {
2060
+ const msg = err instanceof Error ? err.message : String(err);
2061
+ error(msg);
1678
2062
  }
1679
- solution = fs3.readFileSync(file, "utf-8");
1680
- } else {
1681
- error("Forne\xE7a um arquivo ou use --stdin.\n\nExemplo: tostudy validate resposta.md");
1682
- }
1683
- const data = createHttpProvider(session.apiUrl, session.token);
1684
- const deps = { data, logger: logger10 };
1685
- const result = await validateSolution(
1686
- {
1687
- lessonId,
1688
- solution,
1689
- userId: session.userId,
1690
- enrollmentId: activeCourse.enrollmentId
1691
- },
1692
- deps
1693
- );
1694
- if (opts.json) {
1695
- output(result, { json: true });
1696
- } else {
1697
- output(formatValidation(result), { json: false });
1698
- }
1699
- process.exit(result.passed ? 0 : 1);
1700
- } catch (err) {
1701
- const msg = err instanceof Error ? err.message : String(err);
1702
- error(msg);
2063
+ });
1703
2064
  }
1704
2065
  });
1705
2066
 
1706
2067
  // src/commands/menu.ts
1707
2068
  import { Command as Command14 } from "commander";
1708
- var menuCommand = new Command14("menu").description("Show available commands and current study context").action(async () => {
1709
- const session = await getSession();
1710
- const activeCourse = session ? await getActiveCourse() : null;
1711
- const lines = [
1712
- "\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
1713
- "\u2502 ToStudy CLI \u2014 Menu \u2502",
1714
- "\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
1715
- ""
1716
- ];
1717
- if (!session) {
1718
- lines.push(
1719
- " Status: N\xE3o autenticado",
1720
- "",
1721
- " Para come\xE7ar:",
1722
- " tostudy login Autenticar com sua conta ToStudy",
1723
- ""
1724
- );
1725
- } else {
1726
- lines.push(` Usu\xE1rio: ${session.userName}`);
1727
- if (activeCourse) {
1728
- lines.push(` Curso ativo: ${activeCourse.courseTitle}`, "");
1729
- } else {
1730
- lines.push(
1731
- " Curso ativo: (nenhum)",
1732
- " \u2192 tostudy courses para ver seus cursos",
1733
- " \u2192 tostudy select <n\xFAmero> para ativar um curso",
2069
+ var menuCommand;
2070
+ var init_menu = __esm({
2071
+ "src/commands/menu.ts"() {
2072
+ "use strict";
2073
+ init_session();
2074
+ init_formatter();
2075
+ menuCommand = new Command14("menu").description("Show available commands and current study context").action(async () => {
2076
+ const session = await getSession();
2077
+ const activeCourse = session ? await getActiveCourse() : null;
2078
+ const lines = [
2079
+ "\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
2080
+ "\u2502 ToStudy CLI \u2014 Menu \u2502",
2081
+ "\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
1734
2082
  ""
1735
- );
1736
- }
1737
- lines.push(
1738
- " \u2500\u2500\u2500 Navega\xE7\xE3o \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
1739
- " tostudy courses Listar seus cursos",
1740
- " tostudy select <id> Ativar um curso",
1741
- " tostudy progress Ver progresso do curso ativo",
1742
- "",
1743
- " \u2500\u2500\u2500 Estudo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
1744
- " tostudy start Iniciar/retomar o m\xF3dulo atual",
1745
- " tostudy start-next Avan\xE7ar para o pr\xF3ximo m\xF3dulo",
1746
- " tostudy next Avan\xE7ar para a pr\xF3xima li\xE7\xE3o",
1747
- " tostudy lesson Ver conte\xFAdo da li\xE7\xE3o atual",
1748
- "",
1749
- " \u2500\u2500\u2500 Exerc\xEDcios \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
1750
- " tostudy validate <arquivo> Validar sua solu\xE7\xE3o",
1751
- " tostudy hint Obter uma dica progressiva",
1752
- "",
1753
- " \u2500\u2500\u2500 Dicas r\xE1pidas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
1754
- " Adicione --json a qualquer comando para sa\xEDda em JSON",
1755
- " Adicione --help a qualquer comando para ver op\xE7\xF5es",
1756
- ""
1757
- );
2083
+ ];
2084
+ if (!session) {
2085
+ lines.push(
2086
+ " Status: N\xE3o autenticado",
2087
+ "",
2088
+ " Para come\xE7ar:",
2089
+ " tostudy login Autenticar com sua conta ToStudy",
2090
+ ""
2091
+ );
2092
+ } else {
2093
+ lines.push(` Usu\xE1rio: ${session.userName}`);
2094
+ if (activeCourse) {
2095
+ lines.push(` Curso ativo: ${activeCourse.courseTitle}`, "");
2096
+ } else {
2097
+ lines.push(
2098
+ " Curso ativo: (nenhum)",
2099
+ " \u2192 tostudy courses para ver seus cursos",
2100
+ " \u2192 tostudy select <n\xFAmero> para ativar um curso",
2101
+ ""
2102
+ );
2103
+ }
2104
+ lines.push(
2105
+ " \u2500\u2500\u2500 Navega\xE7\xE3o \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
2106
+ " tostudy courses Listar seus cursos",
2107
+ " tostudy select <id> Ativar um curso",
2108
+ " tostudy progress Ver progresso do curso ativo",
2109
+ "",
2110
+ " \u2500\u2500\u2500 Estudo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
2111
+ " tostudy start Iniciar/retomar o m\xF3dulo atual",
2112
+ " tostudy start-next Avan\xE7ar para o pr\xF3ximo m\xF3dulo",
2113
+ " tostudy next Avan\xE7ar para a pr\xF3xima li\xE7\xE3o",
2114
+ " tostudy lesson Ver conte\xFAdo da li\xE7\xE3o atual",
2115
+ "",
2116
+ " \u2500\u2500\u2500 Exerc\xEDcios \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
2117
+ " tostudy validate <arquivo> Validar sua solu\xE7\xE3o",
2118
+ " tostudy hint Obter uma dica progressiva",
2119
+ "",
2120
+ " \u2500\u2500\u2500 Dicas r\xE1pidas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
2121
+ " Adicione --json a qualquer comando para sa\xEDda em JSON",
2122
+ " Adicione --help a qualquer comando para ver op\xE7\xF5es",
2123
+ ""
2124
+ );
2125
+ }
2126
+ output(lines.join("\n"), { json: false });
2127
+ });
1758
2128
  }
1759
- output(lines.join("\n"), { json: false });
1760
2129
  });
1761
2130
 
1762
2131
  // src/cli.ts
2132
+ var cli_exports = {};
2133
+ __export(cli_exports, {
2134
+ createProgram: () => createProgram
2135
+ });
2136
+ import { Command as Command15 } from "commander";
1763
2137
  function createProgram() {
1764
2138
  const program2 = new Command15();
1765
- program2.name("tostudy").description("ToStudy CLI \u2014 study courses from the terminal").version("0.1.1").option("--json", "Output structured JSON (for LLM agents)").option("--verbose", "Enable debug output").option("--course <id>", "Override active course ID");
2139
+ program2.name("tostudy").description("ToStudy CLI \u2014 study courses from the terminal").version("0.1.3").option("--json", "Output structured JSON (for LLM agents)").option("--verbose", "Enable debug output").option("--course <id>", "Override active course ID");
1766
2140
  program2.addCommand(setupCommand);
1767
2141
  program2.addCommand(doctorCommand);
1768
2142
  program2.addCommand(loginCommand);
@@ -1779,8 +2153,31 @@ function createProgram() {
1779
2153
  program2.addCommand(menuCommand);
1780
2154
  return program2;
1781
2155
  }
2156
+ var init_cli = __esm({
2157
+ "src/cli.ts"() {
2158
+ "use strict";
2159
+ init_login();
2160
+ init_logout();
2161
+ init_setup();
2162
+ init_doctor();
2163
+ init_courses2();
2164
+ init_select();
2165
+ init_progress();
2166
+ init_start();
2167
+ init_start_next();
2168
+ init_next();
2169
+ init_lesson();
2170
+ init_hint();
2171
+ init_validate();
2172
+ init_menu();
2173
+ }
2174
+ });
1782
2175
 
1783
2176
  // src/cli-entry.ts
1784
- var program = createProgram();
2177
+ if (!process.env.LOG_LEVEL) {
2178
+ process.env.LOG_LEVEL = "fatal";
2179
+ }
2180
+ var { createProgram: createProgram2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
2181
+ var program = createProgram2();
1785
2182
  program.parse();
1786
2183
  //# sourceMappingURL=cli.js.map