スキル一覧に戻る
janisto

typebox-schemas

by janisto

Fastify playground

0🍴 0📅 2026年1月25日
GitHubで見るManusで実行

SKILL.md


name: typebox-schemas description: Guide for TypeBox schema conventions in Fastify routes and environment validation. Use when defining request/response schemas or validating configuration.

TypeBox Schema Conventions

This skill provides patterns for using TypeBox schemas in this repository.

Route Schemas (Fastify Context)

Use FastifyPluginAsyncTypebox for route plugins to get automatic TypeBox type inference:

import { type FastifyPluginAsyncTypebox, Type } from "@fastify/type-provider-typebox";

const routes: FastifyPluginAsyncTypebox = async (fastify) => {
  fastify.get(
    "/endpoint",
    {
      schema: {
        description: "Endpoint description",
        tags: ["tag-name"],
        summary: "Short summary",
        querystring: Type.Object({
          page: Type.Number({ minimum: 1, default: 1 }),
          limit: Type.Number({ minimum: 1, maximum: 100, default: 10 }),
        }),
        params: Type.Object({
          id: Type.String({ format: "uuid" }),
        }),
        body: Type.Object({
          name: Type.String({ minLength: 1, maxLength: 255 }),
          email: Type.String({ format: "email" }),
        }),
        response: {
          200: Type.Object({
            status: Type.Literal("ok"),
            data: Type.Array(Type.Object({
              id: Type.String(),
              name: Type.String(),
            })),
          }),
          400: Type.Object({
            message: Type.String(),
          }),
          404: Type.Object({
            message: Type.String(),
          }),
        },
      },
    },
    async (request, reply) => {
      return { status: "ok", data: [] };
    },
  );
};

export default routes;

Environment Validation (Pre-Fastify)

Use TypeBox standalone for environment validation before Fastify instance creation:

import Type from "typebox";
import Value from "typebox/value";

const EnvSchema = Type.Object({
  NODE_ENV: Type.Union(
    [
      Type.Literal("development"),
      Type.Literal("production"),
      Type.Literal("test"),
    ],
    { default: "development" },
  ),
  PORT: Type.Number({ default: 3000 }),
  HOST: Type.String({ default: "0.0.0.0" }),
  LOG_LEVEL: Type.Union(
    [
      Type.Literal("trace"),
      Type.Literal("debug"),
      Type.Literal("info"),
      Type.Literal("warn"),
      Type.Literal("error"),
      Type.Literal("fatal"),
    ],
    { default: "info" },
  ),
});

export const env = Value.Parse(EnvSchema, {
  NODE_ENV: process.env.NODE_ENV ?? "development",
  PORT: process.env.PORT ? Number(process.env.PORT) : undefined,
  HOST: process.env.HOST,
  LOG_LEVEL: process.env.LOG_LEVEL,
});

Import Conventions

// Route plugins - use FastifyPluginAsyncTypebox for automatic type inference
import { type FastifyPluginAsyncTypebox, Type } from "@fastify/type-provider-typebox";

// Environment validation - use standalone typebox package
import Type from "typebox";
import Value from "typebox/value";

// Do not use the direct @sinclair/typebox import
// import { Type } from "@sinclair/typebox";  // Do not use

Common Type Patterns

String Types

Type.String()                           // Any string
Type.String({ minLength: 1 })          // Non-empty string
Type.String({ format: "email" })       // Email format
Type.String({ format: "uuid" })        // UUID format
Type.String({ pattern: "^[a-z]+$" })   // Regex pattern
Type.Literal("value")                  // Exact string value

Number Types

Type.Number()                          // Any number
Type.Number({ minimum: 0 })            // Non-negative
Type.Number({ minimum: 1, maximum: 100 }) // Range
Type.Integer()                         // Integer only

Object Types

Type.Object({
  required: Type.String(),
  optional: Type.Optional(Type.String()),
})

Array Types

Type.Array(Type.String())              // Array of strings
Type.Array(Type.Object({ id: Type.String() })) // Array of objects
Type.Array(Type.String(), { minItems: 1 })     // Non-empty array

Union Types

Type.Union([
  Type.Literal("option1"),
  Type.Literal("option2"),
  Type.Literal("option3"),
])

With Defaults

Type.String({ default: "default-value" })
Type.Number({ default: 10 })
Type.Boolean({ default: false })

OpenAPI Integration

TypeBox schemas automatically generate OpenAPI documentation. Include:

  • description on schema properties for documentation
  • Appropriate format hints (email, uuid, date-time)
  • Valid default values
  • Proper constraints (minLength, maximum, etc.)
Type.Object({
  email: Type.String({
    format: "email",
    description: "User email address",
  }),
  createdAt: Type.String({
    format: "date-time",
    description: "ISO 8601 timestamp",
  }),
})

Testing TypeBox Schemas

Verify response shapes match schemas in tests:

it("should return response matching schema", async () => {
  const response = await fastify.inject({
    method: "GET",
    url: "/endpoint",
  });

  expect(response.statusCode).toBe(200);
  const body = response.json();

  // Verify structure matches schema
  expect(body).toHaveProperty("status", "ok");
  expect(body).toHaveProperty("data");
  expect(Array.isArray(body.data)).toBe(true);
});

Commands

cd app
npm run build       # TypeScript will validate schema types
npm run check       # Run Biome linter
npm run test        # Run tests

Boundaries

  • Always use TypeBox for route schemas (not plain JSON Schema)
  • Use the correct import for context (Fastify vs standalone)
  • Do not use @sinclair/typebox directly

スコア

総合スコア

60/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です