@memberjunction/core-entities-server 3.4.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +147 -11
  2. package/dist/custom/AIAgentExampleEntity.server.d.ts +0 -4
  3. package/dist/custom/AIAgentExampleEntity.server.d.ts.map +1 -1
  4. package/dist/custom/AIAgentExampleEntity.server.js +13 -20
  5. package/dist/custom/AIAgentExampleEntity.server.js.map +1 -1
  6. package/dist/custom/AIAgentNoteEntity.server.d.ts +0 -4
  7. package/dist/custom/AIAgentNoteEntity.server.d.ts.map +1 -1
  8. package/dist/custom/AIAgentNoteEntity.server.js +13 -20
  9. package/dist/custom/AIAgentNoteEntity.server.js.map +1 -1
  10. package/dist/custom/AIPromptEntityExtended.server.d.ts +0 -1
  11. package/dist/custom/AIPromptEntityExtended.server.d.ts.map +1 -1
  12. package/dist/custom/AIPromptEntityExtended.server.js +16 -20
  13. package/dist/custom/AIPromptEntityExtended.server.js.map +1 -1
  14. package/dist/custom/AIPromptRunEntity.server.d.ts +0 -4
  15. package/dist/custom/AIPromptRunEntity.server.d.ts.map +1 -1
  16. package/dist/custom/AIPromptRunEntity.server.js +19 -27
  17. package/dist/custom/AIPromptRunEntity.server.js.map +1 -1
  18. package/dist/custom/ActionEntity.server.d.ts +0 -1
  19. package/dist/custom/ActionEntity.server.d.ts.map +1 -1
  20. package/dist/custom/ActionEntity.server.js +26 -35
  21. package/dist/custom/ActionEntity.server.js.map +1 -1
  22. package/dist/custom/ApplicationEntity.server.d.ts +9 -1
  23. package/dist/custom/ApplicationEntity.server.d.ts.map +1 -1
  24. package/dist/custom/ApplicationEntity.server.js +41 -31
  25. package/dist/custom/ApplicationEntity.server.js.map +1 -1
  26. package/dist/custom/ArtifactVersionExtended.server.d.ts +0 -4
  27. package/dist/custom/ArtifactVersionExtended.server.d.ts.map +1 -1
  28. package/dist/custom/ArtifactVersionExtended.server.js +19 -29
  29. package/dist/custom/ArtifactVersionExtended.server.js.map +1 -1
  30. package/dist/custom/ComponentEntity.server.d.ts +0 -1
  31. package/dist/custom/ComponentEntity.server.d.ts.map +1 -1
  32. package/dist/custom/ComponentEntity.server.js +9 -14
  33. package/dist/custom/ComponentEntity.server.js.map +1 -1
  34. package/dist/custom/ConversationDetailEntity.server.d.ts +0 -1
  35. package/dist/custom/ConversationDetailEntity.server.d.ts.map +1 -1
  36. package/dist/custom/ConversationDetailEntity.server.js +7 -12
  37. package/dist/custom/ConversationDetailEntity.server.js.map +1 -1
  38. package/dist/custom/DuplicateRunEntity.server.d.ts +0 -1
  39. package/dist/custom/DuplicateRunEntity.server.d.ts.map +1 -1
  40. package/dist/custom/DuplicateRunEntity.server.js +10 -15
  41. package/dist/custom/DuplicateRunEntity.server.js.map +1 -1
  42. package/dist/custom/QueryEntity.server.d.ts +0 -23
  43. package/dist/custom/QueryEntity.server.d.ts.map +1 -1
  44. package/dist/custom/QueryEntity.server.js +53 -326
  45. package/dist/custom/QueryEntity.server.js.map +1 -1
  46. package/dist/custom/TemplateContentEntity.server.d.ts +0 -1
  47. package/dist/custom/TemplateContentEntity.server.d.ts.map +1 -1
  48. package/dist/custom/TemplateContentEntity.server.js +19 -24
  49. package/dist/custom/TemplateContentEntity.server.js.map +1 -1
  50. package/dist/custom/reportEntity.server.d.ts +0 -1
  51. package/dist/custom/reportEntity.server.d.ts.map +1 -1
  52. package/dist/custom/reportEntity.server.js +9 -14
  53. package/dist/custom/reportEntity.server.js.map +1 -1
  54. package/dist/custom/sql-parser.d.ts +95 -0
  55. package/dist/custom/sql-parser.d.ts.map +1 -0
  56. package/dist/custom/sql-parser.js +313 -0
  57. package/dist/custom/sql-parser.js.map +1 -0
  58. package/dist/custom/userViewEntity.server.d.ts +0 -1
  59. package/dist/custom/userViewEntity.server.d.ts.map +1 -1
  60. package/dist/custom/userViewEntity.server.js +20 -23
  61. package/dist/custom/userViewEntity.server.js.map +1 -1
  62. package/dist/custom/util.js +4 -8
  63. package/dist/custom/util.js.map +1 -1
  64. package/dist/index.d.ts +16 -16
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +16 -65
  67. package/dist/index.js.map +1 -1
  68. package/package.json +20 -19
