Skip to content

TypeScript API

TypeScriptAnalysis exposes a typed symbol table, classes, interfaces, enums, decorators, and a call graph through nearly the same API as Java and Python. The symbol table and the call graph are stable, and CLDK 2.0 adds the dataflow graphs and framework entrypoint detection. The backend also analyzes JavaScript sources.

CLDK.typescript(project_path=...) returns a TypeScriptAnalysis object backed by the codeanalyzer-ts backend, which parses and resolves a project in a single pass with ts-morph (the TypeScript compiler API). The same TypeChecker that builds the symbol table resolves call targets, so call-graph derivation reuses existing resolution.

flowchart LR
    T[TypeScript project] --> A["CLDK.typescript(project_path)"]
    A --> M[ts-morph / TypeChecker]
    M --> S[Symbol table]
    M --> CG["Call graph (tsc + RTA)"]

Project path only. TypeScript analysis needs a project directory of valid TypeScript/TSX sources (there is no single-string source_code mode). Pass it as project_path:

from cldk import CLDK
from cldk.analysis import AnalysisLevel
analysis = CLDK.typescript(
project_path="/path/to/ts/project",
analysis_level=AnalysisLevel.call_graph, # required for the call graph
)
print(analysis.get_classes()) # -> dict[str, TSClass]
graph = analysis.get_call_graph() # -> networkx.DiGraph

Entrypoint detection

CLDK 2.0 answers framework entrypoints with get_entrypoints(), get_entrypoint_classes(), and get_entrypoint_coverage(). The shipped rules detect a framework only when the project declares it as a dependency. CLDK 1.x had get_entry_point_methods() and get_service_entry_point_methods(), which raised NotImplementedError, and CLDK 2.0 removes both. To analyze TypeScript at scale through a shared Neo4j graph, see Analysis at scale.

Source on GitHub cldk 2.0.0rc8

API reference generated from cldk 2.0.0rc8.

TypeScript analysis facade.

Thin, read-only query layer over the canonical TSApplication produced by the codeanalyzer-typescript backend. Mirrors the method vocabulary of JavaAnalysis / PythonAnalysis (there is no shared base class, the facades match by convention) and, like those, delegates all indexing and query work to its backend (TSCodeanalyzer).

class TypeScriptAnalysis

Analysis facade for TypeScript projects.

Delegates every query to a backend. Two interchangeable backends exist, both exposing the same method surface:

  • TSCodeanalyzer (default), walks the in-memory pydantic TSApplication / a NetworkX call graph built from analysis.json;
  • TSNeo4jBackend, answers the same get_* queries with Cypher over the graph codeanalyzer-typescript emits with --emit neo4j. Selected by passing neo4j_config.
NameTypeDescription
project_dir
analysis_level
target_files
eager_analysis
backend_configTSBackend
backendTSAnalysisBackend
applicationTSApplication
has_resolution_edgesboolWhether :meth:get_callsites_for can resolve call sites on this backend right now.
get_application_view() -> TSApplication
get_symbol_table() -> Dict[str, TSModule]
get_modules() -> List[TSModule]
get_call_graph() -> nx.DiGraph

NetworkX DiGraph of the call edges, keyed as every other accessor keys things (module file key, type/callable signature, "<module>.<name>" for an external), each node tagged kind (module | class | interface | enum | type_alias | namespace | callable | external) and id. TypeScript’s own endpoints are kept: a module is the caller of its top-level code and a class the callee of new X(); filter on kind == "callable" for Python’s shape.

get_external_symbols() -> Dict[str, TSExternalSymbol]

The phantom (external) call targets, imported/required library members and builtins the call graph points at, keyed "<module>.<name>" (e.g. node:fs.readFileSync, (builtin).push) as the call graph keys them, the wire’s can:// id on the value. Useful for source→sink reachability.

TypeScriptAnalysis.get_synthesized_callables
Section titled “TypeScriptAnalysis.get_synthesized_callables”
get_synthesized_callables() -> Dict[str, TSSynthesizedCallable]

The synthesized anonymous-callback endpoints the call graph points at, Jelly-resolved callbacks the symbol table never names (keyed by their <host>:<line:col> signature). Empty under the tsc-only resolver. Materialized so anonymous call edges don’t dangle.

get_call_graph_json() -> str
get_callers(target_class_name: str, target_method_declaration: str | None = None) -> Dict

Callers of a method, with the connecting call-graph edge metadata, type, weight and provenance, the same three keys get_call_graph puts on an edge. (There is no tags: it was a schema-1.0.0 call-edge field, and schema v2’s TSCallGraphEdge is {src, dst, prov, weight}.) Pass a bare signature as the first argument for module-level functions or external (phantom) targets.

get_callees(source_class_name: str, source_method_declaration: str | None = None) -> Dict

Callees of a method, with the connecting call-graph edge metadata.

get_class_call_graph(qualified_class_name: str, method_signature: str | None = None) -> List[Tuple[str, str]]

Call-graph edges reachable from a class (or one of its methods).

get_class_hierarchy() -> nx.DiGraph

Inheritance/implementation graph: an edge child → base for every base_class.

get_call_sites(qualified_callable_name: str) -> List[TSCallsite]

The rich, syntactic call sites inside a callable (receiver/argument types, resolved callee_signature, source position).

get_calling_lines(target_signature: str) -> List[int]

Sorted source lines anywhere in the project where target_signature is invoked.

get_call_targets(source_signature: str) -> Set[str]

The call targets invoked from a callable, derived from its call sites.

get_classes() -> Dict[str, TSClass]
get_class(qualified_class_name: str) -> TSClass | None
TypeScriptAnalysis.get_classes_by_criteria
Section titled “TypeScriptAnalysis.get_classes_by_criteria”
get_classes_by_criteria(inclusions: List[str] | None = None, exclusions: List[str] | None = None) -> Dict[str, TSClass]
get_interfaces() -> Dict[str, TSInterface]
get_enums() -> Dict[str, TSEnum]
get_enum_members(qualified_enum_name: str) -> List[TSEnumMember]
get_type_aliases() -> Dict[str, TSTypeAlias]
get_functions() -> Dict[str, TSCallable]

