Skip to content

Commit

Permalink
Move data transformers to edges (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
KATT authored Jan 25, 2021
1 parent 2edcf84 commit 5931a5a
Show file tree
Hide file tree
Showing 26 changed files with 106 additions and 135 deletions.
14 changes: 0 additions & 14 deletions .github/workflows/integration.yml

This file was deleted.

15 changes: 0 additions & 15 deletions .github/workflows/size.yml

This file was deleted.

30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,27 @@ tRPC is a framework for building strongly typed RPC APIs with TypeScript. Altern

## Usage

TODO - see examples
> :construction: Under construction, for now see [`./examples`](./examples)

### Data transformers

You are able to serialize the output data (in order to be able to transparently use e.g. standard `Date`s). The transformers need to be added both to the server and the client.

Data transformers currently live on the edges - in client-specific implementation & in the API response adapters. See a reference of how superjson is attached to ..

- `createNextApiHandler()` in [`./examples/next-ssg-chat/[...trpc.ts]`](./examples/next-ssg-chat/pages/api/trpc/%5B...trpc%5D.ts), and
- `createReactQueryHooks` in [`./examples/next-ssg-chat/pages/_app.tsx`](./examples/next-ssg-chat/pages/_app.tsx)

## Internals

### HTTP Methods <-> endpoint type mapping

| HTTP Method | Mapping | Notes |
| ----------- | ------------------ | -------------------------------------------------------- |
| `GET` | `.queries()` | Args in query string |
| `POST` | `.mutations()` | Args in post body |
| `PATCH` | `.subscriptions()` | Experimental. Uses long-pulling. Should prob not be used |
| HTTP Method | Mapping | Notes |
| ----------- | ------------------ | --------------------------------------------------------------------------------- |
| `GET` | `.queries()` | Args in query string |
| `POST` | `.mutations()` | Args in post body |
| `PATCH` | `.subscriptions()` | Experimental API using long-pulling. Implementation details are likely to change. |


# Development
Expand Down Expand Up @@ -57,13 +68,6 @@ You can play with local examples:
- `yarn playground` - runs `examples/playground`
- `cd examples next-ssg-chat && yarn dev`

```sh
yarn start:app
```

This will start the example/playground on `localhost:1234`. If you have lerna running watch in parallel mode in one terminal, and then you run parcel, your playground will hot reload when you make changes to any imported module whose source is inside of `packages/*/src/*`. Note that to accomplish this, each package's `start` command passes TDSX the `--noClean` flag. This prevents Parcel from exploding between rebuilds because of File Not Found errors.

Important Safety Tip: When adding/altering packages in the playground, use `alias` object in package.json. This will tell Parcel to resolve them to the filesystem instead of trying to install the package from NPM. It also fixes duplicate React errors you may run into.

### Running Cypress

Expand Down
8 changes: 4 additions & 4 deletions examples/next-ssg-chat/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@examples/chat",
"version": "1.0.0-alpha.13",
"version": "1.0.0-alpha.15",
"private": true,
"scripts": {
"dx:next": "next dev",
Expand All @@ -14,10 +14,10 @@
"migrate": "prisma migrate deploy --preview-feature"
},
"dependencies": {
"@katt/trpc-client": "^1.0.0-alpha.13",
"@katt/trpc-react": "^1.0.0-alpha.13",
"@katt/trpc-server": "^1.0.0-alpha.13",
"@prisma/client": "^2.15.0",
"@trpcdev/client": "^1.0.0-alpha.15",
"@trpcdev/react": "^1.0.0-alpha.15",
"@trpcdev/server": "^1.0.0-alpha.15",
"next": "10.0.4",
"react": "17.0.1",
"react-dom": "17.0.1",
Expand Down
4 changes: 2 additions & 2 deletions examples/next-ssg-chat/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createReactQueryHooks, createTRPCClient } from '@katt/trpc-react';
import { createReactQueryHooks, createTRPCClient } from '@trpcdev/react';
import type { AppProps /*, AppContext */ } from 'next/app';
import { QueryClient, QueryClientProvider } from 'react-query';
import { Hydrate } from 'react-query/hydration';
Expand All @@ -7,13 +7,13 @@ import type { ChatRouter, Context } from './api/trpc/[...trpc]';

export const client = createTRPCClient<ChatRouter>({
url: '/api/trpc',
transformer: sj,
});

const queryClient = new QueryClient();
export const hooks = createReactQueryHooks<ChatRouter, Context>({
client,
queryClient,
transformer: sj,
});

function MyApp({ Component, pageProps }: AppProps) {
Expand Down
4 changes: 2 additions & 2 deletions examples/next-ssg-chat/pages/api/trpc/[...trpc].ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as trpc from '@katt/trpc-server';
import { Subscription, SubscriptionEmit } from '@katt/trpc-server';
import * as trpc from '@trpcdev/server';
import { Subscription, SubscriptionEmit } from '@trpcdev/server';
import { Message, PrismaClient } from '@prisma/client';
import { sj } from '../../../utils/serializer';

Expand Down
32 changes: 16 additions & 16 deletions examples/next-ssg-chat/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,22 @@ export default function Home() {
};
const timestamp = useMemo(() => getTimestamp(msgs), [msgs]);
console.log({ timestamp });
useEffect(() => {
return client.subscription(
[
'messages.newMessages',
{
timestamp,
},
],
{
onSuccess(data) {
// console.log('new data', data);
addMessages(data);
},
},
);
}, [timestamp]);
// useEffect(() => {
// return client.subscription(
// [
// 'messages.newMessages',
// {
// timestamp,
// },
// ],
// {
// onSuccess(data) {
// // console.log('new data', data);
// addMessages(data);
// },
// },
// );
// }, [timestamp]);

const addMessage = hooks.useMutation('messages.create');
// useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion examples/next-ssg-chat/utils/serializer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DataTransformer } from '@katt/trpc-server';
import { DataTransformer } from '@trpcdev/server';
import superjson from 'superjson';

export const sj: DataTransformer = {
Expand Down
8 changes: 4 additions & 4 deletions examples/playground/package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"name": "@examples/playground",
"version": "1.0.0-alpha.13",
"version": "1.0.0-alpha.15",
"private": true,
"scripts": {
"dev:server": "nodemon -e ts -w . -x ts-node ./src/server.ts",
"dev:client": "nodemon -e ts -w . -x 'wait-on tcp:2021 && ts-node ./src/client.ts'",
"dev": "run-p dev:* --print-label"
},
"dependencies": {
"@katt/trpc-client": "^1.0.0-alpha.13",
"@katt/trpc-react": "^1.0.0-alpha.13",
"@katt/trpc-server": "^1.0.0-alpha.13",
"@trpcdev/client": "^1.0.0-alpha.15",
"@trpcdev/react": "^1.0.0-alpha.15",
"@trpcdev/server": "^1.0.0-alpha.15",
"@types/node-fetch": "^2.5.8",
"abort-controller": "^3.0.0",
"body-parser": "^1.19.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/playground/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fetch from 'node-fetch';
import AbortController from 'abort-controller';
import type { RootRouter } from './server';
import { createTRPCClient, CreateTRPCClientOptions } from '@katt/trpc-client';
import { createTRPCClient, CreateTRPCClientOptions } from '@trpcdev/client';

const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms));

Expand Down
2 changes: 1 addition & 1 deletion examples/playground/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import bodyParser from 'body-parser';
import { EventEmitter } from 'events';
import express from 'express';
import * as trpc from '@katt/trpc-server';
import * as trpc from '@trpcdev/server';

// ---------- create context
const createContext = ({ req, res }: trpc.CreateExpressContextOptions) => {
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.0.0-alpha.13",
"version": "1.0.0-alpha.15",
"registry": "https://registry.npmjs.org/",
"publishConfig": {
"access": "public"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
},
"scripts": {
"lerna": "lerna",
"start": "lerna run start --scope @katt/trpc-* --stream --parallel",
"start": "lerna run start --scope @trpcdev/* --stream --parallel",
"dev": "yarn start",
"test": "lerna run test --stream --",
"lint": "lerna run lint --stream --",
Expand Down
2 changes: 1 addition & 1 deletion packages/client/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# `@katt/trpc-client`
# `@trpcdev/client`
2 changes: 1 addition & 1 deletion packages/client/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# `@katt/trpc-client`
# `@trpcdev/client`

https://github.com/KATT/trpc
7 changes: 3 additions & 4 deletions packages/client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@katt/trpc-client",
"version": "1.0.0-alpha.13",
"name": "@trpcdev/client",
"version": "1.0.0-alpha.15",
"description": "TRPC Client lib",
"author": "KATT",
"license": "MIT",
Expand All @@ -27,8 +27,7 @@
"tslib": "^2.0.0"
},
"devDependencies": {
"@katt/trpc-server": "^1.0.0-alpha.13",
"react-query": "^3.5.16"
"@trpcdev/server": "^1.0.0-alpha.15"
},
"publishConfig": {
"access": "public"
Expand Down
31 changes: 9 additions & 22 deletions packages/client/src/createTRPCClient.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type {
AnyRouter,
DataTransformer,
HTTPResponseEnvelope,
HTTPSuccessResponseEnvelope,
inferAsyncReturnType,
inferEndpointArgs,
inferHandler,
inferSubscriptionData,
Maybe,
} from '@katt/trpc-server';
} from '@trpcdev/server';

type UnsubscribeFn = () => void;

Expand All @@ -32,12 +31,6 @@ type inferSubscriptionFn<TRouter extends AnyRouter> = <
},
) => UnsubscribeFn;

export type TRPCClient<TRouter extends AnyRouter> = {
query: inferHandler<TRouter['_def']['queries']>;
mutate: inferHandler<TRouter['_def']['mutations']>;
subscription: inferSubscriptionFn<TRouter>;
transformer: DataTransformer;
};
export class TRPCClientError extends Error {
public readonly json?: Maybe<HTTPResponseEnvelope<unknown>>;
public readonly res?: Maybe<Response>;
Expand Down Expand Up @@ -103,19 +96,14 @@ export interface CreateTRPCClientOptions {
getHeaders?: () => Record<string, string | undefined>;
onSuccess?: (data: HTTPSuccessResponseEnvelope<unknown>) => void;
onError?: (error: TRPCClientError) => void;
transformer?: DataTransformer;
}

export function createTRPCClient<TRouter extends AnyRouter>(
opts: CreateTRPCClientOptions,
): TRPCClient<TRouter> {
) {
const { fetchOpts, url } = opts;
const _fetch = getFetch(fetchOpts?.fetch);
const AC = getAbortController(fetchOpts?.AbortController);
const transformer = opts.transformer ?? {
serialize: (data) => data,
deserialize: (data) => data,
};

async function handleResponse(promise: Promise<Response>) {
let res: Maybe<Response> = null;
Expand All @@ -128,7 +116,7 @@ export function createTRPCClient<TRouter extends AnyRouter>(
opts.onSuccess &&
opts.onSuccess({
...json,
data: transformer.deserialize(json.data),
data: json.data,
});
return json.data as any;
}
Expand Down Expand Up @@ -158,9 +146,7 @@ export function createTRPCClient<TRouter extends AnyRouter>(
) => {
let target = `${url}/${path}`;
if (args?.length) {
target += `?args=${encodeURIComponent(
JSON.stringify(args.map(transformer.serialize) as any),
)}`;
target += `?args=${encodeURIComponent(JSON.stringify(args as any))}`;
}
const promise = _fetch(target, {
headers: getHeaders(),
Expand All @@ -175,7 +161,7 @@ export function createTRPCClient<TRouter extends AnyRouter>(
const promise = _fetch(`${url}/${path}`, {
method: 'POST',
body: JSON.stringify({
args: args.map(transformer.serialize),
args: args,
}),
headers: getHeaders(),
});
Expand All @@ -201,14 +187,14 @@ export function createTRPCClient<TRouter extends AnyRouter>(
const promise = _fetch(`${url}/${path}`, {
method: 'PATCH',
body: JSON.stringify({
args: args.map(transformer.serialize),
args: args,
}),
headers: getHeaders(),
signal,
});
try {
// console.log('⏳ waiting for', path, thisArgs);
const data = transformer.deserialize(await handleResponse(promise));
const data = await handleResponse(promise);

if (stopped) {
return;
Expand Down Expand Up @@ -251,6 +237,7 @@ export function createTRPCClient<TRouter extends AnyRouter>(
mutate,
query,
subscription,
transformer,
};
}

export type TRPCClient = ReturnType<typeof createTRPCClient>;
2 changes: 1 addition & 1 deletion packages/react/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# `@katt/trpc-react`
# `@trpcdev/react`

https://github.com/KATT/trpc
Loading

0 comments on commit 5931a5a

Please sign in to comment.