@@ -1,45 +1,18 @@
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
1
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
2
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
3
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
23
6
  };
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.LoadQueryEntityServerSubClass = exports.QueryEntityExtended = void 0;
33
- const core_1 = require("@memberjunction/core");
34
- const core_entities_1 = require("@memberjunction/core-entities");
35
- const global_1 = require("@memberjunction/global");
36
- const aiengine_1 = require("@memberjunction/aiengine");
37
- const ai_prompts_1 = require("@memberjunction/ai-prompts");
38
- const ai_core_plus_1 = require("@memberjunction/ai-core-plus");
39
- const util_1 = require("./util");
40
- const node_sql_parser_1 = require("node-sql-parser");
41
- const nunjucks = __importStar(require("nunjucks"));
42
- let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.QueryEntity {
7
+ import { BaseEntity, LogError, Metadata } from "@memberjunction/core";
8
+ import { QueryEntity } from "@memberjunction/core-entities";
9
+ import { RegisterClass } from "@memberjunction/global";
10
+ import { AIEngine } from "@memberjunction/aiengine";
11
+ import { AIPromptRunner } from "@memberjunction/ai-prompts";
12
+ import { AIPromptParams } from "@memberjunction/ai-core-plus";
13
+ import { EmbedTextLocalHelper } from "./util.js";
14
+ import { SQLParser } from "./sql-parser.js";
15
+ let QueryEntityExtended = class QueryEntityExtended extends QueryEntity {
43
16
  constructor() {
44
17
  super(...arguments);
45
18
  this._queryEntities = [];
@@ -65,7 +38,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
65
38
  * @returns
66
39
  */
67
40
  async EmbedTextLocal(textToEmbed) {
68
- return (0, util_1.EmbedTextLocalHelper)(this, textToEmbed);
41
+ return EmbedTextLocalHelper(this, textToEmbed);
69
42
  }
70
43
  async Save(options) {
71
44
  try {
@@ -104,7 +77,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
104
77
  return true;
105
78
  }
106
79
  catch (e) {
107
- (0, core_1.LogError)('Failed to save query:', e);
80
+ LogError('Failed to save query:', e);
108
81
  this.LatestResult?.Errors.push(e);
109
82
  return false;
110
83
  }
@@ -123,7 +96,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
123
96
  return true;
124
97
  }
125
98
  catch (e) {
126
- (0, core_1.LogError)('Failed to delete query:', e);
99
+ LogError('Failed to delete query:', e);
127
100
  this.LatestResult?.Errors.push(e);
128
101
  return false;
129
102
  }
@@ -139,11 +112,11 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
139
112
  // This is a separate, fast operation that doesn't involve AI
140
113
  const updateResult = await super.Save();
141
114
  if (!updateResult) {
142
- (0, core_1.LogError)('Failed to save query after AI processing completed');
115
+ LogError('Failed to save query after AI processing completed');
143
116
  }
144
117
  }
145
118
  catch (e) {
146
- (0, core_1.LogError)('Error in async AI processing:', e);
119
+ LogError('Error in async AI processing:', e);
147
120
  // Set UsesTemplate to false on error and save
148
121
  // This ensures the query is still usable even if AI extraction fails
149
122
  this.UsesTemplate = false;
@@ -151,7 +124,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
151
124
  await super.Save();
152
125
  }
153
126
  catch (saveError) {
154
- (0, core_1.LogError)('Failed to save query after AI processing error:', saveError);
127
+ LogError('Failed to save query after AI processing error:', saveError);
155
128
  }
156
129
  }
157
130
  }
@@ -168,11 +141,11 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
168
141
  // Save the updated UsesTemplate flag