Top-level (module/namespace) functions.

get_methods() -> Dict[str, Dict[str, TSCallable]]

All methods grouped by class/interface signature.

get_methods_in_class(qualified_class_name: str) -> Dict[str, TSCallable]
get_method(qualified_class_name: str, qualified_method_name: str) -> TSCallable | None
get_method_parameters(qualified_class_name: str, qualified_method_name: str) -> List[str]
get_constructors(qualified_class_name: str) -> Dict[str, TSCallable]
get_fields(qualified_class_name: str) -> List[TSClassAttribute]
TypeScriptAnalysis.get_interface_properties
Section titled “TypeScriptAnalysis.get_interface_properties”
get_interface_properties(qualified_interface_name: str) -> List[TSClassAttribute]
get_imports() -> Dict[str, List[TSImport]]
get_exports() -> Dict[str, List[TSExport]]
get_variables() -> Dict[str, List[TSVariableDeclaration]]

Module-level variable declarations per file.

get_typescript_file(qualified_name: str) -> str | None

File path declaring the class/interface/enum/callable with the given signature.

get_typescript_module(file_path: str) -> TSModule | None
get_nested_classes(qualified_class_name: str) -> List[TSClass]

Always [] on schema v2, on both backends — permanently, not for want of data. A v2 class node holds only callables and fields: the tree gives a class no types bucket, so no class can nest a class. A class declared inside a callable is the surviving case and reads as TSCallable.inner_classes. Kept because the 1.x surface had it (G3).

get_sub_classes(qualified_class_name: str) -> Dict[str, TSClass]
get_extended_classes(qualified_class_name: str) -> List[str]

The base types a class extends (base_classes minus the implemented interfaces).

TypeScriptAnalysis.get_implemented_interfaces
Section titled “TypeScriptAnalysis.get_implemented_interfaces”
get_implemented_interfaces(qualified_class_name: str) -> List[str]
get_decorators(qualified_callable_name: str) -> List[TSDecorator]

Structured decorators (with arguments) applied to a callable.

get_class_decorators(qualified_class_name: str) -> List[TSDecorator]

Structured decorators (with arguments) applied to a class.

TypeScriptAnalysis.get_methods_with_decorators
Section titled “TypeScriptAnalysis.get_methods_with_decorators”
get_methods_with_decorators(decorators: List[str]) -> Dict[str, List[str]]

Map each requested decorator name to the signatures of callables carrying it. TS decorators are captured structurally, so this is populatable at level 1.

TypeScriptAnalysis.get_classes_with_decorators
Section titled “TypeScriptAnalysis.get_classes_with_decorators”
get_classes_with_decorators(decorators: List[str]) -> Dict[str, List[str]]

Map each requested decorator name to the signatures of classes carrying it.

get_callables_overview() -> List[TSCallableOverview]

Return a lightweight overview of every callable in the project, in one bulk read.

A field-projected alternative to get_methods for enumeration: each TSCallableOverview carries the callable’s signature, owning class/interface (if any), native kind, location, and decorators, but not the full reconstruction (call sites, inner callables, locals). On the Neo4j backend this is a single Cypher query instead of the per-entity fan-out get_methods pays. Body-inspect the few you need afterwards via get_method or get_method_bodies.

Returns:

  • List[TSCallableOverview]: A flat list of TSCallableOverview, one per callable
  • List[TSCallableOverview]: (class/interface methods, module- and namespace-level functions, and nested/inner
  • List[TSCallableOverview]: callables).

See Also get_decorated_callables: The same projection filtered by decorator. get_method_bodies: Bulk source-body fetch for chosen signatures.

Note A get x()/set x() accessor pair shares one signature, so this projection (and the other bulk accessors) can diverge between the local and Neo4j backends on a paired accessor, see #300 <https://github.com/codellm-devkit/python-sdk/issues/300>_.

get_method_bodies(signatures: List[str]) -> Dict[str, str]

Return source bodies for the given callable signatures, in one bulk read.

Parameters:

NameTypeDescription
signaturesList[str]Callable signatures to fetch bodies for (e.g. from get_callables_overview).

Returns:

  • Dict[str, str]: A dict mapping each signature to its source body. Signatures with no matching callable
  • Dict[str, str]: are omitted, as are callables whose code is None (e.g. implicit constructors
  • Dict[str, str]: the analyzer synthesizes with no source text), every returned value is a real str.
TypeScriptAnalysis.get_decorated_callables
Section titled “TypeScriptAnalysis.get_decorated_callables”
get_decorated_callables(markers: List[str]) -> List[TSCallableOverview]

Return overviews of callables decorated with any of the given markers, in one bulk read.

Parameters:

NameTypeDescription
markersList[str]Decorator names to match (e.g. ["Get", "Controller"]).

Returns:

  • List[TSCallableOverview]: A list of TSCallableOverview for every callable
  • List[TSCallableOverview]: carrying at least one of markers as a decorator.

See Also get_callables_overview: The unfiltered projection.

get_callsites_for(signatures: List[str]) -> Dict[str, List[TSCallsite]]

Return the call sites of the given callables, keyed by signature, in one bulk read.

Avoids the per-callable reconstruction fan-out when you need call sites for a specific frontier (e.g. dispatch-edge synthesis or external-reader detection).

Parameters:

NameTypeDescription
signaturesList[str]Callable signatures to fetch call sites for.

Returns:

  • Dict[str, List[TSCallsite]]: A dict mapping each existing signature to its list of
  • Dict[str, List[TSCallsite]]: class:~cldk.models.typescript.TSCallsite (empty if the callable has no call sites).
  • Dict[str, List[TSCallsite]]: Signatures with no matching callable are omitted.
locate(path: str, line: int) -> LocateResult

Resolve a source position to its enclosing callable, with the source in hand.

