[Milinda Dias](/content/people/milinda-dias/index.html)

Software Engineer at WunderGraph

December 7, 2025·7min 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](https://cosmo-docs.wundergraph.com/router/gRPC/plugins/ts-plugin/overview) 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](/content/cosmo/federation/schema-composition/index.html) and [schema checks](/content/cosmo/federation/schema-checks/index.html) 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](/content/blog/generative-api-orchestration/index.html).

## 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](https://cosmo-docs.wundergraph.com/tutorial/using-grpc-plugins).

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

1

```undefined
wgc router plugin init planets --language ts
```

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

```undefined
wgc router plugin generate planets
```

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:

```undefined
plugin
├── Dockerfile
├── generated
│   ├── mapping.json
│   ├── service.pb.ts
│   ├── service.proto
│   ├── service.proto.lock.json
│   └── service_grpc.pb.ts
├── package.json
├── tsconfig.json
├── Makefile
├── README.md
├── patches
└── src
	  ├── plugin.ts
	  ├── plugin.test.ts
	  ├── plugin-server.ts
	  └── schema.graphql
```

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](https://cosmo-docs.wundergraph.com/tutorial/using-grpc-plugins) in our docs.

## Frequently Asked Questions (FAQ)

What does the new TypeScript support enable in Cosmo Connect?

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

Do TypeScript plugins offer new capabilities compared to Go plugins?

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

Why did TypeScript plugin support ship after Go?

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.

What steps are required after updating the GraphQL schema inside a plugin?

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

Are TypeScript plugins supported in the Cosmo Cloud Plugin Registry?

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