@rahmantech/knl-view 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +398 -2
  3. package/bin/knl-view.js +943 -0
  4. package/dist/assets/abnfDiagram-WEYOIA3C-B1gaBaSI.js +1 -0
  5. package/dist/assets/arc-NZ9uRaCl.js +1 -0
  6. package/dist/assets/architecture-WOLXFQ4H-8MalLwTd.js +1 -0
  7. package/dist/assets/architectureDiagram-ZHVYKT53-eZ8i5cl4.js +36 -0
  8. package/dist/assets/array-BifhSqXX.js +1 -0
  9. package/dist/assets/blockDiagram-RJAE7QA3-BavOE8BM.js +140 -0
  10. package/dist/assets/c4Diagram-XDPPPE54-DqMaTAzx.js +38 -0
  11. package/dist/assets/channel-BZ2_TTTJ.js +1 -0
  12. package/dist/assets/chunk-2E7WHVMD-B1Hj2BjJ.js +88 -0
  13. package/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  14. package/dist/assets/chunk-4EMNKR2T-HDscrCiq.js +1 -0
  15. package/dist/assets/chunk-55XCU76K-QR_ARj8I.js +1 -0
  16. package/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  17. package/dist/assets/chunk-7S6XSTFO-B0p3o547.js +2 -0
  18. package/dist/assets/chunk-AQDTSKZB-CCxwNyyA.js +72 -0
  19. package/dist/assets/chunk-DSNLSHJZ-BM5PBFmz.js +129 -0
  20. package/dist/assets/chunk-DUW6YSOI-Dgx8z5s3.js +1 -0
  21. package/dist/assets/chunk-HAGFOTED-UCDVFuN_.js +62 -0
  22. package/dist/assets/chunk-HNE4Q36P-C_1sakp2.js +1 -0
  23. package/dist/assets/chunk-J5ZVWO5B-oDCd-gWO.js +1 -0
  24. package/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  25. package/dist/assets/chunk-NGNAAXSQ-C2Wy9Xmz.js +136 -0
  26. package/dist/assets/chunk-NQOKRVIF-b2D1Z4oK.js +213 -0
  27. package/dist/assets/chunk-UHW7PFBP-CJs0VwBY.js +1 -0
  28. package/dist/assets/chunk-VQ5W62QI-DQxjgE4_.js +1 -0
  29. package/dist/assets/chunk-WQQL4CDK-DcjPeAfQ.js +10 -0
  30. package/dist/assets/chunk-XXDRQBXY-glA0kB5s.js +1 -0
  31. package/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  32. package/dist/assets/chunk-YZO67HFG-DJqACL5V.js +1 -0
  33. package/dist/assets/chunk-ZAUX2LTX-CWfaYtwb.js +1 -0
  34. package/dist/assets/chunk-ZCHMQSOR-BGX73Hho.js +2 -0
  35. package/dist/assets/classDiagram-v2-4MYWR3UA-BpYXPz-e.js +217 -0
  36. package/dist/assets/cose-bilkent-JH36ORCC-e1quKm0Q.js +1 -0
  37. package/dist/assets/cynefin-EF2NZ3EQ-hb3oUmFO.js +1 -0
  38. package/dist/assets/cynefinDiagram-WF24UDRP-CnMQvLqi.js +62 -0
  39. package/dist/assets/cytoscape.esm-BegBNzOV.js +321 -0
  40. package/dist/assets/dagre-NK4GIZVX-BH_Y8y3F.js +4 -0
  41. package/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
  42. package/dist/assets/diagram-CBK3MWTC-Dh79VetZ.js +24 -0
  43. package/dist/assets/diagram-I5XIIV2D-D3u-o1RV.js +24 -0
  44. package/dist/assets/diagram-ODIL2UCW-Bfuo-OKS.js +30 -0
  45. package/dist/assets/diagram-PFBEJUXE-CwHasIbs.js +3 -0
  46. package/dist/assets/diagram-RJA3I4VV-D8ttmuE8.js +41 -0
  47. package/dist/assets/diagram-TYUNFSNR-CzC-8RZ0.js +200 -0
  48. package/dist/assets/dist-CUJYGnnI.js +1 -0
  49. package/dist/assets/ebnfDiagram-V4P3TTPT-9AAhU7In.js +1 -0
  50. package/dist/assets/elk-QONTBCTQ-BgvnD1v_.js +27 -0
  51. package/dist/assets/erDiagram-KYQIGQAA-RLtbiLlP.js +99 -0
  52. package/dist/assets/eventmodeling-K75KTNOO-DVY22vNZ.js +1 -0
  53. package/dist/assets/flowDiagram-IUGLLWBU-l7L5DTb5.js +1 -0
  54. package/dist/assets/ganttDiagram-R7GPNTJY-hHiBGa9W.js +292 -0
  55. package/dist/assets/gitGraph-VSP46ZUC-Cvxay1wh.js +1 -0
  56. package/dist/assets/gitGraphDiagram-PDYL7XHY-AOhlpSqg.js +106 -0
  57. package/dist/assets/graphlib-DS17s2tU.js +1 -0
  58. package/dist/assets/index-CBLNQvK3.js +76 -0
  59. package/dist/assets/index-DLgMsUs2.css +1 -0
  60. package/dist/assets/info-OHQRW6UA-CJ8EUO1m.js +1 -0
  61. package/dist/assets/infoDiagram-MVDRKAX5-DOQu7oYI.js +2 -0
  62. package/dist/assets/init-C-OQMol4.js +1 -0
  63. package/dist/assets/ishikawaDiagram-HPEHV2GE-DcVMvGmx.js +70 -0
  64. package/dist/assets/journeyDiagram-BOSHW7O7-luMeqEqz.js +139 -0
  65. package/dist/assets/kanban-definition-FNSA4HC5-KTZbmrW2.js +89 -0
  66. package/dist/assets/katex-B_JcIwqj.js +257 -0
  67. package/dist/assets/line-CmPHiOVm.js +1 -0
  68. package/dist/assets/linear-DHYlKXBA.js +1 -0
  69. package/dist/assets/mermaid-parser.core-BRDI-WhC.js +7 -0
  70. package/dist/assets/mermaid.core-DPTRaYLy.js +44 -0
  71. package/dist/assets/mindmap-definition-6OY57UG3-70EN5Kw_.js +98 -0
  72. package/dist/assets/ordinal-BDEzSJ7C.js +1 -0
  73. package/dist/assets/packet-JDAUHWVQ-CXWz83oS.js +1 -0
  74. package/dist/assets/path-fybaL0A-.js +1 -0
  75. package/dist/assets/pegDiagram-ECIUJNBX-z5UXKmp4.js +1 -0
  76. package/dist/assets/pie-XZMESJXO-rWI1HIQ7.js +1 -0
  77. package/dist/assets/pieDiagram-GNMPY74T-Bh4Kv3NQ.js +39 -0
  78. package/dist/assets/quadrantDiagram-D57K4MC3-wGM4Ckig.js +7 -0
  79. package/dist/assets/radar-ABXABTNO-CIJ92p5N.js +1 -0
  80. package/dist/assets/railroad-I3PHUGI6-8bxua-Hf.js +1 -0
  81. package/dist/assets/railroad-abnf-LNEFI6M7-B9KVI10m.js +1 -0
  82. package/dist/assets/railroad-ebnf-DWYD2UWJ-Bt73rnyJ.js +1 -0
  83. package/dist/assets/railroad-peg-JR7BVNR7-Cie82UPT.js +1 -0
  84. package/dist/assets/railroadDiagram-Y72NRBL7-C1nmi_tl.js +1 -0
  85. package/dist/assets/requirementDiagram-EQYSW5RA-BSianW40.js +84 -0
  86. package/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
  87. package/dist/assets/sankeyDiagram-SY24JHO5-DIa11-h7.js +40 -0
  88. package/dist/assets/sequenceDiagram-BLEHNHQU-Df5rZKz2.js +169 -0
  89. package/dist/assets/sizeCapture-INFHLROL-3uHXrFqA.js +1 -0
  90. package/dist/assets/src-dClg85lX.js +1 -0
  91. package/dist/assets/stateDiagram-v2-A6IESKWZ-B15PTSvX.js +291 -0
  92. package/dist/assets/swimlanes-B3ENRKFQ-C9mgRCMi.js +1 -0
  93. package/dist/assets/swimlanesDiagram-AYQRV4AK-BGFq4t7O.js +8 -0
  94. package/dist/assets/timeline-definition-JXYKGLGB-BDVf_mIv.js +120 -0
  95. package/dist/assets/treeView-D4JQ5SDB-BbBK-25J.js +1 -0
  96. package/dist/assets/treemap-SAJKECNS-CEDX8apk.js +1 -0
  97. package/dist/assets/usecaseDiagram-WPOLBNNX-D1QkwFF8.js +328 -0
  98. package/dist/assets/vennDiagram-Q3Y3IDCW-5PeGZvEO.js +34 -0
  99. package/dist/assets/wardley-7MLQ67FV-BatN94pO.js +1 -0
  100. package/dist/assets/wardleyDiagram-IVAIDKWA-DyCcDS3Y.js +78 -0
  101. package/dist/assets/xychartDiagram-4URNHDU4-CbCXcRlg.js +7 -0
  102. package/dist/index.html +22 -0
  103. package/package.json +46 -4
  104. package/server/config.js +263 -0
  105. package/server/consensus.js +175 -0
  106. package/server/graph/anchordb_client.js +253 -0
  107. package/server/graph/model.js +157 -0
  108. package/server/graph/parser.js +326 -0
  109. package/server/graph/sources.js +660 -0
  110. package/server/graph/syntax.js +257 -0
  111. package/server/index.js +679 -0
  112. package/server/install.js +97 -0
  113. package/server/map.js +126 -0
  114. package/server/models_registry.js +84 -0
  115. package/server/scaffold.js +376 -0
