@memberjunction/db-auto-doc 2.109.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.
Files changed (63) hide show
  1. package/README.md +244 -0
  2. package/bin/run.js +5 -0
  3. package/dist/ai/simple-ai-client.d.ts +70 -0
  4. package/dist/ai/simple-ai-client.d.ts.map +1 -0
  5. package/dist/ai/simple-ai-client.js +181 -0
  6. package/dist/ai/simple-ai-client.js.map +1 -0
  7. package/dist/analyzers/analyzer.d.ts +23 -0
  8. package/dist/analyzers/analyzer.d.ts.map +1 -0
  9. package/dist/analyzers/analyzer.js +127 -0
  10. package/dist/analyzers/analyzer.js.map +1 -0
  11. package/dist/cli-old/cli.d.ts +3 -0
  12. package/dist/cli-old/cli.d.ts.map +1 -0
  13. package/dist/cli-old/cli.js +388 -0
  14. package/dist/cli-old/cli.js.map +1 -0
  15. package/dist/commands/analyze.d.ts +13 -0
  16. package/dist/commands/analyze.d.ts.map +1 -0
  17. package/dist/commands/analyze.js +98 -0
  18. package/dist/commands/analyze.js.map +1 -0
  19. package/dist/commands/export.d.ts +13 -0
  20. package/dist/commands/export.d.ts.map +1 -0
  21. package/dist/commands/export.js +117 -0
  22. package/dist/commands/export.js.map +1 -0
  23. package/dist/commands/init.d.ts +11 -0
  24. package/dist/commands/init.d.ts.map +1 -0
  25. package/dist/commands/init.js +163 -0
  26. package/dist/commands/init.js.map +1 -0
  27. package/dist/commands/reset.d.ts +10 -0
  28. package/dist/commands/reset.d.ts.map +1 -0
  29. package/dist/commands/reset.js +37 -0
  30. package/dist/commands/reset.js.map +1 -0
  31. package/dist/commands/review.d.ts +11 -0
  32. package/dist/commands/review.d.ts.map +1 -0
  33. package/dist/commands/review.js +82 -0
  34. package/dist/commands/review.js.map +1 -0
  35. package/dist/database/connection.d.ts +40 -0
  36. package/dist/database/connection.d.ts.map +1 -0
  37. package/dist/database/connection.js +136 -0
  38. package/dist/database/connection.js.map +1 -0
  39. package/dist/database/introspection.d.ts +59 -0
  40. package/dist/database/introspection.d.ts.map +1 -0
  41. package/dist/database/introspection.js +124 -0
  42. package/dist/database/introspection.js.map +1 -0
  43. package/dist/generators/markdown-generator.d.ts +8 -0
  44. package/dist/generators/markdown-generator.d.ts.map +1 -0
  45. package/dist/generators/markdown-generator.js +106 -0
  46. package/dist/generators/markdown-generator.js.map +1 -0
  47. package/dist/generators/sql-generator.d.ts +20 -0
  48. package/dist/generators/sql-generator.d.ts.map +1 -0
  49. package/dist/generators/sql-generator.js +83 -0
  50. package/dist/generators/sql-generator.js.map +1 -0
  51. package/dist/index.d.ts +23 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +39 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/state/state-manager.d.ts +95 -0
  56. package/dist/state/state-manager.d.ts.map +1 -0
  57. package/dist/state/state-manager.js +236 -0
  58. package/dist/state/state-manager.js.map +1 -0
  59. package/dist/types/state-file.d.ts +124 -0
  60. package/dist/types/state-file.d.ts.map +1 -0
  61. package/dist/types/state-file.js +79 -0
  62. package/dist/types/state-file.js.map +1 -0
  63. package/package.json +62 -0