The single most-needed query for triaging a scanner alert: an alert arrives as file:line and this resolves it to the enclosing callable in one call, rather than get_method, falling back to get_callers, falling back to scanning the symbol table by hand. Four outcomes stay distinguishable, see LocateResult: inside a callable (callable set, plus body when a body node is that precise), at real module scope (module_scope diagnostic), in the gap between two callables (also module scope, never snapped to the nearest callable), or in a file the analysis has no module for (file_not_in_graph).

There is no col parameter. Column-level disambiguation would have to be honoured by both backends to mean anything, and the Neo4j graph projects only start_line / end_line on :TSCallable and :TSBodyNode, so a col would work in-process and be silently ignored over Neo4j. Better absent than documented and inert.

Parameters:

NameTypeDescription
pathstrThe file path. Normalised against the backend’s module keys, so a ./-prefixed or absolute path resolves rather than reading back as file_not_in_graph.
lineintThe 1-based line number.

Returns:

  • LocateResult: class:~cldk.analysis.commons.results.LocateResult carrying the innermost body
  • LocateResult: node, the enclosing callable, its owning class/interface, its module, and the source
  • LocateResult: slice, never an ambiguous empty.

See Also locate_many: The bulk form, the point, not an optimisation.

locate_many(positions: Sequence[Tuple[str, int]]) -> List[LocateResult]

Resolve many (path, line) positions in one round trip, in input order.

Parameters:

NameTypeDescription
positionsSequence[Tuple[str, int]]The (path, line) pairs to resolve, e.g. from a scanner’s alert list.

Returns:

  • List[LocateResult]: class:~cldk.analysis.commons.results.LocateResult per input position, in the
  • List[LocateResult]: same order.

See Also locate: The single-position form.

resolve_callable(name: str, in_class: str | None = None, in_module: str | None = None) -> SliceNode

Resolve a callable name to the one callable it names, in the caller’s vocabulary.

The addressing step every name-taking accessor performs, exposed so a caller can perform it once and keep the answer::

node = ts.resolve_callable("show", in_class="UserController")
node.callable # the full dotted signature, what every other accessor keys by
node.file, node.line

name matches whole or as a dotted suffix; in_class is a dotted suffix of the owning class or interface, in_module a module key ("src/controllers.ts") or the dotted form ("src.controllers"). An anonymous callable is addressed by its <anon@line:col> signature, never by its name, cants calls every one of them "(anonymous)". Ambiguity raises with every candidate; nothing is guessed.

Raises:

  • AmbiguousName: More than one callable matched.
  • SelectorNotInGraph: Nothing matched, naming the argument that missed.
resolve_value(name: str, within: str) -> SliceNode

Resolve a value name inside a callable, in TypeScript, a parameter, to the position that carries it.

The same resolution the dataflow accessors perform on their src, exposed so a caller can check what a name means before asking a question of it::

ts.resolve_value("id", within="UserController.show").kind # "parameter"

Raises:

  • AmbiguousName: within named more than one callable, or name more than one value.
  • SelectorNotInGraph: No such callable, or no such value in it.
get_source(node_id: str) -> str

Return the source text named by node_id, a callable, or one of its body nodes.

Generalises get_method_bodies below callable granularity: node_id is a callable’s signature, a callable’s opaque id, or the body-node id node_id hands back, so a statement or call site locate found can be re-fetched precisely.

Parameters:

NameTypeDescription
node_idstrA callable signature, or an id from locate / resolve_callable, passed back as received, not composed.

Returns:

  • str: The source text, never an ambiguous empty string.

Raises:

  • KeyError: Nothing matches node_id, or it has no recoverable source.
  • NotImplementedError: (Neo4j backend only) node_id names a body node, the attached graph carries no source text below callable granularity.
describe(nodes: Sequence[object]) -> List[SliceNode]

Fill in source for these positions, in one round trip.

Addressing answers where; this answers what, and it is a second call because source is the one field with no size ceiling. Takes anything carrying an address, slice nodes, a locate() result, and gives back the same SliceNode shape with source filled.

Afterwards, source=None means exactly one thing: this position exists and there is no text for it. A ref that names nothing raises instead.

Parameters:

NameTypeDescription
nodesSequence[object]The positions to hydrate. An empty sequence costs no round trip.

Returns:

  • List[SliceNode]: The same positions, in the same order, with source filled where the backend has
  • List[SliceNode]: text for them.

Raises:

  • KeyError: A ref names nothing in this application.
  • TypeError: An element carries no address to look up.
get_cfg(callable: str, in_class: str | None = None, page_size: int = DEFAULT_PAGE_SIZE, cursor: str | None = None) -> EdgePage[TSCfgEdge]

Return one page of the control flow inside one callable, addressed by name.

The graph the analyzer built, not one re-derived here: a conditional’s two successors stay two edges discriminated by kind. Endpoints are the body nodes’ own opaque ids, which get_source and describe both accept::

page = ts.get_cfg("show", in_class="UserController")
page.total # the whole graph's size, on every page
page.complete # False when there is more, with page.next_cursor to fetch it

Parameters:

NameTypeDescription
callablestrThe callable’s name, resolved as by resolve_callable.
in_classstr | NoneDisambiguate by owning class or interface.
page_sizeintMost edges to return.
cursorstr | Nonenext_cursor from a previous page; None starts at the beginning.

Returns:

  • EdgePage[TSCfgEdge]: class:~cldk.analysis.commons.results.EdgePage of
  • EdgePage[TSCfgEdge]: class:~cldk.models.typescript.TSCfgEdge.

Raises:

  • AmbiguousName: More than one callable matched.
  • SelectorNotInGraph: Nothing matched.
  • ValueError: page_size below 1, or a cursor from another page, callable or accessor.
  • CodeanalyzerUsageException: (local backend) built below analysis_level="program_dependency_graph".
get_cdg(callable: str, in_class: str | None = None, page_size: int = DEFAULT_PAGE_SIZE, cursor: str | None = None) -> EdgePage[TSCdgEdge]

Return one page of the control dependence inside one callable.

src is the branching node dst is control dependent on. Arguments, paging and failures are get_cfg’s.

