Skip to content

Commit

Permalink
Update docs for Connect-ES v2 (#226)
Browse files Browse the repository at this point in the history
  • Loading branch information
timostamm authored Nov 19, 2024
1 parent 33e32ea commit 7716a64
Show file tree
Hide file tree
Showing 25 changed files with 439 additions and 559 deletions.
20 changes: 19 additions & 1 deletion docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ source for the demo is public as well, so you can
The interesting bit is that we simply import from a generated SDK on the client side:

```go
import { ElizaService } from "@buf/connectrpc_eliza.connectrpc_es/connectrpc/eliza/v1/eliza_connect";
import { ElizaService } from "@buf/connectrpc_eliza.bufbuild_es/connectrpc/eliza/v1/eliza_pb";
```

### Does Connect-Go provide the equivalent of gRPC's `WithBlock` option when connecting to servers?
Expand Down Expand Up @@ -381,6 +381,24 @@ response headers. You can set cookies with the `Set-Cookie` response header—fo
ctx.responseHeader.append("Set-Cookie", "foo=bar; Max=Age=120")
```

### Parcel fails to resolve imports

Connect-ES and Protobuf-ES use [package exports](https://nodejs.org/docs/latest-v12.x/api/packages.html#packages_exports).
If you see the following error with Parcel, make sure to [enable package exports](https://parceljs.org/features/dependency-resolution/#package-exports):

```
@parcel/core: Failed to resolve '@bufbuild/protobuf/codegenv1'
```

### Metro fails to resolve imports

Connect-ES and Protobuf-ES use [package exports](https://nodejs.org/docs/latest-v12.x/api/packages.html#packages_exports).
If you see the following error with Metro or Expo, make sure to [enable package exports](https://metrobundler.dev/docs/package-exports/):

```
Metro error: Unable to resolve module @bufbuild/protobuf/codegenv1
```

## Deployment

### How do I handle Authorization Bearer headers through middleware/interceptors?
Expand Down
2 changes: 1 addition & 1 deletion docs/node/get-requests-and-caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const transport = createConnectTransport({
baseUrl: "https://demo.connectrpc.com",
useHttpGet: true,
});
const client = createPromiseClient(ElizaService, transport);
const client = createClient(ElizaService, transport);
const response = await client.say(request);
console.log(response);
```
Expand Down
25 changes: 10 additions & 15 deletions docs/node/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ $ cd connect-example
$ npm init -y
$ npm install typescript tsx
$ npx tsc --init
$ npm install @bufbuild/buf @bufbuild/protoc-gen-es@"^1.0.0" @bufbuild/protobuf@"^1.0.0" @connectrpc/protoc-gen-connect-es@"^1.0.0" @connectrpc/connect@"^1.0.0"
$ npm install @bufbuild/buf @bufbuild/protobuf @bufbuild/protoc-gen-es @connectrpc/connect
```

## Define a service
Expand Down Expand Up @@ -70,7 +70,7 @@ service ElizaService {
We're going to generate our code using [Buf](https://www.npmjs.com/package/@bufbuild/buf),
a modern replacement for Google's protobuf compiler. We installed Buf earlier,
but we also need a configuration file to get going. (If you'd prefer, you can
skip this section and use `protoc` instead — `protoc-gen-connect-es`
skip this section and use `protoc` instead — `protoc-gen-es`
behaves like any other plugin.)

First, scaffold a basic [`buf.yaml`][buf.yaml] at the root of your repository:
Expand Down Expand Up @@ -105,9 +105,6 @@ plugins:
- local: protoc-gen-es
out: gen
opt: target=ts
- local: protoc-gen-connect-es
out: gen
opt: target=ts
```

With those configuration files in place, you can lint your schema and generate
Expand All @@ -118,7 +115,7 @@ $ npx buf lint
$ npx buf generate
```

You should now see two generated TypeScript files:
You should now see a generated TypeScript file:

```diff
.
Expand All @@ -127,8 +124,6 @@ You should now see two generated TypeScript files:
// highlight-next-line
├── gen
// highlight-next-line
│ ├── eliza_connect.ts
// highlight-next-line
│ └── eliza_pb.ts
├── node_modules
├── package-lock.json
Expand All @@ -151,7 +146,7 @@ Create a new file `connect.ts` with the following contents:

```ts
import type { ConnectRouter } from "@connectrpc/connect";
import { ElizaService } from "./gen/eliza_connect";
import { ElizaService } from "./gen/eliza_pb";
export default (router: ConnectRouter) =>
// registers connectrpc.eliza.v1.ElizaService
Expand Down Expand Up @@ -228,8 +223,8 @@ You can also make requests using a Connect client. Create a new file `client.ts`
with the following contents:

```ts
import { createPromiseClient } from "@connectrpc/connect";
import { ElizaService } from "./gen/eliza_connect";
import { createClient } from "@connectrpc/connect";
import { ElizaService } from "./gen/eliza_pb";
import { createConnectTransport } from "@connectrpc/connect-node";

const transport = createConnectTransport({
Expand All @@ -238,7 +233,7 @@ const transport = createConnectTransport({
});

async function main() {
const client = createPromiseClient(ElizaService, transport);
const client = createClient(ElizaService, transport);
const res = await client.say({ sentence: "I feel happy." });
console.log(res);
}
Expand All @@ -262,8 +257,8 @@ You can run the same client from a web browser, just by swapping out the
Transport:

```ts
import { createPromiseClient } from "@connectrpc/connect";
import { ElizaService } from "./gen/eliza_connect";
import { createClient } from "@connectrpc/connect";
import { ElizaService } from "./gen/eliza_pb";
// highlight-next-line
import { createConnectTransport } from "@connectrpc/connect-web";

Expand All @@ -276,7 +271,7 @@ const transport = createConnectTransport({
});

async function main() {
const client = createPromiseClient(ElizaService, transport);
const client = createClient(ElizaService, transport);
const res = await client.say({ sentence: "I feel happy." });
console.log(res);
}
Expand Down
50 changes: 28 additions & 22 deletions docs/node/implementing-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ To register this service, call `router.service()`:

```ts
import { ConnectRouter, HandlerContext } from "@connectrpc/connect";
import { ElizaService } from "./gen/eliza_connect";
import { SayRequest, SayResponse } from "./gen/eliza_pb";
import { ElizaService, SayRequest } from "./gen/eliza_pb";
import { create } from "@bufbuild/protobuf";

export default (router: ConnectRouter) =>
router.service(ElizaService, {
async say(req: SayRequest, context: HandlerContext) {
return new SayResponse({
return {
sentence: `You said ${req.sentence}`,
});
};
}
});
```
Expand All @@ -59,7 +59,7 @@ message, or just an initializer for a response message:

```ts
function say(req: SayRequest) {
return new SayResponse({ sentence: `You said ${req.sentence}` });
return create(SayResponseSchema, { sentence: `You said ${req.sentence}` });
}
```

Expand All @@ -82,14 +82,15 @@ The context argument gives you access to headers and service metadata:

```ts
import { HandlerContext } from "@connectrpc/connect";
import { create } from "@bufbuild/protobuf";
import { SayRequest } from "./gen/eliza_pb";

function say(req: SayRequest, context: HandlerContext) {
ctx.service.typeName; // the protobuf type name "ElizaService"
ctx.method.name; // the protobuf rpc name "Say"
context.requestHeader.get("Foo");
context.responseHeader.set("Foo", "Bar");
return new SayResponse({ sentence: `You said ${req.sentence}` });
return { sentence: `You said ${req.sentence}` };
}
```

Expand Down Expand Up @@ -120,24 +121,30 @@ an error detail. Let's use [`google.rpc.LocalizedMessage`](https://buf.build/goo
to localize our error message:

```bash
$ buf generate buf.build/googleapis/googleapis
$ npx buf generate buf.build/googleapis/googleapis
```

```ts
import { Code, ConnectError } from "@connectrpc/connect";
import { ElizaService } from "./gen/eliza_connect";
import { LocalizedMessage } from "./gen/google/rpc/error_details_pb";
import { ElizaService } from "./gen/eliza_pb";
import { LocalizedMessageSchema } from "./gen/google/rpc/error_details_pb";

function say() {
const details = [
new LocalizedMessage({
locale: "fr-CH",
message: "Je n'ai plus de mots.",
}),
new LocalizedMessage({
locale: "ja-JP",
message: "もう言葉がありません。",
}),
{
desc: LocalizedMessageSchema,
value: {
locale: "fr-CH",
message: "Je n'ai plus de mots.",
}
},
{
desc: LocalizedMessageSchema,
value: {
locale: "ja-JP",
message: "もう言葉がありません。",
}
},
];
const metadata = new Headers({
"words-left": "none"
Expand Down Expand Up @@ -222,14 +229,14 @@ away:
```typescript
import type { MethodImpl, ServiceImpl } from "@connectrpc/connect";

export const say: MethodImpl<typeof ElizaService.methods.say> = ...
export const say: MethodImpl<typeof ElizaService.method.say> = ...

export const eliza: ServiceImpl<typeof ElizaService> = {
// ...
};

export class Eliza implements ServiceImpl<typeof ElizaService> {
async say(req: SayRequest) {
say(req: SayRequest) {
return {
sentence: `You said ${req.sentence}`,
};
Expand All @@ -241,7 +248,7 @@ Registering the examples above:

```typescript
import { ConnectRouter } from "@connectrpc/connect";
import { ElizaService } from "./gen/eliza_connect";
import { ElizaService } from "./gen/eliza_pb";
import { say, eliza, Eliza } from "./other-file";

export default (router: ConnectRouter) => {
Expand All @@ -250,8 +257,7 @@ export default (router: ConnectRouter) => {

// alternative for using const say
router.rpc(
ElizaService,
ElizaService.methods.say,
ElizaService.method.say,
say
);

Expand Down
22 changes: 11 additions & 11 deletions docs/node/interceptors.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ One of the common use cases of interceptors is to a handle logic that is common

```ts
// This can come from an auth library like passport.js
import { authenticate } from "./authenticate.js";
import { authenticate } from "./authenticate";

const authenticator: Interceptor = (next) => async (req) => {
// `authenticate` takes the authorization header value
Expand All @@ -134,8 +134,8 @@ But what if we need the user info in one of our RPC implementations? One way is

```ts
import { ConnectRouter } from "@connectrpc/connect";
import { ElizaService } from "./gen/eliza_connect";
import { authenticate } from "authenticate.js";
import { ElizaService } from "./gen/eliza_pb";
import { authenticate } from "authenticate";

export default (router: ConnectRouter) =>
// registers connectrpc.eliza.v1.ElizaService
Expand All @@ -152,7 +152,7 @@ export default (router: ConnectRouter) =>

But this means authentication happens twice, once in the Interceptor and second in our handler. This is where context values come in. We can add the user as a context value which can then be retrieved in the handler. To do so we need to define a context key:

```ts title=user-context.js
```ts title=user-context.ts
import { createContextKey } from "@connectrpc/connect";

type User = { name: string };
Expand All @@ -169,8 +169,8 @@ export { kUser };
We can modify the interceptor to pass the user information using the context key:

```ts
import { authenticate } from "./authenticate.js";
import { kUser } from "user-context.js";
import { authenticate } from "./authenticate";
import { kUser } from "./user-context";
import type { Interceptor } from "@connectrpc/connect";
import { ConnectError, Code } from "@connectrpc/connect";

Expand All @@ -191,9 +191,9 @@ And then in our handler we can use it:

```ts
import { ConnectRouter } from "@connectrpc/connect";
import { ElizaService } from "./gen/eliza_connect";
import { authenticate } from "authenticate.js";
import { kUser } from "user-context.js";
import { ElizaService } from "./gen/eliza_pb";
import { authenticate } from "./authenticate";
import { kUser } from "./user-context";

export default (router: ConnectRouter) =>
// registers connectrpc.eliza.v1.ElizaService
Expand All @@ -213,8 +213,8 @@ You can also pass the context value from the server plugin:
```ts
import { fastify } from "fastify";
import routes from "./connect";
import { kUser } from "user-context.js";
import { authenticate } from "authenticate.js";
import { kUser } from "./user-context";
import { authenticate } from "./authenticate";
import { fastifyConnectPlugin } from "@connectrpc/connect-fastify";

const server = fastify();
Expand Down
15 changes: 15 additions & 0 deletions docs/node/migrating-to-v2.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: Migrating to v2
sidebar_position: 0
---

Version 2 of Connect-ES is available. The key changes are:

- **We're upgrading to Protobuf-ES version 2.** It's the largest change in this release.
- **Connect-ES no longer needs its own code generator plugin.**
- **We're adding support for Next.js 15, Fastify 5, and Express 5.**
- **We're dropping support for old versions of Node.js and TypeScript.** You'll need at least Node.js 18.14.1 and TypeScript 4.9.6.

The upgrade of the Protobuf runtime brings support for [Editions](https://buf.build/blog/protobuf-editions-are-here) and new APIs for Protobuf messages with support for custom options. Messages are now plain TypeScript types, which greatly improves compatibility with the ecosystem. For example, messages can be passed from a server-side component in Next.js to a client-side component without losing any data or types. To learn more about the enhancements, see the [release blog post for Protobuf-ES v2](https://buf.build/blog/protobuf-es-v2).

If you are using version 1, see our [migration guide](https://github.com/connectrpc/connect-es/blob/main/MIGRATING.md) to upgrade to version 2.
10 changes: 5 additions & 5 deletions docs/node/server-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ with your Connect RPCs. Use the plugin from [@connectrpc/connect-fastify](https:
with Fastify:

```bash
$ npm install fastify @connectrpc/connect@"^1.0.0" @connectrpc/connect-node@"^1.0.0" @connectrpc/connect-fastify@"^1.0.0"
$ npm install fastify @connectrpc/connect @connectrpc/connect-node @connectrpc/connect-fastify
```

```ts
Expand Down Expand Up @@ -101,7 +101,7 @@ using the latest React features. With [@connectrpc/connect-next](https://www.npm
you can serve your Connect RPCs via Next.js API Routes.

```bash
$ npm install next@"^13.0.0" @connectrpc/connect@"^1.0.0" @connectrpc/connect-node@"^1.0.0" @connectrpc/connect-next@"^1.0.0"
$ npm install next@"^13.0.0" @connectrpc/connect @connectrpc/connect-node @connectrpc/connect-next
```

To enable the server plugin, create the file `pages/api/[[...connect]].ts` in your project:
Expand Down Expand Up @@ -143,7 +143,7 @@ popular because of its simplicity. Use the middleware provided by [@connectrpc/c
to add your Connect RPCs to Express:

```bash
$ npm install express @connectrpc/connect@"^1.0.0" @connectrpc/connect-node@"^1.0.0" @connectrpc/connect-express@"^1.0.0"
$ npm install express @connectrpc/connect @connectrpc/connect-node @connectrpc/connect-express
```

```ts
Expand Down Expand Up @@ -200,11 +200,11 @@ All adapters take a set of common options:
- `interceptors?: Interceptor[]`<br/>
An array of interceptors to apply to all requests. See [Interceptors](./interceptors.md) for more information.
- `jsonOptions`<br/>
Protobuf [JSON serialization options](https://github.com/bufbuild/protobuf-es/blob/v1/docs/runtime_api.md#json-serialization-options).
Protobuf [JSON serialization options](https://github.com/bufbuild/protobuf-es/blob/v2.2.1/MANUAL.md#json-serialization-options).
If your service uses `google.protobuf.Any`, provide a `typeRegistry` with the
allowed message types.
- `binaryOptions`<br/>
Protobuf [binary serialization options](https://github.com/bufbuild/protobuf-es/blob/v1/docs/runtime_api.md#binary-serialization-options).
Protobuf [binary serialization options](https://github.com/bufbuild/protobuf-es/blob/v2.2.1/MANUAL.md#binary-serialization-options).


## HTTP/2, TLS, and gRPC
Expand Down
Loading

0 comments on commit 7716a64

Please sign in to comment.