@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.
- package/README.md +244 -0
- package/bin/run.js +5 -0
- package/dist/ai/simple-ai-client.d.ts +70 -0
- package/dist/ai/simple-ai-client.d.ts.map +1 -0
- package/dist/ai/simple-ai-client.js +181 -0
- package/dist/ai/simple-ai-client.js.map +1 -0
- package/dist/analyzers/analyzer.d.ts +23 -0
- package/dist/analyzers/analyzer.d.ts.map +1 -0
- package/dist/analyzers/analyzer.js +127 -0
- package/dist/analyzers/analyzer.js.map +1 -0
- package/dist/cli-old/cli.d.ts +3 -0
- package/dist/cli-old/cli.d.ts.map +1 -0
- package/dist/cli-old/cli.js +388 -0
- package/dist/cli-old/cli.js.map +1 -0
- package/dist/commands/analyze.d.ts +13 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +98 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/export.d.ts +13 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +117 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +163 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/reset.d.ts +10 -0
- package/dist/commands/reset.d.ts.map +1 -0
- package/dist/commands/reset.js +37 -0
- package/dist/commands/reset.js.map +1 -0
- package/dist/commands/review.d.ts +11 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +82 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/database/connection.d.ts +40 -0
- package/dist/database/connection.d.ts.map +1 -0
- package/dist/database/connection.js +136 -0
- package/dist/database/connection.js.map +1 -0
- package/dist/database/introspection.d.ts +59 -0
- package/dist/database/introspection.d.ts.map +1 -0
- package/dist/database/introspection.js +124 -0
- package/dist/database/introspection.js.map +1 -0
- package/dist/generators/markdown-generator.d.ts +8 -0
- package/dist/generators/markdown-generator.d.ts.map +1 -0
- package/dist/generators/markdown-generator.js +106 -0
- package/dist/generators/markdown-generator.js.map +1 -0
- package/dist/generators/sql-generator.d.ts +20 -0
- package/dist/generators/sql-generator.d.ts.map +1 -0
- package/dist/generators/sql-generator.js +83 -0
- package/dist/generators/sql-generator.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/state/state-manager.d.ts +95 -0
- package/dist/state/state-manager.d.ts.map +1 -0
- package/dist/state/state-manager.js +236 -0
- package/dist/state/state-manager.js.map +1 -0
- package/dist/types/state-file.d.ts +124 -0
- package/dist/types/state-file.d.ts.map +1 -0
- package/dist/types/state-file.js +79 -0
- package/dist/types/state-file.js.map +1 -0
- 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,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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"}
|