get_ddg(callable: str, in_class: str | None = None, page_size: int = DEFAULT_PAGE_SIZE, cursor: str | None = None) -> EdgePage[TSDdgEdge]

Return one page of the data dependence inside one callable.

Each edge carries the variable it flows and the evidence for it. TypeScript has a single provenance tier: every edge’s prov is ["reaching-defs"], where Python distinguishes ssa / reaching-defs / points-to. Arguments, paging and failures are get_cfg’s.

slice_backward(src: str, within: str, depth: int | None = DEFAULT_DEPTH, max_nodes: int = DEFAULT_MAX_NODES) -> Slice

Return everything the value src depends on, reverse reachability over the SDG.

depth defaults to a finite bound on purpose: a bounded traversal answers a narrower question completely, and total says how much was left out. depth=None asks for the whole cone::

s = ts.slice_backward("id", within="UserController.show")
s.total, s.truncated

Parameters:

NameTypeDescription
srcstrThe value’s name, in TypeScript, a parameter.
withinstrThe callable to look inside. Required: a value name is scoped by its callable.
depthint | NoneMost hops from the seed; None for the whole cone.
max_nodesintMost nodes in the result; a cap that fires is reported, never silent.

Returns:

  • Slice: class:~cldk.analysis.commons.results.Slice, ordered by node id, with source
  • Slice: unhydrated (describe fills it in).

Raises:

  • AmbiguousName: within or src matched more than one thing.
  • SelectorNotInGraph: No such callable, or no such value in it.
  • ValueError: depth is not a positive int, or max_nodes is below 1.
slice_forward(src: str, within: str, depth: int | None = DEFAULT_DEPTH, max_nodes: int = DEFAULT_MAX_NODES) -> Slice

Return everything the value src can affect, the same edges read forward.

Usually the interesting direction for a parameter: nothing flows into one except from its callers. Arguments, bounds and failures are slice_backward’s.

reaches(src: str, dst: str, depth: int | None = None) -> bool

Return whether control can get from one callable to another over the call graph.

The cheap check before asking for the paths themselves. depth is unbounded by default, unlike the slices: a bound on a boolean would collapse “there is no path” and “there is no path within five hops” into the same False.

Parameters:

NameTypeDescription
srcstrThe calling callable’s name.
dststrThe called callable’s name.
depthint | NoneMost call hops, or None for any distance.

Raises:

  • AmbiguousName: Either name matched more than one callable.
  • SelectorNotInGraph: Either matched none.
  • ValueError: depth is not a positive int.
backward_cone(sinks: Sequence[str], depth: int | None = DEFAULT_DEPTH, max_nodes: int = DEFAULT_MAX_NODES) -> Slice

Return every call-graph vertex that can reach any of sinks, “what could get here”.

The accessor to reach for when the sink is a dangerous function and the question is which entry points lead to it. Its nodes are callables and modules: cants makes a module the caller of its own top-level code, so a cone without them would under-report.

Parameters:

NameTypeDescription
sinksSequence[str]The callables to walk back from; a bare string is refused.
depthint | NoneMost call hops back; None for the whole cone.
max_nodesintMost nodes in the result.

Raises:

  • AmbiguousName: A sink matched more than one callable.
  • SelectorNotInGraph: A sink matched none.
  • TypeError: sinks is a bare string.
  • ValueError: sinks is empty, or a bound is out of range.
callers_of(name: str, in_class: str | None = None, in_module: str | None = None) -> List[SliceNode]

Return who calls this, one hop back over the call graph, addressed by name.

The name-based sibling of get_callers, returning SliceNode objects rather than raw dicts. A module is a legitimate caller (kind="module"). [] is unambiguous: a name matching nothing raises.

Raises:

  • AmbiguousName: More than one callable matched.
  • SelectorNotInGraph: Nothing matched.
callees_of(name: str, in_class: str | None = None, in_module: str | None = None) -> List[SliceNode]

Return what this calls, one hop forward, externals included (kind="external").

An external was never analysed, so it has no position: file="" and line=0, with kind saying why. Its callable is the readable "<module>.<name>".

Raises:

  • AmbiguousName: More than one callable matched.
  • SelectorNotInGraph: Nothing matched.
paths_between(src: str, dst: str, src_within: str, dst_within: str, depth: int | None = None, max_paths: int = DEFAULT_MAX_PATHS) -> FlowPaths

Return how one value reaches another, the sequences, where a slice is the set.

Each hop says what justified it: the kind of edge (data / control / argument / return / summary), the variable, and the provenance, which in TypeScript is always ["reaching-defs"]. Only shortest paths are returned.

Two scopes, not one: a value is addressed by a name plus the callable it enters, and a single scope could never find the cross-callable path this accessor exists for. depth is unbounded by default, for reaches’s reason.

Parameters:

NameTypeDescription
srcstrThe value the flow starts at.
dststrThe value it must reach.
src_withinstrThe callable src enters. Required.
dst_withinstrThe callable dst enters. Required.
depthint | NoneMost hops a path may take; None for no bound.
max_pathsintMost paths to return; complete says whether more existed.

Raises:

  • AmbiguousName: A name matched more than one thing.
  • SelectorNotInGraph: A name matched nothing.
  • ValueError: A bound is out of range, or the two endpoints are the same position.
call_paths_between(src: str, dst: str, depth: int | None = None, max_paths: int = DEFAULT_MAX_PATHS) -> FlowPaths

Return how one callable reaches another, the evidence-carrying form of reaches.

Every hop is via="call" with no variable and no provenance: a call is a syntactic fact, and saying so is better than inventing a provenance for it. depth is unbounded by default.

Raises:

  • AmbiguousName: Either name matched more than one callable.
  • SelectorNotInGraph: Either matched nothing.
  • ValueError: A bound is out of range, or src and dst name the same callable.
flows_to_call(src: str, callee: str, within: str, depth: int | None = None) -> bool

Return whether this value reaches any argument of a call to callee.

