gpt-engineer-app[bot] commited on
Commit
45afc75
·
1 Parent(s): 27ad1c9
Files changed (2) hide show
  1. cli/eventdash-debug.mjs +122 -0
  2. src/routeTree.gen.ts +21 -0
cli/eventdash-debug.mjs ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env node
2
+ // EventDash Branch Debug CLI
3
+ //
4
+ // Usage (from your repo root, in the VS Code terminal):
5
+ // node ./cli/eventdash-debug.mjs "API throws 500 on /checkout for Amex cards"
6
+ // node ./cli/eventdash-debug.mjs --base origin/main "describe the failure here"
7
+ // node ./cli/eventdash-debug.mjs --editor cursor "..."
8
+ //
9
+ // Flags:
10
+ // --base <ref> Diff base. Default: auto-detects merge-base with origin/main, falls back to HEAD~1.
11
+ // --editor <id> vscode | cursor. Default: vscode.
12
+ // --endpoint <url> Override API endpoint.
13
+ //
14
+ // Reads LOVABLE_ENDPOINT from env if --endpoint is not passed.
15
+
16
+ import { execSync } from "node:child_process";
17
+ import { resolve } from "node:path";
18
+
19
+ const DEFAULT_ENDPOINT =
20
+ process.env.LOVABLE_ENDPOINT ||
21
+ "https://project--bff39f15-1e2d-4d34-8f4b-7070bac6dbae.lovable.app/api/public/branch-debug";
22
+
23
+ const args = process.argv.slice(2);
24
+ const opts = { base: null, editor: "vscode", endpoint: DEFAULT_ENDPOINT };
25
+ const positional = [];
26
+ for (let i = 0; i < args.length; i++) {
27
+ const a = args[i];
28
+ if (a === "--base") opts.base = args[++i];
29
+ else if (a === "--editor") opts.editor = args[++i];
30
+ else if (a === "--endpoint") opts.endpoint = args[++i];
31
+ else if (a === "-h" || a === "--help") {
32
+ console.log("Usage: node cli/eventdash-debug.mjs [--base <ref>] [--editor vscode|cursor] [--endpoint <url>] \"failure description\"");
33
+ process.exit(0);
34
+ } else positional.push(a);
35
+ }
36
+
37
+ const failureDescription = positional.join(" ").trim();
38
+ if (!failureDescription) {
39
+ console.error("✗ Provide a failure description as an argument.");
40
+ console.error(' e.g. node cli/eventdash-debug.mjs "Checkout 500s on Amex cards after deploy"');
41
+ process.exit(1);
42
+ }
43
+
44
+ function sh(cmd) {
45
+ return execSync(cmd, { encoding: "utf8", maxBuffer: 50 * 1024 * 1024 }).trim();
46
+ }
47
+
48
+ let repoRoot;
49
+ let branch;
50
+ try {
51
+ repoRoot = sh("git rev-parse --show-toplevel");
52
+ branch = sh("git rev-parse --abbrev-ref HEAD");
53
+ } catch {
54
+ console.error("✗ Not inside a git repo. Run this from your project root.");
55
+ process.exit(1);
56
+ }
57
+
58
+ // Determine base ref
59
+ let base = opts.base;
60
+ if (!base) {
61
+ for (const candidate of ["origin/main", "origin/master", "main", "master"]) {
62
+ try {
63
+ base = sh(`git merge-base HEAD ${candidate}`);
64
+ break;
65
+ } catch { /* try next */ }
66
+ }
67
+ if (!base) base = "HEAD~1";
68
+ }
69
+
70
+ console.log(`▸ Repo: ${repoRoot}`);
71
+ console.log(`▸ Branch: ${branch}`);
72
+ console.log(`▸ Base: ${base}`);
73
+ console.log(`▸ Failure: ${failureDescription}\n`);
74
+
75
+ let diff;
76
+ try {
77
+ diff = sh(`git diff ${base}...HEAD`);
78
+ } catch (e) {
79
+ console.error("✗ git diff failed:", e.message);
80
+ process.exit(1);
81
+ }
82
+
83
+ if (!diff) {
84
+ console.error("✗ Empty diff. Nothing changed between base and HEAD.");
85
+ process.exit(1);
86
+ }
87
+
88
+ console.log(`▸ Sending ${(diff.length / 1024).toFixed(1)} KB diff to ${opts.endpoint} ...\n`);
89
+
90
+ const res = await fetch(opts.endpoint, {
91
+ method: "POST",
92
+ headers: { "Content-Type": "application/json" },
93
+ body: JSON.stringify({ diff, failureDescription, repoRoot, editor: opts.editor }),
94
+ });
95
+
96
+ if (!res.ok) {
97
+ const text = await res.text();
98
+ console.error(`✗ API error ${res.status}: ${text}`);
99
+ process.exit(1);
100
+ }
101
+
102
+ const data = await res.json();
103
+ const { summary, suspects, sanitizationStats } = data;
104
+
105
+ const C = { dim: "\x1b[2m", reset: "\x1b[0m", bold: "\x1b[1m", high: "\x1b[31m", med: "\x1b[33m", low: "\x1b[36m", link: "\x1b[34m" };
106
+ const tag = (c) => ({ high: C.high, medium: C.med, low: C.low }[c] || "");
107
+
108
+ console.log(`${C.bold}Summary${C.reset}\n ${summary}\n`);
109
+ console.log(`${C.dim}IP Shield: ${sanitizationStats.identifiersTokenized} identifiers tokenized · ${sanitizationStats.commentsStripped} comments stripped · ${sanitizationStats.secretsBlocked} secrets blocked${C.reset}\n`);
110
+
111
+ if (!suspects?.length) {
112
+ console.log("No suspects returned.");
113
+ process.exit(0);
114
+ }
115
+
116
+ suspects.forEach((s, i) => {
117
+ const jump = s.jumpUrl || `${opts.editor}://file/${resolve(repoRoot, s.filePath)}:${s.lineStart}`;
118
+ console.log(`${tag(s.confidence)}${C.bold}[${i + 1}] ${s.confidence.toUpperCase()}${C.reset} ${s.filePath}:${s.lineStart}-${s.lineEnd}${s.functionName ? ` ${C.dim}(${s.functionName})${C.reset}` : ""}`);
119
+ console.log(` ${C.bold}${s.changeSummary}${C.reset}`);
120
+ console.log(` ${s.mechanism}`);
121
+ console.log(` ${C.link}${jump}${C.reset} ${C.dim}← ⌘-click to open in ${opts.editor === "cursor" ? "Cursor" : "VS Code"}${C.reset}\n`);
122
+ });
src/routeTree.gen.ts CHANGED
@@ -17,6 +17,7 @@ import { Route as DashboardReportsRouteImport } from './routes/dashboard.reports
17
  import { Route as DashboardComplianceRouteImport } from './routes/dashboard.compliance'
