code-graph-context 2.4.4 → 2.5.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.
@@ -1,1595 +0,0 @@
1
- /* eslint-disable prefer-arrow/prefer-arrow-functions */
2
- /* eslint-disable @typescript-eslint/no-explicit-any */
3
- // graph.ts - Optimized for Neo4j performance with context-based framework properties
4
- // ============================================================================
5
- // CORE ENUMS
6
- // ============================================================================
7
- /**
8
- * Core TypeScript AST Node Types (from ts-morph)
9
- */
10
- export var CoreNodeType;
11
- (function (CoreNodeType) {
12
- // File System & Workspace
13
- CoreNodeType["SOURCE_FILE"] = "SourceFile";
14
- // Core TypeScript AST Declarations
15
- CoreNodeType["CLASS_DECLARATION"] = "ClassDeclaration";
16
- CoreNodeType["INTERFACE_DECLARATION"] = "InterfaceDeclaration";
17
- CoreNodeType["ENUM_DECLARATION"] = "EnumDeclaration";
18
- CoreNodeType["FUNCTION_DECLARATION"] = "FunctionDeclaration";
19
- CoreNodeType["VARIABLE_DECLARATION"] = "VariableDeclaration";
20
- // Class Members
21
- CoreNodeType["METHOD_DECLARATION"] = "MethodDeclaration";
22
- CoreNodeType["PROPERTY_DECLARATION"] = "PropertyDeclaration";
23
- CoreNodeType["CONSTRUCTOR_DECLARATION"] = "ConstructorDeclaration";
24
- CoreNodeType["PARAMETER_DECLARATION"] = "ParameterDeclaration";
25
- // Import/Export System
26
- CoreNodeType["IMPORT_DECLARATION"] = "ImportDeclaration";
27
- CoreNodeType["EXPORT_DECLARATION"] = "ExportDeclaration";
28
- // Decorators
29
- CoreNodeType["DECORATOR"] = "Decorator";
30
- })(CoreNodeType || (CoreNodeType = {}));
31
- /**
32
- * Core Edge Types (AST relationships)
33
- */
34
- export var CoreEdgeType;
35
- (function (CoreEdgeType) {
36
- // File Structure
37
- CoreEdgeType["CONTAINS"] = "CONTAINS";
38
- // Import/Export
39
- CoreEdgeType["IMPORTS"] = "IMPORTS";
40
- CoreEdgeType["EXPORTS"] = "EXPORTS";
41
- // Type System
42
- CoreEdgeType["EXTENDS"] = "EXTENDS";
43
- CoreEdgeType["IMPLEMENTS"] = "IMPLEMENTS";
44
- CoreEdgeType["TYPED_AS"] = "TYPED_AS";
45
- // Code Structure
46
- CoreEdgeType["HAS_MEMBER"] = "HAS_MEMBER";
47
- CoreEdgeType["HAS_PARAMETER"] = "HAS_PARAMETER";
48
- CoreEdgeType["CALLS"] = "CALLS";
49
- // Decorator
50
- CoreEdgeType["DECORATED_WITH"] = "DECORATED_WITH";
51
- })(CoreEdgeType || (CoreEdgeType = {}));
52
- /**
53
- * Semantic Node Types (Framework interpretations)
54
- */
55
- export var SemanticNodeType;
56
- (function (SemanticNodeType) {
57
- // NestJS Framework Types
58
- SemanticNodeType["NEST_MODULE"] = "NestModule";
59
- SemanticNodeType["NEST_CONTROLLER"] = "NestController";
60
- SemanticNodeType["NEST_SERVICE"] = "NestService";
61
- SemanticNodeType["NEST_GUARD"] = "NestGuard";
62
- SemanticNodeType["NEST_PIPE"] = "NestPipe";
63
- SemanticNodeType["NEST_INTERCEPTOR"] = "NestInterceptor";
64
- SemanticNodeType["NEST_FILTER"] = "NestFilter";
65
- SemanticNodeType["NEST_PROVIDER"] = "NestProvider";
66
- // HTTP & API Types
67
- SemanticNodeType["HTTP_ENDPOINT"] = "HttpEndpoint";
68
- SemanticNodeType["MESSAGE_HANDLER"] = "MessageHandler";
69
- // Data Types
70
- SemanticNodeType["DTO_CLASS"] = "DTOClass";
71
- SemanticNodeType["ENTITY_CLASS"] = "EntityClass";
72
- SemanticNodeType["CONFIG_CLASS"] = "ConfigClass";
73
- // Testing
74
- SemanticNodeType["TEST_CLASS"] = "TestClass";
75
- })(SemanticNodeType || (SemanticNodeType = {}));
76
- /**
77
- * Semantic Edge Types (Framework relationships)
78
- */
79
- export var SemanticEdgeType;
80
- (function (SemanticEdgeType) {
81
- // NestJS Module System
82
- SemanticEdgeType["MODULE_IMPORTS"] = "MODULE_IMPORTS";
83
- SemanticEdgeType["MODULE_PROVIDES"] = "MODULE_PROVIDES";
84
- SemanticEdgeType["MODULE_EXPORTS"] = "MODULE_EXPORTS";
85
- // Dependency Injection
86
- SemanticEdgeType["INJECTS"] = "INJECTS";
87
- SemanticEdgeType["PROVIDED_BY"] = "PROVIDED_BY";
88
- // HTTP API
89
- SemanticEdgeType["EXPOSES"] = "EXPOSES";
90
- SemanticEdgeType["ACCEPTS"] = "ACCEPTS";
91
- SemanticEdgeType["RESPONDS_WITH"] = "RESPONDS_WITH";
92
- SemanticEdgeType["CONSUMES_MESSAGE"] = "CONSUMES_MESSAGE";
93
- // Security & Middleware
94
- SemanticEdgeType["GUARDED_BY"] = "GUARDED_BY";
95
- SemanticEdgeType["TRANSFORMED_BY"] = "TRANSFORMED_BY";
96
- SemanticEdgeType["INTERCEPTED_BY"] = "INTERCEPTED_BY";
97
- // Domain Logic
98
- SemanticEdgeType["MANAGES"] = "MANAGES";
99
- SemanticEdgeType["VALIDATES"] = "VALIDATES";
100
- // Testing
101
- SemanticEdgeType["TESTS"] = "TESTS";
102
- })(SemanticEdgeType || (SemanticEdgeType = {}));
103
- // ============================================================================
104
- // CORE TYPESCRIPT SCHEMA
105
- // ============================================================================
106
- export const CORE_TYPESCRIPT_SCHEMA = {
107
- name: 'Core TypeScript Schema',
108
- version: '2.0.0',
109
- nodeTypes: {
110
- [CoreNodeType.SOURCE_FILE]: {
111
- coreType: CoreNodeType.SOURCE_FILE,
112
- astNodeKind: 311,
113
- properties: [
114
- {
115
- name: 'name',
116
- type: 'string',
117
- extraction: { method: 'ast', source: 'getBaseName' },
118
- neo4j: { indexed: true, unique: false, required: true },
119
- },
120
- {
121
- name: 'filePath',
122
- type: 'string',
123
- extraction: { method: 'ast', source: 'getFilePath' },
124
- neo4j: { indexed: true, unique: true, required: true },
125
- },
126
- {
127
- name: 'isExported',
128
- type: 'boolean',
129
- extraction: { method: 'static', defaultValue: false },
130
- neo4j: { indexed: true, unique: false, required: true },
131
- },
132
- ],
133
- relationships: [CoreEdgeType.CONTAINS, CoreEdgeType.IMPORTS, CoreEdgeType.EXPORTS],
134
- neo4j: {
135
- labels: ['SourceFile', 'TypeScript'],
136
- primaryLabel: 'SourceFile',
137
- indexed: ['name', 'filePath', 'isExported'],
138
- skipEmbedding: true,
139
- },
140
- },
141
- [CoreNodeType.CLASS_DECLARATION]: {
142
- coreType: CoreNodeType.CLASS_DECLARATION,
143
- astNodeKind: 262,
144
- properties: [
145
- {
146
- name: 'name',
147
- type: 'string',
148
- extraction: { method: 'ast', source: 'getName' },
149
- neo4j: { indexed: true, unique: false, required: true },
150
- },
151
- {
152
- name: 'isExported',
153
- type: 'boolean',
154
- extraction: { method: 'ast', source: 'isExported', defaultValue: false },
155
- neo4j: { indexed: true, unique: false, required: true },
156
- },
157
- {
158
- name: 'visibility',
159
- type: 'string',
160
- extraction: {
161
- method: 'function',
162
- source: (node) => (node.isExported() ? 'public' : 'none'),
163
- defaultValue: 'none',
164
- },
165
- neo4j: { indexed: true, unique: false, required: true },
166
- },
167
- ],
168
- relationships: [
169
- CoreEdgeType.HAS_MEMBER,
170
- CoreEdgeType.EXTENDS,
171
- CoreEdgeType.IMPLEMENTS,
172
- CoreEdgeType.DECORATED_WITH,
173
- ],
174
- neo4j: {
175
- labels: ['Class', 'TypeScript'],
176
- primaryLabel: 'Class',
177
- indexed: ['name', 'isExported', 'visibility'],
178
- },
179
- },
180
- [CoreNodeType.METHOD_DECLARATION]: {
181
- coreType: CoreNodeType.METHOD_DECLARATION,
182
- astNodeKind: 172,
183
- properties: [
184
- {
185
- name: 'name',
186
- type: 'string',
187
- extraction: { method: 'ast', source: 'getName' },
188
- neo4j: { indexed: true, unique: false, required: true },
189
- },
190
- {
191
- name: 'visibility',
192
- type: 'string',
193
- extraction: {
194
- method: 'function',
195
- source: (node) => {
196
- const modifiers = node.getModifiers();
197
- for (const modifier of modifiers) {
198
- const kind = modifier.getKind();
199
- if (kind === 125)
200
- return 'public';
201
- if (kind === 123)
202
- return 'private';
203
- if (kind === 124)
204
- return 'protected';
205
- }
206
- return 'public';
207
- },
208
- defaultValue: 'public',
209
- },
210
- neo4j: { indexed: true, unique: false, required: true },
211
- },
212
- ],
213
- relationships: [CoreEdgeType.HAS_PARAMETER, CoreEdgeType.CALLS, CoreEdgeType.DECORATED_WITH],
214
- neo4j: {
215
- labels: ['Method', 'TypeScript'],
216
- primaryLabel: 'Method',
217
- indexed: ['name', 'visibility'],
218
- },
219
- },
220
- [CoreNodeType.PROPERTY_DECLARATION]: {
221
- coreType: CoreNodeType.PROPERTY_DECLARATION,
222
- astNodeKind: 171,
223
- properties: [
224
- {
225
- name: 'name',
226
- type: 'string',
227
- extraction: { method: 'ast', source: 'getName' },
228
- neo4j: { indexed: true, unique: false, required: true },
229
- },
230
- {
231
- name: 'visibility',
232
- type: 'string',
233
- extraction: {
234
- method: 'function',
235
- source: (node) => {
236
- const modifiers = node.getModifiers();
237
- for (const modifier of modifiers) {
238
- const kind = modifier.getKind();
239
- if (kind === 125)
240
- return 'public';
241
- if (kind === 123)
242
- return 'private';
243
- if (kind === 124)
244
- return 'protected';
245
- }
246
- return 'public';
247
- },
248
- defaultValue: 'public',
249
- },
250
- neo4j: { indexed: true, unique: false, required: true },
251
- },
252
- ],
253
- relationships: [CoreEdgeType.TYPED_AS, CoreEdgeType.DECORATED_WITH],
254
- neo4j: {
255
- labels: ['Property', 'TypeScript'],
256
- primaryLabel: 'Property',
257
- indexed: ['name', 'visibility'],
258
- skipEmbedding: true,
259
- },
260
- },
261
- [CoreNodeType.PARAMETER_DECLARATION]: {
262
- coreType: CoreNodeType.PARAMETER_DECLARATION,
263
- astNodeKind: 169,
264
- properties: [
265
- {
266
- name: 'name',
267
- type: 'string',
268
- extraction: { method: 'ast', source: 'getName' },
269
- neo4j: { indexed: true, unique: false, required: true },
270
- },
271
- ],
272
- relationships: [CoreEdgeType.TYPED_AS, CoreEdgeType.DECORATED_WITH],
273
- neo4j: {
274
- labels: ['Parameter', 'TypeScript'],
275
- primaryLabel: 'Parameter',
276
- indexed: ['name'],
277
- skipEmbedding: true,
278
- },
279
- },
280
- [CoreNodeType.IMPORT_DECLARATION]: {
281
- coreType: CoreNodeType.IMPORT_DECLARATION,
282
- astNodeKind: 272,
283
- properties: [
284
- {
285
- name: 'name',
286
- type: 'string',
287
- extraction: { method: 'ast', source: 'getModuleSpecifierValue' },
288
- neo4j: { indexed: true, unique: false, required: true },
289
- },
290
- ],
291
- relationships: [CoreEdgeType.IMPORTS],
292
- neo4j: {
293
- labels: ['Import', 'TypeScript'],
294
- primaryLabel: 'Import',
295
- indexed: ['name'],
296
- skipEmbedding: true,
297
- },
298
- },
299
- [CoreNodeType.DECORATOR]: {
300
- coreType: CoreNodeType.DECORATOR,
301
- astNodeKind: 170,
302
- properties: [
303
- {
304
- name: 'name',
305
- type: 'string',
306
- extraction: { method: 'ast', source: 'getName' },
307
- neo4j: { indexed: true, unique: false, required: true },
308
- },
309
- ],
310
- relationships: [],
311
- neo4j: {
312
- labels: ['Decorator'],
313
- primaryLabel: 'Decorator',
314
- indexed: ['name'],
315
- skipEmbedding: true,
316
- },
317
- },
318
- // Add remaining core types with minimal properties
319
- [CoreNodeType.INTERFACE_DECLARATION]: {
320
- coreType: CoreNodeType.INTERFACE_DECLARATION,
321
- astNodeKind: 263,
322
- properties: [
323
- {
324
- name: 'name',
325
- type: 'string',
326
- extraction: { method: 'ast', source: 'getName' },
327
- neo4j: { indexed: true, unique: false, required: true },
328
- },
329
- {
330
- name: 'isExported',
331
- type: 'boolean',
332
- extraction: { method: 'ast', source: 'isExported', defaultValue: false },
333
- neo4j: { indexed: true, unique: false, required: true },
334
- },
335
- ],
336
- relationships: [CoreEdgeType.EXTENDS, CoreEdgeType.HAS_MEMBER],
337
- neo4j: {
338
- labels: ['Interface', 'TypeScript'],
339
- primaryLabel: 'Interface',
340
- indexed: ['name', 'isExported'],
341
- },
342
- },
343
- [CoreNodeType.ENUM_DECLARATION]: {
344
- coreType: CoreNodeType.ENUM_DECLARATION,
345
- astNodeKind: 264,
346
- properties: [
347
- {
348
- name: 'name',
349
- type: 'string',
350
- extraction: { method: 'ast', source: 'getName' },
351
- neo4j: { indexed: true, unique: false, required: true },
352
- },
353
- {
354
- name: 'isExported',
355
- type: 'boolean',
356
- extraction: { method: 'ast', source: 'isExported', defaultValue: false },
357
- neo4j: { indexed: true, unique: false, required: true },
358
- },
359
- ],
360
- relationships: [],
361
- neo4j: {
362
- labels: ['Enum', 'TypeScript'],
363
- primaryLabel: 'Enum',
364
- indexed: ['name', 'isExported'],
365
- skipEmbedding: true,
366
- },
367
- },
368
- [CoreNodeType.FUNCTION_DECLARATION]: {
369
- coreType: CoreNodeType.FUNCTION_DECLARATION,
370
- astNodeKind: 261,
371
- properties: [
372
- {
373
- name: 'name',
374
- type: 'string',
375
- extraction: { method: 'ast', source: 'getName' },
376
- neo4j: { indexed: true, unique: false, required: true },
377
- },
378
- {
379
- name: 'isExported',
380
- type: 'boolean',
381
- extraction: { method: 'ast', source: 'isExported', defaultValue: false },
382
- neo4j: { indexed: true, unique: false, required: true },
383
- },
384
- ],
385
- relationships: [CoreEdgeType.HAS_PARAMETER, CoreEdgeType.CALLS],
386
- neo4j: {
387
- labels: ['Function', 'TypeScript'],
388
- primaryLabel: 'Function',
389
- indexed: ['name', 'isExported'],
390
- },
391
- },
392
- [CoreNodeType.VARIABLE_DECLARATION]: {
393
- coreType: CoreNodeType.VARIABLE_DECLARATION,
394
- astNodeKind: 258,
395
- properties: [
396
- {
397
- name: 'name',
398
- type: 'string',
399
- extraction: { method: 'ast', source: 'getName' },
400
- neo4j: { indexed: true, unique: false, required: true },
401
- },
402
- ],
403
- relationships: [],
404
- neo4j: {
405
- labels: ['Variable', 'TypeScript'],
406
- primaryLabel: 'Variable',
407
- indexed: ['name'],
408
- skipEmbedding: true,
409
- },
410
- },
411
- [CoreNodeType.CONSTRUCTOR_DECLARATION]: {
412
- coreType: CoreNodeType.CONSTRUCTOR_DECLARATION,
413
- astNodeKind: 175,
414
- properties: [
415
- {
416
- name: 'name',
417
- type: 'string',
418
- extraction: { method: 'static', defaultValue: 'constructor' },
419
- neo4j: { indexed: true, unique: false, required: true },
420
- },
421
- ],
422
- relationships: [CoreEdgeType.HAS_PARAMETER],
423
- neo4j: {
424
- labels: ['Constructor', 'TypeScript'],
425
- primaryLabel: 'Constructor',
426
- indexed: ['name'],
427
- skipEmbedding: true,
428
- },
429
- },
430
- [CoreNodeType.EXPORT_DECLARATION]: {
431
- coreType: CoreNodeType.EXPORT_DECLARATION,
432
- astNodeKind: 273,
433
- properties: [
434
- {
435
- name: 'name',
436
- type: 'string',
437
- extraction: { method: 'static', defaultValue: 'export' },
438
- neo4j: { indexed: true, unique: false, required: true },
439
- },
440
- ],
441
- relationships: [],
442
- neo4j: {
443
- labels: ['Export', 'TypeScript'],
444
- primaryLabel: 'Export',
445
- indexed: ['name'],
446
- skipEmbedding: true,
447
- },
448
- },
449
- },
450
- edgeTypes: {
451
- [CoreEdgeType.CONTAINS]: {
452
- coreType: CoreEdgeType.CONTAINS,
453
- sourceTypes: [CoreNodeType.SOURCE_FILE, CoreNodeType.CLASS_DECLARATION],
454
- targetTypes: [
455
- CoreNodeType.CLASS_DECLARATION,
456
- CoreNodeType.INTERFACE_DECLARATION,
457
- CoreNodeType.FUNCTION_DECLARATION,
458
- CoreNodeType.METHOD_DECLARATION,
459
- CoreNodeType.PROPERTY_DECLARATION,
460
- ],
461
- properties: [
462
- {
463
- name: 'confidence',
464
- type: 'number',
465
- extraction: { method: 'static', defaultValue: 1.0 },
466
- neo4j: { indexed: true, unique: false, required: true },
467
- },
468
- {
469
- name: 'source',
470
- type: 'string',
471
- extraction: { method: 'static', defaultValue: 'ast' },
472
- neo4j: { indexed: true, unique: false, required: true },
473
- },
474
- ],
475
- neo4j: {
476
- relationshipType: 'CONTAINS',
477
- direction: 'OUTGOING',
478
- },
479
- },
480
- [CoreEdgeType.HAS_MEMBER]: {
481
- coreType: CoreEdgeType.HAS_MEMBER,
482
- sourceTypes: [CoreNodeType.CLASS_DECLARATION, CoreNodeType.INTERFACE_DECLARATION],
483
- targetTypes: [
484
- CoreNodeType.METHOD_DECLARATION,
485
- CoreNodeType.PROPERTY_DECLARATION,
486
- CoreNodeType.CONSTRUCTOR_DECLARATION,
487
- ],
488
- properties: [
489
- {
490
- name: 'confidence',
491
- type: 'number',
492
- extraction: { method: 'static', defaultValue: 1.0 },
493
- neo4j: { indexed: true, unique: false, required: true },
494
- },
495
- {
496
- name: 'source',
497
- type: 'string',
498
- extraction: { method: 'static', defaultValue: 'ast' },
499
- neo4j: { indexed: true, unique: false, required: true },
500
- },
501
- ],
502
- neo4j: {
503
- relationshipType: 'HAS_MEMBER',
504
- direction: 'OUTGOING',
505
- },
506
- },
507
- [CoreEdgeType.HAS_PARAMETER]: {
508
- coreType: CoreEdgeType.HAS_PARAMETER,
509
- sourceTypes: [
510
- CoreNodeType.METHOD_DECLARATION,
511
- CoreNodeType.FUNCTION_DECLARATION,
512
- CoreNodeType.CONSTRUCTOR_DECLARATION,
513
- ],
514
- targetTypes: [CoreNodeType.PARAMETER_DECLARATION],
515
- properties: [
516
- {
517
- name: 'confidence',
518
- type: 'number',
519
- extraction: { method: 'static', defaultValue: 1.0 },
520
- neo4j: { indexed: true, unique: false, required: true },
521
- },
522
- {
523
- name: 'source',
524
- type: 'string',
525
- extraction: { method: 'static', defaultValue: 'ast' },
526
- neo4j: { indexed: true, unique: false, required: true },
527
- },
528
- ],
529
- neo4j: {
530
- relationshipType: 'HAS_PARAMETER',
531
- direction: 'OUTGOING',
532
- },
533
- },
534
- [CoreEdgeType.DECORATED_WITH]: {
535
- coreType: CoreEdgeType.DECORATED_WITH,
536
- sourceTypes: [
537
- CoreNodeType.CLASS_DECLARATION,
538
- CoreNodeType.METHOD_DECLARATION,
539
- CoreNodeType.PROPERTY_DECLARATION,
540
- CoreNodeType.PARAMETER_DECLARATION,
541
- ],
542
- targetTypes: [CoreNodeType.DECORATOR],
543
- properties: [
544
- {
545
- name: 'confidence',
546
- type: 'number',
547
- extraction: { method: 'static', defaultValue: 1.0 },
548
- neo4j: { indexed: true, unique: false, required: true },
549
- },
550
- {
551
- name: 'source',
552
- type: 'string',
553
- extraction: { method: 'static', defaultValue: 'ast' },
554
- neo4j: { indexed: true, unique: false, required: true },
555
- },
556
- ],
557
- neo4j: {
558
- relationshipType: 'DECORATED_WITH',
559
- direction: 'OUTGOING',
560
- },
561
- },
562
- [CoreEdgeType.IMPORTS]: {
563
- coreType: CoreEdgeType.IMPORTS,
564
- sourceTypes: [CoreNodeType.SOURCE_FILE],
565
- targetTypes: [CoreNodeType.SOURCE_FILE],
566
- properties: [
567
- {
568
- name: 'confidence',
569
- type: 'number',
570
- extraction: { method: 'static', defaultValue: 1.0 },
571
- neo4j: { indexed: true, unique: false, required: true },
572
- },
573
- {
574
- name: 'source',
575
- type: 'string',
576
- extraction: { method: 'static', defaultValue: 'ast' },
577
- neo4j: { indexed: true, unique: false, required: true },
578
- },
579
- ],
580
- neo4j: {
581
- relationshipType: 'IMPORTS',
582
- direction: 'OUTGOING',
583
- },
584
- },
585
- [CoreEdgeType.EXPORTS]: {
586
- coreType: CoreEdgeType.EXPORTS,
587
- sourceTypes: [CoreNodeType.SOURCE_FILE],
588
- targetTypes: [
589
- CoreNodeType.CLASS_DECLARATION,
590
- CoreNodeType.INTERFACE_DECLARATION,
591
- CoreNodeType.FUNCTION_DECLARATION,
592
- ],
593
- properties: [
594
- {
595
- name: 'confidence',
596
- type: 'number',
597
- extraction: { method: 'static', defaultValue: 1.0 },
598
- neo4j: { indexed: true, unique: false, required: true },
599
- },
600
- {
601
- name: 'source',
602
- type: 'string',
603
- extraction: { method: 'static', defaultValue: 'ast' },
604
- neo4j: { indexed: true, unique: false, required: true },
605
- },
606
- ],
607
- neo4j: {
608
- relationshipType: 'EXPORTS',
609
- direction: 'OUTGOING',
610
- },
611
- },
612
- [CoreEdgeType.EXTENDS]: {
613
- coreType: CoreEdgeType.EXTENDS,
614
- sourceTypes: [CoreNodeType.CLASS_DECLARATION, CoreNodeType.INTERFACE_DECLARATION],
615
- targetTypes: [CoreNodeType.CLASS_DECLARATION, CoreNodeType.INTERFACE_DECLARATION],
616
- properties: [
617
- {
618
- name: 'confidence',
619
- type: 'number',
620
- extraction: { method: 'static', defaultValue: 1.0 },
621
- neo4j: { indexed: true, unique: false, required: true },
622
- },
623
- {
624
- name: 'source',
625
- type: 'string',
626
- extraction: { method: 'static', defaultValue: 'ast' },
627
- neo4j: { indexed: true, unique: false, required: true },
628
- },
629
- ],
630
- neo4j: {
631
- relationshipType: 'EXTENDS',
632
- direction: 'OUTGOING',
633
- },
634
- },
635
- [CoreEdgeType.IMPLEMENTS]: {
636
- coreType: CoreEdgeType.IMPLEMENTS,
637
- sourceTypes: [CoreNodeType.CLASS_DECLARATION],
638
- targetTypes: [CoreNodeType.INTERFACE_DECLARATION],
639
- properties: [
640
- {
641
- name: 'confidence',
642
- type: 'number',
643
- extraction: { method: 'static', defaultValue: 1.0 },
644
- neo4j: { indexed: true, unique: false, required: true },
645
- },
646
- {
647
- name: 'source',
648
- type: 'string',
649
- extraction: { method: 'static', defaultValue: 'ast' },
650
- neo4j: { indexed: true, unique: false, required: true },
651
- },
652
- ],
653
- neo4j: {
654
- relationshipType: 'IMPLEMENTS',
655
- direction: 'OUTGOING',
656
- },
657
- },
658
- [CoreEdgeType.TYPED_AS]: {
659
- coreType: CoreEdgeType.TYPED_AS,
660
- sourceTypes: [CoreNodeType.PARAMETER_DECLARATION, CoreNodeType.PROPERTY_DECLARATION],
661
- targetTypes: [CoreNodeType.CLASS_DECLARATION, CoreNodeType.INTERFACE_DECLARATION],
662
- properties: [
663
- {
664
- name: 'confidence',
665
- type: 'number',
666
- extraction: { method: 'static', defaultValue: 1.0 },
667
- neo4j: { indexed: true, unique: false, required: true },
668
- },
669
- {
670
- name: 'source',
671
- type: 'string',
672
- extraction: { method: 'static', defaultValue: 'ast' },
673
- neo4j: { indexed: true, unique: false, required: true },
674
- },
675
- ],
676
- neo4j: {
677
- relationshipType: 'TYPED_AS',
678
- direction: 'OUTGOING',
679
- },
680
- },
681
- [CoreEdgeType.CALLS]: {
682
- coreType: CoreEdgeType.CALLS,
683
- sourceTypes: [CoreNodeType.METHOD_DECLARATION, CoreNodeType.FUNCTION_DECLARATION],
684
- targetTypes: [CoreNodeType.METHOD_DECLARATION, CoreNodeType.FUNCTION_DECLARATION],
685
- properties: [
686
- {
687
- name: 'confidence',
688
- type: 'number',
689
- extraction: { method: 'static', defaultValue: 0.8 },
690
- neo4j: { indexed: true, unique: false, required: true },
691
- },
692
- {
693
- name: 'source',
694
- type: 'string',
695
- extraction: { method: 'static', defaultValue: 'pattern' },
696
- neo4j: { indexed: true, unique: false, required: true },
697
- },
698
- ],
699
- neo4j: {
700
- relationshipType: 'CALLS',
701
- direction: 'OUTGOING',
702
- },
703
- },
704
- },
705
- };
706
- // ============================================================================
707
- // NESTJS FRAMEWORK SCHEMA
708
- // ============================================================================
709
- export const NESTJS_FRAMEWORK_SCHEMA = {
710
- name: 'NestJS Framework Schema',
711
- version: '2.0.0',
712
- description: 'NestJS-specific enhancements with context-based properties',
713
- enhances: [CoreNodeType.CLASS_DECLARATION, CoreNodeType.METHOD_DECLARATION],
714
- enhancements: {
715
- NestController: {
716
- name: 'NestController',
717
- targetCoreType: CoreNodeType.CLASS_DECLARATION,
718
- semanticType: SemanticNodeType.NEST_CONTROLLER,
719
- detectionPatterns: [
720
- {
721
- type: 'decorator',
722
- pattern: 'Controller',
723
- confidence: 0.95,
724
- priority: 10,
725
- },
726
- {
727
- type: 'filename',
728
- pattern: /\.controller\.ts$/,
729
- confidence: 0.7,
730
- priority: 5,
731
- },
732
- ],
733
- contextExtractors: [
734
- {
735
- nodeType: CoreNodeType.CLASS_DECLARATION,
736
- semanticType: SemanticNodeType.NEST_CONTROLLER,
737
- extractor: (parsedNode) => {
738
- const node = parsedNode.sourceNode;
739
- if (!node)
740
- return {};
741
- return {
742
- basePath: extractControllerPath(node),
743
- endpointCount: countHttpEndpoints(node),
744
- hasGlobalGuards: hasDecorator(node, 'UseGuards'),
745
- hasGlobalPipes: hasDecorator(node, 'UsePipes'),
746
- hasGlobalInterceptors: hasDecorator(node, 'UseInterceptors'),
747
- version: extractVersion(node),
748
- };
749
- },
750
- priority: 1,
751
- },
752
- ],
753
- additionalRelationships: [SemanticEdgeType.EXPOSES, SemanticEdgeType.INJECTS],
754
- neo4j: {
755
- additionalLabels: ['Controller', 'NestJS'],
756
- primaryLabel: 'Controller',
757
- },
758
- priority: 90,
759
- },
760
- NestService: {
761
- name: 'NestService',
762
- targetCoreType: CoreNodeType.CLASS_DECLARATION,
763
- semanticType: SemanticNodeType.NEST_SERVICE,
764
- detectionPatterns: [
765
- {
766
- type: 'filename',
767
- pattern: /\.service\.ts$/,
768
- confidence: 0.9,
769
- priority: 9,
770
- },
771
- {
772
- type: 'function',
773
- pattern: (node) => node.getName()?.endsWith('Service'),
774
- confidence: 0.7,
775
- priority: 7,
776
- },
777
- ],
778
- contextExtractors: [
779
- {
780
- nodeType: CoreNodeType.CLASS_DECLARATION,
781
- semanticType: SemanticNodeType.NEST_SERVICE,
782
- extractor: (parsedNode) => {
783
- const node = parsedNode.sourceNode;
784
- if (!node)
785
- return {};
786
- return {
787
- scope: extractScope(node),
788
- isAsync: hasAsyncMethods(node),
789
- dependencyCount: countConstructorParameters(node),
790
- injectionToken: extractInjectionToken(node),
791
- };
792
- },
793
- priority: 1,
794
- },
795
- ],
796
- additionalRelationships: [SemanticEdgeType.PROVIDED_BY, SemanticEdgeType.MANAGES],
797
- neo4j: {
798
- additionalLabels: ['Service', 'NestJS'],
799
- primaryLabel: 'Service',
800
- },
801
- priority: 80,
802
- },
803
- NestModule: {
804
- name: 'NestModule',
805
- targetCoreType: CoreNodeType.CLASS_DECLARATION,
806
- semanticType: SemanticNodeType.NEST_MODULE,
807
- detectionPatterns: [
808
- {
809
- type: 'decorator',
810
- pattern: 'Module',
811
- confidence: 0.95,
812
- priority: 10,
813
- },
814
- {
815
- type: 'filename',
816
- pattern: /\.module\.ts$/,
817
- confidence: 0.8,
818
- priority: 7,
819
- },
820
- ],
821
- contextExtractors: [
822
- {
823
- nodeType: CoreNodeType.CLASS_DECLARATION,
824
- semanticType: SemanticNodeType.NEST_MODULE,
825
- extractor: (parsedNode) => {
826
- const node = parsedNode.sourceNode;
827
- if (!node)
828
- return {};
829
- return {
830
- isGlobal: hasDecorator(node, 'Global'),
831
- isDynamic: hasDynamicMethods(node),
832
- imports: extractModuleImports(node),
833
- providers: extractModuleProviders(node),
834
- controllers: extractModuleControllers(node),
835
- exports: extractModuleExports(node),
836
- };
837
- },
838
- priority: 1,
839
- },
840
- ],
841
- additionalRelationships: [SemanticEdgeType.MODULE_IMPORTS, SemanticEdgeType.MODULE_PROVIDES],
842
- neo4j: {
843
- additionalLabels: ['Module', 'NestJS'],
844
- primaryLabel: 'Module',
845
- },
846
- priority: 95,
847
- },
848
- MessageHandler: {
849
- name: 'MessageHandler',
850
- targetCoreType: CoreNodeType.METHOD_DECLARATION,
851
- semanticType: SemanticNodeType.MESSAGE_HANDLER,
852
- detectionPatterns: [
853
- {
854
- type: 'function',
855
- pattern: (node) => {
856
- const decorators = node.getDecorators?.() ?? [];
857
- const messageDecorators = ['MessagePattern', 'EventPattern'];
858
- return decorators.some((d) => messageDecorators.includes(d.getName()));
859
- },
860
- confidence: 0.98,
861
- priority: 15,
862
- },
863
- ],
864
- contextExtractors: [
865
- {
866
- nodeType: CoreNodeType.METHOD_DECLARATION,
867
- semanticType: SemanticNodeType.MESSAGE_HANDLER,
868
- extractor: (parsedNode) => {
869
- const node = parsedNode.sourceNode;
870
- if (!node)
871
- return {};
872
- return {
873
- messageQueueName: extractMessagePattern(node),
874
- isAsync: node.isAsync(),
875
- returnType: node.getReturnTypeNode()?.getText() ?? 'void',
876
- pattern: getPatternType(node),
877
- hasAuth: hasAuthDecorators(node),
878
- hasValidation: hasValidationDecorators(node),
879
- guardNames: extractGuardNames(node),
880
- pipeNames: extractPipeNames(node),
881
- interceptorNames: extractInterceptorNames(node),
882
- endpointType: 'RPC',
883
- };
884
- },
885
- priority: 1,
886
- },
887
- ],
888
- additionalRelationships: [
889
- SemanticEdgeType.CONSUMES_MESSAGE,
890
- SemanticEdgeType.RESPONDS_WITH,
891
- SemanticEdgeType.GUARDED_BY,
892
- ],
893
- neo4j: {
894
- additionalLabels: ['MessageHandler', 'NestJS', 'Microservice'],
895
- primaryLabel: 'MessageHandler',
896
- },
897
- priority: 88,
898
- },
899
- HttpEndpoint: {
900
- name: 'HttpEndpoint',
901
- targetCoreType: CoreNodeType.METHOD_DECLARATION,
902
- semanticType: SemanticNodeType.HTTP_ENDPOINT,
903
- detectionPatterns: [
904
- {
905
- type: 'function',
906
- pattern: (node) => {
907
- const decorators = node.getDecorators?.() ?? [];
908
- const httpDecorators = ['Get', 'Post', 'Put', 'Delete', 'Patch', 'Head', 'Options'];
909
- return decorators.some((d) => httpDecorators.includes(d.getName()));
910
- },
911
- confidence: 0.98,
912
- priority: 15,
913
- },
914
- ],
915
- contextExtractors: [
916
- {
917
- nodeType: CoreNodeType.METHOD_DECLARATION,
918
- semanticType: SemanticNodeType.HTTP_ENDPOINT,
919
- extractor: (parsedNode) => {
920
- const node = parsedNode.sourceNode;
921
- if (!node)
922
- return {};
923
- return {
924
- httpMethod: extractHttpMethod(node),
925
- path: extractRoutePath(node),
926
- fullPath: computeFullPath(node),
927
- statusCode: extractStatusCode(node),
928
- hasAuth: hasAuthDecorators(node),
929
- hasValidation: hasValidationDecorators(node),
930
- guardNames: extractGuardNames(node),
931
- pipeNames: extractPipeNames(node),
932
- interceptorNames: extractInterceptorNames(node),
933
- };
934
- },
935
- priority: 1,
936
- },
937
- ],
938
- additionalRelationships: [SemanticEdgeType.ACCEPTS, SemanticEdgeType.RESPONDS_WITH, SemanticEdgeType.GUARDED_BY],
939
- neo4j: {
940
- additionalLabels: ['HttpEndpoint', 'NestJS'],
941
- primaryLabel: 'HttpEndpoint',
942
- },
943
- priority: 85,
944
- },
945
- EntityClass: {
946
- name: 'EntityClass',
947
- targetCoreType: CoreNodeType.CLASS_DECLARATION,
948
- semanticType: SemanticNodeType.ENTITY_CLASS,
949
- detectionPatterns: [
950
- {
951
- type: 'decorator',
952
- pattern: 'Entity',
953
- confidence: 0.95,
954
- priority: 10,
955
- },
956
- {
957
- type: 'filename',
958
- pattern: /\.entity\.ts$/,
959
- confidence: 0.8,
960
- priority: 7,
961
- },
962
- ],
963
- contextExtractors: [
964
- {
965
- nodeType: CoreNodeType.CLASS_DECLARATION,
966
- semanticType: SemanticNodeType.ENTITY_CLASS,
967
- extractor: (parsedNode) => {
968
- const node = parsedNode.sourceNode;
969
- if (!node)
970
- return {};
971
- return {
972
- tableName: extractTableName(node),
973
- columnCount: countColumns(node),
974
- hasRelations: hasRelationDecorators(node),
975
- };
976
- },
977
- priority: 1,
978
- },
979
- ],
980
- additionalRelationships: [],
981
- neo4j: {
982
- additionalLabels: ['Entity', 'NestJS'],
983
- primaryLabel: 'Entity',
984
- },
985
- priority: 80,
986
- },
987
- DTOClass: {
988
- name: 'DTOClass',
989
- targetCoreType: CoreNodeType.CLASS_DECLARATION,
990
- semanticType: SemanticNodeType.DTO_CLASS,
991
- detectionPatterns: [
992
- {
993
- type: 'filename',
994
- pattern: /\.dto\.ts$/,
995
- confidence: 0.9,
996
- priority: 8,
997
- },
998
- {
999
- type: 'classname',
1000
- pattern: /.*Dto$/,
1001
- confidence: 0.7,
1002
- priority: 6,
1003
- },
1004
- ],
1005
- contextExtractors: [
1006
- {
1007
- nodeType: CoreNodeType.CLASS_DECLARATION,
1008
- semanticType: SemanticNodeType.DTO_CLASS,
1009
- extractor: (parsedNode) => {
1010
- const node = parsedNode.sourceNode;
1011
- if (!node)
1012
- return {};
1013
- return {
1014
- validationDecorators: extractValidationDecorators(node),
1015
- isRequestDto: node.getName()?.toLowerCase().includes('request') ?? false,
1016
- isResponseDto: node.getName()?.toLowerCase().includes('response') || false,
1017
- isPartialDto: extendsPartialType(node),
1018
- baseClass: extractBaseClass(node),
1019
- };
1020
- },
1021
- priority: 1,
1022
- },
1023
- ],
1024
- additionalRelationships: [SemanticEdgeType.VALIDATES],
1025
- neo4j: {
1026
- additionalLabels: ['DTO', 'NestJS'],
1027
- primaryLabel: 'DTO',
1028
- },
1029
- priority: 70,
1030
- },
1031
- },
1032
- edgeEnhancements: {
1033
- DependencyInjection: {
1034
- name: 'DependencyInjection',
1035
- semanticType: SemanticEdgeType.INJECTS,
1036
- detectionPattern: (parsedSourceNode, parsedTargetNode) => {
1037
- return detectDependencyInjection(parsedSourceNode, parsedTargetNode);
1038
- },
1039
- contextExtractor: (parsedSourceNode, parsedTargetNode) => ({
1040
- injectionType: 'constructor',
1041
- injectionToken: extractInjectionTokenFromRelation(parsedSourceNode, parsedTargetNode),
1042
- parameterIndex: findParameterIndex(parsedSourceNode, parsedTargetNode),
1043
- }),
1044
- neo4j: {
1045
- relationshipType: 'INJECTS',
1046
- direction: 'OUTGOING',
1047
- },
1048
- },
1049
- MessageHandlerExposure: {
1050
- name: 'MessageHandlerExposure',
1051
- semanticType: SemanticEdgeType.EXPOSES,
1052
- detectionPattern: (parsedSourceNode, parsedTargetNode) => {
1053
- if (parsedSourceNode.properties?.semanticType !== SemanticNodeType.NEST_CONTROLLER ||
1054
- parsedTargetNode.properties?.semanticType !== SemanticNodeType.MESSAGE_HANDLER) {
1055
- return false;
1056
- }
1057
- if (parsedSourceNode.properties?.filePath !== parsedTargetNode.properties?.filePath) {
1058
- return false;
1059
- }
1060
- // Access AST nodes to check parent relationship
1061
- const sourceNode = parsedSourceNode.sourceNode;
1062
- const targetNode = parsedTargetNode.sourceNode;
1063
- if (sourceNode && targetNode) {
1064
- const methodParent = targetNode.getParent();
1065
- if (methodParent === sourceNode) {
1066
- return true;
1067
- }
1068
- }
1069
- return false;
1070
- },
1071
- contextExtractor: (parsedSourceNode, parsedTargetNode) => ({
1072
- endpointType: 'RPC',
1073
- }),
1074
- neo4j: {
1075
- relationshipType: 'EXPOSES',
1076
- direction: 'OUTGOING',
1077
- },
1078
- },
1079
- HttpEndpointExposure: {
1080
- name: 'HttpEndpointExposure',
1081
- semanticType: SemanticEdgeType.EXPOSES,
1082
- detectionPattern: (parsedSourceNode, parsedTargetNode) => {
1083
- // Check if source is controller and target is HTTP endpoint
1084
- if (parsedSourceNode.properties?.semanticType !== SemanticNodeType.NEST_CONTROLLER ||
1085
- parsedTargetNode.properties?.semanticType !== SemanticNodeType.HTTP_ENDPOINT) {
1086
- return false;
1087
- }
1088
- if (parsedSourceNode.properties?.filePath !== parsedTargetNode.properties?.filePath) {
1089
- return false;
1090
- }
1091
- // Access AST nodes to check parent relationship
1092
- const sourceNode = parsedSourceNode.sourceNode;
1093
- const targetNode = parsedTargetNode.sourceNode;
1094
- if (sourceNode && targetNode) {
1095
- const methodParent = targetNode.getParent();
1096
- if (methodParent === sourceNode) {
1097
- return true;
1098
- }
1099
- }
1100
- return false;
1101
- },
1102
- contextExtractor: (parsedSourceNode, parsedTargetNode) => ({
1103
- httpMethod: parsedTargetNode.properties?.context?.httpMethod ?? '',
1104
- fullPath: computeFullPathFromNodes(parsedSourceNode, parsedTargetNode),
1105
- statusCode: parsedTargetNode.properties?.context?.statusCode ?? 200,
1106
- }),
1107
- neo4j: {
1108
- relationshipType: 'EXPOSES',
1109
- direction: 'OUTGOING',
1110
- },
1111
- },
1112
- },
1113
- contextExtractors: [
1114
- {
1115
- nodeType: CoreNodeType.SOURCE_FILE,
1116
- extractor: (parsedNode) => {
1117
- const node = parsedNode.sourceNode;
1118
- if (!node)
1119
- return {};
1120
- return {
1121
- extension: node.getFilePath().substring(node.getFilePath().lastIndexOf('.')),
1122
- relativePath: extractRelativePath(node),
1123
- isTestFile: /\.(test|spec)\./.test(node.getFilePath()),
1124
- isDeclarationFile: node.getFilePath().endsWith('.d.ts'),
1125
- moduleKind: 'ES6',
1126
- importCount: node.getImportDeclarations().length,
1127
- exportCount: node.getExportDeclarations().length,
1128
- declarationCount: countDeclarations({ node }),
1129
- };
1130
- },
1131
- priority: 1,
1132
- },
1133
- {
1134
- nodeType: CoreNodeType.CLASS_DECLARATION,
1135
- extractor: (parsedNode) => {
1136
- const node = parsedNode.sourceNode;
1137
- if (!node)
1138
- return {};
1139
- return {
1140
- isAbstract: node.getAbstractKeyword() != null,
1141
- isDefaultExport: node.isDefaultExport(),
1142
- extendsClause: node.getExtends()?.getText(),
1143
- implementsClauses: node.getImplements().map((i) => i.getText()),
1144
- decoratorNames: node.getDecorators().map((d) => d.getName()),
1145
- methodCount: node.getMethods().length,
1146
- propertyCount: node.getProperties().length,
1147
- constructorParameterCount: countConstructorParameters(node),
1148
- };
1149
- },
1150
- priority: 1,
1151
- },
1152
- {
1153
- nodeType: CoreNodeType.METHOD_DECLARATION,
1154
- extractor: (parsedNode) => {
1155
- const node = parsedNode.sourceNode;
1156
- if (!node)
1157
- return {};
1158
- return {
1159
- isStatic: node.isStatic(),
1160
- isAsync: node.isAsync(),
1161
- isAbstract: node.isAbstract(),
1162
- returnType: node.getReturnTypeNode()?.getText() || 'void',
1163
- parameterCount: node.getParameters().length,
1164
- decoratorNames: node.getDecorators().map((d) => d.getName()),
1165
- isGetter: node.getKind() === 177,
1166
- isSetter: node.getKind() === 178,
1167
- overloadCount: 1, // Simplified
1168
- };
1169
- },
1170
- priority: 1,
1171
- },
1172
- {
1173
- nodeType: CoreNodeType.PROPERTY_DECLARATION,
1174
- extractor: (parsedNode) => {
1175
- const node = parsedNode.sourceNode;
1176
- if (!node)
1177
- return {};
1178
- return {
1179
- isStatic: node.isStatic(),
1180
- isReadonly: node.isReadonly(),
1181
- type: node.getTypeNode()?.getText() || 'any',
1182
- hasInitializer: node.hasInitializer(),
1183
- decoratorNames: node.getDecorators().map((d) => d.getName()),
1184
- isOptional: node.hasQuestionToken(),
1185
- };
1186
- },
1187
- priority: 1,
1188
- },
1189
- {
1190
- nodeType: CoreNodeType.PARAMETER_DECLARATION,
1191
- extractor: (parsedNode) => {
1192
- const node = parsedNode.sourceNode;
1193
- if (!node)
1194
- return {};
1195
- return {
1196
- type: node.getTypeNode()?.getText() || 'any',
1197
- isOptional: node.hasQuestionToken(),
1198
- isRestParameter: node.isRestParameter(),
1199
- hasDefaultValue: node.hasInitializer(),
1200
- decoratorNames: node.getDecorators().map((d) => d.getName()),
1201
- parameterIndex: node.getChildIndex(),
1202
- };
1203
- },
1204
- priority: 1,
1205
- },
1206
- {
1207
- nodeType: CoreNodeType.IMPORT_DECLARATION,
1208
- extractor: (parsedNode) => {
1209
- const node = parsedNode.sourceNode;
1210
- if (!node)
1211
- return {};
1212
- return {
1213
- moduleSpecifier: node.getModuleSpecifierValue(),
1214
- isTypeOnly: node.isTypeOnly(),
1215
- importKind: determineImportKind(node),
1216
- namedImports: node.getNamedImports().map((ni) => ni.getName()),
1217
- defaultImport: node.getDefaultImport()?.getText() || null,
1218
- namespaceImport: node.getNamespaceImport()?.getText() || null,
1219
- };
1220
- },
1221
- priority: 1,
1222
- },
1223
- {
1224
- nodeType: CoreNodeType.DECORATOR,
1225
- extractor: (parsedNode) => {
1226
- const node = parsedNode.sourceNode;
1227
- if (!node)
1228
- return {};
1229
- return {
1230
- arguments: node.getArguments().map((arg) => arg.getText()),
1231
- target: determineDecoratorTarget(node),
1232
- };
1233
- },
1234
- priority: 1,
1235
- },
1236
- ],
1237
- metadata: {
1238
- targetLanguages: ['typescript'],
1239
- dependencies: ['@nestjs/core', '@nestjs/common'],
1240
- },
1241
- };
1242
- // ============================================================================
1243
- // HELPER FUNCTIONS
1244
- // ============================================================================
1245
- function extractMessagePattern(node) {
1246
- // Check for @EventPattern first
1247
- let decorator = node.getDecorator('EventPattern');
1248
- // Check for @MessagePattern
1249
- decorator ??= node.getDecorator('MessagePattern');
1250
- if (!decorator)
1251
- return '';
1252
- const args = decorator.getArguments();
1253
- if (args.length === 0)
1254
- return '';
1255
- // Get the raw text of the first argument
1256
- const rawPattern = args[0].getText();
1257
- return rawPattern;
1258
- }
1259
- function getPatternType(node) {
1260
- if (node.getDecorator('EventPattern'))
1261
- return 'event';
1262
- if (node.getDecorator('MessagePattern'))
1263
- return 'message';
1264
- return 'event'; // default
1265
- }
1266
- function extractControllerPath(node) {
1267
- const decorator = node.getDecorator('Controller');
1268
- if (!decorator)
1269
- return '';
1270
- const args = decorator.getArguments();
1271
- return args.length > 0 ? `/${args[0].getText().replace(/['"]/g, '')}` : '';
1272
- }
1273
- function countHttpEndpoints(node) {
1274
- const methods = node.getMethods();
1275
- const httpDecorators = ['Get', 'Post', 'Put', 'Delete', 'Patch', 'Head', 'Options'];
1276
- return methods.filter((method) => {
1277
- const decorators = method.getDecorators();
1278
- return decorators.some((d) => httpDecorators.includes(d.getName()));
1279
- }).length;
1280
- }
1281
- function hasDecorator(node, decoratorName) {
1282
- const decorators = node.getDecorators();
1283
- return decorators.some((d) => d.getName() === decoratorName);
1284
- }
1285
- function extractVersion(node) {
1286
- const decorator = node.getDecorator('Version');
1287
- if (!decorator)
1288
- return null;
1289
- const args = decorator.getArguments();
1290
- return args.length > 0 ? args[0].getText().replace(/['"]/g, '') : null;
1291
- }
1292
- function extractScope(node) {
1293
- const decorator = node.getDecorator('Injectable');
1294
- if (!decorator)
1295
- return 'DEFAULT';
1296
- const args = decorator.getArguments();
1297
- if (args.length === 0)
1298
- return 'DEFAULT';
1299
- const argText = args[0].getText();
1300
- if (argText.includes('REQUEST'))
1301
- return 'REQUEST';
1302
- if (argText.includes('TRANSIENT'))
1303
- return 'TRANSIENT';
1304
- return 'DEFAULT';
1305
- }
1306
- function hasAsyncMethods(node) {
1307
- const methods = node.getMethods();
1308
- return methods.some((method) => method.isAsync?.());
1309
- }
1310
- function countConstructorParameters(node) {
1311
- const constructors = node.getConstructors();
1312
- return constructors.length > 0 ? constructors[0].getParameters().length : 0;
1313
- }
1314
- function extractInjectionToken(node) {
1315
- const decorator = node.getDecorator('Injectable');
1316
- if (!decorator)
1317
- return null;
1318
- const args = decorator.getArguments();
1319
- if (args.length > 0 && args[0].getText().startsWith("'")) {
1320
- return args[0].getText().replace(/['"]/g, '');
1321
- }
1322
- return null;
1323
- }
1324
- function hasDynamicMethods(node) {
1325
- const methods = node.getMethods();
1326
- const dynamicMethods = ['forRoot', 'forFeature', 'forRootAsync', 'forFeatureAsync'];
1327
- return methods.some((method) => {
1328
- return method.isStatic?.() && dynamicMethods.includes(method.getName());
1329
- });
1330
- }
1331
- function extractModuleImports(node) {
1332
- return extractModuleArrayProperty(node, 'imports');
1333
- }
1334
- function extractModuleProviders(node) {
1335
- return extractModuleArrayProperty(node, 'providers');
1336
- }
1337
- function extractModuleControllers(node) {
1338
- return extractModuleArrayProperty(node, 'controllers');
1339
- }
1340
- function extractModuleExports(node) {
1341
- return extractModuleArrayProperty(node, 'exports');
1342
- }
1343
- function extractModuleArrayProperty(node, propertyName) {
1344
- const decorator = node.getDecorator('Module');
1345
- if (!decorator)
1346
- return [];
1347
- const args = decorator.getArguments();
1348
- if (args.length === 0)
1349
- return [];
1350
- const configText = args[0].getText();
1351
- const regex = new RegExp(`${propertyName}\\s*:\\s*\\[([^\\]]+)\\]`);
1352
- const match = configText.match(regex);
1353
- if (!match)
1354
- return [];
1355
- return match[1]
1356
- .split(',')
1357
- .map((item) => item.trim().replace(/['"]/g, ''))
1358
- .filter((item) => item.length > 0);
1359
- }
1360
- function extractHttpMethod(node) {
1361
- const decorators = node.getDecorators();
1362
- const httpDecorators = ['Get', 'Post', 'Put', 'Delete', 'Patch', 'Head', 'Options'];
1363
- const httpDecorator = decorators.find((d) => httpDecorators.includes(d.getName()));
1364
- return httpDecorator ? httpDecorator.getName().toUpperCase() : '';
1365
- }
1366
- function extractRoutePath(node) {
1367
- const decorators = node.getDecorators();
1368
- const httpDecorators = ['Get', 'Post', 'Put', 'Delete', 'Patch', 'Head', 'Options'];
1369
- const httpDecorator = decorators.find((d) => httpDecorators.includes(d.getName()));
1370
- if (!httpDecorator)
1371
- return '';
1372
- const args = httpDecorator.getArguments();
1373
- return args.length > 0 ? args[0].getText().replace(/['"]/g, '') : '';
1374
- }
1375
- function computeFullPath(node) {
1376
- const methodPath = extractRoutePath(node);
1377
- // Get the parent controller's base path
1378
- const parentClass = node.getParent();
1379
- const controllerPath = extractControllerPath(parentClass);
1380
- // Combine paths properly
1381
- const fullPath = `${controllerPath}/${methodPath}`.replace(/\/+/g, '/').replace(/\/$/, '') || '/';
1382
- return fullPath;
1383
- }
1384
- function extractStatusCode(node) {
1385
- const decorator = node.getDecorator('HttpCode');
1386
- if (!decorator)
1387
- return null;
1388
- const args = decorator.getArguments();
1389
- if (args.length > 0) {
1390
- const status = parseInt(args[0].getText());
1391
- return isNaN(status) ? null : status;
1392
- }
1393
- return null;
1394
- }
1395
- function hasAuthDecorators(node) {
1396
- const decorators = node.getDecorators();
1397
- const authDecorators = ['UseGuards', 'Auth', 'Roles', 'Public'];
1398
- return decorators.some((d) => authDecorators.includes(d.getName()));
1399
- }
1400
- function hasValidationDecorators(node) {
1401
- const decorators = node.getDecorators();
1402
- const validationDecorators = ['UsePipes', 'ValidationPipe'];
1403
- return decorators.some((d) => validationDecorators.includes(d.getName()));
1404
- }
1405
- function extractGuardNames(node) {
1406
- return extractDecoratorArguments(node, 'UseGuards');
1407
- }
1408
- function extractPipeNames(node) {
1409
- return extractDecoratorArguments(node, 'UsePipes');
1410
- }
1411
- function extractInterceptorNames(node) {
1412
- return extractDecoratorArguments(node, 'UseInterceptors');
1413
- }
1414
- function extractDecoratorArguments(node, decoratorName) {
1415
- const decorator = node.getDecorator(decoratorName);
1416
- if (!decorator)
1417
- return [];
1418
- const args = decorator.getArguments();
1419
- return args.map((arg) => arg.getText().replace(/[(),]/g, '').trim()).filter((name) => name.length > 0);
1420
- }
1421
- function extractTableName(node) {
1422
- const decorator = node.getDecorator('Entity');
1423
- if (!decorator)
1424
- return null;
1425
- const args = decorator.getArguments();
1426
- return args.length > 0 ? args[0].getText().replace(/['"]/g, '') : null;
1427
- }
1428
- function countColumns(node) {
1429
- const properties = node.getProperties();
1430
- return properties.filter((prop) => {
1431
- const decorators = prop.getDecorators();
1432
- return decorators.some((d) => ['Column', 'PrimaryGeneratedColumn'].includes(d.getName()));
1433
- }).length;
1434
- }
1435
- function hasRelationDecorators(node) {
1436
- const properties = node.getProperties();
1437
- const relationDecorators = ['OneToOne', 'OneToMany', 'ManyToOne', 'ManyToMany'];
1438
- return properties.some((prop) => {
1439
- const decorators = prop.getDecorators();
1440
- return decorators.some((d) => relationDecorators.includes(d.getName()));
1441
- });
1442
- }
1443
- function extractValidationDecorators(node) {
1444
- const properties = node.getProperties();
1445
- const validationDecorators = [];
1446
- const commonValidators = [
1447
- 'IsString',
1448
- 'IsNumber',
1449
- 'IsEmail',
1450
- 'IsOptional',
1451
- 'IsNotEmpty',
1452
- 'MinLength',
1453
- 'MaxLength',
1454
- 'IsArray',
1455
- 'IsBoolean',
1456
- 'IsDate',
1457
- 'IsEnum',
1458
- 'IsUUID',
1459
- 'IsUrl',
1460
- 'Min',
1461
- 'Max',
1462
- 'Matches',
1463
- 'IsIn',
1464
- 'IsNotIn',
1465
- 'IsDefined',
1466
- 'ValidateNested',
1467
- ];
1468
- properties.forEach((prop) => {
1469
- const decorators = prop.getDecorators();
1470
- decorators.forEach((decorator) => {
1471
- const name = decorator.getName();
1472
- if (commonValidators.includes(name)) {
1473
- validationDecorators.push(name);
1474
- }
1475
- });
1476
- });
1477
- return [...new Set(validationDecorators)];
1478
- }
1479
- function extendsPartialType(node) {
1480
- const baseClass = node.getBaseClass();
1481
- return baseClass ? baseClass.getText().includes('PartialType') : false;
1482
- }
1483
- function extractBaseClass(node) {
1484
- const baseClass = node.getBaseClass();
1485
- return baseClass ? baseClass.getText() : null;
1486
- }
1487
- function detectDependencyInjection(sourceNode, targetNode) {
1488
- if (sourceNode.properties?.coreType !== CoreNodeType.CLASS_DECLARATION)
1489
- return false;
1490
- if (targetNode.properties?.coreType !== CoreNodeType.CLASS_DECLARATION)
1491
- return false;
1492
- const constructors = sourceNode.sourceNode?.getConstructors();
1493
- if (!constructors || constructors.length === 0)
1494
- return false;
1495
- const constructor = constructors[0];
1496
- const parameters = constructor.getParameters();
1497
- const targetName = targetNode.properties?.name;
1498
- return parameters.some((param) => {
1499
- const paramType = param.getTypeNode()?.getText();
1500
- if (paramType === targetName)
1501
- return true;
1502
- const decorators = param.getDecorators();
1503
- return decorators.some((decorator) => {
1504
- if (decorator.getName() === 'Inject') {
1505
- const args = decorator.getArguments();
1506
- if (args.length > 0) {
1507
- const token = args[0].getText().replace(/['"]/g, '');
1508
- return token === targetName;
1509
- }
1510
- }
1511
- return false;
1512
- });
1513
- });
1514
- }
1515
- function extractInjectionTokenFromRelation(sourceNode, targetNode) {
1516
- const constructors = sourceNode.sourceNode?.getConstructors();
1517
- if (!constructors || constructors.length === 0)
1518
- return null;
1519
- const constructor = constructors[0];
1520
- const parameters = constructor.getParameters();
1521
- for (const param of parameters) {
1522
- const decorators = param.getDecorators();
1523
- for (const decorator of decorators) {
1524
- if (decorator.getName() === 'Inject') {
1525
- const args = decorator.getArguments();
1526
- if (args.length > 0) {
1527
- return args[0].getText().replace(/['"]/g, '');
1528
- }
1529
- }
1530
- }
1531
- }
1532
- return null;
1533
- }
1534
- function findParameterIndex(sourceNode, targetNode) {
1535
- const constructors = sourceNode.sourceNode?.getConstructors();
1536
- if (!constructors || constructors.length === 0)
1537
- return 0;
1538
- const constructor = constructors[0];
1539
- const parameters = constructor.getParameters();
1540
- const targetName = targetNode.properties?.name;
1541
- return parameters.findIndex((param) => {
1542
- const paramType = param.getTypeNode()?.getText();
1543
- return paramType === targetName;
1544
- });
1545
- }
1546
- function computeFullPathFromNodes(sourceNode, targetNode) {
1547
- const basePath = sourceNode.properties?.context?.basePath ?? '';
1548
- const methodPath = targetNode.properties?.context?.path ?? '';
1549
- // Properly combine paths
1550
- const fullPath = `${basePath}/${methodPath}`.replace(/\/+/g, '/').replace(/\/$/, '') || '/';
1551
- return fullPath;
1552
- }
1553
- function extractRelativePath(node) {
1554
- const filePath = node.getFilePath();
1555
- const parts = filePath.split('/');
1556
- return parts.slice(-3).join('/');
1557
- }
1558
- function countDeclarations({ node }) {
1559
- return node.getClasses().length + node.getInterfaces().length + node.getFunctions().length + node.getEnums().length;
1560
- }
1561
- function determineImportKind(node) {
1562
- if (node.getDefaultImport())
1563
- return 'default';
1564
- if (node.getNamespaceImport())
1565
- return 'namespace';
1566
- if (node.getNamedImports().length > 0)
1567
- return 'named';
1568
- return 'side-effect';
1569
- }
1570
- function determineDecoratorTarget(node) {
1571
- const parent = node.getParent();
1572
- if (!parent)
1573
- return 'unknown';
1574
- const kind = parent.getKind();
1575
- if (kind === 262)
1576
- return 'class'; // ClassDeclaration
1577
- if (kind === 172)
1578
- return 'method'; // MethodDeclaration
1579
- if (kind === 171)
1580
- return 'property'; // PropertyDeclaration
1581
- if (kind === 169)
1582
- return 'parameter'; // Parameter
1583
- return 'unknown';
1584
- }
1585
- export const DEFAULT_PARSE_OPTIONS = {
1586
- includePatterns: ['**/*.ts', '**/*.tsx'],
1587
- excludePatterns: ['node_modules/', 'dist/', 'coverage/', '.d.ts', '.spec.ts', '.test.ts'],
1588
- maxFiles: 1000,
1589
- coreSchema: CORE_TYPESCRIPT_SCHEMA,
1590
- frameworkSchemas: [],
1591
- };
1592
- export const NESTJS_PARSE_OPTIONS = {
1593
- ...DEFAULT_PARSE_OPTIONS,
1594
- frameworkSchemas: [NESTJS_FRAMEWORK_SCHEMA],
1595
- };