A dataflow claim, not a control one: a value that merely runs before a call site and feeds none of its arguments is not counted. depth is unbounded by default, a bare False carries no signal that a bound fired.

Parameters:

NameTypeDescription
srcstrThe value, named as a caller would.
calleestrThe called callable.
withinstrThe callable src enters. Required; it scopes src only.
depthint | NoneMost hops; None for no bound.

Raises:

  • AmbiguousName: A name matched more than one thing.
  • SelectorNotInGraph: A name matched nothing.
  • ValueError: depth is not a positive int.
flows_to_argument(src: str, callee: str, arg: str, within: str, depth: int | None = None) -> bool

Return whether this value reaches the argument arg of a call to callee.

The narrower question: a tainted value routinely reaches a function without reaching the parameter that matters. arg is resolved by name, never by position.

Parameters:

NameTypeDescription
srcstrThe value the flow starts at.
calleestrThe called callable.
argstrThe callee’s parameter, by name.
withinstrThe callable src enters. Required; arg is scoped by callee.
depthint | NoneMost hops; None for no bound.

Raises:

  • AmbiguousName: A name matched more than one thing.
  • SelectorNotInGraph: A name matched nothing, including arg naming no parameter of callee, which is a caller error and not a False.
  • ValueError: depth is not a positive int.
taint(sources: Sequence[Tuple[str, str]], sinks: Sequence[Tuple[str, str]], sanitizers: Sequence[Tuple[str, str] | str] = (), depth: int | None = None, max_paths: int = DEFAULT_MAX_PATHS) -> TaintResult

Which of these sources reach which of these sinks, and what to make of the ones that do not.

m sources against n sinks in one traversal, where paths_between proves one flow::

r = ts.taint(
sources=[("userInput", "SearchBar.onChange")],
sinks=[("html", "ResultList.render")],
sanitizers=["SearchBar.sanitizeQuery", ("validated", "SearchBar.onChange")],
)
for path in r.paths:
print(" -> ".join(h.to.name for h in path.hops))
for src, sink in r.exhausted:
print(src, "does not reach", sink)

exhausted is the reason to call this and the only output that can do harm. A pair is listed there when it was searched to exhaustion and nothing was found, the refutation paths_between’s [] cannot give, and only when all three hold: no witness, no diagnostic in unresolved implicating it, and depth was None. An explicit depth empties exhausted by rule, because a bound turns a real long flow into an empty result and a wrong refutation closes a live alert.

complete is the batch’s flag, not the pair’s. While it is False, no absence claim stands on any pair in the result: one blocked pair voids the whole batch’s exhausted.

Sources, sinks and sanitizers are the caller’s to supply: no framework catalogue ships here. A bare str cuts a callable on the path: a transforming sanitizer, named as the wrapper in this application that calls encodeURIComponent, because the bare shape is resolved with resolve_callable. A (name, within) pair cuts a variable inside that callable, which is the only thing that severs a validating guard, since a guard never sits on the data path. Both cuts are applied inside the search, so the result is the shortest unsanitized route.

Every hop’s provenance is reaching-defs, as on paths_between, so a TypeScript witness is argued from its hops rather than from a provenance comparison between two of them.

Parameters:

NameTypeDescription
sourcesSequence[Tuple[str, str]]The values taint enters at, each (name, within).
sinksSequence[Tuple[str, str]]The values it must not reach, addressed the same way.
sanitizersSequence[Tuple[str, str] | str]Bare names cut callables; (name, within) pairs cut variables.
depthint | NoneMost hops; None (the default) for no bound, and exhausted is empty whenever it is set.
max_pathsintMost witnesses per pair, not per call.

Raises:

  • AmbiguousName: A name, or a sanitizer’s within, matched more than one thing.
  • SelectorNotInGraph: A name matched nothing, or a sanitizer’s shape disagrees with what it resolves to.
  • TypeError: sources or sinks is a bare string, which would unpack into a pair.
  • ValueError: A bound is out of range, sources or sinks is empty, or a sanitizer names a blank variable.
get_entrypoints() -> List[TSCallableOverview]

Return overviews of every callable the analyzer marked as an entrypoint.

A CLI command, a route handler, whatever ruleset the entrypoint pass matched. This is where an agent starts a taint question: the callables reachable from outside.

Returns:

  • List[TSCallableOverview]: One overview per marked callable. Empty means the pass found no entrypoint
  • List[TSCallableOverview]: callables, a real fact about the project, not “cannot tell”.

See Also get_entrypoint_classes: The class-level sibling this walk never sees. get_entrypoint_coverage: Whether the detection pass itself had gaps.

get_entrypoint_classes() -> List[TSClassOverview]

Return overviews of every class the analyzer marked as an entrypoint in its own right.

get_entrypoints walks callables only, so a class the rulesets matched with no individually-marked method is invisible to it.

Returns:

  • List[TSClassOverview]: One overview per marked class. Empty means no class carries the mark.

See Also get_entrypoints: The callable-level projection.

TypeScriptAnalysis.get_entrypoint_coverage
Section titled “TypeScriptAnalysis.get_entrypoint_coverage”
get_entrypoint_coverage() -> EntrypointCoverage

Return the entrypoint-detection pass’s own coverage and failure record.

Entrypoint detection under-approximates by design, so silence is its failure mode: get_entrypoints returning [] cannot say whether the pass ran clean or gave up. This is what distinguishes them, the frameworks it recognized, the rulesets it consulted, the near-misses it could not resolve, and the errors it hit.

Returns:

  • EntrypointCoverage: The coverage record. A non-empty diagnostics means the source carries no report at
  • EntrypointCoverage: all, and the other fields are then not “no gaps found” but “nothing to report from”.

See Also get_entrypoints: The accessor whose empty result this disambiguates.

get_artifacts() -> Dict[str, PyArtifact]

Return every non-code artifact the analyzer indexed, keyed by repo-relative path.

package.json, tsconfig.json, a lockfile, a Dockerfile, the files that say what the project depends on and how it is configured, which the code itself never states.

