@chappibunny/repolens 0.8.0 → 1.0.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.
@@ -1,5 +1,6 @@
1
1
  import { ensurePage, replacePageContent } from "./notion.js";
2
2
  import { getCurrentBranch, getBranchQualifiedTitle } from "../utils/branch.js";
3
+ import { warn } from "../utils/logger.js";
3
4
 
4
5
  export async function publishToNotion(cfg, renderedPages) {
5
6
  const parentPageId = process.env.NOTION_PARENT_PAGE_ID;
@@ -22,7 +23,7 @@ export async function publishToNotion(cfg, renderedPages) {
22
23
 
23
24
  // Skip if content not generated (e.g., disabled feature or generation error)
24
25
  if (!markdown) {
25
- console.log(`⚠️ Skipping ${page.key}: No content generated`);
26
+ warn(`Skipping ${page.key}: No content generated`);
26
27
  continue;
27
28
  }
28
29
 
@@ -1,193 +1,232 @@
1
1
  export function renderSystemOverview(cfg, scan) {
2
- const notes = [];
3
-
4
- // Generate meaningful notes based on detected metadata
5
- if (scan.metadata?.frameworks?.length) {
6
- notes.push(`Tech Stack: ${scan.metadata.frameworks.join(", ")}`);
7
- }
8
-
9
- if (scan.metadata?.languages?.size) {
10
- notes.push(`Languages: ${[...scan.metadata.languages].join(", ")}`);
11
- }
12
-
13
- if (scan.metadata?.buildTools?.length) {
14
- notes.push(`Build Tools: ${scan.metadata.buildTools.join(", ")}`);
15
- }
16
-
17
- if (scan.metadata?.testFrameworks?.length) {
18
- notes.push(`Testing: ${scan.metadata.testFrameworks.join(", ")}`);
19
- }
20
-
21
- // Add architectural insights
22
- if (scan.modules.length > 50) {
23
- notes.push(`Architecture: Large modular codebase with ${scan.modules.length} identified modules`);
24
- } else if (scan.modules.length > 20) {
25
- notes.push(`Architecture: Medium-sized modular structure with ${scan.modules.length} modules`);
26
- } else if (scan.modules.length > 0) {
27
- notes.push(`Architecture: Compact modular design with ${scan.modules.length} modules`);
28
- }
29
-
30
- if (scan.api?.length > 0) {
31
- notes.push(`API Coverage: ${scan.api.length} API endpoints detected`);
32
- }
33
-
34
- if (scan.pages?.length > 0) {
35
- notes.push(`UI Pages: ${scan.pages.length} application pages detected`);
36
- }
37
-
38
- // If no meaningful data, show default message
39
- if (notes.length === 0) {
40
- notes.push("This is an overview based on filesystem heuristics. Add a package.json to see framework and tooling details.");
41
- }
42
-
43
- return [
44
- `# ${cfg.project.name} — System Overview`,
45
- ``,
46
- `\`\`\``,
47
- `██████╗ ███████╗██████╗ ██████╗ ██╗ ███████╗███╗ ██╗███████╗`,
48
- `██╔══██╗██╔════╝██╔══██╗██╔═══██╗██║ ██╔════╝████╗ ██║██╔════╝`,
49
- `██████╔╝█████╗ ██████╔╝██║ ██║██║ █████╗ ██╔██╗ ██║███████╗`,
50
- `██╔══██╗██╔══╝ ██╔═══╝ ██║ ██║██║ ██╔══╝ ██║╚██╗██║╚════██║`,
51
- `██║ ██║███████╗██║ ╚██████╔╝███████╗███████╗██║ ╚████║███████║`,
52
- `╚═╝ ╚═╝╚══════╝╚═╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═══╝╚══════╝`,
53
- ` 🔍 Repository Intelligence by RABITAI 🐰`,
54
- `\`\`\``,
2
+ const projectName = cfg.project?.name || "Project";
3
+ const date = new Date().toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
4
+
5
+ const lines = [
6
+ `# ${projectName} — System Overview`,
55
7
  ``,
56
- `What is this? This page provides a high-level snapshot of your codebase structure, showing what technologies you're using and how your code is organized.`,
8
+ `> This page provides a high-level snapshot of the codebase, including its technology stack, structural composition, and scale. It is generated automatically by RepoLens and updated on every publish.`,
57
9
  ``,
58
- `📊 Last Updated: ${new Date().toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" })}`,
10
+ `**Last Updated:** ${date}`,
59
11
  ``,
60
12
  `---`,
61
13
  ``,
62
- `## 📸 Quick Stats`,
63
- ``,
64
- `Here's what we found in your repository:`,
65
- ``,
66
- `- ${scan.filesCount} files scanned across your codebase`,
67
- `- ${scan.modules.length} modules (major code sections) detected`,
68
- `- ${scan.pages?.length || 0} pages in your application`,
69
- `- ${scan.api.length} API endpoints for backend functionality`,
70
- ``,
71
- `## 📦 Largest Modules`,
72
- ``,
73
- `These are your biggest code modules (folders with the most files):`,
74
- ``,
75
- ...(scan.modules.slice(0, 10).map((m) => `- \`${m.key}\` contains ${m.fileCount} files`)),
76
- ``,
77
- `## 🔧 Technology Stack`,
78
- ``,
79
- `Your project uses these technologies:`,
80
- ``,
81
- ...notes.map(note => note),
14
+ `## Repository at a Glance`,
82
15
  ``,
16
+ `| Metric | Value |`,
17
+ `|--------|-------|`,
18
+ `| Files scanned | ${scan.filesCount} |`,
19
+ `| Modules detected | ${scan.modules.length} |`,
20
+ `| Application pages | ${scan.pages?.length || 0} |`,
21
+ `| API endpoints | ${scan.api.length} |`,
22
+ ``
23
+ ];
24
+
25
+ // Technology stack as a proper section with prose
26
+ const frameworks = scan.metadata?.frameworks || [];
27
+ const languages = scan.metadata?.languages ? [...scan.metadata.languages] : [];
28
+ const buildTools = scan.metadata?.buildTools || [];
29
+ const testFrameworks = scan.metadata?.testFrameworks || [];
30
+
31
+ if (frameworks.length || languages.length || buildTools.length || testFrameworks.length) {
32
+ lines.push(
33
+ `## Technology Stack`,
34
+ ``,
35
+ `| Category | Technologies |`,
36
+ `|----------|-------------|`
37
+ );
38
+ if (frameworks.length) lines.push(`| Frameworks | ${frameworks.join(", ")} |`);
39
+ if (languages.length) lines.push(`| Languages | ${languages.join(", ")} |`);
40
+ if (buildTools.length) lines.push(`| Build Tools | ${buildTools.join(", ")} |`);
41
+ if (testFrameworks.length) lines.push(`| Testing | ${testFrameworks.join(", ")} |`);
42
+ lines.push(``);
43
+ }
44
+
45
+ // Architecture summary as descriptive prose
46
+ if (scan.modules.length > 0) {
47
+ let sizeDesc;
48
+ if (scan.modules.length > 50) sizeDesc = "a large, modular codebase";
49
+ else if (scan.modules.length > 20) sizeDesc = "a medium-sized modular codebase";
50
+ else sizeDesc = "a focused, compact codebase";
51
+
52
+ lines.push(
53
+ `## Architecture Summary`,
54
+ ``,
55
+ `The repository is organized as ${sizeDesc} with **${scan.modules.length} modules** spanning **${scan.filesCount} files**. `
56
+ + (scan.api.length > 0 ? `It exposes **${scan.api.length} API endpoint${scan.api.length === 1 ? "" : "s"}** ` : "")
57
+ + (scan.pages?.length > 0 ? `and serves **${scan.pages.length} application page${scan.pages.length === 1 ? "" : "s"}**. ` : ". ")
58
+ + `The largest modules are listed below, ranked by file count.`,
59
+ ``
60
+ );
61
+ }
62
+
63
+ // Largest modules as a table instead of bullets
64
+ const topModules = scan.modules.slice(0, 10);
65
+ if (topModules.length > 0) {
66
+ lines.push(
67
+ `## Largest Modules`,
68
+ ``,
69
+ `| Module | Files | Description |`,
70
+ `|--------|-------|-------------|`
71
+ );
72
+ for (const m of topModules) {
73
+ const desc = describeModule(m.key);
74
+ lines.push(`| \`${m.key}\` | ${m.fileCount} | ${desc} |`);
75
+ }
76
+ lines.push(``);
77
+ }
78
+
79
+ lines.push(
83
80
  `---`,
84
81
  ``,
85
- `💡 Tip: This documentation auto-updates on every push to your main branch!`,
82
+ `*This documentation is generated automatically by [RepoLens](https://github.com/CHAPIBUNNY/repolens) and refreshes on every push to the main branch.*`,
86
83
  ``
87
- ].join("\n");
84
+ );
85
+
86
+ return lines.join("\n");
87
+ }
88
+
89
+ function describeModule(key) {
90
+ const normalized = key.toLowerCase();
91
+ if (normalized.includes("core")) return "Core business logic and shared foundations";
92
+ if (normalized.includes("util")) return "Shared utilities and helper functions";
93
+ if (normalized.includes("api")) return "API route handlers and endpoint definitions";
94
+ if (normalized.includes("component")) return "Reusable UI components";
95
+ if (normalized.includes("hook")) return "Custom React hooks";
96
+ if (normalized.includes("page")) return "Application page components";
97
+ if (normalized.includes("lib")) return "Library code and third-party integrations";
98
+ if (normalized.includes("service")) return "Service layer and external integrations";
99
+ if (normalized.includes("model")) return "Data models and schema definitions";
100
+ if (normalized.includes("store") || normalized.includes("state")) return "State management";
101
+ if (normalized.includes("config")) return "Configuration and settings";
102
+ if (normalized.includes("test")) return "Test suites and fixtures";
103
+ if (normalized.includes("style") || normalized.includes("css")) return "Styling and design tokens";
104
+ if (normalized.includes("type")) return "Type definitions and interfaces";
105
+ if (normalized.includes("middleware")) return "Request middleware and interceptors";
106
+ if (normalized.includes("auth")) return "Authentication and authorization";
107
+ if (normalized.includes("render")) return "Rendering logic and output formatters";
108
+ if (normalized.includes("publish")) return "Publishing and delivery integrations";
109
+ if (normalized.includes("analyz")) return "Code analysis and intelligence";
110
+ if (normalized.includes("delivery")) return "Content delivery and distribution";
111
+ if (normalized.includes("integrat")) return "Third-party service integrations";
112
+ if (normalized.includes("doc")) return "Documentation generation";
113
+ if (normalized.includes("bin") || normalized.includes("cli")) return "CLI entry point and commands";
114
+ return "Application module";
88
115
  }
89
116
 
90
117
  export function renderModuleCatalog(cfg, scan) {
91
118
  const lines = [
92
- `# 📁 Module Catalog`,
119
+ `# Module Catalog`,
93
120
  ``,
94
- `What is this? This is a complete inventory of all code modules (folders) in your project, showing how your codebase is organized.`,
121
+ `> A complete inventory of all code modules in the repository, organized by location and size. Each module represents a distinct area of responsibility within the codebase.`,
95
122
  ``,
96
- `Total modules found: ${scan.modules.length}`,
123
+ `**Total modules:** ${scan.modules.length}`,
97
124
  ``,
98
125
  `---`,
99
- ``,
100
- `## All Modules`,
101
- ``,
102
- `Each module represents a major section of your codebase. The file count shows relative size:`,
103
126
  ``
104
127
  ];
105
128
 
106
129
  if (!scan.modules.length) {
107
- lines.push(`No modules detected. Configure \`module_roots\` in \`.repolens.yml\` to organize your code.`, ``);
130
+ lines.push(
131
+ `No modules detected. Configure \`module_roots\` in \`.repolens.yml\` to define the top-level directories that organize your source code.`,
132
+ ``
133
+ );
108
134
  return lines.join("\n");
109
135
  }
110
136
 
137
+ lines.push(
138
+ `## Module Inventory`,
139
+ ``,
140
+ `| Module | Files | Role |`,
141
+ `|--------|-------|------|`
142
+ );
143
+
111
144
  for (const module of scan.modules.slice(0, 100)) {
112
- lines.push(`- \`${module.key}\` ${module.fileCount} files`);
145
+ const desc = describeModule(module.key);
146
+ lines.push(`| \`${module.key}\` | ${module.fileCount} | ${desc} |`);
113
147
  }
114
148
 
115
149
  if (scan.modules.length > 100) {
116
- lines.push(``, `_(Showing top 100 of ${scan.modules.length} modules)_`);
150
+ lines.push(``, `*Showing the top 100 of ${scan.modules.length} modules.*`);
117
151
  }
118
152
 
119
- lines.push(``, `---`, ``, `💡 Tip: Click any module name to see its location in your codebase.`, ``);
153
+ lines.push(
154
+ ``,
155
+ `---`,
156
+ ``,
157
+ `*Module detection is based on the \`module_roots\` setting in your RepoLens configuration. Adjust this setting to change how modules are grouped.*`,
158
+ ``
159
+ );
120
160
 
121
161
  return lines.join("\n");
122
162
  }
123
163
 
124
164
  export function renderApiSurface(cfg, scan) {
125
165
  const lines = [
126
- `# 🔌 API Surface`,
166
+ `# API Surface`,
127
167
  ``,
128
- `What is this? This page shows both the API endpoints your application provides AND the external APIs it integrates with.`,
168
+ `> This page documents both the API endpoints the application exposes and the external services it integrates with. Use it as a reference for understanding the system's interfaces.`,
129
169
  ``,
130
170
  `---`,
131
171
  ``
132
172
  ];
133
173
 
134
- // Section 1: Internal API Endpoints (what we expose)
174
+ // Section 1: Internal API Endpoints
135
175
  lines.push(
136
176
  `## Internal API Endpoints`,
137
177
  ``,
138
- `These are the backend services your application provides to handle requests.`,
139
- ``,
140
- `Total endpoints: ${scan.api.length}`,
178
+ `These are the backend services the application provides to handle incoming requests.`,
141
179
  ``
142
180
  );
143
181
 
144
182
  if (!scan.api.length) {
145
183
  lines.push(
146
- `No API routes detected. Your project doesn't appear to have Next.js API routes yet.`,
184
+ `No API routes were detected in this scan. If your project uses a routing framework (Express, Fastify, NestJS, etc.), ensure the relevant directories are included in your \`scan.include\` patterns.`,
147
185
  ``
148
186
  );
149
187
  } else {
150
188
  lines.push(
151
- `Each line shows: HTTP Method → API Path → Implementation File`,
152
- ``
189
+ `**Total endpoints:** ${scan.api.length}`,
190
+ ``,
191
+ `| Method | Path | Implementation |`,
192
+ `|--------|------|----------------|`
153
193
  );
154
194
 
155
195
  for (const route of scan.api) {
156
- lines.push(`- ${route.methods.join(", ")} \`${route.path}\` \`${route.file}\``);
196
+ lines.push(`| ${route.methods.join(", ")} | \`${route.path}\` | \`${route.file}\` |`);
157
197
  }
158
-
198
+
159
199
  lines.push(``);
160
200
  }
161
201
 
162
- // Section 2: External API Integrations (what we call)
202
+ // Section 2: External API Integrations
163
203
  lines.push(
164
204
  `---`,
165
205
  ``,
166
206
  `## External API Integrations`,
167
207
  ``,
168
- `These are third-party services your application connects to.`,
208
+ `Third-party services the application connects to, grouped by category.`,
169
209
  ``
170
210
  );
171
211
 
172
212
  if (!scan.externalApis || scan.externalApis.length === 0) {
173
213
  lines.push(
174
- `No external API integrations detected.`,
214
+ `No external API integrations were detected. This section populates automatically when RepoLens identifies SDK imports or API client usage in your codebase.`,
175
215
  ``
176
216
  );
177
217
  } else {
178
- // Group by category
179
218
  const byCategory = {};
180
219
  for (const api of scan.externalApis) {
181
- if (!byCategory[api.category]) {
182
- byCategory[api.category] = [];
183
- }
220
+ if (!byCategory[api.category]) byCategory[api.category] = [];
184
221
  byCategory[api.category].push(api);
185
222
  }
186
223
 
187
224
  for (const [category, apis] of Object.entries(byCategory)) {
188
225
  lines.push(`### ${category}`, ``);
226
+ lines.push(`| Service | Detected In |`);
227
+ lines.push(`|---------|-------------|`);
189
228
  for (const api of apis) {
190
- lines.push(`- **${api.name}** detected in \`${api.detectedIn}\``);
229
+ lines.push(`| ${api.name} | \`${api.detectedIn}\` |`);
191
230
  }
192
231
  lines.push(``);
193
232
  }
@@ -196,10 +235,7 @@ export function renderApiSurface(cfg, scan) {
196
235
  lines.push(
197
236
  `---`,
198
237
  ``,
199
- `💡 Tips:`,
200
- `- **Internal endpoints** handle incoming requests from users/clients`,
201
- `- **External integrations** connect your app to third-party services`,
202
- `- HTTP methods: GET (retrieve), POST (create), PUT/PATCH (update), DELETE (remove)`,
238
+ `*HTTP method reference — GET: retrieve data, POST: create, PUT/PATCH: update, DELETE: remove.*`,
203
239
  ``
204
240
  );
205
241
 
@@ -208,9 +244,9 @@ export function renderApiSurface(cfg, scan) {
208
244
 
209
245
  export function renderRouteMap(cfg, scan) {
210
246
  const lines = [
211
- `# 🗺️ Route Map`,
247
+ `# Route Map`,
212
248
  ``,
213
- `What is this? This page shows all the pages (URLs) users can visit in your application, plus the backend API endpoints that power them.`,
249
+ `> A complete listing of user-facing pages and backend API endpoints. This map shows every URL a user or client can interact with, along with the source file that handles each route.`,
214
250
  ``,
215
251
  `---`,
216
252
  ``
@@ -218,14 +254,16 @@ export function renderRouteMap(cfg, scan) {
218
254
 
219
255
  if (scan.pages?.length) {
220
256
  lines.push(
221
- `## 🏠 Application Pages (${scan.pages.length})`,
257
+ `## Application Pages (${scan.pages.length})`,
222
258
  ``,
223
- `These are the user-facing pages in your app:`,
224
- ``
259
+ `These are the user-facing views in the application. Each row maps a URL path to its implementing component.`,
260
+ ``,
261
+ `| Path | Source File |`,
262
+ `|------|------------|`
225
263
  );
226
264
 
227
265
  for (const page of scan.pages.slice(0, 200)) {
228
- lines.push(`- \`${page.path}\` \`${page.file}\``);
266
+ lines.push(`| \`${page.path}\` | \`${page.file}\` |`);
229
267
  }
230
268
 
231
269
  lines.push(``);
@@ -233,14 +271,16 @@ export function renderRouteMap(cfg, scan) {
233
271
 
234
272
  if (scan.api?.length) {
235
273
  lines.push(
236
- `## 🔌 API Endpoints (${scan.api.length})`,
274
+ `## API Endpoints (${scan.api.length})`,
237
275
  ``,
238
- `These are backend services that handle data operations:`,
239
- ``
276
+ `Backend services that handle data operations and business logic.`,
277
+ ``,
278
+ `| Method | Path | Source File |`,
279
+ `|--------|------|------------|`
240
280
  );
241
281
 
242
282
  for (const route of scan.api.slice(0, 200)) {
243
- lines.push(`- ${route.methods.join(", ")} \`${route.path}\` \`${route.file}\``);
283
+ lines.push(`| ${route.methods.join(", ")} | \`${route.path}\` | \`${route.file}\` |`);
244
284
  }
245
285
 
246
286
  lines.push(``);
@@ -248,29 +288,19 @@ export function renderRouteMap(cfg, scan) {
248
288
 
249
289
  if (!scan.pages?.length && !scan.api?.length) {
250
290
  lines.push(
251
- `## 🔍 Route Detection Status`,
252
- ``,
253
- `No routes were auto-detected in this scan. RABITAI currently supports:`,
254
- ``,
255
- `✅ **Fully Supported:**`,
256
- `- Next.js pages (\`pages/\` and \`app/\` directories)`,
257
- `- Next.js API routes (\`pages/api/\` and App Router)`,
258
- `- Express.js routes (\`app.get\`, \`router.post\`, etc.)`,
259
- `- React Router (\`<Route>\` components)`,
260
- `- Vue Router (\`routes\` array definitions)`,
291
+ `## Route Detection`,
261
292
  ``,
262
- `⏳ **Coming Soon:**`,
263
- `- Fastify routes`,
264
- `- NestJS controllers`,
265
- `- GraphQL endpoints`,
266
- `- tRPC procedures`,
293
+ `No routes were auto-detected in this scan. RepoLens currently supports:`,
267
294
  ``,
268
- `💡 **Your project may:**`,
269
- `- Use a different routing framework (let us know!)`,
270
- `- Have routes outside the scanned directories`,
271
- `- Use dynamic routing patterns we haven't detected yet`,
295
+ `| Framework | Pattern | Status |`,
296
+ `|-----------|---------|--------|`,
297
+ `| Next.js | \`pages/\` and \`app/\` directories | Supported |`,
298
+ `| Next.js API | \`pages/api/\` and App Router | Supported |`,
299
+ `| Express.js | \`app.get\`, \`router.post\`, etc. | Supported |`,
300
+ `| React Router | \`<Route>\` components | Supported |`,
301
+ `| Vue Router | \`routes\` array definitions | Supported |`,
272
302
  ``,
273
- `📬 **Request Support:** Open an issue at [github.com/CHAPIBUNNY/repolens](https://github.com/CHAPIBUNNY/repolens/issues) to request your framework!`,
303
+ `If your project uses a different routing framework, open an issue at [github.com/CHAPIBUNNY/repolens](https://github.com/CHAPIBUNNY/repolens/issues) to request support.`,
274
304
  ``
275
305
  );
276
306
  }
@@ -278,7 +308,7 @@ export function renderRouteMap(cfg, scan) {
278
308
  lines.push(
279
309
  `---`,
280
310
  ``,
281
- `💡 Tip: URL paths starting with \`/api/\` are backend endpoints, others are user-facing pages.`,
311
+ `*Paths starting with \`/api/\` are backend endpoints; all others are user-facing pages.*`,
282
312
  ``
283
313
  );
284
314