@memberjunction/query-gen 0.0.1 → 2.126.1

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 (138) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +34 -0
  3. package/COORDINATOR.md +768 -0
  4. package/IMPLEMENTATION_PLAN.md +1753 -0
  5. package/LLM_ENTITY_GROUPING_PLAN.md +977 -0
  6. package/README.md +675 -29
  7. package/dist/cli/commands/export.d.ts +15 -0
  8. package/dist/cli/commands/export.d.ts.map +1 -0
  9. package/dist/cli/commands/export.js +178 -0
  10. package/dist/cli/commands/export.js.map +1 -0
  11. package/dist/cli/commands/generate.d.ts +19 -0
  12. package/dist/cli/commands/generate.d.ts.map +1 -0
  13. package/dist/cli/commands/generate.js +282 -0
  14. package/dist/cli/commands/generate.js.map +1 -0
  15. package/dist/cli/commands/validate.d.ts +17 -0
  16. package/dist/cli/commands/validate.d.ts.map +1 -0
  17. package/dist/cli/commands/validate.js +193 -0
  18. package/dist/cli/commands/validate.js.map +1 -0
  19. package/dist/cli/config.d.ts +51 -0
  20. package/dist/cli/config.d.ts.map +1 -0
  21. package/dist/cli/config.js +142 -0
  22. package/dist/cli/config.js.map +1 -0
  23. package/dist/cli/index.d.ts +13 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +57 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/core/EntityGrouper.d.ts +74 -0
  28. package/dist/core/EntityGrouper.d.ts.map +1 -0
  29. package/dist/core/EntityGrouper.js +246 -0
  30. package/dist/core/EntityGrouper.js.map +1 -0
  31. package/dist/core/MetadataExporter.d.ts +59 -0
  32. package/dist/core/MetadataExporter.d.ts.map +1 -0
  33. package/dist/core/MetadataExporter.js +151 -0
  34. package/dist/core/MetadataExporter.js.map +1 -0
  35. package/dist/core/QueryDatabaseWriter.d.ts +50 -0
  36. package/dist/core/QueryDatabaseWriter.d.ts.map +1 -0
  37. package/dist/core/QueryDatabaseWriter.js +152 -0
  38. package/dist/core/QueryDatabaseWriter.js.map +1 -0
  39. package/dist/core/QueryFixer.d.ts +48 -0
  40. package/dist/core/QueryFixer.d.ts.map +1 -0
  41. package/dist/core/QueryFixer.js +115 -0
  42. package/dist/core/QueryFixer.js.map +1 -0
  43. package/dist/core/QueryRefiner.d.ts +94 -0
  44. package/dist/core/QueryRefiner.d.ts.map +1 -0
  45. package/dist/core/QueryRefiner.js +267 -0
  46. package/dist/core/QueryRefiner.js.map +1 -0
  47. package/dist/core/QueryTester.d.ts +70 -0
  48. package/dist/core/QueryTester.d.ts.map +1 -0
  49. package/dist/core/QueryTester.js +243 -0
  50. package/dist/core/QueryTester.js.map +1 -0
  51. package/dist/core/QueryWriter.d.ts +57 -0
  52. package/dist/core/QueryWriter.d.ts.map +1 -0
  53. package/dist/core/QueryWriter.js +184 -0
  54. package/dist/core/QueryWriter.js.map +1 -0
  55. package/dist/core/QuestionGenerator.d.ts +58 -0
  56. package/dist/core/QuestionGenerator.d.ts.map +1 -0
  57. package/dist/core/QuestionGenerator.js +145 -0
  58. package/dist/core/QuestionGenerator.js.map +1 -0
  59. package/dist/data/schema.d.ts +230 -0
  60. package/dist/data/schema.d.ts.map +1 -0
  61. package/dist/data/schema.js +6 -0
  62. package/dist/data/schema.js.map +1 -0
  63. package/dist/index.d.ts +28 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +77 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/prompts/PromptNames.d.ts +32 -0
  68. package/dist/prompts/PromptNames.d.ts.map +1 -0
  69. package/dist/prompts/PromptNames.js +35 -0
  70. package/dist/prompts/PromptNames.js.map +1 -0
  71. package/dist/utils/category-builder.d.ts +28 -0
  72. package/dist/utils/category-builder.d.ts.map +1 -0
  73. package/dist/utils/category-builder.js +90 -0
  74. package/dist/utils/category-builder.js.map +1 -0
  75. package/dist/utils/entity-helpers.d.ts +49 -0
  76. package/dist/utils/entity-helpers.d.ts.map +1 -0
  77. package/dist/utils/entity-helpers.js +189 -0
  78. package/dist/utils/entity-helpers.js.map +1 -0
  79. package/dist/utils/error-handlers.d.ts +19 -0
  80. package/dist/utils/error-handlers.d.ts.map +1 -0
  81. package/dist/utils/error-handlers.js +41 -0
  82. package/dist/utils/error-handlers.js.map +1 -0
  83. package/dist/utils/graph-helpers.d.ts +51 -0
  84. package/dist/utils/graph-helpers.d.ts.map +1 -0
  85. package/dist/utils/graph-helpers.js +82 -0
  86. package/dist/utils/graph-helpers.js.map +1 -0
  87. package/dist/utils/prompt-helpers.d.ts +25 -0
  88. package/dist/utils/prompt-helpers.d.ts.map +1 -0
  89. package/dist/utils/prompt-helpers.js +66 -0
  90. package/dist/utils/prompt-helpers.js.map +1 -0
  91. package/dist/utils/query-helpers.d.ts +23 -0
  92. package/dist/utils/query-helpers.d.ts.map +1 -0
  93. package/dist/utils/query-helpers.js +34 -0
  94. package/dist/utils/query-helpers.js.map +1 -0
  95. package/dist/utils/user-helpers.d.ts +15 -0
  96. package/dist/utils/user-helpers.d.ts.map +1 -0
  97. package/dist/utils/user-helpers.js +32 -0
  98. package/dist/utils/user-helpers.js.map +1 -0
  99. package/dist/vectors/EmbeddingService.d.ts +58 -0
  100. package/dist/vectors/EmbeddingService.d.ts.map +1 -0
  101. package/dist/vectors/EmbeddingService.js +90 -0
  102. package/dist/vectors/EmbeddingService.js.map +1 -0
  103. package/dist/vectors/SimilaritySearch.d.ts +51 -0
  104. package/dist/vectors/SimilaritySearch.d.ts.map +1 -0
  105. package/dist/vectors/SimilaritySearch.js +85 -0
  106. package/dist/vectors/SimilaritySearch.js.map +1 -0
  107. package/docs/API.md +1040 -0
  108. package/docs/ARCHITECTURE.md +1120 -0
  109. package/examples/advanced-usage.ts +401 -0
  110. package/examples/basic-usage.ts +285 -0
  111. package/package.json +48 -6
  112. package/src/cli/commands/export.ts +173 -0
  113. package/src/cli/commands/generate.ts +330 -0
  114. package/src/cli/commands/validate.ts +185 -0
  115. package/src/cli/config.ts +203 -0
  116. package/src/cli/index.ts +63 -0
  117. package/src/core/EntityGrouper.ts +318 -0
  118. package/src/core/MetadataExporter.ts +148 -0
  119. package/src/core/QueryDatabaseWriter.ts +187 -0
  120. package/src/core/QueryFixer.ts +153 -0
  121. package/src/core/QueryRefiner.ts +382 -0
  122. package/src/core/QueryTester.ts +264 -0
  123. package/src/core/QueryWriter.ts +239 -0
  124. package/src/core/QuestionGenerator.ts +199 -0
  125. package/src/data/golden-queries.json +1371 -0
  126. package/src/data/schema.ts +252 -0
  127. package/src/index.ts +49 -0
  128. package/src/prompts/PromptNames.ts +36 -0
  129. package/src/utils/category-builder.ts +97 -0
  130. package/src/utils/entity-helpers.ts +203 -0
  131. package/src/utils/error-handlers.ts +41 -0
  132. package/src/utils/graph-helpers.ts +99 -0
  133. package/src/utils/prompt-helpers.ts +79 -0
  134. package/src/utils/query-helpers.ts +32 -0
  135. package/src/utils/user-helpers.ts +39 -0
  136. package/src/vectors/EmbeddingService.ts +109 -0
  137. package/src/vectors/SimilaritySearch.ts +108 -0
  138. package/tsconfig.json +39 -0
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Validate command - Validate existing query templates
3
+ *
4
+ * Tests existing query metadata files to ensure they are valid:
5
+ * - SQL syntax validation
6
+ * - Parameter validation
7
+ * - Output field validation
8
+ * - Execution testing (optional)
9
+ */
10
+
11
+ import ora from 'ora';
12
+ import chalk from 'chalk';
13
+ import * as fs from 'fs';
14
+ import * as path from 'path';
15
+ import { Metadata, DatabaseProviderBase } from '@memberjunction/core';
16
+ import { getSystemUser } from '../../utils/user-helpers';
17
+ import { QueryTester } from '../../core/QueryTester';
18
+ import { extractErrorMessage } from '../../utils/error-handlers';
19
+ import { GeneratedQuery, QueryMetadataRecord } from '../../data/schema';
20
+ import { loadConfig } from '../config';
21
+
22
+ /**
23
+ * Execute the validate command
24
+ *
25
+ * Loads query metadata files and validates each query template.
26
+ * Reports success/failure statistics.
27
+ */
28
+ export async function validateCommand(options: Record<string, unknown>): Promise<void> {
29
+ const spinner = ora('Initializing validation...').start();
30
+
31
+ try {
32
+ const queryPath = String(options.path || './metadata/queries');
33
+ const verbose = Boolean(options.verbose);
34
+
35
+ // Load configuration
36
+ const config = loadConfig(options);
37
+
38
+ // 1. Get system user from UserCache (populated by provider initialization)
39
+ const contextUser = getSystemUser();
40
+
41
+ // 2. Verify database connection and load metadata
42
+ spinner.text = 'Loading metadata...';
43
+ // Assume provider is already configured by the calling application
44
+ if (!Metadata.Provider) {
45
+ throw new Error('Metadata provider not configured. Please ensure database connection is set up before running CLI.');
46
+ }
47
+ spinner.succeed('Metadata loaded');
48
+
49
+ // 3. Load query metadata files
50
+ spinner.start(`Loading query files from ${queryPath}...`);
51
+ const queryFiles = await loadQueryFiles(queryPath);
52
+ spinner.succeed(chalk.green(`Found ${queryFiles.length} query files`));
53
+
54
+ // 4. Validate each query
55
+ const dataProvider = Metadata.Provider.DatabaseConnection as DatabaseProviderBase;
56
+ let passCount = 0;
57
+ let failCount = 0;
58
+ const errors: Array<{ file: string; error: string }> = [];
59
+
60
+ for (let i = 0; i < queryFiles.length; i++) {
61
+ const { file, queries } = queryFiles[i];
62
+ const filePrefix = chalk.cyan(`[${i + 1}/${queryFiles.length}]`);
63
+
64
+ spinner.start(`${filePrefix} Validating ${chalk.dim(file)}...`);
65
+
66
+ for (const queryRecord of queries) {
67
+ try {
68
+ const query = convertMetadataToGeneratedQuery(queryRecord);
69
+
70
+ // Create a minimal business question and entity metadata for testing
71
+ const dummyQuestion = {
72
+ userQuestion: queryRecord.fields.UserQuestion || 'Test query',
73
+ description: queryRecord.fields.Description || '',
74
+ technicalDescription: queryRecord.fields.TechnicalDescription || '',
75
+ complexity: 'medium' as const,
76
+ requiresAggregation: false,
77
+ requiresJoins: false,
78
+ entities: []
79
+ };
80
+
81
+ const tester = new QueryTester(dataProvider, [], dummyQuestion, contextUser, config);
82
+
83
+ // Test query execution
84
+ const testResult = await tester.testQuery(query, 1);
85
+
86
+ if (testResult.success) {
87
+ passCount++;
88
+ if (verbose) {
89
+ spinner.info(`${filePrefix} ${chalk.green('✓')} ${queryRecord.fields.Name}`);
90
+ }
91
+ } else {
92
+ failCount++;
93
+ const errorMsg = testResult.error || 'Unknown error';
94
+ errors.push({ file, error: `${queryRecord.fields.Name}: ${errorMsg}` });
95
+ if (verbose) {
96
+ spinner.warn(`${filePrefix} ${chalk.red('✗')} ${queryRecord.fields.Name}: ${errorMsg}`);
97
+ }
98
+ }
99
+ } catch (error: unknown) {
100
+ failCount++;
101
+ const errorMsg = extractErrorMessage(error, 'Query Validation');
102
+ errors.push({ file, error: `${queryRecord.fields.Name}: ${errorMsg}` });
103
+ if (verbose) {
104
+ spinner.warn(`${filePrefix} ${chalk.red('✗')} ${queryRecord.fields.Name}: ${errorMsg}`);
105
+ }
106
+ }
107
+ }
108
+
109
+ spinner.succeed(`${filePrefix} ${chalk.dim(file)} complete`);
110
+ }
111
+
112
+ // 5. Summary
113
+ if (failCount === 0) {
114
+ spinner.succeed(chalk.green.bold(`✓ All ${passCount} queries validated successfully!`));
115
+ console.log('\n' + chalk.green.bold('✓ Validation complete!\n'));
116
+ console.log(chalk.bold('Summary:'));
117
+ console.log(` Total Queries: ${chalk.cyan(passCount.toString())}`);
118
+ console.log(` Passed: ${chalk.green(passCount.toString())}`);
119
+ console.log(` Failed: ${chalk.green('0')}`);
120
+ process.exit(0);
121
+ } else {
122
+ spinner.fail(chalk.yellow(`Validation completed with ${failCount} errors`));
123
+ console.log('\n' + chalk.yellow.bold('⚠ Validation completed with errors\n'));
124
+ console.log(chalk.bold('Summary:'));
125
+ console.log(` Total Queries: ${chalk.cyan((passCount + failCount).toString())}`);
126
+ console.log(` Passed: ${chalk.green(passCount.toString())}`);
127
+ console.log(` Failed: ${chalk.red(failCount.toString())}`);
128
+
129
+ if (errors.length > 0) {
130
+ console.log('\n' + chalk.bold('Errors:'));
131
+ for (const { file, error } of errors) {
132
+ console.log(chalk.red(` ${file}: ${error}`));
133
+ }
134
+ }
135
+ process.exit(1);
136
+ }
137
+
138
+ } catch (error: unknown) {
139
+ spinner.fail(chalk.red('Validation failed'));
140
+ console.error(chalk.red(extractErrorMessage(error, 'Query Validation')));
141
+ process.exit(1);
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Load all query metadata files from the specified directory
147
+ */
148
+ async function loadQueryFiles(queryPath: string): Promise<Array<{ file: string; queries: QueryMetadataRecord[] }>> {
149
+ const files: Array<{ file: string; queries: QueryMetadataRecord[] }> = [];
150
+
151
+ if (!fs.existsSync(queryPath)) {
152
+ throw new Error(`Query path not found: ${queryPath}`);
153
+ }
154
+
155
+ const entries = fs.readdirSync(queryPath);
156
+ for (const entry of entries) {
157
+ const fullPath = path.join(queryPath, entry);
158
+ const stat = fs.statSync(fullPath);
159
+
160
+ if (stat.isFile() && entry.endsWith('.json')) {
161
+ const content = fs.readFileSync(fullPath, 'utf-8');
162
+ const data = JSON.parse(content);
163
+
164
+ // Handle both single query and array formats
165
+ const queries = Array.isArray(data) ? data : [data];
166
+ files.push({ file: entry, queries });
167
+ }
168
+ }
169
+
170
+ return files;
171
+ }
172
+
173
+ /**
174
+ * Convert metadata record to GeneratedQuery format for testing
175
+ *
176
+ * Note: QueryFields and QueryParameters are auto-extracted by QueryEntity.server.ts,
177
+ * so we only validate the SQL itself. The validate command focuses on SQL syntax
178
+ * and execution, not on field/parameter metadata which is managed by MJ.
179
+ */
180
+ function convertMetadataToGeneratedQuery(record: QueryMetadataRecord): GeneratedQuery {
181
+ return {
182
+ sql: record.fields.SQL,
183
+ parameters: [], // Not needed for validation - QueryEntity will extract
184
+ };
185
+ }
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Configuration loader for QueryGen
3
+ *
4
+ * Loads configuration from mj.config.cjs and merges with CLI options
5
+ */
6
+
7
+ /**
8
+ * QueryGen configuration options
9
+ */
10
+ export interface QueryGenConfig {
11
+ // Entity Filtering
12
+ // NOTE: includeEntities and excludeEntities are mutually exclusive
13
+ // - includeEntities: If provided, ONLY these entities will be processed (allowlist)
14
+ // - excludeEntities: If provided, these entities will be excluded from processing (denylist)
15
+ // - If both are provided, includeEntities takes precedence and excludeEntities is ignored
16
+ includeEntities: string[];
17
+ excludeEntities: string[];
18
+ excludeSchemas: string[];
19
+
20
+ // Entity Grouping
21
+ questionsPerGroup: number;
22
+ minGroupSize: number; // Minimum entities per group
23
+ maxGroupSize: number; // Maximum entities per group
24
+
25
+ // AI Configuration
26
+ modelOverride?: string; // Override model for all prompts (e.g., "GPT-OSS-120B")
27
+ vendorOverride?: string; // Override vendor for all prompts (e.g., "Groq")
28
+ embeddingModel: string;
29
+
30
+ // Iteration Limits
31
+ maxRefinementIterations: number;
32
+ maxFixingIterations: number;
33
+
34
+ // Few-Shot Learning
35
+ topSimilarQueries: number;
36
+
37
+ // Similarity Weighting
38
+ similarityWeights: {
39
+ userQuestion: number;
40
+ description: number;
41
+ technicalDescription: number;
42
+ };
43
+
44
+ // Output Configuration
45
+ outputMode: 'metadata' | 'database' | 'both';
46
+ outputDirectory: string;
47
+ outputCategoryDirectory?: string; // Optional: defaults to outputDirectory if not provided
48
+
49
+ // Query Category Configuration
50
+ rootQueryCategory: string;
51
+ autoCreateEntityQueryCategories: boolean;
52
+
53
+ // Performance
54
+ parallelGenerations: number;
55
+ enableCaching: boolean;
56
+
57
+ // Validation
58
+ testWithSampleData: boolean;
59
+ requireMinRows: number;
60
+ maxRefinementRows: number;
61
+
62
+ // Verbose Logging
63
+ verbose: boolean;
64
+ }
65
+
66
+ /**
67
+ * Default configuration values
68
+ */
69
+ const DEFAULT_CONFIG: QueryGenConfig = {
70
+ includeEntities: [],
71
+ excludeEntities: [],
72
+ excludeSchemas: ['sys', 'INFORMATION_SCHEMA', '__mj'],
73
+ questionsPerGroup: 2,
74
+ minGroupSize: 2, // Multi-entity groups have at least 2 entities
75
+ maxGroupSize: 3, // Keep groups small for focused questions
76
+ embeddingModel: 'text-embedding-3-small',
77
+ maxRefinementIterations: 3,
78
+ maxFixingIterations: 5,
79
+ topSimilarQueries: 5,
80
+ similarityWeights: {
81
+ userQuestion: 0.2,
82
+ description: 0.40,
83
+ technicalDescription: 0.40,
84
+ },
85
+ outputMode: 'metadata',
86
+ outputDirectory: './metadata/queries',
87
+ rootQueryCategory: 'Auto-Generated',
88
+ autoCreateEntityQueryCategories: false,
89
+ parallelGenerations: 1,
90
+ enableCaching: true,
91
+ testWithSampleData: true,
92
+ requireMinRows: 0,
93
+ maxRefinementRows: 10,
94
+ verbose: false,
95
+ };
96
+
97
+ /**
98
+ * Load configuration from mj.config.cjs and merge with CLI options
99
+ *
100
+ * Configuration priority (highest to lowest):
101
+ * 1. CLI options (command line flags)
102
+ * 2. mj.config.cjs queryGen section
103
+ * 3. Default values
104
+ *
105
+ * @param cliOptions - Options provided via command line
106
+ * @returns Merged configuration ready for use
107
+ */
108
+ export function loadConfig(cliOptions: Record<string, unknown>): QueryGenConfig {
109
+ // Start with defaults
110
+ const config: QueryGenConfig = { ...DEFAULT_CONFIG };
111
+
112
+ // Load mj.config.cjs if it exists
113
+ const mjConfig = loadMjConfig();
114
+ if (mjConfig && mjConfig.queryGen) {
115
+ Object.assign(config, mjConfig.queryGen);
116
+ }
117
+
118
+ // Override with CLI options
119
+ if (cliOptions.entities) {
120
+ config.includeEntities = parseArrayOption(cliOptions.entities);
121
+ }
122
+ if (cliOptions.excludeEntities) {
123
+ config.excludeEntities = parseArrayOption(cliOptions.excludeEntities);
124
+ }
125
+ if (cliOptions.excludeSchemas) {
126
+ config.excludeSchemas = parseArrayOption(cliOptions.excludeSchemas);
127
+ }
128
+ if (cliOptions.maxRefinements) {
129
+ config.maxRefinementIterations = parseNumberOption(cliOptions.maxRefinements, 'maxRefinements');
130
+ }
131
+ if (cliOptions.maxFixes) {
132
+ config.maxFixingIterations = parseNumberOption(cliOptions.maxFixes, 'maxFixes');
133
+ }
134
+ if (cliOptions.model) {
135
+ config.modelOverride = String(cliOptions.model);
136
+ }
137
+ if (cliOptions.vendor) {
138
+ config.vendorOverride = String(cliOptions.vendor);
139
+ }
140
+ if (cliOptions.output) {
141
+ config.outputDirectory = String(cliOptions.output);
142
+ }
143
+ if (cliOptions.mode) {
144
+ const mode = String(cliOptions.mode);
145
+ if (mode === 'metadata' || mode === 'database' || mode === 'both') {
146
+ config.outputMode = mode;
147
+ } else {
148
+ throw new Error(`Invalid output mode: ${mode}. Must be metadata, database, or both`);
149
+ }
150
+ }
151
+ if (cliOptions.verbose) {
152
+ config.verbose = true;
153
+ }
154
+
155
+ // Validate entity filtering (includeEntities and excludeEntities are mutually exclusive)
156
+ if (config.includeEntities.length > 0 && config.excludeEntities.length > 0) {
157
+ console.warn('[Warning] Both includeEntities and excludeEntities provided. includeEntities takes precedence, excludeEntities will be ignored.');
158
+ config.excludeEntities = [];
159
+ }
160
+
161
+ return config;
162
+ }
163
+
164
+ /**
165
+ * Load mj.config.cjs from current working directory
166
+ * Returns null if file doesn't exist or can't be loaded
167
+ */
168
+ function loadMjConfig(): { queryGen?: Partial<QueryGenConfig> } | null {
169
+ try {
170
+ const configPath = require('path').join(process.cwd(), 'mj.config.cjs');
171
+ const fs = require('fs');
172
+ if (fs.existsSync(configPath)) {
173
+ return require(configPath);
174
+ }
175
+ } catch (error) {
176
+ // Config file doesn't exist or couldn't be loaded - not an error
177
+ }
178
+ return null;
179
+ }
180
+
181
+ /**
182
+ * Parse array option from CLI (handles both comma-separated strings and arrays)
183
+ */
184
+ function parseArrayOption(value: unknown): string[] {
185
+ if (Array.isArray(value)) {
186
+ return value.map(String);
187
+ }
188
+ if (typeof value === 'string') {
189
+ return value.split(',').map(s => s.trim());
190
+ }
191
+ return [];
192
+ }
193
+
194
+ /**
195
+ * Parse number option from CLI with validation
196
+ */
197
+ function parseNumberOption(value: unknown, name: string): number {
198
+ const num = Number(value);
199
+ if (isNaN(num) || num < 0) {
200
+ throw new Error(`Invalid ${name}: must be a positive number`);
201
+ }
202
+ return num;
203
+ }
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for QueryGen package
4
+ *
5
+ * Usage: mj-querygen <command> [options]
6
+ *
7
+ * Commands:
8
+ * generate - Generate queries for entities
9
+ * validate - Validate existing query templates
10
+ * export - Export queries from database to metadata files
11
+ */
12
+
13
+ import { Command } from 'commander';
14
+ import { generateCommand } from './commands/generate';
15
+ import { validateCommand } from './commands/validate';
16
+ import { exportCommand } from './commands/export';
17
+
18
+ const packageJson = require('../../package.json');
19
+
20
+ const program = new Command();
21
+
22
+ program
23
+ .name('mj-querygen')
24
+ .description('AI-powered SQL query template generation for MemberJunction')
25
+ .version(packageJson.version);
26
+
27
+ program
28
+ .command('generate')
29
+ .description('Generate queries for entities')
30
+ .option('-e, --entities <names...>', 'Specific entities to generate queries for')
31
+ .option('-x, --exclude-entities <names...>', 'Entities to exclude')
32
+ .option('-s, --exclude-schemas <names...>', 'Schemas to exclude')
33
+ .option('-m, --max-entities <number>', 'Max entities per group', '3')
34
+ .option('-r, --max-refinements <number>', 'Max refinement iterations', '3')
35
+ .option('-f, --max-fixes <number>', 'Max error-fixing attempts', '5')
36
+ .option('--model <name>', 'Preferred AI model')
37
+ .option('--vendor <name>', 'Preferred AI vendor')
38
+ .option('-o, --output <path>', 'Output directory')
39
+ .option('--mode <mode>', 'Output mode: metadata|database|both')
40
+ .option('-v, --verbose', 'Verbose output')
41
+ .action(generateCommand);
42
+
43
+ program
44
+ .command('validate')
45
+ .description('Validate existing query templates')
46
+ .option('-p, --path <path>', 'Path to queries metadata file', './metadata/queries')
47
+ .option('-v, --verbose', 'Verbose output')
48
+ .action(validateCommand);
49
+
50
+ program
51
+ .command('export')
52
+ .description('Export queries from database to metadata files')
53
+ .option('-o, --output <path>', 'Output directory')
54
+ .option('-v, --verbose', 'Verbose output')
55
+ .action(exportCommand);
56
+
57
+ // Parse command line arguments
58
+ program.parse();
59
+
60
+ // Show help if no command provided
61
+ if (!process.argv.slice(2).length) {
62
+ program.outputHelp();
63
+ }