@miguelduran14/knowflow 0.1.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.
Files changed (192) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +182 -0
  3. package/dist/advisories.d.ts +16 -0
  4. package/dist/advisories.js +364 -0
  5. package/dist/advisories.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +104 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/copy-resolver.d.ts +22 -0
  10. package/dist/copy-resolver.js +74 -0
  11. package/dist/copy-resolver.js.map +1 -0
  12. package/dist/dataflow.d.ts +2 -0
  13. package/dist/dataflow.js +88 -0
  14. package/dist/dataflow.js.map +1 -0
  15. package/dist/dossier.d.ts +20 -0
  16. package/dist/dossier.js +331 -0
  17. package/dist/dossier.js.map +1 -0
  18. package/dist/explain/claude.d.ts +14 -0
  19. package/dist/explain/claude.js +91 -0
  20. package/dist/explain/claude.js.map +1 -0
  21. package/dist/explain/explain.d.ts +72 -0
  22. package/dist/explain/explain.js +126 -0
  23. package/dist/explain/explain.js.map +1 -0
  24. package/dist/explain/facts.d.ts +23 -0
  25. package/dist/explain/facts.js +266 -0
  26. package/dist/explain/facts.js.map +1 -0
  27. package/dist/explain/fake.d.ts +14 -0
  28. package/dist/explain/fake.js +27 -0
  29. package/dist/explain/fake.js.map +1 -0
  30. package/dist/explain/openai.d.ts +42 -0
  31. package/dist/explain/openai.js +102 -0
  32. package/dist/explain/openai.js.map +1 -0
  33. package/dist/explain/provider.d.ts +19 -0
  34. package/dist/explain/provider.js +2 -0
  35. package/dist/explain/provider.js.map +1 -0
  36. package/dist/explain/sse.d.ts +10 -0
  37. package/dist/explain/sse.js +44 -0
  38. package/dist/explain/sse.js.map +1 -0
  39. package/dist/flow-parser.d.ts +10 -0
  40. package/dist/flow-parser.js +503 -0
  41. package/dist/flow-parser.js.map +1 -0
  42. package/dist/glossary.d.ts +54 -0
  43. package/dist/glossary.js +340 -0
  44. package/dist/glossary.js.map +1 -0
  45. package/dist/index.d.ts +17 -0
  46. package/dist/index.js +16 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/inventory.d.ts +7 -0
  49. package/dist/inventory.js +453 -0
  50. package/dist/inventory.js.map +1 -0
  51. package/dist/lines.d.ts +15 -0
  52. package/dist/lines.js +53 -0
  53. package/dist/lines.js.map +1 -0
  54. package/dist/linker.d.ts +17 -0
  55. package/dist/linker.js +56 -0
  56. package/dist/linker.js.map +1 -0
  57. package/dist/mermaid.d.ts +27 -0
  58. package/dist/mermaid.js +133 -0
  59. package/dist/mermaid.js.map +1 -0
  60. package/dist/parser.d.ts +19 -0
  61. package/dist/parser.js +442 -0
  62. package/dist/parser.js.map +1 -0
  63. package/dist/pic.d.ts +29 -0
  64. package/dist/pic.js +197 -0
  65. package/dist/pic.js.map +1 -0
  66. package/dist/references.d.ts +24 -0
  67. package/dist/references.js +906 -0
  68. package/dist/references.js.map +1 -0
  69. package/dist/source-lines.d.ts +56 -0
  70. package/dist/source-lines.js +114 -0
  71. package/dist/source-lines.js.map +1 -0
  72. package/dist/types.d.ts +499 -0
  73. package/dist/types.js +2 -0
  74. package/dist/types.js.map +1 -0
  75. package/gui/dist/assets/ChainCanvas-C37KyhnE.js +1 -0
  76. package/gui/dist/assets/FlowCanvas-BRklWBCp.js +3 -0
  77. package/gui/dist/assets/RobotProfessor-BtTDTBDq.js +4220 -0
  78. package/gui/dist/assets/fira-code-cyrillic-400-normal-UC0NFL4U.woff2 +0 -0
  79. package/gui/dist/assets/fira-code-cyrillic-400-normal-dc1q3VD7.woff +0 -0
  80. package/gui/dist/assets/fira-code-cyrillic-500-normal-Bu7VCL72.woff +0 -0
  81. package/gui/dist/assets/fira-code-cyrillic-500-normal-CX35h3Mg.woff2 +0 -0
  82. package/gui/dist/assets/fira-code-cyrillic-600-normal-BD56RyRT.woff +0 -0
  83. package/gui/dist/assets/fira-code-cyrillic-600-normal-CPRdbepc.woff2 +0 -0
  84. package/gui/dist/assets/fira-code-cyrillic-ext-400-normal-Buh61xzB.woff +0 -0
  85. package/gui/dist/assets/fira-code-cyrillic-ext-400-normal-txZ9Fk_1.woff2 +0 -0
  86. package/gui/dist/assets/fira-code-cyrillic-ext-500-normal-CYRspHgm.woff2 +0 -0
  87. package/gui/dist/assets/fira-code-cyrillic-ext-500-normal-CwtLmSFD.woff +0 -0
  88. package/gui/dist/assets/fira-code-cyrillic-ext-600-normal-B9wE0zmr.woff2 +0 -0
  89. package/gui/dist/assets/fira-code-cyrillic-ext-600-normal-DldcyWhZ.woff +0 -0
  90. package/gui/dist/assets/fira-code-greek-400-normal-B2Gh_Y8s.woff2 +0 -0
  91. package/gui/dist/assets/fira-code-greek-400-normal-DobhaxvF.woff +0 -0
  92. package/gui/dist/assets/fira-code-greek-500-normal-CVO0IRNt.woff2 +0 -0
  93. package/gui/dist/assets/fira-code-greek-500-normal-DEXIWiey.woff +0 -0
  94. package/gui/dist/assets/fira-code-greek-600-normal-D_h3X2X5.woff +0 -0
  95. package/gui/dist/assets/fira-code-greek-600-normal-Dxp52_By.woff2 +0 -0
  96. package/gui/dist/assets/fira-code-greek-ext-400-normal-DR7mBgIM.woff2 +0 -0
  97. package/gui/dist/assets/fira-code-greek-ext-400-normal-DSPUheWg.woff +0 -0
  98. package/gui/dist/assets/fira-code-greek-ext-500-normal-BO3iq16n.woff2 +0 -0
  99. package/gui/dist/assets/fira-code-greek-ext-500-normal-CMiNLXER.woff +0 -0
  100. package/gui/dist/assets/fira-code-greek-ext-600-normal-C-cQDoOk.woff +0 -0
  101. package/gui/dist/assets/fira-code-greek-ext-600-normal-DtBpFRLc.woff2 +0 -0
  102. package/gui/dist/assets/fira-code-latin-400-normal-C-QZfXAs.woff +0 -0
  103. package/gui/dist/assets/fira-code-latin-400-normal-DGosTW8U.woff2 +0 -0
  104. package/gui/dist/assets/fira-code-latin-500-normal-B6gioGu8.woff2 +0 -0
  105. package/gui/dist/assets/fira-code-latin-500-normal-aMLC2AMm.woff +0 -0
  106. package/gui/dist/assets/fira-code-latin-600-normal-BmSSHshu.woff +0 -0
  107. package/gui/dist/assets/fira-code-latin-600-normal-CvYZpPHg.woff2 +0 -0
  108. package/gui/dist/assets/fira-code-latin-ext-400-normal-DG73JjOf.woff +0 -0
  109. package/gui/dist/assets/fira-code-latin-ext-400-normal-KSMg0QLl.woff2 +0 -0
  110. package/gui/dist/assets/fira-code-latin-ext-500-normal-CaANqXjI.woff +0 -0
  111. package/gui/dist/assets/fira-code-latin-ext-500-normal-Crd9e_oI.woff2 +0 -0
  112. package/gui/dist/assets/fira-code-latin-ext-600-normal-0PFQL1eg.woff +0 -0
  113. package/gui/dist/assets/fira-code-latin-ext-600-normal-Cb7jxoAi.woff2 +0 -0
  114. package/gui/dist/assets/fira-code-symbols2-400-normal-_QEZCEwe.woff +0 -0
  115. package/gui/dist/assets/fira-code-symbols2-500-normal-DwsgbIjQ.woff +0 -0
  116. package/gui/dist/assets/fira-code-symbols2-600-normal-Dvq6IQE5.woff +0 -0
  117. package/gui/dist/assets/fira-sans-cyrillic-300-normal-BO7tmGom.woff2 +0 -0
  118. package/gui/dist/assets/fira-sans-cyrillic-300-normal-BtNmWoqn.woff +0 -0
  119. package/gui/dist/assets/fira-sans-cyrillic-400-normal-CKu2TFQr.woff2 +0 -0
  120. package/gui/dist/assets/fira-sans-cyrillic-400-normal-D9eUeF-O.woff +0 -0
  121. package/gui/dist/assets/fira-sans-cyrillic-500-normal-CXfldnQ8.woff2 +0 -0
  122. package/gui/dist/assets/fira-sans-cyrillic-500-normal-Daski1k2.woff +0 -0
  123. package/gui/dist/assets/fira-sans-cyrillic-600-normal-CJ5P9t7t.woff +0 -0
  124. package/gui/dist/assets/fira-sans-cyrillic-600-normal-JSBvCpTs.woff2 +0 -0
  125. package/gui/dist/assets/fira-sans-cyrillic-700-normal-Bl-HczEO.woff2 +0 -0
  126. package/gui/dist/assets/fira-sans-cyrillic-700-normal-KyW5QH4H.woff +0 -0
  127. package/gui/dist/assets/fira-sans-cyrillic-ext-300-normal-BRn8Tsce.woff2 +0 -0
  128. package/gui/dist/assets/fira-sans-cyrillic-ext-300-normal-DOtRq9zH.woff +0 -0
  129. package/gui/dist/assets/fira-sans-cyrillic-ext-400-normal-Cycyekte.woff2 +0 -0
  130. package/gui/dist/assets/fira-sans-cyrillic-ext-400-normal-Dd5dApAy.woff +0 -0
  131. package/gui/dist/assets/fira-sans-cyrillic-ext-500-normal-Cixivk4R.woff +0 -0
  132. package/gui/dist/assets/fira-sans-cyrillic-ext-500-normal-Dkk5LlrU.woff2 +0 -0
  133. package/gui/dist/assets/fira-sans-cyrillic-ext-600-normal-BKgjRriM.woff +0 -0
  134. package/gui/dist/assets/fira-sans-cyrillic-ext-600-normal-CE6oUZE1.woff2 +0 -0
  135. package/gui/dist/assets/fira-sans-cyrillic-ext-700-normal-BfO9TR-w.woff2 +0 -0
  136. package/gui/dist/assets/fira-sans-cyrillic-ext-700-normal-Gcpdxicj.woff +0 -0
  137. package/gui/dist/assets/fira-sans-greek-300-normal-D3JfF3y9.woff2 +0 -0
  138. package/gui/dist/assets/fira-sans-greek-300-normal-DSgcXl_1.woff +0 -0
  139. package/gui/dist/assets/fira-sans-greek-400-normal-BFCFncbp.woff2 +0 -0
  140. package/gui/dist/assets/fira-sans-greek-400-normal-DQ8sF22y.woff +0 -0
  141. package/gui/dist/assets/fira-sans-greek-500-normal-C9KT8sAy.woff +0 -0
  142. package/gui/dist/assets/fira-sans-greek-500-normal-Cy-TUuxE.woff2 +0 -0
  143. package/gui/dist/assets/fira-sans-greek-600-normal-BlqpLOpF.woff2 +0 -0
  144. package/gui/dist/assets/fira-sans-greek-600-normal-DfHu91YF.woff +0 -0
  145. package/gui/dist/assets/fira-sans-greek-700-normal-BVfcrbV7.woff2 +0 -0
  146. package/gui/dist/assets/fira-sans-greek-700-normal-CJu31rC4.woff +0 -0
  147. package/gui/dist/assets/fira-sans-greek-ext-300-normal-CodlqOxk.woff +0 -0
  148. package/gui/dist/assets/fira-sans-greek-ext-300-normal-DVDwbKuK.woff2 +0 -0
  149. package/gui/dist/assets/fira-sans-greek-ext-400-normal-ByG7UNQ2.woff2 +0 -0
  150. package/gui/dist/assets/fira-sans-greek-ext-400-normal-ClCfNE6D.woff +0 -0
  151. package/gui/dist/assets/fira-sans-greek-ext-500-normal-Bem4H9fH.woff +0 -0
  152. package/gui/dist/assets/fira-sans-greek-ext-500-normal-nq-cjB3m.woff2 +0 -0
  153. package/gui/dist/assets/fira-sans-greek-ext-600-normal-DPxZoeHL.woff +0 -0
  154. package/gui/dist/assets/fira-sans-greek-ext-600-normal-fS0evUH3.woff2 +0 -0
  155. package/gui/dist/assets/fira-sans-greek-ext-700-normal-C1m6bE4Q.woff2 +0 -0
  156. package/gui/dist/assets/fira-sans-greek-ext-700-normal-C8J5qYMq.woff +0 -0
  157. package/gui/dist/assets/fira-sans-latin-300-normal-B2LrTgQS.woff2 +0 -0
  158. package/gui/dist/assets/fira-sans-latin-300-normal-Dwkm-oZ7.woff +0 -0
  159. package/gui/dist/assets/fira-sans-latin-400-normal-66xCkunx.woff +0 -0
  160. package/gui/dist/assets/fira-sans-latin-400-normal-a0AnQzuD.woff2 +0 -0
  161. package/gui/dist/assets/fira-sans-latin-500-normal-Bkfzcwmr.woff +0 -0
  162. package/gui/dist/assets/fira-sans-latin-500-normal-Bvbxc8ch.woff2 +0 -0
  163. package/gui/dist/assets/fira-sans-latin-600-normal-CXKlxLG9.woff2 +0 -0
  164. package/gui/dist/assets/fira-sans-latin-600-normal-DtSgd811.woff +0 -0
  165. package/gui/dist/assets/fira-sans-latin-700-normal-CRhwpWTq.woff2 +0 -0
  166. package/gui/dist/assets/fira-sans-latin-700-normal-DgqLm3Fi.woff +0 -0
  167. package/gui/dist/assets/fira-sans-latin-ext-300-normal-CAROBYR0.woff +0 -0
  168. package/gui/dist/assets/fira-sans-latin-ext-300-normal-GNF4Ac3G.woff2 +0 -0
  169. package/gui/dist/assets/fira-sans-latin-ext-400-normal-BCUwhuGB.woff +0 -0
  170. package/gui/dist/assets/fira-sans-latin-ext-400-normal-BLG_mAEf.woff2 +0 -0
  171. package/gui/dist/assets/fira-sans-latin-ext-500-normal-CFRf4jcC.woff +0 -0
  172. package/gui/dist/assets/fira-sans-latin-ext-500-normal-OO1QnNpY.woff2 +0 -0
  173. package/gui/dist/assets/fira-sans-latin-ext-600-normal-DLMQsaV4.woff +0 -0
  174. package/gui/dist/assets/fira-sans-latin-ext-600-normal-DTQBTt1m.woff2 +0 -0
  175. package/gui/dist/assets/fira-sans-latin-ext-700-normal-cfTxGFzJ.woff +0 -0
  176. package/gui/dist/assets/fira-sans-latin-ext-700-normal-g2Yrd4J5.woff2 +0 -0
  177. package/gui/dist/assets/fira-sans-vietnamese-300-normal-BO7He0nF.woff2 +0 -0
  178. package/gui/dist/assets/fira-sans-vietnamese-300-normal-CeyOCBN-.woff +0 -0
  179. package/gui/dist/assets/fira-sans-vietnamese-400-normal-DUVG35gE.woff +0 -0
  180. package/gui/dist/assets/fira-sans-vietnamese-400-normal-ljDTQFsx.woff2 +0 -0
  181. package/gui/dist/assets/fira-sans-vietnamese-500-normal-ChEXCnJy.woff2 +0 -0
  182. package/gui/dist/assets/fira-sans-vietnamese-500-normal-UV7M6ot_.woff +0 -0
  183. package/gui/dist/assets/fira-sans-vietnamese-600-normal-Bxjaclsw.woff +0 -0
  184. package/gui/dist/assets/fira-sans-vietnamese-600-normal-Dh2KAvU8.woff2 +0 -0
  185. package/gui/dist/assets/fira-sans-vietnamese-700-normal-DFi88MGY.woff +0 -0
  186. package/gui/dist/assets/fira-sans-vietnamese-700-normal-j5oLGLJY.woff2 +0 -0
  187. package/gui/dist/assets/index-CwQzep9r.js +413 -0
  188. package/gui/dist/assets/index-DUFjnEFT.css +1 -0
  189. package/gui/dist/assets/theme-BnuhLJ6X.css +1 -0
  190. package/gui/dist/assets/theme-G7EkTZY2.js +30 -0
  191. package/gui/dist/index.html +13 -0
  192. package/package.json +62 -0
