Chapter 03

tRPC server + SvelteKit 1.0

knaka Tech-Blog
knaka Tech-Blog
2023.03.04に更新

概要:

tRPC + SvelteKit の例となります

  • 前の、React版と似ています。

構成

  • trpc/server : 10.13.2
  • express : 4.18.2
  • svelteKit: 1.5.0

参考


参考のコード

https://github.com/kuc-arc-f/kit1_13trpc


  • tree
$ tree .
.
├── README.md
├── client
│   ├── package.json
│   ├── src
│   │   ├── app.d.ts
│   │   ├── app.html
│   │   ├── lib
│   │   ├── routes
│   │   │   ├── +layout.svelte
│   │   │   ├── +page.svelte
│   │   │   ├── +page.ts
│   │   │   ├── Counter.svelte
│   │   │   ├── Header.svelte
│   │   │   ├── about
│   │   │   │   ├── +page.svelte
│   │   │   │   └── +page.ts
│   │   │   ├── styles.css
│   │   │   ├── trpc
│   │   │   │   ├── +page.svelte
│   │   │   │   └── +page.ts
│   │   └── utils
│   │       └── trpc.ts
│   ├── static
│   ├── svelte.config.js
│   ├── tsconfig.json
│   └── vite.config.ts
└── server
    ├── index.ts
    └── package.json

Server

  • appRouter ,export します
index.ts
import express from 'express';
import { initTRPC } from '@trpc/server';
import * as trpcExpress from '@trpc/server/adapters/express';
import cors from 'cors';
import { z } from 'zod';

const app = express();
const PORT = 3000;
app.use(cors());

const t = initTRPC.create();
const router = t.router;
const publicProcedure = t.procedure;
//type
interface User {
  id: string;
  name: string;
}
const userList: User[] = [
  {
    id: '1',
    name: 'KATT',
  },
];
//
const appRouter = router({
  hello: t.procedure.query(() => {
    return 'Hello World-333';
  }),
  helloName: t.procedure
    .input(z.object({ name: z.string(), age: z.number() }))
    .query(({ input }) => {
      return {
        name: `Hello World ${input.name}`,
        age: input.age,
      };
  }),  
  /**
   * userById
   * @param
   *
   * @return
   */   
  userById: publicProcedure
  .input((val: unknown) => {
    if (typeof val === 'string') return val;
    throw new Error(`Invalid input: ${typeof val}`);
  })
  .query((req) => {
    const input = req.input;
    const user = userList.find((it) => it.id === input);
    return user;
  }),
  /**
   * userCreate
   * @param
   *
   * @return
   */   
  userCreate: publicProcedure
  .input(z.object({ name: z.string() }))
  .mutation((req) => {
    const id = `${Math.random()}`;
    const user: User = {
      id,
      name: req.input.name,
    };
console.log(user);
    userList.push(user);
    return user;
  }),
  /**
   * getUserList
   * @param
   *
   * @return
   */   
  getUserList: publicProcedure.query(() => {
    return userList;
  }),      
});

app.get('/', (_req, res) => res.send('hello'));

app.use(
  '/trpc',
  trpcExpress.createExpressMiddleware({
    router: appRouter,
  })
);

app.listen(PORT, () => console.log(`Example app listening on port ${PORT}!`));

export type AppRouter = typeof appRouter;


Client

  • npm
npm install --save @trpc/client @trpc/server

  • src/utils/trpc.ts
trpc.ts
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../../../server/index';

// Notice the <AppRouter> generic here.
export const trpc = createTRPCProxyClient<AppRouter>({
  links: [
    httpBatchLink({
      url: 'http://localhost:3000/trpc',
    }),
  ],
});

  • src/routes/trpc/+page.svelte : 画面

  • 起動時に, trpc.hello.query等で、取得処理

  • mutation: await trpc.userCreate.mutate , 更新処理

<svelte:head>
	<title>Test</title>
	<meta name="description" content="About this app" />
</svelte:head>

<script lang="ts">
import { trpc } from '../../utils/trpc';
import { goto } from '$app/navigation';
import LibAuth from '$lib/LibAuth';

/** @type {import('./$types').PageData} */
export let data: any, dataHello: string = "";
//console.log(data);

/**
 * startProc
 * @param
 *
 * @return
 */  
const startProc = async function () {
	const hello = await trpc.hello.query();
	dataHello = hello;
console.log(hello);	
	const user = await trpc.userById.query('1');
	console.log(user);
	const userList = await trpc.getUserList.query();
	console.log(userList);
	//
}
startProc();
/**
 * createUser
 * @param
 *
 * @return
 */ 
 const createUser = async function () {
	try{
		const createdUser = await trpc.userCreate.mutate({ name: 'sachinraja' });
//		goto(`/crud`);
	} catch (e) {
      console.error(e);
      alert("error, add");
    }
}
</script>

<!-- MarkUp -->
<div class="text-column">
	<h1>tRPC</h1>
	<hr />
	dataHello= {dataHello}
	<hr />
	<button on:click={createUser} class="btn btn-primary my-2">Add</button>
	<hr />
</div>

<!--
-->

参考のレイアウト


....