18
  import { Route as DashboardCoachingRouteImport } from './routes/dashboard.coaching'
19
  import { Route as DashboardBranchDebugRouteImport } from './routes/dashboard.branch-debug'
 
20
 
21
  const DashboardRoute = DashboardRouteImport.update({
22
  id: '/dashboard',
@@ -58,6 +59,11 @@ const DashboardBranchDebugRoute = DashboardBranchDebugRouteImport.update({
58
  path: '/branch-debug',
59
  getParentRoute: () => DashboardRoute,
60
  } as any)
 
 
 
 
 
61
 
62
  export interface FileRoutesByFullPath {
63
  '/': typeof IndexRoute
@@ -68,6 +74,7 @@ export interface FileRoutesByFullPath {
68
  '/dashboard/compliance': typeof DashboardComplianceRoute
69
  '/dashboard/reports': typeof DashboardReportsRoute
70
  '/dashboard/': typeof DashboardIndexRoute
 
71
  }
72
  export interface FileRoutesByTo {
73
  '/': typeof IndexRoute
@@ -77,6 +84,7 @@ export interface FileRoutesByTo {
77
  '/dashboard/compliance': typeof DashboardComplianceRoute
78
  '/dashboard/reports': typeof DashboardReportsRoute
79
  '/dashboard': typeof DashboardIndexRoute
 
80
  }
81
  export interface FileRoutesById {
82
  __root__: typeof rootRouteImport
@@ -88,6 +96,7 @@ export interface FileRoutesById {
88
  '/dashboard/compliance': typeof DashboardComplianceRoute
89
  '/dashboard/reports': typeof DashboardReportsRoute
90
  '/dashboard/': typeof DashboardIndexRoute
 
91
  }
92
  export interface FileRouteTypes {
93
  fileRoutesByFullPath: FileRoutesByFullPath
@@ -100,6 +109,7 @@ export interface FileRouteTypes {
100
  | '/dashboard/compliance'
101
  | '/dashboard/reports'
102
  | '/dashboard/'
 
103
  fileRoutesByTo: FileRoutesByTo
104
  to:
105
  | '/'
@@ -109,6 +119,7 @@ export interface FileRouteTypes {
109
  | '/dashboard/compliance'
110
  | '/dashboard/reports'
111
  | '/dashboard'
 
112
  id:
113
  | '__root__'
114
  | '/'
@@ -119,12 +130,14 @@ export interface FileRouteTypes {
119
  | '/dashboard/compliance'
120
  | '/dashboard/reports'
121
  | '/dashboard/'
 
122
  fileRoutesById: FileRoutesById
123
  }
124
  export interface RootRouteChildren {
125
  IndexRoute: typeof IndexRoute
126
  AuthRoute: typeof AuthRoute
127
  DashboardRoute: typeof DashboardRouteWithChildren
 
128
  }
129
 
130
  declare module '@tanstack/react-router' {
@@ -185,6 +198,13 @@ declare module '@tanstack/react-router' {
185
  preLoaderRoute: typeof DashboardBranchDebugRouteImport
186
  parentRoute: typeof DashboardRoute
187
  }
 
 
 
 
 
 
 
188
  }
189
  }
190
 
@@ -212,6 +232,7 @@ const rootRouteChildren: RootRouteChildren = {
212
  IndexRoute: IndexRoute,
213
  AuthRoute: AuthRoute,
214
  DashboardRoute: DashboardRouteWithChildren,
 
215
  }
216
  export const routeTree = rootRouteImport
217
  ._addFileChildren(rootRouteChildren)
 
17
  import { Route as DashboardComplianceRouteImport } from './routes/dashboard.compliance'
18
  import { Route as DashboardCoachingRouteImport } from './routes/dashboard.coaching'
19
  import { Route as DashboardBranchDebugRouteImport } from './routes/dashboard.branch-debug'
20
+ import { Route as ApiPublicBranchDebugRouteImport } from './routes/api/public/branch-debug'
21
 
22
  const DashboardRoute = DashboardRouteImport.update({
23
  id: '/dashboard',
 
59
  path: '/branch-debug',
60
  getParentRoute: () => DashboardRoute,
61
  } as any)
62
+ const ApiPublicBranchDebugRoute = ApiPublicBranchDebugRouteImport.update({
63
+ id: '/api/public/branch-debug',
64
+ path: '/api/public/branch-debug',
65
+ getParentRoute: () => rootRouteImport,
66
+ } as any)
67
 
68
  export interface FileRoutesByFullPath {
69
  '/': typeof IndexRoute
 
74
  '/dashboard/compliance': typeof DashboardComplianceRoute
75
  '/dashboard/reports': typeof DashboardReportsRoute
76
  '/dashboard/': typeof DashboardIndexRoute
77
+ '/api/public/branch-debug': typeof ApiPublicBranchDebugRoute
78
  }
79
  export interface FileRoutesByTo {
80
  '/': typeof IndexRoute
 
84
  '/dashboard/compliance': typeof DashboardComplianceRoute
85
  '/dashboard/reports': typeof DashboardReportsRoute
86
  '/dashboard': typeof DashboardIndexRoute
87
+ '/api/public/branch-debug': typeof ApiPublicBranchDebugRoute
88
  }
89
  export interface FileRoutesById {
90
  __root__: typeof rootRouteImport
 
96
  '/dashboard/compliance': typeof DashboardComplianceRoute
97
  '/dashboard/reports': typeof DashboardReportsRoute
98
  '/dashboard/': typeof DashboardIndexRoute
99
+ '/api/public/branch-debug': typeof ApiPublicBranchDebugRoute
100
  }
101
  export interface FileRouteTypes {
102
  fileRoutesByFullPath: FileRoutesByFullPath
 
109
  | '/dashboard/compliance'
110
  | '/dashboard/reports'
111
  | '/dashboard/'
112
+ | '/api/public/branch-debug'
113
  fileRoutesByTo: FileRoutesByTo
114
  to:
115
  | '/'
 
119
  | '/dashboard/compliance'
120
  | '/dashboard/reports'
121
  | '/dashboard'
122
+ | '/api/public/branch-debug'
123
  id:
124
  | '__root__'
125
  | '/'
 
130
  | '/dashboard/compliance'
131
  | '/dashboard/reports'
132
  | '/dashboard/'
133
+ | '/api/public/branch-debug'
134
  fileRoutesById: FileRoutesById
135
  }
136
  export interface RootRouteChildren {
137
  IndexRoute: typeof IndexRoute
138
  AuthRoute: typeof AuthRoute
139
  DashboardRoute: typeof DashboardRouteWithChildren
140
+ ApiPublicBranchDebugRoute: typeof ApiPublicBranchDebugRoute
141
  }
142
 
143
  declare module '@tanstack/react-router' {
 
198
  preLoaderRoute: typeof DashboardBranchDebugRouteImport
199
  parentRoute: typeof DashboardRoute
200
  }
201
+ '/api/public/branch-debug': {
202
+ id: '/api/public/branch-debug'
203
+ path: '/api/public/branch-debug'
204
+ fullPath: '/api/public/branch-debug'
205
+ preLoaderRoute: typeof ApiPublicBranchDebugRouteImport
206
+ parentRoute: typeof rootRouteImport
207
+ }
208
  }
209
  }
210
 
 
232
  IndexRoute: IndexRoute,
233
  AuthRoute: AuthRoute,
234
  DashboardRoute: DashboardRouteWithChildren,
235
+ ApiPublicBranchDebugRoute: ApiPublicBranchDebugRoute,
236
  }
237
  export const routeTree = rootRouteImport
238
  ._addFileChildren(rootRouteChildren)