code-graph-context 2.4.0 → 2.4.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/dist/core/config/fairsquare-framework-schema.js +6 -14
- package/dist/core/config/nestjs-framework-schema.js +9 -3
- package/dist/core/config/schema.js +6 -0
- package/dist/core/embeddings/natural-language-to-cypher.service.js +31 -14
- package/dist/core/parsers/typescript-parser.js +15 -7
- package/package.json +1 -1
|
@@ -525,13 +525,11 @@ export const FAIRSQUARE_FRAMEWORK_SCHEMA = {
|
|
|
525
525
|
{
|
|
526
526
|
type: 'function',
|
|
527
527
|
pattern: (parsedNode) => {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const name = node.getName();
|
|
532
|
-
const typeNode = node.getTypeNode();
|
|
528
|
+
// Use pre-extracted properties (works after AST cleanup in streaming/chunking)
|
|
529
|
+
const name = parsedNode.properties.name;
|
|
530
|
+
const typeAnnotation = parsedNode.properties.typeAnnotation;
|
|
533
531
|
// Check if variable name ends with "Routes" AND has type ModuleRoute[]
|
|
534
|
-
return !!name
|
|
532
|
+
return !!name?.endsWith('Routes') && !!typeAnnotation?.includes('ModuleRoute');
|
|
535
533
|
},
|
|
536
534
|
confidence: 1.0,
|
|
537
535
|
priority: 10,
|
|
@@ -696,14 +694,8 @@ export const FAIRSQUARE_FRAMEWORK_SCHEMA = {
|
|
|
696
694
|
if (matchingRoutes.length === 0)
|
|
697
695
|
return false;
|
|
698
696
|
// CRITICAL FIX: Verify the method belongs to the correct controller
|
|
699
|
-
//
|
|
700
|
-
const
|
|
701
|
-
if (!targetNode || !Node.isMethodDeclaration(targetNode))
|
|
702
|
-
return false;
|
|
703
|
-
const parentClass = targetNode.getParent();
|
|
704
|
-
if (!parentClass || !Node.isClassDeclaration(parentClass))
|
|
705
|
-
return false;
|
|
706
|
-
const parentClassName = parentClass.getName();
|
|
697
|
+
// Use pre-extracted parentClassName property (works after AST cleanup in streaming/chunking)
|
|
698
|
+
const parentClassName = parsedTargetNode.properties.parentClassName;
|
|
707
699
|
if (!parentClassName)
|
|
708
700
|
return false;
|
|
709
701
|
// Check if any matching route's controller name matches the parent class
|
|
@@ -434,7 +434,7 @@ export const NESTJS_FRAMEWORK_SCHEMA = {
|
|
|
434
434
|
},
|
|
435
435
|
{
|
|
436
436
|
type: 'function',
|
|
437
|
-
pattern: (
|
|
437
|
+
pattern: (parsedNode) => parsedNode.sourceNode?.getName()?.endsWith('Service'),
|
|
438
438
|
confidence: 0.7,
|
|
439
439
|
priority: 7,
|
|
440
440
|
},
|
|
@@ -516,7 +516,10 @@ export const NESTJS_FRAMEWORK_SCHEMA = {
|
|
|
516
516
|
detectionPatterns: [
|
|
517
517
|
{
|
|
518
518
|
type: 'function',
|
|
519
|
-
pattern: (
|
|
519
|
+
pattern: (parsedNode) => {
|
|
520
|
+
const node = parsedNode.sourceNode;
|
|
521
|
+
if (!node)
|
|
522
|
+
return false;
|
|
520
523
|
const decorators = node.getDecorators?.() ?? [];
|
|
521
524
|
const messageDecorators = ['MessagePattern', 'EventPattern'];
|
|
522
525
|
return decorators.some((d) => messageDecorators.includes(d.getName()));
|
|
@@ -567,7 +570,10 @@ export const NESTJS_FRAMEWORK_SCHEMA = {
|
|
|
567
570
|
detectionPatterns: [
|
|
568
571
|
{
|
|
569
572
|
type: 'function',
|
|
570
|
-
pattern: (
|
|
573
|
+
pattern: (parsedNode) => {
|
|
574
|
+
const node = parsedNode.sourceNode;
|
|
575
|
+
if (!node)
|
|
576
|
+
return false;
|
|
571
577
|
const decorators = node.getDecorators?.() ?? [];
|
|
572
578
|
const httpDecorators = ['Get', 'Post', 'Put', 'Delete', 'Patch', 'Head', 'Options'];
|
|
573
579
|
return decorators.some((d) => httpDecorators.includes(d.getName()));
|
|
@@ -480,6 +480,12 @@ export const CORE_TYPESCRIPT_SCHEMA = {
|
|
|
480
480
|
extraction: { method: 'static', defaultValue: false }, // We'll set this manually
|
|
481
481
|
neo4j: { indexed: true, unique: false, required: true },
|
|
482
482
|
},
|
|
483
|
+
{
|
|
484
|
+
name: 'typeAnnotation',
|
|
485
|
+
type: 'string',
|
|
486
|
+
extraction: { method: 'ast', source: 'getTypeNode', transform: 'getText' },
|
|
487
|
+
neo4j: { indexed: false, unique: false, required: false },
|
|
488
|
+
},
|
|
483
489
|
],
|
|
484
490
|
relationships: [],
|
|
485
491
|
children: {},
|
|
@@ -277,16 +277,24 @@ Provide ONLY the JSON response with no additional text, markdown formatting, or
|
|
|
277
277
|
frameworkHint = '\nFRAMEWORK DETECTED: React/functional codebase. Use Function nodes for components.';
|
|
278
278
|
}
|
|
279
279
|
return `
|
|
280
|
-
|
|
280
|
+
=== VALID NODE LABELS (use ONLY these after the colon) ===
|
|
281
|
+
${nodeTypes}
|
|
281
282
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
283
|
+
=== VALID RELATIONSHIP TYPES ===
|
|
284
|
+
${relTypes}
|
|
285
|
+
|
|
286
|
+
=== SEMANTIC TYPES (these are PROPERTY values, NOT labels) ===
|
|
287
|
+
${semTypes}
|
|
288
|
+
Query semantic types via property: WHERE n.semanticType = 'TypeName'
|
|
285
289
|
${frameworkHint}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
+
|
|
291
|
+
=== CRITICAL RULES ===
|
|
292
|
+
1. Use ONLY the labels listed above after the colon (:Label)
|
|
293
|
+
2. Semantic types are PROPERTY values, NOT labels
|
|
294
|
+
3. Class/service names are PROPERTY values, NOT labels
|
|
295
|
+
4. WRONG: (n:MyService), (n:MyController) - names as labels
|
|
296
|
+
5. CORRECT: (n:Service {name: 'MyService'}), (n:Controller {name: 'MyController'})
|
|
297
|
+
6. CORRECT: (n:Class) WHERE n.semanticType = 'Service'
|
|
290
298
|
`.trim();
|
|
291
299
|
}
|
|
292
300
|
catch (error) {
|
|
@@ -507,7 +515,7 @@ Remember to include WHERE n.projectId = $projectId for all node patterns.
|
|
|
507
515
|
}
|
|
508
516
|
/**
|
|
509
517
|
* Load valid labels dynamically from the schema file.
|
|
510
|
-
* Returns all keys from rawSchema which represent actual Neo4j labels.
|
|
518
|
+
* Returns all keys from rawSchema AND discoveredSchema.nodeTypes which represent actual Neo4j labels.
|
|
511
519
|
*/
|
|
512
520
|
loadValidLabelsFromSchema() {
|
|
513
521
|
// Fallback to core TypeScript labels if schema not available
|
|
@@ -535,12 +543,21 @@ Remember to include WHERE n.projectId = $projectId for all node patterns.
|
|
|
535
543
|
try {
|
|
536
544
|
const content = fs.readFileSync(this.schemaPath, 'utf-8');
|
|
537
545
|
const schema = JSON.parse(content);
|
|
538
|
-
|
|
539
|
-
|
|
546
|
+
const allLabels = new Set(coreLabels);
|
|
547
|
+
// Extract labels from rawSchema keys
|
|
548
|
+
if (schema.rawSchema?.records?.[0]?._fields?.[0]) {
|
|
549
|
+
const schemaLabels = Object.keys(schema.rawSchema.records[0]._fields[0]);
|
|
550
|
+
schemaLabels.forEach((label) => allLabels.add(label));
|
|
551
|
+
}
|
|
552
|
+
// Also extract labels from discoveredSchema.nodeTypes (includes framework labels)
|
|
553
|
+
if (schema.discoveredSchema?.nodeTypes) {
|
|
554
|
+
for (const nodeType of schema.discoveredSchema.nodeTypes) {
|
|
555
|
+
if (nodeType.label) {
|
|
556
|
+
allLabels.add(nodeType.label);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
540
559
|
}
|
|
541
|
-
|
|
542
|
-
const schemaLabels = Object.keys(schema.rawSchema.records[0]._fields[0]);
|
|
543
|
-
return new Set([...coreLabels, ...schemaLabels]);
|
|
560
|
+
return allLabels;
|
|
544
561
|
}
|
|
545
562
|
catch {
|
|
546
563
|
return coreLabels;
|
|
@@ -542,6 +542,11 @@ export class TypeScriptParser {
|
|
|
542
542
|
return astNode.getName();
|
|
543
543
|
}
|
|
544
544
|
break;
|
|
545
|
+
case CoreNodeType.VARIABLE_DECLARATION:
|
|
546
|
+
if (Node.isVariableDeclaration(astNode)) {
|
|
547
|
+
return astNode.getName();
|
|
548
|
+
}
|
|
549
|
+
break;
|
|
545
550
|
default:
|
|
546
551
|
return astNode.getKindName();
|
|
547
552
|
}
|
|
@@ -552,13 +557,18 @@ export class TypeScriptParser {
|
|
|
552
557
|
return 'Unknown';
|
|
553
558
|
}
|
|
554
559
|
extractProperty(astNode, propDef) {
|
|
555
|
-
const { method, source, defaultValue } = propDef.extraction;
|
|
560
|
+
const { method, source, defaultValue, transform } = propDef.extraction;
|
|
556
561
|
try {
|
|
557
562
|
switch (method) {
|
|
558
563
|
case 'ast':
|
|
559
564
|
if (typeof source === 'string') {
|
|
560
565
|
const fn = astNode[source];
|
|
561
|
-
|
|
566
|
+
let result = typeof fn === 'function' ? fn.call(astNode) : defaultValue;
|
|
567
|
+
// Apply transform if specified (e.g., 'getText' on a returned node)
|
|
568
|
+
if (result && transform && typeof result[transform] === 'function') {
|
|
569
|
+
result = result[transform]();
|
|
570
|
+
}
|
|
571
|
+
return result ?? defaultValue;
|
|
562
572
|
}
|
|
563
573
|
return defaultValue;
|
|
564
574
|
case 'function':
|
|
@@ -1284,11 +1294,9 @@ export class TypeScriptParser {
|
|
|
1284
1294
|
}
|
|
1285
1295
|
case 'function':
|
|
1286
1296
|
if (typeof pattern.pattern === 'function') {
|
|
1287
|
-
// Pass the
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
return false;
|
|
1291
|
-
return pattern.pattern(astNode);
|
|
1297
|
+
// Pass the ParsedNode to pattern functions
|
|
1298
|
+
// Patterns should use pre-extracted properties for cross-chunk compatibility
|
|
1299
|
+
return pattern.pattern(node);
|
|
1292
1300
|
}
|
|
1293
1301
|
return false;
|
|
1294
1302
|
case 'classname':
|
package/package.json
CHANGED