Returns:

  • Dict[str, PyArtifact]: {path: artifact}. Each artifact carries its roles, its text and the config keys it
  • Dict[str, PyArtifact]: defines.

See Also get_dependencies, get_config_keys, get_config_uses.

get_dependencies(direct_only: bool = False, ecosystem: str | None = None, declared_in: str | None = None) -> List[PyDependency]

Return every declared dependency, optionally filtered.

Parameters:

NameTypeDescription
direct_onlyboolKeep only dependencies the project declares itself, not transitive ones.
ecosystemstr | NoneKeep only one packaging ecosystem. Every TypeScript dependency is npm.
declared_instr | NoneKeep only dependencies declared by one artifact (PyDependency.declared_in, e.g. from get_artifacts).

Returns:

  • List[PyDependency]: The matching dependencies.
get_config_keys() -> Dict[str, PyConfigKey]

Return every configuration key the analyzer extracted from the artifacts.

Returns:

  • Dict[str, PyConfigKey]: {id: key}. Each value carries the key’s dotted name, its namespace and its literal
  • Dict[str, PyConfigKey]: value as text.
get_config_uses(key: str | None = None) -> List[PyConfigUseEdge]

Return the resolved edges from a code read to the configuration key it names.

Parameters:

NameTypeDescription
keystr | NoneKeep only edges naming this key by its dotted name (e.g. "compilerOptions.strict"), matched against get_config_keys, since the edge itself carries ids.

Returns:

  • List[PyConfigUseEdge]: The matching edges.

See Also get_config_readers: The same edges, resolved to their reading callables. get_unresolved_config_reads: The reads this cannot show.

TypeScriptAnalysis.get_unresolved_config_reads
Section titled “TypeScriptAnalysis.get_unresolved_config_reads”
get_unresolved_config_reads() -> List[PyConfigRead]

Return every detector-matched configuration read that resolved to no declared key.

get_config_uses can only show reads that landed on a key the analyzer extracted. A read of a key defined somewhere it does not index resolves to nothing, and an empty get_config_uses for some key cannot then distinguish “nothing reads this” from “a read exists and never resolved”. This is that second list.

Returns:

  • List[PyConfigRead]: The unresolved reads, each naming the call site and the callee it went through.
get_config_readers(key: str) -> List[TSCallableOverview]

Return overviews of every callable that reads configuration key key.

get_config_uses hands back opaque body-node ids; this answers the question a caller actually has, which code reads this setting.

Parameters:

NameTypeDescription
keystrThe key’s dotted name, exactly as get_config_uses matches it.

Returns:

  • List[TSCallableOverview]: One overview per reading callable. Empty means no callable reads this key, see
  • List[TSCallableOverview]: meth:get_unresolved_config_reads for the read that never resolved to one.

TypeScript model package, pydantic mirror of codeanalyzer-typescript src/schema/schema.ts (schema v2).

TSCallEdge, TSExternalSymbol, TSSynthesizedCallable, TSClassAttribute, TSEnumMember and TSVariableDeclaration are 1.x names kept as aliases of their v2 classes.

TSCallsite and TSSymbol are 1.x shapes the v2 wire no longer carries, kept importable for the same reason: TSCallsite is still the return type of the call-site accessors, rebuilt from a body node; TSSymbol has no v2 counterpart at all (accessed symbols left the schema) and no accessor returns one — it is an import alias and nothing more.

class TSAnalysis(_Base)

The envelope analysis.json IS.

NameTypeDescription
schema_versionstr
languagestr
max_levelint
k_limitOptional[int]
analyzerTSAnalyzer
applicationTSApplication
class TSAnalyzer(_Base)
NameTypeDescription
namestr
versionstr
class TSApplication(_Base)

The application root: the containment tree plus the app-scope overlays.

NameTypeDescription
idstr
kindLiteral['application']
symbol_tableDict[str, TSModule]
call_graphList[TSCallGraphEdge]
param_inList[TSParamEdge]
param_outList[TSParamEdge]
artifactsDict[str, TSArtifact]
dependenciesList[TSDependency]
unresolved_importsList[TSImportBinding]
config_usesList[TSConfigUse]
config_readsList[TSConfigRead]
external_symbolsOptional[Dict[str, TSExternalNode]]
synthesized_callablesOptional[Dict[str, TSSynthesizedNode]]
entrypoint_reportOptional[TSEntrypointReport]
class TSArtifact(_Base)

A recognized non-code file (config, manifest, CI, container spec).

NameTypeDescription
idstr
kindLiteral['artifact']
pathstr
formatstr
rolesList[str]
size_bytesint
sha256str
sourcestr
extractionstr
config_keysList[TSConfigKey]
class TSBodyNode(_Base)

One entry of a callable’s body{} map, keyed by local id (L:C or @tag).

kind is open: L1 emits call/config_access, L3 adds statement/entry/exit, L4 adds formal_in/formal_out/actual_in/actual_out. callee is the one sanctioned null on the wire (a call node at L1, refined to an id at L2).

NameTypeDescription
idOptional[str]
kindstr
spanOptional[TSSpan]
calleeOptional[str]
ofOptional[str]
parentOptional[str]
method_nameOptional[str]
receiver_exprOptional[str]
receiver_typeOptional[str]
argument_typesList[str]
type_argumentsList[str]
return_typeOptional[str]
is_constructor_callbool
is_optional_chainbool
rootOptional[str]
keyOptional[str]
class TSCallGraphEdge(_Base)

A wire call-graph edge: can:// endpoints, open provenance tokens (tsc, defuse, import, …).

NameTypeDescription
srcstr
dststr
provList[str]
weightint
class TSCallable(_Spanned)

A function / method / constructor / accessor / arrow function.

cfg/cdg/ddg are present from L3, summary from L4; None means the level did not compute them, [] means it did and found none.