169
142
  const updateResult = await super.Save();
170
143
  if (!updateResult) {
171
- (0, core_1.LogError)('Failed to save query after cleanup');
144
+ LogError('Failed to save query after cleanup');
172
145
  }
173
146
  }
174
147
  catch (e) {
175
- (0, core_1.LogError)('Error in async cleanup:', e);
148
+ LogError('Error in async cleanup:', e);
176
149
  }
177
150
  }
178
151
  async extractAndSyncData() {
@@ -182,9 +155,9 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
182
155
  this.SQL.includes('{%') ||
183
156
  this.SQL.includes('{#'));
184
157
  // Ensure AIEngine is configured
185
- await aiengine_1.AIEngine.Instance.Config(false, this.ContextCurrentUser, this.ProviderToUse);
158
+ await AIEngine.Instance.Config(false, this.ContextCurrentUser, this.ProviderToUse);
186
159
  // Find the SQL Query Parameter Extraction prompt
187
- const aiPrompt = aiengine_1.AIEngine.Instance.Prompts.find(p => p.Name === 'SQL Query Parameter Extraction' &&
160
+ const aiPrompt = AIEngine.Instance.Prompts.find(p => p.Name === 'SQL Query Parameter Extraction' &&
188
161
  p.Category === 'MJ: System');
189
162
  if (!aiPrompt) {
190
163
  // Prompt not configured, non-fatal, just warn and return
@@ -202,8 +175,8 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
202
175
  entities: entityMetadata
203
176
  };
204
177
  // Execute the prompt using AIPromptRunner
205
- const promptRunner = new ai_prompts_1.AIPromptRunner();
206
- const params = new ai_core_plus_1.AIPromptParams();
178
+ const promptRunner = new AIPromptRunner();
179
+ const params = new AIPromptParams();
207
180
  params.prompt = aiPrompt;
208
181
  params.data = promptData;
209
182
  params.contextUser = this.ContextCurrentUser;
@@ -248,7 +221,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
248
221
  }
249
222
  catch (e) {
250
223
  // Unexpected error during extraction - log for debugging but don't fail the save
251
- (0, core_1.LogError)(`Query "${this.Name}" AI extraction error:`, e);
224
+ LogError(`Query "${this.Name}" AI extraction error:`, e);
252
225
  this.UsesTemplate = false;
253
226
  }
254
227
  }
@@ -262,69 +235,41 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
262
235
  if (!this.SQL)
263
236
  return results;