@@ -0,0 +1,257 @@
1
+ import { createRequire } from 'node:module'
2
+ import { Parser, Language } from 'web-tree-sitter'
3
+
4
+ // Syntax-aware import extraction with tree-sitter (web-tree-sitter, WASM).
5
+ // One uniform parser API for every supported language: adding a language
6
+ // means adding one grammar package and one extraction case. Grammars are
7
+ // lazy-loaded only when the scanned project actually contains files of
8
+ // that language.
9
+ //
10
+ // Extraction returns the raw import specifiers of a file; deciding which
11
+ // of them point inside the project is the resolver's job (sources.js), so
12
+ // this module stays language-shaped, not project-shaped.
13
+
14
+ const require = createRequire(import.meta.url)
15
+
16
+ const GRAMMAR_WASM = {
17
+ javascript: 'tree-sitter-javascript/tree-sitter-javascript.wasm',
18
+ go: 'tree-sitter-go/tree-sitter-go.wasm'
19
+ }
20
+
21
+ /** The JS family shares one grammar; each other extension has its own. */
22
+ export const SYNTAX_LANGUAGES = {
23
+ '.js': 'javascript',
24
+ '.mjs': 'javascript',
25
+ '.cjs': 'javascript',
26
+ '.go': 'go'
27
+ }
28
+
29
+ let initPromise = null
30
+ const languages = new Map() // grammar name -> Language
31
+ const parsers = new Map() // grammar name -> Parser
32
+
33
+ async function languageFor(ext) {
34
+ const name = SYNTAX_LANGUAGES[ext]
35
+ if (languages.has(name)) return languages.get(name)
36
+ initPromise ||= Parser.init()
37
+ await initPromise
38
+ const lang = await Language.load(require.resolve(GRAMMAR_WASM[name]))
39
+ languages.set(name, lang)
40
+ return lang
41
+ }
42
+
43
+ function parserFor(name, lang) {
44
+ if (!parsers.has(name)) {
45
+ const parser = new Parser()
46
+ parser.setLanguage(lang)
47
+ parsers.set(name, parser)
48
+ }
49
+ return parsers.get(name)
50
+ }
51
+
52
+ function firstDescendant(node, type) {
53
+ if (node.type === type) return node
54
+ for (let i = 0; i < node.childCount; i++) {
55
+ const found = firstDescendant(node.child(i), type)
56
+ if (found) return found
57
+ }
58
+ return null
59
+ }
60
+
61
+ /**
62
+ * Raw specifiers from one parsed tree. JS: ESM import/export sources,
63
+ * dynamic import(), and require(). Go: every import_spec path, alias or
64
+ * not. Bare names, URLs, and package paths are returned as-is; filtering
65
+ * to project-internal targets happens in the resolver.
66
+ */
67
+ function specsFromTree(grammar, tree) {
68
+ const specs = []
69
+ const names = []
70
+ const visit = (node) => {
71
+ if (grammar === 'javascript') {
72
+ if (node.type === 'import_statement' || node.type === 'export_statement') {
73
+ const source = node.childForFieldName('source')
74
+ const fragment = source && firstDescendant(source, 'string_fragment')
75
+ if (fragment) specs.push(fragment.text)
76
+ // Local binding names a qualified call may be addressed through:
77
+ // the default import, the namespace alias, and each named import.
78
+ for (let i = 0; i < node.childCount; i++) {
79
+ const clause = node.child(i)
80
+ if (clause.type !== 'import_clause') continue
81
+ for (let j = 0; j < clause.childCount; j++) {
82
+ const part = clause.child(j)
83
+ if (part.type === 'identifier') names.push(part.text)
84
+ else if (part.type === 'namespace_import') {
85
+ for (let k = 0; k < part.childCount; k++) {
86
+ if (part.child(k).type === 'identifier') names.push(part.child(k).text)
87
+ }
88
+ } else if (part.type === 'named_imports') {
89
+ for (let k = 0; k < part.childCount; k++) {
90
+ const specifier = part.child(k)
91
+ if (specifier.type !== 'import_specifier') continue
92
+ const alias = specifier.childForFieldName('alias') || specifier.childForFieldName('name')
93
+ if (alias) names.push(alias.text)
94
+ }
95
+ }
96
+ }
97
+ }
98
+ } else if (node.type === 'call_expression') {
99
+ const fn = node.childForFieldName('function')
100
+ if (fn && (fn.text === 'require' || fn.text === 'import')) {
101
+ const args = node.childForFieldName('arguments')
102
+ const fragment = args && firstDescendant(args, 'string_fragment')
103
+ if (fragment) specs.push(fragment.text)
104
+ // `const x = require('y')` / `const x = await import('y')`: the
105
+ // declarator name is the binding: the visit starts above it, so
106
+ // walk down from any enclosing declarator via field lookup here.
107
+ let parent = node.parent
108
+ while (parent && parent.type === 'await_expression') parent = parent.parent
109
+ if (parent && parent.type === 'variable_declarator') {
110
+ const name = parent.childForFieldName('name')
111
+ if (name) names.push(name.text)
112
+ }
113
+ }
114
+ }
115
+ } else if (grammar === 'go') {
116
+ if (node.type === 'import_spec') {
117
+ const declared = node.childForFieldName('path')
118
+ const fragment = declared && firstDescendant(declared, 'interpreted_string_literal_content')
119
+ if (fragment) {
120
+ const path = fragment.text
121
+ specs.push(path)
122
+ // The name a qualified call uses: the declared alias, or the last
123
+ // path segment (Go's convention when no alias is given).
124
+ const alias = node.childForFieldName('name')
125
+ if (alias) names.push(alias.text)
126
+ else names.push(path.slice(path.lastIndexOf('/') + 1))
127
+ }
128
+ }
129
+ }
130
+ for (let i = 0; i < node.childCount; i++) visit(node.child(i))
131
+ }
132
+ visit(tree.rootNode)
133
+ return { specs, names }
134
+ }
135
+
136
+ /**
137
+ * Parse one file's text with the grammar of its extension and return its
138
+ * raw import specifiers. A syntax error never throws: tree-sitter recovers
139
+ * and whatever imports are well-formed are still extracted.
140
+ * @param {string} ext lowercase extension with the dot, e.g. '.go'
141
+ * @param {string} content file text
142
+ * @returns {Promise<string[]>}
143
+ */
144
+ export async function extractImportSpecifiers(ext, content) {
145
+ return (await extractCode(ext, content)).imports
146
+ }
147
+
148
+ /**
149
+ * Parse one file once and extract everything the sources graph needs:
150
+ *
151
+ * imports raw import specifiers (see extractImportSpecifiers)
152
+ * importNames local names those imports are addressed by: JS bindings
153
+ * (default/namespace/named, plus `const x = require/import`),
154
+ * Go aliases or last path segments. Evidence that a receiver
155
+ * prefix in a qualified call refers to an import.
156
+ * symbols named definitions: { name, kind, line, lines }, line 1-based,
157
+ * lines = height of the definition
158
+ * calls call sites: { name, recv, row }, row 0-based; recv is the
159
+ * receiver/prefix text for qualified calls (recv.method(),
160
+ * pkg.Fn()) and null for plain identifiers
161
+ *
162
+ * Calls are attributed to nothing here; mapping a call to its enclosing
163
+ * symbol is the caller's job (it needs the full symbol list anyway).
164
+ * A syntax error never throws: tree-sitter recovers and whatever is
165
+ * well-formed is still extracted.
166
+ */
167
+ export async function extractCode(ext, content) {
168
+ const lang = await languageFor(ext)
169
+ const grammar = SYNTAX_LANGUAGES[ext]
170
+ const parser = parserFor(grammar, lang)
171
+ const tree = parser.parse(content)
172
+ try {
173
+ const { specs: imports, names: importNames } = specsFromTree(grammar, tree)
174
+ const { symbols, calls } = structureFromTree(grammar, tree)
175
+ return { imports, importNames, symbols, calls }
176
+ } finally {
177
+ tree.delete()
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Named definitions and call sites from one parsed tree. Only definitions
183
+ * that carry an explicit name enter the graph; anonymous helpers are left
184
+ * out, deterministically.
185
+ */
186
+ function structureFromTree(grammar, tree) {
187
+ const symbols = []
188
+ const calls = []
189
+ const pushSymbol = (node, name, kind) => {
190
+ symbols.push({
191
+ name,
192
+ kind,
193
+ line: node.startPosition.row + 1,
194
+ lines: node.endPosition.row - node.startPosition.row + 1
195
+ })
196
+ }
197
+ const visit = (node, cls) => {
198
+ if (grammar === 'javascript') {
199
+ if (node.type === 'function_declaration' || node.type === 'generator_function_declaration') {
200
+ const name = node.childForFieldName('name')
201
+ if (name) pushSymbol(node, name.text, 'function')
202
+ } else if (node.type === 'class_declaration') {
203
+ const name = node.childForFieldName('name')
204
+ if (name) {
205
+ pushSymbol(node, name.text, 'class')
206
+ cls = name.text // class body below walks with this name in scope
207
+ }
208
+ } else if (node.type === 'method_definition') {
209
+ const name = node.childForFieldName('name')
210
+ if (name && name.type === 'property_identifier' && cls) {
211
+ pushSymbol(node, `${cls}.${name.text}`, 'method')
212
+ }
213
+ } else if (node.type === 'lexical_declaration' || node.type === 'variable_declaration') {
214
+ for (let i = 0; i < node.childCount; i++) {
215
+ const declarator = node.child(i)
216
+ if (declarator.type !== 'variable_declarator') continue
217
+ const value = declarator.childForFieldName('value')
218
+ const name = declarator.childForFieldName('name')
219
+ if (value && name && (value.type === 'arrow_function' || value.type === 'function_expression')) {
220
+ pushSymbol(declarator, name.text, 'function')
221
+ }
222
+ }
223
+ }
224
+ } else if (grammar === 'go') {
225
+ if (node.type === 'function_declaration') {
226
+ const name = node.childForFieldName('name')
227
+ if (name) pushSymbol(node, name.text, 'function')
228
+ } else if (node.type === 'method_declaration') {
229
+ const name = node.childForFieldName('name')
230
+ const receiver = node.childForFieldName('receiver')
231
+ const recvType = receiver && firstDescendant(receiver, 'type_identifier')
232
+ if (name && recvType) pushSymbol(node, `${recvType.text}.${name.text}`, 'method')
233
+ } else if (node.type === 'type_spec') {
234
+ const name = node.childForFieldName('name')
235
+ if (name) pushSymbol(node, name.text, 'type')
236
+ }
237
+ }
238
+ if (node.type === 'call_expression' || node.type === 'new_expression') {
239
+ const fn = node.type === 'call_expression'
240
+ ? node.childForFieldName('function')
241
+ : node.childForFieldName('constructor')
242
+ if (fn) {
243
+ if (fn.type === 'identifier') {
244
+ calls.push({ name: fn.text, recv: null, row: node.startPosition.row })
245
+ } else if (fn.type === 'member_expression' || fn.type === 'selector_expression') {
246
+ const named = fn.namedChildren
247
+ if (named.length >= 2) {
248
+ calls.push({ name: named[named.length - 1].text, recv: named[0].text, row: node.startPosition.row })
249
+ }
250
+ }
251
+ }
252
+ }
253
+ for (let i = 0; i < node.childCount; i++) visit(node.child(i), cls)
254
+ }
255
+ visit(tree.rootNode, null)
256
+ return { symbols, calls }
257
+ }