vibesane 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,8 +42,7 @@ npx vibesane | clip
42
42
 
43
43
  ```text
44
44
  vibesane: sanity check failed on http://localhost:5173 (2 error(s))
45
- error [http_error]: HTTP 500 on script /src/components/Pay.tsx - Transform failed with 1 error:
46
- [PARSE_ERROR] Expected `,` or `}` but found `Identifier`
45
+ error [http_error]: HTTP 500 on script /src/components/Pay.tsx:2:98 - [PARSE_ERROR] Expected `,` or `}` but found `Identifier`
47
46
  +-[ src/components/Pay.tsx:2:98 ]
48
47
  |
49
48
  2 | const broken = { stripeKey: "sk_live_****abcd", msg: "Olá, senha inválida" b: 2 };
@@ -56,8 +55,7 @@ error [secret_leak]: Secret leak on /src/components/Pay.tsx: Stripe secret key (
56
55
 
57
56
  AI FIX PROMPT (copy & paste into Cursor / Claude Code / Gemini CLI):
58
57
  Target: http://localhost:5173
59
- 1. [http_error] HTTP 500 on script /src/components/Pay.tsx - Transform failed with 1 error:
60
- [PARSE_ERROR] Expected `,` or `}` but found `Identifier`
58
+ 1. [http_error] HTTP 500 on script /src/components/Pay.tsx:2:98 - [PARSE_ERROR] Expected `,` or `}` but found `Identifier`
61
59
  +-[ src/components/Pay.tsx:2:98 ]
62
60
  |
63
61
  2 | const broken = { stripeKey: "sk_live_****abcd", msg: "Olá, senha inválida" b: 2 };
@@ -542,6 +542,9 @@ function parseViteErrorObject(raw) {
542
542
  }
543
543
  return null;
544
544
  }
545
+ const OXC_FRAME_HEADER_LC_RE = /^\s*(?:╭─|\+-)\[\s*[^\]]+?:(\d+):(\d+)\s*\]\s*$/;
546
+ const OXC_TRANSFORM_HEADER_RE = /^(?:x\s+)?Transform failed with \d+ errors?:$/i;
547
+ const OXC_CAUSE_LINE_RE = /^\[[A-Z][A-Z0-9_]*\]\s+\S/;
545
548
  export function extractViteErrorInfo(raw, servedRoute) {
546
549
  if (!raw) {
547
550
  return null;
@@ -557,14 +560,34 @@ export function extractViteErrorInfo(raw, servedRoute) {
557
560
  extractSafeAppPath(locFile) ??
558
561
  extractSafeAppPath(idFile) ??
559
562
  cleanServedRoute;
560
- const line = typeof payload.loc?.line === 'number' ? payload.loc.line : undefined;
561
- const column = typeof payload.loc?.column === 'number' ? payload.loc.column : undefined;
562
- const lineColSuffix = line !== undefined ? `:${line}${column !== undefined ? `:${column}` : ''}` : '';
563
- const safeLocation = safeFile ? `${safeFile}${lineColSuffix}` : '';
564
563
  const rawMsgLines = toAsciiSafe(payload.message.replace(ANSI_ESCAPE_RE, '').replace(/\r\n/g, '\n')).split('\n');
565
564
  const firstNonEmptyIdx = rawMsgLines.findIndex((line) => line.trim().length > 0);
566
565
  const firstLine = firstNonEmptyIdx !== -1 ? rawMsgLines[firstNonEmptyIdx] : '';
567
- let cleanMessage = toAsciiSafe(sanitizeSecretsInText(scrubAbsolutePathsInText(firstLine)))
566
+ let summaryLineIdx = firstNonEmptyIdx;
567
+ if (firstNonEmptyIdx !== -1 && OXC_TRANSFORM_HEADER_RE.test(firstLine.trim())) {
568
+ for (let i = firstNonEmptyIdx + 1; i < rawMsgLines.length; i++) {
569
+ if (OXC_CAUSE_LINE_RE.test(rawMsgLines[i].trim())) {
570
+ summaryLineIdx = i;
571
+ break;
572
+ }
573
+ }
574
+ }
575
+ let line = typeof payload.loc?.line === 'number' ? payload.loc.line : undefined;
576
+ let column = typeof payload.loc?.column === 'number' ? payload.loc.column : undefined;
577
+ if (line === undefined && summaryLineIdx !== -1) {
578
+ for (const afterLine of rawMsgLines.slice(summaryLineIdx + 1)) {
579
+ const match = OXC_FRAME_HEADER_LC_RE.exec(afterLine);
580
+ if (match) {
581
+ line = Number(match[1]);
582
+ column = Number(match[2]);
583
+ break;
584
+ }
585
+ }
586
+ }
587
+ const lineColSuffix = line !== undefined ? `:${line}${column !== undefined ? `:${column}` : ''}` : '';
588
+ const safeLocation = safeFile ? `${safeFile}${lineColSuffix}` : '';
589
+ const summaryRawLine = summaryLineIdx !== -1 ? rawMsgLines[summaryLineIdx] : '';
590
+ let cleanMessage = toAsciiSafe(sanitizeSecretsInText(scrubAbsolutePathsInText(summaryRawLine)))
568
591
  .replace(/\s+/g, ' ')
569
592
  .trim();
570
593
  if (/^x\s+/.test(cleanMessage)) {
@@ -583,8 +606,8 @@ export function extractViteErrorInfo(raw, servedRoute) {
583
606
  if (typeof payload.frame === 'string' && payload.frame.trim().length > 0) {
584
607
  codeFrame = formatCodeFrame(payload.frame);
585
608
  }
586
- else if (firstNonEmptyIdx !== -1 && firstNonEmptyIdx + 1 < rawMsgLines.length) {
587
- codeFrame = formatCodeFrame(rawMsgLines.slice(firstNonEmptyIdx + 1).join('\n'));
609
+ else if (summaryLineIdx !== -1 && summaryLineIdx + 1 < rawMsgLines.length) {
610
+ codeFrame = formatCodeFrame(rawMsgLines.slice(summaryLineIdx + 1).join('\n'));
588
611
  }
589
612
  return {
590
613
  summary,
@@ -597,9 +620,29 @@ export function extractViteErrorInfo(raw, servedRoute) {
597
620
  const withoutAnsi = toAsciiSafe(raw.replace(ANSI_ESCAPE_RE, '').replace(/\r\n/g, '\n'));
598
621
  const strippedTags = withoutAnsi.replace(/<[^>]*>/g, '\n');
599
622
  const rawLines = strippedTags.split('\n');
623
+ const firstMsgIdx = rawLines.findIndex((line) => {
624
+ const t = line.trim();
625
+ return (t.includes('Transform failed with') ||
626
+ t.includes('[plugin:vite:') ||
627
+ t.includes('Pre-transform error:'));
628
+ });
629
+ let promotedCauseIdx = -1;
630
+ if (firstMsgIdx !== -1 && OXC_TRANSFORM_HEADER_RE.test(rawLines[firstMsgIdx].trim())) {
631
+ for (let i = firstMsgIdx + 1; i < rawLines.length; i++) {
632
+ if (OXC_CAUSE_LINE_RE.test(rawLines[i].trim())) {
633
+ promotedCauseIdx = i;
634
+ break;
635
+ }
636
+ }
637
+ }
638
+ const summaryLineIdx = promotedCauseIdx !== -1 ? promotedCauseIdx : firstMsgIdx;
600
639
  const frameLines = [];
601
640
  const messageLines = [];
602
- for (const line of rawLines) {
641
+ if (promotedCauseIdx !== -1) {
642
+ messageLines.push(rawLines[promotedCauseIdx].trim());
643
+ }
644
+ for (let i = 0; i < rawLines.length; i++) {
645
+ const line = rawLines[i];
603
646
  const trimmedLine = line.trim();
604
647
  if (!trimmedLine) {
605
648
  continue;
@@ -607,8 +650,16 @@ export function extractViteErrorInfo(raw, servedRoute) {
607
650
  if (/^(?:>\s*)?\d+\s*\|/.test(trimmedLine) ||
608
651
  /^\|\s*\^/.test(trimmedLine) ||
609
652
  /^\s*[+|]-/.test(line) ||
610
- /^\s*\|/.test(line)) {
611
- frameLines.push(line);
653
+ /^\s*\|/.test(line) ||
654
+ /^\s*-+\+\s*$/.test(line)) {
655
+ if (promotedCauseIdx === -1 || i > promotedCauseIdx) {
656
+ frameLines.push(line);
657
+ }
658
+ }
659
+ else if (promotedCauseIdx !== -1) {
660
+ if (i > promotedCauseIdx && OXC_CAUSE_LINE_RE.test(trimmedLine)) {
661
+ frameLines.push(line);
662
+ }
612
663
  }
613
664
  else if (trimmedLine.includes('Transform failed with') ||
614
665
  trimmedLine.includes('[plugin:vite:') ||
@@ -617,15 +668,31 @@ export function extractViteErrorInfo(raw, servedRoute) {
617
668
  }
618
669
  }
619
670
  const baseMsg = messageLines.length > 0 ? messageLines.join(' ') : strippedTags;
620
- const cleanMessage = toAsciiSafe(sanitizeSecretsInText(scrubAbsolutePathsInText(baseMsg)))
671
+ let cleanMessage = toAsciiSafe(sanitizeSecretsInText(scrubAbsolutePathsInText(baseMsg)))
621
672
  .replace(/\s+/g, ' ')
622
673
  .trim();
674
+ if (/^x\s+/.test(cleanMessage)) {
675
+ cleanMessage = cleanMessage.replace(/^x\s+/, '').trim();
676
+ }
623
677
  if (!cleanMessage) {
624
678
  return null;
625
679
  }
680
+ let lineColSuffix = '';
681
+ if (summaryLineIdx !== -1) {
682
+ for (const afterLine of rawLines.slice(summaryLineIdx + 1)) {
683
+ const match = OXC_FRAME_HEADER_LC_RE.exec(afterLine);
684
+ if (match) {
685
+ lineColSuffix = `:${Number(match[1])}:${Number(match[2])}`;
686
+ break;
687
+ }
688
+ }
689
+ }
626
690
  const safeFile = cleanServedRoute ?? extractSafeAppPath(cleanMessage);
627
- const summary = safeFile && !cleanMessage.includes(safeFile)
628
- ? `${safeFile} - ${cleanMessage}`
691
+ const safeLocation = safeFile ? `${safeFile}${lineColSuffix}` : '';
692
+ const summary = safeLocation &&
693
+ !cleanMessage.includes(safeLocation) &&
694
+ !cleanMessage.startsWith(safeFile ?? '')
695
+ ? `${safeLocation} - ${cleanMessage}`
629
696
  : cleanMessage;
630
697
  const codeFrame = frameLines.length > 0 ? formatCodeFrame(frameLines.join('\n')) : undefined;
631
698
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibesane",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Test your vibe-coded web app in 3 seconds. Zero configs, zero setup, zero excuses.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,7 +27,7 @@
27
27
  "node": ">=22.13.0"
28
28
  },
29
29
  "bin": {
30
- "vibesane": "./bin/vibesane.js"
30
+ "vibesane": "bin/vibesane.js"
31
31
  },
32
32
  "main": "./dist/index.js",
33
33
  "types": "./dist/index.d.ts",