August 12, 2026 • Engineering

How we built a deterministic AST engine to fix breaking changes

Building a string-replacement tool is easy. Building an Abstract Syntax Tree transformer that understands TypeScript safely is hard. Here is how we did it.

The Naive Approach: Regex

When we first set out to build Repairo, the goal was simple: if an API vendor changes `client.createCharge()` to `client.charges.create()`, we should just find and replace it in the consumer's codebase.

We quickly realized that regular expressions are fundamentally incapable of understanding code structure. What if the user imported the client under an alias? What if the variable was passed through three different wrapper functions? Regex would either miss the call site entirely or, worse, blindly replace a string inside a completely unrelated comment.

Enter the Abstract Syntax Tree (AST)

To manipulate code safely, you have to understand it the way the compiler does. We rebuilt the core engine using the TypeScript compiler API to parse the consumer repository into an Abstract Syntax Tree.

An AST represents the hierarchical structure of the code. Instead of looking for the string `"client.createCharge"`, we look for a `CallExpression` where the `expression` is a `PropertyAccessExpression` referencing the specific imported type from the vendor's SDK.

Diffing OpenAPI to generate AST Transforms

The real magic happens in the bridge between OpenAPI and the AST. When Repairo detects a breaking change in an OpenAPI spec (e.g., a required field is added to a payload), it generates a structural patch map.

We map the HTTP path and schema change to the corresponding auto-generated SDK method. Our AST engine then walks the tree, finds every `CallExpression` for that method, and structurally modifies the `ObjectLiteralExpression` representing the arguments, injecting the new required field with a `TODO` comment or a safe default.

Why this matters

Because we manipulate the AST, we guarantee that the output is syntactically valid. We preserve the user's formatting, their comments, and their scope.

By taking the hard path, Repairo doesn't just guess at refactors—it calculates them deterministically.

Back home