trpc / v10-playground

tRPC v10 procedure play
https://stackblitz.com/github/trpc/v10-playground?file=src%2Fserver%2Findex.ts,src%2Fclient.ts,src%2Fserver%2Frouters%2FpostRouter.ts&view=editor
13 stars 3 forks source link

Chapter 3) The raw client API #26

Open KATT opened 2 years ago

KATT commented 2 years ago

The raw client API

The API you'd use if you are writing like a CLI or something with tRPC.

Client API Proposal with Proxy:

import type { appRouter } from './server';
import { createClient } from '@trpc/client';

const client = createClient<typeof appRouter>();

async function main() {
  // you can CMD+click `postById` here and jump straight into your backend
  const byId1 = await client.queries.postById({ input: { id: '1' }});

  // with meta data:
  const byId2 = await client.queries.postById({ 
    input: { id: '2' },
    context: {
      batch: false,
    }
  });

  // For backwards compatability:
  const list = await client.query('postList');
}

The reasoning with input: {} as an options object is that sometimes we might want to pass additional configuration and when input is optional it's a bit iffy to do client.query(undefined, {context: {foo: 'bar'}}

mmkal commented 2 years ago

If we are using Proxy, seems like it'd be incrementally barely harder at all to make query and safeQuery have the same pseudo-property procedures:

async function main() {
  // you can CMD+click `postById` here and jump straight into your backend
  try {
    const result = await client.query.postById(({ id: '1' });
  } catch (cause) { 
    const err = getErrorFromUnknown(cause)
    // do something..
  } 
}

async function safeMain() {
  // you can CMD+click `postById` here and jump straight into your backend
  const byId = await client.safeQuery.postById({ id: '1' });

  if (byId.ok) {
    console.log('data', byId.data);
  } else {
    console.log(byId.error); // <--- errors inferred
  }
}

Also, I think if this is added, it should align like the above with zod and make unsafe be the default - I used to think the opposite, and I would in a language with native Option/Either support. But I suffered for two years with io-ts and fp-ts before I learned to stop worrying and love zod. I just couldn't convince coworkers that all of the learning they had to do to stay free of side-effects was worth it, and it caused schisms and noise on pull requests. The default should be "do the thing that gives me the thing". IMHO. CC @colinhacks who I've seen make a similar point somewhere else recently 👋

KATT commented 2 years ago

[..] The default should be "do the thing that gives me the thing". IMHO. CC @colinhacks who I've seen make a similar point somewhere else recently 👋

I think I can only pick one that works with jump to definition though 😢

KATT commented 2 years ago

@mmkal do you ever use the raw client BTW? I'm curious

mmkal commented 2 years ago

Yes - we use it to call our trpc API (deployed in a lambda) from some other lambdas, and in getStaticProps (our backend has fairly complex permissions/networking setup and our frontend is just a vercel app so we don't use nextjs's api)

KATT commented 2 years ago

Alright alright -- this is now ready for review again if you want @mmkal. Almost ready to run on all of this now.