codesynapt 0.0.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.
- package/CHANGELOG.md +17 -0
- package/LICENSE +686 -0
- package/LICENSES.md +141 -0
- package/README.md +331 -0
- package/electron/main.cjs +2849 -0
- package/electron/plugin-loader.cjs +184 -0
- package/electron/preload.cjs +108 -0
- package/package.json +216 -0
- package/packages/core/bin/codesynapt-mcp.cjs +611 -0
- package/packages/core/bin/codesynapt.cjs +1933 -0
- package/packages/core/legacy.js +300 -0
- package/packages/core/lib/control-server.cjs +1539 -0
- package/packages/core/lib/embedding.cjs +89 -0
- package/packages/core/lib/logger.cjs +63 -0
- package/packages/core/lib/search-cache.cjs +140 -0
- package/packages/core/lib/search-worker.cjs +255 -0
- package/packages/core/lib/search.cjs +211 -0
- package/packages/core/lib/symbol-graph.cjs +402 -0
- package/packages/core/lib/symbol-parser-js.cjs +542 -0
- package/packages/core/lib/symbol-parser-misc.cjs +394 -0
- package/packages/core/lib/symbol-parser-py.cjs +215 -0
- package/packages/core/lib/symbol-parser-treesitter.cjs +658 -0
- package/packages/core/lib/symbol-parser-tsc.cjs +332 -0
- package/packages/core/monorepo.js +310 -0
- package/packages/core/parser.js +2234 -0
- package/packages/core/scanner.js +623 -0
- package/plugin-api/LICENSE +21 -0
- package/plugin-api/README.md +114 -0
- package/plugin-api/docs/01-getting-started.md +197 -0
- package/plugin-api/docs/02-concepts.md +269 -0
- package/plugin-api/docs/api-reference.md +463 -0
- package/plugin-api/docs/troubleshooting.md +332 -0
- package/plugin-api/docs/types/exporter.md +377 -0
- package/plugin-api/docs/types/theme.md +312 -0
- package/plugin-api/examples/hello-world-plugin/README.md +70 -0
- package/plugin-api/examples/hello-world-plugin/main.js +36 -0
- package/plugin-api/examples/hello-world-plugin/manifest.json +12 -0
- package/plugin-api/examples/mermaid-exporter/README.md +125 -0
- package/plugin-api/examples/mermaid-exporter/main.js +58 -0
- package/plugin-api/examples/mermaid-exporter/manifest.json +12 -0
- package/plugin-api/examples/rust-parser/README.md +71 -0
- package/plugin-api/examples/rust-parser/main.js +123 -0
- package/plugin-api/examples/rust-parser/manifest.json +12 -0
- package/plugin-api/examples/sunset-theme/README.md +95 -0
- package/plugin-api/examples/sunset-theme/manifest.json +12 -0
- package/plugin-api/examples/sunset-theme/theme.css +31 -0
- package/plugin-api/package.json +20 -0
- package/plugin-api/types.d.ts +395 -0
- package/public/app.js +6837 -0
- package/public/backend.js +285 -0
- package/public/index.html +647 -0
- package/public/plugin-host.js +321 -0
- package/public/style.css +4359 -0
- package/public/vendor/three.module.js +53044 -0
- package/scripts/competitor-watch.mjs +144 -0
- package/scripts/copy-vendor.js +21 -0
- package/scripts/download-bundled-node.cjs +53 -0
- package/scripts/fuses-after-pack.cjs +34 -0
- package/scripts/license-check.js +119 -0
- package/scripts/perf-test.js +200 -0
- package/server.js +132 -0
package/server.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import http from 'http'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import { fileURLToPath } from 'url'
|
|
6
|
+
import { WebSocketServer } from 'ws'
|
|
7
|
+
import { Scanner } from './packages/core/scanner.js'
|
|
8
|
+
|
|
9
|
+
// ─── CLI ──────────────────────────────────────────────────────
|
|
10
|
+
const args = process.argv.slice(2)
|
|
11
|
+
if (args.includes('-h') || args.includes('--help')) {
|
|
12
|
+
console.log(`
|
|
13
|
+
codesynapt — Real-time 3D file/code dependency visualizer
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
codesynapt <directory> [--port <n>]
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
codesynapt .
|
|
20
|
+
codesynapt ~/projects/myapp --port 8080
|
|
21
|
+
`)
|
|
22
|
+
process.exit(0)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const portIdx = args.indexOf('--port')
|
|
26
|
+
const PORT = portIdx >= 0 ? parseInt(args[portIdx + 1]) : 7777
|
|
27
|
+
const dirArg = args.find((a) => !a.startsWith('--') && a !== String(PORT)) || '.'
|
|
28
|
+
const ROOT = path.resolve(dirArg)
|
|
29
|
+
|
|
30
|
+
if (!fs.existsSync(ROOT) || !fs.statSync(ROOT).isDirectory()) {
|
|
31
|
+
console.error(`✗ Not a directory: ${ROOT}`)
|
|
32
|
+
process.exit(1)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ─── Static file server ───────────────────────────────────────
|
|
36
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
37
|
+
const PUBLIC = path.join(__dirname, 'public')
|
|
38
|
+
|
|
39
|
+
const MIME = {
|
|
40
|
+
'.html': 'text/html; charset=utf-8',
|
|
41
|
+
'.js': 'text/javascript; charset=utf-8',
|
|
42
|
+
'.css': 'text/css; charset=utf-8',
|
|
43
|
+
'.json': 'application/json',
|
|
44
|
+
'.svg': 'image/svg+xml',
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Robust containment check — `startsWith` alone leaks sibling dirs that share
|
|
48
|
+
// a prefix (e.g. /a/public vs /a/public-secret). Resolve and use path.relative.
|
|
49
|
+
const isInside = (base, target) => {
|
|
50
|
+
const rel = path.relative(base, target)
|
|
51
|
+
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const server = http.createServer((req, res) => {
|
|
55
|
+
let rel = req.url.split('?')[0]
|
|
56
|
+
try { rel = decodeURIComponent(rel) } catch {} // normalize %2e%2e etc.
|
|
57
|
+
if (rel === '/') rel = '/index.html'
|
|
58
|
+
const filePath = path.join(PUBLIC, rel)
|
|
59
|
+
if (!isInside(PUBLIC, filePath)) {
|
|
60
|
+
res.writeHead(403); res.end(); return
|
|
61
|
+
}
|
|
62
|
+
fs.readFile(filePath, (err, data) => {
|
|
63
|
+
if (err) { res.writeHead(404); res.end('Not found'); return }
|
|
64
|
+
res.writeHead(200, { 'Content-Type': MIME[path.extname(filePath)] || 'text/plain' })
|
|
65
|
+
res.end(data)
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
// ─── WebSocket ────────────────────────────────────────────────
|
|
70
|
+
const wss = new WebSocketServer({ server })
|
|
71
|
+
const scanner = new Scanner(ROOT)
|
|
72
|
+
|
|
73
|
+
const broadcast = (msg) => {
|
|
74
|
+
const str = JSON.stringify(msg)
|
|
75
|
+
wss.clients.forEach((c) => c.readyState === 1 && c.send(str))
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
scanner.on('snapshot', (data) => broadcast({ type: 'snapshot', ...data, root: ROOT }))
|
|
79
|
+
scanner.on('stats', (s) => broadcast({ type: 'stats', ...s }))
|
|
80
|
+
scanner.on('scan-progress', (p) => broadcast({ type: 'scan-progress', ...p }))
|
|
81
|
+
|
|
82
|
+
wss.on('connection', (ws) => {
|
|
83
|
+
// New client gets current state
|
|
84
|
+
ws.send(JSON.stringify({ type: 'snapshot', ...scanner.snapshot(), root: ROOT }))
|
|
85
|
+
|
|
86
|
+
ws.on('message', (raw) => {
|
|
87
|
+
let msg
|
|
88
|
+
try { msg = JSON.parse(raw) } catch { return }
|
|
89
|
+
|
|
90
|
+
if (msg.type === 'read_file') {
|
|
91
|
+
try {
|
|
92
|
+
const full = path.join(ROOT, msg.id)
|
|
93
|
+
if (!isInside(ROOT, full)) return
|
|
94
|
+
const stat = fs.statSync(full)
|
|
95
|
+
if (stat.size > 500_000) {
|
|
96
|
+
ws.send(JSON.stringify({ type: 'file_content', id: msg.id,
|
|
97
|
+
content: '[file too large to preview]', truncated: true }))
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
const content = fs.readFileSync(full, 'utf8').slice(0, 100_000)
|
|
101
|
+
ws.send(JSON.stringify({ type: 'file_content', id: msg.id, content }))
|
|
102
|
+
} catch (e) {
|
|
103
|
+
ws.send(JSON.stringify({ type: 'file_content', id: msg.id,
|
|
104
|
+
content: `[error: ${e.message}]`, error: true }))
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// ─── Start ────────────────────────────────────────────────────
|
|
111
|
+
// Bind to loopback only — never expose this dev server to the LAN.
|
|
112
|
+
server.listen(PORT, '127.0.0.1', () => {
|
|
113
|
+
console.log(`
|
|
114
|
+
┌─ codesynapt ─────────────────────────────────
|
|
115
|
+
│ root: ${ROOT}
|
|
116
|
+
│ open: http://localhost:${PORT}
|
|
117
|
+
└───────────────────────────────────────────────
|
|
118
|
+
`)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
scanner.start()
|
|
122
|
+
|
|
123
|
+
// A bad file / rejected promise must not kill the dev server.
|
|
124
|
+
process.on('uncaughtException', (e) => console.error('[server] uncaughtException:', e && e.stack || e))
|
|
125
|
+
process.on('unhandledRejection', (e) => console.error('[server] unhandledRejection:', e && e.stack || e))
|
|
126
|
+
|
|
127
|
+
process.on('SIGINT', () => {
|
|
128
|
+
console.log('\nshutting down…')
|
|
129
|
+
scanner.stop()
|
|
130
|
+
wss.close()
|
|
131
|
+
server.close(() => process.exit(0))
|
|
132
|
+
})
|