package/README.md ADDED
@@ -0,0 +1,244 @@
1
+ # Database Auto-Documentation Generator
2
+
3
+ AI-powered documentation generator for SQL Server databases. Analyzes your database structure, uses AI to generate comprehensive table and column descriptions, and saves them as SQL Server extended properties.
4
+
5
+ ## 🚀 **Standalone Tool - No MemberJunction Runtime Required**
6
+
7
+ This tool works with **ANY** SQL Server database. You don't need MemberJunction installed or running.
8
+
9
+ ## Features
10
+
11
+ - **🤖 AI-Powered**: Uses LLMs (OpenAI, Anthropic, etc.) to generate intelligent descriptions
12
+ - **🔄 Human-in-Loop**: Interactive mode to provide context and approve AI-generated descriptions
13
+ - **💾 State Management**: JSON state file tracks progress, user input, and AI generations across runs
14
+ - **🎯 Incremental**: Only processes new or changed tables on subsequent runs
15
+ - **🔍 Smart Analysis**:
16
+ - Dependency graph analysis (documents root tables first)
17
+ - Pattern detection (lookup tables, bridge tables, audit tables)
18
+ - Data profiling (sample data, statistics, pattern recognition)
19
+ - Constraint analysis (PKs, FKs, CHECK, UNIQUE)
20
+ - **📊 Multiple Outputs**:
21
+ - SQL scripts with `sp_addextendedproperty` statements
22
+ - Markdown documentation
23
+ - Updated state file for next run
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ # Install globally (for standalone use)
29
+ npm install -g @memberjunction/db-auto-doc
30
+
31
+ # Or use with npx
32
+ npx @memberjunction/db-auto-doc
33
+
34
+ # Or use via MJ CLI (if you have MemberJunction installed)
35
+ mj dbdoc --help
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ ### Standalone CLI
41
+
42
+ ```bash
43
+ # 1. Initialize project
44
+ db-auto-doc init
45
+
46
+ # 2. Edit .env and add your AI API key
47
+ # AI_API_KEY=sk-your-key-here
48
+
49
+ # 3. Analyze database
50
+ db-auto-doc analyze
51
+
52
+ # 4. Review results
53
+ db-auto-doc review
54
+
55
+ # 5. Export documentation
56
+ db-auto-doc export --format=all
57
+ ```
58
+
59
+ ### Via MJ CLI (MemberJunction Users)
60
+
61
+ ```bash
62
+ # Same commands, different prefix
63
+ mj dbdoc init
64
+ mj dbdoc analyze --schemas=dbo
65
+ mj dbdoc review --unapproved-only
66
+ mj dbdoc export --approved-only --execute
67
+ ```
68
+
69
+ ### Programmatic Usage
70
+
71
+ ```typescript
72
+ import {
73
+ DatabaseConnection,
74
+ StateManager,
75
+ DatabaseAnalyzer,
76
+ SimpleAIClient,
77
+ } from '@memberjunction/db-auto-doc';
78
+
79
+ // Initialize
80
+ const connection = DatabaseConnection.fromEnv();
81
+ const stateManager = new StateManager();
82
+ const aiClient = new SimpleAIClient();
83
+ const analyzer = new DatabaseAnalyzer(connection, stateManager, aiClient);
84
+
85
+ // Analyze
86
+ await analyzer.analyze({ schemas: ['dbo'] });
87
+
88
+ // Export
89
+ import { SQLGenerator, MarkdownGenerator } from '@memberjunction/db-auto-doc';
90
+ const state = stateManager.getState();
91
+ const sqlGen = new SQLGenerator();
92
+ const sql = sqlGen.generate(state);
93
+ ```
94
+
95
+ ## CLI Commands
96
+
97
+ ### `db-auto-doc init`
98
+ Initialize new documentation project
99
+ - Prompts for database connection
100
+ - Creates `.env` file
101
+ - Creates `db-doc-state.json`
102
+ - Optionally asks seed questions
103
+
104
+ ### `db-auto-doc analyze`
105
+ Analyze database and generate documentation
106
+ - `--interactive` - Ask questions during analysis
107
+ - `--incremental` - Only process new/changed tables
108
+ - `--schemas <schemas>` - Comma-separated schema list
109
+ - `--batch` - Non-interactive mode
110
+
111
+ ### `db-auto-doc review`
112
+ Review and approve AI-generated documentation
113
+ - `--schema <schema>` - Review specific schema
114
+ - `--unapproved-only` - Only show unapproved items
115
+
116
+ ### `db-auto-doc export`
117
+ Generate output files
118
+ - `--format <format>` - sql|markdown|all (default: all)
119
+ - `--output <path>` - Output directory
120
+ - `--execute` - Execute SQL script (apply to database)
121
+ - `--approved-only` - Only export approved items
122
+
123
+ ### `db-auto-doc reset`
124
+ Reset state file
125
+ - `--all` - Reset entire state file
126
+
127
+ ## Configuration
128
+
129
+ Create a `.env` file:
130
+
131
+ ```env
132
+ # Database Connection
133
+ DB_SERVER=localhost
134
+ DB_DATABASE=YourDatabase
135
+ DB_USER=sa
136
+ DB_PASSWORD=YourPassword
137
+ DB_ENCRYPT=true
138
+ DB_TRUST_SERVER_CERTIFICATE=true
139
+
140
+ # AI Configuration
141
+ AI_PROVIDER=openai
142
+ AI_MODEL=gpt-4
143
+ AI_API_KEY=sk-your-api-key-here
144
+ ```
145
+
146
+ ## State File
147
+
148
+ The `db-doc-state.json` file tracks everything:
149
+
150
+ ```json
151
+ {
152
+ "version": "1.0",
153
+ "database": {
154
+ "server": "localhost",
155
+ "database": "MyDatabase"
156
+ },
157
+ "seedContext": {
158
+ "overallPurpose": "E-commerce platform",
159
+ "businessDomains": ["Sales", "Inventory"]
160
+ },
161
+ "schemas": {
162
+ "dbo": {
163
+ "tables": {
164
+ "Customers": {
165
+ "userNotes": "Merged from Stripe and internal CRM",
166
+ "userApproved": true,
167
+ "aiGenerated": {
168
+ "description": "Primary customer records...",
169
+ "confidence": 0.85
170
+ },
171
+ "finalDescription": "...",
172
+ "columns": { }
173
+ }
174
+ }
175
+ }
176
+ },
177
+ "runHistory": [ ]
178
+ }
179
+ ```
180
+
181
+ ## Example Workflow
182
+
183
+ ```bash
184
+ # First run
185
+ db-auto-doc init
186
+ db-auto-doc analyze --interactive
187
+ db-auto-doc review
188
+ db-auto-doc export --format=all
189
+
190
+ # Add context and refine
191
+ # Edit db-doc-state.json to add notes
192
+ db-auto-doc analyze --incremental
193
+ db-auto-doc review --unapproved-only
194
+
195
+ # Ready for production
196
+ db-auto-doc export --approved-only --execute
197
+ ```
198
+
199
+ ## How It Works
200
+
201
+ 1. **Introspection**: Queries SQL Server system catalogs
202
+ 2. **Profiling**: Samples data and analyzes patterns
203
+ 3. **AI Generation**: Sends context to LLM for descriptions
204
+ 4. **Human Review**: User approves/refines results
205
+ 5. **Output**: Generates SQL scripts and markdown docs
206
+ 6. **Application**: Optionally executes SQL to add extended properties
207
+
208
+ ## Architecture
209
+
210
+ Built following the **AI CLI pattern** (similar to `@memberjunction/ai-cli`):
211
+ - **oclif-based commands** in `src/commands/` (init, analyze, review, export, reset)
212
+ - **Standalone package** with zero MJ runtime dependencies
213
+ - **MJCLI integration** via thin delegation commands in `packages/MJCLI/src/commands/dbdoc/`
214
+ - **Reusable services** exported for programmatic use
215
+ - **State file architecture** enables incremental refinement across runs
216
+
217
+ ## Future Enhancements
218
+
219
+ Possible future additions (not needed for current functionality):
220
+ - Support for more AI providers (Groq, Cerebras, local models)
221
+ - PostgreSQL/MySQL versions
222
+ - Web UI for review
223
+ - Dependency graph visualization
224
+ - CI/CD integration examples
225
+ - Schema diff detection for automatic re-documentation
226
+
227
+ ## Requirements
228
+
229
+ - Node.js 18+
230
+ - SQL Server database access
231
+ - OpenAI or Anthropic API key
232
+
233
+ ## License
234
+
235
+ MIT License - see LICENSE file for details
236
+
237
+ ## Support
238
+
239
+ - GitHub Issues: https://github.com/MemberJunction/MJ/issues
240
+ - Documentation: https://docs.memberjunction.org
241
+
242
+ ## Credits
243
+
244
+ Built by the MemberJunction team for the SQL Server community.
package/bin/run.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ const oclif = require('@oclif/core')
4
+
5
+ oclif.run().then(oclif.flush).catch(oclif.Errors.handle)
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Simplified AI client that doesn't depend on MJ AI infrastructure
3
+ * Uses direct HTTP calls to AI providers
4
+ */
5
+ export interface AITableDocRequest {
6
+ schema: string;
7
+ table: string;
8
+ columns: Array<{
9
+ name: string;
10
+ type: string;
11
+ nullable: boolean;
12
+ isPK: boolean;
13
+ isFK: boolean;
14
+ }>;
15
+ foreignKeys: Array<{
16
+ column: string;
17
+ referencedTable: string;
18
+ }>;
19
+ sampleData?: Record<string, any>[];
20
+ existingDescription?: string;
21
+ userNotes?: string;
22
+ }
23
+ export interface AITableDocResponse {
24
+ description: string;
25
+ purpose?: string;
26
+ usageNotes?: string;
27
+ businessDomain?: string;
28
+ confidence: number;
29
+ columns: Array<{
30
+ name: string;
31
+ description: string;
32
+ purpose?: string;
33
+ validValues?: string;
34
+ confidence: number;
35
+ }>;
36
+ relationships?: Array<{
37
+ type: 'parent' | 'child';
38
+ table: string;
39
+ description: string;
40
+ }>;
41
+ }
42
+ /**
43
+ * Simple AI client - uses fetch() to call OpenAI directly
44
+ * TODO: Add support for other providers (Anthropic, Groq, etc.)
45
+ */
46
+ export declare class SimpleAIClient {
47
+ private provider;
48
+ private model;
49
+ private apiKey;
50
+ constructor();
51
+ /**
52
+ * Generate table documentation
53
+ */
54
+ generateTableDoc(request: AITableDocRequest): Promise<AITableDocResponse & {
55
+ tokensUsed?: number;
56
+ }>;
57
+ /**
58
+ * Call OpenAI API
59
+ */
60
+ private callOpenAI;
61
+ /**
62
+ * Call Anthropic API
63
+ */
64
+ private callAnthropic;
65
+ /**
66
+ * Build table documentation prompt
67
+ */
68
+ private buildTablePrompt;
69
+ }
70
+ //# sourceMappingURL=simple-ai-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple-ai-client.d.ts","sourceRoot":"","sources":["../../src/ai/simple-ai-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,IAAI,EAAE,OAAO,CAAC;QACd,IAAI,EAAE,OAAO,CAAC;KACf,CAAC,CAAC;IACH,WAAW,EAAE,KAAK,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC,CAAC;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,aAAa,CAAC,EAAE,KAAK,CAAC;QACpB,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;QACzB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;CACJ;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;;IAYvB;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,GAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAYzG;;OAEG;YACW,UAAU;IA8CxB;;OAEG;YACW,aAAa;IA2C3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;CA+DzB"}
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ /**
3
+ * Simplified AI client that doesn't depend on MJ AI infrastructure
4
+ * Uses direct HTTP calls to AI providers
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SimpleAIClient = void 0;
8
+ /**
9
+ * Simple AI client - uses fetch() to call OpenAI directly
10
+ * TODO: Add support for other providers (Anthropic, Groq, etc.)
11
+ */
12
+ class SimpleAIClient {
13
+ constructor() {
14
+ this.provider = process.env.AI_PROVIDER || 'openai';
15
+ this.model = process.env.AI_MODEL || 'gpt-4';
16
+ this.apiKey = process.env.AI_API_KEY || '';
17
+ if (!this.apiKey) {
18
+ throw new Error('AI_API_KEY environment variable is required');
19
+ }
20
+ }
21
+ /**
22
+ * Generate table documentation
23
+ */
24
+ async generateTableDoc(request) {
25
+ const prompt = this.buildTablePrompt(request);
26
+ if (this.provider === 'openai') {
27
+ return await this.callOpenAI(prompt);
28
+ }
29
+ else if (this.provider === 'anthropic') {
30
+ return await this.callAnthropic(prompt);
31
+ }
32
+ else {
33
+ throw new Error(`Unsupported AI provider: ${this.provider}`);
34
+ }
35
+ }
36
+ /**
37
+ * Call OpenAI API
38
+ */
39
+ async callOpenAI(prompt) {
40
+ const response = await fetch('https://api.openai.com/v1/chat/completions', {
41
+ method: 'POST',
42
+ headers: {
43
+ 'Content-Type': 'application/json',
44
+ 'Authorization': `Bearer ${this.apiKey}`,
45
+ },
46
+ body: JSON.stringify({
47
+ model: this.model,
48
+ messages: [
49
+ {
50
+ role: 'system',
51
+ content: 'You are a database documentation expert. Generate clear, business-friendly descriptions for database tables and columns. Always respond with valid JSON only.',
52
+ },
53
+ {
54
+ role: 'user',
55
+ content: prompt,
56
+ },
57
+ ],
58
+ temperature: 0.3,
59
+ max_tokens: 2000,
60
+ }),
61
+ });
62
+ if (!response.ok) {
63
+ throw new Error(`OpenAI API error: ${response.statusText}`);
64
+ }
65
+ const data = await response.json();
66
+ const content = data.choices?.[0]?.message?.content;
67
+ if (!content) {
68
+ throw new Error('No content in AI response');
69
+ }
70
+ // Parse JSON response
71
+ const jsonMatch = content.match(/```json\s*([\s\S]*?)\s*```/) || content.match(/\{[\s\S]*\}/);
72
+ const jsonStr = jsonMatch ? (jsonMatch[1] || jsonMatch[0]) : content;
73
+ const doc = JSON.parse(jsonStr);
74
+ return {
75
+ ...doc,
76
+ tokensUsed: data.usage?.total_tokens || 0,
77
+ };
78
+ }
79
+ /**
80
+ * Call Anthropic API
81
+ */
82
+ async callAnthropic(prompt) {
83
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
84
+ method: 'POST',
85
+ headers: {
86
+ 'Content-Type': 'application/json',
87
+ 'x-api-key': this.apiKey,
88
+ 'anthropic-version': '2023-06-01',
89
+ },
90
+ body: JSON.stringify({
91
+ model: this.model,
92
+ max_tokens: 2000,
93
+ temperature: 0.3,
94
+ messages: [
95
+ {
96
+ role: 'user',
97
+ content: `You are a database documentation expert. Generate clear, business-friendly descriptions for database tables and columns. Always respond with valid JSON only.\n\n${prompt}`,
98
+ },
99
+ ],
100
+ }),
101
+ });
102
+ if (!response.ok) {
103
+ throw new Error(`Anthropic API error: ${response.statusText}`);
104
+ }
105
+ const data = await response.json();
106
+ const content = data.content?.[0]?.text;
107
+ if (!content) {
108
+ throw new Error('No content in AI response');
109
+ }
110
+ // Parse JSON response
111
+ const jsonMatch = content.match(/```json\s*([\s\S]*?)\s*```/) || content.match(/\{[\s\S]*\}/);
112
+ const jsonStr = jsonMatch ? (jsonMatch[1] || jsonMatch[0]) : content;
113
+ const doc = JSON.parse(jsonStr);
114
+ return {
115
+ ...doc,
116
+ tokensUsed: (data.usage?.input_tokens || 0) + (data.usage?.output_tokens || 0),
117
+ };
118
+ }
119
+ /**
120
+ * Build table documentation prompt
121
+ */
122
+ buildTablePrompt(request) {
123
+ const lines = [];
124
+ lines.push(`# Table: ${request.schema}.${request.table}`);
125
+ lines.push('');
126
+ lines.push('## Columns');
127
+ for (const col of request.columns) {
128
+ const flags = [];
129
+ if (col.isPK)
130
+ flags.push('PK');
131
+ if (col.isFK)
132
+ flags.push('FK');
133
+ if (!col.nullable)
134
+ flags.push('NOT NULL');
135
+ lines.push(`- ${col.name} (${col.type}) ${flags.join(', ')}`);
136
+ }
137
+ if (request.foreignKeys.length > 0) {
138
+ lines.push('');
139
+ lines.push('## Foreign Keys');
140
+ for (const fk of request.foreignKeys) {
141
+ lines.push(`- ${fk.column} → ${fk.referencedTable}`);
142
+ }
143
+ }
144
+ if (request.sampleData && request.sampleData.length > 0) {
145
+ lines.push('');
146
+ lines.push('## Sample Data');
147
+ lines.push(JSON.stringify(request.sampleData.slice(0, 3), null, 2));
148
+ }
149
+ if (request.existingDescription) {
150
+ lines.push('');
151
+ lines.push('## Existing Description');
152
+ lines.push(request.existingDescription);
153
+ }
154
+ if (request.userNotes) {
155
+ lines.push('');
156
+ lines.push('## User Notes');
157
+ lines.push(request.userNotes);
158
+ }
159
+ lines.push('');
160
+ lines.push('## Task');
161
+ lines.push('Generate documentation for this table. Return ONLY a JSON object with this exact structure:');
162
+ lines.push('```json');
163
+ lines.push('{');
164
+ lines.push(' "description": "What this table stores (2-3 sentences)",');
165
+ lines.push(' "purpose": "Why this table exists (1 sentence)",');
166
+ lines.push(' "businessDomain": "e.g., Sales, HR, Inventory",');
167
+ lines.push(' "confidence": 0.85,');
168
+ lines.push(' "columns": [');
169
+ lines.push(' {');
170
+ lines.push(' "name": "ColumnName",');
171
+ lines.push(' "description": "What this column contains",');
172
+ lines.push(' "confidence": 0.9');
173
+ lines.push(' }');
174
+ lines.push(' ]');
175
+ lines.push('}');
176
+ lines.push('```');
177
+ return lines.join('\n');
178
+ }
179
+ }
180
+ exports.SimpleAIClient = SimpleAIClient;
181
+ //# sourceMappingURL=simple-ai-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple-ai-client.js","sourceRoot":"","sources":["../../src/ai/simple-ai-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { DatabaseConnection } from '../database/connection';
2
+ import { StateManager } from '../state/state-manager';
3
+ import { SimpleAIClient as AIClient } from '../ai/simple-ai-client';
4
+ export interface AnalyzerOptions {
5
+ schemas?: string[];
6
+ excludeSchemas?: string[];
7
+ interactive?: boolean;
8
+ incremental?: boolean;
9
+ }
10
+ /**
11
+ * Main analyzer orchestrating the documentation process
12
+ */
13
+ export declare class DatabaseAnalyzer {
14
+ private connection;
15
+ private stateManager;
16
+ private aiClient;
17
+ constructor(connection: DatabaseConnection, stateManager: StateManager, aiClient: AIClient);
18
+ /**
19
+ * Analyze database and generate documentation
20
+ */
21
+ analyze(options?: AnalyzerOptions): Promise<void>;
22
+ }
23
+ //# sourceMappingURL=analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGpE,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ;gBAFR,UAAU,EAAE,kBAAkB,EAC9B,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,QAAQ;IAG5B;;OAEG;IACG,OAAO,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;CA8H5D"}
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DatabaseAnalyzer = void 0;
7
+ const introspection_1 = require("../database/introspection");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ /**
10
+ * Main analyzer orchestrating the documentation process
11
+ */
12
+ class DatabaseAnalyzer {
13
+ constructor(connection, stateManager, aiClient) {
14
+ this.connection = connection;
15
+ this.stateManager = stateManager;
16
+ this.aiClient = aiClient;
17
+ }
18
+ /**
19
+ * Analyze database and generate documentation
20
+ */
21
+ async analyze(options = {}) {
22
+ const spinner = (0, ora_1.default)('Analyzing database...').start();
23
+ try {
24
+ const introspector = new introspection_1.DatabaseIntrospector(this.connection);
25
+ // Get tables to process
26
+ const tables = await introspector.getTables(options.schemas, options.excludeSchemas);
27
+ spinner.succeed(`Found ${tables.length} tables`);
28
+ let processed = 0;
29
+ let skipped = 0;
30
+ let totalTokens = 0;
31
+ for (const tableInfo of tables) {
32
+ const tableSpinner = (0, ora_1.default)(`Processing ${tableInfo.schema}.${tableInfo.table}`).start();
33
+ try {
34
+ // Check if already processed (incremental mode)
35
+ if (options.incremental) {
36
+ const state = this.stateManager.getState();
37
+ const schema = state.schemas[tableInfo.schema];
38
+ if (schema?.tables[tableInfo.table]?.aiGenerated) {
39
+ tableSpinner.info(`Skipping ${tableInfo.schema}.${tableInfo.table} (already processed)`);
40
+ skipped++;
41
+ continue;
42
+ }
43
+ }
44
+ // Get table details
45
+ const [columns, foreignKeys, extProps, sampleData] = await Promise.all([
46
+ introspector.getColumns(tableInfo.schema, tableInfo.table),
47
+ introspector.getForeignKeys(tableInfo.schema, tableInfo.table),
48
+ introspector.getExtendedProperties(tableInfo.schema, tableInfo.table),
49
+ introspector.sampleData(tableInfo.schema, tableInfo.table, 5),
50
+ ]);
51
+ // Get existing description
52
+ const existingDesc = extProps.find(p => p.objectType === 'TABLE')?.value;
53
+ // Generate documentation with AI
54
+ const aiDoc = await this.aiClient.generateTableDoc({
55
+ schema: tableInfo.schema,
56
+ table: tableInfo.table,
57
+ columns: columns.map(c => ({
58
+ name: c.name,
59
+ type: c.dataType,
60
+ nullable: c.isNullable,
61
+ isPK: c.isPrimaryKey,
62
+ isFK: c.isForeignKey,
63
+ })),
64
+ foreignKeys: foreignKeys.map(fk => ({
65
+ column: fk.column,
66
+ referencedTable: `${fk.referencedSchema}.${fk.referencedTable}`,
67
+ })),
68
+ sampleData,
69
+ existingDescription: existingDesc,
70
+ });
71
+ // Update state with table documentation
72
+ this.stateManager.updateTableAI(tableInfo.schema, tableInfo.table, {
73
+ description: aiDoc.description,
74
+ purpose: aiDoc.purpose,
75
+ usageNotes: aiDoc.usageNotes,
76
+ businessDomain: aiDoc.businessDomain,
77
+ confidence: aiDoc.confidence,
78
+ model: process.env.AI_MODEL || 'gpt-4',
79
+ tokensUsed: aiDoc.tokensUsed,
80
+ relationships: aiDoc.relationships,
81
+ });
82
+ // Update columns
83
+ for (const colDoc of aiDoc.columns) {
84
+ this.stateManager.updateColumnAI(tableInfo.schema, tableInfo.table, colDoc.name, {
85
+ description: colDoc.description,
86
+ purpose: colDoc.purpose,
87
+ validValues: colDoc.validValues,
88
+ confidence: colDoc.confidence,
89
+ model: process.env.AI_MODEL || 'gpt-4',
90
+ });
91
+ }
92
+ if (aiDoc.tokensUsed) {
93
+ totalTokens += aiDoc.tokensUsed;
94
+ }
95
+ processed++;
96
+ tableSpinner.succeed(`Processed ${tableInfo.schema}.${tableInfo.table} (confidence: ${(aiDoc.confidence * 100).toFixed(0)}%)`);
97
+ }
98
+ catch (error) {
99
+ tableSpinner.fail(`Failed to process ${tableInfo.schema}.${tableInfo.table}: ${error}`);
100
+ }
101
+ }
102
+ // Save state
103
+ await this.stateManager.save();
104
+ // Add run history
105
+ this.stateManager.addRunHistory({
106
+ timestamp: new Date().toISOString(),
107
+ phase: 'analyze',
108
+ tablesProcessed: processed,
109
+ tokensUsed: totalTokens,
110
+ cost: totalTokens * 0.000002, // Rough estimate
111
+ });
112
+ await this.stateManager.save();
113
+ console.log('');
114
+ console.log(`✅ Analysis complete!`);
115
+ console.log(` Processed: ${processed} tables`);
116
+ console.log(` Skipped: ${skipped} tables`);
117
+ console.log(` Tokens used: ${totalTokens.toLocaleString()}`);
118
+ console.log(` Estimated cost: $${(totalTokens * 0.000002).toFixed(4)}`);
119
+ }
120
+ catch (error) {
121
+ spinner.fail(`Analysis failed: ${error}`);
122
+ throw error;
123
+ }
124
+ }
125
+ }
126
+ exports.DatabaseAnalyzer = DatabaseAnalyzer;
127
+ //# sourceMappingURL=analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/analyzers/analyzer.ts"],"names":[],"mappings":"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"}