gitnexus 1.4.8 → 1.4.9
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/README.md +7 -0
- package/dist/cli/index-repo.d.ts +15 -0
- package/dist/cli/index-repo.js +115 -0
- package/dist/cli/index.js +11 -2
- package/dist/cli/setup.js +12 -9
- package/dist/cli/wiki.d.ts +4 -0
- package/dist/cli/wiki.js +174 -53
- package/dist/config/supported-languages.d.ts +7 -5
- package/dist/config/supported-languages.js +6 -4
- package/dist/core/graph/graph.js +9 -1
- package/dist/core/graph/types.d.ts +10 -2
- package/dist/core/ingestion/call-processor.d.ts +18 -1
- package/dist/core/ingestion/call-processor.js +297 -38
- package/dist/core/ingestion/call-routing.d.ts +3 -18
- package/dist/core/ingestion/call-routing.js +0 -19
- package/dist/core/ingestion/cobol/cobol-copy-expander.d.ts +57 -0
- package/dist/core/ingestion/cobol/cobol-copy-expander.js +385 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +210 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.js +1509 -0
- package/dist/core/ingestion/cobol/jcl-parser.d.ts +68 -0
- package/dist/core/ingestion/cobol/jcl-parser.js +217 -0
- package/dist/core/ingestion/cobol/jcl-processor.d.ts +33 -0
- package/dist/core/ingestion/cobol/jcl-processor.js +229 -0
- package/dist/core/ingestion/cobol-processor.d.ts +54 -0
- package/dist/core/ingestion/cobol-processor.js +1186 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +17 -0
- package/dist/core/ingestion/entry-point-scoring.js +18 -4
- package/dist/core/ingestion/export-detection.d.ts +47 -8
- package/dist/core/ingestion/export-detection.js +29 -50
- package/dist/core/ingestion/field-extractor.d.ts +29 -0
- package/dist/core/ingestion/field-extractor.js +25 -0
- package/dist/core/ingestion/field-extractors/configs/c-cpp.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/c-cpp.js +108 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.js +73 -0
- package/dist/core/ingestion/field-extractors/configs/dart.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/dart.js +76 -0
- package/dist/core/ingestion/field-extractors/configs/go.d.ts +11 -0
- package/dist/core/ingestion/field-extractors/configs/go.js +64 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +44 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.js +134 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.js +118 -0
- package/dist/core/ingestion/field-extractors/configs/php.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/php.js +67 -0
- package/dist/core/ingestion/field-extractors/configs/python.d.ts +12 -0
- package/dist/core/ingestion/field-extractors/configs/python.js +91 -0
- package/dist/core/ingestion/field-extractors/configs/ruby.d.ts +16 -0
- package/dist/core/ingestion/field-extractors/configs/ruby.js +75 -0
- package/dist/core/ingestion/field-extractors/configs/rust.d.ts +9 -0
- package/dist/core/ingestion/field-extractors/configs/rust.js +55 -0
- package/dist/core/ingestion/field-extractors/configs/swift.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/swift.js +63 -0
- package/dist/core/ingestion/field-extractors/configs/typescript-javascript.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +60 -0
- package/dist/core/ingestion/field-extractors/generic.d.ts +46 -0
- package/dist/core/ingestion/field-extractors/generic.js +111 -0
- package/dist/core/ingestion/field-extractors/typescript.d.ts +77 -0
- package/dist/core/ingestion/field-extractors/typescript.js +291 -0
- package/dist/core/ingestion/field-types.d.ts +59 -0
- package/dist/core/ingestion/field-types.js +2 -0
- package/dist/core/ingestion/framework-detection.d.ts +87 -0
- package/dist/core/ingestion/framework-detection.js +65 -2
- package/dist/core/ingestion/heritage-processor.js +15 -17
- package/dist/core/ingestion/import-processor.d.ts +9 -10
- package/dist/core/ingestion/import-processor.js +59 -14
- package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.d.ts +6 -9
- package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.js +20 -2
- package/dist/core/ingestion/import-resolvers/dart.d.ts +7 -0
- package/dist/core/ingestion/import-resolvers/dart.js +44 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/go.d.ts +4 -5
- package/dist/core/ingestion/{resolvers → import-resolvers}/go.js +17 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.d.ts +9 -1
- package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.js +56 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/php.d.ts +6 -10
- package/dist/core/ingestion/{resolvers → import-resolvers}/php.js +7 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/python.d.ts +9 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/python.js +35 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.d.ts +5 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.js +7 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/rust.d.ts +5 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/rust.js +41 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/standard.d.ts +15 -7
- package/dist/core/ingestion/{resolvers → import-resolvers}/standard.js +22 -3
- package/dist/core/ingestion/import-resolvers/swift.d.ts +7 -0
- package/dist/core/ingestion/import-resolvers/swift.js +23 -0
- package/dist/core/ingestion/import-resolvers/types.d.ts +44 -0
- package/dist/core/ingestion/import-resolvers/types.js +6 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.d.ts +0 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.js +0 -9
- package/dist/core/ingestion/language-config.d.ts +4 -1
- package/dist/core/ingestion/language-provider.d.ts +121 -0
- package/dist/core/ingestion/language-provider.js +24 -0
- package/dist/core/ingestion/languages/c-cpp.d.ts +12 -0
- package/dist/core/ingestion/languages/c-cpp.js +71 -0
- package/dist/core/ingestion/languages/cobol.d.ts +1 -0
- package/dist/core/ingestion/languages/cobol.js +26 -0
- package/dist/core/ingestion/languages/csharp.d.ts +8 -0
- package/dist/core/ingestion/languages/csharp.js +49 -0
- package/dist/core/ingestion/languages/dart.d.ts +12 -0
- package/dist/core/ingestion/languages/dart.js +58 -0
- package/dist/core/ingestion/languages/go.d.ts +11 -0
- package/dist/core/ingestion/languages/go.js +28 -0
- package/dist/core/ingestion/languages/index.d.ts +38 -0
- package/dist/core/ingestion/languages/index.js +63 -0
- package/dist/core/ingestion/languages/java.d.ts +9 -0
- package/dist/core/ingestion/languages/java.js +29 -0
- package/dist/core/ingestion/languages/kotlin.d.ts +9 -0
- package/dist/core/ingestion/languages/kotlin.js +53 -0
- package/dist/core/ingestion/languages/php.d.ts +8 -0
- package/dist/core/ingestion/languages/php.js +145 -0
- package/dist/core/ingestion/languages/python.d.ts +12 -0
- package/dist/core/ingestion/languages/python.js +39 -0
- package/dist/core/ingestion/languages/ruby.d.ts +9 -0
- package/dist/core/ingestion/languages/ruby.js +44 -0
- package/dist/core/ingestion/languages/rust.d.ts +12 -0
- package/dist/core/ingestion/languages/rust.js +44 -0
- package/dist/core/ingestion/languages/swift.d.ts +12 -0
- package/dist/core/ingestion/languages/swift.js +133 -0
- package/dist/core/ingestion/languages/typescript.d.ts +10 -0
- package/dist/core/ingestion/languages/typescript.js +60 -0
- package/dist/core/ingestion/mro-processor.js +14 -15
- package/dist/core/ingestion/{named-binding-extraction.d.ts → named-binding-processor.d.ts} +0 -9
- package/dist/core/ingestion/named-binding-processor.js +42 -0
- package/dist/core/ingestion/named-bindings/csharp.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/csharp.js +37 -0
- package/dist/core/ingestion/named-bindings/java.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/java.js +29 -0
- package/dist/core/ingestion/named-bindings/kotlin.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/kotlin.js +36 -0
- package/dist/core/ingestion/named-bindings/php.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/php.js +61 -0
- package/dist/core/ingestion/named-bindings/python.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/python.js +49 -0
- package/dist/core/ingestion/named-bindings/rust.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/rust.js +64 -0
- package/dist/core/ingestion/named-bindings/types.d.ts +16 -0
- package/dist/core/ingestion/named-bindings/types.js +6 -0
- package/dist/core/ingestion/named-bindings/typescript.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/typescript.js +58 -0
- package/dist/core/ingestion/parsing-processor.d.ts +5 -1
- package/dist/core/ingestion/parsing-processor.js +115 -16
- package/dist/core/ingestion/pipeline.js +925 -424
- package/dist/core/ingestion/resolution-context.js +1 -1
- package/dist/core/ingestion/route-extractors/expo.d.ts +1 -0
- package/dist/core/ingestion/route-extractors/expo.js +36 -0
- package/dist/core/ingestion/route-extractors/middleware.d.ts +47 -0
- package/dist/core/ingestion/route-extractors/middleware.js +143 -0
- package/dist/core/ingestion/route-extractors/nextjs.d.ts +3 -0
- package/dist/core/ingestion/route-extractors/nextjs.js +76 -0
- package/dist/core/ingestion/route-extractors/php.d.ts +7 -0
- package/dist/core/ingestion/route-extractors/php.js +21 -0
- package/dist/core/ingestion/route-extractors/response-shapes.d.ts +20 -0
- package/dist/core/ingestion/route-extractors/response-shapes.js +290 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +8 -7
- package/dist/core/ingestion/tree-sitter-queries.js +231 -9
- package/dist/core/ingestion/type-env.d.ts +14 -17
- package/dist/core/ingestion/type-env.js +66 -14
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +1 -1
- package/dist/core/ingestion/type-extractors/csharp.js +1 -1
- package/dist/core/ingestion/type-extractors/dart.d.ts +15 -0
- package/dist/core/ingestion/type-extractors/dart.js +371 -0
- package/dist/core/ingestion/type-extractors/jvm.js +1 -1
- package/dist/core/ingestion/type-extractors/shared.d.ts +1 -13
- package/dist/core/ingestion/type-extractors/shared.js +9 -102
- package/dist/core/ingestion/type-extractors/swift.js +334 -4
- package/dist/core/ingestion/type-extractors/types.d.ts +3 -1
- package/dist/core/ingestion/{ast-helpers.d.ts → utils/ast-helpers.d.ts} +16 -13
- package/dist/core/ingestion/{ast-helpers.js → utils/ast-helpers.js} +111 -32
- package/dist/core/ingestion/{call-analysis.js → utils/call-analysis.js} +37 -0
- package/dist/core/ingestion/utils/event-loop.d.ts +5 -0
- package/dist/core/ingestion/utils/event-loop.js +5 -0
- package/dist/core/ingestion/utils/language-detection.d.ts +9 -0
- package/dist/core/ingestion/utils/language-detection.js +70 -0
- package/dist/core/ingestion/utils/verbose.d.ts +1 -0
- package/dist/core/ingestion/utils/verbose.js +7 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +43 -2
- package/dist/core/ingestion/workers/parse-worker.js +361 -150
- package/dist/core/lbug/csv-generator.js +34 -1
- package/dist/core/lbug/lbug-adapter.js +6 -0
- package/dist/core/lbug/schema.d.ts +5 -3
- package/dist/core/lbug/schema.js +39 -2
- package/dist/core/tree-sitter/parser-loader.js +7 -1
- package/dist/core/wiki/cursor-client.d.ts +31 -0
- package/dist/core/wiki/cursor-client.js +127 -0
- package/dist/core/wiki/generator.d.ts +28 -9
- package/dist/core/wiki/generator.js +115 -18
- package/dist/core/wiki/graph-queries.d.ts +4 -0
- package/dist/core/wiki/graph-queries.js +7 -1
- package/dist/core/wiki/llm-client.d.ts +2 -0
- package/dist/core/wiki/llm-client.js +8 -4
- package/dist/core/wiki/prompts.d.ts +3 -3
- package/dist/core/wiki/prompts.js +6 -0
- package/dist/mcp/core/lbug-adapter.d.ts +5 -0
- package/dist/mcp/core/lbug-adapter.js +11 -1
- package/dist/mcp/local/local-backend.d.ts +16 -5
- package/dist/mcp/local/local-backend.js +711 -74
- package/dist/mcp/tools.js +71 -2
- package/dist/storage/repo-manager.d.ts +3 -0
- package/package.json +17 -16
- package/dist/core/ingestion/import-resolution.d.ts +0 -101
- package/dist/core/ingestion/import-resolution.js +0 -251
- package/dist/core/ingestion/named-binding-extraction.js +0 -373
- package/dist/core/ingestion/resolvers/index.d.ts +0 -18
- package/dist/core/ingestion/resolvers/index.js +0 -13
- package/dist/core/ingestion/type-extractors/index.d.ts +0 -22
- package/dist/core/ingestion/type-extractors/index.js +0 -31
- package/dist/core/ingestion/utils.d.ts +0 -20
- package/dist/core/ingestion/utils.js +0 -242
- package/scripts/patch-tree-sitter-swift.cjs +0 -74
- /package/dist/core/ingestion/{call-analysis.d.ts → utils/call-analysis.d.ts} +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JCL Parser — Regex single-pass extraction.
|
|
3
|
+
*
|
|
4
|
+
* Extracts JCL constructs from mainframe job streams:
|
|
5
|
+
* - JOB statements (job name, CLASS, MSGCLASS)
|
|
6
|
+
* - EXEC statements (step -> program or proc)
|
|
7
|
+
* - DD statements (dataset references, DISP)
|
|
8
|
+
* - PROC definitions (in-stream and catalogued)
|
|
9
|
+
* - INCLUDE MEMBER= directives
|
|
10
|
+
* - SET symbolic parameters
|
|
11
|
+
* - IF/ELSE/ENDIF conditional execution
|
|
12
|
+
* - JCLLIB ORDER= search paths
|
|
13
|
+
*
|
|
14
|
+
* Pattern follows cobol-preprocessor.ts — regex-only, no tree-sitter.
|
|
15
|
+
*/
|
|
16
|
+
export interface JclParseResults {
|
|
17
|
+
jobs: Array<{
|
|
18
|
+
name: string;
|
|
19
|
+
line: number;
|
|
20
|
+
class?: string;
|
|
21
|
+
msgclass?: string;
|
|
22
|
+
}>;
|
|
23
|
+
steps: Array<{
|
|
24
|
+
name: string;
|
|
25
|
+
jobName: string;
|
|
26
|
+
program?: string;
|
|
27
|
+
proc?: string;
|
|
28
|
+
line: number;
|
|
29
|
+
}>;
|
|
30
|
+
ddStatements: Array<{
|
|
31
|
+
ddName: string;
|
|
32
|
+
stepName: string;
|
|
33
|
+
dataset?: string;
|
|
34
|
+
disp?: string;
|
|
35
|
+
line: number;
|
|
36
|
+
}>;
|
|
37
|
+
procs: Array<{
|
|
38
|
+
name: string;
|
|
39
|
+
line: number;
|
|
40
|
+
isInStream: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
includes: Array<{
|
|
43
|
+
member: string;
|
|
44
|
+
line: number;
|
|
45
|
+
}>;
|
|
46
|
+
sets: Array<{
|
|
47
|
+
variable: string;
|
|
48
|
+
value: string;
|
|
49
|
+
line: number;
|
|
50
|
+
}>;
|
|
51
|
+
jcllib: Array<{
|
|
52
|
+
order: string[];
|
|
53
|
+
line: number;
|
|
54
|
+
}>;
|
|
55
|
+
conditionals: Array<{
|
|
56
|
+
type: 'IF' | 'ELSE' | 'ENDIF';
|
|
57
|
+
condition?: string;
|
|
58
|
+
line: number;
|
|
59
|
+
}>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Parse a JCL file and extract all constructs.
|
|
63
|
+
*
|
|
64
|
+
* @param content - Raw JCL file content
|
|
65
|
+
* @param filePath - Path for diagnostics (not used in extraction)
|
|
66
|
+
* @returns Parsed JCL results
|
|
67
|
+
*/
|
|
68
|
+
export declare function parseJcl(content: string, filePath: string): JclParseResults;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JCL Parser — Regex single-pass extraction.
|
|
3
|
+
*
|
|
4
|
+
* Extracts JCL constructs from mainframe job streams:
|
|
5
|
+
* - JOB statements (job name, CLASS, MSGCLASS)
|
|
6
|
+
* - EXEC statements (step -> program or proc)
|
|
7
|
+
* - DD statements (dataset references, DISP)
|
|
8
|
+
* - PROC definitions (in-stream and catalogued)
|
|
9
|
+
* - INCLUDE MEMBER= directives
|
|
10
|
+
* - SET symbolic parameters
|
|
11
|
+
* - IF/ELSE/ENDIF conditional execution
|
|
12
|
+
* - JCLLIB ORDER= search paths
|
|
13
|
+
*
|
|
14
|
+
* Pattern follows cobol-preprocessor.ts — regex-only, no tree-sitter.
|
|
15
|
+
*/
|
|
16
|
+
// ── JCL statement patterns ─────────────────────────────────────────────
|
|
17
|
+
// JCL continuation: line ends with a non-blank in col 72, next line starts with //
|
|
18
|
+
// We handle continuations by joining lines before matching.
|
|
19
|
+
/** Match //jobname JOB ... */
|
|
20
|
+
const JOB_RE = /^\/\/(\w{1,8})\s+JOB\s+(.*)/i;
|
|
21
|
+
/** Match //stepname EXEC PGM=program or //stepname EXEC procname */
|
|
22
|
+
const EXEC_RE = /^\/\/(\w{1,8})\s+EXEC\s+(.*)/i;
|
|
23
|
+
/** Match //ddname DD ... */
|
|
24
|
+
const DD_RE = /^\/\/(\w{1,8})\s+DD\s+(.*)/i;
|
|
25
|
+
/** Match // JCLLIB ORDER=(lib1,lib2,...) */
|
|
26
|
+
const JCLLIB_RE = /^\/\/\s+JCLLIB\s+ORDER=\(([^)]+)\)/i;
|
|
27
|
+
/** Match // IF condition THEN */
|
|
28
|
+
const IF_RE = /^\/\/\s+IF\s+(.+)\s+THEN/i;
|
|
29
|
+
/** Match // ELSE */
|
|
30
|
+
const ELSE_RE = /^\/\/\s+ELSE\b/i;
|
|
31
|
+
/** Match // ENDIF */
|
|
32
|
+
const ENDIF_RE = /^\/\/\s+ENDIF\b/i;
|
|
33
|
+
/** Match // INCLUDE MEMBER=name */
|
|
34
|
+
const INCLUDE_RE = /^\/\/\s+INCLUDE\s+MEMBER=(\w+)/i;
|
|
35
|
+
/** Match // SET var=value */
|
|
36
|
+
const SET_RE = /^\/\/\s+SET\s+(\w+)=(.+)/i;
|
|
37
|
+
/** Match // PROC or //name PROC */
|
|
38
|
+
const PROC_RE = /^\/\/(\w*)\s+PROC\b/i;
|
|
39
|
+
/** Match // PEND */
|
|
40
|
+
const PEND_RE = /^\/\/\s+PEND\b/i;
|
|
41
|
+
// ── Parameter extractors ───────────────────────────────────────────────
|
|
42
|
+
function extractParam(params, key) {
|
|
43
|
+
// Match KEY=VALUE or KEY='VALUE' in JCL parameter string
|
|
44
|
+
const re = new RegExp(`${key}=(?:'([^']*)'|(\\S+?))(?:[,\\s]|$)`, 'i');
|
|
45
|
+
const m = params.match(re);
|
|
46
|
+
return m ? (m[1] ?? m[2]) : undefined;
|
|
47
|
+
}
|
|
48
|
+
function extractPgm(params) {
|
|
49
|
+
return extractParam(params, 'PGM');
|
|
50
|
+
}
|
|
51
|
+
function extractProc(params) {
|
|
52
|
+
// If no PGM= keyword, the first positional parameter is the proc name
|
|
53
|
+
if (/PGM=/i.test(params))
|
|
54
|
+
return undefined;
|
|
55
|
+
const cleaned = params.replace(/,.*/, '').trim();
|
|
56
|
+
// Proc name is the first token (no = sign)
|
|
57
|
+
if (cleaned && !cleaned.includes('=')) {
|
|
58
|
+
return cleaned.replace(/[,\s].*/s, '').toUpperCase();
|
|
59
|
+
}
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
function extractDsn(params) {
|
|
63
|
+
return extractParam(params, 'DSN') ?? extractParam(params, 'DSNAME');
|
|
64
|
+
}
|
|
65
|
+
function extractDisp(params) {
|
|
66
|
+
const m = params.match(/DISP=\(?\s*([^),\s]+)/i);
|
|
67
|
+
return m ? m[1] : undefined;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Parse a JCL file and extract all constructs.
|
|
71
|
+
*
|
|
72
|
+
* @param content - Raw JCL file content
|
|
73
|
+
* @param filePath - Path for diagnostics (not used in extraction)
|
|
74
|
+
* @returns Parsed JCL results
|
|
75
|
+
*/
|
|
76
|
+
export function parseJcl(content, filePath) {
|
|
77
|
+
const results = {
|
|
78
|
+
jobs: [],
|
|
79
|
+
steps: [],
|
|
80
|
+
ddStatements: [],
|
|
81
|
+
procs: [],
|
|
82
|
+
includes: [],
|
|
83
|
+
sets: [],
|
|
84
|
+
jcllib: [],
|
|
85
|
+
conditionals: [],
|
|
86
|
+
};
|
|
87
|
+
const rawLines = content.split(/\r?\n/);
|
|
88
|
+
// Join continuation lines: a line ending with non-blank in col 71 (0-indexed)
|
|
89
|
+
// followed by a line starting with // is a continuation.
|
|
90
|
+
const lines = [];
|
|
91
|
+
let i = 0;
|
|
92
|
+
while (i < rawLines.length) {
|
|
93
|
+
let line = rawLines[i];
|
|
94
|
+
const lineNum = i + 1;
|
|
95
|
+
// JCL continuation: if line is exactly 72+ chars and col 72 is non-blank
|
|
96
|
+
// and the next line starts with //, join them.
|
|
97
|
+
while (i + 1 < rawLines.length &&
|
|
98
|
+
line.length >= 72 &&
|
|
99
|
+
line[71] !== ' ' &&
|
|
100
|
+
rawLines[i + 1].startsWith('//')) {
|
|
101
|
+
i++;
|
|
102
|
+
// Continuation text starts after // and leading spaces
|
|
103
|
+
const contText = rawLines[i].substring(2).replace(/^\s+/, ' ');
|
|
104
|
+
// Remove the continuation marker (col 72+) from current line
|
|
105
|
+
line = line.substring(0, 71).trimEnd() + contText;
|
|
106
|
+
}
|
|
107
|
+
lines.push({ text: line, lineNum });
|
|
108
|
+
i++;
|
|
109
|
+
}
|
|
110
|
+
let currentJobName = '';
|
|
111
|
+
let currentStepName = '';
|
|
112
|
+
let inStreamProcName = '';
|
|
113
|
+
for (const { text, lineNum } of lines) {
|
|
114
|
+
// Skip JCL comments (starting with //* )
|
|
115
|
+
if (text.startsWith('//*'))
|
|
116
|
+
continue;
|
|
117
|
+
// Skip non-JCL lines (don't start with //)
|
|
118
|
+
if (!text.startsWith('//'))
|
|
119
|
+
continue;
|
|
120
|
+
// PROC definition (in-stream)
|
|
121
|
+
const procMatch = text.match(PROC_RE);
|
|
122
|
+
if (procMatch) {
|
|
123
|
+
const procName = procMatch[1] || inStreamProcName;
|
|
124
|
+
if (procName) {
|
|
125
|
+
results.procs.push({ name: procName.toUpperCase(), line: lineNum, isInStream: true });
|
|
126
|
+
}
|
|
127
|
+
inStreamProcName = procName?.toUpperCase() || '';
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
// PEND (end of in-stream proc)
|
|
131
|
+
if (PEND_RE.test(text)) {
|
|
132
|
+
inStreamProcName = '';
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
// JCLLIB ORDER=
|
|
136
|
+
const jcllibMatch = text.match(JCLLIB_RE);
|
|
137
|
+
if (jcllibMatch) {
|
|
138
|
+
const libs = jcllibMatch[1].split(',').map(s => s.trim().replace(/'/g, ''));
|
|
139
|
+
results.jcllib.push({ order: libs, line: lineNum });
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
// IF/ELSE/ENDIF
|
|
143
|
+
const ifMatch = text.match(IF_RE);
|
|
144
|
+
if (ifMatch) {
|
|
145
|
+
results.conditionals.push({ type: 'IF', condition: ifMatch[1].trim(), line: lineNum });
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (ELSE_RE.test(text)) {
|
|
149
|
+
results.conditionals.push({ type: 'ELSE', line: lineNum });
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (ENDIF_RE.test(text)) {
|
|
153
|
+
results.conditionals.push({ type: 'ENDIF', line: lineNum });
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
// INCLUDE MEMBER=
|
|
157
|
+
const includeMatch = text.match(INCLUDE_RE);
|
|
158
|
+
if (includeMatch) {
|
|
159
|
+
results.includes.push({ member: includeMatch[1].toUpperCase(), line: lineNum });
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
// SET var=value
|
|
163
|
+
const setMatch = text.match(SET_RE);
|
|
164
|
+
if (setMatch) {
|
|
165
|
+
results.sets.push({
|
|
166
|
+
variable: setMatch[1].toUpperCase(),
|
|
167
|
+
value: setMatch[2].trim().replace(/,\s*$/, ''),
|
|
168
|
+
line: lineNum,
|
|
169
|
+
});
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// JOB statement
|
|
173
|
+
const jobMatch = text.match(JOB_RE);
|
|
174
|
+
if (jobMatch) {
|
|
175
|
+
currentJobName = jobMatch[1].toUpperCase();
|
|
176
|
+
const params = jobMatch[2];
|
|
177
|
+
results.jobs.push({
|
|
178
|
+
name: currentJobName,
|
|
179
|
+
line: lineNum,
|
|
180
|
+
class: extractParam(params, 'CLASS'),
|
|
181
|
+
msgclass: extractParam(params, 'MSGCLASS'),
|
|
182
|
+
});
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
// EXEC statement
|
|
186
|
+
const execMatch = text.match(EXEC_RE);
|
|
187
|
+
if (execMatch) {
|
|
188
|
+
currentStepName = execMatch[1].toUpperCase();
|
|
189
|
+
const params = execMatch[2];
|
|
190
|
+
const pgm = extractPgm(params);
|
|
191
|
+
const proc = pgm ? undefined : extractProc(params);
|
|
192
|
+
results.steps.push({
|
|
193
|
+
name: currentStepName,
|
|
194
|
+
jobName: currentJobName,
|
|
195
|
+
program: pgm?.toUpperCase(),
|
|
196
|
+
proc: proc?.toUpperCase(),
|
|
197
|
+
line: lineNum,
|
|
198
|
+
});
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
// DD statement
|
|
202
|
+
const ddMatch = text.match(DD_RE);
|
|
203
|
+
if (ddMatch) {
|
|
204
|
+
const ddName = ddMatch[1].toUpperCase();
|
|
205
|
+
const params = ddMatch[2];
|
|
206
|
+
results.ddStatements.push({
|
|
207
|
+
ddName,
|
|
208
|
+
stepName: currentStepName,
|
|
209
|
+
dataset: extractDsn(params)?.toUpperCase(),
|
|
210
|
+
disp: extractDisp(params)?.toUpperCase(),
|
|
211
|
+
line: lineNum,
|
|
212
|
+
});
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return results;
|
|
217
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JCL Processor — Converts JCL parse results into graph nodes and edges.
|
|
3
|
+
*
|
|
4
|
+
* Maps JCL entities to existing graph types (no new tables):
|
|
5
|
+
* - Job -> CodeElement (description: "jcl-job class:A msgclass:X")
|
|
6
|
+
* - Step -> CodeElement (description: "jcl-step pgm:PROGRAMNAME")
|
|
7
|
+
* - Dataset -> CodeElement (description: "jcl-dataset disp:SHR")
|
|
8
|
+
* - PROC -> Module
|
|
9
|
+
*
|
|
10
|
+
* Edges:
|
|
11
|
+
* - Job CONTAINS Step
|
|
12
|
+
* - Step CALLS Module (when PGM= matches an indexed program)
|
|
13
|
+
* - Step references Dataset (CALLS edge with reason "jcl-dd")
|
|
14
|
+
* - Job/Step IMPORTS PROC
|
|
15
|
+
*
|
|
16
|
+
* Pattern follows detectCrossProgamContracts() in pipeline.ts.
|
|
17
|
+
*/
|
|
18
|
+
import type { KnowledgeGraph } from '../../graph/types.js';
|
|
19
|
+
export interface JclProcessResult {
|
|
20
|
+
jobCount: number;
|
|
21
|
+
stepCount: number;
|
|
22
|
+
datasetCount: number;
|
|
23
|
+
programLinks: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Process JCL files and integrate into the knowledge graph.
|
|
27
|
+
*
|
|
28
|
+
* @param graph - The in-memory knowledge graph
|
|
29
|
+
* @param jclPaths - File paths of JCL files
|
|
30
|
+
* @param jclContents - Map of path -> file content
|
|
31
|
+
* @returns Summary of what was added
|
|
32
|
+
*/
|
|
33
|
+
export declare function processJclFiles(graph: KnowledgeGraph, jclPaths: string[], jclContents: Map<string, string>): JclProcessResult;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JCL Processor — Converts JCL parse results into graph nodes and edges.
|
|
3
|
+
*
|
|
4
|
+
* Maps JCL entities to existing graph types (no new tables):
|
|
5
|
+
* - Job -> CodeElement (description: "jcl-job class:A msgclass:X")
|
|
6
|
+
* - Step -> CodeElement (description: "jcl-step pgm:PROGRAMNAME")
|
|
7
|
+
* - Dataset -> CodeElement (description: "jcl-dataset disp:SHR")
|
|
8
|
+
* - PROC -> Module
|
|
9
|
+
*
|
|
10
|
+
* Edges:
|
|
11
|
+
* - Job CONTAINS Step
|
|
12
|
+
* - Step CALLS Module (when PGM= matches an indexed program)
|
|
13
|
+
* - Step references Dataset (CALLS edge with reason "jcl-dd")
|
|
14
|
+
* - Job/Step IMPORTS PROC
|
|
15
|
+
*
|
|
16
|
+
* Pattern follows detectCrossProgamContracts() in pipeline.ts.
|
|
17
|
+
*/
|
|
18
|
+
import { parseJcl } from './jcl-parser.js';
|
|
19
|
+
import { generateId } from '../../../lib/utils.js';
|
|
20
|
+
/**
|
|
21
|
+
* Process JCL files and integrate into the knowledge graph.
|
|
22
|
+
*
|
|
23
|
+
* @param graph - The in-memory knowledge graph
|
|
24
|
+
* @param jclPaths - File paths of JCL files
|
|
25
|
+
* @param jclContents - Map of path -> file content
|
|
26
|
+
* @returns Summary of what was added
|
|
27
|
+
*/
|
|
28
|
+
export function processJclFiles(graph, jclPaths, jclContents) {
|
|
29
|
+
let jobCount = 0;
|
|
30
|
+
let stepCount = 0;
|
|
31
|
+
let datasetCount = 0;
|
|
32
|
+
let programLinks = 0;
|
|
33
|
+
// Collect all Module names for step -> program linking
|
|
34
|
+
const moduleNames = new Map(); // uppercase name -> node id
|
|
35
|
+
graph.forEachNode(node => {
|
|
36
|
+
if (node.label === 'Module') {
|
|
37
|
+
const nodeName = node.properties.name;
|
|
38
|
+
if (typeof nodeName === 'string') {
|
|
39
|
+
moduleNames.set(nodeName.toUpperCase(), node.id);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
for (const filePath of jclPaths) {
|
|
44
|
+
const content = jclContents.get(filePath);
|
|
45
|
+
if (!content)
|
|
46
|
+
continue;
|
|
47
|
+
const parsed = parseJcl(content, filePath);
|
|
48
|
+
const result = integrateJclResults(graph, parsed, filePath, moduleNames);
|
|
49
|
+
jobCount += result.jobCount;
|
|
50
|
+
stepCount += result.stepCount;
|
|
51
|
+
datasetCount += result.datasetCount;
|
|
52
|
+
programLinks += result.programLinks;
|
|
53
|
+
}
|
|
54
|
+
return { jobCount, stepCount, datasetCount, programLinks };
|
|
55
|
+
}
|
|
56
|
+
function integrateJclResults(graph, parsed, filePath, moduleNames) {
|
|
57
|
+
let jobCount = 0;
|
|
58
|
+
let stepCount = 0;
|
|
59
|
+
let datasetCount = 0;
|
|
60
|
+
let programLinks = 0;
|
|
61
|
+
// Track step node IDs for DD -> step linking
|
|
62
|
+
const stepNodeIds = new Map(); // stepName -> nodeId
|
|
63
|
+
// 1. Create Job nodes
|
|
64
|
+
for (const job of parsed.jobs) {
|
|
65
|
+
const jobId = generateId('CodeElement', `${filePath}:job:${job.name}`);
|
|
66
|
+
const classPart = job.class ? ` class:${job.class}` : '';
|
|
67
|
+
const msgPart = job.msgclass ? ` msgclass:${job.msgclass}` : '';
|
|
68
|
+
graph.addNode({
|
|
69
|
+
id: jobId,
|
|
70
|
+
label: 'CodeElement',
|
|
71
|
+
properties: {
|
|
72
|
+
name: job.name,
|
|
73
|
+
filePath,
|
|
74
|
+
startLine: job.line,
|
|
75
|
+
endLine: job.line,
|
|
76
|
+
description: `jcl-job${classPart}${msgPart}`,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
// Link File -> Job (CONTAINS)
|
|
80
|
+
const fileId = generateId('File', filePath);
|
|
81
|
+
graph.addRelationship({
|
|
82
|
+
id: `${fileId}_contains_${jobId}`,
|
|
83
|
+
type: 'CONTAINS',
|
|
84
|
+
sourceId: fileId,
|
|
85
|
+
targetId: jobId,
|
|
86
|
+
confidence: 1.0,
|
|
87
|
+
reason: 'jcl-job',
|
|
88
|
+
});
|
|
89
|
+
jobCount++;
|
|
90
|
+
}
|
|
91
|
+
// 1.5 Pre-register in-stream PROCs so steps can reference them
|
|
92
|
+
// (fixes ordering bug: steps processed before PROCs were registered)
|
|
93
|
+
for (const proc of parsed.procs) {
|
|
94
|
+
const procId = generateId('Module', `${filePath}:proc:${proc.name}`);
|
|
95
|
+
moduleNames.set(proc.name.toUpperCase(), procId);
|
|
96
|
+
}
|
|
97
|
+
// 2. Create Step nodes and link to programs
|
|
98
|
+
for (const step of parsed.steps) {
|
|
99
|
+
const stepId = generateId('CodeElement', `${filePath}:step:${step.jobName}:${step.name}`);
|
|
100
|
+
const pgmPart = step.program ? ` pgm:${step.program}` : '';
|
|
101
|
+
const procPart = step.proc ? ` proc:${step.proc}` : '';
|
|
102
|
+
graph.addNode({
|
|
103
|
+
id: stepId,
|
|
104
|
+
label: 'CodeElement',
|
|
105
|
+
properties: {
|
|
106
|
+
name: step.name,
|
|
107
|
+
filePath,
|
|
108
|
+
startLine: step.line,
|
|
109
|
+
endLine: step.line,
|
|
110
|
+
description: `jcl-step${pgmPart}${procPart}`,
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
stepNodeIds.set(step.name, stepId);
|
|
114
|
+
// Link Job -> Step (CONTAINS)
|
|
115
|
+
if (step.jobName) {
|
|
116
|
+
const jobId = generateId('CodeElement', `${filePath}:job:${step.jobName}`);
|
|
117
|
+
graph.addRelationship({
|
|
118
|
+
id: `${jobId}_contains_${stepId}`,
|
|
119
|
+
type: 'CONTAINS',
|
|
120
|
+
sourceId: jobId,
|
|
121
|
+
targetId: stepId,
|
|
122
|
+
confidence: 1.0,
|
|
123
|
+
reason: 'jcl-step',
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
// Link Step -> Module (CALLS) when PGM= matches an indexed program
|
|
127
|
+
if (step.program) {
|
|
128
|
+
const moduleId = moduleNames.get(step.program.toUpperCase());
|
|
129
|
+
if (moduleId) {
|
|
130
|
+
graph.addRelationship({
|
|
131
|
+
id: `${stepId}_calls_${moduleId}`,
|
|
132
|
+
type: 'CALLS',
|
|
133
|
+
sourceId: stepId,
|
|
134
|
+
targetId: moduleId,
|
|
135
|
+
confidence: 0.95,
|
|
136
|
+
reason: 'jcl-exec-pgm',
|
|
137
|
+
});
|
|
138
|
+
programLinks++;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Link Step -> PROC (CALLS) — PROC as Module
|
|
142
|
+
if (step.proc) {
|
|
143
|
+
const procModuleId = moduleNames.get(step.proc.toUpperCase());
|
|
144
|
+
if (procModuleId) {
|
|
145
|
+
graph.addRelationship({
|
|
146
|
+
id: `${stepId}_calls_proc_${procModuleId}`,
|
|
147
|
+
type: 'CALLS',
|
|
148
|
+
sourceId: stepId,
|
|
149
|
+
targetId: procModuleId,
|
|
150
|
+
confidence: 0.9,
|
|
151
|
+
reason: 'jcl-exec-proc',
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
stepCount++;
|
|
156
|
+
}
|
|
157
|
+
// 3. Create Dataset nodes from DD statements
|
|
158
|
+
const seenDatasets = new Set();
|
|
159
|
+
for (const dd of parsed.ddStatements) {
|
|
160
|
+
if (!dd.dataset)
|
|
161
|
+
continue;
|
|
162
|
+
// Create dataset node (deduplicated per file)
|
|
163
|
+
const datasetKey = `${filePath}:dataset:${dd.dataset}`;
|
|
164
|
+
const datasetId = generateId('CodeElement', datasetKey);
|
|
165
|
+
if (!seenDatasets.has(dd.dataset)) {
|
|
166
|
+
const dispPart = dd.disp ? ` disp:${dd.disp}` : '';
|
|
167
|
+
graph.addNode({
|
|
168
|
+
id: datasetId,
|
|
169
|
+
label: 'CodeElement',
|
|
170
|
+
properties: {
|
|
171
|
+
name: dd.dataset,
|
|
172
|
+
filePath,
|
|
173
|
+
startLine: dd.line,
|
|
174
|
+
endLine: dd.line,
|
|
175
|
+
description: `jcl-dataset${dispPart}`,
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
seenDatasets.add(dd.dataset);
|
|
179
|
+
datasetCount++;
|
|
180
|
+
}
|
|
181
|
+
// Link Step -> Dataset (CALLS with reason jcl-dd)
|
|
182
|
+
const stepId = stepNodeIds.get(dd.stepName);
|
|
183
|
+
if (stepId) {
|
|
184
|
+
graph.addRelationship({
|
|
185
|
+
id: `${stepId}_dd_${dd.ddName}_${datasetId}`,
|
|
186
|
+
type: 'CALLS',
|
|
187
|
+
sourceId: stepId,
|
|
188
|
+
targetId: datasetId,
|
|
189
|
+
confidence: 0.85,
|
|
190
|
+
reason: `jcl-dd:${dd.ddName}`,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// 4. Create PROC nodes (in-stream procs as Module)
|
|
195
|
+
for (const proc of parsed.procs) {
|
|
196
|
+
if (!proc.isInStream)
|
|
197
|
+
continue;
|
|
198
|
+
const procId = generateId('Module', `${filePath}:proc:${proc.name}`);
|
|
199
|
+
graph.addNode({
|
|
200
|
+
id: procId,
|
|
201
|
+
label: 'Module',
|
|
202
|
+
properties: {
|
|
203
|
+
name: proc.name,
|
|
204
|
+
filePath,
|
|
205
|
+
startLine: proc.line,
|
|
206
|
+
endLine: proc.line,
|
|
207
|
+
description: 'jcl-proc-instream',
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
// Register for step linking
|
|
211
|
+
moduleNames.set(proc.name.toUpperCase(), procId);
|
|
212
|
+
}
|
|
213
|
+
// 5. INCLUDE directives -> IMPORTS edges
|
|
214
|
+
for (const inc of parsed.includes) {
|
|
215
|
+
const moduleId = moduleNames.get(inc.member.toUpperCase());
|
|
216
|
+
if (moduleId) {
|
|
217
|
+
const fileId = generateId('File', filePath);
|
|
218
|
+
graph.addRelationship({
|
|
219
|
+
id: `${fileId}_includes_${moduleId}`,
|
|
220
|
+
type: 'IMPORTS',
|
|
221
|
+
sourceId: fileId,
|
|
222
|
+
targetId: moduleId,
|
|
223
|
+
confidence: 0.9,
|
|
224
|
+
reason: 'jcl-include',
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return { jobCount, stepCount, datasetCount, programLinks };
|
|
229
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COBOL Processor
|
|
3
|
+
*
|
|
4
|
+
* Standalone regex-based processor for COBOL and JCL files.
|
|
5
|
+
* Follows the markdown-processor.ts pattern: takes (graph, files, allPathSet),
|
|
6
|
+
* does its own extraction, and writes directly to the graph.
|
|
7
|
+
*
|
|
8
|
+
* Pipeline:
|
|
9
|
+
* 1. Separate programs from copybooks
|
|
10
|
+
* 2. Build copybook map (name -> content)
|
|
11
|
+
* 3. For each program: expand COPY statements, then run regex extraction
|
|
12
|
+
* 4. Map CobolRegexResults to graph nodes and relationships
|
|
13
|
+
* 5. Optionally process JCL files for job-step cross-references
|
|
14
|
+
*/
|
|
15
|
+
import type { KnowledgeGraph } from '../graph/types.js';
|
|
16
|
+
interface CobolFile {
|
|
17
|
+
path: string;
|
|
18
|
+
content: string;
|
|
19
|
+
}
|
|
20
|
+
export interface CobolProcessResult {
|
|
21
|
+
programs: number;
|
|
22
|
+
paragraphs: number;
|
|
23
|
+
sections: number;
|
|
24
|
+
dataItems: number;
|
|
25
|
+
calls: number;
|
|
26
|
+
copies: number;
|
|
27
|
+
execSqlBlocks: number;
|
|
28
|
+
execCicsBlocks: number;
|
|
29
|
+
entryPoints: number;
|
|
30
|
+
moves: number;
|
|
31
|
+
fileDeclarations: number;
|
|
32
|
+
jclJobs: number;
|
|
33
|
+
jclSteps: number;
|
|
34
|
+
sqlIncludes: number;
|
|
35
|
+
execDliBlocks: number;
|
|
36
|
+
declaratives: number;
|
|
37
|
+
sets: number;
|
|
38
|
+
inspects: number;
|
|
39
|
+
initializes: number;
|
|
40
|
+
}
|
|
41
|
+
/** Returns true if the file is a COBOL or copybook file. */
|
|
42
|
+
export declare function isCobolFile(filePath: string): boolean;
|
|
43
|
+
/** Returns true if the file is a JCL file. */
|
|
44
|
+
export declare function isJclFile(filePath: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Process COBOL and JCL files into the knowledge graph.
|
|
47
|
+
*
|
|
48
|
+
* @param graph - The in-memory knowledge graph
|
|
49
|
+
* @param files - Array of { path, content } for COBOL/JCL files
|
|
50
|
+
* @param allPathSet - Set of all file paths in the repository
|
|
51
|
+
* @returns Summary of what was extracted
|
|
52
|
+
*/
|
|
53
|
+
export declare const processCobol: (graph: KnowledgeGraph, files: CobolFile[], allPathSet: Set<string>) => CobolProcessResult;
|
|
54
|
+
export {};
|