NameTypeDescription
idstr
kindstr
namestr
signaturestr
commentsList[TSComment]
decoratorsList[TSDecorator]
parametersList[TSCallableParameter]
type_parametersList[TSTypeParameter]
return_typeOptional[str]
cyclomatic_complexityint
accessibilityOptional[str]
is_staticbool
is_abstractbool
is_asyncbool
is_generatorbool
is_optionalbool
is_readonlybool
is_exportedbool
is_ambientbool
is_implicitbool
accessor_kindOptional[str]
overload_signaturesList[TSOverloadSignature]
bodyDict[str, TSBodyNode]
callablesDict[str, 'TSCallable']
typesDict[str, 'TSType']
cfgOptional[List[TSCfgEdge]]
cdgOptional[List[TSCdgEdge]]
ddgOptional[List[TSDdgEdge]]
summaryOptional[List[TSSummaryEdge]]
entrypointsOptional[List[TSEntrypoint]]
is_entrypointOptional[bool]
inner_callablesDict[str, 'TSCallable']
inner_classesDict[str, 'TSClass']
class TSCallableOverview(BaseModel)

A lightweight projection of one callable, enough to enumerate and filter without the full TSCallable reconstruction (call-sites, inner callables, locals).

Returned set-at-a-time by TypescriptAnalysis.get_callables_overview / TypescriptAnalysis.get_decorated_callables. Body-inspect only the few you need afterwards via TypescriptAnalysis.get_method/TypescriptAnalysis.get_method_bodies.

NameTypeDescription
signaturestr
namestr
owner_signatureOptional[str]
owner_kindOptional[str]
kindstr
pathstr
start_lineint
end_lineint
decoratorsList[str]
is_exportedbool
is_asyncbool
is_staticbool
accessibilityOptional[str]
from_callable(c: TSCallable, owner_signature: Optional[str], owner_kind: Optional[str], path: str) -> TSCallableOverview

Project a TSCallable into a TSCallableOverview.

Parameters:

NameTypeDescription
cTSCallableThe callable to project.
owner_signatureOptional[str]Signature of the declaring class/interface, or None for a module-level function, arrow, or namespace-owned function.
owner_kindOptional[str]The owner’s node kind ("class" or "interface"), or None when owner_signature is None.
pathstrThe declaring module’s symbol-table key (repo-relative path). The v2 callable does not carry it; the caller iterating symbol_table does.

Returns:

  • TSCallableOverview: The projected overview.
class TSClassOverview(BaseModel)

A lightweight projection of one class, the class-level counterpart to TSCallableOverview, for classes codeanalyzer-typescript marked as entrypoints in their own right (TSClass.is_entrypoint), independently of any individual method.

Returned by TypeScriptAnalysis.get_entrypoint_classes. It mirrors PyClassOverview field for field, because the accessor that returns it mirrors PythonAnalysis.get_entrypoint_classes.

Classes only, on purpose. is_entrypoint is declared on all five TypeScript type kinds (TSClass/TSInterface/TSEnum/TSTypeAlias/TSNamespace all inherit it), but the Neo4j projection stamps it onto :TSCallable and :TSClass nodes only, measured on the 1.3.0 reference graph, where those are the only two labels carrying the property at all. Widening this accessor past classes would therefore answer differently on the two backends, which is the one thing the query surface may not do.

NameTypeDescription
signaturestr
namestr
pathstr
start_lineint
end_lineint
decoratorsList[str]
from_class(c: TSClass, path: str) -> TSClassOverview

Project a TSClass into a TSClassOverview.

Parameters:

NameTypeDescription
cTSClassThe class to project.
pathstrThe declaring module’s symbol-table key (repo-relative path). The v2 type does not carry it; the caller iterating symbol_table does.

Returns:

  • TSClassOverview: The projected overview.
class TSCallableParameter(_Base)

A function / method parameter.

NameTypeDescription
idOptional[str]
namestr
typeOptional[str]
default_valueOptional[str]
is_optionalbool
is_restbool
is_readonlybool
accessibilityOptional[str]
decoratorsList[TSDecorator]
start_lineint
end_lineint
start_columnint
end_columnint
class TSCallsite(_Base)

1.x per-call record. Not on the v2 wire (its view is the call node in body{}); kept so callers that construct or type-check against it keep importing.

NameTypeDescription
method_namestr
receiver_exprOptional[str]
receiver_typeOptional[str]
argument_typesList[str]
type_argumentsList[str]
return_typeOptional[str]
callee_signatureOptional[str]
is_constructor_callbool
is_optional_chainbool
start_lineint
start_columnint
end_lineint
end_columnint
class TSCdgEdge(_Base)
NameTypeDescription
srcstr
dststr
class TSCfgEdge(_Base)
NameTypeDescription
srcstr
dststr
kindstr
class TSClass(_Type)

A class declaration.

NameTypeDescription
kindLiteral['class']
callablesDict[str, TSCallable]
fieldsDict[str, TSField]
decoratorsList[TSDecorator]
base_classesList[str]
implements_typesList[str]
is_abstractbool
type_parametersList[TSTypeParameter]
extends_idsList[str]
implements_idsList[str]
methodsDict[str, TSCallable]
attributesDict[str, TSField]
class TSComment(_Base)

A comment or JSDoc block.

NameTypeDescription
contentstr
is_docstringbool
start_lineint
end_lineint
start_columnint
end_columnint
class TSConfigKey(_Base)

A configuration key flattened out of a config-bearing artifact.

NameTypeDescription
idstr
keystr
namespacestr
valueOptional[Union[str, int, float, bool]]
spanOptional[TSSpan]
referencesList[str]
class TSConfigRead(_Base)

A recognized config read that resolved to no declared key.

NameTypeDescription
sitestr
calleestr
keyOptional[str]
reasonstr
provList[str]
class TSConfigUse(_Base)

A recognized config read (global ordinal src) joined to the TSConfigKey it names.

NameTypeDescription
srcstr
dststr
provList[str]
class TSDdgEdge(_Base)
NameTypeDescription
srcstr
dststr
varOptional[str]
provList[str]
class TSDecorator(_Base)

A decorator applied to a class / member / parameter (structured, with arguments).