@@ -0,0 +1,453 @@
1
+ import { cleanLines, extractProgramIds, matchHeader } from './source-lines.js';
2
+ /**
3
+ * Inventario de lo que el programa toca: ficheros con sus operaciones,
4
+ * bloques EXEC SQL (tablas y cursores) y comandos EXEC CICS.
5
+ *
6
+ * Es extracción literal, no interpretación: se dice QUÉ tabla se nombra y
7
+ * en qué línea, nunca qué significa la consulta. Lo que no se puede
8
+ * resolver contra el fuente aportado (un WRITE de un registro cuyo FD está
9
+ * en un copybook ausente) se lista aparte en vez de atribuirse a un
10
+ * fichero inventado (ADR-0003).
11
+ */
12
+ const DIVISION_RE = /^\s*(IDENTIFICATION|ENVIRONMENT|DATA|PROCEDURE)\s+DIVISION/i;
13
+ const SECTION_RE = /^\s*([A-Z][\w-]*)\s+SECTION\s*\.\s*$/i;
14
+ const FILE_CONTROL_RE = /^\s*FILE-CONTROL\s*\./i;
15
+ const FD_RE = /^\s*(?:FD|SD)\s+([A-Za-z][\w-]*)/i;
16
+ const LEVEL_01_RE = /^\s*01\s+([A-Za-z][\w-]*)/i;
17
+ const SELECT_RE = /(?<![\w-])SELECT\s+(?:OPTIONAL\s+)?([A-Za-z][\w-]*)/i;
18
+ const ASSIGN_RE = /(?<![\w-])ASSIGN\s+(?:TO\s+)?([A-Za-z][\w-]*(?:-[\w-]*)*)/i;
19
+ const ORGANIZATION_RE = /(?<![\w-])ORGANIZATION\s+(?:IS\s+)?([A-Za-z][\w-]*)/i;
20
+ const ACCESS_RE = /(?<![\w-])ACCESS\s+(?:MODE\s+)?(?:IS\s+)?([A-Za-z][\w-]*)/i;
21
+ const EXEC_START_RE = /(?<![\w-])EXEC\s+(SQL|CICS)(?![\w-])/i;
22
+ const END_EXEC_RE = /(?<![\w-])END-EXEC(?![\w-])/i;
23
+ // Verbos de E/S de fichero. OPEN y CLOSE aceptan varios ficheros por
24
+ // sentencia; el resto nombra uno solo (fichero o registro).
25
+ const OPEN_RE = /(?<![\w-])OPEN(?![\w-])([^.]*)/i;
26
+ const CLOSE_RE = /(?<![\w-])CLOSE(?![\w-])([^.]*)/i;
27
+ const SINGLE_IO_RE = /(?<![\w-])(READ|WRITE|REWRITE|DELETE|START)\s+([A-Za-z][\w-]*)/gi;
28
+ const OPEN_MODES = new Set(['INPUT', 'OUTPUT', 'I-O', 'EXTEND']);
29
+ // Verbos y palabras de control con los que puede empezar una sentencia:
30
+ // si una línea arranca por uno de ellos, ya no es continuación del
31
+ // OPEN/CLOSE anterior.
32
+ const STATEMENT_START_RE = /^\s*(OPEN|CLOSE|READ|WRITE|REWRITE|DELETE|START|MOVE|PERFORM|IF|ELSE|END-IF|EVALUATE|WHEN|END-EVALUATE|CALL|GO|DISPLAY|ACCEPT|ADD|SUBTRACT|MULTIPLY|DIVIDE|COMPUTE|EXEC|STOP|GOBACK|EXIT|SET|INITIALIZE|STRING|UNSTRING|INSPECT|SEARCH|SORT|RETURN|RELEASE|CANCEL|CONTINUE|UNLOCK)(?![\w-])/i;
33
+ // Palabras que pueden seguir al nombre en un OPEN/CLOSE sin ser ficheros
34
+ const IO_NOISE = new Set(['WITH', 'NO', 'REWIND', 'LOCK', 'FOR', 'REMOVAL', 'UNIT', 'REEL']);
35
+ function unique(values) {
36
+ return [...new Set(values)];
37
+ }
38
+ /** Tablas nombradas por un EXEC SQL. Solo posiciones donde SQL exige un
39
+ * nombre de tabla: los host variables (`:WS-X`) y las subconsultas
40
+ * quedan fuera, así que un `SELECT ... INTO :WS-N FROM T` da solo `T`. */
41
+ function sqlTables(text) {
42
+ const found = [];
43
+ // Juego de caracteres de un identificador DB2 (letras, dígitos, _, $, #, @),
44
+ // no el de COBOL: el guion NO forma parte de un nombre de tabla.
45
+ const name = "[A-Za-z][\\w$#@]*(?:\\.[A-Za-z][\\w$#@]*)?";
46
+ const patterns = [
47
+ new RegExp(`(?<![\\w-])FROM\\s+(${name})`, 'gi'),
48
+ new RegExp(`(?<![\\w-])JOIN\\s+(${name})`, 'gi'),
49
+ new RegExp(`(?<![\\w-])INSERT\\s+INTO\\s+(${name})`, 'gi'),
50
+ new RegExp(`(?<![\\w-])UPDATE\\s+(${name})`, 'gi'),
51
+ ];
52
+ for (const re of patterns) {
53
+ for (const m of text.matchAll(re))
54
+ found.push(m[1].toUpperCase());
55
+ }
56
+ // Una lista `FROM A, B` nombra las dos tablas.
57
+ for (const m of text.matchAll(new RegExp(`(?<![\\w-])FROM\\s+${name}((?:\\s*,\\s*${name})+)`, 'gi'))) {
58
+ for (const part of m[1].split(',')) {
59
+ const trimmed = part.trim();
60
+ if (trimmed !== '')
61
+ found.push(trimmed.toUpperCase());
62
+ }
63
+ }
64
+ return unique(found);
65
+ }
66
+ /** Cursor nombrado por el bloque, si lo hay */
67
+ function sqlCursor(text) {
68
+ const declare = /(?<![\w-])DECLARE\s+([A-Za-z][\w-]*)\s+(?:.*\s+)?CURSOR(?![\w-])/i.exec(text);
69
+ if (declare)
70
+ return { name: declare[1].toUpperCase(), role: 'declare' };
71
+ const open = /(?<![\w-])OPEN\s+([A-Za-z][\w-]*)/i.exec(text);
72
+ if (open)
73
+ return { name: open[1].toUpperCase(), role: 'open' };
74
+ const fetch = /(?<![\w-])FETCH\s+(?:FIRST\s+FROM\s+|NEXT\s+FROM\s+|FROM\s+)?([A-Za-z][\w-]*)/i.exec(text);
75
+ if (fetch)
76
+ return { name: fetch[1].toUpperCase(), role: 'fetch' };
77
+ const close = /(?<![\w-])CLOSE\s+([A-Za-z][\w-]*)/i.exec(text);
78
+ if (close)
79
+ return { name: close[1].toUpperCase(), role: 'close' };
80
+ return undefined;
81
+ }
82
+ /**
83
+ * Comando CICS: el primer token tras CICS, más un segundo token si es una
84
+ * palabra suelta sin paréntesis (`HANDLE CONDITION`). En `SEND MAP('M1')`
85
+ * el MAP lleva valor, así que queda como opción y el comando es `SEND` —
86
+ * es la forma del fuente, no una normalización a la sintaxis del manual.
87
+ */
88
+ function cicsCommand(text) {
89
+ const m = /(?<![\w-])EXEC\s+CICS\s+([A-Za-z][\w-]*)(?:\s+([A-Za-z][\w-]*)(?![\w-])(?!\s*\())?/i.exec(text);
90
+ if (!m)
91
+ return '';
92
+ return m[2] ? `${m[1].toUpperCase()} ${m[2].toUpperCase()}` : m[1].toUpperCase();
93
+ }
94
+ // Opciones CICS que nombran un recurso: si su valor es un data-name en
95
+ // vez de un literal, el recurso real solo se conoce en ejecución.
96
+ const CICS_RESOURCE_KEYS = new Set([
97
+ 'FILE',
98
+ 'DATASET',
99
+ 'PROGRAM',
100
+ 'MAP',
101
+ 'MAPSET',
102
+ 'TRANSID',
103
+ 'QUEUE',
104
+ 'TSQUEUE',
105
+ 'TDQUEUE',
106
+ 'QNAME',
107
+ ]);
108
+ /**
109
+ * Opciones CICS con nombre de recurso: literales tal cual (`FILE(CUSTFILE)`)
110
+ * y, para las opciones de recurso, también los data-name (`FILE(WS-NOMBRE)`)
111
+ * — estos marcan el bloque como dinámico, porque el recurso real no está en
112
+ * el fuente. Las opciones sin literal ni recurso (LENGTH(100), RESP(WS-R))
113
+ * no se listan: no dicen qué toca el programa.
114
+ */
115
+ function cicsOptions(text) {
116
+ const options = [];
117
+ let dynamic = false;
118
+ for (const m of text.matchAll(/(?<![\w-])([A-Za-z][\w-]*)\s*\(\s*(?:'([^']*)'|"([^"]*)"|([A-Za-z][\w-]*))\s*\)/g)) {
119
+ const key = m[1].toUpperCase();
120
+ const literal = m[2] ?? m[3];
121
+ const ident = m[4];
122
+ if (literal !== undefined) {
123
+ options.push(`${key}(${literal})`);
124
+ }
125
+ else if (ident !== undefined && CICS_RESOURCE_KEYS.has(key)) {
126
+ options.push(`${key}(${ident.toUpperCase()})`);
127
+ dynamic = true;
128
+ }
129
+ }
130
+ return { options: unique(options), dynamic };
131
+ }
132
+ /** Sentencias SELECT de FILE-CONTROL, cada una unida hasta su punto final */
133
+ function collectSelects(lines) {
134
+ const files = [];
135
+ let inFileControl = false;
136
+ let buffer = '';
137
+ const flush = () => {
138
+ const stmt = buffer.replace(/\s+/g, ' ').trim();
139
+ buffer = '';
140
+ const select = SELECT_RE.exec(stmt);
141
+ if (!select)
142
+ return;
143
+ const assign = ASSIGN_RE.exec(stmt);
144
+ const organization = ORGANIZATION_RE.exec(stmt);
145
+ const access = ACCESS_RE.exec(stmt);
146
+ files.push({
147
+ name: select[1].toUpperCase(),
148
+ ...(assign ? { assignTo: assign[1].toUpperCase() } : {}),
149
+ ...(organization ? { organization: organization[1].toUpperCase() } : {}),
150
+ ...(access ? { access: access[1].toUpperCase() } : {}),
151
+ records: [],
152
+ operations: [],
153
+ });
154
+ };
155
+ for (const { masked } of lines) {
156
+ if (FILE_CONTROL_RE.test(masked)) {
157
+ inFileControl = true;
158
+ continue;
159
+ }
160
+ if (!inFileControl)
161
+ continue;
162
+ // FILE-CONTROL termina donde empieza otra sección o división.
163
+ if (DIVISION_RE.test(masked) || SECTION_RE.test(masked)) {
164
+ flush();
165
+ inFileControl = false;
166
+ continue;
167
+ }
168
+ // Un SELECT termina en su punto, esté donde esté: partir la línea por
169
+ // puntos permite tanto un SELECT repartido en varias líneas como dos
170
+ // SELECT en la misma.
171
+ const segments = masked.split('.');
172
+ for (let i = 0; i < segments.length; i++) {
173
+ buffer += ' ' + segments[i];
174
+ if (i < segments.length - 1)
175
+ flush();
176
+ }
177
+ }
178
+ flush();
179
+ return files;
180
+ }
181
+ /** Registros 01 bajo cada FD: es lo que permite resolver un WRITE, que
182
+ * nombra el registro y no el fichero. */
183
+ function collectFdRecords(lines) {
184
+ const byFile = new Map();
185
+ let currentFd;
186
+ for (const { masked } of lines) {
187
+ if (DIVISION_RE.test(masked)) {
188
+ currentFd = undefined;
189
+ continue;
190
+ }
191
+ const fd = FD_RE.exec(masked);
192
+ if (fd) {
193
+ currentFd = fd[1].toUpperCase();
194
+ byFile.set(currentFd, []);
195
+ continue;
196
+ }
197
+ if (SECTION_RE.test(masked)) {
198
+ currentFd = undefined;
199
+ continue;
200
+ }
201
+ if (!currentFd)
202
+ continue;
203
+ const record = LEVEL_01_RE.exec(masked);
204
+ if (record)
205
+ byFile.get(currentFd).push(record[1].toUpperCase());
206
+ }
207
+ return byFile;
208
+ }
209
+ /**
210
+ * Extrae el inventario de E/S y bloques EXEC del fuente completo — los
211
+ * EXEC SQL viven tanto en WORKING-STORAGE (DECLARE CURSOR, INCLUDE) como
212
+ * en la PROCEDURE DIVISION, así que se recorre el programa entero.
213
+ */
214
+ export function parseInventory(source) {
215
+ const lines = cleanLines(source);
216
+ // Nombre del nodo de entrada sintético — el mismo criterio que usa el
217
+ // parser de flujo, para que un párrafo implícito se llame igual en las
218
+ // dos vistas y se puedan cruzar.
219
+ const implicitEntry = extractProgramIds(lines)[0]?.name ?? 'MAIN';
220
+ const files = collectSelects(lines);
221
+ const fdRecords = collectFdRecords(lines);
222
+ for (const file of files) {
223
+ file.records = fdRecords.get(file.name) ?? [];
224
+ }
225
+ const byName = new Map(files.map(f => [f.name, f]));
226
+ const byRecord = new Map();
227
+ for (const file of files) {
228
+ for (const record of file.records)
229
+ byRecord.set(record, file);
230
+ }
231
+ const execs = [];
232
+ const unresolvedFileOps = [];
233
+ let inProcedure = false;
234
+ let paragraph;
235
+ // OPEN/CLOSE cuya lista de ficheros sigue abierta en la línea siguiente
236
+ let pendingIo;
237
+ let pendingMode;
238
+ // Un bloque EXEC abierto acumula líneas hasta su END-EXEC. Se guardan
239
+ // las dos versiones: la enmascarada para reconocer verbos y tablas (un
240
+ // "FROM T" dentro de un literal no es una tabla) y la original para el
241
+ // texto legible y los valores literales de las opciones CICS.
242
+ let openExec;
243
+ const record = (target, op) => {
244
+ const file = byName.get(target) ?? byRecord.get(target);
245
+ if (file)
246
+ file.operations.push(op);
247
+ else
248
+ unresolvedFileOps.push({ ...op, target });
249
+ };
250
+ const collapse = (parts) => parts.join(' ').replace(/\s+/g, ' ').trim();
251
+ for (const { body, masked, line } of lines) {
252
+ if (openExec) {
253
+ openExec.parts.push(masked.trim());
254
+ openExec.raw.push(body.trim());
255
+ if (END_EXEC_RE.test(masked)) {
256
+ execs.push(buildExec(openExec.kind, collapse(openExec.parts), collapse(openExec.raw), openExec.line, {
257
+ paragraph: openExec.paragraph,
258
+ implicit: openExec.paragraphImplicit,
259
+ }));
260
+ openExec = undefined;
261
+ }
262
+ continue;
263
+ }
264
+ if (/^\s*PROCEDURE\s+DIVISION/i.test(masked)) {
265
+ inProcedure = true;
266
+ continue;
267
+ }
268
+ const execStart = EXEC_START_RE.exec(masked);
269
+ if (execStart) {
270
+ const kind = execStart[1].toUpperCase() === 'SQL' ? 'sql' : 'cics';
271
+ // Un EXEC en la DATA DIVISION no tiene párrafo. Uno en la PROCEDURE
272
+ // que aparezca antes de la primera cabecera cae en el nodo de
273
+ // entrada sintético, y se marca como tal: el nombre no está en el
274
+ // fuente (ADR-0003).
275
+ const where = inProcedure ? paragraph ?? implicitEntry : undefined;
276
+ const isImplicit = inProcedure && paragraph === undefined;
277
+ if (END_EXEC_RE.test(masked)) {
278
+ execs.push(buildExec(kind, collapse([masked]), collapse([body]), line, {
279
+ paragraph: where,
280
+ implicit: isImplicit,
281
+ }));
282
+ }
283
+ else {
284
+ openExec = {
285
+ kind,
286
+ line,
287
+ parts: [masked.trim()],
288
+ raw: [body.trim()],
289
+ paragraph: where,
290
+ ...(isImplicit ? { paragraphImplicit: true } : {}),
291
+ };
292
+ }
293
+ continue;
294
+ }
295
+ if (!inProcedure)
296
+ continue;
297
+ const header = matchHeader(masked);
298
+ if (header) {
299
+ paragraph = header.name;
300
+ continue;
301
+ }
302
+ const owner = paragraph ?? implicitEntry;
303
+ const ownerImplicit = paragraph === undefined;
304
+ /** Consume la lista de ficheros de un OPEN/CLOSE, actualizando el modo */
305
+ const takeFileList = (verb, text) => {
306
+ for (const token of text.trim().split(/\s+/)) {
307
+ const upper = token.toUpperCase();
308
+ if (upper === '')
309
+ continue;
310
+ if (verb === 'OPEN' && OPEN_MODES.has(upper)) {
311
+ pendingMode = upper;
312
+ continue;
313
+ }
314
+ if (IO_NOISE.has(upper))
315
+ continue;
316
+ record(upper, {
317
+ verb,
318
+ ...(verb === 'OPEN' && pendingMode ? { mode: pendingMode } : {}),
319
+ paragraph: owner,
320
+ ...(ownerImplicit ? { paragraphImplicit: true } : {}),
321
+ line,
322
+ });
323
+ }
324
+ };
325
+ // Un OPEN/CLOSE con varios ficheros suele repartirse en varias líneas
326
+ // ("OPEN INPUT CUST-FILE" / "OUTPUT RPT-FILE"). La continuación se
327
+ // reconoce por descarte: mientras no empiece otro verbo, sigue siendo
328
+ // la lista del OPEN/CLOSE anterior, hasta el punto que lo cierra.
329
+ if (pendingIo) {
330
+ if (STATEMENT_START_RE.test(masked)) {
331
+ pendingIo = undefined;
332
+ }
333
+ else {
334
+ takeFileList(pendingIo, masked.split('.')[0]);
335
+ if (masked.includes('.'))
336
+ pendingIo = undefined;
337
+ continue;
338
+ }
339
+ }
340
+ const open = OPEN_RE.exec(masked);
341
+ if (open) {
342
+ pendingMode = undefined;
343
+ takeFileList('OPEN', open[1]);
344
+ pendingIo = masked.includes('.') ? undefined : 'OPEN';
345
+ }
346
+ const close = CLOSE_RE.exec(masked);
347
+ if (close) {
348
+ takeFileList('CLOSE', close[1]);
349
+ pendingIo = masked.includes('.') ? undefined : 'CLOSE';
350
+ }
351
+ for (const m of masked.matchAll(SINGLE_IO_RE)) {
352
+ record(m[2].toUpperCase(), {
353
+ verb: m[1].toUpperCase(),
354
+ paragraph: owner,
355
+ ...(ownerImplicit ? { paragraphImplicit: true } : {}),
356
+ line,
357
+ });
358
+ }
359
+ }
360
+ // Un EXEC sin END-EXEC (fuente truncado) se registra igual: es un hecho
361
+ // del fuente aportado, y ocultarlo perdería una tabla o un comando.
362
+ if (openExec) {
363
+ execs.push(buildExec(openExec.kind, collapse(openExec.parts), collapse(openExec.raw), openExec.line, {
364
+ paragraph: openExec.paragraph,
365
+ implicit: openExec.paragraphImplicit,
366
+ }));
367
+ }
368
+ const tables = unique(execs.flatMap(e => e.tables));
369
+ const cursors = new Map();
370
+ for (const exec of execs) {
371
+ if (exec.kind !== 'sql' || !exec.cursor)
372
+ continue;
373
+ const entry = cursors.get(exec.cursor) ?? {
374
+ name: exec.cursor,
375
+ declared: false,
376
+ opened: false,
377
+ fetched: false,
378
+ closed: false,
379
+ tables: [],
380
+ };
381
+ const verb = exec.verb;
382
+ if (verb === 'DECLARE') {
383
+ entry.declared = true;
384
+ entry.tables = unique([...entry.tables, ...exec.tables]);
385
+ }
386
+ if (verb === 'OPEN')
387
+ entry.opened = true;
388
+ if (verb === 'FETCH')
389
+ entry.fetched = true;
390
+ if (verb === 'CLOSE')
391
+ entry.closed = true;
392
+ cursors.set(exec.cursor, entry);
393
+ }
394
+ const cicsCounts = new Map();
395
+ for (const exec of execs) {
396
+ if (exec.kind !== 'cics')
397
+ continue;
398
+ cicsCounts.set(exec.verb, (cicsCounts.get(exec.verb) ?? 0) + 1);
399
+ }
400
+ return {
401
+ files,
402
+ unresolvedFileOps,
403
+ execs,
404
+ tables,
405
+ cursors: [...cursors.values()],
406
+ cicsCommands: [...cicsCounts].map(([command, count]) => ({ command, count })),
407
+ };
408
+ }
409
+ /**
410
+ * `masked` es la versión con los literales en blanco: de ahí salen verbos,
411
+ * tablas y cursores, para que un `FROM ORDERS` escrito dentro de una
412
+ * cadena no se cuele como tabla. `raw` es el texto real: de ahí salen el
413
+ * texto legible del bloque y los valores literales de las opciones CICS,
414
+ * que es precisamente lo que interesa (`FILE('ACCTFILE')`).
415
+ */
416
+ function buildExec(kind, masked, raw, line, where) {
417
+ const location = {
418
+ ...(where.paragraph ? { paragraph: where.paragraph } : {}),
419
+ ...(where.implicit ? { paragraphImplicit: true } : {}),
420
+ };
421
+ if (kind === 'cics') {
422
+ const { options, dynamic } = cicsOptions(raw);
423
+ return {
424
+ kind,
425
+ verb: cicsCommand(masked),
426
+ ...location,
427
+ line,
428
+ text: raw,
429
+ tables: [],
430
+ options,
431
+ ...(dynamic ? { dynamic: true } : {}),
432
+ };
433
+ }
434
+ const verbMatch = /(?<![\w-])EXEC\s+SQL\s+([A-Za-z][\w-]*)/i.exec(masked);
435
+ const verb = verbMatch ? verbMatch[1].toUpperCase() : '';
436
+ const cursor = sqlCursor(masked);
437
+ // SQL dinámico: la sentencia viaja en una host variable, así que no hay
438
+ // tabla que nombrar en el fuente. Se marca en vez de fingir que no toca
439
+ // nada (podría tocar cualquier tabla).
440
+ const dynamic = verb === 'PREPARE' || verb === 'EXECUTE';
441
+ return {
442
+ kind,
443
+ verb,
444
+ ...location,
445
+ line,
446
+ text: raw,
447
+ tables: sqlTables(masked),
448
+ options: [],
449
+ ...(cursor ? { cursor: cursor.name } : {}),
450
+ ...(dynamic ? { dynamic: true } : {}),
451
+ };
452
+ }
453
+ //# sourceMappingURL=inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory.js","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Une líneas de continuación COBOL (columna 7 = '-' o carácter no blanco
3
+ * en área A tras un punto y aparte) en sentencias lógicas. Reconoce el
4
+ * inicio de una sentencia nueva por nivel numérico, COPY o EXEC SQL —
5
+ * las tres formas de sentencia que aparecen en un copybook.
6
+ *
7
+ * Detecta formato fijo vs libre igual que el lado de flujo/inventario
8
+ * (`isFixedFormat`): en fijo se recortan las columnas de secuencia (1-6) e
9
+ * identificación (73-80) y el indicador va en la col. 7; en libre el código
10
+ * ocupa la línea entera y recortar columnas destrozaría los nombres (un
11
+ * `01 WS-REC.` en col. 1 se quedaría en `S-REC.`). Sin esta distinción, la
12
+ * DATA DIVISION en formato libre se parseaba a un esquema vacío mientras el
13
+ * flujo sí se leía — una inconsistencia dentro del propio motor.
14
+ */
15
+ export declare function joinContinuations(lines: string[]): string[];
package/dist/lines.js ADDED
@@ -0,0 +1,53 @@
1
+ import { isFixedFormat } from './source-lines.js';
2
+ /**
3
+ * Une líneas de continuación COBOL (columna 7 = '-' o carácter no blanco
4
+ * en área A tras un punto y aparte) en sentencias lógicas. Reconoce el
5
+ * inicio de una sentencia nueva por nivel numérico, COPY o EXEC SQL —
6
+ * las tres formas de sentencia que aparecen en un copybook.
7
+ *
8
+ * Detecta formato fijo vs libre igual que el lado de flujo/inventario
9
+ * (`isFixedFormat`): en fijo se recortan las columnas de secuencia (1-6) e
10
+ * identificación (73-80) y el indicador va en la col. 7; en libre el código
11
+ * ocupa la línea entera y recortar columnas destrozaría los nombres (un
12
+ * `01 WS-REC.` en col. 1 se quedaría en `S-REC.`). Sin esta distinción, la
13
+ * DATA DIVISION en formato libre se parseaba a un esquema vacío mientras el
14
+ * flujo sí se leía — una inconsistencia dentro del propio motor.
15
+ */
16
+ export function joinContinuations(lines) {
17
+ const logical = [];
18
+ const fixed = isFixedFormat(lines);
19
+ for (const raw of lines) {
20
+ // Columna 7 = indicador, columnas 8-72 = programa, 73-80 = zona de
21
+ // identificación que el compilador ignora (p. ej. "CM2014.2" en la
22
+ // suite NIST). Recortarla evita que un VALUE o un PIC se traguen esa
23
+ // basura y que la detección de fin de sentencia por punto se rompa. En
24
+ // formato libre no hay columnas que recortar.
25
+ const line = fixed ? (raw.length > 6 ? raw.slice(6, 72) : raw) : raw;
26
+ const trimmed = line.trimStart();
27
+ if (trimmed === '' || trimmed.startsWith('*'))
28
+ continue;
29
+ // Columna 7 = '-': continuación explícita — siempre se une a la
30
+ // anterior, aunque esta acabara en punto (p. ej. un literal cuyo
31
+ // texto termina en '.' y sigue en la línea siguiente). Solo es
32
+ // indicador en la col. 7 del formato fijo; en libre una sentencia no
33
+ // empieza por '-'.
34
+ const explicitContinuation = fixed && line[0] === '-';
35
+ const startsNewStatement = /^(\d{1,2}\s+|COPY\b|EXEC\s+SQL\b)/i.test(trimmed);
36
+ // El punto cierra la sentencia COBOL: si la lógica anterior ya terminó
37
+ // en punto, esta línea empieza una nueva aunque no parezca "de datos".
38
+ // Sin esta regla, en un programa completo la última cláusula VALUE de
39
+ // un nivel 88 se tragaría las divisiones siguientes como continuación.
40
+ const previousClosed = logical.length > 0 && /\.\s*$/.test(logical[logical.length - 1]);
41
+ if (!explicitContinuation && (startsNewStatement || previousClosed || logical.length === 0)) {
42
+ logical.push(trimmed);
43
+ }
44
+ else if (logical.length === 0) {
45
+ logical.push(trimmed.replace(/^-\s*/, ''));
46
+ }
47
+ else {
48
+ logical[logical.length - 1] += ' ' + trimmed.replace(/^-\s*/, '');
49
+ }
50
+ }
51
+ return logical;
52
+ }
53
+ //# sourceMappingURL=lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lines.js","sourceRoot":"","sources":["../src/lines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAe;IAC/C,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,CAAA;IAElC,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,mEAAmE;QACnE,mEAAmE;QACnE,qEAAqE;QACrE,uEAAuE;QACvE,8CAA8C;QAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;QAEhC,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAQ;QAEvD,gEAAgE;QAChE,iEAAiE;QACjE,+DAA+D;QAC/D,qEAAqE;QACrE,mBAAmB;QACnB,MAAM,oBAAoB,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,CAAA;QACrD,MAAM,kBAAkB,GAAG,oCAAoC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC7E,uEAAuE;QACvE,uEAAuE;QACvE,sEAAsE;QACtE,uEAAuE;QACvE,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,CAAA;QAExF,IAAI,CAAC,oBAAoB,IAAI,CAAC,kBAAkB,IAAI,cAAc,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YAC5F,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACvB,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;QAC5C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;QACnE,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { LinkedFlow } from './types.js';
2
+ /**
3
+ * Encadena varios programas COBOL: extrae el flujo de cada uno y resuelve
4
+ * qué CALL cruzan de un programa a otro de los aportados.
5
+ *
6
+ * Reglas de honestidad (ADR-0003):
7
+ * - Un CALL dinámico (`CALL WS-VARIABLE`) NUNCA se resuelve, aunque exista
8
+ * un programa con ese nombre: el destino real depende del valor de la
9
+ * variable en ejecución, y elegir uno sería inventar el flujo.
10
+ * - Un CALL literal a un programa no aportado se marca como no resuelto y
11
+ * se lista en `missingPrograms` — eso le dice al usuario exactamente qué
12
+ * fuente le falta por bajar del PDS.
13
+ *
14
+ * `sources` mapea nombre de fichero -> contenido. La identidad de cada
15
+ * programa es su PROGRAM-ID si lo declara; si no, el nombre del fichero.
16
+ */
17
+ export declare function linkPrograms(sources: Map<string, string>): LinkedFlow;
package/dist/linker.js ADDED
@@ -0,0 +1,56 @@
1
+ import { parseFlow } from './flow-parser.js';
2
+ /** COBOL es case-insensitive: los nombres de programa se comparan en mayúsculas */
3
+ function key(name) {
4
+ return name.toUpperCase();
5
+ }
6
+ /**
7
+ * Encadena varios programas COBOL: extrae el flujo de cada uno y resuelve
8
+ * qué CALL cruzan de un programa a otro de los aportados.
9
+ *
10
+ * Reglas de honestidad (ADR-0003):
11
+ * - Un CALL dinámico (`CALL WS-VARIABLE`) NUNCA se resuelve, aunque exista
12
+ * un programa con ese nombre: el destino real depende del valor de la
13
+ * variable en ejecución, y elegir uno sería inventar el flujo.
14
+ * - Un CALL literal a un programa no aportado se marca como no resuelto y
15
+ * se lista en `missingPrograms` — eso le dice al usuario exactamente qué
16
+ * fuente le falta por bajar del PDS.
17
+ *
18
+ * `sources` mapea nombre de fichero -> contenido. La identidad de cada
19
+ * programa es su PROGRAM-ID si lo declara; si no, el nombre del fichero.
20
+ */
21
+ export function linkPrograms(sources) {
22
+ const programs = [];
23
+ for (const [sourceName, text] of sources) {
24
+ const flow = parseFlow(text);
25
+ const fallback = sourceName.replace(/\.[^.]+$/, '');
26
+ programs.push({
27
+ name: flow.programId ?? fallback,
28
+ sourceName,
29
+ flow,
30
+ });
31
+ }
32
+ const byName = new Set(programs.map(p => key(p.name)));
33
+ const calls = [];
34
+ const missingPrograms = [];
35
+ for (const program of programs) {
36
+ for (const edge of program.flow.edges) {
37
+ if (edge.kind !== 'call')
38
+ continue;
39
+ const dynamic = edge.dynamic === true;
40
+ const resolved = !dynamic && byName.has(key(edge.to));
41
+ if (!dynamic && !resolved && !missingPrograms.includes(edge.to)) {
42
+ missingPrograms.push(edge.to);
43
+ }
44
+ calls.push({
45
+ fromProgram: program.name,
46
+ fromParagraph: edge.from,
47
+ toProgram: edge.to,
48
+ resolved,
49
+ dynamic,
50
+ line: edge.line,
51
+ });
52
+ }
53
+ }
54
+ return { programs, calls, missingPrograms };
55
+ }
56
+ //# sourceMappingURL=linker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linker.js","sourceRoot":"","sources":["../src/linker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAG5C,mFAAmF;AACnF,SAAS,GAAG,CAAC,IAAY;IACvB,OAAO,IAAI,CAAC,WAAW,EAAE,CAAA;AAC3B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY,CAAC,OAA4B;IACvD,MAAM,QAAQ,GAAoB,EAAE,CAAA;IAEpC,KAAK,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QACnD,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,IAAI,CAAC,SAAS,IAAI,QAAQ;YAChC,UAAU;YACV,IAAI;SACL,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACtD,MAAM,KAAK,GAAuB,EAAE,CAAA;IACpC,MAAM,eAAe,GAAa,EAAE,CAAA;IAEpC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAQ;YAElC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,KAAK,IAAI,CAAA;YACrC,MAAM,QAAQ,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;YAErD,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;gBAChE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC/B,CAAC;YAED,KAAK,CAAC,IAAI,CAAC;gBACT,WAAW,EAAE,OAAO,CAAC,IAAI;gBACzB,aAAa,EAAE,IAAI,CAAC,IAAI;gBACxB,SAAS,EAAE,IAAI,CAAC,EAAE;gBAClB,QAAQ;gBACR,OAAO;gBACP,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,CAAA;AAC7C,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { FlowEdge, FlowResult, LinkedFlow } from './types.js';
2
+ /**
3
+ * Etiqueta legible de una arista de flujo. Vive en el motor, no en cada
4
+ * superficie, para que el export Mermaid y el canvas de la GUI digan
5
+ * exactamente lo mismo de la misma arista (ADR-0002: la GUI depende del
6
+ * motor, nunca al revés).
7
+ */
8
+ export declare function flowEdgeLabel(edge: FlowEdge): string;
9
+ /**
10
+ * Renderiza los hechos de flujo como diagrama Mermaid (flowchart TD).
11
+ * Es una proyección directa del FlowResult: cada nodo y cada arista del
12
+ * diagrama proviene de un hecho verificado por el parser, y las marcas de
13
+ * fidelidad viajan con él — el nodo de entrada implícito se declara como
14
+ * sintético, un fuente en modo fragmento lleva su aviso visible, y un
15
+ * destino que no existe en el fuente se marca como no encontrado.
16
+ * Formas: párrafos como rectángulos, entrada implícita como estadio,
17
+ * secciones como rectángulo doble, programas externos (CALL) como
18
+ * subrutina.
19
+ */
20
+ export declare function flowToMermaid(flow: FlowResult): string;
21
+ /**
22
+ * Renderiza la cadena entre programas como diagrama Mermaid: un nodo por
23
+ * programa y una arista por CALL que cruza la frontera. Igual que el resto
24
+ * de salidas, refleja los hechos tal cual: los programas no aportados y
25
+ * los destinos dinámicos se marcan, nunca se resuelven a ciegas.
26
+ */
27
+ export declare function linkedFlowToMermaid(linked: LinkedFlow): string;