@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.
- package/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +34 -0
- package/COORDINATOR.md +768 -0
- package/IMPLEMENTATION_PLAN.md +1753 -0
- package/LLM_ENTITY_GROUPING_PLAN.md +977 -0
- package/README.md +675 -29
- package/dist/cli/commands/export.d.ts +15 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +178 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +19 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +282 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +17 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +193 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/config.d.ts +51 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +142 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +57 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/EntityGrouper.d.ts +74 -0
- package/dist/core/EntityGrouper.d.ts.map +1 -0
- package/dist/core/EntityGrouper.js +246 -0
- package/dist/core/EntityGrouper.js.map +1 -0
- package/dist/core/MetadataExporter.d.ts +59 -0
- package/dist/core/MetadataExporter.d.ts.map +1 -0
- package/dist/core/MetadataExporter.js +151 -0
- package/dist/core/MetadataExporter.js.map +1 -0
- package/dist/core/QueryDatabaseWriter.d.ts +50 -0
- package/dist/core/QueryDatabaseWriter.d.ts.map +1 -0
- package/dist/core/QueryDatabaseWriter.js +152 -0
- package/dist/core/QueryDatabaseWriter.js.map +1 -0
- package/dist/core/QueryFixer.d.ts +48 -0
- package/dist/core/QueryFixer.d.ts.map +1 -0
- package/dist/core/QueryFixer.js +115 -0
- package/dist/core/QueryFixer.js.map +1 -0
- package/dist/core/QueryRefiner.d.ts +94 -0
- package/dist/core/QueryRefiner.d.ts.map +1 -0
- package/dist/core/QueryRefiner.js +267 -0
- package/dist/core/QueryRefiner.js.map +1 -0
- package/dist/core/QueryTester.d.ts +70 -0
- package/dist/core/QueryTester.d.ts.map +1 -0
- package/dist/core/QueryTester.js +243 -0
- package/dist/core/QueryTester.js.map +1 -0
- package/dist/core/QueryWriter.d.ts +57 -0
- package/dist/core/QueryWriter.d.ts.map +1 -0
- package/dist/core/QueryWriter.js +184 -0
- package/dist/core/QueryWriter.js.map +1 -0
- package/dist/core/QuestionGenerator.d.ts +58 -0
- package/dist/core/QuestionGenerator.d.ts.map +1 -0
- package/dist/core/QuestionGenerator.js +145 -0
- package/dist/core/QuestionGenerator.js.map +1 -0
- package/dist/data/schema.d.ts +230 -0
- package/dist/data/schema.d.ts.map +1 -0
- package/dist/data/schema.js +6 -0
- package/dist/data/schema.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/PromptNames.d.ts +32 -0
- package/dist/prompts/PromptNames.d.ts.map +1 -0
- package/dist/prompts/PromptNames.js +35 -0
- package/dist/prompts/PromptNames.js.map +1 -0
- package/dist/utils/category-builder.d.ts +28 -0
- package/dist/utils/category-builder.d.ts.map +1 -0
- package/dist/utils/category-builder.js +90 -0
- package/dist/utils/category-builder.js.map +1 -0
- package/dist/utils/entity-helpers.d.ts +49 -0
- package/dist/utils/entity-helpers.d.ts.map +1 -0
- package/dist/utils/entity-helpers.js +189 -0
- package/dist/utils/entity-helpers.js.map +1 -0
- package/dist/utils/error-handlers.d.ts +19 -0
- package/dist/utils/error-handlers.d.ts.map +1 -0
- package/dist/utils/error-handlers.js +41 -0
- package/dist/utils/error-handlers.js.map +1 -0
- package/dist/utils/graph-helpers.d.ts +51 -0
- package/dist/utils/graph-helpers.d.ts.map +1 -0
- package/dist/utils/graph-helpers.js +82 -0
- package/dist/utils/graph-helpers.js.map +1 -0
- package/dist/utils/prompt-helpers.d.ts +25 -0
- package/dist/utils/prompt-helpers.d.ts.map +1 -0
- package/dist/utils/prompt-helpers.js +66 -0
- package/dist/utils/prompt-helpers.js.map +1 -0
- package/dist/utils/query-helpers.d.ts +23 -0
- package/dist/utils/query-helpers.d.ts.map +1 -0
- package/dist/utils/query-helpers.js +34 -0
- package/dist/utils/query-helpers.js.map +1 -0
- package/dist/utils/user-helpers.d.ts +15 -0
- package/dist/utils/user-helpers.d.ts.map +1 -0
- package/dist/utils/user-helpers.js +32 -0
- package/dist/utils/user-helpers.js.map +1 -0
- package/dist/vectors/EmbeddingService.d.ts +58 -0
- package/dist/vectors/EmbeddingService.d.ts.map +1 -0
- package/dist/vectors/EmbeddingService.js +90 -0
- package/dist/vectors/EmbeddingService.js.map +1 -0
- package/dist/vectors/SimilaritySearch.d.ts +51 -0
- package/dist/vectors/SimilaritySearch.d.ts.map +1 -0
- package/dist/vectors/SimilaritySearch.js +85 -0
- package/dist/vectors/SimilaritySearch.js.map +1 -0
- package/docs/API.md +1040 -0
- package/docs/ARCHITECTURE.md +1120 -0
- package/examples/advanced-usage.ts +401 -0
- package/examples/basic-usage.ts +285 -0
- package/package.json +48 -6
- package/src/cli/commands/export.ts +173 -0
- package/src/cli/commands/generate.ts +330 -0
- package/src/cli/commands/validate.ts +185 -0
- package/src/cli/config.ts +203 -0
- package/src/cli/index.ts +63 -0
- package/src/core/EntityGrouper.ts +318 -0
- package/src/core/MetadataExporter.ts +148 -0
- package/src/core/QueryDatabaseWriter.ts +187 -0
- package/src/core/QueryFixer.ts +153 -0
- package/src/core/QueryRefiner.ts +382 -0
- package/src/core/QueryTester.ts +264 -0
- package/src/core/QueryWriter.ts +239 -0
- package/src/core/QuestionGenerator.ts +199 -0
- package/src/data/golden-queries.json +1371 -0
- package/src/data/schema.ts +252 -0
- package/src/index.ts +49 -0
- package/src/prompts/PromptNames.ts +36 -0
- package/src/utils/category-builder.ts +97 -0
- package/src/utils/entity-helpers.ts +203 -0
- package/src/utils/error-handlers.ts +41 -0
- package/src/utils/graph-helpers.ts +99 -0
- package/src/utils/prompt-helpers.ts +79 -0
- package/src/utils/query-helpers.ts +32 -0
- package/src/utils/user-helpers.ts +39 -0
- package/src/vectors/EmbeddingService.ts +109 -0
- package/src/vectors/SimilaritySearch.ts +108 -0
- package/tsconfig.json +39 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* LLM-based Entity Grouper
|
|
4
|
+
*
|
|
5
|
+
* Uses AI to generate semantically meaningful entity groupings based on
|
|
6
|
+
* business context and schema understanding, replacing the deterministic
|
|
7
|
+
* hub-and-spoke algorithm with intelligent semantic analysis.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.EntityGrouper = void 0;
|
|
11
|
+
const core_1 = require("@memberjunction/core");
|
|
12
|
+
const aiengine_1 = require("@memberjunction/aiengine");
|
|
13
|
+
const graph_helpers_1 = require("../utils/graph-helpers");
|
|
14
|
+
const error_handlers_1 = require("../utils/error-handlers");
|
|
15
|
+
const prompt_helpers_1 = require("../utils/prompt-helpers");
|
|
16
|
+
/**
|
|
17
|
+
* Generates entity groups using LLM-based semantic analysis
|
|
18
|
+
*
|
|
19
|
+
* This class replaces the deterministic hub-and-spoke algorithm with an
|
|
20
|
+
* intelligent approach that understands business context and generates
|
|
21
|
+
* meaningful entity combinations for query generation.
|
|
22
|
+
*/
|
|
23
|
+
class EntityGrouper {
|
|
24
|
+
promptName = 'Entity Group Generator';
|
|
25
|
+
config;
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.config = config;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate semantically meaningful entity groups using LLM analysis
|
|
31
|
+
*
|
|
32
|
+
* Note: The LLM determines the optimal number and size of entity groups based on
|
|
33
|
+
* business domain understanding. Makes separate LLM calls for each schema to
|
|
34
|
+
* avoid mixing entities from different databases.
|
|
35
|
+
*
|
|
36
|
+
* @param entities - All entities to analyze
|
|
37
|
+
* @param contextUser - User context for server-side operations
|
|
38
|
+
* @returns Array of validated entity groups with business context
|
|
39
|
+
*/
|
|
40
|
+
async generateEntityGroups(entities, contextUser) {
|
|
41
|
+
try {
|
|
42
|
+
// 1. Group entities by schema
|
|
43
|
+
const entitiesBySchema = this.groupEntitiesBySchema(entities);
|
|
44
|
+
// 2. Process each schema separately
|
|
45
|
+
const allGroups = [];
|
|
46
|
+
let schemaIndex = 0;
|
|
47
|
+
const totalSchemas = entitiesBySchema.size;
|
|
48
|
+
for (const [schemaName, schemaEntities] of entitiesBySchema.entries()) {
|
|
49
|
+
schemaIndex++;
|
|
50
|
+
if (this.config.verbose && totalSchemas > 1) {
|
|
51
|
+
(0, core_1.LogStatus)(`[${schemaIndex}/${totalSchemas}] Processing schema: ${schemaName} (${schemaEntities.length} entities)`);
|
|
52
|
+
}
|
|
53
|
+
// 2a. Prepare schema data for LLM
|
|
54
|
+
const schemaData = this.prepareSchemaData(schemaEntities, schemaName);
|
|
55
|
+
// 2b. Call LLM to generate groups for this schema
|
|
56
|
+
const llmResponse = await this.callLLMForGrouping(schemaData, contextUser);
|
|
57
|
+
// 2c. Validate and convert to EntityGroup objects
|
|
58
|
+
const validatedGroups = this.validateAndConvertGroups(llmResponse, schemaEntities);
|
|
59
|
+
if (this.config.verbose && totalSchemas > 1) {
|
|
60
|
+
(0, core_1.LogStatus)(`[${schemaIndex}/${totalSchemas}] Generated ${validatedGroups.length} groups for schema: ${schemaName}`);
|
|
61
|
+
}
|
|
62
|
+
allGroups.push(...validatedGroups);
|
|
63
|
+
}
|
|
64
|
+
// 3. Deduplicate any similar groups across all schemas
|
|
65
|
+
const deduplicatedGroups = this.deduplicateGroups(allGroups);
|
|
66
|
+
return deduplicatedGroups;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
throw new Error((0, error_handlers_1.extractErrorMessage)(error, 'EntityGrouper.generateEntityGroups'));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Group entities by schema name
|
|
74
|
+
*/
|
|
75
|
+
groupEntitiesBySchema(entities) {
|
|
76
|
+
const schemaMap = new Map();
|
|
77
|
+
for (const entity of entities) {
|
|
78
|
+
const schemaName = entity.SchemaName || 'Unknown';
|
|
79
|
+
const schemaEntities = schemaMap.get(schemaName) || [];
|
|
80
|
+
schemaEntities.push(entity);
|
|
81
|
+
schemaMap.set(schemaName, schemaEntities);
|
|
82
|
+
}
|
|
83
|
+
return schemaMap;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Prepare schema data for LLM prompt
|
|
87
|
+
*
|
|
88
|
+
* Note: The LLM will determine appropriate group count based on business
|
|
89
|
+
* domain understanding and schema complexity. We provide the full entity
|
|
90
|
+
* schema and relationship graph for intelligent analysis.
|
|
91
|
+
*
|
|
92
|
+
* @param entities - Entities within a single schema
|
|
93
|
+
* @param schemaName - Name of the schema being processed
|
|
94
|
+
*/
|
|
95
|
+
prepareSchemaData(entities, schemaName) {
|
|
96
|
+
const formattedEntities = (0, graph_helpers_1.formatEntitiesForPrompt)(entities);
|
|
97
|
+
const relationshipGraph = (0, graph_helpers_1.generateRelationshipGraph)(entities);
|
|
98
|
+
return {
|
|
99
|
+
schemaName,
|
|
100
|
+
entities: formattedEntities,
|
|
101
|
+
relationshipGraph,
|
|
102
|
+
minGroupSize: this.config.minGroupSize,
|
|
103
|
+
maxGroupSize: this.config.maxGroupSize
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Call LLM via AIPromptRunner to generate entity groups
|
|
108
|
+
*/
|
|
109
|
+
async callLLMForGrouping(schemaData, contextUser) {
|
|
110
|
+
// Get prompt entity from AIEngine
|
|
111
|
+
const prompt = aiengine_1.AIEngine.Instance.Prompts.find(p => p.Name === this.promptName);
|
|
112
|
+
if (!prompt) {
|
|
113
|
+
throw new Error(`Prompt "${this.promptName}" not found. Ensure metadata has been synced to database.`);
|
|
114
|
+
}
|
|
115
|
+
// Execute with model/vendor overrides if specified in config
|
|
116
|
+
const result = await (0, prompt_helpers_1.executePromptWithOverrides)(prompt, schemaData, contextUser, this.config);
|
|
117
|
+
if (!result.success) {
|
|
118
|
+
throw new Error(`LLM grouping failed: ${result.errorMessage || 'Unknown error'}`);
|
|
119
|
+
}
|
|
120
|
+
if (!result.result) {
|
|
121
|
+
throw new Error('LLM did not return structured data');
|
|
122
|
+
}
|
|
123
|
+
return result.result;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Validate LLM output and convert to EntityGroup objects
|
|
127
|
+
*/
|
|
128
|
+
validateAndConvertGroups(llmResponse, entities) {
|
|
129
|
+
const entityMap = new Map(entities.map(e => [e.Name, e]));
|
|
130
|
+
const validGroups = [];
|
|
131
|
+
for (const llmGroup of llmResponse.groups) {
|
|
132
|
+
try {
|
|
133
|
+
// Validate all entity names exist
|
|
134
|
+
const groupEntities = llmGroup.entities
|
|
135
|
+
.map(name => entityMap.get(name))
|
|
136
|
+
.filter((e) => e !== undefined);
|
|
137
|
+
if (groupEntities.length !== llmGroup.entities.length) {
|
|
138
|
+
// Skip logging - verbose debug info that clutters output
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
// Validate primary entity exists
|
|
142
|
+
const primaryEntity = entityMap.get(llmGroup.primaryEntity);
|
|
143
|
+
if (!primaryEntity) {
|
|
144
|
+
// Skip logging - verbose debug info that clutters output
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
// Build relationships array (collect all relationships between entities in the group)
|
|
148
|
+
const relationships = this.extractRelationships(groupEntities);
|
|
149
|
+
// Validate connectivity (all entities must be reachable from primary)
|
|
150
|
+
if (groupEntities.length > 1 && !this.isConnected(groupEntities, relationships)) {
|
|
151
|
+
// Skip logging - verbose debug info that clutters output
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
// Create EntityGroup with LLM metadata
|
|
155
|
+
validGroups.push({
|
|
156
|
+
entities: groupEntities,
|
|
157
|
+
relationships,
|
|
158
|
+
primaryEntity,
|
|
159
|
+
relationshipType: llmGroup.relationshipType,
|
|
160
|
+
businessDomain: llmGroup.businessDomain,
|
|
161
|
+
businessRationale: llmGroup.businessRationale,
|
|
162
|
+
expectedQuestionTypes: llmGroup.expectedQuestionTypes
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
// Skip logging - verbose debug info that clutters output
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (validGroups.length === 0) {
|
|
170
|
+
throw new Error('No valid entity groups generated by LLM');
|
|
171
|
+
}
|
|
172
|
+
return validGroups;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Extract relationships between entities in a group
|
|
176
|
+
*/
|
|
177
|
+
extractRelationships(entities) {
|
|
178
|
+
const entityNames = new Set(entities.map(e => e.Name));
|
|
179
|
+
const relationships = [];
|
|
180
|
+
for (const entity of entities) {
|
|
181
|
+
for (const rel of entity.RelatedEntities) {
|
|
182
|
+
if (entityNames.has(rel.RelatedEntity)) {
|
|
183
|
+
relationships.push(rel);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return relationships;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Check if all entities in a group are connected by relationships
|
|
191
|
+
*
|
|
192
|
+
* Uses BFS to verify all entities are reachable from the first entity
|
|
193
|
+
*/
|
|
194
|
+
isConnected(entities, relationships) {
|
|
195
|
+
if (entities.length <= 1)
|
|
196
|
+
return true;
|
|
197
|
+
// Build adjacency map
|
|
198
|
+
const adjacency = new Map();
|
|
199
|
+
for (const entity of entities) {
|
|
200
|
+
adjacency.set(entity.Name, new Set());
|
|
201
|
+
}
|
|
202
|
+
for (const rel of relationships) {
|
|
203
|
+
const entityName = entities.find(e => e.RelatedEntities.includes(rel))?.Name;
|
|
204
|
+
if (entityName) {
|
|
205
|
+
adjacency.get(entityName)?.add(rel.RelatedEntity);
|
|
206
|
+
adjacency.get(rel.RelatedEntity)?.add(entityName); // Bidirectional
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// BFS from first entity
|
|
210
|
+
const visited = new Set();
|
|
211
|
+
const queue = [entities[0].Name];
|
|
212
|
+
visited.add(entities[0].Name);
|
|
213
|
+
while (queue.length > 0) {
|
|
214
|
+
const current = queue.shift();
|
|
215
|
+
const neighbors = adjacency.get(current) || new Set();
|
|
216
|
+
for (const neighbor of neighbors) {
|
|
217
|
+
if (!visited.has(neighbor)) {
|
|
218
|
+
visited.add(neighbor);
|
|
219
|
+
queue.push(neighbor);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// All entities should be visited
|
|
224
|
+
return visited.size === entities.length;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Remove duplicate or highly similar groups
|
|
228
|
+
*
|
|
229
|
+
* Groups are considered duplicates if they contain the exact same set of entities
|
|
230
|
+
*/
|
|
231
|
+
deduplicateGroups(groups) {
|
|
232
|
+
const seen = new Set();
|
|
233
|
+
const unique = [];
|
|
234
|
+
for (const group of groups) {
|
|
235
|
+
// Create normalized key (sorted entity names)
|
|
236
|
+
const key = group.entities.map(e => e.Name).sort().join('|');
|
|
237
|
+
if (!seen.has(key)) {
|
|
238
|
+
seen.add(key);
|
|
239
|
+
unique.push(group);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return unique;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
exports.EntityGrouper = EntityGrouper;
|
|
246
|
+
//# sourceMappingURL=EntityGrouper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityGrouper.js","sourceRoot":"","sources":["../../src/core/EntityGrouper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetadataExporter - Exports validated queries to MJ metadata format
|
|
3
|
+
*
|
|
4
|
+
* Transforms validated queries into MemberJunction metadata JSON files
|
|
5
|
+
* that can be synced to the database using mj-sync.
|
|
6
|
+
*/
|
|
7
|
+
import { ValidatedQuery, ExportResult, QueryCategoryInfo } from '../data/schema';
|
|
8
|
+
/**
|
|
9
|
+
* MetadataExporter class
|
|
10
|
+
* Exports validated queries to MJ metadata JSON format
|
|
11
|
+
*/
|
|
12
|
+
export declare class MetadataExporter {
|
|
13
|
+
/**
|
|
14
|
+
* Export queries to metadata JSON files
|
|
15
|
+
*
|
|
16
|
+
* Transforms validated queries into MemberJunction metadata format
|
|
17
|
+
* and writes them to timestamped JSON files:
|
|
18
|
+
* - .query-categories-{timestamp}.json for the categories
|
|
19
|
+
* - .queries-{timestamp}.json for the queries
|
|
20
|
+
*
|
|
21
|
+
* @param validatedQueries - Array of validated queries to export
|
|
22
|
+
* @param uniqueCategories - Pre-built unique categories for all queries
|
|
23
|
+
* @param outputDirectory - Directory to write the queries file
|
|
24
|
+
* @param outputCategoryDirectory - Optional directory for categories file (defaults to outputDirectory)
|
|
25
|
+
* @returns Export result with file path and query count
|
|
26
|
+
*/
|
|
27
|
+
exportQueries(validatedQueries: ValidatedQuery[], uniqueCategories: QueryCategoryInfo[], outputDirectory: string, outputCategoryDirectory?: string): Promise<ExportResult>;
|
|
28
|
+
/**
|
|
29
|
+
* Transform a validated query into MJ metadata format
|
|
30
|
+
*
|
|
31
|
+
* Note: This method only creates the Query record.
|
|
32
|
+
* QueryFields and QueryParameters are automatically extracted
|
|
33
|
+
* by QueryEntity.server.ts using AI analysis of the SQL template.
|
|
34
|
+
* This happens asynchronously during the Save() operation.
|
|
35
|
+
*
|
|
36
|
+
* @param query - Validated query to transform
|
|
37
|
+
* @returns Query metadata record
|
|
38
|
+
*/
|
|
39
|
+
private toQueryMetadata;
|
|
40
|
+
/**
|
|
41
|
+
* Transform a QueryCategoryInfo into MJ metadata format
|
|
42
|
+
*
|
|
43
|
+
* @param category - Category information
|
|
44
|
+
* @returns Category metadata record
|
|
45
|
+
*/
|
|
46
|
+
private toCategoryMetadata;
|
|
47
|
+
/**
|
|
48
|
+
* Build category lookup string for metadata
|
|
49
|
+
* Uses multi-field lookup to uniquely identify categories in hierarchies
|
|
50
|
+
*
|
|
51
|
+
* For root categories: Name=X&ParentID=null
|
|
52
|
+
* For child categories: Name=X&Parent=Y (where Parent is the parent category name)
|
|
53
|
+
*
|
|
54
|
+
* @param category - Category information
|
|
55
|
+
* @returns Lookup string for CategoryID field
|
|
56
|
+
*/
|
|
57
|
+
private buildCategoryLookup;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=MetadataExporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetadataExporter.d.ts","sourceRoot":"","sources":["../../src/core/MetadataExporter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAuB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGtG;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B;;;;;;;;;;;;;OAaG;IACG,aAAa,CACjB,gBAAgB,EAAE,cAAc,EAAE,EAClC,gBAAgB,EAAE,iBAAiB,EAAE,EACrC,eAAe,EAAE,MAAM,EACvB,uBAAuB,CAAC,EAAE,MAAM,GAC/B,OAAO,CAAC,YAAY,CAAC;IA0CxB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,eAAe;IAoBvB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB;CAS5B"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MetadataExporter - Exports validated queries to MJ metadata format
|
|
4
|
+
*
|
|
5
|
+
* Transforms validated queries into MemberJunction metadata JSON files
|
|
6
|
+
* that can be synced to the database using mj-sync.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
25
|
+
if (mod && mod.__esModule) return mod;
|
|
26
|
+
var result = {};
|
|
27
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
28
|
+
__setModuleDefault(result, mod);
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.MetadataExporter = void 0;
|
|
33
|
+
const fs_1 = require("fs");
|
|
34
|
+
const path = __importStar(require("path"));
|
|
35
|
+
const query_helpers_1 = require("../utils/query-helpers");
|
|
36
|
+
/**
|
|
37
|
+
* MetadataExporter class
|
|
38
|
+
* Exports validated queries to MJ metadata JSON format
|
|
39
|
+
*/
|
|
40
|
+
class MetadataExporter {
|
|
41
|
+
/**
|
|
42
|
+
* Export queries to metadata JSON files
|
|
43
|
+
*
|
|
44
|
+
* Transforms validated queries into MemberJunction metadata format
|
|
45
|
+
* and writes them to timestamped JSON files:
|
|
46
|
+
* - .query-categories-{timestamp}.json for the categories
|
|
47
|
+
* - .queries-{timestamp}.json for the queries
|
|
48
|
+
*
|
|
49
|
+
* @param validatedQueries - Array of validated queries to export
|
|
50
|
+
* @param uniqueCategories - Pre-built unique categories for all queries
|
|
51
|
+
* @param outputDirectory - Directory to write the queries file
|
|
52
|
+
* @param outputCategoryDirectory - Optional directory for categories file (defaults to outputDirectory)
|
|
53
|
+
* @returns Export result with file path and query count
|
|
54
|
+
*/
|
|
55
|
+
async exportQueries(validatedQueries, uniqueCategories, outputDirectory, outputCategoryDirectory) {
|
|
56
|
+
// Generate shared timestamp for both files
|
|
57
|
+
const timestamp = Date.now();
|
|
58
|
+
// Use category directory if provided, otherwise use queries directory
|
|
59
|
+
const categoryDir = outputCategoryDirectory || outputDirectory;
|
|
60
|
+
// 1. Transform to MJ metadata format
|
|
61
|
+
const queryMetadata = validatedQueries.map(q => this.toQueryMetadata(q));
|
|
62
|
+
const categoryMetadata = uniqueCategories.map(c => this.toCategoryMetadata(c));
|
|
63
|
+
// 2. Ensure output directories exist
|
|
64
|
+
await fs_1.promises.mkdir(outputDirectory, { recursive: true });
|
|
65
|
+
if (categoryDir !== outputDirectory) {
|
|
66
|
+
await fs_1.promises.mkdir(categoryDir, { recursive: true });
|
|
67
|
+
}
|
|
68
|
+
// 3. Write categories file (if categories exist)
|
|
69
|
+
if (categoryMetadata.length > 0) {
|
|
70
|
+
const categoriesPath = path.join(categoryDir, `.query-categories-${timestamp}.json`);
|
|
71
|
+
await fs_1.promises.writeFile(categoriesPath, JSON.stringify(categoryMetadata, null, 2), 'utf-8');
|
|
72
|
+
}
|
|
73
|
+
// 4. Write queries file
|
|
74
|
+
const outputPath = path.join(outputDirectory, `.queries-${timestamp}.json`);
|
|
75
|
+
await fs_1.promises.writeFile(outputPath, JSON.stringify(queryMetadata, null, 2), 'utf-8');
|
|
76
|
+
return {
|
|
77
|
+
success: true,
|
|
78
|
+
outputPath,
|
|
79
|
+
queryCount: queryMetadata.length
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Transform a validated query into MJ metadata format
|
|
84
|
+
*
|
|
85
|
+
* Note: This method only creates the Query record.
|
|
86
|
+
* QueryFields and QueryParameters are automatically extracted
|
|
87
|
+
* by QueryEntity.server.ts using AI analysis of the SQL template.
|
|
88
|
+
* This happens asynchronously during the Save() operation.
|
|
89
|
+
*
|
|
90
|
+
* @param query - Validated query to transform
|
|
91
|
+
* @returns Query metadata record
|
|
92
|
+
*/
|
|
93
|
+
toQueryMetadata(query) {
|
|
94
|
+
// Build category lookup path (e.g., "Golden-Queries/Members" becomes lookup filter)
|
|
95
|
+
const categoryLookup = this.buildCategoryLookup(query.category);
|
|
96
|
+
return {
|
|
97
|
+
fields: {
|
|
98
|
+
Name: (0, query_helpers_1.generateQueryName)(query.businessQuestion),
|
|
99
|
+
CategoryID: categoryLookup,
|
|
100
|
+
UserQuestion: query.businessQuestion.userQuestion,
|
|
101
|
+
Description: query.businessQuestion.description,
|
|
102
|
+
TechnicalDescription: query.businessQuestion.technicalDescription,
|
|
103
|
+
SQL: query.query.sql,
|
|
104
|
+
OriginalSQL: query.query.sql,
|
|
105
|
+
UsesTemplate: true,
|
|
106
|
+
Status: 'Pending'
|
|
107
|
+
}
|
|
108
|
+
// relatedEntities removed - QueryEntity.server.ts handles extraction automatically
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Transform a QueryCategoryInfo into MJ metadata format
|
|
113
|
+
*
|
|
114
|
+
* @param category - Category information
|
|
115
|
+
* @returns Category metadata record
|
|
116
|
+
*/
|
|
117
|
+
toCategoryMetadata(category) {
|
|
118
|
+
return {
|
|
119
|
+
fields: {
|
|
120
|
+
Name: category.name,
|
|
121
|
+
ParentID: category.parentName
|
|
122
|
+
? `@lookup:Query Categories.Name=${category.parentName}`
|
|
123
|
+
: null,
|
|
124
|
+
Description: category.description,
|
|
125
|
+
UserID: '@lookup:Users.Name=System'
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Build category lookup string for metadata
|
|
131
|
+
* Uses multi-field lookup to uniquely identify categories in hierarchies
|
|
132
|
+
*
|
|
133
|
+
* For root categories: Name=X&ParentID=null
|
|
134
|
+
* For child categories: Name=X&Parent=Y (where Parent is the parent category name)
|
|
135
|
+
*
|
|
136
|
+
* @param category - Category information
|
|
137
|
+
* @returns Lookup string for CategoryID field
|
|
138
|
+
*/
|
|
139
|
+
buildCategoryLookup(category) {
|
|
140
|
+
if (category.parentName) {
|
|
141
|
+
// Child category - use Name and Parent field (view field showing parent name)
|
|
142
|
+
return `@lookup:Query Categories.Name=${category.name}&Parent=${category.parentName}`;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Root category - use Name and ParentID=null
|
|
146
|
+
return `@lookup:Query Categories.Name=${category.name}&ParentID=null`;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
exports.MetadataExporter = MetadataExporter;
|
|
151
|
+
//# sourceMappingURL=MetadataExporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetadataExporter.js","sourceRoot":"","sources":["../../src/core/MetadataExporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QueryDatabaseWriter - Write validated queries directly to the database
|
|
3
|
+
*
|
|
4
|
+
* Creates Query entities in the database. QueryFields and QueryParameters
|
|
5
|
+
* are automatically extracted by QueryEntity.server.ts using AI analysis
|
|
6
|
+
* of the SQL template during the Save() operation.
|
|
7
|
+
*/
|
|
8
|
+
import { UserInfo } from '@memberjunction/core';
|
|
9
|
+
import { ValidatedQuery, WriteResult } from '../data/schema';
|
|
10
|
+
/**
|
|
11
|
+
* QueryDatabaseWriter class
|
|
12
|
+
* Writes validated queries directly to the database
|
|
13
|
+
*/
|
|
14
|
+
export declare class QueryDatabaseWriter {
|
|
15
|
+
private categoryCache;
|
|
16
|
+
constructor();
|
|
17
|
+
/**
|
|
18
|
+
* Write validated queries to the database
|
|
19
|
+
*
|
|
20
|
+
* Creates Query entities. QueryFields and QueryParameters are automatically
|
|
21
|
+
* extracted by QueryEntity.server.ts using AI analysis of the SQL template.
|
|
22
|
+
* This happens asynchronously during the Save() operation.
|
|
23
|
+
*
|
|
24
|
+
* Errors for individual queries are logged but don't stop the batch process.
|
|
25
|
+
*
|
|
26
|
+
* @param validatedQueries - Array of validated queries to write
|
|
27
|
+
* @param contextUser - User context for entity operations
|
|
28
|
+
* @returns Write result with success status and per-query results
|
|
29
|
+
*/
|
|
30
|
+
writeQueriesToDatabase(validatedQueries: ValidatedQuery[], contextUser: UserInfo): Promise<WriteResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Get or create category ID from QueryCategoryInfo
|
|
33
|
+
* Uses caching to avoid repeated lookups/creations
|
|
34
|
+
* Ensures parent categories exist before creating children
|
|
35
|
+
*/
|
|
36
|
+
private getCategoryId;
|
|
37
|
+
/**
|
|
38
|
+
* Find or create a query category
|
|
39
|
+
*
|
|
40
|
+
* Searches for an existing category with the given name and parent, or creates it if not found.
|
|
41
|
+
*
|
|
42
|
+
* @param categoryName - Name of the category to find or create
|
|
43
|
+
* @param parentCategoryId - Parent category ID (null for root categories)
|
|
44
|
+
* @param description - Description for new categories
|
|
45
|
+
* @param contextUser - User context for entity operations
|
|
46
|
+
* @returns Category ID
|
|
47
|
+
*/
|
|
48
|
+
private findOrCreateCategory;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=QueryDatabaseWriter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryDatabaseWriter.d.ts","sourceRoot":"","sources":["../../src/core/QueryDatabaseWriter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAqB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKnE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAI7D;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,aAAa,CAAkC;;IAKvD;;;;;;;;;;;;OAYG;IACG,sBAAsB,CAC1B,gBAAgB,EAAE,cAAc,EAAE,EAClC,WAAW,EAAE,QAAQ,GACpB,OAAO,CAAC,WAAW,CAAC;IA8CvB;;;;OAIG;YACW,aAAa;IAmC3B;;;;;;;;;;OAUG;YACW,oBAAoB;CA8CnC"}
|