Skip to content

Commit

Permalink
Enforce cardinality as required prop for key
Browse files Browse the repository at this point in the history
Signed-off-by: Paul Sachs <[email protected]>
  • Loading branch information
paul-sachs committed Oct 9, 2024
1 parent 1f3721f commit 60077ef
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 43 deletions.
33 changes: 16 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ npm install @connectrpc/connect-query @connectrpc/connect-web
```

> [!TIP]
>
>
> If you are using something that doesn't automatically install peerDependencies (npm older than v7), you'll want to make sure you also have `@bufbuild/protobuf`, `@connectrpc/connect`, and `@tanstack/react-query` installed. `@connectrpc/connect-web` is required for defining
the transport to be used by the client.
> the transport to be used by the client.
### Usage

Expand Down Expand Up @@ -106,8 +106,8 @@ export declare const ElizaService: GenService<{
methodKind: "unary";
input: typeof SayRequestSchema;
output: typeof SayResponseSchema;
},
}>
};
}>;
```

[`protoc-gen-connect-query`](https://www.npmjs.com/package/@connectrpc/protoc-gen-connect-query) is an optional additional plugin that exports every RPC individually for convenience:
Expand All @@ -120,7 +120,7 @@ import { ElizaService } from "./eliza_pb";
*
* @generated from rpc connectrpc.eliza.v1.ElizaService.Say
*/
export const say: typeof ElizaService["method"]["say"];
export const say: (typeof ElizaService)["method"]["say"];
```

For more information on code generation, see the [documentation for `protoc-gen-connect-query`](https://www.npmjs.com/package/@connectrpc/protoc-gen-connect-query) and the [documentation for `protoc-gen-es`](https://www.npmjs.com/package/@bufbuild/protoc-gen-es).
Expand Down Expand Up @@ -268,6 +268,7 @@ function createConnectQueryKey<Desc extends DescMethod | DescService>(
This function is used under the hood of `useQuery` and other hooks to compute a [`queryKey`](https://tanstack.com/query/v4/docs/react/guides/query-keys) for TanStack Query. You can use it to create (partial) keys yourself to filter queries.

`useQuery` creates a query key with the following parameters:

1. The qualified name of the RPC.
2. The transport being used.
3. The request message.
Expand All @@ -280,7 +281,7 @@ import { ElizaService } from "./gen/eliza_pb";

const myTransport = useTransport();
const queryKey = createConnectQueryKey({
// The schema is the only required parameter.
// The schema is the only required parameter.
schema: ElizaService.method.say,
transport: myTransport,
// You can provide a partial message here.
Expand All @@ -289,15 +290,15 @@ const queryKey = createConnectQueryKey({

// queryKey:
[
"conect-query",
"connect-query",
{
transport: "t1",
serviceName: "connectrpc.eliza.v1.ElizaService",
methodName: "Say",
input: { sentence: "hello" },
cardinality: "finite",
}
]
},
];
```

You can create a partial key that matches all RPCs of a service:
Expand All @@ -312,12 +313,12 @@ const queryKey = createConnectQueryKey({

// queryKey:
[
"conect-query",
"connect-query",
{
serviceName: "connectrpc.eliza.v1.ElizaService",
cardinality: "finite",
}
]
},
];
```

Infinite queries have distinct keys. To create a key for an infinite query, use the parameter `cardinality`:
Expand All @@ -330,7 +331,7 @@ import { ListService } from "./gen/list_pb";
// and passes on the pageParamKey.
const queryKey = createConnectQueryKey({
schema: ListService.method.list,
cardinality: "infinite", // "any" matches infinite and finite queries
cardinality: "infinite",
pageParamKey: "page",
input: { preview: true },
});
Expand Down Expand Up @@ -520,13 +521,12 @@ TanStack Query manages query caching for you based on query keys. [`QueryKey`s](
sentence: "hello there",
},
cardinality: "finite",
}
]
},
];
```

The factory [`createConnectQueryKey`](#createconnectquerykey) makes it easy to create a `ConnectQueryKey`, including partial keys for query filters.


## Testing

Connect-query (along with all other javascript based connect packages) can be tested with the `createRouterTransport` function from `@connectrpc/connect`. This function allows you to create a transport that can be used to test your application without needing to make any network requests. We also have a dedicated package, [@connectrpc/connect-playwright](https://github.com/connectrpc/connect-playwright-es) for testing within [playwright](https://playwright.dev/).
Expand Down Expand Up @@ -616,7 +616,6 @@ function prefetch() {
>
> Transports are taken into consideration when building query keys. If you want to prefetch queries on the server, and hydrate them in the client, make sure to use the same transport key on both sides with [`addStaticKeyToTransport`](#addstatickeytotransport).

### What about Streaming?

Connect-Query currently only supports Unary RPC methods, which use a simple request/response style of communication similar to GET or POST requests in REST. This is because it aligns most closely with TanStack Query's paradigms. However, we understand that there may be use cases for Server Streaming, Client Streaming, and Bidirectional Streaming, and we're eager to hear about them.
Expand Down
1 change: 1 addition & 0 deletions packages/connect-query/src/call-unary-method.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ describe("callUnaryMethod", () => {
schema: ElizaService.method.say,
input,
transport,
cardinality: "finite",
}),
queryFn: async ({
signal,
Expand Down
16 changes: 7 additions & 9 deletions packages/connect-query/src/connect-query-key.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ describe("createConnectQueryKey", () => {
transport: fakeTransport,
schema: ElizaService.method.say,
input: create(SayRequestSchema, { sentence: "hi" }),
cardinality: "finite",
});
expect(key).toStrictEqual([
"connect-query",
Expand Down Expand Up @@ -75,13 +76,15 @@ describe("createConnectQueryKey", () => {
const key = createConnectQueryKey({
schema: ElizaService.method.say,
input: undefined,
cardinality: "finite",
});
expect(key[1].input).toBeUndefined();
});

it("allows to omit input", () => {
const key = createConnectQueryKey({
schema: ElizaService.method.say,
cardinality: "finite",
});
expect(key[1].input).toBeUndefined();
});
Expand All @@ -90,17 +93,11 @@ describe("createConnectQueryKey", () => {
const key = createConnectQueryKey({
schema: ElizaService.method.say,
input: skipToken,
cardinality: "finite",
});
expect(key[1].input).toBe("skipped");
});

it("sets cardinality finite by default", () => {
const key = createConnectQueryKey({
schema: ElizaService.method.say,
});
expect(key[1].cardinality).toBe("finite");
});

it("allows to set cardinality: finite", () => {
const key = createConnectQueryKey({
schema: ElizaService.method.say,
Expand All @@ -109,17 +106,18 @@ describe("createConnectQueryKey", () => {
expect(key[1].cardinality).toBe("finite");
});

it("allows to set cardinality: any", () => {
it("allows to set cardinality: undefined", () => {
const key = createConnectQueryKey({
schema: ElizaService.method.say,
cardinality: "any",
cardinality: undefined,
});
expect(key[1].cardinality).toBeUndefined();
});

it("allows to set a service schema", () => {
const key = createConnectQueryKey({
schema: ElizaService,
cardinality: "finite",
});
expect(key[1].serviceName).toBe(ElizaService.typeName);
expect(key[1].methodName).toBeUndefined();
Expand Down
23 changes: 7 additions & 16 deletions packages/connect-query/src/connect-query-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export type ConnectQueryKey = [
/**
* Whether this is an infinite query, or a regular one.
*/
cardinality?: "infinite" | "finite";
cardinality?: "infinite" | "finite" | undefined;
},
];

Expand All @@ -90,9 +90,9 @@ type KeyParams<Desc extends DescMethod | DescService> = Desc extends DescMethod
*/
transport?: Transport;
/**
* Set `cardinality` in the key - "finite" by default.
* Set `cardinality` in the key - undefined is used for filters to match both finite and infinite queries.
*/
cardinality?: "finite" | "infinite" | "any";
cardinality: "finite" | "infinite" | undefined;
/**
* If omit the field with this name from the key for infinite queries.
*/
Expand All @@ -108,9 +108,9 @@ type KeyParams<Desc extends DescMethod | DescService> = Desc extends DescMethod
*/
transport?: Transport;
/**
* Set `cardinality` in the key - "finite" by default.
* Set `cardinality` in the key - undefined is used for filters to match both finite and infinite queries.
*/
cardinality?: "finite" | "infinite" | "any";
cardinality: "finite" | "infinite" | undefined;
};

/**
Expand Down Expand Up @@ -166,17 +166,8 @@ export function createConnectQueryKey<
if (params.transport !== undefined) {
props.transport = createTransportKey(params.transport);
}
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- "Cases not matched: undefined" 🤷
switch (params.cardinality) {
case undefined:
case "finite":
props.cardinality = "finite";
break;
case "infinite":
props.cardinality = "infinite";
break;
case "any":
break;
if (params.cardinality !== undefined) {
props.cardinality = params.cardinality;
}
if (params.schema.kind == "rpc" && "input" in params) {
if (typeof params.input == "symbol") {
Expand Down
1 change: 1 addition & 0 deletions packages/connect-query/src/create-query-options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe("createQueryOptions", () => {
schema: sayMethodDescriptor,
input: { sentence: "hi" },
transport: mockedElizaTransport,
cardinality: "finite",
});
const opt = createQueryOptions(
sayMethodDescriptor,
Expand Down
1 change: 1 addition & 0 deletions packages/connect-query/src/create-query-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export function createQueryOptions<
schema,
input: input ?? create(schema.input),
transport,
cardinality: "finite",
});
const structuralSharing = createStructuralSharing(schema.output);
const queryFn =
Expand Down
2 changes: 1 addition & 1 deletion packages/connect-query/src/use-infinite-query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ describe("useInfiniteQuery", () => {
queryKey: createConnectQueryKey({
schema: methodDescriptor,
transport: mockedPaginatedTransport,
cardinality: "any",
cardinality: undefined,
pageParamKey: "page",
input: {
page: 0n,
Expand Down

0 comments on commit 60077ef

Please sign in to comment.