@skip-ai/scanner 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,15 @@
1
- export interface CliOptions {
1
+ /** Máscara um token pra nunca imprimir completo em logs/erros: 2ef0...79fb. */
2
+ export declare function maskToken(token: string): string;
3
+ /** Resolve o token: prioriza --token, depois SKIP_TOKEN env var. */
4
+ export declare function resolveToken(cliToken: string | undefined): string;
5
+ export interface SendOptions {
6
+ file: string;
7
+ token: string;
8
+ url: string;
9
+ verbose: boolean;
10
+ noPolling: boolean;
11
+ }
12
+ export interface ScanOptions {
2
13
  token?: string;
3
14
  url: string;
4
15
  dir: string;
@@ -7,5 +18,8 @@ export interface CliOptions {
7
18
  dryRun: boolean;
8
19
  }
9
20
  export declare const DEFAULT_BASE_URL = "https://app.goskip.dev";
10
- export declare function parseCli(argv?: string[]): CliOptions;
21
+ export declare function parseCli(argv?: string[]): {
22
+ command: 'send' | 'scan';
23
+ opts: SendOptions | ScanOptions;
24
+ };
11
25
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,gBAAgB,2BAA2B,CAAC;AAEzD,wBAAgB,QAAQ,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,UAAU,CAuBlE"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAGA,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEjE;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,gBAAgB,2BAA2B,CAAC;AAEzD,wBAAgB,QAAQ,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG;IAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAAA;CAAE,CAyDrH"}
package/dist/cli.js CHANGED
@@ -1,21 +1,63 @@
1
1
  import { Command } from 'commander';
2
+ import { CLI_VERSION } from './reporter.js';
3
+ /** Máscara um token pra nunca imprimir completo em logs/erros: 2ef0...79fb. */
4
+ export function maskToken(token) {
5
+ if (!token)
6
+ return '(vazio)';
7
+ if (token.length <= 8)
8
+ return token.slice(0, 2) + '...' + token.slice(-2);
9
+ return token.slice(0, 4) + '...' + token.slice(-4);
10
+ }
11
+ /** Resolve o token: prioriza --token, depois SKIP_TOKEN env var. */
12
+ export function resolveToken(cliToken) {
13
+ return cliToken || process.env.SKIP_TOKEN || '';
14
+ }
2
15
  export const DEFAULT_BASE_URL = 'https://app.goskip.dev';
3
16
  export function parseCli(argv = process.argv) {
4
17
  const program = new Command()
5
18
  .name('skip-scanner')
6
- .description('Scanner de código para a plataforma Skip AI Accessibility Layer')
7
- .option('-t, --token <token>', 'Token do projeto (obtido no Dashboard). Obrigatório salvo em --dry-run.')
8
- .option('-u, --url <url>', 'URL da plataforma Skip', DEFAULT_BASE_URL)
19
+ .description('Scanner CLI para a plataforma Skip AI Accessibility Layer')
20
+ .version(CLI_VERSION);
21
+ // Comando principal: send (transporta um mapa montado pelo agente)
22
+ program
23
+ .command('send', { isDefault: true })
24
+ .description('Envia um payload já montado (pelo agente/skill) para o Skip Cloud. Este é o modo recomendado.')
25
+ .requiredOption('-f, --file <path>', 'Arquivo JSON com o payload (gerado pelo agente)')
26
+ .option('-t, --token <token>', 'Token do projeto (ou defina SKIP_TOKEN no ambiente)')
27
+ .option('-u, --url <url>', 'URL do Skip Cloud', DEFAULT_BASE_URL)
28
+ .option('--no-polling', 'Enviar sem aguardar o enriquecimento', false)
29
+ .option('-v, --verbose', 'Exibir detalhes no terminal', false)
30
+ .action(() => { });
31
+ // Comando legado: scan (extração por regex — mantido como fallback)
32
+ program
33
+ .command('scan')
34
+ .description('Modo legado: extrai rotas/componentes via regex e envia. Menos inteligente que o agente.')
35
+ .option('-t, --token <token>', 'Token do projeto (ou SKIP_TOKEN). Obrigatório salvo em --dry-run.')
36
+ .option('-u, --url <url>', 'URL do Skip Cloud', DEFAULT_BASE_URL)
9
37
  .option('-d, --dir <dir>', 'Diretório raiz do projeto', process.cwd())
10
38
  .option('-i, --ignore <patterns...>', 'Padrões a ignorar além do padrão', [])
11
39
  .option('--dry-run', 'Executa o scan sem enviar para a plataforma', false)
12
40
  .option('-v, --verbose', 'Exibir detalhes do scan no terminal', false)
13
- .parse(argv);
14
- const opts = program.opts();
15
- // Token é obrigatório fora do dry-run (no dry-run nada é enviado à API).
16
- if (!opts.dryRun && !opts.token) {
17
- program.error("erro: a opção '-t, --token <token>' é obrigatória (ou use --dry-run para testar sem enviar).", { exitCode: 1 });
41
+ .action(() => { });
42
+ program.parse(argv);
43
+ const commandName = program.args[0] === 'scan' ? 'scan' : 'send';
44
+ const command = program.commands.find((c) => c.name() === commandName);
45
+ const opts = (command?.opts() ?? {});
46
+ // Resolve token via --token OU SKIP_TOKEN env var
47
+ if (commandName === 'send') {
48
+ const sendOpts = opts;
49
+ sendOpts.token = resolveToken(sendOpts.token);
50
+ if (!sendOpts.token) {
51
+ program.error("erro: token obrigatório. Use --token=<TOKEN> ou defina SKIP_TOKEN no ambiente.", { exitCode: 1 });
52
+ }
53
+ }
54
+ else {
55
+ const scanOpts = opts;
56
+ scanOpts.token = resolveToken(scanOpts.token);
57
+ if (!scanOpts.dryRun && !scanOpts.token) {
58
+ program.error("erro: token obrigatório. Use --token=<TOKEN> ou SKIP_TOKEN, ou --dry-run para testar sem enviar.", { exitCode: 1 });
59
+ }
18
60
  }
19
- return opts;
61
+ return { command: commandName, opts };
20
62
  }
21
63
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,MAAM,CAAC,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AAEzD,MAAM,UAAU,QAAQ,CAAC,OAAiB,OAAO,CAAC,IAAI;IACpD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;SAC1B,IAAI,CAAC,cAAc,CAAC;SACpB,WAAW,CAAC,iEAAiE,CAAC;SAC9E,MAAM,CAAC,qBAAqB,EAAE,yEAAyE,CAAC;SACxG,MAAM,CAAC,iBAAiB,EAAE,wBAAwB,EAAE,gBAAgB,CAAC;SACrE,MAAM,CAAC,iBAAiB,EAAE,2BAA2B,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SACrE,MAAM,CAAC,4BAA4B,EAAE,kCAAkC,EAAE,EAAE,CAAC;SAC5E,MAAM,CAAC,WAAW,EAAE,6CAA6C,EAAE,KAAK,CAAC;SACzE,MAAM,CAAC,eAAe,EAAE,qCAAqC,EAAE,KAAK,CAAC;SACrE,KAAK,CAAC,IAAI,CAAC,CAAC;IAEf,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAgB,CAAC;IAE1C,4EAA4E;IAC5E,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CACX,8FAA8F,EAC9F,EAAE,QAAQ,EAAE,CAAC,EAAE,CAChB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,7 +1,12 @@
1
1
  #!/usr/bin/env node
2
+ import fs from 'fs';
2
3
  import path from 'path';
3
4
  import chalk from 'chalk';
4
5
  import { parseCli } from './cli.js';
6
+ import { maskObject } from './scanner/secrets.js';
7
+ import { uploadReport, pollStatus } from './uploader.js';
8
+ import { banner, spinner, printSummary, fail } from './ui.js';
9
+ // Modo legado de extração
5
10
  import { detectProject } from './detector.js';
6
11
  import { extractRoutes } from './scanner/routes.js';
7
12
  import { extractComponents } from './scanner/components.js';
@@ -9,34 +14,109 @@ import { extractApiCalls } from './scanner/api-calls.js';
9
14
  import { extractNavigation } from './scanner/navigation.js';
10
15
  import { buildBriefing } from './scanner/briefing.js';
11
16
  import { buildWidgetSnippet } from './scanner/widget-snippet.js';
17
+ import { auditWcag, summarize, WCAG_RULES_VERSION } from './scanner/wcag.js';
18
+ import { calculateScore, scoreColor } from './scanner/score.js';
19
+ /** Aplica cor do chalk conforme o score (necessário porque chalk não é indexável por string). */
20
+ function colorScore(score) {
21
+ const c = scoreColor(score);
22
+ if (c === 'green')
23
+ return chalk.bold.green(`${score}/100`);
24
+ if (c === 'yellow')
25
+ return chalk.bold.yellow(`${score}/100`);
26
+ if (c === 'magenta')
27
+ return chalk.bold.magenta(`${score}/100`);
28
+ return chalk.bold.red(`${score}/100`);
29
+ }
30
+ import { detectGuidedFlows } from './scanner/guided-flows.js';
31
+ import { appendHistory } from './scanner/history.js';
12
32
  import { buildReport, maskReportSecrets, CLI_VERSION } from './reporter.js';
13
- import { uploadReport, pollStatus } from './uploader.js';
14
- import { banner, spinner, printSummary, fail } from './ui.js';
15
33
  import { DEFAULT_IGNORE_PATTERNS } from './scanner/ignore.js';
16
- async function main() {
17
- const opts = parseCli();
18
- const rootDir = path.resolve(opts.dir);
34
+ import { maskToken } from './cli.js';
35
+ // ============ MODO SEND (transportador puro) ============
36
+ async function sendMode(opts) {
37
+ console.log(banner(CLI_VERSION));
38
+ console.log(chalk.dim(` Modo: send (transportador)`));
39
+ console.log(chalk.dim(` Plataforma: ${opts.url}`));
40
+ console.log(chalk.dim(` Token: ${maskToken(opts.token)}`));
41
+ console.log(chalk.dim(` Arquivo: ${opts.file}\n`));
42
+ // 1. Ler o payload do arquivo
43
+ if (!fs.existsSync(opts.file)) {
44
+ throw new Error(`Arquivo não encontrado: ${opts.file}`);
45
+ }
46
+ const readSpinner = spinner('Lendo payload...');
47
+ let payload;
48
+ try {
49
+ payload = JSON.parse(fs.readFileSync(opts.file, 'utf-8'));
50
+ }
51
+ catch (e) {
52
+ readSpinner.fail();
53
+ throw new Error(`JSON inválido em ${opts.file}: ${e instanceof Error ? e.message : String(e)}`);
54
+ }
55
+ readSpinner.succeed('Payload carregado.');
56
+ // 2. Checagem mínima de estrutura — bloqueia se não há dados de scan
57
+ if (!payload.navigationMap && !payload.routes && !payload.wcag) {
58
+ throw new Error('O payload não contém navigationMap, routes nem wcag. Use o validador da skill antes de enviar: node validate-report.js <arquivo>');
59
+ }
60
+ // Aviso (não bloqueia) se faltar auditoria WCAG — o scan estará incompleto
61
+ if (!payload.wcag) {
62
+ console.log(chalk.yellow(' ⚠ Payload sem bloco wcag — o scan estará incompleto no dashboard.'));
63
+ }
64
+ // 3. Preencher metadados se faltarem
65
+ if (!payload.metadata) {
66
+ payload.metadata = {
67
+ framework: payload.framework ?? 'unknown',
68
+ language: payload.language ?? 'TypeScript',
69
+ packageCount: 0,
70
+ typescript: payload.language === 'TypeScript',
71
+ scannedAt: new Date().toISOString(),
72
+ cliVersion: CLI_VERSION,
73
+ };
74
+ }
75
+ // 4. Mascara secrets
76
+ const { result: masked, count: secretsFound } = maskObject(payload);
77
+ const report = { ...masked, secretsFound };
78
+ if (secretsFound > 0) {
79
+ console.log(chalk.yellow(`⚠ ${secretsFound} possível(eis) secret(s) mascarado(s) antes do envio.`));
80
+ }
81
+ if (opts.verbose) {
82
+ console.log('\n' + chalk.dim('Payload a enviar:'));
83
+ console.log(chalk.dim(JSON.stringify(report, null, 2).slice(0, 2000) + (JSON.stringify(report).length > 2000 ? '...' : '')));
84
+ }
85
+ // 5. Enviar
86
+ const uploadSpinner = spinner('Enviando para o Skip Cloud...');
87
+ const scanId = await uploadReport(report, opts.token, opts.url);
88
+ uploadSpinner.succeed(`Scan enviado! ID: ${chalk.yellow(scanId)}`);
89
+ // 6. Polling (opcional)
90
+ if (opts.noPolling) {
91
+ console.log(chalk.dim('\n--no-polling: não aguardando enriquecimento.\n'));
92
+ return;
93
+ }
94
+ const status = await pollStatus(scanId, opts.token, opts.url);
95
+ printSummary({ scanId, entitiesCount: status.entitiesCount, baseUrl: opts.url, status: status.status });
96
+ if (status.status !== 'COMPLETED')
97
+ process.exitCode = 1;
98
+ }
99
+ // ============ MODO SCAN (legado, extração por regex) ============
100
+ async function scanMode(opts) {
19
101
  console.log(banner(CLI_VERSION));
102
+ console.log(chalk.dim(` Modo: scan (legado, regex)`));
103
+ const rootDir = path.resolve(opts.dir);
20
104
  console.log(chalk.dim(` Diretório: ${rootDir}`));
21
105
  console.log(chalk.dim(` Plataforma: ${opts.url}\n`));
106
+ console.log(chalk.yellow(' ⚠ Modo scan usa extração por regex (menos inteligente que o agente).\n'));
22
107
  const ignorePatterns = [...DEFAULT_IGNORE_PATTERNS, ...opts.ignore];
23
- // 1. Detectar framework
24
108
  const detectSpinner = spinner('Detectando projeto...');
25
109
  const signature = detectProject(rootDir);
26
110
  detectSpinner.succeed(`Framework detectado: ${chalk.cyan(signature.framework)} (${signature.language})`);
27
- // 2. Extrair rotas (necessárias para mapear page.tsx -> rota lógica)
28
111
  const routeSpinner = spinner('Extraindo rotas...');
29
112
  const routes = await extractRoutes(rootDir, signature.srcDir, ignorePatterns);
30
113
  routeSpinner.succeed(`${routes.length} rotas encontradas`);
31
- // 3. Extrair componentes e eventos (inventário)
32
114
  const compSpinner = spinner('Extraindo componentes e eventos...');
33
115
  const { components, events } = await extractComponents(rootDir, opts.ignore);
34
116
  compSpinner.succeed(`${components.length} componentes, ${events.length} eventos`);
35
- // 4. Extrair chamadas de API
36
117
  const apiSpinner = spinner('Extraindo chamadas de API...');
37
118
  const apiCalls = await extractApiCalls(rootDir, opts.ignore);
38
119
  apiSpinner.succeed(`${apiCalls.length} chamadas de API detectadas`);
39
- // 5. Extrair mapa de navegação (telas, botões, links, inputs) — núcleo do produto
40
120
  const navSpinner = spinner('Construindo mapa de navegação...');
41
121
  const navigationMap = await extractNavigation(rootDir, opts.ignore, {
42
122
  pagesRoutes: routes.map((r) => ({ physicalPath: r.physicalPath, logicalRoute: r.logicalRoute })),
@@ -44,69 +124,101 @@ async function main() {
44
124
  });
45
125
  const totalActions = navigationMap.screens.reduce((acc, s) => acc + s.actions.length, 0);
46
126
  navSpinner.succeed(`${navigationMap.screens.length} telas mapeadas, ${totalActions} ações, ${navigationMap.navigationGraph.length} arestas de navegação`);
47
- // 6. Gerar briefing em linguagem natural + snippet do widget
48
127
  const briefing = buildBriefing(navigationMap);
49
128
  const widgetSnippet = buildWidgetSnippet();
50
- // 7. Contagem fiel de arquivos físicos lidos
129
+ // ---- Auditoria WCAG ----
130
+ // Lê os arquivos das telas LOCALMENTE (não envia o conteúdo ao servidor).
131
+ const auditSpinner = spinner('Auditando WCAG...');
132
+ const contentsByFile = {};
133
+ for (const s of navigationMap.screens) {
134
+ const abs = path.join(rootDir, s.filePath);
135
+ try {
136
+ contentsByFile[s.filePath] = fs.readFileSync(abs, 'utf-8');
137
+ }
138
+ catch {
139
+ contentsByFile[s.filePath] = '';
140
+ }
141
+ }
142
+ const { violations, checks } = auditWcag(navigationMap.screens, contentsByFile);
143
+ const summary = summarize(violations);
144
+ const { score, level, total } = calculateScore(violations);
145
+ const wcag = {
146
+ score,
147
+ level,
148
+ violations,
149
+ summary,
150
+ checks,
151
+ auditedAt: new Date().toISOString(),
152
+ rulesVersion: WCAG_RULES_VERSION,
153
+ };
154
+ auditSpinner.succeed(`WCAG: score ${colorScore(score)} (${level}), ${total} violação(ões) únicas, ${checks.total} checks [${summary.critical}c/${summary.serious}s/${summary.moderate}m/${summary.minor}i/${summary.unknown}u]`);
155
+ // ---- Fluxos guiados ----
156
+ const guidedFlows = detectGuidedFlows(navigationMap);
157
+ // ---- Histórico (local, enviado junto pra o dashboard) ----
158
+ const historyEntry = {
159
+ scannedAt: wcag.auditedAt,
160
+ score,
161
+ violations: total,
162
+ critical: summary.critical,
163
+ serious: summary.serious,
164
+ moderate: summary.moderate,
165
+ minor: summary.minor,
166
+ unknown: summary.unknown,
167
+ };
168
+ const history = appendHistory(rootDir, historyEntry);
51
169
  const uniqueFiles = new Set([
52
170
  ...routes.map((r) => r.physicalPath),
53
171
  ...components.map((c) => c.filepath),
54
172
  ...apiCalls.map((a) => a.filepath),
55
173
  ...navigationMap.screens.map((s) => s.filePath),
56
174
  ]);
57
- const filesScanned = uniqueFiles.size;
58
- // 8. Montar payload e mascarar secrets
59
175
  const projectName = path.basename(rootDir);
60
176
  const rawReport = buildReport({
61
- signature,
62
- routes,
63
- components,
64
- events,
65
- apiCalls,
66
- navigationMap,
67
- widgetSnippet,
68
- briefing,
69
- filesScanned,
70
- projectName,
177
+ signature, routes, components, events, apiCalls,
178
+ navigationMap, widgetSnippet, briefing, wcag, guidedFlows, history,
179
+ filesScanned: uniqueFiles.size, projectName,
71
180
  });
72
181
  const { report, secretsFound } = maskReportSecrets(rawReport);
73
182
  if (secretsFound > 0) {
74
183
  console.log(chalk.yellow(`⚠ ${secretsFound} possível(eis) secret(s) mascarado(s) antes do envio.`));
75
184
  }
76
185
  if (opts.verbose) {
77
- console.log('\n' + chalk.dim('Briefing (resumo para IA):'));
186
+ console.log('\n' + chalk.dim('Briefing:'));
78
187
  console.log(chalk.dim(briefing));
79
- console.log('\n' + chalk.dim('Navigation Map:'));
80
- console.log(chalk.dim(JSON.stringify(report.navigationMap, null, 2)));
188
+ console.log('\n' + chalk.dim('Top violações WCAG:'));
189
+ for (const v of violations.slice(0, 8)) {
190
+ console.log(chalk.dim(` [${v.severity}] ${v.title} — ${v.screen} (${v.selector})`));
191
+ }
81
192
  }
82
193
  if (opts.dryRun) {
83
- console.log(chalk.bold.cyan('\n🏃 Modo dry-run: pulando envio para a plataforma.\n'));
84
- console.log(` Arquivos escaneados: ${chalk.bold(filesScanned)}`);
85
- console.log(` Telas mapeadas: ${chalk.bold(navigationMap.screens.length)}`);
86
- console.log(` Ações (botões/inputs): ${chalk.bold(totalActions)}`);
87
- console.log(` Arestas de navegação: ${chalk.bold(navigationMap.navigationGraph.length)}`);
88
- console.log(` Rotas: ${chalk.bold(routes.length)}`);
89
- console.log(` Componentes: ${chalk.bold(components.length)}`);
90
- console.log(` Eventos: ${chalk.bold(events.length)}`);
91
- console.log(` Chamadas de API: ${chalk.bold(apiCalls.length)}`);
92
- console.log(` Secrets mascarados: ${chalk.bold(secretsFound)}\n`);
194
+ console.log(chalk.bold.cyan('\n🏃 Modo dry-run: pulando envio.\n'));
195
+ console.log(` Telas mapeadas: ${chalk.bold(navigationMap.screens.length)}`);
196
+ console.log(` Ações: ${chalk.bold(totalActions)}`);
197
+ console.log(` Arestas: ${chalk.bold(navigationMap.navigationGraph.length)}`);
198
+ console.log(` Fluxos guiados: ${chalk.bold(guidedFlows.length)}`);
199
+ console.log(` Score WCAG: ${colorScore(score)} (${level})`);
200
+ console.log(` Violações WCAG: ${chalk.bold(String(total))} [${summary.critical} critical, ${summary.serious} serious, ${summary.moderate} moderate, ${summary.minor} minor]`);
201
+ console.log(` Histórico: ${chalk.bold(String(history.length))} scan(s)\n`);
93
202
  return;
94
203
  }
95
- // 9. Enviar para a plataforma
96
- const uploadSpinner = spinner('Enviando para a plataforma Skip...');
204
+ const uploadSpinner = spinner('Enviando para o Skip Cloud...');
97
205
  const scanId = await uploadReport(report, opts.token, opts.url);
98
206
  uploadSpinner.succeed(`Scan enviado! ID: ${chalk.yellow(scanId)}`);
99
- // 10. Aguardar enriquecimento com IA
100
207
  const status = await pollStatus(scanId, opts.token, opts.url);
101
- printSummary({
102
- scanId,
103
- entitiesCount: status.entitiesCount,
104
- baseUrl: opts.url,
105
- status: status.status,
106
- });
208
+ printSummary({ scanId, entitiesCount: status.entitiesCount, baseUrl: opts.url, status: status.status });
107
209
  if (status.status !== 'COMPLETED')
108
210
  process.exitCode = 1;
109
211
  }
212
+ // ============ Entry point ============
213
+ async function main() {
214
+ const { command, opts } = parseCli();
215
+ if (command === 'send') {
216
+ await sendMode(opts);
217
+ }
218
+ else {
219
+ await scanMode(opts);
220
+ }
221
+ }
110
222
  main().catch((err) => {
111
223
  const msg = err instanceof Error ? err.message : String(err);
112
224
  console.error(fail(`Erro: ${msg}\n`));
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,10 @@ import type { RouteEntry } from './scanner/routes.js';
3
3
  import type { ComponentEntry, EventEntry } from './scanner/components.js';
4
4
  import type { ApiCallEntry } from './scanner/api-calls.js';
5
5
  import type { NavigationMap } from './scanner/navigation.js';
6
- export declare const CLI_VERSION = "0.2.0";
6
+ import type { WcagReport } from './scanner/wcag.js';
7
+ import type { GuidedFlow } from './scanner/guided-flows.js';
8
+ import type { HistoryEntry } from './scanner/history.js';
9
+ export declare const CLI_VERSION = "0.5.0";
7
10
  export interface ScanMetadata {
8
11
  framework: string;
9
12
  language: string;
@@ -25,6 +28,12 @@ export interface ScanReport {
25
28
  widgetSnippet: string;
26
29
  /** Resumo em linguagem natural das telas e ações (pronto para a IA ler). */
27
30
  briefing: string;
31
+ /** Auditoria WCAG: violações, score (0-100) e nível alcançável. */
32
+ wcag: WcagReport;
33
+ /** Fluxos guiados detectados (ex.: login, preenchimento de form). */
34
+ guidedFlows: GuidedFlow[];
35
+ /** Histórico de scans neste projeto (score ao longo do tempo). */
36
+ history: HistoryEntry[];
28
37
  secretsFound: number;
29
38
  metadata: ScanMetadata;
30
39
  }
@@ -37,6 +46,9 @@ export interface BuildReportInput {
37
46
  navigationMap: NavigationMap;
38
47
  widgetSnippet: string;
39
48
  briefing: string;
49
+ wcag: WcagReport;
50
+ guidedFlows: GuidedFlow[];
51
+ history: HistoryEntry[];
40
52
  filesScanned: number;
41
53
  projectName: string;
42
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAG7D,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,mFAAmF;IACnF,aAAa,EAAE,aAAa,CAAC;IAC7B,qFAAqF;IACrF,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,UAAU,CAwB/D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAGlG"}
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,mFAAmF;IACnF,aAAa,EAAE,aAAa,CAAC;IAC7B,qFAAqF;IACrF,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,IAAI,EAAE,UAAU,CAAC;IACjB,qEAAqE;IACrE,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,kEAAkE;IAClE,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,UAAU,CA2B/D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAGlG"}
package/dist/reporter.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { maskObject } from './scanner/secrets.js';
2
- export const CLI_VERSION = '0.2.0';
2
+ export const CLI_VERSION = '0.5.0';
3
3
  /**
4
4
  * Monta o payload final (ScanReport) enviado para a API.
5
5
  */
6
6
  export function buildReport(input) {
7
- const { signature, routes, components, events, apiCalls, navigationMap, widgetSnippet, briefing, filesScanned, projectName } = input;
7
+ const { signature, routes, components, events, apiCalls, navigationMap, widgetSnippet, briefing, wcag, guidedFlows, history, filesScanned, projectName } = input;
8
8
  const report = {
9
9
  projectName,
10
10
  filesScanned,
@@ -15,6 +15,9 @@ export function buildReport(input) {
15
15
  navigationMap,
16
16
  widgetSnippet,
17
17
  briefing,
18
+ wcag,
19
+ guidedFlows,
20
+ history,
18
21
  secretsFound: 0,
19
22
  metadata: {
20
23
  framework: signature.framework,
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AAyCnC;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;IAErI,MAAM,MAAM,GAAe;QACzB,WAAW;QACX,YAAY;QACZ,MAAM;QACN,UAAU;QACV,MAAM;QACN,QAAQ;QACR,aAAa;QACb,aAAa;QACb,QAAQ;QACR,YAAY,EAAE,CAAC;QACf,QAAQ,EAAE;YACR,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,YAAY,EAAE,SAAS,CAAC,YAAY;YACpC,UAAU,EAAE,SAAS,CAAC,QAAQ,KAAK,YAAY;YAC/C,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,UAAU,EAAE,WAAW;SACxB;KACF,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAkB;IAClD,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AAC7E,CAAC"}
1
+ {"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AAkDnC;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;IAEjK,MAAM,MAAM,GAAe;QACzB,WAAW;QACX,YAAY;QACZ,MAAM;QACN,UAAU;QACV,MAAM;QACN,QAAQ;QACR,aAAa;QACb,aAAa;QACb,QAAQ;QACR,IAAI;QACJ,WAAW;QACX,OAAO;QACP,YAAY,EAAE,CAAC;QACf,QAAQ,EAAE;YACR,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,YAAY,EAAE,SAAS,CAAC,YAAY;YACpC,UAAU,EAAE,SAAS,CAAC,QAAQ,KAAK,YAAY;YAC/C,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,UAAU,EAAE,WAAW;SACxB;KACF,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAkB;IAClD,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AAC7E,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { NavigationMap } from './navigation.js';
2
+ export interface GuidedFlowStep {
3
+ screen: string;
4
+ action: string;
5
+ label: string;
6
+ /** Rota destino, se a ação navegar. */
7
+ navigatesTo?: string | null;
8
+ }
9
+ export interface GuidedFlow {
10
+ name: string;
11
+ description: string;
12
+ steps: GuidedFlowStep[];
13
+ }
14
+ /**
15
+ * Detecta fluxos guiados a partir do navigationMap.
16
+ * Um fluxo é uma sequência de ações que leva o usuário a um objetivo
17
+ * (ex.: login, preencher formulário, finalizar compra).
18
+ *
19
+ * Heurística: para cada tela que tem um <form> (ações fill + submit),
20
+ * monta um fluxo "Preencher <tela>" com as ações em ordem.
21
+ */
22
+ export declare function detectGuidedFlows(map: NavigationMap): GuidedFlow[];
23
+ //# sourceMappingURL=guided-flows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guided-flows.d.ts","sourceRoot":"","sources":["../../src/scanner/guided-flows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,iBAAiB,CAAC;AAEvE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU,EAAE,CAwClE"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Detecta fluxos guiados a partir do navigationMap.
3
+ * Um fluxo é uma sequência de ações que leva o usuário a um objetivo
4
+ * (ex.: login, preencher formulário, finalizar compra).
5
+ *
6
+ * Heurística: para cada tela que tem um <form> (ações fill + submit),
7
+ * monta um fluxo "Preencher <tela>" com as ações em ordem.
8
+ */
9
+ export function detectGuidedFlows(map) {
10
+ const flows = [];
11
+ for (const screen of map.screens) {
12
+ const fills = screen.actions.filter((a) => a.kind === 'fill');
13
+ const submits = screen.actions.filter((a) => a.kind === 'submit');
14
+ const navigations = screen.actions.filter((a) => a.kind === 'navigation');
15
+ // Fluxo 1: formulário (fill + submit)
16
+ if (fills.length > 0 && submits.length > 0) {
17
+ const steps = fills
18
+ .sort(byLabel)
19
+ .map((a) => ({ screen: screen.route, action: a.kind, label: a.label }));
20
+ for (const s of submits) {
21
+ steps.push({
22
+ screen: screen.route,
23
+ action: s.kind,
24
+ label: s.label,
25
+ navigatesTo: s.targetRoute,
26
+ });
27
+ }
28
+ flows.push({
29
+ name: flowNameFor(screen.title, submits[0]?.intent),
30
+ description: `Preencher e enviar o formulário da tela ${screen.title}.`,
31
+ steps,
32
+ });
33
+ }
34
+ // Fluxo 2: navegação primária (se há uma navegação clara da tela)
35
+ if (fills.length === 0 && navigations.length === 1) {
36
+ const nav = navigations[0];
37
+ flows.push({
38
+ name: `Ir para ${navLabel(nav)}`,
39
+ description: `Navegar de ${screen.title} para ${navLabel(nav)}.`,
40
+ steps: [{ screen: screen.route, action: nav.kind, label: nav.label, navigatesTo: nav.targetRoute }],
41
+ });
42
+ }
43
+ }
44
+ return flows;
45
+ }
46
+ function byLabel(a, b) {
47
+ return a.label.localeCompare(b.label);
48
+ }
49
+ function navLabel(nav) {
50
+ return nav.targetRoute ?? nav.label;
51
+ }
52
+ function flowNameFor(screenTitle, intent) {
53
+ if (intent === 'login')
54
+ return 'Login do usuário';
55
+ if (intent === 'save')
56
+ return `Salvar em ${screenTitle}`;
57
+ if (intent === 'search')
58
+ return `Buscar em ${screenTitle}`;
59
+ return `Preencher ${screenTitle}`;
60
+ }
61
+ //# sourceMappingURL=guided-flows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guided-flows.js","sourceRoot":"","sources":["../../src/scanner/guided-flows.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface HistoryEntry {
2
+ scannedAt: string;
3
+ score: number;
4
+ violations: number;
5
+ /** Contagem por severidade. */
6
+ critical: number;
7
+ serious: number;
8
+ moderate: number;
9
+ minor: number;
10
+ unknown: number;
11
+ }
12
+ export declare const HISTORY_FILE = ".skip-history.json";
13
+ /**
14
+ * Lê o histórico local do projeto (.skip-history.json).
15
+ * Retorna [] se não existir ou for inválido.
16
+ */
17
+ export declare function readHistory(rootDir: string): HistoryEntry[];
18
+ /**
19
+ * Adiciona uma entrada ao histórico local e retorna o histórico atualizado.
20
+ * Mantém apenas as últimas MAX_ENTRIES entradas.
21
+ */
22
+ export declare function appendHistory(rootDir: string, entry: HistoryEntry): HistoryEntry[];
23
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/scanner/history.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,YAAY,uBAAuB,CAAC;AAGjD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CAS3D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,EAAE,CAalF"}