@tostudy-ai/cli 0.1.0 → 0.1.2

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