Episode ini menutup siklus produksi: pipeline CI yang menegakkan type-safe contracts dan linting, testing unit dan integration dengan vitest, msw, dan snapshot procedure, serta deployment production dengan environment config, observability, dan release flow.

Kode yang hanya lulus di mesin lokal belum apa-apa. Episode 17 membawa kalian ke siklus produksi yang utuh: pipeline CI yang menegakkan type-safe contracts dan linting, testing unit dan integration, serta deployment dengan konfigurasi environment, observability, dan release flow.
Keunggulan tRPC kembali terlihat: karena contract sudah bertipe, pipeline build di CI bisa menangkap pelanggaran yang di REST baru terasa di production.
Pipeline CI untuk project tRPC setidaknya menjalankan: install dependency, typecheck, lint, dan test. Contoh workflow GitHub Actions:
name: CI
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx tsc --noEmit
- run: npm run lint
- run: npm testnpx tsc --noEmit memeriksa seluruh project tanpa menghasilkan file — di sinilah pelanggaran contract tRPC terdeteksi: jika client memakai procedure yang tidak ada atau input yang salah bentuk, compile gagal sebelum deployment.
Karena client dan server berbagi tipe, CI secara otomatis menegakkan konsistensi contract. Ini jauh lebih ketat daripada pipeline REST yang hanya mengecek kode bisa dikompilasi terpisah. Setiap pull request yang mengubah router langsung memvalidasi seluruh pemakaiannya.
Unit test procedure tRPC memakai caller dari episode 2 — tanpa HTTP, namun tetap menjalankan middleware dan validasi:
import { describe, it, expect } from "vitest";
import { createCaller } from "../server/root";
const caller = createCaller({ userId: 1 });
describe("userRouter", () => {
it("mengembalikan user sesuai id", async () => {
const user = await caller.user.byId({ id: 1 });
expect(user.nama).toBe("Arman");
});
it("menolak input yang tidak valid", async () => {
await expect(caller.user.byId({ id: "abc" as never }))
.rejects.toThrow();
});
});createCaller({ userId: 1 }) membuat caller dengan context uji. Pengujian validasi juga mudah: mengirim input salah bentuk akan melempar error zod.
Snapshot testing mengabadikan bentuk output prosedur. Saat output berubah, test menandai perubahan sehingga kalian sadar akan efeknya:
it("output user.byId sesuai snapshot", async () => {
const user = await caller.user.byId({ id: 1 });
expect(user).toMatchInlineSnapshot();
});toMatchInlineSnapshot menyimpan bentuk output persis pada pemanggilan pertama. Perubahan output berikutnya akan terlihat dalam review diff — sangat membantu menjaga backward compatibility dari episode 9.
Untuk integration test dari sisi client, Mock Service Worker (msw) menangkap request jaringan dan mengembalikan respons yang sudah ditentukan:
npm install --save-dev vitest mswimport { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";
const server = setupServer(
http.post("/api/trpc/user.byId", () =>
HttpResponse.json({
result: { data: { id: 1, nama: "Arman" } },
}),
),
);
beforeAll(() => server.listen());
afterAll(() => server.close());setupServer meng-intercept request POST ke endpoint tRPC dan mengembalikan data mock. Dengan ini, komponen React bisa diuji tanpa server nyata, sambil tetap melatih mekanisme transport tRPC.
Deployment production memakai environment variables yang diatur dari episode 7:
NODE_ENV=production
NEXT_PUBLIC_BASE_URL=https://api.contoh.com
DATABASE_URL=postgres://user:password@host:5432/db
REDIS_URL=redis://cache.internal:6379Perhatikan bahwa secret seperti DATABASE_URL dan REDIS_URL tidak boleh ada di repository — letakkan di secret store platform kalian dan injeksikan saat deploy.
Production butuh observability dari episode 14: log terstruktur, metrics, dan tracing aktif dari hari pertama. Untuk release flow, terapkan versi dengan tag:
git tag v1.4.0
git push origin v1.4.0Rilis bertahap dengan semver memberi jaring pengaman: jika versi baru bermasalah, rollback ke tag sebelumnya. Kombinasikan dengan deprecation policy dari episode 9 agar migrasi client selalu terkendali.
Info
Pasang integrasi terus-menerus di PR untuk menjalankan tsc --noEmit dan test lebih dulu. Build yang lambat lulus di pipeline membuat regresi contract tRPC terdeteksi sejak review, bukan setelah merge.
Episode 17 menuntaskan siklus produksi: pipeline CI menegakkan type-safe contracts dan linting, test unit dan integration menjaga perilaku procedure, dan deployment production berjalan dengan konfigurasi environment, observability, serta release flow yang teratur.
Inti yang harus dibawa pulang:
tsc --noEmit, lint, dan test.Di episode 18 selanjutnya — episode terakhir series — kita akan membahas tooling modern & fitur stabil terbaru — @trpc/next, @trpc/react-query, @trpc/server, dan createTRPCProxyClient, fitur stabil seperti router.merge, procedure.input/output, dan links, serta tren full-stack type safety, monorepo, dan API-first DX dengan tRPC.