NameTypeDescription
namestr
qualified_nameOptional[str]
positional_argumentsList[str]
keyword_argumentsDict[str, str]
start_lineint
end_lineint
start_columnint
end_columnint
class TSDependency(_Base)

One third-party dependency, evidence-tagged via prov.

NameTypeDescription
namestr
specstr
kindstr
extrasList[str]
declared_instr
directbool
locked_versionOptional[str]
provides_importsList[str]
provList[str]
class TSEntrypoint(_Base)

One way a callable or class is invoked from outside the application.

NameTypeDescription
frameworkstr
confidencestr
rulestr
rulesetstr
evidenceOptional[str]
routeOptional[str]
http_methodsList[str]
viaOptional[str]
class TSEntrypointReport(_Base)

Coverage and failure record for the entrypoint pass.

NameTypeDescription
frameworks_detectedList[str]
rulesetsList[str]
unresolvedDict[str, int]
errorsList[str]
class TSEnum(_Type)

An enum declaration; its members are fields carrying value.

NameTypeDescription
kindLiteral['enum']
fieldsDict[str, TSField]
is_constbool
membersList[TSField]
class TSExport(_Base)

A TypeScript export / re-export binding.

NameTypeDescription
moduleOptional[str]
resolved_moduleOptional[str]
namestr
aliasOptional[str]
is_type_onlybool
export_kindstr
start_lineint
end_lineint
start_columnint
end_columnint
class TSExternalNode(_Base)

A call target outside the project (library member / builtin), homed on the application as <appId>/@external/<module>/<name>, keyed by that id.

NameTypeDescription
idstr
kindstr
modulestr
namestr
class TSField(_Base)

One open shape for a module variable, a class attribute / interface property, a constructor parameter property and an enum member; each origin sets its own subset. span is absent for constructor parameter properties, in which case the 1.x line/column properties return -1.

NameTypeDescription
idstr
kindLiteral['field']
spanOptional[TSSpan]
namestr
typeOptional[str]
initializerOptional[str]
scopeOptional[str]
declaration_kindOptional[str]
is_exportedbool
commentsList[TSComment]
decoratorsList[TSDecorator]
accessibilityOptional[str]
is_staticbool
is_readonlybool
is_optionalbool
is_abstractbool
valueOptional[str]
start_lineint
end_lineint
start_columnint
end_columnint
class TSImport(_Base)

A TypeScript import binding (one entry per imported name).

NameTypeDescription
modulestr
resolved_moduleOptional[str]
namestr
aliasOptional[str]
is_type_onlybool
import_kindstr
start_lineint
end_lineint
start_columnint
end_columnint
class TSImportBinding(_Base)

A non-relative import no declared dependency accounts for.

NameTypeDescription
modulestr
bound_toOptional[str]
provList[str]
class TSInterface(_Type)

An interface declaration.

NameTypeDescription
kindLiteral['interface']
callablesDict[str, TSCallable]
fieldsDict[str, TSField]
base_classesList[str]
type_parametersList[TSTypeParameter]
call_signaturesList[str]
index_signaturesList[str]
extends_idsList[str]
methodsDict[str, TSCallable]
propertiesDict[str, TSField]
class TSModule(_Base)

A compilation unit (one .ts/.tsx/.js file). The symbol-table key is its repo-relative path; the wire carries no file_path/module_name.

NameTypeDescription
idstr
kindLiteral['module']
spanTSSpan
sourcestr
importsList[TSImport]
exportsList[TSExport]
commentsList[TSComment]
typesDict[str, TSType]
functionsDict[str, TSCallable]
fieldsDict[str, TSField]
is_tsxbool
is_declaration_filebool
content_hashOptional[str]
classesDict[str, TSClass]
interfacesDict[str, TSInterface]
enumsDict[str, TSEnum]
type_aliasesDict[str, TSTypeAlias]
namespacesDict[str, TSNamespace]
variablesList[TSField]
class TSNamespace(_Type)

A namespace / module block, a nested scope with the same buckets as a module.

NameTypeDescription
kindLiteral['namespace']
typesDict[str, 'TSType']
functionsDict[str, TSCallable]
fieldsDict[str, TSField]
classesDict[str, TSClass]
interfacesDict[str, TSInterface]
enumsDict[str, TSEnum]
type_aliasesDict[str, TSTypeAlias]
namespacesDict[str, 'TSNamespace']
variablesList[TSField]
class TSOverloadSignature(_Base)

An overload signature attached to the implementation callable.

NameTypeDescription
parametersList[TSCallableParameter]
return_typeOptional[str]
type_parametersList[TSTypeParameter]
start_lineint
end_lineint
class TSParamEdge(_Base)

An L4 param_in/param_out edge with global ordinal endpoints.

NameTypeDescription
srcstr
dststr
varOptional[str]
class TSSpan(_Base)

start/end are [line, column] (1-based); bytes are [from, to] offsets into the owning module’s source.

NameTypeDescription
startTuple[int, int]
endTuple[int, int]
bytesTuple[int, int]
class TSSummaryEdge(_Base)
NameTypeDescription
srcstr
dststr
varOptional[str]
class TSSymbol(_Base)

1.x accessed-symbol record. Not on the v2 wire; kept importable.

NameTypeDescription
namestr
scopestr
kindstr
typeOptional[str]
qualified_nameOptional[str]
is_builtinbool
linenoint
col_offsetint
class TSSynthesizedNode(_Base)

An entry of the anonymous-callable compatibility index: the map key is the older id (<enclosing>@<line>:<col>) and id the tree id that replaced it; a residual fallback node (no tree home) has key == id and carries name/path/span.

NameTypeDescription
idstr
kindstr
nameOptional[str]
pathOptional[str]
spanOptional[TSSpan]
class TSTypeAlias(_Type)

A type-alias declaration.

NameTypeDescription
kindLiteral['type_alias']
aliased_typestr
type_parametersList[TSTypeParameter]
class TSTypeParameter(_Base)

A generic type parameter, e.g. T extends Base = Default.

NameTypeDescription
namestr
constraintOptional[str]
defaultOptional[str]