API Reference
transit (default export)
Section titled “transit (default export)”The main entry point. A singleton Transit instance.
import { transit } from "transit"transit.rust(dir): FunctionProxy
Section titled “transit.rust(dir): FunctionProxy”Scans a Rust source directory and returns a language handle.
const rs = transit.rust("./rust")Parameters:
dir(string) — path to the directory containing Rust source files
Returns: A FunctionProxy — a Proxy-based handle whose properties map to discovered functions.
Behavior:
- Scans the directory with the tree-sitter scanner (Rust grammar)
- Detects
pub fndeclarations as Tier 1 exports - Detects
// transit:fileand// transit:functionmarkers - Loads the compiled native addon (
.nodeor.so) from the directory - Caches the handle — calling
transit.rust(dir)again with the same path returns the same handle
Transport: In-process native addon (via napi-rs). Zero serialization overhead.
transit.java(dir, options?): FunctionProxy
Section titled “transit.java(dir, options?): FunctionProxy”Scans a Java source directory and returns a language handle.
const jv = transit.java("./java/src/main/java")Parameters:
dir(string) — path to the directory containing Java source filesoptions(optional):classpath(string) — Path to compiled Java classes. Transit auto-detects this by looking forbuild/,out/, ortarget/directories, but you can specify it explicitly.mainClass(string) — Fully qualified main class name. Default:transit.java.TransitService.
Returns: A FunctionProxy — same interface as Rust.
Behavior:
- Scans for
publicmethods (text-based detection) - Auto-discovers the compiled classpath by walking up parent directories looking for
build/,out/, ortarget/containingTransitService.class - On first function call, spawns a resident JVM process and connects via TCP
- The Java process stays alive across calls (no cold starts)
Transport: TCP binary protocol on 127.0.0.1 (ephemeral port).
Examples:
// Auto-detect classpathconst jv = transit.java("./java/src/main/java")
// Explicit classpath and main classconst jv = transit.java("./java", { classpath: "./java/build", mainClass: "com.example.App"})transit.python(dir, options?): FunctionProxy
Section titled “transit.python(dir, options?): FunctionProxy”Scans a Python source directory and returns a language handle.
const py = transit.python("./python")Parameters:
dir(string) — path to the directory containing Python source filesoptions(optional):serverScript(string) — Custom entry point filename. Transit auto-detectstransit_service.py,service.py,main.py,app.py,server.py, andfilters.py. Use this if your file has a different name.
Returns: A FunctionProxy — same interface as Rust/Java.
Behavior:
- Scans for top-level
deffunctions andclassmethods (tree-sitter Python grammar) - Detects
# transit:fileand# transit:functionmarkers (Tiers 2/3) - Filters out private methods (
_prefix) - Class methods are qualified as
ClassName.method_name - On first function call, spawns a resident Python process and connects via TCP
- The Python process stays alive across calls (no cold starts)
Transport: TCP binary protocol on 127.0.0.1 (ephemeral port), same protocol as Java.
Examples:
// Auto-detect entry pointconst py = transit.python("./python")
// Custom entry pointconst py = transit.python("./python", { serverScript: "filters.py" })transit.info(): void
Section titled “transit.info(): void”Prints all discovered functions for every registered language handle.
scanFileSync(filePath): ManifestEntry[]
Section titled “scanFileSync(filePath): ManifestEntry[]”Scan a single file and return its manifest entries. Useful for incremental updates in file watchers.
import { scanFileSync } from "transit"const entries = scanFileSync("./src/lib.rs")invalidateFileCache(root, filePath): void
Section titled “invalidateFileCache(root, filePath): void”Remove a specific file from the scan cache (e.g., when a file is deleted).
clearScanCache(root): void
Section titled “clearScanCache(root): void”Clear the entire scan cache for a directory. Forces a full re-scan on next scanDirectory call.
transit.info()// rust (./rust): 3 functions// - process_general [tier 1] (pub fn process_general(job: FileJob) -> ProcessResult)// java (./java): 2 functions// - processSpecialized [tier 1] (public String processSpecialized(String argsJson))transit.config
Section titled “transit.config”The resolved configuration object (always complete with defaults). Read-only.
console.log(transit.config.build.rust.command) // "cargo build --release"console.log(transit.config.build.java.jvmArgs) // ["-Xmx512m"]console.log(transit.config.maxRestarts) // 3transit.configDir
Section titled “transit.configDir”The directory the config was loaded from (usually process.cwd()).
transit.reloadConfig(dir?): void
Section titled “transit.reloadConfig(dir?): void”Reload config from disk. Call this if transit.config.json changes during development.
transit.reloadConfig() // reload from same dirtransit.reloadConfig("/app") // reload from a different dirConfig Functions (from @transit/schema)
Section titled “Config Functions (from @transit/schema)”These are also re-exported from the transit package for convenience.
loadConfig(dir): Required<TransitConfig> | null
Section titled “loadConfig(dir): Required<TransitConfig> | null”Load, validate, and normalize transit.config.json from a directory. Returns null if no config file exists.
import { loadConfig } from "transit"const config = loadConfig("/my/project")loadConfigWithDefaults(dir): Required<TransitConfig>
Section titled “loadConfigWithDefaults(dir): Required<TransitConfig>”Same as loadConfig() but returns full defaults when no config file exists (never returns null).
validateConfig(raw): TransitConfig
Section titled “validateConfig(raw): TransitConfig”Validate a raw JSON object against the Transit schema. Throws ConfigError with a specific message on invalid input.
import { validateConfig } from "transit"try { const config = validateConfig({ build: { rust: { command: 123 } } })} catch (err) { console.error(err.message) // "transit.config.json → build.rust.command: expected a string, got number"}mergeWithDefaults(config): Required<TransitConfig>
Section titled “mergeWithDefaults(config): Required<TransitConfig>”Fill in Transit defaults for missing fields. Does not overwrite explicitly set values.
FunctionProxy
Section titled “FunctionProxy”The object returned by transit.rust(), transit.java(), etc. It’s a JavaScript Proxy that dynamically resolves property access to function calls.
Calling functions
Section titled “Calling functions”// Flat namespace — works when function names are unique across filesconst result = await rs.processGeneral(job)const result = await jv.processSpecialized(data)Qualified calls (file disambiguation)
Section titled “Qualified calls (file disambiguation)”When two files export functions with the same name:
// Use bracket notation with the filename (without extension)await rs["lib"]["processGeneral"](job)await rs["utils"]["processGeneral"](job)Inspection properties
Section titled “Inspection properties”These are available on any FunctionProxy:
| Property | Type | Description |
|---|---|---|
_manifest |
Manifest |
The full scanner manifest |
_bridge |
RuntimeBridge |
The underlying transport bridge |
_lang |
string |
The language name ("rust", "java", etc.) |
_functions() |
() => ManifestEntry[] |
Returns all discovered function entries |
Error handling
Section titled “Error handling”If a function is not found, the proxy throws:
Function "nonexistent" not found in rust. Available: process_general, versionTransitError
Section titled “TransitError”Unified error type for all cross-language calls. Extends Error.
class TransitError extends Error { readonly language: string; // "rust" | "java" | "python" readonly functionName: string; readonly cause: string; // original error message readonly raw: unknown; // original error object}Example:
try { await rs.processJob(data)} catch (err) { if (err instanceof TransitError) { console.error(`Error in ${err.language}: ${err.cause}`) }}ManifestEntry
Section titled “ManifestEntry”interface ManifestEntry { language: string // "rust" | "java" | "javascript" | "python" sourceFile: string // full path to the source file functionName: string // function name as declared in source signature: string // function signature (without body) exportTier: 1 | 2 | 3 // export tier}Manifest
Section titled “Manifest”interface Manifest { entries: ManifestEntry[] generatedAt: number // timestamp (ms since epoch)}Naming conventions
Section titled “Naming conventions”The scanner normalizes names between languages:
- snake_case (Rust):
process_generalis registered under bothprocess_generalandprocessGeneral - camelCase (Java):
processSpecializedis registered asprocessSpecialized - JS/TS: function names are used as-is
All registrations are case-insensitive for the first letter and support both snake_case and camelCase lookup.
Lifecycle
Section titled “Lifecycle”Rust bridge
Section titled “Rust bridge”transit.rust(dir)scans the directory and creates a handle- First function call triggers addon loading (
index.nodeortarget/release/*.so) - Subsequent calls go directly to the loaded addon
- No cleanup needed — the addon lives in-process
Java bridge
Section titled “Java bridge”transit.java(dir)scans the directory and creates a handle- First function call spawns the JVM process
- The process prints
PORT=<port>to stdout on startup - The bridge connects via TCP and starts health checks
- Subsequent calls go through the TCP connection
- If the process crashes, it auto-restarts (up to 3 times)
- Call
jv._bridge.stop()to shut down the Java process
Python bridge
Section titled “Python bridge”transit.python(dir)scans the directory and creates a handle- First function call spawns the Python process
- The process prints
PORT=<port>to stdout on startup - The bridge connects via TCP and starts health checks
- Subsequent calls go through the TCP connection
- If the process crashes, it auto-restarts (up to 3 times)
- Call
py._bridge.stop()to shut down the Python process