264
237
  try {
265
- // Pre-process Nunjucks templates to get valid SQL for parsing
266
- const processedSQL = this.preProcessNunjucksForParsing(this.SQL);
267
- // Parse the SQL using node-sql-parser
268
- const parser = new node_sql_parser_1.Parser();
269
- let ast;
270
- try {
271
- ast = parser.astify(processedSQL, { database: 'TransactSQL' });
272
- }
273
- catch (parseError) {
274
- // If parsing fails, fall back to regex-based extraction
275
- console.warn(`SQL parsing failed, falling back to regex: ${parseError.message}`);
276
- return this.extractEntityMetadataFromSQLRegex();
277
- }
278
- // Extract table references and column references from AST
279
- const tableAliasMap = new Map();
280
- const referencedColumns = new Set();
281
- // Process AST (handle both single statement and array of statements)
282
- const statements = Array.isArray(ast) ? ast : [ast];
283
- for (const statement of statements) {
284
- this.extractFromAST(statement, tableAliasMap, referencedColumns);
285
- }
286
- // Build entity metadata with only referenced fields
287
- const processedEntities = new Set();
288
- for (const [alias, tableInfo] of tableAliasMap) {
289
- const schemaName = tableInfo.schemaName || 'dbo';
290
- const tableName = tableInfo.tableName;
291
- const key = `${schemaName.toLowerCase()}.${tableName.toLowerCase()}`;
292
- if (processedEntities.has(key))
293
- continue;
294
- processedEntities.add(key);
295
- // Find matching entity in metadata
296
- const matchingEntity = md.Entities.find(e => (e.BaseView.toLowerCase() === tableName.toLowerCase() ||
297
- e.BaseTable.toLowerCase() === tableName.toLowerCase()) &&
298
- e.SchemaName.toLowerCase() === schemaName.toLowerCase());
238
+ // Use the shared SQLParser with Nunjucks preprocessing
239
+ const parseResult = SQLParser.ParseWithTemplatePreprocessing(this.SQL);
240
+ // Cross-reference parsed tables against entity metadata
241
+ for (const tableRef of parseResult.Tables) {
242
+ const matchingEntity = md.Entities.find(e => (e.BaseView.toLowerCase() === tableRef.TableName.toLowerCase() ||
243
+ e.BaseTable.toLowerCase() === tableRef.TableName.toLowerCase()) &&
244
+ e.SchemaName.toLowerCase() === tableRef.SchemaName.toLowerCase());
299
245
  if (matchingEntity) {
300
- // Get fields from the entity's Fields property
301
- const entityFields = matchingEntity.Fields;
302
246
  // Filter to fields that are actually referenced in the SQL
303
- // Check both the field name directly and with table alias prefix
304
- const relevantFields = entityFields
247
+ const relevantFields = matchingEntity.Fields
305
248
  .filter(f => {
306
249
  const fieldLower = f.Name.toLowerCase();
307
- // Check if this field is referenced directly or with any alias
308
- for (const colRef of referencedColumns) {
309
- const colLower = colRef.toLowerCase();
310
- // Match: fieldName, alias.fieldName, tableName.fieldName
311
- if (colLower === fieldLower ||
312
- colLower === `${alias.toLowerCase()}.${fieldLower}` ||
313
- colLower === `${tableName.toLowerCase()}.${fieldLower}` ||
314
- colLower.endsWith(`.${fieldLower}`)) {
250
+ for (const colRef of parseResult.Columns) {
251
+ const colLower = colRef.ColumnName.toLowerCase();
252
+ if (colLower === fieldLower)
315
253
  return true;
254
+ // Check if column qualifier matches table alias or name
255
+ if (colRef.TableQualifier) {
256
+ const qualLower = colRef.TableQualifier.toLowerCase();
257
+ if ((qualLower === tableRef.Alias.toLowerCase() ||
258
+ qualLower === tableRef.TableName.toLowerCase()) &&
259
+ colLower === fieldLower) {
260
+ return true;
261
+ }
316
262
  }
317
263
  }
318
264
  // Also include primary keys as they're always useful context
319
265
  return f.IsPrimaryKey;
320
266
  })
321
- .slice(0, 20) // Limit to 20 most relevant fields per entity
267
+ .slice(0, 20)
322
268
  .map(f => ({
323
269
  name: f.Name,
324
270
  type: f.Type,
325
271
  isPrimaryKey: f.IsPrimaryKey
326
272
  }));
327
- // Only include entity if we found relevant fields
328
273
  if (relevantFields.length > 0) {
329
274
  results.push({
330
275
  name: matchingEntity.Name,
@@ -338,225 +283,9 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
338
283
  return results;
339
284
  }
340
285
  catch (error) {
341
- console.warn(`Error in extractEntityMetadataFromSQL: ${error.message}`);
342
- return this.extractEntityMetadataFromSQLRegex();
343
- }
344
- }
345
- /**
346
- * Pre-processes Nunjucks templates in SQL to create valid SQL for parsing.
347
- * Replaces Nunjucks syntax with placeholder values.
348
- */
349
- preProcessNunjucksForParsing(sql) {
350
- // Create a Nunjucks environment that won't throw on undefined
351
- const env = new nunjucks.Environment(null, {
352
- autoescape: false,
353
- throwOnUndefined: false
354
- });
355
- // Add placeholder filters that return safe SQL values
356
- env.addFilter('sqlString', () => "'placeholder'");
357
- env.addFilter('sqlNumber', () => '0');
358
- env.addFilter('sqlDate', () => "'2000-01-01'");
359
- env.addFilter('sqlIn', () => "('placeholder')");
360
- env.addFilter('sqlIdentifier', (val) => val || 'placeholder');
361
- env.addFilter('sqlNoKeywordsExpression', (val) => val || 'placeholder');
362
- env.addFilter('default', (val, defaultVal) => val || defaultVal || 'placeholder');
363
- env.addFilter('safe', (val) => val || 'placeholder');
364
- env.addFilter('dump', (val) => JSON.stringify(val || {}));
365
- try {
366
- // Try to render the template with placeholder data
367
- // This handles most Nunjucks constructs
368
- const rendered = env.renderString(sql, {});
369
- return rendered;
370
- }
371
- catch (e) {
372
- // If rendering fails, do manual regex replacement
373
- let processed = sql;
374
- // Replace {{ variable | filter }} patterns
375
- processed = processed.replace(/\{\{\s*[\w.]+\s*\|\s*sqlString\s*\}\}/g, "'placeholder'");
376
- processed = processed.replace(/\{\{\s*[\w.]+\s*\|\s*sqlNumber\s*\}\}/g, '0');
377
- processed = processed.replace(/\{\{\s*[\w.]+\s*\|\s*sqlDate\s*\}\}/g, "'2000-01-01'");
378
- processed = processed.replace(/\{\{\s*[\w.]+\s*\|\s*sqlIn\s*\}\}/g, "('placeholder')");
379
- processed = processed.replace(/\{\{\s*[\w.]+\s*\|\s*sqlIdentifier\s*\}\}/g, 'placeholder');
380
- processed = processed.replace(/\{\{\s*[\w.]+\s*[^}]*\}\}/g, "'placeholder'");
381
- // Remove {% if %}, {% endif %}, {% for %}, {% endfor %} blocks
382
- // Keep the content between them
383
- processed = processed.replace(/\{%\s*if\s+[^%]+%\}/g, '');
384
- processed = processed.replace(/\{%\s*endif\s*%\}/g, '');
385
- processed = processed.replace(/\{%\s*else\s*%\}/g, '');
386
- processed = processed.replace(/\{%\s*elif\s+[^%]+%\}/g, '');
387
- processed = processed.replace(/\{%\s*for\s+[^%]+%\}/g, '');
388
- processed = processed.replace(/\{%\s*endfor\s*%\}/g, '');
389
- processed = processed.replace(/\{%\s*set\s+[^%]+%\}/g, '');
390
- processed = processed.replace(/\{#[^#]*#\}/g, ''); // Comments
391
- return processed;
392
- }
393
- }
394
- /**
395
- * Recursively extracts table references and column references from SQL AST.
396
- */
397
- extractFromAST(node, tableAliasMap, referencedColumns) {
398
- if (!node || typeof node !== 'object')
399
- return;
400
- // Handle CTEs (WITH clause) - process these first as they define tables used later
401
- if (node.with) {
402
- for (const cte of Array.isArray(node.with) ? node.with : [node.with]) {
403
- // CTE structure can vary - check multiple possible locations
404
- if (cte.stmt) {
405
- // stmt might be the AST directly or contain ast property
406
- const cteAst = cte.stmt.ast || cte.stmt;
407
- this.extractFromAST(cteAst, tableAliasMap, referencedColumns);
408
- }
409
- }
410
- }
411
- // Extract FROM clause tables (including JOINs)
412
- if (node.from) {
413
- for (const fromItem of Array.isArray(node.from) ? node.from : [node.from]) {
414
- this.extractTableFromItem(fromItem, tableAliasMap, referencedColumns);
415
- }
416
- }
417
- // Extract column references from SELECT
418
- if (node.columns) {
419
- for (const col of Array.isArray(node.columns) ? node.columns : [node.columns]) {
420
- if (col === '*')
421
- continue;
422
- if (col.expr) {
423
- this.extractColumnReferences(col.expr, referencedColumns, tableAliasMap);
424
- }
425
- }
426
- }
427
- // Extract column references from WHERE (and tables from subqueries like EXISTS, IN)
428
- if (node.where) {
429
- this.extractColumnReferences(node.where, referencedColumns, tableAliasMap);
430
- }
431
- // Extract column references from GROUP BY
432
- if (node.groupby) {
433
- const groupItems = node.groupby.columns || node.groupby;
434
- for (const group of Array.isArray(groupItems) ? groupItems : [groupItems]) {
435
- this.extractColumnReferences(group, referencedColumns, tableAliasMap);
436
- }
437
- }
438
- // Extract column references from ORDER BY
439
- if (node.orderby) {
440
- for (const order of Array.isArray(node.orderby) ? node.orderby : [node.orderby]) {
441
- this.extractColumnReferences(order.expr || order, referencedColumns, tableAliasMap);
442
- }
443
- }
444
- // Handle UNION/INTERSECT/EXCEPT - the next query is in _next
445
- if (node._next) {
446
- this.extractFromAST(node._next, tableAliasMap, referencedColumns);
447
- }
448
- }
449
- /**
450
- * Extracts table information from a FROM clause item, handling tables and JOINs.
451
- */
452
- extractTableFromItem(fromItem, tableAliasMap, referencedColumns) {
453
- if (!fromItem)
454
- return;
455
- // Direct table reference
456
- if (fromItem.table) {
457
- const alias = fromItem.as || fromItem.table;
458
- tableAliasMap.set(alias, {
459
- schemaName: fromItem.db || 'dbo',
460
- tableName: fromItem.table
461
- });
462
- }
463
- // Handle subqueries in FROM (derived tables)
464
- if (fromItem.expr) {
465
- // The subquery AST is inside expr.ast
466
- const subqueryAst = fromItem.expr.ast || fromItem.expr;
467
- this.extractFromAST(subqueryAst, tableAliasMap, referencedColumns);
468
- }
469
- // Note: In node-sql-parser, JOINs are represented as separate items in the from array
470
- // with a 'join' property that's a string (e.g., "INNER JOIN", "LEFT JOIN")
471
- // So no need to recurse into join - each table is already in the from array
472
- // Extract column references from ON conditions
473
- if (fromItem.on) {
474
- this.extractColumnReferences(fromItem.on, referencedColumns, tableAliasMap);
475
- }
476
- // Some parsers use 'using' for join conditions
477
- if (fromItem.using) {
478
- for (const col of Array.isArray(fromItem.using) ? fromItem.using : [fromItem.using]) {
479
- if (typeof col === 'string') {
480
- referencedColumns.add(col);
481
- }
482
- else if (col.column) {
483
- referencedColumns.add(col.column);
484
- }
485
- }
486
- }
487
- }
488
- /**
489
- * Extracts column references from an expression node.
490
- * Also extracts tables from subqueries found in expressions (e.g., EXISTS, IN subqueries).
491
- */
492
- extractColumnReferences(expr, referencedColumns, tableAliasMap) {
493
- if (!expr || typeof expr !== 'object')
494
- return;
495
- if (expr.type === 'column_ref') {
496
- const colName = expr.table ? `${expr.table}.${expr.column}` : expr.column;
497
- referencedColumns.add(colName);
498
- }
499
- // Handle subqueries in expressions (EXISTS, IN, scalar subqueries)
500
- if (expr.ast && tableAliasMap) {
501
- this.extractFromAST(expr.ast, tableAliasMap, referencedColumns);
502
- }
503
- // Recursively process nested expressions
504
- if (expr.left)
505
- this.extractColumnReferences(expr.left, referencedColumns, tableAliasMap);
506
- if (expr.right)
507
- this.extractColumnReferences(expr.right, referencedColumns, tableAliasMap);
508
- if (expr.args) {
509
- const args = expr.args.value || expr.args;
510
- for (const arg of Array.isArray(args) ? args : [args]) {
511
- this.extractColumnReferences(arg, referencedColumns, tableAliasMap);
512
- }
513
- }
514
- if (expr.expr)
515
- this.extractColumnReferences(expr.expr, referencedColumns, tableAliasMap);
516
- }
517
- /**
518
- * Fallback regex-based extraction for when SQL parsing fails.
519
- */
520
- extractEntityMetadataFromSQLRegex() {
521
- const md = this.ProviderToUse;
522
- const results = [];
523
- if (!this.SQL)
286
+ console.warn(`Error in extractEntityMetadataFromSQL: ${error}`);
524
287
  return results;
525
- // Simple regex to find schema.table or schema.view references in SQL
526
- const tablePattern = /(?:FROM|JOIN|INTO)\s+(?:\[?(\w+)\]?\.)?\[?(\w+)\]?(?:\s+(?:AS\s+)?(\w+))?/gi;
527
- const matches = [...this.SQL.matchAll(tablePattern)];
528
- const processedViews = new Set();
529
- for (const match of matches) {
530
- const schemaName = match[1] || 'dbo';
531
- const viewOrTable = match[2];
532
- const key = `${schemaName.toLowerCase()}.${viewOrTable.toLowerCase()}`;
533
- if (processedViews.has(key))
534
- continue;
535
- processedViews.add(key);
536
- const matchingEntity = md.Entities.find(e => (e.BaseView.toLowerCase() === viewOrTable.toLowerCase() ||
537
- e.BaseTable.toLowerCase() === viewOrTable.toLowerCase()) &&
538
- e.SchemaName.toLowerCase() === schemaName.toLowerCase());
539
- if (matchingEntity) {
540
- // Get fields from the entity's Fields property
541
- const entityFields = matchingEntity.Fields;
542
- // Include primary keys and fields ending in ID for fallback
543
- const relevantFields = entityFields
544
- .filter(f => f.IsPrimaryKey || f.Name.endsWith('ID'))
545
- .slice(0, 15)
546
- .map(f => ({
547
- name: f.Name,
548
- type: f.Type,
549
- isPrimaryKey: f.IsPrimaryKey
550
- }));
551
- results.push({
552
- name: matchingEntity.Name,
553
- schemaName: matchingEntity.SchemaName,
554
- baseView: matchingEntity.BaseView,
555
- fields: relevantFields
556
- });
557
- }
558
288
  }
559
- return results;
560
289
  }
561
290
  async syncQueryParameters(extractedParams) {
562
291
  // Use the entity's provider instead of creating new Metadata instance
@@ -679,7 +408,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
679
408
  }
680
409
  }
681
410
  catch (e) {
682
- (0, core_1.LogError)(`Query "${this.Name}" - Failed to sync parameters:`, e);
411
+ LogError(`Query "${this.Name}" - Failed to sync parameters:`, e);
683
412
  throw e;
684
413
  }
685
414
  }
@@ -705,7 +434,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
705
434
  }
706
435
  }
707
436
  catch (e) {
708
- (0, core_1.LogError)('Failed to remove query parameters:', e);
437
+ LogError('Failed to remove query parameters:', e);
709
438
  throw e; // Re-throw since we're in a transaction
710
439
  }
711
440
  }
@@ -895,7 +624,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
895
624
  }
896
625
  }
897
626
  catch (e) {
898
- (0, core_1.LogError)(`Query "${this.Name}" - Failed to sync fields:`, e);
627
+ LogError(`Query "${this.Name}" - Failed to sync fields:`, e);
899
628
  throw e;
900
629
  }
901
630
  }
