@kinkai.cloud/vibecheck 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +330 -35
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -14543,6 +14543,7 @@ var MAX_BYTES = 256e3;
14543
14543
  var MAX_ROTULO = 80;
14544
14544
  var MAX_ID = 64;
14545
14545
  var MAX_CAMINHO = 180;
14546
+ var MAX_PACOTES = 32;
14546
14547
  var caminho = external_exports.string().min(1).max(MAX_CAMINHO);
14547
14548
  var noSchema = external_exports.object({
14548
14549
  id: external_exports.string().min(1).max(MAX_ID),
@@ -14565,10 +14566,39 @@ var grafoScanSchema = external_exports.object({
14565
14566
  avancado: external_exports.boolean(),
14566
14567
  nos: external_exports.array(noSchema).max(MAX_NOS),
14567
14568
  arestas: external_exports.array(arestaSchema).max(MAX_ARESTAS),
14568
- comunidades: external_exports.array(comunidadeSchema).max(MAX_COMUNIDADES)
14569
+ comunidades: external_exports.array(comunidadeSchema).max(MAX_COMUNIDADES),
14570
+ pacotes: external_exports.array(external_exports.string().min(1).max(MAX_ROTULO)).max(MAX_PACOTES)
14569
14571
  });
14570
14572
 
14573
+ // ../../packages/graph/src/dicas.ts
14574
+ function rotaDeArquivo(caminho2) {
14575
+ const normal = caminho2.replaceAll("\\", "/");
14576
+ const app = /(?:^|\/)app\/(.+)\/route\.(t|j)sx?$/i.exec(normal);
14577
+ if (app?.[1] !== void 0) {
14578
+ const segmentos = app[1].split("/").filter((s) => s.length > 0 && !s.startsWith("(") && !s.startsWith("@")).map((s) => s.replace(/^\[+\.\.\.(.+)\]+$/, "*").replace(/^\[+(.+)\]+$/, ":$1"));
14579
+ if (segmentos.length === 0) return "/api";
14580
+ return `/${segmentos.join("/")}`;
14581
+ }
14582
+ const pages = /(?:^|\/)pages\/api\/(.+)\.(t|j)sx?$/i.exec(normal);
14583
+ if (pages?.[1] !== void 0) {
14584
+ const semIndex = pages[1].replace(/\/index$/i, "");
14585
+ return `/api/${semIndex}`;
14586
+ }
14587
+ return null;
14588
+ }
14589
+
14571
14590
  // ../../packages/graph/src/mapear.ts
14591
+ var ROTULO_KIND = {
14592
+ browser: "navegador",
14593
+ app: "aplica\xE7\xE3o",
14594
+ api: "API",
14595
+ db: "banco",
14596
+ storage: "arquivos",
14597
+ auth: "autentica\xE7\xE3o",
14598
+ ai: "IA",
14599
+ payments: "pagamentos",
14600
+ secrets: "segredos"
14601
+ };
14572
14602
  var REGRAS = [
14573
14603
  {
14574
14604
  kind: "api",
@@ -14593,13 +14623,78 @@ function mapearKind(sinal) {
14593
14623
  return "app";
14594
14624
  }
14595
14625
 
14626
+ // ../../packages/graph/src/pacotes.ts
14627
+ var CARA_DE_CHAVE = /(sk_live_|sk_test_|rk_live_|pk_live_|pk_test_|sb_secret_|eyJ[A-Za-z0-9_-]{20,}|gsk_[A-Za-z0-9]|sk-ant-|sk-proj-|sk-or-v1-)/i;
14628
+ var REGRAS2 = [
14629
+ { id: "next", teste: /^next(?:\/|$)/ },
14630
+ { id: "react", teste: /^react(?:-dom)?(?:\/|$)/ },
14631
+ { id: "vue", teste: /^vue(?:\/|$)/ },
14632
+ { id: "svelte", teste: /^svelte(?:\/|$)/ },
14633
+ { id: "angular", teste: /^@angular\// },
14634
+ { id: "vite", teste: /^vite(?:\/|$)/ },
14635
+ { id: "astro", teste: /^astro(?:\/|$)/ },
14636
+ { id: "stripe", teste: /^(?:stripe|@stripe\/)/ },
14637
+ { id: "supabase", teste: /^(?:@supabase\/|@supabase$)/ },
14638
+ { id: "firebase", teste: /^(?:firebase|@firebase\/)/ },
14639
+ { id: "clerk", teste: /^@clerk\// },
14640
+ { id: "next-auth", teste: /^(?:next-auth|@auth\/)/ },
14641
+ { id: "prisma", teste: /^(?:@prisma\/client|prisma)(?:\/|$)/ },
14642
+ { id: "drizzle", teste: /^drizzle-orm(?:\/|$)/ },
14643
+ { id: "kysely", teste: /^kysely(?:\/|$)/ },
14644
+ { id: "postgres", teste: /^(?:postgres|pg|@neondatabase\/)/ },
14645
+ { id: "mongodb", teste: /^(?:mongodb|mongoose)(?:\/|$)/ },
14646
+ { id: "styled-components", teste: /^styled-components(?:\/|$)/ },
14647
+ { id: "emotion", teste: /^@emotion\// },
14648
+ { id: "tailwind", teste: /^tailwindcss(?:\/|$)/ },
14649
+ { id: "openai", teste: /^openai(?:\/|$)/ },
14650
+ { id: "anthropic", teste: /^@anthropic-ai\// },
14651
+ { id: "langchain", teste: /^langchain(?:\/|$)/ },
14652
+ { id: "trpc", teste: /^@trpc\// },
14653
+ { id: "hono", teste: /^hono(?:\/|$)/ },
14654
+ { id: "express", teste: /^express(?:\/|$)/ },
14655
+ { id: "fastify", teste: /^fastify(?:\/|$)/ },
14656
+ { id: "graphql", teste: /^(?:graphql|@apollo\/)/ },
14657
+ { id: "redis", teste: /^(?:redis|ioredis)(?:\/|$)/ },
14658
+ { id: "resend", teste: /^resend(?:\/|$)/ },
14659
+ { id: "auth0", teste: /^(?:auth0|@auth0\/)/ },
14660
+ { id: "lucia", teste: /^lucia(?:\/|$)/ },
14661
+ { id: "kinde", teste: /^@kinde-oss\// }
14662
+ ];
14663
+ function idDePacote(spec) {
14664
+ const limpo = spec.trim().replace(/^npm:/, "");
14665
+ if (limpo.length === 0 || limpo.startsWith(".") || limpo.startsWith("/")) return null;
14666
+ if (limpo.startsWith("node:") || limpo.startsWith("#")) return null;
14667
+ for (const regra of REGRAS2) {
14668
+ if (regra.teste.test(limpo)) return regra.id;
14669
+ }
14670
+ return null;
14671
+ }
14672
+ function sanitizarPacote(bruto) {
14673
+ const limpo = bruto.trim().slice(0, MAX_ROTULO);
14674
+ if (limpo.length === 0) return null;
14675
+ if (CARA_DE_CHAVE.test(limpo)) return null;
14676
+ if (!/^[@a-z0-9][a-z0-9._+/-]{0,60}$/i.test(limpo)) return null;
14677
+ return limpo;
14678
+ }
14679
+ function uniquePacotes(values) {
14680
+ const seen = /* @__PURE__ */ new Set();
14681
+ const out = [];
14682
+ for (const value of values) {
14683
+ if (out.length >= MAX_PACOTES) break;
14684
+ const limpo = sanitizarPacote(value);
14685
+ if (limpo === null || seen.has(limpo)) continue;
14686
+ seen.add(limpo);
14687
+ out.push(limpo);
14688
+ }
14689
+ return out;
14690
+ }
14691
+
14596
14692
  // ../../packages/graph/src/sanitize.ts
14597
14693
  var CAMPOS_CORPO = /* @__PURE__ */ new Set([
14598
14694
  "content",
14599
14695
  "snippet",
14600
14696
  "code",
14601
14697
  "rationale",
14602
- "source",
14603
14698
  "body",
14604
14699
  "text",
14605
14700
  "source_location",
@@ -14609,7 +14704,7 @@ var CAMPOS_CORPO = /* @__PURE__ */ new Set([
14609
14704
  ]);
14610
14705
  var EXTENSOES_SEGREDO = /\.(env|pem|key|p12|pfx|crt|cer|p8|keystore)(?:\.|$)/i;
14611
14706
  var SEGMENTO_PROIBIDO = /(?:^|\/)(?:\.env(?:\..+)?|id_rsa|id_ed25519|credentials|secrets?)(?:\/|$)/i;
14612
- var CARA_DE_CHAVE = /(sk_live_|sk_test_|rk_live_|sb_secret_|eyJ[A-Za-z0-9_-]{8,}|gsk_|sk-ant-|sk-proj-|api[_-]?key|secret|password|token|bearer)/i;
14707
+ var CARA_DE_CHAVE2 = /(sk_live_|sk_test_|rk_live_|pk_live_|pk_test_|sb_secret_|sb_publishable_|eyJ[A-Za-z0-9_-]{20,}|gsk_[A-Za-z0-9]|sk-ant-|sk-proj-|sk-or-v1-)/i;
14613
14708
  var MAX_ROTULO_ARQUIVO = MAX_CAMINHO;
14614
14709
  function eRecord(value) {
14615
14710
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -14631,7 +14726,7 @@ function sanitizarCaminho(bruto) {
14631
14726
  function redigirRotulo(bruto) {
14632
14727
  const limpo = bruto.trim().slice(0, MAX_ROTULO);
14633
14728
  if (limpo.length === 0) return "n\xF3";
14634
- if (CARA_DE_CHAVE.test(limpo)) return "[redigido]";
14729
+ if (CARA_DE_CHAVE2.test(limpo)) return "[redigido]";
14635
14730
  return limpo;
14636
14731
  }
14637
14732
  function uniqueCapped(values, cap) {
@@ -14676,10 +14771,28 @@ function stripCorpo(value) {
14676
14771
  const out = {};
14677
14772
  for (const [chave, item] of Object.entries(value)) {
14678
14773
  if (CAMPOS_CORPO.has(chave)) continue;
14774
+ if (chave === "source" && typeof item === "string" && (item.includes("\n") || item.length > MAX_ID)) {
14775
+ continue;
14776
+ }
14679
14777
  out[chave] = stripCorpo(item);
14680
14778
  }
14681
14779
  return out;
14682
14780
  }
14781
+ function primeiroExport(value) {
14782
+ if (typeof value === "string" && value.length > 0) {
14783
+ const primeiro = value.split(/[\s,]+/)[0];
14784
+ return primeiro !== void 0 && primeiro.length > 0 ? primeiro : null;
14785
+ }
14786
+ if (!Array.isArray(value)) return null;
14787
+ for (const item of value) {
14788
+ if (typeof item === "string" && item.length > 0) return item;
14789
+ if (eRecord(item)) {
14790
+ const nome = comoString(item["name"]) ?? comoString(item["identifier"]);
14791
+ if (nome !== null) return nome;
14792
+ }
14793
+ }
14794
+ return null;
14795
+ }
14683
14796
  function nosDoDump(dump) {
14684
14797
  const bruto = dump["nodes"] ?? dump["nos"];
14685
14798
  const lista = Array.isArray(bruto) ? bruto : eRecord(bruto) ? Object.entries(bruto).map(
@@ -14692,7 +14805,7 @@ function nosDoDump(dump) {
14692
14805
  item["arquivos"] ?? item["files"] ?? item["source_file"] ?? item["sourceFile"] ?? item["file"] ?? item["path"]
14693
14806
  );
14694
14807
  const rotulo = redigirRotulo(
14695
- comoString(item["rotulo"]) ?? comoString(item["label"]) ?? comoString(item["name"]) ?? arquivos[0] ?? `n\xF3-${String(i)}`
14808
+ comoString(item["rotulo"]) ?? comoString(item["label"]) ?? comoString(item["name"]) ?? comoString(item["identifier"]) ?? comoString(item["symbol"]) ?? primeiroExport(item["exports"] ?? item["identificadores"]) ?? arquivos[0] ?? `n\xF3-${String(i)}`
14696
14809
  );
14697
14810
  const kindBruto = comoString(item["kind"]) ?? comoString(item["nodeKind"]);
14698
14811
  const kind = kindBruto !== null && NODE_KINDS.includes(kindBruto) ? kindBruto : mapearKind({ rotulo, arquivos });
@@ -14753,7 +14866,7 @@ function comunidadesDoDump(dump, nos) {
14753
14866
  seen.add(nodeKind);
14754
14867
  out2.push({
14755
14868
  nodeKind,
14756
- rotulo: redigirRotulo(comoString(item["rotulo"]) ?? comoString(item["label"]) ?? nodeKind),
14869
+ rotulo: ROTULO_KIND[nodeKind],
14757
14870
  arquivos: uniqueCapped(
14758
14871
  arquivosDe(item["arquivos"] ?? item["files"]),
14759
14872
  MAX_ARQUIVOS_COMUNIDADE
@@ -14775,7 +14888,7 @@ function comunidadesDoDump(dump, nos) {
14775
14888
  if (grupo === void 0) continue;
14776
14889
  const arquivos = uniqueCapped(grupo.arquivos, MAX_ARQUIVOS_COMUNIDADE);
14777
14890
  if (arquivos.length === 0 && grupo.rotulo.length === 0) continue;
14778
- out.push({ nodeKind: kind, rotulo: redigirRotulo(grupo.rotulo), arquivos });
14891
+ out.push({ nodeKind: kind, rotulo: ROTULO_KIND[kind], arquivos });
14779
14892
  if (out.length >= MAX_COMUNIDADES) break;
14780
14893
  }
14781
14894
  return out;
@@ -14795,6 +14908,7 @@ function sanitizarGrafo(entrada) {
14795
14908
  const ids = new Set(nos.map((n) => n.id));
14796
14909
  const arestas = arestasDoDump(limpo, ids);
14797
14910
  const comunidades = comunidadesDoDump(limpo, nos);
14911
+ const pacotes = uniquePacotes(pacotesDoDump(limpo, nos));
14798
14912
  const temArquivo = comunidades.some((c) => c.arquivos.length > 0) || nos.some((n) => n.arquivos.length > 0);
14799
14913
  if (!temArquivo) return { ok: false, motivo: "vazio" };
14800
14914
  const avancado = comunidades.length > 0;
@@ -14805,10 +14919,24 @@ function sanitizarGrafo(entrada) {
14805
14919
  avancado,
14806
14920
  nos,
14807
14921
  arestas,
14808
- comunidades
14922
+ comunidades,
14923
+ pacotes
14809
14924
  }
14810
14925
  };
14811
14926
  }
14927
+ function pacotesDoDump(dump, nos) {
14928
+ const brutos = [];
14929
+ const campo = dump["pacotes"] ?? dump["packages"];
14930
+ if (Array.isArray(campo)) {
14931
+ for (const item of campo) {
14932
+ if (typeof item === "string") brutos.push(item);
14933
+ }
14934
+ }
14935
+ for (const no of nos) {
14936
+ if (no.id.startsWith("pkg:")) brutos.push(no.rotulo);
14937
+ }
14938
+ return brutos;
14939
+ }
14812
14940
 
14813
14941
  // src/graphify.ts
14814
14942
  import { spawn } from "child_process";
@@ -14918,6 +15046,9 @@ async function abrirBrowser(url2) {
14918
15046
  if (await tentarSpawn(cmd, args)) return;
14919
15047
  }
14920
15048
  }
15049
+ function deveAbrirNavegador(opts) {
15050
+ return !opts.ci && !opts.noWait;
15051
+ }
14921
15052
  async function detalheHttp(resposta) {
14922
15053
  const tipo = resposta.headers.get("content-type") ?? "";
14923
15054
  if (tipo.includes("application/json")) {
@@ -14978,16 +15109,13 @@ var IGNORAR = /* @__PURE__ */ new Set([
14978
15109
  "build"
14979
15110
  ]);
14980
15111
  var CODIGO = /\.(m?[jt]sx?)$/;
14981
- var SINAIS = [
14982
- { re: /(?:^|\/)app\/.*\/route\.(t|j)sx?$/i, rotulo: "rota App Router" },
14983
- { re: /(?:^|\/)pages\/api\//i, rotulo: "pages/api" },
14984
- { re: /\bstripe\b/i, rotulo: "stripe" },
14985
- { re: /\bsupabase\b/i, rotulo: "supabase" },
14986
- { re: /\bfirebase\b/i, rotulo: "firebase" },
14987
- { re: /\bopenai\b|\banthropic\b/i, rotulo: "openai" },
14988
- { re: /\bclerk\b|next-auth/i, rotulo: "clerk" }
14989
- ];
14990
- var IMPORT_SINAL = /from\s+['"](@supabase\/|@clerk\/|stripe|firebase|openai|@anthropic|next-auth)/i;
15112
+ var MAX_ARQUIVOS = 800;
15113
+ var MAX_NOS_WALKER = 120;
15114
+ var EXT = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", "/index.ts", "/index.tsx", "/index.js"];
15115
+ var EXPORT_RE = /export\s+(?:default\s+)?(?:async\s+)?(?:function\*?|class|const|let|var|enum)\s+([A-Za-z_$][\w$]*)/g;
15116
+ var EXPORT_LISTA_RE = /export\s+\{([^}]+)\}/g;
15117
+ var FROM_RE = /(?:from\s+|import\s*\(\s*|require\s*\(\s*)['"]([^'"]+)['"]/g;
15118
+ var HANDLERS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
14991
15119
  function listar(raiz, dir, acc) {
14992
15120
  let nomes;
14993
15121
  try {
@@ -15010,31 +15138,196 @@ function listar(raiz, dir, acc) {
15010
15138
  }
15011
15139
  if (!stat.isFile() || !CODIGO.test(nome)) continue;
15012
15140
  acc.push(cheio);
15013
- if (acc.length >= 800) return;
15141
+ if (acc.length >= MAX_ARQUIVOS) return;
15014
15142
  }
15015
15143
  }
15016
- function noDeArquivo(raiz, cheio, i) {
15017
- const rel = relative(raiz, cheio).replaceAll("\\", "/");
15144
+ function posixRel(raiz, cheio) {
15145
+ return relative(raiz, cheio).replaceAll("\\", "/");
15146
+ }
15147
+ function dirnamePosix(caminho2) {
15148
+ const i = caminho2.lastIndexOf("/");
15149
+ return i <= 0 ? "" : caminho2.slice(0, i);
15150
+ }
15151
+ function normalizarPosix(caminho2) {
15152
+ const partes = [];
15153
+ for (const p of caminho2.replaceAll("\\", "/").split("/")) {
15154
+ if (p === "" || p === ".") continue;
15155
+ if (p === "..") {
15156
+ partes.pop();
15157
+ continue;
15158
+ }
15159
+ partes.push(p);
15160
+ }
15161
+ return partes.join("/");
15162
+ }
15163
+ function exportsDe(conteudo) {
15164
+ const out = [];
15165
+ const seen = /* @__PURE__ */ new Set();
15166
+ const push = (nome) => {
15167
+ if (nome.length === 0 || seen.has(nome)) return;
15168
+ seen.add(nome);
15169
+ out.push(nome);
15170
+ };
15171
+ EXPORT_RE.lastIndex = 0;
15172
+ let m;
15173
+ while ((m = EXPORT_RE.exec(conteudo)) !== null) {
15174
+ if (m[1] !== void 0) push(m[1]);
15175
+ }
15176
+ EXPORT_LISTA_RE.lastIndex = 0;
15177
+ while ((m = EXPORT_LISTA_RE.exec(conteudo)) !== null) {
15178
+ const lista = m[1];
15179
+ if (lista === void 0) continue;
15180
+ for (const parte of lista.split(",")) {
15181
+ const nome = parte.trim().split(/\s+as\s+/).at(-1)?.trim();
15182
+ if (nome !== void 0 && /^[A-Za-z_$][\w$]*$/.test(nome)) push(nome);
15183
+ }
15184
+ }
15185
+ return out;
15186
+ }
15187
+ function specsDe(conteudo) {
15188
+ const out = [];
15189
+ FROM_RE.lastIndex = 0;
15190
+ let m;
15191
+ while ((m = FROM_RE.exec(conteudo)) !== null) {
15192
+ if (m[1] !== void 0) out.push(m[1]);
15193
+ }
15194
+ return out;
15195
+ }
15196
+ function acharNoIndice(specPath, indice) {
15197
+ const n = specPath.replaceAll("\\", "/").replace(/^\.\//, "");
15198
+ for (const ext of EXT) {
15199
+ const hit = indice.get(n + ext);
15200
+ if (hit !== void 0) return hit;
15201
+ }
15202
+ return null;
15203
+ }
15204
+ function resolverSpec(de, spec, indice) {
15205
+ if (spec.startsWith(".")) {
15206
+ const base = normalizarPosix(`${dirnamePosix(de)}/${spec}`);
15207
+ return acharNoIndice(base, indice);
15208
+ }
15209
+ const alias = spec.startsWith("@/") ? spec.slice(2) : spec.startsWith("~/") ? spec.slice(2) : null;
15210
+ if (alias === null) return null;
15211
+ for (const prefixo of ["", "src/", "app/"]) {
15212
+ const hit = acharNoIndice(`${prefixo}${alias}`, indice);
15213
+ if (hit !== null) return hit;
15214
+ }
15215
+ return null;
15216
+ }
15217
+ function rotuloDe(rel, exports) {
15218
+ const rota = rotaDeArquivo(rel);
15219
+ const handlers = exports.filter((e) => HANDLERS.has(e));
15220
+ if (rota !== null && handlers.length > 0) return `${handlers[0]} ${rota}`;
15221
+ if (rota !== null) return rota;
15222
+ const simbolo = exports.find((e) => !HANDLERS.has(e));
15223
+ if (simbolo !== void 0) return simbolo;
15224
+ const base = rel.split("/").at(-1)?.replace(/\.(m?[jt]sx?)$/i, "");
15225
+ return base !== void 0 && base.length > 0 && base !== "index" ? base : rel;
15226
+ }
15227
+ function lerArquivo(raiz, cheio) {
15228
+ const rel = posixRel(raiz, cheio);
15018
15229
  let conteudo = "";
15019
15230
  try {
15020
- conteudo = readFileSync2(cheio, "utf8").slice(0, 8e3);
15231
+ conteudo = readFileSync2(cheio, "utf8").slice(0, 12e3);
15021
15232
  } catch {
15022
15233
  return null;
15023
15234
  }
15024
- const rotulo = SINAIS.find((s) => s.re.test(rel) || s.re.test(conteudo) || IMPORT_SINAL.test(conteudo))?.rotulo ?? rel.split("/").at(-1) ?? `arquivo-${String(i)}`;
15025
- return { id: `f${String(i)}`, label: rotulo, source_file: rel };
15235
+ const exports = exportsDe(conteudo);
15236
+ const specs = specsDe(conteudo);
15237
+ return {
15238
+ rel,
15239
+ rotulo: rotuloDe(rel, exports),
15240
+ exports,
15241
+ importsRel: specs.filter((s) => s.startsWith(".") || s.startsWith("@/") || s.startsWith("~/")),
15242
+ importsPkg: specs
15243
+ };
15244
+ }
15245
+ function prioridade(info) {
15246
+ const kind = mapearKind({ rotulo: info.rotulo, arquivos: [info.rel] });
15247
+ if (kind === "api") return 0;
15248
+ if (kind === "payments" || kind === "auth" || kind === "db") return 1;
15249
+ if (kind === "storage" || kind === "secrets" || kind === "browser" || kind === "ai") return 2;
15250
+ if (info.importsPkg.some((s) => idDePacote(s) !== null)) return 3;
15251
+ return 8;
15026
15252
  }
15027
15253
  function extrairDoRepo(raiz) {
15028
- const arquivos = [];
15029
- listar(raiz, raiz, arquivos);
15030
- if (arquivos.length === 0) return null;
15254
+ const caminhos = [];
15255
+ listar(raiz, raiz, caminhos);
15256
+ if (caminhos.length === 0) return null;
15257
+ const infos = [];
15258
+ const indice = /* @__PURE__ */ new Map();
15259
+ for (const cheio of caminhos) {
15260
+ const info = lerArquivo(raiz, cheio);
15261
+ if (info === null) continue;
15262
+ infos.push(info);
15263
+ indice.set(info.rel, info.rel);
15264
+ }
15265
+ if (infos.length === 0) return null;
15266
+ const porRel = new Map(infos.map((i) => [i.rel, i]));
15267
+ const escolhidos = /* @__PURE__ */ new Set();
15268
+ const ordenados = [...infos].sort((a, b) => prioridade(a) - prioridade(b) || a.rel.localeCompare(b.rel));
15269
+ for (const info of ordenados) {
15270
+ if (prioridade(info) <= 3) escolhidos.add(info.rel);
15271
+ }
15272
+ const expandir = (saltos) => {
15273
+ let fronteira = [...escolhidos];
15274
+ for (let s = 0; s < saltos; s += 1) {
15275
+ const proxima = [];
15276
+ for (const rel of fronteira) {
15277
+ const info = porRel.get(rel);
15278
+ if (info === void 0) continue;
15279
+ for (const spec of info.importsRel) {
15280
+ const alvo = resolverSpec(rel, spec, indice);
15281
+ if (alvo === null || escolhidos.has(alvo)) continue;
15282
+ escolhidos.add(alvo);
15283
+ proxima.push(alvo);
15284
+ }
15285
+ }
15286
+ fronteira = proxima;
15287
+ }
15288
+ };
15289
+ expandir(2);
15290
+ if (escolhidos.size === 0) {
15291
+ for (const info of ordenados.slice(0, Math.min(24, ordenados.length))) {
15292
+ escolhidos.add(info.rel);
15293
+ }
15294
+ }
15295
+ const files = [...escolhidos].map((rel) => porRel.get(rel)).filter((i) => i !== void 0).sort((a, b) => prioridade(a) - prioridade(b) || a.rel.localeCompare(b.rel)).slice(0, MAX_NOS_WALKER);
15031
15296
  const nodes = [];
15032
- for (const [i, cheio] of arquivos.entries()) {
15033
- const no = noDeArquivo(raiz, cheio, i);
15034
- if (no !== null) nodes.push(no);
15297
+ const edges = [];
15298
+ const pacotes = /* @__PURE__ */ new Set();
15299
+ const idDe2 = /* @__PURE__ */ new Map();
15300
+ for (const [i, info] of files.entries()) {
15301
+ const id = `f${String(i)}`;
15302
+ idDe2.set(info.rel, id);
15303
+ nodes.push({
15304
+ id,
15305
+ label: info.rotulo,
15306
+ identifier: info.exports[0] ?? info.rotulo,
15307
+ source_file: info.rel
15308
+ });
15035
15309
  }
15036
- if (nodes.length === 0) return null;
15037
- const sanitizado = sanitizarGrafo({ nodes, edges: [] });
15310
+ for (const info of files) {
15311
+ const de = idDe2.get(info.rel);
15312
+ if (de === void 0) continue;
15313
+ for (const spec of info.importsRel) {
15314
+ const alvo = resolverSpec(info.rel, spec, indice);
15315
+ const para = alvo === null ? void 0 : idDe2.get(alvo);
15316
+ if (para === void 0) continue;
15317
+ edges.push({ source: de, target: para, relation: "imports" });
15318
+ }
15319
+ for (const spec of info.importsPkg) {
15320
+ const pkg = idDePacote(spec);
15321
+ if (pkg === null) continue;
15322
+ pacotes.add(pkg);
15323
+ const pkgId = `pkg:${pkg}`;
15324
+ if (!nodes.some((n) => n["id"] === pkgId)) {
15325
+ nodes.push({ id: pkgId, label: pkg });
15326
+ }
15327
+ edges.push({ source: de, target: pkgId, relation: "imports" });
15328
+ }
15329
+ }
15330
+ const sanitizado = sanitizarGrafo({ nodes, edges, pacotes: [...pacotes] });
15038
15331
  if (!sanitizado.ok || !sanitizado.grafo.avancado) return null;
15039
15332
  return sanitizado.grafo;
15040
15333
  }
@@ -15102,6 +15395,7 @@ async function acompanhar(liveUrl, scanId, shareToken) {
15102
15395
  }
15103
15396
  async function main(argv) {
15104
15397
  const ci = temFlag("--ci", argv) || process.env["CI"] === "true" || process.env["VIBECHECK_TOKEN"] !== void 0 && process.env["VIBECHECK_TOKEN"].length > 0;
15398
+ const noWait = temFlag("--no-wait", argv);
15105
15399
  const raiz = arg("--dir", argv) ?? process.cwd();
15106
15400
  let url2 = arg("--url", argv) ?? argv.find((a) => a.startsWith("http")) ?? null;
15107
15401
  let cred = lerToken();
@@ -15142,6 +15436,9 @@ async function main(argv) {
15142
15436
  console.error(corpo.error ?? "n\xE3o foi poss\xEDvel abrir o scan");
15143
15437
  return 1;
15144
15438
  }
15439
+ const live = corpo.liveUrl ?? `${base}/avancado/${corpo.scanId}`;
15440
+ console.warn(live);
15441
+ if (deveAbrirNavegador({ ci, noWait })) await abrirBrowser(live);
15145
15442
  if (avancado && grafo !== null) {
15146
15443
  const put = await fetch(`${base}/api/cli/scan/${corpo.scanId}/graph`, {
15147
15444
  method: "PUT",
@@ -15150,9 +15447,7 @@ async function main(argv) {
15150
15447
  });
15151
15448
  if (!put.ok) console.warn("grafo rejeitado pelo servidor \u2014 scan segue s\xF3 HTTP");
15152
15449
  }
15153
- const live = corpo.liveUrl ?? `${base}/avancado/${corpo.scanId}`;
15154
- console.warn(live);
15155
- if (temFlag("--no-wait", argv)) return 0;
15450
+ if (noWait) return 0;
15156
15451
  return acompanhar(live, corpo.scanId, corpo.shareToken ?? "");
15157
15452
  }
15158
15453
  var codigo = await main(process.argv.slice(2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kinkai.cloud/vibecheck",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {