@memberjunction/cli 2.108.0 ā 2.110.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/commands/dbdoc/analyze.d.ts +10 -0
- package/dist/commands/dbdoc/analyze.js +85 -0
- package/dist/commands/dbdoc/export.d.ts +12 -0
- package/dist/commands/dbdoc/export.js +113 -0
- package/dist/commands/dbdoc/index.d.ts +6 -0
- package/dist/commands/dbdoc/index.js +12 -0
- package/dist/commands/dbdoc/init.d.ts +9 -0
- package/dist/commands/dbdoc/init.js +150 -0
- package/dist/commands/dbdoc/review.d.ts +10 -0
- package/dist/commands/dbdoc/review.js +81 -0
- package/oclif.manifest.json +227 -33
- package/package.json +6 -5
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Analyze extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
incremental: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
schemas: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const core_1 = require("@oclif/core");
|
|
30
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
31
|
+
const dotenv = __importStar(require("dotenv"));
|
|
32
|
+
const db_auto_doc_1 = require("@memberjunction/db-auto-doc");
|
|
33
|
+
dotenv.config();
|
|
34
|
+
class Analyze extends core_1.Command {
|
|
35
|
+
static description = 'Analyze database and generate documentation';
|
|
36
|
+
static examples = [
|
|
37
|
+
'<%= config.bin %> <%= command.id %>',
|
|
38
|
+
'<%= config.bin %> <%= command.id %> --incremental',
|
|
39
|
+
'<%= config.bin %> <%= command.id %> --schemas dbo,sales',
|
|
40
|
+
];
|
|
41
|
+
static flags = {
|
|
42
|
+
incremental: core_1.Flags.boolean({
|
|
43
|
+
description: 'Only process new tables',
|
|
44
|
+
default: false,
|
|
45
|
+
}),
|
|
46
|
+
schemas: core_1.Flags.string({
|
|
47
|
+
description: 'Comma-separated schema list',
|
|
48
|
+
}),
|
|
49
|
+
};
|
|
50
|
+
async run() {
|
|
51
|
+
const { flags } = await this.parse(Analyze);
|
|
52
|
+
this.log(chalk_1.default.blue.bold('\nš Analyzing Database\n'));
|
|
53
|
+
try {
|
|
54
|
+
// Check API key
|
|
55
|
+
if (!process.env.AI_API_KEY || process.env.AI_API_KEY === 'your-api-key-here') {
|
|
56
|
+
this.error('AI_API_KEY not set in .env file');
|
|
57
|
+
}
|
|
58
|
+
const connection = db_auto_doc_1.DatabaseConnection.fromEnv();
|
|
59
|
+
const stateManager = new db_auto_doc_1.StateManager();
|
|
60
|
+
// Test connection
|
|
61
|
+
const connected = await connection.test();
|
|
62
|
+
if (!connected) {
|
|
63
|
+
this.error('Cannot connect to database');
|
|
64
|
+
}
|
|
65
|
+
// Load state
|
|
66
|
+
await stateManager.load(process.env.DB_SERVER || 'localhost', process.env.DB_DATABASE || 'master');
|
|
67
|
+
const aiClient = new db_auto_doc_1.SimpleAIClient();
|
|
68
|
+
const analyzer = new db_auto_doc_1.DatabaseAnalyzer(connection, stateManager, aiClient);
|
|
69
|
+
const schemas = flags.schemas ? flags.schemas.split(',') : undefined;
|
|
70
|
+
await analyzer.analyze({
|
|
71
|
+
schemas,
|
|
72
|
+
incremental: flags.incremental,
|
|
73
|
+
});
|
|
74
|
+
await connection.close();
|
|
75
|
+
this.log(chalk_1.default.green('\nā
Analysis complete!'));
|
|
76
|
+
this.log('\nNext steps:');
|
|
77
|
+
this.log(' - Review: mj dbdoc review');
|
|
78
|
+
this.log(' - Export: mj dbdoc export');
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
this.error(error.message);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.default = Analyze;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Export extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
format: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
|
+
output: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
|
+
'approved-only': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
execute: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const core_1 = require("@oclif/core");
|
|
30
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
31
|
+
const ora_classic_1 = __importDefault(require("ora-classic"));
|
|
32
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
33
|
+
const fs = __importStar(require("fs/promises"));
|
|
34
|
+
const path = __importStar(require("path"));
|
|
35
|
+
const db_auto_doc_1 = require("@memberjunction/db-auto-doc");
|
|
36
|
+
class Export extends core_1.Command {
|
|
37
|
+
static description = 'Generate output files (SQL scripts, markdown documentation)';
|
|
38
|
+
static examples = [
|
|
39
|
+
'<%= config.bin %> <%= command.id %>',
|
|
40
|
+
'<%= config.bin %> <%= command.id %> --format sql',
|
|
41
|
+
'<%= config.bin %> <%= command.id %> --format markdown --output ./docs',
|
|
42
|
+
'<%= config.bin %> <%= command.id %> --execute --approved-only',
|
|
43
|
+
];
|
|
44
|
+
static flags = {
|
|
45
|
+
format: core_1.Flags.string({
|
|
46
|
+
description: 'Output format',
|
|
47
|
+
options: ['sql', 'markdown', 'all'],
|
|
48
|
+
default: 'all',
|
|
49
|
+
}),
|
|
50
|
+
output: core_1.Flags.string({
|
|
51
|
+
description: 'Output directory',
|
|
52
|
+
default: './docs',
|
|
53
|
+
}),
|
|
54
|
+
'approved-only': core_1.Flags.boolean({
|
|
55
|
+
description: 'Only export approved items',
|
|
56
|
+
default: false,
|
|
57
|
+
}),
|
|
58
|
+
execute: core_1.Flags.boolean({
|
|
59
|
+
description: 'Execute SQL script (apply to database)',
|
|
60
|
+
default: false,
|
|
61
|
+
}),
|
|
62
|
+
};
|
|
63
|
+
async run() {
|
|
64
|
+
const { flags } = await this.parse(Export);
|
|
65
|
+
this.log(chalk_1.default.blue.bold('\nš¤ Exporting Documentation\n'));
|
|
66
|
+
try {
|
|
67
|
+
const stateManager = new db_auto_doc_1.StateManager();
|
|
68
|
+
const state = await stateManager.load();
|
|
69
|
+
const outputDir = flags.output;
|
|
70
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
71
|
+
if (flags.format === 'sql' || flags.format === 'all') {
|
|
72
|
+
const sqlGen = new db_auto_doc_1.SQLGenerator();
|
|
73
|
+
const sql = sqlGen.generate(state, {
|
|
74
|
+
approvedOnly: flags['approved-only'],
|
|
75
|
+
});
|
|
76
|
+
const sqlPath = path.join(outputDir, 'extended-properties.sql');
|
|
77
|
+
await fs.writeFile(sqlPath, sql);
|
|
78
|
+
this.log(chalk_1.default.green(`ā Generated SQL: ${sqlPath}`));
|
|
79
|
+
if (flags.execute) {
|
|
80
|
+
const confirmed = await (0, prompts_1.confirm)({
|
|
81
|
+
message: chalk_1.default.yellow('Execute SQL script? This will modify your database.'),
|
|
82
|
+
default: false,
|
|
83
|
+
});
|
|
84
|
+
if (confirmed) {
|
|
85
|
+
const connection = db_auto_doc_1.DatabaseConnection.fromEnv();
|
|
86
|
+
const spinner = (0, ora_classic_1.default)('Executing SQL...').start();
|
|
87
|
+
try {
|
|
88
|
+
await connection.query(sql);
|
|
89
|
+
spinner.succeed('SQL executed successfully');
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
spinner.fail('SQL execution failed');
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
await connection.close();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (flags.format === 'markdown' || flags.format === 'all') {
|
|
100
|
+
const mdGen = new db_auto_doc_1.MarkdownGenerator();
|
|
101
|
+
const markdown = mdGen.generate(state);
|
|
102
|
+
const mdPath = path.join(outputDir, 'database-documentation.md');
|
|
103
|
+
await fs.writeFile(mdPath, markdown);
|
|
104
|
+
this.log(chalk_1.default.green(`ā Generated Markdown: ${mdPath}`));
|
|
105
|
+
}
|
|
106
|
+
this.log(chalk_1.default.green('\nā
Export complete!'));
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
this.error(error.message);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.default = Export;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
class DBDoc extends core_1.Command {
|
|
5
|
+
static description = 'AI-powered database documentation generator';
|
|
6
|
+
static hidden = false;
|
|
7
|
+
async run() {
|
|
8
|
+
// This command just displays help for the dbdoc topic
|
|
9
|
+
await this.config.runCommand('help', ['dbdoc']);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.default = DBDoc;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Init extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
interactive: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
};
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const core_1 = require("@oclif/core");
|
|
30
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
31
|
+
const ora_classic_1 = __importDefault(require("ora-classic"));
|
|
32
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
33
|
+
const fs = __importStar(require("fs/promises"));
|
|
34
|
+
const path = __importStar(require("path"));
|
|
35
|
+
const db_auto_doc_1 = require("@memberjunction/db-auto-doc");
|
|
36
|
+
class Init extends core_1.Command {
|
|
37
|
+
static description = 'Initialize database documentation project';
|
|
38
|
+
static examples = [
|
|
39
|
+
'<%= config.bin %> <%= command.id %>',
|
|
40
|
+
];
|
|
41
|
+
static flags = {
|
|
42
|
+
interactive: core_1.Flags.boolean({
|
|
43
|
+
description: 'Interactive setup',
|
|
44
|
+
default: true,
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
async run() {
|
|
48
|
+
const { flags } = await this.parse(Init);
|
|
49
|
+
this.log(chalk_1.default.blue.bold('\nš Database Documentation Generator\n'));
|
|
50
|
+
try {
|
|
51
|
+
let server;
|
|
52
|
+
let database;
|
|
53
|
+
let user;
|
|
54
|
+
let pwd;
|
|
55
|
+
if (flags.interactive) {
|
|
56
|
+
server = await (0, prompts_1.input)({
|
|
57
|
+
message: 'Database server:',
|
|
58
|
+
default: 'localhost',
|
|
59
|
+
});
|
|
60
|
+
database = await (0, prompts_1.input)({
|
|
61
|
+
message: 'Database name:',
|
|
62
|
+
validate: (val) => (val ? true : 'Database name required'),
|
|
63
|
+
});
|
|
64
|
+
user = await (0, prompts_1.input)({
|
|
65
|
+
message: 'Username:',
|
|
66
|
+
default: 'sa',
|
|
67
|
+
});
|
|
68
|
+
pwd = await (0, prompts_1.password)({
|
|
69
|
+
message: 'Password:',
|
|
70
|
+
mask: '*',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
server = process.env.DB_SERVER || 'localhost';
|
|
75
|
+
database = process.env.DB_DATABASE || '';
|
|
76
|
+
user = process.env.DB_USER || 'sa';
|
|
77
|
+
pwd = process.env.DB_PASSWORD || '';
|
|
78
|
+
}
|
|
79
|
+
// Test connection
|
|
80
|
+
const spinner = (0, ora_classic_1.default)('Testing database connection...').start();
|
|
81
|
+
const connection = new db_auto_doc_1.DatabaseConnection({
|
|
82
|
+
server,
|
|
83
|
+
database,
|
|
84
|
+
user,
|
|
85
|
+
password: pwd,
|
|
86
|
+
encrypt: true,
|
|
87
|
+
trustServerCertificate: true,
|
|
88
|
+
});
|
|
89
|
+
const connected = await connection.test();
|
|
90
|
+
if (!connected) {
|
|
91
|
+
spinner.fail('Connection failed');
|
|
92
|
+
this.exit(1);
|
|
93
|
+
}
|
|
94
|
+
spinner.succeed('Connection successful');
|
|
95
|
+
// Create .env file
|
|
96
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
97
|
+
const envContent = `
|
|
98
|
+
# Database Connection
|
|
99
|
+
DB_SERVER=${server}
|
|
100
|
+
DB_DATABASE=${database}
|
|
101
|
+
DB_USER=${user}
|
|
102
|
+
DB_PASSWORD=${pwd}
|
|
103
|
+
DB_ENCRYPT=true
|
|
104
|
+
DB_TRUST_SERVER_CERTIFICATE=true
|
|
105
|
+
|
|
106
|
+
# AI Configuration
|
|
107
|
+
AI_PROVIDER=openai
|
|
108
|
+
AI_MODEL=gpt-4
|
|
109
|
+
AI_API_KEY=your-api-key-here
|
|
110
|
+
`.trim();
|
|
111
|
+
await fs.writeFile(envPath, envContent);
|
|
112
|
+
this.log(chalk_1.default.green('ā Created .env file'));
|
|
113
|
+
// Create state file
|
|
114
|
+
const stateManager = new db_auto_doc_1.StateManager();
|
|
115
|
+
await stateManager.reset(server, database);
|
|
116
|
+
this.log(chalk_1.default.green('ā Created db-doc-state.json'));
|
|
117
|
+
// Ask seed questions
|
|
118
|
+
if (flags.interactive) {
|
|
119
|
+
const addSeed = await (0, prompts_1.confirm)({
|
|
120
|
+
message: 'Would you like to provide seed context?',
|
|
121
|
+
default: true,
|
|
122
|
+
});
|
|
123
|
+
if (addSeed) {
|
|
124
|
+
const purpose = await (0, prompts_1.input)({
|
|
125
|
+
message: 'Overall database purpose:',
|
|
126
|
+
});
|
|
127
|
+
const domains = await (0, prompts_1.input)({
|
|
128
|
+
message: 'Business domains (comma-separated):',
|
|
129
|
+
});
|
|
130
|
+
const state = stateManager.getState();
|
|
131
|
+
state.seedContext = {
|
|
132
|
+
overallPurpose: purpose,
|
|
133
|
+
businessDomains: domains.split(',').map((d) => d.trim()),
|
|
134
|
+
};
|
|
135
|
+
await stateManager.save();
|
|
136
|
+
this.log(chalk_1.default.green('ā Saved seed context'));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
this.log(chalk_1.default.green.bold('\nā
Initialization complete!\n'));
|
|
140
|
+
this.log('Next steps:');
|
|
141
|
+
this.log(' 1. Edit .env and add your AI API key');
|
|
142
|
+
this.log(' 2. Run: mj dbdoc analyze');
|
|
143
|
+
await connection.close();
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
this.error(error.message);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
exports.default = Init;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Review extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
schema: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
|
+
'unapproved-only': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
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
|
+
const core_1 = require("@oclif/core");
|
|
7
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const db_auto_doc_1 = require("@memberjunction/db-auto-doc");
|
|
10
|
+
class Review extends core_1.Command {
|
|
11
|
+
static description = 'Review and approve AI-generated documentation';
|
|
12
|
+
static examples = [
|
|
13
|
+
'<%= config.bin %> <%= command.id %>',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> --schema dbo',
|
|
15
|
+
'<%= config.bin %> <%= command.id %> --unapproved-only',
|
|
16
|
+
];
|
|
17
|
+
static flags = {
|
|
18
|
+
schema: core_1.Flags.string({
|
|
19
|
+
description: 'Review specific schema',
|
|
20
|
+
}),
|
|
21
|
+
'unapproved-only': core_1.Flags.boolean({
|
|
22
|
+
description: 'Only show unapproved items',
|
|
23
|
+
default: false,
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
async run() {
|
|
27
|
+
const { flags } = await this.parse(Review);
|
|
28
|
+
this.log(chalk_1.default.blue.bold('\nš Review Documentation\n'));
|
|
29
|
+
try {
|
|
30
|
+
const stateManager = new db_auto_doc_1.StateManager();
|
|
31
|
+
const state = await stateManager.load();
|
|
32
|
+
const unapproved = stateManager.getUnapprovedTables(flags.schema);
|
|
33
|
+
if (unapproved.length === 0) {
|
|
34
|
+
this.log(chalk_1.default.green('ā
All tables approved!'));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
this.log(`Found ${unapproved.length} unapproved tables\n`);
|
|
38
|
+
for (const { schema, table } of unapproved) {
|
|
39
|
+
const schemaState = state.schemas[schema];
|
|
40
|
+
const tableState = schemaState.tables[table];
|
|
41
|
+
this.log(chalk_1.default.cyan.bold(`\n${schema}.${table}`));
|
|
42
|
+
this.log('ā'.repeat(50));
|
|
43
|
+
if (tableState.aiGenerated) {
|
|
44
|
+
this.log(chalk_1.default.white('Description:'));
|
|
45
|
+
this.log(tableState.aiGenerated.description);
|
|
46
|
+
this.log('');
|
|
47
|
+
this.log(chalk_1.default.gray(`Confidence: ${(tableState.aiGenerated.confidence * 100).toFixed(0)}%`));
|
|
48
|
+
}
|
|
49
|
+
const action = await (0, prompts_1.select)({
|
|
50
|
+
message: 'Action:',
|
|
51
|
+
choices: [
|
|
52
|
+
{ name: 'Approve', value: 'approve' },
|
|
53
|
+
{ name: 'Add notes', value: 'notes' },
|
|
54
|
+
{ name: 'Skip', value: 'skip' },
|
|
55
|
+
{ name: 'Exit review', value: 'exit' },
|
|
56
|
+
],
|
|
57
|
+
});
|
|
58
|
+
if (action === 'exit') {
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
if (action === 'approve') {
|
|
62
|
+
stateManager.approveTable(schema, table);
|
|
63
|
+
this.log(chalk_1.default.green('ā Approved'));
|
|
64
|
+
}
|
|
65
|
+
if (action === 'notes') {
|
|
66
|
+
const notes = await (0, prompts_1.input)({
|
|
67
|
+
message: 'Enter notes:',
|
|
68
|
+
});
|
|
69
|
+
stateManager.addTableNotes(schema, table, notes);
|
|
70
|
+
this.log(chalk_1.default.green('ā Notes added'));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
await stateManager.save();
|
|
74
|
+
this.log(chalk_1.default.green('\nā
Review complete!'));
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
this.error(error.message);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.default = Review;
|
package/oclif.manifest.json
CHANGED
|
@@ -22,38 +22,6 @@
|
|
|
22
22
|
"index.js"
|
|
23
23
|
]
|
|
24
24
|
},
|
|
25
|
-
"clean": {
|
|
26
|
-
"aliases": [],
|
|
27
|
-
"args": {},
|
|
28
|
-
"description": "Resets the MemberJunction database to a pre-installation state",
|
|
29
|
-
"examples": [
|
|
30
|
-
"<%= config.bin %> <%= command.id %>\n"
|
|
31
|
-
],
|
|
32
|
-
"flags": {
|
|
33
|
-
"verbose": {
|
|
34
|
-
"char": "v",
|
|
35
|
-
"description": "Enable additional logging",
|
|
36
|
-
"name": "verbose",
|
|
37
|
-
"allowNo": false,
|
|
38
|
-
"type": "boolean"
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
"hasDynamicHelp": false,
|
|
42
|
-
"hiddenAliases": [],
|
|
43
|
-
"id": "clean",
|
|
44
|
-
"pluginAlias": "@memberjunction/cli",
|
|
45
|
-
"pluginName": "@memberjunction/cli",
|
|
46
|
-
"pluginType": "core",
|
|
47
|
-
"strict": true,
|
|
48
|
-
"enableJsonFlag": false,
|
|
49
|
-
"isESM": false,
|
|
50
|
-
"relativePath": [
|
|
51
|
-
"dist",
|
|
52
|
-
"commands",
|
|
53
|
-
"clean",
|
|
54
|
-
"index.js"
|
|
55
|
-
]
|
|
56
|
-
},
|
|
57
25
|
"bump": {
|
|
58
26
|
"aliases": [],
|
|
59
27
|
"args": {},
|
|
@@ -126,6 +94,38 @@
|
|
|
126
94
|
"index.js"
|
|
127
95
|
]
|
|
128
96
|
},
|
|
97
|
+
"clean": {
|
|
98
|
+
"aliases": [],
|
|
99
|
+
"args": {},
|
|
100
|
+
"description": "Resets the MemberJunction database to a pre-installation state",
|
|
101
|
+
"examples": [
|
|
102
|
+
"<%= config.bin %> <%= command.id %>\n"
|
|
103
|
+
],
|
|
104
|
+
"flags": {
|
|
105
|
+
"verbose": {
|
|
106
|
+
"char": "v",
|
|
107
|
+
"description": "Enable additional logging",
|
|
108
|
+
"name": "verbose",
|
|
109
|
+
"allowNo": false,
|
|
110
|
+
"type": "boolean"
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"hasDynamicHelp": false,
|
|
114
|
+
"hiddenAliases": [],
|
|
115
|
+
"id": "clean",
|
|
116
|
+
"pluginAlias": "@memberjunction/cli",
|
|
117
|
+
"pluginName": "@memberjunction/cli",
|
|
118
|
+
"pluginType": "core",
|
|
119
|
+
"strict": true,
|
|
120
|
+
"enableJsonFlag": false,
|
|
121
|
+
"isESM": false,
|
|
122
|
+
"relativePath": [
|
|
123
|
+
"dist",
|
|
124
|
+
"commands",
|
|
125
|
+
"clean",
|
|
126
|
+
"index.js"
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
129
|
"codegen": {
|
|
130
130
|
"aliases": [],
|
|
131
131
|
"args": {},
|
|
@@ -157,6 +157,200 @@
|
|
|
157
157
|
"index.js"
|
|
158
158
|
]
|
|
159
159
|
},
|
|
160
|
+
"dbdoc:analyze": {
|
|
161
|
+
"aliases": [],
|
|
162
|
+
"args": {},
|
|
163
|
+
"description": "Analyze database and generate documentation",
|
|
164
|
+
"examples": [
|
|
165
|
+
"<%= config.bin %> <%= command.id %>",
|
|
166
|
+
"<%= config.bin %> <%= command.id %> --incremental",
|
|
167
|
+
"<%= config.bin %> <%= command.id %> --schemas dbo,sales"
|
|
168
|
+
],
|
|
169
|
+
"flags": {
|
|
170
|
+
"incremental": {
|
|
171
|
+
"description": "Only process new tables",
|
|
172
|
+
"name": "incremental",
|
|
173
|
+
"allowNo": false,
|
|
174
|
+
"type": "boolean"
|
|
175
|
+
},
|
|
176
|
+
"schemas": {
|
|
177
|
+
"description": "Comma-separated schema list",
|
|
178
|
+
"name": "schemas",
|
|
179
|
+
"hasDynamicHelp": false,
|
|
180
|
+
"multiple": false,
|
|
181
|
+
"type": "option"
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
"hasDynamicHelp": false,
|
|
185
|
+
"hiddenAliases": [],
|
|
186
|
+
"id": "dbdoc:analyze",
|
|
187
|
+
"pluginAlias": "@memberjunction/cli",
|
|
188
|
+
"pluginName": "@memberjunction/cli",
|
|
189
|
+
"pluginType": "core",
|
|
190
|
+
"strict": true,
|
|
191
|
+
"enableJsonFlag": false,
|
|
192
|
+
"isESM": false,
|
|
193
|
+
"relativePath": [
|
|
194
|
+
"dist",
|
|
195
|
+
"commands",
|
|
196
|
+
"dbdoc",
|
|
197
|
+
"analyze.js"
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
"dbdoc:export": {
|
|
201
|
+
"aliases": [],
|
|
202
|
+
"args": {},
|
|
203
|
+
"description": "Generate output files (SQL scripts, markdown documentation)",
|
|
204
|
+
"examples": [
|
|
205
|
+
"<%= config.bin %> <%= command.id %>",
|
|
206
|
+
"<%= config.bin %> <%= command.id %> --format sql",
|
|
207
|
+
"<%= config.bin %> <%= command.id %> --format markdown --output ./docs",
|
|
208
|
+
"<%= config.bin %> <%= command.id %> --execute --approved-only"
|
|
209
|
+
],
|
|
210
|
+
"flags": {
|
|
211
|
+
"format": {
|
|
212
|
+
"description": "Output format",
|
|
213
|
+
"name": "format",
|
|
214
|
+
"default": "all",
|
|
215
|
+
"hasDynamicHelp": false,
|
|
216
|
+
"multiple": false,
|
|
217
|
+
"options": [
|
|
218
|
+
"sql",
|
|
219
|
+
"markdown",
|
|
220
|
+
"all"
|
|
221
|
+
],
|
|
222
|
+
"type": "option"
|
|
223
|
+
},
|
|
224
|
+
"output": {
|
|
225
|
+
"description": "Output directory",
|
|
226
|
+
"name": "output",
|
|
227
|
+
"default": "./docs",
|
|
228
|
+
"hasDynamicHelp": false,
|
|
229
|
+
"multiple": false,
|
|
230
|
+
"type": "option"
|
|
231
|
+
},
|
|
232
|
+
"approved-only": {
|
|
233
|
+
"description": "Only export approved items",
|
|
234
|
+
"name": "approved-only",
|
|
235
|
+
"allowNo": false,
|
|
236
|
+
"type": "boolean"
|
|
237
|
+
},
|
|
238
|
+
"execute": {
|
|
239
|
+
"description": "Execute SQL script (apply to database)",
|
|
240
|
+
"name": "execute",
|
|
241
|
+
"allowNo": false,
|
|
242
|
+
"type": "boolean"
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
"hasDynamicHelp": false,
|
|
246
|
+
"hiddenAliases": [],
|
|
247
|
+
"id": "dbdoc:export",
|
|
248
|
+
"pluginAlias": "@memberjunction/cli",
|
|
249
|
+
"pluginName": "@memberjunction/cli",
|
|
250
|
+
"pluginType": "core",
|
|
251
|
+
"strict": true,
|
|
252
|
+
"enableJsonFlag": false,
|
|
253
|
+
"isESM": false,
|
|
254
|
+
"relativePath": [
|
|
255
|
+
"dist",
|
|
256
|
+
"commands",
|
|
257
|
+
"dbdoc",
|
|
258
|
+
"export.js"
|
|
259
|
+
]
|
|
260
|
+
},
|
|
261
|
+
"dbdoc": {
|
|
262
|
+
"aliases": [],
|
|
263
|
+
"args": {},
|
|
264
|
+
"description": "AI-powered database documentation generator",
|
|
265
|
+
"flags": {},
|
|
266
|
+
"hasDynamicHelp": false,
|
|
267
|
+
"hidden": false,
|
|
268
|
+
"hiddenAliases": [],
|
|
269
|
+
"id": "dbdoc",
|
|
270
|
+
"pluginAlias": "@memberjunction/cli",
|
|
271
|
+
"pluginName": "@memberjunction/cli",
|
|
272
|
+
"pluginType": "core",
|
|
273
|
+
"strict": true,
|
|
274
|
+
"enableJsonFlag": false,
|
|
275
|
+
"isESM": false,
|
|
276
|
+
"relativePath": [
|
|
277
|
+
"dist",
|
|
278
|
+
"commands",
|
|
279
|
+
"dbdoc",
|
|
280
|
+
"index.js"
|
|
281
|
+
]
|
|
282
|
+
},
|
|
283
|
+
"dbdoc:init": {
|
|
284
|
+
"aliases": [],
|
|
285
|
+
"args": {},
|
|
286
|
+
"description": "Initialize database documentation project",
|
|
287
|
+
"examples": [
|
|
288
|
+
"<%= config.bin %> <%= command.id %>"
|
|
289
|
+
],
|
|
290
|
+
"flags": {
|
|
291
|
+
"interactive": {
|
|
292
|
+
"description": "Interactive setup",
|
|
293
|
+
"name": "interactive",
|
|
294
|
+
"allowNo": false,
|
|
295
|
+
"type": "boolean"
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
"hasDynamicHelp": false,
|
|
299
|
+
"hiddenAliases": [],
|
|
300
|
+
"id": "dbdoc:init",
|
|
301
|
+
"pluginAlias": "@memberjunction/cli",
|
|
302
|
+
"pluginName": "@memberjunction/cli",
|
|
303
|
+
"pluginType": "core",
|
|
304
|
+
"strict": true,
|
|
305
|
+
"enableJsonFlag": false,
|
|
306
|
+
"isESM": false,
|
|
307
|
+
"relativePath": [
|
|
308
|
+
"dist",
|
|
309
|
+
"commands",
|
|
310
|
+
"dbdoc",
|
|
311
|
+
"init.js"
|
|
312
|
+
]
|
|
313
|
+
},
|
|
314
|
+
"dbdoc:review": {
|
|
315
|
+
"aliases": [],
|
|
316
|
+
"args": {},
|
|
317
|
+
"description": "Review and approve AI-generated documentation",
|
|
318
|
+
"examples": [
|
|
319
|
+
"<%= config.bin %> <%= command.id %>",
|
|
320
|
+
"<%= config.bin %> <%= command.id %> --schema dbo",
|
|
321
|
+
"<%= config.bin %> <%= command.id %> --unapproved-only"
|
|
322
|
+
],
|
|
323
|
+
"flags": {
|
|
324
|
+
"schema": {
|
|
325
|
+
"description": "Review specific schema",
|
|
326
|
+
"name": "schema",
|
|
327
|
+
"hasDynamicHelp": false,
|
|
328
|
+
"multiple": false,
|
|
329
|
+
"type": "option"
|
|
330
|
+
},
|
|
331
|
+
"unapproved-only": {
|
|
332
|
+
"description": "Only show unapproved items",
|
|
333
|
+
"name": "unapproved-only",
|
|
334
|
+
"allowNo": false,
|
|
335
|
+
"type": "boolean"
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
"hasDynamicHelp": false,
|
|
339
|
+
"hiddenAliases": [],
|
|
340
|
+
"id": "dbdoc:review",
|
|
341
|
+
"pluginAlias": "@memberjunction/cli",
|
|
342
|
+
"pluginName": "@memberjunction/cli",
|
|
343
|
+
"pluginType": "core",
|
|
344
|
+
"strict": true,
|
|
345
|
+
"enableJsonFlag": false,
|
|
346
|
+
"isESM": false,
|
|
347
|
+
"relativePath": [
|
|
348
|
+
"dist",
|
|
349
|
+
"commands",
|
|
350
|
+
"dbdoc",
|
|
351
|
+
"review.js"
|
|
352
|
+
]
|
|
353
|
+
},
|
|
160
354
|
"install": {
|
|
161
355
|
"aliases": [],
|
|
162
356
|
"args": {},
|
|
@@ -1061,5 +1255,5 @@
|
|
|
1061
1255
|
]
|
|
1062
1256
|
}
|
|
1063
1257
|
},
|
|
1064
|
-
"version": "2.
|
|
1258
|
+
"version": "2.110.0"
|
|
1065
1259
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.110.0",
|
|
4
4
|
"description": "MemberJunction command line tools",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oclif"
|
|
@@ -51,10 +51,11 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@inquirer/prompts": "^5.0.1",
|
|
54
|
-
"@memberjunction/ai-cli": "2.
|
|
55
|
-
"@memberjunction/codegen-lib": "2.
|
|
56
|
-
"@memberjunction/
|
|
57
|
-
"@memberjunction/
|
|
54
|
+
"@memberjunction/ai-cli": "2.110.0",
|
|
55
|
+
"@memberjunction/codegen-lib": "2.110.0",
|
|
56
|
+
"@memberjunction/db-auto-doc": "2.110.0",
|
|
57
|
+
"@memberjunction/metadata-sync": "2.110.0",
|
|
58
|
+
"@memberjunction/sqlserver-dataprovider": "2.110.0",
|
|
58
59
|
"@oclif/core": "^3",
|
|
59
60
|
"@oclif/plugin-help": "^6",
|
|
60
61
|
"@oclif/plugin-version": "^2.0.17",
|