@@ -959,7 +688,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
959
688
  }
960
689
  }
961
690
  catch (e) {
962
- (0, core_1.LogError)(`Query "${this.Name}" - Failed to sync entities:`, e);
691
+ LogError(`Query "${this.Name}" - Failed to sync entities:`, e);
963
692
  throw e;
964
693
  }
965
694
  }
@@ -983,7 +712,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
983
712
  }
984
713
  }
985
714
  catch (e) {
986
- (0, core_1.LogError)('Failed to remove query fields:', e);
715
+ LogError('Failed to remove query fields:', e);
987
716
  throw e;
988
717
  }
989
718
  }
@@ -1007,7 +736,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
1007
736
  }
1008
737
  }
1009
738
  catch (e) {
1010
- (0, core_1.LogError)('Failed to remove query entities:', e);
739
+ LogError('Failed to remove query entities:', e);
1011
740
  throw e;
1012
741
  }
1013
742
  }
@@ -1035,7 +764,7 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
1035
764
  async RefreshRelatedMetadata(refreshFromDB) {
1036
765
  const md = this.ProviderToUse;
1037
766
  if (refreshFromDB) {
1038
- const globalMetadataProvider = core_1.Metadata.Provider;
767
+ const globalMetadataProvider = Metadata.Provider;
1039
768
  await globalMetadataProvider.Refresh(md); // we pass in our metadata provider because that is the connection we want to use if we are in the midst of a transaction
1040
769
  if (globalMetadataProvider !== md) {
1041
770
  // If the global metadata provider is different, we need to refresh it
@@ -1048,10 +777,8 @@ let QueryEntityExtended = class QueryEntityExtended extends core_entities_1.Quer
1048
777
  this._queryParameters = md.QueryParameters.filter(p => p.QueryID === this.ID);
1049
778
  }
1050
779
  };
1051
- exports.QueryEntityExtended = QueryEntityExtended;
1052
- exports.QueryEntityExtended = QueryEntityExtended = __decorate([
1053
- (0, global_1.RegisterClass)(core_1.BaseEntity, 'Queries')
780
+ QueryEntityExtended = __decorate([
781
+ RegisterClass(BaseEntity, 'Queries')
1054
782
  ], QueryEntityExtended);
1055
- function LoadQueryEntityServerSubClass() { }
1056
- exports.LoadQueryEntityServerSubClass = LoadQueryEntityServerSubClass;
783
+ export { QueryEntityExtended };
1057
784
  //# sourceMappingURL=QueryEntity.server.js.map