import { createRequire } from 'node:module'; import { existsSync } from 'node:fs'; import { dirname, join } from 'node:path'; import type { LanguageAdapter } from './types'; import { javascriptAdapter } from './languages/javascript'; import { typescriptAdapter, tsxAdapter } from './languages/typescript'; import { pythonAdapter } from './languages/python'; import { goAdapter } from './languages/go'; import { rustAdapter } from './languages/rust'; import { svelteAdapter } from './languages/svelte'; const require = createRequire(import.meta.url); const adapters = [typescriptAdapter, tsxAdapter, javascriptAdapter, pythonAdapter, goAdapter, rustAdapter, svelteAdapter]; const registry = new Map(); for (const adapter of adapters) for (const extension of adapter.extensions) registry.set(extension, adapter); export function adapterFor(path: string): LanguageAdapter | undefined { const dot = path.lastIndexOf('.'); return dot < 0 ? undefined : registry.get(path.slice(dot).toLowerCase()); } export function supportedExtensions(): string[] { return [...registry.keys()].sort(); } /** * Directory holding the Tree-sitter WASM assets shipped beside a `bun --compile` * native binary. `SHARD_TREE_SITTER_DIR` lets a deployment point elsewhere; * otherwise it is `/tree-sitter`. `process.argv[0]` is the * resolved executable path even for a `--compile` binary (its `argv[1]` is the * `/$bunfs/root/` virtual entry, which is NOT a directory to resolve against). */ export function bundledTreeSitterDir(): string { return process.env.SHARD_TREE_SITTER_DIR ?? join(dirname(process.argv[0] ?? process.cwd()), 'tree-sitter'); } export function grammarPath(name: string): string { // Prefer a grammar shipped beside the native binary; keep package resolution // as the development fallback (node_modules/tree-sitter-wasms/out/...). const candidate = join(bundledTreeSitterDir(), `tree-sitter-${name}.wasm`); if (existsSync(candidate)) return candidate; return require.resolve(`tree-sitter-wasms/out/tree-sitter-${name}.wasm`); } /** * Resolve the `web-tree-sitter` *runtime* wasm (`tree-sitter.wasm` — the * emscripten glue, distinct from the `tree-sitter-.wasm` grammars). The * emscripten loader's default `locateFile` uses the bundled module's `__dirname`, * which a `bun --compile` binary bakes in as the BUILD-TIME path * (`…/node_modules/web-tree-sitter/`); on a deployed host that path does not exist * and every `Parser.init()` aborts with * `ENOENT: …/node_modules/web-tree-sitter/tree-sitter.wasm`. Prefer the wasm * shipped beside the binary (see {@link bundledTreeSitterDir}); fall back to the * package's own file in development. */ export function runtimeWasmPath(): string { const candidate = join(bundledTreeSitterDir(), 'tree-sitter.wasm'); if (existsSync(candidate)) return candidate; return require.resolve('web-tree-sitter/tree-sitter.wasm'); }