cmp-standards 3.3.1 → 3.4.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/index.js +85 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/db/migrations.d.ts +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +80 -0
- package/dist/db/migrations.js.map +1 -1
- package/dist/hooks/cloud-post-tool-use.d.ts +2 -1
- package/dist/hooks/cloud-post-tool-use.d.ts.map +1 -1
- package/dist/hooks/cloud-post-tool-use.js +15 -1
- package/dist/hooks/cloud-post-tool-use.js.map +1 -1
- package/dist/hooks/cloud-session-start.d.ts.map +1 -1
- package/dist/hooks/cloud-session-start.js +5 -1
- package/dist/hooks/cloud-session-start.js.map +1 -1
- package/dist/hooks/expert-review.d.ts +2 -1
- package/dist/hooks/expert-review.d.ts.map +1 -1
- package/dist/hooks/expert-review.js +61 -4
- package/dist/hooks/expert-review.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/patterns/feedback-loop.d.ts +4 -4
- package/dist/patterns/registry.d.ts +3 -3
- package/dist/schema/codewiki-types.d.ts +66 -66
- package/dist/schema/docs-types.d.ts +1253 -0
- package/dist/schema/docs-types.d.ts.map +1 -0
- package/dist/schema/docs-types.js +461 -0
- package/dist/schema/docs-types.js.map +1 -0
- package/dist/schema/expert-types.d.ts +2 -2
- package/dist/schema/opportunity-types.d.ts +67 -23
- package/dist/schema/opportunity-types.d.ts.map +1 -1
- package/dist/schema/opportunity-types.js +16 -0
- package/dist/schema/opportunity-types.js.map +1 -1
- package/dist/services/CodeWikiIndexer.d.ts +25 -3
- package/dist/services/CodeWikiIndexer.d.ts.map +1 -1
- package/dist/services/CodeWikiIndexer.js +185 -21
- package/dist/services/CodeWikiIndexer.js.map +1 -1
- package/dist/services/DocsGenerator.d.ts +78 -0
- package/dist/services/DocsGenerator.d.ts.map +1 -0
- package/dist/services/DocsGenerator.js +551 -0
- package/dist/services/DocsGenerator.js.map +1 -0
- package/dist/services/OpportunityDiscovery.d.ts +1 -0
- package/dist/services/OpportunityDiscovery.d.ts.map +1 -1
- package/dist/services/OpportunityDiscovery.js +35 -6
- package/dist/services/OpportunityDiscovery.js.map +1 -1
- package/dist/services/WikiSyncService.d.ts +110 -0
- package/dist/services/WikiSyncService.d.ts.map +1 -0
- package/dist/services/WikiSyncService.js +278 -0
- package/dist/services/WikiSyncService.js.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file DocsGenerator Service - cmp-standards v3.4
|
|
3
|
+
* @description Automated project documentation generator from CodeWiki data
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Aggregates stats from indexed files (file_metadata, code_structure)
|
|
7
|
+
* - Auto-detects features from code patterns
|
|
8
|
+
* - Generates architecture diagrams (Mermaid)
|
|
9
|
+
* - Creates simple explanations for beginners
|
|
10
|
+
* - Stores documentation as project_doc items in Turso
|
|
11
|
+
*
|
|
12
|
+
* Integration:
|
|
13
|
+
* - Consumes data from CodeWikiIndexer
|
|
14
|
+
* - Can be triggered by WikiSyncService after indexing
|
|
15
|
+
* - Provides data for web UI pages
|
|
16
|
+
*/
|
|
17
|
+
import { turso, getTurso, create } from '../db/turso-client.js';
|
|
18
|
+
import { getLogger } from '../utils/logger.js';
|
|
19
|
+
import { createProjectDoc, createEmptyStats, createEmptyArchitecture, DEFAULT_FEATURE_PATTERNS, PROJECT_CONFIGS, } from '../schema/docs-types.js';
|
|
20
|
+
const logger = getLogger();
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// DocsGenerator Service
|
|
23
|
+
// =============================================================================
|
|
24
|
+
export class DocsGenerator {
|
|
25
|
+
system;
|
|
26
|
+
featurePatterns;
|
|
27
|
+
generateSimpleExplanation;
|
|
28
|
+
constructor(options) {
|
|
29
|
+
this.system = options.system;
|
|
30
|
+
this.featurePatterns = options.featurePatterns ?? DEFAULT_FEATURE_PATTERNS;
|
|
31
|
+
this.generateSimpleExplanation = options.generateSimpleExplanation ?? true;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate full project documentation
|
|
35
|
+
*/
|
|
36
|
+
async generate() {
|
|
37
|
+
const errors = [];
|
|
38
|
+
const config = PROJECT_CONFIGS[this.system];
|
|
39
|
+
if (!config) {
|
|
40
|
+
errors.push(`No configuration found for system: ${this.system}`);
|
|
41
|
+
return {
|
|
42
|
+
doc: createProjectDoc(this.system, this.system),
|
|
43
|
+
stored: false,
|
|
44
|
+
errors,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
logger.info(`[DocsGenerator] Generating docs for ${config.name}`);
|
|
48
|
+
try {
|
|
49
|
+
// Fetch CodeWiki data
|
|
50
|
+
const fileMetadata = await this.getFileMetadata();
|
|
51
|
+
const codeStructures = await this.getCodeStructures();
|
|
52
|
+
const codeDependencies = await this.getCodeDependencies();
|
|
53
|
+
logger.info(`[DocsGenerator] Found ${fileMetadata.length} files, ${codeStructures.length} structures, ${codeDependencies.length} dependencies`);
|
|
54
|
+
// Aggregate stats
|
|
55
|
+
const stats = this.aggregateStats(fileMetadata, codeStructures, codeDependencies);
|
|
56
|
+
// Detect features
|
|
57
|
+
const features = this.detectFeatures(fileMetadata, codeStructures, codeDependencies);
|
|
58
|
+
// Detect architecture
|
|
59
|
+
const architecture = this.detectArchitecture(fileMetadata, codeStructures, codeDependencies);
|
|
60
|
+
// Try to read package.json
|
|
61
|
+
const packageInfo = await this.getPackageInfo(config.packageJsonPath);
|
|
62
|
+
// Create doc
|
|
63
|
+
const doc = createProjectDoc(this.system, config.name, {
|
|
64
|
+
slug: config.slug,
|
|
65
|
+
version: packageInfo?.version ?? '0.0.0',
|
|
66
|
+
description: config.description,
|
|
67
|
+
status: config.status,
|
|
68
|
+
category: config.category,
|
|
69
|
+
stats,
|
|
70
|
+
features,
|
|
71
|
+
architecture,
|
|
72
|
+
packageInfo,
|
|
73
|
+
links: config.links,
|
|
74
|
+
simpleExplanation: config.simpleExplanation,
|
|
75
|
+
sourceFileCount: fileMetadata.length,
|
|
76
|
+
});
|
|
77
|
+
// Store in database
|
|
78
|
+
let stored = false;
|
|
79
|
+
try {
|
|
80
|
+
await this.storeDoc(doc);
|
|
81
|
+
stored = true;
|
|
82
|
+
logger.info(`[DocsGenerator] Stored docs for ${config.name}`);
|
|
83
|
+
}
|
|
84
|
+
catch (storeError) {
|
|
85
|
+
const msg = storeError instanceof Error ? storeError.message : String(storeError);
|
|
86
|
+
errors.push(`Failed to store doc: ${msg}`);
|
|
87
|
+
logger.error(`[DocsGenerator] Store error: ${msg}`);
|
|
88
|
+
}
|
|
89
|
+
return { doc, stored, errors };
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
93
|
+
errors.push(`Generation failed: ${msg}`);
|
|
94
|
+
logger.error(`[DocsGenerator] Generate error: ${msg}`);
|
|
95
|
+
return {
|
|
96
|
+
doc: createProjectDoc(this.system, config.name),
|
|
97
|
+
stored: false,
|
|
98
|
+
errors,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get stored project documentation
|
|
104
|
+
*/
|
|
105
|
+
async getStoredDoc() {
|
|
106
|
+
try {
|
|
107
|
+
getTurso();
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
const items = await turso.query({
|
|
114
|
+
system: this.system,
|
|
115
|
+
type: 'project_doc',
|
|
116
|
+
limit: 1,
|
|
117
|
+
orderBy: 'updated_at',
|
|
118
|
+
orderDir: 'DESC',
|
|
119
|
+
});
|
|
120
|
+
if (items.length === 0)
|
|
121
|
+
return null;
|
|
122
|
+
// turso.query returns items with content property parsed
|
|
123
|
+
const item = items[0];
|
|
124
|
+
return item.content;
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
logger.error(`[DocsGenerator] Failed to get stored doc: ${error}`);
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if docs need regeneration
|
|
133
|
+
*/
|
|
134
|
+
async needsRegeneration() {
|
|
135
|
+
const storedDoc = await this.getStoredDoc();
|
|
136
|
+
if (!storedDoc)
|
|
137
|
+
return true;
|
|
138
|
+
// Get latest indexed file
|
|
139
|
+
try {
|
|
140
|
+
const items = await turso.query({
|
|
141
|
+
system: this.system,
|
|
142
|
+
type: 'file_metadata',
|
|
143
|
+
limit: 1,
|
|
144
|
+
orderBy: 'updated_at',
|
|
145
|
+
orderDir: 'DESC',
|
|
146
|
+
});
|
|
147
|
+
if (items.length === 0)
|
|
148
|
+
return false;
|
|
149
|
+
const item = items[0];
|
|
150
|
+
const lastIndexed = new Date(item.content.lastIndexedAt);
|
|
151
|
+
const lastGenerated = new Date(storedDoc.lastUpdatedAt);
|
|
152
|
+
return lastIndexed > lastGenerated;
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Regenerate docs if needed
|
|
160
|
+
*/
|
|
161
|
+
async regenerateIfNeeded() {
|
|
162
|
+
const needs = await this.needsRegeneration();
|
|
163
|
+
if (!needs) {
|
|
164
|
+
logger.debug(`[DocsGenerator] Docs are up to date for ${this.system}`);
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
return this.generate();
|
|
168
|
+
}
|
|
169
|
+
// ===========================================================================
|
|
170
|
+
// Data Fetching
|
|
171
|
+
// ===========================================================================
|
|
172
|
+
async getFileMetadata() {
|
|
173
|
+
try {
|
|
174
|
+
getTurso();
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
const items = await turso.query({
|
|
181
|
+
system: this.system,
|
|
182
|
+
type: 'file_metadata',
|
|
183
|
+
limit: 1000,
|
|
184
|
+
});
|
|
185
|
+
return items.map(i => i.content);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return [];
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async getCodeStructures() {
|
|
192
|
+
try {
|
|
193
|
+
getTurso();
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return [];
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
const items = await turso.query({
|
|
200
|
+
system: this.system,
|
|
201
|
+
type: 'code_structure',
|
|
202
|
+
limit: 1000,
|
|
203
|
+
});
|
|
204
|
+
return items.map(i => i.content);
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async getCodeDependencies() {
|
|
211
|
+
try {
|
|
212
|
+
getTurso();
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
const items = await turso.query({
|
|
219
|
+
system: this.system,
|
|
220
|
+
type: 'code_dependency',
|
|
221
|
+
limit: 5000,
|
|
222
|
+
});
|
|
223
|
+
return items.map(i => i.content);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return [];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async getPackageInfo(packagePath) {
|
|
230
|
+
if (!packagePath)
|
|
231
|
+
return undefined;
|
|
232
|
+
try {
|
|
233
|
+
const { readFileSync, existsSync } = await import('fs');
|
|
234
|
+
const { resolve } = await import('path');
|
|
235
|
+
const fullPath = resolve(process.cwd(), packagePath);
|
|
236
|
+
if (!existsSync(fullPath))
|
|
237
|
+
return undefined;
|
|
238
|
+
const content = readFileSync(fullPath, 'utf-8');
|
|
239
|
+
const pkg = JSON.parse(content);
|
|
240
|
+
return {
|
|
241
|
+
version: pkg.version ?? '0.0.0',
|
|
242
|
+
dependencies: pkg.dependencies ?? {},
|
|
243
|
+
devDependencies: pkg.devDependencies,
|
|
244
|
+
scripts: pkg.scripts,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// ===========================================================================
|
|
252
|
+
// Stats Aggregation
|
|
253
|
+
// ===========================================================================
|
|
254
|
+
aggregateStats(metadata, structures, dependencies) {
|
|
255
|
+
const stats = createEmptyStats();
|
|
256
|
+
// Count files and LOC
|
|
257
|
+
stats.totalFiles = metadata.length;
|
|
258
|
+
stats.totalLOC = metadata.reduce((sum, f) => sum + f.loc, 0);
|
|
259
|
+
// Languages
|
|
260
|
+
for (const file of metadata) {
|
|
261
|
+
const lang = file.language;
|
|
262
|
+
stats.languages[lang] = (stats.languages[lang] ?? 0) + file.loc;
|
|
263
|
+
}
|
|
264
|
+
// Frameworks and symbols
|
|
265
|
+
const frameworkSet = new Set();
|
|
266
|
+
for (const struct of structures) {
|
|
267
|
+
if (struct.framework)
|
|
268
|
+
frameworkSet.add(struct.framework);
|
|
269
|
+
stats.totalSymbols += struct.symbols.length;
|
|
270
|
+
if (struct.isComponent)
|
|
271
|
+
stats.components++;
|
|
272
|
+
if (struct.isTest)
|
|
273
|
+
stats.tests++;
|
|
274
|
+
}
|
|
275
|
+
stats.frameworks = Array.from(frameworkSet);
|
|
276
|
+
// Dependencies
|
|
277
|
+
const packageCounts = new Map();
|
|
278
|
+
for (const dep of dependencies) {
|
|
279
|
+
if (dep.isExternal) {
|
|
280
|
+
stats.dependencies.external++;
|
|
281
|
+
if (dep.packageName) {
|
|
282
|
+
packageCounts.set(dep.packageName, (packageCounts.get(dep.packageName) ?? 0) + 1);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
stats.dependencies.internal++;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Top packages
|
|
290
|
+
stats.topPackages = Array.from(packageCounts.entries())
|
|
291
|
+
.sort((a, b) => b[1] - a[1])
|
|
292
|
+
.slice(0, 10)
|
|
293
|
+
.map(([name, usageCount]) => ({ name, usageCount }));
|
|
294
|
+
return stats;
|
|
295
|
+
}
|
|
296
|
+
// ===========================================================================
|
|
297
|
+
// Feature Detection
|
|
298
|
+
// ===========================================================================
|
|
299
|
+
detectFeatures(metadata, structures, dependencies) {
|
|
300
|
+
const features = [];
|
|
301
|
+
const detectedIds = new Set();
|
|
302
|
+
for (const pattern of this.featurePatterns) {
|
|
303
|
+
const matchingFiles = [];
|
|
304
|
+
// Check file patterns
|
|
305
|
+
if (pattern.filePatterns) {
|
|
306
|
+
for (const file of metadata) {
|
|
307
|
+
if (this.matchesGlobPattern(file.relativePath, pattern.filePatterns)) {
|
|
308
|
+
matchingFiles.push(file.relativePath);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// Check import patterns
|
|
313
|
+
if (pattern.importPatterns) {
|
|
314
|
+
for (const dep of dependencies) {
|
|
315
|
+
if (dep.isExternal && dep.packageName) {
|
|
316
|
+
for (const importPattern of pattern.importPatterns) {
|
|
317
|
+
if (dep.packageName.includes(importPattern) || dep.targetFile.includes(importPattern)) {
|
|
318
|
+
if (!matchingFiles.includes(dep.sourceFile)) {
|
|
319
|
+
matchingFiles.push(dep.sourceFile);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
// Check code patterns (in file paths/names as simple heuristic)
|
|
327
|
+
if (pattern.codePatterns) {
|
|
328
|
+
for (const struct of structures) {
|
|
329
|
+
for (const codePattern of pattern.codePatterns) {
|
|
330
|
+
const regex = new RegExp(codePattern, 'i');
|
|
331
|
+
// Check exports and symbols
|
|
332
|
+
const hasMatch = struct.symbols.some(s => regex.test(s.name)) ||
|
|
333
|
+
struct.exports.some(e => regex.test(e.name));
|
|
334
|
+
if (hasMatch && !matchingFiles.includes(struct.filePath)) {
|
|
335
|
+
matchingFiles.push(struct.filePath);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const minOccurrences = pattern.minOccurrences ?? 1;
|
|
341
|
+
if (matchingFiles.length >= minOccurrences && !detectedIds.has(pattern.id)) {
|
|
342
|
+
detectedIds.add(pattern.id);
|
|
343
|
+
features.push({
|
|
344
|
+
id: pattern.id,
|
|
345
|
+
name: pattern.name,
|
|
346
|
+
description: pattern.description,
|
|
347
|
+
category: pattern.category,
|
|
348
|
+
icon: pattern.icon,
|
|
349
|
+
detectedFrom: matchingFiles[0],
|
|
350
|
+
files: matchingFiles.slice(0, 10),
|
|
351
|
+
confidence: Math.min(matchingFiles.length / 5, 1),
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
// Sort by confidence
|
|
356
|
+
return features.sort((a, b) => b.confidence - a.confidence);
|
|
357
|
+
}
|
|
358
|
+
matchesGlobPattern(filePath, patterns) {
|
|
359
|
+
const normalizedPath = filePath.replace(/\\/g, '/');
|
|
360
|
+
for (const pattern of patterns) {
|
|
361
|
+
// Simple glob matching (supports ** and *)
|
|
362
|
+
const regexPattern = pattern
|
|
363
|
+
.replace(/\*\*/g, '{{DOUBLESTAR}}')
|
|
364
|
+
.replace(/\*/g, '[^/]*')
|
|
365
|
+
.replace(/{{DOUBLESTAR}}/g, '.*')
|
|
366
|
+
.replace(/\//g, '[\\\\/]');
|
|
367
|
+
const regex = new RegExp(`^${regexPattern}$`, 'i');
|
|
368
|
+
if (regex.test(normalizedPath)) {
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
// ===========================================================================
|
|
375
|
+
// Architecture Detection
|
|
376
|
+
// ===========================================================================
|
|
377
|
+
detectArchitecture(metadata, structures, dependencies) {
|
|
378
|
+
const architecture = createEmptyArchitecture();
|
|
379
|
+
// Detect layers from directory structure
|
|
380
|
+
const layerPatterns = [
|
|
381
|
+
{ name: 'Hooks', description: 'Claude Code integration hooks', pattern: /hooks?\//i },
|
|
382
|
+
{ name: 'Services', description: 'Business logic services', pattern: /services?\//i },
|
|
383
|
+
{ name: 'Database', description: 'Database layer', pattern: /db\//i },
|
|
384
|
+
{ name: 'Schema', description: 'Type definitions and schemas', pattern: /schema\//i },
|
|
385
|
+
{ name: 'CLI', description: 'Command-line interface', pattern: /cli\//i },
|
|
386
|
+
{ name: 'MCP', description: 'Model Context Protocol', pattern: /mcp\//i },
|
|
387
|
+
{ name: 'Utils', description: 'Utility functions', pattern: /utils?\//i },
|
|
388
|
+
{ name: 'Components', description: 'UI Components', pattern: /components?\//i },
|
|
389
|
+
{ name: 'API', description: 'API routes', pattern: /api\//i },
|
|
390
|
+
{ name: 'Lib', description: 'Library code', pattern: /lib\//i },
|
|
391
|
+
];
|
|
392
|
+
const layerMap = new Map();
|
|
393
|
+
for (const file of metadata) {
|
|
394
|
+
for (const lp of layerPatterns) {
|
|
395
|
+
if (lp.pattern.test(file.relativePath)) {
|
|
396
|
+
if (!layerMap.has(lp.name)) {
|
|
397
|
+
layerMap.set(lp.name, {
|
|
398
|
+
name: lp.name,
|
|
399
|
+
description: lp.description,
|
|
400
|
+
path: file.relativePath.split(/[/\\]/).slice(0, -1).join('/'),
|
|
401
|
+
fileCount: 0,
|
|
402
|
+
keyFiles: [],
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
const layer = layerMap.get(lp.name);
|
|
406
|
+
layer.fileCount++;
|
|
407
|
+
if (layer.keyFiles.length < 5) {
|
|
408
|
+
layer.keyFiles.push(file.relativePath);
|
|
409
|
+
}
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
architecture.layers = Array.from(layerMap.values()).sort((a, b) => b.fileCount - a.fileCount);
|
|
415
|
+
// Detect entry points (files with most exports or index files)
|
|
416
|
+
const exportCounts = new Map();
|
|
417
|
+
for (const struct of structures) {
|
|
418
|
+
const exportCount = struct.exports.length;
|
|
419
|
+
if (exportCount > 0) {
|
|
420
|
+
exportCounts.set(struct.filePath, exportCount);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
// Index files and high-export files are entry points
|
|
424
|
+
const entryPointCandidates = metadata
|
|
425
|
+
.filter(f => f.fileName === 'index.ts' ||
|
|
426
|
+
f.fileName === 'index.tsx' ||
|
|
427
|
+
f.fileName === 'index.js' ||
|
|
428
|
+
(exportCounts.get(f.relativePath) ?? 0) > 5)
|
|
429
|
+
.map(f => f.relativePath)
|
|
430
|
+
.slice(0, 10);
|
|
431
|
+
architecture.entryPoints = entryPointCandidates;
|
|
432
|
+
// Generate Mermaid diagram
|
|
433
|
+
architecture.diagram = this.generateMermaidDiagram(architecture.layers, dependencies);
|
|
434
|
+
// Generate simple diagram
|
|
435
|
+
architecture.simpleDiagram = this.generateSimpleDiagram(architecture.layers);
|
|
436
|
+
return architecture;
|
|
437
|
+
}
|
|
438
|
+
generateMermaidDiagram(layers, dependencies) {
|
|
439
|
+
const lines = ['graph TD'];
|
|
440
|
+
// Add subgraphs for each layer
|
|
441
|
+
for (const layer of layers.slice(0, 6)) {
|
|
442
|
+
const safeId = layer.name.replace(/\s+/g, '_');
|
|
443
|
+
lines.push(` subgraph ${safeId}["${layer.name}"]`);
|
|
444
|
+
// Add key files as nodes
|
|
445
|
+
for (let i = 0; i < Math.min(layer.keyFiles.length, 3); i++) {
|
|
446
|
+
const file = layer.keyFiles[i];
|
|
447
|
+
const fileName = file.split(/[/\\]/).pop()?.replace(/\.[^.]+$/, '') ?? 'unknown';
|
|
448
|
+
const nodeId = `${safeId}_${i}`;
|
|
449
|
+
lines.push(` ${nodeId}["${fileName}"]`);
|
|
450
|
+
}
|
|
451
|
+
lines.push(' end');
|
|
452
|
+
}
|
|
453
|
+
// Add some inter-layer connections based on common patterns
|
|
454
|
+
const layerNames = layers.map(l => l.name.replace(/\s+/g, '_'));
|
|
455
|
+
if (layerNames.includes('Hooks') && layerNames.includes('Services')) {
|
|
456
|
+
lines.push(' Hooks --> Services');
|
|
457
|
+
}
|
|
458
|
+
if (layerNames.includes('Services') && layerNames.includes('Database')) {
|
|
459
|
+
lines.push(' Services --> Database');
|
|
460
|
+
}
|
|
461
|
+
if (layerNames.includes('CLI') && layerNames.includes('Services')) {
|
|
462
|
+
lines.push(' CLI --> Services');
|
|
463
|
+
}
|
|
464
|
+
if (layerNames.includes('API') && layerNames.includes('Services')) {
|
|
465
|
+
lines.push(' API --> Services');
|
|
466
|
+
}
|
|
467
|
+
if (layerNames.includes('Components') && layerNames.includes('Lib')) {
|
|
468
|
+
lines.push(' Components --> Lib');
|
|
469
|
+
}
|
|
470
|
+
return lines.join('\n');
|
|
471
|
+
}
|
|
472
|
+
generateSimpleDiagram(layers) {
|
|
473
|
+
const lines = ['graph LR'];
|
|
474
|
+
const simplifiedLayers = layers.slice(0, 4);
|
|
475
|
+
for (let i = 0; i < simplifiedLayers.length; i++) {
|
|
476
|
+
const layer = simplifiedLayers[i];
|
|
477
|
+
const safeId = layer.name.replace(/\s+/g, '_');
|
|
478
|
+
const icon = this.getLayerIcon(layer.name);
|
|
479
|
+
lines.push(` ${safeId}["${icon} ${layer.name}"]`);
|
|
480
|
+
if (i < simplifiedLayers.length - 1) {
|
|
481
|
+
const nextId = simplifiedLayers[i + 1].name.replace(/\s+/g, '_');
|
|
482
|
+
lines.push(` ${safeId} --> ${nextId}`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return lines.join('\n');
|
|
486
|
+
}
|
|
487
|
+
getLayerIcon(layerName) {
|
|
488
|
+
const icons = {
|
|
489
|
+
Hooks: '🪝',
|
|
490
|
+
Services: '⚙️',
|
|
491
|
+
Database: '🗄️',
|
|
492
|
+
Schema: '📋',
|
|
493
|
+
CLI: '💻',
|
|
494
|
+
MCP: '🔌',
|
|
495
|
+
Utils: '🔧',
|
|
496
|
+
Components: '🧩',
|
|
497
|
+
API: '🌐',
|
|
498
|
+
Lib: '📚',
|
|
499
|
+
};
|
|
500
|
+
return icons[layerName] ?? '📁';
|
|
501
|
+
}
|
|
502
|
+
// ===========================================================================
|
|
503
|
+
// Storage
|
|
504
|
+
// ===========================================================================
|
|
505
|
+
async storeDoc(doc) {
|
|
506
|
+
getTurso();
|
|
507
|
+
// Delete existing doc for this project
|
|
508
|
+
try {
|
|
509
|
+
const existing = await turso.query({
|
|
510
|
+
system: this.system,
|
|
511
|
+
type: 'project_doc',
|
|
512
|
+
limit: 10,
|
|
513
|
+
});
|
|
514
|
+
if (existing.length > 0) {
|
|
515
|
+
// Update existing
|
|
516
|
+
const db = getTurso();
|
|
517
|
+
await db.execute({
|
|
518
|
+
sql: `UPDATE items SET content = ?, updated_at = ? WHERE id = ?`,
|
|
519
|
+
args: [JSON.stringify(doc), new Date().toISOString(), existing[0].id],
|
|
520
|
+
});
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
catch {
|
|
525
|
+
// Continue to create new
|
|
526
|
+
}
|
|
527
|
+
// Create new doc
|
|
528
|
+
await create('project_doc', this.system, doc, 'active');
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
// =============================================================================
|
|
532
|
+
// Singleton Management
|
|
533
|
+
// =============================================================================
|
|
534
|
+
const instances = new Map();
|
|
535
|
+
/**
|
|
536
|
+
* Get DocsGenerator instance for a system
|
|
537
|
+
*/
|
|
538
|
+
export function getDocsGenerator(system) {
|
|
539
|
+
if (!instances.has(system)) {
|
|
540
|
+
instances.set(system, new DocsGenerator({ system }));
|
|
541
|
+
}
|
|
542
|
+
return instances.get(system);
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Create new DocsGenerator
|
|
546
|
+
*/
|
|
547
|
+
export function createDocsGenerator(options) {
|
|
548
|
+
return new DocsGenerator(options);
|
|
549
|
+
}
|
|
550
|
+
export default DocsGenerator;
|
|
551
|
+
//# sourceMappingURL=DocsGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DocsGenerator.js","sourceRoot":"","sources":["../../src/services/DocsGenerator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpportunityDiscovery.d.ts","sourceRoot":"","sources":["../../src/services/OpportunityDiscovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,mBAAmB,EAIxB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,
|
|
1
|
+
{"version":3,"file":"OpportunityDiscovery.d.ts","sourceRoot":"","sources":["../../src/services/OpportunityDiscovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,mBAAmB,EAIxB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAGhC,MAAM,gCAAgC,CAAA;AA+VvC,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAW;gBAEb,MAAM,EAAE,SAAS;IAI7B;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,2BAA2B,CAAC,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAiElG;;OAEG;YACW,YAAY;IAyB1B;;OAEG;YACW,aAAa;IAkC3B;;OAEG;YACW,WAAW;IAmEzB;;OAEG;YACW,eAAe;IA4D7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA2B3B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAgBhC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuCxB;;;OAGG;YACW,kBAAkB;IAyChC;;OAEG;IACG,SAAS,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAa3D;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,mBAAmB,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAc9F;;OAEG;IACG,YAAY,CAChB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,aAAa,GAC1E,OAAO,CAAC,IAAI,CAAC;IAqBhB;;OAEG;IACG,cAAc,CAAC,aAAa,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IA6CnE;;OAEG;IACH,OAAO,CAAC,cAAc;CAevB;AAQD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,oBAAoB,CAK/E;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,oBAAoB,CAElF"}
|
|
@@ -16,6 +16,7 @@ import fs from 'fs/promises';
|
|
|
16
16
|
import path from 'path';
|
|
17
17
|
import { turso } from '../db/turso-client.js';
|
|
18
18
|
import { createOpportunity, } from '../schema/opportunity-types.js';
|
|
19
|
+
import { getTurso } from '../db/turso-client.js';
|
|
19
20
|
import { getExpertRouter } from '../experts/ExpertRouter.js';
|
|
20
21
|
const ANALYSIS_PATTERNS = [
|
|
21
22
|
// Edge Cases
|
|
@@ -378,7 +379,7 @@ export class OpportunityDiscovery {
|
|
|
378
379
|
// Calculate summary
|
|
379
380
|
const summary = this.calculateSummary(deduped, filesAnalyzed, Date.now() - startTime);
|
|
380
381
|
// Store opportunities in database
|
|
381
|
-
await this.storeOpportunities(runId, deduped);
|
|
382
|
+
const storage = await this.storeOpportunities(runId, deduped);
|
|
382
383
|
return {
|
|
383
384
|
runId,
|
|
384
385
|
timestamp: new Date().toISOString(),
|
|
@@ -386,6 +387,7 @@ export class OpportunityDiscovery {
|
|
|
386
387
|
opportunities: deduped,
|
|
387
388
|
summary,
|
|
388
389
|
expertsUsed: Array.from(expertsUsed),
|
|
390
|
+
storage,
|
|
389
391
|
};
|
|
390
392
|
}
|
|
391
393
|
/**
|
|
@@ -617,14 +619,41 @@ export class OpportunityDiscovery {
|
|
|
617
619
|
}
|
|
618
620
|
/**
|
|
619
621
|
* Store opportunities in Turso database
|
|
622
|
+
* Returns storage statistics including success/failure counts
|
|
620
623
|
*/
|
|
621
624
|
async storeOpportunities(runId, opportunities) {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
625
|
+
const result = { stored: 0, failed: 0, errors: [] };
|
|
626
|
+
if (opportunities.length === 0) {
|
|
627
|
+
return result;
|
|
628
|
+
}
|
|
629
|
+
// Check if Turso client is available
|
|
630
|
+
try {
|
|
631
|
+
getTurso();
|
|
632
|
+
}
|
|
633
|
+
catch {
|
|
634
|
+
return {
|
|
635
|
+
stored: 0,
|
|
636
|
+
failed: opportunities.length,
|
|
637
|
+
errors: ['Cloud not initialized - run ensureCloud() first'],
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
// Store opportunities in parallel with Promise.allSettled
|
|
641
|
+
const storePromises = opportunities.map(opp => turso.create('opportunity', this.system, { ...opp, runId }, 'active'));
|
|
642
|
+
const results = await Promise.allSettled(storePromises);
|
|
643
|
+
for (const res of results) {
|
|
644
|
+
if (res.status === 'fulfilled') {
|
|
645
|
+
result.stored++;
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
result.failed++;
|
|
649
|
+
// Sanitize error message to avoid leaking tokens
|
|
650
|
+
const errorMsg = res.reason?.message ?? 'Unknown storage error';
|
|
651
|
+
if (!result.errors.includes(errorMsg)) {
|
|
652
|
+
result.errors.push(errorMsg);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
627
655
|
}
|
|
656
|
+
return result;
|
|
628
657
|
}
|
|
629
658
|
/**
|
|
630
659
|
* Get recent opportunities from Turso
|