Blog
/
New Feature

TypeScript Plugin Support for Cosmo Connect

cover
Milinda Dias

Milinda Dias

min read

TLDR;

Cosmo Connect now lets you extend the router entirely in TypeScript. If you already work in a TypeScript-heavy codebase, you no longer need to introduce Go or maintain a separate microservice just to add custom logic to your graph. The plugin runs inside the router, is published through Cosmo Cloud, and participates in schema checks like any other subgraph.

Getting Started with TypeScript Plugins

We’ve released TypeScript plugin support for Cosmo Connect. You can now write plugins in TypeScript and load them directly into the router instead of running a separate service. This makes it easier to expose small pieces of logic, legacy API calls, or internal service integrations behind your GraphQL contract.

Until now, Cosmo Connect router plugins were only available in Go. That’s fine if your team already writes Go, but it can be a blocker if you don’t. Most teams already have people writing TypeScript every day, so adding TS support makes the plugin workflow accessible to a lot more users.

A common pattern we see is teams wanting to expose a small piece of logic or wrap a legacy REST API without spinning up another service. With a TypeScript plugin, you can model a GraphQL type, call the internal API, transform the response, and expose it through the router with minimal overhead. It behaves like a subgraph but without the operational cost of deploying one.

Why TypeScript Plugins Matter

TypeScript plugins don’t introduce new capabilities on top of Go plugins. They make the same plugin workflow available to more teams. From the platform’s point of view, this feature is mainly about adoption and accessibility: if your engineers are already comfortable in TypeScript, they can start using plugins immediately without needing to learn Go first.

In a typical federated setup, each subgraph is its own service with its own deployment. With router plugins, you can move some of that logic into the router itself. This is especially useful if you want to create a new "subgraph" but don't want to deploy an entire service just to do it, or if you have a legacy system that does not speak GraphQL and you want to use router plugins to bridge that gap.

When initializing a plugin, you can now pass in ts as a language option, for example wgc router plugin init planets --language ts.

When you publish the plugin and update the subgraph, it goes through the same composition and schema checks as everything else in Cosmo. There are no extra checks specific to TypeScript plugins.

Like with Go plugins, TypeScript plugins are supported in the Cosmo Cloud Plugin Registry, which means you can push plugins directly to Cosmo Cloud, and it will be pulled by all of your running router instances.

Why TypeScript shipped after Go

Cosmo Connect's plugin story started in Go. The router itself is written in Go, and we use HashiCorp's go-plugin library under the hood to load and manage plugins. That setup is very "batteries included" for Go: most of the low-level mechanics are already handled for us.

TypeScript support took longer because there’s no equivalent, fully packaged runtime for TS plugins. We did more of the plumbing ourselves to make TypeScript plugins feel as integrated as Go plugins, which is why Go shipped first.

If you're curious, our CEO Jens wrote about the choice to use HashiCorp's go-plugin in REST in Peace-Connectors Were Never the Right Supergraph Abstraction .

Initializing a TypeScript plugin

Here is a quick example of what it might look like to implement a TypeScript plugin. For a more in-depth walkthrough, see the full plugin tutorial in our docs .

You start by initializing a Cosmo Connect TypeScript plugin using our CLI. This sets up the basic scaffolding which you can build upon.

1

Cosmo Connect works by generating protobuf definitions from your GraphQL schema. Upon scaffolding the plugin, you still need to generate the protobuf definitions. You can run the following command to generate the protobuf definitions from the GraphQL schema as well as generate the protobuf code.

1

After this, you have a minimal plugin project with a basic TypeScript plugin server. You can now start editing the GraphQL schema inside the plugin directory.

After running the above two commands, you should have the following project structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

As mentioned earlier, the hashicorp-go library provides helpers for initializing a plugin server. We implemented similar helpers ourselves in plugin-server.ts, which includes:

  • Initializing gRPC health checks
  • Initializing the handshake between the router and plugin

The plugin.ts file serves as the entrypoint for your plugin. This is also where you will implement the RPC handlers like queryHello and the new queryPlanet method.

Adding a GraphQL schema

Next, update the schema inside the plugin directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Any time you change these types, you need to regenerate the protobuf definitions so the plugin code has access to the new fields and operations.

Generating Protobuf Types

After updating the schema, we need to regenerate the protobuf types:

1

This uses our internal tool protographic to compile the schema into protobuf definitions the router understands.

You can see this by opening service.proto in the generated proto directory before and after running the command.

Before running generate, the proto file only contains the original World and hello RPC definitions. After running it, the new Planet message and RPC (QueryPlanet) appear in service.proto.

Implementing the Plugin Logic

You implement both of these RPC handlers inside src/plugin-server.ts, alongside the existing QueryHello handler.

The existing hello RPC:

1
2
3
4
5
6
7
8
9
10
11
12
13

Then add the new planet RPC for planet: Planet!:

1
2
3
4
5
6
7
8
9
10
11

This is all the business logic. The router will convert the protobuf response back into GraphQL automatically.

In a real application, this is where you'd call an internal HTTP service, legacy API, or database.

Building the Plugin

Build the plugin:

1

A successful build produces a plugin artifact, which you can verify by looking in the bin folder of the plugin. It should contain a binary, whose name will depend on your OS and architecture. For example, if you ran the build command on an M1 Mac, the binary name would be darwin-arm64.

Publishing the plugin

The next step is to publish the plugin to Cosmo Cloud so that your router can pull and use it.

Publish it to Cosmo Cloud:

1

This uploads the plugin to Cosmo Cloud for the specified namespace.

Then update the subgraph metadata:

1

Updating the subgraph metadata triggers routers in the namespace to reload and pull the new plugin, so the new planet field becomes part of the schema they serve.

Querying the router

Once the router reloads and pulls the updated plugin after the subgraph update, the planet field appears in the playground schema.

1
2
3
4
5
6
7

It returns:

1
2
3
4
5
6
7
8
9

Schema Checks and Observability

When you publish the plugin and update the subgraph:

  • Normal composition rules apply
  • No extra checks are required for TypeScript plugins

For observability:

  • You can test your plugin logic directly in the Playground
  • TypeScript plugins currently don’t have built-in tracing

Conclusion

A good first experiment is to create a TypeScript plugin that wraps a single REST endpoint. Define the GraphQL type, map it in your handler, publish the plugin through Cosmo Cloud, update the subgraph metadata, and query it in the Playground. This gives you end-to-end familiarity with the workflow in a real environment.

That’s the full flow: define the schema, generate the protobufs, implement the handlers in TypeScript, build, publish, and the router reloads automatically once the update completes. This makes it much easier to fold small pieces of logic or legacy services into your graph without standing up another subgraph.

For a more in-depth look at building plugins, check out the full plugin tutorial in our docs.


Frequently Asked Questions (FAQ)

It allows you to write router plugins in TypeScript and load them directly into the router instead of running a separate service.

No. They provide the same plugin workflow but make it accessible to teams that prefer or primarily use TypeScript.

The router and plugin system started in Go and use the go-plugin library, which handles most mechanics for Go. TypeScript required more plumbing because there is no equivalent packaged runtime.

You need to regenerate the protobuf definitions so the router can consume the updated fields and operations.

Yes. They can be published to Cosmo Cloud and pulled by all running router instances.


Milinda Dias

Milinda Dias

Software Engineer at WunderGraph

Milinda is a Software Engineer at WunderGraph with specialized experience in developing mobile offline-first applications and backend systems. He applies this range of experience across product work at WunderGraph.